[
  {
    "path": ".brackets.json",
    "content": "{\n    \"jslint.options\": {\n        \"vars\": true,\n        \"plusplus\": true,\n        \"browser\": false,\n        \"devel\": true,\n        \"nomen\": true,\n        \"indent\": 4,\n        \"maxerr\": 50,\n        \"es5\": true,\n        \"predef\": [\n            \"brackets\",\n\n            \"require\",\n            \"define\",\n            \"$\",\n\n            \"window\",\n            \"setTimeout\",\n            \"clearTimeout\",\n\n            \"ArrayBuffer\",\n            \"XMLHttpRequest\",\n            \"Uint32Array\",\n            \"WebSocket\"\n        ]\n    },\n    \"defaultExtension\": \"js\",\n    \"language\": {\n        \"javascript\": {\n            \"linting.prefer\": [\"ESLint\", \"JSLint\"],\n            \"linting.usePreferredOnly\": true\n        }\n    },\n    \"path\": {\n        \"src/thirdparty/CodeMirror/**/*.js\": {\n            \"spaceUnits\": 2,\n            \"linting.enabled\": false\n        },\n        \"src/thirdparty/globmatch.js\": {\n            \"spaceUnits\": 2,\n            \"linting.enabled\": false\n        }\n    },\n    \"spaceUnits\": 4,\n    \"useTabChar\": false\n}\n"
  },
  {
    "path": ".eslintignore",
    "content": "/src/extensions/default/brackets-eslint"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n    \"rules\": {\n        // the rules below should be sorted in a same way they are sorted on http://eslint.org/docs/rules page\n        // http://eslint.org/docs/rules/#possible-errors\n        \"no-caller\": 2,\n        \"no-control-regex\": 2,\n        \"no-empty\": 1,\n        \"no-invalid-regexp\": 2,\n        \"no-regex-spaces\": 2,\n        \"no-unsafe-negation\": 1,\n        \"valid-jsdoc\": 0,\n        \"valid-typeof\": 2,\n        // http://eslint.org/docs/rules/#best-practices\n        \"curly\": 2,\n        \"eqeqeq\": [2, \"smart\"],\n        \"guard-for-in\": 0,\n        \"no-else-return\": 1,\n        \"no-fallthrough\": 2,\n        \"no-invalid-this\": 1,\n        \"no-iterator\": 2,\n        \"no-loop-func\": 2,\n        \"no-multi-str\": 2,\n        \"no-new-func\": 2,\n        \"no-new-wrappers\": 2,\n        \"no-new\": 2,\n        \"no-proto\": 2,\n        \"no-redeclare\": 1,\n        \"no-script-url\": 2,\n        \"wrap-iife\": [2, \"outside\"],\n        // http://eslint.org/docs/rules/#strict-mode\n        \"strict\": 2,\n        // http://eslint.org/docs/rules/#variables\n        \"no-shadow-restricted-names\": 2,\n        \"no-shadow\": 1,\n        \"no-undef\": 2,\n        \"no-unused-vars\": [1, {\"vars\": \"all\", \"args\": \"none\"}],\n        \"no-use-before-define\": 0,\n        // http://eslint.org/docs/rules/#nodejs-and-commonjs\n        \"no-new-require\": 2,\n        // http://eslint.org/docs/rules/#stylistic-issues\n        \"block-spacing\": 1,\n        \"brace-style\": [1, \"1tbs\", { allowSingleLine: true }],\n        \"camelcase\": 1,\n        \"comma-dangle\": 2,\n        \"comma-spacing\": 1,\n        \"comma-style\": [1, \"last\"],\n        \"computed-property-spacing\": 1,\n        \"eol-last\": 1,\n        \"func-call-spacing\": 1,\n        \"indent\": [1, 4],\n        \"key-spacing\": [1, { beforeColon: false, afterColon: true }],\n        \"max-len\": [1, 120],\n        \"new-cap\": [0, {\n            \"capIsNewExceptions\": [\n                \"$.Deferred\",\n                \"$.Event\",\n                \"CodeMirror.Pos\",\n                \"Immutable.Map\",\n                \"Immutable.List\",\n                \"JSLINT\"\n            ]\n        }],\n        \"new-parens\": 2,\n        \"no-bitwise\": 2,\n        \"no-new-object\": 2,\n        \"no-trailing-spaces\": 1,\n        \"semi-spacing\": 1,\n        \"semi\": 2\n    },\n    \"globals\": {\n        \"$\": false,\n        \"brackets\": false,\n        \"clearTimeout\": false,\n        \"console\": false,\n        \"define\": false,\n        \"require\": false,\n        \"setTimeout\": false,\n        \"window\": false,\n        \"ArrayBuffer\": false,\n        \"Uint32Array\": false,\n        \"WebSocket\": false,\n        \"XMLHttpRequest\": false\n    },\n    \"parserOptions\": {\n        \"ecmaVersion\": 6,\n        \"sourceType\": \"script\",\n        \"ecmaFeatures\": {\n          \"arrowFunctions\": true,\n          \"binaryLiterals\": true,\n          \"blockBindings\": true,\n          \"classes\": true\n        }\n    }\n};\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto"
  },
  {
    "path": ".gitignore",
    "content": "Thumbs.db\n\n# ignore jenkins build info\n/build.prop\n\n# package-lock.json\npackage-lock.json\n\n# ignore node_modules created by grunt, but not more deeply-nested node_modules\n/node_modules\n/npm-debug.log\n\n# ignore node_modules inside src\n/src/node_modules\n/src/JSUtils/node_modules\n/src/JSUtils/node/node_modules\n\n# ignore files copied from node_modules to src/thirdparty\n/src/thirdparty/CodeMirror\n/src/thirdparty/less.min.js\n/src/thirdparty/preact\n/src/thirdparty/preact-compat\n/src/thirdparty/preact-test-utils\n/src/thirdparty/simulate-event\n/src/thirdparty/xtend\n/src/thirdparty/acorn\n\n# ignore compiled files\n/dist\n/src/.index.html\n/src/styles/brackets.min.css\n/src/styles/brackets.min.css.map\n\n# ignore everything in the dev extension directory EXCEPT the README\n# (so that the directory is non-empty and can be in git)\n/src/extensions/dev/*\n!/src/extensions/dev/README.*\n/src/extensions/default/brackets-eslint\n\n/src/extensions/disabled\n\n# ignore .disabled file for default extensions\n/src/extensions/default/*/.disabled\n\n# generate through grunt\n/src/config.json\n\n#OSX .DS_Store files\n.DS_Store\n\n# unit test working directory\n/test/results\n/test/temp\n\n# Netbeans\n/nbproject\n\n# PhpStorm\n.idea\n\n# Files that can be automatically downloaded that we don't want to ship with our builds\n/src/extensibility/node/node_modules/request/tests/\n\n# Files build by scripts\n/src/thirdparty/semver.browser.js\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"src/thirdparty/path-utils\"]\n\tpath = src/thirdparty/path-utils\n\turl = https://github.com/jblas/path-utils.git\n[submodule \"src/thirdparty/mustache\"]\n\tpath = src/thirdparty/mustache\n\turl = https://github.com/janl/mustache.js.git\n[submodule \"src/thirdparty/requirejs\"]\n\tpath = src/thirdparty/requirejs\n\turl = https://github.com/jrburke/requirejs.git\n[submodule \"src/thirdparty/text\"]\n\tpath = src/thirdparty/text\n\turl = https://github.com/requirejs/text.git\n[submodule \"src/thirdparty/i18n\"]\n\tpath = src/thirdparty/i18n\n\turl = https://github.com/requirejs/i18n.git\n[submodule \"src/extensions/default/JSLint/thirdparty/jslint\"]\n\tpath = src/extensions/default/JSLint/thirdparty/jslint\n\turl = https://github.com/peterflynn/JSLint.git\n"
  },
  {
    "path": ".npmrc",
    "content": "package-lock=false\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nsudo: false # use container-based Travis infrastructure\nnode_js:\n  - \"6\"\nbefore_script:\n  - npm install -g grunt-cli\n  - npm install -g jasmine-node\nnotifications:\n  webhooks:\n    urls:\n      - https://webhooks.gitter.im/e/9c767842144fd24d26a5\n    on_success: change  # options: [always|never|change] default: always\n    on_failure: always  # options: [always|never|change] default: always\n    on_start: false     # default: false\nbranches:\n  only:\n    - master\n    - release\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at [admin@brackets.io](mailto:admin@brackets.io). All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# The Basics\n\n### Filing a bug\n\nCheck the [Troubleshooting Page](https://github.com/adobe/brackets/wiki/Troubleshooting) for common\nissues with installing & launching Brackets, using Live Preview, etc.\n\n**For bugs** be sure to search existing issues first. Include steps to consistently reproduce the\nproblem, actual vs. expected results, and your OS and Brackets version number.\nDisable all extensions to verify the issue is a core Brackets bug.\n[Read more guidelines for filing good bugs...](https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue)\n\n**For feature requests** please first check our [feature backlog](http://bit.ly/BracketsBacklog) to\nsee if it's already there. You can upvote features you'd like to see.\n\n### Submitting a pull request\n\n**Before you start coding**, post to the [brackets-dev Google group](http://groups.google.com/group/brackets-dev)\nor the [#brackets IRC channel on freenode](http://webchat.freenode.net/?channels=brackets) about what\nyou're thinking of working on, so you can get early feedback. We don't want you to do tons of work\nand then have to rewrite half of it!\n\nFor more on what's expected in a good pull request, see [Contributing Code](#contributing-code) below.\n\n\n# Ways to Contribute\n\nThere are many ways you can contribute to the Brackets project:\n\n* **Fix a bug** or **implement a new feature** - read on below.\n* **[Write a Brackets extension](https://github.com/adobe/brackets/wiki/How-to-write-extensions)** and\n  tell us about it!\n* **Test Brackets** and [report bugs](https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue)\n  you find. For sample testing steps, see\n  [Brackets smoke tests](https://github.com/adobe/brackets/wiki/Brackets-Smoke-Tests),\n  [smoke tests with a local server](https://github.com/adobe/brackets/wiki/Brackets-Server-Smoke-Tests), and\n  [UI walkthrough steps](https://github.com/adobe/brackets/wiki/Localization-Tests).\n* **Write unit tests** for Brackets.\n* **Translate** Brackets into other languages (and help keep those translations up to date) - see\n  [localization README](https://github.com/adobe/brackets/blob/master/src/nls/README.md).\n* **Write documentation** and help keep it up to date\n  (the [How to Use Brackets](https://github.com/adobe/brackets/wiki/How-to-Use-Brackets) intro page\n  is one example).\n* **Try out some [Brackets extensions](https://github.com/adobe/brackets/wiki/Brackets-Extensions)**\n  and give feedback to their authors.\n\n\n## Where Do I Start?\n\nTo start editing the Brackets code, read **[How to Hack on Brackets](https://github.com/adobe/brackets/wiki/How-to-Hack-on-Brackets)**.\nTo create your first Brackets extension, check out **[How to Write Extensions](https://github.com/adobe/brackets/wiki/How-to-write-extensions)**.\n\nHere are some ideas:\n\n* [Starter bugs](https://github.com/adobe/brackets/issues?labels=starter+bug&state=open) can\n  provide a good intro to the Brackets code.\n* [Extension ideas](https://github.com/adobe/brackets/issues?q=label%3A%22Extension+Idea%22)\n  are feature requests that we think would be best implemented as an add-on; it's up to the\n  Brackets community to write them!\n* [Starter features](http://bit.ly/BracketsBacklog) are a bit larger in scope. Be sure to discuss\n  these in the newsgroup before starting. _(To see starter features, click Filter Cards on the\n  right and then click the green \"Starter Feature\" label)._\n\nOnce you're ready to start coding, see the next section, [Contributing Code](#contributing-code).\n\n**I'm new to JavaScript. How can I contribute to Brackets?** Brackets is a lot more complicated\nthan the average website that uses JS. Better to start on some JS tutorials (like [Codecademy's](http://www.codecademy.com/tracks/javascript)\nor [MDN's](https://developer.mozilla.org/en-US/docs/JavaScript/Getting_Started)) and contribute\nin some of the other ways listed above. Testing is a great way to start thinking like a programmer\nbefore you've learned to code!\n\n\n## Contributing Code\n\nTo get started editing the Brackets code, read [How to Hack on Brackets](https://github.com/adobe/brackets/wiki/How-to-Hack-on-Brackets).\n\nBefore submitting any pull request, please make sure to:\n\n1. Discuss any major changes or questions beforehand in the [brackets-dev newsgroup](http://groups.google.com/group/brackets-dev).\n2. Consider whether your change would be better as an optional extension. Brackets is lightweight\n   and tightly focused - but highly extensible.\n3. Follow the [Pull Request Checklist](https://github.com/adobe/brackets/wiki/Pull-Request-Checklist)\n   to ensure a good-quality pull request.\n4. Sign the [Brackets Contributor License Agreement](http://dev.brackets.io/brackets-contributor-license-agreement.html)\n   (we cannot merge before this).\n\nHigh quality code and a top-notch user experience are very important in Brackets, and we carefully\nreview pull requests to keep it that way. The better you follow the guidelines above, the more likely\nwe are to accept your pull request - and the faster the code review will go.\n\n \n## The Code Review Process\n\nBrackets committers are responsible for reviewing all pull requests, providing feedback, and\nultimately merging good code into `master`. The review process ensures all code is high quality,\nmaintainable, and well documented.\n\nOnce you've opened a pull request, a committer will generally respond to it within a week with an\ninitial set of comments (you don't need to ping anyone to find a reviewer). Some pull requests\nraise larger questions about UI design, product scope or architecture. Those are tagged to indicate\nthat review will take longer:\n\n* \\[PM\\] - needs high-level input from product management\n* \\[XD\\] - needs UI design / visual design discussion\n* \\[ARCH\\] - needs architectural discussion\n\nThe best way to avoid this sort of holdup is to discuss your changes on the newsgroup first!\n\nOnce your pull request is merged, it will appear in the next release of Brackets - generally within\ntwo weeks.\n\n**Interested in becoming a committer?** See the [Committer Policy](https://github.com/adobe/brackets/wiki/Brackets-Committer-Policy)\nfor details. Committers are expected to take a leading role in the project by making significant\ncode contributions, reviewing pull requests, and providing feedback and suggestions on the\ndirection of the project.\n\nEven if you're not a committer, you're still welcome to give feedback on any pull request!\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n'use strict';\n\nmodule.exports = function (grunt) {\n    // load dependencies\n    require('load-grunt-tasks')(grunt, {\n        pattern: [\n            'grunt-*',\n            '!grunt-cli',\n            '!grunt-lib-phantomjs',\n            '!grunt-template-jasmine-requirejs'\n        ]\n    });\n    grunt.loadTasks('tasks');\n\n    // Project configuration.\n    grunt.initConfig({\n        pkg  : grunt.file.readJSON(\"package.json\"),\n        clean: {\n            dist: {\n                files: [{\n                    dot: true,\n                    src: [\n                        'dist',\n                        'src/.index.html',\n                        'src/styles/brackets.css'\n                    ]\n                }]\n            },\n            node_modules_test_dir : {\n                files: [{\n                    dot: true,\n                    src: [\n                        'dist/node_modules/npm/test/fixtures',\n                        'dist/node_modules/npm/node_modules/tar/test',\n                        'dist/node_modules/npm/node_modules/npm-registry-client/test'\n                    ]\n                }]\n            }\n        },\n        copy: {\n            dist: {\n                files: [\n                    {\n                        'dist/index.html': 'src/.index.html'\n                    },\n                    /* static files */\n                    {\n                        expand: true,\n                        dest: 'dist/',\n                        cwd: 'src/',\n                        src: [\n                            'nls/{,*/}*.js',\n                            'xorigin.js',\n                            'dependencies.js',\n                            'thirdparty/requirejs/require.js',\n                            'LiveDevelopment/launch.html',\n                            'LiveDevelopment/transports/**',\n                            'LiveDevelopment/MultiBrowserImpl/transports/**',\n                            'LiveDevelopment/MultiBrowserImpl/launchers/**'\n                        ]\n                    },\n                    /* node domains are not minified and must be copied to dist */\n                    {\n                        expand: true,\n                        dest: 'dist/',\n                        cwd: 'src/',\n                        src: [\n                            'extensibility/node/**',\n                            'JSUtils/node/**',\n                            'languageTools/node/**',\n                            'languageTools/styles/**',\n                            'languageTools/LanguageClient/**',\n                            '!extensibility/node/spec/**',\n                            '!extensibility/node/node_modules/**/{test,tst}/**/*',\n                            '!extensibility/node/node_modules/**/examples/**/*',\n                            'filesystem/impls/appshell/node/**',\n                            '!filesystem/impls/appshell/node/spec/**',\n                            'search/node/**'\n                        ]\n                    },\n                    /* extensions and CodeMirror modes */\n                    {\n                        expand: true,\n                        dest: 'dist/',\n                        cwd: 'src/',\n                        src: [\n                            'extensions/default/**/*',\n                            '!extensions/default/*/unittest-files/**/*',\n                            '!extensions/default/*/unittests.js',\n                            '!extensions/default/{*/thirdparty,**/node_modules}/**/test/**/*',\n                            '!extensions/default/{*/thirdparty,**/node_modules}/**/doc/**/*',\n                            '!extensions/default/{*/thirdparty,**/node_modules}/**/examples/**/*',\n                            '!extensions/default/*/thirdparty/**/*.htm{,l}',\n                            'extensions/dev/*',\n                            'extensions/samples/**/*',\n                            'thirdparty/CodeMirror/**',\n                            'thirdparty/i18n/*.js',\n                            'thirdparty/text/*.js'\n                        ]\n                    },\n                    /* styles, fonts and images */\n                    {\n                        expand: true,\n                        dest: 'dist/styles',\n                        cwd: 'src/styles',\n                        src: ['jsTreeTheme.css', 'fonts/{,*/}*.*', 'images/*', 'brackets.min.css*']\n                    }\n                ]\n            },\n            thirdparty: {\n                files: [\n                    {\n                        expand: true,\n                        dest: 'src/thirdparty/CodeMirror',\n                        cwd: 'src/node_modules/codemirror',\n                        src: [\n                            'addon/{,*/}*',\n                            'keymap/{,*/}*',\n                            'lib/{,*/}*',\n                            'mode/{,*/}*',\n                            'theme/{,*/}*'\n                        ]\n                    },\n                    {\n                        expand: true,\n                        flatten: true,\n                        dest: 'src/thirdparty',\n                        cwd: 'src/node_modules',\n                        src: [\n                            'less/dist/less.min.js'\n                        ]\n                    },\n                    {\n                        expand: true,\n                        flatten: true,\n                        dest: 'src/thirdparty/preact-compat',\n                        cwd: 'src/node_modules/preact-compat',\n                        src: [\n                            'dist/preact-compat.min.js'\n                        ]\n                    },\n                    {\n                        expand: true,\n                        flatten: true,\n                        dest: 'src/thirdparty/simulate-event',\n                        cwd: 'src/node_modules/simulate-event',\n                        src: [\n                            'simulate-event.js'\n                        ]\n                    },\n                    {\n                        expand: true,\n                        flatten: true,\n                        dest: 'src/thirdparty/xtend',\n                        cwd: 'src/node_modules/xtend',\n                        src: [\n                            'mutable.js',\n                            'immutable.js'\n                        ]\n                    },\n                    {\n                        expand: true,\n                        dest: 'src/thirdparty/acorn',\n                        cwd: 'src/node_modules/acorn',\n                        src: [\n                            'dist/{,*/}*'\n                          ]\n                    }\n                ]\n            }\n        },\n        cleanempty: {\n            options: {\n                force: true,\n                files: false\n            },\n            src: ['dist/**/*']\n        },\n        less: {\n            dist: {\n                files: {\n                    \"src/styles/brackets.min.css\": \"src/styles/brackets.less\"\n                },\n                options: {\n                    compress: true,\n                    sourceMap: true,\n                    sourceMapFilename: 'src/styles/brackets.min.css.map',\n                    outputSourceFiles: true,\n                    sourceMapRootpath: '',\n                    sourceMapBasepath: 'src/styles'\n                }\n            }\n        },\n        requirejs: {\n            dist: {\n                // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js\n                options: {\n                    // `name` and `out` is set by grunt-usemin\n                    baseUrl: 'src',\n                    optimize: 'uglify2',\n                    // brackets.js should not be loaded until after polyfills defined in \"utils/Compatibility\"\n                    // so explicitly include it in main.js\n                    include: [\"utils/Compatibility\", \"brackets\"],\n                    // TODO: Figure out how to make sourcemaps work with grunt-usemin\n                    // https://github.com/yeoman/grunt-usemin/issues/30\n                    generateSourceMaps: true,\n                    useSourceUrl: true,\n                    // required to support SourceMaps\n                    // http://requirejs.org/docs/errors.html#sourcemapcomments\n                    preserveLicenseComments: false,\n                    useStrict: true,\n                    // Disable closure, we want define/require to be globals\n                    wrap: false,\n                    exclude: [\"text!config.json\"],\n                    uglify2: {} // https://github.com/mishoo/UglifyJS2\n                }\n            }\n        },\n        targethtml: {\n            dist: {\n                files: {\n                    'src/.index.html': 'src/index.html'\n                }\n            }\n        },\n        useminPrepare: {\n            options: {\n                dest: 'dist'\n            },\n            html: 'src/.index.html'\n        },\n        usemin: {\n            options: {\n                dirs: ['dist']\n            },\n            html: ['dist/{,*/}*.html']\n        },\n        htmlmin: {\n            dist: {\n                options: {\n                    /*removeCommentsFromCDATA: true,\n                    // https://github.com/yeoman/grunt-usemin/issues/44\n                    //collapseWhitespace: true,\n                    collapseBooleanAttributes: true,\n                    removeAttributeQuotes: true,\n                    removeRedundantAttributes: true,\n                    useShortDoctype: true,\n                    removeEmptyAttributes: true,\n                    removeOptionalTags: true*/\n                },\n                files: [{\n                    expand: true,\n                    cwd: 'src',\n                    src: '*.html',\n                    dest: 'dist'\n                }]\n            }\n        },\n        meta : {\n            src   : [\n                'src/**/*.js',\n                '!src/thirdparty/**',\n                '!src/widgets/bootstrap-*.js',\n                '!src/extensions/**/unittest-files/**/*.js',\n                '!src/extensions/**/thirdparty/**/*.js',\n                '!src/extensions/dev/**',\n                '!src/extensions/disabled/**',\n                '!**/node_modules/**/*.js',\n                '!src/**/*-min.js',\n                '!src/**/*.min.js'\n            ],\n            test : [\n                'test/**/*.js',\n                '!test/perf/*-files/**/*.js',\n                '!test/spec/*-files/**/*.js',\n                '!test/spec/*-known-goods/**/*.js',\n                '!test/spec/FindReplace-test-files-*/**/*.js',\n                '!test/smokes/**',\n                '!test/temp/**',\n                '!test/thirdparty/**',\n                '!test/**/node_modules/**/*.js'\n            ],\n            grunt: [\n                'Gruntfile.js',\n                'tasks/**/*.js'\n            ],\n            /* specs that can run in phantom.js */\n            specs : [\n                'test/spec/CommandManager-test.js',\n                //'test/spec/LanguageManager-test.js',\n                //'test/spec/PreferencesManager-test.js',\n                'test/spec/ViewUtils-test.js'\n            ]\n        },\n        watch: {\n            grunt: {\n                files: ['<%= meta.grunt %>'],\n                tasks: ['eslint:grunt']\n            },\n            src: {\n                files: ['<%= meta.src %>'],\n                tasks: ['eslint:src']\n            },\n            test: {\n                files: ['<%= meta.test %>'],\n                tasks: ['eslint:test']\n            },\n            options: {\n                spawn: false\n            }\n        },\n        /* FIXME (jasonsanjose): how to handle extension tests */\n        jasmine : {\n            src : 'undefined.js', /* trick the default runner to run without importing src files */\n            options : {\n                junit : {\n                    path: 'test/results',\n                    consolidate: true\n                },\n                specs : '<%= meta.specs %>',\n                /* Keep in sync with test/SpecRunner.html dependencies */\n                vendor : [\n                    // For reference to why this polyfill is needed see Issue #7951.\n                    // The need for this should go away once the version of phantomjs gets upgraded to 2.0\n                    'test/polyfills.js',\n\n                    'src/thirdparty/jquery-2.1.3.min.js',\n                    'src/thirdparty/less.min.js'\n                ],\n                helpers : [\n                    'test/spec/PhantomHelper.js'\n                ],\n                template : require('grunt-template-jasmine-requirejs'),\n                templateOptions: {\n                    requireConfig : {\n                        baseUrl: 'src',\n                        paths: {\n                            'test' : '../test',\n                            'perf' : '../test/perf',\n                            'spec' : '../test/spec',\n                            'text' : 'thirdparty/text/text',\n                            'i18n' : 'thirdparty/i18n/i18n'\n                        }\n                    }\n                }\n            }\n        },\n        'jasmine_node': {\n            projectRoot: 'src/extensibility/node/spec/'\n        },\n        eslint: {\n            grunt:  '<%= meta.grunt %>',\n            src:    '<%= meta.src %>',\n            test:   '<%= meta.test %>',\n            options: {\n                quiet: true\n            }\n        },\n        shell: {\n            repo: grunt.option(\"shell-repo\") || \"../brackets-shell\",\n            mac: \"<%= shell.repo %>/installer/mac/staging/<%= pkg.name %>.app\",\n            win: \"<%= shell.repo %>/installer/win/staging/<%= pkg.name %>.exe\",\n            linux: \"<%= shell.repo %>/installer/linux/debian/package-root/opt/brackets/brackets\"\n        }\n    });\n\n    // task: install\n    grunt.registerTask('install', [\n        'write-config:dev',\n        'less',\n        'npm-download-default-extensions',\n        'npm-install-source',\n        'pack-web-dependencies'\n    ]);\n\n    // task: test\n    grunt.registerTask('test', ['eslint', 'jasmine', 'nls-check']);\n//    grunt.registerTask('test', ['eslint', 'jasmine', 'jasmine_node', 'nls-check']);\n\n    // task: set-release\n    // Update version number in package.json and rewrite src/config.json\n    grunt.registerTask('set-release', ['update-release-number', 'write-config:dev']);\n\n    grunt.registerTask('build-common', [\n        'eslint:src',\n        'jasmine',\n        'clean',\n        'less',\n        'targethtml',\n        'useminPrepare',\n        'htmlmin',\n        'requirejs',\n        'concat',\n        /*'cssmin',*/\n        /*'uglify',*/\n        'copy:dist',\n        'npm-install',\n        'cleanempty',\n        'usemin',\n        'build-config',\n        'clean:node_modules_test_dir'\n    ]);\n\n    // task: build\n    grunt.registerTask('build', [\n        'write-config:dist',\n        'build-common'\n    ]);\n\n    // task: build\n    grunt.registerTask('build-prerelease', [\n        'write-config:prerelease',\n        'build-common'\n    ]);\n\n    // Default task.\n    grunt.registerTask('default', ['test']);\n};\n\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "### Prerequisites\n\n* [ ] Can you reproduce the problem with `Debug -> Reload Without Extensions`?\n* [ ] Did you perform a cursory search to see if your bug or enhancement is already reported?\n* [ ] Did you read the [Troubleshooting guide](https://github.com/adobe/brackets/wiki/Troubleshooting)?\n\nFor more information on how to write a good bug report read [here](https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue)\nFor more information on how to contribute read [here](https://github.com/adobe/brackets/blob/master/CONTRIBUTING.md)\n\n### Description\n\n[Description of the bug or feature]\n\n### Steps to Reproduce\n\n1. [First Step]\n2. [Second Step]\n3. [and so on...]\n\n**Expected behavior:** [What you expected to happen]\n\n**Actual behavior:** [What actually happened]\n\n### Versions\n\nPlease include the OS and what version of the OS you're running.\nPlease include the version of Brackets. You can find it under `Help -> About Brackets` (Windows and Linux) or `Brackets -> About Brackets` (macOS)\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n \nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"), \nto deal in the Software without restriction, including without limitation \nthe rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the \nSoftware is furnished to do so, subject to the following conditions:\n \nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "NOTICE",
    "content": "Brackets is licensed under the MIT license (see LICENSE file). Brackets uses the following third party libraries that may have licenses \ndiffering from that of Brackets itself. \n\nThird Party Software Notices:\n=============================\n\n\n\"Cowboy\" Ben Alman\nCopyright © 2010-2012 \"Cowboy\" Ben Alman\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\n\nThe Android Open Source Project\nCopyright (C) 2008 The Android Open Source Project\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\nRedistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe Android Open Source Project\nCopyright (C) 2009, 2010 The Android Open Source Project\nThis product includes software licensed under the Apache License, Version 2.0 \nhttp://www.apache.org/licenses/LICENSE-2.0. \n\nThe ANGLE Project Authors \nCopyright (C) 2002-2010 The ANGLE Project Authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\nRedistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nNeither the name of TransGaming Inc., Google Inc., 3DLabs Inc. Ltd., nor the names of \ntheir contributors may be used to endorse or promote products derived from this software \nwithout specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE \nGOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING \nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH \nDAMAGE.\n\nThe Apache Software Foundation\nThis product includes software licensed under the Apache License, Version 2.0 \nhttp://www.apache.org/licenses/LICENSE-2.0Apple Inc.\nWebKit is open source software with portions licensed under the LGPL and BSD \nlicenses. Complete license and copyright information can be found within the code at\nhttp://opensource.adobe.com/wiki/display/webkit/Webkit.\nCopyright (C) 2005 Apple Inc. All rights reserved.\nCopyright (C) 2006 Rob Buis \nCopyright CNRI, All Rights Reserved. \nCopyright (C) 2006 Graham Dennis. All rights reserved.\nCopyright (C) 2007 Robin Dunn. All rights reserved.\nCopyright (C) 2006 Michael Emmel. All rights reserved.\nCopyright (C) 2007 Holger Hans Peter Freyther\nCopyright (C) 2006 Justin Haygood \nCopyright (C) Hewlett-Packard Company\nCopyright (C) 1997-2004, International Business Machines Corporation and others. All \nRights Reserved.\nCopyright (C) 2006 Nefaur Khandker. All rights reserved.\nCopyright (C) 2006 Kimmo Kinnunen \nCopyright (C) 2005 Ben La Monica. All rights reserved.\nCopyright (C) 2007 Matt Lilek \nCopyright (C) 1991, 2000, 2001 by Lucent Technologies\nCopyright (C) 2006 Dave MacLachlan \nCopyright (C) 2006, Nokia Corporation. All rights reserved.\nCopyright (C) 2006, 2007 Vladimir Olexa \nCopyright (C) 2007 Kevin Ollivier \nCopyright 2005 Maksim Orlovich \nCopyright (C) 2007 Alexey Proskuryakov \nCopyright 2005 Frerich Raabe \nCopyright (C) 2006 Mark Rowe. All rights reserved.\nCopyright (C) 2006 Zack Rusin \nCopyright (C) 2006 Eric Seidel\nCopyright (C) 2006 David Smith \nCopyright (C) 2006 James G. Speth \nCopyright (C) 2006 George Staikos. All rights reserved.\nCopyright (C) 2007 Staikos Computing Services Inc.\nCopyright (c) 2000 Malte Starostik \nCopyright (c) 2006 Thomas Stromberg \nCopyright (C) 2007 Alp Toker \nCopyright (C) 2006 Trolltech ASA\nCopyright (C) 1997-2005 University of Cambridge\nCopyright 2000 Guido van Rossum.\nCopyright (C) 2006 Samuel Weinig \nCopyright (C) 2004 by Michal Zalewski \nCopyright (C) 2006 Nikolas Zimmermann Redistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer. \n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution. \n3. Neither the name of Apple Inc. (\"Apple\") nor the names of its contributors may be \nused to endorse or promote products derived from this software without specific prior \nwritten permission. \nTHIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" \nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \nSHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nApple Inc.\nPortions licensed from Apple Computer, Inc. under the terms of the Apple Public Source \nLicense, Version 2. The source code version of these portions and the license are \navailable at http://www.opensource.apple.com/apsl/. \n\nApple Inc.\nCopyright (C) 2006, 2007 Apple Computer, Inc. All rights reserved.\nCopyright (C) 2007, 2008 Apple Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer. \n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution. THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" \nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \nSHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nAUTHORS.txt\nCopyright (c) 2009, 2010, 2011, 2012 AUTHORS.txt (http://jqueryui.com/about)\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nMihai Bazon\nCopyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS”AND \nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED \nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR \nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nCOPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nKin Blas\nCopyright (c) 2011, Kin Blas. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Kin Blas nor the names of its contributors may be used to endorse \nor promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL KIN BLASBE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nBoost Contributors\nPermission is hereby granted, free of charge, to any person or organization obtaining a \ncopy of the software and accompanying documentation covered by this license (the \n\"Software\") to use, reproduce, display, distribute, execute, and transmit the Software, and \nto prepare derivative works of the Software, and to permit third-parties to whom the \nSoftware is furnished to do so, all subject to the following:\nThe copyright notices in the Software and this entire statement, including the above \nlicense grant, this restriction and the following disclaimer, must be included in all copies \nof the Software, in whole or in part, and all derivative works of the Software, unless such \ncopies or derivative works are solely in the form of machine-executable object code \ngenerated by a source language processor.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND \nNON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR \nANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES \nOR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE \nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n\nMark Borgerding \nCopyright (c) 2003-2004, Mark Borgerding. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nIvan Bozhanov\nCopyright (c) 2012 Ivan Bozhanov\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nBrian J. Brennan\nCopyright (c) 2013 Brian J. Brennan\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute,sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.Victor Carbune\nCopyright (C) 2012 \n\nVictor Carbune (victor@rosedu.org)\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY \nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, \nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE \nCOMPUTER, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nCodility Limited\nCopyright (c) 2012 Codility Limited, 107 Cheapside, London EC2V 6DN, UK\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nLachie Cox\nCopyright (c) 2008 Lachie Cox\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nDouglas Crockford - JSMin\nCopyright (c) 2002 Douglas Crockford (www.JSLint.com/www.crockford.com)\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute,sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nThe Software shall be used for Good, not Evil.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nTheo de Raat\nCopyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. All advertising materials mentioning features or use of this software must display the \nfollowing acknowledgement: This product includes software developed by Theo de \nRaadt.\n4. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nDebuggable Limited \nCopyright (c) 2011 Debuggable Limited felix@debuggable.com\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rightsto use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software isfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS INTHE SOFTWARE.\n\nEgor Egorov\nEgor Egorov, me@egorfine.com.\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nCopyright 2013-2014 Facebook, Inc.\nThis product includes software licensed under the Apache License, Version 2.0 \nhttp://www.apache.org/licenses/LICENSE-2.0.\n\nBSD License\nFor Immutable JS software\nCopyright (c) 2014, Facebook, Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n* Neither the name Facebook nor the names of its contributors may be used to\nendorse or promote products derived from this software without specific\nprior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nCopyright (c) 2014, Facebook, Inc. All rights reserved.\n\nReact JavaScript library\n\nLicensed under the Apache License, Version 2.0\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nSee also: https://github.com/facebook/react/blob/master/LICENSE\n\n\nTimothy Farrell\nCopyright (c) 2010 Timothy Farrell\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nNick Galbreath\nCopyright (c) 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. Neither the name of modp.com nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE \nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, \nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, \nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, \nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY \nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \nPOSSIBILITY OF SUCH DAMAGE.\n\nDavid M. Gay and Lucent Technologies\nThe author of this software is David M. Gay.\nCopyright (c) 1991, 1996, 2000, 2001 by Lucent Technologies.\nPermission to use, copy, modify, and distribute this software for any purpose without fee \nis hereby granted, provided that this entire notice is included in all copies of any software \nwhich is or includes a copy or modification of this software and in all copies of the \nsupporting documentation for such software.THIS SOFTWARE IS BEING PROVIDED \"AS IS\", WITHOUT ANY EXPRESS OR \nIMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR \nLUCENT MAKES ANY REPRESENTATION OR WARRANTY OF ANY KIND \nCONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS \nFOR ANY PARTICULAR PURPOSE.\n\nFelix Geisendörfer\nCopyright (C) 2011-2012 Felix Geisendörfer\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nDaniel Glazman\nCopyright (C) 2011 by Daniel Glazman <daniel@glazman.org>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nGoogle\nCopyright (c) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Google Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nGoogle, Inc.\nCopyright 2002, 2007-2008 Google Inc.\nThis product includes software licensed under the Apache License, Version 2.0 \nhttp://www.apache.org/licenses/LICENSE-2.0.\n\nGoogle –The Chromium Authors\nCopyright (c) 2006-2008, 2009, 2010 The Chromium Authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nGoogle – the V8 Project Authors\nCopyright 2009 the V8 project authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributionsin binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nMarshal A. Greenblatt and Google Inc.\nCopyright (c) 2008-2011 Marshall A. Greenblatt. \nPortions Copyright (c)\n2006-2009 Google Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the name Chromium Embedded Framework nor \nthe names of its contributors may be used to endorse or promote products derived from \nthis software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nBrian Grinstead \nCopyright (c) 2011, Brian Grinstead, http://briangrinstead.com\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nJames Halliday\nCopyright 2010 James Halliday (mail@substack.net)\nThis project is free software released under the MIT/X11 license:\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rightsto use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software isfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS INTHE SOFTWARE.\n\nEran Hammer\nCopyright (c) 2012-2013, Eran Hammer.\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met: \n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer. \n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution. * Neither the name of Eran Hammer nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" ANDANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \nAREDISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR \nANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, \nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, \nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ANDON \nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, \nOR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY \nOUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE \nPOSSIBILITY OF SUCH DAMAGE.\n\nMarijn Haverbeke (codemirror, tern, acorn)\nCopyright (C) 2012 by Marijn Haverbeke <marijnh@gmail.com>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\nPlease note that some subdirectories of the CodeMirror distribution include their own \nLICENSE files, and are released under different licences.\n\nAriya Hidayat and other contributors\nCopyright (C) 2012, 2011 Ariya Hidayat and other contributors.Redistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n•Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n•Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, \nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE \nGOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH \nDAMAGE.\n\nTJ Holowaychuk\nCopyright (c) 2010-2012 TJ Holowaychuk <tj@vision-media.ca>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nIndependent JPEG GroupThis software is based in part on the work of the Independent JPEG Group.\n\nIntel Corporation\nCopyright © 2008-2010 Intel Corporation\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice (including the next paragraph) \nshall be included in all copies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nInternational Business Machines Corporation – ICU 1.8.1 and later\nCopyright (c) 1995-2003, 1995 - 2006, 1995-2007, 1995-2009, International Business \nMachines Corporation and others \nAll rights reserved. \nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, and/or sell copies of the Software, and to permit persons to whom the \nSoftware is furnished to do so, provided that the above copyright notice(s) and this \npermission notice appear in all copies of the Software and that both the above copyright \nnotice(s) and this permission notice appear in supporting documentation. \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE \nCOPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE \nFOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL \nDAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF \nUSE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN \nCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \nExcept as contained in this notice, the name of a copyright holder shall not be used in \nadvertising or otherwise to promote the sale, use or other dealings in this Software \nwithout prior written authorization of the copyright holder. \n\nPeter Johnson\nCopyright (C) 2001-2007 Peter Johnson\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER \nCONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nJoyent, Inc. and other Node contributors\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n====\nThis license applies to all parts of Node that are not externally maintained libraries. The \nexternally maintained libraries used by Node are:\n- V8, located at deps/v8. V8's license follows: \nThis license applies to all parts of V8 that are not externally maintained libraries. The \nexternally maintained libraries used by V8 are:\n- PCRE test suite, located in\ntest/mjsunit/third_party/regexp-pcre.js. This is based on the test suite from PCRE-\n7.3, which is copyrighted by the University of Cambridge and Google, Inc. The \ncopyright notice and license are embedded in regexp-pcre.js.\n- Layout tests, located in test/mjsunit/third_party. These are based on layout tests \nfrom webkit.org which are copyrighted by Apple Computer, Inc. and released under a 3-\nclause BSD license.\n- Strongtalk assembler, the basis of the files assembler-arm-inl.h, assembler-arm.cc, \nassembler-arm.h, assembler-ia32-inl.h, assembler-ia32.cc, assembler-ia32.h, assemblerx64-inl.h, assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h, assembler-mips.cc, \nassembler-mips.h, assembler.cc and assembler.h. This code is copyrighted by Sun \nMicrosystems Inc. and released under a 3-clause BSD license.\n- Valgrind client API header, located at third_party/valgrind/valgrind.h. This is \nrelease under the BSD license.\nThese libraries have their own licenses; we recommend you read them, as their terms \nmay differ from the terms below.\nCopyright 2006-2012, the V8 project authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- libev, located at deps/uv/src/unix/ev. libev's license follows:\nAll files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\nAlternatively, the contents of this package may be used under the terms of the GNU \nGeneral Public License (\"GPL\") version 2 or any later version, in which case the \nprovisions of the GPL are applicable instead of the above. If you wish to allow the use of \nyour version of this package only under the terms of the GPL and not to allow others to \nuse your version of this file under the BSD license, indicate your decision by deleting the \nprovisions above and replace them with the notice and other provisions required by the \nGPL in this and the other files of this package. If you do not delete the provisions above, \na recipient may use your version of this file under either the BSD or the GPL.\n- libeio, located at deps/uv/src/unix/eio. libeio's license follows:\nAll files in libeio are Copyright (C)2007,2008 Marc Alexander Lehmann.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\nAlternatively, the contents of this package may be used under the terms of the GNU \nGeneral Public License (\"GPL\") version 2 or any later version, in which case the \nprovisions of the GPL are applicable instead of the above. If you wish to allow the use of \nyour version of this package only under the terms of the GPL and not to allow others to \nuse your version of this file under the BSD license, indicate your decision by deleting the \nprovisions above and replace them with the notice and other provisions required by the GPL in this and the other files of this package. If you do not delete the provisions above, \na recipient may use your version of this file under either the BSD or the GPL.\n- WAF build system, located at tools/waf*. WAF's license follows:\nCopyright Thomas Nagy, 2005-2011\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n-C-Ares, an asynchronous DNS client, located at deps/uv/src/ares. C-Ares license \nfollows:\nCopyright 1998 by the Massachusetts Institute of Technology.\nPermission to use, copy, modify, and distribute this software and its documentation for \nany purpose and without fee is hereby granted, provided that the above copyright notice \nappear in all copies and that both that copyright notice and this permission notice appear \nin supporting documentation, and that the name of M.I.T. not be used in advertising or \npublicity pertaining to distribution of the software without specific, written prior \npermission.M.I.T. makes no representations about the suitability of this software for any purpose. It \nis provided \"as is\" without express or implied warranty.\n- OpenSSL located at deps/openssl. OpenSSL is cryptographic software written by Eric \nYoung (eay@cryptsoft.com) to provide SSL/TLS encryption. OpenSSL's license follows:\n===============================================================\nCopyright (c) 1998-2011 The OpenSSL Project. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1.Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. All advertising materials mentioning features or use of this software must display the \nfollowing acknowledgment:\n\"This product includes software developed by the OpenSSL Project for use in the \nOpenSSL Toolkit. (http://www.openssl.org/)\"\n4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to endorse or \npromote products derived from this software without prior written permission. For \nwritten permission, please contact openssl-core@openssl.org.\n5. Products derived from this software may not be called \"OpenSSL\" nor may \n\"OpenSSL\" appear in their names without prior written permission of the OpenSSL \nProject.\n6. Redistributions of any form whatsoever must retain the following acknowledgment:\n\"This product includes software developed by the OpenSSL Project for use in the \nOpenSSL Toolkit (http://www.openssl.org/)\"\nTHIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY \nEXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, \nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nOpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n===============================================================\nThis product includes cryptographic software written by Eric Young \n(eay@cryptsoft.com). This product includes software written by Tim Hudson \n(tjh@cryptsoft.com).\n- HTTP Parser, located at deps/http_parser. HTTP Parser's license follows:\nhttp_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev.\nAdditional changes are licensed under the same terms as NGINX and copyright Joyent, \nInc. and other Node contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n-Closure Linter is located at tools/closure_linter. Closure's license follows:\nCopyright (c) 2007, Google Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- tools/cpplint.py is a C++ linter. Its license follows:\nCopyright (c) 2009 Google Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met: \n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- lib/buffer_ieee754.js. Its license follows:\nCopyright (c) 2008, Fair Oaks Labs, Inc.\nAll rightsreserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors may be used \nto endorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- lib/punycode.js is copyright 2011 Mathias Bynens <http://mathiasbynens.be/>and \nreleased under the MIT license.\nPunycode.js <http://mths.be/punycode>\nCopyright 2011 Mathias Bynens <http://mathiasbynens.be/>\nAvailable under MIT license <http://mths.be/mit>\n- tools/gyp. GYP is a meta-build system. GYP's license follows:\nCopyright (c) 2009 Google Inc. All rights reserved.Redistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- Zlib at deps/zlib. zlib's license follows:\nzlib.h -- interface of the 'zlib' general purpose compression library version 1.2.4, March \n14th, 2010\nCopyright (C) 1995-2010 Jean-loup Gailly and Mark Adler\nThis software is provided 'as-is', without any express or implied warranty. In no event \nwill the authors be held liable for any damages arising from the use of this software.\nPermission is granted to anyone to use this software for any purpose, including \ncommercial applications, and to alter it and redistribute it freely, subject to the following \nrestrictions:\n1. The origin of this software must not be misrepresented; you must not claim that you \nwrote the original software. If you use this software in a product, an acknowledgment in \nthe product documentation would be appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be \nmisrepresented as being the original software.3. This notice may not be removed or altered from any source distribution.\nJean-loup Gailly\nMark Adler\n- npm is a package manager program located at deps/npm. npm's license follows:\nCopyright 2009-2012, Isaac Z. Schlueter (the \"Original Author\")\nAll rights reserved.\nMIT +no-false-attribs License\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nDistributions of all or part of the Software intended to be used by the recipients as they \nwould use the unmodified Software, containing modifications that substantially alter, \nremove, or disable functionality of the Software, outside of the documented configuration \nmechanisms provided by the Software, shall be modified such that the Original Author's \nbug reporting email addresses and urls are either replaced with the contact information of \nthe parties responsible for the changes, or removed entirely.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\nExcept where noted, this license applies to any and all software programs and associated \ndocumentation files created by the Original Author, when distributed with the Software.\n\"Node.js\" and \"node\" trademark Joyent, Inc. npm is not officially part of the Node.js \nproject, and is neither owned by nor officially affiliated with Joyent, Inc.\nPackages published in the npm registry are not part of npm itself, are the sole property of \ntheir respective maintainers, and are not covered by this license.\"npm Logo\" created by Mathias Pettersson and Brian Hammond, used with permission.\n\"Gubblebum Blocky\" font Copyright (c) 2007 by Tjarda Koster, \nhttp://jelloween.deviantart.com included for use in the npm website and documentation, \nused with permission.\nThis program uses \"node-uuid\", Copyright (c) 2010 Robert Kieffer, according to the \nterms of the MIT license.\nThis program uses \"request\", Copyright (c) 2011 Mikeal Rogers, according to the terms \nof the Apache license.\nThis program uses \"mkdirp\", Copyright (c) 2010 James Halliday, according to the terms \nof the MIT/X11 license.\n- tools/doc/node_modules/marked. Marked is a Markdown parser. Marked's license \nfollows:\nCopyright (c) 2011-2012, Christopher Jeffrey (https://github.com/chjj/)\nPermission is hereby granted, free of charge, to any person obtaining a copy of this\nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n- test/gc/node_modules/weak. Node-weak is a node.js addon that provides garbage \ncollector notifications. Node-weak's license follows:\nCopyright (c) 2011, Ben Noordhuis <info@bnoordhuis.nl>\nPermission to use, copy, modify, and/or distribute this software for any purpose with or \nwithout fee is hereby granted, provided that the above copyright notice and this \npermission notice appear in all copies.THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL \nWARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED \nWARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL \nTHE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR \nCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING \nFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF \nCONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF \nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n-src/ngx-queue.h. ngx-queue.h is taken from the nginx source tree. nginx's\nlicense follows:\nCopyright (C) 2002-2012 Igor Sysoev\nCopyright (C) 2011,2012 Nginx, Inc.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' \nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \nSHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nJussi Kalliokoski\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom 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 \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nStanislav Karchebny\nCopyright (c) 2001 Stanislav Karchebny <berk@madfire.net>\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER \nCONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nRobert Kieffer\nCopyright (c) 2010-2012 Robert Kieffer\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom 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 \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nLearnboost\nCopyright (c) 2012 LearnBoost <tj@learnboost.com>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the 'Software'), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nThe LevelDB Authors\nCopyright (c) 2011 The LevelDB Authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.* Neither the name of Google Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe Libjingle Authors\nCopyright 2012, The Libjingle Authors.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe LibYuv Project Authors\nCopyright 2011 The LibYuv Project Authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google nor the names of its contributors may be used to endorse \nor promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nLinux Foundation, IBM Corp., and Sun Microsystems, Inc.\nCopyright (c) Linux Foundation 2007, 2008\nCopyright (c) IBM Corp. 2006\nCopyright (c) Sun Microsystems, Inc. 2000, 2006\n---\nCopyright (c) 2007, 2010 Linux Foundation \nCopyright (c) 2006 IBM Corporation \nCopyright (c) 2000, 2006 Sun Microsystems, Inc. \nAll rights reserved. \nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer. \n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution. \n3. Neither the name of the Linux Foundation nor the names of its contributors may be \nused to endorse or promote products derived from this software without specific prior \nwritten permission.\n\nMarkLogic Corporation\nCopyright (C) 2011 by MarkLogic Corporation\nAuthor: Mike Brevoort <mike@brevoort.com>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rightsto use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software isfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nNick Mathewson, Dug Song and The Regents of the University of California\nCopyright (c) 2005 Nick Mathewson <nickm@freehaven.net>\nCopyright (c) 2000 Dug Song <dugsong@monkey.org>\nCopyright (c) 1993 The Regents of the University of California. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.3. Neither the name of the University nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS \nIS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \nSHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nCharlie McConnell\nCopyright (C) 2011 by Charlie McConnell\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nCaolan McMahon\nCopyright (c) 2010 Caolan McMahon\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software isfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS INTHE SOFTWARE.\n\nMicrosoft Corporation\nPortions of this software are licensed under the Common Public License 1.0 \n(http://opensource.org/licenses/cpl.php). The source code for these files, along with their \nmodifications can be found at: https://github.com/adobe/bracketsshell/tree/master/installer/win. \n\nTodd C. Miller\nCopyright (c) 1996, 1998-2002 Todd C. Miller <Todd.Miller@courtesan.com>\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions ofsource code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.\n4. Products derived from this software may not be called \"Sudo\" nor may \"Sudo\" appear \nin their names without specific prior written permission from the author.\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED \nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR \nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE \nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, \nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, \nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY \nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \nPOSSIBILITY OF SUCH DAMAGE.\n\nMozilla Foundation and Marti Maria\nCopyright (C) 2009 Mozilla Foundation\nCopyright (C) 1998-2007 Marti Maria\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nMozilla.org\nPortions licensed under the Mozilla Public License Version 1.1, available at \nwww.mozilla.org.\n\nNear Infinity Corporation\nCopyright (c) 2012 Near Infinity Corporation\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE \nANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHT HOLDERS BELIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTIONOF CONTRACT, TORT OR OTHERWISE, \nARISING FROM, OUT OF OR IN CONNECTIONWITH THE SOFTWARE OR THE \nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n\nNetscape Communications\nPortions licensed under the Netscape Public License Version 1.1, available at \nwww.mozilla.org/NPL/.\n\nMark Olesen, Queen’s Univ at Kingston\nCopyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA> Queen's Univ at \nKingston (Canada)\nPermission to use, copy, modify, and distribute this software for any purpose without fee \nis hereby granted, provided that this entire notice is included in all copies of any software \nwhich is or includes a copy or modification of this software and in all copies of the \nsupporting documentation for such software.\nTHIS SOFTWARE IS BEING PROVIDED \"AS IS\", WITHOUT ANY EXPRESS OR \nIMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR \nQUEEN'S UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR \nWARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS \nSOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.\nAll of which is to say that you can do what you like with this source code provided you \ndon't try to sell it as your own and you include an unaltered copy of this message \n(including the copyright).\nIt is also implicitly understood that bug fixes and improvements should make their way \nback to the general Internet community so that everyone benefits.\n\nSascha Peilicke\nCopyright (c) 2011, Sascha Peilicke <saschpe@gmx.de>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nLakshan Perera\nCopyright (c) 2011 Lakshan Perera (laktek.com)\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nJeff Pickhardt\nCopyright (c) 2011 Jeff Pickhardt\nModified from the Python CodeMirror mode, Copyright (c) 2010 Timothy Farrell\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rightsto use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software isfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nPivotal Labs\nCopyright (c) 2008-2010 Pivotal Labs\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to\nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nNiels Provos \nCopyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nBjorn Reese and Daniel Stenberg \nCopyright (C) 2001 Bjorn Reese and Daniel Stenberg.\nPermission to use, copy, modify, and distribute this software for any purpose with or \nwithout fee is hereby granted, provided that the above copyright notice and this \npermission notice appear in all copies.\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR \nIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED \nWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR\nPURPOSE. THE AUTHORS AND CONTRIBUTORS ACCEPT NO \nRESPONSIBILITY IN ANY CONCEIVABLE MANNER.\n\nThe Regents of the University of California \nCopyright (c) 1982, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994\nThe Regents of the University of California. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. All advertising materials mentioning features or use of this software must display the \nfollowing acknowledgement: This product includes software developed by the \nUniversity of California, Berkeley and its contributors.4. Neither the name of the University nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS \"AS \nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \nSHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE. \n\nJonathan 'Wolf' Rentzsch\nCopyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>\nSome rights reserved: <http://opensource.org/licenses/mit-license.php>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nJohn Resig and The Dojo Foundation\nCopyright (c) 2009,2011 John Resig\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout 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 \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\nIncludes Sizzle.js\nhttp://sizzlejs.com/\nCopyright 2011, The Dojo Foundation\nReleased under the MIT, BSD, and GPL Licenses.\n\nJP Richardson\nCopyright (c) 2011-2012 JP Richardson\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the 'Software'), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE. \n\nHenryk Richter \nCopyright (C) 2007 Henryk Richter. built upon xdf objfmt (C) Peter Johnson \nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER \nCONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nRSA Security, Inc.\nPortions licensed under the Mozilla Public License Version 1.1, available at \nwww.mozilla.org.\n\nSabaca\nCopyright (C) 2011 by Sabaca <mail@sabaca.com> under the MIT license.\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rightsto use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software isfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, \nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\nUSE OR OTHER DEALINGS IN THE SOFTWARE.Isaac Z. Schlueter\nCopyright 2009, 2010, 2011 Isaac Z. Schlueter.\nAll rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \nWARRANTIESOF MERCHANTABILITY, FITNESS FOR A PARTICULAR \nPURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY,WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, \nARISINGFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE \nUSE OROTHER DEALINGS IN THE SOFTWARE.\n\nIsaac Z. Schlueter\nCopyright (c) Isaac Z. Schlueter (\"Author\")\nAll rights reserved.\nThe BSD License\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS \nIS'' ANDANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \nLIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND \nFITNESS FOR A PARTICULARPURPOSE ARE DISCLAIMED. IN NO EVENT \nSHALL THE AUTHOR OR CONTRIBUTORSBE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL \nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOFSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; \nORBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \nLIABILITY,WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCEOR OTHERWISE) ARISING IN ANY WAY OUT OF \nTHE USE OF THIS SOFTWARE, EVENIF ADVISED OF THE POSSIBILITY OF \nSUCH DAMAGE.\n\nThomas Schmid\nCopyright (C) 2012 Thomas Schmid <schmid-thomas@gmx.net>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nSencha Inc., LearnBoost, TJ Holowaychuk\nCopyright (c) 2010 Sencha Inc.\nCopyright (c) 2011 LearnBoost\nCopyright (c) 2011 TJ Holowaychuk\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nJulian Seward\nhttp://www.bzip.org\nVersion 1.0.3 of 15 February 2005\nCopyright © 1996-2005 Julian Seward\nThis program, bzip2, the associated library libbzip2, and all documentation, are copyright \n© 1996-2005 Julian Seward. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\nRedistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\nThe origin of this software must not be misrepresented; you must not claim that you \nwrote the original software. If you use this software in a product, an acknowledgment in \nthe product documentation would be appreciated but is not required.\nAltered source versions must be plainly marked as such, and must not be misrepresented \nas being the original software.\nThe name of the author may not be used to endorse or promote products derived from this \nsoftware without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\nPATENTS: To the best of my knowledge, bzip2 and libbzip2 do not use any patented \nalgorithms. However, I do not have the resources to carry out a patent search. Therefore I \ncannot give any guarantee of the above statement.\n\nJulian R. Seward (Valgrind.h)\nThis file is part of Valgrind, a dynamic binary instrumentation framework.\nCopyright (C) 2000-2008 Julian Seward. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. The origin of this software must not be misrepresented; you must not claim that you \nwrote the original software. If you use this software in a product, an acknowledgment in \nthe product documentation would be appreciated but is not required.\n3. Altered source versions must be plainly marked as such, and must not be \nmisrepresented as being the original software.\n4. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, ORTORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nRoman Shtylman\nCopyright (C) Roman Shtylman <shtylman@gmail.com>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nSilicon Graphics, Inc.\nThe Original Code is: OpenGL Sample Implementation, Version 1.2.1, released January \n26, 2000, developed by Silicon Graphics, Inc. The Original Code is Copyright (c) 1991-\n2000 Silicon Graphics, Inc. Copyright in any portions created by third parties is as \nindicated elsewhere herein. All Rights Reserved.\n\nSkype Limited\nCopyright (c) 2006-2011, Skype Limited. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n-Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n-Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n- Neither the name of Internet Society, IETF or IETF Trust, nor the names of specific \ncontributors, may be used to endorse or promote products derived from this software \nwithout specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nsourceLair\nCopyright (c) 2011 sourceLair <support@sourcelair.com>Permission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nEinar Otto Stangvik \nCopyright (c) 2011-2012 Einar Otto Stangvik <einaros@gmail.com>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nSuitable Systems\nCopyright (c) 2010 Suitable Systems\nAll rights reserved.\nDeveloped by: Daniel Griscom\nSuitable Systemshttp://www.suitable.com\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal with the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\n-Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimers.\n-Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimers in the documentation and/or other materials \nprovided with the distribution.\n- Neither the names of Suitable Systems nor the names of its contributors may be used to \nendorse or promote products derived from this Software without specific prior written \npermission.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR \nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, \nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE \nUSE OR OTHER DEALINGS WITH THE SOFTWARE.\nFor more information about SMSLib, see\n<http://www.suitable.com/tools/smslib.html>\nor contact\nDaniel Griscom\nSuitable Systems\n1 Centre Street, Suite 204\nWakefield, MA 01880\n(781) 665-0053\n\nAlexei Svitkine\nCopyright (C) 2010 Alexei Svitkine\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. Neither the name of the author nor the names of other contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER \nCONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nSimon Tatham and Julian Hall\nThe Netwide Assembler is copyright (C) 1996 Simon Tatham and Julian Hall. All rights \nreserved. The software is redistributable under the license given in the file \"License\" \ndistributed in the NASM archive.\nCopyright 1996-2009 the NASM Authors - All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nBenjamin Thomas, Robert Kieffer\nCopyright (c) 2010 Benjamin Thomas, Robert Kieffer\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nTwitter, Inc.\nThis product includes software licensed under the Apache License, Version 2.0 \nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUbalo, Inc.\nCopyright (c) 2011, Ubalo, Inc. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of the Ubalo, Inc. nor the names of its contributors may be used to \nendorse or promote products derived from this software without specific prior written \npermission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \nCONSEQUENTIAL DAMAGES (INCLUDING,BUT NOT LIMITED TO, \nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, \nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, \nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY \nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \nPOSSIBILITY OF SUCH DAMAGE.\n\nMichael Urman\nCopyright (C) 2003-2007 Michael Urman\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER \nCONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nJean-Marc Valin/Xiph.org Foundation\n© 2002-2003, Jean-Marc Valin/Xiph.Org Foundation\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution. \nNeither the name of the Xiph.org Foundation nor the names of its contributors may be \nused to endorse or promote products derived from this software without specific prior \nwritten permission. \nThis software is provided by the copyright holders and contributors “as is” and any \nexpress or implied warranties, including, but not limited to, the implied warranties of \nmerchantability and fitness for a particular purpose are disclaimed. In no event shall the \nfoundation or contributors be liable for any direct, indirect, incidental, special, \nexemplary, or consequential damages (including, but not limited to, procurement of \nsubstitute goods or services; loss of use, data, or profits; or business interruption) \nhowever caused and on any theory of liability, whether in contract, strict liability, or tort \n(including negligence or otherwise) arising in any way out of the use of this software, \neven if advised of the possibility of such damage.\n\nWalmart\nCopyright (c) 2011-2013, Walmart.\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met: \n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer. \n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution. \n* Neither the name of Walmart nor the names of its contributors may be used to endorse \nor promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" ANDANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \nAREDISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR \nANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, \nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, \nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ANDON \nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY \nOUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE \nPOSSIBILITY OF SUCH DAMAGE.\n\nChris Wanstrath and Jan Lehnardt (Mustache.js)\nCopyright (c) 2009 Chris Wanstrath (Ruby)\nCopyright (c) 2010 Jan Lehnardt (JavaScript)\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR \nOTHER DEALINGS IN THE SOFTWARE.\n\nThe WebM Project authors\nCopyright (c) 2010, The WebM Project authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google, nor the WebM Project, nor the names of its contributors \nmay be used to endorse or promote products derived from this software without specific \nprior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe WebRTC project authors \nCopyright (c) 2011, The WebRTC project authors. All rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n* Neither the name of Google nor the names of its contributors may be used to endorse \nor promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, \nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR \nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\nAdditional IP Rights Grant (Patents)\n\"This implementation\" means the copyrightable works distributed by Google as part of \nthe WebRTC code package.Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, \nirrevocable (except as stated in this section) patent license to make, have made, use, offer \nto sell, sell, import, transfer, and otherwise run, modify and propagate the contents of this \nimplementation of the WebRTC code package, where such license applies only to those \npatent claims, both currently owned by Google and acquired in the future, licensable by \nGoogle that are necessarily infringed by this implementation of the WebRTC code \npackage. This grant does not include claims that would be infringed only as a \nconsequence of further modification of this implementation. If you or your agent or \nexclusive licensee institute or order or agree to the institution of patent litigation against \nany entity (including a cross-claim or counterclaim in a lawsuit) alleging that this \nimplementation of the WebRTC code package or any code incorporated within this \nimplementation of the WebRTC code package constitutes direct or contributory patent \ninfringement, or inducement of patent infringement, then any patent rights granted to you \nunder this License for this implementation of the WebRTC code package shall terminate \nas of the date such litigation is filed.\n\nMaxim Yegorushkin \nCopyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com>\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of \nconditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of \nconditions and the following disclaimer in the documentation and/or other materials \nprovided with the distribution.\n3. The name of the author may not be used to endorse or promote products derived from \nthis software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A \nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \nAUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER \nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nAppendTo LLC\nCopyright 2013 appendTo LLC. (http://appendto.com/team)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this \nsoftware and associated documentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights to use, copy, modify, merge, \npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or \nsubstantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nChris Winberry\nCopyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n \nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\nPeter Zotov , Public Domain Notice (murmurhash3-js)\nThe MurmurHash3 algorithm was created by Austin Appleby.  \nThis JavaScript port was authored *  by Peter Zotov (based on Java port by Yonik Seeley) \nand is placed into the public domain. *  The author hereby disclaims copyright to this source code.\n\n\nnode-methods is authored by TJ Holowaychuck under the terms of the MIT license.\n\nFelix Geisendörfer\nCopyright (C) 2011 Felix Geisendörfer\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, including \nwithout limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the \nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT \nNOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. \nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nAndrew Kelley\nCopyright (c) 2013 Andrew Kelley\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nMarco Aurelio\nCopyright (c) 2013 Marco Aurelio\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nLea Verou\nCopyright (c) 2013 Lea Verou. All rights reserved.\n \nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"), \nto deal in the Software without restriction, including without limitation \nthe rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the \nSoftware is furnished to do so, subject to the following conditions:\n \nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \nDEALINGS IN THE SOFTWARE.\n\n\nThe Dojo Foundation\nCopyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>\nBased on Underscore.js 1.5.2, copyright 2009-2013 Jeremy Ashkenas,\nDocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n \nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n \nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\nIsaac Z. Schlueter\nCopyright 2009, 2010, 2011 Isaac Z. Schlueter.\nAll rights reserved.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n\nEditorConfig Team\nCopyright © 2012 EditorConfig Team\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the “Software”), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\nCopyright (C) 2010-2013 Philipp Dunkel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "\n| :warning: On September 1, 2021, Adobe will end support for Brackets. If you would like to continue using, maintaining, and improving Brackets, you may fork the project on [GitHub](https://github.com/adobe/brackets). Through Adobe’s partnership with Microsoft, we encourage users to migrate to [Visual Studio Code](https://aka.ms/brackets-to-vscode), Microsoft’s free code editor built on open source.\n| ---\n\n\nWelcome to Brackets! [![Build Status](https://travis-ci.org/adobe/brackets.svg?branch=master)](https://travis-ci.org/adobe/brackets)\n-------------------\n\nBrackets is a modern open-source code editor for HTML, CSS\nand JavaScript that's *built* in HTML, CSS and JavaScript. \n\nWhat makes Brackets different from other web code editors?\n\n* **Tools shouldn't get in your way.** Instead of cluttering up your coding\nenvironment with lots of panels and icons, the Quick Edit UI in Brackets puts \ncontext-specific code and tools inline.\n* **Brackets is in sync with your browser.** With Live Preview, Brackets\nworks directly with your browser to push code edits instantly and jump\nback and forth between your real source code and the browser view.\n* **Do it yourself.** Because Brackets is open source, and built with HTML, CSS\nand JavaScript, you can [help build](https://github.com/adobe/brackets/blob/master/CONTRIBUTING.md) the best code editor for the web.\n\nBrackets may have reached version 1, but we're not stopping there. We have many feature ideas on our\n[trello board](http://bit.ly/BracketsTrelloBoard) that we're anxious to add and other\ninnovative web development workflows that we're planning to build into Brackets. \nSo take Brackets out for a spin and let us know how we can make it your favorite editor. \n\nYou can see some \n[screenshots of Brackets](https://github.com/adobe/brackets/wiki/Brackets-Screenshots)\non the wiki, [intro videos](http://www.youtube.com/user/CodeBrackets) on YouTube, and news on the [Brackets blog](http://blog.brackets.io/).\n\nHow to install and run Brackets\n-------------------------------\n#### Download\n\nInstallers for the latest stable build for Mac, Windows and Linux (Debian/Ubuntu) can be [downloaded here](http://brackets.io/).\n\n#### Usage\n\nBy default, Brackets opens a folder containing some simple \"Getting Started\" content.\nYou can choose a different folder to edit using *File > Open Folder*.\n\nMost of Brackets should be pretty self-explanatory, but for information on how\nto use its unique features, like Quick Edit and Live Preview, please read\n[How to Use Brackets](http://github.com/adobe/brackets/wiki/How-to-Use-Brackets). \nAlso, see the [release notes](http://github.com/adobe/brackets/wiki/Release-Notes)\nfor a list of new features and known issues in each build.\n\nIn addition to the core features built into Brackets, there is a large and growing\ncommunity of developers building extensions that add all sorts of useful functionality.\nSee the [Brackets Extension Registry](https://registry.brackets.io/)\nfor a list of available extensions. For installation instructions,\nsee the [extensions wiki page](https://github.com/adobe/brackets/wiki/Brackets-Extensions).\n\n#### Need help?\n\nHaving problems starting Brackets the first time, or not sure how to use Brackets?  Please \nreview [Troubleshooting](https://github.com/adobe/brackets/wiki/Troubleshooting), which helps \nyou to fix common problems and find extra help if needed.\n\nHelping Brackets\n----------------\n\n#### I found a bug!\n\nIf you found a repeatable bug, and [troubleshooting](https://github.com/adobe/brackets/wiki/Troubleshooting) \ntips didn't help, then be sure to [search existing issues](https://github.com/adobe/brackets/issues) first.\nInclude steps to consistently reproduce the problem, actual vs. expected results, screenshots, and your OS and\nBrackets version number. Disable all extensions to verify the issue is a core Brackets bug.\n[Read more guidelines for filing good bugs.](https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue)\n\n\n#### I have a new suggestion, but don't know how to program!\n\nFor feature requests please first check our [Trello board](http://bit.ly/BracketsBacklog) to\nsee if it's already there; you can upvote it if so. If not, feel free to file it as an issue as above; we'll\nmove it to the feature backlog for you.\n\n\n#### I want to help with the code!\n\nAwesome! _There are lots of ways you can help._ First read \n[CONTRIBUTING.md](https://github.com/adobe/brackets/blob/master/CONTRIBUTING.md), \nthen learn how to [pull the repo and hack on Brackets](https://github.com/adobe/brackets/wiki/How-to-Hack-on-Brackets).\n\nThe text editor inside Brackets is based on \n[CodeMirror](http://github.com/codemirror/CodeMirror)&mdash;thanks to Marijn for\ntaking our pull requests, implementing feature requests and fixing bugs! See \n[Notes on CodeMirror](https://github.com/adobe/brackets/wiki/Notes-on-CodeMirror)\nfor info on how we're using CodeMirror.\n\nAlthough Brackets is built in HTML/CSS/JS, it currently runs as a desktop \napplication in a thin native shell, so that it can access your local files.\n(If you just try to open the index.html file in a browser, it won't work yet.)\nThe native shell for Brackets lives in a separate repo, \n[adobe/brackets-shell](https://github.com/adobe/brackets-shell/).\n\n\nI want to keep track of how Brackets is doing!\n----------------------------------------------\n\nNot sure you needed the exclamation point there, but we like your enthusiasm.\n\n#### What's Brackets working on next?\n\n* In our [feature backlog](http://bit.ly/BracketsBacklog), the columns to the right\n  (starting from \"Development\") list the features that we're currently working on.\n  \"Ready\" shows what we'll be working on next.\n* Watch our [GitHub activity stream](https://github.com/adobe/brackets/pulse).\n* Watch our [Waffle Kanban board](https://waffle.io/adobe/brackets): Work items in [![Stories in Ready](https://badge.waffle.io/adobe/brackets.svg?label=ready&title=Ready)](http://waffle.io/adobe/brackets) are next. The entire development process is outlined in the [Developer Guide](https://github.com/adobe/brackets/wiki/Brackets-Developers-Guide).\n\n#### Contact info\n\n* **E-mail:** [admin@brackets.io](mailto:admin@brackets.io)\n* **Slack:** [Brackets on Slack](https://brackets.slack.com) (You can join by sending a mail to [admin@brackets.io](mailto:admin@brackets.io) with the subject line `slack registration request` specifying the email addresses you would like to register).\n* **Developers mailing list:** http://groups.google.com/group/brackets-dev\n* **Twitter:** [@brackets](https://twitter.com/brackets)\n* **Blog:** http://blog.brackets.io/\n* **IRC:** [#brackets on freenode](http://webchat.freenode.net/?channels=brackets)\n\n---\n\nPlease note that this project is released with a [Contributor Code of Conduct](https://github.com/adobe/brackets/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.\n"
  },
  {
    "path": "build.json",
    "content": "{\n    \"version\": \"release-1.11-prerelease-2\",\n    \"title\" : \"Brackets 1.11 2nd Pre-release for community testing\",\n    \"description\" : \"This is Brackets 1.11 2nd pre-release build. In this release, CEF has been upgraded for Linux which resolved the much reported libgcrypt dependency, basic es6 support has been added by providing eslint out of the box and making required changes to list Classes/methods/arrow function expressions/generator functions/async functions/class getter-setter methods and much more. \",\n    \"prerelease\": true\n}\n"
  },
  {
    "path": "npm-shrinkwrap.json",
    "content": "{\n  \"name\": \"Brackets\",\n  \"version\": \"1.11.0-0\",\n  \"dependencies\": {\n    \"abbrev\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"abbrev@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz\"\n    },\n    \"acorn\": {\n      \"version\": \"5.1.1\",\n      \"from\": \"acorn@>=5.0.1 <6.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz\",\n      \"dev\": true\n    },\n    \"acorn-dynamic-import\": {\n      \"version\": \"2.0.2\",\n      \"from\": \"acorn-dynamic-import@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"acorn\": {\n          \"version\": \"4.0.13\",\n          \"from\": \"acorn@>=4.0.3 <5.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"acorn-jsx\": {\n      \"version\": \"3.0.1\",\n      \"from\": \"acorn-jsx@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"acorn\": {\n          \"version\": \"3.3.0\",\n          \"from\": \"acorn@>=3.0.4 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"adm-zip\": {\n      \"version\": \"0.4.4\",\n      \"from\": \"adm-zip@0.4.4\",\n      \"resolved\": \"https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz\",\n      \"dev\": true\n    },\n    \"ajv\": {\n      \"version\": \"4.11.8\",\n      \"from\": \"ajv@>=4.7.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz\",\n      \"dev\": true\n    },\n    \"ajv-keywords\": {\n      \"version\": \"1.5.1\",\n      \"from\": \"ajv-keywords@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz\",\n      \"dev\": true\n    },\n    \"align-text\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"align-text@>=0.1.3 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"amdefine\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"amdefine@>=0.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"ansi-escapes\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"ansi-escapes@>=1.1.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz\",\n      \"dev\": true\n    },\n    \"ansi-regex\": {\n      \"version\": \"2.1.1\",\n      \"from\": \"ansi-regex@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz\"\n    },\n    \"ansi-styles\": {\n      \"version\": \"2.2.1\",\n      \"from\": \"ansi-styles@>=2.2.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz\"\n    },\n    \"anymatch\": {\n      \"version\": \"1.3.0\",\n      \"from\": \"anymatch@1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz\"\n    },\n    \"argparse\": {\n      \"version\": \"0.1.16\",\n      \"from\": \"argparse@>=0.1.11 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"underscore.string\": {\n          \"version\": \"2.4.0\",\n          \"from\": \"underscore.string@>=2.4.0 <2.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"arr-diff\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"arr-diff@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz\"\n    },\n    \"arr-flatten\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"arr-flatten@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz\"\n    },\n    \"array-differ\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"array-differ@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"array-union\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"array-union@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"array-uniq\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"array-uniq@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"array-unique\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"array-unique@>=0.2.1 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz\"\n    },\n    \"arrify\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"arrify@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz\"\n    },\n    \"asap\": {\n      \"version\": \"2.0.6\",\n      \"from\": \"asap@>=2.0.3 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/asap/-/asap-2.0.6.tgz\",\n      \"dev\": true,\n      \"optional\": true\n    },\n    \"asn1\": {\n      \"version\": \"0.2.3\",\n      \"from\": \"asn1@>=0.2.3 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz\"\n    },\n    \"asn1.js\": {\n      \"version\": \"4.9.1\",\n      \"from\": \"asn1.js@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz\",\n      \"dev\": true\n    },\n    \"assert\": {\n      \"version\": \"1.4.1\",\n      \"from\": \"assert@>=1.1.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/assert/-/assert-1.4.1.tgz\",\n      \"dev\": true\n    },\n    \"assert-plus\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"assert-plus@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz\"\n    },\n    \"async\": {\n      \"version\": \"2.1.4\",\n      \"from\": \"async@2.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/async/-/async-2.1.4.tgz\"\n    },\n    \"async-each\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"async-each@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz\"\n    },\n    \"asynckit\": {\n      \"version\": \"0.4.0\",\n      \"from\": \"asynckit@>=0.4.0 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\"\n    },\n    \"aws-sign2\": {\n      \"version\": \"0.6.0\",\n      \"from\": \"aws-sign2@>=0.6.0 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz\"\n    },\n    \"aws4\": {\n      \"version\": \"1.6.0\",\n      \"from\": \"aws4@>=1.2.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz\"\n    },\n    \"babel-code-frame\": {\n      \"version\": \"6.22.0\",\n      \"from\": \"babel-code-frame@>=6.16.0 <7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz\",\n      \"dev\": true\n    },\n    \"balanced-match\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"balanced-match@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz\"\n    },\n    \"base64-js\": {\n      \"version\": \"1.2.1\",\n      \"from\": \"base64-js@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz\",\n      \"dev\": true\n    },\n    \"bcrypt-pbkdf\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"bcrypt-pbkdf@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz\",\n      \"optional\": true\n    },\n    \"big.js\": {\n      \"version\": \"3.1.3\",\n      \"from\": \"big.js@>=3.1.3 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz\",\n      \"dev\": true\n    },\n    \"binary\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"binary@>=0.3.0 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary/-/binary-0.3.0.tgz\"\n    },\n    \"binary-extensions\": {\n      \"version\": \"1.9.0\",\n      \"from\": \"binary-extensions@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.9.0.tgz\"\n    },\n    \"bl\": {\n      \"version\": \"0.9.5\",\n      \"from\": \"bl@>=0.9.0 <0.10.0\",\n      \"resolved\": \"https://registry.npmjs.org/bl/-/bl-0.9.5.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"isarray\": {\n          \"version\": \"0.0.1\",\n          \"from\": \"isarray@0.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\",\n          \"dev\": true\n        },\n        \"readable-stream\": {\n          \"version\": \"1.0.34\",\n          \"from\": \"readable-stream@>=1.0.26 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz\",\n          \"dev\": true\n        },\n        \"string_decoder\": {\n          \"version\": \"0.10.31\",\n          \"from\": \"string_decoder@>=0.10.0 <0.11.0\",\n          \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"block-stream\": {\n      \"version\": \"0.0.9\",\n      \"from\": \"block-stream@*\",\n      \"resolved\": \"https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz\",\n      \"dev\": true\n    },\n    \"bn.js\": {\n      \"version\": \"4.11.7\",\n      \"from\": \"bn.js@>=4.1.1 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz\",\n      \"dev\": true\n    },\n    \"body-parser\": {\n      \"version\": \"1.14.2\",\n      \"from\": \"body-parser@>=1.14.0 <1.15.0\",\n      \"resolved\": \"https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"iconv-lite\": {\n          \"version\": \"0.4.13\",\n          \"from\": \"iconv-lite@0.4.13\",\n          \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz\",\n          \"dev\": true\n        },\n        \"qs\": {\n          \"version\": \"5.2.0\",\n          \"from\": \"qs@5.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/qs/-/qs-5.2.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"boom\": {\n      \"version\": \"2.10.1\",\n      \"from\": \"boom@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/boom/-/boom-2.10.1.tgz\"\n    },\n    \"brace-expansion\": {\n      \"version\": \"1.1.8\",\n      \"from\": \"brace-expansion@>=1.1.7 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz\"\n    },\n    \"braces\": {\n      \"version\": \"1.8.5\",\n      \"from\": \"braces@>=1.8.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/braces/-/braces-1.8.5.tgz\"\n    },\n    \"brorand\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"brorand@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz\",\n      \"dev\": true\n    },\n    \"browserify-aes\": {\n      \"version\": \"1.0.6\",\n      \"from\": \"browserify-aes@>=1.0.4 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz\",\n      \"dev\": true\n    },\n    \"browserify-cipher\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"browserify-cipher@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"browserify-des\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"browserify-des@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"browserify-rsa\": {\n      \"version\": \"4.0.1\",\n      \"from\": \"browserify-rsa@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz\",\n      \"dev\": true\n    },\n    \"browserify-sign\": {\n      \"version\": \"4.0.4\",\n      \"from\": \"browserify-sign@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz\",\n      \"dev\": true\n    },\n    \"browserify-zlib\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"browserify-zlib@>=0.1.4 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"buffer\": {\n      \"version\": \"4.9.1\",\n      \"from\": \"buffer@>=4.3.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz\",\n      \"dev\": true\n    },\n    \"buffer-shims\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"buffer-shims@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz\"\n    },\n    \"buffer-xor\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"buffer-xor@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"buffers\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"buffers@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz\"\n    },\n    \"builtin-modules\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"builtin-modules@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz\",\n      \"dev\": true\n    },\n    \"builtin-status-codes\": {\n      \"version\": \"3.0.0\",\n      \"from\": \"builtin-status-codes@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz\",\n      \"dev\": true\n    },\n    \"bytes\": {\n      \"version\": \"2.2.0\",\n      \"from\": \"bytes@2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz\",\n      \"dev\": true\n    },\n    \"caller-path\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"caller-path@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"callsites\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"callsites@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz\",\n      \"dev\": true\n    },\n    \"camelcase\": {\n      \"version\": \"1.2.1\",\n      \"from\": \"camelcase@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz\",\n      \"dev\": true\n    },\n    \"caseless\": {\n      \"version\": \"0.11.0\",\n      \"from\": \"caseless@>=0.11.0 <0.12.0\",\n      \"resolved\": \"https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz\"\n    },\n    \"center-align\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"center-align@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz\",\n      \"dev\": true\n    },\n    \"chainsaw\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"chainsaw@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz\"\n    },\n    \"chalk\": {\n      \"version\": \"1.1.3\",\n      \"from\": \"chalk@>=1.1.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz\"\n    },\n    \"chokidar\": {\n      \"version\": \"1.6.1\",\n      \"from\": \"chokidar@1.6.1\",\n      \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz\"\n    },\n    \"ci-info\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"ci-info@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"cipher-base\": {\n      \"version\": \"1.0.4\",\n      \"from\": \"cipher-base@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz\",\n      \"dev\": true\n    },\n    \"circular-json\": {\n      \"version\": \"0.3.3\",\n      \"from\": \"circular-json@>=0.3.1 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz\",\n      \"dev\": true\n    },\n    \"clean-css\": {\n      \"version\": \"1.0.12\",\n      \"from\": \"clean-css@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/clean-css/-/clean-css-1.0.12.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"commander\": {\n          \"version\": \"1.3.2\",\n          \"from\": \"commander@>=1.3.0 <1.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/commander/-/commander-1.3.2.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"cli-cursor\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"cli-cursor@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"cli-width\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"cli-width@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz\",\n      \"dev\": true\n    },\n    \"cliui\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"cliui@>=2.1.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"wordwrap\": {\n          \"version\": \"0.0.2\",\n          \"from\": \"wordwrap@0.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"co\": {\n      \"version\": \"4.6.0\",\n      \"from\": \"co@>=4.6.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/co/-/co-4.6.0.tgz\",\n      \"dev\": true\n    },\n    \"code-point-at\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"code-point-at@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz\",\n      \"dev\": true\n    },\n    \"coffee-script\": {\n      \"version\": \"1.3.3\",\n      \"from\": \"coffee-script@>=1.3.3 <1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz\",\n      \"dev\": true\n    },\n    \"colors\": {\n      \"version\": \"0.6.2\",\n      \"from\": \"colors@>=0.6.2 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/colors/-/colors-0.6.2.tgz\",\n      \"dev\": true\n    },\n    \"combined-stream\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"combined-stream@>=1.0.5 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz\"\n    },\n    \"commander\": {\n      \"version\": \"2.11.0\",\n      \"from\": \"commander@>=2.9.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/commander/-/commander-2.11.0.tgz\"\n    },\n    \"concat-map\": {\n      \"version\": \"0.0.1\",\n      \"from\": \"concat-map@0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\"\n    },\n    \"concat-stream\": {\n      \"version\": \"1.6.0\",\n      \"from\": \"concat-stream@>=1.5.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz\",\n      \"dev\": true\n    },\n    \"config-chain\": {\n      \"version\": \"1.1.11\",\n      \"from\": \"config-chain@>=1.1.8 <1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz\",\n      \"dev\": true\n    },\n    \"console-browserify\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"console-browserify@>=1.1.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz\",\n      \"dev\": true\n    },\n    \"constants-browserify\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"constants-browserify@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"content-type\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"content-type@>=1.0.1 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"core-util-is\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"core-util-is@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\"\n    },\n    \"create-ecdh\": {\n      \"version\": \"4.0.0\",\n      \"from\": \"create-ecdh@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz\",\n      \"dev\": true\n    },\n    \"create-hash\": {\n      \"version\": \"1.1.3\",\n      \"from\": \"create-hash@>=1.1.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz\",\n      \"dev\": true\n    },\n    \"create-hmac\": {\n      \"version\": \"1.1.6\",\n      \"from\": \"create-hmac@>=1.1.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz\",\n      \"dev\": true\n    },\n    \"cryptiles\": {\n      \"version\": \"2.0.5\",\n      \"from\": \"cryptiles@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz\"\n    },\n    \"crypto-browserify\": {\n      \"version\": \"3.11.1\",\n      \"from\": \"crypto-browserify@>=3.11.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz\",\n      \"dev\": true\n    },\n    \"ctype\": {\n      \"version\": \"0.5.3\",\n      \"from\": \"ctype@0.5.3\",\n      \"resolved\": \"https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz\",\n      \"dev\": true,\n      \"optional\": true\n    },\n    \"d\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"d@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/d/-/d-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"dashdash\": {\n      \"version\": \"1.14.1\",\n      \"from\": \"dashdash@>=1.12.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\"\n        }\n      }\n    },\n    \"date-now\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"date-now@>=0.1.4 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"dateformat\": {\n      \"version\": \"1.0.2-1.2.3\",\n      \"from\": \"dateformat@1.0.2-1.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz\",\n      \"dev\": true\n    },\n    \"debug\": {\n      \"version\": \"2.2.0\",\n      \"from\": \"debug@>=2.2.0 <2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n      \"dev\": true\n    },\n    \"decamelize\": {\n      \"version\": \"1.2.0\",\n      \"from\": \"decamelize@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz\",\n      \"dev\": true\n    },\n    \"decompress-zip\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"decompress-zip@0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.0.tgz\",\n      \"dependencies\": {\n        \"isarray\": {\n          \"version\": \"0.0.1\",\n          \"from\": \"isarray@0.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz\"\n        },\n        \"q\": {\n          \"version\": \"1.5.0\",\n          \"from\": \"q@>=1.1.2 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/q/-/q-1.5.0.tgz\"\n        },\n        \"readable-stream\": {\n          \"version\": \"1.1.14\",\n          \"from\": \"readable-stream@>=1.1.8 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz\"\n        },\n        \"string_decoder\": {\n          \"version\": \"0.10.31\",\n          \"from\": \"string_decoder@>=0.10.0 <0.11.0\",\n          \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n        }\n      }\n    },\n    \"deep-is\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"deep-is@>=0.1.3 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz\",\n      \"dev\": true\n    },\n    \"del\": {\n      \"version\": \"2.2.2\",\n      \"from\": \"del@>=2.0.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/del/-/del-2.2.2.tgz\",\n      \"dev\": true\n    },\n    \"delayed-stream\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"delayed-stream@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\"\n    },\n    \"depd\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"depd@>=1.1.0 <1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/depd/-/depd-1.1.1.tgz\",\n      \"dev\": true\n    },\n    \"des.js\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"des.js@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"diffie-hellman\": {\n      \"version\": \"5.0.2\",\n      \"from\": \"diffie-hellman@>=5.0.0 <6.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz\",\n      \"dev\": true\n    },\n    \"doctrine\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"doctrine@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz\",\n      \"dev\": true\n    },\n    \"dom-walk\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"dom-walk@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz\",\n      \"dev\": true\n    },\n    \"domain-browser\": {\n      \"version\": \"1.1.7\",\n      \"from\": \"domain-browser@>=1.1.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz\",\n      \"dev\": true\n    },\n    \"ecc-jsbn\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"ecc-jsbn@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz\",\n      \"optional\": true\n    },\n    \"ee-first\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"ee-first@1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz\",\n      \"dev\": true\n    },\n    \"elliptic\": {\n      \"version\": \"6.4.0\",\n      \"from\": \"elliptic@>=6.0.0 <7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz\",\n      \"dev\": true\n    },\n    \"emojis-list\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"emojis-list@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz\",\n      \"dev\": true\n    },\n    \"enhanced-resolve\": {\n      \"version\": \"3.4.1\",\n      \"from\": \"enhanced-resolve@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz\",\n      \"dev\": true\n    },\n    \"errno\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"errno@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/errno/-/errno-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"error-ex\": {\n      \"version\": \"1.3.1\",\n      \"from\": \"error-ex@>=1.2.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz\",\n      \"dev\": true\n    },\n    \"es5-ext\": {\n      \"version\": \"0.10.24\",\n      \"from\": \"es5-ext@>=0.10.14 <0.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz\",\n      \"dev\": true\n    },\n    \"es6-iterator\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"es6-iterator@>=2.0.1 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz\",\n      \"dev\": true\n    },\n    \"es6-map\": {\n      \"version\": \"0.1.5\",\n      \"from\": \"es6-map@>=0.1.3 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz\",\n      \"dev\": true\n    },\n    \"es6-set\": {\n      \"version\": \"0.1.5\",\n      \"from\": \"es6-set@>=0.1.5 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz\",\n      \"dev\": true\n    },\n    \"es6-symbol\": {\n      \"version\": \"3.1.1\",\n      \"from\": \"es6-symbol@>=3.1.1 <3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz\",\n      \"dev\": true\n    },\n    \"es6-weak-map\": {\n      \"version\": \"2.0.2\",\n      \"from\": \"es6-weak-map@>=2.0.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz\",\n      \"dev\": true\n    },\n    \"escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"escape-string-regexp@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\"\n    },\n    \"escope\": {\n      \"version\": \"3.6.0\",\n      \"from\": \"escope@>=3.6.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escope/-/escope-3.6.0.tgz\",\n      \"dev\": true\n    },\n    \"eslint\": {\n      \"version\": \"3.19.0\",\n      \"from\": \"eslint@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"argparse\": {\n          \"version\": \"1.0.9\",\n          \"from\": \"argparse@>=1.0.7 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz\",\n          \"dev\": true\n        },\n        \"esprima\": {\n          \"version\": \"4.0.0\",\n          \"from\": \"esprima@>=4.0.0 <5.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz\",\n          \"dev\": true\n        },\n        \"js-yaml\": {\n          \"version\": \"3.9.1\",\n          \"from\": \"js-yaml@>=3.5.1 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"espree\": {\n      \"version\": \"3.4.3\",\n      \"from\": \"espree@>=3.4.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/espree/-/espree-3.4.3.tgz\",\n      \"dev\": true\n    },\n    \"esprima\": {\n      \"version\": \"1.0.4\",\n      \"from\": \"esprima@>=1.0.2 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz\",\n      \"dev\": true\n    },\n    \"esquery\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"esquery@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"esrecurse\": {\n      \"version\": \"4.2.0\",\n      \"from\": \"esrecurse@>=4.1.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz\",\n      \"dev\": true\n    },\n    \"estraverse\": {\n      \"version\": \"4.2.0\",\n      \"from\": \"estraverse@>=4.2.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz\",\n      \"dev\": true\n    },\n    \"esutils\": {\n      \"version\": \"2.0.2\",\n      \"from\": \"esutils@>=2.0.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz\",\n      \"dev\": true\n    },\n    \"event-emitter\": {\n      \"version\": \"0.3.5\",\n      \"from\": \"event-emitter@>=0.3.5 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz\",\n      \"dev\": true\n    },\n    \"eventemitter2\": {\n      \"version\": \"0.4.14\",\n      \"from\": \"eventemitter2@>=0.4.13 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz\",\n      \"dev\": true\n    },\n    \"events\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"events@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/events/-/events-1.1.1.tgz\",\n      \"dev\": true\n    },\n    \"evp_bytestokey\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"evp_bytestokey@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"exit\": {\n      \"version\": \"0.1.2\",\n      \"from\": \"exit@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/exit/-/exit-0.1.2.tgz\",\n      \"dev\": true\n    },\n    \"exit-hook\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"exit-hook@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz\",\n      \"dev\": true\n    },\n    \"expand-brackets\": {\n      \"version\": \"0.1.5\",\n      \"from\": \"expand-brackets@>=0.1.4 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz\"\n    },\n    \"expand-range\": {\n      \"version\": \"1.8.2\",\n      \"from\": \"expand-range@>=1.8.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz\"\n    },\n    \"extend\": {\n      \"version\": \"3.0.1\",\n      \"from\": \"extend@>=3.0.0 <3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/extend/-/extend-3.0.1.tgz\"\n    },\n    \"extglob\": {\n      \"version\": \"0.3.2\",\n      \"from\": \"extglob@>=0.3.1 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz\"\n    },\n    \"extsprintf\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"extsprintf@1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz\"\n    },\n    \"fast-levenshtein\": {\n      \"version\": \"2.0.6\",\n      \"from\": \"fast-levenshtein@>=2.0.4 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz\",\n      \"dev\": true\n    },\n    \"faye-websocket\": {\n      \"version\": \"0.10.0\",\n      \"from\": \"faye-websocket@>=0.10.0 <0.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz\",\n      \"dev\": true\n    },\n    \"figures\": {\n      \"version\": \"1.7.0\",\n      \"from\": \"figures@>=1.3.5 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/figures/-/figures-1.7.0.tgz\",\n      \"dev\": true\n    },\n    \"file-entry-cache\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"file-entry-cache@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz\",\n      \"dev\": true\n    },\n    \"filename-regex\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"filename-regex@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz\"\n    },\n    \"fileset\": {\n      \"version\": \"0.1.8\",\n      \"from\": \"fileset@>=0.1.5 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/fileset/-/fileset-0.1.8.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"glob\": {\n          \"version\": \"3.2.11\",\n          \"from\": \"glob@>=3.0.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n          \"dev\": true,\n          \"dependencies\": {\n            \"minimatch\": {\n              \"version\": \"0.3.0\",\n              \"from\": \"minimatch@>=0.3.0 <0.4.0\",\n              \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n              \"dev\": true\n            }\n          }\n        },\n        \"minimatch\": {\n          \"version\": \"0.4.0\",\n          \"from\": \"minimatch@>=0.0.0 <1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.4.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"fill-range\": {\n      \"version\": \"2.2.3\",\n      \"from\": \"fill-range@>=2.1.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz\"\n    },\n    \"find-parent-dir\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"find-parent-dir@>=0.3.0 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz\",\n      \"dev\": true\n    },\n    \"find-up\": {\n      \"version\": \"1.1.2\",\n      \"from\": \"find-up@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz\",\n      \"dev\": true\n    },\n    \"findup-sync\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"findup-sync@>=0.1.2 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"glob\": {\n          \"version\": \"3.2.11\",\n          \"from\": \"glob@>=3.2.9 <3.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n          \"dev\": true\n        },\n        \"lodash\": {\n          \"version\": \"2.4.2\",\n          \"from\": \"lodash@>=2.4.1 <2.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz\",\n          \"dev\": true\n        },\n        \"minimatch\": {\n          \"version\": \"0.3.0\",\n          \"from\": \"minimatch@>=0.3.0 <0.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"flat-cache\": {\n      \"version\": \"1.2.2\",\n      \"from\": \"flat-cache@>=1.2.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz\",\n      \"dev\": true\n    },\n    \"for-in\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"for-in@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz\"\n    },\n    \"for-own\": {\n      \"version\": \"0.1.5\",\n      \"from\": \"for-own@>=0.1.4 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz\"\n    },\n    \"forever-agent\": {\n      \"version\": \"0.6.1\",\n      \"from\": \"forever-agent@>=0.6.1 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz\"\n    },\n    \"form-data\": {\n      \"version\": \"2.1.4\",\n      \"from\": \"form-data@>=2.1.1 <2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz\"\n    },\n    \"fs-extra\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"fs-extra@2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fs-extra/-/fs-extra-2.0.0.tgz\"\n    },\n    \"fs.realpath\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"fs.realpath@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"fstream\": {\n      \"version\": \"1.0.11\",\n      \"from\": \"fstream@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz\",\n      \"dev\": true\n    },\n    \"gaze\": {\n      \"version\": \"1.1.2\",\n      \"from\": \"gaze@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz\",\n      \"dev\": true\n    },\n    \"generate-function\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"generate-function@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz\"\n    },\n    \"generate-object-property\": {\n      \"version\": \"1.2.0\",\n      \"from\": \"generate-object-property@>=1.1.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz\"\n    },\n    \"get-caller-file\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"get-caller-file@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"getobject\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"getobject@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"getpass\": {\n      \"version\": \"0.1.7\",\n      \"from\": \"getpass@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\"\n        }\n      }\n    },\n    \"glob\": {\n      \"version\": \"7.1.1\",\n      \"from\": \"glob@7.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/glob/-/glob-7.1.1.tgz\",\n      \"dev\": true\n    },\n    \"glob-base\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"glob-base@>=0.3.0 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz\"\n    },\n    \"glob-parent\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"glob-parent@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz\"\n    },\n    \"global\": {\n      \"version\": \"4.3.2\",\n      \"from\": \"global@>=4.3.2 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/global/-/global-4.3.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"process\": {\n          \"version\": \"0.5.2\",\n          \"from\": \"process@>=0.5.1 <0.6.0\",\n          \"resolved\": \"https://registry.npmjs.org/process/-/process-0.5.2.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"globals\": {\n      \"version\": \"9.18.0\",\n      \"from\": \"globals@>=9.14.0 <10.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/globals/-/globals-9.18.0.tgz\",\n      \"dev\": true\n    },\n    \"globby\": {\n      \"version\": \"5.0.0\",\n      \"from\": \"globby@>=5.0.0 <6.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/globby/-/globby-5.0.0.tgz\",\n      \"dev\": true\n    },\n    \"globule\": {\n      \"version\": \"1.2.0\",\n      \"from\": \"globule@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/globule/-/globule-1.2.0.tgz\",\n      \"dev\": true\n    },\n    \"graceful-fs\": {\n      \"version\": \"4.1.11\",\n      \"from\": \"graceful-fs@>=4.1.2 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz\"\n    },\n    \"growl\": {\n      \"version\": \"1.7.0\",\n      \"from\": \"growl@>=1.7.0 <1.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/growl/-/growl-1.7.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt\": {\n      \"version\": \"0.4.5\",\n      \"from\": \"grunt@0.4.5\",\n      \"resolved\": \"https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"async\": {\n          \"version\": \"0.1.22\",\n          \"from\": \"async@>=0.1.22 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/async/-/async-0.1.22.tgz\",\n          \"dev\": true\n        },\n        \"glob\": {\n          \"version\": \"3.1.21\",\n          \"from\": \"glob@>=3.1.21 <3.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.1.21.tgz\",\n          \"dev\": true\n        },\n        \"graceful-fs\": {\n          \"version\": \"1.2.3\",\n          \"from\": \"graceful-fs@>=1.2.0 <1.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz\",\n          \"dev\": true\n        },\n        \"inherits\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"inherits@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz\",\n          \"dev\": true\n        },\n        \"lodash\": {\n          \"version\": \"0.9.2\",\n          \"from\": \"lodash@>=0.9.2 <0.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz\",\n          \"dev\": true\n        },\n        \"minimatch\": {\n          \"version\": \"0.2.14\",\n          \"from\": \"minimatch@>=0.2.12 <0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz\",\n          \"dev\": true\n        },\n        \"nopt\": {\n          \"version\": \"1.0.10\",\n          \"from\": \"nopt@>=1.0.10 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-cleanempty\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"grunt-cleanempty@1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-cleanempty/-/grunt-cleanempty-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"grunt-cli\": {\n      \"version\": \"0.1.9\",\n      \"from\": \"grunt-cli@0.1.9\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-cli/-/grunt-cli-0.1.9.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"nopt\": {\n          \"version\": \"1.0.10\",\n          \"from\": \"nopt@~1.0.10\",\n          \"resolved\": \"https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-contrib-clean\": {\n      \"version\": \"0.4.1\",\n      \"from\": \"grunt-contrib-clean@0.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.4.1.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-concat\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"grunt-contrib-concat@0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-0.3.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-copy\": {\n      \"version\": \"0.4.1\",\n      \"from\": \"grunt-contrib-copy@0.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-0.4.1.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-cssmin\": {\n      \"version\": \"0.6.0\",\n      \"from\": \"grunt-contrib-cssmin@0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-0.6.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-htmlmin\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"grunt-contrib-htmlmin@0.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-htmlmin/-/grunt-contrib-htmlmin-0.1.3.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-jasmine\": {\n      \"version\": \"0.4.2\",\n      \"from\": \"grunt-contrib-jasmine@0.4.2\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-jasmine/-/grunt-contrib-jasmine-0.4.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"graceful-fs\": {\n          \"version\": \"1.1.14\",\n          \"from\": \"graceful-fs@>=1.1.0 <1.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"rimraf\": {\n          \"version\": \"2.0.3\",\n          \"from\": \"rimraf@>=2.0.3 <2.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/rimraf/-/rimraf-2.0.3.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-contrib-less\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"grunt-contrib-less@1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-1.4.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-requirejs\": {\n      \"version\": \"0.4.1\",\n      \"from\": \"grunt-contrib-requirejs@0.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-requirejs/-/grunt-contrib-requirejs-0.4.1.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-uglify\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"grunt-contrib-uglify@0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.2.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-contrib-watch\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"grunt-contrib-watch@1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"async\": {\n          \"version\": \"1.5.2\",\n          \"from\": \"async@>=1.5.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/async/-/async-1.5.2.tgz\",\n          \"dev\": true\n        },\n        \"lodash\": {\n          \"version\": \"3.10.1\",\n          \"from\": \"lodash@>=3.10.1 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-eslint\": {\n      \"version\": \"19.0.0\",\n      \"from\": \"grunt-eslint@19.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-19.0.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-jasmine-node\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"grunt-jasmine-node@0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-jasmine-node/-/grunt-jasmine-node-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-legacy-log\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"grunt-legacy-log@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"lodash\": {\n          \"version\": \"2.4.2\",\n          \"from\": \"lodash@>=2.4.1 <2.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz\",\n          \"dev\": true\n        },\n        \"underscore.string\": {\n          \"version\": \"2.3.3\",\n          \"from\": \"underscore.string@>=2.3.3 <2.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-legacy-log-utils\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"grunt-legacy-log-utils@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"lodash\": {\n          \"version\": \"2.4.2\",\n          \"from\": \"lodash@>=2.4.1 <2.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz\",\n          \"dev\": true\n        },\n        \"underscore.string\": {\n          \"version\": \"2.3.3\",\n          \"from\": \"underscore.string@>=2.3.3 <2.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-legacy-util\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"grunt-legacy-util@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"async\": {\n          \"version\": \"0.1.22\",\n          \"from\": \"async@>=0.1.22 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/async/-/async-0.1.22.tgz\",\n          \"dev\": true\n        },\n        \"lodash\": {\n          \"version\": \"0.9.2\",\n          \"from\": \"lodash@>=0.9.2 <0.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-lib-contrib\": {\n      \"version\": \"0.6.1\",\n      \"from\": \"grunt-lib-contrib@>=0.6.0 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz\",\n      \"dev\": true\n    },\n    \"grunt-lib-phantomjs\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"grunt-lib-phantomjs@0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-lib-phantomjs/-/grunt-lib-phantomjs-0.3.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"semver\": {\n          \"version\": \"1.0.14\",\n          \"from\": \"semver@>=1.0.14 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/semver/-/semver-1.0.14.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"grunt-targethtml\": {\n      \"version\": \"0.2.6\",\n      \"from\": \"grunt-targethtml@0.2.6\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-targethtml/-/grunt-targethtml-0.2.6.tgz\",\n      \"dev\": true\n    },\n    \"grunt-template-jasmine-requirejs\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"grunt-template-jasmine-requirejs@0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-template-jasmine-requirejs/-/grunt-template-jasmine-requirejs-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"grunt-usemin\": {\n      \"version\": \"0.1.11\",\n      \"from\": \"grunt-usemin@0.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/grunt-usemin/-/grunt-usemin-0.1.11.tgz\",\n      \"dev\": true\n    },\n    \"har-validator\": {\n      \"version\": \"2.0.6\",\n      \"from\": \"har-validator@>=2.0.6 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz\"\n    },\n    \"has-ansi\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"has-ansi@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz\"\n    },\n    \"has-flag\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"has-flag@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"hash-base\": {\n      \"version\": \"2.0.2\",\n      \"from\": \"hash-base@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz\",\n      \"dev\": true\n    },\n    \"hash.js\": {\n      \"version\": \"1.1.3\",\n      \"from\": \"hash.js@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz\",\n      \"dev\": true\n    },\n    \"hawk\": {\n      \"version\": \"3.1.3\",\n      \"from\": \"hawk@>=3.1.3 <3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz\"\n    },\n    \"hmac-drbg\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"hmac-drbg@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"hoek\": {\n      \"version\": \"2.16.3\",\n      \"from\": \"hoek@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz\"\n    },\n    \"hooker\": {\n      \"version\": \"0.2.3\",\n      \"from\": \"hooker@>=0.2.3 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz\",\n      \"dev\": true\n    },\n    \"hosted-git-info\": {\n      \"version\": \"2.5.0\",\n      \"from\": \"hosted-git-info@>=2.1.4 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz\",\n      \"dev\": true\n    },\n    \"html-minifier\": {\n      \"version\": \"0.5.6\",\n      \"from\": \"html-minifier@>=0.5.0 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/html-minifier/-/html-minifier-0.5.6.tgz\",\n      \"dev\": true\n    },\n    \"http-errors\": {\n      \"version\": \"1.3.1\",\n      \"from\": \"http-errors@>=1.3.1 <1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz\",\n      \"dev\": true\n    },\n    \"http-signature\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"http-signature@>=1.1.0 <1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz\"\n    },\n    \"https-browserify\": {\n      \"version\": \"0.0.1\",\n      \"from\": \"https-browserify@0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz\",\n      \"dev\": true\n    },\n    \"husky\": {\n      \"version\": \"0.13.2\",\n      \"from\": \"husky@0.13.2\",\n      \"resolved\": \"https://registry.npmjs.org/husky/-/husky-0.13.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"normalize-path\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"normalize-path@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"iconv-lite\": {\n      \"version\": \"0.2.11\",\n      \"from\": \"iconv-lite@>=0.2.11 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz\",\n      \"dev\": true\n    },\n    \"ieee754\": {\n      \"version\": \"1.1.8\",\n      \"from\": \"ieee754@>=1.1.4 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz\",\n      \"dev\": true\n    },\n    \"ignore\": {\n      \"version\": \"3.3.3\",\n      \"from\": \"ignore@>=3.2.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz\",\n      \"dev\": true\n    },\n    \"image-size\": {\n      \"version\": \"0.5.5\",\n      \"from\": \"image-size@>=0.5.0 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz\",\n      \"dev\": true,\n      \"optional\": true\n    },\n    \"imurmurhash\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"imurmurhash@>=0.1.4 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"indexof\": {\n      \"version\": \"0.0.1\",\n      \"from\": \"indexof@0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz\",\n      \"dev\": true\n    },\n    \"inflight\": {\n      \"version\": \"1.0.6\",\n      \"from\": \"inflight@>=1.0.4 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz\",\n      \"dev\": true\n    },\n    \"inherits\": {\n      \"version\": \"2.0.3\",\n      \"from\": \"inherits@>=2.0.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz\"\n    },\n    \"ini\": {\n      \"version\": \"1.3.4\",\n      \"from\": \"ini@>=1.2.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ini/-/ini-1.3.4.tgz\",\n      \"dev\": true\n    },\n    \"inquirer\": {\n      \"version\": \"0.12.0\",\n      \"from\": \"inquirer@>=0.12.0 <0.13.0\",\n      \"resolved\": \"https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz\",\n      \"dev\": true\n    },\n    \"interpret\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"interpret@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"invert-kv\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"invert-kv@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-arrayish\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"is-arrayish@>=0.2.1 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz\",\n      \"dev\": true\n    },\n    \"is-binary-path\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"is-binary-path@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz\"\n    },\n    \"is-buffer\": {\n      \"version\": \"1.1.5\",\n      \"from\": \"is-buffer@>=1.1.5 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz\"\n    },\n    \"is-builtin-module\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-builtin-module@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-ci\": {\n      \"version\": \"1.0.10\",\n      \"from\": \"is-ci@>=1.0.9 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz\",\n      \"dev\": true\n    },\n    \"is-dotfile\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"is-dotfile@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz\"\n    },\n    \"is-equal-shallow\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"is-equal-shallow@>=0.1.3 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz\"\n    },\n    \"is-extendable\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"is-extendable@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz\"\n    },\n    \"is-extglob\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-extglob@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz\"\n    },\n    \"is-fullwidth-code-point\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-fullwidth-code-point@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-glob\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"is-glob@>=2.0.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz\"\n    },\n    \"is-my-json-valid\": {\n      \"version\": \"2.16.0\",\n      \"from\": \"is-my-json-valid@>=2.12.4 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz\"\n    },\n    \"is-number\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"is-number@>=2.1.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz\"\n    },\n    \"is-path-cwd\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-path-cwd@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-path-in-cwd\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-path-in-cwd@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-path-inside\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-path-inside@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-posix-bracket\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"is-posix-bracket@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz\"\n    },\n    \"is-primitive\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"is-primitive@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz\"\n    },\n    \"is-property\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"is-property@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz\"\n    },\n    \"is-resolvable\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-resolvable@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"is-typedarray\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-typedarray@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz\"\n    },\n    \"is-utf8\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"is-utf8@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz\",\n      \"dev\": true\n    },\n    \"isarray\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"isarray@1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\"\n    },\n    \"isobject\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"isobject@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz\"\n    },\n    \"isstream\": {\n      \"version\": \"0.1.2\",\n      \"from\": \"isstream@>=0.1.2 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz\"\n    },\n    \"jasmine-growl-reporter\": {\n      \"version\": \"0.0.3\",\n      \"from\": \"jasmine-growl-reporter@>=0.0.2 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-0.0.3.tgz\",\n      \"dev\": true\n    },\n    \"jasmine-node\": {\n      \"version\": \"1.11.0\",\n      \"from\": \"jasmine-node@1.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/jasmine-node/-/jasmine-node-1.11.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"gaze\": {\n          \"version\": \"0.3.4\",\n          \"from\": \"gaze@>=0.3.2 <0.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/gaze/-/gaze-0.3.4.tgz\",\n          \"dev\": true\n        },\n        \"minimatch\": {\n          \"version\": \"0.2.14\",\n          \"from\": \"minimatch@>=0.2.9 <0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz\",\n          \"dev\": true\n        },\n        \"mkdirp\": {\n          \"version\": \"0.3.5\",\n          \"from\": \"mkdirp@>=0.3.5 <0.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"jasmine-reporters\": {\n      \"version\": \"2.2.1\",\n      \"from\": \"jasmine-reporters@>=0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.2.1.tgz\",\n      \"dev\": true\n    },\n    \"js-tokens\": {\n      \"version\": \"3.0.2\",\n      \"from\": \"js-tokens@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz\",\n      \"dev\": true\n    },\n    \"js-yaml\": {\n      \"version\": \"2.0.5\",\n      \"from\": \"js-yaml@>=2.0.5 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz\",\n      \"dev\": true\n    },\n    \"jsbn\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"jsbn@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz\",\n      \"optional\": true\n    },\n    \"json-loader\": {\n      \"version\": \"0.5.7\",\n      \"from\": \"json-loader@>=0.5.4 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz\",\n      \"dev\": true\n    },\n    \"json-schema\": {\n      \"version\": \"0.2.3\",\n      \"from\": \"json-schema@0.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz\"\n    },\n    \"json-stable-stringify\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"json-stable-stringify@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"json-stringify-safe\": {\n      \"version\": \"5.0.1\",\n      \"from\": \"json-stringify-safe@>=5.0.1 <5.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz\"\n    },\n    \"json5\": {\n      \"version\": \"0.5.1\",\n      \"from\": \"json5@>=0.5.0 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/json5/-/json5-0.5.1.tgz\",\n      \"dev\": true\n    },\n    \"jsonfile\": {\n      \"version\": \"2.4.0\",\n      \"from\": \"jsonfile@>=2.1.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz\"\n    },\n    \"jsonify\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"jsonify@>=0.0.0 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz\",\n      \"dev\": true\n    },\n    \"jsonpointer\": {\n      \"version\": \"4.0.1\",\n      \"from\": \"jsonpointer@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz\"\n    },\n    \"jsprim\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"jsprim@>=1.2.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\"\n        }\n      }\n    },\n    \"junk\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"junk@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/junk/-/junk-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"kew\": {\n      \"version\": \"0.4.0\",\n      \"from\": \"kew@0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/kew/-/kew-0.4.0.tgz\",\n      \"dev\": true\n    },\n    \"keypress\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"keypress@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"kind-of\": {\n      \"version\": \"3.2.2\",\n      \"from\": \"kind-of@>=3.0.2 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz\"\n    },\n    \"lazy-cache\": {\n      \"version\": \"1.0.4\",\n      \"from\": \"lazy-cache@>=1.0.3 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz\",\n      \"dev\": true\n    },\n    \"lcid\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"lcid@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"less\": {\n      \"version\": \"2.7.2\",\n      \"from\": \"less@>=2.7.1 <2.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/less/-/less-2.7.2.tgz\",\n      \"dev\": true\n    },\n    \"levn\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"levn@>=0.3.0 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/levn/-/levn-0.3.0.tgz\",\n      \"dev\": true\n    },\n    \"livereload-js\": {\n      \"version\": \"2.2.2\",\n      \"from\": \"livereload-js@>=2.2.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz\",\n      \"dev\": true\n    },\n    \"load-grunt-tasks\": {\n      \"version\": \"3.5.0\",\n      \"from\": \"load-grunt-tasks@3.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.5.0.tgz\",\n      \"dev\": true\n    },\n    \"load-json-file\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"load-json-file@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"strip-bom\": {\n          \"version\": \"2.0.0\",\n          \"from\": \"strip-bom@>=2.0.0 <3.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"loader-runner\": {\n      \"version\": \"2.3.0\",\n      \"from\": \"loader-runner@>=2.3.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz\",\n      \"dev\": true\n    },\n    \"loader-utils\": {\n      \"version\": \"0.2.17\",\n      \"from\": \"loader-utils@>=0.2.16 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz\",\n      \"dev\": true\n    },\n    \"lodash\": {\n      \"version\": \"4.17.15\",\n      \"from\": \"lodash@4.17.15\",\n      \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz\"\n    },\n    \"longest\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"longest@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/longest/-/longest-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"lru-cache\": {\n      \"version\": \"2.7.3\",\n      \"from\": \"lru-cache@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz\",\n      \"dev\": true\n    },\n    \"media-typer\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"media-typer@0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz\",\n      \"dev\": true\n    },\n    \"memory-fs\": {\n      \"version\": \"0.4.1\",\n      \"from\": \"memory-fs@>=0.4.1 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz\",\n      \"dev\": true\n    },\n    \"micromatch\": {\n      \"version\": \"2.3.11\",\n      \"from\": \"micromatch@>=2.1.5 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz\"\n    },\n    \"miller-rabin\": {\n      \"version\": \"4.0.0\",\n      \"from\": \"miller-rabin@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz\",\n      \"dev\": true\n    },\n    \"mime\": {\n      \"version\": \"1.2.11\",\n      \"from\": \"mime@>=1.2.11 <1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime/-/mime-1.2.11.tgz\",\n      \"dev\": true,\n      \"optional\": true\n    },\n    \"mime-db\": {\n      \"version\": \"1.29.0\",\n      \"from\": \"mime-db@>=1.29.0 <1.30.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz\"\n    },\n    \"mime-types\": {\n      \"version\": \"2.1.16\",\n      \"from\": \"mime-types@>=2.1.7 <2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz\"\n    },\n    \"min-document\": {\n      \"version\": \"2.19.0\",\n      \"from\": \"min-document@>=2.19.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz\",\n      \"dev\": true\n    },\n    \"minimalistic-assert\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"minimalistic-assert@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"minimalistic-crypto-utils\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"minimalistic-crypto-utils@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"minimatch\": {\n      \"version\": \"3.0.4\",\n      \"from\": \"minimatch@>=3.0.2 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz\"\n    },\n    \"minimist\": {\n      \"version\": \"0.0.8\",\n      \"from\": \"minimist@0.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\",\n      \"dev\": true\n    },\n    \"mkdirp\": {\n      \"version\": \"0.5.1\",\n      \"from\": \"mkdirp@>=0.5.0 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n      \"dev\": true\n    },\n    \"mkpath\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"mkpath@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz\"\n    },\n    \"ms\": {\n      \"version\": \"0.7.1\",\n      \"from\": \"ms@0.7.1\",\n      \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\",\n      \"dev\": true\n    },\n    \"multimatch\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"multimatch@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz\",\n      \"dev\": true\n    },\n    \"mute-stream\": {\n      \"version\": \"0.0.5\",\n      \"from\": \"mute-stream@0.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz\",\n      \"dev\": true\n    },\n    \"nan\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"nan@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/nan/-/nan-1.0.0.tgz\"\n    },\n    \"natural-compare\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"natural-compare@>=1.4.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz\",\n      \"dev\": true\n    },\n    \"node-libs-browser\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"node-libs-browser@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.0.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"string_decoder\": {\n          \"version\": \"0.10.31\",\n          \"from\": \"string_decoder@>=0.10.25 <0.11.0\",\n          \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"nopt\": {\n      \"version\": \"3.0.6\",\n      \"from\": \"nopt@>=3.0.1 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz\"\n    },\n    \"normalize-package-data\": {\n      \"version\": \"2.4.0\",\n      \"from\": \"normalize-package-data@>=2.3.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz\",\n      \"dev\": true\n    },\n    \"normalize-path\": {\n      \"version\": \"2.1.1\",\n      \"from\": \"normalize-path@>=2.0.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz\"\n    },\n    \"npm\": {\n      \"version\": \"3.10.10\",\n      \"from\": \"npm@3.10.10\",\n      \"resolved\": \"https://registry.npmjs.org/npm/-/npm-3.10.10.tgz\",\n      \"dependencies\": {\n        \"abbrev\": {\n          \"version\": \"1.0.9\",\n          \"from\": \"abbrev@1.0.9\",\n          \"resolved\": \"https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz\"\n        },\n        \"ansi-regex\": {\n          \"version\": \"2.0.0\",\n          \"from\": \"ansi-regex@2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz\"\n        },\n        \"ansicolors\": {\n          \"version\": \"0.3.2\",\n          \"from\": \"ansicolors@>=0.3.2 <0.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz\"\n        },\n        \"ansistyles\": {\n          \"version\": \"0.1.3\",\n          \"from\": \"ansistyles@>=0.1.3 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz\"\n        },\n        \"aproba\": {\n          \"version\": \"1.0.4\",\n          \"from\": \"aproba@>=1.0.3 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/aproba/-/aproba-1.0.4.tgz\"\n        },\n        \"archy\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"archy@>=1.0.0 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/archy/-/archy-1.0.0.tgz\"\n        },\n        \"asap\": {\n          \"version\": \"2.0.5\",\n          \"from\": \"asap@2.0.5\",\n          \"resolved\": \"https://registry.npmjs.org/asap/-/asap-2.0.5.tgz\"\n        },\n        \"chownr\": {\n          \"version\": \"1.0.1\",\n          \"from\": \"chownr@>=1.0.1 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz\"\n        },\n        \"cmd-shim\": {\n          \"version\": \"2.0.2\",\n          \"from\": \"cmd-shim@2.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/cmd-shim/-/cmd-shim-2.0.2.tgz\"\n        },\n        \"columnify\": {\n          \"version\": \"1.5.4\",\n          \"from\": \"columnify@1.5.4\",\n          \"resolved\": \"https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz\",\n          \"dependencies\": {\n            \"wcwidth\": {\n              \"version\": \"1.0.0\",\n              \"from\": \"wcwidth@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.0.tgz\",\n              \"dependencies\": {\n                \"defaults\": {\n                  \"version\": \"1.0.3\",\n                  \"from\": \"defaults@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz\",\n                  \"dependencies\": {\n                    \"clone\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"clone@>=1.0.2 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/clone/-/clone-1.0.2.tgz\"\n                    }\n                  }\n                }\n              }\n            }\n          }\n        },\n        \"config-chain\": {\n          \"version\": \"1.1.11\",\n          \"from\": \"config-chain@1.1.11\",\n          \"resolved\": \"https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz\",\n          \"dependencies\": {\n            \"proto-list\": {\n              \"version\": \"1.2.4\",\n              \"from\": \"proto-list@>=1.2.1 <1.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz\"\n            }\n          }\n        },\n        \"debuglog\": {\n          \"version\": \"1.0.1\",\n          \"from\": \"debuglog@1.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz\"\n        },\n        \"dezalgo\": {\n          \"version\": \"1.0.3\",\n          \"from\": \"dezalgo@>=1.0.3 <1.1.0\"\n        },\n        \"editor\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"editor@>=1.0.0 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/editor/-/editor-1.0.0.tgz\"\n        },\n        \"fs-vacuum\": {\n          \"version\": \"1.2.9\",\n          \"from\": \"fs-vacuum@latest\",\n          \"resolved\": \"https://registry.npmjs.org/fs-vacuum/-/fs-vacuum-1.2.9.tgz\"\n        },\n        \"fs-write-stream-atomic\": {\n          \"version\": \"1.0.8\",\n          \"from\": \"fs-write-stream-atomic@1.0.8\"\n        },\n        \"fstream\": {\n          \"version\": \"1.0.10\",\n          \"from\": \"fstream@>=1.0.10 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz\"\n        },\n        \"fstream-npm\": {\n          \"version\": \"1.2.0\",\n          \"from\": \"fstream-npm@latest\",\n          \"resolved\": \"https://registry.npmjs.org/fstream-npm/-/fstream-npm-1.2.0.tgz\",\n          \"dependencies\": {\n            \"fstream-ignore\": {\n              \"version\": \"1.0.5\",\n              \"from\": \"fstream-ignore@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz\",\n              \"dependencies\": {\n                \"minimatch\": {\n                  \"version\": \"3.0.3\",\n                  \"from\": \"minimatch@>=3.0.0 <4.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz\",\n                  \"dependencies\": {\n                    \"brace-expansion\": {\n                      \"version\": \"1.1.6\",\n                      \"from\": \"brace-expansion@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz\",\n                      \"dependencies\": {\n                        \"balanced-match\": {\n                          \"version\": \"0.4.2\",\n                          \"from\": \"balanced-match@>=0.4.1 <0.5.0\",\n                          \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz\"\n                        },\n                        \"concat-map\": {\n                          \"version\": \"0.0.1\",\n                          \"from\": \"concat-map@0.0.1\",\n                          \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\"\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        },\n        \"glob\": {\n          \"version\": \"7.1.0\",\n          \"from\": \"glob@7.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/glob/-/glob-7.1.0.tgz\",\n          \"dependencies\": {\n            \"fs.realpath\": {\n              \"version\": \"1.0.0\",\n              \"from\": \"fs.realpath@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz\"\n            },\n            \"minimatch\": {\n              \"version\": \"3.0.3\",\n              \"from\": \"minimatch@>=3.0.2 <4.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz\",\n              \"dependencies\": {\n                \"brace-expansion\": {\n                  \"version\": \"1.1.6\",\n                  \"from\": \"brace-expansion@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz\",\n                  \"dependencies\": {\n                    \"balanced-match\": {\n                      \"version\": \"0.4.2\",\n                      \"from\": \"balanced-match@>=0.4.1 <0.5.0\",\n                      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz\"\n                    },\n                    \"concat-map\": {\n                      \"version\": \"0.0.1\",\n                      \"from\": \"concat-map@0.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"path-is-absolute\": {\n              \"version\": \"1.0.1\",\n              \"from\": \"path-is-absolute@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz\"\n            }\n          }\n        },\n        \"graceful-fs\": {\n          \"version\": \"4.1.9\",\n          \"from\": \"graceful-fs@4.1.9\",\n          \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz\"\n        },\n        \"has-unicode\": {\n          \"version\": \"2.0.1\",\n          \"from\": \"has-unicode@>=2.0.0 <2.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz\"\n        },\n        \"hosted-git-info\": {\n          \"version\": \"2.1.5\",\n          \"from\": \"hosted-git-info@latest\",\n          \"resolved\": \"https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz\"\n        },\n        \"iferr\": {\n          \"version\": \"0.1.5\",\n          \"from\": \"iferr@>=0.1.5 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz\"\n        },\n        \"imurmurhash\": {\n          \"version\": \"0.1.4\",\n          \"from\": \"imurmurhash@>=0.1.4 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz\"\n        },\n        \"inflight\": {\n          \"version\": \"1.0.5\",\n          \"from\": \"inflight@latest\",\n          \"resolved\": \"https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz\"\n        },\n        \"inherits\": {\n          \"version\": \"2.0.3\",\n          \"from\": \"inherits@2.0.3\",\n          \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz\"\n        },\n        \"ini\": {\n          \"version\": \"1.3.4\",\n          \"from\": \"ini@>=1.3.4 <1.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/ini/-/ini-1.3.4.tgz\"\n        },\n        \"init-package-json\": {\n          \"version\": \"1.9.4\",\n          \"from\": \"init-package-json@latest\",\n          \"resolved\": \"https://registry.npmjs.org/init-package-json/-/init-package-json-1.9.4.tgz\",\n          \"dependencies\": {\n            \"glob\": {\n              \"version\": \"6.0.4\",\n              \"from\": \"glob@>=6.0.0 <7.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/glob/-/glob-6.0.4.tgz\",\n              \"dependencies\": {\n                \"minimatch\": {\n                  \"version\": \"3.0.3\",\n                  \"from\": \"minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz\",\n                  \"dependencies\": {\n                    \"brace-expansion\": {\n                      \"version\": \"1.1.6\",\n                      \"from\": \"brace-expansion@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz\",\n                      \"dependencies\": {\n                        \"balanced-match\": {\n                          \"version\": \"0.4.2\",\n                          \"from\": \"balanced-match@>=0.4.1 <0.5.0\",\n                          \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz\"\n                        },\n                        \"concat-map\": {\n                          \"version\": \"0.0.1\",\n                          \"from\": \"concat-map@0.0.1\"\n                        }\n                      }\n                    }\n                  }\n                },\n                \"path-is-absolute\": {\n                  \"version\": \"1.0.0\",\n                  \"from\": \"path-is-absolute@>=1.0.0 <2.0.0\"\n                }\n              }\n            },\n            \"promzard\": {\n              \"version\": \"0.3.0\",\n              \"from\": \"promzard@>=0.3.0 <0.4.0\",\n              \"resolved\": \"https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz\"\n            }\n          }\n        },\n        \"lockfile\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"lockfile@1.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/lockfile/-/lockfile-1.0.2.tgz\"\n        },\n        \"lodash._baseindexof\": {\n          \"version\": \"3.1.0\",\n          \"from\": \"lodash._baseindexof@3.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz\"\n        },\n        \"lodash._baseuniq\": {\n          \"version\": \"4.6.0\",\n          \"from\": \"lodash._baseuniq@latest\",\n          \"resolved\": \"https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz\",\n          \"dependencies\": {\n            \"lodash._createset\": {\n              \"version\": \"4.0.3\",\n              \"from\": \"lodash._createset@>=4.0.0 <4.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz\"\n            },\n            \"lodash._root\": {\n              \"version\": \"3.0.1\",\n              \"from\": \"lodash._root@>=3.0.0 <3.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz\"\n            }\n          }\n        },\n        \"lodash._bindcallback\": {\n          \"version\": \"3.0.1\",\n          \"from\": \"lodash._bindcallback@3.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz\"\n        },\n        \"lodash._cacheindexof\": {\n          \"version\": \"3.0.2\",\n          \"from\": \"lodash._cacheindexof@3.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz\"\n        },\n        \"lodash._createcache\": {\n          \"version\": \"3.1.2\",\n          \"from\": \"lodash._createcache@3.1.2\",\n          \"resolved\": \"https://registry.npmjs.org/lodash._createcache/-/lodash._createcache-3.1.2.tgz\"\n        },\n        \"lodash._getnative\": {\n          \"version\": \"3.9.1\",\n          \"from\": \"lodash._getnative@3.9.1\",\n          \"resolved\": \"https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz\"\n        },\n        \"lodash.clonedeep\": {\n          \"version\": \"4.5.0\",\n          \"from\": \"lodash.clonedeep@4.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz\"\n        },\n        \"lodash.restparam\": {\n          \"version\": \"3.6.1\",\n          \"from\": \"lodash.restparam@3.6.1\",\n          \"resolved\": \"https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz\"\n        },\n        \"lodash.union\": {\n          \"version\": \"4.6.0\",\n          \"from\": \"lodash.union@4.6.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz\"\n        },\n        \"lodash.uniq\": {\n          \"version\": \"4.5.0\",\n          \"from\": \"lodash.uniq@4.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz\"\n        },\n        \"lodash.without\": {\n          \"version\": \"4.4.0\",\n          \"from\": \"lodash.without@4.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz\"\n        },\n        \"mkdirp\": {\n          \"version\": \"0.5.1\",\n          \"from\": \"mkdirp@>=0.5.1 <0.6.0\",\n          \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n          \"dependencies\": {\n            \"minimist\": {\n              \"version\": \"0.0.8\",\n              \"from\": \"minimist@0.0.8\",\n              \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\"\n            }\n          }\n        },\n        \"node-gyp\": {\n          \"version\": \"3.4.0\",\n          \"from\": \"node-gyp@latest\",\n          \"resolved\": \"https://registry.npmjs.org/node-gyp/-/node-gyp-3.4.0.tgz\",\n          \"dependencies\": {\n            \"minimatch\": {\n              \"version\": \"3.0.3\",\n              \"from\": \"minimatch@>=3.0.2 <4.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz\",\n              \"dependencies\": {\n                \"brace-expansion\": {\n                  \"version\": \"1.1.6\",\n                  \"from\": \"brace-expansion@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz\",\n                  \"dependencies\": {\n                    \"balanced-match\": {\n                      \"version\": \"0.4.2\",\n                      \"from\": \"balanced-match@>=0.4.1 <0.5.0\",\n                      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz\"\n                    },\n                    \"concat-map\": {\n                      \"version\": \"0.0.1\",\n                      \"from\": \"concat-map@0.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"npmlog\": {\n              \"version\": \"3.1.2\",\n              \"from\": \"npmlog@>=0.0.0 <1.0.0||>=1.0.0 <2.0.0||>=2.0.0 <3.0.0||>=3.0.0 <4.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz\",\n              \"dependencies\": {\n                \"are-we-there-yet\": {\n                  \"version\": \"1.1.2\",\n                  \"from\": \"are-we-there-yet@~1.1.2\",\n                  \"resolved\": \"https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz\",\n                  \"dependencies\": {\n                    \"delegates\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"delegates@^1.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz\"\n                    }\n                  }\n                },\n                \"console-control-strings\": {\n                  \"version\": \"1.1.0\",\n                  \"from\": \"console-control-strings@~1.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz\"\n                },\n                \"gauge\": {\n                  \"version\": \"2.6.0\",\n                  \"from\": \"gauge@~2.6.0\",\n                  \"resolved\": \"https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz\",\n                  \"dependencies\": {\n                    \"has-color\": {\n                      \"version\": \"0.1.7\",\n                      \"from\": \"has-color@^0.1.7\",\n                      \"resolved\": \"https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz\"\n                    },\n                    \"object-assign\": {\n                      \"version\": \"4.1.0\",\n                      \"from\": \"object-assign@^4.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz\"\n                    },\n                    \"signal-exit\": {\n                      \"version\": \"3.0.0\",\n                      \"from\": \"signal-exit@^3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz\"\n                    },\n                    \"string-width\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"string-width@^1.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz\",\n                      \"dependencies\": {\n                        \"code-point-at\": {\n                          \"version\": \"1.0.0\",\n                          \"from\": \"code-point-at@^1.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz\",\n                          \"dependencies\": {\n                            \"number-is-nan\": {\n                              \"version\": \"1.0.0\",\n                              \"from\": \"number-is-nan@^1.0.0\",\n                              \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\"\n                            }\n                          }\n                        },\n                        \"is-fullwidth-code-point\": {\n                          \"version\": \"1.0.0\",\n                          \"from\": \"is-fullwidth-code-point@^1.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz\",\n                          \"dependencies\": {\n                            \"number-is-nan\": {\n                              \"version\": \"1.0.0\",\n                              \"from\": \"number-is-nan@^1.0.0\",\n                              \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\"\n                            }\n                          }\n                        }\n                      }\n                    },\n                    \"wide-align\": {\n                      \"version\": \"1.1.0\",\n                      \"from\": \"wide-align@^1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz\"\n                    }\n                  }\n                },\n                \"set-blocking\": {\n                  \"version\": \"2.0.0\",\n                  \"from\": \"set-blocking@~2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz\"\n                }\n              }\n            },\n            \"path-array\": {\n              \"version\": \"1.0.1\",\n              \"from\": \"path-array@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz\",\n              \"dependencies\": {\n                \"array-index\": {\n                  \"version\": \"1.0.0\",\n                  \"from\": \"array-index@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz\",\n                  \"dependencies\": {\n                    \"debug\": {\n                      \"version\": \"2.2.0\",\n                      \"from\": \"debug@>=2.2.0 <3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-2.2.0.tgz\",\n                      \"dependencies\": {\n                        \"ms\": {\n                          \"version\": \"0.7.1\",\n                          \"from\": \"ms@0.7.1\",\n                          \"resolved\": \"https://registry.npmjs.org/ms/-/ms-0.7.1.tgz\"\n                        }\n                      }\n                    },\n                    \"es6-symbol\": {\n                      \"version\": \"3.1.0\",\n                      \"from\": \"es6-symbol@>=3.0.2 <4.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz\",\n                      \"dependencies\": {\n                        \"d\": {\n                          \"version\": \"0.1.1\",\n                          \"from\": \"d@>=0.1.1 <0.2.0\",\n                          \"resolved\": \"https://registry.npmjs.org/d/-/d-0.1.1.tgz\"\n                        },\n                        \"es5-ext\": {\n                          \"version\": \"0.10.12\",\n                          \"from\": \"es5-ext@>=0.10.11 <0.11.0\",\n                          \"resolved\": \"https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz\",\n                          \"dependencies\": {\n                            \"es6-iterator\": {\n                              \"version\": \"2.0.0\",\n                              \"from\": \"es6-iterator@>=2.0.0 <3.0.0\",\n                              \"resolved\": \"https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz\"\n                            }\n                          }\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        },\n        \"nopt\": {\n          \"version\": \"3.0.6\",\n          \"from\": \"nopt@>=3.0.6 <3.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz\"\n        },\n        \"normalize-git-url\": {\n          \"version\": \"3.0.2\",\n          \"from\": \"normalize-git-url@>=3.0.2 <3.1.0\"\n        },\n        \"normalize-package-data\": {\n          \"version\": \"2.3.5\",\n          \"from\": \"normalize-package-data@>=2.3.5 <2.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz\",\n          \"dependencies\": {\n            \"is-builtin-module\": {\n              \"version\": \"1.0.0\",\n              \"from\": \"is-builtin-module@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz\",\n              \"dependencies\": {\n                \"builtin-modules\": {\n                  \"version\": \"1.1.1\",\n                  \"from\": \"builtin-modules@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"npm-cache-filename\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"npm-cache-filename@>=1.0.2 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz\"\n        },\n        \"npm-install-checks\": {\n          \"version\": \"3.0.0\",\n          \"from\": \"npm-install-checks@3.0.0\"\n        },\n        \"npm-package-arg\": {\n          \"version\": \"4.2.0\",\n          \"from\": \"npm-package-arg@4.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-4.2.0.tgz\"\n        },\n        \"npm-registry-client\": {\n          \"version\": \"7.2.1\",\n          \"from\": \"npm-registry-client@7.2.1\",\n          \"resolved\": \"https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.2.1.tgz\",\n          \"dependencies\": {\n            \"concat-stream\": {\n              \"version\": \"1.5.2\",\n              \"from\": \"concat-stream@>=1.5.2 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz\",\n              \"dependencies\": {\n                \"readable-stream\": {\n                  \"version\": \"2.0.6\",\n                  \"from\": \"readable-stream@>=2.0.0 <2.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz\",\n                  \"dependencies\": {\n                    \"core-util-is\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"core-util-is@>=1.0.0 <1.1.0\"\n                    },\n                    \"isarray\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"isarray@>=1.0.0 <1.1.0\"\n                    },\n                    \"process-nextick-args\": {\n                      \"version\": \"1.0.7\",\n                      \"from\": \"process-nextick-args@>=1.0.6 <1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz\"\n                    },\n                    \"string_decoder\": {\n                      \"version\": \"0.10.31\",\n                      \"from\": \"string_decoder@>=0.10.0 <0.11.0\"\n                    },\n                    \"util-deprecate\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"util-deprecate@>=1.0.1 <1.1.0\"\n                    }\n                  }\n                },\n                \"typedarray\": {\n                  \"version\": \"0.0.6\",\n                  \"from\": \"typedarray@>=0.0.5 <0.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz\"\n                }\n              }\n            },\n            \"npmlog\": {\n              \"version\": \"3.1.2\",\n              \"from\": \"npmlog@>=2.0.0 <2.1.0||>=3.1.0 <3.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz\",\n              \"optional\": true,\n              \"dependencies\": {\n                \"are-we-there-yet\": {\n                  \"version\": \"1.1.2\",\n                  \"from\": \"are-we-there-yet@~1.1.2\",\n                  \"resolved\": \"https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz\",\n                  \"optional\": true,\n                  \"dependencies\": {\n                    \"delegates\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"delegates@^1.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz\",\n                      \"optional\": true\n                    }\n                  }\n                },\n                \"console-control-strings\": {\n                  \"version\": \"1.1.0\",\n                  \"from\": \"console-control-strings@~1.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz\"\n                },\n                \"gauge\": {\n                  \"version\": \"2.6.0\",\n                  \"from\": \"gauge@~2.6.0\",\n                  \"resolved\": \"https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz\",\n                  \"optional\": true,\n                  \"dependencies\": {\n                    \"has-color\": {\n                      \"version\": \"0.1.7\",\n                      \"from\": \"has-color@^0.1.7\",\n                      \"resolved\": \"https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz\",\n                      \"optional\": true\n                    },\n                    \"object-assign\": {\n                      \"version\": \"4.1.0\",\n                      \"from\": \"object-assign@^4.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz\",\n                      \"optional\": true\n                    },\n                    \"signal-exit\": {\n                      \"version\": \"3.0.0\",\n                      \"from\": \"signal-exit@^3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz\",\n                      \"optional\": true\n                    },\n                    \"string-width\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"string-width@^1.0.1\",\n                      \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz\",\n                      \"dependencies\": {\n                        \"code-point-at\": {\n                          \"version\": \"1.0.0\",\n                          \"from\": \"code-point-at@^1.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz\",\n                          \"dependencies\": {\n                            \"number-is-nan\": {\n                              \"version\": \"1.0.0\",\n                              \"from\": \"number-is-nan@^1.0.0\",\n                              \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\"\n                            }\n                          }\n                        },\n                        \"is-fullwidth-code-point\": {\n                          \"version\": \"1.0.0\",\n                          \"from\": \"is-fullwidth-code-point@^1.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz\",\n                          \"dependencies\": {\n                            \"number-is-nan\": {\n                              \"version\": \"1.0.0\",\n                              \"from\": \"number-is-nan@^1.0.0\",\n                              \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\"\n                            }\n                          }\n                        }\n                      }\n                    },\n                    \"wide-align\": {\n                      \"version\": \"1.1.0\",\n                      \"from\": \"wide-align@^1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz\",\n                      \"optional\": true\n                    }\n                  }\n                },\n                \"set-blocking\": {\n                  \"version\": \"2.0.0\",\n                  \"from\": \"set-blocking@~2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz\",\n                  \"optional\": true\n                }\n              }\n            },\n            \"retry\": {\n              \"version\": \"0.10.0\",\n              \"from\": \"retry@>=0.10.0 <0.11.0\",\n              \"resolved\": \"https://registry.npmjs.org/retry/-/retry-0.10.0.tgz\"\n            }\n          }\n        },\n        \"npm-user-validate\": {\n          \"version\": \"0.1.5\",\n          \"from\": \"npm-user-validate@0.1.5\",\n          \"resolved\": \"https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.5.tgz\"\n        },\n        \"npmlog\": {\n          \"version\": \"4.0.0\",\n          \"from\": \"npmlog@4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/npmlog/-/npmlog-4.0.0.tgz\",\n          \"dependencies\": {\n            \"are-we-there-yet\": {\n              \"version\": \"1.1.2\",\n              \"from\": \"are-we-there-yet@>=1.1.2 <1.2.0\",\n              \"resolved\": \"http://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz\",\n              \"dependencies\": {\n                \"delegates\": {\n                  \"version\": \"1.0.0\",\n                  \"from\": \"delegates@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz\"\n                }\n              }\n            },\n            \"console-control-strings\": {\n              \"version\": \"1.1.0\",\n              \"from\": \"console-control-strings@>=1.1.0 <1.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz\"\n            },\n            \"gauge\": {\n              \"version\": \"2.6.0\",\n              \"from\": \"gauge@>=2.6.0 <2.7.0\",\n              \"resolved\": \"https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz\",\n              \"dependencies\": {\n                \"has-color\": {\n                  \"version\": \"0.1.7\",\n                  \"from\": \"has-color@>=0.1.7 <0.2.0\",\n                  \"resolved\": \"https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz\"\n                },\n                \"object-assign\": {\n                  \"version\": \"4.1.0\",\n                  \"from\": \"object-assign@>=4.0.1 <5.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz\"\n                },\n                \"signal-exit\": {\n                  \"version\": \"3.0.0\",\n                  \"from\": \"signal-exit@>=3.0.0 <4.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz\"\n                },\n                \"string-width\": {\n                  \"version\": \"1.0.2\",\n                  \"from\": \"string-width@>=1.0.1 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz\",\n                  \"dependencies\": {\n                    \"code-point-at\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"code-point-at@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz\",\n                      \"dependencies\": {\n                        \"number-is-nan\": {\n                          \"version\": \"1.0.0\",\n                          \"from\": \"number-is-nan@>=1.0.0 <2.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\"\n                        }\n                      }\n                    },\n                    \"is-fullwidth-code-point\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"is-fullwidth-code-point@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz\",\n                      \"dependencies\": {\n                        \"number-is-nan\": {\n                          \"version\": \"1.0.0\",\n                          \"from\": \"number-is-nan@^1.0.0\",\n                          \"resolved\": \"http://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz\"\n                        }\n                      }\n                    }\n                  }\n                },\n                \"wide-align\": {\n                  \"version\": \"1.1.0\",\n                  \"from\": \"wide-align@>=1.1.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz\"\n                }\n              }\n            },\n            \"set-blocking\": {\n              \"version\": \"2.0.0\",\n              \"from\": \"set-blocking@>=2.0.0 <2.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz\"\n            }\n          }\n        },\n        \"once\": {\n          \"version\": \"1.4.0\",\n          \"from\": \"once@1.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/once/-/once-1.4.0.tgz\"\n        },\n        \"opener\": {\n          \"version\": \"1.4.2\",\n          \"from\": \"opener@1.4.2\",\n          \"resolved\": \"https://registry.npmjs.org/opener/-/opener-1.4.2.tgz\"\n        },\n        \"osenv\": {\n          \"version\": \"0.1.3\",\n          \"from\": \"osenv@>=0.1.3 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/osenv/-/osenv-0.1.3.tgz\",\n          \"dependencies\": {\n            \"os-homedir\": {\n              \"version\": \"1.0.1\",\n              \"from\": \"os-homedir@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz\"\n            },\n            \"os-tmpdir\": {\n              \"version\": \"1.0.1\",\n              \"from\": \"os-tmpdir@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz\"\n            }\n          }\n        },\n        \"path-is-inside\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"path-is-inside@1.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz\"\n        },\n        \"read\": {\n          \"version\": \"1.0.7\",\n          \"from\": \"read@>=1.0.7 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/read/-/read-1.0.7.tgz\",\n          \"dependencies\": {\n            \"mute-stream\": {\n              \"version\": \"0.0.5\",\n              \"from\": \"mute-stream@>=0.0.4 <0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz\"\n            }\n          }\n        },\n        \"read-cmd-shim\": {\n          \"version\": \"1.0.1\",\n          \"from\": \"read-cmd-shim@>=1.0.1 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz\"\n        },\n        \"read-installed\": {\n          \"version\": \"4.0.3\",\n          \"from\": \"read-installed@>=4.0.3 <4.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz\",\n          \"dependencies\": {\n            \"util-extend\": {\n              \"version\": \"1.0.3\",\n              \"from\": \"util-extend@>=1.0.1 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz\"\n            }\n          }\n        },\n        \"read-package-json\": {\n          \"version\": \"2.0.4\",\n          \"from\": \"read-package-json@>=2.0.3 <2.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.4.tgz\",\n          \"dependencies\": {\n            \"glob\": {\n              \"version\": \"6.0.4\",\n              \"from\": \"glob@>=6.0.0 <7.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/glob/-/glob-6.0.4.tgz\",\n              \"dependencies\": {\n                \"minimatch\": {\n                  \"version\": \"3.0.3\",\n                  \"from\": \"minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz\",\n                  \"dependencies\": {\n                    \"brace-expansion\": {\n                      \"version\": \"1.1.6\",\n                      \"from\": \"brace-expansion@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz\",\n                      \"dependencies\": {\n                        \"balanced-match\": {\n                          \"version\": \"0.4.2\",\n                          \"from\": \"balanced-match@>=0.4.1 <0.5.0\",\n                          \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz\"\n                        },\n                        \"concat-map\": {\n                          \"version\": \"0.0.1\",\n                          \"from\": \"concat-map@0.0.1\"\n                        }\n                      }\n                    }\n                  }\n                },\n                \"path-is-absolute\": {\n                  \"version\": \"1.0.0\",\n                  \"from\": \"path-is-absolute@>=1.0.0 <2.0.0\"\n                }\n              }\n            },\n            \"json-parse-helpfulerror\": {\n              \"version\": \"1.0.3\",\n              \"from\": \"json-parse-helpfulerror@>=1.0.2 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz\",\n              \"dependencies\": {\n                \"jju\": {\n                  \"version\": \"1.3.0\",\n                  \"from\": \"jju@>=1.1.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/jju/-/jju-1.3.0.tgz\"\n                }\n              }\n            }\n          }\n        },\n        \"read-package-tree\": {\n          \"version\": \"5.1.5\",\n          \"from\": \"read-package-tree@>=5.1.4 <5.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.1.5.tgz\"\n        },\n        \"readable-stream\": {\n          \"version\": \"2.1.5\",\n          \"from\": \"readable-stream@2.1.5\",\n          \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz\",\n          \"dependencies\": {\n            \"buffer-shims\": {\n              \"version\": \"1.0.0\",\n              \"from\": \"buffer-shims@>=1.0.0 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz\"\n            },\n            \"core-util-is\": {\n              \"version\": \"1.0.2\",\n              \"from\": \"core-util-is@>=1.0.0 <1.1.0\"\n            },\n            \"isarray\": {\n              \"version\": \"1.0.0\",\n              \"from\": \"isarray@>=1.0.0 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\"\n            },\n            \"process-nextick-args\": {\n              \"version\": \"1.0.7\",\n              \"from\": \"process-nextick-args@>=1.0.6 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz\"\n            },\n            \"string_decoder\": {\n              \"version\": \"0.10.31\",\n              \"from\": \"string_decoder@>=0.10.0 <0.11.0\"\n            },\n            \"util-deprecate\": {\n              \"version\": \"1.0.2\",\n              \"from\": \"util-deprecate@>=1.0.1 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\"\n            }\n          }\n        },\n        \"readdir-scoped-modules\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"readdir-scoped-modules@1.0.2\",\n          \"resolved\": \"https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz\"\n        },\n        \"realize-package-specifier\": {\n          \"version\": \"3.0.3\",\n          \"from\": \"realize-package-specifier@>=3.0.2 <3.1.0\"\n        },\n        \"request\": {\n          \"version\": \"2.75.0\",\n          \"from\": \"request@2.75.0\",\n          \"resolved\": \"https://registry.npmjs.org/request/-/request-2.75.0.tgz\",\n          \"dependencies\": {\n            \"aws-sign2\": {\n              \"version\": \"0.6.0\",\n              \"from\": \"aws-sign2@>=0.6.0 <0.7.0\",\n              \"resolved\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz\"\n            },\n            \"aws4\": {\n              \"version\": \"1.4.1\",\n              \"from\": \"aws4@>=1.2.1 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz\"\n            },\n            \"bl\": {\n              \"version\": \"1.1.2\",\n              \"from\": \"bl@>=1.1.2 <1.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/bl/-/bl-1.1.2.tgz\",\n              \"dependencies\": {\n                \"readable-stream\": {\n                  \"version\": \"2.0.6\",\n                  \"from\": \"readable-stream@>=2.0.5 <2.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz\",\n                  \"dependencies\": {\n                    \"core-util-is\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"core-util-is@>=1.0.0 <1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\"\n                    },\n                    \"isarray\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"isarray@>=1.0.0 <1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\"\n                    },\n                    \"process-nextick-args\": {\n                      \"version\": \"1.0.7\",\n                      \"from\": \"process-nextick-args@>=1.0.6 <1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz\"\n                    },\n                    \"string_decoder\": {\n                      \"version\": \"0.10.31\",\n                      \"from\": \"string_decoder@>=0.10.0 <0.11.0\",\n                      \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n                    },\n                    \"util-deprecate\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"util-deprecate@>=1.0.1 <1.1.0\",\n                      \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"caseless\": {\n              \"version\": \"0.11.0\",\n              \"from\": \"caseless@>=0.11.0 <0.12.0\",\n              \"resolved\": \"https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz\"\n            },\n            \"combined-stream\": {\n              \"version\": \"1.0.5\",\n              \"from\": \"combined-stream@>=1.0.5 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz\",\n              \"dependencies\": {\n                \"delayed-stream\": {\n                  \"version\": \"1.0.0\",\n                  \"from\": \"delayed-stream@>=1.0.0 <1.1.0\",\n                  \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\"\n                }\n              }\n            },\n            \"extend\": {\n              \"version\": \"3.0.0\",\n              \"from\": \"extend@>=3.0.0 <3.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/extend/-/extend-3.0.0.tgz\"\n            },\n            \"forever-agent\": {\n              \"version\": \"0.6.1\",\n              \"from\": \"forever-agent@>=0.6.1 <0.7.0\",\n              \"resolved\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz\"\n            },\n            \"form-data\": {\n              \"version\": \"2.0.0\",\n              \"from\": \"form-data@>=2.0.0 <2.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz\",\n              \"dependencies\": {\n                \"asynckit\": {\n                  \"version\": \"0.4.0\",\n                  \"from\": \"asynckit@>=0.4.0 <0.5.0\",\n                  \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\"\n                }\n              }\n            },\n            \"har-validator\": {\n              \"version\": \"2.0.6\",\n              \"from\": \"har-validator@>=2.0.6 <2.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz\",\n              \"dependencies\": {\n                \"chalk\": {\n                  \"version\": \"1.1.3\",\n                  \"from\": \"chalk@>=1.1.1 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz\",\n                  \"dependencies\": {\n                    \"ansi-styles\": {\n                      \"version\": \"2.2.1\",\n                      \"from\": \"ansi-styles@>=2.2.1 <3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz\"\n                    },\n                    \"escape-string-regexp\": {\n                      \"version\": \"1.0.5\",\n                      \"from\": \"escape-string-regexp@>=1.0.2 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\"\n                    },\n                    \"has-ansi\": {\n                      \"version\": \"2.0.0\",\n                      \"from\": \"has-ansi@>=2.0.0 <3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz\"\n                    },\n                    \"supports-color\": {\n                      \"version\": \"2.0.0\",\n                      \"from\": \"supports-color@>=2.0.0 <3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz\"\n                    }\n                  }\n                },\n                \"commander\": {\n                  \"version\": \"2.9.0\",\n                  \"from\": \"commander@>=2.9.0 <3.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/commander/-/commander-2.9.0.tgz\",\n                  \"dependencies\": {\n                    \"graceful-readlink\": {\n                      \"version\": \"1.0.1\",\n                      \"from\": \"graceful-readlink@>=1.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz\"\n                    }\n                  }\n                },\n                \"is-my-json-valid\": {\n                  \"version\": \"2.15.0\",\n                  \"from\": \"is-my-json-valid@>=2.12.4 <3.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz\",\n                  \"dependencies\": {\n                    \"generate-function\": {\n                      \"version\": \"2.0.0\",\n                      \"from\": \"generate-function@>=2.0.0 <3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz\"\n                    },\n                    \"generate-object-property\": {\n                      \"version\": \"1.2.0\",\n                      \"from\": \"generate-object-property@>=1.1.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz\",\n                      \"dependencies\": {\n                        \"is-property\": {\n                          \"version\": \"1.0.2\",\n                          \"from\": \"is-property@>=1.0.0 <2.0.0\",\n                          \"resolved\": \"https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz\"\n                        }\n                      }\n                    },\n                    \"jsonpointer\": {\n                      \"version\": \"4.0.0\",\n                      \"from\": \"jsonpointer@>=4.0.0 <5.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz\"\n                    },\n                    \"xtend\": {\n                      \"version\": \"4.0.1\",\n                      \"from\": \"xtend@>=4.0.0 <5.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz\"\n                    }\n                  }\n                },\n                \"pinkie-promise\": {\n                  \"version\": \"2.0.1\",\n                  \"from\": \"pinkie-promise@>=2.0.0 <3.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz\",\n                  \"dependencies\": {\n                    \"pinkie\": {\n                      \"version\": \"2.0.4\",\n                      \"from\": \"pinkie@>=2.0.0 <3.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz\"\n                    }\n                  }\n                }\n              }\n            },\n            \"hawk\": {\n              \"version\": \"3.1.3\",\n              \"from\": \"hawk@>=3.1.3 <3.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz\",\n              \"dependencies\": {\n                \"boom\": {\n                  \"version\": \"2.10.1\",\n                  \"from\": \"boom@>=2.0.0 <3.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/boom/-/boom-2.10.1.tgz\"\n                },\n                \"cryptiles\": {\n                  \"version\": \"2.0.5\",\n                  \"from\": \"cryptiles@>=2.0.0 <3.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz\"\n                },\n                \"hoek\": {\n                  \"version\": \"2.16.3\",\n                  \"from\": \"hoek@>=2.0.0 <3.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz\"\n                },\n                \"sntp\": {\n                  \"version\": \"1.0.9\",\n                  \"from\": \"sntp@>=1.0.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz\"\n                }\n              }\n            },\n            \"http-signature\": {\n              \"version\": \"1.1.1\",\n              \"from\": \"http-signature@>=1.1.0 <1.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz\",\n              \"dependencies\": {\n                \"assert-plus\": {\n                  \"version\": \"0.2.0\",\n                  \"from\": \"assert-plus@>=0.2.0 <0.3.0\",\n                  \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz\"\n                },\n                \"jsprim\": {\n                  \"version\": \"1.3.1\",\n                  \"from\": \"jsprim@>=1.2.2 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz\",\n                  \"dependencies\": {\n                    \"extsprintf\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"extsprintf@1.0.2\",\n                      \"resolved\": \"https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz\"\n                    },\n                    \"json-schema\": {\n                      \"version\": \"0.2.3\",\n                      \"from\": \"json-schema@0.2.3\",\n                      \"resolved\": \"https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz\"\n                    },\n                    \"verror\": {\n                      \"version\": \"1.3.6\",\n                      \"from\": \"verror@1.3.6\",\n                      \"resolved\": \"https://registry.npmjs.org/verror/-/verror-1.3.6.tgz\"\n                    }\n                  }\n                },\n                \"sshpk\": {\n                  \"version\": \"1.10.1\",\n                  \"from\": \"sshpk@>=1.7.0 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz\",\n                  \"dependencies\": {\n                    \"asn1\": {\n                      \"version\": \"0.2.3\",\n                      \"from\": \"asn1@>=0.2.3 <0.3.0\",\n                      \"resolved\": \"https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz\"\n                    },\n                    \"assert-plus\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\"\n                    },\n                    \"bcrypt-pbkdf\": {\n                      \"version\": \"1.0.0\",\n                      \"from\": \"bcrypt-pbkdf@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz\",\n                      \"optional\": true\n                    },\n                    \"dashdash\": {\n                      \"version\": \"1.14.0\",\n                      \"from\": \"dashdash@>=1.12.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz\"\n                    },\n                    \"ecc-jsbn\": {\n                      \"version\": \"0.1.1\",\n                      \"from\": \"ecc-jsbn@>=0.1.1 <0.2.0\",\n                      \"resolved\": \"https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz\",\n                      \"optional\": true\n                    },\n                    \"getpass\": {\n                      \"version\": \"0.1.6\",\n                      \"from\": \"getpass@>=0.1.1 <0.2.0\",\n                      \"resolved\": \"https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz\"\n                    },\n                    \"jodid25519\": {\n                      \"version\": \"1.0.2\",\n                      \"from\": \"jodid25519@>=1.0.0 <2.0.0\",\n                      \"resolved\": \"https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz\",\n                      \"optional\": true\n                    },\n                    \"jsbn\": {\n                      \"version\": \"0.1.0\",\n                      \"from\": \"jsbn@>=0.1.0 <0.2.0\",\n                      \"resolved\": \"https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz\",\n                      \"optional\": true\n                    },\n                    \"tweetnacl\": {\n                      \"version\": \"0.14.3\",\n                      \"from\": \"tweetnacl@>=0.14.0 <0.15.0\",\n                      \"resolved\": \"https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz\",\n                      \"optional\": true\n                    }\n                  }\n                }\n              }\n            },\n            \"is-typedarray\": {\n              \"version\": \"1.0.0\",\n              \"from\": \"is-typedarray@>=1.0.0 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz\"\n            },\n            \"isstream\": {\n              \"version\": \"0.1.2\",\n              \"from\": \"isstream@>=0.1.2 <0.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz\"\n            },\n            \"json-stringify-safe\": {\n              \"version\": \"5.0.1\",\n              \"from\": \"json-stringify-safe@>=5.0.1 <5.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz\"\n            },\n            \"mime-types\": {\n              \"version\": \"2.1.12\",\n              \"from\": \"mime-types@>=2.1.7 <2.2.0\",\n              \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz\",\n              \"dependencies\": {\n                \"mime-db\": {\n                  \"version\": \"1.24.0\",\n                  \"from\": \"mime-db@>=1.24.0 <1.25.0\",\n                  \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz\"\n                }\n              }\n            },\n            \"node-uuid\": {\n              \"version\": \"1.4.7\",\n              \"from\": \"node-uuid@>=1.4.7 <1.5.0\",\n              \"resolved\": \"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz\"\n            },\n            \"oauth-sign\": {\n              \"version\": \"0.8.2\",\n              \"from\": \"oauth-sign@>=0.8.1 <0.9.0\",\n              \"resolved\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz\"\n            },\n            \"qs\": {\n              \"version\": \"6.2.1\",\n              \"from\": \"qs@>=6.2.0 <6.3.0\",\n              \"resolved\": \"https://registry.npmjs.org/qs/-/qs-6.2.1.tgz\"\n            },\n            \"stringstream\": {\n              \"version\": \"0.0.5\",\n              \"from\": \"stringstream@>=0.0.4 <0.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz\"\n            },\n            \"tough-cookie\": {\n              \"version\": \"2.3.1\",\n              \"from\": \"tough-cookie@>=2.3.0 <2.4.0\",\n              \"resolved\": \"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.1.tgz\"\n            },\n            \"tunnel-agent\": {\n              \"version\": \"0.4.3\",\n              \"from\": \"tunnel-agent@>=0.4.1 <0.5.0\",\n              \"resolved\": \"https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz\"\n            }\n          }\n        },\n        \"retry\": {\n          \"version\": \"0.10.0\",\n          \"from\": \"retry@0.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/retry/-/retry-0.10.0.tgz\"\n        },\n        \"rimraf\": {\n          \"version\": \"2.5.4\",\n          \"from\": \"rimraf@2.5.4\",\n          \"resolved\": \"https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz\"\n        },\n        \"semver\": {\n          \"version\": \"5.3.0\",\n          \"from\": \"semver@5.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/semver/-/semver-5.3.0.tgz\"\n        },\n        \"sha\": {\n          \"version\": \"2.0.1\",\n          \"from\": \"sha@>=2.0.1 <2.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/sha/-/sha-2.0.1.tgz\"\n        },\n        \"slide\": {\n          \"version\": \"1.1.6\",\n          \"from\": \"slide@>=1.1.6 <1.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/slide/-/slide-1.1.6.tgz\"\n        },\n        \"sorted-object\": {\n          \"version\": \"2.0.1\",\n          \"from\": \"sorted-object@2.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/sorted-object/-/sorted-object-2.0.1.tgz\"\n        },\n        \"strip-ansi\": {\n          \"version\": \"3.0.1\",\n          \"from\": \"strip-ansi@*\",\n          \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz\"\n        },\n        \"tar\": {\n          \"version\": \"2.2.1\",\n          \"from\": \"tar@>=2.2.1 <2.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/tar/-/tar-2.2.1.tgz\",\n          \"dependencies\": {\n            \"block-stream\": {\n              \"version\": \"0.0.8\",\n              \"from\": \"block-stream@*\",\n              \"resolved\": \"https://registry.npmjs.org/block-stream/-/block-stream-0.0.8.tgz\"\n            }\n          }\n        },\n        \"text-table\": {\n          \"version\": \"0.2.0\",\n          \"from\": \"text-table@>=0.2.0 <0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz\"\n        },\n        \"uid-number\": {\n          \"version\": \"0.0.6\",\n          \"from\": \"uid-number@0.0.6\",\n          \"resolved\": \"https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz\"\n        },\n        \"umask\": {\n          \"version\": \"1.1.0\",\n          \"from\": \"umask@>=1.1.0 <1.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/umask/-/umask-1.1.0.tgz\"\n        },\n        \"unique-filename\": {\n          \"version\": \"1.1.0\",\n          \"from\": \"unique-filename@>=1.1.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz\",\n          \"dependencies\": {\n            \"unique-slug\": {\n              \"version\": \"2.0.0\",\n              \"from\": \"unique-slug@>=2.0.0 <3.0.0\"\n            }\n          }\n        },\n        \"unpipe\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"unpipe@>=1.0.0 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\"\n        },\n        \"validate-npm-package-license\": {\n          \"version\": \"3.0.1\",\n          \"from\": \"validate-npm-package-license@3.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz\",\n          \"dependencies\": {\n            \"spdx-correct\": {\n              \"version\": \"1.0.2\",\n              \"from\": \"spdx-correct@>=1.0.0 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz\",\n              \"dependencies\": {\n                \"spdx-license-ids\": {\n                  \"version\": \"1.2.0\",\n                  \"from\": \"spdx-license-ids@>=1.0.2 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.0.tgz\"\n                }\n              }\n            },\n            \"spdx-expression-parse\": {\n              \"version\": \"1.0.2\",\n              \"from\": \"spdx-expression-parse@>=1.0.0 <1.1.0\",\n              \"resolved\": \"https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz\",\n              \"dependencies\": {\n                \"spdx-exceptions\": {\n                  \"version\": \"1.0.4\",\n                  \"from\": \"spdx-exceptions@>=1.0.4 <2.0.0\",\n                  \"resolved\": \"https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz\"\n                },\n                \"spdx-license-ids\": {\n                  \"version\": \"1.2.0\",\n                  \"from\": \"spdx-license-ids@>=1.0.0 <2.0.0\"\n                }\n              }\n            }\n          }\n        },\n        \"validate-npm-package-name\": {\n          \"version\": \"2.2.2\",\n          \"from\": \"validate-npm-package-name@>=2.2.2 <2.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-2.2.2.tgz\",\n          \"dependencies\": {\n            \"builtins\": {\n              \"version\": \"0.0.7\",\n              \"from\": \"builtins@0.0.7\",\n              \"resolved\": \"https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz\"\n            }\n          }\n        },\n        \"which\": {\n          \"version\": \"1.2.11\",\n          \"from\": \"which@1.2.11\",\n          \"resolved\": \"https://registry.npmjs.org/which/-/which-1.2.11.tgz\",\n          \"dependencies\": {\n            \"isexe\": {\n              \"version\": \"1.1.2\",\n              \"from\": \"isexe@>=1.1.1 <2.0.0\",\n              \"resolved\": \"https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz\"\n            }\n          }\n        },\n        \"wrappy\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"wrappy@latest\",\n          \"resolved\": \"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz\"\n        },\n        \"write-file-atomic\": {\n          \"version\": \"1.2.0\",\n          \"from\": \"write-file-atomic@1.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.2.0.tgz\"\n        }\n      }\n    },\n    \"npmconf\": {\n      \"version\": \"2.1.1\",\n      \"from\": \"npmconf@2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/npmconf/-/npmconf-2.1.1.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"once\": {\n          \"version\": \"1.3.3\",\n          \"from\": \"once@>=1.3.0 <1.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/once/-/once-1.3.3.tgz\",\n          \"dev\": true\n        },\n        \"semver\": {\n          \"version\": \"4.3.6\",\n          \"from\": \"semver@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0||>=4.0.0 <5.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/semver/-/semver-4.3.6.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"number-is-nan\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"number-is-nan@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"oauth-sign\": {\n      \"version\": \"0.8.2\",\n      \"from\": \"oauth-sign@>=0.8.1 <0.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz\"\n    },\n    \"object-assign\": {\n      \"version\": \"4.1.1\",\n      \"from\": \"object-assign@>=4.0.1 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz\"\n    },\n    \"object.omit\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"object.omit@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz\"\n    },\n    \"on-finished\": {\n      \"version\": \"2.3.0\",\n      \"from\": \"on-finished@>=2.3.0 <2.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz\",\n      \"dev\": true\n    },\n    \"once\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"once@>=1.3.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/once/-/once-1.4.0.tgz\",\n      \"dev\": true\n    },\n    \"onetime\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"onetime@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz\",\n      \"dev\": true\n    },\n    \"opn\": {\n      \"version\": \"4.0.2\",\n      \"from\": \"opn@4.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/opn/-/opn-4.0.2.tgz\"\n    },\n    \"optimist\": {\n      \"version\": \"0.3.7\",\n      \"from\": \"optimist@>=0.3.5 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz\",\n      \"dev\": true\n    },\n    \"optionator\": {\n      \"version\": \"0.8.2\",\n      \"from\": \"optionator@>=0.8.2 <0.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"wordwrap\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"wordwrap@>=1.0.0 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"options\": {\n      \"version\": \"0.0.6\",\n      \"from\": \"options@>=0.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/options/-/options-0.0.6.tgz\"\n    },\n    \"os-browserify\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"os-browserify@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz\",\n      \"dev\": true\n    },\n    \"os-homedir\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"os-homedir@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"os-locale\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"os-locale@>=1.4.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz\",\n      \"dev\": true\n    },\n    \"os-tmpdir\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"os-tmpdir@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz\"\n    },\n    \"osenv\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"osenv@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"package\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"package@>=1.0.0 <1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/package/-/package-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"pako\": {\n      \"version\": \"0.2.9\",\n      \"from\": \"pako@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/pako/-/pako-0.2.9.tgz\",\n      \"dev\": true\n    },\n    \"parse-asn1\": {\n      \"version\": \"5.1.0\",\n      \"from\": \"parse-asn1@>=5.0.0 <6.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz\",\n      \"dev\": true\n    },\n    \"parse-glob\": {\n      \"version\": \"3.0.4\",\n      \"from\": \"parse-glob@>=3.0.4 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz\"\n    },\n    \"parse-json\": {\n      \"version\": \"2.2.0\",\n      \"from\": \"parse-json@>=2.2.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz\",\n      \"dev\": true\n    },\n    \"parseurl\": {\n      \"version\": \"1.3.1\",\n      \"from\": \"parseurl@>=1.3.0 <1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz\",\n      \"dev\": true\n    },\n    \"path-browserify\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"path-browserify@0.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz\",\n      \"dev\": true\n    },\n    \"path-exists\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"path-exists@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz\",\n      \"dev\": true\n    },\n    \"path-is-absolute\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"path-is-absolute@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz\"\n    },\n    \"path-is-inside\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"path-is-inside@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"path-parse\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"path-parse@>=1.0.5 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz\",\n      \"dev\": true\n    },\n    \"path-type\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"path-type@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz\",\n      \"dev\": true\n    },\n    \"pbkdf2\": {\n      \"version\": \"3.0.12\",\n      \"from\": \"pbkdf2@>=3.0.3 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz\",\n      \"dev\": true\n    },\n    \"phantomjs\": {\n      \"version\": \"1.9.18\",\n      \"from\": \"phantomjs@1.9.18\",\n      \"resolved\": \"https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.18.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"asn1\": {\n          \"version\": \"0.1.11\",\n          \"from\": \"asn1@0.1.11\",\n          \"resolved\": \"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"assert-plus\": {\n          \"version\": \"0.1.5\",\n          \"from\": \"assert-plus@>=0.1.5 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"async\": {\n          \"version\": \"0.9.2\",\n          \"from\": \"async@>=0.9.0 <0.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/async/-/async-0.9.2.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"aws-sign2\": {\n          \"version\": \"0.5.0\",\n          \"from\": \"aws-sign2@>=0.5.0 <0.6.0\",\n          \"resolved\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"boom\": {\n          \"version\": \"0.4.2\",\n          \"from\": \"boom@>=0.4.0 <0.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/boom/-/boom-0.4.2.tgz\",\n          \"dev\": true\n        },\n        \"caseless\": {\n          \"version\": \"0.6.0\",\n          \"from\": \"caseless@>=0.6.0 <0.7.0\",\n          \"resolved\": \"https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz\",\n          \"dev\": true\n        },\n        \"combined-stream\": {\n          \"version\": \"0.0.7\",\n          \"from\": \"combined-stream@>=0.0.4 <0.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"cryptiles\": {\n          \"version\": \"0.2.2\",\n          \"from\": \"cryptiles@>=0.2.0 <0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"delayed-stream\": {\n          \"version\": \"0.0.5\",\n          \"from\": \"delayed-stream@0.0.5\",\n          \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"forever-agent\": {\n          \"version\": \"0.5.2\",\n          \"from\": \"forever-agent@>=0.5.0 <0.6.0\",\n          \"resolved\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz\",\n          \"dev\": true\n        },\n        \"form-data\": {\n          \"version\": \"0.1.4\",\n          \"from\": \"form-data@>=0.1.0 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"fs-extra\": {\n          \"version\": \"0.23.1\",\n          \"from\": \"fs-extra@>=0.23.1 <0.24.0\",\n          \"resolved\": \"https://registry.npmjs.org/fs-extra/-/fs-extra-0.23.1.tgz\",\n          \"dev\": true\n        },\n        \"hawk\": {\n          \"version\": \"1.1.1\",\n          \"from\": \"hawk@1.1.1\",\n          \"resolved\": \"https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"hoek\": {\n          \"version\": \"0.9.1\",\n          \"from\": \"hoek@>=0.9.0 <0.10.0\",\n          \"resolved\": \"https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz\",\n          \"dev\": true\n        },\n        \"http-signature\": {\n          \"version\": \"0.10.1\",\n          \"from\": \"http-signature@>=0.10.0 <0.11.0\",\n          \"resolved\": \"https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"mime-types\": {\n          \"version\": \"1.0.2\",\n          \"from\": \"mime-types@>=1.0.1 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz\",\n          \"dev\": true\n        },\n        \"node-uuid\": {\n          \"version\": \"1.4.8\",\n          \"from\": \"node-uuid@>=1.4.0 <1.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz\",\n          \"dev\": true\n        },\n        \"oauth-sign\": {\n          \"version\": \"0.4.0\",\n          \"from\": \"oauth-sign@>=0.4.0 <0.5.0\",\n          \"resolved\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        },\n        \"qs\": {\n          \"version\": \"1.2.2\",\n          \"from\": \"qs@>=1.2.0 <1.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/qs/-/qs-1.2.2.tgz\",\n          \"dev\": true\n        },\n        \"request\": {\n          \"version\": \"2.42.0\",\n          \"from\": \"request@2.42.0\",\n          \"resolved\": \"https://registry.npmjs.org/request/-/request-2.42.0.tgz\",\n          \"dev\": true\n        },\n        \"sntp\": {\n          \"version\": \"0.2.4\",\n          \"from\": \"sntp@>=0.2.0 <0.3.0\",\n          \"resolved\": \"https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz\",\n          \"dev\": true,\n          \"optional\": true\n        }\n      }\n    },\n    \"pify\": {\n      \"version\": \"2.3.0\",\n      \"from\": \"pify@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pify/-/pify-2.3.0.tgz\",\n      \"dev\": true\n    },\n    \"pinkie\": {\n      \"version\": \"2.0.4\",\n      \"from\": \"pinkie@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz\"\n    },\n    \"pinkie-promise\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"pinkie-promise@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz\"\n    },\n    \"pkg-up\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"pkg-up@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"pluralize\": {\n      \"version\": \"1.2.1\",\n      \"from\": \"pluralize@>=1.2.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz\",\n      \"dev\": true\n    },\n    \"prelude-ls\": {\n      \"version\": \"1.1.2\",\n      \"from\": \"prelude-ls@>=1.1.2 <1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz\",\n      \"dev\": true\n    },\n    \"preserve\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"preserve@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz\"\n    },\n    \"process\": {\n      \"version\": \"0.11.10\",\n      \"from\": \"process@>=0.11.0 <0.12.0\",\n      \"resolved\": \"https://registry.npmjs.org/process/-/process-0.11.10.tgz\",\n      \"dev\": true\n    },\n    \"process-nextick-args\": {\n      \"version\": \"1.0.7\",\n      \"from\": \"process-nextick-args@>=1.0.6 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz\"\n    },\n    \"progress\": {\n      \"version\": \"1.1.8\",\n      \"from\": \"progress@1.1.8\",\n      \"resolved\": \"https://registry.npmjs.org/progress/-/progress-1.1.8.tgz\",\n      \"dev\": true\n    },\n    \"promise\": {\n      \"version\": \"7.3.1\",\n      \"from\": \"promise@>=7.1.1 <8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/promise/-/promise-7.3.1.tgz\",\n      \"dev\": true,\n      \"optional\": true\n    },\n    \"proto-list\": {\n      \"version\": \"1.2.4\",\n      \"from\": \"proto-list@>=1.2.1 <1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz\",\n      \"dev\": true\n    },\n    \"prr\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"prr@>=0.0.0 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/prr/-/prr-0.0.0.tgz\",\n      \"dev\": true\n    },\n    \"public-encrypt\": {\n      \"version\": \"4.0.0\",\n      \"from\": \"public-encrypt@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz\",\n      \"dev\": true\n    },\n    \"punycode\": {\n      \"version\": \"1.4.1\",\n      \"from\": \"punycode@>=1.4.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz\"\n    },\n    \"q\": {\n      \"version\": \"1.4.1\",\n      \"from\": \"q@1.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/q/-/q-1.4.1.tgz\",\n      \"dev\": true\n    },\n    \"qs\": {\n      \"version\": \"6.3.2\",\n      \"from\": \"qs@>=6.3.0 <6.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/qs/-/qs-6.3.2.tgz\"\n    },\n    \"querystring\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"querystring@0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz\",\n      \"dev\": true\n    },\n    \"querystring-es3\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"querystring-es3@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz\",\n      \"dev\": true\n    },\n    \"randomatic\": {\n      \"version\": \"1.1.7\",\n      \"from\": \"randomatic@>=1.1.3 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz\",\n      \"dependencies\": {\n        \"is-number\": {\n          \"version\": \"3.0.0\",\n          \"from\": \"is-number@>=3.0.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz\",\n          \"dependencies\": {\n            \"kind-of\": {\n              \"version\": \"3.2.2\",\n              \"from\": \"kind-of@^3.0.2\",\n              \"resolved\": \"https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz\"\n            }\n          }\n        },\n        \"kind-of\": {\n          \"version\": \"4.0.0\",\n          \"from\": \"kind-of@>=4.0.0 <5.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz\"\n        }\n      }\n    },\n    \"randombytes\": {\n      \"version\": \"2.0.5\",\n      \"from\": \"randombytes@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz\",\n      \"dev\": true\n    },\n    \"raw-body\": {\n      \"version\": \"2.1.7\",\n      \"from\": \"raw-body@>=2.1.5 <2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"bytes\": {\n          \"version\": \"2.4.0\",\n          \"from\": \"bytes@2.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz\",\n          \"dev\": true\n        },\n        \"iconv-lite\": {\n          \"version\": \"0.4.13\",\n          \"from\": \"iconv-lite@0.4.13\",\n          \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"read-pkg\": {\n      \"version\": \"1.1.0\",\n      \"from\": \"read-pkg@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz\",\n      \"dev\": true\n    },\n    \"read-pkg-up\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"read-pkg-up@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"readable-stream\": {\n      \"version\": \"2.3.3\",\n      \"from\": \"readable-stream@>=2.0.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz\"\n    },\n    \"readdirp\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"readdirp@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz\"\n    },\n    \"readline2\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"readline2@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"rechoir\": {\n      \"version\": \"0.6.2\",\n      \"from\": \"rechoir@>=0.6.2 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"resolve\": {\n          \"version\": \"1.4.0\",\n          \"from\": \"resolve@>=1.1.6 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"regex-cache\": {\n      \"version\": \"0.4.3\",\n      \"from\": \"regex-cache@>=0.4.2 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz\"\n    },\n    \"remove-trailing-separator\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"remove-trailing-separator@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz\"\n    },\n    \"repeat-element\": {\n      \"version\": \"1.1.2\",\n      \"from\": \"repeat-element@>=1.1.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz\"\n    },\n    \"repeat-string\": {\n      \"version\": \"1.6.1\",\n      \"from\": \"repeat-string@>=1.5.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz\"\n    },\n    \"request\": {\n      \"version\": \"2.79.0\",\n      \"from\": \"request@2.79.0\",\n      \"resolved\": \"https://registry.npmjs.org/request/-/request-2.79.0.tgz\"\n    },\n    \"request-progress\": {\n      \"version\": \"0.3.1\",\n      \"from\": \"request-progress@0.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/request-progress/-/request-progress-0.3.1.tgz\",\n      \"dev\": true\n    },\n    \"require-directory\": {\n      \"version\": \"2.1.1\",\n      \"from\": \"require-directory@>=2.1.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz\",\n      \"dev\": true\n    },\n    \"require-main-filename\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"require-main-filename@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"require-uncached\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"require-uncached@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"requirejs\": {\n      \"version\": \"2.1.22\",\n      \"from\": \"requirejs@>=2.1.0 <2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/requirejs/-/requirejs-2.1.22.tgz\",\n      \"dev\": true\n    },\n    \"resolve\": {\n      \"version\": \"0.3.1\",\n      \"from\": \"resolve@>=0.3.1 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz\",\n      \"dev\": true\n    },\n    \"resolve-from\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"resolve-from@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"resolve-pkg\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"resolve-pkg@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-0.1.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"resolve-from\": {\n          \"version\": \"2.0.0\",\n          \"from\": \"resolve-from@>=2.0.0 <3.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"restore-cursor\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"restore-cursor@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"rewire\": {\n      \"version\": \"1.1.2\",\n      \"from\": \"rewire@1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/rewire/-/rewire-1.1.2.tgz\",\n      \"dev\": true\n    },\n    \"right-align\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"right-align@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz\",\n      \"dev\": true\n    },\n    \"rimraf\": {\n      \"version\": \"2.2.8\",\n      \"from\": \"rimraf@>=2.2.6 <2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz\"\n    },\n    \"ripemd160\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"ripemd160@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz\",\n      \"dev\": true\n    },\n    \"run-async\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"run-async@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"rx-lite\": {\n      \"version\": \"3.1.2\",\n      \"from\": \"rx-lite@>=3.1.2 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz\",\n      \"dev\": true\n    },\n    \"safe-buffer\": {\n      \"version\": \"5.1.1\",\n      \"from\": \"safe-buffer@>=5.1.1 <5.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz\"\n    },\n    \"sax\": {\n      \"version\": \"0.6.1\",\n      \"from\": \"sax@>=0.6.1 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/sax/-/sax-0.6.1.tgz\",\n      \"dev\": true\n    },\n    \"semver\": {\n      \"version\": \"5.3.0\",\n      \"from\": \"semver@5.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-5.3.0.tgz\"\n    },\n    \"set-blocking\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"set-blocking@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz\",\n      \"dev\": true\n    },\n    \"set-immediate-shim\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"set-immediate-shim@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz\"\n    },\n    \"setimmediate\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"setimmediate@>=1.0.4 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz\",\n      \"dev\": true\n    },\n    \"sha.js\": {\n      \"version\": \"2.4.8\",\n      \"from\": \"sha.js@>=2.4.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz\",\n      \"dev\": true\n    },\n    \"shelljs\": {\n      \"version\": \"0.7.8\",\n      \"from\": \"shelljs@>=0.7.5 <0.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz\",\n      \"dev\": true\n    },\n    \"sigmund\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"sigmund@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"slice-ansi\": {\n      \"version\": \"0.0.4\",\n      \"from\": \"slice-ansi@0.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz\",\n      \"dev\": true\n    },\n    \"sntp\": {\n      \"version\": \"1.0.9\",\n      \"from\": \"sntp@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz\"\n    },\n    \"source-list-map\": {\n      \"version\": \"0.1.8\",\n      \"from\": \"source-list-map@>=0.1.7 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz\",\n      \"dev\": true\n    },\n    \"source-map\": {\n      \"version\": \"0.5.6\",\n      \"from\": \"source-map@>=0.5.3 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz\",\n      \"dev\": true\n    },\n    \"spdx-correct\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"spdx-correct@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"spdx-expression-parse\": {\n      \"version\": \"1.0.4\",\n      \"from\": \"spdx-expression-parse@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz\",\n      \"dev\": true\n    },\n    \"spdx-license-ids\": {\n      \"version\": \"1.2.2\",\n      \"from\": \"spdx-license-ids@>=1.0.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz\",\n      \"dev\": true\n    },\n    \"sprintf-js\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"sprintf-js@>=1.0.2 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"sshpk\": {\n      \"version\": \"1.13.1\",\n      \"from\": \"sshpk@>=1.7.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz\",\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\"\n        }\n      }\n    },\n    \"statuses\": {\n      \"version\": \"1.3.1\",\n      \"from\": \"statuses@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz\",\n      \"dev\": true\n    },\n    \"stream-browserify\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"stream-browserify@>=2.0.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz\",\n      \"dev\": true\n    },\n    \"stream-http\": {\n      \"version\": \"2.7.2\",\n      \"from\": \"stream-http@>=2.3.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz\",\n      \"dev\": true\n    },\n    \"string_decoder\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"string_decoder@>=1.0.3 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz\"\n    },\n    \"string-width\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"string-width@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"stringstream\": {\n      \"version\": \"0.0.5\",\n      \"from\": \"stringstream@>=0.0.4 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz\"\n    },\n    \"strip-ansi\": {\n      \"version\": \"3.0.1\",\n      \"from\": \"strip-ansi@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz\"\n    },\n    \"strip-bom\": {\n      \"version\": \"3.0.0\",\n      \"from\": \"strip-bom@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz\",\n      \"dev\": true\n    },\n    \"strip-json-comments\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"strip-json-comments@>=2.0.1 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz\",\n      \"dev\": true\n    },\n    \"supports-color\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"supports-color@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz\"\n    },\n    \"table\": {\n      \"version\": \"3.8.3\",\n      \"from\": \"table@>=3.7.8 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/table/-/table-3.8.3.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-regex\": {\n          \"version\": \"3.0.0\",\n          \"from\": \"ansi-regex@>=3.0.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz\",\n          \"dev\": true\n        },\n        \"is-fullwidth-code-point\": {\n          \"version\": \"2.0.0\",\n          \"from\": \"is-fullwidth-code-point@>=2.0.0 <3.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz\",\n          \"dev\": true\n        },\n        \"string-width\": {\n          \"version\": \"2.1.1\",\n          \"from\": \"string-width@>=2.0.0 <3.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz\",\n          \"dev\": true\n        },\n        \"strip-ansi\": {\n          \"version\": \"4.0.0\",\n          \"from\": \"strip-ansi@>=4.0.0 <5.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"tapable\": {\n      \"version\": \"0.2.7\",\n      \"from\": \"tapable@>=0.2.5 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/tapable/-/tapable-0.2.7.tgz\",\n      \"dev\": true\n    },\n    \"tar\": {\n      \"version\": \"2.2.1\",\n      \"from\": \"tar@2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/tar/-/tar-2.2.1.tgz\",\n      \"dev\": true\n    },\n    \"temp\": {\n      \"version\": \"0.8.3\",\n      \"from\": \"temp@0.8.3\",\n      \"resolved\": \"https://registry.npmjs.org/temp/-/temp-0.8.3.tgz\"\n    },\n    \"temporary\": {\n      \"version\": \"0.0.8\",\n      \"from\": \"temporary@>=0.0.4 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/temporary/-/temporary-0.0.8.tgz\",\n      \"dev\": true\n    },\n    \"text-table\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"text-table@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz\",\n      \"dev\": true\n    },\n    \"throttleit\": {\n      \"version\": \"0.0.2\",\n      \"from\": \"throttleit@>=0.0.2 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz\",\n      \"dev\": true\n    },\n    \"through\": {\n      \"version\": \"2.3.8\",\n      \"from\": \"through@>=2.3.6 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/through/-/through-2.3.8.tgz\",\n      \"dev\": true\n    },\n    \"timers-browserify\": {\n      \"version\": \"2.0.3\",\n      \"from\": \"timers-browserify@>=2.0.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.3.tgz\",\n      \"dev\": true\n    },\n    \"tiny-lr\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"tiny-lr@>=0.2.1 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"qs\": {\n          \"version\": \"5.1.0\",\n          \"from\": \"qs@>=5.1.0 <5.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/qs/-/qs-5.1.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"tinycolor\": {\n      \"version\": \"0.0.1\",\n      \"from\": \"tinycolor@>=0.0.0 <1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz\"\n    },\n    \"to-arraybuffer\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"to-arraybuffer@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz\",\n      \"dev\": true\n    },\n    \"touch\": {\n      \"version\": \"0.0.3\",\n      \"from\": \"touch@0.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/touch/-/touch-0.0.3.tgz\",\n      \"dependencies\": {\n        \"nopt\": {\n          \"version\": \"1.0.10\",\n          \"from\": \"nopt@>=1.0.10 <1.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz\"\n        }\n      }\n    },\n    \"tough-cookie\": {\n      \"version\": \"2.3.2\",\n      \"from\": \"tough-cookie@>=2.3.0 <2.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz\"\n    },\n    \"traverse\": {\n      \"version\": \"0.3.9\",\n      \"from\": \"traverse@>=0.3.0 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz\"\n    },\n    \"tryit\": {\n      \"version\": \"1.0.3\",\n      \"from\": \"tryit@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz\",\n      \"dev\": true\n    },\n    \"tty-browserify\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"tty-browserify@0.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz\",\n      \"dev\": true\n    },\n    \"tunnel-agent\": {\n      \"version\": \"0.4.3\",\n      \"from\": \"tunnel-agent@>=0.4.1 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz\"\n    },\n    \"tweetnacl\": {\n      \"version\": \"0.14.5\",\n      \"from\": \"tweetnacl@>=0.14.0 <0.15.0\",\n      \"resolved\": \"https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz\",\n      \"optional\": true\n    },\n    \"type-check\": {\n      \"version\": \"0.3.2\",\n      \"from\": \"type-check@>=0.3.2 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz\",\n      \"dev\": true\n    },\n    \"type-is\": {\n      \"version\": \"1.6.15\",\n      \"from\": \"type-is@>=1.6.10 <1.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz\",\n      \"dev\": true\n    },\n    \"typedarray\": {\n      \"version\": \"0.0.6\",\n      \"from\": \"typedarray@>=0.0.6 <0.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz\",\n      \"dev\": true\n    },\n    \"uglify-js\": {\n      \"version\": \"2.2.5\",\n      \"from\": \"uglify-js@>=2.2.1 <2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"source-map\": {\n          \"version\": \"0.1.43\",\n          \"from\": \"source-map@>=0.1.7 <0.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"uglify-to-browserify\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"uglify-to-browserify@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz\",\n      \"dev\": true,\n      \"optional\": true\n    },\n    \"uid-number\": {\n      \"version\": \"0.0.5\",\n      \"from\": \"uid-number@0.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/uid-number/-/uid-number-0.0.5.tgz\",\n      \"dev\": true\n    },\n    \"underscore\": {\n      \"version\": \"1.7.0\",\n      \"from\": \"underscore@>=1.7.0 <1.8.0\",\n      \"resolved\": \"https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz\",\n      \"dev\": true\n    },\n    \"underscore.string\": {\n      \"version\": \"2.2.1\",\n      \"from\": \"underscore.string@>=2.2.1 <2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz\",\n      \"dev\": true\n    },\n    \"unpipe\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"unpipe@1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"url\": {\n      \"version\": \"0.11.0\",\n      \"from\": \"url@>=0.11.0 <0.12.0\",\n      \"resolved\": \"https://registry.npmjs.org/url/-/url-0.11.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"punycode\": {\n          \"version\": \"1.3.2\",\n          \"from\": \"punycode@1.3.2\",\n          \"resolved\": \"https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"user-home\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"user-home@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz\",\n      \"dev\": true\n    },\n    \"util\": {\n      \"version\": \"0.10.3\",\n      \"from\": \"util@>=0.10.3 <0.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/util/-/util-0.10.3.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"inherits\": {\n          \"version\": \"2.0.1\",\n          \"from\": \"inherits@2.0.1\",\n          \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"util-deprecate\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"util-deprecate@>=1.0.1 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\"\n    },\n    \"uuid\": {\n      \"version\": \"3.1.0\",\n      \"from\": \"uuid@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz\"\n    },\n    \"validate-npm-package-license\": {\n      \"version\": \"3.0.1\",\n      \"from\": \"validate-npm-package-license@>=3.0.1 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz\",\n      \"dev\": true\n    },\n    \"verror\": {\n      \"version\": \"1.3.6\",\n      \"from\": \"verror@1.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/verror/-/verror-1.3.6.tgz\"\n    },\n    \"vm-browserify\": {\n      \"version\": \"0.0.4\",\n      \"from\": \"vm-browserify@0.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz\",\n      \"dev\": true\n    },\n    \"walkdir\": {\n      \"version\": \"0.0.11\",\n      \"from\": \"walkdir@>=0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz\",\n      \"dev\": true\n    },\n    \"watchpack\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"watchpack@>=1.2.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"chokidar\": {\n          \"version\": \"1.7.0\",\n          \"from\": \"chokidar@>=1.7.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"webpack\": {\n      \"version\": \"2.2.1\",\n      \"from\": \"webpack@2.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/webpack/-/webpack-2.2.1.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"acorn\": {\n          \"version\": \"4.0.13\",\n          \"from\": \"acorn@>=4.0.4 <5.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz\",\n          \"dev\": true\n        },\n        \"supports-color\": {\n          \"version\": \"3.2.3\",\n          \"from\": \"supports-color@>=3.1.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz\",\n          \"dev\": true\n        },\n        \"uglify-js\": {\n          \"version\": \"2.8.29\",\n          \"from\": \"uglify-js@>=2.7.5 <3.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz\",\n          \"dev\": true,\n          \"dependencies\": {\n            \"yargs\": {\n              \"version\": \"3.10.0\",\n              \"from\": \"yargs@>=3.10.0 <3.11.0\",\n              \"resolved\": \"https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz\",\n              \"dev\": true\n            }\n          }\n        }\n      }\n    },\n    \"webpack-sources\": {\n      \"version\": \"0.1.5\",\n      \"from\": \"webpack-sources@>=0.1.4 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.1.5.tgz\",\n      \"dev\": true\n    },\n    \"websocket-driver\": {\n      \"version\": \"0.6.5\",\n      \"from\": \"websocket-driver@>=0.5.1\",\n      \"resolved\": \"https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz\",\n      \"dev\": true\n    },\n    \"websocket-extensions\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"websocket-extensions@>=0.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz\",\n      \"dev\": true\n    },\n    \"which\": {\n      \"version\": \"1.0.9\",\n      \"from\": \"which@>=1.0.5 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/which/-/which-1.0.9.tgz\",\n      \"dev\": true\n    },\n    \"which-module\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"which-module@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz\",\n      \"dev\": true\n    },\n    \"window-size\": {\n      \"version\": \"0.1.0\",\n      \"from\": \"window-size@0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz\",\n      \"dev\": true\n    },\n    \"wordwrap\": {\n      \"version\": \"0.0.3\",\n      \"from\": \"wordwrap@>=0.0.2 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz\",\n      \"dev\": true\n    },\n    \"wrap-ansi\": {\n      \"version\": \"2.1.0\",\n      \"from\": \"wrap-ansi@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz\",\n      \"dev\": true\n    },\n    \"wrappy\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"wrappy@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz\",\n      \"dev\": true\n    },\n    \"write\": {\n      \"version\": \"0.2.1\",\n      \"from\": \"write@>=0.2.1 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/write/-/write-0.2.1.tgz\",\n      \"dev\": true\n    },\n    \"ws\": {\n      \"version\": \"0.4.32\",\n      \"from\": \"ws@>=0.4.31 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/ws/-/ws-0.4.32.tgz\",\n      \"dependencies\": {\n        \"commander\": {\n          \"version\": \"2.1.0\",\n          \"from\": \"commander@>=2.1.0 <2.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/commander/-/commander-2.1.0.tgz\"\n        }\n      }\n    },\n    \"xmldoc\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"xmldoc@>=0.1.2 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/xmldoc/-/xmldoc-0.1.4.tgz\",\n      \"dev\": true\n    },\n    \"xmldom\": {\n      \"version\": \"0.1.27\",\n      \"from\": \"xmldom@>=0.1.22 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz\",\n      \"dev\": true\n    },\n    \"xtend\": {\n      \"version\": \"4.0.1\",\n      \"from\": \"xtend@>=4.0.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz\"\n    },\n    \"y18n\": {\n      \"version\": \"3.2.1\",\n      \"from\": \"y18n@>=3.2.1 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz\",\n      \"dev\": true\n    },\n    \"yargs\": {\n      \"version\": \"6.6.0\",\n      \"from\": \"yargs@>=6.0.0 <7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"camelcase\": {\n          \"version\": \"3.0.0\",\n          \"from\": \"camelcase@>=3.0.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz\",\n          \"dev\": true\n        },\n        \"cliui\": {\n          \"version\": \"3.2.0\",\n          \"from\": \"cliui@>=3.2.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"yargs-parser\": {\n      \"version\": \"4.2.1\",\n      \"from\": \"yargs-parser@>=4.2.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"camelcase\": {\n          \"version\": \"3.0.0\",\n          \"from\": \"camelcase@>=3.0.0 <4.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz\",\n          \"dev\": true\n        }\n      }\n    },\n    \"zlib\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"zlib@1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz\",\n      \"dev\": true\n    },\n    \"zlib-browserify\": {\n      \"version\": \"0.0.1\",\n      \"from\": \"zlib-browserify@0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz\",\n      \"dev\": true\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"Brackets\",\n    \"version\": \"1.15.0-0\",\n    \"apiVersion\": \"1.15.0\",\n    \"homepage\": \"http://brackets.io\",\n    \"issues\": {\n        \"url\": \"http://github.com/adobe/brackets/issues\"\n    },\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/adobe/brackets.git\",\n        \"branch\": \"\",\n        \"SHA\": \"\"\n    },\n    \"defaultExtensions\": {\n        \"brackets-eslint\": \"3.2.0\"\n    },\n    \"dependencies\": {\n        \"anymatch\": \"1.3.0\",\n        \"async\": \"2.1.4\",\n        \"chokidar\": \"1.6.1\",\n        \"decompress-zip\": \"0.3.0\",\n        \"fs-extra\": \"2.0.0\",\n        \"lodash\": \"4.17.15\",\n        \"npm\": \"3.10.10\",\n        \"opn\": \"4.0.2\",\n        \"request\": \"2.79.0\",\n        \"semver\": \"5.3.0\",\n        \"temp\": \"0.8.3\",\n        \"ws\": \"~0.4.31\"\n    },\n    \"devDependencies\": {\n        \"glob\": \"7.1.1\",\n        \"grunt\": \"0.4.5\",\n        \"husky\": \"0.13.2\",\n        \"jasmine-node\": \"1.11.0\",\n        \"grunt-jasmine-node\": \"0.1.0\",\n        \"grunt-cli\": \"0.1.9\",\n        \"phantomjs\": \"1.9.18\",\n        \"grunt-lib-phantomjs\": \"0.3.0\",\n        \"grunt-eslint\": \"19.0.0\",\n        \"grunt-contrib-watch\": \"1.0.0\",\n        \"grunt-contrib-jasmine\": \"0.4.2\",\n        \"grunt-template-jasmine-requirejs\": \"0.1.0\",\n        \"grunt-contrib-cssmin\": \"0.6.0\",\n        \"grunt-contrib-clean\": \"0.4.1\",\n        \"grunt-contrib-copy\": \"0.4.1\",\n        \"grunt-contrib-htmlmin\": \"0.1.3\",\n        \"grunt-contrib-less\": \"1.4.0\",\n        \"grunt-contrib-requirejs\": \"0.4.1\",\n        \"grunt-contrib-uglify\": \"0.2.0\",\n        \"grunt-contrib-concat\": \"0.3.0\",\n        \"grunt-targethtml\": \"0.2.6\",\n        \"grunt-usemin\": \"0.1.11\",\n        \"grunt-cleanempty\": \"1.0.3\",\n        \"load-grunt-tasks\": \"3.5.0\",\n        \"q\": \"1.4.1\",\n        \"rewire\": \"1.1.2\",\n        \"tar\": \"2.2.1\",\n        \"webpack\": \"2.2.1\",\n        \"xmldoc\": \"0.1.2\",\n        \"zlib\": \"1.0.5\"\n    },\n    \"scripts\": {\n        \"prepush\": \"npm run eslint\",\n        \"postinstall\": \"grunt install\",\n        \"test\": \"grunt test\",\n        \"eslint\": \"grunt eslint\"\n    },\n    \"licenses\": [\n        {\n            \"type\": \"MIT\",\n            \"url\": \"https://github.com/adobe/brackets/blob/master/LICENSE\"\n        }\n    ]\n}"
  },
  {
    "path": "samples/bg/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>ПЪРВИ СТЪПКИ С BRACKETS</title>\n        <meta name=\"description\" content=\"Интерактивно ръководство за Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>ПЪРВИ СТЪПКИ С BRACKETS</h1>\n        <h2>Това е Вашето ръководство!</h2>\n        \n        <!--\n            СЪЗДАДЕН С <3 И JAVASCRIPT\n        -->\n        \n        <p>\n            Добре дошли в Brackets, модерен редактор за код с отворен код, който разбира от уеб дизайн. Това е лек,\n            но мощен редактор за код, който слива визуалните инструменти с редактора, така че да получавате достатъчно\n            помощ, когато сте в нужда.\n        </p>\n        \n        <!--\n            КАКВО Е BRACKETS?\n        -->\n        <p>\n            <em>Brackets е един различен вид редактор.</em>\n            Brackets има някои уникални функционалности, като бързо редактиране, преглед на живо и други, които може да не\n            откриете в други редактори. Brackets е написан на JavaScript, HTML и CSS. Това означава, че повечето от хората,\n            които използват Brackets имат уменията и да го променят и подобряват. Всъщност, ние самите използваме Brackets\n            всеки ден, за да градим Brackets. За да научите повече относно ключовите функционалности, продължавайте да четете.\n        </p>\n        \n        <!--\n            ПЪРВИ СТЪПКИ С ВАШИТЕ ФАЙЛОВЕ\n        -->\n        \n        <h3>Проектите в Brackets</h3>\n        <p>\n            За да редактирате своя код в Brackets, трябва да отворите папката, съдържаща файловете Ви.\n            Brackets смята текущо отворената папка за „проект“; функционалностите като подсказки за кода, преглед на живо и\n            бързо редактиране работят само с файловете в текущо отворената папка.\n        </p>\n        \n        <samp>\n            След като приключите с разглеждането на този примерен проект и искате да редактирате собствен код, можете да\n            използвате падащото меню в лявата странична лента, за да превключвате между папките. В момента там е избрано\n            „Getting Started“ — това е папката, съдържаща файла, който разглеждате в момента. Щракнете върху падащото меню и\n            изберете „Отваряне на папка…“, за да отворите своя собствена папка.\n            Можете да използвате това падащо меню, за да се връщате обратно към папките, които сте отворили по-рано,\n            включително този примерен проект.\n        </samp>\n        \n        <!--\n            ВРЪЗКАТА МЕЖДУ HTML, CSS И JAVASCRIPT\n        -->\n        <h3>Бързо редактиране на CSS и JavaScript</h3>\n        <p>\n            Без повече превключване между документи и забравяне къде сте били последно. Когато редактирате HTML, използвайте\n            комбинацията <kbd>Cmd/Ctrl + E</kbd>, за да отворите бърз редактор на място, който показва използвания CSS.\n            Променете CSS кода, натиснете <kbd>ESC</kbd> и се връщате към редактирането на HTML, или просто оставете\n            CSS правилата отворени и те ще станат част от редактора Ви за HTML. Ако натиснете <kbd>ESC</kbd> извън\n            вмъкнатия бърз редактор, всички такива ще се скрият. Бързото редактиране разпознава и правила, описани чрез\n            LESS и SCSS, включително и вложени правила.\n        </p>\n        \n        <samp>\n            Искате да го видите в действие? Поставете курсора върху елемента <!-- <samp> --> по-горе и натиснете\n            <kbd>Cmd/Ctrl + E</kbd>. Би трябвало да се появи бърз редактор за CSS, показващ CSS правилото, което\n            се прилага към този елемент. Бързото редактиране може да работи също и за класове и идентификатори.\n            Можете дори да го използвате с Вашите файлове с LESS и SCSS.\n            \n            Можете да създавате правила по същия начин. Щракнете върху един от елементите <!-- <p> --> по-гори и\n            натиснете <kbd>Cmd/Ctrl + E</kbd>. В момента няма правила за тях, но можете да натиснете бутона\n            „Ново правило“ и да добавите ново правило за <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Снимка на екрана, показваща бързото редактиране на CSS\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Можете да използвате същата клавишна комбинация, за да редактирате и други неща — например функции на\n            JavaScript, цветове и времеви функции за анимации; ние постоянно добавяме още.\n        </p>\n        <p>\n            За сега редакторите на място не могат да се влагат един в друг, така че можете да използвате бързото\n            редактиране само когато курсорът е в „пълния“ редактор.\n        </p>\n        \n        <!--\n            ПРЕГЛЕД НА ЖИВО\n        -->\n        <h3>Преглеждайте промените в HTML и CSS на живо в браузъра</h3>\n        <p>\n            Нали знаете как години наред си играем на „запазване и презареждане“? Играта, в която правите\n            промяна в редактора си, натискате „запазване“, превключвате към браузъра и натискате „презареждане“,\n            за да видите резултата?\n            С Brackets, няма да ви се налага да я играете повече.\n        </p>\n        <p>\n            Brackets ще отвори <em>жива връзка</em> с браузъра Ви и ще му праща промените в HTML и CSS кода\n            докато пишете! Може би вече правите нещо подобно с различни инструменти, работещи в браузъра, но с Brackets\n            няма да има нужда да копирате готовия код обратно в редактора. Кодът Ви работи в браузъра, но\n            живее в редактора!\n        </p>\n        \n        <h3>Осветява на HTML елементи и CSS правила на живо</h3>\n        <p>\n            С Brackets е лесно да видите как промените Ви в HTML и CSS ще променят страницата. Когато курсорът\n            е върху CSS правило, Brackets ще осветява всички елементи, върху които то влияе, в браузъра. Също\n            така, докато редактирате файл с HTML, Brackets ще осветява съответстващите елементи в браузъра.\n        </p>\n        \n        <samp>\n            Ако имате Google Chrome, може да опитате това. Щракнете иконката на светкавица в горния десен\n            ъгъл на прозореца на Brackets или натиснете <kbd>Cmd/Ctrl + Alt + P</kbd>. Когато прегледът на живо\n            е включен за даден HTML документ, всички свързани CSS документи могат да бъдат редактирани в реално време.\n            Иконката ще смени цвета си от сив на златист, когато Brackets установи връзка с браузъра Ви.\n            \n            Сега поставете курсора си върху елемента <!-- <img> --> по-горе. Забележете синия контур,\n            който се появява около изображението в Chrome. Сега натиснете <kbd>Cmd/Ctrl + E</kbd>, за да\n            отворите CSS правилата. Опитайте да промените размера на рамката от 10 на 20 пиксела или\n            променете цвета на фона от „transparent“ на „hotpink“. Ако Brackets и браузърът Ви работят\n            един до друг, ще видите как промените Ви автоматично се виждат в браузъра. Яко, нали?\n        </samp>\n        \n        <p class=\"note\">\n            Засега Brackets поддържа преглед на живо само за HTML и CSS. И все пак, в текущото издание, промените във\n            файловете с код на JavaScript се презареждат автоматично при запазване на файла. В момента работим върху\n            поддръжката на преглед на живо и за JavaScript. Прегледът на живо работи само с Google Chrome, но се надяваме\n            да поддържаме всички основни браузъри в бъдеще.\n        </p>\n        \n        <h3>Бърз преглед</h3>\n        <p>\n            Онези от нас, които не могат да запомнят съответствието между цветовете, изразени чрез шестнадесетични\n            числа и стойности ЧЗС, Brackets прави лесна и бърза проверката на това кой цвят се използва. Както в CSS,\n            така и в HTML, можете просто да посочите дадена цветова стойност или преливка, и Brackets ще Ви покаже как\n            изглежда този цвят или преливка автоматично. Същото важи и за изображенията: просто посочете връзката към\n            изображението в редактора и ще се появи миниатюрен изглед на това изображение.\n        </p>\n        \n        <samp>\n            За да опитате бързия преглед сами, поставете курсора върху елемента <!-- <body> --> в началото на този\n            документ и натиснете <kbd>Cmd/Ctrl + E</kbd>, за да отворите бързия редактор на CSS. Сега просто посочете\n            някоя стойност за цвят. Можете да видите това и при преливките, като отворите бърз редактор за\n            елемента <!-- <html> --> и посочите някоя от стойностите за фона. За да опитате прегледа на изображения,\n            поставете курсора върху снимката на екрана, която може да намерите по-нагоре в този документ.\n        </samp>\n        \n        <h3>Имате нужда от повече? Опитайте някое разширение!</h3>\n        <p>\n            Освен всички приятни функционалности, вградени в Brackets, нашата огромна и постоянно нарастваща\n            общност от разработчици на разширения е създала стотици такива, които добавят полезни и удобни функционалности.\n            Ако има нещо, от което се нуждаете, но не намирате в Brackets, много вероятно е някой вече да е създал\n            разширение за това. За да разгледате или претърсите списъка от налични разширения натиснете\n            <strong>Файл > Управител на разширения…</strong> и изберете раздела „Налични“. Когато намерите това,\n            което искате, просто натиснете бутона „Инсталиране“ до него.\n        </p>\n        \n        <!--\n            КАЖЕТЕ НИ КАКВО МИСЛИТЕ\n        -->\n        <h2>Включете се</h2>\n        <p>\n            Brackets е проект с отворен код. Разработчици от цял свят допринасят, за да изградим заедно\n            един по-добър редактор за код. Много други създават разширения, които увеличават възможностите\n            на Brackets. Кажете ни какво мислите, споделете идеите си или направо се включете в проекта!\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Блогът на екипа зад Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets в GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Регистър на разширенията за Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Уикито на Brackets</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Пощенският списък на разработчиците на Brackets</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets в Туитър</a></li>\n            <li>Пишете си с разработчиците на Brackets в IRC канала <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets във Freenode</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/bg/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/cs/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>ZAČÍNÁME S BRACKETS</title>\n        <meta name=\"description\" content=\"Interaktivní průvodce začátečníka v Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>ZAČÍNÁME S BRACKETS</h1>\n        <h2>Tohle je váš průvodce!</h2>\n        \n        <!--\n            VYTVOŘENO S <3 A S JAVASCRIPTEM\n        -->\n        \n        <p>\n            Vítejte v Brackets, moderním open-source editoru kódu, který rozumí webdesignu. Odlehčeném,\n            a přesto výkonném editoru kódu, který prolíná textový editor s vizuálními nástroji, takže dostanete\n            správné množství pomoci, kdy budete chtít.\n        </p>\n        \n        <!--\n            CO JE BRACKETS?\n        -->\n        <p>\n            <em>Brackets je jiný druh editoru.</em>\n            Brackets obsahuje některé unikátní prvky, jako rychlou úpravu, živý náhled a další, které v jiných\n            editorech pravděpodobně nenajdete. Navíc je Brackets napsán v JavaScriptu, HTML a CSS. To znamená,\n            že mnoho z nás používajících Brackets má znalosti potřebné k úpravě nebo rozšíření editoru. My sami\n            používáme Brackets neustále k vývoji Brackets. Čtěte dál, pokud se chcete dozvědět více o tom,\n            jak používat některé klíčové funkce editoru.\n        </p>\n        \n        <!--\n            ZAČNĚTE S VAŠIMI VLASTNÍMI SOUBORY\n        -->\n        \n        <h3>Projekty v Brackets</h3>\n        <p>\n            Abyste mohli editovat vlastní kód pomocí Brackets, stačí jenom otevřít složku obsahující vaše soubory.\n            Brackets považuje aktuálně otevřenou složku za „projekt“; funkce, jako např. nápovědy kódu, živý náhled\n            nebo rychlou úpravu, pak používá jenom u souborů uvnitř aktuálně otevřené složky.\n        </p>\n        \n        <samp>\n            Jakmile budete připraveni odejít z tohoto ukázkového projektu a editovat vlastní kód, můžete použít\n            rozbalovací nabídku v levém bočním panelu ke změně složek. Rozbalovací nabídka právě teď ukazuje\n            „Getting Started“ - to je složka obsahující soubor, který právě teď prohlížíte. Klikněte na rozbalovací\n            nabídku a vyberte „Otevřít složku…“ k otevření vaší vlastní složky.\n            Rozbalovací nabídku můžete použít také později k přechodu zpátky do složek, které jste otevřeli dříve,\n            včetně tohoto ukázkového projektu.\n        </samp>\n        \n        <!--\n            VZTAH MEZI HTML, CSS A JAVASCRIPTEM\n        -->\n        <h3>Rychlá úprava pro CSS a JavaScript</h3>\n        <p>\n            Žádné další přepínání mezi dokumenty a ztrácení souvislostí. Když editujete HTML, použijte klávesovou\n            zkratku <kbd>Cmd/Ctrl + E</kbd> k otevření rychle vloženého editoru, který zobrazí veškeré související\n            CSS. Proveďte drobnou úpravu ve vašem CSS, stiskněte <kbd>ESC</kbd> a jste zpátky v editaci HTML,\n            nebo prostě nechte CSS předpisy otevřené, čímž se stanou součástí vašeho HTML editoru. Pokud stisknete\n            <kbd>ESC</kbd> mimo rychle vložený editor, skryjí se tyto editory všechny. Rychlá úprava najde také\n            předpisy definované v LESS a SCSS souborech, včetně těch vnořených.\n        </p>\n        \n        <samp>\n            Chcete to vidět v akci? Umístěte kurzor na značku <!-- <samp> --> výše a stiskněte\n            <kbd>Cmd/Ctrl + E</kbd>. Pod danou značkou by se měla objevit rychlá úprava CSS, zobrazující související\n            CSS předpis. Rychlá úprava funguje také v atributech class a id. Stejně tak ji můžete využít ve vašich\n            LESS a SCSS souborech.\n            \n            Stejným způsobem můžete vytvořit i předpisy nové. Klikněte na jednu ze značek <!-- <p> --> výše\n            a stiskněte <kbd>Cmd/Ctrl + E</kbd>. Zatím tu žádné předpisy nejsou, ale můžete kliknout na tlačítko\n            Nový předpis, čímž přidáte nový předpis pro <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Snímek obrazovky zobrazující rychlou úpravu CSS\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Stejnou klávesovou zkratku můžete použít i k editaci jiných věcí - např. funkcí v JavaScriptu, barev\n            nebo funkcí pro načasování animací - a pořád přidáváme další a další.\n        </p>\n        <p>\n            Vložené editory prozatím nemohou být vnořené, rychlou úpravu tedy můžete použít pouze pokud je kurzor\n            uvnitř „plnohodnotného“ editoru.\n        </p>\n        \n        <!--\n            ŽIVÝ NÁHLED\n        -->\n        <h3>Zobrazte změny v HTML a CSS živě v prohlížeči</h3>\n        <p>\n            Znáte ten tanec „uložitaobnovit“, který předvádíme řadu let? Takový ten, kdy provedete změny ve vašem\n            editoru, uložíte je, přepnete na prohlížeč a obnovíte stránku, abyste nakonec viděli výsledek? S Brackets\n            se tomuhle tanci můžete vyhnout.\n        </p>\n        <p>\n            Brackets otevře <em>živé spojení</em> s vaším prohlížečem a posílá změny v HTML a CSS během psaní! Možná\n            už dnes děláte něco podobného s nástroji v prohlížečích, ale s Brackets není potřeba kopírovat výsledný\n            kód a vkládat jej zpátky do editoru. Váš kód běží uvnitř prohlížeče, ale žije ve vašem editoru!\n        </p>\n        \n        <h3>Živé zvýraznění HTML prvků a CSS předpisů</h3>\n        <p>\n            Díky Brackets jednoduše uvidíte, jak vaše změny v HTML a CSS ovlivní stránku. Pokud umístíte kurzor\n            na CSS předpis, Brackets zvýrazní všechny zasažené prvky v prohlížeči. Podobně i při editaci HTML souboru\n            Brackets zvýrazní odpovídající HTML prvky v prohlížeči.\n        </p>\n        \n        <samp>\n            Pokud máte nainstalovaný Google Chrome, můžete si to vyzkoušet sami. Klikněte na ikonu blesku v pravém\n            horním rohu vašeho okna Brackets nebo stiskněte <kbd>Cmd/Ctrl + Alt + P</kbd>. Pokud je pro HTML\n            dokumenty povolen živý náhled, veškeré připojené CSS dokumenty mohou být editovány v reálném čase. Ikona\n            se změní z šedé na zlatou pokud Brackets naváže spojení s vaším prohlížečem.\n            \n            Nyní umístěte kurzor na značku <!-- <img> --> výše. Všimněte si modrého zvýraznění, které se objeví\n            v Google Chrome kolem obrázku. Dále použijte <kbd>Cmd/Ctrl + E</kbd> k otevření definovaných CSS\n            předpisů. Zkuste změnit šířku rámečku z 10px na 20px nebo změnit barvu pozadí z „transparent“\n            na „hotpink“. Pokud běží Brackets a váš prohlížeč vedle sebe, uvidíte, jak se vaše změny okamžitě projeví\n            ve vašem prohlížeči. Úžasné, že?\n        </samp>\n        \n        <p class=\"note\">\n            Brackets v současnosti podporuje živý náhled pouze pro HTML a CSS. V aktuální verzi jsou změny\n            v JavaScriptových souborech alespoň automaticky načteny, jakmile je uložíte. Aktuálně pracujeme právě\n            na podpoře živého náhledu pro JavaScript. Živé náhledy jsou také možné jenom s prohlížečem Google Chrome,\n            ale doufáme, že tuto funkci v budoucnu přineseme do všech hlavních prohlížečů.\n        </p>\n        \n        <h3>Rychlý náhled</h3>\n        <p>\n            Pro ty z vás, kteří si ještě nezapamatovali ekvivalenty barev pro HEX nebo RGB hodnoty, Brackets rychle\n            a jednoduše zobrazí, jaká barva je právě používána. Jak v CSS, tak v HTML prostě najeďte na jakoukoliv\n            barevnou hodnotu nebo barevný přechod a Brackets automaticky zobrazí náhled dané barvy nebo daného\n            barevného přechodu. To samé platí pro obrázky: jednoduše najeďte na odkaz obrázku v editoru Brackets\n            a ten zobrazí malý náhled daného obrázku.\n        </p>\n        \n        <samp>\n            Pokud si rychlý náhled chcete vyzkoušet sami, umístěte kurzor na značku <!-- <body> --> výše v tomto\n            dokumentu a stiskněte <kbd>Cmd/Ctrl + E</kbd> k otevření rychlého editoru CSS. Nyní jednoduše najeďte\n            na kteroukoliv barevnou hodnotu v CSS. Také náhled barevných přechodů můžete vidět v akci otevřením\n            rychlého editoru CSS na značce <!-- <html> --> a najetím na kteroukoliv hodnotu background-image.\n            K vyzkoušení náhledu obrázku umístěte kurzor na snímek obrazovky vložený výše v tomto dokumentu.\n        </samp>\n        \n        <h3>Potřebujete něco jiného? Zkuste doplněk!</h3>\n        <p>\n            Navíc ke všemu skvělému, co je zabudované do Brackets, ještě naše rozsáhlá a rostoucí komunita vývojářů\n            doplňků vyvinula stovky doplňků přidávající další užitečné funkce. Pokud je tu něco, co potřebujete,\n            ale Brackets to nenabízí, s největší pravděpodobností už pro to někdo vytvořil doplněk. K procházení\n            nebo prohledání seznamu dostupných doplňků vyberte <strong>Soubor > Správce doplňků…</strong> a klikněte\n            na záložku „Dostupné“. Až naleznete doplněk, který hledáte, prostě klikněte na tlačítko „Instalovat“\n            vedle něj.\n        </p>\n        \n        <!--\n            DEJTE NÁM VĚDĚT, CO SI MYSLÍTE\n        -->\n        <h2>Zapojte se</h2>\n        <p>\n            Brackets je open-source projekt. Weboví vývojáři z celého světa se podílejí na vývoji a vylepšování\n            editoru. Mnoho dalších vyvíjí doplňky, které rozšiřují možnosti Brackets. Dejte nám vědět, co si myslíte,\n            sdílejte své nápady nebo se přímo podílejte na projektu.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Blog týmu Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets na GitHubu</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Registr doplňků Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Diskutujte s vývojáři Brackets na Skupinách Google</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets na Twitteru</a></li>\n            <li>Chatujte s vývojáři Brackets na IRC kanálu <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">Freenode/#Brackets</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n\n<!-- Last translated for 12ee7cd7c2c0eefb3fdee209eea92a82b66f1693 -->"
  },
  {
    "path": "samples/cs/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/da/Kom godt i gang/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>KOM GODT I GANG MED BRACKETS</title>\n        <meta name=\"description\" content=\"En interaktiv guide til at komme godt i gang med Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>KOM GODT I GANG MED BRACKETS</h1>\n        <h2>Dette er din guide!</h2>\n        \n        <!--\n            SKABT MED <3 OG JAVASCRIPT\n        -->\n        \n        <p>\n            Velkommen til dette tidlige smugkig på Brackets, en ny open-source editor til den næste generation af\n            nettet. Vi er stærke tilhængere af standarder og ønsker at skabe bedre værktøjer til JavaScript, HTML, CSS\n            og andre åbne web teknologier. Dette er vores ydmyge begyndelse.\n        </p>\n        \n        <!--\n            HVAD ER BRACKETS?\n        -->\n        <p>\n            <em>Brackets er en anderledes editor.</em>\n            En nævneværdig forskel er, at denne editor er skrevet i JavaScript, HTML og CSS.\n            Det betyder, at de fleste af jer der bruger Brackets har de nødvendige færdigheder til at ændre og udvide editoren.\n            Faktisk bruger vi selv Brackets hver dag for at bygge Brackets. Det har også nogle unikke funktioner såsom Lyn-Redigering,\n            Live-Forhåndsvisning og andre som du ikke finder i andre editorer.\n            Hvis du vil vide mere om, hvordan du bruger disse funktioner, så læs videre.\n        </p>\n        \n        \n        <h2>Vi afprøver et par nye ting</h2>\n        \n        <!--\n            FORHOLDET MELLEM HTML, CSS OG JAVASCRIPT\n        -->\n        <h3>Lyn-Redigering til CSS og JavaScript</h3>\n        <p>\n            Slut med at skifte mellem dokumenter og miste fokuset. Når du redigerer HTML, kan du trykke\n            <kbd>Cmd/Ctrl + E</kbd> for at åbne en indlejret editor som viser alt det relevante CSS.\n            Tilpas dit CSS, tryk <kbd>ESC</kbd> og du ryger tilbage til dit HTML-dokument, eller du kan efterlade\n            CSS-reglerne åbne så de bliver en del af din HTML-editor. Hvis du trykker <kbd>ESC</kbd> udenfor\n            en Lyn-Redigerings-editor, bliver de alle klappet sammen.\n        </p>\n        \n        <samp>\n            Vil du se hvordan det virker? Placér markøren på <!-- <samp> --> tagget ovenfor og tryk\n            <kbd>Cmd/Ctrl + E</kbd>. Du burde se Lyn-Redigering dukke frem, som viser den CSS-regel som\n            anvendes på den. Lyn-Redigering virker også med klasse- og id-attributter.\n            \n            Du kan oprette nye regler på samme måde. Klik i en af <!-- <p> --> tagsne ovenover og tryk\n            <kbd>Cmd/Ctrl + E</kbd>. Der er ingen regler til den lige nu, men du kan klikke på \"Ny Regel\"\n            for at oprette en ny regel til <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Et skærmbillede der viser CSS-Lyn-Redigering\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Du kan også bruge den samme genvej til at redigere andre ting--såsom funktioner i JavaScript,\n            farver, og timing-funktioner til animationer--og vi føjer mere til hele tiden.\n            Indtil videre kan editorerne ikke indlejres i hinanden, så du kan kun bruge Lyn-Redigering så længe markøren\n            er i det primære redigerings-felt.\n        </p>\n        \n        <!--\n            LIVE-FORHÅNDSVISNING\n        -->\n        <h3>Se ændringer i HTML og CSS live i browseren</h3>\n        <p>\n            Kender du den \"gem/genindlæs\"-finte vi har lavet i årevis? Den hvor du laver ændringer i\n            din editor, gemmer, skifter over til browseren og så genindlæser for endeligt at se resultatet?\n            Med Brackets kan du lægge den finte på hylden.\n        </p>\n        <p>\n            Brackets åbner en <em>direkte forbindelse</em> til din lokale browser og sender HTML og CSS opdateringer imens du\n            skriver! Måske gør du allerede noget lignende i dag med browser-baserede værktøjer, men med Brackets\n            behøver du ikke kopiere den endelige kode tilbage i editoren. Din kode kører i din browser,\n            men bor i din editor!\n        </p>\n        \n        <h3>Live fremhævelse af HTML-elementer og CSS-regler</h3>\n        <p>\n            Brackets gør det nemt at se dine ændringer i HTML og CSS vil påvirke siden. Når markøren\n            er på en CSS-regel, vil Brackets fremhæve alle påvirkede elementer i browseren. Ligeledes, når en\n            HTML-fil redigeres, vil Brackets fremhæve de tilsvarende HTML-elementer i browseren.\n        </p>\n        \n        <samp>\n            Hvis du har Google Chrome installeret, kan du prøve det af selv. Klik på lyn-ikonet\n            i øverste højre hjørne af Brackets vinduet eller tryk <kbd>Cmd/Ctrl + Alt + P</kbd>. Når\n            Live-Forhåndsvisning slåes til på et HTML-dokument, kan alle tilknyttede CSS-dokumenter redigeres i realtid.\n            Ikonet skifter fra grå til guld når Brackets har etableret en forbindelse til browseren.\n            \n            Placér nu markøren på <!-- <img> --> tagget ovenover. Bemærk den blå fremhævning der dukker op\n            rundt om billedet i Chrome. Tryk derefter på <kbd>Cmd/Ctrl + E</kbd> for at åbne de definerede CSS-regler.\n            Prøv at ændre tykkelsen på kanten fra 10px til 20px eller ændre baggrundsfarven\n            fra \"transparent\" til \"hotpink\". Hvis du har Brackets og browseren til at køre side om side,\n            kan du med det samme se dine ændringer blive vist i browseren. Er det ikke sejt?\n        </samp>\n                \n        <p class=\"note\">\n            I dag understøtter Brackets kun Live-Forhåndsvisning for HTML og CSS. Ændringer til JavaScript-filer\n            bliver dog genindlæst automatisk når du gemmer. Vi arbejder i øjeblikket på at Live-Forhåndsvisning\n            også understøtter JavaScript. Live-Forhåndsvisning er også kun muligt med Google Chrome, men vi håber på\n            at bringe denne funktionalitet ud til alle gængse browsere i fremtiden.\n        </p>\n                \n        <h3>Lyn-visning</h3>\n        <p>\n            For dem af os, som endnu ikke kan alle farvers HEX- eller RGB-kode udenad, gør Brackets\n            det hurtigt og nemt at se nøjagtig hvilken farve der er brugt. I enten CSS eller HTML, peger du ganske enkelt på en\n            farve-værdi eller gradient og Brackets vil vise et eksempel af den farve/gradient automatisk. Det\n            samme gælder for billeder: du peger ganske enkelt på billede-adressen i editoren og der vises en\n            miniature-udgave af det billede.\n        </p>\n        \n        <samp>\n            Du kan afprøve Lyn-Visning ved at placére markøren på <!-- <body> --> tagget øverst i dette\n            dokument og trykke <kbd>Cmd/Ctrl + E</kbd> for at åbne CSS-Lyn-Redigering. Her kan du pege på enhver\n            farve-værdi i CSS'en og se farven. Du kan også set det i aktion i gradienter ved at åbne Lyn-Redigering\n            på <!-- <html> --> tagget og pege på en af værdierne for baggrundsbilledet. For at se et smugkig af billeder,\n            peg på adressen til skærmbilledet, som er indsat tidligere i dette dokument.\n        </samp>\n        \n        <h3>Har du brug for noget andet? Prøv en udvidelse!</h3>\n        <p>\n            Som tilføjelse til alle de gode sager der er indbygget i Brackets, har vores store og voksende samfund af\n            udviklere skabt over hundrede udvidelser, som tilføjer nyttig funktionalitet. Hvis der er\n            noget du har brug for, som Brackets ikke tilbyder, er det ret sandsynligt at nogen har lavet en udvidelse til\n            det. For at gennemse eller søge i listen af tilgængelige udvidelser, vælg <strong>Filer > Udvidelses-håndtering</strong>\n            og klik på fanen \"Udvalg\". Når du har fundet en udvidelse du kunne tænke dig, klikker du blot på\n            knappen \"Installér\" ud for den.\n        </p>\n        \n        <!--\n            GIV DIN MENING TIL KENDE\n        -->\n        <h2>Bliv involveret</h2>\n        <p>\n            Brackets er et open-source projekt. Web-udviklere fra hele verden bidrager til at bygge\n            en bedre kode-editor. Endnu flere bygger udvidelser der udvider funktionaliteten af Brackets.\n            Fortæl os hvad du synes, del dine idéer eller bidrag direkte til projektet.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets team-blog</a></li>\n            <li><a href=\"http://github.com/adobe/brackets\">Brackets på GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets udvidelses-register</a></li>\n            <li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets wiki</a></li>\n            <li><a href=\"http://groups.google.com/group/brackets-dev\">Brackets mailingliste for udviklere</a></li>\n            <li><a href=\"https://twitter.com/#!/brackets\">@brackets på Twitter</a></li>\n            <li>Chat med Brackets-udviklere på IRC i #brackets på Freenode</li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/da/Kom godt i gang/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/de/Erste Schritte/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>ERSTE SCHRITTE MIT BRACKETS</title>\n        <meta name=\"description\" content=\"Ein interaktiver Wegweiser für die ersten Schritte mit Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>ERSTE SCHRITTE MIT BRACKETS</h1>\n        <h2>Dies ist Ihre Anleitung!</h2>\n\n        <!--\n            GEMACHT MIT <3 UND JAVASCRIPT\n        -->\n\n        <p>\n            Willkommen zu Brackets, einem modernen, quelloffenen Code-Editor, der Webdesign versteht. Es ist ein\n            einfacher, aber dennoch leistungsfähiger Editor, der Ihnen immer die richtigen Tools einblendet, sodass\n            Sie die genau richtige Menge an Hilfestellung haben, wann immer Sie diese brauchen.\n        </p>\n\n        <!--\n            WAS IST BRACKETS?\n        -->\n        <p>\n            <em>Brackets ist eine andere Art Editor.</em>\n            Brackets hat ein paar einzigartige Features wie Schnelles Bearbeiten, Live-Vorschau und zahlreiche\n            weitere, die Sie in anderen Editoren vergeblich suchen werden. Zudem ist Brackets in JavaScript, HTML\n            und CSS geschrieben. Das heißt, dass die meisten Brackets-Nutzer dazu in der Lage sind, den Editor selbst\n            zu verändern und zu erweitern. Tatsächlich nutzen wir Brackets täglich, um Brackets zu verbessern.\n            Lesen Sie weiter, um mehr über die Nutzung der Hauptfeatures zu erfahren.\n        </p>\n        \n        <!--\n            BEGINNEN SIE, IHRE EIGENEN DATEIEN ZU NUTZEN\n        -->\n\n        <h3>Projekte in Brackets</h3>\n        <p>\n            Um Ihren eigenen Code in Brackets zu bearbeiten, können Sie einfach den Ordner öffnen, der Ihre\n            Dateien enthält.\n            Brackets sieht den geöffneten Ordner als \"Projekt\"; Features wie Code-Vervollständigung, Live-Vorschau\n            und Schnelles Bearbeiten nutzen nur Dateien im aktuell geöffneten Ordner.\n        </p>\n        \n        <samp>\n            Sobald Sie bereit sind, dieses Beispielprojekt zu verlassen und Ihren eigenen Code zu editieren, können\n            Sie die Drop-Down-Liste auf der linken Seite nutzen, um einen Ordner auszuwählen. Die Drop-Down-Liste\n            heißt zurzeit \"Erste Schritte\" - das ist der Ordner, der die aktuell geöffnete Datei enthält. Klicken\n            Sie darauf und wählen Sie daraufhin \"Ordner öffnen…\", um Ihren eigenen Ordner zu öffnen.\n            Sie können auf diese Weise auch später wieder zu zuvor geöffneten Ordnern, wie diesem Beispielprojekt,\n            zurückkehren.\n        </samp>\n\n        <!--\n            DIE BEZIEHUNG VON HTML, CSS UND JAVASCRIPT\n        -->\n        <h3>Schnelles Bearbeiten von CSS und JavaScript</h3>\n        <p>\n            Kein Wechsel zwischen Dokumenten mehr - so verlieren Sie nie den Überblick. Wenn Sie HTML editieren,\n            können Sie die Tastenkombination <kbd>Cmd/Strg + E</kbd> verwenden, um einen Inline-Editor anzuzeigen,\n            der Ihnen alle relevanten CSS-Regeln zum Schnellen Bearbeiten anzeigt.\n            Ändern Sie etwas im CSS, drücken Sie <kbd>ESC</kbd> und schon sind Sie zurück im HTML-Code. Oder lassen\n            Sie die CSS-Regeln einfach offen und sie werden Teil ihres HTML-Editors. Sobald Sie <kbd>ESC</kbd>\n            außerhalb eines solchen Editors drücken, schließen sich alle zusammen. Ein Inline-Editor zeigt Ihnen\n            auch Regeln in LESS- und SCSS-Dateien, inklusive geschachtelter Regeln.\n        </p>\n\n        <samp>\n            Sie wollen das in Aktion sehen? Setzen Sie Ihren Cursor auf den <!-- <samp> -->-Tag oben und drücken\n            Sie <kbd>Cmd/Strg + E</kbd>. Sie sollten einen Editor zum Schnellen Bearbeiten von CSS erscheinen sehen,\n            der die geltenden CSS-Regeln anzeigt. Das Schnelle Bearbeiten funktioniert genauso in Klassen- und\n            ID-Attributen. Sie können es zudem in LESS- und SCSS-Dateien nutzen.\n            \n            Sie können auf die selbe Weise neue Regeln erstellen. Klicken Sie in einen der <!-- <p> -->-Tags weiter\n            oben und drücken Sie <kbd>Cmd/Strg + E</kbd>. Es gibt noch keine Regeln dafür, aber Sie können den\n            \"Neue Regel\"-Button nutzen, um eine neue Regel für <!-- <p> --> hinzuzufügen.\n        </samp>\n\n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Ein Screenshot, der Schnelles Bearbeiten von CSS zeigt\" src=\"screenshots/quick-edit.png\" />\n        </a>\n\n        <p>\n            Sie können die selbe Tastenkombination nutzen, um andere Dinge auf die selbe Weise zu bearbeiten - wie\n            JavaScript-Funktionen, Farben und Animations-Timing-Funktionen - und wir fügen ständig mehr hinzu.\n        </p>\n        <p>\n            Im Augenblick können solche Editoren allerdings nicht verschachtelt werden. Sie können das\n            Schnelle Bearbeiten also nur nutzen, während der Cursor sich im Haupteditor befindet.\n        </p>\n\n        <!--\n            LIVE-VORSCHAU\n        -->\n        <h3>Vorschau auf HTML- und CSS-Änderungen live im Browser anzeigen</h3>\n        <p>\n            Sie kennen den \"Speichern/Neu laden-Tanz\", den wir seit Jahren aufführen? Der, in dem Sie\n            Änderungen in Ihrem Editor machen, Speichern drücken, zum Browser schalten und dann neu laden,\n            um schließlich das Ergebnis zu sehen? Mit Brackets müssen Sie diesen Tanz nicht aufführen.\n        </p>\n        <p>\n            Brackets öffnet eine <em>Live-Verbindung</em> zu Ihrem lokalen Browser und sendet HTML- und CSS-Updates,\n            während Sie tippen! Eventuell tun Sie etwas Ähnliches bereits heute mit browserbasierten Tools,\n            doch mit Brackets ist kein Kopieren und Einfügen des endgültigen Codes im Editor mehr nötig.\n            Ihr Code läuft im Browser, aber lebt in Ihrem Editor!\n        </p>\n\n        <h3>Hervorheben von HTML-Elementen und CSS-Regeln - live!</h3>\n        <p>\n            Brackets macht es Ihnen leicht, zu sehen, welche Auswirkungen Ihre Änderungen in HTML und CSS auf die\n            Seite haben werden. Wenn Ihr Cursor auf einer CSS-Regel platziert ist, hebt Brackets alle zugehörigen\n            Elemente im Browser hervor. Genauso wird Brackets beim Editieren einer HTML-Datei die entsprechenden\n            HTML-Elemente im Browser markieren.\n        </p>\n\n        <samp>\n            Falls Sie Google Chrome installiert haben, können Sie das selbst ausprobieren. Klicken Sie auf\n            das Blitz-Symbol oben rechts oder drücken Sie <kbd>Cmd/Strg + Alt + P</kbd>. Wenn die Live-Vorschau\n            für ein HTML-Dokument aktiviert ist, können alle verknüpften CSS-Dokumente in Echtzeit bearbeitet\n            werden. Das Symbol ändert die Farbe von grau nach gold, sobald Brackets eine Verbindung zu Ihrem\n            Browser hergestellt hat.\n\n            Platzieren Sie Ihren Cursor jetzt auf dem <!-- <img> -->-Tag oben. Sie sehen in Chrome eine blaue\n            Markierung, die um das Bild herum erscheint. Nutzen Sie nun <kbd>Cmd/Strg + E</kbd>, um die\n            definierten CSS-Regeln anzuzeigen.\n            Probieren Sie, die Stärke des Rahmens von 10px auf 20px zu ändern, oder ändern Sie die\n            Hintergrundfarbe von \"transparent\" zu \"hotpink\". Falls Sie Brackets und Ihren Browser nebeneinander\n            laufen haben, können Sie die Änderungen sofort in Ihrem Browser erkennen. Cool, was?\n        </samp>\n\n        <p class=\"note\">\n            Derzeit unterstützt Brackets die Live-Vorschau nur für HTML und CSS. Allerdings werden in der aktuellen\n            Version Änderungen an JavaScript-Dateien automatisch neu geladen, wenn Sie diese speichern. Wir arbeiten\n            momentan an der Unterstützung der Live-Vorschau für JavaScript.\n            Die Live-Vorschau ist außerdem nur mit Google Chrome möglich, doch wir hoffen, diese Funktionalität\n            zukünftig zu allen wichtigen Browsern hinzuzufügen.\n        </p>\n\n        <h3>Schnelle Farbansicht</h3>\n        <p>\n            Für die unter uns, die immer noch nicht die Farb-Äquivalente von HEX- und RGB-Werten kennen, macht es\n            Brackets einfach und schnell, exakt zu sehen, welche Farbe genutzt wird. Fahren Sie in HTML oder CSS\n            einfach über einen Farbwert oder -verlauf und Brackets wird Ihnen automatisch eine Vorschau davon\n            anzeigen. Das selbe gilt für Bilder: Platzieren Sie den Cursor im Brackets-Editor über einem Link zu\n            einem Bild und er wird ein Miniaturansicht von diesem Bild zeigen.\n        </p>\n\n        <samp>\n            Um die Schnelle Farbansicht selbst auszuprobieren, können Sie Ihren Cursor auf dem\n            <!-- <body> -->-Tag am Anfang dieses Dokuments platzieren und <kbd>Cmd/Strg + E</kbd> drücken, um einen\n            CSS-Schnell-Editor zu öffnen. Fahren Sie nun einfach mit dem Cursor über einen der Farbwerte im\n            CSS-Code. Sie können das auch mit Farbverläufen sehen, wenn Sie einen Schnell-Editor für den\n            <!-- <html> -->-Tag anzeigen lassen und über irgendeinen der \"background-image\"-Farbwerte fahren. Um\n            die Bildvorschau auszuprobieren, können Sie Ihren Cursor auf dem Screenshot-Link platzieren, den Sie\n            weiter oben in diesem Dokument finden.\n        </samp>\n\n        <h3>Sie benötigen etwas anderes? Probieren Sie es mit einer Erweiterung!</h3>\n        <p>\n            Zusätzlich zu all dem, was in Brackets eingebaut ist, hat unsere große und wachsende Community der\n            Erweiterungs-Entwickler hunderte Erweiterungen erstellt, die nützliche Funktionen bringen. Wenn\n            Sie etwas brauchen, was es nicht in Brackets gibt, ist es sehr wahrscheinlich, dass bereits jemand\n            eine Erweiterung dafür geschrieben hat. Um die Liste der verfügbaren Erweiterungen zu durchstöbern\n            oder zu durchsuchen nutzen Sie <strong>Datei > Erweiterungs-Verwaltung</strong> und klicken auf\n            den Tab \"Verfügbar\". Wenn Sie eine Erweiterung finden, die Sie nutzen wollen, klicken Sie einfach\n            auf den \"Installieren\"-Button daneben.\n        </p>\n\n        <!--\n            LASSEN SIE UNS WISSEN, WAS SIE DENKEN\n        -->\n        <h2>Machen Sie mit</h2>\n        <p>\n            Brackets ist ein Open-Source-Projekt. Web-Entwickler rund um die Welt helfen mit, einen besseren\n            Code-Editor zu bauen. Noch mehr erstellen Erweiterungen, die die Möglichkeiten von Brackets erweitern.\n            Lassen Sie uns wissen, was Sie denken, teilen Sie Ihre Ideen oder tragen\n            Sie direkt zu dem Projekt bei.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets Team-Blog</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets auf GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets Erweiterungs-Verzeichnis</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets Developer-Mailingliste</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets auf Twitter</a></li>\n            <li>Mit Brackets-Entwicklern via IRC in <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets auf Freenode</a> chatten</li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/de/Erste Schritte/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/el/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>ΞΕΚΙΝΩΝΤΑΣ ΜΕ ΤΟ BRACKETS</title>\n        <meta name=\"description\" content=\"An interactive getting started guide for Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>ΞΕΚΙΝΩΝΤΑΣ ΜΕ ΤΟ BRACKETS</h1>\n        <h2>Αυτός είναι ο οδηγός σας!</h2>\n        \n        <!--\n            MADE WITH <3 AND JAVASCRIPT\n        -->\n        \n        <p>\n            Καλώς ήρθατε σε μια πρώιμη προεπισκόπηση του Brackets, ένας νέος επεξεργαστής κειμένου ανοιχτού-κώδικα για τη νέα γενιά του\n            διαδικτύου. Είμαστε μεγάλοι οπαδοί των προτύπων και θέλουμε να φτιάξουμε καλύτερα εργαλεία για JavaScript, HTML και CSS\n            και σχετικές ανοιχτές τεχνολογίες του διαδικτύου. Αυτό είναι το ταπεινό μας ξεκίνημα.\n        </p>\n        \n        <!--\n            WHAT IS BRACKETS?\n        -->\n        <p>\n            <em>Το Brackets είναι ένας διαφορετικής μορφής επεξεργαστής κειμένου.</em>\n            Μία αξιοσημείωτη διαφορά είναι ότι αυτός ο επεξεργαστής κειμένου είναι γραμμένος σε JavaScript, HTML και CSS.\n            Αυτό σημαίνει ότι οι περισσότεροι από εσάς που χρησιμοποιούν το Brackets έχουν τις ικανότητες να τροποποιήσουν και να επεκτείνουν τον επεξεργαστή κειμένου.\n            Στην πραγματικότητα, χρησιμοποιούμε το Brackets κάθε μέρα για να φτιάξουμε το Brackets. Επίσης, έχει και κάποιες μοναδικές λειτουργίες όπως η Γρήγορα Επεξεργασία,\n            το Live Preview και άλλες που μπορεί να μην βρείτε σε άλλους επεξεργαστές.\n            Για να μάθετε περισσότερα για το πως να χρησιμοποιήσετε αυτές τις λειτουργίες, συνεχίστε το διάβασμα.\n        </p>\n        \n        \n        <h2>Δοκιμάζουμε μερικά νέα πράγματα</h2>\n        \n        <!--\n            THE RELATIONSHIP BETWEEN HTML, CSS AND JAVASCRIPT\n        -->\n        <h3>Γρήγορη Επεξεργασία για CSS και JavaScript</h3>\n        <p>\n            Όχι πια εναλλαγή μεταξύ των αρχείων και απόσπαση της προσοχής. Όταν επεξεργάζεστε HTML, χρησιμοποιήστε\n            την συντόμευση <kbd>Cmd/Ctrl + E</kbd> για να ανοίξετε έναν γρήγορο ενσωματωμένο επεξεργαστή που εμφανίζει το σχετικό CSS κώδικα.\n            Κάντε την αλλαγή στον κώδικα CSS, πατήστε <kbd>ESC</kbd> και είστε πίσω στην επεξεργασία HTML, ή απλά αφήστε τους\n            CSS κανόνες ανοιχτούς και αυτοί θα γίνουν μέρος του επεξεργαστή HTML. Αν πατήσεις <kbd>ESC</kbd> έξω από\n            έναν γρήγορο ενσωματωμένο επεξεργαστή, θα κρυφτούν όλα.\n        </p>\n        \n        <samp>\n            Θέλετε να το δείτε στην πράξη; Βάλε τον κέρσορα στο <!-- <samp> --> tag από πάνω και πάτησε\n            <kbd>Cmd/Ctrl + E</kbd>. Πρέπει να δεις ένα γρήγορο ενσωματωμένο επεξεργαστή να εμφανίζετε από πάνω, που δείχνει τον κανόνα CSS\n            που σχετίζετε με αυτό το tag. Η Γρήγορη Επεξεργασία λειτουργεί επίσης και για class και id ιδιότητες.\n\n            Μπορείτε να δημιουργήσετε και νέους κανόνες με τον ίδιο τρόπο. Κάντε κλικ σε ένα από τα tags <!-- <p> --> από πάνω και πατήστε\n            <kbd>Cmd/Ctrl + E</kbd>. Δεν υπάρχουν κανόνες για αυτό προς το παρόν, αλλά μπορείτε να πατήσετε το κουμπί Νέου Κανόνα\n            για να εισάγετε έναν νέο κανόνα για το <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"A screenshot showing CSS Quick Edit\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Μπορείς να χρησιμοποιήσεις την ίδια συντόμευση για κώδικα JavaScript για να δεις το σώμα μιας συνάρτησης με\n            το να τοποθετείς τον κέρσορα στο όνομα της συνάρτησης που καλείτε. Για τώρα οι γρήγοροι ενσωματωμένοι επεξεργαστές δεν μπορούν\n            να γίνουν ένθετοι, άρα μπορείς να χρησιμοποιήσεις την Γρήγορη Επεξεργασία μόνο όταν ο κέρσορας είναι μέσα σε έναν «πλήρους μεγέθους» επεξεργαστή.\n        </p>\n        \n        <!--\n            LIVE PREVIEW\n        -->\n        <h3>Προεπισκόπηση αλλαγών HTML και CSS ζωντανά στον browser</h3>\n        <p>\n            Ξέρεις αυτό το «χορό save/reload» που κάνουμε τόσα χρόνια; Αυτό που κάνεις αλλαγές στον\n            επεξεργαστή σου, πατάς αποθήκευση, γυρνάς στον browser και μετά κάνεις ανανέωση για να δεις επιτέλους το αποτέλεσμα;\n            Με το Brackets, δεν χρειάζεται να κάνεις αυτόν τον χορό.\n        </p>\n        <p>\n            Το Brackets θα ανοίξει μία <em>ζωντανή σύνδεση</em> στον τοπικό σου browser και θα στείλει τους ανανεωμένους κώδικες HTML και CSS καθώς εσύ\n            πληκτρολογείς! Μπορεί ήδη να κάνεις κάτι τέτοιο με εργαλεία που βασίζονται στον browser, αλλά με το Brackets\n            δεν υπάρχει ανάγκη να αντιγράφεις και να επικολλάς τον τελικό κώδικα πίσω στον επεξεργαστή. Ο κώδικας σου τρέχει στον\n            browser, αλλά ζει στον επεξεργαστή σου!\n        </p>\n        \n        <h3>Ζωντανή επισήμανση στοιχείων HTML και κανόνων CSS</h3>\n        <p>\n            Το Brackets κάνει εύκολο το να βλέπεις πως οι αλλαγές στους κώδικες HTML και CSS θα επηρεάσουν την σελίδα. Όταν ο κέρσορας\n            είναι σε έναν κανόνα CSS, το Brackets θα επισημάνει όλα τα στοιχεία στον browser που επηρεάζονται. Παρόμοια, όταν επεξεργάζεστε\n            ένα αρχείο HTML, το Brackets θα επισημάνει τα αντιστοιχούμενα στοιχεία HTML στον browser.\n        </p>\n        \n        <samp>\n            Αν έχεις εγκατεστημένο τον Google Chrome, μπορείς να το δοκιμάσεις μόνο σου. Κάνε κλικ στο εικονίδιο της αστραπής\n            στην πάνω δεξιά γωνία του παραθύρου του Brackets ή πατήστε <kbd>Cmd/Ctrl + Alt + P</kbd>. Όταν\n            το Live Preview ενεργοποιηθεί σε ένα έγγραφο HTML, όλα τα συνδεόμενα αρχεία CSS μπορούν να επεξεργασθούν σε πραγματικό χρόνο.\n            Το εικονίδιο θα αλλάξει από γκρι σε χρυσό όταν το Brackets δημιουργήσει την σύνδεση με τον browser.\n            \n            Τώρα, τοποθέτησε τον κέρσορα του στο από πάνω <!-- <img> --> tag. Παρατηρήστε την μπλε επισήμανση που εμφανίζετε\n            γύρω από την εικόνα στον Chrome. Έπειτα, χρησιμοποιήστε το <kbd>Cmd/Ctrl + E</kbd> για να ανοίξετε τους ορισμένους κανόνες CSS.\n            Δοκιμάστε να αλλάξετε το μέγεθος του πλαισίου από 1px σε 10px ή αλλάξτε το χρώμα του φόντου\n            από \"dimgray\" σε \"hotpink\". Αν έχετε το Brackets και τον browser σας να είναι δίπλα δίπλα, θα δείτε\n            τις αλλαγές να συμβαίνουν στιγμιαία στον. Αμάτο, έτσι;\n        </samp>\n                \n        <p class=\"note\">\n            Σήμερα, το Brackets υποστηρίζει το Live Preview μόνο για HTML και CSS. Όμως, στην τρέχουσα έκδοση, οι αλλαγές\n            σε αρχεία JavaScript ανανεώνονται αυτόματα όταν κάνετε αποθήκευση. Προς το παρόν δουλεύουμε τη υποστήριξη του Live Preview\n            για JavaScript. Επίσης, οι άμεσες προεπισκοπήσεις του Live Preview είναι δυνατές μόνο με τον Google Chrome, αλλά ελπίζουμε\n            να φέρουμε αυτήν την λειτουργία σε όλους τους μεγάλους browser στο μέλλον.\n        </p>\n                \n        <h3>Γρήγορη Προβολή</h3>\n        <p>\n            Για όσους από εμάς δεν απομνημονεύσει ακόμα τις αντιστοιχίες χρωμάτων για τις τιμές HEX ή RGB, το Brackets κάνει\n            γρήγορο και εύκολο το να βλέπεις ακριβώς ποιο χρώμα χρησιμοποιείται. Είτε σε CSS είτε σε HTML, απλά περάστε το ποντίκι πάνω από\n            τα τιμές του χρώματος ή τις διαβαθμίσεις χρώματος και το Brackets θα εμφανίσει μια προβολή αυτού του χρώματος ή της διαβάθμισης αυτόματα. Το\n            ίδιο συμβαίνει και με τις εικόνες: απλά περάστε πάνω από τον σύνδεσμο της εικόνας στο Brackets και αυτό θα προβάλει μια\n            μικρογραφία αυτής της εικόνας.\n        </p>\n        \n        <samp>\n            Για να δοκιμάσετε την Γρήγορη Προβολή από μόνος σας, βάλτε τον κέρσορα πάνω από το tag <!-- <body> --> στην κορυφή αυτού του\n            αρχείου και πατήστε <kbd>Cmd/Ctrl + E</kbd> για να ανοίξετε έναν γρήγορο επεξεργαστή CSS. Τώρα απλά πηγαίνετε το βελάκι πάνω από οποιοδήποτε\n            τιμή χρώματος μέσα στο αρχείο CSS. Επίσης, μπορείτε να το δείτε στη πράξη σε διαβαθμίσεις χρώματος με το ανοίξετε έναν γρήγορο επεξεργαστή CSS\n            στο tag <!-- <html> --> και πηγαίνοντας το βελάκι πάνω από οποιαδήποτε τιμή χρώματος του φόντου. Για να χρησιμοποιήσετε την προβολή\n            εικόνας, βάλτε τον κέρσορα πάνω από το screenshot που συμπεριλήφθηκε προηγουμένως σε αυτό το έγγραφο.\n        </samp>\n\n        <h3>Χρειάζεστε κάτι άλλο; Δοκιμάστε μία επέκταση!</h3>\n        <p>\n            Εκτός από όλα τα καλά που έχει το Brackets, η μεγάλη και αυξανόμενη κοινότητα των\n            developers επεκτάσεων έχει φτιάξει πάνω από εκατό επεκτάσεις που προσθέτουν χρήσιμες λειτουργίες. Αν υπάρχει\n            κάτι που χρειάζεστε και το Brackets δεν το προσφέρει, είναι πολύ πιθανό κάποιος να έχει φτιάξει μία επέκταση\n            για αυτό. Για να περιηγηθήτε ή να ψάξετε τη λίστα των διαθέσιμων επεκτάσεων, πηγαίντε <strong>Αρχείο > Διαχειρηστής\n            Επεκτάσεων</strong> και κάντε κλικ στην καρτέλα «Διαθέσιμες». Όταν βρείτε μια επέκταση που θέλετε, απλά κάντε κλικ\n            στο κουμπί της εγκτάστασης δίπλα του.\n        </p>\n        \n        <!--\n            LET US KNOW WHAT YOU THINK\n        -->\n        <h2>Συμμετάσχετε</h2>\n        <p>\n            Το Brackets είναι ένα project ανοιχτού κώδικα. Web developers από όλον τον κόσμο συνεισφέρουν για να φτιάξουν\n            έναν καλύτερο επεξεργαστή κώδικα. Πολλοί περισσότεροι φτιάχνουν επεκτάσεις που επεκτείνουν τις δυνατότητες του Brackets.\n            Πείτε μας τι πιστεύετε, μοιραστείτε τις ιδέες σας ή συνεισφέρετε άμεσα στο\n            project.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets Team Blog</a></li>\n            <li><a href=\"http://github.com/adobe/brackets\">Brackets στο GitHub</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki/Brackets-Extensions\">Επεκτάσεις Brackets</a></li>\n            <li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"http://groups.google.com/group/brackets-dev\">Brackets Developer Mailing List</a></li>\n            <li><a href=\"https://twitter.com/#!/brackets\">@Brackets στο Twitter</a></li>\n            <li>Συνομιλήστε με τους προγραμματιστές του Brackets στο IRC κανάλι #brackets στο Freenode (κυρίως στα Αγγλικά)</li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/el/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/es/Primeros Pasos/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>PRIMEROS PASOS CON BRACKETS</title>\n        <meta name=\"description\" content=\"Una guía interactiva de primeros pasos para Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>PRIMEROS PASOS CON BRACKETS</h1>\n        <h2>¡Ésta es tu guía!</h2>\n        \n        <!--\n            HECHO CON <3 Y JAVASCRIPT\n        -->\n\n        <p>\n            Bienvenido a Brackets, un nuevo editor de código abierto que entiende el diseño web. Es un editor de\n            código liviano y potente al mismo tiempo que incluye herramientas visuales dentro del mismo para\n            que puedas obtener la ayuda que necesites cuando la necesites.\n        </p>\n\n        <!--\n            ¿QUÉ ES BRACKETS?\n        -->\n        <p>\n            <em>Brackets es un editor diferente.</em>\n            Brackets tiene varias características únicas como la Edición rápida y la Vista previa dinámica y muchas\n            más que no vas a encontrar en otros editores. Además, Brackets está escrito en JavaScript, HTML y CSS.\n            Esto significa que la mayoría de quienes usan Brackets tienen las habilidades necesarias para modificar y\n            extender el editor. De hecho, nosotros usamos Brackets todos los días para desarrollar Brackets. Para\n            saber más sobre cómo utilizar estas características únicas, continúa leyendo.\n        </p>\n        \n        <!--\n            EMPIEZA CON TUS PROPIOS ARCHIVOS\n        -->\n        \n        <h3>Proyectos en Brackets</h3>\n        <p>\n            Para poder editar tu propio código en Brackets, puedes simplemente abrir la carpeta que contiene los\n            archivos. Brackets considera a la carpeta abierta como el \"proyecto\"; características como las Sugerencias\n            de código, la Vista previa dinámica y la Edición rápida solo utilizan los archivos contenidos dentro de\n            la carpeta actualmente abierta.\n        </p>\n        \n        <samp>\n            Una vez que estés listo para salir del proyecto de ejemplo y editar tu propio código, puedes usar el menú\n            despegable en la barra de la izquierda para cambiar de carpeta. En estos momentos, el menú despegable dice\n            \"Primeros Pasos\" - la cual es la carpeta que contiene el archivo que estás viendo en estos momentos. Haz\n            clic en el menú despegable y selecciona \"Abrir carpeta…\" para abrir tu carpeta.\n            También puedes usar el menú despegable para abrir las carpetas que abriste recientemente, incluyendo este\n            proyecto de ejemplo.\n        </samp>\n        \n        <h2>Estamos intentando algunas cosas nuevas</h2>\n        \n        <!--\n            LA RELACIÓN ENTRE HTML, CSS Y JAVASCRIPT\n        -->\n        <h3>Edición rápida de CSS y JavaScript</h3>\n        <p>\n            Se acabó aquello de estar saltando de documento en documento perdiendo de vista lo que estás haciendo. Mientras\n            estás escribiendo HTML, usa el atajo de teclado <kbd>Cmd/Ctrl + E</kbd> para abrir un editor rápido en\n            línea con todo el contenido CSS relacionado. Ajusta tu CSS y oprime <kbd>ESC</kbd> para volver a tu HTML,\n            o simplemente mantenga las reglas CSS abiertas para que pasen a formar parte de tu editor de HTML. Si\n            pulsas <kbd>ESC</kbd> fuera de un editor rápido, todos se cerrarán a la vez. La edición rápida también\n            funciona con archivos LESS y SCSS, incluyendo las reglas anidadas.\n        </p>\n\n        <samp>\n            ¿Quieres verlo funcionando? Coloca tu cursor sobre la etiqueta <!-- <samp> --> y oprime\n            <kbd>Cmd/Ctrl + E</kbd>. Deberías ver aparecer un editor rápido de CSS más arriba, mostrando la regla de\n            CSS que le afecta. La edición rápida funciona también en atributos de tipo clase e id. También puedes\n            utilizarlo en tus archivos LESS o SCSS.\n            \n            Puedes crear nuevas reglas de la misma manera. Haz clic en una de las etiquetas <!-- <p> --> de más arriba\n            y oprime <kbd>Cmd/Ctrl + E</kbd>. Todavía no hay reglas para ese elemento, pero puedes hacer clic en el\n            botón Nueva Regla para añadir una nueva regla a las etiquetas <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Una captura de pantalla con un Editor Rápido de CSS\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            También puedes usar el mismo atajo para editar otras cosas--como funciones en JavaScript, colores y\n            funciones de temporización de animaciones--y estamos añadiendo más y más continuamente.\n        </p>\n        <p>\n            Por ahora, no se pueden anidar editores en línea, por lo que sólo puedes usar la característica de\n            Edición Rápida cuando el cursor está en un editor \"completo\".\n        </p>\n\n        <!--\n            LIVE PREVIEW\n        -->\n        <h3>Visualiza cambios en archivos HTML y CSS en vivo en el navegador</h3>\n        <p>\n            ¿Conoces ese baile de \"guardar/recargar\" que llevamos años haciendo? ¿Ése en el que haces cambios en tu\n            editor, oprimes guardar, cambias al navegador y recargas para por fin poder ver el resultado? Con\n            Brackets, ya no tienes que hacerlo.\n        </p>\n        <p>\n            ¡Brackets abrirá una <em>conexión en vivo</em> con tu navegador local y le enviará los cambios en el\n            archivo HTML y CSS conforme escribas! Puede que ya estés haciendo algo parecido con las herramientas de\n            desarrollo del navegador, pero con Brackets ya no necesitas copiar y pegar el código final de vuelta a tu\n            editor. ¡Tu código se ejecuta en el navegador, pero vive en tu editor!\n        </p>\n        \n        <h3>Resaltado en vivo de elementos HTML y reglas CSS</h3>\n        <p>\n            Brackets te ayuda a ver cómo los cambios en HTML y CSS afectan a tu página. Cuando tu cursor se encuentre\n            sobre una regla de CSS, Brackets resaltará todos los elementos afectados en el navegador. Del mismo modo,\n            cuando estés editando un archivo HTML, Brackets también resaltará los elementos correspondientes en tu navegador.\n        </p>\n\n        <samp>\n            Si tienes instalado Google Chrome, puedes probarlo tú mismo. Haz clic sobre el icono del rayo de la\n            esquina superior derecha o presiona <kbd>Cmd/Ctrl + Alt + P</kbd>. Cuando la Vista previa dinámica está\n            funcionando en un documento HTML, todos los documentos CSS relacionados se pueden editar en tiempo real.\n            El icono pasará de gris a dorado cuando Brackets consiga establecer una conexión con tu navegador.\n            \n            Ahora, coloca el cursor sobre la etiqueta <!-- <img> --> que se encuentra un poco más arriba. Observa\n            cómo aparece el resaltado azul alrededor de la imagen en Chrome. Luego, utiliza <kbd>Cmd/Ctrl + E</kbd>\n            para abrir las reglas de CSS existentes. Intenta cambiar el tamaño del borde de 10px a 20px o el color\n            del fondo de \"transparent\" a \"hotpink\". Si Brackets y tu navegador están funcionando en paralelo, verás\n            los cambios reflejados de manera instantánea en tu navegador. Genial, ¿verdad?\n        </samp>\n        \n        <p class=\"note\">\n            Actualmente, Brackets sólo soporta Vista previa dinámica para HTML y CSS. Aún así, en la versión actual,\n            los cambios en archivos JavaScript son recargados automáticamente en el navegador cuando guardas. En estos\n            momentos estamos trabajando en el soporte de Vista previa dinámica para JavaScript. Las actualizaciones\n            automáticas sólo son posibles en Google Chrome, pero esperamos poder trasladar esta funcionalidad a todos\n            los grandes navegadores.\n        </p>\n        \n        <h3>Vista Rápida</h3>\n        <p>\n            Para aquellos que todavía no han memorizado las equivalencias de color entre Hex y RGB, Brackets permite\n            ver exactamente qué color se está utilizando rápida y fácilmente. Tanto en CSS como en HTML, simplemente\n            mueve el cursor sobre cualquier valor de color o gradiente y Brackets mostrará una previsualización del\n            mismo de manera automática. Lo mismo sirve para imágenes: simplemente pasa el cursor sobre la dirección\n            de una imagen en Brackets, y éste mostrará una vista en miniatura de la misma.\n        </p>\n        \n        <samp>\n            Para probar la previsualización tú mismo, coloca el cursor en la etiqueta <!-- <body> --> al principio de\n            este documento y oprime <kbd>Cmd/Ctrl + E</kbd> para abrir un editor CSS. Ahora, simplemente mueve el\n            cursor sobre cualquiera de los colores dentro del CSS. También puedes verlo funcionando en gradientes\n            abriendo un editor de CSS en la etiqueta <!-- <html> --> y pasando el cursor por cualquiera de los valores\n            para las imágenes de fondo. Para probar la vista previa de imágenes, coloca el cursor sobre la imagen\n            incluida antes en éste documento.\n        </samp>\n        \n        <h3>¿Necesitas algo más? ¡Prueba una extensión!</h3>\n        <p>\n            Además de todas las bondades naturales de Brackets, nuestra amplia y creciente comunidad de desarrolladores\n            de extensiones ha creado cientos de extensiones que añaden útiles funcionalidades. Si hay algo que\n            necesitas que Brackets no soporta, es bastante probable que alguien haya construido una extensión para\n            ello. Para navegar o buscar en la lista de extensiones disponibles, selecciona <strong>Archivo >\n            Gestionar extensiones...</strong> y haz clic en la pestaña \"Disponibles\". Cuando encuentres una que\n            quieras, simplemente presiona el botón \"Instalar\" a su derecha.\n        </p>\n        \n        <!--\n            HAZNOS SABER LO QUE PIENSAS\n        -->\n        <h2>Involúcrate</h2>\n        <p>\n            Brackets es un proyecto de código abierto. Desarrolladores web de todo el mundo están contribuyendo\n            a construir un mejor editor de código. Haznos saber lo que piensas, comparte tus ideas o contribuye\n            directamente al proyecto.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Blog del equipo de Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets en GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Registro de Extensiones de Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Wiki de Brackets</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Lista de correo de los desarrolladores de Brackets</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets en Twitter</a></li>\n            <li>Habla con los desarrolladores de Brackets por IRC en <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets en Freenode</a></li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/es/Primeros Pasos/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/fa-ir/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<title>شروع به کار با براکتس</title>\n<meta name=\"description\" content=\"تعاملی برای شروع به کار با براکتس.\">\n<link rel=\"stylesheet\" href=\"main.css\">\n</head>\n<body class=\"rtl\">\n<h1> شروع به کار با براکتس </h1>\n<h2>این راهنمایی برای شماست!</h2>\n<!--\nMADE WITH <3 AND JAVASCRIPT\n-->\n<p>\nبه براکتس، ویرایشگر کد منبع باز پیشرفته  که طراحی وب را درک می کند، خوش آمدید.  آن یک چیز سبک و در عین حال قدرتمند است .ویرایشگر کد که ابزارهای بصری را در درون ویرایش گر ترکیب میکند تا  به اندازه کافی  کمک دریافت کنید زمانی که آن را می خواهید.\n</p>\n<!--\nWHAT IS BRACKETS?\n-->\n<p>\n<em>براکتس یک نوع متفاوت از ویرایشگر می باشد.</em>\n براکتس برخی ویژگی های منحصر به فردی دارد مانند ویرایش سریع ،پیشنمایش زنده،و چیزها دیگری  که ممکن است شما آن را در ویرایشگر های دیگر پیدا نکنید. و براکتس با جاوا اسکریپت ،اچ تی ام ال و سی اس اس نوشته شده است. به این معنا که اکثر کاربران براکتس مهارت های لازم برای توسعه و گسترش ویرایشگر را دارند. در حقیقت ما هر روز از براکتس استفاده می کنیم تا براکتس را درست کنیم. برای یادگیری بیشتر درباره اینکه چطور از ویژه گی های کلیدی استفاده کنید بر روی آن مطالعه داشته باشید.\n</p>\n<!--\nGET STARTED WITH YOUR OWN FILES\n-->\n<h3>پروژه ها در براکتس</h3>\n<p>\nبه منظور ویرایش کد با استفاده از براکتس،شما می توانید فقط پوشه ای که شامل فایلها یتان می باشد را باز کنید. براکتس با پوشه جاری باز شده به عنوان یک \"پروژه\" رفتار می کند; ویژه گی نکات کد،پیشنمایش زنده و ویرایش سریع فقط  در پوشه جاری باز شده قابل استفاده است.\n</p>\n<samp>\nهنگامی که شما قصد خارج شدن از پروژه را دارید و کد را ویرایش می کنید، شما می توانید از منوی باز شوند در نوار کناری سمت چپ جهت تغییر پوشه ها استفاده کنید. اکنون،منوی باز شونده نشان می دهد \"Getting Started\" - پوشه ای است که فایلهای که اکنون در حال مشاهده آن هستید را شامل می شود. کلیک کنید بر روی منوی باز شونده و انتخاب کنید \"باز کردن پوشه\"را.\nبرای باز کردن پوشه خودتان.شما می توانید همچنین بعداً استفاده کنید جهت برگشتن به پوشه های که قبلا باز کرده اید شامل همین پروژه نمونه نیز می شود.\n</samp>\n<!--\nTHE RELATIONSHIP BETWEEN HTML, CSS AND JAVASCRIPT\n-->\n<h3>ویرایش سریع برای سی اس اس و جاوا اسکریپت</h3>\n<p>\nتعویض نه چندان زیاد بین اسناد و از دست دادن متن محتوا وقتی در حال ویرایش \"اچ تی ام ال\" هستید از کلید میانبر <kbd>Cmd/Ctrl + E</kbd> استفاده کنید تا یک ویرایشگر سطری سریع باز شود که تمام سی اس اس مربوطه را نشان دهد.\n یک کنترل برای سی اس اس تان بسازید و کلید <kbd>ESC</kbd> را فشار دهید تا به ویرایش اچ تی ام ال تان برگردید، یا فقط قواعد باز شده ی سی اس اس را ترک کنید در نتیجه آنها به بخشی از ویرایشگر اچ تی ام ال تان وارد خواهند شد.\n اگر شما کلید  <kbd>ESC</kbd> کناری از یک  ویرایشگر سطری سریع را فشار دهید آنها از بین می رود. ویرایش سریع همچنین قوانین تعریف شده در فایلهای LESS وSCSS که شامل قوانین تو در تو می باشند پیدا خواهد کرد.\n</p>\n\n\n<samp>\nWant to see it in action? Place your cursor on the <!-- <samp> --> tag above and press\n<kbd>Cmd/Ctrl + E</kbd>. You should see a CSS quick editor appear above, showing the CSS rule that\napplies to it. Quick Edit works in class and id attributes as well. You can use it with your\nLESS and SCSS files also.\nYou can create new rules the same way. Click in one of the <!-- <p> --> tags above and press\n<kbd>Cmd/Ctrl + E</kbd>. There are no rules for it right now, but you can click the New Rule\nbutton to add a new rule for <!-- <p> -->.\n</samp>\n\n\n<a href=\"screenshots/farsiquick-edit.png\">\n<img alt=\"A screenshot showing CSS Quick Edit\" src=\"screenshots/farsiquick-edit.png\" />\n</a>\n<p>\n شما می توانید استفاده کنید از میانبر ثابتی تا چیزهای دیگری را، همچنین ویرایش کنید مثل توابع در جاوااسکریپت، رنگها و توابع زمانی انیمیشن و بیش از هر زمانی استفاده می کنید.\n</p>\n<p>\nدر حال حاضر ویرایشگر های سطری نمی توانند تودرتو باشند بنابراین شما می توانید تنها ویرایشگر سریع را استفاده کنید زمانی که مکان نما در یک ویرایش تمام صفحه است.\n</p>\n<!--\nLIVE PREVIEW\n-->\n<h3>پیش نمایش تغیرات اچ تی ام ال و سی اس اس به صورت زنده در مرورگر</h3>\n<p>\nشما میدانید که ما فرآیند ذخیره /بازنگری را سالهاست انجام می دهیم در ویرایشتان جای را که تغیری ایجاد می کنید ذخیره می کنید و به مرورگر می روید و سپس نو سازی، سرانجام نتیجه را مشاهده کنید؟ با براکتس شما نیازی به آن کار ندارید.\n</p>\n<p>\nبراکتس یک ارتباط زنده با مرورگر محلی تان ایجاد می کند و یک نوع  بروز رسانی اچ تی ام ال و سی اس اس را قرار می دهد در داخل آن. شما همچنین ممکن است چیزهای را که امروزه انجام می دهید با  ابزار های مرورگرهای رایج، اما با براکتس شما نیازی به کپی و جایگزاری و در نهایت بازگشت به ویرایشگر کد ندارید. ویرایش کدهای تان اجرا خواهند شد در مرورگر ،اما  به صورت زنده .\nبراکتس یک <em>ارتباط زنده</em> با مرورگر محلی تان ایجاد می کند و یک نوع  بروز رسانی اچ تی ام ال و سی اس اس را قرار می دهد در داخل آن. شما همچنین ممکن است چیزهای را که امروزه انجام می دهید با  ابزار های مرورگرهای رایج، اما با براکتس شما نیازی به کپی و جایگزاری و در نهایت بازگشت به ویرایشگر کد ندارید. ویرایش کدهای تان اجرا خواهند شد در مرورگر ،اما  به صورت زنده .\n\n</p>\n<h3>هایلایت زنده عناصر اچ تی ام ال و قوانین سی اس اس</h3>\n<p>\nبراکتس تغیرات ایجاد شده در اچ تی ام ال و سی اس اس و چگونگی تاثیر آن بر روی صفحه را به آسانی نشان می دهد. زمانی که نشانگر ماوس بر روی یک قانون سی اس اس قرار می گیرد براکتس تمام عناصر تحت تاثیر را مشخص می کند. مشابهاً زمانی که یک فایل html در حال ویرایش است براکتس عناصر مربوط به اچ تی ام ال را در مرورگر مشخص می کند. امروزه براکتس فقط از پیشنمایش زنده برای اچ تی ام ال و سی اس اس پشتیبانی می کند. اگر چه در نسخه جاری تغییرات در فایلهای جاوااسکریپت به طور خودکار، زمانی که شما ذخیره می کنید مجدّداً بار گذاری می شود. ما در حال کارکردن بر روی پیشنمایش زنده جهت پشتیبانی از جاوا اسکریپت هستیم. پیشنمایش زنده تنها با گوگل کروم ممکن هست، اما ما امیدواریم این قابلیت درآینده برای همه عمده مرورگرهای به کار گرفته شود.\n</p>\n<samp>\nIf you have Google Chrome installed, you can try this out yourself. Click on the lightning bolt\nicon in the top right corner of your Brackets window or hit <kbd>Cmd/Ctrl + Alt + P</kbd>. When\nLive Preview is enabled on an HTML document, all linked CSS documents can be edited in real-time.\nThe icon will change from gray to gold when Brackets establishes a connection to your browser.\nNow, place your cursor on the <!-- <img> --> tag above. Notice the blue highlight that appears\naround the image in Chrome. Next, use <kbd>Cmd/Ctrl + E</kbd> to open up the defined CSS rules.\nTry changing the size of the border from 10px to 20px or change the background\ncolor from \"transparent\" to \"hotpink\". If you have Brackets and your browser running side-by-side, you\nwill see your changes instantly reflected in your browser. Cool, right?\n</samp>\n<p class=\"note\">\n\n</p>\n<h3>نمایش سریع</h3>\n<p>\nبرای برخی از ما که هنوز رنگ معادل برچسب های HEX ,rgbرا حفظ نیستیم، براکتس آن را سریع و راحت ایجاد میکند تا ببینی که دقیقاً کدام رنگ است که استفاده می شود. در هر سی اس اس به سادگی نشانگر ماوس را روی هر مقدار رنگ یا گرادینت در براکتس ببریم، یک پیش نمایش از رنگ/ گرادینت به صورت خودکار نمایش داده خواهد شد. به صورت مشابه برای تصاویر هم بکار می رود. به سادگی زمانی که نشانگر بر روی /آدرس تصویر در ویرایشگر براکتس قرار گیرد به عنوان پیش نمایش تصویر بند انگشتی از عکس نشان خواهد داد.\n</p>\n<samp>\nTo try out Quick View for yourself, place your cursor on the <!-- <body> --> tag at the top of this\ndocument and press <kbd>Cmd/Ctrl + E</kbd> to open a CSS quick editor. Now simply hover over any of the\ncolor values within the CSS. You can also see it in action on gradients by opening a CSS quick editor\non the <!-- <html> --> tag and hovering over any of the background image values. To try out the image\npreview, place your cursor over the screenshot image included earlier in this document.\n</samp>\n<h3>به چیز دیگری نیاز دارید? تلاش یک افزونه!</h3>\n<p>\nعلاوه بر تمام مزایای که در براکتس ایجاد شده است جامعه بزرگ و در حال رشد ما که متشکل از توسعه دهنده افزونه هاست هزاران افزونه برای اضافه شدن قابلیت های بسیار مفید ساخته شده است. اگر نیاز به موارد دیگری دارید که در براکتس ارائه نشده است به احتمال زیاد شخصی افزونه ای را برای آن ایجاد کرده است به فهرست و یا جستجو لیست افزونه های در دسترس رجوع کنید در پرونده ، مدیریت افزونه ها را انتخاب کنید و بر روی برگه در دسترس کلیک کنید. زمانی که افزونه ای را که می خواهید پیدا کردید کافیست بر روی \"نصب\" کلیک کنید و ادامه دهید.\n</p>\n<!--\nLET US KNOW WHAT YOU THINK\n-->\n<h2>درگیر شدن</h2>\n<p>\nبراکتس یک پروژه منبع باز می باشد. توسعه دهندگان وب در سرتاسر جهان در حال مشارکت جهت ساخت یک ویرایشگر بهتر می باشند. بسیاری در حال ساخت افزونه های هستند که توانایی براکتس را افزایش می دهد. آنچه را که به آن فکر می کنید را به ما اطلاع دهید ،ایده های خود را به اشتراک بگزارید یا به صورت مستقیم در پروژه مشارکت کنید.\n</p>\n<ul>\n<li><a href=\"http://brackets.io\">سایت اصلی براکتس</a></li>\n<li><a href=\"http://blog.brackets.io\">وبلاگ تیم براکتس</a></li>\n<li><a href=\"https://github.com/adobe/brackets\">براکتس در  GitHub</a></li>\n<li><a href=\"https://brackets-registry.aboutweb.com\">ثبت افزونه براکتس</a></li>\n<li><a href=\"https://github.com/adobe/brackets/wiki\">دانشنامه براکتس</a></li>\n<li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">فهرست ایمیل توسعه دهنده براکتس</a></li>\n<li><a href=\"https://twitter.com/brackets\">@براکتس در تویترr</a></li>\n<li>گفتگوه با توسعه دهندگان براکتس در IRC <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#براکتس در فرینود</a></li>\n</ul>\n</body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n\n<!-- Last translated for 558502495dddd25974af9f4487f00a35e47dcfec -->"
  },
  {
    "path": "samples/fa-ir/Getting Started/main.css",
    "content": "\n/*\nThis is the CSS rules for the Farsi|فارسیlanguage, which is written right to left.\nby pooya parsa dadashi || datamweb.\n*/\n\nhtml {\n    background-color: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #000;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}\n\n/* Starting custom rules */\n.rtl {\n    direction: rtl;\n    font-family: \"Tahoma\", Helvetica, Arial, sans-serif;\n    text-align: right;\n}\n"
  },
  {
    "path": "samples/fi/Aloitus/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>BRACKETSIN KÄYTÖN ALOITUS</title>\n        <meta name=\"description\" content=\"Vuorovaikutteinen aloitusopas Bracketsille.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>BRACKETSIN KÄYTÖN ALOITUS</h1>\n        <h2>Tämä on oppaasi!</h2>\n        \n        <!--\n            TEHTY <3:LLA JA JAVASCRIPTILLÄ\n        -->\n        \n        <p>\n            Tervetuloa käyttämään Bracketsia, nykyaikaista, avoimen lähdekoodin koodieditoria, joka ymmärtää\n            web-suunnittelun. Se on kevyt mutta silti tehokas: koodieditori, joka sulauttaa visuaaliset työkalut suoraan\n            editoriin, niin että saat oikean määrän apua silloin, kun haluat sitä.\n        </p>\n        \n        <!--\n            MIKÄ BRACKETS ON?\n        -->\n        <p>\n            <em>Brackets on erityyppinen editori.</em>\n            Bracketsissa on joitakin ainutlaatuisia ominaisuuksia, kuten pikamuokkaus, reaaliaikainen esikatselu ja\n            muita, joita et voi löytää muista editoreista. Lisäksi Brackets on kirjoitettu JavaSciptillä, HTML:llä ja\n            CSS:llä. Se tarkoittaa, että useimmilla Bracketsin käyttäjistä on riittävät taidot muokata ja laajentaa\n            editoria. Itse asiassa käytämme Bracketsia joka päivä sen itsensä kehitykseen. Oppiaksesi lisää siitä,\n            kuinka käyttää avainominaisuuksia, jatka lukemista.\n        </p>\n        \n        <!--\n            ALOITUS OMIEN TIEDOSTOJESI KANSSA\n        -->\n        \n        <h3>Projektit Bracketsissa</h3>\n        <p>\n            Muokataksesi omaa koodiasi Bracketsia käyttäen voit vain avata tiedostosi sisältävän kansion. Brackets pitää\n            nykyistä avointa kansiota ”projektina”; ominaisuudet, kuten koodivihjeet, esikatselu ja pikamuokkaus,\n            käyttävät vain parhaillaan avoinna olevan kansion tiedostoja.\n        </p>\n        \n        <samp>\n            Heti kun olet valmis luopumaan tästä näyteprojektista ja muokkaamaan omaa koodiasi, voit käyttää vasemman\n            sivupalkin pudotusvalikkoa kansioiden vaihtamiseen. Juuri nyt pudotusvalikossa lukee ”Aloitus”. Tämä on\n            kansio, joka sisältää tiedoston, jota tarkastelet juuri nyt. Avaa oma kansiosi napsauttamalla\n            pudotusvalikkoa ja valitsemalla ”Avaa kansio…”.\n            Voit käyttää pudotusvalikkoa myös myöhemmin vaihtaaksesi takaisin kansioihin, jotka olet avannut aiemmin,\n            sisältäen tämän näyteprojektin.\n        </samp>\n        \n        <!--\n            YHTEYS HTML:N, CSS:N JA JAVASCRIPTIN VÄLILLÄ\n        -->\n        <h3>Pikamuokkaus CSS:lle ja JavaScriptille</h3>\n        <p>\n            Ei lisää dokumenttien välillä vaihtamista tai asiayhteyden hukkaamista. Muokatessasi HTML:ää käytä\n            näppäinyhdistelmää <kbd>Cmd/Ctrl + E</kbd> avataksesi upotetun pikaeditorin, joka näyttää kaiken tiedostoon\n            liittyvän CSS:n. Muokkaa CSS:ääsi, paina <kbd>ESC</kbd>-näppäintä ja olet taas muokkaamassa HTML:ää, tai\n            yksinkertaisesti jätä CSS-säännöt auki, ja niistä tulee osa HTML-editoriasi. Jos painat\n            <kbd>ESC</kbd>-näppäintä pikaeditorin ulkopuolella, ne kaikki sulkeutuvat. Pikaeditori löytää myös LESS- ja\n            SCSS-tiedostoissa määritellyt säännöt, sisältäen sisäkkäiset sellaiset.\n        </p>\n        \n        <samp>\n            Haluatko nähdä sen toiminnassa? Aseta kohdistin alla olevaan <!-- <samp> --> -tägiin ja paina\n            <kbd>Cmd/Ctrl + E</kbd>. Sinun pitäisi nähdä, kun CSS-pikaeditori ilmestyy alapuolelle näyttäen CSS-säännön,\n            joka pätee siihen. Pikamuokkaus toimii toki myös class- ja id-attribuuttien kanssa. Voit käyttää sitä myös\n            LESS- ja SCSS-tiedostojesi kanssa.\n            \n            Voit luoda uusia sääntöjä samalla tavalla. Napsauta yhtä alaosan <!-- <p> --> -tägeistä ja paina\n            <kbd>Cmd/Ctrl + E</kbd>. Sille ei ole sääntöjä juuri nyt, mutta voit napsauttaa Uusi sääntö -painiketta\n            lisätäksesi uuden säännön <!-- <p> --> -tägeille.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Kuvankaappaus, jossa näkyy CSS:n pikamuokkaus\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Voit käyttää samaa näppäinyhdistelmää muokataksesi myös muita asioita - kuten JavaScriptin funktioita,\n            värejä ja animaatioiden ajoitusfunktioita - ja me lisäämme koko ajan yhä enemmän ominaisuuksia.\n        </p>\n        <p>\n            Toistaiseksi sisäeditorit eivät voi olla sisäkkäin, joten voit käyttää pikamuokkausta vain silloin, kun\n            kohdistin on täyskokoisessa editorissa.\n        </p>\n        \n        <!--\n            ESIKATSELU\n        -->\n        <h3>Esikatsele HTML:n ja CSS:n muutoksia reaaliaikaisesti selaimessa</h3>\n        <p>\n            Tiedäthän sen ”tallenna ja päivitä -tanssin”, jota olemme harrastaneet vuosia? Se, jossa tehdään muutoksia\n            editorissa, painetaan tallenna, vaihdetaan selaimeen ja sitten päivitetään, jotta tulos tulee viimein\n            näkyville? Bracketsissa sinun ei tarvitse harrastaa tätä tanssia.\n        </p>\n        <p>\n            Brackets avaa <em>reaaliaikaisen yhteyden</em> paikalliseen selaimeesi ja vie HTML:n CSS:n päivitykset\n            samalla kun kirjoitat! Saatat olla jo tehnyt jotakin tämän kaltaista selainpohjaisilla työkaluilla, mutta\n            Bracketsin kanssa ei tarvitse kopioida ja liittää lopullista koodia takaisin editoriin. Koodisi suoritetaan\n            selaimessasi, mutta se sijaitsee editorissasi!\n        </p>\n        \n        <h3>Korosta HTML-elementtejä ja CSS-sääntöjä reaaliaikaisesti</h3>\n        <p>\n            Brackets tekee helpoksi nähdä, kuinka muutoksesi HTML:ssä ja CSS:ssä vaikuttavat sivuun. Kun kohdistin on\n            CSS-säännöllä, Brackets korostaa kaikki siihen liittyvät elementit selaimessa. Samalla tavoin muokattaessa\n            HTML-tiedostoa Brackets korostaa vastaavat HTML-elementit selaimessa.\n        </p>\n        \n        <samp>\n            Jos sinulla on Google Chrome asennettuna, voit kokeilla tätä itse. Napsauta Brackets-ikkunan oikeassa\n            yläkulmassa sijaitsevaa salamakuvaketta tai paina <kbd>Cmd/Ctrl + Alt + P</kbd>. Kun esikatselu on käytössä\n            HTML-dokumentissa, kaikkia linkitettyjä CSS-dokumentteja voi muokata reaaliajassa. Kuvake muuttuu harmaasta\n            kultaiseksi, kun Brackets muodostaa yhteyden selaimeesi.\n            \n            Aseta kohdistin nyt yläpuolella olevaan <!-- <img> --> -tägiin. Huomaa sininen korostus, joka ilmestyy kuvan\n            ympärille Chromessa. Käytä seuraavaksi <kbd>Cmd/Ctrl + E</kbd> -näppäinyhdistelmää avataksesi määritellyt\n            CSS-säännöt. Yritä muuttaa reunaviivan kokoa arvosta 10px arvoon 20px tai vaihtaa taustaväriä arvosta\n            ”transparent” arvoon ”hotpink”. Jos Brackets ja selain ovat näytölläsi vierekkäin, näet muutosten\n            heijastuvan välittömästi selaimeesi. Siistiä, eikö?\n        </samp>\n        \n        <p class=\"note\">\n            Nykyisellään Brackets tukee esikatselua vain HTML:lle ja CSS:lle. Kuitenkin jo nykyisessä versiossa\n            muutokset JavaScript-tiedostoihin päivitetään automaattisesti tallentaessasi tiedoston. Työskentelemme\n            parhaillaan esikatselun tuomiseksi JavaScriptille. Esikatselu on myös mahdollista vain Google Chromella,\n            mutta toivomme pystyvämme tuomaan tämän toiminnon kaikille pääselaimille tulevaisuudessa.\n        </p>\n        \n        <h3>Pikanäkymä</h3>\n        <p>\n            Niille meistä, jotka eivät vielä osaa ulkoa värien vastineita HEX- tai RGB-arvoille, Brackets tekee nopeaksi\n            ja helpoksi nähdä täsmälleen, mitä väriä on käyttämässä. Kerta kaikkiaan osoita mitä tahansa väriarvoa tai\n            liukuväriä joko CSS:ssä tai HTML:ssä, ja Brackets näyttää esikatselun tästä väristä tai liukuväristä\n            automaattisesti. Sama tulee kuviin: osoita yksinkertaisesti kuvalinkkiä Brackets-editorissa ja se näyttää\n            pienen esikatselukuvan tästä kuvasta.\n        </p>\n        \n        <samp>\n            Kokeile pikanäkymää itse asettamalla kohdistimesi tämän dokumentin yläosassa sijaitsevaan <!-- <body> -->\n            -tägiin ja painalla <kbd>Cmd/Ctrl + E</kbd> avataksesi CSS-pikaeditorin. Nyt yksinkertaisesti osoita mitä\n            tahansa CSS:n väriarvoista. Voit myös nähdä sen toiminnassa liukuväreissä avaamalla CSS-pikaeditorin\n            <!-- <html> --> -tägille ja osoittamalla mitä tahansa taustakuva-arvoista. Kokeile kuvan esikatselua\n            asettamalla osoittimesi tässä dokumentissa aiemmin esiintyneen kuvankaappauskuvan päälle.\n        </samp>\n        \n        <h3>Tarvitsetko jotakin muuta? Kokeile laajennusta!</h3>\n        <p>\n            Sen kaiken hyvän lisäksi, jota Bracketsiin on rakennettu, on suuri ja kasvava laajennuskehittäjien\n            yhteisömme tehnyt satoja laajennuksia, jotka lisäävät hyödyllisiä toimintoja. Jos on jotakin, jota tarvitset\n            ja jota Brackets ei tarjoa, enemmän kuin todennäköisesti joku on tehnyt laajennuksen siihen. Selaa\n            saatavilla olevien laajennusten luetteloa tai hae siitä valitsemalla <strong>Tiedosto &gt; Laajennusten\n            hallinta</strong> ja napsauttamalla ”Saatavilla”-välilehteä. Kun löydät haluamasi laajennuksen, napsauta\n            vain ”Asenna”-painiketta sen vierestä.\n        </p>\n        \n        <!--\n            KERRO MEILLE, MITÄ AJATTELET\n        -->\n        <h2>Lähde mukaan</h2>\n        <p>\n            Brackets on avoimen lähdekoodin projekti. Web-kehittäjät ympäri maailmaa osallistuvat paremman koodieditorin\n            kehittämiseen. Vieläkin enemmän kehitetään laajennuksia, jotka laajentavat Bracketsin kykyjä. Kerro meille,\n            mitä ajattelet. Jaa ideasi tai osallistu suoraan projektiin.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets-tiimin blogi</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets GitHubissa</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets-laajennusten rekisteri</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets-wiki</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets-kehittäjien postituslista</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets Twitterissä</a></li>\n            <li>Rupattele Brackets-kehittäjien kanssa IRC:ssä: <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets Freenodessa</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/fi/Aloitus/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/fr/Premiers pas/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>PREMIERS PAS AVEC BRACKETS</title>\n        <meta name=\"description\" content=\"An interactive getting started guide for Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>PREMIERS PAS AVEC BRACKETS</h1>\n        <h2>Suivez le guide !</h2>\n        \n        <!--\n            CRÉÉ AVEC <3 ET JAVASCRIPT\n        -->\n        \n        <p>\n            Bienvenue dans Brackets, un éditeur de code open source qui comprend et facilite la conception de sites web. Il s’agit d’un éditeur à la fois léger et puissant qui intègre des outils visuels directement dans son interface, de sorte que chaque opération peut devenir un véritable jeu d’enfant.\n        </p>\n        \n        <!--\n            QU'EST-CE QUE BRACKETS?\n        -->\n        <p>\n            <em>Brackets se distingue des éditeurs traditionnels,</em>\n            notamment par ses fonctionnalités uniques, comme l’Edition rapide ou l’Aperçu en direct, que vous ne trouverez pas forcément dans d’autres éditeurs. Cerise sur le gâteau, Brackets est écrit en JavaScript, en HTML et en CSS. Autrement dit, la grande majorité des utilisateurs de Brackets est capable de modifier et d’étendre l’éditeur. En fait, nous utilisons Brackets tous les jours pour son propre développement. Pour en savoir plus sur l’utilisation de ses fonctionnalités centrales, poursuivez votre lecture.\n        </p>\n        \n        <!--\n            COMMENCER AVEC VOS PROPRES FICHIERS\n        -->\n        \n        <h3>Projets Brackets</h3>\n        <p>\n            Pour éditer votre propre code à l’aide de l’application Brackets, il vous suffit d’ouvrir le dossier contenant vos fichiers.\n            Brackets traite le dossier ouvert en tant que « projet » ; ainsi, les fonctionnalités Indicateurs de code, Aperçu en direct ou encore Edition rapide s’appliquent uniquement aux fichiers du dossier ouvert.\n        </p>\n        \n        <samp>\n            Si vous vous sentez prêt à franchir le cap et à éditer votre propre code, fermez cet exemple de projet et utilisez la liste déroulante de la barre latérale de gauche pour changer de dossier. Pour le moment, la liste déroulante s’intitule « Prise en main », ce qui correspond au dossier dans lequel se trouve le fichier fictif sur lequel vous vous exercez actuellement. Cliquez sur la liste déroulante et sélectionnez « Ouvrir un dossier… » pour accéder à votre propre dossier.\n            Par la suite, vous pourrez tout à fait revenir aux dossiers précédemment ouverts, y compris cet exemple de projet, grâce à cette même liste déroulante.\n        </samp>\n        \n        <!--\n            LA RELATION ENTRE HTML, CSS, ET JAVASCRIPT\n        -->\n        <h3>Edition rapide des codes CSS et JavaScript</h3>\n        <p>\n            Vous ne risquez plus de perdre de vue le contexte en passant d’un document à un autre. Lorsque vous modifiez un fichier HTML, utilisez le raccourci <kbd>Cmd/Ctrl + E</kbd> pour ouvrir un éditeur rapide intégré qui affiche l’ensemble du code CSS associé.\n            Peaufinez votre CSS, puis appuyez sur <kbd>Echap</kbd> pour revenir au format HTML, ou laissez simplement les règles CSS ouvertes afin qu’elles deviennent partie intégrante de l’éditeur HTML. Si vous appuyez sur <kbd>Echap</kbd> en dehors d’un éditeur intégré rapide, tous les éditeurs sont réduits. La fonction Edition rapide détecte également les règles définies dans les fichiers LESS et SCSS, y compris les règles imbriquées.\n        </p>\n\n        <samp>\n            Une petite démonstration ? Placez le curseur de la souris sur la balise <!-- <samp> --> et tapez <kbd>Cmd/Ctrl + E</kbd>. Un éditeur rapide CSS apparaît en superposition, avec la règle CSS applicable. La fonction Edition rapide est également utilisable pour les attributs de classe et d’ID. Vous pouvez aussi vous en servir sur vos fichiers LESS et SCSS.\n            \n            Vous pouvez créer de nouvelles règles en procédant de la même manière. Cliquez sur l’une des balises <!-- <p> --> en haut du document et appuyez sur <kbd>Cmd/Ctrl + E</kbd>. Il n’existe aucune règle associée pour le moment, mais vous pouvez cliquer sur le bouton Nouvelle règle afin d’ajouter une règle pour <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Capture d’écran de la fonction Edition rapide CSS\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Vous pouvez utiliser le même raccourci pour éditer d’autres éléments, comme les fonctions dans JavaScript, les couleurs ou les fonctions de temporisation d’animation ; nous ajoutons sans cesse des nouveautés.\n        </p>\n        <p>\n            Les éditeurs intégrés ne peuvent pas encore être imbriqués. Vous ne pouvez donc utiliser la fonction Edition rapide que lorsque le curseur se trouve dans un éditeur « plein écran ».\n        </p>\n        \n        <!--\n            APERÇU EN DIRECT\n        -->\n        <h3>Affichage des modifications HTML et CSS en direct dans le navigateur</h3>\n        <p>\n            Depuis des années, nous pratiquons tous la fameuse technique « Enregistrer/Actualiser » : apporter des modifications dans l’éditeur, enregistrer, basculer vers le navigateur, puis actualiser la page pour voir le résultat.\n            Avec Brackets, cette longue procédure appartient au passé.\n        </p>\n        <p>\n            Brackets se connecte <em>en direct</em> à votre navigateur local et transmet vos mises à jour au fur et à mesure que vous les appliquez au code HTML et CSS. Certes, il existe des outils accessibles directement depuis le navigateur qui permettent d’obtenir un résultat similaire mais, avec Brackets, vous n’avez pas besoin de copier et coller à nouveau le code final dans l’éditeur. Le navigateur lit votre code, mais c’est l’éditeur qui le fait vivre !\n        </p>\n        \n        <h3>Mise en surbrillance en direct des éléments HTML et règles CSS</h3>\n        <p>\n            Avec Brackets, vous pouvez facilement visualiser les effets des modifications du code HTML et CSS sur la page. Lorsque vous placez le curseur sur une règle CSS, Brackets surligne tous les éléments concernés dans le navigateur. De même, lorsque vous éditez un fichier HTML, Brackets surligne les éléments HTML correspondants dans le navigateur.\n        </p>\n        \n        <samp>\n            Si vous avez installé Google Chrome, vous pouvez dès maintenant tester cette fonctionnalité. Cliquez sur l’icône représentant un éclair en haut à droite de la fenêtre Brackets ou utilisez la combinaison <kbd>Cmd/Ctrl + Alt + P</kbd>. Lorsque le module Aperçu en direct est activé sur un document HTML, tous les documents CSS associés peuvent être modifiés en temps réel.\n            L’icône passe du gris au doré une fois que Brackets a établi la connexion à votre navigateur.\n            \n            Placez maintenant le curseur sur la balise <!-- <img> -->. Vous constatez qu’une surbrillance bleue apparaît tout autour de l’image dans Chrome. Utilisez ensuite la combinaison <kbd>Cmd/Ctrl + E</kbd> pour ouvrir les règles CSS définies.\n            Essayez de faire passer l’épaisseur de la bordure de 10 px à 20 px, ou de remplacer la couleur d’arrière-plan « transparent » par « hotpink ». Si Brackets et votre navigateur s’exécutent côte à côte, ce dernier affiche immédiatement les modifications. Plutôt sympathique, non ?\n        </samp>\n        \n        <p class=\"note\">\n            A l’heure actuelle, le module Aperçu en direct de Brackets ne fonctionne que pour le code HTML et CSS. Cependant, dans cette version, les modifications apportées aux fichiers JavaScript sont automatiquement rechargées lorsque vous enregistrez. Nous travaillons activement à la prise en charge du module Aperçu en direct pour le langage JavaScript. La fonctionnalité Aperçu en direct n’est disponible qu’avec Google Chrome, mais nous souhaitons à l’avenir la déployer sur l’ensemble des navigateurs.\n        </p>\n        \n        <h3>Affichage rapide</h3>\n        <p>\n            Pour ceux d’entre nous qui n’ont pas encore mémorisé les équivalents en couleur des valeurs HEX ou RVB, Brackets permet d’afficher rapidement et facilement la couleur utilisée. Dans le code CSS ou HTML, placez simplement le curseur sur une valeur colorimétrique ou un dégradé, et Brackets affiche automatiquement un aperçu de la couleur ou du dégradé en question. Procédez de même pour les images : placez simplement le curseur sur le lien d’une image dans l’éditeur Brackets pour en afficher une miniature.\n        </p>\n        \n        <samp>\n            Testez la fonction Affichage rapide par vous-même : placez le curseur sur la balise <!-- <body> --> en haut du document et appuyez sur <kbd>Cmd/Ctrl + E</kbd> pour ouvrir un éditeur rapide CSS. A présent, placez le curseur sur l’une des valeurs de couleur dans le code CSS. Vous pouvez également tester cette fonctionnalité sur un dégradé : ouvrez un éditeur rapide CSS sur la balise <!-- <html> -->, puis passez le curseur sur l’une des valeurs de l’image d’arrière-plan. Pour essayer l’aperçu avec une image, placez le curseur sur la capture d’écran insérée plus haut dans le document.\n        </samp>\n        \n        <h3>Vous en voulez plus ? Jetez un œil du côté des extensions !</h3>\n        <p>\n            En plus de tous les atouts déjà intégrés à Brackets, notre communauté de développeurs, qui ne cesse de s’agrandir, a mis au point des centaines d’extensions qui offrent des fonctionnalités très pratiques. Si vous avez besoin d’une fonction qui ne se trouve pas dans Brackets, il est fort probable qu’un utilisateur ait créé l’extension qu’il vous faut. Pour parcourir la liste des extensions disponibles ou en rechercher une en particulier, cliquez sur <strong>Fichier &gt; Gestionnaire d’extensions</strong>, puis ouvrez l’onglet « Disponible ». Lorsque vous trouvez l’extension qui vous convient, il vous suffit de cliquer sur le bouton Installer correspondant.\n        </p>\n        \n        <!--\n            DITES-NOUS CE QUE VOUS EN PENSEZ\n        -->\n        <h2>Participer</h2>\n        <p>\n            Brackets est un projet open source. Des développeurs web du monde entier participent à l’amélioration de l’éditeur de code. Nombreux sont ceux qui créent des extensions afin de développer les possibilités de Brackets.\n            Donnez-nous votre avis, partagez vos idées ou participez directement au projet.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Blog de l’équipe Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets sur GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Registre des extensions Brackets</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Wiki Brackets</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Liste de diffusion des développeurs Brackets</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets on Twitter</a></li>\n            <li>Discutez avec les développeurs de Brackets via IRC sur <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets on Freenode</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/fr/Premiers pas/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/id/Memulai/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>MEMULAI DENGAN BRACKETS</title>\n        <meta name=\"description\" content=\"An interactive getting started guide for Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>MEMULAI DENGAN BRACKETS</h1>\n        <h2>Inilah panduan Anda!</h2>\n        \n        <!--\n            DIBUAT DENGAN <3 DAN JAVASCRIPT\n        -->\n        \n        <p>\n            Selamat datang di Brackets, sebuah editor modern dan open-source yang dirancang untuk mendesain web.\n            Ringan namun bertenaga, editor ini memadukan perangkat visual ke dalamnya sehingga Anda memiliki\n            perangkat yang tepat ketika Anda membutuhkannya.\n        </p>\n        \n        <!--\n            APA ITU BRACKETS?\n        -->\n        <p>\n            <em>Brackets berbeda dari editor lainnya.</em>\n            Brackets memiliki fitur-fitur yang unik seperti Edit Cepat, Tinjauan Langsung dan berbagai macam fitur\n            yang mungkin tidak Anda temui di editor lain. Brackets dikembangkan dengan JavaScript, HTML and CSS.\n            Ini berarti Anda, para pengguna Brackets sudah memiliki kemampuan untuk memodifikasi dan memperluas editor\n            ini. Bahkan, kami menggunakan Brackets setiap hari dalam pengembangan Brackets. Untuk mempelajari cara\n            penggunaan fitur-fitur utama yang ada di dalam Brackets, baca lebih lanjut.\n        </p>\n        \n        <!--\n            MEMULAI DENGAN PEKERJAAN ANDA SENDIRI\n        -->\n        \n        <h3>Proyek di dalam Brackets</h3>\n        <p>\n            Untuk mengedit kode Anda sendiri dengan menggunakan Brackets, Anda bisa langsung membuka folder yang\n            berisi file-file Anda. Brackets memperlakukan folder yang sedang dibuka sebagai \"proyek\"; fitur-fitur\n            seperti Petunjuk Kode, Tinjauan Langsung and Edit Cepat hanya menggunakan file-file yang ada di dalam\n            folder yang sedang dibuka.\n        </p>\n        \n        <samp>\n            Saat Anda siap untuk keluar dari proyek contoh ini dan mengedit kode Anda sendiri, Anda dapat menggunakan\n            dropdown yang ada di sisi kiri sidebar untuk mengganti folder. Saat ini, dropdown Anda menunjukkan\n            \"Memulai\"- itu adalah folder yang berisi file yang Anda lihat saat ini. Klik pada dropdown dan\n            pilih \"Buka Folder…\" untuk membuka folder Anda sendiri.\n            Anda juga bisa menggunakan dropdown nanti untuk berpindah ke folder yang telah Anda buka sebelumnya,\n            termasuk proyek contoh ini.\n        </samp>\n        \n        <!--\n            HTML, CSS DAN JAVASCRIPT SALING BERHUBUNGAN\n        -->\n        <h3>Edit Cepat untuk CSS dan JavaScript</h3>\n        <p>\n            Tidak perlu lagi repot-repot berpindah dari satu dokumen ke dokumen lainnya. Ketika mengedit HTML,\n            gunakan pintasan <kbd>Cmd/Ctrl + E</kbd> untuk membuka Edit Cepat yang menampilkan semua CSS yang sesuai.\n            Ubah CSS Anda, kemudian tekan <kbd>ESC</kbd> dan Anda kembali lagi mengedit HTML, atau tetap buka CSS Anda\n            dan kotak tersebut akan menjadi satu dengan editor Anda. Jika Anda menekan <kbd>ESC</kbd> diluar kotak Edit\n            Cepat, semuanya akan langsung disembunyikan. Edit Cepat juga akan menemukan aturan dalam file LESS dan\n            SCSS, termasuk aturan bersarang.\n        </p>\n        \n        <samp>\n            Mau lihat cara kerjanya? Tempatkan kursor Anda di tag <!-- <samp> --> di atas kemudian tekan\n            <kbd>Cmd/Ctrl + E</kbd>. Anda akan melihat editor cepat CSS muncul, menunjukkan aturan CSS yang sesuai.\n            Edit Cepat juga dapat digunakan untuk atribut class dan id. Anda juga bisa menggunakannya dengan file LESS\n            dan SCSS.\n            \n            Anda bisa membuat aturan baru dengan cara yang sama. Klik salah satu tag <!-- <p> -->\n            di atas dan tekan <kbd>Cmd/Ctrl + E</kbd>. Saat ini tidak ada aturan untuk tag itu, namun\n            Anda bisa klik tombol Aturan Baru untuk menambahkan aturan untuk <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Screenshot menunjukkan Edit Cepat CSS\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Anda juga bisa menggunakan pintasan yang sama untuk mengedit hal-hal lainnya - seperti fungsi di\n            JavaScript, warna, dan fungsi animasi - dan kami terus menambahkan fitur lain setiap saat.\n        </p>\n\n        <p>\n            Saat ini, editor inline tidak dapat disarangkan, sehingga Anda hanya dapat menggunakan Edit Cepat ketika\n            berada dalam mode \"ukuran penuh\".\n        </p>\n        \n        <!--\n            PREVIEW LANGSUNG\n        -->\n        <h3>Tinjau perubahan HTML dan CSS secara langsung di peramban</h3>\n        <p>\n            Anda tahu mengenai teknik \"simpan/muat ulang\" yang sering kita lakukan? Dimana kita mengubah file,\n            kemudian kita simpan, lalu pindah ke peramban dan memuat ulang halaman untuk melihat hasilnya? Dengan\n            Brackets, Anda tidak perlu melakukannya lagi.\n        </p>\n        <p>\n            Brackets akan membuka <em>sambungan langsung</em> ke peramban Anda dan memperbarui HTML dan CSS secara\n            langsung, bahkan ketika Anda mengetik! Mungkin Anda sudah pernah melakukan hal ini dengan perangkat dari\n            peramban, namun dengan Brackets, Anda tidak perlu lagi menyalin kode kembali ke editor. Kode Anda berjalan\n            di peramban, namun tetap berada di editor Anda!\n        </p>\n        \n        <h3>Soroti langsung elemen HTML dan aturan CSS</h3>\n        <p>\n            Brackets mempermudah Anda melihat bagaimana perubahan pada HTML dan CSS yang Anda buat akan mempengaruhi\n            halaman. Ketika kursor Anda berada pada aturan CSS, Brackets akan menyoroti semua elemen yang dipengaruhi\n            pada peramban. Hal yang sama ketika mengedit file HTML, Brackets akan menyoroti elemen HTML yang sesuai\n            pada peramban.\n        </p>\n        \n        <samp>\n            Jika Anda menggunakan Google Chrome, Anda bisa mencoba ini sendiri. Klik pada ikon petir di\n            sebelah kanan atas pada jendela Brackets Anda atau tekan <kbd>Cmd/Ctrl + Alt + P</kbd>.\n            Ketika Tinjauan Langsung dijalankan di dokumen HTML, semua dokumen CSS yang terhubung bisa diedit secara\n            langsung. Ikon petir akan berubah warna dari abu-abu menjadi emas ketika Brackets mendapatkan sambungan\n            ke peramban Anda.\n            \n            Sekarang, tempatkan kursor Anda di tag <!-- <img> --> di atas. Perhatikan sorotan warna biru yang muncul\n            di sekeliling gambar pada Chrome. Lalu, tekan <kbd>Cmd/Ctrl + E</kbd> untuk membuka aturan CSS yang ada.\n            Cobalah ubah ukuran border dari 10px ke 20px atau ubah warna background dari \"transparent\" ke \"hotpink\".\n            Jika Brackets dan peramban berjalan berdampingan, Anda akan dapat melihat perubahannya secara langsung\n            di peramban Anda. Keren, kan?\n        </samp>\n        \n        <p class=\"note\">\n            Saat ini, Brackets hanya mendukung Tinjauan Langsung untuk HTML dan CSS. Namun di versi ini, perubahan\n            terhadap JavaScript akan dimuat ulang ketika Anda menyimpan. Saat ini kami berusaha menambahkan\n            dukungan Tinjauan Langsung untuk JavaScript. Tinjauan Langsung juga hanya bisa dijalankan di peramban\n            Google Chrome, namun kami berharap untuk memberikan fitur ini ke semua peramban di masa depan.\n        </p>\n        \n        <h3>Tampilan Cepat</h3>\n        <p>\n            Bagi Anda yang belum hafal nilai RGB dan HEX sebuah warna, dengan Brackets, Anda dapat dengan mudah dan\n            cepat untuk melihat warna apa saja yang sedang digunakan. Di CSS atau HTML, tempatkan kursor di atas nilai\n            warna atau gradien dan Brackets akan menampilkan warna/gradien tersebut secara otomatis. Sama halnya dengan\n            gambar: taruh kursor di atas link gambar pada editor Brackets dan menampilkan thumbnail dari gambar tersebut.\n        </p>\n        \n        <samp>\n            Untuk mencobanya sendiri, tempatkan kursor Anda pada tag <!-- <body> --> di atas dokumen ini dan tekan\n            <kbd>Cmd/Ctrl + E</kbd> untuk membuka editor cepat CSS. Setelah itu, tempatkan kursor di atas nilai warna\n            apapun di dalam CSS tersebut. Anda juga bisa mencoba sendiri untuk gradien dengan membuka editor cepat\n            CSS pada tag <!-- <html> --> dan menempatkan kursor pada nilai <i>background image</i> manapun. Untuk\n            mencoba tinjauan gambar, tempatkan kursor Anda di atas gambar screenshot yang ada di dokumen ini.\n        </samp>\n        \n        <h3>Ingin fitur lain? Tambahkan ekstensi!</h3>\n        <p>\n            Selain semua fitur-fitur keren yang ada di dalam Brackets, kami mempunyai komunitas pengembang ekstensi\n            yang terus tumbuh jumlahnya dan sudah membuat ratusan ekstensi yang sangat berguna. Apabila Anda\n            membutuhkan fitur yang tidak ada dalam Brackets, kemungkinan besar seseorang telah membuat ekstensi untuk\n            itu. Untuk melihat daftar ekstensi yang tersedia, klik <strong>File > Pengelola Ekstensi</strong> lalu\n            klik di tab \"Tersedia\". Ketika Anda menemukan ekstensi yang Anda inginkan, klik tombol \"Instal\" di sebelahnya.\n        </p>\n        \n        <!--\n            KAMI INGIN DENGAR PENDAPAT ANDA\n        -->\n        <h2>Ikut terlibat</h2>\n        <p>\n            Brackets adalah proyek open-source. Pengembang web dari seluruh dunia berkontribusi untuk membangun editor\n            yang lebih baik. Dan juga ada banyak orang yang menembangkan ekstensi untuk meningkatkan kemampuan Brackets.\n            Beri kami saran, ide, atau berkontribusilah secara langsung untuk Brackets.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Blog Tim Brackets</a></li>\n            <li><a href=\"http://github.com/adobe/brackets\">Brackets di GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Daftar Ekstensi Brackets</a></li>\n            <li><a href=\"http://github.com/adobe/brackets/wiki\">Wiki Brackets</a></li>\n            <li><a href=\"http://groups.google.com/group/brackets-dev\">Milis Pengembang Brackets</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets di Twitter</a></li>\n            <li>Mengobrol dengan pengembang Brackets di IRC dalam <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">channel #brackets di Freenode</a></li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n\n<!-- Last translated for 3066a8c164995790b58a9ea739e9a5450edcc963 -->"
  },
  {
    "path": "samples/id/Memulai/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/it/Primi passi/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>PRIMI PASSI CON BRACKETS!</title>\n        <meta name=\"description\" content=\"Una guida interattiva per muovere i primi passi su Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>PRIMI PASSI CON BRACKETS!</h1>\n        <h2>Questa è la tua guida!</h2>\n        \n        <!--\n            FATTO CON <3 E JAVASCRIPT\n        -->\n        \n        <p>\n            Benvenuto in questa versione preliminare di Brackets, un nuovo editor open-source per la nuova\n            generazione del web. Noi siamo grandi fan degli standard e vogliamo realizzare degli strumenti\n            migliori per lavorare in JavaScript, HTML, CSS e altre tecnologie aperte del web. Questo è il\n            nostro umile inizio.\n        </p>\n        \n        <!--\n            COS'È BRACKETS?\n        -->\n        <p>\n            <em>Brackets è un editor differente.</em>\n            Un importante differenza è che questo editor è scritto in JavaScript, HTML e CSS.\n            Questo significa che la maggior parte di coloro che utilizzano Brackets, sono in grado di modificare\n            e ampliare l'editor. Infatti, noi usiamo Brackets ogni giorno per costruire Brackets.\n            Brackets è inoltre dotato di caratteristiche uniche come Modifica Rapida, Anteprima Live e altre\n            caratteristiche che non trovereste altrove.\n        </p>\n        \n        \n        <h2>Stiamo provando alcune cose nuove</h2>\n        \n        <!--\n            LA RELAZIONE TRA HTML, CSS E JAVASCRIPT\n        -->\n        <h3>Modifica rapida per CSS e JavaScript</h3>\n        <p>\n            Non c'è più bisogno di spostarsi continuamente da un documento all'altro. Quando si lavora al codice\n            HTML, è possibile digitare <kbd>Cmd/Ctrl + E</kbd> per aprire un'area di modifica rapida che mostra\n            il CSS corrispondente. Una volta effettuata una modifica al codice CSS, basta premere <kdb>ESC</kdb>\n            e si ritorna sull'HTML chiudendo l'area di modifica rapida, o è possibile lasciare aperta tale area\n            continuando a lavorare sull'HTML. Premendo invece <kbd>ESC</kbd> al di fuori di tale area, tutte le\n            aree di modifica rapida verranno chiuse.\n        </p>\n        \n        <samp>\n            Vuoi vederlo in azione? Posiziona il cursore nel tag <!-- <samp> --> sopra e premi\n            <kbd>Cmd/Ctrl + E</kbd>. Dovresti vedere un'area di modifica rapida del CSS apparire sopra.\n            Sulla destra vedrai la lista delle regole CSS corrispondenti a questo tag. Scorri\n            semplicemente le regole con <kbd>Alt + Up/Down</kbd> per trovare quella che intendi modificare.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Uno screenshot che mostra una finestra di modifica rapida CSS\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Puoi usare la stessa combinazione di tasti per il codice JavaScript e vedere il corpo di una funzione\n            posizionando il cursore nel nome della funzione chiamata. Per il momento gli editor in linea non possono\n            essere nidificati, quindi è possibile usare la modifica rapida solo quando il cursore è posizionato nell'editor\n            generale.\n        </p>\n        \n        <!--\n            ANTEPRIMA LIVE\n        -->\n        <h3>L'anteprima del CSS cambia in tempo reale nel browser</h3>\n        <p>\n            Conosci la solita procedura \"salva/ricarica\" che abbiamo fatto per anni? Fai una modifica tramite editor,\n            premi \"salva\", passi alla finestra del browser e aggiorni la pagina per vedere il risultato?\n            Con Brackets non avrai più bisogno di questo procedimento.\n        </p>\n        <p>\n            Brackets aprirà una <em>connessione in tempo reale</em> con il tuo browser e gli manderà tutte le modifiche\n            del CSS non appena tu le avrai digitate! Forse oggi stai già facendo qualcosa di simile con qualche\n            strumento browser-based, ma con Brackets non avrai bisogno di copiare e incollare il codice CSS definitivo\n            nel tuo editor. Il tuo codice gira nel browser, ma risiede già nell'editor!\n        </p>\n        \n        <h3>L'anteprima mette in risalto gli elementi HTML e le regole CSS.</h3>\n        <p>\n            Brackets rende semplice vedere come le proprie modifiche all'HTML e al CSS hanno effetto sulla pagina.\n            Quando il cursore è su una regola CSS, nel browser verranno messi in risalto tutti gli elementi che\n            vengono influenzati da quella regola. Similmente, quando stai modificando un file HTML, Brackets metterà\n            in risalto nel browser gli elementi HTML corrispondenti.\n        </p>\n        \n        <samp>\n            Se hai Google Chrome installato, puoi provare da te. Clicca nell'icona con il fulmine nell'angolo\n            in alto a destra della finestra di Brackets oppure premi <kbd>Cmd/Ctrl + Alt + P</kbd>. Quando\n            Anteprima Live è abilitata in un documento HTML, tutti i documenti CSS collegati possono essere\n            modificati in tempo reale. L'icona cambierà colore, dal grigio al dorato, quando Brackets stabilisce\n            una connessione con il tuo browser.\n            \n            Adesso, posiziona il cursore sul tag <!-- <img> --> sopra. Noterai un highlight blu apparire attorno\n            all'imagine su Chrome. Successivamente, usa <kdb>Cmd/Ctrl + E</kdb> per aprire le regole CSS.\n            Prova a cambiare la grandezza del bordo da 10px a 20px o cambia il colore di sfondo da \"transparent\" a\n            \"hotpink\". Se Brackets e il tuo browser sono posizionati fianco a fianco, noterai istantaneamente\n            i cambiamenti anche nel tuo browser. Bello, vero?\n        </samp>\n                \n        <p class=\"note\">\n            Oggi, Brackets supporta solo l'Anteprima Live per il CSS. Comunque, nella versione corrente, i\n            cambiamenti ai file HTML e JavaScript sono automaticamente ricaricati quando si salva. Al momento\n            stiamo lavorando al supporto di HTML e JavaScript nell'Anteprima Live. Inoltre le anteprime live sono\n            supportate solo su Google Chrome, ma per il futuro speriamo di portare questa funzionalità anche\n            sugli altri browser più comuni.\n        </p>\n                \n        <h3>Visualizzazione Rapida</h3>\n        <p>\n            Per coloro che non hanno ancora memorizzato i colori associati ai valori HEX o RGB, Brackets rende\n            facile e veloce vedere esattamente qual è il colore corrispondente. Nei documenti CSS e HTML basta\n            semplicemente posizionare il mouse sopra il valore di ogni colore e Brackets mostrerà automaticamente\n            un'anteprima di quel colore. La stessa cosa vale per le immagini: basta spostare il mouse sopra il\n            link dell'immagine all'interno dell'editor Brackets ed esso mostrerà una miniatura di quell'immagine.\n        </p>\n        \n        <samp>\n            Prova la Visualizzazione Rapida, posiziona il cursore sopra il tag <!-- <body> --> nella parte\n            superiore di questo documento e premi <kbd>Cmd/Ctrl + E</kbd> per una modifica rapida del CSS.\n            Adesso posiziona il mouse sopra un valore di qualche colore. Inoltre puoi vederla in azione sui\n            gradienti aprendo una modifica veloce CSS sopra il tag <!-- <html> --> e posizionando il mouse\n            sopra qualche valore corrispondente all'immagine di sfondo. Prova l'anteprima dell'immagine,\n            posiziona il cursore sopra lo screenshot presente all'inizio di questo documento.\n        </samp>\n        \n        <!--\n            DICCI COSA NE PENSI\n        -->\n        <h2>Partecipa</h2>\n        <p>\n            Brackets è un progetto open source. Sviluppatori web da ogni parte del mondo stanno contribuendo\n            per realizzare un editor migliore. Altri ancora stanno realizzando estensioni che espandono le\n            funzionalità di Brackets. Dicci cosa ne pensi, condividi le tue idee o contribuisci direttamente\n            al progetto.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets Team Blog</a></li>\n            <li><a href=\"http://github.com/adobe/brackets\">Brackets su GitHub</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki/Brackets-Extensions\">Brackets Extensions</a></li>\n            <li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"http://groups.google.com/group/brackets-dev\">Brackets Developer Mailing List</a></li>\n            <li><a href=\"https://twitter.com/#!/brackets\">@Brackets su Twitter</a></li>\n            <li>Chatta con gli sviluppatori di Brackets nel canale IRC #brackets su Freenode</li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/it/Primi passi/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/ja/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>BRACKETS をはじめる前に</title>\n        <meta name=\"description\" content=\"An interactive getting started guide for Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>BRACKETS をはじめる前に</h1>\n        <h2>まずはこのガイドからスタート</h2>\n        \n        <!--\n            <3 と JAVASCRIPT で作成\n        -->\n        \n        <p>\n            Web デザインを認識する最新のオープンソースエディター、Brackets をご利用いただき、ありがとうございます。軽量でありながらパワフルなコードエディターでのビジュアルツールとエディターとの融合により、必要なときに必要なだけのサポートを利用することができます。\n        </p>\n        \n        <!--\n            Brackets とは何ですか？\n        -->\n        <p>\n            <em>Brackets は、新しいタイプのエディターです。</em>\n            Brackets にはクイック編集やライブプレビューなど、他のエディターにはないユニークな機能が備わっています。Brackets は JavaScript、HTML および CSS で記述されています。つまり、ほとんどの Brackets ユーザーは、習得済みのスキルを使って、このエディターそのものを変更したり拡張したりできるということになります。実際、アドビ社内の開発チームも、毎日 Brackets を使用して Brackets の構築を進めています。主要機能の使用方法について、下記で詳しくご説明します。\n        </p>\n        \n        <!--\n            自分のファイルで始めましょう\n        -->\n        \n        <h3>Brackets のプロジェクト</h3>\n        <p>\n            Brackets を使用して独自のコードを記述するには、自分のファイルを格納したフォルダーを開きます。\n            現時点で開いているフォルダーが Brackets によって「プロジェクト」として処理され、そのフォルダー内のファイルのみがコードヒント、ライブプレビュー、クイック編集などの機能で使用されます。\n        </p>\n        \n        <samp>\n            このサンプルプロジェクトを終了し、コードを編集する準備ができたら、左側のサイドバーのドロップダウンを使用してフォルダーを切り替えます。この時点で、ドロップダウンには「はじめに」が表示され、現在表示されているファイルが格納されたフォルダーが選択されています。ドロップダウンで「フォルダーを開く...」を選択して、使用するフォルダーを開きます。\n            ドロップダウンを使用して、このサンプルプロジェクトが含まれるフォルダーなど、以前に開いたフォルダーに切り替えることもできます。\n        </samp>\n        \n        <!--\n            HTML、CSS と JavaScript との関係\n        -->\n        <h3>CSS と JavaScript のクイック編集</h3>\n        <p>\n            いくつものドキュメントを行ったり来たりして、コードの文脈を見失うようなことはもうありません。HTML ファイルの編集中にショートカットの <kbd>Command+E キーまたは Ctrl+E キー</kbd>を使用すると、クイック編集用のインラインエディターが開き、関連する CSS がすべて表示されます。\n            ここで CSS を調整して <kbd>Esc キー</kbd>を押せば、HTML の編集に戻ることができます。また、CSS ルールを開いたままにしておけば、HTML エディターの一部として使用できます。カーソルがクイック編集用インラインエディターの外にあるときに <kbd>Esc キー</kbd>を押すと、CSS ルールはすべて折りたたまれます。また、クイック編集には、ネストされたルールなど、LESS および SCSS ファイルで定義されたルールも備わっています。\n        </p>\n\n        <samp>\n            この機能を実際に使用するには、上部の <!-- <samp> --> タグにカーソルを合わせた状態で <kbd>Command+E キーまたは Ctrl+E キー</kbd>を押します。すると、上部に CSS クイック編集エディターが開き、適用する CSS ルールが表示されます。クイック編集は、クラスおよび id 属性にも使用できます。また、クイック編集は LESS および SCSS ファイルでも使用できます。\n            \n            新規ルールも同じように作成できます。上部の <!-- <p> --> タグのいずれかをクリックし、<kbd>Command+E キーまたは Ctrl+E キー</kbd>を押します。そのとき既存のルールがなければ、「新規ルール」ボタンをクリックして <!-- <p> --> に新規ルールを追加できます。\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"CSS クイック編集のスクリーンショット\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            同じショートカットを使用して、JavaScript の関数、カラー、アニメーションタイミング機能など、他のエレメントも編集できます。アドビでは、この機能を継続して強化していきます。\n        </p>\n        <p>\n            現時点ではインラインエディターをネストすることはできませんので、クイック編集を使用できるのは、カーソルが「フルサイズ」のエディター内にある場合に限られています。\n        </p>\n        \n        <!--\n            ライブプレビュー\n        -->\n        <h3>HTML および CSS の編集結果をブラウザーでライブプレビュー</h3>\n        <p>\n            私たちはずっと、保存とリロードの繰り返し作業に煩わされてきました。エディターで編集して保存し、ブラウザーに切り替えて更新してから、ようやく結果を確認できるという、あの作業です。\n            Brackets では、もうあの作業を行う必要はありません。\n        </p>\n        <p>\n            Brackets では、HTML や CSS のコード編集を行いながら、ローカルブラウザーに<em>ライブ接続</em>し、編集結果をリアルタイムでプレビューできます。ブラウザーベースのツールの中には、現時点でもこれと似たことが可能なものもありますが、Brackets の場合は最終的にコードをエディターにコピー＆ペーストする必要がありません。コードが実行されるのはブラウザー上ですが、コードがある場所は最初からずっとエディター内なのです。\n        </p>\n        \n        <h3>HTML エレメントと CSS ルールのライブハイライト</h3>\n        <p>\n            Brackets では、HTML や CSS の編集内容がどのようにページに反映されるかを、簡単に確認することができます。Brackets で CSS ルール上にカーソルを置くと、ブラウザー上でそのルールに対応するエレメントがすべてハイライト表示されます。これと同じように、HTML ファイルを編集しているときも、ブラウザー上でそれに対応する HTML エレメントがハイライト表示されます。\n        </p>\n        \n        <samp>\n            お使いのコンピューターに Google Chrome がインストールされていれば、これを実際にお試しいただくことができます。Brackets ウィンドウの右上にある稲妻アイコンをクリックするか、<kbd>Command+Alt+P キーまたは Ctrl+Alt+P キー</kbd>を押します。HTML ドキュメントでライブプレビューが有効になっていれば、リンクされている CSS ドキュメントはすべてリアルタイムで編集可能です。\n            Brackets でローカルブラウザーとの接続が確立されると、アイコンがグレーから金色に変わります。\n            \n            この状態で、上部の <!-- <img> --> タグにカーソルを合わせます。すると、Chrome 上で画像の周囲が青くハイライト表示されます。次に、<kbd>Command+E キーまたは Ctrl+E キー</kbd>を押して、定義済みの CSS ルールを開きます。\n            枠のサイズを 10 ピクセルから 20 ピクセルに変更するか、背景色を「透明」から「ホットピンク」に変更してみてください。Brackets とブラウザーが同時に動作していれば、この変更内容が瞬時にブラウザーの表示に反映されるのを確認できます。\n        </samp>\n        \n        <p class=\"note\">\n            現時点で Brackets のライブプレビューが対応しているのは、HTML と CSS のみです。JavaScript ファイルの場合、現行バージョンでは、編集内容を保存した時点で自動的にリロードされます。現在アドビでは、JavaScript のライブプレビュー対応を進めています。また、ライブプレビューの可能なブラウザーは Google Chrome のみですが、将来的には主要なブラウザーすべてでこの機能を利用できるようにしたいと考えています。\n        </p>\n        \n        <h3>クイックビュー</h3>\n        <p>\n            まだ 16 進数値または RGB 値に対応するカラーコードを覚えていなくても、Brackets なら使用されているカラーを正確に、しかもすばやく簡単に確認できます。CSS でも HTML でも、カラー値またはグラデーション上にカーソルを重ねるだけで、そのカラーやグラデーションが自動的に表示されます。画像の場合も同様で、Brackets エディターで画像リンク上にカーソルを重ねると、その画像のプレビューがサムネイルで表示されます。\n        </p>\n        \n        <samp>\n            クイックビューを実際に使ってみるには、このドキュメントの上部にある <!-- <body> --> タグにカーソルを合わせます。その状態で <kbd>Command+E キーまたは Ctrl+E キー</kbd>を押すと、CSS クイック編集エディターが開きます。あとは、CSS 内でカラー値のどれかにカーソルを重ねるだけです。また、グラデーションに対してこの機能を使ってみるには、<!-- <html> --> タグで CSS クイック編集エディターを開き、背景画像の値にカーソルを重ねます。画像のプレビューを試す場合は、このドキュメントの前半に掲載されているスクリーンショット画像にカーソルを重ねてみてください。\n        </samp>\n        \n        <h3>拡張機能でさらに補強</h3>\n        <p>\n            Brackets に組み込まれた優れた機能に加え、拡大を続ける大規模なコミュニティで、デベロッパーらが何百もの便利な拡張機能を構築しています。Brackets にない機能を必要としたとき、ほぼ確実に構築済みの拡張機能が見つかります。使用可能な拡張機能の一覧を参照または検索するには、<strong>ファイル／拡張機能マネージャー</strong> を選択し、「入手可能」タブをクリックします。使用する拡張機能が見つかったら、その横の「インストール」ボタンをクリックします。\n        </p>\n        \n        <!--\n            ご意見をお聞かせください\n        -->\n        <h2>Brackets プロジェクトに参加</h2>\n        <p>\n            Brackets はオープンソースのプロジェクトです。世界中の Web 開発者が、優れたコードエディターの構築に貢献しています。さらに多くの人々が、Brackets の拡張機能の構築に携わっています。\n            ぜひ、このプロジェクトについてご意見・アイデアをお寄せください。プロジェクトへの直接的なご参加もお待ちしております。\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets チームのブログ</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">GitHub の Brackets ページ</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets 拡張機能レジストリ</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets デベロッパーのメーリングリスト</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets on Twitter</a></li>\n            <li>以下の IRC で、Brackets デベロッパーと Brackets についてチャット：<a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets on Freenode</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/ja/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/ko/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>BRACKETS 으로 시작하기</title>\n        <meta name=\"description\" content=\"Brackets에 대한 대화식 시작 안내서입니다.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>BRACKETS 으로 시작하기</h1>\n        <h2>이것은 당신의 가이드입니다.</h2>\n        \n        <!--\n            <3 및 JAVASCRIPT로 작성되었습니다.\n        -->\n        \n        <p>\n            \n            웹 디자인을 이해하는 현대적인 오픈 소스 코드 편집기 인 Brackets에 오신 것을 환영합니다. 가볍고 강력한 코드 편집기로 시각 도구를 편집기에 통합하여 원할 때 도움을받을 수 있습니다.\n        </p>\n        \n        <!--\n            BRACKETS 이란 무엇인가?\n        -->\n        <p>\n            <em>Brackets은 다른 유형의 편집기입니다.</em>\n            Brackets 에는 다른 편집자에서 볼 수없는 빠른 편집, 실시간 미리보기 및 기타 기능과 같은 고유 한 기능이 있습니다. Brackets에는 JavaScript, HTML 및 CSS로 작성됩니다. 즉, 대다수 사용자는 대괄호를 사용하여 편집자를 수정하고 확장하는 데 필요한 기술을 보유하고 있습니다. 사실, 우리는 Brackets을 만들기 위해 Brackets을 매일 사용합니다. 주요 기능 사용 방법에 대한 자세한 내용은 다음을 참조하십시오.\n        </p>\n        \n        <!--\n            자신의 파일로 시작하기\n        -->\n        \n        <h3>Brackets 안에 있는 프로젝트</h3>\n        <p>\n           Brackets을 사용하여 자신의 코드를 편집하려면 파일이 들어있는 폴더를 열면 됩니다.  Brackets은 현재 열려있는 폴더를 \"프로젝트\"로 취급합니다. 코드 힌트, 실시간 미리보기 및 빠른 편집과 같은 기능은 현재 열려있는 폴더 내의 파일에만 사용합니다.\n        </p>\n        \n        <samp>\n            이 샘플 프로젝트에서 벗어나 자신의 코드를 편집 할 준비가되면 왼쪽 사이드 바의 드롭 다운을 사용하여 폴더를 전환 할 수 있습니다. 지금은 드롭 다운에 \"시작하기\"라고 표시되어 있습니다. 바로 지금보고있는 파일이 들어있는 폴더입니다. 드롭 다운을 클릭하고 \"폴더 열기 ...\"를 선택하여 자신의 폴더를 엽니 다. 나중에이 드롭 다운을 사용하여이 샘플 프로젝트를 포함하여 이전에 열어 본 폴더로 다시 전환 할 수도 있습니다.\n        </samp>\n        \n        <!--\n            HTML, CSS 및 JAVASCRIPT 간의 관계\n        -->\n        <h3>CSS 및 JavaScript 용 빠른 편집</h3>\n        <p>\n            문서를 더 이상 전환하지 않고 컨텍스트를 잃어 버리지 않습니다. HTML을 편집 할 때 <kbd> Cmd / Ctrl + E </kbd> 단축키를 사용하여 모든 관련 CSS를 표시하는 빠른 인라인 편집기를 엽니다.\n            CSS를 조정하고 <kbd> ESC </kbd>를 누르면 HTML 편집으로 돌아가거나 CSS 규칙을 열어두면 HTML 편집기의 일부가 됩니다.\n            빠른 인라인 편집기 밖에서 <kbd> ESC </kbd>를 누르면 모두 축소됩니다. 빠른 편집은 중첩 된 규칙을 포함하여 LESS 및 SCSS 파일에 정의 된 규칙을 찾습니다. \n        </p>\n        \n        <samp>\n            그것을 실제로보고 싶습니까? 위의 <!-- <samp> --> 태그에 커서를 놓고 <kbd> Cmd / Ctrl + E </kbd>를 누르십시오. 위의 CSS 빠른 편집기가 표시되어 CSS 규칙이 적용됩니다. 빠른 편집은 클래스 및 id 속성에서도 작동합니다. LESS 및 SCSS 파일과 함께 사용할 수도 있습니다. 같은 방식으로 새 규칙을 만들 수 있습니다. 위의 <!-- <p> --> 태그 중 하나를 클릭하고 <kbd> Cmd / Ctrl + E </kbd>를 누르십시오. 지금은 규칙이 없지만 새 규칙 버튼을 클릭하여 새 규칙을 추가 할 수 있습니다.         \n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"CSS 빠른 편집을 보여주는 스크린 샷\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            동일한 바로 가기를 사용하여 JavaScript, 색상 및 애니메이션 타이밍 기능의 다른 기능을 편집 할 수 있으며 점점 더 많은 시간을 추가하고 있습니다\n        </p>\n        <p>\n          지금은 인라인 편집기를 중첩 할 수 없으므로 커서가 \"전체 크기\"편집기 인 경우에만 빠른 편집을 사용할 수 있습니다.\n        </p>\n        \n        <!--\n            실시간 미리보기\n        -->\n        <h3>HTML 및 CSS 변경 사항을 브라우저에서 미리보기</h3>\n        <p>\n          우리가 수년간 해왔 던 \"저장 / 재 장전 댄스\"를 아십니까? 편집기에서 변경 한 내용을 저장하고 브라우저로 전환 한 다음 새로 고침하여 최종 결과를 확인하십시오. 괄호로, 당신은 그 춤을 할 필요가 없습니다.\n        </p>\n        <p>\n            Brackets은 는 로컬 브라우저에 <em> live connection </em>을 열고 입력 할 때 HTML 및 CSS 업데이트를 푸시합니다. 브라우저 기반 도구를 사용하여 이미 이와 같은 작업을 수행 하고 있을 수도 있지만 Brackets을 사용하면 최종 코드를 복사하여 편집기에 다시 붙여 넣을 필요가 없습니다.  코드는 브라우저에서 실행되지만 편집기에서 실행됩니다.\n        </p>\n        \n        <h3>라이브 HTML 요소 및 CSS 규칙 강조 표시</h3>\n        <p>\n           Brackets을 사용하면 HTML 및 CSS 변경이 페이지에 어떤 영향을 주는지 쉽게 알 수 있습니다. 커서가 CSS 규칙에 있으면 Brackets은 브라우저에서 영향을 받는 모든 요소를 강조 표시합니다.마찬가지로 HTML 파일을 편집 할 때 Brackets은 브라우저에서 해당 HTML 요소를 강조 표시합니다. \n        </p>\n        \n        <samp>\n            Chrome을 설치 한 경우 직접 시도해 볼 수 있습니다. 대괄호 창의 오른쪽 위 모서리에있는 번개 모양 아이콘을 클릭하거나 <kbd> Cmd / Ctrl + Alt + P </kbd>를 누르십시오. HTML 문서에서 실시간 미리보기가 활성화되면 연결된 모든 CSS 문서를 실시간으로 편집 할 수 있습니다. 괄호가 브라우저에 연결되면 아이콘이 회색에서 금색으로 바뀝니다.이제 위의 <!-- <img> --> 태그에 커서를 놓으십시오. Chrome에서 이미지 주변에 나타나는 파란색 강조 표시를 확인합니다. 다음으로 <kbd> Cmd / Ctrl + E </kbd>를 사용하여 정의 된 CSS 규칙을 엽니 다. 국경의 크기를 10px에서 20px로 변경하거나 배경색을 \"투명\"에서 \"핫 핑크\"로 변경하십시오. 대괄호가 있고 브라우저가 나란히 실행되면 변경 사항이 브라우저에 즉시 반영됩니다. 멋지다, 맞지?\n        </samp>\n        \n        <p class=\"note\">\n           현재 브라켓은 HTML 및 CSS에 대한 실시간 미리보기 만 지원합니다. 그러나 현재 버전에서는 저장시 JavaScript 파일의 변경 사항이 자동으로 다시 로드됩니다. 현재 JavaScript에 대한 라이브 미리보기 지원을 위해 노력하고 있습니다. 실시간 미리보기는 Google 크롬에서만 가능하지만 이후 모든 주요 브라우저에 기능을 제공하기를 바랍니다. \n        </p>\n        \n        <h3>빨리보기</h3>\n        <p>\n            HEX 또는 RGB 값에 해당하는 색상을 기억하지 않은 사용자의 경우 Brackets을 사용하면 어떤 색상이 사용되는지 정확하게 볼 수 있습니다. CSS 또는 HTML에서 색상 값이나 변수 위로 마우스를 가져 가면 Brackets에 해당 색상 / 변수의 미리보기가 자동으로 표시됩니다. 이미지도 마찬가지입니다. Brackets 편집기의 이미지 링크 위로 마우스를 가져 가면 해당 이미지의 미리보기 미리보기가 표시됩니다. \n        </p>\n        \n        <samp>\n           빠른보기를 직접 사용해 보려면 이 상단의 <!-- <body> --> 태그에 커서를 올려 놓으십시오. <kbd> Cmd / Ctrl + E </kbd>를 눌러 CSS 빠른 편집기를 엽니다. 이제 간단하게 CSS 내의 색상 값. 또한 <!-- <html> --> 태그에서 CSS 빠른 편집기를 열고 배경 이미지 값 위로 마우스를 가져 가면 그래디언트의 동작을 볼 수 있습니다. 이미지 미리보기를 시험해 보려면 이 문서 앞 부분에 있는 스크린 샷 이미지 위에 커서를 놓으십시오.\n        </samp>\n        \n        <h3>다른 것이 필요합니까? 확장 프로그램을 사용해보십시오!</h3>\n        <p>\n            Brackets에 내장 된 모든 장점에 더하여, 확장 개발자의 대규모 성장 커뮤니티에는 유용한 기능을 추가하는 수백 가지 확장 기능이 있습니다. Brackets이 제공하지 않는 것을 필요로 하는 경우 누군가가 그 확장 기능을 확장했을 가능성이 큽니다. 사용 가능한 확장 프로그램 목록을 탐색하거나 검색하려면 <strong> 파일> 확장 관리자 ... </strong>를 선택하고 '사용 가능'탭을 클릭하십시오. 원하는 확장자를 찾으면 바로 옆에 있는 \"설치\"버튼을 클릭하십시오.\n        </p>\n        \n        <!--\n            당신이 생각하는 것을 우리가 알수있게 하십시오.\n        -->\n        <h2>참여하기</h2>\n        <p>\n           Brackets는 오픈 소스 프로젝트입니다. 전 세계의 웹 개발자가 더 나은 코드 편집기를 작성하는데 기여하고 있습니다. 더 많은 것은 Brackets의 기능을 확장하는 확장 기능을 구축합니다. 의견을 나누거나 아이디어를 공유하거나 프로젝트에 직접 기여하십시오.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets 팀 블로그</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets 깃허브</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets 확장 저장소</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets 위키</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets 개발자 메일 주소</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets 트위터</a></li>\n            <li>IRC의 Brackets 개발자와 채팅 <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">Freenode의 #brackets</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/ko/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/nl/Aan-de-slag/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>AAN DE SLAG MET BRACKETS</title>\n        <meta name=\"description\" content=\"Een interactieve handleiding voor Brackets\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>AAN DE SLAG MET BRACKETS</h1>\n        <h2>Dit is uw gids!</h2>\n\n        <!--\n            GEMAAKT MET <3 EN JAVASCRIPT\n        -->\n\n        <p>Welkom bij een vroeg voorbeeld van Brackets, een nieuwe open-source editor voor de volgende generatie van het web. Wij zijn erg fan van de standaarden en willen een betere tool bouwen voor het bewerken van JavaScript, HTML en CSS en andere gerelateerde open web technologieën. Dit is ons bescheiden begin.</p>\n\n        <!--\n            WAT IS BRACKETS?\n        -->\n        <p><em>Brackets is een ander soort editor.</em>\n            Een opmerkelijk verschil is dat deze editor is geschreven in JavaScript, HTML en CSS. Dit betekent dat de meesten van jullie beschikken over de vaardigheden die nodig zijn om Brackets aan te passen en uit te breiden. Eigenlijk gebruiken we Brackets elke dag om Brackets te bouwen. Brackets heeft ook een paar unieke functies zoals Quick Edit, Live preview en nog meer, welke je niet kunt terugvinden in andere editors. Voor meer informatie over hoe u deze functies kunt gebruiken kunt u hier verder lezen.\n        </p>\n\n\n        <h2>We proberen een paar nieuwe dingen uit</h2>\n\n        <!--\n            DE RELATIE TUSSEN HTML, CSS EN JAVASCRIPT\n        -->\n        <h3>Quick editor voor CSS en JavaScript</h3>\n        <p>Nooit meer schakelen tussen documenten en verliezen van je koppeling. Bij het bewerken van HTML, kun je gebruik maken van de <kbd>Cmd/Ctrl + E</kbd> sneltoets om snel de gekoppelde CSS code te laten zien. Maak een verandering in je CSS, druk op <kbd>ESC</kbd> en je bent weer terug bij het bewerken van de HTML, of laat de CSS code open en ze maken deel uit van de HTML-editor. Als je drukt op <kbd>ESC</kbd> buiten de inline editor, zullen ze allemaal uitvouwen.\n        </p>\n\n        <samp>Wil je het in actie zien? Plaats je cursor op de <!-- <samp> --> tag en druk op <kbd>Cmd/Ctrl + E</kbd>. Je ziet dan een snelle CSS editor verschijnen hierboven, wat de CSS regels laat zien wat er aan gekoppeld is. Quick Edit werkt in zowel class en id attributen. Je kan nieuwe regels maken via dezelfde manier. Klik in een van de <!-- <p> --> tags hierboven en druk op <kbd>Cmd/Ctrl + E</kbd>. Er zijn nu geen regels voor, maar je kunt klikken op de \"Nieuwe regel\"\" knop om een nieuwe regel toe te voegen voor <!-- <p> --> </samp>\n\n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"Een screenshot van de Quick CSS editor\" src=\"screenshots/quick-edit.png\" />\n        </a>\n\n\n        <p>\n            Je kunt dezelfde sneltoets gebruiken om andere dingen te bewerken--zoals functies in JavaScript, kleuren, en animatie timing functies--en we voegen meer en functies meer toe. Nu kunnen inline editors niet genesteld worden, dus kun je alleen Quick Editor gebruiken wanneer de cursor in een \"volledige grootte\" editor staat.</p>\n        <!--\n            LIVE PREVIEW\n        -->\n        <h3>Bekijk HTML en CSS aanpassingen live in de browser</h3>\n        <p>\n            Wist je nog die \"opslaan en herlaad dans\" die we jaren lang hebben gedaan? Dat je het bestand die je hebt gewijzigd in een editor moest opslaan, naar de browser moest omschakelen en dan herladen om het resultaat te kunnen zien. Met Brackets is dat allemaal verleden tijd.\n        </p>\n\n        <p>\n            Brackets opent een <em>live connectie</em> in je locale browser en elke keer wanneer er HTML en CSS updates zijn, werkt het automatisch bij terwijl je typt! Misschien heb je zoiets al gebruikt met browser-gebaseerde tools, maar met Brackets is het niet nodig om helemaal terug te gaan naar de editor en de code uiteindelijk te kopiëeren en te plakken. Je code wordt uitgevoerd in de browser, terwijl je blijft in de editor!</p>\n\n        <h3>Live highlight van HTML elementen en CSS regels </h3>\n        <p>\n            Brackets maakt het makkelijk om te zien hoe wijzigingen in je HTML en CSS de pagina zullen beïnvloeden. Wanneer je je cursor op een CSS-regel zet, zal Brackets alle betrokken elementen in de browser markeren. Ook wanneer je op dat moment een HTML-bestand aan het bewerken bent, zal Brackets de bijbehorende HTML-elementen in de browser markeren.\n        </p>\n\n        <samp>Als je Google Chrome hebt geïnstalleerd, kunt u deze functie zelf uitproberen. Klik op het icoontje met de bliksemschicht rechtsboven in Brackets of druk op <kbd>Cmd/Ctrl + Alt + P</kbd>. Wanneer Live Voorbeeld is ingeschakeld op een HTML-document kunnen ook alle gekoppelde CSS-documenten worden bewerkt. Het icoontje verandert van grijs naar goud als Brackets verbinding heeft met de browser.\n        \n        Hierna plaats je je cursor op de <!-- <img> --> tag hierboven. Let op de blauwe markering die verschijnt rond het beeld in Chrome. Vervolgens drukt u op <kbd>Cmd/Ctrl + E</kbd> om de gedefinieerde CSS-regels te laten zien. Probeer de grootte van de rand te veranderen van 10px naar 20px of verander de achtergrondkleur van \"transparent\" naar \"hotpink\". Als je Brackets en je browser naast elkaar hebt weergegeven, zie je dat de wijzigingen meteen worden weergegeven in zowel de browser als in Brackets. Cool toch?</samp>\n\n        <p class=\"note\">\n            Vandaag de dag ondersteunt Brackets alleen Live Preview voor HTML en CSS. We zijn momenteel bezig met een Live Preview ondersteuning voor JavaScript. Live-previews zijn ook alleen mogelijk met Google Chrome, maar we hopen dat deze functionaliteit in de toekomst voor alle belangrijke browsers beschikbaar is.\n        </p>\n\n        <h3>Quick View</h3>\n\n        <p>Voor iedereen die de waardes voor HEX en RGB nooit geleerd hebben, heeft Brackets iets om snel en eenvoudig een bepaalde kleur te laten zien. Voor zowel CSS of HTML werkt het als volgt: je zet gewoon je cursor op een kleurwaarde of gradiënt en Brackets geeft een voorbeeld van de kleur. Hetzelfde geldt voor afbeeldingen: je zet je cursor op een link die naar een afbeelding leidt en Brackets laat een thumbnail zien van dat beeld.</p>\n\n        <samp>\n            To try out Quick View for yourself, place your cursor on the <!-- <body> --> tag at the top of this\n            document and press <kbd>Cmd/Ctrl + E</kbd> to open a CSS quick editor. Now simply hover over any of the\n            color values within the CSS. You can also see it in action on gradients by opening a CSS quick editor\n            on the <!-- <html> --> tag and hovering over any of the background image values. To try out the image\n            preview, place your cursor over the screenshot image included earlier in this document.\n        </samp>\n        <samp>\n            Om Quick View uit te proberen voor jezelf, plaats je je cursor op de <!-- <body> --> tag bovenaan dit document en druk op <kbd>Cmd/Ctrl + E</kbd> om de Quick Editor voor CSS te openen. Ga nu met de muis over een kleurwaarde heen en je ziet de kleur. Je kunt met deze functie ook gradiënts zien door met de cursor op de <!-- <html> --> tag te staan en met de cursor over een van de afbeeldingskoppelingen te gaan. Om dit uit te proberen, plaats je muis over de afbeelding van het screenshot in dit document.\n        </samp>\n\n\n        <h3>Verder nog iets? Gebruik een extension!</h3>\n        <p>Naast al deze functies die zijn ingebouwd in Brackets, heeft onze grote en groeiende gemeenschap van extensie-ontwikkelaars meer dan honderd extensies gebouwd die nuttige functionaliteiten toevoegen. Mis je iets wat Brackets niet aanbiedt? Dan heeft waarschijnlijk iemand het al gebouwd in een extensie. Om te bladeren of de lijst met extensies te zoeken, ga naar <strong>Bestand &gt; Uitbreidingbeheer</strong> en klik op de \"Beschikbaar\" tab. Als je een extensie vindt die je wil, klik je gewoon op de \"Installeer\" knop.\n        </p>\n\n        <h3>Projecten in Brackets</h3>\n        <p>\n            Om je eigen code te bewerken met Brackets, kun je gewoon een map openen met je bestanden. Brackets behandelt de geopende map als een \"project\"; met functies zoals Code Hints, Live Voorbeelden en Quick Edit gebruiken alleen de bestanden in de geopende map.\n        </p>\n\n        <samp>\n            Zodra u klaar bent om dit voorbeeldproject te bewerken en uw eigen code toe te voegen, kunt u de dropdown gebruiken in de linker zijbalk. Op dit moment is er automatisch gekozen voor de map \"Aan de slag\" - dat is de map met het bestand waar je nu in bezig bent. Klik op de dropdown en kies \"Open map...\" om uw eigen map te openen. Je kunt de dropdown later ook gebruiken om terug te schakelen naar de mappen die je eerder hebt geopend, inclusief dit voorbeeldproject.\n        </samp>\n\n        <!--\n            LAAT ONS WETEN WAT JIJ DENKT\n        -->\n        <h2>Doe mee</h2>\n        <p>\n            Brackets is een open-source project. Web ontwikkelaars over de hele wereld dragen bij om samen een betere code-editor te bouwen. Veel meer extensies die mogelijkheden van Brackets uitbreiden. Laat ons weten wat je denkt, geef ons uw ideeën of draag direct bij aan het project.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a>\n            </li>\n            <li><a href=\"http://blog.brackets.io\">Brackets Team Blog</a>\n            </li>\n            <li><a href=\"http://github.com/adobe/brackets\">Brackets op GitHub</a>\n            </li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets Extension Uitbreiding</a>\n            </li>\n            <li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a>\n            </li>\n            <li><a href=\"http://groups.google.com/group/brackets-dev\">Brackets Ontwikkelaar Mail Verzendlijst</a>\n            </li>\n            <li><a href=\"https://twitter.com/#!/brackets\">@brackets op Twitter</a>\n            </li>\n            <li>Chat met Brackets ontwikkelaars op IRC via #brackets op Freenode</li>\n        </ul>\n\n</body>\n\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/nl/Aan-de-slag/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/pl/Szybki Start/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>SZYBKI START Z BRACKETS</title>\n        <meta name=\"description\" content=\"Interaktywny poradnik szybkiego startu dla Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n\t\t<h1>SZYBKI START Z BRACKETS</h1>\n\t\t<h2>Oto Twój przewodnik!</h2>\n\t\t\n\t\t<!--\n\t\t\tWYKONANO PRZY UŻYCIU <3 I JAVASCRIPTU\n\t\t-->\n\t\t\n\t\t<p>\n\t\t\tWitaj we wczesnej wersji Brackets, edytorze open-source dla sieci nowej generacji. Jesteśmy\n\t\t\twielkimi fanami standardów i chcemy budować lepsze narzędzia dla takich języków jak JavaScript,\n\t\t\tHTML i CSS oraz powiązanych z nimi technologii sieciowych. Taki był nasz skromny początek.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tCZYM JEST BRACKETS?\n\t\t-->\n\t\t<p>\n\t\t\t<em>Patrzysz na wczesną wersję Brackets.</em>\n\t\t\tNa wiele sposobów Brackets jest inny niż typowy edytor. Jedną z różnic jest to, że edytor ten\n\t\t\tzostał napisany w języku JavaScript. Tak więc, mimo iż może on nie być jeszcze gotowy do\n\t\t\tcodziennego użytku, my używamy go codziennie, by budować Brackets.\n\t\t</p>\n\t\t\n\t\t\n\t\t<h2>Testujemy kilka nowych rzeczy</h2>\n\t\t\n\t\t<!--\n\t\t\tPOWIĄZANIE POMIĘDZY HTML, CSS i JAVASCRIPT\n\t\t-->\n\t\t<h3>Szybka edycja CSS i JavaScript</h3>\n\t\t<p>\n\t\t\tPodczas edycji HTMLa użyj skrótu <kbd>Cmd/Ctrl + E</kbd> aby otworzyć szybki wbudowany edytor,\n\t\t\tktóry wyświetli wszystkie powiązane style CSS. Wykonaj modyfikacje w kodzie CSS, wciśnij <kbd>ESC</kbd>\n\t\t\ti wróć do edycji HTML. Możesz również pozostawić wbudowany edytor otwarty, tak aby stał się częścią\n\t\t\tedytora HTML. Jeśli wciśniesz <kbd>ESC</kbd> poza obszarem szybkiego edytora, jego wszystkie okna\n\t\t\tzostaną zamknięte. Koniec z przełączaniem się pomiędzy dokumentami i byciem wyrwanym z kontekstu.\n\t\t</p>\n\t\t\n\t\t<samp>\n\t\t\tChcesz go zobaczyć w akcji? Umieść kursor w tagu <!-- <samp> --> i naciśnij <kbd>Cmd/Ctrl + E</kbd>.\n\t\t\tSzybki edytor CSS pojawi się nad tym tagiem. Po prawej stronie zobaczysz listę wszystkich reguł,\n\t\t\tktóre są powiązane z tym tagiem. Przełączaj się pomiędzy regułami używając skrótu <kbd>Alt + Góra/Dół</kbd>\n\t\t\taby znaleźć ten, który chcesz edytować.\n\t\t</samp>\n\t\t\n\t\t<a href=\"screenshots/quick-edit.png\">\n\t\t\t<img alt=\"Zrzut ekranu pokazujący szybką edycję CSS\" src=\"screenshots/quick-edit.png\" />\n\t\t</a>\n\t\t\n\t\t<p>\n\t\t\tMożesz użyć tego samego skrótu w kodzie JavaScript, aby zobaczyć kod funkcji, którą przywołujesz,\n\t\t\tpoprzez umieszczenie kursora na nazwie funkcji. W ten sam sposób możesz również otworzyć narzędzie\n\t\t\twybierania koloru. Po prostu umieść kursor na dowolnym kolorze zapisanym w formacie hex, rgb lub hsl.\n\t\t\tNa razie wbudowany szybki edytor nie może być niezagnieżdżony, więc możesz używać go jedynie w \"pełnowymiarowym\"\n\t\t\tedytorze.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tBŁYSKAWICZNY PODGLĄD\n\t\t-->\n\t\t<h3>Zmiany w kodzie CSS widoczne na żywo w przeglądarce</h3>\n\t\t<p>\n\t\t\tZapewne znany Ci jest taniec w stylu \"zapisz/przeładuj\", który wykonywaliśmy przez ostatnie lata.\n\t\t\tDokonujesz zmian w edytorze, zapisujesz zmiany, przełączasz się do przeglądarki i odświeżasz stronę,\n\t\t\tby w końcu zobaczyć rezultat Twojej pracy. Z Brackets taki taniec nie jest konieczny.\n\t\t</p>\n\t\t<p>\n\t\t\tBrackets utworzy <em>połączenie na żywo</em> z Twoją lokalną przeglądarką i będzie jej przekazywał\n\t\t\twszelkie zmiany w CSS. Być może już dzisiaj korzystasz z podobnego rozwiązania przy użyciu narzędzi\n\t\t\tw przeglądarce, jednak z Brackets nie ma potrzeby wklejania kodu CSS z powrotem do edytora. Twój kod\n\t\t\tdziała w przeglądarce, ale żyje w edytorze.\n\t\t</p>\n\t\t\n\t\t<samp>\n\t\t\tJeśli posiadasz zainstalowaną przeglądarkę Google Chrome, możesz wypróbować to już teraz. Kliknij\n\t\t\tikonkę błyskawicy (stąd nazwa: Błyskawiczny Podgląd) w prawym górnym rogu lub naciśnij skrót\n\t\t\t<kbd>Cmd/Ctrl + Alt + P</kbd>. Kiedy Błyskawiczny Podgląd zostanie włączony w dokumencie HTML,\n\t\t\twszystkie połączone z nim pliki CSS mogą być edytowane w czasie rzeczywistym. Ikona zmieni kolor\n\t\t\tz szarej na złotą gdy Błyskawiczny Podgląd nawiąże połączenie z Twoją przeglądarką.\n\t\t\t\n\t\t\tTeraz umieść kursor na tagu <!-- <img> --> i wciśnij <kbd>Cmd/Ctrl + E</kbd> aby otworzyć zdefiniowane\n\t\t\tstyle CSS dla tego tagu. Spróbuj zmienić rozmiar obramowania z 10px do 20px lub zmienić kolor tła\n\t\t\tz \"transparent\" na \"hotpink\". Jeśli masz umieszczone okna przeglądarki i Brackets obok siebie\n\t\t\tzobaczysz, że zmiany są natychmiast uwzględniane w przeglądarce. Nieźle, co?\n\t\t</samp>\n\t\t\t\t\n\t\t<p class=\"note\">\n\t\t\tNa dzień dzisiejszy Błyskawiczny Podgląd działa jedynie dla plików CSS. Aktualnie pracujemy nad tym,\n\t\t\taby dodać obsługę plików HTML i JavaScript. W aktualnej wersji zmiany w plikach HTML lub JavaScript\n\t\t\tsą automatycznie uwzględniane w momencie zapisu. Błyskawiczny Podgląd działa jedynie z Google Chrome.\n\t\t\tPragniemy wprowadzić tą funkcję we wszystkich najważniejszych przeglądarkach i mamy nadzieję na\n\t\t\twspółpracę ze strony autorów tych przeglądarek, by stało się to faktem.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tDAJ ZNAĆ CO O TYM SĄDZISZ\n\t\t-->\n\t\t<h2>Zaangażuj się</h2>\n\t\t<p>\n\t\t\tBrackets jest projektem open-source. Web developerzy z całego świata angażują się, by budować coraz\n\t\t\tto lepszy edytor kodu. Daj nam znać co o nim sądzisz, podziel się swoimi pomysłami lub dodaj coś\n\t\t\tbezpośrednio do projektu.\n\t\t</p>\n\t\t<ul>\n\t\t\t<li><a href=\"http://brackets.io\">Brackets.io</a></li>\n\t\t\t<li><a href=\"http://blog.brackets.io\">Blog Zespołu Brackets</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets\">Brackets na GitHub</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n\t\t\t<li><a href=\"http://groups.google.com/group/brackets-dev\">Developerska Lista Mailingowa Brackets</a></li>\n\t\t\t<li><a href=\"https://twitter.com/#!/brackets\">@Brackets na Twitterze</a></li>\n\t\t\t<li>Czatuj z developerami Brackets na IRCu w kanale #brackets na Freenode.</li>\n\t\t</ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/pl/Szybki Start/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/pt-br/Primeiros Passos/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>PRIMEIROS PASSOS COM BRACKETS</title>\n        <meta name=\"description\" content=\"Um guia interativo de primeiros passos para o Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n    <h1>PRIMEIROS PASSOS COM O BRACKETS</h1>\n    <h2>Este é o seu guia!</h2>\n    \n    <!--\n        FEITO COM <3 E JAVASCRIPT\n    -->\n    \n    <p>\n        Bem-vindo ao Brackets, um moderno editor de código open-source que entende de web design. Leve, mas poderoso, ele combina ferramentas visuais no editor para que você obtenha a quantidade certa de ajuda quando precisar.\n    </p>\n    \n    <!--\n        O QUE É O BRACKETS?\n    -->\n        \n    <p>\n        <em>O Brackets é um editor diferente.</em>\n        O Brackets tem algumas características únicas, como a Edição Rápida (Quick Edit), Visualização ao vivo (Live Preview) e muitas outras que você não encontrará em outros editores. E o Brackets é escrito em JavaScript, HTML e CSS. Isso significa que a maioria de vocês que utilizam o Brackets possuem as habilidades necessárias para modificar e estender o editor. Na verdade, usamos o Brackets todos os dias para desenvolver o Brackets. Para saber mais sobre como utilizar os principais recursos, continue lendo.\n    </p>\n    \n    \n    <!--\n        COMECE COM SEUS PRÓPRIOS ARQUIVOS\n    -->\n    \n    <h3>Projetos no Brackets</h3>\n    <p>\n        Para editar seu próprio código utilizando o Brackets, basta abrir a pasta contendo seus arquivos. O Brackets trata a pasta atualmente aberta como um \"Projeto\", recursos como Code Hints, Live Preview e Quick Edit usam apenas os arquivos da pasta atualmente aberta.\n    </p>\n        \n    <samp>\n        Assim que você estiver pronto para sair desse projeto exemplo e editar seu próprio código, você pode usar o menu na barra lateral para trocar de pasta. Nesse momento, o menu diz \"Primeiros Passos\" - que é a pasta que possui o arquivo que você está olhando agora mesmo. Clique no menu e escolha \"Abrir pasta...\" para abrir sua própria pasta.\n        Também é possível utilizar o menu para voltar a pastas que você abriu anteriormente, incluindo esse projeto de exemplo.\n    </samp>\n    \n    <!--\n        A RELAÇÃO ENTRE HTML, CSS E JAVASCRIPT\n    -->\n        \n    <h3>Quick Edit (Edição Rápida) de CSS e JavaScript</h3>\n    <p>\n        Sem mais necessidade de ficar trocando entre seus arquivos e perder o contexto. Quando estiver editando HTML, use o atalho <kbd>Cmd/Ctrl + E</kbd> para abrir um rápido editor em linha (quick inline editor) que mostra todo o CSS relacionado.\n        Faça uma modificação no seu CSS, aperte <kbd>ESC</kbd> e você está de volta a edição do HTML, ou apenas deixe as regras CSS abertas e elas se tornarão parte do seu editor HTML. Se você apertar <kbd>ESC</kbd> fora do quick inline editor, todos eles irão se recolher. Quick Edit também encontrará regras definidas em arquivos LESS e SCSS, incluindo regras aninhadas.\n    </p>\n    \n    <samp>\n        Quer vê-lo em ação? Coloque o cursor sobre a tag <!-- <samp> --> acima e pressione <kbd>Cmd/Ctrl + E</kbd>. Você deverá ver um editor rápido de CSS aparecer acima, mostrando as regras CSS que estão aplicadas a ele. Quick Edit funciona em classes e atributos id também. Você pode usá-lo com seus arquivos LESS e SCSS também.\n        \n        Você pode criar novas regras da mesma maneira. Clique em uma das tags <!-- <p> --> acima e aperte <kbd>Cmd/Ctrl + E</kbd>. Não existem regras para ele nesse momento, mas você pode clicar no botão Nova Regra e adicionar uma nova regra para <!-- <p> -->.\n    </samp>\n    \n    <a href=\"screenshots/quick-edit.png\">\n        <img alt=\"Um screenshot mostrando o editor rápido de CSS\" src=\"screenshots/quick-edit.png\" />\n    </a>\n        \n    <p>\n        Você também pode usar o mesmo atalho para editar outras coisas - como funções em JavaScript, cores e funções de tempo de animação - e nós estamos adicionando mais e mais o tempo todo.\n    </p>\n    <p>\n        Por enquanto inline editors não podem ser aninhados, então você só pode usar Quick Edit enquanto o cursor estiver em um editor de tamanho máximo.\n    </p>\n    \n    <!--\n        VISUALIZAÇÃO AO VIVO (LIVE PREVIEW)\n    -->\n        \n    <h3>Visualize alterações no HTML e CSS ao vivo no navegador</h3>\n    <p>\n        Você sabe aquela \"dança salvar/recarregar\" que temos feito há anos? Aquela onde você faz mudanças no seu editor, clica em salvar, alterna para o navegador e então recarrega a página para finalmente ver o resultado? Com o Brackets, você não precisa fazer essa dança.\n    </p>\n    <p>\n        O Brackets vai abrir uma <em>conexão ao vivo</em> com o seu navegador local e vai enviar as atualizações no CSS enquanto você digita! Você já deve estar fazendo alguma coisa como esta hoje com ferramentas baseadas em navegador, mas com o Brackets\n        não há necessidade de copiar e colar o CSS final de volta para o editor. Seu código é executado no navegador, mas vive em seu editor!\n    </p>\n        \n    <h3>Destaque ao vivo de elementos HTML e regras CSS</h3>\n    <p>\n        O Brackets facilita ver como as mudanças no seu HTML e CSS irão afetar a página.\n        Quando seu cursor está em uma regra CSS, o Brackets irá destacar todos os elementos afetados no navegador. Similarmente, quando estiver editando um arquivo HTML, o Brackets irá destacar o elemento HTML correspondente no navegador.\n    </p>\n    \n    <samp>\n        Se você tem o Google Chrome instalado, você pode tentar fazer isso sozinho. Clique no ícone em forma de raio no canto superior direito ou pressione <kbd>Cmd/Ctrl + Alt + P</kbd>. Quando a Visualização ao Vivo (Live Preview) é habilitada em um documento HTML, todos os documentos CSS vinculados podem ser editados em tempo real. O ícone vai mudar de cinza para ouro quando o Brackets estabelecer uma conexão com o seu navegador.\n        \n        Agora, coloque o cursor sobre a tag <!-- <img> --> acima e use <kbd>Cmd/Ctrl + E</kbd> para abrir as regras CSS definidas. Tente mudar o tamanho da borda de 10px para 20px ou alterar a cor de fundo de \"transparent\" para \"hotpink\". Se você tem o Brackets e seu navegador rodando lado a lado, você vai ver as alterações refletidas instantaneamente no seu navegador. Legal, certo?\n    </samp>\n    \n    <p class=\"note\">\n        Atualmente, o Brackets suporta Visualização ao Vivo (Live Preview) apenas para HTML e CSS. Entretanto, na versão atual, mudanças nos arquivos JavaScript são automaticamente carregadas quando você salva. Estamos trabalhando no suporte à Visualização ao Vivo para JavaScript. Visualizações ao vivo atualmente só são possíveis com Google Chrome, mas nós esperamos trazer essa funcionalidade para os principais navegadores no futuro.\n    </p>\n    \n    <h3>Quick View</h3>\n    <p>\n        Para aqueles de nós que ainda não memorizaram os códigos de cores equivalentes para HEX e RGB, o Brackets facilita ver exatamente qual cor está sendo utilizada. Tanto no CSS quanto no HTML, basta passar o mouse por cima de qualquer valor de cor ou gradiente que o Brackets irá mostrar uma pré-visualização da cor/gradiente. O mesmo vale para imagens: passe o mouse por cima do link da imagem no Brackets  e ele irá mostrar uma pré-visualização dessa imagem.\n    </p>\n        \n    <samp>\n        Tente o Quick View você mesmo, passe o cursor na tag <!-- <body> --> no topo desse documento e aperte <kbd>Cmd/Ctrl + E</kbd> para abrir o editor rápido de CSS. Agora simplesmente passe o mouse por cima de qualquer um dos valores de cor no CSS. Você também pode ver isso em ação em gradientes abrindo um editor rápido de CSS na tag <!-- <html> --> e passando o mouse por qualquer um dos dos valores de background-image. Tente também a pré-visualização de imagens, coloque o mouse sobre o link de screenshot incluído anteriormente nesse documento.\n    </samp>\n        \n    <h3>Precisa de algo mais? Tente uma extensão!</h3>\n    <p>\n        Além de todas as coisas boas construídas no Brackets, nossa grande comunidade de desenvolvedores de extensões tem construído centenas de extensões que adicionam funcionalidades uteis ao editor. Se tem algo que você precisa que o Brackets não oferece, mais do que provavelmente alguém já construiu uma extensão para isso. Para pesquisar na lista de extensões disponíveis, escolha <strong>Arquivo > Gerenciador de Extensões...</strong> e clique na aba \"Disponíveis\". Quando encontrar uma extensão que você quer, apenas clique no botão \"Instalar\" ao lado.\n    </p>\n        \n    <!--\n        DEIXE-NOS SABER O QUE VOCÊ PENSA\n    -->\n        \n    <h2>Envolva-se</h2>\n    <p>\n        O Brackets é um projeto open-source. Desenvolvedores web de todo o mundo estão a contribuir para criar um editor de código melhor. Muitos outros estão desenvolvendo extensões que espandem as capacidades do Brackets. \n        Diga-nos o que você pensa, compartilhe as suas ideias ou contribua diretamente para o projeto.\n    </p>\n    <ul>\n        <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n        <li><a href=\"http://blog.brackets.io\">Blog da Equipe Brackets</a></li>\n        <li><a href=\"http://github.com/adobe/brackets\">Brackets no GitHub</a></li>\n        <li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n        <li><a href=\"http://groups.google.com/group/brackets-dev\">Mailing List Desenvolvedores Brackets</a></li>\n        <li><a href=\"https://twitter.com/brackets\">@Brackets no Twitter</a></li>\n        <li>Fale com os desenvolvedores no canal IRC #brackets no Freenode</li>\n    </ul>\n\n    </body>\n</html>\n\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/pt-br/Primeiros Passos/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/pt-pt/Primeiros Passos/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>PRIMEIROS PASSOS COM BRACKETS</title>\n        <meta name=\"description\" content=\"An interactive getting started guide for Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n\t\t<h1>PRIMEIROS PASSOS COM BRACKETS</h1>\n\t\t<h2>Este é o teu guia!</h2>\n\t\t\n\t\t<!--\n\t\t\tFEITO COM <3 E JAVASCRIPT\n\t\t-->\n\t\t\n\t\t<p>\n\t\t\tBem vindo a esta pré-vizualização do Brackets, um novo editor open-source para a proxima geração web.\n\t\t\tSomos grandes fãs de padrões e queremos construir uma melhor ferramenta para JavaScript, HTML e CSS e relacionadas\n\t\t\tcom tecnologias web abertas. Este é o nosso humilde começo.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tO QUE É O BRACKETS?\n\t\t-->\n\t\t<p>\n\t\t\t<em>Estás a olhar para uma versão antecipada of Brackets</em>\n\t\t\tEm muitas formas, Brackets é um tipo de editor diferente. Uma grande diferença é que este editor é escrito em JavaScript.\n\t\t\tEmbora o Brackets possa não estar pronto para o use dia-a-dia por enquanto, estamos a usa-lo todos os dias para construir o Brackets.\n\t\t</p>\n\t\t\n\t\t\n\t\t<h2>Estamos a tentar algumas coisas novas</h2>\n\t\t\n\t\t<!--\n\t\t\tA RELAÇÃO ENTRE HTML, CSS E JAVASCRIPT\n\t\t-->\n\t\t<h3>Edição Rápida para CSS e JavaScript</h3>\n\t\t<p>\n\t\t\tAo editar HTML, use as teclas de atalho <kbd>Cmd/Ctrl + E</kbd> para abrir um rapidamente o editor de linha que mostra todo o CSS relacionado.\n\t\t\tFaça uma pequena alteração no seu CSS, pressione <kbd>ESC</kbd> e está de volta a editar HTML.\n\t\t\tOu simplesmente deixe as regras de CSS abertas e elas tornam-se parte do seu editor de HTML.\n\t\t\tSe pressionar a tecla <kbd>ESC</kbd> fora do Editor Rápido, todas elas fecham. Sem mais trocas de ficheiros e perdar o fio à meada.\n\t\t</p>\n\t\t\n\t\t<samp>\n\t\t\tQueres ver isto em acção? Posiciona o teu cursor sobre a tag <!-- <samp> --> e pressiona\n\t\t\t<kbd>Cmd/Ctrl + E</kbd>. Deves ver o Editor Rápido de CSS aparecer.\n\t\t\tNa direita vais ver uma lista de regras CSS relacionadas com essa tag.\n\t\t\tSimplesmente navegue pela list de regras com <kbd>Alt + Up/Down</kbd> para encontrar aquela que queres editar.\n\t\t</samp>\n\t\t\n\t\t<a href=\"screenshots/quick-edit.png\">\n\t\t\t<img alt=\"Um screenshot a mostrar a Edição Rápida de CSS\" src=\"screenshots/quick-edit.png\" />\n\t\t</a>\n\t\t\n\t\t<!--\n\t\t\tLIVE PREVIEW\n\t\t-->\n\t\t<h3>Pré-Vizualizar mudança no CSS ao vivo no navegador</h3>\n\t\t<p>\n\t\t\tSabes que a \"dança guardar/recarregar\" que fizemos por anos? Aquela que fazes uma mudança no editor,\n\t\t\tpressionas guardar, mudas para o navegador e precionas recarregar para ver o resultado?\n\t\t\tCom o Brackets, não precisas de fazer essa dança.\n\t\t</p>\n\t\t<p>\n\t\t\tBrackets abre uma <em>live connection</em> para o teu navegador e envia actualizações do CSS assim que escreves!\n\t\t\tProbavelmente já fazias uma coisa parecida com ferramentas de navegador, mas com o Brackets\n\t\t\tnão é preciso copiar e colar o código CSS final de novo no editor. O teu código corre no navegador, e vive no teu editor!\n\t\t</p>\n\t\t\n\t\t<samp>\n\t\t\tSe tens o Google Chrome instalado, podes tentar isto por ti próprio. Clica no icone do relampago no canto superior direito\n\t\t\tou pressiona <kbd>Cmd/Ctrl + Alt + P</kbd>. Quando o Live Preview está ligado a um documento HTML,\n\t\t\ttodo o css ligado a ele pode ser editado em temo real.\n\t\t\tO icone muda de cinzento para dourado quando o Brackets estabelece a ligação ao navegador.\n\t\t\t\n\t\t\tAgora, ponha o seu curso na tag <!-- <img> --> em cima (linha 56) e pressione <kbd>Cmd/Ctrl + E</kbd> Para abrir as regras CSS para aquela tag.\n\t\t\tTenta mudar o tamanho da borda de 10px par 20px ou muda a cor de fundo de \"transparent\"(nome da cor) para \"hotpink\"(nome da cor).\n\t\t\tSe o Brackets e o teu navegador estão a correr lado-a-lado, vais ver que as mudanças são instantaneas no teu navegador.\n\t\t\tAltamente, certo?\n\t\t</samp>\n\t\t\t\t\n\t\t<p class=\"note\">\n\t\t\tHoje, o Brackets só suporta Live Preview para CSS. Estamos de momento a trabalhar no Live Preview para HTML e JavaScript.\n\t\t\tNa versãp actual, não vai ver mudanças no seu ficheiro HTML até guardar o documento.\n\t\t\tLive previews são só possiveis com Google Chrome. Nós queremos trazer esta funcionalidade para todos os navegadores mais conhecidos,\n\t\t\te estamos ansiosos por trabalhar com esses fornecedores.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tDEIXA-NOS SABER O QUE PENSAS\n\t\t-->\n\t\t<h2>Envolva-se</h2>\n\t\t<p>\n\t\t\tBrackets é um projeto open-source. Desenvolvedores Web de todo o mundo estão a contribuir para construir um melhor editor de código.\n\t\t\tDiz-nos o que pensas, partilha as tuas ideias or contribui diretamente para o projeto.\n\t\t</p>\n\t\t<ul>\n\t\t\t<li><a href=\"http://brackets.io\">Brackets.io</a></li>\n\t\t\t<li><a href=\"http://blog.brackets.io\">Brackets Blog da Equipa</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets\">Brackets no GitHub</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n\t\t\t<li><a href=\"http://groups.google.com/group/brackets-dev\">Brackets Lista de Mails Desenvolvedores</a></li>\n\t\t\t<li><a href=\"https://twitter.com/#!/brackets\">@Brackets no Twitter</a></li>\n\t\t\t<li>Fala com os desenvolvedores do Brackets no IRC em #brackets no Freenode</li>\n\t\t</ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/pt-pt/Primeiros Passos/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/root/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>GETTING STARTED WITH BRACKETS</title>\n        <meta name=\"description\" content=\"An interactive getting started guide for Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>GETTING STARTED WITH BRACKETS</h1>\n        <h2>This is your guide!</h2>\n        \n        <!--\n            MADE WITH <3 AND JAVASCRIPT\n        -->\n        \n        <p>\n            Welcome to Brackets, a modern open-source code editor that understands web design. It's a lightweight,\n            yet powerful, code editor that blends visual tools into the editor so you get the right amount of help\n            when you want it.\n        </p>\n        \n        <!--\n            WHAT IS BRACKETS?\n        -->\n        <p>\n            <em>Brackets is a different type of editor.</em>\n            Brackets has some unique features like Quick Edit, Live Preview and others that you may not find in other\n            editors. Brackets is written in JavaScript, HTML and CSS. That means that most of you using Brackets\n            have the skills necessary to modify and extend the editor. In fact, we use Brackets every day to build\n            Brackets. To learn more about how to use the key features, read on.\n        </p>\n        \n        <!--\n            GET STARTED WITH YOUR OWN FILES\n        -->\n        \n        <h3>Projects in Brackets</h3>\n        <p>\n            In order to edit your own code using Brackets, you can just open the folder containing your files.\n            Brackets treats the currently open folder as a \"project\"; features like Code Hints, Live Preview and\n            Quick Edit only use files within the currently open folder.\n        </p>\n        \n        <samp>\n            Once you're ready to get out of this sample project and edit your own code, you can use the dropdown\n            in the left sidebar to switch folders. Right now, the dropdown says \"Getting Started\" - that's the\n            folder containing the file you're looking at right now. Click on the dropdown and choose \"Open Folder…\"\n            to open your own folder.\n            You can also use the dropdown later to switch back to folders you've opened previously, including this\n            sample project.\n        </samp>\n        \n        <!--\n            THE RELATIONSHIP BETWEEN HTML, CSS AND JAVASCRIPT\n        -->\n        <h3>Quick Edit for CSS and JavaScript</h3>\n        <p>\n            No more switching between documents and losing your context. When editing HTML, use the\n            <kbd>Cmd/Ctrl + E</kbd> shortcut to open a quick inline editor that displays all the related CSS.\n            Make a tweak to your CSS, hit <kbd>ESC</kbd> and you're back to editing HTML, or just leave the\n            CSS rules open and they'll become part of your HTML editor. If you hit <kbd>ESC</kbd> outside of\n            a quick inline editor, they'll all collapse. Quick Edit will also find rules defined in LESS and\n            SCSS files, including nested rules.\n        </p>\n        \n        <samp>\n            Want to see it in action? Place your cursor on the <!-- <samp> --> tag above and press\n            <kbd>Cmd/Ctrl + E</kbd>. You should see a CSS quick editor appear above, showing the CSS rule that\n            applies to it. Quick Edit works in class and id attributes as well. You can use it with your\n            LESS and SCSS files also.\n            \n            You can create new rules the same way. Click in one of the <!-- <p> --> tags above and press\n            <kbd>Cmd/Ctrl + E</kbd>. There are no rules for it right now, but you can click the New Rule\n            button to add a new rule for <!-- <p> -->.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"A screenshot showing CSS Quick Edit\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            You can use the same shortcut to edit other things as well - like functions in JavaScript,\n            colors, and animation timing functions - and we're adding more and more all the time.\n        </p>\n        <p>\n            For now inline editors cannot be nested, so you can only use Quick Edit while the cursor\n            is in a \"full size\" editor.\n        </p>\n        \n        <!--\n            LIVE PREVIEW\n        -->\n        <h3>Preview HTML and CSS changes live in the browser</h3>\n        <p>\n            You know that \"save/reload dance\" we've been doing for years? The one where you make changes in\n            your editor, hit save, switch to the browser and then refresh to finally see the result?\n            With Brackets, you don't have to do that dance.\n        </p>\n        <p>\n            Brackets will open a <em>live connection</em> to your local browser and push HTML and CSS updates as you\n            type! You might already be doing something like this today with browser-based tools, but with Brackets\n            there is no need to copy and paste the final code back into the editor. Your code runs in the\n            browser, but lives in your editor!\n        </p>\n        \n        <h3>Live Highlight HTML elements and CSS rules</h3>\n        <p>\n            Brackets makes it easy to see how your changes in HTML and CSS will affect the page. When your cursor\n            is on a CSS rule, Brackets will highlight all affected elements in the browser. Similarly, when editing\n            an HTML file, Brackets will highlight the corresponding HTML elements in the browser.\n        </p>\n        \n        <samp>\n            If you have Google Chrome installed, you can try this out yourself. Click on the lightning bolt\n            icon in the top right corner of your Brackets window or hit <kbd>Cmd/Ctrl + Alt + P</kbd>. When\n            Live Preview is enabled on an HTML document, all linked CSS documents can be edited in real-time.\n            The icon will change from gray to gold when Brackets establishes a connection to your browser.\n            \n            Now, place your cursor on the <!-- <img> --> tag above. Notice the blue highlight that appears\n            around the image in Chrome. Next, use <kbd>Cmd/Ctrl + E</kbd> to open up the defined CSS rules.\n            Try changing the size of the border from 10px to 20px or change the background\n            color from \"transparent\" to \"hotpink\". If you have Brackets and your browser running side-by-side, you\n            will see your changes instantly reflected in your browser. Cool, right?\n        </samp>\n        \n        <p class=\"note\">\n            Today, Brackets only supports Live Preview for HTML and CSS. However, in the current version, changes to\n            JavaScript files are automatically reloaded when you save. We are currently working on Live Preview\n            support for JavaScript. Live previews are also only possible with Google Chrome, but we hope\n            to bring this functionality to all major browsers in the future.\n        </p>\n        \n        <h3>Quick View</h3>\n        <p>\n            For those of us who haven't yet memorized the color equivalents for HEX or RGB values, Brackets makes\n            it quick and easy to see exactly what color is being used. In either CSS or HTML, simply hover over any\n            color value or gradient and Brackets will display a preview of that color/gradient automatically. The\n            same goes for images: simply hover over the image link in the Brackets editor and it will display a\n            thumbnail preview of that image.\n        </p>\n        \n        <samp>\n            To try out Quick View for yourself, place your cursor on the <!-- <body> --> tag at the top of this\n            document and press <kbd>Cmd/Ctrl + E</kbd> to open a CSS quick editor. Now simply hover over any of the\n            color values within the CSS. You can also see it in action on gradients by opening a CSS quick editor\n            on the <!-- <html> --> tag and hovering over any of the background image values. To try out the image\n            preview, place your cursor over the screenshot image included earlier in this document.\n        </samp>\n        \n        <h3>Need something else? Try an extension!</h3>\n        <p>\n            In addition to all the goodness that's built into Brackets, our large and growing community of\n            extension developers has built hundreds of extensions that add useful functionality. If there's\n            something you need that Brackets doesn't offer, more than likely someone has built an extension for\n            it. To browse or search the list of available extensions, choose <strong>File > Extension\n            Manager…</strong> and click on the \"Available\" tab. When you find an extension you want, just click\n            the \"Install\" button next to it.\n        </p>\n        \n        <!--\n            LET US KNOW WHAT YOU THINK\n        -->\n        <h2>Get involved</h2>\n        <p>\n            Brackets is an open-source project. Web developers from around the world are contributing to build\n            a better code editor. Many more are building extensions that expand the capabilities of Brackets.\n            Let us know what you think, share your ideas or contribute directly to the project.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets Team Blog</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">Brackets on GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets Extension Registry</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets Developer Mailing List</a></li>\n            <li><a href=\"https://twitter.com/brackets\">@brackets on Twitter</a></li>\n            <li>Chat with Brackets developers on IRC in <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">#brackets on Freenode</a></li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/root/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/ru/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>НАЧАЛО РАБОТЫ С BRACKETS</title>\n        <meta name=\"description\" content=\"Интерактивное руководство по началу работы в Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n\t\t<h1>НАЧАЛО РАБОТЫ С BRACKETS</h1>\n\t\t<h2>Ваше личное руководство!</h2>\n\t\t\n\t\t<!--\n\t\t\tСДЕЛАНО С <3 И JAVASCRIPT\n\t\t-->\n\t\t\n\t\t\n\t\t<p>\n\t\t\tДобро пожаловать в раннюю версию Brackets, нового редактора с открытым исходным\n\t\t\tкодом для веба следующего поколения. Мы большие фанаты стандартов и хотим построить лучший\n\t\t\tинструмент для JavaScript, HTML и CSS и связанных с ними открытых веб-технологий. Это наше\n\t\t\tскромное начало.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tЧТО ТАКОЕ BRACKETS?\n\t\t-->\n\t\t<p>\n\t\t\t<em>Во многих отношениях, Brackets необычный редактор.</em>\n\t\t\tОдна примечательная особенность в том, что этот редактор написан на JavaScript,\n\t\t\tHTML and CSS. Это означает, что большинство пользователей Brackets имеют навыки\n\t\t\tнеобходимые для доработки и расширения редактора. На самом деле, мы используем Brackets\n\t\t\tкаждый день для того, чтобы улучшать Brackets. Он так же имеет несколько особенностей\n\t\t\tвроде Быстрого Редактирования, Интерактивного Просмотра и других, которые вы не сможете\n\t\t\tнайти в других редакторах.\n\t\t\tЧитайте далее для того чтобы узнать, как использовать эти особенности редактора.\n\t\t</p>\n\t\t\n\t\t\n\t\t<h2>Мы испытываем несколько новых штук</h2>\n\t\t\n\t\t<!--\n\t\t\tОТНОШЕНИЯ МЕЖДУ HTML, CSS И JAVASCRIPT\n\t\t-->\n\t\t<h3>Быстрое редактирование CSS и JavaScript</h3>\n\t\t<p>\n\t\t\tТеперь никакого переключения между документами и потери контекста. Во время редактирования HTML\n\t\t\tиспользуйте сочетание клавиш <kbd>Cmd/Ctrl + E</kbd> для открытия быстрого редактора, который показывает\n\t\t\tвсе связанное с этой строкой CSS. Сделайте изменение CSS-стилей, нажмите <kbd>ESC</kbd> и вернитесь обратно\n\t\t\tк редактированию HTML. Или просто оставьте блок с CSS-правилами открытым, и они станут частью вашего\n\t\t\tHTML-редактора. Если вы нажмете <kbd>ESC</kbd> вне быстрого редактора, все CSS-правила закроются.\n\t\t</p>\n\t\t\n\t\t<samp>\n\t\t\tХотите увидеть это в действии? Поставьте курсор на теге <!-- <samp> --> выше и нажмите\n\t\t\t<kbd>Cmd/Ctrl + E</kbd>. Вы должны увидеть, как выше появится быстрый редактор CSS. Справа вы\n\t\t\tувидите список CSS-правил, которые относятся к этому тегу. Просто прокрутите правила вниз, используя\n\t\t\t<kbd>Alt + Up/Down</kbd>, чтобы найти то, которое вы хотите отредактировать.\n\t\t</samp>\n\t\t\n\t\t<a href=\"screenshots/quick-edit.png\">\n\t\t\t<img alt=\"A screenshot showing CSS Quick Edit\" src=\"screenshots/quick-edit.png\" />\n\t\t</a>\n\t\t\n\t\t<p>\n\t\t\tВы так же можете использовать эти горячие клавиши при работе с кодом JavaScript,\n\t\t\tдля того, чтобы увидеть содержание функции, просто наведите курсор на её название.\n\t\t\tНа данный момент внутри встроенного редактора нельзя открыть еще один, поэтому вы можете\n\t\t\tиспользовать только Быстрое Редактирование, когда курсор находится в \"полноэкранном\" редакторе.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tИНТЕРАКТИВНЫЙ ПРОСМОТР\n\t\t-->\n\t\t<h3>Просматривайте изменения CSS вживую в браузере!</h3>\n\t\t<p>\n\t\t\tВы знаете эти пляски с \"сохранить/перезагрузить\", которые мы делаем годами? Когда вы делаете\n\t\t\tизменения в вашем редакторе, нажимаете сохранить, переключаетесь в браузер и затем нажимаете\n\t\t\tперезагрузить, чтобы наконец увидеть результат? Вместе с Brackets этого больше не придется делать.\n\t\t</p>\n\t\t<p>\n\t\t\tBrackets откроет <em>прямое соединение</em> с вашим локальным браузером и направит ваши изменения CSS, как\n\t\t\tтолько вы их напечатаете! Вы, возможно, уже делали что-то подобное с инструментами, встроенными в браузер,\n\t\t\tно с Brackets больше нет нужды копировать и вставлять финальный CSS обратно в редактор.\n\t\t\tВаш код запускается в браузере, но живет в вашем редакторе!\n\t\t</p>\n\t\t<h3>Подсвечивание HTML-элементов и CSS-правил в реальном времени</h3>\n\t\t<p>\n\t\t   С Brackets стало проще понять, как изменения в HTML и CSS отразятся на странице. Когда ваш курсор находится на\n\t\t   CSS-правиле, Brackets подсветит все затронутые элементы в браузере. То же самое и с редактированием HTML-файла,\n\t\t   Brackets будет подсвечивать соответсвующие HTML-элементы в браузере.\n\t\t</p>\n\t\t<samp>\n\t\t\tЕсли у вас есть установленный Google Chrome, вы можете попробовать это сами. Нажмите на иконку\n\t\t\tмолнии в правом верхнем углу или нажмите <kbd>Cmd/Ctrl + Alt + P</kbd>. Когда Интерактивный Просмотр\n\t\t\tвключен в HTML-документе, все подключенные CSS-документы могут редактироваться в реальном\n\t\t\tвремени. Иконка изменится с серой на золотую, когда Brackets установит соединение с вашим браузером.\n\t\t\t\n\t\t\tТеперь, поставьте курсор на теге <!-- <img> --> выше и используйте <kbd>Cmd/Ctrl + E</kbd>, чтобы\n\t\t\tоткрыть записанные CSS-правила. Попробуйте изменить размер границы с 10 пикселя до 20 или изменить\n\t\t\tцвет фона с \"transparent\" на \"hotpink\". Если Brackets и ваш браузер работают вместе, вы увидите, как ваши\n\t\t\tизменения мгновенно отразятся в вашем браузере. Круто, правда?\n\t\t</samp>\n\t\t\t\t\n\t\t<p class=\"note\">\n\t\t\tСегодня, Brackets поддерживает Интерактивный Просмотр только для CSS. Сейчас мы работаем над поддержкой\n\t\t\tИнтерактивного Просмотра для HTML и JavaScript. В текущей версии вы не увидите изменений в вашем HTML-\n\t\t\tили JavaScript-файле до тех пор, пока не сохраните документ. Интерактивный Просмотр работает только с\n\t\t\tGoogle Chrome. Но в будушем мы планируем добавить эту возможность для всех основных браузеров.\n\t\t</p>\n\t\t<h3>Быстрый просмотр</h3>\n\t\t<p>\n\t\t\tДля тех из нас, кто до сих пор не запомнил значения цветов для HEX или RGB, Brackets позволяет быстро и просто\n\t\t\tпосмотреть напрямую, какой цвет используется. В любом CSS- или HTML-файле, просто наведите курсор на значение\n\t\t\tцвета или градиента и Brackets автоматически отобразит этот цвет/градиент. То же самое и с изображениями:\n\t\t\tпросто наведите курсор на ссылку с изображением в редакторе и Brackets выведет миниатюру этого изображения.\n\t\t</p>\n\t\t\t\t\n\t\t<samp>\n\t\t\t  Попробуйте быстрый просмотр сами, поместите курсор на тэг <!-- <body> --> вверху этого документа и нажмите\n\t\t\t  <kbd>Cmd/Ctrl + E</kbd> для того, чтобы открыть быстрый редактор CSS. Сейчас просто наведите курсор на любое\n\t\t\t  значение цвета в CSS. Вы так же можете увидеть это в действии с градиентом, открыв быстрый редактор CSS на\n\t\t\t  тэге <!-- <html> --> и наведя курсор на любое значение фонового рисунка. Попробуйте быстрый просмотр изображений,\n\t\t\t  поместите ваш курсор на любой скриншот в этом документе.\n\t\t</samp>\n\t\t\n\t\t<!--\n\t\t\tРАССКАЖИТЕ, ЧТО ВЫ ДУМАЕТЕ\n\t\t-->\n\t\t<h2>Принимайте участие</h2>\n\t\t<p>\n\t\t\tBrackets &mdash; проект с открытым исходным кодом. Веб-разработчики со всех уголков мира способствуют\n\t\t\tсозданию лучшего редактора кода. Многие разрабатывают дополнения, которые расширяют возможности\n\t\t\tBrackets. Расскажите нам, что вы думаете, поделитесь идеями или непосредственно поддержите проект.\n\t\t</p>\n\t\t<ul>\n\t\t\t<li><a href=\"http://brackets.io\">Brackets.io</a></li>\n\t\t\t<li><a href=\"http://blog.brackets.io\">Блог команды Brackets</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets\">Brackets на GitHub</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n\t\t\t<li><a href=\"http://groups.google.com/group/brackets-dev\">Почтовая рассылка разработчиков Brackets</a></li>\n\t\t\t<li><a href=\"https://twitter.com/#!/brackets\">@Brackets в Twitter</a></li>\n\t\t\t<li>Общайтесь с разработчиками Brackets в IRC в #brackets на Freenode</li>\n\t\t</ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/ru/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/sv/Kom igang/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>KOM IGÅNG MED BRACKETS</title>\n        <meta name=\"description\" content=\"En interaktiv genomgång av Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n        <h1>KOM IGÅNG MED BRACKETS</h1>\n        <h2>Detta är din guide!</h2>\n        \n        <!--\n            SKAPAD MED <3 OCH JAVASCRIPT\n        -->\n        \n        <p>\n            Välkommen till en tidig version av Brackets, en ny open-source editor för nästa generation av webben.\n            Vi är hängivna anhängare av webbstandarder och vill bygga bättre verktyg för JavaScript, HTML och CSS\n            samt relaterade öppna webbteknologier. Detta är vårt första ödmjuka steg.\n        </p>\n        \n        <!--\n            VAD ÄR BRACKETS?\n        -->\n        <p>\n            <em>Brackets är en annan typ av editor.</em>\n            En anmärkningsvärd skillnad är att denna editor är skriven i JavaScript, HTML och CSS.\n            Detta innebär att de flesta som använder Brackets har kunskapen som krävs för att förändra och förbättra editorn.\n            Faktum är att vi använder Brackets varje dag, för att bygga Brackets. Det har också ett antal unika funktioner som Quick Edit,\n            Live Preview och och ytterligare några som du inte hittar i andra editorer.\n            Läs vidare för att lära dig mer om dessa funktioner.\n        </p>\n        \n        \n        <h2>Vi provar en del nya saker</h2>\n        \n        <!--\n            FÖRHÅLLANDET MELLAN HTML, CSS OCH JAVASCRIPT\n        -->\n        <h3>Quick Edit för CSS och JavaScript</h3>\n        <p>\n            Du behöver inte längre tappa sammanhanget när du flyttar mellan olika dokument. När du redigerar HTML kan du\n            använda kortkommandot <kbd>Cmd/Ctrl + E</kbd> för att öppna en inline-editor som visar all relaterad CSS.\n            Gör förändringen i din CSS, tryck på <kbd>ESC</kbd> och du är tillbaka i HTML. Du kan också lämna CSS-reglerna\n            öppna och göra dem till en del av din HTML-editor. Om du trycker på <kbd>ESC</kbd> utanför en inline-editor\n            döljs samtliga.\n        </p>\n        \n        <samp>\n            Vill du se hur det fungerar? Placera markören på <!-- <samp> -->-elementet ovan och tryck <kbd>Cmd/Ctrl + E</kbd>.\n            Då visas CSS quick editorn ovan. Till höger kan du se en lista över alla CSS-regler som är relaterade\n            till detta element. Det fungerar även på klass och ID-attribut.\n            \n            Du kan skapa nya regler på samma sätt. Klicka på en av <!-- <p> -->-taggarna ovan och tryck <kbd>Cmd/Ctrl + E</kbd>.\n            Just nu finns det inga regler men genom att klicka på knappen Ny regel skapar du en ny stilregel för <!-- <p> -->-taggar.\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"En skärmdump som visas CSS Quick Edit\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            Samma kortkommandon kan användas även på andra saker, till exempel funktioner i JavaScript för att ändra<br>\n            färger, tidsfunktioner för animering och nya saker läggs till hela tiden!\n            Just nu kan inte inline-editorer nästlas så du kan bara använda Quick Edit från den \"fullstora\" editorn.\n        </p>\n        \n        <!--\n            REALTIDSFÖRHANDSVISNING\n        -->\n        <h3>Förhandsvisa CSS-ändringar direkt i webbläsaren</h3>\n        <p>\n            Du vet den där \"spara och ladda om\"-proceduren vi använt oss av i flera år? Den där du gör\n            en ändring i din editor, sparar, går till webbläsaren och laddar om för att se resultatet?\n            Med Brackets behöver du inte göra det.\n        </p>\n        <p>\n            Brackets öppnar en <em>direktlänk</em> till din lokala webbläsare och skjuter ut dina HTML- och CSS-ändringar\n            medan du skriver! Du kanske redan använder något liknande webbläsarverktyg men med Brackets\n            behöver du inte kopiera och klistra in koden fram och tillbaka mellan webbläsare och editor. Din kod\n            körs i webbläsaren men skrivs i din editor!\n        </p>\n        \n        <h3>Markera HTML-element och CSS-regler i realtid</h3>\n        <p>\n            Brackets gör det enkelt att se hur dina HTML- och CSS-ändringar kommer att påverka sidan. När din markör\n            står på en CSS-regel markerar Brackets samtliga berörda element i webbläsaren. På samma sätt markerar\n            Brackets respektive element i webbläsaren när du redigerar HTML-koden.\n        </p>\n        \n        <samp>\n            Om du har Google Chrome installerat kan du prova denna funktion själv. Klicka på blixtikonen\n            i det övre högra hörnet i ditt Brackets-fönster eller använd kortkommandot <kbd>Cmd/Ctrl + Alt + P</kbd>.\n            När Live Preview är aktiverat i ett HTML-dokument kommer alla länkade CSS-dokument att kunna redigeras\n            i realtid. Ikonens färg kommer att byta färg från grå till guld när Brackets lyckats skapa en länk\n            till din webbläsare.\n            \n            Om du sedan placerar markören på <!-- <img> -->-taggen ovan ser du hur en blå markeringen visas runt\n            bilden i Chrome. Du kan sedan använda <kbd>Cmd/Ctrl + E</kbd> för att visa de relaterade CSS-reglerna.\n            Prova att ändra tjockleken på border-egenskapen från 10px till 20px eller att ändra backgrundsfärgen\n            från \"transparent\" till \"hotpink\". Om Brackets och din webbläsare körs sida vid sida kommer du att se\n            dina ändringar genomföras direkt i webbläsaren. Coolt va?\n        </samp>\n                \n        <p class=\"note\">\n            För tillfället stöder Brackets bara Live Preview för HTML och CSS. Dock laddas webbläsaren automatiskt när du\n            sparar HTML- eller JavaScript-dokument. Vi jobbar för fullt med att utveckla stöd för Live Preview\n            även för JavaScript. Live preview fungerar just nu bara i Google Chrome men med tiden hoppas\n            vi kunna erbjuda denna funktionalitet i alla vanligt förekommande webbläsare.\n        </p>\n                \n        <h3>Quick View</h3>\n        <p>\n            För de av oss som fortfarande inte memorerat färgkoderna för HEX eller RGB gör Brackets det snabbt och\n            enkelt att se vilken färg som används. När du pekar på ett färgvärde eller gradient, i antingen\n            HTML eller CSS, visas en förhandsgranskning av färgen/gradienten automatiskt. Detsamma gäller bilder:\n            peka på bildens sökväg i Brackets så visas en tumnagelversion av bilden.\n        </p>\n        \n        <samp>\n            Du kan prova Quick View själv genom att placera markören på <!-- <body> -->-taggen i början av detta\n            dokument och trycka <kbd>Cmd/Ctrl + E</kbd> för att öppna snabbeditorn för CSS. När du pekar över ett\n            färgvärde i CSS-koden visas motsvarande färg. Du kan utnyttja samma funktion med gradients i snabbeditorn -\n            placera markören på <!-- <html> -->-taggen och peka på dess background-image-egenskap. Du kan också prova\n            förhandvisningen av bilder genom att placera markören vid skärmdumpen tidigare i detta dokument.\n        </samp>\n        \n        <h3>Behöver du någonting annat? Prova ett tillägg!</h3>\n        <p>\n            Utöver alla bra funktioner som är inbyggda i Brackets har vårt stora, och växande, community av\n            tilläggsutvecklare tagit fram mer än hundra tillägg som ger mer användar funktionalitet. Om du saknar\n            någonting i Brackets är det stor chans att att någon redan byggt ett tillägg för att lösa det.\n            För att bläddra eller söka i listan över tillgängliga tillägg går du till <strong>Arkiv > Tilläggshanteraren</strong>\n            och klickar på fliken \"Tillgängliga\". När du hittat ett tillägg du vill ha klickar du bara på knappen \"Installera\"\n            intill det.\n        </p>\n        \n        <!--\n            BERÄTTA FÖR OSS VAD DU TYCKER\n        -->\n        <h2>ENGAGERA DIG</h2>\n        <p>\n            Brackets är ett open-source-projekt. Webbutvecklare från hela världen bidrar för att göra Brackets till\n            en bättre kodeditor. Många andra bygger tillägg som ökar Brackets funktionalitet.\n            Berätta för oss vad du tycker, dina åsiker och idéer eller bidra med kod direkt till projektet.\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets utvecklingsblogg</a></li>\n            <li><a href=\"http://github.com/adobe/brackets\">Brackets på GitHub</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Register över Brackets-tillägg</a></li>\n            <li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n            <li><a href=\"http://groups.google.com/group/brackets-dev\">Brackets Developer Mailing List</a></li>\n            <li><a href=\"https://twitter.com/#!/brackets\">@Brackets på Twitter</a></li>\n            <li>Chatta med Brackets-utvecklare via IRC i #brackets på Freenode</li>\n        </ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/sv/Kom igang/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/uk/Pochynayemo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>ПОЧАТОК РОБОТИ З BRACKETS</title>\n        <meta name=\"description\" content=\"Інтерактивний посібник для початківців в Brackets.\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n\n\t\t<h1>ПОЧАТОК РОБОТИ З BRACKETS</h1>\n\t\t<h2>Ваш власний посібник!</h2>\n\t\t\n\t\t<!--\n\t\t\tЗРОБЛЕНО З <3 І JAVASCRIPT\n\t\t-->\n\t\t\n\t\t\n\t\t<p>\n\t\t\tЛаскаво просимо у ранню версію Brackets, нового редактора з відкритим кодом для вебу \n\t\t\tнаступного покоління. Ми великі фанати стандартів і хочемо побудувати кращий інструмент \n\t\t\tдля JavaScript, HTML і CSS та пов'язаних з ними відкритих веб-технологій. Це наш\n\t\t\tскромний початок.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tЩО ТАКЕ BRACKETS?\n\t\t-->\n\t\t<p>\n\t\t\t<em>Багато у чому, Brackets - незвичайний редактор.</em>\n\t\t\tОдна примітна особливість у тому, що цей редактор написаний на JavaScript,\n\t\t\tHTML та CSS. Це означає, що більшість користувачів Brackets мають необхідні\n\t\t\tнавички для доопрацювання і розширення редактора. Насправді, ми використовуємо Brackets\n\t\t\tкожен день для того, щоб покращувати його. Він так само має декілька особливостей,\n\t\t\tтаких як Швидке Редагування, Інтерактивний Перегляд та інших, які ви не зможете\n\t\t\tзнайти у інших редакторах.\n\t\t\tЧитайте далі для того, щоб дізнатися, як використовувати ці особливості редактора.\n\t\t</p>\n\t\t\n\t\t\n\t\t<h2>Ми випробуємо декілька нових штук</h2>\n\t\t\n\t\t<!--\n\t\t\tВІДНОСИНИ МІЖ HTML, CSS ТА JAVASCRIPT\n\t\t-->\n\t\t<h3>Швидке редагування CSS та JavaScript</h3>\n\t\t<p>\n\t\t\tТепер ніякого перемикання між документами і втрати контексту. Під час редагування HTML використовуйте \n\t\t\tпоєднання клавіш <kbd>Cmd/Ctrl + E</kbd> для відкриття швидкого редактора, який показує все пов'язане \n\t\t\tз цим рядком CSS. Зробіть зміну CSS-стилів, натисніть <kbd>ESC</kbd> і поверніться назад до редагування \n\t\t\tHTML. Або просто залиште блок з CSS-правил відкритим, і вони стануть частиною вашого HTML-редактора. \n\t\t\tЯкщо ви натиснете <kbd>ESC</kbd> поза швидким редактором, усі CSS-правила закриються.\n\t\t</p>\n\t\t\n\t\t<samp>\n\t\t\tХочете побачити це в дії? Поставте курсор на тезі <!-- <samp> --> вище і натисніть\n\t\t\t<kbd>Cmd/Ctrl + E</kbd>. Ви повинні побачити, як вище з'явиться швидкий редактор CSS. Праворуч ви\n\t\t\tпобачите список CSS-правил, які відносяться до цього тегу. Просто прокрутіть правила вниз, використовуючи\n\t\t\t<kbd>Alt + Up/Down</kbd>, щоб знайти те, що ви хочете відредагувати.\n\t\t</samp>\n\t\t\n\t\t<a href=\"screenshots/quick-edit.png\">\n\t\t\t<img alt=\"Скріншот який показує CSS Quick Edit\" src=\"screenshots/quick-edit.png\" />\n\t\t</a>\n\t\t\n\t\t<p>\n\t\t\tВи так само можете використовувати ці гарячі клавіши при роботі з кодом JavaScript,\n\t\t\tдля того, щоб побачити зміст функції, просто наведіть курсор на її назву.\n\t\t\tНа даний момент всередині вбудованого редактора не можна відкрити ще один, тому ви можете\n\t\t\tвикористовувати тільки Швидке Редагування, коли курсор знаходиться у \"повноекранному\" редакторі.\n\t\t</p>\n\t\t\n\t\t<!--\n\t\t\tІНТЕРАКТИВНИЙ ПЕРЕГЛЯД\n\t\t-->\n\t\t<h3>Переглядайте зміни CSS наживо в браузері!</h3>\n\t\t<p>\n\t\t\tВи знаєте цю мороку зі \"зберегти / перезавантажити\", яку ми робимо роками? Коли ви робите\n\t\t\tзміни у вашому редакторі, натискаєте зберегти, перемикаєтеся у браузер і потім натискаєте\n\t\t\tперезавантажити, щоб нарешті побачити результат? Разом з Brackets цього більше не доведеться робити.\n\t\t</p>\n\t\t<p>\n\t\t\tBrackets відкриє <em>пряме з'єднання</em> з вашим локальним браузером та направить ваші зміни CSS, як\n\t\t\tтільки ви їх надрукуєте! Ви, можливо, вже робили щось подібне з інструментами, вбудованими в браузер,\n\t\t\tале з Brackets більше немає потреби копіювати та вставляти фінальний CSS назад у редактор.\n\t\t\tВаш код запускається у браузері, але живе у вашому редакторі!\n\t\t</p>\n\t\t<h3>Підсвічування HTML-елементів і CSS-правил у реальному часі</h3>\n\t\t<p>\n\t\t  З Brackets стало простіше зрозуміти, як зміни в HTML і CSS позначаться на сторінці. Коли ваш курсор \n\t\t\tзнаходиться на CSS-правилі, Brackets підсвітить всі його елементи в браузері. Те ж саме і з редагуванням \n\t\t\tHTML-файлу, Brackets буде підсвічувати відповідні HTML-елементи у браузері.\n\t\t</p>\n\t\t<samp>\n\t\t\tЯкщо у вас є встановлений Google Chrome, ви можете спробувати це самі. Натисніть на іконку\n\t\t\tблискавки у правому верхньому кутку або натисніть <kbd>Cmd/Ctrl + Alt + P</kbd>. Коли Інтерактивний \n\t\t\tПерегляд включений у HTML-документі, всі підключені CSS-документи можуть редагуватися у реальному\n\t\t\tчасі. Іконка зміниться з сірої на золоту, коли Brackets встановить з'єднання з вашим браузером.\n\t\t\t\n\t\t\tТепер, поставте курсор на тезі <!-- <img> --> вище і використовуйте <kbd>Cmd/Ctrl + E</kbd>, щоб\n\t\t\tвідкрити записані CSS-правила. Спробуйте змінити розмір межі з 10 пікселів до 20, або змінити\n\t\t\tколір фону з \"transparent\" на \"hotpink\". Якщо Brackets і ваш браузер працюють разом, ви побачите, \n\t\t\tяк ваші зміни миттєво з'являться у вашому браузері. Круто, правда?\n\t\t</samp>\n\t\t\t\t\n\t\t<p class=\"note\">\n\t\t\tСьогодні, Brackets підтримує Інтерактивний Перегляд тільки для CSS. Зараз ми працюємо над підтримкою\n\t\t\tІнтерактивного Перегляду для HTML та JavaScript. У поточній версії ви не побачите змін в вашому HTML-\n\t\t\tабо JavaScript-файлі до тих пір, поки не збережете документ. Інтерактивний Перегляд працює тільки з\n\t\t\tGoogle Chrome. Але в майбутньому ми плануємо додати цю можливість для всіх основних браузерів.\n\t\t</p>\n\t\t<h3>Швидкий перегляд</h3>\n\t\t<p>\n\t\t\tДля тих з нас, хто до цієї пори не запам'ятав значення кольорів для HEX або RGB, Brackets дозволяє швидко і просто\n\t\t\tподивитися безпосередньо, який колір використовується. У будь-якому CSS- або HTML-файлі, просто наведіть курсор \n\t\t\tна значення кольору або градієнта і Brackets автоматично відобразить цей колір / градієнт. Те ж саме і з зображеннями:\n\t\t\tпросто наведіть курсор на посилання з зображенням у редакторі і Brackets виведе мініатюру цього зображення.\n\t\t</p>\n\t\t\t\t\n\t\t<samp>\n\t\t\tСпробуйте швидкий перегляд самі, помістіть курсор на тег <!-- <body> --> вгорі цього документа і натисніть\n\t\t\t<kbd>Cmd/Ctrl + E</kbd> для того, щоб відкрити швидкий редактор CSS. Зараз просто наведіть курсор на будь-яке\n\t\t\tзначення кольору в CSS. Ви так само можете побачити це в дії з градієнтом, відкривши швидкий редактор CSS на\n\t\t\tтезі <!-- <html> --> та навівши курсор на будь-яке значення фонового малюнка. Спробуйте швидкий перегляд \n\t\t\tзображень, помістіть ваш курсор на будь-який скріншот у цьому документі.\n\t\t</samp>\n\t\t\n\t\t<!--\n\t\t\tРОЗКАЖІТЬ, ЩО ВИ ДУМАЄТЕ\n\t\t-->\n\t\t<h2>Приймайте участь</h2>\n\t\t<p>\n\t\t\tBrackets &mdash; проект з відкритим кодом. Веб-розробники з усіх куточків світу сприяють\n\t\t\tстворення кращого редактора коду. Багато розробляють доповнення, які розширюють можливості\n\t\t\tBrackets. Розкажіть нам, що ви думаєте, поділіться ідеями або безпосередньо підтримайте проект.\n\t\t</p>\n\t\t<ul>\n\t\t\t<li><a href=\"http://brackets.io\">Brackets.io</a></li>\n\t\t\t<li><a href=\"http://blog.brackets.io\">Блог команди Brackets</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets\">Brackets на GitHub</a></li>\n\t\t\t<li><a href=\"http://github.com/adobe/brackets/wiki\">Brackets Wiki</a></li>\n\t\t\t<li><a href=\"http://groups.google.com/group/brackets-dev\">Поштова розсилка розробників Brackets</a></li>\n\t\t\t<li><a href=\"https://twitter.com/#!/brackets\">@Brackets у Twitter</a></li>\n\t\t\t<li>Спілкуйтеся з розробниками Brackets в IRC в #brackets на Freenode</li>\n\t\t</ul>\n\n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->"
  },
  {
    "path": "samples/uk/Pochynayemo/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 600;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 600;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "samples/zh-cn/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>BRACKETS 入门</title>\n        <meta name=\"description\" content=\"Brackets 互动式入门指引。\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>BRACKETS 入门</h1>\n        <h2>让我为你好好介绍!</h2>\n        \n        <!--\n            用 <3 跟 JAVASCRIPT 写出来的\n        -->\n        \n        <p>\n            欢迎使用 Brackets，这是个很懂网页设计的现代化开放原始码程式编辑器。\n            轻巧又不失威力，整合多项视觉化的编辑功能，在需要时提供您适当的协助。\n        </p>\n        \n        <!--\n            BRACKETS 是什麽?\n        -->\n        <p>\n            <em>Brackets 与众不同。</em>\n            Brackets 提供「快速编辑」、「即时预览」等别的编辑器没有的独家功能。\n            而且 Brackets 是用 JavaScript, HTML 及 CSS 写出来的。这代表大多数使用 Brackets 的人都有能力修改及扩充它。\n            事实上，Brackets 本身就是我们用 Brackets 一天天打造出来的。\n            如果您想学会如何使用这些功能，请继续看下去。\n        </p>\n        \n        <!--\n            用您自己的档案开始上手\n        -->\n        \n        <h3>Brackets 中的「专案」</h3>\n        <p>\n            只要开启包含您程式码的资料夹，就能使用 Brackets 来编辑。\n            Brackets 会将目前开启的资料夹视为一个「专案」，「程式提示」、「即时预览」及「快速编辑」等功能都只会参考到专案裡的档案。\n        </p>\n        \n        <samp>\n            要是您已经准备好关掉这个范例专案，开始编辑自已的程式，可以使用左边侧栏的下拉式选单切换资料夹。\n            现在应该是选到「Getting Started」，也就是您看的这份文件所在的资料夹。\n            按一下下拉式选单，点选「开启资料夹…」选项，就能开启您自已的资料夹。\n            \n            之后您也可以透过同样的下拉式选单切回开启过的资料夹，包含这个范例专案。\n        </samp>\n        \n        <!--\n            HTML, CSS 及 JAVASCRIPT 之间的关系\n        -->\n        <h3>CSS 及 JavaScript 快速编辑</h3>\n        <p>\n            别再因为不断切换档案而一直分神失焦了。编辑 HTML 时，按下 <kbd>Cmd/Ctrl + E</kbd>\n            快速键就地开启编辑器，秀出所有相关的 CSS 规则。\n            调好 CSS 样式后按 <kbd>ESC</kbd> 马上就能回到 HTML 继续编辑。\n            此外，也可以放手让那些 CSS 规则一直开在 HTML 编辑器裡。\n            只要在快速编辑器的范围外按下 <kbd>ESC</kbd> 键，就能关掉所有快速编辑器。\n            快速编辑也能找到定义在 LESS 及 SCSS 档案中的规则，就算是巢状规则也没问题。\n        </p>\n        \n        <samp>\n            想亲身体验吗? 把游标移到上面的 <!-- <samp> --> 标籤中，按下 <kbd>Cmd/Ctrl + E</kbd>。\n            您应该就会看到 CSS 快速编辑器出现在上方，显示出所有套用到的 CSS 规则。\n            快速编辑功能也支援 class 及 id 属性。搭配 LESS 或 SCSS 档嘛会通喔。\n            \n            您也可以透过这个方式新增规则。在上方随便一个 <!-- <p> --> 标籤上点一下，按 <kbd>Cmd/Ctrl + E</kbd>。\n            可以看到它上面并没有任何 CSS　规则，但您可以按一下「新增规则」按钮，就会新增 <!-- <p> --> 规则。\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"使用 CSS 快速编辑的画面撷图\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            您也能使用相同的快速键编辑其他东西，例如 JavaScript 函式、CSS 色彩、CSS 动画计时函式等，持续增加中。\n        </p>\n        <p>\n            目前还不能在快速编辑器中巢状开启其他快速编辑器，只有游标在主编辑器时才能开快速编辑功能。\n        </p>\n        \n        <!--\n            即时预览\n        -->\n        <h3>在浏览器裡即时预览 HTML 及 CSS 变更</h3>\n        <p>\n            有一种舞叫做「存档再重新载入探戈」，我们跳了好多年，您听过吗?\n            就是在编辑器裡改一改东西，储存好，马上再切过去浏览器，按「重新整理」后才能真正的看到结果，超鸟的!\n            用 Brackets，您永远不必再这麽「跳」。\n        </p>\n        <p>\n            Brackets 会跟您本机的浏览器<em>即时连线</em>，在您修改的同时将 HTML 及 CSS 内容更新过去!\n            说不定活在 21 世纪的您已经用浏览器提供的开发者工具做过类似的事了。\n            但是用 Brackets，您不用再手动把总算是会动的程式複製贴回编辑器。\n            您的程式虽然是跑在浏览器上，但是所有的血与肉都还是在编辑器裡啊!\n        </p>\n        \n        <h3>即时突显 HTML 元素及 CSS 规则</h3>\n        <p>\n            Brackets 让您更容易看到 HTML 及 CSS 的修改会对页面造成什麽影响。\n            当游标停在 CSS 规则上时，Brackets 会在浏览器裡将所有会受影响的元素突显出来。\n            编辑 HTML 档案时，Brackets 也会在浏览器中突显对应的 HTML 元素。\n        </p>\n        \n        <samp>\n            如果您安装了 Google Chrome，马上就可以试看看。\n            按一下 Brackets 视窗右上角的闪电图示，或是按 <kbd>Cmd/Ctrl + Alt + P</kbd>。\n            当即时预览功能在 HTML 档案上启用后，所有连结到的 CSS 档案也都可以马上编辑马上生效。\n            Brackets 与您的浏览器建立连线时，图示会由灰转金。\n            \n            就是现在，把游标移到上面的 <!-- <img> --> 标籤。注意看 Chrome 在图片上显示的蓝色框。\n            接下来，按 <kbd>Cmd/Ctrl + E</kbd> 开启相关的 CSS 规则定义。\n            试著将框线 (border) 值由 10px 改成 20px，或将背景色 (background-color) 由透明 \"transparent\" 改成 \"hotpink\"。\n            如果您把 Brackets 跟浏览器并排放好，就能看到所有异动都直接反应在浏览器上了。酷吧?!\n        </samp>\n        \n        <p class=\"note\">\n            目前 Brackets 只能即时预览 HTML 及 CSS。不过，储存修改过的 JavaScript 档案时也会自动重新载入页面。\n            我们正在努力让即时预览功能支援 JavaScript。\n            此外，即时预览现在只能在 Google Chrome 上执行，我们希望将来能支援所有主流的浏览器。\n        </p>\n        \n        <h3>快速检视</h3>\n        <p>\n            为了那些记不得色彩十六进位值或是 RGB 值的人，Brackets 能快速又简单的让您看见色彩的真相。\n            不管在 CSS 或 HTML 中，只要将滑鼠游标移到任何色彩值或是渐变色上，Brackets 就会自动显示预览。\n            对图片也同样有用，在 Brackets 裡将滑鼠游标移到图片连结上，就会自动显示预览缩图。\n        </p>\n        \n        <samp>\n            自已试试快速检视，只要将游标移到这份文件最上方的 <!-- <body> --> 标籤上，按下 <kbd>Cmd/Ctrl + E</kbd>\n            开启 CSS 快速编辑器，将滑鼠游标移到 CSS 上的任何一个色彩值上就能看到。\n            想要预览渐变色，您也可以在 <!-- <html> --> 标籤上开启 CSS 快速编辑器，移到随便一个背景图片 (background-image) 值就能看到。\n            要试图片预览，则是将游标移到前几段提到的画面撷图上就能看到。\n        </samp>\n        \n        <h3>还不够吗? 安装扩充功能吧!</h3>\n        <p>\n            除了 Brackets 内建的这些好物外，我们那深具规模，且日益状大的开发者社群已经写出了数百个扩充功能。\n            如果您觉得 Brackets 少了什麽，说不定早就有人写好扩充功能了。\n            点一下 <strong>档案 > 扩充功能管理员...</strong>，再点一下「可使用」页籤，就能浏览或搜寻扩充功能清单。\n            一旦找到想要的扩充功能，按一下后面的「安装」按钮就可以了。\n        </p>\n        \n        <!--\n            跟我们说说您的想法\n        -->\n        <h2>一起参与</h2>\n        <p>\n            Brackets 专案是开放原始码的。世界各地的网页开发者贡献一己之力，只为打造出更好的程式编辑器。\n            也有不少人正在开发扩充功能，让 Brackets 更强大。\n            告诉我们您的想法，分享您的构想，或是直接为本专案做点事吧。\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets 开发团队网志</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">GitHub 上的 Brackets</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets 扩充功能登录库</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets 维基</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets 开发者邮寄清单</a></li>\n            <li><a href=\"https://twitter.com/brackets\">Twitter 上的 @brackets</a></li>\n            <li>在 <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">Freenode 的 #brackets</a> IRC 频道上与 Brackets 开发者聊天</li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n"
  },
  {
    "path": "samples/zh-cn/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 700;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 700;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}\n"
  },
  {
    "path": "samples/zh-tw/Getting Started/index.html",
    "content": "<!DOCTYPE html>\n<html>\n    \n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <title>BRACKETS 入門</title>\n        <meta name=\"description\" content=\"Brackets 互動式入門指引。\">\n        <link rel=\"stylesheet\" href=\"main.css\">\n    </head>\n    <body>\n        \n        <h1>BRACKETS 入門</h1>\n        <h2>讓我為您好好介紹!</h2>\n        \n        <!--\n            用 <3 跟 JAVASCRIPT 寫出來的\n        -->\n        \n        <p>\n            歡迎使用 Brackets，這是個很懂網頁設計的現代化開放原始碼程式編輯器。\n            輕巧又不失威力，整合多項視覺化的編輯功能，在需要時提供您適當的協助。\n        </p>\n        \n        <!--\n            BRACKETS 是什麼?\n        -->\n        <p>\n            <em>Brackets 與眾不同。</em>\n            Brackets 提供「快速編輯」、「即時預覽」等別的編輯器沒有的獨家功能。\n            而且 Brackets 是用 JavaScript, HTML 及 CSS 寫出來的。這代表大多數使用 Brackets 的人都有能力修改及擴充它。\n            事實上，Brackets 本身就是我們用 Brackets 一天天打造出來的。\n            如果您想學會如何使用這些功能，請繼續看下去。\n        </p>\n        \n        <!--\n            用您自己的檔案開始上手\n        -->\n        \n        <h3>Brackets 中的「專案」</h3>\n        <p>\n            只要開啟包含您程式碼的資料夾，就能使用 Brackets 來編輯。\n            Brackets 會將目前開啟的資料夾視為一個「專案」，「程式提示」、「即時預覽」及「快速編輯」等功能都只會參考到專案裡的檔案。\n        </p>\n        \n        <samp>\n            要是您已經準備好關掉這個範例專案，開始編輯自已的程式，可以使用左邊側欄的下拉式選單切換資料夾。\n            現在應該是選到「Getting Started」，也就是您看的這份文件所在的資料夾。\n            按一下下拉式選單，點選「開啟資料夾…」選項，就能開啟您自已的資料夾。\n            \n            之後您也可以透過同樣的下拉式選單切回開啟過的資料夾，包含這個範例專案。\n        </samp>\n        \n        <!--\n            HTML, CSS 及 JAVASCRIPT 之間的關係\n        -->\n        <h3>CSS 及 JavaScript 快速編輯</h3>\n        <p>\n            別再因為不斷切換檔案而一直分神失焦了。編輯 HTML 時，按下 <kbd>Cmd/Ctrl + E</kbd>\n            快速鍵就地開啟編輯器，秀出所有相關的 CSS 規則。\n            調好 CSS 樣式後按 <kbd>ESC</kbd> 馬上就能回到 HTML 繼續編輯。\n            此外，也可以放手讓那些 CSS 規則一直開在 HTML 編輯器裡。\n            只要在快速編輯器的範圍外按下 <kbd>ESC</kbd> 鍵，就能關掉所有快速編輯器。\n            快速編輯也能找到定義在 LESS 及 SCSS 檔案中的規則，就算是巢狀規則也沒問題。\n        </p>\n        \n        <samp>\n            想親身體驗嗎? 把游標移到上面的 <!-- <samp> --> 標籤中，按下 <kbd>Cmd/Ctrl + E</kbd>。\n            您應該就會看到 CSS 快速編輯器出現在上方，顯示出所有套用到的 CSS 規則。\n            快速編輯功能也支援 class 及 id 屬性。搭配 LESS 或 SCSS 檔嘛會通喔。\n            \n            您也可以透過這個方式新增規則。在上方隨便一個 <!-- <p> --> 標籤上點一下，按 <kbd>Cmd/Ctrl + E</kbd>。\n            可以看到它上面並沒有任何 CSS　規則，但您可以按一下「新增規則」按鈕，就會新增 <!-- <p> --> 規則。\n        </samp>\n        \n        <a href=\"screenshots/quick-edit.png\">\n            <img alt=\"使用 CSS 快速編輯的畫面擷圖\" src=\"screenshots/quick-edit.png\" />\n        </a>\n        \n        <p>\n            您也能使用相同的快速鍵編輯其他東西，例如 JavaScript 函式、CSS 色彩、CSS 動畫計時函式等，持續增加中。\n        </p>\n        <p>\n            目前還不能在快速編輯器中巢狀開啟其他快速編輯器，只有游標在主編輯器時才能開快速編輯功能。\n        </p>\n        \n        <!--\n            即時預覽\n        -->\n        <h3>在瀏覽器裡即時預覽 HTML 及 CSS 變更</h3>\n        <p>\n            有一種舞叫做「存檔再重新載入探戈」，我們跳了好多年，您聽過嗎?\n            就是在編輯器裡改一改東西，儲存好，馬上再切過去瀏覽器，按「重新整理」後才能真正的看到結果，超鳥的!\n            用 Brackets，您永遠不必再這麼「跳」。\n        </p>\n        <p>\n            Brackets 會跟您本機的瀏覽器<em>即時連線</em>，在您修改的同時將 HTML 及 CSS 內容更新過去!\n            說不定活在 21 世紀的您已經用瀏覽器提供的開發者工具做過類似的事了。\n            但是用 Brackets，您不用再手動把總算是會動的程式複製貼回編輯器。\n            您的程式雖然是跑在瀏覽器上，但是所有的血與肉都還是在編輯器裡啊!\n        </p>\n        \n        <h3>即時突顯 HTML 元素及 CSS 規則</h3>\n        <p>\n            Brackets 讓您更容易看到 HTML 及 CSS 的修改會對頁面造成什麼影響。\n            當游標停在 CSS 規則上時，Brackets 會在瀏覽器裡將所有會受影響的元素突顯出來。\n            編輯 HTML 檔案時，Brackets 也會在瀏覽器中突顯對應的 HTML 元素。\n        </p>\n        \n        <samp>\n            如果您安裝了 Google Chrome，馬上就可以試看看。\n            按一下 Brackets 視窗右上角的閃電圖示，或是按 <kbd>Cmd/Ctrl + Alt + P</kbd>。\n            當即時預覽功能在 HTML 檔案上啟用後，所有連結到的 CSS 檔案也都可以馬上編輯馬上生效。\n            Brackets 與您的瀏覽器建立連線時，圖示會由灰轉金。\n            \n            就是現在，把游標移到上面的 <!-- <img> --> 標籤。注意看 Chrome 在圖片上顯示的藍色框。\n            接下來，按 <kbd>Cmd/Ctrl + E</kbd> 開啟相關的 CSS 規則定義。\n            試著將框線 (border) 值由 10px 改成 20px，或將背景色 (background-color) 由透明 \"transparent\" 改成 \"hotpink\"。\n            如果您把 Brackets 跟瀏覽器並排放好，就能看到所有異動都直接反應在瀏覽器上了。酷吧?!\n        </samp>\n        \n        <p class=\"note\">\n            目前 Brackets 只能即時預覽 HTML 及 CSS。不過，儲存修改過的 JavaScript 檔案時也會自動重新載入頁面。\n            我們正在努力讓即時預覽功能支援 JavaScript。\n            此外，即時預覽現在只能在 Google Chrome 上執行，我們希望將來能支援所有主流的瀏覽器。\n        </p>\n        \n        <h3>快速檢視</h3>\n        <p>\n            為了那些記不得色彩十六進位值或是 RGB 值的人，Brackets 能快速又簡單的讓您看見色彩的真相。\n            不管在 CSS 或 HTML 中，只要將滑鼠游標移到任何色彩值或是漸變色上，Brackets 就會自動顯示預覽。\n            對圖片也同樣有用，在 Brackets 裡將滑鼠游標移到圖片連結上，就會自動顯示預覽縮圖。\n        </p>\n        \n        <samp>\n            自已試試快速檢視，只要將游標移到這份文件最上方的 <!-- <body> --> 標籤上，按下 <kbd>Cmd/Ctrl + E</kbd>\n            開啟 CSS 快速編輯器，將滑鼠游標移到 CSS 上的任何一個色彩值上就能看到。\n            想要預覽漸變色，您也可以在 <!-- <html> --> 標籤上開啟 CSS 快速編輯器，移到隨便一個背景圖片 (background-image) 值就能看到。\n            要試圖片預覽，則是將游標移到前幾段提到的畫面擷圖上就能看到。\n        </samp>\n        \n        <h3>還不夠嗎? 安裝擴充功能吧!</h3>\n        <p>\n            除了 Brackets 內建的這些好物外，我們那深具規模，且日益狀大的開發者社群已經寫出了數百個擴充功能。\n            如果您覺得 Brackets 少了什麼，說不定早就有人寫好擴充功能了。\n            點一下 <strong>檔案 > 擴充功能管理員...</strong>，再點一下「可使用」頁籤，就能瀏覽或搜尋擴充功能清單。\n            一旦找到想要的擴充功能，按一下後面的「安裝」按鈕就可以了。\n        </p>\n        \n        <!--\n            跟我們說說您的想法\n        -->\n        <h2>一起參與</h2>\n        <p>\n            Brackets 專案是開放原始碼的。世界各地的網頁開發者貢獻一己之力，只為打造出更好的程式編輯器。\n            也有不少人正在開發擴充功能，讓 Brackets 更強大。\n            告訴我們您的想法，分享您的構想，或是直接為本專案做點事吧。\n        </p>\n        <ul>\n            <li><a href=\"http://brackets.io\">Brackets.io</a></li>\n            <li><a href=\"http://blog.brackets.io\">Brackets 開發團隊網誌</a></li>\n            <li><a href=\"https://github.com/adobe/brackets\">GitHub 上的 Brackets</a></li>\n            <li><a href=\"https://brackets-registry.aboutweb.com\">Brackets 擴充功能登錄庫</a></li>\n            <li><a href=\"https://github.com/adobe/brackets/wiki\">Brackets 維基</a></li>\n            <li><a href=\"https://groups.google.com/forum/#!forum/brackets-dev\">Brackets 開發者郵寄清單</a></li>\n            <li><a href=\"https://twitter.com/brackets\">Twitter 上的 @brackets</a></li>\n            <li>在 <a href=\"http://webchat.freenode.net/?channels=brackets&uio=d4\">Freenode 的 #brackets</a> IRC 頻道上與 Brackets 開發者聊天</li>\n        </ul>\n        \n    </body>\n</html>\n<!--\n\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[     CODE THE WEB     ]:::::]\n    [:::::[  http://brackets.io  ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [:::::[                      ]:::::]\n    [::::::[[[[[[[:      :]]]]]]]::::::]\n    [::::::::::::::      ::::::::::::::]\n    [::::::::::::::      ::::::::::::::]\n    [[[[[[[[[[[[[[[      ]]]]]]]]]]]]]]]\n\n-->\n\n<!-- Last translated for e3ecc9e7ac7b94f1107a8e3ca7064ac39b345280 -->\n"
  },
  {
    "path": "samples/zh-tw/Getting Started/main.css",
    "content": "html {\n    background: #e6e9e9;\n    background-image: linear-gradient(270deg, rgb(230, 233, 233) 0%, rgb(216, 221, 221) 100%);\n    -webkit-font-smoothing: antialiased;\n}\n\nbody {\n    background: #fff;\n    box-shadow: 0 0 2px rgba(0, 0, 0, 0.06);\n    color: #545454;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n    font-size: 16px;\n    line-height: 1.5;\n    margin: 0 auto;\n    max-width: 800px;\n    padding: 2em 2em 4em;\n}\n\nh1, h2, h3, h4, h5, h6 {\n    color: #222;\n    font-weight: 700;\n    line-height: 1.3;\n}\n\nh2 {\n    margin-top: 1.3em;\n}\n\na {\n    color: #0083e8;\n}\n\nb, strong {\n    font-weight: 700;\n}\n\nsamp {\n    display: none;\n}\n\nimg {\n    animation: colorize 2s cubic-bezier(0, 0, .78, .36) 1;\n    background: transparent;\n    border: 10px solid rgba(0, 0, 0, 0.12);\n    border-radius: 4px;\n    display: block;\n    margin: 1.3em auto;\n    max-width: 95%;\n}\n\n@keyframes colorize {\n    0% {\n        -webkit-filter: grayscale(100%);\n        filter: grayscale(100%);\n    }\n    100% {\n        -webkit-filter: grayscale(0%);\n        filter: grayscale(0%);\n    }\n}"
  },
  {
    "path": "src/JSUtils/HintUtils.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Acorn                       = require(\"node_modules/acorn/dist/acorn\");\n\n    var LANGUAGE_ID                 = \"javascript\",\n        JSX_LANGUAGE_ID             = \"jsx\",\n        HTML_LANGUAGE_ID            = \"html\",\n        PHP_LANGUAGE_ID             = \"php\",\n        SUPPORTED_LANGUAGES         = [LANGUAGE_ID, JSX_LANGUAGE_ID, HTML_LANGUAGE_ID, PHP_LANGUAGE_ID],\n        SINGLE_QUOTE                = \"'\",\n        DOUBLE_QUOTE                = \"\\\"\";\n\n    /**\n     * Create a hint token with name value that occurs at the given list of\n     * positions.\n     *\n     * @param {string} value - name of the new hint token\n     * @param {?Array.<number>=} positions - optional list of positions at which\n     *      the token occurs\n     * @return {Object} - a new hint token\n     */\n    function makeToken(value, positions) {\n        positions = positions || [];\n\n        return {\n            value: value,\n            positions: positions\n        };\n    }\n\n    /**\n     * Is the string key perhaps a valid JavaScript identifier?\n     *\n     * @param {string} key - string to test.\n     * @return {boolean} - could key be a valid identifier?\n     */\n    function maybeIdentifier(key) {\n        var result = false,\n            i;\n\n        for (i = 0; i < key.length; i++) {\n            result = Acorn.isIdentifierChar(key.charCodeAt(i));\n            if (!result) {\n                break;\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * Is the token's class hintable? (A very conservative test.)\n     *\n     * @param {Object} token - the token to test for hintability\n     * @return {boolean} - could the token be hintable?\n     */\n    function hintable(token) {\n\n        function _isInsideRegExp(token) {\n            return token.state && (token.state.lastType === \"regexp\" ||\n                   (token.state.localState && token.state.localState.lastType === \"regexp\"));\n        }\n\n        switch (token.type) {\n        case \"comment\":\n        case \"number\":\n        case \"regexp\":\n        case \"string\":\n        case \"def\":     // exclude variable & param decls\n            return false;\n        case \"string-2\":\n            // exclude strings inside a regexp\n            return !_isInsideRegExp(token);\n        default:\n            return true;\n        }\n    }\n\n    /**\n     *  Determine if hints should be displayed for the given key.\n     *\n     * @param {string} key - key entered by the user\n     * @param {boolean} showOnDot - show hints on dot (\".\").\n     * @return {boolean} true if the hints should be shown for the key,\n     * false otherwise.\n     */\n    function hintableKey(key, showOnDot) {\n        return (key === null || (showOnDot && key === \".\") || maybeIdentifier(key));\n    }\n\n    /*\n     * Get a JS-hints-specific event name. Used to prevent event namespace\n     * pollution.\n     *\n     * @param {string} name - the unqualified event name\n     * @return {string} - the qualified event name\n     */\n    function eventName(name) {\n        var EVENT_TAG = \"brackets-js-hints\";\n        return name + \".\" + EVENT_TAG;\n    }\n\n    /*\n     * Annotate a list of tokens as literals of a particular kind;\n     * if string literals, annotate with an appropriate delimiter.\n     *\n     * @param {Array.<Object>} literals - list of hint tokens\n     * @param {string} kind - the kind of literals in the list (e.g., \"string\")\n     * @return {Array.<Object>} - the input array; to each object in the array a\n     *      new literal {boolean} property has been added to indicate that it\n     *      is a literal hint, and also a new kind {string} property to indicate\n     *      the literal kind. For string literals, a delimiter property is also\n     *      added to indicate what the default delimiter should be (viz. a\n     *      single or double quotation mark).\n     */\n    function annotateLiterals(literals, kind) {\n        return literals.map(function (t) {\n            t.literal = true;\n            t.kind = kind;\n            t.origin = \"ecmascript\";\n            if (kind === \"string\") {\n                if (/[^\\\\]\"/.test(t.value)) {\n                    t.delimiter = SINGLE_QUOTE;\n                } else {\n                    t.delimiter = DOUBLE_QUOTE;\n                }\n            }\n            return t;\n        });\n    }\n\n    /*\n     * Annotate a list of tokens as keywords\n     *\n     * @param {Array.<Object>} keyword - list of keyword tokens\n     * @return {Array.<Object>} - the input array; to each object in the array a\n     *      new keyword {boolean} property has been added to indicate that the\n     *      hint is a keyword.\n     */\n    function annotateKeywords(keywords) {\n        return keywords.map(function (t) {\n            t.keyword = true;\n            t.origin = \"ecmascript\";\n            return t;\n        });\n    }\n\n    function isSupportedLanguage(languageId) {\n        return SUPPORTED_LANGUAGES.indexOf(languageId) !== -1;\n    }\n\n    var KEYWORD_NAMES   = [\n        \"break\", \"case\", \"catch\", \"class\", \"const\", \"continue\", \"debugger\",\n        \"default\", \"delete\", \"do\", \"else\", \"export\", \"extends\", \"finally\",\n        \"for\", \"function\", \"if\", \"import\", \"in\", \"instanceof\", \"let\", \"new\",\n        \"return\", \"super\", \"switch\", \"this\", \"throw\", \"try\", \"typeof\", \"var\",\n        \"void\", \"while\", \"with\", \"yield\"\n    ],\n        KEYWORD_TOKENS  = KEYWORD_NAMES.map(function (t) {\n            return makeToken(t, []);\n        }),\n        KEYWORDS        = annotateKeywords(KEYWORD_TOKENS);\n\n    var LITERAL_NAMES   = [\n        \"true\", \"false\", \"null\"\n    ],\n        LITERAL_TOKENS  = LITERAL_NAMES.map(function (t) {\n            return makeToken(t, []);\n        }),\n        LITERALS        = annotateLiterals(LITERAL_TOKENS);\n\n    exports.makeToken                   = makeToken;\n    exports.hintable                    = hintable;\n    exports.hintableKey                 = hintableKey;\n    exports.maybeIdentifier             = maybeIdentifier;\n    exports.eventName                   = eventName;\n    exports.annotateLiterals            = annotateLiterals;\n    exports.isSupportedLanguage         = isSupportedLanguage;\n    exports.KEYWORDS                    = KEYWORDS;\n    exports.LITERALS                    = LITERALS;\n    exports.LANGUAGE_ID                 = LANGUAGE_ID;\n    exports.SINGLE_QUOTE                = SINGLE_QUOTE;\n    exports.DOUBLE_QUOTE                = DOUBLE_QUOTE;\n    exports.SUPPORTED_LANGUAGES         = SUPPORTED_LANGUAGES;\n});\n"
  },
  {
    "path": "src/JSUtils/MessageIds.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var TERN_ADD_FILES_MSG          = \"AddFiles\",\n        TERN_UPDATE_FILE_MSG        = \"UpdateFile\",\n        TERN_INIT_MSG               = \"Init\",\n        TERN_JUMPTODEF_MSG          = \"JumptoDef\",\n        TERN_COMPLETIONS_MSG        = \"Completions\",\n        TERN_GET_FILE_MSG           = \"GetFile\",\n        TERN_SCOPEDATA_MSG          = \"ScopeData\",\n        TERN_CALLED_FUNC_TYPE_MSG   = \"FunctionType\",\n        TERN_PRIME_PUMP_MSG         = \"PrimePump\",\n        TERN_GET_GUESSES_MSG        = \"GetGuesses\",\n        TERN_WORKER_READY           = \"WorkerReady\",\n        TERN_INFERENCE_TIMEDOUT     = \"InferenceTimedOut\",\n        SET_CONFIG                  = \"SetConfig\",\n        TERN_UPDATE_DIRTY_FILE      = \"UpdateDirtyFileEntry\",\n        TERN_REFS                   = \"getRefs\",\n        TERN_CLEAR_DIRTY_FILES_LIST = \"ClearDirtyFilesList\";\n\n    // Message parameter constants\n    var TERN_FILE_INFO_TYPE_PART    = \"part\",\n        TERN_FILE_INFO_TYPE_FULL    = \"full\",\n        TERN_FILE_INFO_TYPE_EMPTY   = \"empty\";\n\n\n    exports.TERN_ADD_FILES_MSG          = TERN_ADD_FILES_MSG;\n    exports.TERN_JUMPTODEF_MSG          = TERN_JUMPTODEF_MSG;\n    exports.TERN_COMPLETIONS_MSG        = TERN_COMPLETIONS_MSG;\n    exports.TERN_INIT_MSG               = TERN_INIT_MSG;\n    exports.TERN_GET_FILE_MSG           = TERN_GET_FILE_MSG;\n    exports.TERN_SCOPEDATA_MSG          = TERN_SCOPEDATA_MSG;\n    exports.TERN_CALLED_FUNC_TYPE_MSG   = TERN_CALLED_FUNC_TYPE_MSG;\n    exports.TERN_PRIME_PUMP_MSG         = TERN_PRIME_PUMP_MSG;\n    exports.TERN_GET_GUESSES_MSG        = TERN_GET_GUESSES_MSG;\n    exports.TERN_UPDATE_FILE_MSG        = TERN_UPDATE_FILE_MSG;\n    exports.TERN_WORKER_READY           = TERN_WORKER_READY;\n    exports.TERN_FILE_INFO_TYPE_PART    = TERN_FILE_INFO_TYPE_PART;\n    exports.TERN_FILE_INFO_TYPE_FULL    = TERN_FILE_INFO_TYPE_FULL;\n    exports.TERN_FILE_INFO_TYPE_EMPTY   = TERN_FILE_INFO_TYPE_EMPTY;\n    exports.TERN_INFERENCE_TIMEDOUT     = TERN_INFERENCE_TIMEDOUT;\n    exports.SET_CONFIG                  = SET_CONFIG;\n    exports.TERN_UPDATE_DIRTY_FILE      = TERN_UPDATE_DIRTY_FILE;\n    exports.TERN_CLEAR_DIRTY_FILES_LIST = TERN_CLEAR_DIRTY_FILES_LIST;\n    exports.TERN_REFS = TERN_REFS;\n});\n\n\n"
  },
  {
    "path": "src/JSUtils/Preferences.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n\n    This class parses configuration values from a JSON object. The expected\n    name of the file is “.jscodehints” but this class does not actually read\n    the file, it just provides a constant, FILE_NAME.\n\n    The following properties are supported:\n\n     \"excluded-directories\" - An array of directory strings that match\n     directories that will be excluded from analysis. Directories may be\n     excluded if they contain automated tests that aren’t relevant for code hinting.\n     The wildcards “*” and “?” are supported in strings.\n\n     \"excluded-files\" - An array of file strings that match files that will\n     be excluded from analysis. Files are typically excluded because\n     their API is in a JSON file or they are known to cause problems with either\n     stability or performance. The wildcards “*” and “?” are supported in strings.\n\n     \"max-file-count\" - Limits the total number of files that can be processed for\n     hints.\n\n     \"max-file-size\" - Files larger than this number of bytes will not be parsed.\n\n     The strings in \"excluded-directories\" or \"excluded-files\" will be treated as a\n     regular expression if the first and last characters of the string are the '/'\n     character. Note the '\\' character in a regular expression needs to be escaped\n     to be valid in a JSON formatted file. For example \"/[\\d]/\" becomes \"/[\\\\d]/\".\n\n     Example file:\n\n     {\n     \"excluded-directories\" : [\"/ex[\\\\w]*ed/\"],\n     \"excluded-files\" : [\"require.js\", \"jquery*.js\", \"less*.min.js\", \"ember*.js\", \"d2?.js\", \"d3*\"],\n     \"max-file-count\": 100,\n     \"max-file-size\": 524288\n     }\n\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var StringUtils      = require(\"utils/StringUtils\");\n\n    /**\n     *  Convert an array of strings with optional wildcards, to an equivalent\n     *  regular expression.\n     *\n     * @param {Array.<string|RegExp>} settings from the file (note: this may be mutated by this function)\n     * @param {?RegExp} baseRegExp - base regular expression that is always used\n     * @param {?RegExp} defaultRegExp - additional regular expression that is only used if the user has not configured settings\n     * @return {RegExp} Regular expression that captures the array of string\n     * with optional wildcards.\n     */\n    function settingsToRegExp(settings, baseRegExp, defaultRegExp) {\n        var regExpString = \"\";\n\n        if (settings instanceof Array && settings.length > 0) {\n\n            // Append base settings to user settings. The base\n            // settings are builtin and cannot be overridden.\n            if (baseRegExp) {\n                settings.push(\"/\" + baseRegExp.source + \"/\");\n            }\n\n            // convert each string, with optional wildcards to an equivalent\n            // string in a regular expression.\n            settings.forEach(function (value, index) {\n\n                if (typeof value === \"string\") {\n                    var isRegExp = value[0] === '/' && value[value.length - 1] === '/';\n\n                    if (isRegExp) {\n                        value = value.substring(1, value.length - 1);\n                    } else {\n                        value = StringUtils.regexEscape(value);\n\n                        // convert user input wildcard, \"*\" or \"?\", to a regular\n                        // expression. We can just replace the escaped \"*\" or \"?\"\n                        // since we know it is a wildcard.\n                        value = value.replace(\"\\\\?\", \".?\");\n                        value = value.replace(\"\\\\*\", \".*\");\n\n                        // Add \"^\" and \"$\" to prevent matching in the middle of strings.\n                        value = \"^\" + value + \"$\";\n                    }\n\n                    if (index > 0) {\n                        regExpString += \"|\";\n                    }\n\n                    regExpString = regExpString.concat(value);\n                }\n            });\n        }\n\n        if (!regExpString) {\n            var defaultParts = [];\n            if (baseRegExp) {\n                defaultParts.push(baseRegExp.source);\n            }\n            if (defaultRegExp) {\n                defaultParts.push(defaultRegExp.source);\n            }\n            if (defaultParts.length > 0) {\n                regExpString  = defaultParts.join(\"|\");\n            } else {\n                return null;\n            }\n        }\n\n        return new RegExp(regExpString);\n    }\n\n    /**\n     * Constructor to create a default preference object.\n     *\n     * @constructor\n     * @param {Object=} prefs - preference object\n     */\n    function Preferences(prefs) {\n        var BASE_EXCLUDED_DIRECTORIES = null, /* if the user has settings, we don't exclude anything by default */\n            // exclude node_modules for performance reasons and because we don't do full hinting for those anyhow.\n            DEFAULT_EXCLUDED_DIRECTORIES = /node_modules/,\n            // exclude require and jquery since we have special knowledge of those\n            BASE_EXCLUDED_FILES = /^require.*\\.js$|^jquery.*\\.js$/,\n            DEFAULT_MAX_FILE_COUNT = 100,\n            DEFAULT_MAX_FILE_SIZE = 512 * 1024;\n\n        if (prefs) {\n            this._excludedDirectories = settingsToRegExp(prefs[\"excluded-directories\"],\n                                                         BASE_EXCLUDED_DIRECTORIES,\n                                                         DEFAULT_EXCLUDED_DIRECTORIES);\n            this._excludedFiles = settingsToRegExp(prefs[\"excluded-files\"],\n                BASE_EXCLUDED_FILES);\n            this._maxFileCount = prefs[\"max-file-count\"];\n            this._maxFileSize = prefs[\"max-file-size\"];\n\n            // sanity check values\n            if (!this._maxFileCount || this._maxFileCount < 0) {\n                this._maxFileCount = DEFAULT_MAX_FILE_COUNT;\n            }\n\n            if (!this._maxFileSize || this._maxFileSize < 0) {\n                this._maxFileSize = DEFAULT_MAX_FILE_SIZE;\n            }\n\n        } else {\n            this._excludedDirectories = DEFAULT_EXCLUDED_DIRECTORIES;\n            this._excludedFiles = BASE_EXCLUDED_FILES;\n            this._maxFileCount = DEFAULT_MAX_FILE_COUNT;\n            this._maxFileSize = DEFAULT_MAX_FILE_SIZE;\n        }\n    }\n\n    Preferences.FILE_NAME = \".jscodehints\";\n\n    /**\n     * Get the regular expression for excluded directories.\n     *\n     * @return {?RegExp} Regular expression matching the directories that should\n     * be excluded. Returns null if no directories are excluded.\n     */\n    Preferences.prototype.getExcludedDirectories = function () {\n        return this._excludedDirectories;\n    };\n\n    /**\n     * Get the regular expression for excluded files.\n     *\n     * @return {?RegExp} Regular expression matching the files that should\n     * be excluded. Returns null if no files are excluded.\n     */\n    Preferences.prototype.getExcludedFiles = function () {\n        return this._excludedFiles;\n    };\n\n    /**\n     * Get the maximum number of files that will be analyzed.\n     *\n     * @return {number}\n     */\n    Preferences.prototype.getMaxFileCount = function () {\n        return this._maxFileCount;\n    };\n\n    /**\n     * Get the maximum size of a file that will be analyzed. Files that are\n     * larger will be ignored.\n     *\n     * @return {number}\n     */\n    Preferences.prototype.getMaxFileSize = function () {\n        return this._maxFileSize;\n    };\n\n    module.exports = Preferences;\n\n});\n\n"
  },
  {
    "path": "src/JSUtils/ScopeManager.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * Throughout this file, the term \"outer scope\" is used to refer to the outer-\n * most/global/root Scope objects for particular file. The term \"inner scope\"\n * is used to refer to a Scope object that is reachable via the child relation\n * from an outer scope.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var CodeMirror          = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        DefaultDialogs      = require(\"widgets/DefaultDialogs\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        ExtensionUtils      = require(\"utils/ExtensionUtils\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        NodeDomain          = require(\"utils/NodeDomain\"),\n        InMemoryFile        = require(\"document/InMemoryFile\");\n\n    var HintUtils           = require(\"./HintUtils\"),\n        MessageIds          = require(\"./MessageIds\"),\n        Preferences         = require(\"./Preferences\");\n\n    var ternEnvironment     = [],\n        pendingTernRequests = {},\n        builtinFiles        = [\"ecmascript.json\", \"browser.json\", \"jquery.json\"],\n        builtinLibraryNames = [],\n        isDocumentDirty     = false,\n        _hintCount          = 0,\n        currentModule       = null,\n        documentChanges     = null,     // bounds of document changes\n        preferences         = null,\n        deferredPreferences = null;\n    \n    var _bracketsPath       = FileUtils.getNativeBracketsDirectoryPath(),\n        _modulePath         = FileUtils.getNativeModuleDirectoryPath(module),\n        _nodePath           = \"node/TernNodeDomain\",\n        _absoluteModulePath = [_bracketsPath, _modulePath].join(\"/\"),\n        _domainPath         = [_bracketsPath, _modulePath, _nodePath].join(\"/\");\n    \n    \n    var MAX_HINTS           = 30,  // how often to reset the tern server\n        LARGE_LINE_CHANGE   = 100,\n        LARGE_LINE_COUNT    = 10000,\n        OFFSET_ZERO         = {line: 0, ch: 0};\n\n    var config = {};\n    \n    /**\n     *  An array of library names that contain JavaScript builtins definitions.\n     *\n     * @return {Array.<string>} - array of library  names.\n     */\n    function getBuiltins() {\n        return builtinLibraryNames;\n    }\n\n    /**\n     * Read in the json files that have type information for the builtins, dom,etc\n     */\n    function initTernEnv() {\n        var path = [_absoluteModulePath, \"node/node_modules/tern/defs/\"].join(\"/\"),\n            files = builtinFiles,\n            library;\n\n        files.forEach(function (i) {\n            FileSystem.resolve(path + i, function (err, file) {\n                if (!err) {\n                    FileUtils.readAsText(file).done(function (text) {\n                        library = JSON.parse(text);\n                        builtinLibraryNames.push(library[\"!name\"]);\n                        ternEnvironment.push(library);\n                    }).fail(function (error) {\n                        console.log(\"failed to read tern config file \" + i);\n                    });\n                } else {\n                    console.log(\"failed to read tern config file \" + i);\n                }\n            });\n        });\n    }\n\n    initTernEnv();\n\n    /**\n     *  Init preferences from a file in the project root or builtin\n     *  defaults if no file is found;\n     *\n     *  @param {string=} projectRootPath - new project root path. Only needed\n     *  for unit tests.\n     */\n    function initPreferences(projectRootPath) {\n\n        // Reject the old preferences if they have not completed.\n        if (deferredPreferences && deferredPreferences.state() === \"pending\") {\n            deferredPreferences.reject();\n        }\n\n        deferredPreferences = $.Deferred();\n        var pr = ProjectManager.getProjectRoot();\n\n        // Open preferences relative to the project root\n        // Normally there is a project root, but for unit tests we need to\n        // pass in a project root.\n        if (pr) {\n            projectRootPath = pr.fullPath;\n        } else if (!projectRootPath) {\n            console.log(\"initPreferences: projectRootPath has no value\");\n        }\n\n        var path = projectRootPath + Preferences.FILE_NAME;\n\n        FileSystem.resolve(path, function (err, file) {\n            if (!err) {\n                FileUtils.readAsText(file).done(function (text) {\n                    var configObj = null;\n                    try {\n                        configObj = JSON.parse(text);\n                    } catch (e) {\n                        // continue with null configObj which will result in\n                        // default settings.\n                        console.log(\"Error parsing preference file: \" + path);\n                        if (e instanceof SyntaxError) {\n                            console.log(e.message);\n                        }\n                    }\n                    preferences = new Preferences(configObj);\n                    deferredPreferences.resolve();\n                }).fail(function (error) {\n                    preferences = new Preferences();\n                    deferredPreferences.resolve();\n                });\n            } else {\n                preferences = new Preferences();\n                deferredPreferences.resolve();\n            }\n        });\n    }\n\n    /**\n     * Will initialize preferences only if they do not exist.\n     *\n     */\n    function ensurePreferences() {\n        if (!deferredPreferences) {\n            initPreferences();\n        }\n    }\n\n    /**\n     * Send a message to the tern module - if the module is being initialized,\n     * the message will not be posted until initialization is complete\n     */\n    function postMessage(msg) {\n        if (currentModule) {\n            currentModule.postMessage(msg);\n        }\n    }\n\n    /**\n     * Test if the directory should be excluded from analysis.\n     *\n     * @param {!string} path - full directory path.\n     * @return {boolean} true if excluded, false otherwise.\n     */\n    function isDirectoryExcluded(path) {\n        var excludes = preferences.getExcludedDirectories();\n\n        if (!excludes) {\n            return false;\n        }\n\n        var testPath = ProjectManager.makeProjectRelativeIfPossible(path);\n        testPath = FileUtils.stripTrailingSlash(testPath);\n\n        return excludes.test(testPath);\n    }\n\n    /**\n     * Test if the file path is in current editor\n     *\n     * @param {string} filePath file path to test for exclusion.\n     * @return {boolean} true if in editor, false otherwise.\n     */\n    function isFileBeingEdited(filePath) {\n        var currentEditor   = EditorManager.getActiveEditor(),\n            currentDoc      = currentEditor && currentEditor.document;\n\n        return (currentDoc && currentDoc.file.fullPath === filePath);\n    }\n\n    /**\n     * Test if the file path is an internal exclusion.\n     *\n     * @param {string} path file path to test for exclusion.\n     * @return {boolean} true if excluded, false otherwise.\n     */\n    function isFileExcludedInternal(path) {\n        // The detectedExclusions are files detected to be troublesome with current versions of Tern.\n        // detectedExclusions is an array of full paths.\n        var detectedExclusions = PreferencesManager.get(\"jscodehints.detectedExclusions\") || [];\n        if (detectedExclusions && detectedExclusions.indexOf(path) !== -1) {\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Test if the file should be excluded from analysis.\n     *\n     * @param {!File} file - file to test for exclusion.\n     * @return {boolean} true if excluded, false otherwise.\n     */\n    function isFileExcluded(file) {\n        if (file.name[0] === \".\") {\n            return true;\n        }\n\n        var languageID = LanguageManager.getLanguageForPath(file.fullPath).getId();\n        if (languageID !== HintUtils.LANGUAGE_ID) {\n            return true;\n        }\n\n        var excludes = preferences.getExcludedFiles();\n        if (excludes && excludes.test(file.name)) {\n            return true;\n        }\n\n        if (isFileExcludedInternal(file.fullPath)) {\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Add a pending request waiting for the tern-module to complete.\n     * If file is a detected exclusion, then reject request.\n     *\n     * @param {string} file - the name of the file\n     * @param {{line: number, ch: number}} offset - the offset into the file the request is for\n     * @param {string} type - the type of request\n     * @return {jQuery.Promise} - the promise for the request\n     */\n    function addPendingRequest(file, offset, type) {\n        var requests,\n            key = file + \"@\" + offset.line + \"@\" + offset.ch,\n            $deferredRequest;\n\n        // Reject detected exclusions\n        if (isFileExcludedInternal(file)) {\n            return (new $.Deferred()).reject().promise();\n        }\n\n        if (_.has(pendingTernRequests, key)) {\n            requests = pendingTernRequests[key];\n        } else {\n            requests = {};\n            pendingTernRequests[key] = requests;\n        }\n\n        if (_.has(requests, type)) {\n            $deferredRequest = requests[type];\n        } else {\n            requests[type] = $deferredRequest = new $.Deferred();\n        }\n        return $deferredRequest.promise();\n    }\n\n    /**\n     * Get any pending $.Deferred object waiting on the specified file and request type\n     * @param {string} file - the file\n     * @param {{line: number, ch: number}} offset - the offset into the file the request is for\n     * @param {string} type - the type of request\n     * @return {jQuery.Deferred} - the $.Deferred for the request\n     */\n    function getPendingRequest(file, offset, type) {\n        var key = file + \"@\" + offset.line + \"@\" + offset.ch;\n        if (_.has(pendingTernRequests, key)) {\n            var requests = pendingTernRequests[key],\n                requestType = requests[type];\n\n            delete pendingTernRequests[key][type];\n\n            if (!Object.keys(requests).length) {\n                delete pendingTernRequests[key];\n            }\n\n            return requestType;\n        }\n    }\n\n    /**\n     * @param {string} file a relative path\n     * @return {string} returns the path we resolved when we tried to parse the file, or undefined\n     */\n    function getResolvedPath(file) {\n        return currentModule.getResolvedPath(file);\n    }\n\n    /**\n     * Get a Promise for the definition from TernJS, for the file & offset passed in.\n     * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n     * - type of update, name of file, and the text of the update.\n     * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n     * the changed portion of the text. For \"empty\" updates, the file has not been modified\n     * and the text is empty.\n     * @param {{line: number, ch: number}} offset - the offset in the file the hints should be calculate at\n     * @return {jQuery.Promise} - a promise that will resolve to definition when\n     *      it is done\n     */\n    function getJumptoDef(fileInfo, offset) {\n        postMessage({\n            type: MessageIds.TERN_JUMPTODEF_MSG,\n            fileInfo: fileInfo,\n            offset: offset\n        });\n\n        return addPendingRequest(fileInfo.name, offset, MessageIds.TERN_JUMPTODEF_MSG);\n    }\n\n    /**\n     * check to see if the text we are sending to Tern is too long.\n     * @param {string} the text to check\n     * @return {string} the text, or the empty text if the original was too long\n     */\n    function filterText(text) {\n        var newText = text;\n        if (text.length > preferences.getMaxFileSize()) {\n            newText = \"\";\n        }\n        return newText;\n    }\n\n    /**\n     * Get the text of a document, applying any size restrictions\n     * if necessary\n     * @param {Document} document - the document to get the text from\n     * @return {string} the text, or the empty text if the original was too long\n     */\n    function getTextFromDocument(document) {\n        var text = document.getText();\n        text = filterText(text);\n        return text;\n    }\n\n    /**\n     * Handle the response from the tern node domain when\n     * it responds with the references\n     *\n     * @param response - the response from the node domain\n     */\n    function handleRename(response) {\n\n        if (response.error) {\n            EditorManager.getActiveEditor().displayErrorMessageAtCursor(response.error);\n            return;\n        }\n\n        var file = response.file,\n            offset = response.offset;\n\n        var $deferredFindRefs = getPendingRequest(file, offset, MessageIds.TERN_REFS);\n\n        if ($deferredFindRefs) {\n            $deferredFindRefs.resolveWith(null, [response]);\n        }\n    }\n\n    /**\n     * Request Jump-To-Definition from Tern.\n     *\n     * @param {session} session - the session\n     * @param {Document} document - the document\n     * @param {{line: number, ch: number}} offset - the offset into the document\n     * @return {jQuery.Promise} - The promise will not complete until tern\n     *      has completed.\n     */\n    function requestJumptoDef(session, document, offset) {\n        var path    = document.file.fullPath,\n            fileInfo = {\n                type: MessageIds.TERN_FILE_INFO_TYPE_FULL,\n                name: path,\n                offsetLines: 0,\n                text: filterText(session.getJavascriptText())\n            };\n\n        var ternPromise = getJumptoDef(fileInfo, offset);\n\n        return {promise: ternPromise};\n    }\n\n    /**\n     * Handle the response from the tern node domain when\n     * it responds with the definition\n     *\n     * @param response - the response from the node domain\n     */\n    function handleJumptoDef(response) {\n\n        var file = response.file,\n            offset = response.offset;\n\n        var $deferredJump = getPendingRequest(file, offset, MessageIds.TERN_JUMPTODEF_MSG);\n\n        if ($deferredJump) {\n            response.fullPath = getResolvedPath(response.resultFile);\n            $deferredJump.resolveWith(null, [response]);\n        }\n    }\n\n    /**\n     * Handle the response from the tern node domain when\n     * it responds with the scope data\n     *\n     * @param response - the response from the node domain\n     */\n    function handleScopeData(response) {\n        var file = response.file,\n            offset = response.offset;\n\n        var $deferredJump = getPendingRequest(file, offset, MessageIds.TERN_SCOPEDATA_MSG);\n\n        if ($deferredJump) {\n            $deferredJump.resolveWith(null, [response]);\n        }\n    }\n\n    /**\n     * Get a Promise for the completions from TernJS, for the file & offset passed in.\n     *\n     * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n     * - type of update, name of file, and the text of the update.\n     * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n     * the changed portion of the text. For \"empty\" updates, the file has not been modified\n     * and the text is empty.\n     * @param {{line: number, ch: number}} offset - the offset in the file the hints should be calculate at\n     * @param {boolean} isProperty - true if getting a property hint,\n     * otherwise getting an identifier hint.\n     * @return {jQuery.Promise} - a promise that will resolve to an array of completions when\n     *      it is done\n     */\n    function getTernHints(fileInfo, offset, isProperty) {\n\n        /**\n         *  If the document is large and we have modified a small portions of it that\n         *  we are asking hints for, then send a partial document.\n         */\n        postMessage({\n            type: MessageIds.TERN_COMPLETIONS_MSG,\n            fileInfo: fileInfo,\n            offset: offset,\n            isProperty: isProperty\n        });\n\n        return addPendingRequest(fileInfo.name, offset, MessageIds.TERN_COMPLETIONS_MSG);\n    }\n\n    /**\n     * Get a Promise for the function type from TernJS.\n     * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n     * - type of update, name of file, and the text of the update.\n     * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n     * the changed portion of the text. For \"empty\" updates, the file has not been modified\n     * and the text is empty.\n     * @param {{line:number, ch:number}} offset - the line, column info for what we want the function type of.\n     * @return {jQuery.Promise} - a promise that will resolve to the function type of the function being called.\n     */\n    function getTernFunctionType(fileInfo, offset) {\n        postMessage({\n            type: MessageIds.TERN_CALLED_FUNC_TYPE_MSG,\n            fileInfo: fileInfo,\n            offset: offset\n        });\n\n        return addPendingRequest(fileInfo.name, offset, MessageIds.TERN_CALLED_FUNC_TYPE_MSG);\n    }\n\n\n    /**\n     *  Given a starting and ending position, get a code fragment that is self contained\n     *  enough to be compiled.\n     *\n     * @param {!Session} session - the current session\n     * @param {{line: number, ch: number}} start - the starting position of the changes\n     * @return {{type: string, name: string, offsetLines: number, text: string}}\n     */\n    function getFragmentAround(session, start) {\n        var minIndent = null,\n            minLine   = null,\n            endLine,\n            cm        = session.editor._codeMirror,\n            tabSize   = cm.getOption(\"tabSize\"),\n            document  = session.editor.document,\n            p,\n            min,\n            indent,\n            line;\n\n        // expand range backwards\n        for (p = start.line - 1, min = Math.max(0, p - 100); p >= min; --p) {\n            line = session.getLine(p);\n            var fn = line.search(/\\bfunction\\b/);\n\n            if (fn >= 0) {\n                indent = CodeMirror.countColumn(line, null, tabSize);\n                if (minIndent === null || minIndent > indent) {\n                    if (session.getToken({line: p, ch: fn + 1}).type === \"keyword\") {\n                        minIndent = indent;\n                        minLine = p;\n                    }\n                }\n            }\n        }\n\n        if (minIndent === null) {\n            minIndent = 0;\n        }\n\n        if (minLine === null) {\n            minLine = min;\n        }\n\n        var max = Math.min(cm.lastLine(), start.line + 100),\n            endCh = 0;\n\n        for (endLine = start.line + 1; endLine < max; ++endLine) {\n            line = cm.getLine(endLine);\n\n            if (line.length > 0) {\n                indent = CodeMirror.countColumn(line, null, tabSize);\n                if (indent <= minIndent) {\n                    endCh = line.length;\n                    break;\n                }\n            }\n        }\n\n        var from = {line: minLine, ch: 0},\n            to   = {line: endLine, ch: endCh};\n\n        return {type: MessageIds.TERN_FILE_INFO_TYPE_PART,\n            name: document.file.fullPath,\n            offsetLines: from.line,\n            text: document.getRange(from, to)};\n    }\n\n\n    /**\n     * Get an object that describes what tern needs to know about the updated\n     * file to produce a hint. As a side-effect of this calls the document\n     * changes are reset.\n     *\n     * @param {!Session} session - the current session\n     * @param {boolean=} preventPartialUpdates - if true, disallow partial updates.\n     * Optional, defaults to false.\n     * @return {{type: string, name: string, offsetLines: number, text: string}}\n     */\n    function getFileInfo(session, preventPartialUpdates) {\n        var start = session.getCursor(),\n            end = start,\n            document = session.editor.document,\n            path = document.file.fullPath,\n            isHtmlFile = LanguageManager.getLanguageForPath(path).getId() === \"html\",\n            result;\n\n        if (isHtmlFile) {\n            result = {type: MessageIds.TERN_FILE_INFO_TYPE_FULL,\n                name: path,\n                text: session.getJavascriptText()};\n        } else if (!documentChanges) {\n            result = {type: MessageIds.TERN_FILE_INFO_TYPE_EMPTY,\n                name: path,\n                text: \"\"};\n        } else if (!preventPartialUpdates && session.editor.lineCount() > LARGE_LINE_COUNT &&\n                (documentChanges.to - documentChanges.from < LARGE_LINE_CHANGE) &&\n                documentChanges.from <= start.line &&\n                documentChanges.to > end.line) {\n            result = getFragmentAround(session, start);\n        } else {\n            result = {type: MessageIds.TERN_FILE_INFO_TYPE_FULL,\n                name: path,\n                text: getTextFromDocument(document)};\n        }\n\n        documentChanges = null;\n        return result;\n    }\n\n    /**\n     *  Get the current offset. The offset is adjusted for \"part\" updates.\n     *\n     * @param {!Session} session - the current session\n     * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n     * - type of update, name of file, and the text of the update.\n     * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n     * the changed portion of the text. For \"empty\" updates, the file has not been modified\n     * and the text is empty.\n     * @param {{line: number, ch: number}=} offset - the default offset (optional). Will\n     * use the cursor if not provided.\n     * @return {{line: number, ch: number}}\n     */\n    function getOffset(session, fileInfo, offset) {\n        var newOffset;\n\n        if (offset) {\n            newOffset = {line: offset.line, ch: offset.ch};\n        } else {\n            newOffset = session.getCursor();\n        }\n\n        if (fileInfo.type === MessageIds.TERN_FILE_INFO_TYPE_PART) {\n            newOffset.line = Math.max(0, newOffset.line - fileInfo.offsetLines);\n        }\n\n        return newOffset;\n    }\n\n    /**\n     * Get a Promise for all of the known properties from TernJS, for the directory and file.\n     * The properties will be used as guesses in tern.\n     * @param {Session} session - the active hinting session\n     * @param {Document} document - the document for which scope info is\n     *      desired\n     * @return {jQuery.Promise} - The promise will not complete until the tern\n     *      request has completed.\n     */\n    function requestGuesses(session, document) {\n        var $deferred = $.Deferred(),\n            fileInfo = getFileInfo(session),\n            offset = getOffset(session, fileInfo);\n\n        postMessage({\n            type: MessageIds.TERN_GET_GUESSES_MSG,\n            fileInfo: fileInfo,\n            offset: offset\n        });\n\n        var promise = addPendingRequest(fileInfo.name, offset, MessageIds.TERN_GET_GUESSES_MSG);\n        promise.done(function (guesses) {\n            session.setGuesses(guesses);\n            $deferred.resolve();\n        }).fail(function () {\n            $deferred.reject();\n        });\n\n        return $deferred.promise();\n    }\n\n    /**\n     * Handle the response from the tern node domain when\n     * it responds with the list of completions\n     *\n     * @param {{file: string, offset: {line: number, ch: number}, completions:Array.<string>,\n     *          properties:Array.<string>}} response - the response from node domain\n     */\n    function handleTernCompletions(response) {\n\n        var file = response.file,\n            offset = response.offset,\n            completions = response.completions,\n            properties = response.properties,\n            fnType  = response.fnType,\n            type = response.type,\n            error = response.error,\n            $deferredHints = getPendingRequest(file, offset, type);\n\n        if ($deferredHints) {\n            if (error) {\n                $deferredHints.reject();\n            } else if (completions) {\n                $deferredHints.resolveWith(null, [{completions: completions}]);\n            } else if (properties) {\n                $deferredHints.resolveWith(null, [{properties: properties}]);\n            } else if (fnType) {\n                $deferredHints.resolveWith(null, [fnType]);\n            }\n        }\n    }\n\n    /**\n     * Handle the response from the tern node domain when\n     * it responds to the get guesses message.\n     *\n     * @param {{file: string, type: string, offset: {line: number, ch: number},\n     *      properties: Array.<string>}} response -\n     *      the response from node domain contains the guesses for a\n     *      property lookup.\n     */\n    function handleGetGuesses(response) {\n        var path = response.file,\n            type = response.type,\n            offset = response.offset,\n            $deferredHints = getPendingRequest(path, offset, type);\n\n        if ($deferredHints) {\n            $deferredHints.resolveWith(null, [response.properties]);\n        }\n    }\n\n    /**\n     * Handle the response from the tern node domain when\n     * it responds to the update file message.\n     *\n     * @param {{path: string, type: string}} response - the response from node domain\n     */\n    function handleUpdateFile(response) {\n\n        var path = response.path,\n            type = response.type,\n            $deferredHints = getPendingRequest(path, OFFSET_ZERO, type);\n\n        if ($deferredHints) {\n            $deferredHints.resolve();\n        }\n    }\n\n    /**\n     * Handle timed out inference\n     *\n     * @param {{path: string, type: string}} response - the response from node domain\n     */\n    function handleTimedOut(response) {\n\n        var detectedExclusions  = PreferencesManager.get(\"jscodehints.detectedExclusions\") || [],\n            filePath            = response.file;\n\n        // Don't exclude the file currently being edited\n        if (isFileBeingEdited(filePath)) {\n            return;\n        }\n\n        // Handle file that is already excluded\n        if (detectedExclusions.indexOf(filePath) !== -1) {\n            console.log(\"JavaScriptCodeHints.handleTimedOut: file already in detectedExclusions array timed out: \" + filePath);\n            return;\n        }\n\n        // Save detected exclusion in project prefs so no further time is wasted on it\n        detectedExclusions.push(filePath);\n        PreferencesManager.set(\"jscodehints.detectedExclusions\", detectedExclusions, { location: { scope: \"project\" } });\n\n        // Show informational dialog\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_INFO,\n            Strings.DETECTED_EXCLUSION_TITLE,\n            StringUtils.format(\n                Strings.DETECTED_EXCLUSION_INFO,\n                StringUtils.breakableUrl(filePath)\n            ),\n            [\n                {\n                    className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                    id        : Dialogs.DIALOG_BTN_OK,\n                    text      : Strings.OK\n                }\n            ]\n        );\n    }\n    \n    DocumentManager.on(\"dirtyFlagChange\", function (event, changedDoc) {\n        if (changedDoc.file.fullPath) {\n            postMessage({\n                type: MessageIds.TERN_UPDATE_DIRTY_FILE,\n                name: changedDoc.file.fullPath,\n                action: changedDoc.isDirty\n            });\n        }\n    });\n\n    // Clear dirty document list in tern node domain\n    ProjectManager.on(\"beforeProjectClose\", function () {\n        postMessage({\n            type: MessageIds.TERN_CLEAR_DIRTY_FILES_LIST\n        });\n    });\n\n    /**\n     * Encapsulate all the logic to talk to the tern module.  This will create\n     * a new instance of a TernModule, which the rest of the hinting code can use to talk\n     * to the tern node domain, without worrying about initialization, priming the pump, etc.\n     *\n     */\n    function TernModule() {\n        var ternPromise         = null,\n            addFilesPromise     = null,\n            rootTernDir         = null,\n            projectRoot         = null,\n            stopAddingFiles     = false,\n            resolvedFiles       = {},       // file -> resolved file\n            numInitialFiles     = 0,\n            numResolvedFiles    = 0,\n            numAddedFiles       = 0,\n            _ternNodeDomain     = null;\n\n        /**\n         * @param {string} file a relative path\n         * @return {string} returns the path we resolved when we tried to parse the file, or undefined\n         */\n        function getResolvedPath(file) {\n            return resolvedFiles[file];\n        }\n\n        /**\n         *  Determine whether the current set of files are using modules to pull in\n         *  additional files.\n         *\n         * @return {boolean} - true if more files than the current directory have\n         * been read in.\n         */\n        function usingModules() {\n            return numInitialFiles !== numResolvedFiles;\n        }\n\n        /**\n         * Send a message to the tern node domain - if the module is being initialized,\n         * the message will not be posted until initialization is complete\n         */\n        function postMessage(msg) {\n            addFilesPromise.done(function (ternModule) {\n                // If an error came up during file handling, bail out now\n                if (!_ternNodeDomain) {\n                    return;\n                }\n\n                if (config.debug) {\n                    console.debug(\"Sending message\", msg);\n                }\n                _ternNodeDomain.exec(\"invokeTernCommand\", msg);\n            });\n        }\n\n        /**\n         * Send a message to the tern node domain - this is only for messages that\n         * need to be sent before and while the addFilesPromise is being resolved.\n         */\n        function _postMessageByPass(msg) {\n            ternPromise.done(function (ternModule) {\n                if (config.debug) {\n                    console.debug(\"Sending message\", msg);\n                }\n                _ternNodeDomain.exec(\"invokeTernCommand\", msg);\n            });\n        }\n\n        /**\n         *  Update tern with the new contents of a given file.\n         *\n         * @param {Document} document - the document to update\n         * @return {jQuery.Promise} - the promise for the request\n         */\n        function updateTernFile(document) {\n            var path  = document.file.fullPath;\n\n            _postMessageByPass({\n                type       : MessageIds.TERN_UPDATE_FILE_MSG,\n                path       : path,\n                text       : getTextFromDocument(document)\n            });\n\n            return addPendingRequest(path, OFFSET_ZERO, MessageIds.TERN_UPDATE_FILE_MSG);\n        }\n\n        /**\n         * Handle a request from the tern node domain for text of a file\n         *\n         * @param {{file:string}} request - the request from the tern node domain.  Should be an Object containing the name\n         *      of the file tern wants the contents of \n         */\n        function handleTernGetFile(request) {\n\n            function replyWith(name, txt) {\n                _postMessageByPass({\n                    type: MessageIds.TERN_GET_FILE_MSG,\n                    file: name,\n                    text: txt\n                });\n            }\n\n            var name = request.file;\n\n            /**\n             * Helper function to get the text of a given document and send it to tern.\n             * If DocumentManager successfully gets the file's text then we'll send it to the tern node domain.\n             * The Promise for getDocumentText() is returned so that custom fail functions can be used.\n             *\n             * @param {string} filePath - the path of the file to get the text of\n             * @return {jQuery.Promise} - the Promise returned from DocumentMangaer.getDocumentText()\n             */\n            function getDocText(filePath) {\n                if (!FileSystem.isAbsolutePath(filePath) || // don't handle URLs\n                        filePath.slice(0, 2) === \"//\") { // don't handle protocol-relative URLs like //example.com/main.js (see #10566)\n                    return (new $.Deferred()).reject().promise();\n                }\n\n                var file = FileSystem.getFileForPath(filePath),\n                    promise = DocumentManager.getDocumentText(file);\n\n                promise.done(function (docText) {\n                    resolvedFiles[name] = filePath;\n                    numResolvedFiles++;\n                    replyWith(name, filterText(docText));\n                });\n                return promise;\n            }\n\n            /**\n             * Helper function to find any files in the project that end with the\n             * name we are looking for.  This is so we can find requirejs modules\n             * when the baseUrl is unknown, or when the project root is not the same\n             * as the script root (e.g. if you open the 'brackets' dir instead of 'brackets/src' dir).\n             */\n            function findNameInProject() {\n                // check for any files in project that end with the right path.\n                var fileName = name.substring(name.lastIndexOf(\"/\") + 1);\n\n                function _fileFilter(entry) {\n                    return entry.name === fileName;\n                }\n\n                ProjectManager.getAllFiles(_fileFilter).done(function (files) {\n                    var file;\n                    files = files.filter(function (file) {\n                        var pos = file.fullPath.length - name.length;\n                        return pos === file.fullPath.lastIndexOf(name);\n                    });\n\n                    if (files.length === 1) {\n                        file = files[0];\n                    }\n                    if (file) {\n                        getDocText(file.fullPath).fail(function () {\n                            replyWith(name, \"\");\n                        });\n                    } else {\n                        replyWith(name, \"\");\n                    }\n                });\n            }\n\n            if (!isFileExcludedInternal(name)) {\n                getDocText(name).fail(function () {\n                    getDocText(rootTernDir + name).fail(function () {\n                        // check relative to project root\n                        getDocText(projectRoot + name)\n                            // last look for any files that end with the right path\n                            // in the project\n                            .fail(findNameInProject);\n                    });\n                });\n            }\n        }\n\n        /**\n         *  Prime the pump for a fast first lookup.\n         *\n         * @param {string} path - full path of file\n         * @return {jQuery.Promise} - the promise for the request\n         */\n        function primePump(path, isUntitledDoc) {\n            _postMessageByPass({\n                type            : MessageIds.TERN_PRIME_PUMP_MSG,\n                path            : path,\n                isUntitledDoc   : isUntitledDoc\n            });\n\n            return addPendingRequest(path, OFFSET_ZERO, MessageIds.TERN_PRIME_PUMP_MSG);\n        }\n\n        /**\n         * Handle the response from the tern node domain when\n         * it responds to the prime pump message.\n         *\n         * @param {{path: string, type: string}} response - the response from node domain\n         */\n        function handlePrimePumpCompletion(response) {\n\n            var path = response.path,\n                type = response.type,\n                $deferredHints = getPendingRequest(path, OFFSET_ZERO, type);\n\n            if ($deferredHints) {\n                $deferredHints.resolve();\n            }\n        }\n\n        /**\n         *  Add new files to tern, keeping any previous files.\n         *  The tern server must be initialized before making\n         *  this call.\n         *\n         * @param {Array.<string>} files - array of file to add to tern.\n         * @return {boolean} - true if more files may be added, false if maximum has been reached.\n         */\n        function addFilesToTern(files) {\n            // limit the number of files added to tern.\n            var maxFileCount = preferences.getMaxFileCount();\n            if (numResolvedFiles + numAddedFiles < maxFileCount) {\n                var available = maxFileCount - numResolvedFiles - numAddedFiles;\n\n                if (available < files.length) {\n                    files = files.slice(0, available);\n                }\n\n                numAddedFiles += files.length;\n                ternPromise.done(function (ternModule) {\n                    var msg = {\n                        type        : MessageIds.TERN_ADD_FILES_MSG,\n                        files       : files\n                    };\n\n                    if (config.debug) {\n                        console.debug(\"Sending message\", msg);\n                    }\n                    _ternNodeDomain.exec(\"invokeTernCommand\", msg);\n                });\n\n            } else {\n                stopAddingFiles = true;\n            }\n\n            return stopAddingFiles;\n        }\n\n        /**\n         *  Add the files in the directory and subdirectories of a given directory\n         *  to tern.\n         *\n         * @param {string} dir - the root directory to add.\n         * @param {function ()} doneCallback - called when all files have been\n         * added to tern.\n         */\n        function addAllFilesAndSubdirectories(dir, doneCallback) {\n            FileSystem.resolve(dir, function (err, directory) {\n                function visitor(entry) {\n                    if (entry.isFile) {\n                        if (!isFileExcluded(entry)) { // ignore .dotfiles and non-.js files\n                            addFilesToTern([entry.fullPath]);\n                        }\n                    } else {\n                        return !isDirectoryExcluded(entry.fullPath) &&\n                            entry.name.indexOf(\".\") !== 0 &&\n                            !stopAddingFiles;\n                    }\n                }\n\n                if (err) {\n                    return;\n                }\n\n                if (dir === FileSystem.getDirectoryForPath(rootTernDir)) {\n                    doneCallback();\n                    return;\n                }\n\n                directory.visit(visitor, doneCallback);\n            });\n        }\n\n        /**\n         * Init the Tern module that does all the code hinting work.\n         */\n        function initTernModule() {\n            var moduleDeferred = $.Deferred();\n            ternPromise = moduleDeferred.promise();\n            \n            function prepareTern() {  \n                _ternNodeDomain.exec(\"setInterface\", {\n                    messageIds : MessageIds\n                });\n\n                _ternNodeDomain.exec(\"invokeTernCommand\", {\n                    type: MessageIds.SET_CONFIG,\n                    config: config\n                });\n                moduleDeferred.resolveWith(null, [_ternNodeDomain]);\n            }\n            \n            if (_ternNodeDomain) {\n                _ternNodeDomain.exec(\"resetTernServer\");\n                moduleDeferred.resolveWith(null, [_ternNodeDomain]);\n            } else {\n                _ternNodeDomain     = new NodeDomain(\"TernNodeDomain\", _domainPath);\n                _ternNodeDomain.on(\"data\", function (evt, data) {\n                    if (config.debug) {\n                        console.log(\"Message received\", data.type);\n                    }\n\n                    var response = data,\n                        type = response.type;\n\n                    if (type === MessageIds.TERN_COMPLETIONS_MSG ||\n                            type === MessageIds.TERN_CALLED_FUNC_TYPE_MSG) {\n                        // handle any completions the tern server calculated\n                        handleTernCompletions(response);\n                    } else if (type === MessageIds.TERN_GET_FILE_MSG) {\n                        // handle a request for the contents of a file\n                        handleTernGetFile(response);\n                    } else if (type === MessageIds.TERN_JUMPTODEF_MSG) {\n                        handleJumptoDef(response);\n                    } else if (type === MessageIds.TERN_SCOPEDATA_MSG) {\n                        handleScopeData(response);\n                    } else if (type === MessageIds.TERN_REFS) {\n                        handleRename(response);\n                    } else if (type === MessageIds.TERN_PRIME_PUMP_MSG) {\n                        handlePrimePumpCompletion(response);\n                    } else if (type === MessageIds.TERN_GET_GUESSES_MSG) {\n                        handleGetGuesses(response);\n                    } else if (type === MessageIds.TERN_UPDATE_FILE_MSG) {\n                        handleUpdateFile(response);\n                    } else if (type === MessageIds.TERN_INFERENCE_TIMEDOUT) {\n                        handleTimedOut(response);\n                    } else if (type === MessageIds.TERN_WORKER_READY) {\n                        moduleDeferred.resolveWith(null, [_ternNodeDomain]);\n                    } else if (type === \"RE_INIT_TERN\") {\n                        // Ensure the request is because of a node restart\n                        if (currentModule) {\n                            prepareTern();\n                            // Mark the module with resetForced, then creation of TernModule will \n                            // happen again as part of '_maybeReset' call\n                            currentModule.resetForced = true;\n                        }\n                    } else {\n                        console.log(\"Tern Module: \" + (response.log || response));\n                    }\n                });\n            \n                _ternNodeDomain.promise().done(prepareTern);\n            }\n        }\n\n        /**\n         * Create a new tern server.\n         */\n        function initTernServer(dir, files) {\n            initTernModule();\n            numResolvedFiles = 0;\n            numAddedFiles = 0;\n            stopAddingFiles = false;\n            numInitialFiles = files.length;\n\n            ternPromise.done(function (ternModule) {\n                var msg = {\n                    type        : MessageIds.TERN_INIT_MSG,\n                    dir         : dir,\n                    files       : files,\n                    env         : ternEnvironment,\n                    timeout     : PreferencesManager.get(\"jscodehints.inferenceTimeout\")\n                };\n                _ternNodeDomain.exec(\"invokeTernCommand\", msg);\n            });\n            rootTernDir = dir + \"/\";\n        }\n\n        /**\n         *  We can skip tern initialization if we are opening a file that has\n         *  already been added to tern.\n         *\n         * @param {string} newFile - full path of new file being opened in the editor.\n         * @return {boolean} - true if tern initialization should be skipped,\n         * false otherwise.\n         */\n        function canSkipTernInitialization(newFile) {\n            return resolvedFiles[newFile] !== undefined;\n        }\n\n\n        /**\n         *  Do the work to initialize a code hinting session.\n         *\n         * @param {Session} session - the active hinting session (TODO: currently unused)\n         * @param {!Document} document - the document the editor has changed to\n         * @param {?Document} previousDocument - the document the editor has changed from\n         */\n        function doEditorChange(session, document, previousDocument) {\n            var file        = document.file,\n                path        = file.fullPath,\n                dir         = file.parentPath,\n                pr;\n\n            var addFilesDeferred = $.Deferred();\n\n            documentChanges = null;\n            addFilesPromise = addFilesDeferred.promise();\n            pr = ProjectManager.getProjectRoot() ? ProjectManager.getProjectRoot().fullPath : null;\n\n            // avoid re-initializing tern if possible.\n            if (canSkipTernInitialization(path)) {\n\n                // update the previous document in tern to prevent stale files.\n                if (isDocumentDirty && previousDocument) {\n                    var updateFilePromise = updateTernFile(previousDocument);\n                    updateFilePromise.done(function () {\n                        primePump(path, document.isUntitled());\n                        addFilesDeferred.resolveWith(null, [_ternNodeDomain]);\n                    });\n                } else {\n                    addFilesDeferred.resolveWith(null, [_ternNodeDomain]);\n                }\n\n                isDocumentDirty = false;\n                return;\n            }\n            \n            if (previousDocument && previousDocument.isDirty) {\n                updateTernFile(previousDocument);\n            }\n    \n            isDocumentDirty = false;\n            resolvedFiles = {};\n            projectRoot = pr;\n\n            ensurePreferences();\n            deferredPreferences.done(function () {\n                if (file instanceof InMemoryFile) {\n                    initTernServer(pr, []);\n                    var hintsPromise = primePump(path, true);\n                    hintsPromise.done(function () {\n                        addFilesDeferred.resolveWith(null, [_ternNodeDomain]);\n                    });\n                    return;\n                }\n\n                FileSystem.resolve(dir, function (err, directory) {\n                    if (err) {\n                        console.error(\"Error resolving\", dir);\n                        addFilesDeferred.resolveWith(null);\n                        return;\n                    }\n\n                    directory.getContents(function (err, contents) {\n                        if (err) {\n                            console.error(\"Error getting contents for\", directory);\n                            addFilesDeferred.resolveWith(null);\n                            return;\n                        }\n\n                        var files = contents\n                            .filter(function (entry) {\n                                return entry.isFile && !isFileExcluded(entry);\n                            })\n                            .map(function (entry) {\n                                return entry.fullPath;\n                            });\n\n                        initTernServer(dir, files);\n\n                        var hintsPromise = primePump(path, false);\n                        hintsPromise.done(function () {\n                            if (!usingModules()) {\n                                // Read the subdirectories of the new file's directory.\n                                // Read them first in case there are too many files to\n                                // read in the project.\n                                addAllFilesAndSubdirectories(dir, function () {\n                                    // If the file is in the project root, then read\n                                    // all the files under the project root.\n                                    var currentDir = (dir + \"/\");\n                                    if (projectRoot && currentDir !== projectRoot &&\n                                            currentDir.indexOf(projectRoot) === 0) {\n                                        addAllFilesAndSubdirectories(projectRoot, function () {\n                                            // prime the pump again but this time don't wait\n                                            // for completion.\n                                            primePump(path, false);\n                                            addFilesDeferred.resolveWith(null, [_ternNodeDomain]);\n                                        });\n                                    } else {\n                                        addFilesDeferred.resolveWith(null, [_ternNodeDomain]);\n                                    }\n                                });\n                            } else {\n                                addFilesDeferred.resolveWith(null, [_ternNodeDomain]);\n                            }\n                        });\n                    });\n                });\n            });\n        }\n\n        /**\n         * Called each time a new editor becomes active.\n         *\n         * @param {Session} session - the active hinting session (TODO: currently unused by doEditorChange())\n         * @param {!Document} document - the document of the editor that has changed\n         * @param {?Document} previousDocument - the document of the editor is changing from\n         */\n        function handleEditorChange(session, document, previousDocument) {\n            if (addFilesPromise === null) {\n                doEditorChange(session, document, previousDocument);\n            } else {\n                addFilesPromise.done(function () {\n                    doEditorChange(session, document, previousDocument);\n                });\n            }\n        }\n\n        /**\n         * Do some cleanup when a project is closed.\n         *\n         * We can clean up the node tern server we use to calculate hints now, since\n         * we know we will need to re-init it in any new project that is opened.  \n         */\n        function resetModule() {\n            function resetTernServer() {\n                if (_ternNodeDomain.ready()) {\n                    _ternNodeDomain.exec('resetTernServer');\n                }\n            }\n            \n            if (_ternNodeDomain) {\n                if (addFilesPromise) {\n                    // If we're in the middle of added files, don't reset \n                    // until we're done\n                    addFilesPromise.done(resetTernServer).fail(resetTernServer);\n                } else {\n                    resetTernServer();\n                }\n            }\n        }\n\n        function whenReady(func) {\n            addFilesPromise.done(func);\n        }\n        \n        this.resetModule = resetModule;\n        this.handleEditorChange = handleEditorChange;\n        this.postMessage = postMessage;\n        this.getResolvedPath = getResolvedPath;\n        this.whenReady = whenReady;\n\n        return this;\n    }\n\n    var resettingDeferred = null;\n\n    /**\n     * reset the tern module, if necessary.  \n     *\n     * During debugging, you can turn this automatic resetting behavior off\n     * by running this in the console:\n     * brackets._configureJSCodeHints({ noReset: true })\n     *\n     * This function is also used in unit testing with the \"force\" flag to\n     * reset the module for each test to start with a clean environment.\n     *\n     * @param {Session} session\n     * @param {Document} document\n     * @param {boolean} force true to force a reset regardless of how long since the last one\n     * @return {Promise} Promise resolved when the module is ready. \n     *                   The new (or current, if there was no reset) module is passed to the callback.\n     */\n    function _maybeReset(session, document, force) {\n        var newTernModule;\n        // if we're in the middle of a reset, don't have to check\n        // the new module will be online soon\n        if (!resettingDeferred) {\n\n            // We don't reset if the debugging flag is set\n            // because it's easier to debug if the module isn't\n            // getting reset all the time.\n            if (currentModule.resetForced || force || (!config.noReset && ++_hintCount > MAX_HINTS)) {\n                if (config.debug) {\n                    console.debug(\"Resetting tern module\");\n                }\n\n                resettingDeferred = new $.Deferred();\n                newTernModule = new TernModule();\n                newTernModule.handleEditorChange(session, document, null);\n                newTernModule.whenReady(function () {\n                    // reset the old module\n                    currentModule.resetModule();\n                    currentModule = newTernModule;\n                    resettingDeferred.resolve(currentModule);\n                    // all done reseting\n                    resettingDeferred = null;\n                });\n                _hintCount = 0;\n            } else {\n                var d = new $.Deferred();\n                d.resolve(currentModule);\n                return d.promise();\n            }\n        }\n\n        return resettingDeferred.promise();\n    }\n\n    /**\n     * Request a parameter hint from Tern.\n     *\n     * @param {Session} session - the active hinting session\n     * @param {{line: number, ch: number}} functionOffset - the offset of the function call.\n     * @return {jQuery.Promise} - The promise will not complete until the\n     *      hint has completed.\n     */\n    function requestParameterHint(session, functionOffset) {\n        var $deferredHints = $.Deferred(),\n            fileInfo = getFileInfo(session, true),\n            offset = getOffset(session, fileInfo, functionOffset),\n            fnTypePromise = getTernFunctionType(fileInfo, offset);\n\n        $.when(fnTypePromise).done(\n            function (fnType) {\n                session.setFnType(fnType);\n                session.setFunctionCallPos(functionOffset);\n                $deferredHints.resolveWith(null, [fnType]);\n            }\n        ).fail(function () {\n            $deferredHints.reject();\n        });\n\n        return $deferredHints.promise();\n    }\n\n    /**\n     * Request hints from Tern.\n     *\n     * Note that successive calls to getScope may return the same objects, so\n     * clients that wish to modify those objects (e.g., by annotating them based\n     * on some temporary context) should copy them first. See, e.g.,\n     * Session.getHints().\n     *\n     * @param {Session} session - the active hinting session\n     * @param {Document} document - the document for which scope info is\n     *      desired\n     * @return {jQuery.Promise} - The promise will not complete until the tern\n     *      hints have completed.\n     */\n    function requestHints(session, document) {\n        var $deferredHints = $.Deferred(),\n            hintPromise,\n            sessionType = session.getType(),\n            fileInfo = getFileInfo(session),\n            offset = getOffset(session, fileInfo, null);\n\n        _maybeReset(session, document);\n\n        hintPromise = getTernHints(fileInfo, offset, sessionType.property);\n\n        $.when(hintPromise).done(\n            function (completions, fnType) {\n                if (completions.completions) {\n                    session.setTernHints(completions.completions);\n                    session.setGuesses(null);\n                } else {\n                    session.setTernHints([]);\n                    session.setGuesses(completions.properties);\n                }\n\n                $deferredHints.resolveWith(null);\n            }\n        ).fail(function () {\n            $deferredHints.reject();\n        });\n\n        return $deferredHints.promise();\n    }\n\n    /**\n     *  Track the update area of the current document so we can tell if we can send\n     *  partial updates to tern or not.\n     *\n     * @param {Array.<{from: {line:number, ch: number}, to: {line:number, ch: number},\n     *     text: Array<string>}>} changeList - the document changes from the current change event\n     */\n    function trackChange(changeList) {\n        var changed = documentChanges, i;\n        if (changed === null) {\n            documentChanges = changed = {from: changeList[0].from.line, to: changeList[0].from.line};\n            if (config.debug) {\n                console.debug(\"ScopeManager: document has changed\");\n            }\n        }\n\n        for (i = 0; i < changeList.length; i++) {\n            var thisChange = changeList[i],\n                end = thisChange.from.line + (thisChange.text.length - 1);\n            if (thisChange.from.line < changed.to) {\n                changed.to = changed.to - (thisChange.to.line - end);\n            }\n\n            if (end >= changed.to) {\n                changed.to = end + 1;\n            }\n\n            if (changed.from > thisChange.from.line) {\n                changed.from = thisChange.from.line;\n            }\n        }\n    }\n\n    /*\n     * Called each time the file associated with the active editor changes.\n     * Marks the file as being dirty.\n     *\n     * @param {from: {line:number, ch: number}, to: {line:number, ch: number}}\n     */\n    function handleFileChange(changeList) {\n        isDocumentDirty = true;\n        trackChange(changeList);\n    }\n\n    /**\n     * Called each time a new editor becomes active.\n     *\n     * @param {Session} session - the active hinting session\n     * @param {Document} document - the document of the editor that has changed\n     * @param {?Document} previousDocument - the document of the editor is changing from\n     */\n    function handleEditorChange(session, document, previousDocument) {\n\n        if (!currentModule) {\n            currentModule = new TernModule();\n        }\n        \n        return currentModule.handleEditorChange(session, document, previousDocument);\n    }\n\n    /**\n     * Do some cleanup when a project is closed.\n     * Clean up previous analysis data from the module\n     */\n    function handleProjectClose() {\n        if (currentModule) {\n            currentModule.resetModule();\n        }\n    }\n\n    /**\n     *  Read in project preferences when a new project is opened.\n     *  Look in the project root directory for a preference file.\n     *\n     *  @param {string=} projectRootPath - new project root path(optional).\n     *  Only needed for unit tests.\n     */\n    function handleProjectOpen(projectRootPath) {\n        initPreferences(projectRootPath);\n    }\n\n    /** Used to avoid timing bugs in unit tests */\n    function _readyPromise() {\n        return deferredPreferences;\n    }\n\n    /**\n     * @private\n     * \n     * Update the configuration in the tern node domain.\n     */\n    function _setConfig(configUpdate) {\n        config = brackets._configureJSCodeHints.config;\n        postMessage({\n            type: MessageIds.SET_CONFIG,\n            config: configUpdate\n        });\n    }\n\n    exports._setConfig = _setConfig;\n    exports._maybeReset = _maybeReset;\n    exports.getBuiltins = getBuiltins;\n    exports.getResolvedPath = getResolvedPath;\n    exports.getTernHints = getTernHints;\n    exports.handleEditorChange = handleEditorChange;\n    exports.requestGuesses = requestGuesses;\n    exports.handleFileChange = handleFileChange;\n    exports.requestHints = requestHints;\n    exports.requestJumptoDef = requestJumptoDef;\n    exports.requestParameterHint = requestParameterHint;\n    exports.handleProjectClose = handleProjectClose;\n    exports.handleProjectOpen = handleProjectOpen;\n    exports._readyPromise = _readyPromise;\n    exports.filterText = filterText;\n    exports.postMessage = postMessage;\n    exports.addPendingRequest = addPendingRequest;\n});\n"
  },
  {
    "path": "src/JSUtils/Session.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var StringMatch     = require(\"utils/StringMatch\"),\n        TokenUtils      = require(\"utils/TokenUtils\"),\n        LanguageManager = require(\"language/LanguageManager\"),\n        HTMLUtils       = require(\"language/HTMLUtils\"),\n        HintUtils       = require(\"JSUtils/HintUtils\"),\n        ScopeManager    = require(\"JSUtils/ScopeManager\"),\n        Acorn           = require(\"node_modules/acorn/dist/acorn\"),\n        Acorn_Loose     = require(\"node_modules/acorn/dist/acorn_loose\");\n\n    /**\n     * Session objects encapsulate state associated with a hinting session\n     * and provide methods for updating and querying the session.\n     *\n     * @constructor\n     * @param {Editor} editor - the editor context for the session\n     */\n    function Session(editor) {\n        this.editor = editor;\n        this.path = editor.document.file.fullPath;\n        this.ternHints = [];\n        this.ternGuesses = null;\n        this.fnType = null;\n        this.builtins = null;\n    }\n\n    /**\n     *  Get the builtin libraries tern is using.\n     *\n     * @return {Array.<string>} - array of library names.\n     * @private\n     */\n    Session.prototype._getBuiltins = function () {\n        if (!this.builtins) {\n            this.builtins = ScopeManager.getBuiltins();\n            this.builtins.push(\"requirejs.js\");     // consider these globals as well.\n        }\n\n        return this.builtins;\n    };\n\n    /**\n     * Get the name of the file associated with the current session\n     *\n     * @return {string} - the full pathname of the file associated with the\n     *      current session\n     */\n    Session.prototype.getPath = function () {\n        return this.path;\n    };\n\n    /**\n     * Get the current cursor position.\n     *\n     * @return {{line: number, ch: number}} - the current cursor position\n     */\n    Session.prototype.getCursor = function () {\n        return this.editor.getCursorPos();\n    };\n\n    /**\n     * Get the text of a line.\n     *\n     * @param {number} line - the line number\n     * @return {string} - the text of the line\n     */\n    Session.prototype.getLine = function (line) {\n        var doc = this.editor.document;\n        return doc.getLine(line);\n    };\n\n    /**\n     * Get the offset of the current cursor position\n     *\n     * @return {number} - the offset into the current document of the current\n     *      cursor\n     */\n    Session.prototype.getOffset = function () {\n        var cursor = this.getCursor();\n\n        return this.getOffsetFromCursor(cursor);\n    };\n\n    /**\n     * Get the offset of a cursor position\n     *\n     * @param {{line: number, ch: number}} the line/col info\n     * @return {number} - the offset into the current document of the cursor\n     */\n    Session.prototype.getOffsetFromCursor = function (cursor) {\n        return this.editor.indexFromPos(cursor);\n    };\n\n    /**\n     * Get the token at the given cursor position, or at the current cursor\n     * if none is given.\n     *\n     * @param {?{line: number, ch: number}} cursor - the cursor position\n     *      at which to retrieve a token\n     * @return {Object} - the CodeMirror token at the given cursor position\n     */\n    Session.prototype.getToken = function (cursor) {\n        var cm = this.editor._codeMirror;\n\n        if (cursor) {\n            return TokenUtils.getTokenAt(cm, cursor);\n        } else {\n            return TokenUtils.getTokenAt(cm, this.getCursor());\n        }\n    };\n\n    /**\n     * Get the token after the one at the given cursor position\n     *\n     * @param {{line: number, ch: number}} cursor - cursor position before\n     *      which a token should be retrieved\n     * @return {Object} - the CodeMirror token after the one at the given\n     *      cursor position\n     */\n    Session.prototype.getNextTokenOnLine = function (cursor) {\n        cursor = this.getNextCursorOnLine(cursor);\n        if (cursor) {\n            return this.getToken(cursor);\n        }\n\n        return null;\n    };\n\n    /**\n     * Get the next cursor position on the line, or null if there isn't one.\n     *\n     * @return {?{line: number, ch: number}} - the cursor position\n     *      immediately following the current cursor position, or null if\n     *      none exists.\n     */\n    Session.prototype.getNextCursorOnLine = function (cursor) {\n        var doc     = this.editor.document,\n            line    = doc.getLine(cursor.line);\n\n        if (cursor.ch < line.length) {\n            return {\n                ch  : cursor.ch + 1,\n                line: cursor.line\n            };\n        } else {\n            return null;\n        }\n    };\n\n    /**\n     * Get the token before the one at the given cursor position\n     *\n     * @param {{line: number, ch: number}} cursor - cursor position after\n     *      which a token should be retrieved\n     * @return {Object} - the CodeMirror token before the one at the given\n     *      cursor position\n     */\n    Session.prototype._getPreviousToken = function (cursor) {\n        var token   = this.getToken(cursor),\n            prev    = token,\n            doc     = this.editor.document;\n\n        do {\n            if (prev.start < cursor.ch) {\n                cursor.ch = prev.start;\n            } else if (prev.start > 0) {\n                cursor.ch = prev.start - 1;\n            } else if (cursor.line > 0) {\n                cursor.ch = doc.getLine(cursor.line - 1).length;\n                cursor.line--;\n            } else {\n                break;\n            }\n            prev = this.getToken(cursor);\n        } while (!/\\S/.test(prev.string));\n\n        return prev;\n    };\n\n    /**\n     * Get the token after the one at the given cursor position\n     *\n     * @param {{line: number, ch: number}} cursor - cursor position after\n     *      which a token should be retrieved\n     * @param {boolean} skipWhitespace - true if this should skip over whitespace tokens\n     * @return {Object} - the CodeMirror token after the one at the given\n     *      cursor position\n     */\n    Session.prototype.getNextToken = function (cursor, skipWhitespace) {\n        var token   = this.getToken(cursor),\n            next    = token,\n            doc     = this.editor.document;\n\n        do {\n            if (next.end > cursor.ch) {\n                cursor.ch = next.end;\n            } else if (next.end < doc.getLine(cursor.line).length) {\n                cursor.ch = next.end + 1;\n            } else if (doc.getLine(cursor.line + 1)) {\n                cursor.ch = 0;\n                cursor.line++;\n            } else {\n                next = null;\n                break;\n            }\n            next = this.getToken(cursor);\n        } while (skipWhitespace && !/\\S/.test(next.string));\n\n        return next;\n    };\n\n    /**\n     * Calculate a query string relative to the current cursor position\n     * and token. E.g., from a state \"identi<cursor>er\", the query string is\n     * \"identi\".\n     *\n     * @return {string} - the query string for the current cursor position\n     */\n    Session.prototype.getQuery = function () {\n        var cursor  = this.getCursor(),\n            token   = this.getToken(cursor),\n            query   = \"\",\n            start   = cursor.ch,\n            end     = start;\n\n        if (token) {\n            var line = this.getLine(cursor.line);\n            while (start > 0) {\n                if (HintUtils.maybeIdentifier(line[start - 1])) {\n                    start--;\n                } else {\n                    break;\n                }\n            }\n\n            query = line.substring(start, end);\n        }\n\n        return query;\n    };\n\n    /**\n     * Find the context of a property lookup. For example, for a lookup\n     * foo(bar, baz(quux)).prop, foo is the context.\n     *\n     * @param {{line: number, ch: number}} cursor - the cursor position\n     *      at which context information is to be retrieved\n     * @param {number=} depth - the current depth of the parenthesis stack, or\n     *      undefined if the depth is 0.\n     * @return {string} - the context for the property that was looked up\n     */\n    Session.prototype.getContext = function (cursor, depth) {\n        var token = this.getToken(cursor);\n\n        if (depth === undefined) {\n            depth = 0;\n        }\n\n        if (token.string === \")\") {\n            this._getPreviousToken(cursor);\n            return this.getContext(cursor, ++depth);\n        } else if (token.string === \"(\") {\n            this._getPreviousToken(cursor);\n            return this.getContext(cursor, --depth);\n        } else {\n            if (depth > 0 || token.string === \".\") {\n                this._getPreviousToken(cursor);\n                return this.getContext(cursor, depth);\n            } else {\n                return token.string;\n            }\n        }\n    };\n\n    /**\n     * @return {{line:number, ch:number}} - the line, col info for where the previous \".\"\n     *      in a property lookup occurred, or undefined if no previous \".\" was found.\n     */\n    Session.prototype.findPreviousDot = function () {\n        var cursor = this.getCursor(),\n            token = this.getToken(cursor);\n\n        // If the cursor is right after the dot, then the current token will be \".\"\n        if (token && token.string === \".\") {\n            return cursor;\n        } else {\n            // If something has been typed like 'foo.b' then we have to look back 2 tokens\n            // to get past the 'b' token\n            token = this._getPreviousToken(cursor);\n            if (token && token.string === \".\") {\n                return cursor;\n            }\n        }\n        return undefined;\n    };\n\n    /**\n     *\n     * @param {Object} token - a CodeMirror token\n     * @return {*} - the lexical state of the token\n     */\n    function getLexicalState(token) {\n        if (token.state.lexical) {\n            // in a javascript file this is just in the state field\n            return token.state.lexical;\n        } else if (token.state.localState && token.state.localState.lexical) {\n            // inline javascript in an html file will have this in\n            // the localState field\n            return token.state.localState.lexical;\n        }\n    }\n\n\n    /**\n     * Determine if the caret is either within a function call or on the function call itself.\n     *\n     * @return {{inFunctionCall: boolean, functionCallPos: {line: number, ch: number}}}\n     * inFunctionCall - true if the caret if either within a function call or on the\n     * function call itself.\n     * functionCallPos - the offset of the '(' character of the function call if inFunctionCall\n     * is true, otherwise undefined.\n     */\n    Session.prototype.getFunctionInfo = function () {\n        var inFunctionCall   = false,\n            cursor           = this.getCursor(),\n            functionCallPos,\n            token            = this.getToken(cursor),\n            lexical,\n            self = this,\n            foundCall = false;\n\n        /**\n         * Test if the cursor is on a function identifier\n         *\n         * @return {Object} - lexical state if on a function identifier, null otherwise.\n         */\n        function isOnFunctionIdentifier() {\n\n            // Check if we might be on function identifier of the function call.\n            var type = token.type,\n                nextToken,\n                localLexical,\n                localCursor = {line: cursor.line, ch: token.end};\n\n            if (type === \"variable-2\" || type === \"variable\" || type === \"property\") {\n                nextToken = self.getNextToken(localCursor, true);\n                if (nextToken && nextToken.string === \"(\") {\n                    localLexical = getLexicalState(nextToken);\n                    return localLexical;\n                }\n            }\n\n            return null;\n        }\n\n        /**\n         * Test is a lexical state is in a function call.\n         *\n         * @param {Object} lex - lexical state.\n         * @return {Object | boolean}\n         *\n         */\n        function isInFunctionalCall(lex) {\n            // in a call, or inside array or object brackets that are inside a function.\n            return (lex && (lex.info === \"call\" ||\n                (lex.info === undefined && (lex.type === \"]\" || lex.type === \"}\") &&\n                    lex.prev.info === \"call\")));\n        }\n\n        if (token) {\n            // if this token is part of a function call, then the tokens lexical info\n            // will be annotated with \"call\".\n            // If the cursor is inside an array, \"[]\", or object, \"{}\", the lexical state\n            // will be undefined, not \"call\". lexical.prev will be the function state.\n            // Handle this case and then set \"lexical\" to lexical.prev.\n            // Also test if the cursor is on a function identifier of a function call.\n            lexical = getLexicalState(token);\n            foundCall = isInFunctionalCall(lexical);\n\n            if (!foundCall) {\n                lexical = isOnFunctionIdentifier();\n                foundCall = isInFunctionalCall(lexical);\n            }\n\n            if (foundCall) {\n                // we need to find the location of the called function so that we can request the functions type.\n                // the token's lexical info will contain the column where the open \"(\" for the\n                // function call occurs, but for whatever reason it does not have the line, so\n                // we have to walk back and try to find the correct location.  We do this by walking\n                // up the lines starting with the line the token is on, and seeing if any of the lines\n                // have \"(\" at the column indicated by the tokens lexical state.\n                // We walk back 9 lines, as that should be far enough to find most function calls,\n                // and it will prevent us from walking back thousands of lines if something went wrong.\n                // there is nothing magical about 9 lines, and it can be adjusted if it doesn't seem to be\n                // working well\n                if (lexical.info === undefined) {\n                    lexical = lexical.prev;\n                }\n\n                var col = lexical.info === \"call\" ? lexical.column : lexical.prev.column,\n                    line,\n                    e,\n                    found;\n                for (line = this.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {\n                    if (this.getLine(line).charAt(col) === \"(\") {\n                        found = true;\n                        break;\n                    }\n                }\n\n                if (found) {\n                    inFunctionCall = true;\n                    functionCallPos = {line: line, ch: col};\n                }\n            }\n        }\n\n        return {\n            inFunctionCall: inFunctionCall,\n            functionCallPos: functionCallPos\n        };\n    };\n\n    /**\n     * Get the type of the current session, i.e., whether it is a property\n     * lookup and, if so, what the context of the lookup is.\n     *\n     * @return {{property: boolean,\n                 context: string} - an Object consisting\n     *      of a {boolean} \"property\" that indicates whether or not the type of\n     *      the session is a property lookup, and a {string} \"context\" that\n     *      indicates the object context (as described in getContext above) of\n     *      the property lookup, or null if there is none. The context is\n     *      always null for non-property lookups.\n     */\n    Session.prototype.getType = function () {\n        var propertyLookup   = false,\n            context          = null,\n            cursor           = this.getCursor(),\n            token            = this.getToken(cursor);\n\n        if (token) {\n            if (token.type === \"property\") {\n                propertyLookup = true;\n            }\n\n            cursor = this.findPreviousDot();\n            if (cursor) {\n                propertyLookup = true;\n                context = this.getContext(cursor);\n            }\n        }\n\n        return {\n            property: propertyLookup,\n            context: context\n        };\n    };\n\n    // Comparison function used for sorting that does a case-insensitive string\n    // comparison on the \"value\" field of both objects. Unlike a normal string\n    // comparison, however, this sorts leading \"_\" to the bottom, given that a\n    // leading \"_\" usually denotes a private value.\n    function penalizeUnderscoreValueCompare(a, b) {\n        var aName = a.value.toLowerCase(), bName = b.value.toLowerCase();\n        // this sort function will cause _ to sort lower than lower case\n        // alphabetical letters\n        if (aName[0] === \"_\" && bName[0] !== \"_\") {\n            return 1;\n        } else if (bName[0] === \"_\" && aName[0] !== \"_\") {\n            return -1;\n        }\n        if (aName < bName) {\n            return -1;\n        } else if (aName > bName) {\n            return 1;\n        }\n        return 0;\n    }\n\n    /**\n     * Get a list of hints for the current session using the current scope\n     * information.\n     *\n     * @param {string} query - the query prefix\n     * @param {StringMatcher} matcher - the class to find query matches and sort the results\n     * @return {hints: Array.<string>, needGuesses: boolean} - array of\n     * matching hints. If needGuesses is true, then the caller needs to\n     * request guesses and call getHints again.\n     */\n    Session.prototype.getHints = function (query, matcher) {\n\n        if (query === undefined) {\n            query = \"\";\n        }\n\n        var MAX_DISPLAYED_HINTS = 500,\n            type                = this.getType(),\n            builtins            = this._getBuiltins(),\n            needGuesses         = false,\n            hints;\n\n        /**\n         *  Is the origin one of the builtin files.\n         *\n         * @param {string} origin\n         */\n        function isBuiltin(origin) {\n            return builtins.indexOf(origin) !== -1;\n        }\n\n        /**\n         *  Filter an array hints using a given query and matcher.\n         *  The hints are returned in the format of the matcher.\n         *  The matcher returns the value in the \"label\" property,\n         *  the match score in \"matchGoodness\" property.\n         *\n         * @param {Array} hints - array of hints\n         * @param {StringMatcher} matcher\n         * @return {Array} - array of matching hints.\n         */\n        function filterWithQueryAndMatcher(hints, matcher) {\n            var matchResults = $.map(hints, function (hint) {\n                var searchResult = matcher.match(hint.value, query);\n                if (searchResult) {\n                    searchResult.value = hint.value;\n                    searchResult.guess = hint.guess;\n                    searchResult.type = hint.type;\n\n                    if (hint.keyword !== undefined) {\n                        searchResult.keyword = hint.keyword;\n                    }\n\n                    if (hint.literal !== undefined) {\n                        searchResult.literal = hint.literal;\n                    }\n\n                    if (hint.depth !== undefined) {\n                        searchResult.depth = hint.depth;\n                    }\n\n                    if (hint.doc) {\n                        searchResult.doc = hint.doc;\n                    }\n\n                    if (hint.url) {\n                        searchResult.url = hint.url;\n                    }\n\n                    if (!type.property && !type.showFunctionType && hint.origin &&\n                            isBuiltin(hint.origin)) {\n                        searchResult.builtin = 1;\n                    } else {\n                        searchResult.builtin = 0;\n                    }\n                }\n\n                return searchResult;\n            });\n\n            return matchResults;\n        }\n\n        if (type.property) {\n            hints = this.ternHints || [];\n            hints = filterWithQueryAndMatcher(hints, matcher);\n\n            // If there are no hints then switch over to guesses.\n            if (hints.length === 0) {\n                if (this.ternGuesses) {\n                    hints = filterWithQueryAndMatcher(this.ternGuesses, matcher);\n                } else {\n                    needGuesses = true;\n                }\n            }\n\n            StringMatch.multiFieldSort(hints, [ \"matchGoodness\", penalizeUnderscoreValueCompare ]);\n        } else {     // identifiers, literals, and keywords\n            hints = this.ternHints || [];\n            hints = hints.concat(HintUtils.LITERALS);\n            hints = hints.concat(HintUtils.KEYWORDS);\n            hints = filterWithQueryAndMatcher(hints, matcher);\n            StringMatch.multiFieldSort(hints, [ \"matchGoodness\", \"depth\", \"builtin\", penalizeUnderscoreValueCompare ]);\n        }\n\n        if (hints.length > MAX_DISPLAYED_HINTS) {\n            hints = hints.slice(0, MAX_DISPLAYED_HINTS);\n        }\n\n        return {hints: hints, needGuesses: needGuesses};\n    };\n\n    Session.prototype.setTernHints = function (newHints) {\n        this.ternHints = newHints;\n    };\n\n    Session.prototype.setGuesses = function (newGuesses) {\n        this.ternGuesses = newGuesses;\n    };\n\n    /**\n     * Set a new function type hint.\n     *\n     * @param {Array<{name: string, type: string, isOptional: boolean}>} newFnType -\n     * Array of function hints.\n     */\n    Session.prototype.setFnType = function (newFnType) {\n        this.fnType = newFnType;\n    };\n\n    /**\n     * The position of the function call for the current fnType.\n     *\n     * @param {{line:number, ch:number}} functionCallPos - the offset of the function call.\n     */\n    Session.prototype.setFunctionCallPos = function (functionCallPos) {\n        this.functionCallPos = functionCallPos;\n    };\n\n    /**\n     * Get the function type hint.  This will format the hint, showing the\n     * parameter at the cursor in bold.\n     *\n     * @return {{parameters: Array<{name: string, type: string, isOptional: boolean}>,\n     * currentIndex: number}} An Object where the\n     * \"parameters\" property is an array of parameter objects;\n     * the \"currentIndex\" property index of the hint the cursor is on, may be\n     * -1 if the cursor is on the function identifier.\n     */\n    Session.prototype.getParameterHint = function () {\n        var fnHint = this.fnType,\n            cursor = this.getCursor(),\n            token = this.getToken(this.functionCallPos),\n            start = {line: this.functionCallPos.line, ch: token.start},\n            fragment = this.editor.document.getRange(start,\n                {line: this.functionCallPos.line + 10, ch: 0});\n\n        var ast;\n        try {\n            ast = Acorn.parse(fragment);\n        } catch (e) {\n            ast = Acorn_Loose.parse_dammit(fragment, {});\n        }\n\n        // find argument as cursor location and bold it.\n        var startOffset = this.getOffsetFromCursor(start),\n            cursorOffset = this.getOffsetFromCursor(cursor),\n            offset = cursorOffset - startOffset,\n            node = ast.body[0],\n            currentArg = -1;\n\n        if (node.type === \"ExpressionStatement\") {\n            node = node.expression;\n            if (node.type === \"SequenceExpression\") {\n                node = node.expressions[0];\n            }\n            if (node.type === \"BinaryExpression\") {\n                if (node.left.type === \"CallExpression\") {\n                    node = node.left;\n                } else if (node.right.type === \"CallExpression\") {\n                    node = node.right;\n                }\n            }\n            if (node.type === \"CallExpression\") {\n                var args = node[\"arguments\"],\n                    i,\n                    n = args.length,\n                    lastEnd = offset,\n                    text;\n                for (i = 0; i < n; i++) {\n                    node = args[i];\n                    if (offset >= node.start && offset <= node.end) {\n                        currentArg = i;\n                        break;\n                    } else if (offset < node.start) {\n                        // The range of nodes can be disjoint so see i f we\n                        // passed the node. If we passed the node look at the\n                        // text between the nodes to figure out which\n                        // arg we are on.\n                        text = fragment.substring(lastEnd, node.start);\n\n                        // test if comma is before or after the offset\n                        if (text.indexOf(\",\") >= (offset - lastEnd)) {\n                            // comma is after the offset so the current arg is the\n                            // previous arg node.\n                            i--;\n                        } else if (i === 0 && text.indexOf(\"(\") !== -1) {\n                            // the cursor is on the function identifier\n                            currentArg = -1;\n                            break;\n                        }\n\n                        currentArg = Math.max(0, i);\n                        break;\n                    } else if (i + 1 === n) {\n                        // look for a comma after the node.end. This will tell us we\n                        // are on the next argument, even there is no text, and therefore no node,\n                        // for the next argument.\n                        text = fragment.substring(node.end, offset);\n                        if (text.indexOf(\",\") !== -1) {\n                            currentArg = i + 1; // we know we are after the current arg, but keep looking\n                        }\n                    }\n\n                    lastEnd = node.end;\n                }\n\n                // if there are no args, then figure out if we are on the function identifier\n                if (n === 0 && cursorOffset > this.getOffsetFromCursor(this.functionCallPos)) {\n                    currentArg = 0;\n                }\n            }\n        }\n\n        return {parameters: fnHint, currentIndex: currentArg};\n    };\n\n    /**\n     * Get the javascript text of the file open in the editor for this Session.\n     * For a javascript file, this is just the text of the file.  For an HTML file,\n     * this will be only the text in the <script> tags.  This is so that we can pass\n     * just the javascript text to tern, and avoid confusing it with HTML tags, since it\n     * only knows how to parse javascript.\n     * @return {string} - the \"javascript\" text that can be sent to Tern.\n     */\n    Session.prototype.getJavascriptText = function () {\n        if (LanguageManager.getLanguageForPath(this.editor.document.file.fullPath).getId() === \"html\") {\n            // HTML file - need to send back only the bodies of the\n            // <script> tags\n            var text = \"\",\n                editor = this.editor,\n                scriptBlocks = HTMLUtils.findBlocks(editor, \"javascript\");\n\n            // Add all the javascript text\n            // For non-javascript blocks we replace everything except for newlines\n            // with whitespace.  This is so that the offset and cursor positions\n            // we get from the document still work.\n            // Alternatively we could strip the non-javascript text, and modify the offset,\n            // and/or cursor, but then we have to remember how to reverse the translation\n            // to support jump-to-definition\n            var htmlStart = {line: 0, ch: 0};\n            scriptBlocks.forEach(function (scriptBlock) {\n                var start = scriptBlock.start,\n                    end = scriptBlock.end;\n\n                // get the preceding html text, and replace it with whitespace\n                var htmlText = editor.document.getRange(htmlStart, start);\n                htmlText = htmlText.replace(/./g, \" \");\n\n                htmlStart = end;\n                text += htmlText + scriptBlock.text;\n            });\n\n            return text;\n        } else {\n            // Javascript file, just return the text\n            return this.editor.document.getText();\n        }\n    };\n\n    /**\n     * Determine if the cursor is located in the name of a function declaration.\n     * This is so we can suppress hints when in a function name, as we do for variable and\n     * parameter declarations, but we can tell those from the token itself rather than having\n     * to look at previous tokens.\n     *\n     * @return {boolean} - true if the current cursor position is in the name of a function\n     * declaration.\n     */\n    Session.prototype.isFunctionName = function () {\n        var cursor = this.getCursor(),\n            prevToken = this._getPreviousToken(cursor);\n\n        return prevToken.string === \"function\";\n    };\n\n    module.exports = Session;\n});\n"
  },
  {
    "path": "src/JSUtils/node/ExtractFileContent.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n        \nvar fs = require(\"fs\"),\n    _dirtyFilesCache = {};\n\n/**\n * Clears the cache for dirty file paths\n */\nfunction clearDirtyFilesCache() {\n    _dirtyFilesCache = {};\n}\n\n/**\n * Updates the files cache with fullpath when dirty flag changes for a document\n * If the doc is being marked as dirty then an entry is created in the cache\n * If the doc is being marked as clean then the corresponsing entry gets cleared from cache\n *\n * @param {String} name - fullpath of the document\n * @param {boolean} action - whether the document is dirty\n */\nfunction updateDirtyFilesCache(name, action) {\n    if (action) {\n        _dirtyFilesCache[name] = true;\n    } else {\n        if (_dirtyFilesCache[name]) {\n            delete _dirtyFilesCache[name];\n        }\n    }\n}\n\n/**\n * Extract content locally from the file system used fs.readFile()\n *\n * @param {String} fileName - fullpath of the document\n * @param {Function} callback - callback handle to post the content back\n */\nfunction _readFile(fileName, callback) {\n    fs.readFile(fileName, \"utf8\", function (err, data) {\n        var content = \"\";\n        if (!err) {\n            content = data;\n        }\n        callback.apply(null, [fileName, content]);\n    });\n}\n\n/**\n * Extracts file content for the given file name(1st param) and invokes the callback handle(2nd param) with \n * extracted file content. Content can be extracted locally from the file system used fs.readFile()\n * or conditionally from main context(brackets main thread) by using the 3rd param \n *\n * @param {String} fileName - fullpath of the document\n * @param {Function} callback - callback handle to post the content back\n * @param {Object} extractFromMainContext - content request handle wrapper from main thread\n */\nfunction extractContent(fileName, callback, extractFromMainContext) {\n    // Ask the main thread context to provide the updated file content\n    // We can't yet use node io to read, to utilize shells encoding detection\n    extractFromMainContext.apply(null, [fileName]);\n}\n\nexports.extractContent = extractContent;\nexports.clearFilesCache = clearDirtyFilesCache;\nexports.updateFilesCache = updateDirtyFilesCache;\n\n"
  },
  {
    "path": "src/JSUtils/node/TernNodeDomain.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*eslint-env node */\n/*jslint node: true */\n/*global setImmediate */\n\n\n\n\"use strict\";\n\nvar config = {};\nvar _domainManager;\nvar MessageIds;\nvar ternOptions;\nvar self = {\n    postMessage: function (data) {\n        _domainManager.emitEvent(\"TernNodeDomain\", \"data\", [data]);\n    }\n};\n\nvar Tern = require(\"tern\"),\n    Infer = require(\"tern/lib/infer\");\n    \nrequire(\"tern/plugin/requirejs\");\nrequire(\"tern/plugin/doc_comment\");\nrequire(\"tern/plugin/angular\");\n\n\nvar ExtractContent = require(\"./ExtractFileContent\");\n\nvar ternServer  = null,\n    isUntitledDoc = false,\n    inferenceTimeout;\n\n// Save the tern callbacks for when we get the contents of the file\nvar fileCallBacks = {};\n\n/**\n * Send a log message back from the node to the main thread\n * @private\n * @param {string} msg - the log message\n */\nfunction _log(msg) {\n    console.log(msg);\n}\n\n/**\n * Report exception\n * @private\n * @param {Error} e - the error object\n */\nfunction _reportError(e, file) {\n    if (e instanceof Infer.TimedOut) {\n        // Post a message back to the main thread with timedout info\n        self.postMessage({\n            type: MessageIds.TERN_INFERENCE_TIMEDOUT,\n            file: file\n        });\n    } else {\n        _log(\"Error thrown in tern_node domain:\" + e.message + \"\\n\" + e.stack);\n    }\n}\n\n/**\n * Handle a response from the main thread providing the contents of a file\n * @param {string} file - the name of the file\n * @param {string} text - the contents of the file\n */\nfunction handleGetFile(file, text) {\n    var next = fileCallBacks[file];\n    if (next) {\n        try {\n            next(null, text);\n        } catch (e) {\n            _reportError(e, file);\n        }\n    }\n    delete fileCallBacks[file];\n}\n\nfunction _getNormalizedFilename(fileName) {\n    if (!isUntitledDoc && ternServer.projectDir && fileName.indexOf(ternServer.projectDir) === -1) {\n        fileName = ternServer.projectDir + fileName;\n    }\n    return fileName;\n}\n\nfunction _getDenormalizedFilename(fileName) {\n    if (!isUntitledDoc && ternServer.projectDir && fileName.indexOf(ternServer.projectDir) === 0) {\n        fileName = fileName.slice(ternServer.projectDir.length);\n    }\n    return fileName;\n}\n\n/**\n * Callback handle to request contents of a file from the main thread\n * @param {string} file - the name of the file\n */\nfunction _requestFileContent(name) {\n    self.postMessage({\n        type: MessageIds.TERN_GET_FILE_MSG,\n        file: name\n    });\n}\n\n/**\n * Provide the contents of the requested file to tern\n * @param {string} name - the name of the file\n * @param {Function} next - the function to call with the text of the file\n *  once it has been read in.\n */\nfunction getFile(name, next) {\n    // save the callback\n    fileCallBacks[name] = next;\n\n    setImmediate(function () {\n        try {\n            ExtractContent.extractContent(name, handleGetFile, _requestFileContent);\n        } catch (error) {\n            console.log(error);\n        }\n    });\n}\n\n/**\n * Create a new tern server.\n *\n * @param {Object} env - an Object with the environment, as read in from\n *  the json files in thirdparty/tern/defs\n * @param {Array.<string>} files - a list of filenames tern should be aware of\n */\nfunction initTernServer(env, files) {\n    ternOptions = {\n        defs: env,\n        async: true,\n        getFile: getFile,\n        plugins: {requirejs: {}, doc_comment: true, angular: true},\n        ecmaVersion: 9\n    };\n\n    // If a server is already created just reset the analysis data before marking it for GC\n    if (ternServer) {\n        ternServer.reset();\n        Infer.resetGuessing();\n    }\n        \n    ternServer = new Tern.Server(ternOptions);\n\n    files.forEach(function (file) {\n        ternServer.addFile(file);\n    });\n\n}\n\n/**\n * Resets an existing tern server.\n */\nfunction resetTernServer() {\n    // If a server is already created just reset the analysis data \n    if (ternServer) {\n        ternServer.reset();\n        Infer.resetGuessing();\n        // tell the main thread we're ready to start processing again\n        self.postMessage({type: MessageIds.TERN_WORKER_READY});\n    }\n}\n\n/**\n * Create a \"empty\" update object.\n *\n * @param {string} path - full path of the file.\n * @return {{type: string, name: string, offsetLines: number, text: string}} -\n * \"empty\" update.\n\n */\nfunction createEmptyUpdate(path) {\n    return {type: MessageIds.TERN_FILE_INFO_TYPE_EMPTY,\n        name: path,\n        offsetLines: 0,\n        text: \"\"};\n}\n\n/**\n * Build an object that can be used as a request to tern.\n *\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {string} query - the type of request being made\n * @param {{line: number, ch: number}} offset -\n */\nfunction buildRequest(fileInfo, query, offset) {\n    query = {type: query};\n    query.start = offset;\n    query.end = offset;\n    query.file = (fileInfo.type === MessageIds.TERN_FILE_INFO_TYPE_PART) ? \"#0\" : fileInfo.name;\n    query.filter = false;\n    query.sort = false;\n    query.depths = true;\n    query.guess = true;\n    query.origins = true;\n    query.types = true;\n    query.expandWordForward = false;\n    query.lineCharPositions = true;\n    query.docs = true;\n    query.urls = true;\n\n    var request = {query: query, files: [], offset: offset, timeout: inferenceTimeout};\n    if (fileInfo.type !== MessageIds.TERN_FILE_INFO_TYPE_EMPTY) {\n        // Create a copy to mutate ahead\n        var fileInfoCopy = JSON.parse(JSON.stringify(fileInfo));\n        request.files.push(fileInfoCopy);\n    }\n\n    return request;\n}\n\n\n/**\n * Get all References location\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {{line: number, ch: number}} offset - the offset into the\n * file for cursor\n */\n function getRefs(fileInfo, offset) {\n    var request = buildRequest(fileInfo, \"refs\", offset);\n    try {\n        ternServer.request(request, function (error, data) {\n            if (error) {\n                _log(\"Error returned from Tern 'refs' request: \" + error);\n                var response = {\n                    type: MessageIds.TERN_REFS,\n                    error: error.message\n                };\n                self.postMessage(response);\n                return;\n            }\n            var response = {\n                type: MessageIds.TERN_REFS,\n                file: fileInfo.name,\n                offset: offset,\n                references: data\n            };\n            // Post a message back to the main thread with the results\n            self.postMessage(response);\n        });\n    } catch (e) {\n        _reportError(e, fileInfo.name);\n    }\n}\n\n/**\n * Get scope at the offset in the file\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {{line: number, ch: number}} offset - the offset into the\n * file for cursor\n */\nfunction getScopeData(fileInfo, offset) {\n    // Create a new tern Server\n    // Existing tern server resolves all the required modules which might take time\n    // We only need to analyze single file for getting the scope\n    ternOptions.plugins = {};\n    var ternServer = new Tern.Server(ternOptions);\n    ternServer.addFile(fileInfo.name, fileInfo.text);\n\n    var error;\n    var request = buildRequest(fileInfo, \"completions\", offset); // for primepump\n\n    try {\n        // primepump\n        ternServer.request(request, function (ternError, data) {\n            if (ternError) {\n                _log(\"Error for Tern request: \\n\" + JSON.stringify(request) + \"\\n\" + ternError);\n                error = ternError.toString();\n            } else {\n                var file = ternServer.findFile(fileInfo.name);\n                var scope = Infer.scopeAt(file.ast, Tern.resolvePos(file, offset), file.scope);\n\n                if (scope) {\n                    // Remove unwanted properties to remove cycles in the object\n                    scope = JSON.parse(JSON.stringify(scope, function(key, value) {\n                        if ([\"proto\", \"propertyOf\", \"onNewProp\", \"sourceFile\", \"maybeProps\"].includes(key)) {\n                            return undefined;\n                        }\n                        else if (key === \"fnType\") {\n                             return value.name || \"FunctionExpression\";\n                        }\n                        else if (key === \"props\") {\n                            for (var key in value) {\n                                value[key] = value[key].propertyName;\n                            }\n                            return value;\n                        } else if (key === \"originNode\") {\n                            return value && {\n                                start: value.start,\n                                end: value.end,\n                                type: value.type,\n                                body: {\n                                    start: value.body.start,\n                                    end: value.body.end\n                                }\n                            };\n                        }\n\n                        return value;\n                    }));\n                }\n\n                self.postMessage({\n                    type: MessageIds.TERN_SCOPEDATA_MSG,\n                    file: _getNormalizedFilename(fileInfo.name),\n                    offset: offset,\n                    scope: scope\n                });\n            }\n        });\n    } catch (e) {\n        _reportError(e, fileInfo.name);\n    } finally {\n        ternServer.reset();\n        Infer.resetGuessing();\n    }\n}\n\n\n/**\n * Get definition location\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {{line: number, ch: number}} offset - the offset into the\n * file for cursor\n */\nfunction getJumptoDef(fileInfo, offset) {\n    var request = buildRequest(fileInfo, \"definition\", offset);\n    // request.query.typeOnly = true;       // FIXME: tern doesn't work exactly right yet.\n\n    try {\n        ternServer.request(request, function (error, data) {\n            if (error) {\n                _log(\"Error returned from Tern 'definition' request: \" + error);\n                self.postMessage({type: MessageIds.TERN_JUMPTODEF_MSG, file: fileInfo.name, offset: offset});\n                return;\n            }\n            var response = {\n                type: MessageIds.TERN_JUMPTODEF_MSG,\n                file: _getNormalizedFilename(fileInfo.name),\n                resultFile: data.file,\n                offset: offset,\n                start: data.start,\n                end: data.end\n            };\n\n            request = buildRequest(fileInfo, \"type\", offset);\n            // See if we can tell if the reference is to a Function type\n            ternServer.request(request, function (error, data) {\n                if (!error) {\n                    response.isFunction = data.type.length > 2 && data.type.substring(0, 2) === \"fn\";\n                }\n\n                // Post a message back to the main thread with the definition\n                self.postMessage(response);\n            });\n\n        });\n    } catch (e) {\n        _reportError(e, fileInfo.name);\n    }\n}\n\n/**\n * Get all the known properties for guessing.\n *\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {{line: number, ch: number}} offset -\n * the offset into the file where we want completions for\n * @param {string} type     - the type of the message to reply with.\n */\nfunction getTernProperties(fileInfo, offset, type) {\n\n    var request = buildRequest(fileInfo, \"properties\", offset),\n        i;\n    //_log(\"tern properties: request \" + request.type + dir + \" \" + file);\n    try {\n        ternServer.request(request, function (error, data) {\n            var properties = [];\n            if (error) {\n                _log(\"Error returned from Tern 'properties' request: \" + error);\n            } else {\n                //_log(\"tern properties: completions = \" + data.completions.length);\n                properties = data.completions.map(function (completion) {\n                    return {value: completion, type: completion.type, guess: true};\n                });\n            }\n            // Post a message back to the main thread with the completions\n            self.postMessage({type: type,\n                              file: _getNormalizedFilename(fileInfo.name),\n                              offset: offset,\n                              properties: properties\n                });\n        });\n    } catch (e) {\n        _reportError(e, fileInfo.name);\n    }\n}\n\n/**\n * Get the completions for the given offset\n *\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {{line: number, ch: number}} offset -\n * the offset into the file where we want completions for\n * @param {boolean} isProperty - true if getting a property hint,\n * otherwise getting an identifier hint.\n */\nfunction getTernHints(fileInfo, offset, isProperty) {\n    var request = buildRequest(fileInfo, \"completions\", offset),\n        i;\n    //_log(\"request \" + dir + \" \" + file + \" \" + offset /*+ \" \" + text */);\n    try {\n        ternServer.request(request, function (error, data) {\n            var completions = [];\n            if (error) {\n                _log(\"Error returned from Tern 'completions' request: \" + error);\n            } else {\n                //_log(\"found \" + data.completions + \" for \" + file + \"@\" + offset);\n                completions = data.completions.map(function (completion) {\n                    return {value: completion.name, type: completion.type, depth: completion.depth,\n                        guess: completion.guess, origin: completion.origin, doc: completion.doc, url: completion.url};\n                });\n            }\n\n            if (completions.length > 0 || !isProperty) {\n                // Post a message back to the main thread with the completions\n                self.postMessage({type: MessageIds.TERN_COMPLETIONS_MSG,\n                    file: _getNormalizedFilename(fileInfo.name),\n                    offset: offset,\n                    completions: completions\n                    });\n            } else {\n                // if there are no completions, then get all the properties\n                getTernProperties(fileInfo, offset, MessageIds.TERN_COMPLETIONS_MSG);\n            }\n        });\n    } catch (e) {\n        _reportError(e, fileInfo.name);\n    }\n}\n\n/**\n *  Given a Tern type object, convert it to an array of Objects, where each object describes\n *  a parameter.\n *\n * @param {!Infer.Fn} inferFnType - type to convert.\n * @return {Array<{name: string, type: string, isOptional: boolean}>} where each entry in the array is a parameter.\n */\nfunction getParameters(inferFnType) {\n\n    // work around define functions before use warning.\n    var recordTypeToString, inferTypeToString, processInferFnTypeParameters, inferFnTypeToString;\n\n    /**\n     *  Convert an infer array type to a string.\n     *\n     *  Formatted using google closure style. For example:\n     *\n     *  \"Array.<string, number>\"\n     *\n     * @param {Infer.Arr} inferArrType\n     *\n     * @return {string} - array formatted in google closure style.\n     *\n     */\n    function inferArrTypeToString(inferArrType) {\n        var result = \"Array.<\";\n\n        result += inferArrType.props[\"<i>\"].types.map(inferTypeToString).join(\", \");\n\n        // workaround case where types is zero length\n        if (inferArrType.props[\"<i>\"].types.length === 0) {\n            result += \"Object\";\n        }\n        result += \">\";\n\n        return result;\n    }\n\n    /**\n     * Convert properties to a record type annotation.\n     *\n     * @param {Object} props\n     * @return {string} - record type annotation\n     */\n    recordTypeToString = function (props) {\n        var result = \"{\",\n            first = true,\n            prop;\n\n        result += Object.keys(props).map(function (key) {\n            return key + \": \" + inferTypeToString(props[key]);\n        }).join(\", \");\n\n        result += \"}\";\n\n        return result;\n    };\n\n    /**\n     *  Convert an infer type to a string.\n     *\n     * @param {*} inferType - one of the Infer's types; Infer.Prim, Infer.Arr, Infer.ANull. Infer.Fn functions are\n     * not handled here.\n     *\n     * @return {string}\n     *\n     */\n    inferTypeToString = function (inferType) {\n        var result;\n\n        if (inferType instanceof Infer.AVal) {\n            inferType = inferType.types[0];\n        }\n\n        if (inferType instanceof Infer.Prim) {\n            result = inferType.toString();\n            if (result === \"string\") {\n                result = \"String\";\n            } else if (result === \"number\") {\n                result = \"Number\";\n            } else if (result === \"boolean\") {\n                result = \"Boolean\";\n            }\n        } else if (inferType instanceof Infer.Arr) {\n            result = inferArrTypeToString(inferType);\n        } else if (inferType instanceof Infer.Fn) {\n            result = inferFnTypeToString(inferType);\n        } else if (inferType instanceof Infer.Obj) {\n            if (inferType.name === undefined) {\n                result = recordTypeToString(inferType.props);\n            } else {\n                result = inferType.name;\n            }\n        } else {\n            result = \"Object\";\n        }\n\n        return result;\n    };\n\n    /**\n     * Format the given parameter array. Handles separators between\n     * parameters, syntax for optional parameters, and the order of the\n     * parameter type and parameter name.\n     *\n     * @param {!Array.<{name: string, type: string, isOptional: boolean}>} params -\n     * array of parameter descriptors\n     * @param {function(string)=} appendSeparators - callback function to append separators.\n     * The separator is passed to the callback.\n     * @param {function(string, number)=} appendParameter - callback function to append parameter.\n     * The formatted parameter type and name is passed to the callback along with the\n     * current index of the parameter.\n     * @param {boolean=} typesOnly - only show parameter types. The\n     * default behavior is to include both parameter names and types.\n     * @return {string} - formatted parameter hint\n     */\n    function formatParameterHint(params, appendSeparators, appendParameter, typesOnly) {\n        var result = \"\",\n            pendingOptional = false;\n\n        params.forEach(function (value, i) {\n            var param = value.type,\n                separators = \"\";\n\n            if (value.isOptional) {\n                // if an optional param is following by an optional parameter, then\n                // terminate the bracket. Otherwise enclose a required parameter\n                // in the same bracket.\n                if (pendingOptional) {\n                    separators += \"]\";\n                }\n\n                pendingOptional = true;\n            }\n\n            if (i > 0) {\n                separators += \", \";\n            }\n\n            if (value.isOptional) {\n                separators += \"[\";\n            }\n\n            if (appendSeparators) {\n                appendSeparators(separators);\n            }\n\n            result += separators;\n\n            if (!typesOnly) {\n                param += \" \" + value.name;\n            }\n\n            if (appendParameter) {\n                appendParameter(param, i);\n            }\n\n            result += param;\n\n        });\n\n        if (pendingOptional) {\n            if (appendSeparators) {\n                appendSeparators(\"]\");\n            }\n\n            result += \"]\";\n        }\n\n        return result;\n    }\n\n    /**\n     * Convert an infer function type to a Google closure type string.\n     *\n     * @param {Infer.Fn} inferType - type to convert.\n     * @return {string} - function type as a string.\n     */\n    inferFnTypeToString = function (inferType) {\n        var result = \"function(\",\n            params = processInferFnTypeParameters(inferType);\n\n        result += /*HintUtils2.*/formatParameterHint(params, null, null, true);\n        if (inferType.retval) {\n            result += \"):\";\n            result += inferTypeToString(inferType.retval);\n        }\n\n        return result;\n    };\n\n    /**\n     * Convert an infer function type to string.\n     *\n     * @param {*} inferType - one of the Infer's types; Infer.Fn, Infer.Prim, Infer.Arr, Infer.ANull\n     * @return {Array<{name: string, type: string, isOptional: boolean}>} where each entry in the array is a parameter.\n     */\n    processInferFnTypeParameters = function (inferType) {\n        var params = [],\n            i;\n\n        for (i = 0; i < inferType.args.length; i++) {\n            var param = {},\n                name = inferType.argNames[i],\n                type = inferType.args[i];\n\n            if (!name) {\n                name = \"param\" + (i + 1);\n            }\n\n            if (name[name.length - 1] === \"?\") {\n                name = name.substring(0, name.length - 1);\n                param.isOptional = true;\n            }\n\n            param.name = name;\n            param.type = inferTypeToString(type);\n            params.push(param);\n        }\n\n        return params;\n    };\n\n    return processInferFnTypeParameters(inferFnType);\n}\n\n/**\n * Get the function type for the given offset\n *\n * @param {{type: string, name: string, offsetLines: number, text: string}} fileInfo\n * - type of update, name of file, and the text of the update.\n * For \"full\" updates, the whole text of the file is present. For \"part\" updates,\n * the changed portion of the text. For \"empty\" updates, the file has not been modified\n * and the text is empty.\n * @param {{line: number, ch: number}} offset -\n * the offset into the file where we want completions for\n */\nfunction handleFunctionType(fileInfo, offset) {\n    var request = buildRequest(fileInfo, \"type\", offset),\n        error;\n\n    request.query.preferFunction = true;\n\n    var fnType = \"\";\n    try {\n        ternServer.request(request, function (ternError, data) {\n\n            if (ternError) {\n                _log(\"Error for Tern request: \\n\" + JSON.stringify(request) + \"\\n\" + ternError);\n                error = ternError.toString();\n            } else {\n                var file = ternServer.findFile(fileInfo.name);\n\n                // convert query from partial to full offsets\n                var newOffset = offset;\n                if (fileInfo.type === MessageIds.TERN_FILE_INFO_TYPE_PART) {\n                    newOffset = {line: offset.line + fileInfo.offsetLines, ch: offset.ch};\n                }\n\n                request = buildRequest(createEmptyUpdate(fileInfo.name), \"type\", newOffset);\n\n                var expr = Tern.findQueryExpr(file, request.query);\n                Infer.resetGuessing();\n                var type = Infer.expressionType(expr);\n                type = type.getFunctionType() || type.getType();\n\n                if (type) {\n                    fnType = getParameters(type);\n                } else {\n                    ternError = \"No parameter type found\";\n                    _log(ternError);\n                }\n            }\n        });\n    } catch (e) {\n        _reportError(e, fileInfo.name);\n    }\n\n    // Post a message back to the main thread with the completions\n    self.postMessage({type: MessageIds.TERN_CALLED_FUNC_TYPE_MSG,\n        file: _getNormalizedFilename(fileInfo.name),\n        offset: offset,\n        fnType: fnType,\n        error: error\n        });\n}\n\n/**\n *  Add an array of files to tern.\n *\n * @param {Array.<string>} files - each string in the array is the full\n * path of a file.\n */\nfunction handleAddFiles(files) {\n    files.forEach(function (file) {\n        ternServer.addFile(file);\n    });\n}\n\n/**\n *  Update the context of a file in tern.\n *\n * @param {string} path - full path of file.\n * @param {string} text - content of the file.\n */\nfunction handleUpdateFile(path, text) {\n\n    ternServer.addFile(path, text);\n\n    self.postMessage({type: MessageIds.TERN_UPDATE_FILE_MSG,\n        path: path\n        });\n\n    // reset to get the best hints with the updated file.\n    ternServer.reset();\n    Infer.resetGuessing();\n}\n\n/**\n *  Make a completions request to tern to force tern to resolve files\n *  and create a fast first lookup for the user.\n * @param {string} path     - the path of the file\n */\nfunction handlePrimePump(path) {\n    var fileName = _getDenormalizedFilename(path);\n    var fileInfo = createEmptyUpdate(fileName),\n        request = buildRequest(fileInfo, \"completions\", {line: 0, ch: 0});\n\n    try {\n        ternServer.request(request, function (error, data) {\n            // Post a message back to the main thread\n            self.postMessage({type: MessageIds.TERN_PRIME_PUMP_MSG,\n                path: _getNormalizedFilename(path)\n                });\n        });\n    } catch (e) {\n        _reportError(e, path);\n    }\n}\n\n/**\n * Updates the configuration, typically for debugging purposes.\n *\n * @param {Object} configUpdate new configuration\n */\nfunction setConfig(configUpdate) {\n    config = configUpdate;\n}\n\nfunction _requestTernServer(commandConfig) {\n    var file, text, offset,\n        request = commandConfig,\n        type = request.type;\n    if (config.debug) {\n        _log(\"Message received \" + type);\n    }\n\n    if (type === MessageIds.TERN_INIT_MSG) {\n        var env     = request.env,\n            files   = request.files;\n        inferenceTimeout = request.timeout;\n        initTernServer(env, files);\n    } else if (type === MessageIds.TERN_COMPLETIONS_MSG) {\n        offset  = request.offset;\n        getTernHints(request.fileInfo, offset, request.isProperty);\n    } else if (type === MessageIds.TERN_GET_FILE_MSG) {\n        file = request.file;\n        text = request.text;\n        handleGetFile(file, text);\n    } else if (type === MessageIds.TERN_CALLED_FUNC_TYPE_MSG) {\n        offset  = request.offset;\n        handleFunctionType(request.fileInfo, offset);\n    } else if (type === MessageIds.TERN_JUMPTODEF_MSG) {\n        offset  = request.offset;\n        getJumptoDef(request.fileInfo, offset);\n    } else if (type === MessageIds.TERN_SCOPEDATA_MSG) {\n        offset  = request.offset;\n        getScopeData(request.fileInfo, offset);\n    } else if (type === MessageIds.TERN_REFS) {\n        offset  = request.offset;\n        getRefs(request.fileInfo, offset);\n    } else if (type === MessageIds.TERN_ADD_FILES_MSG) {\n        handleAddFiles(request.files);\n    } else if (type === MessageIds.TERN_PRIME_PUMP_MSG) {\n        isUntitledDoc = request.isUntitledDoc;\n        handlePrimePump(request.path);\n    } else if (type === MessageIds.TERN_GET_GUESSES_MSG) {\n        offset  = request.offset;\n        getTernProperties(request.fileInfo, offset, MessageIds.TERN_GET_GUESSES_MSG);\n    } else if (type === MessageIds.TERN_UPDATE_FILE_MSG) {\n        handleUpdateFile(request.path, request.text);\n    } else if (type === MessageIds.SET_CONFIG) {\n        setConfig(request.config);\n    } else if (type === MessageIds.TERN_UPDATE_DIRTY_FILE) {\n        ExtractContent.updateFilesCache(request.name, request.action);\n    } else if (type === MessageIds.TERN_CLEAR_DIRTY_FILES_LIST) {\n        ExtractContent.clearFilesCache();\n    } else {\n        _log(\"Unknown message: \" + JSON.stringify(request));\n    }\n}\n\nfunction invokeTernCommand(commandConfig) {\n    try {\n        _requestTernServer(commandConfig);\n    } catch (error) {\n        console.warn(error);\n    }\n}\n\nfunction setInterface(msgInterface) {\n    MessageIds = msgInterface.messageIds;\n}\n\nfunction checkInterfaceAndReInit() {\n    if (!MessageIds) {\n        // WTF - Worse than failure\n        // We are here as node process got restarted \n        // Request for ReInitialization of interface and Tern Server\n        self.postMessage({\n            type: \"RE_INIT_TERN\"\n        });\n    }\n}\n\n /**\n * Initialize the test domain with commands and events related to find in files.\n * @param {DomainManager} domainManager The DomainManager for the TernNodeDomain\n */\nfunction init(domainManager) {\n    if (!domainManager.hasDomain(\"TernNodeDomain\")) {\n        domainManager.registerDomain(\"TernNodeDomain\", {major: 0, minor: 1});\n    }\n\n    _domainManager = domainManager;\n\n    domainManager.registerCommand(\n        \"TernNodeDomain\",       // domain name\n        \"invokeTernCommand\",    // command name\n        invokeTernCommand,   // command handler function\n        false,          // this command is synchronous in Node\n        \"Invokes a tern command on node\",\n        [{name: \"commandConfig\", // parameters\n            type: \"object\",\n            description: \"Object containing tern command configuration\"}]\n    );\n\n    domainManager.registerCommand(\n        \"TernNodeDomain\",       // domain name\n        \"setInterface\",    // command name\n        setInterface,   // command handler function\n        false,          // this command is synchronous in Node\n        \"Sets the shared message interface\",\n        [{name: \"msgInterface\", // parameters\n            type: \"object\",\n            description: \"Object containing messageId enums\"}]\n    );\n\n    domainManager.registerCommand(\n        \"TernNodeDomain\",       // domain name\n        \"resetTernServer\",    // command name\n        resetTernServer,   // command handler function\n        true,          // this command is synchronous in Node\n        \"Resets an existing tern server\"\n    );\n\n    domainManager.registerEvent(\n        \"TernNodeDomain\",     // domain name\n        \"data\",   // event name\n        [\n            {\n                name: \"data\",\n                type: \"Object\",\n                description: \"data to be returned to main thread\"\n            }\n        ]\n    );\n    setTimeout(checkInterfaceAndReInit, 1000);\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/JSUtils/node/package.json",
    "content": "{\n  \"name\": \"brackets-javascript-code-hints\",\n  \"dependencies\": {\n    \"acorn\": \"5.1.1\",\n    \"tern\": \"0.21.0\"\n  }\n}\n"
  },
  {
    "path": "src/JSUtils/package.json",
    "content": "{\n  \"name\": \"brackets-javascript-code-utils\",\n  \"dependencies\": {\n    \"acorn\": \"3.3.0\"\n  }\n}\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/CSSAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint forin: true */\n\n/**\n * CSSAgent keeps track of loaded style sheets and allows reloading them\n * from a {Document}.\n *\n * CSSAgent dispatches styleSheetAdded and styleSheetRemoved events, passing\n * the URL for the added/removed style sheet.\n */\ndefine(function CSSAgent(require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var Inspector       = require(\"LiveDevelopment/Inspector/Inspector\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        PathUtils       = require(\"thirdparty/path-utils/path-utils\");\n\n    /**\n     * Stylesheet details\n     * @type {Object.<string, CSS.CSSStyleSheetHeader>}\n     */\n    var _styleSheetDetails = {};\n\n    /**\n     * Is getAllStyleSheets() API defined? - This is undefined until we test for API\n     * @type {boolean}\n     */\n    var _getAllStyleSheetsNotFound;\n\n    /**\n     * Create a canonicalized version of the given URL, stripping off query strings and hashes.\n     * @param {string} url the URL to canonicalize\n     * @return the canonicalized URL\n     */\n    function _canonicalize(url) {\n        return PathUtils.parseUrl(url).hrefNoSearch;\n    }\n\n    /**\n     * @private\n     * WebInspector Event: Page.frameNavigated\n     * @param {jQuery.Event} event\n     * @param {frame: Frame} res\n     */\n    function _onFrameNavigated(event, res) {\n        // Clear maps when navigating to a new page, but not if an iframe was loaded\n        if (!res.frame.parentId) {\n            _styleSheetDetails = {};\n        }\n    }\n\n    /**\n     * Get the style sheets for a url\n     * @param {string} url\n     * @return {Object.<string, CSSStyleSheetHeader>}\n     */\n    function styleForURL(url) {\n        var styleSheetId, styles = {};\n        url = _canonicalize(url);\n        for (styleSheetId in _styleSheetDetails) {\n            if (_styleSheetDetails[styleSheetId].canonicalizedURL === url) {\n                styles[styleSheetId] = _styleSheetDetails[styleSheetId];\n            }\n        }\n        return styles;\n    }\n\n    /**\n     * Reload a CSS style sheet from a document\n     * @param {Document} document\n     * @param {string=} newContent new content of every stylesheet. Defaults to doc.getText() if omitted\n     * @return {jQuery.Promise}\n     */\n    function reloadCSSForDocument(doc, newContent) {\n        var styles = styleForURL(doc.url),\n            styleSheetId,\n            deferreds = [];\n\n        if (newContent === undefined) {\n            newContent = doc.getText();\n        }\n        for (styleSheetId in styles) {\n            deferreds.push(Inspector.CSS.setStyleSheetText(styles[styleSheetId].styleSheetId, newContent));\n        }\n        if (!deferreds.length) {\n            console.error(\"Style Sheet for document not loaded: \" + doc.url);\n            return new $.Deferred().reject().promise();\n        }\n        // return master deferred\n        return $.when.apply($, deferreds);\n    }\n\n    /**\n     * Empties a CSS style sheet given a document that has been deleted\n     * @param {Document} document\n     * @return {jQuery.Promise}\n     */\n    function clearCSSForDocument(doc) {\n        return reloadCSSForDocument(doc, \"\");\n    }\n\n    /**\n     * @private\n     * @param {jQuery.Event} event\n     * @param {header: CSSStyleSheetHeader}\n     */\n    function _styleSheetAdded(event, res) {\n        var url             = _canonicalize(res.header.sourceURL),\n            existing        = styleForURL(res.header.sourceURL),\n            styleSheetId    = res.header.styleSheetId,\n            duplicate;\n\n        // detect duplicates\n        duplicate = _.some(existing, function (styleSheet) {\n            return styleSheet && styleSheet.styleSheetId === styleSheetId;\n        });\n        if (duplicate) {\n            return;\n        }\n\n        _styleSheetDetails[styleSheetId] = res.header;\n        _styleSheetDetails[styleSheetId].canonicalizedURL = url; // canonicalized URL\n\n        exports.trigger(\"styleSheetAdded\", url, res.header);\n    }\n\n    /**\n     * @private\n     * @param {jQuery.Event} event\n     * @param {styleSheetId: StyleSheetId}\n     */\n    function _styleSheetRemoved(event, res) {\n        var header = _styleSheetDetails[res.styleSheetId];\n\n        delete _styleSheetDetails[res.styleSheetId];\n\n        exports.trigger(\"styleSheetRemoved\", header.canonicalizedURL, header);\n    }\n\n    /**\n     * @private\n     * Attempt to use deleted API CSS.getAllStyleSheets\n     * @param {jQuery.Event} event\n     * @param {frameId: Network.FrameId}\n     */\n    function _onFrameStoppedLoading(event, res) {\n        var regexChromeUA,\n            userAgent,\n            uaMatch;\n\n        // Check for undefined so user agent string is only parsed once\n        if (_getAllStyleSheetsNotFound === undefined) {\n            regexChromeUA = /Chrome\\/(\\d+)\\./;  // Example: \"... Chrome/34.0.1847.131 ...\"\n            userAgent     = Inspector.getUserAgent();\n            uaMatch       = userAgent.match(regexChromeUA);\n\n            // If we have user agent string, and Chrome is >= 34, then don't use getAllStyleSheets\n            if (uaMatch && parseInt(uaMatch[1], 10) >= 34) {\n                _getAllStyleSheetsNotFound = true;\n                Inspector.Page.off(\"frameStoppedLoading.CSSAgent\", _onFrameStoppedLoading);\n                return;\n            }\n        }\n\n        // Manually fire getAllStyleSheets since it will be removed from\n        // Inspector.json in a future update\n        Inspector.send(\"CSS\", \"getAllStyleSheets\").done(function (res) {\n            res.headers.forEach(function (header) {\n                // _styleSheetAdded will ignore duplicates\n                _getAllStyleSheetsNotFound = false;\n                _styleSheetAdded(null, { header: header });\n            });\n        }).fail(function (err) {\n            // Disable getAllStyleSheets if the first call fails\n            _getAllStyleSheetsNotFound = (err.code === -32601);\n            Inspector.Page.off(\"frameStoppedLoading.CSSAgent\", _onFrameStoppedLoading);\n        });\n    }\n\n    /** Enable the domain */\n    function enable() {\n        return Inspector.CSS.enable();\n    }\n\n    /** Initialize the agent */\n    function load() {\n        Inspector.Page.on(\"frameNavigated.CSSAgent\", _onFrameNavigated);\n        Inspector.CSS.on(\"styleSheetAdded.CSSAgent\", _styleSheetAdded);\n        Inspector.CSS.on(\"styleSheetRemoved.CSSAgent\", _styleSheetRemoved);\n\n        // getAllStyleSheets was deleted beginning with Chrome 34\n        if (!_getAllStyleSheetsNotFound) {\n            Inspector.Page.on(\"frameStoppedLoading.CSSAgent\", _onFrameStoppedLoading);\n        }\n    }\n\n    /** Clean up */\n    function unload() {\n        Inspector.Page.off(\".CSSAgent\");\n        Inspector.CSS.off(\".CSSAgent\");\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Export public functions\n    exports.enable = enable;\n    exports.styleForURL = styleForURL;\n    exports.reloadCSSForDocument = reloadCSSForDocument;\n    exports.clearCSSForDocument = clearCSSForDocument;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/ConsoleAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * ConsoleAgent forwards all console message from the remote console to the\n * local console.\n */\ndefine(function ConsoleAgent(require, exports, module) {\n    \"use strict\";\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _lastMessage; // {Console.ConsoleMessage} the last received message\n\n    /** Log a remote message to the local console\n     * @param {Console.ConsoleMessage} message\n     */\n    function _log(message) {\n        var level = message.level;\n        if (level === \"warning\") {\n            level = \"warn\";\n        }\n        var text = \"ConsoleAgent: \" + message.text;\n        if (message.url) {\n            text += \" (url: \" + message.url + \")\";\n        }\n        if (message.stackTrace) {\n            var callFrame = message.stackTrace[0];\n            text += \" in \" + callFrame.functionName + \":\" + callFrame.columnNumber;\n        }\n        console[level](text);\n    }\n\n    // WebInspector Event: Console.messageAdded\n    function _onMessageAdded(event, res) {\n        // res = {message}\n        _lastMessage = res.message;\n        _log(_lastMessage);\n    }\n\n    // WebInspector Event: Console.messageRepeatCountUpdated\n    function _onMessageRepeatCountUpdated(event, res) {\n        // res = {count}\n        if (_lastMessage) {\n            _log(_lastMessage);\n        }\n    }\n\n    // WebInspector Event: Console.messagesCleared\n    function _onMessagesCleared(event, res) {\n        // res = {}\n    }\n\n    /**\n     * Enable the inspector Console domain\n     * @return {jQuery.Promise} A promise resolved when the Console.enable() command is successful.\n     */\n    function enable() {\n        return Inspector.Console.enable();\n    }\n\n    /** Initialize the agent */\n    function load() {\n        Inspector.Console\n            .on(\"messageAdded.ConsoleAgent\", _onMessageAdded)\n            .on(\"messageRepeatCountUpdated.ConsoleAgent\", _onMessageRepeatCountUpdated)\n            .on(\"messagesCleared.ConsoleAgent\", _onMessagesCleared);\n    }\n\n    /** Clean up */\n    function unload() {\n        Inspector.Console.off(\".ConsoleAgent\");\n    }\n\n    // Export public functions\n    exports.enable = enable;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/DOMAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * DOMAgent constructs and maintains a tree of {DOMNode}s that represents the\n * rendered DOM tree in the remote browser. Nodes can be accessed by id or\n * location (source offset). To update the DOM tree in response to a change of\n * the source document (replace [from,to] with text) call\n * `applyChange(from, to, text)`.\n *\n * The DOMAgent triggers `getDocument` once it has loaded\n * the document.\n */\ndefine(function DOMAgent(require, exports, module) {\n    \"use strict\";\n\n    var Inspector       = require(\"LiveDevelopment/Inspector/Inspector\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        EditAgent       = require(\"LiveDevelopment/Agents/EditAgent\"),\n        DOMNode         = require(\"LiveDevelopment/Agents/DOMNode\"),\n        DOMHelpers      = require(\"LiveDevelopment/Agents/DOMHelpers\");\n\n    var _load; // {$.Deferred} load promise\n    var _idToNode; // {nodeId -> node}\n    var _pendingRequests; // {integer} number of pending requests before initial loading is complete\n\n    /** Get the last node before the given location\n     * @param {integer} location\n     */\n    function nodeBeforeLocation(location) {\n        var node;\n        exports.root.each(function each(n) {\n            if (!n.location || location < n.location) {\n                return true;\n            }\n            if (!node || node.location < n.location) {\n                node = n;\n            }\n        });\n        return node;\n    }\n\n    /** Get the element node that encloses the given location\n     * @param {location}\n     */\n    function allNodesAtLocation(location) {\n        var nodes = [];\n        exports.root.each(function each(n) {\n            if (n.type === DOMNode.TYPE_ELEMENT && n.isAtLocation(location)) {\n                nodes.push(n);\n            }\n        });\n        return nodes;\n    }\n\n    /** Get the node at the given location\n     * @param {location}\n     */\n    function nodeAtLocation(location) {\n        return exports.root.find(function each(n) {\n            return n.isAtLocation(location, false);\n        });\n    }\n\n    /** Find the node for the given id\n     * @param {DOMNode} node\n     */\n    function nodeWithId(nodeId) {\n        return _idToNode[nodeId];\n    }\n\n    /** Update the node index\n     * @param {DOMNode} node\n     */\n    function removeNode(node) {\n        if (node.nodeId) {\n            delete _idToNode[node.nodeId];\n        }\n    }\n\n    /** Update the node index\n     * @param {DOMNode} node\n     */\n    function addNode(node) {\n        if (node.nodeId) {\n            _idToNode[node.nodeId] = node;\n        }\n    }\n\n    /** Request the child nodes for a node\n     * @param {DOMNode} node\n     */\n    function requestChildNodes(node) {\n        if (_pendingRequests >= 0) {\n            _pendingRequests++;\n        }\n        Inspector.DOM.requestChildNodes(node.nodeId);\n    }\n\n    /** Eliminate the query string from a URL\n     * @param {string} URL\n     */\n    function _cleanURL(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Map the DOM document to the source text\n     * @param {string} source\n     */\n    function _mapDocumentToSource(source) {\n        var node = exports.root;\n        DOMHelpers.eachNode(source, function each(payload) {\n            if (!node) {\n                return true;\n            }\n            if (payload.closing) {\n                var parent = node.findParentForNextNodeMatchingPayload(payload);\n                if (!parent) {\n                    return console.warn(\"Matching Parent not at \" + payload.sourceOffset + \" (\" + payload.nodeName + \")\");\n                }\n                parent.closeLocation = payload.sourceOffset;\n                parent.closeLength = payload.sourceLength;\n            } else {\n                var next = node.findNextNodeMatchingPayload(payload);\n                if (!next) {\n                    return console.warn(\"Skipping Source Node at \" + payload.sourceOffset);\n                }\n                node = next;\n                node.location = payload.sourceOffset;\n                node.length = payload.sourceLength;\n                if (payload.closed) {\n                    node.closed = payload.closed;\n                }\n            }\n        });\n    }\n\n    /** Load the source document and match it with the DOM tree*/\n    function _onFinishedLoadingDOM() {\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", exports.url);\n        request.onload = function onLoad() {\n            if ((request.status >= 200 && request.status < 300) ||\n                    request.status === 304 || request.status === 0) {\n                _mapDocumentToSource(request.response);\n                _load.resolve();\n            } else {\n                var msg = \"Received status \" + request.status + \" from XMLHttpRequest while attempting to load source file at \" + exports.url;\n                _load.reject(msg, { message: msg });\n            }\n        };\n        request.onerror = function onError() {\n            var msg = \"Could not load source file at \" + exports.url;\n            _load.reject(msg, { message: msg });\n        };\n        request.send(null);\n    }\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        Inspector.DOM.getDocument(function onGetDocument(res) {\n            exports.trigger(\"getDocument\", res);\n            // res = {root}\n            _idToNode = {};\n            _pendingRequests = 0;\n            exports.root = new DOMNode(exports, res.root);\n        });\n    }\n\n    // WebInspector Event: Page.frameNavigated\n    function _onFrameNavigated(event, res) {\n        // res = {frame}\n        if (!res.frame.parentId) {\n            exports.url = _cleanURL(res.frame.url);\n        }\n    }\n\n     // WebInspector Event: DOM.documentUpdated\n    function _onDocumentUpdated(event, res) {\n        // res = {}\n    }\n\n    // WebInspector Event: DOM.setChildNodes\n    function _onSetChildNodes(event, res) {\n        // res = {parentId, nodes}\n        var node = nodeWithId(res.parentId);\n        node.setChildrenPayload(res.nodes);\n        if (_pendingRequests > 0 && --_pendingRequests === 0) {\n            _onFinishedLoadingDOM();\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeCountUpdated\n    function _onChildNodeCountUpdated(event, res) {\n        // res = {nodeId, childNodeCount}\n        if (res.nodeId > 0) {\n            Inspector.DOM.requestChildNodes(res.nodeId);\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeInserted\n    function _onChildNodeInserted(event, res) {\n        // res = {parentNodeId, previousNodeId, node}\n        if (res.node.nodeId > 0) {\n            var parent = nodeWithId(res.parentNodeId);\n            var previousNode = nodeWithId(res.previousNodeId);\n            var node = new DOMNode(exports, res.node);\n            parent.insertChildAfter(node, previousNode);\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeRemoved\n    function _onChildNodeRemoved(event, res) {\n        // res = {parentNodeId, nodeId}\n        if (res.nodeId > 0) {\n            var node = nodeWithId(res.nodeId);\n            node.remove();\n        }\n    }\n\n    /** Apply a change\n     * @param {integer} start offset of the change\n     * @param {integer} end offset of the change\n     * @param {string} change text\n     */\n    function applyChange(from, to, text) {\n        var delta = from - to + text.length;\n        var node = nodeAtLocation(from);\n\n        // insert a text node\n        if (!node) {\n            if (!(/^\\s*$/).test(text)) {\n                console.warn(\"Inserting nodes not supported.\");\n                node = nodeBeforeLocation(from);\n            }\n        } else if (node.type === 3) {\n            // update a text node\n            var value = node.value.substr(0, from - node.location);\n            value += text;\n            value += node.value.substr(to - node.location);\n            node.value = value;\n            if (!EditAgent.isEditing) {\n                // only update the DOM if the change was not caused by the edit agent\n                Inspector.DOM.setNodeValue(node.nodeId, node.value);\n            }\n        } else {\n            console.warn(\"Changing non-text nodes not supported.\");\n        }\n\n        // adjust the location of all nodes after the change\n        if (node) {\n            node.length += delta;\n            exports.root.each(function each(n) {\n                if (n.location > node.location) {\n                    n.location += delta;\n                }\n                if (n.closeLocation !== undefined && n.closeLocation > node.location) {\n                    n.closeLocation += delta;\n                }\n            });\n        }\n    }\n\n    /** Enable the domain */\n    function enable() {\n        return Inspector.DOM.enable();\n    }\n\n    /** Disable the domain */\n    function disable() {\n        return Inspector.DOM.disable();\n    }\n\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        Inspector.Page\n            .on(\"frameNavigated.DOMAgent\", _onFrameNavigated)\n            .on(\"loadEventFired.DOMAgent\", _onLoadEventFired);\n        Inspector.DOM\n            .on(\"documentUpdated.DOMAgent\", _onDocumentUpdated)\n            .on(\"setChildNodes.DOMAgent\", _onSetChildNodes)\n            .on(\"childNodeCountUpdated.DOMAgent\", _onChildNodeCountUpdated)\n            .on(\"childNodeInserted.DOMAgent\", _onChildNodeInserted)\n            .on(\"childNodeRemoved.DOMAgent\", _onChildNodeRemoved);\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        Inspector.Page.off(\".DOMAgent\");\n        Inspector.DOM.off(\".DOMAgent\");\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Export private functions\n    exports.enable = enable;\n    exports.disable = disable;\n    exports.nodeBeforeLocation = nodeBeforeLocation;\n    exports.allNodesAtLocation = allNodesAtLocation;\n    exports.nodeAtLocation = nodeAtLocation;\n    exports.nodeWithId = nodeWithId;\n    exports.removeNode = removeNode;\n    exports.addNode = addNode;\n    exports.requestChildNodes = requestChildNodes;\n    exports.applyChange = applyChange;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/DOMHelpers.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\n/**\n * DOMHelpers is a collection of functions used by the DOMAgent exports `eachNode(src, callback)`\n */\ndefine(function DOMHelpersModule(require, exports, module) {\n    \"use strict\";\n\n    /** Test if the given character is a quote character\n     * {char} source character\n     * {char} escape (previous) character\n     * {char} quote character\n     */\n    function _isQuote(c, escape, quote) {\n        if (escape === \"\\\\\") {\n            return false;\n        }\n        if (quote !== undefined) {\n            return c === quote;\n        }\n        return c === \"\\\"\" || c === \"'\";\n    }\n\n    /** Remove quotes from the string and adjust escaped quotes\n     * @param {string} source string\n     */\n    function _removeQuotes(src) {\n        if (_isQuote(src[0]) && src[src.length - 1] === src[0]) {\n            var q = src[0];\n            src = src.substr(1, src.length - 2);\n            src = src.replace(\"\\\\\" + q, q);\n        }\n        return src;\n    }\n\n    /** Find the next match using several constraints\n     * @param {string} source string\n     * @param {string} or [{regex}, {length}] the match definition\n     * @param {integer} ignore characters before this offset\n     * @param {boolean} watch for quotes\n     * @param [{string},{string}] watch for comments\n     */\n    function _find(src, match, skip, quotes, comments) {\n        if (typeof match === \"string\") {\n            match = [match, match.length];\n        }\n        if (skip === undefined) {\n            skip = 0;\n        }\n        var i, activeQuote, isComment = false;\n        for (i = skip; i < src.length; i++) {\n            if (quotes && _isQuote(src[i], src[i - 1], activeQuote)) {\n                // starting quote\n                activeQuote = activeQuote ? undefined : src[i];\n            } else if (!activeQuote) {\n                if (comments && !isComment && src.substr(i, comments[0].length) === comments[0]) {\n                    // opening comment\n                    isComment = true;\n                    i += comments[0].length - 1;\n                } else if (isComment) {\n                    // we are commented\n                    if (src.substr(i, comments[1].length) === comments[1]) {\n                        isComment = false;\n                        i += comments[1].length - 1;\n                    }\n                } else if (src.substr(i, match[1]).search(match[0]) === 0) {\n                    // match\n                    return i;\n                }\n            }\n        }\n        return -1;\n    }\n\n    /** Callback iterator using `_find` */\n    function _findEach(src, match, quotes, comments, callback) {\n        var from = 0;\n        var to;\n        while (from < src.length) {\n            to = _find(src, match, from, quotes, comments);\n            if (to < 0) {\n                to = src.length;\n            }\n            callback(src.substr(from, to - from));\n            from = to + 1;\n        }\n    }\n\n    /** Find the next tag\n     * @param {string} source string\n     * @param {integer} ignore characters before this offset\n     */\n    function _findTag(src, skip) {\n        var from, to, inc;\n        from = _find(src, [/<[a-z!\\/]/i, 2], skip);\n        if (from < 0) {\n            return null;\n        }\n        if (src.substr(from, 4) === \"<!--\") {\n            // html comments\n            to = _find(src, \"-->\", from + 4);\n            inc = 3;\n        } else if (src.substr(from, 7).toLowerCase() === \"<script\") {\n            // script tag\n            to = _find(src.toLowerCase(), \"</script>\", from + 7);\n            inc = 9;\n        } else if (src.substr(from, 6).toLowerCase() === \"<style\") {\n            // style tag\n            to = _find(src.toLowerCase(), \"</style>\", from + 6);\n            inc = 8;\n        } else {\n            to = _find(src, \">\", from + 1, true);\n            inc = 1;\n        }\n        if (to < 0) {\n            return null;\n        }\n        return {from: from, length: to + inc - from};\n    }\n\n    /** Extract tag attributes from the given source of a single tag\n     * @param {string} source content\n     */\n    function _extractAttributes(content) {\n\n        // remove the node name and the closing bracket and optional slash\n        content = content.replace(/^<\\S+\\s*/, \"\");\n        content = content.replace(/\\s*\\/?>$/, \"\");\n        if (content.length === 0) {\n            return;\n        }\n\n        // go through the items and identify key value pairs split by =\n        var index, key, value;\n        var attributes = {};\n        _findEach(content, [/\\s/, 1], true, undefined, function each(item) {\n            index = item.search(\"=\");\n            if (index < 0) {\n                return;\n            }\n\n            // get the key\n            key = item.substr(0, index).trim();\n            if (key.length === 0) {\n                return;\n            }\n\n            // get the value\n            value = item.substr(index + 1).trim();\n            value = _removeQuotes(value);\n            attributes[key] = value;\n        });\n\n        return attributes;\n    }\n\n    /** Extract the node payload\n     * @param {string} source content\n     */\n    function extractPayload(content) {\n        var payload = {};\n\n        if (content[0] !== \"<\") {\n            // text\n            payload.nodeType = 3;\n            payload.nodeValue = content;\n        } else if (content.substr(0, 4) === \"<!--\") {\n            // comment\n            payload.nodeType = 8;\n            payload.nodeValue = content.substr(4, content.length - 7);\n        } else if (content[1] === \"!\") {\n            // doctype\n            payload.nodeType = 10;\n        } else {\n            // regular element\n            payload.nodeType = 1;\n            payload.nodeName = /^<([^>\\s]+)/.exec(content)[1].toUpperCase();\n            payload.attributes = _extractAttributes(content);\n\n            // closing node (/ at the beginning)\n            if (payload.nodeName[0] === \"/\") {\n                payload.nodeName = payload.nodeName.substr(1);\n                payload.closing = true;\n            }\n\n            // closed node (/ at the end)\n            if (content[content.length - 2] === \"/\") {\n                payload.closed = true;\n            }\n\n            // Special handling for script/style tag since we've already collected\n            // everything up to the end tag.\n            if (payload.nodeName === \"SCRIPT\" || payload.nodeName === \"STYLE\") {\n                payload.closed = true;\n            }\n        }\n        return payload;\n    }\n\n    /** Split the source string into payloads representing individual nodes\n     * @param {string} source\n     * @param {function(payload)} callback\n     */\n    // split a string into individual node contents\n    function eachNode(src, callback) {\n        var index = 0;\n        var text, range, length, payload;\n        while (index < src.length) {\n\n            // find the next tag\n            range = _findTag(src, index);\n            if (!range) {\n                range = { from: src.length, length: 0 };\n            }\n\n            // add the text before the tag\n            length = range.from - index;\n            if (length > 0) {\n                text = src.substr(index, length);\n                if (/\\S/.test(text)) {\n                    payload = extractPayload(text);\n                    payload.sourceOffset = index;\n                    payload.sourceLength = length;\n                    callback(payload);\n                }\n            }\n\n            // add the tag\n            if (range.length > 0) {\n                payload = extractPayload(src.substr(range.from, range.length));\n                payload.sourceOffset = range.from;\n                payload.sourceLength = range.length;\n                callback(payload);\n            }\n\n            // advance\n            index = range.from + range.length;\n        }\n    }\n\n    // Export public functions\n    exports.extractPayload = extractPayload;\n    exports.eachNode = eachNode;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/DOMNode.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint forin: true */\n\n/**\n * DOMNode represents a node in the DOM tree. It is constructed from a payload\n * similar to {DOM.Node} and supports all basic tree operations. If a node has\n * a nodeId it is registered with the `DOMAgent` via `addNode()`. The node's\n * sourceOffset and sourceLength is stored as its location and length. Nodes can\n * iterated using `each()` or `find()`. `dump` shows the entire tree on the console.\n */\ndefine(function DOMNodeModule(require, exports, module) {\n    \"use strict\";\n\n    var DOMHelpers = require(\"LiveDevelopment/Agents/DOMHelpers\");\n\n    /** Fill a string to the given length (used for debug output)\n     * @param {string} source string\n     * @param {integer} length\n     * @param {char} fill character\n     */\n    function _fill(string, length, c) {\n        if (c === undefined) {\n            c = \" \";\n        }\n        while (string.length < length) {\n            string += c;\n        }\n        return string;\n    }\n\n    /** Construct a find condition (used in `find` and `findParent`)\n     * The match can be a callback returning true or false, the node\n     * name or the node type.\n     * @param {function} or {string} or {number} match criteria\n     */\n    function _makeFindCondition(match) {\n        switch (typeof match) {\n        case \"function\":\n            return match;\n        case \"string\":\n            return function findCondition(name, node) {\n                return node.name === name;\n            }.bind(undefined, match.toUpperCase());\n        case \"number\":\n            return function findCondition(type, node) {\n                return node.type === type;\n            }.bind(undefined, match);\n        default:\n            console.error(\"Invalid find condition: \" + match);\n        }\n    }\n\n    /** Constructor\n     * @param {DOMAgent} the agent is passed to avoid circular relationships\n     * @param {DOM.Node} node payload\n     */\n    var DOMNode = function DOMNode(agent, payload) {\n        this.agent = agent;\n        this.children = [];\n        this.attributes = {};\n\n        // set the payload\n        if (typeof payload === \"string\") {\n            payload = DOMHelpers.extractPayload(payload);\n        }\n        if (payload) {\n            this.setPayload(payload);\n        }\n        this.agent.addNode(this);\n    };\n\n    var TYPE_ELEMENT = DOMNode.TYPE_ELEMENT = 1; // element node\n    var TYPE_ATTRIBUTE = DOMNode.TYPE_ATTRIBUTE = 2; // attribute node (unused)\n    var TYPE_TEXT = DOMNode.TYPE_TEXT = 3; // text node\n    var TYPE_COMMENT = DOMNode.TYPE_COMMENT = 8; // comment node <!-- -->\n    var TYPE_DOCUMENT = DOMNode.TYPE_DOCUMENT = 9; // document node <!DOCUMENT>\n\n    /** Remove a node */\n    DOMNode.prototype.remove = function remove() {\n        this.agent.removeNode(this);\n        if (this.parent) {\n            this.parent.removeChild(this);\n        }\n    };\n\n\n    /** Node Payload ***********************************************************/\n\n    /** Set the node payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.setPayload = function setPayload(payload) {\n        this.nodeId = payload.nodeId;\n        this.type = payload.nodeType;\n        if (payload.nodeName) {\n            this.name = payload.nodeName;\n        }\n        if (payload.nodeValue) {\n            this.value = payload.nodeValue;\n        }\n        this.attributes = {};\n        if (payload.attributes) {\n            var i, k, v;\n            for (i = 0; i < payload.attributes.length; i += 2) {\n                k = payload.attributes[i];\n                v = payload.attributes[i + 1];\n                this.attributes[k] = v;\n            }\n        }\n        if (payload.sourceOffset) {\n            this.location = payload.sourceOffset;\n        }\n        if (payload.sourceLength) {\n            this.length = payload.sourceLength;\n        } else {\n            if (this.value) {\n                this.length = this.value.length;\n            } else if (this.name) {\n                this.length = this.name.length + 2;\n            }\n        }\n        if (payload.children) {\n            this.setChildrenPayload(payload.children);\n        } else if (payload.childNodeCount) {\n            this.agent.requestChildNodes(this);\n        }\n    };\n\n    /** Create child nodes from the given payload\n     * @param [{DOM.Node}] payload of the children\n     */\n    DOMNode.prototype.setChildrenPayload = function setChildrenPayload(childrenPayload) {\n        var i, payload, node;\n        for (i in childrenPayload) {\n            payload = childrenPayload[i];\n            node = new DOMNode(this.agent, payload);\n            this.appendChild(node);\n        }\n    };\n\n    /** Construct the payload for this node */\n    DOMNode.prototype.payload = function payload() {\n        var res = { type: this.type };\n        if (this.nodeType === TYPE_ELEMENT) {\n            res.nodeName = this.name;\n        } else {\n            res.value = this.value;\n        }\n        return res;\n    };\n\n    /** Find the next node that matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.findParentForNextNodeMatchingPayload = function findParentForNextNodeMatchingPayload(payload) {\n        var parent = this.canHaveChildren() ? this : this.parent;\n        while (parent && !parent.matchesPayload(payload)) {\n            parent = parent.parent;\n        }\n        return parent;\n    };\n\n    /** Find the next node that matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.findNextNodeMatchingPayload = function findNextNodeMatchingPayload(payload) {\n        var next = this.nextNode();\n        while (next && !next.matchesPayload(payload)) {\n            next = next.nextNode();\n        }\n        return next;\n    };\n\n    /** Test if the node matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.matchesPayload = function matchesPayload(payload) {\n        var r = false;\n        if (this.type === payload.nodeType) {\n            switch (this.type) {\n            case 1:\n                r = this.name === payload.nodeName;\n                break;\n            case 3:\n                // TODO payload.nodeValue's HTML Entities must be decoded\n                // r = this.value === payload.nodeValue;\n                r = true;\n                break;\n            default:\n                r = true;\n            }\n        }\n        // Useful output for debugging this - do not remove\n        // console.debug(this.type + \",\" + this.name + \",\" + this.value + \" = \" + payload.nodeType + \",\" + payload.nodeName + \",\" + payload.value + \" -> \" + r);\n        return r;\n    };\n\n    /** Resolve the node and retrieve its objectId from the remote debugger */\n    DOMNode.prototype.resolve = function resolve() {\n        var def = new $.Deferred();\n        if (this.objectId) {\n            def.resolve(this);\n        } else if (!this.nodeId) {\n            def.reject();\n        } else {\n            this.agent.resolveNode(this, function onResolve(res) {\n                this.objectId = res.object.objectId;\n                def.resolve(this);\n            }.bind(this));\n        }\n        return def.promise();\n    };\n\n\n    /** Tree Operations ******************************************************/\n\n    /** Can the node have children? */\n    DOMNode.prototype.canHaveChildren = function canHaveChildren() {\n        return (this.type === 1 && !this.closed && !this.closing && this.nodeName !== \"LINK\");\n    };\n\n    /** Remove a child\n     * @param {DOMNode} child node to remove\n     */\n    DOMNode.prototype.removeChild = function removeChild(node) {\n        this.children.splice(this.indexOfChild(node), 1);\n        delete node.parent;\n    };\n\n    /** Insert a child node at the given index\n     * @param {DOMNode} node to insert\n     * @param {integer} optional index (node is appended if missing)\n     */\n    DOMNode.prototype.insertChildAt = function insertChildAt(node, index) {\n        if (node.parent) {\n            node.parent.removeChild(node);\n        }\n        if (!index || index < 0 || index > this.children.length) {\n            index = this.children.length;\n        }\n        this.children.splice(index, 0, node);\n        node.parent = this;\n        return node;\n    };\n\n    /** Append a child to this node\n     * @param {DOMNode} child node to append\n     */\n    DOMNode.prototype.appendChild = function appendChild(node) {\n        return this.insertChildAt(node);\n    };\n\n    /** Insert a child node after the given node\n     * @param {DOMNode} child node to insert\n     * @param {DOMNode} existing child node\n     */\n    DOMNode.prototype.insertChildAfter = function insertChildAfter(node, sibling) {\n        var index = this.indexOfChild(sibling);\n        if (index >= 0) {\n            index++;\n        }\n        return this.insertChildAt(node, index);\n    };\n\n    /** Insert a child node before the given node\n     * @param {DOMNode} child node to insert\n     * @param {DOMNode} existing child node\n     */\n    DOMNode.prototype.insertChildBefore = function insertChildBefore(node, sibling) {\n        var index = this.indexOfChild(sibling);\n        return this.insertChildAt(node, index);\n    };\n\n    /** Determine the index of a child node\n     * @param {DOMNode} child node\n     */\n    DOMNode.prototype.indexOfChild = function indexOfChild(node) {\n        if (!node) {\n            return -1;\n        }\n        var i;\n        for (i in this.children) {\n            if (this.children[i] === node) {\n                return parseInt(i, 0);\n            }\n        }\n        return -1;\n    };\n\n    /** Get the previous sibling */\n    DOMNode.prototype.previousSibling = function previousSibling() {\n        if (!this.parent) {\n            return null;\n        }\n        return this.parent.children[this.parent.indexOfChild(this) - 1];\n    };\n\n    /** Get the next sibling */\n    DOMNode.prototype.nextSibling = function nextSibling() {\n        if (!this.parent) {\n            return null;\n        }\n        return this.parent.children[this.parent.indexOfChild(this) + 1];\n    };\n\n    /** Get the previous node */\n    DOMNode.prototype.previousNode = function previousNode() {\n        var node = this.previousSibling();\n        if (node) {\n            if (node.children.length > 0) {\n                node = node.children[node.children.length - 1];\n            }\n        } else {\n            node = this.parent;\n        }\n        return node;\n    };\n\n    /** Get the next node */\n    DOMNode.prototype.nextNode = function nextNode() {\n        if (this.children.length > 0) {\n            // return the first child\n            return this.children[0];\n        }\n        // return this or any ancestor's next sibling\n        var node, parent = this;\n        while (parent) {\n            node = parent.nextSibling();\n            if (node) {\n                return node;\n            }\n            parent = parent.parent;\n        }\n        return null;\n    };\n\n    /** Traverse the tree\n     * @param {function({DOM.Node})} called for this node and all descendants\n     */\n    DOMNode.prototype.each = function each(callback) {\n        if (callback(this) === false) {\n            return false;\n        }\n        var i;\n        for (i in this.children) {\n            if (this.children[i].each(callback) === false) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    /** Find a node in the tree\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.find = function find(match) {\n        var findCondition = _makeFindCondition(match);\n        var node = null;\n        this.each(function each(n) {\n            if (findCondition(n)) {\n                node = n;\n                return false;\n            }\n        });\n        return node;\n    };\n\n    /** Find all nodes with the given find condition\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.findAll = function findAll(match) {\n        var nodes = [];\n        var findCondition = _makeFindCondition(match);\n        this.each(function each(node) {\n            if (findCondition(node)) {\n                nodes.push(node);\n            }\n        });\n        return nodes;\n    };\n\n    /** Iterate over all parent nodes\n     * @param {function({DOM.Node})} called for each ancestor\n     */\n    DOMNode.prototype.eachParent = function eachParent(callback) {\n        var node = this.parent;\n        while (node) {\n            if (callback(node) === false) {\n                return;\n            }\n            node = node.parent;\n        }\n        return null;\n    };\n\n    /** Find a parent node that matches the find condition\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.findParent = function findParent(findCondition) {\n        var theParent = null;\n        this.eachParent(function each(parent) {\n            if (findCondition(parent)) {\n                theParent = parent;\n                return false;\n            }\n        });\n        return theParent;\n    };\n\n    /** Find the root of the tree */\n    DOMNode.prototype.root = function root() {\n        var node = this;\n        while (node.parent) {\n            node = node.parent;\n        }\n        return node;\n    };\n\n\n   /** Node Info ***********************************************************/\n\n   /** Test if the given location is inside this node\n    * @param {integer} location\n    * @param {boolean} also include children\n    */\n    DOMNode.prototype.isAtLocation = function isAtLocation(location, includeChildren) {\n        if (includeChildren === undefined) {\n            includeChildren = true;\n        }\n        if (!this.location || location < this.location) {\n            return false;\n        }\n        var to;\n        if (includeChildren && this.closeLocation) {\n            to = this.closeLocation + this.closeLength;\n        } else {\n            to = this.location + this.length;\n        }\n        if (this.type === TYPE_TEXT) {\n            to += 1;\n        }\n        return location < to;\n    };\n\n    /** Test if this node is empty */\n    DOMNode.prototype.isEmpty = function isEmpty() {\n        return this.type === TYPE_TEXT && /^\\s*$/.test(this.value);\n    };\n\n    /** Debug Output */\n    DOMNode.prototype.toString = function toString() {\n        var r;\n        switch (this.type) {\n        case TYPE_ELEMENT:\n            r = \"<\" + this.name + \">\";\n            break;\n        case TYPE_ATTRIBUTE:\n            r = \"[ATTRIBUTE]\";\n            break;\n        case TYPE_TEXT:\n            r = this.value.replace(/\\s+/, \" \").substr(0, 40);\n            break;\n        case TYPE_COMMENT:\n            r = \"<!--\" + this.value.replace(/\\s+/, \" \").substr(0, 33) + \"-->\";\n            break;\n        case TYPE_DOCUMENT:\n            r = \"<!DOCTYPE>\";\n            break;\n        }\n        return r;\n    };\n\n    /** Detailed Debug Output */\n    DOMNode.prototype.dump = function dump(pre) {\n        if (pre === undefined) {\n            pre = \"\";\n        }\n        var r = pre + this.toString();\n        if (this.location) {\n            r = _fill(r, 60);\n            r += \" (\" + this.location + \",\" + (this.location + this.length) + \")\";\n            if (this.closeLocation) {\n                r += \" (\" + this.closeLocation + \",\" + (this.closeLocation + this.closeLength) + \")\";\n            }\n        }\n        if (this.nodeId) {\n            r = _fill(r, 80);\n            r += \" {\" + this.nodeId + \"}\";\n        }\n        console.info(r);\n        pre += \". \";\n        var i;\n        for (i in this.children) {\n            this.children[i].dump(pre);\n        }\n    };\n\n    return DOMNode;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/EditAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * EditAgent propagates changes from the in-document editor to the source\n * document.\n */\ndefine(function EditAgent(require, exports, module) {\n    \"use strict\";\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var GotoAgent = require(\"LiveDevelopment/Agents/GotoAgent\");\n\n    var EditorManager = require(\"editor/EditorManager\");\n\n    var _editedNode;\n\n    /** Find changed characters\n     * @param {string} old value\n     * @param {string} changed value\n     * @return {from, to, text}\n     */\n    function _findChangedCharacters(oldValue, value) {\n        if (oldValue === value) {\n            return undefined;\n        }\n        var length = oldValue.length;\n        var index = 0;\n\n        // find the first character that changed\n        var i;\n        for (i = 0; i < length; i++) {\n            if (value[i] !== oldValue[i]) {\n                break;\n            }\n        }\n        index += i;\n        value = value.substr(i);\n        length -= i;\n\n        // find the last character that changed\n        for (i = 0; i < length; i++) {\n            if (value[value.length - 1 - i] !== oldValue[oldValue.length - 1 - i]) {\n                break;\n            }\n        }\n        length -= i;\n        value = value.substr(0, value.length - i);\n\n        return { from: index, to: index + length, text: value };\n    }\n\n    // WebInspector Event: DOM.characterDataModified\n    function _onCharacterDataModified(event, res) {\n        // res = {nodeId, characterData}\n        if (_editedNode.nodeId !== res.nodeId) {\n            return;\n        }\n\n        GotoAgent.open(DOMAgent.url);\n        var editor = EditorManager.getCurrentFullEditor();\n        var codeMirror = editor._codeMirror;\n        var change = _findChangedCharacters(_editedNode.value, res.characterData);\n        if (change) {\n            var from = codeMirror.posFromIndex(_editedNode.location + change.from);\n            var to = codeMirror.posFromIndex(_editedNode.location + change.to);\n            exports.isEditing = true;\n            editor.document.replaceRange(change.text, from, to);\n            exports.isEditing = false;\n\n            var newPos = codeMirror.posFromIndex(_editedNode.location + change.from + change.text.length);\n            editor.setCursorPos(newPos.line, newPos.ch);\n        }\n    }\n\n    // Remote Event: Go to the given source node\n    function _onRemoteEdit(event, res) {\n        // res = {nodeId, name, value}\n\n        // detach from DOM change events\n        if (res.value === \"0\") {\n            Inspector.DOM.off(\".EditAgent\");\n            return;\n        }\n\n        // find and store the edited node\n        var node = DOMAgent.nodeWithId(res.nodeId);\n        node = node.children[0];\n        if (!node.location) {\n            return;\n        }\n        _editedNode = node;\n\n        // attach to character data modified events\n        Inspector.DOM.on(\"characterDataModified.EditAgent\", _onCharacterDataModified);\n    }\n\n    /** Initialize the agent */\n    function load() {\n        RemoteAgent.on(\"edit.EditAgent\", _onRemoteEdit);\n    }\n\n    /** Initialize the agent */\n    function unload() {\n        RemoteAgent.off(\".EditAgent\");\n    }\n\n    // Export public functions\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/GotoAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n\n/*jslint forin: true, regexp: true */\n\n/**\n * GotoAgent constructs and responds to the in-browser goto dialog.\n */\ndefine(function GotoAgent(require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\"),\n        DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\"),\n        ScriptAgent = require(\"LiveDevelopment/Agents/ScriptAgent\"),\n        RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\"),\n        EditorManager = require(\"editor/EditorManager\"),\n        CommandManager = require(\"command/CommandManager\"),\n        Commands = require(\"command/Commands\");\n\n\n    /** Return the URL without the query string\n     * @param {string} URL\n     */\n    function _urlWithoutQueryString(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Get the file component of the given url\n     * @param {string} URL\n     */\n    function _fileFromURL(url) {\n        var comp = url.split(\"/\");\n        return comp[comp.length - 1];\n    }\n\n    /** Make the given node a target for goto\n     * @param [] targets array\n     * @param {DOMNode} node\n     */\n    function _makeHTMLTarget(targets, node) {\n        if (node.location) {\n            var url = DOMAgent.url;\n            var location = node.location;\n            if (node.canHaveChildren()) {\n                location += node.length;\n            }\n            url += \":\" + location;\n            var name = \"&lt;\" + node.name + \"&gt;\";\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"html\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Make the given css rule a target for goto\n     * @param [] targets array\n     * @param {CSS.Rule} node\n     */\n    function _makeCSSTarget(targets, rule) {\n        if (rule.sourceURL) {\n            var url = rule.sourceURL;\n            url += \":\" + rule.style.range.start;\n            var name = rule.selectorList.text;\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"css\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Make the given javascript callFrame the target for goto\n     * @param [] targets array\n     * @param {Debugger.CallFrame} node\n     */\n    function _makeJSTarget(targets, callFrame) {\n        var script = ScriptAgent.scriptWithId(callFrame.location.scriptId);\n        if (script && script.url) {\n            var url = script.url;\n            url += \":\" + callFrame.location.lineNumber + \",\" + callFrame.location.columnNumber;\n            var name = callFrame.functionName;\n            if (name === \"\") {\n                name = \"anonymous function\";\n            }\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"js\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Gather options where to go to from the given source node */\n    function _onRemoteShowGoto(event, res) {\n        // res = {nodeId, name, value}\n        var node = DOMAgent.nodeWithId(res.nodeId);\n\n        // get all css rules that apply to the given node\n        Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onMatchedStyles(res) {\n            var i, targets = [];\n            _makeHTMLTarget(targets, node);\n            for (i in node.trace) {\n                _makeJSTarget(targets, node.trace[i]);\n            }\n            for (i in node.events) {\n                var trace = node.events[i];\n                _makeJSTarget(targets, trace.callFrames[0]);\n            }\n            for (i in res.matchedCSSRules.reverse()) {\n                _makeCSSTarget(targets, res.matchedCSSRules[i].rule);\n            }\n            RemoteAgent.call(\"showGoto\", targets);\n        });\n    }\n\n    /** Point the master editor to the given location\n     * @param {integer} location in file\n     */\n    function openLocation(location, noFlash) {\n        var editor = EditorManager.getCurrentFullEditor();\n        var codeMirror = editor._codeMirror;\n        if (typeof location === \"number\") {\n            location = codeMirror.posFromIndex(location);\n        }\n        codeMirror.setCursor(location);\n        editor.focus();\n\n        if (!noFlash) {\n            codeMirror.addLineClass(location.line, \"wrap\", \"flash\");\n            window.setTimeout(function () {\n                codeMirror.removeLineClass(location.line, \"wrap\", \"flash\");\n            }, 1000);\n        }\n    }\n\n    /** Open the editor at the given url and editor location\n     * @param {string} url\n     * @param {integer} optional location in file\n     */\n    function open(url, location, noFlash) {\n        console.assert(url.substr(0, 7) === \"file://\", \"Cannot open non-file URLs\");\n\n        var result = new $.Deferred();\n\n        url = _urlWithoutQueryString(url);\n        // Extract the path, also strip the third slash when on Windows\n        var path = url.slice(brackets.platform === \"win\" ? 8 : 7);\n        // URL-decode the path ('%20' => ' ')\n        path = decodeURI(path);\n        var promise = CommandManager.execute(Commands.FILE_OPEN, {fullPath: path});\n        promise.done(function onDone(doc) {\n            if (location) {\n                openLocation(location, noFlash);\n            }\n            result.resolve();\n        });\n        promise.fail(function onErr(err) {\n            console.error(err);\n            result.reject(err);\n        });\n\n        return result.promise();\n    }\n\n    /** Go to the given source node */\n    function _onRemoteGoto(event, res) {\n        // res = {nodeId, name, value}\n        var location, url = res.value;\n        var matches = /^(.*):([^:]+)$/.exec(url);\n        if (matches) {\n            url = matches[1];\n            location = matches[2].split(\",\");\n            if (location.length === 1) {\n                location = parseInt(location[0], 10);\n            } else {\n                location = { line: parseInt(location[0], 10), ch: parseInt(location[1], 10) };\n            }\n        }\n        open(url, location);\n    }\n\n    /** Initialize the agent */\n    function load() {\n        RemoteAgent\n            .on(\"showgoto.GotoAgent\", _onRemoteShowGoto)\n            .on(\"goto.GotoAgent\", _onRemoteGoto);\n    }\n\n    /** Initialize the agent */\n    function unload() {\n        RemoteAgent.off(\".GotoAgent\");\n    }\n\n    // Export public functions\n    exports.openLocation = openLocation;\n    exports.open = open;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/HighlightAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * HighlightAgent dispatches events for highlight requests from in-browser\n * highlight requests, and allows highlighting nodes and rules in the browser.\n *\n * Trigger \"highlight\" when a node should be highlighted\n */\ndefine(function HighlightAgent(require, exports, module) {\n    \"use strict\";\n\n    var DOMAgent        = require(\"LiveDevelopment/Agents/DOMAgent\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        Inspector       = require(\"LiveDevelopment/Inspector/Inspector\"),\n        LiveDevelopment = require(\"LiveDevelopment/LiveDevelopment\"),\n        RemoteAgent     = require(\"LiveDevelopment/Agents/RemoteAgent\"),\n        _               = require(\"thirdparty/lodash\");\n\n    var _highlight = {}; // active highlight\n\n    // Remote Event: Highlight\n    function _onRemoteHighlight(event, res) {\n        var node;\n        if (res.value === \"1\") {\n            node = DOMAgent.nodeWithId(res.nodeId);\n        }\n        exports.trigger(\"highlight\", node);\n    }\n\n    /** Hide in-browser highlighting */\n    function hide() {\n        switch (_highlight.type) {\n        case \"node\":\n            Inspector.DOM.hideHighlight();\n            break;\n        case \"css\":\n            RemoteAgent.call(\"hideHighlight\");\n            break;\n        }\n        _highlight = {};\n    }\n\n    /** Highlight a single node using DOM.highlightNode\n     * @param {DOMNode} node\n     */\n    function node(n) {\n        if (!LiveDevelopment.config.experimental) {\n            return;\n        }\n\n        if (!Inspector.config.highlight) {\n            return;\n        }\n\n        // go to the parent of a text node\n        if (n && n.type === 3) {\n            n = n.parent;\n        }\n\n        // node cannot be highlighted\n        if (!n || !n.nodeId || n.type !== 1) {\n            return hide();\n        }\n\n        // node is already highlighted\n        if (_highlight.type === \"node\" && _highlight.ref === n.nodeId) {\n            return;\n        }\n\n        // highlight the node\n        _highlight = {type: \"node\", ref: n.nodeId};\n        Inspector.DOM.highlightNode(n.nodeId, Inspector.config.highlightConfig);\n    }\n\n    /** Highlight all nodes affected by a CSS rule\n     * @param {string} rule selector\n     */\n    function rule(name) {\n        if (_highlight.ref === name) {\n            return;\n        }\n        hide();\n        _highlight = {type: \"css\", ref: name};\n        RemoteAgent.call(\"highlightRule\", name);\n    }\n\n    /** Highlight all nodes with 'data-brackets-id' value\n     * that matches id, or if id is an array, matches any of the given ids.\n     * @param {string|Array<string>} value of the 'data-brackets-id' to match,\n     * or an array of such.\n     */\n    function domElement(ids) {\n        var selector = \"\";\n        if (!Array.isArray(ids)) {\n            ids = [ids];\n        }\n        _.each(ids, function (id) {\n            if (selector !== \"\") {\n                selector += \",\";\n            }\n            selector += \"[data-brackets-id='\" + id + \"']\";\n        });\n        rule(selector);\n    }\n\n    /**\n     * Redraw active highlights\n     */\n    function redraw() {\n        RemoteAgent.call(\"redrawHighlights\");\n    }\n\n    /** Initialize the agent */\n    function load() {\n        if (LiveDevelopment.config.experimental) {\n            RemoteAgent.on(\"highlight.HighlightAgent\", _onRemoteHighlight);\n        }\n    }\n\n    /** Clean up */\n    function unload() {\n        if (LiveDevelopment.config.experimental) {\n            RemoteAgent.off(\".HighlightAgent\");\n        }\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Export public functions\n    exports.hide = hide;\n    exports.node = node;\n    exports.rule = rule;\n    exports.domElement = domElement;\n    exports.redraw = redraw;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/NetworkAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * NetworkAgent tracks all resources loaded by the remote debugger. Use\n * `wasURLRequested(url)` to query whether a resource was loaded.\n */\ndefine(function NetworkAgent(require, exports, module) {\n    \"use strict\";\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _urlRequested = {}; // url -> request info\n\n    /** Return the URL without the query string\n     * @param {string} URL\n     */\n    function _urlWithoutQueryString(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Return the resource information for a given URL\n     * @param {string} url\n     */\n    function wasURLRequested(url) {\n        return _urlRequested && _urlRequested[url];\n    }\n\n    function _logURL(url) {\n        _urlRequested[_urlWithoutQueryString(url)] = true;\n    }\n\n    // WebInspector Event: Network.requestWillBeSent\n    function _onRequestWillBeSent(event, res) {\n        // res = {requestId, frameId, loaderId, documentURL, request, timestamp, initiator, stackTrace, redirectResponse}\n        _logURL(res.request.url);\n    }\n\n    function _reset() {\n        _urlRequested = {};\n    }\n\n    // WebInspector Event: Page.frameNavigated\n    function _onFrameNavigated(event, res) {\n        // res = {frame}\n        // Clear log when navigating to a new page, but not if an iframe was loaded\n        if (!res.frame.parentId) {\n            _reset();\n        }\n        _logURL(res.frame.url);\n    }\n\n    /**\n     * Enable the inspector Network domain\n     * @return {jQuery.Promise} A promise resolved when the Network.enable() command is successful.\n     */\n    function enable() {\n        return Inspector.Network.enable();\n    }\n\n    /** Initialize the agent */\n    function load() {\n        Inspector.Page.on(\"frameNavigated.NetworkAgent\", _onFrameNavigated);\n        Inspector.Network.on(\"requestWillBeSent.NetworkAgent\", _onRequestWillBeSent);\n    }\n\n    /** Unload the agent */\n    function unload() {\n        _reset();\n        Inspector.Page.off(\".NetworkAgent\");\n        Inspector.Network.off(\".NetworkAgent\");\n    }\n\n    // Export public functions\n    exports.wasURLRequested = wasURLRequested;\n    exports.enable = enable;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/RemoteAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\n/**\n * RemoteAgent defines and provides an interface for custom remote functions\n * loaded from RemoteFunctions. Remote commands are executed via\n * `call(name, varargs)`.\n *\n * Remote events are dispatched as events on this object.\n */\ndefine(function RemoteAgent(require, exports, module) {\n    \"use strict\";\n\n    var LiveDevelopment     = require(\"LiveDevelopment/LiveDevelopment\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        Inspector           = require(\"LiveDevelopment/Inspector/Inspector\"),\n        RemoteFunctions     = require(\"text!LiveDevelopment/Agents/RemoteFunctions.js\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\");\n\n    var _load; // deferred load\n    var _objectId; // the object id of the remote object\n    var _intervalId; // interval used to send keepAlive events\n\n    // WebInspector Event: DOM.attributeModified\n    function _onAttributeModified(event, res) {\n        // res = {nodeId, name, value}\n        var matches = /^data-ld-(.*)/.exec(res.name);\n        if (matches) {\n            exports.trigger(matches[1], res);\n        }\n    }\n\n    function _call(objectId, method, varargs) {\n        console.assert(objectId, \"Attempted to call remote method without objectId set.\");\n        var args = Array.prototype.slice.call(arguments, 2),\n            callback,\n            deferred = new $.Deferred();\n\n        // if the last argument is a function it is the callback function\n        if (typeof args[args.length - 1] === \"function\") {\n            callback = args.pop();\n        }\n\n        // Resolve node parameters\n        args = args.map(function (arg) {\n            if (arg && arg.nodeId) {\n                return arg.resolve();\n            }\n\n            return arg;\n        });\n\n        $.when.apply(undefined, args).done(function onResolvedAllNodes() {\n            var params = [];\n\n            args.forEach(function (arg) {\n                if (arg.objectId) {\n                    params.push({objectId: arg.objectId});\n                } else {\n                    params.push({value: arg});\n                }\n            });\n\n            Inspector.Runtime.callFunctionOn(objectId, method, params, undefined, callback)\n                .then(deferred.resolve, deferred.reject);\n        });\n\n        return deferred.promise();\n    }\n\n    /** Call a remote function\n     * The parameters are passed on to the remote functions. Nodes are resolved\n     * and sent as objectIds.\n     * @param {string} function name\n     */\n    function call(method, varargs) {\n        var argsArray = [_objectId, \"_LD.\" + method];\n\n        if (arguments.length > 1) {\n            argsArray = argsArray.concat(Array.prototype.slice.call(arguments, 1));\n        }\n\n        return _call.apply(null, argsArray);\n    }\n\n    function _stopKeepAliveInterval() {\n        if (_intervalId) {\n            window.clearInterval(_intervalId);\n            _intervalId = null;\n        }\n    }\n\n    function _startKeepAliveInterval() {\n        _stopKeepAliveInterval();\n\n        _intervalId = window.setInterval(function () {\n            call(\"keepAlive\");\n        }, 1000);\n    }\n\n    // WebInspector Event: Page.frameNavigated\n    function _onFrameNavigated(event, res) {\n        // res = {frame}\n        // Re-inject RemoteFunctions when navigating to a new page, but not if an iframe was loaded\n        if (res.frame.parentId) {\n            return;\n        }\n\n        _stopKeepAliveInterval();\n\n        // inject RemoteFunctions\n        var command = \"window._LD=\" + RemoteFunctions + \"(\" + JSON.stringify(LiveDevelopment.config) + \",\" + PreferencesManager.get(\"livedev.wsPort\") + \");\";\n\n        Inspector.Runtime.evaluate(command, function onEvaluate(response) {\n            if (response.error || response.wasThrown) {\n                _load.reject(response.error);\n            } else {\n                _objectId = response.result.objectId;\n                _load.resolve();\n\n                _startKeepAliveInterval();\n            }\n        });\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        Inspector.Page.on(\"frameNavigated.RemoteAgent\", _onFrameNavigated);\n        Inspector.Page.on(\"frameStartedLoading.RemoteAgent\", _stopKeepAliveInterval);\n        Inspector.DOM.on(\"attributeModified.RemoteAgent\", _onAttributeModified);\n\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        Inspector.Page.off(\".RemoteAgent\");\n        Inspector.DOM.off(\".RemoteAgent\");\n        _stopKeepAliveInterval();\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Export public functions\n    exports.call = call;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/RemoteFunctions.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint forin: true */\n/*global Node, MessageEvent */\n/*theseus instrument: false */\n\n/**\n * RemoteFunctions define the functions to be executed in the browser. This\n * modules should define a single function that returns an object of all\n * exported functions.\n */\nfunction RemoteFunctions(config, remoteWSPort) {\n    \"use strict\";\n\n    var experimental;\n    if (!config) {\n        experimental = false;    \n    } else {\n        experimental = config.experimental;    \n    }\n    var lastKeepAliveTime = Date.now();\n    var req, timeout;\n    var animateHighlight = function (time) {\n        if(req) {\n            window.cancelAnimationFrame(req);\t\n            window.clearTimeout(timeout);\n        }\n        req = window.requestAnimationFrame(redrawHighlights);\n\n        timeout = setTimeout(function () {\n            window.cancelAnimationFrame(req);\t\n            req = null;\n        }, time * 1000);\n    };\n\n    /**\n     * @type {DOMEditHandler}\n     */\n    var _editHandler;\n\n    var HIGHLIGHT_CLASSNAME = \"__brackets-ld-highlight\",\n        KEEP_ALIVE_TIMEOUT  = 3000;   // Keep alive timeout value, in milliseconds\n\n    // determine whether an event should be processed for Live Development\n    function _validEvent(event) {\n        if (window.navigator.platform.substr(0, 3) === \"Mac\") {\n            // Mac\n            return event.metaKey;\n        } else {\n            // Windows\n            return event.ctrlKey;\n        }\n    }\n\n    // determine the color for a type\n    function _typeColor(type, highlight) {\n        switch (type) {\n        case \"html\":\n            return highlight ? \"#eec\" : \"#ffe\";\n        case \"css\":\n            return highlight ? \"#cee\" : \"#eff\";\n        case \"js\":\n            return highlight ? \"#ccf\" : \"#eef\";\n        default:\n            return highlight ? \"#ddd\" : \"#eee\";\n        }\n    }\n\n    // compute the screen offset of an element\n    function _screenOffset(element) {\n        var elemBounds = element.getBoundingClientRect(),\n            body = window.document.body,\n            offsetTop,\n            offsetLeft;\n\n        if (window.getComputedStyle(body).position === \"static\") {\n            offsetLeft = elemBounds.left + window.pageXOffset;\n            offsetTop = elemBounds.top + window.pageYOffset;\n        } else {\n            var bodyBounds = body.getBoundingClientRect();\n            offsetLeft = elemBounds.left - bodyBounds.left;\n            offsetTop = elemBounds.top - bodyBounds.top;\n        }\n        return { left: offsetLeft, top: offsetTop };\n    }\n\n    // set an event on a element\n    function _trigger(element, name, value, autoRemove) {\n        var key = \"data-ld-\" + name;\n        if (value !== undefined && value !== null) {\n            element.setAttribute(key, value);\n            if (autoRemove) {\n                window.setTimeout(element.removeAttribute.bind(element, key));\n            }\n        } else {\n            element.removeAttribute(key);\n        }\n    }\n    \n    // Checks if the element is in Viewport in the client browser\n    function isInViewport(element) {\n        var rect = element.getBoundingClientRect();\n        var html = window.document.documentElement;\n        return (\n            rect.top >= 0 &&\n            rect.left >= 0 &&\n            rect.bottom <= (window.innerHeight || html.clientHeight) &&\n            rect.right <= (window.innerWidth || html.clientWidth)\n        );\n    }\n    \n    // returns the distance from the top of the closest relatively positioned parent element\n    function getDocumentOffsetTop(element) {\n        return element.offsetTop + (element.offsetParent ? getDocumentOffsetTop(element.offsetParent) : 0);\n    }\n\n    // construct the info menu\n    function Menu(element) {\n        this.element = element;\n        _trigger(this.element, \"showgoto\", 1, true);\n        window.setTimeout(window.remoteShowGoto);\n        this.remove = this.remove.bind(this);\n    }\n\n    Menu.prototype = {\n        onClick: function (url, event) {\n            event.preventDefault();\n            _trigger(this.element, \"goto\", url, true);\n            this.remove();\n        },\n\n        createBody: function () {\n            if (this.body) {\n                return;\n            }\n\n            // compute the position on screen\n            var offset = _screenOffset(this.element),\n                x = offset.left,\n                y = offset.top + this.element.offsetHeight;\n\n            // create the container\n            this.body = window.document.createElement(\"div\");\n            this.body.style.setProperty(\"z-index\", 2147483647);\n            this.body.style.setProperty(\"position\", \"absolute\");\n            this.body.style.setProperty(\"left\", x + \"px\");\n            this.body.style.setProperty(\"top\", y + \"px\");\n            this.body.style.setProperty(\"font-size\", \"11pt\");\n\n            // draw the background\n            this.body.style.setProperty(\"background\", \"#fff\");\n            this.body.style.setProperty(\"border\", \"1px solid #888\");\n            this.body.style.setProperty(\"-webkit-box-shadow\", \"2px 2px 6px 0px #ccc\");\n            this.body.style.setProperty(\"border-radius\", \"6px\");\n            this.body.style.setProperty(\"padding\", \"6px\");\n        },\n\n        addItem: function (target) {\n            var item = window.document.createElement(\"div\");\n            item.style.setProperty(\"padding\", \"2px 6px\");\n            if (this.body.childNodes.length > 0) {\n                item.style.setProperty(\"border-top\", \"1px solid #ccc\");\n            }\n            item.style.setProperty(\"cursor\", \"pointer\");\n            item.style.setProperty(\"background\", _typeColor(target.type));\n            item.innerHTML = target.name;\n            item.addEventListener(\"click\", this.onClick.bind(this, target.url));\n\n            if (target.file) {\n                var file = window.document.createElement(\"i\");\n                file.style.setProperty(\"float\", \"right\");\n                file.style.setProperty(\"margin-left\", \"12px\");\n                file.innerHTML = \" \" + target.file;\n                item.appendChild(file);\n            }\n            this.body.appendChild(item);\n        },\n\n        show: function () {\n            if (!this.body) {\n                this.body = this.createBody();\n            }\n            if (!this.body.parentNode) {\n                window.document.body.appendChild(this.body);\n            }\n            window.document.addEventListener(\"click\", this.remove);\n        },\n\n        remove: function () {\n            if (this.body && this.body.parentNode) {\n                window.document.body.removeChild(this.body);\n            }\n            window.document.removeEventListener(\"click\", this.remove);\n        }\n\n    };\n\n    function Editor(element) {\n        this.onBlur = this.onBlur.bind(this);\n        this.onKeyPress = this.onKeyPress.bind(this);\n\n        this.element = element;\n        this.element.setAttribute(\"contenteditable\", \"true\");\n        this.element.focus();\n        this.element.addEventListener(\"blur\", this.onBlur);\n        this.element.addEventListener(\"keypress\", this.onKeyPress);\n\n        this.revertText = this.element.innerHTML;\n\n        _trigger(this.element, \"edit\", 1);\n    }\n\n    Editor.prototype = {\n        onBlur: function (event) {\n            this.element.removeAttribute(\"contenteditable\");\n            this.element.removeEventListener(\"blur\", this.onBlur);\n            this.element.removeEventListener(\"keypress\", this.onKeyPress);\n            _trigger(this.element, \"edit\", 0, true);\n        },\n\n        onKeyPress: function (event) {\n            switch (event.which) {\n            case 13: // return\n                this.element.blur();\n                break;\n            case 27: // esc\n                this.element.innerHTML = this.revertText;\n                this.element.blur();\n                break;\n            }\n        }\n    };\n\n    function Highlight(color, trigger) {\n        this.color = color;\n        this.trigger = !!trigger;\n        this.elements = [];\n        this.selector = \"\";\n    }\n\n    Highlight.prototype = {\n        _elementExists: function (element) {\n            var i;\n            for (i in this.elements) {\n                if (this.elements[i] === element) {\n                    return true;\n                }\n            }\n            return false;\n        },\n        _makeHighlightDiv: function (element, doAnimation) {\n            var elementBounds = element.getBoundingClientRect(),\n                highlight = window.document.createElement(\"div\"),\n                elementStyling = window.getComputedStyle(element),\n                transitionDuration = parseFloat(elementStyling.getPropertyValue('transition-duration')),\n                animationDuration = parseFloat(elementStyling.getPropertyValue('animation-duration'));\n            \n            if (transitionDuration) {\n                animateHighlight(transitionDuration);\n            }\n\n            if (animationDuration) {\n                animateHighlight(animationDuration);\n            }\n\n            // Don't highlight elements with 0 width & height\n            if (elementBounds.width === 0 && elementBounds.height === 0) {\n                return;\n            }\n            \n            var realElBorder = {\n              right: elementStyling.getPropertyValue('border-right-width'),\n              left: elementStyling.getPropertyValue('border-left-width'),\n              top: elementStyling.getPropertyValue('border-top-width'),\n              bottom: elementStyling.getPropertyValue('border-bottom-width')\n            };\n            \n            var borderBox = elementStyling.boxSizing === 'border-box';\n            \n            var innerWidth = parseFloat(elementStyling.width),\n                innerHeight = parseFloat(elementStyling.height),\n                outerHeight = innerHeight,\n                outerWidth = innerWidth;\n                \n            if (!borderBox) {\n                innerWidth += parseFloat(elementStyling.paddingLeft) + parseFloat(elementStyling.paddingRight);\n                innerHeight += parseFloat(elementStyling.paddingTop) + parseFloat(elementStyling.paddingBottom);\n                outerWidth = innerWidth + parseFloat(realElBorder.right) +\n                parseFloat(realElBorder.left),\n                outerHeight = innerHeight + parseFloat(realElBorder.bottom) + parseFloat(realElBorder.top);\n            }\n\n          \n            var visualisations = {\n                horizontal: \"left, right\",\n                vertical: \"top, bottom\"\n            };\n          \n            var drawPaddingRect = function(side) {\n              var elStyling = {};\n                \n              if (visualisations.horizontal.indexOf(side) >= 0) {\n                elStyling['width'] =  elementStyling.getPropertyValue('padding-' + side);\n                elStyling['height'] = innerHeight + \"px\";\n                elStyling['top'] = 0;\n                  \n                  if (borderBox) {\n                    elStyling['height'] = innerHeight - parseFloat(realElBorder.top) - parseFloat(realElBorder.bottom) + \"px\";\n                  }\n                \n              } else {\n                elStyling['height'] = elementStyling.getPropertyValue('padding-' + side);  \n                elStyling['width'] = innerWidth + \"px\";\n                elStyling['left'] = 0;\n                  \n                  if (borderBox) {\n                    elStyling['width'] = innerWidth - parseFloat(realElBorder.left) - parseFloat(realElBorder.right) + \"px\";\n                  }\n              }\n                \n              elStyling[side] = 0;\n              elStyling['position'] = 'absolute';\n              \n              return elStyling;\n            };\n          \n          var drawMarginRect = function(side) {\n            var elStyling = {};\n            \n            var margin = [];\n            margin['right'] = parseFloat(elementStyling.getPropertyValue('margin-right'));\n            margin['top'] = parseFloat(elementStyling.getPropertyValue('margin-top'));\n            margin['bottom'] = parseFloat(elementStyling.getPropertyValue('margin-bottom'));\n            margin['left'] = parseFloat(elementStyling.getPropertyValue('margin-left'));\n          \n            if(visualisations['horizontal'].indexOf(side) >= 0) {\n\n              elStyling['width'] = elementStyling.getPropertyValue('margin-' + side);\n              elStyling['height'] = outerHeight + margin['top'] + margin['bottom'] + \"px\";\n              elStyling['top'] = \"-\" + (margin['top'] + parseFloat(realElBorder.top))  + \"px\";\n            } else {\n              elStyling['height'] = elementStyling.getPropertyValue('margin-' + side);\n              elStyling['width'] = outerWidth + \"px\";\n              elStyling['left'] = \"-\" + realElBorder.left;\n            }\n\n            elStyling[side] = \"-\" + (margin[side] + parseFloat(realElBorder[side])) + \"px\";\n            elStyling['position'] = 'absolute';\n\n            return elStyling;\n          };\n\n            var setVisibility = function (el) {\n                if (\n                    !config.remoteHighlight.showPaddingMargin || \n                    parseInt(el.height, 10) <= 0 || \n                    parseInt(el.width, 10) <= 0 \n                ) {\n                    el.display = 'none';\n                } else {\n                    el.display = 'block';\n                }\n            };\n            \n            var mainBoxStyles = config.remoteHighlight.stylesToSet;\n            \n            var paddingVisualisations = [\n              drawPaddingRect('top'),\n              drawPaddingRect('right'),\n              drawPaddingRect('bottom'),\n              drawPaddingRect('left')  \n            ];\n                \n            var marginVisualisations = [\n              drawMarginRect('top'),\n              drawMarginRect('right'),\n              drawMarginRect('bottom'),\n              drawMarginRect('left')  \n            ];\n            \n            var setupVisualisations = function (arr, config) {\n                var i;\n                for (i = 0; i < arr.length; i++) {\n                    setVisibility(arr[i]);\n                    \n                    // Applies to every visualisationElement (padding or margin div)\n                    arr[i][\"transform\"] = \"none\";\n                    var el = window.document.createElement(\"div\"),\n                        styles = Object.assign(\n                        {},\n                        config,\n                        arr[i]\n                    );\n\n                    _setStyleValues(styles, el.style);\n\n                    highlight.appendChild(el);\n                }\n            };\n            \n            setupVisualisations(\n                marginVisualisations,\n                config.remoteHighlight.marginStyling\n            );\n            setupVisualisations(\n                paddingVisualisations,\n                config.remoteHighlight.paddingStyling\n            );\n            \n            highlight.className = HIGHLIGHT_CLASSNAME;\n\n            var offset = _screenOffset(element);\n            \t\t\n            var el = element,\t\t\n            offsetLeft = 0,\t\t\n            offsetTop  = 0;\t\t\n             \t\t\n            // Probably the easiest way to get elements position without including transform\t\t\n            do {\t\t\n               offsetLeft += el.offsetLeft;\t\t\n               offsetTop  += el.offsetTop;\t\t\n               el = el.offsetParent;\t\t\n            } while(el);\n\n            var stylesToSet = {\n                \"left\": offsetLeft + \"px\",\n                \"top\": offsetTop + \"px\",\n                \"width\": innerWidth + \"px\",\n                \"height\": innerHeight + \"px\",\n                \"z-index\": 2000000,\n                \"margin\": 0,\n                \"padding\": 0,\n                \"position\": \"absolute\",\n                \"pointer-events\": \"none\",\n                \"box-shadow\": \"0 0 1px #fff\",\n                \"box-sizing\": elementStyling.getPropertyValue('box-sizing'),\t\t\n                \"border-right\": elementStyling.getPropertyValue('border-right'),\t\t\n                \"border-left\": elementStyling.getPropertyValue('border-left'),\t\t\n                \"border-top\": elementStyling.getPropertyValue('border-top'),\t\t\n                \"border-bottom\": elementStyling.getPropertyValue('border-bottom'),\t\t\n                \"transform\": elementStyling.getPropertyValue('transform'),\t\t\n                \"transform-origin\": elementStyling.getPropertyValue('transform-origin'),\t\t\n                \"border-color\": config.remoteHighlight.borderColor\n            };\n            \n            var mergedStyles = Object.assign({}, stylesToSet,  config.remoteHighlight.stylesToSet);\n\n            var animateStartValues = config.remoteHighlight.animateStartValue;\n\n            var animateEndValues = config.remoteHighlight.animateEndValue;\n\n            var transitionValues = {\n                \"transition-property\": \"opacity, background-color, transform\",\n                \"transition-duration\": \"300ms, 2.3s\"\n            };\n\n            function _setStyleValues(styleValues, obj) {\n                var prop;\n\n                for (prop in styleValues) {\n                    obj.setProperty(prop, styleValues[prop]);\n                }\n            }\n\n            _setStyleValues(mergedStyles, highlight.style);\n            _setStyleValues(\n                doAnimation ? animateStartValues : animateEndValues,\n                highlight.style\n            );\n\n\n            if (doAnimation) {\n                _setStyleValues(transitionValues, highlight.style);\n\n                window.setTimeout(function () {\n                    _setStyleValues(animateEndValues, highlight.style);\n                }, 20);\n            }\n\n            window.document.body.appendChild(highlight);\n        },\n\n        add: function (element, doAnimation) {\n            if (this._elementExists(element) || element === window.document) {\n                return;\n            }\n            if (this.trigger) {\n                _trigger(element, \"highlight\", 1);\n            }\n            \n            if ((!window.event || window.event instanceof MessageEvent) && !isInViewport(element)) {\n                var top = getDocumentOffsetTop(element);\n                if (top) {\n                    top -= (window.innerHeight / 2);\n                    window.scrollTo(0, top);\n                }\n            }\n            this.elements.push(element);\n\n            this._makeHighlightDiv(element, doAnimation);\n        },\n\n        clear: function () {\n            var i, highlights = window.document.querySelectorAll(\".\" + HIGHLIGHT_CLASSNAME),\n                body = window.document.body;\n\n            for (i = 0; i < highlights.length; i++) {\n                body.removeChild(highlights[i]);\n            }\n\n            if (this.trigger) {\n                for (i = 0; i < this.elements.length; i++) {\n                    _trigger(this.elements[i], \"highlight\", 0);\n                }\n            }\n\n            this.elements = [];\n        },\n\n        redraw: function () {\n            var i, highlighted;\n\n            // When redrawing a selector-based highlight, run a new selector\n            // query to ensure we have the latest set of elements to highlight.\n            if (this.selector) {\n                highlighted = window.document.querySelectorAll(this.selector);\n            } else {\n                highlighted = this.elements.slice(0);\n            }\n\n            this.clear();\n            for (i = 0; i < highlighted.length; i++) {\n                this.add(highlighted[i], false);\n            }\n        }\n    };\n\n    var _currentEditor;\n    function _toggleEditor(element) {\n        _currentEditor = new Editor(element);\n    }\n\n    var _currentMenu;\n    function _toggleMenu(element) {\n        if (_currentMenu) {\n            _currentMenu.remove();\n        }\n        _currentMenu = new Menu(element);\n    }\n\n    var _localHighlight;\n    var _remoteHighlight;\n    var _setup = false;\n\n\n    /** Event Handlers ***********************************************************/\n\n    function onMouseOver(event) {\n        if (_validEvent(event)) {\n            _localHighlight.add(event.target, true);\n        }\n    }\n\n    function onMouseOut(event) {\n        if (_validEvent(event)) {\n            _localHighlight.clear();\n        }\n    }\n\n    function onMouseMove(event) {\n        onMouseOver(event);\n        window.document.removeEventListener(\"mousemove\", onMouseMove);\n    }\n\n    function onClick(event) {\n        if (_validEvent(event)) {\n            event.preventDefault();\n            event.stopPropagation();\n            if (event.altKey) {\n                _toggleEditor(event.target);\n            } else {\n                _toggleMenu(event.target);\n            }\n        }\n    }\n\n    function onKeyUp(event) {\n        if (_setup && !_validEvent(event)) {\n            window.document.removeEventListener(\"keyup\", onKeyUp);\n            window.document.removeEventListener(\"mouseover\", onMouseOver);\n            window.document.removeEventListener(\"mouseout\", onMouseOut);\n            window.document.removeEventListener(\"mousemove\", onMouseMove);\n            window.document.removeEventListener(\"click\", onClick);\n            _localHighlight.clear();\n            _localHighlight = undefined;\n            _setup = false;\n        }\n    }\n\n    function onKeyDown(event) {\n        if (!_setup && _validEvent(event)) {\n            window.document.addEventListener(\"keyup\", onKeyUp);\n            window.document.addEventListener(\"mouseover\", onMouseOver);\n            window.document.addEventListener(\"mouseout\", onMouseOut);\n            window.document.addEventListener(\"mousemove\", onMouseMove);\n            window.document.addEventListener(\"click\", onClick);\n            _localHighlight = new Highlight(\"#ecc\", true);\n            _setup = true;\n        }\n    }\n\n    /** Public Commands **********************************************************/\n\n    // keep alive. Called once a second when a Live Development connection is active.\n    // If several seconds have passed without this method being called, we can assume\n    // that the connection has been severed and we should remove all our code/hooks.\n    function keepAlive() {\n        lastKeepAliveTime = Date.now();\n    }\n\n    // show goto\n    function showGoto(targets) {\n        if (!_currentMenu) {\n            return;\n        }\n        _currentMenu.createBody();\n        var i;\n        for (i in targets) {\n            _currentMenu.addItem(targets[i]);\n        }\n        _currentMenu.show();\n    }\n\n    // remove active highlights\n    function hideHighlight() {\n        if (_remoteHighlight) {\n            _remoteHighlight.clear();\n            _remoteHighlight = null;\n        }\n    }\n\n    // highlight a node\n    function highlight(node, clear) {\n        if (!_remoteHighlight) {\n            _remoteHighlight = new Highlight(\"#cfc\");\n        }\n        if (clear) {\n            _remoteHighlight.clear();\n        }\n        _remoteHighlight.add(node, true);\n    }\n\n    // highlight a rule\n    function highlightRule(rule) {\n        hideHighlight();\n        var i, nodes = window.document.querySelectorAll(rule);\n        for (i = 0; i < nodes.length; i++) {\n            highlight(nodes[i]);\n        }\n        _remoteHighlight.selector = rule;\n    }\n\n    // redraw active highlights\n    function redrawHighlights() {\n        if (_remoteHighlight) {\n            _remoteHighlight.redraw();\n        }\n    }\n\n    window.addEventListener(\"resize\", redrawHighlights);\n    // Add a capture-phase scroll listener to update highlights when\n    // any element scrolls.\n\n    function _scrollHandler(e) {\n        // Document scrolls can be updated immediately. Any other scrolls\n        // need to be updated on a timer to ensure the layout is correct.\n        if (e.target === window.document) {\n            redrawHighlights();\n        } else {\n            if (_remoteHighlight || _localHighlight) {\n                window.setTimeout(redrawHighlights, 0);\n            }\n        }\n    }\n\n    window.addEventListener(\"scroll\", _scrollHandler, true);\n\n    var aliveTest = window.setInterval(function () {\n        if (Date.now() > lastKeepAliveTime + KEEP_ALIVE_TIMEOUT) {\n            // Remove highlights\n            hideHighlight();\n\n            // Remove listeners\n            window.removeEventListener(\"resize\", redrawHighlights);\n            window.removeEventListener(\"scroll\", _scrollHandler, true);\n\n            // Clear this interval\n            window.clearInterval(aliveTest);\n        }\n    }, 1000);\n\n    /**\n     * Constructor\n     * @param {Document} htmlDocument\n     */\n    function DOMEditHandler(htmlDocument) {\n        this.htmlDocument = htmlDocument;\n        this.rememberedNodes = null;\n        this.entityParseParent = htmlDocument.createElement(\"div\");\n    }\n\n    /**\n     * @private\n     * Find the first matching element with the specified data-brackets-id\n     * @param {string} id\n     * @return {Element}\n     */\n    DOMEditHandler.prototype._queryBracketsID = function (id) {\n        if (!id) {\n            return null;\n        }\n\n        if (this.rememberedNodes && this.rememberedNodes[id]) {\n            return this.rememberedNodes[id];\n        }\n\n        var results = this.htmlDocument.querySelectorAll(\"[data-brackets-id='\" + id + \"']\");\n        return results && results[0];\n    };\n\n    /**\n     * @private\n     * Insert a new child element\n     * @param {Element} targetElement Parent element already in the document\n     * @param {Element} childElement New child element\n     * @param {Object} edit\n     */\n    DOMEditHandler.prototype._insertChildNode = function (targetElement, childElement, edit) {\n        var before = this._queryBracketsID(edit.beforeID),\n            after  = this._queryBracketsID(edit.afterID);\n\n        if (edit.firstChild) {\n            before = targetElement.firstChild;\n        } else if (edit.lastChild) {\n            after = targetElement.lastChild;\n        }\n\n        if (before) {\n            targetElement.insertBefore(childElement, before);\n        } else if (after && (after !== targetElement.lastChild)) {\n            targetElement.insertBefore(childElement, after.nextSibling);\n        } else {\n            targetElement.appendChild(childElement);\n        }\n    };\n\n    /**\n     * @private\n     * Given a string containing encoded entity references, returns the string with the entities decoded.\n     * @param {string} text The text to parse.\n     * @return {string} The decoded text.\n     */\n    DOMEditHandler.prototype._parseEntities = function (text) {\n        // Kind of a hack: just set the innerHTML of a div to the text, which will parse the entities, then\n        // read the content out.\n        var result;\n        this.entityParseParent.innerHTML = text;\n        result = this.entityParseParent.textContent;\n        this.entityParseParent.textContent = \"\";\n        return result;\n    };\n\n    /**\n     * @private\n     * @param {Node} node\n     * @return {boolean} true if node expects its content to be raw text (not parsed for entities) according to the HTML5 spec.\n     */\n    function _isRawTextNode(node) {\n        return (node.nodeType === Node.ELEMENT_NODE && /script|style|noscript|noframes|noembed|iframe|xmp/i.test(node.tagName));\n    }\n\n    /**\n     * @private\n     * Replace a range of text and comment nodes with an optional new text node\n     * @param {Element} targetElement\n     * @param {Object} edit\n     */\n    DOMEditHandler.prototype._textReplace = function (targetElement, edit) {\n        function prevIgnoringHighlights(node) {\n            do {\n                node = node.previousSibling;\n            } while (node && node.className === HIGHLIGHT_CLASSNAME);\n            return node;\n        }\n        function nextIgnoringHighlights(node) {\n            do {\n                node = node.nextSibling;\n            } while (node && node.className === HIGHLIGHT_CLASSNAME);\n            return node;\n        }\n        function lastChildIgnoringHighlights(node) {\n            node = (node.childNodes.length ? node.childNodes.item(node.childNodes.length - 1) : null);\n            if (node && node.className === HIGHLIGHT_CLASSNAME) {\n                node = prevIgnoringHighlights(node);\n            }\n            return node;\n        }\n\n        var start           = (edit.afterID)  ? this._queryBracketsID(edit.afterID)  : null,\n            startMissing    = edit.afterID && !start,\n            end             = (edit.beforeID) ? this._queryBracketsID(edit.beforeID) : null,\n            endMissing      = edit.beforeID && !end,\n            moveNext        = start && nextIgnoringHighlights(start),\n            current         = moveNext || (end && prevIgnoringHighlights(end)) || lastChildIgnoringHighlights(targetElement),\n            next,\n            textNode        = (edit.content !== undefined) ? this.htmlDocument.createTextNode(_isRawTextNode(targetElement) ? edit.content : this._parseEntities(edit.content)) : null,\n            lastRemovedWasText,\n            isText;\n\n        // remove all nodes inside the range\n        while (current && (current !== end)) {\n            isText = current.nodeType === Node.TEXT_NODE;\n\n            // if start is defined, delete following text nodes\n            // if start is not defined, delete preceding text nodes\n            next = (moveNext) ? nextIgnoringHighlights(current) : prevIgnoringHighlights(current);\n\n            // only delete up to the nearest element.\n            // if the start/end tag was deleted in a prior edit, stop removing\n            // nodes when we hit adjacent text nodes\n            if ((current.nodeType === Node.ELEMENT_NODE) ||\n                    ((startMissing || endMissing) && (isText && lastRemovedWasText))) {\n                break;\n            } else {\n                lastRemovedWasText = isText;\n\n                if (current.remove) {\n                    current.remove();\n                } else if (current.parentNode && current.parentNode.removeChild) {\n                    current.parentNode.removeChild(current);\n                }\n                current = next;\n            }\n        }\n\n        if (textNode) {\n            // OK to use nextSibling here (not nextIgnoringHighlights) because we do literally\n            // want to insert immediately after the start tag.\n            if (start && start.nextSibling) {\n                targetElement.insertBefore(textNode, start.nextSibling);\n            } else if (end) {\n                targetElement.insertBefore(textNode, end);\n            } else {\n                targetElement.appendChild(textNode);\n            }\n        }\n    };\n\n    /**\n     * @private\n     * Apply an array of DOM edits to the document\n     * @param {Array.<Object>} edits\n     */\n    DOMEditHandler.prototype.apply = function (edits) {\n        var targetID,\n            targetElement,\n            childElement,\n            self = this;\n\n        this.rememberedNodes = {};\n\n        edits.forEach(function (edit) {\n            var editIsSpecialTag = edit.type === \"elementInsert\" && (edit.tag === \"html\" || edit.tag === \"head\" || edit.tag === \"body\");\n\n            if (edit.type === \"rememberNodes\") {\n                edit.tagIDs.forEach(function (tagID) {\n                    var node = self._queryBracketsID(tagID);\n                    self.rememberedNodes[tagID] = node;\n                    if (node.remove) {\n                        node.remove();\n                    } else if (node.parentNode && node.parentNode.removeChild) {\n                        node.parentNode.removeChild(node);\n                    }\n                });\n                return;\n            }\n\n            targetID = edit.type.match(/textReplace|textDelete|textInsert|elementInsert|elementMove/) ? edit.parentID : edit.tagID;\n            targetElement = self._queryBracketsID(targetID);\n\n            if (!targetElement && !editIsSpecialTag) {\n                console.error(\"data-brackets-id=\" + targetID + \" not found\");\n                return;\n            }\n\n            switch (edit.type) {\n            case \"attrChange\":\n            case \"attrAdd\":\n                targetElement.setAttribute(edit.attribute, self._parseEntities(edit.value));\n                break;\n            case \"attrDelete\":\n                targetElement.removeAttribute(edit.attribute);\n                break;\n            case \"elementDelete\":\n                if (targetElement.remove) {\n                    targetElement.remove();\n                } else if (targetElement.parentNode && targetElement.parentNode.removeChild) {\n                    targetElement.parentNode.removeChild(targetElement);\n                }\n                break;\n            case \"elementInsert\":\n                childElement = null;\n                if (editIsSpecialTag) {\n                    // If we already have one of these elements (which we should), then\n                    // just copy the attributes and set the ID.\n                    childElement = self.htmlDocument[edit.tag === \"html\" ? \"documentElement\" : edit.tag];\n                    if (!childElement) {\n                        // Treat this as a normal insertion.\n                        editIsSpecialTag = false;\n                    }\n                }\n                if (!editIsSpecialTag) {\n                    childElement = self.htmlDocument.createElement(edit.tag);\n                }\n\n                Object.keys(edit.attributes).forEach(function (attr) {\n                    childElement.setAttribute(attr, self._parseEntities(edit.attributes[attr]));\n                });\n                childElement.setAttribute(\"data-brackets-id\", edit.tagID);\n\n                if (!editIsSpecialTag) {\n                    self._insertChildNode(targetElement, childElement, edit);\n                }\n                break;\n            case \"elementMove\":\n                childElement = self._queryBracketsID(edit.tagID);\n                self._insertChildNode(targetElement, childElement, edit);\n                break;\n            case \"textInsert\":\n                var textElement = self.htmlDocument.createTextNode(_isRawTextNode(targetElement) ? edit.content : self._parseEntities(edit.content));\n                self._insertChildNode(targetElement, textElement, edit);\n                break;\n            case \"textReplace\":\n            case \"textDelete\":\n                self._textReplace(targetElement, edit);\n                break;\n            }\n        });\n\n        this.rememberedNodes = {};\n\n        // update highlight after applying diffs\n        redrawHighlights();\n    };\n\n    function applyDOMEdits(edits) {\n        _editHandler.apply(edits);\n    }\n\n    /**\n     *\n     * @param {Element} elem\n     */\n    function _domElementToJSON(elem) {\n        var json = { tag: elem.tagName.toLowerCase(), attributes: {}, children: [] },\n            i,\n            len,\n            node,\n            value;\n\n        len = elem.attributes.length;\n        for (i = 0; i < len; i++) {\n            node = elem.attributes.item(i);\n            value = (node.name === \"data-brackets-id\") ? parseInt(node.value, 10) : node.value;\n            json.attributes[node.name] = value;\n        }\n\n        len = elem.childNodes.length;\n        for (i = 0; i < len; i++) {\n            node = elem.childNodes.item(i);\n\n            // ignores comment nodes and visuals generated by live preview\n            if (node.nodeType === Node.ELEMENT_NODE && node.className !== HIGHLIGHT_CLASSNAME) {\n                json.children.push(_domElementToJSON(node));\n            } else if (node.nodeType === Node.TEXT_NODE) {\n                json.children.push({ content: node.nodeValue });\n            }\n        }\n\n        return json;\n    }\n\n    function getSimpleDOM() {\n        return JSON.stringify(_domElementToJSON(window.document.documentElement));\n    }\n    \n    function updateConfig(newConfig) {\n        config = JSON.parse(newConfig);\n        return JSON.stringify(config);\n    }\n\n    // init\n    _editHandler = new DOMEditHandler(window.document);\n\n    if (experimental) {\n        window.document.addEventListener(\"keydown\", onKeyDown);\n    }\n    \n    var _ws = null;\n\n    function onDocumentClick(event) {\n        var element = event.target,\n            currentDataId,\n            newDataId;\n        \n        if (_ws && element && element.hasAttribute('data-brackets-id')) {\n            _ws.send(JSON.stringify({\n                type: \"message\",\n                message: element.getAttribute('data-brackets-id')\n            }));\n        }\n    }\n    \n    \n    function createWebSocket() {\n        _ws = new WebSocket(\"ws://localhost:\" + remoteWSPort);\n        _ws.onopen = function () {\n            window.document.addEventListener(\"click\", onDocumentClick);\n        };\n                \n        _ws.onmessage = function (evt) {\n        };\n                \n        _ws.onclose = function () {\n            // websocket is closed\n            window.document.removeEventListener(\"click\", onDocumentClick);\n        };\n    }\n    \n    if (remoteWSPort) {\n        createWebSocket();\n    }\n    \n    return {\n        \"DOMEditHandler\"        : DOMEditHandler,\n        \"keepAlive\"             : keepAlive,\n        \"showGoto\"              : showGoto,\n        \"hideHighlight\"         : hideHighlight,\n        \"highlight\"             : highlight,\n        \"highlightRule\"         : highlightRule,\n        \"redrawHighlights\"      : redrawHighlights,\n        \"applyDOMEdits\"         : applyDOMEdits,\n        \"getSimpleDOM\"          : getSimpleDOM,\n        \"updateConfig\"          : updateConfig\n    };\n}\n"
  },
  {
    "path": "src/LiveDevelopment/Agents/ScriptAgent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * ScriptAgent tracks all executed scripts, defines internal breakpoints, and\n * interfaces with the remote debugger.\n */\ndefine(function ScriptAgent(require, exports, module) {\n    \"use strict\";\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n\n    var _load; // the load promise\n    var _urlToScript; // url -> script info\n    var _idToScript; // id -> script info\n    var _insertTrace; // the last recorded trace of a DOM insertion\n\n    // TODO: should the parameter to this be an ID rather than a URL?\n    /** Get the script information for a given url\n     * @param {string} url\n     */\n    function scriptWithId(url) {\n        return _idToScript[url];\n    }\n\n    // TODO: Strip off query/hash strings from URL (see CSSAgent._canonicalize())\n    /** Get the script information for a given url\n     * @param {string} url\n     */\n    function scriptForURL(url) {\n        return _urlToScript[url];\n    }\n\n    // DOMAgent Event: Document root loaded\n    function _onGetDocument(event, res) {\n        Inspector.DOMDebugger.setDOMBreakpoint(res.root.nodeId, \"subtree-modified\");\n        _load.resolve();\n    }\n\n    // WebInspector Event: DOM.childNodeInserted\n    function _onChildNodeInserted(event, res) {\n        // res = {parentNodeId, previousNodeId, node}\n        if (_insertTrace) {\n            var node = DOMAgent.nodeWithId(res.node.nodeId);\n            node.trace = _insertTrace;\n            _insertTrace = undefined;\n        }\n    }\n\n    // TODO: Strip off query/hash strings from URL (see CSSAgent._canonicalize())\n    // WebInspector Event: Debugger.scriptParsed\n    function _onScriptParsed(event, res) {\n        // res = {scriptId, url, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL}\n        _idToScript[res.scriptId] = res;\n        _urlToScript[res.url] = res;\n    }\n\n    // WebInspector Event: Debugger.scriptFailedToParse\n    function _onScriptFailedToParse(event, res) {\n        // res = {url, scriptSource, startLine, errorLine, errorMessage}\n    }\n\n    // WebInspector Event: Debugger.paused\n    function _onPaused(event, res) {\n        // res = {callFrames, reason, data}\n        switch (res.reason) {\n\n        // Exception\n        case \"exception\":\n            Inspector.Debugger.resume();\n            // var callFrame = res.callFrames[0];\n            // var script = scriptWithId(callFrame.location.scriptId);\n            break;\n\n        // DOMBreakpoint\n        case \"DOM\":\n            Inspector.Debugger.resume();\n            if (res.data.type === \"subtree-modified\" && res.data.insertion === true) {\n                _insertTrace = res.callFrames;\n            }\n            break;\n        }\n\n    }\n\n    function _reset() {\n        _urlToScript = {};\n        _idToScript = {};\n    }\n\n    /**\n     * @private\n     * WebInspector Event: Page.frameNavigated\n     * @param {jQuery.Event} event\n     * @param {frame: Frame} res\n     */\n    function _onFrameNavigated(event, res) {\n        // Clear maps when navigating to a new page, but not if an iframe was loaded\n        if (!res.frame.parentId) {\n            _reset();\n        }\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _reset();\n        _load = new $.Deferred();\n\n        var enableResult = new $.Deferred();\n\n        Inspector.Debugger.enable().done(function () {\n            Inspector.Debugger.setPauseOnExceptions(\"uncaught\").done(function () {\n                enableResult.resolve();\n            });\n        });\n\n        Inspector.Page.on(\"frameNavigated.ScriptAgent\", _onFrameNavigated);\n        DOMAgent.on(\"getDocument.ScriptAgent\", _onGetDocument);\n        Inspector.Debugger\n            .on(\"scriptParsed.ScriptAgent\", _onScriptParsed)\n            .on(\"scriptFailedToParse.ScriptAgent\", _onScriptFailedToParse)\n            .on(\"paused.ScriptAgent\", _onPaused);\n        Inspector.DOM.on(\"childNodeInserted.ScriptAgent\", _onChildNodeInserted);\n\n        return $.when(_load.promise(), enableResult.promise());\n    }\n\n    /** Clean up */\n    function unload() {\n        _reset();\n        Inspector.Page.off(\".ScriptAgent\");\n        DOMAgent.off(\".ScriptAgent\");\n        Inspector.Debugger.off(\".ScriptAgent\");\n        Inspector.DOM.off(\".ScriptAgent\");\n    }\n\n    // Export public functions\n    exports.scriptWithId = scriptWithId;\n    exports.scriptForURL = scriptForURL;\n    exports.load = load;\n    exports.unload = unload;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Documents/CSSDocument.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint forin: true */\n\n/**\n * CSSDocument manages a single CSS source document\n *\n * __EDITING__\n *\n * Editing the document will cause the style sheet to be reloaded via the\n * CSSAgent, which immediately updates the appearance of the rendered document.\n *\n * __HIGHLIGHTING__\n *\n * CSSDocument supports highlighting nodes from the HighlightAgent and\n * highlighting all DOMNode corresponding to the rule at the cursor position\n * in the editor.\n *\n * __EVENTS__\n *\n * CSSDocument dispatches these events:\n *\n * - deleted -- When the file for the underlying Document has been deleted.\n *   The 2nd argument to the listener will be this CSSDocument.\n */\ndefine(function CSSDocumentModule(require, exports, module) {\n    \"use strict\";\n\n    var _               = require(\"thirdparty/lodash\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        CSSAgent        = require(\"LiveDevelopment/Agents/CSSAgent\"),\n        CSSUtils        = require(\"language/CSSUtils\"),\n        EditorManager   = require(\"editor/EditorManager\"),\n        HighlightAgent  = require(\"LiveDevelopment/Agents/HighlightAgent\"),\n        Inspector       = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    /**\n     * @constructor\n     * @param {!Document} doc The source document from Brackets\n     * @param {!Editor} editor The editor for this document\n     */\n    var CSSDocument = function CSSDocument(doc, editor) {\n        this.doc = doc;\n\n        this._highlight = [];\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n\n        // Add a ref to the doc since we're listening for change events\n        this.doc.addRef();\n        this.onChange = this.onChange.bind(this);\n        this.onDeleted = this.onDeleted.bind(this);\n\n        this.doc.on(\"change.CSSDocument\", this.onChange);\n        this.doc.on(\"deleted.CSSDocument\", this.onDeleted);\n\n        this.onActiveEditorChange = this.onActiveEditorChange.bind(this);\n        EditorManager.on(\"activeEditorChange\", this.onActiveEditorChange);\n\n        if (editor) {\n            // Attach now\n            this.attachToEditor(editor);\n        }\n    };\n    EventDispatcher.makeEventDispatcher(CSSDocument.prototype);\n\n    /**\n     * @private\n     * Get the CSSStyleSheetHeader for this document\n     */\n    CSSDocument.prototype._getStyleSheetHeader = function () {\n        return CSSAgent.styleForURL(this.doc.url);\n    };\n\n    /**\n     * Get the browser version of the source\n     * @return {jQuery.promise} Promise resolved with the text content of this CSS document\n     */\n    CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() {\n        function getOnlyValue(obj) {\n            var key;\n            for (key in obj) {\n                if (_.has(obj, key)) {\n                    return obj[key];\n                }\n            }\n            return null;\n        }\n\n        var deferred = new $.Deferred(),\n            styleSheetHeader = this._getStyleSheetHeader(),\n            styleSheet = getOnlyValue(styleSheetHeader);\n\n        if (styleSheet) {\n            Inspector.CSS.getStyleSheetText(styleSheet.styleSheetId).then(function (res) {\n                deferred.resolve(res.text);\n            }, deferred.reject);\n        } else {\n            deferred.reject();\n        }\n\n        return deferred.promise();\n    };\n\n    /** Close the document */\n    CSSDocument.prototype.close = function close() {\n        this.doc.off(\".CSSDocument\");\n        EditorManager.off(\"activeEditorChange\", this.onActiveEditorChange);\n        this.doc.releaseRef();\n        this.detachFromEditor();\n    };\n\n    /**\n     * @private\n     * Update the style sheet text content and redraw highlights\n     */\n    CSSDocument.prototype._updateBrowser = function () {\n        var reloadPromise = CSSAgent.reloadCSSForDocument(this.doc);\n\n        if (Inspector.config.highlight) {\n            reloadPromise.done(HighlightAgent.redraw);\n        }\n    };\n\n    CSSDocument.prototype.attachToEditor = function (editor) {\n        this.editor = editor;\n\n        if (this.editor) {\n            HighlightAgent.on(\"highlight\", this.onHighlight);\n            this.editor.on(\"cursorActivity.CSSDocument\", this.onCursorActivity);\n            this.updateHighlight();\n        }\n    };\n\n    CSSDocument.prototype.detachFromEditor = function () {\n        if (this.editor) {\n            HighlightAgent.hide();\n            HighlightAgent.off(\"highlight\", this.onHighlight);\n            this.editor.off(\".CSSDocument\");\n            this.onHighlight();\n            this.editor = null;\n        }\n    };\n\n    CSSDocument.prototype.updateHighlight = function () {\n        if (Inspector.config.highlight && this.editor) {\n            var editor = this.editor,\n                selectors = [];\n            _.each(this.editor.getSelections(), function (sel) {\n                var selector = CSSUtils.findSelectorAtDocumentPos(editor, (sel.reversed ? sel.end : sel.start));\n                if (selector) {\n                    selectors.push(selector);\n                }\n            });\n            if (selectors.length) {\n                HighlightAgent.rule(selectors.join(\",\"));\n            } else {\n                HighlightAgent.hide();\n            }\n        }\n    };\n\n    /**\n     * Enable instrumented CSS\n     * @param enabled {boolean}\n     */\n    CSSDocument.prototype.setInstrumentationEnabled = function setInstrumentationEnabled(enabled) {\n        // no-op\n        // \"Instrumentation\" is always enabled for CSS, we make no modifications\n    };\n\n    /**\n     * Returns true if document edits appear live in the connected browser\n     * @return {boolean}\n     */\n    CSSDocument.prototype.isLiveEditingEnabled = function () {\n        return true;\n    };\n\n    /**\n     * Returns a JSON object with HTTP response overrides\n     * @return {{body: string}}\n     */\n    CSSDocument.prototype.getResponseData = function getResponseData(enabled) {\n        // Serve up the in-memory text, including any unsaved changes\n        return {\n            body: this.doc.getText()\n        };\n    };\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity of the editor */\n    CSSDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n        this.updateHighlight();\n    };\n\n    /** Triggered whenever the Document is edited */\n    CSSDocument.prototype.onChange = function onChange(event, editor, change) {\n        this._updateBrowser();\n    };\n\n    /** Triggered if the Document's file is deleted */\n    CSSDocument.prototype.onDeleted = function onDeleted(event, editor, change) {\n        // clear the CSS\n        CSSAgent.clearCSSForDocument(this.doc);\n\n        // shut down, since our Document is now dead\n        this.close();\n        this.trigger(\"deleted\", this);\n    };\n\n    /** Triggered when the active editor changes */\n    CSSDocument.prototype.onActiveEditorChange = function (event, newActive, oldActive) {\n        this.detachFromEditor();\n\n        if (newActive && newActive.document === this.doc) {\n            this.attachToEditor(newActive);\n        }\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    CSSDocument.prototype.onHighlight = function onHighlight(event, node) {\n        // clear an existing highlight\n        var i;\n        for (i in this._highlight) {\n            this._highlight[i].clear();\n        }\n        this._highlight = [];\n        if (!node || !node.location) {\n            return;\n        }\n\n        // WebInspector Command: CSS.getMatchedStylesForNode\n        Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) {\n            // res = {matchedCSSRules, pseudoElements, inherited}\n            var codeMirror = this.editor._codeMirror,\n                styleSheetIds = this._getStyleSheetHeader();\n\n            var i, rule, from, to;\n            for (i in res.matchedCSSRules) {\n                rule = res.matchedCSSRules[i];\n                if (rule.ruleId && styleSheetIds[rule.ruleId.styleSheetId]) {\n                    from = codeMirror.posFromIndex(rule.selectorRange.start);\n                    to = codeMirror.posFromIndex(rule.style.range.end);\n                    this._highlight.push(codeMirror.markText(from, to, { className: \"highlight\" }));\n                }\n            }\n        }.bind(this));\n    };\n\n    // Export the class\n    module.exports = CSSDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Documents/CSSPreprocessorDocument.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * CSSPreprocessorDocument manages a single LESS or SASS source document\n *\n * __HIGHLIGHTING__\n *\n * CSSPreprocessorDocument supports highlighting all DOMNode corresponding to the rule at\n * the cursor position in the editor.\n *\n */\ndefine(function CSSPreprocessorDocumentModule(require, exports, module) {\n    \"use strict\";\n\n    var _               = require(\"thirdparty/lodash\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        CSSUtils        = require(\"language/CSSUtils\"),\n        EditorManager   = require(\"editor/EditorManager\"),\n        HighlightAgent  = require(\"LiveDevelopment/Agents/HighlightAgent\"),\n        Inspector       = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    /**\n     * @constructor\n     * @param {!Document} doc The source document from Brackets\n     * @param {?Editor} editor The editor for this document. This is not used here since\n     *                  we always need to get the active editor for a preprocessor document\n     *                  and not the one passed in `editor`.\n     */\n    var CSSPreprocessorDocument = function CSSPreprocessorDocument(doc, editor) {\n        this.doc = doc;\n\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n\n        // Add a ref to the doc since we're listening for change events\n        this.doc.addRef();\n        this.onActiveEditorChange = this.onActiveEditorChange.bind(this);\n        EditorManager.on(\"activeEditorChange\", this.onActiveEditorChange);\n        this.onActiveEditorChange(null, EditorManager.getActiveEditor(), null);\n    };\n\n    // CSSPreprocessorDocument doesn't dispatch events, but the \"live document\" interface requires an on() API\n    EventDispatcher.makeEventDispatcher(CSSPreprocessorDocument.prototype);\n\n    /** Close the document */\n    CSSPreprocessorDocument.prototype.close = function close() {\n        this.doc.off(\".CSSPreprocessorDocument\");\n        EditorManager.off(\"activeEditorChange\", this.onActiveEditorChange);\n        this.doc.releaseRef();\n        this.detachFromEditor();\n    };\n\n    /** Return false so edits cause \"out of sync\" icon to appear */\n    CSSPreprocessorDocument.prototype.isLiveEditingEnabled = function () {\n        // Normally this isn't called since wasURLRequested() returns false for us, but if user's\n        // page uses less.js to dynamically load LESS files, then it'll be true and we'll get called.\n        return false;\n    };\n\n    CSSPreprocessorDocument.prototype.attachToEditor = function (editor) {\n        this.editor = editor;\n\n        if (this.editor) {\n            this.editor.on(\"cursorActivity.CSSPreprocessorDocument\", this.onCursorActivity);\n            this.updateHighlight();\n        }\n    };\n\n    CSSPreprocessorDocument.prototype.detachFromEditor = function () {\n        if (this.editor) {\n            HighlightAgent.hide();\n            this.editor.off(\".CSSPreprocessorDocument\");\n            this.editor = null;\n        }\n    };\n\n    CSSPreprocessorDocument.prototype.updateHighlight = function () {\n        if (Inspector.config.highlight && this.editor) {\n            var editor = this.editor,\n                selectors = [];\n            _.each(this.editor.getSelections(), function (sel) {\n                var selector = CSSUtils.findSelectorAtDocumentPos(editor, (sel.reversed ? sel.end : sel.start));\n                if (selector) {\n                    selectors.push(selector);\n                }\n            });\n            if (selectors.length) {\n                HighlightAgent.rule(selectors.join(\",\"));\n            } else {\n                HighlightAgent.hide();\n            }\n        }\n    };\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity of the editor */\n    CSSPreprocessorDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n        this.updateHighlight();\n    };\n\n    /** Triggered when the active editor changes */\n    CSSPreprocessorDocument.prototype.onActiveEditorChange = function (event, newActive, oldActive) {\n        this.detachFromEditor();\n\n        if (newActive && newActive.document === this.doc) {\n            this.attachToEditor(newActive);\n        }\n    };\n\n    // Export the class\n    module.exports = CSSPreprocessorDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Documents/HTMLDocument.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * HTMLDocument manages a single HTML source document\n *\n * __EDITING__\n *\n * Editing the document will cause the corresponding node to be updated\n * by calling `applyChanges` on the DOMAgent. This will only work for\n * altering text nodes and will break when attempting to change DOM elements\n * or inserting or deleting nodes.\n *\n * __HIGHLIGHTING__\n *\n * HTMLDocument supports highlighting nodes from the HighlightAgent and\n * highlighting the DOMNode corresponding to the cursor position in the\n * editor.\n */\ndefine(function HTMLDocumentModule(require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = require(\"editor/EditorManager\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        HighlightAgent      = require(\"LiveDevelopment/Agents/HighlightAgent\"),\n        HTMLInstrumentation = require(\"language/HTMLInstrumentation\"),\n        Inspector           = require(\"LiveDevelopment/Inspector/Inspector\"),\n        LiveDevelopment     = require(\"LiveDevelopment/LiveDevelopment\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        RemoteAgent         = require(\"LiveDevelopment/Agents/RemoteAgent\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    /**\n     * @constructor\n     * @param {!Document} doc The source document from Brackets\n     * @param {!Editor} editor The editor for this document\n     */\n    var HTMLDocument = function HTMLDocument(doc, editor) {\n        this.doc = doc;\n        if (this.doc) {\n            this.doc.addRef();\n        }\n\n        this.editor = editor;\n        this._instrumentationEnabled = false;\n\n        this._onActiveEditorChange = this._onActiveEditorChange.bind(this);\n        EditorManager.on(\"activeEditorChange\", this._onActiveEditorChange);\n\n        // Attach now\n        this.attachToEditor(editor);\n    };\n    EventDispatcher.makeEventDispatcher(HTMLDocument.prototype);\n\n    /**\n     * Enable or disable instrumented HTML\n     * @param {boolean} enabled Whether to enable or disable\n     */\n    HTMLDocument.prototype.setInstrumentationEnabled = function setInstrumentationEnabled(enabled) {\n        if (enabled && !this._instrumentationEnabled && this.editor) {\n            HTMLInstrumentation.scanDocument(this.doc);\n            HTMLInstrumentation._markText(this.editor);\n        }\n\n        this._instrumentationEnabled = enabled;\n    };\n\n    /**\n     * Returns true if document edits appear live in the connected browser\n     * @return {boolean}\n     */\n    HTMLDocument.prototype.isLiveEditingEnabled = function () {\n        return this._instrumentationEnabled;\n    };\n\n    /**\n     * Returns a JSON object with HTTP response overrides\n     * @param {boolean} enabled (Unused)\n     * @return {{body: string}}\n     */\n    HTMLDocument.prototype.getResponseData = function getResponseData(enabled) {\n        var body;\n        if (this._instrumentationEnabled) {\n            if (this.editor) {\n                body = HTMLInstrumentation.generateInstrumentedHTML(this.editor);\n            } else {\n                this.doc._ensureMasterEditor();\n                body = HTMLInstrumentation.generateInstrumentedHTML(this.doc._masterEditor);\n            }\n        }\n\n        return {\n            body: body || this.doc.getText()\n        };\n    };\n\n    /**\n     * Close the document\n     */\n    HTMLDocument.prototype.close = function close() {\n        if (this.editor) {\n            this.editor.off(\".HTMLDocument\");\n        }\n\n        if (this.doc) {\n            this.doc.releaseRef();\n        }\n\n        EditorManager.off(\"activeEditorChange\", this._onActiveEditorChange);\n\n        // Experimental code\n        if (LiveDevelopment.config.experimental) {\n            // Force highlight teardown\n            this._onHighlight();\n        }\n    };\n\n    /**\n     * Attach new editor\n     * @param {!Editor} editor The editor for this document\n     */\n    HTMLDocument.prototype.attachToEditor = function (editor) {\n        var self = this;\n        this.editor = editor;\n\n        // Performance optimization to use closures instead of Function.bind()\n        // to improve responsiveness during cursor movement and keyboard events\n        this.editor.on(\"cursorActivity.HTMLDocument\", function (event, editor) {\n            self._onCursorActivity(event, editor);\n        });\n\n        this.editor.on(\"change.HTMLDocument\", function (event, editor, change) {\n            self._onChange(event, editor, change);\n        });\n\n        this.editor.on(\"beforeDestroy.HTMLDocument\", function (event, editor) {\n            self._onDestroy(event, editor);\n        });\n\n        // Experimental code\n        if (LiveDevelopment.config.experimental) {\n            HighlightAgent.on(\"highlight.HTMLDocument\", function (event, node) {\n                self._onHighlight(event, node);\n            });\n        }\n\n        if (this._instrumentationEnabled) {\n            // Resync instrumentation with editor\n            HTMLInstrumentation._markText(this.editor);\n        }\n    };\n\n    /**\n     * Detach current editor\n     */\n    HTMLDocument.prototype.detachFromEditor = function () {\n        if (this.editor) {\n            HighlightAgent.hide();\n            this.editor.off(\".HTMLDocument\");\n            this._removeHighlight();\n            this.editor = null;\n        }\n    };\n\n    /**\n     * Update the highlight\n     */\n    HTMLDocument.prototype.updateHighlight = function () {\n        var editor = this.editor,\n            ids = [];\n\n        if (Inspector.config.highlight) {\n            if (editor) {\n                _.each(editor.getSelections(), function (sel) {\n                    var tagID = HTMLInstrumentation._getTagIDAtDocumentPos(\n                        editor,\n                        sel.reversed ? sel.end : sel.start\n                    );\n                    if (tagID !== -1) {\n                        ids.push(tagID);\n                    }\n                });\n            }\n\n            if (!ids.length) {\n                HighlightAgent.hide();\n            } else {\n                HighlightAgent.domElement(ids);\n            }\n        }\n    };\n\n    /** Event Handlers *******************************************************/\n\n    /**\n     * Triggered on cursor activity by the editor\n     * @param {$.Event} event Event\n     * @param {!Editor} editor The editor for this document\n     */\n    HTMLDocument.prototype._onCursorActivity = function (event, editor) {\n        if (this.editor !== editor) {\n            return;\n        }\n        this.updateHighlight();\n    };\n\n    /**\n     * @private\n     * For the given editor change, compare the resulting browser DOM with the\n     * in-editor DOM. If there are any diffs, a warning is logged to the\n     * console along with each diff.\n     * @param {Object} change CodeMirror editor change data\n     */\n    HTMLDocument.prototype._compareWithBrowser = function (change) {\n        var self = this;\n\n        RemoteAgent.call(\"getSimpleDOM\").done(function (res) {\n            var browserSimpleDOM = JSON.parse(res.result.value),\n                edits,\n                node,\n                result;\n\n            try {\n                result = HTMLInstrumentation._getBrowserDiff(self.editor, browserSimpleDOM);\n            } catch (err) {\n                console.error(\"Error comparing in-browser DOM to in-editor DOM\");\n                console.error(err.stack);\n                return;\n            }\n\n            edits = result.diff.filter(function (delta) {\n                // ignore textDelete in html root element\n                node = result.browser.nodeMap[delta.parentID];\n\n                if (node && node.tag === \"html\" && delta.type === \"textDelete\") {\n                    return false;\n                }\n\n                return true;\n            });\n\n            if (edits.length > 0) {\n                console.warn(\"Browser DOM does not match after change: \" + JSON.stringify(change));\n\n                edits.forEach(function (delta) {\n                    console.log(delta);\n                });\n            }\n        });\n    };\n\n    /**\n     * Triggered when the editor is being destroyed\n     * @param {$.Event} event Event\n     * @param {!Editor} editor The editor being destroyed\n     */\n    HTMLDocument.prototype._onDestroy = function (event, editor) {\n        if (this.editor === editor) {\n            this.detachFromEditor();\n        }\n    };\n\n\n    /**\n     * Triggered on change by the editor\n     * @param {$.Event} event Event\n     * @param {!Editor} editor The editor for this document\n     * @param {Object} change CodeMirror editor change data\n     */\n    HTMLDocument.prototype._onChange = function (event, editor, change) {\n        // Make sure LiveHTML is turned on\n        if (!this._instrumentationEnabled) {\n            return;\n        }\n\n        // Apply DOM edits is async, so previous PerfUtils timer may still be\n        // running. PerfUtils does not support running multiple timers with same\n        // name, so do not start another timer in this case.\n        var perfTimerName   = \"HTMLDocument applyDOMEdits\",\n            isNestedTimer   = PerfUtils.isActive(perfTimerName);\n        if (!isNestedTimer) {\n            PerfUtils.markStart(perfTimerName);\n        }\n\n        // Only handles attribute changes currently.\n        // TODO: text changes should be easy to add\n        // TODO: if new tags are added, need to instrument them\n        var self                = this,\n            result              = HTMLInstrumentation.getUnappliedEditList(editor, change),\n            applyEditsPromise;\n\n        if (result.edits) {\n            applyEditsPromise = RemoteAgent.call(\"applyDOMEdits\", result.edits);\n\n            applyEditsPromise.always(function () {\n                if (!isNestedTimer) {\n                    PerfUtils.addMeasurement(perfTimerName);\n                }\n            });\n        }\n\n        this.errors = result.errors || [];\n        this.trigger(\"statusChanged\", this);\n\n        // Debug-only: compare in-memory vs. in-browser DOM\n        // edit this file or set a conditional breakpoint at the top of this function:\n        //     \"this._debug = true, false\"\n        if (this._debug) {\n            console.log(\"Edits applied to browser were:\");\n            console.log(JSON.stringify(result.edits, null, 2));\n            applyEditsPromise.done(function () {\n                self._compareWithBrowser(change);\n            });\n        }\n\n//        var marker = HTMLInstrumentation._getMarkerAtDocumentPos(\n//            this.editor,\n//            editor.getCursorPos()\n//        );\n//\n//        if (marker && marker.tagID) {\n//            var range   = marker.find(),\n//                text    = marker.doc.getRange(range.from, range.to);\n//\n//            // HACK maintain ID\n//            text = text.replace(\">\", \" data-brackets-id='\" + marker.tagID + \"'>\");\n//\n//            // FIXME incorrectly replaces body elements with content only, missing body element\n//            RemoteAgent.remoteElement(marker.tagID).replaceWith(text);\n//        }\n\n        // if (!this.editor) {\n        //     return;\n        // }\n        // var codeMirror = this.editor._codeMirror;\n        // while (change) {\n        //     var from = codeMirror.indexFromPos(change.from);\n        //     var to = codeMirror.indexFromPos(change.to);\n        //     var text = change.text.join(\"\\n\");\n        //     DOMAgent.applyChange(from, to, text);\n        //     change = change.next;\n        // }\n    };\n\n    /**\n     * Triggered when the active editor changes\n     * @param {$.Event} event Event\n     * @param {!Editor} newActive The new active editor\n     * @param {!Editor} oldActive The old active editor\n     */\n    HTMLDocument.prototype._onActiveEditorChange = function (event, newActive, oldActive) {\n        this.detachFromEditor();\n\n        if (newActive && newActive.document === this.doc) {\n            this.attachToEditor(newActive);\n        }\n    };\n\n    /**\n     * Triggered by the HighlightAgent to highlight a node in the editor\n     * @param {$.Event} event Event\n     * @param {DOMElement} node Element to highlight\n     */\n    HTMLDocument.prototype._onHighlight = function (event, node) {\n        this._removeHighlight();\n        if (!node || !node.location || !this.editor) {\n            return;\n        }\n\n        var codeMirror = this.editor._codeMirror;\n        var to, from = codeMirror.posFromIndex(node.location);\n        if (node.closeLocation) {\n            to = node.closeLocation + node.closeLength;\n        } else {\n            to = node.location + node.length;\n        }\n\n        to = codeMirror.posFromIndex(to);\n        this._highlight = codeMirror.markText(from, to, { className: \"highlight\" });\n    };\n\n    /**\n     * Remove all highlighting\n     */\n    HTMLDocument.prototype._removeHighlight = function () {\n        if (this._highlight) {\n            this._highlight.clear();\n            this._highlight = null;\n        }\n    };\n\n    // Export the class\n    module.exports = HTMLDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Documents/JSDocument.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint forin: true */\n\n/**\n * JSDocument manages a single JavaScript source document\n *\n * __EDITING__\n *\n * Editing the document will cause the script to be reloaded via the\n * ScriptAgent, which updates the implementation of all functions without\n * loosing any state. To support redrawing canvases, jQuery must be loaded\n * and a rerender method must be attached to every canvas that clears and\n * renders the canvas.\n *\n * __HIGHLIGHTING__\n *\n * JSDocument supports highlighting nodes from the HighlightAgent. Support\n * for highlighting the nodes that were created / touched by the current\n * line is missing.\n */\ndefine(function JSDocumentModule(require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher = require(\"utils/EventDispatcher\"),\n        Inspector       = require(\"LiveDevelopment/Inspector/Inspector\"),\n        ScriptAgent     = require(\"LiveDevelopment/Agents/ScriptAgent\"),\n        HighlightAgent  = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /**\n     * @constructor\n     * @param {!Document} doc The source document from Brackets\n     * @param {!Editor} editor The editor for this document\n     */\n    var JSDocument = function JSDocument(doc, editor) {\n        if (!editor) {\n            return;\n        }\n        this.doc = doc;\n        this.editor = editor;\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onChange = this.onChange.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        HighlightAgent.on(\"highlight\", this.onHighlight);\n        this.editor.on(\"change\", this.onChange);\n        this.editor.on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n    };\n\n    // JSDocument doesn't dispatch events, but the \"live document\" interface requires having an on() API\n    EventDispatcher.makeEventDispatcher(JSDocument.prototype);\n\n    /** Close the document */\n    JSDocument.prototype.close = function close() {\n        if (!this.editor) {\n            return;\n        }\n        HighlightAgent.off(\"highlight\", this.onHighlight);\n        this.editor.off(\"change\", this.onChange);\n        this.editor.off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n    };\n\n    JSDocument.prototype.script = function script() {\n        return ScriptAgent.scriptForURL(this.doc.url);\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity by the editor */\n    JSDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n    };\n\n    /** Triggered on change by the editor */\n    JSDocument.prototype.onChange = function onChange(event, editor, change) {\n        var src = this.doc.getText();\n        Inspector.Debugger.setScriptSource(this.script().scriptId, src, function onSetScriptSource(res) {\n            Inspector.Runtime.evaluate(\"if($)$(\\\"canvas\\\").each(function(i,e){if(e.rerender)e.rerender()})\");\n        }.bind(this));\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    JSDocument.prototype.onHighlight = function onHighlight(event, node) {\n        // clear an existing highlight\n        var codeMirror = this.editor._codeMirror;\n        var i;\n        for (i in this._highlight) {\n            codeMirror.removeLineClass(this._highlight[i], \"wrap\", \"highlight\");\n        }\n        this._highlight = [];\n        if (!node || !node.trace) {\n            return;\n        }\n\n        // go through the trace and find highlight the lines of this script\n        var scriptId = this.script().scriptId;\n        var callFrame, line;\n        for (i in node.trace) {\n            callFrame = node.trace[i];\n            if (callFrame.location && callFrame.location.scriptId === scriptId) {\n                line = callFrame.location.lineNumber;\n                codeMirror.addLineClass(line, \"wrap\", \"highlight\");\n                this._highlight.push(line);\n            }\n        }\n    };\n\n    // Export the class\n    module.exports = JSDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Inspector/Inspector.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint forin: true */\n/*global FileError */\n\n /**\n * Inspector manages the connection to Chrome/Chromium's remote debugger.\n * See inspector.html for the documentation of the remote debugger.\n *\n * __SETUP__\n *\n * To enable remote debugging in Chrome or Chromium open either application\n * with the following parameters:\n *\n *     --enable-remote-debugger --remote-debugging-port=9222\n *\n * This will open an HTTP server on the specified port, which can be used to\n * browse the available remote debugger sessions. In general, every open\n * browser tab can host an individual remote debugger session. The\n * available interfaces can be exported by requesting:\n *\n *     http://127.0.0.1:9222/json\n *\n * The response is a JSON-formatted array that specifies all available remote\n * debugger sessions including the remote debugging web sockets.\n *\n * Inspector can connect directly to a web socket via `connect(socketURL)`, or\n * it can find the web socket that corresponds to the tab at the given URL and\n * connect to it via `connectToURL(url)`. The later returns a promise. To\n * disconnect use `disconnect()`.\n *\n * __EVENTS__\n *\n * Inspector dispatches several connectivity-related events + all remote debugger\n * events (see below). Event handlers are attached via `on(event, function)` and\n * detached via `off(event, function)`.\n *\n *   `connect`    Inspector did successfully connect to the remote debugger\n *   `disconnect` Inspector did disconnect from the remote debugger\n *   `error`      Inspector encountered an error\n *   `message`    Inspector received a message from the remote debugger - this\n *                provides a low-level entry point to remote debugger events\n *\n * __REMOTE DEBUGGER COMMANDS__\n *\n * Commands are executed by calling `{Domain}.{Command}()` with the parameters\n * specified in the order of the remote debugger documentation. These command\n * functions are generated automatically at runtime from Inspector.json. The\n * actual implementation of these functions is found in\n * `_send(method, signature, varargs)`, which verifies, serializes, and\n * transmits the command to the remote debugger. If the last parameter of any\n * command function call is a function, it will be used as the callback.\n *\n * __REMOTE DEBUGGER EVENTS__\n *\n * Debugger events are dispatched as regular events using {Domain}.{Event} as\n * the event name. The handler function will be called with a single parameter\n * that stores all returned values as an object.\n */\ndefine(function Inspector(require, exports, module) {\n    \"use strict\";\n\n    var Async           = require(\"utils/Async\"),\n        EventDispatcher = require(\"utils/EventDispatcher\");\n\n    /**\n     * Map message IDs to the callback function and original JSON message\n     * @type {Object.<number, {callback: function, message: Object}}\n     */\n    var _messageCallbacks = {};\n\n    var _messageId = 1,     // id used for remote method calls, auto-incrementing\n        _socket,            // remote debugger WebSocket\n        _connectDeferred,   // The deferred connect\n        _userAgent = \"\";    // user agent string\n\n    /** Check a parameter value against the given signature\n     * This only checks for optional parameters, not types\n     * Type checking is complex because of $ref and done on the remote end anyways\n     * @param {signature}\n     * @param {value}\n     */\n    function _verifySignature(signature, value) {\n        if (value === undefined) {\n            console.assert(signature.optional === true, \"Missing argument: \" + signature.name);\n        }\n        return true;\n    }\n\n    /** Send a message to the remote debugger\n     * All passed arguments after the signature are passed on as parameters.\n     * If the last argument is a function, it is used as the callback function.\n     * @param {string} remote method\n     * @param {object} the method signature\n     */\n    function _send(method, signature, varargs) {\n        if (!_socket) {\n            console.log(\"You must connect to the WebSocket before sending messages.\");\n\n            // FUTURE: Our current implementation closes and re-opens an inspector connection whenever\n            // a new HTML file is selected. If done quickly enough, pending requests from the previous\n            // connection could come in before the new socket connection is established. For now we\n            // simply ignore this condition.\n            // This race condition will go away once we support multiple inspector connections and turn\n            // off auto re-opening when a new HTML file is selected.\n            return (new $.Deferred()).reject().promise();\n        }\n\n        var id, callback, args, i, params = {}, promise, msg;\n\n        // extract the parameters, the callback function, and the message id\n        args = Array.prototype.slice.call(arguments, 2);\n        if (typeof args[args.length - 1] === \"function\") {\n            callback = args.pop();\n        } else {\n            var deferred = new $.Deferred();\n            promise = deferred.promise();\n            callback = function (result, error) {\n                if (error) {\n                    deferred.reject(error);\n                } else {\n                    deferred.resolve(result);\n                }\n            };\n        }\n\n        id = _messageId++;\n\n        // verify the parameters against the method signature\n        // this also constructs the params object of type {name -> value}\n        if (signature) {\n            for (i in signature) {\n                if (_verifySignature(args[i], signature[i])) {\n                    params[signature[i].name] = args[i];\n                }\n            }\n        }\n\n        // Store message callback and send message\n        msg = { method: method, id: id, params: params };\n        _messageCallbacks[id] = { callback: callback, message: msg };\n        _socket.send(JSON.stringify(msg));\n\n        return promise;\n    }\n\n    /**\n     * Manually send a message to the remote debugger\n     * All passed arguments after the command are passed on as parameters.\n     * If the last argument is a function, it is used as the callback function.\n     * @param {string} domain\n     * @param {string} command\n     */\n    function send(domain, command, varargs) {\n        return _send(domain + \".\" + command, null, varargs);\n    }\n\n    /** WebSocket did close */\n    function _onDisconnect() {\n        _socket = undefined;\n        exports.trigger(\"disconnect\");\n    }\n\n    /** WebSocket reported an error */\n    function _onError(error) {\n        if (_connectDeferred) {\n            _connectDeferred.reject();\n            _connectDeferred = null;\n        }\n        exports.trigger(\"error\", error);\n    }\n\n    /** WebSocket did open */\n    function _onConnect() {\n        if (_connectDeferred) {\n            _connectDeferred.resolve();\n            _connectDeferred = null;\n        }\n        exports.trigger(\"connect\");\n    }\n\n    /** Received message from the WebSocket\n     * A message can be one of three things:\n     *   1. an error -> report it\n     *   2. the response to a previous command -> run the stored callback\n     *   3. an event -> trigger an event handler method\n     * @param {object} message\n     */\n    function _onMessage(message) {\n        var response    = JSON.parse(message.data),\n            msgRecord   = _messageCallbacks[response.id],\n            callback    = msgRecord && msgRecord.callback,\n            msgText     = (msgRecord && msgRecord.message) || \"No message\";\n\n        if (msgRecord) {\n            // Messages with an ID are a response to a command, fire callback\n            callback(response.result, response.error);\n            delete _messageCallbacks[response.id];\n        } else if (response.method) {\n            // Messages with a method are an event, trigger event handlers\n            var domainAndMethod = response.method.split(\".\"),\n                domain = domainAndMethod[0],\n                method = domainAndMethod[1];\n\n            EventDispatcher.triggerWithArray(exports[domain], method, response.params);\n        }\n\n        // Always fire event handlers for all messages/errors\n        exports.trigger(\"message\", response);\n\n        if (response.error) {\n            exports.trigger(\"error\", response.error, msgText);\n        }\n    }\n\n\n    /** Public Functions *****************************************************/\n\n    /** Get a list of the available windows/tabs/extensions that are remote-debuggable\n     * @param {string} host IP or name\n     * @param {integer} debugger port\n     */\n    function getDebuggableWindows(host, port) {\n        if (!host) {\n            host = \"127.0.0.1\";\n        }\n        if (!port) {\n            port = 9222;\n        }\n        var def = new $.Deferred();\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"http://\" + host + \":\" + port + \"/json\");\n        request.onload = function onLoad() {\n            var sockets = JSON.parse(request.response);\n            def.resolve(sockets);\n        };\n        request.onerror = function onError() {\n            def.reject(request.response);\n        };\n\n        request.send(null);\n\n        return def.promise();\n    }\n\n    /**\n     * Disconnect from the remote debugger WebSocket\n     * @return {jQuery.Promise} Promise that is resolved immediately if not\n     *     currently connected or asynchronously when the socket is closed.\n     */\n    function disconnect() {\n        var deferred = new $.Deferred(),\n            promise = deferred.promise();\n\n        if (_socket && (_socket.readyState === WebSocket.OPEN)) {\n            _socket.onclose = function () {\n                // trigger disconnect event\n                _onDisconnect();\n\n                deferred.resolve();\n            };\n\n            promise = Async.withTimeout(promise, 5000);\n\n            _socket.close();\n        } else {\n            if (_socket) {\n                delete _socket.onmessage;\n                delete _socket.onopen;\n                delete _socket.onclose;\n                delete _socket.onerror;\n\n                _socket = undefined;\n            }\n\n            deferred.resolve();\n        }\n\n        return promise;\n    }\n\n    /**\n     * Connect to the remote debugger WebSocket at the given URL.\n     * Clients must listen for the `connect` event.\n     * @param {string} WebSocket URL\n     */\n    function connect(socketURL) {\n        disconnect().done(function () {\n            _socket = new WebSocket(socketURL);\n            _socket.onmessage = _onMessage;\n            _socket.onopen = _onConnect;\n            _socket.onclose = _onDisconnect;\n            _socket.onerror = _onError;\n        });\n    }\n\n    /** Connect to the remote debugger of the page that is at the given URL\n     * @param {string} url\n     */\n    function connectToURL(url) {\n        if (_connectDeferred) {\n            // reject an existing connection attempt\n            _connectDeferred.reject(\"CANCEL\");\n        }\n        var deferred = new $.Deferred();\n        _connectDeferred = deferred;\n        var promise = getDebuggableWindows();\n        promise.done(function onGetAvailableSockets(response) {\n            var i, page;\n            for (i in response) {\n                page = response[i];\n                if (page.webSocketDebuggerUrl && page.url.indexOf(url) === 0) {\n                    connect(page.webSocketDebuggerUrl);\n                    // _connectDeferred may be resolved by onConnect or rejected by onError\n                    return;\n                }\n            }\n            deferred.reject(FileError.ERR_NOT_FOUND); // Reject with a \"not found\" error\n        });\n        promise.fail(function onFail(err) {\n            deferred.reject(err);\n        });\n        return deferred.promise();\n    }\n\n    /** Check if the inspector is connected */\n    function connected() {\n        return _socket !== undefined && _socket.readyState === WebSocket.OPEN;\n    }\n\n    /**\n     * Get user agent string\n     * @return {string}\n     */\n    function getUserAgent() {\n        return _userAgent;\n    }\n\n    /**\n     * Set user agent string\n     * @param {string} userAgent User agent string returned from Chrome\n     */\n    function setUserAgent(userAgent) {\n        _userAgent = userAgent;\n    }\n\n    /** Initialize the Inspector\n     * Read the Inspector.json configuration and define the command objects\n     * -> Inspector.domain.command()\n     */\n    function init(theConfig) {\n        exports.config = theConfig;\n\n        var InspectorText = require(\"text!LiveDevelopment/Inspector/Inspector.json\"),\n            InspectorJSON = JSON.parse(InspectorText);\n\n        var i, j, domain, command;\n        for (i in InspectorJSON.domains) {\n            domain = InspectorJSON.domains[i];\n            var exportedDomain = {};\n            exports[domain.domain] = exportedDomain;\n            EventDispatcher.makeEventDispatcher(exportedDomain);\n            for (j in domain.commands) {\n                command = domain.commands[j];\n                exportedDomain[command.name] = _send.bind(undefined, domain.domain + \".\" + command.name, command.parameters);\n            }\n        }\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Export public functions\n    exports.connect              = connect;\n    exports.connected            = connected;\n    exports.connectToURL         = connectToURL;\n    exports.disconnect           = disconnect;\n    exports.getDebuggableWindows = getDebuggableWindows;\n    exports.getUserAgent         = getUserAgent;\n    exports.init                 = init;\n    exports.send                 = send;\n    exports.setUserAgent         = setUserAgent;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Inspector/Inspector.json",
    "content": "{\n    \"version\": { \"major\": \"1\", \"minor\": \"1\" },\n    \"domains\": [{\n        \"domain\": \"Inspector\",\n        \"hidden\": true,\n        \"types\": [],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables inspector domain notifications.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables inspector domain notifications.\"\n            },\n            {\n                \"name\": \"reset\",\n                \"description\": \"Resets all domains.\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"evaluateForTestInFrontend\",\n                \"parameters\": [\n                    { \"name\": \"testCallId\", \"type\": \"integer\" },\n                    { \"name\": \"script\", \"type\": \"string\" }\n                ]\n            },\n            {\n                \"name\": \"inspect\",\n                \"parameters\": [\n                    { \"name\": \"object\", \"$ref\": \"Runtime.RemoteObject\" },\n                    { \"name\": \"hints\", \"type\": \"object\" }\n                ]\n            },\n            {\n                \"name\": \"detached\",\n                \"description\": \"Fired when remote debugging connection is about to be terminated. Contains detach reason.\",\n                \"parameters\": [\n                    { \"name\": \"reason\", \"type\": \"string\", \"description\": \"The reason why connection has been terminated.\" }\n                ]\n            },\n            {\n                \"name\": \"targetCrashed\",\n                \"description\": \"Fired when debugging target has crashed\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Memory\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"MemoryBlock\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"size\", \"type\": \"number\", \"optional\": true, \"description\": \"Size of the block in bytes if available\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Unique name used to identify the component that allocated this block\" },\n                    { \"name\": \"children\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"MemoryBlock\" }}\n                ]\n            },\n            {\n                \"id\": \"HeapSnapshotChunk\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"strings\", \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"An array of strings that were found since last update.\" },\n                    { \"name\": \"nodes\", \"type\": \"array\", \"items\": { \"type\": \"integer\" }, \"description\": \"An array of nodes that were found since last update.\" },\n                    { \"name\": \"edges\", \"type\": \"array\", \"items\": { \"type\": \"integer\" }, \"description\": \"An array of edges that were found since last update.\" },\n                    { \"name\": \"baseToRealNodeId\", \"type\": \"array\", \"items\": { \"type\": \"integer\" }, \"description\": \"An array of integers for nodeId remapping. Even nodeId has to be mapped to the following odd nodeId.\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"getDOMCounters\",\n                \"returns\": [\n                    { \"name\": \"documents\", \"type\": \"integer\" },\n                    { \"name\": \"nodes\", \"type\": \"integer\" },\n                    { \"name\": \"jsEventListeners\", \"type\": \"integer\" }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"addNativeSnapshotChunk\",\n                \"parameters\": [\n                    { \"name\": \"chunk\", \"$ref\": \"HeapSnapshotChunk\", \"description\": \"A chunk of the serialized the snapshot.\" }\n                ]\n            }\n        ]\n    },\n    {\n        \"domain\": \"Page\",\n        \"description\": \"Actions and events related to the inspected page belong to the page domain.\",\n        \"types\": [\n            {\n                \"id\": \"ResourceType\",\n                \"type\": \"string\",\n                \"enum\": [\"Document\", \"Stylesheet\", \"Image\", \"Font\", \"Script\", \"XHR\", \"WebSocket\", \"Other\"],\n                \"description\": \"Resource type as it was perceived by the rendering engine.\"\n            },\n            {\n              \"id\": \"FrameId\",\n              \"type\": \"string\",\n              \"description\": \"Unique frame identifier.\"\n            },\n            {\n                \"id\": \"Frame\",\n                \"type\": \"object\",\n                \"description\": \"Information about the Frame on the page.\",\n                \"properties\": [\n                    { \"name\": \"id\", \"type\": \"string\", \"description\": \"Frame unique identifier.\" },\n                    { \"name\": \"parentId\", \"type\": \"string\", \"optional\": true, \"description\": \"Parent frame identifier.\" },\n                    { \"name\": \"loaderId\", \"$ref\": \"Network.LoaderId\", \"description\": \"Identifier of the loader associated with this frame.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"optional\": true, \"description\": \"Frame's name as specified in the tag.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Frame document's URL.\" },\n                    { \"name\": \"securityOrigin\", \"type\": \"string\", \"description\": \"Frame document's security origin.\" },\n                    { \"name\": \"mimeType\", \"type\": \"string\", \"description\": \"Frame document's mimeType as determined by the browser.\" }\n                ]\n            },\n            {\n                \"id\": \"FrameResourceTree\",\n                \"type\": \"object\",\n                \"description\": \"Information about the Frame hierarchy along with their cached resources.\",\n                \"properties\": [\n                    { \"name\": \"frame\", \"$ref\": \"Frame\", \"description\": \"Frame information for this tree item.\" },\n                    { \"name\": \"childFrames\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"FrameResourceTree\" }, \"description\": \"Child frames.\" },\n                    { \"name\": \"resources\", \"type\": \"array\",\n                        \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": [\n                                { \"name\": \"url\", \"type\": \"string\", \"description\": \"Resource URL.\" },\n                                { \"name\": \"type\", \"$ref\": \"ResourceType\", \"description\": \"Type of this resource.\" },\n                                { \"name\": \"mimeType\", \"type\": \"string\", \"description\": \"Resource mimeType as determined by the browser.\" },\n                                { \"name\": \"failed\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the resource failed to load.\" },\n                                { \"name\": \"canceled\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the resource was canceled during loading.\" }\n                            ]\n                        },\n                        \"description\": \"Information about frame resources.\"\n                    }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"id\": \"SearchMatch\",\n                \"type\": \"object\",\n                \"description\": \"Search match for resource.\",\n                \"properties\": [\n                    { \"name\": \"lineNumber\", \"type\": \"number\", \"description\": \"Line number in resource content.\" },\n                    { \"name\": \"lineContent\", \"type\": \"string\", \"description\": \"Line with match content.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"id\": \"SearchResult\",\n                \"type\": \"object\",\n                \"description\": \"Search result for resource.\",\n                \"properties\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Resource URL.\" },\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Resource frame id.\" },\n                    { \"name\": \"matchesCount\", \"type\": \"number\", \"description\": \"Number of matches in the resource content.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"id\": \"Cookie\",\n                \"type\": \"object\",\n                \"description\": \"Cookie object\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Cookie name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"Cookie value.\" },\n                    { \"name\": \"domain\", \"type\": \"string\", \"description\": \"Cookie domain.\" },\n                    { \"name\": \"path\", \"type\": \"string\", \"description\": \"Cookie path.\" },\n                    { \"name\": \"expires\", \"type\": \"number\", \"description\": \"Cookie expires.\" },\n                    { \"name\": \"size\", \"type\": \"integer\", \"description\": \"Cookie size.\" },\n                    { \"name\": \"httpOnly\", \"type\": \"boolean\", \"description\": \"True if cookie is http-only.\" },\n                    { \"name\": \"secure\", \"type\": \"boolean\", \"description\": \"True if cookie is secure.\" },\n                    { \"name\": \"session\", \"type\": \"boolean\", \"description\": \"True in case of session cookie.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"id\": \"ScriptIdentifier\",\n                \"type\": \"string\",\n                \"description\": \"Unique script identifier.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"NavigationEntry\",\n                \"type\": \"object\",\n                \"description\": \"Navigation history entry.\",\n                \"properties\": [\n                  { \"name\": \"id\", \"type\": \"integer\", \"description\": \"Unique id of the navigation history entry.\" },\n                  { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the navigation history entry.\" },\n                  { \"name\": \"title\", \"type\": \"string\", \"description\": \"Title of the navigation history entry.\" }\n                ],\n                \"hidden\": true\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables page domain notifications.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables page domain notifications.\"\n            },\n            {\n                \"name\": \"addScriptToEvaluateOnLoad\",\n                \"parameters\": [\n                    { \"name\": \"scriptSource\", \"type\": \"string\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"identifier\", \"$ref\": \"ScriptIdentifier\", \"description\": \"Identifier of the added script.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"removeScriptToEvaluateOnLoad\",\n                \"parameters\": [\n                    { \"name\": \"identifier\", \"$ref\": \"ScriptIdentifier\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"reload\",\n                \"parameters\": [\n                    { \"name\": \"ignoreCache\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, browser cache is ignored (as if the user pressed Shift+refresh).\" },\n                    { \"name\": \"scriptToEvaluateOnLoad\", \"type\": \"string\", \"optional\": true, \"description\": \"If set, the script will be injected into all frames of the inspected page after reload.\" },\n                    { \"name\": \"scriptPreprocessor\", \"type\": \"string\", \"optional\": true, \"description\": \"Script body that should evaluate to function that will preprocess all the scripts before their compilation.\", \"hidden\": true }\n                ],\n                \"description\": \"Reloads given page optionally ignoring the cache.\"\n            },\n            {\n                \"name\": \"navigate\",\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL to navigate the page to.\" }\n                ],\n                \"description\": \"Navigates current page to the given URL.\"\n            },\n            {\n              \"name\": \"getNavigationHistory\",\n              \"parameters\": [],\n              \"returns\": [\n                { \"name\": \"currentIndex\", \"type\": \"integer\", \"description\": \"Index of the current navigation history entry.\" },\n                { \"name\": \"entries\", \"type\": \"array\", \"items\": { \"$ref\": \"NavigationEntry\"}, \"description\": \"Array of navigation history entries.\" }\n              ],\n              \"description\": \"Returns navigation history for the current page.\",\n              \"hidden\": true\n            },\n            {\n              \"name\": \"navigateToHistoryEntry\",\n              \"parameters\": [\n                  { \"name\": \"entryId\", \"type\": \"integer\", \"description\": \"Unique id of the entry to navigate to.\" }\n              ],\n              \"description\": \"Navigates current page to the given history entry.\",\n              \"hidden\": true\n            },\n            {\n                \"name\": \"getCookies\",\n                \"returns\": [\n                    { \"name\": \"cookies\", \"type\": \"array\", \"items\": { \"$ref\": \"Cookie\"}, \"description\": \"Array of cookie objects.\" },\n                    { \"name\": \"cookiesString\", \"type\": \"string\", \"description\": \"document.cookie string representation of the cookies.\" }\n                ],\n                \"description\": \"Returns all browser cookies. Depending on the backend support, will either return detailed cookie information in the <code>cookie</code> field or string cookie representation using <code>cookieString</code>.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"deleteCookie\",\n                \"parameters\": [\n                    { \"name\": \"cookieName\", \"type\": \"string\", \"description\": \"Name of the cookie to remove.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL to match cooke domain and path.\" }\n                ],\n                \"description\": \"Deletes browser cookie with given name, domain and path.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getResourceTree\",\n                \"description\": \"Returns present frame / resource tree structure.\",\n                \"returns\": [\n                    { \"name\": \"frameTree\", \"$ref\": \"FrameResourceTree\", \"description\": \"Present frame / resource tree structure.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getResourceContent\",\n                \"description\": \"Returns content of the given resource.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Frame id to get resource for.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the resource to get content for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"content\", \"type\": \"string\", \"description\": \"Resource content.\" },\n                    { \"name\": \"base64Encoded\", \"type\": \"boolean\", \"description\": \"True, if content was served as base64.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"searchInResource\",\n                \"description\": \"Searches for given string in resource content.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Frame id for resource to search in.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the resource to search in.\" },\n                    { \"name\": \"query\", \"type\": \"string\", \"description\": \"String to search for.\"  },\n                    { \"name\": \"caseSensitive\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, search is case sensitive.\" },\n                    { \"name\": \"isRegex\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, treats string parameter as regex.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"array\", \"items\": { \"$ref\": \"SearchMatch\" }, \"description\": \"List of search matches.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"searchInResources\",\n                \"description\": \"Searches for given string in frame / resource tree structure.\",\n                \"parameters\": [\n                    { \"name\": \"text\", \"type\": \"string\", \"description\": \"String to search for.\"  },\n                    { \"name\": \"caseSensitive\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, search is case sensitive.\" },\n                    { \"name\": \"isRegex\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, treats string parameter as regex.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"array\", \"items\": { \"$ref\": \"SearchResult\" }, \"description\": \"List of search results.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setDocumentContent\",\n                \"description\": \"Sets given markup as the document's HTML.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Frame id to set HTML for.\" },\n                    { \"name\": \"html\", \"type\": \"string\", \"description\": \"HTML content to set.\"  }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setDeviceMetricsOverride\",\n                \"description\": \"Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \\\"device-width\\\"/\\\"device-height\\\"-related CSS media query results) and the font scale factor.\",\n                \"parameters\": [\n                    { \"name\": \"width\", \"type\": \"integer\", \"description\": \"Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override.\" },\n                    { \"name\": \"height\", \"type\": \"integer\", \"description\": \"Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override.\" },\n                    { \"name\": \"fontScaleFactor\", \"type\": \"number\", \"description\": \"Overriding font scale factor value (must be positive). 1 disables the override.\" },\n                    { \"name\": \"fitWindow\", \"type\": \"boolean\", \"description\": \"Whether a view that exceeds the available browser window area should be scaled down to fit.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setShowPaintRects\",\n                \"description\": \"Requests that backend shows paint rectangles\",\n                \"parameters\": [\n                    { \"name\": \"result\", \"type\": \"boolean\", \"description\": \"True for showing paint rectangles\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setShowDebugBorders\",\n                \"description\": \"Requests that backend shows debug borders on layers\",\n                \"parameters\": [\n                    { \"name\": \"show\", \"type\": \"boolean\", \"description\": \"True for showing debug borders\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setShowFPSCounter\",\n                \"description\": \"Requests that backend shows the FPS counter\",\n                \"parameters\": [\n                    { \"name\": \"show\", \"type\": \"boolean\", \"description\": \"True for showing the FPS counter\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setContinuousPaintingEnabled\",\n                \"description\": \"Requests that backend enables continuous painting\",\n                \"parameters\": [\n                    { \"name\": \"enabled\", \"type\": \"boolean\", \"description\": \"True for enabling cointinuous painting\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setShowScrollBottleneckRects\",\n                \"description\": \"Requests that backend shows scroll bottleneck rects\",\n                \"parameters\": [\n                    { \"name\": \"show\", \"type\": \"boolean\", \"description\": \"True for showing scroll bottleneck rects\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getScriptExecutionStatus\",\n                \"description\": \"Determines if scripts can be executed in the page.\",\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"string\", \"enum\": [\"allowed\", \"disabled\", \"forbidden\"], \"description\": \"Script execution status: \\\"allowed\\\" if scripts can be executed, \\\"disabled\\\" if script execution has been disabled through page settings, \\\"forbidden\\\" if script execution for the given page is not possible for other reasons.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setScriptExecutionDisabled\",\n                \"description\": \"Switches script execution in the page.\",\n                \"parameters\": [\n                    { \"name\": \"value\", \"type\": \"boolean\", \"description\": \"Whether script execution should be disabled in the page.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setGeolocationOverride\",\n                \"description\": \"Overrides the Geolocation Position or Error.\",\n                \"parameters\": [\n                    { \"name\": \"latitude\", \"type\": \"number\", \"optional\": true, \"description\": \"Mock longitude\"},\n                    { \"name\": \"longitude\", \"type\": \"number\", \"optional\": true, \"description\": \"Mock latitude\"},\n                    { \"name\": \"accuracy\", \"type\": \"number\", \"optional\": true, \"description\": \"Mock accuracy\"}\n                ]\n            },\n            {\n                \"name\": \"clearGeolocationOverride\",\n                \"description\": \"Clears the overriden Geolocation Position and Error.\"\n            },\n            {\n                \"name\": \"setDeviceOrientationOverride\",\n                \"description\": \"Overrides the Device Orientation.\",\n                \"parameters\": [\n                    { \"name\": \"alpha\", \"type\": \"number\", \"description\": \"Mock alpha\"},\n                    { \"name\": \"beta\", \"type\": \"number\", \"description\": \"Mock beta\"},\n                    { \"name\": \"gamma\", \"type\": \"number\", \"description\": \"Mock gamma\"}\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"clearDeviceOrientationOverride\",\n                \"description\": \"Clears the overridden Device Orientation.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setTouchEmulationEnabled\",\n                \"parameters\": [\n                    { \"name\": \"enabled\", \"type\": \"boolean\", \"description\": \"Whether the touch event emulation should be enabled.\" }\n                ],\n                \"description\": \"Toggles mouse event-based touch event emulation.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setEmulatedMedia\",\n                \"parameters\": [\n                    { \"name\": \"media\", \"type\": \"string\", \"description\": \"Media type to emulate. Empty string disables the override.\" }\n                ],\n                \"description\": \"Emulates the given media for CSS media queries.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"captureScreenshot\",\n                \"description\": \"Capture page screenshot.\",\n                \"parameters\": [\n                    { \"name\": \"format\", \"type\": \"string\", \"optional\": true, \"enum\": [\"jpeg\", \"png\"], \"description\": \"Image compression format.\" },\n                    { \"name\": \"quality\", \"type\": \"integer\", \"optional\": true, \"description\": \"Compression quality from range [0..100].\" },\n                    { \"name\": \"maxWidth\", \"type\": \"integer\", \"optional\": true, \"description\": \"Maximum screenshot width.\" },\n                    { \"name\": \"maxHeight\", \"type\": \"integer\", \"optional\": true, \"description\": \"Maximum screenshot height.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"data\", \"type\": \"string\", \"description\": \"Base64-encoded image data (PNG).\" },\n                    { \"name\": \"deviceScaleFactor\", \"type\": \"number\", \"hidden\": true, \"description\": \"Device scale factor.\" },\n                    { \"name\": \"pageScaleFactor\", \"type\": \"number\", \"hidden\": true, \"description\": \"Page scale factor.\" },\n                    { \"name\": \"viewport\", \"$ref\": \"DOM.Rect\", \"hidden\": true, \"description\": \"Viewport in CSS pixels.\" }\n                ]\n            },\n            {\n                \"name\": \"startScreencast\",\n                \"description\": \"Starts sending each frame using the <code>screencastFrame</code> event.\",\n                \"parameters\": [\n                    { \"name\": \"format\", \"type\": \"string\", \"optional\": true, \"enum\": [\"jpeg\", \"png\"], \"description\": \"Image compression format.\" },\n                    { \"name\": \"quality\", \"type\": \"integer\", \"optional\": true, \"description\": \"Compression quality from range [0..100].\" },\n                    { \"name\": \"maxWidth\", \"type\": \"integer\", \"optional\": true, \"description\": \"Maximum screenshot width.\" },\n                    { \"name\": \"maxHeight\", \"type\": \"integer\", \"optional\": true, \"description\": \"Maximum screenshot height.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"stopScreencast\",\n                \"description\": \"Stops sending each frame in the <code>screencastFrame</code>.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"handleJavaScriptDialog\",\n                \"description\": \"Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).\",\n                \"parameters\": [\n                    { \"name\": \"accept\", \"type\": \"boolean\", \"description\": \"Whether to accept or dismiss the dialog.\" },\n                    { \"name\": \"promptText\", \"type\": \"string\", \"optional\": true, \"description\": \"The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setShowViewportSizeOnResize\",\n                \"description\": \"Paints viewport size upon main frame resize.\",\n                \"parameters\": [\n                    { \"name\": \"show\", \"type\": \"boolean\", \"description\": \"Whether to paint size or not.\" },\n                    { \"name\": \"showGrid\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether to paint grid as well.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setForceCompositingMode\",\n                \"description\": \"Force accelerated compositing mode for inspected page.\",\n                \"parameters\": [\n                    { \"name\": \"force\", \"type\": \"boolean\", \"description\": \"Whether to force accelerated compositing or not.\" }\n                ],\n                \"hidden\": true\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"domContentEventFired\",\n                \"parameters\": [\n                    { \"name\": \"timestamp\", \"type\": \"number\" }\n                ]\n            },\n            {\n                \"name\": \"loadEventFired\",\n                \"parameters\": [\n                    { \"name\": \"timestamp\", \"type\": \"number\" }\n                ]\n            },\n            {\n                \"name\": \"frameAttached\",\n                \"description\": \"Fired when frame has been attached to its parent.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Id of the frame that has been attached.\" }\n                ]\n            },\n            {\n                \"name\": \"frameNavigated\",\n                \"description\": \"Fired once navigation of the frame has completed. Frame is now associated with the new loader.\",\n                \"parameters\": [\n                    { \"name\": \"frame\", \"$ref\": \"Frame\", \"description\": \"Frame object.\" }\n                ]\n            },\n            {\n                \"name\": \"frameDetached\",\n                \"description\": \"Fired when frame has been detached from its parent.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Id of the frame that has been detached.\" }\n                ]\n            },\n            {\n                \"name\": \"frameStartedLoading\",\n                \"description\": \"Fired when frame has started loading.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Id of the frame that has started loading.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"frameStoppedLoading\",\n                \"description\": \"Fired when frame has stopped loading.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Id of the frame that has stopped loading.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"frameScheduledNavigation\",\n                \"description\": \"Fired when frame schedules a potential navigation.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Id of the frame that has scheduled a navigation.\" },\n                    { \"name\": \"delay\", \"type\": \"number\", \"description\": \"Delay (in seconds) until the navigation is scheduled to begin. The navigation is not guaranteed to start.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"frameClearedScheduledNavigation\",\n                \"description\": \"Fired when frame no longer has a scheduled navigation.\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"FrameId\", \"description\": \"Id of the frame that has cleared its scheduled navigation.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"javascriptDialogOpening\",\n                \"description\": \"Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.\",\n                \"parameters\": [\n                    { \"name\": \"message\", \"type\": \"string\", \"description\": \"Message that will be displayed by the dialog.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"javascriptDialogClosed\",\n                \"description\": \"Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) has been closed.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"scriptsEnabled\",\n                \"description\": \"Fired when the JavaScript is enabled/disabled on the page\",\n                \"parameters\": [\n                    { \"name\": \"isEnabled\", \"type\": \"boolean\", \"description\": \"Whether script execution is enabled or disabled on the page.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"screencastFrame\",\n                \"description\": \"Compressed image data requested by the <code>startScreencast</code>.\",\n                \"parameters\": [\n                    { \"name\": \"data\", \"type\": \"string\", \"description\": \"Base64-encoded compressed image.\" },\n                    { \"name\": \"deviceScaleFactor\", \"type\": \"number\", \"hidden\": true, \"optional\": true, \"description\": \"Device scale factor.\" },\n                    { \"name\": \"pageScaleFactor\", \"type\": \"number\", \"hidden\": true, \"optional\": true, \"description\": \"Page scale factor.\" },\n                    { \"name\": \"viewport\", \"$ref\": \"DOM.Rect\", \"hidden\": true, \"optional\": true, \"description\": \"Viewport in CSS pixels.\" },\n                    { \"name\": \"offsetTop\", \"type\": \"number\", \"hidden\": true, \"optional\": true, \"description\": \"Top offset in DIP.\" },\n                    { \"name\": \"offsetBottom\", \"type\": \"number\", \"hidden\": true, \"optional\": true, \"description\": \"Bottom offset in DIP.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"screencastVisibilityChanged\",\n                \"description\": \"Fired when the page with currently enabled screencast was shown or hidden </code>.\",\n                \"parameters\": [\n                    { \"name\": \"visible\", \"type\": \"boolean\", \"description\": \"True if the page is visible.\" }\n                ],\n                \"hidden\": true\n            }\n        ]\n    },\n    {\n        \"domain\": \"Runtime\",\n        \"description\": \"Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.\",\n        \"types\": [\n            {\n                \"id\": \"RemoteObjectId\",\n                \"type\": \"string\",\n                \"description\": \"Unique object identifier.\"\n            },\n            {\n                \"id\": \"RemoteObject\",\n                \"type\": \"object\",\n                \"description\": \"Mirror object referencing original JavaScript object.\",\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"object\", \"function\", \"undefined\", \"string\", \"number\", \"boolean\"], \"description\": \"Object type.\" },\n                    { \"name\": \"subtype\", \"type\": \"string\", \"optional\": true, \"enum\": [\"array\", \"null\", \"node\", \"regexp\", \"date\"], \"description\": \"Object subtype hint. Specified for <code>object</code> type values only.\" },\n                    { \"name\": \"className\", \"type\": \"string\", \"optional\": true, \"description\": \"Object class (constructor) name. Specified for <code>object</code> type values only.\" },\n                    { \"name\": \"value\", \"type\": \"any\", \"optional\": true, \"description\": \"Remote object value (in case of primitive values or JSON values if it was requested).\" },\n                    { \"name\": \"description\", \"type\": \"string\", \"optional\": true, \"description\": \"String representation of the object.\" },\n                    { \"name\": \"objectId\", \"$ref\": \"RemoteObjectId\", \"optional\": true, \"description\": \"Unique object identifier (for non-primitive values).\" },\n                    { \"name\": \"preview\", \"$ref\": \"ObjectPreview\", \"optional\": true, \"description\": \"Preview containing abbreviated property values.\", \"hidden\": true }\n                ]\n            },\n            {\n                \"id\": \"ObjectPreview\",\n                \"type\": \"object\",\n                \"hidden\": true,\n                \"description\": \"Object containing abbreviated remote object value.\",\n                \"properties\": [\n                    { \"name\": \"lossless\", \"type\": \"boolean\", \"description\": \"Determines whether preview is lossless (contains all information of the original object).\" },\n                    { \"name\": \"overflow\", \"type\": \"boolean\", \"description\": \"True iff some of the properties of the original did not fit.\" },\n                    { \"name\": \"properties\", \"type\": \"array\", \"items\": { \"$ref\": \"PropertyPreview\" }, \"description\": \"List of the properties.\" }\n                ]\n            },\n            {\n                \"id\": \"PropertyPreview\",\n                \"type\": \"object\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Property name.\" },\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"object\", \"function\", \"undefined\", \"string\", \"number\", \"boolean\"], \"description\": \"Object type.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"optional\": true, \"description\": \"User-friendly property value string.\" },\n                    { \"name\": \"valuePreview\", \"$ref\": \"ObjectPreview\", \"optional\": true, \"description\": \"Nested value preview.\" },\n                    { \"name\": \"subtype\", \"type\": \"string\", \"optional\": true, \"enum\": [\"array\", \"null\", \"node\", \"regexp\", \"date\"], \"description\": \"Object subtype hint. Specified for <code>object</code> type values only.\" }\n                ]\n            },\n            {\n                \"id\": \"PropertyDescriptor\",\n                \"type\": \"object\",\n                \"description\": \"Object property descriptor.\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Property name.\" },\n                    { \"name\": \"value\", \"$ref\": \"RemoteObject\", \"optional\": true, \"description\": \"The value associated with the property.\" },\n                    { \"name\": \"writable\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the value associated with the property may be changed (data descriptors only).\" },\n                    { \"name\": \"get\", \"$ref\": \"RemoteObject\", \"optional\": true, \"description\": \"A function which serves as a getter for the property, or <code>undefined</code> if there is no getter (accessor descriptors only).\" },\n                    { \"name\": \"set\", \"$ref\": \"RemoteObject\", \"optional\": true, \"description\": \"A function which serves as a setter for the property, or <code>undefined</code> if there is no setter (accessor descriptors only).\" },\n                    { \"name\": \"configurable\", \"type\": \"boolean\", \"description\": \"True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.\" },\n                    { \"name\": \"enumerable\", \"type\": \"boolean\", \"description\": \"True if this property shows up during enumeration of the properties on the corresponding object.\" },\n                    { \"name\": \"wasThrown\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the result was thrown during the evaluation.\" },\n                    { \"name\": \"isOwn\", \"optional\": true, \"type\": \"boolean\", \"description\": \"True if the property is owned for the object.\", \"hidden\": true }\n\n                ]\n            },\n            {\n                \"id\": \"InternalPropertyDescriptor\",\n                \"type\": \"object\",\n                \"description\": \"Object internal property descriptor. This property isn't normally visible in JavaScript code.\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Conventional property name.\" },\n                    { \"name\": \"value\", \"$ref\": \"RemoteObject\", \"optional\": true, \"description\": \"The value associated with the property.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"id\": \"CallArgument\",\n                \"type\": \"object\",\n                \"description\": \"Represents function call argument. Either remote object id <code>objectId</code> or primitive <code>value</code> or neither of (for undefined) them should be specified.\",\n                \"properties\": [\n                    { \"name\": \"value\", \"type\": \"any\", \"optional\": true, \"description\": \"Primitive value.\" },\n                    { \"name\": \"objectId\", \"$ref\": \"RemoteObjectId\", \"optional\": true, \"description\": \"Remote object handle.\" }\n                ]\n            },\n            {\n                \"id\": \"ExecutionContextId\",\n                \"type\": \"integer\",\n                \"description\": \"Id of an execution context.\"\n            },\n            {\n                \"id\": \"ExecutionContextDescription\",\n                \"type\": \"object\",\n                \"description\": \"Description of an isolated world.\",\n                \"properties\": [\n                    { \"name\": \"id\", \"$ref\": \"ExecutionContextId\", \"description\": \"Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed.\" },\n                    { \"name\": \"isPageContext\", \"type\": \"boolean\", \"description\": \"True if this is a context where inspected web page scripts run. False if it is a content script isolated context.\", \"hidden\": true },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Human readable name describing given context.\", \"hidden\": true},\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Id of the owning frame.\" }\n                ]\n            }\n\n        ],\n        \"commands\": [\n            {\n                \"name\": \"evaluate\",\n                \"parameters\": [\n                    { \"name\": \"expression\", \"type\": \"string\", \"description\": \"Expression to evaluate.\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"Symbolic group name that can be used to release multiple objects.\" },\n                    { \"name\": \"includeCommandLineAPI\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Determines whether Command Line API should be available during the evaluation.\", \"hidden\": true },\n                    { \"name\": \"doNotPauseOnExceptionsAndMuteConsole\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.\", \"hidden\": true },\n                    { \"name\": \"contextId\", \"$ref\": \"Runtime.ExecutionContextId\", \"optional\": true, \"description\": \"Specifies in which isolated context to perform evaluation. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page.\" },\n                    { \"name\": \"returnByValue\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the result is expected to be a JSON object that should be sent by value.\" },\n                    { \"name\": \"generatePreview\", \"type\": \"boolean\", \"optional\": true, \"hidden\": true, \"description\": \"Whether preview should be generated for the result.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"$ref\": \"RemoteObject\", \"description\": \"Evaluation result.\" },\n                    { \"name\": \"wasThrown\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the result was thrown during the evaluation.\" }\n                ],\n                \"description\": \"Evaluates expression on global object.\"\n            },\n            {\n                \"name\": \"callFunctionOn\",\n                \"parameters\": [\n                    { \"name\": \"objectId\", \"$ref\": \"RemoteObjectId\", \"description\": \"Identifier of the object to call function on.\" },\n                    { \"name\": \"functionDeclaration\", \"type\": \"string\", \"description\": \"Declaration of the function to call.\" },\n                    { \"name\": \"arguments\", \"type\": \"array\", \"items\": { \"$ref\": \"CallArgument\", \"description\": \"Call argument.\" }, \"optional\": true, \"description\": \"Call arguments. All call arguments must belong to the same JavaScript world as the target object.\" },\n                    { \"name\": \"doNotPauseOnExceptionsAndMuteConsole\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Specifies whether function call should stop on exceptions and mute console. Overrides setPauseOnException state.\", \"hidden\": true },\n                    { \"name\": \"returnByValue\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the result is expected to be a JSON object which should be sent by value.\" },\n                    { \"name\": \"generatePreview\", \"type\": \"boolean\", \"optional\": true, \"hidden\": true, \"description\": \"Whether preview should be generated for the result.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"$ref\": \"RemoteObject\", \"description\": \"Call result.\" },\n                    { \"name\": \"wasThrown\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the result was thrown during the evaluation.\" }\n                ],\n                \"description\": \"Calls function with given declaration on the given object. Object group of the result is inherited from the target object.\"\n            },\n            {\n                \"name\": \"getProperties\",\n                \"parameters\": [\n                    { \"name\": \"objectId\", \"$ref\": \"RemoteObjectId\", \"description\": \"Identifier of the object to return properties for.\" },\n                    { \"name\": \"ownProperties\", \"optional\": true, \"type\": \"boolean\", \"description\": \"If true, returns properties belonging only to the element itself, not to its prototype chain.\" },\n                    { \"name\": \"accessorPropertiesOnly\", \"optional\": true, \"type\": \"boolean\", \"description\": \"If true, returns accessor properties (with getter/setter) only; internal properties are not returned either.\", \"hidden\": true }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"array\", \"items\": { \"$ref\": \"PropertyDescriptor\"}, \"description\": \"Object properties.\" },\n                    { \"name\": \"internalProperties\", \"optional\": true, \"type\": \"array\", \"items\": { \"$ref\": \"InternalPropertyDescriptor\"}, \"description\": \"Internal object properties (only of the element itself).\", \"hidden\": true }\n                ],\n                \"description\": \"Returns properties of a given object. Object group of the result is inherited from the target object.\"\n            },\n            {\n                \"name\": \"releaseObject\",\n                \"parameters\": [\n                    { \"name\": \"objectId\", \"$ref\": \"RemoteObjectId\", \"description\": \"Identifier of the object to release.\" }\n                ],\n                \"description\": \"Releases remote object with given id.\"\n            },\n            {\n                \"name\": \"releaseObjectGroup\",\n                \"parameters\": [\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"description\": \"Symbolic object group name.\" }\n                ],\n                \"description\": \"Releases all remote objects that belong to a given group.\"\n            },\n            {\n                \"name\": \"run\",\n                \"hidden\": true,\n                \"description\": \"Tells inspected instance(worker or page) that it can run in case it was started paused.\"\n            },\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"hidden\": true,\n                \"description\": \"Disables reporting of execution contexts creation.\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"executionContextCreated\",\n                \"parameters\": [\n                    { \"name\": \"context\", \"$ref\": \"ExecutionContextDescription\", \"description\": \"A newly created execution contex.\" }\n                ],\n                \"description\": \"Issued when new execution context is created.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Console\",\n        \"description\": \"Console domain defines methods and events for interaction with the JavaScript console. Console collects messages created by means of the <a href='http://getfirebug.com/wiki/index.php/Console_API'>JavaScript Console API</a>. One needs to enable this domain using <code>enable</code> command in order to start receiving the console messages. Browser collects messages issued while console domain is not enabled as well and reports them using <code>messageAdded</code> notification upon enabling.\",\n        \"types\": [\n            {\n                \"id\": \"Timestamp\",\n                \"type\": \"number\",\n                \"description\": \"Number of seconds since epoch.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"ConsoleMessage\",\n                \"type\": \"object\",\n                \"description\": \"Console message.\",\n                \"properties\": [\n                    { \"name\": \"source\", \"type\": \"string\", \"enum\": [\"xml\", \"javascript\", \"network\", \"console-api\", \"storage\", \"appcache\", \"rendering\", \"css\", \"security\", \"other\", \"deprecation\"], \"description\": \"Message source.\" },\n                    { \"name\": \"level\", \"type\": \"string\", \"enum\": [\"log\", \"warning\", \"error\", \"debug\"], \"description\": \"Message severity.\" },\n                    { \"name\": \"text\", \"type\": \"string\", \"description\": \"Message text.\" },\n                    { \"name\": \"type\", \"type\": \"string\", \"optional\": true, \"enum\": [\"log\", \"dir\", \"dirxml\", \"table\", \"trace\", \"clear\", \"startGroup\", \"startGroupCollapsed\", \"endGroup\", \"assert\", \"profile\", \"profileEnd\"], \"description\": \"Console message type.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"optional\": true, \"description\": \"URL of the message origin.\" },\n                    { \"name\": \"line\", \"type\": \"integer\", \"optional\": true, \"description\": \"Line number in the resource that generated this message.\" },\n                    { \"name\": \"column\", \"type\": \"integer\", \"optional\": true, \"description\": \"Column number in the resource that generated this message.\" },\n                    { \"name\": \"repeatCount\", \"type\": \"integer\", \"optional\": true, \"description\": \"Repeat count for repeated messages.\" },\n                    { \"name\": \"parameters\", \"type\": \"array\", \"items\": { \"$ref\": \"Runtime.RemoteObject\" }, \"optional\": true, \"description\": \"Message parameters in case of the formatted message.\" },\n                    { \"name\": \"stackTrace\", \"$ref\": \"StackTrace\", \"optional\": true, \"description\": \"JavaScript stack trace for assertions and error messages.\" },\n                    { \"name\": \"networkRequestId\", \"$ref\": \"Network.RequestId\", \"optional\": true, \"description\": \"Identifier of the network request associated with this message.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp, when this message was fired.\", \"hidden\": true }\n                ]\n            },\n            {\n                \"id\": \"CallFrame\",\n                \"type\": \"object\",\n                \"description\": \"Stack entry for console errors and assertions.\",\n                \"properties\": [\n                    { \"name\": \"functionName\", \"type\": \"string\", \"description\": \"JavaScript function name.\" },\n                    { \"name\": \"scriptId\", \"type\": \"string\", \"description\": \"JavaScript script id.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"JavaScript script name or url.\" },\n                    { \"name\": \"lineNumber\", \"type\": \"integer\", \"description\": \"JavaScript script line number.\" },\n                    { \"name\": \"columnNumber\", \"type\": \"integer\", \"description\": \"JavaScript script column number.\" }\n                ]\n            },\n            {\n                \"id\": \"StackTrace\",\n                \"type\": \"array\",\n                \"items\": { \"$ref\": \"CallFrame\" },\n                \"description\": \"Call frames for assertions or error messages.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables console domain, prevents further console messages from being reported to the client.\"\n            },\n            {\n                \"name\": \"clearMessages\",\n                \"description\": \"Clears console messages collected in the browser.\"\n            },\n            {\n                \"name\": \"setMonitoringXHREnabled\",\n                \"parameters\": [\n                    { \"name\": \"enabled\", \"type\": \"boolean\", \"description\": \"Monitoring enabled state.\" }\n                ],\n                \"description\": \"Toggles monitoring of XMLHttpRequest. If <code>true</code>, console will receive messages upon each XHR issued.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"addInspectedNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"DOM node id to be accessible by means of $x command line API.\" }\n                ],\n                \"description\": \"Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"addInspectedHeapObject\",\n                \"parameters\": [\n                    { \"name\": \"heapObjectId\", \"type\": \"integer\" }\n                ],\n                \"hidden\": true\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"messageAdded\",\n                \"parameters\": [\n                    { \"name\": \"message\", \"$ref\": \"ConsoleMessage\", \"description\": \"Console message that has been added.\" }\n                ],\n                \"description\": \"Issued when new console message is added.\"\n            },\n            {\n                \"name\": \"messageRepeatCountUpdated\",\n                \"parameters\": [\n                    { \"name\": \"count\", \"type\": \"integer\", \"description\": \"New repeat count value.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp of most recent message in batch.\", \"hidden\": true }\n                ],\n                \"description\": \"Issued when subsequent message(s) are equal to the previous one(s).\"\n            },\n            {\n                \"name\": \"messagesCleared\",\n                \"description\": \"Issued when console is cleared. This happens either upon <code>clearMessages</code> command or after page navigation.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Network\",\n        \"description\": \"Network domain allows tracking network activities of the page. It exposes information about http, file, data and other requests and responses, their headers, bodies, timing, etc.\",\n        \"types\": [\n            {\n                \"id\": \"LoaderId\",\n                \"type\": \"string\",\n                \"description\": \"Unique loader identifier.\"\n            },\n            {\n                \"id\": \"RequestId\",\n                \"type\": \"string\",\n                \"description\": \"Unique request identifier.\"\n            },\n            {\n                \"id\": \"Timestamp\",\n                \"type\": \"number\",\n                \"description\": \"Number of seconds since epoch.\"\n            },\n            {\n                \"id\": \"Headers\",\n                \"type\": \"object\",\n                \"description\": \"Request / response headers as keys / values of JSON object.\"\n            },\n            {\n                \"id\": \"ResourceTiming\",\n                \"type\": \"object\",\n                \"description\": \"Timing information for the request.\",\n                \"properties\": [\n                    { \"name\": \"requestTime\", \"type\": \"number\", \"description\": \"Timing's requestTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this requestTime.\" },\n                    { \"name\": \"proxyStart\", \"type\": \"number\", \"description\": \"Started resolving proxy.\" },\n                    { \"name\": \"proxyEnd\", \"type\": \"number\", \"description\": \"Finished resolving proxy.\" },\n                    { \"name\": \"dnsStart\", \"type\": \"number\", \"description\": \"Started DNS address resolve.\" },\n                    { \"name\": \"dnsEnd\", \"type\": \"number\", \"description\": \"Finished DNS address resolve.\" },\n                    { \"name\": \"connectStart\", \"type\": \"number\", \"description\": \"Started connecting to the remote host.\" },\n                    { \"name\": \"connectEnd\", \"type\": \"number\", \"description\": \"Connected to the remote host.\" },\n                    { \"name\": \"sslStart\", \"type\": \"number\", \"description\": \"Started SSL handshake.\" },\n                    { \"name\": \"sslEnd\", \"type\": \"number\", \"description\": \"Finished SSL handshake.\" },\n                    { \"name\": \"sendStart\", \"type\": \"number\", \"description\": \"Started sending request.\" },\n                    { \"name\": \"sendEnd\", \"type\": \"number\", \"description\": \"Finished sending request.\" },\n                    { \"name\": \"receiveHeadersEnd\", \"type\": \"number\", \"description\": \"Finished receiving response headers.\" }\n                ]\n            },\n            {\n                \"id\": \"Request\",\n                \"type\": \"object\",\n                \"description\": \"HTTP request data.\",\n                \"properties\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Request URL.\" },\n                    { \"name\": \"method\", \"type\": \"string\", \"description\": \"HTTP request method.\" },\n                    { \"name\": \"headers\", \"$ref\": \"Headers\", \"description\": \"HTTP request headers.\" },\n                    { \"name\": \"postData\", \"type\": \"string\", \"optional\": true, \"description\": \"HTTP POST request data.\" }\n                ]\n            },\n            {\n                \"id\": \"Response\",\n                \"type\": \"object\",\n                \"description\": \"HTTP response data.\",\n                \"properties\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Response URL. This URL can be different from CachedResource.url in case of redirect.\" },\n                    { \"name\": \"status\", \"type\": \"number\", \"description\": \"HTTP response status code.\" },\n                    { \"name\": \"statusText\", \"type\": \"string\", \"description\": \"HTTP response status text.\" },\n                    { \"name\": \"headers\", \"$ref\": \"Headers\", \"description\": \"HTTP response headers.\" },\n                    { \"name\": \"headersText\", \"type\": \"string\", \"optional\": true, \"description\": \"HTTP response headers text.\" },\n                    { \"name\": \"mimeType\", \"type\": \"string\", \"description\": \"Resource mimeType as determined by the browser.\" },\n                    { \"name\": \"requestHeaders\", \"$ref\": \"Headers\", \"optional\": true, \"description\": \"Refined HTTP request headers that were actually transmitted over the network.\" },\n                    { \"name\": \"requestHeadersText\", \"type\": \"string\", \"optional\": true, \"description\": \"HTTP request headers text.\" },\n                    { \"name\": \"connectionReused\", \"type\": \"boolean\", \"description\": \"Specifies whether physical connection was actually reused for this request.\" },\n                    { \"name\": \"connectionId\", \"type\": \"number\", \"description\": \"Physical connection id that was actually used for this request.\" },\n                    { \"name\": \"fromDiskCache\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Specifies that the request was served from the disk cache.\" },\n                    { \"name\": \"timing\", \"$ref\": \"ResourceTiming\", \"optional\": true, \"description\": \"Timing information for the given request.\" }\n                ]\n            },\n            {\n                \"id\": \"WebSocketRequest\",\n                \"type\": \"object\",\n                \"description\": \"WebSocket request data.\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"headers\", \"$ref\": \"Headers\", \"description\": \"HTTP response headers.\" }\n                ]\n            },\n            {\n                \"id\": \"WebSocketResponse\",\n                \"type\": \"object\",\n                \"description\": \"WebSocket response data.\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"status\", \"type\": \"number\", \"description\": \"HTTP response status code.\" },\n                    { \"name\": \"statusText\", \"type\": \"string\", \"description\": \"HTTP response status text.\" },\n                    { \"name\": \"headers\", \"$ref\": \"Headers\", \"description\": \"HTTP response headers.\" }\n                ]\n            },\n            {\n                \"id\": \"WebSocketFrame\",\n                \"type\": \"object\",\n                \"description\": \"WebSocket frame data.\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"opcode\", \"type\": \"number\", \"description\": \"WebSocket frame opcode.\" },\n                    { \"name\": \"mask\", \"type\": \"boolean\", \"description\": \"WebSocke frame mask.\" },\n                    { \"name\": \"payloadData\", \"type\": \"string\", \"description\": \"WebSocke frame payload data.\" }\n                ]\n            },\n            {\n                \"id\": \"CachedResource\",\n                \"type\": \"object\",\n                \"description\": \"Information about the cached resource.\",\n                \"properties\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Resource URL. This is the url of the original network request.\" },\n                    { \"name\": \"type\", \"$ref\": \"Page.ResourceType\", \"description\": \"Type of this resource.\" },\n                    { \"name\": \"response\", \"$ref\": \"Response\", \"optional\": true, \"description\": \"Cached response data.\" },\n                    { \"name\": \"bodySize\", \"type\": \"number\", \"description\": \"Cached response body size.\" }\n                ]\n            },\n            {\n                \"id\": \"Initiator\",\n                \"type\": \"object\",\n                \"description\": \"Information about the request initiator.\",\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"parser\", \"script\", \"other\"], \"description\": \"Type of this initiator.\" },\n                    { \"name\": \"stackTrace\", \"$ref\": \"Console.StackTrace\", \"optional\": true, \"description\": \"Initiator JavaScript stack trace, set for Script only.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"optional\": true, \"description\": \"Initiator URL, set for Parser type only.\" },\n                    { \"name\": \"lineNumber\", \"type\": \"number\", \"optional\": true, \"description\": \"Initiator line number, set for Parser type only.\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables network tracking, network events will now be delivered to the client.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables network tracking, prevents network events from being sent to the client.\"\n            },\n            {\n                \"name\": \"setUserAgentOverride\",\n                \"description\": \"Allows overriding user agent with the given string.\",\n                \"parameters\": [\n                    { \"name\": \"userAgent\", \"type\": \"string\", \"description\": \"User agent to use.\" }\n                ]\n            },\n            {\n                \"name\": \"setExtraHTTPHeaders\",\n                \"description\": \"Specifies whether to always send extra HTTP headers with the requests from this page.\",\n                \"parameters\": [\n                    { \"name\": \"headers\", \"$ref\": \"Headers\", \"description\": \"Map with extra HTTP headers.\" }\n                ]\n            },\n            {\n                \"name\": \"getResponseBody\",\n                \"description\": \"Returns content served for the given request.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Identifier of the network request to get content for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"body\", \"type\": \"string\", \"description\": \"Response body.\" },\n                    { \"name\": \"base64Encoded\", \"type\": \"boolean\", \"description\": \"True, if content was sent as base64.\" }\n                ]\n            },\n            {\n                \"name\": \"replayXHR\",\n                \"description\": \"This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Identifier of XHR to replay.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"canClearBrowserCache\",\n                \"description\": \"Tells whether clearing browser cache is supported.\",\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"boolean\", \"description\": \"True if browser cache can be cleared.\" }\n                ]\n            },\n            {\n                \"name\": \"clearBrowserCache\",\n                \"description\": \"Clears browser cache.\"\n            },\n            {\n                \"name\": \"canClearBrowserCookies\",\n                \"description\": \"Tells whether clearing browser cookies is supported.\",\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"boolean\", \"description\": \"True if browser cookies can be cleared.\" }\n                ]\n            },\n            {\n                \"name\": \"clearBrowserCookies\",\n                \"description\": \"Clears browser cookies.\"\n            },\n            {\n                \"name\": \"setCacheDisabled\",\n                \"parameters\": [\n                    { \"name\": \"cacheDisabled\", \"type\": \"boolean\", \"description\": \"Cache disabled state.\" }\n                ],\n                \"description\": \"Toggles ignoring cache for each request. If <code>true</code>, cache will not be used.\"\n            },  \n            {\n                \"name\": \"loadResourceForFrontend\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Frame to load the resource from.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the resource to load.\" },\n                    { \"name\": \"requestHeaders\", \"$ref\": \"Network.Headers\", \"optional\": true, \"description\": \"Request headers.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"statusCode\", \"type\": \"number\", \"description\": \"HTTP status code.\" },\n                    { \"name\": \"responseHeaders\", \"$ref\": \"Network.Headers\", \"description\": \"Response headers.\" },\n                    { \"name\": \"content\", \"type\": \"string\", \"description\": \"Resource content.\" }\n                ],\n                \"description\": \"Loads a resource in the context of a frame on the inspected page without cross origin checks.\",\n                \"hidden\": true\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"requestWillBeSent\",\n                \"description\": \"Fired when page is about to send HTTP request.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Frame identifier.\", \"hidden\": true },\n                    { \"name\": \"loaderId\", \"$ref\": \"LoaderId\", \"description\": \"Loader identifier.\" },\n                    { \"name\": \"documentURL\", \"type\": \"string\", \"description\": \"URL of the document this request is loaded for.\" },\n                    { \"name\": \"request\", \"$ref\": \"Request\", \"description\": \"Request data.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"initiator\", \"$ref\": \"Initiator\", \"description\": \"Request initiator.\" },\n                    { \"name\": \"redirectResponse\", \"optional\": true, \"$ref\": \"Response\", \"description\": \"Redirect response data.\" }\n                ]\n            },\n            {\n                \"name\": \"requestServedFromCache\",\n                \"description\": \"Fired if request ended up loading from cache.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" }\n                ]\n            },\n            {\n                \"name\": \"responseReceived\",\n                \"description\": \"Fired when HTTP response is available.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Frame identifier.\", \"hidden\": true },\n                    { \"name\": \"loaderId\", \"$ref\": \"LoaderId\", \"description\": \"Loader identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"type\", \"$ref\": \"Page.ResourceType\", \"description\": \"Resource type.\" },\n                    { \"name\": \"response\", \"$ref\": \"Response\", \"description\": \"Response data.\" }\n                ]\n            },\n            {\n                \"name\": \"dataReceived\",\n                \"description\": \"Fired when data chunk was received over the network.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"dataLength\", \"type\": \"integer\", \"description\": \"Data chunk length.\" },\n                    { \"name\": \"encodedDataLength\", \"type\": \"integer\", \"description\": \"Actual bytes received (might be less than dataLength for compressed encodings).\" }\n                ]\n            },\n            {\n                \"name\": \"loadingFinished\",\n                \"description\": \"Fired when HTTP request has finished loading.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" }\n                ]\n            },\n            {\n                \"name\": \"loadingFailed\",\n                \"description\": \"Fired when HTTP request has failed to load.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"errorText\", \"type\": \"string\", \"description\": \"User friendly error message.\" },\n                    { \"name\": \"canceled\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if loading was canceled.\" }\n                ]\n            },\n            {\n                \"name\": \"webSocketWillSendHandshakeRequest\",\n                \"description\": \"Fired when WebSocket is about to initiate handshake.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"request\", \"$ref\": \"WebSocketRequest\", \"description\": \"WebSocket request data.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"webSocketHandshakeResponseReceived\",\n                \"description\": \"Fired when WebSocket handshake response becomes available.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"response\", \"$ref\": \"WebSocketResponse\", \"description\": \"WebSocket response data.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"webSocketCreated\",\n                \"description\": \"Fired upon WebSocket creation.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"WebSocket request URL.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"webSocketClosed\",\n                \"description\": \"Fired when WebSocket is closed.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"webSocketFrameReceived\",\n                \"description\": \"Fired when WebSocket frame is received.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"response\", \"$ref\": \"WebSocketFrame\", \"description\": \"WebSocket response data.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"webSocketFrameError\",\n                \"description\": \"Fired when WebSocket frame error occurs.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"errorMessage\", \"type\": \"string\", \"description\": \"WebSocket frame error message.\" }\n                ],\n                \"hidden\": true\n            },\n            {\n                \"name\": \"webSocketFrameSent\",\n                \"description\": \"Fired when WebSocket frame is sent.\",\n                \"parameters\": [\n                    { \"name\": \"requestId\", \"$ref\": \"RequestId\", \"description\": \"Request identifier.\" },\n                    { \"name\": \"timestamp\", \"$ref\": \"Timestamp\", \"description\": \"Timestamp.\" },\n                    { \"name\": \"response\", \"$ref\": \"WebSocketFrame\", \"description\": \"WebSocket response data.\" }\n                ],\n                \"hidden\": true\n            }\n        ]\n    },\n    {\n        \"domain\": \"Database\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"DatabaseId\",\n                \"type\": \"string\",\n                \"description\": \"Unique identifier of Database object.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"Database\",\n                \"type\": \"object\",\n                \"description\": \"Database object.\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"id\", \"$ref\": \"DatabaseId\", \"description\": \"Database ID.\" },\n                    { \"name\": \"domain\", \"type\": \"string\", \"description\": \"Database domain.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Database name.\" },\n                    { \"name\": \"version\", \"type\": \"string\", \"description\": \"Database version.\" }\n                ]\n            },\n            {\n                \"id\": \"Error\",\n                \"type\": \"object\",\n                \"description\": \"Database error.\",\n                \"properties\": [\n                    { \"name\": \"message\", \"type\": \"string\", \"description\": \"Error message.\" },\n                    { \"name\": \"code\", \"type\": \"integer\", \"description\": \"Error code.\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables database tracking, database events will now be delivered to the client.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables database tracking, prevents database events from being sent to the client.\"\n            },\n            {\n                \"name\": \"getDatabaseTableNames\",\n                \"parameters\": [\n                    { \"name\": \"databaseId\", \"$ref\": \"DatabaseId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"tableNames\", \"type\": \"array\", \"items\": { \"type\": \"string\" } }\n                ]\n            },\n            {\n                \"name\": \"executeSQL\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"databaseId\", \"$ref\": \"DatabaseId\" },\n                    { \"name\": \"query\", \"type\": \"string\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"columnNames\", \"type\": \"array\", \"optional\": true, \"items\": { \"type\": \"string\" } },\n                    { \"name\": \"values\", \"type\": \"array\", \"optional\": true, \"items\": { \"type\": \"any\" }},\n                    { \"name\": \"sqlError\", \"$ref\": \"Error\", \"optional\": true }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"addDatabase\",\n                \"parameters\": [\n                    { \"name\": \"database\", \"$ref\": \"Database\" }\n                ]\n            }\n        ]\n    },\n    {\n        \"domain\": \"IndexedDB\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"DatabaseWithObjectStores\",\n                \"type\": \"object\",\n                \"description\": \"Database with an array of object stores.\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Database name.\" },\n                    { \"name\": \"version\", \"type\": \"string\", \"description\": \"Deprecated string database version.\" },\n                    { \"name\": \"intVersion\", \"type\": \"integer\", \"description\": \"Integer database version.\" },\n                    { \"name\": \"objectStores\", \"type\": \"array\", \"items\": { \"$ref\": \"ObjectStore\" }, \"description\": \"Object stores in this database.\" }\n                ]\n            },\n            {\n                \"id\": \"ObjectStore\",\n                \"type\": \"object\",\n                \"description\": \"Object store.\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Object store name.\" },\n                    { \"name\": \"keyPath\", \"$ref\": \"KeyPath\", \"description\": \"Object store key path.\" },\n                    { \"name\": \"autoIncrement\", \"type\": \"boolean\", \"description\": \"If true, object store has auto increment flag set.\" },\n                    { \"name\": \"indexes\", \"type\": \"array\", \"items\": { \"$ref\": \"ObjectStoreIndex\" }, \"description\": \"Indexes in this object store.\" }\n                ]\n            },\n            {\n                \"id\": \"ObjectStoreIndex\",\n                \"type\": \"object\",\n                \"description\": \"Object store index.\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Index name.\" },\n                    { \"name\": \"keyPath\", \"$ref\": \"KeyPath\", \"description\": \"Index key path.\" },\n                    { \"name\": \"unique\", \"type\": \"boolean\", \"description\": \"If true, index is unique.\" },\n                    { \"name\": \"multiEntry\", \"type\": \"boolean\", \"description\": \"If true, index allows multiple entries for a key.\" }\n                ]\n            },\n            {\n                \"id\": \"Key\",\n                \"type\": \"object\",\n                \"description\": \"Key.\",\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"number\", \"string\", \"date\", \"array\"], \"description\": \"Key type.\" },\n                    { \"name\": \"number\", \"type\": \"number\", \"optional\": true, \"description\": \"Number value.\" },\n                    { \"name\": \"string\", \"type\": \"string\", \"optional\": true, \"description\": \"String value.\" },\n                    { \"name\": \"date\", \"type\": \"number\", \"optional\": true, \"description\": \"Date value.\" },\n                    { \"name\": \"array\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"Key\" }, \"description\": \"Array value.\" }\n                ]\n            },\n            {\n                \"id\": \"KeyRange\",\n                \"type\": \"object\",\n                \"description\": \"Key range.\",\n                \"properties\": [\n                    { \"name\": \"lower\", \"$ref\": \"Key\", \"optional\": true, \"description\": \"Lower bound.\" },\n                    { \"name\": \"upper\", \"$ref\": \"Key\", \"optional\": true, \"description\": \"Upper bound.\" },\n                    { \"name\": \"lowerOpen\", \"type\": \"boolean\", \"description\": \"If true lower bound is open.\" },\n                    { \"name\": \"upperOpen\", \"type\": \"boolean\", \"description\": \"If true upper bound is open.\" }\n                ]\n            },\n            {\n                \"id\": \"DataEntry\",\n                \"type\": \"object\",\n                \"description\": \"Data entry.\",\n                \"properties\": [\n                    { \"name\": \"key\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Key.\" },\n                    { \"name\": \"primaryKey\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Primary key.\" },\n                    { \"name\": \"value\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Value.\" }\n                ]\n            },\n            {\n                \"id\": \"KeyPath\",\n                \"type\": \"object\",\n                \"description\": \"Key path.\",\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"null\", \"string\", \"array\"], \"description\": \"Key path type.\" },\n                    { \"name\": \"string\", \"type\": \"string\", \"optional\": true, \"description\": \"String value.\" },\n                    { \"name\": \"array\", \"type\": \"array\", \"optional\": true, \"items\": { \"type\": \"string\" }, \"description\": \"Array value.\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables events from backend.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables events from backend.\"\n            },\n            {\n                \"name\": \"requestDatabaseNames\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"securityOrigin\", \"type\": \"string\", \"description\": \"Security origin.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"databaseNames\", \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"Database names for origin.\" }\n                ],\n                \"description\": \"Requests database names for given security origin.\"\n            },\n            {\n                \"name\": \"requestDatabase\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"securityOrigin\", \"type\": \"string\", \"description\": \"Security origin.\" },\n                    { \"name\": \"databaseName\", \"type\": \"string\", \"description\": \"Database name.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"databaseWithObjectStores\", \"$ref\": \"DatabaseWithObjectStores\", \"description\": \"Database with an array of object stores.\" }\n                ],\n                \"description\": \"Requests database with given name in given frame.\"\n            },\n            {\n                \"name\": \"requestData\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"securityOrigin\", \"type\": \"string\", \"description\": \"Security origin.\" },\n                    { \"name\": \"databaseName\", \"type\": \"string\", \"description\": \"Database name.\" },\n                    { \"name\": \"objectStoreName\", \"type\": \"string\", \"description\": \"Object store name.\" },\n                    { \"name\": \"indexName\", \"type\": \"string\", \"description\": \"Index name, empty string for object store data requests.\" },\n                    { \"name\": \"skipCount\", \"type\": \"integer\", \"description\": \"Number of records to skip.\" },\n                    { \"name\": \"pageSize\", \"type\": \"integer\", \"description\": \"Number of records to fetch.\" },\n                    { \"name\": \"keyRange\", \"$ref\": \"KeyRange\", \"optional\": true, \"description\": \"Key range.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"objectStoreDataEntries\", \"type\": \"array\", \"items\": { \"$ref\": \"DataEntry\" }, \"description\": \"Array of object store data entries.\" },\n                    { \"name\": \"hasMore\", \"type\": \"boolean\", \"description\": \"If true, there are more entries to fetch in the given range.\" }\n                ],\n                \"description\": \"Requests data from object store or index.\"\n            },\n            {\n                \"name\": \"clearObjectStore\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"securityOrigin\", \"type\": \"string\", \"description\": \"Security origin.\" },\n                    { \"name\": \"databaseName\", \"type\": \"string\", \"description\": \"Database name.\" },\n                    { \"name\": \"objectStoreName\", \"type\": \"string\", \"description\": \"Object store name.\" }\n                ],\n                \"returns\": [\n                ],\n                \"description\": \"Clears all entries from an object store.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"DOMStorage\",\n        \"hidden\": true,\n        \"description\": \"Query and modify DOM storage.\",\n        \"types\": [\n            {\n                \"id\": \"StorageId\",\n                \"type\": \"object\",\n                \"description\": \"DOM Storage identifier.\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"securityOrigin\", \"type\": \"string\", \"description\": \"Security origin for the storage.\" },\n                    { \"name\": \"isLocalStorage\", \"type\": \"boolean\", \"description\": \"Whether the storage is local storage (not session storage).\" }\n                ]\n            },\n            {\n                \"id\": \"Item\",\n                \"type\": \"array\",\n                \"description\": \"DOM Storage item.\",\n                \"hidden\": true,\n                \"items\": { \"type\": \"string\" }\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables storage tracking, storage events will now be delivered to the client.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables storage tracking, prevents storage events from being sent to the client.\"\n            },\n            {\n                \"name\": \"getDOMStorageItems\",\n                \"parameters\": [\n                    { \"name\": \"storageId\", \"$ref\": \"StorageId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"entries\", \"type\": \"array\", \"items\": { \"$ref\": \"Item\" } }\n                ]\n            },\n            {\n                \"name\": \"setDOMStorageItem\",\n                \"parameters\": [\n                    { \"name\": \"storageId\", \"$ref\": \"StorageId\" },\n                    { \"name\": \"key\", \"type\": \"string\" },\n                    { \"name\": \"value\", \"type\": \"string\" }\n                ]\n            },\n            {\n                \"name\": \"removeDOMStorageItem\",\n                \"parameters\": [\n                    { \"name\": \"storageId\", \"$ref\": \"StorageId\" },\n                    { \"name\": \"key\", \"type\": \"string\" }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"domStorageItemsCleared\",\n                \"parameters\": [\n                    { \"name\": \"storageId\",  \"$ref\": \"StorageId\" }\n                ]\n            },\n            {\n                \"name\": \"domStorageItemRemoved\",\n                \"parameters\": [\n                    { \"name\": \"storageId\",  \"$ref\": \"StorageId\" },\n                    { \"name\": \"key\", \"type\": \"string\" }\n                ]\n            },\n            {\n                \"name\": \"domStorageItemAdded\",\n                \"parameters\": [\n                    { \"name\": \"storageId\",  \"$ref\": \"StorageId\" },\n                    { \"name\": \"key\", \"type\": \"string\" },\n                    { \"name\": \"newValue\", \"type\": \"string\" }\n                ]\n            },\n            {\n                \"name\": \"domStorageItemUpdated\",\n                \"parameters\": [\n                    { \"name\": \"storageId\",  \"$ref\": \"StorageId\" },\n                    { \"name\": \"key\", \"type\": \"string\" },\n                    { \"name\": \"oldValue\", \"type\": \"string\" },\n                    { \"name\": \"newValue\", \"type\": \"string\" }\n                ]\n            }\n        ]\n    },\n    {\n        \"domain\": \"ApplicationCache\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"ApplicationCacheResource\",\n                \"type\": \"object\",\n                \"description\": \"Detailed application cache resource information.\",\n                \"properties\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Resource url.\" },\n                    { \"name\": \"size\", \"type\": \"integer\", \"description\": \"Resource size.\" },\n                    { \"name\": \"type\", \"type\": \"string\", \"description\": \"Resource type.\" }\n                ]\n            },\n            {\n                \"id\": \"ApplicationCache\",\n                \"type\": \"object\",\n                \"description\": \"Detailed application cache information.\",\n                \"properties\": [\n                    { \"name\": \"manifestURL\", \"type\": \"string\", \"description\": \"Manifest URL.\" },\n                    { \"name\": \"size\", \"type\": \"number\", \"description\": \"Application cache size.\" },\n                    { \"name\": \"creationTime\", \"type\": \"number\", \"description\": \"Application cache creation time.\" },\n                    { \"name\": \"updateTime\", \"type\": \"number\", \"description\": \"Application cache update time.\" },\n                    { \"name\": \"resources\", \"type\": \"array\", \"items\": { \"$ref\": \"ApplicationCacheResource\" }, \"description\": \"Application cache resources.\" }\n                ]\n            },\n            {\n                \"id\": \"FrameWithManifest\",\n                \"type\": \"object\",\n                \"description\": \"Frame identifier - manifest URL pair.\",\n                \"properties\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Frame identifier.\" },\n                    { \"name\": \"manifestURL\", \"type\": \"string\", \"description\": \"Manifest URL.\" },\n                    { \"name\": \"status\", \"type\": \"integer\", \"description\": \"Application cache status.\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"getFramesWithManifests\",\n                \"returns\": [\n                    { \"name\": \"frameIds\", \"type\": \"array\", \"items\": { \"$ref\": \"FrameWithManifest\" }, \"description\": \"Array of frame identifiers with manifest urls for each frame containing a document associated with some application cache.\" }\n                ],\n                \"description\": \"Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache.\"\n            },\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables application cache domain notifications.\"\n            },\n            {\n                \"name\": \"getManifestForFrame\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Identifier of the frame containing document whose manifest is retrieved.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"manifestURL\", \"type\": \"string\", \"description\": \"Manifest URL for document in the given frame.\" }\n                ],\n                \"description\": \"Returns manifest URL for document in the given frame.\"\n            },\n            {\n                \"name\": \"getApplicationCacheForFrame\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Identifier of the frame containing document whose application cache is retrieved.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"applicationCache\", \"$ref\": \"ApplicationCache\", \"description\": \"Relevant application cache data for the document in given frame.\" }\n                ],\n                \"description\": \"Returns relevant application cache data for the document in given frame.\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"applicationCacheStatusUpdated\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Identifier of the frame containing document whose application cache updated status.\" },\n                    { \"name\": \"manifestURL\", \"type\": \"string\", \"description\": \"Manifest URL.\" },\n                    { \"name\": \"status\", \"type\": \"integer\", \"description\": \"Updated application cache status.\" }\n                ]\n            },\n            {\n                \"name\": \"networkStateUpdated\",\n                \"parameters\": [\n                    { \"name\": \"isNowOnline\", \"type\": \"boolean\" }\n                ]\n            }\n        ]\n    },\n    {\n        \"domain\": \"FileSystem\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"Entry\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"filesystem: URL for the entry.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"The name of the file or directory.\" },\n                    { \"name\": \"isDirectory\", \"type\": \"boolean\", \"description\": \"True if the entry is a directory.\" },\n                    { \"name\": \"mimeType\", \"type\": \"string\", \"optional\": true, \"description\": \"MIME type of the entry, available for a file only.\" },\n                    { \"name\": \"resourceType\", \"$ref\": \"Page.ResourceType\", \"optional\": true, \"description\": \"ResourceType of the entry, available for a file only.\" },\n                    { \"name\": \"isTextFile\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the entry is a text file.\" }\n                ],\n                \"description\": \"Represents a browser side file or directory.\"\n            },\n            {\n                \"id\": \"Metadata\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"modificationTime\", \"type\": \"number\", \"description\": \"Modification time.\" },\n                    { \"name\": \"size\", \"type\": \"number\", \"description\": \"File size. This field is always zero for directories.\" }\n                ],\n                \"description\": \"Represents metadata of a file or entry.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables events from backend.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables events from backend.\"\n            },\n            {\n                \"name\": \"requestFileSystemRoot\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"origin\", \"type\": \"string\", \"description\": \"Security origin of requesting FileSystem. One of frames in current page needs to have this security origin.\" },\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"temporary\", \"persistent\"], \"description\": \"FileSystem type of requesting FileSystem.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"errorCode\", \"type\": \"integer\", \"description\": \"0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.\" },\n                    { \"name\": \"root\", \"$ref\": \"Entry\", \"optional\": true, \"description\": \"Contains root of the requested FileSystem if the command completed successfully.\" }\n                ],\n                \"description\": \"Returns root directory of the FileSystem, if exists.\"\n            },\n            {\n                \"name\": \"requestDirectoryContent\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the directory that the frontend is requesting to read from.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"errorCode\", \"type\": \"integer\", \"description\": \"0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.\" },\n                    { \"name\": \"entries\", \"type\": \"array\", \"items\": { \"$ref\": \"Entry\" }, \"optional\": true, \"description\": \"Contains all entries on directory if the command completed successfully.\" }\n                ],\n                \"description\": \"Returns content of the directory.\"\n            },\n            {\n                \"name\": \"requestMetadata\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the entry that the frontend is requesting to get metadata from.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"errorCode\", \"type\": \"integer\", \"description\": \"0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.\" },\n                    { \"name\": \"metadata\", \"$ref\": \"Metadata\", \"optional\": true, \"description\": \"Contains metadata of the entry if the command completed successfully.\" }\n                ],\n                \"description\": \"Returns metadata of the entry.\"\n            },\n            {\n                \"name\": \"requestFileContent\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the file that the frontend is requesting to read from.\" },\n                    { \"name\": \"readAsText\", \"type\": \"boolean\", \"description\": \"True if the content should be read as text, otherwise the result will be returned as base64 encoded text.\" },\n                    { \"name\": \"start\", \"type\": \"integer\", \"optional\": true, \"description\": \"Specifies the start of range to read.\" },\n                    { \"name\": \"end\", \"type\": \"integer\", \"optional\": true, \"description\": \"Specifies the end of range to read exclusively.\" },\n                    { \"name\": \"charset\", \"type\": \"string\", \"optional\": true, \"description\": \"Overrides charset of the content when content is served as text.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"errorCode\", \"type\": \"integer\", \"description\": \"0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.\" },\n                    { \"name\": \"content\", \"type\": \"string\", \"optional\": true, \"description\": \"Content of the file.\" },\n                    { \"name\": \"charset\", \"type\": \"string\", \"optional\": true, \"description\": \"Charset of the content if it is served as text.\" }\n                ],\n                \"description\": \"Returns content of the file. Result should be sliced into [start, end).\"\n            },\n            {\n                \"name\": \"deleteEntry\",\n                \"async\": true,\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the entry to delete.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"errorCode\", \"type\": \"integer\", \"description\": \"0, if no error. Otherwise errorCode is set to FileError::ErrorCode value.\" }\n                ],\n                \"description\": \"Deletes specified entry. If the entry is a directory, the agent deletes children recursively.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"DOM\",\n        \"description\": \"This domain exposes DOM read/write operations. Each DOM Node is represented with its mirror object that has an <code>id</code>. This <code>id</code> can be used to get additional information on the Node, resolve it into the JavaScript object wrapper, etc. It is important that client receives DOM events only for the nodes that are known to the client. Backend keeps track of the nodes that were sent to the client and never sends the same node twice. It is client's responsibility to collect information about the nodes that were sent to the client.<p>Note that <code>iframe</code> owner elements will return corresponding document elements as their child nodes.</p>\",\n        \"types\": [\n            {\n                \"id\": \"NodeId\",\n                \"type\": \"integer\",\n                \"description\": \"Unique DOM node identifier.\"\n            },\n            {\n                \"id\": \"BackendNodeId\",\n                \"type\": \"integer\",\n                \"description\": \"Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"PseudoType\",\n                \"type\": \"string\",\n                \"enum\": [\"before\", \"after\"],\n                \"description\": \"Pseudo element type.\"\n            },\n            {\n                \"id\": \"Node\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Node identifier that is passed into the rest of the DOM messages as the <code>nodeId</code>. Backend will only push node with given <code>id</code> once. It is aware of all requested nodes and will only fire DOM events for nodes known to the client.\" },\n                    { \"name\": \"nodeType\", \"type\": \"integer\", \"description\": \"<code>Node</code>'s nodeType.\" },\n                    { \"name\": \"nodeName\", \"type\": \"string\", \"description\": \"<code>Node</code>'s nodeName.\" },\n                    { \"name\": \"localName\", \"type\": \"string\", \"description\": \"<code>Node</code>'s localName.\" },\n                    { \"name\": \"nodeValue\", \"type\": \"string\", \"description\": \"<code>Node</code>'s nodeValue.\" },\n                    { \"name\": \"childNodeCount\", \"type\": \"integer\", \"optional\": true, \"description\": \"Child count for <code>Container</code> nodes.\" },\n                    { \"name\": \"children\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"Node\" }, \"description\": \"Child nodes of this node when requested with children.\" },\n                    { \"name\": \"attributes\", \"type\": \"array\", \"optional\": true, \"items\": { \"type\": \"string\" }, \"description\": \"Attributes of the <code>Element</code> node in the form of flat array <code>[name1, value1, name2, value2]</code>.\" },\n                    { \"name\": \"documentURL\", \"type\": \"string\", \"optional\": true, \"description\": \"Document URL that <code>Document</code> or <code>FrameOwner</code> node points to.\" },\n                    { \"name\": \"baseURL\", \"type\": \"string\", \"optional\": true, \"description\": \"Base URL that <code>Document</code> or <code>FrameOwner</code> node uses for URL completion.\", \"hidden\": true },\n                    { \"name\": \"publicId\", \"type\": \"string\", \"optional\": true, \"description\": \"<code>DocumentType</code>'s publicId.\" },\n                    { \"name\": \"systemId\", \"type\": \"string\", \"optional\": true, \"description\": \"<code>DocumentType</code>'s systemId.\" },\n                    { \"name\": \"internalSubset\", \"type\": \"string\", \"optional\": true, \"description\": \"<code>DocumentType</code>'s internalSubset.\" },\n                    { \"name\": \"xmlVersion\", \"type\": \"string\", \"optional\": true, \"description\": \"<code>Document</code>'s XML version in case of XML documents.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"optional\": true, \"description\": \"<code>Attr</code>'s name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"optional\": true, \"description\": \"<code>Attr</code>'s value.\" },\n                    { \"name\": \"pseudoType\", \"$ref\": \"PseudoType\", \"optional\": true, \"description\": \"Pseudo element type for this node.\" },\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"optional\": true, \"description\": \"Frame ID for frame owner elements.\", \"hidden\": true },\n                    { \"name\": \"contentDocument\", \"$ref\": \"Node\", \"optional\": true, \"description\": \"Content document for frame owner elements.\" },\n                    { \"name\": \"shadowRoots\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"Node\" }, \"description\": \"Shadow root list for given element host.\", \"hidden\": true },\n                    { \"name\": \"templateContent\", \"$ref\": \"Node\", \"optional\": true, \"description\": \"Content document fragment for template elements.\", \"hidden\": true },\n                    { \"name\": \"pseudoElements\", \"type\": \"array\", \"items\": { \"$ref\": \"Node\" }, \"optional\": true, \"description\": \"Pseudo elements associated with this node.\", \"hidden\": true }\n                ],\n                \"description\": \"DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.\"\n            },\n            {\n                \"id\": \"EventListener\",\n                \"type\": \"object\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"description\": \"<code>EventListener</code>'s type.\" },\n                    { \"name\": \"useCapture\", \"type\": \"boolean\", \"description\": \"<code>EventListener</code>'s useCapture.\" },\n                    { \"name\": \"isAttribute\", \"type\": \"boolean\", \"description\": \"<code>EventListener</code>'s isAttribute.\" },\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Target <code>DOMNode</code> id.\" },\n                    { \"name\": \"handlerBody\", \"type\": \"string\", \"description\": \"Event handler function body.\" },\n                    { \"name\": \"location\", \"$ref\": \"Debugger.Location\", \"optional\": true, \"description\": \"Handler code location.\" },\n                    { \"name\": \"sourceName\", \"type\": \"string\", \"optional\": true, \"description\": \"Source script URL.\" },\n                    { \"name\": \"handler\", \"$ref\": \"Runtime.RemoteObject\", \"optional\": true, \"description\": \"Event handler function value.\" }\n                ],\n                \"description\": \"DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.\"\n            },\n            {\n                \"id\": \"RGBA\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"r\", \"type\": \"integer\", \"description\": \"The red component, in the [0-255] range.\" },\n                    { \"name\": \"g\", \"type\": \"integer\", \"description\": \"The green component, in the [0-255] range.\" },\n                    { \"name\": \"b\", \"type\": \"integer\", \"description\": \"The blue component, in the [0-255] range.\" },\n                    { \"name\": \"a\", \"type\": \"number\", \"optional\": true, \"description\": \"The alpha component, in the [0-1] range (default: 1).\" }\n                ],\n                \"description\": \"A structure holding an RGBA color.\"\n            },\n            {\n                \"id\": \"Quad\",\n                \"type\": \"array\",\n                \"items\": { \"type\": \"number\" },\n                \"minItems\": 8,\n                \"maxItems\": 8,\n                \"description\": \"An array of quad vertices, x immediately followed by y for each point, points clock-wise.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"BoxModel\",\n                \"type\": \"object\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"content\", \"$ref\": \"Quad\", \"description\": \"Content box\" },\n                    { \"name\": \"padding\", \"$ref\": \"Quad\", \"description\": \"Padding box\" },\n                    { \"name\": \"border\", \"$ref\": \"Quad\", \"description\": \"Border box\" },\n                    { \"name\": \"margin\", \"$ref\": \"Quad\", \"description\": \"Margin box\" },\n                    { \"name\": \"width\", \"type\": \"integer\", \"description\": \"Node width\" },\n                    { \"name\": \"height\", \"type\": \"integer\", \"description\": \"Node height\" }\n                ],\n                \"description\": \"Box model.\"\n            },\n            {\n                \"id\": \"Rect\",\n                \"type\": \"object\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"x\", \"type\": \"number\", \"description\": \"X coordinate\" },\n                    { \"name\": \"y\", \"type\": \"number\", \"description\": \"Y coordinate\" },\n                    { \"name\": \"width\", \"type\": \"number\", \"description\": \"Rectangle width\" },\n                    { \"name\": \"height\", \"type\": \"number\", \"description\": \"Rectangle height\" }\n                ],\n                \"description\": \"Rectangle.\"\n            },\n            {\n                \"id\": \"HighlightConfig\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"showInfo\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the node info tooltip should be shown (default: false).\" },\n                    { \"name\": \"contentColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The content box highlight fill color (default: transparent).\" },\n                    { \"name\": \"paddingColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The padding highlight fill color (default: transparent).\" },\n                    { \"name\": \"borderColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The border highlight fill color (default: transparent).\" },\n                    { \"name\": \"marginColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The margin highlight fill color (default: transparent).\" },\n                    { \"name\": \"eventTargetColor\", \"$ref\": \"RGBA\", \"optional\": true, \"hidden\": true, \"description\": \"The event target element highlight fill color (default: transparent).\" }\n                ],\n                \"description\": \"Configuration data for the highlighting of page elements.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables DOM agent for the given page.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables DOM agent for the given page.\"\n            },\n            {\n                \"name\": \"getDocument\",\n                \"returns\": [\n                    { \"name\": \"root\", \"$ref\": \"Node\", \"description\": \"Resulting node.\" }\n                ],\n                \"description\": \"Returns the root DOM node to the caller.\"\n            },\n            {\n                \"name\": \"requestChildNodes\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to get children for.\" },\n                    { \"name\": \"depth\", \"type\": \"integer\", \"optional\": true, \"description\": \"The maximum depth at which children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0.\", \"hidden\": true }\n                ],\n                \"description\": \"Requests that children of the node with given id are returned to the caller in form of <code>setChildNodes</code> events where not only immediate children are retrieved, but all children down to the specified depth.\"\n            },\n            {\n                \"name\": \"querySelector\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to query upon.\" },\n                    { \"name\": \"selector\", \"type\": \"string\", \"description\": \"Selector string.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Query selector result.\" }\n                ],\n                \"description\": \"Executes <code>querySelector</code> on a given node.\"\n            },\n            {\n                \"name\": \"querySelectorAll\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to query upon.\" },\n                    { \"name\": \"selector\", \"type\": \"string\", \"description\": \"Selector string.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeIds\", \"type\": \"array\", \"items\": { \"$ref\": \"NodeId\" }, \"description\": \"Query selector result.\" }\n                ],\n                \"description\": \"Executes <code>querySelectorAll</code> on a given node.\"\n            },\n            {\n                \"name\": \"setNodeName\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to set name for.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"New node's name.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"New node's id.\" }\n                ],\n                \"description\": \"Sets node name for a node with given id.\"\n            },\n            {\n                \"name\": \"setNodeValue\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to set value for.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"New node's value.\" }\n                ],\n                \"description\": \"Sets node value for a node with given id.\"\n            },\n            {\n                \"name\": \"removeNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to remove.\" }\n                ],\n                \"description\": \"Removes node with given id.\"\n            },\n            {\n                \"name\": \"setAttributeValue\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the element to set attribute for.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Attribute name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"Attribute value.\" }\n                ],\n                \"description\": \"Sets attribute for an element with given id.\"\n            },\n            {\n                \"name\": \"setAttributesAsText\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the element to set attributes for.\" },\n                    { \"name\": \"text\", \"type\": \"string\", \"description\": \"Text with a number of attributes. Will parse this text using HTML parser.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"optional\": true, \"description\": \"Attribute name to replace with new attributes derived from text in case text parsed successfully.\" }\n                ],\n                \"description\": \"Sets attributes on element with given id. This method is useful when user edits some existing attribute value and types in several attribute name/value pairs.\"\n            },\n            {\n                \"name\": \"removeAttribute\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the element to remove attribute from.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Name of the attribute to remove.\" }\n                ],\n                \"description\": \"Removes attribute with given name from an element with given id.\"\n            },\n            {\n                \"name\": \"getEventListenersForNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to get listeners for.\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"Symbolic group name for handler value. Handler value is not returned without this parameter specified.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"listeners\", \"type\": \"array\", \"items\": { \"$ref\": \"EventListener\"}, \"description\": \"Array of relevant listeners.\" }\n                ],\n                \"description\": \"Returns event listeners relevant to the node.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getOuterHTML\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to get markup for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"outerHTML\", \"type\": \"string\", \"description\": \"Outer HTML markup.\" }\n                ],\n                \"description\": \"Returns node's HTML markup.\"\n            },\n            {\n                \"name\": \"setOuterHTML\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to set markup for.\" },\n                    { \"name\": \"outerHTML\", \"type\": \"string\", \"description\": \"Outer HTML markup to set.\" }\n                ],\n                \"description\": \"Sets node HTML markup, returns new node id.\"\n            },\n            {\n                \"name\": \"performSearch\",\n                \"parameters\": [\n                    { \"name\": \"query\", \"type\": \"string\", \"description\": \"Plain text or query selector or XPath search query.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"searchId\", \"type\": \"string\", \"description\": \"Unique search session identifier.\" },\n                    { \"name\": \"resultCount\", \"type\": \"integer\", \"description\": \"Number of search results.\" }\n                ],\n                \"description\": \"Searches for a given string in the DOM tree. Use <code>getSearchResults</code> to access search results or <code>cancelSearch</code> to end this search session.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getSearchResults\",\n                \"parameters\": [\n                    { \"name\": \"searchId\", \"type\": \"string\", \"description\": \"Unique search session identifier.\" },\n                    { \"name\": \"fromIndex\", \"type\": \"integer\", \"description\": \"Start index of the search result to be returned.\" },\n                    { \"name\": \"toIndex\", \"type\": \"integer\", \"description\": \"End index of the search result to be returned.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeIds\", \"type\": \"array\", \"items\": { \"$ref\": \"NodeId\" }, \"description\": \"Ids of the search result nodes.\" }\n                ],\n                \"description\": \"Returns search results from given <code>fromIndex</code> to given <code>toIndex</code> from the sarch with the given identifier.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"discardSearchResults\",\n                \"parameters\": [\n                    { \"name\": \"searchId\", \"type\": \"string\", \"description\": \"Unique search session identifier.\" }\n                ],\n                \"description\": \"Discards search results from the session with the given id. <code>getSearchResults</code> should no longer be called for that search.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"requestNode\",\n                \"parameters\": [\n                    { \"name\": \"objectId\", \"$ref\": \"Runtime.RemoteObjectId\", \"description\": \"JavaScript object id to convert into node.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Node id for given object.\" }\n                ],\n                \"description\": \"Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of <code>setChildNodes</code> notifications.\"\n            },\n            {\n                \"name\": \"setInspectModeEnabled\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"enabled\", \"type\": \"boolean\", \"description\": \"True to enable inspection mode, false to disable it.\" },\n                    { \"name\": \"inspectShadowDOM\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True to enable inspection mode for shadow DOM.\" },\n                    { \"name\": \"highlightConfig\", \"$ref\": \"HighlightConfig\", \"optional\": true, \"description\": \"A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>.\" }\n                ],\n                \"description\": \"Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection.\"\n            },\n            {\n                \"name\": \"highlightRect\",\n                \"parameters\": [\n                    { \"name\": \"x\", \"type\": \"integer\", \"description\": \"X coordinate\" },\n                    { \"name\": \"y\", \"type\": \"integer\", \"description\": \"Y coordinate\" },\n                    { \"name\": \"width\", \"type\": \"integer\", \"description\": \"Rectangle width\" },\n                    { \"name\": \"height\", \"type\": \"integer\", \"description\": \"Rectangle height\" },\n                    { \"name\": \"color\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The highlight fill color (default: transparent).\" },\n                    { \"name\": \"outlineColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The highlight outline color (default: transparent).\" }\n                ],\n                \"description\": \"Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport.\"\n            },\n            {\n                \"name\": \"highlightQuad\",\n                \"parameters\": [\n                    { \"name\": \"quad\", \"$ref\": \"Quad\", \"description\": \"Quad to highlight\" },\n                    { \"name\": \"color\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The highlight fill color (default: transparent).\" },\n                    { \"name\": \"outlineColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The highlight outline color (default: transparent).\" }\n                ],\n                \"description\": \"Highlights given quad. Coordinates are absolute with respect to the main frame viewport.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"highlightNode\",\n                \"parameters\": [\n                    { \"name\": \"highlightConfig\", \"$ref\": \"HighlightConfig\",  \"description\": \"A descriptor for the highlight appearance.\" },\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"optional\": true, \"description\": \"Identifier of the node to highlight.\" },\n                    { \"name\": \"objectId\", \"$ref\": \"Runtime.RemoteObjectId\", \"optional\": true, \"description\": \"JavaScript object id of the node to be highlighted.\", \"hidden\": true }\n                ],\n                \"description\": \"Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified.\"\n            },\n            {\n                \"name\": \"hideHighlight\",\n                \"description\": \"Hides DOM node highlight.\"\n            },\n            {\n                \"name\": \"highlightFrame\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Identifier of the frame to highlight.\" },\n                    { \"name\": \"contentColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The content box highlight fill color (default: transparent).\" },\n                    { \"name\": \"contentOutlineColor\", \"$ref\": \"RGBA\", \"optional\": true, \"description\": \"The content box highlight outline color (default: transparent).\" }\n                ],\n                \"description\": \"Highlights owner element of the frame with given id.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"pushNodeByPathToFrontend\",\n                \"parameters\": [\n                    { \"name\": \"path\", \"type\": \"string\", \"description\": \"Path to node in the proprietary format.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node for given path.\" }\n                ],\n                \"description\": \"Requests that the node is sent to the caller given its path. // FIXME, use XPath\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"pushNodeByBackendIdToFrontend\",\n                \"parameters\": [\n                    { \"name\": \"backendNodeId\", \"$ref\": \"BackendNodeId\", \"description\": \"The backend node id of the node.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"The pushed node's id.\" }\n                ],\n                \"description\": \"Requests that the node is sent to the caller given its backend node id.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"releaseBackendNodeIds\",\n                \"parameters\": [\n                    { \"name\": \"nodeGroup\", \"type\": \"string\", \"description\": \"The backend node ids group name.\" }\n                ],\n                \"description\": \"Requests that group of <code>BackendNodeIds</code> is released.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"resolveNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to resolve.\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"Symbolic group name that can be used to release multiple objects.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"object\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"JavaScript object wrapper for given node.\" }\n                ],\n                \"description\": \"Resolves JavaScript node object for given node id.\"\n            },\n            {\n                \"name\": \"getAttributes\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to retrieve attibutes for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"attributes\", \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"An interleaved array of node attribute names and values.\" }\n                ],\n                \"description\": \"Returns attributes for the specified node.\"\n            },\n            {\n                \"name\": \"moveTo\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to drop.\" },\n                    { \"name\": \"targetNodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the element to drop into.\" },\n                    { \"name\": \"insertBeforeNodeId\", \"$ref\": \"NodeId\", \"optional\": true, \"description\": \"Drop node before given one.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"New id of the moved node.\" }\n                ],\n                \"description\": \"Moves node into the new container, places it before the given anchor.\"\n            },\n            {\n                \"name\": \"undo\",\n                \"description\": \"Undoes the last performed action.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"redo\",\n                \"description\": \"Re-does the last undone action.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"markUndoableState\",\n                \"description\": \"Marks last undoable state.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"focus\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to focus.\" }\n                ],\n                \"description\": \"Focuses the given element.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setFileInputFiles\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the file input node to set files for.\" },\n                    { \"name\": \"files\", \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"Array of file paths to set.\" }\n                ],\n                \"description\": \"Sets files for the given file input element.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getBoxModel\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to get box model for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"model\", \"$ref\": \"BoxModel\", \"description\": \"Box model for the node.\" }\n                ],\n                \"description\": \"Returns boxes for the currently selected nodes.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getNodeForLocation\",\n                \"parameters\": [\n                    { \"name\": \"x\", \"type\": \"integer\", \"description\": \"X coordinate.\" },\n                    { \"name\": \"y\", \"type\": \"integer\", \"description\": \"Y coordinate.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node at given coordinates.\" }\n                ],\n                \"description\": \"Returns node id at given location.\",\n                \"hidden\": true\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"documentUpdated\",\n                \"description\": \"Fired when <code>Document</code> has been totally updated. Node ids are no longer valid.\"\n            },\n            {\n                \"name\": \"inspectNodeRequested\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node to inspect.\" }\n                ],\n                \"description\": \"Fired when the node should be inspected. This happens after call to <code>setInspectModeEnabled</code>.\",\n                \"hidden\" : true\n            },\n            {\n                \"name\": \"setChildNodes\",\n                \"parameters\": [\n                    { \"name\": \"parentId\", \"$ref\": \"NodeId\", \"description\": \"Parent node id to populate with children.\" },\n                    { \"name\": \"nodes\", \"type\": \"array\", \"items\": { \"$ref\": \"Node\"}, \"description\": \"Child nodes array.\" }\n                ],\n                \"description\": \"Fired when backend wants to provide client with the missing DOM structure. This happens upon most of the calls requesting node ids.\"\n            },\n            {\n                \"name\": \"attributeModified\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node that has changed.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Attribute name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"Attribute value.\" }\n                ],\n                \"description\": \"Fired when <code>Element</code>'s attribute is modified.\"\n            },\n            {\n                \"name\": \"attributeRemoved\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node that has changed.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"A ttribute name.\" }\n                ],\n                \"description\": \"Fired when <code>Element</code>'s attribute is removed.\"\n            },\n            {\n                \"name\": \"inlineStyleInvalidated\",\n                \"parameters\": [\n                    { \"name\": \"nodeIds\", \"type\": \"array\", \"items\": { \"$ref\": \"NodeId\" }, \"description\": \"Ids of the nodes for which the inline styles have been invalidated.\" }\n                ],\n                \"description\": \"Fired when <code>Element</code>'s inline style is modified via a CSS property modification.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"characterDataModified\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node that has changed.\" },\n                    { \"name\": \"characterData\", \"type\": \"string\", \"description\": \"New text value.\" }\n                ],\n                \"description\": \"Mirrors <code>DOMCharacterDataModified</code> event.\"\n            },\n            {\n                \"name\": \"childNodeCountUpdated\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node that has changed.\" },\n                    { \"name\": \"childNodeCount\", \"type\": \"integer\", \"description\": \"New node count.\" }\n                ],\n                \"description\": \"Fired when <code>Container</code>'s child node count has changed.\"\n            },\n            {\n                \"name\": \"childNodeInserted\",\n                \"parameters\": [\n                    { \"name\": \"parentNodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node that has changed.\" },\n                    { \"name\": \"previousNodeId\", \"$ref\": \"NodeId\", \"description\": \"If of the previous siblint.\" },\n                    { \"name\": \"node\", \"$ref\": \"Node\", \"description\": \"Inserted node data.\" }\n                ],\n                \"description\": \"Mirrors <code>DOMNodeInserted</code> event.\"\n            },\n            {\n                \"name\": \"childNodeRemoved\",\n                \"parameters\": [\n                    { \"name\": \"parentNodeId\", \"$ref\": \"NodeId\", \"description\": \"Parent id.\" },\n                    { \"name\": \"nodeId\", \"$ref\": \"NodeId\", \"description\": \"Id of the node that has been removed.\" }\n                ],\n                \"description\": \"Mirrors <code>DOMNodeRemoved</code> event.\"\n            },\n            {\n                \"name\": \"shadowRootPushed\",\n                \"parameters\": [\n                    { \"name\": \"hostId\", \"$ref\": \"NodeId\", \"description\": \"Host element id.\" },\n                    { \"name\": \"root\", \"$ref\": \"Node\", \"description\": \"Shadow root.\" }\n                ],\n                \"description\": \"Called when shadow root is pushed into the element.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"shadowRootPopped\",\n                \"parameters\": [\n                    { \"name\": \"hostId\", \"$ref\": \"NodeId\", \"description\": \"Host element id.\" },\n                    { \"name\": \"rootId\", \"$ref\": \"NodeId\", \"description\": \"Shadow root id.\" }\n                ],\n                \"description\": \"Called when shadow root is popped from the element.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"pseudoElementAdded\",\n                \"parameters\": [\n                    { \"name\": \"parentId\", \"$ref\": \"NodeId\", \"description\": \"Pseudo element's parent element id.\" },\n                    { \"name\": \"pseudoElement\", \"$ref\": \"Node\", \"description\": \"The added pseudo element.\" }\n                ],\n                \"description\": \"Called when a pseudo element is added to an element.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"pseudoElementRemoved\",\n                \"parameters\": [\n                    { \"name\": \"parentId\", \"$ref\": \"NodeId\", \"description\": \"Pseudo element's parent element id.\" },\n                    { \"name\": \"pseudoElementId\", \"$ref\": \"NodeId\", \"description\": \"The removed pseudo element id.\" }\n                ],\n                \"description\": \"Called when a pseudo element is removed from an element.\",\n                \"hidden\": true\n            }\n        ]\n    },\n    {\n        \"domain\": \"CSS\",\n        \"hidden\": true,\n        \"description\": \"This domain exposes CSS read/write operations. All CSS objects (stylesheets, rules, and styles) have an associated <code>id</code> used in subsequent operations on the related object. Each object type has a specific <code>id</code> structure, and those are not interchangeable between objects of different kinds. CSS objects can be loaded using the <code>get*ForNode()</code> calls (which accept a DOM node id). A client can also discover all the existing stylesheets with the <code>getAllStyleSheets()</code> method (or keeping track of the <code>styleSheetAdded</code>/<code>styleSheetRemoved</code> events) and subsequently load the required stylesheet contents using the <code>getStyleSheet[Text]()</code> methods.\",\n        \"types\": [\n            {\n                \"id\": \"StyleSheetId\",\n                \"type\": \"string\"\n            },\n            {\n                \"id\": \"CSSStyleId\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\", \"description\": \"Enclosing stylesheet identifier.\" },\n                    { \"name\": \"ordinal\", \"type\": \"integer\", \"description\": \"The style ordinal within the stylesheet.\" }\n                ],\n                \"description\": \"This object identifies a CSS style in a unique way.\"\n            },\n            {\n                \"id\": \"StyleSheetOrigin\",\n                \"type\": \"string\",\n                \"enum\": [\"user\", \"user-agent\", \"inspector\", \"regular\"],\n                \"description\": \"Stylesheet type: \\\"user\\\" for user stylesheets, \\\"user-agent\\\" for user-agent stylesheets, \\\"inspector\\\" for stylesheets created by the inspector (i.e. those holding the \\\"via inspector\\\" rules), \\\"regular\\\" for regular stylesheets.\"\n            },\n            {\n                \"id\": \"CSSRuleId\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\", \"description\": \"Enclosing stylesheet identifier.\" },\n                    { \"name\": \"ordinal\", \"type\": \"integer\", \"description\": \"The rule ordinal within the stylesheet.\" }\n                ],\n                \"description\": \"This object identifies a CSS rule in a unique way.\"\n            },\n            {\n                \"id\": \"PseudoIdMatches\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"pseudoId\", \"type\": \"integer\", \"description\": \"Pseudo style identifier (see <code>enum PseudoId</code> in <code>RenderStyleConstants.h</code>).\"},\n                    { \"name\": \"matches\", \"type\": \"array\", \"items\": { \"$ref\": \"RuleMatch\" }, \"description\": \"Matches of CSS rules applicable to the pseudo style.\"}\n                ],\n                \"description\": \"CSS rule collection for a single pseudo style.\"\n            },\n            {\n                \"id\": \"InheritedStyleEntry\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"inlineStyle\", \"$ref\": \"CSSStyle\", \"optional\": true, \"description\": \"The ancestor node's inline style, if any, in the style inheritance chain.\" },\n                    { \"name\": \"matchedCSSRules\", \"type\": \"array\", \"items\": { \"$ref\": \"RuleMatch\" }, \"description\": \"Matches of CSS rules matching the ancestor node in the style inheritance chain.\" }\n                ],\n                \"description\": \"CSS rule collection for a single pseudo style.\"\n            },\n            {\n                \"id\": \"RuleMatch\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"rule\", \"$ref\": \"CSSRule\", \"description\": \"CSS rule in the match.\" },\n                    { \"name\": \"matchingSelectors\", \"type\": \"array\", \"items\": { \"type\": \"integer\" }, \"description\": \"Matching selector indices in the rule's selectorList selectors (0-based).\" }\n                ],\n                \"description\": \"Match data for a CSS rule.\"\n            },\n            {\n                \"id\": \"SelectorList\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"selectors\", \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"Selectors in the list.\" },\n                    { \"name\": \"text\", \"type\": \"string\", \"description\": \"Rule selector text.\" },\n                    { \"name\": \"range\", \"$ref\": \"SourceRange\", \"optional\": true, \"description\": \"Rule selector range in the underlying resource (if available).\" }\n                ],\n                \"description\": \"Selector list data.\"\n            },\n            {\n                \"id\": \"CSSStyleAttribute\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"DOM attribute name (e.g. \\\"width\\\").\"},\n                    { \"name\": \"style\", \"$ref\": \"CSSStyle\", \"description\": \"CSS style generated by the respective DOM attribute.\"}\n                ],\n                \"description\": \"CSS style information for a DOM style attribute.\"\n            },\n            {\n                \"id\": \"CSSStyleSheetHeader\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\", \"description\": \"The stylesheet identifier.\"},\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Owner frame identifier.\"},\n                    { \"name\": \"sourceURL\", \"type\": \"string\", \"description\": \"Stylesheet resource URL.\"},\n                    { \"name\": \"sourceMapURL\", \"type\": \"string\", \"optional\": true, \"description\": \"URL of source map associated with the stylesheet (if any).\" },\n                    { \"name\": \"origin\", \"$ref\": \"StyleSheetOrigin\", \"description\": \"Stylesheet origin.\"},\n                    { \"name\": \"title\", \"type\": \"string\", \"description\": \"Stylesheet title.\"},\n                    { \"name\": \"disabled\", \"type\": \"boolean\", \"description\": \"Denotes whether the stylesheet is disabled.\"},\n                    { \"name\": \"hasSourceURL\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the sourceURL field value comes from the sourceURL comment.\" },\n                    { \"name\": \"isInline\", \"type\": \"boolean\", \"description\": \"Whether this stylesheet is created for STYLE tag by parser. This flag is not set for document.written STYLE tags.\" },\n                    { \"name\": \"startLine\", \"type\": \"number\", \"description\": \"Line offset of the stylesheet within the resource (zero based).\" },\n                    { \"name\": \"startColumn\", \"type\": \"number\", \"description\": \"Column offset of the stylesheet within the resource (zero based).\" }\n                ],\n                \"description\": \"CSS stylesheet metainformation.\"\n            },\n            {\n                \"id\": \"CSSStyleSheetBody\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\", \"description\": \"The stylesheet identifier.\"},\n                    { \"name\": \"rules\", \"type\": \"array\", \"items\": { \"$ref\": \"CSSRule\" }, \"description\": \"Stylesheet resource URL.\"},\n                    { \"name\": \"text\", \"type\": \"string\", \"optional\": true, \"description\": \"Stylesheet resource contents (if available).\"}\n                ],\n                \"description\": \"CSS stylesheet contents.\"\n            },\n            {\n                \"id\": \"CSSRule\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"ruleId\", \"$ref\": \"CSSRuleId\", \"optional\": true, \"description\": \"The CSS rule identifier (absent for user agent stylesheet and user-specified stylesheet rules).\"},\n                    { \"name\": \"selectorList\", \"$ref\": \"SelectorList\", \"description\": \"Rule selector data.\" },\n                    { \"name\": \"sourceURL\", \"type\": \"string\", \"optional\": true, \"description\": \"Parent stylesheet resource URL (for regular rules).\"},\n                    { \"name\": \"origin\", \"$ref\": \"StyleSheetOrigin\", \"description\": \"Parent stylesheet's origin.\"},\n                    { \"name\": \"style\", \"$ref\": \"CSSStyle\", \"description\": \"Associated style declaration.\" },\n                    { \"name\": \"media\", \"type\": \"array\", \"items\": { \"$ref\": \"CSSMedia\" }, \"optional\": true, \"description\": \"Media list array (for rules involving media queries). The array enumerates media queries starting with the innermost one, going outwards.\" }\n                ],\n                \"description\": \"CSS rule representation.\"\n            },\n            {\n                \"id\": \"SourceRange\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"startLine\", \"type\": \"integer\", \"description\": \"Start line of range.\" },\n                    { \"name\": \"startColumn\", \"type\": \"integer\", \"description\": \"Start column of range (inclusive).\" },\n                    { \"name\": \"endLine\", \"type\": \"integer\", \"description\": \"End line of range\" },\n                    { \"name\": \"endColumn\", \"type\": \"integer\", \"description\": \"End column of range (exclusive).\" }\n                ],\n                \"description\": \"Text range within a resource. All numbers are zero-based.\"\n            },\n            {\n                \"id\": \"ShorthandEntry\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Shorthand name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"Shorthand value.\" }\n                ]\n            },\n            {\n                \"id\": \"CSSPropertyInfo\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Property name.\" },\n                    { \"name\": \"longhands\", \"type\": \"array\", \"optional\": true, \"items\": { \"type\": \"string\" }, \"description\": \"Longhand property names.\" }\n                ]\n            },\n            {\n                \"id\": \"CSSComputedStyleProperty\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Computed style property name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"Computed style property value.\" }\n                ]\n            },\n            {\n                \"id\": \"CSSStyle\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"styleId\", \"$ref\": \"CSSStyleId\", \"optional\": true, \"description\": \"The CSS style identifier (absent for attribute styles).\" },\n                    { \"name\": \"cssProperties\", \"type\": \"array\", \"items\": { \"$ref\": \"CSSProperty\" }, \"description\": \"CSS properties in the style.\" },\n                    { \"name\": \"shorthandEntries\", \"type\": \"array\", \"items\": { \"$ref\": \"ShorthandEntry\" }, \"description\": \"Computed values for all shorthands found in the style.\" },\n                    { \"name\": \"cssText\", \"type\": \"string\", \"optional\": true, \"description\": \"Style declaration text (if available).\" },\n                    { \"name\": \"range\", \"$ref\": \"SourceRange\", \"optional\": true, \"description\": \"Style declaration range in the enclosing stylesheet (if available).\" },\n                    { \"name\": \"width\", \"type\": \"string\", \"optional\": true, \"description\": \"The effective \\\"width\\\" property value from this style.\" },\n                    { \"name\": \"height\", \"type\": \"string\", \"optional\": true, \"description\": \"The effective \\\"height\\\" property value from this style.\" }\n                ],\n                \"description\": \"CSS style representation.\"\n            },\n            {\n                \"id\": \"CSSProperty\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"The property name.\" },\n                    { \"name\": \"value\", \"type\": \"string\", \"description\": \"The property value.\" },\n                    { \"name\": \"priority\", \"type\": \"string\", \"optional\": true, \"description\": \"The property priority (implies \\\"\\\" if absent).\" },\n                    { \"name\": \"implicit\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the property is implicit (implies <code>false</code> if absent).\" },\n                    { \"name\": \"text\", \"type\": \"string\", \"optional\": true, \"description\": \"The full property text as specified in the style.\" },\n                    { \"name\": \"parsedOk\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the property is understood by the browser (implies <code>true</code> if absent).\" },\n                    { \"name\": \"status\", \"type\": \"string\", \"enum\": [\"active\", \"inactive\", \"disabled\", \"style\"], \"optional\": true, \"description\": \"The property status: \\\"active\\\" if the property is effective in the style, \\\"inactive\\\" if the property is overridden by a same-named property in this style later on, \\\"disabled\\\" if the property is disabled by the user, \\\"style\\\" (implied if absent) if the property is reported by the browser rather than by the CSS source parser.\" },\n                    { \"name\": \"range\", \"$ref\": \"SourceRange\", \"optional\": true, \"description\": \"The entire property range in the enclosing style declaration (if available).\" }\n                ],\n                \"description\": \"CSS property declaration data.\"\n            },\n            {\n                \"id\": \"CSSMedia\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"text\", \"type\": \"string\", \"description\": \"Media query text.\" },\n                    { \"name\": \"source\", \"type\": \"string\", \"enum\": [\"mediaRule\", \"importRule\", \"linkedSheet\", \"inlineSheet\"], \"description\": \"Source of the media query: \\\"mediaRule\\\" if specified by a @media rule, \\\"importRule\\\" if specified by an @import rule, \\\"linkedSheet\\\" if specified by a \\\"media\\\" attribute in a linked stylesheet's LINK tag, \\\"inlineSheet\\\" if specified by a \\\"media\\\" attribute in an inline stylesheet's STYLE tag.\" },\n                    { \"name\": \"sourceURL\", \"type\": \"string\", \"optional\": true, \"description\": \"URL of the document containing the media query description.\" },\n                    { \"name\": \"range\", \"$ref\": \"SourceRange\", \"optional\": true, \"description\": \"The associated rule (@media or @import) header range in the enclosing stylesheet (if available).\" },\n                    { \"name\": \"parentStyleSheetId\", \"$ref\": \"StyleSheetId\", \"optional\": true, \"description\": \"Identifier of the stylesheet containing this object (if exists).\" }\n                ],\n                \"description\": \"CSS media query descriptor.\"\n            },\n            {\n                \"id\": \"SelectorProfileEntry\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"selector\", \"type\": \"string\", \"description\": \"CSS selector of the corresponding rule.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the resource containing the corresponding rule.\" },\n                    { \"name\": \"lineNumber\", \"type\": \"integer\", \"description\": \"Selector line number in the resource for the corresponding rule.\" },\n                    { \"name\": \"time\", \"type\": \"number\", \"description\": \"Total time this rule handling contributed to the browser running time during profiling (in milliseconds).\" },\n                    { \"name\": \"hitCount\", \"type\": \"integer\", \"description\": \"Number of times this rule was considered a candidate for matching against DOM elements.\" },\n                    { \"name\": \"matchCount\", \"type\": \"integer\", \"description\": \"Number of times this rule actually matched a DOM element.\" }\n                ],\n                \"description\": \"CSS selector profile entry.\"\n            },\n            {\n                \"id\": \"SelectorProfile\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"totalTime\", \"type\": \"number\", \"description\": \"Total processing time for all selectors in the profile (in milliseconds).\" },\n                    { \"name\": \"data\", \"type\": \"array\", \"items\": { \"$ref\": \"SelectorProfileEntry\" }, \"description\": \"CSS selector profile entries.\" }\n                ]\n            },\n            {\n                \"id\": \"Region\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"regionOverset\", \"type\": \"string\", \"enum\": [\"overset\", \"fit\", \"empty\"], \"description\": \"The \\\"overset\\\" attribute of a Named Flow.\" },\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"The corresponding DOM node id.\" }\n                ],\n                \"description\": \"This object represents a region that flows from a Named Flow.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"NamedFlow\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"documentNodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"The document node id.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"Named Flow identifier.\" },\n                    { \"name\": \"overset\", \"type\": \"boolean\", \"description\": \"The \\\"overset\\\" attribute of a Named Flow.\" },\n                    { \"name\": \"content\", \"type\": \"array\", \"items\": { \"$ref\": \"DOM.NodeId\" }, \"description\": \"An array of nodes that flow into the Named Flow.\" },\n                    { \"name\": \"regions\", \"type\": \"array\", \"items\": { \"$ref\": \"Region\" }, \"description\": \"An array of regions associated with the Named Flow.\" }\n                ],\n                \"description\": \"This object represents a Named Flow.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"PlatformFontUsage\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"familyName\", \"type\": \"string\", \"description\": \"Font's family name reported by platform.\"},\n                    { \"name\": \"glyphCount\", \"type\": \"number\", \"description\": \"Amount of glyphs that were rendered with this font.\"}\n                ],\n                \"description\": \"Information about amount of glyphs that were rendered with given font.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"async\": true,\n                \"description\": \"Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been enabled until the result of this command is received.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables the CSS agent for the given page.\"\n            },\n            {\n                \"name\": \"getMatchedStylesForNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\" },\n                    { \"name\": \"includePseudo\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether to include pseudo styles (default: true).\" },\n                    { \"name\": \"includeInherited\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether to include inherited styles (default: true).\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"matchedCSSRules\", \"type\": \"array\", \"items\": { \"$ref\": \"RuleMatch\" }, \"optional\": true, \"description\": \"CSS rules matching this node, from all applicable stylesheets.\" },\n                    { \"name\": \"pseudoElements\", \"type\": \"array\", \"items\": { \"$ref\": \"PseudoIdMatches\" }, \"optional\": true, \"description\": \"Pseudo style matches for this node.\" },\n                    { \"name\": \"inherited\", \"type\": \"array\", \"items\": { \"$ref\": \"InheritedStyleEntry\" }, \"optional\": true, \"description\": \"A chain of inherited styles (from the immediate node parent up to the DOM tree root).\" }\n                ],\n                \"description\": \"Returns requested styles for a DOM node identified by <code>nodeId</code>.\"\n            },\n            {\n                \"name\": \"getInlineStylesForNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"inlineStyle\", \"$ref\": \"CSSStyle\", \"optional\": true, \"description\": \"Inline style for the specified DOM node.\" },\n                    { \"name\": \"attributesStyle\", \"$ref\": \"CSSStyle\", \"optional\": true, \"description\": \"Attribute-defined element style (e.g. resulting from \\\"width=20 height=100%\\\").\"}\n                ],\n                \"description\": \"Returns the styles defined inline (explicitly in the \\\"style\\\" attribute and implicitly, using DOM attributes) for a DOM node identified by <code>nodeId</code>.\"\n            },\n            {\n                \"name\": \"getComputedStyleForNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"computedStyle\", \"type\": \"array\", \"items\": { \"$ref\": \"CSSComputedStyleProperty\" }, \"description\": \"Computed style for the specified DOM node.\" }\n                ],\n                \"description\": \"Returns the computed style for a DOM node identified by <code>nodeId</code>.\"\n            },\n            {\n                \"name\": \"getPlatformFontsForNode\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"cssFamilyName\", \"type\": \"string\", \"description\": \"Font family name which is determined by computed style.\" },\n                    { \"name\": \"fonts\", \"type\": \"array\", \"items\": { \"$ref\": \"PlatformFontUsage\"}, \"description\": \"Usage statistics for every employed platform font.\" }\n                ],\n                \"description\": \"Requests information about platform fonts which we used to render child TextNodes in the given node.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"getAllStyleSheets\",\n                \"returns\": [\n                    { \"name\": \"headers\", \"type\": \"array\", \"items\": { \"$ref\": \"CSSStyleSheetHeader\" }, \"description\": \"Descriptor entries for all available stylesheets.\" }\n                ],\n                \"description\": \"Returns metainfo entries for all known stylesheets.\"\n            },\n            {\n                \"name\": \"getStyleSheet\",\n                \"parameters\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"styleSheet\", \"$ref\": \"CSSStyleSheetBody\", \"description\": \"Stylesheet contents for the specified <code>styleSheetId</code>.\" }\n                ],\n                \"description\": \"Returns stylesheet data for the specified <code>styleSheetId</code>.\"\n            },\n            {\n                \"name\": \"getStyleSheetText\",\n                \"parameters\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"text\", \"type\": \"string\", \"description\": \"The stylesheet text.\" }\n                ],\n                \"description\": \"Returns the current textual content and the URL for a stylesheet.\"\n            },\n            {\n                \"name\": \"setStyleSheetText\",\n                \"parameters\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\" },\n                    { \"name\": \"text\", \"type\": \"string\" }\n                ],\n                \"description\": \"Sets the new stylesheet text, thereby invalidating all existing <code>CSSStyleId</code>'s and <code>CSSRuleId</code>'s contained by this stylesheet.\"\n            },\n            {\n                \"name\": \"setStyleText\",\n                \"parameters\": [\n                    { \"name\": \"styleId\", \"$ref\": \"CSSStyleId\" },\n                    { \"name\": \"text\", \"type\": \"string\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"style\", \"$ref\": \"CSSStyle\", \"description\": \"The resulting style after the text modification.\" }\n                ],\n                \"description\": \"Updates the CSSStyleDeclaration text.\"\n            },\n            {\n                \"name\": \"setPropertyText\",\n                \"parameters\": [\n                    { \"name\": \"styleId\", \"$ref\": \"CSSStyleId\" },\n                    { \"name\": \"propertyIndex\", \"type\": \"integer\" },\n                    { \"name\": \"text\", \"type\": \"string\" },\n                    { \"name\": \"overwrite\", \"type\": \"boolean\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"style\", \"$ref\": \"CSSStyle\", \"description\": \"The resulting style after the property text modification.\" }\n                ],\n                \"description\": \"Sets the new <code>text</code> for a property in the respective style, at offset <code>propertyIndex</code>. If <code>overwrite</code> is <code>true</code>, a property at the given offset is overwritten, otherwise inserted. <code>text</code> entirely replaces the property <code>name: value</code>.\"\n            },\n            {\n                \"name\": \"toggleProperty\",\n                \"parameters\": [\n                    { \"name\": \"styleId\", \"$ref\": \"CSSStyleId\" },\n                    { \"name\": \"propertyIndex\", \"type\": \"integer\" },\n                    { \"name\": \"disable\", \"type\": \"boolean\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"style\", \"$ref\": \"CSSStyle\", \"description\": \"The resulting style after the property toggling.\" }\n                ],\n                \"description\": \"Toggles the property in the respective style, at offset <code>propertyIndex</code>. The <code>disable</code> parameter denotes whether the property should be disabled (i.e. removed from the style declaration). If <code>disable == false</code>, the property gets put back into its original place in the style declaration.\"\n            },\n            {\n                \"name\": \"setRuleSelector\",\n                \"parameters\": [\n                    { \"name\": \"ruleId\", \"$ref\": \"CSSRuleId\" },\n                    { \"name\": \"selector\", \"type\": \"string\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"rule\", \"$ref\": \"CSSRule\", \"description\": \"The resulting rule after the selector modification.\" }\n                ],\n                \"description\": \"Modifies the rule selector.\"\n            },\n            {\n                \"name\": \"addRule\",\n                \"parameters\": [\n                    { \"name\": \"contextNodeId\", \"$ref\": \"DOM.NodeId\" },\n                    { \"name\": \"selector\", \"type\": \"string\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"rule\", \"$ref\": \"CSSRule\", \"description\": \"The newly created rule.\" }\n                ],\n                \"description\": \"Creates a new empty rule with the given <code>selector</code> in a special \\\"inspector\\\" stylesheet in the owner document of the context node.\"\n            },\n            {\n                \"name\": \"getSupportedCSSProperties\",\n                \"returns\": [\n                    { \"name\": \"cssProperties\", \"type\": \"array\", \"items\": { \"$ref\": \"CSSPropertyInfo\" }, \"description\": \"Supported property metainfo.\" }\n                ],\n                \"description\": \"Returns all supported CSS property names.\"\n            },\n            {\n                \"name\": \"forcePseudoState\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"The element id for which to force the pseudo state.\" },\n                    { \"name\": \"forcedPseudoClasses\", \"type\": \"array\", \"items\": { \"type\": \"string\", \"enum\": [\"active\", \"focus\", \"hover\", \"visited\"] }, \"description\": \"Element pseudo classes to force when computing the element's style.\" }\n                ],\n                \"description\": \"Ensures that the given node will have specified pseudo-classes whenever its style is computed by the browser.\"\n            },\n            {\n                \"name\": \"getNamedFlowCollection\",\n                \"parameters\": [\n                    { \"name\": \"documentNodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"The document node id for which to get the Named Flow Collection.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"namedFlows\", \"type\": \"array\", \"items\": { \"$ref\": \"NamedFlow\" }, \"description\": \"An array containing the Named Flows in the document.\" }\n                ],\n                \"description\": \"Returns the Named Flows from the document.\",\n                \"hidden\": true\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"mediaQueryResultChanged\",\n                \"description\": \"Fires whenever a MediaQuery result changes (for example, after a browser window has been resized.) The current implementation considers only viewport-dependent media features.\"\n            },\n            {\n                \"name\": \"styleSheetChanged\",\n                \"parameters\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\" }\n                ],\n                \"description\": \"Fired whenever a stylesheet is changed as a result of the client operation.\"\n            },\n            {\n                \"name\": \"styleSheetAdded\",\n                \"parameters\": [\n                    { \"name\": \"header\", \"$ref\": \"CSSStyleSheetHeader\", \"description\": \"Added stylesheet metainfo.\" }\n                ],\n                \"description\": \"Fired whenever an active document stylesheet is added.\"\n            },\n            {\n                \"name\": \"styleSheetRemoved\",\n                \"parameters\": [\n                    { \"name\": \"styleSheetId\", \"$ref\": \"StyleSheetId\", \"description\": \"Identifier of the removed stylesheet.\" }\n                ],\n                \"description\": \"Fired whenever an active document stylesheet is removed.\"\n            },\n            {\n                \"name\": \"namedFlowCreated\",\n                \"parameters\": [\n                    { \"name\": \"namedFlow\", \"$ref\": \"NamedFlow\", \"description\": \"The new Named Flow.\" }\n                ],\n                \"description\": \"Fires when a Named Flow is created.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"namedFlowRemoved\",\n                \"parameters\": [\n                    { \"name\": \"documentNodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"The document node id.\" },\n                    { \"name\": \"flowName\", \"type\": \"string\", \"description\": \"Identifier of the removed Named Flow.\" }\n                ],\n                \"description\": \"Fires when a Named Flow is removed: has no associated content nodes and regions.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"regionLayoutUpdated\",\n                \"parameters\": [\n                    { \"name\": \"namedFlow\", \"$ref\": \"NamedFlow\", \"description\": \"The Named Flow whose layout may have changed.\" }\n                ],\n                \"description\": \"Fires when a Named Flow's layout may have changed.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"regionOversetChanged\",\n                \"parameters\": [\n                    { \"name\": \"namedFlow\", \"$ref\": \"NamedFlow\", \"description\": \"The Named Flow containing the regions whose regionOverset values changed.\" }\n                ],\n                \"description\": \"Fires if any of the regionOverset values changed in a Named Flow's region chain.\",\n                \"hidden\": true\n            }\n        ]\n    },\n    {\n        \"domain\": \"Timeline\",\n        \"description\": \"Timeline provides its clients with instrumentation records that are generated during the page runtime. Timeline instrumentation can be started and stopped using corresponding commands. While timeline is started, it is generating timeline event records.\",\n        \"types\": [\n            {\n                \"id\": \"DOMCounters\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"documents\", \"type\": \"integer\" },\n                    { \"name\": \"nodes\", \"type\": \"integer\" },\n                    { \"name\": \"jsEventListeners\", \"type\": \"integer\" }\n                ],\n                \"description\": \"Current values of DOM counters.\",\n                \"hidden\": true\n            },\n            {\n                \"id\": \"TimelineEvent\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"description\": \"Event type.\" },\n                    { \"name\": \"thread\", \"type\": \"string\", \"optional\": true, \"description\": \"If present, identifies the thread that produced the event.\", \"hidden\": true },\n                    { \"name\": \"data\", \"type\": \"object\", \"description\": \"Event data.\" },\n                    { \"name\": \"children\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"TimelineEvent\" }, \"description\": \"Nested records.\" },\n                    { \"name\": \"counters\", \"$ref\": \"DOMCounters\", \"optional\": true, \"hidden\": true, \"description\": \"Current values of DOM counters.\" },\n                    { \"name\": \"usedHeapSize\", \"type\": \"integer\", \"optional\": true, \"hidden\": true, \"description\": \"Current size of JS heap.\" },\n                    { \"name\": \"nativeHeapStatistics\", \"type\": \"object\", \"optional\": true, \"hidden\": true, \"description\": \"Native heap statistics.\" }\n                ],\n                \"description\": \"Timeline record contains information about the recorded activity.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables timeline. After this call, timeline can be started from within the page (for example upon console.timeline).\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables timeline.\"\n            },\n            {\n                \"name\": \"start\",\n                \"parameters\": [\n                    { \"name\": \"maxCallStackDepth\", \"optional\": true, \"type\": \"integer\", \"description\": \"Samples JavaScript stack traces up to <code>maxCallStackDepth</code>, defaults to 5.\" },\n                    { \"name\": \"bufferEvents\", \"optional\": true, \"type\": \"boolean\", \"hidden\": true, \"description\": \"Whether instrumentation events should be buffered and returned upon <code>stop</code> call.\" },\n                    { \"name\": \"includeDomCounters\", \"optional\": true, \"type\": \"boolean\", \"hidden\": true, \"description\": \"Whether DOM counters data should be included into timeline events.\" },\n                    { \"name\": \"includeNativeMemoryStatistics\", \"optional\": true, \"type\": \"boolean\", \"hidden\": true, \"description\": \"Whether native memory usage statistics should be reported as part of timeline events.\" }\n                ],\n                \"description\": \"Starts capturing instrumentation events.\"\n            },\n            {\n                \"name\": \"stop\",\n                \"description\": \"Stops capturing instrumentation events.\",\n                \"returns\": [\n                    { \"name\": \"events\", \"type\": \"array\", \"items\": { \"$ref\": \"TimelineEvent\" }, \"optional\": true, \"hidden\": true, \"description\": \"Timeline event record data.\" }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"eventRecorded\",\n                \"parameters\": [\n                    { \"name\": \"record\", \"$ref\": \"TimelineEvent\", \"description\": \"Timeline event record data.\" }\n                ],\n                \"description\": \"Fired for every instrumentation event while timeline is started.\"\n            },\n            {\n                \"name\": \"started\",\n                \"parameters\": [\n                    { \"name\": \"consoleTimeline\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If specified, identifies that timeline was started using console.timeline() call.\" }\n                ],\n                \"description\": \"Fired when timeline is started.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"stopped\",\n                \"parameters\": [\n                    { \"name\": \"consoleTimeline\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If specified, identifies that timeline was started using console.timeline() call.\" }\n                ],\n                \"description\": \"Fired when timeline is stopped.\",\n                \"hidden\": true\n            }\n        ]\n    },\n    {\n        \"domain\": \"Debugger\",\n        \"description\": \"Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.\",\n        \"types\": [\n            {\n                \"id\": \"BreakpointId\",\n                \"type\": \"string\",\n                \"description\": \"Breakpoint identifier.\"\n            },\n            {\n                \"id\": \"ScriptId\",\n                \"type\": \"string\",\n                \"description\": \"Unique script identifier.\"\n            },\n            {\n                \"id\": \"CallFrameId\",\n                \"type\": \"string\",\n                \"description\": \"Call frame identifier.\"\n            },\n            {\n                \"id\": \"Location\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"description\": \"Script identifier as reported in the <code>Debugger.scriptParsed</code>.\" },\n                    { \"name\": \"lineNumber\", \"type\": \"integer\", \"description\": \"Line number in the script (0-based).\" },\n                    { \"name\": \"columnNumber\", \"type\": \"integer\", \"optional\": true, \"description\": \"Column number in the script (0-based).\" }\n                ],\n                \"description\": \"Location in the source code.\"\n            },\n            {\n                \"id\": \"FunctionDetails\",\n                \"hidden\": true,\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"location\", \"$ref\": \"Location\", \"description\": \"Location of the function.\" },\n                    { \"name\": \"name\", \"type\": \"string\", \"optional\": true, \"description\": \"Name of the function. Not present for anonymous functions.\" },\n                    { \"name\": \"displayName\", \"type\": \"string\", \"optional\": true, \"description\": \"Display name of the function(specified in 'displayName' property on the function object).\" },\n                    { \"name\": \"inferredName\", \"type\": \"string\", \"optional\": true, \"description\": \"Name of the function inferred from its initial assignment.\" },\n                    { \"name\": \"scopeChain\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"Scope\" }, \"description\": \"Scope chain for this closure.\" }\n                ],\n                \"description\": \"Information about the function.\"\n            },\n            {\n                \"id\": \"CallFrame\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"callFrameId\", \"$ref\": \"CallFrameId\", \"description\": \"Call frame identifier. This identifier is only valid while the virtual machine is paused.\" },\n                    { \"name\": \"functionName\", \"type\": \"string\", \"description\": \"Name of the JavaScript function called on this call frame.\" },\n                    { \"name\": \"location\", \"$ref\": \"Location\", \"description\": \"Location in the source code.\" },\n                    { \"name\": \"scopeChain\", \"type\": \"array\", \"items\": { \"$ref\": \"Scope\" }, \"description\": \"Scope chain for this call frame.\" },\n                    { \"name\": \"this\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"<code>this</code> object for this call frame.\" }\n                ],\n                \"description\": \"JavaScript call frame. Array of call frames form the call stack.\"\n            },\n            {\n                \"id\": \"Scope\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"global\", \"local\", \"with\", \"closure\", \"catch\"], \"description\": \"Scope type.\" },\n                    { \"name\": \"object\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties.\" }\n                ],\n                \"description\": \"Scope description.\"\n            },\n            {\n                \"id\": \"SetScriptSourceError\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"compileError\", \"optional\": true, \"type\": \"object\", \"properties\":\n                        [\n                            { \"name\": \"message\", \"type\": \"string\", \"description\": \"Compiler error message\" },\n                            { \"name\": \"lineNumber\", \"type\": \"integer\", \"description\": \"Compile error line number (1-based)\" },\n                            { \"name\": \"columnNumber\", \"type\": \"integer\", \"description\": \"Compile error column number (1-based)\" }\n                        ]\n                    }\n                ],\n                \"description\": \"Error data for setScriptSource command. compileError is a case type for uncompilable script source error.\",\n                \"hidden\": true\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables debugger for given page.\"\n            },\n            {\n                \"name\": \"setBreakpointsActive\",\n                \"parameters\": [\n                    { \"name\": \"active\", \"type\": \"boolean\", \"description\": \"New value for breakpoints active state.\" }\n                ],\n                \"description\": \"Activates / deactivates all breakpoints on the page.\"\n            },\n            {\n                \"name\": \"setSkipAllPauses\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"skipped\", \"type\": \"boolean\", \"description\": \"New value for skip pauses state.\" },\n                    { \"name\": \"untilReload\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether page reload should set skipped to false.\" }\n                ],\n                \"description\": \"Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc).\"\n            },\n            {\n                \"name\": \"setBreakpointByUrl\",\n                \"parameters\": [\n                    { \"name\": \"lineNumber\", \"type\": \"integer\", \"description\": \"Line number to set breakpoint at.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"optional\": true, \"description\": \"URL of the resources to set breakpoint on.\" },\n                    { \"name\": \"urlRegex\", \"type\": \"string\", \"optional\": true, \"description\": \"Regex pattern for the URLs of the resources to set breakpoints on. Either <code>url</code> or <code>urlRegex</code> must be specified.\" },\n                    { \"name\": \"columnNumber\", \"type\": \"integer\", \"optional\": true, \"description\": \"Offset in the line to set breakpoint at.\" },\n                    { \"name\": \"condition\", \"type\": \"string\", \"optional\": true, \"description\": \"Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true.\" },\n                    { \"name\": \"isAntibreakpoint\", \"type\": \"boolean\", \"optional\": true, \"hidden\": true, \"description\": \"Creates pseudo-breakpoint that prevents debugger from pausing on exception at this location.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"breakpointId\", \"$ref\": \"BreakpointId\", \"description\": \"Id of the created breakpoint for further reference.\" },\n                    { \"name\": \"locations\", \"type\": \"array\", \"items\": { \"$ref\": \"Location\"}, \"description\": \"List of the locations this breakpoint resolved into upon addition.\" }\n                ],\n                \"description\": \"Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads.\"\n            },\n            {\n                \"name\": \"setBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"location\", \"$ref\": \"Location\", \"description\": \"Location to set breakpoint in.\" },\n                    { \"name\": \"condition\", \"type\": \"string\", \"optional\": true, \"description\": \"Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"breakpointId\", \"$ref\": \"BreakpointId\", \"description\": \"Id of the created breakpoint for further reference.\" },\n                    { \"name\": \"actualLocation\", \"$ref\": \"Location\", \"description\": \"Location this breakpoint resolved into.\" }\n                ],\n                \"description\": \"Sets JavaScript breakpoint at a given location.\"\n            },\n            {\n                \"name\": \"removeBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"breakpointId\", \"$ref\": \"BreakpointId\" }\n                ],\n                \"description\": \"Removes JavaScript breakpoint.\"\n            },\n            {\n                \"name\": \"continueToLocation\",\n                \"parameters\": [\n                    { \"name\": \"location\", \"$ref\": \"Location\", \"description\": \"Location to continue to.\" },\n                    { \"name\": \"interstatementLocation\", \"type\": \"boolean\", \"optional\": true, \"hidden\": true, \"description\": \"Allows breakpoints at the intemediate positions inside statements.\" }\n                ],\n                \"description\": \"Continues execution until specific location is reached.\"\n            },\n            {\n                \"name\": \"stepOver\",\n                \"description\": \"Steps over the statement.\"\n            },\n            {\n                \"name\": \"stepInto\",\n                \"description\": \"Steps into the function call.\"\n            },\n            {\n                \"name\": \"stepOut\",\n                \"description\": \"Steps out of the function call.\"\n            },\n            {\n                \"name\": \"pause\",\n                \"description\": \"Stops on the next JavaScript statement.\"\n            },\n            {\n                \"name\": \"resume\",\n                \"description\": \"Resumes JavaScript execution.\"\n            },\n            {\n                \"name\": \"searchInContent\",\n                \"parameters\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"description\": \"Id of the script to search in.\" },\n                    { \"name\": \"query\", \"type\": \"string\", \"description\": \"String to search for.\"  },\n                    { \"name\": \"caseSensitive\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, search is case sensitive.\" },\n                    { \"name\": \"isRegex\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true, treats string parameter as regex.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"array\", \"items\": { \"$ref\": \"Page.SearchMatch\" }, \"description\": \"List of search matches.\" }\n                ],\n                \"description\": \"Searches for given string in script content.\"\n            },\n            {\n                \"name\": \"canSetScriptSource\",\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"boolean\", \"description\": \"True if <code>setScriptSource</code> is supported.\" }\n                ],\n                \"description\": \"Always returns true.\"\n            },\n            {\n                \"name\": \"setScriptSource\",\n                \"parameters\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"description\": \"Id of the script to edit.\" },\n                    { \"name\": \"scriptSource\", \"type\": \"string\", \"description\": \"New content of the script.\" },\n                    { \"name\": \"preview\", \"type\": \"boolean\", \"optional\": true, \"description\": \" If true the change will not actually be applied. Preview mode may be used to get result description without actually modifying the code.\", \"hidden\": true }\n                ],\n                \"returns\": [\n                    { \"name\": \"callFrames\", \"type\": \"array\", \"optional\": true, \"items\": { \"$ref\": \"CallFrame\"}, \"description\": \"New stack trace in case editing has happened while VM was stopped.\" },\n                    { \"name\": \"result\", \"type\": \"object\", \"optional\": true, \"description\": \"VM-specific description of the changes applied.\", \"hidden\": true }\n                ],\n                \"error\": {\n                    \"$ref\": \"SetScriptSourceError\"\n                },\n                \"description\": \"Edits JavaScript source live.\"\n            },\n            {\n                \"name\": \"restartFrame\",\n                \"parameters\": [\n                    { \"name\": \"callFrameId\", \"$ref\": \"CallFrameId\", \"description\": \"Call frame identifier to evaluate on.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"callFrames\", \"type\": \"array\", \"items\": { \"$ref\": \"CallFrame\"}, \"description\": \"New stack trace.\" },\n                    { \"name\": \"result\", \"type\": \"object\", \"description\": \"VM-specific description.\", \"hidden\": true }\n                ],\n                \"hidden\": true,\n                \"description\": \"Restarts particular call frame from the beginning.\"\n            },\n            {\n                \"name\": \"getScriptSource\",\n                \"parameters\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"description\": \"Id of the script to get source for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"scriptSource\", \"type\": \"string\", \"description\": \"Script source.\" }\n                ],\n                \"description\": \"Returns source for the script with given id.\"\n            },\n            {\n                \"name\": \"getFunctionDetails\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"functionId\", \"$ref\": \"Runtime.RemoteObjectId\", \"description\": \"Id of the function to get location for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"details\", \"$ref\": \"FunctionDetails\", \"description\": \"Information about the function.\" }\n                ],\n                \"description\": \"Returns detailed informtation on given function.\"\n            },\n            {\n                \"name\": \"setPauseOnExceptions\",\n                \"parameters\": [\n                    { \"name\": \"state\", \"type\": \"string\", \"enum\": [\"none\", \"uncaught\", \"all\"], \"description\": \"Pause on exceptions mode.\" }\n                ],\n                \"description\": \"Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>.\"\n            },\n            {\n                \"name\": \"evaluateOnCallFrame\",\n                \"parameters\": [\n                    { \"name\": \"callFrameId\", \"$ref\": \"CallFrameId\", \"description\": \"Call frame identifier to evaluate on.\" },\n                    { \"name\": \"expression\", \"type\": \"string\", \"description\": \"Expression to evaluate.\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"String object group name to put result into (allows rapid releasing resulting object handles using <code>releaseObjectGroup</code>).\" },\n                    { \"name\": \"includeCommandLineAPI\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Specifies whether command line API should be available to the evaluated expression, defaults to false.\", \"hidden\": true },\n                    { \"name\": \"doNotPauseOnExceptionsAndMuteConsole\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.\", \"hidden\": true },\n                    { \"name\": \"returnByValue\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the result is expected to be a JSON object that should be sent by value.\" },\n                    { \"name\": \"generatePreview\", \"type\": \"boolean\", \"optional\": true, \"hidden\": true, \"description\": \"Whether preview should be generated for the result.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Object wrapper for the evaluation result.\" },\n                    { \"name\": \"wasThrown\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the result was thrown during the evaluation.\" }\n                ],\n                \"description\": \"Evaluates expression on a given call frame.\"\n            },\n            {\n                \"name\": \"compileScript\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"expression\", \"type\": \"string\", \"description\": \"Expression to compile.\" },\n                    { \"name\": \"sourceURL\", \"type\": \"string\", \"description\": \"Source url to be set for the script.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"optional\": true, \"description\": \"Id of the script.\" },\n                    { \"name\": \"syntaxErrorMessage\", \"type\": \"string\", \"optional\": true, \"description\": \"Syntax error message if compilation failed.\" }\n                ],\n                \"description\": \"Compiles expression.\"\n            },\n            {\n                \"name\": \"runScript\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"description\": \"Id of the script to run.\" },\n                    { \"name\": \"contextId\", \"$ref\": \"Runtime.ExecutionContextId\", \"optional\": true, \"description\": \"Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page.\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"Symbolic group name that can be used to release multiple objects.\" },\n                    { \"name\": \"doNotPauseOnExceptionsAndMuteConsole\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Run result.\" },\n                    { \"name\": \"wasThrown\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True if the result was thrown during the script run.\" }\n                ],\n                \"description\": \"Runs script with given id in a given context.\"\n            },\n            {\n                \"name\": \"setOverlayMessage\",\n                \"parameters\": [\n                    { \"name\": \"message\", \"type\": \"string\", \"optional\": true, \"description\": \"Overlay message to display when paused in debugger.\" }\n                ],\n                \"hidden\": true,\n                \"description\": \"Sets overlay message.\"\n            },\n            {\n                \"name\": \"setVariableValue\",\n                \"parameters\": [\n                    { \"name\": \"scopeNumber\", \"type\": \"integer\", \"description\": \"0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually.\" },\n                    { \"name\": \"variableName\", \"type\": \"string\", \"description\": \"Variable name.\" },\n                    { \"name\": \"newValue\", \"$ref\": \"Runtime.CallArgument\", \"description\": \"New variable value.\" },\n                    { \"name\": \"callFrameId\", \"$ref\": \"CallFrameId\", \"optional\": true, \"description\": \"Id of callframe that holds variable.\" },\n                    { \"name\": \"functionObjectId\", \"$ref\": \"Runtime.RemoteObjectId\", \"optional\": true, \"description\": \"Object id of closure (function) that holds variable.\" }\n                ],\n                \"hidden\": true,\n                \"description\": \"Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually.\"\n            },\n            {\n                \"name\": \"getStepInPositions\",\n                \"parameters\": [\n                    { \"name\": \"callFrameId\", \"$ref\": \"CallFrameId\", \"description\": \"Id of a call frame where the current statement should be analized\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"stepInPositions\", \"type\": \"array\", \"items\": { \"$ref\": \"Location\" }, \"optional\": true, \"description\": \"experimental\" }\n                ],\n                \"hidden\": true,\n                \"description\": \"Lists all positions where step-in is possible for a current statement in a specified call frame\"\n            },\n            {\n                \"name\": \"getBacktrace\",\n                \"returns\": [\n                    { \"name\": \"callFrames\", \"type\": \"array\", \"items\": { \"$ref\": \"CallFrame\"}, \"description\": \"Call stack the virtual machine stopped on.\" }\n                ],\n                \"hidden\": true,\n                \"description\": \"Returns call stack including variables changed since VM was paused. VM must be paused.\"\n            },\n            {\n                \"name\": \"skipStackFrames\",\n                \"parameters\": [\n                    { \"name\": \"script\", \"optional\": true, \"type\": \"string\", \"description\": \"Regular expression defining the scripts to ignore while stepping.\" }\n                ],\n                \"hidden\": true,\n                \"description\": \"Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"globalObjectCleared\",\n                \"description\": \"Called when global has been cleared and debugger client should reset its state. Happens upon navigation or reload.\"\n            },\n            {\n                \"name\": \"scriptParsed\",\n                \"parameters\": [\n                    { \"name\": \"scriptId\", \"$ref\": \"ScriptId\", \"description\": \"Identifier of the script parsed.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL or name of the script parsed (if any).\" },\n                    { \"name\": \"startLine\", \"type\": \"integer\", \"description\": \"Line offset of the script within the resource with given URL (for script tags).\" },\n                    { \"name\": \"startColumn\", \"type\": \"integer\", \"description\": \"Column offset of the script within the resource with given URL.\" },\n                    { \"name\": \"endLine\", \"type\": \"integer\", \"description\": \"Last line of the script.\" },\n                    { \"name\": \"endColumn\", \"type\": \"integer\", \"description\": \"Length of the last line of the script.\" },\n                    { \"name\": \"isContentScript\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Determines whether this script is a user extension script.\" },\n                    { \"name\": \"sourceMapURL\", \"type\": \"string\", \"optional\": true, \"description\": \"URL of source map associated with script (if any).\" },\n                    { \"name\": \"hasSourceURL\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True, if this script has sourceURL.\", \"hidden\": true }\n                ],\n                \"description\": \"Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.\"\n            },\n            {\n                \"name\": \"scriptFailedToParse\",\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL of the script that failed to parse.\" },\n                    { \"name\": \"scriptSource\", \"type\": \"string\", \"description\": \"Source text of the script that failed to parse.\" },\n                    { \"name\": \"startLine\", \"type\": \"integer\", \"description\": \"Line offset of the script within the resource.\" },\n                    { \"name\": \"errorLine\", \"type\": \"integer\", \"description\": \"Line with error.\" },\n                    { \"name\": \"errorMessage\", \"type\": \"string\", \"description\": \"Parse error message.\" }\n                ],\n                \"description\": \"Fired when virtual machine fails to parse the script.\"\n            },\n            {\n                \"name\": \"breakpointResolved\",\n                \"parameters\": [\n                    { \"name\": \"breakpointId\", \"$ref\": \"BreakpointId\", \"description\": \"Breakpoint unique identifier.\" },\n                    { \"name\": \"location\", \"$ref\": \"Location\", \"description\": \"Actual breakpoint location.\" }\n                ],\n                \"description\": \"Fired when breakpoint is resolved to an actual script and location.\"\n            },\n            {\n                \"name\": \"paused\",\n                \"parameters\": [\n                    { \"name\": \"callFrames\", \"type\": \"array\", \"items\": { \"$ref\": \"CallFrame\" }, \"description\": \"Call stack the virtual machine stopped on.\" },\n                    { \"name\": \"reason\", \"type\": \"string\", \"enum\": [ \"XHR\", \"DOM\", \"EventListener\", \"exception\", \"assert\", \"CSPViolation\", \"debugCommand\", \"other\" ], \"description\": \"Pause reason.\" },\n                    { \"name\": \"data\", \"type\": \"object\", \"optional\": true, \"description\": \"Object containing break-specific auxiliary properties.\" },\n                    { \"name\": \"hitBreakpoints\", \"type\": \"array\", \"optional\": true, \"items\": { \"type\": \"string\" }, \"description\": \"Hit breakpoints IDs\", \"hidden\": true }\n                ],\n                \"description\": \"Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.\"\n            },\n            {\n                \"name\": \"resumed\",\n                \"description\": \"Fired when the virtual machine resumed execution.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"DOMDebugger\",\n        \"description\": \"DOM debugging allows setting breakpoints on particular DOM operations and events. JavaScript execution will stop on these operations as if there was a regular breakpoint set.\",\n        \"types\": [\n            {\n                \"id\": \"DOMBreakpointType\",\n                \"type\": \"string\",\n                \"enum\": [\"subtree-modified\", \"attribute-modified\", \"node-removed\"],\n                \"description\": \"DOM breakpoint type.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"setDOMBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"Identifier of the node to set breakpoint on.\" },\n                    { \"name\": \"type\", \"$ref\": \"DOMBreakpointType\", \"description\": \"Type of the operation to stop upon.\" }\n                ],\n                \"description\": \"Sets breakpoint on particular operation with DOM.\"\n            },\n            {\n                \"name\": \"removeDOMBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\", \"description\": \"Identifier of the node to remove breakpoint from.\" },\n                    { \"name\": \"type\", \"$ref\": \"DOMBreakpointType\", \"description\": \"Type of the breakpoint to remove.\" }\n                ],\n                \"description\": \"Removes DOM breakpoint that was set using <code>setDOMBreakpoint</code>.\"\n            },\n            {\n                \"name\": \"setEventListenerBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"eventName\", \"type\": \"string\", \"description\": \"DOM Event name to stop on (any DOM event will do).\" }\n                ],\n                \"description\": \"Sets breakpoint on particular DOM event.\"\n            },\n            {\n                \"name\": \"removeEventListenerBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"eventName\", \"type\": \"string\", \"description\": \"Event name.\" }\n                ],\n                \"description\": \"Removes breakpoint on particular DOM event.\"\n            },\n            {\n                \"name\": \"setInstrumentationBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"eventName\", \"type\": \"string\", \"description\": \"Instrumentation name to stop on.\" }\n                ],\n                \"description\": \"Sets breakpoint on particular native event.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"removeInstrumentationBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"eventName\", \"type\": \"string\", \"description\": \"Instrumentation name to stop on.\" }\n                ],\n                \"description\": \"Removes breakpoint on particular native event.\",\n                \"hidden\": true\n            },\n            {\n                \"name\": \"setXHRBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Resource URL substring. All XHRs having this substring in the URL will get stopped upon.\" }\n                ],\n                \"description\": \"Sets breakpoint on XMLHttpRequest.\"\n            },\n            {\n                \"name\": \"removeXHRBreakpoint\",\n                \"parameters\": [\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"Resource URL substring.\" }\n                ],\n                \"description\": \"Removes breakpoint from XMLHttpRequest.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Profiler\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"ProfileHeader\",\n                \"type\": \"object\",\n                \"description\": \"Profile header.\",\n                \"properties\": [\n                    { \"name\": \"title\", \"type\": \"string\", \"description\": \"Profile title.\" },\n                    { \"name\": \"uid\", \"type\": \"integer\", \"description\": \"Unique identifier of the profile.\" }\n                ]\n            },\n            {\n                \"id\": \"CPUProfileNode\",\n                \"type\": \"object\",\n                \"description\": \"CPU Profile node. Holds callsite information, execution statistics and child nodes.\",\n                \"properties\": [\n                    { \"name\": \"functionName\", \"type\": \"string\", \"description\": \"Function name.\" },\n                    { \"name\": \"scriptId\", \"$ref\": \"Debugger.ScriptId\", \"description\": \"Script identifier.\" },\n                    { \"name\": \"url\", \"type\": \"string\", \"description\": \"URL.\" },\n                    { \"name\": \"lineNumber\", \"type\": \"integer\", \"description\": \"Line number.\" },\n                    { \"name\": \"hitCount\", \"type\": \"integer\", \"description\": \"Number of samples where this node was on top of the call stack.\" },\n                    { \"name\": \"callUID\", \"type\": \"number\", \"description\": \"Call UID.\" },\n                    { \"name\": \"children\", \"type\": \"array\", \"items\": { \"$ref\": \"CPUProfileNode\" }, \"description\": \"Child nodes.\" },\n                    { \"name\": \"deoptReason\", \"type\": \"string\", \"description\": \"The reason of being not optimized. The function may be deoptimized or marked as don't optimize.\"},\n                    { \"name\": \"id\", \"optional\": true, \"type\": \"integer\", \"description\": \"Unique id of the node.\" }\n                ]\n            },\n            {\n                \"id\": \"CPUProfile\",\n                \"type\": \"object\",\n                \"description\": \"Profile.\",\n                \"properties\": [\n                    { \"name\": \"head\", \"$ref\": \"CPUProfileNode\" },\n                    { \"name\": \"startTime\", \"type\": \"number\", \"description\": \"Profiling start time in seconds.\" },\n                    { \"name\": \"endTime\", \"type\": \"number\", \"description\": \"Profiling end time in seconds.\" },\n                    { \"name\": \"samples\", \"optional\": true, \"type\": \"array\", \"items\": { \"type\": \"integer\" }, \"description\": \"Ids of samples top nodes.\" }\n                ]\n            },\n            {\n                \"id\": \"HeapSnapshotObjectId\",\n                \"type\": \"string\",\n                \"description\": \"Heap snashot object id.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\"\n            },\n            {\n                \"name\": \"disable\"\n            },\n            {\n                \"name\": \"setSamplingInterval\",\n                \"parameters\": [\n                    { \"name\": \"interval\", \"type\": \"integer\", \"description\": \"New sampling interval in microseconds.\" }\n                ],\n                \"description\": \"Changes CPU profiler sampling interval. Must be called before CPU profiles recording started.\"\n            },\n            {\n                \"name\": \"start\"\n            },\n            {\n                \"name\": \"stop\",\n                \"returns\": [\n                    { \"name\": \"header\", \"$ref\": \"ProfileHeader\", \"description\": \"The header of the recorded profile.\"}\n                ]\n            },\n            {\n                \"name\": \"getProfileHeaders\",\n                \"returns\": [\n                    { \"name\": \"headers\", \"type\": \"array\", \"items\": { \"$ref\": \"ProfileHeader\"} }\n                ]\n            },\n            {\n                \"name\": \"getCPUProfile\",\n                \"parameters\": [\n                    { \"name\": \"uid\", \"type\": \"integer\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"profile\", \"$ref\": \"CPUProfile\" }\n                ]\n            },\n            {\n                \"name\": \"removeProfile\",\n                \"parameters\": [\n                    { \"name\": \"type\", \"type\": \"string\" },\n                    { \"name\": \"uid\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"clearProfiles\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"addProfileHeader\",\n                \"parameters\": [\n                    { \"name\": \"header\", \"$ref\": \"ProfileHeader\" }\n                ]\n            },\n            {\n                \"name\": \"setRecordingProfile\",\n                \"parameters\": [\n                    { \"name\": \"isProfiling\", \"type\": \"boolean\" }\n                ]\n            },\n            {\n                \"name\": \"resetProfiles\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"HeapProfiler\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"ProfileHeader\",\n                \"type\": \"object\",\n                \"description\": \"Profile header.\",\n                \"properties\": [\n                    { \"name\": \"title\", \"type\": \"string\", \"description\": \"Profile title.\" },\n                    { \"name\": \"uid\", \"type\": \"integer\", \"description\": \"Unique identifier of the profile.\" },\n                    { \"name\": \"maxJSObjectId\", \"type\": \"integer\", \"optional\": true, \"description\": \"Last seen JS object Id.\" }\n                ]\n            },\n            {\n                \"id\": \"HeapSnapshotObjectId\",\n                \"type\": \"string\",\n                \"description\": \"Heap snashot object id.\"\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"getProfileHeaders\",\n                \"returns\": [\n                    { \"name\": \"headers\", \"type\": \"array\", \"items\": { \"$ref\": \"ProfileHeader\"} }\n                ]\n            },\n            {\n                \"name\": \"startTrackingHeapObjects\"\n            },\n            {\n                \"name\": \"stopTrackingHeapObjects\"\n            },\n            {\n                \"name\": \"getHeapSnapshot\",\n                \"parameters\": [\n                    { \"name\": \"uid\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"removeProfile\",\n                \"parameters\": [\n                    { \"name\": \"uid\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"clearProfiles\"\n            },\n            {\n                \"name\": \"takeHeapSnapshot\",\n                \"parameters\": [\n                    { \"name\": \"reportProgress\", \"type\": \"boolean\", \"optional\": true, \"description\": \"If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken.\" }\n                ]\n            },\n            {\n                \"name\": \"collectGarbage\"\n            },\n            {\n                \"name\": \"getObjectByHeapObjectId\",\n                \"parameters\": [\n                    { \"name\": \"objectId\", \"$ref\": \"HeapSnapshotObjectId\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"Symbolic group name that can be used to release multiple objects.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"$ref\": \"Runtime.RemoteObject\", \"description\": \"Evaluation result.\" }\n                ]\n            },\n            {\n                \"name\": \"getHeapObjectId\",\n                \"parameters\": [\n                    { \"name\": \"objectId\", \"$ref\": \"Runtime.RemoteObjectId\", \"description\": \"Identifier of the object to get heap object id for.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"heapSnapshotObjectId\", \"$ref\": \"HeapSnapshotObjectId\", \"description\": \"Id of the heap snapshot object corresponding to the passed remote object id.\" }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"addProfileHeader\",\n                \"parameters\": [\n                    { \"name\": \"header\", \"$ref\": \"ProfileHeader\" }\n                ]\n            },\n            {\n                \"name\": \"addHeapSnapshotChunk\",\n                \"parameters\": [\n                    { \"name\": \"uid\", \"type\": \"integer\" },\n                    { \"name\": \"chunk\", \"type\": \"string\" }\n                ]\n            },\n            {\n                \"name\": \"finishHeapSnapshot\",\n                \"parameters\": [\n                    { \"name\": \"uid\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"resetProfiles\"\n            },\n            {\n                \"name\": \"reportHeapSnapshotProgress\",\n                \"parameters\": [\n                    { \"name\": \"done\", \"type\": \"integer\" },\n                    { \"name\": \"total\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"lastSeenObjectId\",\n                \"description\": \"If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.\",\n                \"parameters\": [\n                    { \"name\": \"lastSeenObjectId\", \"type\": \"integer\" },\n                    { \"name\": \"timestamp\", \"type\": \"number\" }\n                ]\n            },\n            {\n                \"name\": \"heapStatsUpdate\",\n                \"description\": \"If heap objects tracking has been started then backend may send update for one or more fragments\",\n                \"parameters\": [\n                    { \"name\": \"statsUpdate\", \"type\": \"array\", \"items\": { \"type\": \"integer\" }, \"description\": \"An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment.\"}\n                ]\n            }\n        ]\n    },\n    {\n        \"domain\": \"Worker\",\n        \"hidden\": true,\n        \"types\": [],\n        \"commands\": [\n            {\n                \"name\": \"enable\"\n            },\n            {\n                \"name\": \"disable\"\n            },\n            {\n                \"name\": \"sendMessageToWorker\",\n                \"parameters\": [\n                    { \"name\": \"workerId\", \"type\": \"integer\" },\n                    { \"name\": \"message\", \"type\": \"object\" }\n                ]\n            },\n            {\n                \"name\": \"canInspectWorkers\",\n                \"description\": \"Tells whether browser supports workers inspection.\",\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"boolean\", \"description\": \"True if browser has workers support.\" }\n                ]\n            },\n            {\n                \"name\": \"connectToWorker\",\n                \"parameters\": [\n                    { \"name\": \"workerId\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"disconnectFromWorker\",\n                \"parameters\": [\n                    { \"name\": \"workerId\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"setAutoconnectToWorkers\",\n                \"parameters\": [\n                    { \"name\": \"value\", \"type\": \"boolean\" }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"workerCreated\",\n                \"parameters\": [\n                    { \"name\": \"workerId\", \"type\": \"integer\" },\n                    { \"name\": \"url\", \"type\": \"string\" },\n                    { \"name\": \"inspectorConnected\", \"type\": \"boolean\" }\n                ]\n            },\n            {\n                \"name\": \"workerTerminated\",\n                \"parameters\": [\n                    { \"name\": \"workerId\", \"type\": \"integer\" }\n                ]\n            },\n            {\n                \"name\": \"dispatchMessageFromWorker\",\n                \"parameters\": [\n                    { \"name\": \"workerId\", \"type\": \"integer\" },\n                    { \"name\": \"message\", \"type\": \"object\" }\n                ]\n            },\n            {\n                \"name\": \"disconnectedFromWorker\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Canvas\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"ResourceId\",\n                \"type\": \"string\",\n                \"description\": \"Unique resource identifier.\"\n            },\n            {\n                \"id\": \"ResourceStateDescriptor\",\n                \"type\": \"object\",\n                \"description\": \"Resource state descriptor.\",\n                \"properties\": [\n                    { \"name\": \"name\", \"type\": \"string\", \"description\": \"State name.\" },\n                    { \"name\": \"enumValueForName\", \"type\": \"string\", \"optional\": true, \"description\": \"String representation of the enum value, if <code>name</code> stands for an enum.\" },\n                    { \"name\": \"value\", \"$ref\": \"CallArgument\", \"optional\": true, \"description\": \"The value associated with the particular state.\" },\n                    { \"name\": \"values\", \"type\": \"array\", \"items\": { \"$ref\": \"ResourceStateDescriptor\" }, \"optional\": true, \"description\": \"Array of values associated with the particular state. Either <code>value</code> or <code>values</code> will be specified.\" },\n                    { \"name\": \"isArray\", \"type\": \"boolean\", \"optional\": true, \"description\": \"True iff the given <code>values</code> items stand for an array rather than a list of grouped states.\" }\n                ]\n            },\n            {\n                \"id\": \"ResourceState\",\n                \"type\": \"object\",\n                \"description\": \"Resource state.\",\n                \"properties\": [\n                    { \"name\": \"id\", \"$ref\": \"ResourceId\" },\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" },\n                    { \"name\": \"descriptors\", \"type\": \"array\", \"items\": { \"$ref\": \"ResourceStateDescriptor\" }, \"optional\": true, \"description\": \"Describes current <code>Resource</code> state.\" },\n                    { \"name\": \"imageURL\", \"type\": \"string\", \"optional\": true, \"description\": \"Screenshot image data URL.\" }\n                ]\n            },\n            {\n                \"id\": \"CallArgument\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"description\", \"type\": \"string\", \"description\": \"String representation of the object.\" },\n                    { \"name\": \"enumName\", \"type\": \"string\", \"optional\": true, \"description\": \"Enum name, if any, that stands for the value (for example, a WebGL enum name).\" },\n                    { \"name\": \"resourceId\", \"$ref\": \"ResourceId\", \"optional\": true, \"description\": \"Resource identifier. Specified for <code>Resource</code> objects only.\" },\n                    { \"name\": \"type\", \"type\": \"string\", \"optional\": true, \"enum\": [\"object\", \"function\", \"undefined\", \"string\", \"number\", \"boolean\"], \"description\": \"Object type. Specified for non <code>Resource</code> objects only.\" },\n                    { \"name\": \"subtype\", \"type\": \"string\", \"optional\": true, \"enum\": [\"array\", \"null\", \"node\", \"regexp\", \"date\"], \"description\": \"Object subtype hint. Specified for <code>object</code> type values only.\" },\n                    { \"name\": \"remoteObject\", \"$ref\": \"Runtime.RemoteObject\", \"optional\": true, \"description\": \"The <code>RemoteObject</code>, if requested.\" }\n                ]\n            },\n            {\n                \"id\": \"Call\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"contextId\", \"$ref\": \"ResourceId\" },\n                    { \"name\": \"functionName\", \"type\": \"string\", \"optional\": true },\n                    { \"name\": \"arguments\", \"type\": \"array\", \"items\": { \"$ref\": \"CallArgument\" }, \"optional\": true },\n                    { \"name\": \"result\", \"$ref\": \"CallArgument\", \"optional\": true },\n                    { \"name\": \"isDrawingCall\", \"type\": \"boolean\", \"optional\": true },\n                    { \"name\": \"isFrameEndCall\", \"type\": \"boolean\", \"optional\": true },\n                    { \"name\": \"property\", \"type\": \"string\", \"optional\": true },\n                    { \"name\": \"value\", \"$ref\": \"CallArgument\", \"optional\": true },\n                    { \"name\": \"sourceURL\", \"type\": \"string\", \"optional\": true },\n                    { \"name\": \"lineNumber\", \"type\": \"integer\", \"optional\": true },\n                    { \"name\": \"columnNumber\", \"type\": \"integer\", \"optional\": true }\n                ]\n            },\n            {\n                \"id\": \"TraceLogId\",\n                \"type\": \"string\",\n                \"description\": \"Unique trace log identifier.\"\n            },\n            {\n                \"id\": \"TraceLog\",\n                \"type\": \"object\",\n                \"properties\": [\n                    { \"name\": \"id\", \"$ref\": \"TraceLogId\" },\n                    { \"name\": \"calls\", \"type\": \"array\", \"items\": { \"$ref\": \"Call\" } },\n                    { \"name\": \"contexts\", \"type\": \"array\", \"items\": { \"$ref\": \"CallArgument\" } },\n                    { \"name\": \"startOffset\", \"type\": \"integer\" },\n                    { \"name\": \"alive\", \"type\": \"boolean\" },\n                    { \"name\": \"totalAvailableCalls\", \"type\": \"number\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables Canvas inspection.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables Canvas inspection.\"\n            },\n            {\n                \"name\": \"dropTraceLog\",\n                \"parameters\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" }\n                ]\n            },\n            {\n                \"name\": \"hasUninstrumentedCanvases\",\n                \"returns\": [\n                    { \"name\": \"result\", \"type\": \"boolean\" }\n                ],\n                \"description\": \"Checks if there is any uninstrumented canvas in the inspected page.\"\n            },\n            {\n                \"name\": \"captureFrame\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"optional\": true, \"description\": \"Identifier of the frame containing document whose canvases are to be captured. If omitted, main frame is assumed.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\", \"description\": \"Identifier of the trace log containing captured canvas calls.\" }\n                ],\n                \"description\": \"Starts (or continues) a canvas frame capturing which will be stopped automatically after the next frame is prepared.\"\n            },\n            {\n                \"name\": \"startCapturing\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"optional\": true, \"description\": \"Identifier of the frame containing document whose canvases are to be captured. If omitted, main frame is assumed.\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\", \"description\": \"Identifier of the trace log containing captured canvas calls.\" }\n                ],\n                \"description\": \"Starts (or continues) consecutive canvas frames capturing. The capturing is stopped by the corresponding stopCapturing command.\"\n            },\n            {\n                \"name\": \"stopCapturing\",\n                \"parameters\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" }\n                ]\n            },\n            {\n                \"name\": \"getTraceLog\",\n                \"parameters\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" },\n                    { \"name\": \"startOffset\", \"type\": \"integer\", \"optional\": true },\n                    { \"name\": \"maxLength\", \"type\": \"integer\", \"optional\": true }\n                ],\n                \"returns\": [\n                    { \"name\": \"traceLog\", \"$ref\": \"TraceLog\" }\n                ]\n            },\n            {\n                \"name\": \"replayTraceLog\",\n                \"parameters\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" },\n                    { \"name\": \"stepNo\", \"type\": \"integer\", \"description\": \"Last call index in the trace log to replay (zero based).\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"resourceState\", \"$ref\": \"ResourceState\" },\n                    { \"name\": \"replayTime\", \"type\": \"number\", \"description\": \"Replay time (in milliseconds).\" }\n                ]\n            },\n            {\n                \"name\": \"getResourceState\",\n                \"parameters\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" },\n                    { \"name\": \"resourceId\", \"$ref\": \"ResourceId\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"resourceState\", \"$ref\": \"ResourceState\" }\n                ]\n            },\n            {\n                \"name\": \"evaluateTraceLogCallArgument\",\n                \"parameters\": [\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\" },\n                    { \"name\": \"callIndex\", \"type\": \"integer\", \"description\": \"Index of the call to evaluate on (zero based).\" },\n                    { \"name\": \"argumentIndex\", \"type\": \"integer\", \"description\": \"Index of the argument to evaluate (zero based). Provide <code>-1</code> to evaluate call result.\" },\n                    { \"name\": \"objectGroup\", \"type\": \"string\", \"optional\": true, \"description\": \"String object group name to put result into (allows rapid releasing resulting object handles using <code>Runtime.releaseObjectGroup</code>).\" }\n                ],\n                \"returns\": [\n                    { \"name\": \"result\", \"$ref\": \"Runtime.RemoteObject\", \"optional\": true, \"description\": \"Object wrapper for the evaluation result.\" },\n                    { \"name\": \"resourceState\", \"$ref\": \"ResourceState\", \"optional\": true, \"description\": \"State of the <code>Resource</code> object.\" }\n                ],\n                \"description\": \"Evaluates a given trace call argument or its result.\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"contextCreated\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"description\": \"Identifier of the frame containing a canvas with a context.\" }\n                ],\n                \"description\": \"Fired when a canvas context has been created in the given frame. The context may not be instrumented (see hasUninstrumentedCanvases command).\"\n            },\n            {\n                \"name\": \"traceLogsRemoved\",\n                \"parameters\": [\n                    { \"name\": \"frameId\", \"$ref\": \"Page.FrameId\", \"optional\": true, \"description\": \"If given, trace logs from the given frame were removed.\" },\n                    { \"name\": \"traceLogId\", \"$ref\": \"TraceLogId\", \"optional\": true, \"description\": \"If given, trace log with the given ID was removed.\" }\n                ],\n                \"description\": \"Fired when a set of trace logs were removed from the backend. If no parameters are given, all trace logs were removed.\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Input\",\n        \"types\": [\n            {\n                \"id\": \"TouchPoint\",\n                \"type\": \"object\",\n                \"hidden\": true,\n                \"properties\": [\n                    { \"name\": \"state\", \"type\": \"string\", \"enum\": [\"touchPressed\", \"touchReleased\", \"touchMoved\", \"touchStationary\", \"touchCancelled\"], \"description\": \"State of the touch point.\" },\n                    { \"name\": \"x\", \"type\": \"integer\", \"description\": \"X coordinate of the event relative to the main frame's viewport.\"},\n                    { \"name\": \"y\", \"type\": \"integer\", \"description\": \"Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport.\"},\n                    { \"name\": \"radiusX\", \"type\": \"integer\", \"optional\": true, \"description\": \"X radius of the touch area (default: 1).\"},\n                    { \"name\": \"radiusY\", \"type\": \"integer\", \"optional\": true, \"description\": \"Y radius of the touch area (default: 1).\"},\n                    { \"name\": \"rotationAngle\", \"type\": \"number\", \"optional\": true, \"description\": \"Rotation angle (default: 0.0).\"},\n                    { \"name\": \"force\", \"type\": \"number\", \"optional\": true, \"description\": \"Force (default: 1.0).\"},\n                    { \"name\": \"id\", \"type\": \"number\", \"optional\": true, \"description\": \"Identifier used to track touch sources between events, must be unique within an event.\"}\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"dispatchKeyEvent\",\n                \"parameters\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"keyDown\", \"keyUp\", \"rawKeyDown\", \"char\"], \"description\": \"Type of the key event.\" },\n                    { \"name\": \"modifiers\", \"type\": \"integer\", \"optional\": true, \"description\": \"Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).\" },\n                    { \"name\": \"timestamp\", \"type\": \"number\", \"optional\": true, \"description\": \"Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).\" },\n                    { \"name\": \"text\", \"type\": \"string\", \"optional\": true, \"description\": \"Text as generated by processing a virtual key code with a keyboard layout. Not needed for for <code>keyUp</code> and <code>rawKeyDown</code> events (default: \\\"\\\")\" },\n                    { \"name\": \"unmodifiedText\", \"type\": \"string\", \"optional\": true, \"description\": \"Text that would have been generated by the keyboard if no modifiers were pressed (except for shift). Useful for shortcut (accelerator) key handling (default: \\\"\\\").\" },\n                    { \"name\": \"keyIdentifier\", \"type\": \"string\", \"optional\": true, \"description\": \"Unique key identifier (e.g., 'U+0041') (default: \\\"\\\").\" },\n                    { \"name\": \"windowsVirtualKeyCode\", \"type\": \"integer\", \"optional\": true, \"description\": \"Windows virtual key code (default: 0).\" },\n                    { \"name\": \"nativeVirtualKeyCode\", \"type\": \"integer\", \"optional\": true, \"description\": \"Native virtual key code (default: 0).\" },\n                    { \"name\": \"macCharCode\", \"type\": \"integer\", \"optional\": true, \"description\": \"Mac character code (default: 0).\" },\n                    { \"name\": \"autoRepeat\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the event was generated from auto repeat (default: false).\" },\n                    { \"name\": \"isKeypad\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the event was generated from the keypad (default: false).\" },\n                    { \"name\": \"isSystemKey\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Whether the event was a system key event (default: false).\" }\n                ],\n                \"description\": \"Dispatches a key event to the page.\"\n            },\n            {\n                \"name\": \"dispatchMouseEvent\",\n                \"parameters\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"mousePressed\", \"mouseReleased\", \"mouseMoved\"], \"description\": \"Type of the mouse event.\" },\n                    { \"name\": \"x\", \"type\": \"integer\", \"description\": \"X coordinate of the event relative to the main frame's viewport.\"},\n                    { \"name\": \"y\", \"type\": \"integer\", \"description\": \"Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport.\"},\n                    { \"name\": \"modifiers\", \"type\": \"integer\", \"optional\": true, \"description\": \"Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).\" },\n                    { \"name\": \"timestamp\", \"type\": \"number\", \"optional\": true, \"description\": \"Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).\" },\n                    { \"name\": \"button\", \"type\": \"string\", \"enum\": [\"none\", \"left\", \"middle\", \"right\"], \"optional\": true, \"description\": \"Mouse button (default: \\\"none\\\").\" },\n                    { \"name\": \"clickCount\", \"type\": \"integer\", \"optional\": true, \"description\": \"Number of times the mouse button was clicked (default: 0).\" },\n                    { \"name\": \"deviceSpace\", \"type\": \"boolean\", \"optional\": true, \"hidden\": true, \"description\": \"If true, x and y are given in dip wrt current viewport.\" }\n                ],\n                \"description\": \"Dispatches a mouse event to the page.\"\n            },\n            {\n                \"name\": \"dispatchTouchEvent\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"touchStart\", \"touchEnd\", \"touchMove\"], \"description\": \"Type of the touch event.\" },\n                    { \"name\": \"touchPoints\", \"type\": \"array\", \"items\": { \"$ref\": \"TouchPoint\" }, \"description\": \"Touch points.\" },\n                    { \"name\": \"modifiers\", \"type\": \"integer\", \"optional\": true, \"description\": \"Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).\" },\n                    { \"name\": \"timestamp\", \"type\": \"number\", \"optional\": true, \"description\": \"Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).\" }\n                ],\n                \"description\": \"Dispatches a touch event to the page.\"\n            },\n            {\n                \"name\": \"dispatchGestureEvent\",\n                \"hidden\": true,\n                \"parameters\": [\n                    { \"name\": \"type\", \"type\": \"string\", \"enum\": [\"scrollBegin\", \"scrollEnd\", \"scrollUpdate\", \"tapDown\", \"tap\", \"pinchBegin\", \"pinchEnd\", \"pinchUpdate\"], \"description\": \"Type of the gesture event.\" },\n                    { \"name\": \"x\", \"type\": \"integer\", \"description\": \"X coordinate relative to the screen's viewport.\"},\n                    { \"name\": \"y\", \"type\": \"integer\", \"description\": \"Y coordinate relative to the screen's viewport.\"},\n                    { \"name\": \"timestamp\", \"type\": \"number\", \"optional\": true, \"description\": \"Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).\" },\n                    { \"name\": \"deltaX\", \"type\": \"integer\", \"optional\": true, \"description\": \"Delta X where apllies.\"},\n                    { \"name\": \"deltaY\", \"type\": \"integer\", \"optional\": true, \"description\": \"Delta Y where apllies.\"},\n                    { \"name\": \"pinchScale\", \"type\": \"number\", \"optional\": true, \"description\": \"Pinch scale.\" }\n                ],\n                \"description\": \"Dispatches a gesture event to the page.\"\n            }\n        ],\n        \"events\": []\n    },\n    {\n        \"domain\": \"LayerTree\",\n        \"hidden\": true,\n        \"types\": [\n            {\n                \"id\": \"LayerId\",\n                \"type\": \"string\",\n                \"description\": \"Unique RenderLayer identifier.\"\n            },\n            {\n                \"id\": \"Layer\",\n                \"type\": \"object\",\n                \"description\": \"Information about a compositing layer.\",\n                \"properties\": [\n                    { \"name\": \"layerId\", \"$ref\": \"LayerId\", \"description\": \"The unique id for this layer.\" },\n                    { \"name\": \"parentLayerId\", \"$ref\": \"LayerId\", \"optional\": true, \"description\": \"The id of parent (not present for root).\" },\n                    { \"name\": \"nodeId\", \"$ref\": \"DOM.NodeId\", \"optional\": true, \"description\": \"The id for the node associated with this layer.\" },\n                    { \"name\": \"offsetX\", \"type\": \"number\", \"description\": \"Offset from parent layer, X coordinate.\" },\n                    { \"name\": \"offsetY\", \"type\": \"number\", \"description\": \"Offset from parent layer, X coordinate.\" },\n                    { \"name\": \"width\", \"type\": \"number\", \"description\": \"Layer width.\" },\n                    { \"name\": \"height\", \"type\": \"number\", \"description\": \"Layer height.\" },\n                    { \"name\": \"transform\", \"type\": \"array\", \"items\": { \"type\": \"number\" }, \"minItems\": 16, \"maxItems\": 16, \"optional\": true, \"description\": \"Transformation matrix for layer, default is identity matrix\" },\n                    { \"name\": \"anchorX\", \"type\": \"number\", \"optional\": true, \"description\": \"Transform anchor point X, absent if no transform specified\" },\n                    { \"name\": \"anchorY\", \"type\": \"number\", \"optional\": true, \"description\": \"Transform anchor point Y, absent if no transform specified\" },\n                    { \"name\": \"anchorZ\", \"type\": \"number\", \"optional\": true, \"description\": \"Transform anchor point Z, absent if no transform specified\" },\n                    { \"name\": \"paintCount\", \"type\": \"integer\", \"description\": \"Indicates how many time this layer has painted.\" },\n                    { \"name\": \"invisible\", \"type\": \"boolean\", \"optional\": true, \"description\": \"Set if layer is not visible.\" }\n                ]\n            }\n        ],\n        \"commands\": [\n            {\n                \"name\": \"enable\",\n                \"description\": \"Enables compositing tree inspection.\"\n            },\n            {\n                \"name\": \"disable\",\n                \"description\": \"Disables compositing tree inspection.\"\n            },\n            {\n                \"name\": \"getLayers\",\n                \"parameters\": [\n                    { \"name\": \"nodeId\", \"optional\": true, \"$ref\": \"DOM.NodeId\", \"description\": \"Root of the subtree for which we want to gather layers (return entire tree if not specified)\" }\n                ],\n                \"description\": \"Returns the layer tree structure of the current page.\",\n                \"returns\": [\n                    { \"name\": \"layers\", \"type\": \"array\", \"items\": { \"$ref\": \"Layer\" }, \"description\": \"Child layers.\" }\n                ]\n            },\n            {\n                \"name\": \"compositingReasons\",\n                \"parameters\": [\n                    { \"name\": \"layerId\", \"$ref\": \"LayerId\", \"description\": \"The id of the layer for which we want to get the reasons it was composited.\" }\n                ],\n                \"description\": \"Provides the reasons why the given layer was composited.\",\n                \"returns\": [\n                    { \"name\": \"compositingReasons\", \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"A list of strings specifying reasons for the given layer to become composited.\" }\n                ]\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"layerTreeDidChange\"\n            }\n        ]\n    },\n    {\n        \"domain\": \"Tracing\",\n        \"hidden\": true,\n        \"commands\": [\n            {\n                \"name\": \"start\",\n                \"description\": \"Strart trace events collection.\",\n                \"parameters\": [\n                    { \"name\": \"categories\", \"type\": \"string\", \"description\": \"Category/tag filter\" }\n                ]\n            },\n            {\n                \"name\": \"end\",\n                \"description\": \"Stop trace events collection.\"\n            }\n        ],\n        \"events\": [\n            {\n                \"name\": \"dataCollected\",\n                \"parameters\": [\n                    { \"name\": \"value\", \"type\": \"array\", \"items\": { \"type\": \"object\" } }\n                ]\n            },\n            {\n                \"name\": \"tracingComplete\"\n            }\n        ]\n    }]\n}\n"
  },
  {
    "path": "src/LiveDevelopment/Inspector/inspector.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>Inspector 1.1 Documentation</title>\n<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js\"></script>\n<script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js\"></script>\n<script src=\"http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js\"></script>\n<script>\n$(function () {\nvar _domain = $(window.location.hash);\nif (_domain.length === 0) _domain = $(\"#toc\");\n$(\".domain\").hide();\n_domain.show();\n$(\".dropdown-toggle\").dropdown();\n$(\"a[href^=#]\").click(function (e) {\ne.preventDefault();\nvar domainAndName = e.currentTarget.hash.split(\".\");\nwindow.location = domainAndName[0];\nvar symbol = $(domainAndName.join(\"_\"));\nvar speed;\nif (_domain !== domainAndName[0]) {\n$(_domain).hide();\n_domain = domainAndName[0];\n$(_domain).show();\nspeed = 0;\n} else {\nspeed = \"fast\";\n}\n$(\"html, body\").animate({\nscrollTop: symbol.offset().top - 70 + \"px\"\n}, speed);\nif (domainAndName.length > 1) symbol.effect(\"highlight\", { color: \"#ffc\"}, 1000);\n});\n});\n</script>\n<link href=\"http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css\" rel=\"stylesheet\">\n<style>\nbody {padding: 70px 0 20px 0;}\nh3, dl {font-family: Menlo, Monaco, \"Courier New\", monospace;}\ndl {font-size: 12.025px;}\ndl dd {margin-bottom: 6px;}\ndl .text {margin-left:12px; font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;}\nh3 {border-top: 1px solid #aaa; padding: 8px 0;}\nh3 .label {float: left; margin: 6px;}\nfooter p {text-align: center; margin: 0;}\n</style>\n</head>\n<body>\n<div class=\"navbar navbar-fixed-top\">\n<div class=\"navbar-inner\">\n<div class=\"container\">\n<a href=\"#toc\" class=\"brand\">WebInspector v1.1</a>\n<ul class=\"nav nav-pills\">\n<li class=\"dropdown\" id=\"domain-menu\">\n<a class=\"dropdown-toggle\" data-toggle=\"dropdown\">Domains<b class=\"caret\"></b></a>\n<ul class=\"dropdown-menu\">\n<li><a href='#ApplicationCache'>ApplicationCache</a></li>\n<li><a href='#CSS'>CSS</a></li>\n<li><a href='#Canvas'>Canvas</a></li>\n<li><a href='#Console'>Console</a></li>\n<li><a href='#DOM'>DOM</a></li>\n<li><a href='#DOMDebugger'>DOMDebugger</a></li>\n<li><a href='#DOMStorage'>DOMStorage</a></li>\n<li><a href='#Database'>Database</a></li>\n<li><a href='#Debugger'>Debugger</a></li>\n<li><a href='#FileSystem'>FileSystem</a></li>\n<li><a href='#HeapProfiler'>HeapProfiler</a></li>\n<li><a href='#IndexedDB'>IndexedDB</a></li>\n<li><a href='#Input'>Input</a></li>\n<li><a href='#Inspector'>Inspector</a></li>\n<li><a href='#LayerTree'>LayerTree</a></li>\n<li><a href='#Memory'>Memory</a></li>\n<li><a href='#Network'>Network</a></li>\n<li><a href='#Page'>Page</a></li>\n<li><a href='#Profiler'>Profiler</a></li>\n<li><a href='#Runtime'>Runtime</a></li>\n<li><a href='#Timeline'>Timeline</a></li>\n<li><a href='#Tracing'>Tracing</a></li>\n<li><a href='#Worker'>Worker</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n</div>\n<div class='container'>\n<section id='toc' class='domain'>\n<h1>Table of Contents</h1>\n<h3><a href=\"#ApplicationCache\">ApplicationCache</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#ApplicationCache.ApplicationCacheResource'>ApplicationCache.ApplicationCacheResource</a>: Detailed application cache resource information.</li>\n<li><a href='#ApplicationCache.ApplicationCache'>ApplicationCache.ApplicationCache</a>: Detailed application cache information.</li>\n<li><a href='#ApplicationCache.FrameWithManifest'>ApplicationCache.FrameWithManifest</a>: Frame identifier - manifest URL pair.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#ApplicationCache.getFramesWithManifests'>ApplicationCache.getFramesWithManifests</a>: Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache.</li>\n<li><a href='#ApplicationCache.enable'>ApplicationCache.enable</a>: Enables application cache domain notifications.</li>\n<li><a href='#ApplicationCache.getManifestForFrame'>ApplicationCache.getManifestForFrame</a>: Returns manifest URL for document in the given frame.</li>\n<li><a href='#ApplicationCache.getApplicationCacheForFrame'>ApplicationCache.getApplicationCacheForFrame</a>: Returns relevant application cache data for the document in given frame.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#ApplicationCache.applicationCacheStatusUpdated'>ApplicationCache.applicationCacheStatusUpdated</a></li>\n<li><a href='#ApplicationCache.networkStateUpdated'>ApplicationCache.networkStateUpdated</a></li>\n</ul>\n<h3><a href=\"#CSS\">CSS</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a></li>\n<li><a href='#CSS.CSSStyleId'>CSS.CSSStyleId</a>: This object identifies a CSS style in a unique way.</li>\n<li><a href='#CSS.StyleSheetOrigin'>CSS.StyleSheetOrigin</a>: Stylesheet type: \"user\" for user stylesheets, \"user-agent\" for user-agent stylesheets, \"inspector\" for stylesheets created by the inspector (i.e. those holding the \"via inspector\" rules), \"regular\" for regular stylesheets.</li>\n<li><a href='#CSS.CSSRuleId'>CSS.CSSRuleId</a>: This object identifies a CSS rule in a unique way.</li>\n<li><a href='#CSS.PseudoIdMatches'>CSS.PseudoIdMatches</a>: CSS rule collection for a single pseudo style.</li>\n<li><a href='#CSS.InheritedStyleEntry'>CSS.InheritedStyleEntry</a>: CSS rule collection for a single pseudo style.</li>\n<li><a href='#CSS.RuleMatch'>CSS.RuleMatch</a>: Match data for a CSS rule.</li>\n<li><a href='#CSS.SelectorList'>CSS.SelectorList</a>: Selector list data.</li>\n<li><a href='#CSS.CSSStyleAttribute'>CSS.CSSStyleAttribute</a>: CSS style information for a DOM style attribute.</li>\n<li><a href='#CSS.CSSStyleSheetHeader'>CSS.CSSStyleSheetHeader</a>: CSS stylesheet metainformation.</li>\n<li><a href='#CSS.CSSStyleSheetBody'>CSS.CSSStyleSheetBody</a>: CSS stylesheet contents.</li>\n<li><a href='#CSS.CSSRule'>CSS.CSSRule</a>: CSS rule representation.</li>\n<li><a href='#CSS.SourceRange'>CSS.SourceRange</a>: Text range within a resource. All numbers are zero-based.</li>\n<li><a href='#CSS.ShorthandEntry'>CSS.ShorthandEntry</a></li>\n<li><a href='#CSS.CSSPropertyInfo'>CSS.CSSPropertyInfo</a></li>\n<li><a href='#CSS.CSSComputedStyleProperty'>CSS.CSSComputedStyleProperty</a></li>\n<li><a href='#CSS.CSSStyle'>CSS.CSSStyle</a>: CSS style representation.</li>\n<li><a href='#CSS.CSSProperty'>CSS.CSSProperty</a>: CSS property declaration data.</li>\n<li><a href='#CSS.CSSMedia'>CSS.CSSMedia</a>: CSS media query descriptor.</li>\n<li><a href='#CSS.SelectorProfileEntry'>CSS.SelectorProfileEntry</a>: CSS selector profile entry.</li>\n<li><a href='#CSS.SelectorProfile'>CSS.SelectorProfile</a></li>\n<li><a href='#CSS.Region'>CSS.Region</a>: This object represents a region that flows from a Named Flow.</li>\n<li><a href='#CSS.NamedFlow'>CSS.NamedFlow</a>: This object represents a Named Flow.</li>\n<li><a href='#CSS.PlatformFontUsage'>CSS.PlatformFontUsage</a>: Information about amount of glyphs that were rendered with given font.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#CSS.enable'>CSS.enable</a>: Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been enabled until the result of this command is received.</li>\n<li><a href='#CSS.disable'>CSS.disable</a>: Disables the CSS agent for the given page.</li>\n<li><a href='#CSS.getMatchedStylesForNode'>CSS.getMatchedStylesForNode</a>: Returns requested styles for a DOM node identified by nodeId.</li>\n<li><a href='#CSS.getInlineStylesForNode'>CSS.getInlineStylesForNode</a>: Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM attributes) for a DOM node identified by nodeId.</li>\n<li><a href='#CSS.getComputedStyleForNode'>CSS.getComputedStyleForNode</a>: Returns the computed style for a DOM node identified by nodeId.</li>\n<li><a href='#CSS.getPlatformFontsForNode'>CSS.getPlatformFontsForNode</a>: Requests information about platform fonts which we used to render child TextNodes in the given node.</li>\n<li><a href='#CSS.getAllStyleSheets'>CSS.getAllStyleSheets</a>: Returns metainfo entries for all known stylesheets.</li>\n<li><a href='#CSS.getStyleSheet'>CSS.getStyleSheet</a>: Returns stylesheet data for the specified styleSheetId.</li>\n<li><a href='#CSS.getStyleSheetText'>CSS.getStyleSheetText</a>: Returns the current textual content and the URL for a stylesheet.</li>\n<li><a href='#CSS.setStyleSheetText'>CSS.setStyleSheetText</a>: Sets the new stylesheet text, thereby invalidating all existing CSSStyleId's and CSSRuleId's contained by this stylesheet.</li>\n<li><a href='#CSS.setStyleText'>CSS.setStyleText</a>: Updates the CSSStyleDeclaration text.</li>\n<li><a href='#CSS.setPropertyText'>CSS.setPropertyText</a>: Sets the new text for a property in the respective style, at offset propertyIndex. If overwrite is true, a property at the given offset is overwritten, otherwise inserted. text entirely replaces the property name: value.</li>\n<li><a href='#CSS.toggleProperty'>CSS.toggleProperty</a>: Toggles the property in the respective style, at offset propertyIndex. The disable parameter denotes whether the property should be disabled (i.e. removed from the style declaration). If disable == false, the property gets put back into its original place in the style declaration.</li>\n<li><a href='#CSS.setRuleSelector'>CSS.setRuleSelector</a>: Modifies the rule selector.</li>\n<li><a href='#CSS.addRule'>CSS.addRule</a>: Creates a new empty rule with the given selector in a special \"inspector\" stylesheet in the owner document of the context node.</li>\n<li><a href='#CSS.getSupportedCSSProperties'>CSS.getSupportedCSSProperties</a>: Returns all supported CSS property names.</li>\n<li><a href='#CSS.forcePseudoState'>CSS.forcePseudoState</a>: Ensures that the given node will have specified pseudo-classes whenever its style is computed by the browser.</li>\n<li><a href='#CSS.getNamedFlowCollection'>CSS.getNamedFlowCollection</a>: Returns the Named Flows from the document.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#CSS.mediaQueryResultChanged'>CSS.mediaQueryResultChanged</a>: Fires whenever a MediaQuery result changes (for example, after a browser window has been resized.) The current implementation considers only viewport-dependent media features.</li>\n<li><a href='#CSS.styleSheetChanged'>CSS.styleSheetChanged</a>: Fired whenever a stylesheet is changed as a result of the client operation.</li>\n<li><a href='#CSS.styleSheetAdded'>CSS.styleSheetAdded</a>: Fired whenever an active document stylesheet is added.</li>\n<li><a href='#CSS.styleSheetRemoved'>CSS.styleSheetRemoved</a>: Fired whenever an active document stylesheet is removed.</li>\n<li><a href='#CSS.namedFlowCreated'>CSS.namedFlowCreated</a>: Fires when a Named Flow is created.</li>\n<li><a href='#CSS.namedFlowRemoved'>CSS.namedFlowRemoved</a>: Fires when a Named Flow is removed: has no associated content nodes and regions.</li>\n<li><a href='#CSS.regionLayoutUpdated'>CSS.regionLayoutUpdated</a>: Fires when a Named Flow's layout may have changed.</li>\n<li><a href='#CSS.regionOversetChanged'>CSS.regionOversetChanged</a>: Fires if any of the regionOverset values changed in a Named Flow's region chain.</li>\n</ul>\n<h3><a href=\"#Canvas\">Canvas</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Canvas.ResourceId'>Canvas.ResourceId</a>: Unique resource identifier.</li>\n<li><a href='#Canvas.ResourceStateDescriptor'>Canvas.ResourceStateDescriptor</a>: Resource state descriptor.</li>\n<li><a href='#Canvas.ResourceState'>Canvas.ResourceState</a>: Resource state.</li>\n<li><a href='#Canvas.CallArgument'>Canvas.CallArgument</a></li>\n<li><a href='#Canvas.Call'>Canvas.Call</a></li>\n<li><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a>: Unique trace log identifier.</li>\n<li><a href='#Canvas.TraceLog'>Canvas.TraceLog</a></li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Canvas.enable'>Canvas.enable</a>: Enables Canvas inspection.</li>\n<li><a href='#Canvas.disable'>Canvas.disable</a>: Disables Canvas inspection.</li>\n<li><a href='#Canvas.dropTraceLog'>Canvas.dropTraceLog</a></li>\n<li><a href='#Canvas.hasUninstrumentedCanvases'>Canvas.hasUninstrumentedCanvases</a>: Checks if there is any uninstrumented canvas in the inspected page.</li>\n<li><a href='#Canvas.captureFrame'>Canvas.captureFrame</a>: Starts (or continues) a canvas frame capturing which will be stopped automatically after the next frame is prepared.</li>\n<li><a href='#Canvas.startCapturing'>Canvas.startCapturing</a>: Starts (or continues) consecutive canvas frames capturing. The capturing is stopped by the corresponding stopCapturing command.</li>\n<li><a href='#Canvas.stopCapturing'>Canvas.stopCapturing</a></li>\n<li><a href='#Canvas.getTraceLog'>Canvas.getTraceLog</a></li>\n<li><a href='#Canvas.replayTraceLog'>Canvas.replayTraceLog</a></li>\n<li><a href='#Canvas.getResourceState'>Canvas.getResourceState</a></li>\n<li><a href='#Canvas.evaluateTraceLogCallArgument'>Canvas.evaluateTraceLogCallArgument</a>: Evaluates a given trace call argument or its result.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Canvas.contextCreated'>Canvas.contextCreated</a>: Fired when a canvas context has been created in the given frame. The context may not be instrumented (see hasUninstrumentedCanvases command).</li>\n<li><a href='#Canvas.traceLogsRemoved'>Canvas.traceLogsRemoved</a>: Fired when a set of trace logs were removed from the backend. If no parameters are given, all trace logs were removed.</li>\n</ul>\n<h3><a href=\"#Console\">Console</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Console.Timestamp'>Console.Timestamp</a>: Number of seconds since epoch.</li>\n<li><a href='#Console.ConsoleMessage'>Console.ConsoleMessage</a>: Console message.</li>\n<li><a href='#Console.CallFrame'>Console.CallFrame</a>: Stack entry for console errors and assertions.</li>\n<li><a href='#Console.StackTrace'>Console.StackTrace</a>: Call frames for assertions or error messages.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Console.enable'>Console.enable</a>: Enables console domain, sends the messages collected so far to the client by means of the messageAdded notification.</li>\n<li><a href='#Console.disable'>Console.disable</a>: Disables console domain, prevents further console messages from being reported to the client.</li>\n<li><a href='#Console.clearMessages'>Console.clearMessages</a>: Clears console messages collected in the browser.</li>\n<li><a href='#Console.setMonitoringXHREnabled'>Console.setMonitoringXHREnabled</a>: Toggles monitoring of XMLHttpRequest. If true, console will receive messages upon each XHR issued.</li>\n<li><a href='#Console.addInspectedNode'>Console.addInspectedNode</a>: Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).</li>\n<li><a href='#Console.addInspectedHeapObject'>Console.addInspectedHeapObject</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Console.messageAdded'>Console.messageAdded</a>: Issued when new console message is added.</li>\n<li><a href='#Console.messageRepeatCountUpdated'>Console.messageRepeatCountUpdated</a>: Issued when subsequent message(s) are equal to the previous one(s).</li>\n<li><a href='#Console.messagesCleared'>Console.messagesCleared</a>: Issued when console is cleared. This happens either upon clearMessages command or after page navigation.</li>\n</ul>\n<h3><a href=\"#DOM\">DOM</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#DOM.NodeId'>DOM.NodeId</a>: Unique DOM node identifier.</li>\n<li><a href='#DOM.BackendNodeId'>DOM.BackendNodeId</a>: Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.</li>\n<li><a href='#DOM.PseudoType'>DOM.PseudoType</a>: Pseudo element type.</li>\n<li><a href='#DOM.Node'>DOM.Node</a>: DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.</li>\n<li><a href='#DOM.EventListener'>DOM.EventListener</a>: DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.</li>\n<li><a href='#DOM.RGBA'>DOM.RGBA</a>: A structure holding an RGBA color.</li>\n<li><a href='#DOM.Quad'>DOM.Quad</a>: An array of quad vertices, x immediately followed by y for each point, points clock-wise.</li>\n<li><a href='#DOM.BoxModel'>DOM.BoxModel</a>: Box model.</li>\n<li><a href='#DOM.Rect'>DOM.Rect</a>: Rectangle.</li>\n<li><a href='#DOM.HighlightConfig'>DOM.HighlightConfig</a>: Configuration data for the highlighting of page elements.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#DOM.enable'>DOM.enable</a>: Enables DOM agent for the given page.</li>\n<li><a href='#DOM.disable'>DOM.disable</a>: Disables DOM agent for the given page.</li>\n<li><a href='#DOM.getDocument'>DOM.getDocument</a>: Returns the root DOM node to the caller.</li>\n<li><a href='#DOM.requestChildNodes'>DOM.requestChildNodes</a>: Requests that children of the node with given id are returned to the caller in form of setChildNodes events where not only immediate children are retrieved, but all children down to the specified depth.</li>\n<li><a href='#DOM.querySelector'>DOM.querySelector</a>: Executes querySelector on a given node.</li>\n<li><a href='#DOM.querySelectorAll'>DOM.querySelectorAll</a>: Executes querySelectorAll on a given node.</li>\n<li><a href='#DOM.setNodeName'>DOM.setNodeName</a>: Sets node name for a node with given id.</li>\n<li><a href='#DOM.setNodeValue'>DOM.setNodeValue</a>: Sets node value for a node with given id.</li>\n<li><a href='#DOM.removeNode'>DOM.removeNode</a>: Removes node with given id.</li>\n<li><a href='#DOM.setAttributeValue'>DOM.setAttributeValue</a>: Sets attribute for an element with given id.</li>\n<li><a href='#DOM.setAttributesAsText'>DOM.setAttributesAsText</a>: Sets attributes on element with given id. This method is useful when user edits some existing attribute value and types in several attribute name/value pairs.</li>\n<li><a href='#DOM.removeAttribute'>DOM.removeAttribute</a>: Removes attribute with given name from an element with given id.</li>\n<li><a href='#DOM.getEventListenersForNode'>DOM.getEventListenersForNode</a>: Returns event listeners relevant to the node.</li>\n<li><a href='#DOM.getOuterHTML'>DOM.getOuterHTML</a>: Returns node's HTML markup.</li>\n<li><a href='#DOM.setOuterHTML'>DOM.setOuterHTML</a>: Sets node HTML markup, returns new node id.</li>\n<li><a href='#DOM.performSearch'>DOM.performSearch</a>: Searches for a given string in the DOM tree. Use getSearchResults to access search results or cancelSearch to end this search session.</li>\n<li><a href='#DOM.getSearchResults'>DOM.getSearchResults</a>: Returns search results from given fromIndex to given toIndex from the sarch with the given identifier.</li>\n<li><a href='#DOM.discardSearchResults'>DOM.discardSearchResults</a>: Discards search results from the session with the given id. getSearchResults should no longer be called for that search.</li>\n<li><a href='#DOM.requestNode'>DOM.requestNode</a>: Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of setChildNodes notifications.</li>\n<li><a href='#DOM.setInspectModeEnabled'>DOM.setInspectModeEnabled</a>: Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection.</li>\n<li><a href='#DOM.highlightRect'>DOM.highlightRect</a>: Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport.</li>\n<li><a href='#DOM.highlightQuad'>DOM.highlightQuad</a>: Highlights given quad. Coordinates are absolute with respect to the main frame viewport.</li>\n<li><a href='#DOM.highlightNode'>DOM.highlightNode</a>: Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified.</li>\n<li><a href='#DOM.hideHighlight'>DOM.hideHighlight</a>: Hides DOM node highlight.</li>\n<li><a href='#DOM.highlightFrame'>DOM.highlightFrame</a>: Highlights owner element of the frame with given id.</li>\n<li><a href='#DOM.pushNodeByPathToFrontend'>DOM.pushNodeByPathToFrontend</a>: Requests that the node is sent to the caller given its path. // FIXME, use XPath</li>\n<li><a href='#DOM.pushNodeByBackendIdToFrontend'>DOM.pushNodeByBackendIdToFrontend</a>: Requests that the node is sent to the caller given its backend node id.</li>\n<li><a href='#DOM.releaseBackendNodeIds'>DOM.releaseBackendNodeIds</a>: Requests that group of BackendNodeIds is released.</li>\n<li><a href='#DOM.resolveNode'>DOM.resolveNode</a>: Resolves JavaScript node object for given node id.</li>\n<li><a href='#DOM.getAttributes'>DOM.getAttributes</a>: Returns attributes for the specified node.</li>\n<li><a href='#DOM.moveTo'>DOM.moveTo</a>: Moves node into the new container, places it before the given anchor.</li>\n<li><a href='#DOM.undo'>DOM.undo</a>: Undoes the last performed action.</li>\n<li><a href='#DOM.redo'>DOM.redo</a>: Re-does the last undone action.</li>\n<li><a href='#DOM.markUndoableState'>DOM.markUndoableState</a>: Marks last undoable state.</li>\n<li><a href='#DOM.focus'>DOM.focus</a>: Focuses the given element.</li>\n<li><a href='#DOM.setFileInputFiles'>DOM.setFileInputFiles</a>: Sets files for the given file input element.</li>\n<li><a href='#DOM.getBoxModel'>DOM.getBoxModel</a>: Returns boxes for the currently selected nodes.</li>\n<li><a href='#DOM.getNodeForLocation'>DOM.getNodeForLocation</a>: Returns node id at given location.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#DOM.documentUpdated'>DOM.documentUpdated</a>: Fired when Document has been totally updated. Node ids are no longer valid.</li>\n<li><a href='#DOM.inspectNodeRequested'>DOM.inspectNodeRequested</a>: Fired when the node should be inspected. This happens after call to setInspectModeEnabled.</li>\n<li><a href='#DOM.setChildNodes'>DOM.setChildNodes</a>: Fired when backend wants to provide client with the missing DOM structure. This happens upon most of the calls requesting node ids.</li>\n<li><a href='#DOM.attributeModified'>DOM.attributeModified</a>: Fired when Element's attribute is modified.</li>\n<li><a href='#DOM.attributeRemoved'>DOM.attributeRemoved</a>: Fired when Element's attribute is removed.</li>\n<li><a href='#DOM.inlineStyleInvalidated'>DOM.inlineStyleInvalidated</a>: Fired when Element's inline style is modified via a CSS property modification.</li>\n<li><a href='#DOM.characterDataModified'>DOM.characterDataModified</a>: Mirrors DOMCharacterDataModified event.</li>\n<li><a href='#DOM.childNodeCountUpdated'>DOM.childNodeCountUpdated</a>: Fired when Container's child node count has changed.</li>\n<li><a href='#DOM.childNodeInserted'>DOM.childNodeInserted</a>: Mirrors DOMNodeInserted event.</li>\n<li><a href='#DOM.childNodeRemoved'>DOM.childNodeRemoved</a>: Mirrors DOMNodeRemoved event.</li>\n<li><a href='#DOM.shadowRootPushed'>DOM.shadowRootPushed</a>: Called when shadow root is pushed into the element.</li>\n<li><a href='#DOM.shadowRootPopped'>DOM.shadowRootPopped</a>: Called when shadow root is popped from the element.</li>\n<li><a href='#DOM.pseudoElementAdded'>DOM.pseudoElementAdded</a>: Called when a pseudo element is added to an element.</li>\n<li><a href='#DOM.pseudoElementRemoved'>DOM.pseudoElementRemoved</a>: Called when a pseudo element is removed from an element.</li>\n</ul>\n<h3><a href=\"#DOMDebugger\">DOMDebugger</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#DOMDebugger.DOMBreakpointType'>DOMDebugger.DOMBreakpointType</a>: DOM breakpoint type.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#DOMDebugger.setDOMBreakpoint'>DOMDebugger.setDOMBreakpoint</a>: Sets breakpoint on particular operation with DOM.</li>\n<li><a href='#DOMDebugger.removeDOMBreakpoint'>DOMDebugger.removeDOMBreakpoint</a>: Removes DOM breakpoint that was set using setDOMBreakpoint.</li>\n<li><a href='#DOMDebugger.setEventListenerBreakpoint'>DOMDebugger.setEventListenerBreakpoint</a>: Sets breakpoint on particular DOM event.</li>\n<li><a href='#DOMDebugger.removeEventListenerBreakpoint'>DOMDebugger.removeEventListenerBreakpoint</a>: Removes breakpoint on particular DOM event.</li>\n<li><a href='#DOMDebugger.setInstrumentationBreakpoint'>DOMDebugger.setInstrumentationBreakpoint</a>: Sets breakpoint on particular native event.</li>\n<li><a href='#DOMDebugger.removeInstrumentationBreakpoint'>DOMDebugger.removeInstrumentationBreakpoint</a>: Removes breakpoint on particular native event.</li>\n<li><a href='#DOMDebugger.setXHRBreakpoint'>DOMDebugger.setXHRBreakpoint</a>: Sets breakpoint on XMLHttpRequest.</li>\n<li><a href='#DOMDebugger.removeXHRBreakpoint'>DOMDebugger.removeXHRBreakpoint</a>: Removes breakpoint from XMLHttpRequest.</li>\n</ul>\n<h3><a href=\"#DOMStorage\">DOMStorage</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a>: DOM Storage identifier.</li>\n<li><a href='#DOMStorage.Item'>DOMStorage.Item</a>: DOM Storage item.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#DOMStorage.enable'>DOMStorage.enable</a>: Enables storage tracking, storage events will now be delivered to the client.</li>\n<li><a href='#DOMStorage.disable'>DOMStorage.disable</a>: Disables storage tracking, prevents storage events from being sent to the client.</li>\n<li><a href='#DOMStorage.getDOMStorageItems'>DOMStorage.getDOMStorageItems</a></li>\n<li><a href='#DOMStorage.setDOMStorageItem'>DOMStorage.setDOMStorageItem</a></li>\n<li><a href='#DOMStorage.removeDOMStorageItem'>DOMStorage.removeDOMStorageItem</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#DOMStorage.domStorageItemsCleared'>DOMStorage.domStorageItemsCleared</a></li>\n<li><a href='#DOMStorage.domStorageItemRemoved'>DOMStorage.domStorageItemRemoved</a></li>\n<li><a href='#DOMStorage.domStorageItemAdded'>DOMStorage.domStorageItemAdded</a></li>\n<li><a href='#DOMStorage.domStorageItemUpdated'>DOMStorage.domStorageItemUpdated</a></li>\n</ul>\n<h3><a href=\"#Database\">Database</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Database.DatabaseId'>Database.DatabaseId</a>: Unique identifier of Database object.</li>\n<li><a href='#Database.Database'>Database.Database</a>: Database object.</li>\n<li><a href='#Database.Error'>Database.Error</a>: Database error.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Database.enable'>Database.enable</a>: Enables database tracking, database events will now be delivered to the client.</li>\n<li><a href='#Database.disable'>Database.disable</a>: Disables database tracking, prevents database events from being sent to the client.</li>\n<li><a href='#Database.getDatabaseTableNames'>Database.getDatabaseTableNames</a></li>\n<li><a href='#Database.executeSQL'>Database.executeSQL</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Database.addDatabase'>Database.addDatabase</a></li>\n</ul>\n<h3><a href=\"#Debugger\">Debugger</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Debugger.BreakpointId'>Debugger.BreakpointId</a>: Breakpoint identifier.</li>\n<li><a href='#Debugger.ScriptId'>Debugger.ScriptId</a>: Unique script identifier.</li>\n<li><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a>: Call frame identifier.</li>\n<li><a href='#Debugger.Location'>Debugger.Location</a>: Location in the source code.</li>\n<li><a href='#Debugger.FunctionDetails'>Debugger.FunctionDetails</a>: Information about the function.</li>\n<li><a href='#Debugger.CallFrame'>Debugger.CallFrame</a>: JavaScript call frame. Array of call frames form the call stack.</li>\n<li><a href='#Debugger.Scope'>Debugger.Scope</a>: Scope description.</li>\n<li><a href='#Debugger.SetScriptSourceError'>Debugger.SetScriptSourceError</a>: Error data for setScriptSource command. compileError is a case type for uncompilable script source error.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Debugger.enable'>Debugger.enable</a>: Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received.</li>\n<li><a href='#Debugger.disable'>Debugger.disable</a>: Disables debugger for given page.</li>\n<li><a href='#Debugger.setBreakpointsActive'>Debugger.setBreakpointsActive</a>: Activates / deactivates all breakpoints on the page.</li>\n<li><a href='#Debugger.setSkipAllPauses'>Debugger.setSkipAllPauses</a>: Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc).</li>\n<li><a href='#Debugger.setBreakpointByUrl'>Debugger.setBreakpointByUrl</a>: Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in locations property. Further matching script parsing will result in subsequent breakpointResolved events issued. This logical breakpoint will survive page reloads.</li>\n<li><a href='#Debugger.setBreakpoint'>Debugger.setBreakpoint</a>: Sets JavaScript breakpoint at a given location.</li>\n<li><a href='#Debugger.removeBreakpoint'>Debugger.removeBreakpoint</a>: Removes JavaScript breakpoint.</li>\n<li><a href='#Debugger.continueToLocation'>Debugger.continueToLocation</a>: Continues execution until specific location is reached.</li>\n<li><a href='#Debugger.stepOver'>Debugger.stepOver</a>: Steps over the statement.</li>\n<li><a href='#Debugger.stepInto'>Debugger.stepInto</a>: Steps into the function call.</li>\n<li><a href='#Debugger.stepOut'>Debugger.stepOut</a>: Steps out of the function call.</li>\n<li><a href='#Debugger.pause'>Debugger.pause</a>: Stops on the next JavaScript statement.</li>\n<li><a href='#Debugger.resume'>Debugger.resume</a>: Resumes JavaScript execution.</li>\n<li><a href='#Debugger.searchInContent'>Debugger.searchInContent</a>: Searches for given string in script content.</li>\n<li><a href='#Debugger.canSetScriptSource'>Debugger.canSetScriptSource</a>: Always returns true.</li>\n<li><a href='#Debugger.setScriptSource'>Debugger.setScriptSource</a>: Edits JavaScript source live.</li>\n<li><a href='#Debugger.restartFrame'>Debugger.restartFrame</a>: Restarts particular call frame from the beginning.</li>\n<li><a href='#Debugger.getScriptSource'>Debugger.getScriptSource</a>: Returns source for the script with given id.</li>\n<li><a href='#Debugger.getFunctionDetails'>Debugger.getFunctionDetails</a>: Returns detailed informtation on given function.</li>\n<li><a href='#Debugger.setPauseOnExceptions'>Debugger.setPauseOnExceptions</a>: Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is none.</li>\n<li><a href='#Debugger.evaluateOnCallFrame'>Debugger.evaluateOnCallFrame</a>: Evaluates expression on a given call frame.</li>\n<li><a href='#Debugger.compileScript'>Debugger.compileScript</a>: Compiles expression.</li>\n<li><a href='#Debugger.runScript'>Debugger.runScript</a>: Runs script with given id in a given context.</li>\n<li><a href='#Debugger.setOverlayMessage'>Debugger.setOverlayMessage</a>: Sets overlay message.</li>\n<li><a href='#Debugger.setVariableValue'>Debugger.setVariableValue</a>: Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually.</li>\n<li><a href='#Debugger.getStepInPositions'>Debugger.getStepInPositions</a>: Lists all positions where step-in is possible for a current statement in a specified call frame</li>\n<li><a href='#Debugger.getBacktrace'>Debugger.getBacktrace</a>: Returns call stack including variables changed since VM was paused. VM must be paused.</li>\n<li><a href='#Debugger.skipStackFrames'>Debugger.skipStackFrames</a>: Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Debugger.globalObjectCleared'>Debugger.globalObjectCleared</a>: Called when global has been cleared and debugger client should reset its state. Happens upon navigation or reload.</li>\n<li><a href='#Debugger.scriptParsed'>Debugger.scriptParsed</a>: Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.</li>\n<li><a href='#Debugger.scriptFailedToParse'>Debugger.scriptFailedToParse</a>: Fired when virtual machine fails to parse the script.</li>\n<li><a href='#Debugger.breakpointResolved'>Debugger.breakpointResolved</a>: Fired when breakpoint is resolved to an actual script and location.</li>\n<li><a href='#Debugger.paused'>Debugger.paused</a>: Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.</li>\n<li><a href='#Debugger.resumed'>Debugger.resumed</a>: Fired when the virtual machine resumed execution.</li>\n</ul>\n<h3><a href=\"#FileSystem\">FileSystem</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#FileSystem.Entry'>FileSystem.Entry</a>: Represents a browser side file or directory.</li>\n<li><a href='#FileSystem.Metadata'>FileSystem.Metadata</a>: Represents metadata of a file or entry.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#FileSystem.enable'>FileSystem.enable</a>: Enables events from backend.</li>\n<li><a href='#FileSystem.disable'>FileSystem.disable</a>: Disables events from backend.</li>\n<li><a href='#FileSystem.requestFileSystemRoot'>FileSystem.requestFileSystemRoot</a>: Returns root directory of the FileSystem, if exists.</li>\n<li><a href='#FileSystem.requestDirectoryContent'>FileSystem.requestDirectoryContent</a>: Returns content of the directory.</li>\n<li><a href='#FileSystem.requestMetadata'>FileSystem.requestMetadata</a>: Returns metadata of the entry.</li>\n<li><a href='#FileSystem.requestFileContent'>FileSystem.requestFileContent</a>: Returns content of the file. Result should be sliced into [start, end).</li>\n<li><a href='#FileSystem.deleteEntry'>FileSystem.deleteEntry</a>: Deletes specified entry. If the entry is a directory, the agent deletes children recursively.</li>\n</ul>\n<h3><a href=\"#HeapProfiler\">HeapProfiler</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#HeapProfiler.ProfileHeader'>HeapProfiler.ProfileHeader</a>: Profile header.</li>\n<li><a href='#HeapProfiler.HeapSnapshotObjectId'>HeapProfiler.HeapSnapshotObjectId</a>: Heap snashot object id.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#HeapProfiler.getProfileHeaders'>HeapProfiler.getProfileHeaders</a></li>\n<li><a href='#HeapProfiler.startTrackingHeapObjects'>HeapProfiler.startTrackingHeapObjects</a></li>\n<li><a href='#HeapProfiler.stopTrackingHeapObjects'>HeapProfiler.stopTrackingHeapObjects</a></li>\n<li><a href='#HeapProfiler.getHeapSnapshot'>HeapProfiler.getHeapSnapshot</a></li>\n<li><a href='#HeapProfiler.removeProfile'>HeapProfiler.removeProfile</a></li>\n<li><a href='#HeapProfiler.clearProfiles'>HeapProfiler.clearProfiles</a></li>\n<li><a href='#HeapProfiler.takeHeapSnapshot'>HeapProfiler.takeHeapSnapshot</a></li>\n<li><a href='#HeapProfiler.collectGarbage'>HeapProfiler.collectGarbage</a></li>\n<li><a href='#HeapProfiler.getObjectByHeapObjectId'>HeapProfiler.getObjectByHeapObjectId</a></li>\n<li><a href='#HeapProfiler.getHeapObjectId'>HeapProfiler.getHeapObjectId</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#HeapProfiler.addProfileHeader'>HeapProfiler.addProfileHeader</a></li>\n<li><a href='#HeapProfiler.addHeapSnapshotChunk'>HeapProfiler.addHeapSnapshotChunk</a></li>\n<li><a href='#HeapProfiler.finishHeapSnapshot'>HeapProfiler.finishHeapSnapshot</a></li>\n<li><a href='#HeapProfiler.resetProfiles'>HeapProfiler.resetProfiles</a></li>\n<li><a href='#HeapProfiler.reportHeapSnapshotProgress'>HeapProfiler.reportHeapSnapshotProgress</a></li>\n<li><a href='#HeapProfiler.lastSeenObjectId'>HeapProfiler.lastSeenObjectId</a>: If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.</li>\n<li><a href='#HeapProfiler.heapStatsUpdate'>HeapProfiler.heapStatsUpdate</a>: If heap objects tracking has been started then backend may send update for one or more fragments</li>\n</ul>\n<h3><a href=\"#IndexedDB\">IndexedDB</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#IndexedDB.DatabaseWithObjectStores'>IndexedDB.DatabaseWithObjectStores</a>: Database with an array of object stores.</li>\n<li><a href='#IndexedDB.ObjectStore'>IndexedDB.ObjectStore</a>: Object store.</li>\n<li><a href='#IndexedDB.ObjectStoreIndex'>IndexedDB.ObjectStoreIndex</a>: Object store index.</li>\n<li><a href='#IndexedDB.Key'>IndexedDB.Key</a>: Key.</li>\n<li><a href='#IndexedDB.KeyRange'>IndexedDB.KeyRange</a>: Key range.</li>\n<li><a href='#IndexedDB.DataEntry'>IndexedDB.DataEntry</a>: Data entry.</li>\n<li><a href='#IndexedDB.KeyPath'>IndexedDB.KeyPath</a>: Key path.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#IndexedDB.enable'>IndexedDB.enable</a>: Enables events from backend.</li>\n<li><a href='#IndexedDB.disable'>IndexedDB.disable</a>: Disables events from backend.</li>\n<li><a href='#IndexedDB.requestDatabaseNames'>IndexedDB.requestDatabaseNames</a>: Requests database names for given security origin.</li>\n<li><a href='#IndexedDB.requestDatabase'>IndexedDB.requestDatabase</a>: Requests database with given name in given frame.</li>\n<li><a href='#IndexedDB.requestData'>IndexedDB.requestData</a>: Requests data from object store or index.</li>\n<li><a href='#IndexedDB.clearObjectStore'>IndexedDB.clearObjectStore</a>: Clears all entries from an object store.</li>\n</ul>\n<h3><a href=\"#Input\">Input</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Input.TouchPoint'>Input.TouchPoint</a></li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Input.dispatchKeyEvent'>Input.dispatchKeyEvent</a>: Dispatches a key event to the page.</li>\n<li><a href='#Input.dispatchMouseEvent'>Input.dispatchMouseEvent</a>: Dispatches a mouse event to the page.</li>\n<li><a href='#Input.dispatchTouchEvent'>Input.dispatchTouchEvent</a>: Dispatches a touch event to the page.</li>\n<li><a href='#Input.dispatchGestureEvent'>Input.dispatchGestureEvent</a>: Dispatches a gesture event to the page.</li>\n</ul>\n<h3><a href=\"#Inspector\">Inspector</a></h3>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Inspector.enable'>Inspector.enable</a>: Enables inspector domain notifications.</li>\n<li><a href='#Inspector.disable'>Inspector.disable</a>: Disables inspector domain notifications.</li>\n<li><a href='#Inspector.reset'>Inspector.reset</a>: Resets all domains.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Inspector.evaluateForTestInFrontend'>Inspector.evaluateForTestInFrontend</a></li>\n<li><a href='#Inspector.inspect'>Inspector.inspect</a></li>\n<li><a href='#Inspector.detached'>Inspector.detached</a>: Fired when remote debugging connection is about to be terminated. Contains detach reason.</li>\n<li><a href='#Inspector.targetCrashed'>Inspector.targetCrashed</a>: Fired when debugging target has crashed</li>\n</ul>\n<h3><a href=\"#LayerTree\">LayerTree</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#LayerTree.LayerId'>LayerTree.LayerId</a>: Unique RenderLayer identifier.</li>\n<li><a href='#LayerTree.Layer'>LayerTree.Layer</a>: Information about a compositing layer.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#LayerTree.enable'>LayerTree.enable</a>: Enables compositing tree inspection.</li>\n<li><a href='#LayerTree.disable'>LayerTree.disable</a>: Disables compositing tree inspection.</li>\n<li><a href='#LayerTree.getLayers'>LayerTree.getLayers</a>: Returns the layer tree structure of the current page.</li>\n<li><a href='#LayerTree.compositingReasons'>LayerTree.compositingReasons</a>: Provides the reasons why the given layer was composited.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#LayerTree.layerTreeDidChange'>LayerTree.layerTreeDidChange</a></li>\n</ul>\n<h3><a href=\"#Memory\">Memory</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Memory.MemoryBlock'>Memory.MemoryBlock</a></li>\n<li><a href='#Memory.HeapSnapshotChunk'>Memory.HeapSnapshotChunk</a></li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Memory.getDOMCounters'>Memory.getDOMCounters</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Memory.addNativeSnapshotChunk'>Memory.addNativeSnapshotChunk</a></li>\n</ul>\n<h3><a href=\"#Network\">Network</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Network.LoaderId'>Network.LoaderId</a>: Unique loader identifier.</li>\n<li><a href='#Network.RequestId'>Network.RequestId</a>: Unique request identifier.</li>\n<li><a href='#Network.Timestamp'>Network.Timestamp</a>: Number of seconds since epoch.</li>\n<li><a href='#Network.Headers'>Network.Headers</a>: Request / response headers as keys / values of JSON object.</li>\n<li><a href='#Network.ResourceTiming'>Network.ResourceTiming</a>: Timing information for the request.</li>\n<li><a href='#Network.Request'>Network.Request</a>: HTTP request data.</li>\n<li><a href='#Network.Response'>Network.Response</a>: HTTP response data.</li>\n<li><a href='#Network.WebSocketRequest'>Network.WebSocketRequest</a>: WebSocket request data.</li>\n<li><a href='#Network.WebSocketResponse'>Network.WebSocketResponse</a>: WebSocket response data.</li>\n<li><a href='#Network.WebSocketFrame'>Network.WebSocketFrame</a>: WebSocket frame data.</li>\n<li><a href='#Network.CachedResource'>Network.CachedResource</a>: Information about the cached resource.</li>\n<li><a href='#Network.Initiator'>Network.Initiator</a>: Information about the request initiator.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Network.enable'>Network.enable</a>: Enables network tracking, network events will now be delivered to the client.</li>\n<li><a href='#Network.disable'>Network.disable</a>: Disables network tracking, prevents network events from being sent to the client.</li>\n<li><a href='#Network.setUserAgentOverride'>Network.setUserAgentOverride</a>: Allows overriding user agent with the given string.</li>\n<li><a href='#Network.setExtraHTTPHeaders'>Network.setExtraHTTPHeaders</a>: Specifies whether to always send extra HTTP headers with the requests from this page.</li>\n<li><a href='#Network.getResponseBody'>Network.getResponseBody</a>: Returns content served for the given request.</li>\n<li><a href='#Network.replayXHR'>Network.replayXHR</a>: This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.</li>\n<li><a href='#Network.canClearBrowserCache'>Network.canClearBrowserCache</a>: Tells whether clearing browser cache is supported.</li>\n<li><a href='#Network.clearBrowserCache'>Network.clearBrowserCache</a>: Clears browser cache.</li>\n<li><a href='#Network.canClearBrowserCookies'>Network.canClearBrowserCookies</a>: Tells whether clearing browser cookies is supported.</li>\n<li><a href='#Network.clearBrowserCookies'>Network.clearBrowserCookies</a>: Clears browser cookies.</li>\n<li><a href='#Network.setCacheDisabled'>Network.setCacheDisabled</a>: Toggles ignoring cache for each request. If true, cache will not be used.</li>\n<li><a href='#Network.loadResourceForFrontend'>Network.loadResourceForFrontend</a>: Loads a resource in the context of a frame on the inspected page without cross origin checks.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Network.requestWillBeSent'>Network.requestWillBeSent</a>: Fired when page is about to send HTTP request.</li>\n<li><a href='#Network.requestServedFromCache'>Network.requestServedFromCache</a>: Fired if request ended up loading from cache.</li>\n<li><a href='#Network.responseReceived'>Network.responseReceived</a>: Fired when HTTP response is available.</li>\n<li><a href='#Network.dataReceived'>Network.dataReceived</a>: Fired when data chunk was received over the network.</li>\n<li><a href='#Network.loadingFinished'>Network.loadingFinished</a>: Fired when HTTP request has finished loading.</li>\n<li><a href='#Network.loadingFailed'>Network.loadingFailed</a>: Fired when HTTP request has failed to load.</li>\n<li><a href='#Network.webSocketWillSendHandshakeRequest'>Network.webSocketWillSendHandshakeRequest</a>: Fired when WebSocket is about to initiate handshake.</li>\n<li><a href='#Network.webSocketHandshakeResponseReceived'>Network.webSocketHandshakeResponseReceived</a>: Fired when WebSocket handshake response becomes available.</li>\n<li><a href='#Network.webSocketCreated'>Network.webSocketCreated</a>: Fired upon WebSocket creation.</li>\n<li><a href='#Network.webSocketClosed'>Network.webSocketClosed</a>: Fired when WebSocket is closed.</li>\n<li><a href='#Network.webSocketFrameReceived'>Network.webSocketFrameReceived</a>: Fired when WebSocket frame is received.</li>\n<li><a href='#Network.webSocketFrameError'>Network.webSocketFrameError</a>: Fired when WebSocket frame error occurs.</li>\n<li><a href='#Network.webSocketFrameSent'>Network.webSocketFrameSent</a>: Fired when WebSocket frame is sent.</li>\n</ul>\n<h3><a href=\"#Page\">Page</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Page.ResourceType'>Page.ResourceType</a>: Resource type as it was perceived by the rendering engine.</li>\n<li><a href='#Page.FrameId'>Page.FrameId</a>: Unique frame identifier.</li>\n<li><a href='#Page.Frame'>Page.Frame</a>: Information about the Frame on the page.</li>\n<li><a href='#Page.FrameResourceTree'>Page.FrameResourceTree</a>: Information about the Frame hierarchy along with their cached resources.</li>\n<li><a href='#Page.SearchMatch'>Page.SearchMatch</a>: Search match for resource.</li>\n<li><a href='#Page.SearchResult'>Page.SearchResult</a>: Search result for resource.</li>\n<li><a href='#Page.Cookie'>Page.Cookie</a>: Cookie object</li>\n<li><a href='#Page.ScriptIdentifier'>Page.ScriptIdentifier</a>: Unique script identifier.</li>\n<li><a href='#Page.NavigationEntry'>Page.NavigationEntry</a>: Navigation history entry.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Page.enable'>Page.enable</a>: Enables page domain notifications.</li>\n<li><a href='#Page.disable'>Page.disable</a>: Disables page domain notifications.</li>\n<li><a href='#Page.addScriptToEvaluateOnLoad'>Page.addScriptToEvaluateOnLoad</a></li>\n<li><a href='#Page.removeScriptToEvaluateOnLoad'>Page.removeScriptToEvaluateOnLoad</a></li>\n<li><a href='#Page.reload'>Page.reload</a>: Reloads given page optionally ignoring the cache.</li>\n<li><a href='#Page.navigate'>Page.navigate</a>: Navigates current page to the given URL.</li>\n<li><a href='#Page.getNavigationHistory'>Page.getNavigationHistory</a>: Returns navigation history for the current page.</li>\n<li><a href='#Page.navigateToHistoryEntry'>Page.navigateToHistoryEntry</a>: Navigates current page to the given history entry.</li>\n<li><a href='#Page.getCookies'>Page.getCookies</a>: Returns all browser cookies. Depending on the backend support, will either return detailed cookie information in the cookie field or string cookie representation using cookieString.</li>\n<li><a href='#Page.deleteCookie'>Page.deleteCookie</a>: Deletes browser cookie with given name, domain and path.</li>\n<li><a href='#Page.getResourceTree'>Page.getResourceTree</a>: Returns present frame / resource tree structure.</li>\n<li><a href='#Page.getResourceContent'>Page.getResourceContent</a>: Returns content of the given resource.</li>\n<li><a href='#Page.searchInResource'>Page.searchInResource</a>: Searches for given string in resource content.</li>\n<li><a href='#Page.searchInResources'>Page.searchInResources</a>: Searches for given string in frame / resource tree structure.</li>\n<li><a href='#Page.setDocumentContent'>Page.setDocumentContent</a>: Sets given markup as the document's HTML.</li>\n<li><a href='#Page.setDeviceMetricsOverride'>Page.setDeviceMetricsOverride</a>: Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results) and the font scale factor.</li>\n<li><a href='#Page.setShowPaintRects'>Page.setShowPaintRects</a>: Requests that backend shows paint rectangles</li>\n<li><a href='#Page.setShowDebugBorders'>Page.setShowDebugBorders</a>: Requests that backend shows debug borders on layers</li>\n<li><a href='#Page.setShowFPSCounter'>Page.setShowFPSCounter</a>: Requests that backend shows the FPS counter</li>\n<li><a href='#Page.setContinuousPaintingEnabled'>Page.setContinuousPaintingEnabled</a>: Requests that backend enables continuous painting</li>\n<li><a href='#Page.setShowScrollBottleneckRects'>Page.setShowScrollBottleneckRects</a>: Requests that backend shows scroll bottleneck rects</li>\n<li><a href='#Page.getScriptExecutionStatus'>Page.getScriptExecutionStatus</a>: Determines if scripts can be executed in the page.</li>\n<li><a href='#Page.setScriptExecutionDisabled'>Page.setScriptExecutionDisabled</a>: Switches script execution in the page.</li>\n<li><a href='#Page.setGeolocationOverride'>Page.setGeolocationOverride</a>: Overrides the Geolocation Position or Error.</li>\n<li><a href='#Page.clearGeolocationOverride'>Page.clearGeolocationOverride</a>: Clears the overriden Geolocation Position and Error.</li>\n<li><a href='#Page.setDeviceOrientationOverride'>Page.setDeviceOrientationOverride</a>: Overrides the Device Orientation.</li>\n<li><a href='#Page.clearDeviceOrientationOverride'>Page.clearDeviceOrientationOverride</a>: Clears the overridden Device Orientation.</li>\n<li><a href='#Page.setTouchEmulationEnabled'>Page.setTouchEmulationEnabled</a>: Toggles mouse event-based touch event emulation.</li>\n<li><a href='#Page.setEmulatedMedia'>Page.setEmulatedMedia</a>: Emulates the given media for CSS media queries.</li>\n<li><a href='#Page.captureScreenshot'>Page.captureScreenshot</a>: Capture page screenshot.</li>\n<li><a href='#Page.startScreencast'>Page.startScreencast</a>: Starts sending each frame using the screencastFrame event.</li>\n<li><a href='#Page.stopScreencast'>Page.stopScreencast</a>: Stops sending each frame in the screencastFrame.</li>\n<li><a href='#Page.handleJavaScriptDialog'>Page.handleJavaScriptDialog</a>: Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).</li>\n<li><a href='#Page.setShowViewportSizeOnResize'>Page.setShowViewportSizeOnResize</a>: Paints viewport size upon main frame resize.</li>\n<li><a href='#Page.setForceCompositingMode'>Page.setForceCompositingMode</a>: Force accelerated compositing mode for inspected page.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Page.domContentEventFired'>Page.domContentEventFired</a></li>\n<li><a href='#Page.loadEventFired'>Page.loadEventFired</a></li>\n<li><a href='#Page.frameAttached'>Page.frameAttached</a>: Fired when frame has been attached to its parent.</li>\n<li><a href='#Page.frameNavigated'>Page.frameNavigated</a>: Fired once navigation of the frame has completed. Frame is now associated with the new loader.</li>\n<li><a href='#Page.frameDetached'>Page.frameDetached</a>: Fired when frame has been detached from its parent.</li>\n<li><a href='#Page.frameStartedLoading'>Page.frameStartedLoading</a>: Fired when frame has started loading.</li>\n<li><a href='#Page.frameStoppedLoading'>Page.frameStoppedLoading</a>: Fired when frame has stopped loading.</li>\n<li><a href='#Page.frameScheduledNavigation'>Page.frameScheduledNavigation</a>: Fired when frame schedules a potential navigation.</li>\n<li><a href='#Page.frameClearedScheduledNavigation'>Page.frameClearedScheduledNavigation</a>: Fired when frame no longer has a scheduled navigation.</li>\n<li><a href='#Page.javascriptDialogOpening'>Page.javascriptDialogOpening</a>: Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.</li>\n<li><a href='#Page.javascriptDialogClosed'>Page.javascriptDialogClosed</a>: Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) has been closed.</li>\n<li><a href='#Page.scriptsEnabled'>Page.scriptsEnabled</a>: Fired when the JavaScript is enabled/disabled on the page</li>\n<li><a href='#Page.screencastFrame'>Page.screencastFrame</a>: Compressed image data requested by the startScreencast.</li>\n<li><a href='#Page.screencastVisibilityChanged'>Page.screencastVisibilityChanged</a>: Fired when the page with currently enabled screencast was shown or hidden .</li>\n</ul>\n<h3><a href=\"#Profiler\">Profiler</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Profiler.ProfileHeader'>Profiler.ProfileHeader</a>: Profile header.</li>\n<li><a href='#Profiler.CPUProfileNode'>Profiler.CPUProfileNode</a>: CPU Profile node. Holds callsite information, execution statistics and child nodes.</li>\n<li><a href='#Profiler.CPUProfile'>Profiler.CPUProfile</a>: Profile.</li>\n<li><a href='#Profiler.HeapSnapshotObjectId'>Profiler.HeapSnapshotObjectId</a>: Heap snashot object id.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Profiler.enable'>Profiler.enable</a></li>\n<li><a href='#Profiler.disable'>Profiler.disable</a></li>\n<li><a href='#Profiler.setSamplingInterval'>Profiler.setSamplingInterval</a>: Changes CPU profiler sampling interval. Must be called before CPU profiles recording started.</li>\n<li><a href='#Profiler.start'>Profiler.start</a></li>\n<li><a href='#Profiler.stop'>Profiler.stop</a></li>\n<li><a href='#Profiler.getProfileHeaders'>Profiler.getProfileHeaders</a></li>\n<li><a href='#Profiler.getCPUProfile'>Profiler.getCPUProfile</a></li>\n<li><a href='#Profiler.removeProfile'>Profiler.removeProfile</a></li>\n<li><a href='#Profiler.clearProfiles'>Profiler.clearProfiles</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Profiler.addProfileHeader'>Profiler.addProfileHeader</a></li>\n<li><a href='#Profiler.setRecordingProfile'>Profiler.setRecordingProfile</a></li>\n<li><a href='#Profiler.resetProfiles'>Profiler.resetProfiles</a></li>\n</ul>\n<h3><a href=\"#Runtime\">Runtime</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a>: Unique object identifier.</li>\n<li><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a>: Mirror object referencing original JavaScript object.</li>\n<li><a href='#Runtime.ObjectPreview'>Runtime.ObjectPreview</a>: Object containing abbreviated remote object value.</li>\n<li><a href='#Runtime.PropertyPreview'>Runtime.PropertyPreview</a></li>\n<li><a href='#Runtime.PropertyDescriptor'>Runtime.PropertyDescriptor</a>: Object property descriptor.</li>\n<li><a href='#Runtime.InternalPropertyDescriptor'>Runtime.InternalPropertyDescriptor</a>: Object internal property descriptor. This property isn't normally visible in JavaScript code.</li>\n<li><a href='#Runtime.CallArgument'>Runtime.CallArgument</a>: Represents function call argument. Either remote object id objectId or primitive value or neither of (for undefined) them should be specified.</li>\n<li><a href='#Runtime.ExecutionContextId'>Runtime.ExecutionContextId</a>: Id of an execution context.</li>\n<li><a href='#Runtime.ExecutionContextDescription'>Runtime.ExecutionContextDescription</a>: Description of an isolated world.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Runtime.evaluate'>Runtime.evaluate</a>: Evaluates expression on global object.</li>\n<li><a href='#Runtime.callFunctionOn'>Runtime.callFunctionOn</a>: Calls function with given declaration on the given object. Object group of the result is inherited from the target object.</li>\n<li><a href='#Runtime.getProperties'>Runtime.getProperties</a>: Returns properties of a given object. Object group of the result is inherited from the target object.</li>\n<li><a href='#Runtime.releaseObject'>Runtime.releaseObject</a>: Releases remote object with given id.</li>\n<li><a href='#Runtime.releaseObjectGroup'>Runtime.releaseObjectGroup</a>: Releases all remote objects that belong to a given group.</li>\n<li><a href='#Runtime.run'>Runtime.run</a>: Tells inspected instance(worker or page) that it can run in case it was started paused.</li>\n<li><a href='#Runtime.enable'>Runtime.enable</a>: Enables reporting of execution contexts creation by means of executionContextCreated event. When the reporting gets enabled the event will be sent immediately for each existing execution context.</li>\n<li><a href='#Runtime.disable'>Runtime.disable</a>: Disables reporting of execution contexts creation.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Runtime.executionContextCreated'>Runtime.executionContextCreated</a>: Issued when new execution context is created.</li>\n</ul>\n<h3><a href=\"#Timeline\">Timeline</a></h3>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Timeline.DOMCounters'>Timeline.DOMCounters</a>: Current values of DOM counters.</li>\n<li><a href='#Timeline.TimelineEvent'>Timeline.TimelineEvent</a>: Timeline record contains information about the recorded activity.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Timeline.enable'>Timeline.enable</a>: Enables timeline. After this call, timeline can be started from within the page (for example upon console.timeline).</li>\n<li><a href='#Timeline.disable'>Timeline.disable</a>: Disables timeline.</li>\n<li><a href='#Timeline.start'>Timeline.start</a>: Starts capturing instrumentation events.</li>\n<li><a href='#Timeline.stop'>Timeline.stop</a>: Stops capturing instrumentation events.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Timeline.eventRecorded'>Timeline.eventRecorded</a>: Fired for every instrumentation event while timeline is started.</li>\n<li><a href='#Timeline.started'>Timeline.started</a>: Fired when timeline is started.</li>\n<li><a href='#Timeline.stopped'>Timeline.stopped</a>: Fired when timeline is stopped.</li>\n</ul>\n<h3><a href=\"#Tracing\">Tracing</a></h3>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Tracing.start'>Tracing.start</a>: Strart trace events collection.</li>\n<li><a href='#Tracing.end'>Tracing.end</a>: Stop trace events collection.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Tracing.dataCollected'>Tracing.dataCollected</a></li>\n<li><a href='#Tracing.tracingComplete'>Tracing.tracingComplete</a></li>\n</ul>\n<h3><a href=\"#Worker\">Worker</a></h3>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Worker.enable'>Worker.enable</a></li>\n<li><a href='#Worker.disable'>Worker.disable</a></li>\n<li><a href='#Worker.sendMessageToWorker'>Worker.sendMessageToWorker</a></li>\n<li><a href='#Worker.canInspectWorkers'>Worker.canInspectWorkers</a>: Tells whether browser supports workers inspection.</li>\n<li><a href='#Worker.connectToWorker'>Worker.connectToWorker</a></li>\n<li><a href='#Worker.disconnectFromWorker'>Worker.disconnectFromWorker</a></li>\n<li><a href='#Worker.setAutoconnectToWorkers'>Worker.setAutoconnectToWorkers</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Worker.workerCreated'>Worker.workerCreated</a></li>\n<li><a href='#Worker.workerTerminated'>Worker.workerTerminated</a></li>\n<li><a href='#Worker.dispatchMessageFromWorker'>Worker.dispatchMessageFromWorker</a></li>\n<li><a href='#Worker.disconnectedFromWorker'>Worker.disconnectedFromWorker</a></li>\n</ul>\n</section>\n<section id='ApplicationCache' class='domain'>\n<h1>ApplicationCache</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#ApplicationCache.ApplicationCacheResource'>ApplicationCache.ApplicationCacheResource</a>: Detailed application cache resource information.</li>\n<li><a href='#ApplicationCache.ApplicationCache'>ApplicationCache.ApplicationCache</a>: Detailed application cache information.</li>\n<li><a href='#ApplicationCache.FrameWithManifest'>ApplicationCache.FrameWithManifest</a>: Frame identifier - manifest URL pair.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#ApplicationCache.getFramesWithManifests'>ApplicationCache.getFramesWithManifests</a>: Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache.</li>\n<li><a href='#ApplicationCache.enable'>ApplicationCache.enable</a>: Enables application cache domain notifications.</li>\n<li><a href='#ApplicationCache.getManifestForFrame'>ApplicationCache.getManifestForFrame</a>: Returns manifest URL for document in the given frame.</li>\n<li><a href='#ApplicationCache.getApplicationCacheForFrame'>ApplicationCache.getApplicationCacheForFrame</a>: Returns relevant application cache data for the document in given frame.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#ApplicationCache.applicationCacheStatusUpdated'>ApplicationCache.applicationCacheStatusUpdated</a></li>\n<li><a href='#ApplicationCache.networkStateUpdated'>ApplicationCache.networkStateUpdated</a></li>\n</ul>\n<div id='ApplicationCache_ApplicationCacheResource' class='type'>\n<h3>ApplicationCache.ApplicationCacheResource <span class='label'>Type</span></h3>\n<p>Detailed application cache resource information.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Resource url.</span></dd>\n<dt>size</dt>\n<dd>Integer <span class='text'>Resource size.</span></dd>\n<dt>type</dt>\n<dd>String <span class='text'>Resource type.</span></dd>\n</dl>\n</div>\n<div id='ApplicationCache_ApplicationCache' class='type'>\n<h3>ApplicationCache.ApplicationCache <span class='label'>Type</span></h3>\n<p>Detailed application cache information.</p>\n<dl>\n<dt>manifestURL</dt>\n<dd>String <span class='text'>Manifest URL.</span></dd>\n<dt>size</dt>\n<dd>Number <span class='text'>Application cache size.</span></dd>\n<dt>creationTime</dt>\n<dd>Number <span class='text'>Application cache creation time.</span></dd>\n<dt>updateTime</dt>\n<dd>Number <span class='text'>Application cache update time.</span></dd>\n<dt>resources</dt>\n<dd>[<a href='#ApplicationCache.ApplicationCacheResource'>ApplicationCache.ApplicationCacheResource</a>] <span class='text'>Application cache resources.</span></dd>\n</dl>\n</div>\n<div id='ApplicationCache_FrameWithManifest' class='type'>\n<h3>ApplicationCache.FrameWithManifest <span class='label'>Type</span></h3>\n<p>Frame identifier - manifest URL pair.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame identifier.</span></dd>\n<dt>manifestURL</dt>\n<dd>String <span class='text'>Manifest URL.</span></dd>\n<dt>status</dt>\n<dd>Integer <span class='text'>Application cache status.</span></dd>\n</dl>\n</div>\n<div id='ApplicationCache_getFramesWithManifests' class='command'>\n<h3>ApplicationCache.getFramesWithManifests <span class='label label-success'>Command</span></h3>\n<p>Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>frameIds</dt>\n<dd>[<a href='#ApplicationCache.FrameWithManifest'>ApplicationCache.FrameWithManifest</a>] <span class='text'>Array of frame identifiers with manifest urls for each frame containing a document associated with some application cache.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: ApplicationCache.getFramesWithManifests\nApplicationCache.getFramesWithManifests(function callback(res) {\n\t// res = {frameIds}\n});\n</pre>\n</div>\n<div id='ApplicationCache_enable' class='command'>\n<h3>ApplicationCache.enable <span class='label label-success'>Command</span></h3>\n<p>Enables application cache domain notifications.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: ApplicationCache.enable\nApplicationCache.enable();\n</pre>\n</div>\n<div id='ApplicationCache_getManifestForFrame' class='command'>\n<h3>ApplicationCache.getManifestForFrame <span class='label label-success'>Command</span></h3>\n<p>Returns manifest URL for document in the given frame.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame containing document whose manifest is retrieved.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>manifestURL</dt>\n<dd>String <span class='text'>Manifest URL for document in the given frame.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: ApplicationCache.getManifestForFrame\nApplicationCache.getManifestForFrame(frameId, function callback(res) {\n\t// res = {manifestURL}\n});\n</pre>\n</div>\n<div id='ApplicationCache_getApplicationCacheForFrame' class='command'>\n<h3>ApplicationCache.getApplicationCacheForFrame <span class='label label-success'>Command</span></h3>\n<p>Returns relevant application cache data for the document in given frame.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame containing document whose application cache is retrieved.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>applicationCache</dt>\n<dd><a href='#ApplicationCache.ApplicationCache'>ApplicationCache.ApplicationCache</a> <span class='text'>Relevant application cache data for the document in given frame.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: ApplicationCache.getApplicationCacheForFrame\nApplicationCache.getApplicationCacheForFrame(frameId, function callback(res) {\n\t// res = {applicationCache}\n});\n</pre>\n</div>\n<div id='ApplicationCache_applicationCacheStatusUpdated' class='command'>\n<h3>ApplicationCache.applicationCacheStatusUpdated <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame containing document whose application cache updated status.</span></dd>\n<dt>manifestURL</dt>\n<dd>String <span class='text'>Manifest URL.</span></dd>\n<dt>status</dt>\n<dd>Integer <span class='text'>Updated application cache status.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: ApplicationCache.applicationCacheStatusUpdated\nfunction onApplicationCacheStatusUpdated(res) {\n\t// res = {frameId, manifestURL, status}\n}\n</pre>\n</div>\n<div id='ApplicationCache_networkStateUpdated' class='command'>\n<h3>ApplicationCache.networkStateUpdated <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>isNowOnline</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: ApplicationCache.networkStateUpdated\nfunction onNetworkStateUpdated(res) {\n\t// res = {isNowOnline}\n}\n</pre>\n</div>\n</section>\n<section id='CSS' class='domain'>\n<h1>CSS</h1>\n<p>This domain exposes CSS read/write operations. All CSS objects (stylesheets, rules, and styles) have an associated <code>id</code> used in subsequent operations on the related object. Each object type has a specific <code>id</code> structure, and those are not interchangeable between objects of different kinds. CSS objects can be loaded using the <code>get*ForNode()</code> calls (which accept a DOM node id). A client can also discover all the existing stylesheets with the <code>getAllStyleSheets()</code> method (or keeping track of the <code>styleSheetAdded</code>/<code>styleSheetRemoved</code> events) and subsequently load the required stylesheet contents using the <code>getStyleSheet[Text]()</code> methods.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a></li>\n<li><a href='#CSS.CSSStyleId'>CSS.CSSStyleId</a>: This object identifies a CSS style in a unique way.</li>\n<li><a href='#CSS.StyleSheetOrigin'>CSS.StyleSheetOrigin</a>: Stylesheet type: \"user\" for user stylesheets, \"user-agent\" for user-agent stylesheets, \"inspector\" for stylesheets created by the inspector (i.e. those holding the \"via inspector\" rules), \"regular\" for regular stylesheets.</li>\n<li><a href='#CSS.CSSRuleId'>CSS.CSSRuleId</a>: This object identifies a CSS rule in a unique way.</li>\n<li><a href='#CSS.PseudoIdMatches'>CSS.PseudoIdMatches</a>: CSS rule collection for a single pseudo style.</li>\n<li><a href='#CSS.InheritedStyleEntry'>CSS.InheritedStyleEntry</a>: CSS rule collection for a single pseudo style.</li>\n<li><a href='#CSS.RuleMatch'>CSS.RuleMatch</a>: Match data for a CSS rule.</li>\n<li><a href='#CSS.SelectorList'>CSS.SelectorList</a>: Selector list data.</li>\n<li><a href='#CSS.CSSStyleAttribute'>CSS.CSSStyleAttribute</a>: CSS style information for a DOM style attribute.</li>\n<li><a href='#CSS.CSSStyleSheetHeader'>CSS.CSSStyleSheetHeader</a>: CSS stylesheet metainformation.</li>\n<li><a href='#CSS.CSSStyleSheetBody'>CSS.CSSStyleSheetBody</a>: CSS stylesheet contents.</li>\n<li><a href='#CSS.CSSRule'>CSS.CSSRule</a>: CSS rule representation.</li>\n<li><a href='#CSS.SourceRange'>CSS.SourceRange</a>: Text range within a resource. All numbers are zero-based.</li>\n<li><a href='#CSS.ShorthandEntry'>CSS.ShorthandEntry</a></li>\n<li><a href='#CSS.CSSPropertyInfo'>CSS.CSSPropertyInfo</a></li>\n<li><a href='#CSS.CSSComputedStyleProperty'>CSS.CSSComputedStyleProperty</a></li>\n<li><a href='#CSS.CSSStyle'>CSS.CSSStyle</a>: CSS style representation.</li>\n<li><a href='#CSS.CSSProperty'>CSS.CSSProperty</a>: CSS property declaration data.</li>\n<li><a href='#CSS.CSSMedia'>CSS.CSSMedia</a>: CSS media query descriptor.</li>\n<li><a href='#CSS.SelectorProfileEntry'>CSS.SelectorProfileEntry</a>: CSS selector profile entry.</li>\n<li><a href='#CSS.SelectorProfile'>CSS.SelectorProfile</a></li>\n<li><a href='#CSS.Region'>CSS.Region</a>: This object represents a region that flows from a Named Flow.</li>\n<li><a href='#CSS.NamedFlow'>CSS.NamedFlow</a>: This object represents a Named Flow.</li>\n<li><a href='#CSS.PlatformFontUsage'>CSS.PlatformFontUsage</a>: Information about amount of glyphs that were rendered with given font.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#CSS.enable'>CSS.enable</a>: Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been enabled until the result of this command is received.</li>\n<li><a href='#CSS.disable'>CSS.disable</a>: Disables the CSS agent for the given page.</li>\n<li><a href='#CSS.getMatchedStylesForNode'>CSS.getMatchedStylesForNode</a>: Returns requested styles for a DOM node identified by nodeId.</li>\n<li><a href='#CSS.getInlineStylesForNode'>CSS.getInlineStylesForNode</a>: Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM attributes) for a DOM node identified by nodeId.</li>\n<li><a href='#CSS.getComputedStyleForNode'>CSS.getComputedStyleForNode</a>: Returns the computed style for a DOM node identified by nodeId.</li>\n<li><a href='#CSS.getPlatformFontsForNode'>CSS.getPlatformFontsForNode</a>: Requests information about platform fonts which we used to render child TextNodes in the given node.</li>\n<li><a href='#CSS.getAllStyleSheets'>CSS.getAllStyleSheets</a>: Returns metainfo entries for all known stylesheets.</li>\n<li><a href='#CSS.getStyleSheet'>CSS.getStyleSheet</a>: Returns stylesheet data for the specified styleSheetId.</li>\n<li><a href='#CSS.getStyleSheetText'>CSS.getStyleSheetText</a>: Returns the current textual content and the URL for a stylesheet.</li>\n<li><a href='#CSS.setStyleSheetText'>CSS.setStyleSheetText</a>: Sets the new stylesheet text, thereby invalidating all existing CSSStyleId's and CSSRuleId's contained by this stylesheet.</li>\n<li><a href='#CSS.setStyleText'>CSS.setStyleText</a>: Updates the CSSStyleDeclaration text.</li>\n<li><a href='#CSS.setPropertyText'>CSS.setPropertyText</a>: Sets the new text for a property in the respective style, at offset propertyIndex. If overwrite is true, a property at the given offset is overwritten, otherwise inserted. text entirely replaces the property name: value.</li>\n<li><a href='#CSS.toggleProperty'>CSS.toggleProperty</a>: Toggles the property in the respective style, at offset propertyIndex. The disable parameter denotes whether the property should be disabled (i.e. removed from the style declaration). If disable == false, the property gets put back into its original place in the style declaration.</li>\n<li><a href='#CSS.setRuleSelector'>CSS.setRuleSelector</a>: Modifies the rule selector.</li>\n<li><a href='#CSS.addRule'>CSS.addRule</a>: Creates a new empty rule with the given selector in a special \"inspector\" stylesheet in the owner document of the context node.</li>\n<li><a href='#CSS.getSupportedCSSProperties'>CSS.getSupportedCSSProperties</a>: Returns all supported CSS property names.</li>\n<li><a href='#CSS.forcePseudoState'>CSS.forcePseudoState</a>: Ensures that the given node will have specified pseudo-classes whenever its style is computed by the browser.</li>\n<li><a href='#CSS.getNamedFlowCollection'>CSS.getNamedFlowCollection</a>: Returns the Named Flows from the document.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#CSS.mediaQueryResultChanged'>CSS.mediaQueryResultChanged</a>: Fires whenever a MediaQuery result changes (for example, after a browser window has been resized.) The current implementation considers only viewport-dependent media features.</li>\n<li><a href='#CSS.styleSheetChanged'>CSS.styleSheetChanged</a>: Fired whenever a stylesheet is changed as a result of the client operation.</li>\n<li><a href='#CSS.styleSheetAdded'>CSS.styleSheetAdded</a>: Fired whenever an active document stylesheet is added.</li>\n<li><a href='#CSS.styleSheetRemoved'>CSS.styleSheetRemoved</a>: Fired whenever an active document stylesheet is removed.</li>\n<li><a href='#CSS.namedFlowCreated'>CSS.namedFlowCreated</a>: Fires when a Named Flow is created.</li>\n<li><a href='#CSS.namedFlowRemoved'>CSS.namedFlowRemoved</a>: Fires when a Named Flow is removed: has no associated content nodes and regions.</li>\n<li><a href='#CSS.regionLayoutUpdated'>CSS.regionLayoutUpdated</a>: Fires when a Named Flow's layout may have changed.</li>\n<li><a href='#CSS.regionOversetChanged'>CSS.regionOversetChanged</a>: Fires if any of the regionOverset values changed in a Named Flow's region chain.</li>\n</ul>\n<div id='CSS_StyleSheetId' class='type'>\n<h3>CSS.StyleSheetId <span class='label'>Type</span></h3>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='CSS_CSSStyleId' class='type'>\n<h3>CSS.CSSStyleId <span class='label'>Type</span></h3>\n<p>This object identifies a CSS style in a unique way.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a> <span class='text'>Enclosing stylesheet identifier.</span></dd>\n<dt>ordinal</dt>\n<dd>Integer <span class='text'>The style ordinal within the stylesheet.</span></dd>\n</dl>\n</div>\n<div id='CSS_StyleSheetOrigin' class='type'>\n<h3>CSS.StyleSheetOrigin <span class='label'>Type</span></h3>\n<p>Stylesheet type: \"user\" for user stylesheets, \"user-agent\" for user-agent stylesheets, \"inspector\" for stylesheets created by the inspector (i.e. those holding the \"via inspector\" rules), \"regular\" for regular stylesheets.</p>\n<dl>\n<dd>( user | user-agent | inspector | regular )</dd>\n</dl>\n</div>\n<div id='CSS_CSSRuleId' class='type'>\n<h3>CSS.CSSRuleId <span class='label'>Type</span></h3>\n<p>This object identifies a CSS rule in a unique way.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a> <span class='text'>Enclosing stylesheet identifier.</span></dd>\n<dt>ordinal</dt>\n<dd>Integer <span class='text'>The rule ordinal within the stylesheet.</span></dd>\n</dl>\n</div>\n<div id='CSS_PseudoIdMatches' class='type'>\n<h3>CSS.PseudoIdMatches <span class='label'>Type</span></h3>\n<p>CSS rule collection for a single pseudo style.</p>\n<dl>\n<dt>pseudoId</dt>\n<dd>Integer <span class='text'>Pseudo style identifier (see <code>enum PseudoId</code> in <code>RenderStyleConstants.h</code>).</span></dd>\n<dt>matches</dt>\n<dd>[<a href='#CSS.RuleMatch'>CSS.RuleMatch</a>] <span class='text'>Matches of CSS rules applicable to the pseudo style.</span></dd>\n</dl>\n</div>\n<div id='CSS_InheritedStyleEntry' class='type'>\n<h3>CSS.InheritedStyleEntry <span class='label'>Type</span></h3>\n<p>CSS rule collection for a single pseudo style.</p>\n<dl>\n<dt>inlineStyle (optional)</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>The ancestor node's inline style, if any, in the style inheritance chain.</span></dd>\n<dt>matchedCSSRules</dt>\n<dd>[<a href='#CSS.RuleMatch'>CSS.RuleMatch</a>] <span class='text'>Matches of CSS rules matching the ancestor node in the style inheritance chain.</span></dd>\n</dl>\n</div>\n<div id='CSS_RuleMatch' class='type'>\n<h3>CSS.RuleMatch <span class='label'>Type</span></h3>\n<p>Match data for a CSS rule.</p>\n<dl>\n<dt>rule</dt>\n<dd><a href='#CSS.CSSRule'>CSS.CSSRule</a> <span class='text'>CSS rule in the match.</span></dd>\n<dt>matchingSelectors</dt>\n<dd>[Integer] <span class='text'>Matching selector indices in the rule's selectorList selectors (0-based).</span></dd>\n</dl>\n</div>\n<div id='CSS_SelectorList' class='type'>\n<h3>CSS.SelectorList <span class='label'>Type</span></h3>\n<p>Selector list data.</p>\n<dl>\n<dt>selectors</dt>\n<dd>[String] <span class='text'>Selectors in the list.</span></dd>\n<dt>text</dt>\n<dd>String <span class='text'>Rule selector text.</span></dd>\n<dt>range (optional)</dt>\n<dd><a href='#CSS.SourceRange'>CSS.SourceRange</a> <span class='text'>Rule selector range in the underlying resource (if available).</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSStyleAttribute' class='type'>\n<h3>CSS.CSSStyleAttribute <span class='label'>Type</span></h3>\n<p>CSS style information for a DOM style attribute.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>DOM attribute name (e.g. \"width\").</span></dd>\n<dt>style</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>CSS style generated by the respective DOM attribute.</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSStyleSheetHeader' class='type'>\n<h3>CSS.CSSStyleSheetHeader <span class='label'>Type</span></h3>\n<p>CSS stylesheet metainformation.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a> <span class='text'>The stylesheet identifier.</span></dd>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Owner frame identifier.</span></dd>\n<dt>sourceURL</dt>\n<dd>String <span class='text'>Stylesheet resource URL.</span></dd>\n<dt>sourceMapURL (optional)</dt>\n<dd>String <span class='text'>URL of source map associated with the stylesheet (if any).</span></dd>\n<dt>origin</dt>\n<dd><a href='#CSS.StyleSheetOrigin'>CSS.StyleSheetOrigin</a> <span class='text'>Stylesheet origin.</span></dd>\n<dt>title</dt>\n<dd>String <span class='text'>Stylesheet title.</span></dd>\n<dt>disabled</dt>\n<dd>Boolean <span class='text'>Denotes whether the stylesheet is disabled.</span></dd>\n<dt>hasSourceURL (optional)</dt>\n<dd>Boolean <span class='text'>Whether the sourceURL field value comes from the sourceURL comment.</span></dd>\n<dt>isInline</dt>\n<dd>Boolean <span class='text'>Whether this stylesheet is created for STYLE tag by parser. This flag is not set for document.written STYLE tags.</span></dd>\n<dt>startLine</dt>\n<dd>Number <span class='text'>Line offset of the stylesheet within the resource (zero based).</span></dd>\n<dt>startColumn</dt>\n<dd>Number <span class='text'>Column offset of the stylesheet within the resource (zero based).</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSStyleSheetBody' class='type'>\n<h3>CSS.CSSStyleSheetBody <span class='label'>Type</span></h3>\n<p>CSS stylesheet contents.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a> <span class='text'>The stylesheet identifier.</span></dd>\n<dt>rules</dt>\n<dd>[<a href='#CSS.CSSRule'>CSS.CSSRule</a>] <span class='text'>Stylesheet resource URL.</span></dd>\n<dt>text (optional)</dt>\n<dd>String <span class='text'>Stylesheet resource contents (if available).</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSRule' class='type'>\n<h3>CSS.CSSRule <span class='label'>Type</span></h3>\n<p>CSS rule representation.</p>\n<dl>\n<dt>ruleId (optional)</dt>\n<dd><a href='#CSS.CSSRuleId'>CSS.CSSRuleId</a> <span class='text'>The CSS rule identifier (absent for user agent stylesheet and user-specified stylesheet rules).</span></dd>\n<dt>selectorList</dt>\n<dd><a href='#CSS.SelectorList'>CSS.SelectorList</a> <span class='text'>Rule selector data.</span></dd>\n<dt>sourceURL (optional)</dt>\n<dd>String <span class='text'>Parent stylesheet resource URL (for regular rules).</span></dd>\n<dt>origin</dt>\n<dd><a href='#CSS.StyleSheetOrigin'>CSS.StyleSheetOrigin</a> <span class='text'>Parent stylesheet's origin.</span></dd>\n<dt>style</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>Associated style declaration.</span></dd>\n<dt>media (optional)</dt>\n<dd>[<a href='#CSS.CSSMedia'>CSS.CSSMedia</a>] <span class='text'>Media list array (for rules involving media queries). The array enumerates media queries starting with the innermost one, going outwards.</span></dd>\n</dl>\n</div>\n<div id='CSS_SourceRange' class='type'>\n<h3>CSS.SourceRange <span class='label'>Type</span></h3>\n<p>Text range within a resource. All numbers are zero-based.</p>\n<dl>\n<dt>startLine</dt>\n<dd>Integer <span class='text'>Start line of range.</span></dd>\n<dt>startColumn</dt>\n<dd>Integer <span class='text'>Start column of range (inclusive).</span></dd>\n<dt>endLine</dt>\n<dd>Integer <span class='text'>End line of range</span></dd>\n<dt>endColumn</dt>\n<dd>Integer <span class='text'>End column of range (exclusive).</span></dd>\n</dl>\n</div>\n<div id='CSS_ShorthandEntry' class='type'>\n<h3>CSS.ShorthandEntry <span class='label'>Type</span></h3>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Shorthand name.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>Shorthand value.</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSPropertyInfo' class='type'>\n<h3>CSS.CSSPropertyInfo <span class='label'>Type</span></h3>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Property name.</span></dd>\n<dt>longhands (optional)</dt>\n<dd>[String] <span class='text'>Longhand property names.</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSComputedStyleProperty' class='type'>\n<h3>CSS.CSSComputedStyleProperty <span class='label'>Type</span></h3>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Computed style property name.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>Computed style property value.</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSStyle' class='type'>\n<h3>CSS.CSSStyle <span class='label'>Type</span></h3>\n<p>CSS style representation.</p>\n<dl>\n<dt>styleId (optional)</dt>\n<dd><a href='#CSS.CSSStyleId'>CSS.CSSStyleId</a> <span class='text'>The CSS style identifier (absent for attribute styles).</span></dd>\n<dt>cssProperties</dt>\n<dd>[<a href='#CSS.CSSProperty'>CSS.CSSProperty</a>] <span class='text'>CSS properties in the style.</span></dd>\n<dt>shorthandEntries</dt>\n<dd>[<a href='#CSS.ShorthandEntry'>CSS.ShorthandEntry</a>] <span class='text'>Computed values for all shorthands found in the style.</span></dd>\n<dt>cssText (optional)</dt>\n<dd>String <span class='text'>Style declaration text (if available).</span></dd>\n<dt>range (optional)</dt>\n<dd><a href='#CSS.SourceRange'>CSS.SourceRange</a> <span class='text'>Style declaration range in the enclosing stylesheet (if available).</span></dd>\n<dt>width (optional)</dt>\n<dd>String <span class='text'>The effective \"width\" property value from this style.</span></dd>\n<dt>height (optional)</dt>\n<dd>String <span class='text'>The effective \"height\" property value from this style.</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSProperty' class='type'>\n<h3>CSS.CSSProperty <span class='label'>Type</span></h3>\n<p>CSS property declaration data.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>The property name.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>The property value.</span></dd>\n<dt>priority (optional)</dt>\n<dd>String <span class='text'>The property priority (implies \"\" if absent).</span></dd>\n<dt>implicit (optional)</dt>\n<dd>Boolean <span class='text'>Whether the property is implicit (implies <code>false</code> if absent).</span></dd>\n<dt>text (optional)</dt>\n<dd>String <span class='text'>The full property text as specified in the style.</span></dd>\n<dt>parsedOk (optional)</dt>\n<dd>Boolean <span class='text'>Whether the property is understood by the browser (implies <code>true</code> if absent).</span></dd>\n<dt>status (optional)</dt>\n<dd>( active | inactive | disabled | style ) <span class='text'>The property status: \"active\" if the property is effective in the style, \"inactive\" if the property is overridden by a same-named property in this style later on, \"disabled\" if the property is disabled by the user, \"style\" (implied if absent) if the property is reported by the browser rather than by the CSS source parser.</span></dd>\n<dt>range (optional)</dt>\n<dd><a href='#CSS.SourceRange'>CSS.SourceRange</a> <span class='text'>The entire property range in the enclosing style declaration (if available).</span></dd>\n</dl>\n</div>\n<div id='CSS_CSSMedia' class='type'>\n<h3>CSS.CSSMedia <span class='label'>Type</span></h3>\n<p>CSS media query descriptor.</p>\n<dl>\n<dt>text</dt>\n<dd>String <span class='text'>Media query text.</span></dd>\n<dt>source</dt>\n<dd>( mediaRule | importRule | linkedSheet | inlineSheet ) <span class='text'>Source of the media query: \"mediaRule\" if specified by a @media rule, \"importRule\" if specified by an @import rule, \"linkedSheet\" if specified by a \"media\" attribute in a linked stylesheet's LINK tag, \"inlineSheet\" if specified by a \"media\" attribute in an inline stylesheet's STYLE tag.</span></dd>\n<dt>sourceURL (optional)</dt>\n<dd>String <span class='text'>URL of the document containing the media query description.</span></dd>\n<dt>range (optional)</dt>\n<dd><a href='#CSS.SourceRange'>CSS.SourceRange</a> <span class='text'>The associated rule (@media or @import) header range in the enclosing stylesheet (if available).</span></dd>\n<dt>parentStyleSheetId (optional)</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a> <span class='text'>Identifier of the stylesheet containing this object (if exists).</span></dd>\n</dl>\n</div>\n<div id='CSS_SelectorProfileEntry' class='type'>\n<h3>CSS.SelectorProfileEntry <span class='label'>Type</span></h3>\n<p>CSS selector profile entry.</p>\n<dl>\n<dt>selector</dt>\n<dd>String <span class='text'>CSS selector of the corresponding rule.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the resource containing the corresponding rule.</span></dd>\n<dt>lineNumber</dt>\n<dd>Integer <span class='text'>Selector line number in the resource for the corresponding rule.</span></dd>\n<dt>time</dt>\n<dd>Number <span class='text'>Total time this rule handling contributed to the browser running time during profiling (in milliseconds).</span></dd>\n<dt>hitCount</dt>\n<dd>Integer <span class='text'>Number of times this rule was considered a candidate for matching against DOM elements.</span></dd>\n<dt>matchCount</dt>\n<dd>Integer <span class='text'>Number of times this rule actually matched a DOM element.</span></dd>\n</dl>\n</div>\n<div id='CSS_SelectorProfile' class='type'>\n<h3>CSS.SelectorProfile <span class='label'>Type</span></h3>\n<dl>\n<dt>totalTime</dt>\n<dd>Number <span class='text'>Total processing time for all selectors in the profile (in milliseconds).</span></dd>\n<dt>data</dt>\n<dd>[<a href='#CSS.SelectorProfileEntry'>CSS.SelectorProfileEntry</a>] <span class='text'>CSS selector profile entries.</span></dd>\n</dl>\n</div>\n<div id='CSS_Region' class='type'>\n<h3>CSS.Region <span class='label'>Type</span></h3>\n<p>This object represents a region that flows from a Named Flow.</p>\n<dl>\n<dt>regionOverset</dt>\n<dd>( overset | fit | empty ) <span class='text'>The \"overset\" attribute of a Named Flow.</span></dd>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The corresponding DOM node id.</span></dd>\n</dl>\n</div>\n<div id='CSS_NamedFlow' class='type'>\n<h3>CSS.NamedFlow <span class='label'>Type</span></h3>\n<p>This object represents a Named Flow.</p>\n<dl>\n<dt>documentNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The document node id.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Named Flow identifier.</span></dd>\n<dt>overset</dt>\n<dd>Boolean <span class='text'>The \"overset\" attribute of a Named Flow.</span></dd>\n<dt>content</dt>\n<dd>[<a href='#DOM.NodeId'>DOM.NodeId</a>] <span class='text'>An array of nodes that flow into the Named Flow.</span></dd>\n<dt>regions</dt>\n<dd>[<a href='#CSS.Region'>CSS.Region</a>] <span class='text'>An array of regions associated with the Named Flow.</span></dd>\n</dl>\n</div>\n<div id='CSS_PlatformFontUsage' class='type'>\n<h3>CSS.PlatformFontUsage <span class='label'>Type</span></h3>\n<p>Information about amount of glyphs that were rendered with given font.</p>\n<dl>\n<dt>familyName</dt>\n<dd>String <span class='text'>Font's family name reported by platform.</span></dd>\n<dt>glyphCount</dt>\n<dd>Number <span class='text'>Amount of glyphs that were rendered with this font.</span></dd>\n</dl>\n</div>\n<div id='CSS_enable' class='command'>\n<h3>CSS.enable <span class='label label-success'>Command</span></h3>\n<p>Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been enabled until the result of this command is received.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.enable\nCSS.enable();\n</pre>\n</div>\n<div id='CSS_disable' class='command'>\n<h3>CSS.disable <span class='label label-success'>Command</span></h3>\n<p>Disables the CSS agent for the given page.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.disable\nCSS.disable();\n</pre>\n</div>\n<div id='CSS_getMatchedStylesForNode' class='command'>\n<h3>CSS.getMatchedStylesForNode <span class='label label-success'>Command</span></h3>\n<p>Returns requested styles for a DOM node identified by <code>nodeId</code>.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a></dd>\n<dt>includePseudo (optional)</dt>\n<dd>Boolean <span class='text'>Whether to include pseudo styles (default: true).</span></dd>\n<dt>includeInherited (optional)</dt>\n<dd>Boolean <span class='text'>Whether to include inherited styles (default: true).</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>matchedCSSRules (optional)</dt>\n<dd>[<a href='#CSS.RuleMatch'>CSS.RuleMatch</a>] <span class='text'>CSS rules matching this node, from all applicable stylesheets.</span></dd>\n<dt>pseudoElements (optional)</dt>\n<dd>[<a href='#CSS.PseudoIdMatches'>CSS.PseudoIdMatches</a>] <span class='text'>Pseudo style matches for this node.</span></dd>\n<dt>inherited (optional)</dt>\n<dd>[<a href='#CSS.InheritedStyleEntry'>CSS.InheritedStyleEntry</a>] <span class='text'>A chain of inherited styles (from the immediate node parent up to the DOM tree root).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getMatchedStylesForNode\nCSS.getMatchedStylesForNode(nodeId, includePseudo, includeInherited, function callback(res) {\n\t// res = {matchedCSSRules, pseudoElements, inherited}\n});\n</pre>\n</div>\n<div id='CSS_getInlineStylesForNode' class='command'>\n<h3>CSS.getInlineStylesForNode <span class='label label-success'>Command</span></h3>\n<p>Returns the styles defined inline (explicitly in the \"style\" attribute and implicitly, using DOM attributes) for a DOM node identified by <code>nodeId</code>.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>inlineStyle (optional)</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>Inline style for the specified DOM node.</span></dd>\n<dt>attributesStyle (optional)</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>Attribute-defined element style (e.g. resulting from \"width=20 height=100%\").</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getInlineStylesForNode\nCSS.getInlineStylesForNode(nodeId, function callback(res) {\n\t// res = {inlineStyle, attributesStyle}\n});\n</pre>\n</div>\n<div id='CSS_getComputedStyleForNode' class='command'>\n<h3>CSS.getComputedStyleForNode <span class='label label-success'>Command</span></h3>\n<p>Returns the computed style for a DOM node identified by <code>nodeId</code>.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>computedStyle</dt>\n<dd>[<a href='#CSS.CSSComputedStyleProperty'>CSS.CSSComputedStyleProperty</a>] <span class='text'>Computed style for the specified DOM node.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getComputedStyleForNode\nCSS.getComputedStyleForNode(nodeId, function callback(res) {\n\t// res = {computedStyle}\n});\n</pre>\n</div>\n<div id='CSS_getPlatformFontsForNode' class='command'>\n<h3>CSS.getPlatformFontsForNode <span class='label label-success'>Command</span></h3>\n<p>Requests information about platform fonts which we used to render child TextNodes in the given node.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>cssFamilyName</dt>\n<dd>String <span class='text'>Font family name which is determined by computed style.</span></dd>\n<dt>fonts</dt>\n<dd>[<a href='#CSS.PlatformFontUsage'>CSS.PlatformFontUsage</a>] <span class='text'>Usage statistics for every employed platform font.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getPlatformFontsForNode\nCSS.getPlatformFontsForNode(nodeId, function callback(res) {\n\t// res = {cssFamilyName, fonts}\n});\n</pre>\n</div>\n<div id='CSS_getAllStyleSheets' class='command'>\n<h3>CSS.getAllStyleSheets <span class='label label-success'>Command</span></h3>\n<p>Returns metainfo entries for all known stylesheets.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>headers</dt>\n<dd>[<a href='#CSS.CSSStyleSheetHeader'>CSS.CSSStyleSheetHeader</a>] <span class='text'>Descriptor entries for all available stylesheets.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getAllStyleSheets\nCSS.getAllStyleSheets(function callback(res) {\n\t// res = {headers}\n});\n</pre>\n</div>\n<div id='CSS_getStyleSheet' class='command'>\n<h3>CSS.getStyleSheet <span class='label label-success'>Command</span></h3>\n<p>Returns stylesheet data for the specified <code>styleSheetId</code>.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>styleSheet</dt>\n<dd><a href='#CSS.CSSStyleSheetBody'>CSS.CSSStyleSheetBody</a> <span class='text'>Stylesheet contents for the specified <code>styleSheetId</code>.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getStyleSheet\nCSS.getStyleSheet(styleSheetId, function callback(res) {\n\t// res = {styleSheet}\n});\n</pre>\n</div>\n<div id='CSS_getStyleSheetText' class='command'>\n<h3>CSS.getStyleSheetText <span class='label label-success'>Command</span></h3>\n<p>Returns the current textual content and the URL for a stylesheet.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>text</dt>\n<dd>String <span class='text'>The stylesheet text.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getStyleSheetText\nCSS.getStyleSheetText(styleSheetId, function callback(res) {\n\t// res = {text}\n});\n</pre>\n</div>\n<div id='CSS_setStyleSheetText' class='command'>\n<h3>CSS.setStyleSheetText <span class='label label-success'>Command</span></h3>\n<p>Sets the new stylesheet text, thereby invalidating all existing <code>CSSStyleId</code>'s and <code>CSSRuleId</code>'s contained by this stylesheet.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a></dd>\n<dt>text</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.setStyleSheetText\nCSS.setStyleSheetText(styleSheetId, text);\n</pre>\n</div>\n<div id='CSS_setStyleText' class='command'>\n<h3>CSS.setStyleText <span class='label label-success'>Command</span></h3>\n<p>Updates the CSSStyleDeclaration text.</p>\n<dl>\n<dt>styleId</dt>\n<dd><a href='#CSS.CSSStyleId'>CSS.CSSStyleId</a></dd>\n<dt>text</dt>\n<dd>String</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>style</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>The resulting style after the text modification.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.setStyleText\nCSS.setStyleText(styleId, text, function callback(res) {\n\t// res = {style}\n});\n</pre>\n</div>\n<div id='CSS_setPropertyText' class='command'>\n<h3>CSS.setPropertyText <span class='label label-success'>Command</span></h3>\n<p>Sets the new <code>text</code> for a property in the respective style, at offset <code>propertyIndex</code>. If <code>overwrite</code> is <code>true</code>, a property at the given offset is overwritten, otherwise inserted. <code>text</code> entirely replaces the property <code>name: value</code>.</p>\n<dl>\n<dt>styleId</dt>\n<dd><a href='#CSS.CSSStyleId'>CSS.CSSStyleId</a></dd>\n<dt>propertyIndex</dt>\n<dd>Integer</dd>\n<dt>text</dt>\n<dd>String</dd>\n<dt>overwrite</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>style</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>The resulting style after the property text modification.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.setPropertyText\nCSS.setPropertyText(styleId, propertyIndex, text, overwrite, function callback(res) {\n\t// res = {style}\n});\n</pre>\n</div>\n<div id='CSS_toggleProperty' class='command'>\n<h3>CSS.toggleProperty <span class='label label-success'>Command</span></h3>\n<p>Toggles the property in the respective style, at offset <code>propertyIndex</code>. The <code>disable</code> parameter denotes whether the property should be disabled (i.e. removed from the style declaration). If <code>disable == false</code>, the property gets put back into its original place in the style declaration.</p>\n<dl>\n<dt>styleId</dt>\n<dd><a href='#CSS.CSSStyleId'>CSS.CSSStyleId</a></dd>\n<dt>propertyIndex</dt>\n<dd>Integer</dd>\n<dt>disable</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>style</dt>\n<dd><a href='#CSS.CSSStyle'>CSS.CSSStyle</a> <span class='text'>The resulting style after the property toggling.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.toggleProperty\nCSS.toggleProperty(styleId, propertyIndex, disable, function callback(res) {\n\t// res = {style}\n});\n</pre>\n</div>\n<div id='CSS_setRuleSelector' class='command'>\n<h3>CSS.setRuleSelector <span class='label label-success'>Command</span></h3>\n<p>Modifies the rule selector.</p>\n<dl>\n<dt>ruleId</dt>\n<dd><a href='#CSS.CSSRuleId'>CSS.CSSRuleId</a></dd>\n<dt>selector</dt>\n<dd>String</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>rule</dt>\n<dd><a href='#CSS.CSSRule'>CSS.CSSRule</a> <span class='text'>The resulting rule after the selector modification.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.setRuleSelector\nCSS.setRuleSelector(ruleId, selector, function callback(res) {\n\t// res = {rule}\n});\n</pre>\n</div>\n<div id='CSS_addRule' class='command'>\n<h3>CSS.addRule <span class='label label-success'>Command</span></h3>\n<p>Creates a new empty rule with the given <code>selector</code> in a special \"inspector\" stylesheet in the owner document of the context node.</p>\n<dl>\n<dt>contextNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a></dd>\n<dt>selector</dt>\n<dd>String</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>rule</dt>\n<dd><a href='#CSS.CSSRule'>CSS.CSSRule</a> <span class='text'>The newly created rule.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.addRule\nCSS.addRule(contextNodeId, selector, function callback(res) {\n\t// res = {rule}\n});\n</pre>\n</div>\n<div id='CSS_getSupportedCSSProperties' class='command'>\n<h3>CSS.getSupportedCSSProperties <span class='label label-success'>Command</span></h3>\n<p>Returns all supported CSS property names.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>cssProperties</dt>\n<dd>[<a href='#CSS.CSSPropertyInfo'>CSS.CSSPropertyInfo</a>] <span class='text'>Supported property metainfo.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getSupportedCSSProperties\nCSS.getSupportedCSSProperties(function callback(res) {\n\t// res = {cssProperties}\n});\n</pre>\n</div>\n<div id='CSS_forcePseudoState' class='command'>\n<h3>CSS.forcePseudoState <span class='label label-success'>Command</span></h3>\n<p>Ensures that the given node will have specified pseudo-classes whenever its style is computed by the browser.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The element id for which to force the pseudo state.</span></dd>\n<dt>forcedPseudoClasses</dt>\n<dd>[( active | focus | hover | visited )] <span class='text'>Element pseudo classes to force when computing the element's style.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.forcePseudoState\nCSS.forcePseudoState(nodeId, forcedPseudoClasses);\n</pre>\n</div>\n<div id='CSS_getNamedFlowCollection' class='command'>\n<h3>CSS.getNamedFlowCollection <span class='label label-success'>Command</span></h3>\n<p>Returns the Named Flows from the document.</p>\n<dl>\n<dt>documentNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The document node id for which to get the Named Flow Collection.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>namedFlows</dt>\n<dd>[<a href='#CSS.NamedFlow'>CSS.NamedFlow</a>] <span class='text'>An array containing the Named Flows in the document.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: CSS.getNamedFlowCollection\nCSS.getNamedFlowCollection(documentNodeId, function callback(res) {\n\t// res = {namedFlows}\n});\n</pre>\n</div>\n<div id='CSS_mediaQueryResultChanged' class='command'>\n<h3>CSS.mediaQueryResultChanged <span class='label label-info'>Event</span></h3>\n<p>Fires whenever a MediaQuery result changes (for example, after a browser window has been resized.) The current implementation considers only viewport-dependent media features.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.mediaQueryResultChanged\nfunction onMediaQueryResultChanged(res) {\n\t// res = {}\n}\n</pre>\n</div>\n<div id='CSS_styleSheetChanged' class='command'>\n<h3>CSS.styleSheetChanged <span class='label label-info'>Event</span></h3>\n<p>Fired whenever a stylesheet is changed as a result of the client operation.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.styleSheetChanged\nfunction onStyleSheetChanged(res) {\n\t// res = {styleSheetId}\n}\n</pre>\n</div>\n<div id='CSS_styleSheetAdded' class='command'>\n<h3>CSS.styleSheetAdded <span class='label label-info'>Event</span></h3>\n<p>Fired whenever an active document stylesheet is added.</p>\n<dl>\n<dt>header</dt>\n<dd><a href='#CSS.CSSStyleSheetHeader'>CSS.CSSStyleSheetHeader</a> <span class='text'>Added stylesheet metainfo.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.styleSheetAdded\nfunction onStyleSheetAdded(res) {\n\t// res = {header}\n}\n</pre>\n</div>\n<div id='CSS_styleSheetRemoved' class='command'>\n<h3>CSS.styleSheetRemoved <span class='label label-info'>Event</span></h3>\n<p>Fired whenever an active document stylesheet is removed.</p>\n<dl>\n<dt>styleSheetId</dt>\n<dd><a href='#CSS.StyleSheetId'>CSS.StyleSheetId</a> <span class='text'>Identifier of the removed stylesheet.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.styleSheetRemoved\nfunction onStyleSheetRemoved(res) {\n\t// res = {styleSheetId}\n}\n</pre>\n</div>\n<div id='CSS_namedFlowCreated' class='command'>\n<h3>CSS.namedFlowCreated <span class='label label-info'>Event</span></h3>\n<p>Fires when a Named Flow is created.</p>\n<dl>\n<dt>namedFlow</dt>\n<dd><a href='#CSS.NamedFlow'>CSS.NamedFlow</a> <span class='text'>The new Named Flow.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.namedFlowCreated\nfunction onNamedFlowCreated(res) {\n\t// res = {namedFlow}\n}\n</pre>\n</div>\n<div id='CSS_namedFlowRemoved' class='command'>\n<h3>CSS.namedFlowRemoved <span class='label label-info'>Event</span></h3>\n<p>Fires when a Named Flow is removed: has no associated content nodes and regions.</p>\n<dl>\n<dt>documentNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The document node id.</span></dd>\n<dt>flowName</dt>\n<dd>String <span class='text'>Identifier of the removed Named Flow.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.namedFlowRemoved\nfunction onNamedFlowRemoved(res) {\n\t// res = {documentNodeId, flowName}\n}\n</pre>\n</div>\n<div id='CSS_regionLayoutUpdated' class='command'>\n<h3>CSS.regionLayoutUpdated <span class='label label-info'>Event</span></h3>\n<p>Fires when a Named Flow's layout may have changed.</p>\n<dl>\n<dt>namedFlow</dt>\n<dd><a href='#CSS.NamedFlow'>CSS.NamedFlow</a> <span class='text'>The Named Flow whose layout may have changed.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.regionLayoutUpdated\nfunction onRegionLayoutUpdated(res) {\n\t// res = {namedFlow}\n}\n</pre>\n</div>\n<div id='CSS_regionOversetChanged' class='command'>\n<h3>CSS.regionOversetChanged <span class='label label-info'>Event</span></h3>\n<p>Fires if any of the regionOverset values changed in a Named Flow's region chain.</p>\n<dl>\n<dt>namedFlow</dt>\n<dd><a href='#CSS.NamedFlow'>CSS.NamedFlow</a> <span class='text'>The Named Flow containing the regions whose regionOverset values changed.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: CSS.regionOversetChanged\nfunction onRegionOversetChanged(res) {\n\t// res = {namedFlow}\n}\n</pre>\n</div>\n</section>\n<section id='Canvas' class='domain'>\n<h1>Canvas</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Canvas.ResourceId'>Canvas.ResourceId</a>: Unique resource identifier.</li>\n<li><a href='#Canvas.ResourceStateDescriptor'>Canvas.ResourceStateDescriptor</a>: Resource state descriptor.</li>\n<li><a href='#Canvas.ResourceState'>Canvas.ResourceState</a>: Resource state.</li>\n<li><a href='#Canvas.CallArgument'>Canvas.CallArgument</a></li>\n<li><a href='#Canvas.Call'>Canvas.Call</a></li>\n<li><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a>: Unique trace log identifier.</li>\n<li><a href='#Canvas.TraceLog'>Canvas.TraceLog</a></li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Canvas.enable'>Canvas.enable</a>: Enables Canvas inspection.</li>\n<li><a href='#Canvas.disable'>Canvas.disable</a>: Disables Canvas inspection.</li>\n<li><a href='#Canvas.dropTraceLog'>Canvas.dropTraceLog</a></li>\n<li><a href='#Canvas.hasUninstrumentedCanvases'>Canvas.hasUninstrumentedCanvases</a>: Checks if there is any uninstrumented canvas in the inspected page.</li>\n<li><a href='#Canvas.captureFrame'>Canvas.captureFrame</a>: Starts (or continues) a canvas frame capturing which will be stopped automatically after the next frame is prepared.</li>\n<li><a href='#Canvas.startCapturing'>Canvas.startCapturing</a>: Starts (or continues) consecutive canvas frames capturing. The capturing is stopped by the corresponding stopCapturing command.</li>\n<li><a href='#Canvas.stopCapturing'>Canvas.stopCapturing</a></li>\n<li><a href='#Canvas.getTraceLog'>Canvas.getTraceLog</a></li>\n<li><a href='#Canvas.replayTraceLog'>Canvas.replayTraceLog</a></li>\n<li><a href='#Canvas.getResourceState'>Canvas.getResourceState</a></li>\n<li><a href='#Canvas.evaluateTraceLogCallArgument'>Canvas.evaluateTraceLogCallArgument</a>: Evaluates a given trace call argument or its result.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Canvas.contextCreated'>Canvas.contextCreated</a>: Fired when a canvas context has been created in the given frame. The context may not be instrumented (see hasUninstrumentedCanvases command).</li>\n<li><a href='#Canvas.traceLogsRemoved'>Canvas.traceLogsRemoved</a>: Fired when a set of trace logs were removed from the backend. If no parameters are given, all trace logs were removed.</li>\n</ul>\n<div id='Canvas_ResourceId' class='type'>\n<h3>Canvas.ResourceId <span class='label'>Type</span></h3>\n<p>Unique resource identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Canvas_ResourceStateDescriptor' class='type'>\n<h3>Canvas.ResourceStateDescriptor <span class='label'>Type</span></h3>\n<p>Resource state descriptor.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>State name.</span></dd>\n<dt>enumValueForName (optional)</dt>\n<dd>String <span class='text'>String representation of the enum value, if <code>name</code> stands for an enum.</span></dd>\n<dt>value (optional)</dt>\n<dd><a href='#Canvas.CallArgument'>Canvas.CallArgument</a> <span class='text'>The value associated with the particular state.</span></dd>\n<dt>values (optional)</dt>\n<dd>[<a href='#Canvas.ResourceStateDescriptor'>Canvas.ResourceStateDescriptor</a>] <span class='text'>Array of values associated with the particular state. Either <code>value</code> or <code>values</code> will be specified.</span></dd>\n<dt>isArray (optional)</dt>\n<dd>Boolean <span class='text'>True iff the given <code>values</code> items stand for an array rather than a list of grouped states.</span></dd>\n</dl>\n</div>\n<div id='Canvas_ResourceState' class='type'>\n<h3>Canvas.ResourceState <span class='label'>Type</span></h3>\n<p>Resource state.</p>\n<dl>\n<dt>id</dt>\n<dd><a href='#Canvas.ResourceId'>Canvas.ResourceId</a></dd>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n<dt>descriptors (optional)</dt>\n<dd>[<a href='#Canvas.ResourceStateDescriptor'>Canvas.ResourceStateDescriptor</a>] <span class='text'>Describes current <code>Resource</code> state.</span></dd>\n<dt>imageURL (optional)</dt>\n<dd>String <span class='text'>Screenshot image data URL.</span></dd>\n</dl>\n</div>\n<div id='Canvas_CallArgument' class='type'>\n<h3>Canvas.CallArgument <span class='label'>Type</span></h3>\n<dl>\n<dt>description</dt>\n<dd>String <span class='text'>String representation of the object.</span></dd>\n<dt>enumName (optional)</dt>\n<dd>String <span class='text'>Enum name, if any, that stands for the value (for example, a WebGL enum name).</span></dd>\n<dt>resourceId (optional)</dt>\n<dd><a href='#Canvas.ResourceId'>Canvas.ResourceId</a> <span class='text'>Resource identifier. Specified for <code>Resource</code> objects only.</span></dd>\n<dt>type (optional)</dt>\n<dd>( object | function | undefined | string | number | boolean ) <span class='text'>Object type. Specified for non <code>Resource</code> objects only.</span></dd>\n<dt>subtype (optional)</dt>\n<dd>( array | null | node | regexp | date ) <span class='text'>Object subtype hint. Specified for <code>object</code> type values only.</span></dd>\n<dt>remoteObject (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>The <code>RemoteObject</code>, if requested.</span></dd>\n</dl>\n</div>\n<div id='Canvas_Call' class='type'>\n<h3>Canvas.Call <span class='label'>Type</span></h3>\n<dl>\n<dt>contextId</dt>\n<dd><a href='#Canvas.ResourceId'>Canvas.ResourceId</a></dd>\n<dt>functionName (optional)</dt>\n<dd>String</dd>\n<dt>arguments (optional)</dt>\n<dd>[<a href='#Canvas.CallArgument'>Canvas.CallArgument</a>]</dd>\n<dt>result (optional)</dt>\n<dd><a href='#Canvas.CallArgument'>Canvas.CallArgument</a></dd>\n<dt>isDrawingCall (optional)</dt>\n<dd>Boolean</dd>\n<dt>isFrameEndCall (optional)</dt>\n<dd>Boolean</dd>\n<dt>property (optional)</dt>\n<dd>String</dd>\n<dt>value (optional)</dt>\n<dd><a href='#Canvas.CallArgument'>Canvas.CallArgument</a></dd>\n<dt>sourceURL (optional)</dt>\n<dd>String</dd>\n<dt>lineNumber (optional)</dt>\n<dd>Integer</dd>\n<dt>columnNumber (optional)</dt>\n<dd>Integer</dd>\n</dl>\n</div>\n<div id='Canvas_TraceLogId' class='type'>\n<h3>Canvas.TraceLogId <span class='label'>Type</span></h3>\n<p>Unique trace log identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Canvas_TraceLog' class='type'>\n<h3>Canvas.TraceLog <span class='label'>Type</span></h3>\n<dl>\n<dt>id</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n<dt>calls</dt>\n<dd>[<a href='#Canvas.Call'>Canvas.Call</a>]</dd>\n<dt>contexts</dt>\n<dd>[<a href='#Canvas.CallArgument'>Canvas.CallArgument</a>]</dd>\n<dt>startOffset</dt>\n<dd>Integer</dd>\n<dt>alive</dt>\n<dd>Boolean</dd>\n<dt>totalAvailableCalls</dt>\n<dd>Number</dd>\n</dl>\n</div>\n<div id='Canvas_enable' class='command'>\n<h3>Canvas.enable <span class='label label-success'>Command</span></h3>\n<p>Enables Canvas inspection.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.enable\nCanvas.enable();\n</pre>\n</div>\n<div id='Canvas_disable' class='command'>\n<h3>Canvas.disable <span class='label label-success'>Command</span></h3>\n<p>Disables Canvas inspection.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.disable\nCanvas.disable();\n</pre>\n</div>\n<div id='Canvas_dropTraceLog' class='command'>\n<h3>Canvas.dropTraceLog <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.dropTraceLog\nCanvas.dropTraceLog(traceLogId);\n</pre>\n</div>\n<div id='Canvas_hasUninstrumentedCanvases' class='command'>\n<h3>Canvas.hasUninstrumentedCanvases <span class='label label-success'>Command</span></h3>\n<p>Checks if there is any uninstrumented canvas in the inspected page.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.hasUninstrumentedCanvases\nCanvas.hasUninstrumentedCanvases(function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Canvas_captureFrame' class='command'>\n<h3>Canvas.captureFrame <span class='label label-success'>Command</span></h3>\n<p>Starts (or continues) a canvas frame capturing which will be stopped automatically after the next frame is prepared.</p>\n<dl>\n<dt>frameId (optional)</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame containing document whose canvases are to be captured. If omitted, main frame is assumed.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a> <span class='text'>Identifier of the trace log containing captured canvas calls.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.captureFrame\nCanvas.captureFrame(frameId, function callback(res) {\n\t// res = {traceLogId}\n});\n</pre>\n</div>\n<div id='Canvas_startCapturing' class='command'>\n<h3>Canvas.startCapturing <span class='label label-success'>Command</span></h3>\n<p>Starts (or continues) consecutive canvas frames capturing. The capturing is stopped by the corresponding stopCapturing command.</p>\n<dl>\n<dt>frameId (optional)</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame containing document whose canvases are to be captured. If omitted, main frame is assumed.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a> <span class='text'>Identifier of the trace log containing captured canvas calls.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.startCapturing\nCanvas.startCapturing(frameId, function callback(res) {\n\t// res = {traceLogId}\n});\n</pre>\n</div>\n<div id='Canvas_stopCapturing' class='command'>\n<h3>Canvas.stopCapturing <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.stopCapturing\nCanvas.stopCapturing(traceLogId);\n</pre>\n</div>\n<div id='Canvas_getTraceLog' class='command'>\n<h3>Canvas.getTraceLog <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n<dt>startOffset (optional)</dt>\n<dd>Integer</dd>\n<dt>maxLength (optional)</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>traceLog</dt>\n<dd><a href='#Canvas.TraceLog'>Canvas.TraceLog</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.getTraceLog\nCanvas.getTraceLog(traceLogId, startOffset, maxLength, function callback(res) {\n\t// res = {traceLog}\n});\n</pre>\n</div>\n<div id='Canvas_replayTraceLog' class='command'>\n<h3>Canvas.replayTraceLog <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n<dt>stepNo</dt>\n<dd>Integer <span class='text'>Last call index in the trace log to replay (zero based).</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>resourceState</dt>\n<dd><a href='#Canvas.ResourceState'>Canvas.ResourceState</a></dd>\n<dt>replayTime</dt>\n<dd>Number <span class='text'>Replay time (in milliseconds).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.replayTraceLog\nCanvas.replayTraceLog(traceLogId, stepNo, function callback(res) {\n\t// res = {resourceState, replayTime}\n});\n</pre>\n</div>\n<div id='Canvas_getResourceState' class='command'>\n<h3>Canvas.getResourceState <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n<dt>resourceId</dt>\n<dd><a href='#Canvas.ResourceId'>Canvas.ResourceId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>resourceState</dt>\n<dd><a href='#Canvas.ResourceState'>Canvas.ResourceState</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.getResourceState\nCanvas.getResourceState(traceLogId, resourceId, function callback(res) {\n\t// res = {resourceState}\n});\n</pre>\n</div>\n<div id='Canvas_evaluateTraceLogCallArgument' class='command'>\n<h3>Canvas.evaluateTraceLogCallArgument <span class='label label-success'>Command</span></h3>\n<p>Evaluates a given trace call argument or its result.</p>\n<dl>\n<dt>traceLogId</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a></dd>\n<dt>callIndex</dt>\n<dd>Integer <span class='text'>Index of the call to evaluate on (zero based).</span></dd>\n<dt>argumentIndex</dt>\n<dd>Integer <span class='text'>Index of the argument to evaluate (zero based). Provide <code>-1</code> to evaluate call result.</span></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>String object group name to put result into (allows rapid releasing resulting object handles using <code>Runtime.releaseObjectGroup</code>).</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Object wrapper for the evaluation result.</span></dd>\n<dt>resourceState (optional)</dt>\n<dd><a href='#Canvas.ResourceState'>Canvas.ResourceState</a> <span class='text'>State of the <code>Resource</code> object.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Canvas.evaluateTraceLogCallArgument\nCanvas.evaluateTraceLogCallArgument(traceLogId, callIndex, argumentIndex, objectGroup, function callback(res) {\n\t// res = {result, resourceState}\n});\n</pre>\n</div>\n<div id='Canvas_contextCreated' class='command'>\n<h3>Canvas.contextCreated <span class='label label-info'>Event</span></h3>\n<p>Fired when a canvas context has been created in the given frame. The context may not be instrumented (see hasUninstrumentedCanvases command).</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame containing a canvas with a context.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Canvas.contextCreated\nfunction onContextCreated(res) {\n\t// res = {frameId}\n}\n</pre>\n</div>\n<div id='Canvas_traceLogsRemoved' class='command'>\n<h3>Canvas.traceLogsRemoved <span class='label label-info'>Event</span></h3>\n<p>Fired when a set of trace logs were removed from the backend. If no parameters are given, all trace logs were removed.</p>\n<dl>\n<dt>frameId (optional)</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>If given, trace logs from the given frame were removed.</span></dd>\n<dt>traceLogId (optional)</dt>\n<dd><a href='#Canvas.TraceLogId'>Canvas.TraceLogId</a> <span class='text'>If given, trace log with the given ID was removed.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Canvas.traceLogsRemoved\nfunction onTraceLogsRemoved(res) {\n\t// res = {frameId, traceLogId}\n}\n</pre>\n</div>\n</section>\n<section id='Console' class='domain'>\n<h1>Console</h1>\n<p>Console domain defines methods and events for interaction with the JavaScript console. Console collects messages created by means of the <a href='http://getfirebug.com/wiki/index.php/Console_API'>JavaScript Console API</a>. One needs to enable this domain using <code>enable</code> command in order to start receiving the console messages. Browser collects messages issued while console domain is not enabled as well and reports them using <code>messageAdded</code> notification upon enabling.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Console.Timestamp'>Console.Timestamp</a>: Number of seconds since epoch.</li>\n<li><a href='#Console.ConsoleMessage'>Console.ConsoleMessage</a>: Console message.</li>\n<li><a href='#Console.CallFrame'>Console.CallFrame</a>: Stack entry for console errors and assertions.</li>\n<li><a href='#Console.StackTrace'>Console.StackTrace</a>: Call frames for assertions or error messages.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Console.enable'>Console.enable</a>: Enables console domain, sends the messages collected so far to the client by means of the messageAdded notification.</li>\n<li><a href='#Console.disable'>Console.disable</a>: Disables console domain, prevents further console messages from being reported to the client.</li>\n<li><a href='#Console.clearMessages'>Console.clearMessages</a>: Clears console messages collected in the browser.</li>\n<li><a href='#Console.setMonitoringXHREnabled'>Console.setMonitoringXHREnabled</a>: Toggles monitoring of XMLHttpRequest. If true, console will receive messages upon each XHR issued.</li>\n<li><a href='#Console.addInspectedNode'>Console.addInspectedNode</a>: Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).</li>\n<li><a href='#Console.addInspectedHeapObject'>Console.addInspectedHeapObject</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Console.messageAdded'>Console.messageAdded</a>: Issued when new console message is added.</li>\n<li><a href='#Console.messageRepeatCountUpdated'>Console.messageRepeatCountUpdated</a>: Issued when subsequent message(s) are equal to the previous one(s).</li>\n<li><a href='#Console.messagesCleared'>Console.messagesCleared</a>: Issued when console is cleared. This happens either upon clearMessages command or after page navigation.</li>\n</ul>\n<div id='Console_Timestamp' class='type'>\n<h3>Console.Timestamp <span class='label'>Type</span></h3>\n<p>Number of seconds since epoch.</p>\n<dl>\n<dd>Number</dd>\n</dl>\n</div>\n<div id='Console_ConsoleMessage' class='type'>\n<h3>Console.ConsoleMessage <span class='label'>Type</span></h3>\n<p>Console message.</p>\n<dl>\n<dt>source</dt>\n<dd>( xml | javascript | network | console-api | storage | appcache | rendering | css | security | other | deprecation ) <span class='text'>Message source.</span></dd>\n<dt>level</dt>\n<dd>( log | warning | error | debug ) <span class='text'>Message severity.</span></dd>\n<dt>text</dt>\n<dd>String <span class='text'>Message text.</span></dd>\n<dt>type (optional)</dt>\n<dd>( log | dir | dirxml | table | trace | clear | startGroup | startGroupCollapsed | endGroup | assert | profile | profileEnd ) <span class='text'>Console message type.</span></dd>\n<dt>url (optional)</dt>\n<dd>String <span class='text'>URL of the message origin.</span></dd>\n<dt>line (optional)</dt>\n<dd>Integer <span class='text'>Line number in the resource that generated this message.</span></dd>\n<dt>column (optional)</dt>\n<dd>Integer <span class='text'>Column number in the resource that generated this message.</span></dd>\n<dt>repeatCount (optional)</dt>\n<dd>Integer <span class='text'>Repeat count for repeated messages.</span></dd>\n<dt>parameters (optional)</dt>\n<dd>[<a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a>] <span class='text'>Message parameters in case of the formatted message.</span></dd>\n<dt>stackTrace (optional)</dt>\n<dd><a href='#Console.StackTrace'>Console.StackTrace</a> <span class='text'>JavaScript stack trace for assertions and error messages.</span></dd>\n<dt>networkRequestId (optional)</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Identifier of the network request associated with this message.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Console.Timestamp'>Console.Timestamp</a> <span class='text'>Timestamp, when this message was fired.</span></dd>\n</dl>\n</div>\n<div id='Console_CallFrame' class='type'>\n<h3>Console.CallFrame <span class='label'>Type</span></h3>\n<p>Stack entry for console errors and assertions.</p>\n<dl>\n<dt>functionName</dt>\n<dd>String <span class='text'>JavaScript function name.</span></dd>\n<dt>scriptId</dt>\n<dd>String <span class='text'>JavaScript script id.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>JavaScript script name or url.</span></dd>\n<dt>lineNumber</dt>\n<dd>Integer <span class='text'>JavaScript script line number.</span></dd>\n<dt>columnNumber</dt>\n<dd>Integer <span class='text'>JavaScript script column number.</span></dd>\n</dl>\n</div>\n<div id='Console_StackTrace' class='type'>\n<h3>Console.StackTrace <span class='label'>Type</span></h3>\n<p>Call frames for assertions or error messages.</p>\n<dl>\n<dd>[<a href='#Console.CallFrame'>Console.CallFrame</a>]</dd>\n</dl>\n</div>\n<div id='Console_enable' class='command'>\n<h3>Console.enable <span class='label label-success'>Command</span></h3>\n<p>Enables console domain, sends the messages collected so far to the client by means of the <code>messageAdded</code> notification.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Console.enable\nConsole.enable();\n</pre>\n</div>\n<div id='Console_disable' class='command'>\n<h3>Console.disable <span class='label label-success'>Command</span></h3>\n<p>Disables console domain, prevents further console messages from being reported to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Console.disable\nConsole.disable();\n</pre>\n</div>\n<div id='Console_clearMessages' class='command'>\n<h3>Console.clearMessages <span class='label label-success'>Command</span></h3>\n<p>Clears console messages collected in the browser.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Console.clearMessages\nConsole.clearMessages();\n</pre>\n</div>\n<div id='Console_setMonitoringXHREnabled' class='command'>\n<h3>Console.setMonitoringXHREnabled <span class='label label-success'>Command</span></h3>\n<p>Toggles monitoring of XMLHttpRequest. If <code>true</code>, console will receive messages upon each XHR issued.</p>\n<dl>\n<dt>enabled</dt>\n<dd>Boolean <span class='text'>Monitoring enabled state.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Console.setMonitoringXHREnabled\nConsole.setMonitoringXHREnabled(enabled);\n</pre>\n</div>\n<div id='Console_addInspectedNode' class='command'>\n<h3>Console.addInspectedNode <span class='label label-success'>Command</span></h3>\n<p>Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions).</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>DOM node id to be accessible by means of $x command line API.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Console.addInspectedNode\nConsole.addInspectedNode(nodeId);\n</pre>\n</div>\n<div id='Console_addInspectedHeapObject' class='command'>\n<h3>Console.addInspectedHeapObject <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>heapObjectId</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Console.addInspectedHeapObject\nConsole.addInspectedHeapObject(heapObjectId);\n</pre>\n</div>\n<div id='Console_messageAdded' class='command'>\n<h3>Console.messageAdded <span class='label label-info'>Event</span></h3>\n<p>Issued when new console message is added.</p>\n<dl>\n<dt>message</dt>\n<dd><a href='#Console.ConsoleMessage'>Console.ConsoleMessage</a> <span class='text'>Console message that has been added.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Console.messageAdded\nfunction onMessageAdded(res) {\n\t// res = {message}\n}\n</pre>\n</div>\n<div id='Console_messageRepeatCountUpdated' class='command'>\n<h3>Console.messageRepeatCountUpdated <span class='label label-info'>Event</span></h3>\n<p>Issued when subsequent message(s) are equal to the previous one(s).</p>\n<dl>\n<dt>count</dt>\n<dd>Integer <span class='text'>New repeat count value.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Console.Timestamp'>Console.Timestamp</a> <span class='text'>Timestamp of most recent message in batch.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Console.messageRepeatCountUpdated\nfunction onMessageRepeatCountUpdated(res) {\n\t// res = {count, timestamp}\n}\n</pre>\n</div>\n<div id='Console_messagesCleared' class='command'>\n<h3>Console.messagesCleared <span class='label label-info'>Event</span></h3>\n<p>Issued when console is cleared. This happens either upon <code>clearMessages</code> command or after page navigation.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Console.messagesCleared\nfunction onMessagesCleared(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n<section id='DOM' class='domain'>\n<h1>DOM</h1>\n<p>This domain exposes DOM read/write operations. Each DOM Node is represented with its mirror object that has an <code>id</code>. This <code>id</code> can be used to get additional information on the Node, resolve it into the JavaScript object wrapper, etc. It is important that client receives DOM events only for the nodes that are known to the client. Backend keeps track of the nodes that were sent to the client and never sends the same node twice. It is client's responsibility to collect information about the nodes that were sent to the client.<p>Note that <code>iframe</code> owner elements will return corresponding document elements as their child nodes.</p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#DOM.NodeId'>DOM.NodeId</a>: Unique DOM node identifier.</li>\n<li><a href='#DOM.BackendNodeId'>DOM.BackendNodeId</a>: Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.</li>\n<li><a href='#DOM.PseudoType'>DOM.PseudoType</a>: Pseudo element type.</li>\n<li><a href='#DOM.Node'>DOM.Node</a>: DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.</li>\n<li><a href='#DOM.EventListener'>DOM.EventListener</a>: DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.</li>\n<li><a href='#DOM.RGBA'>DOM.RGBA</a>: A structure holding an RGBA color.</li>\n<li><a href='#DOM.Quad'>DOM.Quad</a>: An array of quad vertices, x immediately followed by y for each point, points clock-wise.</li>\n<li><a href='#DOM.BoxModel'>DOM.BoxModel</a>: Box model.</li>\n<li><a href='#DOM.Rect'>DOM.Rect</a>: Rectangle.</li>\n<li><a href='#DOM.HighlightConfig'>DOM.HighlightConfig</a>: Configuration data for the highlighting of page elements.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#DOM.enable'>DOM.enable</a>: Enables DOM agent for the given page.</li>\n<li><a href='#DOM.disable'>DOM.disable</a>: Disables DOM agent for the given page.</li>\n<li><a href='#DOM.getDocument'>DOM.getDocument</a>: Returns the root DOM node to the caller.</li>\n<li><a href='#DOM.requestChildNodes'>DOM.requestChildNodes</a>: Requests that children of the node with given id are returned to the caller in form of setChildNodes events where not only immediate children are retrieved, but all children down to the specified depth.</li>\n<li><a href='#DOM.querySelector'>DOM.querySelector</a>: Executes querySelector on a given node.</li>\n<li><a href='#DOM.querySelectorAll'>DOM.querySelectorAll</a>: Executes querySelectorAll on a given node.</li>\n<li><a href='#DOM.setNodeName'>DOM.setNodeName</a>: Sets node name for a node with given id.</li>\n<li><a href='#DOM.setNodeValue'>DOM.setNodeValue</a>: Sets node value for a node with given id.</li>\n<li><a href='#DOM.removeNode'>DOM.removeNode</a>: Removes node with given id.</li>\n<li><a href='#DOM.setAttributeValue'>DOM.setAttributeValue</a>: Sets attribute for an element with given id.</li>\n<li><a href='#DOM.setAttributesAsText'>DOM.setAttributesAsText</a>: Sets attributes on element with given id. This method is useful when user edits some existing attribute value and types in several attribute name/value pairs.</li>\n<li><a href='#DOM.removeAttribute'>DOM.removeAttribute</a>: Removes attribute with given name from an element with given id.</li>\n<li><a href='#DOM.getEventListenersForNode'>DOM.getEventListenersForNode</a>: Returns event listeners relevant to the node.</li>\n<li><a href='#DOM.getOuterHTML'>DOM.getOuterHTML</a>: Returns node's HTML markup.</li>\n<li><a href='#DOM.setOuterHTML'>DOM.setOuterHTML</a>: Sets node HTML markup, returns new node id.</li>\n<li><a href='#DOM.performSearch'>DOM.performSearch</a>: Searches for a given string in the DOM tree. Use getSearchResults to access search results or cancelSearch to end this search session.</li>\n<li><a href='#DOM.getSearchResults'>DOM.getSearchResults</a>: Returns search results from given fromIndex to given toIndex from the sarch with the given identifier.</li>\n<li><a href='#DOM.discardSearchResults'>DOM.discardSearchResults</a>: Discards search results from the session with the given id. getSearchResults should no longer be called for that search.</li>\n<li><a href='#DOM.requestNode'>DOM.requestNode</a>: Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of setChildNodes notifications.</li>\n<li><a href='#DOM.setInspectModeEnabled'>DOM.setInspectModeEnabled</a>: Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection.</li>\n<li><a href='#DOM.highlightRect'>DOM.highlightRect</a>: Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport.</li>\n<li><a href='#DOM.highlightQuad'>DOM.highlightQuad</a>: Highlights given quad. Coordinates are absolute with respect to the main frame viewport.</li>\n<li><a href='#DOM.highlightNode'>DOM.highlightNode</a>: Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified.</li>\n<li><a href='#DOM.hideHighlight'>DOM.hideHighlight</a>: Hides DOM node highlight.</li>\n<li><a href='#DOM.highlightFrame'>DOM.highlightFrame</a>: Highlights owner element of the frame with given id.</li>\n<li><a href='#DOM.pushNodeByPathToFrontend'>DOM.pushNodeByPathToFrontend</a>: Requests that the node is sent to the caller given its path. // FIXME, use XPath</li>\n<li><a href='#DOM.pushNodeByBackendIdToFrontend'>DOM.pushNodeByBackendIdToFrontend</a>: Requests that the node is sent to the caller given its backend node id.</li>\n<li><a href='#DOM.releaseBackendNodeIds'>DOM.releaseBackendNodeIds</a>: Requests that group of BackendNodeIds is released.</li>\n<li><a href='#DOM.resolveNode'>DOM.resolveNode</a>: Resolves JavaScript node object for given node id.</li>\n<li><a href='#DOM.getAttributes'>DOM.getAttributes</a>: Returns attributes for the specified node.</li>\n<li><a href='#DOM.moveTo'>DOM.moveTo</a>: Moves node into the new container, places it before the given anchor.</li>\n<li><a href='#DOM.undo'>DOM.undo</a>: Undoes the last performed action.</li>\n<li><a href='#DOM.redo'>DOM.redo</a>: Re-does the last undone action.</li>\n<li><a href='#DOM.markUndoableState'>DOM.markUndoableState</a>: Marks last undoable state.</li>\n<li><a href='#DOM.focus'>DOM.focus</a>: Focuses the given element.</li>\n<li><a href='#DOM.setFileInputFiles'>DOM.setFileInputFiles</a>: Sets files for the given file input element.</li>\n<li><a href='#DOM.getBoxModel'>DOM.getBoxModel</a>: Returns boxes for the currently selected nodes.</li>\n<li><a href='#DOM.getNodeForLocation'>DOM.getNodeForLocation</a>: Returns node id at given location.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#DOM.documentUpdated'>DOM.documentUpdated</a>: Fired when Document has been totally updated. Node ids are no longer valid.</li>\n<li><a href='#DOM.inspectNodeRequested'>DOM.inspectNodeRequested</a>: Fired when the node should be inspected. This happens after call to setInspectModeEnabled.</li>\n<li><a href='#DOM.setChildNodes'>DOM.setChildNodes</a>: Fired when backend wants to provide client with the missing DOM structure. This happens upon most of the calls requesting node ids.</li>\n<li><a href='#DOM.attributeModified'>DOM.attributeModified</a>: Fired when Element's attribute is modified.</li>\n<li><a href='#DOM.attributeRemoved'>DOM.attributeRemoved</a>: Fired when Element's attribute is removed.</li>\n<li><a href='#DOM.inlineStyleInvalidated'>DOM.inlineStyleInvalidated</a>: Fired when Element's inline style is modified via a CSS property modification.</li>\n<li><a href='#DOM.characterDataModified'>DOM.characterDataModified</a>: Mirrors DOMCharacterDataModified event.</li>\n<li><a href='#DOM.childNodeCountUpdated'>DOM.childNodeCountUpdated</a>: Fired when Container's child node count has changed.</li>\n<li><a href='#DOM.childNodeInserted'>DOM.childNodeInserted</a>: Mirrors DOMNodeInserted event.</li>\n<li><a href='#DOM.childNodeRemoved'>DOM.childNodeRemoved</a>: Mirrors DOMNodeRemoved event.</li>\n<li><a href='#DOM.shadowRootPushed'>DOM.shadowRootPushed</a>: Called when shadow root is pushed into the element.</li>\n<li><a href='#DOM.shadowRootPopped'>DOM.shadowRootPopped</a>: Called when shadow root is popped from the element.</li>\n<li><a href='#DOM.pseudoElementAdded'>DOM.pseudoElementAdded</a>: Called when a pseudo element is added to an element.</li>\n<li><a href='#DOM.pseudoElementRemoved'>DOM.pseudoElementRemoved</a>: Called when a pseudo element is removed from an element.</li>\n</ul>\n<div id='DOM_NodeId' class='type'>\n<h3>DOM.NodeId <span class='label'>Type</span></h3>\n<p>Unique DOM node identifier.</p>\n<dl>\n<dd>Integer</dd>\n</dl>\n</div>\n<div id='DOM_BackendNodeId' class='type'>\n<h3>DOM.BackendNodeId <span class='label'>Type</span></h3>\n<p>Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.</p>\n<dl>\n<dd>Integer</dd>\n</dl>\n</div>\n<div id='DOM_PseudoType' class='type'>\n<h3>DOM.PseudoType <span class='label'>Type</span></h3>\n<p>Pseudo element type.</p>\n<dl>\n<dd>( before | after )</dd>\n</dl>\n</div>\n<div id='DOM_Node' class='type'>\n<h3>DOM.Node <span class='label'>Type</span></h3>\n<p>DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Node identifier that is passed into the rest of the DOM messages as the <code>nodeId</code>. Backend will only push node with given <code>id</code> once. It is aware of all requested nodes and will only fire DOM events for nodes known to the client.</span></dd>\n<dt>nodeType</dt>\n<dd>Integer <span class='text'><code>Node</code>'s nodeType.</span></dd>\n<dt>nodeName</dt>\n<dd>String <span class='text'><code>Node</code>'s nodeName.</span></dd>\n<dt>localName</dt>\n<dd>String <span class='text'><code>Node</code>'s localName.</span></dd>\n<dt>nodeValue</dt>\n<dd>String <span class='text'><code>Node</code>'s nodeValue.</span></dd>\n<dt>childNodeCount (optional)</dt>\n<dd>Integer <span class='text'>Child count for <code>Container</code> nodes.</span></dd>\n<dt>children (optional)</dt>\n<dd>[<a href='#DOM.Node'>DOM.Node</a>] <span class='text'>Child nodes of this node when requested with children.</span></dd>\n<dt>attributes (optional)</dt>\n<dd>[String] <span class='text'>Attributes of the <code>Element</code> node in the form of flat array <code>[name1, value1, name2, value2]</code>.</span></dd>\n<dt>documentURL (optional)</dt>\n<dd>String <span class='text'>Document URL that <code>Document</code> or <code>FrameOwner</code> node points to.</span></dd>\n<dt>baseURL (optional)</dt>\n<dd>String <span class='text'>Base URL that <code>Document</code> or <code>FrameOwner</code> node uses for URL completion.</span></dd>\n<dt>publicId (optional)</dt>\n<dd>String <span class='text'><code>DocumentType</code>'s publicId.</span></dd>\n<dt>systemId (optional)</dt>\n<dd>String <span class='text'><code>DocumentType</code>'s systemId.</span></dd>\n<dt>internalSubset (optional)</dt>\n<dd>String <span class='text'><code>DocumentType</code>'s internalSubset.</span></dd>\n<dt>xmlVersion (optional)</dt>\n<dd>String <span class='text'><code>Document</code>'s XML version in case of XML documents.</span></dd>\n<dt>name (optional)</dt>\n<dd>String <span class='text'><code>Attr</code>'s name.</span></dd>\n<dt>value (optional)</dt>\n<dd>String <span class='text'><code>Attr</code>'s value.</span></dd>\n<dt>pseudoType (optional)</dt>\n<dd><a href='#DOM.PseudoType'>DOM.PseudoType</a> <span class='text'>Pseudo element type for this node.</span></dd>\n<dt>frameId (optional)</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame ID for frame owner elements.</span></dd>\n<dt>contentDocument (optional)</dt>\n<dd><a href='#DOM.Node'>DOM.Node</a> <span class='text'>Content document for frame owner elements.</span></dd>\n<dt>shadowRoots (optional)</dt>\n<dd>[<a href='#DOM.Node'>DOM.Node</a>] <span class='text'>Shadow root list for given element host.</span></dd>\n<dt>templateContent (optional)</dt>\n<dd><a href='#DOM.Node'>DOM.Node</a> <span class='text'>Content document fragment for template elements.</span></dd>\n<dt>pseudoElements (optional)</dt>\n<dd>[<a href='#DOM.Node'>DOM.Node</a>] <span class='text'>Pseudo elements associated with this node.</span></dd>\n</dl>\n</div>\n<div id='DOM_EventListener' class='type'>\n<h3>DOM.EventListener <span class='label'>Type</span></h3>\n<p>DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.</p>\n<dl>\n<dt>type</dt>\n<dd>String <span class='text'><code>EventListener</code>'s type.</span></dd>\n<dt>useCapture</dt>\n<dd>Boolean <span class='text'><code>EventListener</code>'s useCapture.</span></dd>\n<dt>isAttribute</dt>\n<dd>Boolean <span class='text'><code>EventListener</code>'s isAttribute.</span></dd>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Target <code>DOMNode</code> id.</span></dd>\n<dt>handlerBody</dt>\n<dd>String <span class='text'>Event handler function body.</span></dd>\n<dt>location (optional)</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Handler code location.</span></dd>\n<dt>sourceName (optional)</dt>\n<dd>String <span class='text'>Source script URL.</span></dd>\n<dt>handler (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Event handler function value.</span></dd>\n</dl>\n</div>\n<div id='DOM_RGBA' class='type'>\n<h3>DOM.RGBA <span class='label'>Type</span></h3>\n<p>A structure holding an RGBA color.</p>\n<dl>\n<dt>r</dt>\n<dd>Integer <span class='text'>The red component, in the [0-255] range.</span></dd>\n<dt>g</dt>\n<dd>Integer <span class='text'>The green component, in the [0-255] range.</span></dd>\n<dt>b</dt>\n<dd>Integer <span class='text'>The blue component, in the [0-255] range.</span></dd>\n<dt>a (optional)</dt>\n<dd>Number <span class='text'>The alpha component, in the [0-1] range (default: 1).</span></dd>\n</dl>\n</div>\n<div id='DOM_Quad' class='type'>\n<h3>DOM.Quad <span class='label'>Type</span></h3>\n<p>An array of quad vertices, x immediately followed by y for each point, points clock-wise.</p>\n<dl>\n<dd>[Number]</dd>\n</dl>\n</div>\n<div id='DOM_BoxModel' class='type'>\n<h3>DOM.BoxModel <span class='label'>Type</span></h3>\n<p>Box model.</p>\n<dl>\n<dt>content</dt>\n<dd><a href='#DOM.Quad'>DOM.Quad</a> <span class='text'>Content box</span></dd>\n<dt>padding</dt>\n<dd><a href='#DOM.Quad'>DOM.Quad</a> <span class='text'>Padding box</span></dd>\n<dt>border</dt>\n<dd><a href='#DOM.Quad'>DOM.Quad</a> <span class='text'>Border box</span></dd>\n<dt>margin</dt>\n<dd><a href='#DOM.Quad'>DOM.Quad</a> <span class='text'>Margin box</span></dd>\n<dt>width</dt>\n<dd>Integer <span class='text'>Node width</span></dd>\n<dt>height</dt>\n<dd>Integer <span class='text'>Node height</span></dd>\n</dl>\n</div>\n<div id='DOM_Rect' class='type'>\n<h3>DOM.Rect <span class='label'>Type</span></h3>\n<p>Rectangle.</p>\n<dl>\n<dt>x</dt>\n<dd>Number <span class='text'>X coordinate</span></dd>\n<dt>y</dt>\n<dd>Number <span class='text'>Y coordinate</span></dd>\n<dt>width</dt>\n<dd>Number <span class='text'>Rectangle width</span></dd>\n<dt>height</dt>\n<dd>Number <span class='text'>Rectangle height</span></dd>\n</dl>\n</div>\n<div id='DOM_HighlightConfig' class='type'>\n<h3>DOM.HighlightConfig <span class='label'>Type</span></h3>\n<p>Configuration data for the highlighting of page elements.</p>\n<dl>\n<dt>showInfo (optional)</dt>\n<dd>Boolean <span class='text'>Whether the node info tooltip should be shown (default: false).</span></dd>\n<dt>contentColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The content box highlight fill color (default: transparent).</span></dd>\n<dt>paddingColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The padding highlight fill color (default: transparent).</span></dd>\n<dt>borderColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The border highlight fill color (default: transparent).</span></dd>\n<dt>marginColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The margin highlight fill color (default: transparent).</span></dd>\n<dt>eventTargetColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The event target element highlight fill color (default: transparent).</span></dd>\n</dl>\n</div>\n<div id='DOM_enable' class='command'>\n<h3>DOM.enable <span class='label label-success'>Command</span></h3>\n<p>Enables DOM agent for the given page.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.enable\nDOM.enable();\n</pre>\n</div>\n<div id='DOM_disable' class='command'>\n<h3>DOM.disable <span class='label label-success'>Command</span></h3>\n<p>Disables DOM agent for the given page.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.disable\nDOM.disable();\n</pre>\n</div>\n<div id='DOM_getDocument' class='command'>\n<h3>DOM.getDocument <span class='label label-success'>Command</span></h3>\n<p>Returns the root DOM node to the caller.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>root</dt>\n<dd><a href='#DOM.Node'>DOM.Node</a> <span class='text'>Resulting node.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getDocument\nDOM.getDocument(function callback(res) {\n\t// res = {root}\n});\n</pre>\n</div>\n<div id='DOM_requestChildNodes' class='command'>\n<h3>DOM.requestChildNodes <span class='label label-success'>Command</span></h3>\n<p>Requests that children of the node with given id are returned to the caller in form of <code>setChildNodes</code> events where not only immediate children are retrieved, but all children down to the specified depth.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to get children for.</span></dd>\n<dt>depth (optional)</dt>\n<dd>Integer <span class='text'>The maximum depth at which children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.requestChildNodes\nDOM.requestChildNodes(nodeId, depth);\n</pre>\n</div>\n<div id='DOM_querySelector' class='command'>\n<h3>DOM.querySelector <span class='label label-success'>Command</span></h3>\n<p>Executes <code>querySelector</code> on a given node.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to query upon.</span></dd>\n<dt>selector</dt>\n<dd>String <span class='text'>Selector string.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Query selector result.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.querySelector\nDOM.querySelector(nodeId, selector, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_querySelectorAll' class='command'>\n<h3>DOM.querySelectorAll <span class='label label-success'>Command</span></h3>\n<p>Executes <code>querySelectorAll</code> on a given node.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to query upon.</span></dd>\n<dt>selector</dt>\n<dd>String <span class='text'>Selector string.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeIds</dt>\n<dd>[<a href='#DOM.NodeId'>DOM.NodeId</a>] <span class='text'>Query selector result.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.querySelectorAll\nDOM.querySelectorAll(nodeId, selector, function callback(res) {\n\t// res = {nodeIds}\n});\n</pre>\n</div>\n<div id='DOM_setNodeName' class='command'>\n<h3>DOM.setNodeName <span class='label label-success'>Command</span></h3>\n<p>Sets node name for a node with given id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to set name for.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>New node's name.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>New node's id.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setNodeName\nDOM.setNodeName(nodeId, name, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_setNodeValue' class='command'>\n<h3>DOM.setNodeValue <span class='label label-success'>Command</span></h3>\n<p>Sets node value for a node with given id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to set value for.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>New node's value.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setNodeValue\nDOM.setNodeValue(nodeId, value);\n</pre>\n</div>\n<div id='DOM_removeNode' class='command'>\n<h3>DOM.removeNode <span class='label label-success'>Command</span></h3>\n<p>Removes node with given id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to remove.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.removeNode\nDOM.removeNode(nodeId);\n</pre>\n</div>\n<div id='DOM_setAttributeValue' class='command'>\n<h3>DOM.setAttributeValue <span class='label label-success'>Command</span></h3>\n<p>Sets attribute for an element with given id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the element to set attribute for.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Attribute name.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>Attribute value.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setAttributeValue\nDOM.setAttributeValue(nodeId, name, value);\n</pre>\n</div>\n<div id='DOM_setAttributesAsText' class='command'>\n<h3>DOM.setAttributesAsText <span class='label label-success'>Command</span></h3>\n<p>Sets attributes on element with given id. This method is useful when user edits some existing attribute value and types in several attribute name/value pairs.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the element to set attributes for.</span></dd>\n<dt>text</dt>\n<dd>String <span class='text'>Text with a number of attributes. Will parse this text using HTML parser.</span></dd>\n<dt>name (optional)</dt>\n<dd>String <span class='text'>Attribute name to replace with new attributes derived from text in case text parsed successfully.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setAttributesAsText\nDOM.setAttributesAsText(nodeId, text, name);\n</pre>\n</div>\n<div id='DOM_removeAttribute' class='command'>\n<h3>DOM.removeAttribute <span class='label label-success'>Command</span></h3>\n<p>Removes attribute with given name from an element with given id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the element to remove attribute from.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Name of the attribute to remove.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.removeAttribute\nDOM.removeAttribute(nodeId, name);\n</pre>\n</div>\n<div id='DOM_getEventListenersForNode' class='command'>\n<h3>DOM.getEventListenersForNode <span class='label label-success'>Command</span></h3>\n<p>Returns event listeners relevant to the node.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to get listeners for.</span></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>Symbolic group name for handler value. Handler value is not returned without this parameter specified.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>listeners</dt>\n<dd>[<a href='#DOM.EventListener'>DOM.EventListener</a>] <span class='text'>Array of relevant listeners.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getEventListenersForNode\nDOM.getEventListenersForNode(nodeId, objectGroup, function callback(res) {\n\t// res = {listeners}\n});\n</pre>\n</div>\n<div id='DOM_getOuterHTML' class='command'>\n<h3>DOM.getOuterHTML <span class='label label-success'>Command</span></h3>\n<p>Returns node's HTML markup.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to get markup for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>outerHTML</dt>\n<dd>String <span class='text'>Outer HTML markup.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getOuterHTML\nDOM.getOuterHTML(nodeId, function callback(res) {\n\t// res = {outerHTML}\n});\n</pre>\n</div>\n<div id='DOM_setOuterHTML' class='command'>\n<h3>DOM.setOuterHTML <span class='label label-success'>Command</span></h3>\n<p>Sets node HTML markup, returns new node id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to set markup for.</span></dd>\n<dt>outerHTML</dt>\n<dd>String <span class='text'>Outer HTML markup to set.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setOuterHTML\nDOM.setOuterHTML(nodeId, outerHTML);\n</pre>\n</div>\n<div id='DOM_performSearch' class='command'>\n<h3>DOM.performSearch <span class='label label-success'>Command</span></h3>\n<p>Searches for a given string in the DOM tree. Use <code>getSearchResults</code> to access search results or <code>cancelSearch</code> to end this search session.</p>\n<dl>\n<dt>query</dt>\n<dd>String <span class='text'>Plain text or query selector or XPath search query.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>searchId</dt>\n<dd>String <span class='text'>Unique search session identifier.</span></dd>\n<dt>resultCount</dt>\n<dd>Integer <span class='text'>Number of search results.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.performSearch\nDOM.performSearch(query, function callback(res) {\n\t// res = {searchId, resultCount}\n});\n</pre>\n</div>\n<div id='DOM_getSearchResults' class='command'>\n<h3>DOM.getSearchResults <span class='label label-success'>Command</span></h3>\n<p>Returns search results from given <code>fromIndex</code> to given <code>toIndex</code> from the sarch with the given identifier.</p>\n<dl>\n<dt>searchId</dt>\n<dd>String <span class='text'>Unique search session identifier.</span></dd>\n<dt>fromIndex</dt>\n<dd>Integer <span class='text'>Start index of the search result to be returned.</span></dd>\n<dt>toIndex</dt>\n<dd>Integer <span class='text'>End index of the search result to be returned.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeIds</dt>\n<dd>[<a href='#DOM.NodeId'>DOM.NodeId</a>] <span class='text'>Ids of the search result nodes.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getSearchResults\nDOM.getSearchResults(searchId, fromIndex, toIndex, function callback(res) {\n\t// res = {nodeIds}\n});\n</pre>\n</div>\n<div id='DOM_discardSearchResults' class='command'>\n<h3>DOM.discardSearchResults <span class='label label-success'>Command</span></h3>\n<p>Discards search results from the session with the given id. <code>getSearchResults</code> should no longer be called for that search.</p>\n<dl>\n<dt>searchId</dt>\n<dd>String <span class='text'>Unique search session identifier.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.discardSearchResults\nDOM.discardSearchResults(searchId);\n</pre>\n</div>\n<div id='DOM_requestNode' class='command'>\n<h3>DOM.requestNode <span class='label label-success'>Command</span></h3>\n<p>Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of <code>setChildNodes</code> notifications.</p>\n<dl>\n<dt>objectId</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>JavaScript object id to convert into node.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Node id for given object.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.requestNode\nDOM.requestNode(objectId, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_setInspectModeEnabled' class='command'>\n<h3>DOM.setInspectModeEnabled <span class='label label-success'>Command</span></h3>\n<p>Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection.</p>\n<dl>\n<dt>enabled</dt>\n<dd>Boolean <span class='text'>True to enable inspection mode, false to disable it.</span></dd>\n<dt>inspectShadowDOM (optional)</dt>\n<dd>Boolean <span class='text'>True to enable inspection mode for shadow DOM.</span></dd>\n<dt>highlightConfig (optional)</dt>\n<dd><a href='#DOM.HighlightConfig'>DOM.HighlightConfig</a> <span class='text'>A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setInspectModeEnabled\nDOM.setInspectModeEnabled(enabled, inspectShadowDOM, highlightConfig);\n</pre>\n</div>\n<div id='DOM_highlightRect' class='command'>\n<h3>DOM.highlightRect <span class='label label-success'>Command</span></h3>\n<p>Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport.</p>\n<dl>\n<dt>x</dt>\n<dd>Integer <span class='text'>X coordinate</span></dd>\n<dt>y</dt>\n<dd>Integer <span class='text'>Y coordinate</span></dd>\n<dt>width</dt>\n<dd>Integer <span class='text'>Rectangle width</span></dd>\n<dt>height</dt>\n<dd>Integer <span class='text'>Rectangle height</span></dd>\n<dt>color (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The highlight fill color (default: transparent).</span></dd>\n<dt>outlineColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The highlight outline color (default: transparent).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.highlightRect\nDOM.highlightRect(x, y, width, height, color, outlineColor);\n</pre>\n</div>\n<div id='DOM_highlightQuad' class='command'>\n<h3>DOM.highlightQuad <span class='label label-success'>Command</span></h3>\n<p>Highlights given quad. Coordinates are absolute with respect to the main frame viewport.</p>\n<dl>\n<dt>quad</dt>\n<dd><a href='#DOM.Quad'>DOM.Quad</a> <span class='text'>Quad to highlight</span></dd>\n<dt>color (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The highlight fill color (default: transparent).</span></dd>\n<dt>outlineColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The highlight outline color (default: transparent).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.highlightQuad\nDOM.highlightQuad(quad, color, outlineColor);\n</pre>\n</div>\n<div id='DOM_highlightNode' class='command'>\n<h3>DOM.highlightNode <span class='label label-success'>Command</span></h3>\n<p>Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified.</p>\n<dl>\n<dt>highlightConfig</dt>\n<dd><a href='#DOM.HighlightConfig'>DOM.HighlightConfig</a> <span class='text'>A descriptor for the highlight appearance.</span></dd>\n<dt>nodeId (optional)</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Identifier of the node to highlight.</span></dd>\n<dt>objectId (optional)</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>JavaScript object id of the node to be highlighted.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.highlightNode\nDOM.highlightNode(highlightConfig, nodeId, objectId);\n</pre>\n</div>\n<div id='DOM_hideHighlight' class='command'>\n<h3>DOM.hideHighlight <span class='label label-success'>Command</span></h3>\n<p>Hides DOM node highlight.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.hideHighlight\nDOM.hideHighlight();\n</pre>\n</div>\n<div id='DOM_highlightFrame' class='command'>\n<h3>DOM.highlightFrame <span class='label label-success'>Command</span></h3>\n<p>Highlights owner element of the frame with given id.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Identifier of the frame to highlight.</span></dd>\n<dt>contentColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The content box highlight fill color (default: transparent).</span></dd>\n<dt>contentOutlineColor (optional)</dt>\n<dd><a href='#DOM.RGBA'>DOM.RGBA</a> <span class='text'>The content box highlight outline color (default: transparent).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.highlightFrame\nDOM.highlightFrame(frameId, contentColor, contentOutlineColor);\n</pre>\n</div>\n<div id='DOM_pushNodeByPathToFrontend' class='command'>\n<h3>DOM.pushNodeByPathToFrontend <span class='label label-success'>Command</span></h3>\n<p>Requests that the node is sent to the caller given its path. // FIXME, use XPath</p>\n<dl>\n<dt>path</dt>\n<dd>String <span class='text'>Path to node in the proprietary format.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node for given path.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.pushNodeByPathToFrontend\nDOM.pushNodeByPathToFrontend(path, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_pushNodeByBackendIdToFrontend' class='command'>\n<h3>DOM.pushNodeByBackendIdToFrontend <span class='label label-success'>Command</span></h3>\n<p>Requests that the node is sent to the caller given its backend node id.</p>\n<dl>\n<dt>backendNodeId</dt>\n<dd><a href='#DOM.BackendNodeId'>DOM.BackendNodeId</a> <span class='text'>The backend node id of the node.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The pushed node's id.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.pushNodeByBackendIdToFrontend\nDOM.pushNodeByBackendIdToFrontend(backendNodeId, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_releaseBackendNodeIds' class='command'>\n<h3>DOM.releaseBackendNodeIds <span class='label label-success'>Command</span></h3>\n<p>Requests that group of <code>BackendNodeIds</code> is released.</p>\n<dl>\n<dt>nodeGroup</dt>\n<dd>String <span class='text'>The backend node ids group name.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.releaseBackendNodeIds\nDOM.releaseBackendNodeIds(nodeGroup);\n</pre>\n</div>\n<div id='DOM_resolveNode' class='command'>\n<h3>DOM.resolveNode <span class='label label-success'>Command</span></h3>\n<p>Resolves JavaScript node object for given node id.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to resolve.</span></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>Symbolic group name that can be used to release multiple objects.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>object</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>JavaScript object wrapper for given node.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.resolveNode\nDOM.resolveNode(nodeId, objectGroup, function callback(res) {\n\t// res = {object}\n});\n</pre>\n</div>\n<div id='DOM_getAttributes' class='command'>\n<h3>DOM.getAttributes <span class='label label-success'>Command</span></h3>\n<p>Returns attributes for the specified node.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to retrieve attibutes for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>attributes</dt>\n<dd>[String] <span class='text'>An interleaved array of node attribute names and values.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getAttributes\nDOM.getAttributes(nodeId, function callback(res) {\n\t// res = {attributes}\n});\n</pre>\n</div>\n<div id='DOM_moveTo' class='command'>\n<h3>DOM.moveTo <span class='label label-success'>Command</span></h3>\n<p>Moves node into the new container, places it before the given anchor.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to drop.</span></dd>\n<dt>targetNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the element to drop into.</span></dd>\n<dt>insertBeforeNodeId (optional)</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Drop node before given one.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>New id of the moved node.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.moveTo\nDOM.moveTo(nodeId, targetNodeId, insertBeforeNodeId, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_undo' class='command'>\n<h3>DOM.undo <span class='label label-success'>Command</span></h3>\n<p>Undoes the last performed action.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.undo\nDOM.undo();\n</pre>\n</div>\n<div id='DOM_redo' class='command'>\n<h3>DOM.redo <span class='label label-success'>Command</span></h3>\n<p>Re-does the last undone action.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.redo\nDOM.redo();\n</pre>\n</div>\n<div id='DOM_markUndoableState' class='command'>\n<h3>DOM.markUndoableState <span class='label label-success'>Command</span></h3>\n<p>Marks last undoable state.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.markUndoableState\nDOM.markUndoableState();\n</pre>\n</div>\n<div id='DOM_focus' class='command'>\n<h3>DOM.focus <span class='label label-success'>Command</span></h3>\n<p>Focuses the given element.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to focus.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.focus\nDOM.focus(nodeId);\n</pre>\n</div>\n<div id='DOM_setFileInputFiles' class='command'>\n<h3>DOM.setFileInputFiles <span class='label label-success'>Command</span></h3>\n<p>Sets files for the given file input element.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the file input node to set files for.</span></dd>\n<dt>files</dt>\n<dd>[String] <span class='text'>Array of file paths to set.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.setFileInputFiles\nDOM.setFileInputFiles(nodeId, files);\n</pre>\n</div>\n<div id='DOM_getBoxModel' class='command'>\n<h3>DOM.getBoxModel <span class='label label-success'>Command</span></h3>\n<p>Returns boxes for the currently selected nodes.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to get box model for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>model</dt>\n<dd><a href='#DOM.BoxModel'>DOM.BoxModel</a> <span class='text'>Box model for the node.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getBoxModel\nDOM.getBoxModel(nodeId, function callback(res) {\n\t// res = {model}\n});\n</pre>\n</div>\n<div id='DOM_getNodeForLocation' class='command'>\n<h3>DOM.getNodeForLocation <span class='label label-success'>Command</span></h3>\n<p>Returns node id at given location.</p>\n<dl>\n<dt>x</dt>\n<dd>Integer <span class='text'>X coordinate.</span></dd>\n<dt>y</dt>\n<dd>Integer <span class='text'>Y coordinate.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node at given coordinates.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOM.getNodeForLocation\nDOM.getNodeForLocation(x, y, function callback(res) {\n\t// res = {nodeId}\n});\n</pre>\n</div>\n<div id='DOM_documentUpdated' class='command'>\n<h3>DOM.documentUpdated <span class='label label-info'>Event</span></h3>\n<p>Fired when <code>Document</code> has been totally updated. Node ids are no longer valid.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.documentUpdated\nfunction onDocumentUpdated(res) {\n\t// res = {}\n}\n</pre>\n</div>\n<div id='DOM_inspectNodeRequested' class='command'>\n<h3>DOM.inspectNodeRequested <span class='label label-info'>Event</span></h3>\n<p>Fired when the node should be inspected. This happens after call to <code>setInspectModeEnabled</code>.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node to inspect.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.inspectNodeRequested\nfunction onInspectNodeRequested(res) {\n\t// res = {nodeId}\n}\n</pre>\n</div>\n<div id='DOM_setChildNodes' class='command'>\n<h3>DOM.setChildNodes <span class='label label-info'>Event</span></h3>\n<p>Fired when backend wants to provide client with the missing DOM structure. This happens upon most of the calls requesting node ids.</p>\n<dl>\n<dt>parentId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Parent node id to populate with children.</span></dd>\n<dt>nodes</dt>\n<dd>[<a href='#DOM.Node'>DOM.Node</a>] <span class='text'>Child nodes array.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.setChildNodes\nfunction onSetChildNodes(res) {\n\t// res = {parentId, nodes}\n}\n</pre>\n</div>\n<div id='DOM_attributeModified' class='command'>\n<h3>DOM.attributeModified <span class='label label-info'>Event</span></h3>\n<p>Fired when <code>Element</code>'s attribute is modified.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node that has changed.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Attribute name.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>Attribute value.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.attributeModified\nfunction onAttributeModified(res) {\n\t// res = {nodeId, name, value}\n}\n</pre>\n</div>\n<div id='DOM_attributeRemoved' class='command'>\n<h3>DOM.attributeRemoved <span class='label label-info'>Event</span></h3>\n<p>Fired when <code>Element</code>'s attribute is removed.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node that has changed.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>A ttribute name.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.attributeRemoved\nfunction onAttributeRemoved(res) {\n\t// res = {nodeId, name}\n}\n</pre>\n</div>\n<div id='DOM_inlineStyleInvalidated' class='command'>\n<h3>DOM.inlineStyleInvalidated <span class='label label-info'>Event</span></h3>\n<p>Fired when <code>Element</code>'s inline style is modified via a CSS property modification.</p>\n<dl>\n<dt>nodeIds</dt>\n<dd>[<a href='#DOM.NodeId'>DOM.NodeId</a>] <span class='text'>Ids of the nodes for which the inline styles have been invalidated.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.inlineStyleInvalidated\nfunction onInlineStyleInvalidated(res) {\n\t// res = {nodeIds}\n}\n</pre>\n</div>\n<div id='DOM_characterDataModified' class='command'>\n<h3>DOM.characterDataModified <span class='label label-info'>Event</span></h3>\n<p>Mirrors <code>DOMCharacterDataModified</code> event.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node that has changed.</span></dd>\n<dt>characterData</dt>\n<dd>String <span class='text'>New text value.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.characterDataModified\nfunction onCharacterDataModified(res) {\n\t// res = {nodeId, characterData}\n}\n</pre>\n</div>\n<div id='DOM_childNodeCountUpdated' class='command'>\n<h3>DOM.childNodeCountUpdated <span class='label label-info'>Event</span></h3>\n<p>Fired when <code>Container</code>'s child node count has changed.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node that has changed.</span></dd>\n<dt>childNodeCount</dt>\n<dd>Integer <span class='text'>New node count.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.childNodeCountUpdated\nfunction onChildNodeCountUpdated(res) {\n\t// res = {nodeId, childNodeCount}\n}\n</pre>\n</div>\n<div id='DOM_childNodeInserted' class='command'>\n<h3>DOM.childNodeInserted <span class='label label-info'>Event</span></h3>\n<p>Mirrors <code>DOMNodeInserted</code> event.</p>\n<dl>\n<dt>parentNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node that has changed.</span></dd>\n<dt>previousNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>If of the previous siblint.</span></dd>\n<dt>node</dt>\n<dd><a href='#DOM.Node'>DOM.Node</a> <span class='text'>Inserted node data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.childNodeInserted\nfunction onChildNodeInserted(res) {\n\t// res = {parentNodeId, previousNodeId, node}\n}\n</pre>\n</div>\n<div id='DOM_childNodeRemoved' class='command'>\n<h3>DOM.childNodeRemoved <span class='label label-info'>Event</span></h3>\n<p>Mirrors <code>DOMNodeRemoved</code> event.</p>\n<dl>\n<dt>parentNodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Parent id.</span></dd>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Id of the node that has been removed.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.childNodeRemoved\nfunction onChildNodeRemoved(res) {\n\t// res = {parentNodeId, nodeId}\n}\n</pre>\n</div>\n<div id='DOM_shadowRootPushed' class='command'>\n<h3>DOM.shadowRootPushed <span class='label label-info'>Event</span></h3>\n<p>Called when shadow root is pushed into the element.</p>\n<dl>\n<dt>hostId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Host element id.</span></dd>\n<dt>root</dt>\n<dd><a href='#DOM.Node'>DOM.Node</a> <span class='text'>Shadow root.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.shadowRootPushed\nfunction onShadowRootPushed(res) {\n\t// res = {hostId, root}\n}\n</pre>\n</div>\n<div id='DOM_shadowRootPopped' class='command'>\n<h3>DOM.shadowRootPopped <span class='label label-info'>Event</span></h3>\n<p>Called when shadow root is popped from the element.</p>\n<dl>\n<dt>hostId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Host element id.</span></dd>\n<dt>rootId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Shadow root id.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.shadowRootPopped\nfunction onShadowRootPopped(res) {\n\t// res = {hostId, rootId}\n}\n</pre>\n</div>\n<div id='DOM_pseudoElementAdded' class='command'>\n<h3>DOM.pseudoElementAdded <span class='label label-info'>Event</span></h3>\n<p>Called when a pseudo element is added to an element.</p>\n<dl>\n<dt>parentId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Pseudo element's parent element id.</span></dd>\n<dt>pseudoElement</dt>\n<dd><a href='#DOM.Node'>DOM.Node</a> <span class='text'>The added pseudo element.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.pseudoElementAdded\nfunction onPseudoElementAdded(res) {\n\t// res = {parentId, pseudoElement}\n}\n</pre>\n</div>\n<div id='DOM_pseudoElementRemoved' class='command'>\n<h3>DOM.pseudoElementRemoved <span class='label label-info'>Event</span></h3>\n<p>Called when a pseudo element is removed from an element.</p>\n<dl>\n<dt>parentId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Pseudo element's parent element id.</span></dd>\n<dt>pseudoElementId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The removed pseudo element id.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOM.pseudoElementRemoved\nfunction onPseudoElementRemoved(res) {\n\t// res = {parentId, pseudoElementId}\n}\n</pre>\n</div>\n</section>\n<section id='DOMDebugger' class='domain'>\n<h1>DOMDebugger</h1>\n<p>DOM debugging allows setting breakpoints on particular DOM operations and events. JavaScript execution will stop on these operations as if there was a regular breakpoint set.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#DOMDebugger.DOMBreakpointType'>DOMDebugger.DOMBreakpointType</a>: DOM breakpoint type.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#DOMDebugger.setDOMBreakpoint'>DOMDebugger.setDOMBreakpoint</a>: Sets breakpoint on particular operation with DOM.</li>\n<li><a href='#DOMDebugger.removeDOMBreakpoint'>DOMDebugger.removeDOMBreakpoint</a>: Removes DOM breakpoint that was set using setDOMBreakpoint.</li>\n<li><a href='#DOMDebugger.setEventListenerBreakpoint'>DOMDebugger.setEventListenerBreakpoint</a>: Sets breakpoint on particular DOM event.</li>\n<li><a href='#DOMDebugger.removeEventListenerBreakpoint'>DOMDebugger.removeEventListenerBreakpoint</a>: Removes breakpoint on particular DOM event.</li>\n<li><a href='#DOMDebugger.setInstrumentationBreakpoint'>DOMDebugger.setInstrumentationBreakpoint</a>: Sets breakpoint on particular native event.</li>\n<li><a href='#DOMDebugger.removeInstrumentationBreakpoint'>DOMDebugger.removeInstrumentationBreakpoint</a>: Removes breakpoint on particular native event.</li>\n<li><a href='#DOMDebugger.setXHRBreakpoint'>DOMDebugger.setXHRBreakpoint</a>: Sets breakpoint on XMLHttpRequest.</li>\n<li><a href='#DOMDebugger.removeXHRBreakpoint'>DOMDebugger.removeXHRBreakpoint</a>: Removes breakpoint from XMLHttpRequest.</li>\n</ul>\n<div id='DOMDebugger_DOMBreakpointType' class='type'>\n<h3>DOMDebugger.DOMBreakpointType <span class='label'>Type</span></h3>\n<p>DOM breakpoint type.</p>\n<dl>\n<dd>( subtree-modified | attribute-modified | node-removed )</dd>\n</dl>\n</div>\n<div id='DOMDebugger_setDOMBreakpoint' class='command'>\n<h3>DOMDebugger.setDOMBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Sets breakpoint on particular operation with DOM.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Identifier of the node to set breakpoint on.</span></dd>\n<dt>type</dt>\n<dd><a href='#DOMDebugger.DOMBreakpointType'>DOMDebugger.DOMBreakpointType</a> <span class='text'>Type of the operation to stop upon.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.setDOMBreakpoint\nDOMDebugger.setDOMBreakpoint(nodeId, type);\n</pre>\n</div>\n<div id='DOMDebugger_removeDOMBreakpoint' class='command'>\n<h3>DOMDebugger.removeDOMBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Removes DOM breakpoint that was set using <code>setDOMBreakpoint</code>.</p>\n<dl>\n<dt>nodeId</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Identifier of the node to remove breakpoint from.</span></dd>\n<dt>type</dt>\n<dd><a href='#DOMDebugger.DOMBreakpointType'>DOMDebugger.DOMBreakpointType</a> <span class='text'>Type of the breakpoint to remove.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.removeDOMBreakpoint\nDOMDebugger.removeDOMBreakpoint(nodeId, type);\n</pre>\n</div>\n<div id='DOMDebugger_setEventListenerBreakpoint' class='command'>\n<h3>DOMDebugger.setEventListenerBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Sets breakpoint on particular DOM event.</p>\n<dl>\n<dt>eventName</dt>\n<dd>String <span class='text'>DOM Event name to stop on (any DOM event will do).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.setEventListenerBreakpoint\nDOMDebugger.setEventListenerBreakpoint(eventName);\n</pre>\n</div>\n<div id='DOMDebugger_removeEventListenerBreakpoint' class='command'>\n<h3>DOMDebugger.removeEventListenerBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Removes breakpoint on particular DOM event.</p>\n<dl>\n<dt>eventName</dt>\n<dd>String <span class='text'>Event name.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.removeEventListenerBreakpoint\nDOMDebugger.removeEventListenerBreakpoint(eventName);\n</pre>\n</div>\n<div id='DOMDebugger_setInstrumentationBreakpoint' class='command'>\n<h3>DOMDebugger.setInstrumentationBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Sets breakpoint on particular native event.</p>\n<dl>\n<dt>eventName</dt>\n<dd>String <span class='text'>Instrumentation name to stop on.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.setInstrumentationBreakpoint\nDOMDebugger.setInstrumentationBreakpoint(eventName);\n</pre>\n</div>\n<div id='DOMDebugger_removeInstrumentationBreakpoint' class='command'>\n<h3>DOMDebugger.removeInstrumentationBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Removes breakpoint on particular native event.</p>\n<dl>\n<dt>eventName</dt>\n<dd>String <span class='text'>Instrumentation name to stop on.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.removeInstrumentationBreakpoint\nDOMDebugger.removeInstrumentationBreakpoint(eventName);\n</pre>\n</div>\n<div id='DOMDebugger_setXHRBreakpoint' class='command'>\n<h3>DOMDebugger.setXHRBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Sets breakpoint on XMLHttpRequest.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Resource URL substring. All XHRs having this substring in the URL will get stopped upon.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.setXHRBreakpoint\nDOMDebugger.setXHRBreakpoint(url);\n</pre>\n</div>\n<div id='DOMDebugger_removeXHRBreakpoint' class='command'>\n<h3>DOMDebugger.removeXHRBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Removes breakpoint from XMLHttpRequest.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Resource URL substring.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMDebugger.removeXHRBreakpoint\nDOMDebugger.removeXHRBreakpoint(url);\n</pre>\n</div>\n</section>\n<section id='DOMStorage' class='domain'>\n<h1>DOMStorage</h1>\n<p>Query and modify DOM storage.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a>: DOM Storage identifier.</li>\n<li><a href='#DOMStorage.Item'>DOMStorage.Item</a>: DOM Storage item.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#DOMStorage.enable'>DOMStorage.enable</a>: Enables storage tracking, storage events will now be delivered to the client.</li>\n<li><a href='#DOMStorage.disable'>DOMStorage.disable</a>: Disables storage tracking, prevents storage events from being sent to the client.</li>\n<li><a href='#DOMStorage.getDOMStorageItems'>DOMStorage.getDOMStorageItems</a></li>\n<li><a href='#DOMStorage.setDOMStorageItem'>DOMStorage.setDOMStorageItem</a></li>\n<li><a href='#DOMStorage.removeDOMStorageItem'>DOMStorage.removeDOMStorageItem</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#DOMStorage.domStorageItemsCleared'>DOMStorage.domStorageItemsCleared</a></li>\n<li><a href='#DOMStorage.domStorageItemRemoved'>DOMStorage.domStorageItemRemoved</a></li>\n<li><a href='#DOMStorage.domStorageItemAdded'>DOMStorage.domStorageItemAdded</a></li>\n<li><a href='#DOMStorage.domStorageItemUpdated'>DOMStorage.domStorageItemUpdated</a></li>\n</ul>\n<div id='DOMStorage_StorageId' class='type'>\n<h3>DOMStorage.StorageId <span class='label'>Type</span></h3>\n<p>DOM Storage identifier.</p>\n<dl>\n<dt>securityOrigin</dt>\n<dd>String <span class='text'>Security origin for the storage.</span></dd>\n<dt>isLocalStorage</dt>\n<dd>Boolean <span class='text'>Whether the storage is local storage (not session storage).</span></dd>\n</dl>\n</div>\n<div id='DOMStorage_Item' class='type'>\n<h3>DOMStorage.Item <span class='label'>Type</span></h3>\n<p>DOM Storage item.</p>\n<dl>\n<dd>[String]</dd>\n</dl>\n</div>\n<div id='DOMStorage_enable' class='command'>\n<h3>DOMStorage.enable <span class='label label-success'>Command</span></h3>\n<p>Enables storage tracking, storage events will now be delivered to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMStorage.enable\nDOMStorage.enable();\n</pre>\n</div>\n<div id='DOMStorage_disable' class='command'>\n<h3>DOMStorage.disable <span class='label label-success'>Command</span></h3>\n<p>Disables storage tracking, prevents storage events from being sent to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMStorage.disable\nDOMStorage.disable();\n</pre>\n</div>\n<div id='DOMStorage_getDOMStorageItems' class='command'>\n<h3>DOMStorage.getDOMStorageItems <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>entries</dt>\n<dd>[<a href='#DOMStorage.Item'>DOMStorage.Item</a>]</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMStorage.getDOMStorageItems\nDOMStorage.getDOMStorageItems(storageId, function callback(res) {\n\t// res = {entries}\n});\n</pre>\n</div>\n<div id='DOMStorage_setDOMStorageItem' class='command'>\n<h3>DOMStorage.setDOMStorageItem <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n<dt>key</dt>\n<dd>String</dd>\n<dt>value</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMStorage.setDOMStorageItem\nDOMStorage.setDOMStorageItem(storageId, key, value);\n</pre>\n</div>\n<div id='DOMStorage_removeDOMStorageItem' class='command'>\n<h3>DOMStorage.removeDOMStorageItem <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n<dt>key</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: DOMStorage.removeDOMStorageItem\nDOMStorage.removeDOMStorageItem(storageId, key);\n</pre>\n</div>\n<div id='DOMStorage_domStorageItemsCleared' class='command'>\n<h3>DOMStorage.domStorageItemsCleared <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOMStorage.domStorageItemsCleared\nfunction onDomStorageItemsCleared(res) {\n\t// res = {storageId}\n}\n</pre>\n</div>\n<div id='DOMStorage_domStorageItemRemoved' class='command'>\n<h3>DOMStorage.domStorageItemRemoved <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n<dt>key</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOMStorage.domStorageItemRemoved\nfunction onDomStorageItemRemoved(res) {\n\t// res = {storageId, key}\n}\n</pre>\n</div>\n<div id='DOMStorage_domStorageItemAdded' class='command'>\n<h3>DOMStorage.domStorageItemAdded <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n<dt>key</dt>\n<dd>String</dd>\n<dt>newValue</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOMStorage.domStorageItemAdded\nfunction onDomStorageItemAdded(res) {\n\t// res = {storageId, key, newValue}\n}\n</pre>\n</div>\n<div id='DOMStorage_domStorageItemUpdated' class='command'>\n<h3>DOMStorage.domStorageItemUpdated <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>storageId</dt>\n<dd><a href='#DOMStorage.StorageId'>DOMStorage.StorageId</a></dd>\n<dt>key</dt>\n<dd>String</dd>\n<dt>oldValue</dt>\n<dd>String</dd>\n<dt>newValue</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: DOMStorage.domStorageItemUpdated\nfunction onDomStorageItemUpdated(res) {\n\t// res = {storageId, key, oldValue, newValue}\n}\n</pre>\n</div>\n</section>\n<section id='Database' class='domain'>\n<h1>Database</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Database.DatabaseId'>Database.DatabaseId</a>: Unique identifier of Database object.</li>\n<li><a href='#Database.Database'>Database.Database</a>: Database object.</li>\n<li><a href='#Database.Error'>Database.Error</a>: Database error.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Database.enable'>Database.enable</a>: Enables database tracking, database events will now be delivered to the client.</li>\n<li><a href='#Database.disable'>Database.disable</a>: Disables database tracking, prevents database events from being sent to the client.</li>\n<li><a href='#Database.getDatabaseTableNames'>Database.getDatabaseTableNames</a></li>\n<li><a href='#Database.executeSQL'>Database.executeSQL</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Database.addDatabase'>Database.addDatabase</a></li>\n</ul>\n<div id='Database_DatabaseId' class='type'>\n<h3>Database.DatabaseId <span class='label'>Type</span></h3>\n<p>Unique identifier of Database object.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Database_Database' class='type'>\n<h3>Database.Database <span class='label'>Type</span></h3>\n<p>Database object.</p>\n<dl>\n<dt>id</dt>\n<dd><a href='#Database.DatabaseId'>Database.DatabaseId</a> <span class='text'>Database ID.</span></dd>\n<dt>domain</dt>\n<dd>String <span class='text'>Database domain.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Database name.</span></dd>\n<dt>version</dt>\n<dd>String <span class='text'>Database version.</span></dd>\n</dl>\n</div>\n<div id='Database_Error' class='type'>\n<h3>Database.Error <span class='label'>Type</span></h3>\n<p>Database error.</p>\n<dl>\n<dt>message</dt>\n<dd>String <span class='text'>Error message.</span></dd>\n<dt>code</dt>\n<dd>Integer <span class='text'>Error code.</span></dd>\n</dl>\n</div>\n<div id='Database_enable' class='command'>\n<h3>Database.enable <span class='label label-success'>Command</span></h3>\n<p>Enables database tracking, database events will now be delivered to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Database.enable\nDatabase.enable();\n</pre>\n</div>\n<div id='Database_disable' class='command'>\n<h3>Database.disable <span class='label label-success'>Command</span></h3>\n<p>Disables database tracking, prevents database events from being sent to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Database.disable\nDatabase.disable();\n</pre>\n</div>\n<div id='Database_getDatabaseTableNames' class='command'>\n<h3>Database.getDatabaseTableNames <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>databaseId</dt>\n<dd><a href='#Database.DatabaseId'>Database.DatabaseId</a></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>tableNames</dt>\n<dd>[String]</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Database.getDatabaseTableNames\nDatabase.getDatabaseTableNames(databaseId, function callback(res) {\n\t// res = {tableNames}\n});\n</pre>\n</div>\n<div id='Database_executeSQL' class='command'>\n<h3>Database.executeSQL <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>databaseId</dt>\n<dd><a href='#Database.DatabaseId'>Database.DatabaseId</a></dd>\n<dt>query</dt>\n<dd>String</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>columnNames (optional)</dt>\n<dd>[String]</dd>\n<dt>values (optional)</dt>\n<dd>[Any]</dd>\n<dt>sqlError (optional)</dt>\n<dd><a href='#Database.Error'>Database.Error</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Database.executeSQL\nDatabase.executeSQL(databaseId, query, function callback(res) {\n\t// res = {columnNames, values, sqlError}\n});\n</pre>\n</div>\n<div id='Database_addDatabase' class='command'>\n<h3>Database.addDatabase <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>database</dt>\n<dd><a href='#Database.Database'>Database.Database</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Database.addDatabase\nfunction onAddDatabase(res) {\n\t// res = {database}\n}\n</pre>\n</div>\n</section>\n<section id='Debugger' class='domain'>\n<h1>Debugger</h1>\n<p>Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Debugger.BreakpointId'>Debugger.BreakpointId</a>: Breakpoint identifier.</li>\n<li><a href='#Debugger.ScriptId'>Debugger.ScriptId</a>: Unique script identifier.</li>\n<li><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a>: Call frame identifier.</li>\n<li><a href='#Debugger.Location'>Debugger.Location</a>: Location in the source code.</li>\n<li><a href='#Debugger.FunctionDetails'>Debugger.FunctionDetails</a>: Information about the function.</li>\n<li><a href='#Debugger.CallFrame'>Debugger.CallFrame</a>: JavaScript call frame. Array of call frames form the call stack.</li>\n<li><a href='#Debugger.Scope'>Debugger.Scope</a>: Scope description.</li>\n<li><a href='#Debugger.SetScriptSourceError'>Debugger.SetScriptSourceError</a>: Error data for setScriptSource command. compileError is a case type for uncompilable script source error.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Debugger.enable'>Debugger.enable</a>: Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received.</li>\n<li><a href='#Debugger.disable'>Debugger.disable</a>: Disables debugger for given page.</li>\n<li><a href='#Debugger.setBreakpointsActive'>Debugger.setBreakpointsActive</a>: Activates / deactivates all breakpoints on the page.</li>\n<li><a href='#Debugger.setSkipAllPauses'>Debugger.setSkipAllPauses</a>: Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc).</li>\n<li><a href='#Debugger.setBreakpointByUrl'>Debugger.setBreakpointByUrl</a>: Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in locations property. Further matching script parsing will result in subsequent breakpointResolved events issued. This logical breakpoint will survive page reloads.</li>\n<li><a href='#Debugger.setBreakpoint'>Debugger.setBreakpoint</a>: Sets JavaScript breakpoint at a given location.</li>\n<li><a href='#Debugger.removeBreakpoint'>Debugger.removeBreakpoint</a>: Removes JavaScript breakpoint.</li>\n<li><a href='#Debugger.continueToLocation'>Debugger.continueToLocation</a>: Continues execution until specific location is reached.</li>\n<li><a href='#Debugger.stepOver'>Debugger.stepOver</a>: Steps over the statement.</li>\n<li><a href='#Debugger.stepInto'>Debugger.stepInto</a>: Steps into the function call.</li>\n<li><a href='#Debugger.stepOut'>Debugger.stepOut</a>: Steps out of the function call.</li>\n<li><a href='#Debugger.pause'>Debugger.pause</a>: Stops on the next JavaScript statement.</li>\n<li><a href='#Debugger.resume'>Debugger.resume</a>: Resumes JavaScript execution.</li>\n<li><a href='#Debugger.searchInContent'>Debugger.searchInContent</a>: Searches for given string in script content.</li>\n<li><a href='#Debugger.canSetScriptSource'>Debugger.canSetScriptSource</a>: Always returns true.</li>\n<li><a href='#Debugger.setScriptSource'>Debugger.setScriptSource</a>: Edits JavaScript source live.</li>\n<li><a href='#Debugger.restartFrame'>Debugger.restartFrame</a>: Restarts particular call frame from the beginning.</li>\n<li><a href='#Debugger.getScriptSource'>Debugger.getScriptSource</a>: Returns source for the script with given id.</li>\n<li><a href='#Debugger.getFunctionDetails'>Debugger.getFunctionDetails</a>: Returns detailed informtation on given function.</li>\n<li><a href='#Debugger.setPauseOnExceptions'>Debugger.setPauseOnExceptions</a>: Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is none.</li>\n<li><a href='#Debugger.evaluateOnCallFrame'>Debugger.evaluateOnCallFrame</a>: Evaluates expression on a given call frame.</li>\n<li><a href='#Debugger.compileScript'>Debugger.compileScript</a>: Compiles expression.</li>\n<li><a href='#Debugger.runScript'>Debugger.runScript</a>: Runs script with given id in a given context.</li>\n<li><a href='#Debugger.setOverlayMessage'>Debugger.setOverlayMessage</a>: Sets overlay message.</li>\n<li><a href='#Debugger.setVariableValue'>Debugger.setVariableValue</a>: Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually.</li>\n<li><a href='#Debugger.getStepInPositions'>Debugger.getStepInPositions</a>: Lists all positions where step-in is possible for a current statement in a specified call frame</li>\n<li><a href='#Debugger.getBacktrace'>Debugger.getBacktrace</a>: Returns call stack including variables changed since VM was paused. VM must be paused.</li>\n<li><a href='#Debugger.skipStackFrames'>Debugger.skipStackFrames</a>: Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Debugger.globalObjectCleared'>Debugger.globalObjectCleared</a>: Called when global has been cleared and debugger client should reset its state. Happens upon navigation or reload.</li>\n<li><a href='#Debugger.scriptParsed'>Debugger.scriptParsed</a>: Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.</li>\n<li><a href='#Debugger.scriptFailedToParse'>Debugger.scriptFailedToParse</a>: Fired when virtual machine fails to parse the script.</li>\n<li><a href='#Debugger.breakpointResolved'>Debugger.breakpointResolved</a>: Fired when breakpoint is resolved to an actual script and location.</li>\n<li><a href='#Debugger.paused'>Debugger.paused</a>: Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.</li>\n<li><a href='#Debugger.resumed'>Debugger.resumed</a>: Fired when the virtual machine resumed execution.</li>\n</ul>\n<div id='Debugger_BreakpointId' class='type'>\n<h3>Debugger.BreakpointId <span class='label'>Type</span></h3>\n<p>Breakpoint identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Debugger_ScriptId' class='type'>\n<h3>Debugger.ScriptId <span class='label'>Type</span></h3>\n<p>Unique script identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Debugger_CallFrameId' class='type'>\n<h3>Debugger.CallFrameId <span class='label'>Type</span></h3>\n<p>Call frame identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Debugger_Location' class='type'>\n<h3>Debugger.Location <span class='label'>Type</span></h3>\n<p>Location in the source code.</p>\n<dl>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Script identifier as reported in the <code>Debugger.scriptParsed</code>.</span></dd>\n<dt>lineNumber</dt>\n<dd>Integer <span class='text'>Line number in the script (0-based).</span></dd>\n<dt>columnNumber (optional)</dt>\n<dd>Integer <span class='text'>Column number in the script (0-based).</span></dd>\n</dl>\n</div>\n<div id='Debugger_FunctionDetails' class='type'>\n<h3>Debugger.FunctionDetails <span class='label'>Type</span></h3>\n<p>Information about the function.</p>\n<dl>\n<dt>location</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Location of the function.</span></dd>\n<dt>name (optional)</dt>\n<dd>String <span class='text'>Name of the function. Not present for anonymous functions.</span></dd>\n<dt>displayName (optional)</dt>\n<dd>String <span class='text'>Display name of the function(specified in 'displayName' property on the function object).</span></dd>\n<dt>inferredName (optional)</dt>\n<dd>String <span class='text'>Name of the function inferred from its initial assignment.</span></dd>\n<dt>scopeChain (optional)</dt>\n<dd>[<a href='#Debugger.Scope'>Debugger.Scope</a>] <span class='text'>Scope chain for this closure.</span></dd>\n</dl>\n</div>\n<div id='Debugger_CallFrame' class='type'>\n<h3>Debugger.CallFrame <span class='label'>Type</span></h3>\n<p>JavaScript call frame. Array of call frames form the call stack.</p>\n<dl>\n<dt>callFrameId</dt>\n<dd><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a> <span class='text'>Call frame identifier. This identifier is only valid while the virtual machine is paused.</span></dd>\n<dt>functionName</dt>\n<dd>String <span class='text'>Name of the JavaScript function called on this call frame.</span></dd>\n<dt>location</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Location in the source code.</span></dd>\n<dt>scopeChain</dt>\n<dd>[<a href='#Debugger.Scope'>Debugger.Scope</a>] <span class='text'>Scope chain for this call frame.</span></dd>\n<dt>this</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'><code>this</code> object for this call frame.</span></dd>\n</dl>\n</div>\n<div id='Debugger_Scope' class='type'>\n<h3>Debugger.Scope <span class='label'>Type</span></h3>\n<p>Scope description.</p>\n<dl>\n<dt>type</dt>\n<dd>( global | local | with | closure | catch ) <span class='text'>Scope type.</span></dd>\n<dt>object</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties.</span></dd>\n</dl>\n</div>\n<div id='Debugger_SetScriptSourceError' class='type'>\n<h3>Debugger.SetScriptSourceError <span class='label'>Type</span></h3>\n<p>Error data for setScriptSource command. compileError is a case type for uncompilable script source error.</p>\n<dl>\n<dt>compileError (optional)</dt>\n<dd>Object</dd>\n</dl>\n</div>\n<div id='Debugger_enable' class='command'>\n<h3>Debugger.enable <span class='label label-success'>Command</span></h3>\n<p>Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.enable\nDebugger.enable();\n</pre>\n</div>\n<div id='Debugger_disable' class='command'>\n<h3>Debugger.disable <span class='label label-success'>Command</span></h3>\n<p>Disables debugger for given page.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.disable\nDebugger.disable();\n</pre>\n</div>\n<div id='Debugger_setBreakpointsActive' class='command'>\n<h3>Debugger.setBreakpointsActive <span class='label label-success'>Command</span></h3>\n<p>Activates / deactivates all breakpoints on the page.</p>\n<dl>\n<dt>active</dt>\n<dd>Boolean <span class='text'>New value for breakpoints active state.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setBreakpointsActive\nDebugger.setBreakpointsActive(active);\n</pre>\n</div>\n<div id='Debugger_setSkipAllPauses' class='command'>\n<h3>Debugger.setSkipAllPauses <span class='label label-success'>Command</span></h3>\n<p>Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc).</p>\n<dl>\n<dt>skipped</dt>\n<dd>Boolean <span class='text'>New value for skip pauses state.</span></dd>\n<dt>untilReload (optional)</dt>\n<dd>Boolean <span class='text'>Whether page reload should set skipped to false.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setSkipAllPauses\nDebugger.setSkipAllPauses(skipped, untilReload);\n</pre>\n</div>\n<div id='Debugger_setBreakpointByUrl' class='command'>\n<h3>Debugger.setBreakpointByUrl <span class='label label-success'>Command</span></h3>\n<p>Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in <code>locations</code> property. Further matching script parsing will result in subsequent <code>breakpointResolved</code> events issued. This logical breakpoint will survive page reloads.</p>\n<dl>\n<dt>lineNumber</dt>\n<dd>Integer <span class='text'>Line number to set breakpoint at.</span></dd>\n<dt>url (optional)</dt>\n<dd>String <span class='text'>URL of the resources to set breakpoint on.</span></dd>\n<dt>urlRegex (optional)</dt>\n<dd>String <span class='text'>Regex pattern for the URLs of the resources to set breakpoints on. Either <code>url</code> or <code>urlRegex</code> must be specified.</span></dd>\n<dt>columnNumber (optional)</dt>\n<dd>Integer <span class='text'>Offset in the line to set breakpoint at.</span></dd>\n<dt>condition (optional)</dt>\n<dd>String <span class='text'>Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true.</span></dd>\n<dt>isAntibreakpoint (optional)</dt>\n<dd>Boolean <span class='text'>Creates pseudo-breakpoint that prevents debugger from pausing on exception at this location.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>breakpointId</dt>\n<dd><a href='#Debugger.BreakpointId'>Debugger.BreakpointId</a> <span class='text'>Id of the created breakpoint for further reference.</span></dd>\n<dt>locations</dt>\n<dd>[<a href='#Debugger.Location'>Debugger.Location</a>] <span class='text'>List of the locations this breakpoint resolved into upon addition.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setBreakpointByUrl\nDebugger.setBreakpointByUrl(lineNumber, url, urlRegex, columnNumber, condition, isAntibreakpoint, function callback(res) {\n\t// res = {breakpointId, locations}\n});\n</pre>\n</div>\n<div id='Debugger_setBreakpoint' class='command'>\n<h3>Debugger.setBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Sets JavaScript breakpoint at a given location.</p>\n<dl>\n<dt>location</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Location to set breakpoint in.</span></dd>\n<dt>condition (optional)</dt>\n<dd>String <span class='text'>Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>breakpointId</dt>\n<dd><a href='#Debugger.BreakpointId'>Debugger.BreakpointId</a> <span class='text'>Id of the created breakpoint for further reference.</span></dd>\n<dt>actualLocation</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Location this breakpoint resolved into.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setBreakpoint\nDebugger.setBreakpoint(location, condition, function callback(res) {\n\t// res = {breakpointId, actualLocation}\n});\n</pre>\n</div>\n<div id='Debugger_removeBreakpoint' class='command'>\n<h3>Debugger.removeBreakpoint <span class='label label-success'>Command</span></h3>\n<p>Removes JavaScript breakpoint.</p>\n<dl>\n<dt>breakpointId</dt>\n<dd><a href='#Debugger.BreakpointId'>Debugger.BreakpointId</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.removeBreakpoint\nDebugger.removeBreakpoint(breakpointId);\n</pre>\n</div>\n<div id='Debugger_continueToLocation' class='command'>\n<h3>Debugger.continueToLocation <span class='label label-success'>Command</span></h3>\n<p>Continues execution until specific location is reached.</p>\n<dl>\n<dt>location</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Location to continue to.</span></dd>\n<dt>interstatementLocation (optional)</dt>\n<dd>Boolean <span class='text'>Allows breakpoints at the intemediate positions inside statements.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.continueToLocation\nDebugger.continueToLocation(location, interstatementLocation);\n</pre>\n</div>\n<div id='Debugger_stepOver' class='command'>\n<h3>Debugger.stepOver <span class='label label-success'>Command</span></h3>\n<p>Steps over the statement.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.stepOver\nDebugger.stepOver();\n</pre>\n</div>\n<div id='Debugger_stepInto' class='command'>\n<h3>Debugger.stepInto <span class='label label-success'>Command</span></h3>\n<p>Steps into the function call.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.stepInto\nDebugger.stepInto();\n</pre>\n</div>\n<div id='Debugger_stepOut' class='command'>\n<h3>Debugger.stepOut <span class='label label-success'>Command</span></h3>\n<p>Steps out of the function call.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.stepOut\nDebugger.stepOut();\n</pre>\n</div>\n<div id='Debugger_pause' class='command'>\n<h3>Debugger.pause <span class='label label-success'>Command</span></h3>\n<p>Stops on the next JavaScript statement.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.pause\nDebugger.pause();\n</pre>\n</div>\n<div id='Debugger_resume' class='command'>\n<h3>Debugger.resume <span class='label label-success'>Command</span></h3>\n<p>Resumes JavaScript execution.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.resume\nDebugger.resume();\n</pre>\n</div>\n<div id='Debugger_searchInContent' class='command'>\n<h3>Debugger.searchInContent <span class='label label-success'>Command</span></h3>\n<p>Searches for given string in script content.</p>\n<dl>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Id of the script to search in.</span></dd>\n<dt>query</dt>\n<dd>String <span class='text'>String to search for.</span></dd>\n<dt>caseSensitive (optional)</dt>\n<dd>Boolean <span class='text'>If true, search is case sensitive.</span></dd>\n<dt>isRegex (optional)</dt>\n<dd>Boolean <span class='text'>If true, treats string parameter as regex.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>[<a href='#Page.SearchMatch'>Page.SearchMatch</a>] <span class='text'>List of search matches.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.searchInContent\nDebugger.searchInContent(scriptId, query, caseSensitive, isRegex, function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Debugger_canSetScriptSource' class='command'>\n<h3>Debugger.canSetScriptSource <span class='label label-success'>Command</span></h3>\n<p>Always returns true.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>Boolean <span class='text'>True if <code>setScriptSource</code> is supported.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.canSetScriptSource\nDebugger.canSetScriptSource(function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Debugger_setScriptSource' class='command'>\n<h3>Debugger.setScriptSource <span class='label label-success'>Command</span></h3>\n<p>Edits JavaScript source live.</p>\n<dl>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Id of the script to edit.</span></dd>\n<dt>scriptSource</dt>\n<dd>String <span class='text'>New content of the script.</span></dd>\n<dt>preview (optional)</dt>\n<dd>Boolean <span class='text'> If true the change will not actually be applied. Preview mode may be used to get result description without actually modifying the code.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>callFrames (optional)</dt>\n<dd>[<a href='#Debugger.CallFrame'>Debugger.CallFrame</a>] <span class='text'>New stack trace in case editing has happened while VM was stopped.</span></dd>\n<dt>result (optional)</dt>\n<dd>Object <span class='text'>VM-specific description of the changes applied.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setScriptSource\nDebugger.setScriptSource(scriptId, scriptSource, preview, function callback(res) {\n\t// res = {callFrames, result}\n});\n</pre>\n</div>\n<div id='Debugger_restartFrame' class='command'>\n<h3>Debugger.restartFrame <span class='label label-success'>Command</span></h3>\n<p>Restarts particular call frame from the beginning.</p>\n<dl>\n<dt>callFrameId</dt>\n<dd><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a> <span class='text'>Call frame identifier to evaluate on.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>callFrames</dt>\n<dd>[<a href='#Debugger.CallFrame'>Debugger.CallFrame</a>] <span class='text'>New stack trace.</span></dd>\n<dt>result</dt>\n<dd>Object <span class='text'>VM-specific description.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.restartFrame\nDebugger.restartFrame(callFrameId, function callback(res) {\n\t// res = {callFrames, result}\n});\n</pre>\n</div>\n<div id='Debugger_getScriptSource' class='command'>\n<h3>Debugger.getScriptSource <span class='label label-success'>Command</span></h3>\n<p>Returns source for the script with given id.</p>\n<dl>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Id of the script to get source for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>scriptSource</dt>\n<dd>String <span class='text'>Script source.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.getScriptSource\nDebugger.getScriptSource(scriptId, function callback(res) {\n\t// res = {scriptSource}\n});\n</pre>\n</div>\n<div id='Debugger_getFunctionDetails' class='command'>\n<h3>Debugger.getFunctionDetails <span class='label label-success'>Command</span></h3>\n<p>Returns detailed informtation on given function.</p>\n<dl>\n<dt>functionId</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Id of the function to get location for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>details</dt>\n<dd><a href='#Debugger.FunctionDetails'>Debugger.FunctionDetails</a> <span class='text'>Information about the function.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.getFunctionDetails\nDebugger.getFunctionDetails(functionId, function callback(res) {\n\t// res = {details}\n});\n</pre>\n</div>\n<div id='Debugger_setPauseOnExceptions' class='command'>\n<h3>Debugger.setPauseOnExceptions <span class='label label-success'>Command</span></h3>\n<p>Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is <code>none</code>.</p>\n<dl>\n<dt>state</dt>\n<dd>( none | uncaught | all ) <span class='text'>Pause on exceptions mode.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setPauseOnExceptions\nDebugger.setPauseOnExceptions(state);\n</pre>\n</div>\n<div id='Debugger_evaluateOnCallFrame' class='command'>\n<h3>Debugger.evaluateOnCallFrame <span class='label label-success'>Command</span></h3>\n<p>Evaluates expression on a given call frame.</p>\n<dl>\n<dt>callFrameId</dt>\n<dd><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a> <span class='text'>Call frame identifier to evaluate on.</span></dd>\n<dt>expression</dt>\n<dd>String <span class='text'>Expression to evaluate.</span></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>String object group name to put result into (allows rapid releasing resulting object handles using <code>releaseObjectGroup</code>).</span></dd>\n<dt>includeCommandLineAPI (optional)</dt>\n<dd>Boolean <span class='text'>Specifies whether command line API should be available to the evaluated expression, defaults to false.</span></dd>\n<dt>doNotPauseOnExceptionsAndMuteConsole (optional)</dt>\n<dd>Boolean <span class='text'>Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.</span></dd>\n<dt>returnByValue (optional)</dt>\n<dd>Boolean <span class='text'>Whether the result is expected to be a JSON object that should be sent by value.</span></dd>\n<dt>generatePreview (optional)</dt>\n<dd>Boolean <span class='text'>Whether preview should be generated for the result.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Object wrapper for the evaluation result.</span></dd>\n<dt>wasThrown (optional)</dt>\n<dd>Boolean <span class='text'>True if the result was thrown during the evaluation.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.evaluateOnCallFrame\nDebugger.evaluateOnCallFrame(callFrameId, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, function callback(res) {\n\t// res = {result, wasThrown}\n});\n</pre>\n</div>\n<div id='Debugger_compileScript' class='command'>\n<h3>Debugger.compileScript <span class='label label-success'>Command</span></h3>\n<p>Compiles expression.</p>\n<dl>\n<dt>expression</dt>\n<dd>String <span class='text'>Expression to compile.</span></dd>\n<dt>sourceURL</dt>\n<dd>String <span class='text'>Source url to be set for the script.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>scriptId (optional)</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Id of the script.</span></dd>\n<dt>syntaxErrorMessage (optional)</dt>\n<dd>String <span class='text'>Syntax error message if compilation failed.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.compileScript\nDebugger.compileScript(expression, sourceURL, function callback(res) {\n\t// res = {scriptId, syntaxErrorMessage}\n});\n</pre>\n</div>\n<div id='Debugger_runScript' class='command'>\n<h3>Debugger.runScript <span class='label label-success'>Command</span></h3>\n<p>Runs script with given id in a given context.</p>\n<dl>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Id of the script to run.</span></dd>\n<dt>contextId (optional)</dt>\n<dd><a href='#Runtime.ExecutionContextId'>Runtime.ExecutionContextId</a> <span class='text'>Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page.</span></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>Symbolic group name that can be used to release multiple objects.</span></dd>\n<dt>doNotPauseOnExceptionsAndMuteConsole (optional)</dt>\n<dd>Boolean <span class='text'>Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Run result.</span></dd>\n<dt>wasThrown (optional)</dt>\n<dd>Boolean <span class='text'>True if the result was thrown during the script run.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.runScript\nDebugger.runScript(scriptId, contextId, objectGroup, doNotPauseOnExceptionsAndMuteConsole, function callback(res) {\n\t// res = {result, wasThrown}\n});\n</pre>\n</div>\n<div id='Debugger_setOverlayMessage' class='command'>\n<h3>Debugger.setOverlayMessage <span class='label label-success'>Command</span></h3>\n<p>Sets overlay message.</p>\n<dl>\n<dt>message (optional)</dt>\n<dd>String <span class='text'>Overlay message to display when paused in debugger.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setOverlayMessage\nDebugger.setOverlayMessage(message);\n</pre>\n</div>\n<div id='Debugger_setVariableValue' class='command'>\n<h3>Debugger.setVariableValue <span class='label label-success'>Command</span></h3>\n<p>Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually.</p>\n<dl>\n<dt>scopeNumber</dt>\n<dd>Integer <span class='text'>0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually.</span></dd>\n<dt>variableName</dt>\n<dd>String <span class='text'>Variable name.</span></dd>\n<dt>newValue</dt>\n<dd><a href='#Runtime.CallArgument'>Runtime.CallArgument</a> <span class='text'>New variable value.</span></dd>\n<dt>callFrameId (optional)</dt>\n<dd><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a> <span class='text'>Id of callframe that holds variable.</span></dd>\n<dt>functionObjectId (optional)</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Object id of closure (function) that holds variable.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.setVariableValue\nDebugger.setVariableValue(scopeNumber, variableName, newValue, callFrameId, functionObjectId);\n</pre>\n</div>\n<div id='Debugger_getStepInPositions' class='command'>\n<h3>Debugger.getStepInPositions <span class='label label-success'>Command</span></h3>\n<p>Lists all positions where step-in is possible for a current statement in a specified call frame</p>\n<dl>\n<dt>callFrameId</dt>\n<dd><a href='#Debugger.CallFrameId'>Debugger.CallFrameId</a> <span class='text'>Id of a call frame where the current statement should be analized</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>stepInPositions (optional)</dt>\n<dd>[<a href='#Debugger.Location'>Debugger.Location</a>] <span class='text'>experimental</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.getStepInPositions\nDebugger.getStepInPositions(callFrameId, function callback(res) {\n\t// res = {stepInPositions}\n});\n</pre>\n</div>\n<div id='Debugger_getBacktrace' class='command'>\n<h3>Debugger.getBacktrace <span class='label label-success'>Command</span></h3>\n<p>Returns call stack including variables changed since VM was paused. VM must be paused.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>callFrames</dt>\n<dd>[<a href='#Debugger.CallFrame'>Debugger.CallFrame</a>] <span class='text'>Call stack the virtual machine stopped on.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.getBacktrace\nDebugger.getBacktrace(function callback(res) {\n\t// res = {callFrames}\n});\n</pre>\n</div>\n<div id='Debugger_skipStackFrames' class='command'>\n<h3>Debugger.skipStackFrames <span class='label label-success'>Command</span></h3>\n<p>Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful.</p>\n<dl>\n<dt>script (optional)</dt>\n<dd>String <span class='text'>Regular expression defining the scripts to ignore while stepping.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Debugger.skipStackFrames\nDebugger.skipStackFrames(script);\n</pre>\n</div>\n<div id='Debugger_globalObjectCleared' class='command'>\n<h3>Debugger.globalObjectCleared <span class='label label-info'>Event</span></h3>\n<p>Called when global has been cleared and debugger client should reset its state. Happens upon navigation or reload.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Debugger.globalObjectCleared\nfunction onGlobalObjectCleared(res) {\n\t// res = {}\n}\n</pre>\n</div>\n<div id='Debugger_scriptParsed' class='command'>\n<h3>Debugger.scriptParsed <span class='label label-info'>Event</span></h3>\n<p>Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger.</p>\n<dl>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Identifier of the script parsed.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL or name of the script parsed (if any).</span></dd>\n<dt>startLine</dt>\n<dd>Integer <span class='text'>Line offset of the script within the resource with given URL (for script tags).</span></dd>\n<dt>startColumn</dt>\n<dd>Integer <span class='text'>Column offset of the script within the resource with given URL.</span></dd>\n<dt>endLine</dt>\n<dd>Integer <span class='text'>Last line of the script.</span></dd>\n<dt>endColumn</dt>\n<dd>Integer <span class='text'>Length of the last line of the script.</span></dd>\n<dt>isContentScript (optional)</dt>\n<dd>Boolean <span class='text'>Determines whether this script is a user extension script.</span></dd>\n<dt>sourceMapURL (optional)</dt>\n<dd>String <span class='text'>URL of source map associated with script (if any).</span></dd>\n<dt>hasSourceURL (optional)</dt>\n<dd>Boolean <span class='text'>True, if this script has sourceURL.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Debugger.scriptParsed\nfunction onScriptParsed(res) {\n\t// res = {scriptId, url, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL, hasSourceURL}\n}\n</pre>\n</div>\n<div id='Debugger_scriptFailedToParse' class='command'>\n<h3>Debugger.scriptFailedToParse <span class='label label-info'>Event</span></h3>\n<p>Fired when virtual machine fails to parse the script.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the script that failed to parse.</span></dd>\n<dt>scriptSource</dt>\n<dd>String <span class='text'>Source text of the script that failed to parse.</span></dd>\n<dt>startLine</dt>\n<dd>Integer <span class='text'>Line offset of the script within the resource.</span></dd>\n<dt>errorLine</dt>\n<dd>Integer <span class='text'>Line with error.</span></dd>\n<dt>errorMessage</dt>\n<dd>String <span class='text'>Parse error message.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Debugger.scriptFailedToParse\nfunction onScriptFailedToParse(res) {\n\t// res = {url, scriptSource, startLine, errorLine, errorMessage}\n}\n</pre>\n</div>\n<div id='Debugger_breakpointResolved' class='command'>\n<h3>Debugger.breakpointResolved <span class='label label-info'>Event</span></h3>\n<p>Fired when breakpoint is resolved to an actual script and location.</p>\n<dl>\n<dt>breakpointId</dt>\n<dd><a href='#Debugger.BreakpointId'>Debugger.BreakpointId</a> <span class='text'>Breakpoint unique identifier.</span></dd>\n<dt>location</dt>\n<dd><a href='#Debugger.Location'>Debugger.Location</a> <span class='text'>Actual breakpoint location.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Debugger.breakpointResolved\nfunction onBreakpointResolved(res) {\n\t// res = {breakpointId, location}\n}\n</pre>\n</div>\n<div id='Debugger_paused' class='command'>\n<h3>Debugger.paused <span class='label label-info'>Event</span></h3>\n<p>Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.</p>\n<dl>\n<dt>callFrames</dt>\n<dd>[<a href='#Debugger.CallFrame'>Debugger.CallFrame</a>] <span class='text'>Call stack the virtual machine stopped on.</span></dd>\n<dt>reason</dt>\n<dd>( XHR | DOM | EventListener | exception | assert | CSPViolation | debugCommand | other ) <span class='text'>Pause reason.</span></dd>\n<dt>data (optional)</dt>\n<dd>Object <span class='text'>Object containing break-specific auxiliary properties.</span></dd>\n<dt>hitBreakpoints (optional)</dt>\n<dd>[String] <span class='text'>Hit breakpoints IDs</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Debugger.paused\nfunction onPaused(res) {\n\t// res = {callFrames, reason, data, hitBreakpoints}\n}\n</pre>\n</div>\n<div id='Debugger_resumed' class='command'>\n<h3>Debugger.resumed <span class='label label-info'>Event</span></h3>\n<p>Fired when the virtual machine resumed execution.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Debugger.resumed\nfunction onResumed(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n<section id='FileSystem' class='domain'>\n<h1>FileSystem</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#FileSystem.Entry'>FileSystem.Entry</a>: Represents a browser side file or directory.</li>\n<li><a href='#FileSystem.Metadata'>FileSystem.Metadata</a>: Represents metadata of a file or entry.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#FileSystem.enable'>FileSystem.enable</a>: Enables events from backend.</li>\n<li><a href='#FileSystem.disable'>FileSystem.disable</a>: Disables events from backend.</li>\n<li><a href='#FileSystem.requestFileSystemRoot'>FileSystem.requestFileSystemRoot</a>: Returns root directory of the FileSystem, if exists.</li>\n<li><a href='#FileSystem.requestDirectoryContent'>FileSystem.requestDirectoryContent</a>: Returns content of the directory.</li>\n<li><a href='#FileSystem.requestMetadata'>FileSystem.requestMetadata</a>: Returns metadata of the entry.</li>\n<li><a href='#FileSystem.requestFileContent'>FileSystem.requestFileContent</a>: Returns content of the file. Result should be sliced into [start, end).</li>\n<li><a href='#FileSystem.deleteEntry'>FileSystem.deleteEntry</a>: Deletes specified entry. If the entry is a directory, the agent deletes children recursively.</li>\n</ul>\n<div id='FileSystem_Entry' class='type'>\n<h3>FileSystem.Entry <span class='label'>Type</span></h3>\n<p>Represents a browser side file or directory.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>filesystem: URL for the entry.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>The name of the file or directory.</span></dd>\n<dt>isDirectory</dt>\n<dd>Boolean <span class='text'>True if the entry is a directory.</span></dd>\n<dt>mimeType (optional)</dt>\n<dd>String <span class='text'>MIME type of the entry, available for a file only.</span></dd>\n<dt>resourceType (optional)</dt>\n<dd><a href='#Page.ResourceType'>Page.ResourceType</a> <span class='text'>ResourceType of the entry, available for a file only.</span></dd>\n<dt>isTextFile (optional)</dt>\n<dd>Boolean <span class='text'>True if the entry is a text file.</span></dd>\n</dl>\n</div>\n<div id='FileSystem_Metadata' class='type'>\n<h3>FileSystem.Metadata <span class='label'>Type</span></h3>\n<p>Represents metadata of a file or entry.</p>\n<dl>\n<dt>modificationTime</dt>\n<dd>Number <span class='text'>Modification time.</span></dd>\n<dt>size</dt>\n<dd>Number <span class='text'>File size. This field is always zero for directories.</span></dd>\n</dl>\n</div>\n<div id='FileSystem_enable' class='command'>\n<h3>FileSystem.enable <span class='label label-success'>Command</span></h3>\n<p>Enables events from backend.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.enable\nFileSystem.enable();\n</pre>\n</div>\n<div id='FileSystem_disable' class='command'>\n<h3>FileSystem.disable <span class='label label-success'>Command</span></h3>\n<p>Disables events from backend.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.disable\nFileSystem.disable();\n</pre>\n</div>\n<div id='FileSystem_requestFileSystemRoot' class='command'>\n<h3>FileSystem.requestFileSystemRoot <span class='label label-success'>Command</span></h3>\n<p>Returns root directory of the FileSystem, if exists.</p>\n<dl>\n<dt>origin</dt>\n<dd>String <span class='text'>Security origin of requesting FileSystem. One of frames in current page needs to have this security origin.</span></dd>\n<dt>type</dt>\n<dd>( temporary | persistent ) <span class='text'>FileSystem type of requesting FileSystem.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>errorCode</dt>\n<dd>Integer <span class='text'>0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.</span></dd>\n<dt>root (optional)</dt>\n<dd><a href='#FileSystem.Entry'>FileSystem.Entry</a> <span class='text'>Contains root of the requested FileSystem if the command completed successfully.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.requestFileSystemRoot\nFileSystem.requestFileSystemRoot(origin, type, function callback(res) {\n\t// res = {errorCode, root}\n});\n</pre>\n</div>\n<div id='FileSystem_requestDirectoryContent' class='command'>\n<h3>FileSystem.requestDirectoryContent <span class='label label-success'>Command</span></h3>\n<p>Returns content of the directory.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the directory that the frontend is requesting to read from.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>errorCode</dt>\n<dd>Integer <span class='text'>0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.</span></dd>\n<dt>entries (optional)</dt>\n<dd>[<a href='#FileSystem.Entry'>FileSystem.Entry</a>] <span class='text'>Contains all entries on directory if the command completed successfully.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.requestDirectoryContent\nFileSystem.requestDirectoryContent(url, function callback(res) {\n\t// res = {errorCode, entries}\n});\n</pre>\n</div>\n<div id='FileSystem_requestMetadata' class='command'>\n<h3>FileSystem.requestMetadata <span class='label label-success'>Command</span></h3>\n<p>Returns metadata of the entry.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the entry that the frontend is requesting to get metadata from.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>errorCode</dt>\n<dd>Integer <span class='text'>0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.</span></dd>\n<dt>metadata (optional)</dt>\n<dd><a href='#FileSystem.Metadata'>FileSystem.Metadata</a> <span class='text'>Contains metadata of the entry if the command completed successfully.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.requestMetadata\nFileSystem.requestMetadata(url, function callback(res) {\n\t// res = {errorCode, metadata}\n});\n</pre>\n</div>\n<div id='FileSystem_requestFileContent' class='command'>\n<h3>FileSystem.requestFileContent <span class='label label-success'>Command</span></h3>\n<p>Returns content of the file. Result should be sliced into [start, end).</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the file that the frontend is requesting to read from.</span></dd>\n<dt>readAsText</dt>\n<dd>Boolean <span class='text'>True if the content should be read as text, otherwise the result will be returned as base64 encoded text.</span></dd>\n<dt>start (optional)</dt>\n<dd>Integer <span class='text'>Specifies the start of range to read.</span></dd>\n<dt>end (optional)</dt>\n<dd>Integer <span class='text'>Specifies the end of range to read exclusively.</span></dd>\n<dt>charset (optional)</dt>\n<dd>String <span class='text'>Overrides charset of the content when content is served as text.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>errorCode</dt>\n<dd>Integer <span class='text'>0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value.</span></dd>\n<dt>content (optional)</dt>\n<dd>String <span class='text'>Content of the file.</span></dd>\n<dt>charset (optional)</dt>\n<dd>String <span class='text'>Charset of the content if it is served as text.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.requestFileContent\nFileSystem.requestFileContent(url, readAsText, start, end, charset, function callback(res) {\n\t// res = {errorCode, content, charset}\n});\n</pre>\n</div>\n<div id='FileSystem_deleteEntry' class='command'>\n<h3>FileSystem.deleteEntry <span class='label label-success'>Command</span></h3>\n<p>Deletes specified entry. If the entry is a directory, the agent deletes children recursively.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the entry to delete.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>errorCode</dt>\n<dd>Integer <span class='text'>0, if no error. Otherwise errorCode is set to FileError::ErrorCode value.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: FileSystem.deleteEntry\nFileSystem.deleteEntry(url, function callback(res) {\n\t// res = {errorCode}\n});\n</pre>\n</div>\n</section>\n<section id='HeapProfiler' class='domain'>\n<h1>HeapProfiler</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#HeapProfiler.ProfileHeader'>HeapProfiler.ProfileHeader</a>: Profile header.</li>\n<li><a href='#HeapProfiler.HeapSnapshotObjectId'>HeapProfiler.HeapSnapshotObjectId</a>: Heap snashot object id.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#HeapProfiler.getProfileHeaders'>HeapProfiler.getProfileHeaders</a></li>\n<li><a href='#HeapProfiler.startTrackingHeapObjects'>HeapProfiler.startTrackingHeapObjects</a></li>\n<li><a href='#HeapProfiler.stopTrackingHeapObjects'>HeapProfiler.stopTrackingHeapObjects</a></li>\n<li><a href='#HeapProfiler.getHeapSnapshot'>HeapProfiler.getHeapSnapshot</a></li>\n<li><a href='#HeapProfiler.removeProfile'>HeapProfiler.removeProfile</a></li>\n<li><a href='#HeapProfiler.clearProfiles'>HeapProfiler.clearProfiles</a></li>\n<li><a href='#HeapProfiler.takeHeapSnapshot'>HeapProfiler.takeHeapSnapshot</a></li>\n<li><a href='#HeapProfiler.collectGarbage'>HeapProfiler.collectGarbage</a></li>\n<li><a href='#HeapProfiler.getObjectByHeapObjectId'>HeapProfiler.getObjectByHeapObjectId</a></li>\n<li><a href='#HeapProfiler.getHeapObjectId'>HeapProfiler.getHeapObjectId</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#HeapProfiler.addProfileHeader'>HeapProfiler.addProfileHeader</a></li>\n<li><a href='#HeapProfiler.addHeapSnapshotChunk'>HeapProfiler.addHeapSnapshotChunk</a></li>\n<li><a href='#HeapProfiler.finishHeapSnapshot'>HeapProfiler.finishHeapSnapshot</a></li>\n<li><a href='#HeapProfiler.resetProfiles'>HeapProfiler.resetProfiles</a></li>\n<li><a href='#HeapProfiler.reportHeapSnapshotProgress'>HeapProfiler.reportHeapSnapshotProgress</a></li>\n<li><a href='#HeapProfiler.lastSeenObjectId'>HeapProfiler.lastSeenObjectId</a>: If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.</li>\n<li><a href='#HeapProfiler.heapStatsUpdate'>HeapProfiler.heapStatsUpdate</a>: If heap objects tracking has been started then backend may send update for one or more fragments</li>\n</ul>\n<div id='HeapProfiler_ProfileHeader' class='type'>\n<h3>HeapProfiler.ProfileHeader <span class='label'>Type</span></h3>\n<p>Profile header.</p>\n<dl>\n<dt>title</dt>\n<dd>String <span class='text'>Profile title.</span></dd>\n<dt>uid</dt>\n<dd>Integer <span class='text'>Unique identifier of the profile.</span></dd>\n<dt>maxJSObjectId (optional)</dt>\n<dd>Integer <span class='text'>Last seen JS object Id.</span></dd>\n</dl>\n</div>\n<div id='HeapProfiler_HeapSnapshotObjectId' class='type'>\n<h3>HeapProfiler.HeapSnapshotObjectId <span class='label'>Type</span></h3>\n<p>Heap snashot object id.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='HeapProfiler_getProfileHeaders' class='command'>\n<h3>HeapProfiler.getProfileHeaders <span class='label label-success'>Command</span></h3>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>headers</dt>\n<dd>[<a href='#HeapProfiler.ProfileHeader'>HeapProfiler.ProfileHeader</a>]</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.getProfileHeaders\nHeapProfiler.getProfileHeaders(function callback(res) {\n\t// res = {headers}\n});\n</pre>\n</div>\n<div id='HeapProfiler_startTrackingHeapObjects' class='command'>\n<h3>HeapProfiler.startTrackingHeapObjects <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.startTrackingHeapObjects\nHeapProfiler.startTrackingHeapObjects();\n</pre>\n</div>\n<div id='HeapProfiler_stopTrackingHeapObjects' class='command'>\n<h3>HeapProfiler.stopTrackingHeapObjects <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.stopTrackingHeapObjects\nHeapProfiler.stopTrackingHeapObjects();\n</pre>\n</div>\n<div id='HeapProfiler_getHeapSnapshot' class='command'>\n<h3>HeapProfiler.getHeapSnapshot <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>uid</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.getHeapSnapshot\nHeapProfiler.getHeapSnapshot(uid);\n</pre>\n</div>\n<div id='HeapProfiler_removeProfile' class='command'>\n<h3>HeapProfiler.removeProfile <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>uid</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.removeProfile\nHeapProfiler.removeProfile(uid);\n</pre>\n</div>\n<div id='HeapProfiler_clearProfiles' class='command'>\n<h3>HeapProfiler.clearProfiles <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.clearProfiles\nHeapProfiler.clearProfiles();\n</pre>\n</div>\n<div id='HeapProfiler_takeHeapSnapshot' class='command'>\n<h3>HeapProfiler.takeHeapSnapshot <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>reportProgress (optional)</dt>\n<dd>Boolean <span class='text'>If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.takeHeapSnapshot\nHeapProfiler.takeHeapSnapshot(reportProgress);\n</pre>\n</div>\n<div id='HeapProfiler_collectGarbage' class='command'>\n<h3>HeapProfiler.collectGarbage <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.collectGarbage\nHeapProfiler.collectGarbage();\n</pre>\n</div>\n<div id='HeapProfiler_getObjectByHeapObjectId' class='command'>\n<h3>HeapProfiler.getObjectByHeapObjectId <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>objectId</dt>\n<dd><a href='#HeapProfiler.HeapSnapshotObjectId'>HeapProfiler.HeapSnapshotObjectId</a></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>Symbolic group name that can be used to release multiple objects.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Evaluation result.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.getObjectByHeapObjectId\nHeapProfiler.getObjectByHeapObjectId(objectId, objectGroup, function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='HeapProfiler_getHeapObjectId' class='command'>\n<h3>HeapProfiler.getHeapObjectId <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>objectId</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Identifier of the object to get heap object id for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>heapSnapshotObjectId</dt>\n<dd><a href='#HeapProfiler.HeapSnapshotObjectId'>HeapProfiler.HeapSnapshotObjectId</a> <span class='text'>Id of the heap snapshot object corresponding to the passed remote object id.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: HeapProfiler.getHeapObjectId\nHeapProfiler.getHeapObjectId(objectId, function callback(res) {\n\t// res = {heapSnapshotObjectId}\n});\n</pre>\n</div>\n<div id='HeapProfiler_addProfileHeader' class='command'>\n<h3>HeapProfiler.addProfileHeader <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>header</dt>\n<dd><a href='#HeapProfiler.ProfileHeader'>HeapProfiler.ProfileHeader</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.addProfileHeader\nfunction onAddProfileHeader(res) {\n\t// res = {header}\n}\n</pre>\n</div>\n<div id='HeapProfiler_addHeapSnapshotChunk' class='command'>\n<h3>HeapProfiler.addHeapSnapshotChunk <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>uid</dt>\n<dd>Integer</dd>\n<dt>chunk</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.addHeapSnapshotChunk\nfunction onAddHeapSnapshotChunk(res) {\n\t// res = {uid, chunk}\n}\n</pre>\n</div>\n<div id='HeapProfiler_finishHeapSnapshot' class='command'>\n<h3>HeapProfiler.finishHeapSnapshot <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>uid</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.finishHeapSnapshot\nfunction onFinishHeapSnapshot(res) {\n\t// res = {uid}\n}\n</pre>\n</div>\n<div id='HeapProfiler_resetProfiles' class='command'>\n<h3>HeapProfiler.resetProfiles <span class='label label-info'>Event</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.resetProfiles\nfunction onResetProfiles(res) {\n\t// res = {}\n}\n</pre>\n</div>\n<div id='HeapProfiler_reportHeapSnapshotProgress' class='command'>\n<h3>HeapProfiler.reportHeapSnapshotProgress <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>done</dt>\n<dd>Integer</dd>\n<dt>total</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.reportHeapSnapshotProgress\nfunction onReportHeapSnapshotProgress(res) {\n\t// res = {done, total}\n}\n</pre>\n</div>\n<div id='HeapProfiler_lastSeenObjectId' class='command'>\n<h3>HeapProfiler.lastSeenObjectId <span class='label label-info'>Event</span></h3>\n<p>If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.</p>\n<dl>\n<dt>lastSeenObjectId</dt>\n<dd>Integer</dd>\n<dt>timestamp</dt>\n<dd>Number</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.lastSeenObjectId\nfunction onLastSeenObjectId(res) {\n\t// res = {lastSeenObjectId, timestamp}\n}\n</pre>\n</div>\n<div id='HeapProfiler_heapStatsUpdate' class='command'>\n<h3>HeapProfiler.heapStatsUpdate <span class='label label-info'>Event</span></h3>\n<p>If heap objects tracking has been started then backend may send update for one or more fragments</p>\n<dl>\n<dt>statsUpdate</dt>\n<dd>[Integer] <span class='text'>An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: HeapProfiler.heapStatsUpdate\nfunction onHeapStatsUpdate(res) {\n\t// res = {statsUpdate}\n}\n</pre>\n</div>\n</section>\n<section id='IndexedDB' class='domain'>\n<h1>IndexedDB</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#IndexedDB.DatabaseWithObjectStores'>IndexedDB.DatabaseWithObjectStores</a>: Database with an array of object stores.</li>\n<li><a href='#IndexedDB.ObjectStore'>IndexedDB.ObjectStore</a>: Object store.</li>\n<li><a href='#IndexedDB.ObjectStoreIndex'>IndexedDB.ObjectStoreIndex</a>: Object store index.</li>\n<li><a href='#IndexedDB.Key'>IndexedDB.Key</a>: Key.</li>\n<li><a href='#IndexedDB.KeyRange'>IndexedDB.KeyRange</a>: Key range.</li>\n<li><a href='#IndexedDB.DataEntry'>IndexedDB.DataEntry</a>: Data entry.</li>\n<li><a href='#IndexedDB.KeyPath'>IndexedDB.KeyPath</a>: Key path.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#IndexedDB.enable'>IndexedDB.enable</a>: Enables events from backend.</li>\n<li><a href='#IndexedDB.disable'>IndexedDB.disable</a>: Disables events from backend.</li>\n<li><a href='#IndexedDB.requestDatabaseNames'>IndexedDB.requestDatabaseNames</a>: Requests database names for given security origin.</li>\n<li><a href='#IndexedDB.requestDatabase'>IndexedDB.requestDatabase</a>: Requests database with given name in given frame.</li>\n<li><a href='#IndexedDB.requestData'>IndexedDB.requestData</a>: Requests data from object store or index.</li>\n<li><a href='#IndexedDB.clearObjectStore'>IndexedDB.clearObjectStore</a>: Clears all entries from an object store.</li>\n</ul>\n<div id='IndexedDB_DatabaseWithObjectStores' class='type'>\n<h3>IndexedDB.DatabaseWithObjectStores <span class='label'>Type</span></h3>\n<p>Database with an array of object stores.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Database name.</span></dd>\n<dt>version</dt>\n<dd>String <span class='text'>Deprecated string database version.</span></dd>\n<dt>intVersion</dt>\n<dd>Integer <span class='text'>Integer database version.</span></dd>\n<dt>objectStores</dt>\n<dd>[<a href='#IndexedDB.ObjectStore'>IndexedDB.ObjectStore</a>] <span class='text'>Object stores in this database.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_ObjectStore' class='type'>\n<h3>IndexedDB.ObjectStore <span class='label'>Type</span></h3>\n<p>Object store.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Object store name.</span></dd>\n<dt>keyPath</dt>\n<dd><a href='#IndexedDB.KeyPath'>IndexedDB.KeyPath</a> <span class='text'>Object store key path.</span></dd>\n<dt>autoIncrement</dt>\n<dd>Boolean <span class='text'>If true, object store has auto increment flag set.</span></dd>\n<dt>indexes</dt>\n<dd>[<a href='#IndexedDB.ObjectStoreIndex'>IndexedDB.ObjectStoreIndex</a>] <span class='text'>Indexes in this object store.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_ObjectStoreIndex' class='type'>\n<h3>IndexedDB.ObjectStoreIndex <span class='label'>Type</span></h3>\n<p>Object store index.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Index name.</span></dd>\n<dt>keyPath</dt>\n<dd><a href='#IndexedDB.KeyPath'>IndexedDB.KeyPath</a> <span class='text'>Index key path.</span></dd>\n<dt>unique</dt>\n<dd>Boolean <span class='text'>If true, index is unique.</span></dd>\n<dt>multiEntry</dt>\n<dd>Boolean <span class='text'>If true, index allows multiple entries for a key.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_Key' class='type'>\n<h3>IndexedDB.Key <span class='label'>Type</span></h3>\n<p>Key.</p>\n<dl>\n<dt>type</dt>\n<dd>( number | string | date | array ) <span class='text'>Key type.</span></dd>\n<dt>number (optional)</dt>\n<dd>Number <span class='text'>Number value.</span></dd>\n<dt>string (optional)</dt>\n<dd>String <span class='text'>String value.</span></dd>\n<dt>date (optional)</dt>\n<dd>Number <span class='text'>Date value.</span></dd>\n<dt>array (optional)</dt>\n<dd>[<a href='#IndexedDB.Key'>IndexedDB.Key</a>] <span class='text'>Array value.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_KeyRange' class='type'>\n<h3>IndexedDB.KeyRange <span class='label'>Type</span></h3>\n<p>Key range.</p>\n<dl>\n<dt>lower (optional)</dt>\n<dd><a href='#IndexedDB.Key'>IndexedDB.Key</a> <span class='text'>Lower bound.</span></dd>\n<dt>upper (optional)</dt>\n<dd><a href='#IndexedDB.Key'>IndexedDB.Key</a> <span class='text'>Upper bound.</span></dd>\n<dt>lowerOpen</dt>\n<dd>Boolean <span class='text'>If true lower bound is open.</span></dd>\n<dt>upperOpen</dt>\n<dd>Boolean <span class='text'>If true upper bound is open.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_DataEntry' class='type'>\n<h3>IndexedDB.DataEntry <span class='label'>Type</span></h3>\n<p>Data entry.</p>\n<dl>\n<dt>key</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Key.</span></dd>\n<dt>primaryKey</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Primary key.</span></dd>\n<dt>value</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Value.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_KeyPath' class='type'>\n<h3>IndexedDB.KeyPath <span class='label'>Type</span></h3>\n<p>Key path.</p>\n<dl>\n<dt>type</dt>\n<dd>( null | string | array ) <span class='text'>Key path type.</span></dd>\n<dt>string (optional)</dt>\n<dd>String <span class='text'>String value.</span></dd>\n<dt>array (optional)</dt>\n<dd>[String] <span class='text'>Array value.</span></dd>\n</dl>\n</div>\n<div id='IndexedDB_enable' class='command'>\n<h3>IndexedDB.enable <span class='label label-success'>Command</span></h3>\n<p>Enables events from backend.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: IndexedDB.enable\nIndexedDB.enable();\n</pre>\n</div>\n<div id='IndexedDB_disable' class='command'>\n<h3>IndexedDB.disable <span class='label label-success'>Command</span></h3>\n<p>Disables events from backend.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: IndexedDB.disable\nIndexedDB.disable();\n</pre>\n</div>\n<div id='IndexedDB_requestDatabaseNames' class='command'>\n<h3>IndexedDB.requestDatabaseNames <span class='label label-success'>Command</span></h3>\n<p>Requests database names for given security origin.</p>\n<dl>\n<dt>securityOrigin</dt>\n<dd>String <span class='text'>Security origin.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>databaseNames</dt>\n<dd>[String] <span class='text'>Database names for origin.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: IndexedDB.requestDatabaseNames\nIndexedDB.requestDatabaseNames(securityOrigin, function callback(res) {\n\t// res = {databaseNames}\n});\n</pre>\n</div>\n<div id='IndexedDB_requestDatabase' class='command'>\n<h3>IndexedDB.requestDatabase <span class='label label-success'>Command</span></h3>\n<p>Requests database with given name in given frame.</p>\n<dl>\n<dt>securityOrigin</dt>\n<dd>String <span class='text'>Security origin.</span></dd>\n<dt>databaseName</dt>\n<dd>String <span class='text'>Database name.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>databaseWithObjectStores</dt>\n<dd><a href='#IndexedDB.DatabaseWithObjectStores'>IndexedDB.DatabaseWithObjectStores</a> <span class='text'>Database with an array of object stores.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: IndexedDB.requestDatabase\nIndexedDB.requestDatabase(securityOrigin, databaseName, function callback(res) {\n\t// res = {databaseWithObjectStores}\n});\n</pre>\n</div>\n<div id='IndexedDB_requestData' class='command'>\n<h3>IndexedDB.requestData <span class='label label-success'>Command</span></h3>\n<p>Requests data from object store or index.</p>\n<dl>\n<dt>securityOrigin</dt>\n<dd>String <span class='text'>Security origin.</span></dd>\n<dt>databaseName</dt>\n<dd>String <span class='text'>Database name.</span></dd>\n<dt>objectStoreName</dt>\n<dd>String <span class='text'>Object store name.</span></dd>\n<dt>indexName</dt>\n<dd>String <span class='text'>Index name, empty string for object store data requests.</span></dd>\n<dt>skipCount</dt>\n<dd>Integer <span class='text'>Number of records to skip.</span></dd>\n<dt>pageSize</dt>\n<dd>Integer <span class='text'>Number of records to fetch.</span></dd>\n<dt>keyRange (optional)</dt>\n<dd><a href='#IndexedDB.KeyRange'>IndexedDB.KeyRange</a> <span class='text'>Key range.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>objectStoreDataEntries</dt>\n<dd>[<a href='#IndexedDB.DataEntry'>IndexedDB.DataEntry</a>] <span class='text'>Array of object store data entries.</span></dd>\n<dt>hasMore</dt>\n<dd>Boolean <span class='text'>If true, there are more entries to fetch in the given range.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: IndexedDB.requestData\nIndexedDB.requestData(securityOrigin, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange, function callback(res) {\n\t// res = {objectStoreDataEntries, hasMore}\n});\n</pre>\n</div>\n<div id='IndexedDB_clearObjectStore' class='command'>\n<h3>IndexedDB.clearObjectStore <span class='label label-success'>Command</span></h3>\n<p>Clears all entries from an object store.</p>\n<dl>\n<dt>securityOrigin</dt>\n<dd>String <span class='text'>Security origin.</span></dd>\n<dt>databaseName</dt>\n<dd>String <span class='text'>Database name.</span></dd>\n<dt>objectStoreName</dt>\n<dd>String <span class='text'>Object store name.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: IndexedDB.clearObjectStore\nIndexedDB.clearObjectStore(securityOrigin, databaseName, objectStoreName, function callback(res) {\n\t// res = {}\n});\n</pre>\n</div>\n</section>\n<section id='Input' class='domain'>\n<h1>Input</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Input.TouchPoint'>Input.TouchPoint</a></li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Input.dispatchKeyEvent'>Input.dispatchKeyEvent</a>: Dispatches a key event to the page.</li>\n<li><a href='#Input.dispatchMouseEvent'>Input.dispatchMouseEvent</a>: Dispatches a mouse event to the page.</li>\n<li><a href='#Input.dispatchTouchEvent'>Input.dispatchTouchEvent</a>: Dispatches a touch event to the page.</li>\n<li><a href='#Input.dispatchGestureEvent'>Input.dispatchGestureEvent</a>: Dispatches a gesture event to the page.</li>\n</ul>\n<div id='Input_TouchPoint' class='type'>\n<h3>Input.TouchPoint <span class='label'>Type</span></h3>\n<dl>\n<dt>state</dt>\n<dd>( touchPressed | touchReleased | touchMoved | touchStationary | touchCancelled ) <span class='text'>State of the touch point.</span></dd>\n<dt>x</dt>\n<dd>Integer <span class='text'>X coordinate of the event relative to the main frame's viewport.</span></dd>\n<dt>y</dt>\n<dd>Integer <span class='text'>Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport.</span></dd>\n<dt>radiusX (optional)</dt>\n<dd>Integer <span class='text'>X radius of the touch area (default: 1).</span></dd>\n<dt>radiusY (optional)</dt>\n<dd>Integer <span class='text'>Y radius of the touch area (default: 1).</span></dd>\n<dt>rotationAngle (optional)</dt>\n<dd>Number <span class='text'>Rotation angle (default: 0.0).</span></dd>\n<dt>force (optional)</dt>\n<dd>Number <span class='text'>Force (default: 1.0).</span></dd>\n<dt>id (optional)</dt>\n<dd>Number <span class='text'>Identifier used to track touch sources between events, must be unique within an event.</span></dd>\n</dl>\n</div>\n<div id='Input_dispatchKeyEvent' class='command'>\n<h3>Input.dispatchKeyEvent <span class='label label-success'>Command</span></h3>\n<p>Dispatches a key event to the page.</p>\n<dl>\n<dt>type</dt>\n<dd>( keyDown | keyUp | rawKeyDown | char ) <span class='text'>Type of the key event.</span></dd>\n<dt>modifiers (optional)</dt>\n<dd>Integer <span class='text'>Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).</span></dd>\n<dt>timestamp (optional)</dt>\n<dd>Number <span class='text'>Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).</span></dd>\n<dt>text (optional)</dt>\n<dd>String <span class='text'>Text as generated by processing a virtual key code with a keyboard layout. Not needed for for <code>keyUp</code> and <code>rawKeyDown</code> events (default: \"\")</span></dd>\n<dt>unmodifiedText (optional)</dt>\n<dd>String <span class='text'>Text that would have been generated by the keyboard if no modifiers were pressed (except for shift). Useful for shortcut (accelerator) key handling (default: \"\").</span></dd>\n<dt>keyIdentifier (optional)</dt>\n<dd>String <span class='text'>Unique key identifier (e.g., 'U+0041') (default: \"\").</span></dd>\n<dt>windowsVirtualKeyCode (optional)</dt>\n<dd>Integer <span class='text'>Windows virtual key code (default: 0).</span></dd>\n<dt>nativeVirtualKeyCode (optional)</dt>\n<dd>Integer <span class='text'>Native virtual key code (default: 0).</span></dd>\n<dt>macCharCode (optional)</dt>\n<dd>Integer <span class='text'>Mac character code (default: 0).</span></dd>\n<dt>autoRepeat (optional)</dt>\n<dd>Boolean <span class='text'>Whether the event was generated from auto repeat (default: false).</span></dd>\n<dt>isKeypad (optional)</dt>\n<dd>Boolean <span class='text'>Whether the event was generated from the keypad (default: false).</span></dd>\n<dt>isSystemKey (optional)</dt>\n<dd>Boolean <span class='text'>Whether the event was a system key event (default: false).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Input.dispatchKeyEvent\nInput.dispatchKeyEvent(type, modifiers, timestamp, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, isKeypad, isSystemKey);\n</pre>\n</div>\n<div id='Input_dispatchMouseEvent' class='command'>\n<h3>Input.dispatchMouseEvent <span class='label label-success'>Command</span></h3>\n<p>Dispatches a mouse event to the page.</p>\n<dl>\n<dt>type</dt>\n<dd>( mousePressed | mouseReleased | mouseMoved ) <span class='text'>Type of the mouse event.</span></dd>\n<dt>x</dt>\n<dd>Integer <span class='text'>X coordinate of the event relative to the main frame's viewport.</span></dd>\n<dt>y</dt>\n<dd>Integer <span class='text'>Y coordinate of the event relative to the main frame's viewport. 0 refers to the top of the viewport and Y increases as it proceeds towards the bottom of the viewport.</span></dd>\n<dt>modifiers (optional)</dt>\n<dd>Integer <span class='text'>Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).</span></dd>\n<dt>timestamp (optional)</dt>\n<dd>Number <span class='text'>Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).</span></dd>\n<dt>button (optional)</dt>\n<dd>( none | left | middle | right ) <span class='text'>Mouse button (default: \"none\").</span></dd>\n<dt>clickCount (optional)</dt>\n<dd>Integer <span class='text'>Number of times the mouse button was clicked (default: 0).</span></dd>\n<dt>deviceSpace (optional)</dt>\n<dd>Boolean <span class='text'>If true, x and y are given in dip wrt current viewport.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Input.dispatchMouseEvent\nInput.dispatchMouseEvent(type, x, y, modifiers, timestamp, button, clickCount, deviceSpace);\n</pre>\n</div>\n<div id='Input_dispatchTouchEvent' class='command'>\n<h3>Input.dispatchTouchEvent <span class='label label-success'>Command</span></h3>\n<p>Dispatches a touch event to the page.</p>\n<dl>\n<dt>type</dt>\n<dd>( touchStart | touchEnd | touchMove ) <span class='text'>Type of the touch event.</span></dd>\n<dt>touchPoints</dt>\n<dd>[<a href='#Input.TouchPoint'>Input.TouchPoint</a>] <span class='text'>Touch points.</span></dd>\n<dt>modifiers (optional)</dt>\n<dd>Integer <span class='text'>Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).</span></dd>\n<dt>timestamp (optional)</dt>\n<dd>Number <span class='text'>Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Input.dispatchTouchEvent\nInput.dispatchTouchEvent(type, touchPoints, modifiers, timestamp);\n</pre>\n</div>\n<div id='Input_dispatchGestureEvent' class='command'>\n<h3>Input.dispatchGestureEvent <span class='label label-success'>Command</span></h3>\n<p>Dispatches a gesture event to the page.</p>\n<dl>\n<dt>type</dt>\n<dd>( scrollBegin | scrollEnd | scrollUpdate | tapDown | tap | pinchBegin | pinchEnd | pinchUpdate ) <span class='text'>Type of the gesture event.</span></dd>\n<dt>x</dt>\n<dd>Integer <span class='text'>X coordinate relative to the screen's viewport.</span></dd>\n<dt>y</dt>\n<dd>Integer <span class='text'>Y coordinate relative to the screen's viewport.</span></dd>\n<dt>timestamp (optional)</dt>\n<dd>Number <span class='text'>Time at which the event occurred. Measured in UTC time in seconds since January 1, 1970 (default: current time).</span></dd>\n<dt>deltaX (optional)</dt>\n<dd>Integer <span class='text'>Delta X where apllies.</span></dd>\n<dt>deltaY (optional)</dt>\n<dd>Integer <span class='text'>Delta Y where apllies.</span></dd>\n<dt>pinchScale (optional)</dt>\n<dd>Number <span class='text'>Pinch scale.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Input.dispatchGestureEvent\nInput.dispatchGestureEvent(type, x, y, timestamp, deltaX, deltaY, pinchScale);\n</pre>\n</div>\n</section>\n<section id='Inspector' class='domain'>\n<h1>Inspector</h1>\n<p></p>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Inspector.enable'>Inspector.enable</a>: Enables inspector domain notifications.</li>\n<li><a href='#Inspector.disable'>Inspector.disable</a>: Disables inspector domain notifications.</li>\n<li><a href='#Inspector.reset'>Inspector.reset</a>: Resets all domains.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Inspector.evaluateForTestInFrontend'>Inspector.evaluateForTestInFrontend</a></li>\n<li><a href='#Inspector.inspect'>Inspector.inspect</a></li>\n<li><a href='#Inspector.detached'>Inspector.detached</a>: Fired when remote debugging connection is about to be terminated. Contains detach reason.</li>\n<li><a href='#Inspector.targetCrashed'>Inspector.targetCrashed</a>: Fired when debugging target has crashed</li>\n</ul>\n<div id='Inspector_enable' class='command'>\n<h3>Inspector.enable <span class='label label-success'>Command</span></h3>\n<p>Enables inspector domain notifications.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Inspector.enable\nInspector.enable();\n</pre>\n</div>\n<div id='Inspector_disable' class='command'>\n<h3>Inspector.disable <span class='label label-success'>Command</span></h3>\n<p>Disables inspector domain notifications.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Inspector.disable\nInspector.disable();\n</pre>\n</div>\n<div id='Inspector_reset' class='command'>\n<h3>Inspector.reset <span class='label label-success'>Command</span></h3>\n<p>Resets all domains.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Inspector.reset\nInspector.reset();\n</pre>\n</div>\n<div id='Inspector_evaluateForTestInFrontend' class='command'>\n<h3>Inspector.evaluateForTestInFrontend <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>testCallId</dt>\n<dd>Integer</dd>\n<dt>script</dt>\n<dd>String</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Inspector.evaluateForTestInFrontend\nfunction onEvaluateForTestInFrontend(res) {\n\t// res = {testCallId, script}\n}\n</pre>\n</div>\n<div id='Inspector_inspect' class='command'>\n<h3>Inspector.inspect <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>object</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a></dd>\n<dt>hints</dt>\n<dd>Object</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Inspector.inspect\nfunction onInspect(res) {\n\t// res = {object, hints}\n}\n</pre>\n</div>\n<div id='Inspector_detached' class='command'>\n<h3>Inspector.detached <span class='label label-info'>Event</span></h3>\n<p>Fired when remote debugging connection is about to be terminated. Contains detach reason.</p>\n<dl>\n<dt>reason</dt>\n<dd>String <span class='text'>The reason why connection has been terminated.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Inspector.detached\nfunction onDetached(res) {\n\t// res = {reason}\n}\n</pre>\n</div>\n<div id='Inspector_targetCrashed' class='command'>\n<h3>Inspector.targetCrashed <span class='label label-info'>Event</span></h3>\n<p>Fired when debugging target has crashed</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Inspector.targetCrashed\nfunction onTargetCrashed(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n<section id='LayerTree' class='domain'>\n<h1>LayerTree</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#LayerTree.LayerId'>LayerTree.LayerId</a>: Unique RenderLayer identifier.</li>\n<li><a href='#LayerTree.Layer'>LayerTree.Layer</a>: Information about a compositing layer.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#LayerTree.enable'>LayerTree.enable</a>: Enables compositing tree inspection.</li>\n<li><a href='#LayerTree.disable'>LayerTree.disable</a>: Disables compositing tree inspection.</li>\n<li><a href='#LayerTree.getLayers'>LayerTree.getLayers</a>: Returns the layer tree structure of the current page.</li>\n<li><a href='#LayerTree.compositingReasons'>LayerTree.compositingReasons</a>: Provides the reasons why the given layer was composited.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#LayerTree.layerTreeDidChange'>LayerTree.layerTreeDidChange</a></li>\n</ul>\n<div id='LayerTree_LayerId' class='type'>\n<h3>LayerTree.LayerId <span class='label'>Type</span></h3>\n<p>Unique RenderLayer identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='LayerTree_Layer' class='type'>\n<h3>LayerTree.Layer <span class='label'>Type</span></h3>\n<p>Information about a compositing layer.</p>\n<dl>\n<dt>layerId</dt>\n<dd><a href='#LayerTree.LayerId'>LayerTree.LayerId</a> <span class='text'>The unique id for this layer.</span></dd>\n<dt>parentLayerId (optional)</dt>\n<dd><a href='#LayerTree.LayerId'>LayerTree.LayerId</a> <span class='text'>The id of parent (not present for root).</span></dd>\n<dt>nodeId (optional)</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>The id for the node associated with this layer.</span></dd>\n<dt>offsetX</dt>\n<dd>Number <span class='text'>Offset from parent layer, X coordinate.</span></dd>\n<dt>offsetY</dt>\n<dd>Number <span class='text'>Offset from parent layer, X coordinate.</span></dd>\n<dt>width</dt>\n<dd>Number <span class='text'>Layer width.</span></dd>\n<dt>height</dt>\n<dd>Number <span class='text'>Layer height.</span></dd>\n<dt>transform (optional)</dt>\n<dd>[Number] <span class='text'>Transformation matrix for layer, default is identity matrix</span></dd>\n<dt>anchorX (optional)</dt>\n<dd>Number <span class='text'>Transform anchor point X, absent if no transform specified</span></dd>\n<dt>anchorY (optional)</dt>\n<dd>Number <span class='text'>Transform anchor point Y, absent if no transform specified</span></dd>\n<dt>anchorZ (optional)</dt>\n<dd>Number <span class='text'>Transform anchor point Z, absent if no transform specified</span></dd>\n<dt>paintCount</dt>\n<dd>Integer <span class='text'>Indicates how many time this layer has painted.</span></dd>\n<dt>invisible (optional)</dt>\n<dd>Boolean <span class='text'>Set if layer is not visible.</span></dd>\n</dl>\n</div>\n<div id='LayerTree_enable' class='command'>\n<h3>LayerTree.enable <span class='label label-success'>Command</span></h3>\n<p>Enables compositing tree inspection.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: LayerTree.enable\nLayerTree.enable();\n</pre>\n</div>\n<div id='LayerTree_disable' class='command'>\n<h3>LayerTree.disable <span class='label label-success'>Command</span></h3>\n<p>Disables compositing tree inspection.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: LayerTree.disable\nLayerTree.disable();\n</pre>\n</div>\n<div id='LayerTree_getLayers' class='command'>\n<h3>LayerTree.getLayers <span class='label label-success'>Command</span></h3>\n<p>Returns the layer tree structure of the current page.</p>\n<dl>\n<dt>nodeId (optional)</dt>\n<dd><a href='#DOM.NodeId'>DOM.NodeId</a> <span class='text'>Root of the subtree for which we want to gather layers (return entire tree if not specified)</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>layers</dt>\n<dd>[<a href='#LayerTree.Layer'>LayerTree.Layer</a>] <span class='text'>Child layers.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: LayerTree.getLayers\nLayerTree.getLayers(nodeId, function callback(res) {\n\t// res = {layers}\n});\n</pre>\n</div>\n<div id='LayerTree_compositingReasons' class='command'>\n<h3>LayerTree.compositingReasons <span class='label label-success'>Command</span></h3>\n<p>Provides the reasons why the given layer was composited.</p>\n<dl>\n<dt>layerId</dt>\n<dd><a href='#LayerTree.LayerId'>LayerTree.LayerId</a> <span class='text'>The id of the layer for which we want to get the reasons it was composited.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>compositingReasons</dt>\n<dd>[String] <span class='text'>A list of strings specifying reasons for the given layer to become composited.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: LayerTree.compositingReasons\nLayerTree.compositingReasons(layerId, function callback(res) {\n\t// res = {compositingReasons}\n});\n</pre>\n</div>\n<div id='LayerTree_layerTreeDidChange' class='command'>\n<h3>LayerTree.layerTreeDidChange <span class='label label-info'>Event</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: LayerTree.layerTreeDidChange\nfunction onLayerTreeDidChange(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n<section id='Memory' class='domain'>\n<h1>Memory</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Memory.MemoryBlock'>Memory.MemoryBlock</a></li>\n<li><a href='#Memory.HeapSnapshotChunk'>Memory.HeapSnapshotChunk</a></li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Memory.getDOMCounters'>Memory.getDOMCounters</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Memory.addNativeSnapshotChunk'>Memory.addNativeSnapshotChunk</a></li>\n</ul>\n<div id='Memory_MemoryBlock' class='type'>\n<h3>Memory.MemoryBlock <span class='label'>Type</span></h3>\n<dl>\n<dt>size (optional)</dt>\n<dd>Number <span class='text'>Size of the block in bytes if available</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Unique name used to identify the component that allocated this block</span></dd>\n<dt>children (optional)</dt>\n<dd>[<a href='#Memory.MemoryBlock'>Memory.MemoryBlock</a>]</dd>\n</dl>\n</div>\n<div id='Memory_HeapSnapshotChunk' class='type'>\n<h3>Memory.HeapSnapshotChunk <span class='label'>Type</span></h3>\n<dl>\n<dt>strings</dt>\n<dd>[String] <span class='text'>An array of strings that were found since last update.</span></dd>\n<dt>nodes</dt>\n<dd>[Integer] <span class='text'>An array of nodes that were found since last update.</span></dd>\n<dt>edges</dt>\n<dd>[Integer] <span class='text'>An array of edges that were found since last update.</span></dd>\n<dt>baseToRealNodeId</dt>\n<dd>[Integer] <span class='text'>An array of integers for nodeId remapping. Even nodeId has to be mapped to the following odd nodeId.</span></dd>\n</dl>\n</div>\n<div id='Memory_getDOMCounters' class='command'>\n<h3>Memory.getDOMCounters <span class='label label-success'>Command</span></h3>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>documents</dt>\n<dd>Integer</dd>\n<dt>nodes</dt>\n<dd>Integer</dd>\n<dt>jsEventListeners</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Memory.getDOMCounters\nMemory.getDOMCounters(function callback(res) {\n\t// res = {documents, nodes, jsEventListeners}\n});\n</pre>\n</div>\n<div id='Memory_addNativeSnapshotChunk' class='command'>\n<h3>Memory.addNativeSnapshotChunk <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>chunk</dt>\n<dd><a href='#Memory.HeapSnapshotChunk'>Memory.HeapSnapshotChunk</a> <span class='text'>A chunk of the serialized the snapshot.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Memory.addNativeSnapshotChunk\nfunction onAddNativeSnapshotChunk(res) {\n\t// res = {chunk}\n}\n</pre>\n</div>\n</section>\n<section id='Network' class='domain'>\n<h1>Network</h1>\n<p>Network domain allows tracking network activities of the page. It exposes information about http, file, data and other requests and responses, their headers, bodies, timing, etc.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Network.LoaderId'>Network.LoaderId</a>: Unique loader identifier.</li>\n<li><a href='#Network.RequestId'>Network.RequestId</a>: Unique request identifier.</li>\n<li><a href='#Network.Timestamp'>Network.Timestamp</a>: Number of seconds since epoch.</li>\n<li><a href='#Network.Headers'>Network.Headers</a>: Request / response headers as keys / values of JSON object.</li>\n<li><a href='#Network.ResourceTiming'>Network.ResourceTiming</a>: Timing information for the request.</li>\n<li><a href='#Network.Request'>Network.Request</a>: HTTP request data.</li>\n<li><a href='#Network.Response'>Network.Response</a>: HTTP response data.</li>\n<li><a href='#Network.WebSocketRequest'>Network.WebSocketRequest</a>: WebSocket request data.</li>\n<li><a href='#Network.WebSocketResponse'>Network.WebSocketResponse</a>: WebSocket response data.</li>\n<li><a href='#Network.WebSocketFrame'>Network.WebSocketFrame</a>: WebSocket frame data.</li>\n<li><a href='#Network.CachedResource'>Network.CachedResource</a>: Information about the cached resource.</li>\n<li><a href='#Network.Initiator'>Network.Initiator</a>: Information about the request initiator.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Network.enable'>Network.enable</a>: Enables network tracking, network events will now be delivered to the client.</li>\n<li><a href='#Network.disable'>Network.disable</a>: Disables network tracking, prevents network events from being sent to the client.</li>\n<li><a href='#Network.setUserAgentOverride'>Network.setUserAgentOverride</a>: Allows overriding user agent with the given string.</li>\n<li><a href='#Network.setExtraHTTPHeaders'>Network.setExtraHTTPHeaders</a>: Specifies whether to always send extra HTTP headers with the requests from this page.</li>\n<li><a href='#Network.getResponseBody'>Network.getResponseBody</a>: Returns content served for the given request.</li>\n<li><a href='#Network.replayXHR'>Network.replayXHR</a>: This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.</li>\n<li><a href='#Network.canClearBrowserCache'>Network.canClearBrowserCache</a>: Tells whether clearing browser cache is supported.</li>\n<li><a href='#Network.clearBrowserCache'>Network.clearBrowserCache</a>: Clears browser cache.</li>\n<li><a href='#Network.canClearBrowserCookies'>Network.canClearBrowserCookies</a>: Tells whether clearing browser cookies is supported.</li>\n<li><a href='#Network.clearBrowserCookies'>Network.clearBrowserCookies</a>: Clears browser cookies.</li>\n<li><a href='#Network.setCacheDisabled'>Network.setCacheDisabled</a>: Toggles ignoring cache for each request. If true, cache will not be used.</li>\n<li><a href='#Network.loadResourceForFrontend'>Network.loadResourceForFrontend</a>: Loads a resource in the context of a frame on the inspected page without cross origin checks.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Network.requestWillBeSent'>Network.requestWillBeSent</a>: Fired when page is about to send HTTP request.</li>\n<li><a href='#Network.requestServedFromCache'>Network.requestServedFromCache</a>: Fired if request ended up loading from cache.</li>\n<li><a href='#Network.responseReceived'>Network.responseReceived</a>: Fired when HTTP response is available.</li>\n<li><a href='#Network.dataReceived'>Network.dataReceived</a>: Fired when data chunk was received over the network.</li>\n<li><a href='#Network.loadingFinished'>Network.loadingFinished</a>: Fired when HTTP request has finished loading.</li>\n<li><a href='#Network.loadingFailed'>Network.loadingFailed</a>: Fired when HTTP request has failed to load.</li>\n<li><a href='#Network.webSocketWillSendHandshakeRequest'>Network.webSocketWillSendHandshakeRequest</a>: Fired when WebSocket is about to initiate handshake.</li>\n<li><a href='#Network.webSocketHandshakeResponseReceived'>Network.webSocketHandshakeResponseReceived</a>: Fired when WebSocket handshake response becomes available.</li>\n<li><a href='#Network.webSocketCreated'>Network.webSocketCreated</a>: Fired upon WebSocket creation.</li>\n<li><a href='#Network.webSocketClosed'>Network.webSocketClosed</a>: Fired when WebSocket is closed.</li>\n<li><a href='#Network.webSocketFrameReceived'>Network.webSocketFrameReceived</a>: Fired when WebSocket frame is received.</li>\n<li><a href='#Network.webSocketFrameError'>Network.webSocketFrameError</a>: Fired when WebSocket frame error occurs.</li>\n<li><a href='#Network.webSocketFrameSent'>Network.webSocketFrameSent</a>: Fired when WebSocket frame is sent.</li>\n</ul>\n<div id='Network_LoaderId' class='type'>\n<h3>Network.LoaderId <span class='label'>Type</span></h3>\n<p>Unique loader identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Network_RequestId' class='type'>\n<h3>Network.RequestId <span class='label'>Type</span></h3>\n<p>Unique request identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Network_Timestamp' class='type'>\n<h3>Network.Timestamp <span class='label'>Type</span></h3>\n<p>Number of seconds since epoch.</p>\n<dl>\n<dd>Number</dd>\n</dl>\n</div>\n<div id='Network_Headers' class='type'>\n<h3>Network.Headers <span class='label'>Type</span></h3>\n<p>Request / response headers as keys / values of JSON object.</p>\n</div>\n<div id='Network_ResourceTiming' class='type'>\n<h3>Network.ResourceTiming <span class='label'>Type</span></h3>\n<p>Timing information for the request.</p>\n<dl>\n<dt>requestTime</dt>\n<dd>Number <span class='text'>Timing's requestTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this requestTime.</span></dd>\n<dt>proxyStart</dt>\n<dd>Number <span class='text'>Started resolving proxy.</span></dd>\n<dt>proxyEnd</dt>\n<dd>Number <span class='text'>Finished resolving proxy.</span></dd>\n<dt>dnsStart</dt>\n<dd>Number <span class='text'>Started DNS address resolve.</span></dd>\n<dt>dnsEnd</dt>\n<dd>Number <span class='text'>Finished DNS address resolve.</span></dd>\n<dt>connectStart</dt>\n<dd>Number <span class='text'>Started connecting to the remote host.</span></dd>\n<dt>connectEnd</dt>\n<dd>Number <span class='text'>Connected to the remote host.</span></dd>\n<dt>sslStart</dt>\n<dd>Number <span class='text'>Started SSL handshake.</span></dd>\n<dt>sslEnd</dt>\n<dd>Number <span class='text'>Finished SSL handshake.</span></dd>\n<dt>sendStart</dt>\n<dd>Number <span class='text'>Started sending request.</span></dd>\n<dt>sendEnd</dt>\n<dd>Number <span class='text'>Finished sending request.</span></dd>\n<dt>receiveHeadersEnd</dt>\n<dd>Number <span class='text'>Finished receiving response headers.</span></dd>\n</dl>\n</div>\n<div id='Network_Request' class='type'>\n<h3>Network.Request <span class='label'>Type</span></h3>\n<p>HTTP request data.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Request URL.</span></dd>\n<dt>method</dt>\n<dd>String <span class='text'>HTTP request method.</span></dd>\n<dt>headers</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>HTTP request headers.</span></dd>\n<dt>postData (optional)</dt>\n<dd>String <span class='text'>HTTP POST request data.</span></dd>\n</dl>\n</div>\n<div id='Network_Response' class='type'>\n<h3>Network.Response <span class='label'>Type</span></h3>\n<p>HTTP response data.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Response URL. This URL can be different from CachedResource.url in case of redirect.</span></dd>\n<dt>status</dt>\n<dd>Number <span class='text'>HTTP response status code.</span></dd>\n<dt>statusText</dt>\n<dd>String <span class='text'>HTTP response status text.</span></dd>\n<dt>headers</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>HTTP response headers.</span></dd>\n<dt>headersText (optional)</dt>\n<dd>String <span class='text'>HTTP response headers text.</span></dd>\n<dt>mimeType</dt>\n<dd>String <span class='text'>Resource mimeType as determined by the browser.</span></dd>\n<dt>requestHeaders (optional)</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>Refined HTTP request headers that were actually transmitted over the network.</span></dd>\n<dt>requestHeadersText (optional)</dt>\n<dd>String <span class='text'>HTTP request headers text.</span></dd>\n<dt>connectionReused</dt>\n<dd>Boolean <span class='text'>Specifies whether physical connection was actually reused for this request.</span></dd>\n<dt>connectionId</dt>\n<dd>Number <span class='text'>Physical connection id that was actually used for this request.</span></dd>\n<dt>fromDiskCache (optional)</dt>\n<dd>Boolean <span class='text'>Specifies that the request was served from the disk cache.</span></dd>\n<dt>timing (optional)</dt>\n<dd><a href='#Network.ResourceTiming'>Network.ResourceTiming</a> <span class='text'>Timing information for the given request.</span></dd>\n</dl>\n</div>\n<div id='Network_WebSocketRequest' class='type'>\n<h3>Network.WebSocketRequest <span class='label'>Type</span></h3>\n<p>WebSocket request data.</p>\n<dl>\n<dt>headers</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>HTTP response headers.</span></dd>\n</dl>\n</div>\n<div id='Network_WebSocketResponse' class='type'>\n<h3>Network.WebSocketResponse <span class='label'>Type</span></h3>\n<p>WebSocket response data.</p>\n<dl>\n<dt>status</dt>\n<dd>Number <span class='text'>HTTP response status code.</span></dd>\n<dt>statusText</dt>\n<dd>String <span class='text'>HTTP response status text.</span></dd>\n<dt>headers</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>HTTP response headers.</span></dd>\n</dl>\n</div>\n<div id='Network_WebSocketFrame' class='type'>\n<h3>Network.WebSocketFrame <span class='label'>Type</span></h3>\n<p>WebSocket frame data.</p>\n<dl>\n<dt>opcode</dt>\n<dd>Number <span class='text'>WebSocket frame opcode.</span></dd>\n<dt>mask</dt>\n<dd>Boolean <span class='text'>WebSocke frame mask.</span></dd>\n<dt>payloadData</dt>\n<dd>String <span class='text'>WebSocke frame payload data.</span></dd>\n</dl>\n</div>\n<div id='Network_CachedResource' class='type'>\n<h3>Network.CachedResource <span class='label'>Type</span></h3>\n<p>Information about the cached resource.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Resource URL. This is the url of the original network request.</span></dd>\n<dt>type</dt>\n<dd><a href='#Page.ResourceType'>Page.ResourceType</a> <span class='text'>Type of this resource.</span></dd>\n<dt>response (optional)</dt>\n<dd><a href='#Network.Response'>Network.Response</a> <span class='text'>Cached response data.</span></dd>\n<dt>bodySize</dt>\n<dd>Number <span class='text'>Cached response body size.</span></dd>\n</dl>\n</div>\n<div id='Network_Initiator' class='type'>\n<h3>Network.Initiator <span class='label'>Type</span></h3>\n<p>Information about the request initiator.</p>\n<dl>\n<dt>type</dt>\n<dd>( parser | script | other ) <span class='text'>Type of this initiator.</span></dd>\n<dt>stackTrace (optional)</dt>\n<dd><a href='#Console.StackTrace'>Console.StackTrace</a> <span class='text'>Initiator JavaScript stack trace, set for Script only.</span></dd>\n<dt>url (optional)</dt>\n<dd>String <span class='text'>Initiator URL, set for Parser type only.</span></dd>\n<dt>lineNumber (optional)</dt>\n<dd>Number <span class='text'>Initiator line number, set for Parser type only.</span></dd>\n</dl>\n</div>\n<div id='Network_enable' class='command'>\n<h3>Network.enable <span class='label label-success'>Command</span></h3>\n<p>Enables network tracking, network events will now be delivered to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.enable\nNetwork.enable();\n</pre>\n</div>\n<div id='Network_disable' class='command'>\n<h3>Network.disable <span class='label label-success'>Command</span></h3>\n<p>Disables network tracking, prevents network events from being sent to the client.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.disable\nNetwork.disable();\n</pre>\n</div>\n<div id='Network_setUserAgentOverride' class='command'>\n<h3>Network.setUserAgentOverride <span class='label label-success'>Command</span></h3>\n<p>Allows overriding user agent with the given string.</p>\n<dl>\n<dt>userAgent</dt>\n<dd>String <span class='text'>User agent to use.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.setUserAgentOverride\nNetwork.setUserAgentOverride(userAgent);\n</pre>\n</div>\n<div id='Network_setExtraHTTPHeaders' class='command'>\n<h3>Network.setExtraHTTPHeaders <span class='label label-success'>Command</span></h3>\n<p>Specifies whether to always send extra HTTP headers with the requests from this page.</p>\n<dl>\n<dt>headers</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>Map with extra HTTP headers.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.setExtraHTTPHeaders\nNetwork.setExtraHTTPHeaders(headers);\n</pre>\n</div>\n<div id='Network_getResponseBody' class='command'>\n<h3>Network.getResponseBody <span class='label label-success'>Command</span></h3>\n<p>Returns content served for the given request.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Identifier of the network request to get content for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>body</dt>\n<dd>String <span class='text'>Response body.</span></dd>\n<dt>base64Encoded</dt>\n<dd>Boolean <span class='text'>True, if content was sent as base64.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.getResponseBody\nNetwork.getResponseBody(requestId, function callback(res) {\n\t// res = {body, base64Encoded}\n});\n</pre>\n</div>\n<div id='Network_replayXHR' class='command'>\n<h3>Network.replayXHR <span class='label label-success'>Command</span></h3>\n<p>This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Identifier of XHR to replay.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.replayXHR\nNetwork.replayXHR(requestId);\n</pre>\n</div>\n<div id='Network_canClearBrowserCache' class='command'>\n<h3>Network.canClearBrowserCache <span class='label label-success'>Command</span></h3>\n<p>Tells whether clearing browser cache is supported.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>Boolean <span class='text'>True if browser cache can be cleared.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.canClearBrowserCache\nNetwork.canClearBrowserCache(function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Network_clearBrowserCache' class='command'>\n<h3>Network.clearBrowserCache <span class='label label-success'>Command</span></h3>\n<p>Clears browser cache.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.clearBrowserCache\nNetwork.clearBrowserCache();\n</pre>\n</div>\n<div id='Network_canClearBrowserCookies' class='command'>\n<h3>Network.canClearBrowserCookies <span class='label label-success'>Command</span></h3>\n<p>Tells whether clearing browser cookies is supported.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>Boolean <span class='text'>True if browser cookies can be cleared.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.canClearBrowserCookies\nNetwork.canClearBrowserCookies(function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Network_clearBrowserCookies' class='command'>\n<h3>Network.clearBrowserCookies <span class='label label-success'>Command</span></h3>\n<p>Clears browser cookies.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.clearBrowserCookies\nNetwork.clearBrowserCookies();\n</pre>\n</div>\n<div id='Network_setCacheDisabled' class='command'>\n<h3>Network.setCacheDisabled <span class='label label-success'>Command</span></h3>\n<p>Toggles ignoring cache for each request. If <code>true</code>, cache will not be used.</p>\n<dl>\n<dt>cacheDisabled</dt>\n<dd>Boolean <span class='text'>Cache disabled state.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.setCacheDisabled\nNetwork.setCacheDisabled(cacheDisabled);\n</pre>\n</div>\n<div id='Network_loadResourceForFrontend' class='command'>\n<h3>Network.loadResourceForFrontend <span class='label label-success'>Command</span></h3>\n<p>Loads a resource in the context of a frame on the inspected page without cross origin checks.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame to load the resource from.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the resource to load.</span></dd>\n<dt>requestHeaders (optional)</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>Request headers.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>statusCode</dt>\n<dd>Number <span class='text'>HTTP status code.</span></dd>\n<dt>responseHeaders</dt>\n<dd><a href='#Network.Headers'>Network.Headers</a> <span class='text'>Response headers.</span></dd>\n<dt>content</dt>\n<dd>String <span class='text'>Resource content.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Network.loadResourceForFrontend\nNetwork.loadResourceForFrontend(frameId, url, requestHeaders, function callback(res) {\n\t// res = {statusCode, responseHeaders, content}\n});\n</pre>\n</div>\n<div id='Network_requestWillBeSent' class='command'>\n<h3>Network.requestWillBeSent <span class='label label-info'>Event</span></h3>\n<p>Fired when page is about to send HTTP request.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame identifier.</span></dd>\n<dt>loaderId</dt>\n<dd><a href='#Network.LoaderId'>Network.LoaderId</a> <span class='text'>Loader identifier.</span></dd>\n<dt>documentURL</dt>\n<dd>String <span class='text'>URL of the document this request is loaded for.</span></dd>\n<dt>request</dt>\n<dd><a href='#Network.Request'>Network.Request</a> <span class='text'>Request data.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>initiator</dt>\n<dd><a href='#Network.Initiator'>Network.Initiator</a> <span class='text'>Request initiator.</span></dd>\n<dt>redirectResponse (optional)</dt>\n<dd><a href='#Network.Response'>Network.Response</a> <span class='text'>Redirect response data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.requestWillBeSent\nfunction onRequestWillBeSent(res) {\n\t// res = {requestId, frameId, loaderId, documentURL, request, timestamp, initiator, redirectResponse}\n}\n</pre>\n</div>\n<div id='Network_requestServedFromCache' class='command'>\n<h3>Network.requestServedFromCache <span class='label label-info'>Event</span></h3>\n<p>Fired if request ended up loading from cache.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.requestServedFromCache\nfunction onRequestServedFromCache(res) {\n\t// res = {requestId}\n}\n</pre>\n</div>\n<div id='Network_responseReceived' class='command'>\n<h3>Network.responseReceived <span class='label label-info'>Event</span></h3>\n<p>Fired when HTTP response is available.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame identifier.</span></dd>\n<dt>loaderId</dt>\n<dd><a href='#Network.LoaderId'>Network.LoaderId</a> <span class='text'>Loader identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>type</dt>\n<dd><a href='#Page.ResourceType'>Page.ResourceType</a> <span class='text'>Resource type.</span></dd>\n<dt>response</dt>\n<dd><a href='#Network.Response'>Network.Response</a> <span class='text'>Response data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.responseReceived\nfunction onResponseReceived(res) {\n\t// res = {requestId, frameId, loaderId, timestamp, type, response}\n}\n</pre>\n</div>\n<div id='Network_dataReceived' class='command'>\n<h3>Network.dataReceived <span class='label label-info'>Event</span></h3>\n<p>Fired when data chunk was received over the network.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>dataLength</dt>\n<dd>Integer <span class='text'>Data chunk length.</span></dd>\n<dt>encodedDataLength</dt>\n<dd>Integer <span class='text'>Actual bytes received (might be less than dataLength for compressed encodings).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.dataReceived\nfunction onDataReceived(res) {\n\t// res = {requestId, timestamp, dataLength, encodedDataLength}\n}\n</pre>\n</div>\n<div id='Network_loadingFinished' class='command'>\n<h3>Network.loadingFinished <span class='label label-info'>Event</span></h3>\n<p>Fired when HTTP request has finished loading.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.loadingFinished\nfunction onLoadingFinished(res) {\n\t// res = {requestId, timestamp}\n}\n</pre>\n</div>\n<div id='Network_loadingFailed' class='command'>\n<h3>Network.loadingFailed <span class='label label-info'>Event</span></h3>\n<p>Fired when HTTP request has failed to load.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>errorText</dt>\n<dd>String <span class='text'>User friendly error message.</span></dd>\n<dt>canceled (optional)</dt>\n<dd>Boolean <span class='text'>True if loading was canceled.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.loadingFailed\nfunction onLoadingFailed(res) {\n\t// res = {requestId, timestamp, errorText, canceled}\n}\n</pre>\n</div>\n<div id='Network_webSocketWillSendHandshakeRequest' class='command'>\n<h3>Network.webSocketWillSendHandshakeRequest <span class='label label-info'>Event</span></h3>\n<p>Fired when WebSocket is about to initiate handshake.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>request</dt>\n<dd><a href='#Network.WebSocketRequest'>Network.WebSocketRequest</a> <span class='text'>WebSocket request data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketWillSendHandshakeRequest\nfunction onWebSocketWillSendHandshakeRequest(res) {\n\t// res = {requestId, timestamp, request}\n}\n</pre>\n</div>\n<div id='Network_webSocketHandshakeResponseReceived' class='command'>\n<h3>Network.webSocketHandshakeResponseReceived <span class='label label-info'>Event</span></h3>\n<p>Fired when WebSocket handshake response becomes available.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>response</dt>\n<dd><a href='#Network.WebSocketResponse'>Network.WebSocketResponse</a> <span class='text'>WebSocket response data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketHandshakeResponseReceived\nfunction onWebSocketHandshakeResponseReceived(res) {\n\t// res = {requestId, timestamp, response}\n}\n</pre>\n</div>\n<div id='Network_webSocketCreated' class='command'>\n<h3>Network.webSocketCreated <span class='label label-info'>Event</span></h3>\n<p>Fired upon WebSocket creation.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>WebSocket request URL.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketCreated\nfunction onWebSocketCreated(res) {\n\t// res = {requestId, url}\n}\n</pre>\n</div>\n<div id='Network_webSocketClosed' class='command'>\n<h3>Network.webSocketClosed <span class='label label-info'>Event</span></h3>\n<p>Fired when WebSocket is closed.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketClosed\nfunction onWebSocketClosed(res) {\n\t// res = {requestId, timestamp}\n}\n</pre>\n</div>\n<div id='Network_webSocketFrameReceived' class='command'>\n<h3>Network.webSocketFrameReceived <span class='label label-info'>Event</span></h3>\n<p>Fired when WebSocket frame is received.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>response</dt>\n<dd><a href='#Network.WebSocketFrame'>Network.WebSocketFrame</a> <span class='text'>WebSocket response data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketFrameReceived\nfunction onWebSocketFrameReceived(res) {\n\t// res = {requestId, timestamp, response}\n}\n</pre>\n</div>\n<div id='Network_webSocketFrameError' class='command'>\n<h3>Network.webSocketFrameError <span class='label label-info'>Event</span></h3>\n<p>Fired when WebSocket frame error occurs.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>errorMessage</dt>\n<dd>String <span class='text'>WebSocket frame error message.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketFrameError\nfunction onWebSocketFrameError(res) {\n\t// res = {requestId, timestamp, errorMessage}\n}\n</pre>\n</div>\n<div id='Network_webSocketFrameSent' class='command'>\n<h3>Network.webSocketFrameSent <span class='label label-info'>Event</span></h3>\n<p>Fired when WebSocket frame is sent.</p>\n<dl>\n<dt>requestId</dt>\n<dd><a href='#Network.RequestId'>Network.RequestId</a> <span class='text'>Request identifier.</span></dd>\n<dt>timestamp</dt>\n<dd><a href='#Network.Timestamp'>Network.Timestamp</a> <span class='text'>Timestamp.</span></dd>\n<dt>response</dt>\n<dd><a href='#Network.WebSocketFrame'>Network.WebSocketFrame</a> <span class='text'>WebSocket response data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Network.webSocketFrameSent\nfunction onWebSocketFrameSent(res) {\n\t// res = {requestId, timestamp, response}\n}\n</pre>\n</div>\n</section>\n<section id='Page' class='domain'>\n<h1>Page</h1>\n<p>Actions and events related to the inspected page belong to the page domain.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Page.ResourceType'>Page.ResourceType</a>: Resource type as it was perceived by the rendering engine.</li>\n<li><a href='#Page.FrameId'>Page.FrameId</a>: Unique frame identifier.</li>\n<li><a href='#Page.Frame'>Page.Frame</a>: Information about the Frame on the page.</li>\n<li><a href='#Page.FrameResourceTree'>Page.FrameResourceTree</a>: Information about the Frame hierarchy along with their cached resources.</li>\n<li><a href='#Page.SearchMatch'>Page.SearchMatch</a>: Search match for resource.</li>\n<li><a href='#Page.SearchResult'>Page.SearchResult</a>: Search result for resource.</li>\n<li><a href='#Page.Cookie'>Page.Cookie</a>: Cookie object</li>\n<li><a href='#Page.ScriptIdentifier'>Page.ScriptIdentifier</a>: Unique script identifier.</li>\n<li><a href='#Page.NavigationEntry'>Page.NavigationEntry</a>: Navigation history entry.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Page.enable'>Page.enable</a>: Enables page domain notifications.</li>\n<li><a href='#Page.disable'>Page.disable</a>: Disables page domain notifications.</li>\n<li><a href='#Page.addScriptToEvaluateOnLoad'>Page.addScriptToEvaluateOnLoad</a></li>\n<li><a href='#Page.removeScriptToEvaluateOnLoad'>Page.removeScriptToEvaluateOnLoad</a></li>\n<li><a href='#Page.reload'>Page.reload</a>: Reloads given page optionally ignoring the cache.</li>\n<li><a href='#Page.navigate'>Page.navigate</a>: Navigates current page to the given URL.</li>\n<li><a href='#Page.getNavigationHistory'>Page.getNavigationHistory</a>: Returns navigation history for the current page.</li>\n<li><a href='#Page.navigateToHistoryEntry'>Page.navigateToHistoryEntry</a>: Navigates current page to the given history entry.</li>\n<li><a href='#Page.getCookies'>Page.getCookies</a>: Returns all browser cookies. Depending on the backend support, will either return detailed cookie information in the cookie field or string cookie representation using cookieString.</li>\n<li><a href='#Page.deleteCookie'>Page.deleteCookie</a>: Deletes browser cookie with given name, domain and path.</li>\n<li><a href='#Page.getResourceTree'>Page.getResourceTree</a>: Returns present frame / resource tree structure.</li>\n<li><a href='#Page.getResourceContent'>Page.getResourceContent</a>: Returns content of the given resource.</li>\n<li><a href='#Page.searchInResource'>Page.searchInResource</a>: Searches for given string in resource content.</li>\n<li><a href='#Page.searchInResources'>Page.searchInResources</a>: Searches for given string in frame / resource tree structure.</li>\n<li><a href='#Page.setDocumentContent'>Page.setDocumentContent</a>: Sets given markup as the document's HTML.</li>\n<li><a href='#Page.setDeviceMetricsOverride'>Page.setDeviceMetricsOverride</a>: Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results) and the font scale factor.</li>\n<li><a href='#Page.setShowPaintRects'>Page.setShowPaintRects</a>: Requests that backend shows paint rectangles</li>\n<li><a href='#Page.setShowDebugBorders'>Page.setShowDebugBorders</a>: Requests that backend shows debug borders on layers</li>\n<li><a href='#Page.setShowFPSCounter'>Page.setShowFPSCounter</a>: Requests that backend shows the FPS counter</li>\n<li><a href='#Page.setContinuousPaintingEnabled'>Page.setContinuousPaintingEnabled</a>: Requests that backend enables continuous painting</li>\n<li><a href='#Page.setShowScrollBottleneckRects'>Page.setShowScrollBottleneckRects</a>: Requests that backend shows scroll bottleneck rects</li>\n<li><a href='#Page.getScriptExecutionStatus'>Page.getScriptExecutionStatus</a>: Determines if scripts can be executed in the page.</li>\n<li><a href='#Page.setScriptExecutionDisabled'>Page.setScriptExecutionDisabled</a>: Switches script execution in the page.</li>\n<li><a href='#Page.setGeolocationOverride'>Page.setGeolocationOverride</a>: Overrides the Geolocation Position or Error.</li>\n<li><a href='#Page.clearGeolocationOverride'>Page.clearGeolocationOverride</a>: Clears the overriden Geolocation Position and Error.</li>\n<li><a href='#Page.setDeviceOrientationOverride'>Page.setDeviceOrientationOverride</a>: Overrides the Device Orientation.</li>\n<li><a href='#Page.clearDeviceOrientationOverride'>Page.clearDeviceOrientationOverride</a>: Clears the overridden Device Orientation.</li>\n<li><a href='#Page.setTouchEmulationEnabled'>Page.setTouchEmulationEnabled</a>: Toggles mouse event-based touch event emulation.</li>\n<li><a href='#Page.setEmulatedMedia'>Page.setEmulatedMedia</a>: Emulates the given media for CSS media queries.</li>\n<li><a href='#Page.captureScreenshot'>Page.captureScreenshot</a>: Capture page screenshot.</li>\n<li><a href='#Page.startScreencast'>Page.startScreencast</a>: Starts sending each frame using the screencastFrame event.</li>\n<li><a href='#Page.stopScreencast'>Page.stopScreencast</a>: Stops sending each frame in the screencastFrame.</li>\n<li><a href='#Page.handleJavaScriptDialog'>Page.handleJavaScriptDialog</a>: Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).</li>\n<li><a href='#Page.setShowViewportSizeOnResize'>Page.setShowViewportSizeOnResize</a>: Paints viewport size upon main frame resize.</li>\n<li><a href='#Page.setForceCompositingMode'>Page.setForceCompositingMode</a>: Force accelerated compositing mode for inspected page.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Page.domContentEventFired'>Page.domContentEventFired</a></li>\n<li><a href='#Page.loadEventFired'>Page.loadEventFired</a></li>\n<li><a href='#Page.frameAttached'>Page.frameAttached</a>: Fired when frame has been attached to its parent.</li>\n<li><a href='#Page.frameNavigated'>Page.frameNavigated</a>: Fired once navigation of the frame has completed. Frame is now associated with the new loader.</li>\n<li><a href='#Page.frameDetached'>Page.frameDetached</a>: Fired when frame has been detached from its parent.</li>\n<li><a href='#Page.frameStartedLoading'>Page.frameStartedLoading</a>: Fired when frame has started loading.</li>\n<li><a href='#Page.frameStoppedLoading'>Page.frameStoppedLoading</a>: Fired when frame has stopped loading.</li>\n<li><a href='#Page.frameScheduledNavigation'>Page.frameScheduledNavigation</a>: Fired when frame schedules a potential navigation.</li>\n<li><a href='#Page.frameClearedScheduledNavigation'>Page.frameClearedScheduledNavigation</a>: Fired when frame no longer has a scheduled navigation.</li>\n<li><a href='#Page.javascriptDialogOpening'>Page.javascriptDialogOpening</a>: Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.</li>\n<li><a href='#Page.javascriptDialogClosed'>Page.javascriptDialogClosed</a>: Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) has been closed.</li>\n<li><a href='#Page.scriptsEnabled'>Page.scriptsEnabled</a>: Fired when the JavaScript is enabled/disabled on the page</li>\n<li><a href='#Page.screencastFrame'>Page.screencastFrame</a>: Compressed image data requested by the startScreencast.</li>\n<li><a href='#Page.screencastVisibilityChanged'>Page.screencastVisibilityChanged</a>: Fired when the page with currently enabled screencast was shown or hidden .</li>\n</ul>\n<div id='Page_ResourceType' class='type'>\n<h3>Page.ResourceType <span class='label'>Type</span></h3>\n<p>Resource type as it was perceived by the rendering engine.</p>\n<dl>\n<dd>( Document | Stylesheet | Image | Font | Script | XHR | WebSocket | Other )</dd>\n</dl>\n</div>\n<div id='Page_FrameId' class='type'>\n<h3>Page.FrameId <span class='label'>Type</span></h3>\n<p>Unique frame identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Page_Frame' class='type'>\n<h3>Page.Frame <span class='label'>Type</span></h3>\n<p>Information about the Frame on the page.</p>\n<dl>\n<dt>id</dt>\n<dd>String <span class='text'>Frame unique identifier.</span></dd>\n<dt>parentId (optional)</dt>\n<dd>String <span class='text'>Parent frame identifier.</span></dd>\n<dt>loaderId</dt>\n<dd><a href='#Network.LoaderId'>Network.LoaderId</a> <span class='text'>Identifier of the loader associated with this frame.</span></dd>\n<dt>name (optional)</dt>\n<dd>String <span class='text'>Frame's name as specified in the tag.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>Frame document's URL.</span></dd>\n<dt>securityOrigin</dt>\n<dd>String <span class='text'>Frame document's security origin.</span></dd>\n<dt>mimeType</dt>\n<dd>String <span class='text'>Frame document's mimeType as determined by the browser.</span></dd>\n</dl>\n</div>\n<div id='Page_FrameResourceTree' class='type'>\n<h3>Page.FrameResourceTree <span class='label'>Type</span></h3>\n<p>Information about the Frame hierarchy along with their cached resources.</p>\n<dl>\n<dt>frame</dt>\n<dd><a href='#Page.Frame'>Page.Frame</a> <span class='text'>Frame information for this tree item.</span></dd>\n<dt>childFrames (optional)</dt>\n<dd>[<a href='#Page.FrameResourceTree'>Page.FrameResourceTree</a>] <span class='text'>Child frames.</span></dd>\n<dt>resources</dt>\n<dd>[Object] <span class='text'>Information about frame resources.</span></dd>\n</dl>\n</div>\n<div id='Page_SearchMatch' class='type'>\n<h3>Page.SearchMatch <span class='label'>Type</span></h3>\n<p>Search match for resource.</p>\n<dl>\n<dt>lineNumber</dt>\n<dd>Number <span class='text'>Line number in resource content.</span></dd>\n<dt>lineContent</dt>\n<dd>String <span class='text'>Line with match content.</span></dd>\n</dl>\n</div>\n<div id='Page_SearchResult' class='type'>\n<h3>Page.SearchResult <span class='label'>Type</span></h3>\n<p>Search result for resource.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>Resource URL.</span></dd>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Resource frame id.</span></dd>\n<dt>matchesCount</dt>\n<dd>Number <span class='text'>Number of matches in the resource content.</span></dd>\n</dl>\n</div>\n<div id='Page_Cookie' class='type'>\n<h3>Page.Cookie <span class='label'>Type</span></h3>\n<p>Cookie object</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Cookie name.</span></dd>\n<dt>value</dt>\n<dd>String <span class='text'>Cookie value.</span></dd>\n<dt>domain</dt>\n<dd>String <span class='text'>Cookie domain.</span></dd>\n<dt>path</dt>\n<dd>String <span class='text'>Cookie path.</span></dd>\n<dt>expires</dt>\n<dd>Number <span class='text'>Cookie expires.</span></dd>\n<dt>size</dt>\n<dd>Integer <span class='text'>Cookie size.</span></dd>\n<dt>httpOnly</dt>\n<dd>Boolean <span class='text'>True if cookie is http-only.</span></dd>\n<dt>secure</dt>\n<dd>Boolean <span class='text'>True if cookie is secure.</span></dd>\n<dt>session</dt>\n<dd>Boolean <span class='text'>True in case of session cookie.</span></dd>\n</dl>\n</div>\n<div id='Page_ScriptIdentifier' class='type'>\n<h3>Page.ScriptIdentifier <span class='label'>Type</span></h3>\n<p>Unique script identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Page_NavigationEntry' class='type'>\n<h3>Page.NavigationEntry <span class='label'>Type</span></h3>\n<p>Navigation history entry.</p>\n<dl>\n<dt>id</dt>\n<dd>Integer <span class='text'>Unique id of the navigation history entry.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the navigation history entry.</span></dd>\n<dt>title</dt>\n<dd>String <span class='text'>Title of the navigation history entry.</span></dd>\n</dl>\n</div>\n<div id='Page_enable' class='command'>\n<h3>Page.enable <span class='label label-success'>Command</span></h3>\n<p>Enables page domain notifications.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.enable\nPage.enable();\n</pre>\n</div>\n<div id='Page_disable' class='command'>\n<h3>Page.disable <span class='label label-success'>Command</span></h3>\n<p>Disables page domain notifications.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.disable\nPage.disable();\n</pre>\n</div>\n<div id='Page_addScriptToEvaluateOnLoad' class='command'>\n<h3>Page.addScriptToEvaluateOnLoad <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>scriptSource</dt>\n<dd>String</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>identifier</dt>\n<dd><a href='#Page.ScriptIdentifier'>Page.ScriptIdentifier</a> <span class='text'>Identifier of the added script.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.addScriptToEvaluateOnLoad\nPage.addScriptToEvaluateOnLoad(scriptSource, function callback(res) {\n\t// res = {identifier}\n});\n</pre>\n</div>\n<div id='Page_removeScriptToEvaluateOnLoad' class='command'>\n<h3>Page.removeScriptToEvaluateOnLoad <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>identifier</dt>\n<dd><a href='#Page.ScriptIdentifier'>Page.ScriptIdentifier</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.removeScriptToEvaluateOnLoad\nPage.removeScriptToEvaluateOnLoad(identifier);\n</pre>\n</div>\n<div id='Page_reload' class='command'>\n<h3>Page.reload <span class='label label-success'>Command</span></h3>\n<p>Reloads given page optionally ignoring the cache.</p>\n<dl>\n<dt>ignoreCache (optional)</dt>\n<dd>Boolean <span class='text'>If true, browser cache is ignored (as if the user pressed Shift+refresh).</span></dd>\n<dt>scriptToEvaluateOnLoad (optional)</dt>\n<dd>String <span class='text'>If set, the script will be injected into all frames of the inspected page after reload.</span></dd>\n<dt>scriptPreprocessor (optional)</dt>\n<dd>String <span class='text'>Script body that should evaluate to function that will preprocess all the scripts before their compilation.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.reload\nPage.reload(ignoreCache, scriptToEvaluateOnLoad, scriptPreprocessor);\n</pre>\n</div>\n<div id='Page_navigate' class='command'>\n<h3>Page.navigate <span class='label label-success'>Command</span></h3>\n<p>Navigates current page to the given URL.</p>\n<dl>\n<dt>url</dt>\n<dd>String <span class='text'>URL to navigate the page to.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.navigate\nPage.navigate(url);\n</pre>\n</div>\n<div id='Page_getNavigationHistory' class='command'>\n<h3>Page.getNavigationHistory <span class='label label-success'>Command</span></h3>\n<p>Returns navigation history for the current page.</p>\n<dl>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>currentIndex</dt>\n<dd>Integer <span class='text'>Index of the current navigation history entry.</span></dd>\n<dt>entries</dt>\n<dd>[<a href='#Page.NavigationEntry'>Page.NavigationEntry</a>] <span class='text'>Array of navigation history entries.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.getNavigationHistory\nPage.getNavigationHistory(function callback(res) {\n\t// res = {currentIndex, entries}\n});\n</pre>\n</div>\n<div id='Page_navigateToHistoryEntry' class='command'>\n<h3>Page.navigateToHistoryEntry <span class='label label-success'>Command</span></h3>\n<p>Navigates current page to the given history entry.</p>\n<dl>\n<dt>entryId</dt>\n<dd>Integer <span class='text'>Unique id of the entry to navigate to.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.navigateToHistoryEntry\nPage.navigateToHistoryEntry(entryId);\n</pre>\n</div>\n<div id='Page_getCookies' class='command'>\n<h3>Page.getCookies <span class='label label-success'>Command</span></h3>\n<p>Returns all browser cookies. Depending on the backend support, will either return detailed cookie information in the <code>cookie</code> field or string cookie representation using <code>cookieString</code>.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>cookies</dt>\n<dd>[<a href='#Page.Cookie'>Page.Cookie</a>] <span class='text'>Array of cookie objects.</span></dd>\n<dt>cookiesString</dt>\n<dd>String <span class='text'>document.cookie string representation of the cookies.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.getCookies\nPage.getCookies(function callback(res) {\n\t// res = {cookies, cookiesString}\n});\n</pre>\n</div>\n<div id='Page_deleteCookie' class='command'>\n<h3>Page.deleteCookie <span class='label label-success'>Command</span></h3>\n<p>Deletes browser cookie with given name, domain and path.</p>\n<dl>\n<dt>cookieName</dt>\n<dd>String <span class='text'>Name of the cookie to remove.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL to match cooke domain and path.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.deleteCookie\nPage.deleteCookie(cookieName, url);\n</pre>\n</div>\n<div id='Page_getResourceTree' class='command'>\n<h3>Page.getResourceTree <span class='label label-success'>Command</span></h3>\n<p>Returns present frame / resource tree structure.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>frameTree</dt>\n<dd><a href='#Page.FrameResourceTree'>Page.FrameResourceTree</a> <span class='text'>Present frame / resource tree structure.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.getResourceTree\nPage.getResourceTree(function callback(res) {\n\t// res = {frameTree}\n});\n</pre>\n</div>\n<div id='Page_getResourceContent' class='command'>\n<h3>Page.getResourceContent <span class='label label-success'>Command</span></h3>\n<p>Returns content of the given resource.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame id to get resource for.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the resource to get content for.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>content</dt>\n<dd>String <span class='text'>Resource content.</span></dd>\n<dt>base64Encoded</dt>\n<dd>Boolean <span class='text'>True, if content was served as base64.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.getResourceContent\nPage.getResourceContent(frameId, url, function callback(res) {\n\t// res = {content, base64Encoded}\n});\n</pre>\n</div>\n<div id='Page_searchInResource' class='command'>\n<h3>Page.searchInResource <span class='label label-success'>Command</span></h3>\n<p>Searches for given string in resource content.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame id for resource to search in.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL of the resource to search in.</span></dd>\n<dt>query</dt>\n<dd>String <span class='text'>String to search for.</span></dd>\n<dt>caseSensitive (optional)</dt>\n<dd>Boolean <span class='text'>If true, search is case sensitive.</span></dd>\n<dt>isRegex (optional)</dt>\n<dd>Boolean <span class='text'>If true, treats string parameter as regex.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>[<a href='#Page.SearchMatch'>Page.SearchMatch</a>] <span class='text'>List of search matches.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.searchInResource\nPage.searchInResource(frameId, url, query, caseSensitive, isRegex, function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Page_searchInResources' class='command'>\n<h3>Page.searchInResources <span class='label label-success'>Command</span></h3>\n<p>Searches for given string in frame / resource tree structure.</p>\n<dl>\n<dt>text</dt>\n<dd>String <span class='text'>String to search for.</span></dd>\n<dt>caseSensitive (optional)</dt>\n<dd>Boolean <span class='text'>If true, search is case sensitive.</span></dd>\n<dt>isRegex (optional)</dt>\n<dd>Boolean <span class='text'>If true, treats string parameter as regex.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>[<a href='#Page.SearchResult'>Page.SearchResult</a>] <span class='text'>List of search results.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.searchInResources\nPage.searchInResources(text, caseSensitive, isRegex, function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Page_setDocumentContent' class='command'>\n<h3>Page.setDocumentContent <span class='label label-success'>Command</span></h3>\n<p>Sets given markup as the document's HTML.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Frame id to set HTML for.</span></dd>\n<dt>html</dt>\n<dd>String <span class='text'>HTML content to set.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setDocumentContent\nPage.setDocumentContent(frameId, html);\n</pre>\n</div>\n<div id='Page_setDeviceMetricsOverride' class='command'>\n<h3>Page.setDeviceMetricsOverride <span class='label label-success'>Command</span></h3>\n<p>Overrides the values of device screen dimensions (window.screen.width, window.screen.height, window.innerWidth, window.innerHeight, and \"device-width\"/\"device-height\"-related CSS media query results) and the font scale factor.</p>\n<dl>\n<dt>width</dt>\n<dd>Integer <span class='text'>Overriding width value in pixels (minimum 0, maximum 10000000). 0 disables the override.</span></dd>\n<dt>height</dt>\n<dd>Integer <span class='text'>Overriding height value in pixels (minimum 0, maximum 10000000). 0 disables the override.</span></dd>\n<dt>fontScaleFactor</dt>\n<dd>Number <span class='text'>Overriding font scale factor value (must be positive). 1 disables the override.</span></dd>\n<dt>fitWindow</dt>\n<dd>Boolean <span class='text'>Whether a view that exceeds the available browser window area should be scaled down to fit.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setDeviceMetricsOverride\nPage.setDeviceMetricsOverride(width, height, fontScaleFactor, fitWindow);\n</pre>\n</div>\n<div id='Page_setShowPaintRects' class='command'>\n<h3>Page.setShowPaintRects <span class='label label-success'>Command</span></h3>\n<p>Requests that backend shows paint rectangles</p>\n<dl>\n<dt>result</dt>\n<dd>Boolean <span class='text'>True for showing paint rectangles</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setShowPaintRects\nPage.setShowPaintRects(result);\n</pre>\n</div>\n<div id='Page_setShowDebugBorders' class='command'>\n<h3>Page.setShowDebugBorders <span class='label label-success'>Command</span></h3>\n<p>Requests that backend shows debug borders on layers</p>\n<dl>\n<dt>show</dt>\n<dd>Boolean <span class='text'>True for showing debug borders</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setShowDebugBorders\nPage.setShowDebugBorders(show);\n</pre>\n</div>\n<div id='Page_setShowFPSCounter' class='command'>\n<h3>Page.setShowFPSCounter <span class='label label-success'>Command</span></h3>\n<p>Requests that backend shows the FPS counter</p>\n<dl>\n<dt>show</dt>\n<dd>Boolean <span class='text'>True for showing the FPS counter</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setShowFPSCounter\nPage.setShowFPSCounter(show);\n</pre>\n</div>\n<div id='Page_setContinuousPaintingEnabled' class='command'>\n<h3>Page.setContinuousPaintingEnabled <span class='label label-success'>Command</span></h3>\n<p>Requests that backend enables continuous painting</p>\n<dl>\n<dt>enabled</dt>\n<dd>Boolean <span class='text'>True for enabling cointinuous painting</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setContinuousPaintingEnabled\nPage.setContinuousPaintingEnabled(enabled);\n</pre>\n</div>\n<div id='Page_setShowScrollBottleneckRects' class='command'>\n<h3>Page.setShowScrollBottleneckRects <span class='label label-success'>Command</span></h3>\n<p>Requests that backend shows scroll bottleneck rects</p>\n<dl>\n<dt>show</dt>\n<dd>Boolean <span class='text'>True for showing scroll bottleneck rects</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setShowScrollBottleneckRects\nPage.setShowScrollBottleneckRects(show);\n</pre>\n</div>\n<div id='Page_getScriptExecutionStatus' class='command'>\n<h3>Page.getScriptExecutionStatus <span class='label label-success'>Command</span></h3>\n<p>Determines if scripts can be executed in the page.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>( allowed | disabled | forbidden ) <span class='text'>Script execution status: \"allowed\" if scripts can be executed, \"disabled\" if script execution has been disabled through page settings, \"forbidden\" if script execution for the given page is not possible for other reasons.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.getScriptExecutionStatus\nPage.getScriptExecutionStatus(function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Page_setScriptExecutionDisabled' class='command'>\n<h3>Page.setScriptExecutionDisabled <span class='label label-success'>Command</span></h3>\n<p>Switches script execution in the page.</p>\n<dl>\n<dt>value</dt>\n<dd>Boolean <span class='text'>Whether script execution should be disabled in the page.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setScriptExecutionDisabled\nPage.setScriptExecutionDisabled(value);\n</pre>\n</div>\n<div id='Page_setGeolocationOverride' class='command'>\n<h3>Page.setGeolocationOverride <span class='label label-success'>Command</span></h3>\n<p>Overrides the Geolocation Position or Error.</p>\n<dl>\n<dt>latitude (optional)</dt>\n<dd>Number <span class='text'>Mock longitude</span></dd>\n<dt>longitude (optional)</dt>\n<dd>Number <span class='text'>Mock latitude</span></dd>\n<dt>accuracy (optional)</dt>\n<dd>Number <span class='text'>Mock accuracy</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setGeolocationOverride\nPage.setGeolocationOverride(latitude, longitude, accuracy);\n</pre>\n</div>\n<div id='Page_clearGeolocationOverride' class='command'>\n<h3>Page.clearGeolocationOverride <span class='label label-success'>Command</span></h3>\n<p>Clears the overriden Geolocation Position and Error.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.clearGeolocationOverride\nPage.clearGeolocationOverride();\n</pre>\n</div>\n<div id='Page_setDeviceOrientationOverride' class='command'>\n<h3>Page.setDeviceOrientationOverride <span class='label label-success'>Command</span></h3>\n<p>Overrides the Device Orientation.</p>\n<dl>\n<dt>alpha</dt>\n<dd>Number <span class='text'>Mock alpha</span></dd>\n<dt>beta</dt>\n<dd>Number <span class='text'>Mock beta</span></dd>\n<dt>gamma</dt>\n<dd>Number <span class='text'>Mock gamma</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setDeviceOrientationOverride\nPage.setDeviceOrientationOverride(alpha, beta, gamma);\n</pre>\n</div>\n<div id='Page_clearDeviceOrientationOverride' class='command'>\n<h3>Page.clearDeviceOrientationOverride <span class='label label-success'>Command</span></h3>\n<p>Clears the overridden Device Orientation.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.clearDeviceOrientationOverride\nPage.clearDeviceOrientationOverride();\n</pre>\n</div>\n<div id='Page_setTouchEmulationEnabled' class='command'>\n<h3>Page.setTouchEmulationEnabled <span class='label label-success'>Command</span></h3>\n<p>Toggles mouse event-based touch event emulation.</p>\n<dl>\n<dt>enabled</dt>\n<dd>Boolean <span class='text'>Whether the touch event emulation should be enabled.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setTouchEmulationEnabled\nPage.setTouchEmulationEnabled(enabled);\n</pre>\n</div>\n<div id='Page_setEmulatedMedia' class='command'>\n<h3>Page.setEmulatedMedia <span class='label label-success'>Command</span></h3>\n<p>Emulates the given media for CSS media queries.</p>\n<dl>\n<dt>media</dt>\n<dd>String <span class='text'>Media type to emulate. Empty string disables the override.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setEmulatedMedia\nPage.setEmulatedMedia(media);\n</pre>\n</div>\n<div id='Page_captureScreenshot' class='command'>\n<h3>Page.captureScreenshot <span class='label label-success'>Command</span></h3>\n<p>Capture page screenshot.</p>\n<dl>\n<dt>format (optional)</dt>\n<dd>( jpeg | png ) <span class='text'>Image compression format.</span></dd>\n<dt>quality (optional)</dt>\n<dd>Integer <span class='text'>Compression quality from range [0..100].</span></dd>\n<dt>maxWidth (optional)</dt>\n<dd>Integer <span class='text'>Maximum screenshot width.</span></dd>\n<dt>maxHeight (optional)</dt>\n<dd>Integer <span class='text'>Maximum screenshot height.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>data</dt>\n<dd>String <span class='text'>Base64-encoded image data (PNG).</span></dd>\n<dt>deviceScaleFactor</dt>\n<dd>Number <span class='text'>Device scale factor.</span></dd>\n<dt>pageScaleFactor</dt>\n<dd>Number <span class='text'>Page scale factor.</span></dd>\n<dt>viewport</dt>\n<dd><a href='#DOM.Rect'>DOM.Rect</a> <span class='text'>Viewport in CSS pixels.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.captureScreenshot\nPage.captureScreenshot(format, quality, maxWidth, maxHeight, function callback(res) {\n\t// res = {data, deviceScaleFactor, pageScaleFactor, viewport}\n});\n</pre>\n</div>\n<div id='Page_startScreencast' class='command'>\n<h3>Page.startScreencast <span class='label label-success'>Command</span></h3>\n<p>Starts sending each frame using the <code>screencastFrame</code> event.</p>\n<dl>\n<dt>format (optional)</dt>\n<dd>( jpeg | png ) <span class='text'>Image compression format.</span></dd>\n<dt>quality (optional)</dt>\n<dd>Integer <span class='text'>Compression quality from range [0..100].</span></dd>\n<dt>maxWidth (optional)</dt>\n<dd>Integer <span class='text'>Maximum screenshot width.</span></dd>\n<dt>maxHeight (optional)</dt>\n<dd>Integer <span class='text'>Maximum screenshot height.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.startScreencast\nPage.startScreencast(format, quality, maxWidth, maxHeight);\n</pre>\n</div>\n<div id='Page_stopScreencast' class='command'>\n<h3>Page.stopScreencast <span class='label label-success'>Command</span></h3>\n<p>Stops sending each frame in the <code>screencastFrame</code>.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.stopScreencast\nPage.stopScreencast();\n</pre>\n</div>\n<div id='Page_handleJavaScriptDialog' class='command'>\n<h3>Page.handleJavaScriptDialog <span class='label label-success'>Command</span></h3>\n<p>Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).</p>\n<dl>\n<dt>accept</dt>\n<dd>Boolean <span class='text'>Whether to accept or dismiss the dialog.</span></dd>\n<dt>promptText (optional)</dt>\n<dd>String <span class='text'>The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.handleJavaScriptDialog\nPage.handleJavaScriptDialog(accept, promptText);\n</pre>\n</div>\n<div id='Page_setShowViewportSizeOnResize' class='command'>\n<h3>Page.setShowViewportSizeOnResize <span class='label label-success'>Command</span></h3>\n<p>Paints viewport size upon main frame resize.</p>\n<dl>\n<dt>show</dt>\n<dd>Boolean <span class='text'>Whether to paint size or not.</span></dd>\n<dt>showGrid (optional)</dt>\n<dd>Boolean <span class='text'>Whether to paint grid as well.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setShowViewportSizeOnResize\nPage.setShowViewportSizeOnResize(show, showGrid);\n</pre>\n</div>\n<div id='Page_setForceCompositingMode' class='command'>\n<h3>Page.setForceCompositingMode <span class='label label-success'>Command</span></h3>\n<p>Force accelerated compositing mode for inspected page.</p>\n<dl>\n<dt>force</dt>\n<dd>Boolean <span class='text'>Whether to force accelerated compositing or not.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Page.setForceCompositingMode\nPage.setForceCompositingMode(force);\n</pre>\n</div>\n<div id='Page_domContentEventFired' class='command'>\n<h3>Page.domContentEventFired <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>timestamp</dt>\n<dd>Number</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.domContentEventFired\nfunction onDomContentEventFired(res) {\n\t// res = {timestamp}\n}\n</pre>\n</div>\n<div id='Page_loadEventFired' class='command'>\n<h3>Page.loadEventFired <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>timestamp</dt>\n<dd>Number</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.loadEventFired\nfunction onLoadEventFired(res) {\n\t// res = {timestamp}\n}\n</pre>\n</div>\n<div id='Page_frameAttached' class='command'>\n<h3>Page.frameAttached <span class='label label-info'>Event</span></h3>\n<p>Fired when frame has been attached to its parent.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the frame that has been attached.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameAttached\nfunction onFrameAttached(res) {\n\t// res = {frameId}\n}\n</pre>\n</div>\n<div id='Page_frameNavigated' class='command'>\n<h3>Page.frameNavigated <span class='label label-info'>Event</span></h3>\n<p>Fired once navigation of the frame has completed. Frame is now associated with the new loader.</p>\n<dl>\n<dt>frame</dt>\n<dd><a href='#Page.Frame'>Page.Frame</a> <span class='text'>Frame object.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameNavigated\nfunction onFrameNavigated(res) {\n\t// res = {frame}\n}\n</pre>\n</div>\n<div id='Page_frameDetached' class='command'>\n<h3>Page.frameDetached <span class='label label-info'>Event</span></h3>\n<p>Fired when frame has been detached from its parent.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the frame that has been detached.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameDetached\nfunction onFrameDetached(res) {\n\t// res = {frameId}\n}\n</pre>\n</div>\n<div id='Page_frameStartedLoading' class='command'>\n<h3>Page.frameStartedLoading <span class='label label-info'>Event</span></h3>\n<p>Fired when frame has started loading.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the frame that has started loading.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameStartedLoading\nfunction onFrameStartedLoading(res) {\n\t// res = {frameId}\n}\n</pre>\n</div>\n<div id='Page_frameStoppedLoading' class='command'>\n<h3>Page.frameStoppedLoading <span class='label label-info'>Event</span></h3>\n<p>Fired when frame has stopped loading.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the frame that has stopped loading.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameStoppedLoading\nfunction onFrameStoppedLoading(res) {\n\t// res = {frameId}\n}\n</pre>\n</div>\n<div id='Page_frameScheduledNavigation' class='command'>\n<h3>Page.frameScheduledNavigation <span class='label label-info'>Event</span></h3>\n<p>Fired when frame schedules a potential navigation.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the frame that has scheduled a navigation.</span></dd>\n<dt>delay</dt>\n<dd>Number <span class='text'>Delay (in seconds) until the navigation is scheduled to begin. The navigation is not guaranteed to start.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameScheduledNavigation\nfunction onFrameScheduledNavigation(res) {\n\t// res = {frameId, delay}\n}\n</pre>\n</div>\n<div id='Page_frameClearedScheduledNavigation' class='command'>\n<h3>Page.frameClearedScheduledNavigation <span class='label label-info'>Event</span></h3>\n<p>Fired when frame no longer has a scheduled navigation.</p>\n<dl>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the frame that has cleared its scheduled navigation.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.frameClearedScheduledNavigation\nfunction onFrameClearedScheduledNavigation(res) {\n\t// res = {frameId}\n}\n</pre>\n</div>\n<div id='Page_javascriptDialogOpening' class='command'>\n<h3>Page.javascriptDialogOpening <span class='label label-info'>Event</span></h3>\n<p>Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.</p>\n<dl>\n<dt>message</dt>\n<dd>String <span class='text'>Message that will be displayed by the dialog.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.javascriptDialogOpening\nfunction onJavascriptDialogOpening(res) {\n\t// res = {message}\n}\n</pre>\n</div>\n<div id='Page_javascriptDialogClosed' class='command'>\n<h3>Page.javascriptDialogClosed <span class='label label-info'>Event</span></h3>\n<p>Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) has been closed.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.javascriptDialogClosed\nfunction onJavascriptDialogClosed(res) {\n\t// res = {}\n}\n</pre>\n</div>\n<div id='Page_scriptsEnabled' class='command'>\n<h3>Page.scriptsEnabled <span class='label label-info'>Event</span></h3>\n<p>Fired when the JavaScript is enabled/disabled on the page</p>\n<dl>\n<dt>isEnabled</dt>\n<dd>Boolean <span class='text'>Whether script execution is enabled or disabled on the page.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.scriptsEnabled\nfunction onScriptsEnabled(res) {\n\t// res = {isEnabled}\n}\n</pre>\n</div>\n<div id='Page_screencastFrame' class='command'>\n<h3>Page.screencastFrame <span class='label label-info'>Event</span></h3>\n<p>Compressed image data requested by the <code>startScreencast</code>.</p>\n<dl>\n<dt>data</dt>\n<dd>String <span class='text'>Base64-encoded compressed image.</span></dd>\n<dt>deviceScaleFactor (optional)</dt>\n<dd>Number <span class='text'>Device scale factor.</span></dd>\n<dt>pageScaleFactor (optional)</dt>\n<dd>Number <span class='text'>Page scale factor.</span></dd>\n<dt>viewport (optional)</dt>\n<dd><a href='#DOM.Rect'>DOM.Rect</a> <span class='text'>Viewport in CSS pixels.</span></dd>\n<dt>offsetTop (optional)</dt>\n<dd>Number <span class='text'>Top offset in DIP.</span></dd>\n<dt>offsetBottom (optional)</dt>\n<dd>Number <span class='text'>Bottom offset in DIP.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.screencastFrame\nfunction onScreencastFrame(res) {\n\t// res = {data, deviceScaleFactor, pageScaleFactor, viewport, offsetTop, offsetBottom}\n}\n</pre>\n</div>\n<div id='Page_screencastVisibilityChanged' class='command'>\n<h3>Page.screencastVisibilityChanged <span class='label label-info'>Event</span></h3>\n<p>Fired when the page with currently enabled screencast was shown or hidden </code>.</p>\n<dl>\n<dt>visible</dt>\n<dd>Boolean <span class='text'>True if the page is visible.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Page.screencastVisibilityChanged\nfunction onScreencastVisibilityChanged(res) {\n\t// res = {visible}\n}\n</pre>\n</div>\n</section>\n<section id='Profiler' class='domain'>\n<h1>Profiler</h1>\n<p></p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Profiler.ProfileHeader'>Profiler.ProfileHeader</a>: Profile header.</li>\n<li><a href='#Profiler.CPUProfileNode'>Profiler.CPUProfileNode</a>: CPU Profile node. Holds callsite information, execution statistics and child nodes.</li>\n<li><a href='#Profiler.CPUProfile'>Profiler.CPUProfile</a>: Profile.</li>\n<li><a href='#Profiler.HeapSnapshotObjectId'>Profiler.HeapSnapshotObjectId</a>: Heap snashot object id.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Profiler.enable'>Profiler.enable</a></li>\n<li><a href='#Profiler.disable'>Profiler.disable</a></li>\n<li><a href='#Profiler.setSamplingInterval'>Profiler.setSamplingInterval</a>: Changes CPU profiler sampling interval. Must be called before CPU profiles recording started.</li>\n<li><a href='#Profiler.start'>Profiler.start</a></li>\n<li><a href='#Profiler.stop'>Profiler.stop</a></li>\n<li><a href='#Profiler.getProfileHeaders'>Profiler.getProfileHeaders</a></li>\n<li><a href='#Profiler.getCPUProfile'>Profiler.getCPUProfile</a></li>\n<li><a href='#Profiler.removeProfile'>Profiler.removeProfile</a></li>\n<li><a href='#Profiler.clearProfiles'>Profiler.clearProfiles</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Profiler.addProfileHeader'>Profiler.addProfileHeader</a></li>\n<li><a href='#Profiler.setRecordingProfile'>Profiler.setRecordingProfile</a></li>\n<li><a href='#Profiler.resetProfiles'>Profiler.resetProfiles</a></li>\n</ul>\n<div id='Profiler_ProfileHeader' class='type'>\n<h3>Profiler.ProfileHeader <span class='label'>Type</span></h3>\n<p>Profile header.</p>\n<dl>\n<dt>title</dt>\n<dd>String <span class='text'>Profile title.</span></dd>\n<dt>uid</dt>\n<dd>Integer <span class='text'>Unique identifier of the profile.</span></dd>\n</dl>\n</div>\n<div id='Profiler_CPUProfileNode' class='type'>\n<h3>Profiler.CPUProfileNode <span class='label'>Type</span></h3>\n<p>CPU Profile node. Holds callsite information, execution statistics and child nodes.</p>\n<dl>\n<dt>functionName</dt>\n<dd>String <span class='text'>Function name.</span></dd>\n<dt>scriptId</dt>\n<dd><a href='#Debugger.ScriptId'>Debugger.ScriptId</a> <span class='text'>Script identifier.</span></dd>\n<dt>url</dt>\n<dd>String <span class='text'>URL.</span></dd>\n<dt>lineNumber</dt>\n<dd>Integer <span class='text'>Line number.</span></dd>\n<dt>hitCount</dt>\n<dd>Integer <span class='text'>Number of samples where this node was on top of the call stack.</span></dd>\n<dt>callUID</dt>\n<dd>Number <span class='text'>Call UID.</span></dd>\n<dt>children</dt>\n<dd>[<a href='#Profiler.CPUProfileNode'>Profiler.CPUProfileNode</a>] <span class='text'>Child nodes.</span></dd>\n<dt>deoptReason</dt>\n<dd>String <span class='text'>The reason of being not optimized. The function may be deoptimized or marked as don't optimize.</span></dd>\n<dt>id (optional)</dt>\n<dd>Integer <span class='text'>Unique id of the node.</span></dd>\n</dl>\n</div>\n<div id='Profiler_CPUProfile' class='type'>\n<h3>Profiler.CPUProfile <span class='label'>Type</span></h3>\n<p>Profile.</p>\n<dl>\n<dt>head</dt>\n<dd><a href='#Profiler.CPUProfileNode'>Profiler.CPUProfileNode</a></dd>\n<dt>startTime</dt>\n<dd>Number <span class='text'>Profiling start time in seconds.</span></dd>\n<dt>endTime</dt>\n<dd>Number <span class='text'>Profiling end time in seconds.</span></dd>\n<dt>samples (optional)</dt>\n<dd>[Integer] <span class='text'>Ids of samples top nodes.</span></dd>\n</dl>\n</div>\n<div id='Profiler_HeapSnapshotObjectId' class='type'>\n<h3>Profiler.HeapSnapshotObjectId <span class='label'>Type</span></h3>\n<p>Heap snashot object id.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Profiler_enable' class='command'>\n<h3>Profiler.enable <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.enable\nProfiler.enable();\n</pre>\n</div>\n<div id='Profiler_disable' class='command'>\n<h3>Profiler.disable <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.disable\nProfiler.disable();\n</pre>\n</div>\n<div id='Profiler_setSamplingInterval' class='command'>\n<h3>Profiler.setSamplingInterval <span class='label label-success'>Command</span></h3>\n<p>Changes CPU profiler sampling interval. Must be called before CPU profiles recording started.</p>\n<dl>\n<dt>interval</dt>\n<dd>Integer <span class='text'>New sampling interval in microseconds.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.setSamplingInterval\nProfiler.setSamplingInterval(interval);\n</pre>\n</div>\n<div id='Profiler_start' class='command'>\n<h3>Profiler.start <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.start\nProfiler.start();\n</pre>\n</div>\n<div id='Profiler_stop' class='command'>\n<h3>Profiler.stop <span class='label label-success'>Command</span></h3>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>header</dt>\n<dd><a href='#Profiler.ProfileHeader'>Profiler.ProfileHeader</a> <span class='text'>The header of the recorded profile.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.stop\nProfiler.stop(function callback(res) {\n\t// res = {header}\n});\n</pre>\n</div>\n<div id='Profiler_getProfileHeaders' class='command'>\n<h3>Profiler.getProfileHeaders <span class='label label-success'>Command</span></h3>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>headers</dt>\n<dd>[<a href='#Profiler.ProfileHeader'>Profiler.ProfileHeader</a>]</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.getProfileHeaders\nProfiler.getProfileHeaders(function callback(res) {\n\t// res = {headers}\n});\n</pre>\n</div>\n<div id='Profiler_getCPUProfile' class='command'>\n<h3>Profiler.getCPUProfile <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>uid</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>profile</dt>\n<dd><a href='#Profiler.CPUProfile'>Profiler.CPUProfile</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.getCPUProfile\nProfiler.getCPUProfile(uid, function callback(res) {\n\t// res = {profile}\n});\n</pre>\n</div>\n<div id='Profiler_removeProfile' class='command'>\n<h3>Profiler.removeProfile <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>type</dt>\n<dd>String</dd>\n<dt>uid</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.removeProfile\nProfiler.removeProfile(type, uid);\n</pre>\n</div>\n<div id='Profiler_clearProfiles' class='command'>\n<h3>Profiler.clearProfiles <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Profiler.clearProfiles\nProfiler.clearProfiles();\n</pre>\n</div>\n<div id='Profiler_addProfileHeader' class='command'>\n<h3>Profiler.addProfileHeader <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>header</dt>\n<dd><a href='#Profiler.ProfileHeader'>Profiler.ProfileHeader</a></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Profiler.addProfileHeader\nfunction onAddProfileHeader(res) {\n\t// res = {header}\n}\n</pre>\n</div>\n<div id='Profiler_setRecordingProfile' class='command'>\n<h3>Profiler.setRecordingProfile <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>isProfiling</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Profiler.setRecordingProfile\nfunction onSetRecordingProfile(res) {\n\t// res = {isProfiling}\n}\n</pre>\n</div>\n<div id='Profiler_resetProfiles' class='command'>\n<h3>Profiler.resetProfiles <span class='label label-info'>Event</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Profiler.resetProfiles\nfunction onResetProfiles(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n<section id='Runtime' class='domain'>\n<h1>Runtime</h1>\n<p>Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a>: Unique object identifier.</li>\n<li><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a>: Mirror object referencing original JavaScript object.</li>\n<li><a href='#Runtime.ObjectPreview'>Runtime.ObjectPreview</a>: Object containing abbreviated remote object value.</li>\n<li><a href='#Runtime.PropertyPreview'>Runtime.PropertyPreview</a></li>\n<li><a href='#Runtime.PropertyDescriptor'>Runtime.PropertyDescriptor</a>: Object property descriptor.</li>\n<li><a href='#Runtime.InternalPropertyDescriptor'>Runtime.InternalPropertyDescriptor</a>: Object internal property descriptor. This property isn't normally visible in JavaScript code.</li>\n<li><a href='#Runtime.CallArgument'>Runtime.CallArgument</a>: Represents function call argument. Either remote object id objectId or primitive value or neither of (for undefined) them should be specified.</li>\n<li><a href='#Runtime.ExecutionContextId'>Runtime.ExecutionContextId</a>: Id of an execution context.</li>\n<li><a href='#Runtime.ExecutionContextDescription'>Runtime.ExecutionContextDescription</a>: Description of an isolated world.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Runtime.evaluate'>Runtime.evaluate</a>: Evaluates expression on global object.</li>\n<li><a href='#Runtime.callFunctionOn'>Runtime.callFunctionOn</a>: Calls function with given declaration on the given object. Object group of the result is inherited from the target object.</li>\n<li><a href='#Runtime.getProperties'>Runtime.getProperties</a>: Returns properties of a given object. Object group of the result is inherited from the target object.</li>\n<li><a href='#Runtime.releaseObject'>Runtime.releaseObject</a>: Releases remote object with given id.</li>\n<li><a href='#Runtime.releaseObjectGroup'>Runtime.releaseObjectGroup</a>: Releases all remote objects that belong to a given group.</li>\n<li><a href='#Runtime.run'>Runtime.run</a>: Tells inspected instance(worker or page) that it can run in case it was started paused.</li>\n<li><a href='#Runtime.enable'>Runtime.enable</a>: Enables reporting of execution contexts creation by means of executionContextCreated event. When the reporting gets enabled the event will be sent immediately for each existing execution context.</li>\n<li><a href='#Runtime.disable'>Runtime.disable</a>: Disables reporting of execution contexts creation.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Runtime.executionContextCreated'>Runtime.executionContextCreated</a>: Issued when new execution context is created.</li>\n</ul>\n<div id='Runtime_RemoteObjectId' class='type'>\n<h3>Runtime.RemoteObjectId <span class='label'>Type</span></h3>\n<p>Unique object identifier.</p>\n<dl>\n<dd>String</dd>\n</dl>\n</div>\n<div id='Runtime_RemoteObject' class='type'>\n<h3>Runtime.RemoteObject <span class='label'>Type</span></h3>\n<p>Mirror object referencing original JavaScript object.</p>\n<dl>\n<dt>type</dt>\n<dd>( object | function | undefined | string | number | boolean ) <span class='text'>Object type.</span></dd>\n<dt>subtype (optional)</dt>\n<dd>( array | null | node | regexp | date ) <span class='text'>Object subtype hint. Specified for <code>object</code> type values only.</span></dd>\n<dt>className (optional)</dt>\n<dd>String <span class='text'>Object class (constructor) name. Specified for <code>object</code> type values only.</span></dd>\n<dt>value (optional)</dt>\n<dd>Any <span class='text'>Remote object value (in case of primitive values or JSON values if it was requested).</span></dd>\n<dt>description (optional)</dt>\n<dd>String <span class='text'>String representation of the object.</span></dd>\n<dt>objectId (optional)</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Unique object identifier (for non-primitive values).</span></dd>\n<dt>preview (optional)</dt>\n<dd><a href='#Runtime.ObjectPreview'>Runtime.ObjectPreview</a> <span class='text'>Preview containing abbreviated property values.</span></dd>\n</dl>\n</div>\n<div id='Runtime_ObjectPreview' class='type'>\n<h3>Runtime.ObjectPreview <span class='label'>Type</span></h3>\n<p>Object containing abbreviated remote object value.</p>\n<dl>\n<dt>lossless</dt>\n<dd>Boolean <span class='text'>Determines whether preview is lossless (contains all information of the original object).</span></dd>\n<dt>overflow</dt>\n<dd>Boolean <span class='text'>True iff some of the properties of the original did not fit.</span></dd>\n<dt>properties</dt>\n<dd>[<a href='#Runtime.PropertyPreview'>Runtime.PropertyPreview</a>] <span class='text'>List of the properties.</span></dd>\n</dl>\n</div>\n<div id='Runtime_PropertyPreview' class='type'>\n<h3>Runtime.PropertyPreview <span class='label'>Type</span></h3>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Property name.</span></dd>\n<dt>type</dt>\n<dd>( object | function | undefined | string | number | boolean ) <span class='text'>Object type.</span></dd>\n<dt>value (optional)</dt>\n<dd>String <span class='text'>User-friendly property value string.</span></dd>\n<dt>valuePreview (optional)</dt>\n<dd><a href='#Runtime.ObjectPreview'>Runtime.ObjectPreview</a> <span class='text'>Nested value preview.</span></dd>\n<dt>subtype (optional)</dt>\n<dd>( array | null | node | regexp | date ) <span class='text'>Object subtype hint. Specified for <code>object</code> type values only.</span></dd>\n</dl>\n</div>\n<div id='Runtime_PropertyDescriptor' class='type'>\n<h3>Runtime.PropertyDescriptor <span class='label'>Type</span></h3>\n<p>Object property descriptor.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Property name.</span></dd>\n<dt>value (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>The value associated with the property.</span></dd>\n<dt>writable (optional)</dt>\n<dd>Boolean <span class='text'>True if the value associated with the property may be changed (data descriptors only).</span></dd>\n<dt>get (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>A function which serves as a getter for the property, or <code>undefined</code> if there is no getter (accessor descriptors only).</span></dd>\n<dt>set (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>A function which serves as a setter for the property, or <code>undefined</code> if there is no setter (accessor descriptors only).</span></dd>\n<dt>configurable</dt>\n<dd>Boolean <span class='text'>True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.</span></dd>\n<dt>enumerable</dt>\n<dd>Boolean <span class='text'>True if this property shows up during enumeration of the properties on the corresponding object.</span></dd>\n<dt>wasThrown (optional)</dt>\n<dd>Boolean <span class='text'>True if the result was thrown during the evaluation.</span></dd>\n<dt>isOwn (optional)</dt>\n<dd>Boolean <span class='text'>True if the property is owned for the object.</span></dd>\n</dl>\n</div>\n<div id='Runtime_InternalPropertyDescriptor' class='type'>\n<h3>Runtime.InternalPropertyDescriptor <span class='label'>Type</span></h3>\n<p>Object internal property descriptor. This property isn't normally visible in JavaScript code.</p>\n<dl>\n<dt>name</dt>\n<dd>String <span class='text'>Conventional property name.</span></dd>\n<dt>value (optional)</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>The value associated with the property.</span></dd>\n</dl>\n</div>\n<div id='Runtime_CallArgument' class='type'>\n<h3>Runtime.CallArgument <span class='label'>Type</span></h3>\n<p>Represents function call argument. Either remote object id <code>objectId</code> or primitive <code>value</code> or neither of (for undefined) them should be specified.</p>\n<dl>\n<dt>value (optional)</dt>\n<dd>Any <span class='text'>Primitive value.</span></dd>\n<dt>objectId (optional)</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Remote object handle.</span></dd>\n</dl>\n</div>\n<div id='Runtime_ExecutionContextId' class='type'>\n<h3>Runtime.ExecutionContextId <span class='label'>Type</span></h3>\n<p>Id of an execution context.</p>\n<dl>\n<dd>Integer</dd>\n</dl>\n</div>\n<div id='Runtime_ExecutionContextDescription' class='type'>\n<h3>Runtime.ExecutionContextDescription <span class='label'>Type</span></h3>\n<p>Description of an isolated world.</p>\n<dl>\n<dt>id</dt>\n<dd><a href='#Runtime.ExecutionContextId'>Runtime.ExecutionContextId</a> <span class='text'>Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed.</span></dd>\n<dt>isPageContext</dt>\n<dd>Boolean <span class='text'>True if this is a context where inspected web page scripts run. False if it is a content script isolated context.</span></dd>\n<dt>name</dt>\n<dd>String <span class='text'>Human readable name describing given context.</span></dd>\n<dt>frameId</dt>\n<dd><a href='#Page.FrameId'>Page.FrameId</a> <span class='text'>Id of the owning frame.</span></dd>\n</dl>\n</div>\n<div id='Runtime_evaluate' class='command'>\n<h3>Runtime.evaluate <span class='label label-success'>Command</span></h3>\n<p>Evaluates expression on global object.</p>\n<dl>\n<dt>expression</dt>\n<dd>String <span class='text'>Expression to evaluate.</span></dd>\n<dt>objectGroup (optional)</dt>\n<dd>String <span class='text'>Symbolic group name that can be used to release multiple objects.</span></dd>\n<dt>includeCommandLineAPI (optional)</dt>\n<dd>Boolean <span class='text'>Determines whether Command Line API should be available during the evaluation.</span></dd>\n<dt>doNotPauseOnExceptionsAndMuteConsole (optional)</dt>\n<dd>Boolean <span class='text'>Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.</span></dd>\n<dt>contextId (optional)</dt>\n<dd><a href='#Runtime.ExecutionContextId'>Runtime.ExecutionContextId</a> <span class='text'>Specifies in which isolated context to perform evaluation. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page.</span></dd>\n<dt>returnByValue (optional)</dt>\n<dd>Boolean <span class='text'>Whether the result is expected to be a JSON object that should be sent by value.</span></dd>\n<dt>generatePreview (optional)</dt>\n<dd>Boolean <span class='text'>Whether preview should be generated for the result.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Evaluation result.</span></dd>\n<dt>wasThrown (optional)</dt>\n<dd>Boolean <span class='text'>True if the result was thrown during the evaluation.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.evaluate\nRuntime.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, contextId, returnByValue, generatePreview, function callback(res) {\n\t// res = {result, wasThrown}\n});\n</pre>\n</div>\n<div id='Runtime_callFunctionOn' class='command'>\n<h3>Runtime.callFunctionOn <span class='label label-success'>Command</span></h3>\n<p>Calls function with given declaration on the given object. Object group of the result is inherited from the target object.</p>\n<dl>\n<dt>objectId</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Identifier of the object to call function on.</span></dd>\n<dt>functionDeclaration</dt>\n<dd>String <span class='text'>Declaration of the function to call.</span></dd>\n<dt>arguments (optional)</dt>\n<dd>[<a href='#Runtime.CallArgument'>Runtime.CallArgument</a>] <span class='text'>Call arguments. All call arguments must belong to the same JavaScript world as the target object.</span></dd>\n<dt>doNotPauseOnExceptionsAndMuteConsole (optional)</dt>\n<dd>Boolean <span class='text'>Specifies whether function call should stop on exceptions and mute console. Overrides setPauseOnException state.</span></dd>\n<dt>returnByValue (optional)</dt>\n<dd>Boolean <span class='text'>Whether the result is expected to be a JSON object which should be sent by value.</span></dd>\n<dt>generatePreview (optional)</dt>\n<dd>Boolean <span class='text'>Whether preview should be generated for the result.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd><a href='#Runtime.RemoteObject'>Runtime.RemoteObject</a> <span class='text'>Call result.</span></dd>\n<dt>wasThrown (optional)</dt>\n<dd>Boolean <span class='text'>True if the result was thrown during the evaluation.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.callFunctionOn\nRuntime.callFunctionOn(objectId, functionDeclaration, arguments, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, function callback(res) {\n\t// res = {result, wasThrown}\n});\n</pre>\n</div>\n<div id='Runtime_getProperties' class='command'>\n<h3>Runtime.getProperties <span class='label label-success'>Command</span></h3>\n<p>Returns properties of a given object. Object group of the result is inherited from the target object.</p>\n<dl>\n<dt>objectId</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Identifier of the object to return properties for.</span></dd>\n<dt>ownProperties (optional)</dt>\n<dd>Boolean <span class='text'>If true, returns properties belonging only to the element itself, not to its prototype chain.</span></dd>\n<dt>accessorPropertiesOnly (optional)</dt>\n<dd>Boolean <span class='text'>If true, returns accessor properties (with getter/setter) only; internal properties are not returned either.</span></dd>\n</dl>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>[<a href='#Runtime.PropertyDescriptor'>Runtime.PropertyDescriptor</a>] <span class='text'>Object properties.</span></dd>\n<dt>internalProperties (optional)</dt>\n<dd>[<a href='#Runtime.InternalPropertyDescriptor'>Runtime.InternalPropertyDescriptor</a>] <span class='text'>Internal object properties (only of the element itself).</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.getProperties\nRuntime.getProperties(objectId, ownProperties, accessorPropertiesOnly, function callback(res) {\n\t// res = {result, internalProperties}\n});\n</pre>\n</div>\n<div id='Runtime_releaseObject' class='command'>\n<h3>Runtime.releaseObject <span class='label label-success'>Command</span></h3>\n<p>Releases remote object with given id.</p>\n<dl>\n<dt>objectId</dt>\n<dd><a href='#Runtime.RemoteObjectId'>Runtime.RemoteObjectId</a> <span class='text'>Identifier of the object to release.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.releaseObject\nRuntime.releaseObject(objectId);\n</pre>\n</div>\n<div id='Runtime_releaseObjectGroup' class='command'>\n<h3>Runtime.releaseObjectGroup <span class='label label-success'>Command</span></h3>\n<p>Releases all remote objects that belong to a given group.</p>\n<dl>\n<dt>objectGroup</dt>\n<dd>String <span class='text'>Symbolic object group name.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.releaseObjectGroup\nRuntime.releaseObjectGroup(objectGroup);\n</pre>\n</div>\n<div id='Runtime_run' class='command'>\n<h3>Runtime.run <span class='label label-success'>Command</span></h3>\n<p>Tells inspected instance(worker or page) that it can run in case it was started paused.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.run\nRuntime.run();\n</pre>\n</div>\n<div id='Runtime_enable' class='command'>\n<h3>Runtime.enable <span class='label label-success'>Command</span></h3>\n<p>Enables reporting of execution contexts creation by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.enable\nRuntime.enable();\n</pre>\n</div>\n<div id='Runtime_disable' class='command'>\n<h3>Runtime.disable <span class='label label-success'>Command</span></h3>\n<p>Disables reporting of execution contexts creation.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Runtime.disable\nRuntime.disable();\n</pre>\n</div>\n<div id='Runtime_executionContextCreated' class='command'>\n<h3>Runtime.executionContextCreated <span class='label label-info'>Event</span></h3>\n<p>Issued when new execution context is created.</p>\n<dl>\n<dt>context</dt>\n<dd><a href='#Runtime.ExecutionContextDescription'>Runtime.ExecutionContextDescription</a> <span class='text'>A newly created execution contex.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Runtime.executionContextCreated\nfunction onExecutionContextCreated(res) {\n\t// res = {context}\n}\n</pre>\n</div>\n</section>\n<section id='Timeline' class='domain'>\n<h1>Timeline</h1>\n<p>Timeline provides its clients with instrumentation records that are generated during the page runtime. Timeline instrumentation can be started and stopped using corresponding commands. While timeline is started, it is generating timeline event records.</p>\n<span class='label'>Type</span>\n<ul>\n<li><a href='#Timeline.DOMCounters'>Timeline.DOMCounters</a>: Current values of DOM counters.</li>\n<li><a href='#Timeline.TimelineEvent'>Timeline.TimelineEvent</a>: Timeline record contains information about the recorded activity.</li>\n</ul>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Timeline.enable'>Timeline.enable</a>: Enables timeline. After this call, timeline can be started from within the page (for example upon console.timeline).</li>\n<li><a href='#Timeline.disable'>Timeline.disable</a>: Disables timeline.</li>\n<li><a href='#Timeline.start'>Timeline.start</a>: Starts capturing instrumentation events.</li>\n<li><a href='#Timeline.stop'>Timeline.stop</a>: Stops capturing instrumentation events.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Timeline.eventRecorded'>Timeline.eventRecorded</a>: Fired for every instrumentation event while timeline is started.</li>\n<li><a href='#Timeline.started'>Timeline.started</a>: Fired when timeline is started.</li>\n<li><a href='#Timeline.stopped'>Timeline.stopped</a>: Fired when timeline is stopped.</li>\n</ul>\n<div id='Timeline_DOMCounters' class='type'>\n<h3>Timeline.DOMCounters <span class='label'>Type</span></h3>\n<p>Current values of DOM counters.</p>\n<dl>\n<dt>documents</dt>\n<dd>Integer</dd>\n<dt>nodes</dt>\n<dd>Integer</dd>\n<dt>jsEventListeners</dt>\n<dd>Integer</dd>\n</dl>\n</div>\n<div id='Timeline_TimelineEvent' class='type'>\n<h3>Timeline.TimelineEvent <span class='label'>Type</span></h3>\n<p>Timeline record contains information about the recorded activity.</p>\n<dl>\n<dt>type</dt>\n<dd>String <span class='text'>Event type.</span></dd>\n<dt>thread (optional)</dt>\n<dd>String <span class='text'>If present, identifies the thread that produced the event.</span></dd>\n<dt>data</dt>\n<dd>Object <span class='text'>Event data.</span></dd>\n<dt>children (optional)</dt>\n<dd>[<a href='#Timeline.TimelineEvent'>Timeline.TimelineEvent</a>] <span class='text'>Nested records.</span></dd>\n<dt>counters (optional)</dt>\n<dd><a href='#Timeline.DOMCounters'>Timeline.DOMCounters</a> <span class='text'>Current values of DOM counters.</span></dd>\n<dt>usedHeapSize (optional)</dt>\n<dd>Integer <span class='text'>Current size of JS heap.</span></dd>\n<dt>nativeHeapStatistics (optional)</dt>\n<dd>Object <span class='text'>Native heap statistics.</span></dd>\n</dl>\n</div>\n<div id='Timeline_enable' class='command'>\n<h3>Timeline.enable <span class='label label-success'>Command</span></h3>\n<p>Enables timeline. After this call, timeline can be started from within the page (for example upon console.timeline).</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Timeline.enable\nTimeline.enable();\n</pre>\n</div>\n<div id='Timeline_disable' class='command'>\n<h3>Timeline.disable <span class='label label-success'>Command</span></h3>\n<p>Disables timeline.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Timeline.disable\nTimeline.disable();\n</pre>\n</div>\n<div id='Timeline_start' class='command'>\n<h3>Timeline.start <span class='label label-success'>Command</span></h3>\n<p>Starts capturing instrumentation events.</p>\n<dl>\n<dt>maxCallStackDepth (optional)</dt>\n<dd>Integer <span class='text'>Samples JavaScript stack traces up to <code>maxCallStackDepth</code>, defaults to 5.</span></dd>\n<dt>bufferEvents (optional)</dt>\n<dd>Boolean <span class='text'>Whether instrumentation events should be buffered and returned upon <code>stop</code> call.</span></dd>\n<dt>includeDomCounters (optional)</dt>\n<dd>Boolean <span class='text'>Whether DOM counters data should be included into timeline events.</span></dd>\n<dt>includeNativeMemoryStatistics (optional)</dt>\n<dd>Boolean <span class='text'>Whether native memory usage statistics should be reported as part of timeline events.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Timeline.start\nTimeline.start(maxCallStackDepth, bufferEvents, includeDomCounters, includeNativeMemoryStatistics);\n</pre>\n</div>\n<div id='Timeline_stop' class='command'>\n<h3>Timeline.stop <span class='label label-success'>Command</span></h3>\n<p>Stops capturing instrumentation events.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>events (optional)</dt>\n<dd>[<a href='#Timeline.TimelineEvent'>Timeline.TimelineEvent</a>] <span class='text'>Timeline event record data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Timeline.stop\nTimeline.stop(function callback(res) {\n\t// res = {events}\n});\n</pre>\n</div>\n<div id='Timeline_eventRecorded' class='command'>\n<h3>Timeline.eventRecorded <span class='label label-info'>Event</span></h3>\n<p>Fired for every instrumentation event while timeline is started.</p>\n<dl>\n<dt>record</dt>\n<dd><a href='#Timeline.TimelineEvent'>Timeline.TimelineEvent</a> <span class='text'>Timeline event record data.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Timeline.eventRecorded\nfunction onEventRecorded(res) {\n\t// res = {record}\n}\n</pre>\n</div>\n<div id='Timeline_started' class='command'>\n<h3>Timeline.started <span class='label label-info'>Event</span></h3>\n<p>Fired when timeline is started.</p>\n<dl>\n<dt>consoleTimeline (optional)</dt>\n<dd>Boolean <span class='text'>If specified, identifies that timeline was started using console.timeline() call.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Timeline.started\nfunction onStarted(res) {\n\t// res = {consoleTimeline}\n}\n</pre>\n</div>\n<div id='Timeline_stopped' class='command'>\n<h3>Timeline.stopped <span class='label label-info'>Event</span></h3>\n<p>Fired when timeline is stopped.</p>\n<dl>\n<dt>consoleTimeline (optional)</dt>\n<dd>Boolean <span class='text'>If specified, identifies that timeline was started using console.timeline() call.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Timeline.stopped\nfunction onStopped(res) {\n\t// res = {consoleTimeline}\n}\n</pre>\n</div>\n</section>\n<section id='Tracing' class='domain'>\n<h1>Tracing</h1>\n<p></p>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Tracing.start'>Tracing.start</a>: Strart trace events collection.</li>\n<li><a href='#Tracing.end'>Tracing.end</a>: Stop trace events collection.</li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Tracing.dataCollected'>Tracing.dataCollected</a></li>\n<li><a href='#Tracing.tracingComplete'>Tracing.tracingComplete</a></li>\n</ul>\n<div id='Tracing_start' class='command'>\n<h3>Tracing.start <span class='label label-success'>Command</span></h3>\n<p>Strart trace events collection.</p>\n<dl>\n<dt>categories</dt>\n<dd>String <span class='text'>Category/tag filter</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Tracing.start\nTracing.start(categories);\n</pre>\n</div>\n<div id='Tracing_end' class='command'>\n<h3>Tracing.end <span class='label label-success'>Command</span></h3>\n<p>Stop trace events collection.</p>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Tracing.end\nTracing.end();\n</pre>\n</div>\n<div id='Tracing_dataCollected' class='command'>\n<h3>Tracing.dataCollected <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>value</dt>\n<dd>[Object]</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Tracing.dataCollected\nfunction onDataCollected(res) {\n\t// res = {value}\n}\n</pre>\n</div>\n<div id='Tracing_tracingComplete' class='command'>\n<h3>Tracing.tracingComplete <span class='label label-info'>Event</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Tracing.tracingComplete\nfunction onTracingComplete(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n<section id='Worker' class='domain'>\n<h1>Worker</h1>\n<p></p>\n<span class='label label-success'>Command</span>\n<ul>\n<li><a href='#Worker.enable'>Worker.enable</a></li>\n<li><a href='#Worker.disable'>Worker.disable</a></li>\n<li><a href='#Worker.sendMessageToWorker'>Worker.sendMessageToWorker</a></li>\n<li><a href='#Worker.canInspectWorkers'>Worker.canInspectWorkers</a>: Tells whether browser supports workers inspection.</li>\n<li><a href='#Worker.connectToWorker'>Worker.connectToWorker</a></li>\n<li><a href='#Worker.disconnectFromWorker'>Worker.disconnectFromWorker</a></li>\n<li><a href='#Worker.setAutoconnectToWorkers'>Worker.setAutoconnectToWorkers</a></li>\n</ul>\n<span class='label label-info'>Event</span>\n<ul>\n<li><a href='#Worker.workerCreated'>Worker.workerCreated</a></li>\n<li><a href='#Worker.workerTerminated'>Worker.workerTerminated</a></li>\n<li><a href='#Worker.dispatchMessageFromWorker'>Worker.dispatchMessageFromWorker</a></li>\n<li><a href='#Worker.disconnectedFromWorker'>Worker.disconnectedFromWorker</a></li>\n</ul>\n<div id='Worker_enable' class='command'>\n<h3>Worker.enable <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.enable\nWorker.enable();\n</pre>\n</div>\n<div id='Worker_disable' class='command'>\n<h3>Worker.disable <span class='label label-success'>Command</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.disable\nWorker.disable();\n</pre>\n</div>\n<div id='Worker_sendMessageToWorker' class='command'>\n<h3>Worker.sendMessageToWorker <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>workerId</dt>\n<dd>Integer</dd>\n<dt>message</dt>\n<dd>Object</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.sendMessageToWorker\nWorker.sendMessageToWorker(workerId, message);\n</pre>\n</div>\n<div id='Worker_canInspectWorkers' class='command'>\n<h3>Worker.canInspectWorkers <span class='label label-success'>Command</span></h3>\n<p>Tells whether browser supports workers inspection.</p>\n<h4>Callback Parameters:</h4>\n<dl>\n<dt>result</dt>\n<dd>Boolean <span class='text'>True if browser has workers support.</span></dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.canInspectWorkers\nWorker.canInspectWorkers(function callback(res) {\n\t// res = {result}\n});\n</pre>\n</div>\n<div id='Worker_connectToWorker' class='command'>\n<h3>Worker.connectToWorker <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>workerId</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.connectToWorker\nWorker.connectToWorker(workerId);\n</pre>\n</div>\n<div id='Worker_disconnectFromWorker' class='command'>\n<h3>Worker.disconnectFromWorker <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>workerId</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.disconnectFromWorker\nWorker.disconnectFromWorker(workerId);\n</pre>\n</div>\n<div id='Worker_setAutoconnectToWorkers' class='command'>\n<h3>Worker.setAutoconnectToWorkers <span class='label label-success'>Command</span></h3>\n<dl>\n<dt>value</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Command: Worker.setAutoconnectToWorkers\nWorker.setAutoconnectToWorkers(value);\n</pre>\n</div>\n<div id='Worker_workerCreated' class='command'>\n<h3>Worker.workerCreated <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>workerId</dt>\n<dd>Integer</dd>\n<dt>url</dt>\n<dd>String</dd>\n<dt>inspectorConnected</dt>\n<dd>Boolean</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Worker.workerCreated\nfunction onWorkerCreated(res) {\n\t// res = {workerId, url, inspectorConnected}\n}\n</pre>\n</div>\n<div id='Worker_workerTerminated' class='command'>\n<h3>Worker.workerTerminated <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>workerId</dt>\n<dd>Integer</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Worker.workerTerminated\nfunction onWorkerTerminated(res) {\n\t// res = {workerId}\n}\n</pre>\n</div>\n<div id='Worker_dispatchMessageFromWorker' class='command'>\n<h3>Worker.dispatchMessageFromWorker <span class='label label-info'>Event</span></h3>\n<dl>\n<dt>workerId</dt>\n<dd>Integer</dd>\n<dt>message</dt>\n<dd>Object</dd>\n</dl>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Worker.dispatchMessageFromWorker\nfunction onDispatchMessageFromWorker(res) {\n\t// res = {workerId, message}\n}\n</pre>\n</div>\n<div id='Worker_disconnectedFromWorker' class='command'>\n<h3>Worker.disconnectedFromWorker <span class='label label-info'>Event</span></h3>\n<h4>Code Example:</h4>\n<pre>\n// WebInspector Event: Worker.disconnectedFromWorker\nfunction onDisconnectedFromWorker(res) {\n\t// res = {}\n}\n</pre>\n</div>\n</section>\n</div>\n<footer>\n<p>Generated from Inspector.json v1.1 on 2014-12-08 11:14:07-0800</p>\n<p>Implementation by <a href='mailto:jdiehl@adobe.com'>Jonathan Diehl</a></p>\n</footer>\n</body>\n</html>\n"
  },
  {
    "path": "src/LiveDevelopment/Inspector/jsdoc.rb",
    "content": "#!/bin/ruby\n#\n#\n# Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n#  \n# Permission is hereby granted, free of charge, to any person obtaining a\n# copy of this software and associated documentation files (the \"Software\"), \n# to deal in the Software without restriction, including without limitation \n# the rights to use, copy, modify, merge, publish, distribute, sublicense, \n# and/or sell copies of the Software, and to permit persons to whom the \n# Software is furnished to do so, subject to the following conditions:\n#  \n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#  \n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n# DEALINGS IN THE SOFTWARE.\n# \n#\n# This script generates debugger documentation from Inspector.json\n#\n# Required Ruby Gems\n#  json date open-uri\n\nrequire \"rubygems\"\nrequire \"json\"\nrequire \"date\"\nrequire \"open-uri\"\n\n#INSPECTOR_URL   = \"http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/inspector/Inspector.json\"\nINSPECTOR_URL   = \"Inspector.json\"\nOUTPUT          = \"inspector.html\"\n\nclass NilClass\n\tdef empty?\n\t\ttrue\n\tend\n\tdef each\n\tend\nend\n\nclass String\n\tdef upcaseFirst\n\t\tself[0, 1].upcase + self[1, self.length - 1]\n\tend\nend\n\nclass JSDoc\n\n\tdef typedef(domain, info)\n\t\treturn \"[\" + typedef(domain, info['items']) + \"]\" if info['items']\n\t\tif info[\"$ref\"]\n\t\t\tref = info[\"$ref\"]\n\t\t\tref = domain + \".\" + ref unless ref =~ /\\./\n\t\t\tr = \"<a href='##{ref}'>#{ref}</a>\" if info[\"$ref\"]\n\t\telsif info[\"enum\"]\n\t\t\tr = \"( #{info['enum'].join \" | \"} )\"\n\t\telse\n\t\t\tr = info[\"type\"].upcaseFirst\n\t\tend\n\t\tr\n\tend\n\n\tdef initialize(input, output)\n\t\t@input = input\n\t\t@output = output\n\tend\n\n\tdef open\n\t\t@in = JSON.parse(File.open(@input).read)\n\t\t@in[\"domains\"].sort! { |a,b| a[\"domain\"] <=> b[\"domain\"] }\n\t\t@version = \"#{@in['version']['major']}.#{@in['version']['minor']}\"\n\t\tFile.open(@output, \"w\") do |out|\n\t\t\t@out = out\n\t\t\tyield\n\t\tend\n\tend\n\n\tdef run\n\t\topen do \n\t\t\twriteDocument do\n\t\t\t\twriteTOC\n\t\t\t\t@in[\"domains\"].each { |domain| writeDomain domain }\n\t\t\tend\n\t\tend\n\tend\n\n\tdef write(*args)\n\t\targs.each { |line| @out.write line + \"\\n\" }\n\tend\n\n\tdef writeParams(domain, params, prefixLine = false)\n\t\treturn unless params\n\t\twrite prefixLine if prefixLine\n\t\twrite \"<dl>\"\n\t\tparams.each do |p|\n\t\t\tname = p[\"name\"]\n\t\t\tdescription = \" <span class='text'>#{p['description']}</span>\" if p['description']\n\t\t\ttype = typedef domain, p\n\t\t\tname += \" (optional)\" if p['optional']\n\t\t\twrite \"<dt>#{name}</dt>\"\n\t\t\twrite \"<dd>#{type}#{description}</dd>\"\n\t\tend\n\t\twrite \"</dl>\"\n\tend\n\n\tdef writeTOCLine(domain, info)\n\t\tinfo[\"name\"] ||= info[\"id\"]\n\t\tuid = \"#{domain}.#{info['name']}\"\n\t\tdescription = info['description'] ? \": #{info['description'].gsub(/<[^>]*>/, \"\")}\" : \"\"\n\t\twrite \"<li><a href='##{uid}'>#{uid}</a>#{description}</li>\"\n\tend\n\n\tdef writeTOCDomain(info)\n\t\tdomain = info[\"domain\"]\n\t\tunless info[\"types\"].empty?\n\t\t\twrite \"<span class='label'>Type</span>\", \"<ul>\"\n\t\t\tinfo[\"types\"].each { |p| writeTOCLine domain, p }\n\t\t\twrite \"</ul>\"\n\t\tend\n\t\tunless info[\"commands\"].empty?\n\t\t\twrite \"<span class='label label-success'>Command</span>\", \"<ul>\"\n\t\t\tinfo[\"commands\"].each { |p| writeTOCLine domain, p }\n\t\t\twrite \"</ul>\"\n\t\tend\n\t\tunless info[\"events\"].empty?\n\t\t\twrite \"<span class='label label-info'>Event</span>\", \"<ul>\"\n\t\t\tinfo[\"events\"].each { |p| writeTOCLine domain, p }\n\t\t\twrite \"</ul>\"\n\t\tend\n\tend\n\n\tdef writeDocument\n\t\t@out.write <<-eos\n<!DOCTYPE html>\n<html>\n<head>\n<title>Inspector #{@version} Documentation</title>\n<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js\"></script>\n<script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js\"></script>\n<script src=\"http://twitter.github.com/bootstrap/assets/js/bootstrap-dropdown.js\"></script>\n<script>\n$(function () {\nvar _domain = $(window.location.hash);\nif (_domain.length === 0) _domain = $(\"#toc\");\n$(\".domain\").hide();\n_domain.show();\n$(\".dropdown-toggle\").dropdown();\n$(\"a[href^=#]\").click(function (e) {\ne.preventDefault();\nvar domainAndName = e.currentTarget.hash.split(\".\");\nwindow.location = domainAndName[0];\nvar symbol = $(domainAndName.join(\"_\"));\nvar speed;\nif (_domain !== domainAndName[0]) {\n$(_domain).hide();\n_domain = domainAndName[0];\n$(_domain).show();\nspeed = 0;\n} else {\nspeed = \"fast\";\n}\n$(\"html, body\").animate({\nscrollTop: symbol.offset().top - 70 + \"px\"\n}, speed);\nif (domainAndName.length > 1) symbol.effect(\"highlight\", { color: \"#ffc\"}, 1000);\n});\n});\n</script>\n<link href=\"http://twitter.github.com/bootstrap/assets/css/bootstrap.css\" rel=\"stylesheet\">\n<style>\nbody {padding: 70px 0 20px 0;}\nh3, dl {font-family: Menlo, Monaco, \"Courier New\", monospace;}\ndl {font-size: 12.025px;}\ndl dd {margin-bottom: 6px;}\ndl .text {margin-left:12px; font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;}\nh3 {border-top: 1px solid #aaa; padding: 8px 0;}\nh3 .label {float: left; margin: 6px;}\nfooter p {text-align: center; margin: 0;}\n</style>\n</head>\n<body>\n<div class=\"navbar navbar-fixed-top\">\n<div class=\"navbar-inner\">\n<div class=\"container\">\n<a href=\"#toc\" class=\"brand\">WebInspector v#{@version}</a>\n<ul class=\"nav nav-pills\">\n<li class=\"dropdown\" id=\"domain-menu\">\n<a class=\"dropdown-toggle\" data-toggle=\"dropdown\">Domains<b class=\"caret\"></b></a>\n<ul class=\"dropdown-menu\">\neos\n\t\t@in[\"domains\"].each { |info| write \"<li><a href='##{info['domain']}'>#{info['domain']}</a></li>\" }\n\t\twrite \"</ul>\", \"</li>\", \"</ul>\", \"</div>\", \"</div>\", \"</div>\", \"<div class='container'>\"\n\t\tyield\n\t\twrite \"</div>\", \"<footer>\"\n\t\twrite \"<p>Generated from Inspector.json v#{@version} on #{DateTime.now.strftime '%F %T%z'}</p>\"\n\t\twrite \"<p>Implementation by <a href='mailto:jdiehl@adobe.com'>Jonathan Diehl</a></p>\"\n\t\twrite \"</footer>\", \"</body>\", \"</html>\"\n\tend\n\n\tdef writeTOC\n\t\twrite \"<section id='toc' class='domain'>\", \"<h1>Table of Contents</h1>\"\n\t\t@in[\"domains\"].each do |info|\n\t\t\tdomain = info[\"domain\"]\n\t\t\twrite \"<h3><a href=\\\"##{info['domain']}\\\">#{info['domain']}</a></h3>\"\n\t\t\twriteTOCDomain info\n\t\tend\n\t\twrite \"</section>\"\n\tend\n\n\tdef writeDomain(info)\n\t\tdomain, description = info[\"domain\"], info[\"description\"]\n\t\ttypes, commands, events = info[\"types\"], info[\"commands\"], info[\"events\"]\n\t\twrite \"<section id='#{domain}' class='domain'>\"\n\t\twrite \"<h1>#{domain}</h1>\"\n\t\twrite \"<p>#{description}</p>\"\n\t\twriteTOCDomain info\n\t\tif types\n\t\t\ttypes.each    { |info| writeType domain, info    }\n\t\tend\n\t\tif commands\n\t\t\tcommands.each    { |info| writeCommand domain, info    }\n\t\tend\n\t\tif events\n\t\t\tevents.each    { |info| writeEvent domain, info    }\n\t\tend\n\t\twrite \"</section>\"\n\tend\n\n\tdef writeType(domain, info)\n\t\tname, description = info[\"id\"], info[\"description\"]\n\t\ttype, enum, properties = info[\"type\"], info[\"enum\"], info[\"properties\"]\n\t\twrite \"<div id='#{domain}_#{name}' class='type'>\"\n\t\twrite \"<h3>#{domain}.#{name} <span class='label'>Type</span></h3>\"\n\t\twrite \"<p>#{description}</p>\" if description\n\t\tif type != \"object\"\n\t\t\twrite \"<dl>\"\n\t\t\twrite \"<dd>#{typedef domain, info}</dd>\"\n\t\t\twrite \"</dl>\"\n\t\tend\n\t\twriteParams domain, properties\n\t\twrite \"</div>\"\n\tend\n\n\tdef writeCommand(domain, info)\n\t\tname, description = info[\"name\"], info[\"description\"]\n\t\tparameters, returns = info[\"parameters\"], info[\"returns\"]\n\t\twrite \"<div id='#{domain}_#{name}' class='command'>\"\n\t\twrite \"<h3>#{domain}.#{name} <span class='label label-success'>Command</span></h3>\"\n\t\twrite \"<p>#{description}</p>\" if description\n\t\twriteParams domain, parameters\n\t\twriteParams domain, returns, \"<h4>Callback Parameters:</h4>\"\n\t\twrite \"<h4>Code Example:</h4>\", \"<pre>\"\n\t\tparamNames = parameters.collect { |p| p[\"name\"] } if parameters\n\t\tparamNames ||= []\n\t\tif returns\n\t\t\treturnNames = returns.collect { |p| p[\"name\"] }\n\t\t\tparamNames << \"function callback(res) {\\n\\t// res = {#{returnNames.join \", \"}}\\n}\"\n\t\tend\n\t\twrite \"// WebInspector Command: #{domain}.#{name}\"\n\t\twrite \"#{domain}.#{name}(#{paramNames.join \", \"});\"\n\t\twrite \"</pre>\", \"</div>\"\n\tend\n\n\tdef writeEvent(domain, info)\n\t\tname, description = info[\"name\"], info[\"description\"]\n\t\tparameters = info[\"parameters\"]\n\t\twrite \"<div id='#{domain}_#{name}' class='command'>\"\n\t\twrite \"<h3>#{domain}.#{name} <span class='label label-info'>Event</span></h3>\"\n\t\twrite \"<p>#{description}</p>\" if description\n\t\twriteParams domain, parameters\n\t\twrite \"<h4>Code Example:</h4>\", \"<pre>\"\n\t\tparamNames = parameters.collect { |p| p[\"name\"] } if parameters\n\t\tparamNames ||= []\n\t\twrite \"// WebInspector Event: #{domain}.#{name}\"\n\t\twrite \"function on#{name.upcaseFirst}(res) {\\n\\t// res = {#{paramNames.join \", \"}}\\n}\"\n\t\twrite \"</pre>\", \"</div>\"\n\tend\n\nend\n\njsdoc = JSDoc.new INSPECTOR_URL, OUTPUT\njsdoc.run"
  },
  {
    "path": "src/LiveDevelopment/LiveDevMultiBrowser.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * LiveDevelopment allows Brackets to launch a browser with a \"live preview\" that's\n * connected to the current editor.\n *\n * # STARTING\n *\n * To start a session call `open`. This will read the currentDocument from brackets,\n * launch it in the default browser, and connect to it for live editing.\n *\n * # STOPPING\n *\n * To stop a session call `close`. This will close the connection to the browser\n * (but will not close the browser tab).\n *\n * # STATUS\n *\n * Status updates are dispatched as `statusChange` jQuery events. The status\n * is passed as the first parameter and the reason for the change as the second\n * parameter. Currently only the \"Inactive\" status supports the reason parameter.\n * The status codes are:\n *\n *  0: Inactive\n *  1: Connecting (waiting for a browser connection)\n *  2: Active\n *  3: Out of sync\n *  4: Sync error\n *  5: Reloading (after saving JS changes)\n *  6: Restarting (switching context to a new HTML live doc)\n *\n * The reason codes are:\n * - null (Unknown reason)\n * - \"explicit_close\" (LiveDevelopment.close() was called)\n * - \"navigated_away\" (The browser changed to a location outside of the project)\n * - \"detached_target_closed\" (The tab or window was closed)\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Status Codes\n    var STATUS_INACTIVE      = exports.STATUS_INACTIVE       =  0;\n    var STATUS_CONNECTING    = exports.STATUS_CONNECTING     =  1;\n    var STATUS_ACTIVE        = exports.STATUS_ACTIVE         =  2;\n    var STATUS_OUT_OF_SYNC   = exports.STATUS_OUT_OF_SYNC    =  3;\n    var STATUS_SYNC_ERROR    = exports.STATUS_SYNC_ERROR     =  4;\n    var STATUS_RELOADING     = exports.STATUS_RELOADING      =  5;\n    var STATUS_RESTARTING    = exports.STATUS_RESTARTING     =  6;\n\n    var CommandManager       = require(\"command/CommandManager\"),\n        Commands             = require(\"command/Commands\"),\n        Dialogs              = require(\"widgets/Dialogs\"),\n        DefaultDialogs       = require(\"widgets/DefaultDialogs\"),\n        DocumentManager      = require(\"document/DocumentManager\"),\n        EditorManager        = require(\"editor/EditorManager\"),\n        EventDispatcher      = require(\"utils/EventDispatcher\"),\n        FileUtils            = require(\"file/FileUtils\"),\n        MainViewManager      = require(\"view/MainViewManager\"),\n        PreferencesDialogs   = require(\"preferences/PreferencesDialogs\"),\n        ProjectManager       = require(\"project/ProjectManager\"),\n        Strings              = require(\"strings\"),\n        _                    = require(\"thirdparty/lodash\"),\n        LiveDevelopmentUtils = require(\"LiveDevelopment/LiveDevelopmentUtils\"),\n        LiveDevServerManager = require(\"LiveDevelopment/LiveDevServerManager\"),\n        NodeSocketTransport  = require(\"LiveDevelopment/MultiBrowserImpl/transports/NodeSocketTransport\"),\n        LiveDevProtocol      = require(\"LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol\"),\n        DefaultLauncher      = require(\"LiveDevelopment/MultiBrowserImpl/launchers/Launcher\");\n\n    // Documents\n    var LiveCSSDocument      = require(\"LiveDevelopment/MultiBrowserImpl/documents/LiveCSSDocument\"),\n        LiveHTMLDocument     = require(\"LiveDevelopment/MultiBrowserImpl/documents/LiveHTMLDocument\");\n\n    /**\n     * @private\n     * The live HTML document for the currently active preview.\n     * @type {LiveHTMLDocument}\n     */\n    var _liveDocument;\n\n    /**\n     * @private\n     * Live documents related to the active HTML document - for example, CSS files\n     * that are used by the document.\n     * @type {Object.<string: {LiveHTMLDocument|LiveCSSDocument}>}\n     */\n    var _relatedDocuments = {};\n\n    /**\n     * @private\n     * Protocol handler that provides the actual live development API on top of the current transport.\n     */\n    var _protocol = LiveDevProtocol;\n\n    /**\n     * @private\n     * Current browser launcher for preview.\n     */\n    var _launcher;\n\n    /**\n     * @private\n     * Current live preview server\n     * @type {BaseServer}\n     */\n    var _server;\n\n    /**\n     * @private\n     * Determine which live document class should be used for a given document\n     * @param {Document} document The document we want to create a live document for.\n     * @return {function} The constructor for the live document class; will be a subclass of LiveDocument.\n     */\n    function _classForDocument(doc) {\n        if (doc.getLanguage().getId() === \"css\") {\n            return LiveCSSDocument;\n        }\n\n        if (LiveDevelopmentUtils.isHtmlFileExt(doc.file.fullPath)) {\n            return LiveHTMLDocument;\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns true if the global Live Development mode is on (might be in the middle of connecting).\n     * @return {boolean}\n     */\n    function isActive() {\n        return exports.status > STATUS_INACTIVE;\n    }\n\n    /**\n     * Returns the live document for a given path, or null if there is no live document for it.\n     * @param {string} path\n     * @return {?LiveDocument}\n     */\n    function getLiveDocForPath(path) {\n        if (!_server) {\n            return null;\n        }\n\n        return _server.get(path);\n    }\n\n    /**\n     * @private\n     * Close a live document.\n     * @param {LiveDocument}\n     */\n    function _closeDocument(liveDocument) {\n        liveDocument.off(\".livedev\");\n        liveDocument.close();\n    }\n\n    /**\n     * Removes the given CSS/JSDocument from _relatedDocuments. Signals that the\n     * given file is no longer associated with the HTML document that is live (e.g.\n     * if the related file has been deleted on disk).\n     * @param {string} url Absolute URL of the related document\n     */\n    function _handleRelatedDocumentDeleted(url) {\n        var liveDoc = _relatedDocuments[url];\n        if (liveDoc) {\n            delete _relatedDocuments[url];\n        }\n\n        if (_server) {\n            _server.remove(liveDoc);\n        }\n        _closeDocument(liveDoc);\n    }\n\n    /**\n     * Update the status. Triggers a statusChange event.\n     * @param {number} status new status\n     * @param {?string} closeReason Optional string key suffix to display to\n     *     user when closing the live development connection (see LIVE_DEV_* keys)\n     */\n    function _setStatus(status, closeReason) {\n        // Don't send a notification when the status didn't actually change\n        if (status === exports.status) {\n            return;\n        }\n\n        exports.status = status;\n\n        var reason = status === STATUS_INACTIVE ? closeReason : null;\n        exports.trigger(\"statusChange\", status, reason);\n    }\n\n    /**\n     * @private\n     * Close all live documents.\n     */\n    function _closeDocuments() {\n        if (_liveDocument) {\n            _closeDocument(_liveDocument);\n            _liveDocument = undefined;\n        }\n\n        Object.keys(_relatedDocuments).forEach(function (url) {\n            _closeDocument(_relatedDocuments[url]);\n            delete _relatedDocuments[url];\n        });\n\n        // Clear all documents from request filtering\n        if (_server) {\n            _server.clear();\n        }\n    }\n\n    /**\n     * @private\n     * Returns the URL that we would serve the given path at.\n     * @param {string} path\n     * @return {string}\n     */\n    function _resolveUrl(path) {\n        return _server && _server.pathToUrl(path);\n    }\n\n    /**\n     * @private\n     * Create a LiveDocument for a Brackets editor/document to manage communication between the\n     * editor and the browser.\n     * @param {Document} doc\n     * @param {Editor} editor\n     * @param {roots} roots\n     * @return {?LiveDocument} The live document, or null if this type of file doesn't support live editing.\n     */\n    function _createLiveDocument(doc, editor, roots) {\n        var DocClass = _classForDocument(doc),\n            liveDocument;\n\n        if (!DocClass) {\n            return null;\n        }\n\n        liveDocument = new DocClass(_protocol, _resolveUrl, doc, editor, roots);\n\n        liveDocument.on(\"errorStatusChanged.livedev\", function (event, hasErrors) {\n            if (isActive()) {\n                _setStatus(hasErrors ? STATUS_SYNC_ERROR : STATUS_ACTIVE);\n            }\n        });\n\n        return liveDocument;\n    }\n\n    /**\n     * Documents are considered to be out-of-sync if they are dirty and\n     * do not have \"update while editing\" support\n     * @param {Document} doc\n     * @return {boolean}\n     */\n    function _docIsOutOfSync(doc) {\n        var liveDoc = _server && _server.get(doc.file.fullPath),\n            isLiveEditingEnabled = liveDoc && liveDoc.isLiveEditingEnabled();\n\n        return doc.isDirty && !isLiveEditingEnabled;\n    }\n\n    /**\n     * Handles a notification from the browser that a stylesheet was loaded into\n     * the live HTML document. If the stylesheet maps to a file in the project, then\n     * creates a live document for the stylesheet and adds it to _relatedDocuments.\n     * @param {$.Event} event\n     * @param {string} url The URL of the stylesheet that was added.\n     * @param {array} roots The URLs of the roots of the stylesheet (the css files loaded through <link>)\n     */\n    function _styleSheetAdded(event, url, roots) {\n        var path = _server && _server.urlToPath(url),\n            alreadyAdded = !!_relatedDocuments[url];\n\n        // path may be null if loading an external stylesheet.\n        // Also, the stylesheet may already exist and be reported as added twice\n        // due to Chrome reporting added/removed events after incremental changes\n        // are pushed to the browser\n        if (!path || alreadyAdded) {\n            return;\n        }\n\n        var docPromise = DocumentManager.getDocumentForPath(path);\n\n        docPromise.done(function (doc) {\n            if ((_classForDocument(doc) === LiveCSSDocument) &&\n                    (!_liveDocument || (doc !== _liveDocument.doc))) {\n                var liveDoc = _createLiveDocument(doc, doc._masterEditor, roots);\n                if (liveDoc) {\n                    _server.add(liveDoc);\n                    _relatedDocuments[doc.url] = liveDoc;\n                    liveDoc.on(\"updateDoc\", function (event, url) {\n                        var path = _server.urlToPath(url),\n                            doc = getLiveDocForPath(path);\n                        doc._updateBrowser();\n                    });\n                }\n            }\n        });\n    }\n\n    /**\n     * @private\n     * Determine an index file that can be used to start Live Development.\n     * This function will inspect all files in a project to find the closest index file\n     * available for currently opened document. We are searching for these files:\n     *  - index.html\n     *  - index.htm\n     *\n     * If the project is configured with a custom base url for live development, then\n     * the list of possible index files is extended to contain these index files too:\n     *  - index.php\n     *  - index.php3\n     *  - index.php4\n     *  - index.php5\n     *  - index.phtm\n     *  - index.phtml\n     *  - index.cfm\n     *  - index.cfml\n     *  - index.asp\n     *  - index.aspx\n     *  - index.jsp\n     *  - index.jspx\n     *  - index.shm\n     *  - index.shml\n     *\n     * If a file was found, the promise will be resolved with the full path to this file. If no file\n     * was found in the whole project tree, the promise will be resolved with null.\n     *\n     * @return {jQuery.Promise} A promise that is resolved with a full path\n     * to a file if one could been determined, or null if there was no suitable index\n     * file.\n     */\n    function _getInitialDocFromCurrent() {\n        var doc = DocumentManager.getCurrentDocument(),\n            refPath,\n            i;\n\n        // Is the currently opened document already a file we can use for Live Development?\n        if (doc) {\n            refPath = doc.file.fullPath;\n            if (LiveDevelopmentUtils.isStaticHtmlFileExt(refPath) || LiveDevelopmentUtils.isServerHtmlFileExt(refPath)) {\n                return new $.Deferred().resolve(doc);\n            }\n        }\n\n        var result = new $.Deferred();\n\n        var baseUrl = ProjectManager.getBaseUrl(),\n            hasOwnServerForLiveDevelopment = (baseUrl && baseUrl.length);\n\n        ProjectManager.getAllFiles().done(function (allFiles) {\n            var projectRoot = ProjectManager.getProjectRoot().fullPath,\n                containingFolder,\n                indexFileFound = false,\n                stillInProjectTree = true;\n\n            if (refPath) {\n                containingFolder = FileUtils.getDirectoryPath(refPath);\n            } else {\n                containingFolder = projectRoot;\n            }\n\n            var filteredFiltered = allFiles.filter(function (item) {\n                var parent = FileUtils.getParentPath(item.fullPath);\n\n                return (containingFolder.indexOf(parent) === 0);\n            });\n\n            var filterIndexFile = function (fileInfo) {\n                if (fileInfo.fullPath.indexOf(containingFolder) === 0) {\n                    if (FileUtils.getFilenameWithoutExtension(fileInfo.name) === \"index\") {\n                        if (hasOwnServerForLiveDevelopment) {\n                            if ((LiveDevelopmentUtils.isServerHtmlFileExt(fileInfo.name)) ||\n                                    (LiveDevelopmentUtils.isStaticHtmlFileExt(fileInfo.name))) {\n                                return true;\n                            }\n                        } else if (LiveDevelopmentUtils.isStaticHtmlFileExt(fileInfo.name)) {\n                            return true;\n                        }\n                    } else {\n                        return false;\n                    }\n                }\n            };\n\n            while (!indexFileFound && stillInProjectTree) {\n                i = _.findIndex(filteredFiltered, filterIndexFile);\n\n                // We found no good match\n                if (i === -1) {\n                    // traverse the directory tree up one level\n                    containingFolder = FileUtils.getParentPath(containingFolder);\n                    // Are we still inside the project?\n                    if (containingFolder.indexOf(projectRoot) === -1) {\n                        stillInProjectTree = false;\n                    }\n                } else {\n                    indexFileFound = true;\n                }\n            }\n\n            if (i !== -1) {\n                DocumentManager.getDocumentForPath(filteredFiltered[i].fullPath).then(result.resolve, result.resolve);\n                return;\n            }\n\n            result.resolve(null);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Close the connection and the associated window\n     * @param {boolean} doCloseWindow Use true to close the window/tab in the browser\n     * @param {?string} reason Optional string key suffix to display to user (see LIVE_DEV_* keys)\n     */\n    function _close(doCloseWindow, reason) {\n        if (exports.status !== STATUS_INACTIVE) {\n            // Close live documents\n            _closeDocuments();\n            // Close all active connections\n            _protocol.closeAllConnections();\n\n            if (_server) {\n                // Stop listening for requests when disconnected\n                _server.stop();\n\n                // Dispose server\n                _server = null;\n            }\n        }\n    //TODO: implement closeWindow together with launchers.\n//        if (doCloseWindow) {\n//\n//        }\n        _setStatus(STATUS_INACTIVE, reason || \"explicit_close\");\n    }\n\n    /**\n     * Closes all active connections.\n     * Returns a resolved promise for API compatibility.\n     * @return {$.Promise} A resolved promise\n     */\n    function close() {\n        _close(true);\n        return new $.Deferred().resolve().promise();\n    }\n\n    /**\n     * @private\n     * Displays an error when no HTML file can be found to preview.\n     */\n    function _showWrongDocError() {\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n            Strings.LIVE_DEV_NEED_HTML_MESSAGE\n        );\n    }\n\n    /**\n     * @private\n     * Displays an error when the server for live development files can't be started.\n     */\n    function _showLiveDevServerNotReadyError() {\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n            Strings.LIVE_DEV_SERVER_NOT_READY_MESSAGE\n        );\n    }\n\n    /**\n     * @private\n     * Creates the main live document for a given HTML document and notifies the server it exists.\n     * TODO: we should really maintain the list of live documents, not the server.\n     * @param {Document} doc\n     */\n    function _createLiveDocumentForFrame(doc) {\n        // create live document\n        doc._ensureMasterEditor();\n        _liveDocument = _createLiveDocument(doc, doc._masterEditor);\n        _server.add(_liveDocument);\n    }\n\n\n     /**\n     * Launches the given URL in the default browser.\n     * @param {string} url\n     * TODO: launchers for multiple browsers\n     */\n    function _launch(url) {\n        // open default browser\n        // TODO: fail?\n        //\n        _launcher.launch(url);\n    }\n\n    /**\n     * @private\n     * Launches the given document in the browser, given that a live document has already\n     * been created for it.\n     * @param {Document} doc\n     */\n    function _open(doc) {\n        if (doc && _liveDocument && doc === _liveDocument.doc) {\n            if (_server) {\n                // Launch the URL in the browser. If it's the first one to connect back to us,\n                // our status will transition to ACTIVE once it does so.\n                if (exports.status < STATUS_ACTIVE) {\n                    _launch(_server.pathToUrl(doc.file.fullPath));\n                }\n                if (exports.status === STATUS_RESTARTING) {\n                    // change page in browser\n                    _protocol.navigate(_server.pathToUrl(doc.file.fullPath));\n                }\n\n                _protocol\n                    // TODO: timeout if we don't get a connection within a certain time\n                    .on(\"ConnectionConnect.livedev\", function (event, msg) {\n                        // check for the first connection\n                        if (_protocol.getConnectionIds().length === 1) {\n                            // check the page that connection comes from matches the current live document session\n                            if (_liveDocument && (msg.url === _resolveUrl(_liveDocument.doc.file.fullPath))) {\n                                _setStatus(STATUS_ACTIVE);\n                            }\n                        }\n                    })\n                    .on(\"ConnectionClose.livedev\", function (event, msg) {\n                        // close session when the last connection was closed\n                        if (_protocol.getConnectionIds().length === 0) {\n                            setTimeout(function () {\n                                if (_protocol.getConnectionIds().length === 0 &&\n                                        exports.status <= STATUS_ACTIVE) {\n                                    _close(false, \"detached_target_closed\");\n                                }\n                            }, 5000);\n                        }\n                    })\n                    // extract stylesheets and create related LiveCSSDocument instances\n                    .on(\"DocumentRelated.livedev\", function (event, msg) {\n                        var relatedDocs = msg.related;\n                        var docs = Object.keys(relatedDocs.stylesheets);\n                        docs.forEach(function (url) {\n                            _styleSheetAdded(null, url, relatedDocs.stylesheets[url]);\n                        });\n                    })\n                    // create new LiveCSSDocument if a new stylesheet is added\n                    .on(\"StylesheetAdded.livedev\", function (event, msg) {\n                        _styleSheetAdded(null, msg.href, msg.roots);\n                    })\n                    // remove LiveCSSDocument instance when stylesheet is removed\n                    .on(\"StylesheetRemoved.livedev\", function (event, msg) {\n                        _handleRelatedDocumentDeleted(msg.href);\n                    });\n            } else {\n                console.error(\"LiveDevelopment._open(): No server active\");\n            }\n        } else {\n            // Unlikely that we would get to this state where\n            // a connection is in process but there is no current\n            // document\n            close();\n        }\n    }\n\n    /**\n     * @private\n     * Creates the live document in preparation for launching the\n     * preview of the given document, then launches it. (The live document\n     * must already exist before we launch it so that the server can\n     * ask it for the instrumented version of the document when the browser\n     * requests it.)\n     * TODO: could probably just consolidate this with _open()\n     * @param {Document} doc\n     */\n    function _doLaunchAfterServerReady(initialDoc) {\n\n        _createLiveDocumentForFrame(initialDoc);\n\n        // start listening for requests\n        _server.start();\n\n        // open browser to the url\n        _open(initialDoc);\n    }\n\n    /**\n     * @private\n     * Create the server in preparation for opening a live preview.\n     * @param {Document} doc The document we want the server for. Different servers handle\n     * different types of project (a static server for when no app server is configured,\n     * vs. a user server when there is an app server set in File > Project Settings).\n     */\n    function _prepareServer(doc) {\n        var deferred = new $.Deferred(),\n            showBaseUrlPrompt = false;\n\n        _server = LiveDevServerManager.getServer(doc.file.fullPath);\n\n        // Optionally prompt for a base URL if no server was found but the\n        // file is a known server file extension\n        showBaseUrlPrompt = !_server && LiveDevelopmentUtils.isServerHtmlFileExt(doc.file.fullPath);\n\n        if (showBaseUrlPrompt) {\n            // Prompt for a base URL\n            PreferencesDialogs.showProjectPreferencesDialog(\"\", Strings.LIVE_DEV_NEED_BASEURL_MESSAGE)\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_OK && ProjectManager.getBaseUrl()) {\n                        // If base url is specifed, then re-invoke _prepareServer() to continue\n                        _prepareServer(doc).then(deferred.resolve, deferred.reject);\n                    } else {\n                        deferred.reject();\n                    }\n                });\n        } else if (_server) {\n            // Startup the server\n            var readyPromise = _server.readyToServe();\n            if (!readyPromise) {\n                _showLiveDevServerNotReadyError();\n                deferred.reject();\n            } else {\n                readyPromise.then(deferred.resolve, function () {\n                    _showLiveDevServerNotReadyError();\n                    deferred.reject();\n                });\n            }\n        } else {\n            // No server found\n            deferred.reject();\n        }\n\n        return deferred.promise();\n    }\n\n    /**\n     * @private\n     * MainViewManager.currentFileChange event handler.\n     * When switching documents, close the current preview and open a new one.\n     */\n    function _onFileChange() {\n        var doc = DocumentManager.getCurrentDocument();\n        if (!isActive() || !doc) {\n            return;\n        }\n\n        // close the current session and begin a new session\n        var docUrl = _server && _server.pathToUrl(doc.file.fullPath),\n            isViewable = _server && _server.canServe(doc.file.fullPath);\n\n        if (_liveDocument.doc.url !== docUrl && isViewable) {\n            // clear live doc and related docs\n            _closeDocuments();\n            // create new live doc\n            _createLiveDocumentForFrame(doc);\n            _setStatus(STATUS_RESTARTING);\n            _open(doc);\n\n        }\n    }\n\n\n    /**\n     * Open a live preview on the current docuemnt.\n     */\n    function open() {\n        // TODO: need to run _onDocumentChange() after load if doc != currentDocument here? Maybe not, since activeEditorChange\n        // doesn't trigger it, while inline editors can still cause edits in doc other than currentDoc...\n        _getInitialDocFromCurrent().done(function (doc) {\n            var prepareServerPromise = (doc && _prepareServer(doc)) || new $.Deferred().reject(),\n                otherDocumentsInWorkingFiles;\n\n            if (doc && !doc._masterEditor) {\n                otherDocumentsInWorkingFiles = MainViewManager.getWorkingSetSize(MainViewManager.ALL_PANES);\n                MainViewManager.addToWorkingSet(MainViewManager.ACTIVE_PANE, doc.file);\n\n                if (!otherDocumentsInWorkingFiles) {\n                    CommandManager.execute(Commands.CMD_OPEN, { fullPath: doc.file.fullPath });\n                }\n            }\n\n            // wait for server (StaticServer, Base URL or file:)\n            prepareServerPromise\n                .done(function () {\n                    _setStatus(STATUS_CONNECTING);\n                    _doLaunchAfterServerReady(doc);\n                })\n                .fail(function () {\n                    _showWrongDocError();\n                });\n        });\n    }\n\n    /**\n     * For files that don't support as-you-type live editing, but are loaded by live HTML documents\n     * (e.g. JS files), we want to reload the full document when they're saved.\n     * @param {$.Event} event\n     * @param {Document} doc\n     */\n    function _onDocumentSaved(event, doc) {\n        if (!isActive() || !_server) {\n            return;\n        }\n\n        var absolutePath            = doc.file.fullPath,\n            liveDocument            = absolutePath && _server.get(absolutePath),\n            liveEditingEnabled      = liveDocument && liveDocument.isLiveEditingEnabled  && liveDocument.isLiveEditingEnabled();\n\n        // Skip reload if the saved document has live editing enabled\n        if (liveEditingEnabled) {\n            return;\n        }\n\n        // reload the page if the given document is a JS file related\n        // to the current live document.\n        if (_liveDocument.isRelated(absolutePath)) {\n            if (doc.getLanguage().getId() === \"javascript\") {\n                _setStatus(STATUS_RELOADING);\n                _protocol.reload();\n            }\n        }\n    }\n\n    /**\n     * For files that don't support as-you-type live editing, but are loaded by live HTML documents\n     * (e.g. JS files), we want to show a dirty indicator on the live development icon when they\n     * have unsaved changes, so the user knows s/he needs to save in order to have the page reload.\n     * @param {$.Event} event\n     * @param {Document} doc\n     */\n    function _onDirtyFlagChange(event, doc) {\n        if (!isActive() || !_server) {\n            return;\n        }\n\n        var absolutePath = doc.file.fullPath;\n\n        if (_liveDocument.isRelated(absolutePath)) {\n            // Set status to out of sync if dirty. Otherwise, set it to active status.\n            _setStatus(_docIsOutOfSync(doc) ? STATUS_OUT_OF_SYNC : STATUS_ACTIVE);\n        }\n    }\n\n    /**\n     * Sets the current transport mechanism to be used by the live development protocol\n     * (e.g. socket server, iframe postMessage, etc.)\n     * The low-level transport. Must provide the following methods:\n     *\n     * - start(): Initiates transport (eg. creates Web Socket server).\n     * - send(idOrArray, string): Dispatches the given protocol message (provided as a JSON string) to the given client ID\n     *   or array of client IDs. (See the \"connect\" message for an explanation of client IDs.)\n     * - close(id): Closes the connection to the given client ID.\n     * - getRemoteScript(): Returns a script that should be injected into the page's HTML in order to handle the remote side\n     *   of the transport. Should include the \"<script>\" tags. Should return null if no injection is necessary.\n     *\n     * It must also dispatch the following jQuery events:\n     *\n     * - \"connect\": When a target browser connects back to the transport. Must provide two parameters:\n     *   - clientID - a unique number representing this connection\n     *   - url - the URL of the page in the target browser that's connecting to us\n     * - \"message\": When a message is received by the transport. Must provide two parameters:\n     *   - clientID - the ID of the client sending the message\n     *   - message - the text of the message as a JSON string\n     * - \"close\": When the remote browser closes the connection. Must provide one parameter:\n     *   - clientID - the ID of the client closing the connection\n     *\n     * @param {{launch: function(string), send: function(number|Array.<number>, string), close: function(number), getRemoteScript: function(): ?string}} transport\n     */\n    function setTransport(transport) {\n        _protocol.setTransport(transport);\n    }\n\n    /**\n     * Sets the current browser launcher mechanism to be used by live development\n     * (e.g., default browser, iframe-based browser, etc.)\n     * The launcher must provide the following method:\n     *\n     * - launch(url): Launch the given URL in the appropriate browser.\n     *\n     * @param {{launch: function(string)}} launcher\n     */\n    function setLauncher(launcher) {\n        if (!(launcher && launcher.launch)) {\n            console.log(\"Invalid launcher object: \", launcher, new Error(\"LiveDevMultiBrowser.setLauncher()\"));\n            return;\n        }\n        _launcher = launcher;\n    }\n\n    /**\n     * Initialize the LiveDevelopment module.\n     */\n    function init(config) {\n        exports.config = config;\n        MainViewManager\n            .on(\"currentFileChange\", _onFileChange);\n        DocumentManager\n            .on(\"documentSaved\", _onDocumentSaved)\n            .on(\"dirtyFlagChange\", _onDirtyFlagChange);\n        ProjectManager\n            .on(\"beforeProjectClose beforeAppClose\", close);\n\n        // Default transport for live connection messages - can be changed\n        setTransport(NodeSocketTransport);\n\n        // Default launcher for preview browser - can be changed\n        setLauncher(DefaultLauncher);\n\n        // Initialize exports.status\n        _setStatus(STATUS_INACTIVE);\n    }\n\n    function getLiveDocForEditor(editor) {\n        if (!editor) {\n            return null;\n        }\n        return getLiveDocForPath(editor.document.file.fullPath);\n    }\n\n    /**\n     *  Enable highlighting\n     */\n    function showHighlight() {\n        var doc = getLiveDocForEditor(EditorManager.getActiveEditor());\n\n        if (doc && doc.updateHighlight) {\n            doc.updateHighlight();\n        }\n    }\n\n    /**\n     * Hide any active highlighting\n     */\n    function hideHighlight() {\n        if (_protocol) {\n            _protocol.evaluate(\"_LD.hideHighlight()\");\n        }\n    }\n\n    /**\n     * Redraw highlights\n     */\n    function redrawHighlight() {\n        if (_protocol) {\n            _protocol.evaluate(\"_LD.redrawHighlights()\");\n        }\n    }\n\n    /**\n     * Originally unload and reload agents. It doesn't apply for this new implementation.\n     * @return {jQuery.Promise} Already resolved promise.\n     */\n    function reconnect() {\n        return $.Deferred().resolve();\n    }\n\n    /**\n     * Reload current page in all connected browsers.\n     */\n    function reload() {\n        if (_protocol) {\n            _protocol.reload();\n        }\n    }\n\n    /**\n     * Returns current project server config. Copied from original LiveDevelopment.\n     */\n    function getCurrentProjectServerConfig() {\n        return {\n            baseUrl: ProjectManager.getBaseUrl(),\n            pathResolver: ProjectManager.makeProjectRelativeIfPossible,\n            root: ProjectManager.getProjectRoot().fullPath\n        };\n    }\n\n    /**\n     * @private\n     * Returns the base URL of the current server serving the active live document, or null if\n     * there is no active live document.\n     * @return {?string}\n     */\n    function getServerBaseUrl() {\n        return _server && _server.getBaseUrl();\n    }\n\n    // for unit testing only\n    function _getCurrentLiveDoc() {\n        return _liveDocument;\n    }\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // For unit testing\n    exports._server                   = _server;\n    exports._getCurrentLiveDoc        = _getCurrentLiveDoc;\n    exports._getInitialDocFromCurrent = _getInitialDocFromCurrent;\n\n    // Export public functions\n    exports.open                = open;\n    exports.close               = close;\n    exports.reconnect           = reconnect;\n    exports.reload              = reload;\n    exports.getLiveDocForPath   = getLiveDocForPath;\n    exports.showHighlight       = showHighlight;\n    exports.hideHighlight       = hideHighlight;\n    exports.redrawHighlight     = redrawHighlight;\n    exports.init                = init;\n    exports.isActive            = isActive;\n    exports.getServerBaseUrl    = getServerBaseUrl;\n    exports.getCurrentProjectServerConfig = getCurrentProjectServerConfig;\n    exports.setTransport        = setTransport;\n    exports.setLauncher         = setLauncher;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/LiveDevServerManager.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * LiveDevServerManager Overview:\n *\n * The LiveDevServerManager allows extensions to register to be Live Development\n * servers. Servers are queried for their ability to serve a page in\n * order of descending priority by way their canServe methods.\n *\n * NOTE: This API is currently experimental and intented to be internal-only.\n * It is very likely that it will be changed in the near future and/or\n * removed entirely.\n *\n *   `LiveDevServerManager.getServer(localPath)`\n *\n * Returns highest priority server (BaseServer) that can serve the local file.\n *\n * A Live Development server must implement the BaseServer API. See\n * LiveDevelopment/Servers/BaseServer base class.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _serverProviders   = [];\n\n    /**\n     * @private\n     * Comparator to sort providers based on their priority\n     * @param {number} a\n     * @param {number} b\n     */\n    function _providerSort(a, b) {\n        return b.priority - a.priority;\n    }\n\n    /**\n     * Determines which provider can serve a file with a local path.\n     *\n     * @param {string} localPath A local path to file being served.\n     * @return {?BaseServer} A server no null if no servers can serve the file\n     */\n    function getServer(localPath) {\n        var provider, server, i;\n\n        for (i = 0; i < _serverProviders.length; i++) {\n            provider = _serverProviders[i];\n            server = provider.create();\n\n            if (server.canServe(localPath)) {\n                return server;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * The method by which a server registers itself. It returns an\n     * object handler that can be used to remove that server from the list.\n     *\n     * @param {BaseServer|{create: function():BaseServer}} provider\n     *  The provider to be registered, described below.\n     * @param {number} priority\n     *  A non-negative number used to break ties among providers for a\n     *  particular url. Providers that register with a higher priority will\n     *  have the opportunity to provide a given url before those with a\n     *  lower priority. The higher the number, the higher the priority.\n     * @return {{object}}\n     */\n    function registerServer(provider, priority) {\n        if (!provider.create) {\n            console.error(\"Incompatible live development server provider\");\n            return;\n        }\n\n        var providerObj = {};\n\n        providerObj.create = provider.create;\n        providerObj.priority = priority || 0;\n\n        _serverProviders.push(providerObj);\n        _serverProviders.sort(_providerSort);\n\n        return providerObj;\n    }\n\n    /**\n     * Remove a server from the list of the registered providers.\n     *\n     * @param {{object}} provider The provider to be removed.\n     */\n    function removeServer(provider) {\n        var i;\n        for (i = 0; i < _serverProviders.length; i++) {\n            if (provider === _serverProviders[i]) {\n                _serverProviders.splice(i, 1);\n            }\n        }\n    }\n\n    // Backwards compatibility\n    exports.getProvider         = getServer;\n    exports.registerProvider    = registerServer;\n\n    // Define public API\n    exports.getServer           = getServer;\n    exports.registerServer      = registerServer;\n    exports.removeServer        = removeServer;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/LiveDevelopment.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global open */\n\n/**\n * LiveDevelopment manages the Inspector, all Agents, and the active LiveDocument\n *\n * __STARTING__\n *\n * To start a session call `open`. This will read the currentDocument from brackets,\n * launch the LiveBrowser (currently Chrome) with the remote debugger port open,\n * establish the Inspector connection to the remote debugger, and finally load all\n * agents.\n *\n * __STOPPING__\n *\n * To stop a session call `close`. This will close the active browser window,\n * disconnect the Inspector, unload all agents, and clean up.\n *\n * __STATUS__\n *\n * Status updates are dispatched as `statusChange` jQuery events. The status\n * is passed as the first parameter and the reason for the change as the second\n * parameter. Currently only the \"Inactive\" status supports the reason parameter.\n * The status codes are:\n *\n *     -1: Error\n *      0: Inactive\n *      1: Connecting to the remote debugger\n *      2: Loading agents\n *      3: Active\n *      4: Out of sync\n *      5: Sync error\n *\n * The reason codes are:\n * - null (Unknown reason)\n * - \"explicit_close\" (LiveDevelopment.close() was called)\n * - \"navigated_away\" (The browser changed to a location outside of the project)\n * - \"detached_target_closed\" (The tab or window was closed)\n * - \"detached_replaced_with_devtools\" (The developer tools were opened in the browser)\n */\ndefine(function LiveDevelopment(require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var _ = require(\"thirdparty/lodash\");\n\n    // Status Codes\n    var STATUS_ERROR          = exports.STATUS_ERROR          = -1;\n    var STATUS_INACTIVE       = exports.STATUS_INACTIVE       =  0;\n    var STATUS_CONNECTING     = exports.STATUS_CONNECTING     =  1;\n    var STATUS_LOADING_AGENTS = exports.STATUS_LOADING_AGENTS =  2;\n    var STATUS_ACTIVE         = exports.STATUS_ACTIVE         =  3;\n    var STATUS_OUT_OF_SYNC    = exports.STATUS_OUT_OF_SYNC    =  4;\n    var STATUS_SYNC_ERROR     = exports.STATUS_SYNC_ERROR     =  5;\n\n    var Async                = require(\"utils/Async\"),\n        CSSUtils             = require(\"language/CSSUtils\"),\n        Dialogs              = require(\"widgets/Dialogs\"),\n        DefaultDialogs       = require(\"widgets/DefaultDialogs\"),\n        DocumentManager      = require(\"document/DocumentManager\"),\n        EditorManager        = require(\"editor/EditorManager\"),\n        EventDispatcher      = require(\"utils/EventDispatcher\"),\n        FileServer           = require(\"LiveDevelopment/Servers/FileServer\").FileServer,\n        FileSystemError      = require(\"filesystem/FileSystemError\"),\n        FileUtils            = require(\"file/FileUtils\"),\n        LiveDevelopmentUtils = require(\"LiveDevelopment/LiveDevelopmentUtils\"),\n        LiveDevServerManager = require(\"LiveDevelopment/LiveDevServerManager\"),\n        MainViewManager      = require(\"view/MainViewManager\"),\n        NativeApp            = require(\"utils/NativeApp\"),\n        PreferencesDialogs   = require(\"preferences/PreferencesDialogs\"),\n        ProjectManager       = require(\"project/ProjectManager\"),\n        Strings              = require(\"strings\"),\n        StringUtils          = require(\"utils/StringUtils\"),\n        UserServer           = require(\"LiveDevelopment/Servers/UserServer\").UserServer,\n        WebSocketTransport   = require(\"LiveDevelopment/transports/WebSocketTransport\"),\n        PreferencesManager   = require(\"preferences/PreferencesManager\"),\n        HealthLogger         = require(\"utils/HealthLogger\");\n\n    // Inspector\n    var Inspector       = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    // Documents\n    var CSSDocument     = require(\"LiveDevelopment/Documents/CSSDocument\"),\n        CSSPreprocessorDocument = require(\"LiveDevelopment/Documents/CSSPreprocessorDocument\"),\n        HTMLDocument    = require(\"LiveDevelopment/Documents/HTMLDocument\"),\n        JSDocument      = require(\"LiveDevelopment/Documents/JSDocument\");\n\n    // Document errors\n    var SYNC_ERROR_CLASS = \"live-preview-sync-error\";\n\n    // Agents\n    var CSSAgent = require(\"LiveDevelopment/Agents/CSSAgent\");\n\n    var agents = {\n        \"console\"   : require(\"LiveDevelopment/Agents/ConsoleAgent\"),\n        \"remote\"    : require(\"LiveDevelopment/Agents/RemoteAgent\"),\n        \"network\"   : require(\"LiveDevelopment/Agents/NetworkAgent\"),\n        \"dom\"       : require(\"LiveDevelopment/Agents/DOMAgent\"),\n        \"css\"       : CSSAgent,\n        \"script\"    : require(\"LiveDevelopment/Agents/ScriptAgent\"),\n        \"highlight\" : require(\"LiveDevelopment/Agents/HighlightAgent\"),\n        \"goto\"      : require(\"LiveDevelopment/Agents/GotoAgent\"),\n        \"edit\"      : require(\"LiveDevelopment/Agents/EditAgent\")\n    };\n\n    // construct path to launch.html\n    // window location is can be one of the following:\n    // Installed:                /path/to/Brackets.app/Contents/www/index.html\n    // Installed, dev:           /path/to/Brackets.app/Contents/dev/src/index.html\n    // Installed, dev, test:     /path/to/Brackets.app/Contents/dev/test/SpecRunner.html\n    // Arbitrary git repo:       /path/to/brackets/src/index.html\n    // Arbitrary git repo, test: /path/to/brackets/test/SpecRunner.html\n    var launcherUrl = window.location.pathname;\n\n    // special case for test/SpecRunner.html since we can't tell how requirejs\n    // baseUrl is configured dynamically\n    launcherUrl = launcherUrl.replace(\"/test/SpecRunner.html\", \"/src/index.html\");\n\n    launcherUrl = launcherUrl.substr(0, launcherUrl.lastIndexOf(\"/\")) + \"/LiveDevelopment/launch.html\";\n    launcherUrl = window.location.origin + launcherUrl;\n\n    // Some agents are still experimental, so we don't enable them all by default\n    // However, extensions can enable them by calling enableAgent().\n    // This object is used as a set (thus all properties have the value 'true').\n    // Property names should match property names in the 'agents' object.\n    var _enabledAgentNames = {\n        \"console\"   : true,\n        \"remote\"    : true,\n        \"network\"   : true,\n        \"css\"       : true,\n        \"highlight\" : true\n    };\n\n    /**\n     * Store the names (matching property names in the 'agent' object) of agents that we've loaded\n     * @type {string}\n     */\n    var _loadedAgentNames = [];\n\n    /**\n     * Live Preview current Document info\n     * @type {HTMLDocument}\n     */\n    var _liveDocument;\n\n    /**\n     * Related Live Documents\n     * @type {Object.<string: (HTMLDocument|CSSDocument)>}\n     */\n    var _relatedDocuments = {};\n\n    /**\n     * Promise returned for each call to open()\n     * @type {jQuery.Deferred}\n     */\n    var _openDeferred;\n\n    /**\n     * Promise returned for each call to close()\n     * @type {jQuery.Deferred}\n     */\n    var _closeDeferred;\n\n    // Disallow re-entrancy of loadAgents()\n    var _loadAgentsPromise;\n\n    /**\n     * Current live preview server\n     * @type {BaseServer}\n     */\n    var _server;\n\n    /**\n     * @private\n     * Handles of registered servers\n     */\n    var _regServers = [];\n    \n    PreferencesManager.definePreference(\"livedev.wsPort\", \"number\", 8125, {\n        description: Strings.DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\n    });\n    \n    PreferencesManager.definePreference(\"livedev.enableReverseInspect\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_LIVEDEV_ENABLE_REVERSE_INSPECT\n    });\n\n    function _isPromisePending(promise) {\n        return promise && promise.state() === \"pending\";\n    }\n\n    /** Get the current document from the document manager\n     * _adds extension, url and root to the document\n     */\n    function _getCurrentDocument() {\n        return DocumentManager.getCurrentDocument();\n    }\n\n    /** Determine which document class should be used for a given document\n     * @param {Document} document\n     */\n    function _classForDocument(doc) {\n        switch (doc.getLanguage().getId()) {\n        case \"less\":\n        case \"scss\":\n            return CSSPreprocessorDocument;\n        case \"css\":\n            return CSSDocument;\n        case \"javascript\":\n            return exports.config.experimental ? JSDocument : null;\n        }\n\n        if (LiveDevelopmentUtils.isHtmlFileExt(doc.file.fullPath)) {\n            return HTMLDocument;\n        }\n\n        return null;\n    }\n\n    function getLiveDocForPath(path) {\n        if (!_server) {\n            return undefined;\n        }\n\n        return _server.get(path);\n    }\n\n    function getLiveDocForEditor(editor) {\n        if (!editor) {\n            return null;\n        }\n        return getLiveDocForPath(editor.document.file.fullPath);\n    }\n\n    /**\n     * @private\n     * Clears errors from line number gutter (line class)\n     * @param {HTMLDocument|CSSDocument} liveDocument\n     */\n    function _doClearErrors(liveDocument) {\n        var lineHandle;\n\n        if (!liveDocument.editor ||\n                !liveDocument._errorLineHandles ||\n                !liveDocument._errorLineHandles.length) {\n            return;\n        }\n\n        liveDocument.editor._codeMirror.operation(function () {\n            while (true) {\n                // Iterate over all lines that were previously marked with an error\n                lineHandle = liveDocument._errorLineHandles.pop();\n\n                if (!lineHandle) {\n                    break;\n                }\n\n                liveDocument.editor._codeMirror.removeLineClass(lineHandle, \"wrap\", SYNC_ERROR_CLASS);\n            }\n        });\n    }\n\n    /**\n     * @private\n     * Make a message to direct users to the troubleshooting page\n     * @param {string} msg Original message\n     * @return {string} Original message plus link to troubleshooting page.\n     */\n    function _makeTroubleshootingMessage(msg) {\n        return msg + \" \" + StringUtils.format(Strings.LIVE_DEVELOPMENT_TROUBLESHOOTING, brackets.config.troubleshoot_url);\n    }\n\n    /**\n     * @private\n     * Close a live document\n     */\n    function _closeDocument(liveDocument) {\n        _doClearErrors(liveDocument);\n        liveDocument.close();\n\n        if (liveDocument.editor) {\n            liveDocument.editor.off(\".livedev\");\n        }\n\n        liveDocument.off(\".livedev\");\n    }\n\n    /**\n     * Removes the given CSS/JSDocument from _relatedDocuments. Signals that the\n     * given file is no longer associated with the HTML document that is live (e.g.\n     * if the related file has been deleted on disk).\n     */\n    function _closeRelatedDocument(liveDoc) {\n        if (_relatedDocuments[liveDoc.doc.url]) {\n            delete _relatedDocuments[liveDoc.doc.url];\n        }\n\n        if (_server) {\n            _server.remove(liveDoc);\n        }\n\n        _closeDocument(liveDoc);\n    }\n\n    /**\n     * Update the status. Triggers a statusChange event.\n     * @param {number} status new status\n     * @param {?string} closeReason Optional string key suffix to display to\n     *     user when closing the live development connection (see LIVE_DEV_* keys)\n     */\n    function _setStatus(status, closeReason) {\n        // Don't send a notification when the status didn't actually change\n        if (status === exports.status) {\n            return;\n        }\n\n        exports.status = status;\n\n        var reason = status === STATUS_INACTIVE ? closeReason : null;\n        exports.trigger(\"statusChange\", status, reason);\n    }\n\n    /**\n     * @private\n     * Event handler for live document errors. Displays error status in the editor gutter.\n     * @param {$.Event} event\n     * @param {HTMLDocument|CSSDocument} liveDocument\n     * @param {Array.<{token: SimpleNode, startPos: Pos, endPos: Pos}>} errors\n     */\n    function _handleLiveDocumentStatusChanged(liveDocument) {\n        var startLine,\n            endLine,\n            i,\n            lineHandle,\n            status = (liveDocument.errors.length) ? STATUS_SYNC_ERROR : STATUS_ACTIVE;\n\n        _setStatus(status);\n\n        if (!liveDocument.editor) {\n            return;\n        }\n\n        // Buffer addLineClass DOM changes in a CodeMirror operation\n        liveDocument.editor._codeMirror.operation(function () {\n            // Remove existing errors before marking new ones\n            _doClearErrors(liveDocument);\n\n            liveDocument._errorLineHandles = liveDocument._errorLineHandles || [];\n\n            liveDocument.errors.forEach(function (error) {\n                startLine = error.startPos.line;\n                endLine = error.endPos.line;\n\n                for (i = startLine; i < endLine + 1; i++) {\n                    lineHandle = liveDocument.editor._codeMirror.addLineClass(i, \"wrap\", SYNC_ERROR_CLASS);\n                    liveDocument._errorLineHandles.push(lineHandle);\n                }\n            });\n        });\n    }\n\n    /**\n     * @private\n     * Close all live documents\n     */\n    function _closeDocuments() {\n        if (_liveDocument) {\n            _closeDocument(_liveDocument);\n            _liveDocument = undefined;\n        }\n\n        Object.keys(_relatedDocuments).forEach(function (url) {\n            _closeDocument(_relatedDocuments[url]);\n            delete _relatedDocuments[url];\n        });\n\n        // Clear all documents from request filtering\n        if (_server) {\n            _server.clear();\n        }\n    }\n\n    /**\n     * @private\n     * Create a live version of a Brackets document\n     * @param {Document} doc Current document\n     * @param {Editor} editor Current editor\n     * @return {?(HTMLDocument|CSSDocument)}\n     */\n    function _createDocument(doc, editor) {\n        var DocClass        = _classForDocument(doc),\n            liveDocument    = new DocClass(doc, editor);\n\n        if (!DocClass) {\n            return null;\n        }\n\n        liveDocument.on(\"statusChanged.livedev\", function () {\n            _handleLiveDocumentStatusChanged(liveDocument);\n        });\n\n        return liveDocument;\n    }\n\n    /**\n     * @private\n     * Initialize `_liveDocument`.\n     * @param {Document} doc Current document\n     */\n    function _createLiveDocumentForFrame(doc) {\n        // create live document\n        doc._ensureMasterEditor();\n        _liveDocument = _createDocument(doc, doc._masterEditor);\n        _server.add(_liveDocument);\n    }\n\n    /** Enable an agent. Takes effect next time a connection is made. Does not affect\n     *  current live development sessions.\n     *\n     *  @param {string} name of agent to enable\n     */\n    function enableAgent(name) {\n        if (agents.hasOwnProperty(name) && !_enabledAgentNames.hasOwnProperty(name)) {\n            _enabledAgentNames[name] = true;\n        }\n    }\n\n    /** Disable an agent. Takes effect next time a connection is made. Does not affect\n     *  current live development sessions.\n     *\n     *  @param {string} name of agent to disable\n     */\n    function disableAgent(name) {\n        if (_enabledAgentNames.hasOwnProperty(name)) {\n            delete _enabledAgentNames[name];\n        }\n    }\n\n    /** Documents are considered to be out-of-sync if they are dirty and\n     *  do not have \"update while editing\" support\n     * @param {Document} doc\n     */\n    function _docIsOutOfSync(doc) {\n        var liveDoc = _server && _server.get(doc.file.fullPath),\n            isLiveEditingEnabled = liveDoc && liveDoc.isLiveEditingEnabled();\n\n        return doc.isDirty && !isLiveEditingEnabled;\n    }\n\n    /** Triggered by Inspector.error */\n    function _onError(event, error, msgData) {\n        var message;\n\n        // Sometimes error.message is undefined\n        if (!error.message) {\n            console.warn(\"Expected a non-empty string in error.message, got this instead:\", error.message);\n            message = JSON.stringify(error);\n        } else {\n            message = error.message;\n        }\n\n        // Remove \"Uncaught\" from the beginning to avoid the inspector popping up\n        if (message && message.substr(0, 8) === \"Uncaught\") {\n            message = message.substr(9);\n        }\n\n        // Additional information, like exactly which parameter could not be processed.\n        var data = error.data;\n        if (Array.isArray(data)) {\n            message += \"\\n\" + data.join(\"\\n\");\n        }\n\n        // Show the message, but include the error object for further information (e.g. error code)\n        console.error(message, error, msgData);\n    }\n\n    function _styleSheetAdded(event, url) {\n        var path = _server && _server.urlToPath(url),\n            exists = !!_relatedDocuments[url];\n\n        // path may be null if loading an external stylesheet.\n        // Also, the stylesheet may already exist and be reported as added twice\n        // due to Chrome reporting added/removed events after incremental changes\n        // are pushed to the browser\n        if (!path || exists) {\n            return;\n        }\n\n        var docPromise = DocumentManager.getDocumentForPath(path);\n\n        docPromise.done(function (doc) {\n            if ((_classForDocument(doc) === CSSDocument ||\n                    _classForDocument(doc) === CSSPreprocessorDocument) &&\n                    (!_liveDocument || (doc !== _liveDocument.doc))) {\n                // The doc may already have an editor (e.g. starting live preview from an css file),\n                // so pass the editor if any\n                var liveDoc = _createDocument(doc, doc._masterEditor);\n                if (liveDoc) {\n                    _server.add(liveDoc);\n                    _relatedDocuments[doc.url] = liveDoc;\n\n                    liveDoc.on(\"deleted.livedev\", function (event, liveDoc) {\n                        _closeRelatedDocument(liveDoc);\n                    });\n                }\n            }\n        });\n    }\n\n    /** Unload the agents */\n    function unloadAgents() {\n        _loadedAgentNames.forEach(function (name) {\n            agents[name].unload();\n        });\n        _loadedAgentNames = [];\n    }\n\n    /**\n     * @private\n     * Invoke a no-arg method on an inspector agent\n     * @param {string} name Agent name\n     * @param {stirng} methodName Method name to call on the agent\n     */\n    function _invokeAgentMethod(name, methodName) {\n        var oneAgentPromise;\n\n        if (agents[name] && agents[name][methodName]) {\n            oneAgentPromise = agents[name][methodName].call();\n        }\n\n        if (!oneAgentPromise) {\n            oneAgentPromise = new $.Deferred().resolve().promise();\n        } else {\n            oneAgentPromise.fail(function () {\n                console.error(methodName + \" failed on agent\", name);\n            });\n        }\n\n        return oneAgentPromise;\n    }\n\n    function getEnabledAgents() {\n        var enabledAgents;\n\n        // Select agents to use\n        if (exports.config.experimental) {\n            // load all agents\n            enabledAgents = agents;\n        } else {\n            // load only enabled agents\n            enabledAgents = _enabledAgentNames;\n        }\n\n        return Object.keys(enabledAgents);\n    }\n\n    /**\n     * @private\n     * Setup agents that need inspector domains enabled before loading\n     */\n    function _enableAgents() {\n        // enable agents in parallel\n        return Async.doInParallel(\n            getEnabledAgents(),\n            function (name) {\n                return _invokeAgentMethod(name, \"enable\");\n            },\n            true\n        );\n    }\n\n    /** Load the agents */\n    function loadAgents() {\n        // If we're already loading agents return same promise\n        if (_loadAgentsPromise) {\n            return _loadAgentsPromise;\n        }\n\n        var result = new $.Deferred(),\n            allAgentsPromise;\n\n        _loadAgentsPromise = result.promise();\n\n        _setStatus(STATUS_LOADING_AGENTS);\n\n        // load agents in parallel\n        allAgentsPromise = Async.doInParallel(\n            getEnabledAgents(),\n            function (name) {\n                return _invokeAgentMethod(name, \"load\").done(function () {\n                    _loadedAgentNames.push(name);\n                });\n            },\n            true\n        );\n\n        // wrap agent loading with a timeout\n        allAgentsPromise = Async.withTimeout(allAgentsPromise, 10000);\n\n        allAgentsPromise.done(function () {\n            var doc = (_liveDocument) ? _liveDocument.doc : null;\n\n            if (doc) {\n                var status = STATUS_ACTIVE;\n\n                if (_docIsOutOfSync(doc)) {\n                    status = STATUS_OUT_OF_SYNC;\n                }\n\n                _setStatus(status);\n                result.resolve();\n            } else {\n                result.reject();\n            }\n        });\n\n        allAgentsPromise.fail(result.reject);\n\n        _loadAgentsPromise\n            .fail(function () {\n                // show error loading live dev dialog\n                _setStatus(STATUS_ERROR);\n\n                Dialogs.showModalDialog(\n                    Dialogs.DIALOG_ID_ERROR,\n                    Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n                    _makeTroubleshootingMessage(Strings.LIVE_DEV_LOADING_ERROR_MESSAGE)\n                );\n            })\n            .always(function () {\n                _loadAgentsPromise = null;\n            });\n\n        return _loadAgentsPromise;\n    }\n\n    /**\n     * @private\n     * Determine an index file that can be used to start Live Development.\n     * This function will inspect all files in a project to find the closest index file\n     * available for currently opened document. We are searching for these files:\n     *  - index.html\n     *  - index.htm\n     *\n     * If the project is configured with a custom base url for live development, then\n     * the list of possible index files is extended to contain these index files too:\n     *  - index.php\n     *  - index.php3\n     *  - index.php4\n     *  - index.php5\n     *  - index.phtm\n     *  - index.phtml\n     *  - index.cfm\n     *  - index.cfml\n     *  - index.asp\n     *  - index.aspx\n     *  - index.jsp\n     *  - index.jspx\n     *  - index.shm\n     *  - index.shml\n     *\n     * If a file was found, the promise will be resolved with the full path to this file. If no file\n     * was found in the whole project tree, the promise will be resolved with null.\n     *\n     * @return {jQuery.Promise} A promise that is resolved with a full path\n     * to a file if one could been determined, or null if there was no suitable index\n     * file.\n     */\n    function _getInitialDocFromCurrent() {\n        var doc = _getCurrentDocument(),\n            refPath,\n            i;\n\n        // Is the currently opened document already a file we can use for Live Development?\n        if (doc) {\n            refPath = doc.file.fullPath;\n            if (LiveDevelopmentUtils.isStaticHtmlFileExt(refPath) || LiveDevelopmentUtils.isServerHtmlFileExt(refPath)) {\n                return new $.Deferred().resolve(doc);\n            }\n        }\n\n        var result = new $.Deferred();\n\n        var baseUrl = ProjectManager.getBaseUrl(),\n            hasOwnServerForLiveDevelopment = (baseUrl && baseUrl.length);\n\n        ProjectManager.getAllFiles().done(function (allFiles) {\n            var projectRoot = ProjectManager.getProjectRoot().fullPath,\n                containingFolder,\n                indexFileFound = false,\n                stillInProjectTree = true;\n\n            if (refPath) {\n                containingFolder = FileUtils.getDirectoryPath(refPath);\n            } else {\n                containingFolder = projectRoot;\n            }\n\n            var filteredFiltered = allFiles.filter(function (item) {\n                var parent = FileUtils.getParentPath(item.fullPath);\n\n                return (containingFolder.indexOf(parent) === 0);\n            });\n\n            var filterIndexFile = function (fileInfo) {\n                if (fileInfo.fullPath.indexOf(containingFolder) === 0) {\n                    if (FileUtils.getFilenameWithoutExtension(fileInfo.name) === \"index\") {\n                        if (hasOwnServerForLiveDevelopment) {\n                            if ((LiveDevelopmentUtils.isServerHtmlFileExt(fileInfo.name)) ||\n                                    (LiveDevelopmentUtils.isStaticHtmlFileExt(fileInfo.name))) {\n                                return true;\n                            }\n                        } else if (LiveDevelopmentUtils.isStaticHtmlFileExt(fileInfo.name)) {\n                            return true;\n                        }\n                    } else {\n                        return false;\n                    }\n                }\n            };\n\n            while (!indexFileFound && stillInProjectTree) {\n                i = _.findIndex(filteredFiltered, filterIndexFile);\n\n                // We found no good match\n                if (i === -1) {\n                    // traverse the directory tree up one level\n                    containingFolder = FileUtils.getParentPath(containingFolder);\n                    // Are we still inside the project?\n                    if (containingFolder.indexOf(projectRoot) === -1) {\n                        stillInProjectTree = false;\n                    }\n                } else {\n                    indexFileFound = true;\n                }\n            }\n\n            if (i !== -1) {\n                DocumentManager.getDocumentForPath(filteredFiltered[i].fullPath).then(result.resolve, result.resolve);\n                return;\n            }\n\n            result.resolve(null);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * If the current editor is for a CSS preprocessor file, then add it to the style sheet\n     * so that we can track cursor positions in the editor to show live preview highlighting.\n     * For normal CSS we only do highlighting from files we know for sure are referenced by the\n     * current live preview document, but for preprocessors we just assume that any preprocessor\n     * file you edit is probably related to the live preview.\n     *\n     * @param {Event} event (unused)\n     * @param {Editor} current Current editor\n     * @param {Editor} previous Previous editor\n     *\n     */\n    function onActiveEditorChange(event, current, previous) {\n        if (previous && previous.document &&\n                CSSUtils.isCSSPreprocessorFile(previous.document.file.fullPath)) {\n            var prevDocUrl = _server && _server.pathToUrl(previous.document.file.fullPath);\n\n            if (_relatedDocuments && _relatedDocuments[prevDocUrl]) {\n                _closeRelatedDocument(_relatedDocuments[prevDocUrl]);\n            }\n        }\n        if (current && current.document &&\n                CSSUtils.isCSSPreprocessorFile(current.document.file.fullPath)) {\n            var docUrl = _server && _server.pathToUrl(current.document.file.fullPath);\n            _styleSheetAdded(null, docUrl);\n        }\n    }\n\n    /**\n     * @private\n     * While still connected to the Inspector, do cleanup for agents,\n     * documents and server.\n     * @param {boolean} doCloseWindow Use true to close the window/tab in the browser\n     * @return {jQuery.Promise} A promise that is always resolved\n     */\n    function _doInspectorDisconnect(doCloseWindow) {\n        var closePromise,\n            deferred    = new $.Deferred(),\n            connected   = Inspector.connected();\n\n        EditorManager.off(\"activeEditorChange\", onActiveEditorChange);\n\n        Inspector.Page.off(\".livedev\");\n        Inspector.off(\".livedev\");\n\n        // Wait if agents are loading\n        if (_loadAgentsPromise) {\n            _loadAgentsPromise.always(unloadAgents);\n        } else {\n            unloadAgents();\n        }\n\n        // Close live documents\n        _closeDocuments();\n\n        if (_server) {\n            // Stop listening for requests when disconnected\n            _server.stop();\n\n            // Dispose server\n            _server = null;\n        }\n\n        if (doCloseWindow && connected) {\n            closePromise = Inspector.Runtime.evaluate(\"window.open('', '_self').close();\");\n\n            // Add a timeout to continue cleanup if Inspector does not respond\n            closePromise = Async.withTimeout(closePromise, 5000);\n        } else {\n            closePromise = new $.Deferred().resolve();\n        }\n\n        // Disconnect WebSocket if connected\n        closePromise.always(function () {\n            if (Inspector.connected()) {\n                Inspector.disconnect().always(deferred.resolve);\n            } else {\n                deferred.resolve();\n            }\n        });\n\n        return deferred.promise();\n    }\n\n    /**\n     * @private\n     * Close the connection and the associated window asynchronously\n     * @param {boolean} doCloseWindow Use true to close the window/tab in the browser\n     * @param {?string} reason Optional string key suffix to display to user (see LIVE_DEV_* keys)\n     * @return {jQuery.Promise} Always return a resolved promise once the connection is closed\n     */\n    function _close(doCloseWindow, reason) {\n        WebSocketTransport.closeWebSocketServer();\n        if (_closeDeferred) {\n            return _closeDeferred;\n        } else {\n            _closeDeferred = new $.Deferred();\n            _closeDeferred.always(function () {\n                _closeDeferred = null;\n            });\n        }\n\n        var promise = _closeDeferred.promise();\n\n        /*\n         * Finish closing the live development connection, including setting\n         * the status accordingly.\n         */\n        function cleanup() {\n            // Need to do this in order to trigger the corresponding CloseLiveBrowser cleanups required on\n            // the native Mac side\n            var closeDeferred = (brackets.platform === \"mac\") ? NativeApp.closeLiveBrowser() : $.Deferred().resolve();\n            closeDeferred.done(function () {\n                _setStatus(STATUS_INACTIVE, reason || \"explicit_close\");\n                // clean-up registered servers\n                _regServers.forEach(function (server) {\n                    LiveDevServerManager.removeServer(server);\n                });\n                _regServers = [];\n                _closeDeferred.resolve();\n            }).fail(function (err) {\n                if (err) {\n                    reason +=  \" (\" + err + \")\";\n                }\n                _setStatus(STATUS_INACTIVE, reason || \"explicit_close\");\n                _closeDeferred.resolve();\n            });\n        }\n\n        if (_isPromisePending(_openDeferred)) {\n            // Reject calls to open if requests are still pending\n            _openDeferred.reject();\n        }\n\n        if (exports.status === STATUS_INACTIVE) {\n            // Ignore close if status is inactive\n            _closeDeferred.resolve();\n        } else {\n            _doInspectorDisconnect(doCloseWindow).always(cleanup);\n        }\n\n        return promise;\n    }\n\n    // WebInspector Event: Page.frameNavigated\n    function _onFrameNavigated(event, res) {\n        // res = {frame}\n        var url = res.frame.url,\n            baseUrl,\n            baseUrlRegExp;\n\n        // Only check domain of root frame (with undefined parentId)\n        if (res.frame.parentId) {\n            return;\n        }\n\n        // Any local file is OK\n        if (url.match(/^file:\\/\\//i) || !_server) {\n            return;\n        }\n\n        // Need base url to build reg exp\n        baseUrl = _server.getBaseUrl();\n        if (!baseUrl) {\n            return;\n        }\n\n        // Test that url is within site\n        baseUrlRegExp = new RegExp(\"^\" + StringUtils.regexEscape(baseUrl), \"i\");\n        if (!url.match(baseUrlRegExp)) {\n            // No longer in site, so terminate live dev, but don't close browser window\n            _close(false, \"navigated_away\");\n        }\n    }\n\n    /**\n     * @private\n     * Triggered by unexpected Inspector disconnect event\n     */\n    function _onDisconnect(event) {\n        _close(false, \"closed_unknown_reason\");\n    }\n\n    function _onDetached(event, res) {\n        var closeReason;\n\n        if (res && res.reason) {\n            // Get the explanation from res.reason, e.g. \"replaced_with_devtools\", \"target_closed\", \"canceled_by_user\"\n            // Examples taken from https://chromiumcodereview.appspot.com/10947037/patch/12001/13004\n            // However, the link refers to the Chrome Extension API, it may not apply 100% to the Inspector API\n            // Prefix with \"detached_\" to create a quasi-namespace for Chrome's reasons\n            closeReason = \"detached_\" + res.reason;\n        }\n\n        _close(false, closeReason);\n    }\n\n    /**\n     * Unload and reload agents\n     * @return {jQuery.Promise} Resolves once the agents are loaded\n     */\n    function reconnect() {\n        if (_loadAgentsPromise) {\n            // Agents are already loading, so don't unload\n            return _loadAgentsPromise;\n        }\n\n        unloadAgents();\n\n        // Clear any existing related documents before we reload the agents.\n        // We need to recreate them for the reloaded document due to some\n        // desirable side-effects (see #7606). Eventually, we should simplify\n        // the way we get that behavior.\n        _.forOwn(_relatedDocuments, function (relatedDoc) {\n            _closeRelatedDocument(relatedDoc);\n        });\n\n        return loadAgents();\n    }\n\n    /** reload the live preview */\n    function reload() {\n        // Unload and reload agents before reloading the page\n        // Some agents (e.g. DOMAgent and RemoteAgent) require us to\n        // navigate to the page first before loading can complete.\n        // To accomodate this, we load all agents (in reconnect())\n        // and navigate in parallel.\n        reconnect();\n\n        // Reload HTML page\n        Inspector.Page.reload();\n    }\n\n    /**\n     * Close the connection and the associated window asynchronously\n     * @return {jQuery.Promise} Resolves once the connection is closed\n     */\n    function close() {\n        return _close(true);\n    }\n\n    /**\n     * @private\n     * Create a promise that resolves when the interstitial page has\n     * finished loading.\n     *\n     * @return {jQuery.Promise} Resolves once page is loaded\n     */\n    function _waitForInterstitialPageLoad() {\n        var deferred    = $.Deferred(),\n            keepPolling = true,\n            timer       = window.setTimeout(function () {\n                keepPolling = false;\n                deferred.reject();\n            }, 10000); // 10 seconds\n\n        /*\n         * Asynchronously check to see if the interstitial page has\n         * finished loading; if not, check again until timing out.\n         */\n        function pollInterstitialPage() {\n            if (keepPolling && Inspector.connected()) {\n                Inspector.Runtime.evaluate(\"window.isBracketsLiveDevelopmentInterstitialPageLoaded\", function (response) {\n                    var result = response.result;\n\n                    if (result.type === \"boolean\" && result.value) {\n                        window.clearTimeout(timer);\n                        deferred.resolve();\n                    } else {\n                        window.setTimeout(pollInterstitialPage, 100);\n                    }\n                });\n            } else {\n                deferred.reject();\n            }\n        }\n\n        pollInterstitialPage();\n        return deferred.promise();\n    }\n\n    /**\n     * @private\n     * Load agents and navigate to the target document once the\n     * interstitial page has finished loading.\n     */\n    function _onInterstitialPageLoad() {\n\n        Inspector.Runtime.evaluate(\"window.navigator.userAgent\", function (uaResponse) {\n            Inspector.setUserAgent(uaResponse.result.value);\n        });\n\n        // Domains for some agents must be enabled first before loading\n        var enablePromise = Inspector.Page.enable().then(function () {\n            return Inspector.DOM.enable().then(_enableAgents, _enableAgents);\n        });\n\n        enablePromise.done(function () {\n            // Some agents (e.g. DOMAgent and RemoteAgent) require us to\n            // navigate to the page first before loading can complete.\n            // To accomodate this, we load all agents and navigate in\n            // parallel.\n\n            // resolve/reject the open() promise after agents complete\n            loadAgents().then(_openDeferred.resolve, _openDeferred.reject);\n\n            _getInitialDocFromCurrent().done(function (doc) {\n                if (doc && _liveDocument) {\n                    if (doc !== _liveDocument.doc) {\n                        _createLiveDocumentForFrame(doc);\n                    }\n\n                    // Navigate from interstitial to the document\n                    // Fires a frameNavigated event\n                    if (_server) {\n                        Inspector.Page.navigate(_server.pathToUrl(doc.file.fullPath));\n                    } else {\n                        console.error(\"LiveDevelopment._onInterstitialPageLoad(): No server active\");\n                    }\n                } else {\n                    // Unlikely that we would get to this state where\n                    // a connection is in process but there is no current\n                    // document\n                    close();\n                }\n            });\n        });\n    }\n\n    /** Triggered by Inspector.connect */\n    function _onConnect(event) {\n        // When the browser navigates away from the primary live document\n        Inspector.Page.on(\"frameNavigated.livedev\", _onFrameNavigated);\n\n        // When the Inspector WebSocket disconnects unexpectedely\n        Inspector.on(\"disconnect.livedev\", _onDisconnect);\n\n        _waitForInterstitialPageLoad()\n            .fail(function () {\n                close();\n\n                Dialogs.showModalDialog(\n                    DefaultDialogs.DIALOG_ID_ERROR,\n                    Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n                    _makeTroubleshootingMessage(Strings.LIVE_DEV_LOADING_ERROR_MESSAGE)\n                );\n            })\n            .done(_onInterstitialPageLoad);\n    }\n\n    function _showWrongDocError() {\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n            _makeTroubleshootingMessage(Strings.LIVE_DEV_NEED_HTML_MESSAGE)\n        );\n        _openDeferred.reject();\n    }\n\n    function _showLiveDevServerNotReadyError() {\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n            _makeTroubleshootingMessage(Strings.LIVE_DEV_SERVER_NOT_READY_MESSAGE)\n        );\n        _openDeferred.reject();\n    }\n\n    function _openInterstitialPage() {\n        var browserStarted  = false,\n            retryCount      = 0;\n\n        // Open the live browser if the connection fails, retry 3 times\n        Inspector.connectToURL(launcherUrl).fail(function onConnectFail(err) {\n            if (err === \"CANCEL\") {\n                _openDeferred.reject(err);\n                return;\n            }\n\n            if (retryCount > 3) {\n                _setStatus(STATUS_ERROR);\n\n                var dialogPromise = Dialogs.showModalDialog(\n                    DefaultDialogs.DIALOG_ID_LIVE_DEVELOPMENT,\n                    Strings.LIVE_DEVELOPMENT_RELAUNCH_TITLE,\n                    _makeTroubleshootingMessage(Strings.LIVE_DEVELOPMENT_ERROR_MESSAGE),\n                    [\n                        {\n                            className: Dialogs.DIALOG_BTN_CLASS_LEFT,\n                            id:        Dialogs.DIALOG_BTN_CANCEL,\n                            text:      Strings.CANCEL\n                        },\n                        {\n                            className: Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                            id:        Dialogs.DIALOG_BTN_OK,\n                            text:      Strings.RELAUNCH_CHROME\n                        }\n                    ]\n                );\n\n                dialogPromise.done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_OK) {\n                        // User has chosen to reload Chrome, quit the running instance\n                        _setStatus(STATUS_INACTIVE);\n                        _close()\n                            .done(function () {\n                                browserStarted = false;\n                                // Continue to use _openDeferred\n                                open(true);\n                            })\n                            .fail(function (err) {\n                                // Report error?\n                                _setStatus(STATUS_ERROR);\n                                browserStarted = false;\n                                _openDeferred.reject(\"CLOSE_LIVE_BROWSER\");\n                            });\n                    } else {\n                        _close()\n                            .done(function () {\n                                browserStarted = false;\n                                _openDeferred.reject(\"CANCEL\");\n                            })\n                            .fail(function (err) {\n                                // Report error?\n                                _setStatus(STATUS_ERROR);\n                                browserStarted = false;\n                                _openDeferred.reject(\"CLOSE_LIVE_BROWSER\");\n                            });\n                    }\n                });\n\n                return;\n            }\n            retryCount++;\n\n            if (!browserStarted && exports.status !== STATUS_ERROR) {\n                NativeApp.openLiveBrowser(\n                    launcherUrl,\n                    true        // enable remote debugging\n                )\n                    .done(function () {\n                        browserStarted = true;\n                    })\n                    .fail(function (err) {\n                        var message;\n\n                        _setStatus(STATUS_ERROR);\n                        if (err === FileSystemError.NOT_FOUND) {\n                            message = Strings.ERROR_CANT_FIND_CHROME;\n                        } else {\n                            message = StringUtils.format(Strings.ERROR_LAUNCHING_BROWSER, err);\n                        }\n\n                        Dialogs.showModalDialog(\n                            DefaultDialogs.DIALOG_ID_ERROR,\n                            Strings.ERROR_LAUNCHING_BROWSER_TITLE,\n                            _makeTroubleshootingMessage(message)\n                        );\n\n                        _openDeferred.reject(\"OPEN_LIVE_BROWSER\");\n                    });\n            }\n\n            if (exports.status !== STATUS_ERROR) {\n                window.setTimeout(function retryConnect() {\n                    Inspector.connectToURL(launcherUrl).fail(onConnectFail);\n                }, 3000);\n            }\n        });\n    }\n\n    // helper function that actually does the launch once we are sure we have\n    // a doc and the server for that doc is up and running.\n    function _doLaunchAfterServerReady(initialDoc) {\n        // update status\n        _setStatus(STATUS_CONNECTING);\n        _createLiveDocumentForFrame(initialDoc);\n\n        // start listening for requests\n        _server.start();\n\n        // Install a one-time event handler when connected to the launcher page\n        Inspector.one(\"connect\", _onConnect);\n\n        // open browser to the interstitial page to prepare for loading agents\n        _openInterstitialPage();\n\n        // Once all agents loaded (see _onInterstitialPageLoad()), begin Live Highlighting for preprocessor documents\n        _openDeferred.done(function () {\n            // Setup activeEditorChange event listener so that we can track cursor positions in\n            // CSS preprocessor files and perform live preview highlighting on all elements with\n            // the current selector in the preprocessor file.\n            EditorManager.on(\"activeEditorChange\", onActiveEditorChange);\n\n            // Explicitly trigger onActiveEditorChange so that live preview highlighting\n            // can be set up for the preprocessor files.\n            onActiveEditorChange(null, EditorManager.getActiveEditor(), null);\n        });\n    }\n\n    function _prepareServer(doc) {\n        var deferred = new $.Deferred(),\n            showBaseUrlPrompt = false;\n\n        _server = LiveDevServerManager.getServer(doc.file.fullPath);\n\n        // Optionally prompt for a base URL if no server was found but the\n        // file is a known server file extension\n        showBaseUrlPrompt = !exports.config.experimental && !_server &&\n            LiveDevelopmentUtils.isServerHtmlFileExt(doc.file.fullPath);\n\n        if (showBaseUrlPrompt) {\n            // Prompt for a base URL\n            PreferencesDialogs.showProjectPreferencesDialog(\"\", Strings.LIVE_DEV_NEED_BASEURL_MESSAGE)\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_OK && ProjectManager.getBaseUrl()) {\n                        // If base url is specifed, then re-invoke _prepareServer() to continue\n                        _prepareServer(doc).then(deferred.resolve, deferred.reject);\n                    } else {\n                        deferred.reject();\n                    }\n                });\n        } else if (_server) {\n            // Startup the server\n            var readyPromise = _server.readyToServe();\n            if (!readyPromise) {\n                _showLiveDevServerNotReadyError();\n                deferred.reject();\n            } else {\n                readyPromise.then(deferred.resolve, function () {\n                    _showLiveDevServerNotReadyError();\n                    deferred.reject();\n                });\n            }\n        } else {\n            // No server found\n            deferred.reject();\n        }\n\n        return deferred.promise();\n    }\n\n    function getCurrentProjectServerConfig() {\n        return {\n            baseUrl: ProjectManager.getBaseUrl(),\n            pathResolver: ProjectManager.makeProjectRelativeIfPossible,\n            root: ProjectManager.getProjectRoot().fullPath\n        };\n    }\n\n    function _createUserServer() {\n        return new UserServer(getCurrentProjectServerConfig());\n    }\n\n    function _createFileServer() {\n        return new FileServer(getCurrentProjectServerConfig());\n    }\n\n    /**\n     * Open the Connection and go live\n     *\n     * @param {!boolean} restart  true if relaunching and _openDeferred already exists\n     * @return {jQuery.Promise} Resolves once live preview is open\n     */\n    function open(restart) {\n        // If close() is still pending, wait for close to finish before opening\n        if (_isPromisePending(_closeDeferred)) {\n            return _closeDeferred.then(function () {\n                return open(restart);\n            });\n        }\n\n        if (!restart) {\n            // Return existing promise if it is still pending\n            if (_isPromisePending(_openDeferred)) {\n                return _openDeferred;\n            } else {\n                _openDeferred = new $.Deferred();\n                _openDeferred.always(function () {\n                    _openDeferred = null;\n                });\n            }\n        }\n        // Send analytics data when Live Preview is opened\n        HealthLogger.sendAnalyticsData(\n            \"livePreviewOpen\",\n            \"usage\",\n            \"livePreview\",\n            \"open\"\n        );\n\n        // Register user defined server provider and keep handlers for further clean-up\n        _regServers.push(LiveDevServerManager.registerServer({ create: _createUserServer }, 99));\n        _regServers.push(LiveDevServerManager.registerServer({ create: _createFileServer }, 0));\n\n        // TODO: need to run _onFileChanged() after load if doc != currentDocument here? Maybe not, since activeEditorChange\n        // doesn't trigger it, while inline editors can still cause edits in doc other than currentDoc...\n        _getInitialDocFromCurrent().done(function (doc) {\n            var prepareServerPromise = (doc && _prepareServer(doc)) || new $.Deferred().reject(),\n                otherDocumentsInWorkingFiles;\n\n            if (doc && !doc._masterEditor) {\n                otherDocumentsInWorkingFiles = MainViewManager.getWorkingSet(MainViewManager.ALL_PANES).length;\n                MainViewManager.addToWorkingSet(MainViewManager.ACTIVE_PANE, doc.file);\n\n                if (!otherDocumentsInWorkingFiles) {\n                    MainViewManager._edit(MainViewManager.ACTIVE_PANE, doc);\n                }\n            }\n\n            // wait for server (StaticServer, Base URL or file:)\n            prepareServerPromise\n                .done(function () {\n                    var reverseInspectPref = PreferencesManager.get(\"livedev.enableReverseInspect\"),\n                        wsPort             = PreferencesManager.get(\"livedev.wsPort\");\n                        \n                    if (wsPort && reverseInspectPref) {\n                        WebSocketTransport.createWebSocketServer(wsPort);\n                    }\n                    _doLaunchAfterServerReady(doc);\n                })\n                .fail(function () {\n                    _showWrongDocError();\n                });\n        });\n\n        return _openDeferred.promise();\n    }\n\n    /** Enable highlighting */\n    function showHighlight() {\n        var doc = getLiveDocForEditor(EditorManager.getActiveEditor());\n\n        if (doc && doc.updateHighlight) {\n            doc.updateHighlight();\n        }\n    }\n\n    /** Hide any active highlighting */\n    function hideHighlight() {\n        if (Inspector.connected() && agents.highlight) {\n            agents.highlight.hide();\n        }\n    }\n\n    /** Redraw highlights **/\n    function redrawHighlight() {\n        if (Inspector.connected() && agents.highlight) {\n            agents.highlight.redraw();\n        }\n    }\n\n    /**\n     * @private\n     * MainViewManager.currentFileChange event handler.\n     */\n    function _onFileChanged() {\n        var doc = _getCurrentDocument();\n\n        if (!doc || !Inspector.connected()) {\n            return;\n        }\n\n        // close the current session and begin a new session if the current\n        // document changes to an HTML document that was not loaded yet\n        var docUrl = _server && _server.pathToUrl(doc.file.fullPath),\n            wasRequested = agents.network && agents.network.wasURLRequested(docUrl),\n            isViewable = exports.config.experimental || (_server && _server.canServe(doc.file.fullPath));\n\n        if (!wasRequested && isViewable) {\n            // Update status\n            _setStatus(STATUS_CONNECTING);\n\n            // clear live doc and related docs\n            _closeDocuments();\n\n            // create new live doc\n            _createLiveDocumentForFrame(doc);\n\n            // Navigate to the new page within this site. Agents must handle\n            // frameNavigated event to clear any saved state.\n            Inspector.Page.navigate(docUrl).then(function () {\n                _setStatus(STATUS_ACTIVE);\n            }, function () {\n                _close(false, \"closed_unknown_reason\");\n            });\n        } else if (wasRequested) {\n            // Update highlight\n            showHighlight();\n        }\n    }\n\n    /**\n     * Triggered by a documentSaved event from DocumentManager.\n     * @param {$.Event} event\n     * @param {Document} doc\n     */\n    function _onDocumentSaved(event, doc) {\n        if (!Inspector.connected() || !_server) {\n            return;\n        }\n\n        var absolutePath            = doc.file.fullPath,\n            liveDocument            = absolutePath && _server.get(absolutePath),\n            liveEditingEnabled      = liveDocument && liveDocument.isLiveEditingEnabled  && liveDocument.isLiveEditingEnabled();\n\n        // Skip reload if the saved document has live editing enabled\n        if (liveEditingEnabled) {\n            return;\n        }\n\n        var documentUrl     = _server.pathToUrl(absolutePath),\n            wasRequested    = agents.network && agents.network.wasURLRequested(documentUrl);\n\n        if (wasRequested) {\n            reload();\n        }\n    }\n\n    /** Triggered by a change in dirty flag from the DocumentManager */\n    function _onDirtyFlagChange(event, doc) {\n        if (doc && Inspector.connected() &&\n                _server && agents.network && agents.network.wasURLRequested(_server.pathToUrl(doc.file.fullPath))) {\n            // Set status to out of sync if dirty. Otherwise, set it to active status.\n            _setStatus(_docIsOutOfSync(doc) ? STATUS_OUT_OF_SYNC : STATUS_ACTIVE);\n        }\n    }\n\n    /** Initialize the LiveDevelopment Session */\n    function init(theConfig) {\n        exports.config = theConfig;\n\n        Inspector.on(\"error\", _onError);\n        Inspector.Inspector.on(\"detached\", _onDetached);\n\n        // Only listen for styleSheetAdded\n        // We may get interim added/removed events when pushing incremental updates\n        CSSAgent.on(\"styleSheetAdded.livedev\", _styleSheetAdded);\n\n        MainViewManager\n            .on(\"currentFileChange\", _onFileChanged);\n        DocumentManager\n            .on(\"documentSaved\", _onDocumentSaved)\n            .on(\"dirtyFlagChange\", _onDirtyFlagChange);\n        ProjectManager\n            .on(\"beforeProjectClose beforeAppClose\", close);\n\n        // Initialize exports.status\n        _setStatus(STATUS_INACTIVE);\n    }\n\n    function _getServer() {\n        return _server;\n    }\n\n    function getServerBaseUrl() {\n        return _server && _server.getBaseUrl();\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // For unit testing\n    exports.launcherUrl               = launcherUrl;\n    exports._getServer                = _getServer;\n    exports._getInitialDocFromCurrent = _getInitialDocFromCurrent;\n\n    // Export public functions\n    exports.agents              = agents;\n    exports.open                = open;\n    exports.close               = close;\n    exports.reconnect           = reconnect;\n    exports.reload              = reload;\n    exports.enableAgent         = enableAgent;\n    exports.disableAgent        = disableAgent;\n    exports.getLiveDocForPath   = getLiveDocForPath;\n    exports.showHighlight       = showHighlight;\n    exports.hideHighlight       = hideHighlight;\n    exports.redrawHighlight     = redrawHighlight;\n    exports.init                = init;\n    exports.getCurrentProjectServerConfig = getCurrentProjectServerConfig;\n    exports.getServerBaseUrl    = getServerBaseUrl;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/LiveDevelopmentUtils.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Set of utilities for working with files and text content.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var LanguageManager = require(\"language/LanguageManager\"),\n        ProjectManager  = require(\"project/ProjectManager\");\n\n    /**\n     * File extensions - hard-coded for now, but may want to make these preferences\n     * @const {Array.<string>}\n     */\n    var _staticHtmlFileExts = [\"htm\", \"html\", \"xhtml\"],\n        _serverHtmlFileExts = [\"php\", \"php3\", \"php4\", \"php5\", \"phtm\", \"phtml\", \"cfm\", \"cfml\", \"asp\", \"aspx\", \"jsp\", \"jspx\", \"shtm\", \"shtml\"];\n\n    /**\n     * Determine if file extension is a static html file extension.\n     * @param {string} filePath could be a path, a file name or just a file extension\n     * @return {boolean} Returns true if fileExt is in the list\n     */\n    function isStaticHtmlFileExt(filePath) {\n        if (!filePath) {\n            return false;\n        }\n\n        return (_staticHtmlFileExts.indexOf(LanguageManager.getLanguageForPath(filePath).getId()) !== -1);\n    }\n\n    /**\n     * Determine if file extension is a server html file extension.\n     * @param {string} filePath could be a path, a file name or just a file extension\n     * @return {boolean} Returns true if fileExt is in the list\n     */\n    function isServerHtmlFileExt(filePath) {\n        if (!filePath) {\n            return false;\n        }\n\n        return (_serverHtmlFileExts.indexOf(LanguageManager.getLanguageForPath(filePath).getId()) !== -1);\n    }\n\n    /**\n     * Returns true if we think the given extension is for an HTML file.\n     * @param {string} ext The extension to check.\n     * @return {boolean} true if this is an HTML extension.\n     */\n    function isHtmlFileExt(ext) {\n        return (isStaticHtmlFileExt(ext) ||\n                (ProjectManager.getBaseUrl() && isServerHtmlFileExt(ext)));\n    }\n\n    // Define public API\n    exports.isHtmlFileExt       = isHtmlFileExt;\n    exports.isStaticHtmlFileExt = isStaticHtmlFileExt;\n    exports.isServerHtmlFileExt = isServerHtmlFileExt;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/README.md",
    "content": "This is an experimental implementation to replace the current live development architecture with something more flexible that isn't tied solely to Chrome Developer Tools. \nIt's based on the current Live Development code in Brackets and has been incubated at njx/brackets-livedev2.\n\n### What's working\n\nIt can be enabled by setting ```livedev.multibrowser``` preference to true. If enabled, it will launch will launch the page in your default browser when clicking on the LiveDevelopment icon as it works today. You should then also be able to copy and paste the URL from that browser into any other browser, live edits will then update all connected browsers at once.\n\nThis is still an experimental implementation, the basic functionality for CSS/HTML editing is working but there are could be some scenarios that might be partially or entirely not covered yet. Page reload when saving changes on related Javascript files is also working. Documents that are loaded by the current HTML live doc are being tracked by ```DocumentObserver``` at the browser side which relies on DOM MutationObserver for monitoring added/removed stylesheets and Javascript files (just monitoring ```<link>``` and ```<script>``` added/removed nodes so far. \n\n### Basic architecture\n\nThe primary difference in this architecture is that communication with the browser is done via an injected script rather than CDT's native remote debugging interface, and the browser connects back to Brackets rather than Brackets connecting to the browser. This makes it so:\n\n* launching a preview, injecting scripts into the HTML, and establishing the connection between the previewed page and Brackets are relatively simple and largely decoupled\n* live preview can work in any browser, not just Chrome\n* multiple browsers can connect to the same live preview session in Brackets\n* browsers could theoretically connect from anywhere on the network that can see Brackets (though right now it's only implemented for localhost)\n* opening dev tools in the browser doesn't break live preview\n\nCommunication between Brackets and the browser is factored into three layers:\n\n1. a low-level \"transport\" layer, which is responsible for launching live preview in the browser and providing a simple textual message bus between the browser and Brackets.\n2. the \"protocol\" layer, which sits on top of the transport layer and provides the actual semantic behavior (currently just \"evaluate in browser\")\n3. the injected RemoteFunctions script, which is the same as in today's LiveDevelopment and provides Brackets-specific functionality (highlighting, DOM edit application) on top of the core protocol.\n\nThe reason for this factoring is so that the transport layer can be swapped out for different use cases, and so that anything higher-level we need that can be easily built in terms of eval doesn't have to be built into the protocol.\n\n(We could arguably get rid of the distinction between (2) and (3), and basically roll all the Brackets functionality into the \"protocol\" layer by simply merging the RemoteFunctions script into the protocol remote script. The only reason to keep the protocol layer separate, IMO, is if we want to keep it compatible with CDT, a la RemoteDebug - so it only provides the functionality that CDT does.)\n\nThe transport layer currently implemented uses a WebSocket server in Node, coupled with an injected script in the browser that connects back to that server. However, this could easily be swapped out for a different transport layer that supports a preview iframe directly inside Brackets, where the communication is via `postMessage()`.\n\nThe protocol layer currently exposes a very simple API that currently just contains specific protocol functions: \n * \"evaluate\"  which evals in the browser\n * \"reload\" which reload the page in the browser\n * \"navigate\" which allow the browser navigate to a given URL\n \nThe over-the-wire protocol is a JSON message that more or less looks like the CDT wire protocol, although it's not an exact match right now - again, we could decide to make it exactly mimic CDT if we wanted.\n\nIf we want to eventually reintroduce a CDT connection (or hook up to RemoteDebug), we have two choices: we could either just implement it as a separate transport, or we could implement it as a separate protocol impl entirely. Implementing it as a transport would be easier, and would be fine for talking to our own injected script; but it would only make sense for talking to CDT-specific functionality if we were very good about our wire protocol looking like the CDT wire protocol in general. Otherwise, we would probably want to consider swapping out the protocol entirely.\n\n### Explanation of the flow\n\nI've created a [really crappy block diagram](https://raw.githubusercontent.com/wiki/njx/brackets-livedev2/livedev2-block-diagram.png) of how the various bits talk to each other.\n\nHere's a short summary of what happens when the user clicks on the Live Preview button on an HTML page.\n\n1. LiveDevelopment creates a LiveHTMLDocument for the page, passing it the protocol handler (LiveDevProtocol). LiveHTMLDocument manages communication between the editor and the browser for HTML pages.\n2. LiveDevelopment tells StaticServer that this path has a live document. StaticServer is in charge of actually serving the page and associated assets to the browser. (Note: eventually I think we should get rid of this step - StaticServer shouldn't know anything about live documents directly; it should just have a way of request instrumented text for HTML URLs.)\n3. LiveDevelopment tells the launcher to open the page via the StaticServer URL, then it opens the page in the default browser.\n4. The browser requests the page from StaticServer. StaticServer notes that there is a live document for this page, and requests an instrumented version of the page from LiveHTMLDocument. (The current \"requestFilterPaths\" mechanism for this could be simplified, I think.)\n5. LiveHTMLDocument instruments the page for live editing using the existing HTMLInstrumentation mechanism, and additionally includes remote scripts provided by the protocol (LiveDevProtocolRemote), transport (NodeSocketTransportRemote), remote functions (RemoteFunctions) and document observation (DocumentObserver) which tracks related documents. The transport script includes the URL for the WebSocket server created when the transport is started after being set to the protocol layer.\n6. The instrumented page is sent back to StaticServer, which responds to the browser with the instrumented version. Other files requested by the browser are simply returned directly by StaticServer.\n7. As the browser loads the page, it encounters the injected scripts. The transport script connects back to the NodeSocketTransport's WebSocket server created in step 3 and sends it a \"connect\" message to tell it what URL has been loaded in the browser. The NodeSocketTransport assigns the socket a client id so it can keep track of which socket is associated with which page instance, then raises a \"connect\" event.\n8. LivDevProtocol receives the \"connect\" event and makes a note of the associated client ID updating the current active connections. LiveDevelopment also receives the \"connect\" event, it checks that the URL that comes on the message matches the current live doc instance and updates session status to STATUS_ACTIVE in case this is the first client connected.\nAfter the live document is loaded in the browser, DocumentObserver scan related stylesheets and Javascript files and send a message 'DocumentRelated' which contains their URLs. LiveDevelopment receives the message, extract stylesshes and creates a LiveCSSDocument instance per each of them. LiveHTMLDocument listen to the same message and further notifications (added/removed) to keep info about its related docs which is needed by LiveDocument (eg. when saving changes of a JS file).\n9. As the user makes live edits or changes selection, LiveHTMLDocument calls the protocol handler's \"evaluate\" function to call functions from the injected RemoteFunctions.\n10. The protocol's \"evaluate\" method packages up the request as a JSON message and sends it via the transport.\n11. The remote transport handler unpacks the message and passes it to the remote protocol handler, which finally interprets it and evals its content.\n12. If another browser loads the same page (from the StaticServer URL), steps 4-8 repeat, with LiveHTMLDocument just adding the new connection's client ID to its list. Future evals are then sent to all the associated client IDs for the page.\n\n\n### Changes from existing LiveDevelopment code\n\n* the existing code for talking to Chrome Developer Tools via the remote debugging interface is gone for now\n* CSSDocument and HTMLDocument were renamed to LiveCSSDocument and LiveHTMLDocument, with a new LiveDocument base class\n* the \"agents\" are all gone - a lot of them were dead code anyway; other functionality was rolled into LiveDocument\n* communication is factored into transport and protocol layers (see above)\n* HTMLInstrumentation and HTMLSimpleDOM were modified slightly (which is why they're copied into the extension), to make it possible to inject the remote scripts and to fix an issue with re-instrumenting the HTML when a second browser connects to Live Development. The former change is harmless; the latter change would need some review or possibly more work in order to merge into master. \n\n\n#### Unit tests\n\nWe would definitely need a good suite of unit tests for the new functionality. There are just a few integration tests that were 'migrated' from the current suite of LiveDevelopment but, it would need more granular unit tests and be able to run them on multiple browsers.\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/documents/LiveCSSDocument.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\n/**\n * LiveCSSDocument manages a single CSS source document\n *\n * # EDITING\n *\n * Editing the document will cause the style sheet to be reloaded in the browser,\n * which immediately updates the appearance of the rendered document.\n *\n * # HIGHLIGHTING\n *\n * DOM nodes corresponding to the rule at the current cursor position are highlighted.\n *\n * # EVENTS\n *\n * LiveCSSDocument dispatches these events:\n *  deleted - When the file for the underlying Document has been deleted. The\n *      2nd argument to the listener will be this LiveCSSDocument.\n */\ndefine(function LiveCSSDocumentModule(require, exports, module) {\n    \"use strict\";\n\n    var _               = require(\"thirdparty/lodash\"),\n        CSSUtils        = require(\"language/CSSUtils\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        LiveDocument    = require(\"LiveDevelopment/MultiBrowserImpl/documents/LiveDocument\"),\n        PathUtils       = require(\"thirdparty/path-utils/path-utils\");\n\n    /**\n     * @constructor\n     * @see LiveDocument\n     * @param {LiveDevProtocol} protocol The protocol to use for communicating with the browser.\n     * @param {function(string): string} urlResolver A function that, given a path on disk, should return\n     *     the URL that Live Development serves that path at.\n     * @param {Document} doc The Brackets document that this live document is connected to.\n     * @param {?Editor} editor If specified, a particular editor that this live document is managing.\n     *     If not specified initially, the LiveDocument will connect to the editor for the given document\n     *     when it next becomes the active editor.\n     */\n    var LiveCSSDocument = function LiveCSSDocument(protocol, urlResolver, doc, editor, roots) {\n        LiveDocument.apply(this, arguments);\n\n        // Add a ref to the doc since we're listening for change events\n        this.doc.addRef();\n        this.onChange = this.onChange.bind(this);\n        this.onDeleted = this.onDeleted.bind(this);\n\n        this.doc.on(\"change.LiveCSSDocument\", this.onChange);\n        this.doc.on(\"deleted.LiveCSSDocument\", this.onDeleted);\n        if (editor) {\n            this._attachToEditor(editor);\n        }\n    };\n\n    LiveCSSDocument.prototype = Object.create(LiveDocument.prototype);\n    LiveCSSDocument.prototype.constructor = LiveCSSDocument;\n    LiveCSSDocument.prototype.parentClass = LiveDocument.prototype;\n\n    EventDispatcher.makeEventDispatcher(LiveCSSDocument.prototype);\n\n    /**\n     * @override\n     * Closes the live document, terminating its connection to the browser.\n     */\n    LiveCSSDocument.prototype.close = function () {\n        this.doc.off(\".LiveCSSDocument\");\n        this.doc.releaseRef();\n        this.parentClass.close.call(this);\n    };\n\n    /**\n     * When the user edits the file, update the stylesheet in the browser and redraw highlights.\n     */\n    LiveCSSDocument.prototype._updateBrowser = function () {\n        var i,\n            docUrl = this.doc.url;\n\n        // Determines whether an url() line contains a relative or absolute URL, and makes\n        // the URL absolute to the CSS file if it is relative\n        function makeUrlsRelativeToCss(match, quotationMark, url) {\n            if (PathUtils.isRelativeUrl(url)) {\n                var absUrl = PathUtils.makeUrlAbsolute(url, docUrl);\n                return \"url(\" + quotationMark + absUrl + quotationMark + \")\";\n            }\n            return match;\n        }\n\n        for (i = 0; i < this.roots.length; i++) {\n            if (docUrl !== this.roots[i].toString()) {\n                // if it's not directly included through <link>,\n                // reload the original doc\n                this.trigger(\"updateDoc\", this.roots[i]);\n            } else {\n                var docText = this.doc.getText();\n\n                // Replace all occurrences of url() where the URL is relative to the CSS file with\n                // an absolute URL so it is relative to the CSS file, not the HTML file (see #11936)\n                docText = docText.replace(/\\burl\\(\\s*([\"']?)([^)\\n]+)\\1\\s*\\)/ig, makeUrlsRelativeToCss);\n                this.protocol.setStylesheetText(docUrl, docText);\n            }\n        }\n        this.redrawHighlights();\n    };\n\n    /**\n     * @override\n     * Update the highlights in the browser based on the cursor position.\n     */\n    LiveCSSDocument.prototype.updateHighlight = function () {\n        if (this.isHighlightEnabled() && this.editor) {\n            var editor = this.editor,\n                selectors = [];\n            _.each(this.editor.getSelections(), function (sel) {\n                var selector = CSSUtils.findSelectorAtDocumentPos(editor, (sel.reversed ? sel.end : sel.start));\n                if (selector) {\n                    selectors.push(selector);\n                }\n            });\n            if (selectors.length) {\n                this.highlightRule(selectors.join(\",\"));\n            } else {\n                this.hideHighlight();\n            }\n        }\n    };\n\n    /**\n     * @override\n     * Returns true if document edits appear live in the connected browser.\n     * @return {boolean}\n     */\n    LiveCSSDocument.prototype.isLiveEditingEnabled = function () {\n        return true;\n    };\n\n    /** Event Handlers *******************************************************/\n\n    /**\n     * @private\n     * Handles edits to the document. Updates the stylesheet in the browser.\n     * @param {$.Event} event\n     * @param {Editor} editor\n     * @param {Object} change\n     */\n    LiveCSSDocument.prototype.onChange = function (event, editor, change) {\n        this._updateBrowser();\n    };\n\n    /**\n     * @private\n     * Handles when the associated CSS document is deleted on disk. Removes the\n     * stylesheet from the browser and shuts down the live document.\n     * @param {$.Event} event\n     */\n    LiveCSSDocument.prototype.onDeleted = function (event) {\n        // TODO Need to add protocol API to remove the stylesheet from the document.\n        //CSSAgent.clearCSSForDocument(this.doc);\n\n        // shut down, since our Document is now dead\n        this.close();\n        this.trigger(\"deleted\", [this]);\n    };\n\n    // Only used for unit testing.\n    LiveCSSDocument.prototype.getSourceFromBrowser = function () {\n        var deferred = new $.Deferred();\n\n        this.protocol.getStylesheetText(this.doc.url)\n            .then(function (res) {\n                deferred.resolve(res.text);\n            }, deferred.reject);\n\n        return deferred.promise();\n    };\n\n    // Export the class\n    module.exports = LiveCSSDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/documents/LiveDocument.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = require(\"editor/EditorManager\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    /**\n     * @const\n     * CSS class to use for live preview errors.\n     * @type {string}\n     */\n    var SYNC_ERROR_CLASS = \"live-preview-sync-error\";\n\n    /**\n     * @constructor\n     * Base class for managing the connection between a live editor and the browser. Provides functions\n     * for subclasses to highlight relevant nodes in the browser, and to mark errors in the editor.\n     *\n     * Raises these events:\n     *     \"connect\" - when a browser connects from the URL that maps to this live document. Passes the\n     *          URL as a parameter.\n     *     \"errorStatusChanged\" - when the status of errors that might prevent live edits from\n     *          working (e.g. HTML syntax errors) has changed. Passes a boolean that's true if there\n     *          are errors, false otherwise.\n     *\n     * @param {LiveDevProtocol} protocol The protocol to use for communicating with the browser.\n     * @param {function(string): string} urlResolver A function that, given a path on disk, should return\n     *     the URL that Live Development serves that path at.\n     * @param {Document} doc The Brackets document that this live document is connected to.\n     * @param {?Editor} editor If specified, a particular editor that this live document is managing.\n     *     If not specified initially, the LiveDocument will connect to the editor for the given document\n     *     when it next becomes the active editor.\n     */\n    function LiveDocument(protocol, urlResolver, doc, editor, roots) {\n        this.protocol = protocol;\n        this.urlResolver = urlResolver;\n        this.doc = doc;\n        this.roots = roots || [];\n\n        this._onActiveEditorChange = this._onActiveEditorChange.bind(this);\n        this._onCursorActivity = this._onCursorActivity.bind(this);\n        this._onHighlightPrefChange = this._onHighlightPrefChange.bind(this);\n\n        EditorManager.on(\"activeEditorChange\", this._onActiveEditorChange);\n\n        PreferencesManager.stateManager.getPreference(\"livedev.highlight\")\n            .on(\"change\", this._onHighlightPrefChange);\n\n        // Redraw highlights when window gets focus. This ensures that the highlights\n        // will be in sync with any DOM changes that may have occurred.\n        $(window).focus(this._onHighlightPrefChange);\n\n        if (editor) {\n            // Attach now\n            this._attachToEditor(editor);\n        }\n    }\n\n    EventDispatcher.makeEventDispatcher(LiveDocument.prototype);\n\n    /**\n     * Closes the live document, terminating its connection to the browser.\n     */\n    LiveDocument.prototype.close = function () {\n\n        this._clearErrorDisplay();\n        this._detachFromEditor();\n        EditorManager.off(\"activeEditorChange\", this._onActiveEditorChange);\n        PreferencesManager.stateManager.getPreference(\"livedev.highlight\")\n            .off(\"change\", this._onHighlightPrefChange);\n    };\n\n    /**\n     * Returns true if document edits appear live in the connected browser.\n     * Should be overridden by subclasses.\n     * @return {boolean}\n     */\n    LiveDocument.prototype.isLiveEditingEnabled = function () {\n        return false;\n    };\n\n    /**\n     * Called to turn instrumentation on or off for this file. Triggered by being\n     * requested from the browser. Should be implemented by subclasses if instrumentation\n     * is necessary for the subclass's document type.\n     * TODO: this doesn't seem necessary...if we're a live document, we should\n     * always have instrumentation on anyway.\n     * @param {boolean} enabled\n     */\n    LiveDocument.prototype.setInstrumentationEnabled = function (enabled) {\n        // Does nothing in base class.\n    };\n\n    /**\n     * Returns the instrumented version of the file. By default, just returns\n     * the document text. Should be overridden by subclasses for cases if instrumentation\n     * is necessary for the subclass's document type.\n     * @return {{body: string}} document body\n     */\n    LiveDocument.prototype.getResponseData = function (enabled) {\n        return {\n            body: this.doc.getText()\n        };\n    };\n\n    /**\n     * @private\n     * Handles changes to the \"Live Highlight\" preference, switching it on/off in the browser as appropriate.\n     */\n    LiveDocument.prototype._onHighlightPrefChange = function () {\n        if (this.isHighlightEnabled()) {\n            this.updateHighlight();\n        } else {\n            this.hideHighlight();\n        }\n    };\n\n    /**\n     * @private\n     * Handles when the active editor changes, attaching to the new editor if it's for the current document.\n     * @param {$.Event} event\n     * @param {?Editor} newActive\n     * @param {?Editor} oldActive\n     */\n    LiveDocument.prototype._onActiveEditorChange = function (event, newActive, oldActive) {\n\n        //FIXME: #7 prevents the page to be reloaded when editing JS files.\n        //       Temporarily disabling this code to make JS editing work.\n//      this._detachFromEditor();\n\n        if (newActive && newActive.document === this.doc) {\n            this._attachToEditor(newActive);\n        }\n    };\n\n    /**\n     * @private\n     * Attaches to an editor for our associated document when it becomes active.\n     * @param {Editor} editor\n     */\n    LiveDocument.prototype._attachToEditor = function (editor) {\n        this.editor = editor;\n\n        if (this.editor) {\n            this.editor.on(\"cursorActivity\", this._onCursorActivity);\n            this.updateHighlight();\n        }\n    };\n\n    /**\n     * @private\n     * Detaches from the current editor.\n     */\n    LiveDocument.prototype._detachFromEditor = function () {\n        if (this.editor) {\n            this.hideHighlight();\n            this.editor.off(\"cursorActivity\", this._onCursorActivity);\n            this.editor = null;\n        }\n    };\n\n    /**\n     * @private\n     * Handles a cursor change in our attached editor. Updates the highlight in the browser.\n     * @param {$.Event} event\n     * @param {Editor} editor\n     */\n    LiveDocument.prototype._onCursorActivity = function (event, editor) {\n        if (!this.editor) {\n            return;\n        }\n        this.updateHighlight();\n    };\n\n    /**\n     * @private\n     * Update errors shown by the live document in the editor. Should be called by subclasses\n     * when the list of errors changes.\n     */\n    LiveDocument.prototype._updateErrorDisplay = function () {\n        var self = this,\n            startLine,\n            endLine,\n            i,\n            lineHandle;\n\n        if (!this.editor) {\n            return;\n        }\n\n        // Buffer addLineClass DOM changes in a CodeMirror operation\n        this.editor._codeMirror.operation(function () {\n            // Remove existing errors before marking new ones\n            self._clearErrorDisplay();\n\n            self._errorLineHandles = self._errorLineHandles || [];\n\n            self.errors.forEach(function (error) {\n                startLine = error.startPos.line;\n                endLine = error.endPos.line;\n\n                for (i = startLine; i < endLine + 1; i++) {\n                    lineHandle = self.editor._codeMirror.addLineClass(i, \"wrap\", SYNC_ERROR_CLASS);\n                    self._errorLineHandles.push(lineHandle);\n                }\n            });\n        });\n\n        this.trigger(\"errorStatusChanged\", !!this.errors.length);\n    };\n\n    /**\n     * @private\n     * Clears the errors shown in the attached editor.\n     */\n    LiveDocument.prototype._clearErrorDisplay = function () {\n        var self = this,\n            lineHandle;\n\n        if (!this.editor ||\n                !this._errorLineHandles ||\n                !this._errorLineHandles.length) {\n            return;\n        }\n\n        this.editor._codeMirror.operation(function () {\n            while (true) {\n                // Iterate over all lines that were previously marked with an error\n                lineHandle = self._errorLineHandles.pop();\n\n                if (!lineHandle) {\n                    break;\n                }\n\n                self.editor._codeMirror.removeLineClass(lineHandle, \"wrap\", SYNC_ERROR_CLASS);\n            }\n        });\n    };\n\n    /**\n     * Returns true if we should be highlighting.\n     * @return {boolean}\n     */\n    LiveDocument.prototype.isHighlightEnabled = function () {\n        return PreferencesManager.getViewState(\"livedev.highlight\");\n    };\n\n    /**\n     * Called when the highlight in the browser should be updated because the user has\n     * changed the selection. Does nothing in base class, should be implemented by subclasses\n     * that implement highlighting functionality.\n     */\n    LiveDocument.prototype.updateHighlight = function () {\n        // Does nothing in base class\n    };\n\n    /**\n     * Hides the current highlight in the browser.\n     * @param {boolean=} temporary If true, this isn't a change of state - we're just about\n     *     to re-highlight.\n     */\n    LiveDocument.prototype.hideHighlight = function (temporary) {\n        if (!temporary) {\n            this._lastHighlight = null;\n        }\n        this.protocol.evaluate(\"_LD.hideHighlight()\");\n    };\n\n    /**\n     * Highlight all nodes affected by a CSS rule. Should be called by subclass implementations of\n     * `updateHighlight()`.\n     * @param {string} name The selector whose matched nodes should be highlighted.\n     */\n    LiveDocument.prototype.highlightRule = function (name) {\n        if (this._lastHighlight === name) {\n            return;\n        }\n        this._lastHighlight = name;\n        this.protocol.evaluate(\"_LD.highlightRule(\" + JSON.stringify(name) + \")\");\n    };\n\n    /**\n     * Highlight all nodes with 'data-brackets-id' value\n     * that matches id, or if id is an array, matches any of the given ids.\n     * Should be called by subclass implementations of\n     * `updateHighlight()`.\n     * @param {string|Array.<string>} value of the 'data-brackets-id' to match,\n     * or an array of such.\n     */\n    LiveDocument.prototype.highlightDomElement = function (ids) {\n        var selector = \"\";\n        if (!Array.isArray(ids)) {\n            ids = [ids];\n        }\n        _.each(ids, function (id) {\n            if (selector !== \"\") {\n                selector += \",\";\n            }\n            selector += \"[data-brackets-id='\" + id + \"']\";\n        });\n        this.highlightRule(selector);\n    };\n\n    /**\n     * Redraw active highlights.\n     */\n    LiveDocument.prototype.redrawHighlights = function () {\n        if (this.isHighlightEnabled()) {\n            this.protocol.evaluate(\"_LD.redrawHighlights()\");\n        }\n    };\n\n    module.exports = LiveDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/documents/LiveHTMLDocument.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * LiveHTMLDocument manages a single HTML source document. Edits to the HTML are applied live in\n * the browser, and the DOM node corresponding to the selection is highlighted.\n *\n * LiveHTMLDocument relies on HTMLInstrumentation in order to map tags in the HTML source text\n * to DOM nodes in the browser, so edits can be incrementally applied.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher     = require(\"utils/EventDispatcher\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        _                   = require(\"thirdparty/lodash\"),\n        LiveDocument        = require(\"LiveDevelopment/MultiBrowserImpl/documents/LiveDocument\"),\n        HTMLInstrumentation = require(\"LiveDevelopment/MultiBrowserImpl/language/HTMLInstrumentation\");\n\n\n    /**\n     * @constructor\n     * @see LiveDocument\n     * @param {LiveDevProtocol} protocol The protocol to use for communicating with the browser.\n     * @param {function(string): string} urlResolver A function that, given a path on disk, should return\n     *     the URL that Live Development serves that path at.\n     * @param {Document} doc The Brackets document that this live document is connected to.\n     * @param {?Editor} editor If specified, a particular editor that this live document is managing.\n     *     If not specified initially, the LiveDocument will connect to the editor for the given document\n     *     when it next becomes the active editor.\n     */\n    function LiveHTMLDocument(protocol, urlResolver, doc, editor) {\n        LiveDocument.apply(this, arguments);\n\n        this._instrumentationEnabled = false;\n        this._relatedDocuments = {\n            stylesheets: {},\n            scripts: {}\n        };\n\n        this._onChange = this._onChange.bind(this);\n        this.doc.on(\"change\", this._onChange);\n\n        this._onRelated = this._onRelated.bind(this);\n        this.protocol.on(\"DocumentRelated\", this._onRelated);\n\n        this._onStylesheetAdded = this._onStylesheetAdded.bind(this);\n        this.protocol.on(\"StylesheetAdded\", this._onStylesheetAdded);\n\n        this._onStylesheetRemoved = this._onStylesheetRemoved.bind(this);\n        this.protocol.on(\"StylesheetRemoved\", this._onStylesheetRemoved);\n\n        this._onScriptAdded = this._onScriptAdded.bind(this);\n        this.protocol.on(\"ScriptAdded\", this._onScriptAdded);\n\n        this._onScriptRemoved = this._onScriptRemoved.bind(this);\n        this.protocol.on(\"ScriptRemoved\", this._onScriptRemoved);\n\n    }\n\n    LiveHTMLDocument.prototype = Object.create(LiveDocument.prototype);\n    LiveHTMLDocument.prototype.constructor = LiveHTMLDocument;\n    LiveHTMLDocument.prototype.parentClass = LiveDocument.prototype;\n\n    EventDispatcher.makeEventDispatcher(LiveHTMLDocument.prototype);\n\n    /**\n     * @override\n     * Returns true if document edits appear live in the connected browser.\n     * @return {boolean}\n     */\n    LiveHTMLDocument.prototype.isLiveEditingEnabled = function () {\n        return this._instrumentationEnabled;\n    };\n\n    /**\n     * @override\n     * Called to turn instrumentation on or off for this file. Triggered by being\n     * requested from the browser.\n     * TODO: this doesn't seem necessary...if we're a live document, we should\n     * always have instrumentation on anyway.\n     * @param {boolean} enabled\n     */\n    LiveHTMLDocument.prototype.setInstrumentationEnabled = function (enabled) {\n        if (!this.editor) {\n            // TODO: error\n            return;\n        }\n        if (enabled && !this._instrumentationEnabled) {\n            // TODO: not clear why we do this here instead of waiting for the next time we want to\n            // generate the instrumented HTML. This won't work if the dom offsets are out of date.\n            HTMLInstrumentation.scanDocument(this.doc);\n            HTMLInstrumentation._markText(this.editor);\n        }\n\n        this._instrumentationEnabled = enabled;\n    };\n\n    /**\n     * Returns the instrumented version of the file.\n     * @return {{body: string}} instrumented doc\n     */\n    LiveHTMLDocument.prototype.getResponseData = function (enabled) {\n        var body;\n        if (this._instrumentationEnabled) {\n            body = HTMLInstrumentation.generateInstrumentedHTML(this.editor, this.protocol.getRemoteScript());\n        }\n\n        return {\n            body: body || this.doc.getText()\n        };\n    };\n\n    /**\n     * @override\n     * Closes the live document, terminating its connection to the browser.\n     */\n    LiveHTMLDocument.prototype.close = function () {\n        this.doc.off(\"change\", this._onChange);\n        this.parentClass.close.call(this);\n    };\n\n    /**\n     * @override\n     * Update the highlights in the browser based on the cursor position.\n     */\n    LiveHTMLDocument.prototype.updateHighlight = function () {\n        if (!this.editor || !this.isHighlightEnabled()) {\n            return;\n        }\n        var editor = this.editor,\n            ids = [];\n        _.each(this.editor.getSelections(), function (sel) {\n            var tagID = HTMLInstrumentation._getTagIDAtDocumentPos(\n                editor,\n                sel.reversed ? sel.end : sel.start\n            );\n            if (tagID !== -1) {\n                ids.push(tagID);\n            }\n        });\n\n        if (!ids.length) {\n            this.hideHighlight();\n        } else {\n            this.highlightDomElement(ids);\n        }\n    };\n\n    /**\n     * @private\n     * For the given editor change, compare the resulting browser DOM with the\n     * in-editor DOM. If there are any diffs, a warning is logged to the\n     * console along with each diff.\n     * @param {Object} change CodeMirror editor change data\n     */\n    LiveHTMLDocument.prototype._compareWithBrowser = function (change) {\n        // TODO: Not implemented.\n    };\n\n    /**\n     * @private\n     * Handles edits to the document. Determines what's changed in the source and sends DOM diffs to the browser.\n     * @param {$.Event} event\n     * @param {Document} doc\n     * @param {Object} change\n     */\n    LiveHTMLDocument.prototype._onChange = function (event, doc, change) {\n        // Make sure LiveHTML is turned on\n        if (!this._instrumentationEnabled) {\n            return;\n        }\n\n        // Apply DOM edits is async, so previous PerfUtils timer may still be\n        // running. PerfUtils does not support running multiple timers with same\n        // name, so do not start another timer in this case.\n        var perfTimerName   = \"LiveHTMLDocument applyDOMEdits\",\n            isNestedTimer   = PerfUtils.isActive(perfTimerName);\n        if (!isNestedTimer) {\n            PerfUtils.markStart(perfTimerName);\n        }\n\n        var self                = this,\n            result              = HTMLInstrumentation.getUnappliedEditList(this.editor, change),\n            applyEditsPromise;\n\n        if (result.edits) {\n            applyEditsPromise = this.protocol.evaluate(\"_LD.applyDOMEdits(\" + JSON.stringify(result.edits) + \")\");\n\n            applyEditsPromise.always(function () {\n                if (!isNestedTimer) {\n                    PerfUtils.addMeasurement(perfTimerName);\n                }\n            });\n        }\n\n        this.errors = result.errors || [];\n        this._updateErrorDisplay();\n\n        // Debug-only: compare in-memory vs. in-browser DOM\n        // edit this file or set a conditional breakpoint at the top of this function:\n        //     \"this._debug = true, false\"\n        if (this._debug) {\n            console.log(\"Edits applied to browser were:\");\n            console.log(JSON.stringify(result.edits, null, 2));\n            applyEditsPromise.done(function () {\n                self._compareWithBrowser(change);\n            });\n        }\n    };\n\n\n    /**\n     * @private\n     * Handles message DocumentRelated from the browser.\n     * @param {$.Event} event\n     * @param {Object} msg\n     */\n    LiveHTMLDocument.prototype._onRelated = function (event, msg) {\n        this._relatedDocuments = msg.related;\n        return;\n    };\n\n    /**\n     * @private\n     * Handles message Stylesheet.Added from the browser.\n     * @param {$.Event} event\n     * @param {Object} msg\n     */\n    LiveHTMLDocument.prototype._onStylesheetAdded = function (event, msg) {\n        this._relatedDocuments.stylesheets[msg.href] = true;\n        return;\n    };\n\n    /**\n     * @private\n     * Handles message Stylesheet.Removed from the browser.\n     * @param {$.Event} event\n     * @param {Object} msg\n     */\n    LiveHTMLDocument.prototype._onStylesheetRemoved = function (event, msg) {\n        delete (this._relatedDocuments.stylesheets[msg.href]);\n        return;\n    };\n\n    /**\n     * @private\n     * Handles message Script.Added from the browser.\n     * @param {$.Event} event\n     * @param {Object} msg\n     */\n    LiveHTMLDocument.prototype._onScriptAdded = function (event, msg) {\n        this._relatedDocuments.scripts[msg.src] = true;\n        return;\n    };\n\n     /**\n     * @private\n     * Handles message Script.Removed from the browser.\n     * @param {$.Event} event\n     * @param {Object} msg\n     */\n    LiveHTMLDocument.prototype._onScriptRemoved = function (event, msg) {\n        delete (this._relatedDocuments.scripts[msg.src]);\n        return;\n    };\n\n     /**\n     * For the given path, check if the document is related to the live HTML document.\n     * Related means that is an external Javascript or CSS file that is included as part of the DOM.\n     * @param {String} fullPath.\n     * @return {boolean} - is related or not.\n     */\n    LiveHTMLDocument.prototype.isRelated = function (fullPath) {\n        return (this._relatedDocuments.scripts[this.urlResolver(fullPath)] || this._relatedDocuments.stylesheets[this.urlResolver(fullPath)]);\n    };\n\n    LiveHTMLDocument.prototype.getRelated = function () {\n        return this._relatedDocuments;\n    };\n    // Export the class\n    module.exports = LiveHTMLDocument;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/language/HTMLInstrumentation.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: HTML Instrumentation*/\n\n/**\n * HTMLInstrumentation\n *\n * This module contains functions for \"instrumenting\" html code so that we can track\n * the relationship of source code to DOM nodes in the browser. This functionality is\n * used by both live highlighting and live HTML editing.\n *\n * During live HTML development, the HTML source code is parsed to identify tag boundaries.\n * Each tag is assigned an ID which is stored in markers that are inserted into the editor.\n * These IDs are also included in \"data-brackets-id\" attributes that are inserted in the\n * HTML code that's served to the browser via the Live Development server.\n *\n * The primary function for that functionality is generateInstrumentedHTML(). This does just\n * what it says - it will read the HTML content in the doc and generate instrumented code by\n * injecting \"data-brackets-id\" attributes. Additionally, it caches the parsed DOM for use\n * by future updates.\n *\n * As the user makes edits in the editor, we determine how the DOM structure should change\n * based on the edits to the source code; those edits are generated by getUnappliedEditList().\n * HTMLDocument (in LiveDevelopment) takes those edits and sends them to the browser (via\n * RemoteFunctions) so that the DOM structure in the live preview can be updated accordingly.\n *\n * There are also helper functions for returning the tagID associated with a specified\n * position in the document--this is used in live highlighting.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DocumentManager = require(\"document/DocumentManager\"),\n        HTMLDOMDiff     = require(\"language/HTMLDOMDiff\"),\n        HTMLSimpleDOM   = require(\"LiveDevelopment/MultiBrowserImpl/language/HTMLSimpleDOM\");\n\n    var allowIncremental = true;\n\n    // Hash of scanned documents. Key is the full path of the doc. Value is an object\n    // with two properties: timestamp and dom. Timestamp is the document timestamp,\n    // dom is the root node of a simple DOM tree.\n    var _cachedValues = {};\n\n    /**\n     * @private\n     * Removes the cached information (DOM, timestamp, etc.) used by HTMLInstrumentation\n     * for the given document.\n     * @param {$.Event} event (unused)\n     * @param {Document} document The document to clear from the cache.\n     */\n    function _removeDocFromCache(evt, document) {\n        if (_cachedValues.hasOwnProperty(document.file.fullPath)) {\n            delete _cachedValues[document.file.fullPath];\n            document.off(\".htmlInstrumentation\");\n        }\n    }\n\n    /**\n     * @private\n     * Checks if two CodeMirror-style {line, ch} positions are equal.\n     * @param {{line: number, ch: number}} pos1\n     * @param {{line: number, ch: number}} pos2\n     * @return {boolean} true if pos1 and pos2 are equal. Fails if either of them is falsy.\n     */\n    function _posEq(pos1, pos2) {\n        return pos1 && pos2 && pos1.line === pos2.line && pos1.ch === pos2.ch;\n    }\n\n    /**\n     * @private\n     * Filters the given marks to find the ones that correspond to instrumented tags,\n     * sorts them by their starting position, and looks up and/or stores their ranges\n     * in the given markCache.\n     * @param {Array} marks An array of mark objects returned by CodeMirror.\n     * @param {Object} markCache An object that maps tag IDs to {mark, range} objects.\n     *     If a mark in the marks array is already in the cache, we use the cached range info,\n     *     otherwise we look up its range in CodeMirror and store it in the cache.\n     * @return {Array.<{mark: Object, range: {line: number, ch: number}}>} The filtered and\n     *     sorted array of mark info objects (each of which contains the mark and its range,\n     *     so the range doesn't need to be looked up again).\n     */\n    function _getSortedTagMarks(marks, markCache) {\n        marks = marks.filter(function (mark) {\n            return !!mark.tagID;\n        }).map(function (mark) {\n            // All marks should exist since we just got them from CodeMirror.\n            if (!markCache[mark.tagID]) {\n                markCache[mark.tagID] = {mark: mark, range: mark.find()};\n            }\n            return markCache[mark.tagID];\n        });\n        marks.sort(function (mark1, mark2) {\n            return (mark1.range.from.line === mark2.range.from.line ?\n                    mark1.range.from.ch - mark2.range.from.ch :\n                    mark1.range.from.line - mark2.range.from.line);\n        });\n\n        return marks;\n    }\n\n    /**\n     * @private\n     * Finds the mark for the DOM node at the given position in the editor.\n     * @param {Editor} editor The editor containing the instrumented document.\n     * @param {{line: number, ch: number}} pos The position to find the DOM marker for.\n     * @param {boolean} preferParent If true, and the pos is at one or the other edge of the\n     *     innermost marked range, return the immediately enclosing mark instead.\n     * @param {Object=} markCache An optional cache to look up positions of existing\n     *     markers. (This avoids calling the find() operation on marks multiple times,\n     *     which is expensive.)\n     * @return {Object} The CodeMirror mark object that represents the DOM node at the\n     *     given position.\n     */\n    function _getMarkerAtDocumentPos(editor, pos, preferParent, markCache) {\n        var marks, match;\n\n        markCache = markCache || {};\n        marks = _getSortedTagMarks(editor._codeMirror.findMarksAt(pos), markCache);\n        if (!marks.length) {\n            return null;\n        }\n\n        // The mark with the latest start is the innermost one.\n        match = marks[marks.length - 1];\n        if (preferParent) {\n            // If the match is exactly at the edge of the range and preferParent is set,\n            // we want to pop upwards.\n            if (_posEq(match.range.from, pos) || _posEq(match.range.to, pos)) {\n                if (marks.length > 1) {\n                    match = marks[marks.length - 2];\n                } else {\n                    // We must be outside the root, so there's no containing tag.\n                    match = null;\n                }\n            }\n        }\n\n        return match.mark;\n    }\n\n    /**\n     * Get the instrumented tagID at the specified position. Returns -1 if\n     * there are no instrumented tags at the location.\n     * The _markText() function must be called before calling this function.\n     *\n     * NOTE: This function is \"private\" for now (has a leading underscore), since\n     * the API is likely to change in the future.\n     *\n     * @param {Editor} editor The editor to scan.\n     * @param {{line: number, ch: number}} pos The position to find the DOM marker for.\n     * @param {Object=} markCache An optional cache to look up positions of existing\n     *     markers. (This avoids calling the find() operation on marks multiple times,\n     *     which is expensive.)\n     * @return {number} tagID at the specified position, or -1 if there is no tag\n     */\n    function _getTagIDAtDocumentPos(editor, pos, markCache) {\n        var match = _getMarkerAtDocumentPos(editor, pos, false, markCache);\n\n        return (match) ? match.tagID : -1;\n    }\n\n    /**\n     * Recursively walks the SimpleDOM starting at node and marking\n     * all tags in the CodeMirror instance. The more useful interface\n     * is the _markTextFromDOM function which clears existing marks\n     * before calling this function to create new ones.\n     *\n     * @param {CodeMirror} cm CodeMirror instance in which to mark tags\n     * @param {Object} node SimpleDOM node to use as the root for marking\n     */\n    function _markTags(cm, node) {\n        node.children.forEach(function (childNode) {\n            if (childNode.isElement()) {\n                _markTags(cm, childNode);\n            }\n        });\n        var mark = cm.markText(node.startPos, node.endPos);\n        mark.tagID = node.tagID;\n    }\n\n    /**\n     * Clears the marks from the document and creates new ones.\n     *\n     * @param {Editor} editor Editor object holding this document\n     * @param {Object} dom SimpleDOM root object that contains the parsed structure\n     */\n    function _markTextFromDOM(editor, dom) {\n        var cm = editor._codeMirror;\n\n        // Remove existing marks\n        var marks = cm.getAllMarks();\n        cm.operation(function () {\n            marks.forEach(function (mark) {\n                if (mark.hasOwnProperty(\"tagID\")) {\n                    mark.clear();\n                }\n            });\n        });\n\n        // Mark\n        _markTags(cm, dom);\n    }\n\n    /**\n     * @constructor\n     * Subclass of HTMLSimpleDOM.Builder that builds an updated DOM after changes have been made,\n     * and maps nodes from the new DOM to the old DOM by tag ID. For non-structural edits, avoids reparsing\n     * the whole editor. Also updates marks in the editor based on the new DOM state.\n     *\n     * @param {Object} previousDOM The root of the HTMLSimpleDOM tree representing a previous state of the DOM.\n     * @param {Editor} editor The editor containing the instrumented HTML.\n     * @param {Array=} changeList An optional array of CodeMirror change records representing the\n     *     edits the user made in the editor since previousDOM was built. If provided, and the\n     *     edits are not structural, DOMUpdater will do a fast incremental reparse. If not provided,\n     *     or if one of the edits changes the DOM structure, DOMUpdater will reparse the whole DOM.\n     */\n    function DOMUpdater(previousDOM, editor, changeList) {\n        var text, startOffset = 0, startOffsetPos;\n\n        this.isIncremental = false;\n\n        function isDangerousEdit(text) {\n            // We don't consider & dangerous since entities only affect text content, not\n            // overall DOM structure.\n            return (/[<>\\/=\\\"\\']/).test(text);\n        }\n\n        // If there's more than one change, be conservative and assume we have to do a full reparse.\n        if (changeList && changeList.length === 1) {\n            // If the inserted or removed text doesn't have any characters that could change the\n            // structure of the DOM (e.g. by adding or removing a tag boundary), then we can do\n            // an incremental reparse of just the parent tag containing the edit. This should just\n            // be the marked range that contains the beginning of the edit range, since that position\n            // isn't changed by the edit.\n            var change = changeList[0];\n            if (!isDangerousEdit(change.text) && !isDangerousEdit(change.removed)) {\n                // If the edit is right at the beginning or end of a tag, we want to be conservative\n                // and use the parent as the edit range.\n                var startMark = _getMarkerAtDocumentPos(editor, change.from, true);\n                if (startMark) {\n                    var range = startMark.find();\n                    if (range) {\n                        text = editor._codeMirror.getRange(range.from, range.to);\n                        this.changedTagID = startMark.tagID;\n                        startOffsetPos = range.from;\n                        startOffset = editor._codeMirror.indexFromPos(startOffsetPos);\n                        this.isIncremental = true;\n                    }\n                }\n            }\n        }\n\n        if (!this.changedTagID) {\n            // We weren't able to incrementally update, so just rebuild and diff everything.\n            text = editor.document.getText();\n        }\n\n        HTMLSimpleDOM.Builder.call(this, text, startOffset, startOffsetPos);\n        this.editor = editor;\n        this.cm = editor._codeMirror;\n        this.previousDOM = previousDOM;\n    }\n\n    DOMUpdater.prototype = Object.create(HTMLSimpleDOM.Builder.prototype);\n\n    /**\n     * @private\n     * Returns true if the given node has an ancestor whose tagID is the given ID.\n     * @param {Object} node A node from an HTMLSimpleDOM structure.\n     * @param {number} id The ID of the tag to check for.\n     * @return {boolean} true if the node has an ancestor with that ID.\n     */\n    function _hasAncestorWithID(node, id) {\n        var ancestor = node.parent;\n        while (ancestor && ancestor.tagID !== id) {\n            ancestor = ancestor.parent;\n        }\n        return !!ancestor;\n    }\n\n    /**\n     * Overrides the `getID` method to return the tag ID from the document. If a viable tag\n     * ID cannot be found in the document marks, then a new ID is returned. This will also\n     * assign a new ID if the tag changed between the previous and current versions of this\n     * node.\n     *\n     * @param {Object} newTag tag object for the current element\n     * @return {int} best ID\n     */\n    DOMUpdater.prototype.getID = function (newTag, markCache) {\n        // Get the mark at the start of the tagname (not before the beginning of the tag, because that's\n        // actually inside the parent).\n        var currentTagID = _getTagIDAtDocumentPos(this.editor, HTMLSimpleDOM._offsetPos(newTag.startPos, 1), markCache);\n\n        // If the new tag is in an unmarked range, or the marked range actually corresponds to an\n        // ancestor tag, then this must be a newly inserted tag, so give it a new tag ID.\n        if (currentTagID === -1 || _hasAncestorWithID(newTag, currentTagID)) {\n            currentTagID = this.getNewID();\n        } else {\n            // If the tag has changed between the previous DOM and the new one, we assign a new ID\n            // so that the old tag will be deleted and the new one inserted.\n            var oldNode = this.previousDOM.nodeMap[currentTagID];\n            if (!oldNode || oldNode.tag !== newTag.tag) {\n                currentTagID = this.getNewID();\n            }\n        }\n        return currentTagID;\n    };\n\n    /**\n     * Updates the CodeMirror marks in the editor to reflect the new bounds of nodes in\n     * the given nodeMap.\n     * @param {Object} nodeMap The node map from the new DOM.\n     * @param {Object} markCache The cache of existing mark ranges built during the latest parse.\n     */\n    DOMUpdater.prototype._updateMarkedRanges = function (nodeMap, markCache) {\n        // FUTURE: this is somewhat inefficient (getting all the marks involves passing linearly through\n        // the document once), but it doesn't seem to be a hotspot right now.\n        var updateIDs = Object.keys(nodeMap),\n            cm = this.cm,\n            marks = cm.getAllMarks();\n\n        cm.operation(function () {\n            marks.forEach(function (mark) {\n                if (mark.hasOwnProperty(\"tagID\") && nodeMap[mark.tagID]) {\n                    var node = nodeMap[mark.tagID],\n                        markInfo = markCache[mark.tagID];\n                    // If the mark's bounds already match, avoid destroying and recreating the mark,\n                    // since that incurs some overhead.\n                    if (!(markInfo && _posEq(markInfo.range.from, node.startPos) && _posEq(markInfo.range.to, node.endPos))) {\n                        mark.clear();\n                        mark = cm.markText(node.startPos, node.endPos);\n                        mark.tagID = node.tagID;\n                    }\n                    updateIDs.splice(updateIDs.indexOf(String(node.tagID)), 1);\n                }\n            });\n\n            // Any remaining updateIDs are new.\n            updateIDs.forEach(function (id) {\n                var node = nodeMap[id], mark;\n                if (node.isElement()) {\n                    mark = cm.markText(node.startPos, node.endPos);\n                    mark.tagID = Number(id);\n                }\n            });\n        });\n    };\n\n    /**\n     * @private\n     * Creates a map from tagIDs to nodes in the given HTMLSimpleDOM subtree and\n     * stores it on the root.\n     * @param {Object} root The root of an HTMLSimpleDOM tree.\n     */\n    DOMUpdater.prototype._buildNodeMap = function (root) {\n        var nodeMap = {};\n\n        function walk(node) {\n            if (node.tagID) {\n                nodeMap[node.tagID] = node;\n            }\n            if (node.isElement()) {\n                node.children.forEach(walk);\n            }\n        }\n\n        walk(root);\n        root.nodeMap = nodeMap;\n    };\n\n    /**\n     * @private\n     * Removes all nodes deleted between the oldSubtree and the newSubtree from the given nodeMap,\n     * and clears marks associated with those nodes.\n     * @param {Object} nodeMap The nodeMap to update to remove deleted items.\n     * @param {Object} oldSubtreeMap The nodeMap for the original subtree (which should be a subset of the\n     *     first nodeMap).\n     * @param {Object} newSubtreeMap The nodeMap for the new subtree.\n     */\n    DOMUpdater.prototype._handleDeletions = function (nodeMap, oldSubtreeMap, newSubtreeMap) {\n        var deletedIDs = [];\n        Object.keys(oldSubtreeMap).forEach(function (key) {\n            if (!newSubtreeMap.hasOwnProperty(key)) {\n                deletedIDs.push(key);\n                delete nodeMap[key];\n            }\n        });\n\n        if (deletedIDs.length) {\n            // FUTURE: would be better to cache the mark for each node. Also, could\n            // conceivably combine this with _updateMarkedRanges().\n            var marks = this.cm.getAllMarks();\n            marks.forEach(function (mark) {\n                if (mark.hasOwnProperty(\"tagID\") && deletedIDs.indexOf(mark.tagID) !== -1) {\n                    mark.clear();\n                }\n            });\n        }\n    };\n\n    /**\n     * Reparses the document (or a portion of it if we can do it incrementally).\n     * Note that in an incremental update, the old DOM is actually mutated (the new\n     * subtree is swapped in for the old subtree).\n     * @return {?{newDOM: Object, oldSubtree: Object, newSubtree: Object}} newDOM is\n     *      the full new DOM. For a full update, oldSubtree is the full old DOM\n     *      and newSubtree is the same as newDOM; for an incremental update,\n     *      oldSubtree is the portion of the old tree that was reparsed,\n     *      newSubtree is the updated version, and newDOM is actually the same\n     *      as the original DOM (with newSubtree swapped in for oldSubtree).\n     *      If the document can't be parsed due to invalid HTML, returns null.\n     */\n    DOMUpdater.prototype.update = function () {\n        var markCache = {},\n            newSubtree = this.build(true, markCache),\n            result = {\n                // default result if we didn't identify a changed portion\n                newDOM: newSubtree,\n                oldSubtree: this.previousDOM,\n                newSubtree: newSubtree\n            };\n\n        if (!newSubtree) {\n            return null;\n        }\n\n        if (this.changedTagID) {\n            // Find the old subtree that's going to get swapped out.\n            var oldSubtree = this.previousDOM.nodeMap[this.changedTagID],\n                parent = oldSubtree.parent;\n\n            // If we didn't have a parent, then the whole tree changed anyway, so\n            // we'll just return the default result.\n            if (parent) {\n                var childIndex = parent.children.indexOf(oldSubtree);\n                if (childIndex === -1) {\n                    // This should never happen...\n                    console.error(\"DOMUpdater.update(): couldn't locate old subtree in tree\");\n                } else {\n                    // Swap the new subtree in place of the old subtree.\n                    oldSubtree.parent = null;\n                    newSubtree.parent = parent;\n                    parent.children[childIndex] = newSubtree;\n\n                    // Overwrite any node mappings in the parent DOM with the\n                    // mappings for the new subtree. We keep the nodeMap around\n                    // on the new subtree so that the differ can use it later.\n                    $.extend(this.previousDOM.nodeMap, newSubtree.nodeMap);\n\n                    // Update marked ranges for all items in the new subtree.\n                    this._updateMarkedRanges(newSubtree.nodeMap, markCache);\n\n                    // Build a local nodeMap for the old subtree so the differ can\n                    // use it.\n                    this._buildNodeMap(oldSubtree);\n\n                    // Clean up the info for any deleted nodes that are no longer in\n                    // the new tree.\n                    this._handleDeletions(this.previousDOM.nodeMap, oldSubtree.nodeMap, newSubtree.nodeMap);\n\n                    // Update the signatures for all parents of the new subtree.\n                    var curParent = parent;\n                    while (curParent) {\n                        curParent.update();\n                        curParent = curParent.parent;\n                    }\n\n                    result.newDOM = this.previousDOM;\n                    result.oldSubtree = oldSubtree;\n                }\n            }\n        } else {\n            _markTextFromDOM(this.editor, result.newDOM);\n        }\n\n        return result;\n    };\n\n    /**\n     * @private\n     * Builds a new DOM for the current state of the editor, diffs it against the\n     * previous DOM, and generates a DOM edit list that can be used to replay the\n     * diffs in the browser.\n     * @param {Object} previousDOM The HTMLSimpleDOM corresponding to the previous state of the editor.\n     *     Note that in the case of an incremental edit, this will be mutated to create the new DOM\n     *     (by swapping out the subtree corresponding to the changed portion).\n     * @param {Editor} editor The editor containing the instrumented HTML.\n     * @param {Array=} changeList If specified, a CodeMirror changelist reflecting all the\n     *     text changes in the editor since previousDOM was built. If specified, we will\n     *     attempt to do an incremental update (although we might fall back to a full update\n     *     in various cases). If not specified, we will always do a full update.\n     * @return {{dom: Object, edits: Array}} The new DOM representing the current state of the\n     *     editor, and an array of edits that can be applied to update the browser (see\n     *     HTMLDOMDiff for more information on the edit format).\n     */\n    function _updateDOM(previousDOM, editor, changeList) {\n        if (!allowIncremental) {\n            changeList = undefined;\n        }\n        var updater = new DOMUpdater(previousDOM, editor, changeList);\n        var result = updater.update();\n        if (!result) {\n            return { errors: updater.errors };\n        }\n\n        var edits = HTMLDOMDiff.domdiff(result.oldSubtree, result.newSubtree);\n\n        // We're done with the nodeMap that was added to the subtree by the updater.\n        if (result.newSubtree !== result.newDOM) {\n            delete result.newSubtree.nodeMap;\n        }\n\n        return {\n            dom: result.newDOM,\n            edits: edits,\n            _wasIncremental: updater.isIncremental // for unit tests only\n        };\n    }\n\n    /**\n     * Calculates the DOM edits that are needed to update the browser from the state the\n     * editor was in the last time that scanDocument(), getInstrumentedHTML(), or\n     * getUnappliedEditList() was called (whichever is most recent). Caches this state so\n     * it can be used as the base state for the next getUnappliedEditList().\n     *\n     * For simple text edits, this update is done quickly and incrementally. For structural\n     * edits (edits that change the DOM structure or add/remove attributes), the update\n     * requires a full reparse.\n     *\n     * If the document currently contains invalid HTML, no edits will be generated until\n     * getUnappliedEditList() is called when the document is valid, at which point the edits\n     * will reflect all the changes needed to catch the browser up with all the edits\n     * made while the document was invalid.\n     *\n     * @param {Editor} editor The editor containing the instrumented HTML\n     * @param {Array} changeList A CodeMirror change list describing the text changes made\n     *     in the editor since the last update. If specified, we will attempt to do an\n     *     incremental update.\n     * @return {Array} edits A list of edits to apply in the browser. See HTMLDOMDiff for\n     *     more information on the format of these edits.\n     */\n    function getUnappliedEditList(editor, changeList) {\n        var cachedValue = _cachedValues[editor.document.file.fullPath];\n\n        // We might not have a previous DOM if the document was empty before this edit.\n        if (!cachedValue || !cachedValue.dom || _cachedValues[editor.document.file.fullPath].invalid) {\n            // We were in an invalid state, so do a full rebuild.\n            changeList = null;\n        }\n\n        var result = _updateDOM(cachedValue && cachedValue.dom, editor, changeList);\n\n        if (!result.errors) {\n            _cachedValues[editor.document.file.fullPath] = {\n                timestamp: editor.document.diskTimestamp,\n                dom: result.dom,\n                dirty: false\n            };\n            // Since this was an incremental update, we can't rely on the node start/end offsets\n            // in the dom (because nodes after the updated portion didn't have their offsets\n            // updated); the marks in the editor are more accurate.\n            // TODO: should we consider ripping through the dom and fixing up other offsets?\n            result.dom.fullBuild = false;\n            return { edits: result.edits };\n        } else {\n            if (cachedValue) {\n                cachedValue.invalid = true;\n            }\n            return { errors: result.errors };\n        }\n    }\n\n    /**\n     * @private\n     * Add SimpleDOMBuilder metadata to browser DOM tree JSON representation\n     * @param {Object} root\n     */\n    function _processBrowserSimpleDOM(browserRoot, editorRootTagID) {\n        var nodeMap         = {},\n            root;\n\n        function _processElement(elem) {\n            elem.tagID = elem.attributes[\"data-brackets-id\"];\n\n            // remove data-brackets-id attribute for diff\n            delete elem.attributes[\"data-brackets-id\"];\n\n            elem.children.forEach(function (child) {\n                // set parent\n                child.parent = elem;\n\n                if (child.isElement()) {\n                    _processElement(child);\n                } else if (child.isText()) {\n                    child.update();\n                    child.tagID = HTMLSimpleDOM.getTextNodeID(child);\n\n                    nodeMap[child.tagID] = child;\n                }\n            });\n\n            elem.update();\n\n            nodeMap[elem.tagID] = elem;\n\n            // Choose the root element based on the root tag in the editor.\n            // The browser may insert html, head and body elements if missing.\n            if (elem.tagID === editorRootTagID) {\n                root = elem;\n            }\n        }\n\n        _processElement(browserRoot);\n\n        root = root || browserRoot;\n        root.nodeMap = nodeMap;\n\n        return root;\n    }\n\n    /**\n     * @private\n     * Diff the browser DOM with the in-editor DOM\n     * @param {Editor} editor\n     * @param {Object} browserSimpleDOM\n     */\n    function _getBrowserDiff(editor, browserSimpleDOM) {\n        var cachedValue = _cachedValues[editor.document.file.fullPath],\n            editorRoot  = cachedValue.dom,\n            browserRoot;\n\n        browserRoot = _processBrowserSimpleDOM(browserSimpleDOM, editorRoot.tagID);\n\n        return {\n            diff    : HTMLDOMDiff.domdiff(editorRoot, browserRoot),\n            browser : browserRoot,\n            editor  : editorRoot\n        };\n    }\n\n    DocumentManager.on(\"beforeDocumentDelete\", _removeDocFromCache);\n\n    /**\n     * Parses the document, returning an HTMLSimpleDOM structure and caching it as the\n     * initial state of the document. Will return a cached copy of the DOM if the\n     * document hasn't changed since the last time scanDocument was called.\n     *\n     * This is called by generateInstrumentedHTML(), but it can be useful to call it\n     * ahead of time so the DOM is cached and doesn't need to be rescanned when the\n     * instrumented HTML is requested by the browser.\n     *\n     * @param {Document} doc The doc to scan.\n     * @return {Object} Root DOM node of the document.\n     */\n    function scanDocument(doc) {\n        if (!_cachedValues.hasOwnProperty(doc.file.fullPath)) {\n            // TODO: this doesn't seem to be correct any more. The DOM should never be \"dirty\" (i.e., out of sync\n            // with the editor) unless the doc is invalid.\n//            $(doc).on(\"change.htmlInstrumentation\", function () {\n//                if (_cachedValues[doc.file.fullPath]) {\n//                    _cachedValues[doc.file.fullPath].dirty = true;\n//                }\n//            });\n\n            // Assign to cache, but don't set a value yet\n            _cachedValues[doc.file.fullPath] = null;\n        }\n\n        var cachedValue = _cachedValues[doc.file.fullPath];\n        // TODO: No longer look at doc or cached value \"dirty\" settings, because even if the doc is dirty, the dom\n        // should generally be up to date unless the HTML is invalid. (However, the node offsets will be dirty of\n        // the dom was incrementally updated - we should note that somewhere.)\n        if (cachedValue && !cachedValue.invalid && cachedValue.timestamp === doc.diskTimestamp) {\n            return cachedValue.dom;\n        }\n\n        var text = doc.getText(),\n            dom = HTMLSimpleDOM.build(text);\n\n        if (dom) {\n            // Cache results\n            _cachedValues[doc.file.fullPath] = {\n                timestamp: doc.diskTimestamp,\n                dom: dom,\n                dirty: false\n            };\n            // Note that this was a full build, so we know that we can trust the node start/end offsets.\n            dom.fullBuild = true;\n        }\n\n        return dom;\n    }\n\n    /**\n     * Generate instrumented HTML for the specified editor's document, and mark the associated tag\n     * ranges in the editor. Each tag has a \"data-brackets-id\" attribute with a unique ID for its\n     * value. For example, \"<div>\" becomes something like \"<div data-brackets-id='45'>\". The attribute\n     * value is just a number that is guaranteed to be unique.\n     *\n     * Also stores marks in the given editor that correspond to the tag ranges. These marks are used\n     * to track the DOM structure for in-browser highlighting and live HTML updating.\n     *\n     * This only needs to be done once on load of a document. As the document is edited in memory,\n     * the instrumentation is kept up to date via the diffs and edits that are generated on change\n     * events. Call this again only if you want to do a full re-sync of the editor's DOM state.\n     *\n     * @param {Editor} editor The editor whose document we're instrumenting, and which we should\n     *     mark ranges in.\n     * @return {string} instrumented html content\n     */\n    function generateInstrumentedHTML(editor, remoteScript) {\n        var doc = editor.document,\n            dom = scanDocument(doc),\n            orig = doc.getText(),\n            gen = \"\",\n            lastIndex = 0,\n            remoteScriptInserted = false,\n            markCache;\n\n        if (!dom) {\n            return null;\n        }\n\n        // Ensure that the marks in the editor are up to date with respect to the given DOM.\n        // (But only do this if the dom we got back from scanDocument() was a full rebuild. Otherwise,\n        // rely on the marks in the editor.)\n        if (dom.fullBuild) {\n            _markTextFromDOM(editor, dom);\n        } else {\n            markCache = {};\n            editor._codeMirror.getAllMarks().forEach(function (mark) {\n                if (mark.tagID) {\n                    markCache[mark.tagID] = { mark: mark, range: mark.find() };\n                }\n            });\n        }\n\n        // Walk through the dom nodes and insert the 'data-brackets-id' attribute at the\n        // end of the open tag\n        function walk(node) {\n            if (node.tag) {\n                var attrText = \" data-brackets-id='\" + node.tagID + \"'\";\n\n                // If the dom was fully rebuilt, use its offsets. Otherwise, use the marks in the\n                // associated editor, since they'll be more up to date.\n                var startOffset;\n                if (dom.fullBuild) {\n                    startOffset = node.start;\n                } else {\n                    var mark = markCache[node.tagID];\n                    if (mark) {\n                        startOffset = editor._codeMirror.indexFromPos(mark.range.from);\n                    } else {\n                        console.warn(\"generateInstrumentedHTML(): couldn't find existing mark for tagID \" + node.tagID);\n                        startOffset = node.start;\n                    }\n                }\n\n                // Insert the attribute as the first attribute in the tag.\n                var insertIndex = startOffset + node.tag.length + 1;\n                gen += orig.substr(lastIndex, insertIndex - lastIndex) + attrText;\n                lastIndex = insertIndex;\n\n                // If we have a script to inject and this is the head tag, inject it immediately\n                // after the open tag.\n                if (remoteScript && !remoteScriptInserted && node.tag === \"head\") {\n                    insertIndex = node.openEnd;\n                    gen += orig.substr(lastIndex, insertIndex - lastIndex) + remoteScript;\n                    lastIndex = insertIndex;\n                    remoteScriptInserted = true;\n                }\n            }\n\n            if (node.isElement()) {\n                node.children.forEach(walk);\n            }\n        }\n\n        walk(dom);\n        gen += orig.substr(lastIndex);\n\n        if (remoteScript && !remoteScriptInserted) {\n            // if the remote script couldn't be injected before (e.g. due to missing \"head\" tag),\n            // append it at the end\n            gen += remoteScript;\n        }\n\n        return gen;\n    }\n\n    /**\n     * Mark the text for the specified editor. Either scanDocument() or\n     * generateInstrumentedHTML() must be called before this function\n     * is called.\n     *\n     * NOTE: This function is \"private\" for now (has a leading underscore), since\n     * the API is likely to change in the future.\n     *\n     * @param {Editor} editor The editor whose text should be marked.\n     * @return none\n     */\n    function _markText(editor) {\n        var cache = _cachedValues[editor.document.file.fullPath],\n            dom = cache && cache.dom;\n\n        if (!dom) {\n            console.error(\"Couldn't find the dom for \" + editor.document.file.fullPath);\n            return;\n        } else if (!dom.fullBuild) {\n            console.error(\"Tried to mark text from a stale DOM for \" + editor.document.file.fullPath);\n            return;\n        }\n\n        _markTextFromDOM(editor, dom);\n    }\n\n    /**\n     * @private\n     * Clear the DOM cache. For unit testing only.\n     */\n    function _resetCache() {\n        _cachedValues = {};\n    }\n\n    // private methods\n    exports._markText                   = _markText;\n    exports._getMarkerAtDocumentPos     = _getMarkerAtDocumentPos;\n    exports._getTagIDAtDocumentPos      = _getTagIDAtDocumentPos;\n    exports._markTextFromDOM            = _markTextFromDOM;\n    exports._updateDOM                  = _updateDOM;\n    exports._allowIncremental           = allowIncremental;\n    exports._getBrowserDiff             = _getBrowserDiff;\n    exports._resetCache                 = _resetCache;\n\n    // public API\n    exports.scanDocument                = scanDocument;\n    exports.generateInstrumentedHTML    = generateInstrumentedHTML;\n    exports.getUnappliedEditList        = getUnappliedEditList;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/language/HTMLSimpleDOM.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: HTML Instrumentation*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Tokenizer       = require(\"language/HTMLTokenizer\").Tokenizer,\n        MurmurHash3     = require(\"thirdparty/murmurhash3_gc\"),\n        PerfUtils       = require(\"utils/PerfUtils\");\n\n    var seed = Math.floor(Math.random() * 65535);\n\n    var tagID = 1;\n\n    /**\n     * A list of tags whose start causes any of a given set of immediate parent\n     * tags to close. This mostly comes from the HTML5 spec section on omitted close tags:\n     * http://www.w3.org/html/wg/drafts/html/master/syntax.html#optional-tags\n     * This doesn't handle general content model violations.\n     */\n    var openImpliesClose = {\n        li      : { li: true },\n        dt      : { dd: true, dt: true },\n        dd      : { dd: true, dt: true },\n        address : { p: true },\n        article : { p: true },\n        aside   : { p: true },\n        blockquote : { p: true },\n        dir     : { p: true },\n        div     : { p: true },\n        dl      : { p: true },\n        fieldset: { p: true },\n        footer  : { p: true },\n        form    : { p: true },\n        h1      : { p: true },\n        h2      : { p: true },\n        h3      : { p: true },\n        h4      : { p: true },\n        h5      : { p: true },\n        h6      : { p: true },\n        header  : { p: true },\n        hgroup  : { p: true },\n        hr      : { p: true },\n        main    : { p: true },\n        menu    : { p: true },\n        nav     : { p: true },\n        ol      : { p: true },\n        p       : { p: true },\n        pre     : { p: true },\n        section : { p: true },\n        table   : { p: true },\n        ul      : { p: true },\n        rt      : { rp: true, rt: true },\n        rp      : { rp: true, rt: true },\n        optgroup: { optgroup: true, option: true },\n        option  : { option: true },\n        tbody   : { thead: true, tbody: true, tfoot: true },\n        tfoot   : { tbody: true },\n        tr      : { tr: true, th: true, td: true },\n        th      : { th: true, td: true },\n        td      : { thead: true, th: true, td: true },\n        body    : { head: true, link: true, script: true }\n    };\n\n    /**\n     * A list of tags that are self-closing (do not contain other elements).\n     * Mostly taken from http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements\n     */\n    var voidElements = {\n        area: true,\n        base: true,\n        basefont: true,\n        br: true,\n        col: true,\n        command: true,\n        embed: true,\n        frame: true,\n        hr: true,\n        img: true,\n        input: true,\n        isindex: true,\n        keygen: true,\n        link: true,\n        menuitem: true,\n        meta: true,\n        param: true,\n        source: true,\n        track: true,\n        wbr: true\n    };\n\n    /**\n     * @constructor\n     *\n     * A SimpleNode represents one node in a SimpleDOM tree. Each node can have\n     * any set of properties on it, though there are a couple of assumptions made.\n     * Elements will have `children` and `attributes` properties. Text nodes will have a `content`\n     * property. All Elements will have a `tagID` and text nodes *can* have one.\n     *\n     * @param {Object} properties the properties provided will be set on the new object.\n     */\n    function SimpleNode(properties) {\n        $.extend(this, properties);\n    }\n\n    SimpleNode.prototype = {\n\n        /**\n         * Updates signatures used to optimize the number of comparisons done during\n         * diffing. This is important to call if you change:\n         *\n         * * children\n         * * child node attributes\n         * * text content of a text node\n         * * child node text\n         */\n        update: function () {\n            if (this.isElement()) {\n                var i,\n                    subtreeHashes = \"\",\n                    childHashes = \"\",\n                    child;\n                for (i = 0; i < this.children.length; i++) {\n                    child = this.children[i];\n                    if (child.isElement()) {\n                        childHashes += String(child.tagID);\n                        subtreeHashes += String(child.tagID) + child.attributeSignature + child.subtreeSignature;\n                    } else {\n                        childHashes += child.textSignature;\n                        subtreeHashes += child.textSignature;\n                    }\n                }\n                this.childSignature = MurmurHash3.hashString(childHashes, childHashes.length, seed);\n                this.subtreeSignature = MurmurHash3.hashString(subtreeHashes, subtreeHashes.length, seed);\n            } else {\n                this.textSignature = MurmurHash3.hashString(this.content, this.content.length, seed);\n            }\n        },\n\n        /**\n         * Updates the signature of this node's attributes. Call this after making attribute changes.\n         */\n        updateAttributeSignature: function () {\n            var attributeString = JSON.stringify(this.attributes);\n            this.attributeSignature = MurmurHash3.hashString(attributeString, attributeString.length, seed);\n        },\n\n        /**\n         * Is this node an element node?\n         *\n         * @return {bool} true if it is an element\n         */\n        isElement: function () {\n            return !!this.children;\n        },\n\n        /**\n         * Is this node a text node?\n         *\n         * @return {bool} true if it is text\n         */\n        isText: function () {\n            return !this.children;\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Generates a synthetic ID for text nodes. These IDs are only used\n     * for convenience when reading a SimpleDOM that is dumped to the console.\n     *\n     * @param {Object} textNode new node for which we are generating an ID\n     * @return {string} ID for the node\n     */\n    function getTextNodeID(textNode) {\n        var childIndex = textNode.parent.children.indexOf(textNode);\n        if (childIndex === 0) {\n            return textNode.parent.tagID + \".0\";\n        }\n        return textNode.parent.children[childIndex - 1].tagID + \"t\";\n    }\n\n    /**\n     * @private\n     *\n     * Adds two {line, ch}-style positions, returning a new pos.\n     */\n    function _addPos(pos1, pos2) {\n        return {line: pos1.line + pos2.line, ch: (pos2.line === 0 ? pos1.ch + pos2.ch : pos2.ch)};\n    }\n\n    /**\n     * @private\n     *\n     * Offsets the character offset of the given {line, ch} pos by the given amount and returns a new\n     * pos. Not for general purpose use as it does not account for line boundaries.\n     */\n    function _offsetPos(pos, offset) {\n        return {line: pos.line, ch: pos.ch + offset};\n    }\n\n    /**\n     * @constructor\n     *\n     * A Builder creates a SimpleDOM tree of SimpleNode objects representing the\n     * \"important\" contents of an HTML document. It does not include things like comments.\n     * The nodes include information about their position in the text provided.\n     *\n     * @param {string} text The text to parse\n     * @param {?int} startOffset starting offset in the text\n     * @param {?{line: int, ch: int}} startOffsetPos line/ch position in the text\n     */\n    function Builder(text, startOffset, startOffsetPos) {\n        this.stack = [];\n        this.text = text;\n        this.t = new Tokenizer(text);\n        this.currentTag = null;\n        this.startOffset = startOffset || 0;\n        this.startOffsetPos = startOffsetPos || {line: 0, ch: 0};\n    }\n\n    Builder.prototype._logError = function (token) {\n        var error       = { token: token },\n            startPos    = token ? (token.startPos || token.endPos) : this.startOffsetPos,\n            endPos      = token ? token.endPos : this.startOffsetPos;\n\n        error.startPos = _addPos(this.startOffsetPos, startPos);\n        error.endPos = _addPos(this.startOffsetPos, endPos);\n\n        if (!this.errors) {\n            this.errors = [];\n        }\n\n        this.errors.push(error);\n    };\n\n    /**\n     * Builds the SimpleDOM.\n     *\n     * @param {?bool} strict if errors are detected, halt and return null\n     * @param {?Object} markCache a cache that can be used in ID generation (is passed to `getID`)\n     * @return {SimpleNode} root of tree or null if parsing failed\n     */\n    Builder.prototype.build = function (strict, markCache) {\n        var self = this;\n        var token, lastClosedTag, lastTextNode;\n        var stack = this.stack;\n        var attributeName = null;\n        var nodeMap = {};\n\n        markCache = markCache || {};\n\n        // Start timers for building full and partial DOMs.\n        // Appropriate timer is used, and the other is discarded.\n        var timerBuildFull = \"HTMLInstr. Build DOM Full\";\n        var timerBuildPart = \"HTMLInstr. Build DOM Partial\";\n        PerfUtils.markStart([timerBuildFull, timerBuildPart]);\n\n        function closeTag(endIndex, endPos) {\n            lastClosedTag = stack[stack.length - 1];\n            stack.pop();\n            lastClosedTag.update();\n\n            lastClosedTag.end = self.startOffset + endIndex;\n            lastClosedTag.endPos = _addPos(self.startOffsetPos, endPos);\n        }\n\n        while ((token = this.t.nextToken()) !== null) {\n            // lastTextNode is used to glue text nodes together\n            // If the last node we saw was text but this one is not, then we're done gluing.\n            // If this node is a comment, we might still encounter more text.\n            if (token.type !== \"text\" && token.type !== \"comment\" && lastTextNode) {\n                lastTextNode = null;\n            }\n\n            if (token.type === \"error\") {\n                PerfUtils.finalizeMeasurement(timerBuildFull);  // discard\n                PerfUtils.addMeasurement(timerBuildPart);       // use\n                this._logError(token);\n                return null;\n            } else if (token.type === \"opentagname\") {\n                var newTagName = token.contents.toLowerCase(),\n                    newTag;\n\n                if (openImpliesClose.hasOwnProperty(newTagName)) {\n                    var closable = openImpliesClose[newTagName];\n                    while (stack.length > 0 && closable.hasOwnProperty(stack[stack.length - 1].tag)) {\n                        // Close the previous tag at the start of this tag.\n                        // Adjust backwards for the < before the tag name.\n                        closeTag(token.start - 1, _offsetPos(token.startPos, -1));\n                    }\n                }\n\n                newTag = new SimpleNode({\n                    tag: token.contents.toLowerCase(),\n                    children: [],\n                    attributes: {},\n                    parent: (stack.length ? stack[stack.length - 1] : null),\n                    start: this.startOffset + token.start - 1,\n                    startPos: _addPos(this.startOffsetPos, _offsetPos(token.startPos, -1)) // ok because we know the previous char was a \"<\"\n                });\n                newTag.tagID = this.getID(newTag, markCache);\n\n                // During undo in particular, it's possible that tag IDs may be reused and\n                // the marks in the document may be misleading. If a tag ID has been reused,\n                // we apply a new tag ID to ensure that our edits come out correctly.\n                if (nodeMap[newTag.tagID]) {\n                    newTag.tagID = this.getNewID();\n                }\n\n                nodeMap[newTag.tagID] = newTag;\n                if (newTag.parent) {\n                    newTag.parent.children.push(newTag);\n                }\n                this.currentTag = newTag;\n\n                if (voidElements.hasOwnProperty(newTag.tag)) {\n                    // This is a self-closing element.\n                    newTag.update();\n                } else {\n                    stack.push(newTag);\n                }\n            } else if (token.type === \"opentagend\" || token.type === \"selfclosingtag\") {\n                // TODO: disallow <p/>?\n                if (this.currentTag) {\n                    if (token.type === \"selfclosingtag\" && stack.length && stack[stack.length - 1] === this.currentTag) {\n                        // This must have been a self-closing tag that we didn't identify as a void element\n                        // (e.g. an SVG tag). Pop it off the stack as if we had encountered its close tag.\n                        closeTag(token.end, token.endPos);\n                    } else {\n                        // We're ending an open tag. Record the end of the open tag as the end of the\n                        // range. (If we later find a close tag for this tag, the end will get overwritten\n                        // with the end of the close tag. In the case of a self-closing tag, we should never\n                        // encounter that.)\n                        // Note that we don't need to update the signature here because the signature only\n                        // relies on the tag name and ID, and isn't affected by the tag's attributes, so\n                        // the signature we calculated when creating the tag is still the same. If we later\n                        // find a close tag for this tag, we'll update the signature to account for its\n                        // children at that point (in the next \"else\" case).\n                        this.currentTag.openEnd = this.currentTag.end = this.startOffset + token.end;\n                        this.currentTag.endPos = _addPos(this.startOffsetPos, token.endPos);\n                        lastClosedTag = this.currentTag;\n                        this.currentTag.updateAttributeSignature();\n                        this.currentTag = null;\n                    }\n                }\n            } else if (token.type === \"closetag\") {\n                // If this is a self-closing element, ignore the close tag.\n                var closeTagName = token.contents.toLowerCase();\n                if (!voidElements.hasOwnProperty(closeTagName)) {\n                    // Find the topmost item on the stack that matches. If we can't find one, assume\n                    // this is just a dangling closing tag and ignore it.\n                    var i;\n                    for (i = stack.length - 1; i >= 0; i--) {\n                        if (stack[i].tag === closeTagName) {\n                            break;\n                        }\n                    }\n                    if (strict && i !== stack.length - 1) {\n                        // If we're in strict mode, treat unbalanced tags as invalid.\n                        PerfUtils.finalizeMeasurement(timerBuildFull);\n                        PerfUtils.addMeasurement(timerBuildPart);\n                        this._logError(token);\n                        return null;\n                    }\n                    if (i >= 0) {\n                        do {\n                            // For all tags we're implicitly closing (before we hit the matching tag), we want the\n                            // implied end to be the beginning of the close tag (which is two characters, \"</\", before\n                            // the start of the tagname). For the actual tag we're explicitly closing, we want the\n                            // implied end to be the end of the close tag (which is one character, \">\", after the end of\n                            // the tagname).\n                            if (stack.length === i + 1) {\n                                closeTag(token.end + 1, _offsetPos(token.endPos, 1));\n                            } else {\n                                closeTag(token.start - 2, _offsetPos(token.startPos, -2));\n                            }\n                        } while (stack.length > i);\n                    } else {\n                        // If we're in strict mode, treat unmatched close tags as invalid. Otherwise\n                        // we just silently ignore them.\n                        if (strict) {\n                            PerfUtils.finalizeMeasurement(timerBuildFull);\n                            PerfUtils.addMeasurement(timerBuildPart);\n                            this._logError(token);\n                            return null;\n                        }\n                    }\n                }\n            } else if (token.type === \"attribname\") {\n                attributeName = token.contents.toLowerCase();\n                // Set the value to the empty string in case this is an empty attribute. If it's not,\n                // it will get overwritten by the attribvalue later.\n                this.currentTag.attributes[attributeName] = \"\";\n            } else if (token.type === \"attribvalue\" && attributeName !== null) {\n                this.currentTag.attributes[attributeName] = token.contents;\n                attributeName = null;\n            } else if (token.type === \"text\") {\n                if (stack.length) {\n                    var parent = stack[stack.length - 1];\n                    var newNode;\n\n                    // Check to see if we're continuing a previous text.\n                    if (lastTextNode) {\n                        newNode = lastTextNode;\n                        newNode.content += token.contents;\n                    } else {\n                        newNode = new SimpleNode({\n                            parent: stack[stack.length - 1],\n                            content: token.contents\n                        });\n                        parent.children.push(newNode);\n                        newNode.tagID = getTextNodeID(newNode);\n                        nodeMap[newNode.tagID] = newNode;\n                        lastTextNode = newNode;\n                    }\n\n                    newNode.update();\n                }\n            }\n        }\n\n        // If we have any tags hanging open (e.g. html or body), fail the parse if we're in strict mode,\n        // otherwise close them at the end of the document.\n        if (stack.length) {\n            if (strict) {\n                PerfUtils.finalizeMeasurement(timerBuildFull);\n                PerfUtils.addMeasurement(timerBuildPart);\n                this._logError(token);\n                return null;\n            } else {\n                // Manually compute the position of the end of the text (we can't rely on the\n                // tokenizer for this since it may not get to the very end)\n                // TODO: should probably make the tokenizer get to the end...\n                var lines = this.text.split(\"\\n\"),\n                    lastPos = {line: lines.length - 1, ch: lines[lines.length - 1].length};\n                while (stack.length) {\n                    closeTag(this.text.length, lastPos);\n                }\n            }\n        }\n\n        var dom = lastClosedTag;\n        if (!dom) {\n            // This can happen if the document has no nontrivial content, or if the user tries to\n            // have something at the root other than the HTML tag. In all such cases, we treat the\n            // document as invalid.\n            this._logError(token);\n            return null;\n        }\n\n        dom.nodeMap = nodeMap;\n        PerfUtils.addMeasurement(timerBuildFull);       // use\n        PerfUtils.finalizeMeasurement(timerBuildPart);  // discard\n\n        return dom;\n    };\n\n    /**\n     * Returns a new tag ID.\n     *\n     * @return {int} unique tag ID\n     */\n    Builder.prototype.getNewID = function () {\n        return tagID++;\n    };\n\n    /**\n     * Returns the best tag ID for the new tag object given.\n     * The default implementation just calls `getNewID`\n     * and returns a unique ID.\n     *\n     * @param {Object} newTag tag object to potentially inspect to choose an ID\n     * @return {int} unique tag ID\n     */\n    Builder.prototype.getID = Builder.prototype.getNewID;\n\n    /**\n     * Builds a SimpleDOM from the text provided. If `strict` mode is true, parsing\n     * will halt as soon as any error is seen and null will be returned.\n     *\n     * @param {string} text Text of document to parse\n     * @param {bool} strict True for strict parsing\n     * @return {SimpleNode} root of tree or null if strict failed\n     */\n    function build(text, strict) {\n        var builder = new Builder(text);\n        return builder.build(strict);\n    }\n\n    /**\n     * @private\n     *\n     * Generates a string version of a SimpleDOM for debugging purposes.\n     *\n     * @param {SimpleNode} root root of the tree\n     * @return {string} Text version of the tree.\n     */\n    function _dumpDOM(root) {\n        var result = \"\",\n            indent = \"\";\n\n        function walk(node) {\n            if (node.tag) {\n                result += indent + \"TAG \" + node.tagID + \" \" + node.tag + \" \" + JSON.stringify(node.attributes) + \"\\n\";\n            } else {\n                result += indent + \"TEXT \" + (node.tagID || \"- \") + node.content + \"\\n\";\n            }\n            if (node.isElement()) {\n                indent += \"  \";\n                node.children.forEach(walk);\n                indent = indent.slice(2);\n            }\n        }\n        walk(root);\n\n        return result;\n    }\n\n    // Public API\n    exports.build                       = build;\n    exports.Builder                     = Builder;\n    exports.SimpleNode                  = SimpleNode;\n\n    // Private API\n    exports._dumpDOM                    = _dumpDOM;\n    exports._offsetPos                  = _offsetPos;\n    exports._getTextNodeID              = getTextNodeID;\n    exports._seed                       = seed;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/launchers/Launcher.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils  = require(\"file/FileUtils\"),\n        NodeDomain = require(\"utils/NodeDomain\");\n\n    var _bracketsPath   = FileUtils.getNativeBracketsDirectoryPath(),\n        _modulePath     = FileUtils.getNativeModuleDirectoryPath(module),\n        _nodePath       = \"node/LauncherDomain\",\n        _domainPath     = [_bracketsPath, _modulePath, _nodePath].join(\"/\"),\n        _nodeDomain     = new NodeDomain(\"launcher\", _domainPath);\n\n\n    /**\n     * Launch the given URL in the system default browser.\n     * @param {string} url\n     */\n    function launch(url) {\n        // launch from node domain\n        _nodeDomain.exec(\"launch\", url);\n    }\n\n    // Exports\n    exports.launch = launch;\n\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/launchers/node/LauncherDomain.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nvar open = require(\"opn\");\n\n/**\n * @private\n * The Brackets domain manager for registering node extensions.\n * @type {?DomainManager}\n */\nvar _domainManager;\n\n/**\n * Launch the given URL in the system default browser.\n    * TODO: it now launching just on default browser, add launchers for specific browsers.\n * @param {string} url\n */\nfunction _cmdLaunch(url) {\n    open(url);\n}\n\n\n/**\n * Initializes the domain and registers commands.\n * @param {DomainManager} domainManager The DomainManager for the server\n */\nfunction init(domainManager) {\n    _domainManager = domainManager;\n    if (!domainManager.hasDomain(\"launcher\")) {\n        domainManager.registerDomain(\"launcher\", {major: 0, minor: 1});\n    }\n    domainManager.registerCommand(\n        \"launcher\",      // domain name\n        \"launch\",       // command name\n        _cmdLaunch,     // command handler function\n        false,          // this command is synchronous in Node\n        \"Launches a given HTML file in the browser for live development\",\n        [\n            { name: \"url\", type: \"string\", description: \"file:// url to the HTML file\" },\n            { name: \"browser\", type: \"string\", description: \"browser name\"}\n        ],\n        []\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Provides the protocol that Brackets uses to talk to a browser instance for live development.\n * Protocol methods are converted to a JSON message format, which is then sent over a provided\n * low-level transport and interpreted in the browser. For messages that expect a response, the\n * response is returned through a promise as an object. Scripts that implement remote logic are\n * provided during the instrumentation stage by \"getRemoteFunctions()\".\n *\n * Events raised by the remote browser are dispatched as jQuery events which type is equal to the 'method'\n * property. The received message object is dispatched as the first parameter and enriched with a\n * 'clientId' property being the client ID of the remote browser.\n *\n * It keeps active connections which are  updated when receiving \"connect\" and \"close\" from the\n * underlying transport. Events \"Connection.connect\"/\"Connection.close\" are triggered as\n * propagation of transport's \"connect\"/\"close\".\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher = require(\"utils/EventDispatcher\");\n\n    // Text of the script we'll inject into the browser that handles protocol requests.\n    var LiveDevProtocolRemote = require(\"text!LiveDevelopment/MultiBrowserImpl/protocol/remote/LiveDevProtocolRemote.js\"),\n        DocumentObserver      = require(\"text!LiveDevelopment/MultiBrowserImpl/protocol/remote/DocumentObserver.js\"),\n        RemoteFunctions       = require(\"text!LiveDevelopment/Agents/RemoteFunctions.js\"),\n        EditorManager         = require(\"editor/EditorManager\"),\n        LiveDevMultiBrowser   = require(\"LiveDevelopment/LiveDevMultiBrowser\"),\n        HTMLInstrumentation   = require(\"language/HTMLInstrumentation\");\n\n    /**\n     * @private\n     * Active connections.\n     * @type {Object}\n     */\n    var _connections = {};\n\n    /**\n     * @private\n     * The low-level transport we're communicating over, set by `setTransport()`.\n     * @type {{start: function(), send: function(number|Array.<number>, string), close: function(number), getRemoteScript: function(): ?string}}\n     */\n    var _transport = null;\n\n    /**\n     * @private\n     * A unique message serial number, used to match up responses with request messages.\n     * @type {number}\n     */\n    var _nextMsgId = 1;\n\n    /**\n     * @private\n     * A map of response IDs to deferreds, for messages that are awaiting responses.\n     * @type {Object}\n     */\n    var _responseDeferreds = {};\n\n    /**\n     * Returns an array of the client IDs that are being managed by this live document.\n     * @return {Array.<number>}\n     */\n    function getConnectionIds() {\n        return Object.keys(_connections);\n    }\n\n    /**\n     * @private\n     * Handles a message received from the remote protocol handler via the transport.\n     * If the message has an `id` field, it's assumed to be a response to a previous\n     * request, and will be passed along to the original promise returned by `_send()`.\n     * Otherwise, it's treated as an event and dispatched.\n     * TODO: we should probably have a way of returning the results from all clients, not just the first?\n     *\n     * @param {number} clientId ID of the client that sent the message\n     * @param {string} msg The message that was sent, in JSON string format\n     */\n    function _receive(clientId, msgStr) {\n        var msg = JSON.parse(msgStr),\n            event = msg.method || \"event\",\n            deferred;\n        if (msg.id) {\n            deferred = _responseDeferreds[msg.id];\n            if (deferred) {\n                delete _responseDeferreds[msg.id];\n                if (msg.error) {\n                    deferred.reject(msg);\n                } else {\n                    deferred.resolve(msg);\n                }\n            }\n        } else if (msg.tagId) {\n            var editor = EditorManager.getActiveEditor(),\n                position = HTMLInstrumentation.getPositionFromTagId(editor, parseInt(msg.tagId, 10));\n            if (position) {\n                editor.setCursorPos(position.line, position.ch, true);\n            }\n        } else {\n            // enrich received message with clientId\n            msg.clientId = clientId;\n            exports.trigger(event, msg);\n        }\n    }\n\n    /**\n     * @private\n     * Dispatches a message to the remote protocol handler via the transport.\n     *\n     * @param {Object} msg The message to send.\n     * @param {number|Array.<number>} idOrArray ID or IDs of the client(s) that should\n     *     receive the message.\n     * @return {$.Promise} A promise that's fulfilled when the response to the message is received.\n     */\n    function _send(msg, clients) {\n        var id = _nextMsgId++,\n            result = new $.Deferred();\n\n        // broadcast if there are no specific clients\n        clients = clients || getConnectionIds();\n        msg.id = id;\n        _responseDeferreds[id] = result;\n        _transport.send(clients, JSON.stringify(msg));\n        return result.promise();\n    }\n\n     /**\n     * @private\n     * Handles when a connection is made to the live development protocol handler.\n     * Injects the RemoteFunctions script in order to provide highlighting and live DOM editing functionality.\n     * Records the connection's client ID and triggers the \"Coonnection.connect\" event.\n     * @param {number} clientId\n     * @param {string} url\n     */\n    function _connect(clientId, url) {\n        // add new connections\n        // TODO: check URL\n        _connections[clientId] = true;\n\n        exports.trigger(\"ConnectionConnect\", {\n            clientId: clientId,\n            url: url\n        });\n    }\n\n    /**\n     * @private\n     * Handles when a connection is closed.\n     * @param {number} clientId\n     */\n    function _close(clientId) {\n        delete _connections[clientId];\n        exports.trigger(\"ConnectionClose\", {\n            clientId: clientId\n        });\n    }\n\n\n    /**\n     * Sets the transport that should be used by the protocol. See `LiveDevelopment.setTransport()`\n     * for more detail on the transport.\n     * @param {{start: function(string), send: function(number|Array.<number>, string), close: function(number), getRemoteScript: function(): ?string}} transport\n     */\n    function setTransport(transport) {\n        if (_transport) {\n            _transport.off(\".livedev\");\n        }\n        _transport = transport;\n\n        _transport\n            .on(\"connect.livedev\", function (event, msg) {\n                _connect(msg[0], msg[1]);\n            })\n            .on(\"message.livedev\", function (event, msg) {\n                _receive(msg[0], msg[1]);\n            })\n            .on(\"close.livedev\", function (event, msg) {\n                _close(msg[0]);\n            });\n        _transport.start();\n    }\n\n\n    /**\n     * Returns a script that should be injected into the HTML that's launched in the\n     * browser in order to implement remote commands that handle protocol requests.\n     * Includes the <script> tags.\n     * @return {string}\n     */\n    function getRemoteFunctionsScript() {\n        var script = \"\";\n        // Inject DocumentObserver into the browser (tracks related documents)\n        script += DocumentObserver;\n        // Inject remote functions into the browser.\n        script += \"window._LD=(\" + RemoteFunctions + \"(\" + JSON.stringify(LiveDevMultiBrowser.config) + \"))\";\n        return \"<script>\\n\" + script + \"</script>\\n\";\n    }\n\n    /**\n     * Returns a script that should be injected into the HTML that's launched in the\n     * browser in order to handle protocol requests. Includes the <script> tags.\n     * This script will also include the script required by the transport, if any.\n     * @return {string}\n     */\n    function getRemoteScript() {\n        var transportScript = _transport.getRemoteScript() || \"\";\n        var remoteFunctionsScript = getRemoteFunctionsScript() || \"\";\n        return transportScript +\n            \"<script>\\n\" + LiveDevProtocolRemote + \"</script>\\n\" +\n            remoteFunctionsScript;\n    }\n\n    /**\n     * Protocol method. Evaluates the given script in the browser (in global context), and returns a promise\n     * that will be fulfilled with the result of the script, if any.\n     * @param {number|Array.<number>} clients A client ID or array of client IDs that should evaluate\n     *      the script.\n     * @param {string} script The script to evaluate.\n     * @return {$.Promise} A promise that's resolved with the return value from the first client that responds\n     *      to the evaluation.\n     */\n    function evaluate(script, clients) {\n        return _send(\n            {\n                method: \"Runtime.evaluate\",\n                params: {\n                    expression: script\n                }\n            },\n            clients\n        );\n    }\n\n    /**\n     * Protocol method. Reloads a CSS styleseet in the browser (by replacing its text) given its url.\n     * @param {string} url Absolute URL of the stylesheet\n     * @param {string} text The new text of the stylesheet\n     * @param {number|Array.<number>} clients A client ID or array of client IDs that should evaluate\n     *      the script.\n     * @return {$.Promise} A promise that's resolved with the return value from the first client that responds\n     *      to the evaluation.\n     */\n    function setStylesheetText(url, text, clients) {\n        return _send(\n            {\n                method: \"CSS.setStylesheetText\",\n                params: {\n                    url: url,\n                    text: text\n                }\n            }\n        );\n    }\n\n     /**\n     * Protocol method. Rretrieves the content of a given stylesheet (for unit testing)\n     * @param {number|Array.<number>} clients A client ID or array of client IDs that should navigate to the given URL.\n     * @param {string} url Absolute URL that identifies the stylesheet.\n     * @return {$.Promise} A promise that's resolved with the return value from the first client that responds\n     *      to the method.\n     */\n    function getStylesheetText(url, clients) {\n        return _send(\n            {\n                method: \"CSS.getStylesheetText\",\n                params: {\n                    url: url\n                }\n            },\n            clients\n        );\n    }\n\n    /**\n     * Protocol method. Reloads the page that is currently loaded into the browser, optionally ignoring cache.\n     * @param {number|Array.<number>} clients A client ID or array of client IDs that should reload the page.\n     * @param {boolean} ignoreCache If true, browser cache is ignored.\n     * @return {$.Promise} A promise that's resolved with the return value from the first client that responds\n     *      to the method.\n     */\n    function reload(ignoreCache, clients) {\n        return _send(\n            {\n                method: \"Page.reload\",\n                params: {\n                    ignoreCache: true\n                }\n            },\n            clients\n        );\n    }\n\n    /**\n     * Protocol method. Navigates current page to the given URL.\n     * @param {number|Array.<number>} clients A client ID or array of client IDs that should navigate to the given URL.\n     * @param {string} url URL to navigate the page to.\n     * @return {$.Promise} A promise that's resolved with the return value from the first client that responds\n     *      to the method.\n     */\n    function navigate(url, clients) {\n        return _send(\n            {\n                method: \"Page.navigate\",\n                params: {\n                    url: url\n                }\n            },\n            clients\n        );\n    }\n\n    /**\n     * Closes the connection to the given client. Proxies to the transport.\n     * @param {number} clientId\n     */\n    function close(clientId) {\n        _transport.close(clientId);\n    }\n\n    function closeAllConnections() {\n        getConnectionIds().forEach(function (clientId) {\n            close(clientId);\n        });\n        _connections = {};\n    }\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // public API\n    exports.setTransport = setTransport;\n    exports.getRemoteScript = getRemoteScript;\n    exports.evaluate = evaluate;\n    exports.setStylesheetText = setStylesheetText;\n    exports.getStylesheetText = getStylesheetText;\n    exports.reload = reload;\n    exports.navigate = navigate;\n    exports.close = close;\n    exports.getConnectionIds = getConnectionIds;\n    exports.closeAllConnections = closeAllConnections;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/protocol/remote/DocumentObserver.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global setInterval, clearInterval */\n\n(function (global) {\n    \"use strict\";\n\n    var ProtocolManager = global._Brackets_LiveDev_ProtocolManager;\n\n    var _document = null;\n    var _transport;\n\n\n    /**\n     * Retrieves related documents (external CSS and JS files)\n     *\n     * @return {{scripts: object, stylesheets: object}} Related scripts and stylesheets\n     */\n    function related() {\n\n        var rel = {\n            scripts: {},\n            stylesheets: {}\n        };\n        var i;\n        // iterate on document scripts (HTMLCollection doesn't provide forEach iterator).\n        for (i = 0; i < _document.scripts.length; i++) {\n            // add only external scripts\n            if (_document.scripts[i].src) {\n                rel.scripts[_document.scripts[i].src] = true;\n            }\n        }\n\n        var s, j;\n        //traverse @import rules\n        var traverseRules = function _traverseRules(sheet, base) {\n            var i,\n                href = sheet.href,\n                cssRules;\n\n            // Deal with Firefox's SecurityError when accessing sheets\n            // from other domains. Chrome will safely return `undefined`.\n            try {\n                cssRules = sheet.cssRules;\n            } catch (e) {\n                if (e.name !== \"SecurityError\") {\n                    throw e;\n                }\n            }\n\n            if (href && cssRules) {\n                if (rel.stylesheets[href] === undefined) {\n                    rel.stylesheets[href] = [];\n                }\n                rel.stylesheets[href].push(base);\n\n                for (i = 0; i < cssRules.length; i++) {\n                    if (cssRules[i].href) {\n                        traverseRules(cssRules[i].styleSheet, base);\n                    }\n                }\n            }\n        };\n        //iterate on document.stylesheets (StyleSheetList doesn't provide forEach iterator).\n        for (j = 0; j < window.document.styleSheets.length; j++) {\n            s = window.document.styleSheets[j];\n            traverseRules(s, s.href);\n        }\n        return rel;\n    }\n\n    /**\n     * Common functions.\n     */\n    var Utils = {\n\n        isExternalStylesheet: function (node) {\n            return (node.nodeName.toUpperCase() === \"LINK\" && node.rel === \"stylesheet\" && node.href);\n        },\n        isExternalScript: function (node) {\n            return (node.nodeName.toUpperCase() === \"SCRIPT\" && node.src);\n        }\n    };\n\n    /**\n     * CSS related commands and notifications\n     */\n    var CSS = {\n\n            /**\n            * Maintains a map of stylesheets loaded thorugh @import rules and their parents.\n            * Populated by extractImports, consumed by notifyImportsAdded / notifyImportsRemoved.\n            * @type {\n            */\n            stylesheets : {},\n\n            /**\n             * Check the stylesheet that was just added be really loaded\n             * to be able to extract potential import-ed stylesheets.\n             * It invokes notifyStylesheetAdded once the sheet is loaded.\n             * @param  {string} href Absolute URL of the stylesheet.\n             */\n            checkForStylesheetLoaded : function (href) {\n                var self = this;\n\n\n                // Inspect CSSRules for @imports:\n                // styleSheet obejct is required to scan CSSImportRules but\n                // browsers differ on the implementation of MutationObserver interface.\n                // Webkit triggers notifications before stylesheets are loaded,\n                // Firefox does it after loading.\n                // There are also differences on when 'load' event is triggered for\n                // the 'link' nodes. Webkit triggers it before stylesheet is loaded.\n                // Some references to check:\n                //      http://www.phpied.com/when-is-a-stylesheet-really-loaded/\n                //      http://stackoverflow.com/questions/17747616/webkit-dynamically-created-stylesheet-when-does-it-really-load\n                //        http://stackoverflow.com/questions/11425209/are-dom-mutation-observers-slower-than-dom-mutation-events\n                //\n                // TODO: This is just a temporary 'cross-browser' solution, it needs optimization.\n                var loadInterval = setInterval(function () {\n                    var i;\n                    for (i = 0; i < window.document.styleSheets.length; i++) {\n                        if (window.document.styleSheets[i].href === href) {\n                            //clear interval\n                            clearInterval(loadInterval);\n                            // notify stylesheets added\n                            self.notifyStylesheetAdded(href);\n                            break;\n                        }\n                    }\n                }, 50);\n            },\n\n            onStylesheetRemoved : function (url) {\n                // get style node created when setting new text for stylesheet.\n                var s = window.document.getElementById(url);\n                // remove\n                if (s && s.parentNode && s.parentNode.removeChild) {\n                    s.parentNode.removeChild(s);\n                }\n            },\n\n            /**\n             * Send a notification for the stylesheet added and\n             * its import-ed styleshets based on document.stylesheets diff\n             * from previous status. It also updates stylesheets status.\n             */\n            notifyStylesheetAdded : function () {\n                var added = {},\n                    current,\n                    newStatus;\n\n                current = this.stylesheets;\n                newStatus = related().stylesheets;\n\n                Object.keys(newStatus).forEach(function (v, i) {\n                    if (!current[v]) {\n                        added[v] = newStatus[v];\n                    }\n                });\n\n                Object.keys(added).forEach(function (v, i) {\n                    _transport.send(JSON.stringify({\n                        method: \"StylesheetAdded\",\n                        href: v,\n                        roots: [added[v]]\n                    }));\n                });\n\n                this.stylesheets = newStatus;\n            },\n\n            /**\n             * Send a notification for the removed stylesheet and\n             * its import-ed styleshets based on document.stylesheets diff\n             * from previous status. It also updates stylesheets status.\n             */\n            notifyStylesheetRemoved : function () {\n\n                var self = this;\n                var removed = {},\n                    newStatus,\n                    current;\n\n                current = self.stylesheets;\n                newStatus = related().stylesheets;\n\n                Object.keys(current).forEach(function (v, i) {\n                    if (!newStatus[v]) {\n                        removed[v] = current[v];\n                        // remove node created by setStylesheetText if any\n                        self.onStylesheetRemoved(current[v]);\n                    }\n                });\n\n                Object.keys(removed).forEach(function (v, i) {\n                    _transport.send(JSON.stringify({\n                        method: \"StylesheetRemoved\",\n                        href: v,\n                        roots: [removed[v]]\n                    }));\n                });\n\n                self.stylesheets = newStatus;\n            }\n        };\n\n\n    /* process related docs added */\n    function _onNodesAdded(nodes) {\n        var i;\n        for (i = 0; i < nodes.length; i++) {\n            //check for Javascript files\n            if (Utils.isExternalScript(nodes[i])) {\n                _transport.send(JSON.stringify({\n                    method: 'ScriptAdded',\n                    src: nodes[i].src\n                }));\n            }\n            //check for stylesheets\n            if (Utils.isExternalStylesheet(nodes[i])) {\n                CSS.checkForStylesheetLoaded(nodes[i].href);\n            }\n        }\n    }\n    /* process related docs removed */\n    function _onNodesRemoved(nodes) {\n        var i;\n        //iterate on removed nodes\n        for (i = 0; i < nodes.length; i++) {\n\n            // check for external JS files\n            if (Utils.isExternalScript(nodes[i])) {\n                _transport.send(JSON.stringify({\n                    method: 'ScriptRemoved',\n                    src: nodes[i].src\n                }));\n            }\n            //check for external StyleSheets\n            if (Utils.isExternalStylesheet(nodes[i])) {\n                CSS.notifyStylesheetRemoved(nodes[i].href);\n            }\n        }\n    }\n\n    function _enableListeners() {\n        // enable MutationOberver if it's supported\n        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;\n        if (MutationObserver) {\n            var observer = new MutationObserver(function (mutations) {\n                mutations.forEach(function (mutation) {\n                    if (mutation.addedNodes.length > 0) {\n                        _onNodesAdded(mutation.addedNodes);\n                    }\n                    if (mutation.removedNodes.length > 0) {\n                        _onNodesRemoved(mutation.removedNodes);\n                    }\n                });\n            });\n            observer.observe(_document, {\n                childList: true,\n                subtree: true\n            });\n        } else {\n            // use MutationEvents as fallback\n            window.document.addEventListener('DOMNodeInserted', function niLstnr(e) {\n                _onNodesAdded([e.target]);\n            });\n            window.document.addEventListener('DOMNodeRemoved', function nrLstnr(e) {\n                _onNodesRemoved([e.target]);\n            });\n        }\n    }\n\n\n    /**\n     * Start listening for events and send initial related documents message.\n     *\n     * @param {HTMLDocument} document\n     * @param {object} transport Live development transport connection\n     */\n    function start(document, transport) {\n        _transport = transport;\n        _document = document;\n        // start listening to node changes\n        _enableListeners();\n\n        var rel = related();\n\n        // send the current status of related docs.\n        _transport.send(JSON.stringify({\n            method: \"DocumentRelated\",\n            related: rel\n        }));\n        // initialize stylesheets with current status for further notifications.\n        CSS.stylesheets = rel.stylesheets;\n    }\n\n    /**\n     * Stop listening.\n     * TODO currently a no-op.\n     */\n    function stop() {\n\n    }\n\n    var DocumentObserver = {\n        start: start,\n        stop: stop,\n        related: related\n    };\n\n    ProtocolManager.setDocumentObserver(DocumentObserver);\n\n}(this));\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/protocol/remote/LiveDevProtocolRemote.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint evil: true */\n\n// This is the script that Brackets live development injects into HTML pages in order to\n// establish and maintain the live development socket connection. Note that Brackets may\n// also inject other scripts via \"evaluate\" once this has connected back to Brackets.\n\n(function (global) {\n    \"use strict\";\n\n    // This protocol handler assumes that there is also an injected transport script that\n    // has the following methods:\n    //     setCallbacks(obj) - a method that takes an object with a \"message\" callback that\n    //         will be called with the message string whenever a message is received by the transport.\n    //     send(msgStr) - sends the given message string over the transport.\n    var transport = global._Brackets_LiveDev_Transport;\n\n    /**\n     * Manage messaging between Editor and Browser at the protocol layer.\n     * Handle messages that arrives through the current transport and dispatch them\n     * to subscribers. Subscribers are handlers that implements remote commands/functions.\n     * Property 'method' of messages body is used as the 'key' to identify message types.\n     * Provide a 'send' operation that allows remote commands sending messages to the Editor.\n     */\n    var MessageBroker = {\n\n        /**\n         * Collection of handlers (subscribers) per each method.\n         * To be pushed by 'on' and consumed by 'trigger' stored this way:\n         *      handlers[method] = [handler1, handler2, ...]\n         */\n        handlers: {},\n\n         /**\n          * Dispatch messages to handlers according to msg.method value.\n          * @param {Object} msg Message to be dispatched.\n          */\n        trigger: function (msg) {\n            var msgHandlers;\n            if (!msg.method) {\n                // no message type, ignoring it\n                // TODO: should we trigger a generic event?\n                console.log(\"[Brackets LiveDev] Received message without method.\");\n                return;\n            }\n            // get handlers for msg.method\n            msgHandlers = this.handlers[msg.method];\n\n            if (msgHandlers && msgHandlers.length > 0) {\n                // invoke handlers with the received message\n                msgHandlers.forEach(function (handler) {\n                    try {\n                        // TODO: check which context should be used to call handlers here.\n                        handler(msg);\n                        return;\n                    } catch (e) {\n                        console.log(\"[Brackets LiveDev] Error executing a handler for \" + msg.method);\n                        console.log(e.stack);\n                        return;\n                    }\n                });\n            } else {\n                // no subscribers, ignore it.\n                // TODO: any other default handling? (eg. specific respond, trigger as a generic event, etc.);\n                console.log(\"[Brackets LiveDev] No subscribers for message \" + msg.method);\n                return;\n            }\n        },\n\n        /**\n         * Send a response of a particular message to the Editor.\n         * Original message must provide an 'id' property\n         * @param {Object} orig Original message.\n         * @param {Object} response Message to be sent as the response.\n         */\n        respond: function (orig, response) {\n            if (!orig.id) {\n                console.log(\"[Brackets LiveDev] Trying to send a response for a message with no ID\");\n                return;\n            }\n            response.id = orig.id;\n            this.send(response);\n        },\n\n        /**\n         * Subscribe handlers to specific messages.\n         * @param {string} method Message type.\n         * @param {function} handler.\n         * TODO: add handler name or any identification mechanism to then implement 'off'?\n         */\n        on: function (method, handler) {\n            if (!method || !handler) {\n                return;\n            }\n            if (!this.handlers[method]) {\n                //initialize array\n                this.handlers[method] = [];\n            }\n            // add handler to the stack\n            this.handlers[method].push(handler);\n        },\n\n        /**\n         * Send a message to the Editor.\n         * @param {string} msgStr Message to be sent.\n         */\n        send: function (msgStr) {\n            transport.send(JSON.stringify(msgStr));\n        }\n    };\n\n    /**\n     * Runtime Domain. Implements remote commands for \"Runtime.*\"\n     */\n    var Runtime = {\n        /**\n         * Evaluate an expresion and return its result.\n         */\n        evaluate: function (msg) {\n            console.log(\"Runtime.evaluate\");\n            var result = eval(msg.params.expression);\n            MessageBroker.respond(msg, {\n                result: JSON.stringify(result) // TODO: in original protocol this is an object handle\n            });\n        }\n    };\n\n    // subscribe handler to method Runtime.evaluate\n    MessageBroker.on(\"Runtime.evaluate\", Runtime.evaluate);\n\n    /**\n     * CSS Domain.\n     */\n    var CSS = {\n\n        setStylesheetText : function (msg) {\n\n            if (!msg || !msg.params || !msg.params.text || !msg.params.url) {\n                return;\n            }\n\n            var i,\n                node;\n\n            var head = window.document.getElementsByTagName('head')[0];\n            // create an style element to replace the one loaded with <link>\n            var s = window.document.createElement('style');\n            s.type = 'text/css';\n            s.appendChild(window.document.createTextNode(msg.params.text));\n\n            for (i = 0; i < window.document.styleSheets.length; i++) {\n                node = window.document.styleSheets[i];\n                if (node.ownerNode.id === msg.params.url) {\n                    head.insertBefore(s, node.ownerNode); // insert the style element here\n                    // now can remove the style element previously created (if any)\n                    node.ownerNode.parentNode.removeChild(node.ownerNode);\n                } else if (node.href === msg.params.url  && !node.disabled) {\n                    // if the link element to change\n                    head.insertBefore(s, node.ownerNode); // insert the style element here\n                    node.disabled = true;\n                    i++; // since we have just inserted a stylesheet\n                }\n            }\n            s.id = msg.params.url;\n        },\n\n        /**\n        * retrieves the content of the stylesheet\n        * TODO: it now depends on reloadCSS implementation\n        */\n        getStylesheetText: function (msg) {\n            var i,\n                sheet,\n                text = \"\";\n            for (i = 0; i < window.document.styleSheets.length; i++) {\n                sheet = window.document.styleSheets[i];\n                // if it was already 'reloaded'\n                if (sheet.ownerNode.id ===  msg.params.url) {\n                    text = sheet.ownerNode.textContent;\n                } else if (sheet.href === msg.params.url && !sheet.disabled) {\n                    var j,\n                        rules;\n\n                    // Deal with Firefox's SecurityError when accessing sheets\n                    // from other domains, and Chrome returning `undefined`.\n                    try {\n                        rules = window.document.styleSheets[i].cssRules;\n                    } catch (e) {\n                        if (e.name !== \"SecurityError\") {\n                            throw e;\n                        }\n                    }\n                    if (!rules) {\n                        return;\n                    }\n\n                    for (j = 0; j < rules.length; j++) {\n                        text += rules[j].cssText + '\\n';\n                    }\n                }\n            }\n\n            MessageBroker.respond(msg, {\n                text: text\n            });\n        }\n    };\n\n    MessageBroker.on(\"CSS.setStylesheetText\", CSS.setStylesheetText);\n    MessageBroker.on(\"CSS.getStylesheetText\", CSS.getStylesheetText);\n\n    /**\n     * Page Domain.\n     */\n    var Page = {\n        /**\n         * Reload the current page optionally ignoring cache.\n         * @param {Object} msg\n         */\n        reload: function (msg) {\n            // just reload the page\n            window.location.reload(msg.params.ignoreCache);\n        },\n\n        /**\n         * Navigate to a different page.\n         * @param {Object} msg\n         */\n        navigate: function (msg) {\n            if (msg.params.url) {\n                // navigate to a new page.\n                window.location.replace(msg.params.url);\n            }\n        }\n    };\n\n    // subscribe handler to method Page.reload\n    MessageBroker.on(\"Page.reload\", Page.reload);\n    MessageBroker.on(\"Page.navigate\", Page.navigate);\n    MessageBroker.on(\"ConnectionClose\", Page.close);\n\n\n\n    // By the time this executes, there must already be an active transport.\n    if (!transport) {\n        console.error(\"[Brackets LiveDev] No transport set\");\n        return;\n    }\n\n    var ProtocolManager = {\n\n        _documentObserver: {},\n\n        _protocolHandler: {},\n\n        enable: function () {\n            transport.setCallbacks(this._protocolHandler);\n            transport.enable();\n        },\n\n        onConnect: function () {\n            this._documentObserver.start(window.document, transport);\n        },\n\n        onClose: function () {\n            var body = window.document.getElementsByTagName(\"body\")[0],\n                overlay = window.document.createElement(\"div\"),\n                background = window.document.createElement(\"div\"),\n                status = window.document.createElement(\"div\");\n\n            overlay.style.width = \"100%\";\n            overlay.style.height = \"100%\";\n            overlay.style.zIndex = 2227;\n            overlay.style.position = \"fixed\";\n            overlay.style.top = 0;\n            overlay.style.left = 0;\n\n            background.style.backgroundColor = \"#fff\";\n            background.style.opacity = 0.5;\n            background.style.width = \"100%\";\n            background.style.height = \"100%\";\n            background.style.position = \"fixed\";\n            background.style.top = 0;\n            background.style.left = 0;\n\n            status.textContent = \"Live Development Session has Ended\";\n            status.style.width = \"100%\";\n            status.style.color = \"#fff\";\n            status.style.backgroundColor = \"#666\";\n            status.style.position = \"fixed\";\n            status.style.top = 0;\n            status.style.left = 0;\n            status.style.padding = \"0.2em\";\n            status.style.verticalAlign = \"top\";\n            status.style.textAlign = \"center\";\n            overlay.appendChild(background);\n            overlay.appendChild(status);\n            body.appendChild(overlay);\n\n            // change the title as well\n            window.document.title = \"(Brackets Live Preview: closed) \" + window.document.title;\n        },\n\n        setDocumentObserver: function (documentOberver) {\n            if (!documentOberver) {\n                return;\n            }\n            this._documentObserver = documentOberver;\n        },\n\n        setProtocolHandler: function (protocolHandler) {\n            if (!protocolHandler) {\n                return;\n            }\n            this._protocolHandler = protocolHandler;\n        }\n    };\n\n    // exposing ProtocolManager\n    global._Brackets_LiveDev_ProtocolManager = ProtocolManager;\n\n    /**\n     * The remote handler for the protocol.\n     */\n    var ProtocolHandler = {\n        /**\n         * Handles a message from the transport. Parses it as JSON and delegates\n         * to MessageBroker who is in charge of routing them to handlers.\n         * @param {string} msgStr The protocol message as stringified JSON.\n         */\n        message: function (msgStr) {\n            var msg;\n            try {\n                msg = JSON.parse(msgStr);\n            } catch (e) {\n                console.log(\"[Brackets LiveDev] Malformed message received: \", msgStr);\n                return;\n            }\n            // delegates handling/routing to MessageBroker.\n            MessageBroker.trigger(msg);\n        },\n\n        close: function (evt) {\n            ProtocolManager.onClose();\n        },\n\n        connect: function (evt) {\n            ProtocolManager.onConnect();\n        }\n    };\n\n    ProtocolManager.setProtocolHandler(ProtocolHandler);\n\n    window.addEventListener('load', function () {\n        ProtocolManager.enable();\n    });\n    \n    /**\n    * Sends the message containing tagID which is being clicked\n    * to the editor in order to change the cursor position to\n    * the HTML tag corresponding to the clicked element.\n    */\n    function onDocumentClick(event) {\n        var element = event.target;\n        if (element && element.hasAttribute('data-brackets-id')) {\n            MessageBroker.send({\"tagId\": element.getAttribute('data-brackets-id')});\n        }\n    }\n    window.document.addEventListener(\"click\", onDocumentClick);\n\n}(this));\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/transports/NodeSocketTransport.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n// This transport provides a WebSocket connection between Brackets and a live browser preview.\n// This is just a thin wrapper around the Node extension (NodeSocketTransportDomain) that actually\n// provides the WebSocket server and handles the communication. We also rely on an injected script in\n// the browser for the other end of the transport.\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils       = require(\"file/FileUtils\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        NodeDomain      = require(\"utils/NodeDomain\");\n\n    // The script that will be injected into the previewed HTML to handle the other side of the socket connection.\n    var NodeSocketTransportRemote = require(\"text!LiveDevelopment/MultiBrowserImpl/transports/remote/NodeSocketTransportRemote.js\");\n\n    // The node extension that actually provides the WebSocket server.\n\n    var domainPath = FileUtils.getNativeBracketsDirectoryPath() + \"/\" + FileUtils.getNativeModuleDirectoryPath(module) + \"/node/NodeSocketTransportDomain\";\n\n    var NodeSocketTransportDomain = new NodeDomain(\"nodeSocketTransport\", domainPath);\n\n    // This must match the port declared in NodeSocketTransportDomain.js.\n    // TODO: randomize this?\n    var SOCKET_PORT = 8123;\n\n    /**\n     * Returns the script that should be injected into the browser to handle the other end of the transport.\n     * @return {string}\n     */\n    function getRemoteScript() {\n        return \"<script>\\n\" +\n            NodeSocketTransportRemote +\n            \"this._Brackets_LiveDev_Socket_Transport_URL = 'ws://localhost:\" + SOCKET_PORT + \"';\\n\" +\n            \"</script>\\n\";\n    }\n\n    // Events\n\n    // We can simply retrigger the events we receive from the node domain directly, since they're in\n    // the same format expected by clients of the transport.\n\n    [\"connect\", \"message\", \"close\"].forEach(function (type) {\n        NodeSocketTransportDomain.on(type, function () {\n            console.log(\"NodeSocketTransport - event - \" + type + \" - \" + JSON.stringify(Array.prototype.slice.call(arguments, 1)));\n            // Remove the event object from the argument list.\n            exports.trigger(type, Array.prototype.slice.call(arguments, 1));\n        });\n    });\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Exports\n    exports.getRemoteScript = getRemoteScript;\n\n    // Proxy the node domain methods directly through, since they have exactly the same\n    // signatures as the ones we're supposed to provide.\n    [\"start\", \"send\", \"close\"].forEach(function (method) {\n        exports[method] = function () {\n            var args = Array.prototype.slice.call(arguments);\n            args.unshift(method);\n            console.log(\"NodeSocketTransport - \" + args);\n            NodeSocketTransportDomain.exec.apply(NodeSocketTransportDomain, args);\n        };\n    });\n\n});\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/transports/node/NodeSocketTransportDomain.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nvar WebSocketServer = require(\"ws\").Server,\n    _ = require(\"lodash\");\n\n/**\n * @private\n * The WebSocket server we listen for incoming connections on.\n * @type {?WebSocketServer}\n */\nvar _wsServer;\n\n/**\n * @private\n * The Brackets domain manager for registering node extensions.\n * @type {?DomainManager}\n */\nvar _domainManager;\n\n/**\n * @private\n * The ID that should be allocated to the next client that connects to the transport.\n * @type {number}\n */\nvar _nextClientId = 1;\n\n/**\n * @private\n * A map of client IDs to the URL and WebSocket for the given ID.\n * @type {Object.<number, {id: number, url: string, socket: WebSocket}>}\n */\nvar _clients = {};\n\n// This must match the port declared in NodeSocketTransport.js.\n// TODO: randomize this?\nvar SOCKET_PORT = 8123;\n\n/**\n * @private\n * Returns the client info for a given WebSocket, or null if that socket isn't registered.\n * @param {WebSocket} ws\n * @return {?{id: number, url: string, socket: WebSocket}}\n */\nfunction _clientForSocket(ws) {\n    return _.find(_clients, function (client) {\n        return (client.socket === ws);\n    });\n}\n\n/**\n * @private\n * Creates the WebSocketServer and handles incoming connections.\n */\nfunction _createServer() {\n    if (!_wsServer) {\n        // TODO: make port configurable, or use random port\n        _wsServer = new WebSocketServer({port: SOCKET_PORT});\n        _wsServer.on(\"connection\", function (ws) {\n            ws.on(\"message\", function (msg) {\n                console.log(\"WebSocketServer - received - \" + msg);\n                var msgObj;\n                try {\n                    msgObj = JSON.parse(msg);\n                } catch (e) {\n                    console.error(\"nodeSocketTransport: Error parsing message: \" + msg);\n                    return;\n                }\n\n                // See the comment in NodeSocketTransportRemote.connect() for why we have an extra\n                // layer of transport-layer message objects surrounding the protocol messaging.\n\n                if (msgObj.type === \"connect\") {\n                    if (!msgObj.url) {\n                        console.error(\"nodeSocketTransport: Malformed connect message: \" + msg);\n                        return;\n                    }\n                    var clientId = _nextClientId++;\n                    _clients[clientId] = {\n                        id: clientId,\n                        url: msgObj.url,\n                        socket: ws\n                    };\n                    console.log(\"emitting connect event\");\n                    _domainManager.emitEvent(\"nodeSocketTransport\", \"connect\", [clientId, msgObj.url]);\n                } else if (msgObj.type === \"message\") {\n                    var client = _clientForSocket(ws);\n                    if (client) {\n                        _domainManager.emitEvent(\"nodeSocketTransport\", \"message\", [client.id, msgObj.message]);\n                    } else {\n                        console.error(\"nodeSocketTransport: Couldn't locate client for message: \" + msg);\n                    }\n                } else {\n                    console.error(\"nodeSocketTransport: Got bad socket message type: \" + msg);\n                }\n            }).on(\"error\", function (e) {\n                // TODO: emit error event\n                var client = _clientForSocket(ws);\n                console.error(\"nodeSocketTransport: Error on socket for client \" + JSON.stringify(client) + \": \" + e);\n            }).on(\"close\", function () {\n                var client = _clientForSocket(ws);\n                if (client) {\n                    _domainManager.emitEvent(\"nodeSocketTransport\", \"close\", [client.id]);\n                    delete _clients[client.id];\n                } else {\n                    console.error(\"nodeSocketTransport: Socket closed, but couldn't locate client\");\n                }\n            });\n        }).on(\"error\", function (e) {\n            // TODO: emit error event\n            console.error(\"nodeSocketTransport: Error on live preview server creation: \" + e);\n        });\n    }\n}\n\n/**\n * Initializes the socket server.\n * @param {string} url\n */\nfunction _cmdStart(url) {\n    _createServer();\n}\n\n/**\n * Sends a transport-layer message over the socket.\n * @param {number|Array.<number>} idOrArray A client ID or array of client IDs to send the message to.\n * @param {string} msgStr The message to send as a JSON string.\n */\nfunction _cmdSend(idOrArray, msgStr) {\n    if (!Array.isArray(idOrArray)) {\n        idOrArray = [idOrArray];\n    }\n    idOrArray.forEach(function (id) {\n        var client = _clients[id];\n        if (!client) {\n            console.error(\"nodeSocketTransport: Couldn't find client ID: \" + id);\n        } else {\n            client.socket.send(msgStr);\n        }\n    });\n}\n\n/**\n * Closes the connection for a given client ID.\n * @param {number} clientId\n */\nfunction _cmdClose(clientId) {\n    var client = _clients[clientId];\n    if (client) {\n        client.socket.close();\n        delete _clients[clientId];\n    }\n}\n\n/**\n * Initializes the domain and registers commands.\n * @param {DomainManager} domainManager The DomainManager for the server\n */\nfunction init(domainManager) {\n    _domainManager = domainManager;\n    if (!domainManager.hasDomain(\"nodeSocketTransport\")) {\n        domainManager.registerDomain(\"nodeSocketTransport\", {major: 0, minor: 1});\n    }\n    domainManager.registerCommand(\n        \"nodeSocketTransport\",      // domain name\n        \"start\",       // command name\n        _cmdStart,     // command handler function\n        false,          // this command is synchronous in Node\n        \"Creates the WS server\",\n        []\n    );\n    domainManager.registerCommand(\n        \"nodeSocketTransport\",      // domain name\n        \"send\",         // command name\n        _cmdSend,       // command handler function\n        false,          // this command is synchronous in Node\n        \"Sends a message to a given client or list of clients\",\n        [\n            {name: \"idOrArray\", type: \"number|Array.<number>\", description: \"id or array of ids to send the message to\"},\n            {name: \"message\", type: \"string\", description: \"JSON message to send\"}\n        ],\n        []\n    );\n    domainManager.registerCommand(\n        \"nodeSocketTransport\",      // domain name\n        \"close\",         // command name\n        _cmdClose,       // command handler function\n        false,          // this command is synchronous in Node\n        \"Closes the connection to a given client\",\n        [\n            {name: \"id\", type: \"number\", description: \"id of connection to close\"}\n        ],\n        []\n    );\n    domainManager.registerEvent(\n        \"nodeSocketTransport\",\n        \"connect\",\n        [\n            {name: \"clientID\", type: \"number\", description: \"ID of live preview page connecting to live development\"},\n            {name: \"url\", type: \"string\", description: \"URL of page that live preview is connecting from\"}\n        ]\n    );\n    domainManager.registerEvent(\n        \"nodeSocketTransport\",\n        \"message\",\n        [\n            {name: \"clientID\", type: \"number\", description: \"ID of live preview page sending message\"},\n            {name: \"msg\", type: \"string\", description: \"JSON message from client page\"}\n        ]\n    );\n    domainManager.registerEvent(\n        \"nodeSocketTransport\",\n        \"close\",\n        [\n            {name: \"clientID\", type: \"number\", description: \"ID of live preview page being closed\"}\n        ]\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/LiveDevelopment/MultiBrowserImpl/transports/remote/NodeSocketTransportRemote.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n// This is a transport injected into the browser via a script that handles the low\n// level communication between the live development protocol handlers on both sides.\n// This transport provides a web socket mechanism. It's injected separately from the\n// protocol handler so that the transport can be changed separately.\n\n(function (global) {\n    \"use strict\";\n\n    var WebSocketTransport = {\n        /**\n         * @private\n         * The WebSocket that we communicate with Brackets over.\n         * @type {?WebSocket}\n         */\n        _ws: null,\n\n        /**\n         * @private\n         * An object that contains callbacks to handle various transport events. See `setCallbacks()`.\n         * @type {?{connect: ?function, message: ?function(string), close: ?function}}\n         */\n        _callbacks: null,\n\n        /**\n         * Sets the callbacks that should be called when various transport events occur. All callbacks\n         * are optional, but you should at least implement \"message\" or nothing interesting will happen :)\n         * @param {?{connect: ?function, message: ?function(string), close: ?function}} callbacks\n         *      The callbacks to set.\n         *      connect - called when a connection is established to Brackets\n         *      message(msgStr) - called with a string message sent from Brackets\n         *      close - called when Brackets closes the connection\n         */\n        setCallbacks: function (callbacks) {\n            if (!global._Brackets_LiveDev_Socket_Transport_URL) {\n                console.error(\"[Brackets LiveDev] No socket transport URL injected\");\n            } else {\n                this._callbacks = callbacks;\n            }\n        },\n\n        /**\n         * Connects to the NodeSocketTransport in Brackets at the given WebSocket URL.\n         * @param {string} url\n         */\n        connect: function (url) {\n            var self = this;\n            this._ws = new WebSocket(url);\n\n            // One potential source of confusion: the transport sends two \"types\" of messages -\n            // these are distinct from the protocol's own messages. This is because this transport\n            // needs to send an initial \"connect\" message telling the Brackets side of the transport\n            // the URL of the page that it's connecting from, distinct from the actual protocol\n            // message traffic. Actual protocol messages are sent as a JSON payload in a message of\n            // type \"message\".\n            //\n            // Other transports might not need to do this - for example, a transport that simply\n            // talks to an iframe within the same process already knows what URL that iframe is\n            // pointing to, so the only comunication that needs to happen via postMessage() is the\n            // actual protocol message strings, and no extra wrapping is necessary.\n\n            this._ws.onopen = function (event) {\n                // Send the initial \"connect\" message to tell the other end what URL we're from.\n                self._ws.send(JSON.stringify({\n                    type: \"connect\",\n                    url: global.location.href\n                }));\n                console.log(\"[Brackets LiveDev] Connected to Brackets at \" + url);\n                if (self._callbacks && self._callbacks.connect) {\n                    self._callbacks.connect();\n                }\n            };\n            this._ws.onmessage = function (event) {\n                console.log(\"[Brackets LiveDev] Got message: \" + event.data);\n                if (self._callbacks && self._callbacks.message) {\n                    self._callbacks.message(event.data);\n                }\n            };\n            this._ws.onclose = function (event) {\n                self._ws = null;\n                if (self._callbacks && self._callbacks.close) {\n                    self._callbacks.close();\n                }\n            };\n            // TODO: onerror\n        },\n\n        /**\n         * Sends a message over the transport.\n         * @param {string} msgStr The message to send.\n         */\n        send: function (msgStr) {\n            if (this._ws) {\n                // See comment in `connect()` above about why we wrap the message in a transport message\n                // object.\n                this._ws.send(JSON.stringify({\n                    type: \"message\",\n                    message: msgStr\n                }));\n            } else {\n                console.log(\"[Brackets LiveDev] Tried to send message over closed connection: \" + msgStr);\n            }\n        },\n\n        /**\n         * Establish web socket connection.\n         */\n        enable: function () {\n            this.connect(global._Brackets_LiveDev_Socket_Transport_URL);\n        }\n    };\n    global._Brackets_LiveDev_Transport = WebSocketTransport;\n}(this));\n"
  },
  {
    "path": "src/LiveDevelopment/Servers/BaseServer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * Base class for live preview servers\n     *\n     * Configuration parameters for this server:\n     * - baseUrl      - Optional base URL (populated by the current project)\n     * - pathResolver - Function to covert absolute native paths to project relative paths\n     * - root         - Native path to the project root (and base URL)\n     *\n     * @constructor\n     * @param {!{baseUrl: string, root: string, pathResolver: function(string): string}} config\n     */\n    function BaseServer(config) {\n        this._baseUrl       = config.baseUrl;\n        this._root          = config.root;          // ProjectManager.getProjectRoot().fullPath\n        this._pathResolver  = config.pathResolver;  // ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath)\n        this._liveDocuments = {};\n    }\n\n    /**\n     * Returns a base url for current project.\n     *\n     * @return {string}\n     * Base url for current project.\n     */\n    BaseServer.prototype.getBaseUrl = function () {\n        return this._baseUrl;\n    };\n\n    /**\n     * @private\n     * Augments the given Brackets document with information that's useful for live development\n     * @param {Object} liveDocument\n     */\n    BaseServer.prototype._setDocInfo = function (liveDocument) {\n        var parentUrl,\n            matches,\n            doc = liveDocument.doc;\n\n        // FUTURE: some of these things should just be moved into core Document; others should\n        // be in a LiveDevelopment-specific object attached to the doc.\n        matches = /^(.*\\/)(.+\\.([^.]+))$/.exec(doc.file.fullPath);\n        if (!matches) {\n            return;\n        }\n\n        doc.extension = matches[3];\n\n        parentUrl = this.pathToUrl(matches[1]);\n        doc.url = parentUrl + encodeURI(matches[2]);\n\n        // the root represents the document that should be displayed in the browser\n        // for live development (the file for HTML files)\n        // TODO: Issue #2033 Improve how default page is determined\n        doc.root = { url: doc.url };\n\n        // TODO: Better workflow of liveDocument.doc.url assignment\n        // Force sync the browser after a URL is assigned\n        if (doc.isDirty && liveDocument._updateBrowser) {\n            liveDocument._updateBrowser();\n        }\n    };\n\n    /**\n     * Returns a URL for a given path\n     * @param {string} path Absolute path to covert to a URL\n     * @return {?string} Converts a path within the project root to a URL.\n     *  Returns null if the path is not a descendant of the project root.\n     */\n    BaseServer.prototype.pathToUrl = function (path) {\n        var baseUrl         = this.getBaseUrl(),\n            relativePath    = this._pathResolver(path);\n\n        // See if base url has been specified and path is within project\n        if (relativePath !== path) {\n            // Map to server url. Base url is already encoded, so don't encode again.\n            var encodedDocPath = encodeURI(path);\n            var encodedProjectPath = encodeURI(this._root);\n\n            return encodedDocPath.replace(encodedProjectPath, baseUrl);\n        }\n\n        return null;\n    };\n\n    /**\n     * Convert a URL to a local full file path\n     * @param {string} url\n     * @return {?string} The absolute path for given URL or null if the path is\n     *  not a descendant of the project.\n     */\n    BaseServer.prototype.urlToPath = function (url) {\n        var path,\n            baseUrl = \"\";\n\n        baseUrl = this.getBaseUrl();\n\n        if (baseUrl !== \"\" && url.indexOf(baseUrl) === 0) {\n            // Use base url to translate to local file path.\n            // Need to use encoded project path because it's decoded below.\n            path = url.replace(baseUrl, encodeURI(this._root));\n\n            return decodeURI(path);\n        }\n\n        return null;\n    };\n\n    /**\n     * Called by LiveDevelopment before to prepare the server before navigating\n     * to the project's base URL. The provider returns a jQuery promise.\n     * The Live Development launch process waits until the promise\n     * is resolved or rejected. If the promise is rejected, an error window\n     * is shown and Live Development does not start..\n     *\n     * @return {jQuery.Promise} Promise that may be asynchronously resolved\n     *  when the server is ready to handle HTTP requests.\n     */\n    BaseServer.prototype.readyToServe = function () {\n        // Base implementation always resolves\n        return $.Deferred().resolve().promise();\n    };\n\n    /**\n     * Determines if this server can serve local file. LiveDevServerManager\n     * calls this method when determining if a server can serve a file.\n     * @param {string} localPath A local path to file being served.\n     * @return {boolean} true When the file can be served, otherwise false.\n     */\n    BaseServer.prototype.canServe = function (localPath) {\n        return true;\n    };\n\n    BaseServer.prototype._documentKey = function (absolutePath) {\n        return \"/\" + encodeURI(this._pathResolver(absolutePath));\n    };\n\n    /**\n     * Adds a live document to server\n     * @param {Object} liveDocument\n     */\n    BaseServer.prototype.add = function (liveDocument) {\n        if (!liveDocument) {\n            return;\n        }\n\n        // use the project relative path as a key to lookup requests\n        var key = this._documentKey(liveDocument.doc.file.fullPath);\n\n        this._setDocInfo(liveDocument);\n        this._liveDocuments[key] = liveDocument;\n    };\n\n    /**\n     * Removes a live document from the server\n     * @param {Object} liveDocument\n     */\n    BaseServer.prototype.remove = function (liveDocument) {\n        if (!liveDocument) {\n            return;\n        }\n\n        var key = this._liveDocuments[this._documentKey(liveDocument.doc.file.fullPath)];\n\n        if (key) {\n            delete this._liveDocuments[key];\n        }\n    };\n\n    /**\n     * Lookup a live document using it's full path key\n     * @param {string} path Absolute path to covert to a URL\n     * @param {?Object} liveDocument Returns a live document or undefined if a\n     *     document does not exist for the path.\n     */\n    BaseServer.prototype.get = function (path) {\n        return this._liveDocuments[this._documentKey(path)];\n    };\n\n    /**\n     * Clears all live documents currently attached to the server\n     */\n    BaseServer.prototype.clear = function () {\n        this._liveDocuments = {};\n    };\n\n    /**\n     * Start the server\n     */\n    BaseServer.prototype.start = function () {\n        // do nothing\n    };\n\n    /**\n     * Stop the server\n     */\n    BaseServer.prototype.stop = function () {\n        // do nothing\n    };\n\n    exports.BaseServer = BaseServer;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Servers/FileServer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var BaseServer           = require(\"LiveDevelopment/Servers/BaseServer\").BaseServer,\n        LiveDevelopmentUtils = require(\"LiveDevelopment/LiveDevelopmentUtils\");\n\n    // The path on Windows starts with a drive letter (e.g. \"C:\").\n    // In order to make it a valid file: URL we need to add an\n    // additional slash to the prefix.\n    var PREFIX = (brackets.platform === \"win\") ? \"file:///\" : \"file://\";\n\n    /**\n     * Server for file: URLs\n     *\n     * Configuration parameters for this server:\n     * - baseUrl      - Optional base URL (populated by the current project)\n     * - pathResolver - Function to covert absolute native paths to project relative paths\n     * - root         - Native path to the project root (and base URL)\n     *\n     * @constructor\n     * @param {!{baseUrl: string, root: string, pathResolver: function(string): string}} config\n     * @extends {BaseServer}\n     */\n    function FileServer(config) {\n        BaseServer.call(this, config);\n    }\n\n    FileServer.prototype = Object.create(BaseServer.prototype);\n    FileServer.prototype.constructor = FileServer;\n\n    /**\n     * Determines whether we can serve local file.\n     * @param {string} localPath A local path to file being served.\n     * @return {boolean} true for yes, otherwise false.\n     */\n    FileServer.prototype.canServe = function (localPath) {\n        // FileServer requires that the base URL is undefined and static HTML files\n        return (!this._baseUrl && LiveDevelopmentUtils.isStaticHtmlFileExt(localPath));\n    };\n\n    /**\n     * Convert a file: URL to a absolute file path\n     * @param {string} url\n     * @return {?string} The absolute path for given file: URL or null if the path is\n     *  not a descendant of the project.\n     */\n    FileServer.prototype.urlToPath = function (url) {\n        if (url.indexOf(PREFIX) === 0) {\n            // Convert a file URL to local file path\n            return decodeURI(url.slice(PREFIX.length));\n        }\n\n        return null;\n    };\n\n    /**\n     * Returns a file: URL for a given absolute path\n     * @param {string} path Absolute path to covert to a file: URL\n     * @return {string} Converts an absolute path within the project root to a file: URL.\n     */\n    FileServer.prototype.pathToUrl = function (path) {\n        return encodeURI(PREFIX + path);\n    };\n\n    exports.FileServer = FileServer;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/Servers/UserServer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var BaseServer             = require(\"LiveDevelopment/Servers/BaseServer\").BaseServer,\n        LiveDevelopmentUtils   = require(\"LiveDevelopment/LiveDevelopmentUtils\");\n\n    /**\n     * Live preview server for user specified server as defined with Live Preview Base Url\n     * Project setting. In a clean installation of Brackets, this is the highest priority\n     * server provider, if defined.\n     *\n     * Configuration parameters for this server:\n     * - baseUrl      - Optional base URL (populated by the current project)\n     * - pathResolver - Function to covert absolute native paths to project relative paths\n     * - root         - Native path to the project root (and base URL)\n     *\n     * @constructor\n     * @param {!{baseUrl: string, root: string, pathResolver: function(string)}} config\n     * @extends {BaseServer}\n     */\n    function UserServer(config) {\n        BaseServer.call(this, config);\n    }\n\n    UserServer.prototype = Object.create(BaseServer.prototype);\n    UserServer.prototype.constructor = UserServer;\n\n    /**\n     * Determines whether we can serve local file.\n     * @param {string} localPath A local path to file being served.\n     * @return {boolean} true for yes, otherwise false.\n     */\n    UserServer.prototype.canServe = function (localPath) {\n        // UserServer can only function when the project specifies a base URL\n        if (!this._baseUrl) {\n            return false;\n        }\n\n        // If we can't transform the local path to a project relative path,\n        // the path cannot be served\n        if (localPath === this._pathResolver(localPath)) {\n            return false;\n        }\n\n        return LiveDevelopmentUtils.isStaticHtmlFileExt(localPath) ||\n            LiveDevelopmentUtils.isServerHtmlFileExt(localPath);\n    };\n\n    exports.UserServer = UserServer;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/launch.html",
    "content": "<!DOCTYPE html>\n\n<!-- \n  Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n   \n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the \"Software\"), \n  to deal in the Software without restriction, including without limitation \n  the rights to use, copy, modify, merge, publish, distribute, sublicense, \n  and/or sell copies of the Software, and to permit persons to whom the \n  Software is furnished to do so, subject to the following conditions:\n   \n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n   \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n  DEALINGS IN THE SOFTWARE.\n-->\n\n<html>\n\n<head>\n    <title>Waiting...</title>\n    <script type=\"application/javascript\">\n        /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n        /*global window: true */\n\n        function handleLoad () {\n            window.isBracketsLiveDevelopmentInterstitialPageLoaded = true;\n        }\n    </script>\n    <style type=\"text/css\">\n        html, body {\n            width: 100%;\n            height: 100%;\n            padding: 0;\n            margin: 0;\n            background: #E6E6E6;\n        }\n        #loading-image {\n            background: url(\"../styles/images/no_content_bg.svg\");\n            width: 55px;\n            height: 55px;\n            position: relative;\n            margin: -55px auto 0;\n            top: 50%;\n        }\n    </style>\n</head>\n<body onload=\"handleLoad()\">\n    <div id=\"loading-image\">\n    </div>\n</body>\n\n</html>"
  },
  {
    "path": "src/LiveDevelopment/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global less */\n\n/**\n * main integrates LiveDevelopment into Brackets\n *\n * This module creates two menu items:\n *\n *  \"Go Live\": open or close a Live Development session and visualize the status\n *  \"Highlight\": toggle source highlighting\n */\ndefine(function main(require, exports, module) {\n    \"use strict\";\n\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        Commands            = require(\"command/Commands\"),\n        AppInit             = require(\"utils/AppInit\"),\n        LiveDevelopment     = require(\"LiveDevelopment/LiveDevelopment\"),\n        MultiBrowserLiveDev = require(\"LiveDevelopment/LiveDevMultiBrowser\"),\n        Inspector           = require(\"LiveDevelopment/Inspector/Inspector\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        DefaultDialogs      = require(\"widgets/DefaultDialogs\"),\n        UrlParams           = require(\"utils/UrlParams\").UrlParams,\n        Strings             = require(\"strings\"),\n        ExtensionUtils      = require(\"utils/ExtensionUtils\"),\n        StringUtils         = require(\"utils/StringUtils\");\n\n    var params = new UrlParams();\n    var config = {\n        experimental: false, // enable experimental features\n        debug: true, // enable debug output and helpers\n        autoconnect: false, // go live automatically after startup?\n        highlight: true, // enable highlighting?\n        highlightConfig: { // the highlight configuration for the Inspector\n            borderColor:  {r: 255, g: 229, b: 153, a: 0.66},\n            contentColor: {r: 111, g: 168, b: 220, a: 0.55},\n            marginColor:  {r: 246, g: 178, b: 107, a: 0.66},\n            paddingColor: {r: 147, g: 196, b: 125, a: 0.66},\n            showInfo: true\n        }\n    };\n    // Status labels/styles are ordered: error, not connected, progress1, progress2, connected.\n    var _status,\n        _allStatusStyles = [\"warning\", \"info\", \"success\", \"out-of-sync\", \"sync-error\"].join(\" \");\n\n    var _$btnGoLive; // reference to the GoLive button\n\n    // current selected implementation (LiveDevelopment | LiveDevMultiBrowser)\n    var LiveDevImpl;\n\n    // \"livedev.multibrowser\" preference\n    var PREF_MULTIBROWSER = \"multibrowser\";\n    var prefs = PreferencesManager.getExtensionPrefs(\"livedev\");\n    var multiBrowserPref = prefs.definePreference(PREF_MULTIBROWSER, \"boolean\", false, {\n        description: Strings.DESCRIPTION_LIVE_DEV_MULTIBROWSER\n    });\n\n    // \"livedev.remoteHighlight\" preference\n    var PREF_REMOTEHIGHLIGHT = \"remoteHighlight\";\n    var remoteHighlightPref = prefs.definePreference(PREF_REMOTEHIGHLIGHT, \"object\", {\n        animateStartValue: {\n            \"background-color\": \"rgba(0, 162, 255, 0.5)\",\n            \"opacity\": 0\n        },\n        animateEndValue: {\n            \"background-color\": \"rgba(0, 162, 255, 0)\",\n            \"opacity\": 0.6\n        },\n        \"paddingStyling\": {\n            \"border-width\": \"1px\",\n            \"border-style\": \"dashed\",\n            \"border-color\": \"rgba(0, 162, 255, 0.5)\"\n        },\n        \"marginStyling\": {\n            \"background-color\": \"rgba(21, 165, 255, 0.58)\"\n        },\n        \"borderColor\": \"rgba(21, 165, 255, 0.85)\",\n        \"showPaddingMargin\": true\n    }, {\n        description: Strings.DESCRIPTION_LIVE_DEV_HIGHLIGHT_SETTINGS\n    });\n    \n    /** Toggles or sets the preference **/\n    function _togglePref(key, value) {\n        var val,\n            oldPref = !!prefs.get(key);\n\n        if (value === undefined) {\n            val = !oldPref;\n        } else {\n            val = !!value;\n        }\n\n        // update menu\n        if (val !== oldPref) {\n            prefs.set(key, val);\n        }\n\n        return val;\n    }\n\n    /* Toggles or sets the \"livedev.multibrowser\" preference */\n    function _toggleLivePreviewMultiBrowser(value) {\n        var val = _togglePref(PREF_MULTIBROWSER, value);\n\n        CommandManager.get(Commands.TOGGLE_LIVE_PREVIEW_MB_MODE).setChecked(val);\n        // Issue #10217: multi-browser does not support user server, so disable\n        // the setting if it is enabled.\n        CommandManager.get(Commands.FILE_PROJECT_SETTINGS).setEnabled(!val);\n    }\n\n    /** Load Live Development LESS Style */\n    function _loadStyles() {\n        var lessText = require(\"text!LiveDevelopment/main.less\");\n\n        less.render(lessText, function onParse(err, tree) {\n            console.assert(!err, err);\n            ExtensionUtils.addEmbeddedStyleSheet(tree.css);\n        });\n    }\n\n    /**\n     * Change the appearance of a button. Omit text to remove any extra text; omit style to return to default styling;\n     * omit tooltip to leave tooltip unchanged.\n     */\n    function _setLabel($btn, text, style, tooltip) {\n        // Clear text/styles from previous status\n        $(\"span\", $btn).remove();\n        $btn.removeClass(_allStatusStyles);\n\n        // Set text/styles for new status\n        if (text && text.length > 0) {\n            $(\"<span class=\\\"label\\\">\")\n                .addClass(style)\n                .text(text)\n                .appendTo($btn);\n        } else {\n            $btn.addClass(style);\n        }\n\n        if (tooltip) {\n            $btn.attr(\"title\", tooltip);\n        }\n    }\n\n    /**\n     * Toggles LiveDevelopment and synchronizes the state of UI elements that reports LiveDevelopment status\n     *\n     * Stop Live Dev when in an active state (ACTIVE, OUT_OF_SYNC, SYNC_ERROR).\n     * Start Live Dev when in an inactive state (ERROR, INACTIVE).\n     * Do nothing when in a connecting state (CONNECTING, LOADING_AGENTS).\n     */\n    function _handleGoLiveCommand() {\n        if (LiveDevImpl.status >= LiveDevImpl.STATUS_ACTIVE) {\n            LiveDevImpl.close();\n        } else if (LiveDevImpl.status <= LiveDevImpl.STATUS_INACTIVE) {\n            if (!params.get(\"skipLiveDevelopmentInfo\") && !PreferencesManager.getViewState(\"livedev.afterFirstLaunch\")) {\n                PreferencesManager.setViewState(\"livedev.afterFirstLaunch\", \"true\");\n                Dialogs.showModalDialog(\n                    DefaultDialogs.DIALOG_ID_INFO,\n                    Strings.LIVE_DEVELOPMENT_INFO_TITLE,\n                    Strings.LIVE_DEVELOPMENT_INFO_MESSAGE\n                ).done(function (id) {\n                    LiveDevImpl.open();\n                });\n            } else {\n                LiveDevImpl.open();\n            }\n        }\n    }\n\n    /** Called on status change */\n    function _showStatusChangeReason(reason) {\n        // Destroy the previous twipsy (options are not updated otherwise)\n        _$btnGoLive.twipsy(\"hide\").removeData(\"twipsy\");\n\n        // If there was no reason or the action was an explicit request by the user, don't show a twipsy\n        if (!reason || reason === \"explicit_close\") {\n            return;\n        }\n\n        // Translate the reason\n        var translatedReason = Strings[\"LIVE_DEV_\" + reason.toUpperCase()];\n        if (!translatedReason) {\n            translatedReason = StringUtils.format(Strings.LIVE_DEV_CLOSED_UNKNOWN_REASON, reason);\n        }\n\n        // Configure the twipsy\n        var options = {\n            placement: \"left\",\n            trigger: \"manual\",\n            autoHideDelay: 5000,\n            title: function () {\n                return translatedReason;\n            }\n        };\n\n        // Show the twipsy with the explanation\n        _$btnGoLive.twipsy(options).twipsy(\"show\");\n    }\n\n    /** Create the menu item \"Go Live\" */\n    function _setupGoLiveButton() {\n        if (!_$btnGoLive) {\n            _$btnGoLive = $(\"#toolbar-go-live\");\n            _$btnGoLive.click(function onGoLive() {\n                _handleGoLiveCommand();\n            });\n        }\n        LiveDevImpl.on(\"statusChange\", function statusChange(event, status, reason) {\n            // status starts at -1 (error), so add one when looking up name and style\n            // See the comments at the top of LiveDevelopment.js for details on the\n            // various status codes.\n            _setLabel(_$btnGoLive, null, _status[status + 1].style, _status[status + 1].tooltip);\n            _showStatusChangeReason(reason);\n            if (config.autoconnect) {\n                window.sessionStorage.setItem(\"live.enabled\", status === 3);\n            }\n        });\n\n        // Initialize tooltip for 'not connected' state\n        _setLabel(_$btnGoLive, null, _status[1].style, _status[1].tooltip);\n    }\n\n    /** Maintains state of the Live Preview menu item */\n    function _setupGoLiveMenu() {\n        LiveDevImpl.on(\"statusChange\", function statusChange(event, status) {\n            // Update the checkmark next to 'Live Preview' menu item\n            // Add checkmark when status is STATUS_ACTIVE; otherwise remove it\n            CommandManager.get(Commands.FILE_LIVE_FILE_PREVIEW).setChecked(status === LiveDevImpl.STATUS_ACTIVE);\n            CommandManager.get(Commands.FILE_LIVE_HIGHLIGHT).setEnabled(status === LiveDevImpl.STATUS_ACTIVE);\n        });\n    }\n\n    function _updateHighlightCheckmark() {\n        CommandManager.get(Commands.FILE_LIVE_HIGHLIGHT).setChecked(config.highlight);\n    }\n\n    function _handlePreviewHighlightCommand() {\n        config.highlight = !config.highlight;\n        _updateHighlightCheckmark();\n        if (config.highlight) {\n            LiveDevImpl.showHighlight();\n        } else {\n            LiveDevImpl.hideHighlight();\n        }\n        PreferencesManager.setViewState(\"livedev.highlight\", config.highlight);\n    }\n\n    /**\n     * Sets the MultiBrowserLiveDev implementation if multibrowser is truthy,\n     * keeps default LiveDevelopment implementation based on CDT otherwise.\n     * It also resets the listeners and UI elements.\n     */\n    function _setImplementation(multibrowser) {\n        if (multibrowser) {\n            // set implemenation\n            LiveDevImpl = MultiBrowserLiveDev;\n            // update styles for UI status\n            _status = [\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, style: \"warning\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, style: \"\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_PROGRESS1, style: \"info\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_CONNECTED, style: \"success\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_OUT_OF_SYNC, style: \"out-of-sync\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_SYNC_ERROR, style: \"sync-error\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_PROGRESS1, style: \"info\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_PROGRESS1, style: \"info\" }\n            ];\n        } else {\n            LiveDevImpl = LiveDevelopment;\n            _status = [\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, style: \"warning\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, style: \"\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_PROGRESS1, style: \"info\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_PROGRESS2, style: \"info\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_CONNECTED, style: \"success\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_OUT_OF_SYNC, style: \"out-of-sync\" },\n                { tooltip: Strings.LIVE_DEV_STATUS_TIP_SYNC_ERROR, style: \"sync-error\" }\n            ];\n        }\n        // setup status changes listeners for new implementation\n        _setupGoLiveButton();\n        _setupGoLiveMenu();\n        // toggle the menu\n        _toggleLivePreviewMultiBrowser(multibrowser);\n    }\n\n    /** Setup window references to useful LiveDevelopment modules */\n    function _setupDebugHelpers() {\n        window.ld = LiveDevelopment;\n        window.i = Inspector;\n        window.report = function report(params) { window.params = params; console.info(params); };\n    }\n\n    /** force reload the live preview */\n    function _handleReloadLivePreviewCommand() {\n        if (LiveDevelopment.status >= LiveDevelopment.STATUS_ACTIVE) {\n            LiveDevelopment.reload();\n        }\n    }\n\n    /** Initialize LiveDevelopment */\n    AppInit.appReady(function () {\n        params.parse();\n        config.remoteHighlight = prefs.get(PREF_REMOTEHIGHLIGHT);\n\n        Inspector.init(config);\n        LiveDevelopment.init(config);\n\n        // init experimental multi-browser implementation\n        // it can be enable by setting 'livedev.multibrowser' preference to true.\n        // It has to be initiated at this point in case of dynamically switching\n        // by changing the preference value.\n        MultiBrowserLiveDev.init(config);\n\n        _loadStyles();\n        _updateHighlightCheckmark();\n\n        _setImplementation(prefs.get(PREF_MULTIBROWSER));\n\n        if (config.debug) {\n            _setupDebugHelpers();\n        }\n\n        // trigger autoconnect\n        if (config.autoconnect &&\n                window.sessionStorage.getItem(\"live.enabled\") === \"true\" &&\n                DocumentManager.getCurrentDocument()) {\n            _handleGoLiveCommand();\n        }\n\n        // Redraw highlights when window gets focus. This ensures that the highlights\n        // will be in sync with any DOM changes that may have occurred.\n        $(window).focus(function () {\n            if (Inspector.connected() && config.highlight) {\n                LiveDevelopment.redrawHighlight();\n            }\n        });\n\n        multiBrowserPref\n            .on(\"change\", function () {\n                // Stop the current session if it is open and set implementation based on\n                // the pref value. We could start the new implementation immediately, but\n                // since the current document is potentially a user preferences file, Live\n                // Preview will not locate the html file to serve.\n                if (LiveDevImpl && LiveDevImpl.status >= LiveDevImpl.STATUS_ACTIVE) {\n                    LiveDevImpl.close()\n                        .done(function () {\n                            // status changes will now be listened by the new implementation\n                            LiveDevImpl.off(\"statusChange\");\n                            _setImplementation(prefs.get(PREF_MULTIBROWSER));\n                        });\n                } else {\n                    _setImplementation(prefs.get(PREF_MULTIBROWSER));\n                }\n            });\n        \n        remoteHighlightPref\n            .on(\"change\", function () {\n                config.remoteHighlight = prefs.get(PREF_REMOTEHIGHLIGHT);\n                       \n                if (LiveDevImpl && LiveDevImpl.status >= LiveDevImpl.STATUS_ACTIVE) {\n                    LiveDevImpl.agents.remote.call(\"updateConfig\",JSON.stringify(config));\n                }\n            });\n\n    });\n\n    // init prefs\n    PreferencesManager.stateManager.definePreference(\"livedev.highlight\", \"boolean\", true)\n        .on(\"change\", function () {\n            config.highlight = PreferencesManager.getViewState(\"livedev.highlight\");\n            _updateHighlightCheckmark();\n        });\n\n    config.highlight = PreferencesManager.getViewState(\"livedev.highlight\");\n\n    // init commands\n    CommandManager.register(Strings.CMD_LIVE_FILE_PREVIEW,  Commands.FILE_LIVE_FILE_PREVIEW, _handleGoLiveCommand);\n    CommandManager.register(Strings.CMD_LIVE_HIGHLIGHT, Commands.FILE_LIVE_HIGHLIGHT, _handlePreviewHighlightCommand);\n    CommandManager.register(Strings.CMD_RELOAD_LIVE_PREVIEW, Commands.CMD_RELOAD_LIVE_PREVIEW, _handleReloadLivePreviewCommand);\n    CommandManager.register(Strings.CMD_TOGGLE_LIVE_PREVIEW_MB_MODE, Commands.TOGGLE_LIVE_PREVIEW_MB_MODE, _toggleLivePreviewMultiBrowser);\n\n    CommandManager.get(Commands.FILE_LIVE_HIGHLIGHT).setEnabled(false);\n\n    // Export public functions\n});\n"
  },
  {
    "path": "src/LiveDevelopment/main.less",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n.CodeMirror {\n    .highlight {\n        background: #ecc;\n    }\n    .flash {\n       -webkit-animation: flash 1s;\n    }\n}\n  \n@-webkit-keyframes flash {\n    from {\n        background: #ecc;\n    }\n    to {\n        background: inherit;\n    }\n}"
  },
  {
    "path": "src/LiveDevelopment/transports/WebSocketTransport.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/** \n * This transport provides a WebSocket connection between Brackets and a live browser preview.\n * This is just a thin wrapper around the Node extension (WebSocketTransportDomain) that actually\n * provides the WebSocket server and handles the communication. We also rely on an injected script in\n * the browser for the other end of the transport.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils           = require(\"file/FileUtils\"),\n        NodeDomain          = require(\"utils/NodeDomain\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        HTMLInstrumentation = require(\"language/HTMLInstrumentation\");\n\n    // The node extension that actually provides the WebSocket server.\n\n    var domainPath = FileUtils.getNativeBracketsDirectoryPath() + \"/\" + FileUtils.getNativeModuleDirectoryPath(module) + \"/node/WebSocketTransportDomain\";\n\n    var WebSocketTransportDomain = new NodeDomain(\"webSocketTransport\", domainPath);\n\n    // Events\n\n    WebSocketTransportDomain.on(\"message\", function (obj, message) {\n        console.log(\"WebSocketTransport - event - message\" + \" - \" + message);\n        var editor = EditorManager.getActiveEditor(),\n            position = HTMLInstrumentation.getPositionFromTagId(editor, parseInt(message, 10));\n        if (position) {\n            editor.setCursorPos(position.line, position.ch, true);\n        }\n    });\n    \n    function createWebSocketServer(port) {\n        WebSocketTransportDomain.exec(\"start\", parseInt(port, 10));\n    }\n    \n    function closeWebSocketServer() {\n        WebSocketTransportDomain.exec(\"close\");\n    }\n    \n    exports.createWebSocketServer = createWebSocketServer;\n    exports.closeWebSocketServer  = closeWebSocketServer;\n});\n"
  },
  {
    "path": "src/LiveDevelopment/transports/node/WebSocketTransportDomain.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * WebSocketTransportDomain creates a websocket server for Live Preview\n * It receives the message containing tagID from the Remote Client(onClick)\n * and emits an event which is listened by WebSocketTransport which \n * brings the cursor to the tag corresponding to that particular tagID\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nvar WebSocketServer = require(\"ws\").Server;\n\n/**\n * @private\n * The WebSocket server we listen for incoming connections on.\n * @type {?WebSocketServer}\n */\nvar _wsServer;\n\n/**\n * @private\n * The Brackets domain manager for registering node extensions.\n * @type {?DomainManager}\n */\nvar _domainManager;\n\n/**\n * @private\n * Creates the WebSocketServer and handles incoming connections.\n */\nfunction _createServer(socketPort) {\n    if (!_wsServer) {\n        // TODO: make port configurable, or use random port\n        _wsServer = new WebSocketServer({port: socketPort});\n        _wsServer.on(\"connection\", function (ws) {\n            ws.on(\"message\", function (msg) {\n                console.log(\"WebSocketServer - received - \" + msg);\n                var msgObj;\n                try {\n                    msgObj = JSON.parse(msg);\n                } catch (e) {\n                    console.error(\"webSocketTransport: Error parsing message: \" + msg);\n                    return;\n                }\n\n                if (msgObj.type === \"message\") {\n                    _domainManager.emitEvent(\"webSocketTransport\", \"message\", msgObj.message);\n                } else {\n                    console.error(\"webSocketTransport: Got bad socket message type: \" + msg);\n                }\n            }).on(\"error\", function (e) {\n                console.error(\"webSocketTransport: Error on socket : \" + e);\n            }).on(\"close\", function () {\n                console.log(\"webSocketTransport closed\");\n            });\n        }).on(\"error\", function (e) {\n            console.error(\"webSocketTransport: Error on live preview server creation: \" + e);\n        });\n    }\n}\n\n/**\n * Initializes the socket server.\n * @param {number} port\n */\nfunction _cmdStart(port) {\n    _createServer(port);\n}\n\n/**\n * Kill the WebSocketServer\n */\nfunction _cmdClose() {\n    if (_wsServer) {\n        _wsServer.close();\n        _wsServer = null;\n    }\n}\n\n/**\n * Initializes the domain and registers commands.\n * @param {DomainManager} domainManager The DomainManager for the server\n */\nfunction init(domainManager) {\n    _domainManager = domainManager;\n    if (!domainManager.hasDomain(\"webSocketTransport\")) {\n        domainManager.registerDomain(\"webSocketTransport\", {major: 0, minor: 1});\n    }\n    \n    domainManager.registerEvent(\n        \"webSocketTransport\",\n        \"message\",\n        [\n            {\n                name: \"msg\",\n                type: \"string\",\n                description: \"JSON message from client page\"\n            }\n        ]\n    );\n    \n    domainManager.registerCommand(\n        \"webSocketTransport\",       // domain name\n        \"start\",                    // command name\n        _cmdStart,                  // command handler function\n        false,                      // this command is synchronous in Node\n        \"Creates the WS server\",\n        [\n            {\n                name: \"port\",\n                type: \"number\",\n                description: \"Port on which server needs to listen\"\n            }\n        ],\n        []\n    );\n    \n    domainManager.registerCommand(\n        \"webSocketTransport\",       // domain name\n        \"close\",                    // command name\n        _cmdClose,                  // command handler function\n        false,                      // this command is synchronous in Node\n        \"Kills the websocket server\",\n        []\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/base-config/keyboard.json",
    "content": "{\n    \"file.newDoc\":  [\n        \"Ctrl-N\"\n    ],\n    \"file.open\":  [\n        \"Ctrl-O\"\n    ],\n    \"file.close\":  [\n        \"Ctrl-W\"\n    ],\n    \"file.openFolder\": [\n        \"Ctrl-Alt-O\"\n    ],\n    \"file.close_all\":  [\n        \"Ctrl-Shift-W\"\n    ],\n    \"file.save\":  [\n        \"Ctrl-S\"\n    ],\n    \"file.saveAll\":  [\n        \"Ctrl-Alt-S\"\n    ],\n    \"file.saveAs\":  [\n        \"Ctrl-Shift-S\"\n    ],    \n    \"file.liveFilePreview\":  [\n        \"Ctrl-Alt-P\"\n    ],\n    \"file.reloadLivePreview\": [\n        {\n            \"key\": \"Ctrl-Shift-R\"\n        }\n    ],\n    \"file.previewHighlight\":  [\n        \"Ctrl-Shift-C\"\n    ],\n    \"file.quit\":  [\n        \"Ctrl-Q\"\n    ],\n    \"edit.undo\": [\n        \"Ctrl-Z\"\n    ],\n    \"edit.redo\": [\n        {\n            \"key\": \"Ctrl-Y\"\n        },\n        {\n            \"key\": \"Cmd-Shift-Z\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"edit.cut\": [\n        \"Ctrl-X\"\n    ],\n    \"edit.copy\": [\n        \"Ctrl-C\"\n    ],\n    \"edit.paste\": [\n        \"Ctrl-V\"\n    ],\n    \"edit.selectAll\":  [\n        \"Ctrl-A\"\n    ],\n    \"edit.selectLine\":  [\n        {\n            \"key\": \"Ctrl-L\"\n        },\n        {\n            \"key\": \"Ctrl-L\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"edit.splitSelIntoLines\": [\n        {\n           \"key\": \"Ctrl-Alt-L\"\n        },\n        {\n           \"key\":\"Ctrl-Shift-L\",\n           \"platform\": \"linux\"\n        }\n    ],\n    \"edit.addCursorToPrevLine\": [\n        {\n            \"key\": \"Shift-Alt-Up\",\n            \"displayKey\": \"Shift-Alt-↑\"\n        }\n    ],\n    \"edit.addCursorToNextLine\": [\n        {\n            \"key\": \"Shift-Alt-Down\",\n            \"displayKey\": \"Shift-Alt-↓\"\n        }\n    ],\n    \"edit.indent\":  [\n        {\n            \"key\": \"Ctrl-]\"\n        }\n    ],\n    \"edit.unindent\":  [\n        {\n            \"key\": \"Ctrl-[\"\n        }\n    ],\n    \"edit.duplicate\":  [\n        \"Ctrl-D\"\n    ],\n    \"edit.deletelines\":  [\n        \"Ctrl-Shift-D\"\n    ],\n    \"edit.lineUp\":  [\n        {\n            \"key\": \"Ctrl-Shift-Up\",\n            \"displayKey\": \"Ctrl-Shift-↑\"\n        },\n        {\n            \"key\": \"Cmd-Ctrl-Up\",\n            \"displayKey\": \"Cmd-Ctrl-↑\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"edit.lineDown\":  [\n        {\n            \"key\": \"Ctrl-Shift-Down\",\n            \"displayKey\": \"Ctrl-Shift-↓\"\n        },\n        {\n            \"key\": \"Cmd-Ctrl-Down\",\n            \"displayKey\": \"Cmd-Ctrl-↓\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"edit.openLineAbove\":  [\n        \"Ctrl-Shift-Enter\"\n    ],\n    \"edit.openLineBelow\":  [\n        \"Ctrl-Enter\"\n    ],\n    \"edit.lineComment\":  [\n        \"Ctrl-/\"\n    ],\n    \"edit.blockComment\":  [\n        {\n            \"key\": \"Ctrl-Shift-/\"\n        },\n        {\n            \"key\": \"Cmd-Opt-/\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"edit.showCodeHints\":  [\n        {\n            \"key\": \"Ctrl-Space\"\n        },\n        {\n            \"key\": \"Ctrl-Space\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"cmd.find\":  [\n        \"Ctrl-F\"\n    ],\n    \"cmd.findInFiles\":  [\n        \"Ctrl-Shift-F\"\n    ],\n    \"cmd.findAllReferences\":  [\n        \"Shift-F12\"\n    ],\n    \"cmd.replaceInFiles\":  [\n        {\n            \"key\": \"Ctrl-Shift-H\"\n        },\n        {\n            \"key\": \"Cmd-Opt-Shift-F\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"cmd.findNext\":  [\n        {\n            \"key\": \"F3\"\n        },\n        {\n            \"key\": \"Cmd-G\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"cmd.findPrevious\":  [\n        {\n            \"key\": \"Shift-F3\"\n        },\n        {\n            \"key\": \"Cmd-Shift-G\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"cmd.findAllAndSelect\": [\n        {\n            \"key\": \"Alt-F3\"\n        },\n        {\n            \"key\": \"Cmd-Ctrl-G\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"cmd.addNextMatch\": [\n        {\n            \"key\": \"Ctrl-B\"\n        }\n    ],\n    \"cmd.skipCurrentMatch\": [\n        {\n            \"key\": \"Ctrl-Shift-B\"\n        }\n    ],\n    \"cmd.replace\":  [\n        {\n            \"key\": \"Ctrl-H\"\n        },\n        {\n            \"key\": \"Cmd-Opt-F\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"view.toggleSidebar\":  [\n        {   \n            \"key\" : \"Ctrl-Alt-H\"\n        },\n        {\n            \"key\": \"Cmd-Shift-H\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"view.increaseFontSize\":  [\n        {\n            \"key\": \"Ctrl-=\",\n            \"displayKey\": \"Ctrl-+\"\n        },\n        {\n            \"key\": \"Ctrl-+\"\n        }\n    ],\n    \"view.decreaseFontSize\":  [\n        {\n            \"key\": \"Ctrl--\",\n            \"displayKey\": \"Ctrl-−\"\n        }\n    ],\n    \"view.restoreFontSize\":  [\n        \"Ctrl-0\"\n    ],\n    \"view.scrollLineUp\":  [\n        {\n            \"key\": \"Ctrl-Up\",\n            \"displayKey\": \"Ctrl-\\u2191\"\n        },\n        {\n            \"key\": \"Ctrl-Opt-Up\",\n            \"displayKey\": \"Ctrl-Opt-\\u2191\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"view.scrollLineDown\":  [\n        {\n            \"key\": \"Ctrl-Down\",\n            \"displayKey\": \"Ctrl-\\u2193\"\n        },\n        {\n            \"key\": \"Ctrl-Opt-Down\",\n            \"displayKey\": \"Ctrl-Opt-\\u2193\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"navigate.quickOpen\":  [\n        \"Ctrl-Shift-O\"\n    ],\n    \"navigate.gotoLine\":  [\n        {\n            \"key\": \"Ctrl-G\"\n        },\n        {\n            \"key\": \"Cmd-L\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"navigate.gotoDefinition\":  [\n        \"Ctrl-T\"\n    ],\n    \"navigate.gotoDefinitionInProject\":  [\n        \"Ctrl-Shift-T\"\n    ],\n    \"navigate.jumptoDefinition\":  [\n        \"Ctrl-J\"\n    ],\n    \"navigate.gotoFirstProblem\":  [\n        {\n            \"key\": \"F8\"\n        },\n        {\n            \"key\": \"Cmd-'\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"navigate.nextDocListOrder\":  [\n        {\n            \"key\": \"Ctrl-PageDown\"\n        }\n    ],\n    \"navigate.prevDocListOrder\":  [\n        {\n            \"key\": \"Ctrl-PageUp\"\n        }\n    ],\n    \"navigate.toggleQuickEdit\":  [\n        \"Ctrl-E\"\n    ],\n    \"navigate.toggleQuickDocs\":  [\n        \"Ctrl-K\"\n    ],\n    \"navigate.previousMatch\":  [\n        {\n            \"key\": \"Alt-Up\",\n            \"displayKey\": \"Alt-↑\"\n        }\n    ],\n    \"navigate.nextMatch\":  [\n        {\n            \"key\": \"Alt-Down\",\n            \"displayKey\": \"Alt-↓\"\n        }\n    ],\n    \"navigate.newRule\":  [\n        \"Ctrl-Alt-N\"\n    ],\n    \"file.rename\":  [\n        \"F2\"\n    ],\n    \"help.support\": [\n        \"F1\"\n    ]\n}\n"
  },
  {
    "path": "src/brackets.config.dev.json",
    "content": "{\n    \"healthDataServerURL\"        : \"https://healthdev.brackets.io/healthDataLog\",\n    \"analyticsDataServerURL\"     : \"https://cc-api-data-stage.adobe.io/ingest\",\n    \"serviceKey\"                 : \"brackets-service\",\n    \"environment\"                : \"stage\",\n    \"update_info_url\"            : \"https://s3.amazonaws.com/files.brackets.io/updates/prerelease/<locale>.json\",\n    \"notification_info_url\"      : \"https://s3.amazonaws.com/files.brackets.io/notifications/prerelease/<locale>.json\",\n    \"buildtype\"                  : \"dev\"\n}\n"
  },
  {
    "path": "src/brackets.config.dist.json",
    "content": "{\n    \"healthDataServerURL\"     : \"https://health.brackets.io/healthDataLog\",\n    \"analyticsDataServerURL\"  : \"https://cc-api-data.adobe.io/ingest\",\n    \"serviceKey\"              : \"brackets-service\",\n    \"environment\"             : \"production\",\n    \"update_info_url\"         : \"https://getupdates.brackets.io/getupdates?locale=<locale>\",\n    \"notification_info_url\"   : \"https://getupdates.brackets.io/getnotifications?locale=<locale>\",\n    \"buildtype\"               : \"production\"\n}\n"
  },
  {
    "path": "src/brackets.config.json",
    "content": "{\n    \"config\"                :\n    {\n        \"app_title\"                  : \"Brackets\",\n        \"app_name_about\"             : \"Brackets\",\n        \"about_icon\"                 : \"styles/images/brackets_icon.svg\",\n        \"how_to_use_url\"             : \"https://github.com/adobe/brackets/wiki/How-to-Use-Brackets\",\n        \"support_url\"                : \"https://github.com/adobe/brackets/wiki/Troubleshooting\",\n        \"suggest_feature_url\"        : \"https://github.com/adobe/brackets/wiki/Suggest-a-Feature\",\n        \"get_involved_url\"           : \"https://github.com/adobe/brackets/blob/master/CONTRIBUTING.md\",\n        \"glob_help_url\"              : \"https://github.com/adobe/brackets/wiki/Using-File-Filters\",\n        \"release_notes_url\"          : \"https://github.com/adobe/brackets/wiki/Release-Notes\",\n        \"homepage_url\"               : \"http://brackets.io\",\n        \"twitter_url\"                : \"https://twitter.com/brackets\",\n        \"troubleshoot_url\"           : \"https://github.com/adobe/brackets/wiki/Troubleshooting#wiki-livedev\",\n        \"twitter_name\"               : \"@brackets\",\n        \"contributors_url\"           : \"https://api.github.com/repos/adobe/brackets/contributors?per_page={0}&page={1}\",\n        \"extension_listing_url\"      : \"\",\n        \"extension_registry\"         : \"https://s3.amazonaws.com/extend.brackets/registry.json\",\n        \"extension_url\"              : \"https://s3.amazonaws.com/extend.brackets/{0}/{0}-{1}.zip\",\n        \"linting.enabled_by_default\" : true,\n        \"build_timestamp\"            : \"\"\n    }\n}\n"
  },
  {
    "path": "src/brackets.config.prerelease.json",
    "content": "{\n    \"healthDataServerURL\"     : \"https://health.brackets.io/healthDataLog\",\n    \"analyticsDataServerURL\"  : \"https://cc-api-data.adobe.io/ingest\",\n    \"serviceKey\"              : \"brackets-service\",\n    \"environment\"             : \"production\",\n    \"update_info_url\"         : \"https://s3.amazonaws.com/files.brackets.io/updates/prerelease/<locale>.json\",\n    \"notification_info_url\"   : \"https://s3.amazonaws.com/files.brackets.io/notifications/prerelease/<locale>.json\",\n    \"buildtype\"               : \"prerelease\"\n}\n"
  },
  {
    "path": "src/brackets.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global jQuery */\n\n// TODO: (issue #264) break out the definition of brackets into a separate module from the application controller logic\n\n/**\n * brackets is the root of the Brackets codebase. This file pulls in all other modules as\n * dependencies (or dependencies thereof), initializes the UI, and binds global menus & keyboard\n * shortcuts to their Commands.\n *\n * Unlike other modules, this one can be accessed without an explicit require() because it exposes\n * a global object, window.brackets.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent non-module scripts\n    require(\"widgets/bootstrap-dropdown\");\n    require(\"widgets/bootstrap-modal\");\n    require(\"widgets/bootstrap-twipsy-mod\");\n\n    // Load CodeMirror add-ons--these attach themselves to the CodeMirror module\n    require(\"thirdparty/CodeMirror/addon/edit/closebrackets\");\n    require(\"thirdparty/CodeMirror/addon/edit/closetag\");\n    require(\"thirdparty/CodeMirror/addon/edit/matchbrackets\");\n    require(\"thirdparty/CodeMirror/addon/edit/matchtags\");\n    require(\"thirdparty/CodeMirror/addon/fold/xml-fold\");\n    require(\"thirdparty/CodeMirror/addon/mode/multiplex\");\n    require(\"thirdparty/CodeMirror/addon/mode/overlay\");\n    require(\"thirdparty/CodeMirror/addon/mode/simple\");\n    require(\"thirdparty/CodeMirror/addon/scroll/scrollpastend\");\n    require(\"thirdparty/CodeMirror/addon/search/match-highlighter\");\n    require(\"thirdparty/CodeMirror/addon/search/searchcursor\");\n    require(\"thirdparty/CodeMirror/addon/selection/active-line\");\n    require(\"thirdparty/CodeMirror/addon/selection/mark-selection\");\n    require(\"thirdparty/CodeMirror/keymap/sublime\");\n\n    // Load dependent modules\n    var AppInit             = require(\"utils/AppInit\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        FileSyncManager     = require(\"project/FileSyncManager\"),\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        Strings             = require(\"strings\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        DefaultDialogs      = require(\"widgets/DefaultDialogs\"),\n        ExtensionLoader     = require(\"utils/ExtensionLoader\"),\n        Async               = require(\"utils/Async\"),\n        UpdateNotification  = require(\"utils/UpdateNotification\"),\n        UrlParams           = require(\"utils/UrlParams\").UrlParams,\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        DragAndDrop         = require(\"utils/DragAndDrop\"),\n        NativeApp           = require(\"utils/NativeApp\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\"),\n        ViewCommandHandlers = require(\"view/ViewCommandHandlers\"),\n        MainViewManager     = require(\"view/MainViewManager\");\n\n    var MainViewHTML        = require(\"text!htmlContent/main-view.html\");\n\n    // load modules for later use\n    require(\"utils/Global\");\n    require(\"editor/CSSInlineEditor\");\n    require(\"project/WorkingSetSort\");\n    require(\"search/QuickOpen\");\n    require(\"search/QuickOpenHelper\");\n    require(\"file/FileUtils\");\n    require(\"project/SidebarView\");\n    require(\"utils/Resizer\");\n    require(\"LiveDevelopment/main\");\n    require(\"utils/NodeConnection\");\n    require(\"utils/NodeDomain\");\n    require(\"utils/ColorUtils\");\n    require(\"view/ThemeManager\");\n    require(\"thirdparty/lodash\");\n    require(\"language/XMLUtils\");\n    require(\"language/JSONUtils\");\n    require(\"widgets/InlineMenu\");\n\n    // DEPRECATED: In future we want to remove the global CodeMirror, but for now we\n    // expose our required CodeMirror globally so as to avoid breaking extensions in the\n    // interim.\n    var CodeMirror = require(\"thirdparty/CodeMirror/lib/codemirror\");\n\n    Object.defineProperty(window, \"CodeMirror\", {\n        get: function () {\n            DeprecationWarning.deprecationWarning('Use brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\") instead of global CodeMirror.', true);\n            return CodeMirror;\n        }\n    });\n\n    // DEPRECATED: In future we want to remove the global Mustache, but for now we\n    // expose our required Mustache globally so as to avoid breaking extensions in the\n    // interim.\n    var Mustache = require(\"thirdparty/mustache/mustache\");\n\n    Object.defineProperty(window, \"Mustache\", {\n        get: function () {\n            DeprecationWarning.deprecationWarning('Use brackets.getModule(\"thirdparty/mustache/mustache\") instead of global Mustache.', true);\n            return Mustache;\n        }\n    });\n\n    // DEPRECATED: In future we want to remove the global PathUtils, but for now we\n    // expose our required PathUtils globally so as to avoid breaking extensions in the\n    // interim.\n    var PathUtils = require(\"thirdparty/path-utils/path-utils\");\n\n    Object.defineProperty(window, \"PathUtils\", {\n        get: function () {\n            DeprecationWarning.deprecationWarning('Use brackets.getModule(\"thirdparty/path-utils/path-utils\") instead of global PathUtils.', true);\n            return PathUtils;\n        }\n    });\n    \n    //load language features\n    require(\"features/ParameterHintsManager\");\n    require(\"features/JumpToDefManager\");\n\n    // Load modules that self-register and just need to get included in the main project\n    require(\"command/DefaultMenus\");\n    require(\"document/ChangedDocumentTracker\");\n    require(\"editor/EditorCommandHandlers\");\n    require(\"editor/EditorOptionHandlers\");\n    require(\"editor/EditorStatusBar\");\n    require(\"editor/ImageViewer\");\n    require(\"extensibility/InstallExtensionDialog\");\n    require(\"extensibility/ExtensionManagerDialog\");\n    require(\"help/HelpCommandHandlers\");\n    require(\"search/FindInFilesUI\");\n    require(\"search/FindReplace\");\n\n    //Load find References Feature Manager\n    require(\"features/FindReferencesManager\");\n\n    //Load common JS module\n    require(\"JSUtils/Session\");\n    require(\"JSUtils/ScopeManager\");\n\n    //load Language Tools Module\n    require(\"languageTools/PathConverters\");\n    require(\"languageTools/LanguageTools\");\n    require(\"languageTools/ClientLoader\");\n    require(\"languageTools/BracketsToNodeInterface\");\n    require(\"languageTools/DefaultProviders\");\n    require(\"languageTools/DefaultEventHandlers\");\n\n\n    PerfUtils.addMeasurement(\"brackets module dependencies resolved\");\n\n    // Local variables\n    var params = new UrlParams();\n\n    // read URL params\n    params.parse();\n\n\n    /**\n     * Setup test object\n     */\n    function _initTest() {\n        // TODO: (issue #265) Make sure the \"test\" object is not included in final builds\n        // All modules that need to be tested from the context of the application\n        // must to be added to this object. The unit tests cannot just pull\n        // in the modules since they would run in context of the unit test window,\n        // and would not have access to the app html/css.\n        brackets.test = {\n            CodeHintManager         : require(\"editor/CodeHintManager\"),\n            CodeInspection          : require(\"language/CodeInspection\"),\n            CommandManager          : require(\"command/CommandManager\"),\n            Commands                : require(\"command/Commands\"),\n            CSSUtils                : require(\"language/CSSUtils\"),\n            DefaultDialogs          : require(\"widgets/DefaultDialogs\"),\n            Dialogs                 : require(\"widgets/Dialogs\"),\n            DocumentCommandHandlers : require(\"document/DocumentCommandHandlers\"),\n            DocumentManager         : require(\"document/DocumentManager\"),\n            DocumentModule          : require(\"document/Document\"),\n            DOMAgent                : require(\"LiveDevelopment/Agents/DOMAgent\"),\n            DragAndDrop             : require(\"utils/DragAndDrop\"),\n            EditorManager           : require(\"editor/EditorManager\"),\n            ExtensionLoader         : require(\"utils/ExtensionLoader\"),\n            ExtensionUtils          : require(\"utils/ExtensionUtils\"),\n            File                    : require(\"filesystem/File\"),\n            FileFilters             : require(\"search/FileFilters\"),\n            FileSyncManager         : require(\"project/FileSyncManager\"),\n            FileSystem              : require(\"filesystem/FileSystem\"),\n            FileUtils               : require(\"file/FileUtils\"),\n            FileViewController      : require(\"project/FileViewController\"),\n            FindInFiles             : require(\"search/FindInFiles\"),\n            FindInFilesUI           : require(\"search/FindInFilesUI\"),\n            HTMLInstrumentation     : require(\"language/HTMLInstrumentation\"),\n            Inspector               : require(\"LiveDevelopment/Inspector/Inspector\"),\n            InstallExtensionDialog  : require(\"extensibility/InstallExtensionDialog\"),\n            JSUtils                 : require(\"language/JSUtils\"),\n            KeyBindingManager       : require(\"command/KeyBindingManager\"),\n            LanguageManager         : require(\"language/LanguageManager\"),\n            LiveDevelopment         : require(\"LiveDevelopment/LiveDevelopment\"),\n            LiveDevMultiBrowser     : require(\"LiveDevelopment/LiveDevMultiBrowser\"),\n            LiveDevServerManager    : require(\"LiveDevelopment/LiveDevServerManager\"),\n            MainViewFactory         : require(\"view/MainViewFactory\"),\n            MainViewManager         : require(\"view/MainViewManager\"),\n            Menus                   : require(\"command/Menus\"),\n            MultiRangeInlineEditor  : require(\"editor/MultiRangeInlineEditor\").MultiRangeInlineEditor,\n            NativeApp               : require(\"utils/NativeApp\"),\n            PerfUtils               : require(\"utils/PerfUtils\"),\n            PreferencesManager      : require(\"preferences/PreferencesManager\"),\n            ProjectManager          : require(\"project/ProjectManager\"),\n            RemoteAgent             : require(\"LiveDevelopment/Agents/RemoteAgent\"),\n            ScrollTrackMarkers      : require(\"search/ScrollTrackMarkers\"),\n            UpdateNotification      : require(\"utils/UpdateNotification\"),\n            WorkingSetView          : require(\"project/WorkingSetView\"),\n            doneLoading             : false\n        };\n\n        AppInit.appReady(function () {\n            brackets.test.doneLoading = true;\n        });\n    }\n\n    /**\n     * Setup Brackets\n     */\n    function _onReady() {\n        PerfUtils.addMeasurement(\"window.document Ready\");\n\n        // Let the user know Brackets doesn't run in a web browser yet\n        if (brackets.inBrowser) {\n            Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_ERROR,\n                Strings.ERROR_IN_BROWSER_TITLE,\n                Strings.ERROR_IN_BROWSER\n            );\n        }\n\n        brackets.app.getRemoteDebuggingPort(function (err, remote_debugging_port){\n            var InfoBar = require('widgets/infobar'),\n                StringUtils = require(\"utils/StringUtils\");\n            if ((!err) && remote_debugging_port && remote_debugging_port > 0) {\n                InfoBar.showInfoBar({\n                    type: \"warning\",\n                    title: `${Strings.REMOTE_DEBUGGING_ENABLED}${remote_debugging_port}`,\n                    description: \"\"\n                });\n            } else if (err) {\n                InfoBar.showInfoBar({\n                    type: \"error\",\n                    title: StringUtils.format(Strings.REMOTE_DEBUGGING_PORT_INVALID, err, 1024, 65534),\n                    description: \"\"\n                });\n            }\n        });\n        // Use quiet scrollbars if we aren't on Lion. If we're on Lion, only\n        // use native scroll bars when the mouse is not plugged in or when\n        // using the \"Always\" scroll bar setting.\n        var osxMatch = /Mac OS X 10\\D([\\d+])\\D/.exec(window.navigator.userAgent);\n        if (osxMatch && osxMatch[1] && Number(osxMatch[1]) >= 7) {\n            // test a scrolling div for scrollbars\n            var $testDiv = $(\"<div style='position:fixed;left:-50px;width:50px;height:50px;overflow:auto;'><div style='width:100px;height:100px;'/></div>\").appendTo(window.document.body);\n\n            if ($testDiv.outerWidth() === $testDiv.get(0).clientWidth) {\n                $(\".sidebar\").removeClass(\"quiet-scrollbars\");\n            }\n\n            $testDiv.remove();\n        }\n\n        // Load default languages and preferences\n        Async.waitForAll([LanguageManager.ready, PreferencesManager.ready]).always(function () {\n            // Load all extensions. This promise will complete even if one or more\n            // extensions fail to load.\n            var extensionPathOverride = params.get(\"extensions\");  // used by unit tests\n            var extensionLoaderPromise = ExtensionLoader.init(extensionPathOverride ? extensionPathOverride.split(\",\") : null);\n\n            // Load the initial project after extensions have loaded\n            extensionLoaderPromise.always(function () {\n               // Signal that extensions are loaded\n                AppInit._dispatchReady(AppInit.EXTENSIONS_LOADED);\n\n                // Finish UI initialization\n                ViewCommandHandlers.restoreFontSize();\n                var initialProjectPath = ProjectManager.getInitialProjectPath();\n                ProjectManager.openProject(initialProjectPath).always(function () {\n                    _initTest();\n\n                    // If this is the first launch, and we have an index.html file in the project folder (which should be\n                    // the samples folder on first launch), open it automatically. (We explicitly check for the\n                    // samples folder in case this is the first time we're launching Brackets after upgrading from\n                    // an old version that might not have set the \"afterFirstLaunch\" pref.)\n                    var deferred = new $.Deferred();\n\n                    if (!params.get(\"skipSampleProjectLoad\") && !PreferencesManager.getViewState(\"afterFirstLaunch\")) {\n                        PreferencesManager.setViewState(\"afterFirstLaunch\", \"true\");\n                        if (ProjectManager.isWelcomeProjectPath(initialProjectPath)) {\n                            FileSystem.resolve(initialProjectPath + \"index.html\", function (err, file) {\n                                if (!err) {\n                                    var promise = CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, { fullPath: file.fullPath });\n                                    promise.then(deferred.resolve, deferred.reject);\n                                } else {\n                                    deferred.reject();\n                                }\n                            });\n                        } else {\n                            deferred.resolve();\n                        }\n                    } else {\n                        deferred.resolve();\n                    }\n\n                    deferred.always(function () {\n                        // Signal that Brackets is loaded\n                        AppInit._dispatchReady(AppInit.APP_READY);\n\n                        PerfUtils.addMeasurement(\"Application Startup\");\n\n                        if (PreferencesManager._isUserScopeCorrupt()) {\n                            var userPrefFullPath = PreferencesManager.getUserPrefFile();\n                            // user scope can get corrupt only if the file exists, is readable,\n                            // but malformed. no need to check for its existance.\n                            var info = MainViewManager.findInAllWorkingSets(userPrefFullPath);\n                            var paneId;\n                            if (info.length) {\n                                paneId = info[0].paneId;\n                            }\n                            FileViewController.openFileAndAddToWorkingSet(userPrefFullPath, paneId)\n                                .done(function () {\n                                    Dialogs.showModalDialog(\n                                        DefaultDialogs.DIALOG_ID_ERROR,\n                                        Strings.ERROR_PREFS_CORRUPT_TITLE,\n                                        Strings.ERROR_PREFS_CORRUPT\n                                    ).done(function () {\n                                        // give the focus back to the editor with the pref file\n                                        MainViewManager.focusActivePane();\n                                    });\n                                });\n                        }\n\n                    });\n\n                    // See if any startup files were passed to the application\n                    if (brackets.app.getPendingFilesToOpen) {\n                        brackets.app.getPendingFilesToOpen(function (err, paths) {\n                            DragAndDrop.openDroppedFiles(paths);\n                        });\n                    }\n                });\n            });\n        });\n\n        // Check for updates\n        if (!brackets.inBrowser && !params.get(\"skipUpdateCheck\")) {\n            AppInit.appReady(function () {\n                // launches periodic checks for updates cca every 24 hours\n                UpdateNotification.launchAutomaticUpdate();\n            });\n        }\n    }\n\n    /**\n     * Setup event handlers prior to dispatching AppInit.HTML_READY\n     */\n    function _beforeHTMLReady() {\n        // Add the platform (mac, win or linux) to the body tag so we can have platform-specific CSS rules\n        $(\"body\").addClass(\"platform-\" + brackets.platform);\n\n        // Browser-hosted version may also have different CSS (e.g. since '#titlebar' is shown)\n        if (brackets.inBrowser) {\n            $(\"body\").addClass(\"in-browser\");\n        } else {\n            $(\"body\").addClass(\"in-appshell\");\n        }\n\n        // Enable/Disable HTML Menus\n        if (brackets.nativeMenus) {\n            $(\"body\").addClass(\"has-appshell-menus\");\n        } else {\n            // (issue #5310) workaround for bootstrap dropdown: prevent the menu item to grab\n            // the focus -- override jquery focus implementation for top-level menu items\n            (function () {\n                var defaultFocus = $.fn.focus;\n                $.fn.focus = function () {\n                    if (!this.hasClass(\"dropdown-toggle\")) {\n                        return defaultFocus.apply(this, arguments);\n                    }\n                };\n            }());\n        }\n\n        // Localize MainViewHTML and inject into <BODY> tag\n        $(\"body\").html(Mustache.render(MainViewHTML, { shouldAddAA: (brackets.platform === \"mac\"), Strings: Strings }));\n\n        // Update title\n        $(\"title\").text(brackets.config.app_title);\n\n        // Respond to dragging & dropping files/folders onto the window by opening them. If we don't respond\n        // to these events, the file would load in place of the Brackets UI\n        DragAndDrop.attachHandlers();\n\n        // TODO: (issue 269) to support IE, need to listen to document instead (and even then it may not work when focus is in an input field?)\n        $(window).focus(function () {\n            // This call to syncOpenDocuments() *should* be a no-op now that we have\n            // file watchers, but is still here as a safety net.\n            FileSyncManager.syncOpenDocuments();\n        });\n\n        // Prevent unhandled middle button clicks from triggering native behavior\n        // Example: activating AutoScroll (see #510)\n        $(\"html\").on(\"mousedown\", \".inline-widget\", function (e) {\n            if (e.button === 1) {\n                e.preventDefault();\n            }\n        });\n\n        // The .no-focus style is added to clickable elements that should\n        // not steal focus. Calling preventDefault() on mousedown prevents\n        // focus from going to the click target.\n        $(\"html\").on(\"mousedown\", \".no-focus\", function (e) {\n            // Text fields should always be focusable.\n            var $target = $(e.target),\n                isFormElement =\n                    $target.is(\"input\") ||\n                    $target.is(\"textarea\") ||\n                    $target.is(\"select\");\n\n            if (!isFormElement) {\n                e.preventDefault();\n            }\n        });\n\n        // Prevent clicks on any link from navigating to a different page (which could lose unsaved\n        // changes). We can't use a simple .on(\"click\", \"a\") because of http://bugs.jquery.com/ticket/3861:\n        // jQuery hides non-left clicks from such event handlers, yet middle-clicks still cause CEF to\n        // navigate. Also, a capture handler is more reliable than bubble.\n        window.document.body.addEventListener(\"click\", function (e) {\n            // Check parents too, in case link has inline formatting tags\n            var node = e.target, url;\n            while (node) {\n                if (node.tagName === \"A\") {\n                    url = node.getAttribute(\"href\");\n                    if (url && !url.match(/^#/)) {\n                        NativeApp.openURLInDefaultBrowser(url);\n                    }\n                    e.preventDefault();\n                    break;\n                }\n                node = node.parentElement;\n            }\n        }, true);\n\n        // Prevent extensions from using window.open() to insecurely load untrusted web content\n        var real_windowOpen = window.open;\n        window.open = function (url) {\n            // Allow file:// URLs, relative URLs (implicitly file: also), and about:blank\n            if (!url.match(/^file:\\/\\//) && !url.match(/^about:blank/) && url.indexOf(\":\") !== -1) {\n                throw new Error(\"Brackets-shell is not a secure general purpose web browser. Use NativeApp.openURLInDefaultBrowser() to open URLs in the user's main browser\");\n            }\n            return real_windowOpen.apply(window, arguments);\n        };\n\n        // jQuery patch to shim deprecated usage of $() on EventDispatchers\n        var DefaultCtor = jQuery.fn.init;\n        jQuery.fn.init = function (firstArg, secondArg) {\n            var jQObject = new DefaultCtor(firstArg, secondArg);\n\n            // Is this a Brackets EventDispatcher object? (not a DOM node or other object)\n            if (firstArg && firstArg._EventDispatcher) {\n                // Patch the jQ wrapper object so it calls EventDispatcher's APIs instead of jQuery's\n                jQObject.on  = firstArg.on.bind(firstArg);\n                jQObject.one = firstArg.one.bind(firstArg);\n                jQObject.off = firstArg.off.bind(firstArg);\n                // Don't offer legacy support for trigger()/triggerHandler() on core model objects; extensions\n                // shouldn't be doing that anyway since it's basically poking at private API\n\n                // Console warning, since $() is deprecated for EventDispatcher objects\n                // (pass true to only print once per caller, and index 4 since the extension caller is deeper in the stack than usual)\n                DeprecationWarning.deprecationWarning(\"Deprecated: Do not use $().on/off() on Brackets modules and model objects. Call on()/off() directly on the object without a $() wrapper.\", true, 4);\n            }\n            return jQObject;\n        };\n    }\n\n    // Wait for view state to load.\n    var viewStateTimer = PerfUtils.markStart(\"User viewstate loading\");\n    PreferencesManager._smUserScopeLoading.always(function () {\n        PerfUtils.addMeasurement(viewStateTimer);\n        // Dispatch htmlReady event\n        _beforeHTMLReady();\n        AppInit._dispatchReady(AppInit.HTML_READY);\n        $(window.document).ready(_onReady);\n    });\n});\n"
  },
  {
    "path": "src/command/CommandManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n /**\n  * Manages global application commands that can be called from menu items, key bindings, or subparts\n  * of the application.\n  *\n  * This module dispatches these event(s):\n  *    - commandRegistered  -- when a new command is registered\n  *    - beforeExecuteCommand -- before dispatching a command\n  */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher = require(\"utils/EventDispatcher\");\n\n\n    /**\n     * Map of all registered global commands\n     * @type {Object.<commandID: string, Command>}\n     */\n    var _commands = {};\n\n    /**\n     * Temporary copy of commands map for restoring after testing\n     * TODO (issue #1039): implement separate require contexts for unit tests\n     * @type {Object.<commandID: string, Command>}\n     */\n    var _commandsOriginal = {};\n\n    /**\n     * Events:\n     * - enabledStateChange\n     * - checkedStateChange\n     * - keyBindingAdded\n     * - keyBindingRemoved\n     *\n     * @constructor\n     * @private\n     * @param {string} name - text that will be displayed in the UI to represent command\n     * @param {string} id\n     * @param {function} commandFn - the function that is called when the command is executed.\n     *\n     * TODO: where should this be triggered, The Command or Exports?\n     */\n    function Command(name, id, commandFn) {\n        this._name = name;\n        this._id = id;\n        this._commandFn = commandFn;\n        this._checked = undefined;\n        this._enabled = true;\n    }\n    EventDispatcher.makeEventDispatcher(Command.prototype);\n\n    /**\n     * Get command id\n     * @return {string}\n     */\n    Command.prototype.getID = function () {\n        return this._id;\n    };\n\n    /**\n     * Executes the command. Additional arguments are passed to the executing function\n     *\n     * @return {$.Promise} a jQuery promise that will be resolved when the command completes.\n     */\n    Command.prototype.execute = function () {\n        if (!this._enabled) {\n            return (new $.Deferred()).reject().promise();\n        }\n\n        var result = this._commandFn.apply(this, arguments);\n        if (!result) {\n            // If command does not return a promise, assume that it handled the\n            // command and return a resolved promise\n            return (new $.Deferred()).resolve().promise();\n        } else {\n            return result;\n        }\n    };\n\n    /**\n     * Is command enabled?\n     * @return {boolean}\n     */\n    Command.prototype.getEnabled = function () {\n        return this._enabled;\n    };\n\n    /**\n     * Sets enabled state of Command and dispatches \"enabledStateChange\"\n     * when the enabled state changes.\n     * @param {boolean} enabled\n     */\n    Command.prototype.setEnabled = function (enabled) {\n        var changed = this._enabled !== enabled;\n        this._enabled = enabled;\n\n        if (changed) {\n            this.trigger(\"enabledStateChange\");\n        }\n    };\n\n    /**\n     * Sets enabled state of Command and dispatches \"checkedStateChange\"\n     * when the enabled state changes.\n     * @param {boolean} checked\n     */\n    Command.prototype.setChecked = function (checked) {\n        var changed = this._checked !== checked;\n        this._checked = checked;\n\n        if (changed) {\n            this.trigger(\"checkedStateChange\");\n        }\n    };\n\n    /**\n     * Is command checked?\n     * @return {boolean}\n     */\n    Command.prototype.getChecked = function () {\n        return this._checked;\n    };\n\n    /**\n     * Sets the name of the Command and dispatches \"nameChange\" so that\n     * UI that reflects the command name can update.\n     *\n     * Note, a Command name can appear in either HTML or native UI\n     * so HTML tags should not be used. To add a Unicode character,\n     * use \\uXXXX instead of an HTML entity.\n     *\n     * @param {string} name\n     */\n    Command.prototype.setName = function (name) {\n        var changed = this._name !== name;\n        this._name = name;\n\n        if (changed) {\n            this.trigger(\"nameChange\");\n        }\n    };\n\n    /**\n     * Get command name\n     * @return {string}\n     */\n    Command.prototype.getName = function () {\n        return this._name;\n    };\n\n\n\n    /**\n     * Registers a global command.\n     * @param {string} name - text that will be displayed in the UI to represent command\n     * @param {string} id - unique identifier for command.\n     *      Core commands in Brackets use a simple command title as an id, for example \"open.file\".\n     *      Extensions should use the following format: \"author.myextension.mycommandname\".\n     *      For example, \"lschmitt.csswizard.format.css\".\n     * @param {function(...)} commandFn - the function to call when the command is executed. Any arguments passed to\n     *     execute() (after the id) are passed as arguments to the function. If the function is asynchronous,\n     *     it must return a jQuery promise that is resolved when the command completes. Otherwise, the\n     *     CommandManager will assume it is synchronous, and return a promise that is already resolved.\n     * @return {?Command}\n     */\n    function register(name, id, commandFn) {\n        if (_commands[id]) {\n            console.log(\"Attempting to register an already-registered command: \" + id);\n            return null;\n        }\n        if (!name || !id || !commandFn) {\n            console.error(\"Attempting to register a command with a missing name, id, or command function:\" + name + \" \" + id);\n            return null;\n        }\n\n        var command = new Command(name, id, commandFn);\n        _commands[id] = command;\n\n        exports.trigger(\"commandRegistered\", command);\n\n        return command;\n    }\n\n    /**\n     * Registers a global internal only command.\n     * @param {string} id - unique identifier for command.\n     *      Core commands in Brackets use a simple command title as an id, for example \"app.abort_quit\".\n     *      Extensions should use the following format: \"author.myextension.mycommandname\".\n     *      For example, \"lschmitt.csswizard.format.css\".\n     * @param {function(...)} commandFn - the function to call when the command is executed. Any arguments passed to\n     *     execute() (after the id) are passed as arguments to the function. If the function is asynchronous,\n     *     it must return a jQuery promise that is resolved when the command completes. Otherwise, the\n     *     CommandManager will assume it is synchronous, and return a promise that is already resolved.\n     * @return {?Command}\n     */\n    function registerInternal(id, commandFn) {\n        if (_commands[id]) {\n            console.log(\"Attempting to register an already-registered command: \" + id);\n            return null;\n        }\n        if (!id || !commandFn) {\n            console.error(\"Attempting to register an internal command with a missing id, or command function: \" + id);\n            return null;\n        }\n\n        var command = new Command(null, id, commandFn);\n        _commands[id] = command;\n\n        exports.trigger(\"commandRegistered\", command);\n\n        return command;\n    }\n\n    /**\n     * Clear all commands for unit testing, but first make copy of commands so that\n     * they can be restored afterward\n     */\n    function _testReset() {\n        _commandsOriginal = _commands;\n        _commands = {};\n    }\n\n    /**\n     * Restore original commands after test and release copy\n     */\n    function _testRestore() {\n        _commands = _commandsOriginal;\n        _commandsOriginal = {};\n    }\n\n    /**\n     * Retrieves a Command object by id\n     * @param {string} id\n     * @return {Command}\n     */\n    function get(id) {\n        return _commands[id];\n    }\n\n    /**\n     * Returns the ids of all registered commands\n     * @return {Array.<string>}\n     */\n    function getAll() {\n        return Object.keys(_commands);\n    }\n\n    /**\n     * Looks up and runs a global command. Additional arguments are passed to the command.\n     *\n     * @param {string} id The ID of the command to run.\n     * @return {$.Promise} a jQuery promise that will be resolved when the command completes.\n     */\n    function execute(id) {\n        var command = _commands[id];\n\n        if (command) {\n            try {\n                exports.trigger(\"beforeExecuteCommand\", id);\n            } catch (err) {\n                console.error(err);\n            }\n\n            return command.execute.apply(command, Array.prototype.slice.call(arguments, 1));\n        } else {\n            return (new $.Deferred()).reject().promise();\n        }\n    }\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Define public API\n    exports.register            = register;\n    exports.registerInternal    = registerInternal;\n    exports.execute             = execute;\n    exports.get                 = get;\n    exports.getAll              = getAll;\n    exports._testReset          = _testReset;\n    exports._testRestore        = _testRestore;\n});\n"
  },
  {
    "path": "src/command/Commands.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DeprecationWarning = require(\"utils/DeprecationWarning\");\n\n    /**\n     * List of constants for global command IDs.\n     */\n\n    // FILE\n    exports.FILE_NEW_UNTITLED           = \"file.newDoc\";                // DocumentCommandHandlers.js   handleFileNew()\n    exports.FILE_NEW                    = \"file.newFile\";               // DocumentCommandHandlers.js   handleFileNewInProject()\n    exports.FILE_NEW_FOLDER             = \"file.newFolder\";             // DocumentCommandHandlers.js   handleNewFolderInProject()\n    exports.FILE_OPEN                   = \"file.open\";                  // DocumentCommandHandlers.js   handleDocumentOpen()\n    exports.FILE_OPEN_FOLDER            = \"file.openFolder\";            // ProjectManager.js            openProject()\n    exports.FILE_SAVE                   = \"file.save\";                  // DocumentCommandHandlers.js   handleFileSave()\n    exports.FILE_SAVE_ALL               = \"file.saveAll\";               // DocumentCommandHandlers.js   handleFileSaveAll()\n    exports.FILE_SAVE_AS                = \"file.saveAs\";                // DocumentCommandHandlers.js   handleFileSaveAs()\n    exports.FILE_CLOSE                  = \"file.close\";                 // DocumentCommandHandlers.js   handleFileClose()\n    exports.FILE_CLOSE_ALL              = \"file.close_all\";             // DocumentCommandHandlers.js   handleFileCloseAll()\n    exports.FILE_CLOSE_LIST             = \"file.close_list\";            // DocumentCommandHandlers.js   handleFileCloseList()\n    exports.FILE_OPEN_DROPPED_FILES     = \"file.openDroppedFiles\";      // DragAndDrop.js               openDroppedFiles()\n    exports.FILE_LIVE_FILE_PREVIEW      = \"file.liveFilePreview\";       // LiveDevelopment/main.js      _handleGoLiveCommand()\n    exports.TOGGLE_LIVE_PREVIEW_MB_MODE = \"file.toggleLivePreviewMB\";   // LiveDevelopment/main.js      _toggleLivePreviewMultiBrowser()\n    exports.CMD_RELOAD_LIVE_PREVIEW     = \"file.reloadLivePreview\";     // LiveDevelopment/main.js      _handleReloadLivePreviewCommand()\n    exports.FILE_LIVE_HIGHLIGHT         = \"file.previewHighlight\";      // LiveDevelopment/main.js      _handlePreviewHighlightCommand()\n    exports.FILE_PROJECT_SETTINGS       = \"file.projectSettings\";       // ProjectManager.js            _projectSettings()\n    exports.FILE_RENAME                 = \"file.rename\";                // DocumentCommandHandlers.js   handleFileRename()\n    exports.FILE_DELETE                 = \"file.delete\";                // DocumentCommandHandlers.js   handleFileDelete()\n    exports.FILE_EXTENSION_MANAGER      = \"file.extensionManager\";      // ExtensionManagerDialog.js    _showDialog()\n    exports.FILE_REFRESH                = \"file.refresh\";               // ProjectManager.js            refreshFileTree()\n    exports.FILE_OPEN_PREFERENCES       = \"file.openPreferences\";       // PreferencesManager.js        _handleOpenPreferences()\n    exports.FILE_OPEN_KEYMAP            = \"file.openKeyMap\";            // KeyBindingManager.js         _openUserKeyMap()\n\n    // File shell callbacks - string must MATCH string in native code (appshell/command_callbacks.h)\n    exports.FILE_CLOSE_WINDOW           = \"file.close_window\";          // DocumentCommandHandlers.js   handleFileCloseWindow()\n    exports.FILE_QUIT                   = \"file.quit\";                  // DocumentCommandHandlers.js   handleFileQuit()\n\n    // EDIT\n    // File shell callbacks - string must MATCH string in native code (appshell/command_callbacks.h)\n    exports.EDIT_UNDO                   = \"edit.undo\";                  // EditorCommandHandlers.js     handleUndo()\n    exports.EDIT_REDO                   = \"edit.redo\";                  // EditorCommandHandlers.js     handleRedo()\n    exports.EDIT_CUT                    = \"edit.cut\";                   // EditorCommandHandlers.js     ignoreCommand()\n    exports.EDIT_COPY                   = \"edit.copy\";                  // EditorCommandHandlers.js     ignoreCommand()\n    exports.EDIT_PASTE                  = \"edit.paste\";                 // EditorCommandHandlers.js     ignoreCommand()\n    exports.EDIT_SELECT_ALL             = \"edit.selectAll\";             // EditorCommandHandlers.js     _handleSelectAll()\n\n    exports.EDIT_SELECT_LINE            = \"edit.selectLine\";            // EditorCommandHandlers.js     selectLine()\n    exports.EDIT_SPLIT_SEL_INTO_LINES   = \"edit.splitSelIntoLines\";     // EditorCommandHandlers.js     splitSelIntoLines()\n    exports.EDIT_ADD_CUR_TO_NEXT_LINE   = \"edit.addCursorToNextLine\";   // EditorCommandHandlers.js     addCursorToNextLine()\n    exports.EDIT_ADD_CUR_TO_PREV_LINE   = \"edit.addCursorToPrevLine\";   // EditorCommandHandlers.js     addCursorToPrevLine()\n    exports.EDIT_INDENT                 = \"edit.indent\";                // EditorCommandHandlers.js     indentText()\n    exports.EDIT_UNINDENT               = \"edit.unindent\";              // EditorCommandHandlers.js     unindentText()\n    exports.EDIT_DUPLICATE              = \"edit.duplicate\";             // EditorCommandHandlers.js     duplicateText()\n    exports.EDIT_DELETE_LINES           = \"edit.deletelines\";           // EditorCommandHandlers.js     deleteCurrentLines()\n    exports.EDIT_LINE_COMMENT           = \"edit.lineComment\";           // EditorCommandHandlers.js     lineComment()\n    exports.EDIT_BLOCK_COMMENT          = \"edit.blockComment\";          // EditorCommandHandlers.js     blockComment()\n    exports.EDIT_LINE_UP                = \"edit.lineUp\";                // EditorCommandHandlers.js     moveLineUp()\n    exports.EDIT_LINE_DOWN              = \"edit.lineDown\";              // EditorCommandHandlers.js     moveLineDown()\n    exports.EDIT_OPEN_LINE_ABOVE        = \"edit.openLineAbove\";         // EditorCommandHandlers.js     openLineAbove()\n    exports.EDIT_OPEN_LINE_BELOW        = \"edit.openLineBelow\";         // EditorCommandHandlers.js     openLineBelow()\n    exports.TOGGLE_CLOSE_BRACKETS       = \"edit.autoCloseBrackets\";     // EditorOptionHandlers.js      _getToggler()\n    exports.SHOW_CODE_HINTS             = \"edit.showCodeHints\";         // CodeHintManager.js           _startNewSession()\n\n    // FIND\n    exports.CMD_FIND                    = \"cmd.find\";                   // FindReplace.js               _launchFind()\n    exports.CMD_FIND_IN_FILES           = \"cmd.findInFiles\";            // FindInFilesUI.js             _showFindBar()\n    exports.CMD_FIND_IN_SUBTREE         = \"cmd.findInSubtree\";          // FindInFilesUI.js             _showFindBarForSubtree()\n    exports.CMD_FIND_NEXT               = \"cmd.findNext\";               // FindReplace.js               _findNext()\n    exports.CMD_FIND_PREVIOUS           = \"cmd.findPrevious\";           // FindReplace.js               _findPrevious()\n    exports.CMD_FIND_ALL_AND_SELECT     = \"cmd.findAllAndSelect\";       // FindReplace.js               _findAllAndSelect()\n    exports.CMD_ADD_NEXT_MATCH          = \"cmd.addNextMatch\";           // FindReplace.js               _expandAndAddNextToSelection()\n    exports.CMD_SKIP_CURRENT_MATCH      = \"cmd.skipCurrentMatch\";       // FindReplace.js               _skipCurrentMatch()\n    exports.CMD_REPLACE                 = \"cmd.replace\";                // FindReplace.js               _replace()\n    exports.CMD_REPLACE_IN_FILES        = \"cmd.replaceInFiles\";         // FindInFilesUI.js             _showReplaceBar()\n    exports.CMD_REPLACE_IN_SUBTREE      = \"cmd.replaceInSubtree\";       // FindInFilesUI.js             _showReplaceBarForSubtree()\n    exports.CMD_FIND_ALL_REFERENCES     = \"cmd.findAllReferences\";      // findReferencesManager.js     _openReferencesPanel()\n\n    // VIEW\n    exports.CMD_THEMES_OPEN_SETTINGS    = \"view.themesOpenSetting\";     // MenuCommands.js              Settings.open()\n    exports.VIEW_HIDE_SIDEBAR           = \"view.toggleSidebar\";         // SidebarView.js               toggle()\n    exports.VIEW_INCREASE_FONT_SIZE     = \"view.increaseFontSize\";      // ViewCommandHandlers.js       _handleIncreaseFontSize()\n    exports.VIEW_DECREASE_FONT_SIZE     = \"view.decreaseFontSize\";      // ViewCommandHandlers.js       _handleDecreaseFontSize()\n    exports.VIEW_RESTORE_FONT_SIZE      = \"view.restoreFontSize\";       // ViewCommandHandlers.js       _handleRestoreFontSize()\n    exports.VIEW_SCROLL_LINE_UP         = \"view.scrollLineUp\";          // ViewCommandHandlers.js       _handleScrollLineUp()\n    exports.VIEW_SCROLL_LINE_DOWN       = \"view.scrollLineDown\";        // ViewCommandHandlers.js       _handleScrollLineDown()\n    exports.VIEW_TOGGLE_INSPECTION      = \"view.toggleCodeInspection\";  // CodeInspection.js            toggleEnabled()\n    exports.TOGGLE_LINE_NUMBERS         = \"view.toggleLineNumbers\";     // EditorOptionHandlers.js      _getToggler()\n    exports.TOGGLE_ACTIVE_LINE          = \"view.toggleActiveLine\";      // EditorOptionHandlers.js      _getToggler()\n    exports.TOGGLE_WORD_WRAP            = \"view.toggleWordWrap\";        // EditorOptionHandlers.js      _getToggler()\n    exports.TOGGLE_SEARCH_AUTOHIDE      = \"view.toggleSearchAutoHide\";  // EditorOptionHandlers.js      _getToggler() \n\n    exports.CMD_OPEN                        = \"cmd.open\";\n    exports.CMD_ADD_TO_WORKINGSET_AND_OPEN  = \"cmd.addToWorkingSetAndOpen\";          // DocumentCommandHandlers.js   handleOpenDocumentInNewPane()\n\n    // NAVIGATE\n    exports.NAVIGATE_NEXT_DOC           = \"navigate.nextDoc\";           // DocumentCommandHandlers.js   handleGoNextDoc()\n    exports.NAVIGATE_PREV_DOC           = \"navigate.prevDoc\";           // DocumentCommandHandlers.js   handleGoPrevDoc()\n    exports.NAVIGATE_NEXT_DOC_LIST_ORDER    = \"navigate.nextDocListOrder\";           // DocumentCommandHandlers.js   handleGoNextDocListOrder()\n    exports.NAVIGATE_PREV_DOC_LIST_ORDER    = \"navigate.prevDocListOrder\";           // DocumentCommandHandlers.js   handleGoPrevDocListOrder()\n    exports.NAVIGATE_SHOW_IN_FILE_TREE  = \"navigate.showInFileTree\";    // DocumentCommandHandlers.js   handleShowInTree()\n    exports.NAVIGATE_SHOW_IN_OS         = \"navigate.showInOS\";          // DocumentCommandHandlers.js   handleShowInOS()\n    exports.NAVIGATE_QUICK_OPEN         = \"navigate.quickOpen\";         // QuickOpen.js                 doFileSearch()\n    exports.NAVIGATE_JUMPTO_DEFINITION  = \"navigate.jumptoDefinition\";  // JumpToDefManager.js             _doJumpToDef()\n    exports.NAVIGATE_GOTO_DEFINITION    = \"navigate.gotoDefinition\";    // QuickOpen.js                 doDefinitionSearch()\n    exports.NAVIGATE_GOTO_DEFINITION_PROJECT = \"navigate.gotoDefinitionInProject\";    // QuickOpen.js                 doDefinitionSearchInProject()\n    exports.NAVIGATE_GOTO_LINE          = \"navigate.gotoLine\";          // QuickOpen.js                 doGotoLine()\n    exports.NAVIGATE_GOTO_FIRST_PROBLEM = \"navigate.gotoFirstProblem\";  // CodeInspection.js            handleGotoFirstProblem()\n    exports.TOGGLE_QUICK_EDIT           = \"navigate.toggleQuickEdit\";   // EditorManager.js             _toggleInlineWidget()\n    exports.TOGGLE_QUICK_DOCS           = \"navigate.toggleQuickDocs\";   // EditorManager.js             _toggleInlineWidget()\n    exports.QUICK_EDIT_NEXT_MATCH       = \"navigate.nextMatch\";         // MultiRangeInlineEditor.js    _nextRange()\n    exports.QUICK_EDIT_PREV_MATCH       = \"navigate.previousMatch\";     // MultiRangeInlineEditor.js    _previousRange()\n    exports.CSS_QUICK_EDIT_NEW_RULE     = \"navigate.newRule\";           // CSSInlineEditor.js           _handleNewRule()\n\n    // HELP\n    exports.HELP_CHECK_FOR_UPDATE       = \"help.checkForUpdate\";        // HelpCommandHandlers.js       _handleCheckForUpdates()\n    exports.HELP_HOW_TO_USE_BRACKETS    = \"help.howToUseBrackets\";      // HelpCommandHandlers.js       _handleLinkMenuItem()\n    exports.HELP_SUPPORT                = \"help.support\";               // HelpCommandHandlers.js       _handleLinkMenuItem()\n    exports.HELP_SUGGEST                = \"help.suggest\";               // HelpCommandHandlers.js       _handleLinkMenuItem()\n    exports.HELP_RELEASE_NOTES          = \"help.releaseNotes\";          // HelpCommandHandlers.js       _handleLinkMenuItem()\n    exports.HELP_GET_INVOLVED           = \"help.getInvolved\";           // HelpCommandHandlers.js       _handleLinkMenuItem()\n    exports.HELP_SHOW_EXT_FOLDER        = \"help.showExtensionsFolder\";  // HelpCommandHandlers.js       _handleShowExtensionsFolder()\n    exports.HELP_HOMEPAGE               = \"help.homepage\";              // HelpCommandHandlers.js       _handleLinkMenuItem()\n    exports.HELP_TWITTER                = \"help.twitter\";               // HelpCommandHandlers.js       _handleLinkMenuItem()\n\n    // Working Set Configuration\n    exports.CMD_WORKINGSET_SORT_BY_ADDED  = \"cmd.sortWorkingSetByAdded\";     // WorkingSetSort.js       _handleSort()\n    exports.CMD_WORKINGSET_SORT_BY_NAME   = \"cmd.sortWorkingSetByName\";      // WorkingSetSort.js       _handleSort()\n    exports.CMD_WORKINGSET_SORT_BY_TYPE   = \"cmd.sortWorkingSetByType\";      // WorkingSetSort.js       _handleSort()\n    exports.CMD_WORKING_SORT_TOGGLE_AUTO  = \"cmd.sortWorkingSetToggleAuto\";  // WorkingSetSort.js       _handleToggleAutoSort()\n\n    // Split View\n    exports.CMD_SPLITVIEW_NONE          = \"cmd.splitViewNone\";          // SidebarView.js               _handleSplitNone()\n    exports.CMD_SPLITVIEW_VERTICAL      = \"cmd.splitViewVertical\";      // SidebarView.js               _handleSplitVertical()\n    exports.CMD_SPLITVIEW_HORIZONTAL    = \"cmd.splitViewHorizontal\";    // SidebarView.js               _handleSplitHorizontal()\n    exports.CMD_SWITCH_PANE_FOCUS       = \"cmd.switchPaneFocus\";        // MainViewManager.js           _switchPaneFocus()\n\n    // File shell callbacks - string must MATCH string in native code (appshell/command_callbacks.h)\n    exports.HELP_ABOUT                  = \"help.about\";                 // HelpCommandHandlers.js       _handleAboutDialog()\n\n    // APP\n    exports.APP_RELOAD                  = \"app.reload\";                 // DocumentCommandHandlers.js   handleReload()\n    exports.APP_RELOAD_WITHOUT_EXTS     = \"app.reload_without_exts\";    // DocumentCommandHandlers.js   handleReloadWithoutExts()\n\n    // File shell callbacks - string must MATCH string in native code (appshell/command_callbacks.h)\n    exports.APP_ABORT_QUIT              = \"app.abort_quit\";             // DocumentCommandHandlers.js   handleAbortQuit()\n    exports.APP_BEFORE_MENUPOPUP        = \"app.before_menupopup\";       // DocumentCommandHandlers.js   handleBeforeMenuPopup()\n\n    // ADD_TO_WORKING_SET is deprectated but we need a handler for it because the new command doesn't return the same result as the legacy command\n    exports.FILE_ADD_TO_WORKING_SET     = \"file.addToWorkingSet\";       // Deprecated through DocumentCommandHandlers.js handleFileAddToWorkingSet\n\n    // Show or Hide sidebar\n    exports.HIDE_SIDEBAR                = \"view.hideSidebar\";           // SidebarView.js               hide()\n    exports.SHOW_SIDEBAR                = \"view.showSidebar\";           // SidebarView.js               show()\n\n    // DEPRECATED: Working Set Commands\n    DeprecationWarning.deprecateConstant(exports, \"SORT_WORKINGSET_BY_ADDED\",   \"CMD_WORKINGSET_SORT_BY_ADDED\");\n    DeprecationWarning.deprecateConstant(exports, \"SORT_WORKINGSET_BY_NAME\",    \"CMD_WORKINGSET_SORT_BY_NAME\");\n    DeprecationWarning.deprecateConstant(exports, \"SORT_WORKINGSET_BY_TYPE\",    \"CMD_WORKINGSET_SORT_BY_TYPE\");\n    DeprecationWarning.deprecateConstant(exports, \"SORT_WORKINGSET_AUTO\",       \"CMD_WORKING_SORT_TOGGLE_AUTO\");\n});\n\n"
  },
  {
    "path": "src/command/DefaultMenus.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Initializes the default brackets menu items.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit         = require(\"utils/AppInit\"),\n        Commands        = require(\"command/Commands\"),\n        Menus           = require(\"command/Menus\"),\n        Strings         = require(\"strings\"),\n        MainViewManager = require(\"view/MainViewManager\"),\n        CommandManager  = require(\"command/CommandManager\");\n\n    /**\n     * Disables menu items present in items if enabled is true.\n     * enabled is true if file is saved and present on user system.\n     * @param {boolean} enabled\n     * @param {array} items\n     */\n    function _setContextMenuItemsVisible(enabled, items) {\n        items.forEach(function (item) {\n            CommandManager.get(item).setEnabled(enabled);\n        });\n    }\n    \n    /**\n     * Checks if file saved and present on system and\n     * disables menu items accordingly\n     */\n    function _setMenuItemsVisible() {\n        var file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);\n        if (file) {\n            file.exists(function (err, isPresent) {\n                if (err) {\n                    return err;\n                }\n                _setContextMenuItemsVisible(isPresent, [Commands.FILE_RENAME, Commands.NAVIGATE_SHOW_IN_FILE_TREE, Commands.NAVIGATE_SHOW_IN_OS]);   \n            });\n        }\n    }\n\n    AppInit.htmlReady(function () {\n        /*\n         * File menu\n         */\n        var menu;\n        menu = Menus.addMenu(Strings.FILE_MENU, Menus.AppMenuBar.FILE_MENU);\n        menu.addMenuItem(Commands.FILE_NEW_UNTITLED);\n        menu.addMenuItem(Commands.FILE_OPEN);\n        menu.addMenuItem(Commands.FILE_OPEN_FOLDER);\n        menu.addMenuItem(Commands.FILE_CLOSE);\n        menu.addMenuItem(Commands.FILE_CLOSE_ALL);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_SAVE);\n        menu.addMenuItem(Commands.FILE_SAVE_ALL);\n        menu.addMenuItem(Commands.FILE_SAVE_AS);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW);\n        menu.addMenuItem(Commands.TOGGLE_LIVE_PREVIEW_MB_MODE);\n        menu.addMenuItem(Commands.FILE_PROJECT_SETTINGS);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_EXTENSION_MANAGER);\n\n        // suppress redundant quit menu item on mac\n        if (brackets.platform !== \"mac\" || !brackets.nativeMenus) {\n            menu.addMenuDivider();\n            menu.addMenuItem(Commands.FILE_QUIT);\n        }\n\n        /*\n         * Edit  menu\n         */\n        menu = Menus.addMenu(Strings.EDIT_MENU, Menus.AppMenuBar.EDIT_MENU);\n        menu.addMenuItem(Commands.EDIT_UNDO);\n        menu.addMenuItem(Commands.EDIT_REDO);\n        menu.addMenuDivider();\n        if (brackets.nativeMenus) {\n            // Native-only - can't programmatically trigger clipboard actions from JS menus\n            menu.addMenuItem(Commands.EDIT_CUT);\n            menu.addMenuItem(Commands.EDIT_COPY);\n            menu.addMenuItem(Commands.EDIT_PASTE);\n            menu.addMenuDivider();\n        }\n        menu.addMenuItem(Commands.EDIT_SELECT_ALL);\n        menu.addMenuItem(Commands.EDIT_SELECT_LINE);\n        menu.addMenuItem(Commands.EDIT_SPLIT_SEL_INTO_LINES);\n        menu.addMenuItem(Commands.EDIT_ADD_CUR_TO_PREV_LINE);\n        menu.addMenuItem(Commands.EDIT_ADD_CUR_TO_NEXT_LINE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_INDENT);\n        menu.addMenuItem(Commands.EDIT_UNINDENT);\n        menu.addMenuItem(Commands.EDIT_DUPLICATE);\n        menu.addMenuItem(Commands.EDIT_DELETE_LINES);\n        menu.addMenuItem(Commands.EDIT_LINE_UP);\n        menu.addMenuItem(Commands.EDIT_LINE_DOWN);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_LINE_COMMENT);\n        menu.addMenuItem(Commands.EDIT_BLOCK_COMMENT);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.SHOW_CODE_HINTS);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_CLOSE_BRACKETS);\n\n        /*\n         * Find menu\n         */\n        menu = Menus.addMenu(Strings.FIND_MENU, Menus.AppMenuBar.FIND_MENU);\n        menu.addMenuItem(Commands.CMD_FIND);\n        menu.addMenuItem(Commands.CMD_FIND_NEXT);\n        menu.addMenuItem(Commands.CMD_FIND_PREVIOUS);\n        menu.addMenuItem(Commands.CMD_FIND_ALL_AND_SELECT);\n        menu.addMenuItem(Commands.CMD_ADD_NEXT_MATCH);\n        menu.addMenuItem(Commands.CMD_SKIP_CURRENT_MATCH);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.CMD_FIND_IN_FILES);\n        menu.addMenuItem(Commands.CMD_FIND_ALL_REFERENCES);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.CMD_REPLACE);\n        menu.addMenuItem(Commands.CMD_REPLACE_IN_FILES);\n\n        /*\n         * View menu\n         */\n        menu = Menus.addMenu(Strings.VIEW_MENU, Menus.AppMenuBar.VIEW_MENU);\n        menu.addMenuItem(Commands.CMD_THEMES_OPEN_SETTINGS);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.CMD_SPLITVIEW_NONE);\n        menu.addMenuItem(Commands.CMD_SPLITVIEW_VERTICAL);\n        menu.addMenuItem(Commands.CMD_SPLITVIEW_HORIZONTAL);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.VIEW_HIDE_SIDEBAR);\n        menu.addMenuItem(Commands.TOGGLE_SEARCH_AUTOHIDE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.VIEW_INCREASE_FONT_SIZE);\n        menu.addMenuItem(Commands.VIEW_DECREASE_FONT_SIZE);\n        menu.addMenuItem(Commands.VIEW_RESTORE_FONT_SIZE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_ACTIVE_LINE);\n        menu.addMenuItem(Commands.TOGGLE_LINE_NUMBERS);\n        menu.addMenuItem(Commands.TOGGLE_WORD_WRAP);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_LIVE_HIGHLIGHT);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.VIEW_TOGGLE_INSPECTION);\n\n        /*\n         * Navigate menu\n         */\n        menu = Menus.addMenu(Strings.NAVIGATE_MENU, Menus.AppMenuBar.NAVIGATE_MENU);\n        menu.addMenuItem(Commands.NAVIGATE_QUICK_OPEN);\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_LINE);\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_DEFINITION);\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT);\n        menu.addMenuItem(Commands.NAVIGATE_JUMPTO_DEFINITION);\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_FIRST_PROBLEM);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.NAVIGATE_NEXT_DOC);\n        menu.addMenuItem(Commands.NAVIGATE_PREV_DOC);\n        menu.addMenuItem(Commands.NAVIGATE_NEXT_DOC_LIST_ORDER);\n        menu.addMenuItem(Commands.NAVIGATE_PREV_DOC_LIST_ORDER);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.NAVIGATE_SHOW_IN_FILE_TREE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        menu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH);\n        menu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH);\n        menu.addMenuItem(Commands.CSS_QUICK_EDIT_NEW_RULE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_QUICK_DOCS);\n\n        /*\n         * Help menu\n         */\n        menu = Menus.addMenu(Strings.HELP_MENU, Menus.AppMenuBar.HELP_MENU);\n        menu.addMenuItem(Commands.HELP_CHECK_FOR_UPDATE);\n\n        menu.addMenuDivider();\n        if (brackets.config.how_to_use_url) {\n            menu.addMenuItem(Commands.HELP_HOW_TO_USE_BRACKETS);\n        }\n        if (brackets.config.support_url) {\n            menu.addMenuItem(Commands.HELP_SUPPORT);\n        }\n        if (brackets.config.suggest_feature_url) {\n            menu.addMenuItem(Commands.HELP_SUGGEST);\n        }\n        if (brackets.config.release_notes_url) {\n            menu.addMenuItem(Commands.HELP_RELEASE_NOTES);\n        }\n        if (brackets.config.get_involved_url) {\n            menu.addMenuItem(Commands.HELP_GET_INVOLVED);\n        }\n\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.HELP_SHOW_EXT_FOLDER);\n\n        var hasAboutItem = (brackets.platform !== \"mac\" || !brackets.nativeMenus);\n\n        // Add final divider only if we have a homepage URL or twitter URL or about item\n        if (hasAboutItem || brackets.config.homepage_url || brackets.config.twitter_url) {\n            menu.addMenuDivider();\n        }\n\n        if (brackets.config.homepage_url) {\n            menu.addMenuItem(Commands.HELP_HOMEPAGE);\n        }\n\n        if (brackets.config.twitter_url) {\n            menu.addMenuItem(Commands.HELP_TWITTER);\n        }\n        // supress redundant about menu item in mac shell\n        if (hasAboutItem) {\n            menu.addMenuItem(Commands.HELP_ABOUT);\n        }\n\n\n        /*\n         * Context Menus\n         */\n\n        // WorkingSet context menu - Unlike most context menus, we can't attach\n        // listeners here because the DOM nodes for each pane's working set are\n        // created dynamically. Each WorkingSetView attaches its own listeners.\n        var workingset_cmenu = Menus.registerContextMenu(Menus.ContextMenuIds.WORKING_SET_CONTEXT_MENU);\n        workingset_cmenu.addMenuItem(Commands.FILE_SAVE);\n        workingset_cmenu.addMenuItem(Commands.FILE_SAVE_AS);\n        workingset_cmenu.addMenuItem(Commands.FILE_RENAME);\n        workingset_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_FILE_TREE);\n        workingset_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);\n        workingset_cmenu.addMenuDivider();\n        workingset_cmenu.addMenuItem(Commands.CMD_FIND_IN_SUBTREE);\n        workingset_cmenu.addMenuItem(Commands.CMD_REPLACE_IN_SUBTREE);\n        workingset_cmenu.addMenuDivider();\n        workingset_cmenu.addMenuItem(Commands.FILE_CLOSE);\n\n        var workingset_configuration_menu = Menus.registerContextMenu(Menus.ContextMenuIds.WORKING_SET_CONFIG_MENU);\n        workingset_configuration_menu.addMenuItem(Commands.CMD_WORKINGSET_SORT_BY_ADDED);\n        workingset_configuration_menu.addMenuItem(Commands.CMD_WORKINGSET_SORT_BY_NAME);\n        workingset_configuration_menu.addMenuItem(Commands.CMD_WORKINGSET_SORT_BY_TYPE);\n        workingset_configuration_menu.addMenuDivider();\n        workingset_configuration_menu.addMenuItem(Commands.CMD_WORKING_SORT_TOGGLE_AUTO);\n\n        var splitview_menu = Menus.registerContextMenu(Menus.ContextMenuIds.SPLITVIEW_MENU);\n        splitview_menu.addMenuItem(Commands.CMD_SPLITVIEW_NONE);\n        splitview_menu.addMenuItem(Commands.CMD_SPLITVIEW_VERTICAL);\n        splitview_menu.addMenuItem(Commands.CMD_SPLITVIEW_HORIZONTAL);\n\n        var project_cmenu = Menus.registerContextMenu(Menus.ContextMenuIds.PROJECT_MENU);\n        project_cmenu.addMenuItem(Commands.FILE_NEW);\n        project_cmenu.addMenuItem(Commands.FILE_NEW_FOLDER);\n        project_cmenu.addMenuItem(Commands.FILE_RENAME);\n        project_cmenu.addMenuItem(Commands.FILE_DELETE);\n        project_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);\n        project_cmenu.addMenuDivider();\n        project_cmenu.addMenuItem(Commands.CMD_FIND_IN_SUBTREE);\n        project_cmenu.addMenuItem(Commands.CMD_REPLACE_IN_SUBTREE);\n        project_cmenu.addMenuDivider();\n        project_cmenu.addMenuItem(Commands.FILE_REFRESH);\n\n        var editor_cmenu = Menus.registerContextMenu(Menus.ContextMenuIds.EDITOR_MENU);\n        // editor_cmenu.addMenuItem(Commands.NAVIGATE_JUMPTO_DEFINITION);\n        editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_DOCS);\n        editor_cmenu.addMenuItem(Commands.CMD_FIND_ALL_REFERENCES);\n        editor_cmenu.addMenuDivider();\n        editor_cmenu.addMenuItem(Commands.EDIT_CUT);\n        editor_cmenu.addMenuItem(Commands.EDIT_COPY);\n        editor_cmenu.addMenuItem(Commands.EDIT_PASTE);\n\n        editor_cmenu.addMenuDivider();\n        editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);\n\n        var inline_editor_cmenu = Menus.registerContextMenu(Menus.ContextMenuIds.INLINE_EDITOR_MENU);\n        inline_editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        inline_editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);\n        inline_editor_cmenu.addMenuDivider();\n        inline_editor_cmenu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH);\n        inline_editor_cmenu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH);\n\n        /**\n         * Context menu for code editors (both full-size and inline)\n         * Auto selects the word the user clicks if the click does not occur over\n         * an existing selection\n         */\n        $(\"#editor-holder\").on(\"contextmenu\", function (e) {\n            require([\"editor/EditorManager\"], function (EditorManager) {\n                if ($(e.target).parents(\".CodeMirror-gutter\").length !== 0) {\n                    return;\n                }\n\n                // Note: on mousedown before this event, CodeMirror automatically checks mouse pos, and\n                // if not clicking on a selection moves the cursor to click location. When triggered\n                // from keyboard, no pre-processing occurs and the cursor/selection is left as is.\n\n                var editor = EditorManager.getFocusedEditor(),\n                    inlineWidget = EditorManager.getFocusedInlineWidget();\n\n                if (editor) {\n                    //if (!editor.hasSelection()) {\n                        // Prevent menu from overlapping text by moving it down a little\n                        // Temporarily backout this change for now to help mitigate issue #1111,\n                        // which only happens if mouse is not over context menu. Better fix\n                        // requires change to bootstrap, which is too risky for now.\n                        //e.pageY += 6;\n                    //}\n\n                    // Inline text editors have a different context menu (safe to assume it's not some other\n                    // type of inline widget since we already know an Editor has focus)\n                    if (inlineWidget) {\n                        inline_editor_cmenu.open(e);\n                    } else {\n                        editor_cmenu.open(e);\n                    }\n                }\n            });\n        });\n\n        /**\n         * Context menu for folder tree\n         */\n        $(\"#project-files-container\").on(\"contextmenu\", function (e) {\n            project_cmenu.open(e);\n        });\n\n        // Dropdown menu for workspace sorting\n        Menus.ContextMenu.assignContextMenuToSelector(\".working-set-option-btn\", workingset_configuration_menu);\n\n        // Dropdown menu for view splitting\n        Menus.ContextMenu.assignContextMenuToSelector(\".working-set-splitview-btn\", splitview_menu);\n\n        // Prevent the browser context menu since Brackets creates a custom context menu\n        $(window).contextmenu(function (e) {\n            e.preventDefault();\n        });\n\n        /*\n         * General menu event processing\n         */\n        // Prevent clicks on top level menus and menu items from taking focus\n        $(window.document).on(\"mousedown\", \".dropdown\", function (e) {\n            e.preventDefault();\n        });\n\n        // Switch menus when the mouse enters an adjacent menu\n        // Only open the menu if another one has already been opened\n        // by clicking\n        $(window.document).on(\"mouseenter\", \"#titlebar .dropdown\", function (e) {\n            var open = $(this).siblings(\".open\");\n            if (open.length > 0) {\n                open.removeClass(\"open\");\n                $(this).addClass(\"open\");\n            }\n        });\n        // Check the visibility of context menu items before opening the context menu.\n        // 'Rename', 'Show in file tree' and 'Show in explorer' items will be disabled for files that have not yet been saved to disk.\n        Menus.getContextMenu(Menus.ContextMenuIds.WORKING_SET_CONTEXT_MENU).on(\"beforeContextMenuOpen\", _setMenuItemsVisible);        \n        Menus.getContextMenu(Menus.ContextMenuIds.PROJECT_MENU).on(\"beforeContextMenuOpen\", _setMenuItemsVisible);\n    });\n});\n"
  },
  {
    "path": "src/command/KeyBindingManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*unittests: KeyBindingManager */\n\n/**\n * Manages the mapping of keyboard inputs to commands.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var AppInit             = require(\"utils/AppInit\"),\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        DefaultDialogs      = require(\"widgets/DefaultDialogs\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileSystemError     = require(\"filesystem/FileSystemError\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        KeyEvent            = require(\"utils/KeyEvent\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        UrlParams           = require(\"utils/UrlParams\").UrlParams,\n        _                   = require(\"thirdparty/lodash\");\n\n    var KeyboardPrefs       = JSON.parse(require(\"text!base-config/keyboard.json\"));\n\n    var KEYMAP_FILENAME     = \"keymap.json\",\n        _userKeyMapFilePath = brackets.app.getApplicationSupportDirectory() + \"/\" + KEYMAP_FILENAME;\n\n    /**\n     * @private\n     * Maps normalized shortcut descriptor to key binding info.\n     * @type {!Object.<string, {commandID: string, key: string, displayKey: string}>}\n     */\n    var _keyMap            = {},    // For the actual key bindings including user specified ones\n        // For the default factory key bindings, cloned from _keyMap after all extensions are loaded.\n        _defaultKeyMap     = {};\n\n    /**\n     * @typedef {{shortcut: !string,\n     *            commandID: ?string}} UserKeyBinding\n     */\n\n    /**\n     * @private\n     * Maps shortcut descriptor to a command id.\n     * @type {UserKeyBinding}\n     */\n    var _customKeyMap      = {},\n        _customKeyMapCache = {};\n\n    /**\n     * @private\n     * Maps commandID to the list of shortcuts that are bound to it.\n     * @type {!Object.<string, Array.<{key: string, displayKey: string}>>}\n     */\n    var _commandMap  = {};\n\n    /**\n     * @private\n     * An array of command ID for all the available commands including the commands\n     * of installed extensions.\n     * @type {Array.<string>}\n     */\n    var _allCommands = [];\n\n    /**\n     * @private\n     * Maps key names to the corresponding unicode symols\n     * @type {{key: string, displayKey: string}}\n     */\n    var _displayKeyMap        = { \"up\":    \"\\u2191\",\n                                  \"down\":  \"\\u2193\",\n                                  \"left\":  \"\\u2190\",\n                                  \"right\": \"\\u2192\",\n                                  \"-\":     \"\\u2212\" };\n\n    var _specialCommands      = [Commands.EDIT_UNDO, Commands.EDIT_REDO, Commands.EDIT_SELECT_ALL,\n                                 Commands.EDIT_CUT, Commands.EDIT_COPY, Commands.EDIT_PASTE],\n        _reservedShortcuts    = [\"Ctrl-Z\", \"Ctrl-Y\", \"Ctrl-A\", \"Ctrl-X\", \"Ctrl-C\", \"Ctrl-V\"],\n        _macReservedShortcuts = [\"Cmd-,\", \"Cmd-H\", \"Cmd-Alt-H\", \"Cmd-M\", \"Cmd-Shift-Z\", \"Cmd-Q\"],\n        _keyNames             = [\"Up\", \"Down\", \"Left\", \"Right\", \"Backspace\", \"Enter\", \"Space\", \"Tab\",\n                                 \"PageUp\", \"PageDown\", \"Home\", \"End\", \"Insert\", \"Delete\"];\n\n    /**\n     * @private\n     * Flag to show key binding errors in the key map file. Default is true and\n     * it will be set to false when reloading without extensions. This flag is not\n     * used to suppress errors in loading or parsing the key map file. So if the key\n     * map file is corrupt, then the error dialog still shows up.\n     *\n     * @type {boolean}\n     */\n    var _showErrors = true;\n\n    /**\n     * @private\n     * Allow clients to toggle key binding\n     * @type {boolean}\n     */\n    var _enabled = true;\n\n    /**\n     * @private\n     * Stack of registered global keydown hooks.\n     * @type {Array.<function(Event): boolean>}\n     */\n    var _globalKeydownHooks = [];\n\n    /**\n     * @private\n     * Forward declaration for JSLint.\n     * @type {Function}\n     */\n    var _loadUserKeyMap;\n\n    /**\n     * @private\n     * States of Ctrl key down detection\n     * @enum {number}\n     */\n    var CtrlDownStates = {\n        \"NOT_YET_DETECTED\"    : 0,\n        \"DETECTED\"            : 1,\n        \"DETECTED_AND_IGNORED\": 2   // For consecutive ctrl keydown events while a Ctrl key is being hold down\n    };\n\n    /**\n     * @private\n     * Flags used to determine whether right Alt key is pressed. When it is pressed,\n     * the following two keydown events are triggered in that specific order.\n     *\n     *    1. _ctrlDown - flag used to record { ctrlKey: true, keyIdentifier: \"Control\", ... } keydown event\n     *    2. _altGrDown - flag used to record { ctrlKey: true, altKey: true, keyIdentifier: \"Alt\", ... } keydown event\n     *\n     * @type {CtrlDownStates|boolean}\n     */\n    var _ctrlDown = CtrlDownStates.NOT_YET_DETECTED,\n        _altGrDown = false;\n\n    /**\n     * @private\n     * Used to record the timeStamp property of the last keydown event.\n     * @type {number}\n     */\n    var _lastTimeStamp;\n\n    /**\n     * @private\n     * Used to record the keyIdentifier property of the last keydown event.\n     * @type {string}\n     */\n    var _lastKeyIdentifier;\n\n    /*\n     * @private\n     * Constant used for checking the interval between Control keydown event and Alt keydown event.\n     * If the right Alt key is down we get Control keydown followed by Alt keydown within 30 ms. if\n     * the user is pressing Control key and then Alt key, the interval will be larger than 30 ms.\n     * @type {number}\n     */\n    var MAX_INTERVAL_FOR_CTRL_ALT_KEYS = 30;\n\n    /**\n     * @private\n     * Forward declaration for JSLint.\n     * @type {Function}\n     */\n    var _onCtrlUp;\n\n    /**\n     * @private\n     * Resets all the flags and removes _onCtrlUp event listener.\n     *\n     */\n    function _quitAltGrMode() {\n        _enabled = true;\n        _ctrlDown = CtrlDownStates.NOT_YET_DETECTED;\n        _altGrDown = false;\n        _lastTimeStamp = null;\n        _lastKeyIdentifier = null;\n        $(window).off(\"keyup\", _onCtrlUp);\n    }\n\n    /**\n     * @private\n     * Detects the release of AltGr key by checking all keyup events\n     * until we receive one with ctrl key code. Once detected, reset\n     * all the flags and also remove this event listener.\n     *\n     * @param {!KeyboardEvent} e keyboard event object\n     */\n    _onCtrlUp = function (e) {\n        var key = e.keyCode || e.which;\n        if (_altGrDown && key === KeyEvent.DOM_VK_CONTROL) {\n            _quitAltGrMode();\n        }\n    };\n\n    /**\n     * @private\n     * Detects whether AltGr key is pressed. When it is pressed, the first keydown event has\n     * ctrlKey === true with keyIdentifier === \"Control\". The next keydown event with\n     * altKey === true, ctrlKey === true and keyIdentifier === \"Alt\" is sent within 30 ms. Then\n     * the next keydown event with altKey === true, ctrlKey === true and keyIdentifier === \"Control\"\n     * is sent. If the user keep holding AltGr key down, then the second and third\n     * keydown events are repeatedly sent out alternately. If the user is also holding down Ctrl\n     * key, then either keyIdentifier === \"Control\" or keyIdentifier === \"Alt\" is repeatedly sent\n     * but not alternately.\n     *\n     * Once we detect the AltGr key down, then disable KeyBindingManager and set up a keyup\n     * event listener to detect the release of the altGr key so that we can re-enable KeyBindingManager.\n     * When we detect the addition of Ctrl key besides AltGr key, we also quit AltGr mode and re-enable\n     * KeyBindingManager.\n     *\n     * @param {!KeyboardEvent} e keyboard event object\n     */\n    function _detectAltGrKeyDown(e) {\n        if (brackets.platform !== \"win\") {\n            return;\n        }\n\n        if (!_altGrDown) {\n            if (_ctrlDown !== CtrlDownStates.DETECTED_AND_IGNORED && e.ctrlKey && e.keyIdentifier === \"Control\") {\n                _ctrlDown = CtrlDownStates.DETECTED;\n            } else if (e.repeat && e.ctrlKey && e.keyIdentifier === \"Control\") {\n                // We get here if the user is holding down left/right Control key. Set it to false\n                // so that we don't misidentify the combination of Ctrl and Alt keys as AltGr key.\n                _ctrlDown = CtrlDownStates.DETECTED_AND_IGNORED;\n            } else if (_ctrlDown === CtrlDownStates.DETECTED && e.altKey && e.ctrlKey && e.keyIdentifier === \"Alt\" &&\n                        (e.timeStamp - _lastTimeStamp) < MAX_INTERVAL_FOR_CTRL_ALT_KEYS) {\n                _altGrDown = true;\n                _lastKeyIdentifier = \"Alt\";\n                _enabled = false;\n                $(window).on(\"keyup\", _onCtrlUp);\n            } else {\n                // Reset _ctrlDown so that we can start over in detecting the two key events\n                // required for AltGr key.\n                _ctrlDown = CtrlDownStates.NOT_YET_DETECTED;\n            }\n            _lastTimeStamp = e.timeStamp;\n        } else if (e.keyIdentifier === \"Control\" || e.keyIdentifier === \"Alt\") {\n            // If the user is NOT holding down AltGr key or is also pressing Ctrl key,\n            // then _lastKeyIdentifier will be the same as keyIdentifier in the current\n            // key event. So we need to quit AltGr mode to re-enable KBM.\n            if (e.altKey && e.ctrlKey && e.keyIdentifier === _lastKeyIdentifier) {\n                _quitAltGrMode();\n            } else {\n                _lastKeyIdentifier = e.keyIdentifier;\n            }\n        }\n    }\n\n    /**\n     * @private\n     */\n    function _reset() {\n        _keyMap = {};\n        _defaultKeyMap = {};\n        _customKeyMap = {};\n        _customKeyMapCache = {};\n        _commandMap = {};\n        _globalKeydownHooks = [];\n        _userKeyMapFilePath = brackets.app.getApplicationSupportDirectory() + \"/\" + KEYMAP_FILENAME;\n    }\n\n    /**\n     * @private\n     * Initialize an empty keymap as the current keymap. It overwrites the current keymap if there is one.\n     * builds the keyDescriptor string from the given parts\n     * @param {boolean} hasCtrl Is Ctrl key enabled\n     * @param {boolean} hasAlt Is Alt key enabled\n     * @param {boolean} hasShift Is Shift key enabled\n     * @param {string} key The key that's pressed\n     * @return {string} The normalized key descriptor\n     */\n    function _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key) {\n        if (!key) {\n            console.log(\"KeyBindingManager _buildKeyDescriptor() - No key provided!\");\n            return \"\";\n        }\n\n        var keyDescriptor = [];\n\n        if (hasMacCtrl) {\n            keyDescriptor.push(\"Ctrl\");\n        }\n        if (hasAlt) {\n            keyDescriptor.push(\"Alt\");\n        }\n        if (hasShift) {\n            keyDescriptor.push(\"Shift\");\n        }\n\n        if (hasCtrl) {\n            // Windows display Ctrl first, Mac displays Command symbol last\n            if (brackets.platform === \"mac\") {\n                keyDescriptor.push(\"Cmd\");\n            } else {\n                keyDescriptor.unshift(\"Ctrl\");\n            }\n        }\n\n        keyDescriptor.push(key);\n\n        return keyDescriptor.join(\"-\");\n    }\n\n\n    /**\n     * normalizes the incoming key descriptor so the modifier keys are always specified in the correct order\n     * @param {string} The string for a key descriptor, can be in any order, the result will be Ctrl-Alt-Shift-<Key>\n     * @return {string} The normalized key descriptor or null if the descriptor invalid\n     */\n    function normalizeKeyDescriptorString(origDescriptor) {\n        var hasMacCtrl = false,\n            hasCtrl = false,\n            hasAlt = false,\n            hasShift = false,\n            key = \"\",\n            error = false;\n\n        function _compareModifierString(left, right) {\n            if (!left || !right) {\n                return false;\n            }\n            left = left.trim().toLowerCase();\n            right = right.trim().toLowerCase();\n\n            return (left.length > 0 && left === right);\n        }\n\n        origDescriptor.split(\"-\").forEach(function parseDescriptor(ele, i, arr) {\n            if (_compareModifierString(\"ctrl\", ele)) {\n                if (brackets.platform === \"mac\") {\n                    hasMacCtrl = true;\n                } else {\n                    hasCtrl = true;\n                }\n            } else if (_compareModifierString(\"cmd\", ele)) {\n                if (brackets.platform === \"mac\") {\n                    hasCtrl = true;\n                } else {\n                    error = true;\n                }\n            } else if (_compareModifierString(\"alt\", ele)) {\n                hasAlt = true;\n            } else if (_compareModifierString(\"opt\", ele)) {\n                if (brackets.platform === \"mac\") {\n                    hasAlt = true;\n                } else {\n                    error = true;\n                }\n            } else if (_compareModifierString(\"shift\", ele)) {\n                hasShift = true;\n            } else if (key.length > 0) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Multiple keys defined. Using key: \" + key + \" from: \" + origDescriptor);\n                error = true;\n            } else {\n                key = ele;\n            }\n        });\n\n        if (error) {\n            return null;\n        }\n\n        // Check to see if the binding is for \"-\".\n        if (key === \"\" && origDescriptor.search(/^.+--$/) !== -1) {\n            key = \"-\";\n        }\n\n        // '+' char is valid if it's the only key. Keyboard shortcut strings should use\n        // unicode characters (unescaped). Keyboard shortcut display strings may use\n        // unicode escape sequences (e.g. \\u20AC euro sign)\n        if ((key.indexOf(\"+\")) >= 0 && (key.length > 1)) {\n            return null;\n        }\n\n        // Ensure that the first letter of the key name is in upper case and the rest are\n        // in lower case. i.e. 'a' => 'A' and 'up' => 'Up'\n        if (/^[a-z]/i.test(key)) {\n            key = _.capitalize(key.toLowerCase());\n        }\n\n        // Also make sure that the second word of PageUp/PageDown has the first letter in upper case.\n        if (/^Page/.test(key)) {\n            key = key.replace(/(up|down)$/, function (match, p1) {\n                return _.capitalize(p1);\n            });\n        }\n\n        // No restriction on single character key yet, but other key names are restricted to either\n        // Function keys or those listed in _keyNames array.\n        if (key.length > 1 && !/F\\d+/.test(key) &&\n                _keyNames.indexOf(key) === -1) {\n            return null;\n        }\n\n        return _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key);\n    }\n\n    /**\n     * @private\n     * Looks for keycodes that have os-inconsistent keys and fixes them.\n     * @param {number} The keycode from the keyboard event.\n     * @param {string} The current best guess at what the key is.\n     * @return {string} If the key is OS-inconsistent, the correct key; otherwise, the original key.\n     **/\n    function _mapKeycodeToKey(keycode, key) {\n        // If keycode represents one of the digit keys (0-9), then return the corresponding digit\n        // by subtracting KeyEvent.DOM_VK_0 from keycode. ie. [48-57] --> [0-9]\n        if (keycode >= KeyEvent.DOM_VK_0 && keycode <= KeyEvent.DOM_VK_9) {\n            return String(keycode - KeyEvent.DOM_VK_0);\n        // Do the same with the numpad numbers\n        // by subtracting KeyEvent.DOM_VK_NUMPAD0 from keycode. ie. [96-105] --> [0-9]\n        } else if (keycode >= KeyEvent.DOM_VK_NUMPAD0 && keycode <= KeyEvent.DOM_VK_NUMPAD9) {\n            return String(keycode - KeyEvent.DOM_VK_NUMPAD0);\n        }\n\n\n        switch (keycode) {\n        case KeyEvent.DOM_VK_SEMICOLON:\n            return \";\";\n        case KeyEvent.DOM_VK_EQUALS:\n            return \"=\";\n        case KeyEvent.DOM_VK_COMMA:\n            return \",\";\n        case KeyEvent.DOM_VK_SUBTRACT:\n        case KeyEvent.DOM_VK_DASH:\n            return \"-\";\n        case KeyEvent.DOM_VK_ADD:\n            return \"+\";\n        case KeyEvent.DOM_VK_DECIMAL:\n        case KeyEvent.DOM_VK_PERIOD:\n            return \".\";\n        case KeyEvent.DOM_VK_DIVIDE:\n        case KeyEvent.DOM_VK_SLASH:\n            return \"/\";\n        case KeyEvent.DOM_VK_BACK_QUOTE:\n            return \"`\";\n        case KeyEvent.DOM_VK_OPEN_BRACKET:\n            return \"[\";\n        case KeyEvent.DOM_VK_BACK_SLASH:\n            return \"\\\\\";\n        case KeyEvent.DOM_VK_CLOSE_BRACKET:\n            return \"]\";\n        case KeyEvent.DOM_VK_QUOTE:\n            return \"'\";\n        default:\n            return key;\n        }\n    }\n\n    /**\n     * Takes a keyboard event and translates it into a key in a key map\n     */\n    function _translateKeyboardEvent(event) {\n        var hasMacCtrl = (brackets.platform === \"mac\") ? (event.ctrlKey) : false,\n            hasCtrl = (brackets.platform !== \"mac\") ? (event.ctrlKey) : (event.metaKey),\n            hasAlt = (event.altKey),\n            hasShift = (event.shiftKey),\n            key = String.fromCharCode(event.keyCode);\n\n        //From the W3C, if we can get the KeyboardEvent.keyIdentifier then look here\n        //As that will let us use keys like then function keys \"F5\" for commands. The\n        //full set of values we can use is here\n        //http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set\n        var ident = event.keyIdentifier;\n        if (ident) {\n            if (ident.charAt(0) === \"U\" && ident.charAt(1) === \"+\") {\n                //This is a unicode code point like \"U+002A\", get the 002A and use that\n                key = String.fromCharCode(parseInt(ident.substring(2), 16));\n            } else {\n                //This is some non-character key, just use the raw identifier\n                key = ident;\n            }\n        }\n\n        // Translate some keys to their common names\n        if (key === \"\\t\") {\n            key = \"Tab\";\n        } else if (key === \" \") {\n            key = \"Space\";\n        } else if (key === \"\\b\") {\n            key = \"Backspace\";\n        } else if (key === \"Help\") {\n            key = \"Insert\";\n        } else if (event.keyCode === KeyEvent.DOM_VK_DELETE) {\n            key = \"Delete\";\n        } else {\n            key = _mapKeycodeToKey(event.keyCode, key);\n        }\n\n        return _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key);\n    }\n\n    /**\n     * Convert normalized key representation to display appropriate for platform.\n     * @param {!string} descriptor Normalized key descriptor.\n     * @return {!string} Display/Operating system appropriate string\n     */\n    function formatKeyDescriptor(descriptor) {\n        var displayStr;\n\n        if (brackets.platform === \"mac\") {\n            displayStr = descriptor.replace(/-(?!$)/g, \"\");     // remove dashes\n            displayStr = displayStr.replace(\"Ctrl\", \"\\u2303\");  // Ctrl > control symbol\n            displayStr = displayStr.replace(\"Cmd\", \"\\u2318\");   // Cmd > command symbol\n            displayStr = displayStr.replace(\"Shift\", \"\\u21E7\"); // Shift > shift symbol\n            displayStr = displayStr.replace(\"Alt\", \"\\u2325\");   // Alt > option symbol\n        } else {\n            displayStr = descriptor.replace(\"Ctrl\", Strings.KEYBOARD_CTRL);\n            displayStr = displayStr.replace(\"Shift\", Strings.KEYBOARD_SHIFT);\n            displayStr = displayStr.replace(/-(?!$)/g, \"+\");\n        }\n\n        displayStr = displayStr.replace(\"Space\", Strings.KEYBOARD_SPACE);\n\n        displayStr = displayStr.replace(\"PageUp\", Strings.KEYBOARD_PAGE_UP);\n        displayStr = displayStr.replace(\"PageDown\", Strings.KEYBOARD_PAGE_DOWN);\n        displayStr = displayStr.replace(\"Home\", Strings.KEYBOARD_HOME);\n        displayStr = displayStr.replace(\"End\", Strings.KEYBOARD_END);\n\n        displayStr = displayStr.replace(\"Ins\", Strings.KEYBOARD_INSERT);\n        displayStr = displayStr.replace(\"Del\", Strings.KEYBOARD_DELETE);\n\n        return displayStr;\n    }\n\n    /**\n     * @private\n     * @param {string} A normalized key-description string.\n     * @return {boolean} true if the key is already assigned, false otherwise.\n     */\n    function _isKeyAssigned(key) {\n        return (_keyMap[key] !== undefined);\n    }\n\n    /**\n     * Remove a key binding from _keymap\n     *\n     * @param {!string} key - a key-description string that may or may not be normalized.\n     * @param {?string} platform - OS from which to remove the binding (all platforms if unspecified)\n     */\n    function removeBinding(key, platform) {\n        if (!key || ((platform !== null) && (platform !== undefined) && (platform !== brackets.platform))) {\n            return;\n        }\n\n        var normalizedKey = normalizeKeyDescriptorString(key);\n\n        if (!normalizedKey) {\n            console.log(\"Failed to normalize \" + key);\n        } else if (_isKeyAssigned(normalizedKey)) {\n            var binding = _keyMap[normalizedKey],\n                command = CommandManager.get(binding.commandID),\n                bindings = _commandMap[binding.commandID];\n\n            // delete key binding record\n            delete _keyMap[normalizedKey];\n\n            if (bindings) {\n                // delete mapping from command to key binding\n                _commandMap[binding.commandID] = bindings.filter(function (b) {\n                    return (b.key !== normalizedKey);\n                });\n\n                if (command) {\n                    command.trigger(\"keyBindingRemoved\", {key: normalizedKey, displayKey: binding.displayKey});\n                }\n            }\n        }\n    }\n\n    /**\n     * @private\n     *\n     * Updates _allCommands array and _defaultKeyMap with the new key binding\n     * if it is not yet in the _allCommands array. _allCommands array is initialized\n     * only in extensionsLoaded event. So any new commands or key bindings added after\n     * that will be updated here.\n     *\n     * @param {{commandID: string, key: string, displayKey:string, explicitPlatform: string}} newBinding\n     */\n    function _updateCommandAndKeyMaps(newBinding) {\n        if (_allCommands.length === 0) {\n            return;\n        }\n\n        if (newBinding && newBinding.commandID && _allCommands.indexOf(newBinding.commandID) === -1) {\n            _defaultKeyMap[newBinding.commandID] = _.cloneDeep(newBinding);\n\n            // Process user key map again to catch any reassignment to all new key bindings added from extensions.\n            _loadUserKeyMap();\n        }\n    }\n\n    /**\n     * @private\n     *\n     * @param {string} commandID\n     * @param {string|{{key: string, displayKey: string}}} keyBinding - a single shortcut.\n     * @param {?string} platform\n     *     - \"all\" indicates all platforms, not overridable\n     *     - undefined indicates all platforms, overridden by platform-specific binding\n     * @param {boolean=} userBindings true if adding a user key binding or undefined otherwise.\n     * @return {?{key: string, displayKey:String}} Returns a record for valid key bindings.\n     *     Returns null when key binding platform does not match, binding does not normalize,\n     *     or is already assigned.\n     */\n    function _addBinding(commandID, keyBinding, platform, userBindings) {\n        var key,\n            result = null,\n            normalized,\n            normalizedDisplay,\n            explicitPlatform = keyBinding.platform || platform,\n            targetPlatform,\n            command,\n            bindingsToDelete = [],\n            existing;\n\n        // For platform: \"all\", use explicit current platform\n        if (explicitPlatform && explicitPlatform !== \"all\") {\n            targetPlatform = explicitPlatform;\n        } else {\n            targetPlatform = brackets.platform;\n        }\n\n\n        // Skip if the key binding is not for this platform.\n        if (explicitPlatform === \"mac\" && brackets.platform !== \"mac\") {\n            return null;\n        }\n\n        // if the request does not specify an explicit platform, and we're\n        // currently on a mac, then replace Ctrl with Cmd.\n        key = (keyBinding.key) || keyBinding;\n        if (brackets.platform === \"mac\" && (explicitPlatform === undefined || explicitPlatform === \"all\")) {\n            key = key.replace(\"Ctrl\", \"Cmd\");\n            if (keyBinding.displayKey !== undefined) {\n                keyBinding.displayKey = keyBinding.displayKey.replace(\"Ctrl\", \"Cmd\");\n            }\n        }\n\n        normalized = normalizeKeyDescriptorString(key);\n\n        // skip if the key binding is invalid\n        if (!normalized) {\n            console.error(\"Unable to parse key binding \" + key + \". Permitted modifiers: Ctrl, Cmd, Alt, Opt, Shift; separated by '-' (not '+').\");\n            return null;\n        }\n\n        // check for duplicate key bindings\n        existing = _keyMap[normalized];\n\n        // for cross-platform compatibility\n        if (exports.useWindowsCompatibleBindings) {\n            // windows-only key bindings are used as the default binding\n            // only if a default binding wasn't already defined\n            if (explicitPlatform === \"win\") {\n                // search for a generic or platform-specific binding if it\n                // already exists\n                if (existing && (!existing.explicitPlatform ||\n                                 existing.explicitPlatform === brackets.platform ||\n                                 existing.explicitPlatform === \"all\")) {\n                    // do not clobber existing binding with windows-only binding\n                    return null;\n                }\n\n                // target this windows binding for the current platform\n                targetPlatform = brackets.platform;\n            }\n        }\n\n        // skip if this binding doesn't match the current platform\n        if (targetPlatform !== brackets.platform) {\n            return null;\n        }\n\n        // skip if the key is already assigned\n        if (existing) {\n            if (!existing.explicitPlatform && explicitPlatform) {\n                // remove the the generic binding to replace with this new platform-specific binding\n                removeBinding(normalized);\n                existing = false;\n            }\n        }\n\n        // delete existing bindings when\n        // (1) replacing a windows-compatible binding with a generic or\n        //     platform-specific binding\n        // (2) replacing a generic binding with a platform-specific binding\n        var existingBindings = _commandMap[commandID] || [],\n            isWindowsCompatible,\n            isReplaceGeneric,\n            ignoreGeneric;\n\n        existingBindings.forEach(function (binding) {\n            // remove windows-only bindings in _commandMap\n            isWindowsCompatible = exports.useWindowsCompatibleBindings &&\n                binding.explicitPlatform === \"win\";\n\n            // remove existing generic binding\n            isReplaceGeneric = !binding.explicitPlatform &&\n                explicitPlatform;\n\n            if (isWindowsCompatible || isReplaceGeneric) {\n                bindingsToDelete.push(binding);\n            } else {\n                // existing binding is platform-specific and the requested binding is generic\n                ignoreGeneric = binding.explicitPlatform && !explicitPlatform;\n            }\n        });\n\n        if (ignoreGeneric) {\n            // explicit command binding overrides this one\n            return null;\n        }\n\n        if (existing) {\n            // do not re-assign a key binding\n            console.error(\"Cannot assign \" + normalized + \" to \" + commandID + \". It is already assigned to \" + _keyMap[normalized].commandID);\n            return null;\n        }\n\n        // remove generic or windows-compatible bindings\n        bindingsToDelete.forEach(function (binding) {\n            removeBinding(binding.key);\n        });\n\n        // optional display-friendly string (e.g. CMD-+ instead of CMD-=)\n        normalizedDisplay = (keyBinding.displayKey) ? normalizeKeyDescriptorString(keyBinding.displayKey) : normalized;\n\n        // 1-to-many commandID mapping to key binding\n        if (!_commandMap[commandID]) {\n            _commandMap[commandID] = [];\n        }\n\n        result = {\n            key                 : normalized,\n            displayKey          : normalizedDisplay,\n            explicitPlatform    : explicitPlatform\n        };\n\n        _commandMap[commandID].push(result);\n\n        // 1-to-1 key binding to commandID\n        _keyMap[normalized] = {\n            commandID           : commandID,\n            key                 : normalized,\n            displayKey          : normalizedDisplay,\n            explicitPlatform    : explicitPlatform\n        };\n\n        if (!userBindings) {\n            _updateCommandAndKeyMaps(_keyMap[normalized]);\n        }\n\n        // notify listeners\n        command = CommandManager.get(commandID);\n\n        if (command) {\n            command.trigger(\"keyBindingAdded\", result);\n        }\n\n        return result;\n    }\n\n    /**\n     * Returns a copy of the current key map. If the optional 'defaults' parameter is true,\n     * then a copy of the default key map is returned.\n     * @param {boolean=} defaults true if the caller wants a copy of the default key map.\n     *                            Otherwise, the current active key map is returned.\n     * @return {!Object.<string, {commandID: string, key: string, displayKey: string}>}\n     */\n    function getKeymap(defaults) {\n        return $.extend({}, defaults ? _defaultKeyMap : _keyMap);\n    }\n\n    /**\n     * Process the keybinding for the current key.\n     *\n     * @param {string} A key-description string.\n     * @return {boolean} true if the key was processed, false otherwise\n     */\n    function _handleKey(key) {\n        if (_enabled && _keyMap[key]) {\n            // The execute() function returns a promise because some commands are async.\n            // Generally, commands decide whether they can run or not synchronously,\n            // and reject immediately, so we can test for that synchronously.\n            var promise = CommandManager.execute(_keyMap[key].commandID);\n            return (promise.state() !== \"rejected\");\n        }\n        return false;\n    }\n\n    /**\n     * @private\n     *\n     * Sort objects by platform property. Objects with a platform property come\n     * before objects without a platform property.\n     */\n    function _sortByPlatform(a, b) {\n        var a1 = (a.platform) ? 1 : 0,\n            b1 = (b.platform) ? 1 : 0;\n        return b1 - a1;\n    }\n\n    /**\n     * Add one or more key bindings to a particular Command.\n     *\n     * @param {!string | Command} command - A command ID or command object\n     * @param {?({key: string, displayKey: string}|Array.<{key: string, displayKey: string, platform: string}>)} keyBindings\n     *     A single key binding or an array of keybindings. Example:\n     *     \"Shift-Cmd-F\". Mac and Win key equivalents are automatically\n     *     mapped to each other. Use displayKey property to display a different\n     *     string (e.g. \"CMD+\" instead of \"CMD=\").\n     * @param {?string} platform The target OS of the keyBindings either\n     *     \"mac\", \"win\" or \"linux\". If undefined, all platforms not explicitly\n     *     defined will use the key binding.\n     *     NOTE: If platform is not specified, Ctrl will be replaced by Cmd for \"mac\" platform\n     * @return {{key: string, displayKey:String}|Array.<{key: string, displayKey:String}>}\n     *     Returns record(s) for valid key binding(s)\n     */\n    function addBinding(command, keyBindings, platform) {\n        var commandID = \"\",\n            results;\n\n        if (!command) {\n            console.error(\"addBinding(): missing required parameter: command\");\n            return;\n        }\n\n        if (!keyBindings) { return; }\n\n        if (typeof (command) === \"string\") {\n            commandID = command;\n        } else {\n            commandID = command.getID();\n        }\n\n        if (Array.isArray(keyBindings)) {\n            var keyBinding;\n            results = [];\n\n            // process platform-specific bindings first\n            keyBindings.sort(_sortByPlatform);\n\n            keyBindings.forEach(function addSingleBinding(keyBindingRequest) {\n                // attempt to add keybinding\n                keyBinding = _addBinding(commandID, keyBindingRequest, keyBindingRequest.platform);\n\n                if (keyBinding) {\n                    results.push(keyBinding);\n                }\n            });\n        } else {\n            results = _addBinding(commandID, keyBindings, platform);\n        }\n\n        return results;\n    }\n\n    /**\n     * Retrieve key bindings currently associated with a command\n     *\n     * @param {!string | Command} command - A command ID or command object\n     * @return {!Array.<{{key: string, displayKey: string}}>} An array of associated key bindings.\n     */\n    function getKeyBindings(command) {\n        var bindings    = [],\n            commandID   = \"\";\n\n        if (!command) {\n            console.error(\"getKeyBindings(): missing required parameter: command\");\n            return [];\n        }\n\n        if (typeof (command) === \"string\") {\n            commandID = command;\n        } else {\n            commandID = command.getID();\n        }\n\n        bindings = _commandMap[commandID];\n        return bindings || [];\n    }\n\n    /**\n     * Adds default key bindings when commands are registered to CommandManager\n     * @param {$.Event} event jQuery event\n     * @param {Command} command Newly registered command\n     */\n    function _handleCommandRegistered(event, command) {\n        var commandId   = command.getID(),\n            defaults    = KeyboardPrefs[commandId];\n\n        if (defaults) {\n            addBinding(commandId, defaults);\n        }\n    }\n\n    /**\n     * Adds a global keydown hook that gets first crack at keydown events\n     * before standard keybindings do. This is intended for use by modal or\n     * semi-modal UI elements like dialogs or the code hint list that should\n     * execute before normal command bindings are run.\n     *\n     * The hook is passed one parameter, the original keyboard event. If the\n     * hook handles the event (or wants to block other global hooks from\n     * handling the event), it should return true. Note that this will *only*\n     * stop other global hooks and KeyBindingManager from handling the\n     * event; to prevent further event propagation, you will need to call\n     * stopPropagation(), stopImmediatePropagation(), and/or preventDefault()\n     * as usual.\n     *\n     * Multiple keydown hooks can be registered, and are executed in order,\n     * most-recently-added first.\n     *\n     * (We have to have a special API for this because (1) handlers are normally\n     * called in least-recently-added order, and we want most-recently-added;\n     * (2) native DOM events don't have a way for us to find out if\n     * stopImmediatePropagation()/stopPropagation() has been called on the\n     * event, so we have to have some other way for one of the hooks to\n     * indicate that it wants to block the other hooks from running.)\n     *\n     * @param {function(Event): boolean} hook The global hook to add.\n     */\n    function addGlobalKeydownHook(hook) {\n        _globalKeydownHooks.push(hook);\n    }\n\n    /**\n     * Removes a global keydown hook added by `addGlobalKeydownHook`.\n     * Does not need to be the most recently added hook.\n     *\n     * @param {function(Event): boolean} hook The global hook to remove.\n     */\n    function removeGlobalKeydownHook(hook) {\n        var index = _globalKeydownHooks.indexOf(hook);\n        if (index !== -1) {\n            _globalKeydownHooks.splice(index, 1);\n        }\n    }\n\n    /**\n     * Handles a given keydown event, checking global hooks first before\n     * deciding to handle it ourselves.\n     * @param {Event} The keydown event to handle.\n     */\n    function _handleKeyEvent(event) {\n        var i, handled = false;\n        for (i = _globalKeydownHooks.length - 1; i >= 0; i--) {\n            if (_globalKeydownHooks[i](event)) {\n                handled = true;\n                break;\n            }\n        }\n        _detectAltGrKeyDown(event);\n        if (!handled && _handleKey(_translateKeyboardEvent(event))) {\n            event.stopPropagation();\n            event.preventDefault();\n        }\n    }\n\n    AppInit.htmlReady(function () {\n        // Install keydown event listener.\n        window.document.body.addEventListener(\n            \"keydown\",\n            _handleKeyEvent,\n            true\n        );\n\n        exports.useWindowsCompatibleBindings = (brackets.platform !== \"mac\") &&\n            (brackets.platform !== \"win\");\n    });\n\n    /**\n     * @private\n     * Displays an error dialog and also opens the user key map file for editing only if\n     * the error is not the loading file error.\n     *\n     * @param {?string} err Error type returned from JSON parser or open file operation\n     * @param {string=} message Error message to be displayed in the dialog\n     */\n    function _showErrorsAndOpenKeyMap(err, message) {\n        // Asynchronously loading Dialogs module to avoid the circular dependency\n        require([\"widgets/Dialogs\"], function (Dialogs) {\n            var errorMessage = Strings.ERROR_KEYMAP_CORRUPT;\n\n            if (err === FileSystemError.UNSUPPORTED_ENCODING) {\n                errorMessage = Strings.ERROR_LOADING_KEYMAP;\n            } else if (message) {\n                errorMessage = message;\n            }\n\n            Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_ERROR,\n                Strings.ERROR_KEYMAP_TITLE,\n                errorMessage\n            )\n                .done(function () {\n                    if (err !== FileSystemError.UNSUPPORTED_ENCODING) {\n                        CommandManager.execute(Commands.FILE_OPEN_KEYMAP);\n                    }\n                });\n        });\n    }\n\n    /**\n     * @private\n     *\n     * Checks whether the given command ID is a special command that the user can't bind\n     * to another shortcut.\n     * @param {!string} commandID A string referring to a specific command\n     * @return {boolean} true if normalizedKey is a special command, false otherwise.\n     */\n    function _isSpecialCommand(commandID) {\n        if (brackets.platform === \"mac\" && commandID === \"file.quit\") {\n            return true;\n        }\n\n        return (_specialCommands.indexOf(commandID) > -1);\n    }\n\n    /**\n     * @private\n     *\n     * Checks whether the given key combination is a shortcut of a special command\n     * or a Mac system command that the user can't reassign to another command.\n     * @param {!string} normalizedKey A key combination string used for a keyboard shortcut\n     * @return {boolean} true if normalizedKey is a restricted shortcut, false otherwise.\n     */\n    function _isReservedShortcuts(normalizedKey) {\n        if (!normalizedKey) {\n            return false;\n        }\n\n        if (_reservedShortcuts.indexOf(normalizedKey) > -1 ||\n                _reservedShortcuts.indexOf(normalizedKey.replace(\"Cmd\", \"Ctrl\")) > -1) {\n            return true;\n        }\n\n        if (brackets.platform === \"mac\" && _macReservedShortcuts.indexOf(normalizedKey) > -1) {\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * @private\n     *\n     * Creates a bullet list item for any item in the given list.\n     * @param {Array.<string>} list An array of strings to be converted into a\n     * message string with a bullet list.\n     * @return {string} the html text version of the list\n     */\n    function _getBulletList(list) {\n        var message = \"<ul class='dialog-list'>\";\n        list.forEach(function (info) {\n            message += \"<li>\" + info + \"</li>\";\n        });\n        message += \"</ul>\";\n        return message;\n    }\n\n    /**\n     * @private\n     *\n     * Gets the corresponding unicode symbol of an arrow key for display in the menu.\n     * @param {string} key The non-modifier key used in the shortcut. It does not need to be normalized.\n     * @return {string} An empty string if key is not one of those we want to show with the unicode symbol.\n     *                  Otherwise, the corresponding unicode symbol is returned.\n     */\n    function _getDisplayKey(key) {\n        var displayKey = \"\",\n            match = key ? key.match(/(Up|Down|Left|Right|\\-)$/i) : null;\n        if (match && !/Page(Up|Down)/.test(key)) {\n            displayKey = key.substr(0, match.index) + _displayKeyMap[match[0].toLowerCase()];\n        }\n        return displayKey;\n    }\n\n    /**\n     * @private\n     *\n     * Applies each user key binding to all the affected commands and updates _keyMap.\n     * Shows errors in a dialog and then opens the user key map file if any of the following\n     * is detected while applying the user key bindings.\n     *     - A key binding is attempting to modify a special command.\n     *     - A key binding is attempting to assign a shortcut of a special command to another one.\n     *     - Multiple key bindings are specified for the same command ID.\n     *     - The same key combination is listed for multiple key bindings.\n     *     - A key binding has any invalid key syntax.\n     *     - A key binding is referring to a non-existent command ID.\n     */\n    function _applyUserKeyBindings() {\n        var remappedCommands   = [],\n            remappedKeys       = [],\n            restrictedCommands = [],\n            restrictedKeys     = [],\n            invalidKeys        = [],\n            invalidCommands    = [],\n            multipleKeys       = [],\n            duplicateBindings  = [],\n            errorMessage       = \"\";\n\n        _.forEach(_customKeyMap, function (commandID, key) {\n            var normalizedKey    = normalizeKeyDescriptorString(key),\n                existingBindings = _commandMap[commandID] || [];\n\n            // Skip this since we don't allow user to update key binding of a special\n            // command like cut, copy, paste, undo, redo and select all.\n            if (_isSpecialCommand(commandID)) {\n                restrictedCommands.push(commandID);\n                return;\n            }\n\n            // Skip this since we don't allow user to update a shortcut used in\n            // a special command or any Mac system command.\n            if (_isReservedShortcuts(normalizedKey)) {\n                restrictedKeys.push(key);\n                return;\n            }\n\n            // Skip this if the key is invalid.\n            if (!normalizedKey) {\n                invalidKeys.push(key);\n                return;\n            }\n\n            if (_isKeyAssigned(normalizedKey)) {\n                if (remappedKeys.indexOf(normalizedKey) !== -1) {\n                    // JSON parser already removed all the duplicates that have the exact\n                    // same case or order in their keys. So we're only detecting duplicate\n                    // bindings that have different orders or different cases used in the key.\n                    duplicateBindings.push(key);\n                    return;\n                }\n                // The same key binding already exists, so skip this.\n                if (_keyMap[normalizedKey].commandID === commandID) {\n                    // Still need to add it to the remappedCommands so that\n                    // we can detect any duplicate later on.\n                    remappedCommands.push(commandID);\n                    return;\n                }\n                removeBinding(normalizedKey);\n            }\n\n            if (remappedKeys.indexOf(normalizedKey) === -1) {\n                remappedKeys.push(normalizedKey);\n            }\n\n            // Remove another key binding if the new key binding is for a command\n            // that has a different key binding. e.g. \"Ctrl-W\": \"edit.selectLine\"\n            // requires us to remove \"Ctrl-W\" from \"file.close\" command, but we\n            // also need to remove \"Ctrl-L\" from \"edit.selectLine\".\n            if (existingBindings.length) {\n                existingBindings.forEach(function (binding) {\n                    removeBinding(binding.key);\n                });\n            }\n\n            if (commandID) {\n                if (_allCommands.indexOf(commandID) !== -1) {\n                    if (remappedCommands.indexOf(commandID) === -1) {\n                        var keybinding = { key: normalizedKey };\n\n                        keybinding.displayKey = _getDisplayKey(normalizedKey);\n                        _addBinding(commandID, keybinding.displayKey ? keybinding : normalizedKey, brackets.platform, true);\n                        remappedCommands.push(commandID);\n                    } else {\n                        multipleKeys.push(commandID);\n                    }\n                } else {\n                    invalidCommands.push(commandID);\n                }\n            }\n        });\n\n        if (restrictedCommands.length) {\n            errorMessage = StringUtils.format(Strings.ERROR_RESTRICTED_COMMANDS, _getBulletList(restrictedCommands));\n        }\n\n        if (restrictedKeys.length) {\n            errorMessage += StringUtils.format(Strings.ERROR_RESTRICTED_SHORTCUTS, _getBulletList(restrictedKeys));\n        }\n\n        if (multipleKeys.length) {\n            errorMessage += StringUtils.format(Strings.ERROR_MULTIPLE_SHORTCUTS, _getBulletList(multipleKeys));\n        }\n\n        if (duplicateBindings.length) {\n            errorMessage += StringUtils.format(Strings.ERROR_DUPLICATE_SHORTCUTS, _getBulletList(duplicateBindings));\n        }\n\n        if (invalidKeys.length) {\n            errorMessage += StringUtils.format(Strings.ERROR_INVALID_SHORTCUTS, _getBulletList(invalidKeys));\n        }\n\n        if (invalidCommands.length) {\n            errorMessage += StringUtils.format(Strings.ERROR_NONEXISTENT_COMMANDS, _getBulletList(invalidCommands));\n        }\n\n        if (_showErrors && errorMessage) {\n            _showErrorsAndOpenKeyMap(\"\", errorMessage);\n        }\n    }\n\n    /**\n     * @private\n     *\n     * Restores the default key bindings for all the commands that are modified by each key binding\n     * specified in _customKeyMapCache (old version) but no longer specified in _customKeyMap (new version).\n     */\n    function _undoPriorUserKeyBindings() {\n        _.forEach(_customKeyMapCache, function (commandID, key) {\n            var normalizedKey  = normalizeKeyDescriptorString(key),\n                defaults       = _.find(_.toArray(_defaultKeyMap), { \"commandID\": commandID }),\n                defaultCommand = _defaultKeyMap[normalizedKey];\n\n            // We didn't modified this before, so skip it.\n            if (_isSpecialCommand(commandID) ||\n                    _isReservedShortcuts(normalizedKey)) {\n                return;\n            }\n\n            if (_isKeyAssigned(normalizedKey) &&\n                    _customKeyMap[key] !== commandID && _customKeyMap[normalizedKey] !== commandID) {\n                // Unassign the key from any command. e.g. \"Cmd-W\": \"file.open\" in _customKeyMapCache\n                // will require us to remove Cmd-W shortcut from file.open command.\n                removeBinding(normalizedKey);\n            }\n\n            // Reassign the default key binding. e.g. \"Cmd-W\": \"file.open\" in _customKeyMapCache\n            // will require us to reassign Cmd-O shortcut to file.open command.\n            if (defaults) {\n                addBinding(commandID, defaults, brackets.platform);\n            }\n\n            // Reassign the default key binding of the previously modified command.\n            // e.g. \"Cmd-W\": \"file.open\" in _customKeyMapCache will require us to reassign Cmd-W\n            // shortcut to file.close command.\n            if (defaultCommand && defaultCommand.key) {\n                addBinding(defaultCommand.commandID, defaultCommand.key, brackets.platform);\n            }\n        });\n    }\n\n    /**\n     * @private\n     *\n     * Gets the full file path to the user key map file. In testing environment\n     * a different file path is returned so that running integration tests won't\n     * pop up the error dialog showing the errors from the actual user key map file.\n     *\n     * @return {string} full file path to the user key map file.\n     */\n    function _getUserKeyMapFilePath() {\n        if (window.isBracketsTestWindow) {\n            return brackets.app.getApplicationSupportDirectory() + \"/_test_/\" + KEYMAP_FILENAME;\n        }\n        return _userKeyMapFilePath;\n    }\n\n    /**\n     * @private\n     *\n     * Reads in the user key map file and parses its content into JSON.\n     * Returns the user key bindings if JSON has \"overrides\".\n     * Otherwise, returns an empty object or an error if the file\n     * cannot be parsed or loaded.\n     *\n     * @return {$.Promise} a jQuery promise that will be resolved with the JSON\n     * object if the user key map file has \"overrides\" property or an empty JSON.\n     * If the key map file cannot be read or cannot be parsed by the JSON parser,\n     * then the promise is rejected with an error.\n     */\n    function _readUserKeyMap() {\n        var file   = FileSystem.getFileForPath(_getUserKeyMapFilePath()),\n            result = new $.Deferred();\n\n        file.exists(function (err, doesExist) {\n            if (doesExist) {\n                FileUtils.readAsText(file)\n                    .done(function (text) {\n                        var keyMap = {};\n                        try {\n                            if (text) {\n                                var json = JSON.parse(text);\n                                // If no overrides, return an empty key map.\n                                result.resolve((json && json.overrides) || keyMap);\n                            } else {\n                                // The file is empty, so return an empty key map.\n                                result.resolve(keyMap);\n                            }\n                        } catch (err) {\n                            // Cannot parse the text read from the key map file.\n                            result.reject(err);\n                        }\n                    })\n                    .fail(function (err) {\n                        // Key map file cannot be loaded.\n                        result.reject(err);\n                    });\n            } else {\n                // Just resolve if no user key map file\n                result.resolve();\n            }\n        });\n        return result.promise();\n    }\n\n    /**\n     * @private\n     *\n     * Reads in the user key bindings and updates the key map with each user key\n     * binding by removing the existing one assigned to each key and adding\n     * new one for the specified command id. Shows errors and opens the user\n     * key map file if it cannot be parsed.\n     *\n     * This function is wrapped with debounce so that its execution is always delayed\n     * by 200 ms. The delay is required because when this function is called some\n     * extensions may still be adding some commands and their key bindings asychronously.\n     */\n    _loadUserKeyMap = _.debounce(function () {\n        _readUserKeyMap()\n            .then(function (keyMap) {\n                // Some extensions may add a new command without any key binding. So\n                // we always have to get all commands again to ensure that we also have\n                // those from any extensions installed during the current session.\n                _allCommands = CommandManager.getAll();\n\n                _customKeyMapCache = _.cloneDeep(_customKeyMap);\n                _customKeyMap = keyMap;\n                _undoPriorUserKeyBindings();\n                _applyUserKeyBindings();\n            }, function (err) {\n                _showErrorsAndOpenKeyMap(err);\n            });\n    }, 200);\n\n    /**\n     * @private\n     *\n     * Opens the existing key map file or creates a new one with default content\n     * if it does not exist.\n     */\n    function _openUserKeyMap() {\n        var userKeyMapPath = _getUserKeyMapFilePath(),\n            file = FileSystem.getFileForPath(userKeyMapPath);\n        file.exists(function (err, doesExist) {\n            if (doesExist) {\n                CommandManager.execute(Commands.FILE_OPEN, { fullPath: userKeyMapPath });\n            } else {\n                var defaultContent = \"{\\n    \\\"documentation\\\": \\\"https://github.com/adobe/brackets/wiki/User-Key-Bindings\\\",\" +\n                                     \"\\n    \\\"overrides\\\": {\" +\n                                     \"\\n        \\n    }\\n}\\n\";\n\n                FileUtils.writeText(file, defaultContent, true)\n                    .done(function () {\n                        CommandManager.execute(Commands.FILE_OPEN, { fullPath: userKeyMapPath });\n                    });\n            }\n        });\n    }\n\n    // Due to circular dependencies, not safe to call on() directly\n    EventDispatcher.on_duringInit(CommandManager, \"commandRegistered\", _handleCommandRegistered);\n    CommandManager.register(Strings.CMD_OPEN_KEYMAP, Commands.FILE_OPEN_KEYMAP, _openUserKeyMap);\n\n    // Asynchronously loading DocumentManager to avoid the circular dependency\n    require([\"document/DocumentManager\"], function (DocumentManager) {\n        DocumentManager.on(\"documentSaved\", function checkKeyMapUpdates(e, doc) {\n            if (doc && doc.file.fullPath === _userKeyMapFilePath) {\n                _loadUserKeyMap();\n            }\n        });\n    });\n\n    /**\n     * @private\n     *\n     * Initializes _allCommands array and _defaultKeyMap so that we can use them for\n     * detecting non-existent commands and restoring the original key binding.\n     */\n    function _initCommandAndKeyMaps() {\n        _allCommands = CommandManager.getAll();\n        // Keep a copy of the default key bindings before loading user key bindings.\n        _defaultKeyMap = _.cloneDeep(_keyMap);\n    }\n\n    /**\n     * @private\n     *\n     * Sets the full file path to the user key map file. Only used by unit tests\n     * to load a test file instead of the actual user key map file.\n     *\n     * @param {string} fullPath file path to the user key map file.\n     */\n    function _setUserKeyMapFilePath(fullPath) {\n        _userKeyMapFilePath = fullPath;\n    }\n\n    AppInit.extensionsLoaded(function () {\n        var params  = new UrlParams();\n        params.parse();\n        if (params.get(\"reloadWithoutUserExts\") === \"true\") {\n            _showErrors = false;\n        }\n\n        _initCommandAndKeyMaps();\n        _loadUserKeyMap();\n    });\n\n    // unit test only\n    exports._reset = _reset;\n    exports._setUserKeyMapFilePath = _setUserKeyMapFilePath;\n    exports._getDisplayKey = _getDisplayKey;\n    exports._loadUserKeyMap = _loadUserKeyMap;\n    exports._initCommandAndKeyMaps = _initCommandAndKeyMaps;\n    exports._onCtrlUp = _onCtrlUp;\n\n    // Define public API\n    exports.getKeymap = getKeymap;\n    exports.addBinding = addBinding;\n    exports.removeBinding = removeBinding;\n    exports.formatKeyDescriptor = formatKeyDescriptor;\n    exports.getKeyBindings = getKeyBindings;\n    exports.addGlobalKeydownHook = addGlobalKeydownHook;\n    exports.removeGlobalKeydownHook = removeGlobalKeydownHook;\n\n    /**\n     * Use windows-specific bindings if no other are found (e.g. Linux).\n     * Core Brackets modules that use key bindings should always define at\n     * least a generic keybinding that is applied for all platforms. This\n     * setting effectively creates a compatibility mode for third party\n     * extensions that define explicit key bindings for Windows and Mac, but\n     * not Linux.\n     */\n    exports.useWindowsCompatibleBindings = false;\n\n    // For unit testing only\n    exports._handleKey = _handleKey;\n    exports._handleKeyEvent = _handleKeyEvent;\n});\n"
  },
  {
    "path": "src/command/Menus.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    // Load dependent modules\n    var Commands            = require(\"command/Commands\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        KeyBindingManager   = require(\"command/KeyBindingManager\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PopUpManager        = require(\"widgets/PopUpManager\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\");\n\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    /**\n     * Brackets Application Menu Constants\n     * @enum {string}\n     */\n    var AppMenuBar = {\n        FILE_MENU       : \"file-menu\",\n        EDIT_MENU       : \"edit-menu\",\n        FIND_MENU       : \"find-menu\",\n        VIEW_MENU       : \"view-menu\",\n        NAVIGATE_MENU   : \"navigate-menu\",\n        HELP_MENU       : \"help-menu\"\n    };\n\n    /**\n     * Brackets Context Menu Constants\n     * @enum {string}\n     */\n    var ContextMenuIds = {\n        EDITOR_MENU:                    \"editor-context-menu\",\n        INLINE_EDITOR_MENU:             \"inline-editor-context-menu\",\n        PROJECT_MENU:                   \"project-context-menu\",\n        WORKING_SET_CONTEXT_MENU:       \"workingset-context-menu\",\n        WORKING_SET_CONFIG_MENU:        \"workingset-configuration-menu\",\n        SPLITVIEW_MENU:                 \"splitview-menu\"\n    };\n\n    /**\n     * Brackets Application Menu Section Constants\n     * It is preferred that plug-ins specify the location of new MenuItems\n     * in terms of a menu section rather than a specific MenuItem. This provides\n     * looser coupling to Bracket's internal MenuItems and makes menu organization\n     * more semantic.\n     * Use these constants as the \"relativeID\" parameter when calling addMenuItem() and\n     * specify a position of FIRST_IN_SECTION or LAST_IN_SECTION.\n     *\n     * Menu sections are denoted by dividers or the beginning/end of a menu\n     */\n    var MenuSection = {\n        // Menu Section                     Command ID to mark the section\n        FILE_OPEN_CLOSE_COMMANDS:           {sectionMarker: Commands.FILE_NEW},\n        FILE_SAVE_COMMANDS:                 {sectionMarker: Commands.FILE_SAVE},\n        FILE_LIVE:                          {sectionMarker: Commands.FILE_LIVE_FILE_PREVIEW},\n        FILE_EXTENSION_MANAGER:             {sectionMarker: Commands.FILE_EXTENSION_MANAGER},\n\n        EDIT_UNDO_REDO_COMMANDS:            {sectionMarker: Commands.EDIT_UNDO},\n        EDIT_TEXT_COMMANDS:                 {sectionMarker: Commands.EDIT_CUT},\n        EDIT_SELECTION_COMMANDS:            {sectionMarker: Commands.EDIT_SELECT_ALL},\n        EDIT_MODIFY_SELECTION:              {sectionMarker: Commands.EDIT_INDENT},\n        EDIT_COMMENT_SELECTION:             {sectionMarker: Commands.EDIT_LINE_COMMENT},\n        EDIT_CODE_HINTS_COMMANDS:           {sectionMarker: Commands.SHOW_CODE_HINTS},\n        EDIT_TOGGLE_OPTIONS:                {sectionMarker: Commands.TOGGLE_CLOSE_BRACKETS},\n\n        FIND_FIND_COMMANDS:                 {sectionMarker: Commands.CMD_FIND},\n        FIND_FIND_IN_COMMANDS:              {sectionMarker: Commands.CMD_FIND_IN_FILES},\n        FIND_REPLACE_COMMANDS:              {sectionMarker: Commands.CMD_REPLACE},\n\n        VIEW_HIDESHOW_COMMANDS:             {sectionMarker: Commands.VIEW_HIDE_SIDEBAR},\n        VIEW_FONTSIZE_COMMANDS:             {sectionMarker: Commands.VIEW_INCREASE_FONT_SIZE},\n        VIEW_TOGGLE_OPTIONS:                {sectionMarker: Commands.TOGGLE_ACTIVE_LINE},\n\n        NAVIGATE_GOTO_COMMANDS:             {sectionMarker: Commands.NAVIGATE_QUICK_OPEN},\n        NAVIGATE_DOCUMENTS_COMMANDS:        {sectionMarker: Commands.NAVIGATE_NEXT_DOC},\n        NAVIGATE_OS_COMMANDS:               {sectionMarker: Commands.NAVIGATE_SHOW_IN_FILE_TREE},\n        NAVIGATE_QUICK_EDIT_COMMANDS:       {sectionMarker: Commands.TOGGLE_QUICK_EDIT},\n        NAVIGATE_QUICK_DOCS_COMMANDS:       {sectionMarker: Commands.TOGGLE_QUICK_DOCS}\n    };\n\n\n    /**\n     * Insertion position constants\n     * Used by addMenu(), addMenuItem(), and addSubMenu() to\n     * specify the relative position of a newly created menu object\n     * @enum {string}\n     */\n    var BEFORE           = \"before\",\n        AFTER            = \"after\",\n        FIRST            = \"first\",\n        LAST             = \"last\",\n        FIRST_IN_SECTION = \"firstInSection\",\n        LAST_IN_SECTION  = \"lastInSection\";\n\n    /**\n     * Other constants\n     */\n    var DIVIDER = \"---\";\n    var SUBMENU = \"SUBMENU\";\n\n    /**\n     * Error Codes from Brackets Shell\n     * @enum {number}\n     */\n    var NO_ERROR           = 0,\n        ERR_UNKNOWN        = 1,\n        ERR_INVALID_PARAMS = 2,\n        ERR_NOT_FOUND      = 3;\n\n    /**\n     * Maps menuID's to Menu objects\n     * @type {Object.<string, Menu>}\n     */\n    var menuMap = {};\n\n    /**\n     * Maps contextMenuID's to ContextMenu objects\n     * @type {Object.<string, ContextMenu>}\n     */\n    var contextMenuMap = {};\n\n    /**\n     * Maps menuItemID's to MenuItem objects\n     * @type {Object.<string, MenuItem>}\n     */\n    var menuItemMap = {};\n\n    /**\n     * Retrieves the Menu object for the corresponding id.\n     * @param {string} id\n     * @return {Menu}\n     */\n    function getMenu(id) {\n        return menuMap[id];\n    }\n\n    /**\n     * Retrieves the map of all Menu objects.\n     * @return {Object.<string, Menu>}\n     */\n    function getAllMenus() {\n        return menuMap;\n    }\n\n    /**\n     * Retrieves the ContextMenu object for the corresponding id.\n     * @param {string} id\n     * @return {ContextMenu}\n     */\n    function getContextMenu(id) {\n        return contextMenuMap[id];\n    }\n\n    /**\n    * Removes the attached event listeners from the corresponding object.\n    * @param {ManuItem} menuItem\n    */\n    function removeMenuItemEventListeners(menuItem) {\n        menuItem._command\n            .off(\"enabledStateChange\", menuItem._enabledChanged)\n            .off(\"checkedStateChange\", menuItem._checkedChanged)\n            .off(\"nameChange\", menuItem._nameChanged)\n            .off(\"keyBindingAdded\", menuItem._keyBindingAdded)\n            .off(\"keyBindingRemoved\", menuItem._keyBindingRemoved);\n    }\n\n    /**\n     * Check whether a ContextMenu exists for the given id.\n     * @param {string} id\n     * @return {boolean}\n     */\n    function _isContextMenu(id) {\n        return !!getContextMenu(id);\n    }\n\n    function _isHTMLMenu(id) {\n        return (!brackets.nativeMenus || _isContextMenu(id));\n    }\n\n    /**\n     * Retrieves the MenuItem object for the corresponding id.\n     * @param {string} id\n     * @return {MenuItem}\n     */\n    function getMenuItem(id) {\n        return menuItemMap[id];\n    }\n\n    function _getHTMLMenu(id) {\n        return $(\"#\" + StringUtils.jQueryIdEscape(id)).get(0);\n    }\n\n    function _getHTMLMenuItem(id) {\n        return $(\"#\" + StringUtils.jQueryIdEscape(id)).get(0);\n    }\n\n    function _addKeyBindingToMenuItem($menuItem, key, displayKey) {\n        var $shortcut = $menuItem.find(\".menu-shortcut\");\n\n        if ($shortcut.length === 0) {\n            $shortcut = $(\"<span class='menu-shortcut' />\");\n            $menuItem.append($shortcut);\n        }\n\n        $shortcut.data(\"key\", key);\n        $shortcut.text(KeyBindingManager.formatKeyDescriptor(displayKey));\n    }\n\n    function _addExistingKeyBinding(menuItem) {\n        var bindings = KeyBindingManager.getKeyBindings(menuItem.getCommand().getID()),\n            binding = null;\n\n        if (bindings.length > 0) {\n            // add the latest key binding\n            binding = bindings[bindings.length - 1];\n            _addKeyBindingToMenuItem($(_getHTMLMenuItem(menuItem.id)), binding.key, binding.displayKey);\n        }\n\n        return binding;\n    }\n\n    var _menuDividerIDCount = 1;\n    function _getNextMenuItemDividerID() {\n        return \"brackets-menuDivider-\" + _menuDividerIDCount++;\n    }\n\n    // Help function for inserting elements into a list\n    function _insertInList($list, $element, position, $relativeElement) {\n        // Determine where to insert. Default is LAST.\n        var inserted = false;\n        if (position) {\n\n            // Adjust relative position for menu section positions since $relativeElement\n            // has already been resolved by _getRelativeMenuItem() to a menuItem\n            if (position === FIRST_IN_SECTION) {\n                position = BEFORE;\n            } else if (position === LAST_IN_SECTION) {\n                position = AFTER;\n            }\n\n            if (position === FIRST) {\n                $list.prepend($element);\n                inserted = true;\n            } else if ($relativeElement && $relativeElement.length > 0) {\n                if (position === AFTER) {\n                    $relativeElement.after($element);\n                    inserted = true;\n                } else if (position === BEFORE) {\n                    $relativeElement.before($element);\n                    inserted = true;\n                }\n            }\n        }\n\n        // Default to LAST\n        if (!inserted) {\n            $list.append($element);\n        }\n    }\n\n    /**\n     * MenuItem represents a single menu item that executes a Command or a menu divider. MenuItems\n     * may have a sub-menu. A MenuItem may correspond to an HTML-based\n     * menu item or a native menu item if Brackets is running in a native application shell\n     *\n     * Since MenuItems may have a native implementation clients should create MenuItems through\n     * addMenuItem() and should NOT construct a MenuItem object directly.\n     * Clients should also not access HTML content of a menu directly and instead use\n     * the MenuItem API to query and modify menus items.\n     *\n     * MenuItems are views on to Command objects so modify the underlying Command to modify the\n     * name, enabled, and checked state of a MenuItem. The MenuItem will update automatically\n     *\n     * @constructor\n     * @private\n     *\n     * @param {string} id\n     * @param {string|Command} command - the Command this MenuItem will reflect.\n     *                                   Use DIVIDER to specify a menu divider\n     */\n    function MenuItem(id, command) {\n        this.id = id;\n        this.isDivider = (command === DIVIDER);\n        this.isNative = false;\n\n        if (!this.isDivider && command !== SUBMENU) {\n            // Bind event handlers\n            this._enabledChanged = this._enabledChanged.bind(this);\n            this._checkedChanged = this._checkedChanged.bind(this);\n            this._nameChanged = this._nameChanged.bind(this);\n            this._keyBindingAdded = this._keyBindingAdded.bind(this);\n            this._keyBindingRemoved = this._keyBindingRemoved.bind(this);\n\n            this._command = command;\n            this._command\n                .on(\"enabledStateChange\", this._enabledChanged)\n                .on(\"checkedStateChange\", this._checkedChanged)\n                .on(\"nameChange\", this._nameChanged)\n                .on(\"keyBindingAdded\", this._keyBindingAdded)\n                .on(\"keyBindingRemoved\", this._keyBindingRemoved);\n        }\n    }\n\n    /**\n     * Menu represents a top-level menu in the menu bar. A Menu may correspond to an HTML-based\n     * menu or a native menu if Brackets is running in a native application shell.\n     *\n     * Since menus may have a native implementation clients should create Menus through\n     * addMenu() and should NOT construct a Menu object directly.\n     * Clients should also not access HTML content of a menu directly and instead use\n     * the Menu API to query and modify menus.\n     *\n     * @constructor\n     * @private\n     *\n     * @param {string} id\n     */\n    function Menu(id) {\n        this.id = id;\n    }\n\n    Menu.prototype._getMenuItemId = function (commandId) {\n        return (this.id + \"-\" + commandId);\n    };\n\n    /**\n     * Determine MenuItem in this Menu, that has the specified command\n     *\n     * @param {Command} command - the command to search for.\n     * @return {?HTMLLIElement} menu item list element\n     */\n    Menu.prototype._getMenuItemForCommand = function (command) {\n        if (!command) {\n            return null;\n        }\n        var foundMenuItem = menuItemMap[this._getMenuItemId(command.getID())];\n        if (!foundMenuItem) {\n            return null;\n        }\n        return $(_getHTMLMenuItem(foundMenuItem.id)).closest(\"li\");\n    };\n\n    /**\n     * Determine relative MenuItem\n     *\n     * @param {?string} relativeID - id of command (future: sub-menu).\n     * @param {?string} position - only needed when relativeID is a MenuSection\n     * @return {?HTMLLIElement} menu item list element\n     */\n    Menu.prototype._getRelativeMenuItem = function (relativeID, position) {\n        var $relativeElement;\n\n        if (relativeID) {\n            if (position === FIRST_IN_SECTION || position === LAST_IN_SECTION) {\n                if (!relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.error(\"Bad Parameter in _getRelativeMenuItem(): relativeID must be a MenuSection when position refers to a menu section\");\n                    return null;\n                }\n\n                // Determine the $relativeElement by traversing the sibling list and\n                // stop at the first divider found\n                // TODO: simplify using nextUntil()/prevUntil()\n                var $sectionMarker = this._getMenuItemForCommand(CommandManager.get(relativeID.sectionMarker));\n                if (!$sectionMarker) {\n                    console.error(\"_getRelativeMenuItem(): MenuSection \" + relativeID.sectionMarker +\n                                  \" not found in Menu \" + this.id);\n                    return null;\n                }\n                var $listElem = $sectionMarker;\n                $relativeElement = $listElem;\n                while (true) {\n                    $listElem = (position === FIRST_IN_SECTION ? $listElem.prev() : $listElem.next());\n                    if ($listElem.length === 0) {\n                        break;\n                    } else if ($listElem.find(\".divider\").length > 0) {\n                        break;\n                    } else {\n                        $relativeElement = $listElem;\n                    }\n                }\n\n            } else {\n                if (relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.error(\"Bad Parameter in _getRelativeMenuItem(): if relativeID is a MenuSection, position must be FIRST_IN_SECTION or LAST_IN_SECTION\");\n                    return null;\n                }\n\n                // handle FIRST, LAST, BEFORE, & AFTER\n                var command = CommandManager.get(relativeID);\n                if (command) {\n                    // Lookup Command for this Command id\n                    // Find MenuItem that has this command\n                    $relativeElement = this._getMenuItemForCommand(command);\n                }\n                if (!$relativeElement) {\n                    console.error(\"_getRelativeMenuItem(): MenuItem with Command id \" + relativeID +\n                                  \" not found in Menu \" + this.id);\n                    return null;\n                }\n            }\n\n            return $relativeElement;\n\n        } else if (position && position !== FIRST && position !== LAST) {\n            console.error(\"Bad Parameter in _getRelativeMenuItem(): relative position specified with no relativeID\");\n            return null;\n        }\n\n        return $relativeElement;\n    };\n\n    /**\n     * Removes the specified menu item from this Menu. Key bindings are unaffected; use KeyBindingManager\n     * directly to remove key bindings if desired.\n     *\n     * @param {!string | Command} command - command the menu would execute if we weren't deleting it.\n     */\n    Menu.prototype.removeMenuItem = function (command) {\n        var menuItemID,\n            commandID;\n\n        if (!command) {\n            console.error(\"removeMenuItem(): missing required parameters: command\");\n            return;\n        }\n\n        if (typeof (command) === \"string\") {\n            var commandObj = CommandManager.get(command);\n            if (!commandObj) {\n                console.error(\"removeMenuItem(): command not found: \" + command);\n                return;\n            }\n            commandID = command;\n        } else {\n            commandID = command.getID();\n        }\n        menuItemID = this._getMenuItemId(commandID);\n\n        var menuItem = getMenuItem(menuItemID);\n        removeMenuItemEventListeners(menuItem);\n\n        if (_isHTMLMenu(this.id)) {\n            // Targeting parent to get the menu item <a> and the <li> that contains it\n            $(_getHTMLMenuItem(menuItemID)).parent().remove();\n        } else {\n            brackets.app.removeMenuItem(commandID, function (err) {\n                if (err) {\n                    console.error(\"removeMenuItem() -- command not found: \" + commandID + \" (error: \" + err + \")\");\n                }\n            });\n        }\n\n        delete menuItemMap[menuItemID];\n    };\n\n    /**\n     * Removes the specified menu divider from this Menu.\n     *\n     * @param {!string} menuItemID - the menu item id of the divider to remove.\n     */\n    Menu.prototype.removeMenuDivider = function (menuItemID) {\n        var menuItem,\n            $HTMLMenuItem;\n\n        if (!menuItemID) {\n            console.error(\"removeMenuDivider(): missing required parameters: menuItemID\");\n            return;\n        }\n\n        menuItem = getMenuItem(menuItemID);\n\n        if (!menuItem) {\n            console.error(\"removeMenuDivider(): parameter menuItemID: %s is not a valid menu item id\", menuItemID);\n            return;\n        }\n\n        if (!menuItem.isDivider) {\n            console.error(\"removeMenuDivider(): parameter menuItemID: %s is not a menu divider\", menuItemID);\n            return;\n        }\n\n        if (_isHTMLMenu(this.id)) {\n            // Targeting parent to get the menu divider <hr> and the <li> that contains it\n            $HTMLMenuItem = $(_getHTMLMenuItem(menuItemID)).parent();\n            if ($HTMLMenuItem) {\n                $HTMLMenuItem.remove();\n            } else {\n                console.error(\"removeMenuDivider(): HTML menu divider not found: %s\", menuItemID);\n                return;\n            }\n        } else {\n            brackets.app.removeMenuItem(menuItem.dividerId, function (err) {\n                if (err) {\n                    console.error(\"removeMenuDivider() -- divider not found: %s (error: %s)\", menuItemID, err);\n                }\n            });\n        }\n\n        if (!menuItemMap[menuItemID]) {\n            console.error(\"removeMenuDivider(): menu divider not found in menuItemMap: %s\", menuItemID);\n            return;\n        }\n\n        delete menuItemMap[menuItemID];\n    };\n\n    /**\n     * Adds a new menu item with the specified id and display text. The insertion position is\n     * specified via the relativeID and position arguments which describe a position\n     * relative to another MenuItem or MenuGroup. It is preferred that plug-ins\n     * insert new  MenuItems relative to a menu section rather than a specific\n     * MenuItem (see Menu Section Constants).\n     *\n     * TODO: Sub-menus are not yet supported, but when they are implemented this API will\n     * allow adding new MenuItems to sub-menus as well.\n     *\n     * Note, keyBindings are bound to Command objects not MenuItems. The provided keyBindings\n     *      will be bound to the supplied Command object rather than the MenuItem.\n     *\n     * @param {!string | Command} command - the command the menu will execute.\n     *      Pass Menus.DIVIDER for a menu divider, or just call addMenuDivider() instead.\n     * @param {?string | Array.<{key: string, platform: string}>}  keyBindings - register one\n     *      one or more key bindings to associate with the supplied command.\n     * @param {?string} position - constant defining the position of new MenuItem relative to\n     *      other MenuItems. Values:\n     *          - With no relativeID, use Menus.FIRST or LAST (default is LAST)\n     *          - Relative to a command id, use BEFORE or AFTER (required)\n     *          - Relative to a MenuSection, use FIRST_IN_SECTION or LAST_IN_SECTION (required)\n     * @param {?string} relativeID - command id OR one of the MenuSection.* constants. Required\n     *      for all position constants except FIRST and LAST.\n     *\n     * @return {MenuItem} the newly created MenuItem\n     */\n    Menu.prototype.addMenuItem = function (command, keyBindings, position, relativeID) {\n        var menuID = this.id,\n            id,\n            $menuItem,\n            menuItem,\n            name,\n            commandID;\n\n        if (!command) {\n            console.error(\"addMenuItem(): missing required parameters: command\");\n            return null;\n        }\n\n        if (typeof (command) === \"string\") {\n            if (command === DIVIDER) {\n                name = DIVIDER;\n                commandID = _getNextMenuItemDividerID();\n            } else {\n                commandID = command;\n                command = CommandManager.get(commandID);\n                if (!command) {\n                    console.error(\"addMenuItem(): commandID not found: \" + commandID);\n                    return null;\n                }\n                name = command.getName();\n            }\n        } else {\n            commandID = command.getID();\n            name = command.getName();\n        }\n\n        // Internal id is the a composite of the parent menu id and the command id.\n        id = this._getMenuItemId(commandID);\n\n        if (menuItemMap[id]) {\n            console.log(\"MenuItem added with same id of existing MenuItem: \" + id);\n            return null;\n        }\n\n        // create MenuItem\n        menuItem = new MenuItem(id, command);\n        menuItemMap[id] = menuItem;\n\n        // create MenuItem DOM\n        if (_isHTMLMenu(this.id)) {\n            if (name === DIVIDER) {\n                $menuItem = $(\"<li><hr class='divider' id='\" + id + \"' /></li>\");\n            } else {\n                // Create the HTML Menu\n                $menuItem = $(\"<li><a href='#' id='\" + id + \"'> <span class='menu-name'></span></a></li>\");\n\n                $menuItem.on(\"click\", function () {\n                    menuItem._command.execute();\n                });\n\n                var self = this;\n                $menuItem.on(\"mouseenter\", function () {\n                    self.closeSubMenu();\n                });\n            }\n\n            // Insert menu item\n            var $relativeElement = this._getRelativeMenuItem(relativeID, position);\n            _insertInList($(\"li#\" + StringUtils.jQueryIdEscape(this.id) + \" > ul.dropdown-menu\"),\n                          $menuItem, position, $relativeElement);\n        } else {\n            var bindings = KeyBindingManager.getKeyBindings(commandID),\n                binding,\n                bindingStr = \"\",\n                displayStr = \"\";\n\n            if (bindings && bindings.length > 0) {\n                binding = bindings[bindings.length - 1];\n                bindingStr = binding.displayKey || binding.key;\n            }\n\n            if (bindingStr.length > 0) {\n                displayStr = KeyBindingManager.formatKeyDescriptor(bindingStr);\n            }\n\n            if (position === FIRST_IN_SECTION || position === LAST_IN_SECTION) {\n                if (!relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.error(\"Bad Parameter in _getRelativeMenuItem(): relativeID must be a MenuSection when position refers to a menu section\");\n                    return null;\n                }\n\n                // For sections, pass in the marker for that section.\n                relativeID = relativeID.sectionMarker;\n            }\n\n            brackets.app.addMenuItem(this.id, name, commandID, bindingStr, displayStr, position, relativeID, function (err) {\n                switch (err) {\n                case NO_ERROR:\n                    break;\n                case ERR_INVALID_PARAMS:\n                    console.error(\"addMenuItem(): Invalid Parameters when adding the command \" + commandID);\n                    break;\n                case ERR_NOT_FOUND:\n                    console.error(\"_getRelativeMenuItem(): MenuItem with Command id \" + relativeID + \" not found in the Menu \" + menuID);\n                    break;\n                default:\n                    console.error(\"addMenuItem(); Unknown Error (\" + err + \") when adding the command \" + commandID);\n                }\n            });\n            menuItem.isNative = true;\n        }\n\n        // Initialize MenuItem state\n        if (menuItem.isDivider) {\n            menuItem.dividerId = commandID;\n        } else {\n            if (keyBindings) {\n                // Add key bindings. The MenuItem listens to the Command object to update MenuItem DOM with shortcuts.\n                if (!Array.isArray(keyBindings)) {\n                    keyBindings = [keyBindings];\n                }\n            }\n\n            // Note that keyBindings passed during MenuItem creation take precedent over any existing key bindings\n            KeyBindingManager.addBinding(commandID, keyBindings);\n\n            // Look for existing key bindings\n            _addExistingKeyBinding(menuItem);\n\n            menuItem._checkedChanged();\n            menuItem._enabledChanged();\n            menuItem._nameChanged();\n        }\n\n        return menuItem;\n    };\n\n    /**\n     * Inserts divider item in menu.\n     * @param {?string} position - constant defining the position of new the divider relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants).\n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new\n     *      divider will be positioned relative to. Required for all position constants\n     *      except FIRST and LAST\n     *\n     * @return {MenuItem} the newly created divider\n     */\n    Menu.prototype.addMenuDivider = function (position, relativeID) {\n        return this.addMenuItem(DIVIDER, \"\", position, relativeID);\n    };\n\n    /**\n     * NOT IMPLEMENTED\n     * Alternative JSON based API to addMenuItem()\n     *\n     * All properties are required unless noted as optional.\n     *\n     * @param { Array.<{\n     *              id:         string,\n     *              command:    string | Command,\n     *              ?bindings:   string | Array.<{key: string, platform: string}>,\n     *          }>} jsonStr\n     *        }\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants).\n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new\n     *      menuItem will be positioned relative to. Required when position is\n     *      AFTER or BEFORE, ignored when position is FIRST or LAST.\n     *\n     * @return {MenuItem} the newly created MenuItem\n     */\n    // Menu.prototype.createMenuItemsFromJSON = function (jsonStr, position, relativeID) {\n    //     NOT IMPLEMENTED\n    // };\n\n\n    /**\n     * NOT IMPLEMENTED\n     * @param {!string} text displayed in menu item\n     * @param {!string} id\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants)\n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new\n     *      menuItem will be positioned relative to. Required when position is\n     *      AFTER or BEFORE, ignored when position is FIRST or LAST.\n     *\n     * @return {MenuItem} newly created menuItem for sub-menu\n     */\n    // MenuItem.prototype.createSubMenu = function (text, id, position, relativeID) {\n    //     NOT IMPLEMENTED\n    // };\n\n    /**\n     *\n     * Creates a new submenu and a menuItem and adds the menuItem of the submenu\n     * to the menu and returns the submenu.\n     *\n     * A submenu will have the same structure of a menu with a additional field\n     * parentMenuItem which has the reference of the submenu's parent menuItem.\n\n     * A submenu will raise the following events:\n     * - beforeSubMenuOpen\n     * - beforeSubMenuClose\n     *\n     * Note, This function will create only a context submenu.\n     *\n     * TODO: Make this function work for Menus\n     *\n     *\n     * @param {!string} name displayed in menu item of the submenu\n     * @param {!string} id\n     * @param {?string} position - constant defining the position of new MenuItem of the submenu relative to\n     *      other MenuItems. Values:\n     *          - With no relativeID, use Menus.FIRST or LAST (default is LAST)\n     *          - Relative to a command id, use BEFORE or AFTER (required)\n     *          - Relative to a MenuSection, use FIRST_IN_SECTION or LAST_IN_SECTION (required)\n     * @param {?string} relativeID - command id OR one of the MenuSection.* constants. Required\n     *      for all position constants except FIRST and LAST.\n     *\n     * @return {Menu} the newly created submenu\n     */\n    Menu.prototype.addSubMenu = function (name, id, position, relativeID) {\n\n        if (!name || !id) {\n            console.error(\"addSubMenu(): missing required parameters: name and id\");\n            return null;\n        }\n\n        // Guard against duplicate context menu ids\n        if (contextMenuMap[id]) {\n            console.log(\"Context menu added with id of existing Context Menu: \" + id);\n            return null;\n        }\n\n        var menu = new ContextMenu(id);\n        contextMenuMap[id] = menu;\n\n        var menuItemID = this.id + \"-\" + id;\n\n        if (menuItemMap[menuItemID]) {\n            console.log(\"MenuItem added with same id of existing MenuItem: \" + id);\n            return null;\n        }\n\n        // create MenuItem\n        var menuItem = new MenuItem(menuItemID, SUBMENU);\n        menuItemMap[menuItemID] = menuItem;\n\n        menu.parentMenuItem = menuItem;\n\n        // create MenuItem DOM\n        if (_isHTMLMenu(this.id)) {\n            // Create the HTML MenuItem\n            var $menuItem = $(\"<li><a href='#' id='\" + menuItemID + \"'> \"   +\n                             \"<span class='menu-name'>\" + name + \"</span>\" +\n                             \"<span style='float: right'>&rtrif;</span>\"   +\n                             \"</a></li>\");\n\n            var self = this;\n            $menuItem.on(\"mouseenter\", function(e) {\n                if (self.openSubMenu && self.openSubMenu.id === menu.id) {\n                    return;\n                }\n                self.closeSubMenu();\n                self.openSubMenu = menu;\n                menu.open();\n            });\n\n            // Insert menu item\n            var $relativeElement = this._getRelativeMenuItem(relativeID, position);\n            _insertInList($(\"li#\" + StringUtils.jQueryIdEscape(this.id) + \" > ul.dropdown-menu\"),\n            $menuItem, position, $relativeElement);\n        } else {\n            // TODO: add submenus for native menus\n        }\n        return menu;\n    };\n\n\n    /**\n     * Removes the specified submenu from this Menu.\n     *\n     * Note, this function will only remove context submenus\n     *\n     * TODO: Make this function work for Menus\n     *\n     * @param {!string} subMenuID - the menu id of the submenu to remove.\n     */\n    Menu.prototype.removeSubMenu = function (subMenuID) {\n        var subMenu,\n            parentMenuItem,\n            commandID = \"\";\n\n        if (!subMenuID) {\n            console.error(\"removeSubMenu(): missing required parameters: subMenuID\");\n            return;\n        }\n\n        subMenu = getContextMenu(subMenuID);\n\n        if (!subMenu || !subMenu.parentMenuItem) {\n            console.error(\"removeSubMenu(): parameter subMenuID: %s is not a valid submenu id\", subMenuID);\n            return;\n        }\n\n        parentMenuItem = subMenu.parentMenuItem;\n\n\n        if (!menuItemMap[parentMenuItem.id]) {\n            console.error(\"removeSubMenu(): parent menuItem not found in menuItemMap: %s\", parentMenuItem.id);\n            return;\n        }\n\n        // Remove all of the menu items in the submenu\n        _.forEach(menuItemMap, function (value, key) {\n            if (_.startsWith(key, subMenuID)) {\n                if (value.isDivider) {\n                    subMenu.removeMenuDivider(key);\n                } else {\n                    commandID = value.getCommand();\n                    subMenu.removeMenuItem(commandID);\n                }\n            }\n        });\n\n        if (_isHTMLMenu(this.id)) {\n            $(_getHTMLMenuItem(parentMenuItem.id)).parent().remove(); // remove the menu item\n            $(_getHTMLMenu(subMenuID)).remove(); // remove the menu\n        } else {\n            // TODO: remove submenus for native menus\n        }\n\n\n        delete menuItemMap[parentMenuItem.id];\n        delete contextMenuMap[subMenuID];\n    };\n\n    /**\n     * Closes the submenu if the menu has a submenu open.\n     */\n    Menu.prototype.closeSubMenu = function() {\n        if (this.openSubMenu) {\n            this.openSubMenu.close();\n            this.openSubMenu = null;\n        }\n    };\n    /**\n     * Gets the Command associated with a MenuItem\n     * @return {Command}\n     */\n    MenuItem.prototype.getCommand = function () {\n        return this._command;\n    };\n\n    /**\n     * NOT IMPLEMENTED\n     * Returns the parent MenuItem if the menu item is a sub-menu, returns null otherwise.\n     * @return {MenuItem}\n     */\n    // MenuItem.prototype.getParentMenuItem = function () {\n    //     NOT IMPLEMENTED;\n    // };\n\n    /**\n     * Returns the parent Menu for this MenuItem\n     * @return {Menu}\n     */\n    MenuItem.prototype.getParentMenu = function () {\n        var parent = $(_getHTMLMenuItem(this.id)).parents(\".dropdown\").get(0);\n        if (!parent) {\n            return null;\n        }\n\n        return getMenu(parent.id);\n    };\n\n    /**\n     * Synchronizes MenuItem checked state with underlying Command checked state\n     */\n    MenuItem.prototype._checkedChanged = function () {\n        var checked = !!this._command.getChecked();\n        if (this.isNative) {\n            var enabled = !!this._command.getEnabled();\n            brackets.app.setMenuItemState(this._command.getID(), enabled, checked, function (err) {\n                if (err) {\n                    console.log(\"Error setting menu item state: \" + err);\n                }\n            });\n        } else {\n            ViewUtils.toggleClass($(_getHTMLMenuItem(this.id)), \"checked\", checked);\n        }\n    };\n\n    /**\n     * Synchronizes MenuItem enabled state with underlying Command enabled state\n     */\n    MenuItem.prototype._enabledChanged = function () {\n        if (this.isNative) {\n            var enabled = !!this._command.getEnabled();\n            var checked = !!this._command.getChecked();\n            brackets.app.setMenuItemState(this._command.getID(), enabled, checked, function (err) {\n                if (err) {\n                    console.log(\"Error setting menu item state: \" + err);\n                }\n            });\n        } else {\n            ViewUtils.toggleClass($(_getHTMLMenuItem(this.id)), \"disabled\", !this._command.getEnabled());\n        }\n    };\n\n    /**\n     * Synchronizes MenuItem name with underlying Command name\n     */\n    MenuItem.prototype._nameChanged = function () {\n        if (this.isNative) {\n            brackets.app.setMenuTitle(this._command.getID(), this._command.getName(), function (err) {\n                if (err) {\n                    console.log(\"Error setting menu title: \" + err);\n                }\n            });\n        } else {\n            $(_getHTMLMenuItem(this.id)).find(\".menu-name\").text(this._command.getName());\n        }\n    };\n\n    /**\n     * @private\n     * Updates MenuItem DOM with a keyboard shortcut label\n     */\n    MenuItem.prototype._keyBindingAdded = function (event, keyBinding) {\n        if (this.isNative) {\n            var shortcutKey = keyBinding.displayKey || keyBinding.key;\n            brackets.app.setMenuItemShortcut(this._command.getID(), shortcutKey, KeyBindingManager.formatKeyDescriptor(shortcutKey), function (err) {\n                if (err) {\n                    console.error(\"Error setting menu item shortcut: \" + err);\n                }\n            });\n        } else {\n            _addKeyBindingToMenuItem($(_getHTMLMenuItem(this.id)), keyBinding.key, keyBinding.displayKey);\n        }\n    };\n\n    /**\n     * @private\n     * Updates MenuItem DOM to remove keyboard shortcut label\n     */\n    MenuItem.prototype._keyBindingRemoved = function (event, keyBinding) {\n        if (this.isNative) {\n            brackets.app.setMenuItemShortcut(this._command.getID(), \"\", \"\", function (err) {\n                if (err) {\n                    console.error(\"Error setting menu item shortcut: \" + err);\n                }\n            });\n        } else {\n            var $shortcut = $(_getHTMLMenuItem(this.id)).find(\".menu-shortcut\");\n\n            if ($shortcut.length > 0 && $shortcut.data(\"key\") === keyBinding.key) {\n                // check for any other bindings\n                if (_addExistingKeyBinding(this) === null) {\n                    $shortcut.empty();\n                }\n            }\n        }\n    };\n\n    /**\n     * Closes all menus that are open\n     */\n    function closeAll() {\n        $(\".dropdown\").removeClass(\"open\");\n    }\n\n    /**\n     * Adds a top-level menu to the application menu bar which may be native or HTML-based.\n     *\n     * @param {!string} name - display text for menu\n     * @param {!string} id - unique identifier for a menu.\n     *      Core Menus in Brackets use a simple  title as an id, for example \"file-menu\".\n     *      Extensions should use the following format: \"author.myextension.mymenuname\".\n     * @param {?string} position - constant defining the position of new the Menu relative\n     *  to other Menus. Default is LAST (see Insertion position constants).\n     *\n     * @param {?string} relativeID - id of Menu the new Menu will be positioned relative to. Required\n     *      when position is AFTER or BEFORE, ignored when position is FIRST or LAST\n     *\n     * @return {?Menu} the newly created Menu\n     */\n    function addMenu(name, id, position, relativeID) {\n        name = _.escape(name);\n        var $menubar = $(\"#titlebar .nav\"),\n            menu;\n\n        if (!name || !id) {\n            console.error(\"call to addMenu() is missing required parameters\");\n            return null;\n        }\n\n        // Guard against duplicate menu ids\n        if (menuMap[id]) {\n            console.log(\"Menu added with same name and id of existing Menu: \" + id);\n            return null;\n        }\n\n        menu = new Menu(id);\n        menuMap[id] = menu;\n\n        if (!_isHTMLMenu(id)) {\n            brackets.app.addMenu(name, id, position, relativeID, function (err) {\n                switch (err) {\n                case NO_ERROR:\n                    // Make sure name is up to date\n                    brackets.app.setMenuTitle(id, name, function (err) {\n                        if (err) {\n                            console.error(\"setMenuTitle() -- error: \" + err);\n                        }\n                    });\n                    break;\n                case ERR_UNKNOWN:\n                    console.error(\"addMenu(): Unknown Error when adding the menu \" + id);\n                    break;\n                case ERR_INVALID_PARAMS:\n                    console.error(\"addMenu(): Invalid Parameters when adding the menu \" + id);\n                    break;\n                case ERR_NOT_FOUND:\n                    console.error(\"addMenu(): Menu with command \" + relativeID + \" could not be found when adding the menu \" + id);\n                    break;\n                default:\n                    console.error(\"addMenu(): Unknown Error (\" + err + \") when adding the menu \" + id);\n                }\n            });\n            return menu;\n        }\n\n        var $toggle = $(\"<a href='#' class='dropdown-toggle' data-toggle='dropdown'>\" + name + \"</a>\"),\n            $popUp = $(\"<ul class='dropdown-menu'></ul>\"),\n            $newMenu = $(\"<li class='dropdown' id='\" + id + \"'></li>\").append($toggle).append($popUp);\n\n        // Insert menu\n        var $relativeElement = relativeID && $(_getHTMLMenu(relativeID));\n        _insertInList($menubar, $newMenu, position, $relativeElement);\n\n        // Install ESC key handling\n        PopUpManager.addPopUp($popUp, closeAll, false);\n\n        // todo error handling\n\n        return menu;\n    }\n\n    /**\n     * Removes a top-level menu from the application menu bar which may be native or HTML-based.\n     *\n     * @param {!string} id - unique identifier for a menu.\n     *      Core Menus in Brackets use a simple title as an id, for example \"file-menu\".\n     *      Extensions should use the following format: \"author.myextension.mymenuname\".\n     */\n    function removeMenu(id) {\n        var menu,\n            commandID = \"\";\n\n        if (!id) {\n            console.error(\"removeMenu(): missing required parameter: id\");\n            return;\n        }\n\n        if (!menuMap[id]) {\n            console.error(\"removeMenu(): menu id not found: %s\", id);\n            return;\n        }\n\n        // Remove all of the menu items in the menu\n        menu = getMenu(id);\n\n        _.forEach(menuItemMap, function (value, key) {\n            if (_.startsWith(key, id)) {\n                if (value.isDivider) {\n                    menu.removeMenuDivider(key);\n                } else {\n                    commandID = value.getCommand();\n                    menu.removeMenuItem(commandID);\n                }\n            }\n        });\n\n        if (_isHTMLMenu(id)) {\n            $(_getHTMLMenu(id)).remove();\n        } else {\n            brackets.app.removeMenu(id, function (err) {\n                if (err) {\n                    console.error(\"removeMenu() -- id not found: \" + id + \" (error: \" + err + \")\");\n                }\n            });\n        }\n\n        delete menuMap[id];\n    }\n\n    /**\n     * Represents a context menu that can open at a specific location in the UI.\n     *\n     * Clients should not create this object directly and should instead use registerContextMenu()\n     * to create new ContextMenu objects.\n     *\n     * Context menus in brackets may be HTML-based or native so clients should not reach into\n     * the HTML and should instead manipulate ContextMenus through the API.\n     *\n     * Events:\n     * - beforeContextMenuOpen\n     * - beforeContextMenuClose\n     *\n     * @constructor\n     * @extends {Menu}\n     */\n    function ContextMenu(id) {\n        Menu.apply(this, arguments);\n\n        var $newMenu = $(\"<li class='dropdown context-menu' id='\" + StringUtils.jQueryIdEscape(id) + \"'></li>\"),\n            $popUp = $(\"<ul class='dropdown-menu'></ul>\"),\n            $toggle = $(\"<a href='#' class='dropdown-toggle' data-toggle='dropdown'></a>\").hide();\n\n        // assemble the menu fragments\n        $newMenu.append($toggle).append($popUp);\n\n        // insert into DOM\n        $(\"#context-menu-bar > ul\").append($newMenu);\n\n        var self = this;\n        PopUpManager.addPopUp($popUp,\n            function () {\n                self.close();\n            },\n            false);\n\n        // Listen to ContextMenu's beforeContextMenuOpen event to first close other popups\n        PopUpManager.listenToContextMenu(this);\n    }\n    ContextMenu.prototype = Object.create(Menu.prototype);\n    ContextMenu.prototype.constructor = ContextMenu;\n    ContextMenu.prototype.parentClass = Menu.prototype;\n    EventDispatcher.makeEventDispatcher(ContextMenu.prototype);\n\n\n    /**\n     * Displays the ContextMenu at the specified location and dispatches the\n     * \"beforeContextMenuOpen\" event or \"beforeSubMenuOpen\" event (for submenus).\n     * The menu location may be adjusted to prevent clipping by the browser window.\n     * All other menus and ContextMenus will be closed before a new menu\n     * will be closed before a new menu is shown (if the new menu is not\n     * a submenu).\n     *\n     * In case of submenus, the parentMenu of the submenu will not be closed when the\n     * sub menu is open.\n     *\n     * @param {MouseEvent | {pageX:number, pageY:number}} mouseOrLocation - pass a MouseEvent\n     *      to display the menu near the mouse or pass in an object with page x/y coordinates\n     *      for a specific location.This paramter is not used for submenus. Submenus are always\n     *      displayed at a position relative to the parent menu.\n     */\n    ContextMenu.prototype.open = function (mouseOrLocation) {\n\n        if (!this.parentMenuItem &&\n           (!mouseOrLocation || !mouseOrLocation.hasOwnProperty(\"pageX\") || !mouseOrLocation.hasOwnProperty(\"pageY\"))) {\n            console.error(\"ContextMenu open(): missing required parameter\");\n            return;\n        }\n\n        var $window = $(window),\n            escapedId = StringUtils.jQueryIdEscape(this.id),\n            $menuAnchor = $(\"#\" + escapedId),\n            $menuWindow = $(\"#\" + escapedId + \" > ul\"),\n            posTop,\n            posLeft;\n\n        // only show context menu if it has menu items\n        if ($menuWindow.children().length <= 0) {\n            return;\n        }\n\n\n        // adjust positioning so menu is not clipped off bottom or right\n        if (this.parentMenuItem) { // If context menu is a submenu\n\n            this.trigger(\"beforeSubMenuOpen\");\n\n            var $parentMenuItem = $(_getHTMLMenuItem(this.parentMenuItem.id));\n\n            posTop = $parentMenuItem.offset().top;\n            posLeft = $parentMenuItem.offset().left + $parentMenuItem.outerWidth();\n\n            var elementRect = {\n                top:    posTop,\n                left:   posLeft,\n                height: $menuWindow.height() + 25,\n                width:  $menuWindow.width()\n            },\n            clip = ViewUtils.getElementClipSize($window, elementRect);\n\n            if (clip.bottom > 0) {\n                posTop = Math.max(0, posTop + $parentMenuItem.height() - $menuWindow.height());\n            }\n\n            posTop -= 30;   // shift top for hidden parent element\n            posLeft += 3;\n\n            if (clip.right > 0) {\n                posLeft = Math.max(0, posLeft - $parentMenuItem.outerWidth() - $menuWindow.outerWidth());\n            }\n        } else {\n            this.trigger(\"beforeContextMenuOpen\");\n\n            // close all other dropdowns\n            closeAll();\n\n            posTop  = mouseOrLocation.pageY;\n            posLeft = mouseOrLocation.pageX;\n\n            var elementRect = {\n                top:    posTop,\n                left:   posLeft,\n                height: $menuWindow.height() + 25,\n                width:  $menuWindow.width()\n            },\n            clip = ViewUtils.getElementClipSize($window, elementRect);\n\n            if (clip.bottom > 0) {\n                posTop = Math.max(0, posTop - clip.bottom);\n            }\n            posTop -= 30;   // shift top for hidden parent element\n            posLeft += 5;\n\n\n            if (clip.right > 0) {\n                posLeft = Math.max(0, posLeft - clip.right);\n            }\n        }\n\n        // open the context menu at final location\n        $menuAnchor.addClass(\"open\")\n                   .css({\"left\": posLeft, \"top\": posTop});\n    };\n\n\n    /**\n     * Closes the context menu.\n     */\n    ContextMenu.prototype.close = function () {\n        if (this.parentMenuItem) {\n            this.trigger(\"beforeSubMenuClose\");\n        } else {\n            this.trigger(\"beforeContextMenuClose\");\n        }\n        this.closeSubMenu();\n        $(\"#\" + StringUtils.jQueryIdEscape(this.id)).removeClass(\"open\");\n    };\n\n    /**\n     * Detect if current context menu is already open\n     */\n    ContextMenu.prototype.isOpen = function () {\n        return $(\"#\" + StringUtils.jQueryIdEscape(this.id)).hasClass(\"open\");\n    };\n\n\n    /**\n     * Associate a context menu to a DOM element.\n     * This static function take care of registering event handlers for the click event\n     * listener and passing the right \"position\" object to the Context#open method\n     */\n    ContextMenu.assignContextMenuToSelector = function (selector, cmenu) {\n        $(selector).on(\"click\", function (e) {\n            var buttonOffset,\n                buttonHeight;\n\n            e.stopPropagation();\n\n            if (cmenu.isOpen()) {\n                cmenu.close();\n            } else {\n                buttonOffset = $(this).offset();\n                buttonHeight = $(this).outerHeight();\n                cmenu.open({\n                    pageX: buttonOffset.left,\n                    pageY: buttonOffset.top + buttonHeight\n                });\n            }\n        });\n    };\n\n\n    /**\n     * Registers new context menu with Brackets.\n\n     * Extensions should generally use the predefined context menus built into Brackets. Use this\n     * API to add a new context menu to UI that is specific to an extension.\n     *\n     * After registering  a new context menu clients should:\n     *      - use addMenuItem() to add items to the context menu\n     *      - call open() to show the context menu.\n     *      For example:\n     *      $(\"#my_ID\").contextmenu(function (e) {\n     *          if (e.which === 3) {\n     *              my_cmenu.open(e);\n     *          }\n     *      });\n     *\n     * To make menu items be contextual to things like selection, listen for the \"beforeContextMenuOpen\"\n     * to make changes to Command objects before the context menu is shown. MenuItems are views of\n     * Commands, which control a MenuItem's name, enabled state, and checked state.\n     *\n     * @param {string} id - unique identifier for context menu.\n     *      Core context menus in Brackets use a simple title as an id.\n     *      Extensions should use the following format: \"author.myextension.mycontextmenu name\"\n     * @return {?ContextMenu} the newly created context menu\n     */\n    function registerContextMenu(id) {\n        if (!id) {\n            console.error(\"call to registerContextMenu() is missing required parameters\");\n            return null;\n        }\n\n        // Guard against duplicate menu ids\n        if (contextMenuMap[id]) {\n            console.log(\"Context Menu added with same name and id of existing Context Menu: \" + id);\n            return null;\n        }\n\n        var cmenu = new ContextMenu(id);\n        contextMenuMap[id] = cmenu;\n        return cmenu;\n    }\n\n    // Deprecated menu ids\n    DeprecationWarning.deprecateConstant(ContextMenuIds, \"WORKING_SET_MENU\", \"WORKING_SET_CONTEXT_MENU\");\n    DeprecationWarning.deprecateConstant(ContextMenuIds, \"WORKING_SET_SETTINGS_MENU\", \"WORKING_SET_CONFIG_MENU\");\n\n    // Define public API\n    exports.AppMenuBar = AppMenuBar;\n    exports.ContextMenuIds = ContextMenuIds;\n    exports.MenuSection = MenuSection;\n    exports.BEFORE = BEFORE;\n    exports.AFTER = AFTER;\n    exports.LAST = LAST;\n    exports.FIRST = FIRST;\n    exports.FIRST_IN_SECTION = FIRST_IN_SECTION;\n    exports.LAST_IN_SECTION = LAST_IN_SECTION;\n    exports.DIVIDER = DIVIDER;\n    exports.getMenu = getMenu;\n    exports.getAllMenus = getAllMenus;\n    exports.getMenuItem = getMenuItem;\n    exports.getContextMenu = getContextMenu;\n    exports.addMenu = addMenu;\n    exports.removeMenu = removeMenu;\n    exports.registerContextMenu = registerContextMenu;\n    exports.closeAll = closeAll;\n    exports.Menu = Menu;\n    exports.MenuItem = MenuItem;\n    exports.ContextMenu = ContextMenu;\n});\n"
  },
  {
    "path": "src/dependencies.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Check for missing dependencies\n */\nwindow.setTimeout(function () {\n    \"use strict\";\n\n    var key, missingDeps = \"\";\n    var deps = { \"jQuery\": window.$, \"RequireJS\": window.require };\n\n    for (key in deps) {\n        if (deps.hasOwnProperty(key) && !deps[key]) {\n            missingDeps += \"<li>\" + key + \"</li>\";\n        }\n    }\n\n    if (missingDeps.length > 0) {\n        var str = \"<h1>Missing libraries</h1>\" +\n                  \"<p>Oops! One or more required libraries could not be found.</p>\" +\n                  \"<ul>\" + missingDeps + \"</ul>\" +\n                  \"<p>If you're running from a local copy of the Brackets source, please make sure submodules are updated by running:</p>\" +\n                  \"<pre>git submodule update --init</pre>\" +\n                  \"<p>If you're still having problems, please contact us via one of the channels mentioned at the bottom of the <a target=\\\"blank\\\" href=\\\"../README.md\\\">README</a>.</p>\" +\n                  \"<p><a href=\\\"#\\\" onclick=\\\"window.location.reload()\\\">Reload Brackets</a></p>\";\n\n        window.document.write(str);\n    }\n}, 1000);\n"
  },
  {
    "path": "src/document/ChangedDocumentTracker.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Defines a ChangedDocumentTracker class to monitor changes to files in the current project.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DocumentManager = require(\"document/DocumentManager\"),\n        ProjectManager  = require(\"project/ProjectManager\");\n\n    /**\n     * Tracks \"change\" events on opened Documents. Used to monitor changes\n     * to documents in-memory and update caches. Assumes all documents have\n     * changed when the Brackets window loses and regains focus. Does not\n     * read timestamps of files on disk. Clients may optionally track file\n     * timestamps on disk independently.\n     * @constructor\n     */\n    function ChangedDocumentTracker() {\n        var self = this;\n\n        this._changedPaths = {};\n        this._windowFocus = true;\n        this._addListener = this._addListener.bind(this);\n        this._removeListener = this._removeListener.bind(this);\n        this._onChange = this._onChange.bind(this);\n        this._onWindowFocus = this._onWindowFocus.bind(this);\n\n        DocumentManager.on(\"afterDocumentCreate\", function (event, doc) {\n            // Only track documents in the current project\n            if (ProjectManager.isWithinProject(doc.file.fullPath)) {\n                self._addListener(doc);\n            }\n        });\n\n        DocumentManager.on(\"beforeDocumentDelete\", function (event, doc) {\n            // In case a document somehow remains loaded after its project\n            // has been closed, unconditionally attempt to remove the listener.\n            self._removeListener(doc);\n        });\n\n        $(window).focus(this._onWindowFocus);\n    }\n\n    /**\n     * @private\n     * Assumes all files are changed when the window loses and regains focus.\n     */\n    ChangedDocumentTracker.prototype._addListener = function (doc) {\n        doc.on(\"change\", this._onChange);\n    };\n\n    /**\n     * @private\n     */\n    ChangedDocumentTracker.prototype._removeListener = function (doc) {\n        doc.off(\"change\", this._onChange);\n    };\n\n    /**\n     * @private\n     * Assumes all files are changed when the window loses and regains focus.\n     */\n    ChangedDocumentTracker.prototype._onWindowFocus = function (event, doc) {\n        this._windowFocus = true;\n    };\n\n    /**\n     * @private\n     * Tracks changed documents.\n     */\n    ChangedDocumentTracker.prototype._onChange = function (event, doc) {\n        // if it was already changed, and the client hasn't reset the tracker,\n        // then leave it changed.\n        this._changedPaths[doc.file.fullPath] = true;\n    };\n\n    /**\n     * Empty the set of dirty paths. Begin tracking new dirty documents.\n     */\n    ChangedDocumentTracker.prototype.reset = function () {\n        this._changedPaths = {};\n        this._windowFocus = false;\n    };\n\n    /**\n     * Check if a file path is dirty.\n     * @param {!string} file path\n     * @return {!boolean} Returns true if the file was dirtied since the last reset.\n     */\n    ChangedDocumentTracker.prototype.isPathChanged = function (path) {\n        return this._windowFocus || this._changedPaths[path];\n    };\n\n    /**\n     * Get the set of changed paths since the last reset.\n     * @return {Array.<string>} Changed file paths\n     */\n    ChangedDocumentTracker.prototype.getChangedPaths = function () {\n        return $.makeArray(this._changedPaths);\n    };\n\n    module.exports = ChangedDocumentTracker;\n});\n"
  },
  {
    "path": "src/document/Document.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = require(\"editor/EditorManager\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        InMemoryFile        = require(\"document/InMemoryFile\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        CodeMirror          = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    /**\n     * Model for the contents of a single file and its current modification state.\n     * See DocumentManager documentation for important usage notes.\n     *\n     * Document dispatches these events:\n     *\n     * __change__ -- When the text of the editor changes (including due to undo/redo).\n     *\n     * Passes ({Document}, {ChangeList}), where ChangeList is an array\n     * of change record objects. Each change record looks like:\n     *\n     *     { from: start of change, expressed as {line: <line number>, ch: <character offset>},\n     *       to: end of change, expressed as {line: <line number>, ch: <chracter offset>},\n     *       text: array of lines of text to replace existing text }\n     *\n     * The line and ch offsets are both 0-based.\n     *\n     * The ch offset in \"from\" is inclusive, but the ch offset in \"to\" is exclusive. For example,\n     * an insertion of new content (without replacing existing content) is expressed by a range\n     * where from and to are the same.\n     *\n     * If \"from\" and \"to\" are undefined, then this is a replacement of the entire text content.\n     *\n     * IMPORTANT: If you listen for the \"change\" event, you MUST also addRef() the document\n     * (and releaseRef() it whenever you stop listening). You should also listen to the \"deleted\"\n     * event.\n     *\n     * __deleted__ -- When the file for this document has been deleted. All views onto the document should\n     * be closed. The document will no longer be editable or dispatch \"change\" events.\n     *\n     * __languageChanged__ -- When the value of getLanguage() has changed. 2nd argument is the old value,\n     * 3rd argument is the new value.\n     *\n     * @constructor\n     * @param {!File} file  Need not lie within the project.\n     * @param {!Date} initialTimestamp  File's timestamp when we read it off disk.\n     * @param {!string} rawText  Text content of the file.\n     */\n    function Document(file, initialTimestamp, rawText) {\n        this.file = file;\n        this.editable = !file.readOnly;\n        this._updateLanguage();\n        this.refreshText(rawText, initialTimestamp, true);\n        // List of full editors which are initialized as master editors for this doc.\n        this._associatedFullEditors = [];\n    }\n\n    EventDispatcher.makeEventDispatcher(Document.prototype);\n\n    /**\n     * Number of clients who want this Document to stay alive. The Document is listed in\n     * DocumentManager._openDocuments whenever refCount > 0.\n     */\n    Document.prototype._refCount = 0;\n\n    /**\n     * The File for this document. Need not lie within the project.\n     * If Document is untitled, this is an InMemoryFile object.\n     * @type {!File}\n     */\n    Document.prototype.file = null;\n\n    /**\n     * The Language for this document. Will be resolved by file extension in the constructor\n     * @type {!Language}\n     */\n    Document.prototype.language = null;\n\n    /**\n     * Whether this document has unsaved changes or not.\n     * When this changes on any Document, DocumentManager dispatches a \"dirtyFlagChange\" event.\n     * @type {boolean}\n     */\n    Document.prototype.isDirty = false;\n\n    /**\n     * Whether this document is currently being saved.\n     * @type {boolean}\n     */\n    Document.prototype.isSaving = false;\n\n    /**\n     * What we expect the file's timestamp to be on disk. If the timestamp differs from this, then\n     * it means the file was modified by an app other than Brackets.\n     * @type {!Date}\n     */\n    Document.prototype.diskTimestamp = null;\n\n    /**\n     * The timestamp of the document at the point where the user last said to keep changes that conflict\n     * with the current disk version. Can also be -1, indicating that the file was deleted on disk at the\n     * last point when the user said to keep changes, or null, indicating that the user has not said to\n     * keep changes.\n     * Note that this is a time as returned by Date.getTime(), not a Date object.\n     * @type {?Number}\n     */\n    Document.prototype.keepChangesTime = null;\n\n    /**\n     * True while refreshText() is in progress and change notifications shouldn't trip the dirty flag.\n     * @type {boolean}\n     */\n    Document.prototype._refreshInProgress = false;\n\n    /**\n     * The text contents of the file, or null if our backing model is _masterEditor.\n     * @type {?string}\n     */\n    Document.prototype._text = null;\n\n    /**\n     * Editor object representing the full-size editor UI for this document. May be null if Document\n     * has not yet been modified or been the currentDocument; in that case, our backing model is the\n     * string _text.\n     * @type {?Editor}\n     */\n    Document.prototype._masterEditor = null;\n\n    /**\n     * The content's line-endings style. If a Document is created on empty text, or text with\n     * inconsistent line endings, defaults to the current platform's standard endings.\n     * @type {FileUtils.LINE_ENDINGS_CRLF|FileUtils.LINE_ENDINGS_LF}\n     */\n    Document.prototype._lineEndings = null;\n\n    /** Add a ref to keep this Document alive */\n    Document.prototype.addRef = function () {\n        //console.log(\"+++REF+++ \"+this);\n\n        if (this._refCount === 0) {\n            //console.log(\"+++ adding to open list\");\n            if (exports.trigger(\"_afterDocumentCreate\", this)) {\n                return;\n            }\n        }\n        this._refCount++;\n    };\n    /** Remove a ref that was keeping this Document alive */\n    Document.prototype.releaseRef = function () {\n        //console.log(\"---REF--- \"+this);\n\n        this._refCount--;\n        if (this._refCount < 0) {\n            console.error(\"Document ref count has fallen below zero!\");\n            return;\n        }\n        if (this._refCount === 0) {\n            //console.log(\"--- removing from open list\");\n            if (exports.trigger(\"_beforeDocumentDelete\", this)) {\n                return;\n            }\n        }\n    };\n\n    /**\n     * Attach a backing Editor to the Document, enabling setText() to be called. Assumes Editor has\n     * already been initialized with the value of getText(). ONLY Editor should call this (and only\n     * when EditorManager has told it to act as the master editor).\n     * @param {!Editor} masterEditor\n     */\n    Document.prototype._makeEditable = function (masterEditor) {\n\n        this._text = null;\n        this._masterEditor = masterEditor;\n\n        masterEditor.on(\"change\", this._handleEditorChange.bind(this));\n    };\n\n    /**\n     * Detach the backing Editor from the Document, disallowing setText(). The text content is\n     * stored back onto _text so other Document clients continue to have read-only access. ONLY\n     * Editor.destroy() should call this.\n     */\n    Document.prototype._makeNonEditable = function () {\n        if (!this._masterEditor) {\n            console.error(\"Document is already non-editable\");\n        } else {\n            // _text represents the raw text, so fetch without normalized line endings\n            this._text = this.getText(true);\n            this._associatedFullEditors.splice(this._associatedFullEditors.indexOf(this._masterEditor), 1);\n\n            // Identify the most recently created full editor before this and set that as new master editor\n            if (this._associatedFullEditors.length > 0) {\n                this._masterEditor = this._associatedFullEditors[this._associatedFullEditors.length - 1];\n            } else {\n                this._masterEditor = null;\n            }\n        }\n    };\n\n    /**\n     * Toggles the master editor which has gained focus from a pool of full editors\n     * To be used internally by Editor only\n     */\n    Document.prototype._toggleMasterEditor = function (masterEditor) {\n        // Do a check before processing the request to ensure inline editors are not being set as master editor\n        if (this.file === masterEditor.document.file && this._associatedFullEditors.indexOf(masterEditor) >= 0) {\n            this._masterEditor = masterEditor;\n        }\n    };\n\n\n    /**\n     * Checks and returns if a full editor exists for the provided pane attached to this document\n     * @param {String} paneId\n     * @return {Editor} Attached editor bound to the provided pane id\n     */\n    Document.prototype._checkAssociatedEditorForPane = function (paneId) {\n        var editorCount, editorForPane;\n        for (editorCount = 0; editorCount < this._associatedFullEditors.length; ++editorCount) {\n            if (this._associatedFullEditors[editorCount]._paneId === paneId) {\n                editorForPane = this._associatedFullEditors[editorCount];\n                break;\n            }\n        }\n\n        return editorForPane;\n    };\n\n    /**\n     * Disassociates an editor from this document if present in the associated editor list\n     * To be used internally by Editor only when destroyed and not the current master editor for the document\n     */\n    Document.prototype._disassociateEditor = function (editor) {\n        // Do a check before processing the request to ensure inline editors are not being handled\n        if (this._associatedFullEditors.indexOf(editor) >= 0) {\n            this._associatedFullEditors.splice(this._associatedFullEditors.indexOf(editor), 1);\n        }\n    };\n\n    /**\n     * Aassociates a full editor to this document\n     * To be used internally by Editor only when pane marking happens\n     */\n    Document.prototype._associateEditor = function (editor) {\n        // Do a check before processing the request to ensure inline editors are not being handled\n        if (this._associatedFullEditors.indexOf(editor) === -1) {\n            this._associatedFullEditors.push(editor);\n        }\n    };\n\n    /**\n     * Guarantees that _masterEditor is non-null. If needed, asks EditorManager to create a new master\n     * editor bound to this Document (which in turn causes Document._makeEditable() to be called).\n     * Should ONLY be called by Editor and Document.\n     */\n    Document.prototype._ensureMasterEditor = function () {\n        if (!this._masterEditor) {\n            EditorManager._createUnattachedMasterEditor(this);\n        }\n    };\n\n    /**\n     * Returns the document's current contents; may not be saved to disk yet. Whenever this\n     * value changes, the Document dispatches a \"change\" event.\n     *\n     * @param {boolean=} useOriginalLineEndings If true, line endings in the result depend on the\n     *      Document's line endings setting (based on OS & the original text loaded from disk).\n     *      If false, line endings are always \\n (like all the other Document text getter methods).\n     * @return {string}\n     */\n    Document.prototype.getText = function (useOriginalLineEndings) {\n        if (this._masterEditor) {\n            // CodeMirror.getValue() always returns text with LF line endings; fix up to match line\n            // endings preferred by the document, if necessary\n            var codeMirrorText = this._masterEditor._codeMirror.getValue();\n            if (useOriginalLineEndings) {\n                if (this._lineEndings === FileUtils.LINE_ENDINGS_CRLF) {\n                    return codeMirrorText.replace(/\\n/g, \"\\r\\n\");\n                }\n            }\n            return codeMirrorText;\n\n        } else {\n            // Optimized path that doesn't require creating master editor\n            if (useOriginalLineEndings) {\n                return this._text;\n            } else {\n                return Document.normalizeText(this._text);\n            }\n        }\n    };\n\n    /** Normalizes line endings the same way CodeMirror would */\n    Document.normalizeText = function (text) {\n        return text.replace(/\\r\\n/g, \"\\n\");\n    };\n\n    /**\n     * Sets the contents of the document. Treated as an edit. Line endings will be rewritten to\n     * match the document's current line-ending style.\n     * @param {!string} text The text to replace the contents of the document with.\n     */\n    Document.prototype.setText = function (text) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.setValue(text);\n        // _handleEditorChange() triggers \"change\" event\n    };\n\n    /**\n     * @private\n     * Triggers the appropriate events when a change occurs: \"change\" on the Document instance\n     * and \"documentChange\" on the Document module.\n     * @param {Object} changeList Changelist in CodeMirror format\n     */\n    Document.prototype._notifyDocumentChange = function (changeList) {\n        this.trigger(\"change\", this, changeList);\n        exports.trigger(\"documentChange\", this, changeList);\n    };\n\n    /**\n     * Sets the contents of the document. Treated as reloading the document from disk: the document\n     * will be marked clean with a new timestamp, the undo/redo history is cleared, and we re-check\n     * the text's line-ending style. CAN be called even if there is no backing editor.\n     * @param {!string} text The text to replace the contents of the document with.\n     * @param {!Date} newTimestamp Timestamp of file at the time we read its new contents from disk.\n     * @param {boolean} initial True if this is the initial load of the document. In that case,\n     *      we don't send change events.\n     */\n    Document.prototype.refreshText = function (text, newTimestamp, initial) {\n        var perfTimerName = PerfUtils.markStart(\"refreshText:\\t\" + (!this.file || this.file.fullPath));\n\n        // If clean, don't transiently mark dirty during refresh\n        // (we'll still send change events though, of course)\n        this._refreshInProgress = true;\n\n        if (this._masterEditor) {\n            this._masterEditor._resetText(text);  // clears undo history too\n            // _handleEditorChange() triggers \"change\" event for us\n        } else {\n            this._text = text;\n\n            if (!initial) {\n                // We fake a change record here that looks like CodeMirror's text change records, but\n                // omits \"from\" and \"to\", by which we mean the entire text has changed.\n                // TODO: Dumb to split it here just to join it again in the change handler, but this is\n                // the CodeMirror change format. Should we document our change format to allow this to\n                // either be an array of lines or a single string?\n                this._notifyDocumentChange([{text: text.split(/\\r?\\n/)}]);\n            }\n        }\n        this._updateTimestamp(newTimestamp);\n\n        // If Doc was dirty before refresh, reset it to clean now (don't always call, to avoid no-op dirtyFlagChange events) Since\n        // _resetText() above already ensures Editor state is clean, it's safe to skip _markClean() as long as our own state is already clean too.\n        if (this.isDirty) {\n            this._markClean();\n        }\n        this._refreshInProgress = false;\n\n        // Sniff line-ending style\n        this._lineEndings = FileUtils.sniffLineEndings(text);\n        if (!this._lineEndings) {\n            this._lineEndings = FileUtils.getPlatformLineEndings();\n        }\n\n        exports.trigger(\"_documentRefreshed\", this);\n\n        PerfUtils.addMeasurement(perfTimerName);\n    };\n\n    /**\n     * Adds, replaces, or removes text. If a range is given, the text at that range is replaced with the\n     * given new text; if text == \"\", then the entire range is effectively deleted. If 'end' is omitted,\n     * then the new text is inserted at that point and all existing text is preserved. Line endings will\n     * be rewritten to match the document's current line-ending style.\n     *\n     * IMPORTANT NOTE: Because of #1688, do not use this in cases where you might be\n     * operating on a linked document (like the main document for an inline editor)\n     * during an outer CodeMirror operation (like a key event that's handled by the\n     * editor itself). A common case of this is code hints in inline editors. In\n     * such cases, use `editor._codeMirror.replaceRange()` instead. This should be\n     * fixed when we migrate to use CodeMirror's native document-linking functionality.\n     *\n     * @param {!string} text  Text to insert or replace the range with\n     * @param {!{line:number, ch:number}} start  Start of range, inclusive (if 'to' specified) or insertion point (if not)\n     * @param {?{line:number, ch:number}} end  End of range, exclusive; optional\n     * @param {?string} origin  Optional string used to batch consecutive edits for undo.\n     *     If origin starts with \"+\", then consecutive edits with the same origin will be batched for undo if\n     *     they are close enough together in time.\n     *     If origin starts with \"*\", then all consecutive edit with the same origin will be batched for\n     *     undo.\n     *     Edits with origins starting with other characters will not be batched.\n     *     (Note that this is a higher level of batching than batchOperation(), which already batches all\n     *     edits within it for undo. Origin batching works across operations.)\n     */\n    Document.prototype.replaceRange = function (text, start, end, origin) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.replaceRange(text, start, end, origin);\n        // _handleEditorChange() triggers \"change\" event\n    };\n\n    /**\n     * Returns the characters in the given range. Line endings are normalized to '\\n'.\n     * @param {!{line:number, ch:number}} start  Start of range, inclusive\n     * @param {!{line:number, ch:number}} end  End of range, exclusive\n     * @return {!string}\n     */\n    Document.prototype.getRange = function (start, end) {\n        this._ensureMasterEditor();\n        return this._masterEditor._codeMirror.getRange(start, end);\n    };\n\n    /**\n     * Returns the text of the given line (excluding any line ending characters)\n     * @param {number} Zero-based line number\n     * @return {!string}\n     */\n    Document.prototype.getLine = function (lineNum) {\n        this._ensureMasterEditor();\n        return this._masterEditor._codeMirror.getLine(lineNum);\n    };\n\n    /**\n     * Batches a series of related Document changes. Repeated calls to replaceRange() should be wrapped in a\n     * batch for efficiency. Begins the batch, calls doOperation(), ends the batch, and then returns.\n     * @param {function()} doOperation\n     */\n    Document.prototype.batchOperation = function (doOperation) {\n        this._ensureMasterEditor();\n\n        var self = this;\n        self._masterEditor._codeMirror.operation(doOperation);\n    };\n\n    /**\n     * Handles changes from the master backing Editor. Changes are triggered either by direct edits\n     * to that Editor's UI, OR by our setText()/refreshText() methods.\n     * @private\n     */\n    Document.prototype._handleEditorChange = function (event, editor, changeList) {\n        // Handle editor change event only when it is originated from the master editor for this doc\n        if (this._masterEditor !== editor) {\n            return;\n        }\n\n        // TODO: This needs to be kept in sync with SpecRunnerUtils.createMockActiveDocument(). In the\n        // future, we should fix things so that we either don't need mock documents or that this\n        // is factored so it will just run in both.\n        if (!this._refreshInProgress) {\n            // Sync isDirty from CodeMirror state\n            var wasDirty = this.isDirty;\n            this.isDirty = !editor._codeMirror.isClean();\n\n            // Notify if isDirty just changed (this also auto-adds us to working set if needed)\n            if (wasDirty !== this.isDirty) {\n                exports.trigger(\"_dirtyFlagChange\", this);\n            }\n        }\n\n        // Notify that Document's text has changed\n        this._notifyDocumentChange(changeList);\n    };\n\n    /**\n     * @private\n     */\n    Document.prototype._markClean = function () {\n        this.isDirty = false;\n        if (this._masterEditor) {\n            this._masterEditor._codeMirror.markClean();\n        }\n        exports.trigger(\"_dirtyFlagChange\", this);\n    };\n\n    /**\n     * @private\n     */\n    Document.prototype._updateTimestamp = function (timestamp) {\n        this.diskTimestamp = timestamp;\n        // Clear the \"keep changes\" timestamp since it's no longer relevant.\n        this.keepChangesTime = null;\n    };\n\n    /**\n     * Called when the document is saved (which currently happens in DocumentCommandHandlers). Marks the\n     * document not dirty and notifies listeners of the save.\n     */\n    Document.prototype.notifySaved = function () {\n        if (!this._masterEditor) {\n            console.log(\"### Warning: saving a Document that is not modifiable!\");\n        }\n\n        this._markClean();\n\n        // TODO: (issue #295) fetching timestamp async creates race conditions (albeit unlikely ones)\n        var thisDoc = this;\n        this.file.stat(function (err, stat) {\n            if (!err) {\n                thisDoc._updateTimestamp(stat.mtime);\n            } else {\n                console.log(\"Error updating timestamp after saving file: \" + thisDoc.file.fullPath);\n            }\n            exports.trigger(\"_documentSaved\", thisDoc);\n        });\n    };\n\n    /**\n     * Adjusts a given position taking a given replaceRange-type edit into account.\n     * If the position is within the original edit range (start and end inclusive),\n     * it gets pushed to the end of the content that replaced the range. Otherwise,\n     * if it's after the edit, it gets adjusted so it refers to the same character\n     * it did before the edit.\n     * @param {!{line:number, ch: number}} pos The position to adjust.\n     * @param {!Array.<string>} textLines The text of the change, split into an array of lines.\n     * @param {!{line: number, ch: number}} start The start of the edit.\n     * @param {!{line: number, ch: number}} end The end of the edit.\n     * @return {{line: number, ch: number}} The adjusted position.\n     */\n    Document.prototype.adjustPosForChange = function (pos, textLines, start, end) {\n        // Same as CodeMirror.adjustForChange(), but that's a private function\n        // and Marijn would rather not expose it publicly.\n        var change = { text: textLines, from: start, to: end };\n\n        if (CodeMirror.cmpPos(pos, start) < 0) {\n            return pos;\n        }\n        if (CodeMirror.cmpPos(pos, end) <= 0) {\n            return CodeMirror.changeEnd(change);\n        }\n\n        var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1,\n            ch = pos.ch;\n        if (pos.line === change.to.line) {\n            ch += CodeMirror.changeEnd(change).ch - change.to.ch;\n        }\n        return {line: line, ch: ch};\n    };\n\n    /**\n     * Like _.each(), but if given a single item not in an array, acts as\n     * if it were an array containing just that item.\n     */\n    function oneOrEach(itemOrArr, cb) {\n        if (Array.isArray(itemOrArr)) {\n            _.each(itemOrArr, cb);\n        } else {\n            cb(itemOrArr, 0);\n        }\n    }\n\n    /**\n     * Helper function for edit operations that operate on multiple selections. Takes an \"edit list\"\n     * that specifies a list of replaceRanges that should occur, but where all the positions are with\n     * respect to the document state before all the edits (i.e., you don't have to figure out how to fix\n     * up the selections after each sub-edit). Edits must be non-overlapping (in original-document terms).\n     * All the edits are done in a single batch.\n     *\n     * If your edits are structured in such a way that each individual edit would cause its associated\n     * selection to be properly updated, then all you need to specify are the edits themselves, and the\n     * selections will automatically be updated as the edits are performed. However, for some\n     * kinds of edits, you need to fix up the selection afterwards. In that case, you can specify one\n     * or more selections to be associated with each edit. Those selections are assumed to be in terms\n     * of the document state after the edit, *as if* that edit were the only one being performed (i.e.,\n     * you don't have to worry about adjusting for the effect of other edits). If you supply these selections,\n     * then this function will adjust them as necessary for the effects of other edits, and then return a\n     * flat list of all the selections, suitable for passing to `setSelections()`.\n     *\n     * @param {!Array.<{edit: {text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}\n     *                        | Array.<{text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}>,\n     *                  selection: ?{start:{line:number, ch:number}, end:{line:number, ch:number},\n     *                              primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}\n     *                        | ?Array.<{start:{line:number, ch:number}, end:{line:number, ch:number},\n     *                                  primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}>} edits\n     *     Specifies the list of edits to perform in a manner similar to CodeMirror's `replaceRange`. This array\n     *     will be mutated.\n     *\n     *     `edit` is the edit to perform:\n     *         `text` will replace the current contents of the range between `start` and `end`.\n     *         If `end` is unspecified, the text is inserted at `start`.\n     *         `start` and `end` should be positions relative to the document *ignoring* all other edit descriptions\n     *         (i.e., as if you were only performing this one edit on the document).\n     *     If any of the edits overlap, an error will be thrown.\n     *\n     *     If `selection` is specified, it should be a selection associated with this edit.\n     *          If `isBeforeEdit` is set on the selection, the selection will be fixed up for this edit.\n     *          If not, it won't be fixed up for this edit, meaning it should be expressed in terms of\n     *          the document state after this individual edit is performed (ignoring any other edits).\n     *          Note that if you were planning on just specifying `isBeforeEdit` for every selection, you can\n     *          accomplish the same thing by simply not passing any selections and letting the editor update\n     *          the existing selections automatically.\n     *\n     *     Note that `edit` and `selection` can each be either an individual edit/selection, or a group of\n     *     edits/selections to apply in order. This can be useful if you need to perform multiple edits in a row\n     *     and then specify a resulting selection that shouldn't be fixed up for any of those edits (but should be\n     *     fixed up for edits related to other selections). It can also be useful if you have several selections\n     *     that should ignore the effects of a given edit because you've fixed them up already (this commonly happens\n     *     with line-oriented edits where multiple cursors on the same line should be ignored, but still tracked).\n     *     Within an edit group, edit positions must be specified relative to previous edits within that group. Also,\n     *     the total bounds of edit groups must not overlap (e.g. edits in one group can't surround an edit from another group).\n     *\n     * @param {?string} origin An optional edit origin that's passed through to each replaceRange().\n     * @return {Array<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean}>}\n     *     The list of passed selections adjusted for the performed edits, if any.\n     */\n    Document.prototype.doMultipleEdits = function (edits, origin) {\n        var self = this;\n\n        // Sort the edits backwards, so we don't have to adjust the edit positions as we go along\n        // (though we do have to adjust the selection positions).\n        edits.sort(function (editDesc1, editDesc2) {\n            var edit1 = (Array.isArray(editDesc1.edit) ? editDesc1.edit[0] : editDesc1.edit),\n                edit2 = (Array.isArray(editDesc2.edit) ? editDesc2.edit[0] : editDesc2.edit);\n            // Treat all no-op edits as if they should happen before all other edits (the order\n            // doesn't really matter, as long as they sort out of the way of the real edits).\n            if (!edit1) {\n                return -1;\n            } else if (!edit2) {\n                return 1;\n            } else {\n                return CodeMirror.cmpPos(edit2.start, edit1.start);\n            }\n        });\n\n        // Pull out the selections, in the same order as the edits.\n        var result = _.cloneDeep(_.pluck(edits, \"selection\"));\n\n        // Preflight the edits to specify \"end\" if unspecified and make sure they don't overlap.\n        // (We don't want to do it during the actual edits, since we don't want to apply some of\n        // the edits before we find out.)\n        _.each(edits, function (editDesc, index) {\n            oneOrEach(editDesc.edit, function (edit) {\n                if (edit) {\n                    if (!edit.end) {\n                        edit.end = edit.start;\n                    }\n                    if (index > 0) {\n                        var prevEditGroup = edits[index - 1].edit;\n                        // The edits are in reverse order, so we want to make sure this edit ends\n                        // before any of the previous ones start.\n                        oneOrEach(prevEditGroup, function (prevEdit) {\n                            if (CodeMirror.cmpPos(edit.end, prevEdit.start) > 0) {\n                                throw new Error(\"Document.doMultipleEdits(): Overlapping edits specified\");\n                            }\n                        });\n                    }\n                }\n            });\n        });\n\n        // Perform the edits.\n        this.batchOperation(function () {\n            _.each(edits, function (editDesc, index) {\n                // Perform this group of edits. The edit positions are guaranteed to be okay\n                // since all the previous edits we've done have been later in the document. However,\n                // we have to fix up any selections that overlap or come after the edit.\n                oneOrEach(editDesc.edit, function (edit) {\n                    if (edit) {\n                        self.replaceRange(edit.text, edit.start, edit.end, origin);\n\n                        // Fix up all the selections *except* the one(s) related to this edit list that\n                        // are not \"before-edit\" selections.\n                        var textLines = edit.text.split(\"\\n\");\n                        _.each(result, function (selections, selIndex) {\n                            if (selections) {\n                                oneOrEach(selections, function (sel) {\n                                    if (sel.isBeforeEdit || selIndex !== index) {\n                                        sel.start = self.adjustPosForChange(sel.start, textLines, edit.start, edit.end);\n                                        sel.end = self.adjustPosForChange(sel.end, textLines, edit.start, edit.end);\n                                    }\n                                });\n                            }\n                        });\n                    }\n                });\n            });\n        });\n\n        result = _.chain(result)\n            .filter(function (item) {\n                return item !== undefined;\n            })\n            .flatten()\n            .sort(function (sel1, sel2) {\n                return CodeMirror.cmpPos(sel1.start, sel2.start);\n            })\n            .value();\n        _.each(result, function (item) {\n            delete item.isBeforeEdit;\n        });\n        return result;\n    };\n\n    /* (pretty toString(), to aid debugging) */\n    Document.prototype.toString = function () {\n        var dirtyInfo = (this.isDirty ? \" (dirty!)\" : \" (clean)\");\n        var editorInfo = (this._masterEditor ? \" (Editable)\" : \" (Non-editable)\");\n        var refInfo = \" refs:\" + this._refCount;\n        return \"[Document \" + this.file.fullPath + dirtyInfo + editorInfo + refInfo + \"]\";\n    };\n\n    /**\n     * Returns the language this document is written in.\n     * The language returned is based on the file extension.\n     * @return {Language} An object describing the language used in this document\n     */\n    Document.prototype.getLanguage = function () {\n        return this.language;\n    };\n\n    /**\n     * Updates the language to match the current mapping given by LanguageManager\n     */\n    Document.prototype._updateLanguage = function () {\n        var oldLanguage = this.language;\n        this.language = LanguageManager.getLanguageForPath(this.file.fullPath);\n        if (oldLanguage && oldLanguage !== this.language) {\n            this.trigger(\"languageChanged\", oldLanguage, this.language);\n        }\n    };\n\n    /** Called when Document.file has been modified (due to a rename) */\n    Document.prototype._notifyFilePathChanged = function () {\n        // File extension may have changed\n        this._updateLanguage();\n    };\n\n    /**\n     * Is this an untitled document?\n     *\n     * @return {boolean} - whether or not the document is untitled\n     */\n    Document.prototype.isUntitled = function () {\n        return this.file instanceof InMemoryFile;\n    };\n\n    /**\n     *  Reloads the document from FileSystem\n     *  @return {promise} - to check if reload was successful or not\n     */\n    Document.prototype.reload = function () {\n        var $deferred = $.Deferred();\n        var self = this;\n        FileUtils.readAsText(this.file)\n            .done(function (text, readTimestamp) {\n                self.refreshText(text, readTimestamp);\n                $deferred.resolve();\n            })\n            .fail(function (error) {\n                console.log(\"Error reloading contents of \" + self.file.fullPath, error);\n                $deferred.reject();\n            });\n        return $deferred.promise();\n    };\n\n    // We dispatch events from the module level, and the instance level. Instance events are wired up\n    // in the Document constructor.\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Define public API\n    exports.Document = Document;\n});\n"
  },
  {
    "path": "src/document/DocumentCommandHandlers.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit             = require(\"utils/AppInit\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileSystemError     = require(\"filesystem/FileSystemError\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        InMemoryFile        = require(\"document/InMemoryFile\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Async               = require(\"utils/Async\"),\n        HealthLogger        = require(\"utils/HealthLogger\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        DefaultDialogs      = require(\"widgets/DefaultDialogs\"),\n        Strings             = require(\"strings\"),\n        PopUpManager        = require(\"widgets/PopUpManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        KeyEvent            = require(\"utils/KeyEvent\"),\n        Inspector           = require(\"LiveDevelopment/Inspector/Inspector\"),\n        Menus               = require(\"command/Menus\"),\n        UrlParams           = require(\"utils/UrlParams\").UrlParams,\n        StatusBar           = require(\"widgets/StatusBar\"),\n        WorkspaceManager    = require(\"view/WorkspaceManager\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    /**\n     * Handlers for commands related to document handling (opening, saving, etc.)\n     */\n\n    /**\n     * Container for label shown above editor; must be an inline element\n     * @type {jQueryObject}\n     */\n    var _$title = null;\n\n    /**\n     * Container for dirty dot; must be an inline element\n     * @type {jQueryObject}\n     */\n    var _$dirtydot = null;\n\n    /**\n     * Container for _$title; need not be an inline element\n     * @type {jQueryObject}\n     */\n    var _$titleWrapper = null;\n\n    /**\n     * Label shown above editor for current document: filename and potentially some of its path\n     * @type {string}\n     */\n    var _currentTitlePath = null;\n\n    /**\n     * Determine the dash character for each platform. Use emdash on Mac\n     * and a standard dash on all other platforms.\n     * @type {string}\n     */\n    var _osDash = brackets.platform === \"mac\" ? \"\\u2014\" : \"-\";\n\n    /**\n     * String template for window title when no file is open.\n     * @type {string}\n     */\n    var WINDOW_TITLE_STRING_NO_DOC = \"{0} \" + _osDash + \" {1}\";\n\n    /**\n    * String template for window title when a file is open.\n    * @type {string}\n    */\n    var WINDOW_TITLE_STRING_DOC = \"{0} ({1}) \" + _osDash + \" {2}\";\n\n    /**\n     * Container for _$titleWrapper; if changing title changes this element's height, must kick editor to resize\n     * @type {jQueryObject}\n     */\n    var _$titleContainerToolbar = null;\n\n    /**\n     * Last known height of _$titleContainerToolbar\n     * @type {number}\n     */\n    var _lastToolbarHeight = null;\n\n    /**\n     * index to use for next, new Untitled document\n     * @type {number}\n     */\n    var _nextUntitledIndexToUse = 1;\n\n    /**\n     * prevents reentrancy of browserReload()\n     * @type {boolean}\n     */\n    var _isReloading = false;\n\n    /** Unique token used to indicate user-driven cancellation of Save As (as opposed to file IO error) */\n    var USER_CANCELED = { userCanceled: true };\n\n    PreferencesManager.definePreference(\"defaultExtension\", \"string\", \"\", {\n        excludeFromHints: true\n    });\n    EventDispatcher.makeEventDispatcher(exports);\n\n    /**\n     * Event triggered when File Save is cancelled, when prompted to save dirty files\n     */\n    var APP_QUIT_CANCELLED = \"appQuitCancelled\";\n\n    \n    /**\n     * JSLint workaround for circular dependency\n     * @type {function}\n     */\n    var handleFileSaveAs;\n\n    /**\n     * Updates the title bar with new file title or dirty indicator\n     * @private\n     */\n    function _updateTitle() {\n        var currentDoc          = DocumentManager.getCurrentDocument(),\n            windowTitle         = brackets.config.app_title,\n            currentlyViewedFile = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE),\n            currentlyViewedPath = currentlyViewedFile && currentlyViewedFile.fullPath,\n            readOnlyString      = (currentlyViewedFile && currentlyViewedFile.readOnly) ? \"[Read Only] - \" : \"\";\n\n        if (!brackets.nativeMenus) {\n            if (currentlyViewedPath) {\n                _$title.text(_currentTitlePath);\n                _$title.attr(\"title\", currentlyViewedPath);\n                if (currentDoc) {\n                    // dirty dot is always in DOM so layout doesn't change, and visibility is toggled\n                    _$dirtydot.css(\"visibility\", (currentDoc.isDirty) ? \"visible\" : \"hidden\");\n                } else {\n                    // hide dirty dot if there is no document\n                    _$dirtydot.css(\"visibility\", \"hidden\");\n                }\n            } else {\n                _$title.text(\"\");\n                _$title.attr(\"title\", \"\");\n                _$dirtydot.css(\"visibility\", \"hidden\");\n            }\n\n            // Set _$titleWrapper to a fixed width just large enough to accommodate _$title. This seems equivalent to what\n            // the browser would do automatically, but the CSS trick we use for layout requires _$titleWrapper to have a\n            // fixed width set on it (see the \"#titlebar\" CSS rule for details).\n            _$titleWrapper.css(\"width\", \"\");\n            var newWidth = _$title.width();\n            _$titleWrapper.css(\"width\", newWidth);\n\n            // Changing the width of the title may cause the toolbar layout to change height, which needs to resize the\n            // editor beneath it (toolbar changing height due to window resize is already caught by EditorManager).\n            var newToolbarHeight = _$titleContainerToolbar.height();\n            if (_lastToolbarHeight !== newToolbarHeight) {\n                _lastToolbarHeight = newToolbarHeight;\n                WorkspaceManager.recomputeLayout();\n            }\n        }\n\n        var projectRoot = ProjectManager.getProjectRoot();\n        if (projectRoot) {\n            var projectName = projectRoot.name;\n            // Construct shell/browser window title, e.g. \"• index.html (myProject) — Brackets\"\n            if (currentlyViewedPath) {\n                windowTitle = StringUtils.format(WINDOW_TITLE_STRING_DOC, readOnlyString + _currentTitlePath, projectName, brackets.config.app_title);\n                // Display dirty dot when there are unsaved changes\n                if (currentDoc && currentDoc.isDirty) {\n                    windowTitle = \"• \" + windowTitle;\n                }\n            } else {\n                // A document is not open\n                windowTitle = StringUtils.format(WINDOW_TITLE_STRING_NO_DOC, projectName, brackets.config.app_title);\n            }\n        }\n        window.document.title = windowTitle;\n    }\n\n    /**\n     * Returns a short title for a given document.\n     *\n     * @param {Document} doc - the document to compute the short title for\n     * @return {string} - a short title for doc.\n     */\n    function _shortTitleForDocument(doc) {\n        var fullPath = doc.file.fullPath;\n\n        // If the document is untitled then return the filename, (\"Untitled-n.ext\");\n        // otherwise show the project-relative path if the file is inside the\n        // current project or the full absolute path if it's not in the project.\n        if (doc.isUntitled()) {\n            return fullPath.substring(fullPath.lastIndexOf(\"/\") + 1);\n        } else {\n            return ProjectManager.makeProjectRelativeIfPossible(fullPath);\n        }\n    }\n\n    /**\n     * Handles currentFileChange and filenameChanged events and updates the titlebar\n     */\n    function handleCurrentFileChange() {\n        var newFile = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);\n\n        if (newFile) {\n            var newDocument = DocumentManager.getOpenDocumentForPath(newFile.fullPath);\n\n            if (newDocument) {\n                _currentTitlePath = _shortTitleForDocument(newDocument);\n            } else {\n                _currentTitlePath = ProjectManager.makeProjectRelativeIfPossible(newFile.fullPath);\n            }\n        } else {\n            _currentTitlePath = null;\n        }\n\n        // Update title text & \"dirty dot\" display\n        _updateTitle();\n    }\n\n    /**\n     * Handles dirtyFlagChange event and updates the title bar if necessary\n     */\n    function handleDirtyChange(event, changedDoc) {\n        var currentDoc = DocumentManager.getCurrentDocument();\n\n        if (currentDoc && changedDoc.file.fullPath === currentDoc.file.fullPath) {\n            _updateTitle();\n        }\n    }\n\n    /**\n     * Shows an error dialog indicating that the given file could not be opened due to the given error\n     * @param {!FileSystemError} name\n     * @return {!Dialog}\n     */\n    function showFileOpenError(name, path) {\n        return Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_OPENING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_OPENING_FILE,\n                StringUtils.breakableUrl(path),\n                FileUtils.getFileErrorString(name)\n            )\n        );\n    }\n\n    /**\n     * @private\n     * Creates a document and displays an editor for the specified file path.\n     * @param {!string} fullPath\n     * @param {boolean=} silent If true, don't show error message\n     * @param {string=} paneId, the id oi the pane in which to open the file. Can be undefined, a valid pane id or ACTIVE_PANE.\n     * @param {{*}=} options, command options\n     * @return {$.Promise} a jQuery promise that will either\n     * - be resolved with a file for the specified file path or\n     * - be rejected with FileSystemError if the file can not be read.\n     * If paneId is undefined, the ACTIVE_PANE constant\n     */\n    function _doOpen(fullPath, silent, paneId, options) {\n        var result = new $.Deferred();\n\n        // workaround for https://github.com/adobe/brackets/issues/6001\n        // TODO should be removed once bug is closed.\n        // if we are already displaying a file do nothing but resolve immediately.\n        // this fixes timing issues in test cases.\n        if (MainViewManager.getCurrentlyViewedPath(paneId || MainViewManager.ACTIVE_PANE) === fullPath) {\n            result.resolve(MainViewManager.getCurrentlyViewedFile(paneId || MainViewManager.ACTIVE_PANE));\n            return result.promise();\n        }\n\n        function _cleanup(fileError, fullFilePath) {\n            if (fullFilePath) {\n                // For performance, we do lazy checking of file existence, so it may be in workingset\n                MainViewManager._removeView(paneId, FileSystem.getFileForPath(fullFilePath));\n                MainViewManager.focusActivePane();\n            }\n            result.reject(fileError);\n        }\n        function _showErrorAndCleanUp(fileError, fullFilePath) {\n            if (silent) {\n                _cleanup(fileError, fullFilePath);\n            } else {\n                showFileOpenError(fileError, fullFilePath).done(function () {\n                    _cleanup(fileError, fullFilePath);\n                });\n            }\n        }\n\n        if (!fullPath) {\n            throw new Error(\"_doOpen() called without fullPath\");\n        } else {\n            var perfTimerName = PerfUtils.markStart(\"Open File:\\t\" + fullPath);\n            result.always(function () {\n                PerfUtils.addMeasurement(perfTimerName);\n            });\n\n            var file = FileSystem.getFileForPath(fullPath);\n            if (options && options.encoding) {\n                file._encoding = options.encoding;\n            } else {\n                var projectRoot = ProjectManager.getProjectRoot(),\n                    context = {\n                        location : {\n                            scope: \"user\",\n                            layer: \"project\",\n                            layerID: projectRoot.fullPath\n                        }\n                    };\n                var encoding = PreferencesManager.getViewState(\"encoding\", context);\n                if (encoding && encoding[fullPath]) {\n                    file._encoding = encoding[fullPath];\n                }\n            }\n            MainViewManager._open(paneId, file, options)\n                .done(function () {\n                    result.resolve(file);\n                })\n                .fail(function (fileError) {\n                    _showErrorAndCleanUp(fileError, fullPath);\n                    result.reject();\n                });\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Used to track the default directory for the file open dialog\n     */\n    var _defaultOpenDialogFullPath = null;\n\n    /**\n     * @private\n     * Opens a file and displays its view (editor, image view, etc...) for the specified path.\n     * If no path is specified, a file prompt is provided for input.\n     * @param {?string} fullPath - The path of the file to open; if it's null we'll prompt for it\n     * @param {boolean=} silent - If true, don't show error message\n     * @param {string=}  paneId - the pane in which to open the file. Can be undefined, a valid pane id or ACTIVE_PANE\n     * @param {{*}=} options - options to pass to MainViewManager._open\n     * @return {$.Promise} a jQuery promise resolved with a Document object or\n     *                      rejected with an err\n     */\n    function _doOpenWithOptionalPath(fullPath, silent, paneId, options) {\n        var result;\n        paneId = paneId || MainViewManager.ACTIVE_PANE;\n        if (!fullPath) {\n            // Create placeholder deferred\n            result = new $.Deferred();\n\n            //first time through, default to the current project path\n            if (!_defaultOpenDialogFullPath) {\n                _defaultOpenDialogFullPath = ProjectManager.getProjectRoot().fullPath;\n            }\n            // Prompt the user with a dialog\n            FileSystem.showOpenDialog(true, false, Strings.OPEN_FILE, _defaultOpenDialogFullPath, null, function (err, paths) {\n                if (!err) {\n                    if (paths.length > 0) {\n                        // Add all files to the workingset without verifying that\n                        // they still exist on disk (for faster opening)\n                        var filesToOpen = [];\n\n                        paths.forEach(function (path) {\n                            filesToOpen.push(FileSystem.getFileForPath(path));\n                        });\n                        MainViewManager.addListToWorkingSet(paneId, filesToOpen);\n\n                        _doOpen(paths[paths.length - 1], silent, paneId, options)\n                            .done(function (file) {\n                                _defaultOpenDialogFullPath =\n                                    FileUtils.getDirectoryPath(\n                                        MainViewManager.getCurrentlyViewedPath(paneId)\n                                    );\n                            })\n                            // Send the resulting document that was opened\n                            .then(result.resolve, result.reject);\n                    } else {\n                        // Reject if the user canceled the dialog\n                        result.reject();\n                    }\n                }\n            });\n        } else {\n            result = _doOpen(fullPath, silent, paneId, options);\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Splits a decorated file path into its parts.\n     * @param {?string} path - a string of the form \"fullpath[:lineNumber[:columnNumber]]\"\n     * @return {{path: string, line: ?number, column: ?number}}\n     */\n    function _parseDecoratedPath(path) {\n        var result = {path: path, line: null, column: null};\n        if (path) {\n            // If the path has a trailing :lineNumber and :columnNumber, strip\n            // these off and assign to result.line and result.column.\n            var matchResult = /(.+?):([0-9]+)(:([0-9]+))?$/.exec(path);\n            if (matchResult) {\n                result.path = matchResult[1];\n                if (matchResult[2]) {\n                    result.line = parseInt(matchResult[2], 10);\n                }\n                if (matchResult[4]) {\n                    result.column = parseInt(matchResult[4], 10);\n                }\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @typedef {{fullPath:?string=, silent:boolean=, paneId:string=}} FileCommandData\n     * fullPath: is in the form \"path[:lineNumber[:columnNumber]]\"\n     * lineNumber and columnNumber are 1-origin: lines and columns are 1-based\n     */\n\n    /**\n     * @typedef {{fullPath:?string=, index:number=, silent:boolean=, forceRedraw:boolean=, paneId:string=}} PaneCommandData\n     * fullPath: is in the form \"path[:lineNumber[:columnNumber]]\"\n     * lineNumber and columnNumber are 1-origin: lines and columns are 1-based\n     */\n\n    /**\n     * Opens the given file and makes it the current file. Does NOT add it to the workingset.\n     * @param {FileCommandData=} commandData - record with the following properties:\n     *   fullPath: File to open;\n     *   silent: optional flag to suppress error messages;\n     *   paneId: optional PaneId (defaults to active pane)\n     * @return {$.Promise} a jQuery promise that will be resolved with a file object\n     */\n    function handleFileOpen(commandData) {\n        var fileInfo = _parseDecoratedPath(commandData ? commandData.fullPath : null),\n            silent = (commandData && commandData.silent) || false,\n            paneId = (commandData && commandData.paneId) || MainViewManager.ACTIVE_PANE,\n            result = new $.Deferred();\n\n        _doOpenWithOptionalPath(fileInfo.path, silent, paneId, commandData && commandData.options)\n            .done(function (file) {\n                HealthLogger.fileOpened(file._path, false, file._encoding);\n                if (!commandData || !commandData.options || !commandData.options.noPaneActivate) {\n                    MainViewManager.setActivePaneId(paneId);\n                }\n\n                // If a line and column number were given, position the editor accordingly.\n                if (fileInfo.line !== null) {\n                    if (fileInfo.column === null || (fileInfo.column <= 0)) {\n                        fileInfo.column = 1;\n                    }\n\n                    // setCursorPos expects line/column numbers as 0-origin, so we subtract 1\n                    EditorManager.getCurrentFullEditor().setCursorPos(fileInfo.line - 1,\n                                                                      fileInfo.column - 1,\n                                                                      true);\n                }\n\n                result.resolve(file);\n            })\n            .fail(function (err) {\n                result.reject(err);\n            });\n\n        return result;\n        // Testing notes: here are some recommended manual tests for handleFileOpen, on Macintosh.\n        // Do all tests with brackets already running, and also with brackets not already running.\n        //\n        // drag a file onto brackets icon in desktop (this uses undecorated paths)\n        // drag a file onto brackets icon in taskbar (this uses undecorated paths)\n        // open a file from brackets sidebar (this uses undecorated paths)\n        // from command line: ...../Brackets.app/Contents path         - where 'path' is undecorated\n        // from command line: ...../Brackets.app path                  - where 'path' has the form \"path:line\"\n        // from command line: ...../Brackets.app path                  - where 'path' has the form \"path:line:column\"\n        // from command line: open -a ...../Brackets.app path          - where 'path' is undecorated\n        // do \"View Source\" from Adobe Scout version 1.2 or newer (this will use decorated paths of the form \"path:line:column\")\n    }\n\n    /**\n     * Opens the given file, makes it the current file, does NOT add it to the workingset\n     * @param {FileCommandData} commandData\n     *   fullPath: File to open;\n     *   silent: optional flag to suppress error messages;\n     *   paneId: optional PaneId (defaults to active pane)\n     * @return {$.Promise} a jQuery promise that will be resolved with @type {Document}\n     */\n    function handleDocumentOpen(commandData) {\n        var result = new $.Deferred();\n        handleFileOpen(commandData)\n            .done(function (file) {\n                // if we succeeded with an open file\n                //  then we need to resolve that to a document.\n                //  getOpenDocumentForPath will return null if there isn't a\n                //  supporting document for that file (e.g. an image)\n                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n                result.resolve(doc);\n            })\n            .fail(function (err) {\n                result.reject(err);\n            });\n\n        return result.promise();\n\n    }\n\n    /**\n     * Opens the given file, makes it the current file, AND adds it to the workingset\n     * @param {!PaneCommandData} commandData - record with the following properties:\n     *   fullPath: File to open;\n     *   index: optional index to position in workingset (defaults to last);\n     *   silent: optional flag to suppress error messages;\n     *   forceRedraw: flag to force the working set view redraw;\n     *   paneId: optional PaneId (defaults to active pane)\n     * @return {$.Promise} a jQuery promise that will be resolved with a @type {File}\n     */\n    function handleFileAddToWorkingSetAndOpen(commandData) {\n        return handleFileOpen(commandData).done(function (file) {\n            var paneId = (commandData && commandData.paneId) || MainViewManager.ACTIVE_PANE;\n            MainViewManager.addToWorkingSet(paneId, file, commandData.index, commandData.forceRedraw);\n            HealthLogger.fileOpened(file.fullPath, true);\n        });\n    }\n\n    /**\n     * @deprecated\n     * Opens the given file, makes it the current document, AND adds it to the workingset\n     * @param {!PaneCommandData} commandData - record with the following properties:\n     *   fullPath: File to open;\n     *   index: optional index to position in workingset (defaults to last);\n     *   silent: optional flag to suppress error messages;\n     *   forceRedraw: flag to force the working set view redraw;\n     *   paneId: optional PaneId (defaults to active pane)\n     * @return {$.Promise} a jQuery promise that will be resolved with @type {File}\n     */\n    function handleFileAddToWorkingSet(commandData) {\n        // This is a legacy deprecated command that\n        //  will use the new command and resolve with a document\n        //  as the legacy command would only support.\n        DeprecationWarning.deprecationWarning(\"Commands.FILE_ADD_TO_WORKING_SET has been deprecated.  Use Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN instead.\");\n        var result = new $.Deferred();\n\n        handleFileAddToWorkingSetAndOpen(commandData)\n            .done(function (file) {\n                // if we succeeded with an open file\n                //  then we need to resolve that to a document.\n                //  getOpenDocumentForPath will return null if there isn't a\n                //  supporting document for that file (e.g. an image)\n                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n                result.resolve(doc);\n            })\n            .fail(function (err) {\n                result.reject(err);\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Ensures the suggested file name doesn't already exit.\n     * @param {Directory} dir  The directory to use\n     * @param {string} baseFileName  The base to start with, \"-n\" will get appended to make unique\n     * @param {boolean} isFolder True if the suggestion is for a folder name\n     * @return {$.Promise} a jQuery promise that will be resolved with a unique name starting with\n     *   the given base name\n     */\n    function _getUntitledFileSuggestion(dir, baseFileName, isFolder) {\n        var suggestedName   = baseFileName + \"-\" + _nextUntitledIndexToUse++,\n            deferred        = $.Deferred();\n\n        if (_nextUntitledIndexToUse > 9999) {\n            //we've tried this enough\n            deferred.reject();\n        } else {\n            var path = dir.fullPath + suggestedName,\n                entry = isFolder ? FileSystem.getDirectoryForPath(path)\n                                 : FileSystem.getFileForPath(path);\n\n            entry.exists(function (err, exists) {\n                if (err || exists) {\n                    _getUntitledFileSuggestion(dir, baseFileName, isFolder)\n                        .then(deferred.resolve, deferred.reject);\n                } else {\n                    deferred.resolve(suggestedName);\n                }\n            });\n        }\n\n        return deferred.promise();\n    }\n\n    /**\n     * Prevents re-entrancy into handleFileNewInProject()\n     *\n     * handleFileNewInProject() first prompts the user to name a file and then asynchronously writes the file when the\n     * filename field loses focus. This boolean prevent additional calls to handleFileNewInProject() when an existing\n     * file creation call is outstanding\n     */\n    var fileNewInProgress = false;\n\n    /**\n     * Bottleneck function for creating new files and folders in the project tree.\n     * @private\n     * @param {boolean} isFolder - true if creating a new folder, false if creating a new file\n     */\n    function _handleNewItemInProject(isFolder) {\n        if (fileNewInProgress) {\n            ProjectManager.forceFinishRename();\n            return;\n        }\n        fileNewInProgress = true;\n\n        // Determine the directory to put the new file\n        // If a file is currently selected in the tree, put it next to it.\n        // If a directory is currently selected in the tree, put it in it.\n        // If an Untitled document is selected or nothing is selected in the tree, put it at the root of the project.\n        var baseDirEntry,\n            selected = ProjectManager.getFileTreeContext();\n        if ((!selected) || (selected instanceof InMemoryFile)) {\n            selected = ProjectManager.getProjectRoot();\n        }\n\n        if (selected.isFile) {\n            baseDirEntry = FileSystem.getDirectoryForPath(selected.parentPath);\n        }\n\n        baseDirEntry = baseDirEntry || selected;\n\n        // Create the new node. The createNewItem function does all the heavy work\n        // of validating file name, creating the new file and selecting.\n        function createWithSuggestedName(suggestedName) {\n            return ProjectManager.createNewItem(baseDirEntry, suggestedName, false, isFolder)\n                .always(function () { fileNewInProgress = false; });\n        }\n\n        return _getUntitledFileSuggestion(baseDirEntry, Strings.UNTITLED, isFolder)\n            .then(createWithSuggestedName, createWithSuggestedName.bind(undefined, Strings.UNTITLED));\n    }\n\n    /**\n     * Create a new untitled document in the workingset, and make it the current document.\n     * Promise is resolved (synchronously) with the newly-created Document.\n     */\n    function handleFileNew() {\n        //var defaultExtension = PreferencesManager.get(\"defaultExtension\");\n        //if (defaultExtension) {\n        //    defaultExtension = \".\" + defaultExtension;\n        //}\n        var defaultExtension = \"\";  // disable preference setting for now\n\n        var doc = DocumentManager.createUntitledDocument(_nextUntitledIndexToUse++, defaultExtension);\n        MainViewManager._edit(MainViewManager.ACTIVE_PANE, doc);\n\n        HealthLogger.sendAnalyticsData(\n            HealthLogger.commonStrings.USAGE +\n            HealthLogger.commonStrings.FILE_OPEN +\n            HealthLogger.commonStrings.FILE_NEW,\n            HealthLogger.commonStrings.USAGE,\n            HealthLogger.commonStrings.FILE_OPEN,\n            HealthLogger.commonStrings.FILE_NEW\n        );\n\n        return new $.Deferred().resolve(doc).promise();\n    }\n\n    /**\n     * Create a new file in the project tree.\n     */\n    function handleFileNewInProject() {\n        _handleNewItemInProject(false);\n    }\n\n    /**\n     * Create a new folder in the project tree.\n     */\n    function handleNewFolderInProject() {\n        _handleNewItemInProject(true);\n    }\n\n    /**\n     * @private\n     * Shows an Error modal dialog\n     * @param {string} name\n     * @param {string} path\n     * @return {Dialog}\n     */\n    function _showSaveFileError(name, path) {\n        return Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_SAVING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_SAVING_FILE,\n                StringUtils.breakableUrl(path),\n                FileUtils.getFileErrorString(name)\n            )\n        );\n    }\n\n    /**\n     * Saves a document to its existing path. Does NOT support untitled documents.\n     * @param {!Document} docToSave\n     * @param {boolean=} force Ignore CONTENTS_MODIFIED errors from the FileSystem\n     * @return {$.Promise} a promise that is resolved with the File of docToSave (to mirror\n     *   the API of _doSaveAs()). Rejected in case of IO error (after error dialog dismissed).\n     */\n    function doSave(docToSave, force) {\n        var result = new $.Deferred(),\n            file = docToSave.file;\n\n        function handleError(error) {\n            _showSaveFileError(error, file.fullPath)\n                .done(function () {\n                    result.reject(error);\n                });\n        }\n\n        function handleContentsModified() {\n            Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_ERROR,\n                Strings.EXT_MODIFIED_TITLE,\n                StringUtils.format(\n                    Strings.EXT_MODIFIED_WARNING,\n                    StringUtils.breakableUrl(docToSave.file.fullPath)\n                ),\n                [\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_LEFT,\n                        id        : Dialogs.DIALOG_BTN_SAVE_AS,\n                        text      : Strings.SAVE_AS\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,\n                        id        : Dialogs.DIALOG_BTN_CANCEL,\n                        text      : Strings.CANCEL\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                        id        : Dialogs.DIALOG_BTN_OK,\n                        text      : Strings.SAVE_AND_OVERWRITE\n                    }\n                ]\n            )\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                        result.reject();\n                    } else if (id === Dialogs.DIALOG_BTN_OK) {\n                        // Re-do the save, ignoring any CONTENTS_MODIFIED errors\n                        doSave(docToSave, true).then(result.resolve, result.reject);\n                    } else if (id === Dialogs.DIALOG_BTN_SAVE_AS) {\n                        // Let the user choose a different path at which to write the file\n                        handleFileSaveAs({doc: docToSave}).then(result.resolve, result.reject);\n                    }\n                });\n        }\n\n        function trySave() {\n            // We don't want normalized line endings, so it's important to pass true to getText()\n            FileUtils.writeText(file, docToSave.getText(true), force)\n                .done(function () {\n                    docToSave.notifySaved();\n                    result.resolve(file);\n                    HealthLogger.fileSaved(docToSave);\n                })\n                .fail(function (err) {\n                    if (err === FileSystemError.CONTENTS_MODIFIED) {\n                        handleContentsModified();\n                    } else {\n                        handleError(err);\n                    }\n                });\n        }\n\n        if (docToSave.isDirty) {\n            if (docToSave.keepChangesTime) {\n                // The user has decided to keep conflicting changes in the editor. Check to make sure\n                // the file hasn't changed since they last decided to do that.\n                docToSave.file.stat(function (err, stat) {\n                    // If the file has been deleted on disk, the stat will return an error, but that's fine since\n                    // that means there's no file to overwrite anyway, so the save will succeed without us having\n                    // to set force = true.\n                    if (!err && docToSave.keepChangesTime === stat.mtime.getTime()) {\n                        // OK, it's safe to overwrite the file even though we never reloaded the latest version,\n                        // since the user already said s/he wanted to ignore the disk version.\n                        force = true;\n                    }\n                    trySave();\n                });\n            } else {\n                trySave();\n            }\n        } else {\n            result.resolve(file);\n        }\n        result.always(function () {\n            MainViewManager.focusActivePane();\n        });\n        return result.promise();\n    }\n\n    /**\n     * Reverts the Document to the current contents of its file on disk. Discards any unsaved changes\n     * in the Document.\n     * @private\n     * @param {Document} doc\n     * @param {boolean=} suppressError If true, then a failure to read the file will be ignored and the\n     *      resulting promise will be resolved rather than rejected.\n     * @return {$.Promise} a Promise that's resolved when done, or (if suppressError is false)\n     *      rejected with a FileSystemError if the file cannot be read (after showing an error\n     *      dialog to the user).\n     */\n    function _doRevert(doc, suppressError) {\n        var result = new $.Deferred();\n\n        FileUtils.readAsText(doc.file)\n            .done(function (text, readTimestamp) {\n                doc.refreshText(text, readTimestamp);\n                result.resolve();\n            })\n            .fail(function (error) {\n                if (suppressError) {\n                    result.resolve();\n                } else {\n                    showFileOpenError(error, doc.file.fullPath)\n                        .done(function () {\n                            result.reject(error);\n                        });\n                }\n            });\n\n        return result.promise();\n    }\n    \n    /**\n     * Dispatches the app quit cancelled event\n     */\n    function dispatchAppQuitCancelledEvent() {\n        exports.trigger(exports.APP_QUIT_CANCELLED);\n    }\n\n\n    /**\n     * Opens the native OS save as dialog and saves document.\n     * The original document is reverted in case it was dirty.\n     * Text selection and cursor position from the original document\n     * are preserved in the new document.\n     * When saving to the original document the document is saved as if save was called.\n     * @param {Document} doc\n     * @param {?{cursorPos:!Object, selection:!Object, scrollPos:!Object}} settings - properties of\n     *      the original document's editor that need to be carried over to the new document\n     *      i.e. scrollPos, cursorPos and text selection\n     * @return {$.Promise} a promise that is resolved with the saved document's File. Rejected in\n     *   case of IO error (after error dialog dismissed), or if the Save dialog was canceled.\n     */\n    function _doSaveAs(doc, settings) {\n        var origPath,\n            saveAsDefaultPath,\n            defaultName,\n            result = new $.Deferred();\n\n        function _doSaveAfterSaveDialog(path) {\n            var newFile;\n\n            // Reconstruct old doc's editor's view state, & finally resolve overall promise\n            function _configureEditorAndResolve() {\n                var editor = EditorManager.getActiveEditor();\n                if (editor) {\n                    if (settings) {\n                        editor.setSelections(settings.selections);\n                        editor.setScrollPos(settings.scrollPos.x, settings.scrollPos.y);\n                    }\n                }\n                result.resolve(newFile);\n            }\n\n            // Replace old document with new one in open editor & workingset\n            function openNewFile() {\n                var fileOpenPromise;\n\n                if (FileViewController.getFileSelectionFocus() === FileViewController.PROJECT_MANAGER) {\n                    // If selection is in the tree, leave workingset unchanged - even if orig file is in the list\n                    fileOpenPromise = FileViewController\n                        .openAndSelectDocument(path, FileViewController.PROJECT_MANAGER);\n                } else {\n                    // If selection is in workingset, replace orig item in place with the new file\n                    var info = MainViewManager.findInAllWorkingSets(doc.file.fullPath).shift();\n\n                    // Remove old file from workingset; no redraw yet since there's a pause before the new file is opened\n                    MainViewManager._removeView(info.paneId, doc.file, true);\n\n                    // Add new file to workingset, and ensure we now redraw (even if index hasn't changed)\n                    fileOpenPromise = handleFileAddToWorkingSetAndOpen({fullPath: path, paneId: info.paneId, index: info.index, forceRedraw: true});\n                }\n\n                // always configure editor after file is opened\n                fileOpenPromise.always(function () {\n                    _configureEditorAndResolve();\n                });\n            }\n\n            // Same name as before - just do a regular Save\n            if (path === origPath) {\n                doSave(doc).then(result.resolve, result.reject);\n                return;\n            }\n\n            doc.isSaving = true;    // mark that we're saving the document\n\n            // First, write document's current text to new file\n            if (doc.file._encoding && doc.file._encoding !== \"UTF-8\") {\n                var projectRoot = ProjectManager.getProjectRoot(),\n                    context = {\n                        location : {\n                            scope: \"user\",\n                            layer: \"project\",\n                            layerID: projectRoot.fullPath\n                        }\n                    };\n                var encoding = PreferencesManager.getViewState(\"encoding\", context);\n                encoding[path] = doc.file._encoding;\n                PreferencesManager.setViewState(\"encoding\", encoding, context);\n            }\n            newFile = FileSystem.getFileForPath(path);\n            newFile._encoding = doc.file._encoding;\n\n            // Save as warns you when you're about to overwrite a file, so we\n            // explicitly allow \"blind\" writes to the filesystem in this case,\n            // ignoring warnings about the contents being modified outside of\n            // the editor.\n            FileUtils.writeText(newFile, doc.getText(true), true)\n                .done(function () {\n                    // If there were unsaved changes before Save As, they don't stay with the old\n                    // file anymore - so must revert the old doc to match disk content.\n                    // Only do this if the doc was dirty: _doRevert on a file that is not dirty and\n                    // not in the workingset has the side effect of adding it to the workingset.\n                    if (doc.isDirty && !(doc.isUntitled())) {\n                        // if the file is dirty it must be in the workingset\n                        // _doRevert is side effect free in this case\n                        _doRevert(doc).always(openNewFile);\n                    } else {\n                        openNewFile();\n                    }\n                    HealthLogger.fileSaved(doc);\n                })\n                .fail(function (error) {\n                    _showSaveFileError(error, path)\n                        .done(function () {\n                            result.reject(error);\n                        });\n                })\n                .always(function () {\n                    // mark that we're done saving the document\n                    doc.isSaving = false;\n                });\n        }\n\n        if (doc) {\n            origPath = doc.file.fullPath;\n            // If the document is an untitled document, we should default to project root.\n            if (doc.isUntitled()) {\n                // (Issue #4489) if we're saving an untitled document, go ahead and switch to this document\n                //   in the editor, so that if we're, for example, saving several files (ie. Save All),\n                //   then the user can visually tell which document we're currently prompting them to save.\n                var info = MainViewManager.findInAllWorkingSets(origPath).shift();\n\n                if (info) {\n                    MainViewManager._open(info.paneId, doc.file);\n                }\n\n                // If the document is untitled, default to project root.\n                saveAsDefaultPath = ProjectManager.getProjectRoot().fullPath;\n            } else {\n                saveAsDefaultPath = FileUtils.getDirectoryPath(origPath);\n            }\n            defaultName = FileUtils.getBaseName(origPath);\n            var file = FileSystem.getFileForPath(origPath);\n            if (file instanceof InMemoryFile) {\n                var language = LanguageManager.getLanguageForPath(origPath);\n                if (language) {\n                    var fileExtensions = language.getFileExtensions();\n                    if (fileExtensions && fileExtensions.length > 0) {\n                        defaultName += \".\" + fileExtensions[0];\n                    }\n                }\n            }\n            FileSystem.showSaveDialog(Strings.SAVE_FILE_AS, saveAsDefaultPath, defaultName, function (err, selectedPath) {\n                if (!err) {\n                    if (selectedPath) {\n                        _doSaveAfterSaveDialog(selectedPath);\n                    } else {\n                        dispatchAppQuitCancelledEvent();\n                        result.reject(USER_CANCELED);\n                    }\n                } else {\n                    result.reject(err);\n                }\n            });\n        } else {\n            result.reject();\n        }\n        return result.promise();\n    }\n\n    /**\n     * Saves the given file. If no file specified, assumes the current document.\n     * @param {?{doc: ?Document}} commandData  Document to close, or null\n     * @return {$.Promise} resolved with the saved document's File (which MAY DIFFER from the doc\n     *   passed in, if the doc was untitled). Rejected in case of IO error (after error dialog\n     *   dismissed), or if doc was untitled and the Save dialog was canceled (will be rejected with\n     *   USER_CANCELED object).\n     */\n    function handleFileSave(commandData) {\n        var activeEditor = EditorManager.getActiveEditor(),\n            activeDoc = activeEditor && activeEditor.document,\n            doc = (commandData && commandData.doc) || activeDoc,\n            settings;\n\n        if (doc && !doc.isSaving) {\n            if (doc.isUntitled()) {\n                if (doc === activeDoc) {\n                    settings = {\n                        selections: activeEditor.getSelections(),\n                        scrollPos: activeEditor.getScrollPos()\n                    };\n                }\n\n                return _doSaveAs(doc, settings);\n            } else {\n                return doSave(doc);\n            }\n        }\n\n        return $.Deferred().reject().promise();\n    }\n\n    /**\n     * Saves all unsaved documents corresponding to 'fileList'. Returns a Promise that will be resolved\n     * once ALL the save operations have been completed. If ANY save operation fails, an error dialog is\n     * immediately shown but after dismissing we continue saving the other files; after all files have\n     * been processed, the Promise is rejected if any ONE save operation failed (the error given is the\n     * first one encountered). If the user cancels any Save As dialog (for untitled files), the\n     * Promise is immediately rejected.\n     *\n     * @param {!Array.<File>} fileList\n     * @return {!$.Promise} Resolved with {!Array.<File>}, which may differ from 'fileList'\n     *      if any of the files were Unsaved documents. Or rejected with {?FileSystemError}.\n     */\n    function _saveFileList(fileList) {\n        // Do in serial because doSave shows error UI for each file, and we don't want to stack\n        // multiple dialogs on top of each other\n        var userCanceled = false,\n            filesAfterSave = [];\n\n        return Async.doSequentially(\n            fileList,\n            function (file) {\n                // Abort remaining saves if user canceled any Save As dialog\n                if (userCanceled) {\n                    return (new $.Deferred()).reject().promise();\n                }\n\n                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n                if (doc) {\n                    var savePromise = handleFileSave({doc: doc});\n                    savePromise\n                        .done(function (newFile) {\n                            filesAfterSave.push(newFile);\n                        })\n                        .fail(function (error) {\n                            if (error === USER_CANCELED) {\n                                userCanceled = true;\n                            }\n                        });\n                    return savePromise;\n                } else {\n                    // workingset entry that was never actually opened - ignore\n                    filesAfterSave.push(file);\n                    return (new $.Deferred()).resolve().promise();\n                }\n            },\n            false  // if any save fails, continue trying to save other files anyway; then reject at end\n        ).then(function () {\n            return filesAfterSave;\n        });\n    }\n\n    /**\n     * Saves all unsaved documents. See _saveFileList() for details on the semantics.\n     * @return {$.Promise}\n     */\n    function saveAll() {\n        return _saveFileList(MainViewManager.getWorkingSet(MainViewManager.ALL_PANES));\n    }\n\n    /**\n     * Prompts user with save as dialog and saves document.\n     * @return {$.Promise} a promise that is resolved once the save has been completed\n     */\n    handleFileSaveAs = function (commandData) {\n        // Default to current document if doc is null\n        var doc = null,\n            settings;\n\n        if (commandData) {\n            doc = commandData.doc;\n        } else {\n            var activeEditor = EditorManager.getActiveEditor();\n            if (activeEditor) {\n                doc = activeEditor.document;\n                settings = {};\n                settings.selections = activeEditor.getSelections();\n                settings.scrollPos = activeEditor.getScrollPos();\n            }\n        }\n\n        // doc may still be null, e.g. if no editors are open, but _doSaveAs() does a null check on\n        // doc.\n        return _doSaveAs(doc, settings);\n    };\n\n    /**\n     * Saves all unsaved documents.\n     * @return {$.Promise} a promise that is resolved once ALL the saves have been completed; or rejected\n     *      after all operations completed if any ONE of them failed.\n     */\n    function handleFileSaveAll() {\n        return saveAll();\n    }\n\n    /**\n     * Closes the specified file: removes it from the workingset, and closes the main editor if one\n     * is open. Prompts user about saving changes first, if document is dirty.\n     *\n     * @param {?{file: File, promptOnly:boolean}} commandData  Optional bag of arguments:\n     *      file - File to close; assumes the current document if not specified.\n     *      promptOnly - If true, only displays the relevant confirmation UI and does NOT actually\n     *          close the document. This is useful when chaining file-close together with other user\n     *          prompts that may be cancelable.\n     *      _forceClose - If true, closes the document without prompting even if there are unsaved\n     *          changes. Only for use in unit tests.\n     * @return {$.Promise} a promise that is resolved when the file is closed, or if no file is open.\n     *      FUTURE: should we reject the promise if no file is open?\n     */\n    function handleFileClose(commandData) {\n        var file,\n            promptOnly,\n            _forceClose,\n            _spawnedRequest,\n            paneId = MainViewManager.ACTIVE_PANE;\n\n        if (commandData) {\n            file        = commandData.file;\n            promptOnly  = commandData.promptOnly;\n            _forceClose = commandData._forceClose;\n            paneId      = commandData.paneId || paneId;\n            _spawnedRequest = commandData.spawnedRequest || false;\n        }\n\n        // utility function for handleFileClose: closes document & removes from workingset\n        function doClose(file) {\n            if (!promptOnly) {\n                MainViewManager._close(paneId, file);\n                HealthLogger.fileClosed(file);\n            }\n        }\n\n        var result = new $.Deferred(), promise = result.promise();\n\n        // Default to current document if doc is null\n        if (!file) {\n            file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);\n        }\n\n        // No-op if called when nothing is open; TODO: (issue #273) should command be grayed out instead?\n        if (!file) {\n            result.resolve();\n            return promise;\n        }\n\n        var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n\n        if (doc && doc.isDirty && !_forceClose && (MainViewManager.isExclusiveToPane(doc.file, paneId) || _spawnedRequest)) {\n            // Document is dirty: prompt to save changes before closing if only the document is exclusively\n            // listed in the requested pane or this is part of a list close request\n            var filename = FileUtils.getBaseName(doc.file.fullPath);\n\n            Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_SAVE_CLOSE,\n                Strings.SAVE_CLOSE_TITLE,\n                StringUtils.format(\n                    Strings.SAVE_CLOSE_MESSAGE,\n                    StringUtils.breakableUrl(filename)\n                ),\n                [\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_LEFT,\n                        id        : Dialogs.DIALOG_BTN_DONTSAVE,\n                        text      : Strings.DONT_SAVE\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,\n                        id        : Dialogs.DIALOG_BTN_CANCEL,\n                        text      : Strings.CANCEL\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                        id        : Dialogs.DIALOG_BTN_OK,\n                        text      : Strings.SAVE\n                    }\n                ]\n            )\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                        dispatchAppQuitCancelledEvent();\n                        result.reject();\n                    } else if (id === Dialogs.DIALOG_BTN_OK) {\n                        // \"Save\" case: wait until we confirm save has succeeded before closing\n                        handleFileSave({doc: doc})\n                            .done(function (newFile) {\n                                doClose(newFile);\n                                result.resolve();\n                            })\n                            .fail(function () {\n                                result.reject();\n                            });\n                    } else {\n                        // \"Don't Save\" case: even though we're closing the main editor, other views of\n                        // the Document may remain in the UI. So we need to revert the Document to a clean\n                        // copy of whatever's on disk.\n                        doClose(file);\n\n                        // Only reload from disk if we've executed the Close for real.\n                        if (promptOnly) {\n                            result.resolve();\n                        } else {\n                            // Even if there are no listeners attached to the document at this point, we want\n                            // to do the revert anyway, because clients who are listening to the global documentChange\n                            // event from the Document module (rather than attaching to the document directly),\n                            // such as the Find in Files panel, should get a change event. However, in that case,\n                            // we want to ignore errors during the revert, since we don't want a failed revert\n                            // to throw a dialog if the document isn't actually open in the UI.\n                            var suppressError = !DocumentManager.getOpenDocumentForPath(file.fullPath);\n                            _doRevert(doc, suppressError)\n                                .then(result.resolve, result.reject);\n                        }\n                    }\n                });\n            result.always(function () {\n                MainViewManager.focusActivePane();\n            });\n        } else {\n            // File is not open, or IS open but Document not dirty: close immediately\n            doClose(file);\n            MainViewManager.focusActivePane();\n            result.resolve();\n        }\n        return promise;\n    }\n\n    /**\n     * @param {!Array.<File>} list - the list of files to close\n     * @param {boolean} promptOnly - true to just prompt for saving documents with actually closing them.\n     * @param {boolean} _forceClose Whether to force all the documents to close even if they have unsaved changes. For unit testing only.\n     * @return {jQuery.Promise} promise that is resolved or rejected when the function finishes.\n     */\n    function _closeList(list, promptOnly, _forceClose) {\n        var result      = new $.Deferred(),\n            unsavedDocs = [];\n\n        list.forEach(function (file) {\n            var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n            if (doc && doc.isDirty) {\n                unsavedDocs.push(doc);\n            }\n        });\n\n        if (unsavedDocs.length === 0 || _forceClose) {\n            // No unsaved changes or we want to ignore them, so we can proceed without a prompt\n            result.resolve();\n\n        } else if (unsavedDocs.length === 1) {\n            // Only one unsaved file: show the usual single-file-close confirmation UI\n            var fileCloseArgs = { file: unsavedDocs[0].file, promptOnly: promptOnly, spawnedRequest: true };\n\n            handleFileClose(fileCloseArgs).done(function () {\n                // still need to close any other, non-unsaved documents\n                result.resolve();\n            }).fail(function () {\n                result.reject();\n            });\n\n        } else {\n            // Multiple unsaved files: show a single bulk prompt listing all files\n            var message = Strings.SAVE_CLOSE_MULTI_MESSAGE + FileUtils.makeDialogFileList(_.map(unsavedDocs, _shortTitleForDocument));\n\n            Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_SAVE_CLOSE,\n                Strings.SAVE_CLOSE_TITLE,\n                message,\n                [\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_LEFT,\n                        id        : Dialogs.DIALOG_BTN_DONTSAVE,\n                        text      : Strings.DONT_SAVE\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,\n                        id        : Dialogs.DIALOG_BTN_CANCEL,\n                        text      : Strings.CANCEL\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                        id        : Dialogs.DIALOG_BTN_OK,\n                        text      : Strings.SAVE\n                    }\n                ]\n            )\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                        dispatchAppQuitCancelledEvent();\n                        result.reject();\n                    } else if (id === Dialogs.DIALOG_BTN_OK) {\n                        // Save all unsaved files, then if that succeeds, close all\n                        _saveFileList(list).done(function (listAfterSave) {\n                            // List of files after save may be different, if any were Untitled\n                            result.resolve(listAfterSave);\n                        }).fail(function () {\n                            result.reject();\n                        });\n                    } else {\n                        // \"Don't Save\" case--we can just go ahead and close all files.\n                        result.resolve();\n                    }\n                });\n        }\n\n        // If all the unsaved-changes confirmations pan out above, then go ahead & close all editors\n        // NOTE: this still happens before any done() handlers added by our caller, because jQ\n        // guarantees that handlers run in the order they are added.\n        result.done(function (listAfterSave) {\n            listAfterSave = listAfterSave || list;\n            if (!promptOnly) {\n                MainViewManager._closeList(MainViewManager.ALL_PANES, listAfterSave);\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Closes all open files; equivalent to calling handleFileClose() for each document, except\n     * that unsaved changes are confirmed once, in bulk.\n     * @param {?{promptOnly: boolean, _forceClose: boolean}}\n     *          If promptOnly is true, only displays the relevant confirmation UI and does NOT\n     *          actually close any documents. This is useful when chaining close-all together with\n     *          other user prompts that may be cancelable.\n     *          If _forceClose is true, forces the files to close with no confirmation even if dirty.\n     *          Should only be used for unit test cleanup.\n     * @return {$.Promise} a promise that is resolved when all files are closed\n     */\n    function handleFileCloseAll(commandData) {\n        return _closeList(MainViewManager.getAllOpenFiles(),\n                                    (commandData && commandData.promptOnly), (commandData && commandData._forceClose));\n    }\n\n\n    /**\n     * Closes a list of open files; equivalent to calling handleFileClose() for each document, except\n     * that unsaved changes are confirmed once, in bulk.\n     * @param {?{promptOnly: boolean, _forceClose: boolean}}\n     *          If promptOnly is true, only displays the relevant confirmation UI and does NOT\n     *          actually close any documents. This is useful when chaining close-all together with\n     *          other user prompts that may be cancelable.\n     *          If _forceClose is true, forces the files to close with no confirmation even if dirty.\n     *          Should only be used for unit test cleanup.\n     * @return {$.Promise} a promise that is resolved when all files are closed\n     */\n    function handleFileCloseList(commandData) {\n        return _closeList(commandData.fileList);\n    }\n\n    /**\n     * @private - tracks our closing state if we get called again\n     */\n    var _windowGoingAway = false;\n\n    /**\n     * @private\n     * Common implementation for close/quit/reload which all mostly\n     * the same except for the final step\n     * @param {Object} commandData - (not referenced)\n     * @param {!function()} postCloseHandler - called after close\n     * @param {!function()} failHandler - called when the save fails to cancel closing the window\n     */\n    function _handleWindowGoingAway(commandData, postCloseHandler, failHandler) {\n        if (_windowGoingAway) {\n            //if we get called back while we're closing, then just return\n            return (new $.Deferred()).reject().promise();\n        }\n\n        return CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })\n            .done(function () {\n                _windowGoingAway = true;\n\n                // Give everyone a chance to save their state - but don't let any problems block\n                // us from quitting\n                try {\n                    ProjectManager.trigger(\"beforeAppClose\");\n                } catch (ex) {\n                    console.error(ex);\n                }\n\n                postCloseHandler();\n            })\n            .fail(function () {\n                _windowGoingAway = false;\n                if (failHandler) {\n                    failHandler();\n                }\n            });\n    }\n\n    /**\n     * @private\n     * Implementation for abortQuit callback to reset quit sequence settings\n     */\n    function handleAbortQuit() {\n        _windowGoingAway = false;\n    }\n\n    /**\n     * @private\n     * Implementation for native APP_BEFORE_MENUPOPUP callback to trigger beforeMenuPopup event\n     */\n    function handleBeforeMenuPopup() {\n        PopUpManager.trigger(\"beforeMenuPopup\");\n    }\n\n    /**\n     * Confirms any unsaved changes, then closes the window\n     * @param {Object} command data\n     */\n    function handleFileCloseWindow(commandData) {\n        return _handleWindowGoingAway(\n            commandData,\n            function () {\n                window.close();\n            },\n            function () {\n                // if fail, tell the app to abort any pending quit operation.\n                brackets.app.abortQuit();\n            }\n        );\n    }\n\n    /** Show a textfield to rename whatever is currently selected in the sidebar (or current doc if nothing else selected) */\n    function handleFileRename() {\n        // Prefer selected sidebar item (which could be a folder)\n        var entry = ProjectManager.getContext();\n        if (!entry) {\n            // Else use current file (not selected in ProjectManager if not visible in tree or workingset)\n            entry = MainViewManager.getCurrentlyViewedFile();\n        }\n        if (entry) {\n            ProjectManager.renameItemInline(entry);\n        }\n    }\n\n    /** Closes the window, then quits the app */\n    function handleFileQuit(commandData) {\n        return _handleWindowGoingAway(\n            commandData,\n            function () {\n                brackets.app.quit();\n            },\n            function () {\n                // if fail, don't exit: user canceled (or asked us to save changes first, but we failed to do so)\n                brackets.app.abortQuit();\n            }\n        );\n    }\n\n\n    /** Are we already listening for a keyup to call detectDocumentNavEnd()? */\n    var _addedNavKeyHandler = false;\n\n    /**\n     * When the Ctrl key is released, if we were in the middle of a next/prev document navigation\n     * sequence, now is the time to end it and update the MRU order. If we allowed the order to update\n     * on every next/prev increment, the 1st & 2nd entries would just switch places forever and we'd\n     * never get further down the list.\n     * @param {jQueryEvent} event Key-up event\n     */\n    function detectDocumentNavEnd(event) {\n        if (event.keyCode === KeyEvent.DOM_VK_CONTROL) {  // Ctrl key\n            MainViewManager.endTraversal();\n            _addedNavKeyHandler = false;\n            $(window.document.body).off(\"keyup\", detectDocumentNavEnd);\n        }\n    }\n\n    /**\n     * Navigate to the next/previous (MRU or list order) document. Don't update MRU order yet\n     * @param {!number} inc Delta indicating in which direction we're going\n     * @param {?boolean} listOrder Whether to navigate using MRU or list order. Defaults to MRU order\n     */\n    function goNextPrevDoc(inc, listOrder) {\n        var result;\n        if (listOrder) {\n            result = MainViewManager.traverseToNextViewInListOrder(inc);\n        } else {\n            result = MainViewManager.traverseToNextViewByMRU(inc);\n        }\n\n        if (result) {\n            var file = result.file,\n                paneId = result.paneId;\n\n            MainViewManager.beginTraversal();\n            CommandManager.execute(Commands.FILE_OPEN, {fullPath: file.fullPath,\n                                                        paneId: paneId });\n\n            // Listen for ending of Ctrl+Tab sequence\n            if (!_addedNavKeyHandler) {\n                _addedNavKeyHandler = true;\n                $(window.document.body).keyup(detectDocumentNavEnd);\n            }\n        }\n    }\n\n    /** Next Doc command handler (MRU order) **/\n    function handleGoNextDoc() {\n        goNextPrevDoc(+1);\n    }\n\n    /** Previous Doc command handler (MRU order) **/\n    function handleGoPrevDoc() {\n        goNextPrevDoc(-1);\n    }\n\n    /** Next Doc command handler (list order) **/\n    function handleGoNextDocListOrder() {\n        goNextPrevDoc(+1, true);\n    }\n\n    /** Previous Doc command handler (list order) **/\n    function handleGoPrevDocListOrder() {\n        goNextPrevDoc(-1, true);\n    }\n\n    /** Show in File Tree command handler **/\n    function handleShowInTree() {\n        ProjectManager.showInTree(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE));\n    }\n\n    /** Delete file command handler  **/\n    function handleFileDelete() {\n        var entry = ProjectManager.getSelectedItem();\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_EXT_DELETED,\n            Strings.CONFIRM_DELETE_TITLE,\n            StringUtils.format(\n                entry.isFile ? Strings.CONFIRM_FILE_DELETE : Strings.CONFIRM_FOLDER_DELETE,\n                StringUtils.breakableUrl(entry.name)\n            ),\n            [\n                {\n                    className : Dialogs.DIALOG_BTN_CLASS_NORMAL,\n                    id        : Dialogs.DIALOG_BTN_CANCEL,\n                    text      : Strings.CANCEL\n                },\n                {\n                    className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                    id        : Dialogs.DIALOG_BTN_OK,\n                    text      : Strings.DELETE\n                }\n            ]\n        )\n            .done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_OK) {\n                    ProjectManager.deleteItem(entry);\n                }\n            });\n    }\n\n    /** Show the selected sidebar (tree or workingset) item in Finder/Explorer */\n    function handleShowInOS() {\n        var entry = ProjectManager.getSelectedItem();\n        if (entry) {\n            brackets.app.showOSFolder(entry.fullPath, function (err) {\n                if (err) {\n                    console.error(\"Error showing '\" + entry.fullPath + \"' in OS folder:\", err);\n                }\n            });\n        }\n    }\n\n    /**\n     * Disables Brackets' cache via the remote debugging protocol.\n     * @return {$.Promise} A jQuery promise that will be resolved when the cache is disabled and be rejected in any other case\n     */\n    function _disableCache() {\n        var result = new $.Deferred();\n\n        if (brackets.inBrowser) {\n            result.resolve();\n        } else {\n            brackets.app.getRemoteDebuggingPort(function (err, port){\n                if ((!err) && port && port > 0) {\n                    Inspector.getDebuggableWindows(\"127.0.0.1\", port)\n                        .fail(result.reject)\n                        .done(function (response) {\n                            var page = response[0];\n                            if (!page || !page.webSocketDebuggerUrl) {\n                                result.reject();\n                                return;\n                            }\n                            var _socket = new WebSocket(page.webSocketDebuggerUrl);\n                            // Disable the cache\n                            _socket.onopen = function _onConnect() {\n                                _socket.send(JSON.stringify({ id: 1, method: \"Network.setCacheDisabled\", params: { \"cacheDisabled\": true } }));\n                            };\n                            // The first message will be the confirmation => disconnected to allow remote debugging of Brackets\n                            _socket.onmessage = function _onMessage(e) {\n                                _socket.close();\n                                result.resolve();\n                            };\n                            // In case of an error\n                            _socket.onerror = result.reject;\n                        });\n                } else {\n                    result.reject();\n                }\n            });\n        }\n\n        return result.promise();\n    }\n\n    /**\n    * Does a full reload of the browser window\n    * @param {string} href The url to reload into the window\n    */\n    function browserReload(href) {\n        if (_isReloading) {\n            return;\n        }\n\n        _isReloading = true;\n\n        return CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true }).done(function () {\n            // Give everyone a chance to save their state - but don't let any problems block\n            // us from quitting\n            try {\n                ProjectManager.trigger(\"beforeAppClose\");\n            } catch (ex) {\n                console.error(ex);\n            }\n\n            // Disable the cache to make reloads work\n            _disableCache().always(function () {\n                // Remove all menus to assure every part of Brackets is reloaded\n                _.forEach(Menus.getAllMenus(), function (value, key) {\n                    Menus.removeMenu(key);\n                });\n\n                // If there's a fragment in both URLs, setting location.href won't actually reload\n                var fragment = href.indexOf(\"#\");\n                if (fragment !== -1) {\n                    href = href.substr(0, fragment);\n                }\n\n                // Defer for a more successful reload - issue #11539\n                setTimeout(function () {\n                    window.location.href = href;\n                }, 1000);\n            });\n        }).fail(function () {\n            _isReloading = false;\n        });\n    }\n\n    /**\n     * Restarts brackets Handler\n     * @param {boolean=} loadWithoutExtensions - true to restart without extensions,\n     *                                           otherwise extensions are loadeed as it is durning a typical boot\n     */\n    function handleReload(loadWithoutExtensions) {\n        var href    = window.location.href,\n            params  = new UrlParams();\n\n        // Make sure the Reload Without User Extensions parameter is removed\n        params.parse();\n\n        if (loadWithoutExtensions) {\n            if (!params.get(\"reloadWithoutUserExts\")) {\n                params.put(\"reloadWithoutUserExts\", true);\n            }\n        } else {\n            if (params.get(\"reloadWithoutUserExts\")) {\n                params.remove(\"reloadWithoutUserExts\");\n            }\n        }\n\n        if (href.indexOf(\"?\") !== -1) {\n            href = href.substring(0, href.indexOf(\"?\"));\n        }\n\n        if (!params.isEmpty()) {\n            href += \"?\" + params.toString();\n        }\n\n        // Give Mac native menus extra time to update shortcut highlighting.\n        // Prevents the menu highlighting from getting messed up after reload.\n        window.setTimeout(function () {\n            browserReload(href);\n        }, 100);\n    }\n\n    /** Reload Without Extensions commnad handler **/\n    var handleReloadWithoutExts = _.partial(handleReload, true);\n\n    /**\n     * Attach a beforeunload handler to notify user about unsaved changes and URL redirection in CEF.\n     * Prevents data loss in scenario reported under #13708\n     * Make sure we don't attach this handler if the current window is actually a test window\n    **/\n\n    var isTestWindow = (new window.URLSearchParams(window.location.search || \"\")).get(\"testEnvironment\");\n    if (!isTestWindow) {\n        window.onbeforeunload = function(e) {\n            var openDocs = DocumentManager.getAllOpenDocuments();\n\n            // Detect any unsaved changes\n            openDocs = openDocs.filter(function(doc) {\n                return doc && doc.isDirty;\n            });\n\n            // Ensure we are not in normal app-quit or reload workflow\n            if (!_isReloading && !_windowGoingAway) {\n                if (openDocs.length > 0) {\n                    return Strings.WINDOW_UNLOAD_WARNING_WITH_UNSAVED_CHANGES;\n                } else {\n                    return Strings.WINDOW_UNLOAD_WARNING;\n                }\n            }\n        };\n    }\n\n    /** Do some initialization when the DOM is ready **/\n    AppInit.htmlReady(function () {\n        // If in Reload Without User Extensions mode, update UI and log console message\n        var params      = new UrlParams(),\n            $icon       = $(\"#toolbar-extension-manager\"),\n            $indicator  = $(\"<div>\" + Strings.STATUSBAR_USER_EXTENSIONS_DISABLED + \"</div>\");\n\n        params.parse();\n\n        if (params.get(\"reloadWithoutUserExts\") === \"true\") {\n            CommandManager.get(Commands.FILE_EXTENSION_MANAGER).setEnabled(false);\n            $icon.css({display: \"none\"});\n            StatusBar.addIndicator(\"status-user-exts\", $indicator, true);\n            console.log(\"Brackets reloaded with extensions disabled\");\n        }\n\n        // Init DOM elements\n        _$titleContainerToolbar = $(\"#titlebar\");\n        _$titleWrapper = $(\".title-wrapper\", _$titleContainerToolbar);\n        _$title = $(\".title\", _$titleWrapper);\n        _$dirtydot = $(\".dirty-dot\", _$titleWrapper);\n    });\n\n    // Exported for unit testing only\n    exports._parseDecoratedPath = _parseDecoratedPath;\n\n    // Set some command strings\n    var quitString  = Strings.CMD_QUIT,\n        showInOS    = Strings.CMD_SHOW_IN_OS;\n    if (brackets.platform === \"win\") {\n        quitString  = Strings.CMD_EXIT;\n        showInOS    = Strings.CMD_SHOW_IN_EXPLORER;\n    } else if (brackets.platform === \"mac\") {\n        showInOS    = Strings.CMD_SHOW_IN_FINDER;\n    }\n\n    // Define public API\n    exports.showFileOpenError = showFileOpenError;\n    exports.APP_QUIT_CANCELLED = APP_QUIT_CANCELLED;\n    \n\n    // Deprecated commands\n    CommandManager.register(Strings.CMD_ADD_TO_WORKING_SET,          Commands.FILE_ADD_TO_WORKING_SET,        handleFileAddToWorkingSet);\n    CommandManager.register(Strings.CMD_FILE_OPEN,                   Commands.FILE_OPEN,                      handleDocumentOpen);\n\n    // New commands\n    CommandManager.register(Strings.CMD_ADD_TO_WORKING_SET,          Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, handleFileAddToWorkingSetAndOpen);\n    CommandManager.register(Strings.CMD_FILE_OPEN,                   Commands.CMD_OPEN,                       handleFileOpen);\n\n    // File Commands\n    CommandManager.register(Strings.CMD_FILE_NEW_UNTITLED,           Commands.FILE_NEW_UNTITLED,              handleFileNew);\n    CommandManager.register(Strings.CMD_FILE_NEW,                    Commands.FILE_NEW,                       handleFileNewInProject);\n    CommandManager.register(Strings.CMD_FILE_NEW_FOLDER,             Commands.FILE_NEW_FOLDER,                handleNewFolderInProject);\n    CommandManager.register(Strings.CMD_FILE_SAVE,                   Commands.FILE_SAVE,                      handleFileSave);\n    CommandManager.register(Strings.CMD_FILE_SAVE_ALL,               Commands.FILE_SAVE_ALL,                  handleFileSaveAll);\n    CommandManager.register(Strings.CMD_FILE_SAVE_AS,                Commands.FILE_SAVE_AS,                   handleFileSaveAs);\n    CommandManager.register(Strings.CMD_FILE_RENAME,                 Commands.FILE_RENAME,                    handleFileRename);\n    CommandManager.register(Strings.CMD_FILE_DELETE,                 Commands.FILE_DELETE,                    handleFileDelete);\n\n    // Close Commands\n    CommandManager.register(Strings.CMD_FILE_CLOSE,                  Commands.FILE_CLOSE,                     handleFileClose);\n    CommandManager.register(Strings.CMD_FILE_CLOSE_ALL,              Commands.FILE_CLOSE_ALL,                 handleFileCloseAll);\n    CommandManager.register(Strings.CMD_FILE_CLOSE_LIST,             Commands.FILE_CLOSE_LIST,                handleFileCloseList);\n\n    // Traversal\n    CommandManager.register(Strings.CMD_NEXT_DOC,                    Commands.NAVIGATE_NEXT_DOC,              handleGoNextDoc);\n    CommandManager.register(Strings.CMD_PREV_DOC,                    Commands.NAVIGATE_PREV_DOC,              handleGoPrevDoc);\n\n    CommandManager.register(Strings.CMD_NEXT_DOC_LIST_ORDER,         Commands.NAVIGATE_NEXT_DOC_LIST_ORDER,   handleGoNextDocListOrder);\n    CommandManager.register(Strings.CMD_PREV_DOC_LIST_ORDER,         Commands.NAVIGATE_PREV_DOC_LIST_ORDER,   handleGoPrevDocListOrder);\n\n    // Special Commands\n    CommandManager.register(showInOS,                                Commands.NAVIGATE_SHOW_IN_OS,            handleShowInOS);\n    CommandManager.register(quitString,                              Commands.FILE_QUIT,                      handleFileQuit);\n    CommandManager.register(Strings.CMD_SHOW_IN_TREE,                Commands.NAVIGATE_SHOW_IN_FILE_TREE,     handleShowInTree);\n\n    // These commands have no UI representation and are only used internally\n    CommandManager.registerInternal(Commands.APP_ABORT_QUIT,            handleAbortQuit);\n    CommandManager.registerInternal(Commands.APP_BEFORE_MENUPOPUP,      handleBeforeMenuPopup);\n    CommandManager.registerInternal(Commands.FILE_CLOSE_WINDOW,         handleFileCloseWindow);\n    CommandManager.registerInternal(Commands.APP_RELOAD,                handleReload);\n    CommandManager.registerInternal(Commands.APP_RELOAD_WITHOUT_EXTS,   handleReloadWithoutExts);\n\n    // Listen for changes that require updating the editor titlebar\n    ProjectManager.on(\"projectOpen\", _updateTitle);\n    DocumentManager.on(\"dirtyFlagChange\", handleDirtyChange);\n    DocumentManager.on(\"fileNameChange\", handleCurrentFileChange);\n    MainViewManager.on(\"currentFileChange\", handleCurrentFileChange);\n\n    // Reset the untitled document counter before changing projects\n    ProjectManager.on(\"beforeProjectClose\", function () { _nextUntitledIndexToUse = 1; });\n});\n"
  },
  {
    "path": "src/document/DocumentManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * DocumentManager maintains a list of currently 'open' Documents. The DocumentManager is responsible\n * for coordinating document operations and dispatching certain document events.\n *\n * Document is the model for a file's contents; it dispatches events whenever those contents change.\n * To transiently inspect a file's content, simply get a Document and call getText() on it. However,\n * to be notified of Document changes or to modify a Document, you MUST call addRef() to ensure the\n * Document instance 'stays alive' and is shared by all other who read/modify that file. ('Open'\n * Documents are all Documents that are 'kept alive', i.e. have ref count > 0).\n *\n * To get a Document, call getDocumentForPath(); never new up a Document yourself.\n *\n * Secretly, a Document may use an Editor instance to act as the model for its internal state. (This\n * is unavoidable because CodeMirror does not separate its model from its UI). Documents are not\n * modifiable until they have a backing 'master Editor'. Creation of the backing Editor is owned by\n * EditorManager. A Document only gets a backing Editor if it opened in an editor.\n *\n * A non-modifiable Document may still dispatch change notifications, if the Document was changed\n * externally on disk.\n *\n * Aside from the text content, Document tracks a few pieces of metadata - notably, whether there are\n * any unsaved changes.\n *\n * This module dispatches several events:\n *\n *    - dirtyFlagChange -- When any Document's isDirty flag changes. The 2nd arg to the listener is the\n *      Document whose flag changed.\n *    - documentSaved -- When a Document's changes have been saved. The 2nd arg to the listener is the\n *      Document that has been saved.\n *    - documentRefreshed -- When a Document's contents have been reloaded from disk. The 2nd arg to the\n *      listener is the Document that has been refreshed.\n *\n * NOTE: WorkingSet APIs have been deprecated and have moved to MainViewManager as WorkingSet APIs\n *       Some WorkingSet APIs that have been identified as being used by 3rd party extensions will\n *       emit deprecation warnings and call the WorkingSet APIS to maintain backwards compatibility\n *\n *    - currentDocumentChange -- Deprecated: use EditorManager activeEditorChange (which covers all editors,\n *      not just full-sized editors) or MainViewManager currentFileChange (which covers full-sized views\n *      only, but is also triggered for non-editor views e.g. image files).\n *\n *    - fileNameChange -- When the name of a file or folder has changed. The 2nd arg is the old name.\n *      The 3rd arg is the new name.  Generally, however, file objects have already been changed by the\n *      time this event is dispatched so code that relies on matching the filename to a file object\n *      will need to compare the newname.\n *\n *    - pathDeleted -- When a file or folder has been deleted. The 2nd arg is the path that was deleted.\n *\n * To listen for events, do something like this: (see EventDispatcher for details on this pattern)\n *    DocumentManager.on(\"eventname\", handler);\n *\n * Document objects themselves also dispatch some events - see Document docs for details.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var AppInit             = require(\"utils/AppInit\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        DocumentModule      = require(\"document/Document\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        MainViewFactory     = require(\"view/MainViewFactory\"),\n        FileSyncManager     = require(\"project/FileSyncManager\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        InMemoryFile        = require(\"document/InMemoryFile\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        Strings             = require(\"strings\");\n\n\n    /**\n     * @private\n     * Random path prefix for untitled documents\n     */\n    var _untitledDocumentPath = \"/_brackets_\" + _.random(10000000, 99999999);\n\n    /**\n     * All documents with refCount > 0. Maps Document.file.id -> Document.\n     * @private\n     * @type {Object.<string, Document>}\n     */\n    var _openDocuments = {};\n\n    /**\n     * Returns the existing open Document for the given file, or null if the file is not open ('open'\n     * means referenced by the UI somewhere). If you will hang onto the Document, you must addRef()\n     * it; see {@link #getDocumentForPath} for details.\n     * @param {!string} fullPath\n     * @return {?Document}\n     */\n    function getOpenDocumentForPath(fullPath) {\n        var id;\n\n        // Need to walk all open documents and check for matching path. We can't\n        // use getFileForPath(fullPath).id since the file it returns won't match\n        // an Untitled document's InMemoryFile.\n        for (id in _openDocuments) {\n            if (_openDocuments.hasOwnProperty(id)) {\n                if (_openDocuments[id].file.fullPath === fullPath) {\n                    return _openDocuments[id];\n                }\n            }\n        }\n        return null;\n    }\n\n    /**\n     * Returns the Document that is currently open in the editor UI. May be null.\n     * @return {?Document}\n     */\n    function getCurrentDocument() {\n        var file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);\n\n        if (file) {\n            return getOpenDocumentForPath(file.fullPath);\n        }\n\n        return null;\n    }\n\n\n    /**\n     * Returns a list of items in the working set in UI list order. May be 0-length, but never null.\n     * @deprecated Use MainViewManager.getWorkingSet() instead\n     * @return {Array.<File>}\n     */\n    function getWorkingSet() {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.getWorkingSet() instead of DocumentManager.getWorkingSet()\", true);\n        return MainViewManager.getWorkingSet(MainViewManager.ALL_PANES)\n            .filter(function (file) {\n                // Legacy didn't allow for files with custom viewers\n                return !MainViewFactory.findSuitableFactoryForPath(file.fullPath);\n            });\n    }\n\n    /**\n     * Returns the index of the file matching fullPath in the working set.\n     * @deprecated Use MainViewManager.findInWorkingSet() instead\n     * @param {!string} fullPath\n     * @return {number} index, -1 if not found\n     */\n    function findInWorkingSet(fullPath) {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.findInWorkingSet() instead of DocumentManager.findInWorkingSet()\", true);\n        return MainViewManager.findInWorkingSet(MainViewManager.ACTIVE_PANE, fullPath);\n    }\n\n    /**\n     * Returns all Documents that are 'open' in the UI somewhere (for now, this means open in an\n     * inline editor and/or a full-size editor). Only these Documents can be modified, and only\n     * these Documents are synced with external changes on disk.\n     * @return {Array.<Document>}\n     */\n    function getAllOpenDocuments() {\n        var result = [];\n        var id;\n        for (id in _openDocuments) {\n            if (_openDocuments.hasOwnProperty(id)) {\n                result.push(_openDocuments[id]);\n            }\n        }\n        return result;\n    }\n\n\n    /**\n     * Adds the given file to the end of the working set list.\n     * @deprecated Use MainViewManager.addToWorkingSet() instead\n     * @param {!File} file\n     * @param {number=} index  Position to add to list (defaults to last); -1 is ignored\n     * @param {boolean=} forceRedraw  If true, a working set change notification is always sent\n     *    (useful if suppressRedraw was used with removeFromWorkingSet() earlier)\n     */\n    function addToWorkingSet(file, index, forceRedraw) {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.addToWorkingSet() instead of DocumentManager.addToWorkingSet()\", true);\n        MainViewManager.addToWorkingSet(MainViewManager.ACTIVE_PANE, file, index, forceRedraw);\n    }\n\n    /**\n     * @deprecated Use MainViewManager.addListToWorkingSet() instead\n     * Adds the given file list to the end of the working set list.\n     * If a file in the list has its own custom viewer, then it\n     * is not added into the working set.\n     * Does not change which document is currently open in the editor.\n     * More efficient than calling addToWorkingSet() (in a loop) for\n     * a list of files because there's only 1 redraw at the end\n     * @param {!Array.<File>} fileList\n     */\n    function addListToWorkingSet(fileList) {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.addListToWorkingSet() instead of DocumentManager.addListToWorkingSet()\", true);\n        MainViewManager.addListToWorkingSet(MainViewManager.ACTIVE_PANE, fileList);\n    }\n\n\n    /**\n     * closes a list of files\n     * @deprecated Use CommandManager.execute(Commands.FILE_CLOSE_LIST) instead\n     * @param {!Array.<File>} list - list of File objectgs to close\n     */\n    function removeListFromWorkingSet(list) {\n        DeprecationWarning.deprecationWarning(\"Use CommandManager.execute(Commands.FILE_CLOSE_LIST, {PaneId: MainViewManager.ALL_PANES, fileList: list}) instead of DocumentManager.removeListFromWorkingSet()\", true);\n        CommandManager.execute(Commands.FILE_CLOSE_LIST, {PaneId: MainViewManager.ALL_PANES, fileList: list});\n    }\n\n    /**\n     * closes all open files\n     * @deprecated CommandManager.execute(Commands.FILE_CLOSE_ALL) instead\n     */\n    function closeAll() {\n        DeprecationWarning.deprecationWarning(\"Use CommandManager.execute(Commands.FILE_CLOSE_ALL,{PaneId: MainViewManager.ALL_PANES}) instead of DocumentManager.closeAll()\", true);\n        CommandManager.execute(Commands.FILE_CLOSE_ALL, {PaneId: MainViewManager.ALL_PANES});\n    }\n\n    /**\n     * closes the specified file file\n     * @deprecated use CommandManager.execute(Commands.FILE_CLOSE, {File: file}) instead\n     * @param {!File} file - the file to close\n     */\n    function closeFullEditor(file) {\n        DeprecationWarning.deprecationWarning(\"Use CommandManager.execute(Commands.FILE_CLOSE, {File: file} instead of DocumentManager.closeFullEditor()\", true);\n        CommandManager.execute(Commands.FILE_CLOSE, {File: file});\n    }\n\n    /**\n     * opens the specified document for editing in the currently active pane\n     * @deprecated use CommandManager.execute(Commands.CMD_OPEN, {fullPath: doc.file.fullPath}) instead\n     * @param {!Document} document  The Document to make current.\n     */\n    function setCurrentDocument(doc) {\n        DeprecationWarning.deprecationWarning(\"Use CommandManager.execute(Commands.CMD_OPEN) instead of DocumentManager.setCurrentDocument()\", true);\n        CommandManager.execute(Commands.CMD_OPEN, {fullPath: doc.file.fullPath});\n    }\n\n\n    /**\n     * freezes the Working Set MRU list\n     * @deprecated use MainViewManager.beginTraversal() instead\n     */\n    function beginDocumentNavigation() {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.beginTraversal() instead of DocumentManager.beginDocumentNavigation()\", true);\n        MainViewManager.beginTraversal();\n    }\n\n    /**\n     * ends document navigation and moves the current file to the front of the MRU list in the Working Set\n     * @deprecated use MainViewManager.endTraversal() instead\n     */\n    function finalizeDocumentNavigation() {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.endTraversal() instead of DocumentManager.finalizeDocumentNavigation()\", true);\n        MainViewManager.endTraversal();\n    }\n\n    /**\n     * Get the next or previous file in the working set, in MRU order (relative to currentDocument). May\n     * return currentDocument itself if working set is length 1.\n     * @deprecated use MainViewManager.traverseToNextViewByMRU() instead\n     */\n    function getNextPrevFile(inc) {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.traverseToNextViewByMRU() instead of DocumentManager.getNextPrevFile()\", true);\n        var result = MainViewManager.traverseToNextViewByMRU(inc);\n        if (result) {\n            return result.file;\n        }\n        return null;\n    }\n\n    /**\n     * Cleans up any loose Documents whose only ref is its own master Editor, and that Editor is not\n     * rooted in the UI anywhere. This can happen if the Editor is auto-created via Document APIs that\n     * trigger _ensureMasterEditor() without making it dirty. E.g. a command invoked on the focused\n     * inline editor makes no-op edits or does a read-only operation.\n     */\n    function _gcDocuments() {\n        getAllOpenDocuments().forEach(function (doc) {\n            // Is the only ref to this document its own master Editor?\n            if (doc._refCount === 1 && doc._masterEditor) {\n                // Destroy the Editor if it's not being kept alive by the UI\n                MainViewManager._destroyEditorIfNotNeeded(doc);\n            }\n        });\n    }\n\n\n    /**\n     * Gets an existing open Document for the given file, or creates a new one if the Document is\n     * not currently open ('open' means referenced by the UI somewhere). Always use this method to\n     * get Documents; do not call the Document constructor directly. This method is safe to call\n     * in parallel.\n     *\n     * If you are going to hang onto the Document for more than just the duration of a command - e.g.\n     * if you are going to display its contents in a piece of UI - then you must addRef() the Document\n     * and listen for changes on it. (Note: opening the Document in an Editor automatically manages\n     * refs and listeners for that Editor UI).\n     *\n     * If all you need is the Document's getText() value, use the faster getDocumentText() instead.\n     *\n     * @param {!string} fullPath\n     * @param {!object} fileObj actual File|RemoteFile or some other protocol adapter handle\n     * @return {$.Promise} A promise object that will be resolved with the Document, or rejected\n     *      with a FileSystemError if the file is not yet open and can't be read from disk.\n     */\n    function getDocumentForPath(fullPath, fileObj) {\n        var doc = getOpenDocumentForPath(fullPath);\n\n        if (doc) {\n            // use existing document\n            return new $.Deferred().resolve(doc).promise();\n        } else {\n            var result = new $.Deferred(),\n                promise = result.promise();\n\n            // return null in case of untitled documents\n            if (fullPath.indexOf(_untitledDocumentPath) === 0) {\n                result.resolve(null);\n                return promise;\n            }\n\n            var file            = fileObj || FileSystem.getFileForPath(fullPath),\n                pendingPromise  = getDocumentForPath._pendingDocumentPromises[file.id];\n\n            if (pendingPromise) {\n                // wait for the result of a previous request\n                return pendingPromise;\n            } else {\n                // log this document's Promise as pending\n                getDocumentForPath._pendingDocumentPromises[file.id] = promise;\n\n                // create a new document\n                var perfTimerName = PerfUtils.markStart(\"getDocumentForPath:\\t\" + fullPath);\n\n                result.done(function () {\n                    PerfUtils.addMeasurement(perfTimerName);\n                }).fail(function () {\n                    PerfUtils.finalizeMeasurement(perfTimerName);\n                });\n\n                FileUtils.readAsText(file)\n                    .always(function () {\n                        // document is no longer pending\n                        delete getDocumentForPath._pendingDocumentPromises[file.id];\n                    })\n                    .done(function (rawText, readTimestamp) {\n                        doc = new DocumentModule.Document(file, readTimestamp, rawText);\n\n                        // This is a good point to clean up any old dangling Documents\n                        _gcDocuments();\n\n                        result.resolve(doc);\n                    })\n                    .fail(function (fileError) {\n                        result.reject(fileError);\n                    });\n\n                return promise;\n            }\n        }\n    }\n\n    /**\n     * Document promises that are waiting to be resolved. It is possible for multiple clients\n     * to request the same document simultaneously before the initial request has completed.\n     * In particular, this happens at app startup where the working set is created and the\n     * initial active document is opened in an editor. This is essential to ensure that only\n     * one Document exists for any File.\n     * @private\n     * @type {Object.<string, $.Promise>}\n     */\n    getDocumentForPath._pendingDocumentPromises = {};\n\n    /**\n     * Gets the text of a Document (including any unsaved changes), or would-be Document if the\n     * file is not actually open. More efficient than getDocumentForPath(). Use when you're reading\n     * document(s) but don't need to hang onto a Document object.\n     *\n     * If the file is open this is equivalent to calling getOpenDocumentForPath().getText(). If the\n     * file is NOT open, this is like calling getDocumentForPath()...getText() but more efficient.\n     * Differs from plain FileUtils.readAsText() in two ways: (a) line endings are still normalized\n     * as in Document.getText(); (b) unsaved changes are returned if there are any.\n     *\n     * @param {!File} file The file to get the text for.\n     * @param {boolean=} checkLineEndings Whether to return line ending information. Default false (slightly more efficient).\n     * @return {$.Promise}\n     *     A promise that is resolved with three parameters:\n     *          contents - string: the document's text\n     *          timestamp - Date: the last time the document was changed on disk (might not be the same as the last time it was changed in memory)\n     *          lineEndings - string: the original line endings of the file, one of the FileUtils.LINE_ENDINGS_* constants;\n     *              will be null if checkLineEndings was false.\n     *     or rejected with a filesystem error.\n     */\n    function getDocumentText(file, checkLineEndings) {\n        var result = new $.Deferred(),\n            doc = getOpenDocumentForPath(file.fullPath);\n        if (doc) {\n            result.resolve(doc.getText(), doc.diskTimestamp, checkLineEndings ? doc._lineEndings : null);\n        } else {\n            file.read(function (err, contents, encoding, stat) {\n                if (err) {\n                    result.reject(err);\n                } else {\n                    // Normalize line endings the same way Document would, but don't actually\n                    // new up a Document (which entails a bunch of object churn).\n                    var originalLineEndings = checkLineEndings ? FileUtils.sniffLineEndings(contents) : null;\n                    contents = DocumentModule.Document.normalizeText(contents);\n                    result.resolve(contents, stat.mtime, originalLineEndings);\n                }\n            });\n        }\n        return result.promise();\n    }\n\n\n    /**\n     * Creates an untitled document. The associated File has a fullPath that\n     * looks like /some-random-string/Untitled-counter.fileExt.\n     *\n     * @param {number} counter - used in the name of the new Document's File\n     * @param {string} fileExt - file extension of the new Document's File, including \".\"\n     * @return {Document} - a new untitled Document\n     */\n    function createUntitledDocument(counter, fileExt) {\n        var filename = Strings.UNTITLED + \"-\" + counter + fileExt,\n            fullPath = _untitledDocumentPath + \"/\" + filename,\n            now = new Date(),\n            file = new InMemoryFile(fullPath, FileSystem);\n\n        FileSystem.addEntryForPathIfRequired(file, fullPath);\n\n        return new DocumentModule.Document(file, now, \"\");\n    }\n\n    /**\n     * Reacts to a file being deleted: if there is a Document for this file, causes it to dispatch a\n     * \"deleted\" event; ensures it's not the currentDocument; and removes this file from the working\n     * set. These actions in turn cause all open editors for this file to close. Discards any unsaved\n     * changes - it is expected that the UI has already confirmed with the user before calling.\n     *\n     * To simply close a main editor when the file hasn't been deleted, use closeFullEditor() or FILE_CLOSE.\n     *\n     * FUTURE: Instead of an explicit notify, we should eventually listen for deletion events on some\n     * sort of \"project file model,\" making this just a private event handler.\n     *\n     * NOTE: This function is not for general consumption, is considered private and may be deprecated\n     *        without warning in a future release.\n     *\n     * @param {!File} file\n     */\n    function notifyFileDeleted(file) {\n        // Notify all editors to close as well\n        exports.trigger(\"pathDeleted\", file.fullPath);\n\n        var doc = getOpenDocumentForPath(file.fullPath);\n\n        if (doc) {\n            doc.trigger(\"deleted\");\n        }\n\n        // At this point, all those other views SHOULD have released the Doc\n        if (doc && doc._refCount > 0) {\n            console.warn(\"Deleted \" + file.fullPath + \" Document still has \" + doc._refCount + \" references. Did someone addRef() without listening for 'deleted'?\");\n        }\n    }\n\n    /**\n     * Called after a file or folder has been deleted. This function is responsible\n     * for updating underlying model data and notifying all views of the change.\n     *\n     * @param {string} fullPath The path of the file/folder that has been deleted\n     */\n    function notifyPathDeleted(fullPath) {\n        // FileSyncManager.syncOpenDocuments() does all the work prompting\n        //  the user to save any unsaved changes and then calls us back\n        //  via notifyFileDeleted\n        FileSyncManager.syncOpenDocuments(Strings.FILE_DELETED_TITLE);\n\n        var projectRoot = ProjectManager.getProjectRoot(),\n            context = {\n                location : {\n                    scope: \"user\",\n                    layer: \"project\",\n                    layerID: projectRoot.fullPath\n                }\n            };\n        var encoding = PreferencesManager.getViewState(\"encoding\", context);\n        delete encoding[fullPath];\n        PreferencesManager.setViewState(\"encoding\", encoding, context);\n\n        if (!getOpenDocumentForPath(fullPath) &&\n                !MainViewManager.findInAllWorkingSets(fullPath).length) {\n            // For images not open in the workingset,\n            // FileSyncManager.syncOpenDocuments() will\n            //  not tell us to close those views\n            exports.trigger(\"pathDeleted\", fullPath);\n        }\n    }\n\n    /**\n     * Called after a file or folder name has changed. This function is responsible\n     * for updating underlying model data and notifying all views of the change.\n     *\n     * @param {string} oldName The old name of the file/folder\n     * @param {string} newName The new name of the file/folder\n     */\n    function notifyPathNameChanged(oldName, newName) {\n        // Notify all open documents\n        _.forEach(_openDocuments, function (doc) {\n            // TODO: Only notify affected documents? For now _notifyFilePathChange\n            // just updates the language if the extension changed, so it's fine\n            // to call for all open docs.\n            doc._notifyFilePathChanged();\n        });\n\n        // Send a \"fileNameChange\" event. This will trigger the views to update.\n        exports.trigger(\"fileNameChange\", oldName, newName);\n    }\n\n\n    /**\n     * @private\n     * Update document\n     */\n    function _handleLanguageAdded() {\n        _.forEach(_openDocuments, function (doc) {\n            // No need to look at the new language if this document has one already\n            if (doc.getLanguage().isFallbackLanguage()) {\n                doc._updateLanguage();\n            }\n        });\n    }\n\n    /**\n     * @private\n     * Update document\n     */\n    function _handleLanguageModified(event, language) {\n        _.forEach(_openDocuments, function (doc) {\n            var docLanguage = doc.getLanguage();\n            // A modified language can affect a document\n            // - if its language was modified\n            // - if the document doesn't have a language yet and its file extension was added to the modified language\n            if (docLanguage === language || docLanguage.isFallbackLanguage()) {\n                doc._updateLanguage();\n            }\n        });\n    }\n\n    // For compatibility\n    DocumentModule\n        .on(\"_afterDocumentCreate\", function (event, doc) {\n            if (_openDocuments[doc.file.id]) {\n                console.error(\"Document for this path already in _openDocuments!\");\n                return true;\n            }\n\n            _openDocuments[doc.file.id] = doc;\n            exports.trigger(\"afterDocumentCreate\", doc);\n        })\n        .on(\"_beforeDocumentDelete\", function (event, doc) {\n            if (!_openDocuments[doc.file.id]) {\n                console.error(\"Document with references was not in _openDocuments!\");\n                return true;\n            }\n\n            exports.trigger(\"beforeDocumentDelete\", doc);\n            delete _openDocuments[doc.file.id];\n        })\n        .on(\"_documentRefreshed\", function (event, doc) {\n            exports.trigger(\"documentRefreshed\", doc);\n        })\n        .on(\"_dirtyFlagChange\", function (event, doc) {\n            // Modules listening on the doc instance notified about dirtyflag change\n            // To be used internally by Editor\n            doc.trigger(\"_dirtyFlagChange\", doc);\n            exports.trigger(\"dirtyFlagChange\", doc);\n            if (doc.isDirty) {\n                MainViewManager.addToWorkingSet(MainViewManager.ACTIVE_PANE, doc.file);\n\n                // We just dirtied a doc and added it to the active working set\n                //  this may have come from an internal dirtying so if it was\n                //  added to a working set that had no active document then\n                //  open the document\n                //\n                // See: https://github.com/adobe/brackets/issues/9569\n                //\n                // NOTE: Adding a file to the active working set may not actually add\n                //       it to the active working set (e.g. the document was already\n                //       opened to the inactive working set.)\n                //\n                //       Check that it was actually added to the active working set\n\n                if (!MainViewManager.getCurrentlyViewedFile() &&\n                        MainViewManager.findInWorkingSet(MainViewManager.ACTIVE_PANE, doc.file.fullPath) !== -1) {\n                    CommandManager.execute(Commands.FILE_OPEN, {fullPath: doc.file.fullPath});\n                }\n            }\n        })\n        .on(\"_documentSaved\", function (event, doc) {\n            exports.trigger(\"documentSaved\", doc);\n        });\n\n    // Set up event dispatch\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // This deprecated event is dispatched manually from \"currentFileChange\" below\n    EventDispatcher.markDeprecated(exports, \"currentDocumentChange\", \"MainViewManager.currentFileChange\");\n\n    // These deprecated events are automatically dispatched by DeprecationWarning, set up in AppInit.extensionsLoaded()\n    EventDispatcher.markDeprecated(exports, \"workingSetAdd\",        \"MainViewManager.workingSetAdd\");\n    EventDispatcher.markDeprecated(exports, \"workingSetAddList\",    \"MainViewManager.workingSetAddList\");\n    EventDispatcher.markDeprecated(exports, \"workingSetRemove\",     \"MainViewManager.workingSetRemove\");\n    EventDispatcher.markDeprecated(exports, \"workingSetRemoveList\", \"MainViewManager.workingSetRemoveList\");\n    EventDispatcher.markDeprecated(exports, \"workingSetSort\",       \"MainViewManager.workingSetSort\");\n\n    /*\n     * After extensionsLoaded, register the proxying listeners that convert newer events to\n     * deprecated events. This ensures that extension listeners still run later than core\n     * listeners. If we registered these proxies earlier, extensions would get the deprecated\n     * event before some core listeners may have run, which could cause bugs (e.g. WorkingSetView\n     * needs to process these events before the Extension Highlighter extension).\n     */\n    AppInit.extensionsLoaded(function () {\n        // Listens for the given event on MainViewManager, and triggers a copy of the event\n        // on DocumentManager whenever it occurs\n        function _proxyDeprecatedEvent(eventName) {\n            DeprecationWarning.deprecateEvent(exports,\n                                              MainViewManager,\n                                              eventName,\n                                              eventName,\n                                              \"DocumentManager.\" + eventName,\n                                              \"MainViewManager.\" + eventName);\n        }\n        _proxyDeprecatedEvent(\"workingSetAdd\");\n        _proxyDeprecatedEvent(\"workingSetAddList\");\n        _proxyDeprecatedEvent(\"workingSetRemove\");\n        _proxyDeprecatedEvent(\"workingSetRemoveList\");\n        _proxyDeprecatedEvent(\"workingSetSort\");\n    });\n\n    // Handle file saves that may affect preferences\n    exports.on(\"documentSaved\", function (e, doc) {\n        PreferencesManager.fileChanged(doc.file.fullPath);\n    });\n\n    MainViewManager.on(\"currentFileChange\", function (e, newFile, newPaneId, oldFile) {\n        var newDoc = null,\n            oldDoc = null;\n\n        if (newFile) {\n            newDoc = getOpenDocumentForPath(newFile.fullPath);\n        }\n\n        if (oldFile) {\n            oldDoc = getOpenDocumentForPath(oldFile.fullPath);\n        }\n\n        if (oldDoc) {\n            oldDoc.off(\"languageChanged.DocumentManager\");\n        }\n\n        if (newDoc) {\n            PreferencesManager._setCurrentLanguage(newDoc.getLanguage().getId());\n            newDoc.on(\"languageChanged.DocumentManager\", function (e, oldLang, newLang) {\n                PreferencesManager._setCurrentLanguage(newLang.getId());\n                exports.trigger(\"currentDocumentLanguageChanged\", [oldLang, newLang]);\n            });\n        } else {\n            PreferencesManager._setCurrentLanguage(undefined);\n        }\n\n        if (newDoc !== oldDoc) {\n            // Dispatch deprecated event with doc args (not File args as the new event uses)\n            exports.trigger(\"currentDocumentChange\", newDoc, oldDoc);\n        }\n\n    });\n\n    // Deprecated APIs\n    exports.getWorkingSet                  = getWorkingSet;\n    exports.findInWorkingSet               = findInWorkingSet;\n    exports.addToWorkingSet                = addToWorkingSet;\n    exports.addListToWorkingSet            = addListToWorkingSet;\n    exports.removeListFromWorkingSet       = removeListFromWorkingSet;\n    exports.getCurrentDocument             = getCurrentDocument;\n    exports.beginDocumentNavigation        = beginDocumentNavigation;\n    exports.finalizeDocumentNavigation     = finalizeDocumentNavigation;\n    exports.getNextPrevFile                = getNextPrevFile;\n    exports.setCurrentDocument             = setCurrentDocument;\n    exports.closeFullEditor                = closeFullEditor;\n    exports.closeAll                       = closeAll;\n\n    // Define public API\n    exports.Document                    = DocumentModule.Document;\n    exports.getDocumentForPath          = getDocumentForPath;\n    exports.getOpenDocumentForPath      = getOpenDocumentForPath;\n    exports.getDocumentText             = getDocumentText;\n    exports.createUntitledDocument      = createUntitledDocument;\n    exports.getAllOpenDocuments         = getAllOpenDocuments;\n\n    // For internal use only\n    exports.notifyPathNameChanged       = notifyPathNameChanged;\n    exports.notifyPathDeleted           = notifyPathDeleted;\n    exports.notifyFileDeleted           = notifyFileDeleted;\n\n    // Performance measurements\n    PerfUtils.createPerfMeasurement(\"DOCUMENT_MANAGER_GET_DOCUMENT_FOR_PATH\", \"DocumentManager.getDocumentForPath()\");\n\n    // Handle Language change events\n    LanguageManager.on(\"languageAdded\", _handleLanguageAdded);\n    LanguageManager.on(\"languageModified\", _handleLanguageModified);\n});\n"
  },
  {
    "path": "src/document/InMemoryFile.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Represents a file that will never exist on disk - a placeholder backing file for untitled Documents. NO ONE\n * other than DocumentManager should create instances of InMemoryFile. It is valid to test for one (`instanceof\n * InMemoryFile`), but it's better to check `doc.isUntitled` where possible.\n *\n * Attempts to read/write an InMemoryFile will always fail, and exists() always yields false. InMemoryFile.fullPath\n * is just a placeholder, and should not be displayed anywhere in the UI; fullPath IS guaranteed to be unique, however.\n *\n * An InMemoryFile is not added to the filesystem index, so if you ask the filesystem anything about this\n * object, it won't know what you're talking about (`filesystem.getFileForPath(someInMemFile.fullPath)` will not\n * return someInMemFile).\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var File            = require(\"filesystem/File\"),\n        FileSystemError = require(\"filesystem/FileSystemError\");\n\n    function InMemoryFile(fullPath, fileSystem) {\n        File.call(this, fullPath, fileSystem);\n    }\n\n    InMemoryFile.prototype = Object.create(File.prototype);\n    InMemoryFile.prototype.constructor = InMemoryFile;\n    InMemoryFile.prototype.parentClass = File.prototype;\n\n    // Stub out invalid calls inherited from File\n\n    /**\n     * Reject any attempts to read the file.\n     *\n     * Read a file as text.\n     *\n     * @param {Object=} options Currently unused.\n     * @param {function (number, string, object)} callback\n     */\n    InMemoryFile.prototype.read = function (options, callback) {\n        if (typeof (options) === \"function\") {\n            callback = options;\n        }\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    /**\n     * Rejects any attempts to write the file.\n     *\n     * @param {string} data Data to write.\n     * @param {string=} encoding Encoding for data. Defaults to UTF-8.\n     * @param {!function (err, object)} callback Callback that is passed the\n     *              error code and the file's new stats if the write is successful.\n     */\n    InMemoryFile.prototype.write = function (data, encoding, callback) {\n        if (typeof (encoding) === \"function\") {\n            callback = encoding;\n        }\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n\n    // Stub out invalid calls inherited from FileSystemEntry\n\n    InMemoryFile.prototype.exists = function (callback) {\n        callback(null, false);\n    };\n\n    InMemoryFile.prototype.stat = function (callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    InMemoryFile.prototype.unlink = function (callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    InMemoryFile.prototype.rename = function (newName, callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    InMemoryFile.prototype.moveToTrash = function (callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    // Export this class\n    module.exports = InMemoryFile;\n});\n"
  },
  {
    "path": "src/document/TextRange.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher = require(\"utils/EventDispatcher\");\n\n\n    /**\n     * Stores a range of lines that is automatically maintained as the Document changes. The range\n     * MAY drop out of sync with the Document in certain edge cases; startLine & endLine will become\n     * null when that happens.\n     *\n     * Important: you must dispose() a TextRange when you're done with it. Because TextRange addRef()s\n     * the Document (in order to listen to it), you will leak Documents otherwise.\n     *\n     * TextRange dispatches these events:\n     *  - change -- When the range boundary line numbers change (due to a Document change)\n     *  - contentChange -- When the actual content of the range changes. This might or might not\n     *    be accompanied by a change in the boundary line numbers.\n     *  - lostSync -- When the backing Document changes in such a way that the range can no longer\n     *    accurately be maintained. Generally, occurs whenever an edit spans a range boundary.\n     *    After this, startLine & endLine will be unusable (set to null).\n     *    Also occurs when the document is deleted, though startLine & endLine won't be modified\n     * These events only ever occur in response to Document changes, so if you are already listening\n     * to the Document, you could ignore the TextRange events and just read its updated value in your\n     * own Document change handler.\n     *\n     * @constructor\n     *\n     * @param {!Document} document\n     * @param {number} startLine First line in range (0-based, inclusive)\n     * @param {number} endLine   Last line in range (0-based, inclusive)\n     */\n    function TextRange(document, startLine, endLine) {\n        this.startLine = startLine;\n        this.endLine = endLine;\n\n        this.document = document;\n        document.addRef();\n        // store this-bound versions of listeners so we can remove them later\n        this._handleDocumentChange = this._handleDocumentChange.bind(this);\n        this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);\n        document.on(\"change\", this._handleDocumentChange);\n        document.on(\"deleted\", this._handleDocumentDeleted);\n    }\n    EventDispatcher.makeEventDispatcher(TextRange.prototype);\n\n\n    /** Detaches from the Document. The TextRange will no longer update or send change events */\n    TextRange.prototype.dispose = function (editor, change) {\n        // Disconnect from Document\n        this.document.releaseRef();\n        this.document.off(\"change\", this._handleDocumentChange);\n        this.document.off(\"deleted\", this._handleDocumentDeleted);\n    };\n\n\n    /**\n     * Containing document\n     * @type {!Document}\n     */\n    TextRange.prototype.document = null;\n\n    /**\n     * Starting Line\n     * @type {?number} Null after \"lostSync\" is dispatched\n     */\n    TextRange.prototype.startLine = null;\n\n    /**\n     * Ending Line\n     * @type {?number} Null after \"lostSync\" is dispatched\n     */\n    TextRange.prototype.endLine = null;\n\n\n    /**\n     * Applies a single Document change object (out of the linked list of multiple such objects)\n     * to this range.\n     * @param {Object} change The CodeMirror change record.\n     * @return {{hasChanged: boolean, hasContentChanged: boolean}} Whether the range boundary\n     *     and/or content has changed.\n     */\n    TextRange.prototype._applySingleChangeToRange = function (change) {\n        // console.log(this + \" applying change to (\" +\n        //         (change.from && (change.from.line+\",\"+change.from.ch)) + \" - \" +\n        //         (change.to && (change.to.line+\",\"+change.to.ch)) + \")\");\n\n        // Special case: the range is no longer meaningful since the entire text was replaced\n        if (!change.from || !change.to) {\n            this.startLine = null;\n            this.endLine = null;\n            return {hasChanged: true, hasContentChanged: true};\n\n        // Special case: certain changes around the edges of the range are problematic, because\n        // if they're undone, we'll be unable to determine how to fix up the range to include the\n        // undone content. (The \"undo\" will just look like an insertion outside our bounds.) So\n        // in those cases, we destroy the range instead of fixing it up incorrectly. The specific\n        // cases are:\n        // 1. Edit crosses the start boundary of the inline editor (defined as character 0\n        //    of the first line).\n        // 2. Edit crosses the end boundary of the inline editor (defined as the newline at\n        //    the end of the last line).\n        // Note: we also used to disallow edits that start at the beginning of the range (character 0\n        //    of the first line) if they crossed a newline. This was a vestige from before case #1\n        //    was added; now that edits crossing the top boundary (actually, undos of such edits) are\n        //    out of the picture, edits on the first line of the range unambiguously belong inside it.\n        } else if ((change.from.line < this.startLine && change.to.line >= this.startLine) ||\n                   (change.from.line <= this.endLine && change.to.line > this.endLine)) {\n            this.startLine = null;\n            this.endLine = null;\n            return {hasChanged: true, hasContentChanged: true};\n\n        // Normal case: update the range end points if any content was added before them. Note that\n        // we don't rely on line handles for this since we want to gracefully handle cases where the\n        // start or end line was deleted during a change.\n        } else {\n            var numAdded = change.text.length - (change.to.line - change.from.line + 1);\n            var result = {hasChanged: false, hasContentChanged: false};\n\n            // This logic is so simple because we've already excluded all cases where the change\n            // crosses the range boundaries\n            if (numAdded !== 0) {\n                if (change.to.line < this.startLine) {\n                    this.startLine += numAdded;\n                    result.hasChanged = true;\n                }\n                if (change.to.line <= this.endLine) {\n                    this.endLine += numAdded;\n                    result.hasChanged = true;\n                }\n            }\n            if (change.from.line >= this.startLine && change.from.line <= this.endLine) {\n                // Since we know the change doesn't cross the range boundary, as long as the\n                // start of the change is within the range, we know the content changed.\n                result.hasContentChanged = true;\n            }\n\n            // console.log(\"Now \" + this);\n\n            return result;\n        }\n    };\n\n    /**\n     * Updates the range based on the changeList from a Document \"change\" event. Dispatches a\n     * \"change\" event if the range was adjusted at all. Dispatches a \"lostSync\" event instead if the\n     * range can no longer be accurately maintained.\n     */\n    TextRange.prototype._applyChangesToRange = function (changeList) {\n        var hasChanged = false, hasContentChanged = false;\n        var i;\n        for (i = 0; i < changeList.length; i++) {\n            // Apply this step of the change list\n            var result = this._applySingleChangeToRange(changeList[i]);\n            hasChanged = hasChanged || result.hasChanged;\n            hasContentChanged = hasContentChanged || result.hasContentChanged;\n\n            // If we lost sync with the range, just bail now\n            if (this.startLine === null || this.endLine === null) {\n                this.trigger(\"lostSync\");\n                break;\n            }\n        }\n\n        if (hasChanged) {\n            this.trigger(\"change\");\n        }\n        if (hasContentChanged) {\n            this.trigger(\"contentChange\");\n        }\n    };\n\n    TextRange.prototype._handleDocumentChange = function (event, doc, changeList) {\n        this._applyChangesToRange(changeList);\n    };\n\n    TextRange.prototype._handleDocumentDeleted = function (event) {\n        this.trigger(\"lostSync\");\n    };\n\n\n    /* (pretty toString(), to aid debugging) */\n    TextRange.prototype.toString = function () {\n        return \"[TextRange \" + this.startLine + \"-\" + this.endLine + \" in \" + this.document + \"]\";\n    };\n\n\n    // Define public API\n    exports.TextRange = TextRange;\n});\n"
  },
  {
    "path": "src/editor/CSSInlineEditor.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var CSSUtils                = require(\"language/CSSUtils\"),\n        DropdownButton          = require(\"widgets/DropdownButton\").DropdownButton,\n        CommandManager          = require(\"command/CommandManager\"),\n        Commands                = require(\"command/Commands\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        Editor                  = require(\"editor/Editor\").Editor,\n        LanguageManager         = require(\"language/LanguageManager\"),\n        ProjectManager          = require(\"project/ProjectManager\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        HTMLUtils               = require(\"language/HTMLUtils\"),\n        MultiRangeInlineEditor  = require(\"editor/MultiRangeInlineEditor\"),\n        Strings                 = require(\"strings\"),\n        ViewUtils               = require(\"utils/ViewUtils\"),\n        HealthLogger            = require(\"utils/HealthLogger\"),\n        _                       = require(\"thirdparty/lodash\");\n\n    var _newRuleCmd,\n        _newRuleHandlers = [];\n\n    function _getCSSFilesInProject() {\n        return ProjectManager.getAllFiles(ProjectManager.getLanguageFilter([\"css\", \"less\", \"scss\"]));\n    }\n\n    /**\n     * Given a position in an HTML editor, returns the relevant selector for the attribute/tag\n     * surrounding that position, or \"\" if none is found.\n     * @param {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {selectorName: {string}, reason: {string}}\n     * @private\n     */\n    function _getSelectorName(editor, pos) {\n        var tagInfo = HTMLUtils.getTagInfo(editor, pos),\n            selectorName = \"\",\n            reason;\n\n        if (tagInfo.position.tokenType === HTMLUtils.TAG_NAME || tagInfo.position.tokenType === HTMLUtils.CLOSING_TAG) {\n            // Type selector\n            selectorName = tagInfo.tagName;\n        } else if (tagInfo.position.tokenType === HTMLUtils.ATTR_NAME ||\n                   tagInfo.position.tokenType === HTMLUtils.ATTR_VALUE) {\n            if (tagInfo.attr.name === \"class\") {\n                // Class selector. We only look for the class name\n                // that includes the insertion point. For example, if\n                // the attribute is:\n                //   class=\"error-dialog modal hide\"\n                // and the insertion point is inside \"modal\", we want \".modal\"\n                var attributeValue = tagInfo.attr.value;\n                if (/\\S/.test(attributeValue)) {\n                    var startIndex = attributeValue.substr(0, tagInfo.position.offset).lastIndexOf(\" \");\n                    var endIndex = attributeValue.indexOf(\" \", tagInfo.position.offset);\n                    selectorName = \".\" +\n                        attributeValue.substring(\n                            startIndex === -1 ? 0 : startIndex + 1,\n                            endIndex === -1 ? attributeValue.length : endIndex\n                        );\n\n                    // If the insertion point is surrounded by space between two classnames, selectorName is \".\"\n                    if (selectorName === \".\") {\n                        selectorName = \"\";\n                        reason = Strings.ERROR_CSSQUICKEDIT_BETWEENCLASSES;\n                    }\n                } else {\n                    reason = Strings.ERROR_CSSQUICKEDIT_CLASSNOTFOUND;\n                }\n            } else if (tagInfo.attr.name === \"id\") {\n                // ID selector\n                var trimmedVal = tagInfo.attr.value.trim();\n                if (trimmedVal) {\n                    selectorName = \"#\" + trimmedVal;\n                } else {\n                    reason = Strings.ERROR_CSSQUICKEDIT_IDNOTFOUND;\n                }\n            } else {\n                reason = Strings.ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR;\n            }\n        }\n\n        return {\n            selectorName: selectorName,\n            reason:       reason\n        };\n    }\n\n    /**\n     * @private\n     * Add a new rule for the given selector to the given stylesheet, then add the rule to the\n     * given inline editor.\n     * @param {string} selectorName The selector to create a rule for.\n     * @param {MultiRangeInlineEditor} inlineEditor The inline editor to display the new rule in.\n     * @param {string} path The path to the stylesheet file.\n     */\n    function _addRule(selectorName, inlineEditor, path) {\n        DocumentManager.getDocumentForPath(path).done(function (styleDoc) {\n            var newRuleInfo = CSSUtils.addRuleToDocument(styleDoc, selectorName, Editor.getUseTabChar(path), Editor.getSpaceUnits(path));\n            inlineEditor.addAndSelectRange(selectorName, styleDoc, newRuleInfo.range.from.line, newRuleInfo.range.to.line);\n            inlineEditor.editor.setCursorPos(newRuleInfo.pos.line, newRuleInfo.pos.ch);\n        });\n    }\n\n    /**\n     * @private\n     * Handle the \"new rule\" menu item by dispatching it to the handler for the focused inline editor.\n     */\n    function _handleNewRule() {\n        var inlineEditor = MultiRangeInlineEditor.getFocusedMultiRangeInlineEditor();\n        if (inlineEditor) {\n            var handlerInfo = _.find(_newRuleHandlers, function (entry) {\n                return entry.inlineEditor === inlineEditor;\n            });\n            if (handlerInfo) {\n                handlerInfo.handler();\n            }\n        }\n    }\n\n    /** Item renderer for stylesheet-picker dropdown */\n    function _stylesheetListRenderer(item) {\n        var html = \"<span class='stylesheet-name'>\" + _.escape(item.name);\n        if (item.subDirStr) {\n            html += \"<span class='stylesheet-dir'> — \" + _.escape(item.subDirStr) + \"</span>\";\n        }\n        html += \"</span>\";\n        return html;\n    }\n\n    /**\n     * This function is registered with EditManager as an inline editor provider. It creates a CSSInlineEditor\n     * when cursor is on an HTML tag name, class attribute, or id attribute, find associated\n     * CSS rules and show (one/all of them) in an inline editor.\n     *\n     * @param {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {?$.Promise} synchronously resolved with an InlineWidget; or error\n     *         {string} if pos is in tag but not in tag name, class attr, or id attr; or null if the\n     *         selection isn't even close to a context where we could provide anything.\n     */\n    function htmlToCSSProvider(hostEditor, pos) {\n\n        // Only provide a CSS editor when cursor is in HTML content\n        if (hostEditor.getLanguageForSelection().getId() !== \"html\") {\n            return null;\n        }\n\n        //Send analytics data for QuickEdit open\n        HealthLogger.sendAnalyticsData(\n            \"QuickEditOpen\",\n            \"usage\",\n            \"quickEdit\",\n            \"open\"\n        );\n\n        // Only provide CSS editor if the selection is within a single line\n        var sel = hostEditor.getSelection();\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n\n        // Always use the selection start for determining selector name. The pos\n        // parameter is usually the selection end.\n        var selectorResult = _getSelectorName(hostEditor, sel.start);\n        if (selectorResult.selectorName === \"\") {\n            return selectorResult.reason || null;\n        }\n\n        var selectorName = selectorResult.selectorName;\n\n        var result = new $.Deferred(),\n            cssInlineEditor,\n            cssFileInfos = [],\n            newRuleButton;\n\n        /**\n         * @private\n         * Callback when item from dropdown list is selected\n         */\n        function _onDropdownSelect(event, fileInfo) {\n            _addRule(selectorName, cssInlineEditor, fileInfo.fullPath);\n        }\n\n        /**\n         * @private\n         * Checks to see if there are any stylesheets in the project, and returns the appropriate\n         * \"no rules\"/\"no stylesheets\" message accordingly.\n         * @return {$.Promise} a promise that is resolved with the message to show. Never rejected.\n         */\n        function _getNoRulesMsg() {\n            var result = new $.Deferred();\n            _getCSSFilesInProject().done(function (fileInfos) {\n                result.resolve(fileInfos.length ? Strings.CSS_QUICK_EDIT_NO_MATCHES : Strings.CSS_QUICK_EDIT_NO_STYLESHEETS);\n            });\n            return result;\n        }\n\n        /**\n         * @private\n         * Update the enablement of associated menu commands.\n         */\n        function _updateCommands() {\n            _newRuleCmd.setEnabled(cssInlineEditor.hasFocus() && !newRuleButton.$button.hasClass(\"disabled\"));\n        }\n\n        /**\n         * @private\n         * Create a new rule on click.\n         */\n        function _handleNewRuleClick(e) {\n            if (!newRuleButton.$button.hasClass(\"disabled\")) {\n                if (cssFileInfos.length === 1) {\n                    // Just go ahead and create the rule.\n                    _addRule(selectorName, cssInlineEditor, cssFileInfos[0].fullPath);\n                } else {\n                    // Although not attached to button click in 'dropdown mode', this handler can still be\n                    // invoked via the command shortcut. Just toggle dropdown open/closed in that case.\n                    newRuleButton.toggleDropdown();\n                }\n            }\n        }\n\n        /**\n         * @private\n         * Sort files with LESS/SCSS above CSS, and then within each grouping sort by path & filename\n         * (the same order we use for Find in Files)\n         * @param {!File} a, b\n         * @return {number}\n         */\n        function _fileComparator(a, b) {\n            var aIsCSS = LanguageManager.getLanguageForPath(a.fullPath).getId() === \"css\",\n                bIsCSS = LanguageManager.getLanguageForPath(b.fullPath).getId() === \"css\";\n            if (aIsCSS && !bIsCSS) {\n                return 1;\n            } else if (!aIsCSS && bIsCSS) {\n                return -1;\n            } else {\n                return FileUtils.comparePaths(a.fullPath, b.fullPath);\n            }\n        }\n\n        /**\n         * @private\n         * Prepare file list for display\n         */\n        function _prepFileList(files) {\n            // First, sort list (the same ordering we use for the results list)\n            files.sort(_fileComparator);\n\n            // Find any files that share the same name (with different path)\n            var fileNames = {};\n            files.forEach(function (file) {\n                if (!fileNames[file.name]) {\n                    fileNames[file.name] = [];\n                }\n                fileNames[file.name].push(file);\n            });\n\n            // For any duplicate filenames, set subDirStr to a path snippet the helps\n            // the user distinguish each file in the list.\n            _.forEach(fileNames, function (files) {\n                if (files.length > 1) {\n                    var displayPaths = ViewUtils.getDirNamesForDuplicateFiles(files);\n                    files.forEach(function (file, i) {\n                        file.subDirStr = displayPaths[i];\n                    });\n                }\n            });\n\n            return files;\n        }\n\n        function _onHostEditorScroll() {\n            newRuleButton.closeDropdown();\n        }\n\n        CSSUtils.findMatchingRules(selectorName, hostEditor.document)\n            .done(function (rules) {\n                var inlineEditorDeferred = new $.Deferred();\n                cssInlineEditor = new MultiRangeInlineEditor.MultiRangeInlineEditor(CSSUtils.consolidateRules(rules),\n                                                                                    _getNoRulesMsg, CSSUtils.getRangeSelectors,\n                                                                                    _fileComparator);\n                cssInlineEditor.load(hostEditor);\n                cssInlineEditor.$htmlContent\n                    .on(\"focusin\", _updateCommands)\n                    .on(\"focusout\", _updateCommands);\n                cssInlineEditor.on(\"add\", function () {\n                    inlineEditorDeferred.resolve();\n                });\n                cssInlineEditor.on(\"close\", function () {\n                    newRuleButton.closeDropdown();\n                    hostEditor.off(\"scroll\", _onHostEditorScroll);\n                });\n\n                var $header = $(\".inline-editor-header\", cssInlineEditor.$htmlContent);\n                newRuleButton = new DropdownButton(Strings.BUTTON_NEW_RULE, [], _stylesheetListRenderer); // actual item list populated later, below\n                newRuleButton.$button.addClass(\"disabled\");  // disabled until list is known\n                newRuleButton.$button.addClass(\"btn-mini stylesheet-button\");\n                $header.append(newRuleButton.$button);\n                _newRuleHandlers.push({inlineEditor: cssInlineEditor, handler: _handleNewRuleClick});\n\n                hostEditor.on(\"scroll\", _onHostEditorScroll);\n\n                result.resolve(cssInlineEditor);\n\n\n                // Now that dialog has been built, collect list of stylesheets\n                var stylesheetsPromise = _getCSSFilesInProject();\n\n                // After both the stylesheets are loaded and the inline editor has been added to the DOM,\n                // update the UI accordingly. (Those can happen in either order, so we need to wait for both.)\n                // Note that the stylesheetsPromise needs to be passed first in order for the fileInfos to be\n                // properly passed to the handler, since $.when() passes the results in order of the argument\n                // list.\n                $.when(stylesheetsPromise, inlineEditorDeferred.promise())\n                    .done(function (fileInfos) {\n                        cssFileInfos = _prepFileList(fileInfos);\n\n                        // \"New Rule\" button is disabled by default and gets enabled\n                        // here if there are any stylesheets in project\n                        if (cssFileInfos.length > 0) {\n                            newRuleButton.$button.removeClass(\"disabled\");\n                            if (!rules.length) {\n                                // Force focus to the button so the user can create a new rule from the keyboard.\n                                newRuleButton.$button.focus();\n                            }\n\n                            if (cssFileInfos.length === 1) {\n                                // Make it look & feel like a plain button in this case\n                                newRuleButton.$button.removeClass(\"btn-dropdown\");\n                                newRuleButton.$button.on(\"click\", _handleNewRuleClick);\n                            } else {\n                                // Fill out remaining dropdown attributes otherwise\n                                newRuleButton.items = cssFileInfos;\n                                newRuleButton.on(\"select\", _onDropdownSelect);\n                            }\n                        }\n\n                        _updateCommands();\n                    });\n            })\n            .fail(function (error) {\n                console.warn(\"Error in findMatchingRules()\", error);\n                result.reject();\n            });\n\n        return result.promise();\n    }\n\n    EditorManager.registerInlineEditProvider(htmlToCSSProvider);\n\n    _newRuleCmd = CommandManager.register(Strings.CMD_CSS_QUICK_EDIT_NEW_RULE, Commands.CSS_QUICK_EDIT_NEW_RULE, _handleNewRule);\n    _newRuleCmd.setEnabled(false);\n});\n"
  },
  {
    "path": "src/editor/CodeHintList.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var KeyBindingManager = require(\"command/KeyBindingManager\"),\n        Menus             = require(\"command/Menus\"),\n        KeyEvent          = require(\"utils/KeyEvent\"),\n        StringUtils       = require(\"utils/StringUtils\"),\n        ValidationUtils   = require(\"utils/ValidationUtils\"),\n        ViewUtils         = require(\"utils/ViewUtils\"),\n        PopUpManager      = require(\"widgets/PopUpManager\"),\n        Mustache          = require(\"thirdparty/mustache/mustache\");\n\n    var CodeHintListHTML  = require(\"text!htmlContent/code-hint-list.html\");\n\n    /**\n     * Displays a popup list of hints for a given editor context.\n     *\n     * @constructor\n     * @param {Editor} editor\n     * @param {boolean} insertHintOnTab Whether pressing tab inserts the selected hint\n     * @param {number} maxResults Maximum hints displayed at once. Defaults to 50\n     */\n    function CodeHintList(editor, insertHintOnTab, maxResults) {\n\n        /**\n         * The list of hints to display\n         *\n         * @type {Array.<string|jQueryObject>}\n         */\n        this.hints = [];\n\n        /**\n         * The selected position in the list; otherwise -1.\n         *\n         * @type {number}\n         */\n        this.selectedIndex = -1;\n\n        /**\n         * The maximum number of hints to display. Can be overriden via maxCodeHints pref\n         *\n         * @type {number}\n         */\n        this.maxResults = ValidationUtils.isIntegerInRange(maxResults, 1, 1000) ? maxResults : 50;\n\n        /**\n         * Is the list currently open?\n         *\n         * @type {boolean}\n         */\n        this.opened = false;\n\n        /**\n         * The editor context\n         *\n         * @type {Editor}\n         */\n        this.editor = editor;\n\n        /**\n         * Whether the currently selected hint should be inserted on a tab key event\n         *\n         * @type {boolean}\n         */\n        this.insertHintOnTab = insertHintOnTab;\n\n        /**\n         * Pending text insertion\n         *\n         * @type {string}\n         */\n        this.pendingText = \"\";\n\n        /**\n         * The hint selection callback function\n         *\n         * @type {Function}\n         */\n        this.handleSelect = null;\n\n        /**\n         * The hint list closure callback function\n         *\n         * @type {Function}\n         */\n        this.handleClose = null;\n\n        /**\n         * The hint list menu object\n         *\n         * @type {jQuery.Object}\n         */\n        this.$hintMenu =\n            $(\"<li class='dropdown codehint-menu'></li>\")\n                .append($(\"<a href='#' class='dropdown-toggle' data-toggle='dropdown'></a>\")\n                        .hide())\n                .append(\"<ul class='dropdown-menu'></ul>\");\n\n        this._keydownHook = this._keydownHook.bind(this);\n    }\n\n    /**\n     * Select the item in the hint list at the specified index, or remove the\n     * selection if index < 0.\n     *\n     * @private\n     * @param {number} index\n     */\n    CodeHintList.prototype._setSelectedIndex = function (index) {\n        var items = this.$hintMenu.find(\"li\");\n\n        // Range check\n        index = Math.max(-1, Math.min(index, items.length - 1));\n\n        // Clear old highlight\n        if (this.selectedIndex !== -1) {\n            $(items[this.selectedIndex]).find(\"a\").removeClass(\"highlight\");\n        }\n\n        this.selectedIndex = index;\n\n        // Highlight the new selected item, if necessary\n        if (this.selectedIndex !== -1) {\n            var $item = $(items[this.selectedIndex]);\n            var $view = this.$hintMenu.find(\"ul.dropdown-menu\");\n\n            $item.find(\"a\").addClass(\"highlight\");\n            ViewUtils.scrollElementIntoView($view, $item, false);\n\n            if (this.handleHighlight) {\n                this.handleHighlight($item.find(\"a\"), this.$hintMenu.find(\"#codehint-desc\"));\n            }\n        }\n    };\n\n    /**\n     * Appends text to end of pending text.\n     *\n     * @param {string} text\n     */\n    CodeHintList.prototype.addPendingText = function (text) {\n        this.pendingText += text;\n    };\n\n    /**\n     * Removes text from beginning of pending text.\n     *\n     * @param {string} text\n     */\n    CodeHintList.prototype.removePendingText = function (text) {\n        if (this.pendingText.indexOf(text) === 0) {\n            this.pendingText = this.pendingText.slice(text.length);\n        }\n    };\n\n    /**\n     * Rebuilds the list items for the hint list.\n     *\n     * @private\n     */\n    CodeHintList.prototype._buildListView = function (hintObj) {\n        var self            = this,\n            match           = hintObj.match,\n            selectInitial   = hintObj.selectInitial,\n            view            = { hints: [] },\n            _addHint;\n\n        this.hints = hintObj.hints;\n        this.hints.handleWideResults = hintObj.handleWideResults;\n        this.enableDescription = hintObj.enableDescription;\n\n        // if there is no match, assume name is already a formatted jQuery\n        // object; otherwise, use match to format name for display.\n        if (match) {\n            _addHint = function (name) {\n                var displayName = name.replace(\n                    new RegExp(StringUtils.regexEscape(match), \"i\"),\n                    \"<strong>$&</strong>\"\n                );\n\n                view.hints.push({ formattedHint: \"<span>\" + displayName + \"</span>\" });\n            };\n        } else {\n            _addHint = function (hint) {\n                view.hints.push({ formattedHint: (hint.jquery) ? \"\" : hint });\n            };\n        }\n\n        // clear the list\n        this.$hintMenu.find(\"li\").remove();\n\n        // if there are no hints then close the list; otherwise add them and\n        // set the selection\n        if (this.hints.length === 0) {\n            if (this.handleClose) {\n                this.handleClose();\n            }\n        } else {\n            this.hints.some(function (item, index) {\n                if (index >= self.maxResults) {\n                    return true;\n                }\n\n                _addHint(item);\n            });\n\n            // render code hint list\n            var $ul = this.$hintMenu.find(\"ul.dropdown-menu\"),\n                $parent = $ul.parent();\n\n            // remove list temporarily to save rendering time\n            $ul.remove().append(Mustache.render(CodeHintListHTML, view));\n\n            $ul.children(\"li\").each(function (index, element) {\n                var hint        = self.hints[index],\n                    $element    = $(element);\n\n                // store hint on each list item\n                $element.data(\"hint\", hint);\n\n                // insert jQuery hint objects after the template is rendered\n                if (hint.jquery) {\n                    $element.find(\".codehint-item\").append(hint);\n                }\n            });\n\n            // delegate list item events to the top-level ul list element\n            $ul.on(\"click\", \"li\", function (e) {\n                // Don't let the click propagate upward (otherwise it will\n                // hit the close handler in bootstrap-dropdown).\n                e.stopPropagation();\n                if (self.handleSelect) {\n                    self.handleSelect($(this).data(\"hint\"));\n                }\n            });\n\n            // Lists with wide results require different formatting\n            if (this.hints.handleWideResults) {\n                $ul.find(\"li a\").addClass(\"wide-result\");\n            }\n\n            // attach to DOM\n            $parent.append($ul);\n\n            // If a a description field requested attach one\n            if (this.enableDescription) {\n                // Remove the desc element first to ensure DOM order\n                $parent.find(\"#codehint-desc\").remove();\n                $parent.append(\"<div id='codehint-desc' class='dropdown-menu quiet-scrollbars'></div>\");\n                $ul.addClass(\"withDesc\");\n            }\n            this._setSelectedIndex(selectInitial ? 0 : -1);\n        }\n    };\n\n    /**\n     * Computes top left location for hint list so that the list is not clipped by the window.\n     * Also computes the largest available width.\n     *\n     * @private\n     * @return {{left: number, top: number, width: number}}\n     */\n    CodeHintList.prototype._calcHintListLocation = function () {\n        var cursor      = this.editor._codeMirror.cursorCoords(),\n            posTop      = cursor.bottom,\n            posLeft     = cursor.left,\n            textHeight  = this.editor.getTextHeight(),\n            $window     = $(window),\n            $menuWindow = this.$hintMenu.children(\"ul\"),\n            $descElement = this.$hintMenu.find(\"#codehint-desc\"),\n            descOverhang = $descElement.length === 1 ? $descElement.height() : 0,\n            menuHeight  = $menuWindow.outerHeight() + descOverhang;\n\n        // TODO Ty: factor out menu repositioning logic so code hints and Context menus share code\n        // adjust positioning so menu is not clipped off bottom or right\n        var bottomOverhang = posTop + menuHeight - $window.height();\n        if (bottomOverhang > 0) {\n            posTop -= (textHeight + 2 + menuHeight);\n        }\n\n        posTop -= 30;   // shift top for hidden parent element\n\n        var menuWidth = $menuWindow.width();\n        var availableWidth = menuWidth;\n        var rightOverhang = posLeft + menuWidth - $window.width();\n        if (rightOverhang > 0) {\n            posLeft = Math.max(0, posLeft - rightOverhang);\n        } else if (this.hints.handleWideResults) {\n            // Right overhang is negative\n            availableWidth = menuWidth + Math.abs(rightOverhang);\n        }\n\n        //Creating the offset element for hint description element\n        var descOffset = this.$hintMenu.find(\"ul.dropdown-menu\")[0].getBoundingClientRect().height;\n        if (descOffset === 0) {\n            descOffset = menuHeight - descOverhang;\n        }\n        this.$hintMenu.find(\"#codehint-desc\").css(\"margin-top\", descOffset - 1);\n\n        return {left: posLeft, top: posTop, width: availableWidth};\n    };\n\n    /**\n     * Check whether Event is one of the keys that we handle or not.\n     *\n     * @param {KeyBoardEvent|keyBoardEvent.keyCode} keyEvent\n     */\n    CodeHintList.prototype.isHandlingKeyCode = function (keyCodeOrEvent) {\n        var keyCode = typeof keyCodeOrEvent === \"object\" ? keyCodeOrEvent.keyCode : keyCodeOrEvent;\n        var ctrlKey = typeof keyCodeOrEvent === \"object\" ? keyCodeOrEvent.ctrlKey : false;\n\n\n        return (keyCode === KeyEvent.DOM_VK_UP || keyCode === KeyEvent.DOM_VK_DOWN ||\n                keyCode === KeyEvent.DOM_VK_PAGE_UP || keyCode === KeyEvent.DOM_VK_PAGE_DOWN ||\n                keyCode === KeyEvent.DOM_VK_RETURN ||\n                keyCode === KeyEvent.DOM_VK_CONTROL ||\n                keyCode === KeyEvent.DOM_VK_ESCAPE ||\n                (ctrlKey && keyCode === KeyEvent.DOM_VK_SPACE) ||\n                (keyCode === KeyEvent.DOM_VK_TAB && this.insertHintOnTab));\n    };\n\n    /**\n     * Convert keydown events into hint list navigation actions.\n     *\n     * @param {KeyBoardEvent} keyEvent\n     * @param {bool} isFakeKeydown - True if faked key down call (for example calling CTRL+Space while hints are open)\n     */\n    CodeHintList.prototype._keydownHook = function (event, isFakeKeydown) {\n        var keyCode,\n            self = this;\n\n        // positive distance rotates down; negative distance rotates up\n        function _rotateSelection(distance) {\n            var len = Math.min(self.hints.length, self.maxResults),\n                pos;\n\n            if (self.selectedIndex < 0) {\n                // set the initial selection\n                pos = (distance > 0) ? distance - 1 : len - 1;\n\n            } else {\n                // adjust current selection\n                pos = self.selectedIndex;\n\n                // Don't \"rotate\" until all items have been shown\n                if (distance > 0) {\n                    if (pos === (len - 1)) {\n                        pos = 0;  // wrap\n                    } else {\n                        pos = Math.min(pos + distance, len - 1);\n                    }\n                } else {\n                    if (pos === 0) {\n                        pos = (len - 1);  // wrap\n                    } else {\n                        pos = Math.max(pos + distance, 0);\n                    }\n                }\n            }\n\n            self._setSelectedIndex(pos);\n        }\n\n        // Calculate the number of items per scroll page.\n        function _itemsPerPage() {\n            var itemsPerPage = 1,\n                $items = self.$hintMenu.find(\"li\"),\n                $view = self.$hintMenu.find(\"ul.dropdown-menu\"),\n                itemHeight;\n\n            if ($items.length !== 0) {\n                itemHeight = $($items[0]).height();\n                if (itemHeight) {\n                    // round down to integer value\n                    itemsPerPage = Math.floor($view.height() / itemHeight);\n                    itemsPerPage = Math.max(1, Math.min(itemsPerPage, $items.length));\n                }\n            }\n\n            return itemsPerPage;\n        }\n\n        // If we're no longer visible, skip handling the key and end the session.\n        if (!this.isOpen()) {\n            this.handleClose();\n            return false;\n        }\n\n        // (page) up, (page) down, enter and tab key are handled by the list\n        if ((event.type === \"keydown\" || isFakeKeydown) && this.isHandlingKeyCode(event)) {\n            keyCode = event.keyCode;\n\n            if (event.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                event.stopImmediatePropagation();\n                this.handleClose();\n                \n                return false;\n            } else if (event.shiftKey &&\n                    (event.keyCode === KeyEvent.DOM_VK_UP ||\n                     event.keyCode === KeyEvent.DOM_VK_DOWN ||\n                     event.keyCode === KeyEvent.DOM_VK_PAGE_UP ||\n                     event.keyCode === KeyEvent.DOM_VK_PAGE_DOWN)) {\n                this.handleClose();\n                // Let the event bubble.\n                return false;\n            } else if (keyCode === KeyEvent.DOM_VK_UP) {\n                _rotateSelection.call(this, -1);\n            } else if (keyCode === KeyEvent.DOM_VK_DOWN ||\n                    (event.ctrlKey && keyCode === KeyEvent.DOM_VK_SPACE)) {\n                _rotateSelection.call(this, 1);\n            } else if (keyCode === KeyEvent.DOM_VK_PAGE_UP) {\n                _rotateSelection.call(this, -_itemsPerPage());\n            } else if (keyCode === KeyEvent.DOM_VK_PAGE_DOWN) {\n                _rotateSelection.call(this, _itemsPerPage());\n            } else if (this.selectedIndex !== -1 &&\n                    (keyCode === KeyEvent.DOM_VK_RETURN ||\n                    (keyCode === KeyEvent.DOM_VK_TAB && this.insertHintOnTab))) {\n\n                if (this.pendingText) {\n                    // Issues #5003: We received a \"selection\" key while there is \"pending\n                    // text\". This is rare but can happen because CM uses polling, so we\n                    // can receive key events while CM is waiting for timeout to expire.\n                    // Pending text may dismiss the list, or it may cause a valid selection\n                    // which keeps open hint list. We can compare pending text against\n                    // list to determine whether list is dismissed or not, but to handle\n                    // inserting selection in the page we'd need to either:\n                    // 1. Synchronously force CodeMirror to poll (but there is not\n                    //    yet a public API for that).\n                    // 2. Pass pending text back to where text gets inserted, which\n                    //    means it would need to be implemented for every HintProvider!\n                    // You have to be typing so fast to hit this case, that's it's\n                    // highly unlikely that inserting something from list was the intent,\n                    // which makes this pretty rare, so case #2 is not worth implementing.\n                    // If case #1 gets implemented, then we may want to use it here.\n                    // So, assume that pending text dismisses hints and let event bubble.\n                    return false;\n                }\n\n                // Trigger a click handler to commmit the selected item\n                $(this.$hintMenu.find(\"li\")[this.selectedIndex]).trigger(\"click\");\n            } else {\n                // Let the event bubble.\n                return false;\n            }\n\n            event.stopImmediatePropagation();\n            event.preventDefault();\n            return true;\n        }\n\n        // If we didn't handle it, let other global keydown hooks handle it.\n        return false;\n    };\n\n    /**\n     * Is the CodeHintList open?\n     *\n     * @return {boolean}\n     */\n    CodeHintList.prototype.isOpen = function () {\n        // We don't get a notification when the dropdown closes. The best\n        // we can do is keep an \"opened\" flag and check to see if we\n        // still have the \"open\" class applied.\n        if (this.opened && !this.$hintMenu.hasClass(\"open\")) {\n            this.opened = false;\n        }\n\n        return this.opened;\n    };\n\n    /**\n     * Displays the hint list at the current cursor position\n     *\n     * @param {{hints: Array.<string|jQueryObject>, match: string,\n     *          selectInitial: boolean}} hintObj\n     */\n    CodeHintList.prototype.open = function (hintObj) {\n        Menus.closeAll();\n        this._buildListView(hintObj);\n\n        if (this.hints.length) {\n            // Need to add the menu to the DOM before trying to calculate its ideal location.\n            $(\"#codehint-menu-bar > ul\").append(this.$hintMenu);\n\n            var hintPos = this._calcHintListLocation();\n\n            this.$hintMenu.addClass(\"open\")\n                .css({\"left\": hintPos.left, \"top\": hintPos.top, \"width\": hintPos.width + \"px\"});\n            this.opened = true;\n\n            KeyBindingManager.addGlobalKeydownHook(this._keydownHook);\n        }\n    };\n\n    /**\n     * Updates the (already open) hint list window with new hints\n     *\n     * @param {{hints: Array.<string|jQueryObject>, match: string,\n     *          selectInitial: boolean}} hintObj\n     */\n    CodeHintList.prototype.update = function (hintObj) {\n        this.$hintMenu.addClass(\"apply-transition\");\n        this._buildListView(hintObj);\n\n        // Update the CodeHintList location\n        if (this.hints.length) {\n            var hintPos = this._calcHintListLocation();\n            this.$hintMenu.css({\"left\": hintPos.left, \"top\": hintPos.top,\n                                \"width\": hintPos.width + \"px\"});\n        }\n    };\n    /**\n     * Calls the move up keybind to move hint suggestion selector\n     *\n     * @param {KeyBoardEvent} keyEvent\n     */\n    CodeHintList.prototype.callMoveUp = function (event) {\n        this._keydownHook(event, true);\n    };\n    /**\n     * Closes the hint list\n     */\n    CodeHintList.prototype.close = function () {\n        this.opened = false;\n\n        if (this.$hintMenu) {\n            this.$hintMenu.removeClass(\"open\");\n            PopUpManager.removePopUp(this.$hintMenu);\n            this.$hintMenu.remove();\n        }\n\n        KeyBindingManager.removeGlobalKeydownHook(this._keydownHook);\n    };\n\n    /**\n     * Set the hint list selection callback function\n     *\n     * @param {Function} callback\n     */\n    CodeHintList.prototype.onSelect = function (callback) {\n        this.handleSelect = callback;\n    };\n\n    /**\n      * Set the hint list highlight callback function\n      *\n      * @param {Function} callback\n      */\n    CodeHintList.prototype.onHighlight = function (callback) {\n        this.handleHighlight = callback;\n    };\n\n    /**\n     * Set the hint list closure callback function\n     *\n     * @param {Function} callback\n     */\n    CodeHintList.prototype.onClose = function (callback) {\n        // TODO: Due to #1381, this won't get called if the user clicks out of\n        // the code hint menu. That's (sort of) okay right now since it doesn't\n        // really matter if a single old invisible code hint list is lying\n        // around (it will ignore keydown events, and it'll get closed the next\n        // time the user pops up a code hint). Once #1381 is fixed this issue\n        // should go away.\n        this.handleClose = callback;\n    };\n\n\n    // Define public API\n    exports.CodeHintList = CodeHintList;\n});\n"
  },
  {
    "path": "src/editor/CodeHintManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * __CodeHintManager Overview:__\n *\n * The CodeHintManager mediates the interaction between the editor and a\n * collection of hint providers. If hints are requested explicitly by the\n * user, then the providers registered for the current language are queried\n * for their ability to provide hints in order of descending priority by\n * way their hasHints methods. Character insertions may also constitute an\n * implicit request for hints; consequently, providers for the current\n * language are also queried on character insertion for both their ability to\n * provide hints and also for the suitability of providing implicit hints\n * in the given editor context.\n *\n * Once a provider responds affirmatively to a request for hints, the\n * manager begins a hinting session with that provider, begins to query\n * that provider for hints by way of its getHints method, and opens the\n * hint list window. The hint list is kept open for the duration of the\n * current session. The manager maintains the session until either:\n *\n *  1. the provider gives a null response to a request for hints;\n *  2. a deferred response to getHints fails to resolve;\n *  3. the user explicitly dismisses the hint list window;\n *  4. the editor is closed or becomes inactive; or\n *  5. the editor undergoes a \"complex\" change, e.g., a multi-character\n *     insertion, deletion or navigation.\n *\n * Single-character insertions, deletions or navigations may not\n * invalidate the current session; in which case, each such change\n * precipitates a successive call to getHints.\n *\n * If the user selects a hint from the rendered hint list then the\n * provider is responsible for inserting the hint into the editor context\n * for the current session by way of its insertHint method. The provider\n * may use the return value of insertHint to request that an additional\n * explicit hint request be triggered, potentially beginning a new\n * session.\n *\n *\n * __CodeHintProvider Overview:__\n *\n * A code hint provider should implement the following three functions:\n *\n * - `CodeHintProvider.hasHints(editor, implicitChar)`\n * - `CodeHintProvider.getHints(implicitChar)`\n * - `CodeHintProvider.insertHint(hint)`\n *\n * The behavior of these three functions is described in detail below.\n *\n * __CodeHintProvider.hasHints(editor, implicitChar)__\n *\n * The method by which a provider indicates intent to provide hints for a\n * given editor. The manager calls this method both when hints are\n * explicitly requested (via, e.g., Ctrl-Space) and when they may be\n * implicitly requested as a result of character insertion in the editor.\n * If the provider responds negatively then the manager may query other\n * providers for hints. Otherwise, a new hinting session begins with this\n * provider, during which the manager may repeatedly query the provider\n * for hints via the getHints method. Note that no other providers will be\n * queried until the hinting session ends.\n *\n * The implicitChar parameter is used to determine whether the hinting\n * request is explicit or implicit. If the string is null then hints were\n * explicitly requested and the provider should reply based on whether it\n * is possible to return hints for the given editor context. Otherwise,\n * the string contains just the last character inserted into the editor's\n * document and the request for hints is implicit. In this case, the\n * provider should determine whether it is both possible and appropriate\n * to show hints. Because implicit hints can be triggered by every\n * character insertion, hasHints may be called frequently; consequently,\n * the provider should endeavor to return a value as quickly as possible.\n *\n * Because calls to hasHints imply that a hinting session is about to\n * begin, a provider may wish to clean up cached data from previous\n * sessions in this method. Similarly, if the provider returns true, it\n * may wish to prepare to cache data suitable for the current session. In\n * particular, it should keep a reference to the editor object so that it\n * can access the editor in future calls to getHints and insertHints.\n *\n * param {Editor} editor\n * A non-null editor object for the active window.\n *\n * param {string} implicitChar\n * Either null, if the hinting request was explicit, or a single character\n * that represents the last insertion and that indicates an implicit\n * hinting request.\n *\n * return {boolean}\n * Determines whether the current provider is able to provide hints for\n * the given editor context and, in case implicitChar is non- null,\n * whether it is appropriate to do so.\n *\n *\n * __CodeHintProvider.getHints(implicitChar)__\n *\n * The method by which a provider provides hints for the editor context\n * associated with the current session. The getHints method is called only\n * if the provider asserted its willingness to provide hints in an earlier\n * call to hasHints. The provider may return null or false, which indicates\n * that the manager should end the current hinting session and close the hint\n * list window; or true, which indicates that the manager should end the\n * current hinting session but immediately attempt to begin a new hinting\n * session by querying registered providers. Otherwise, the provider should\n * return a response object that contains the following properties:\n *\n *  1. hints, a sorted array hints that the provider could later insert\n *     into the editor;\n *  2. match, a string that the manager may use to emphasize substrings of\n *     hints in the hint list (case-insensitive); and\n *  3. selectInitial, a boolean that indicates whether or not the\n *     first hint in the list should be selected by default.\n *  4. handleWideResults, a boolean (or undefined) that indicates whether\n *     to allow result string to stretch width of display.\n *\n * If the array of\n * hints is empty, then the manager will render an empty list, but the\n * hinting session will remain open and the value of the selectInitial\n * property is irrelevant.\n *\n * Alternatively, the provider may return a jQuery.Deferred object\n * that resolves with an object with the structure described above. In\n * this case, the manager will initially render the hint list window with\n * a throbber and will render the actual list once the deferred object\n * resolves to a response object. If a hint list has already been rendered\n * (from an earlier call to getHints), then the old list will continue\n * to be displayed until the new deferred has resolved.\n *\n * Both the manager and the provider can reject the deferred object. The\n * manager will reject the deferred if the editor changes state (e.g., the\n * user types a character) or if the hinting session ends (e.g., the user\n * explicitly closes the hints by pressing escape). The provider can use\n * this event to, e.g., abort an expensive computation. Consequently, the\n * provider may assume that getHints will not be called again until the\n * deferred object from the current call has resolved or been rejected. If\n * the provider rejects the deferred, the manager will end the hinting\n * session.\n *\n * The getHints method may be called by the manager repeatedly during a\n * hinting session. Providers may wish to cache information for efficiency\n * that may be useful throughout these sessions. The same editor context\n * will be used throughout a session, and will only change during the\n * session as a result of single-character insertions, deletions and\n * cursor navigations. The provider may assume that, throughout the\n * lifetime of the session, the getHints method will be called exactly\n * once for each such editor change. Consequently, the provider may also\n * assume that the document will not be changed outside of the editor\n * during a session.\n *\n * param {string} implicitChar\n * Either null, if the request to update the hint list was a result of\n * navigation, or a single character that represents the last insertion.\n *\n *     return {jQuery.Deferred|{\n *          hints: Array.<string|jQueryObject>,\n *          match: string,\n *          selectInitial: boolean,\n *          handleWideResults: boolean}}\n *\n * Null if the provider wishes to end the hinting session. Otherwise, a\n * response object, possibly deferred, that provides 1. a sorted array\n * hints that consists either of strings or jQuery objects; 2. a string\n * match, possibly null, that is used by the manager to emphasize\n * matching substrings when rendering the hint list; and 3. a boolean that\n * indicates whether the first result, if one exists, should be selected\n * by default in the hint list window. If match is non-null, then the\n * hints should be strings.\n *\n * If the match is null, the manager will not\n * attempt to emphasize any parts of the hints when rendering the hint\n * list; instead the provider may return strings or jQuery objects for\n * which emphasis is self-contained. For example, the strings may contain\n * substrings that wrapped in bold tags. In this way, the provider can\n * choose to let the manager handle emphasis for the simple and common case\n * of prefix matching, or can provide its own emphasis if it wishes to use\n * a more sophisticated matching algorithm.\n *\n *\n * __CodeHintProvider.insertHint(hint)__\n *\n * The method by which a provider inserts a hint into the editor context\n * associated with the current session. The provider may assume that the\n * given hint was returned by the provider in some previous call in the\n * current session to getHints, but not necessarily the most recent call.\n * After the insertion has been performed, the current hinting session is\n * closed. The provider should return a boolean value to indicate whether\n * or not the end of the session should be immediately followed by a new\n * explicit hinting request, which may result in a new hinting session\n * being opened with some provider, but not necessarily the current one.\n *\n * param {string} hint\n * The hint to be inserted into the editor context for the current session.\n *\n * return {boolean}\n * Indicates whether the manager should follow hint insertion with an\n * explicit hint request.\n *\n *\n * __CodeHintProvider.insertHintOnTab__\n *\n * type {?boolean} insertHintOnTab\n * Indicates whether the CodeHintManager should request that the provider of\n * the current session insert the currently selected hint on tab key events,\n * or if instead a tab character should be inserted into the editor. If omitted,\n * the fallback behavior is determined by the CodeHintManager. The default\n * behavior is to insert a tab character, but this can be changed with the\n * insertHintOnTab Preference.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        Strings             = require(\"strings\"),\n        KeyEvent            = require(\"utils/KeyEvent\"),\n        CodeHintList        = require(\"editor/CodeHintList\").CodeHintList,\n        PreferencesManager  = require(\"preferences/PreferencesManager\");\n\n    var hintProviders    = { \"all\" : [] },\n        lastChar         = null,\n        sessionProvider  = null,\n        sessionEditor    = null,\n        hintList         = null,\n        deferredHints    = null,\n        keyDownEditor    = null,\n        codeHintsEnabled = true,\n        codeHintOpened   = false;\n\n    PreferencesManager.definePreference(\"showCodeHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_SHOW_CODE_HINTS\n    });\n    PreferencesManager.definePreference(\"insertHintOnTab\", \"boolean\", false, {\n        description: Strings.DESCRIPTION_INSERT_HINT_ON_TAB\n    });\n    PreferencesManager.definePreference(\"maxCodeHints\", \"number\", 50, {\n        description: Strings.DESCRIPTION_MAX_CODE_HINTS\n    });\n\n    PreferencesManager.on(\"change\", \"showCodeHints\", function () {\n        codeHintsEnabled = PreferencesManager.get(\"showCodeHints\");\n    });\n\n    /**\n     * Comparator to sort providers from high to low priority\n     */\n    function _providerSort(a, b) {\n        return b.priority - a.priority;\n    }\n\n    /**\n     * The method by which a CodeHintProvider registers its willingness to\n     * providing hints for editors in a given language.\n     *\n     * @param {!CodeHintProvider} provider\n     * The hint provider to be registered, described below.\n     *\n     * @param {!Array.<string>} languageIds\n     * The set of language ids for which the provider is capable of\n     * providing hints. If the special language id name \"all\" is included then\n     * the provider may be called for any language.\n     *\n     * @param {?number} priority\n     * Used to break ties among hint providers for a particular language.\n     * Providers with a higher number will be asked for hints before those\n     * with a lower priority value. Defaults to zero.\n     */\n    function registerHintProvider(providerInfo, languageIds, priority) {\n        var providerObj = { provider: providerInfo,\n                            priority: priority || 0 };\n\n        if (languageIds.indexOf(\"all\") !== -1) {\n            // Ignore anything else in languageIds and just register for every language. This includes\n            // the special \"all\" language since its key is in the hintProviders map from the beginning.\n            var languageId;\n            for (languageId in hintProviders) {\n                if (hintProviders.hasOwnProperty(languageId)) {\n                    hintProviders[languageId].push(providerObj);\n                    hintProviders[languageId].sort(_providerSort);\n                }\n            }\n        } else {\n            languageIds.forEach(function (languageId) {\n                if (!hintProviders[languageId]) {\n                    // Initialize provider list with any existing all-language providers\n                    hintProviders[languageId] = Array.prototype.concat(hintProviders.all);\n                }\n                hintProviders[languageId].push(providerObj);\n                hintProviders[languageId].sort(_providerSort);\n            });\n        }\n    }\n\n    /**\n     * @private\n     * Remove a code hint provider\n     * @param {!CodeHintProvider} provider Code hint provider to remove\n     * @param {(string|Array.<string>)=} targetLanguageId Optional set of\n     *     language IDs for languages to remove the provider for. Defaults\n     *     to all languages.\n     */\n    function _removeHintProvider(provider, targetLanguageId) {\n        var index,\n            providers,\n            targetLanguageIdArr;\n\n        if (Array.isArray(targetLanguageId)) {\n            targetLanguageIdArr = targetLanguageId;\n        } else if (targetLanguageId) {\n            targetLanguageIdArr = [targetLanguageId];\n        } else {\n            targetLanguageIdArr = Object.keys(hintProviders);\n        }\n\n        targetLanguageIdArr.forEach(function (languageId) {\n            providers = hintProviders[languageId];\n\n            for (index = 0; index < providers.length; index++) {\n                if (providers[index].provider === provider) {\n                    providers.splice(index, 1);\n                    break;\n                }\n            }\n        });\n    }\n\n    /**\n     *  Return the array of hint providers for the given language id.\n     *  This gets called (potentially) on every keypress. So, it should be fast.\n     *\n     * @param {!string} languageId\n     * @return {?Array.<{provider: Object, priority: number}>}\n     */\n    function _getProvidersForLanguageId(languageId) {\n        var providers = hintProviders[languageId] || hintProviders.all;\n\n        // Exclude providers that are explicitly disabled in the preferences.\n        // All code hint providers that do not have their constructor\n        // names listed in the preferences are enabled by default.\n        return providers.filter(function (provider) {\n            var prefKey = \"codehint.\" + provider.provider.constructor.name;\n            return PreferencesManager.get(prefKey) !== false;\n        });\n    }\n\n    var _beginSession;\n\n    /**\n     * End the current hinting session\n     */\n    function _endSession() {\n        if (!hintList) {\n            return;\n        }\n        hintList.close();\n        hintList = null;\n        codeHintOpened = false;\n        keyDownEditor = null;\n        sessionProvider = null;\n        sessionEditor = null;\n        if (deferredHints) {\n            deferredHints.reject();\n            deferredHints = null;\n        }\n    }\n\n    /**\n     * Is there a hinting session active for a given editor?\n     *\n     * NOTE: the sessionEditor, sessionProvider and hintList objects are\n     * only guaranteed to be initialized during an active session.\n     *\n     * @param {Editor} editor\n     * @return boolean\n     */\n    function _inSession(editor) {\n        if (sessionEditor) {\n            if (sessionEditor === editor &&\n                    (hintList.isOpen() ||\n                     (deferredHints && deferredHints.state() === \"pending\"))) {\n                return true;\n            } else {\n                // the editor has changed\n                _endSession();\n            }\n        }\n        return false;\n    }\n    /**\n     * From an active hinting session, get hints from the current provider and\n     * render the hint list window.\n     *\n     * Assumes that it is called when a session is active (i.e. sessionProvider is not null).\n     */\n    function _updateHintList(callMoveUpEvent) {\n\n        callMoveUpEvent = typeof callMoveUpEvent === \"undefined\" ? false : callMoveUpEvent;\n\n        if (deferredHints) {\n            deferredHints.reject();\n            deferredHints = null;\n        }\n\n        if (callMoveUpEvent) {\n            return hintList.callMoveUp(callMoveUpEvent);\n        }\n\n        var response = sessionProvider.getHints(lastChar);\n        lastChar = null;\n\n        if (!response) {\n            // the provider wishes to close the session\n            _endSession();\n        } else {\n            // if the response is true, end the session and begin another\n            if (response === true) {\n                var previousEditor = sessionEditor;\n\n                _endSession();\n                _beginSession(previousEditor);\n            } else if (response.hasOwnProperty(\"hints\")) { // a synchronous response\n                if (hintList.isOpen()) {\n                    // the session is open\n                    hintList.update(response);\n                } else {\n                    hintList.open(response);\n                }\n            } else { // response is a deferred\n                deferredHints = response;\n                response.done(function (hints) {\n                    // Guard against timing issues where the session ends before the\n                    // response gets a chance to execute the callback.  If the session\n                    // ends first while still waiting on the response, then hintList\n                    // will get cleared up.\n                    if (!hintList) {\n                        return;\n                    }\n\n                    if (hintList.isOpen()) {\n                        // the session is open\n                        hintList.update(hints);\n                    } else {\n                        hintList.open(hints);\n                    }\n                });\n            }\n        }\n    }\n\n    /**\n     * Try to begin a new hinting session.\n     * @param {Editor} editor\n     */\n    _beginSession = function (editor) {\n\n        if (!codeHintsEnabled) {\n            return;\n        }\n\n        // Don't start a session if we have a multiple selection.\n        if (editor.getSelections().length > 1) {\n            return;\n        }\n\n        // Find a suitable provider, if any\n        var language = editor.getLanguageForSelection(),\n            enabledProviders = _getProvidersForLanguageId(language.getId());\n\n        enabledProviders.some(function (item, index) {\n            if (item.provider.hasHints(editor, lastChar)) {\n                sessionProvider = item.provider;\n                return true;\n            }\n        });\n\n        // If a provider is found, initialize the hint list and update it\n        if (sessionProvider) {\n            var insertHintOnTab,\n                maxCodeHints = PreferencesManager.get(\"maxCodeHints\");\n            if (sessionProvider.insertHintOnTab !== undefined) {\n                insertHintOnTab = sessionProvider.insertHintOnTab;\n            } else {\n                insertHintOnTab = PreferencesManager.get(\"insertHintOnTab\");\n            }\n\n            sessionEditor = editor;\n            hintList = new CodeHintList(sessionEditor, insertHintOnTab, maxCodeHints);\n            hintList.onHighlight(function ($hint, $hintDescContainer) {\n                if (hintList.enableDescription && $hintDescContainer && $hintDescContainer.length) {\n                    // If the current hint provider listening for hint item highlight change\n                    if (sessionProvider.onHighlight) {\n                        sessionProvider.onHighlight($hint, $hintDescContainer);\n                    }\n\n                    // Update the hint description\n                    if (sessionProvider.updateHintDescription) {\n                        sessionProvider.updateHintDescription($hint, $hintDescContainer);\n                    }\n                } else {\n                    if (sessionProvider.onHighlight) {\n                        sessionProvider.onHighlight($hint);\n                    }\n                }\n            });\n            hintList.onSelect(function (hint) {\n                var restart = sessionProvider.insertHint(hint),\n                    previousEditor = sessionEditor;\n                _endSession();\n                if (restart) {\n                    _beginSession(previousEditor);\n                }\n            });\n            hintList.onClose(_endSession);\n\n            _updateHintList();\n        } else {\n            lastChar = null;\n        }\n    };\n\n    /**\n     * Handles keys related to displaying, searching, and navigating the hint list.\n     * This gets called before handleChange.\n     *\n     * TODO: Ideally, we'd get a more semantic event from the editor that told us\n     * what changed so that we could do all of this logic without looking at\n     * key events. Then, the purposes of handleKeyEvent and handleChange could be\n     * combined. Doing this well requires changing CodeMirror.\n     *\n     * @param {Event} jqEvent\n     * @param {Editor} editor\n     * @param {KeyboardEvent} event\n     */\n    function _handleKeydownEvent(jqEvent, editor, event) {\n        keyDownEditor = editor;\n        if (!(event.ctrlKey || event.altKey || event.metaKey) &&\n                (event.keyCode === KeyEvent.DOM_VK_ENTER ||\n                 event.keyCode === KeyEvent.DOM_VK_RETURN ||\n                 event.keyCode === KeyEvent.DOM_VK_TAB)) {\n            lastChar = String.fromCharCode(event.keyCode);\n        }\n    }\n    function _handleKeypressEvent(jqEvent, editor, event) {\n        keyDownEditor = editor;\n\n        // Last inserted character, used later by handleChange\n        lastChar = String.fromCharCode(event.charCode);\n\n        // Pending Text is used in hintList._keydownHook()\n        if (hintList) {\n            hintList.addPendingText(lastChar);\n        }\n    }\n    function _handleKeyupEvent(jqEvent, editor, event) {\n        keyDownEditor = editor;\n        if (_inSession(editor)) {\n          if (event.keyCode === KeyEvent.DOM_VK_HOME || \n                  event.keyCode === KeyEvent.DOM_VK_END) {\n                _endSession();\n            } else if (event.keyCode === KeyEvent.DOM_VK_LEFT ||\n                       event.keyCode === KeyEvent.DOM_VK_RIGHT ||\n                       event.keyCode === KeyEvent.DOM_VK_BACK_SPACE) {\n                // Update the list after a simple navigation.\n                // We do this in \"keyup\" because we want the cursor position to be updated before\n                // we redraw the list.\n                _updateHintList();\n            } else if (event.ctrlKey && event.keyCode === KeyEvent.DOM_VK_SPACE) {\n                _updateHintList(event);\n            }\n        }\n    }\n\n    /**\n     * Handle a selection change event in the editor. If the selection becomes a\n     * multiple selection, end our current session.\n     * @param {BracketsEvent} event\n     * @param {Editor} editor\n     */\n    function _handleCursorActivity(event, editor) {\n        if (_inSession(editor)) {\n            if (editor.getSelections().length > 1) {\n                _endSession();\n            }\n        }\n    }\n\n    /**\n     * Start a new implicit hinting session, or update the existing hint list.\n     * Called by the editor after handleKeyEvent, which is responsible for setting\n     * the lastChar.\n     *\n     * @param {Event} event\n     * @param {Editor} editor\n     * @param {{from: Pos, to: Pos, text: Array, origin: string}} changeList\n     */\n    function _handleChange(event, editor, changeList) {\n        if (lastChar && editor === keyDownEditor) {\n            keyDownEditor = null;\n            if (_inSession(editor)) {\n                var charToRetest = lastChar;\n                _updateHintList();\n\n                // _updateHintList() may end a hinting session and clear lastChar, but a\n                // different provider may want to start a new session with the same character.\n                // So check whether current provider terminates the current hinting\n                // session. If so, then restore lastChar and restart a new session.\n                if (!_inSession(editor)) {\n                    lastChar = charToRetest;\n                    _beginSession(editor);\n                }\n            } else {\n                _beginSession(editor);\n            }\n\n            // Pending Text is used in hintList._keydownHook()\n            if (hintList && changeList[0] && changeList[0].text.length && changeList[0].text[0].length) {\n                var expectedLength = editor.getCursorPos().ch - changeList[0].from.ch,\n                    newText = changeList[0].text[0];\n                // We may get extra text in newText since some features like auto\n                // close braces can append some text automatically.\n                // See https://github.com/adobe/brackets/issues/6345#issuecomment-32548064\n                // as an example of this scenario.\n                if (newText.length > expectedLength) {\n                    // Strip off the extra text before calling removePendingText.\n                    newText = newText.substr(0, expectedLength);\n                }\n                hintList.removePendingText(newText);\n            }\n        }\n    }\n\n    /**\n     * Test whether the provider has an exclusion that is still the same as text after the cursor.\n     *\n     * @param {string} exclusion - Text not to be overwritten when the provider inserts the selected hint.\n     * @param {string} textAfterCursor - Text that is immediately after the cursor position.\n     * @return {boolean} true if the exclusion is not null and is exactly the same as textAfterCursor,\n     * false otherwise.\n     */\n    function hasValidExclusion(exclusion, textAfterCursor) {\n        return (exclusion && exclusion === textAfterCursor);\n    }\n\n    /**\n     *  Test if a hint popup is open.\n     *\n     * @return {boolean} - true if the hints are open, false otherwise.\n     */\n    function isOpen() {\n        return (hintList && hintList.isOpen());\n    }\n\n    /**\n     * Explicitly start a new session. If we have an existing session,\n     * then close the current one and restart a new one.\n     * @param {Editor} editor\n     */\n    function _startNewSession(editor) {\n        if (isOpen()) {\n            return;\n        }\n\n        if (!editor) {\n            editor = EditorManager.getFocusedEditor();\n        }\n        if (editor) {\n            lastChar = null;\n            if (_inSession(editor)) {\n                _endSession();\n            }\n\n            // Begin a new explicit session\n            _beginSession(editor);\n        }\n    }\n\n    /**\n     * Expose CodeHintList for unit testing\n     */\n    function _getCodeHintList() {\n        return hintList;\n    }\n\n    function activeEditorChangeHandler(event, current, previous) {\n        if (current) {\n            current.on(\"editorChange\", _handleChange);\n            current.on(\"keydown\",  _handleKeydownEvent);\n            current.on(\"keypress\", _handleKeypressEvent);\n            current.on(\"keyup\",    _handleKeyupEvent);\n            current.on(\"cursorActivity\", _handleCursorActivity);\n        }\n\n        if (previous) {\n            //Removing all old Handlers\n            previous.off(\"editorChange\", _handleChange);\n            previous.off(\"keydown\",  _handleKeydownEvent);\n            previous.off(\"keypress\", _handleKeypressEvent);\n            previous.off(\"keyup\",    _handleKeyupEvent);\n            previous.off(\"cursorActivity\", _handleCursorActivity);\n        }\n    }\n\n    activeEditorChangeHandler(null, EditorManager.getActiveEditor(), null);\n\n    EditorManager.on(\"activeEditorChange\", activeEditorChangeHandler);\n \n    // Dismiss code hints before executing any command other than showing code hints since the command\n    // may make the current hinting session irrevalent after execution.\n    // For example, when the user hits Ctrl+K to open Quick Doc, it is\n    // pointless to keep the hint list since the user wants to view the Quick Doc\n    CommandManager.on(\"beforeExecuteCommand\", function (event, commandId) {\n        if (commandId !== Commands.SHOW_CODE_HINTS) {\n            _endSession();\n        }\n    });\n\n    CommandManager.register(Strings.CMD_SHOW_CODE_HINTS, Commands.SHOW_CODE_HINTS, _startNewSession);\n\n    exports._getCodeHintList        = _getCodeHintList;\n    exports._removeHintProvider     = _removeHintProvider;\n\n    // Define public API\n    exports.isOpen                  = isOpen;\n    exports.registerHintProvider    = registerHintProvider;\n    exports.hasValidExclusion       = hasValidExclusion;\n});\n"
  },
  {
    "path": "src/editor/Editor.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Editor is a 1-to-1 wrapper for a CodeMirror editor instance. It layers on Brackets-specific\n * functionality and provides APIs that cleanly pass through the bits of CodeMirror that the rest\n * of our codebase may want to interact with. An Editor is always backed by a Document, and stays\n * in sync with its content; because Editor keeps the Document alive, it's important to always\n * destroy() an Editor that's going away so it can release its Document ref.\n *\n * For now, there's a distinction between the \"master\" Editor for a Document - which secretly acts\n * as the Document's internal model of the text state - and the multitude of \"slave\" secondary Editors\n * which, via Document, sync their changes to and from that master.\n *\n * For now, direct access to the underlying CodeMirror object is still possible via `_codeMirror` --\n * but this is considered deprecated and may go away.\n *\n * The Editor object dispatches the following events:\n *    - keydown, keypress, keyup -- When any key event happens in the editor (whether it changes the\n *      text or not). Handlers are passed `(BracketsEvent, Editor, KeyboardEvent)`. The 3nd arg is the\n *      raw DOM event. Note: most listeners will only want to listen for \"keypress\".\n *    - cursorActivity -- When the user moves the cursor or changes the selection, or an edit occurs.\n *      Note: do not listen to this in order to be generally informed of edits--listen to the\n *      \"change\" event on Document instead.\n *    - scroll -- When the editor is scrolled, either by user action or programmatically.\n *    - lostContent -- When the backing Document changes in such a way that this Editor is no longer\n *      able to display accurate text. This occurs if the Document's file is deleted, or in certain\n *      Document->editor syncing edge cases that we do not yet support (the latter cause will\n *      eventually go away).\n *    - optionChange -- Triggered when an option for the editor is changed. The 2nd arg to the listener\n *      is a string containing the editor option that is changing. The 3rd arg, which can be any\n *      data type, is the new value for the editor option.\n *    - beforeDestroy - Triggered before the object is about to dispose of all its internal state data\n *      so that listeners can cache things like scroll pos, etc...\n *\n * The Editor also dispatches \"change\" events internally, but you should listen for those on\n * Documents, not Editors.\n *\n * To listen for events, do something like this: (see EventDispatcher for details on this pattern)\n *     `editorInstance.on(\"eventname\", handler);`\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AnimationUtils     = require(\"utils/AnimationUtils\"),\n        Async              = require(\"utils/Async\"),\n        CodeMirror         = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        LanguageManager    = require(\"language/LanguageManager\"),\n        EventDispatcher    = require(\"utils/EventDispatcher\"),\n        Menus              = require(\"command/Menus\"),\n        PerfUtils          = require(\"utils/PerfUtils\"),\n        PopUpManager       = require(\"widgets/PopUpManager\"),\n        PreferencesManager = require(\"preferences/PreferencesManager\"),\n        Strings            = require(\"strings\"),\n        TextRange          = require(\"document/TextRange\").TextRange,\n        TokenUtils         = require(\"utils/TokenUtils\"),\n        ValidationUtils    = require(\"utils/ValidationUtils\"),\n        HTMLUtils          = require(\"language/HTMLUtils\"),\n        ViewUtils          = require(\"utils/ViewUtils\"),\n        MainViewManager    = require(\"view/MainViewManager\"),\n        _                  = require(\"thirdparty/lodash\");\n\n    /** Editor preferences */\n\n    var CLOSE_BRACKETS      = \"closeBrackets\",\n        CLOSE_TAGS          = \"closeTags\",\n        DRAG_DROP           = \"dragDropText\",\n        HIGHLIGHT_MATCHES   = \"highlightMatches\",\n        LINEWISE_COPY_CUT   = \"lineWiseCopyCut\",\n        SCROLL_PAST_END     = \"scrollPastEnd\",\n        SHOW_CURSOR_SELECT  = \"showCursorWhenSelecting\",\n        SHOW_LINE_NUMBERS   = \"showLineNumbers\",\n        SMART_INDENT        = \"smartIndent\",\n        SOFT_TABS           = \"softTabs\",\n        SPACE_UNITS         = \"spaceUnits\",\n        STYLE_ACTIVE_LINE   = \"styleActiveLine\",\n        TAB_SIZE            = \"tabSize\",\n        UPPERCASE_COLORS    = \"uppercaseColors\",\n        USE_TAB_CHAR        = \"useTabChar\",\n        WORD_WRAP           = \"wordWrap\",\n        AUTO_HIDE_SEARCH    = \"autoHideSearch\",\n        INDENT_LINE_COMMENT   = \"indentLineComment\",\n        INDENT_LINE_COMMENT = \"indentLineComment\",\n        INPUT_STYLE         = \"inputStyle\";\n\n\n    /**\n      * A list of gutter name and priorities currently registered for editors.\n      * The line number gutter is defined as { name: LINE_NUMBER_GUTTER, priority: 100 }\n      * @type {Array.<{name: string, priority: number, languageIds: Array}}\n      */\n    var registeredGutters = [];\n\n    var cmOptions         = {};\n\n    /**\n     * Constants\n     * @type {number}\n     */\n    var MIN_SPACE_UNITS         =  1,\n        MIN_TAB_SIZE            =  1,\n        DEFAULT_SPACE_UNITS     =  4,\n        DEFAULT_TAB_SIZE        =  4,\n        MAX_SPACE_UNITS         = 10,\n        MAX_TAB_SIZE            = 10;\n\n    var LINE_NUMBER_GUTTER = \"CodeMirror-linenumbers\",\n        LINE_NUMBER_GUTTER_PRIORITY     = 100,\n        CODE_FOLDING_GUTTER_PRIORITY    = 1000;\n\n    // Mappings from Brackets preferences to CodeMirror options\n    cmOptions[CLOSE_BRACKETS]     = \"autoCloseBrackets\";\n    cmOptions[CLOSE_TAGS]         = \"autoCloseTags\";\n    cmOptions[DRAG_DROP]          = \"dragDrop\";\n    cmOptions[HIGHLIGHT_MATCHES]  = \"highlightSelectionMatches\";\n    cmOptions[LINEWISE_COPY_CUT]  = \"lineWiseCopyCut\";\n    cmOptions[SCROLL_PAST_END]    = \"scrollPastEnd\";\n    cmOptions[SHOW_CURSOR_SELECT] = \"showCursorWhenSelecting\";\n    cmOptions[SHOW_LINE_NUMBERS]  = \"lineNumbers\";\n    cmOptions[SMART_INDENT]       = \"smartIndent\";\n    cmOptions[SPACE_UNITS]        = \"indentUnit\";\n    cmOptions[STYLE_ACTIVE_LINE]  = \"styleActiveLine\";\n    cmOptions[TAB_SIZE]           = \"tabSize\";\n    cmOptions[USE_TAB_CHAR]       = \"indentWithTabs\";\n    cmOptions[WORD_WRAP]          = \"lineWrapping\";\n    cmOptions[INPUT_STYLE]        = \"inputStyle\";\n\n    PreferencesManager.definePreference(CLOSE_BRACKETS,     \"boolean\", true, {\n        description: Strings.DESCRIPTION_CLOSE_BRACKETS\n    });\n\n    // CodeMirror, html mode, set some tags do not close automatically.\n    // We do not initialize \"dontCloseTags\" because otherwise we would overwrite the default behavior of CodeMirror.\n    PreferencesManager.definePreference(CLOSE_TAGS,         \"object\", { whenOpening: true, whenClosing: true, indentTags: [] }, {\n        description: Strings.DESCRIPTION_CLOSE_TAGS,\n        keys: {\n            dontCloseTags: {\n                type: \"array\",\n                description: Strings.DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\n            },\n            whenOpening: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_CLOSE_TAGS_WHEN_OPENING,\n                initial: true\n            },\n            whenClosing: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING,\n                initial: true\n            },\n            indentTags: {\n                type: \"array\",\n                description: Strings.DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\n            }\n        }\n    });\n    PreferencesManager.definePreference(DRAG_DROP,          \"boolean\", false, {\n        description: Strings.DESCRIPTION_DRAG_DROP_TEXT\n    });\n    PreferencesManager.definePreference(HIGHLIGHT_MATCHES,  \"boolean\", false, {\n        description: Strings.DESCRIPTION_HIGHLIGHT_MATCHES,\n        keys: {\n            showToken: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN,\n                initial: false\n            },\n            wordsOnly: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY,\n                initial: false\n            }\n        }\n    });\n    PreferencesManager.definePreference(LINEWISE_COPY_CUT,  \"boolean\", true, {\n        description: Strings.DESCRIPTION_LINEWISE_COPY_CUT\n    });\n    PreferencesManager.definePreference(SCROLL_PAST_END,    \"boolean\", false, {\n        description: Strings.DESCRIPTION_SCROLL_PAST_END\n    });\n    PreferencesManager.definePreference(SHOW_CURSOR_SELECT, \"boolean\", false, {\n        description: Strings.DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\n    });\n    PreferencesManager.definePreference(SHOW_LINE_NUMBERS,  \"boolean\", true, {\n        description: Strings.DESCRIPTION_SHOW_LINE_NUMBERS\n    });\n    PreferencesManager.definePreference(SMART_INDENT,       \"boolean\", true, {\n        description: Strings.DESCRIPTION_SMART_INDENT\n    });\n    PreferencesManager.definePreference(SOFT_TABS,          \"boolean\", true, {\n        description: Strings.DESCRIPTION_SOFT_TABS\n    });\n    PreferencesManager.definePreference(SPACE_UNITS,        \"number\", DEFAULT_SPACE_UNITS, {\n        validator: _.partialRight(ValidationUtils.isIntegerInRange, MIN_SPACE_UNITS, MAX_SPACE_UNITS),\n        description: Strings.DESCRIPTION_SPACE_UNITS\n    });\n    PreferencesManager.definePreference(STYLE_ACTIVE_LINE,  \"boolean\", false, {\n        description: Strings.DESCRIPTION_STYLE_ACTIVE_LINE\n    });\n    PreferencesManager.definePreference(TAB_SIZE,           \"number\", DEFAULT_TAB_SIZE, {\n        validator: _.partialRight(ValidationUtils.isIntegerInRange, MIN_TAB_SIZE, MAX_TAB_SIZE),\n        description: Strings.DESCRIPTION_TAB_SIZE\n    });\n    PreferencesManager.definePreference(UPPERCASE_COLORS,   \"boolean\", false, {\n        description: Strings.DESCRIPTION_UPPERCASE_COLORS\n    });\n    PreferencesManager.definePreference(USE_TAB_CHAR,       \"boolean\", false, {\n        description: Strings.DESCRIPTION_USE_TAB_CHAR\n    });\n    PreferencesManager.definePreference(WORD_WRAP,          \"boolean\", true, {\n        description: Strings.DESCRIPTION_WORD_WRAP\n    });\n  \n    PreferencesManager.definePreference(AUTO_HIDE_SEARCH,   \"boolean\", true, {\n        description: Strings.DESCRIPTION_SEARCH_AUTOHIDE\n    });\n\n    PreferencesManager.definePreference(INDENT_LINE_COMMENT,  \"boolean\", false, {\n        description: Strings.DESCRIPTION_INDENT_LINE_COMMENT\n    });\n    PreferencesManager.definePreference(INPUT_STYLE,  \"string\", \"textarea\", {\n        description: Strings.DESCRIPTION_INPUT_STYLE\n    });\n\n    var editorOptions = Object.keys(cmOptions);\n\n    /** Editor preferences */\n\n    /**\n     * Guard flag to prevent focus() reentrancy (via blur handlers), even across Editors\n     * @type {boolean}\n     */\n    var _duringFocus = false;\n\n    /**\n     * Constant: ignore upper boundary when centering text\n     * @type {number}\n     */\n    var BOUNDARY_CHECK_NORMAL   = 0,\n        BOUNDARY_IGNORE_TOP     = 1;\n\n    /**\n     * @private\n     * Create a copy of the given CodeMirror position\n     * @param {!CodeMirror.Pos} pos\n     * @return {CodeMirror.Pos}\n     */\n    function _copyPos(pos) {\n        return new CodeMirror.Pos(pos.line, pos.ch);\n    }\n\n    /**\n     * Helper functions to check options.\n     * @param {number} options BOUNDARY_CHECK_NORMAL or BOUNDARY_IGNORE_TOP\n     */\n    function _checkTopBoundary(options) {\n        return (options !== BOUNDARY_IGNORE_TOP);\n    }\n\n    function _checkBottomBoundary(options) {\n        return true;\n    }\n\n    /**\n     * Helper function to build preferences context based on the full path of\n     * the file.\n     *\n     * @param {string} fullPath Full path of the file\n     *\n     * @return {*} A context for the specified file name\n     */\n    function _buildPreferencesContext(fullPath) {\n        return PreferencesManager._buildContext(fullPath,\n            fullPath ? LanguageManager.getLanguageForPath(fullPath).getId() : undefined);\n    }\n\n    /**\n     * List of all current (non-destroy()ed) Editor instances. Needed when changing global preferences\n     * that affect all editors, e.g. tabbing or color scheme settings.\n     * @type {Array.<Editor>}\n     */\n    var _instances = [];\n\n    /**\n     * Creates a new CodeMirror editor instance bound to the given Document. The Document need not have\n     * a \"master\" Editor realized yet, even if makeMasterEditor is false; in that case, the first time\n     * an edit occurs we will automatically ask EditorManager to create a \"master\" editor to render the\n     * Document modifiable.\n     *\n     * ALWAYS call destroy() when you are done with an Editor - otherwise it will leak a Document ref.\n     *\n     * @constructor\n     *\n     * @param {!Document} document\n     * @param {!boolean} makeMasterEditor  If true, this Editor will set itself as the (secret) \"master\"\n     *          Editor for the Document. If false, this Editor will attach to the Document as a \"slave\"/\n     *          secondary editor.\n     * @param {!jQueryObject|DomNode} container  Container to add the editor to.\n     * @param {{startLine: number, endLine: number}=} range If specified, range of lines within the document\n     *          to display in this editor. Inclusive.\n     * @param {!Object} options If specified, contains editor options that can be passed to CodeMirror\n     */\n    function Editor(document, makeMasterEditor, container, range, options) {\n        var self = this;\n\n        var isReadOnly = (options && options.isReadOnly) || !document.editable;\n\n        _instances.push(this);\n\n        // Attach to document: add ref & handlers\n        this.document = document;\n        document.addRef();\n\n        if (container.jquery) {\n            // CodeMirror wants a DOM element, not a jQuery wrapper\n            container = container.get(0);\n        }\n\n        var $container = $(container);\n\n        if (range) {    // attach this first: want range updated before we process a change\n            this._visibleRange = new TextRange(document, range.startLine, range.endLine);\n        }\n\n        // store this-bound version of listeners so we can remove them later\n        this._handleDocumentChange = this._handleDocumentChange.bind(this);\n        this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);\n        this._handleDocumentLanguageChanged = this._handleDocumentLanguageChanged.bind(this);\n        this._doWorkingSetSync = this._doWorkingSetSync.bind(this);\n        document.on(\"change\", this._handleDocumentChange);\n        document.on(\"deleted\", this._handleDocumentDeleted);\n        document.on(\"languageChanged\", this._handleDocumentLanguageChanged);\n        // To sync working sets if the view is for same doc across panes\n        document.on(\"_dirtyFlagChange\", this._doWorkingSetSync);\n\n        var mode = this._getModeFromDocument();\n\n        // (if makeMasterEditor, we attach the Doc back to ourselves below once we're fully initialized)\n\n        this._inlineWidgets = [];\n        this._inlineWidgetQueues = {};\n        this._hideMarks = [];\n        this._lastEditorWidth = null;\n\n        this._$messagePopover = null;\n\n        // To track which pane the editor is being attached to if it's a full editor\n        this._paneId = null;\n\n        // To track the parent editor ( host editor at that time of creation) of an inline editor\n        this._hostEditor = null;\n\n        // Editor supplies some standard keyboard behavior extensions of its own\n        var codeMirrorKeyMap = {\n            \"Tab\": function () { self._handleTabKey(); },\n            \"Shift-Tab\": \"indentLess\",\n\n            \"Left\": function (instance) {\n                self._handleSoftTabNavigation(-1, \"moveH\");\n            },\n            \"Right\": function (instance) {\n                self._handleSoftTabNavigation(1, \"moveH\");\n            },\n            \"Backspace\": function (instance) {\n                self._handleSoftTabNavigation(-1, \"deleteH\");\n            },\n            \"Delete\": function (instance) {\n                self._handleSoftTabNavigation(1, \"deleteH\");\n            },\n            \"Esc\": function (instance) {\n                if (self.getSelections().length > 1) {\n                    CodeMirror.commands.singleSelection(instance);\n                } else {\n                    self.removeAllInlineWidgets();\n                }\n            },\n            \"Home\":      \"goLineLeftSmart\",\n            \"Cmd-Left\":  \"goLineLeftSmart\",\n            \"End\":       \"goLineRight\",\n            \"Cmd-Right\": \"goLineRight\"\n        };\n\n        var currentOptions = this._currentOptions = _.zipObject(\n            editorOptions,\n            _.map(editorOptions, function (prefName) {\n                return self._getOption(prefName);\n            })\n        );\n\n        // When panes are created *after* the showLineNumbers option has been turned off\n        //  we need to apply the show-line-padding class or the text will be juxtaposed\n        //  to the edge of the editor which makes it not easy to read.  The code below to handle\n        //  that the option change only applies the class to panes that have already been created\n        // This line ensures that the class is applied to any editor created after the fact\n        $container.toggleClass(\"show-line-padding\", Boolean(!this._getOption(\"showLineNumbers\")));\n\n        // Create the CodeMirror instance\n        // (note: CodeMirror doesn't actually require using 'new', but jslint complains without it)\n        this._codeMirror = new CodeMirror(container, {\n            autoCloseBrackets           : currentOptions[CLOSE_BRACKETS],\n            autoCloseTags               : currentOptions[CLOSE_TAGS],\n            coverGutterNextToScrollbar  : true,\n            cursorScrollMargin          : 3,\n            dragDrop                    : currentOptions[DRAG_DROP],\n            electricChars               : true,\n            extraKeys                   : codeMirrorKeyMap,\n            highlightSelectionMatches   : currentOptions[HIGHLIGHT_MATCHES],\n            indentUnit                  : currentOptions[USE_TAB_CHAR] ? currentOptions[TAB_SIZE] : currentOptions[SPACE_UNITS],\n            indentWithTabs              : currentOptions[USE_TAB_CHAR],\n            inputStyle                  : currentOptions[INPUT_STYLE],\n            lineNumbers                 : currentOptions[SHOW_LINE_NUMBERS],\n            lineWiseCopyCut             : currentOptions[LINEWISE_COPY_CUT],\n            lineWrapping                : currentOptions[WORD_WRAP],\n            matchBrackets               : { maxScanLineLength: 50000, maxScanLines: 1000 },\n            matchTags                   : { bothTags: true },\n            scrollPastEnd               : !range && currentOptions[SCROLL_PAST_END],\n            showCursorWhenSelecting     : currentOptions[SHOW_CURSOR_SELECT],\n            smartIndent                 : currentOptions[SMART_INDENT],\n            styleActiveLine             : currentOptions[STYLE_ACTIVE_LINE],\n            tabSize                     : currentOptions[TAB_SIZE],\n            readOnly                    : isReadOnly\n        });\n\n        // Can't get CodeMirror's focused state without searching for\n        // CodeMirror-focused. Instead, track focus via onFocus and onBlur\n        // options and track state with this._focused\n        this._focused = false;\n\n        this._installEditorListeners();\n\n        this._renderGutters();\n\n        this.on(\"cursorActivity\", function (event, editor) {\n            self._handleCursorActivity(event);\n        });\n        this.on(\"keypress\", function (event, editor, domEvent) {\n            self._handleKeypressEvents(domEvent);\n        });\n        this.on(\"change\", function (event, editor, changeList) {\n            self._handleEditorChange(changeList);\n        });\n        this.on(\"focus\", function (event, editor) {\n            if (self._hostEditor) {\n                // Mark the host editor as the master editor for the hosting document\n                self._hostEditor.document._toggleMasterEditor(self._hostEditor);\n            } else {\n                // Set this full editor as master editor for the document\n                self.document._toggleMasterEditor(self);\n            }\n        });\n\n        // Set code-coloring mode BEFORE populating with text, to avoid a flash of uncolored text\n        this._codeMirror.setOption(\"mode\", mode);\n\n        // Initially populate with text. This will send a spurious change event, so need to make\n        // sure this is understood as a 'sync from document' case, not a genuine edit\n        this._duringSync = true;\n        this._resetText(document.getText());\n        this._duringSync = false;\n\n        if (range) {\n            this._updateHiddenLines();\n            this.setCursorPos(range.startLine, 0);\n        }\n\n        // Now that we're fully initialized, we can point the document back at us if needed\n        if (makeMasterEditor) {\n            document._makeEditable(this);\n        }\n\n        // Add scrollTop property to this object for the scroll shadow code to use\n        Object.defineProperty(this, \"scrollTop\", {\n            get: function () {\n                return this._codeMirror.getScrollInfo().top;\n            }\n        });\n\n        // Add an $el getter for Pane Views\n        Object.defineProperty(this,  \"$el\", {\n            get: function () {\n                return $(this.getRootElement());\n            }\n        });\n    }\n\n    EventDispatcher.makeEventDispatcher(Editor.prototype);\n    EventDispatcher.markDeprecated(Editor.prototype, \"keyEvent\", \"'keydown/press/up'\");\n\n    Editor.prototype.markPaneId = function (paneId) {\n        this._paneId = paneId;\n\n        // Also add this to the pool of full editors\n        this.document._associateEditor(this);\n\n        // In case this Editor is initialized not as the first full editor for the document\n        // and the document is already dirty and present in another working set, make sure\n        // to add this documents to the new panes working set.\n        this._doWorkingSetSync(null, this.document);\n    };\n\n    Editor.prototype._doWorkingSetSync = function (event, doc) {\n        if (doc === this.document && this._paneId && this.document.isDirty) {\n            MainViewManager.addToWorkingSet(this._paneId, this.document.file, -1, false);\n        }\n    };\n\n    /**\n     * Removes this editor from the DOM and detaches from the Document. If this is the \"master\"\n     * Editor that is secretly providing the Document's backing state, then the Document reverts to\n     * a read-only string-backed mode.\n     */\n    Editor.prototype.destroy = function () {\n        this.trigger(\"beforeDestroy\", this);\n\n        // CodeMirror docs for getWrapperElement() say all you have to do is \"Remove this from your\n        // tree to delete an editor instance.\"\n        $(this.getRootElement()).remove();\n\n        _instances.splice(_instances.indexOf(this), 1);\n\n        // Disconnect from Document\n        this.document.releaseRef();\n        this.document.off(\"change\", this._handleDocumentChange);\n        this.document.off(\"deleted\", this._handleDocumentDeleted);\n        this.document.off(\"languageChanged\", this._handleDocumentLanguageChanged);\n        this.document.off(\"_dirtyFlagChange\", this._doWorkingSetSync);\n\n        if (this._visibleRange) {   // TextRange also refs the Document\n            this._visibleRange.dispose();\n        }\n\n        // If we're the Document's master editor, disconnecting from it has special meaning\n        if (this.document._masterEditor === this) {\n            this.document._makeNonEditable();\n        } else {\n            this.document._disassociateEditor(this);\n        }\n\n        // Destroying us destroys any inline widgets we're hosting. Make sure their closeCallbacks\n        // run, at least, since they may also need to release Document refs\n        var self = this;\n        this._inlineWidgets.forEach(function (inlineWidget) {\n            self._removeInlineWidgetInternal(inlineWidget);\n        });\n    };\n\n    /**\n     * @private\n     * Handle any cursor movement in editor, including selecting and unselecting text.\n     * @param {!Event} event\n     */\n    Editor.prototype._handleCursorActivity = function (event) {\n        this._updateStyleActiveLine();\n    };\n\n    /**\n     * @private\n     * Removes any whitespace after one of ]{}) to prevent trailing whitespace when auto-indenting\n     */\n    Editor.prototype._handleWhitespaceForElectricChars = function () {\n        var self        = this,\n            instance    = this._codeMirror,\n            selections,\n            lineStr;\n\n        selections = this.getSelections().map(function (sel) {\n            lineStr = instance.getLine(sel.end.line);\n\n            if (lineStr && !/\\S/.test(lineStr)) {\n                // if the line is all whitespace, move the cursor to the end of the line\n                // before indenting so that embedded whitespace such as indents are not\n                // orphaned to the right of the electric char being inserted\n                sel.end.ch = self.document.getLine(sel.end.line).length;\n            }\n            return sel;\n        });\n        this.setSelections(selections);\n    };\n\n    /**\n     * @private\n     * Handle CodeMirror key events.\n     * @param {!Event} event\n     */\n    Editor.prototype._handleKeypressEvents = function (event) {\n        var keyStr = String.fromCharCode(event.which || event.keyCode);\n\n        if (/[\\]\\{\\}\\)]/.test(keyStr)) {\n            this._handleWhitespaceForElectricChars();\n        }\n    };\n\n    /**\n     * @private\n     * Helper function for `_handleTabKey()` (case 2) - see comment in that function.\n     * @param {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>} selections\n     *     The selections to indent.\n     */\n    Editor.prototype._addIndentAtEachSelection = function (selections) {\n        var instance = this._codeMirror,\n            usingTabs = instance.getOption(\"indentWithTabs\"),\n            indentUnit = instance.getOption(\"indentUnit\"),\n            edits = [];\n\n        _.each(selections, function (sel) {\n            var indentStr = \"\", i, numSpaces;\n            if (usingTabs) {\n                indentStr = \"\\t\";\n            } else {\n                numSpaces = indentUnit - (sel.start.ch % indentUnit);\n                for (i = 0; i < numSpaces; i++) {\n                    indentStr += \" \";\n                }\n            }\n            edits.push({edit: {text: indentStr, start: sel.start}});\n        });\n\n        this.document.doMultipleEdits(edits);\n    };\n\n    /**\n     * @private\n     * Helper function for `_handleTabKey()` (case 3) - see comment in that function.\n     * @param {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>} selections\n     *     The selections to indent.\n     */\n    Editor.prototype._autoIndentEachSelection = function (selections) {\n        // Capture all the line lengths, so we can tell if anything changed.\n        // Note that this function should only be called if all selections are within a single line.\n        var instance = this._codeMirror,\n            lineLengths = {};\n        _.each(selections, function (sel) {\n            lineLengths[sel.start.line] = instance.getLine(sel.start.line).length;\n        });\n\n        // First, try to do a smart indent on all selections.\n        CodeMirror.commands.indentAuto(instance);\n\n        // If there were no code or selection changes, then indent each selection one more indent.\n        var changed = false,\n            newSelections = this.getSelections();\n        if (newSelections.length === selections.length) {\n            _.each(selections, function (sel, index) {\n                var newSel = newSelections[index];\n                if (CodeMirror.cmpPos(sel.start, newSel.start) !== 0 ||\n                        CodeMirror.cmpPos(sel.end, newSel.end) !== 0 ||\n                        instance.getLine(sel.start.line).length !== lineLengths[sel.start.line]) {\n                    changed = true;\n                    // Bail - we don't need to look any further once we've found a change.\n                    return false;\n                }\n            });\n        } else {\n            changed = true;\n        }\n\n        if (!changed) {\n            CodeMirror.commands.indentMore(instance);\n        }\n    };\n\n    /**\n     * @private\n     * Handle Tab key press.\n     */\n    Editor.prototype._handleTabKey = function () {\n        // Tab key handling is done as follows:\n        // 1. If any of the selections are multiline, just add one indent level to the\n        //    beginning of all lines that intersect any selection.\n        // 2. Otherwise, if any of the selections is a cursor or single-line range that\n        //    ends at or after the first non-whitespace character in a line:\n        //    - if indentation is set to tabs, just insert a hard tab before each selection.\n        //    - if indentation is set to spaces, insert the appropriate number of spaces before\n        //      each selection to get to its next soft tab stop.\n        // 3. Otherwise (all selections are cursors or single-line, and are in the whitespace\n        //    before their respective lines), try to autoindent each line based on the mode.\n        //    If none of the cursors moved and no space was added, then add one indent level\n        //    to the beginning of all lines.\n\n        // Note that in case 2, we do the \"dumb\" insertion even if the cursor is immediately\n        // before the first non-whitespace character in a line. It might seem more convenient\n        // to do autoindent in that case. However, the problem is if that line is already\n        // indented past its \"proper\" location. In that case, we don't want Tab to\n        // *outdent* the line. If we had more control over the autoindent algorithm or\n        // implemented it ourselves, we could handle that case separately.\n\n        var instance = this._codeMirror,\n            selectionType = \"indentAuto\",\n            selections = this.getSelections();\n\n        _.each(selections, function (sel) {\n            if (sel.start.line !== sel.end.line) {\n                // Case 1 - we found a multiline selection. We can bail as soon as we find one of these.\n                selectionType = \"indentAtBeginning\";\n                return false;\n            } else if (sel.end.ch > 0 && sel.end.ch >= instance.getLine(sel.end.line).search(/\\S/)) {\n                // Case 2 - we found a selection that ends at or after the first non-whitespace\n                // character on the line. We need to keep looking in case we find a later multiline\n                // selection though.\n                selectionType = \"indentAtSelection\";\n            }\n        });\n\n        switch (selectionType) {\n        case \"indentAtBeginning\":\n            // Case 1\n            CodeMirror.commands.indentMore(instance);\n            break;\n\n        case \"indentAtSelection\":\n            // Case 2\n            this._addIndentAtEachSelection(selections);\n            break;\n\n        case \"indentAuto\":\n            // Case 3\n            this._autoIndentEachSelection(selections);\n            break;\n        }\n    };\n\n    /**\n     * @private\n     * Handle left arrow, right arrow, backspace and delete keys when soft tabs are used.\n     * @param {number} direction Direction of movement: 1 for forward, -1 for backward\n     * @param {string} functionName name of the CodeMirror function to call if we handle the key\n     */\n    Editor.prototype._handleSoftTabNavigation = function (direction, functionName) {\n        var instance = this._codeMirror,\n            overallJump = null;\n\n        if (!instance.getOption(\"indentWithTabs\") && PreferencesManager.get(SOFT_TABS)) {\n            var indentUnit = instance.getOption(\"indentUnit\");\n\n            _.each(this.getSelections(), function (sel) {\n                if (CodeMirror.cmpPos(sel.start, sel.end) !== 0) {\n                    // This is a range - it will just collapse/be deleted regardless of the jump we set, so\n                    // we can just ignore it and continue. (We don't want to return false in this case since\n                    // we want to keep looking at other ranges.)\n                    return;\n                }\n\n                var cursor = sel.start,\n                    jump   = (indentUnit === 0) ? 1 : cursor.ch % indentUnit,\n                    line   = instance.getLine(cursor.line);\n\n                // Don't do any soft tab handling if there are non-whitespace characters before the cursor in\n                // any of the selections.\n                if (line.substr(0, cursor.ch).search(/\\S/) !== -1) {\n                    jump = null;\n                } else if (direction === 1) { // right\n                    if (indentUnit) {\n                        jump = indentUnit - jump;\n                    }\n\n                    // Don't jump if it would take us past the end of the line, or if there are\n                    // non-whitespace characters within the jump distance.\n                    if (cursor.ch + jump > line.length || line.substr(cursor.ch, jump).search(/\\S/) !== -1) {\n                        jump = null;\n                    }\n                } else { // left\n                    // If we are on the tab boundary, jump by the full amount,\n                    // but not beyond the start of the line.\n                    if (jump === 0) {\n                        jump = indentUnit;\n                    }\n                    if (cursor.ch - jump < 0) {\n                        jump = null;\n                    } else {\n                        // We're moving left, so negate the jump.\n                        jump = -jump;\n                    }\n                }\n\n                // Did we calculate a jump, and is this jump value either the first one or\n                // consistent with all the other jumps? If so, we're good. Otherwise, bail\n                // out of the foreach, since as soon as we hit an inconsistent jump we don't\n                // have to look any further.\n                if (jump !== null &&\n                        (overallJump === null || overallJump === jump)) {\n                    overallJump = jump;\n                } else {\n                    overallJump = null;\n                    return false;\n                }\n            });\n        }\n\n        if (overallJump === null) {\n            // Just do the default move, which is one char in the given direction.\n            overallJump = direction;\n        }\n        instance[functionName](overallJump, \"char\");\n    };\n\n    /**\n     * Determine the mode to use from the document's language\n     * Uses \"text/plain\" if the language does not define a mode\n     * @return {string} The mode to use\n     */\n    Editor.prototype._getModeFromDocument = function () {\n        // We'd like undefined/null/\"\" to mean plain text mode. CodeMirror defaults to plaintext for any\n        // unrecognized mode, but it complains on the console in that fallback case: so, convert\n        // here so we're always explicit, avoiding console noise.\n        return this.document.getLanguage().getMode() || \"text/plain\";\n    };\n\n\n    /**\n     * Selects all text and maintains the current scroll position.\n     */\n    Editor.prototype.selectAllNoScroll = function () {\n        var cm = this._codeMirror,\n            info = this._codeMirror.getScrollInfo();\n\n        // Note that we do not have to check for the visible range here. This\n        // concern is handled internally by code mirror.\n        cm.operation(function () {\n            cm.scrollTo(info.left, info.top);\n            cm.execCommand(\"selectAll\");\n        });\n    };\n\n    /**\n     * @return {boolean} True if editor is not showing the entire text of the document (i.e. an inline editor)\n     */\n    Editor.prototype.isTextSubset = function () {\n        return Boolean(this._visibleRange);\n    };\n\n    /**\n     * Ensures that the lines that are actually hidden in the inline editor correspond to\n     * the desired visible range.\n     */\n    Editor.prototype._updateHiddenLines = function () {\n        if (this._visibleRange) {\n            var cm = this._codeMirror,\n                self = this;\n            cm.operation(function () {\n                self._hideMarks.forEach(function (mark) {\n                    if (mark) {\n                        mark.clear();\n                    }\n                });\n                self._hideMarks = [];\n                self._hideMarks.push(self._hideLines(0, self._visibleRange.startLine));\n                self._hideMarks.push(self._hideLines(self._visibleRange.endLine + 1, self.lineCount()));\n            });\n        }\n    };\n\n    Editor.prototype._applyChanges = function (changeList) {\n        // _visibleRange has already updated via its own Document listener. See if this change caused\n        // it to lose sync. If so, our whole view is stale - signal our owner to close us.\n        if (this._visibleRange) {\n            if (this._visibleRange.startLine === null || this._visibleRange.endLine === null) {\n                this.trigger(\"lostContent\");\n                return;\n            }\n        }\n\n        // Apply text changes to CodeMirror editor\n        var cm = this._codeMirror;\n        cm.operation(function () {\n            var change, newText, i;\n            for (i = 0; i < changeList.length; i++) {\n                change = changeList[i];\n                newText = change.text.join('\\n');\n                if (!change.from || !change.to) {\n                    if (change.from || change.to) {\n                        console.error(\"Change record received with only one end undefined--replacing entire text\");\n                    }\n                    cm.setValue(newText);\n                } else {\n                    cm.replaceRange(newText, change.from, change.to, change.origin);\n                }\n\n            }\n        });\n\n        // The update above may have inserted new lines - must hide any that fall outside our range\n        this._updateHiddenLines();\n    };\n\n    /**\n     * Responds to changes in the CodeMirror editor's text, syncing the changes to the Document.\n     * There are several cases where we want to ignore a CodeMirror change:\n     *  - if we're the master editor, editor changes can be ignored because Document is already listening\n     *    for our changes\n     *  - if we're a secondary editor, editor changes should be ignored if they were caused by us reacting\n     *    to a Document change\n     */\n    Editor.prototype._handleEditorChange = function (changeList) {\n        // we're currently syncing from the Document, so don't echo back TO the Document\n        if (this._duringSync) {\n            return;\n        }\n\n        // Secondary editor: force creation of \"master\" editor backing the model, if doesn't exist yet\n        this.document._ensureMasterEditor();\n\n        if (this.document._masterEditor !== this) {\n            // Secondary editor:\n            // we're not the ground truth; if we got here, this was a real editor change (not a\n            // sync from the real ground truth), so we need to sync from us into the document\n            // (which will directly push the change into the master editor).\n            // FUTURE: Technically we should add a replaceRange() method to Document and go through\n            // that instead of talking to its master editor directly. It's not clear yet exactly\n            // what the right Document API would be, though.\n            this._duringSync = true;\n            this.document._masterEditor._applyChanges(changeList);\n            this._duringSync = false;\n\n            // Update which lines are hidden inside our editor, since we're not going to go through\n            // _applyChanges() in our own editor.\n            this._updateHiddenLines();\n        }\n        // Else, Master editor:\n        // we're the ground truth; nothing else to do, since Document listens directly to us\n        // note: this change might have been a real edit made by the user, OR this might have\n        // been a change synced from another editor\n\n        // The \"editorChange\" event is mostly for the use of the CodeHintManager.\n        // It differs from the normal \"change\" event, that it's actually publicly usable,\n        // whereas the \"change\" event should be listened to on the document. Also the\n        // Editor dispatches a change event before this event is dispatched, because\n        // CodeHintManager needs to hook in here when other things are already done.\n        this.trigger(\"editorChange\", this, changeList);\n    };\n\n    /**\n     * Responds to changes in the Document's text, syncing the changes into our CodeMirror instance.\n     * There are several cases where we want to ignore a Document change:\n     *  - if we're the master editor, Document changes should be ignored because we already have the right\n     *    text (either the change originated with us, or it has already been set into us by Document)\n     *  - if we're a secondary editor, Document changes should be ignored if they were caused by us sending\n     *    the document an editor change that originated with us\n     */\n    Editor.prototype._handleDocumentChange = function (event, doc, changeList) {\n        // we're currently syncing to the Document, so don't echo back FROM the Document\n        if (this._duringSync) {\n            return;\n        }\n\n        if (this.document._masterEditor !== this) {\n            // Secondary editor:\n            // we're not the ground truth; and if we got here, this was a Document change that\n            // didn't come from us (e.g. a sync from another editor, a direct programmatic change\n            // to the document, or a sync from external disk changes)... so sync from the Document\n            this._duringSync = true;\n            this._applyChanges(changeList);\n            this._duringSync = false;\n        }\n        // Else, Master editor:\n        // we're the ground truth; nothing to do since Document change is just echoing our\n        // editor changes\n    };\n\n    /**\n     * Responds to the Document's underlying file being deleted. The Document is now basically dead,\n     * so we must close.\n     */\n    Editor.prototype._handleDocumentDeleted = function (event) {\n        // Pass the delete event along as the cause (needed in MultiRangeInlineEditor)\n        this.trigger(\"lostContent\", event);\n    };\n\n    /**\n     * Responds to language changes, for instance when the file extension is changed.\n     */\n    Editor.prototype._handleDocumentLanguageChanged = function (event) {\n        this._codeMirror.setOption(\"mode\", this._getModeFromDocument());\n    };\n\n\n    /**\n     * Install event handlers on the CodeMirror instance, translating them into\n     * jQuery events on the Editor instance.\n     */\n    Editor.prototype._installEditorListeners = function () {\n        var self = this;\n\n        // Redispatch these CodeMirror key events as Editor events\n        function _onKeyEvent(instance, event) {\n            self.trigger(\"keyEvent\", self, event);  // deprecated\n            self.trigger(event.type, self, event);\n            return event.defaultPrevented;   // false tells CodeMirror we didn't eat the event\n        }\n        this._codeMirror.on(\"keydown\",  _onKeyEvent);\n        this._codeMirror.on(\"keypress\", _onKeyEvent);\n        this._codeMirror.on(\"keyup\",    _onKeyEvent);\n\n        // FUTURE: if this list grows longer, consider making this a more generic mapping\n        // NOTE: change is a \"private\" event--others shouldn't listen to it on Editor, only on\n        // Document\n        // Also, note that we use the new \"changes\" event in v4, which provides an array of\n        // change objects. Our own event is still called just \"change\".\n        this._codeMirror.on(\"changes\", function (instance, changeList) {\n            self.trigger(\"change\", self, changeList);\n        });\n        this._codeMirror.on(\"beforeChange\", function (instance, changeObj) {\n            self.trigger(\"beforeChange\", self, changeObj);\n        });\n        this._codeMirror.on(\"cursorActivity\", function (instance) {\n            self.trigger(\"cursorActivity\", self);\n        });\n        this._codeMirror.on(\"beforeSelectionChange\", function (instance, selectionObj) {\n            self.trigger(\"beforeSelectionChange\", selectionObj);\n        });\n        this._codeMirror.on(\"scroll\", function (instance) {\n            // If this editor is visible, close all dropdowns on scroll.\n            // (We don't want to do this if we're just scrolling in a non-visible editor\n            // in response to some document change event.)\n            if (self.isFullyVisible()) {\n                Menus.closeAll();\n            }\n\n            self.trigger(\"scroll\", self);\n        });\n\n        // Convert CodeMirror onFocus events to EditorManager activeEditorChanged\n        this._codeMirror.on(\"focus\", function () {\n            self._focused = true;\n            self.trigger(\"focus\", self);\n            \n        });\n\n        this._codeMirror.on(\"blur\", function () {\n            self._focused = false;\n            self.trigger(\"blur\", self);\n        });\n\n        this._codeMirror.on(\"update\", function (instance) {\n            self.trigger(\"update\", self);\n        });\n        this._codeMirror.on(\"overwriteToggle\", function (instance, newstate) {\n            self.trigger(\"overwriteToggle\", self, newstate);\n        });\n\n        // Disable CodeMirror's drop handling if a file/folder is dropped\n        this._codeMirror.on(\"drop\", function (cm, event) {\n            var files = event.dataTransfer.files;\n            if (files && files.length) {\n                event.preventDefault();\n            }\n        });\n        // For word wrap. Code adapted from https://codemirror.net/demo/indentwrap.html#\n        this._codeMirror.on(\"renderLine\", function (cm, line, elt) {\n            var charWidth = self._codeMirror.defaultCharWidth();\n            var off = CodeMirror.countColumn(line.text, null, cm.getOption(\"tabSize\")) * charWidth;\n            elt.style.textIndent = \"-\" + off + \"px\";\n            elt.style.paddingLeft = off + \"px\";\n        });\n    };\n\n    /**\n     * Sets the contents of the editor, clears the undo/redo history and marks the document clean. Dispatches a change event.\n     * Semi-private: only Document should call this.\n     * @param {!string} text\n     */\n    Editor.prototype._resetText = function (text) {\n        var currentText = this._codeMirror.getValue();\n\n        // compare with ignoring line-endings, issue #11826\n        var textLF = text ? text.replace(/(\\r\\n|\\r|\\n)/g, \"\\n\") : null;\n        var currentTextLF = currentText ? currentText.replace(/(\\r\\n|\\r|\\n)/g, \"\\n\") : null;\n        if (textLF === currentTextLF) {\n            // there's nothing to reset\n            return;\n        }\n\n        var perfTimerName = PerfUtils.markStart(\"Editor._resetText()\\t\" + (!this.document || this.document.file.fullPath));\n\n        var cursorPos = this.getCursorPos(),\n            scrollPos = this.getScrollPos();\n\n        // This *will* fire a change event, but we clear the undo immediately afterward\n        this._codeMirror.setValue(text);\n        this._codeMirror.refresh();\n\n        // Make sure we can't undo back to the empty state before setValue(), and mark\n        // the document clean.\n        this._codeMirror.clearHistory();\n        this._codeMirror.markClean();\n\n        // restore cursor and scroll positions\n        this.setCursorPos(cursorPos);\n        this.setScrollPos(scrollPos.x, scrollPos.y);\n\n        PerfUtils.addMeasurement(perfTimerName);\n    };\n\n   /**\n    * Gets the file associated with this editor\n    * This is a required Pane-View interface method\n    * @return {!File} the file associated with this editor\n    */\n    Editor.prototype.getFile = function () {\n        return this.document.file;\n    };\n\n    /**\n     * Gets the current cursor position within the editor.\n     * @param {boolean} expandTabs  If true, return the actual visual column number instead of the character offset in\n     *      the \"ch\" property.\n     * @param {?string} which Optional string indicating which end of the\n     *  selection to return. It may be \"start\", \"end\", \"head\" (the side of the\n     *  selection that moves when you press shift+arrow), or \"anchor\" (the\n     *  fixed side of the selection). Omitting the argument is the same as\n     *  passing \"head\". A {line, ch} object will be returned.)\n     * @return {!{line:number, ch:number}}\n     */\n    Editor.prototype.getCursorPos = function (expandTabs, which) {\n        // Translate \"start\" and \"end\" to the official CM names (it actually\n        // supports them as-is, but that isn't documented and we don't want to\n        // rely on it).\n        if (which === \"start\") {\n            which = \"from\";\n        } else if (which === \"end\") {\n            which = \"to\";\n        }\n        var cursor = _copyPos(this._codeMirror.getCursor(which));\n\n        if (expandTabs) {\n            cursor.ch = this.getColOffset(cursor);\n        }\n        return cursor;\n    };\n\n    /**\n     * Returns the display column (zero-based) for a given string-based pos. Differs from pos.ch only\n     * when the line contains preceding \\t chars. Result depends on the current tab size setting.\n     * @param {!{line:number, ch:number}} pos\n     * @return {number}\n     */\n    Editor.prototype.getColOffset = function (pos) {\n        var line    = this._codeMirror.getRange({line: pos.line, ch: 0}, pos),\n            tabSize = null,\n            column  = 0,\n            i;\n\n        for (i = 0; i < line.length; i++) {\n            if (line[i] === '\\t') {\n                if (tabSize === null) {\n                    tabSize = Editor.getTabSize();\n                }\n                if (tabSize > 0) {\n                    column += (tabSize - (column % tabSize));\n                }\n            } else {\n                column++;\n            }\n        }\n        return column;\n    };\n\n    /**\n     * Returns the string-based pos for a given display column (zero-based) in given line. Differs from column\n     * only when the line contains preceding \\t chars. Result depends on the current tab size setting.\n     * @param {number} lineNum Line number\n     * @param {number} column Display column number\n     * @return {number}\n     */\n    Editor.prototype.getCharIndexForColumn = function (lineNum, column) {\n        var line    = this._codeMirror.getLine(lineNum),\n            tabSize = null,\n            iCol    = 0,\n            i;\n\n        for (i = 0; iCol < column; i++) {\n            if (line[i] === '\\t') {\n                if (tabSize === null) {\n                    tabSize = Editor.getTabSize();\n                }\n                if (tabSize > 0) {\n                    iCol += (tabSize - (iCol % tabSize));\n                }\n            } else {\n                iCol++;\n            }\n        }\n        return i;\n    };\n\n    /**\n     * Sets the cursor position within the editor. Removes any selection.\n     * @param {number} line  The 0 based line number.\n     * @param {number} ch  The 0 based character position; treated as 0 if unspecified.\n     * @param {boolean=} center  True if the view should be centered on the new cursor position.\n     * @param {boolean=} expandTabs  If true, use the actual visual column number instead of the character offset as\n     *      the \"ch\" parameter.\n     */\n    Editor.prototype.setCursorPos = function (line, ch, center, expandTabs) {\n        if (expandTabs) {\n            ch = this.getColOffset({line: line, ch: ch});\n        }\n        this._codeMirror.setCursor(line, ch);\n        if (center) {\n            this.centerOnCursor();\n        }\n    };\n\n    /**\n     * Set the editor size in pixels or percentage\n     * @param {(number|string)} width\n     * @param {(number|string)} height\n     */\n    Editor.prototype.setSize = function (width, height) {\n        this._codeMirror.setSize(width, height);\n    };\n\n    /** @const */\n    var CENTERING_MARGIN = 0.15;\n\n    /**\n     * Scrolls the editor viewport to vertically center the line with the cursor,\n     * but only if the cursor is currently near the edges of the viewport or\n     * entirely outside the viewport.\n     *\n     * This does not alter the horizontal scroll position.\n     *\n     * @param {number} centerOptions Option value, or 0 for no options; one of the BOUNDARY_* constants above.\n     */\n    Editor.prototype.centerOnCursor = function (centerOptions) {\n        var $scrollerElement = $(this.getScrollerElement());\n        var editorHeight = $scrollerElement.height();\n\n        // we need to make adjustments for the statusbar's padding on the bottom and the menu bar on top.\n        var statusBarHeight = $scrollerElement.outerHeight() - editorHeight;\n        var menuBarHeight = $scrollerElement.offset().top;\n\n        var documentCursorPosition = this._codeMirror.cursorCoords(null, \"local\").bottom;\n        var screenCursorPosition = this._codeMirror.cursorCoords(null, \"page\").bottom - menuBarHeight;\n\n        // If the cursor is already reasonably centered, we won't\n        // make any change. \"Reasonably centered\" is defined as\n        // not being within CENTERING_MARGIN of the top or bottom\n        // of the editor (where CENTERING_MARGIN is a percentage\n        // of the editor height).\n        // For finding the first item (i.e. find while typing), do\n        // not center if hit is in first half of screen because this\n        // appears to be an unnecesary scroll.\n        if ((_checkTopBoundary(centerOptions) && (screenCursorPosition < editorHeight * CENTERING_MARGIN)) ||\n                (_checkBottomBoundary(centerOptions) && (screenCursorPosition > editorHeight * (1 - CENTERING_MARGIN)))) {\n\n            var pos = documentCursorPosition - editorHeight / 2 + statusBarHeight;\n            var info = this._codeMirror.getScrollInfo();\n            pos = Math.min(Math.max(pos, 0), (info.height - info.clientHeight));\n            this.setScrollPos(null, pos);\n        }\n    };\n\n    /**\n     * Given a position, returns its index within the text (assuming \\n newlines)\n     * @param {!{line:number, ch:number}}\n     * @return {number}\n     */\n    Editor.prototype.indexFromPos = function (coords) {\n        return this._codeMirror.indexFromPos(coords);\n    };\n\n    Editor.prototype.posFromIndex = function (index) {\n        return this._codeMirror.posFromIndex(index);\n    };\n\n    /**\n     * Returns true if pos is between start and end (INclusive at start; EXclusive at end by default,\n     * but overridable via the endInclusive flag).\n     * @param {{line:number, ch:number}} pos\n     * @param {{line:number, ch:number}} start\n     * @param {{line:number, ch:number}} end\n     * @param {boolean} endInclusive\n     *\n     */\n    Editor.prototype.posWithinRange = function (pos, start, end, endInclusive) {\n        if (start.line <= pos.line && end.line >= pos.line) {\n            if (endInclusive) {\n                return (start.line < pos.line || start.ch <= pos.ch) &&  // inclusive\n                    (end.line > pos.line   || end.ch >= pos.ch);      // inclusive\n            } else {\n                return (start.line < pos.line || start.ch <= pos.ch) &&  // inclusive\n                    (end.line > pos.line   || end.ch > pos.ch);       // exclusive\n            }\n\n        }\n        return false;\n    };\n\n    /**\n     * @return {boolean} True if there's a text selection; false if there's just an insertion point\n     */\n    Editor.prototype.hasSelection = function () {\n        return this._codeMirror.somethingSelected();\n    };\n\n    /**\n     * @private\n     * Takes an anchor/head pair and returns a start/end pair where the start is guaranteed to be <= end, and a \"reversed\" flag indicating\n     * if the head is before the anchor.\n     * @param {!{line: number, ch: number}} anchorPos\n     * @param {!{line: number, ch: number}} headPos\n     * @return {!{start:{line:number, ch:number}, end:{line:number, ch:number}}, reversed:boolean} the normalized range with start <= end\n     */\n    function _normalizeRange(anchorPos, headPos) {\n        if (headPos.line < anchorPos.line || (headPos.line === anchorPos.line && headPos.ch < anchorPos.ch)) {\n            return {start: _copyPos(headPos), end: _copyPos(anchorPos), reversed: true};\n        } else {\n            return {start: _copyPos(anchorPos), end: _copyPos(headPos), reversed: false};\n        }\n    }\n\n    /**\n     * Gets the current selection; if there is more than one selection, returns the primary selection\n     * (generally the last one made). Start is inclusive, end is exclusive. If there is no selection,\n     * returns the current cursor position as both the start and end of the range (i.e. a selection\n     * of length zero). If `reversed` is set, then the head of the selection (the end of the selection\n     * that would be changed if the user extended the selection) is before the anchor.\n     * @return {!{start:{line:number, ch:number}, end:{line:number, ch:number}}, reversed:boolean}\n     */\n    Editor.prototype.getSelection = function () {\n        return _normalizeRange(this.getCursorPos(false, \"anchor\"), this.getCursorPos(false, \"head\"));\n    };\n\n    /**\n     * Returns an array of current selections, nonoverlapping and sorted in document order.\n     * Each selection is a start/end pair, with the start guaranteed to come before the end.\n     * Cursors are represented as a range whose start is equal to the end.\n     * If `reversed` is set, then the head of the selection\n     * (the end of the selection that would be changed if the user extended the selection)\n     * is before the anchor.\n     * If `primary` is set, then that selection is the primary selection.\n     * @return {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>}\n     */\n    Editor.prototype.getSelections = function () {\n        var primarySel = this.getSelection();\n        return _.map(this._codeMirror.listSelections(), function (sel) {\n            var result = _normalizeRange(sel.anchor, sel.head);\n            if (result.start.line === primarySel.start.line && result.start.ch === primarySel.start.ch &&\n                    result.end.line === primarySel.end.line && result.end.ch === primarySel.end.ch) {\n                result.primary = true;\n            } else {\n                result.primary = false;\n            }\n            return result;\n        });\n    };\n\n    /**\n     * Takes the given selections, and expands each selection so it encompasses whole lines. Merges\n     * adjacent line selections together. Keeps track of each original selection associated with a given\n     * line selection (there might be multiple if individual selections were merged into a single line selection).\n     * Useful for doing multiple-selection-aware line edits.\n     *\n     * @param {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>} selections\n     *      The selections to expand.\n     * @param {{expandEndAtStartOfLine: boolean, mergeAdjacent: boolean}} options\n     *      expandEndAtStartOfLine: true if a range selection that ends at the beginning of a line should be expanded\n     *          to encompass the line. Default false.\n     *      mergeAdjacent: true if adjacent line ranges should be merged. Default true.\n     * @return {Array.<{selectionForEdit: {start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean},\n     *                  selectionsToTrack: Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>}>}\n     *      The combined line selections. For each selection, `selectionForEdit` is the line selection, and `selectionsToTrack` is\n     *      the set of original selections that combined to make up the given line selection. Note that the selectionsToTrack will\n     *      include the original objects passed in `selections`, so if it is later mutated the original passed-in selections will be\n     *      mutated as well.\n     */\n    Editor.prototype.convertToLineSelections = function (selections, options) {\n        var self = this;\n        options = options || {};\n        _.defaults(options, { expandEndAtStartOfLine: false, mergeAdjacent: true });\n\n        // Combine adjacent lines with selections so they don't collide with each other, as they would\n        // if we did them individually.\n        var combinedSelections = [], prevSel;\n        _.each(selections, function (sel) {\n            var newSel = _.cloneDeep(sel);\n\n            // Adjust selection to encompass whole lines.\n            newSel.start.ch = 0;\n            // The end of the selection becomes the start of the next line, if it isn't already\n            // or if expandEndAtStartOfLine is set.\n            var hasSelection = (newSel.start.line !== newSel.end.line) || (newSel.start.ch !== newSel.end.ch);\n            if (options.expandEndAtStartOfLine || !hasSelection || newSel.end.ch !== 0) {\n                newSel.end = {line: newSel.end.line + 1, ch: 0};\n            }\n\n            // If the start of the new selection is within the range of the previous (expanded) selection, merge\n            // the two selections together, but keep track of all the original selections that were related to this\n            // selection, so they can be properly adjusted. (We only have to check for the start being inside the previous\n            // range - it can't be before it because the selections started out sorted.)\n            if (prevSel && self.posWithinRange(newSel.start, prevSel.selectionForEdit.start, prevSel.selectionForEdit.end, options.mergeAdjacent)) {\n                prevSel.selectionForEdit.end.line = newSel.end.line;\n                prevSel.selectionsToTrack.push(sel);\n            } else {\n                prevSel = {selectionForEdit: newSel, selectionsToTrack: [sel]};\n                combinedSelections.push(prevSel);\n            }\n        });\n        return combinedSelections;\n    };\n\n    /**\n     * Returns the currently selected text, or \"\" if no selection. Includes \\n if the\n     * selection spans multiple lines (does NOT reflect the Document's line-endings style). By\n     * default, returns only the contents of the primary selection, unless `allSelections` is true.\n     * @param {boolean=} allSelections Whether to return the contents of all selections (separated\n     *     by newlines) instead of just the primary selection. Default false.\n     * @return {!string} The selected text.\n     */\n    Editor.prototype.getSelectedText = function (allSelections) {\n        if (allSelections) {\n            return this._codeMirror.getSelection();\n        } else {\n            var sel = this.getSelection();\n            return this.document.getRange(sel.start, sel.end);\n        }\n    };\n\n    /**\n     * Sets the current selection. Start is inclusive, end is exclusive. Places the cursor at the\n     * end of the selection range. Optionally centers around the cursor after\n     * making the selection\n     *\n     * @param {!{line:number, ch:number}} start\n     * @param {{line:number, ch:number}=} end If not specified, defaults to start.\n     * @param {boolean} center true to center the viewport\n     * @param {number} centerOptions Option value, or 0 for no options; one of the BOUNDARY_* constants above.\n     * @param {?string} origin An optional string that describes what other selection or edit operations this\n     *      should be merged with for the purposes of undo. See {@link Document#replaceRange} for more details.\n     */\n    Editor.prototype.setSelection = function (start, end, center, centerOptions, origin) {\n        this.setSelections([{start: start, end: end || start}], center, centerOptions, origin);\n    };\n\n    /**\n     * Sets a multiple selection, with the \"primary\" selection (the one returned by\n     * getSelection() and getCursorPos()) defaulting to the last if not specified.\n     * Overlapping ranges will be automatically merged, and the selection will be sorted.\n     * Optionally centers around the primary selection after making the selection.\n     * @param {!Array<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean}>} selections\n     *      The selection ranges to set. If the start and end of a range are the same, treated as a cursor.\n     *      If reversed is true, set the anchor of the range to the end instead of the start.\n     *      If primary is true, this is the primary selection. Behavior is undefined if more than\n     *      one selection has primary set to true. If none has primary set to true, the last one is primary.\n     * @param {boolean} center true to center the viewport around the primary selection.\n     * @param {number} centerOptions Option value, or 0 for no options; one of the BOUNDARY_* constants above.\n     * @param {?string} origin An optional string that describes what other selection or edit operations this\n     *      should be merged with for the purposes of undo. See {@link Document#replaceRange} for more details.\n     */\n    Editor.prototype.setSelections = function (selections, center, centerOptions, origin) {\n        var primIndex = selections.length - 1, options;\n        if (origin) {\n            options = { origin: origin };\n        }\n        this._codeMirror.setSelections(_.map(selections, function (sel, index) {\n            if (sel.primary) {\n                primIndex = index;\n            }\n            return { anchor: sel.reversed ? sel.end : sel.start, head: sel.reversed ? sel.start : sel.end };\n        }), primIndex, options);\n        if (center) {\n            this.centerOnCursor(centerOptions);\n        }\n    };\n\n    /**\n     * Sets the editors overwrite mode state. If null is passed, the state is toggled.\n     *\n     * @param {?boolean} start\n     */\n    Editor.prototype.toggleOverwrite = function (state) {\n        this._codeMirror.toggleOverwrite(state);\n    };\n\n    /**\n     * Selects word that the given pos lies within or adjacent to. If pos isn't touching a word\n     * (e.g. within a token like \"//\"), moves the cursor to pos without selecting a range.\n     * @param {!{line:number, ch:number}}\n     */\n    Editor.prototype.selectWordAt = function (pos) {\n        var word = this._codeMirror.findWordAt(pos);\n        this.setSelection(word.anchor, word.head);\n    };\n\n    /**\n     * Gets the total number of lines in the document (includes lines not visible in the viewport)\n     * @return {!number}\n     */\n    Editor.prototype.lineCount = function () {\n        return this._codeMirror.lineCount();\n    };\n\n    /**\n     * Deterines if line is fully visible.\n     * @param {number} zero-based index of the line to test\n     * @return {boolean} true if the line is fully visible, false otherwise\n     */\n    Editor.prototype.isLineVisible = function (line) {\n        var coords = this._codeMirror.charCoords({line: line, ch: 0}, \"local\"),\n            scrollInfo = this._codeMirror.getScrollInfo(),\n            top = scrollInfo.top,\n            bottom = scrollInfo.top + scrollInfo.clientHeight;\n\n        // Check top and bottom and return false for partially visible lines.\n        return (coords.top >= top && coords.bottom <= bottom);\n    };\n\n    /**\n     * Gets the number of the first visible line in the editor.\n     * @return {number} The 0-based index of the first visible line.\n     */\n    Editor.prototype.getFirstVisibleLine = function () {\n        return (this._visibleRange ? this._visibleRange.startLine : 0);\n    };\n\n    /**\n     * Gets the number of the last visible line in the editor.\n     * @return {number} The 0-based index of the last visible line.\n     */\n    Editor.prototype.getLastVisibleLine = function () {\n        return (this._visibleRange ? this._visibleRange.endLine : this.lineCount() - 1);\n    };\n\n    /* Hides the specified line number in the editor\n     * @param {!from} line to start hiding from (inclusive)\n     * @param {!to} line to end hiding at (exclusive)\n     * @return {TextMarker} The CodeMirror mark object that's hiding the lines\n     */\n    Editor.prototype._hideLines = function (from, to) {\n        if (to <= from) {\n            return;\n        }\n\n        // We set clearWhenEmpty: false so that if there's a blank line at the beginning or end of\n        // the document, and that's the only hidden line, we can still actually hide it. Doing so\n        // requires us to create a 0-length marked span, which would ordinarily be cleaned up by CM\n        // if clearWithEmpty is true. See https://groups.google.com/forum/#!topic/codemirror/RB8VNF8ow2w\n        var value = this._codeMirror.markText(\n            {line: from, ch: 0},\n            {line: to - 1, ch: this._codeMirror.getLine(to - 1).length},\n            {collapsed: true, inclusiveLeft: true, inclusiveRight: true, clearWhenEmpty: false}\n        );\n\n        return value;\n    };\n\n    /**\n     * Gets the total height of the document in pixels (not the viewport)\n     * @return {!number} height in pixels\n     */\n    Editor.prototype.totalHeight = function () {\n        return this.getScrollerElement().scrollHeight;\n    };\n\n    /**\n     * Gets the scroller element from the editor.\n     * @return {!HTMLDivElement} scroller\n     */\n    Editor.prototype.getScrollerElement = function () {\n        return this._codeMirror.getScrollerElement();\n    };\n\n    /**\n     * Gets the root DOM node of the editor.\n     * @return {!HTMLDivElement} The editor's root DOM node.\n     */\n    Editor.prototype.getRootElement = function () {\n        return this._codeMirror.getWrapperElement();\n    };\n\n\n    /**\n     * Gets the lineSpace element within the editor (the container around the individual lines of code).\n     * FUTURE: This is fairly CodeMirror-specific. Logic that depends on this may break if we switch\n     * editors.\n     * @return {!HTMLDivElement} The editor's lineSpace element.\n     */\n    Editor.prototype._getLineSpaceElement = function () {\n        return $(\".CodeMirror-lines\", this.getScrollerElement()).children().get(0);\n    };\n\n    /**\n     * Returns the current scroll position of the editor.\n     * @return {{x:number, y:number}} The x,y scroll position in pixels\n     */\n    Editor.prototype.getScrollPos = function () {\n        var scrollInfo = this._codeMirror.getScrollInfo();\n        return { x: scrollInfo.left, y: scrollInfo.top };\n    };\n\n    /**\n     * Restores and adjusts the current scroll position of the editor.\n     * @param {{x:number, y:number}} scrollPos - The x,y scroll position in pixels\n     * @param {!number} heightDelta - The amount of delta H to apply to the scroll position\n     */\n    Editor.prototype.adjustScrollPos = function (scrollPos, heightDelta) {\n        this._codeMirror.scrollTo(scrollPos.x, scrollPos.y + heightDelta);\n    };\n\n    /**\n     * Sets the current scroll position of the editor.\n     * @param {number} x scrollLeft position in pixels\n     * @param {number} y scrollTop position in pixels\n     */\n    Editor.prototype.setScrollPos = function (x, y) {\n        this._codeMirror.scrollTo(x, y);\n    };\n\n    /*\n     * Returns the current text height of the editor.\n     * @return {number} Height of the text in pixels\n     */\n    Editor.prototype.getTextHeight = function () {\n        return this._codeMirror.defaultTextHeight();\n    };\n\n    /**\n     * Adds an inline widget below the given line. If any inline widget was already open for that\n     * line, it is closed without warning.\n     * @param {!{line:number, ch:number}} pos  Position in text to anchor the inline.\n     * @param {!InlineWidget} inlineWidget The widget to add.\n     * @param {boolean=} scrollLineIntoView Scrolls the associated line into view. Default true.\n     * @return {$.Promise} A promise object that is resolved when the widget has been added (but might\n     *     still be animating open). Never rejected.\n     */\n    Editor.prototype.addInlineWidget = function (pos, inlineWidget, scrollLineIntoView) {\n        var self = this,\n            queue = this._inlineWidgetQueues[pos.line],\n            deferred = new $.Deferred();\n        if (!queue) {\n            queue = new Async.PromiseQueue();\n            this._inlineWidgetQueues[pos.line] = queue;\n        }\n        queue.add(function () {\n            self._addInlineWidgetInternal(pos, inlineWidget, scrollLineIntoView, deferred);\n            return deferred.promise();\n        });\n        return deferred.promise();\n    };\n\n    /**\n     * @private\n     * Does the actual work of addInlineWidget().\n     */\n    Editor.prototype._addInlineWidgetInternal = function (pos, inlineWidget, scrollLineIntoView, deferred) {\n        var self = this;\n\n        this.removeAllInlineWidgetsForLine(pos.line).done(function () {\n            if (scrollLineIntoView === undefined) {\n                scrollLineIntoView = true;\n            }\n\n            if (scrollLineIntoView) {\n                self._codeMirror.scrollIntoView(pos);\n            }\n\n            inlineWidget.info = self._codeMirror.addLineWidget(pos.line, inlineWidget.htmlContent,\n                                                               { coverGutter: true, noHScroll: true });\n            CodeMirror.on(inlineWidget.info.line, \"delete\", function () {\n                self._removeInlineWidgetInternal(inlineWidget);\n            });\n            self._inlineWidgets.push(inlineWidget);\n\n            // Set up the widget to start closed, then animate open when its initial height is set.\n            inlineWidget.$htmlContent.height(0);\n            AnimationUtils.animateUsingClass(inlineWidget.htmlContent, \"animating\")\n                .done(function () {\n                    deferred.resolve();\n                });\n\n            // Callback to widget once parented to the editor. The widget should call back to\n            // setInlineWidgetHeight() in order to set its initial height and animate open.\n            inlineWidget.onAdded();\n        });\n    };\n\n    /**\n     * Removes all inline widgets\n     */\n    Editor.prototype.removeAllInlineWidgets = function () {\n        // copy the array because _removeInlineWidgetInternal will modify the original\n        var widgets = [].concat(this.getInlineWidgets());\n\n        return Async.doInParallel(\n            widgets,\n            this.removeInlineWidget.bind(this)\n        );\n    };\n\n    /**\n     * Removes the given inline widget.\n     * @param {number} inlineWidget The widget to remove.\n     * @return {$.Promise} A promise that is resolved when the inline widget is fully closed and removed from the DOM.\n     */\n    Editor.prototype.removeInlineWidget = function (inlineWidget) {\n        var deferred = new $.Deferred(),\n            self = this;\n\n        function finishRemoving() {\n            self._codeMirror.removeLineWidget(inlineWidget.info);\n            self._removeInlineWidgetInternal(inlineWidget);\n            deferred.resolve();\n        }\n\n        if (!inlineWidget.closePromise) {\n            // Remove the inline widget from our internal list immediately, so\n            // everyone external to us knows it's essentially already gone. We\n            // don't want to wait until it's done animating closed (but we do want\n            // the other stuff in _removeInlineWidgetInternal to wait until then).\n            self._removeInlineWidgetFromList(inlineWidget);\n\n            // If we're not visible (in which case the widget will have 0 client height),\n            // don't try to do the animation, because nothing will happen and we won't get\n            // called back right away. (The animation would happen later when we switch\n            // back to the editor.)\n            if (self.isFullyVisible()) {\n                AnimationUtils.animateUsingClass(inlineWidget.htmlContent, \"animating\")\n                    .done(finishRemoving);\n                inlineWidget.$htmlContent.height(0);\n            } else {\n                finishRemoving();\n            }\n            inlineWidget.closePromise = deferred.promise();\n        }\n        return inlineWidget.closePromise;\n    };\n\n    /**\n     * Removes all inline widgets for a given line\n     * @param {number} lineNum The line number to modify\n     */\n    Editor.prototype.removeAllInlineWidgetsForLine = function (lineNum) {\n        var lineInfo = this._codeMirror.lineInfo(lineNum),\n            widgetInfos = (lineInfo && lineInfo.widgets) ? [].concat(lineInfo.widgets) : null,\n            self = this;\n\n        if (widgetInfos && widgetInfos.length) {\n            // Map from CodeMirror LineWidget to Brackets InlineWidget\n            var inlineWidget,\n                allWidgetInfos = this._inlineWidgets.map(function (w) {\n                    return w.info;\n                });\n\n            return Async.doInParallel(\n                widgetInfos,\n                function (info) {\n                    // Lookup the InlineWidget object using the same index\n                    inlineWidget = self._inlineWidgets[allWidgetInfos.indexOf(info)];\n                    if (inlineWidget) {\n                        return self.removeInlineWidget(inlineWidget);\n                    } else {\n                        return new $.Deferred().resolve().promise();\n                    }\n                }\n            );\n        } else {\n            return new $.Deferred().resolve().promise();\n        }\n    };\n\n    /**\n     * Cleans up the given inline widget from our internal list of widgets. It's okay\n     * to call this multiple times for the same widget--it will just do nothing if\n     * the widget has already been removed.\n     * @param {InlineWidget} inlineWidget  an inline widget.\n     */\n    Editor.prototype._removeInlineWidgetFromList = function (inlineWidget) {\n        var l = this._inlineWidgets.length,\n            i;\n        for (i = 0; i < l; i++) {\n            if (this._inlineWidgets[i] === inlineWidget) {\n                this._inlineWidgets.splice(i, 1);\n                break;\n            }\n        }\n    };\n\n    /**\n     * Removes the inline widget from the editor and notifies it to clean itself up.\n     * @param {InlineWidget} inlineWidget  an inline widget.\n     */\n    Editor.prototype._removeInlineWidgetInternal = function (inlineWidget) {\n        if (!inlineWidget.isClosed) {\n            this._removeInlineWidgetFromList(inlineWidget);\n            inlineWidget.onClosed();\n            inlineWidget.isClosed = true;\n        }\n    };\n\n    /**\n     * Returns a list of all inline widgets currently open in this editor. Each entry contains the\n     * inline's id, and the data parameter that was passed to addInlineWidget().\n     * @return {!Array.<{id:number, data:Object}>}\n     */\n    Editor.prototype.getInlineWidgets = function () {\n        return this._inlineWidgets;\n    };\n\n      /**\n     * Returns the currently focused inline widget, if any.\n     * @return {?InlineWidget}\n     */\n    Editor.prototype.getFocusedInlineWidget = function () {\n        var result = null;\n\n        this.getInlineWidgets().forEach(function (widget) {\n            if (widget.hasFocus()) {\n                result = widget;\n            }\n        });\n\n        return result;\n    };\n\n    /**\n     * Display temporary popover message at current cursor position. Display message above\n     * cursor if space allows, otherwise below.\n     *\n     * @param {string} errorMsg Error message to display\n     */\n    Editor.prototype.displayErrorMessageAtCursor = function (errorMsg) {\n        var arrowBelow, cursorPos, cursorCoord, popoverRect,\n            top, left, clip, arrowCenter, arrowLeft,\n            self = this,\n            POPOVER_MARGIN = 10,\n            POPOVER_ARROW_HALF_WIDTH = 10,\n            POPOVER_ARROW_HALF_BASE = POPOVER_ARROW_HALF_WIDTH + 3; // 3 is border radius\n\n        function _removeListeners() {\n            self.off(\".msgbox\");\n        }\n\n        // PopUpManager.removePopUp() callback\n        function _clearMessagePopover() {\n            if (self._$messagePopover && self._$messagePopover.length > 0) {\n                // self._$messagePopover.remove() is done by PopUpManager\n                self._$messagePopover = null;\n            }\n            _removeListeners();\n        }\n\n        // PopUpManager.removePopUp() is called either directly by this closure, or by\n        // PopUpManager as a result of another popup being invoked.\n        function _removeMessagePopover() {\n            if (self._$messagePopover) {\n                PopUpManager.removePopUp(self._$messagePopover);\n            }\n        }\n\n        function _addListeners() {\n            self\n                .on(\"blur.msgbox\",           _removeMessagePopover)\n                .on(\"change.msgbox\",         _removeMessagePopover)\n                .on(\"cursorActivity.msgbox\", _removeMessagePopover)\n                .on(\"update.msgbox\",         _removeMessagePopover);\n        }\n\n        // Only 1 message at a time\n        if (this._$messagePopover) {\n            _removeMessagePopover();\n        }\n\n        // Make sure cursor is in view\n        cursorPos = this.getCursorPos();\n        this._codeMirror.scrollIntoView(cursorPos);\n\n        // Determine if arrow is above or below\n        cursorCoord = this._codeMirror.charCoords(cursorPos);\n\n        // Assume popover height is max of 2 lines\n        arrowBelow = (cursorCoord.top > 100);\n\n        // Text is dynamic, so build popover first so we can measure final width\n        this._$messagePopover = $(\"<div/>\").addClass(\"popover-message\").appendTo($(\"body\"));\n        if (!arrowBelow) {\n            $(\"<div/>\").addClass(\"arrowAbove\").appendTo(this._$messagePopover);\n        }\n        $(\"<div/>\").addClass(\"text\").appendTo(this._$messagePopover).html(errorMsg);\n        if (arrowBelow) {\n            $(\"<div/>\").addClass(\"arrowBelow\").appendTo(this._$messagePopover);\n        }\n\n        // Estimate where to position popover.\n        top = (arrowBelow) ? cursorCoord.top - this._$messagePopover.height() - POPOVER_MARGIN\n                           : cursorCoord.bottom + POPOVER_MARGIN;\n        left = cursorCoord.left - (this._$messagePopover.width() / 2);\n\n        popoverRect = {\n            top:    top,\n            left:   left,\n            height: this._$messagePopover.height(),\n            width:  this._$messagePopover.width()\n        };\n\n        // See if popover is clipped on any side\n        clip = ViewUtils.getElementClipSize($(\"#editor-holder\"), popoverRect);\n\n        // Prevent horizontal clipping\n        if (clip.left > 0) {\n            left += clip.left;\n        } else if (clip.right > 0) {\n            left -= clip.right;\n        }\n\n        // Popover text and arrow are positioned individually\n        this._$messagePopover.css({\"top\": top, \"left\": left});\n\n        // Position popover arrow centered over/under cursor...\n        arrowCenter = cursorCoord.left - left;\n\n        // ... but don't let it slide off text box\n        arrowCenter = Math.min(popoverRect.width - POPOVER_ARROW_HALF_BASE,\n                               Math.max(arrowCenter, POPOVER_ARROW_HALF_BASE));\n\n        arrowLeft = arrowCenter - POPOVER_ARROW_HALF_WIDTH;\n        if (arrowBelow) {\n            this._$messagePopover.find(\".arrowBelow\").css({\"margin-left\": arrowLeft});\n        } else {\n            this._$messagePopover.find(\".arrowAbove\").css({\"margin-left\": arrowLeft});\n        }\n\n        // Add listeners\n        PopUpManager.addPopUp(this._$messagePopover, _clearMessagePopover, true);\n        _addListeners();\n\n        // Animate open\n        AnimationUtils.animateUsingClass(this._$messagePopover[0], \"animateOpen\").done(function () {\n            // Make sure we still have a popover\n            if (self._$messagePopover && self._$messagePopover.length > 0) {\n                self._$messagePopover.addClass(\"open\");\n\n                // Don't add scroll listeners until open so we don't get event\n                // from scrolling cursor into view\n                self.on(\"scroll.msgbox\", _removeMessagePopover);\n\n                // Animate closed -- which includes delay to show message\n                AnimationUtils.animateUsingClass(self._$messagePopover[0], \"animateClose\", 6000)\n                    .done(_removeMessagePopover);\n            }\n        });\n    };\n\n    /**\n     * Returns the offset of the top of the virtual scroll area relative to the browser window (not the editor\n     * itself). Mainly useful for calculations related to scrollIntoView(), where you're starting with the\n     * offset() of a child widget (relative to the browser window) and need to figure out how far down it is from\n     * the top of the virtual scroll area (excluding the top padding).\n     * @return {number}\n     */\n    Editor.prototype.getVirtualScrollAreaTop = function () {\n        var topPadding = this._getLineSpaceElement().offsetTop, // padding within mover\n            scroller = this.getScrollerElement();\n        return $(scroller).offset().top - scroller.scrollTop + topPadding;\n    };\n\n    /**\n     * Sets the height of an inline widget in this editor.\n     * @param {!InlineWidget} inlineWidget The widget whose height should be set.\n     * @param {!number} height The height of the widget.\n     * @param {boolean=} ensureVisible Whether to scroll the entire widget into view. Default false.\n     */\n    Editor.prototype.setInlineWidgetHeight = function (inlineWidget, height, ensureVisible) {\n        var self = this,\n            node = inlineWidget.htmlContent,\n            oldHeight = (node && $(node).height()) || 0,\n            changed = (oldHeight !== height),\n            isAttached = inlineWidget.info !== undefined;\n\n        function updateHeight() {\n            // Notify CodeMirror for the height change.\n            if (isAttached) {\n                inlineWidget.info.changed();\n            }\n        }\n\n        function setOuterHeight() {\n            function finishAnimating(e) {\n                if (e.target === node) {\n                    updateHeight();\n                    $(node).off(\"webkitTransitionEnd\", finishAnimating);\n                }\n            }\n            $(node).height(height);\n            if ($(node).hasClass(\"animating\")) {\n                $(node).on(\"webkitTransitionEnd\", finishAnimating);\n            } else {\n                updateHeight();\n            }\n        }\n\n        // Make sure we set an explicit height on the widget, so children can use things like\n        // min-height if they want.\n        if (changed || !node.style.height) {\n            // If we're animating, set the wrapper's height on a timeout so the layout is finished before we animate.\n            if ($(node).hasClass(\"animating\")) {\n                window.setTimeout(setOuterHeight, 0);\n            } else {\n                setOuterHeight();\n            }\n        }\n\n        if (ensureVisible && isAttached) {\n            var offset = $(node).offset(), // offset relative to document\n                position = $(node).position(), // position within parent linespace\n                scrollerTop = self.getVirtualScrollAreaTop();\n\n            self._codeMirror.scrollIntoView({\n                left: position.left,\n                top: offset.top - scrollerTop,\n                right: position.left, // don't try to make the right edge visible\n                bottom: offset.top + height - scrollerTop\n            });\n        }\n    };\n\n    /**\n     * @private\n     * Get the starting line number for an inline widget.\n     * @param {!InlineWidget} inlineWidget\n     * @return {number} The line number of the widget or -1 if not found.\n     */\n    Editor.prototype._getInlineWidgetLineNumber = function (inlineWidget) {\n        return this._codeMirror.getLineNumber(inlineWidget.info.line);\n    };\n\n    /** Gives focus to the editor control */\n    Editor.prototype.focus = function () {\n        // Focusing an editor synchronously triggers focus/blur handlers. If a blur handler attemps to focus\n        // another editor, we'll put CM in a bad state (because CM assumes programmatically focusing itself\n        // will always succeed, and if you're in the middle of another focus change that appears to be untrue).\n        // So instead, we simply ignore reentrant focus attempts.\n        // See bug #2951 for an example of this happening and badly hosing things.\n        if (_duringFocus) {\n            return;\n        }\n\n        _duringFocus = true;\n        try {\n            this._codeMirror.focus();\n        } finally {\n            _duringFocus = false;\n        }\n    };\n\n    /** Returns true if the editor has focus */\n    Editor.prototype.hasFocus = function () {\n        return this._focused;\n    };\n\n    /*\n     * @typedef {scrollPos:{x:number, y:number},Array.<{start:{line:number, ch:number},end:{line:number, ch:number}}>} EditorViewState\n     */\n\n    /*\n     * returns the view state for the editor\n     * @return {!EditorViewState}\n     */\n    Editor.prototype.getViewState = function () {\n        return {\n            selections: this.getSelections(),\n            scrollPos: this.getScrollPos()\n        };\n\n    };\n\n    /*\n     * Restores the view state\n     * @param {!EditorViewState} viewState - the view state object to restore\n     */\n    Editor.prototype.restoreViewState = function (viewState) {\n        if (viewState.selection) {\n            // We no longer write out single-selection, but there might be some view state\n            // from an older version.\n            this.setSelection(viewState.selection.start, viewState.selection.end);\n        }\n        if (viewState.selections) {\n            this.setSelections(viewState.selections);\n        }\n        if (viewState.scrollPos) {\n            this.setScrollPos(viewState.scrollPos.x, viewState.scrollPos.y);\n        }\n    };\n\n    /**\n     * Re-renders the editor UI\n     * @param {boolean=} handleResize true if this is in response to resizing the editor. Default false.\n     */\n    Editor.prototype.refresh = function (handleResize) {\n        // If focus is currently in a child of the CodeMirror editor (e.g. in an inline widget), but not in\n        // the CodeMirror input field itself, remember the focused item so we can restore focus after the\n        // refresh (which might cause the widget to be removed from the display list temporarily).\n        var focusedItem = window.document.activeElement,\n            restoreFocus = $.contains(this._codeMirror.getScrollerElement(), focusedItem);\n        this._codeMirror.refresh();\n        if (restoreFocus) {\n            focusedItem.focus();\n        }\n    };\n\n    /**\n     * Re-renders the editor, and all children inline editors.\n     * @param {boolean=} handleResize true if this is in response to resizing the editor. Default false.\n     */\n    Editor.prototype.refreshAll = function (handleResize) {\n        this.refresh(handleResize);\n        this.getInlineWidgets().forEach(function (inlineWidget) {\n            inlineWidget.refresh();\n        });\n    };\n\n    /** Undo the last edit. */\n    Editor.prototype.undo = function () {\n        this._codeMirror.undo();\n    };\n\n    /** Redo the last un-done edit. */\n    Editor.prototype.redo = function () {\n        this._codeMirror.redo();\n    };\n\n    /**\n     * View API Visibility Change Notification handler.  This is also\n     * called by the native \"setVisible\" API which refresh can be optimized\n     * @param {boolean} show true to show the editor, false to hide it\n     * @param {boolean} refresh true (default) to refresh the editor, false to skip refreshing it\n     */\n    Editor.prototype.notifyVisibilityChange = function (show, refresh) {\n        if (show && (refresh || refresh === undefined)) {\n            this.refresh();\n        }\n        if (show) {\n            this._inlineWidgets.forEach(function (inlineWidget) {\n                inlineWidget.onParentShown();\n            });\n        }\n    };\n\n    /**\n     * Shows or hides the editor within its parent. Does not force its ancestors to\n     * become visible.\n     * @param {boolean} show true to show the editor, false to hide it\n     * @param {boolean} refresh true (default) to refresh the editor, false to skip refreshing it\n     */\n    Editor.prototype.setVisible = function (show, refresh) {\n        this.$el.css(\"display\", (show ? \"\" : \"none\"));\n        this.notifyVisibilityChange(show, refresh);\n    };\n\n    /**\n     * Returns true if the editor is fully visible--i.e., is in the DOM, all ancestors are\n     * visible, and has a non-zero width/height.\n     */\n    Editor.prototype.isFullyVisible = function () {\n        return $(this.getRootElement()).is(\":visible\");\n    };\n\n    /**\n     * Gets the syntax-highlighting mode for the given range.\n     * Returns null if the mode at the start of the selection differs from the mode at the end -\n     * an *approximation* of whether the mode is consistent across the whole range (a pattern like\n     * A-B-A would return A as the mode, not null).\n     *\n     * @param {!{line: number, ch: number}} start The start of the range to check.\n     * @param {!{line: number, ch: number}} end The end of the range to check.\n     * @param {boolean=} knownMixed Whether we already know we're in a mixed mode and need to check both\n     *     the start and end.\n     * @return {?(Object|string)} Name of syntax-highlighting mode, or object containing a \"name\" property\n     *     naming the mode along with configuration options required by the mode.\n     * @see {@link LanguageManager::#getLanguageForPath} and {@link LanguageManager::Language#getMode}.\n     */\n    Editor.prototype.getModeForRange = function (start, end, knownMixed) {\n        var outerMode = this._codeMirror.getMode(),\n            startMode = TokenUtils.getModeAt(this._codeMirror, start),\n            endMode = TokenUtils.getModeAt(this._codeMirror, end);\n        if (!knownMixed && outerMode.name === startMode.name) {\n            // Mode does not vary: just use the editor-wide mode name\n            return this._codeMirror.getOption(\"mode\");\n        } else if (!startMode || !endMode || startMode.name !== endMode.name) {\n            return null;\n        } else {\n            return startMode;\n        }\n    };\n\n    /**\n     * Gets the syntax-highlighting mode for the current selection or cursor position. (The mode may\n     * vary within one file due to embedded languages, e.g. JS embedded in an HTML script block). See\n     * `getModeForRange()` for how this is determined for a single selection.\n     *\n     * If there are multiple selections, this will return a mode only if all the selections are individually\n     * consistent and resolve to the same mode.\n     *\n     * @return {?(Object|string)} Name of syntax-highlighting mode, or object containing a \"name\" property\n     *     naming the mode along with configuration options required by the mode.\n     * @see {@link LanguageManager::#getLanguageForPath} and {@link LanguageManager::Language#getMode}.\n     */\n    Editor.prototype.getModeForSelection = function () {\n        // Check for mixed mode info\n        var self        = this,\n            sels        = this.getSelections(),\n            primarySel  = this.getSelection(),\n            outerMode   = this._codeMirror.getMode(),\n            startMode   = TokenUtils.getModeAt(this._codeMirror, primarySel.start),\n            isMixed     = (outerMode.name !== startMode.name);\n\n        if (isMixed) {\n            // This is the magic code to let the code view know that we are in 'css' context\n            // if the CodeMirror outermode is 'htmlmixed' and we are in 'style' attributes\n            // value context. This has to be done as CodeMirror doesn't yet think this as 'css'\n            // This magic is executed only when user is having a cursor and not selection\n            // We will enable selection handling one we figure a way out to handle mixed scope selection\n            if (outerMode.name === 'htmlmixed' && primarySel.start.line === primarySel.end.line && primarySel.start.ch === primarySel.end.ch) {\n                var tagInfo = HTMLUtils.getTagInfo(this, primarySel.start, true),\n                    tokenType = tagInfo.position.tokenType;\n \n                if (tokenType === HTMLUtils.ATTR_VALUE && tagInfo.attr.name.toLowerCase() === 'style') {\n                    return 'css';\n                }\n            }\n            // Shortcut the first check to avoid getModeAt(), which can be expensive\n            if (primarySel.start.line !== primarySel.end.line || primarySel.start.ch !== primarySel.end.ch) {\n                var endMode = TokenUtils.getModeAt(this._codeMirror, primarySel.end);\n\n                if (startMode.name !== endMode.name) {\n                    return null;\n                }\n            }\n\n            // If mixed mode, check that mode is the same at start & end of each selection\n            var hasMixedSel = _.some(sels, function (sel) {\n                if (sels === primarySel) {\n                    // We already checked this before, so we know it's not mixed.\n                    return false;\n                }\n\n                var rangeMode = self.getModeForRange(sel.start, sel.end, true);\n                return (!rangeMode || rangeMode.name !== startMode.name);\n            });\n            if (hasMixedSel) {\n                return null;\n            }\n\n            return startMode.name;\n        } else {\n            // Mode does not vary: just use the editor-wide mode\n            return this._codeMirror.getOption(\"mode\");\n        }\n    };\n\n    /*\n     * gets the language for the selection. (Javascript selected from an HTML document or CSS selected from an HTML document, etc...)\n     * @return {!Language}\n     */\n    Editor.prototype.getLanguageForSelection = function () {\n        return this.document.getLanguage().getLanguageForMode(this.getModeForSelection());\n    };\n\n    /**\n     * Gets the syntax-highlighting mode for the document.\n     *\n     * @return {Object|String} Object or Name of syntax-highlighting mode\n     * @see {@link LanguageManager::#getLanguageForPath|LanguageManager.getLanguageForPath} and {@link LanguageManager::Language#getMode|Language.getMode}.\n     */\n    Editor.prototype.getModeForDocument = function () {\n        return this._codeMirror.getOption(\"mode\");\n    };\n\n    /**\n     * The Document we're bound to\n     * @type {!Document}\n     */\n    Editor.prototype.document = null;\n\n\n    /**\n     * The Editor's last known width.\n     * Used in conjunction with updateLayout to recompute the layout\n     * if the parent container changes its size since our last layout update.\n     * @type {?number}\n     */\n    Editor.prototype._lastEditorWidth = null;\n\n\n    /**\n     * If true, we're in the middle of syncing to/from the Document. Used to ignore spurious change\n     * events caused by us (vs. change events caused by others, which we need to pay attention to).\n     * @type {!boolean}\n     */\n    Editor.prototype._duringSync = false;\n\n    /**\n     * @private\n     * NOTE: this is actually \"semi-private\": EditorManager also accesses this field... as well as\n     * a few other modules. However, we should try to gradually move most code away from talking to\n     * CodeMirror directly.\n     * @type {!CodeMirror}\n     */\n    Editor.prototype._codeMirror = null;\n\n    /**\n     * @private\n     * @type {!Array.<{id:number, data:Object}>}\n     */\n    Editor.prototype._inlineWidgets = null;\n\n    /**\n     * @private\n     * @type {?TextRange}\n     */\n    Editor.prototype._visibleRange = null;\n\n    /**\n     * @private\n     * @type {Object}\n     * Promise queues for inline widgets being added to a given line.\n     */\n    Editor.prototype._inlineWidgetQueues = null;\n\n    /**\n     * @private\n     * @type {Array}\n     * A list of objects corresponding to the markers that are hiding lines in the current editor.\n     */\n    Editor.prototype._hideMarks = null;\n\n    /**\n     * @private\n     *\n     * Retrieve the value of the named preference for this document.\n     *\n     * @param {string} prefName Name of preference to retrieve.\n     * @return {*} current value of that pref\n     */\n    Editor.prototype._getOption = function (prefName) {\n        return PreferencesManager.get(prefName, PreferencesManager._buildContext(this.document.file.fullPath, this.document.getLanguage().getId()));\n    };\n\n    /**\n     * @private\n     *\n     * Updates the editor to the current value of prefName for the file being edited.\n     *\n     * @param {string} prefName Name of the preference to visibly update\n     */\n    Editor.prototype._updateOption = function (prefName) {\n        var oldValue = this._currentOptions[prefName],\n            newValue = this._getOption(prefName);\n\n        if (oldValue !== newValue) {\n            this._currentOptions[prefName] = newValue;\n\n            if (prefName === USE_TAB_CHAR) {\n                this._codeMirror.setOption(cmOptions[prefName], newValue);\n                this._codeMirror.setOption(\"indentUnit\", newValue === true ?\n                                           this._currentOptions[TAB_SIZE] :\n                                           this._currentOptions[SPACE_UNITS]\n                                          );\n            } else if (prefName === STYLE_ACTIVE_LINE) {\n                this._updateStyleActiveLine();\n            } else if (prefName === SCROLL_PAST_END && this._visibleRange) {\n                // Do not apply this option to inline editors\n                return;\n            } else if (prefName === SHOW_LINE_NUMBERS) {\n                Editor._toggleLinePadding(!newValue);\n                this._codeMirror.setOption(cmOptions[SHOW_LINE_NUMBERS], newValue);\n                if (newValue) {\n                    Editor.registerGutter(LINE_NUMBER_GUTTER, LINE_NUMBER_GUTTER_PRIORITY);\n                } else {\n                    Editor.unregisterGutter(LINE_NUMBER_GUTTER);\n                }\n                this.refreshAll();\n            } else {\n                this._codeMirror.setOption(cmOptions[prefName], newValue);\n            }\n\n            this.trigger(\"optionChange\", prefName, newValue);\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Used to ensure that \"style active line\" is turned off when there is a selection.\n     */\n    Editor.prototype._updateStyleActiveLine = function () {\n        if (this.hasSelection()) {\n            if (this._codeMirror.getOption(\"styleActiveLine\")) {\n                this._codeMirror.setOption(\"styleActiveLine\", false);\n            }\n        } else {\n            this._codeMirror.setOption(\"styleActiveLine\", this._currentOptions[STYLE_ACTIVE_LINE]);\n        }\n    };\n\n    /**\n     * resizes the editor to fill its parent container\n     * should not be used on inline editors\n     * @param {boolean=} forceRefresh - forces the editor to update its layout\n     *                                   even if it already matches the container's height / width\n     */\n    Editor.prototype.updateLayout = function (forceRefresh) {\n        var curRoot = this.getRootElement(),\n            curWidth = $(curRoot).width(),\n            $editorHolder = this.$el.parent(),\n            editorAreaHt = $editorHolder.height();\n\n        if (!curRoot.style.height || $(curRoot).height() !== editorAreaHt) {\n            // Call setSize() instead of $.height() to allow CodeMirror to\n            // check for options like line wrapping\n            this.setSize(null, editorAreaHt);\n            if (forceRefresh === undefined) {\n                forceRefresh = true;\n            }\n        } else if (curWidth !== this._lastEditorWidth) {\n            if (forceRefresh === undefined) {\n                forceRefresh = true;\n            }\n        }\n        this._lastEditorWidth = curWidth;\n\n        if (forceRefresh) {\n            this.refreshAll(forceRefresh);\n        }\n    };\n\n    /**\n     * Clears all marks from the gutter with the specified name.\n     * @param {string} name The name of the gutter to clear.\n     */\n    Editor.prototype.clearGutter = function (name) {\n        this._codeMirror.clearGutter(name);\n    };\n\n    /**\n     * Renders all registered gutters\n     * @private\n     */\n    Editor.prototype._renderGutters = function () {\n        var languageId = this.document.getLanguage().getId();\n\n        function _filterByLanguages(gutter) {\n            return !gutter.languages || gutter.languages.indexOf(languageId) > -1;\n        }\n\n        function _sortByPriority(a, b) {\n            return a.priority - b.priority;\n        }\n\n        function _getName(gutter) {\n            return gutter.name;\n        }\n\n        var gutters = registeredGutters.map(_getName),\n            rootElement = this.getRootElement();\n\n        // If the line numbers gutter has not been explicitly registered and the CodeMirror lineNumbes option is\n        // set to true, we explicitly add the line numbers gutter. This case occurs the first time the editor loads\n        // and showLineNumbers is set to true in preferences\n        if (gutters.indexOf(LINE_NUMBER_GUTTER) < 0 && this._codeMirror.getOption(cmOptions[SHOW_LINE_NUMBERS])) {\n            registeredGutters.push({name: LINE_NUMBER_GUTTER, priority: LINE_NUMBER_GUTTER_PRIORITY});\n        }\n\n        gutters = registeredGutters.sort(_sortByPriority)\n            .filter(_filterByLanguages)\n            .map(_getName);\n\n        this._codeMirror.setOption(\"gutters\", gutters);\n        this._codeMirror.refresh();\n\n        if (gutters.indexOf(LINE_NUMBER_GUTTER) < 0) {\n            $(rootElement).addClass(\"linenumber-disabled\");\n        } else {\n            $(rootElement).removeClass(\"linenumber-disabled\");\n        }\n    };\n\n    /**\n     * Sets the marker for the specified gutter on the specified line number\n     * @param   {string}   lineNumber The line number for the inserted gutter marker\n     * @param   {string}   gutterName The name of the gutter\n     * @param   {object}   marker     The dom element representing the marker to the inserted in the gutter\n     */\n    Editor.prototype.setGutterMarker = function (lineNumber, gutterName, marker) {\n        var gutterNameRegistered = registeredGutters.some(function (gutter) {\n            return gutter.name === gutterName;\n        });\n\n        if (!gutterNameRegistered) {\n            console.warn(\"Gutter name must be registered before calling editor.setGutterMarker\");\n            return;\n        }\n\n        this._codeMirror.setGutterMarker(lineNumber, gutterName, marker);\n    };\n\n    /**\n     * Returns the list of gutters current registered on all editors.\n     * @return {!Array.<{name: string, priority: number}>}\n     */\n    Editor.getRegisteredGutters = function () {\n        return registeredGutters;\n    };\n\n    /**\n     * Registers the gutter with the specified name at the given priority.\n     * @param {string} name    The name of the gutter.\n     * @param {number} priority  A number denoting the priority of the gutter. Priorities higher than LINE_NUMBER_GUTTER_PRIORITY appear after the line numbers. Priority less than LINE_NUMBER_GUTTER_PRIORITY appear before.\n     * @param {?Array<string>} languageIds A list of language ids that this gutter is valid for. If no language ids are passed, then the gutter is valid in all languages.\n     */\n    Editor.registerGutter = function (name, priority, languageIds) {\n        if (isNaN(priority)) {\n            console.warn(\"A non-numeric priority value was passed to registerGutter. The value will default to 0.\");\n            priority = 0;\n        }\n\n        if (!name || typeof name !== \"string\") {\n            console.error(\"The name of the registered gutter must be a string.\");\n            return;\n        }\n\n        var gutter = {name: name, priority: priority, languages: languageIds},\n            gutterExists = registeredGutters.some(function (gutter) {\n                return gutter.name === name;\n            });\n\n        if (!gutterExists) {\n            registeredGutters.push(gutter);\n        }\n\n        Editor.forEveryEditor(function (editor) {\n            editor._renderGutters();\n        });\n    };\n\n    /**\n     * Unregisters the gutter with the specified name and removes it from the UI.\n     * @param {string} name The name of the gutter to be unregistered.\n     */\n    Editor.unregisterGutter = function (name) {\n        var i, gutter;\n        registeredGutters = registeredGutters.filter(function (gutter) {\n            return gutter.name !== name;\n        });\n\n        Editor.forEveryEditor(function (editor) {\n            editor._renderGutters();\n        });\n    };\n\n    // Global settings that affect Editor instances that share the same preference locations\n\n    /**\n     * Sets whether to use tab characters (vs. spaces) when inserting new text.\n     * Affects any editors that share the same preference location.\n     * @param {boolean} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setUseTabChar = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(USE_TAB_CHAR, value, options);\n    };\n\n    /**\n     * Gets whether the specified or current file uses tab characters (vs. spaces) when inserting new text\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean}\n     */\n    Editor.getUseTabChar = function (fullPath) {\n        return PreferencesManager.get(USE_TAB_CHAR, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets tab character width.\n     * Affects any editors that share the same preference location.\n     * @param {number} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setTabSize = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(TAB_SIZE, value, options);\n    };\n\n    /**\n     * Get indent unit\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {number}\n     */\n    Editor.getTabSize = function (fullPath) {\n        return PreferencesManager.get(TAB_SIZE, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets indentation width.\n     * Affects any editors that share the same preference location.\n     * @param {number} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setSpaceUnits = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(SPACE_UNITS, value, options);\n    };\n\n    /**\n     * Get indentation width\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {number}\n     */\n    Editor.getSpaceUnits = function (fullPath) {\n        return PreferencesManager.get(SPACE_UNITS, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets the auto close brackets.\n     * Affects any editors that share the same preference location.\n     * @param {boolean} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setCloseBrackets = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(CLOSE_BRACKETS, value, options);\n    };\n\n    /**\n     * Gets whether the specified or current file uses auto close brackets\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean}\n     */\n    Editor.getCloseBrackets = function (fullPath) {\n        return PreferencesManager.get(CLOSE_BRACKETS, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets show line numbers option.\n     * Affects any editors that share the same preference location.\n     * @param {boolean} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setShowLineNumbers = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(SHOW_LINE_NUMBERS, value, options);\n    };\n\n    /**\n     * Returns true if show line numbers is enabled for the specified or current file\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean}\n     */\n    Editor.getShowLineNumbers = function (fullPath) {\n        return PreferencesManager.get(SHOW_LINE_NUMBERS, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets show active line option.\n     * Affects any editors that share the same preference location.\n     * @param {boolean} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setShowActiveLine = function (value, fullPath) {\n        return PreferencesManager.set(STYLE_ACTIVE_LINE, value);\n    };\n\n    /**\n     * Returns true if show active line is enabled for the specified or current file\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean}\n     */\n    Editor.getShowActiveLine = function (fullPath) {\n        return PreferencesManager.get(STYLE_ACTIVE_LINE, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets word wrap option.\n     * Affects any editors that share the same preference location.\n     * @param {boolean} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setWordWrap = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(WORD_WRAP, value, options);\n    };\n\n    /**\n     * Returns true if word wrap is enabled for the specified or current file\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean}\n     */\n    Editor.getWordWrap = function (fullPath) {\n        return PreferencesManager.get(WORD_WRAP, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Sets indentLineComment option.\n     * Affects any editors that share the same preference location.\n     * @param {boolean} value\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean} true if value was valid\n     */\n    Editor.setIndentLineComment = function (value, fullPath) {\n        var options = fullPath && {context: fullPath};\n        return PreferencesManager.set(INDENT_LINE_COMMENT, value, options);\n    };\n\n    /**\n     * Returns true if indentLineComment is enabled for the specified or current file\n     * @param {string=} fullPath Path to file to get preference for\n     * @return {boolean}\n     */\n    Editor.getIndentLineComment = function (fullPath) {\n        return PreferencesManager.get(INDENT_LINE_COMMENT, _buildPreferencesContext(fullPath));\n    };\n\n    /**\n     * Runs callback for every Editor instance that currently exists\n     * @param {!function(!Editor)} callback\n     */\n    Editor.forEveryEditor = function (callback) {\n        _instances.forEach(callback);\n    };\n\n    /**\n     * @private\n     * Toggles the left padding of all code editors.  Used to provide more\n     * space between the code text and the left edge of the editor when\n     * line numbers are hidden.\n     * @param {boolean} showLinePadding\n     */\n    Editor._toggleLinePadding = function (showLinePadding) {\n        // apply class to all pane DOM nodes\n        var $holders = [];\n        _instances.forEach(function (editor) {\n            var $editorHolder = editor.$el.parent();\n            if ($holders.indexOf($editorHolder) === -1) {\n                $holders.push($editorHolder);\n            }\n        });\n\n        _.each($holders, function ($holder) {\n            $holder.toggleClass(\"show-line-padding\", Boolean(showLinePadding));\n        });\n    };\n    \n    Editor.LINE_NUMBER_GUTTER_PRIORITY = LINE_NUMBER_GUTTER_PRIORITY;\n    Editor.CODE_FOLDING_GUTTER_PRIORITY = CODE_FOLDING_GUTTER_PRIORITY;\n    \n    // Set up listeners for preference changes\n    editorOptions.forEach(function (prefName) {\n        PreferencesManager.on(\"change\", prefName, function () {\n            _instances.forEach(function (editor) {\n                editor._updateOption(prefName);\n            });\n        });\n    });\n\n    // Define public API\n    exports.Editor                  = Editor;\n    exports.BOUNDARY_CHECK_NORMAL   = BOUNDARY_CHECK_NORMAL;\n    exports.BOUNDARY_IGNORE_TOP     = BOUNDARY_IGNORE_TOP;\n});\n"
  },
  {
    "path": "src/editor/EditorCommandHandlers.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Text-editing commands that apply to whichever Editor is currently focused\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var Commands           = require(\"command/Commands\"),\n        Strings            = require(\"strings\"),\n        Editor              = require(\"editor/Editor\").Editor,\n        CommandManager     = require(\"command/CommandManager\"),\n        EditorManager      = require(\"editor/EditorManager\"),\n        StringUtils        = require(\"utils/StringUtils\"),\n        TokenUtils         = require(\"utils/TokenUtils\"),\n        CodeMirror         = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        _                  = require(\"thirdparty/lodash\");\n\n    /**\n     * List of constants\n     */\n    var DIRECTION_UP    = -1;\n    var DIRECTION_DOWN  = +1;\n\n    /**\n     * @private\n     * Creates special regular expressions that matches the line prefix but not the block prefix or suffix\n     * @param {!string} lineSyntax  a line comment prefix\n     * @param {!string} blockSyntax  a block comment prefix or suffix\n     * @return {RegExp}\n     */\n    function _createSpecialLineExp(lineSyntax, blockSyntax) {\n        var i, character, escapedCharacter,\n            subExps   = [],\n            prevChars = \"\";\n\n        for (i = lineSyntax.length; i < blockSyntax.length; i++) {\n            character = blockSyntax.charAt(i);\n            escapedCharacter = StringUtils.regexEscape(character);\n            subExps.push(prevChars + \"[^\" + escapedCharacter + \"]\");\n            if (prevChars) {\n                subExps.push(prevChars + \"$\");\n            }\n            prevChars += escapedCharacter;\n        }\n        return new RegExp(\"^\\\\s*\" + StringUtils.regexEscape(lineSyntax) + \"($|\" + subExps.join(\"|\") + \")\");\n    }\n\n    /**\n     * @private\n     * Creates regular expressions for multiple line comment prefixes\n     * @param {!Array.<string>} prefixes  the line comment prefixes\n     * @param {string=} blockPrefix  the block comment prefix\n     * @param {string=} blockSuffix  the block comment suffix\n     * @return {Array.<RegExp>}\n     */\n    function _createLineExpressions(prefixes, blockPrefix, blockSuffix) {\n        var lineExp = [], escapedPrefix, nothingPushed;\n\n        prefixes.forEach(function (prefix) {\n            escapedPrefix = StringUtils.regexEscape(prefix);\n            nothingPushed = true;\n\n            if (blockPrefix && blockPrefix.indexOf(prefix) === 0) {\n                lineExp.push(_createSpecialLineExp(prefix, blockPrefix));\n                nothingPushed = false;\n            }\n            if (blockSuffix && blockPrefix !== blockSuffix && blockSuffix.indexOf(prefix) === 0) {\n                lineExp.push(_createSpecialLineExp(prefix, blockSuffix));\n                nothingPushed = false;\n            }\n            if (nothingPushed) {\n                lineExp.push(new RegExp(\"^\\\\s*\" + escapedPrefix));\n            }\n        });\n        return lineExp;\n    }\n\n    /**\n     * @private\n     * Returns true if any regular expression matches the given string\n     * @param {!string} string  where to look\n     * @param {!Array.<RegExp>} expressions  what to look\n     * @return {boolean}\n     */\n    function _matchExpressions(string, expressions) {\n        return expressions.some(function (exp) {\n            return string.match(exp);\n        });\n    }\n\n    /**\n     * @private\n     * Returns the line comment prefix that best matches the string. Since there might be line comment prefixes\n     * that are prefixes of other line comment prefixes, it searches through all and returns the longest line\n     * comment prefix that matches the string.\n     * @param {!string} string  where to look\n     * @param {!Array.<RegExp>} expressions  the line comment regular expressions\n     * @param {!Array.<string>} prefixes  the line comment prefixes\n     * @return {string}\n     */\n    function _getLinePrefix(string, expressions, prefixes) {\n        var result = null;\n        expressions.forEach(function (exp, index) {\n            if (string.match(exp) && ((result && result.length < prefixes[index].length) || !result)) {\n                result = prefixes[index];\n            }\n        });\n        return result;\n    }\n\n    /**\n     * @private\n     * Searches between startLine and endLine to check if there is at least one line commented with a line comment, and\n     * skips all the block comments.\n     * @param {!Editor} editor\n     * @param {!number} startLine  valid line inside the document\n     * @param {!number} endLine  valid line inside the document\n     * @param {!Array.<RegExp>} lineExp  an array of line comment prefixes regular expressions\n     * @return {boolean} true if there is at least one uncommented line\n     */\n    function _containsNotLineComment(editor, startLine, endLine, lineExp) {\n        var i, line,\n            containsNotLineComment = false;\n\n        for (i = startLine; i <= endLine; i++) {\n            line = editor.document.getLine(i);\n            // A line is commented out if it starts with 0-N whitespace chars, then a line comment prefix\n            if (line.match(/\\S/) && !_matchExpressions(line, lineExp)) {\n                containsNotLineComment = true;\n                break;\n            }\n        }\n        return containsNotLineComment;\n    }\n\n    /**\n     * @private\n     * Generates an edit that adds or removes line-comment tokens to all the lines in the selected range,\n     * preserving selection and cursor position. Applies to currently focused Editor. The given selection\n     * must already be a line selection in the form returned by `Editor.convertToLineSelections()`.\n     *\n     * If all non-whitespace lines are already commented out, then we uncomment; otherwise we comment\n     * out. Commenting out adds the prefix at column 0 of every line. Uncommenting removes the first prefix\n     * on each line (if any - empty lines might not have one).\n     *\n     * @param {!Editor} editor\n     * @param {!Array.<string>} prefixes, e.g. [\"//\"]\n     * @param {string=} blockPrefix, e.g. \"<!--\"\n     * @param {string=} blockSuffix, e.g. \"-->\"\n     * @param {!Editor} editor The editor to edit within.\n     * @param {!{selectionForEdit: {start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean},\n     *           selectionsToTrack: Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>}}\n     *      lineSel A line selection as returned from `Editor.convertToLineSelections()`. `selectionForEdit` is the selection to perform\n     *      the line comment operation on, and `selectionsToTrack` are a set of selections associated with this line that need to be\n     *      tracked through the edit.\n     * @return {{edit: {text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}|Array.<{text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}>,\n     *                  selection: {start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}|\n     *                  Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}}\n     *      An edit description suitable for including in the edits array passed to `Document.doMultipleEdits()`.\n     */\n    function _getLineCommentPrefixEdit(editor, prefixes, blockPrefix, blockSuffix, lineSel) {\n        var doc         = editor.document,\n            sel         = lineSel.selectionForEdit,\n            trackedSels = lineSel.selectionsToTrack,\n            lineExp     = _createLineExpressions(prefixes, blockPrefix, blockSuffix),\n            startLine   = sel.start.line,\n            endLine     = sel.end.line,\n            editGroup   = [];\n\n        // In full-line selection, cursor pos is start of next line - but don't want to modify that line\n        if (sel.end.ch === 0) {\n            endLine--;\n        }\n\n        // Decide if we're commenting vs. un-commenting\n        // Are there any non-blank lines that aren't commented out? (We ignore blank lines because\n        // some editors like Sublime don't comment them out)\n        var i, line, prefix, commentI,\n            containsNotLineComment = _containsNotLineComment(editor, startLine, endLine, lineExp);\n\n        if (containsNotLineComment) {\n            // Comment out - prepend the first prefix to each line\n            line = doc.getLine(startLine);\n            var originalCursorPosition = line.search(/\\S|$/);\n            \n            var firstCharPosition, cursorPosition = originalCursorPosition;\n            \n            for (i = startLine; i <= endLine; i++) {\n                //check if preference for indent line comment is available otherwise go back to default indentation\n                if (Editor.getIndentLineComment()) {\n                    //ignore the first line and recalculate cursor position for first non white space char of every line\n                    if (i !== startLine) {\n                        line = doc.getLine(i);\n                        firstCharPosition = line.search(/\\S|$/);\n                    }\n                    //if the non space first character position is before original start position , put comment at the new position otherwise older pos\n                    if (firstCharPosition < originalCursorPosition) {\n                        cursorPosition = firstCharPosition;\n                    } else {\n                        cursorPosition = originalCursorPosition;\n                    }\n                    \n                    editGroup.push({text: prefixes[0], start: {line: i, ch: cursorPosition}});\n                } else {\n                    editGroup.push({text: prefixes[0], start: {line: i, ch: 0}});\n                }\n            }\n\n            // Make sure tracked selections include the prefix that was added at start of range\n            _.each(trackedSels, function (trackedSel) {\n                if (trackedSel.start.ch === 0 && CodeMirror.cmpPos(trackedSel.start, trackedSel.end) !== 0) {\n                    trackedSel.start = {line: trackedSel.start.line, ch: 0};\n                    trackedSel.end = {line: trackedSel.end.line, ch: (trackedSel.end.line === endLine ? trackedSel.end.ch + prefixes[0].length : 0)};\n                } else {\n                    trackedSel.isBeforeEdit = true;\n                }\n            });\n        } else {\n            // Uncomment - remove the prefix on each line (if any)\n            for (i = startLine; i <= endLine; i++) {\n                line   = doc.getLine(i);\n                prefix = _getLinePrefix(line, lineExp, prefixes);\n\n                if (prefix) {\n                    commentI = line.indexOf(prefix);\n                    editGroup.push({text: \"\", start: {line: i, ch: commentI}, end: {line: i, ch: commentI + prefix.length}});\n                }\n            }\n            _.each(trackedSels, function (trackedSel) {\n                trackedSel.isBeforeEdit = true;\n            });\n        }\n        return {edit: editGroup, selection: trackedSels};\n    }\n\n    /**\n     * @private\n     * Given a token context it will search backwards to determine if the given token is part of a block comment\n     * that doesn't start at the initial token. This is used to know if a line comment is part of a block comment\n     * or if a block delimiter is the prefix or suffix, by passing a token context at that position. Since the\n     * token context will be moved backwards a lot, it is better to pass a new context.\n     *\n     * @param {!{editor:{CodeMirror}, pos:{ch:{number}, line:{number}}, token:{object}}} ctx  token context\n     * @param {!string} prefix  the block comment prefix\n     * @param {!string} suffix  the block comment suffix\n     * @param {!RegExp} prefixExp  a block comment prefix regular expression\n     * @param {!RegExp} suffixExp  a block comment suffix regular expression\n     * @param {!Array.<RegExp>} lineExp  an array of line comment prefixes regular expressions\n     * @return {boolean}\n     */\n    function _isPrevTokenABlockComment(ctx, prefix, suffix, prefixExp, suffixExp, lineExp) {\n        // Start searching from the previous token\n        var result = TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx);\n\n        // Look backwards until we find a none line comment token\n        while (result && _matchExpressions(ctx.token.string, lineExp)) {\n            result = TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx);\n        }\n\n        // If we are now in a block comment token\n        if (result && ctx.token.type === \"comment\") {\n            // If it doesnt matches either prefix or suffix, we know is a block comment\n            if (!ctx.token.string.match(prefixExp) && !ctx.token.string.match(suffixExp)) {\n                return true;\n            // We found a line with just a block comment delimiter, but we can't tell which one it is, so we will\n            // keep searching recursively and return the opposite value\n            } else if (prefix === suffix && ctx.token.string.length === prefix.length) {\n                return !_isPrevTokenABlockComment(ctx, prefix, suffix, prefixExp, suffixExp, lineExp);\n            // We can just now the result by checking if the string matches the prefix\n            } else {\n                return ctx.token.string.match(prefixExp);\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Return the column of the first non whitespace char in the given line.\n     *\n     * @private\n     * @param {!Document} doc\n     * @param {number} lineNum\n     * @returns {number} the column index or null\n     */\n    function _firstNotWs(doc, lineNum) {\n        var text = doc.getLine(lineNum);\n        if (text === null || text === undefined) {\n            return 0;\n        }\n\n        return text.search(/\\S|$/);\n    }\n\n    /**\n     * Generates an edit that adds or removes block-comment tokens to the selection, preserving selection\n     * and cursor position. Applies to the currently focused Editor.\n     *\n     * If the selection is inside a block-comment or one block-comment is inside or partially inside the selection\n     * it will uncomment, otherwise it will comment out, unless if there are multiple block comments inside the selection,\n     * where it does nothing.\n     * Commenting out adds the prefix before the selection and the suffix after.\n     * Uncommenting removes them.\n     *\n     * If all the lines inside the selection are line-comment and if the selection is not inside a block-comment, it will\n     * line uncomment all the lines, otherwise it will block comment/uncomment. In the first case, we return null to\n     * indicate to the caller that it needs to handle this selection as a line comment.\n     *\n     * @param {!Editor} editor\n     * @param {!string} prefix, e.g. \"<!--\"\n     * @param {!string} suffix, e.g. \"-->\"\n     * @param {!Array.<string>} linePrefixes, e.g. [\"//\"]\n     * @param {!{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}} sel\n     *      The selection to block comment/uncomment.\n     * @param {?Array.<{!{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}}>} selectionsToTrack\n     *      An array of selections that should be tracked through this edit.\n     * @param {String} command The command callee. It cans be \"line\" or \"block\".\n     * @return {{edit: {text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}|Array.<{text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}>,\n     *                  selection: {start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}|\n     *                  Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}}\n     *      An edit description suitable for including in the edits array passed to `Document.doMultipleEdits()`.\n     */\n    function _getBlockCommentPrefixSuffixEdit(editor, prefix, suffix, linePrefixes, sel, selectionsToTrack, command) {\n        var doc            = editor.document,\n            ctx            = TokenUtils.getInitialContext(editor._codeMirror, {line: sel.start.line, ch: sel.start.ch}),\n            selEndIndex    = editor.indexFromPos(sel.end),\n            lineExp        = _createLineExpressions(linePrefixes, prefix, suffix),\n            prefixExp      = new RegExp(\"^\" + StringUtils.regexEscape(prefix), \"g\"),\n            suffixExp      = new RegExp(StringUtils.regexEscape(suffix) + \"$\", \"g\"),\n            prefixPos      = null,\n            suffixPos      = null,\n            commentAtStart = true,\n            isBlockComment = false,\n            canComment     = false,\n            invalidComment = false,\n            lineUncomment  = false,\n            result         = true,\n            editGroup      = [],\n            edit;\n\n        var searchCtx, atSuffix, suffixEnd, initialPos, endLine;\n\n        var indentLineComment = Editor.getIndentLineComment();\n\n        function isIndentLineCommand() {\n            return indentLineComment && command === \"line\";\n        }\n\n        if (!selectionsToTrack) {\n            // Track the original selection.\n            selectionsToTrack = [_.cloneDeep(sel)];\n        }\n\n        // First move the context to the first none white-space token\n        if (!ctx.token.type && !/\\S/.test(ctx.token.string)) {\n            result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx);\n        }\n\n        // Next, move forwards until we find a comment inside the selection\n        while (result && ctx.token.type !== \"comment\") {\n            result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) && editor.indexFromPos(ctx.pos) <= selEndIndex;\n            commentAtStart = false;\n        }\n\n        // We are now in a comment, lets check if it is a block or a line comment\n        if (result && ctx.token.type === \"comment\") {\n            // This token might be at a line comment, but we can't be sure yet\n            if (_matchExpressions(ctx.token.string, lineExp)) {\n                // If the token starts at ch 0 with no starting white spaces, then this might be a block comment or a line\n                // comment over the whole line, and if we found this comment at the start of the selection, we need to search\n                // backwards until we get can tell if we are in a block or a line comment\n                if (ctx.token.start === 0 && !ctx.token.string.match(/^\\\\s*/) && commentAtStart) {\n                    searchCtx      = TokenUtils.getInitialContext(editor._codeMirror, {line: ctx.pos.line, ch: ctx.token.start});\n                    isBlockComment = _isPrevTokenABlockComment(searchCtx, prefix, suffix, prefixExp, suffixExp, lineExp);\n\n                // If not, we already know that is a line comment\n                } else {\n                    isBlockComment = false;\n                }\n\n            // If it was not a line comment, it has to be a block comment\n            } else {\n                isBlockComment = true;\n\n                // If we are in a line that only has a prefix or a suffix and the prefix and suffix are the same string,\n                // lets find first if this is a prefix or suffix and move the context position to the inside of the block comment.\n                // This means that the token will be anywere inside the block comment, including the lines with the delimiters.\n                // This is required so that later we can find the prefix by moving backwards and the suffix by moving forwards.\n                if (ctx.token.string === prefix && prefix === suffix) {\n                    searchCtx = TokenUtils.getInitialContext(editor._codeMirror, {line: ctx.pos.line, ch: ctx.token.start});\n                    atSuffix  = _isPrevTokenABlockComment(searchCtx, prefix, suffix, prefixExp, suffixExp, lineExp);\n                    if (atSuffix) {\n                        TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx);\n                    } else {\n                        TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx);\n                    }\n                }\n            }\n\n            if (isBlockComment) {\n                // Save the initial position to start searching for the suffix from here\n                initialPos = _.cloneDeep(ctx.pos);\n\n                // Find the position of the start of the prefix\n                result = true;\n                while (result && !ctx.token.string.match(prefixExp)) {\n                    result = TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx);\n                }\n                prefixPos = result && {line: ctx.pos.line, ch: ctx.token.start};\n\n                // Restore the context at the initial position to find the position of the start of the suffix,\n                // but only when we found the prefix alone in one line\n                if (ctx.token.string === prefix && prefix === suffix) {\n                    ctx = TokenUtils.getInitialContext(editor._codeMirror, _.cloneDeep(initialPos));\n                }\n\n                while (result && !ctx.token.string.match(suffixExp)) {\n                    result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx);\n                }\n                suffixPos = result && {line: ctx.pos.line, ch: ctx.token.end - suffix.length};\n\n                // Lets check if there are more comments in the selection. We do nothing if there is one\n                do {\n                    result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) &&\n                        editor.indexFromPos(ctx.pos) <= selEndIndex;\n                } while (result && !ctx.token.string.match(prefixExp));\n                invalidComment = result && !!ctx.token.string.match(prefixExp);\n\n                // Make sure we didn't search so far backward or forward that we actually found a block comment\n                // that's entirely before or after the selection.\n                suffixEnd = suffixPos && { line: suffixPos.line, ch: suffixPos.ch + suffix.length };\n                if ((suffixEnd && CodeMirror.cmpPos(sel.start, suffixEnd) > 0) || (prefixPos && CodeMirror.cmpPos(sel.end, prefixPos) < 0)) {\n                    canComment = true;\n                }\n\n            } else {\n                // In full-line selection, cursor pos is at the start of next line - but don't want to modify that line\n                endLine = sel.end.line;\n                if (sel.end.ch === 0 && editor.hasSelection()) {\n                    endLine--;\n                }\n                // Find if all the lines are line-commented.\n                if (!_containsNotLineComment(editor, sel.start.line, endLine, lineExp)) {\n                    lineUncomment = true;\n                } else {\n                    canComment = true;\n                }\n            }\n        // If not, we can comment\n        } else {\n            canComment = true;\n        }\n\n\n        // Make the edit\n        if (invalidComment) {\n            // We don't want to do an edit, but we still want to track selections associated with it.\n            edit = {edit: [], selection: selectionsToTrack};\n\n        } else if (lineUncomment) {\n            // Return a null edit. This is a signal to the caller that we should delegate to the\n            // line commenting code. We don't want to just generate the edit here, because the edit\n            // might need to be coalesced with other line-uncomment edits generated by cursors on the\n            // same line.\n            edit = null;\n\n        } else {\n            // Comment out - add the suffix to the start and the prefix to the end.\n            if (canComment) {\n                var completeLineSel = sel.start.ch === 0 && sel.end.ch === 0 && sel.start.line < sel.end.line;\n                var startCh = _firstNotWs(doc, sel.start.line);\n                if (completeLineSel) {\n                    if (isIndentLineCommand()) {\n                        var endCh = _firstNotWs(doc, sel.end.line - 1);\n                        var useTabChar = Editor.getUseTabChar(editor.document.file.fullPath);\n                        var indentChar = useTabChar ? \"\\t\" : \" \";\n                        editGroup.push({\n                            text: _.repeat(indentChar, endCh) + suffix + \"\\n\",\n                            start: {line: sel.end.line, ch: 0}\n                        });\n                        editGroup.push({\n                            text: prefix + \"\\n\" + _.repeat(indentChar, startCh),\n                            start: {line: sel.start.line, ch: startCh}\n                        });\n                    } else {\n                        editGroup.push({text: suffix + \"\\n\", start: sel.end});\n                        editGroup.push({text: prefix + \"\\n\", start: sel.start});\n                    }\n                } else {\n                    editGroup.push({text: suffix, start: sel.end});\n                    if (isIndentLineCommand()) {\n                        editGroup.push({text: prefix, start: { line: sel.start.line, ch: startCh }});\n                    } else {\n                        editGroup.push({text: prefix, start: sel.start});\n                    }\n                }\n\n                // Correct the tracked selections. We can't just use the default selection fixup,\n                // because it will push the end of the selection past the inserted content. Also,\n                // it's possible that we have to deal with tracked selections that might be outside\n                // the bounds of the edit.\n                _.each(selectionsToTrack, function (trackedSel) {\n                    function updatePosForEdit(pos) {\n                        // First adjust for the suffix insertion. Don't adjust\n                        // positions that are exactly at the suffix insertion point.\n                        if (CodeMirror.cmpPos(pos, sel.end) > 0) {\n                            if (completeLineSel) {\n                                pos.line++;\n                            } else if (pos.line === sel.end.line) {\n                                pos.ch += suffix.length;\n                            }\n                        }\n                        // Now adjust for the prefix insertion. In this case, we do\n                        // want to adjust positions that are exactly at the insertion\n                        // point.\n                        if (CodeMirror.cmpPos(pos, sel.start) >= 0) {\n                            if (completeLineSel) {\n                                // Just move the line down.\n                                pos.line++;\n                            } else if (pos.line === sel.start.line && !(isIndentLineCommand() && pos.ch < startCh)) {\n                                pos.ch += prefix.length;\n                            }\n                        }\n                    }\n\n                    updatePosForEdit(trackedSel.start);\n                    updatePosForEdit(trackedSel.end);\n                });\n\n            // Uncomment - remove prefix and suffix.\n            } else {\n                // Find if the prefix and suffix are at the ch 0 and if they are the only thing in the line.\n                // If both are found we assume that a complete line selection comment added new lines, so we remove them.\n                var line          = doc.getLine(prefixPos.line).trim(),\n                    prefixAtStart = prefixPos.ch === 0 && prefix.length === line.length,\n                    prefixIndented = indentLineComment && prefix.length === line.length,\n                    suffixAtStart = false,\n                    suffixIndented = false;\n\n                if (suffixPos) {\n                    line = doc.getLine(suffixPos.line).trim();\n                    suffixAtStart = suffixPos.ch === 0 && suffix.length === line.length;\n                    suffixIndented = indentLineComment && suffix.length === line.length;\n                }\n\n                // Remove the suffix if there is one\n                if (suffixPos) {\n                    if (suffixIndented) {\n                        editGroup.push({text: \"\", start: {line: suffixPos.line, ch: 0}, end: {line: suffixPos.line + 1, ch: 0}});\n                    } else if (prefixAtStart && suffixAtStart) {\n                        editGroup.push({text: \"\", start: suffixPos, end: {line: suffixPos.line + 1, ch: 0}});\n                    } else {\n                        editGroup.push({text: \"\", start: suffixPos, end: {line: suffixPos.line, ch: suffixPos.ch + suffix.length}});\n                    }\n                }\n\n                // Remove the prefix\n                if (prefixIndented) {\n                    editGroup.push({text: \"\", start: {line: prefixPos.line, ch: 0}, end: {line: prefixPos.line + 1, ch: 0}});\n                } else if (prefixAtStart && suffixAtStart) {\n                    editGroup.push({text: \"\", start: prefixPos, end: {line: prefixPos.line + 1, ch: 0}});\n                } else {\n                    editGroup.push({text: \"\", start: prefixPos, end: {line: prefixPos.line, ch: prefixPos.ch + prefix.length}});\n                }\n\n                // Don't fix up the tracked selections here - let the edit fix them up.\n                _.each(selectionsToTrack, function (trackedSel) {\n                    trackedSel.isBeforeEdit = true;\n                });\n            }\n\n            edit = {edit: editGroup, selection: selectionsToTrack};\n        }\n\n        return edit;\n    }\n\n\n    /**\n     * Generates an edit that adds or removes block-comment tokens to the selection, preserving selection\n     * and cursor position. Applies to the currently focused Editor. The selection must already be a\n     * line selection in the form returned by `Editor.convertToLineSelections()`.\n     *\n     * The implementation uses blockCommentPrefixSuffix, with the exception of the case where\n     * there is no selection on a uncommented and not empty line. In this case the whole lines gets\n     * commented in a block-comment.\n     *\n     * @param {!Editor} editor\n     * @param {!String} prefix\n     * @param {!String} suffix\n     * @param {!{selectionForEdit: {start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean},\n     *           selectionsToTrack: Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, reversed:boolean, primary:boolean}>}}\n     *      lineSel A line selection as returned from `Editor.convertToLineSelections()`. `selectionForEdit` is the selection to perform\n     *      the line comment operation on, and `selectionsToTrack` are a set of selections associated with this line that need to be\n     *      tracked through the edit.\n     * @param {String} command The command callee. It cans be \"line\" or \"block\".\n     * @return {{edit: {text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}|Array.<{text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}>,\n     *                  selection: {start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}|\n     *                  Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}}\n     *      An edit description suitable for including in the edits array passed to `Document.doMultipleEdits()`.\n     */\n    function _getLineCommentPrefixSuffixEdit(editor, prefix, suffix, lineSel, command) {\n        var sel = lineSel.selectionForEdit;\n\n        // For one-line selections, we shrink the selection to exclude the trailing newline.\n        if (sel.end.line === sel.start.line + 1 && sel.end.ch === 0) {\n            sel.end = {line: sel.start.line, ch: editor.document.getLine(sel.start.line).length};\n        }\n\n        // Now just run the standard block comment code, but make sure to track any associated selections\n        // that were subsumed into this line selection.\n        return _getBlockCommentPrefixSuffixEdit(editor, prefix, suffix, [], sel, lineSel.selectionsToTrack, command);\n    }\n\n    /**\n     * @private\n     * Generates an array of edits for toggling line comments on the given selections.\n     *\n     * @param {!Editor} editor The editor to edit within.\n     * @param {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}\n     *      selections The selections we want to line-comment.\n     * @param {String} command The command callee. It cans be \"line\" or \"block\".\n     * @return {Array.<{edit: {text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}|Array.<{text: string, start:{line: number, ch: number}, end:?{line: number, ch: number}}>,\n     *                  selection: {start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}|\n     *                  Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean, isBeforeEdit: boolean}>}>}\n     *      An array of edit descriptions suitable for including in the edits array passed to `Document.doMultipleEdits()`.\n     */\n    function _getLineCommentEdits(editor, selections, command) {\n        // We need to expand line selections in order to coalesce cursors on the same line, but we\n        // don't want to merge adjacent line selections.\n        var lineSelections = editor.convertToLineSelections(selections, { mergeAdjacent: false }),\n            edits = [];\n        _.each(lineSelections, function (lineSel) {\n            var sel = lineSel.selectionForEdit,\n                mode = editor.getModeForRange(sel.start, sel.end),\n                edit;\n            if (mode) {\n                var language = editor.document.getLanguage().getLanguageForMode(mode.name || mode);\n\n                if (language.hasLineCommentSyntax()) {\n                    edit = _getLineCommentPrefixEdit(editor, language.getLineCommentPrefixes(), language.getBlockCommentPrefix(), language.getBlockCommentSuffix(), lineSel);\n                } else if (language.hasBlockCommentSyntax()) {\n                    edit = _getLineCommentPrefixSuffixEdit(editor, language.getBlockCommentPrefix(), language.getBlockCommentSuffix(), lineSel, command);\n                }\n            }\n            if (!edit) {\n                // Even if we didn't want to do an edit, we still need to track the selection.\n                edit = {selection: lineSel.selectionsToTrack};\n            }\n            edits.push(edit);\n        });\n        return edits;\n    }\n\n    /**\n     * Invokes a language-specific line-comment/uncomment handler\n     * @param {?Editor} editor If unspecified, applies to the currently focused editor\n     */\n    function lineComment(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        editor.setSelections(editor.document.doMultipleEdits(_getLineCommentEdits(editor, editor.getSelections(), \"line\")));\n    }\n\n    /**\n     * Invokes a language-specific block-comment/uncomment handler\n     * @param {?Editor} editor If unspecified, applies to the currently focused editor\n     */\n    function blockComment(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        var edits = [],\n            lineCommentSels = [];\n        _.each(editor.getSelections(), function (sel) {\n            var mode = editor.getModeForRange(sel.start, sel.end),\n                edit = {edit: [], selection: [sel]}; // default edit in case we don't have a mode for this selection\n            if (mode) {\n                var language = editor.document.getLanguage().getLanguageForMode(mode.name || mode);\n\n                if (language.hasBlockCommentSyntax()) {\n                    // getLineCommentPrefixes always return an array, and will be empty if no line comment syntax is defined\n                    edit = _getBlockCommentPrefixSuffixEdit(editor, language.getBlockCommentPrefix(), language.getBlockCommentSuffix(),\n                                                            language.getLineCommentPrefixes(), sel);\n                    if (!edit) {\n                        // This is only null if the block comment code found that the selection is within a line-commented line.\n                        // Add this to the list of line-comment selections we need to handle. Since edit is null, we'll skip\n                        // pushing anything onto the edit list for this selection.\n                        lineCommentSels.push(sel);\n                    }\n                }\n            }\n            if (edit) {\n                edits.push(edit);\n            }\n        });\n\n        // Handle any line-comment edits. It's okay if these are out-of-order with the other edits, since\n        // they shouldn't overlap, and `doMultipleEdits()` will take care of sorting the edits so the\n        // selections can be tracked appropriately.\n        edits.push.apply(edits, _getLineCommentEdits(editor, lineCommentSels, \"block\"));\n\n        editor.setSelections(editor.document.doMultipleEdits(edits));\n    }\n\n    /**\n     * Duplicates the selected text, or current line if no selection. The cursor/selection is left\n     * on the second copy.\n     */\n    function duplicateText(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        var selections = editor.getSelections(),\n            delimiter = \"\",\n            edits = [],\n            rangeSels = [],\n            cursorSels = [],\n            doc = editor.document;\n\n        // When there are multiple selections, we want to handle all the cursors first (duplicating\n        // their lines), then all the ranges (duplicating the ranges).\n        _.each(selections, function (sel) {\n            if (CodeMirror.cmpPos(sel.start, sel.end) === 0) {\n                cursorSels.push(sel);\n            } else {\n                rangeSels.push(sel);\n            }\n        });\n\n        var cursorLineSels = editor.convertToLineSelections(cursorSels);\n        _.each(cursorLineSels, function (lineSel, index) {\n            var sel = lineSel.selectionForEdit;\n            if (sel.end.line === editor.lineCount()) {\n                delimiter = \"\\n\";\n            }\n            // Don't need to explicitly track selections since we are doing the edits in such a way that\n            // the existing selections will get appropriately updated.\n            edits.push({edit: {text: doc.getRange(sel.start, sel.end) + delimiter, start: sel.start }});\n        });\n        _.each(rangeSels, function (sel) {\n            edits.push({edit: {text: doc.getRange(sel.start, sel.end), start: sel.start }});\n        });\n\n        doc.doMultipleEdits(edits);\n    }\n\n    /**\n     * Deletes the current line if there is no selection or the lines for the selection\n     * (removing the end of line too)\n     */\n    function deleteCurrentLines(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        // Walk the selections, calculating the deletion edits we need to do as we go;\n        // document.doMultipleEdits() will take care of adjusting the edit locations when\n        // it actually performs the edits.\n        var doc = editor.document,\n            from,\n            to,\n            lineSelections = editor.convertToLineSelections(editor.getSelections()),\n            edits = [];\n\n        _.each(lineSelections, function (lineSel, index) {\n            var sel = lineSel.selectionForEdit;\n\n            from = sel.start;\n            to = sel.end; // this is already at the beginning of the line after the last selected line\n            if (to.line === editor.getLastVisibleLine() + 1) {\n                // Instead of deleting the newline after the last line, delete the newline\n                // before the beginning of the line--unless this is the entire visible content\n                // of the editor, in which case just delete the line content.\n                if (from.line > editor.getFirstVisibleLine()) {\n                    from.line -= 1;\n                    from.ch = doc.getLine(from.line).length;\n                }\n                to.line -= 1;\n                to.ch = doc.getLine(to.line).length;\n            }\n\n            // We don't need to track the original selections, since they'll get collapsed as\n            // part of the various deletions that occur.\n            edits.push({edit: {text: \"\", start: from, end: to}});\n        });\n        doc.doMultipleEdits(edits);\n    }\n\n    /**\n     * Moves the selected text, or current line if no selection. The cursor/selection\n     * moves with the line/lines.\n     * @param {Editor} editor - target editor\n     * @param {Number} direction - direction of the move (-1,+1) => (Up,Down)\n     */\n    function moveLine(editor, direction) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        var doc             = editor.document,\n            lineSelections  = editor.convertToLineSelections(editor.getSelections()),\n            isInlineWidget  = !!EditorManager.getFocusedInlineWidget(),\n            firstLine       = editor.getFirstVisibleLine(),\n            lastLine        = editor.getLastVisibleLine(),\n            totalLines      = editor.lineCount(),\n            lineLength      = 0,\n            edits           = [],\n            newSels         = [],\n            pos             = {};\n\n        _.each(lineSelections, function (lineSel) {\n            var sel = lineSel.selectionForEdit,\n                editGroup = [];\n\n            // Make the move\n            switch (direction) {\n            case DIRECTION_UP:\n                if (sel.start.line !== firstLine) {\n                    var prevText = doc.getRange({ line: sel.start.line - 1, ch: 0 }, sel.start);\n\n                    if (sel.end.line === lastLine + 1) {\n                        if (isInlineWidget) {\n                            prevText   = prevText.substring(0, prevText.length - 1);\n                            lineLength = doc.getLine(sel.end.line - 1).length;\n                            editGroup.push({text: \"\\n\", start: { line: sel.end.line - 1, ch: lineLength }});\n                        } else {\n                            prevText = \"\\n\" + prevText.substring(0, prevText.length - 1);\n                        }\n                    }\n\n                    editGroup.push({text: \"\", start: { line: sel.start.line - 1, ch: 0 }, end: sel.start});\n                    editGroup.push({text: prevText, start: { line: sel.end.line - 1, ch: 0 }});\n\n                    // Make sure CodeMirror hasn't expanded the selection to include\n                    // the line we inserted below.\n                    _.each(lineSel.selectionsToTrack, function (originalSel) {\n                        originalSel.start.line--;\n                        originalSel.end.line--;\n                    });\n\n                    edits.push({edit: editGroup, selection: lineSel.selectionsToTrack});\n                }\n                break;\n            case DIRECTION_DOWN:\n                if (sel.end.line <= lastLine) {\n                    var nextText      = doc.getRange(sel.end, { line: sel.end.line + 1, ch: 0 }),\n                        deletionStart = sel.end;\n\n                    if (sel.end.line === lastLine) {\n                        if (isInlineWidget) {\n                            if (sel.end.line === totalLines - 1) {\n                                nextText += \"\\n\";\n                            }\n                            lineLength = doc.getLine(sel.end.line - 1).length;\n                            editGroup.push({text: \"\\n\", start: { line: sel.end.line, ch: doc.getLine(sel.end.line).length }});\n                        } else {\n                            nextText     += \"\\n\";\n                            deletionStart = { line: sel.end.line - 1, ch: doc.getLine(sel.end.line - 1).length };\n                        }\n                    }\n\n                    editGroup.push({text: \"\", start: deletionStart, end: { line: sel.end.line + 1, ch: 0 }});\n                    if (lineLength) {\n                        editGroup.push({text: \"\", start: { line: sel.end.line - 1, ch: lineLength }, end: { line: sel.end.line, ch: 0 }});\n                    }\n                    editGroup.push({text: nextText, start: { line: sel.start.line, ch: 0 }});\n\n                    // In this case, we don't need to track selections, because the edits are done in such a way that\n                    // the existing selections will automatically be updated properly by CodeMirror as it does the edits.\n                    edits.push({edit: editGroup});\n                }\n                break;\n            }\n        });\n\n        // Make sure selections are correct and primary selection is scrolled into view\n        if (edits.length) {\n            newSels = doc.doMultipleEdits(edits);\n\n            pos.ch = 0;\n\n            if (direction === DIRECTION_UP) {\n                editor.setSelections(newSels);\n                pos.line = editor.getSelection().start.line;\n            } else if (direction === DIRECTION_DOWN) {\n                pos.line = editor.getSelection().end.line;\n            } else {\n                console.error(\"EditorCommandHandler.moveLine() called with invalid argument 'direction' = %d\", direction);\n                pos = null;\n            }\n\n            editor._codeMirror.scrollIntoView(pos);\n        }\n    }\n\n    /**\n     * Moves the selected text, or current line if no selection, one line up. The cursor/selection\n     * moves with the line/lines.\n     */\n    function moveLineUp(editor) {\n        moveLine(editor, DIRECTION_UP);\n    }\n\n    /**\n     * Moves the selected text, or current line if no selection, one line down. The cursor/selection\n     * moves with the line/lines.\n     */\n    function moveLineDown(editor) {\n        moveLine(editor, DIRECTION_DOWN);\n    }\n\n    /**\n     * Inserts a new and smart indented line above/below the selected text, or current line if no selection.\n     * The cursor is moved in the new line.\n     * @param {Editor} editor - target editor\n     * @param {Number} direction - direction where to place the new line (-1,+1) => (Up,Down)\n     */\n    function openLine(editor, direction) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        var selections     = editor.getSelections(),\n            isInlineWidget = !!EditorManager.getFocusedInlineWidget(),\n            lastLine       = editor.getLastVisibleLine(),\n            doc            = editor.document,\n            edits          = [],\n            newSelections,\n            line;\n\n        // First, insert all the newlines (skipping multiple selections on the same line),\n        // then indent them all. (We can't easily do them all at once, because doMultipleEdits()\n        // won't do the indentation for us, but we want its help tracking any selection changes\n        // as the result of the edits.)\n\n        // Note that we don't just use `editor.getLineSelections()` here because we don't actually want\n        // to coalesce adjacent selections - we just want to ignore dupes.\n\n        doc.batchOperation(function () {\n            _.each(selections, function (sel, index) {\n                if (index === 0 ||\n                        (direction === DIRECTION_UP && sel.start.line > selections[index - 1].start.line) ||\n                        (direction === DIRECTION_DOWN && sel.end.line > selections[index - 1].end.line)) {\n                    // Insert the new line\n                    switch (direction) {\n                    case DIRECTION_UP:\n                        line = sel.start.line;\n                        break;\n                    case DIRECTION_DOWN:\n                        line = sel.end.line;\n                        if (!(CodeMirror.cmpPos(sel.start, sel.end) !== 0 && sel.end.ch === 0)) {\n                            // If not linewise selection\n                            line++;\n                        }\n                        break;\n                    }\n\n                    var insertPos;\n                    if (line > lastLine && isInlineWidget) {\n                        insertPos = {line: line - 1, ch: doc.getLine(line - 1).length};\n                    } else {\n                        insertPos = {line: line, ch: 0};\n                    }\n                    // We want the selection after this edit to be right before the \\n we just inserted.\n                    edits.push({edit: {text: \"\\n\", start: insertPos}, selection: {start: insertPos, end: insertPos, primary: sel.primary}});\n                } else {\n                    // We just want to discard this selection, since we've already operated on the\n                    // same line and it would just collapse to the same location. But if this was\n                    // primary, make sure the last selection we did operate on ends up as primary.\n                    if (sel.primary) {\n                        edits[edits.length - 1].selections[0].primary = true;\n                    }\n                }\n            });\n            newSelections = doc.doMultipleEdits(edits, \"+input\");\n\n            // Now indent each added line (which doesn't mess up any line numbers, and\n            // we're going to set the character offset to the last position on each line anyway).\n            _.each(newSelections, function (sel) {\n                // This is a bit of a hack. The document is the one that batches operations, but we want\n                // to use CodeMirror's \"smart indent\" operation. So we need to use the document's own backing editor's\n                // CodeMirror to do the indentation. A better way to fix this would be to expose this\n                // operation on Document, but I'm not sure we want to sign up for that as a public API.\n                doc._masterEditor._codeMirror.indentLine(sel.start.line, \"smart\", true);\n                sel.start.ch = null; // last character on line\n                sel.end = sel.start;\n            });\n        });\n        editor.setSelections(newSelections);\n    }\n\n    /**\n     * Inserts a new and smart indented line above the selected text, or current line if no selection.\n     * The cursor is moved in the new line.\n     * @param {Editor} editor - target editor\n     */\n    function openLineAbove(editor) {\n        openLine(editor, DIRECTION_UP);\n    }\n\n    /**\n     * Inserts a new and smart indented line below the selected text, or current line if no selection.\n     * The cursor is moved in the new line.\n     * @param {Editor} editor - target editor\n     */\n    function openLineBelow(editor) {\n        openLine(editor, DIRECTION_DOWN);\n    }\n\n    /**\n     * Indent a line of text if no selection. Otherwise, indent all lines in selection.\n     */\n    function indentText() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        editor._codeMirror.execCommand(\"indentMore\");\n    }\n\n    /**\n     * Unindent a line of text if no selection. Otherwise, unindent all lines in selection.\n     */\n    function unindentText() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        editor._codeMirror.execCommand(\"indentLess\");\n    }\n\n    function selectLine(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (editor) {\n            // We can just use `convertToLineSelections`, but throw away the original tracked selections and just use the\n            // coalesced selections.\n            editor.setSelections(_.pluck(editor.convertToLineSelections(editor.getSelections(), { expandEndAtStartOfLine: true }), \"selectionForEdit\"));\n        }\n    }\n\n    /**\n     * @private\n     * Takes the current selection and splits each range into separate selections, one per line.\n     * @param {!Editor} editor The editor to operate on.\n     */\n    function splitSelIntoLines(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (editor) {\n            editor._codeMirror.execCommand(\"splitSelectionByLine\");\n        }\n    }\n\n    /**\n     * @private\n     * Adds a cursor on the next/previous line after/before each selected range to the selection.\n     * @param {!Editor} editor The editor to operate on.\n     * @param {number} dir The direction to add - 1 is down, -1 is up.\n     */\n    function addCursorToSelection(editor, dir) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (editor) {\n            var origSels = editor.getSelections(),\n                newSels = [];\n            _.each(origSels, function (sel) {\n                var pos, colOffset;\n                if ((dir === -1 && sel.start.line > editor.getFirstVisibleLine()) || (dir === 1 && sel.end.line < editor.getLastVisibleLine())) {\n                    // Add a new cursor on the next line up/down. It's okay if it overlaps another selection, because CM\n                    // will take care of throwing it away in that case. It will also take care of clipping the char position\n                    // to the end of the new line if the line is shorter.\n                    pos = _.clone(dir === -1 ? sel.start : sel.end);\n\n                    // get sel column of current selection\n                    colOffset = editor.getColOffset(pos);\n\n                    pos.line += dir;\n\n                    // translate column to ch in line of new selection\n                    pos.ch = editor.getCharIndexForColumn(pos.line, colOffset);\n\n\n                    // If this is the primary selection, we want the new cursor we're adding to become the\n                    // primary selection.\n                    newSels.push({start: pos, end: pos, primary: sel.primary});\n                    sel.primary = false;\n                }\n            });\n            // CM will take care of sorting the selections.\n            editor.setSelections(origSels.concat(newSels));\n        }\n    }\n\n    /**\n     * @private\n     * Adds a cursor on the previous line before each selected range to the selection.\n     * @param {!Editor} editor The editor to operate on.\n     */\n    function addCursorToPrevLine(editor) {\n        addCursorToSelection(editor, -1);\n    }\n\n    /**\n     * @private\n     * Adds a cursor on the next line after each selected range to the selection.\n     * @param {!Editor} editor The editor to operate on.\n     */\n    function addCursorToNextLine(editor) {\n        addCursorToSelection(editor, 1);\n    }\n\n    function handleUndoRedo(operation) {\n        var editor = EditorManager.getFocusedEditor();\n        var result = new $.Deferred();\n\n        if (editor) {\n            editor[operation]();\n            result.resolve();\n        } else {\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n    function handleUndo() {\n        return handleUndoRedo(\"undo\");\n    }\n\n    function handleRedo() {\n        return handleUndoRedo(\"redo\");\n    }\n\n    function _handleSelectAll() {\n        var result = new $.Deferred(),\n            editor = EditorManager.getFocusedEditor();\n\n        if (editor) {\n            editor.selectAllNoScroll();\n            result.resolve();\n        } else {\n            result.reject();    // command not handled\n        }\n\n        return result.promise();\n    }\n\n    function _execCommand(cmd) {\n        window.document.execCommand(cmd);\n    }\n    function _execCommandCut() {\n        _execCommand(\"cut\");\n    }\n    function _execCommandCopy() {\n        _execCommand(\"copy\");\n    }\n    function _execCommandPaste() {\n        _execCommand(\"paste\");\n    }\n\n    // Register commands\n    CommandManager.register(Strings.CMD_INDENT,                 Commands.EDIT_INDENT,                 indentText);\n    CommandManager.register(Strings.CMD_UNINDENT,               Commands.EDIT_UNINDENT,               unindentText);\n    CommandManager.register(Strings.CMD_COMMENT,                Commands.EDIT_LINE_COMMENT,           lineComment);\n    CommandManager.register(Strings.CMD_BLOCK_COMMENT,          Commands.EDIT_BLOCK_COMMENT,          blockComment);\n    CommandManager.register(Strings.CMD_DUPLICATE,              Commands.EDIT_DUPLICATE,              duplicateText);\n    CommandManager.register(Strings.CMD_DELETE_LINES,           Commands.EDIT_DELETE_LINES,           deleteCurrentLines);\n    CommandManager.register(Strings.CMD_LINE_UP,                Commands.EDIT_LINE_UP,                moveLineUp);\n    CommandManager.register(Strings.CMD_LINE_DOWN,              Commands.EDIT_LINE_DOWN,              moveLineDown);\n    CommandManager.register(Strings.CMD_OPEN_LINE_ABOVE,        Commands.EDIT_OPEN_LINE_ABOVE,        openLineAbove);\n    CommandManager.register(Strings.CMD_OPEN_LINE_BELOW,        Commands.EDIT_OPEN_LINE_BELOW,        openLineBelow);\n    CommandManager.register(Strings.CMD_SELECT_LINE,            Commands.EDIT_SELECT_LINE,            selectLine);\n    CommandManager.register(Strings.CMD_SPLIT_SEL_INTO_LINES,   Commands.EDIT_SPLIT_SEL_INTO_LINES,   splitSelIntoLines);\n    CommandManager.register(Strings.CMD_ADD_CUR_TO_NEXT_LINE,   Commands.EDIT_ADD_CUR_TO_NEXT_LINE,   addCursorToNextLine);\n    CommandManager.register(Strings.CMD_ADD_CUR_TO_PREV_LINE,   Commands.EDIT_ADD_CUR_TO_PREV_LINE,   addCursorToPrevLine);\n\n    CommandManager.register(Strings.CMD_UNDO,                   Commands.EDIT_UNDO,                   handleUndo);\n    CommandManager.register(Strings.CMD_REDO,                   Commands.EDIT_REDO,                   handleRedo);\n    CommandManager.register(Strings.CMD_CUT,                    Commands.EDIT_CUT,                    _execCommandCut);\n    CommandManager.register(Strings.CMD_COPY,                   Commands.EDIT_COPY,                   _execCommandCopy);\n    CommandManager.register(Strings.CMD_PASTE,                  Commands.EDIT_PASTE,                  _execCommandPaste);\n    CommandManager.register(Strings.CMD_SELECT_ALL,             Commands.EDIT_SELECT_ALL,             _handleSelectAll);\n});\n"
  },
  {
    "path": "src/editor/EditorManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * EditorManager owns the UI for the editor area. This essentially mirrors the 'current document'\n * property maintained by DocumentManager's model.\n *\n * Note that there is a little bit of unusual overlap between EditorManager and DocumentManager:\n * because the Document state is actually stored in the CodeMirror editor UI, DocumentManager is\n * not a pure headless model. Each Document encapsulates an editor instance, and thus EditorManager\n * must have some knowledge about Document's internal state (we access its _editor property).\n *\n * This module dispatches the following events:\n *    - activeEditorChange --  Fires after the active editor (full or inline).\n *\n *      Doesn't fire when editor temporarily loses focus to a non-editor\n *      control (e.g. search toolbar or modal dialog, or window deactivation).\n *\n *      Does fire when focus moves between inline editor and its full-size container.\n *\n *      This event tracks `MainViewManagers's `currentFileChange` event and all editor\n *      objects \"focus\" event.\n *\n *          (e, editorGainingFocus:editor, editorLosingFocus:editor)\n *\n *      The 2nd arg to the listener is which Editor became active; the 3rd arg is\n *      which Editor is deactivated as a result. Either one may be null.\n *      NOTE (#1257): `getFocusedEditor()` sometimes lags behind this event. Listeners\n *      should use the arguments or call `getActiveEditor()` to reliably see which Editor\n *      just gained focus.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var Commands            = require(\"command/Commands\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        WorkspaceManager    = require(\"view/WorkspaceManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        ViewStateManager    = require(\"view/ViewStateManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Editor              = require(\"editor/Editor\").Editor,\n        InlineTextEditor    = require(\"editor/InlineTextEditor\").InlineTextEditor,\n        Strings             = require(\"strings\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\");\n\n\n    /**\n     * Currently focused Editor (full-size, inline, or otherwise)\n     * @type {?Editor}\n     * @private\n     */\n    var _lastFocusedEditor = null;\n\n    /**\n     * Registered inline-editor widget providers sorted descending by priority.\n     * @see {@link #registerInlineEditProvider}.\n     * @type {Array.<{priority:number, provider:function(...)}>}\n     * @private\n     */\n    var _inlineEditProviders = [];\n\n    /**\n     * Registered inline documentation widget providers sorted descending by priority.\n     * @see {@link #registerInlineDocsProvider}.\n     * @type {Array.<{priority:number, provider:function(...)}>}\n     * @private\n     */\n    var _inlineDocsProviders = [];\n\n    /**\n     * DOM element to house any hidden editors created soley for inline widgets\n     * @private\n     * @type {jQuery}\n     */\n    var _$hiddenEditorsContainer;\n\n\n    /**\n     * Retrieves the visible full-size Editor for the currently opened file in the ACTIVE_PANE\n     * @return {?Editor} editor of the current view or null\n     */\n    function getCurrentFullEditor() {\n        var currentPath = MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE),\n            doc = currentPath && DocumentManager.getOpenDocumentForPath(currentPath);\n        return doc && doc._masterEditor;\n    }\n\n\n\n    /**\n     * Updates _viewStateCache from the given editor's actual current state\n     * @private\n     * @param {!Editor} editor - editor to cache data for\n     */\n    function _saveEditorViewState(editor) {\n        ViewStateManager.updateViewState(editor);\n    }\n\n    /**\n     * Updates _viewStateCache from the given editor's actual current state\n     * @param {!Editor} editor - editor restore cached data\n     * @private\n     */\n    function _restoreEditorViewState(editor) {\n        // We want to ignore the current state of the editor, so don't call __getViewState()\n        var viewState = ViewStateManager.getViewState(editor.document.file);\n        if (viewState) {\n            editor.restoreViewState(viewState);\n        }\n    }\n\n\n\t/**\n     * Editor focus handler to change the currently active editor\n     * @private\n     * @param {?Editor} current - the editor that will be the active editor\n     */\n    function _notifyActiveEditorChanged(current) {\n        // Skip if the Editor that gained focus was already the most recently focused editor.\n        // This may happen e.g. if the window loses then regains focus.\n        if (_lastFocusedEditor === current) {\n            return;\n        }\n        var previous = _lastFocusedEditor;\n        _lastFocusedEditor = current;\n\n        exports.trigger(\"activeEditorChange\", current, previous);\n    }\n\n    /**\n     * Current File Changed handler\n     * MainViewManager dispatches a \"currentFileChange\" event whenever the currently viewed\n     * file changes.  Which could mean that the previously viewed file has been closed or a\n     * non-editor view (image) has been given focus.  _notifyAcitveEditorChanged is also hooked\n     * up to editor.focus to handle focus events for editors which handles changing focus between\n     * two editors but, because editormanager maintains  a \"_lastFocusedEditor\" state, we have to\n     * \"nullify\" that state whenever the focus goes to a non-editor or when the current editor is closed\n     * @private\n     * @param {!jQuery.Event} e - event\n     * @param {?File} file - current file (can be null)\n     */\n    function _handleCurrentFileChange(e, file) {\n        var doc = file && DocumentManager.getOpenDocumentForPath(file.fullPath);\n        _notifyActiveEditorChanged(doc && doc._masterEditor);\n    }\n\n    /**\n     * Creates a new Editor bound to the given Document.\n     * The editor is appended to the given container as a visible child.\n     * @private\n     * @param {!Document} doc  Document for the Editor's content\n     * @param {!boolean} makeMasterEditor  If true, the Editor will set itself as the private \"master\"\n     *          Editor for the Document. If false, the Editor will attach to the Document as a \"slave.\"\n     * @param {!jQueryObject} container  Container to add the editor to.\n     * @param {{startLine: number, endLine: number}=} range If specified, range of lines within the document\n     *          to display in this editor. Inclusive.\n     * @param {!Object} editorOptions If specified, contains editor options that can be passed to CodeMirror\n     * @return {Editor} the newly created editor.\n     */\n    function _createEditorForDocument(doc, makeMasterEditor, container, range, editorOptions) {\n        var editor = new Editor(doc, makeMasterEditor, container, range, editorOptions);\n\n        editor.on(\"focus\", function () {\n            _notifyActiveEditorChanged(editor);\n        });\n\n        editor.on(\"beforeDestroy\", function () {\n            if (editor.$el.is(\":visible\")) {\n                _saveEditorViewState(editor);\n            }\n        });\n\n        return editor;\n    }\n\n    /**\n     * @private\n     * Finds an inline widget provider from the given list that can offer a widget for the current cursor\n     * position, and once the widget has been created inserts it into the editor.\n     *\n     * @param {!Editor} editor The host editor\n     * @param {Array.<{priority:number, provider:function(...)}>} providers\n     *      prioritized list of providers\n     * @param {string=} defaultErrorMsg Default message to display if no providers return non-null\n     * @return {$.Promise} a promise that will be resolved when an InlineWidget\n     *      is created or rejected if no inline providers have offered one.\n     */\n    function _openInlineWidget(editor, providers, defaultErrorMsg) {\n        PerfUtils.markStart(PerfUtils.INLINE_WIDGET_OPEN);\n\n        // Run through inline-editor providers until one responds\n        var pos = editor.getCursorPos(),\n            inlinePromise,\n            i,\n            result = new $.Deferred(),\n            errorMsg,\n            providerRet;\n\n        // Query each provider in priority order. Provider may return:\n        // 1. `null` to indicate it does not apply to current cursor position\n        // 2. promise that should resolve to an InlineWidget\n        // 3. string which indicates provider does apply to current cursor position,\n        //    but reason it could not create InlineWidget\n        //\n        // Keep looping until a provider is found. If a provider is not found,\n        // display the highest priority error message that was found, otherwise display\n        // default error message\n        for (i = 0; i < providers.length && !inlinePromise; i++) {\n            var provider = providers[i].provider;\n            providerRet = provider(editor, pos);\n            if (providerRet) {\n                if (providerRet.hasOwnProperty(\"done\")) {\n                    inlinePromise = providerRet;\n                } else if (!errorMsg && typeof (providerRet) === \"string\") {\n                    errorMsg = providerRet;\n                }\n            }\n        }\n\n        // Use default error message if none other provided\n        errorMsg = errorMsg || defaultErrorMsg;\n\n        // If one of them will provide a widget, show it inline once ready\n        if (inlinePromise) {\n            inlinePromise.done(function (inlineWidget) {\n                editor.addInlineWidget(pos, inlineWidget).done(function () {\n                    PerfUtils.addMeasurement(PerfUtils.INLINE_WIDGET_OPEN);\n                    result.resolve();\n                });\n            }).fail(function () {\n                // terminate timer that was started above\n                PerfUtils.finalizeMeasurement(PerfUtils.INLINE_WIDGET_OPEN);\n                editor.displayErrorMessageAtCursor(errorMsg);\n                result.reject();\n            });\n        } else {\n            // terminate timer that was started above\n            PerfUtils.finalizeMeasurement(PerfUtils.INLINE_WIDGET_OPEN);\n            editor.displayErrorMessageAtCursor(errorMsg);\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n\n    /**\n     * Closes any focused inline widget. Else, asynchronously asks providers to create one.\n     *\n     * @param {Array.<{priority:number, provider:function(...)}>} providers\n     *   prioritized list of providers\n     * @param {string=} errorMsg Default message to display if no providers return non-null\n     * @return {!Promise} A promise resolved with true if an inline widget is opened or false\n     *   when closed. Rejected if there is neither an existing widget to close nor a provider\n     *   willing to create a widget (or if no editor is open).\n     */\n    function _toggleInlineWidget(providers, errorMsg) {\n        var result = new $.Deferred();\n\n        var currentEditor = getCurrentFullEditor();\n\n        if (currentEditor) {\n            var inlineWidget = currentEditor.getFocusedInlineWidget();\n\n            if (inlineWidget) {\n                // an inline widget's editor has focus, so close it\n                PerfUtils.markStart(PerfUtils.INLINE_WIDGET_CLOSE);\n                inlineWidget.close().done(function () {\n                    PerfUtils.addMeasurement(PerfUtils.INLINE_WIDGET_CLOSE);\n                    // return a resolved promise to CommandManager\n                    result.resolve(false);\n                });\n            } else {\n                // main editor has focus, so create an inline editor\n                _openInlineWidget(currentEditor, providers, errorMsg).done(function () {\n                    result.resolve(true);\n                }).fail(function () {\n                    result.reject();\n                });\n            }\n        } else {\n            // Can not open an inline editor without a host editor\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * Inserts a prioritized provider object into the array in sorted (descending) order.\n     * @private\n     * @param {Array.<{priority:number, provider:function(...)}>} array\n     * @param {number} priority\n     * @param {function(...)} provider\n     */\n    function _insertProviderSorted(array, provider, priority) {\n        var index,\n            prioritizedProvider = {\n                priority: priority,\n                provider: provider\n            };\n\n        for (index = 0; index < array.length; index++) {\n            if (array[index].priority < priority) {\n                break;\n            }\n        }\n\n        array.splice(index, 0, prioritizedProvider);\n    }\n\n\n    /**\n     * Creates a hidden, unattached master editor that is needed when a document is created for the\n     * sole purpose of creating an inline editor so operations that require a master editor can be performed\n     * Only called from Document._ensureMasterEditor()\n     * The editor view is placed in a hidden part of the DOM but can later be moved to a visible pane\n     * when the document is opened using pane.addView()\n     * @param {!Document} doc - document to create a hidden editor for\n     */\n    function _createUnattachedMasterEditor(doc) {\n        // attach to the hidden containers DOM node if necessary\n        if (!_$hiddenEditorsContainer) {\n            _$hiddenEditorsContainer = $(\"#hidden-editors\");\n        }\n        // Create an editor\n        var editor = _createEditorForDocument(doc, true, _$hiddenEditorsContainer);\n        // and hide it\n        editor.setVisible(false);\n    }\n\n    /**\n     * Removes the given widget UI from the given hostEditor (agnostic of what the widget's content\n     * is). The widget's onClosed() callback will be run as a result.\n     * @param {!Editor} hostEditor The editor containing the widget.\n     * @param {!InlineWidget} inlineWidget The inline widget to close.\n     * @return {$.Promise} A promise that's resolved when the widget is fully closed.\n     */\n    function closeInlineWidget(hostEditor, inlineWidget) {\n        // If widget has focus, return it to the hostEditor & move the cursor to where the inline used to be\n        if (inlineWidget.hasFocus()) {\n            // Place cursor back on the line just above the inline (the line from which it was opened)\n            // If cursor's already on that line, leave it be to preserve column position\n            var widgetLine = hostEditor._codeMirror.getLineNumber(inlineWidget.info.line);\n            var cursorLine = hostEditor.getCursorPos().line;\n            if (cursorLine !== widgetLine) {\n                hostEditor.setCursorPos({ line: widgetLine, pos: 0 });\n            }\n\n            hostEditor.focus();\n        }\n\n        return hostEditor.removeInlineWidget(inlineWidget);\n    }\n\n    /**\n     * Registers a new inline editor provider. When Quick Edit is invoked each registered provider is\n     * asked if it wants to provide an inline editor given the current editor and cursor location.\n     * An optional priority parameter is used to give providers with higher priority an opportunity\n     * to provide an inline editor before providers with lower priority.\n     *\n     * @param {function(!Editor, !{line:number, ch:number}):?($.Promise|string)} provider\n     * @param {number=} priority\n     * The provider returns a promise that will be resolved with an InlineWidget, or returns a string\n     * indicating why the provider cannot respond to this case (or returns null to indicate no reason).\n     */\n    function registerInlineEditProvider(provider, priority) {\n        if (priority === undefined) {\n            priority = 0;\n        }\n        _insertProviderSorted(_inlineEditProviders, provider, priority);\n    }\n\n    /**\n     * Registers a new inline docs provider. When Quick Docs is invoked each registered provider is\n     * asked if it wants to provide inline docs given the current editor and cursor location.\n     * An optional priority parameter is used to give providers with higher priority an opportunity\n     * to provide an inline editor before providers with lower priority.\n     *\n     * @param {function(!Editor, !{line:number, ch:number}):?($.Promise|string)} provider\n     * @param {number=} priority\n     * The provider returns a promise that will be resolved with an InlineWidget, or returns a string\n     * indicating why the provider cannot respond to this case (or returns null to indicate no reason).\n     */\n    function registerInlineDocsProvider(provider, priority) {\n        if (priority === undefined) {\n            priority = 0;\n        }\n        _insertProviderSorted(_inlineDocsProviders, provider, priority);\n    }\n\n\n    /**\n     * @private\n     * Given a host editor, return a list of all Editors in all its open inline widgets. (Ignoring\n     * any other inline widgets that might be open but don't contain Editors).\n     * @param {!Editor} hostEditor\n     * @return {Array.<Editor>}\n     *\n     */\n    function getInlineEditors(hostEditor) {\n        var inlineEditors = [];\n\n        if (hostEditor) {\n            hostEditor.getInlineWidgets().forEach(function (widget) {\n                if (widget instanceof InlineTextEditor && widget.editor) {\n                    inlineEditors.push(widget.editor);\n                }\n            });\n        }\n\n        return inlineEditors;\n    }\n\n\n\n    /**\n     * @private\n     * Creates a new \"full-size\" (not inline) Editor for the given Document, and sets it as the\n     * Document's master backing editor. The editor is not yet visible;\n     * Semi-private: should only be called within this module or by Document.\n     * @param {!Document} document  Document whose main/full Editor to create\n     * @param {!Pane} pane  Pane in which the editor will be hosted\n     * @param {!Object} editorOptions If specified, contains editor options that\n     * can be passed to CodeMirror\n     * @return {!Editor}\n     */\n    function _createFullEditorForDocument(document, pane, editorOptions) {\n        // Create editor; make it initially invisible\n        var editor = _createEditorForDocument(document, true, pane.$content, undefined, editorOptions);\n        editor.setVisible(false);\n        pane.addView(editor);\n        exports.trigger(\"_fullEditorCreatedForDocument\", document, editor, pane.id);\n        return editor;\n    }\n\n\n    /**\n     * Creates a new inline Editor instance for the given Document.\n     * The editor is not yet visible or attached to a host editor.\n     * @param {!Document} doc  Document for the Editor's content\n     * @param {?{startLine:Number, endLine:Number}} range  If specified, all lines outside the given\n     *      range are hidden from the editor. Range is inclusive. Line numbers start at 0.\n     * @param {HTMLDivContainer} inlineContent\n     * @param  {function(inlineWidget)} closeThisInline\n     *\n     * @return {{content:DOMElement, editor:Editor}}\n     */\n    function createInlineEditorForDocument(doc, range, inlineContent) {\n        // Hide the container for the editor before creating it so that CodeMirror doesn't do extra work\n        // when initializing the document. When we construct the editor, we have to set its text and then\n        // set the (small) visible range that we show in the editor. If the editor is visible, CM has to\n        // render a large portion of the document before setting the visible range. By hiding the editor\n        // first and showing it after the visible range is set, we avoid that initial render.\n        $(inlineContent).hide();\n        var inlineEditor = _createEditorForDocument(doc, false, inlineContent, range);\n        inlineEditor._hostEditor = getCurrentFullEditor();\n        $(inlineContent).show();\n\n        return { content: inlineContent, editor: inlineEditor };\n    }\n\n    /**\n     * Returns focus to the last visible editor that had focus. If no editor visible, does nothing.\n     * This function should be called to restore editor focus after it has been temporarily\n     * removed. For example, after a dialog with editable text is closed.\n     */\n    function focusEditor() {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.focusActivePane() instead of EditorManager.focusEditor().\", true);\n        MainViewManager.focusActivePane();\n    }\n\n    /**\n     * @deprecated\n     * resizes the editor\n     */\n    function resizeEditor() {\n        DeprecationWarning.deprecationWarning(\"Use WorkspaceManager.recomputeLayout() instead of EditorManager.resizeEditor().\", true);\n        WorkspaceManager.recomputeLayout();\n    }\n\n    /**\n     * Create and/or show the editor for the specified document\n     * @param {!Document} document - document to edit\n     * @param {!Pane} pane - pane to show it in\n     * @param {!Object} editorOptions - If specified, contains\n     * editor options that can be passed to CodeMirror\n     * @private\n     */\n    function _showEditor(document, pane, editorOptions) {\n        // Ensure a main editor exists for this document to show in the UI\n        var createdNewEditor = false,\n            editor = document._masterEditor;\n\n        // Check if a master editor is not set already or the current master editor doesn't belong\n        // to the pane container requested - to support creation of multiple full editors\n        // This check is required as _masterEditor is the active full editor for the document\n        // and there can be existing full editor created for other panes\n        if (editor && editor._paneId && editor._paneId !== pane.id) {\n            editor = document._checkAssociatedEditorForPane(pane.id);\n        }\n\n        if (!editor) {\n            // Performance (see #4757) Chrome wastes time messing with selection\n            // that will just be changed at end, so clear it for now\n            if (window.getSelection && window.getSelection().empty) {  // Chrome\n                window.getSelection().empty();\n            }\n\n            // Editor doesn't exist: populate a new Editor with the text\n            editor = _createFullEditorForDocument(document, pane, editorOptions);\n            createdNewEditor = true;\n        } else if (editor.$el.parent()[0] !== pane.$content[0]) {\n            // editor does exist but is not a child of the pane so add it to the\n            //  pane (which will switch the view's container as well)\n            pane.addView(editor);\n        }\n\n        // show the view\n        pane.showView(editor);\n\n        if (MainViewManager.getActivePaneId() === pane.id) {\n            // give it focus\n            editor.focus();\n        }\n\n        if (createdNewEditor) {\n            _restoreEditorViewState(editor);\n        }\n    }\n\n    /**\n     * @deprecated use MainViewManager.getCurrentlyViewedFile() instead\n     * @return {string=} path of the file currently viewed in the active, full sized editor or null when there is no active editor\n     */\n    function getCurrentlyViewedPath() {\n        DeprecationWarning.deprecationWarning(\"Use MainViewManager.getCurrentlyViewedFile() instead of EditorManager.getCurrentlyViewedPath().\", true);\n\n        // We only want to return a path of a document object\n        // not other things like images, etc...\n        var currentPath = MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE),\n            doc;\n\n        if (currentPath) {\n            doc = DocumentManager.getOpenDocumentForPath(currentPath);\n        }\n\n        if (doc) {\n            return currentPath;\n        }\n\n        return null;\n    }\n\n    /**\n     * @deprecated There is no equivalent API moving forward.\n     * Use MainViewManager._initialize() from a unit test to create a Main View attached to a specific DOM element\n     */\n    function setEditorHolder() {\n        throw new Error(\"EditorManager.setEditorHolder() has been removed.\");\n    }\n\n    /**\n     * @deprecated Register a View Factory instead\n     * @see MainViewFactory::#registerViewFactory\n     */\n    function registerCustomViewer() {\n        throw new Error(\"EditorManager.registerCustomViewer() has been removed.\");\n    }\n\n    /**\n     * Determines if the file can be opened in an editor\n     * @param {!string} fullPath - file to be opened\n     * @return {boolean} true if the file can be opened in an editor, false if not\n     */\n    function canOpenPath(fullPath) {\n        return !LanguageManager.getLanguageForPath(fullPath).isBinary();\n    }\n\n    /**\n     * Opens the specified document in the given pane\n     * @param {!Document} doc - the document to open\n     * @param {!Pane} pane - the pane to open the document in\n     * @param {!Object} editorOptions - If specified, contains\n     * editor options that can be passed to CodeMirror\n     * @return {boolean} true if the file can be opened, false if not\n     */\n    function openDocument(doc, pane, editorOptions) {\n        var perfTimerName = PerfUtils.markStart(\"EditorManager.openDocument():\\t\" + (!doc || doc.file.fullPath));\n\n        if (doc && pane) {\n            _showEditor(doc, pane, editorOptions);\n        }\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n\n    /**\n     * Returns the currently focused inline widget, if any.\n     * @return {?InlineWidget}\n     */\n    function getFocusedInlineWidget() {\n        var currentEditor = getCurrentFullEditor();\n        if (currentEditor) {\n            return currentEditor.getFocusedInlineWidget();\n        }\n        return null;\n    }\n\n    /**\n     * Returns the focused Editor within an inline text editor, or null if something else has focus\n     * @return {?Editor}\n     */\n    function _getFocusedInlineEditor() {\n        var focusedWidget = getFocusedInlineWidget();\n        if (focusedWidget instanceof InlineTextEditor) {\n            return focusedWidget.getFocusedEditor();\n        }\n        return null;\n    }\n\n    /**\n     * Returns the currently focused editor instance (full-sized OR inline editor).\n     * This function is similar to getActiveEditor(), with one main difference: this\n     * function will only return editors that currently have focus, whereas\n     * getActiveEditor() will return the last visible editor that was given focus (but\n     * may not currently have focus because, for example, a dialog with editable text\n     * is open).\n     * @return {?Editor}\n     */\n    function getFocusedEditor() {\n        var currentEditor = getCurrentFullEditor();\n        if (currentEditor) {\n\n            // See if any inlines have focus\n            var focusedInline = _getFocusedInlineEditor();\n            if (focusedInline) {\n                return focusedInline;\n            }\n\n            // otherwise, see if full-sized editor has focus\n            if (currentEditor.hasFocus()) {\n                return currentEditor;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns the current active editor (full-sized OR inline editor). This editor may not\n     * have focus at the moment, but it is visible and was the last editor that was given\n     * focus. Returns null if no editors are active.\n     * @see #getFocusedEditor\n     * @return {?Editor}\n     */\n    function getActiveEditor() {\n        return _lastFocusedEditor;\n    }\n\n    /**\n     * file removed from pane handler.\n     * @param {jQuery.Event} e\n     * @param {File|Array.<File>} removedFiles - file, path or array of files or paths that are being removed\n     */\n    function _handleRemoveFromPaneView(e, removedFiles) {\n        var handleFileRemoved = function (file) {\n            var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n\n            if (doc) {\n                MainViewManager._destroyEditorIfNotNeeded(doc);\n            }\n        };\n\n        // when files are removed from a pane then\n        //    we should destroy any unnecssary views\n        if ($.isArray(removedFiles)) {\n            removedFiles.forEach(function (removedFile) {\n                handleFileRemoved(removedFile);\n            });\n        } else {\n            handleFileRemoved(removedFiles);\n        }\n    }\n\n\n    // Set up event dispatching\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // File-based preferences handling\n    exports.on(\"activeEditorChange\", function (e, current) {\n        if (current && current.document && current.document.file) {\n            PreferencesManager._setCurrentFile(current.document.file.fullPath);\n        }\n    });\n\n    // Initialize: command handlers\n    CommandManager.register(Strings.CMD_TOGGLE_QUICK_EDIT, Commands.TOGGLE_QUICK_EDIT, function () {\n        return _toggleInlineWidget(_inlineEditProviders, Strings.ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND);\n    });\n    CommandManager.register(Strings.CMD_TOGGLE_QUICK_DOCS, Commands.TOGGLE_QUICK_DOCS, function () {\n        return _toggleInlineWidget(_inlineDocsProviders, Strings.ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND);\n    });\n\n    MainViewManager.on(\"currentFileChange\", _handleCurrentFileChange);\n    MainViewManager.on(\"workingSetRemove workingSetRemoveList\", _handleRemoveFromPaneView);\n\n\n    // For unit tests and internal use only\n    exports._createFullEditorForDocument  = _createFullEditorForDocument;\n    exports._notifyActiveEditorChanged    = _notifyActiveEditorChanged;\n\n    // Internal Use only\n    exports._saveEditorViewState          = _saveEditorViewState;\n    exports._createUnattachedMasterEditor = _createUnattachedMasterEditor;\n\n    // Define public API\n    exports.createInlineEditorForDocument = createInlineEditorForDocument;\n    exports.getFocusedInlineWidget        = getFocusedInlineWidget;\n    exports.getInlineEditors              = getInlineEditors;\n    exports.closeInlineWidget             = closeInlineWidget;\n    exports.openDocument                  = openDocument;\n    exports.canOpenPath                   = canOpenPath;\n\n    // Convenience Methods\n    exports.getActiveEditor               = getActiveEditor;\n    exports.getCurrentFullEditor          = getCurrentFullEditor;\n    exports.getFocusedEditor              = getFocusedEditor;\n\n\n    exports.registerInlineEditProvider    = registerInlineEditProvider;\n    exports.registerInlineDocsProvider    = registerInlineDocsProvider;\n\n    // Deprecated\n    exports.registerCustomViewer          = registerCustomViewer;\n    exports.resizeEditor                  = resizeEditor;\n    exports.focusEditor                   = focusEditor;\n    exports.getCurrentlyViewedPath        = getCurrentlyViewedPath;\n    exports.setEditorHolder               = setEditorHolder;\n});\n"
  },
  {
    "path": "src/editor/EditorOptionHandlers.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit             = require(\"utils/AppInit\"),\n        Editor              = require(\"editor/Editor\").Editor,\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        Strings             = require(\"strings\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    // Constants for the preferences referred to in this file\n    var SHOW_LINE_NUMBERS = \"showLineNumbers\",\n        STYLE_ACTIVE_LINE = \"styleActiveLine\",\n        WORD_WRAP         = \"wordWrap\",\n        CLOSE_BRACKETS    = \"closeBrackets\",\n        AUTO_HIDE_SEARCH  = \"autoHideSearch\";\n\n\n    /**\n     * @private\n     *\n     * Maps from preference names to the command names needed to update the checked status.\n     */\n    var _optionMapping = {};\n    _optionMapping[SHOW_LINE_NUMBERS] = Commands.TOGGLE_LINE_NUMBERS;\n    _optionMapping[STYLE_ACTIVE_LINE] = Commands.TOGGLE_ACTIVE_LINE;\n    _optionMapping[WORD_WRAP] = Commands.TOGGLE_WORD_WRAP;\n    _optionMapping[CLOSE_BRACKETS] = Commands.TOGGLE_CLOSE_BRACKETS;\n    _optionMapping[AUTO_HIDE_SEARCH] = Commands.TOGGLE_SEARCH_AUTOHIDE;\n\n\n\n    /**\n     * @private\n     *\n     * Updates the command checked status based on the preference name given.\n     *\n     * @param {string} name Name of preference that has changed\n     */\n    function _updateCheckedState(name) {\n        var mapping = _optionMapping[name];\n        if (!mapping) {\n            return;\n        }\n        CommandManager.get(mapping).setChecked(PreferencesManager.get(name));\n    }\n\n    // Listen to preference changes for the preferences we care about\n    Object.keys(_optionMapping).forEach(function (preference) {\n        PreferencesManager.on(\"change\", preference, function () {\n            _updateCheckedState(preference);\n        });\n    });\n\n    /**\n     * @private\n     * Creates a function that will toggle the named preference.\n     *\n     * @param {string} prefName Name of preference that should be toggled by the function\n     */\n    function _getToggler(prefName) {\n        return function () {\n            PreferencesManager.set(prefName, !PreferencesManager.get(prefName));\n        };\n    }\n\n    function _init() {\n        _.each(_optionMapping, function (commandName, prefName) {\n            CommandManager.get(commandName).setChecked(PreferencesManager.get(prefName));\n        });\n\n        if (!Editor.getShowLineNumbers()) {\n            Editor._toggleLinePadding(true);\n        }\n    }\n\n    CommandManager.register(Strings.CMD_TOGGLE_LINE_NUMBERS, Commands.TOGGLE_LINE_NUMBERS, _getToggler(SHOW_LINE_NUMBERS));\n    CommandManager.register(Strings.CMD_TOGGLE_ACTIVE_LINE, Commands.TOGGLE_ACTIVE_LINE, _getToggler(STYLE_ACTIVE_LINE));\n    CommandManager.register(Strings.CMD_TOGGLE_WORD_WRAP, Commands.TOGGLE_WORD_WRAP, _getToggler(WORD_WRAP));\n    CommandManager.register(Strings.CMD_TOGGLE_CLOSE_BRACKETS, Commands.TOGGLE_CLOSE_BRACKETS, _getToggler(CLOSE_BRACKETS));\n    CommandManager.register(Strings.CMD_TOGGLE_SEARCH_AUTOHIDE, Commands.TOGGLE_SEARCH_AUTOHIDE, _getToggler(AUTO_HIDE_SEARCH));\n\n    AppInit.htmlReady(_init);\n});\n"
  },
  {
    "path": "src/editor/EditorStatusBar.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Manages parts of the status bar related to the current editor's state.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var _                    = require(\"thirdparty/lodash\"),\n        AnimationUtils       = require(\"utils/AnimationUtils\"),\n        AppInit              = require(\"utils/AppInit\"),\n        DropdownButton       = require(\"widgets/DropdownButton\").DropdownButton,\n        EditorManager        = require(\"editor/EditorManager\"),\n        MainViewManager      = require(\"view/MainViewManager\"),\n        Editor               = require(\"editor/Editor\").Editor,\n        KeyEvent             = require(\"utils/KeyEvent\"),\n        LanguageManager      = require(\"language/LanguageManager\"),\n        PreferencesManager   = require(\"preferences/PreferencesManager\"),\n        StatusBar            = require(\"widgets/StatusBar\"),\n        Strings              = require(\"strings\"),\n        FileUtils            = require(\"file/FileUtils\"),\n        InMemoryFile         = require(\"document/InMemoryFile\"),\n        Dialogs              = require(\"widgets/Dialogs\"),\n        DefaultDialogs       = require(\"widgets/DefaultDialogs\"),\n        ProjectManager       = require(\"project/ProjectManager\"),\n        Async                = require(\"utils/Async\"),\n        FileSystem           = require(\"filesystem/FileSystem\"),\n        CommandManager       = require(\"command/CommandManager\"),\n        Commands             = require(\"command/Commands\"),\n        DocumentManager      = require(\"document/DocumentManager\"),\n        StringUtils          = require(\"utils/StringUtils\"),\n        HealthLogger         = require(\"utils/HealthLogger\");\n    \n    var SupportedEncodingsText = require(\"text!supported-encodings.json\"),\n        SupportedEncodings = JSON.parse(SupportedEncodingsText);\n\n    /* StatusBar indicators */\n    var languageSelect, // this is a DropdownButton instance\n        encodingSelect, // this is a DropdownButton instance\n        $cursorInfo,\n        $fileInfo,\n        $indentType,\n        $indentWidthLabel,\n        $indentWidthInput,\n        $statusOverwrite;\n\n    /** Special list item for the 'set as default' gesture in language switcher dropdown */\n    var LANGUAGE_SET_AS_DEFAULT = {};\n\n\n    /**\n     * Determine string based on count\n     * @param {number} number Count\n     * @param {string} singularStr Singular string\n     * @param {string} pluralStr Plural string\n     * @return {string} Proper string to use for count\n     */\n    function _formatCountable(number, singularStr, pluralStr) {\n        return StringUtils.format(number > 1 ? pluralStr : singularStr, number);\n    }\n\n    /**\n     * Update file mode\n     * @param {Editor} editor Current editor\n     */\n    function _updateLanguageInfo(editor) {\n        var doc = editor.document,\n            lang = doc.getLanguage();\n\n        // Show the current language as button title\n        languageSelect.$button.text(lang.getName());\n    }\n\n    /**\n     * Update encoding\n     * @param {Editor} editor Current editor\n     */\n    function _updateEncodingInfo(editor) {\n        var doc = editor.document;\n\n        // Show the current encoding as button title\n        if (!doc.file._encoding) {\n            doc.file._encoding = \"UTF-8\";\n        }\n        encodingSelect.$button.text(doc.file._encoding);\n    }\n\n    /**\n     * Update file information\n     * @param {Editor} editor Current editor\n     */\n    function _updateFileInfo(editor) {\n        var lines = editor.lineCount();\n        $fileInfo.text(_formatCountable(lines, Strings.STATUSBAR_LINE_COUNT_SINGULAR, Strings.STATUSBAR_LINE_COUNT_PLURAL));\n    }\n\n    /**\n     * Update indent type and size\n     * @param {string} fullPath Path to file in current editor\n     */\n    function _updateIndentType(fullPath) {\n        var indentWithTabs = Editor.getUseTabChar(fullPath);\n        $indentType.text(indentWithTabs ? Strings.STATUSBAR_TAB_SIZE : Strings.STATUSBAR_SPACES);\n        $indentType.attr(\"title\", indentWithTabs ? Strings.STATUSBAR_INDENT_TOOLTIP_SPACES : Strings.STATUSBAR_INDENT_TOOLTIP_TABS);\n        $indentWidthLabel.attr(\"title\", indentWithTabs ? Strings.STATUSBAR_INDENT_SIZE_TOOLTIP_TABS : Strings.STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES);\n    }\n\n    /**\n     * Get indent size based on type\n     * @param {string} fullPath Path to file in current editor\n     * @return {number} Indent size\n     */\n    function _getIndentSize(fullPath) {\n        return Editor.getUseTabChar(fullPath) ? Editor.getTabSize(fullPath) : Editor.getSpaceUnits(fullPath);\n    }\n\n    /**\n     * Update indent size\n     * @param {string} fullPath Path to file in current editor\n     */\n    function _updateIndentSize(fullPath) {\n        var size = _getIndentSize(fullPath);\n        $indentWidthLabel.text(size);\n        $indentWidthInput.val(size);\n    }\n\n    /**\n     * Toggle indent type\n     */\n    function _toggleIndentType() {\n        var current = EditorManager.getActiveEditor(),\n            fullPath = current && current.document.file.fullPath;\n\n        Editor.setUseTabChar(!Editor.getUseTabChar(fullPath), fullPath);\n        _updateIndentType(fullPath);\n        _updateIndentSize(fullPath);\n    }\n\n    /**\n     * Update cursor(s)/selection(s) information\n     * @param {Event} event (unused)\n     * @param {Editor} editor Current editor\n     */\n    function _updateCursorInfo(event, editor) {\n        editor = editor || EditorManager.getActiveEditor();\n\n        // compute columns, account for tab size\n        var cursor = editor.getCursorPos(true);\n\n        var cursorStr = StringUtils.format(Strings.STATUSBAR_CURSOR_POSITION, cursor.line + 1, cursor.ch + 1);\n\n        var sels = editor.getSelections(),\n            selStr = \"\";\n\n        if (sels.length > 1) {\n            //Send analytics data for multicursor use\n            HealthLogger.sendAnalyticsData(\n                \"multiCursor\",\n                \"usage\",\n                \"multiCursor\",\n                \"use\"\n            );\n            selStr = StringUtils.format(Strings.STATUSBAR_SELECTION_MULTIPLE, sels.length);\n        } else if (editor.hasSelection()) {\n            var sel = sels[0];\n            if (sel.start.line !== sel.end.line) {\n                var lines = sel.end.line - sel.start.line + 1;\n                if (sel.end.ch === 0) {\n                    lines--;  // end line is exclusive if ch is 0, inclusive otherwise\n                }\n                selStr = _formatCountable(lines, Strings.STATUSBAR_SELECTION_LINE_SINGULAR, Strings.STATUSBAR_SELECTION_LINE_PLURAL);\n            } else {\n                var cols = editor.getColOffset(sel.end) - editor.getColOffset(sel.start);  // end ch is exclusive always\n                selStr = _formatCountable(cols, Strings.STATUSBAR_SELECTION_CH_SINGULAR, Strings.STATUSBAR_SELECTION_CH_PLURAL);\n            }\n        }\n        $cursorInfo.text(cursorStr + selStr);\n    }\n\n    /**\n     * Change indent size\n     * @param {string} fullPath Path to file in current editor\n     * @param {string} value Size entered into status bar\n     */\n    function _changeIndentWidth(fullPath, value) {\n        $indentWidthLabel.removeClass(\"hidden\");\n        $indentWidthInput.addClass(\"hidden\");\n\n        // remove all event handlers from the input field\n        $indentWidthInput.off(\"blur keyup\");\n\n        // restore focus to the editor\n        MainViewManager.focusActivePane();\n\n        var valInt = parseInt(value, 10);\n        if (Editor.getUseTabChar(fullPath)) {\n            if (!Editor.setTabSize(valInt, fullPath)) {\n                return;     // validation failed\n            }\n        } else {\n            if (!Editor.setSpaceUnits(valInt, fullPath)) {\n                return;     // validation failed\n            }\n        }\n\n        // update indicator\n        _updateIndentSize(fullPath);\n\n        // column position may change when tab size changes\n        _updateCursorInfo();\n    }\n\n    /**\n     * Update insert/overwrite label\n     * @param {Event} event (unused)\n     * @param {Editor} editor Current editor\n     * @param {string} newstate New overwrite state\n     * @param {boolean=} doNotAnimate True if state should not be animated\n     */\n    function _updateOverwriteLabel(event, editor, newstate, doNotAnimate) {\n        if ($statusOverwrite.text() === (newstate ? Strings.STATUSBAR_OVERWRITE : Strings.STATUSBAR_INSERT)) {\n            // label already up-to-date\n            return;\n        }\n\n        $statusOverwrite.text(newstate ? Strings.STATUSBAR_OVERWRITE : Strings.STATUSBAR_INSERT);\n\n        if (!doNotAnimate) {\n            AnimationUtils.animateUsingClass($statusOverwrite[0], \"flash\", 1500);\n        }\n    }\n\n    /**\n     * Update insert/overwrite indicator\n     * @param {Event} event (unused)\n     */\n    function _updateEditorOverwriteMode(event) {\n        var editor = EditorManager.getActiveEditor(),\n            newstate = !editor._codeMirror.state.overwrite;\n\n        // update label with no transition\n        _updateOverwriteLabel(event, editor, newstate, true);\n        editor.toggleOverwrite(newstate);\n    }\n\n    /**\n     * Initialize insert/overwrite indicator\n     * @param {Editor} currentEditor Current editor\n     */\n    function _initOverwriteMode(currentEditor) {\n        currentEditor.toggleOverwrite($statusOverwrite.text() === Strings.STATUSBAR_OVERWRITE);\n        $statusOverwrite.attr(\"title\", Strings.STATUSBAR_INSOVR_TOOLTIP);\n    }\n\n    /**\n     * Handle active editor change event\n     * @param {Event} event (unused)\n     * @param {Editor} current Current editor\n     * @param {Editor} previous Previous editor\n     */\n    function _onActiveEditorChange(event, current, previous) {\n        if (previous) {\n            previous.off(\".statusbar\");\n            previous.document.off(\".statusbar\");\n            previous.document.releaseRef();\n        }\n\n        if (!current) {\n            StatusBar.hideAllPanes();\n        } else {\n            var fullPath = current.document.file.fullPath;\n            StatusBar.showAllPanes();\n\n            current.on(\"cursorActivity.statusbar\", _updateCursorInfo);\n            current.on(\"optionChange.statusbar\", function () {\n                _updateIndentType(fullPath);\n                _updateIndentSize(fullPath);\n            });\n            current.on(\"change.statusbar\", function () {\n                // async update to keep typing speed smooth\n                window.setTimeout(function () { _updateFileInfo(current); }, 0);\n            });\n            current.on(\"overwriteToggle.statusbar\", _updateOverwriteLabel);\n\n            current.document.addRef();\n            current.document.on(\"languageChanged.statusbar\", function () {\n                _updateLanguageInfo(current);\n            });\n\n            _updateCursorInfo(null, current);\n            _updateLanguageInfo(current);\n            _updateEncodingInfo(current);\n            _updateFileInfo(current);\n            _initOverwriteMode(current);\n            _updateIndentType(fullPath);\n            _updateIndentSize(fullPath);\n        }\n    }\n\n    /**\n     * Populate the languageSelect DropdownButton's menu with all registered Languages\n     */\n    function _populateLanguageDropdown() {\n        // Get all non-binary languages\n        var languages = _.values(LanguageManager.getLanguages()).filter(function (language) {\n            return !language.isBinary();\n        });\n\n        // sort dropdown alphabetically\n        languages.sort(function (a, b) {\n            return a.getName().toLowerCase().localeCompare(b.getName().toLowerCase());\n        });\n\n        languageSelect.items = languages;\n\n        // Add option to top of menu for persisting the override\n        languageSelect.items.unshift(\"---\");\n        languageSelect.items.unshift(LANGUAGE_SET_AS_DEFAULT);\n    }\n\n    /**\n     * Change the encoding and reload the current document.\n     * If passed then save the preferred encoding in state.\n     */\n    function _changeEncodingAndReloadDoc(document) {\n        var promise = document.reload();\n        promise.done(function (text, readTimestamp) {\n            encodingSelect.$button.text(document.file._encoding);\n            // Store the preferred encoding in the state\n            var projectRoot = ProjectManager.getProjectRoot(),\n                context = {\n                    location : {\n                        scope: \"user\",\n                        layer: \"project\",\n                        layerID: projectRoot.fullPath\n                    }\n                };\n            var encoding = PreferencesManager.getViewState(\"encoding\", context);\n            encoding[document.file.fullPath] = document.file._encoding;\n            PreferencesManager.setViewState(\"encoding\", encoding, context);\n        });\n        promise.fail(function (error) {\n            console.log(\"Error reloading contents of \" + document.file.fullPath, error);\n        });\n    }\n\n\n    /**\n     * Populate the encodingSelect DropdownButton's menu with all registered encodings\n     */\n    function _populateEncodingDropdown() {\n        encodingSelect.items = SupportedEncodings;\n    }\n\n    /**\n     * Initialize\n     */\n    function _init() {\n\n        $cursorInfo         = $(\"#status-cursor\");\n        $fileInfo           = $(\"#status-file\");\n        $indentType         = $(\"#indent-type\");\n        $indentWidthLabel   = $(\"#indent-width-label\");\n        $indentWidthInput   = $(\"#indent-width-input\");\n        $statusOverwrite    = $(\"#status-overwrite\");\n\n        languageSelect      = new DropdownButton(\"\", [], function (item, index) {\n            var document = EditorManager.getActiveEditor().document,\n                defaultLang = LanguageManager.getLanguageForPath(document.file.fullPath, true);\n\n            if (item === LANGUAGE_SET_AS_DEFAULT) {\n                var label = _.escape(StringUtils.format(Strings.STATUSBAR_SET_DEFAULT_LANG, LanguageManager.getCompoundFileExtension(document.file.fullPath)));\n                return { html: label, enabled: document.getLanguage() !== defaultLang };\n            }\n\n            var html = _.escape(item.getName());\n\n            // Show indicators for currently selected & default languages for the current file\n            if (item === defaultLang) {\n                html += \" <span class='default-language'>\" + Strings.STATUSBAR_DEFAULT_LANG + \"</span>\";\n            }\n            if (item === document.getLanguage()) {\n                html = \"<span class='checked-language'></span>\" + html;\n            }\n            return html;\n        });\n\n        languageSelect.dropdownExtraClasses = \"dropdown-status-bar\";\n        languageSelect.$button.addClass(\"btn-status-bar\");\n        $(\"#status-language\").append(languageSelect.$button);\n        languageSelect.$button.attr(\"title\", Strings.STATUSBAR_LANG_TOOLTIP);\n\n\n        encodingSelect = new DropdownButton(\"\", [], function (item, index) {\n            var document = EditorManager.getActiveEditor().document;\n            var html = _.escape(item);\n\n            // Show indicators for currently selected & default languages for the current file\n            if (item === \"UTF-8\") {\n                html += \" <span class='default-language'>\" + Strings.STATUSBAR_DEFAULT_LANG + \"</span>\";\n            }\n            if (item === document.file._encoding) {\n                html = \"<span class='checked-language'></span>\" + html;\n            }\n            return html;\n        });\n\n        encodingSelect.dropdownExtraClasses = \"dropdown-status-bar\";\n        encodingSelect.$button.addClass(\"btn-status-bar\");\n        $(\"#status-encoding\").append(encodingSelect.$button);\n        encodingSelect.$button.attr(\"title\", Strings.STATUSBAR_ENCODING_TOOLTIP);\n\n\n        // indentation event handlers\n        $indentType.on(\"click\", _toggleIndentType);\n        $indentWidthLabel\n            .on(\"click\", function () {\n                // update the input value before displaying\n                var fullPath = EditorManager.getActiveEditor().document.file.fullPath;\n                $indentWidthInput.val(_getIndentSize(fullPath));\n\n                $indentWidthLabel.addClass(\"hidden\");\n                $indentWidthInput.removeClass(\"hidden\");\n                $indentWidthInput.focus();\n\n                $indentWidthInput\n                    .on(\"blur\", function () {\n                        _changeIndentWidth(fullPath, $indentWidthInput.val());\n                    })\n                    .on(\"keyup\", function (event) {\n                        if (event.keyCode === KeyEvent.DOM_VK_RETURN) {\n                            $indentWidthInput.blur();\n                        } else if (event.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                            _changeIndentWidth(fullPath, false);\n                        }\n                    });\n            });\n\n        $indentWidthInput.focus(function () { $indentWidthInput.select(); });\n\n        // Language select change handler\n        languageSelect.on(\"select\", function (e, lang) {\n            var document = EditorManager.getActiveEditor().document,\n                fullPath = document.file.fullPath;\n\n            var fileType = (document.file instanceof InMemoryFile) ? \"newFile\" : \"existingFile\",\n                filelanguageName = lang ? lang._name : \"\";\n\n            HealthLogger.sendAnalyticsData(\n                HealthLogger.commonStrings.USAGE + HealthLogger.commonStrings.LANGUAGE_CHANGE\n                + filelanguageName + fileType,\n                HealthLogger.commonStrings.USAGE,\n                HealthLogger.commonStrings.LANGUAGE_CHANGE,\n                filelanguageName.toLowerCase(),\n                fileType\n            );\n\n            if (lang === LANGUAGE_SET_AS_DEFAULT) {\n                // Set file's current language in preferences as a file extension override (only enabled if not default already)\n                var fileExtensionMap = PreferencesManager.get(\"language.fileExtensions\");\n                fileExtensionMap[LanguageManager.getCompoundFileExtension(fullPath)] = document.getLanguage().getId();\n                PreferencesManager.set(\"language.fileExtensions\", fileExtensionMap);\n\n            } else {\n                // Set selected language as a path override for just this one file (not persisted)\n                var defaultLang = LanguageManager.getLanguageForPath(fullPath, true);\n                // if default language selected, pass null to clear the override\n                LanguageManager.setLanguageOverrideForPath(fullPath, lang === defaultLang ? null : lang);\n            }\n        });\n\n        // Encoding select change handler\n        encodingSelect.on(\"select\", function (e, encoding) {\n            var document = EditorManager.getActiveEditor().document,\n                originalPath = document.file.fullPath,\n                originalEncoding = document.file._encoding;\n\n            document.file._encoding = encoding;\n            if (!(document.file instanceof InMemoryFile) && document.isDirty) {\n                CommandManager.execute(Commands.FILE_SAVE_AS, {doc: document}).done(function () {\n                    var doc = DocumentManager.getCurrentDocument();\n                    if (originalPath === doc.file.fullPath) {\n                        _changeEncodingAndReloadDoc(doc);\n                    } else {\n                        document.file._encoding = originalEncoding;\n                    }\n                }).fail(function () {\n                    document.file._encoding = originalEncoding;\n                });\n            } else if (document.file instanceof InMemoryFile) {\n                encodingSelect.$button.text(encoding);\n            } else if (!document.isDirty) {\n                _changeEncodingAndReloadDoc(document);\n            }\n        });\n\n        $statusOverwrite.on(\"click\", _updateEditorOverwriteMode);\n    }\n\n    // Initialize: status bar focused listener\n    EditorManager.on(\"activeEditorChange\", _onActiveEditorChange);\n\n    function _checkFileExistance(filePath, index, encoding) {\n        var deferred = new $.Deferred(),\n            fileEntry = FileSystem.getFileForPath(filePath);\n    \n        fileEntry.exists(function (err, exists) {\n            if (!err && exists) {\n                deferred.resolve();\n            } else {\n                delete encoding[filePath];\n                deferred.reject();\n            }\n        });\n\n        return deferred.promise();\n    }\n\n    ProjectManager.on(\"projectOpen\", function () {\n        var projectRoot = ProjectManager.getProjectRoot(),\n            context = {\n                location : {\n                    scope: \"user\",\n                    layer: \"project\",\n                    layerID: projectRoot.fullPath\n                }\n            };\n        var encoding = PreferencesManager.getViewState(\"encoding\", context);\n        if (!encoding) {\n            encoding = {};\n            PreferencesManager.setViewState(\"encoding\", encoding, context);\n        }\n        Async.doSequentially(Object.keys(encoding), function (filePath, index) {\n            return _checkFileExistance(filePath, index, encoding);\n        }, false)\n            .always(function () {\n                PreferencesManager.setViewState(\"encoding\", encoding, context);\n            });\n    });\n\n    AppInit.htmlReady(_init);\n    AppInit.appReady(function () {\n        // Populate language switcher with all languages after startup; update it later if this set changes\n        _populateLanguageDropdown();\n        _populateEncodingDropdown();\n        LanguageManager.on(\"languageAdded languageModified\", _populateLanguageDropdown);\n        _onActiveEditorChange(null, EditorManager.getActiveEditor(), null);\n        StatusBar.show();\n    });\n});\n"
  },
  {
    "path": "src/editor/ImageViewer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        ImageViewTemplate   = require(\"text!htmlContent/image-view.html\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        MainViewFactory     = require(\"view/MainViewFactory\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        _                   = require(\"thirdparty/lodash\"),\n        Mustache            = require(\"thirdparty/mustache/mustache\");\n\n    var _viewers = {};\n\n    /**\n     * ImageView objects are constructed when an image is opened\n     * @see {@link Pane} for more information about where ImageViews are rendered\n     *\n     * @constructor\n     * @param {!File} file - The image file object to render\n     * @param {!jQuery} container - The container to render the image view in\n     */\n    function ImageView(file, $container) {\n        this.file = file;\n        this.$el = $(Mustache.render(ImageViewTemplate, {fullPath: file.encodedPath || 'file:///' + FileUtils.encodeFilePath(file.fullPath),\n                                                         now: new Date().valueOf()}));\n\n        $container.append(this.$el);\n\n        this._naturalWidth = 0;\n        this._naturalHeight = 0;\n        this._scale = 100;           // 100%\n        this._scaleDivInfo = null;   // coordinates of hidden scale sticker\n\n        this.relPath = ProjectManager.makeProjectRelativeIfPossible(this.file.fullPath);\n\n        this.$imagePath = this.$el.find(\".image-path\");\n        this.$imagePreview = this.$el.find(\".image-preview\");\n        this.$imageData = this.$el.find(\".image-data\");\n\n        this.$image = this.$el.find(\".image\");\n        this.$imageTip = this.$el.find(\".image-tip\");\n        this.$imageGuides = this.$el.find(\".image-guide\");\n        this.$imageScale = this.$el.find(\".image-scale\");\n        this.$x_value = this.$el.find(\".x-value\");\n        this.$y_value = this.$el.find(\".y-value\");\n        this.$horzGuide = this.$el.find(\".horz-guide\");\n        this.$vertGuide = this.$el.find(\".vert-guide\");\n\n        this.$imagePath.text(this.relPath).attr(\"title\", this.relPath);\n        this.$imagePreview.on(\"load\", _.bind(this._onImageLoaded, this));\n\n        _viewers[file.fullPath] = this;\n    }\n\n    /**\n     * DocumentManger.fileNameChange handler - when an image is renamed, we must\n     * update the view\n     *\n     * @param {jQuery.Event} e - event\n     * @param {!string} oldPath - the name of the file that's changing changing\n     * @param {!string} newPath - the name of the file that's changing changing\n     * @private\n     */\n    ImageView.prototype._onFilenameChange = function (e, oldPath, newPath) {\n        /*\n         * File objects are already updated when the event is triggered\n         * so we just need to see if the file has the same path as our image\n         */\n        if (this.file.fullPath === newPath) {\n            this.relPath = ProjectManager.makeProjectRelativeIfPossible(newPath);\n            this.$imagePath.text(this.relPath).attr(\"title\", this.relPath);\n        }\n    };\n\n    /**\n     * <img>.on(\"load\") handler - updates content of the image view\n     *                            initializes computed values\n     *                            installs event handlers\n     * @param {Event} e - event\n     * @private\n     */\n    ImageView.prototype._onImageLoaded = function (e) {\n        // add dimensions and size\n        this._naturalWidth = e.currentTarget.naturalWidth;\n        this._naturalHeight = e.currentTarget.naturalHeight;\n\n        var extension = FileUtils.getFileExtension(this.file.fullPath);\n        var dimensionString = this._naturalWidth + \" &times; \" + this._naturalHeight + \" \" + Strings.UNIT_PIXELS;\n\n        if (extension === \"ico\") {\n            dimensionString += \" (\" + Strings.IMAGE_VIEWER_LARGEST_ICON + \")\";\n        }\n\n        // get image size\n        var self = this;\n\n        this.file.stat(function (err, stat) {\n            if (err) {\n                self.$imageData.html(dimensionString);\n            } else {\n                var sizeString = \"\";\n                if (stat.size) {\n                    sizeString = \" &mdash; \" + StringUtils.prettyPrintBytes(stat.size, 2);\n                }\n                var dimensionAndSize = dimensionString + sizeString;\n                self.$imageData.html(dimensionAndSize)\n                        .attr(\"title\", dimensionAndSize\n                                    .replace(\"&times;\", \"x\")\n                                    .replace(\"&mdash;\", \"-\"));\n            }\n        });\n\n        // make sure we always show the right file name\n        DocumentManager.on(\"fileNameChange.ImageView\", _.bind(this._onFilenameChange, this));\n\n        this.$imageTip.hide();\n        this.$imageGuides.hide();\n\n        this.$image.on(\"mousemove.ImageView\", \".image-preview\", _.bind(this._showImageTip, this))\n                   .on(\"mouseleave.ImageView\", \".image-preview\", _.bind(this._hideImageTip, this));\n\n        this._updateScale();\n    };\n\n    /**\n     * Update the scale element\n     * @private\n     */\n    ImageView.prototype._updateScale = function () {\n        var currentWidth = this.$imagePreview.width();\n\n        if (currentWidth && currentWidth < this._naturalWidth) {\n            this._scale = currentWidth / this._naturalWidth * 100;\n            this.$imageScale.text(Math.floor(this._scale) + \"%\")\n                // Keep the position of the image scale div relative to the image.\n                .css(\"left\", this.$imagePreview.position().left + 5)\n                .show();\n        } else {\n            // Reset everything related to the image scale sticker before hiding it.\n            this._scale = 100;\n            this._scaleDivInfo = null;\n            this.$imageScale.text(\"\").hide();\n        }\n    };\n\n\n    /**\n     * Show image coordinates under the mouse cursor\n     * @param {Event} e - event\n     * @private\n     */\n    ImageView.prototype._showImageTip = function (e) {\n        // Don't show image tip if this._scale is close to zero.\n        // since we won't have enough room to show tip anyway.\n        if (Math.floor(this._scale) === 0) {\n            return;\n        }\n\n        var x                   = Math.round(e.offsetX * 100 / this._scale),\n            y                   = Math.round(e.offsetY * 100 / this._scale),\n            imagePos            = this.$imagePreview.position(),\n            left                = e.offsetX + imagePos.left,\n            top                 = e.offsetY + imagePos.top,\n            width               = this.$imagePreview.width(),\n            height              = this.$imagePreview.height(),\n            windowWidth         = $(window).width(),\n            fourDigitImageWidth = this._naturalWidth.toString().length === 4,\n\n            // @todo -- seems a bit strange that we're computing sizes\n            //          using magic numbers\n\n            infoWidth1          = 112,    // info div width 96px + vertical toolbar width 16px\n            infoWidth2          = 120,    // info div width 104px (for 4-digit image width) + vertical toolbar width 16px\n            tipOffsetX          = 10,     // adjustment for info div left from x coordinate of cursor\n            tipOffsetY          = -54,    // adjustment for info div top from y coordinate of cursor\n            tipMinusOffsetX1    = -82,    // for less than 4-digit image width\n            tipMinusOffsetX2    = -90;    // for 4-digit image width\n\n        // Check whether we're getting mousemove events beyond the image boundaries due to a browser bug\n        // or the rounding calculation above for a scaled image. For example, if an image is 120 px wide,\n        // we should get mousemove events in the range of 0 <= x < 120, but not 120 or more. If we get\n        // a value beyond the range, then simply handle the event as if it were a mouseleave.\n        if (x < 0 || x >= this._naturalWidth || y < 0 || y >= this._naturalHeight) {\n            this._hideImageTip(e);\n            this.$imagePreview.css(\"cursor\", \"auto\");\n            return;\n        }\n\n        this.$imagePreview.css(\"cursor\", \"none\");\n\n        this._handleMouseEnterOrExitScaleSticker(left, top);\n\n        // Check whether to show the image tip on the left.\n        if ((e.pageX + infoWidth1) > windowWidth ||\n                (fourDigitImageWidth && (e.pageX + infoWidth2) > windowWidth)) {\n            tipOffsetX = fourDigitImageWidth ? tipMinusOffsetX2 : tipMinusOffsetX1;\n        }\n\n        this.$x_value.text(x + \"px\");\n        this.$y_value.text(y + \"px\");\n\n        this.$imageTip.css({\n            left: left + tipOffsetX,\n            top: top + tipOffsetY\n        }).show();\n\n        this.$horzGuide.css({\n            left: imagePos.left,\n            top: top,\n            width: width - 1\n        }).show();\n\n        this.$vertGuide.css({\n            left: left,\n            top: imagePos.top,\n            height: height - 1\n        }).show();\n    };\n\n    /**\n     * Hide image coordinates info tip\n     * @param {Event} e - event\n     * @private\n     */\n    ImageView.prototype._hideImageTip = function (e) {\n        var $target   = $(e.target),\n            targetPos = $target.position(),\n            imagePos  = this.$imagePreview.position(),\n            right     = imagePos.left + this.$imagePreview.width(),\n            bottom    = imagePos.top + this.$imagePreview.height(),\n            x         = targetPos.left + e.offsetX,\n            y         = targetPos.top + e.offsetY;\n\n        // Hide image tip and guides only if the cursor is outside of the image.\n        if (x < imagePos.left || x >= right ||\n                y < imagePos.top || y >= bottom) {\n            this._hideGuidesAndTip();\n            if (this._scaleDivInfo) {\n                this._scaleDivInfo = null;\n                this.$imageScale.show();\n            }\n        }\n    };\n\n    /**\n     * Hides both guides and the tip\n     * @private\n     */\n    ImageView.prototype._hideGuidesAndTip = function () {\n        this.$imageTip.hide();\n        this.$imageGuides.hide();\n    };\n\n    /**\n     * Check mouse entering/exiting the scale sticker.\n     * Hide it when entering and show it again when exiting.\n     *\n     * @param {number} offsetX mouse offset from the left of the previewing image\n     * @param {number} offsetY mouseoffset from the top of the previewing image\n     * @private\n     */\n    ImageView.prototype._handleMouseEnterOrExitScaleSticker = function (offsetX, offsetY) {\n        var imagePos       = this.$imagePreview.position(),\n            scaleDivPos    = this.$imageScale.position(),\n            imgWidth       = this.$imagePreview.width(),\n            imgHeight      = this.$imagePreview.height(),\n            scaleDivLeft,\n            scaleDivTop,\n            scaleDivRight,\n            scaleDivBottom;\n\n        if (this._scaleDivInfo) {\n            scaleDivLeft   = this._scaleDivInfo.left;\n            scaleDivTop    = this._scaleDivInfo.top;\n            scaleDivRight  = this._scaleDivInfo.right;\n            scaleDivBottom = this._scaleDivInfo.bottom;\n\n            if ((imgWidth + imagePos.left) < scaleDivRight) {\n                scaleDivRight = imgWidth + imagePos.left;\n            }\n\n            if ((imgHeight + imagePos.top) < scaleDivBottom) {\n                scaleDivBottom = imgHeight + imagePos.top;\n            }\n\n        } else {\n            scaleDivLeft   = scaleDivPos.left;\n            scaleDivTop    = scaleDivPos.top;\n            scaleDivRight  = this.$imageScale.width() + scaleDivLeft;\n            scaleDivBottom = this.$imageScale.height() + scaleDivTop;\n        }\n\n        if (this._scaleDivInfo) {\n            // See whether the cursor is no longer inside the hidden scale div.\n            // If so, show it again.\n            if ((offsetX < scaleDivLeft || offsetX > scaleDivRight) ||\n                    (offsetY < scaleDivTop || offsetY > scaleDivBottom)) {\n                this._scaleDivInfo = null;\n                this.$imageScale.show();\n            }\n        } else if ((offsetX >= scaleDivLeft && offsetX <= scaleDivRight) &&\n                (offsetY >= scaleDivTop && offsetY <= scaleDivBottom)) {\n            // Handle mouse inside image scale div.\n            // But hide it only if the pixel under mouse is also in the image.\n            if (offsetX < (imagePos.left + imgWidth) &&\n                    offsetY < (imagePos.top + imgHeight)) {\n                // Remember image scale div coordinates before hiding it.\n                this._scaleDivInfo = {left: scaleDivPos.left,\n                                 top: scaleDivPos.top,\n                                 right: scaleDivRight,\n                                 bottom: scaleDivBottom};\n                this.$imageScale.hide();\n            }\n        }\n    };\n\n    /**\n     * View Interface functions\n     */\n\n    /*\n     * Retrieves the file object for this view\n     * return {!File} the file object for this view\n     */\n    ImageView.prototype.getFile = function () {\n        return this.file;\n    };\n\n    /*\n     * Updates the layout of the view\n     */\n    ImageView.prototype.updateLayout = function () {\n        this._hideGuidesAndTip();\n\n        var $container = this.$el.parent();\n\n        var pos = $container.position(),\n            iWidth = $container.innerWidth(),\n            iHeight = $container.innerHeight(),\n            oWidth = $container.outerWidth(),\n            oHeight = $container.outerHeight();\n\n        // $view is \"position:absolute\" so\n        //  we have to update the height, width and position\n        this.$el.css({top: pos.top + ((oHeight - iHeight) / 2),\n                        left: pos.left + ((oWidth - iWidth) / 2),\n                        width: iWidth,\n                        height: iHeight});\n        this._updateScale();\n    };\n\n    /*\n     * Destroys the view\n     */\n    ImageView.prototype.destroy = function () {\n        delete _viewers[this.file.fullPath];\n        DocumentManager.off(\".ImageView\");\n        this.$image.off(\".ImageView\");\n        this.$el.remove();\n    };\n\n    /*\n     * Refreshes the image preview with what's on disk\n     */\n    ImageView.prototype.refresh = function () {\n        var noCacheUrl = this.$imagePreview.attr(\"src\"),\n            now = new Date().valueOf(),\n            index = noCacheUrl.indexOf(\"?\");\n\n        // strip the old param off\n        if (index > 0) {\n            noCacheUrl = noCacheUrl.slice(0, index);\n        }\n\n        // add a new param which will force chrome to\n        //  re-read the image from disk\n        noCacheUrl = noCacheUrl + \"?ver=\" + now;\n\n\n        // Update the DOM node with the src URL\n        this.$imagePreview.attr(\"src\", noCacheUrl);\n    };\n\n    /*\n     * Creates an image view object and adds it to the specified pane\n     * @param {!File} file - the file to create an image of\n     * @param {!Pane} pane - the pane in which to host the view\n     * @return {jQuery.Promise}\n     */\n    function _createImageView(file, pane) {\n        var view = pane.getViewForPath(file.fullPath);\n\n        if (view) {\n            pane.showView(view);\n        } else {\n            view = new ImageView(file, pane.$content);\n            pane.addView(view, true);\n        }\n        return new $.Deferred().resolve().promise();\n    }\n\n    /**\n     * Handles file system change events so we can refresh\n     *  image viewers for the files that changed on disk due to external editors\n     * @param {jQuery.event} event - event object\n     * @param {?File} file - file object that changed\n     * @param {Array.<FileSystemEntry>=} added If entry is a Directory, contains zero or more added children\n     * @param {Array.<FileSystemEntry>=} removed If entry is a Directory, contains zero or more removed children\n     */\n    function _handleFileSystemChange(event, entry, added, removed) {\n        // this may have been called because files were added\n        //  or removed to the file system.  We don't care about those\n        if (!entry || entry.isDirectory) {\n            return;\n        }\n\n        // Look for a viewer for the changed file\n        var viewer = _viewers[entry.fullPath];\n\n        // viewer found, call its refresh method\n        if (viewer) {\n            viewer.refresh();\n        }\n    }\n\n    /*\n     * Install an event listener to receive all file system change events\n     * so we can refresh the view when changes are made to the image in an external editor\n     */\n    FileSystem.on(\"change\", _handleFileSystemChange);\n\n    /*\n     * Initialization, register our view factory\n     */\n    MainViewFactory.registerViewFactory({\n        canOpenFile: function (fullPath) {\n            var lang = LanguageManager.getLanguageForPath(fullPath);\n            return (lang.getId() === \"image\");\n        },\n        openFile: function (file, pane) {\n            return _createImageView(file, pane);\n        }\n    });\n\n    /*\n     * This is for extensions that want to create a\n     * view factory based on ImageViewer\n     */\n    exports.ImageView = ImageView;\n});\n"
  },
  {
    "path": "src/editor/InlineTextEditor.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n\n// FUTURE: Merge part (or all) of this class with MultiRangeInlineEditor\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var CodeMirror          = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        InlineWidget        = require(\"editor/InlineWidget\").InlineWidget,\n        KeyEvent            = require(\"utils/KeyEvent\");\n\n    /**\n     * Shows or hides the dirty indicator\n     * @private\n     */\n    function _showDirtyIndicator($indicatorDiv, isDirty) {\n        // Show or hide the dirty indicator by adjusting\n        // the width of the div.\n        $indicatorDiv.css(\"width\", isDirty ? 16 : 0);\n    }\n\n    /**\n     * Respond to dirty flag change event. If the dirty flag is associated with an inline editor,\n     * show (or hide) the dirty indicator.\n     * @private\n     */\n    function _dirtyFlagChangeHandler(event, doc) {\n        var $dirtyIndicators = $(\".inline-text-editor .dirty-indicator\"),\n            $indicator;\n\n        $dirtyIndicators.each(function (index, indicator) {\n            $indicator = $(this);\n            if ($indicator.data(\"fullPath\") === doc.file.fullPath) {\n                _showDirtyIndicator($indicator, doc.isDirty);\n            }\n        });\n    }\n\n    /**\n     * @constructor\n     * @extends {InlineWidget}\n     */\n    function InlineTextEditor() {\n        InlineWidget.call(this);\n\n        this.editor = null;\n\n        // We need to set this as a capture handler so CodeMirror doesn't handle Esc before we see it.\n        this.handleKeyDown = this.handleKeyDown.bind(this);\n        this.htmlContent.addEventListener(\"keydown\", this.handleKeyDown, true);\n    }\n    InlineTextEditor.prototype = Object.create(InlineWidget.prototype);\n    InlineTextEditor.prototype.constructor = InlineTextEditor;\n    InlineTextEditor.prototype.parentClass = InlineWidget.prototype;\n\n    InlineTextEditor.prototype.$wrapper = null;\n    /** @type {Editor} */\n    InlineTextEditor.prototype.editor = null;\n    InlineTextEditor.prototype.$editorHolder = null;\n    InlineTextEditor.prototype.$header = null;\n    InlineTextEditor.prototype.$filename = null;\n\n   /**\n     * Given a host editor and its inline editors, find the widest gutter and make all the others match\n     * @param {!Editor} hostEditor Host editor containing all the inline editors to sync\n     * @private\n     */\n    function _syncGutterWidths(hostEditor) {\n        var allHostedEditors = EditorManager.getInlineEditors(hostEditor);\n\n        // add the host itself to the list too\n        allHostedEditors.push(hostEditor);\n\n        var maxWidth = 0;\n        allHostedEditors.forEach(function (editor) {\n            var $gutter = $(editor._codeMirror.getGutterElement()).find(\".CodeMirror-linenumbers\");\n            $gutter.css(\"min-width\", \"\");\n            var curWidth = $gutter.width();\n            if (curWidth > maxWidth) {\n                maxWidth = curWidth;\n            }\n        });\n\n        if (allHostedEditors.length === 1) {\n            //There's only the host, just refresh the gutter\n            allHostedEditors[0]._codeMirror.setOption(\"gutters\", allHostedEditors[0]._codeMirror.getOption(\"gutters\"));\n            return;\n        }\n\n        maxWidth = maxWidth + \"px\";\n        allHostedEditors.forEach(function (editor) {\n            $(editor._codeMirror.getGutterElement()).find(\".CodeMirror-linenumbers\").css(\"min-width\", maxWidth);\n\n            // Force CodeMirror to refresh the gutter\n            editor._codeMirror.setOption(\"gutters\", editor._codeMirror.getOption(\"gutters\"));\n        });\n    }\n\n    /**\n     * Called any time inline was closed, whether manually (via close()) or automatically\n     */\n    InlineTextEditor.prototype.onClosed = function () {\n        InlineTextEditor.prototype.parentClass.onClosed.apply(this, arguments);\n\n        _syncGutterWidths(this.hostEditor);\n\n        // Destroy the inline editor.\n        this.setInlineContent(null);\n        this.htmlContent.removeEventListener(\"keydown\", this.handleKeyDown, true);\n    };\n\n    /**\n     * Update the inline editor's height when the number of lines change. The\n     * base implementation of this method does nothing.\n     */\n    InlineTextEditor.prototype.sizeInlineWidgetToContents = function () {\n        // brackets_codemirror_overrides.css adds height:auto to CodeMirror\n        // Inline editors themselves do not need to be sized, but layouts like\n        // the one used in CSSInlineEditor do need some manual layout.\n    };\n\n    /**\n     * Some tasks have to wait until we've been parented into the outer editor\n     * @param {string} the inline ID that is generated by CodeMirror after the widget that holds the inline\n     *  editor is constructed and added to the DOM\n     */\n    InlineTextEditor.prototype.onAdded = function () {\n        var self = this;\n\n        InlineTextEditor.prototype.parentClass.onAdded.apply(this, arguments);\n\n        if (this.editor) {\n            this.editor.refresh();\n        }\n\n        // Update display of inline editors when the hostEditor signals a redraw\n        CodeMirror.on(this.info, \"redraw\", function () {\n            // At the point where we get the redraw, CodeMirror might not yet have actually\n            // re-added the widget to the DOM. This is filed as https://github.com/codemirror/CodeMirror/issues/1226.\n            // For now, we can work around it by doing the refresh on a setTimeout().\n            window.setTimeout(function () {\n                if (self.editor) {\n                    self.editor.refresh();\n                }\n            }, 0);\n        });\n\n        _syncGutterWidths(this.hostEditor);\n\n        if (this.editor) {\n            this.editor.focus();\n        }\n    };\n\n    /**\n     * @return {?Editor} If an Editor within this inline editor has focus, returns it. Otherwise returns null.\n     */\n    InlineTextEditor.prototype.getFocusedEditor = function () {\n        if (this.editor && this.editor.hasFocus()) {\n            return this.editor;\n        }\n        return null;\n    };\n\n    /**\n     * @private\n     * Make sure that if we want to handle Esc to cancel a multiple selection, we don't let it bubble\n     * up to InlineWidget, which will close the edit.\n     */\n    InlineTextEditor.prototype.handleKeyDown = function (e) {\n        if (e.keyCode === KeyEvent.DOM_VK_ESCAPE && this.editor && this.editor.getSelections().length > 1) {\n            CodeMirror.commands.singleSelection(this.editor._codeMirror);\n            e.stopImmediatePropagation();\n        }\n    };\n\n    /**\n     * Sets the document and range to show in the inline editor, or null to destroy the current editor and leave\n     * the content blank.\n     * @param {Document} doc The document to show, or null to show nothing\n     * @param {number} startLine The first line of text in `doc` to show in inline editor. Ignored if doc is null.\n     * @param {number} endLine The last line of text in `doc` to show in inline editor. Ignored if doc is null.\n     */\n    InlineTextEditor.prototype.setInlineContent = function (doc, startLine, endLine) {\n        var self = this;\n\n        // Destroy the previous editor if we had one and clear out the filename info.\n        if (this.editor) {\n            this.editor.off(\".InlineTextEditor\");\n            this.editor.destroy(); // remove from DOM and release ref on Document\n            this.editor = null;\n            this.$filename.off(\".InlineTextEditor\")\n                .removeAttr(\"title\");\n            this.$filename.html(\"\");\n        }\n\n        if (!doc) {\n            return;\n        }\n\n        var range = {\n            startLine: startLine,\n            endLine: endLine\n        };\n\n        // dirty indicator, with file path stored on it\n        var $dirtyIndicatorDiv = $(\"<div/>\")\n            .addClass(\"dirty-indicator\")\n            .html(\"&bull;\")\n            .width(0); // initialize indicator as hidden\n        $dirtyIndicatorDiv.data(\"fullPath\", doc.file.fullPath);\n\n        this.$lineNumber = $(\"<span class='line-number'/>\");\n\n        // update contents of filename link\n        this.$filename.append($dirtyIndicatorDiv)\n            .append(doc.file.name + \" : \")\n            .append(this.$lineNumber)\n            .attr(\"title\", doc.file.fullPath);\n\n        // clicking filename jumps to full editor view\n        this.$filename.on(\"click.InlineTextEditor\", function () {\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: doc.file.fullPath })\n                .done(function () {\n                    EditorManager.getCurrentFullEditor().setCursorPos(startLine, 0, true);\n                });\n        });\n\n        var inlineInfo = EditorManager.createInlineEditorForDocument(doc, range, this.$editorHolder.get(0));\n        this.editor = inlineInfo.editor;\n\n        // Init line number display\n        this._updateLineRange(inlineInfo.editor);\n\n        // Always update the widget height when an inline editor completes a\n        // display update\n        this.editor.on(\"update.InlineTextEditor\", function (event, editor) {\n            self.sizeInlineWidgetToContents();\n        });\n\n        // Size editor to content whenever text changes (via edits here or any\n        // other view of the doc: Editor fires \"change\" any time its text\n        // changes, regardless of origin)\n        this.editor.on(\"change.InlineTextEditor\", function (event, editor) {\n            if (self.hostEditor.isFullyVisible()) {\n                self.sizeInlineWidgetToContents();\n                self._updateLineRange(editor);\n            }\n        });\n\n        // If Document's file is deleted, or Editor loses sync with Document, delegate to this._onLostContent()\n        this.editor.on(\"lostContent.InlineTextEditor\", function () {\n            self._onLostContent.apply(self, arguments);\n        });\n\n        // set dirty indicator state\n        _showDirtyIndicator($dirtyIndicatorDiv, doc.isDirty);\n    };\n\n    /**\n     * Updates start line display.\n     * @param {Editor} editor\n     */\n    InlineTextEditor.prototype._updateLineRange = function (editor) {\n        this._startLine = editor.getFirstVisibleLine();\n        this._endLine = editor.getLastVisibleLine();\n        this._lineCount = this._endLine - this._startLine;\n\n        this.$lineNumber.text(this._startLine + 1);\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineTextEditor.prototype.load = function (hostEditor) {\n        InlineTextEditor.prototype.parentClass.load.apply(this, arguments);\n\n        // We don't create the actual editor here--that will happen the first time\n        // setInlineContent() is called.\n        this.$wrapper = $(\"<div/>\").addClass(\"inline-text-editor\").appendTo(this.$htmlContent);\n        this.$header = $(\"<div/>\").addClass(\"inline-editor-header\").appendTo(this.$wrapper);\n        this.$filename = $(\"<a/>\").addClass(\"filename\").appendTo(this.$header);\n        this.$editorHolder = $(\"<div/>\").addClass(\"inline-editor-holder\").appendTo(this.$wrapper);\n    };\n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineTextEditor.prototype.onParentShown = function () {\n        InlineTextEditor.prototype.parentClass.onParentShown.apply(this, arguments);\n\n        // Refresh line number display and codemirror line number gutter\n        if (this.editor) {\n            this._updateLineRange(this.editor);\n            this.editor.refresh();\n        }\n\n        // We need to call this explicitly whenever the host editor is reshown\n        this.sizeInlineWidgetToContents();\n    };\n\n    /**\n     * If Document's file is deleted, or Editor loses sync with Document, just close\n     */\n    InlineTextEditor.prototype._onLostContent = function () {\n        // Note: this closes the entire inline widget if any one Editor loses sync. This seems\n        // better than leaving it open but suddenly removing one rule from the result list.\n        this.close();\n    };\n\n\n    // Consolidate all dirty document updates\n    // Due to circular dependencies, not safe to call on() directly\n    EventDispatcher.on_duringInit(DocumentManager, \"dirtyFlagChange\", _dirtyFlagChangeHandler);\n\n    exports.InlineTextEditor = InlineTextEditor;\n\n});\n"
  },
  {
    "path": "src/editor/InlineWidget.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var EditorManager       = require(\"editor/EditorManager\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        KeyEvent            = require(\"utils/KeyEvent\");\n\n    /**\n     * @constructor\n     *\n     */\n    function InlineWidget() {\n        var self = this;\n\n        // create the outer wrapper div\n        this.htmlContent = window.document.createElement(\"div\");\n        this.$htmlContent = $(this.htmlContent).addClass(\"inline-widget\").attr(\"tabindex\", \"-1\");\n        this.$htmlContent.append(\"<div class='shadow top' />\")\n            .append(\"<div class='shadow bottom' />\")\n            .append(\"<a href='#' class='close no-focus'>&times;</a>\");\n\n        // create the close button\n        this.$closeBtn = this.$htmlContent.find(\".close\");\n        this.$closeBtn.click(function (e) {\n            self.close();\n            e.stopImmediatePropagation();\n        });\n\n        this.$htmlContent.on(\"keydown\", function (e) {\n            if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                self.close();\n                e.stopImmediatePropagation();\n            }\n        });\n    }\n    InlineWidget.prototype.htmlContent = null;\n    InlineWidget.prototype.$htmlContent = null;\n    InlineWidget.prototype.id = null;\n    InlineWidget.prototype.hostEditor = null;\n    EventDispatcher.makeEventDispatcher(InlineWidget.prototype);\n\n    /**\n     * Initial height of inline widget in pixels. Can be changed later via hostEditor.setInlineWidgetHeight()\n     * @type {number}\n     */\n    InlineWidget.prototype.height = 0;\n\n    /**\n     * Closes this inline widget and all its contained Editors\n     * @return {$.Promise} A promise that's resolved when the widget is fully closed.\n     */\n    InlineWidget.prototype.close = function () {\n        return EditorManager.closeInlineWidget(this.hostEditor, this);\n        // closeInlineWidget() causes our onClosed() handler to be called\n    };\n\n    /**\n     * @return {boolean} True if any part of the inline widget is focused\n     */\n    InlineWidget.prototype.hasFocus = function () {\n        var focusedItem = window.document.activeElement,\n            htmlContent = this.$htmlContent[0];\n        return $.contains(htmlContent, focusedItem) || htmlContent === focusedItem;\n    };\n\n    /**\n     * Called any time inline is closed, whether manually or automatically.\n     */\n    InlineWidget.prototype.onClosed = function () {\n        this.trigger(\"close\");\n    };\n\n    /**\n     * Called once content is parented in the host editor's DOM. Useful for performing tasks like setting\n     * focus or measuring content, which require htmlContent to be in the DOM tree.\n     *\n     * IMPORTANT: onAdded() MUST be overridden to call hostEditor.setInlineWidgetHeight() at least once to\n     * set the initial height (required to animate it open). The widget will never open otherwise.\n     */\n    InlineWidget.prototype.onAdded = function () {\n        this.trigger(\"add\");\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineWidget.prototype.load = function (hostEditor) {\n        this.hostEditor = hostEditor;\n    };\n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineWidget.prototype.onParentShown = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * Called when the parent editor does a full refresh--for example, when the font size changes.\n     */\n    InlineWidget.prototype.refresh = function () {\n        // do nothing - base implementation\n    };\n\n    exports.InlineWidget = InlineWidget;\n\n});\n"
  },
  {
    "path": "src/editor/MultiRangeInlineEditor.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n// FUTURE: Merge part (or all) of this class with InlineTextEditor\n\n/**\n * An inline editor for displaying and editing multiple text ranges. Each range corresponds to a\n * contiguous set of lines in a file.\n *\n * In the current implementation, only one range is visible at a time. A list on the right side\n * of the editor allows the user to select which range is visible.\n *\n * This module does not dispatch any events.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    // Load dependent modules\n    var TextRange           = require(\"document/TextRange\").TextRange,\n        InlineTextEditor    = require(\"editor/InlineTextEditor\").InlineTextEditor,\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        CommandManager      = require(\"command/CommandManager\");\n\n    var _prevMatchCmd, _nextMatchCmd;\n\n    /**\n     * Remove trailing \"px\" from a style size value.\n     * @param {!JQuery} $target Element in DOM\n     * @param {!string} styleName Style name to query\n     * @return {number} Style value converted from string to number, removing \"px\" units\n     */\n    function _parseStyleSize($target, styleName) {\n        return parseInt($target.css(styleName), 10);\n    }\n\n    /** Returns a 'context' object for getting/setting project-specific preferences */\n    function _getPrefsContext() {\n        var projectRoot = ProjectManager.getProjectRoot();  // note: null during unit tests!\n        return { location : { scope: \"user\", layer: \"project\", layerID: projectRoot && projectRoot.fullPath } };\n    }\n\n\n    /**\n     * Stores one search result: its source file, line range, etc. plus the DOM node representing it\n     * in the results list.\n     * @constructor\n     */\n    function SearchResultItem(rangeResult) {\n        this.name = rangeResult.name;\n        this.textRange = new TextRange(rangeResult.document, rangeResult.lineStart, rangeResult.lineEnd);\n        // this.$listItem is assigned in load()\n    }\n    SearchResultItem.prototype.name = null;\n    SearchResultItem.prototype.textRange = null;\n    SearchResultItem.prototype.$listItem = null;\n\n    function _updateRangeLabel(listItem, range, labelCB) {\n        if (labelCB) {\n            range.name = labelCB(range.textRange);\n        }\n        var text = _.escape(range.name) + \" <span class='related-file'>:\" + (range.textRange.startLine + 1) + \"</span>\";\n        listItem.html(text);\n        listItem.attr(\"title\", listItem.text());\n    }\n\n\n    /**\n     * @constructor\n     * @param {Array.<{name:String,document:Document,lineStart:number,lineEnd:number}>} ranges The text\n     *      ranges to display. Results within the same file are expected to be contiguous in this array.\n     * @param {?function(): $.Promise} messageCB Optional; returns a promise resolved with a message to\n     *      show when no matches are available. The message should be already-escaped HTML.\n     * @param {?function(range): string} labelCB Optional; returns an updated label string for the given\n     *      range. Called when we detect that the content of a range has changed. The label is plain\n     *      text, not HTML.\n     * @param {?function(!File, !File):number} fileComparator Optional comparison function for sorting\n     *      the results list (based on range.document.file). Defaults to FileUtils.comparePaths().\n     * @extends {InlineTextEditor}\n     */\n    function MultiRangeInlineEditor(ranges, messageCB, labelCB, fileComparator) {\n        InlineTextEditor.call(this);\n\n        // Store the results to show in the range list. This creates TextRanges bound to the Document,\n        // which will stay up to date automatically (but we must be sure to detach them later)\n        this._ranges = ranges.map(function (rangeResult) {\n            return new SearchResultItem(rangeResult);\n        });\n        this._messageCB = messageCB;\n        this._labelCB = labelCB;\n\n        this._selectedRangeIndex = -1;\n        this._collapsedFiles = {};\n\n        // Set up list sort order\n        this._fileComparator = fileComparator || function defaultComparator(file1, file2) {\n            return FileUtils.comparePaths(file1.fullPath, file2.fullPath);\n        };\n        this._ranges.sort(function (result1, result2) {\n            return this._fileComparator(result1.textRange.document.file, result2.textRange.document.file);\n        }.bind(this));\n    }\n    MultiRangeInlineEditor.prototype = Object.create(InlineTextEditor.prototype);\n    MultiRangeInlineEditor.prototype.constructor = MultiRangeInlineEditor;\n    MultiRangeInlineEditor.prototype.parentClass = InlineTextEditor.prototype;\n\n    MultiRangeInlineEditor.prototype.$messageDiv = null;\n    MultiRangeInlineEditor.prototype.$relatedContainer = null;\n    MultiRangeInlineEditor.prototype.$related = null;\n    MultiRangeInlineEditor.prototype.$selectedMarker = null;\n\n    /** Includes all the _ranges[i].$listItem items, as well as section headers */\n    MultiRangeInlineEditor.prototype.$rangeList = null;\n\n    /**\n     * List of search results. Section headers are not represented in this list (they are implied before each group of\n     * of consecutive results from the same Document).\n     * @type {!Array.<SearchResultItem>}\n     */\n    MultiRangeInlineEditor.prototype._ranges = null;\n\n    /** Index into this._ranges - indices do not include section headers */\n    MultiRangeInlineEditor.prototype._selectedRangeIndex = null;\n\n    /**\n     * Map from fullPath to true if collapsed. May not agree with preferences, in cases where multiple inline editors make\n     * concurrent changes.\n     * @type {!Object.<string, boolean>}\n     */\n    MultiRangeInlineEditor.prototype._collapsedFiles = null;\n\n    MultiRangeInlineEditor.prototype._messageCB = null;\n    MultiRangeInlineEditor.prototype._labelCB = null;\n    MultiRangeInlineEditor.prototype._fileComparator = null;\n\n    /** @type {!Object.<string, jQueryObject>} Map from fullPath to section header DOM node */\n    MultiRangeInlineEditor.prototype._$headers = null;\n\n\n    /**\n     * @private\n     * Add a new result item <li> to the range list UI ($rangeList) and saves it in range.$listItem\n     * @param {SearchResultItem} range The range to add.\n     */\n    MultiRangeInlineEditor.prototype._createListItem = function (range) {\n        var self = this,\n            $rangeItem = $(\"<li/>\");\n\n        // Attach filename for unit test use\n        $rangeItem.data(\"filename\", range.textRange.document.file.name);\n\n        $rangeItem.appendTo(this.$rangeList);\n\n        _updateRangeLabel($rangeItem, range);\n        $rangeItem.mousedown(function () {\n            self.setSelectedIndex(self._ranges.indexOf(range));\n        });\n\n        range.$listItem = $rangeItem;\n    };\n\n    /** Collapses/expands a file section in the range list UI */\n    MultiRangeInlineEditor.prototype._toggleSection = function (fullPath, duringInit) {\n        var $headerItem = this._$headers[fullPath];\n        var $disclosureIcon = $headerItem.find(\".disclosure-triangle\");\n        var isCollapsing = $disclosureIcon.hasClass(\"expanded\");\n        $disclosureIcon.toggleClass(\"expanded\");\n        $headerItem.nextUntil(\".section-header\").toggle(!isCollapsing);  // explicit visibility arg, since during load() jQ doesn't think nodes are visible\n\n        // Update instance-specific state...\n        this._collapsedFiles[fullPath] = isCollapsing;\n        // ...AND persist as per-project view state\n        if (!duringInit) {\n            var setting = PreferencesManager.getViewState(\"inlineEditor.collapsedFiles\", _getPrefsContext()) || {};\n            if (isCollapsing) {\n                setting[fullPath] = true;\n            } else {\n                delete setting[fullPath];\n            }\n            PreferencesManager.setViewState(\"inlineEditor.collapsedFiles\", setting, _getPrefsContext());\n        }\n\n        // Show/hide selection indicator if selection was in collapsed section\n        this._updateSelectedMarker(false);\n\n        // Changing height of rule list may change ht of overall editor\n        this._ruleListHeightChanged();\n\n        // If user expands collapsed section and nothing selected yet, select first result in this section\n        if (this._selectedRangeIndex === -1 && !isCollapsing && !duringInit) {\n            var index = _.findIndex(this._ranges, function (resultItem) {\n                return resultItem.textRange.document.file.fullPath === fullPath;\n            });\n            this.setSelectedIndex(index);\n        }\n    };\n\n    /** Adds a file section header <li> to the range list UI ($rangeList) and adds it to the this._$headers map */\n    MultiRangeInlineEditor.prototype._createHeaderItem = function (doc) {\n        var $headerItem = $(\"<li class='section-header'><span class='disclosure-triangle expanded'/><span class='filename'>\" + _.escape(doc.file.name) + \"</span></li>\")\n            .attr(\"title\", ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n            .appendTo(this.$rangeList);\n\n        $headerItem.click(function () {\n            this._toggleSection(doc.file.fullPath);\n        }.bind(this));\n\n        this._$headers[doc.file.fullPath] = $headerItem;\n    };\n\n    /** Refresh the contents of $rangeList */\n    MultiRangeInlineEditor.prototype._renderList = function () {\n        this.$rangeList.empty();\n        this._$headers = {};\n\n        var self = this,\n            lastSectionDoc,\n            numItemsInSection = 0;\n\n        // After seeing all results for a given file, update its header with total # of results\n        function finalizeSection() {\n            if (lastSectionDoc) {\n                self._$headers[lastSectionDoc.file.fullPath].append(\" (\" + numItemsInSection + \")\");\n                if (self._collapsedFiles[lastSectionDoc.file.fullPath]) {\n                    self._toggleSection(lastSectionDoc.file.fullPath, true);\n                }\n            }\n        }\n\n        this._ranges.forEach(function (resultItem) {\n            if (lastSectionDoc !== resultItem.textRange.document) {\n                // Finalize previous section\n                finalizeSection();\n\n                // Initialize new section\n                lastSectionDoc = resultItem.textRange.document;\n                numItemsInSection = 0;\n\n                // Create filename header for new section\n                this._createHeaderItem(lastSectionDoc);\n            }\n            numItemsInSection++;\n            this._createListItem(resultItem);\n        }, this);\n\n        // Finalize last section\n        finalizeSection();\n    };\n\n\n    /**\n     * @override\n     * @param {!Editor} hostEditor  Outer Editor instance that inline editor will sit within.\n     *\n     */\n    MultiRangeInlineEditor.prototype.load = function (hostEditor) {\n        MultiRangeInlineEditor.prototype.parentClass.load.apply(this, arguments);\n\n        // Create the message area\n        this.$messageDiv = $(\"<div/>\")\n            .addClass(\"inline-editor-message\");\n\n        // Prevent touch scroll events from bubbling up to the parent editor.\n        this.$editorHolder.on(\"mousewheel.MultiRangeInlineEditor\", function (e) {\n            e.stopPropagation();\n        });\n\n        // Outer container for border-left and scrolling\n        this.$relatedContainer = $(\"<div/>\").addClass(\"related-container\");\n\n        // List \"selection\" highlight\n        this.$selectedMarker = $(\"<div/>\").appendTo(this.$relatedContainer).addClass(\"selection\");\n\n        // Inner container\n        this.$related = $(\"<div/>\").appendTo(this.$relatedContainer).addClass(\"related\");\n\n        // Range list\n        this.$rangeList = $(\"<ul/>\").appendTo(this.$related);\n\n        // Determine which sections are initially collapsed (the actual collapsing happens after onAdded(),\n        // because jQuery.hide() requires the computed value of 'display' to work properly)\n        var toCollapse = PreferencesManager.getViewState(\"inlineEditor.collapsedFiles\", _getPrefsContext()) || {};\n        Object.keys(toCollapse).forEach(function (fullPath) {\n            this._collapsedFiles[fullPath] = true;\n        }.bind(this));\n\n        // Render list & section headers (matching collapsed state set above)\n        this._renderList();\n\n        if (this._ranges.length > 1) {      // attach to main container\n            this.$wrapper.before(this.$relatedContainer);\n        }\n\n        // Add TextRange listeners to update UI as text changes\n        var self = this;\n        this._ranges.forEach(function (range, index) {\n            // Update list item as TextRange changes\n            range.textRange.on(\"change\", function () {\n                _updateRangeLabel(range.$listItem, range);\n            }).on(\"contentChange\", function () {\n                _updateRangeLabel(range.$listItem, range, self._labelCB);\n            });\n\n            // If TextRange lost sync, remove it from the list (and close the widget if no other ranges are left)\n            range.textRange.on(\"lostSync\", function () {\n                self._removeRange(range);\n            });\n        });\n\n        // Initial selection is the first non-collapsed result item\n        var indexToSelect = _.findIndex(this._ranges, function (range) {\n            return !this._collapsedFiles[range.textRange.document.file.fullPath];\n        }.bind(this));\n        if (this._ranges.length === 1 && indexToSelect === -1) {\n            // If no right-hand rule list shown, select the one result even if it's in a collapsed file (since no way to expand)\n            indexToSelect = 0;\n        }\n\n        if (indexToSelect !== -1) {\n            // select the first visible range\n            this.setSelectedIndex(indexToSelect);\n        } else {\n            // force the message div to show\n            this.setSelectedIndex(-1);\n        }\n\n        // Listen for clicks directly on us, so we can set focus back to the editor\n        var clickHandler = this._onClick.bind(this);\n        this.$htmlContent.on(\"click.MultiRangeInlineEditor\", clickHandler);\n        // Also handle mouseup in case the user drags a little bit\n        this.$htmlContent.on(\"mouseup.MultiRangeInlineEditor\", clickHandler);\n\n        // Update the rule list navigation menu items when we gain/lose focus.\n        this.$htmlContent\n            .on(\"focusin.MultiRangeInlineEditor\", this._updateCommands.bind(this))\n            .on(\"focusout.MultiRangeInlineEditor\", this._updateCommands.bind(this));\n    };\n\n    /**\n     * @private\n     * Updates the enablement for the rule list navigation commands.\n     */\n    MultiRangeInlineEditor.prototype._updateCommands = function () {\n        var enabled = (this.hasFocus() && this._ranges.length > 1);\n        _prevMatchCmd.setEnabled(enabled && this._selectedRangeIndex > 0);\n        _nextMatchCmd.setEnabled(enabled && this._selectedRangeIndex !== -1 && this._selectedRangeIndex < this._ranges.length - 1);\n    };\n\n    /**\n     * @override\n     */\n    MultiRangeInlineEditor.prototype.onAdded = function () {\n        // Set the initial position of the selected marker now that we're laid out.\n        this._updateSelectedMarker(false);\n\n        // Call super\n        MultiRangeInlineEditor.prototype.parentClass.onAdded.apply(this, arguments);\n\n        // Initially size the inline widget (calls sizeInlineWidgetToContents())\n        this._ruleListHeightChanged();\n\n        this._updateCommands();\n    };\n\n    /**\n     * Specify the range that is shown in the editor.\n     *\n     * @param {!number} index The index of the range to select, or -1 to deselect all. Index into this._ranges,\n     *      so section headers are not included in the sequence.\n     * @param {boolean} force Whether to re-select the item even if we think it's already selected\n     *     (used if the range list has changed).\n     */\n    MultiRangeInlineEditor.prototype.setSelectedIndex = function (index, force) {\n        var newIndex = Math.min(Math.max(-1, index), this._ranges.length - 1),\n            self = this;\n\n        if (!force && newIndex !== -1 && newIndex === this._selectedRangeIndex) {\n            return;\n        }\n\n        // Remove selected class(es)\n        var $previousItem = (this._selectedRangeIndex >= 0) ? this._ranges[this._selectedRangeIndex].$listItem : null;\n        if ($previousItem) {\n            $previousItem.removeClass(\"selected\");\n        }\n\n        // Clear our listeners on the previous editor since it'll be destroyed in setInlineContent().\n        if (this.editor) {\n            this.editor.off(\".MultiRangeInlineEditor\");\n        }\n\n        this._selectedRangeIndex = newIndex;\n\n        if (newIndex === -1) {\n            // show the message div\n            this.setInlineContent(null);\n            var hasHiddenMatches = this._ranges.length > 0;\n            if (hasHiddenMatches) {\n                this.$messageDiv.text(Strings.INLINE_EDITOR_HIDDEN_MATCHES);\n            } else if (this._messageCB) {\n                this._messageCB(hasHiddenMatches).done(function (msg) {\n                    self.$messageDiv.html(msg);\n                });\n            } else {\n                this.$messageDiv.text(Strings.INLINE_EDITOR_NO_MATCHES);\n            }\n            this.$htmlContent.append(this.$messageDiv);\n            this.sizeInlineWidgetToContents();\n        } else {\n            this.$messageDiv.remove();\n\n            var range = this._getSelectedRange();\n            range.$listItem.addClass(\"selected\");\n\n            // Add new editor\n            this.setInlineContent(range.textRange.document, range.textRange.startLine, range.textRange.endLine);\n            this.editor.focus();\n\n            this._updateEditorMinHeight();\n            this.editor.refresh();\n\n            // Ensure the cursor position is visible in the host editor as the user is arrowing around.\n            this.editor.on(\"cursorActivity.MultiRangeInlineEditor\", this._ensureCursorVisible.bind(this));\n\n            // ensureVisibility is set to false because we don't want to scroll the main editor when the user selects a view\n            this.sizeInlineWidgetToContents();\n\n            this._updateSelectedMarker(true);\n        }\n\n        this._updateCommands();\n    };\n\n    /**\n     * Ensures that the editor's min-height is set so it never gets shorter than the rule list.\n     * This is necessary to make sure the editor's horizontal scrollbar stays at the bottom of the\n     * widget.\n     */\n    MultiRangeInlineEditor.prototype._updateEditorMinHeight = function () {\n        if (!this.editor) {\n            return;\n        }\n\n        // Set the scroller's min-height to the natural height of the rule list, so the editor\n        // always stays at least as tall as the rule list.\n        var ruleListNaturalHeight = this.$related.outerHeight(),\n            headerHeight = $(\".inline-editor-header\", this.$htmlContent).outerHeight();\n\n        // If the widget isn't fully loaded yet, bail--we'll get called again in onAdded().\n        if (!ruleListNaturalHeight || !headerHeight) {\n            return;\n        }\n\n        // We have to set this on the scroller instead of the wrapper because:\n        // * we want the wrapper's actual height to remain \"auto\"\n        // * if we set a min-height on the wrapper, the scroller's height: 100% doesn't\n        //   respect it (height: 100% doesn't seem to work properly with min-height on the parent)\n        $(this.editor.getScrollerElement())\n            .css(\"min-height\", (ruleListNaturalHeight - headerHeight) + \"px\");\n    };\n\n    /** Update inline widget height to reflect changed rule-list height */\n    MultiRangeInlineEditor.prototype._ruleListHeightChanged = function () {\n        // Editor's min height depends on rule list height\n        this._updateEditorMinHeight();\n\n        // Overall widget height may have changed too\n        this.sizeInlineWidgetToContents();\n    };\n\n    MultiRangeInlineEditor.prototype._removeRange = function (range) {\n        // If this is the last range, just close the whole widget\n        if (this._ranges.length <= 1) {\n            this.close();\n            return;  // note: the dispose() that would normally happen below is covered by close()\n        }\n\n        // Now we know there is at least one other range -> found out which one this is\n        var index = this._ranges.indexOf(range);\n\n        // If the range to be removed is the selected one, first switch to another one\n        if (index === this._selectedRangeIndex) {\n            // If possible, select the one below, else select the one above\n            if (index + 1 < this._ranges.length) {\n                this.setSelectedIndex(index + 1);\n            } else {\n                this.setSelectedIndex(index - 1);\n            }\n        }\n\n        // Now we can remove this range\n        range.textRange.dispose();\n        this._ranges.splice(index, 1);\n\n        // Re-render list & section headers\n        this._renderList();\n\n        // Move selection highlight if deletion affected its position\n        if (index < this._selectedRangeIndex) {\n            this._selectedRangeIndex--;\n            this._updateSelectedMarker(true);\n        }\n\n        if (this._ranges.length === 1) {\n            this.$relatedContainer.remove();\n\n            // Refresh the height of the inline editor since we remove\n            // the entire selector list.\n            if (this.editor) {\n                this.editor.refresh();\n            }\n        }\n\n        this._updateCommands();\n    };\n\n    /**\n     * Adds a new range to the inline editor and selects it. The range will be inserted\n     * immediately below the last range for the same document, or at the end of the list\n     * if there are no other ranges for that document.\n     * @param {string} name The label for the new range.\n     * @param {Document} doc The document the range is in.\n     * @param {number} lineStart The starting line of the range, 0-based, inclusive.\n     * @param {number} lineEnd The ending line of the range, 0-based, inclusive.\n     */\n    MultiRangeInlineEditor.prototype.addAndSelectRange = function (name, doc, lineStart, lineEnd) {\n        var newRange = new SearchResultItem({\n                name: name,\n                document: doc,\n                lineStart: lineStart,\n                lineEnd: lineEnd\n            }),\n            i;\n\n        // Insert the new range after the last range from the same doc, or at the\n        // end of the list.\n        for (i = 0; i < this._ranges.length; i++) {\n            if (this._fileComparator(this._ranges[i].textRange.document.file, doc.file) > 0) {\n                break;\n            }\n        }\n        this._ranges.splice(i, 0, newRange);\n\n        // Update rule list display\n        this._renderList();\n\n        // Ensure rule list is visible if there are now multiple results\n        if (this._ranges.length > 1 && !this.$relatedContainer.parent().length) {\n            this.$wrapper.before(this.$relatedContainer);\n        }\n\n        // If added rule is in a collapsed item, expand it for clarity\n        if (this._collapsedFiles[doc.file.fullPath]) {\n            this._toggleSection(doc.file.fullPath);\n        }\n\n        // Select new range, showing it in the editor\n        this.setSelectedIndex(i, true);  // force, since i might be same as before\n\n        this._updateCommands();\n    };\n\n    MultiRangeInlineEditor.prototype._updateSelectedMarker = function (animate) {\n        // If no selection or selection is in a collapsed section, just hide the marker\n        if (this._selectedRangeIndex < 0 || this._collapsedFiles[this._getSelectedRange().textRange.document.file.fullPath]) {\n            this.$selectedMarker.hide();\n            return;\n        }\n\n        var $rangeItem = this._ranges[this._selectedRangeIndex].$listItem;\n\n        // scroll the selection to the rangeItem\n        var containerHeight = this.$relatedContainer.height(),\n            itemTop = $rangeItem.position().top,\n            scrollTop = this.$relatedContainer.scrollTop();\n\n        this.$selectedMarker\n            .show()\n            .toggleClass(\"animate\", animate)\n            .css(\"top\", itemTop)\n            .height($rangeItem.outerHeight());\n\n        if (containerHeight <= 0) {\n            return;\n        }\n\n        var paddingTop = _parseStyleSize($rangeItem.parent(), \"paddingTop\");\n\n        if ((itemTop - paddingTop) < scrollTop) {\n            this.$relatedContainer.scrollTop(itemTop - paddingTop);\n        } else {\n            var itemBottom = itemTop + $rangeItem.height() + _parseStyleSize($rangeItem.parent(), \"paddingBottom\");\n\n            if (itemBottom > (scrollTop + containerHeight)) {\n                this.$relatedContainer.scrollTop(itemBottom - containerHeight);\n            }\n        }\n    };\n\n    /**\n     * Called any time inline is closed, whether manually (via closeThisInline()) or automatically\n     */\n    MultiRangeInlineEditor.prototype.onClosed = function () {\n        // Superclass onClosed() destroys editor\n        MultiRangeInlineEditor.prototype.parentClass.onClosed.apply(this, arguments);\n\n        // de-ref all the Documents in the search results\n        this._ranges.forEach(function (searchResult) {\n            searchResult.textRange.dispose();\n        });\n\n        // Remove event handlers\n        this.$htmlContent.off(\".MultiRangeInlineEditor\");\n        this.$editorHolder.off(\".MultiRangeInlineEditor\");\n    };\n\n    /**\n     * Prevent clicks in the dead areas of the inlineWidget from changing the focus and insertion point in the editor.\n     * This is done by detecting clicks in the inlineWidget that are not inside the editor or the range list and\n     * restoring focus and the insertion point.\n     */\n    MultiRangeInlineEditor.prototype._onClick = function (event) {\n        if (!this.editor) {\n            return;\n        }\n\n        var childEditor = this.editor,\n            editorRoot = childEditor.getRootElement(),\n            editorPos = $(editorRoot).offset();\n\n        function containsClick($parent) {\n            return $parent.find(event.target).length > 0 || $parent[0] === event.target;\n        }\n\n        // Ignore clicks in editor and clicks on filename link\n        // Check clicks on filename link in the context of the current inline widget.\n        if (!containsClick($(editorRoot)) && !containsClick($(\".filename\", this.$htmlContent))) {\n            childEditor.focus();\n            // Only set the cursor if the click isn't in the range list.\n            if (!containsClick(this.$relatedContainer)) {\n                if (event.pageY < editorPos.top) {\n                    childEditor.setCursorPos(0, 0);\n                } else if (event.pageY > editorPos.top + $(editorRoot).height()) {\n                    var lastLine = childEditor.getLastVisibleLine();\n                    childEditor.setCursorPos(lastLine, childEditor.document.getLine(lastLine).length);\n                }\n            }\n        }\n    };\n\n    /**\n     * Based on the position of the cursor in the inline editor, determine whether we need to change the\n     * vertical scroll position of the host editor to ensure that the cursor is visible.\n     */\n    MultiRangeInlineEditor.prototype._ensureCursorVisible = function () {\n        if (!this.editor) {\n            return;\n        }\n\n        if ($.contains(this.editor.getRootElement(), window.document.activeElement)) {\n            var hostScrollPos = this.hostEditor.getScrollPos(),\n                cursorCoords = this.editor._codeMirror.cursorCoords();\n\n            // Vertically, we want to set the scroll position relative to the overall host editor, not\n            // the lineSpace of the widget itself. We don't want to modify the horizontal scroll position.\n            var scrollerTop = this.hostEditor.getVirtualScrollAreaTop();\n            this.hostEditor._codeMirror.scrollIntoView({\n                left: hostScrollPos.x,\n                top: cursorCoords.top - scrollerTop,\n                right: hostScrollPos.x,\n                bottom: cursorCoords.bottom - scrollerTop\n            });\n        }\n    };\n\n    /**\n     * Overwrite InlineTextEditor's _onLostContent to do nothing if the document's file is deleted\n     * (deletes are handled via TextRange's lostSync).\n     */\n    MultiRangeInlineEditor.prototype._onLostContent = function (event, cause) {\n        // Ignore when the editor's content got lost due to a deleted file\n        if (cause && cause.type === \"deleted\") { return; }\n        // Else yield to the parent's implementation\n        return MultiRangeInlineEditor.prototype.parentClass._onLostContent.apply(this, arguments);\n    };\n\n    /**\n     * @return {Array.<SearchResultItem>}\n     */\n    MultiRangeInlineEditor.prototype._getRanges = function () {\n        return this._ranges;\n    };\n\n    /**\n     * @return {!SearchResultItem}\n     */\n    MultiRangeInlineEditor.prototype._getSelectedRange = function () {\n        return this._selectedRangeIndex >= 0 ? this._ranges[this._selectedRangeIndex] : null;\n    };\n\n    /**\n     * Move the selection up or down, skipping any collapsed groups. If selection is currently IN a\n     * collapsed group, we expand it first so that other items in the same file are eligible.\n     */\n    MultiRangeInlineEditor.prototype._selectNextPrev = function (dir) {\n        if (this._selectedRangeIndex === -1) {\n            return;\n        }\n\n        // Traverse up or down the list until we find an item eligible for selection\n        var origDoc = this._ranges[this._selectedRangeIndex].textRange.document,\n            i;\n        for (i = this._selectedRangeIndex + dir; i >= 0 && i < this._ranges.length; i += dir) {\n            var doc = this._ranges[i].textRange.document;\n\n            // If first candidate is in same collapsed group as current selection, expand it\n            if (doc === origDoc && this._collapsedFiles[doc.file.fullPath]) {\n                this._toggleSection(doc.file.fullPath);\n            }\n\n            // Only consider expanded groups now\n            if (!this._collapsedFiles[doc.file.fullPath]) {\n                this.setSelectedIndex(i);\n                return;\n            }\n        }\n        // If we got here, we couldn't find any eligible item - so do nothing. Happens if selection is\n        // already the first/last item, or if all remaining items above/below the selection are collapsed.\n    };\n\n    /**\n     * Display the next range in the range list\n     */\n    MultiRangeInlineEditor.prototype._selectNextRange = function () {\n        this._selectNextPrev(1);\n    };\n\n    /**\n     *  Display the previous range in the range list\n     */\n    MultiRangeInlineEditor.prototype._selectPreviousRange = function () {\n        this._selectNextPrev(-1);\n    };\n\n    /**\n     * Sizes the inline widget height to be the maximum between the range list height and the editor height\n     * @override\n     */\n    MultiRangeInlineEditor.prototype.sizeInlineWidgetToContents = function () {\n        // Size the code mirror editors height to the editor content\n        MultiRangeInlineEditor.prototype.parentClass.sizeInlineWidgetToContents.call(this);\n\n        // Size the widget height to the max between the editor/message content and the related ranges list\n        var widgetHeight = Math.max(this.$related.height(),\n                                    this.$header.outerHeight() +\n                                        (this._selectedRangeIndex === -1 ? this.$messageDiv.outerHeight() : this.$editorHolder.height()));\n\n        if (widgetHeight) {\n            this.hostEditor.setInlineWidgetHeight(this, widgetHeight, false);\n        }\n    };\n\n    /**\n     * Called when the editor containing the inline is made visible. Updates UI based on\n     * state that might have changed while the editor was hidden.\n     */\n    MultiRangeInlineEditor.prototype.onParentShown = function () {\n        MultiRangeInlineEditor.prototype.parentClass.onParentShown.apply(this, arguments);\n        this._updateSelectedMarker(false);\n    };\n\n    /**\n     * Refreshes the height of the inline editor and all child editors.\n     * @override\n     */\n    MultiRangeInlineEditor.prototype.refresh = function () {\n        MultiRangeInlineEditor.prototype.parentClass.refresh.apply(this, arguments);\n        this.sizeInlineWidgetToContents();\n        if (this.editor) {\n            this.editor.refresh();\n        }\n    };\n\n    /**\n     * Returns the currently focused MultiRangeInlineEditor.\n     * @return {MultiRangeInlineEditor}\n     */\n    function getFocusedMultiRangeInlineEditor() {\n        var focusedWidget = EditorManager.getFocusedInlineWidget();\n        if (focusedWidget instanceof MultiRangeInlineEditor) {\n            return focusedWidget;\n        } else {\n            return null;\n        }\n    }\n\n    /**\n     * Previous Range command handler\n     */\n    function _previousRange() {\n        var focusedMultiRangeInlineEditor = getFocusedMultiRangeInlineEditor();\n        if (focusedMultiRangeInlineEditor) {\n            focusedMultiRangeInlineEditor._selectPreviousRange();\n        }\n    }\n\n    /**\n     * Next Range command handler\n     */\n    function _nextRange() {\n        var focusedMultiRangeInlineEditor = getFocusedMultiRangeInlineEditor();\n        if (focusedMultiRangeInlineEditor) {\n            focusedMultiRangeInlineEditor._selectNextRange();\n        }\n    }\n\n    _prevMatchCmd = CommandManager.register(Strings.CMD_QUICK_EDIT_PREV_MATCH, Commands.QUICK_EDIT_PREV_MATCH, _previousRange);\n    _prevMatchCmd.setEnabled(false);\n    _nextMatchCmd = CommandManager.register(Strings.CMD_QUICK_EDIT_NEXT_MATCH, Commands.QUICK_EDIT_NEXT_MATCH, _nextRange);\n    _nextMatchCmd.setEnabled(false);\n\n    exports.MultiRangeInlineEditor = MultiRangeInlineEditor;\n    exports.getFocusedMultiRangeInlineEditor = getFocusedMultiRangeInlineEditor;\n});\n"
  },
  {
    "path": "src/extensibility/ExtensionManager.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*unittests: ExtensionManager*/\n\n/**\n * The ExtensionManager fetches/caches the extension registry and provides\n * information about the status of installed extensions. ExtensionManager raises the\n * following events:\n * - statusChange - indicates that an extension has been installed/uninstalled or\n *   its status has otherwise changed. Second parameter is the id of the\n *   extension.\n * - registryUpdate - indicates that an existing extension was synchronized\n *   with new data from the registry.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                   = require(\"thirdparty/lodash\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        Package             = require(\"extensibility/Package\"),\n        AppInit             = require(\"utils/AppInit\"),\n        Async               = require(\"utils/Async\"),\n        ExtensionLoader     = require(\"utils/ExtensionLoader\"),\n        ExtensionUtils      = require(\"utils/ExtensionUtils\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        ThemeManager        = require(\"view/ThemeManager\");\n\n    // semver.browser is an AMD-compatible module\n    var semver = require(\"thirdparty/semver.browser\");\n\n    /**\n     * @private\n     * @type {$.Deferred} Keeps track of the current registry download so that if a request is already\n     * in progress and another request to download the registry comes in, we don't send yet another request.\n     * This is primarily used when multiple view models need to download the registry at the same time.\n     */\n    var pendingDownloadRegistry = null;\n\n    /**\n     * Extension status constants.\n     */\n    var ENABLED      = \"enabled\",\n        DISABLED     = \"disabled\",\n        START_FAILED = \"startFailed\";\n\n    /**\n     * Extension location constants.\n     */\n    var LOCATION_DEFAULT = \"default\",\n        LOCATION_DEV     = \"dev\",\n        LOCATION_USER    = \"user\",\n        LOCATION_UNKNOWN = \"unknown\";\n\n    /**\n     * Extension auto-install folder. Also used for preferences key.\n     */\n    var FOLDER_AUTOINSTALL = \"auto-install-extensions\";\n\n    /**\n     * @private\n     * @type {Object.<string, {metadata: Object, path: string, status: string}>}\n     * The set of all known extensions, both from the registry and locally installed.\n     * The keys are either \"name\" from package.json (for extensions that have package metadata)\n     * or the last segment of local file paths (for installed legacy extensions\n     * with no package metadata). The fields of each record are:\n     *     registryInfo: object containing the info for this id from the main registry (containing metadata, owner,\n     *         and versions). This will be null for legacy extensions.\n     *     installInfo: object containing the info for a locally-installed extension:\n     *         metadata: the package metadata loaded from the local package.json, or null if it's a legacy extension.\n     *             This will be different from registryInfo.metadata if there's a newer version in the registry.\n     *         path: the local path to the extension folder on disk\n     *         locationType: general type of installation; one of the LOCATION_* constants above\n     *         status: the current status, one of the status constants above\n     */\n    var extensions = {};\n\n    /**\n     * Requested changes to the installed extensions.\n     */\n    var _idsToRemove = {},\n        _idsToUpdate = {},\n        _idsToDisable = {};\n\n    PreferencesManager.stateManager.definePreference(FOLDER_AUTOINSTALL, \"object\", undefined);\n    PreferencesManager.definePreference(\"extensions.sort\", \"string\", \"publishedDate\", {\n        description: Strings.SORT_EXTENSION_METHOD\n    });\n\n    /**\n     * @private\n     * Synchronizes the information between the public registry and the installed\n     * extensions. Specifically, this makes the `owner` available in each and sets\n     * an `updateAvailable` flag.\n     *\n     * @param {string} id of the extension to synchronize\n     */\n    function synchronizeEntry(id) {\n        var entry = extensions[id];\n\n        // Do nothing if we only have one set of data\n        if (!entry || !entry.installInfo || !entry.registryInfo) {\n            return;\n        }\n\n        entry.installInfo.owner = entry.registryInfo.owner;\n\n        // Assume false\n        entry.installInfo.updateAvailable   = false;\n        entry.registryInfo.updateAvailable  = false;\n        entry.installInfo.updateCompatible  = false;\n        entry.registryInfo.updateCompatible = false;\n\n        var currentVersion = entry.installInfo.metadata ? entry.installInfo.metadata.version : null;\n        if (currentVersion && semver.lt(currentVersion, entry.registryInfo.metadata.version)) {\n            // Note: available update may still be incompatible; we check for this when rendering the Update button in ExtensionManagerView._renderItem()\n            entry.registryInfo.updateAvailable  = true;\n            entry.installInfo.updateAvailable   = true;\n            // Calculate updateCompatible to check if there's an update for current version of Brackets\n            var lastCompatibleVersionInfo = _.findLast(entry.registryInfo.versions, function (versionInfo) {\n                return !versionInfo.brackets || semver.satisfies(brackets.metadata.apiVersion, versionInfo.brackets);\n            });\n            if (lastCompatibleVersionInfo && lastCompatibleVersionInfo.version && semver.lt(currentVersion, lastCompatibleVersionInfo.version)) {\n                entry.installInfo.updateCompatible        = true;\n                entry.registryInfo.updateCompatible       = true;\n                entry.installInfo.lastCompatibleVersion   = lastCompatibleVersionInfo.version;\n                entry.registryInfo.lastCompatibleVersion  = lastCompatibleVersionInfo.version;\n            }\n        }\n\n        exports.trigger(\"registryUpdate\", id);\n    }\n\n\n    /**\n     * @private\n     * Verifies if an extension is a theme based on the presence of the field \"theme\"\n     * in the package.json.  If it is a theme, then the theme file is just loaded by the\n     * ThemeManager\n     *\n     * @param {string} id of the theme extension to load\n     */\n    function loadTheme(id) {\n        var extension = extensions[id];\n        if (extension.installInfo && extension.installInfo.metadata && extension.installInfo.metadata.theme) {\n            ThemeManager.loadPackage(extension.installInfo);\n        }\n    }\n\n\n    /**\n     * @private\n     * Sets our data. For unit testing only.\n     */\n    function _setExtensions(newExtensions) {\n        exports.extensions = extensions = newExtensions;\n        Object.keys(extensions).forEach(function (id) {\n            synchronizeEntry(id);\n        });\n    }\n\n    /**\n     * @private\n     * Clears out our existing data. For unit testing only.\n     */\n    function _reset() {\n        exports.extensions = extensions = {};\n        _idsToRemove = {};\n        _idsToUpdate = {};\n        _idsToDisable = {};\n    }\n\n    /**\n     * Downloads the registry of Brackets extensions and stores the information in our\n     * extension info.\n     *\n     * @return {$.Promise} a promise that's resolved with the registry JSON data\n     * or rejected if the server can't be reached.\n     */\n    function downloadRegistry() {\n        if (pendingDownloadRegistry) {\n            return pendingDownloadRegistry.promise();\n        }\n\n        pendingDownloadRegistry = new $.Deferred();\n\n        $.ajax({\n            url: brackets.config.extension_registry,\n            dataType: \"json\",\n            cache: false\n        })\n            .done(function (data) {\n                exports.hasDownloadedRegistry = true;\n                Object.keys(data).forEach(function (id) {\n                    if (!extensions[id]) {\n                        extensions[id] = {};\n                    }\n                    extensions[id].registryInfo = data[id];\n                    synchronizeEntry(id);\n                });\n                exports.trigger(\"registryDownload\");\n                pendingDownloadRegistry.resolve();\n            })\n            .fail(function () {\n                pendingDownloadRegistry.reject();\n            })\n            .always(function () {\n                // Make sure to clean up the pending registry so that new requests can be made.\n                pendingDownloadRegistry = null;\n            });\n\n        return pendingDownloadRegistry.promise();\n    }\n\n\n    /**\n     * @private\n     * When an extension is loaded, fetches the package.json and stores the extension in our map.\n     * @param {$.Event} e The event object\n     * @param {string} path The local path of the loaded extension's folder.\n     */\n    function _handleExtensionLoad(e, path) {\n        function setData(metadata) {\n            var locationType,\n                id = metadata.name,\n                userExtensionPath = ExtensionLoader.getUserExtensionPath();\n            if (path.indexOf(userExtensionPath) === 0) {\n                locationType = LOCATION_USER;\n            } else {\n                var segments = path.split(\"/\"), parent;\n                if (segments.length > 2) {\n                    parent = segments[segments.length - 2];\n                }\n                if (parent === \"dev\") {\n                    locationType = LOCATION_DEV;\n                } else if (parent === \"default\") {\n                    locationType = LOCATION_DEFAULT;\n                } else {\n                    locationType = LOCATION_UNKNOWN;\n                }\n            }\n            if (!extensions[id]) {\n                extensions[id] = {};\n            }\n            extensions[id].installInfo = {\n                metadata: metadata,\n                path: path,\n                locationType: locationType,\n                status: (e.type === \"loadFailed\" ? START_FAILED : (e.type === \"disabled\" ? DISABLED : ENABLED))\n            };\n\n            synchronizeEntry(id);\n            loadTheme(id);\n            exports.trigger(\"statusChange\", id);\n        }\n\n        function deduceMetadata() {\n            var match = path.match(/\\/([^\\/]+)$/),\n                name = (match && match[1]) || path,\n                metadata = { name: name, title: name };\n            return metadata;\n        }\n\n        ExtensionUtils.loadMetadata(path)\n            .done(function (metadata) {\n                setData(metadata);\n            })\n            .fail(function (disabled) {\n                // If there's no package.json, this is a legacy extension. It was successfully loaded,\n                // but we don't have an official ID or metadata for it, so we just create an id and\n                // \"title\" for it (which is the last segment of its pathname)\n                // and record that it's enabled.\n                var metadata = deduceMetadata();\n                metadata.disabled = disabled;\n                setData(metadata);\n            });\n    }\n\n    /**\n     * Determines if the given versions[] entry is compatible with the given Brackets API version, and if not\n     * specifies why.\n     * @param {Object} extVersion\n     * @param {string} apiVersion\n     * @return {{isCompatible: boolean, requiresNewer: ?boolean, compatibleVersion: ?string}}\n     */\n    function getCompatibilityInfoForVersion(extVersion, apiVersion) {\n        var requiredVersion = (extVersion.brackets || (extVersion.engines && extVersion.engines.brackets)),\n            result = {};\n        result.isCompatible = !requiredVersion || semver.satisfies(apiVersion, requiredVersion);\n        if (result.isCompatible) {\n            result.compatibleVersion = extVersion.version;\n        } else {\n            // Find out reason for incompatibility\n            if (requiredVersion.charAt(0) === '<') {\n                result.requiresNewer = false;\n            } else if (requiredVersion.charAt(0) === '>') {\n                result.requiresNewer = true;\n            } else if (requiredVersion.charAt(0) === \"~\") {\n                var compareVersion = requiredVersion.slice(1);\n                // Need to add .0s to this style of range in order to compare (since valid version\n                // numbers must have major/minor/patch).\n                if (compareVersion.match(/^[0-9]+$/)) {\n                    compareVersion += \".0.0\";\n                } else if (compareVersion.match(/^[0-9]+\\.[0-9]+$/)) {\n                    compareVersion += \".0\";\n                }\n                result.requiresNewer = semver.lt(apiVersion, compareVersion);\n            }\n        }\n        return result;\n    }\n\n    /**\n     * Finds the newest version of the entry that is compatible with the given Brackets API version, if any.\n     * @param {Object} entry The registry entry to check.\n     * @param {string} apiVersion The Brackets API version to check against.\n     * @return {{isCompatible: boolean, requiresNewer: ?boolean, compatibleVersion: ?string, isLatestVersion: boolean}}\n     *      Result contains an \"isCompatible\" member saying whether it's compatible. If compatible, \"compatibleVersion\"\n     *      specifies the newest version that is compatible and \"isLatestVersion\" indicates if this is the absolute\n     *      latest version of the extension or not. If !isCompatible or !isLatestVersion, \"requiresNewer\" says whether\n     *      the latest version is incompatible due to requiring a newer (vs. older) version of Brackets.\n     */\n    function getCompatibilityInfo(entry, apiVersion) {\n        if (!entry.versions) {\n            var fallback = getCompatibilityInfoForVersion(entry.metadata, apiVersion);\n            if (fallback.isCompatible) {\n                fallback.isLatestVersion = true;\n            }\n            return fallback;\n        }\n\n        var i = entry.versions.length - 1,\n            latestInfo = getCompatibilityInfoForVersion(entry.versions[i], apiVersion);\n\n        if (latestInfo.isCompatible) {\n            latestInfo.isLatestVersion = true;\n            return latestInfo;\n        } else {\n            // Look at earlier versions (skipping very latest version since we already checked it)\n            for (i--; i >= 0; i--) {\n                var compatInfo = getCompatibilityInfoForVersion(entry.versions[i], apiVersion);\n                if (compatInfo.isCompatible) {\n                    compatInfo.isLatestVersion = false;\n                    compatInfo.requiresNewer = latestInfo.requiresNewer;\n                    return compatInfo;\n                }\n            }\n\n            // No version is compatible, so just return info for the latest version\n            return latestInfo;\n        }\n    }\n\n    /**\n     * Given an extension id and version number, returns the URL for downloading that extension from\n     * the repository. Does not guarantee that the extension exists at that URL.\n     * @param {string} id The extension's name from the metadata.\n     * @param {string} version The version to download.\n     * @return {string} The URL to download the extension from.\n     */\n    function getExtensionURL(id, version) {\n        return StringUtils.format(brackets.config.extension_url, id, version);\n    }\n\n    /**\n     * Removes the installed extension with the given id.\n     * @param {string} id The id of the extension to remove.\n     * @return {$.Promise} A promise that's resolved when the extension is removed or\n     *     rejected with an error if there's a problem with the removal.\n     */\n    function remove(id) {\n        var result = new $.Deferred();\n        if (extensions[id] && extensions[id].installInfo) {\n            Package.remove(extensions[id].installInfo.path)\n                .done(function () {\n                    extensions[id].installInfo = null;\n                    result.resolve();\n                    exports.trigger(\"statusChange\", id);\n                })\n                .fail(function (err) {\n                    result.reject(err);\n                });\n        } else {\n            result.reject(StringUtils.format(Strings.EXTENSION_NOT_INSTALLED, id));\n        }\n        return result.promise();\n    }\n\n    /**\n     * @private\n     *\n     * Disables or enables the installed extensions.\n     *\n     * @param {string} id The id of the extension to disable or enable.\n     * @param {boolean} enable A boolean indicating whether to enable or disable.\n     * @return {$.Promise} A promise that's resolved when the extension action is\n     *      completed or rejected with an error that prevents the action from completion.\n     */\n    function _enableOrDisable(id, enable) {\n        var result = new $.Deferred(),\n            extension = extensions[id];\n        if (extension && extension.installInfo) {\n            Package[(enable ? \"enable\" : \"disable\")](extension.installInfo.path)\n                .done(function () {\n                    extension.installInfo.status = enable ? ENABLED : DISABLED;\n                    extension.installInfo.metadata.disabled = !enable;\n                    result.resolve();\n                    exports.trigger(\"statusChange\", id);\n                })\n                .fail(function (err) {\n                    result.reject(err);\n                });\n        } else {\n            result.reject(StringUtils.format(Strings.EXTENSION_NOT_INSTALLED, id));\n        }\n        return result.promise();\n    }\n\n    /**\n     * Disables the installed extension with the given id.\n     *\n     * @param {string} id The id of the extension to disable.\n     * @return {$.Promise} A promise that's resolved when the extenion is disabled or\n     *      rejected with an error that prevented the disabling.\n     */\n    function disable(id) {\n        return _enableOrDisable(id, false);\n    }\n\n    /**\n     * Enables the installed extension with the given id.\n     *\n     * @param {string} id The id of the extension to enable.\n     * @return {$.Promise} A promise that's resolved when the extenion is enabled or\n     *      rejected with an error that prevented the enabling.\n     */\n    function enable(id) {\n        return _enableOrDisable(id, true);\n    }\n\n    /**\n     * Updates an installed extension with the given package file.\n     * @param {string} id of the extension\n     * @param {string} packagePath path to the package file\n     * @param {boolean=} keepFile Flag to keep extension package file, default=false\n     * @return {$.Promise} A promise that's resolved when the extension is updated or\n     *     rejected with an error if there's a problem with the update.\n     */\n    function update(id, packagePath, keepFile) {\n        return Package.installUpdate(packagePath, id).done(function () {\n            if (!keepFile) {\n                FileSystem.getFileForPath(packagePath).unlink();\n            }\n        });\n    }\n\n    /**\n     * Deletes any temporary files left behind by extensions that\n     * were marked for update.\n     */\n    function cleanupUpdates() {\n        Object.keys(_idsToUpdate).forEach(function (id) {\n            var installResult = _idsToUpdate[id],\n                keepFile = installResult.keepFile,\n                filename = installResult.localPath;\n\n            if (filename && !keepFile) {\n                FileSystem.getFileForPath(filename).unlink();\n            }\n        });\n        _idsToUpdate = {};\n    }\n\n    /**\n     * Unmarks all extensions marked for removal.\n     */\n    function unmarkAllForRemoval() {\n        _idsToRemove = {};\n    }\n\n    /**\n     * Marks an extension for later removal, or unmarks an extension previously marked.\n     * @param {string} id The id of the extension to mark for removal.\n     * @param {boolean} mark Whether to mark or unmark it.\n     */\n    function markForRemoval(id, mark) {\n        if (mark) {\n            _idsToRemove[id] = true;\n        } else {\n            delete _idsToRemove[id];\n        }\n        exports.trigger(\"statusChange\", id);\n    }\n\n    /**\n     * Returns true if an extension is marked for removal.\n     * @param {string} id The id of the extension to check.\n     * @return {boolean} true if it's been marked for removal, false otherwise.\n     */\n    function isMarkedForRemoval(id) {\n        return !!(_idsToRemove[id]);\n    }\n\n    /**\n     * Returns true if there are any extensions marked for removal.\n     * @return {boolean} true if there are extensions to remove\n     */\n    function hasExtensionsToRemove() {\n        return Object.keys(_idsToRemove).length > 0;\n    }\n\n    /**\n     * Marks an extension for disabling later, or unmarks an extension previously marked.\n     *\n     * @param {string} id The id of the extension\n     * @param {boolean} mark Whether to mark or unmark the extension.\n     */\n    function markForDisabling(id, mark) {\n        if (mark) {\n            _idsToDisable[id] = true;\n        } else {\n            delete _idsToDisable[id];\n        }\n        exports.trigger(\"statusChange\", id);\n    }\n\n    /**\n     * Returns true if an extension is mark for disabling.\n     *\n     * @param {string} id The id of the extension to check.\n     * @return {boolean} true if it's been mark for disabling, false otherwise.\n     */\n    function isMarkedForDisabling(id) {\n        return !!(_idsToDisable[id]);\n    }\n\n    /**\n     * Returns true if there are any extensions marked for disabling.\n     * @return {boolean} true if there are extensions to disable\n     */\n    function hasExtensionsToDisable() {\n        return Object.keys(_idsToDisable).length > 0;\n    }\n\n    /**\n     * Unmarks all the extensions that have been marked for disabling.\n     */\n    function unmarkAllForDisabling() {\n        _idsToDisable = {};\n    }\n\n    /**\n     * If a downloaded package appears to be an update, mark the extension for update.\n     * If an extension was previously marked for removal, marking for update will\n     * turn off the removal mark.\n     * @param {Object} installationResult info about the install provided by the Package.download function\n     */\n    function updateFromDownload(installationResult) {\n        if (installationResult.keepFile === undefined) {\n            installationResult.keepFile = false;\n        }\n\n        var installationStatus = installationResult.installationStatus;\n        if (installationStatus === Package.InstallationStatuses.ALREADY_INSTALLED ||\n                installationStatus === Package.InstallationStatuses.NEEDS_UPDATE ||\n                installationStatus === Package.InstallationStatuses.SAME_VERSION ||\n                installationStatus === Package.InstallationStatuses.OLDER_VERSION) {\n            var id = installationResult.name;\n            delete _idsToRemove[id];\n            _idsToUpdate[id] = installationResult;\n            exports.trigger(\"statusChange\", id);\n        }\n    }\n\n    /**\n     * Removes the mark for an extension to be updated on restart. Also deletes the\n     * downloaded package file.\n     * @param {string} id The id of the extension for which the update is being removed\n     */\n    function removeUpdate(id) {\n        var installationResult = _idsToUpdate[id];\n        if (!installationResult) {\n            return;\n        }\n        if (installationResult.localPath && !installationResult.keepFile) {\n            FileSystem.getFileForPath(installationResult.localPath).unlink();\n        }\n        delete _idsToUpdate[id];\n        exports.trigger(\"statusChange\", id);\n    }\n\n    /**\n     * Returns true if an extension is marked for update.\n     * @param {string} id The id of the extension to check.\n     * @return {boolean} true if it's been marked for update, false otherwise.\n     */\n    function isMarkedForUpdate(id) {\n        return !!(_idsToUpdate[id]);\n    }\n\n    /**\n     * Returns true if there are any extensions marked for update.\n     * @return {boolean} true if there are extensions to update\n     */\n    function hasExtensionsToUpdate() {\n        return Object.keys(_idsToUpdate).length > 0;\n    }\n\n    /**\n     * Removes extensions previously marked for removal.\n     * @return {$.Promise} A promise that's resolved when all extensions are removed, or rejected\n     *     if one or more extensions can't be removed. When rejected, the argument will be an\n     *     array of error objects, each of which contains an \"item\" property with the id of the\n     *     failed extension and an \"error\" property with the actual error.\n     */\n    function removeMarkedExtensions() {\n        return Async.doInParallel_aggregateErrors(\n            Object.keys(_idsToRemove),\n            function (id) {\n                return remove(id);\n            }\n        );\n    }\n\n    /**\n     * Disables extensions marked for disabling.\n     *\n     * If the return promise is rejected, the argument will contain an array of objects. Each\n     * element is an object identifying the extension failed with \"item\" property set to the\n     * extension id which has failed to be disabled and \"error\" property set to the error.\n     *\n     * @return {$.Promise} A promise that's resolved when all extensions marked for disabling are\n     *      disabled or rejected if one or more extensions can't be disabled.\n     */\n    function disableMarkedExtensions() {\n        return Async.doInParallel_aggregateErrors(\n            Object.keys(_idsToDisable),\n            function (id) {\n                return disable(id);\n            }\n        );\n    }\n\n    /**\n     * Updates extensions previously marked for update.\n     * @return {$.Promise} A promise that's resolved when all extensions are updated, or rejected\n     *     if one or more extensions can't be updated. When rejected, the argument will be an\n     *     array of error objects, each of which contains an \"item\" property with the id of the\n     *     failed extension and an \"error\" property with the actual error.\n     */\n    function updateExtensions() {\n        return Async.doInParallel_aggregateErrors(\n            Object.keys(_idsToUpdate),\n            function (id) {\n                var installationResult = _idsToUpdate[id];\n                return update(installationResult.name, installationResult.localPath, installationResult.keepFile);\n            }\n        );\n    }\n\n    /**\n     * Gets an array of extensions that are currently installed and can be updated to a new version\n     * @return {Array.<{id: string, installVersion: string, registryVersion: string}>}\n     *     where id = extensionId\n     *     installVersion = currently installed version of extension\n     *     registryVersion = latest version compatible with current Brackets\n     */\n    function getAvailableUpdates() {\n        var result = [];\n        Object.keys(extensions).forEach(function (extensionId) {\n            var extensionInfo = extensions[extensionId];\n            // skip extensions that are not installed or are not in the registry\n            if (!extensionInfo.installInfo || !extensionInfo.registryInfo) {\n                return;\n            }\n            if (extensionInfo.registryInfo.updateCompatible) {\n                result.push({\n                    id: extensionId,\n                    installVersion: extensionInfo.installInfo.metadata.version,\n                    registryVersion: extensionInfo.registryInfo.lastCompatibleVersion\n                });\n            }\n        });\n        return result;\n    }\n\n    /**\n     * Takes the array returned from getAvailableUpdates() as an input and removes those entries\n     * that are no longer current - when currently installed version of an extension\n     * is equal or newer than registryVersion returned by getAvailableUpdates().\n     * This function is designed to work without the necessity to download extension registry\n     * @param {Array.<{id: string, installVersion: string, registryVersion: string}>} updates\n     *     previous output of getAvailableUpdates()\n     * @return {Array.<{id: string, installVersion: string, registryVersion: string}>}\n     *     filtered input as function description\n     */\n    function cleanAvailableUpdates(updates) {\n        return updates.reduce(function (arr, updateInfo) {\n            var extDefinition = extensions[updateInfo.id];\n            if (!extDefinition || !extDefinition.installInfo) {\n                // extension has been uninstalled in the meantime\n                return arr;\n            }\n\n            var installedVersion = extDefinition.installInfo.metadata.version;\n            if (semver.lt(installedVersion, updateInfo.registryVersion)) {\n                arr.push(updateInfo);\n            }\n\n            return arr;\n        }, []);\n    }\n\n    /**\n     * @private\n     * Find valid extensions in specified path\n     * @param {string} dirPath Directory with extensions\n     * @param {Object} autoExtensions Object that maps names of previously auto-installed\n     *      extensions {string} to installed version {string}.\n     * @return {$.Promise} Promise that resolves with arrays for extensions to update and install\n     */\n    function _getAutoInstallFiles(dirPath, autoExtensions) {\n        var zipFiles    = [],\n            installZips = [],\n            updateZips  = [],\n            deferred    = new $.Deferred();\n\n        FileSystem.getDirectoryForPath(dirPath).getContents(function (err, contents) {\n            if (!err) {\n                zipFiles = contents.filter(function (dirItem) {\n                    return (dirItem.isFile && FileUtils.getFileExtension(dirItem.fullPath) === \"zip\");\n                });\n            }\n\n            // Parse zip files and separate new installs vs. updates\n            Async.doInParallel_aggregateErrors(zipFiles, function (file) {\n                var zipFilePromise = new $.Deferred();\n\n                // Call validate() so that we open the local zip file and parse the\n                // package.json. We need the name to detect if this zip will be a\n                // new install or an update.\n                Package.validate(file.fullPath, { requirePackageJSON: true }).done(function (info) {\n                    if (info.errors.length) {\n                        zipFilePromise.reject(Package.formatError(info.errors));\n                        return;\n                    }\n\n                    var extensionInfo, installedVersion, zipArray, existingItem,\n                        extensionName   = info.metadata.name,\n                        autoExtVersion  = autoExtensions[extensionName];\n\n                    // Verify extension has not already been auto-installed/updated\n                    if (autoExtVersion && semver.lte(info.metadata.version, autoExtVersion)) {\n                        // Have already auto installed/updated version >= version of this extension\n                        zipFilePromise.reject();\n                        return;\n                    }\n\n                    // Verify extension has not already been installed/updated by some other means\n                    extensionInfo = extensions[extensionName];\n                    installedVersion = extensionInfo && extensionInfo.installInfo && extensionInfo.installInfo.metadata.version;\n                    if (installedVersion && semver.lte(info.metadata.version, installedVersion)) {\n                        // Have already manually installed/updated version >= version of this extension\n                        zipFilePromise.reject();\n                        return;\n                    }\n\n                    // Update appropriate zip array. There could be multiple zip files for an\n                    // extension, so make sure only the latest is stored\n                    zipArray = (installedVersion) ? updateZips : installZips;\n                    zipArray.some(function (zip) {\n                        if (zip.info.metadata.name === extensionName) {\n                            existingItem = zip;\n                            return true;\n                        }\n                        return false;\n                    });\n                    if (existingItem) {\n                        if (semver.lt(existingItem.info.metadata.version, info.metadata.version)) {\n                            existingItem.file = file;\n                            existingItem.info = info;\n                        }\n                    } else {\n                        zipArray.push({ file: file, info: info });\n                    }\n\n                    zipFilePromise.resolve();\n                }).fail(function (err) {\n                    zipFilePromise.reject(Package.formatError(err));\n                });\n\n                return zipFilePromise.promise();\n            }).fail(function (errorArray) {\n                // Async.doInParallel() fails if some are successful, so write errors\n                // to console and always resolve\n                errorArray.forEach(function (errorObj) {\n                    // If we rejected without an error argument, it means it was no problem\n                    // (e.g. same version of extension is already installed)\n                    if (errorObj.error) {\n                        if (errorObj.error.forEach) {\n                            console.error(\"Errors for\", errorObj.item);\n                            errorObj.error.forEach(function (error) {\n                                console.error(Package.formatError(error));\n                            });\n                        } else {\n                            console.error(\"Error for\", errorObj.item, errorObj);\n                        }\n                    }\n                });\n            }).always(function () {\n                deferred.resolve({\n                    installZips: installZips,\n                    updateZips:  updateZips\n                });\n            });\n        });\n\n        return deferred.promise();\n    }\n\n    /**\n     * @private\n     * Auto-install extensions bundled with installer\n     * @return {$.Promise} Promise that resolves when finished\n     */\n    function _autoInstallExtensions() {\n        var dirPath        = FileUtils.getDirectoryPath(FileUtils.getNativeBracketsDirectoryPath()) + FOLDER_AUTOINSTALL + \"/\",\n            autoExtensions = PreferencesManager.getViewState(FOLDER_AUTOINSTALL) || {},\n            deferred       = new $.Deferred();\n\n        _getAutoInstallFiles(dirPath, autoExtensions).done(function (result) {\n            var installPromise = Async.doSequentially(result.installZips, function (zip) {\n                autoExtensions[zip.info.metadata.name] = zip.info.metadata.version;\n                return Package.installFromPath(zip.file.fullPath);\n            });\n\n            var updatePromise = installPromise.always(function () {\n                return Async.doSequentially(result.updateZips, function (zip) {\n                    autoExtensions[zip.info.metadata.name] = zip.info.metadata.version;\n                    return Package.installUpdate(zip.file.fullPath);\n                });\n            });\n\n            // Always resolve the outer promise\n            updatePromise.always(function () {\n                // Keep track of auto-installed extensions so we only install an extension once\n                PreferencesManager.setViewState(FOLDER_AUTOINSTALL, autoExtensions);\n\n                deferred.resolve();\n            });\n        });\n\n        return deferred.promise();\n    }\n\n    AppInit.appReady(function () {\n        Package._getNodeConnectionDeferred().done(function () {\n            _autoInstallExtensions();\n        });\n    });\n\n    // Listen to extension load and loadFailed events\n    ExtensionLoader\n        .on(\"load\", _handleExtensionLoad)\n        .on(\"loadFailed\", _handleExtensionLoad)\n        .on(\"disabled\", _handleExtensionLoad);\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Public exports\n    exports.downloadRegistry        = downloadRegistry;\n    exports.getCompatibilityInfo    = getCompatibilityInfo;\n    exports.getExtensionURL         = getExtensionURL;\n    exports.remove                  = remove;\n    exports.update                  = update;\n    exports.disable                 = disable;\n    exports.enable                  = enable;\n    exports.extensions              = extensions;\n    exports.cleanupUpdates          = cleanupUpdates;\n    exports.markForRemoval          = markForRemoval;\n    exports.isMarkedForRemoval      = isMarkedForRemoval;\n    exports.unmarkAllForRemoval     = unmarkAllForRemoval;\n    exports.hasExtensionsToRemove   = hasExtensionsToRemove;\n    exports.markForDisabling        = markForDisabling;\n    exports.isMarkedForDisabling    = isMarkedForDisabling;\n    exports.unmarkAllForDisabling   = unmarkAllForDisabling;\n    exports.hasExtensionsToDisable  = hasExtensionsToDisable;\n    exports.updateFromDownload      = updateFromDownload;\n    exports.removeUpdate            = removeUpdate;\n    exports.isMarkedForUpdate       = isMarkedForUpdate;\n    exports.hasExtensionsToUpdate   = hasExtensionsToUpdate;\n    exports.removeMarkedExtensions  = removeMarkedExtensions;\n    exports.disableMarkedExtensions = disableMarkedExtensions;\n    exports.updateExtensions        = updateExtensions;\n    exports.getAvailableUpdates     = getAvailableUpdates;\n    exports.cleanAvailableUpdates   = cleanAvailableUpdates;\n\n    exports.hasDownloadedRegistry   = false;\n\n    exports.ENABLED       = ENABLED;\n    exports.DISABLED      = DISABLED;\n    exports.START_FAILED  = START_FAILED;\n\n    exports.LOCATION_DEFAULT  = LOCATION_DEFAULT;\n    exports.LOCATION_DEV      = LOCATION_DEV;\n    exports.LOCATION_USER     = LOCATION_USER;\n    exports.LOCATION_UNKNOWN  = LOCATION_UNKNOWN;\n\n    // For unit testing only\n    exports._getAutoInstallFiles    = _getAutoInstallFiles;\n    exports._reset                  = _reset;\n    exports._setExtensions          = _setExtensions;\n});\n"
  },
  {
    "path": "src/extensibility/ExtensionManagerDialog.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                           = require(\"thirdparty/lodash\"),\n        Mustache                    = require(\"thirdparty/mustache/mustache\"),\n        Dialogs                     = require(\"widgets/Dialogs\"),\n        DefaultDialogs              = require(\"widgets/DefaultDialogs\"),\n        FileSystem                  = require(\"filesystem/FileSystem\"),\n        FileUtils                   = require(\"file/FileUtils\"),\n        Package                     = require(\"extensibility/Package\"),\n        Strings                     = require(\"strings\"),\n        StringUtils                 = require(\"utils/StringUtils\"),\n        Commands                    = require(\"command/Commands\"),\n        CommandManager              = require(\"command/CommandManager\"),\n        InstallExtensionDialog      = require(\"extensibility/InstallExtensionDialog\"),\n        AppInit                     = require(\"utils/AppInit\"),\n        Async                       = require(\"utils/Async\"),\n        KeyEvent                    = require(\"utils/KeyEvent\"),\n        ExtensionManager            = require(\"extensibility/ExtensionManager\"),\n        ExtensionManagerView        = require(\"extensibility/ExtensionManagerView\").ExtensionManagerView,\n        ExtensionManagerViewModel   = require(\"extensibility/ExtensionManagerViewModel\"),\n        PreferencesManager          = require(\"preferences/PreferencesManager\");\n\n    var dialogTemplate    = require(\"text!htmlContent/extension-manager-dialog.html\");\n\n    // bootstrap tabs component\n    require(\"widgets/bootstrap-tab\");\n\n    var _activeTabIndex;\n\n    function _stopEvent(event) {\n        event.stopPropagation();\n        event.preventDefault();\n    }\n\n    /**\n     * @private\n     * Triggers changes requested by the dialog UI.\n     */\n    function _performChanges() {\n        // If an extension was removed or updated, prompt the user to quit Brackets.\n        var hasRemovedExtensions    = ExtensionManager.hasExtensionsToRemove(),\n            hasUpdatedExtensions    = ExtensionManager.hasExtensionsToUpdate(),\n            hasDisabledExtensions   = ExtensionManager.hasExtensionsToDisable();\n        if (!hasRemovedExtensions && !hasUpdatedExtensions && !hasDisabledExtensions) {\n            return;\n        }\n\n        var buttonLabel = Strings.CHANGE_AND_RELOAD;\n        if (hasRemovedExtensions && !hasUpdatedExtensions && !hasDisabledExtensions) {\n            buttonLabel = Strings.REMOVE_AND_RELOAD;\n        } else if (hasUpdatedExtensions && !hasRemovedExtensions && !hasDisabledExtensions) {\n            buttonLabel = Strings.UPDATE_AND_RELOAD;\n        } else if (hasDisabledExtensions && !hasRemovedExtensions && !hasUpdatedExtensions) {\n            buttonLabel = Strings.DISABLE_AND_RELOAD;\n        }\n\n        var dlg = Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_CHANGE_EXTENSIONS,\n            Strings.CHANGE_AND_RELOAD_TITLE,\n            Strings.CHANGE_AND_RELOAD_MESSAGE,\n            [\n                {\n                    className : Dialogs.DIALOG_BTN_CLASS_NORMAL,\n                    id        : Dialogs.DIALOG_BTN_CANCEL,\n                    text      : Strings.CANCEL\n                },\n                {\n                    className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                    id        : Dialogs.DIALOG_BTN_OK,\n                    text      : buttonLabel\n                }\n            ],\n            false\n        ),\n            $dlg = dlg.getElement();\n\n        $dlg.one(\"buttonClick\", function (e, buttonId) {\n            if (buttonId === Dialogs.DIALOG_BTN_OK) {\n                // Disable the dialog buttons so the user can't dismiss it,\n                // and show a message indicating that we're doing the updates,\n                // in case it takes a long time.\n                $dlg.find(\".dialog-button\").prop(\"disabled\", true);\n                $dlg.find(\".close\").hide();\n                $dlg.find(\".dialog-message\")\n                    .text(Strings.PROCESSING_EXTENSIONS)\n                    .append(\"<span class='spinner inline spin'/>\");\n\n                var removeExtensionsPromise,\n                    updateExtensionsPromise,\n                    disableExtensionsPromise,\n                    removeErrors,\n                    updateErrors,\n                    disableErrors;\n\n                removeExtensionsPromise = ExtensionManager.removeMarkedExtensions()\n                    .fail(function (errorArray) {\n                        removeErrors = errorArray;\n                    });\n                updateExtensionsPromise = ExtensionManager.updateExtensions()\n                    .fail(function (errorArray) {\n                        updateErrors = errorArray;\n                    });\n                disableExtensionsPromise = ExtensionManager.disableMarkedExtensions()\n                    .fail(function (errorArray) {\n                        disableErrors = errorArray;\n                    });\n\n                Async.waitForAll([removeExtensionsPromise, updateExtensionsPromise, disableExtensionsPromise], true)\n                    .always(function () {\n                        dlg.close();\n                    })\n                    .done(function () {\n                        CommandManager.execute(Commands.APP_RELOAD);\n                    })\n                    .fail(function () {\n                        var ids = [],\n                            dialogs = [];\n\n                        function nextDialog() {\n                            var dialog = dialogs.shift();\n                            if (dialog) {\n                                Dialogs.showModalDialog(dialog.dialog, dialog.title, dialog.message)\n                                    .done(nextDialog);\n                            } else {\n                                // Even in case of error condition, we still have to reload\n                                CommandManager.execute(Commands.APP_RELOAD);\n                            }\n                        }\n\n                        if (removeErrors) {\n                            removeErrors.forEach(function (errorObj) {\n                                ids.push(errorObj.item);\n                            });\n                            dialogs.push({\n                                dialog: DefaultDialogs.DIALOG_ID_ERROR,\n                                title: Strings.EXTENSION_MANAGER_REMOVE,\n                                message: StringUtils.format(Strings.EXTENSION_MANAGER_REMOVE_ERROR, ids.join(\", \"))\n                            });\n                        }\n\n                        if (updateErrors) {\n                            // This error case should be very uncommon.\n                            // Just let the user know that we couldn't update\n                            // this extension and log the errors to the console.\n                            ids.length = 0;\n                            updateErrors.forEach(function (errorObj) {\n                                ids.push(errorObj.item);\n                                if (errorObj.error && errorObj.error.forEach) {\n                                    console.error(\"Errors for\", errorObj.item);\n                                    errorObj.error.forEach(function (error) {\n                                        console.error(Package.formatError(error));\n                                    });\n                                } else {\n                                    console.error(\"Error for\", errorObj.item, errorObj);\n                                }\n                            });\n                            dialogs.push({\n                                dialog: DefaultDialogs.DIALOG_ID_ERROR,\n                                title: Strings.EXTENSION_MANAGER_UPDATE,\n                                message: StringUtils.format(Strings.EXTENSION_MANAGER_UPDATE_ERROR, ids.join(\", \"))\n                            });\n                        }\n\n                        if (disableErrors) {\n                            ids.length = 0;\n                            disableErrors.forEach(function (errorObj) {\n                                ids.push(errorObj.item);\n                            });\n                            dialogs.push({\n                                dialog: DefaultDialogs.DIALOG_ID_ERROR,\n                                title: Strings.EXTENSION_MANAGER_DISABLE,\n                                message: StringUtils.format(Strings.EXTENSION_MANAGER_DISABLE_ERROR, ids.join(\", \"))\n                            });\n                        }\n\n                        nextDialog();\n                    });\n            } else {\n                dlg.close();\n                ExtensionManager.cleanupUpdates();\n                ExtensionManager.unmarkAllForRemoval();\n                ExtensionManager.unmarkAllForDisabling();\n            }\n        });\n    }\n\n\n    /**\n     * @private\n     * Install extensions from the local file system using the install dialog.\n     * @return {$.Promise}\n     */\n    function _installUsingDragAndDrop() {\n        var installZips = [],\n            updateZips = [],\n            deferred = new $.Deferred(),\n            validatePromise;\n\n        brackets.app.getDroppedFiles(function (err, paths) {\n            if (err) {\n                // Only possible error is invalid params, silently ignore\n                console.error(err);\n                deferred.resolve();\n                return;\n            }\n\n            // Parse zip files and separate new installs vs. updates\n            validatePromise = Async.doInParallel_aggregateErrors(paths, function (path) {\n                var result = new $.Deferred();\n\n                FileSystem.resolve(path, function (err, file) {\n                    var extension = FileUtils.getFileExtension(path),\n                        isZip = file.isFile && (extension === \"zip\"),\n                        errStr;\n\n                    if (err) {\n                        errStr = FileUtils.getFileErrorString(err);\n                    } else if (!isZip) {\n                        errStr = Strings.INVALID_ZIP_FILE;\n                    }\n\n                    if (errStr) {\n                        result.reject(errStr);\n                        return;\n                    }\n\n                    // Call validate() so that we open the local zip file and parse the\n                    // package.json. We need the name to detect if this zip will be a\n                    // new install or an update.\n                    Package.validate(path, { requirePackageJSON: true }).done(function (info) {\n                        if (info.errors.length) {\n                            result.reject(info.errors.map(Package.formatError).join(\" \"));\n                            return;\n                        }\n\n                        var extensionName = info.metadata.name,\n                            extensionInfo = ExtensionManager.extensions[extensionName],\n                            isUpdate = extensionInfo && !!extensionInfo.installInfo;\n\n                        if (isUpdate) {\n                            updateZips.push(file);\n                        } else {\n                            installZips.push(file);\n                        }\n\n                        result.resolve();\n                    }).fail(function (err) {\n                        result.reject(Package.formatError(err));\n                    });\n                });\n\n                return result.promise();\n            });\n\n            validatePromise.done(function () {\n                var installPromise = Async.doSequentially(installZips, function (file) {\n                    return InstallExtensionDialog.installUsingDialog(file);\n                });\n\n                var updatePromise = installPromise.then(function () {\n                    return Async.doSequentially(updateZips, function (file) {\n                        return InstallExtensionDialog.updateUsingDialog(file).done(function (result) {\n                            ExtensionManager.updateFromDownload(result);\n                        });\n                    });\n                });\n\n                // InstallExtensionDialog displays it's own errors, always\n                // resolve the outer promise\n                updatePromise.always(deferred.resolve);\n            }).fail(function (errorArray) {\n                deferred.reject(errorArray);\n            });\n        });\n\n        return deferred.promise();\n    }\n\n    /**\n     * @private\n     * Show a dialog that allows the user to browse and manage extensions.\n     */\n    function _showDialog() {\n        var dialog,\n            $dlg,\n            views   = [],\n            $search,\n            $searchClear,\n            $modalDlg,\n            context = { Strings: Strings, showRegistry: !!brackets.config.extension_registry },\n            models  = [];\n\n        // Load registry only if the registry URL exists\n        if (context.showRegistry) {\n            models.push(new ExtensionManagerViewModel.RegistryViewModel());\n            models.push(new ExtensionManagerViewModel.ThemesViewModel());\n        }\n\n        models.push(new ExtensionManagerViewModel.InstalledViewModel());\n        models.push(new ExtensionManagerViewModel.DefaultViewModel());\n\n        function updateSearchDisabled() {\n            var model           = models[_activeTabIndex],\n                searchDisabled  = ($search.val() === \"\") &&\n                                  (!model.filterSet || model.filterSet.length === 0);\n\n            $search.prop(\"disabled\", searchDisabled);\n            $searchClear.prop(\"disabled\", searchDisabled);\n\n            return searchDisabled;\n        }\n\n        function clearSearch() {\n            $search.val(\"\");\n            views.forEach(function (view, index) {\n                view.filter(\"\");\n                $modalDlg.scrollTop(0);\n            });\n\n            if (!updateSearchDisabled()) {\n                $search.focus();\n            }\n        }\n\n        // Open the dialog\n        dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(dialogTemplate, context));\n\n        // On dialog close: clean up listeners & models, and commit changes\n        dialog.done(function () {\n            $(window.document).off(\".extensionManager\");\n\n            models.forEach(function (model) {\n                model.dispose();\n            });\n\n            _performChanges();\n        });\n\n        // Create the view.\n        $dlg = dialog.getElement();\n        $search = $(\".search\", $dlg);\n        $searchClear = $(\".search-clear\", $dlg);\n        $modalDlg = $(\".modal-body\", $dlg);\n\n        function setActiveTab($tab) {\n            if (models[_activeTabIndex]) {\n                models[_activeTabIndex].scrollPos = $modalDlg.scrollTop();\n            }\n            $tab.tab(\"show\");\n            if (models[_activeTabIndex]) {\n                $modalDlg.scrollTop(models[_activeTabIndex].scrollPos || 0);\n                clearSearch();\n                if (_activeTabIndex === 2) {\n                    $(\".ext-sort-group\").hide();\n                } else {\n                    $(\".ext-sort-group\").show();\n                }\n            }\n        }\n\n        // Dialog tabs\n        $dlg.find(\".nav-tabs a\")\n            .on(\"click\", function (event) {\n                setActiveTab($(this));\n            });\n\n        // Navigate through tabs via Ctrl-(Shift)-Tab\n        // (focus may be on document.body if text in extension listing clicked - see #9511)\n        $(window.document).on(\"keyup.extensionManager\", function (event) {\n            if (event.keyCode === KeyEvent.DOM_VK_TAB && event.ctrlKey) {\n                var $tabs = $(\".nav-tabs a\", $dlg),\n                    tabIndex = _activeTabIndex;\n\n                if (event.shiftKey) {\n                    tabIndex--;\n                } else {\n                    tabIndex++;\n                }\n                tabIndex %= $tabs.length;\n                setActiveTab($tabs.eq(tabIndex));\n            }\n        });\n\n        // Update & hide/show the notification overlay on a tab's icon, based on its model's notifyCount\n        function updateNotificationIcon(index) {\n            var model = models[index],\n                $notificationIcon = $dlg.find(\".nav-tabs li\").eq(index).find(\".notification\");\n            if (model.notifyCount) {\n                $notificationIcon.text(model.notifyCount);\n                $notificationIcon.show();\n            } else {\n                $notificationIcon.hide();\n            }\n        }\n\n        // Initialize models and create a view for each model\n        var modelInitPromise = Async.doInParallel(models, function (model, index) {\n            var view    = new ExtensionManagerView(),\n                promise = view.initialize(model),\n                lastNotifyCount;\n\n            promise.always(function () {\n                views[index] = view;\n\n                lastNotifyCount = model.notifyCount;\n                updateNotificationIcon(index);\n            });\n\n            model.on(\"change\", function () {\n                if (lastNotifyCount !== model.notifyCount) {\n                    lastNotifyCount = model.notifyCount;\n                    updateNotificationIcon(index);\n                }\n            });\n\n            return promise;\n        }, true);\n\n        modelInitPromise.always(function () {\n            $(\".spinner\", $dlg).remove();\n\n            views.forEach(function (view) {\n                view.$el.appendTo($modalDlg);\n            });\n\n            // Update search UI before new tab is shown\n            $(\"a[data-toggle='tab']\", $dlg).each(function (index, tabElement) {\n                $(tabElement).on(\"show\", function (event) {\n                    _activeTabIndex = index;\n\n                    // Focus the search input\n                    if (!updateSearchDisabled()) {\n                        $dlg.find(\".search\").focus();\n                    }\n                });\n            });\n\n            // Filter the views when the user types in the search field.\n            var searchTimeoutID;\n            $dlg.on(\"input\", \".search\", function (e) {\n                clearTimeout(searchTimeoutID);\n                var query = $(this).val();\n                searchTimeoutID = setTimeout(function () {\n                    views[_activeTabIndex].filter(query);\n                    $modalDlg.scrollTop(0);\n                }, 200);\n            }).on(\"click\", \".search-clear\", clearSearch);\n            \n            // Sort the extension list based on the current selected sorting criteria\n            $dlg.on(\"change\", \".sort-extensions\", function (e) {\n                var sortBy = $(this).val();\n                PreferencesManager.set(\"extensions.sort\", sortBy);\n                models.forEach(function (model, index) {\n                    if (index <= 1) {\n                        model._setSortedExtensionList(ExtensionManager.extensions, index === 1);\n                        views[index].filter($(\".search\").val());\n                    }\n                });\n            });\n\n            // Disable the search field when there are no items in the model\n            models.forEach(function (model, index) {\n                model.on(\"change\", function () {\n                    if (_activeTabIndex === index) {\n                        updateSearchDisabled();\n                    }\n                });\n            });\n\n            var $activeTab = $dlg.find(\".nav-tabs li.active a\");\n            if ($activeTab.length) { // If there's already a tab selected, show it\n                $activeTab.parent().removeClass(\"active\"); // workaround for bootstrap-tab\n                $activeTab.tab(\"show\");\n            } else if ($(\"#toolbar-extension-manager\").hasClass('updatesAvailable')) {\n                // Open dialog to Installed tab if extension updates are available\n                $dlg.find(\".nav-tabs a.installed\").tab(\"show\");\n            } else { // Otherwise show the first tab\n                $dlg.find(\".nav-tabs a:first\").tab(\"show\");\n            }\n            // If activeTab was explicitly selected by user,\n            // then check for the selection\n            // Or if there was an update available since activeTab.length would be 0,\n            // then check for updatesAvailable class in toolbar-extension-manager\n            if (($activeTab.length && $activeTab.hasClass(\"installed\")) || (!$activeTab.length && $(\"#toolbar-extension-manager\").hasClass('updatesAvailable'))) {\n                $(\".ext-sort-group\").hide();\n            } else {\n                $(\".ext-sort-group\").show();\n            }\n        });\n\n        // Handle the 'Install from URL' button.\n        $(\".extension-manager-dialog .install-from-url\")\n            .click(function () {\n                InstallExtensionDialog.showDialog().done(ExtensionManager.updateFromDownload);\n            });\n\n        // Handle the drag/drop zone\n        var $dropzone = $(\"#install-drop-zone\"),\n            $dropmask = $(\"#install-drop-zone-mask\");\n\n        $dropzone\n            .on(\"dragover\", function (event) {\n                _stopEvent(event);\n\n                if (!event.originalEvent.dataTransfer.files) {\n                    return;\n                }\n\n                var items = event.originalEvent.dataTransfer.items,\n                    isValidDrop = false;\n\n                isValidDrop = _.every(items, function (item) {\n                    if (item.kind === \"file\") {\n                        var entry = item.webkitGetAsEntry(),\n                            extension = FileUtils.getFileExtension(entry.fullPath);\n\n                        return entry.isFile && extension === \"zip\";\n                    }\n\n                    return false;\n                });\n\n                if (isValidDrop) {\n                    // Set an absolute width to stabilize the button size\n                    $dropzone.width($dropzone.width());\n\n                    // Show drop styling and message\n                    $dropzone.removeClass(\"drag\");\n                    $dropzone.addClass(\"drop\");\n                } else {\n                    event.originalEvent.dataTransfer.dropEffect = \"none\";\n                }\n            })\n            .on(\"drop\", _stopEvent);\n\n        $dropmask\n            .on(\"dragover\", function (event) {\n                _stopEvent(event);\n                event.originalEvent.dataTransfer.dropEffect = \"copy\";\n            })\n            .on(\"dragleave\", function () {\n                $dropzone.removeClass(\"drop\");\n                $dropzone.addClass(\"drag\");\n            })\n            .on(\"drop\", function (event) {\n                _stopEvent(event);\n\n                if (event.originalEvent.dataTransfer.files) {\n                    // Attempt install\n                    _installUsingDragAndDrop().fail(function (errorArray) {\n                        var message = Strings.INSTALL_EXTENSION_DROP_ERROR;\n\n                        message += \"<ul class='dialog-list'>\";\n                        errorArray.forEach(function (info) {\n                            message += \"<li><span class='dialog-filename'>\";\n                            message += StringUtils.breakableUrl(info.item);\n                            message += \"</span>: \" + info.error + \"</li>\";\n                        });\n                        message += \"</ul>\";\n\n                        Dialogs.showModalDialog(\n                            DefaultDialogs.DIALOG_ID_ERROR,\n                            Strings.EXTENSION_MANAGER_TITLE,\n                            message\n                        );\n                    }).always(function () {\n                        $dropzone.removeClass(\"validating\");\n                        $dropzone.addClass(\"drag\");\n                    });\n\n                    // While installing, show validating message\n                    $dropzone.removeClass(\"drop\");\n                    $dropzone.addClass(\"validating\");\n                }\n            });\n\n        return new $.Deferred().resolve(dialog).promise();\n    }\n\n    CommandManager.register(Strings.CMD_EXTENSION_MANAGER, Commands.FILE_EXTENSION_MANAGER, _showDialog);\n\n    AppInit.appReady(function () {\n        $(\"#toolbar-extension-manager\").click(_showDialog);\n    });\n\n    // Unit tests\n    exports._performChanges = _performChanges;\n});\n"
  },
  {
    "path": "src/extensibility/ExtensionManagerView.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: ExtensionManager*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Strings                   = require(\"strings\"),\n        EventDispatcher           = require(\"utils/EventDispatcher\"),\n        StringUtils               = require(\"utils/StringUtils\"),\n        ExtensionManager          = require(\"extensibility/ExtensionManager\"),\n        registry_utils            = require(\"extensibility/registry_utils\"),\n        InstallExtensionDialog    = require(\"extensibility/InstallExtensionDialog\"),\n        LocalizationUtils         = require(\"utils/LocalizationUtils\"),\n        LanguageManager           = require(\"language/LanguageManager\"),\n        Mustache                  = require(\"thirdparty/mustache/mustache\"),\n        PathUtils                 = require(\"thirdparty/path-utils/path-utils\"),\n        itemTemplate              = require(\"text!htmlContent/extension-manager-view-item.html\"),\n        PreferencesManager        = require(\"preferences/PreferencesManager\");\n        \n\n    /**\n     * Create a detached link element, so that we can use it later to extract url details like 'protocol'\n     */\n    var _tmpLink = window.document.createElement('a');\n\n    /**\n     * Creates a view enabling the user to install and manage extensions. Must be initialized\n     * with initialize(). When the view is closed, dispose() must be called.\n     * @constructor\n     */\n    function ExtensionManagerView() {\n    }\n    EventDispatcher.makeEventDispatcher(ExtensionManagerView.prototype);\n\n    /**\n     * Initializes the view to show a set of extensions.\n     * @param {ExtensionManagerViewModel} model Model object containing extension data to view\n     * @return {$.Promise} a promise that's resolved once the view has been initialized. Never\n     *     rejected.\n     */\n    ExtensionManagerView.prototype.initialize = function (model) {\n        var self = this,\n            result = new $.Deferred();\n        this.model = model;\n        this._itemTemplate = Mustache.compile(itemTemplate);\n        this._itemViews = {};\n        this.$el = $(\"<div class='extension-list tab-pane' id='\" + this.model.source + \"'/>\");\n        this._$emptyMessage = $(\"<div class='empty-message'/>\")\n            .appendTo(this.$el);\n        this._$infoMessage = $(\"<div class='info-message'/>\")\n            .appendTo(this.$el).html(this.model.infoMessage);\n        this._$table = $(\"<table class='table'/>\").appendTo(this.$el);\n        $(\".sort-extensions\").val(PreferencesManager.get(\"extensions.sort\"));\n\n        this.model.initialize().done(function () {\n            self._setupEventHandlers();\n        }).always(function () {\n            self._render();\n            result.resolve();\n        });\n\n        return result.promise();\n    };\n\n    /**\n     * @type {jQueryObject}\n     * The root of the view's DOM tree.\n     */\n    ExtensionManagerView.prototype.$el = null;\n\n    /**\n     * @type {Model}\n     * The view's model. Handles sorting and filtering of items in the view.\n     */\n    ExtensionManagerView.prototype.model = null;\n\n    /**\n     * @type {jQueryObject}\n     * Element showing a message when there are no extensions.\n     */\n    ExtensionManagerView.prototype._$emptyMessage = null;\n\n    /**\n     * @private\n     * @type {jQueryObject}\n     * The root of the table inside the view.\n     */\n    ExtensionManagerView.prototype._$table = null;\n\n    /**\n     * @private\n     * @type {function} The compiled template we use for rendering items in the extension list.\n     */\n    ExtensionManagerView.prototype._itemTemplate = null;\n\n    /**\n     * @private\n     * @type {Object.<string, jQueryObject>}\n     * The individual views for each item, keyed by the extension ID.\n     */\n    ExtensionManagerView.prototype._itemViews = null;\n\n    /**\n     * Toggles between truncated and full length extension descriptions\n     * @param {string} id The id of the extension clicked\n     * @param {JQueryElement} $element The DOM element of the extension clicked\n     * @param {boolean} showFull true if full length description should be shown, false for shortened version.\n     */\n    ExtensionManagerView.prototype._toggleDescription = function (id, $element, showFull) {\n        var description, linkTitle,\n            info = this.model._getEntry(id);\n\n        // Toggle between appropriate descriptions and link title,\n        // depending on if extension is installed or not\n        if (showFull) {\n            description = info.metadata.description;\n            linkTitle = Strings.VIEW_TRUNCATED_DESCRIPTION;\n        } else {\n            description = info.metadata.shortdescription;\n            linkTitle = Strings.VIEW_COMPLETE_DESCRIPTION;\n        }\n\n        $element.data(\"toggle-desc\", showFull ? \"trunc-desc\" : \"expand-desc\")\n                .attr(\"title\", linkTitle)\n                .prev(\".ext-full-description\").text(description);\n    };\n\n    /**\n     * @private\n     * Attaches our event handlers. We wait to do this until we've fully fetched the extension list.\n     */\n    ExtensionManagerView.prototype._setupEventHandlers = function () {\n        var self = this;\n\n        // Listen for model data and filter changes.\n        this.model\n            .on(\"filter\", function () {\n                self._render();\n            })\n            .on(\"change\", function (e, id) {\n                var extensions = self.model.extensions,\n                    $oldItem = self._itemViews[id];\n                self._updateMessage();\n                if (self.model.filterSet.indexOf(id) === -1) {\n                    // This extension is not in the filter set. Remove it from the view if we\n                    // were rendering it previously.\n                    if ($oldItem) {\n                        $oldItem.remove();\n                        delete self._itemViews[id];\n                    }\n                } else {\n                    // Render the item, replacing the old item if we had previously rendered it.\n                    var $newItem = self._renderItem(extensions[id], self.model._getEntry(id));\n                    if ($oldItem) {\n                        $oldItem.replaceWith($newItem);\n                        self._itemViews[id] = $newItem;\n                    }\n                }\n            });\n\n        // UI event handlers\n        this.$el\n            .on(\"click\", \"a\", function (e) {\n                var $target = $(e.target);\n                if ($target.hasClass(\"undo-remove\")) {\n                    ExtensionManager.markForRemoval($target.attr(\"data-extension-id\"), false);\n                } else if ($target.hasClass(\"remove\")) {\n                    ExtensionManager.markForRemoval($target.attr(\"data-extension-id\"), true);\n                } else if ($target.hasClass(\"undo-update\")) {\n                    ExtensionManager.removeUpdate($target.attr(\"data-extension-id\"));\n                } else if ($target.hasClass(\"undo-disable\")) {\n                    ExtensionManager.markForDisabling($target.attr(\"data-extension-id\"), false);\n                } else if ($target.data(\"toggle-desc\") === \"expand-desc\") {\n                    this._toggleDescription($target.attr(\"data-extension-id\"), $target, true);\n                } else if ($target.data(\"toggle-desc\") === \"trunc-desc\") {\n                    this._toggleDescription($target.attr(\"data-extension-id\"), $target, false);\n                }\n            }.bind(this))\n            .on(\"click\", \"button.install\", function (e) {\n                self._installUsingDialog($(e.target).attr(\"data-extension-id\"));\n            })\n            .on(\"click\", \"button.update\", function (e) {\n                self._installUsingDialog($(e.target).attr(\"data-extension-id\"), true);\n            })\n            .on(\"click\", \"button.remove\", function (e) {\n                ExtensionManager.markForRemoval($(e.target).attr(\"data-extension-id\"), true);\n            })\n            .on(\"click\", \"button.disable\", function (e) {\n                ExtensionManager.markForDisabling($(e.target).attr(\"data-extension-id\"), true);\n            })\n            .on(\"click\", \"button.enable\", function (e) {\n                ExtensionManager.enable($(e.target).attr(\"data-extension-id\"));\n            });\n    };\n\n    /**\n     * @private\n     * Renders the view for a single extension entry.\n     * @param {Object} entry The extension entry to render.\n     * @param {Object} info The extension's metadata.\n     * @return {jQueryObject} The rendered node as a jQuery object.\n     */\n    ExtensionManagerView.prototype._renderItem = function (entry, info) {\n        // Create a Mustache context object containing the entry data and our helper functions.\n\n        // Start with the basic info from the given entry, either the installation info or the\n        // registry info depending on what we're listing.\n        var context = $.extend({}, info);\n\n        // Normally we would merge the strings into the context we're passing into the template,\n        // but since we're instantiating the template for every item, it seems wrong to take the hit\n        // of copying all the strings into the context, so we just make it a subfield.\n        context.Strings = Strings;\n\n        // Calculate various bools, since Mustache doesn't let you use expressions and interprets\n        // arrays as iteration contexts.\n        context.isInstalled = !!entry.installInfo;\n        context.failedToStart = (entry.installInfo && entry.installInfo.status === ExtensionManager.START_FAILED);\n        context.disabled = (entry.installInfo && entry.installInfo.status === ExtensionManager.DISABLED);\n        context.hasVersionInfo = !!info.versions;\n\n        if (entry.registryInfo) {\n            var latestVerCompatInfo = ExtensionManager.getCompatibilityInfo(entry.registryInfo, brackets.metadata.apiVersion);\n            context.isCompatible = latestVerCompatInfo.isCompatible;\n            context.requiresNewer = latestVerCompatInfo.requiresNewer;\n            context.isCompatibleLatest = latestVerCompatInfo.isLatestVersion;\n            if (!context.isCompatibleLatest) {\n                var installWarningBase = context.requiresNewer ? Strings.EXTENSION_LATEST_INCOMPATIBLE_NEWER : Strings.EXTENSION_LATEST_INCOMPATIBLE_OLDER;\n                context.installWarning = StringUtils.format(installWarningBase, entry.registryInfo.versions[entry.registryInfo.versions.length - 1].version, latestVerCompatInfo.compatibleVersion);\n            }\n            context.downloadCount = entry.registryInfo.totalDownloads;\n        } else {\n            // We should only get here when viewing the Installed tab and some extensions don't exist in the registry\n            // (or registry is offline). These flags *should* always be ignored in that scenario, but just in case...\n            context.isCompatible = context.isCompatibleLatest = true;\n        }\n\n        // Check if extension metadata contains localized content.\n        var lang            = brackets.getLocale(),\n            shortLang       = lang.split(\"-\")[0];\n        if (info.metadata[\"package-i18n\"]) {\n            [shortLang, lang].forEach(function (locale) {\n                if (info.metadata[\"package-i18n\"].hasOwnProperty(locale)) {\n                    // only overlay specific properties with the localized values\n                    [\"title\", \"description\", \"homepage\", \"keywords\"].forEach(function (prop) {\n                        if (info.metadata[\"package-i18n\"][locale].hasOwnProperty(prop)) {\n                            info.metadata[prop] = info.metadata[\"package-i18n\"][locale][prop];\n                        }\n                    });\n                }\n            });\n        }\n\n        if (info.metadata.description !== undefined) {\n            info.metadata.shortdescription = StringUtils.truncate(info.metadata.description, 200);\n        }\n\n        context.isMarkedForRemoval = ExtensionManager.isMarkedForRemoval(info.metadata.name);\n        context.isMarkedForDisabling = ExtensionManager.isMarkedForDisabling(info.metadata.name);\n        context.isMarkedForUpdate = ExtensionManager.isMarkedForUpdate(info.metadata.name);\n        var hasPendingAction = context.isMarkedForDisabling || context.isMarkedForRemoval || context.isMarkedForUpdate;\n\n        context.showInstallButton = (this.model.source === this.model.SOURCE_REGISTRY || this.model.source === this.model.SOURCE_THEMES) && !context.updateAvailable;\n        context.showUpdateButton = context.updateAvailable && !context.isMarkedForUpdate && !context.isMarkedForRemoval;\n\n        context.allowInstall = context.isCompatible && !context.isInstalled;\n\n        if (Array.isArray(info.metadata.i18n) && info.metadata.i18n.length > 0) {\n            context.translated = true;\n            context.translatedLangs =\n                info.metadata.i18n.map(function (value) {\n                    if (value === \"root\") {\n                        value = \"en\";\n                    }\n                    return { name: LocalizationUtils.getLocalizedLabel(value), locale: value };\n                })\n                .sort(function (lang1, lang2) {\n                    // List users language first\n                    var locales         = [lang1.locale, lang2.locale],\n                        userLangIndex   = locales.indexOf(lang);\n                    if (userLangIndex > -1) {\n                        return userLangIndex;\n                    }\n                    userLangIndex = locales.indexOf(shortLang);\n                    if (userLangIndex > -1) {\n                        return userLangIndex;\n                    }\n\n                    return lang1.name.localeCompare(lang2.name);\n                })\n                .map(function (value) {\n                    return value.name;\n                })\n                .join(\", \");\n            context.translatedLangs = StringUtils.format(Strings.EXTENSION_TRANSLATED_LANGS, context.translatedLangs);\n\n            // If the selected language is System Default, match both the short (2-char) language code\n            // and the long one\n            var translatedIntoUserLang =\n                (brackets.isLocaleDefault() && info.metadata.i18n.indexOf(shortLang) > -1) ||\n                info.metadata.i18n.indexOf(lang) > -1;\n            context.extensionTranslated = StringUtils.format(\n                translatedIntoUserLang ? Strings.EXTENSION_TRANSLATED_USER_LANG : Strings.EXTENSION_TRANSLATED_GENERAL,\n                info.metadata.i18n.length\n            );\n        }\n\n        var isInstalledInUserFolder = (entry.installInfo && entry.installInfo.locationType === ExtensionManager.LOCATION_USER);\n        context.allowRemove = isInstalledInUserFolder;\n        context.allowUpdate = context.showUpdateButton && context.isCompatible && context.updateCompatible && isInstalledInUserFolder;\n        if (!context.allowUpdate) {\n            context.updateNotAllowedReason = isInstalledInUserFolder ? Strings.CANT_UPDATE : Strings.CANT_UPDATE_DEV;\n        }\n\n        context.removalAllowed = this.model.source === \"installed\" &&\n            !context.failedToStart && !hasPendingAction;\n        var isDefaultOrInstalled = this.model.source === \"default\" || this.model.source === \"installed\";\n        var isDefaultAndTheme = this.model.source === \"default\" && context.metadata.theme;\n        context.disablingAllowed = isDefaultOrInstalled && !isDefaultAndTheme && !context.disabled && !hasPendingAction;\n        context.enablingAllowed = isDefaultOrInstalled && !isDefaultAndTheme && context.disabled && !hasPendingAction;\n\n        // Copy over helper functions that we share with the registry app.\n        [\"lastVersionDate\", \"authorInfo\"].forEach(function (helper) {\n            context[helper] = registry_utils[helper];\n        });\n\n        // Do some extra validation on homepage url to make sure we don't end up executing local binary\n        if (context.metadata.homepage) {\n            var parsed = PathUtils.parseUrl(context.metadata.homepage);\n\n            // We can't rely on path-utils because of known problems with protocol identification\n            // Falling back to Browsers protocol identification mechanism\n            _tmpLink.href = context.metadata.homepage;\n\n            // Check if the homepage refers to a local resource\n            if (_tmpLink.protocol === \"file:\") {\n                var language = LanguageManager.getLanguageForExtension(parsed.filenameExtension.replace(/^\\./, ''));\n                // If identified language for the local resource is binary, don't list it\n                if (language && language.isBinary()) {\n                    delete context.metadata.homepage;\n                }\n            }\n        }\n\n        return $(this._itemTemplate(context));\n    };\n\n    /**\n     * @private\n     * Display an optional message (hiding the extension list if displayed)\n     * @return {boolean} Returns true if a message is displayed\n     */\n    ExtensionManagerView.prototype._updateMessage = function () {\n        if (this.model.message) {\n            this._$emptyMessage.css(\"display\", \"block\");\n            this._$emptyMessage.html(this.model.message);\n            this._$infoMessage.css(\"display\", \"none\");\n            this._$table.css(\"display\", \"none\");\n\n            return true;\n        } else {\n            this._$emptyMessage.css(\"display\", \"none\");\n            this._$infoMessage.css(\"display\", this.model.infoMessage ? \"block\" : \"none\");\n            this._$table.css(\"display\", \"\");\n\n            return false;\n        }\n    };\n\n    /**\n     * @private\n     * Renders the extension entry table based on the model's current filter set. Will create\n     * new items for entries that haven't yet been rendered, but will not re-render existing items.\n     */\n    ExtensionManagerView.prototype._render = function () {\n        var self = this;\n\n        this._$table.empty();\n        this._updateMessage();\n\n        this.model.filterSet.forEach(function (id) {\n            var $item = self._itemViews[id];\n            if (!$item) {\n                $item = self._renderItem(self.model.extensions[id], self.model._getEntry(id));\n                self._itemViews[id] = $item;\n            }\n            $item.appendTo(self._$table);\n        });\n\n        this.trigger(\"render\");\n    };\n\n    /**\n     * @private\n     * Install the extension with the given ID using the install dialog.\n     * @param {string} id ID of the extension to install.\n     */\n    ExtensionManagerView.prototype._installUsingDialog = function (id, _isUpdate) {\n        var entry = this.model.extensions[id];\n        if (entry && entry.registryInfo) {\n            var compatInfo = ExtensionManager.getCompatibilityInfo(entry.registryInfo, brackets.metadata.apiVersion),\n                url = ExtensionManager.getExtensionURL(id, compatInfo.compatibleVersion);\n\n            // TODO: this should set .done on the returned promise\n            if (_isUpdate) {\n                InstallExtensionDialog.updateUsingDialog(url).done(ExtensionManager.updateFromDownload);\n            } else {\n                InstallExtensionDialog.installUsingDialog(url);\n            }\n        }\n    };\n\n    /**\n     * Filters the contents of the view.\n     * @param {string} query The query to filter by.\n     */\n    ExtensionManagerView.prototype.filter = function (query) {\n        this.model.filter(query);\n    };\n\n    exports.ExtensionManagerView = ExtensionManagerView;\n});\n"
  },
  {
    "path": "src/extensibility/ExtensionManagerViewModel.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: ExtensionManager*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var ExtensionManager    = require(\"extensibility/ExtensionManager\"),\n        registry_utils      = require(\"extensibility/registry_utils\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        Strings             = require(\"strings\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\");\n\n    /**\n     * @private\n     * @type {Array}\n     * A list of fields to search when trying to search for a query string in an object. Each field is\n     * represented as an array of keys to recurse downward through the object. We store this here to avoid\n     * doing it for each search call.\n     */\n    var _searchFields = [[\"metadata\", \"name\"], [\"metadata\", \"title\"], [\"metadata\", \"description\"],\n                         [\"metadata\", \"author\", \"name\"], [\"metadata\", \"keywords\"], [\"owner\"]];\n    /**\n     * The base model for the ExtensionManagerView. Keeps track of the extensions that are currently visible\n     * and manages sorting/filtering them. Must be disposed with dispose() when done.\n     * Events:\n     * - change - triggered when the data for a given extension changes. Second parameter is the extension id.\n     * - filter - triggered whenever the filtered set changes (including on initialize).\n     *\n     * @constructor\n     */\n    function ExtensionManagerViewModel() {\n        this._handleStatusChange = this._handleStatusChange.bind(this);\n\n        // Listen for extension status changes.\n        ExtensionManager\n            .on(\"statusChange.\" + this.source, this._handleStatusChange)\n            .on(\"registryUpdate.\" + this.source, this._handleStatusChange);\n    }\n    EventDispatcher.makeEventDispatcher(ExtensionManagerViewModel.prototype);\n\n    /**\n     * @type {string}\n     * Constant indicating that this model/view should initialize from the main extension registry.\n     */\n    ExtensionManagerViewModel.prototype.SOURCE_REGISTRY = \"registry\";\n\n    /**\n     * @type {string}\n     * Constant indicating that this model/view should initialize from the main extension registry with only themes.\n     */\n    ExtensionManagerViewModel.prototype.SOURCE_THEMES = \"themes\";\n\n    /**\n     * @type {string}\n     * Constant indicating that this model/view should initialize from the list of locally installed extensions.\n     */\n    ExtensionManagerViewModel.prototype.SOURCE_INSTALLED = \"installed\";\n\n    /**\n     * @type {string}\n     * Constant indicating that this model/view should initialize from the list of default bundled extensions.\n     */\n    ExtensionManagerViewModel.prototype.SOURCE_DEFAULT = \"default\";\n\n    /**\n     * @type {Object}\n     * The current set of extensions managed by this model. Same as ExtensionManager.extensions.\n     */\n    ExtensionManagerViewModel.prototype.extensions = null;\n\n    /**\n     * @type {string}\n     * The current source for the model; one of the SOURCE_* keys above.\n     */\n    ExtensionManagerViewModel.prototype.source = null;\n\n    /**\n     * @type {Array.<Object>}\n     * The list of IDs of items matching the current query and sorted with the current sort.\n     */\n    ExtensionManagerViewModel.prototype.filterSet = null;\n\n    /**\n     * @type {Object}\n     * The list of all ids from the extension list, sorted with the current sort.\n     */\n    ExtensionManagerViewModel.prototype.sortedFullSet = null;\n\n    /**\n     * @private\n     * @type {string}\n     * The last query we filtered by. Used to optimize future searches.\n     */\n    ExtensionManagerViewModel.prototype._lastQuery = null;\n\n    /**\n     * @type {string}\n     * Info message to display to the user when listing extensions\n     */\n    ExtensionManagerViewModel.prototype.infoMessage = null;\n\n    /**\n     * @type {string}\n     * An optional message to display to the user\n     */\n    ExtensionManagerViewModel.prototype.message = null;\n\n    /**\n     * @type {number}\n     * Number to show in tab's notification icon. No icon shown if 0.\n     */\n    ExtensionManagerViewModel.prototype.notifyCount = 0;\n\n    /**\n     * @private {$.Promise}\n     * Internal use only to track when initialization fails, see usage in _updateMessage.\n     */\n    ExtensionManagerViewModel.prototype._initializeFromSourcePromise = null;\n\n    /**\n     * Unregisters listeners when we're done.\n     */\n    ExtensionManagerViewModel.prototype.dispose = function () {\n        ExtensionManager.off(\".\" + this.source);\n    };\n\n    /**\n     * @private\n     * Sets up the initial filtered set based on the sorted full set.\n     */\n    ExtensionManagerViewModel.prototype._setInitialFilter = function () {\n        // Initial filtered list is the same as the sorted list.\n        this.filterSet = _.clone(this.sortedFullSet);\n        this.trigger(\"filter\");\n    };\n\n    /**\n     * @private\n     * Re-sorts the current full set based on the source we're viewing.\n     * The base implementation does nothing.\n     */\n    ExtensionManagerViewModel.prototype._sortFullSet = function () { };\n\n    /**\n     * Initializes the model from the source.\n     */\n    ExtensionManagerViewModel.prototype.initialize = function () {\n        var self = this;\n\n        this._initializeFromSourcePromise = this._initializeFromSource().always(function () {\n            self._updateMessage();\n        });\n\n        return this._initializeFromSourcePromise;\n    };\n\n    /**\n     * @private\n     * Updates the initial set and filter as necessary when the status of an extension changes,\n     * and notifies listeners of the change.\n     * @param {$.Event} e The jQuery event object.\n     * @param {string} id The id of the extension whose status changed.\n     */\n    ExtensionManagerViewModel.prototype._handleStatusChange = function (e, id) {\n        this.trigger(\"change\", id);\n    };\n\n    /**\n     * @private\n     * Searches for the given query in the current extension list and updates the filter set,\n     * dispatching a filter event.\n     * @param {string} query The string to search for.\n     * @param {boolean} force If true, always filter starting with the full set, not the last\n     *     query's filter.\n     */\n    ExtensionManagerViewModel.prototype.filter = function (query, force) {\n        var self = this, initialList;\n        if (!force && this._lastQuery && query.indexOf(this._lastQuery) === 0) {\n            // This is the old query with some new letters added, so we know we can just\n            // search in the current filter set. (This is true even if query has spaces).\n            initialList = this.filterSet;\n        } else {\n            // This is a new query, so start with the full list.\n            initialList = this.sortedFullSet;\n        }\n\n        var keywords = query.toLowerCase().split(/\\s+/);\n\n        // Takes 'extensionList' and returns a version filtered to only those that match 'keyword'\n        function filterForKeyword(extensionList, word) {\n            var filteredList = [];\n            extensionList.forEach(function (id) {\n                var entry = self._getEntry(id);\n                if (entry && self._entryMatchesQuery(entry, word)) {\n                    filteredList.push(id);\n                }\n            });\n            return filteredList;\n        }\n\n        // \"AND\" the keywords together: successively filter down the result set by each keyword in turn\n        var i, currentList = initialList;\n        for (i = 0; i < keywords.length; i++) {\n            currentList = filterForKeyword(currentList, keywords[i]);\n        }\n\n        this._lastQuery = query;\n        this.filterSet = currentList;\n\n        this._updateMessage();\n\n        this.trigger(\"filter\");\n    };\n\n    /**\n     * @private\n     * Updates an optional message displayed to the user along with the extension list.\n     */\n    ExtensionManagerViewModel.prototype._updateMessage = function () {\n        if (this._initializeFromSourcePromise && this._initializeFromSourcePromise.state() === \"rejected\") {\n            this.message = Strings.EXTENSION_MANAGER_ERROR_LOAD;\n        } else if (this.filterSet && this.filterSet.length === 0) {\n            this.message = this.sortedFullSet && this.sortedFullSet.length ? Strings.NO_EXTENSION_MATCHES : Strings.NO_EXTENSIONS;\n        } else {\n            this.message = null;\n        }\n    };\n\n    /**\n     * @private\n     * This is to be overridden by subclasses to provide the metadata for the extension\n     * with the provided `id`.\n     *\n     * @param {string} id of the extension\n     * @return {Object?} extension metadata or null if there's no matching extension\n     */\n    ExtensionManagerViewModel.prototype._getEntry = function (id) {\n        return null;\n    };\n\n    /**\n     * @private\n     * Tests if the given entry matches the query.\n     * @param {Object} entry The extension entry to test.\n     * @param {string} query The query to match against.\n     * @return {boolean} Whether the query matches.\n     */\n    ExtensionManagerViewModel.prototype._entryMatchesQuery = function (entry, query) {\n        return query === \"\" ||\n            _searchFields.some(function (fieldSpec) {\n                var i, cur = entry;\n                for (i = 0; i < fieldSpec.length; i++) {\n                    // Recurse downward through the specified fields to the leaf value.\n                    cur = cur[fieldSpec[i]];\n                    if (!cur) {\n                        return false;\n                    }\n                }\n                // If the leaf value is an array (like keywords), search each item, otherwise\n                // just search in the string.\n                if (Array.isArray(cur)) {\n                    return cur.some(function (keyword) {\n                        return keyword.toLowerCase().indexOf(query) !== -1;\n                    });\n                } else if (fieldSpec[fieldSpec.length - 1] === \"owner\") {\n                    // Special handling: ignore the authentication source when querying,\n                    // since it's not useful to search on\n                    var components = cur.split(\":\");\n                    if (components[1].toLowerCase().indexOf(query) !== -1) {\n                        return true;\n                    }\n                } else if (cur.toLowerCase().indexOf(query) !== -1) {\n                    return true;\n                }\n            });\n    };\n\n    ExtensionManagerViewModel.prototype._setSortedExtensionList = function (extensions, isTheme) {\n        this.filterSet = this.sortedFullSet = registry_utils.sortRegistry(extensions, \"registryInfo\", PreferencesManager.get(\"extensions.sort\"))\n            .filter(function (entry) {\n                if (!isTheme) {\n                    return entry.registryInfo && !entry.registryInfo.metadata.theme;\n                } else {\n                    return entry.registryInfo && entry.registryInfo.metadata.theme;\n                }\n            })\n            .map(function (entry) {\n                return entry.registryInfo.metadata.name;\n            });\n    };\n\n    /**\n     * The model for the ExtensionManagerView that is responsible for handling registry-based extensions.\n     * This extends ExtensionManagerViewModel.\n     * Must be disposed with dispose() when done.\n     *\n     * Events:\n     * - change - triggered when the data for a given extension changes. Second parameter is the extension id.\n     * - filter - triggered whenever the filtered set changes (including on initialize).\n     *\n     * @constructor\n     */\n    function RegistryViewModel() {\n        ExtensionManagerViewModel.call(this);\n        this.infoMessage = Strings.REGISTRY_SANITY_CHECK_WARNING;\n    }\n\n    RegistryViewModel.prototype = Object.create(ExtensionManagerViewModel.prototype);\n    RegistryViewModel.prototype.constructor = RegistryViewModel;\n\n    /**\n     * @type {string}\n     * RegistryViewModels always have a source of SOURCE_REGISTRY.\n     */\n    RegistryViewModel.prototype.source = ExtensionManagerViewModel.prototype.SOURCE_REGISTRY;\n\n    /**\n     * Initializes the model from the remote extension registry.\n     * @return {$.Promise} a promise that's resolved with the registry JSON data\n     * or rejected if the server can't be reached.\n     */\n    RegistryViewModel.prototype._initializeFromSource = function () {\n        var self = this;\n        return ExtensionManager.downloadRegistry()\n            .done(function () {\n                self.extensions = ExtensionManager.extensions;\n\n                // Sort the registry by last published date and store the sorted list of IDs.\n                self._setSortedExtensionList(ExtensionManager.extensions, false);\n                self._setInitialFilter();\n            })\n            .fail(function () {\n                self.extensions = [];\n                self.sortedFullSet = [];\n                self.filterSet = [];\n            });\n    };\n\n    /**\n     * @private\n     * Finds the extension metadata by id. If there is no extension matching the given id,\n     * this returns `null`.\n     * @param {string} id of the extension\n     * @return {Object?} extension metadata or null if there's no matching extension\n     */\n    RegistryViewModel.prototype._getEntry = function (id) {\n        var entry = this.extensions[id];\n        if (entry) {\n            return entry.registryInfo;\n        }\n        return entry;\n    };\n\n    /**\n     * The model for the ExtensionManagerView that is responsible for handling previously-installed extensions.\n     * This extends ExtensionManagerViewModel.\n     * Must be disposed with dispose() when done.\n     *\n     * Events:\n     * - change - triggered when the data for a given extension changes. Second parameter is the extension id.\n     * - filter - triggered whenever the filtered set changes (including on initialize).\n     *\n     * @constructor\n     */\n    function InstalledViewModel() {\n        ExtensionManagerViewModel.call(this);\n\n        // when registry is downloaded, sort extensions again - those with updates will be before others\n        var self = this;\n        ExtensionManager.on(\"registryDownload.\" + this.source, function () {\n            self._sortFullSet();\n            self._setInitialFilter();\n        });\n    }\n\n    InstalledViewModel.prototype = Object.create(ExtensionManagerViewModel.prototype);\n    InstalledViewModel.prototype.constructor = InstalledViewModel;\n\n    /**\n     * @type {string}\n     * InstalledViewModels always have a source of SOURCE_INSTALLED.\n     */\n    InstalledViewModel.prototype.source = ExtensionManagerViewModel.prototype.SOURCE_INSTALLED;\n\n    /**\n     * Initializes the model from the set of locally installed extensions, sorted\n     * alphabetically by id (or name of the extension folder for legacy extensions).\n     * @return {$.Promise} a promise that's resolved when we're done initializing.\n     */\n    InstalledViewModel.prototype._initializeFromSource = function () {\n        var self = this;\n        this.extensions = ExtensionManager.extensions;\n        this.sortedFullSet = Object.keys(this.extensions)\n            .filter(function (key) {\n                return self.extensions[key].installInfo &&\n                    self.extensions[key].installInfo.locationType !== ExtensionManager.LOCATION_DEFAULT;\n            });\n        this._sortFullSet();\n        this._setInitialFilter();\n        this._countUpdates();\n\n        return new $.Deferred().resolve().promise();\n    };\n\n    /**\n     * @private\n     * Re-sorts the current full set\n     */\n    InstalledViewModel.prototype._sortFullSet = function () {\n        var self = this;\n\n        this.sortedFullSet = this.sortedFullSet.sort(function (key1, key2) {\n            // before sorting by name, put first extensions that have updates\n            var ua1 = self.extensions[key1].installInfo.updateAvailable,\n                ua2 = self.extensions[key2].installInfo.updateAvailable;\n\n            if (ua1 && !ua2) {\n                return -1;\n            } else if (!ua1 && ua2) {\n                return 1;\n            }\n\n            var metadata1 = self.extensions[key1].installInfo.metadata,\n                metadata2 = self.extensions[key2].installInfo.metadata,\n                id1 = (metadata1.title || metadata1.name).toLocaleLowerCase(),\n                id2 = (metadata2.title || metadata2.name).toLocaleLowerCase();\n\n            return id1.localeCompare(id2);\n        });\n    };\n\n    /**\n     * @private\n     * Updates notifyCount based on number of extensions with an update available\n     */\n    InstalledViewModel.prototype._countUpdates = function () {\n        var self = this;\n        this.notifyCount = 0;\n        this.sortedFullSet.forEach(function (key) {\n            if (self.extensions[key].installInfo.updateCompatible && !ExtensionManager.isMarkedForUpdate(key)) {\n                self.notifyCount++;\n            }\n        });\n    };\n\n    /**\n     * @private\n     * Updates the initial set and filter as necessary when the status of an extension changes,\n     * and notifies listeners of the change.\n     * @param {$.Event} e The jQuery event object.\n     * @param {string} id The id of the extension whose status changed.\n     */\n    InstalledViewModel.prototype._handleStatusChange = function (e, id) {\n        var index = this.sortedFullSet.indexOf(id),\n            refilter = false;\n        if (index !== -1 && !this.extensions[id].installInfo) {\n            // This was in our set, but was uninstalled. Remove it.\n            this.sortedFullSet.splice(index, 1);\n            this._countUpdates();  // may also affect update count\n            refilter = true;\n        } else if (index === -1 && this.extensions[id].installInfo) {\n            // This was not in our set, but is now installed. Add it and resort.\n            this.sortedFullSet.push(id);\n            this._sortFullSet();\n            refilter = true;\n        }\n        if (refilter) {\n            this.filter(this._lastQuery || \"\", true);\n        }\n\n        if (this.extensions[id].installInfo) {\n            // If our count of available updates may have been affected, re-count\n            this._countUpdates();\n        }\n\n        ExtensionManagerViewModel.prototype._handleStatusChange.call(this, e, id);\n    };\n\n    /**\n     * @private\n     * Finds the extension metadata by id. If there is no extension matching the given id,\n     * this returns `null`.\n     * @param {string} id of the extension\n     * @return {Object?} extension metadata or null if there's no matching extension\n     */\n    InstalledViewModel.prototype._getEntry = function (id) {\n        var entry = this.extensions[id];\n        if (entry) {\n            return entry.installInfo;\n        }\n        return entry;\n    };\n\n    /**\n     * Model for displaying default extensions that come bundled with Brackets\n     */\n    function DefaultViewModel() {\n        ExtensionManagerViewModel.call(this);\n    }\n\n    // Inheritance setup\n    DefaultViewModel.prototype = Object.create(ExtensionManagerViewModel.prototype);\n    DefaultViewModel.prototype.constructor = DefaultViewModel;\n\n    /**\n     * Add SOURCE_DEFAULT to DefaultViewModel\n     */\n    DefaultViewModel.prototype.source = ExtensionManagerViewModel.prototype.SOURCE_DEFAULT;\n\n    /**\n     * Initializes the model from the set of default extensions, sorted alphabetically by id\n     * @return {$.Promise} a promise that's resolved when we're done initializing.\n     */\n    DefaultViewModel.prototype._initializeFromSource = function () {\n        var self = this;\n        this.extensions = ExtensionManager.extensions;\n        this.sortedFullSet = Object.keys(this.extensions)\n            .filter(function (key) {\n                return self.extensions[key].installInfo &&\n                    self.extensions[key].installInfo.locationType === ExtensionManager.LOCATION_DEFAULT;\n            });\n        this._sortFullSet();\n        this._setInitialFilter();\n        return new $.Deferred().resolve().promise();\n    };\n\n    /**\n     * @private\n     * Re-sorts the current full set\n     */\n    DefaultViewModel.prototype._sortFullSet = function () {\n        var self = this;\n        this.sortedFullSet = this.sortedFullSet.sort(function (key1, key2) {\n            var metadata1 = self.extensions[key1].installInfo.metadata,\n                metadata2 = self.extensions[key2].installInfo.metadata,\n                id1 = (metadata1.title || metadata1.name).toLocaleLowerCase(),\n                id2 = (metadata2.title || metadata2.name).toLocaleLowerCase();\n            return id1.localeCompare(id2);\n        });\n    };\n\n    /**\n     * @private\n     * Finds the default extension metadata by id. If there is no default extension matching the given id,\n     * this returns `null`.\n     * @param {string} id of the theme extension\n     * @return {Object?} extension metadata or null if there's no matching extension\n     */\n    DefaultViewModel.prototype._getEntry = function (id) {\n        return this.extensions[id] ? this.extensions[id].installInfo : null;\n    };\n\n    /**\n     * The model for the ExtensionManagerView that is responsible for handling registry-based theme extensions.\n     * This extends ExtensionManagerViewModel.\n     * Must be disposed with dispose() when done.\n     *\n     * Events:\n     * - change - triggered when the data for a given extension changes. Second parameter is the extension id.\n     * - filter - triggered whenever the filtered set changes (including on initialize).\n     *\n     * @constructor\n     */\n    function ThemesViewModel() {\n        ExtensionManagerViewModel.call(this);\n    }\n\n    // Inheritance setup\n    ThemesViewModel.prototype = Object.create(ExtensionManagerViewModel.prototype);\n    ThemesViewModel.prototype.constructor = ThemesViewModel;\n\n    /**\n     * @type {string}\n     * ThemeViewModels always have a source of SOURCE_THEMES.\n     */\n    ThemesViewModel.prototype.source = ExtensionManagerViewModel.prototype.SOURCE_THEMES;\n\n    /**\n     * Initializes the model from the remote extension registry.\n     * @return {$.Promise} a promise that's resolved with the registry JSON data.\n     */\n    ThemesViewModel.prototype._initializeFromSource = function () {\n        var self = this;\n        return ExtensionManager.downloadRegistry()\n            .done(function () {\n                self.extensions = ExtensionManager.extensions;\n\n                // Sort the registry by last published date and store the sorted list of IDs.\n                self._setSortedExtensionList(ExtensionManager.extensions, true);\n                self._setInitialFilter();\n            })\n            .fail(function () {\n                self.extensions = [];\n                self.sortedFullSet = [];\n                self.filterSet = [];\n            });\n    };\n\n    /**\n     * @private\n     * Finds the theme extension metadata by id. If there is no theme extension matching the given id,\n     * this returns `null`.\n     * @param {string} id of the theme extension\n     * @return {Object?} extension metadata or null if there's no matching extension\n     */\n    ThemesViewModel.prototype._getEntry = function (id) {\n        var entry = this.extensions[id];\n        if (entry) {\n            return entry.registryInfo;\n        }\n        return entry;\n    };\n\n    exports.RegistryViewModel = RegistryViewModel;\n    exports.ThemesViewModel = ThemesViewModel;\n    exports.InstalledViewModel = InstalledViewModel;\n    exports.DefaultViewModel = DefaultViewModel;\n});"
  },
  {
    "path": "src/extensibility/InstallExtensionDialog.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: Install Extension Dialog*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Dialogs                = require(\"widgets/Dialogs\"),\n        File                   = require(\"filesystem/File\"),\n        StringUtils            = require(\"utils/StringUtils\"),\n        Strings                = require(\"strings\"),\n        FileSystem             = require(\"filesystem/FileSystem\"),\n        KeyEvent               = require(\"utils/KeyEvent\"),\n        Package                = require(\"extensibility/Package\"),\n        NativeApp              = require(\"utils/NativeApp\"),\n        InstallDialogTemplate  = require(\"text!htmlContent/install-extension-dialog.html\"),\n        Mustache               = require(\"thirdparty/mustache/mustache\");\n\n    var STATE_CLOSED              = 0,\n        STATE_START               = 1,\n        STATE_VALID_URL           = 2,\n        STATE_INSTALLING          = 3,\n        STATE_INSTALLED           = 4,\n        STATE_INSTALL_FAILED      = 5,\n        STATE_CANCELING_INSTALL   = 6,\n        STATE_CANCELING_HUNG      = 7,\n        STATE_INSTALL_CANCELED    = 8,\n        STATE_ALREADY_INSTALLED   = 9,\n        STATE_OVERWRITE_CONFIRMED = 10,\n        STATE_NEEDS_UPDATE        = 11;\n\n    /**\n     * Creates a new extension installer dialog.\n     * @constructor\n     * @param {{install: function(url), cancel: function()}} installer The installer backend to use.\n     */\n    function InstallExtensionDialog(installer, _isUpdate) {\n        this._installer = installer;\n        this._state = STATE_CLOSED;\n        this._installResult = null;\n        this._isUpdate = _isUpdate;\n\n        // Timeout before we allow user to leave STATE_INSTALL_CANCELING without waiting for a resolution\n        // (per-instance so we can poke it for unit testing)\n        this._cancelTimeout = 10 * 1000;\n    }\n\n    /**\n     * The dialog root.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$dlg = null;\n\n    /**\n     * The url input field.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$url = null;\n\n    /**\n     * The ok button.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$okButton = null;\n\n    /**\n     * The cancel button.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$cancelButton = null;\n\n    /**\n     * The area containing the url input label and field.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$inputArea = null;\n\n    /**\n     * The area containing the installation message and spinner.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$msgArea = null;\n\n    /**\n     * The span containing the installation message.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$msg = null;\n\n    /**\n     * The \"Browse Extensions\" button.\n     * @type {jQuery}\n     */\n    InstallExtensionDialog.prototype.$browseExtensionsButton = null;\n\n    /**\n     * A deferred that's resolved/rejected when the dialog is closed and\n     * something has/hasn't been installed successfully.\n     * @type {$.Deferred}\n     */\n    InstallExtensionDialog.prototype._dialogDeferred = null;\n\n\n    /**\n     * installer The installer backend for this dialog.\n     * @type {{install: function(url), cancel: function()}}\n     */\n    InstallExtensionDialog.prototype._installer = null;\n\n    /**\n     * The current state of the dialog; one of the STATE_* constants above.\n     * @type {number}\n     */\n    InstallExtensionDialog.prototype._state = null;\n\n    /**\n     * @private\n     * Transitions the dialog into a new state as the installation proceeds.\n     * @param {number} newState The state to transition into; one of the STATE_* variables.\n     */\n    InstallExtensionDialog.prototype._enterState = function (newState) {\n        var url,\n            msg,\n            self = this,\n            prevState = this._state;\n\n        // Store the new state up front in case some of the processing below ends up changing\n        // the state again immediately.\n        this._state = newState;\n\n        switch (newState) {\n        case STATE_START:\n            // This should match the default appearance of the dialog when it first opens.\n            this.$msg.find(\".spinner\").remove();\n            this.$msgArea.hide();\n            this.$inputArea.show();\n            this.$okButton\n                .prop(\"disabled\", true)\n                .text(Strings.INSTALL);\n            break;\n\n        case STATE_VALID_URL:\n            this.$okButton.prop(\"disabled\", false);\n            break;\n\n        case STATE_INSTALLING:\n            url = this.$url.val().trim();\n            this.$inputArea.hide();\n            this.$browseExtensionsButton.hide();\n            this.$msg.text(StringUtils.format(Strings.INSTALLING_FROM, url))\n                .append(\"<span class='spinner inline spin'/>\");\n            this.$msgArea.show();\n            this.$okButton.prop(\"disabled\", true);\n            this._installer.install(url)\n                .done(function (result) {\n                    self._installResult = result;\n                    if (result.installationStatus === Package.InstallationStatuses.ALREADY_INSTALLED ||\n                            result.installationStatus === Package.InstallationStatuses.OLDER_VERSION ||\n                            result.installationStatus === Package.InstallationStatuses.SAME_VERSION) {\n                        self._enterState(STATE_ALREADY_INSTALLED);\n                    } else if (result.installationStatus === Package.InstallationStatuses.NEEDS_UPDATE) {\n                        self._enterState(STATE_NEEDS_UPDATE);\n                    } else {\n                        self._enterState(STATE_INSTALLED);\n                    }\n                })\n                .fail(function (err) {\n                    // If the \"failure\" is actually a user-requested cancel, don't show an error UI\n                    if (err === \"CANCELED\") {\n                        console.assert(self._state === STATE_CANCELING_INSTALL || self._state === STATE_CANCELING_HUNG);\n                        self._enterState(STATE_INSTALL_CANCELED);\n                    } else {\n                        self._errorMessage = Package.formatError(err);\n                        self._enterState(STATE_INSTALL_FAILED);\n                    }\n                });\n            break;\n\n        case STATE_CANCELING_INSTALL:\n            // This should call back the STATE_INSTALLING fail() handler above, unless it's too late to cancel\n            // in which case we'll still jump to STATE_INSTALLED after this\n            this.$cancelButton.prop(\"disabled\", true);\n            this.$msg.text(Strings.CANCELING_INSTALL);\n            this._installer.cancel();\n            window.setTimeout(function () {\n                if (self._state === STATE_CANCELING_INSTALL) {\n                    self._enterState(STATE_CANCELING_HUNG);\n                }\n            }, this._cancelTimeout);\n            break;\n\n        case STATE_CANCELING_HUNG:\n            this.$msg.text(Strings.CANCELING_HUNG);\n            this.$okButton\n                .removeAttr(\"disabled\")\n                .text(Strings.CLOSE);\n            break;\n\n        case STATE_INSTALLED:\n        case STATE_INSTALL_FAILED:\n        case STATE_INSTALL_CANCELED:\n        case STATE_NEEDS_UPDATE:\n            if (newState === STATE_INSTALLED) {\n                msg = Strings.INSTALL_SUCCEEDED;\n            } else if (newState === STATE_INSTALL_FAILED) {\n                msg = Strings.INSTALL_FAILED;\n            } else if (newState === STATE_NEEDS_UPDATE) {\n                msg = Strings.EXTENSION_UPDATE_INSTALLED;\n            } else {\n                msg = Strings.INSTALL_CANCELED;\n            }\n            this.$msg.html($(\"<strong/>\").text(msg));\n            if (this._errorMessage) {\n                this.$msg.append($(\"<p/>\").text(this._errorMessage));\n            }\n            this.$okButton\n                .removeAttr(\"disabled\")\n                .text(Strings.CLOSE);\n            this.$cancelButton.hide();\n            break;\n\n        case STATE_ALREADY_INSTALLED:\n            var installResult = this._installResult;\n            var status = installResult.installationStatus;\n            var msgText = Strings[\"EXTENSION_\" + status];\n            if (status === Package.InstallationStatuses.OLDER_VERSION) {\n                msgText = StringUtils.format(msgText, installResult.metadata.version, installResult.installedVersion);\n            }\n            this.$msg.text(msgText);\n            this.$okButton\n                .prop(\"disabled\", false)\n                .text(Strings.OVERWRITE);\n            break;\n\n        case STATE_OVERWRITE_CONFIRMED:\n            this._enterState(STATE_CLOSED);\n            break;\n\n        case STATE_CLOSED:\n            $(window.document.body).off(\".installDialog\");\n\n           // Only resolve as successful if we actually installed something.\n            Dialogs.cancelModalDialogIfOpen(\"install-extension-dialog\");\n            if (prevState === STATE_INSTALLED || prevState === STATE_NEEDS_UPDATE ||\n                    prevState === STATE_OVERWRITE_CONFIRMED) {\n                this._dialogDeferred.resolve(this._installResult);\n            } else {\n                this._dialogDeferred.reject();\n            }\n            break;\n        }\n    };\n\n    /**\n     * @private\n     * Handle a click on the Cancel button, which either cancels an ongoing installation (leaving\n     * the dialog open), or closes the dialog if no installation is in progress.\n     */\n    InstallExtensionDialog.prototype._handleCancel = function () {\n        if (this._state === STATE_INSTALLING) {\n            this._enterState(STATE_CANCELING_INSTALL);\n        } else if (this._state === STATE_ALREADY_INSTALLED) {\n            // If we were prompting the user about overwriting a previous installation,\n            // and the user cancels, we can delete the downloaded file.\n            if (this._installResult && this._installResult.localPath && !this._installResult.keepFile) {\n                var filename = this._installResult.localPath;\n                FileSystem.getFileForPath(filename).unlink();\n            }\n            this._enterState(STATE_CLOSED);\n        } else if (this._state !== STATE_CANCELING_INSTALL) {\n            this._enterState(STATE_CLOSED);\n        }\n    };\n\n    /**\n     * @private\n     * Handle a click on the default button, which is \"Install\" while we're waiting for the\n     * user to enter a URL, and \"Close\" once we've successfully finished installation.\n     */\n    InstallExtensionDialog.prototype._handleOk = function () {\n        if (this._state === STATE_INSTALLED ||\n                this._state === STATE_INSTALL_FAILED ||\n                this._state === STATE_INSTALL_CANCELED ||\n                this._state === STATE_CANCELING_HUNG ||\n                this._state === STATE_NEEDS_UPDATE) {\n            // In these end states, this is a \"Close\" button: just close the dialog and indicate\n            // success.\n            this._enterState(STATE_CLOSED);\n        } else if (this._state === STATE_VALID_URL) {\n            this._enterState(STATE_INSTALLING);\n        } else if (this._state === STATE_ALREADY_INSTALLED) {\n            this._enterState(STATE_OVERWRITE_CONFIRMED);\n        }\n    };\n\n    /**\n     * @private\n     * Handle key up events on the document. We use this to detect the Esc key.\n     */\n    InstallExtensionDialog.prototype._handleKeyUp = function (e) {\n        if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n            this._handleCancel();\n        }\n    };\n\n    /**\n     * @private\n     * Handle typing in the URL field.\n     */\n    InstallExtensionDialog.prototype._handleUrlInput = function (e) {\n        var url     = this.$url.val().trim(),\n            valid   = (url !== \"\");\n        if (!valid && this._state === STATE_VALID_URL) {\n            this._enterState(STATE_START);\n        } else if (valid && this._state === STATE_START) {\n            this._enterState(STATE_VALID_URL);\n        }\n    };\n\n    /**\n     * @private\n     * Closes the dialog if it's not already closed. For unit testing only.\n     */\n    InstallExtensionDialog.prototype._close = function () {\n        if (this._state !== STATE_CLOSED) {\n            this._enterState(STATE_CLOSED);\n        }\n    };\n\n    /**\n     * Initialize and show the dialog.\n     * @param {string=} urlToInstall If specified, immediately starts installing the given file as if the user had\n     *     specified it.\n     * @return {$.Promise} A promise object that will be resolved when the selected extension\n     *     has finished installing, or rejected if the dialog is cancelled.\n     */\n    InstallExtensionDialog.prototype.show = function (urlToInstall) {\n        if (this._state !== STATE_CLOSED) {\n            // Somehow the dialog got invoked twice. Just ignore this.\n            return this._dialogDeferred.promise();\n        }\n\n        var context = {\n            Strings: Strings,\n            isUpdate: this._isUpdate,\n            includeBrowseExtensions: !!brackets.config.extension_listing_url\n        };\n\n        // We ignore the promise returned by showModalDialogUsingTemplate, since we're managing the\n        // lifecycle of the dialog ourselves.\n        Dialogs.showModalDialogUsingTemplate(Mustache.render(InstallDialogTemplate, context), false);\n\n        this.$dlg          = $(\".install-extension-dialog.instance\");\n        this.$url          = this.$dlg.find(\".url\").focus();\n        this.$okButton     = this.$dlg.find(\".dialog-button[data-button-id='ok']\");\n        this.$cancelButton = this.$dlg.find(\".dialog-button[data-button-id='cancel']\");\n        this.$inputArea    = this.$dlg.find(\".input-field\");\n        this.$msgArea      = this.$dlg.find(\".message-field\");\n        this.$msg          = this.$msgArea.find(\".message\");\n        this.$browseExtensionsButton = this.$dlg.find(\".browse-extensions\");\n\n        this.$okButton.on(\"click\", this._handleOk.bind(this));\n        this.$cancelButton.on(\"click\", this._handleCancel.bind(this));\n        this.$url.on(\"input\", this._handleUrlInput.bind(this));\n        this.$browseExtensionsButton.on(\"click\", function () {\n            NativeApp.openURLInDefaultBrowser(brackets.config.extension_listing_url);\n        });\n        $(window.document.body).on(\"keyup.installDialog\", this._handleKeyUp.bind(this));\n\n        this._enterState(STATE_START);\n        if (urlToInstall) {\n            // Act as if the user had manually entered the URL.\n            this.$url.val(urlToInstall);\n            this._enterState(STATE_VALID_URL);\n            this._enterState(STATE_INSTALLING);\n        }\n\n        this._dialogDeferred = new $.Deferred();\n        return this._dialogDeferred.promise();\n    };\n\n\n    /** Mediates between this module and the Package extension-installation utils. Mockable for unit-testing. */\n    function InstallerFacade(isLocalFile) {\n        this._isLocalFile = isLocalFile;\n    }\n\n    InstallerFacade.prototype.install = function (url) {\n        if (this.pendingInstall) {\n            console.error(\"Extension installation already pending\");\n            return new $.Deferred().reject(\"DOWNLOAD_ID_IN_USE\").promise();\n        }\n\n        if (this._isLocalFile) {\n            var deferred = new $.Deferred();\n\n            this.pendingInstall = {\n                promise: deferred.promise(),\n                cancel: function () {\n                    // Can't cancel local zip installs\n                }\n            };\n\n            Package.installFromPath(url).then(function (installationResult) {\n                // Flag to keep zip files for local file installation\n                installationResult.keepFile = true;\n                deferred.resolve(installationResult);\n            }, deferred.reject);\n        } else {\n            this.pendingInstall = Package.installFromURL(url);\n        }\n\n        // Store now since we'll null pendingInstall immediately if the promise was resolved synchronously\n        var promise = this.pendingInstall.promise;\n\n        var self = this;\n        this.pendingInstall.promise.always(function () {\n            self.pendingInstall = null;\n        });\n\n        return promise;\n    };\n    InstallerFacade.prototype.cancel = function () {\n        this.pendingInstall.cancel();\n    };\n\n    /**\n     * @private\n     * Show a dialog that allows the user to enter the URL of an extension ZIP file to install.\n     * @return {$.Promise} A promise object that will be resolved when the selected extension\n     *     has finished installing, or rejected if the dialog is cancelled.\n     */\n    function showDialog() {\n        var dlg = new InstallExtensionDialog(new InstallerFacade());\n        return dlg.show();\n    }\n\n    /**\n     * @private\n     * Show the installation dialog and automatically begin installing the given URL.\n     * @param {(string|File)=} urlOrFileToInstall If specified, immediately starts installing the given file as if the user had\n     *     specified it.\n     * @return {$.Promise} A promise object that will be resolved when the selected extension\n     *     has finished installing, or rejected if the dialog is cancelled.\n     */\n    function installUsingDialog(urlOrFileToInstall, _isUpdate) {\n        var isLocalFile = (urlOrFileToInstall instanceof File),\n            dlg = new InstallExtensionDialog(new InstallerFacade(isLocalFile), _isUpdate);\n\n        return dlg.show(urlOrFileToInstall.fullPath || urlOrFileToInstall);\n    }\n\n    /**\n     * @private\n     * Show the update dialog and automatically begin downloading the update from the given URL.\n     * @param {string} urlToUpdate URL to download\n     * @return {$.Promise} A promise object that will be resolved when the selected extension\n     *     has finished downloading, or rejected if the dialog is cancelled.\n     */\n    function updateUsingDialog(urlToUpdate) {\n        return installUsingDialog(urlToUpdate, true);\n    }\n\n    exports.showDialog          = showDialog;\n    exports.installUsingDialog  = installUsingDialog;\n    exports.updateUsingDialog   = updateUsingDialog;\n\n    // Exposed for unit testing only\n    exports._Dialog = InstallExtensionDialog;\n});\n"
  },
  {
    "path": "src/extensibility/Package.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\n/**\n * Functions for working with extension packages\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit              = require(\"utils/AppInit\"),\n        FileSystem           = require(\"filesystem/FileSystem\"),\n        FileUtils            = require(\"file/FileUtils\"),\n        StringUtils          = require(\"utils/StringUtils\"),\n        Strings              = require(\"strings\"),\n        ExtensionLoader      = require(\"utils/ExtensionLoader\"),\n        NodeConnection       = require(\"utils/NodeConnection\"),\n        PreferencesManager   = require(\"preferences/PreferencesManager\"),\n        PathUtils            = require(\"thirdparty/path-utils/path-utils\");\n\n    PreferencesManager.definePreference(\"proxy\", \"string\", undefined, {\n        description: Strings.DESCRIPTION_PROXY\n    });\n\n    var PREF_EXTENSIONS_DEFAULT_DISABLED = \"extensions.default.disabled\";\n    PreferencesManager.definePreference(PREF_EXTENSIONS_DEFAULT_DISABLED, \"array\", [], {\n        description: Strings.DESCRIPTION_DISABLED_DEFAULT_EXTENSIONS\n    });\n\n    var Errors = {\n        ERROR_LOADING: \"ERROR_LOADING\",\n        MALFORMED_URL: \"MALFORMED_URL\",\n        UNSUPPORTED_PROTOCOL: \"UNSUPPORTED_PROTOCOL\"\n    };\n\n    var InstallationStatuses = {\n        FAILED: \"FAILED\",\n        INSTALLED: \"INSTALLED\",\n        ALREADY_INSTALLED: \"ALREADY_INSTALLED\",\n        SAME_VERSION: \"SAME_VERSION\",\n        OLDER_VERSION: \"OLDER_VERSION\",\n        NEEDS_UPDATE: \"NEEDS_UPDATE\",\n        DISABLED: \"DISABLED\"\n    };\n\n    /**\n     * @private\n     * @type {NodeConnection}\n     * Connects to ExtensionManagerDomain\n     */\n    var _nodeConnection;\n\n    /**\n     * @private\n     * @type {jQuery.Deferred.<NodeConnection>}\n     * A deferred which is resolved with a NodeConnection or rejected if\n     * we are unable to connect to Node.\n     */\n    var _nodeConnectionDeferred = $.Deferred();\n\n    /**\n     * @type {number} Used to generate unique download ids\n     */\n    var _uniqueId = 0;\n\n    function _extensionManagerCall(callback) {\n        if (_nodeConnection.domains.extensionManager) {\n            return callback(_nodeConnection.domains.extensionManager);\n        } else {\n            return new $.Deferred().reject(\"extensionManager domain is undefined\").promise();\n        }\n    }\n\n    /**\n     * TODO: can this go away now that we never call it directly?\n     *\n     * Validates the package at the given path. The actual validation is\n     * handled by the Node server.\n     *\n     * The promise is resolved with an object:\n     * { errors: Array.<{string}>, metadata: { name:string, version:string, ... } }\n     * metadata is pulled straight from package.json and will be undefined\n     * if there are errors or null if the extension did not include package.json.\n     *\n     * @param {string} Absolute path to the package zip file\n     * @param {{requirePackageJSON: ?boolean}} validation options\n     * @return {$.Promise} A promise that is resolved with information about the package\n     */\n    function validate(path, options) {\n        return _extensionManagerCall(function (extensionManager) {\n            var d = new $.Deferred();\n            \n            // make sure proxy is attached to options before calling validate\n            // so npm can use it in the domain\n            options = options || {};\n            options.proxy = PreferencesManager.get(\"proxy\");\n            \n            extensionManager.validate(path, options)\n                .done(function (result) {\n                    d.resolve({\n                        errors: result.errors,\n                        metadata: result.metadata\n                    });\n                })\n                .fail(function (error) {\n                    d.reject(error);\n                });\n\n            return d.promise();\n        });\n    }\n\n    /**\n     * Validates and installs the package at the given path. Validation and\n     * installation is handled by the Node process.\n     *\n     * The extension will be installed into the user's extensions directory.\n     * If the user already has the extension installed, it will instead go\n     * into their disabled extensions directory.\n     *\n     * The promise is resolved with an object:\n     * { errors: Array.<{string}>, metadata: { name:string, version:string, ... },\n     * disabledReason:string, installedTo:string, commonPrefix:string }\n     * metadata is pulled straight from package.json and is likely to be undefined\n     * if there are errors. It is null if there was no package.json.\n     *\n     * disabledReason is either null or the reason the extension was installed disabled.\n     *\n     * @param {string} path Absolute path to the package zip file\n     * @param {?string} nameHint Hint for the extension folder's name (used in favor of\n     *          path's filename if present, and if no package metadata present).\n     * @param {?boolean} _doUpdate private argument used to signal an update\n     * @return {$.Promise} A promise that is resolved with information about the package\n     *          (which may include errors, in which case the extension was disabled), or\n     *          rejected with an error object.\n     */\n    function install(path, nameHint, _doUpdate) {\n        return _extensionManagerCall(function (extensionManager) {\n            var d                       = new $.Deferred(),\n                destinationDirectory    = ExtensionLoader.getUserExtensionPath(),\n                disabledDirectory       = destinationDirectory.replace(/\\/user$/, \"/disabled\"),\n                systemDirectory         = FileUtils.getNativeBracketsDirectoryPath() + \"/extensions/default/\";\n\n            var operation = _doUpdate ? \"update\" : \"install\";\n            extensionManager[operation](path, destinationDirectory, {\n                disabledDirectory: disabledDirectory,\n                systemExtensionDirectory: systemDirectory,\n                apiVersion: brackets.metadata.apiVersion,\n                nameHint: nameHint,\n                proxy: PreferencesManager.get(\"proxy\")\n            })\n                .done(function (result) {\n                    result.keepFile = false;\n\n                    if (result.installationStatus !== InstallationStatuses.INSTALLED || _doUpdate) {\n                        d.resolve(result);\n                    } else {\n                        // This was a new extension and everything looked fine.\n                        // We load it into Brackets right away.\n                        ExtensionLoader.loadExtension(result.name, {\n                            // On Windows, it looks like Node converts Unix-y paths to backslashy paths.\n                            // We need to convert them back.\n                            baseUrl: FileUtils.convertWindowsPathToUnixPath(result.installedTo)\n                        }, \"main\").then(function () {\n                            d.resolve(result);\n                        }, function () {\n                            d.reject(Errors.ERROR_LOADING);\n                        });\n                    }\n                })\n                .fail(function (error) {\n                    d.reject(error);\n                });\n\n            return d.promise();\n        });\n    }\n\n\n\n    /**\n     * Special case handling to make the common case of downloading from GitHub easier; modifies 'urlInfo' as\n     * needed. Converts a bare GitHub repo URL to the corresponding master ZIP URL; or if given a direct\n     * master ZIP URL already, sets a nicer download filename (both cases use the repo name).\n     *\n     * @param {{url:string, parsed:Array.<string>, filenameHint:string}} urlInfo\n     */\n    function githubURLFilter(urlInfo) {\n        if (urlInfo.parsed.hostname === \"github.com\" || urlInfo.parsed.hostname === \"www.github.com\") {\n            // Is it a URL to the root of a repo? (/user/repo)\n            var match = /^\\/[^\\/?]+\\/([^\\/?]+)(\\/?)$/.exec(urlInfo.parsed.pathname);\n            if (match) {\n                if (!match[2]) {\n                    urlInfo.url += \"/\";\n                }\n                urlInfo.url += \"archive/master.zip\";\n                urlInfo.filenameHint = match[1] + \".zip\";\n\n            } else {\n                // Is it a URL directly to the repo's 'master.zip'? (/user/repo/archive/master.zip)\n                match = /^\\/[^\\/?]+\\/([^\\/?]+)\\/archive\\/master.zip$/.exec(urlInfo.parsed.pathname);\n                if (match) {\n                    urlInfo.filenameHint = match[1] + \".zip\";\n                }\n            }\n        }\n    }\n\n    /**\n     * Downloads from the given URL to a temporary location. On success, resolves with the path of the\n     * downloaded file (typically in a temp folder) and a hint for the real filename. On failure, rejects\n     * with an error object.\n     *\n     * @param {string} url URL of the file to be downloaded\n     * @param {number} downloadId Unique number to identify this request\n     * @return {$.Promise}\n     */\n    function download(url, downloadId) {\n        return _extensionManagerCall(function (extensionManager) {\n            var d = new $.Deferred();\n\n            // Validate URL\n            // TODO: PathUtils fails to parse URLs that are missing the protocol part (e.g. starts immediately with \"www...\")\n            var parsed = PathUtils.parseUrl(url);\n            if (!parsed.hostname) {  // means PathUtils failed to parse at all\n                d.reject(Errors.MALFORMED_URL);\n                return d.promise();\n            }\n            if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n                d.reject(Errors.UNSUPPORTED_PROTOCOL);\n                return d.promise();\n            }\n\n            var urlInfo = { url: url, parsed: parsed, filenameHint: parsed.filename };\n            githubURLFilter(urlInfo);\n\n            // Decide download destination\n            var filename = urlInfo.filenameHint;\n            filename = filename.replace(/[^a-zA-Z0-9_\\- \\(\\)\\.]/g, \"_\"); // make sure it's a valid filename\n            if (!filename) {  // in case of URL ending in \"/\"\n                filename = \"extension.zip\";\n            }\n\n            // Download the bits (using Node since brackets-shell doesn't support binary file IO)\n            var r = extensionManager.downloadFile(downloadId, urlInfo.url, PreferencesManager.get(\"proxy\"));\n            r.done(function (result) {\n                d.resolve({ localPath: FileUtils.convertWindowsPathToUnixPath(result), filenameHint: urlInfo.filenameHint });\n            }).fail(function (err) {\n                d.reject(err);\n            });\n\n            return d.promise();\n        });\n    }\n\n    /**\n     * Attempts to synchronously cancel the given pending download. This may not be possible, e.g.\n     * if the download has already finished.\n     *\n     * @param {number} downloadId Identifier previously passed to download()\n     */\n    function cancelDownload(downloadId) {\n        return _extensionManagerCall(function (extensionManager) {\n            return extensionManager.abortDownload(downloadId);\n        });\n    }\n\n    /**\n     * On success, resolves with an extension metadata object; at that point, the extension has already\n     * started running in Brackets. On failure (including validation errors), rejects with an error object.\n     *\n     * An error object consists of either a string error code OR an array where the first entry is the error\n     * code and the remaining entries are further info. The error code string is one of either\n     * ExtensionsDomain.Errors or Package.Errors. Use formatError() to convert an error object to a friendly,\n     * localized error message.\n     *\n     * @param {string} path Absolute path to the package zip file\n     * @param {?string} filenameHint Hint for the extension folder's name (used in favor of\n     *          path's filename if present, and if no package metadata present).\n     * @return {$.Promise} A promise that is rejected if there are errors during\n     *          install or the extension is disabled.\n     */\n    function installFromPath(path, filenameHint) {\n        var d = new $.Deferred();\n\n        install(path, filenameHint)\n            .done(function (result) {\n                result.keepFile = true;\n\n                var installationStatus = result.installationStatus;\n                if (installationStatus === InstallationStatuses.ALREADY_INSTALLED ||\n                        installationStatus === InstallationStatuses.NEEDS_UPDATE ||\n                        installationStatus === InstallationStatuses.SAME_VERSION ||\n                        installationStatus === InstallationStatuses.OLDER_VERSION) {\n                    d.resolve(result);\n                } else {\n                    if (result.errors && result.errors.length > 0) {\n                        // Validation errors - for now, only return the first one\n                        d.reject(result.errors[0]);\n                    } else if (result.disabledReason) {\n                        // Extension valid but left disabled (wrong API version, extension name collision, etc.)\n                        d.reject(result.disabledReason);\n                    } else {\n                        // Success! Extension is now running in Brackets\n                        d.resolve(result);\n                    }\n                }\n            })\n            .fail(function (err) {\n                d.reject(err);\n            });\n\n        return d.promise();\n    }\n\n    /**\n     * On success, resolves with an extension metadata object; at that point, the extension has already\n     * started running in Brackets. On failure (including validation errors), rejects with an error object.\n     *\n     * An error object consists of either a string error code OR an array where the first entry is the error\n     * code and the remaining entries are further info. The error code string is one of either\n     * ExtensionsDomain.Errors or Package.Errors. Use formatError() to convert an error object to a friendly,\n     * localized error message.\n     *\n     * The returned cancel() function will *attempt* to cancel installation, but it is not guaranteed to\n     * succeed. If cancel() succeeds, the Promise is rejected with a CANCELED error code. If we're unable\n     * to cancel, the Promise is resolved or rejected normally, as if cancel() had never been called.\n     *\n     * @return {{promise: $.Promise, cancel: function():boolean}}\n     */\n    function installFromURL(url) {\n        var STATE_DOWNLOADING = 1,\n            STATE_INSTALLING = 2,\n            STATE_SUCCEEDED = 3,\n            STATE_FAILED = 4;\n\n        var d = new $.Deferred();\n        var state = STATE_DOWNLOADING;\n\n        var downloadId = (_uniqueId++);\n        download(url, downloadId)\n            .done(function (downloadResult) {\n                state = STATE_INSTALLING;\n\n                installFromPath(downloadResult.localPath, downloadResult.filenameHint)\n                    .done(function (result) {\n                        var installationStatus = result.installationStatus;\n\n                        state = STATE_SUCCEEDED;\n                        result.localPath = downloadResult.localPath;\n                        result.keepFile = false;\n\n                        if (installationStatus === InstallationStatuses.INSTALLED) {\n                            // Delete temp file\n                            FileSystem.getFileForPath(downloadResult.localPath).unlink();\n                        }\n\n                        d.resolve(result);\n                    })\n                    .fail(function (err) {\n                        // File IO errors, internal error in install()/validate(), or extension startup crashed\n                        state = STATE_FAILED;\n                        FileSystem.getFileForPath(downloadResult.localPath).unlink();\n                        d.reject(err);  // TODO: needs to be err.message ?\n                    });\n            })\n            .fail(function (err) {\n                // Download error (the Node-side download code cleans up any partial ZIP file)\n                state = STATE_FAILED;\n                d.reject(err);\n            });\n\n        return {\n            promise: d.promise(),\n            cancel: function () {\n                if (state === STATE_DOWNLOADING) {\n                    // This will trigger download()'s fail() handler with CANCELED as the err code\n                    cancelDownload(downloadId);\n                }\n                // Else it's too late to cancel; we'll continue on through the done() chain and emit\n                // a success result (calling done() handlers) if all else goes well.\n            }\n        };\n    }\n\n    /**\n     * Converts an error object as returned by install(), installFromPath() or\n     * installFromURL() into a flattened, localized string.\n     *\n     * @param {string|Array.<string>} error\n     * @return {string}\n     */\n    function formatError(error) {\n        function localize(key) {\n            if (Strings[key]) {\n                return Strings[key];\n            }\n            console.log(\"Unknown installation error\", key);\n            return Strings.UNKNOWN_ERROR;\n        }\n\n        if (Array.isArray(error)) {\n            error[0] = localize(error[0]);\n            return StringUtils.format.apply(window, error);\n        } else {\n            return localize(error);\n        }\n    }\n\n    /**\n     * Removes the extension at the given path.\n     *\n     * @param {string} path The absolute path to the extension to remove.\n     * @return {$.Promise} A promise that's resolved when the extension is removed, or\n     *     rejected if there was an error.\n     */\n    function remove(path) {\n        return _extensionManagerCall(function (extensionManager) {\n            return extensionManager.remove(path);\n        });\n    }\n\n    /**\n     * This function manages the PREF_EXTENSIONS_DEFAULT_DISABLED preference\n     * holding an array of default extension paths that should not be loaded\n     * on Brackets startup\n     */\n    function toggleDefaultExtension(path, enabled) {\n        var arr = PreferencesManager.get(PREF_EXTENSIONS_DEFAULT_DISABLED);\n        if (!Array.isArray(arr)) { arr = []; }\n        var io = arr.indexOf(path);\n        if (enabled === true && io !== -1) {\n            arr.splice(io, 1);\n        } else if (enabled === false && io === -1) {\n            arr.push(path);\n        }\n        PreferencesManager.set(PREF_EXTENSIONS_DEFAULT_DISABLED, arr);\n    }\n\n    /**\n     * Disables the extension at the given path.\n     *\n     * @param {string} path The absolute path to the extension to disable.\n     * @return {$.Promise} A promise that's resolved when the extenion is disabled, or\n     *      rejected if there was an error.\n     */\n    function disable(path) {\n        var result = new $.Deferred(),\n            file = FileSystem.getFileForPath(path + \"/.disabled\");\n\n        var defaultExtensionPath = ExtensionLoader.getDefaultExtensionPath();\n        if (file.fullPath.indexOf(defaultExtensionPath) === 0) {\n            toggleDefaultExtension(path, false);\n            result.resolve();\n            return result.promise();\n        }\n\n        file.write(\"\", function (err) {\n            if (err) {\n                return result.reject(err);\n            }\n            result.resolve();\n        });\n        return result.promise();\n    }\n\n    /**\n     * Enables the extension at the given path.\n     *\n     * @param {string} path The absolute path to the extension to enable.\n     * @return {$.Promise} A promise that's resolved when the extenion is enable, or\n     *      rejected if there was an error.\n     */\n    function enable(path) {\n        var result = new $.Deferred(),\n            file = FileSystem.getFileForPath(path + \"/.disabled\");\n\n        function afterEnable() {\n            ExtensionLoader.loadExtension(FileUtils.getBaseName(path), { baseUrl: path }, \"main\")\n                .done(result.resolve)\n                .fail(result.reject);\n        }\n\n        var defaultExtensionPath = ExtensionLoader.getDefaultExtensionPath();\n        if (file.fullPath.indexOf(defaultExtensionPath) === 0) {\n            toggleDefaultExtension(path, true);\n            afterEnable();\n            return result.promise();\n        }\n\n        file.unlink(function (err) {\n            if (err) {\n                return result.reject(err);\n            }\n            afterEnable();\n        });\n        return result.promise();\n    }\n\n    /**\n     * Install an extension update located at path.\n     * This assumes that the installation was previously attempted\n     * and an installationStatus of \"ALREADY_INSTALLED\", \"NEEDS_UPDATE\", \"SAME_VERSION\",\n     * or \"OLDER_VERSION\" was the result.\n     *\n     * This workflow ensures that there should not generally be validation errors\n     * because the first pass at installation the extension looked at the metadata\n     * and installed packages.\n     *\n     * @param {string} path to package file\n     * @param {?string} nameHint Hint for the extension folder's name (used in favor of\n     *          path's filename if present, and if no package metadata present).\n     * @return {$.Promise} A promise that is resolved when the extension is successfully\n     *      installed or rejected if there is a problem.\n     */\n    function installUpdate(path, nameHint) {\n        var d = new $.Deferred();\n        install(path, nameHint, true)\n            .done(function (result) {\n                if (result.installationStatus !== InstallationStatuses.INSTALLED) {\n                    d.reject(result.errors);\n                } else {\n                    d.resolve(result);\n                }\n            })\n            .fail(function (error) {\n                d.reject(error);\n            });\n        return d.promise();\n    }\n\n    /**\n     * Allows access to the deferred that manages the node connection. This\n     * is *only* for unit tests. Messing with this not in testing will\n     * potentially break everything.\n     *\n     * @private\n     * @return {jQuery.Deferred} The deferred that manages the node connection\n     */\n    function _getNodeConnectionDeferred() {\n        return _nodeConnectionDeferred;\n    }\n\n    // Initializes node connection\n    // TODO: duplicates code from StaticServer\n    // TODO: can this be done lazily?\n    AppInit.appReady(function () {\n        _nodeConnection = new NodeConnection();\n        _nodeConnection.connect(true).then(function () {\n            var domainPath = FileUtils.getNativeBracketsDirectoryPath() + \"/\" + FileUtils.getNativeModuleDirectoryPath(module) + \"/node/ExtensionManagerDomain\";\n\n            _nodeConnection.loadDomains(domainPath, true)\n                .then(\n                    function () {\n                        _nodeConnectionDeferred.resolve();\n                    },\n                    function () { // Failed to connect\n                        console.error(\"[Extensions] Failed to connect to node\", arguments);\n                        _nodeConnectionDeferred.reject();\n                    }\n                );\n        });\n    });\n\n    // For unit tests only\n    exports._getNodeConnectionDeferred = _getNodeConnectionDeferred;\n\n    exports.installFromURL          = installFromURL;\n    exports.installFromPath         = installFromPath;\n    exports.validate                = validate;\n    exports.install                 = install;\n    exports.remove                  = remove;\n    exports.disable                 = disable;\n    exports.enable                  = enable;\n    exports.installUpdate           = installUpdate;\n    exports.formatError             = formatError;\n    exports.InstallationStatuses    = InstallationStatuses;\n});\n"
  },
  {
    "path": "src/extensibility/node/ExtensionManagerDomain.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar semver   = require(\"semver\"),\n    path     = require(\"path\"),\n    request  = require(\"request\"),\n    fs       = require(\"fs-extra\"),\n    temp     = require(\"temp\"),\n    validate = require(\"./package-validator\").validate;\n\n// Automatically clean up temp files on exit\ntemp.track();\n\nvar Errors = {\n    API_NOT_COMPATIBLE: \"API_NOT_COMPATIBLE\",\n    MISSING_REQUIRED_OPTIONS: \"MISSING_REQUIRED_OPTIONS\",\n    DOWNLOAD_ID_IN_USE: \"DOWNLOAD_ID_IN_USE\",\n    BAD_HTTP_STATUS: \"BAD_HTTP_STATUS\",             // {0} is the HTTP status code\n    NO_SERVER_RESPONSE: \"NO_SERVER_RESPONSE\",\n    CANNOT_WRITE_TEMP: \"CANNOT_WRITE_TEMP\",\n    CANCELED: \"CANCELED\"\n};\n\nvar Statuses = {\n    FAILED: \"FAILED\",\n    INSTALLED: \"INSTALLED\",\n    ALREADY_INSTALLED: \"ALREADY_INSTALLED\",\n    SAME_VERSION: \"SAME_VERSION\",\n    OLDER_VERSION: \"OLDER_VERSION\",\n    NEEDS_UPDATE: \"NEEDS_UPDATE\",\n    DISABLED: \"DISABLED\"\n};\n\n/**\n * Maps unique download ID to info about the pending download. No entry if download no longer pending.\n * outStream is only present if we've started receiving the body.\n * @type {Object.<string, {request:!http.ClientRequest, callback:!function(string, string), localPath:string, outStream:?fs.WriteStream}>}\n */\nvar pendingDownloads = {};\n\n/**\n * Private function to remove the installation directory if the installation fails.\n * This does not call any callbacks. It's assumed that the callback has already been called\n * and this cleanup routine will do its best to complete in the background. If there's\n * a problem here, it is simply logged with console.error.\n *\n * @param {string} installDirectory Directory to remove\n */\nfunction _removeFailedInstallation(installDirectory) {\n    fs.remove(installDirectory, function (err) {\n        if (err) {\n            console.error(\"Error while removing directory after failed installation\", installDirectory, err);\n        }\n    });\n}\n\n/**\n * Private function to unzip to the correct directory.\n *\n * @param {string} Absolute path to the package zip file\n * @param {string} Absolute path to the destination directory for unzipping\n * @param {Object} the return value with the useful information for the client\n * @param {Function} callback function that is called at the end of the unzipping\n */\nfunction _performInstall(packagePath, installDirectory, validationResult, callback) {\n    validationResult.installedTo = installDirectory;\n\n    function fail(err) {\n        _removeFailedInstallation(installDirectory);\n        callback(err, null);\n    }\n\n    function finish() {\n        // The status may have already been set previously (as in the\n        // DISABLED case.\n        if (!validationResult.installationStatus) {\n            validationResult.installationStatus = Statuses.INSTALLED;\n        }\n        callback(null, validationResult);\n    }\n\n    fs.mkdirs(installDirectory, function (err) {\n        if (err) {\n            callback(err);\n            return;\n        }\n        var sourceDir = path.join(validationResult.extractDir, validationResult.commonPrefix);\n\n        fs.copy(sourceDir, installDirectory, function (err) {\n            if (err) {\n                return fail(err);\n            }\n            finish();\n        });\n    });\n}\n\n/**\n * Private function to remove the target directory and then install.\n *\n * @param {string} Absolute path to the package zip file\n * @param {string} Absolute path to the destination directory for unzipping\n * @param {Object} the return value with the useful information for the client\n * @param {Function} callback function that is called at the end of the unzipping\n */\nfunction _removeAndInstall(packagePath, installDirectory, validationResult, callback) {\n    // If this extension was previously installed but disabled, we will overwrite the\n    // previous installation in that directory.\n    fs.remove(installDirectory, function (err) {\n        if (err) {\n            callback(err);\n            return;\n        }\n        _performInstall(packagePath, installDirectory, validationResult, callback);\n    });\n}\n\nfunction _checkExistingInstallation(validationResult, installDirectory, systemInstallDirectory, callback) {\n    // If the extension being installed does not have a package.json, we can't\n    // do any kind of version comparison, so we just signal to the UI that\n    // it already appears to be installed.\n    if (!validationResult.metadata) {\n        validationResult.installationStatus = Statuses.ALREADY_INSTALLED;\n        callback(null, validationResult);\n        return;\n    }\n\n    fs.readJson(path.join(installDirectory, \"package.json\"), function (err, packageObj) {\n        // if the package.json is unreadable, we assume that the new package is an update\n        // that is the first to include a package.json.\n        if (err) {\n            validationResult.installationStatus = Statuses.NEEDS_UPDATE;\n        } else {\n            // Check to see if the version numbers signal an update.\n            if (semver.lt(packageObj.version, validationResult.metadata.version)) {\n                validationResult.installationStatus = Statuses.NEEDS_UPDATE;\n            } else if (semver.gt(packageObj.version, validationResult.metadata.version)) {\n                // Pass a message back to the UI that the new package appears to be an older version\n                // than what's installed.\n                validationResult.installationStatus = Statuses.OLDER_VERSION;\n                validationResult.installedVersion = packageObj.version;\n            } else {\n                // Signal to the UI that it looks like the user is re-installing the\n                // same version.\n                validationResult.installationStatus = Statuses.SAME_VERSION;\n            }\n        }\n        callback(null, validationResult);\n    });\n}\n\n/**\n * A \"legacy package\" is an extension that was installed based on the GitHub name without\n * a package.json file. Checking for the presence of these legacy extensions will help\n * users upgrade if the extension developer puts a different name in package.json than\n * the name of the GitHub project.\n *\n * @param {string} legacyDirectory directory to check for old-style extension.\n */\nfunction legacyPackageCheck(legacyDirectory) {\n    return fs.existsSync(legacyDirectory) && !fs.existsSync(path.join(legacyDirectory, \"package.json\"));\n}\n\n/**\n * Implements the \"install\" command in the \"extensions\" domain.\n *\n * There is no need to call validate independently. Validation is the first\n * thing that is done here.\n *\n * After the extension is validated, it is installed in destinationDirectory\n * unless the extension is already present there. If it is already present,\n * a determination is made about whether the package being installed is\n * an update. If it does appear to be an update, then result.installationStatus\n * is set to NEEDS_UPDATE. If not, then it's set to ALREADY_INSTALLED.\n *\n * If the installation succeeds, then result.installationStatus is set to INSTALLED.\n *\n * The extension is unzipped into a directory in destinationDirectory with\n * the name of the extension (the name is derived either from package.json\n * or the name of the zip file).\n *\n * The destinationDirectory will be created if it does not exist.\n *\n * @param {string} Absolute path to the package zip file\n * @param {string} the destination directory\n * @param {{disabledDirectory: !string, apiVersion: !string, nameHint: ?string,\n *      systemExtensionDirectory: !string}} additional settings to control the installation\n * @param {function} callback (err, result)\n * @param {function} pCallback (msg) callback for notifications about operation progress\n * @param {boolean} _doUpdate  private argument to signal that an update should be performed\n */\nfunction _cmdInstall(packagePath, destinationDirectory, options, callback, pCallback, _doUpdate) {\n    if (!options || !options.disabledDirectory || !options.apiVersion || !options.systemExtensionDirectory) {\n        callback(new Error(Errors.MISSING_REQUIRED_OPTIONS), null);\n        return;\n    }\n\n    function validateCallback(err, validationResult) {\n        validationResult.localPath = packagePath;\n\n        // This is a wrapper for the callback that will delete the temporary\n        // directory to which the package was unzipped.\n        function deleteTempAndCallback(err) {\n            if (validationResult.extractDir) {\n                fs.remove(validationResult.extractDir);\n                delete validationResult.extractDir;\n            }\n            callback(err, validationResult);\n        }\n\n        // If there was trouble at the validation stage, we stop right away.\n        if (err || validationResult.errors.length > 0) {\n            validationResult.installationStatus = Statuses.FAILED;\n            deleteTempAndCallback(err);\n            return;\n        }\n\n        // Prefers the package.json name field, but will take the zip\n        // file's name if that's all that's available.\n        var extensionName, guessedName;\n        if (options.nameHint) {\n            guessedName = path.basename(options.nameHint, \".zip\");\n        } else {\n            guessedName = path.basename(packagePath, \".zip\");\n        }\n        if (validationResult.metadata) {\n            extensionName = validationResult.metadata.name;\n        } else {\n            extensionName = guessedName;\n        }\n\n        validationResult.name = extensionName;\n        var installDirectory = path.join(destinationDirectory, extensionName),\n            legacyDirectory = path.join(destinationDirectory, guessedName),\n            systemInstallDirectory = path.join(options.systemExtensionDirectory, extensionName);\n\n        if (validationResult.metadata && validationResult.metadata.engines &&\n                validationResult.metadata.engines.brackets) {\n            var compatible = semver.satisfies(options.apiVersion,\n                                              validationResult.metadata.engines.brackets);\n            if (!compatible) {\n                installDirectory = path.join(options.disabledDirectory, extensionName);\n                validationResult.installationStatus = Statuses.DISABLED;\n                validationResult.disabledReason = Errors.API_NOT_COMPATIBLE;\n                _removeAndInstall(packagePath, installDirectory, validationResult, deleteTempAndCallback);\n                return;\n            }\n        }\n\n        // The \"legacy\" stuff should go away after all of the commonly used extensions\n        // have been upgraded with package.json files.\n        var hasLegacyPackage = validationResult.metadata && legacyPackageCheck(legacyDirectory);\n\n        // If the extension is already there, we signal to the front end that it's already installed\n        // unless the front end has signaled an intent to update.\n        if (hasLegacyPackage || fs.existsSync(installDirectory) || fs.existsSync(systemInstallDirectory)) {\n            if (_doUpdate === true) {\n                if (hasLegacyPackage) {\n                    // When there's a legacy installed extension, remove it first,\n                    // then also remove any new-style directory the user may have.\n                    // This helps clean up if the user is in a state where they have\n                    // both legacy and new extensions installed.\n                    fs.remove(legacyDirectory, function (err) {\n                        if (err) {\n                            deleteTempAndCallback(err);\n                            return;\n                        }\n                        _removeAndInstall(packagePath, installDirectory, validationResult, deleteTempAndCallback);\n                    });\n                } else {\n                    _removeAndInstall(packagePath, installDirectory, validationResult, deleteTempAndCallback);\n                }\n            } else if (hasLegacyPackage) {\n                validationResult.installationStatus = Statuses.NEEDS_UPDATE;\n                validationResult.name = guessedName;\n                deleteTempAndCallback(null);\n            } else {\n                _checkExistingInstallation(validationResult, installDirectory, systemInstallDirectory, deleteTempAndCallback);\n            }\n        } else {\n            // Regular installation with no conflicts.\n            validationResult.disabledReason = null;\n            _performInstall(packagePath, installDirectory, validationResult, deleteTempAndCallback);\n        }\n    }\n\n    validate(packagePath, options, validateCallback);\n}\n\n/**\n * Implements the \"update\" command in the \"extensions\" domain.\n *\n * Currently, this just wraps _cmdInstall, but will remove the existing directory\n * first.\n *\n * There is no need to call validate independently. Validation is the first\n * thing that is done here.\n *\n * After the extension is validated, it is installed in destinationDirectory\n * unless the extension is already present there. If it is already present,\n * a determination is made about whether the package being installed is\n * an update. If it does appear to be an update, then result.installationStatus\n * is set to NEEDS_UPDATE. If not, then it's set to ALREADY_INSTALLED.\n *\n * If the installation succeeds, then result.installationStatus is set to INSTALLED.\n *\n * The extension is unzipped into a directory in destinationDirectory with\n * the name of the extension (the name is derived either from package.json\n * or the name of the zip file).\n *\n * The destinationDirectory will be created if it does not exist.\n *\n * @param {string} Absolute path to the package zip file\n * @param {string} the destination directory\n * @param {{disabledDirectory: !string, apiVersion: !string, nameHint: ?string,\n *      systemExtensionDirectory: !string}} additional settings to control the installation\n * @param {function} callback (err, result)\n * @param {function} pCallback (msg) callback for notifications about operation progress\n */\nfunction _cmdUpdate(packagePath, destinationDirectory, options, callback, pCallback) {\n    _cmdInstall(packagePath, destinationDirectory, options, callback, pCallback, true);\n}\n\n/**\n * Wrap up after the given download has terminated (successfully or not). Closes connections, calls back the\n * client's callback, and IF there was an error, delete any partially-downloaded file.\n *\n * @param {string} downloadId Unique id originally passed to _cmdDownloadFile()\n * @param {?string} error If null, download was treated as successful\n */\nfunction _endDownload(downloadId, error) {\n    var downloadInfo = pendingDownloads[downloadId];\n    delete pendingDownloads[downloadId];\n\n    if (error) {\n        // Abort the download if still pending\n        // Note that this will trigger response's \"end\" event\n        downloadInfo.request.abort();\n\n        // Clean up any partially-downloaded file\n        // (if no outStream, then we never got a response back yet and never created any file)\n        if (downloadInfo.outStream) {\n            downloadInfo.outStream.end(function () {\n                fs.unlink(downloadInfo.localPath);\n            });\n        }\n\n        downloadInfo.callback(error, null);\n\n    } else {\n        // Download completed successfully. Flush stream to disk and THEN signal completion\n        downloadInfo.outStream.end(function () {\n            downloadInfo.callback(null, downloadInfo.localPath);\n        });\n    }\n}\n\n/**\n * Implements \"downloadFile\" command, asynchronously.\n */\nfunction _cmdDownloadFile(downloadId, url, proxy, callback, pCallback) {\n    // Backwards compatibility check, added in 0.37\n    if (typeof proxy === \"function\") {\n        callback = proxy;\n        proxy = undefined;\n    }\n\n    if (pendingDownloads[downloadId]) {\n        callback(Errors.DOWNLOAD_ID_IN_USE, null);\n        return;\n    }\n\n    var req = request.get({\n        url: url,\n        encoding: null,\n        proxy: proxy\n    },\n        // Note: we could use the traditional \"response\"/\"data\"/\"end\" events too if we wanted to stream data\n        // incrementally, limit download size, etc. - but the simple callback is good enough for our needs.\n        function (error, response, body) {\n            if (error) {\n                // Usually means we never got a response - server is down, no DNS entry, etc.\n                _endDownload(downloadId, Errors.NO_SERVER_RESPONSE);\n                return;\n            }\n            if (response.statusCode !== 200) {\n                _endDownload(downloadId, [Errors.BAD_HTTP_STATUS, response.statusCode]);\n                return;\n            }\n\n            var stream = temp.createWriteStream(\"brackets\");\n            if (!stream) {\n                _endDownload(downloadId, Errors.CANNOT_WRITE_TEMP);\n                return;\n            }\n            pendingDownloads[downloadId].localPath = stream.path;\n            pendingDownloads[downloadId].outStream = stream;\n\n            stream.write(body);\n            _endDownload(downloadId);\n        });\n\n    pendingDownloads[downloadId] = { request: req, callback: callback };\n}\n\n/**\n * Implements \"abortDownload\" command, synchronously.\n */\nfunction _cmdAbortDownload(downloadId) {\n    if (!pendingDownloads[downloadId]) {\n        // This may mean the download already completed\n        return false;\n    } else {\n        _endDownload(downloadId, Errors.CANCELED);\n        return true;\n    }\n}\n\n/**\n * Implements the remove extension command.\n */\nfunction _cmdRemove(extensionDir, callback, pCallback) {\n    fs.remove(extensionDir, function (err) {\n        if (err) {\n            callback(err);\n        } else {\n            callback(null);\n        }\n    });\n}\n\n/**\n * Initialize the \"extensions\" domain.\n * The extensions domain handles downloading, unpacking/verifying, and installing extensions.\n */\nfunction init(domainManager) {\n    if (!domainManager.hasDomain(\"extensionManager\")) {\n        domainManager.registerDomain(\"extensionManager\", {major: 0, minor: 1});\n    }\n    domainManager.registerCommand(\n        \"extensionManager\",\n        \"validate\",\n        validate,\n        true,\n        \"Verifies that the contents of the given ZIP file are a valid Brackets extension package\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path of the extension package\"\n        }, {\n            name: \"options\",\n            type: \"{requirePackageJSON: ?boolean}\",\n            description: \"options to control the behavior of the validator\"\n        }],\n        [{\n            name: \"errors\",\n            type: \"string|Array.<string>\",\n            description: \"download error, if any; first string is error code (one of Errors.*); subsequent strings are additional info\"\n        }, {\n            name: \"metadata\",\n            type: \"{name: string, version: string}\",\n            description: \"all package.json metadata (null if there's no package.json)\"\n        }]\n    );\n    domainManager.registerCommand(\n        \"extensionManager\",\n        \"install\",\n        _cmdInstall,\n        true,\n        \"Installs the given Brackets extension if it is valid (runs validation command automatically)\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path of the extension package\"\n        }, {\n            name: \"destinationDirectory\",\n            type: \"string\",\n            description: \"absolute filesystem path where this extension should be installed\"\n        }, {\n            name: \"options\",\n            type: \"{disabledDirectory: !string, apiVersion: !string, nameHint: ?string, systemExtensionDirectory: !string, proxy: ?string}\",\n            description: \"installation options: disabledDirectory should be set so that extensions can be installed disabled.\"\n        }],\n        [{\n            name: \"errors\",\n            type: \"string|Array.<string>\",\n            description: \"download error, if any; first string is error code (one of Errors.*); subsequent strings are additional info\"\n        }, {\n            name: \"metadata\",\n            type: \"{name: string, version: string}\",\n            description: \"all package.json metadata (null if there's no package.json)\"\n        }, {\n            name: \"disabledReason\",\n            type: \"string\",\n            description: \"reason this extension was installed disabled (one of Errors.*), none if it was enabled\"\n        }, {\n            name: \"installationStatus\",\n            type: \"string\",\n            description: \"Current status of the installation (an extension can be valid but not installed because it's an update\"\n        }, {\n            name: \"installedTo\",\n            type: \"string\",\n            description: \"absolute path where the extension was installed to\"\n        }, {\n            name: \"commonPrefix\",\n            type: \"string\",\n            description: \"top level directory in the package zip which contains all of the files\"\n        }]\n    );\n    domainManager.registerCommand(\n        \"extensionManager\",\n        \"update\",\n        _cmdUpdate,\n        true,\n        \"Updates the given Brackets extension (for which install was generally previously attemped). Brackets must be quit after this.\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path of the extension package\"\n        }, {\n            name: \"destinationDirectory\",\n            type: \"string\",\n            description: \"absolute filesystem path where this extension should be installed\"\n        }, {\n            name: \"options\",\n            type: \"{disabledDirectory: !string, apiVersion: !string, nameHint: ?string, systemExtensionDirectory: !string}\",\n            description: \"installation options: disabledDirectory should be set so that extensions can be installed disabled.\"\n        }],\n        [{\n            name: \"errors\",\n            type: \"string|Array.<string>\",\n            description: \"download error, if any; first string is error code (one of Errors.*); subsequent strings are additional info\"\n        }, {\n            name: \"metadata\",\n            type: \"{name: string, version: string}\",\n            description: \"all package.json metadata (null if there's no package.json)\"\n        }, {\n            name: \"disabledReason\",\n            type: \"string\",\n            description: \"reason this extension was installed disabled (one of Errors.*), none if it was enabled\"\n        }, {\n            name: \"installationStatus\",\n            type: \"string\",\n            description: \"Current status of the installation (an extension can be valid but not installed because it's an update\"\n        }, {\n            name: \"installedTo\",\n            type: \"string\",\n            description: \"absolute path where the extension was installed to\"\n        }, {\n            name: \"commonPrefix\",\n            type: \"string\",\n            description: \"top level directory in the package zip which contains all of the files\"\n        }]\n    );\n    domainManager.registerCommand(\n        \"extensionManager\",\n        \"remove\",\n        _cmdRemove,\n        true,\n        \"Removes the Brackets extension at the given path.\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path of the installed extension folder\"\n        }],\n        {}\n    );\n    domainManager.registerCommand(\n        \"extensionManager\",\n        \"downloadFile\",\n        _cmdDownloadFile,\n        true,\n        \"Downloads the file at the given URL, saving it to a temp location. Callback receives path to the downloaded file.\",\n        [{\n            name: \"downloadId\",\n            type: \"string\",\n            description: \"Unique identifier for this download 'session'\"\n        }, {\n            name: \"url\",\n            type: \"string\",\n            description: \"URL to download from\"\n        }, {\n            name: \"proxy\",\n            type: \"string\",\n            description: \"optional proxy URL\"\n        }],\n        {\n            type: \"string\",\n            description: \"Local path to the downloaded file\"\n        }\n    );\n    domainManager.registerCommand(\n        \"extensionManager\",\n        \"abortDownload\",\n        _cmdAbortDownload,\n        false,\n        \"Aborts any pending download with the given id. Ignored if no download pending (may be already complete).\",\n        [{\n            name: \"downloadId\",\n            type: \"string\",\n            description: \"Unique identifier for this download 'session', previously pased to downloadFile\"\n        }],\n        {\n            type: \"boolean\",\n            description: \"True if the download was pending and able to be canceled; false otherwise\"\n        }\n    );\n}\n\n// used in unit tests\nexports._cmdValidate = validate;\nexports._cmdInstall = _cmdInstall;\nexports._cmdRemove = _cmdRemove;\nexports._cmdUpdate = _cmdUpdate;\n\n// used to load the domain\nexports.init = init;\n"
  },
  {
    "path": "src/extensibility/node/README.md",
    "content": "## Brackets Extensibility\n\nThis code is used by Brackets to implement its extension management features. It is likely not useful to anyone not working with Brackets extensions.\n"
  },
  {
    "path": "src/extensibility/node/npm-installer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* eslint-env node */\n\n\"use strict\";\n\nvar fs    = require(\"fs-extra\"),\n    path  = require(\"path\"),\n    spawn = require(\"child_process\").spawn;\n\nvar Errors = {\n    NPM_INSTALL_FAILED: \"NPM_INSTALL_FAILED\"\n};\n\n/**\n * Private function to run \"npm install --production\" command in the extension directory.\n *\n * @param {string} installDirectory Directory to remove\n * @param {array} npmOptions can contain additional options like `--production` or `--proxy http://127.0.0.1:8888`\n * @param {function} callback NodeJS style callback to call after finish\n */\nfunction _performNpmInstall(installDirectory, npmOptions, callback) {\n    var npmPath = path.resolve(path.dirname(require.resolve(\"npm\")), \"..\", \"bin\", \"npm-cli.js\");\n    var args = [npmPath, \"install\"].concat(npmOptions);\n\n    console.log(\"running npm \" + args.slice(1).join(\" \") + \" in \" + installDirectory);\n\n    var child = spawn(process.execPath, args, { cwd: installDirectory });\n\n    child.on(\"error\", function (err) {\n        return callback(err);\n    });\n\n    var stdout = [];\n    child.stdout.addListener(\"data\", function (buffer) {\n        stdout.push(buffer);\n    });\n\n    var stderr = [];\n    child.stderr.addListener(\"data\", function (buffer) {\n        stderr.push(buffer);\n    });\n\n    var exitCode = 0;\n    child.addListener(\"exit\", function (code) {\n        exitCode = code;\n    });\n\n    child.addListener(\"close\", function () {\n        stderr = Buffer.concat(stderr).toString();\n        stdout = Buffer.concat(stdout).toString();\n        if (exitCode > 0) {\n            console.error(\"npm-stderr: \" + stderr);\n            return callback(new Error(stderr));\n        }\n        if (stderr) {\n            console.warn(\"npm-stderr: \" + stderr);\n        }\n        console.log(\"npm-stdout: \" + stdout);\n        return callback();\n    });\n\n    child.stdin.end();\n}\n\n/**\n * Checks package.json of the extracted extension for npm dependencies\n * and runs npm install when required.\n * @param {Object} validationResult return value of the validation procedure\n * @param {Function} callback function to be called after the end of validation procedure\n */\nfunction performNpmInstallIfRequired(npmOptions, validationResult, callback) {\n\n    function finish() {\n        callback(null, validationResult);\n    }\n\n    var installDirectory = path.join(validationResult.extractDir, validationResult.commonPrefix);\n    var packageJson;\n\n    try {\n        packageJson = fs.readJsonSync(path.join(installDirectory, \"package.json\"));\n    } catch (e) {\n        packageJson = null;\n    }\n\n    if (!packageJson || !packageJson.dependencies || !Object.keys(packageJson.dependencies).length) {\n        return finish();\n    }\n\n    _performNpmInstall(installDirectory, npmOptions, function (err) {\n        if (err) {\n            validationResult.errors.push([Errors.NPM_INSTALL_FAILED, err.toString()]);\n        }\n        finish();\n    });\n}\n\nexports.performNpmInstallIfRequired = performNpmInstallIfRequired;\n"
  },
  {
    "path": "src/extensibility/node/package-validator.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true, regexp: true */\n\n\"use strict\";\n\nvar DecompressZip               = require(\"decompress-zip\"),\n    semver                      = require(\"semver\"),\n    path                        = require(\"path\"),\n    temp                        = require(\"temp\"),\n    fs                          = require(\"fs-extra\"),\n    performNpmInstallIfRequired = require(\"./npm-installer\").performNpmInstallIfRequired;\n\n// Track and cleanup files at exit\ntemp.track();\n\nvar Errors = {\n    NOT_FOUND_ERR: \"NOT_FOUND_ERR\",                       // {0} is path where ZIP file was expected\n    INVALID_ZIP_FILE: \"INVALID_ZIP_FILE\",                 // {0} is path to ZIP file\n    INVALID_PACKAGE_JSON: \"INVALID_PACKAGE_JSON\",         // {0} is JSON parse error, {1} is path to ZIP file\n    MISSING_PACKAGE_NAME: \"MISSING_PACKAGE_NAME\",         // {0} is path to ZIP file\n    BAD_PACKAGE_NAME: \"BAD_PACKAGE_NAME\",                 // {0} is the name\n    MISSING_PACKAGE_VERSION: \"MISSING_PACKAGE_VERSION\",   // {0} is path to ZIP file\n    INVALID_VERSION_NUMBER: \"INVALID_VERSION_NUMBER\",     // {0} is version string in JSON, {1} is path to ZIP file\n    MISSING_MAIN: \"MISSING_MAIN\",                         // {0} is path to ZIP file\n    MISSING_PACKAGE_JSON: \"MISSING_PACKAGE_JSON\",         // {0} is path to ZIP file\n    INVALID_BRACKETS_VERSION: \"INVALID_BRACKETS_VERSION\", // {0} is the version string in JSON, {1} is the path to the zip file,\n    DISALLOWED_WORDS: \"DISALLOWED_WORDS\"                  // {0} is the field with the word, {1} is a string list of words that were in violation, {2} is the path to the zip file\n};\n\n/*\n * Directories to ignore when determining whether the contents of an extension are\n * in a subfolder.\n */\nvar ignoredFolders = [ \"__MACOSX\" ];\n\n/**\n * Returns true if the name presented is acceptable as a package name. This enforces the\n * requirement as presented in the CommonJS spec: http://wiki.commonjs.org/wiki/Packages/1.0\n * which states:\n *\n * \"This must be a unique, lowercase alpha-numeric name without spaces. It may include \".\" or \"_\" or \"-\" characters.\"\n *\n * We add the additional requirement that the first character must be a letter or number\n * (there's a security implication to allowing a name like \"..\", because the name is\n * used in directory names).\n *\n * @param {string} name to test\n * @return {boolean} true if the name is valid\n */\nfunction validateName(name) {\n    if (/^[a-z0-9][a-z0-9._\\-]*$/.exec(name)) {\n        return true;\n    }\n    return false;\n}\n\n// Parses strings of the form \"name <email> (url)\" where email and url are optional\nvar _personRegex = /^([^<\\(]+)(?:\\s+<([^>]+)>)?(?:\\s+\\(([^\\)]+)\\))?$/;\n\n/**\n * Normalizes person fields from package.json.\n *\n * These fields can be an object with name, email and url properties or a\n * string of the form \"name <email> <url>\". This does a tolerant parsing of\n * the data to try to return an object with name and optional email and url.\n * If the string does not match the format, the string is returned as the\n * name on the resulting object.\n *\n * If an object other than a string is passed in, it's returned as is.\n *\n * @param <String|Object> obj to normalize\n * @return {Object} person object with name and optional email and url\n */\nfunction parsePersonString(obj) {\n    if (typeof (obj) === \"string\") {\n        var parts = _personRegex.exec(obj);\n\n        // No regex match, so we just synthesize an object with an opaque name string\n        if (!parts) {\n            return {\n                name: obj\n            };\n        } else {\n            var result = {\n                name: parts[1]\n            };\n            if (parts[2]) {\n                result.email = parts[2];\n            }\n            if (parts[3]) {\n                result.url = parts[3];\n            }\n            return result;\n        }\n    } else {\n        // obj is not a string, so return as is\n        return obj;\n    }\n}\n\n/**\n * Determines if any of the words in wordlist appear in str.\n *\n * @param {String[]} wordlist list of words to check\n * @param {String} str to check for words\n * @return {String[]} words that matched\n */\nfunction containsWords(wordlist, str) {\n    var i;\n    var matches = [];\n    for (i = 0; i < wordlist.length; i++) {\n        var re = new RegExp(\"\\\\b\" + wordlist[i] + \"\\\\b\", \"i\");\n        if (re.exec(str)) {\n            matches.push(wordlist[i]);\n        }\n    }\n    return matches;\n}\n\n/**\n * Finds the common prefix, if any, for the files in a package file.\n *\n * In some package files, all of the files are contained in a subdirectory, and this function\n * will identify that directory if it exists.\n *\n * @param {string} extractDir directory into which the package was extracted\n * @param {function(Error, string)} callback function to accept err, commonPrefix (which will be \"\" if there is none)\n */\nfunction findCommonPrefix(extractDir, callback) {\n    fs.readdir(extractDir, function (err, files) {\n        ignoredFolders.forEach(function (folder) {\n            var index = files.indexOf(folder);\n            if (index !== -1) {\n                files.splice(index, 1);\n            }\n        });\n        if (err) {\n            callback(err);\n        } else if (files.length === 1) {\n            var name = files[0];\n            if (fs.statSync(path.join(extractDir, name)).isDirectory()) {\n                callback(null, name);\n            } else {\n                callback(null, \"\");\n            }\n        } else {\n            callback(null, \"\");\n        }\n    });\n}\n\n/**\n * Validates the contents of package.json.\n *\n * @param {string} path path to package file (used in error reporting)\n * @param {string} packageJSON path to the package.json file to check\n * @param {Object} options validation options passed to `validate()`\n * @param {function(Error, Array.<Array.<string, ...>>, Object)} callback function to call with array of errors and metadata\n */\nfunction validatePackageJSON(path, packageJSON, options, callback) {\n    var errors = [];\n    if (fs.existsSync(packageJSON)) {\n        fs.readFile(packageJSON, {\n            encoding: \"utf8\"\n        }, function (err, data) {\n            if (err) {\n                callback(err, null, null);\n                return;\n            }\n\n            var metadata;\n\n            try {\n                metadata = JSON.parse(data);\n            } catch (e) {\n                errors.push([Errors.INVALID_PACKAGE_JSON, e.toString(), path]);\n                callback(null, errors, undefined);\n                return;\n            }\n\n            // confirm required fields in the metadata\n            if (!metadata.name) {\n                errors.push([Errors.MISSING_PACKAGE_NAME, path]);\n            } else if (!validateName(metadata.name)) {\n                errors.push([Errors.BAD_PACKAGE_NAME, metadata.name]);\n            }\n            if (!metadata.version) {\n                errors.push([Errors.MISSING_PACKAGE_VERSION, path]);\n            } else if (!semver.valid(metadata.version)) {\n                errors.push([Errors.INVALID_VERSION_NUMBER, metadata.version, path]);\n            }\n\n            // normalize the author\n            if (metadata.author) {\n                metadata.author = parsePersonString(metadata.author);\n            }\n\n            // contributors should be an array of people.\n            // normalize each entry.\n            if (metadata.contributors) {\n                if (metadata.contributors.map) {\n                    metadata.contributors = metadata.contributors.map(function (person) {\n                        return parsePersonString(person);\n                    });\n                } else {\n                    metadata.contributors = [\n                        parsePersonString(metadata.contributors)\n                    ];\n                }\n            }\n\n            if (metadata.engines && metadata.engines.brackets) {\n                var range = metadata.engines.brackets;\n                if (!semver.validRange(range)) {\n                    errors.push([Errors.INVALID_BRACKETS_VERSION, range, path]);\n                }\n            }\n\n            if (options.disallowedWords) {\n                [\"title\", \"description\", \"name\"].forEach(function (field) {\n                    var words = containsWords(options.disallowedWords, metadata[field]);\n                    if (words.length > 0) {\n                        errors.push([Errors.DISALLOWED_WORDS, field, words.toString(), path]);\n                    }\n                });\n            }\n            callback(null, errors, metadata);\n        });\n    } else {\n        if (options.requirePackageJSON) {\n            errors.push([Errors.MISSING_PACKAGE_JSON, path]);\n        }\n        callback(null, errors, null);\n    }\n}\n\n/**\n * Extracts the package into the given directory and then validates it.\n *\n * @param {string} zipPath path to package zip file\n * @param {string} extractDir directory to extract package into\n * @param {Object} options validation options\n * @param {function(Error, {errors: Array, metadata: Object, commonPrefix: string, extractDir: string})} callback function to call with the result\n */\nfunction extractAndValidateFiles(zipPath, extractDir, options, callback) {\n    var unzipper = new DecompressZip(zipPath);\n    unzipper.on(\"error\", function (err) {\n        // General error to report for problems reading the file\n        callback(null, {\n            errors: [[Errors.INVALID_ZIP_FILE, zipPath, err]]\n        });\n        return;\n    });\n\n    unzipper.on(\"extract\", function (log) {\n        findCommonPrefix(extractDir, function (err, commonPrefix) {\n            if (err) {\n                callback(err, null);\n                return;\n            }\n            var packageJSON = path.join(extractDir, commonPrefix, \"package.json\");\n            validatePackageJSON(zipPath, packageJSON, options, function (err, errors, metadata) {\n                if (err) {\n                    callback(err, null);\n                    return;\n                }\n                var mainJS  = path.join(extractDir, commonPrefix, \"main.js\"),\n                    isTheme = metadata && metadata.theme;\n\n                // Throw missing main.js file only for non-theme extensions\n                if (!isTheme && !fs.existsSync(mainJS)) {\n                    errors.push([Errors.MISSING_MAIN, zipPath, mainJS]);\n                }\n\n                var npmOptions = ['--production'];\n\n                if (options.proxy) {\n                    npmOptions.push('--proxy ' + options.proxy);\n                }\n\n                if (process.platform.startsWith('win')) {\n                    // On Windows force a 32 bit build until nodejs 64 bit is supported.\n                    npmOptions.push('--arch=ia32');\n                    npmOptions.push('--npm_config_arch=ia32');\n                    npmOptions.push('--npm_config_target_arch=ia32');\n                }\n\n                performNpmInstallIfRequired(npmOptions, {\n                    errors: errors,\n                    metadata: metadata,\n                    commonPrefix: commonPrefix,\n                    extractDir: extractDir\n                }, callback);\n            });\n        });\n    });\n\n    unzipper.extract({\n        path: extractDir,\n        filter: function (file) {\n            return file.type !== \"SymbolicLink\";\n        }\n    });\n}\n\n/**\n * Implements the \"validate\" command in the \"extensions\" domain.\n * Validates the zipped package at path.\n *\n * The \"err\" parameter of the callback is only set if there was an\n * unexpected error. Otherwise, errors are reported in the result.\n *\n * The result object has an \"errors\" property. It is an array of\n * arrays of strings. Each array in the array is a set of parameters\n * that can be passed to StringUtils.format for internationalization.\n * The array will be empty if there are no errors.\n *\n * The result will have a \"metadata\" property if the metadata was\n * read successfully from package.json in the zip file.\n *\n * @param {string} path Absolute path to the package zip file\n * @param {{requirePackageJSON: ?boolean, disallowedWords: ?Array.<string>, proxy: ?<string>}} options for validation\n * @param {function} callback (err, result)\n */\nfunction validate(path, options, callback) {\n    options = options || {};\n    fs.exists(path, function (doesExist) {\n        if (!doesExist) {\n            callback(null, {\n                errors: [[Errors.NOT_FOUND_ERR, path]]\n            });\n            return;\n        }\n        temp.mkdir(\"bracketsPackage_\", function _tempDirCreated(err, extractDir) {\n            if (err) {\n                callback(err, null);\n                return;\n            }\n            extractAndValidateFiles(path, extractDir, options, callback);\n        });\n    });\n}\n\n// exported for unit testing\nexports._parsePersonString = parsePersonString;\n\nexports.errors = Errors;\nexports.validate = validate;\n"
  },
  {
    "path": "src/extensibility/node/spec/Installation.spec.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n/*global expect, describe, it, beforeEach, afterEach */\n\n\"use strict\";\n\nvar ExtensionsDomain = require(\"../ExtensionManagerDomain\"),\n    fs               = require(\"fs-extra\"),\n    async            = require(\"async\"),\n    path             = require(\"path\");\n\nvar testFilesDirectory = path.join(path.dirname(module.filename),\n                                    \"..\",   // node\n                                    \"..\",   // extensibility\n                                    \"..\",   // src\n                                    \"..\",   // brackets\n                                    \"test\",\n                                    \"spec\",\n                                    \"extension-test-files\"),\n    installParent      = path.join(path.dirname(module.filename), \"extensions\"),\n    installDirectory   = path.join(installParent, \"good\"),\n    disabledDirectory  = path.join(installParent, \"disabled\"),\n    systemExtensionDirectory = path.join(installParent, \"system\");\n\nvar basicValidExtension       = path.join(testFilesDirectory, \"basic-valid-extension.zip\"),\n    basicValidExtension09     = path.join(testFilesDirectory, \"basic-valid-extension-0.9.zip\"),\n    basicValidExtension2      = path.join(testFilesDirectory, \"basic-valid-extension-2.0.zip\"),\n    missingMain               = path.join(testFilesDirectory, \"missing-main.zip\"),\n    oneLevelDown              = path.join(testFilesDirectory, \"one-level-extension-master.zip\"),\n    incompatibleVersion       = path.join(testFilesDirectory, \"incompatible-version.zip\"),\n    invalidZip                = path.join(testFilesDirectory, \"invalid-zip-file.zip\"),\n    missingPackageJSON        = path.join(testFilesDirectory, \"missing-package-json.zip\"),\n    missingPackageJSONUpdate  = path.join(testFilesDirectory, \"missing-package-json-update.zip\"),\n    missingPackageJSONRenamed = path.join(testFilesDirectory, \"added-package-json-test\", \"missing-package-json.zip\"),\n    withSymlink               = path.join(testFilesDirectory, \"with-symlink.zip\"),\n    withNpmDependencies       = path.join(testFilesDirectory, \"with-npm-dependencies.zip\");\n\n\ndescribe(\"Package Installation\", function () {\n\n    var standardOptions = {\n        disabledDirectory: disabledDirectory,\n        systemExtensionDirectory: systemExtensionDirectory,\n        apiVersion: \"0.22.0\"\n    };\n\n    beforeEach(function (done) {\n        fs.mkdirs(installDirectory, function (err) {\n            fs.mkdirs(disabledDirectory, function (err) {\n                done();\n            });\n        });\n    });\n\n    afterEach(function (done) {\n        fs.remove(installParent, function (err) {\n            done();\n        });\n    });\n\n    function checkPaths(pathsToCheck, callback) {\n        var existsCalls = [];\n        pathsToCheck.forEach(function (path) {\n            existsCalls.push(function (callback) {\n                fs.exists(path, async.apply(callback, null));\n            });\n        });\n\n        async.parallel(existsCalls, function (err, results) {\n            expect(err).toBeNull();\n            results.forEach(function (result, num) {\n                expect(result ? \"\" : pathsToCheck[num] + \" does not exist\").toEqual(\"\");\n            });\n            callback();\n        });\n    }\n\n    it(\"should validate the package\", function (done) {\n        ExtensionsDomain._cmdInstall(missingMain, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(result.installationStatus).toEqual(\"FAILED\");\n            done();\n        });\n    });\n\n    it(\"should work fine if all is well\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n            var extensionDirectory = path.join(installDirectory, \"basic-valid-extension\");\n\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(0);\n            expect(result.metadata.name).toEqual(\"basic-valid-extension\");\n            expect(result.name).toEqual(\"basic-valid-extension\");\n            expect(result.installedTo).toEqual(extensionDirectory);\n            expect(result.installationStatus).toEqual(\"INSTALLED\");\n\n            var pathsToCheck = [\n                path.join(extensionDirectory, \"package.json\"),\n                path.join(extensionDirectory, \"main.js\")\n            ];\n\n            checkPaths(pathsToCheck, done);\n        });\n    });\n\n    it(\"should signal if an update installation is required\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n            var extensionDirectory = path.join(installDirectory, \"basic-valid-extension\");\n\n            expect(err).toBeNull();\n            expect(result.installedTo).toEqual(extensionDirectory);\n            expect(result.installationStatus).toEqual(\"INSTALLED\");\n            ExtensionsDomain._cmdInstall(basicValidExtension2, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toEqual(\"NEEDS_UPDATE\");\n                expect(result.localPath).toEqual(basicValidExtension2);\n                done();\n            });\n        });\n    });\n\n    it(\"should successfully update an extension\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            ExtensionsDomain._cmdInstall(basicValidExtension2, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toBe(\"NEEDS_UPDATE\");\n                ExtensionsDomain._cmdUpdate(basicValidExtension2, installDirectory, standardOptions, function (err, result) {\n                    expect(err).toBeNull();\n                    expect(result.installationStatus).toBe(\"INSTALLED\");\n                    expect(result.installedTo.substr(0, installDirectory.length)).toEqual(installDirectory);\n                    expect(fs.existsSync(result.installedTo)).toBe(true);\n                    var packageInfo = fs.readJsonSync(path.join(result.installedTo, \"package.json\"));\n                    expect(packageInfo.version).toBe(\"2.0.0\");\n                    done();\n                });\n            });\n        });\n    });\n\n    it(\"should signal an update if a package.json appears\", function (done) {\n        ExtensionsDomain._cmdInstall(missingPackageJSON, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.installationStatus).toEqual(\"INSTALLED\");\n            ExtensionsDomain._cmdInstall(missingPackageJSONUpdate, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toEqual(\"NEEDS_UPDATE\");\n                done();\n            });\n        });\n    });\n\n    // This is mildly redundant. the validation check should catch this.\n    // But, I wanted to be sure that the install function doesn't try to\n    // do anything with the file before validation.\n    it(\"should fail for missing package\", function (done) {\n        ExtensionsDomain._cmdInstall(path.join(testFilesDirectory, \"NOT A PACKAGE\"),\n                                     installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                var errors = result.errors;\n                expect(errors.length).toEqual(1);\n                expect(errors[0][0]).toEqual(\"NOT_FOUND_ERR\");\n                done();\n            });\n    });\n\n    it(\"should not install by default if the same version is already installed\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toEqual(\"SAME_VERSION\");\n                done();\n            });\n        });\n    });\n\n    it(\"should not install by default if an older version is already installed\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            ExtensionsDomain._cmdInstall(basicValidExtension09, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toEqual(\"OLDER_VERSION\");\n                done();\n            });\n        });\n    });\n\n    it(\"should not install by default if the same legacy extension is already installed\", function (done) {\n        ExtensionsDomain._cmdInstall(missingPackageJSON, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            ExtensionsDomain._cmdInstall(missingPackageJSON, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toEqual(\"ALREADY_INSTALLED\");\n                done();\n            });\n        });\n    });\n\n    it(\"should yield an error if there's no disabled directory set\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, { apiVersion: \"0.22.0\" }, function (err, result) {\n            expect(err.message).toEqual(\"MISSING_REQUIRED_OPTIONS\");\n            done();\n        });\n    });\n\n    it(\"should yield an error if there's no apiVersion set\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, { disabledDirectory: disabledDirectory }, function (err, result) {\n            expect(err.message).toEqual(\"MISSING_REQUIRED_OPTIONS\");\n            done();\n        });\n    });\n\n    it(\"should derive the name from the zip if there's no package.json\", function (done) {\n        ExtensionsDomain._cmdInstall(missingPackageJSON, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.disabledReason).toBeNull();\n            var extensionDirectory = path.join(installDirectory, \"missing-package-json\");\n            var pathsToCheck = [\n                path.join(extensionDirectory, \"main.js\")\n            ];\n            checkPaths(pathsToCheck, done);\n        });\n    });\n\n    it(\"should install with the common prefix removed\", function (done) {\n        ExtensionsDomain._cmdInstall(oneLevelDown, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            var extensionDirectory = path.join(installDirectory, \"one-level-extension\");\n            var pathsToCheck = [\n                path.join(extensionDirectory, \"main.js\"),\n                path.join(extensionDirectory, \"package.json\"),\n                path.join(extensionDirectory, \"lib\", \"foo.js\")\n            ];\n            checkPaths(pathsToCheck, done);\n        });\n    });\n\n    it(\"should disable extensions that are not compatible with the current Brackets API\", function (done) {\n        ExtensionsDomain._cmdInstall(incompatibleVersion, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.installationStatus).toEqual(\"DISABLED\");\n            expect(result.disabledReason).toEqual(\"API_NOT_COMPATIBLE\");\n            var extensionDirectory = path.join(disabledDirectory, \"incompatible-version\");\n            var pathsToCheck = [\n                path.join(extensionDirectory, \"main.js\"),\n                path.join(extensionDirectory, \"package.json\")\n            ];\n            checkPaths(pathsToCheck, done);\n        });\n    });\n\n    it(\"should not have trouble with invalid zip files\", function (done) {\n        ExtensionsDomain._cmdInstall(invalidZip, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(1);\n            done();\n        });\n    });\n\n    it(\"should remove an installed package\", function (done) {\n        ExtensionsDomain._cmdInstall(basicValidExtension, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(fs.existsSync(result.installedTo)).toBe(true);\n            ExtensionsDomain._cmdRemove(result.installedTo, function (err) {\n                expect(err).toBeNull();\n                expect(fs.existsSync(result.installedTo)).toBe(false);\n                done();\n            });\n        });\n    });\n\n    it(\"should handle a package renamed with package.json\", function (done) {\n        ExtensionsDomain._cmdInstall(missingPackageJSON, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(fs.existsSync(result.installedTo)).toBe(true);\n            var legacyDirectory = result.installedTo;\n            ExtensionsDomain._cmdInstall(missingPackageJSONRenamed, installDirectory, standardOptions, function (err, result) {\n                expect(err).toBeNull();\n                expect(result.installationStatus).toBe(\"NEEDS_UPDATE\");\n                expect(result.name).toBe(\"missing-package-json\");\n                ExtensionsDomain._cmdUpdate(missingPackageJSONRenamed, installDirectory, standardOptions, function (err, result) {\n                    expect(err).toBeNull();\n                    expect(result.installationStatus).toBe(\"INSTALLED\");\n                    expect(result.name).toBe(\"renamed-in-package-json\");\n                    expect(fs.existsSync(legacyDirectory)).toBe(false);\n                    done();\n                });\n            });\n        });\n    });\n\n    it(\"should strip out symlinks in the zipfile\", function (done) {\n        ExtensionsDomain._cmdInstall(withSymlink, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            expect(fs.existsSync(result.installedTo)).toBe(true);\n            expect(fs.existsSync(path.join(result.installedTo, \"bin\", \"foo\"))).toBe(false);\n            done();\n        });\n    });\n    \n    it(\"should download npm dependencies when present\", function (done) {\n        ExtensionsDomain._cmdInstall(withNpmDependencies, installDirectory, standardOptions, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            expect(fs.existsSync(result.installedTo)).toBe(true);\n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\"))).toBe(true);\n            \n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\", \"lodash\"))).toBe(true);\n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\", \"lodash\", \"package.json\"))).toBe(true);\n            var packageInfo = JSON.parse(fs.readFileSync(path.join(result.installedTo, \"node_modules\", \"lodash\", \"package.json\")));\n            expect(packageInfo.version.slice(0,2)).toBe(\"3.\");\n            \n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\", \"moment\"))).toBe(true);\n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\", \"moment\", \"package.json\"))).toBe(true);\n            packageInfo = JSON.parse(fs.readFileSync(path.join(result.installedTo, \"node_modules\", \"moment\", \"package.json\")));\n            expect(packageInfo.version.slice(0,4)).toBe(\"2.5.\");\n            \n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\", \"underscore\"))).toBe(true);\n            expect(fs.existsSync(path.join(result.installedTo, \"node_modules\", \"underscore\", \"package.json\"))).toBe(true);\n            packageInfo = JSON.parse(fs.readFileSync(path.join(result.installedTo, \"node_modules\", \"underscore\", \"package.json\")));\n            expect(packageInfo.version).toBe(\"1.0.4\");\n            \n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensibility/node/spec/Validation.spec.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n/*global expect, describe, it, afterEach */\n\n\"use strict\";\n\nvar rewire           = require(\"rewire\"),\n    packageValidator = rewire(\"../package-validator\"),\n    path             = require(\"path\"),\n    temp             = require(\"temp\");\n\nvar testFilesDirectory = path.join(path.dirname(module.filename),\n                                    \"..\",   // node\n                                    \"..\",   // extensibility\n                                    \"..\",   // src\n                                    \"..\",   // brackets\n                                    \"test\",\n                                    \"spec\",\n                                    \"extension-test-files\");\n\nvar basicValidExtension    = path.join(testFilesDirectory, \"basic-valid-extension.zip\"),\n    basicValidExtension2   = path.join(testFilesDirectory, \"basic-valid-extension-2.0.zip\"),\n    basicValidTheme        = path.join(testFilesDirectory, \"basic-valid-theme-1.0.zip\"),\n    missingPackageJSON     = path.join(testFilesDirectory, \"missing-package-json.zip\"),\n    invalidJSON            = path.join(testFilesDirectory, \"invalid-json.zip\"),\n    invalidZip             = path.join(testFilesDirectory, \"invalid-zip-file.zip\"),\n    missingNameVersion     = path.join(testFilesDirectory, \"missing-name-version.zip\"),\n    missingMain            = path.join(testFilesDirectory, \"missing-main.zip\"),\n    oneLevelDown           = path.join(testFilesDirectory, \"one-level-extension-master.zip\"),\n    bogusTopDir            = path.join(testFilesDirectory, \"bogus-top-dir.zip\"),\n    badname                = path.join(testFilesDirectory, \"badname.zip\"),\n    mainInDirectory        = path.join(testFilesDirectory, \"main-in-directory.zip\"),\n    invalidVersion         = path.join(testFilesDirectory, \"invalid-version.zip\"),\n    invalidBracketsVersion = path.join(testFilesDirectory, \"invalid-brackets-version.zip\"),\n    ignoredFolder          = path.join(testFilesDirectory, \"has-macosx.zip\");\n\ndescribe(\"Package Validation\", function () {\n\n    afterEach(function () {\n        temp.cleanup();\n    });\n\n    it(\"should handle a good package\", function (done) {\n        packageValidator.validate(basicValidExtension, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.extractDir).toBeDefined();\n            expect(result.errors.length).toEqual(0);\n            var metadata = result.metadata;\n            expect(metadata.name).toEqual(\"basic-valid-extension\");\n            expect(metadata.version).toEqual(\"1.0.0\");\n            expect(metadata.title).toEqual(\"Basic Valid Extension\");\n            expect(metadata.author.name).toEqual(\"Alfred Einstein\");\n            expect(metadata.author.email).toEqual(\"alfred_not_albert@thoseeinsteins.org\");\n            expect(metadata.author.url).toBeUndefined();\n            done();\n        });\n    });\n\n    it(\"should NOT complain about missing package.json\", function (done) {\n        packageValidator.validate(missingPackageJSON, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(0);\n            expect(result.metadata).toBeNull();\n            done();\n        });\n    });\n\n    it(\"should complain about missing package.json if you tell it to\", function (done) {\n        packageValidator.validate(missingPackageJSON, {\n            requirePackageJSON: true\n        }, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"MISSING_PACKAGE_JSON\");\n            done();\n        });\n    });\n\n    it(\"should complain about illegal path\", function (done) {\n        packageValidator.validate(path.join(testFilesDirectory, \"NO_FILE_HERE\"), {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"NOT_FOUND_ERR\");\n            expect(result.metadata).toBeUndefined();\n            done();\n        });\n    });\n\n    it(\"should complain about invalid JSON\", function (done) {\n        packageValidator.validate(invalidJSON, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"INVALID_PACKAGE_JSON\");\n            expect(errors[0][1]).toEqual(\"SyntaxError: Unexpected token I\");\n            expect(errors[0][2]).toEqual(invalidJSON);\n            expect(result.metadata).toBeUndefined();\n            done();\n        });\n    });\n\n    it(\"should complain about an invalid zip file\", function (done) {\n        packageValidator.validate(invalidZip, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"INVALID_ZIP_FILE\");\n            done();\n        });\n    });\n\n    it(\"should require name and version in the metadata\", function (done) {\n        packageValidator.validate(missingNameVersion, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(2);\n            expect(errors[0][0]).toEqual(\"MISSING_PACKAGE_NAME\");\n            expect(errors[1][0]).toEqual(\"MISSING_PACKAGE_VERSION\");\n            done();\n        });\n    });\n\n    it(\"should validate the version number\", function (done) {\n        packageValidator.validate(invalidVersion, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"INVALID_VERSION_NUMBER\");\n            expect(errors[0][1]).toEqual(\"NOT A VERSION\");\n            done();\n        });\n    });\n\n    it(\"should require a main.js in the zip file\", function (done) {\n        packageValidator.validate(missingMain, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"MISSING_MAIN\");\n            done();\n        });\n    });\n\n    it(\"should NOT require a main.js in the zip file for a theme\", function (done) {\n        packageValidator.validate(basicValidTheme, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            expect(result.metadata.theme).toBeDefined();\n            done();\n        });\n    });\n\n    it(\"should determine the common prefix if there is one\", function (done) {\n        packageValidator.validate(oneLevelDown, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            expect(result.metadata.name).toEqual(\"one-level-extension\");\n            expect(result.commonPrefix).toEqual(\"one-level-extension-master\");\n            expect(result.metadata.author.name).toEqual(\"A Person\");\n            done();\n        });\n    });\n\n    it(\"should not be fooled by bogus top directories\", function (done) {\n        packageValidator.validate(bogusTopDir, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            expect(result.metadata.name).toEqual(\"bogus-top-dir\");\n            expect(result.commonPrefix).toEqual(\"\");\n            done();\n        });\n    });\n\n    it(\"should not allow names that contain disallowed characters\", function (done) {\n        packageValidator.validate(badname, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(1);\n            expect(result.errors[0][0]).toEqual(\"BAD_PACKAGE_NAME\");\n            done();\n        });\n    });\n\n    it(\"should complain about files that don't have main in the top dir\", function (done) {\n        packageValidator.validate(mainInDirectory, {}, function (err, result) {\n            expect(err).toBeNull();\n            var errors = result.errors;\n            expect(errors.length).toEqual(1);\n            expect(errors[0][0]).toEqual(\"MISSING_MAIN\");\n            done();\n        });\n    });\n\n    it(\"should handle a variety of person forms\", function () {\n        var parse = packageValidator._parsePersonString;\n        expect(parse(\"A Person\")).toEqual({\n            name: \"A Person\"\n        });\n        expect(parse({\n            name: \"A Person\"\n        })).toEqual({\n            name: \"A Person\"\n        });\n        expect(parse(\"A Person (http://foo.bar)\")).toEqual({\n            name: \"A Person\",\n            url: \"http://foo.bar\"\n        });\n        expect(parse(\"A Person <foo@bar>\")).toEqual({\n            name: \"A Person\",\n            email: \"foo@bar\"\n        });\n        expect(parse(\"A Person <foo@bar> (http://foo.bar)\")).toEqual({\n            name: \"A Person\",\n            email: \"foo@bar\",\n            url: \"http://foo.bar\"\n        });\n    });\n\n    it(\"should handle contributors\", function (done) {\n        packageValidator.validate(basicValidExtension2, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            var contrib = result.metadata.contributors;\n            expect(contrib.length).toEqual(3);\n            expect(contrib[0]).toEqual({\n                name: \"Johan Einstein\"\n            });\n            expect(contrib[1]).toEqual({\n                name: \"Albert Einstein Jr.\",\n                email: \"not_that_albert@thoseeinsteins.org\"\n            });\n            expect(contrib[2]).toEqual({\n                name: \"Jens Einstein\",\n                email: \"jens@thoseeinsteins.org\"\n            });\n            done();\n        });\n    });\n\n    it(\"should validate the Brackets version\", function (done) {\n        packageValidator.validate(invalidBracketsVersion, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(1);\n            expect(result.errors[0][0]).toEqual(\"INVALID_BRACKETS_VERSION\");\n            expect(result.errors[0][1]).toEqual(\"foo\");\n            done();\n        });\n    });\n\n    it(\"should reject a package with rejected words in title or description\", function (done) {\n        packageValidator.validate(basicValidExtension, {\n            disallowedWords: [\"valid\"]\n        }, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(2);\n            expect(result.errors[0][0]).toEqual(\"DISALLOWED_WORDS\");\n            expect(result.errors[0][1]).toEqual(\"title\");\n            expect(result.errors[0][2]).toEqual(\"valid\");\n            expect(result.errors[1][0]).toEqual(\"DISALLOWED_WORDS\");\n            expect(result.errors[1][1]).toEqual(\"name\");\n            expect(result.errors[1][2]).toEqual(\"valid\");\n            done();\n        });\n    });\n\n    it(\"should only allow certain characters in the name\", function () {\n        var validateName = packageValidator.__get__(\"validateName\");\n        expect(validateName(\"Foo\")).toEqual(false);\n        expect(validateName(\"foo\")).toEqual(true);\n        expect(validateName(\"foo2\")).toEqual(true);\n        expect(validateName(\"foo.bar\")).toEqual(true);\n        expect(validateName(\"foo-bar\")).toEqual(true);\n        expect(validateName(\"foo_bar\")).toEqual(true);\n        expect(validateName(\"foo&bar\")).toEqual(false);\n        expect(validateName(\"foo/bar\")).toEqual(false);\n        expect(validateName(\"..\")).toEqual(false);\n        expect(validateName(\".\")).toEqual(false);\n    });\n\n    it(\"should ignore the __MACOSX folder when looking for a single subfolder\", function (done) {\n        packageValidator.validate(ignoredFolder, {}, function (err, result) {\n            expect(err).toBeNull();\n            expect(result.errors.length).toEqual(0);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensibility/registry_utils.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * N.B.: This file was copied from `lib/registry_utils.js` in `https://github.com/adobe/brackets-registry`.\n * We can't use the exact same file currently because Brackets uses AMD-style modules, so this version has\n * the AMD wrapper added (and is reindented to avoid JSLint complaints).. If changes are made here, the\n * version in the registry app should be kept in sync.\n * In the future, we should have a better mechanism for sharing code between the two.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // From Brackets StringUtils\n    function htmlEscape(str) {\n        return String(str)\n            .replace(/&/g, \"&amp;\")\n            .replace(/\"/g, \"&quot;\")\n            .replace(/'/g, \"&#39;\")\n            .replace(/</g, \"&lt;\")\n            .replace(/>/g, \"&gt;\");\n    }\n\n    /**\n     * Gets the last version from the given object and returns the short form of its date.\n     * Assumes \"this\" is the current template context.\n     * @return {string} The formatted date.\n     */\n    exports.lastVersionDate = function () {\n        var result;\n        if (this.versions && this.versions.length) {\n            result = this.versions[this.versions.length - 1].published;\n            if (result) {\n                result = new Date(result);\n                result = result.toLocaleDateString(brackets.getLocale(), {\n                    \"year\": \"numeric\",\n                    \"month\": \"2-digit\",\n                    \"day\": \"2-digit\"\n                });\n            }\n        }\n        return result || \"\";\n    };\n\n    /**\n     * Returns a more friendly display form of the owner's internal user id.\n     * Assumes \"this\" is the current template context.\n     * @return {string} A display version in the form \"id (service)\".\n     */\n    exports.formatUserId = function () {\n        var friendlyName;\n        if (this.owner) {\n            var nameComponents = this.owner.split(\":\");\n            friendlyName = nameComponents[1];\n        }\n        return friendlyName;\n    };\n\n    /**\n     * Given a registry item, returns a URL that represents its owner's page on the auth service.\n     * Currently only handles GitHub.\n     * Assumes \"this\" is the current template context.\n     * @return {string} A link to that user's page on the service.\n     */\n    exports.ownerLink = function () {\n        var url;\n        if (this.owner) {\n            var nameComponents = this.owner.split(\":\");\n            if (nameComponents[0] === \"github\") {\n                url = \"https://github.com/\" + nameComponents[1];\n            }\n        }\n        return url;\n    };\n\n    /**\n     * Given a registry item, formats the author information, including a link to the owner's\n     * github page (if available) and the author's name from the metadata.\n     */\n    exports.authorInfo = function () {\n        var result = \"\",\n            ownerLink = exports.ownerLink.call(this),\n            userId = exports.formatUserId.call(this);\n        if (this.metadata && this.metadata.author) {\n            result = htmlEscape(this.metadata.author.name || this.metadata.author);\n        } else if (userId) {\n            result = htmlEscape(userId);\n        }\n        if (ownerLink) {\n            result = \"<a href='\" + htmlEscape(ownerLink) + \"' title='\" + htmlEscape(ownerLink) + \"'>\" + result + \"</a>\";\n        }\n        return result;\n    };\n\n    /**\n     * Returns an array of current registry entries, sorted by the publish date of the latest version of each entry.\n     * @param {object} registry The unsorted registry.\n     * @param {string} subkey The subkey to look for the registry metadata in. If unspecified, assumes\n     *     we should look at the top level of the object.\n     * @return {Array} Sorted array of registry entries.\n     */\n    exports.sortRegistry = function (registry, subkey, sortBy) {\n        function getPublishTime(entry) {\n            if (entry.versions) {\n                return new Date(entry.versions[entry.versions.length - 1].published).getTime();\n            }\n\n            return Number.NEGATIVE_INFINITY;\n        }\n\n        var sortedEntries = [];\n\n        // Sort the registry by last published date (newest first).\n        Object.keys(registry).forEach(function (key) {\n            sortedEntries.push(registry[key]);\n        });\n        sortedEntries.sort(function (entry1, entry2) {\n            if (sortBy !== \"publishedDate\") {\n                if (entry1.registryInfo && entry2.registryInfo) {\n                    return entry2.registryInfo.totalDownloads - entry1.registryInfo.totalDownloads;\n                } else {\n                    return Number.NEGATIVE_INFINITY;\n                }\n            } else {\n                return getPublishTime((subkey && entry2[subkey]) || entry2) -\n                    getPublishTime((subkey && entry1[subkey]) || entry1);\n            }\n        });\n\n        return sortedEntries;\n    };\n});\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/MessageIds.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    exports.DOWNLOAD_INSTALLER              = \"node.downloadInstaller\";\n    exports.PERFORM_CLEANUP                 = \"node.performCleanup\";\n    exports.VALIDATE_INSTALLER              = \"node.validateInstaller\";\n    exports.INITIALIZE_STATE                = \"node.initializeState\";\n    exports.CHECK_INSTALLER_STATUS          = \"node.checkInstallerStatus\";\n    exports.REMOVE_FROM_REQUESTERS          = \"node.removeFromRequesters\";\n    exports.SHOW_STATUS_INFO                = \"brackets.showStatusInfo\";\n    exports.NOTIFY_DOWNLOAD_SUCCESS         = \"brackets.notifyDownloadSuccess\";\n    exports.SHOW_ERROR_MESSAGE              = \"brackets.showErrorMessage\";\n    exports.NOTIFY_DOWNLOAD_FAILURE         = \"brackets.notifyDownloadFailure\";\n    exports.NOTIFY_SAFE_TO_DOWNLOAD         = \"brackets.notifySafeToDownload\";\n    exports.NOTIFY_INITIALIZATION_COMPLETE  = \"brackets.notifyinitializationComplete\";\n    exports.NOTIFY_VALIDATION_STATUS        = \"brackets.notifyvalidationStatus\";\n    exports.NOTIFY_INSTALLATION_STATUS      = \"brackets.notifyInstallationStatus\";\n    exports.NODE_DOMAIN_INITIALIZED         = \"brackets.nodeDomainInitialized\";\n    exports.REGISTER_BRACKETS_FUNCTIONS     = \"brackets.registerBracketsFunctions\";\n});\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/StateHandler.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileSystem = brackets.getModule(\"filesystem/FileSystem\"),\n        FileUtils = brackets.getModule(\"file/FileUtils\");\n\n    var FILE_NOT_FOUND = 0,\n        FILE_NOT_READ = 1,\n        FILE_PARSE_EXCEPTION = 2,\n        FILE_READ_FAIL = 3;\n\n    /**\n     * @constructor\n     * Creates a StateHandler object for a JSON file. It maintains the following :\n     * path - path to the JSON file,\n     * state - parsed content of the file\n     * @param {string} path - path to the JSON file\n     */\n    var StateHandler = function (path) {\n        this.path = path;\n        this.state = null;\n    };\n\n    /**\n     * Checks if the file exists\n     * @returns {$.Deferred} - a jquery deferred promise,\n     *                       that is resolved with existence or non-existence\n     *                       of json file.\n     */\n    StateHandler.prototype.exists = function () {\n        var result = $.Deferred(),\n            _file = FileSystem.getFileForPath(this.path);\n\n        _file.exists(function (err, exists) {\n            if (err) {\n                result.reject();\n            } else if (exists) {\n                result.resolve();\n            } else {\n                result.reject();\n            }\n        });\n\n        return result.promise();\n    };\n\n    /**\n     * Parses the JSON file, and maintains a state for the parsed data\n     * @returns {$.Deferred} - a jquery deferred promise,\n     *                       that is resolved with a parsing success or failure\n     */\n    StateHandler.prototype.parse = function () {\n        var result = $.Deferred(),\n            _file = FileSystem.getFileForPath(this.path);\n        var self = this;\n\n        this.exists()\n            .done(function () {\n                FileUtils.readAsText(_file)\n                    .done(function (text) {\n                        try {\n                            if (text) {\n                                self.state = JSON.parse(text);\n                                result.resolve();\n                            } else {\n                                result.reject(FILE_READ_FAIL);\n                            }\n                        } catch (error) {\n                            result.reject(FILE_PARSE_EXCEPTION);\n                        }\n                    })\n                    .fail(function () {\n                        result.reject(FILE_NOT_READ);\n                    });\n\n            })\n            .fail(function () {\n                result.reject(FILE_NOT_FOUND);\n            });\n\n        return result.promise();\n    };\n\n    /**\n     * Sets the value of a key in a json file.\n     * @param   {string} key  - key for which the value is to be set\n     * @param   {string} value - the value to be set for the given key\n     * @returns {$.Deferred} - a jquery deferred promise, that is resolved with a write success or failure\n     */\n    StateHandler.prototype.set = function (key, value) {\n        this.state = this.state || {};\n        this.state[key] = value;\n\n        return this.write(true);\n    };\n\n    /**\n     * Gets the value for a given key, from the in-memory state maintained for a json file.\n     * @param   {string} key - key for which value is to be retrieved\n     * @returns {string} value for the given key\n     */\n    StateHandler.prototype.get = function (key) {\n        var retval = null;\n\n        if (this.state && this.state[key] !== undefined) {\n            retval = this.state[key];\n        }\n\n        return retval;\n    };\n\n     /**\n     * Reads the value of a key from a json file.\n     * @param   {string} key - key for which the value is to be read\n     * @returns {$.Deferred} - a jquery deferred promise, that is resolved\n     *                       with the read value or read failure.\n     */\n    StateHandler.prototype.refresh = function () {\n        var result = $.Deferred(),\n            self = this;\n\n        self.parse()\n            .done(function () {\n                if (self.state) {\n                    result.resolve();\n                } else {\n                    result.reject();\n                    console.warn(\"AutoUpdate : updateHelper.json could not be read\");\n                }\n            })\n            .fail(function (error) {\n                result.reject();\n                console.error(\"AutoUpdate : updateHelper.json could not be parsed\", error);\n            });\n\n        return result.promise();\n    };\n\n    /**\n     * Performs the write of JSON object to a file.\n     * @param   {string} filepath - path to JSON file\n     * @param   {object} json  - JSON object to write\n     * @returns {$.Deferred} - a jquery deferred promise,\n     *                       that is resolved with the write success or failure\n     */\n    function _write(filePath, json) {\n        var result = $.Deferred(),\n            _file = FileSystem.getFileForPath(filePath);\n\n        if (_file) {\n\n            var content = JSON.stringify(json);\n            FileUtils.writeText(_file, content, true)\n                .done(function () {\n                    result.resolve();\n                })\n                .fail(function (err) {\n                    result.reject();\n                });\n\n        } else {\n            result.reject();\n        }\n\n        return result.promise();\n    }\n    /**\n     * Writes content into a json file\n     * @param   {boolean} overwrite  - true if file is to be overwritten, false otherwise\n     * @param   {object} [content=this.state] - content to be written into the json file.\n     * @returns {$.Deferred} - a jquery deferred promise, that is resolved with a write success or failure\n     */\n    StateHandler.prototype.write = function (overwrite) {\n        var result = $.Deferred(),\n            self = this;\n\n        function writePromise(path, contentToWrite) {\n            _write(path, contentToWrite)\n                .done(function () {\n                    result.resolve();\n                })\n                .fail(function (err) {\n                    result.reject();\n                });\n        }\n\n        var content = self.state;\n        if (overwrite) {\n            writePromise(self.path, content);\n        } else {\n            //check for existence\n            self.exists()\n                .fail(function () {\n                    writePromise(self.path, content);\n                }).done(function () {\n                    result.reject();\n                });\n        }\n\n        return result.promise();\n    };\n\n    /**\n     * Resets the content of the in-memory state\n     */\n    StateHandler.prototype.reset = function () {\n        this.state = null;\n    };\n\n    exports.StateHandler = StateHandler;\n    exports.MessageKeys = {\n        FILE_NOT_FOUND: FILE_NOT_FOUND,\n        FILE_NOT_READ: FILE_NOT_READ,\n        FILE_PARSE_EXCEPTION: FILE_PARSE_EXCEPTION,\n        FILE_READ_FAIL: FILE_READ_FAIL\n    };\n});\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/UpdateInfoBar.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var MainViewManager     = brackets.getModule(\"view/MainViewManager\"),\n        Mustache            = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        EventDispatcher     = brackets.getModule(\"utils/EventDispatcher\"),\n        UpdateBarHtml       = require(\"text!htmlContent/updateBar.html\"),\n        Strings             = brackets.getModule(\"strings\"),\n        _                  =  brackets.getModule(\"thirdparty/lodash\");\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    /** Event triggered when Restart button is clicked on the update bar\n    */\n    var RESTART_BTN_CLICKED = \"restartBtnClicked\";\n\n    /** Event triggered when Later button is clicked on the update bar\n    */\n    var LATER_BTN_CLICKED = \"laterBtnClicked\";\n\n    // Key handlers for buttons in UI\n    var SPACE_KEY = 32, // keycode for space key\n        ESC_KEY   = 27; // keycode for escape key\n\n    /**\n     * Generates the json to be used by Mustache for rendering\n     * @param   {object}   msgObj - json object containing message information to be displayed\n     * @returns {object} - the generated json object\n     */\n    function generateJsonForMustache(msgObj) {\n        var msgJsonObj = {};\n        if (msgObj.type) {\n            msgJsonObj.type = \"'\" + msgObj.type + \"'\";\n        }\n        msgJsonObj.title = msgObj.title;\n        msgJsonObj.description = msgObj.description;\n        if (msgObj.needButtons) {\n            msgJsonObj.buttons = [{\n                \"id\": \"restart\",\n                \"value\": Strings.RESTART_BUTTON,\n                \"tIndex\": \"'0'\"\n            }, {\n                \"id\": \"later\",\n                \"value\": Strings.LATER_BUTTON,\n                \"tIndex\": \"'0'\"\n            }];\n            msgJsonObj.needButtons = msgObj.needButtons;\n        }\n        return msgJsonObj;\n    }\n\n    /**\n     * Removes and cleans up the update bar from DOM\n     */\n    function cleanUpdateBar() {\n        var $updateBar = $('#update-bar');\n        if ($updateBar.length > 0) {\n            $updateBar.remove();\n        }\n        $(window.document).off(\"keydown.AutoUpdate\");\n        $(window).off('resize.AutoUpdateBar');\n    }\n\n    /**\n     * Displays the Update Bar UI\n     * @param   {object} msgObj - json object containing message info to be displayed\n     *\n     */\n    function showUpdateBar(msgObj) {\n        var jsonToMustache = generateJsonForMustache(msgObj),\n            $updateBarElement = $(Mustache.render(UpdateBarHtml, jsonToMustache));\n\n        cleanUpdateBar(); //Remove an already existing update bar, if any\n        $updateBarElement.prependTo(\".content\");\n\n        var $updateBar = $('#update-bar'),\n            $updateContent = $updateBar.find('#update-content'),\n            $contentContainer = $updateBar.find('#content-container'),\n            $buttonContainer = $updateBar.find('#button-container'),\n            $iconContainer = $updateBar.find('#icon-container'),\n            $closeIconContainer = $updateBar.find('#close-icon-container'),\n            $heading = $updateBar.find('#heading'),\n            $description = $updateBar.find('#description'),\n            $restart = $updateBar.find('#update-btn-restart'),\n            $later = $updateBar.find('#update-btn-later'),\n            $closeIcon = $updateBar.find('#close-icon');\n\n        if ($updateContent.length > 0) {\n            if ($updateContent[0].scrollWidth > $updateContent.innerWidth()) {\n            //Text has over-flown, show the update content as tooltip message\n                if ($contentContainer.length > 0 &&\n                        $heading.length > 0 &&\n                        $description.length > 0) {\n                    $contentContainer.attr(\"title\", $heading.text() + $description.text());\n                }\n            }\n        }\n        // Content Container Width between Icon Container and Button Container or Close Icon Container\n        // will be assigned when window will be rezied.\n        var resizeContentContainer = function () {\n            if($updateContent.length > 0 && $contentContainer.length > 0 && $updateBar.length > 0) {\n                var newWidth = $updateBar.outerWidth() - 38;\n                if($buttonContainer.length > 0) {\n                    newWidth = newWidth- $buttonContainer.outerWidth();\n                }\n                if($iconContainer.length > 0) {\n                    newWidth = newWidth - $iconContainer.outerWidth();\n                }\n                if($closeIconContainer.length > 0) {\n                    newWidth = newWidth - $closeIconContainer.outerWidth();\n                }\n\n                $contentContainer.css({\n                    \"maxWidth\": newWidth\n                });\n            }\n        };\n\n        resizeContentContainer();\n        $(window).on('resize.AutoUpdateBar', _.debounce(resizeContentContainer, 150));\n\n        //Event handlers on the Update Bar\n\n        // Click and key handlers on Restart button\n        if ($restart.length > 0) {\n            $restart.click(function () {\n                cleanUpdateBar();\n                exports.trigger(exports.RESTART_BTN_CLICKED);\n            });\n\n            $restart.keyup(function (event) {\n                if (event.which === SPACE_KEY) {\n                    $restart.trigger('click');\n                }\n            });\n        }\n\n        // Click and key handlers on Later button\n        if ($later.length > 0) {\n            $later.click(function () {\n                cleanUpdateBar();\n                MainViewManager.focusActivePane();\n                exports.trigger(exports.LATER_BTN_CLICKED);\n            });\n\n            $later.keyup(function (event) {\n                if (event.which === SPACE_KEY) {\n                    $later.trigger('click');\n                }\n            });\n        }\n\n        // Click and key handlers on Close button\n        if ($closeIcon.length > 0) {\n            $closeIcon.click(function () {\n                cleanUpdateBar();\n                MainViewManager.focusActivePane();\n            });\n\n            $closeIcon.keyup(function (event) {\n                if (event.which === SPACE_KEY) {\n                    $closeIcon.trigger('click');\n                }\n            });\n        }\n        $(window.document).on(\"keydown.AutoUpdate\", function (event) {\n            var code = event.which;\n            if (code === ESC_KEY) {\n                // Keyboard input of Esc key on Update Bar dismisses and removes the bar\n                cleanUpdateBar();\n                MainViewManager.focusActivePane();\n                event.stopImmediatePropagation();\n            }\n        });\n    }\n    exports.showUpdateBar = showUpdateBar;\n    exports.RESTART_BTN_CLICKED = RESTART_BTN_CLICKED;\n    exports.LATER_BTN_CLICKED = LATER_BTN_CLICKED;\n});\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/UpdateStatus.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var UpdateStatusHtml = require(\"text!htmlContent/updateStatus.html\"),\n        ExtensionUtils   = brackets.getModule(\"utils/ExtensionUtils\"),\n        Mustache         = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        Strings          = brackets.getModule(\"strings\"),\n        StringUtils      = brackets.getModule(\"utils/StringUtils\");\n\n    ExtensionUtils.loadStyleSheet(module, \"styles/styles.css\");\n\n    /**\n     * Cleans up status information from Status Bar\n     */\n    function cleanUpdateStatus() {\n        $('#update-status').remove();\n    }\n\n    /**\n     * Displays the status information on Status Bar\n     * @param {string} id - the id of string to display\n     */\n    function showUpdateStatus(id) {\n        cleanUpdateStatus();\n\n        var $updateStatus = $(Mustache.render(UpdateStatusHtml, {\"Strings\": Strings}));\n        $updateStatus.appendTo('#status-bar');\n        if(id === \"initial-download\") {\n            var valStr = StringUtils.format(Strings.NUMBER_WITH_PERCENTAGE, 0);\n            $('#update-status #' + id + ' #' + 'percent').text(valStr);\n        }\n        $('#update-status #' + id).show();\n    }\n\n    /**\n     * Modifies the status information on Status Bar\n     * @param {object} statusObj - json containing status info - {\n     *                           target - id of string to modify,\n     *                           spans - array of objects of type - {\n     *                           id - id of span for modifiable substring,\n     *                           val - the new value to modifiable substring }\n     *                           }\n     */\n    function modifyUpdateStatus(statusObj) {\n        statusObj.spans.forEach(function (span) {\n            var valStr = span.val;\n            if(span.id === \"percent\") {\n                valStr = StringUtils.format(Strings.NUMBER_WITH_PERCENTAGE, span.val.split('%')[0]);\n            }\n            $('#update-status #' + statusObj.target + ' #' + span.id).text(valStr);\n        });\n    }\n\n    /**\n     * Displays the progress bar on Status bar, while the download is in progress\n     * @param {object} statusObj - json containing status info - {\n     *                           target - id of string to modify,\n     *                           spans - array of objects of type - {\n     *                           id - id of span for modifiable substring,\n     *                           val - the new value to modifiable substring }\n     *                           }\n     */\n    function displayProgress(statusObj) {\n        statusObj.spans.forEach(function (span) {\n            if (span.id === 'percent') {\n                var bgColor = $('#status-bar').css('backgroundColor'),\n                    bgval = 'linear-gradient(to right, #1474BF ' + span.val + ', ' + bgColor + ' 0%';\n                $('#update-status').css('background', bgval);\n            }\n        });\n\n    }\n\n    exports.showUpdateStatus = showUpdateStatus;\n    exports.modifyUpdateStatus = modifyUpdateStatus;\n    exports.cleanUpdateStatus = cleanUpdateStatus;\n    exports.displayProgress = displayProgress;\n});\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/htmlContent/updateBar.html",
    "content": "<div id=\"update-bar\" {{#type}}class={{{type}}}{{/type}} tabindex=\"0\">\n    <div id=\"icon-container\">\n        <svg id=\"update-icon\"> </svg>\n    </div>\n    <div id=\"content-container\">\n        <p id=\"update-content\"><span id=\"heading\">{{title}}</span>&nbsp;&nbsp;<span id=\"description\">{{{description}}}</span></p>\n    </div>\n    {{#needButtons}}\n    <div id=\"button-container\">\n        {{#buttons}}\n        <button type=\"button\" id=\"update-btn-{{id}}\" class=\"update-btn\" {{#tIndex}}tabIndex={{{tIndex}}}{{/tIndex}}>{{value}}</button>\n        {{/buttons}}\n    </div>\n    {{/needButtons}}\n    {{^buttons}}\n    <div id=\"close-icon-container\">\n        <button type=\"button\" id=\"close-icon\" tabIndex=\"0\">&times;</button>\n    </div>\n    {{/buttons}}\n</div>"
  },
  {
    "path": "src/extensions/default/AutoUpdate/htmlContent/updateStatus.html",
    "content": "<div id=\"update-status\">\n    <p id=\"initial-download\">{{Strings.INITIAL_DOWNLOAD}}<span id=\"percent\"></span></p>\n    <p id=\"retry-download\">{{Strings.RETRY_DOWNLOAD}}<span id=\"attempt\">1/5</span></p>\n    <p id=\"validating-installer\">{{Strings.VALIDATING_INSTALLER}}</p>\n</div>\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/main.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n/* eslint-disable indent */\n/* eslint-disable max-len */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        ProjectManager          = brackets.getModule(\"project/ProjectManager\"),\n        Commands                = brackets.getModule(\"command/Commands\"),\n        AppInit                 = brackets.getModule(\"utils/AppInit\"),\n        UpdateNotification      = brackets.getModule(\"utils/UpdateNotification\"),\n        DocumentCommandHandlers = brackets.getModule(\"document/DocumentCommandHandlers\"),\n        NodeDomain              = brackets.getModule(\"utils/NodeDomain\"),\n        FileSystem              = brackets.getModule(\"filesystem/FileSystem\"),\n        PreferencesManager      = brackets.getModule(\"preferences/PreferencesManager\"),\n        FileUtils               = brackets.getModule(\"file/FileUtils\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        HealthLogger            = brackets.getModule(\"utils/HealthLogger\"),\n        StateHandlerModule      = require(\"StateHandler\"),\n        MessageIds              = require(\"MessageIds\"),\n        UpdateStatus            = require(\"UpdateStatus\"),\n        UpdateInfoBar           = require(\"UpdateInfoBar\");\n\n\n    var _modulePath = FileUtils.getNativeModuleDirectoryPath(module),\n        _nodePath = \"node/AutoUpdateDomain\",\n        _domainPath = [_modulePath, _nodePath].join(\"/\"),\n        updateDomain,\n        domainID;\n\n    var appSupportDirectory = brackets.app.getApplicationSupportDirectory(),\n        updateDir = appSupportDirectory + '/updateTemp',\n        updateJsonPath = updateDir + '/' + 'updateHelper.json';\n\n    var StateHandler = StateHandlerModule.StateHandler,\n        StateHandlerMessages = StateHandlerModule.MessageKeys;\n\n    var updateJsonHandler;\n\n    var MAX_DOWNLOAD_ATTEMPTS = 6,\n        downloadAttemptsRemaining;\n\n\t// Below Strings are to identify an AutoUpdate Event.\n    var autoUpdateEventNames = {\n        AUTOUPDATE_DOWNLOAD_START: \"DownloadStarted\",\n        AUTOUPDATE_DOWNLOAD_COMPLETED: \"DownloadCompleted\",\n        AUTOUPDATE_DOWNLOAD_FAILED: \"DownloadFailed\",\n        AUTOUPDATE_DOWNLOAD_COMPLETE_USER_CLICK_RESTART: \"DownloadCompletedAndUserClickedRestart\",\n        AUTOUPDATE_DOWNLOAD_COMPLETE_USER_CLICK_LATER: \"DownloadCompletedAndUserClickedLater\",\n        AUTOUPDATE_DOWNLOADCOMPLETE_UPDATE_BAR_RENDERED: \"DownloadCompleteUpdateBarRendered\",\n        AUTOUPDATE_INSTALLATION_FAILED: \"InstallationFailed\",\n        AUTOUPDATE_INSTALLATION_SUCCESS: \"InstallationSuccess\",\n        AUTOUPDATE_CLEANUP_FAILED: \"AutoUpdateCleanUpFailed\"\n    };\n\n    // function map for brackets functions\n    var functionMap = {};\n\n    var _updateParams;\n\n    //Namespacing the event\n    var APP_QUIT_CANCELLED = DocumentCommandHandlers.APP_QUIT_CANCELLED + \".auto-update\";\n\n    var _nodeErrorMessages = {\n        UPDATEDIR_READ_FAILED: 0,\n        UPDATEDIR_CLEAN_FAILED: 1,\n        CHECKSUM_DID_NOT_MATCH: 2,\n        INSTALLER_NOT_FOUND: 3,\n        DOWNLOAD_ERROR: 4,\n        NETWORK_SLOW_OR_DISCONNECTED: 5\n    };\n\n    var updateProgressKey = \"autoUpdateInProgress\",\n        isAutoUpdateInitiated = false;\n\n    /**\n     * Checks if an auto update session is currently in progress\n     * @returns {boolean} - true if an auto update session is currently in progress, false otherwise\n     */\n    function checkIfAnotherSessionInProgress() {\n        var result = $.Deferred();\n        if(updateJsonHandler) {\n            var state = updateJsonHandler.state;\n\n            updateJsonHandler.refresh()\n                .done(function() {\n                    var val = updateJsonHandler.get(updateProgressKey);\n                    if(val !== null) {\n                        result.resolve(val);\n                    } else {\n                        result.reject();\n                    }\n                })\n                .fail(function() {\n                    updateJsonHandler.state = state;\n                    result.reject();\n                });\n        }\n        return result.promise();\n    }\n\n    /**\n     * Checks if auto update preference is enabled or disabled\n     * @private\n     * @returns {boolean} - true if preference enabled, false otherwise\n     */\n    function _isAutoUpdateEnabled() {\n        return (PreferencesManager.get(\"autoUpdate.AutoUpdate\") !== false);\n    }\n\n    /**\n     * Receives messages from node\n     * @param {object} event  - event received from node\n     * @param {object}   msgObj - json containing - {\n     *                          fn - function to execute on Brackets side\n     *                          args - arguments to the above function\n     *                          requester - ID of the current requester domain\n     */\n    function receiveMessageFromNode(event, msgObj) {\n        if (functionMap[msgObj.fn]) {\n            if(domainID === msgObj.requester) {\n                functionMap[msgObj.fn].apply(null, msgObj.args);\n            }\n        }\n    }\n\n     /*\n     * Checks if Brackets version got updated\n     * @returns {boolean}  true if version updated, false otherwise\n     */\n    function checkIfVersionUpdated() {\n\n        var latestBuildNumber = updateJsonHandler.get(\"latestBuildNumber\"),\n            currentBuildNumber = Number(/-([0-9]+)/.exec(brackets.metadata.version)[1]);\n\n        return latestBuildNumber === currentBuildNumber;\n    }\n\n\n     /**\n     * Gets the arguments to a function in an array\n     * @param   {object} args - the arguments object\n     * @returns {Array}   - array of actual arguments\n     */\n    function getFunctionArgs(args) {\n        if (args.length > 1) {\n            var fnArgs = new Array(args.length - 1),\n                i;\n\n            for (i = 1; i < args.length; ++i) {\n                fnArgs[i - 1] = args[i];\n            }\n            return fnArgs;\n        }\n        return [];\n    }\n\n\n    /**\n     * Posts messages to node\n     * @param {string} messageId - Message to be passed\n     */\n    function postMessageToNode(messageId) {\n        var msg = {\n            fn: messageId,\n            args: getFunctionArgs(arguments),\n            requester: domainID\n        };\n        updateDomain.exec('data', msg);\n    }\n\n     /**\n     * Checks Install failure scenarios\n     */\n    function checkInstallationStatus() {\n        var searchParams = {\n                \"updateDir\": updateDir,\n                \"installErrorStr\": [\"ERROR:\"],\n                \"bracketsErrorStr\": [\"ERROR:\"],\n                \"encoding\": \"utf8\"\n            },\n            // Below are the possible Windows Installer error strings, which will be searched for in the installer logs to track failures.\n            winInstallErrorStrArr = [\n                \"Installation success or error status\",\n                \"Reconfiguration success or error status\"\n            ];\n        if (brackets.platform === \"win\") {\n            searchParams.installErrorStr = winInstallErrorStrArr;\n            searchParams.encoding = \"utf16le\";\n        }\n        postMessageToNode(MessageIds.CHECK_INSTALLER_STATUS, searchParams);\n    }\n\n     /**\n     * Checks and handles the update success and failure scenarios\n     */\n    function checkUpdateStatus() {\n        var filesToCache = ['.logs'],\n            downloadCompleted = updateJsonHandler.get(\"downloadCompleted\"),\n            updateInitiatedInPrevSession = updateJsonHandler.get(\"updateInitiatedInPrevSession\");\n\n        if (downloadCompleted && updateInitiatedInPrevSession) {\n            var isNewVersion = checkIfVersionUpdated();\n            updateJsonHandler.reset();\n            if (isNewVersion) {\n                // We get here if the update was successful\n                UpdateInfoBar.showUpdateBar({\n                    type: \"success\",\n                    title: Strings.UPDATE_SUCCESSFUL,\n                    description: \"\"\n                });\n                HealthLogger.sendAnalyticsData(\n                    autoUpdateEventNames.AUTOUPDATE_INSTALLATION_SUCCESS,\n                    \"autoUpdate\",\n                    \"install\",\n                    \"complete\",\n                    \"\"\n                );\n            } else {\n                // We get here if the update started but failed\n                checkInstallationStatus();\n                UpdateInfoBar.showUpdateBar({\n                    type: \"error\",\n                    title: Strings.UPDATE_FAILED,\n                    description: Strings.GO_TO_SITE\n                });\n            }\n        } else if (downloadCompleted && !updateInitiatedInPrevSession) {\n            // We get here if the download was complete and user selected UpdateLater\n            if (brackets.platform === \"mac\") {\n                filesToCache = ['.dmg', '.json'];\n            } else if (brackets.platform === \"win\") {\n                filesToCache = ['.msi', '.json'];\n            }\n        }\n\n        postMessageToNode(MessageIds.PERFORM_CLEANUP, filesToCache);\n    }\n\n\t/**\n     * Send Installer Error Code to Analytics Server\n     */\n\n    function handleInstallationStatus(statusObj) {\n        var errorCode = \"\",\n            errorline = statusObj.installError;\n        if (errorline) {\n            errorCode = errorline.substr(errorline.lastIndexOf(':') + 2, errorline.length);\n        }\n        HealthLogger.sendAnalyticsData(\n            autoUpdateEventNames.AUTOUPDATE_INSTALLATION_FAILED,\n            \"autoUpdate\",\n            \"install\",\n            \"fail\",\n            errorCode\n        );\n    }\n\n\n     /**\n     * Initializes the state of parsed content from updateHelper.json\n     * returns Promise Object Which is resolved when parsing is success\n     * and rejected if parsing is failed.\n     */\n    function initState() {\n        var result = $.Deferred();\n        updateJsonHandler.parse()\n            .done(function() {\n                result.resolve();\n            })\n            .fail(function (code) {\n                var logMsg;\n                switch (code) {\n                case StateHandlerMessages.FILE_NOT_FOUND:\n                    logMsg = \"AutoUpdate : updateHelper.json cannot be parsed, does not exist\";\n                    break;\n                case StateHandlerMessages.FILE_NOT_READ:\n                    logMsg = \"AutoUpdate : updateHelper.json could not be read\";\n                    break;\n                case StateHandlerMessages.FILE_PARSE_EXCEPTION:\n                    logMsg = \"AutoUpdate : updateHelper.json could not be parsed, exception encountered\";\n                    break;\n                case StateHandlerMessages.FILE_READ_FAIL:\n                    logMsg = \"AutoUpdate : updateHelper.json could not be parsed\";\n                    break;\n                }\n                console.log(logMsg);\n                result.reject();\n            });\n        return result.promise();\n    }\n\n\n\n    /**\n     * Sets up the Auto Update environment\n     */\n    function setupAutoUpdate() {\n        updateJsonHandler = new StateHandler(updateJsonPath);\n        updateDomain.on('data', receiveMessageFromNode);\n\n        updateDomain.exec('initNode', {\n            messageIds: MessageIds,\n            updateDir: updateDir,\n            requester: domainID\n        });\n    }\n\n\n    /**\n     * Initializes the state for AutoUpdate process\n     * @returns {$.Deferred} - a jquery promise,\n     *                       that is resolved with success or failure\n     *                       of state initialization\n     */\n    function initializeState() {\n        var result = $.Deferred();\n\n        FileSystem.resolve(updateDir, function (err) {\n            if (!err) {\n                result.resolve();\n            } else {\n                var directory = FileSystem.getDirectoryForPath(updateDir);\n                directory.create(function (error) {\n                    if (error) {\n                        console.error('AutoUpdate : Error in creating update directory in Appdata');\n                        result.reject();\n                    } else {\n                        result.resolve();\n                    }\n                });\n            }\n        });\n\n        return result.promise();\n    }\n\n\n\n    /**\n     * Handles the auto update event, which is triggered when user clicks GetItNow in UpdateNotification dialog\n     * @param {object} updateParams - json object containing update information {\n     *                              installerName - name of the installer\n     *                              downloadURL - download URL\n     *                              latestBuildNumber - build number\n     *                              checksum - checksum }\n     */\n    function initiateAutoUpdate(updateParams) {\n        _updateParams = updateParams;\n        downloadAttemptsRemaining = MAX_DOWNLOAD_ATTEMPTS;\n\n        initializeState()\n            .done(function () {\n\n                 var setUpdateInProgress = function() {\n                    var initNodeFn = function () {\n                        isAutoUpdateInitiated = true;\n                        postMessageToNode(MessageIds.INITIALIZE_STATE, _updateParams);\n                    };\n\n                    if (updateJsonHandler.get('latestBuildNumber') !== _updateParams.latestBuildNumber) {\n                        setUpdateStateInJSON('latestBuildNumber', _updateParams.latestBuildNumber)\n                            .done(initNodeFn);\n                    } else {\n                        initNodeFn();\n                    }\n                };\n\n                checkIfAnotherSessionInProgress()\n                    .done(function(inProgress) {\n                        if(inProgress) {\n                            UpdateInfoBar.showUpdateBar({\n                                type: \"error\",\n                                title: Strings.AUTOUPDATE_ERROR,\n                                description: Strings.AUTOUPDATE_IN_PROGRESS\n                            });\n                        } else {\n                             setUpdateStateInJSON(\"autoUpdateInProgress\", true)\n                                .done(setUpdateInProgress);\n\n                        }\n                    })\n                    .fail(function() {\n                        setUpdateStateInJSON(\"autoUpdateInProgress\", true)\n                            .done(setUpdateInProgress);\n\n                    });\n\n            })\n            .fail(function () {\n                UpdateInfoBar.showUpdateBar({\n                    type: \"error\",\n                    title: Strings.INITIALISATION_FAILED,\n                    description: \"\"\n                });\n            });\n    }\n\n\n     /**\n     * Typical signature of an update entry, with the most frequently used keys\n     * @typedef {Object} Update~Entry\n     * @property {Number} buildNumber - The build number for the update\n     * @property {string} versionString - Version for the update\n     * @property {string} releaseNotesURL - URL for release notes for the update\n     * @property {array} newFeatures - Array of new features in the update\n     * @property {boolean} prerelease - Boolean to distinguish prerelease from a stable release\n     * @property {Object} platforms - JSON object, containing asset info for the update, for each platform\n     *                        Asset info for each platform consists of :\n     *                        @property {string} checksum - checksum of the asset\n     *                        @property {string} downloadURL - download URL of the asset\n     *\n     */\n\n    /**\n     * Handles and processes the update info, required for app auto update\n     * @private\n     * @param {Array} updates - array of {...Update~Entry} update entries\n     */\n    function _updateProcessHandler(updates) {\n\n            if (!updates) {\n                console.warn(\"AutoUpdate : updates information not available.\");\n                return;\n            }\n            var OS = brackets.getPlatformInfo(),\n                checksum,\n                downloadURL,\n                installerName,\n                platforms,\n                latestUpdate;\n\n            latestUpdate = updates[0];\n            platforms = latestUpdate ? latestUpdate.platforms : null;\n\n            if (platforms && platforms[OS]) {\n\n                //If no checksum field is present then we're setting it to 0, just as a safety check,\n                // although ideally this situation should never occur in releases post its introduction.\n                checksum = platforms[OS].checksum ? platforms[OS].checksum : 0,\n                downloadURL = platforms[OS].downloadURL ? platforms[OS].downloadURL : \"\",\n                installerName = downloadURL ? downloadURL.split(\"/\").pop() : \"\";\n\n            } else {\n                // Update not present for current platform\n                return false;\n            }\n\n            if (!checksum || !downloadURL || !installerName) {\n                console.warn(\"AutoUpdate : asset information incorrect for the update\");\n                return false;\n            }\n\n            var updateParams = {\n                downloadURL: downloadURL,\n                installerName: installerName,\n                latestBuildNumber: latestUpdate.buildNumber,\n                checksum: checksum\n            };\n\n\n            //Initiate the auto update, with update params\n            initiateAutoUpdate(updateParams);\n\t    \n\t    //Send a truthy value to ensure caller is informed about successful initialization of auto-update\n\t    return true;\n    }\n\n\n     /**\n     * Unregisters the App Quit event handler\n     */\n    function resetAppQuitHandler() {\n        DocumentCommandHandlers.off(APP_QUIT_CANCELLED);\n    }\n\n\n    /**\n     * Unsets the Auto Update environment\n     */\n    function unsetAutoUpdate() {\n        updateJsonHandler = null;\n        updateDomain.off('data');\n        resetAppQuitHandler();\n    }\n\n\n    /**\n     * Defines preference to enable/disable Auto Update\n     */\n    function setupAutoUpdatePreference() {\n        PreferencesManager.definePreference(\"autoUpdate.AutoUpdate\", \"boolean\", true, {\n            description: Strings.DESCRIPTION_AUTO_UPDATE\n        });\n\n        // Set or unset the auto update, based on preference state change\n        PreferencesManager.on(\"change\", \"autoUpdate.AutoUpdate\", function () {\n            if (_isAutoUpdateEnabled()) {\n                setupAutoUpdate();\n                UpdateNotification.registerUpdateHandler(_updateProcessHandler);\n            } else {\n                unsetAutoUpdate();\n                UpdateNotification.resetToDefaultUpdateHandler();\n            }\n        });\n    }\n\n\n    /**\n     * Creates the Node Domain for Auto Update\n     */\n    function setupAutoUpdateDomain() {\n        updateDomain = new NodeDomain(\"AutoUpdate\", _domainPath);\n    }\n\n\n    /**\n     * Overriding the appReady for Auto update\n     */\n\n    AppInit.appReady(function () {\n\n        // Auto Update is supported on Win and Mac, as of now\n        if (brackets.platform === \"linux\" || !(brackets.app.setUpdateParams)) {\n            return;\n        }\n        setupAutoUpdateDomain();\n\n        //Bail out if update domain could not be created\n        if (!updateDomain) {\n            return;\n        }\n\n        // Check if the update domain is properly initialised\n        updateDomain.promise()\n             .done(function () {\n                setupAutoUpdatePreference();\n                if (_isAutoUpdateEnabled()) {\n                    domainID = (new Date()).getTime().toString();\n                    setupAutoUpdate();\n                    UpdateNotification.registerUpdateHandler(_updateProcessHandler);\n                }\n            })\n             .fail(function (err) {\n                console.error(\"AutoUpdate : node domain could not be initialized.\");\n                return;\n            });\n    });\n\n    /**\n     * Enables/disables the state of \"Auto Update In Progress\" in UpdateHandler.json\n     */\n    function nodeDomainInitialized(reset) {\n        initState()\n            .done(function () {\n                var inProgress = updateJsonHandler.get(updateProgressKey);\n                if (inProgress && reset) {\n                    setUpdateStateInJSON(updateProgressKey, !reset)\n                        .always(checkUpdateStatus);\n                 } else if (!inProgress) {\n                    checkUpdateStatus();\n                }\n            });\n    }\n\n\n    /**\n     * Enables/disables the state of \"Check For Updates\" menu entry under Help Menu\n     */\n    function enableCheckForUpdateEntry(enable) {\n        var cfuCommand = CommandManager.get(Commands.HELP_CHECK_FOR_UPDATE);\n        cfuCommand.setEnabled(enable);\n        UpdateNotification.enableUpdateNotificationIcon(enable);\n    }\n\n    /**\n     * Checks if it is the first iteration of download\n     * @returns {boolean} - true if first iteration, false if it is a retrial of download\n     */\n    function isFirstIterationDownload() {\n        return (downloadAttemptsRemaining === MAX_DOWNLOAD_ATTEMPTS);\n    }\n\n    /**\n     * Resets the update state in updatehelper.json in case of failure,\n     * and logs an error with the message\n     * @param {string} message - the message to be logged onto console\n     */\n    function resetStateInFailure(message) {\n        updateJsonHandler.reset();\n\n        UpdateInfoBar.showUpdateBar({\n            type: \"error\",\n            title: Strings.UPDATE_FAILED,\n            description: \"\"\n        });\n\n        enableCheckForUpdateEntry(true);\n        console.error(message);\n\n    }\n\n    /**\n     * Sets the update state in updateHelper.json in Appdata\n     * @param   {string} key   - key to be set\n     * @param   {string} value - value to be set\n     * @returns {$.Deferred} - a jquery promise, that is resolved with\n     *                       success or failure of state update in json file\n     */\n    function setUpdateStateInJSON(key, value) {\n         var result = $.Deferred();\n\n        updateJsonHandler.set(key, value)\n            .done(function () {\n                result.resolve();\n            })\n            .fail(function () {\n                resetStateInFailure(\"AutoUpdate : Could not modify updatehelper.json\");\n                result.reject();\n            });\n        return result.promise();\n    }\n\n    /**\n     * Handles a safe download of the latest installer,\n     * safety is ensured by cleaning up any pre-existing installers\n     * from update directory before beginning a fresh download\n     */\n    function handleSafeToDownload() {\n        var downloadFn = function () {\n            if (isFirstIterationDownload()) {\n                // For the first iteration of download, show download\n                //status info in Status bar, and pass download to node\n                UpdateStatus.showUpdateStatus(\"initial-download\");\n                postMessageToNode(MessageIds.DOWNLOAD_INSTALLER, true);\n            } else {\n                /* For the retry iterations of download, modify the\n                download status info in Status bar, and pass download to node */\n                var attempt = (MAX_DOWNLOAD_ATTEMPTS - downloadAttemptsRemaining);\n                if (attempt > 1) {\n                    var info = attempt.toString() + \"/5\";\n                    var status = {\n                        target: \"retry-download\",\n                        spans: [{\n                            id: \"attempt\",\n                            val: info\n                        }]\n                    };\n                    UpdateStatus.modifyUpdateStatus(status);\n                } else {\n                    UpdateStatus.showUpdateStatus(\"retry-download\");\n                }\n                postMessageToNode(MessageIds.DOWNLOAD_INSTALLER, false);\n            }\n\n            --downloadAttemptsRemaining;\n        };\n\n        if(!isAutoUpdateInitiated) {\n            isAutoUpdateInitiated = true;\n            updateJsonHandler.refresh()\n                .done(function() {\n                    setUpdateStateInJSON('downloadCompleted', false)\n                        .done(downloadFn);\n                });\n        } else {\n            setUpdateStateInJSON('downloadCompleted', false)\n                .done(downloadFn);\n        }\n    }\n\n    /**\n     * Checks if there is an active internet connection available\n     * @returns {boolean} - true if online, false otherwise\n     */\n    function checkIfOnline() {\n        return window.navigator.onLine;\n    }\n\n    /**\n     * Attempts a download of the latest installer, while cleaning up any existing downloaded installers\n     */\n    function attemptToDownload() {\n        if (checkIfOnline()) {\n            postMessageToNode(MessageIds.PERFORM_CLEANUP, ['.json'], true);\n        } else {\n            enableCheckForUpdateEntry(true);\n            UpdateStatus.cleanUpdateStatus();\n            HealthLogger.sendAnalyticsData(\n                autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_FAILED,\n                \"autoUpdate\",\n                \"download\",\n                \"fail\",\n                \"No Internet connection available.\"\n            );\n            UpdateInfoBar.showUpdateBar({\n                type: \"warning\",\n                title: Strings.DOWNLOAD_FAILED,\n                description: Strings.INTERNET_UNAVAILABLE\n            });\n\n            setUpdateStateInJSON(\"autoUpdateInProgress\", false);\n        }\n    }\n\n    /**\n     * Validates the checksum of a file against a given checksum\n     * @param {object} params - json containing {\n     *                        filePath - path to the file,\n     *                        expectedChecksum - the checksum to validate against }\n     */\n    function validateChecksum(params) {\n        postMessageToNode(MessageIds.VALIDATE_INSTALLER, params);\n    }\n\n    /**\n     * Gets the latest installer, by either downloading a new one or fetching the cached download.\n     */\n    function getLatestInstaller() {\n        var downloadCompleted = updateJsonHandler.get('downloadCompleted');\n        if (!downloadCompleted) {\n            attemptToDownload();\n        } else {\n            validateChecksum();\n        }\n    }\n\n    /**\n     * Handles the show status information callback from Node.\n     * It modifies the info displayed on Status bar.\n     * @param {object} statusObj - json containing status info {\n     *                         target - id of string to display,\n     *                         spans - Array containing json objects of type - {\n     *                             id - span id,\n     *                             val - string to fill the span element with }\n     *                         }\n     */\n    function showStatusInfo(statusObj) {\n        if (statusObj.target === \"initial-download\") {\n            HealthLogger.sendAnalyticsData(\n                autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_START,\n                \"autoUpdate\",\n                \"download\",\n                \"started\",\n                \"\"\n            );\n            UpdateStatus.modifyUpdateStatus(statusObj);\n        }\n        UpdateStatus.displayProgress(statusObj);\n    }\n\n    /**\n     * Handles the error messages from Node, in a popup displayed to the user.\n     * @param {string} message - error string\n     */\n    function showErrorMessage(message) {\n        var analyticsDescriptionMessage = \"\";\n\n        switch (message) {\n        case _nodeErrorMessages.UPDATEDIR_READ_FAILED:\n            analyticsDescriptionMessage = \"Update directory could not be read.\";\n            break;\n        case _nodeErrorMessages.UPDATEDIR_CLEAN_FAILED:\n            analyticsDescriptionMessage = \"Update directory could not be cleaned.\";\n            break;\n        }\n        console.log(\"AutoUpdate : Clean-up failed! Reason : \" + analyticsDescriptionMessage + \".\\n\");\n        HealthLogger.sendAnalyticsData(\n                autoUpdateEventNames.AUTOUPDATE_CLEANUP_FAILED,\n                \"autoUpdate\",\n                \"cleanUp\",\n                \"fail\",\n                analyticsDescriptionMessage\n        );\n    }\n\n\n    /**\n     * Handles the Cancel button click by user in\n     * Unsaved changes prompt, which would come up if user\n     * has dirty files and he/she clicked UpdateNow\n     */\n    function dirtyFileSaveCancelled() {\n        UpdateInfoBar.showUpdateBar({\n            type: \"warning\",\n            title: Strings.WARNING_TYPE,\n            description: Strings.UPDATE_ON_NEXT_LAUNCH\n        });\n    }\n\n    /**\n     * Registers the App Quit event handler, in case of dirty\n     * file save cancelled scenario, while Auto Update is scheduled to run on quit\n     */\n    function setAppQuitHandler() {\n        resetAppQuitHandler();\n        DocumentCommandHandlers.on(APP_QUIT_CANCELLED, dirtyFileSaveCancelled);\n    }\n\n\n    /**\n     * Initiates the update process, when user clicks UpdateNow in the update popup\n     * @param {string} formattedInstallerPath - formatted path to the latest installer\n     * @param {string} formattedLogFilePath  - formatted path to the installer log file\n     * @param {string} installStatusFilePath  -  path to the install status log file\n     */\n    function initiateUpdateProcess(formattedInstallerPath, formattedLogFilePath, installStatusFilePath) {\n\n        // Get additional update parameters on Mac : installDir, appName, and updateDir\n        function getAdditionalParams() {\n            var retval = {};\n            var installDir = FileUtils.getNativeBracketsDirectoryPath();\n\n            if (installDir) {\n                var appPath = installDir.split(\"/Contents/www\")[0];\n                installDir = appPath.substr(0, appPath.lastIndexOf('/'));\n                var appName = appPath.substr(appPath.lastIndexOf('/') + 1);\n\n                retval = {\n                    installDir: installDir,\n                    appName: appName,\n                    updateDir: updateDir\n                };\n            }\n            return retval;\n        }\n\n        // Update function, to carry out app update\n        var updateFn = function () {\n            var infoObj = {\n                installerPath: formattedInstallerPath,\n                logFilePath: formattedLogFilePath,\n                installStatusFilePath: installStatusFilePath\n            };\n\n            if (brackets.platform === \"mac\") {\n                var additionalParams = getAdditionalParams(),\n                    key;\n\n                for (key in additionalParams) {\n                    if (additionalParams.hasOwnProperty(key)) {\n                        infoObj[key] = additionalParams[key];\n                    }\n                }\n            }\n\n            // Set update parameters for app update\n            if (brackets.app.setUpdateParams) {\n                brackets.app.setUpdateParams(JSON.stringify(infoObj), function (err) {\n                    if (err) {\n                        resetStateInFailure(\"AutoUpdate : Update parameters could not be set for the installer. Error encountered: \" + err);\n                    } else {\n                        setAppQuitHandler();\n                        CommandManager.execute(Commands.FILE_QUIT);\n                    }\n                });\n            } else {\n                resetStateInFailure(\"AutoUpdate : setUpdateParams could not be found in shell\");\n            }\n        };\n        setUpdateStateInJSON('updateInitiatedInPrevSession', true)\n            .done(updateFn);\n    }\n\n    /**\n     * Detaches the Update Bar Buttons event handlers\n     */\n    function detachUpdateBarBtnHandlers() {\n        UpdateInfoBar.off(UpdateInfoBar.RESTART_BTN_CLICKED);\n        UpdateInfoBar.off(UpdateInfoBar.LATER_BTN_CLICKED);\n    }\n\n\n    /**\n     * Handles the installer validation callback from Node\n     * @param {object} statusObj - json containing - {\n     *                           valid - (boolean)true for a valid installer, false otherwise,\n     *                           installerPath, logFilePath,\n     *                           installStatusFilePath - for a valid installer,\n     *                           err - for an invalid installer }\n     */\n    function handleValidationStatus(statusObj) {\n        enableCheckForUpdateEntry(true);\n        UpdateStatus.cleanUpdateStatus();\n\n        if (statusObj.valid) {\n\n            // Installer is validated successfully\n            var statusValidFn = function () {\n\n                // Restart button click handler\n                var restartBtnClicked = function () {\n                    HealthLogger.sendAnalyticsData(\n                        autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_COMPLETE_USER_CLICK_RESTART,\n                        \"autoUpdate\",\n                        \"installNotification\",\n                        \"installNow \",\n                        \"click\"\n                    );\n                    detachUpdateBarBtnHandlers();\n                    initiateUpdateProcess(statusObj.installerPath, statusObj.logFilePath, statusObj.installStatusFilePath);\n                };\n\n                // Later button click handler\n                var laterBtnClicked = function () {\n                    HealthLogger.sendAnalyticsData(\n                        autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_COMPLETE_USER_CLICK_LATER,\n                        \"autoUpdate\",\n                        \"installNotification\",\n                        \"cancel\",\n                        \"click\"\n                    );\n                    detachUpdateBarBtnHandlers();\n                    setUpdateStateInJSON('updateInitiatedInPrevSession', false);\n                };\n\n                //attaching UpdateBar handlers\n                UpdateInfoBar.on(UpdateInfoBar.RESTART_BTN_CLICKED, restartBtnClicked);\n                UpdateInfoBar.on(UpdateInfoBar.LATER_BTN_CLICKED, laterBtnClicked);\n\n                UpdateInfoBar.showUpdateBar({\n                    title: Strings.DOWNLOAD_COMPLETE,\n                    description: Strings.CLICK_RESTART_TO_UPDATE,\n                    needButtons: true\n                });\n\n                setUpdateStateInJSON(\"autoUpdateInProgress\", false);\n                HealthLogger.sendAnalyticsData(\n                    autoUpdateEventNames.AUTOUPDATE_DOWNLOADCOMPLETE_UPDATE_BAR_RENDERED,\n                    \"autoUpdate\",\n                    \"installNotification\",\n                    \"render\",\n                    \"\"\n                );\n            };\n\n            if(!isAutoUpdateInitiated) {\n                isAutoUpdateInitiated = true;\n                updateJsonHandler.refresh()\n                    .done(function() {\n                        setUpdateStateInJSON('downloadCompleted', true)\n                        .done(statusValidFn);\n                });\n            } else {\n                 setUpdateStateInJSON('downloadCompleted', true)\n                    .done(statusValidFn);\n            }\n        } else {\n\n            // Installer validation failed\n\n            if (updateJsonHandler.get(\"downloadCompleted\")) {\n\n                // If this was a cached download, retry downloading\n                updateJsonHandler.reset();\n\n                var statusInvalidFn = function () {\n                    downloadAttemptsRemaining = MAX_DOWNLOAD_ATTEMPTS;\n                    getLatestInstaller();\n                };\n\n                setUpdateStateInJSON('downloadCompleted', false)\n                    .done(statusInvalidFn);\n            } else {\n\n                // If this is a new download, prompt the message on update bar\n                var descriptionMessage = \"\",\n                    analyticsDescriptionMessage = \"\";\n\n                switch (statusObj.err) {\n                case _nodeErrorMessages.CHECKSUM_DID_NOT_MATCH:\n                    descriptionMessage = Strings.CHECKSUM_DID_NOT_MATCH;\n                    analyticsDescriptionMessage = \"Checksum didn't match.\";\n                    break;\n                case _nodeErrorMessages.INSTALLER_NOT_FOUND:\n                    descriptionMessage = Strings.INSTALLER_NOT_FOUND;\n                    analyticsDescriptionMessage = \"Installer not found.\";\n                    break;\n                }\n                HealthLogger.sendAnalyticsData(\n                    autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_FAILED,\n                    \"autoUpdate\",\n                    \"download\",\n                    \"fail\",\n                    analyticsDescriptionMessage\n                );\n                UpdateInfoBar.showUpdateBar({\n                    type: \"error\",\n                    title: Strings.VALIDATION_FAILED,\n                    description: descriptionMessage\n                });\n\n                setUpdateStateInJSON(\"autoUpdateInProgress\", false);\n            }\n        }\n    }\n\n    /**\n     * Handles the download failure callback from Node\n     * @param {string} message - reason of download failure\n     */\n    function handleDownloadFailure(message) {\n        console.log(\"AutoUpdate : Download of latest installer failed in Attempt \" +\n            (MAX_DOWNLOAD_ATTEMPTS - downloadAttemptsRemaining) + \".\\n Reason : \" + message);\n\n        if (downloadAttemptsRemaining) {\n\n            // Retry the downloading\n            attemptToDownload();\n        } else {\n\n            // Download could not completed, all attempts exhausted\n            enableCheckForUpdateEntry(true);\n            UpdateStatus.cleanUpdateStatus();\n\n            var descriptionMessage = \"\",\n                analyticsDescriptionMessage = \"\";\n            if (message === _nodeErrorMessages.DOWNLOAD_ERROR) {\n                descriptionMessage = Strings.DOWNLOAD_ERROR;\n                analyticsDescriptionMessage = \"Error occurred while downloading.\";\n            } else if (message === _nodeErrorMessages.NETWORK_SLOW_OR_DISCONNECTED) {\n                descriptionMessage = Strings.NETWORK_SLOW_OR_DISCONNECTED;\n                analyticsDescriptionMessage = \"Network is Disconnected or too slow.\";\n            }\n            HealthLogger.sendAnalyticsData(\n                autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_FAILED,\n                \"autoUpdate\",\n                \"download\",\n                \"fail\",\n                analyticsDescriptionMessage\n            );\n            UpdateInfoBar.showUpdateBar({\n                type: \"error\",\n                title: Strings.DOWNLOAD_FAILED,\n                description: descriptionMessage\n            });\n\n            setUpdateStateInJSON(\"autoUpdateInProgress\", false);\n        }\n\n    }\n\n\n    /**\n     * Handles the completion of node state initialization\n     */\n    function handleInitializationComplete() {\n        enableCheckForUpdateEntry(false);\n        getLatestInstaller();\n    }\n\n\n    /**\n     * Handles Download completion callback from Node\n     */\n    function handleDownloadSuccess() {\n        HealthLogger.sendAnalyticsData(\n            autoUpdateEventNames.AUTOUPDATE_DOWNLOAD_COMPLETED,\n            \"autoUpdate\",\n            \"download\",\n            \"complete\",\n            \"\"\n        );\n        UpdateStatus.showUpdateStatus(\"validating-installer\");\n        validateChecksum();\n    }\n\n\n    function _handleAppClose() {\n        postMessageToNode(MessageIds.REMOVE_FROM_REQUESTERS);\n    }\n\n    /**\n     * Generates a map for brackets side functions\n     */\n    function registerBracketsFunctions() {\n        functionMap[\"brackets.notifyinitializationComplete\"] = handleInitializationComplete;\n        functionMap[\"brackets.showStatusInfo\"]               = showStatusInfo;\n        functionMap[\"brackets.notifyDownloadSuccess\"]        = handleDownloadSuccess;\n        functionMap[\"brackets.showErrorMessage\"]             = showErrorMessage;\n        functionMap[\"brackets.notifyDownloadFailure\"]        = handleDownloadFailure;\n        functionMap[\"brackets.notifySafeToDownload\"]         = handleSafeToDownload;\n        functionMap[\"brackets.notifyvalidationStatus\"]       = handleValidationStatus;\n        functionMap[\"brackets.notifyInstallationStatus\"]     = handleInstallationStatus;\n\n        ProjectManager.on(\"beforeProjectClose beforeAppClose\", _handleAppClose);\n    }\n    functionMap[\"brackets.nodeDomainInitialized\"]     = nodeDomainInitialized;\n    functionMap[\"brackets.registerBracketsFunctions\"] = registerBracketsFunctions;\n\n});\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/node/AutoUpdateDomain.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global exports */\n/*global process*/\n(function () {\n    \"use strict\";\n\n    var _domainManager;\n\n    var request = require('request'),\n        progress = require('request-progress'),\n        path = require('path'),\n        fs = require('fs-extra'),\n        crypto = require('crypto');\n\n    // Current Date and Time needed for log filenames\n    var curDate = Date.now().toString();\n\n    //AUTOUPDATE_PRERELEASE\n    //Installer log file\n    var logFile = curDate + 'update.logs',\n        logFilePath;\n\n    //Install status file\n    var installStatusFile = curDate + 'installStatus.logs',\n        installStatusFilePath;\n\n    var updateDir,\n        _updateParams;\n\n    var MessageIds,\n        installerPath;\n\n    // function map for node functions\n    var functionMap = {};\n\n    var nodeErrorMessages = {\n        UPDATEDIR_READ_FAILED: 0,\n        UPDATEDIR_CLEAN_FAILED: 1,\n        CHECKSUM_DID_NOT_MATCH: 2,\n        INSTALLER_NOT_FOUND: 3,\n        DOWNLOAD_ERROR: 4,\n        NETWORK_SLOW_OR_DISCONNECTED: 5\n    };\n\n    var requesters = {},\n        isNodeDomainInitialized = false;\n\n    /**\n     * Gets the arguments to a function in an array\n     * @param   {object} args - the arguments object\n     * @returns {Array}   - array of actual arguments\n     */\n    function getFunctionArgs(args) {\n        if (args.length > 2) {\n            var fnArgs = new Array(args.length - 2),\n                i;\n            for (i = 2; i < args.length; ++i) {\n                fnArgs[i - 2] = args[i];\n            }\n            return fnArgs;\n        }\n        return [];\n    }\n\n\n    /**\n     * Posts messages to brackets\n     * @param {string} messageId - Message to be passed\n     */\n    function postMessageToBrackets(messageId, requester) {\n        if(!requesters[requester]) {\n            for (var key in requesters) {\n                requester = key;\n                break;\n            }\n        }\n\n        var msgObj = {\n            fn: messageId,\n            args: getFunctionArgs(arguments),\n            requester: requester.toString()\n        };\n        _domainManager.emitEvent('AutoUpdate', 'data', [msgObj]);\n    }\n\n    /**\n     * Quotes and Converts a file path, to accommodate platform dependent paths\n     * @param   {string} qncPath - file path\n     * @param   {boolean} resolve - false if path is only to be quoted, true if both quoted and converted\n     * @returns {string}  quoted and converted file path\n     */\n    function quoteAndConvert(qncPath, resolve) {\n        if (resolve) {\n            qncPath = path.resolve(qncPath);\n        }\n        return \"\\\"\" + qncPath + \"\\\"\";\n    }\n\n\n    /**\n     * Validates the checksum of a file against a given checksum\n     * @param {object} params - json containing {\n     *                        filePath - path to the file,\n     *                        expectedChecksum - the checksum to validate against }\n     */\n    function validateChecksum(requester, params) {\n        params = params || {\n            filePath: installerPath,\n            expectedChecksum: _updateParams.checksum\n        };\n\n        var hash = crypto.createHash('sha256'),\n            currentRequester = requester || \"\";\n\n        if (fs.existsSync(params.filePath)) {\n            var stream = fs.createReadStream(params.filePath);\n\n            stream.on('data', function (data) {\n                hash.update(data);\n            });\n\n            stream.on('end', function () {\n                var calculatedChecksum = hash.digest('hex'),\n                    isValidChecksum = (params.expectedChecksum === calculatedChecksum),\n                    status;\n\n                if (isValidChecksum) {\n                    if (process.platform === \"darwin\") {\n                        status = {\n                            valid: true,\n                            installerPath: installerPath,\n                            logFilePath: logFilePath,\n                            installStatusFilePath: installStatusFilePath\n                        };\n                    } else if (process.platform === \"win32\") {\n                        status = {\n                            valid: true,\n                            installerPath: quoteAndConvert(installerPath, true),\n                            logFilePath: quoteAndConvert(logFilePath, true),\n                            installStatusFilePath: installStatusFilePath\n                        };\n                    }\n                } else {\n                    status = {\n                        valid: false,\n                        err: nodeErrorMessages.CHECKSUM_DID_NOT_MATCH\n                    };\n                }\n                postMessageToBrackets(MessageIds.NOTIFY_VALIDATION_STATUS, currentRequester, status);\n            });\n        } else {\n            var status = {\n                valid: false,\n                err: nodeErrorMessages.INSTALLER_NOT_FOUND\n            };\n            postMessageToBrackets(MessageIds.NOTIFY_VALIDATION_STATUS, currentRequester, status);\n        }\n    }\n\n\t/**\n     * Parse the Installer log and search for a error strings\n\t * one it finds the line which has any of error String\n     * it return that line and exit\n     */\n    function parseInstallerLog(filepath, searchstring, encoding, callback) {\n        var line = \"\";\n        var searchFn = function searchFn(str) {\n            var arr = str.split('\\n'),\n                lineNum,\n                pos;\n            for (lineNum = arr.length - 1; lineNum >= 0; lineNum--) {\n                var searchStrNum;\n                for (searchStrNum = 0; searchStrNum < searchstring.length; searchStrNum++) {\n                    pos = arr[lineNum].search(searchstring[searchStrNum]);\n                    if (pos !== -1) {\n                        line = arr[lineNum];\n                        break;\n                    }\n                }\n                if (pos !== -1) {\n                    break;\n                }\n            }\n            callback(line);\n        };\n\n        fs.readFile(filepath, {\"encoding\": encoding})\n            .then(function (str) {\n                return searchFn(str);\n            }).catch(function () {\n                callback(\"\");\n            });\n    }\n\n    /**\n     * one it finds the line which has any of error String\n     * after parsing the Log\n     * it notifies the bracket.\n     * @param{Object} searchParams is object contains Information Error String\n     * Encoding of Log File Update Diectory Path.\n     */\n    function checkInstallerStatus(requester, searchParams) {\n        var installErrorStr = searchParams.installErrorStr,\n            bracketsErrorStr = searchParams.bracketsErrorStr,\n            updateDirectory = searchParams.updateDir,\n            encoding =        searchParams.encoding || \"utf8\",\n            statusObj = {installError: \": BA_UN\"},\n            logFileAvailable = false,\n            currentRequester = requester || \"\";\n\n        var notifyBrackets = function notifyBrackets(errorline) {\n            statusObj.installError = errorline || \": BA_UN\";\n            postMessageToBrackets(MessageIds.NOTIFY_INSTALLATION_STATUS, currentRequester, statusObj);\n        };\n\n        var parseLog = function (files) {\n            files.forEach(function (file) {\n                var fileExt = path.extname(path.basename(file));\n                if (fileExt === \".logs\") {\n                    var fileName = path.basename(file),\n                        fileFullPath = updateDirectory + '/' + file;\n                    if (fileName.search(\"installStatus.logs\") !== -1) {\n                        logFileAvailable = true;\n                        parseInstallerLog(fileFullPath, bracketsErrorStr, \"utf8\", notifyBrackets);\n                    } else if (fileName.search(\"update.logs\") !== -1) {\n                        logFileAvailable = true;\n                        parseInstallerLog(fileFullPath, installErrorStr, encoding, notifyBrackets);\n                    }\n                }\n            });\n            if (!logFileAvailable) {\n                postMessageToBrackets(MessageIds.NOTIFY_INSTALLATION_STATUS, currentRequester, statusObj);\n            }\n        };\n\n        fs.readdir(updateDirectory)\n            .then(function (files) {\n                return parseLog(files);\n            }).catch(function () {\n                postMessageToBrackets(MessageIds.NOTIFY_INSTALLATION_STATUS, currentRequester, statusObj);\n            });\n    }\n\n    /**\n     * Downloads the installer for latest Brackets release\n     * @param {boolean} sendInfo   - true if download status info needs to be\n     *                             sent back to Brackets, false otherwise\n     * @param {object}   [updateParams=_updateParams] - json containing update parameters\n     */\n    function downloadInstaller(requester, isInitialAttempt, updateParams) {\n        updateParams = updateParams || _updateParams;\n        var currentRequester = requester || \"\";\n        try {\n            var ext = path.extname(updateParams.installerName);\n            var localInstallerPath = path.resolve(updateDir, Date.now().toString() + ext),\n                localInstallerFile = fs.createWriteStream(localInstallerPath),\n                requestCompleted = true,\n                readTimeOut = 180000;\n            progress(request(updateParams.downloadURL, {timeout: readTimeOut}), {})\n                .on('progress', function (state) {\n                    var target = \"retry-download\";\n                    if (isInitialAttempt) {\n                        target = \"initial-download\";\n                    }\n                    var info = Math.floor(parseFloat(state.percent) * 100).toString() + '%';\n                    var status = {\n                        target: target,\n                        spans: [{\n                            id: \"percent\",\n                            val: info\n                        }]\n                    };\n                    postMessageToBrackets(MessageIds.SHOW_STATUS_INFO, currentRequester, status);\n                })\n                .on('error', function (err) {\n                    console.log(\"AutoUpdate : Download failed. Error occurred : \" + err.toString());\n                    requestCompleted = false;\n                    localInstallerFile.end();\n                    var error = err.code === 'ESOCKETTIMEDOUT' || err.code === 'ENOTFOUND' ?\n                                nodeErrorMessages.NETWORK_SLOW_OR_DISCONNECTED :\n                                nodeErrorMessages.DOWNLOAD_ERROR;\n                    postMessageToBrackets(MessageIds.NOTIFY_DOWNLOAD_FAILURE, currentRequester, error);\n                })\n                .pipe(localInstallerFile)\n                .on('close', function () {\n                    if (requestCompleted) {\n                        try {\n                            fs.renameSync(localInstallerPath, installerPath);\n                            postMessageToBrackets(MessageIds.NOTIFY_DOWNLOAD_SUCCESS, currentRequester);\n                        } catch (e) {\n                            console.log(\"AutoUpdate : Download failed. Exception occurred : \" + e.toString());\n                            postMessageToBrackets(MessageIds.NOTIFY_DOWNLOAD_FAILURE,\n                                                      currentRequester, nodeErrorMessages.DOWNLOAD_ERROR);\n                        }\n                    }\n                });\n        } catch (e) {\n            console.log(\"AutoUpdate : Download failed. Exception occurred : \" + e.toString());\n            postMessageToBrackets(MessageIds.NOTIFY_DOWNLOAD_FAILURE,\n                                  currentRequester, nodeErrorMessages.DOWNLOAD_ERROR);\n        }\n    }\n\n    /**\n     * Performs clean up for the contents in Update Directory in AppData\n     * @param {Array} filesToCache - array of file types to cache\n     * @param {boolean} notifyBack  - true if Brackets needs to be\n     *                              notified post cleanup, false otherwise\n     */\n    function performCleanup(requester, filesToCache, notifyBack) {\n        var currentRequester = requester || \"\";\n        function filterFilesAndNotify(files, filesToCacheArr, notifyBackToBrackets) {\n            files.forEach(function (file) {\n                var fileExt = path.extname(path.basename(file));\n                if (filesToCacheArr.indexOf(fileExt) < 0) {\n                    var fileFullPath = updateDir + '/' + file;\n                    try {\n                        fs.removeSync(fileFullPath);\n                    } catch (e) {\n                        console.log(\"AutoUpdate : Exception occured in removing \", fileFullPath, e);\n                    }\n                }\n            });\n            if (notifyBackToBrackets) {\n                postMessageToBrackets(MessageIds.NOTIFY_SAFE_TO_DOWNLOAD, currentRequester);\n            }\n        }\n\n        fs.stat(updateDir)\n            .then(function (stats) {\n                if (stats) {\n                    if (filesToCache) {\n                        fs.readdir(updateDir)\n                            .then(function (files) {\n                                filterFilesAndNotify(files, filesToCache, notifyBack);\n                            })\n                            .catch(function (err) {\n                                console.log(\"AutoUpdate : Error in Reading Update Dir for Cleanup : \" + err.toString());\n                                postMessageToBrackets(MessageIds.SHOW_ERROR_MESSAGE,\n                                                      currentRequester, nodeErrorMessages.UPDATEDIR_READ_FAILED);\n                            });\n                    } else {\n                        fs.remove(updateDir)\n                            .then(function () {\n                                console.log('AutoUpdate : Update Directory in AppData Cleaned: Complete');\n                            })\n                            .catch(function (err) {\n                                console.log(\"AutoUpdate : Error in Cleaning Update Dir : \" + err.toString());\n                                postMessageToBrackets(MessageIds.SHOW_ERROR_MESSAGE,\n                                                      currentRequester, nodeErrorMessages.UPDATEDIR_CLEAN_FAILED);\n                            });\n                    }\n                }\n            })\n            .catch(function (err) {\n                console.log(\"AutoUpdate : Error in Reading Update Dir stats for Cleanup : \" + err.toString());\n                postMessageToBrackets(MessageIds.SHOW_ERROR_MESSAGE,\n                                      currentRequester, nodeErrorMessages.UPDATEDIR_CLEAN_FAILED);\n            });\n    }\n\n    /**\n     * Initializes the node with update parameters\n     * @param {object} updateParams - json containing update parameters\n     */\n    function initializeState(requester, updateParams) {\n        var currentRequester = requester || \"\";\n        _updateParams = updateParams;\n        installerPath = path.resolve(updateDir, updateParams.installerName);\n        postMessageToBrackets(MessageIds.NOTIFY_INITIALIZATION_COMPLETE, currentRequester);\n    }\n\n\n    function removeFromRequesters(requester) {\n        if (requesters.hasOwnProperty(requester.toString())) {\n            delete requesters[requester];\n        }\n    }\n\n    /**\n     * Generates a map for node side functions\n     */\n    function registerNodeFunctions() {\n        functionMap[\"node.downloadInstaller\"] = downloadInstaller;\n        functionMap[\"node.performCleanup\"] = performCleanup;\n        functionMap[\"node.validateInstaller\"] = validateChecksum;\n        functionMap[\"node.initializeState\"] = initializeState;\n        functionMap[\"node.checkInstallerStatus\"] = checkInstallerStatus;\n        functionMap[\"node.removeFromRequesters\"] = removeFromRequesters;\n    }\n\n    /**\n     * Initializes node for the auto update, registers messages and node side funtions\n     * @param {object} initObj - json containing init information {\n     *                         messageIds : Messages for brackets and node communication\n     *                         updateDir  : update directory in Appdata\n     *                         requester  : ID of the current requester domain}\n     */\n    function initNode(initObj) {\n        var resetUpdateProgres = false;\n        if (!isNodeDomainInitialized) {\n            MessageIds = initObj.messageIds;\n            updateDir = path.resolve(initObj.updateDir);\n            logFilePath = path.resolve(updateDir, logFile);\n            installStatusFilePath = path.resolve(updateDir, installStatusFile);\n            registerNodeFunctions();\n            isNodeDomainInitialized = true;\n            resetUpdateProgres = true;\n        }\n        postMessageToBrackets(MessageIds.NODE_DOMAIN_INITIALIZED, initObj.requester.toString(), resetUpdateProgres);\n        requesters[initObj.requester.toString()] = true;\n        postMessageToBrackets(MessageIds.REGISTER_BRACKETS_FUNCTIONS, initObj.requester.toString());\n    }\n\n\n    /**\n     * Receives messages from brackets\n     * @param {object} msgObj - json containing - {\n     *                          fn - function to execute on node side\n     *                          args - arguments to the above function }\n     */\n    function receiveMessageFromBrackets(msgObj) {\n        var argList = msgObj.args;\n        argList.unshift(msgObj.requester || \"\");\n        functionMap[msgObj.fn].apply(null, argList);\n    }\n\n    /**\n     * Initialize the domain with commands and events related to AutoUpdate\n     * @param {DomainManager} domainManager - The DomainManager for AutoUpdateDomain\n     */\n\n    function init(domainManager) {\n        if (!domainManager.hasDomain(\"AutoUpdate\")) {\n            domainManager.registerDomain(\"AutoUpdate\", {\n                major: 0,\n                minor: 1\n            });\n        }\n        _domainManager = domainManager;\n\n        domainManager.registerCommand(\n            \"AutoUpdate\",\n            \"initNode\",\n            initNode,\n            true,\n            \"Initializes node for the auto update\",\n            [\n                {\n                    name: \"initObj\",\n                    type: \"object\",\n                    description: \"json object containing init information\"\n                }\n            ],\n            []\n        );\n\n        domainManager.registerCommand(\n            \"AutoUpdate\",\n            \"data\",\n            receiveMessageFromBrackets,\n            true,\n            \"Receives messages from brackets\",\n            [\n                {\n                    name: \"msgObj\",\n                    type: \"object\",\n                    description: \"json object containing message info\"\n                }\n            ],\n            []\n        );\n\n        domainManager.registerEvent(\n            \"AutoUpdate\",\n            \"data\",\n            [\n                {\n                    name: \"msgObj\",\n                    type: \"object\",\n                    description: \"json object containing message info to pass to brackets\"\n                }\n            ]\n        );\n    }\n\n    exports.init = init;\n\n}());\n\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/node/package.json",
    "content": "{\n  \"name\": \"brackets-auto-update\",\n  \"dependencies\": {\n    \"request\": \"^2.83.0\",\n    \"request-progress\": \"^3.0.0\",\n    \"fs-extra\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "src/extensions/default/AutoUpdate/styles/styles.css",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*Status bar*/\n#update-status {\n    position: relative;\n    float: right;\n    padding: 0px 20px;\n    height: 25px;\n    min-width: 9%;\n    width: auto;\n    text-align: center;\n    background: #fff;\n}\n\n.dark #update-status {\n    background: #1c1c1e;\n}\n\n#update-status p {\n    position: relative;\n    display: none;\n    white-space: nowrap;\n    font-family: 'SourceSansPro';\n}\n\n/*Update Bar*/\n#update-bar {\n    display: block;\n    background-color: #105F9C;\n    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.53);\n    height: 38px;\n    width: 100%;\n    position: absolute;\n    z-index: 15;\n    left: 0px;\n    bottom: 25px;\n    outline: none;\n\toverflow: hidden;\n}\n\n#update-bar #icon-container {\n    width: auto;\n    height: auto;\n    padding: 11px;\n    float: left;\n}\n#update-bar #icon-container #update-icon {\n    background: url(\"../images/info.svg\") no-repeat 0 0;\n    width: 16px;\n    height: 16px;\n    display: block;\n}\n\n#update-bar #content-container {\n    padding: 10px 7px;\n    float: left;\n    max-width: 78%;\n}\n\n#update-bar #content-container #update-content {\n    margin: 0px !important; /*Check if this important is necessary*/\n    line-height: 18px;\n    font-size: 14px;\n    font-family: 'SourceSansPro';\n    color: #FFFFFF;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n#update-bar #content-container #update-content #heading{\n    font-weight: bold;\n}\n/*For focussed link of brackets.io*/\n#update-bar #content-container #update-content #description a:focus{\n    box-shadow: none;\n}\n\n#update-bar #content-container #update-content #description a{\n    text-decoration: underline;\n\tcolor: #FFFFFF;\n}\n\n#update-bar #button-container {\n    display: block;\n\tfloat: right;\n\tright: 40px;\n\tposition: fixed;\n\tbackground-color: #105F9C;\n\tmin-width: 180px;\n}\n\n#update-bar #close-icon-container {\n    height: auto;\n    padding: 9px;\n    position: fixed;\n    float: right;\n    text-align: center;\n    width: auto;\n\tmin-width: 66px;\n\tright: 30px;\n\tbackground-color: #105F9C;\n}\n\n#update-bar #close-icon-container #close-icon {\n    display: block;\n    color: white;\n    font-size: 18px;\n    line-height: 18px;\n    text-decoration: none;\n    width: 18px;\n    height: 18px;\n    background-color: transparent;\n    border: none;\n    padding: 0px; /*This is needed to center the icon*/\n\tfloat: right;\n}\n\n#update-bar #close-icon-container #close-icon:hover {\n    background-color: rgba(255, 255, 255 ,0.16);\n    border-radius: 50%;    \n}\n\n#update-bar #close-icon-container #close-icon:focus {\n    background-color: rgba(255, 255, 255 ,0.16);\n    border-radius: 50%;\n    border: 1px solid #C3E3FF;\n    outline: 0;\n}\n\n#update-bar #close-icon-container #close-icon:focus:active {\n    background-color: rgba(255, 255, 255 ,0.32);  \n    border: none;\n}\n\n.update-btn {\n    width: auto;\n    height: 28px;\n    position: relative;\n    float: right;\n    padding: 4px 15px;\n    border: 1px solid #EAEAEA;\n    border-radius: 3px;\n    font-size: 14px;\n    text-align: center;\n    font-family: 'SourceSansPro';\n    color: #E6E6E6;\n    margin-top: 5px;\n    margin-right: 10px;\n    background-color: transparent;\n}\n\n.update-btn:hover {\n    border-color: #C9C9C9;\n    background-color: #EAEAEA;\n    color: #202020;\n}\n\n.update-btn:focus:active {\n    border: 1px solid #B5B5B5;\n    background-color: #CCCCCC;\n    color: #202020;\n    padding: 4px 15px;\n    box-shadow: none;\n}\n\n.update-btn:focus {\n    border: 2px solid #C3E3FF;\n    background-color: #EAEAEA;\n    color: #202020;\n    box-shadow: 0px 3px 6px rgba(148, 206, 255, 0.23);\n    padding: 3px 14px;\n}\n\n/*Warning Message in Update Bar*/\n#update-bar.warning, #update-bar.warning #close-icon-container {\n    background-color: #DA7A12;\n}\n\n.dark #update-bar.warning, .dark #update-bar.warning #close-icon-container {\n    background-color: #E6851A;\n}\n\n#update-bar.warning #icon-container #update-icon,\n#update-bar.error #icon-container #update-icon {\n    background: url(\"../images/alert.svg\") no-repeat 0 0;\n}\n\n/*Error message in Update Bar*/\n#update-bar.error, #update-bar.error #close-icon-container {\n    background-color: #D7373F;\n}\n\n.dark #update-bar.error, .dark #update-bar.error #close-icon-container{\n    background-color: #E4484F;\n}\n/*Success message in Update Bar*/\n#update-bar.success, #update-bar.success #close-icon-container {\n    background-color: #278E6B;\n}\n\n.dark #update-bar.success, .dark #update-bar.success #close-icon-container {\n    background-color: #2E9D77;\n}\n\n#update-bar.success #icon-container #update-icon{\n    background: url(\"../images/checkmarkcircle.svg\") no-repeat 0 0;\n}\n\n\n/*Overrides*/\n\n#status-indicators {\n    position: relative;\n    float: right;\n}\n"
  },
  {
    "path": "src/extensions/default/CSSAtRuleCodeHints/AtRulesDef.json",
    "content": "{\n    \"@charset\":             \"Defines the character set used by the style sheet.\",\n    \"@counter-style\":       \"Defines specific counter styles that are not part of the predefined set of styles.\",\n    \"@font-face\":           \"Describes the aspect of an external font to be downloaded.\",\n    \"@font-feature-values\": \"Defines common names in font-variant-alternates for feature activated differently in OpenType.\",\n    \"@import\":              \"Tells the CSS engine to include an external style sheet.\",\n    \"@keyframes\":           \"Describes the aspect of intermediate steps in a CSS animation sequence.\",\n    \"@media\":               \"A conditional group rule which will apply its content if the device meets the criteria of the condition defined using a media query.\",\n    \"@namespace\":           \"Tells the CSS engine that all its content must be considered prefixed with an XML namespace.\",\n    \"@page\":                \"Describes the aspect of layout changes which will be applied when printing the document.\",\n    \"@supports\":            \"A conditional group rule which will apply its content if the browser meets the criteria of the given condition.\"\n}\n"
  },
  {
    "path": "src/extensions/default/CSSAtRuleCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit         = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager = brackets.getModule(\"editor/CodeHintManager\"),\n        AtRulesText     = require(\"text!AtRulesDef.json\"),\n        AtRules         = JSON.parse(AtRulesText);\n\n\n    /**\n     * @constructor\n     */\n    function AtRuleHints() {\n    }\n\n    // As we are only going to provide @rules name hints\n    // we should claim that we don't have hints for anything else\n    AtRuleHints.prototype.hasHints = function (editor, implicitChar) {\n        var pos = editor.getCursorPos(),\n            token = editor._codeMirror.getTokenAt(pos),\n            cmState;\n\n        this.editor = editor;\n\n        if (token.state.base && token.state.base.localState) {\n            cmState = token.state.base.localState;\n        } else {\n            cmState = token.state.localState || token.state;\n        }\n\n        // Check if we are at '@' rule 'def' context\n        if ((token.type === \"def\" && cmState.context.type === \"at\")\n                || (token.type === \"variable-2\" && (cmState.context.type === \"top\" || cmState.context.type === \"block\"))) {\n            this.filter = token.string;\n            return true;\n        } else {\n            this.filter = null;\n            return false;\n        }\n    };\n\n    AtRuleHints.prototype.getHints = function (implicitChar) {\n        var pos     = this.editor.getCursorPos(),\n            token   = this.editor._codeMirror.getTokenAt(pos);\n\n        this.filter = token.string;\n        this.token = token;\n        \n        if (!this.filter) {\n            return null;\n        }\n\n        // Filter the property list based on the token string\n        var result = Object.keys(AtRules).filter(function (key) {\n            if (key.indexOf(token.string) === 0) {\n                return key;\n            }\n        }).sort();\n\n        return {\n            hints: result,\n            match: this.filter,\n            selectInitial: true,\n            defaultDescriptionWidth: true,\n            handleWideResults: false\n        };\n    };\n\n\n    /**\n     * Inserts a given @<rule> hint into the current editor context.\n     *\n     * @param {string} completion\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    AtRuleHints.prototype.insertHint = function (completion) {\n        var cursor = this.editor.getCursorPos();\n        this.editor.document.replaceRange(completion, {line: cursor.line, ch: this.token.start}, {line: cursor.line, ch: this.token.end});\n        return false;\n    };\n\n    AppInit.appReady(function () {\n        // Register code hint providers\n        var restrictedBlockHints = new AtRuleHints();\n        CodeHintManager.registerHintProvider(restrictedBlockHints, [\"css\", \"less\", \"scss\"], 0);\n        \n        // For unit testing\n        exports.restrictedBlockHints = restrictedBlockHints;\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/CSSAtRuleCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, xit, expect, beforeEach, afterEach */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils     = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        CSSAtRuleCodeHints  = require(\"main\");\n\n    describe(\"CSS '@' rules Code Hinting\", function () {\n\n        var defaultContent = \"@ { \\n\" +\n                             \"} \\n\" +\n                             \" \\n\" +\n                             \"@m \";\n                             \n\n        var testDocument, testEditor;\n\n        /*\n         * Create a mockup editor with the given content and language id.\n         *\n         * @param {string} content - content for test window\n         * @param {string} languageId\n         */\n        function setupTest(content, languageId) {\n            var mock = SpecRunnerUtils.createMockEditor(content, languageId);\n            testDocument = mock.doc;\n            testEditor = mock.editor;\n        }\n\n        function tearDownTest() {\n            SpecRunnerUtils.destroyMockEditor(testDocument);\n            testEditor = null;\n            testDocument = null;\n        }\n\n        // Ask provider for hints at current cursor position; expect it to return some\n        function expectHints(provider, implicitChar, returnWholeObj) {\n            expect(provider.hasHints(testEditor, implicitChar)).toBe(true);\n            var hintsObj = provider.getHints();\n            expect(hintsObj).toBeTruthy();\n            // return just the array of hints if returnWholeObj is falsy\n            return returnWholeObj ? hintsObj : hintsObj.hints;\n        }\n\n        // Ask provider for hints at current cursor position; expect it NOT to return any\n        function expectNoHints(provider, implicitChar) {\n            expect(provider.hasHints(testEditor, implicitChar)).toBe(false);\n        }\n\n        // compares lists to ensure they are the same\n        function verifyListsAreIdentical(hintList, values) {\n            var i;\n            expect(hintList.length).toBe(values.length);\n            for (i = 0; i < values.length; i++) {\n                expect(hintList[i]).toBe(values[i]);\n            }\n        }\n\n\n        function selectHint(provider, expectedHint, implicitChar) {\n            var hintList = expectHints(provider, implicitChar);\n            expect(hintList.indexOf(expectedHint)).not.toBe(-1);\n            return provider.insertHint(expectedHint);\n        }\n\n        // Helper function for testing cursor position\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n        function expectCursorAt(pos) {\n            var selection = testEditor.getSelection();\n            expect(fixPos(selection.start)).toEqual(fixPos(selection.end));\n            expect(fixPos(selection.start)).toEqual(fixPos(pos));\n        }\n        \n        function verifyFirstEntry(hintList, expectedFirstHint) {\n            expect(hintList[0]).toBe(expectedFirstHint);\n        }\n\n        // Helper function to\n        // a) ensure the hintList and the list with the available values have the same size\n        // b) ensure that all possible values are mentioned in the hintList\n        function verifyAllValues(hintList, values) {\n            expect(hintList.length).toBe(values.length);\n            expect(hintList.sort().toString()).toBe(values.sort().toString());\n        }\n        \n        \n        var modesToTest = ['css', 'scss', 'less'],\n            modeCounter;\n        \n        \n        var selectMode = function () {\n            return modesToTest[modeCounter];\n        };\n\n        describe(\"'@' rules in styles mode (selection of correct restricted block based on input)\", function () {\n\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, selectMode());\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n            \n            var testAllHints = function () {\n                    testEditor.setCursorPos({ line: 0, ch: 1 });    // after @\n                    var hintList = expectHints(CSSAtRuleCodeHints.restrictedBlockHints);\n                    verifyFirstEntry(hintList, \"@charset\");  // filtered on \"empty string\"\n                    verifyListsAreIdentical(hintList, [\"@charset\",\n                                                       \"@counter-style\",\n                                                       \"@font-face\",\n                                                       \"@font-feature-values\",\n                                                       \"@import\",\n                                                       \"@keyframes\",\n                                                       \"@media\",\n                                                       \"@namespace\",\n                                                       \"@page\",\n                                                       \"@supports\"]);\n                },\n                testFilteredHints = function () {\n                    testEditor.setCursorPos({ line: 3, ch: 2 });    // after @m\n                    var hintList = expectHints(CSSAtRuleCodeHints.restrictedBlockHints);\n                    verifyFirstEntry(hintList, \"@media\");  // filtered on \"@m\"\n                    verifyListsAreIdentical(hintList, [\"@media\"]);\n                },\n                testNoHintsOnSpace = function () {\n                    testEditor.setCursorPos({ line: 3, ch: 3 });    // after {\n                    expect(CSSAtRuleCodeHints.restrictedBlockHints.hasHints(testEditor, '')).toBe(false);\n                },\n                testNoHints = function () {\n                    testEditor.setCursorPos({ line: 0, ch: 0 });    // after {\n                    expect(CSSAtRuleCodeHints.restrictedBlockHints.hasHints(testEditor, 'c')).toBe(false);\n                };\n            \n            for (modeCounter in modesToTest) {\n                it(\"should list all rule hints right after @\", testAllHints);\n                it(\"should list filtered rule hints right after @m\", testFilteredHints);\n                it(\"should not list rule hints on space\", testNoHintsOnSpace);\n                it(\"should not list rule hints if the cursor is before @\", testNoHints);\n            }\n        });\n        \n        describe(\"'@' rules in LESS mode (selection of correct restricted block based on input)\", function () {\n            defaultContent = \"@ { \\n\" +\n                             \"} \\n\" +\n                             \" \\n\" +\n                             \"@m \\n\" +\n                             \"@green: green;\\n\" +\n                             \".div { \\n\" +\n                             \"color: @\" +\n                             \"} \\n\";\n\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"less\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n            \n            it(\"should not list rule hints in less variable evaluation scope\", function () {\n                testEditor.setCursorPos({ line: 3, ch: 3 });    // after {\n                expect(CSSAtRuleCodeHints.restrictedBlockHints.hasHints(testEditor, '')).toBe(false);\n            });\n            \n        });\n\n        describe(\"'@' rule hint insertion\", function () {\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"css\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should insert @rule selected\", function () {\n                testEditor.setCursorPos({ line: 0, ch: 1 });   // cursor after '@'\n                selectHint(CSSAtRuleCodeHints.restrictedBlockHints, \"@charset\");\n                expect(testDocument.getLine(0)).toBe(\"@charset { \");\n                expectCursorAt({ line: 0, ch: 8 });\n            });\n\n            it(\"should insert filtered selection by replacing the existing rule\", function () {\n                testEditor.setCursorPos({ line: 3, ch: 2 });   // cursor after '@m'\n                selectHint(CSSAtRuleCodeHints.restrictedBlockHints, \"@media\");\n                expect(testDocument.getLine(3)).toBe(\"@media \");\n                expectCursorAt({ line: 3, ch: 6 });\n            });\n        });\n\n    });\n});\n\n"
  },
  {
    "path": "src/extensions/default/CSSCodeHints/CSSProperties.json",
    "content": "{\n    \"align-content\":               {\"values\": [\"center\", \"flex-end\", \"flex-start\", \"space-around\", \"space-between\", \"stretch\"]},\n    \"align-items\":                 {\"values\": [\"baseline\", \"center\", \"flex-end\", \"flex-start\", \"stretch\"]},\n    \"align-self\":                  {\"values\": [\"auto\", \"baseline\", \"center\", \"flex-end\", \"flex-start\", \"stretch\"]},\n    \"all\":                         {\"values\": []},\n    \"animation\":                   {\"values\": []},\n    \"animation-delay\":             {\"values\": []},\n    \"animation-direction\":         {\"values\": [\"alternate\", \"alternate-reverse\", \"normal\", \"reverse\"]},\n    \"animation-duration\":          {\"values\": []},\n    \"animation-fill-mode\":         {\"values\": [\"backwards\", \"both\", \"forwards\", \"none\"]},\n    \"animation-iteration-count\":   {\"values\": [\"infinite\"]},\n    \"animation-name\":              {\"values\": [\"none\"]},\n    \"animation-play-state\":        {\"values\": [\"paused\", \"running\"]},\n    \"animation-timing-function\":   {\"values\": [\"cubic-bezier()\", \"ease\", \"ease-in\", \"ease-in-out\", \"ease-out\", \"linear\", \"step-end\", \"step-start\", \"steps()\"]},\n    \"backface-visibility\":         {\"values\": [\"hidden\", \"visible\"]},\n    \"background\":                  {\"values\": []},\n    \"background-attachment\":       {\"values\": [\"fixed\", \"local\", \"scroll\", \"inherit\"]},\n    \"background-blend-mode\":       {\"values\": [\"color\", \"color-burn\", \"color-dodge\", \"darken\", \"difference\", \"exclusion\", \"hard-light\", \"hue\", \"lighten\", \"luminosity\", \"multiply\", \"normal\", \"overlay\", \"saturation\", \"screen\", \"soft-light\"]},\n    \"background-clip\":             {\"values\": [\"border-box\", \"content-box\", \"padding-box\", \"inherit\"]},\n    \"background-color\":            {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"background-image\":            {\"values\": [\"image()\", \"linear-gradient()\", \"radial-gradient()\", \"repeating-linear-gradient()\", \"repeating-radial-gradient()\", \"url()\"]},\n    \"background-origin\":           {\"values\": [\"border-box\", \"content-box\", \"padding-box\", \"inherit\"]},\n    \"background-position\":         {\"values\": [\"left\", \"center\", \"right\", \"bottom\", \"top\"]},\n    \"background-repeat\":           {\"values\": [\"no-repeat\", \"repeat\", \"repeat-x\", \"repeat-y\", \"round\", \"space\"]},\n    \"background-size\":             {\"values\": [\"auto\", \"contain\", \"cover\"]},\n    \"border\":                      {\"values\": []},\n    \"border-collapse\":             {\"values\": [\"collapse\", \"separate\", \"inherit\"]},\n    \"border-color\":                {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"border-spacing\":              {\"values\": [\"inherit\"]},\n    \"border-style\":                {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"border-bottom\":               {\"values\": []},\n    \"border-bottom-color\":         {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"border-bottom-left-radius\":   {\"values\": []},\n    \"border-bottom-right-radius\":  {\"values\": []},\n    \"border-bottom-style\":         {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"border-bottom-width\":         {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"border-image\":                {\"values\": [ \"url()\" ]},\n    \"border-image-outset\":         {\"values\": []},\n    \"border-image-slice\":          {\"values\": []},\n    \"border-image-source\":         {\"values\": []},\n    \"border-image-repeat\":         {\"values\": [\"repeat\", \"round\", \"space\", \"stretch\"]},\n    \"border-image-width\":          {\"values\": [\"auto\"]},\n    \"border-left\":                 {\"values\": []},\n    \"border-left-color\":           {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"border-left-style\":           {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"border-left-width\":           {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"border-radius\":               {\"values\": []},\n    \"border-right\":                {\"values\": []},\n    \"border-right-color\":          {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"border-right-style\":          {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"border-right-width\":          {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"border-top\":                  {\"values\": []},\n    \"border-top-color\":            {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"border-top-left-radius\":      {\"values\": []},\n    \"border-top-right-radius\":     {\"values\": []},\n    \"border-top-style\":            {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"border-top-width\":            {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"border-width\":                {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"box-decoration-break\":        {\"values\": [\"clone\", \"slice\"]},\n    \"box-shadow\":                  {\"values\": []},\n    \"box-sizing\":                  {\"values\": [\"border-box\", \"content-box\", \"inherit\"]},\n    \"bottom\":                      {\"values\": [\"auto\", \"inherit\"]},\n    \"break-after\":                 {\"values\": [\"always\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\", \"column\", \"left\", \"page\", \"region\", \"right\"]},\n    \"break-before\":                {\"values\": [\"always\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\", \"column\", \"left\", \"page\", \"region\", \"right\"]},\n    \"break-inside\":                {\"values\": [\"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\"]},\n    \"caption-side\":                {\"values\": [\"bottom\", \"top\", \"inherit\"]},\n    \"caret-color\":                 {\"values\": [\"auto\"], \"type\": \"color\"},\n    \"clear\":                       {\"values\": [\"both\", \"left\", \"none\", \"right\", \"inherit\"]},\n    \"clip\":                        {\"values\": [\"auto\", \"inherit\"]},\n    \"color\":                       {\"values\": [\"inherit\"], \"type\": \"color\"},\n    \"columns\":                     {\"values\": []},\n    \"column-count\":                {\"values\": []},\n    \"column-fill\":                 {\"values\": [\"auto\", \"balance\"]},\n    \"column-gap\":                  {\"values\": [\"normal\"]},\n    \"column-rule\":                 {\"values\": []},\n    \"column-rule-color\":           {\"values\": [], \"type\": \"color\"},\n    \"column-rule-style\":           {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"column-rule-width\":           {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"column-span\":                 {\"values\": [\"all\", \"none\"]},\n    \"column-width\":                {\"values\": [\"auto\", \"inherit\"]},\n    \"content\":                     {\"values\": [\"attr()\", \"close-quote\", \"no-close-quote\", \"no-open-quote\", \"normal\", \"none\", \"open-quote\", \"inherit\"]},\n    \"counter-increment\":           {\"values\": [\"none\", \"inherit\"]},\n    \"counter-reset\":               {\"values\": [\"none\", \"inherit\"]},\n    \"cursor\":                      {\"values\": [\"alias\", \"all-scroll\", \"auto\", \"cell\", \"col-resize\", \"context-menu\", \"copy\", \"crosshair\", \"default\", \"e-resize\", \"ew-resize\", \"grab\", \"grabbing\", \"help\", \"inherit\", \"move\", \"n-resize\", \"ne-resize\", \"nesw-resize\", \"no-drop\", \"none\", \"not-allowed\", \"ns-resize\", \"nw-resize\", \"nwse-resize\", \"pointer\", \"progress\", \"row-resize\", \"s-resize\", \"se-resize\", \"sw-resize\", \"text\", \"vertical-text\", \"w-resize\", \"wait\", \"zoom-in\", \"zoom-out\"]},\n    \"direction\":                   {\"values\": [\"ltr\", \"rtl\", \"inherit\"]},\n    \"display\":                     {\"values\": [\"block\", \"contents\", \"flex\", \"flow-root\", \"grid\", \"inline\", \"inline-block\", \"inline-flex\", \"inline-grid\", \"inline-table\", \"list-item\", \"none\", \"run-in\", \"subgrid\", \"table\", \"table-caption\", \"table-cell\", \"table-column\", \"table-column-group\", \"table-footer-group\", \"table-header-group\", \"table-row\", \"table-row-group\", \"inherit\"]},\n    \"empty-cells\":                 {\"values\": [\"hide\", \"show\", \"inherit\"]},\n    \"filter\":                      {\"values\": [\"blur()\", \"brightness()\", \"contrast()\", \"custom()\", \"drop-shadow()\", \"grayscale()\", \"hue-rotate()\", \"invert()\", \"none\", \"opacity()\", \"sepia()\", \"saturate()\", \"url()\"]},\n    \"flex\":                        {\"values\": [\"auto\", \"initial\", \"none\"]},\n    \"flex-basis\":                  {\"values\": [\"auto\"]},\n    \"flex-direction\":              {\"values\": [\"column\", \"column-reverse\", \"row\", \"row-reverse\"]},\n    \"flex-flow\":                   {\"values\": [\"column\", \"column-reverse\", \"nowrap\", \"row\", \"row-reverse\", \"wrap\", \"wrap-reverse\"]},\n    \"flex-grow\":                   {\"values\": []},\n    \"flex-shrink\":                 {\"values\": []},\n    \"flex-wrap\":                   {\"values\": [\"nowrap\", \"wrap\", \"wrap-reverse\"]},\n    \"float\":                       {\"values\": [\"left\", \"right\", \"none\", \"inherit\"]},\n    \"flow-into\":                   {\"values\": [\"none\"], \"type\": \"named-flow\"},\n    \"flow-from\":                   {\"values\": [\"none\", \"inherit\"], \"type\": \"named-flow\"},\n    \"font\":                        {\"values\": []},\n    \"font-display\":                {\"values\": [\"auto\", \"block\", \"swap\", \"fallback\", \"optional\"]},\n    \"font-family\":                 {\"values\": [\"cursive\", \"fantasy\", \"inherit\", \"monospace\", \"sans-serif\", \"serif\"]},\n    \"font-feature-settings\":       {\"values\": [\"normal\"]},\n    \"font-kerning\":                {\"values\": [\"auto\", \"none\", \"normal\"]},\n    \"font-language-override\":      {\"values\": [\"normal\"]},\n    \"font-size\":                   {\"values\": []},\n    \"font-size-adjust\":            {\"values\": [\"auto\", \"none\"]},\n    \"font-stretch\":                {\"values\": [\"condensed\", \"expanded\", \"extra-condensed\", \"extra-expanded\", \"normal\", \"semi-condensed\", \"semi-expanded\", \"ultra-condensed\", \"ultra-expanded\"]},\n    \"font-style\":                  {\"values\": [\"italic\", \"normal\", \"oblique\"]},\n    \"font-synthesis\":              {\"values\": [\"none\", \"style\", \"weight\"]},\n    \"font-variant\":                {\"values\": [\"normal\", \"small-caps\", \"inherit\"]},\n    \"font-variant-alternates\":     {\"values\": [\"normal\"]},\n    \"font-variant-caps\":           {\"values\": [\"normal\", \"small-caps\", \"all-small-caps\", \"petite-caps\", \"all-petite-caps\", \"unicase\", \"titling-caps\"]},\n    \"font-variant-east-asian\":     {\"values\": [\"normal\"]},\n    \"font-variant-ligatures\":      {\"values\": [\"normal\", \"none\"]},\n    \"font-variant-numeric\":        {\"values\": [\"normal\"]},\n    \"font-variant-position\":       {\"values\": [\"normal\", \"sub\", \"super\"]},\n    \"font-weight\":                 {\"values\": [\"bold\", \"bolder\", \"lighter\", \"normal\", \"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\", \"inherit\"]},\n    \"grid\":                        {\"values\": []},\n    \"grid-area\":                   {\"values\": []},\n    \"grid-auto-columns\":           {\"values\": []},\n    \"grid-auto-flow\":              {\"values\": [\"row\", \"column\", \"dense\"]},\n    \"grid-auto-rows\":              {\"values\": []},\n    \"grid-column\":                 {\"values\": [\"auto\"]},\n    \"grid-column-end\":             {\"values\": []},\n    \"grid-column-gap\":             {\"values\": []},\n    \"grid-column-start\":           {\"values\": []},\n    \"grid-gap\":                    {\"values\": []},\n    \"grid-row\":                    {\"values\": [\"auto\"]},\n    \"grid-row-end\":                {\"values\": []},\n    \"grid-row-start\":              {\"values\": []},\n    \"grid-row-gap\":                {\"values\": []},\n    \"grid-template\":               {\"values\": [\"none\"]},\n    \"grid-template-areas\":         {\"values\": []},\n    \"grid-template-columns\":       {\"values\": [\"auto\"]},\n    \"grid-template-rows\":          {\"values\": [\"auto\"]},\n    \"hanging-punctuation\":         {\"values\": [\"allow-end\", \"first\", \"force-end\", \"last\", \"none\"]},\n    \"height\":                      {\"values\": [\"auto\", \"inherit\"]},\n    \"hyphens\":                     {\"values\": [\"auto\", \"manual\", \"none\"]},\n    \"image-orientation\":           {\"values\": []},\n    \"image-resolution\":            {\"values\": [\"from-image\", \"snap\"]},\n    \"isolation\":                   {\"values\": [\"auto\", \"isolate\"]},\n    \"justify-content\":             {\"values\": [\"center\", \"flex-end\", \"flex-start\", \"space-around\", \"space-between\"]},\n    \"justify-items\":               {\"values\": [\"auto\", \"normal\", \"stretch\", \"center\", \"start\", \"end\", \"flex-start\", \"flex-end\", \"self-start\", \"self-end\", \"left\", \"right\", \"baseline\", \"first\", \"last\", \"safe\", \"unsafe\", \"legacy\", \"inherit\", \"initial\"]},\n    \"justify-self\":                {\"values\": [\"auto\", \"normal\", \"stretch\", \"center\", \"start\", \"end\", \"flex-start\", \"flex-end\", \"self-start\", \"self-end\", \"left\", \"right\", \"baseline\", \"first\", \"last\", \"safe\", \"unsafe\", \"inherit\", \"initial\"]},\n    \"left\":                        {\"values\": [\"auto\", \"inherit\"]},\n    \"letter-spacing\":              {\"values\": [\"normal\", \"inherit\"]},\n    \"line-height\":                 {\"values\": [\"normal\", \"inherit\"]},\n    \"list-style\":                  {\"values\": [\"none\", \"inherit\", \"initial\", \"unset\", \"url()\", \"armenian\", \"circle\", \"decimal\", \"decimal-leading-zero\", \"disc\", \"georgian\", \"inside\", \"lower-alpha\", \"lower-greek\", \"lower-latin\", \"lower-roman\", \"outside\", \"square\", \"upper-alpha\", \"upper-latin\", \"upper-roman\"]},\n    \"list-style-image\":            {\"values\": [\"none\", \"url()\", \"inherit\"]},\n    \"list-style-position\":         {\"values\": [\"inside\", \"outside\", \"inherit\"]},\n    \"list-style-type\":             {\"values\": [\"armenian\", \"circle\", \"decimal\", \"decimal-leading-zero\", \"disc\", \"georgian\", \"lower-alpha\", \"lower-greek\", \"lower-latin\", \"lower-roman\", \"none\", \"square\", \"upper-alpha\", \"upper-latin\", \"upper-roman\", \"inherit\"]},\n    \"margin\":                      {\"values\": [\"auto\", \"inherit\"]},\n    \"margin-bottom\":               {\"values\": [\"auto\", \"inherit\"]},\n    \"margin-left\":                 {\"values\": [\"auto\", \"inherit\"]},\n    \"margin-right\":                {\"values\": [\"auto\", \"inherit\"]},\n    \"margin-top\":                  {\"values\": [\"auto\", \"inherit\"]},\n    \"max-height\":                  {\"values\": [\"none\", \"inherit\"]},\n    \"max-width\":                   {\"values\": [\"none\", \"inherit\"]},\n    \"min-height\":                  {\"values\": [\"inherit\"]},\n    \"min-width\":                   {\"values\": [\"inherit\"]},\n    \"mix-blend-mode\":              {\"values\": [\"color\", \"color-burn\", \"color-dodge\", \"darken\", \"difference\", \"exclusion\", \"hard-light\", \"hue\", \"lighten\", \"luminosity\", \"multiply\", \"normal\", \"overlay\", \"saturation\", \"screen\", \"soft-light\"]},\n    \"object-fit\":                  {\"values\": [\"contain\", \"cover\", \"fill\", \"none\", \"scale-down\"]},\n    \"object-position\":             {\"values\": [\"left\", \"center\", \"right\", \"bottom\", \"top\"]},\n    \"opacity\":                     {\"values\": [\"inherit\"]},\n    \"order\":                       {\"values\": []},\n    \"orphans\":                     {\"values\": [\"inherit\"]},\n    \"outline\":                     {\"values\": [\"inherit\"]},\n    \"outline-color\":               {\"values\": [\"invert\", \"inherit\"], \"type\": \"color\"},\n    \"outline-offset\":              {\"values\": [\"inherit\"]},\n    \"outline-style\":               {\"values\": [\"dashed\", \"dotted\", \"double\", \"groove\", \"hidden\", \"inset\", \"none\", \"outset\", \"ridge\", \"solid\", \"inherit\"]},\n    \"outline-width\":               {\"values\": [\"medium\", \"thin\", \"thick\", \"inherit\"]},\n    \"overflow\":                    {\"values\": [\"auto\", \"hidden\", \"scroll\", \"visible\", \"inherit\"]},\n    \"overflow-x\":                  {\"values\": [\"auto\", \"hidden\", \"scroll\", \"visible\", \"inherit\"]},\n    \"overflow-y\":                  {\"values\": [\"auto\", \"hidden\", \"scroll\", \"visible\", \"inherit\"]},\n    \"padding\":                     {\"values\": [\"inherit\"]},\n    \"padding-bottom\":              {\"values\": []},\n    \"padding-left\":                {\"values\": []},\n    \"padding-right\":               {\"values\": []},\n    \"padding-top\":                 {\"values\": []},\n    \"page-break-after\":            {\"values\": [\"always\", \"auto\", \"avoid\", \"left\", \"right\", \"inherit\"]},\n    \"page-break-before\":           {\"values\": [\"always\", \"auto\", \"avoid\", \"left\", \"right\", \"inherit\"]},\n    \"page-break-inside\":           {\"values\": [\"auto\", \"avoid\", \"inherit\"]},\n    \"perspective\":                 {\"values\": [\"none\"]},\n    \"perspective-origin\":          {\"values\": [\"bottom\", \"center\", \"left\", \"right\", \"top\"]},\n    \"pointer-events\":              {\"values\": [\"all\", \"auto\", \"fill\", \"inherit\", \"none\", \"painted\", \"stroke\", \"visible\", \"visibleFill\", \"visiblePainted\", \"visibleStroke\"]},\n    \"position\":                    {\"values\": [\"absolute\", \"fixed\", \"relative\", \"static\", \"sticky\", \"inherit\"]},\n    \"quotes\":                      {\"values\": [\"none\", \"inherit\"]},\n    \"region-break-after\":          {\"values\": [\"always\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\", \"column\", \"left\", \"page\", \"region\", \"right\"]},\n    \"region-break-before\":         {\"values\": [\"always\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\", \"column\", \"left\", \"page\", \"region\", \"right\"]},\n    \"region-break-inside\":         {\"values\": [\"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\"]},\n    \"region-fragment\":             {\"values\": [\"auto\", \"break\"]},\n    \"resize\":                      {\"values\": [\"both\", \"horizontal\", \"none\", \"vertical\", \"inherit\"]},\n    \"right\":                       {\"values\": [\"auto\", \"inherit\"]},\n    \"scroll-behavior\":             {\"values\": [\"auto\", \"smooth\"]},\n    \"scroll-snap-type\":            {\"values\": [\"none\", \"x\", \"y\", \"block\", \"inline\", \"both\", \"mandatory\", \"proximity\"]},\n    \"src\":                         {\"values\": [ \"url()\"]},\n    \"shape-image-threshold\":       {\"values\": []},\n    \"shape-inside\":                {\"values\": [\"auto\", \"circle()\", \"ellipse()\", \"inherit\", \"outside-shape\", \"polygon()\", \"rectangle()\"]},\n    \"shape-margin\":                {\"values\": []},\n    \"shape-outside\":               {\"values\": [\"none\", \"inherit\", \"circle()\", \"ellipse()\", \"polygon()\", \"inset()\", \"margin-box\", \"border-box\", \"padding-box\", \"content-box\", \"url()\", \"image()\", \"linear-gradient()\", \"radial-gradient()\", \"repeating-linear-gradient()\", \"repeating-radial-gradient()\"]},\n    \"tab-size\":                    {\"values\": []},\n    \"table-layout\":                {\"values\": [\"auto\", \"fixed\", \"inherit\"]},\n    \"text-align\":                  {\"values\": [\"start\", \"end\", \"center\", \"left\", \"justify\", \"right\", \"match-parent\", \"justify-all\", \"inherit\"]},\n    \"text-align-last\":             {\"values\": [\"center\", \"left\", \"justify\", \"right\", \"inherit\"]},\n    \"text-decoration\":             {\"values\": [\"line-through\", \"none\", \"overline\", \"underline\", \"inherit\"]},\n    \"text-decoration-color\":       {\"values\": [], \"type\": \"color\"},\n    \"text-decoration-line\":        {\"values\": [\"line-through\", \"none\", \"overline\", \"underline\"]},\n    \"text-decoration-skip\":        {\"values\": [\"edges\", \"ink\", \"none\", \"objects\", \"spaces\"]},\n    \"text-decoration-style\":       {\"values\": [\"dashed\", \"dotted\", \"double\", \"solid\", \"wavy\"]},\n    \"text-emphasis\":               {\"values\": []},\n    \"text-emphasis-color\":         {\"values\": [], \"type\": \"color\"},\n    \"text-emphasis-position\":      {\"values\": [\"above\", \"below\", \"left\", \"right\"]},\n    \"text-emphasis-style\":         {\"values\": [\"circle\", \"dot\", \"double-circle\", \"filled\", \"none\", \"open\", \"sesame\", \"triangle\"]},\n    \"text-indent\":                 {\"values\": [\"inherit\"]},\n    \"text-justify\":                {\"values\": [\"auto\", \"none\", \"inter-word\", \"inter-character\", \"inherit\"]},\n    \"text-overflow\":               {\"values\": [\"clip\", \"ellipsis\", \"inherit\"]},\n    \"text-shadow\":                 {\"values\": []},\n    \"text-rendering\":              {\"values\": [\"auto\", \"geometricPrecision\", \"optimizeLegibility\", \"optimizeSpeed\"]},\n    \"text-transform\":              {\"values\": [\"capitalize\", \"full-width\", \"lowercase\", \"none\", \"uppercase\", \"inherit\"]},\n    \"text-underline-position\":     {\"values\": [\"alphabetic\", \"auto\", \"below\", \"left\", \"right\"]},\n    \"top\":                         {\"values\": [\"auto\", \"inherit\"]},\n    \"transform\":                   {\"values\": [\"matrix()\", \"matrix3d()\", \"none\", \"perspective()\", \"rotate()\", \"rotate3d()\", \"rotateX()\", \"rotateY()\", \"rotateZ()\", \"scale()\", \"scale3d()\", \"scaleX()\", \"scaleY()\", \"scaleZ()\", \"skewX()\", \"skewY()\", \"translate()\", \"translate3d()\", \"translateX()\", \"translateY()\", \"translateZ()\"]},\n    \"transform-origin\":            {\"values\": [\"bottom\", \"center\", \"left\", \"right\", \"top\"]},\n    \"transform-style\":             {\"values\": [\"flat\", \"preserve-3d\"]},\n    \"transition\":                  {\"values\": []},\n    \"transition-delay\":            {\"values\": []},\n    \"transition-duration\":         {\"values\": []},\n    \"transition-property\":         {\"values\": [\"all\", \"none\"]},\n    \"transition-timing-function\":  {\"values\": [\"cubic-bezier()\", \"ease\", \"ease-in\", \"ease-in-out\", \"ease-out\", \"linear\", \"step-end\", \"step-start\", \"steps()\"]},\n    \"unicode-bidi\":                {\"values\": [\"bidi-override\", \"embed\", \"normal\", \"inherit\"]},\n    \"unicode-range\":               {\"values\": []},\n    \"user-select\":                 {\"values\": [\"all\", \"auto\", \"contain\", \"none\", \"text\"]},\n    \"vertical-align\":              {\"values\": [\"baseline\", \"bottom\", \"middle\", \"sub\", \"super\", \"text-bottom\", \"text-top\", \"top\", \"inherit\"]},\n    \"visibility\":                  {\"values\": [\"collapse\", \"hidden\", \"visible\", \"inherit\"]},\n    \"white-space\":                 {\"values\": [\"normal\", \"nowrap\", \"pre\", \"pre-line\", \"pre-wrap\", \"inherit\"]},\n    \"widows\":                      {\"values\": [\"inherit\"]},\n    \"width\":                       {\"values\": [\"auto\", \"inherit\"]},\n    \"will-change\":                 {\"values\": [\"auto\", \"contents\", \"opacity\", \"scroll-position\", \"transform\", \"inherit\", \"initial\", \"unset\"]},\n    \"word-break\":                  {\"values\": [\"normal\", \"break-all\", \"keep-all\"]},\n    \"word-spacing\":                {\"values\": [\"normal\", \"inherit\"]},\n    \"word-wrap\":                   {\"values\": [\"break-word\", \"normal\"]},\n    \"z-index\":                     {\"values\": [\"auto\", \"inherit\"]}\n}\n"
  },
  {
    "path": "src/extensions/default/CSSCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        CSSUtils            = brackets.getModule(\"language/CSSUtils\"),\n        HTMLUtils           = brackets.getModule(\"language/HTMLUtils\"),\n        LanguageManager     = brackets.getModule(\"language/LanguageManager\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        TokenUtils          = brackets.getModule(\"utils/TokenUtils\"),\n        StringMatch         = brackets.getModule(\"utils/StringMatch\"),\n        ColorUtils          = brackets.getModule(\"utils/ColorUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        CSSProperties       = require(\"text!CSSProperties.json\"),\n        properties          = JSON.parse(CSSProperties);\n\n\n    PreferencesManager.definePreference(\"codehint.CssPropHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_CSS_PROP_HINTS\n    });\n\n    // Context of the last request for hints: either CSSUtils.PROP_NAME,\n    // CSSUtils.PROP_VALUE or null.\n    var lastContext,\n        stringMatcherOptions = { preferPrefixMatches: true };\n\n    /**\n     * @constructor\n     */\n    function CssPropHints() {\n        this.primaryTriggerKeys = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-()\";\n        this.secondaryTriggerKeys = \":\";\n        this.exclusion = null;\n    }\n\n    /**\n     * Get the CSS style text of the file open in the editor for this hinting session.\n     * For a CSS file, this is just the text of the file. For an HTML file,\n     * this will be only the text in the <style> tags.\n     *\n     * @return {string} the \"css\" text that can be sent to CSSUtils to extract all named flows.\n     */\n    CssPropHints.prototype.getCssStyleText = function () {\n        if (LanguageManager.getLanguageForPath(this.editor.document.file.fullPath).getId() === \"html\") {\n            // Collect text in all style blocks\n            var text = \"\",\n                styleBlocks = HTMLUtils.findBlocks(this.editor, \"css\");\n\n            styleBlocks.forEach(function (styleBlock) {\n                text += styleBlock.text;\n            });\n\n            return text;\n        } else {\n            // css file, just return the text\n            return this.editor.document.getText();\n        }\n    };\n\n    /**\n     * Extract all the named flows from any \"flow-from\" or \"flow-into\" properties\n     * in the current document. If we have the cached list of named flows and the\n     * cursor is still on the same line as the cached cursor, then the cached list\n     * is returned. Otherwise, we recollect all named flows and update the cache.\n     *\n     * @return {Array.<string>} All named flows available in the current document.\n     */\n    CssPropHints.prototype.getNamedFlows = function () {\n        if (this.namedFlowsCache) {\n            // If the cursor is no longer on the same line, then the cache is stale.\n            // Delete cache so we can extract all named flows again.\n            if (this.namedFlowsCache.cursor.line !== this.cursor.line) {\n                this.namedFlowsCache = null;\n            }\n        }\n\n        if (!this.namedFlowsCache) {\n            this.namedFlowsCache = {};\n            this.namedFlowsCache.flows = CSSUtils.extractAllNamedFlows(this.getCssStyleText());\n            this.namedFlowsCache.cursor = { line: this.cursor.line, ch: this.cursor.ch };\n        }\n\n        return this.namedFlowsCache.flows;\n    };\n\n    /**\n     * Check whether the exclusion is still the same as text after the cursor.\n     * If not, reset it to null.\n     *\n     * @param {boolean} propNameOnly\n     * true to indicate that we update the exclusion only if the cursor is inside property name context.\n     * Otherwise, we also update exclusion for property value context.\n     */\n    CssPropHints.prototype.updateExclusion = function (propNameOnly) {\n        var textAfterCursor;\n        if (this.exclusion && this.info) {\n            if (this.info.context === CSSUtils.PROP_NAME) {\n                textAfterCursor = this.info.name.substr(this.info.offset);\n            } else if (!propNameOnly && this.info.context === CSSUtils.PROP_VALUE) {\n                textAfterCursor = this.info.value.substr(this.info.offset);\n            }\n            if (!CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                this.exclusion = null;\n            }\n        }\n    };\n\n    /**\n     * Determines whether CSS propertyname or -name hints are available in the current editor\n     * context.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {String} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {Boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non- null,\n     * whether it is appropriate to do so.\n     */\n    CssPropHints.prototype.hasHints = function (editor, implicitChar) {\n        this.editor = editor;\n        var cursor = this.editor.getCursorPos();\n\n        lastContext = null;\n        this.info = CSSUtils.getInfoAtPos(editor, cursor);\n\n        if (this.info.context !== CSSUtils.PROP_NAME && this.info.context !== CSSUtils.PROP_VALUE) {\n            return false;\n        }\n\n        if (implicitChar) {\n            this.updateExclusion(false);\n            if (this.info.context === CSSUtils.PROP_NAME) {\n                // Check if implicitChar is the first character typed before an existing property name.\n                if (!this.exclusion && this.info.offset === 1 && implicitChar === this.info.name[0]) {\n                    this.exclusion = this.info.name.substr(this.info.offset);\n                }\n            }\n\n            return (this.primaryTriggerKeys.indexOf(implicitChar) !== -1) ||\n                   (this.secondaryTriggerKeys.indexOf(implicitChar) !== -1);\n        } else if (this.info.context === CSSUtils.PROP_NAME) {\n            if (this.info.offset === 0) {\n                this.exclusion = this.info.name;\n            } else {\n                this.updateExclusion(true);\n            }\n        }\n\n        return true;\n    };\n\n    /**\n     * Returns a sorted and formatted list of hints with the query substring\n     * highlighted.\n     *\n     * @param {Array.<Object>} hints - the list of hints to format\n     * @param {string} query - querystring used for highlighting matched\n     *      portions of each hint\n     * @return {Array.jQuery} sorted Array of jQuery DOM elements to insert\n     */\n    function formatHints(hints, query) {\n        var hasColorSwatch = hints.some(function (token) {\n            return token.color;\n        });\n\n        StringMatch.basicMatchSort(hints);\n        return hints.map(function (token) {\n            var $hintObj = $(\"<span>\").addClass(\"brackets-css-hints\");\n\n            // highlight the matched portion of each hint\n            if (token.stringRanges) {\n                token.stringRanges.forEach(function (item) {\n                    if (item.matched) {\n                        $hintObj.append($(\"<span>\")\n                            .text(item.text)\n                            .addClass(\"matched-hint\"));\n                    } else {\n                        $hintObj.append(item.text);\n                    }\n                });\n            } else {\n                $hintObj.text(token.value);\n            }\n\n            if (hasColorSwatch) {\n                $hintObj = ColorUtils.formatColorHint($hintObj, token.color);\n            }\n\n            return $hintObj;\n        });\n    }\n\n    /**\n     * Returns a list of availble CSS propertyname or -value hints if possible for the current\n     * editor context.\n     *\n     * @param {Editor} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {jQuery.Deferred|{\n     *              hints: Array.<string|jQueryObject>,\n     *              match: string,\n     *              selectInitial: boolean,\n     *              handleWideResults: boolean}}\n     * Null if the provider wishes to end the hinting session. Otherwise, a\n     * response object that provides:\n     * 1. a sorted array hints that consists of strings\n     * 2. a string match that is used by the manager to emphasize matching\n     *    substrings when rendering the hint list\n     * 3. a boolean that indicates whether the first result, if one exists,\n     *    should be selected by default in the hint list window.\n     * 4. handleWideResults, a boolean (or undefined) that indicates whether\n     *    to allow result string to stretch width of display.\n     */\n    CssPropHints.prototype.getHints = function (implicitChar) {\n        this.cursor = this.editor.getCursorPos();\n        this.info = CSSUtils.getInfoAtPos(this.editor, this.cursor);\n\n        var needle = this.info.name,\n            valueNeedle = \"\",\n            context = this.info.context,\n            valueArray,\n            type,\n            namedFlows,\n            result,\n            selectInitial = false;\n\n        // Clear the exclusion if the user moves the cursor with left/right arrow key.\n        this.updateExclusion(true);\n\n        if (context === CSSUtils.PROP_VALUE) {\n\n            // Always select initial value\n            selectInitial = true;\n\n            // We need to end the session and begin a new session if the ( char is typed to\n            // get arguments into the list when typing too fast\n            if (implicitChar === \"(\") {\n                return true;\n            }\n\n            // When switching from a NAME to a VALUE context, restart the session\n            // to give other more specialized providers a chance to intervene.\n            if (lastContext === CSSUtils.PROP_NAME) {\n                return true;\n            } else {\n                lastContext = CSSUtils.PROP_VALUE;\n            }\n\n            if (!properties[needle]) {\n                return null;\n            }\n\n            // Cursor is in an existing property value or partially typed value\n            if (!this.info.isNewItem && this.info.index !== -1) {\n                valueNeedle = this.info.values[this.info.index].trim();\n                valueNeedle = valueNeedle.substr(0, this.info.offset);\n            }\n\n            valueArray = properties[needle].values;\n            type = properties[needle].type;\n            if (type === \"named-flow\") {\n                namedFlows = this.getNamedFlows();\n\n                if (valueNeedle.length === this.info.offset && namedFlows.indexOf(valueNeedle) !== -1) {\n                    // Exclude the partially typed named flow at cursor since it\n                    // is not an existing one used in other css rule.\n                    namedFlows.splice(namedFlows.indexOf(valueNeedle), 1);\n                }\n\n                valueArray = valueArray.concat(namedFlows);\n            } else if (type === \"color\") {\n                valueArray = valueArray.concat(ColorUtils.COLOR_NAMES.map(function (color) {\n                    return { text: color, color: color };\n                }));\n                valueArray.push(\"transparent\", \"currentColor\");\n            }\n\n            result = $.map(valueArray, function (pvalue) {\n                var result = StringMatch.stringMatch(pvalue.text || pvalue, valueNeedle, stringMatcherOptions);\n                if (result) {\n                    if (pvalue.color) {\n                        result.color = pvalue.color;\n                    }\n\n                    return result;\n                }\n            });\n\n            return {\n                hints: formatHints(result, valueNeedle),\n                match: null, // the CodeHintManager should not format the results\n                selectInitial: selectInitial\n            };\n        } else if (context === CSSUtils.PROP_NAME) {\n\n            // Select initial property if anything has been typed\n            if (this.primaryTriggerKeys.indexOf(implicitChar) !== -1 || needle !== \"\") {\n                selectInitial = true;\n            }\n\n            if (lastContext === CSSUtils.PROP_VALUE) {\n                // close the session if we're coming from a property value\n                // see https://github.com/adobe/brackets/issues/9496\n                return null;\n            }\n\n            lastContext = CSSUtils.PROP_NAME;\n            needle = needle.substr(0, this.info.offset);\n\n            result = $.map(properties, function (pvalues, pname) {\n                var result = StringMatch.stringMatch(pname, needle, stringMatcherOptions);\n                if (result) {\n                    return result;\n                }\n            });\n\n            return {\n                hints: formatHints(result, needle),\n                match: null, // the CodeHintManager should not format the results\n                selectInitial: selectInitial,\n                handleWideResults: false\n            };\n        }\n        return null;\n    };\n\n    /**\n     * Inserts a given CSS protertyname or -value hint into the current editor context.\n     *\n     * @param {String} hint\n     * The hint to be inserted into the editor context.\n     *\n     * @return {Boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    CssPropHints.prototype.insertHint = function (hint) {\n        var offset = this.info.offset,\n            cursor = this.editor.getCursorPos(),\n            start = {line: -1, ch: -1},\n            end = {line: -1, ch: -1},\n            keepHints = false,\n            adjustCursor = false,\n            newCursor,\n            ctx;\n\n        if (hint.jquery) {\n            hint = hint.text();\n        }\n\n        if (this.info.context !== CSSUtils.PROP_NAME && this.info.context !== CSSUtils.PROP_VALUE) {\n            return false;\n        }\n\n        start.line = end.line = cursor.line;\n        start.ch = cursor.ch - offset;\n\n        if (this.info.context === CSSUtils.PROP_NAME) {\n            keepHints = true;\n            var textAfterCursor = this.info.name.substr(this.info.offset);\n            if (this.info.name.length === 0 || CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                // It's a new insertion, so append a colon and set keepHints\n                // to show property value hints.\n                hint += \": \";\n                end.ch = start.ch;\n                end.ch += offset;\n\n                if (this.exclusion) {\n                    // Append a space to the end of hint to insert and then adjust\n                    // the cursor before that space.\n                    hint += \" \";\n                    adjustCursor = true;\n                    newCursor = { line: cursor.line,\n                                  ch: start.ch + hint.length - 1 };\n                    this.exclusion = null;\n                }\n            } else {\n                // It's a replacement of an existing one or just typed in property.\n                // So we need to check whether there is an existing colon following\n                // the current property name. If a colon already exists, then we also\n                // adjust the cursor position and show code hints for property values.\n                end.ch = start.ch + this.info.name.length;\n                ctx = TokenUtils.getInitialContext(this.editor._codeMirror, cursor);\n                if (ctx.token.string.length > 0 && !/\\S/.test(ctx.token.string)) {\n                    // We're at the very beginning of a property name. So skip it\n                    // before we locate the colon following it.\n                    TokenUtils.moveNextToken(ctx);\n                }\n                if (TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) && ctx.token.string === \":\") {\n                    adjustCursor = true;\n                    newCursor = { line: cursor.line,\n                                  ch: cursor.ch + (hint.length - this.info.name.length) };\n                    // Adjust cursor to the position after any whitespace that follows the colon, if there is any.\n                    if (TokenUtils.moveNextToken(ctx) && ctx.token.string.length > 0 && !/\\S/.test(ctx.token.string)) {\n                        newCursor.ch += ctx.token.string.length;\n                    }\n                } else {\n                    hint += \": \";\n                }\n            }\n        } else {\n            if (!this.info.isNewItem && this.info.index !== -1) {\n                // Replacing an existing property value or partially typed value\n                end.ch = start.ch + this.info.values[this.info.index].length;\n            } else {\n                // Inserting a new property value\n                end.ch = start.ch;\n            }\n\n            var parenMatch = hint.match(/\\(.*?\\)/);\n            if (parenMatch) {\n                // value has (...), so place cursor inside opening paren\n                // and keep hints open\n                adjustCursor = true;\n                newCursor = { line: cursor.line,\n                              ch: start.ch + parenMatch.index + 1 };\n                keepHints = true;\n            }\n        }\n\n        // HACK (tracking adobe/brackets#1688): We talk to the private CodeMirror instance\n        // directly to replace the range instead of using the Document, as we should. The\n        // reason is due to a flaw in our current document synchronization architecture when\n        // inline editors are open.\n        this.editor._codeMirror.replaceRange(hint, start, end);\n\n        if (adjustCursor) {\n            this.editor.setCursorPos(newCursor);\n        }\n\n        return keepHints;\n    };\n\n    AppInit.appReady(function () {\n        var cssPropHints = new CssPropHints();\n        CodeHintManager.registerHintProvider(cssPropHints, [\"css\", \"scss\", \"less\"], 1);\n\n        ExtensionUtils.loadStyleSheet(module, \"styles/brackets-css-hints.css\");\n\n        // For unit testing\n        exports.cssPropHintProvider = cssPropHints;\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/CSSCodeHints/styles/brackets-css-hints.css",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n.brackets-css-hints .matched-hint {\n    font-weight: 500;\n}\n\n.dark .brackets-css-hints .matched-hint {\n    color: #ccc;\n}\n"
  },
  {
    "path": "src/extensions/default/CSSCodeHints/unittest-files/region-template.html",
    "content": "<element name=\"x-formatting-example\" extends=\"body\">\n  <template>\n    <style>\n      article {\n          flow-into: article;\n      }\n\n      #rA, #rB, #rC {\n          height: auto;\n\n          margin: 1em 1em 0em 1em;\n          padding: 1em;\n          border: 3px solid #46A4E9;\n      }\n\n      #rA {\n          width: auto;\n      }\n\n      #rB {\n          float: left;\n          width: 15em;\n          max-height: 150px;\n      }\n\n      #rC {\n          float: right;\n          width: 12em;\n          flow-from: ;\n      }\n\n      #main-flow {\n          padding: 0em 1em 0em 1em;\n          flow-from: regionC;\n          flow-into: ;\n      }\n    </style>\n\n    <div id=\"rA\"></div>\n    <div id=\"rB\"></div>\n    <div id=\"rC\"></div>\n    <content></content>\n  </template>\n</element>        \n\n<body is=\"x-formatting-example\">\n    <article>\n        <p style=\"break-after:region;\">Example of <code>flow from: some-named-flow;</code></p>\n        <p>...</p>\n    </article>\n\n    <div id=\"main-flow\">\n        <p>Lorem ipsum dolor ...</p>\n    </div>\n    <div id=\"side-flow\">\n        <p>Lorem ipsum dolor ...</p>\n    </div>\n</body>"
  },
  {
    "path": "src/extensions/default/CSSCodeHints/unittest-files/regions.css",
    "content": "/* basic tests */\narticle.content {\n    flow-into: main;\n}\n\nsection.layout > div {\n    flow-from: main;\n}\n\n\n#jeff.content {\n    flow-into: jeff;\n}\n\n#jeff.layout > div {\n    flow-from: jeff;\n}\n\n/* exclude matches inside comments tests */\n\n/*\np.content {\n    flow-into: carter;\n}\n\np.layout > div {\n    flow-from: carter;\n}\n*/\n\n/* exclude matches inside strings tests */\n\ndiv {\n    content: \"/* p.content { flow-into: carter; } p.layout > div { flow-from: carter; } */\";\n}\n\n\ndiv {\n    content: \"html.content { flow-into: dexter; } html.layout > div { flow-from: dexter; }\";\n}\n\n\n/*\ndiv.content {\n    content: \"flow-into: martin;\";\n}\n\ndiv.layout > div {\n    content: \"flow-from: martin;\";\n}\n*/\n\n/* multi-line property tests */\n\n#randy.content {\n    flow-into:   \n        randy\n        ;\n}\n\n#randy.layout > div {\n    flow-from:  randy;\n}\n\n/* test to exclude duplicates */\n#yin.content {\n    flow-from: ;\n    flow-into: jeff;\n}\n\n#yin.layout > div {\n    flow-from: jeff;\n}\n\n/* flow-from only tests */\n#raymond.layout > div {\n    flow-from: lim;\n    \n}\n\n/* underscores and dashes */\n#ingo.content {\n    flow-from: edge-code_now_shipping; \n}\n\n/* invalid / ignored flows */\n#test364.content {\n    flow-from: default; \n    flow-from: none; \n    flow-from: inherit;\n    flow-from: auto;\n    flow-from: initial;\n    flow-from: content;\n    flow-from: element;\n}\n\n/* colors */\n.colorful {\n    color: ;\n    background-color: ;\n    border-left-color: deep;\n    border-color: rent;\n    height: ;\n    color: transparent;\n}\n"
  },
  {
    "path": "src/extensions/default/CSSCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, xit, expect, beforeEach, afterEach */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        testContentCSS  = require(\"text!unittest-files/regions.css\"),\n        testContentHTML = require(\"text!unittest-files/region-template.html\"),\n        CSSCodeHints    = require(\"main\");\n\n    describe(\"CSS Code Hinting\", function () {\n\n        var defaultContent = \"@media screen { \\n\" +\n                             \" body { \\n\" +\n                             \" }\\n\" +\n                             \"} \\n\" +\n                             \".selector { \\n\" +\n                             \" \\n\" +\n                             \" b\\n\" +\n                             \" bord\\n\" +\n                             \" border-\\n\" +\n                             \" border-colo\\n\" +\n                             \" border-color: red;\\n\" +      // line: 10\n                             \" d\\n\" +\n                             \" disp\\n\" +\n                             \" display: \\n\" +\n                             \" display: in\\n\" +\n                             \" bordborder: \\n\" +\n                             \" color\\n\" +\n                             \"} \\n\";\n                             \n        var defaultHTMLContent = \"<html> \\n\" +\n                                 \"<head> \\n\" +\n                                 \"</head> \\n\" +\n                                 \"<body> \\n\" +\n                                 \"<div style=' \\n\" + // line 4\n                                 \" \\n\" +\n                                 \" b\\n\" +\n                                 \" bord\\n\" +\n                                 \" border-\\n\" +\n                                 \" border-colo\\n\" +\n                                 \" border-color: red;'>\\n\" + // line 10\n                                 \"</div> \\n\" +\n                                 \"</body> \\n\" +\n                                 \"</html> \\n\";\n\n        var testDocument, testEditor;\n\n        /*\n         * Create a mockup editor with the given content and language id.\n         *\n         * @param {string} content - content for test window\n         * @param {string} languageId\n         */\n        function setupTest(content, languageId) {\n            var mock = SpecRunnerUtils.createMockEditor(content, languageId);\n            testDocument = mock.doc;\n            testEditor = mock.editor;\n        }\n\n        function tearDownTest() {\n            SpecRunnerUtils.destroyMockEditor(testDocument);\n            testEditor = null;\n            testDocument = null;\n        }\n\n        function extractHintList(hints) {\n            return $.map(hints, function ($node) {\n                return $node.text();\n            });\n        }\n\n        // Ask provider for hints at current cursor position; expect it to return some\n        function expectHints(provider, implicitChar, returnWholeObj) {\n            expect(provider.hasHints(testEditor, implicitChar)).toBe(true);\n            var hintsObj = provider.getHints();\n            expect(hintsObj).toBeTruthy();\n            // return just the array of hints if returnWholeObj is falsy\n            return returnWholeObj ? hintsObj : extractHintList(hintsObj.hints);\n        }\n\n        // Ask provider for hints at current cursor position; expect it NOT to return any\n        function expectNoHints(provider, implicitChar) {\n            expect(provider.hasHints(testEditor, implicitChar)).toBe(false);\n        }\n\n        function verifyAttrHints(hintList, expectedFirstHint) {\n            expect(hintList.indexOf(\"div\")).toBe(-1);\n            expect(hintList[0]).toBe(expectedFirstHint);\n        }\n\n        // compares lists to ensure they are the same\n        function verifyListsAreIdentical(hintList, values) {\n            var i;\n            expect(hintList.length).toBe(values.length);\n            for (i = 0; i < values.length; i++) {\n                expect(hintList[i]).toBe(values[i]);\n            }\n        }\n\n\n        function selectHint(provider, expectedHint, implicitChar) {\n            var hintList = expectHints(provider, implicitChar);\n            expect(hintList.indexOf(expectedHint)).not.toBe(-1);\n            return provider.insertHint(expectedHint);\n        }\n\n        // Helper function for testing cursor position\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n        function expectCursorAt(pos) {\n            var selection = testEditor.getSelection();\n            expect(fixPos(selection.start)).toEqual(fixPos(selection.end));\n            expect(fixPos(selection.start)).toEqual(fixPos(pos));\n        }\n\n        // Helper function to\n        // a) ensure the hintList and the list with the available values have the same size\n        // b) ensure that all possible values are mentioned in the hintList\n        function verifyAllValues(hintList, values) {\n            expect(hintList.length).toBe(values.length);\n            expect(hintList.sort().toString()).toBe(values.sort().toString());\n        }\n\n        describe(\"CSS properties in general (selection of correct property based on input)\", function () {\n\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"css\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should list all prop-name hints right after curly bracket\", function () {\n                testEditor.setCursorPos({ line: 4, ch: 11 });    // after {\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"align-content\");  // filtered on \"empty string\"\n            });\n\n            it(\"should list all prop-name hints in new line\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 1 });\n\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"align-content\");  // filtered on \"empty string\"\n            });\n\n            it(\"should list all prop-name hints starting with 'b' in new line\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 2 });\n\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"backface-visibility\");  // filtered on \"b\"\n            });\n\n            it(\"should list all prop-name hints starting with 'bord' \", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 6, ch: 2 });\n\n                testEditor.setCursorPos({ line: 7, ch: 5 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border\");  // filtered on \"bord\"\n            });\n\n            it(\"should list all prop-name hints starting with 'border-' \", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 7, ch: 5 });\n\n                testEditor.setCursorPos({ line: 8, ch: 8 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border-bottom\");  // filtered on \"border-\"\n            });\n\n            it(\"should list only prop-name hint border-color\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 8, ch: 8 });\n\n                testEditor.setCursorPos({ line: 9, ch: 12 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border-color\");  // filtered on \"border-color\"\n                verifyListsAreIdentical(hintList, [\"border-color\",\n                                                   \"border-left-color\",\n                                                   \"border-top-color\",\n                                                   \"border-bottom-color\",\n                                                   \"border-right-color\"]);\n            });\n\n            it(\"should list prop-name hints at end of property-value finished by ;\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 19 });    // after ;\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"align-content\");  // filtered on \"empty string\"\n            });\n\n            it(\"should NOT list prop-name hints right before curly bracket\", function () {\n                testEditor.setCursorPos({ line: 4, ch: 10 });    // inside .selector, before {\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should NOT list prop-name hints after declaration of mediatype\", function () {\n                testEditor.setCursorPos({ line: 0, ch: 15 });    // after {\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should NOT list prop-name hints if previous property is not closed properly\", function () {\n                testEditor.setCursorPos({ line: 16, ch: 6 });   // cursor directly after color\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n            it(\"should NOT list prop-name hints in media type declaration\", function () {\n                testEditor.setCursorPos({ line: 0, ch: 1 });\n                expect(CSSCodeHints.cssPropHintProvider.hasHints(testEditor, 'm')).toBe(false);\n            });\n        });\n\n        describe(\"CSS property hint insertion\", function () {\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"css\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should insert colon prop-name selected\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 6, ch: 2 });\n\n                testEditor.setCursorPos({ line: 7, ch: 5 });   // cursor after 'bord'\n                selectHint(CSSCodeHints.cssPropHintProvider, \"border\");\n                expect(testDocument.getLine(7)).toBe(\" border: \");\n                expectCursorAt({ line: 7, ch: 9 });\n            });\n\n            it(\"should not insert semicolon after prop-value selected\", function () {\n                testDocument.replaceRange(\";\", { line: 12, ch: 5 });\n                testEditor.setCursorPos({ line: 13, ch: 10 });   // cursor after 'display: '\n                selectHint(CSSCodeHints.cssPropHintProvider, \"block\");\n                expect(testDocument.getLine(13)).toBe(\" display: block\");\n            });\n\n            it(\"should insert prop-name directly after semicolon\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 19 });   // cursor after red;\n                selectHint(CSSCodeHints.cssPropHintProvider, \"align-content\");\n                expect(testDocument.getLine(10)).toBe(\" border-color: red;align-content: \");\n            });\n\n            it(\"should insert nothing but the closure(semicolon) if prop-value is fully written\", function () {\n                testDocument.replaceRange(\";\", { line: 15, ch: 13 }); // insert text ;\n                testEditor.setCursorPos({ line: 16, ch: 6 });   // cursor directly after color\n                selectHint(CSSCodeHints.cssPropHintProvider, \"color\");\n                expect(testDocument.getLine(16)).toBe(\" color: \");\n                expectCursorAt({ line: 16, ch: 8 });\n            });\n\n            it(\"should insert prop-name before an existing one\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 1 });   // cursor before border-color:\n                selectHint(CSSCodeHints.cssPropHintProvider, \"float\");\n                expect(testDocument.getLine(10)).toBe(\" float:  border-color: red;\");\n                expectCursorAt({ line: 10, ch: 8 });\n            });\n\n            it(\"should insert prop-name before an existing one when invoked with an implicit character\", function () {\n                testDocument.replaceRange(\"f\", { line: 10, ch: 1 }); // insert \"f\" before border-color:\n                testEditor.setCursorPos({ line: 10, ch: 2 });        // set cursor before border-color:\n                selectHint(CSSCodeHints.cssPropHintProvider, \"float\", \"f\");\n                expect(testDocument.getLine(10)).toBe(\" float:  border-color: red;\");\n                expectCursorAt({ line: 10, ch: 8 });\n            });\n\n            it(\"should replace the existing prop-value with the new selection\", function () {\n                testDocument.replaceRange(\";\", { line: 12, ch: 5 });\n                testDocument.replaceRange(\"block\", { line: 13, ch: 10 });\n                testEditor.setCursorPos({ line: 13, ch: 10 });   // cursor before block\n                selectHint(CSSCodeHints.cssPropHintProvider, \"none\");\n                expect(testDocument.getLine(13)).toBe(\" display: none\");\n                expectCursorAt({ line: 13, ch: 14 });\n            });\n\n            xit(\"should start new hinting whenever there is a whitespace last stringliteral\", function () {\n                // topic: multi-value properties\n                // this needs to be discussed, whether or not this behaviour is aimed for\n                // if so, changes to CSSUtils.getInfoAt need to be done imho to classify this\n                testDocument.replaceRange(\" \", { line: 16, ch: 6 }); // insert whitespace after color\n                testEditor.setCursorPos({ line: 16, ch: 7 });   // cursor one whitespace after color\n                selectHint(CSSCodeHints.cssPropHintProvider, \"color\");\n                expect(testDocument.getLine(16)).toBe(\" color color:\");\n                expectCursorAt({ line: 16, ch: 13 });\n            });\n        });\n\n        describe(\"CSS prop-value hints\", function () {\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"css\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should list all prop-values for 'display' after colon\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 12, ch: 5 });\n\n                testEditor.setCursorPos({ line: 13, ch: 9 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"block\");  // filtered after \"display:\"\n            });\n\n            it(\"should list all prop-values for 'display' after colon and whitespace\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 12, ch: 5 });\n\n                testEditor.setCursorPos({ line: 13, ch: 10 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"block\");  // filtered after \"display: \"\n            });\n\n            it(\"should list all prop-values starting with 'in' for 'display' after colon and whitespace\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 13, ch: 10 });\n\n                testEditor.setCursorPos({ line: 14, ch: 12 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"inherit\");  // filtered after \"display: in\"\n            });\n\n            it(\"should NOT list prop-value hints for unknown prop-name\", function () {\n                testEditor.setCursorPos({ line: 15, ch: 12 });  // at bordborder:\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n        });\n\n        describe(\"CSS hint provider inside mixed htmlfiles\", function () {\n            var defaultContent = \"<html> \\n\" +\n                                 \"<head><style>.selector{display: none;}</style></head> \\n\" +\n                                 \"<body> <style> \\n\" +\n                                 \" body { \\n\" +\n                                 \"    background-color: red; \\n\" +\n                                 \" \\n\" +\n                                 \"} \\n\" +\n                                 \"</style>\\n\" +\n                                 \"<div class='selector'></div>\\n\" +\n                                 \"<style> .foobar { \\n\" +\n                                 \" colo </style>\\n\" +\n                                 \"</body></html>\";\n\n            beforeEach(function () {\n                // create dummy Document for the Editor\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"html\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should list prop-name hints right after curly bracket\", function () {\n                testEditor.setCursorPos({ line: 3, ch: 7 });  // inside body-selector, after {\n                expectHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should list prop-name hints inside single-line styletags at start\", function () {\n                testEditor.setCursorPos({ line: 1, ch: 23 });  // inside style, after {\n                expectHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should list prop-name hints inside single-line styletags after semicolon\", function () {\n                testEditor.setCursorPos({ line: 1, ch: 37 });  // inside style, after ;\n                expectHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should list prop-name hints inside multi-line styletags with cursor in first line\", function () {\n                testEditor.setCursorPos({ line: 9, ch: 18 });   // inside style, after {\n                expectHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should list prop-name hints inside multi-line styletags with cursor in last line\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 5 });    // inside style, after colo\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyListsAreIdentical(hintList, [\"color\",\n                                                   \"border-color\",\n                                                   \"background-color\",\n                                                   \"border-left-color\",\n                                                   \"border-top-color\",\n                                                   \"outline-color\",\n                                                   \"border-bottom-color\",\n                                                   \"border-right-color\",\n                                                   \"text-decoration-color\",\n                                                   \"text-emphasis-color\",\n                                                   \"column-count\",\n                                                   \"column-rule-color\",\n                                                   \"background-blend-mode\"]);\n            });\n\n            it(\"should NOT list prop-name hints between closed styletag and new opening styletag\", function () {\n                testEditor.setCursorPos({ line: 8, ch: 0 });    // right before <div\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should NOT list hints right before curly bracket\", function () {\n                testEditor.setCursorPos({ line: 3, ch: 6 });    // inside body-selector, before {\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should NOT list hints inside head-tag\", function () {\n                testEditor.setCursorPos({ line: 1, ch: 6 });    // between <head> and </head> {\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n        });\n        \n        describe(\"CSS Hint provider in style attribute value context for html mode\", function () {\n\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultHTMLContent, \"html\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n            \n            it(\"should list all prop-name hints right after the open quote for style value context\", function () {\n                testEditor.setCursorPos({ line: 4, ch: 12 });    // after \"='\"\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"align-content\");  // filtered on \"empty string\"\n            });\n\n            it(\"should list all prop-name hints in new line for style value context\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 0 });\n\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"align-content\");  // filtered on \"empty string\"\n            });\n\n            it(\"should list all prop-name hints starting with 'b' in new line for style value context\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 2 });\n\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"backface-visibility\");  // filtered on \"b\"\n            });\n\n            it(\"should list all prop-name hints starting with 'bord' for style value context\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 6, ch: 2 });\n\n                testEditor.setCursorPos({ line: 7, ch: 5 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border\");  // filtered on \"bord\"\n            });\n\n            it(\"should list all prop-name hints starting with 'border-' for style value context\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 7, ch: 5 });\n\n                testEditor.setCursorPos({ line: 8, ch: 8 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border-bottom\");  // filtered on \"border-\"\n            });\n\n            it(\"should list only prop-name hint border-color for style value context\", function () {\n                // insert semicolon after previous rule to avoid incorrect tokenizing\n                testDocument.replaceRange(\";\", { line: 8, ch: 8 });\n\n                testEditor.setCursorPos({ line: 9, ch: 12 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border-color\");  // filtered on \"border-color\"\n                verifyListsAreIdentical(hintList, [\"border-color\",\n                                                   \"border-left-color\",\n                                                   \"border-top-color\",\n                                                   \"border-bottom-color\",\n                                                   \"border-right-color\"]);\n            });\n\n            it(\"should list prop-name hints at end of property-value finished by ; for style value context\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 19 });    // after ;\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"align-content\");  // filtered on \"empty string\"\n            });\n\n            it(\"should NOT list prop-name hints right before style value context\", function () {\n                testEditor.setCursorPos({ line: 4, ch: 11 });    // after =\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n\n            it(\"should NOT list prop-name hints after style value context\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 20 });    // after \"'\"\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n            \n        });\n\n\n        describe(\"CSS hint provider in other filecontext (e.g. javascript)\", function () {\n            var defaultContent = \"function foobar (args) { \\n \" +\n                                 \"    /* do sth */ \\n\" +\n                                 \"    return 1; \\n\" +\n                                 \"} \\n\";\n            beforeEach(function () {\n                // create dummy Document for the Editor\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"javascript\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should NOT list hints after function declaration\", function () {\n                testEditor.setCursorPos({ line: 0, ch: 24 });    // after {  after function declaration\n                expectNoHints(CSSCodeHints.cssPropHintProvider);\n            });\n        });\n\n        describe(\"CSS hint provider cursor placement inside value functions\", function () {\n            var defaultContent = \".selector { \\n\" + // line 0\n                                 \"shape-inside:\\n\" + // line 1\n                                 \"}\\n\"; // line 2\n\n            beforeEach(function () {\n                // create dummy Document for the Editor\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"css\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should should place the cursor between the parens of the value function\", function () {\n                var expectedString = \"shape-inside:polygon()\";\n\n                testEditor.setCursorPos({ line: 1, ch: 15 });    // after shape-inside\n                expectHints(CSSCodeHints.cssPropHintProvider);\n                selectHint(CSSCodeHints.cssPropHintProvider, \"polygon()\");\n                expect(testDocument.getLine(1).length).toBe(expectedString.length);\n                expect(testDocument.getLine(1)).toBe(expectedString);\n                expectCursorAt({ line: 1, ch: expectedString.length - 1 });\n            });\n        });\n\n        describe(\"CSS hint provider for regions and exclusions\", function () {\n            var defaultContent = \".selector { \\n\" + // line 0\n                                 \" shape-inside: \\n;\" + // line 1\n                                 \" shape-outside: \\n;\" + // line 2\n                                 \" region-fragment: \\n;\" + // line 3\n                                 \" region-break-after: \\n;\" + // line 4\n                                 \" region-break-inside: \\n;\" + // line 5\n                                 \" region-break-before: \\n;\" + // line 6\n                                 \" -ms-region\\n;\" + // line 7\n                                 \" -webkit-region\\n;\" + // line 8\n                                 \" flow-from: \\n;\" + // line 9\n                                 \" flow-into: \\n;\" + // line 10\n                                 \"}\\n\"; // line 11\n\n            beforeEach(function () {\n                // create dummy Document for the Editor\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, \"css\");\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should list 7 value-name hints for shape-inside\", function () {\n                testEditor.setCursorPos({ line: 1, ch: 15 });    // after shape-inside\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"auto\");  // first hint should be auto\n                verifyAllValues(hintList, [\"auto\", \"circle()\", \"ellipse()\", \"inherit\", \"outside-shape\", \"polygon()\", \"rectangle()\"]);\n            });\n\n            it(\"should list 16 value-name hints for shape-outside\", function () {\n                testEditor.setCursorPos({ line: 2, ch: 16 });    // after shape-outside\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"border-box\");  // first hint should be border-box\n                verifyAllValues(hintList, [\"none\", \"inherit\", \"circle()\", \"ellipse()\", \"polygon()\", \"inset()\", \"margin-box\", \"border-box\", \"padding-box\", \"content-box\", \"url()\", \"image()\", \"linear-gradient()\", \"radial-gradient()\", \"repeating-linear-gradient()\", \"repeating-radial-gradient()\"]);\n            });\n\n            it(\"should list 2 value-name hints for region-fragment\", function () {\n                testEditor.setCursorPos({ line: 3, ch: 18 });    // after region-fragment\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"auto\");  // first hint should be auto\n                verifyAllValues(hintList, [\"auto\", \"break\"]);\n            });\n\n            it(\"should list 11 value-name hints for region-break-after\", function () {\n                testEditor.setCursorPos({ line: 4, ch: 21 });    // after region-break-after\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"always\");  // first hint should be always\n                verifyAllValues(hintList, [\"always\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\", \"column\", \"left\", \"page\", \"region\", \"right\"]);\n            });\n\n            it(\"should list 5 value-name hints for region-break-inside\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 22 });    // after region-break-inside\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"auto\");  // first hint should be auto\n                verifyAllValues(hintList, [\"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\"]);\n            });\n\n            it(\"should list 11 value-name hints for region-break-before\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 23 });    // after region-break-before\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"always\");  // first hint should be always\n                verifyAllValues(hintList, [\"always\", \"auto\", \"avoid\", \"avoid-column\", \"avoid-page\", \"avoid-region\", \"column\", \"left\", \"page\", \"region\", \"right\"]);\n            });\n\n            // TODO: Need to add vendor prefixed properties for CSS code hint provider.\n            xit(\"should list 4 value-name hints for vendor prefixed region-* properties\", function () {\n                testEditor.setCursorPos({ line: 7, ch: 16 });    // after -ms-region\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"region-break-after\");  // first hint should be region-break-after\n                verifyAllValues(hintList, [\"region-break-after\", \"region-break-before\", \"region-break-inside\", \"region-fragment\"]);\n\n                testEditor.setCursorPos({ line: 8, ch: 20 });    // after -webkit-region\n                hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"region-break-after\");  // first hint should be region-break-after\n                verifyAllValues(hintList, [\"region-break-after\", \"region-break-before\", \"region-break-inside\", \"region-fragment\"]);\n            });\n\n            it(\"should list 2 value-name hints for flow-from\", function () {\n                testEditor.setCursorPos({ line: 9, ch: 12 });    // after flow-from\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"inherit\");  // first hint should be inherit\n                verifyAllValues(hintList, [\"inherit\", \"none\"]);\n            });\n\n            it(\"should list 1 value-name hint for flow-into\", function () {\n                testEditor.setCursorPos({ line: 10, ch: 12 });    // after flow-into\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"none\");  // first hint should be none\n                verifyAllValues(hintList, [\"none\"]);\n            });\n        });\n\n        describe(\"Named flow hints for flow-into and flow-from properties in a CSS file\", function () {\n            beforeEach(function () {\n                setupTest(testContentCSS, \"css\");\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should list more than 2 value hints for flow-from\", function () {\n                testEditor.setCursorPos({ line: 66, ch: 15 });    // after flow-from\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"edge-code_now_shipping\");  // first hint should be edge-code_now_shipping\n                verifyAllValues(hintList, [\"edge-code_now_shipping\", \"inherit\", \"jeff\", \"lim\", \"main\", \"none\", \"randy\"]);\n            });\n\n            it(\"should list more than 1 value hint for flow-into\", function () {\n                testEditor.setCursorPos({ line: 77, ch: 4 });\n                selectHint(CSSCodeHints.cssPropHintProvider, \"flow-into\");\n                expect(testDocument.getLine(77)).toBe(\"    flow-into: \");\n                expectCursorAt({ line: 77, ch: 15 });\n\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"edge-code_now_shipping\");  // first hint should be edge-code_now_shipping\n                verifyAllValues(hintList, [\"edge-code_now_shipping\", \"jeff\", \"lim\", \"main\", \"none\", \"randy\"]);\n            });\n\n            it(\"should NOT include partially entered named flow value in hint list\", function () {\n                // Insert a letter for a new named flow after flow-from: on line 66\n                testDocument.replaceRange(\"m\", { line: 66, ch: 15 });\n\n                testEditor.setCursorPos({ line: 66, ch: 16 });    // after flow-from: m\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyListsAreIdentical(hintList, [\"main\", \"lim\"]);\n            });\n\n        });\n\n        describe(\"Named flow hints inside a style block of an HTML\", function () {\n            beforeEach(function () {\n                setupTest(testContentHTML, \"html\");\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should include only 2 named flows available in the style block for flow-from\", function () {\n                testEditor.setCursorPos({ line: 28, ch: 21 });    // after flow-from\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"article\");  // first hint should be article\n                verifyAllValues(hintList, [\"article\", \"inherit\", \"none\", \"regionC\"]);\n            });\n\n            it(\"should include only 2 named flows available in the style block for flow-into\", function () {\n                testEditor.setCursorPos({ line: 34, ch: 21 });\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"article\");  // first hint should be article\n                verifyAllValues(hintList, [\"article\", \"none\", \"regionC\"]);\n            });\n\n            it(\"should NOT include partially entered named flow value in hint list\", function () {\n                // Insert a letter for a new named flow after flow-from: on line 28\n                testDocument.replaceRange(\"m\", { line: 28, ch: 21 });\n\n                testEditor.setCursorPos({ line: 28, ch: 22 });    // after flow-from: m\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAllValues(hintList, []);\n            });\n\n            it(\"should NOT show named flow available inisde HTML text\", function () {\n                // Insert a letter for a new named flow after flow-from: on line 28\n                testDocument.replaceRange(\"some\", { line: 28, ch: 21 });\n\n                testEditor.setCursorPos({ line: 28, ch: 25 });    // after flow-from: some\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                // some-named-flow should not be in the hint list since it is inside HTML text\n                verifyAllValues(hintList, []);\n            });\n        });\n\n        describe(\"Color names and swatches in a CSS file\", function () {\n            beforeEach(function () {\n                setupTest(testContentCSS, \"css\");\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should list color names for color\", function () {\n                testEditor.setCursorPos({ line: 98, ch: 11 }); // after color\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"aliceblue\"); // first hint should be aliceblue\n            });\n\n            it(\"should show color swatches for background-color\", function () {\n                testEditor.setCursorPos({ line: 99, ch: 22 }); // after background-color\n                var hints = expectHints(CSSCodeHints.cssPropHintProvider, undefined, true).hints;\n                expect(hints[0].text()).toBe(\"aliceblue\"); // first hint should be aliceblue\n                expect(hints[0].find(\".color-swatch\").length).toBe(1);\n                // CEF 2623 will output \"aliceblue\" whereas earlier versions give \"rgb(240, 248, 255)\",\n                // so we need this ugly hack to make sure this test passes on both\n                expect(hints[0].find(\".color-swatch\").css(\"backgroundColor\")).toMatch(/^rgb\\(240, 248, 255\\)$|aliceblue/);\n            });\n\n            it(\"should filter out color names appropriately\", function () {\n                testEditor.setCursorPos({ line: 100, ch: 27 }); // after border-left-color\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                verifyAttrHints(hintList, \"deeppink\"); // first hint should be deeppink\n                verifyAllValues(hintList, [\"deeppink\", \"deepskyblue\"]);\n            });\n\n            it(\"should always include transparent and currentColor and they should not have a swatch, but class no-swatch-margin\", function () {\n                testEditor.setCursorPos({ line: 101, ch: 22 }); // after border-color\n                var hints = expectHints(CSSCodeHints.cssPropHintProvider, undefined, true).hints,\n                    hintList = extractHintList(hints);\n                verifyAttrHints(hintList, \"currentColor\"); // first hint should be currentColor\n                verifyAllValues(hintList, [\"currentColor\", \"darkmagenta\", \"transparent\"]);\n                expect(hints[0].find(\".color-swatch\").length).toBe(0); // no swatch for currentColor\n                expect(hints[2].find(\".color-swatch\").length).toBe(0); // no swatch for transparent\n                expect(hints[0].hasClass(\"no-swatch-margin\")).toBeTruthy(); // no-swatch-margin applied to currentColor\n                expect(hints[2].hasClass(\"no-swatch-margin\")).toBeTruthy(); // no-swatch-margin applied to transparent\n            });\n\n            it(\"should remove class no-swatch-margin from transparent if it's the only one in the list\", function () {\n                testEditor.setCursorPos({ line: 103, ch: 22 }); // after color\n                var hints = expectHints(CSSCodeHints.cssPropHintProvider, undefined, true).hints,\n                    hintList = extractHintList(hints);\n                verifyAllValues(hintList, [\"transparent\"]);\n                expect(hints[0].find(\".color-swatch\").length).toBe(0); // no swatch for transparent\n                expect(hints[0].hasClass(\"no-swatch-margin\")).toBeFalsy(); // no-swatch-margin not applied to transparent\n            });\n\n            it(\"should insert color names correctly\", function () {\n                var expectedString  = \"    border-left-color: deeppink;\",\n                    line            = 100;\n\n                testEditor.setCursorPos({ line: line, ch: 27 }); // after border-left-color\n                expectHints(CSSCodeHints.cssPropHintProvider);\n                selectHint(CSSCodeHints.cssPropHintProvider, \"deeppink\");\n                expect(testDocument.getLine(line).length).toBe(expectedString.length);\n                expect(testDocument.getLine(line)).toBe(expectedString);\n                expectCursorAt({ line: line, ch: expectedString.length - 1 });\n            });\n\n\n            it(\"should not display color names for unrelated properties\", function () {\n                testEditor.setCursorPos({ line: 102, ch: 12 }); // after height\n                var hintList = expectHints(CSSCodeHints.cssPropHintProvider);\n                expect(hintList.indexOf(\"aliceblue\")).toBe(-1);\n            });\n        });\n\n        describe(\"Should not invoke CSS hints on space key\", function () {\n            beforeEach(function () {\n                setupTest(testContentHTML, \"html\");\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should not trigger CSS property name hints with space key\", function () {\n                testEditor.setCursorPos({ line: 25, ch: 11 });    // after {\n                expectNoHints(CSSCodeHints.cssPropHintProvider, \" \");\n            });\n\n            it(\"should not trigger CSS property value hints with space key\", function () {\n                testEditor.setCursorPos({ line: 28, ch: 21 });    // after flow-from\n                expectNoHints(CSSCodeHints.cssPropHintProvider, \" \");\n            });\n        });\n    });\n});\n\n"
  },
  {
    "path": "src/extensions/default/CSSPseudoSelectorHints/PseudoSelectors.json",
    "content": "{\n    \"classes\": {\n        \"active\":              {\"desc\": \"Selects the link being pressed\"},\n        \"any-link\":            {\"desc\": \"Selects every hyperlink, e.g., <a>, <area> and <link> with href attribute\"},\n        \"checked\":             {\"desc\": \"Selects every checked checkbox\"},\n        \"default\":             {\"desc\": \"Selects every UI element that is the default among a group of similar elements\"},\n        \"dir(direction)\":      {\"desc\": \"Selects every element whose text direction is 'direction'\", \"text\": \"dir()\"},\n        \"disabled\":            {\"desc\": \"Selects every disabled form element\"},\n        \"empty\":               {\"desc\": \"Selects every element that has no any child nodes\"},\n        \"enabled\":             {\"desc\": \"Selects every enabled form element\"},\n        \"first\":               {\"desc\": \"With @page, selects the first page of a printed document\"},\n        \"first-child\":         {\"desc\": \"Selects every element that is the first child of its parent\"},\n        \"first-of-type\":       {\"desc\": \"Selects every element that is the first element of the specific type of its parent\"},\n        \"focus\":               {\"desc\": \"Selects the input element which has focus\"},\n        \"focus-within\":        {\"desc\": \"Selects every element which or whose descendant has focus\"},\n        \"fullscreen\":          {\"desc\": \"Selects the element being in fullscreen mode\"},\n        \"hover\":               {\"desc\": \"Selects elements on pointer over\"},\n        \"in-range\":            {\"desc\": \"Selects input elements with a value within a specified range\"},\n        \"indeterminate\":       {\"desc\": \"Selects every indeterminate checkbox, radio button or progress bar\"},\n        \"invalid\":             {\"desc\": \"Selects all input elements with an invalid value\"},\n        \"lang(languages)\":     {\"desc\": \"Selects every element whose language is contained by the 'languages' list\", \"text\": \"lang()\"},\n        \"last-child\":          {\"desc\": \"Selects every element that is the last child of its parent\"},\n        \"last-of-type\":        {\"desc\": \"Selects every element that is the last element of the specific type of its parent\"},\n        \"left\":                {\"desc\": \"With @page, selects every left-hand page of a printed document\"},\n        \"link\":                {\"desc\": \"Selects all unvisited links\"},\n        \"matches(selectors)\":  {\"desc\": \"Selects every element that is matched by one or more selectors in the 'selectors' list\", \"text\": \"matches()\"},\n        \"not(selectors)\":      {\"desc\": \"Selects every element that is not matched by any selector in the 'selectors' list\", \"text\": \"not()\"},\n        \"nth-child(n)\":        {\"desc\": \"Selects every element that is the nth child of its parent\", \"text\": \"nth-child()\"},\n        \"nth-last-child(n)\":   {\"desc\": \"Selects every element that is the nth child of its parent, counting from the last child\", \"text\": \"nth-last-child()\"},\n        \"nth-last-of-type(n)\": {\"desc\": \"Selects every element that is the nth element of the specific type of its parent, counting from the last child\", \"text\": \"nth-last-of-type()\"},\n        \"nth-of-type(n)\":      {\"desc\": \"Selects every element that is the nth element of the specific type of its parent\",  \"text\": \"nth-of-type(n)\"},\n        \"only-child\":          {\"desc\": \"Selects every element that is the only child of its parent\"},\n        \"only-of-type\":        {\"desc\": \"Selects every element that is the only element of the specific type of its parent\"},\n        \"optional\":            {\"desc\": \"Selects non-required form elements\"},\n        \"out-of-range\":        {\"desc\": \"Selects input elements with a value outside a specified range\"},\n        \"placeholder-shown\":   {\"desc\": \"Selects all <input> and <textarea> elements currently showing placeholder text\"},\n        \"read-only\":           {\"desc\": \"Selects form elements with the 'readonly' attribute specified\"},\n        \"read-write\":          {\"desc\": \"Selects form elements with the 'readonly' attribute NOT specified\"},\n        \"required\":            {\"desc\": \"Selects required form elements\"},\n        \"right\":               {\"desc\": \"With @page, selects every right-hand page of a printed document\"},\n        \"root\":                {\"desc\": \"Selects the document's root element\"},\n        \"target\":              {\"desc\": \"Selects the element whose ID matches with the URL hash\"},\n        \"valid\":               {\"desc\": \"Selects all input elements with a valid value\"},\n        \"visited\":             {\"desc\": \"Selects all visited links\"}\n    },\n    \"elements\": {\n        \"after\":         {\"desc\": \"Insert something after the content of each element matched by this selector\"},\n        \"backdrop\":      {\"desc\": \"Selects the box rendered immediately below a <dialog> or an element in fullscreen mode\"},\n        \"before\":        {\"desc\": \"Insert something before the content of each element matched by this selector\"},\n        \"cue\":           {\"desc\": \"Selects the cues of WebVTT subtitles\"},\n        \"cue(selector)\": {\"desc\": \"Selects the cues of WebVTT subtitles, matched by 'selector'\", \"text\": \"cue()\"},\n        \"first-letter\":  {\"desc\": \"Selects the first letter of every element matched by this selector\"},\n        \"first-line\":    {\"desc\": \"Selects the first line of every element matched by this selector\"},\n        \"placeholder\":   {\"desc\": \"Selects the placeholder text of <input> and <textarea> elements\"},\n        \"selection\":     {\"desc\": \"Selects the portion of an element that is selected by a user\"}\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/CSSPseudoSelectorHints/main.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        TokenUtils          = brackets.getModule(\"utils/TokenUtils\"),\n        PseudoRulesText     = require(\"text!PseudoSelectors.json\"),\n        PseudoRules         = JSON.parse(PseudoRulesText);\n\n\n    var TOKEN_TYPE_PSEUDO_CLASS   = 0,\n        TOKEN_TYPE_PSEUDO_ELEMENT = 1,\n        PUNCTUATION_CHAR          = ':';\n\n    function _getPseudoContext(token, cursorText, ctx) {\n        var slicedToken,\n            contextType = -1;\n\n        // Magic code to get around CM's 'pseudo' identification logic\n        // As per CSS3 spec :\n        // -> ':' identifies pseudo classes\n        // -> '::' identifies pseudo elements\n        // We should strictly check for single or double occurance of ':' by slicing\n        // the line text till the token start position\n\n        if (token.state.state === \"pseudo\") {\n            slicedToken = cursorText.substr(0, token.start + 1).slice(-3);\n        } else if (token.type === \"variable-3\") {\n            slicedToken = cursorText.substr(0, token.start).slice(-3);\n        }\n        \n        if (!slicedToken) {\n            //We get here when in SCSS mode and the cursor is right after ':'\n            //Test the previous token first\n            TokenUtils.movePrevToken(ctx);\n            if (ctx.token.string === PUNCTUATION_CHAR) {\n                //We are in pseudo element context ('::')\n                contextType = TOKEN_TYPE_PSEUDO_ELEMENT;\n            } else {\n                contextType = TOKEN_TYPE_PSEUDO_CLASS;\n            }\n        } else {\n            if (slicedToken.slice(-2) === \"::\") {\n                contextType = TOKEN_TYPE_PSEUDO_ELEMENT;\n            } else if (slicedToken.slice(-1) === \":\") {\n                contextType = TOKEN_TYPE_PSEUDO_CLASS;\n            }\n        }\n\n        return contextType;\n    }\n\n    /**\n     * @constructor\n     */\n    function PseudoSelectorHints() {\n    }\n    \n    function _validatePseudoContext(token) {\n        return token.state.state === \"pseudo\" || token.type === \"variable-3\" || token.string === PUNCTUATION_CHAR;\n    }\n\n    // As we are only going to provide :<pseudo> name hints\n    // we should claim that we don't have hints for anything else\n    PseudoSelectorHints.prototype.hasHints = function (editor, implicitChar) {\n        var pos = editor.getCursorPos(),\n            token = editor._codeMirror.getTokenAt(pos);\n\n        this.editor = editor;\n\n        // Check if we are at ':' pseudo rule or in 'variable-3' 'def' context\n        return _validatePseudoContext(token);\n    };\n\n    PseudoSelectorHints.prototype.getHints = function (implicitChar) {\n        var pos = this.editor.getCursorPos(),\n            token = this.editor._codeMirror.getTokenAt(pos),\n            filter = token.type === \"variable-3\" ? token.string : \"\",\n            lineTillCursor = this.editor._codeMirror.getLine(pos.line),\n            ctx = TokenUtils.getInitialContext(this.editor._codeMirror, pos);\n\n        if (!_validatePseudoContext(token)) {\n            return null;\n        }\n\n        // validate and keep the context in scope so that it can be used while getting description\n        this.context = _getPseudoContext(token, lineTillCursor, ctx);\n        \n        // If we are not able to find context, don't proceed\n        if (this.context === -1) {\n            return null;\n        }\n\n        this.token = token;\n\n        // Filter the property list based on the token string\n        var result = Object.keys(this.context === TOKEN_TYPE_PSEUDO_CLASS ? PseudoRules.classes : PseudoRules.elements).filter(function (key) {\n            if (key.indexOf(filter) === 0) {\n                return key;\n            }\n        }).sort();\n\n        return {\n            hints: result,\n            match: filter,\n            selectInitial: true,\n            defaultDescriptionWidth: true,\n            handleWideResults: false\n        };\n    };\n\n    /**\n     * Inserts a given ':<pseudo>' hint into the current editor context.\n     *\n     * @param {string} completion\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    PseudoSelectorHints.prototype.insertHint = function (completion) {\n        var cursor = this.editor.getCursorPos();\n        var startPos = {line: cursor.line, ch: this.token.start},\n            endPos   = {line: cursor.line, ch: this.token.end};\n\n        if (this.token.state.state === \"pseudo\") {\n            // We have just started the 'pseudo' context, start replacing the current token by leaving ':' char\n            startPos.ch = startPos.ch + 1;\n            endPos = startPos;\n        }\n\n        if (this.context === TOKEN_TYPE_PSEUDO_CLASS) {\n            // If the hint label contains annotated data for illustration, then we might have\n            // different text to be inserted.\n            completion = PseudoRules.classes[completion].text || completion;\n        }\n\n        this.editor.document.replaceRange(completion, startPos, endPos);\n\n        if (completion.slice(-1) === \")\") {\n            cursor = this.editor.getCursorPos();\n            this.editor.setCursorPos({line: cursor.line, ch: cursor.ch - 1});\n        }\n\n        return false;\n    };\n\n    AppInit.appReady(function () {\n        // Register code hint providers\n        var pseudoSelectorHints = new PseudoSelectorHints();\n        CodeHintManager.registerHintProvider(pseudoSelectorHints, [\"css\", \"scss\", \"less\"], 0);\n        \n        // For test\n        exports.pseudoSelectorHints = pseudoSelectorHints;\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/CSSPseudoSelectorHints/unittests.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, xit, expect, beforeEach, afterEach */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils             = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        CSSPseudoSelectorCodeHints  = require(\"main\"),\n        PseudoStaticDataRaw         = require(\"text!PseudoSelectors.json\"),\n        PseudoStaticData            = JSON.parse(PseudoStaticDataRaw);\n\n    describe(\"CSS Pseudo class/element Code Hinting\", function () {\n\n        var defaultContent = \".selector1: { \\n\" +\n                             \"} \\n\" +\n                             \".selector2:: { \\n\" +\n                             \"} \\n\" +\n                             \".selector3:n { \\n\" +\n                             \"} \\n\" +\n                             \".selector4::f { \\n\" +\n                             \"} \\n\";\n                             \n\n        var testDocument, testEditor;\n\n        /*\n         * Create a mockup editor with the given content and language id.\n         *\n         * @param {string} content - content for test window\n         * @param {string} languageId\n         */\n        function setupTest(content, languageId) {\n            var mock = SpecRunnerUtils.createMockEditor(content, languageId);\n            testDocument = mock.doc;\n            testEditor = mock.editor;\n        }\n\n        function tearDownTest() {\n            SpecRunnerUtils.destroyMockEditor(testDocument);\n            testEditor = null;\n            testDocument = null;\n        }\n\n        // Ask provider for hints at current cursor position; expect it to return some\n        function expectHints(provider, implicitChar, returnWholeObj) {\n            expect(provider.hasHints(testEditor, implicitChar)).toBe(true);\n            var hintsObj = provider.getHints();\n            expect(hintsObj).toBeTruthy();\n            // return just the array of hints if returnWholeObj is falsy\n            return returnWholeObj ? hintsObj : hintsObj.hints;\n        }\n\n        // Ask provider for hints at current cursor position; expect it NOT to return any\n        function expectNoHints(provider, implicitChar) {\n            expect(provider.hasHints(testEditor, implicitChar)).toBe(false);\n        }\n\n        // compares lists to ensure they are the same\n        function verifyListsAreIdentical(hintList, values) {\n            var i;\n            expect(hintList.length).toBe(values.length);\n            for (i = 0; i < values.length; i++) {\n                expect(hintList[i]).toBe(values[i]);\n            }\n        }\n\n\n        function selectHint(provider, expectedHint, implicitChar) {\n            var hintList = expectHints(provider, implicitChar);\n            expect(hintList.indexOf(expectedHint)).not.toBe(-1);\n            return provider.insertHint(expectedHint);\n        }\n\n        // Helper function for testing cursor position\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n        function expectCursorAt(pos) {\n            var selection = testEditor.getSelection();\n            expect(fixPos(selection.start)).toEqual(fixPos(selection.end));\n            expect(fixPos(selection.start)).toEqual(fixPos(pos));\n        }\n        \n        function verifyFirstEntry(hintList, expectedFirstHint) {\n            expect(hintList[0]).toBe(expectedFirstHint);\n        }\n\n        // Helper function to\n        // a) ensure the hintList and the list with the available values have the same size\n        // b) ensure that all possible values are mentioned in the hintList\n        function verifyAllValues(hintList, values) {\n            expect(hintList.length).toBe(values.length);\n            expect(hintList.sort().toString()).toBe(values.sort().toString());\n        }\n        \n        var modesToTest = ['css', 'scss', 'less'],\n            modeCounter;\n        \n        \n        var selectMode = function () {\n            return modesToTest[modeCounter];\n        };\n\n        describe(\"Pseudo classes in different style modes\", function () {\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, selectMode());\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n            \n            var testAllHints = function () {\n                    testEditor.setCursorPos({ line: 0, ch: 11 });    // after :\n                    var hintList = expectHints(CSSPseudoSelectorCodeHints.pseudoSelectorHints);\n                    console.log(JSON.stringify(hintList));\n                    verifyFirstEntry(hintList, \"active\");  // filtered on \"empty string\"\n                    verifyListsAreIdentical(hintList, Object.keys(PseudoStaticData.classes).sort());\n                },\n                testFilteredHints = function () {\n                    testEditor.setCursorPos({ line: 4, ch: 12 });    // after :n\n                    var hintList = expectHints(CSSPseudoSelectorCodeHints.pseudoSelectorHints);\n                    console.log(JSON.stringify(hintList));\n                    verifyFirstEntry(hintList, \"not(selectors)\");  // filtered on \"n\"\n                    verifyListsAreIdentical(hintList, [\"not(selectors)\",\n                                                       \"nth-child(n)\",\n                                                       \"nth-last-child(n)\",\n                                                       \"nth-last-of-type(n)\",\n                                                       \"nth-of-type(n)\"]);\n                },\n                testNoHints = function () {\n                    testEditor.setCursorPos({ line: 0, ch: 10 });    // after {\n                    expect(CSSPseudoSelectorCodeHints.pseudoSelectorHints.hasHints(testEditor, 'a')).toBe(false);\n                };\n            \n            for (modeCounter in modesToTest) {\n                it(\"should list all Pseudo selectors right after :\", testAllHints);\n                it(\"should list filtered pseudo selectors right after :n\", testFilteredHints);\n                it(\"should not list rule hints if the cursor is before :\", testNoHints);\n            }\n        });\n\n\n        describe(\"Pseudo elements in various style modes\", function () {\n\n            beforeEach(function () {\n                // create Editor instance (containing a CodeMirror instance)\n                var mock = SpecRunnerUtils.createMockEditor(defaultContent, selectMode());\n                testEditor = mock.editor;\n                testDocument = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n            \n            var testAllHints = function () {\n                    testEditor.setCursorPos({ line: 2, ch: 12 });    // after ::\n                    var hintList = expectHints(CSSPseudoSelectorCodeHints.pseudoSelectorHints);\n                    console.log(JSON.stringify(hintList));\n                    verifyFirstEntry(hintList, \"after\");  // filtered on \"empty string\"\n                    verifyListsAreIdentical(hintList, Object.keys(PseudoStaticData.elements).sort());\n                },\n                testFilteredHints = function () {\n                    testEditor.setCursorPos({ line: 6, ch: 13 });    // after ::f\n                    var hintList = expectHints(CSSPseudoSelectorCodeHints.pseudoSelectorHints);\n                    console.log(JSON.stringify(hintList));\n                    verifyFirstEntry(hintList, \"first-letter\");  // filtered on \"f\"\n                    verifyListsAreIdentical(hintList, [\"first-letter\",\n                                                       \"first-line\"]);\n                },\n                testNoHints = function () {\n                    testEditor.setCursorPos({ line: 2, ch: 10 });    // after ::f\n                    expect(CSSPseudoSelectorCodeHints.pseudoSelectorHints.hasHints(testEditor, 'c')).toBe(false);\n                };\n            \n            for (modeCounter in modesToTest) {\n                it(\"should list all Pseudo selectors right after :\", testAllHints);\n                it(\"should list filtered pseudo selectors right after ::f\", testFilteredHints);\n                it(\"should not list rule hints if the cursor is before :\", testNoHints);\n            }\n\n        });\n\n    });\n});\n\n"
  },
  {
    "path": "src/extensions/default/CloseOthers/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Menus               = brackets.getModule(\"command/Menus\"),\n        CommandManager      = brackets.getModule(\"command/CommandManager\"),\n        Commands            = brackets.getModule(\"command/Commands\"),\n        MainViewManager     = brackets.getModule(\"view/MainViewManager\"),\n        Strings             = brackets.getModule(\"strings\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        workingSetListCmenu = Menus.getContextMenu(Menus.ContextMenuIds.WORKING_SET_CONTEXT_MENU);\n\n    // Constants\n    var closeOthers             = \"file.close_others\",\n        closeAbove              = \"file.close_above\",\n        closeBelow              = \"file.close_below\";\n\n    // Global vars and preferences\n    var prefs                   = PreferencesManager.getExtensionPrefs(\"closeOthers\"),\n        menuEntriesShown        = {};\n\n    prefs.definePreference(\"below\",  \"boolean\", true, {\n        description: Strings.DESCRIPTION_CLOSE_OTHERS_BELOW\n    });\n    prefs.definePreference(\"others\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_CLOSE_OTHERS\n    });\n    prefs.definePreference(\"above\",  \"boolean\", true, {\n        description: Strings.DESCRIPTION_CLOSE_OTHERS_ABOVE\n    });\n\n\n    /**\n     * Handle the different Close Other commands\n     * @param {string} mode\n     */\n    function handleClose(mode) {\n        var targetIndex  = MainViewManager.findInWorkingSet(MainViewManager.ACTIVE_PANE, MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE)),\n            workingSetList = MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE),\n            start        = (mode === closeBelow) ? (targetIndex + 1) : 0,\n            end          = (mode === closeAbove) ? (targetIndex) : (workingSetList.length),\n            files        = [],\n            i;\n\n        for (i = start; i < end; i++) {\n            if ((mode === closeOthers && i !== targetIndex) || (mode !== closeOthers)) {\n                files.push(workingSetList[i]);\n            }\n        }\n\n        CommandManager.execute(Commands.FILE_CLOSE_LIST, {fileList: files});\n    }\n\n    /**\n     * Enable/Disable the menu items depending on which document is selected in the working set\n     */\n    function contextMenuOpenHandler() {\n        var file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);\n\n        if (file) {\n            var targetIndex  = MainViewManager.findInWorkingSet(MainViewManager.ACTIVE_PANE, file.fullPath),\n                workingSetListSize = MainViewManager.getWorkingSetSize(MainViewManager.ACTIVE_PANE);\n\n            if (targetIndex === workingSetListSize - 1) { // hide \"Close Others Below\" if the last file in Working Files is selected\n                CommandManager.get(closeBelow).setEnabled(false);\n            } else {\n                CommandManager.get(closeBelow).setEnabled(true);\n            }\n\n            if (workingSetListSize === 1) { // hide \"Close Others\" if there is only one file in Working Files\n                CommandManager.get(closeOthers).setEnabled(false);\n            } else {\n                CommandManager.get(closeOthers).setEnabled(true);\n            }\n\n            if (targetIndex === 0) { // hide \"Close Others Above\" if the first file in Working Files is selected\n                CommandManager.get(closeAbove).setEnabled(false);\n            } else {\n                CommandManager.get(closeAbove).setEnabled(true);\n            }\n        }\n    }\n\n\n    /**\n     * Returns the preferences used to add/remove the menu items\n     * @return {{closeBelow: boolean, closeOthers: boolean, closeAbove: boolean}}\n     */\n    function getPreferences() {\n        // It's senseless to look prefs up for the current file, instead look them up for\n        // the current project (or globally)\n        return {\n            closeBelow  : prefs.get(\"below\",  PreferencesManager.CURRENT_PROJECT),\n            closeOthers : prefs.get(\"others\", PreferencesManager.CURRENT_PROJECT),\n            closeAbove  : prefs.get(\"above\",  PreferencesManager.CURRENT_PROJECT)\n        };\n    }\n\n    /**\n     * When the preferences changed, add/remove the required menu items\n     */\n    function prefChangeHandler() {\n        var prefs = getPreferences();\n\n        if (prefs.closeBelow !== menuEntriesShown.closeBelow) {\n            if (prefs.closeBelow) {\n                workingSetListCmenu.addMenuItem(closeBelow, \"\", Menus.AFTER, Commands.FILE_CLOSE);\n            } else {\n                workingSetListCmenu.removeMenuItem(closeBelow);\n            }\n        }\n\n        if (prefs.closeOthers !== menuEntriesShown.closeOthers) {\n            if (prefs.closeOthers) {\n                workingSetListCmenu.addMenuItem(closeOthers, \"\", Menus.AFTER, Commands.FILE_CLOSE);\n            } else {\n                workingSetListCmenu.removeMenuItem(closeOthers);\n            }\n        }\n\n        if (prefs.closeAbove !== menuEntriesShown.closeAbove) {\n            if (prefs.closeAbove) {\n                workingSetListCmenu.addMenuItem(closeAbove, \"\", Menus.AFTER, Commands.FILE_CLOSE);\n            } else {\n                workingSetListCmenu.removeMenuItem(closeAbove);\n            }\n        }\n\n        menuEntriesShown = prefs;\n    }\n\n    /**\n     * Register the Commands and add the Menu Items, if required\n     */\n    function initializeCommands() {\n        var prefs = getPreferences();\n\n        CommandManager.register(Strings.CMD_FILE_CLOSE_BELOW, closeBelow, function () {\n            handleClose(closeBelow);\n        });\n        CommandManager.register(Strings.CMD_FILE_CLOSE_OTHERS, closeOthers, function () {\n            handleClose(closeOthers);\n        });\n        CommandManager.register(Strings.CMD_FILE_CLOSE_ABOVE, closeAbove, function () {\n            handleClose(closeAbove);\n        });\n\n        if (prefs.closeBelow) {\n            workingSetListCmenu.addMenuItem(closeBelow, \"\", Menus.AFTER, Commands.FILE_CLOSE);\n        }\n        if (prefs.closeOthers) {\n            workingSetListCmenu.addMenuItem(closeOthers, \"\", Menus.AFTER, Commands.FILE_CLOSE);\n        }\n        if (prefs.closeAbove) {\n            workingSetListCmenu.addMenuItem(closeAbove, \"\", Menus.AFTER, Commands.FILE_CLOSE);\n        }\n        menuEntriesShown = prefs;\n    }\n\n\n    // Initialize using the prefs\n    initializeCommands();\n\n    // Add a context menu open handler\n    workingSetListCmenu.on(\"beforeContextMenuOpen\", contextMenuOpenHandler);\n\n    prefs.on(\"change\", prefChangeHandler);\n});\n"
  },
  {
    "path": "src/extensions/default/CloseOthers/unittest-files/dummy.js",
    "content": "//This is dummy file. To commit unnittest-files folder git needs a file.\n"
  },
  {
    "path": "src/extensions/default/CloseOthers/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, runs, waitsForDone, spyOn */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        FileUtils\t\t= brackets.getModule(\"file/FileUtils\"),\n        CommandManager,\n        Commands,\n        Dialogs,\n        EditorManager,\n        DocumentManager,\n        MainViewManager,\n        FileSystem;\n\n    describe(\"CloseOthers\", function () {\n        var extensionPath = FileUtils.getNativeModuleDirectoryPath(module),\n            testPath      = extensionPath + \"/unittest-files/\",\n            testWindow,\n            $,\n            docSelectIndex,\n            cmdToRun,\n            brackets;\n\n        function createUntitled(count) {\n            function doCreateUntitled(content) {\n                runs(function () {\n                    var promise = CommandManager.execute(Commands.FILE_NEW_UNTITLED);\n                    promise.done(function (untitledDoc) {\n                        untitledDoc.replaceRange(content, {line: 0, ch: 0});\n                    });\n                    waitsForDone(promise, \"FILE_NEW_UNTITLED\");\n                });\n            }\n\n            var i;\n            for (i = 0; i < count; i++) {\n                doCreateUntitled(String(i));\n            }\n        }\n\n        /** Expect a file to exist (failing test if not) and then delete it */\n        function expectAndDelete(fullPath) {\n            runs(function () {\n                var promise = SpecRunnerUtils.resolveNativeFileSystemPath(fullPath);\n                waitsForDone(promise, \"Verify file exists: \" + fullPath);\n            });\n            runs(function () {\n                var promise = SpecRunnerUtils.deletePath(fullPath);\n                waitsForDone(promise, \"Remove testfile \" + fullPath, 5000);\n            });\n        }\n\n        function getFilename(i) {\n            return testPath + \"test_closeothers\" + i + \".js\";\n        }\n\n        beforeEach(function () {\n\n            runs(function () {\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow = w;\n                    $ = testWindow.$;\n                    brackets\t\t= testWindow.brackets;\n                    DocumentManager = testWindow.brackets.test.DocumentManager;\n                    MainViewManager = testWindow.brackets.test.MainViewManager;\n                    CommandManager  = testWindow.brackets.test.CommandManager;\n                    EditorManager   = testWindow.brackets.test.EditorManager;\n                    Dialogs\t\t\t= testWindow.brackets.test.Dialogs;\n                    Commands        = testWindow.brackets.test.Commands;\n                    FileSystem      = testWindow.brackets.test.FileSystem;\n                });\n            });\n\n            runs(function () {\n                SpecRunnerUtils.loadProjectInTestWindow(testPath);\n            });\n\n            createUntitled(5);\n\n            runs(function () {\n                var fileI = 0;\n                spyOn(FileSystem, 'showSaveDialog').andCallFake(function (dialogTitle, initialPath, proposedNewName, callback) {\n                    callback(undefined, getFilename(fileI));\n                    fileI++;\n                });\n\n                var promise = CommandManager.execute(Commands.FILE_SAVE_ALL);\n                waitsForDone(promise, \"FILE_SAVE_ALL\", 5000);\n            });\n        });\n\n        afterEach(function () {\n            // Verify files exist & clean up\n            [0, 1, 2, 3, 4].forEach(function (i) {\n                expectAndDelete(getFilename(i));\n            });\n\n            testWindow    = null;\n            $             = null;\n            brackets      = null;\n            EditorManager = null;\n            SpecRunnerUtils.closeTestWindow();\n        });\n\n\n        function runCloseOthers() {\n            var ws = MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE),\n                promise;\n\n            if (ws.length > docSelectIndex) {\n                DocumentManager.getDocumentForPath(ws[docSelectIndex].fullPath).done(function (doc) {\n                    MainViewManager._edit(MainViewManager.ACTIVE_PANE, doc);\n                });\n\n                runs(function () {\n                    promise = CommandManager.execute(cmdToRun);\n                    waitsForDone(promise, cmdToRun);\n                });\n                runs(function () {\n                    expect(MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE)).toEqual(ws[docSelectIndex].fullPath, \"Path of document in editor after close others command should be the document that was selected\");\n                });\n            }\n        }\n\n        it(\"Close others\", function () {\n            docSelectIndex = 2;\n            cmdToRun       = \"file.close_others\";\n\n            runCloseOthers();\n\n            runs(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(1);\n            });\n        });\n\n        it(\"Close others above\", function () {\n            docSelectIndex = 2;\n            cmdToRun       = \"file.close_above\";\n\n            runCloseOthers();\n\n            runs(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(3);\n            });\n        });\n\n        it(\"Close others below\", function () {\n            docSelectIndex = 1;\n            cmdToRun       = \"file.close_below\";\n\n            runCloseOthers();\n\n            runs(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(2);\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/Prefs.js",
    "content": "/**\n * Wrapper around brackets pref system to ensure preferences are stored in in one single object instead of using multiple keys.\n * This is to make it easy for the user who edits their preferences file to easily manage the potentially numerous lines of preferences generated by the persisting code-folding state.\n * @author Patrick Oladimeji\n * @date 3/22/14 20:39:53 PM\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var ProjectManager              = brackets.getModule(\"project/ProjectManager\"),\n        PreferencesManager          = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings                     = brackets.getModule(\"strings\"),\n        prefs                       = PreferencesManager.getExtensionPrefs(\"code-folding\"),\n        FOLDS_PREF_KEY              = \"code-folding.folds\",\n        // preference key strings are here for now since they are not used in any UI\n        ENABLE_CODE_FOLDING         = \"Enable code folding\",\n        MIN_FOLD_SIZE               = \"Minimum fold size\",\n        SAVE_FOLD_STATES            = \"Save fold states\",\n        ALWAYS_USE_INDENT_FOLD      = \"Always use indent fold\",\n        HIDE_FOLD_BUTTONS           = \"Hide fold triangles\",\n        MAX_FOLD_LEVEL              = \"Max fold level\",\n        MAKE_SELECTIONS_FOLDABLE     = \"Makes selections foldable\";\n\n    //default preference values\n    prefs.definePreference(\"enabled\", \"boolean\", true,\n                           {name: ENABLE_CODE_FOLDING, description: Strings.DESCRIPTION_CODE_FOLDING_ENABLED});\n    prefs.definePreference(\"minFoldSize\", \"number\", 2,\n                           {name: MIN_FOLD_SIZE, description: Strings.DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE});\n    prefs.definePreference(\"saveFoldStates\", \"boolean\", true,\n                           {name: SAVE_FOLD_STATES, description: Strings.DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES});\n    prefs.definePreference(\"alwaysUseIndentFold\", \"boolean\", false,\n                           {name: ALWAYS_USE_INDENT_FOLD, description: Strings.DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD});\n    prefs.definePreference(\"hideUntilMouseover\", \"boolean\", false,\n                           {name: HIDE_FOLD_BUTTONS, description: Strings.DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER});\n    prefs.definePreference(\"maxFoldLevel\", \"number\", 2,\n                           {name: MAX_FOLD_LEVEL, description: Strings.DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL});\n    prefs.definePreference(\"makeSelectionsFoldable\", \"boolean\", true,\n                           {name: MAKE_SELECTIONS_FOLDABLE, description: Strings.DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE});\n\n    PreferencesManager.stateManager.definePreference(FOLDS_PREF_KEY, \"object\", {});\n\n    /**\n      * Simplifies the fold ranges into an array of pairs of numbers.\n      * @param {!Object} folds the raw fold ranges indexed by line numbers\n      * @return {Object} an object whose keys are line numbers and the values are array\n      * of two 2-element arrays. First array contains [from.line, from.ch] and the second contains [to.line, to.ch]\n      */\n    function simplify(folds) {\n        if (!folds) {\n            return;\n        }\n        var res = {}, range;\n        Object.keys(folds).forEach(function (line) {\n            range = folds[line];\n            res[line] = Array.isArray(range) ? range : [[range.from.line, range.from.ch], [range.to.line, range.to.ch]];\n        });\n        return res;\n    }\n\n    /**\n      * Inflates the fold ranges stored as simplified numeric arrays. The inflation converts the data into\n      * objects whose keys are line numbers and whose values are objects in the format {from: {line, ch}, to: {line, ch}}.\n      * @param {Object}  folds the simplified fold ranges\n      * @return {Object} the converted fold ranges\n      */\n    function inflate(folds) {\n        if (!folds) {\n            return;\n        }\n         //transform the folds into objects with from and to properties\n        var ranges = {}, obj;\n        Object.keys(folds).forEach(function (line) {\n            obj = folds[line];\n            ranges[line] = {from: {line: obj[0][0], ch: obj[0][1]}, to: {line: obj[1][0], ch: obj[1][1]}};\n        });\n\n        return ranges;\n    }\n\n    /**\n     * Returns a 'context' object for getting/setting project-specific view state preferences.\n     * Similar to code in MultiRangeInlineEditor._getPrefsContext()...\n     */\n    function getViewStateContext() {\n        var projectRoot = ProjectManager.getProjectRoot();  // note: null during unit tests!\n        return { location : { scope: \"user\",\n                              layer: \"project\",\n                              layerID: projectRoot && projectRoot.fullPath } };\n    }\n\n    /**\n      * Gets the line folds saved for the specified path.\n      * @param {string} path the document path\n      * @return {Object} the line folds for the document at the specified path\n      */\n    function getFolds(path) {\n        var context = getViewStateContext();\n        var folds = PreferencesManager.getViewState(FOLDS_PREF_KEY, context);\n        return inflate(folds[path]);\n    }\n\n    /**\n      * Saves the line folds for the specified path\n      * @param {!string} path the path to the document\n      * @param {Object} folds the fold ranges to save for the current document\n      */\n    function setFolds(path, folds) {\n        var context = getViewStateContext();\n        var allFolds = PreferencesManager.getViewState(FOLDS_PREF_KEY, context);\n        allFolds[path] = simplify(folds);\n        PreferencesManager.setViewState(FOLDS_PREF_KEY, allFolds, context);\n    }\n\n    /**\n      * Get the code folding setting with the specified key from the store\n      * @param {!string} key The key for the setting to retrieve\n      * @return {string} the setting with the specified key\n      */\n    function getSetting(key) {\n        return prefs.get(key);\n    }\n\n    /**\n      * Clears all the saved line folds for all documents.\n      */\n    function clearAllFolds() {\n        PreferencesManager.setViewState(FOLDS_PREF_KEY, {});\n    }\n\n    module.exports.getFolds = getFolds;\n    module.exports.setFolds = setFolds;\n    module.exports.getSetting = getSetting;\n    module.exports.clearAllFolds = clearAllFolds;\n    module.exports.prefsObject = prefs;\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/foldhelpers/foldSelected.js",
    "content": "/**\n * Selection range helper for code folding.\n * @author Patrick Oladimeji\n * @date 31/07/2015 00:11:53\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * This helper returns the start and end range representing the current selection in the editor.\n     * @param   {Object} cm    The Codemirror instance\n     * @param   {Object} start A Codemirror.Pos object {line, ch} representing the current line we are\n     *                          checking for fold ranges\n     * @returns {Object} The fold range, {from, to} representing the current selection.\n     */\n    function SelectionFold(cm, start) {\n        if (!cm.somethingSelected()) {\n            return;\n        }\n\n        var from = cm.getCursor(\"from\"),\n            to  = cm.getCursor(\"to\");\n        if (from.line === start.line) {\n            return {from: from, to: to};\n        }\n    }\n\n    module.exports = SelectionFold;\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/foldhelpers/foldcode.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n// Based on http://codemirror.net/addon/fold/foldcode.js\n// Modified by Patrick Oladimeji for Brackets\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n    var CodeMirror          = brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\"),\n        prefs               = require(\"Prefs\");\n\n    /**\n      * Performs the folding and unfolding of code regions.\n      * @param {CodeMirror} cm the CodeMirror instance\n      * @param {number| Object} pos\n      */\n    function doFold(cm, pos, options, force) {\n        options = options || {};\n        force = force || \"fold\";\n        if (typeof pos === \"number\") {\n            pos = CodeMirror.Pos(pos, 0);\n        }\n\n        var finder = options.rangeFinder || CodeMirror.fold.auto,\n            range,\n            widget,\n            textRange;\n\n        function getRange(allowFolded) {\n            var range = options.range || finder(cm, pos);\n            if (!range || range.to.line - range.from.line < prefs.getSetting(\"minFoldSize\")) {\n                return null;\n            }\n            var marks = cm.findMarksAt(range.from),\n                i,\n                lastMark,\n                foldMarks;\n            for (i = 0; i < marks.length; ++i) {\n                if (marks[i].__isFold && force !== \"fold\") {\n                    if (!allowFolded) {\n                        return null;\n                    }\n                    range.cleared = true;\n                    marks[i].clear();\n                }\n            }\n            //check for overlapping folds\n            if (marks && marks.length) {\n                foldMarks = marks.filter(function (d) {\n                    return d.__isFold;\n                });\n                if (foldMarks && foldMarks.length) {\n                    lastMark = foldMarks[foldMarks.length - 1].find();\n                    if (lastMark && range.from.line <= lastMark.to.line && lastMark.to.line < range.to.line) {\n                        return null;\n                    }\n                }\n            }\n            return range;\n        }\n\n        function makeWidget() {\n            var widget = window.document.createElement(\"span\");\n            widget.className = \"CodeMirror-foldmarker\";\n            return widget;\n        }\n\n        range = getRange(true);\n        if (options.scanUp) {\n            while (!range && pos.line > cm.firstLine()) {\n                pos = CodeMirror.Pos(pos.line - 1, 0);\n                range = getRange(false);\n            }\n        }\n        if (!range || range.cleared || force === \"unfold\" || range.to.line - range.from.line < prefs.getSetting(\"minFoldSize\")) {\n            if (range) { range.cleared = false; }\n            return;\n        }\n\n        widget = makeWidget();\n        textRange = cm.markText(range.from, range.to, {\n            replacedWith: widget,\n            clearOnEnter: true,\n            __isFold: true\n        });\n\n        CodeMirror.on(widget, \"mousedown\", function (e) {\n            textRange.clear();\n            e.preventDefault();\n        });\n\n        textRange.on(\"clear\", function (from, to) {\n            delete cm._lineFolds[from.line];\n            CodeMirror.signal(cm, \"unfold\", cm, from, to);\n        });\n\n        if (force === \"fold\") {\n            delete range.cleared;\n            // In some cases such as in xml style files, the start of  line folds can span multiple lines.\n            // For instance the attributes of an element can span multiple lines. In these cases when folding\n            // we want to render a gutter marker for both the beginning and end of the opening xml tag.\n            if (pos.line < range.from.line) {\n                cm._lineFolds[range.from.line] = range;\n            } else {\n                cm._lineFolds[pos.line] = range;\n            }\n        } else {\n            delete cm._lineFolds[pos.line];\n        }\n\n        CodeMirror.signal(cm, force, cm, range.from, range.to);\n        return range;\n    }\n\n    /**\n        Initialises extensions and helpers on the CodeMirror object\n    */\n    function init() {\n        CodeMirror.defineExtension(\"foldCode\", function (pos, options, force) {\n            return doFold(this, pos, options, force);\n        });\n\n        CodeMirror.defineExtension(\"unfoldCode\", function (pos, options) {\n            return doFold(this, pos, options, \"unfold\");\n        });\n\n        CodeMirror.defineExtension(\"isFolded\", function (line) {\n            return this._lineFolds && this._lineFolds[line];\n        });\n\n        /**\n          * Checks the validity of the ranges passed in the parameter and returns the foldranges\n          * that are still valid in the current document\n          * @param {object} folds the dictionary of lines in the current document that should be folded\n          * @returns {object} valid folds found in those passed in parameter\n          */\n        CodeMirror.defineExtension(\"getValidFolds\", function (folds) {\n            var keys, rf = CodeMirror.fold.auto, cm = this, result = {}, range, cachedRange;\n            if (folds && (keys = Object.keys(folds)).length) {\n                keys.forEach(function (lineNumber) {\n                    lineNumber = +lineNumber;\n                    if (lineNumber >= cm.firstLine() && lineNumber <= cm.lastLine()) {\n                        range = rf(cm, CodeMirror.Pos(lineNumber, 0));\n                        cachedRange = folds[lineNumber];\n                        if (range && cachedRange && range.from.line === cachedRange.from.line &&\n                                range.to.line === cachedRange.to.line) {\n                            result[lineNumber] = folds[lineNumber];\n                        }\n                    }\n                });\n            }\n            return result;\n        });\n\n        /**\n          * Utility function to fold the region at the current cursor position in  a document\n          * @param {CodeMirror} cm the CodeMirror instance\n          * @param {?options} options extra options to pass to the fold function\n          */\n        CodeMirror.commands.fold = function (cm, options) {\n            cm.foldCode(cm.getCursor(), options, \"fold\");\n        };\n\n        /**\n          * Utility function to unfold the region at the current cursor position in  a document\n          * @param {CodeMirror} cm the CodeMirror instance\n          * @param {?options} options extra options to pass to the fold function\n          */\n        CodeMirror.commands.unfold = function (cm, options) {\n            cm.foldCode(cm.getCursor(), options, \"unfold\");\n        };\n\n        /**\n          * Utility function to fold all foldable regions in a document\n          * @param {CodeMirror} cm the CodeMirror instance\n          */\n        CodeMirror.commands.foldAll = function (cm) {\n            cm.operation(function () {\n                var i, e;\n                for (i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) {\n                    cm.foldCode(CodeMirror.Pos(i, 0), null, \"fold\");\n                }\n            });\n        };\n\n        /**\n          * Utility function to unfold all folded regions in a document\n          * @param {CodeMirror} cm the CodeMirror instance\n          * @param {?number} from the line number for the beginning of the region to unfold\n          * @param {?number} to the line number for the end of the region to unfold\n          */\n        CodeMirror.commands.unfoldAll = function (cm, from, to) {\n            from = from || cm.firstLine();\n            to = to || cm.lastLine();\n            cm.operation(function () {\n                var i, e;\n                for (i = from, e = to; i <= e; i++) {\n                    if (cm.isFolded(i)) { cm.unfoldCode(i, {range: cm._lineFolds[i]}); }\n                }\n            });\n        };\n\n        /**\n          * Folds the specified range. The descendants of any fold regions within the range are also folded up to\n          * a level set globally in the `maxFoldLevel' preferences\n          * @param {CodeMirror} cm the CodeMirror instance\n          * @param {?number} start the line number for the beginning of the region to fold\n          * @param {?number} end the line number for the end of the region to fold\n          */\n        CodeMirror.commands.foldToLevel = function (cm, start, end) {\n            var rf = CodeMirror.fold.auto;\n            function foldLevel(n, from, to) {\n                if (n > 0) {\n                    var i = from, range;\n                    while (i < to) {\n                        range = rf(cm, CodeMirror.Pos(i, 0));\n                        if (range) {\n                            //call fold level for the range just folded\n                            foldLevel(n - 1, range.from.line + 1, range.to.line - 1);\n                            cm.foldCode(CodeMirror.Pos(i, 0), null, \"fold\");\n                            i = range.to.line + 1;\n                        } else {\n                            i++;\n                        }\n                    }\n                }\n            }\n            cm.operation(function () {\n                start = start === undefined ? cm.firstLine() : start;\n                end = end || cm.lastLine();\n                foldLevel(prefs.getSetting(\"maxFoldLevel\"), start, end);\n            });\n        };\n\n        /**\n          * Helper to combine an array of fold range finders into one. This goes through the\n          * list of fold helpers in the parameter arguments and returns the first non-null\n          * range found from calling the fold helpers in order.\n          */\n        CodeMirror.registerHelper(\"fold\", \"combine\", function () {\n            var funcs = Array.prototype.slice.call(arguments, 0);\n            return function (cm, start) {\n                var i;\n                for (i = 0; i < funcs.length; ++i) {\n                    var found = funcs[i] && funcs[i](cm, start);\n                    if (found) {\n                        return found;\n                    }\n                }\n            };\n        });\n\n        /**\n          * Creates a helper which returns the appropriate fold function based on the mode of the current position in\n          * a document.\n          * @param {CodeMirror} cm the CodeMirror instance\n          * @param {number} start the current position in the document\n          */\n        CodeMirror.registerHelper(\"fold\", \"auto\", function (cm, start) {\n            var helpers = cm.getHelpers(start, \"fold\"), i, range;\n            //ensure mode helper is loaded if there is one\n            var mode = cm.getMode().name;\n            var modeHelper = CodeMirror.fold[mode];\n            if (modeHelper && helpers.indexOf(modeHelper) < 0) {\n                helpers.push(modeHelper);\n            }\n            for (i = 0; i < helpers.length; i++) {\n                range = helpers[i](cm, start);\n                if (range && range.to.line - range.from.line >= prefs.getSetting(\"minFoldSize\")) { return range; }\n            }\n        });\n    }\n\n    exports.init = init;\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/foldhelpers/foldgutter.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n// Based on http://codemirror.net/addon/fold/foldgutter.js\n// Modified by Patrick Oladimeji for Brackets\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n    var CodeMirror      = brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\"),\n        prefs           = require(\"Prefs\");\n\n    function State(options) {\n        this.options = options;\n        this.from = this.to = 0;\n    }\n\n    function parseOptions(opts) {\n        if (opts === true) { opts = {}; }\n        if (!opts.gutter) { opts.gutter = \"CodeMirror-foldgutter\"; }\n        if (!opts.indicatorOpen) { opts.indicatorOpen = \"CodeMirror-foldgutter-open\"; }\n        if (!opts.indicatorFolded) { opts.indicatorFolded = \"CodeMirror-foldgutter-folded\"; }\n        return opts;\n    }\n\n    /**\n      * Utility for creating fold markers in fold gutter\n      * @param {string} spec the className for the marker\n      * @return {HTMLElement} a htmlelement representing the fold marker\n      */\n    function marker(spec) {\n        var elt = window.document.createElement(\"div\");\n        elt.className = spec;\n        return elt;\n    }\n\n    /**\n     * Checks whether or not a marker is a code-folding marker\n     * @param   {Object}   m a CodeMirror TextMarker object\n     * @returns {boolean} true if the marker is a codefolding range marker or false otherwise\n     */\n    function isFold(m) {\n        return m.__isFold;\n    }\n\n    /**\n      * Updates the gutter markers for the specified range\n      * @param {!CodeMirror} cm the CodeMirror instance for the active editor\n      * @param {!number} from the starting line for the update\n      * @param {!number} to the ending line for the update\n      */\n    function updateFoldInfo(cm, from, to) {\n        var minFoldSize = prefs.getSetting(\"minFoldSize\") || 2;\n        var opts = cm.state.foldGutter.options;\n        var fade = prefs.getSetting(\"hideUntilMouseover\");\n        var $gutter = $(cm.getGutterElement());\n        var i = from;\n\n        function clear(m) {\n            return m.clear();\n        }\n\n        /**\n          * @private\n          * helper function to check if the given line is in a folded region in the editor.\n          * @param {number} line the\n          * @return {Object} the range that hides the specified line or undefine if the line is not hidden\n          */\n        function _isCurrentlyFolded(line) {\n            var keys = Object.keys(cm._lineFolds), i = 0, range;\n            while (i < keys.length) {\n                range = cm._lineFolds[keys[i]];\n                if (range.from.line < line && range.to.line >= line) {\n                    return range;\n                }\n                i++;\n            }\n        }\n\n        /**\n            This case is needed when unfolding a region that does not cause the viewport to change.\n            For instance in a file with about 15 lines, if some code regions are folded and unfolded, the\n            viewport change event isn't fired by CodeMirror. The setTimeout is a workaround to trigger the\n            gutter update after the viewport has been drawn.\n        */\n        if (i === to) {\n            window.setTimeout(function () {\n                var vp = cm.getViewport();\n                updateFoldInfo(cm, vp.from, vp.to);\n            }, 200);\n        }\n\n        while (i < to) {\n            var sr = _isCurrentlyFolded(i), // surrounding range for the current line if one exists\n                range;\n            var mark = marker(\"CodeMirror-foldgutter-blank\");\n            var pos = CodeMirror.Pos(i, 0),\n                func = opts.rangeFinder || CodeMirror.fold.auto;\n            // don't look inside collapsed ranges\n            if (sr) {\n                i = sr.to.line + 1;\n            } else {\n                range = cm._lineFolds[i] || (func && func(cm, pos));\n\n                if (!fade || (fade && $gutter.is(\":hover\"))) {\n                    if (cm.isFolded(i)) {\n                        // expand fold if invalid\n                        if (range) {\n                            mark = marker(opts.indicatorFolded);\n                        } else {\n                            cm.findMarksAt(pos).filter(isFold)\n                                .forEach(clear);\n                        }\n                    } else {\n                        if (range && range.to.line - range.from.line >= minFoldSize) {\n                            mark = marker(opts.indicatorOpen);\n                        }\n                    }\n                }\n                cm.setGutterMarker(i, opts.gutter, mark);\n                i++;\n            }\n        }\n    }\n\n    /**\n      * Updates the fold information in the viewport for the specified range\n      * @param {CodeMirror} cm the instance of the CodeMirror object\n      * @param {?number} from the starting line number for the update\n      * @param {?number} to the end line number for the update\n      */\n    function updateInViewport(cm, from, to) {\n        var vp = cm.getViewport(), state = cm.state.foldGutter;\n        from = isNaN(from) ? vp.from : from;\n        to = isNaN(to) ? vp.to : to;\n\n        if (!state) { return; }\n        cm.operation(function () {\n            updateFoldInfo(cm, from, to);\n        });\n        state.from = from;\n        state.to = to;\n    }\n\n    /**\n     * Helper function to return the fold text marker on a line in an editor\n     * @param   {CodeMirror} cm   The CodeMirror instance for the active editor\n     * @param   {Number}     line The line number representing the position of the fold marker\n     * @returns {TextMarker} A CodeMirror TextMarker object\n     */\n    function getFoldOnLine(cm, line) {\n        var pos = CodeMirror.Pos(line, 0);\n        var folds = cm.findMarksAt(pos) || [];\n        folds = folds.filter(isFold);\n        return folds.length ? folds[0] : undefined;\n    }\n\n    /**\n     * Synchronises the code folding states in the CM doc to cm._lineFolds cache.\n     * When an undo operation is done, if folded code fragments are restored, then\n     * we need to update cm._lineFolds with the fragments\n     * @param {Object}   cm       cm the CodeMirror instance for the active  editor\n     * @param {Object}   from     starting position in the doc to sync the fold states from\n     * @param {[[Type]]} lineAdded a number to show how many lines where added to the document\n     */\n    function syncDocToFoldsCache(cm, from, lineAdded) {\n        var minFoldSize = prefs.getSetting(\"minFoldSize\") || 2;\n        var i, fold, range;\n        if (lineAdded <= 0) {\n            return;\n        }\n\n        for (i = from; i <= from + lineAdded; i = i + 1) {\n            fold = getFoldOnLine(cm, i);\n            if (fold) {\n                range = fold.find();\n                if (range && range.to.line - range.from.line >= minFoldSize) {\n                    cm._lineFolds[i] = range;\n                    i = range.to.line;\n                } else {\n                    delete cm._lineFolds[i];\n                }\n            }\n        }\n    }\n\n    /**\n     * Helper function to move a fold range object by the specified number of lines\n     * @param {Object} range    An object specifying the fold range to move. It contains {from, to} which are CodeMirror.Pos objects.\n     * @param {Number} numLines A positive or negative number representing the numbe of lines to move the range by\n     */\n    function moveRange(range, numLines) {\n        return {from: CodeMirror.Pos(range.from.line + numLines, range.from.ch),\n                to: CodeMirror.Pos(range.to.line + numLines, range.to.ch)};\n    }\n\n    /**\n      * Updates the line folds cache usually when the document changes.\n      * The following cases are accounted for:\n      * 1.  When the change does not add a new line to the document we check if the line being modified\n      *     is folded. If that is the case, changes to this line might affect the range stored in the cache\n      *     so we update the range using the range finder function.\n      * 2.  If lines have been added, we need to update the records for all lines in the folds cache\n      *     which are greater than the line position at which we are adding the new line(s). When existing\n      *     folds are above the addition we keep the original position in the cache.\n      * 3.  If lines are being removed, we need to update the records for all lines in the folds cache which are\n      *     greater than the line position at which we are removing the new lines, while making sure to\n      *     not include any folded lines in the cache that are part of the removed chunk.\n      * @param {!CodeMirror} cm        the CodeMirror instance for the active editor\n      * @param {!number}     from      the line number designating the start position of the change\n      * @param {!number}     linesDiff a number to show how many lines where removed or added to the document.\n      *                                This value is negative for deletions and positive for additions.\n      */\n    function updateFoldsCache(cm, from, linesDiff) {\n        var oldRange, newRange;\n        var minFoldSize = prefs.getSetting(\"minFoldSize\") || 2;\n        var foldedLines = Object.keys(cm._lineFolds).map(function (d) {\n            return +d;\n        });\n        var opts = cm.state.foldGutter.options || {};\n        var rf = opts.rangeFinder || CodeMirror.fold.auto;\n\n        if (linesDiff === 0) {\n            if (foldedLines.indexOf(from) >= 0) {\n                newRange = rf(cm, CodeMirror.Pos(from, 0));\n                if (newRange && newRange.to.line - newRange.from.line >= minFoldSize) {\n                    cm._lineFolds[from] = newRange;\n                } else {\n                    delete cm._lineFolds[from];\n                }\n            }\n        } else if (foldedLines.length) {\n            var newFolds = {};\n            foldedLines.forEach(function (line) {\n                oldRange = cm._lineFolds[line];\n                //update range with lines-diff\n                newRange = moveRange(oldRange, linesDiff);\n                // for removed lines we want to check lines that lie outside the deleted range\n                if (linesDiff < 0) {\n                    if (line < from) {\n                        newFolds[line] = oldRange;\n                    } else if (line >= from + Math.abs(linesDiff)) {\n                        newFolds[line + linesDiff] = newRange;\n                    }\n                } else {\n                    if (line < from) {\n                        newFolds[line] = oldRange;\n                    } else if (line >= from) {\n                        newFolds[line + linesDiff] = newRange;\n                    }\n                }\n            });\n            cm._lineFolds = newFolds;\n        }\n    }\n\n    /**\n      * Triggered when the content of the document changes. When the entire content of the document\n      * is changed - e.g., changes made from a different editor, the same lineFolds are kept only if\n      * they are still valid in the context of the new document content.\n      * @param {!CodeMirror} cm the CodeMirror instance for the active editor\n      * @param {!Object} changeObj detailed information about the change that occurred in the document\n      */\n    function onChange(cm, changeObj) {\n        if (changeObj.origin === \"setValue\") {//text content has changed outside of brackets\n            var folds = cm.getValidFolds(cm._lineFolds);\n            cm._lineFolds = folds;\n            Object.keys(folds).forEach(function (line) {\n                cm.foldCode(+line);\n            });\n        } else {\n            var state = cm.state.foldGutter;\n            var lineChanges = changeObj.text.length - changeObj.removed.length;\n            // for undo actions that add new line(s) to the document first update the folds cache as normal\n            // and then update the folds cache with any line folds that exist in the new lines\n            if (changeObj.origin === \"undo\" && lineChanges > 0) {\n                updateFoldsCache(cm, changeObj.from.line, lineChanges);\n                syncDocToFoldsCache(cm, changeObj.from.line, lineChanges);\n            } else {\n                updateFoldsCache(cm, changeObj.from.line, lineChanges);\n            }\n            if (lineChanges !== 0) {\n                updateFoldInfo(cm, Math.max(0, changeObj.from.line + lineChanges), Math.max(0, changeObj.from.line + lineChanges) + 1);\n            }\n            state.from = changeObj.from.line;\n            state.to = 0;\n            window.clearTimeout(state.changeUpdate);\n            state.changeUpdate = window.setTimeout(function () {\n                updateInViewport(cm);\n            }, 600);\n        }\n    }\n\n    /**\n      * Triggered on viewport changes e.g., user scrolls or resizes the viewport.\n      * @param {!CodeMirror} cm the CodeMirror instance for the active editor\n      */\n    function onViewportChange(cm) {\n        var state = cm.state.foldGutter;\n        window.clearTimeout(state.changeUpdate);\n        state.changeUpdate = window.setTimeout(function () {\n            var vp = cm.getViewport();\n            if (state.from === state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {\n                updateInViewport(cm);\n            } else {\n                cm.operation(function () {\n                    if (vp.from < state.from) {\n                        updateFoldInfo(cm, vp.from, state.from);\n                        state.from = vp.from;\n                    }\n                    if (vp.to > state.to) {\n                        updateFoldInfo(cm, state.to, vp.to);\n                        state.to = vp.to;\n                    } else {\n                        updateFoldInfo(cm, vp.from, vp.to);\n                        state.to = vp.to;\n                        state.from = vp.from;\n                    }\n                });\n            }\n        }, 400);\n    }\n\n    /**\n     * Triggered when the cursor moves in the editor and used to detect text selection changes\n     * in the editor.\n     * @param {!CodeMirror} cm the CodeMirror instance for the active editor\n     */\n    function onCursorActivity(cm) {\n        var state = cm.state.foldGutter;\n        var vp = cm.getViewport();\n        window.clearTimeout(state.changeUpdate);\n        state.changeUpdate = window.setTimeout(function () {\n            //need to render the entire visible viewport to remove fold marks rendered from previous selections if any\n            updateInViewport(cm, vp.from, vp.to);\n        }, 400);\n    }\n\n    /**\n      * Triggered when a code segment is folded.\n      * @param {!CodeMirror} cm the CodeMirror instance for the active editor\n      * @param {!Object} from  the ch and line position that designates the start of the region\n      * @param {!Object} to the ch and line position that designates the end of the region\n      */\n    function onFold(cm, from, to) {\n        var state = cm.state.foldGutter;\n        updateFoldInfo(cm, from.line, from.line + 1);\n    }\n\n    /**\n      * Triggered when a folded code segment is unfolded.\n      * @param {!CodeMirror} cm the CodeMirror instance for the active editor\n      * @param {!{line:number, ch:number}} from  the ch and line position that designates the start of the region\n      * @param {!{line:number, ch:number}} to the ch and line position that designates the end of the region\n      */\n    function onUnFold(cm, from, to) {\n        var state = cm.state.foldGutter;\n        var vp = cm.getViewport();\n        delete cm._lineFolds[from.line];\n        updateFoldInfo(cm, from.line, to.line || vp.to);\n    }\n\n    /**\n      * Initialises the fold gutter and registers event handlers for changes to document, viewport\n      * and user interactions.\n      */\n    function init() {\n        CodeMirror.defineOption(\"foldGutter\", false, function (cm, val, old) {\n            if (old && old !== CodeMirror.Init) {\n                cm.clearGutter(cm.state.foldGutter.options.gutter);\n                cm.state.foldGutter = null;\n                cm.off(\"gutterClick\", old.onGutterClick);\n                cm.off(\"change\", onChange);\n                cm.off(\"viewportChange\", onViewportChange);\n                cm.off(\"cursorActivity\", onCursorActivity);\n\n                cm.off(\"fold\", onFold);\n                cm.off(\"unfold\", onUnFold);\n                cm.off(\"swapDoc\", updateInViewport);\n            }\n            if (val) {\n                cm.state.foldGutter = new State(parseOptions(val));\n                updateInViewport(cm);\n                cm.on(\"gutterClick\", val.onGutterClick);\n                cm.on(\"change\", onChange);\n                cm.on(\"viewportChange\", onViewportChange);\n                cm.on(\"cursorActivity\", onCursorActivity);\n                cm.on(\"fold\", onFold);\n                cm.on(\"unfold\", onUnFold);\n                cm.on(\"swapDoc\", updateInViewport);\n            }\n        });\n    }\n\n    exports.init = init;\n    exports.updateInViewport = updateInViewport;\n\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/foldhelpers/handlebarsFold.js",
    "content": "/*\n * Copyright (c) 2016 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Fold range finder for handlebars/mustache template type files.\n * @author Patrick Oladimeji\n * @date 14/08/2016 22:04:21\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n    var CodeMirror  = brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\"),\n        _           = brackets.getModule(\"thirdparty/lodash\"),\n        StringUtils = brackets.getModule(\"utils/StringUtils\");\n\n    /**\n     * Utility function for scanning the text in a document until a certain condition is met\n     * @param {object}  cm  The code mirror object representing the document\n     * @param {string}  startCh  The start character position for the scan operation\n     * @param {number}  startLine The start line position for the scan operation\n     * @param {function (string): boolean} condition A predicate function that takes in the text seen so far and returns true if the scanning process should be halted\n     * @returns {{from:CodeMirror.Pos, to: CodeMirror.Pos, string: string}} An object representing the range of text scanned.\n     */\n    function scanTextUntil(cm, startCh, startLine, condition) {\n        var line = cm.getLine(startLine),\n            seen = \"\",\n            characterIndex = startCh,\n            currentLine = startLine,\n            range;\n        while (currentLine <= cm.lastLine()) {\n            if (line.length === 0) {\n                characterIndex = 0;\n                line = cm.getLine(++currentLine);\n            } else {\n                seen = seen.concat(line[characterIndex] || \"\");\n                if (condition(seen)) {\n                    range = {\n                        from: {ch: startCh, line: startLine},\n                        to: {ch: characterIndex, line: currentLine},\n                        string: seen\n                    };\n                    return range;\n                } else if (characterIndex >= line.length) {\n                    seen = seen.concat(cm.lineSeparator());\n                    if (condition(seen)) {\n                        range = {\n                            from: {ch: startCh, line: startLine},\n                            to: {ch: characterIndex, line: currentLine},\n                            string: seen\n                        };\n                        return range;\n                    }\n                    characterIndex = 0;\n                    line = cm.getLine(++currentLine);\n                } else {\n                    ++characterIndex;\n                }\n            }\n        }\n    }\n\n    /**\n     * Utility function used to detect the end of a helper name when scanning a series of text.\n     * The end of a helper name is signalled by a space character or the `}`\n     * @param   {string}  seen The string seen so far\n     * @returns {boolean} True when the end of a helper name has been detected.\n     */\n    function endHelperName(seen) {\n        return (/\\s$/).test(seen) || StringUtils.endsWith(seen, \"}\");\n    }\n\n    /**\n     * Returns a predicate function that returns true when a specific character is found\n     * @param   {string}   character the character to use in the match function\n     * @returns {function} A function that checks if the last character of the parameter string matches the parameter character\n     */\n    function readUntil(character) {\n        return function (seen) {\n            return seen[seen.length - 1] === character;\n        };\n    }\n\n    function getRange(cm, start) {\n        var currentLine = start.line,\n            text = cm.getLine(currentLine) || \"\",\n            i = 0,\n            tagStack = [],\n            braceStack = [],\n            found,\n            openTag,\n            openPos,\n            currentCharacter,\n            openTagIndex = text.indexOf(\"{{\"),\n            range;\n\n        if (openTagIndex < 0 || text[openTagIndex + 2] === \"/\") {\n            return;\n        }\n\n        found = scanTextUntil(cm, openTagIndex + 2, currentLine, endHelperName);\n        if (!found) {\n            return;\n        }\n\n        openPos = {\n            from: {line: currentLine, ch: openTagIndex},\n            to: found.to\n        };\n        openTag = found.string.substring(0, found.string.length - 1);\n        if (openTag[0] === \"#\" || openTag[0] === \"~\" || openTag[0] === \"^\") {\n            found = scanTextUntil(cm, openPos.to.ch, openPos.to.line, function (seen) {\n                return seen.length > 1 && seen.substr(-2) === \"}}\";\n            });\n            if (found) {\n                openPos.to = {line: found.to.line, ch: found.to.ch + 1};\n            }\n            tagStack.push(openTag.substr(1));\n        } else {\n            braceStack.push(\"{{\");\n        }\n\n        i = found.to.ch;\n        currentLine = found.to.line;\n\n        while (currentLine <= cm.lastLine()) {\n            text = cm.getLine(currentLine);\n            currentCharacter = (text && text[i]) || \"\";\n            switch (currentCharacter) {\n            case \"{\":\n                if (text[i + 1] === \"{\") {\n                    found = scanTextUntil(cm, i + 2, currentLine, endHelperName);\n                    if (found) {\n                        var tag = found.string.substring(0, found.string.length - 1);\n                        if (tag[0] === \"#\" || tag[0] === \"~\" || tag[0] === \"^\") {\n                            tagStack.push(tag.substr(1));\n                        } else if (tag[0] === \"/\" &&\n                                   (_.last(tagStack) === tag.substr(1) || _.last(tagStack) === \"*\" + tag.substr(1))) {\n                            tagStack.pop();\n                            if (tagStack.length === 0 && braceStack.length === 0) {\n                                range = {\n                                    from: openPos.to,\n                                    to: {ch: i, line: currentLine}\n                                };\n                                return range;\n                            }\n                        } else {\n                            braceStack.push(\"{{\");\n                        }\n                    }\n                }\n                break;\n            case \"}\":\n                if (text[i + 1] === \"}\") {\n                    braceStack.pop();\n                    if (braceStack.length === 0 && tagStack.length === 0) {\n                        range = {\n                            from: openPos.to,\n                            to: {ch: i, line: currentLine}\n                        };\n                        return range;\n                    }\n                }\n                break;\n            case \"\\\"\":\n            case \"'\":\n                found = scanTextUntil(cm, i + 1, currentLine, readUntil(text[i]));\n                if (found) {\n                    i = found.to.ch;\n                    currentLine = found.to.line;\n                }\n                break;\n            default:\n                break;\n            }\n\n            ++i;\n            if (i >= text.length) {\n                ++currentLine;\n                i = 0;\n            }\n        }\n    }\n\n    module.exports = getRange;\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/foldhelpers/indentFold.js",
    "content": "/**\n * Fold range finder based on line indentations. Ignores blank lines and commented lines\n * @author Patrick Oladimeji\n * @date 12/27/13 21:54:41 PM\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n    var CodeMirror  = brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\"),\n        cols        = CodeMirror.countColumn,\n        pos         = CodeMirror.Pos;\n\n    function lastNonEmptyLineNumber(cm) {\n        var lc = cm.lastLine(), line = cm.getLine(lc);\n        while (lc > 0 && line.trim().length === 0) {\n            lc--;\n            line = cm.getLine(lc);\n        }\n        return lc;\n    }\n\n    function indentFold(cm, start) {\n        var lineText = cm.getLine(start.line), tabSize = cm.getOption(\"tabSize\");\n\n        var lineIndent = cols(lineText, null, tabSize), collapsible = false, lineCount = cm.lineCount();\n        var token = cm.getTokenAt(pos(start.line, lineIndent + 1));\n        //no folding for blank lines or commented lines\n        if (lineText.trim().length === 0 || (token && token.type === \"comment\")) {\n            return;\n        }\n        var i, indent, currentLine;\n        for (i = start.line + 1; i < lineCount; i++) {\n            currentLine = cm.getLine(i);\n            indent = cols(currentLine, null, tabSize);\n\n            token = cm.getTokenAt(pos(i, indent + 1));\n            //only fold for non blank lines or non commented lines\n            if (currentLine.trim().length !== 0 && (token && token.type !== \"comment\")) {\n                if (!collapsible) {\n                    if (indent > lineIndent) {\n                        collapsible = true;\n                    }\n                } else {\n                    if (indent <= lineIndent) {\n                        return {from: pos(start.line, lineText.length),\n                                to: pos(i - 1, cm.getLine(i - 1).length)};\n                    }\n                }\n\n                if (indent === lineIndent || indent < lineIndent) {\n                    return;\n                }\n            }\n        }\n        //use last nonempty line as the end of the folding region if there is no explicit end to this indent\n        if (collapsible) {\n            i = lastNonEmptyLineNumber(cm);\n            return {from: pos(start.line, lineText.length), to: pos(i, cm.getLine(i).length)};\n        }\n    }\n\n    module.exports = indentFold;\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/main.js",
    "content": "/*\n* Copyright (c) 2013 Patrick Oladimeji. All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining a\n* copy of this software and associated documentation files (the \"Software\"),\n* to deal in the Software without restriction, including without limitation\n* the rights to use, copy, modify, merge, publish, distribute, sublicense,\n* and/or sell copies of the Software, and to permit persons to whom the\n* Software is furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n* DEALINGS IN THE SOFTWARE.\n*\n*/\n/**\n * Code folding extension for brackets\n * @author Patrick Oladimeji\n * @date 10/24/13 9:35:26 AM\n */\n \ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CodeMirror              = brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        AppInit                 = brackets.getModule(\"utils/AppInit\"),\n        CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        DocumentManager         = brackets.getModule(\"document/DocumentManager\"),\n        Editor                  = brackets.getModule(\"editor/Editor\").Editor,\n        EditorManager           = brackets.getModule(\"editor/EditorManager\"),\n        ProjectManager          = brackets.getModule(\"project/ProjectManager\"),\n        ViewStateManager        = brackets.getModule(\"view/ViewStateManager\"),\n        KeyBindingManager       = brackets.getModule(\"command/KeyBindingManager\"),\n        ExtensionUtils          = brackets.getModule(\"utils/ExtensionUtils\"),\n        Menus                   = brackets.getModule(\"command/Menus\"),\n        prefs                   = require(\"Prefs\"),\n        COLLAPSE_ALL            = \"codefolding.collapse.all\",\n        COLLAPSE                = \"codefolding.collapse\",\n        EXPAND                  = \"codefolding.expand\",\n        EXPAND_ALL              = \"codefolding.expand.all\",\n        GUTTER_NAME             = \"CodeMirror-foldgutter\",\n        CODE_FOLDING_GUTTER_PRIORITY   = Editor.CODE_FOLDING_GUTTER_PRIORITY,\n        codeFoldingMenuDivider  = \"codefolding.divider\",\n        collapseKey             = \"Ctrl-Alt-[\",\n        expandKey               = \"Ctrl-Alt-]\",\n        collapseAllKey          = \"Alt-1\",\n        expandAllKey            = \"Shift-Alt-1\",\n        collapseAllKeyMac       = \"Cmd-1\",\n        expandAllKeyMac         = \"Cmd-Shift-1\";\n\n    ExtensionUtils.loadStyleSheet(module, \"main.less\");\n\n    // Load CodeMirror addons\n    brackets.getModule([\"thirdparty/CodeMirror/addon/fold/brace-fold\"]);\n    brackets.getModule([\"thirdparty/CodeMirror/addon/fold/comment-fold\"]);\n    brackets.getModule([\"thirdparty/CodeMirror/addon/fold/markdown-fold\"]);\n\n    // Still using slightly modified versions of the foldcode.js and foldgutter.js since we\n    // need to modify the gutter click handler to take care of some collapse and expand features\n    // e.g. collapsing all children when 'alt' key is pressed\n    var foldGutter              = require(\"foldhelpers/foldgutter\"),\n        foldCode                = require(\"foldhelpers/foldcode\"),\n        indentFold              = require(\"foldhelpers/indentFold\"),\n        handlebarsFold          = require(\"foldhelpers/handlebarsFold\"),\n        selectionFold           = require(\"foldhelpers/foldSelected\");\n\n\n    /** Set to true when init() has run; set back to false after deinit() has run */\n    var _isInitialized = false;\n\n    /** Used to keep track of files for which line folds have been restored.*/\n\n    /**\n      * Restores the linefolds in the editor using values fetched from the preference store\n      * Checks the document to ensure that changes have not been made (e.g., in a different editor)\n      * to invalidate the saved line folds.\n      * Selection Folds are found by comparing the line folds in the preference store with the\n      * selection ranges in the viewState of the current document. Any selection range in the view state\n      * that is folded in the prefs will be folded. Unlike other fold range finder, the only validation\n      * on selection folds is to check that they satisfy the minimum fold range.\n      * @param {Editor} editor  the editor whose saved line folds should be restored\n      */\n    function restoreLineFolds(editor) {\n        /**\n         * Checks if the range from and to Pos is the same as the selection start and end Pos\n         * @param   {Object}  range     {from, to} where from and to are CodeMirror.Pos objects\n         * @param   {Object}  selection {start, end} where start and end are CodeMirror.Pos objects\n         * @returns {Boolean} true if the range and selection span the same region and false otherwise\n         */\n        function rangeEqualsSelection(range, selection) {\n            return range.from.line === selection.start.line && range.from.ch === selection.start.ch &&\n                range.to.line === selection.end.line && range.to.ch === selection.end.ch;\n        }\n\n        /**\n         * Checks if the range is equal to one of the selections in the viewState\n         * @param   {Object}  range     {from, to} where from and to are CodeMirror.Pos objects.\n         * @param   {Object}  viewState The current editor's ViewState object\n         * @returns {Boolean} true if the range is found in the list of selections or false if not.\n         */\n        function isInViewStateSelection(range, viewState) {\n            if (!viewState || !viewState.selections) {\n                return false;\n            }\n\n            return viewState.selections.some(function (selection) {\n                return rangeEqualsSelection(range, selection);\n            });\n        }\n\n        var saveFolds = prefs.getSetting(\"saveFoldStates\");\n        \n        if (!editor || !saveFolds) {\n            if (editor) {\n                editor._codeMirror._lineFolds = editor._codeMirror._lineFolds || {};\n            }\n            return;\n        }\n                \n        var cm = editor._codeMirror;\n        var viewState = ViewStateManager.getViewState(editor.document.file);\n        var path = editor.document.file.fullPath;\n        var folds = cm._lineFolds || prefs.getFolds(path) || {};\n        \n        //separate out selection folds from non-selection folds\n        var nonSelectionFolds = {}, selectionFolds = {}, range;\n        Object.keys(folds).forEach(function (line) {\n            range = folds[line];\n            if (isInViewStateSelection(range, viewState)) {\n                selectionFolds[line] = range;\n            } else {\n                nonSelectionFolds[line] = range;\n            }\n        });\n        nonSelectionFolds = cm.getValidFolds(nonSelectionFolds);\n        //add the selection folds\n        Object.keys(selectionFolds).forEach(function (line) {\n            nonSelectionFolds[line] = selectionFolds[line];\n        });\n        cm._lineFolds = nonSelectionFolds;\n        prefs.setFolds(path, cm._lineFolds);\n        Object.keys(cm._lineFolds).forEach(function (line) {\n            cm.foldCode(Number(line), {range: cm._lineFolds[line]});\n        });\n    }\n\n    /**\n      * Saves the line folds in the editor using the preference storage\n      * @param {Editor} editor the editor whose line folds should be saved\n      */\n    function saveLineFolds(editor) {\n        var saveFolds = prefs.getSetting(\"saveFoldStates\");\n        if (!editor || !saveFolds) {\n            return;\n        }\n        var folds = editor._codeMirror._lineFolds || {};\n        var path = editor.document.file.fullPath;\n        if (Object.keys(folds).length) {\n            prefs.setFolds(path, folds);\n        } else {\n            prefs.setFolds(path, undefined);\n        }\n    }\n\n    /**\n      * Event handler for gutter click. Manages folding and unfolding code regions. If the Alt key\n      * is pressed while clicking the fold gutter, child code fragments are also folded/unfolded\n      * up to a level defined in the `maxFoldLevel' preference.\n      * @param {!CodeMirror} cm the CodeMirror object\n      * @param {number} line the line number for the clicked gutter\n      * @param {string} gutter the name of the gutter element clicked\n      * @param {!KeyboardEvent} event the underlying dom event triggered for the gutter click\n      */\n    function onGutterClick(cm, line, gutter, event) {\n        var opts = cm.state.foldGutter.options, pos = CodeMirror.Pos(line);\n        if (gutter !== opts.gutter) { return; }\n        var range;\n        var _lineFolds = cm._lineFolds;\n        if (cm.isFolded(line)) {\n            if (event.altKey) { // unfold code including children\n                range = _lineFolds[line];\n                CodeMirror.commands.unfoldAll(cm, range.from.line, range.to.line);\n            } else {\n                cm.unfoldCode(line, {range: _lineFolds[line]});\n            }\n        } else {\n            if (event.altKey) {\n                range = CodeMirror.fold.auto(cm, pos);\n                if (range) {\n                    CodeMirror.commands.foldToLevel(cm, range.from.line, range.to.line);\n                }\n            } else {\n                cm.foldCode(line);\n            }\n        }\n    }\n\n    /**\n      * Collapses the code region nearest the current cursor position.\n      * Nearest is found by searching from the current line and moving up the document until an\n      * opening code-folding region is found.\n      */\n    function collapseCurrent() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        var cm = editor._codeMirror;\n        var cursor = editor.getCursorPos(), i;\n        // Move cursor up until a collapsible line is found\n        for (i = cursor.line; i >= 0; i--) {\n            if (cm.foldCode(i)) {\n                editor.setCursorPos(i);\n                return;\n            }\n        }\n    }\n\n    /**\n      * Expands the code region at the current cursor position.\n      */\n    function expandCurrent() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            var cursor = editor.getCursorPos(), cm = editor._codeMirror;\n            cm.unfoldCode(cursor.line);\n        }\n    }\n\n    /**\n      * Collapses all foldable regions in the current document. Folding is done up to a level 'n'\n      * which is defined in the `maxFoldLevel` preference. Levels refer to fold heirarchies e.g., for the following\n      * code fragment, the function is level 1, the if statement is level 2 and the forEach is level 3\n      *\n      *     function sample() {\n      *         if (debug) {\n      *             logMessages.forEach(function (m) {\n      *                 console.debug(m);\n      *             });\n      *         }\n      *     }\n      */\n    function collapseAll() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            var cm = editor._codeMirror;\n            CodeMirror.commands.foldToLevel(cm);\n        }\n    }\n\n    /**\n      * Expands all folded regions in the current document\n      */\n    function expandAll() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            var cm = editor._codeMirror;\n            CodeMirror.commands.unfoldAll(cm);\n        }\n    }\n\n    function clearGutter(editor) {\n        var cm = editor._codeMirror;\n        var BLANK_GUTTER_CLASS = \"CodeMirror-foldgutter-blank\";\n        editor.clearGutter(GUTTER_NAME);\n        var blank = window.document.createElement(\"div\");\n        blank.className = BLANK_GUTTER_CLASS;\n        var vp = cm.getViewport();\n        cm.operation(function () {\n            cm.eachLine(vp.from, vp.to, function (line) {\n                editor.setGutterMarker(line.lineNo(), GUTTER_NAME, blank);\n            });\n        });\n    }\n\n    /**\n      * Renders and sets up event listeners the code-folding gutter.\n      * @param {Editor} editor the editor on which to initialise the fold gutter\n      */\n    function setupGutterEventListeners(editor) {\n        var cm = editor._codeMirror;\n        $(editor.getRootElement()).addClass(\"folding-enabled\");\n        cm.setOption(\"foldGutter\", {onGutterClick: onGutterClick});\n\n        $(cm.getGutterElement()).on({\n            mouseenter: function () {\n                if (prefs.getSetting(\"hideUntilMouseover\")) {\n                    foldGutter.updateInViewport(cm);\n                } else {\n                    $(editor.getRootElement()).addClass(\"over-gutter\");\n                }\n            },\n            mouseleave: function () {\n                if (prefs.getSetting(\"hideUntilMouseover\")) {\n                    clearGutter(editor);\n                } else {\n                    $(editor.getRootElement()).removeClass(\"over-gutter\");\n                }\n            }\n        });\n    }\n\n    /**\n      * Remove the fold gutter for a given CodeMirror instance.\n      * @param {Editor} editor the editor instance whose gutter should be removed\n      */\n    function removeGutters(editor) {\n        Editor.unregisterGutter(GUTTER_NAME);\n        $(editor.getRootElement()).removeClass(\"folding-enabled\");\n        CodeMirror.defineOption(\"foldGutter\", false, null);\n    }\n\n    /**\n      * Add gutter and restore saved expand/collapse state.\n      * @param {Editor} editor the editor instance where gutter should be added.\n      */\n    function enableFoldingInEditor(editor) {\n        restoreLineFolds(editor);\n        setupGutterEventListeners(editor);\n        editor._codeMirror.refresh();\n    }\n\n    /**\n      * When a brand new editor is seen, initialise fold-gutter and restore line folds in it. \n      * Save line folds in departing editor in case it's getting closed.\n      * @param {object} event the event object\n      * @param {Editor} current the current editor\n      * @param {Editor} previous the previous editor\n      */\n    function onActiveEditorChanged(event, current, previous) {\n        if (current && !current._codeMirror._lineFolds) {\n            enableFoldingInEditor(current);\n        }\n        if (previous) {\n            saveLineFolds(previous);\n        }\n    }\n\n    /**\n      * Saves the line folds in the current full editor before it is closed.\n      */\n    function saveBeforeClose() {\n        // We've already saved all other open editors when they go active->inactive\n        saveLineFolds(EditorManager.getActiveEditor());\n    }\n\n    /**\n     * Remove code-folding functionality\n     */\n    function deinit() {\n        _isInitialized = false;\n\n        KeyBindingManager.removeBinding(collapseKey);\n        KeyBindingManager.removeBinding(expandKey);\n        KeyBindingManager.removeBinding(collapseAllKey);\n        KeyBindingManager.removeBinding(expandAllKey);\n        KeyBindingManager.removeBinding(collapseAllKeyMac);\n        KeyBindingManager.removeBinding(expandAllKeyMac);\n\n        //remove menus\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuDivider(codeFoldingMenuDivider.id);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(COLLAPSE);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(EXPAND);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(COLLAPSE_ALL);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(EXPAND_ALL);\n\n        EditorManager.off(\".CodeFolding\");\n        DocumentManager.off(\".CodeFolding\");\n        ProjectManager.off(\".CodeFolding\");\n\n        // Remove gutter & revert collapsed sections in all currently open editors\n        Editor.forEveryEditor(function (editor) {\n            CodeMirror.commands.unfoldAll(editor._codeMirror);\n        });\n        removeGutters();\n    }\n\n    /**\n     * Enable code-folding functionality\n     */\n    function init() {\n        _isInitialized = true;\n\n        foldCode.init();\n        foldGutter.init();\n\n        // Many CodeMirror modes specify which fold helper should be used for that language. For a few that\n        // don't, we register helpers explicitly here. We also register a global helper for generic indent-based\n        // folding, which cuts across all languages if enabled via preference.\n        CodeMirror.registerGlobalHelper(\"fold\", \"selectionFold\", function (mode, cm) {\n            return prefs.getSetting(\"makeSelectionsFoldable\");\n        }, selectionFold);\n        CodeMirror.registerGlobalHelper(\"fold\", \"indent\", function (mode, cm) {\n            return prefs.getSetting(\"alwaysUseIndentFold\");\n        }, indentFold);\n\n        CodeMirror.registerHelper(\"fold\", \"handlebars\", handlebarsFold);\n        CodeMirror.registerHelper(\"fold\", \"htmlhandlebars\", handlebarsFold);\n        CodeMirror.registerHelper(\"fold\", \"htmlmixed\", handlebarsFold);\n\n        EditorManager.on(\"activeEditorChange.CodeFolding\", onActiveEditorChanged);\n        DocumentManager.on(\"documentRefreshed.CodeFolding\", function (event, doc) {\n            restoreLineFolds(doc._masterEditor);\n        });\n\n        ProjectManager.on(\"beforeProjectClose.CodeFolding beforeAppClose.CodeFolding\", saveBeforeClose);\n\n        //create menus\n        codeFoldingMenuDivider = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuDivider();\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(COLLAPSE_ALL);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(EXPAND_ALL);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(COLLAPSE);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(EXPAND);\n\n        //register keybindings\n        KeyBindingManager.addBinding(COLLAPSE_ALL, [ {key: collapseAllKey}, {key: collapseAllKeyMac, platform: \"mac\"} ]);\n        KeyBindingManager.addBinding(EXPAND_ALL, [ {key: expandAllKey}, {key: expandAllKeyMac, platform: \"mac\"} ]);\n        KeyBindingManager.addBinding(COLLAPSE, collapseKey);\n        KeyBindingManager.addBinding(EXPAND, expandKey);\n\n\n        // Add gutters & restore saved expand/collapse state in all currently open editors\n        Editor.registerGutter(GUTTER_NAME, CODE_FOLDING_GUTTER_PRIORITY);\n        Editor.forEveryEditor(function (editor) {\n            enableFoldingInEditor(editor);\n        });\n    }\n\n    /**\n      * Register change listener for the preferences file.\n      */\n    function watchPrefsForChanges() {\n        prefs.prefsObject.on(\"change\", function (e, data) {\n            if (data.ids.indexOf(\"enabled\") > -1) {\n                // Check if enabled state mismatches whether code-folding is actually initialized (can't assume\n                // since preference change events can occur when the value hasn't really changed)\n                var isEnabled = prefs.getSetting(\"enabled\");\n                if (isEnabled && !_isInitialized) {\n                    init();\n                } else if (!isEnabled && _isInitialized) {\n                    deinit();\n                }\n            }\n        });\n    }\n\n    AppInit.htmlReady(function () {\n        CommandManager.register(Strings.COLLAPSE_ALL, COLLAPSE_ALL, collapseAll);\n        CommandManager.register(Strings.EXPAND_ALL, EXPAND_ALL, expandAll);\n        CommandManager.register(Strings.COLLAPSE_CURRENT, COLLAPSE, collapseCurrent);\n        CommandManager.register(Strings.EXPAND_CURRENT, EXPAND, expandCurrent);\n\n        if (prefs.getSetting(\"enabled\")) {\n            init();\n        }\n        watchPrefsForChanges();\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/main.less",
    "content": "@font-size: 1.1em;\n@color-triangle: #ccc;\n@color-triangle-mouseover: #aaa;\n@color-triangle-collapsed: #999;\n@color-marker-bg: #fff;\n@color-marker-border: #d7d7d7;\n@color-marker-text: #777;\n\n.CodeMirror-foldgutter {\n    &-open:after {\n        content: \"\\25bc\";\n        font-size: @font-size;\n        color: @color-triangle;\n    }\n    &-folded:after {\n        content: \"\\25b6\";\n        font-size: @font-size;\n        color: @color-triangle-collapsed;\n    }\n}\n\n.CodeMirror.over-gutter, .CodeMirror-activeline {\n    .CodeMirror-foldgutter-open:after {\n        color: @color-triangle-mouseover;\n    }\n}\n\n.CodeMirror-foldgutter,\n.CodeMirror-foldgutter-open,\n.CodeMirror-foldgutter-folded,\n.CodeMirror-foldgutter-blank {\n    width: @font-size;\n    cursor: default;\n    line-height: 100%;\n}\n\n.CodeMirror-foldgutter-open,\n.CodeMirror-foldgutter-folded {\n    padding-top: 2px;\n}\n\n.CodeMirror-gutter-elt {\n    height: 100% !important;\n}\n\n.CodeMirror.folding-enabled .CodeMirror-linenumber {\n    // Normally linenumber gutter has large right-padding to separate it from the code's text. But the\n    // folding gutter provides that same separation, so we need much less padding when it's displayed.\n    padding-right: 5px;\n}\n\n// If line numbers are not shown and codefolding is enabled we remove the left padding.\n// We add the same padding below to the fold gutter\n.show-line-padding {\n    .folding-enabled.linenumber-disabled pre {\n        padding-left: 0;\n    }\n}\n\n.CodeMirror.linenumber-disabled {\n    // When there are no line numbers, .show-line-padding class adds 15px left padding to line numbers.\n    // Here we compensate for that gap by adding the same padding to the folding gutter.\n    .CodeMirror-foldgutter,\n    .CodeMirror-foldgutter-open,\n    .CodeMirror-foldgutter-folded,\n    .CodeMirror-foldgutter-blank {\n        padding-left: 15px;\n    }\n}\n\n.CodeMirror-foldmarker {\n    // Re-enabling the pointer events for the fold marker. As pointer events are disabled for \"CodeMirror-lines\"\n    // to fix issue #2780.\n    pointer-events: auto;\n    padding-right: 3px;\n    padding-left: 3px;\n    margin-right: 3px;\n    margin-left: 3px;\n    border-radius: 2px;\n    cursor: pointer;\n    border: 1px solid @color-marker-border;\n    color: @color-marker-text;\n    background-color: @color-marker-bg;\n\n    &:after {\n        content: \"...\";\n        font-size: 1em;\n        vertical-align: top;\n        line-height: 0.8em;\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/package.json",
    "content": "{\n    \"title\": \"Code Folding\",\n    \"name\": \"code-folding\",\n    \"author\": \"Patrick Oladimeji <patrick@dustygem.co.uk>\",\n    \"contributors\": [\n        {\"name\": \"Patrick Oladimeji\", \"email\": \"thehogfather@dustygem.co.uk\", \"url\": \"https://github.com/thehogfather\"},\n        {\"name\": \"Daniel Glazman\", \"email\": \"daniel@glazman.org\"}\n    ],\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/unittest-files/test.hbs",
    "content": "{{!--\n        comments\n        go\n        here\n--}}\n\n{{#test}}\n\n\n{{/test}}\n\n<h1>Comments</h1>\n\n<div id=\"comments\">\n\n    {{#each comments}}\n        {{../permalink\n\n        }}\n\n        {{#if title}}\n            {{../permalink}}\n        {{/if}}\n    {{/each}}\n\n    {{#each comments}}\n    <h2><a href=\"/posts/{{../permalink}}#{{id}}\">{{title}}</a></h2>\n    <div>\n        {{\n            body\n        }}\n        <section class=\"person\">\n            {{~person}}\n                <div>Name: {{firstName}} {{lastName}}</div>\n                <div>Email: {{email}}</div>\n                <div>Phone: {{phone}}</div>\n            {{/person}}\n            {{#*inline \"myPartial\"}}\n                My Content\n            {{/inline}}\n            {{^relationships}}\n                Relationship details go here\n            {{/relationships}}\n        </section>\n    </div>\n    {{/each}}\n</div>\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/unittest-files/test.html",
    "content": "<html>\n    <head>\n        <style>      \n            .test {\n                /* this should be collapsible */\n            }\n        </style>\n        <script>\n            function () {\n                /* this should be collapsible */\n            }\n        </script>\n    </head>\n    <body>\n        <form action=\"#\" method=\"post\">\n            <div>\n                 <label for=\"name\">Text Input:</label>\n                 <input type=\"text\" name=\"name\" id=\"name\" value=\"\" tabindex=\"1\" />\n            </div>\n            <table>\n                <thead>\n                    <tr>\n                        <th>\n                           {{handlebars}}\n                        </th>\n                    </tr>\n                </thead>\n                <tbody>\n                    <tr>\n                        <td></td>\n                    </tr>\n                </tbody>\n            </table>\n            <div>\n                 <h4>Radio Button Choice</h4>\n\n                 <label \n                        for=\"radio-choice-1\">\n                     Choice 1\n                </label>\n                 <input type=\"radio\" name=\"radio-choice-1\" id=\"radio-choice-1\" tabindex=\"2\" value=\"choice-1\" />\n\n                 <label for=\"radio-choice-2\">Choice 2</label>\n                 <input type=\"radio\" name=\"radio-choice-2\" id=\"radio-choice-2\" tabindex=\"3\" value=\"choice-2\" />\n            </div>\n        </form>\n    </body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/unittest-files/test.js",
    "content": "/**\n  * Synchronises the code folding states in the CM doc to cm._lineFolds cache.\n  * When an undo operation is done, if folded code fragments are restored, then\n  * we need to update cm._lineFolds with the fragments\n  * @param {Object}   cm        cm the CodeMirror instance for the active  editor\n  * @param {Object}   from      starting position in the doc to sync the fold states from\n  * @param {[[Type]]} lineAdded a number to show how many lines where added to the document\n*/\n/*global define, brackets, document, window, $, CodeMirror, isFold, prefs*/\n\nfunction syncDocToFoldsCache(cm, from, lineAdded) {\n    \"use strict\";\n    var minFoldSize = prefs.getSetting(\"minFoldSize\") || 2;\n    var opts = cm.state.foldGutter.options || {};\n    var rf = opts.rangeFinder || CodeMirror.fold.auto;\n    var i, pos, folds, fold, range;\n    if (lineAdded <= 0) {\n        return;\n    }\n\n    for (i = from; i <= from + lineAdded; i = i + 1) {\n        pos = CodeMirror.Pos(i);\n        folds = cm.doc.findMarksAt(pos).filter(isFold);\n        fold = folds.length ? fold = folds[0] : undefined;\n        if (fold) {\n            range = rf(cm, CodeMirror.Pos(i));\n            if (range && range.to.line - range.from.line >= minFoldSize) {\n                cm._lineFolds[i] = range;\n                i = range.to.line;\n            } else {\n                delete cm._lineFolds[i];\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/extensions/default/CodeFolding/unittests.js",
    "content": "/**\n * Codefolding unit test files\n * @author Patrick Oladimeji\n * @date 01/08/2015 18:34\n */\n\n/*global describe, beforeEach, afterEach, it, expect, runs, waitsForDone, waitsFor*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        FileUtils = brackets.getModule(\"file/FileUtils\");\n\n    describe(\"Code Folding\", function () {\n        var testWindow,\n            testEditor,\n            EditorManager,\n            DocumentManager,\n            CommandManager,\n            PreferencesManager,\n            prefs,\n            cm,\n            gutterName = \"CodeMirror-foldgutter\",\n            foldMarkerOpen = gutterName + \"-open\",\n            foldMarkerClosed = gutterName + \"-folded\";\n        var extensionPath = FileUtils.getNativeModuleDirectoryPath(module),\n            testDocumentDirectory = extensionPath + \"/unittest-files/\",\n            // The line numbers referenced below are dependent on the files in /unittest-files directory.\n            // Remember to update the numbers if the files change.\n            testFilesSpec = {\n                js: {\n                    filePath: testDocumentDirectory + \"test.js\",\n                    foldableLines: [1, 11, 17, 21, 25, 27, 30],\n                    sameLevelFoldableLines: [17, 21],\n                    firstSelection: {start: {line: 2, ch: 0}, end: {line: 10, ch: 0}},\n                    secondSelection: {start: {line: 5, ch: 0}, end: {line: 8, ch: 4}}\n                },\n                html: {\n                    filePath: testDocumentDirectory + \"test.html\",\n                    foldableLines: [1, 2, 3, 4, 8, 9, 14, 15, 16, 20, 21, 22, 23, 28, 29, 34, 37],\n                    sameLevelFoldableLines: [3, 8],\n                    firstSelection: {start: {line: 38, ch: 0}, end: {line: 41, ch: 0}},\n                    secondSelection: {start: {line: 42, ch: 0}, end: {line: 45, ch: 4}}\n                },\n                hbs: {\n                    filePath: testDocumentDirectory + \"test.hbs\",\n                    foldableLines: [1, 7, 14, 16, 17, 21, 26, 28, 29, 32, 33, 38, 41],\n                    sameLevelFoldableLines: [1, 7, 14],\n                    firstSelection: {start: {line: 2, ch: 0}, end: {line: 10, ch: 0}},\n                    secondSelection: {start: {line: 5, ch: 0}, end: {line: 8, ch: 4}}\n                }\n            },\n            open = \"open\",\n            folded = \"folded\";\n\n        /**\n         * Utility to temporarily set preference values in the session scope\n         */\n        function setPreference(key, value) {\n            prefs.set(key, value, {\n                locations: {\n                    scope: \"session\"\n                }\n            });\n        }\n\n        /**\n         * Open a test file\n         * @param {String} path The path to the file to open\n         */\n        function openTestFile(path) {\n            var promise = SpecRunnerUtils.openProjectFiles([path]);\n            promise.then(function () {\n                testEditor = EditorManager.getCurrentFullEditor();\n                cm = testEditor._codeMirror;\n            });\n            waitsForDone(promise, \"Test file opened\", 3000);\n        }\n\n        /**\n         * Sets up the test window and loads the test project\n         */\n        function setup() {\n            runs(function () {\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow = w;\n                    EditorManager = w.brackets.test.EditorManager;\n                    DocumentManager = w.brackets.test.DocumentManager;\n                    PreferencesManager = w.brackets.test.PreferencesManager;\n                    CommandManager = w.brackets.test.CommandManager;\n\n                    prefs = PreferencesManager.getExtensionPrefs(\"code-folding\");\n                }, {hasNativeMenus: true});\n            });\n\n            runs(function () {\n                //setPreference(\"saveFoldStates\", false);\n                SpecRunnerUtils.loadProjectInTestWindow(testDocumentDirectory);\n            });\n        }\n\n        /**\n         * Closes the test window\n         */\n        function tearDown() {\n            SpecRunnerUtils.closeTestWindow();\n        }\n\n        /**\n         * Runs the specified command\n         * @param   {String}  command The command to run\n         * @returns {Promise} A promise that resolves after command execution is completed or failed\n         */\n        function runCommand(command) {\n            return CommandManager.execute(command);\n        }\n\n        /**\n         * Folds the code on the given line number\n         * @param {Number} line The line number to fold\n         */\n        function foldCodeOnLine(line) {\n            cm.setCursor(line - 1);\n            var promise = runCommand(\"codefolding.collapse\");\n            waitsForDone(promise, \"Collapse code\", 2000);\n        }\n\n        /**\n         * Expands the code on the given line number\n         * @param {Number} line The line number to fold\n         */\n        function expandCodeOnLine(line) {\n            cm.setCursor(line - 1);\n            var promise = runCommand(\"codefolding.expand\");\n            waitsForDone(promise, \"Expand code\", 2000);\n        }\n\n        /**\n         * Returns all the fold marks currently inside the editor\n         * @returns {Array<TextMark>} The fold marks currently inside the editor\n         */\n        function getEditorFoldMarks() {\n            testEditor = EditorManager.getCurrentFullEditor();\n            cm = testEditor._codeMirror;\n\n            var marks = cm.getAllMarks().filter(function (m) {\n                return m.__isFold;\n            });\n            return marks;\n        }\n\n        /**\n         * Gets information about the mark in the gutter specifically whether it is folded or open.\n         * @param   {Object} lineInfo The CodeMirror lineInfo object\n         * @returns {Object} an object with line and type property\n         */\n        function gutterMarkState(lineInfo) {\n            if (!lineInfo || !lineInfo.gutterMarkers) {\n                return;\n            }\n            var classes = lineInfo.gutterMarkers[gutterName].classList;\n            if (classes && classes.contains(foldMarkerClosed)) {\n                return {line: lineInfo.line, type: folded};\n            } else if (classes && classes.contains(foldMarkerOpen)) {\n                return {line: lineInfo.line, type: open};\n            }\n            return;\n        }\n\n        /**\n         * Helper function to return the fold markers on the current codeMirror instance\n         *\n         * @returns {Array<object>} An array of objects containing the line and the type of marker.\n         */\n        function getGutterFoldMarks() {\n            testEditor = EditorManager.getCurrentFullEditor();\n            cm = testEditor._codeMirror;\n            var marks = [];\n            cm.eachLine(function (lineHandle) {\n                var lineInfo = cm.lineInfo(lineHandle);\n                marks.push(gutterMarkState(lineInfo));\n            });\n\n            return marks.filter(function (m) { return m; });\n        }\n\n        /**\n         * Helper function to filter out all open gutter markers\n         * @param   {Object}  m the marker to filter\n         * @returns {boolean} true if the marker is open or false otherwise\n         */\n        function filterOpen(m) {\n            return m.type === open;\n        }\n\n        /**\n         * Helper function to filter out all closed gutter markers.\n         * @param   {Object}  m the marker to to filter\n         * @returns {boolean} true if the marker is closed or false otherwise\n         */\n        function filterFolded(m) {\n            return m.type === folded;\n        }\n\n        /*\n         * Helper function to return the line number on a marker\n         * @param   {Object} m the maker whose line number we want to retrieve\n         * @returns {Number} the line number of the marker\n         */\n        function getLineNumber(m) {\n            return m.line;\n        }\n\n        /**\n         * Helper function to change the lines to zero-based index\n         * @param   {Array<number>} lines the line numbers to change to zero base index\n         * @returns {Array<number>} the zero-based index of the lines passed in\n         */\n        function toZeroIndex(lines) {\n            return lines.map(function (l) {\n                return l - 1;\n            });\n        }\n\n        /**\n         * Helper function to select a range of text in the editor\n         * @param   {CodeMirror.Pos} start the start position of the selection\n         * @param   {CodeMirror.Pos} end   the end position of the selection\n         */\n        function selectTextInEditor(start, end) {\n            var marksVisible = false;\n            runs(function () {\n                cm.setSelection(start, end);\n                setTimeout(function () {\n                    //wait for foldmarks to be rendered\n                    marksVisible = true;\n                }, 410);\n            });\n\n            waitsFor(function () {\n                return marksVisible;\n            }, \"Fold markers now visible in gutter\", 500);\n        }\n\n        beforeEach(function () {\n            setup();\n        });\n\n        afterEach(function () {\n            testWindow.closeAllFiles();\n            tearDown();\n        });\n\n        Object.keys(testFilesSpec).forEach(function (file) {\n            var testFilePath = testFilesSpec[file].filePath;\n            var foldableLines = testFilesSpec[file].foldableLines;\n            var testFileSpec = testFilesSpec[file];\n            describe(file + \" - Editor/Gutter\", function () {\n                beforeEach(function () {\n                    runs(function () {\n                        openTestFile(testFilePath);\n                    });\n\n                    runs(function () {\n                        testEditor = EditorManager.getCurrentFullEditor();\n                        cm = testEditor._codeMirror;\n                    });\n                });\n\n                afterEach(function () {\n                    testWindow.closeAllFiles();\n                });\n\n                it(\"renders fold marks on startup\", function () {\n                    var marks = getGutterFoldMarks();\n                    expect(marks.length).toBeGreaterThan(0);\n                    marks.map(getLineNumber).forEach(function (line) {\n                        expect(toZeroIndex(foldableLines)).toContain(line);\n                    });\n                });\n\n                it(\"creates a folded region in editor when fold marker is clicked\", function () {\n                    var lineNumber = foldableLines[0];\n                    runs(function () {\n                        foldCodeOnLine(lineNumber);\n                    });\n\n                    runs(function () {\n                        var marks = getEditorFoldMarks();\n                        expect(marks.length).toEqual(1);\n                        expect(marks[0].lines[0].lineNo()).toEqual(lineNumber - 1);\n                    });\n                });\n\n                it(\"clears the folded region in editor when collapsed fold marker is clicked\", function () {\n                    var lineNumber = foldableLines[0];\n                    runs(function () {\n                        foldCodeOnLine(lineNumber);\n                    });\n                    runs(function () {\n                        expandCodeOnLine(lineNumber);\n                    });\n\n                    runs(function () {\n                        var marks = getEditorFoldMarks();\n                        expect(marks.length).toEqual(0);\n                    });\n                });\n\n                it(\"expands and updates the fold gutter when text marker for a folded region in editor is cleared\", function () {\n                    var lineNumber = foldableLines[0];\n                    runs(function () {\n                        foldCodeOnLine(lineNumber);\n                    });\n                    runs(function () {\n                        var marks = getEditorFoldMarks().filter(function (m) {\n                            var range = m.find();\n                            return range ? range.from.line === lineNumber - 1 : false;\n                        });\n                        marks[0].clear();\n                    });\n\n                    runs(function () {\n                        var marks = getEditorFoldMarks();\n                        var gutterMark = getGutterFoldMarks().filter(function (m) {\n                            return m.line === lineNumber - 1 && m.type === open;\n                        });\n                        expect(marks.length).toEqual(0);\n                        expect(gutterMark.length).toEqual(1);\n\n                    });\n                });\n\n                it(\"renders folded marker in the gutter for folded code regions\", function () {\n                    var lineNumbers = testFilesSpec[file].sameLevelFoldableLines;\n                    runs(function () {\n                        lineNumbers.forEach(function (l) {\n                            foldCodeOnLine(l);\n                        });\n                    });\n\n                    runs(function () {\n                        var marks = getGutterFoldMarks().filter(filterFolded);\n                        expect(marks.length).toEqual(lineNumbers.length);\n\n                        var gutterNumbers = marks\n                            .map(getLineNumber);\n                        expect(gutterNumbers).toEqual(toZeroIndex(lineNumbers));\n                    });\n                });\n\n                it(\"indicates foldable lines in the gutter\", function () {\n                    var lineNumbers = foldableLines;\n                    var marks = getGutterFoldMarks();\n                    var gutterNumbers = marks.filter(filterOpen)\n                        .map(getLineNumber);\n                    expect(gutterNumbers).toEqual(toZeroIndex(lineNumbers));\n                });\n\n                describe(\"Preferences\", function () {\n                    it(\"persists fold states\", function () {\n                        var lineNumbers = testFileSpec.sameLevelFoldableLines;\n                        runs(function () {\n                            lineNumbers.forEach(function (line) {\n                                foldCodeOnLine(line);\n                            });\n                        });\n                        runs(function () {\n                            testWindow.closeAllFiles();\n                        });\n\n                        runs(function () {\n                            openTestFile(testFilePath);\n                        });\n\n                        runs(function () {\n                            var marks = getEditorFoldMarks();\n                            var gutterNumbers = marks.map(function (mark) {\n                                return mark.lines[0].lineNo();\n                            });\n                            expect(gutterNumbers).toEqual(toZeroIndex(lineNumbers));\n                        });\n                    });\n\n                    it(\"can disable persistence of fold states\", function () {\n                        setPreference(\"saveFoldStates\", false);\n                        runs(function () {\n                            foldCodeOnLine(foldableLines[0]);\n                        });\n                        runs(function () {\n                            testWindow.closeAllFiles();\n                        });\n\n                        runs(function () {\n                            openTestFile(testFilePath);\n                        });\n\n                        runs(function () {\n                            var marks = getEditorFoldMarks();\n                            expect(marks.length).toEqual(0);\n                        });\n                        \n                        runs(function () {\n                            var lineNumbers = foldableLines;\n                            var marks = getGutterFoldMarks();\n                            var gutterNumbers = marks.filter(filterOpen)\n                                .map(getLineNumber);\n                            expect(gutterNumbers).toEqual(toZeroIndex(lineNumbers));\n                        });\n                    });\n\n                    it(\"can set the minimum fold size\", function () {\n                        setPreference(\"minFoldSize\", 20000);\n                        runs(function () {\n                            testWindow.closeAllFiles();\n                        });\n\n                        runs(function () {\n                            openTestFile(testFilePath);\n                        });\n\n                        runs(function () {\n                            var marks = getGutterFoldMarks();\n                            expect(marks.length).toEqual(0);\n                        });\n                    });\n\n                    it(\"can disable code folding\", function () {\n                        setPreference(\"enabled\", false);\n                        runs(function () {\n                            var marks = getEditorFoldMarks();\n                            expect(marks.length).toEqual(0);\n                        });\n                    });\n\n                    describe(\"Fold selected region\", function () {\n                        it(\"can be enabled by setting `makeSelectionsFoldable' to true\", function () {\n                            var start = testFileSpec.firstSelection.start, end = testFileSpec.firstSelection.end;\n                            setPreference(\"makeSelectionsFoldable\", true);\n\n                            selectTextInEditor(start, end);\n\n                            runs(function () {\n                                var marks = getGutterFoldMarks().filter(filterOpen).map(getLineNumber);\n                                expect(marks).toContain(start.line);\n                            });\n                        });\n\n                        it(\"can be disabled by setting `makeSelectionsFoldable' to false\", function () {\n                            setPreference(\"makeSelectionsFoldable\", false);\n                            var start = testFileSpec.firstSelection.start, end = testFileSpec.firstSelection.end;\n                            selectTextInEditor(start, end);\n\n                            runs(function () {\n                                var marks = getGutterFoldMarks().filter(filterOpen)\n                                    .map(getLineNumber).filter(function (d) {\n                                        return d === start.line;\n                                    });\n                                expect(marks.length).toEqual(0);\n                            });\n                        });\n\n                        it(\"shows fold ranges for only the most recent selection\", function () {\n                            var firstSelection = testFileSpec.firstSelection,\n                                secondSelection = testFileSpec.secondSelection;\n\n                            selectTextInEditor(firstSelection.start, firstSelection.end);\n\n                            selectTextInEditor(secondSelection.start, secondSelection.end);\n\n                            runs(function () {\n                                var marks = getGutterFoldMarks().filter(filterOpen)\n                                    .map(getLineNumber);\n                                expect(marks).toContain(secondSelection.start.line);\n                                expect(marks).not.toContain(firstSelection.start.line);\n                            });\n                        });\n                    });\n\n                });\n\n                describe(\"Editor text changes\", function () {\n                    var foldableLine = foldableLines[1],\n                        expandTimeoutElapsed = false;\n\n                    // add a line after folding a region preserves the region and the region can be unfolded\n                    it(\"can unfold a folded region after a line has been added above it\", function () {\n                        runs(function () {\n                            foldCodeOnLine(foldableLine);\n                            cm.replaceRange(\"\\r\\n\", {line: foldableLine - 1, ch: 0});\n                        });\n\n                        runs(function () {\n                            expandCodeOnLine(foldableLine + 1);\n                            setTimeout(function () {\n                                expandTimeoutElapsed = true;\n                            }, 400);\n                        });\n\n                        waitsFor(function () {\n                            return expandTimeoutElapsed;\n                        }, \"waiting a moment for gutter markerts to be re-rendered\", 500);\n\n                        runs(function () {\n                            var marks = getGutterFoldMarks().filter(filterFolded);\n                            expect(marks.length).toEqual(0);\n                        });\n\n                    });\n\n                    it(\"can unfold a folded region even after a line has been removed above it\", function () {\n                        runs(function () {\n                            foldCodeOnLine(foldableLine);\n                            cm.replaceRange(\"\", {line: foldableLine - 1, ch: 0}, {line: foldableLine, ch: 0});\n                        });\n\n                        runs(function () {\n                            expandCodeOnLine(foldableLine - 1);\n                            setTimeout(function () {\n                                expandTimeoutElapsed = true;\n                            }, 400);\n                        });\n\n                        waitsFor(function () {\n                            return expandTimeoutElapsed;\n                        }, \"waiting a moment for gutter markerts to be re-rendered\", 500);\n\n                        runs(function () {\n                            var marks = getGutterFoldMarks().filter(filterFolded);\n                            expect(marks.length).toEqual(0);\n                        });\n                    });\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/CommandLineTool/main.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global appshell */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Menus                   = brackets.getModule(\"command/Menus\"),\n        CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        Dialogs                 = brackets.getModule(\"widgets/Dialogs\"),\n        DefaultDialogs          = brackets.getModule(\"widgets/DefaultDialogs\"),\n        StringUtils             = brackets.getModule(\"utils/StringUtils\");\n\n    function _mapCLToolsErrorCodeToString(errorCode) {\n\n        var errorString;\n        switch (errorCode) {\n        case appshell.app.ERR_CL_TOOLS_RMFAILED:\n            errorString = Strings.ERROR_CLTOOLS_RMFAILED;\n            break;\n        case appshell.app.ERR_CL_TOOLS_MKDIRFAILED:\n            errorString = Strings.ERROR_CLTOOLS_MKDIRFAILED;\n            break;\n        case appshell.app.ERR_CL_TOOLS_SYMLINKFAILED:\n            errorString = Strings.ERROR_CLTOOLS_LNFAILED;\n            break;\n        case appshell.app.ERR_CL_TOOLS_SERVFAILED:\n            errorString = Strings.ERROR_CLTOOLS_SERVFAILED;\n            break;\n        case appshell.app.ERR_CL_TOOLS_NOTSUPPORTED:\n            errorString = Strings.ERROR_CLTOOLS_NOTSUPPORTED;\n            break;\n        default:\n            errorString = StringUtils.format(Strings.GENERIC_ERROR, errorCode);\n            break;\n        }\n\n        return errorString;\n    }\n\n    function handleInstallCommandResult(errorCode) {\n        var dialog;\n\n        if (errorCode === appshell.app.ERR_CL_TOOLS_CANCELLED) {\n            // The user has cancelled the authentication dialog.\n            return;\n        } else if (errorCode === appshell.app.NO_ERROR) {\n            // flag success message here.\n            dialog = Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_INFO,\n                Strings.CREATING_LAUNCH_SCRIPT_TITLE,\n                Strings.LAUNCH_SCRIPT_CREATE_SUCCESS\n            );\n            Dialogs.addLinkTooltips(dialog);\n\n        } else {\n            var errorString = _mapCLToolsErrorCodeToString(errorCode);\n            var errMsg = StringUtils.format(Strings.ERROR_CREATING_LAUNCH_SCRIPT, errorString);\n            dialog = Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_ERROR,\n                Strings.CREATING_LAUNCH_SCRIPT_TITLE,\n                errMsg\n            );\n            Dialogs.addLinkTooltips(dialog);\n        }\n    }\n\n    function handleInstallCommand() {\n        appshell.app.installCommandLine(function (serviceCode) {\n            handleInstallCommandResult(serviceCode);\n        });\n    }\n\n    // Register the command and add the menu to file menu.\n    function addCommand() {\n\n        var menu                    = Menus.getMenu(Menus.AppMenuBar.FILE_MENU),\n            INSTALL_COMMAND_SCRIPT  = \"file.installCommandScript\";\n\n        CommandManager.register(Strings.CMD_LAUNCH_SCRIPT_MAC, INSTALL_COMMAND_SCRIPT, handleInstallCommand);\n        menu.addMenuDivider();\n        menu.addMenuItem(INSTALL_COMMAND_SCRIPT);\n    }\n\n    // Append this menu only for Mac.\n    if (brackets.platform === \"mac\") {\n        addCommand();\n    }\n\n});\n"
  },
  {
    "path": "src/extensions/default/DarkTheme/main.less",
    "content": "// Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n// Style definitions are from\n// https://github.com/chriskempson/tomorrow-theme/tree/master/Brackets\n\n/*\n * Brackets Default Theme\n *\n * Defines all the variables that one can configure in a theme. This should\n * contain all variables / mixins for UI styling that we want to be able to\n * change in a theme.\n *\n * Throughout the rest of the LESS files we should _only_ use color\n * variable names that are on the LHS of the list below. So, if we\n * need a new color for some UI element, we should add a variable\n * in this file.\n */\n\n/* Define some variables used in multiple places */\n@background: #1d1f21;\n@foreground: #ddd;\n\n/* Code Styling */\n\n.CodeMirror, .CodeMirror-scroll {\n    background-color: @background;\n    color: @foreground;\n}\n\n.CodeMirror-focused .CodeMirror-activeline-background {\n    background: #2f2f2f;\n}\n\n.show-line-padding .CodeMirror-focused .CodeMirror-activeline-background {\n    box-shadow: inset 15px 0 0 0 #000;\n}\n\n.CodeMirror-focused .CodeMirror-activeline {\n    .CodeMirror-gutter-elt {\n        background: rgba(0, 0, 0, 0.2);\n        color: #fff;\n    }\n    .inline-widget .CodeMirror-gutter-elt {\n        color: #767676;\n    }\n}\n\n.cm-atom, .cm-string, .cm-string-2, .cm-hr {color: #d89333;}\n.cm-number, .cm-attribute, .cm-plus {color: #85a300;}\n.cm-def, .cm-property {color: #b77fdb;}\n.cm-variable, .cm-variable-2, .cm-variable-3, .cm-operator, .cm-meta, .cm-bracket {color: @foreground;}\n.cm-comment {color: #767676;}\n.cm-minus {color: #dc322f;}\n.cm-header {color: #d85896;}\n.cm-link {color: #b77fdb; text-decoration: none;}\n.cm-rangeinfo {color: #6c71c4;}\n.cm-keyword, .cm-qualifier, .cm-builtin, .cm-tag, .cm-quote {color: #6c9ef8;}\n.cm-error {color: #dc322f;}\n\n/* Extra CSS */\n\n.CodeMirror-searching {\n    background-color: #d3cd69;\n    &.searching-current-match {\n        background-color: #f6a644;\n    }\n}\n\n\n.CodeMirror-cursor {\n    border-left: 1px solid #c5c8c6 !important;\n}\n\n.CodeMirror-gutters {\n    background-color: @background;\n    border-right: none;\n}\n\n.CodeMirror-linenumber {\n    color: #767676;\n}\n\n.CodeMirror .CodeMirror-selected {\n    background: #333f48;\n}\n.CodeMirror-focused .CodeMirror-selected {\n    background: #0050a0;\n}\n\n.CodeMirror-matchingbracket, .CodeMirror-matchingtag {\n    /* Ensure visibility against gray inline editor background */\n    background-color: #2e5c00;\n    color: @foreground !important;\n}\n\n.CodeMirror-overwrite .CodeMirror-cursor {\n    border-left: none !important;\n    border-bottom: 1px solid #fff;\n}\n\n/*\n    CodeMirror's use of descendant selectors for certain styling causes problems when editors are\n    nested because, for items in the inner editor, the left-hand clause in the selector will now\n    match either the actual containing CodeMirror instance *OR* the outer \"host\" CodeMirror instance.\n\n    TODO (issue #324): We'll still have problems if editors can be nested more than one level deep,\n    or if any other descendant-selector-driven CM styles can differ between inner & outer editors\n    (potential problem areas include line wrap and coloring theme: basically, anything in codemirror.css\n    that uses a descandant selector where the CSS class name to the left of the space is something\n    other than a vanilla .CodeMirror)\n */\n.CodeMirror {\n    .CodeMirror {\n        background: transparent;\n    }\n\n    .CodeMirror .CodeMirror-gutters {\n        background: transparent;\n        border-right: none;\n    }\n\n    .CodeMirror .CodeMirror-activeline-background {\n        background: transparent;\n    }\n\n    .CodeMirror .CodeMirror-activeline .CodeMirror-gutter-elt {\n        background: transparent;\n        color: #767676;\n    }\n\n    .CodeMirror-focused .CodeMirror-activeline-background {\n        background: #2f2f2f;\n    }\n\n    .CodeMirror-focused .CodeMirror-activeline {\n        .CodeMirror-gutter-elt {\n            background: rgba(0, 0, 0, 0.2);\n            color: #fff;\n        }\n    }\n}\n\n.CodeMirror-foldgutter-open:after {\n    color: #666;\n}\n.CodeMirror-foldgutter-folded:after {\n    color: #aaa;\n}\n\n.CodeMirror.over-gutter, .CodeMirror-activeline {\n    .CodeMirror-foldgutter-open:after {\n        color: #888;\n    }\n}\n\n.CodeMirror-foldmarker {\n    border-color: #000;\n    color: #ccc;\n    background-color: #444;\n}\n\n/* Non-editor styling */\n\n.image-view,\n.not-editor {\n    background-color: @background;\n}\n\n.view-pane .image-view {\n    color: @foreground;\n}\n"
  },
  {
    "path": "src/extensions/default/DarkTheme/package.json",
    "content": "{\n    \"title\": \"Brackets Dark\",\n    \"name\": \"dark-theme\",\n    \"description\": \"Built-in dark theme for Brackets\",\n    \"version\": \"0.42.0\",\n    \"author\": \"Miguel Castillo <mahchagnu@gmail.com>\",\n    \"engines\": {\n        \"brackets\": \">=0.42.0\"\n    },\n    \"theme\": {\n        \"file\": \"main.less\",\n        \"dark\": true\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/DebugCommands/ErrorNotification.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _               = brackets.getModule(\"thirdparty/lodash\"),\n        AnimationUtils  = brackets.getModule(\"utils/AnimationUtils\"),\n        ExtensionUtils  = brackets.getModule(\"utils/ExtensionUtils\"),\n        Strings         = brackets.getModule(\"strings\");\n\n    var $span      = null,\n        errorCount = 0,\n        _attached  = false,\n        _windowOnError,\n        _consoleError,\n        _consoleClear;\n\n    ExtensionUtils.loadStyleSheet(module, \"styles.css\");\n\n    function showDeveloperTools() {\n        try {\n            brackets.app.showDeveloperTools();\n        } catch (err) {\n            console.error(err);\n        }\n    }\n\n    function handleClick(event) {\n        if (event.shiftKey) {\n            window.console.clear();\n        } else {\n            showDeveloperTools();\n        }\n    }\n\n    function refreshIndicator() {\n        // never show 0 errors\n        if (!_attached || errorCount === 0) {\n            // hide notifier if it was attached previously\n            // but errorCount was cleared or it was disabled\n            if ($span) {\n                $span.parent().hide();\n            }\n            return;\n        }\n\n        // update span if it was created before\n        if ($span) {\n            $span.text(errorCount).parent().show();\n            return;\n        }\n\n        // create the span\n        $span = $(\"<span>\").text(errorCount);\n        $(\"<div>\")\n            .attr(\"id\", \"error-counter\")\n            .attr(\"title\", Strings.CMD_SHOW_DEV_TOOLS + \"\\u2026\")\n            .text(Strings.ERRORS + \": \")\n            .append($span)\n            .on(\"click\", handleClick)\n            .insertBefore(\"#status-bar .spinner\");\n    }\n\n    var blink = _.debounce(function () {\n        AnimationUtils.animateUsingClass($span.parent()[0], \"flash\", 1500);\n    }, 100);\n\n    function incErrorCount() {\n        errorCount++;\n        blink();\n        refreshIndicator();\n    }\n\n    function clearErrorCount() {\n        errorCount = 0;\n        refreshIndicator();\n    }\n\n    function attachFunctions() {\n        if (_attached) {\n            return;\n        }\n\n        _attached      = true;\n        _windowOnError = window.onerror;\n        _consoleError  = window.console.error;\n        _consoleClear  = window.console.clear;\n\n        // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onerror\n        window.onerror = function (errorMsg, url, lineNumber) {\n            incErrorCount();\n            if (_windowOnError) {\n                return _windowOnError(errorMsg, url, lineNumber);\n            }\n            // return false means that we didn't handle this error and it should run the default handler\n            return false;\n        };\n\n        window.console.error = function () {\n            incErrorCount();\n            return _consoleError.apply(window.console, arguments);\n        };\n\n        window.console.clear = function () {\n            clearErrorCount();\n            return _consoleClear.apply(window.console, arguments);\n        };\n    }\n\n    function detachFunctions() {\n        if (!_attached) {\n            return;\n        }\n\n        _attached            = false;\n        window.onerror       = _windowOnError;\n        window.console.error = _consoleError;\n        window.console.clear = _consoleClear;\n    }\n\n    function toggle(bool) {\n        if (bool) {\n            attachFunctions();\n        } else {\n            detachFunctions();\n        }\n        refreshIndicator();\n    }\n\n    // Public API\n    exports.toggle = toggle;\n\n});\n"
  },
  {
    "path": "src/extensions/default/DebugCommands/NodeDebugUtils.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var NodeConnection = brackets.getModule(\"utils/NodeConnection\");\n\n    /**\n     * @private\n     * @type{NodeConnection}\n     * Connection to node for executing commands like enableDebugger\n     */\n    var _nodeConnection = null;\n\n    /**\n     * @private\n     * @type{Array.<{level: string, timestamp: Date, message: string}>}\n     * History of all log messages received from node (useful for inspecting\n     * from the developer tools console)\n     */\n    var _nodeLog = [];\n\n    /**\n     * Logs the state of the current node server to the console.\n     */\n    function logNodeState() {\n        if (brackets.app && brackets.app.getNodeState) {\n            brackets.app.getNodeState(function (err, port) {\n                if (err) {\n                    console.log(\"[NodeDebugUtils] Node is in error state \" + err);\n                } else {\n                    console.log(\"[NodeDebugUtils] Node is listening on port \" + port);\n                }\n            });\n        } else {\n            console.error(\"[NodeDebugUtils] No brackets.app.getNodeState function. Maybe you're running the wrong shell?\");\n        }\n    }\n\n    /**\n     * Sends a command to node to cause a restart.\n     */\n    function restartNode() {\n        try {\n            _nodeConnection.domains.base.restartNode();\n        } catch (e) {\n            window.alert(\"Failed trying to restart Node: \" + e.message);\n        }\n    }\n\n    /**\n     * Sends a command to node to enable the debugger.\n     */\n    function enableDebugger() {\n        try {\n            _nodeConnection.domains.base.enableDebugger();\n        } catch (e) {\n            window.alert(\"Failed trying to enable Node debugger: \" + e.message);\n        }\n    }\n\n    /**\n     * @private\n     * Handler for log events from Node. Stores the messages in an internal array\n     * for possible inspection in the developer tools. Also forwards messages to\n     * the developer tools console.\n     * @param {jQuery.Event} evt The event object from jQuery (not used)\n     * @param {string} level The level of the log message. Can be anything, but\n     *   should be something like \"log\", \"info\", \"warn\", or \"error\"\n     * @param {string} timestamp Time the event occurred in node, as a string\n     * @param {string} message The log message\n     */\n    function handleLogEvent(evt, level, timestamp, message) {\n        // For some reason, stringifying and then parsing a Date through JSON turns\n        // it into a string.\n        var timestampAsDate = new Date(timestamp);\n\n        _nodeLog.push({\n            level: level,\n            timestamp: timestampAsDate,\n            message: message\n        });\n\n        var formattedMessage = \"[node-\" + level + \" \" + timestampAsDate.toLocaleTimeString() +  \"] \" + message;\n\n        switch (level) {\n        case \"info\":\n        case \"warn\":\n        case \"error\":\n            console[level](formattedMessage);\n            break;\n        default:\n            console.log(formattedMessage);\n        }\n\n    }\n\n    _nodeConnection = new NodeConnection();\n    _nodeConnection.connect(true);\n\n    // TODO: It would be nice to add a menu item that allows the user\n    // to enable/disable forwarding of node logs to the console.\n    _nodeConnection.on(\"base:log\", handleLogEvent);\n\n    exports.logNodeState = logNodeState;\n    exports.restartNode = restartNode;\n    exports.enableDebugger = enableDebugger;\n\n});\n"
  },
  {
    "path": "src/extensions/default/DebugCommands/htmlContent/language-dialog.html",
    "content": "<div class=\"switch-language modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{Strings.LANGUAGE_TITLE}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        <p class=\"dialog-message\">\n            {{Strings.LANGUAGE_MESSAGE}}\n            <select>\n                {{#languages}}\n                <option value=\"{{language}}\">{{label}}</option>\n                {{/languages}}\n            </select>\n        </p>\n    </div>\n    <div class=\"modal-footer\">\n        <button class=\"dialog-button btn primary\" data-button-id=\"ok\" disabled>{{Strings.LANGUAGE_SUBMIT}}</button>\n        <button class=\"dialog-button btn left\" data-button-id=\"cancel\">{{Strings.CANCEL}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/DebugCommands/htmlContent/perf-dialog.html",
    "content": "<div class=\"modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">Performance Data</h1>\n    </div>\n    <div class=\"modal-body no-padding\">\n        <table class=\"table table-striped\">\n            <thead><th>Operation</th><th class=\"right\">Time (ms)</th></thead>\n            <tbody>\n                {{#perfData}}\n                <tr>\n                    <td>{{{testName}}}</td>\n                    <td class=\"right\">{{value}}</td>\n                </tr>\n                {{/perfData}}\n            </tbody>\n        </table>\n    </div>\n    <div class=\"modal-footer\">\n        <div class=\"left\">\n            <label for=\"brackets-perf-raw-data\" class=\"inline\">Raw data (copy paste out):</label>\n            <textarea rows=\"1\" id=\"brackets-perf-raw-data\" style=\"margin: 0; width: 50px;\">{{delimitedPerfData}}</textarea>        \n        </div>\n        <button class=\"dialog-button btn primary\" data-button-id=\"ok\">Close</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/DebugCommands/keyboard.json",
    "content": "{\n    \"showDeveloperTools\":  [\n        {\n            \"key\": \"F12\"\n        },\n        {\n            \"key\": \"Cmd-Opt-I\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"refreshWindow\":  [\n        {\n            \"key\": \"F5\"\n        },\n        {\n            \"key\": \"Cmd-R\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"reloadWithoutUserExts\":  [\n        {\n            \"key\": \"Shift-F5\"\n        },\n        {\n            \"key\": \"Cmd-Ctrl-R\",\n            \"platform\": \"mac\"\n        }\n    ]\n}"
  },
  {
    "path": "src/extensions/default/DebugCommands/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = brackets.getModule(\"thirdparty/lodash\");\n\n    var Commands               = brackets.getModule(\"command/Commands\"),\n        CommandManager         = brackets.getModule(\"command/CommandManager\"),\n        Menus                  = brackets.getModule(\"command/Menus\"),\n        FileSystem             = brackets.getModule(\"filesystem/FileSystem\"),\n        FileUtils              = brackets.getModule(\"file/FileUtils\"),\n        PerfUtils              = brackets.getModule(\"utils/PerfUtils\"),\n        StringUtils            = brackets.getModule(\"utils/StringUtils\"),\n        Dialogs                = brackets.getModule(\"widgets/Dialogs\"),\n        Strings                = brackets.getModule(\"strings\"),\n        PreferencesManager     = brackets.getModule(\"preferences/PreferencesManager\"),\n        LocalizationUtils      = brackets.getModule(\"utils/LocalizationUtils\"),\n        MainViewManager        = brackets.getModule(\"view/MainViewManager\"),\n        WorkingSetView         = brackets.getModule(\"project/WorkingSetView\"),\n        ExtensionManager       = brackets.getModule(\"extensibility/ExtensionManager\"),\n        Mustache               = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        ErrorNotification      = require(\"ErrorNotification\"),\n        NodeDebugUtils         = require(\"NodeDebugUtils\"),\n        PerfDialogTemplate     = require(\"text!htmlContent/perf-dialog.html\"),\n        LanguageDialogTemplate = require(\"text!htmlContent/language-dialog.html\");\n\n    var KeyboardPrefs = JSON.parse(require(\"text!keyboard.json\"));\n\n    // default preferences file name\n    var DEFAULT_PREFERENCES_FILENAME = \"defaultPreferences.json\",\n        SUPPORTED_PREFERENCE_TYPES   = [\"number\", \"boolean\", \"string\", \"array\", \"object\"];\n\n    var recomputeDefaultPrefs        = true,\n        defaultPreferencesFullPath   = brackets.app.getApplicationSupportDirectory() + \"/\" + DEFAULT_PREFERENCES_FILENAME;\n\n    /**\n     * Brackets Application Menu Constant\n     * @const {string}\n     */\n    var DEBUG_MENU = \"debug-menu\";\n\n     /**\n      * Debug commands IDs\n      * @enum {string}\n      */\n    var DEBUG_REFRESH_WINDOW                  = \"debug.refreshWindow\", // string must MATCH string in native code (brackets_extensions)\n        DEBUG_SHOW_DEVELOPER_TOOLS            = \"debug.showDeveloperTools\",\n        DEBUG_RUN_UNIT_TESTS                  = \"debug.runUnitTests\",\n        DEBUG_SHOW_PERF_DATA                  = \"debug.showPerfData\",\n        DEBUG_RELOAD_WITHOUT_USER_EXTS        = \"debug.reloadWithoutUserExts\",\n        DEBUG_NEW_BRACKETS_WINDOW             = \"debug.newBracketsWindow\",\n        DEBUG_SWITCH_LANGUAGE                 = \"debug.switchLanguage\",\n        DEBUG_ENABLE_NODE_DEBUGGER            = \"debug.enableNodeDebugger\",\n        DEBUG_LOG_NODE_STATE                  = \"debug.logNodeState\",\n        DEBUG_RESTART_NODE                    = \"debug.restartNode\",\n        DEBUG_SHOW_ERRORS_IN_STATUS_BAR       = \"debug.showErrorsInStatusBar\",\n        DEBUG_OPEN_BRACKETS_SOURCE            = \"debug.openBracketsSource\",\n        DEBUG_OPEN_PREFERENCES_IN_SPLIT_VIEW  = \"debug.openPrefsInSplitView\";\n\n    // define a preference to turn off opening preferences in split-view.\n    var prefs = PreferencesManager.getExtensionPrefs(\"preferencesView\");\n    prefs.definePreference(\"openPrefsInSplitView\",   \"boolean\", true, {\n        description: Strings.DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\n    });\n\n    prefs.definePreference(\"openUserPrefsInSecondPane\",   \"boolean\", true, {\n        description: Strings.DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\n    });\n\n    PreferencesManager.definePreference(DEBUG_SHOW_ERRORS_IN_STATUS_BAR, \"boolean\", false, {\n        description: Strings.DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\n    });\n\n    function handleShowDeveloperTools() {\n        brackets.app.showDeveloperTools();\n    }\n\n    // Implements the 'Run Tests' menu to bring up the Jasmine unit test window\n    var _testWindow = null;\n    function _runUnitTests(spec) {\n        var queryString = spec ? \"?spec=\" + spec : \"\";\n        if (_testWindow && !_testWindow.closed) {\n            if (_testWindow.location.search !== queryString) {\n                _testWindow.location.href = \"../test/SpecRunner.html\" + queryString;\n            } else {\n                _testWindow.location.reload(true);\n            }\n        } else {\n            _testWindow = window.open(\"../test/SpecRunner.html\" + queryString, \"brackets-test\", \"width=\" + $(window).width() + \",height=\" + $(window).height());\n            _testWindow.location.reload(true); // if it had been opened earlier, force a reload because it will be cached\n        }\n    }\n\n    function handleReload() {\n        CommandManager.execute(Commands.APP_RELOAD);\n    }\n\n    function handleReloadWithoutUserExts() {\n        CommandManager.execute(Commands.APP_RELOAD_WITHOUT_EXTS);\n    }\n\n    function handleNewBracketsWindow() {\n        window.open(window.location.href);\n    }\n\n    function handleShowPerfData() {\n        var templateVars = {\n            delimitedPerfData: PerfUtils.getDelimitedPerfData(),\n            perfData: []\n        };\n\n        var getValue = function (entry) {\n            // entry is either an Array or a number\n            if (Array.isArray(entry)) {\n                // For Array of values, return: minimum/average(count)/maximum/last\n                var i, e, avg, sum = 0, min = Number.MAX_VALUE, max = 0;\n\n                for (i = 0; i < entry.length; i++) {\n                    e = entry[i];\n                    min = Math.min(min, e);\n                    sum += e;\n                    max = Math.max(max, e);\n                }\n                avg = Math.round(sum * 10 / entry.length) / 10; // tenth of a millisecond\n                return String(min) + \"/\" + String(avg) + \"(\" + entry.length + \")/\" + String(max) + \"/\" + String(e);\n            } else {\n                return entry;\n            }\n        };\n\n        var perfData = PerfUtils.getData();\n        _.forEach(perfData, function (value, testName) {\n            templateVars.perfData.push({\n                testName: StringUtils.breakableUrl(testName),\n                value:    getValue(value)\n            });\n        });\n\n        var template = Mustache.render(PerfDialogTemplate, templateVars);\n        Dialogs.showModalDialogUsingTemplate(template);\n\n        // Select the raw perf data field on click since select all doesn't\n        // work outside of the editor\n        $(\"#brackets-perf-raw-data\").click(function () {\n            $(this).focus().select();\n        });\n    }\n\n    function handleSwitchLanguage() {\n        var stringsPath = FileUtils.getNativeBracketsDirectoryPath() + \"/nls\";\n\n        FileSystem.getDirectoryForPath(stringsPath).getContents(function (err, entries) {\n            if (!err) {\n                var $dialog,\n                    $submit,\n                    $select,\n                    locale,\n                    curLocale = (brackets.isLocaleDefault() ? null : brackets.getLocale()),\n                    languages = [];\n\n                var setLanguage = function (event) {\n                    locale = $select.val();\n                    $submit.prop(\"disabled\", locale === (curLocale || \"\"));\n                };\n\n                // inspect all children of dirEntry\n                entries.forEach(function (entry) {\n                    if (entry.isDirectory) {\n                        var match = entry.name.match(/^([a-z]{2})(-[a-z]{2})?$/);\n\n                        if (match) {\n                            var language = entry.name,\n                                label = match[1];\n\n                            if (match[2]) {\n                                label += match[2].toUpperCase();\n                            }\n\n                            languages.push({label: LocalizationUtils.getLocalizedLabel(label), language: language});\n                        }\n                    }\n                });\n                // add English (US), which is the root folder and should be sorted as well\n                languages.push({label: LocalizationUtils.getLocalizedLabel(\"en\"),  language: \"en\"});\n\n                // sort the languages via their display name\n                languages.sort(function (lang1, lang2) {\n                    return lang1.label.localeCompare(lang2.label);\n                });\n\n                // add system default (which is placed on the very top)\n                languages.unshift({label: Strings.LANGUAGE_SYSTEM_DEFAULT, language: null});\n\n                var template = Mustache.render(LanguageDialogTemplate, {languages: languages, Strings: Strings});\n                Dialogs.showModalDialogUsingTemplate(template).done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_OK && locale !== curLocale) {\n                        brackets.setLocale(locale);\n                        CommandManager.execute(Commands.APP_RELOAD);\n                    }\n                });\n\n                $dialog = $(\".switch-language.instance\");\n                $submit = $dialog.find(\".dialog-button[data-button-id='\" + Dialogs.DIALOG_BTN_OK + \"']\");\n                $select = $dialog.find(\"select\");\n\n                $select.on(\"change\", setLanguage).val(curLocale);\n            }\n        });\n    }\n\n    function enableRunTestsMenuItem() {\n        if (brackets.inBrowser) {\n            return;\n        }\n\n        // Check for the SpecRunner.html file\n        var file = FileSystem.getFileForPath(\n            FileUtils.getNativeBracketsDirectoryPath() + \"/../test/SpecRunner.html\"\n        );\n\n        file.exists(function (err, exists) {\n            if (!err && exists) {\n                // If the SpecRunner.html file exists, enable the menu item.\n                // (menu item is already disabled, so no need to disable if the\n                // file doesn't exist).\n                CommandManager.get(DEBUG_RUN_UNIT_TESTS).setEnabled(true);\n            }\n        });\n    }\n\n    function toggleErrorNotification(bool) {\n        var val,\n            oldPref = !!PreferencesManager.get(DEBUG_SHOW_ERRORS_IN_STATUS_BAR);\n\n        if (bool === undefined) {\n            val = !oldPref;\n        } else {\n            val = !!bool;\n        }\n\n        ErrorNotification.toggle(val);\n\n        // update menu\n        CommandManager.get(DEBUG_SHOW_ERRORS_IN_STATUS_BAR).setChecked(val);\n        if (val !== oldPref) {\n            PreferencesManager.set(DEBUG_SHOW_ERRORS_IN_STATUS_BAR, val);\n        }\n    }\n\n    function handleOpenBracketsSource() {\n        // Brackets source dir w/o the trailing src/ folder\n        var dir = FileUtils.getNativeBracketsDirectoryPath().replace(/\\/[^\\/]+$/, \"/\");\n        brackets.app.showOSFolder(dir);\n    }\n\n    function _openPrefFilesInSplitView(prefsPath, defaultPrefsPath, deferredPromise) {\n\n        var currScheme         = MainViewManager.getLayoutScheme(),\n            file               = FileSystem.getFileForPath(prefsPath),\n            defaultPrefsFile   = FileSystem.getFileForPath(defaultPrefsPath),\n            DEFAULT_PREFS_PANE = \"first-pane\",\n            USER_PREFS_PANE    = \"second-pane\";\n\n        // Exchange the panes, if default preferences need to be opened\n        // in the right pane.\n        if (!prefs.get(\"openUserPrefsInSecondPane\")) {\n            DEFAULT_PREFS_PANE = \"second-pane\";\n            USER_PREFS_PANE    = \"first-pane\";\n        }\n\n        function _openFiles() {\n\n            if (currScheme.rows === 1 && currScheme.columns === 1) {\n                // Split layout is not active yet. Initiate the\n                // split view.\n                MainViewManager.setLayoutScheme(1, 2);\n            }\n\n            // Open the default preferences in the left pane in the read only mode.\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: defaultPrefsPath, paneId: DEFAULT_PREFS_PANE, options: { isReadOnly: true } })\n                .done(function () {\n\n                    // Make sure the preference file is going to be opened in pane\n                    // specified in the preference.\n                    if (MainViewManager.findInWorkingSet(DEFAULT_PREFS_PANE, prefsPath) >= 0) {\n\n                        MainViewManager._moveView(DEFAULT_PREFS_PANE, USER_PREFS_PANE, file, 0, true);\n\n                        // Now refresh the project tree by asking\n                        // it to rebuild the UI.\n                        WorkingSetView.refresh(true);\n                    }\n\n                    CommandManager.execute(Commands.FILE_OPEN, { fullPath: prefsPath, paneId: USER_PREFS_PANE})\n                        .done(function () {\n                            deferredPromise.resolve();\n                        }).fail(function () {\n                            deferredPromise.reject();\n                        });\n                }).fail(function () {\n                    deferredPromise.reject();\n                });\n        }\n\n        var resultObj = MainViewManager.findInAllWorkingSets(defaultPrefsPath);\n        if (resultObj && resultObj.length > 0) {\n            CommandManager.execute(Commands.FILE_CLOSE, {file: defaultPrefsFile, paneId: resultObj[0].paneId})\n                .done(function () {\n                    _openFiles();\n                }).fail(function () {\n                    deferredPromise.reject();\n                });\n        } else {\n            _openFiles();\n        }\n\n    }\n\n    function _isSupportedPrefType(prefType) {\n\n        if (SUPPORTED_PREFERENCE_TYPES.indexOf(prefType) >= 0) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n   /*\n    * This method tries to deduce the preference type\n    * based on various parameters like objects initial\n    * value, object type, object's type property.\n    */\n    function _getPrefType(prefItem) {\n\n        var finalPrefType = \"undefined\";\n\n        if (prefItem) {\n            // check the type parameter.\n            var _prefType = prefItem.type;\n            if (_prefType !== undefined) {\n                finalPrefType = prefItem.type.toLowerCase();\n                // make sure the initial property's\n                // object type matches to that of 'type' property.\n                if (prefItem.initial !== undefined) {\n\n                    if (Array.isArray(prefItem.initial)) {\n                        _prefType = \"array\";\n                    } else {\n                        var _initialType = typeof (prefItem.initial);\n                        _initialType = _initialType.toLowerCase();\n                        if (_prefType !== _initialType) {\n                            _prefType = _initialType;\n                        }\n                    }\n                }\n            }\n\n            if (_prefType) {\n                // preference object's type\n                // is defined. Check if that is valid or not.\n                finalPrefType = _prefType;\n                if (!_isSupportedPrefType(finalPrefType)) {\n                    finalPrefType = \"undefined\";\n                }\n            } else if (Array.isArray(prefItem)) {\n                // Check if the object itself\n                // is an array, in which case\n                // we log the default.\n                finalPrefType = \"array\";\n            } else if (prefItem.initial !== undefined  ||\n                       prefItem.keys !== undefined) {\n\n                // OK looks like this preference has\n                // no explicit type defined. instead\n                // it needs to be deduced from initial/keys\n                // variable.\n                var _prefVar;\n                if (prefItem.initial !== undefined) {\n                    _prefVar = prefItem.initial;\n                } else {\n                    _prefVar = prefItem.keys;\n                }\n\n                if (Array.isArray(_prefVar)) {\n                    // In cases of array the\n                    // typeof is returning a function.\n                    finalPrefType = \"array\";\n                }\n\n            } else {\n                finalPrefType = typeof (prefItem);\n            }\n        }\n\n        // Now make sure we recognize this format.\n        if (!_isSupportedPrefType(finalPrefType)) {\n            finalPrefType = \"undefined\";\n        }\n\n        return finalPrefType;\n    }\n\n    function _isValidPref(pref) {\n\n        // Make sure to generate pref description only for\n        // user overrides and don't generate for properties\n        // meant to be used for internal purposes. Also check\n        // if the preference type is valid or not.\n        if (pref && !pref.excludeFromHints && _getPrefType(pref) !== \"undefined\") {\n            return true;\n        }\n\n        return false;\n    }\n\n   /*\n    * This method tries to match between initial objects\n    * and key objects and then aggregates objects from both\n    * the properties.\n    */\n    function _getChildPrefs(prefItem) {\n\n        var finalObj = {},\n            keysFound = false;\n\n        if (!prefItem) {\n            return {};\n        }\n\n        function _populateKeys(allKeys) {\n\n            var prop;\n            if (typeof (allKeys) === \"object\") {\n                // iterate through the list.\n                keysFound = true;\n                for (prop in allKeys) {\n                    if (allKeys.hasOwnProperty(prop)) {\n                        finalObj[prop] = allKeys[prop];\n                    }\n                }\n            }\n        }\n\n        _populateKeys(prefItem.initial);\n        _populateKeys(prefItem.keys);\n\n        // Last resort: Maybe plain objects, in which case\n        // we blindly extract all the properties.\n        if (!keysFound) {\n            _populateKeys(prefItem);\n        }\n\n        return finalObj;\n    }\n\n    function _formatBasicPref(prefItem, prefName, tabIndentStr) {\n\n        if (!prefItem || typeof (prefName) !== \"string\" || _getPrefType(prefItem) === \"object\") {\n            // return empty string in case of\n            // object or pref is not defined.\n            return \"\";\n        }\n\n        var prefDescription = prefItem.description || \"\",\n            prefDefault     = prefItem.initial,\n            prefFormatText  = tabIndentStr + \"\\t// {0}\\n\" + tabIndentStr + \"\\t\\\"{1}\\\": {2}\",\n            prefItemType    = _getPrefType(prefItem);\n\n        if (prefDefault === undefined && !prefItem.description) {\n            // This could be the case when prefItem is a basic JS variable.\n            if (prefItemType === \"number\" || prefItemType === \"boolean\" || prefItemType === \"string\") {\n                prefDefault = prefItem;\n            }\n        }\n\n        if (prefDefault === undefined) {\n            if (prefItemType === \"number\") {\n                prefDefault = 0;\n            } else if (prefItemType === \"boolean\") {\n                // Defaulting the preference to false,\n                // in case this is missing.\n                prefDefault = false;\n            } else {\n                // for all other types\n                prefDefault = \"\";\n            }\n        }\n\n        if ((prefDescription === undefined || prefDescription.length === 0)) {\n            if (!Array.isArray(prefDefault)) {\n                prefDescription = Strings.DEFAULT_PREFERENCES_JSON_DEFAULT + \": \" + prefDefault;\n            } else {\n                prefDescription = \"\";\n            }\n        }\n\n        if (prefItemType === \"array\") {\n            prefDefault = \"[]\";\n        } else if (prefDefault.length === 0 || (prefItemType !== \"boolean\" && prefItemType !== \"number\")) {\n            prefDefault = \"\\\"\" + prefDefault + \"\\\"\";\n        }\n\n        return StringUtils.format(prefFormatText, prefDescription, prefName, prefDefault);\n    }\n\n    function _formatPref(prefName,  prefItem, indentLevel) {\n\n        // check for validity of the parameters being passed\n        if (!prefItem || indentLevel < 0 || !prefName || !prefName.length) {\n            return \"\";\n        }\n\n        var iLevel,\n            prefItemKeys,\n            entireText     = \"\",\n            prefItemDesc   = prefItem.description || \"\",\n            prefItemType   = _getPrefType(prefItem),\n            hasKeys        = false,\n            tabIndents     = \"\",\n            numKeys        = 0;\n\n        // Generate the indentLevel string\n        for (iLevel = 0; iLevel < indentLevel; iLevel++) {\n            tabIndents += \"\\t\";\n        }\n\n        // Check if the preference is an object.\n        if (_getPrefType(prefItem) === \"object\") {\n            prefItemKeys = _getChildPrefs(prefItem);\n            if (Object.keys(prefItemKeys).length > 0) {\n                hasKeys = true;\n            }\n        }\n\n        // There are some properties like \"highlightMatches\" that\n        // are declared as boolean type but still can take object keys.\n        // The below condition check can take care of cases like this.\n        if (prefItemType !== \"object\" && hasKeys === false) {\n            return _formatBasicPref(prefItem, prefName, tabIndents);\n        }\n\n        // Indent the beginning of the object.\n        tabIndents += \"\\t\";\n\n        if (prefItemDesc && prefItemDesc.length > 0) {\n            entireText = tabIndents + \"// \" + prefItemDesc + \"\\n\";\n        }\n\n        entireText += tabIndents + \"\\\"\" + prefName + \"\\\": \" + \"{\";\n\n        if (prefItemKeys) {\n            numKeys = Object.keys(prefItemKeys).length;\n        }\n\n        // In case the object array is empty\n        if (numKeys <= 0) {\n            entireText += \"}\";\n            return entireText;\n        } else {\n            entireText += \"\\n\";\n        }\n\n        // Now iterate through all the keys\n        // and generate nested formatted objects.\n\n        Object.keys(prefItemKeys).sort().forEach(function (property) {\n\n            if (prefItemKeys.hasOwnProperty(property)) {\n\n                var pref = prefItemKeys[property];\n\n                if (_isValidPref(pref)) {\n\n                    var formattedText = \"\";\n\n                    if (_getPrefType(pref) === \"object\") {\n                        formattedText = _formatPref(property, pref, indentLevel + 1);\n                    } else {\n                        formattedText = _formatBasicPref(pref, property, tabIndents);\n                    }\n\n                    if (formattedText.length > 0) {\n                        entireText += formattedText + \",\\n\\n\";\n                    }\n                }\n            }\n        });\n\n        // Strip \",\\n\\n\" that got added above, for the last property\n        if (entireText.length > 0) {\n            entireText = entireText.slice(0, -3) + \"\\n\" + tabIndents + \"}\";\n        } else {\n            entireText = \"{}\";\n        }\n\n        return entireText;\n    }\n\n    function _getDefaultPreferencesString() {\n\n        var allPrefs       = PreferencesManager.getAllPreferences(),\n            headerComment  = Strings.DEFAULT_PREFERENCES_JSON_HEADER_COMMENT + \"\\n\\n{\\n\",\n            entireText     = \"\";\n\n        Object.keys(allPrefs).sort().forEach(function (property) {\n            if (allPrefs.hasOwnProperty(property)) {\n\n                var pref = allPrefs[property];\n\n                if (_isValidPref(pref)) {\n                    entireText += _formatPref(property, pref, 0) + \",\\n\\n\";\n                }\n            }\n        });\n\n        // Strip \",\\n\\n\" that got added above, for the last property\n        if (entireText.length > 0) {\n            entireText = headerComment + entireText.slice(0, -3) + \"\\n}\\n\";\n        } else {\n            entireText = headerComment + \"}\\n\";\n        }\n\n        return entireText;\n    }\n\n    function _loadDefaultPrefs(prefsPath, deferredPromise) {\n\n        var defaultPrefsPath = defaultPreferencesFullPath,\n            file             = FileSystem.getFileForPath(defaultPrefsPath);\n\n        function _executeDefaultOpenPrefsCommand() {\n\n            CommandManager.execute(Commands.FILE_OPEN_PREFERENCES)\n                .done(function () {\n                    deferredPromise.resolve();\n                }).fail(function () {\n                    deferredPromise.reject();\n                });\n        }\n\n        file.exists(function (err, doesExist) {\n\n            if (doesExist) {\n\n                // Go about recreating the default preferences file.\n                if (recomputeDefaultPrefs) {\n\n                    var prefsString       = _getDefaultPreferencesString();\n                    recomputeDefaultPrefs = false;\n\n                    // We need to delete this first\n                    file.unlink(function (err) {\n                        if (!err) {\n                            // Go about recreating this\n                            // file and write the default\n                            // preferences string to this file.\n                            FileUtils.writeText(file, prefsString, true)\n                                .done(function () {\n                                    recomputeDefaultPrefs = false;\n                                    _openPrefFilesInSplitView(prefsPath, defaultPrefsPath, deferredPromise);\n                                }).fail(function (error) {\n                                    // Give a chance for default preferences command.\n                                    console.error(\"Unable to write to default preferences file! error code:\" + error);\n                                    _executeDefaultOpenPrefsCommand();\n                                });\n                        } else {\n                            // Some error occured while trying to delete\n                            // the file. In this case open the user\n                            // preferences alone.\n                            console.error(\"Unable to delete the existing default preferences file! error code:\" + err);\n                            _executeDefaultOpenPrefsCommand();\n                        }\n                    });\n\n                } else {\n                    // Default preferences already generated.\n                    // Just go about opening both the files.\n                    _openPrefFilesInSplitView(prefsPath, defaultPrefsPath, deferredPromise);\n                }\n            } else {\n\n                // The default prefs file does not exist at all.\n                // So go about recreating the default preferences\n                // file.\n                var _prefsString = _getDefaultPreferencesString();\n                FileUtils.writeText(file, _prefsString, true)\n                    .done(function () {\n                        recomputeDefaultPrefs = false;\n                        _openPrefFilesInSplitView(prefsPath, defaultPrefsPath, deferredPromise);\n                    }).fail(function (error) {\n                        // Give a chance for default preferences command.\n                        console.error(\"Unable to write to default preferences file! error code:\" + error);\n                        _executeDefaultOpenPrefsCommand();\n                    });\n            }\n        });\n    }\n\n    function handleOpenPrefsInSplitView() {\n\n        var fullPath        = PreferencesManager.getUserPrefFile(),\n            file            = FileSystem.getFileForPath(fullPath),\n            splitViewPrefOn = prefs.get(\"openPrefsInSplitView\"),\n            result          = new $.Deferred();\n\n        if (!splitViewPrefOn) {\n            return CommandManager.execute(Commands.FILE_OPEN_PREFERENCES);\n        } else {\n            file.exists(function (err, doesExist) {\n                if (doesExist) {\n                    _loadDefaultPrefs(fullPath, result);\n                } else {\n                    FileUtils.writeText(file, \"\", true)\n                        .done(function () {\n                            _loadDefaultPrefs(fullPath, result);\n                        }).fail(function () {\n                            result.reject();\n                        });\n                }\n            });\n        }\n\n        return result.promise();\n    }\n\n    ExtensionManager.on(\"statusChange\", function (id) {\n        // Seems like an extension(s) got installed.\n        // Need to recompute the default prefs.\n        recomputeDefaultPrefs = true;\n    });\n\n    /* Register all the command handlers */\n\n    // Show Developer Tools (optionally enabled)\n    CommandManager.register(Strings.CMD_SHOW_DEV_TOOLS,             DEBUG_SHOW_DEVELOPER_TOOLS,     handleShowDeveloperTools)\n        .setEnabled(!!brackets.app.showDeveloperTools);\n    CommandManager.register(Strings.CMD_REFRESH_WINDOW,             DEBUG_REFRESH_WINDOW,           handleReload);\n    CommandManager.register(Strings.CMD_RELOAD_WITHOUT_USER_EXTS,   DEBUG_RELOAD_WITHOUT_USER_EXTS, handleReloadWithoutUserExts);\n    CommandManager.register(Strings.CMD_NEW_BRACKETS_WINDOW,        DEBUG_NEW_BRACKETS_WINDOW,      handleNewBracketsWindow);\n\n    // Start with the \"Run Tests\" item disabled. It will be enabled later if the test file can be found.\n    CommandManager.register(Strings.CMD_RUN_UNIT_TESTS,       DEBUG_RUN_UNIT_TESTS,         _runUnitTests)\n        .setEnabled(false);\n\n    CommandManager.register(Strings.CMD_SHOW_PERF_DATA,            DEBUG_SHOW_PERF_DATA,            handleShowPerfData);\n\n    // Open Brackets Source (optionally enabled)\n    CommandManager.register(Strings.CMD_OPEN_BRACKETS_SOURCE,      DEBUG_OPEN_BRACKETS_SOURCE,      handleOpenBracketsSource)\n        .setEnabled(!StringUtils.endsWith(decodeURI(window.location.pathname), \"/www/index.html\"));\n\n    CommandManager.register(Strings.CMD_SWITCH_LANGUAGE,           DEBUG_SWITCH_LANGUAGE,           handleSwitchLanguage);\n    CommandManager.register(Strings.CMD_SHOW_ERRORS_IN_STATUS_BAR, DEBUG_SHOW_ERRORS_IN_STATUS_BAR, toggleErrorNotification);\n\n    // Node-related Commands\n    CommandManager.register(Strings.CMD_ENABLE_NODE_DEBUGGER, DEBUG_ENABLE_NODE_DEBUGGER,   NodeDebugUtils.enableDebugger);\n    CommandManager.register(Strings.CMD_LOG_NODE_STATE,       DEBUG_LOG_NODE_STATE,         NodeDebugUtils.logNodeState);\n    CommandManager.register(Strings.CMD_RESTART_NODE,         DEBUG_RESTART_NODE,           NodeDebugUtils.restartNode);\n\n    CommandManager.register(Strings.CMD_OPEN_PREFERENCES, DEBUG_OPEN_PREFERENCES_IN_SPLIT_VIEW, handleOpenPrefsInSplitView);\n\n    enableRunTestsMenuItem();\n    toggleErrorNotification(PreferencesManager.get(DEBUG_SHOW_ERRORS_IN_STATUS_BAR));\n\n    PreferencesManager.on(\"change\", DEBUG_SHOW_ERRORS_IN_STATUS_BAR, function () {\n        toggleErrorNotification(PreferencesManager.get(DEBUG_SHOW_ERRORS_IN_STATUS_BAR));\n    });\n\n    /*\n     * Debug menu\n     */\n    var menu = Menus.addMenu(Strings.DEBUG_MENU, DEBUG_MENU, Menus.BEFORE, Menus.AppMenuBar.HELP_MENU);\n    menu.addMenuItem(DEBUG_SHOW_DEVELOPER_TOOLS, KeyboardPrefs.showDeveloperTools);\n    menu.addMenuItem(DEBUG_REFRESH_WINDOW, KeyboardPrefs.refreshWindow);\n    menu.addMenuItem(DEBUG_RELOAD_WITHOUT_USER_EXTS, KeyboardPrefs.reloadWithoutUserExts);\n    menu.addMenuItem(DEBUG_NEW_BRACKETS_WINDOW);\n    menu.addMenuDivider();\n    menu.addMenuItem(DEBUG_SWITCH_LANGUAGE);\n    menu.addMenuDivider();\n    menu.addMenuItem(DEBUG_RUN_UNIT_TESTS);\n    menu.addMenuItem(DEBUG_SHOW_PERF_DATA);\n    menu.addMenuItem(DEBUG_OPEN_BRACKETS_SOURCE);\n    menu.addMenuDivider();\n    menu.addMenuItem(DEBUG_ENABLE_NODE_DEBUGGER);\n    menu.addMenuItem(DEBUG_LOG_NODE_STATE);\n    menu.addMenuItem(DEBUG_RESTART_NODE);\n    menu.addMenuItem(DEBUG_SHOW_ERRORS_IN_STATUS_BAR);\n    menu.addMenuItem(DEBUG_OPEN_PREFERENCES_IN_SPLIT_VIEW); // this command will enable defaultPreferences and brackets preferences to be open side by side in split view.\n    menu.addMenuItem(Commands.FILE_OPEN_KEYMAP);      // this command is defined in core, but exposed only in Debug menu for now\n\n    // exposed for convenience, but not official API\n    exports._runUnitTests = _runUnitTests;\n});\n"
  },
  {
    "path": "src/extensions/default/DebugCommands/styles.css",
    "content": "#error-counter {\n    cursor: pointer;\n    transition: all 3s;\n    color: #f74687;\n    background-color: transparent;\n}\n#error-counter.flash {\n    transition: all 1s;\n    background-color: #ffb0cd;\n}\n"
  },
  {
    "path": "src/extensions/default/HTMLCodeHints/HtmlAttributes.json",
    "content": "{\n    \"accesskey\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"class\":              { \"attribOption\": [], \"global\": \"true\", \"type\": \"cssStyle\" },\n    \"contenteditable\":    { \"attribOption\": [], \"global\": \"true\", \"type\": \"boolean\" },\n    \"contextmenu\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"dir\":                { \"attribOption\": [\"ltr\", \"rtl\"], \"global\": \"true\"},\n    \"draggable\":          { \"attribOption\": [\"auto\", \"false\", \"true\"], \"global\": \"true\" },\n    \"dropzone\":           { \"attribOption\": [\"copy\", \"move\", \"link\"], \"global\": \"true\" },\n    \"hidden\":             { \"attribOption\": [], \"type\": \"flag\", \"global\": \"true\" },\n    \"id\":                 { \"attribOption\": [], \"global\": \"true\", \"type\": \"cssId\" },\n    \"lang\":               { \"attribOption\": [\"ab\", \"aa\", \"af\", \"sq\", \"am\", \"ar\", \"an\", \"hy\", \"as\", \"ay\", \"az\", \"ba\", \"eu\", \"bn\", \"dz\", \"bh\", \"bi\", \"br\",\n                                             \"bg\", \"my\", \"be\", \"km\", \"ca\", \"zh\", \"co\", \"hr\", \"cs\", \"da\", \"nl\", \"en\", \"eo\", \"et\", \"fo\", \"fa\", \"fi\", \"fr\",\n                                             \"fy\", \"gl\", \"gd\", \"gv\", \"ka\", \"de\", \"el\", \"kl\", \"gn\", \"gu\", \"ht\", \"ha\", \"he\", \"hi\", \"hu\", \"is\", \"io\", \"id\",\n                                             \"ia\", \"ie\", \"iu\", \"ik\", \"ga\", \"it\", \"ja\", \"jv\", \"kn\", \"ks\", \"kk\", \"rw\", \"ky\", \"rn\", \"ko\", \"ku\", \"lo\", \"la\",\n                                             \"lv\", \"li\", \"ln\", \"lt\", \"mk\", \"mg\", \"ms\", \"ml\", \"mt\", \"mi\", \"mr\", \"mo\", \"mn\", \"na\", \"ne\", \"no\", \"oc\", \"or\",\n                                             \"om\", \"ps\", \"pl\", \"pt\", \"pa\", \"qu\", \"rm\", \"ro\", \"ru\", \"sz\", \"sm\", \"sg\", \"sa\", \"sr\", \"sh\", \"st\", \"tn\", \"sn\",\n                                             \"ii\", \"sd\", \"si\", \"ss\", \"sk\", \"sl\", \"so\", \"es\", \"su\", \"sw\", \"sv\", \"tl\", \"tg\", \"ta\", \"tt\", \"te\", \"th\", \"bo\",\n                                             \"ti\", \"to\", \"ts\", \"tr\", \"tk\", \"tw\", \"ug\", \"uk\", \"ur\", \"uz\", \"vi\", \"vo\", \"wa\", \"cy\", \"wo\", \"xh\", \"yi\", \"yo\",\n                                             \"zu\"],\n                            \"global\": \"true\" },\n    \"role\":               { \"attribOption\": [\"alert\", \"alertdialog\", \"article\", \"application\", \"banner\", \"button\", \"checkbox\", \"columnheader\", \"combobox\",\n                                             \"complementary\", \"contentinfo\", \"definition\", \"directory\", \"dialog\", \"document\", \"form\", \"grid\", \"gridcell\",\n                                             \"group\", \"heading\", \"img\", \"link\", \"list\", \"listbox\", \"listitem\", \"log\", \"main\", \"marquee\", \"math\", \"menu\",\n                                             \"menubar\", \"menuitem\", \"menuitemcheckbox\", \"menuitemradio\", \"navigation\", \"note\", \"option\", \"presentation\",\n                                             \"progressbar\", \"radio\", \"radiogroup\", \"region\", \"row\", \"rowgroup\", \"rowheader\", \"scrollbar\", \"search\",\n                                             \"separator\", \"slider\", \"spinbutton\", \"status\", \"tab\", \"tablist\", \"tabpanel\", \"textbox\", \"timer\", \"toolbar\",\n                                             \"tooltip\", \"tree\", \"treegrid\", \"treeitem\"],\n                            \"global\": \"true\" },\n    \"spellcheck\":         { \"attribOption\": [], \"global\": \"true\", \"type\": \"boolean\" },\n    \"style\":              { \"attribOption\": [], \"global\": \"true\", \"type\": \"style\" },\n    \"tabindex\":           { \"attribOption\": [], \"global\": \"true\" },\n    \"title\":              { \"attribOption\": [], \"global\": \"true\" },\n\n    \"onabort\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"onblur\":             { \"attribOption\": [], \"global\": \"true\" },\n    \"oncanplay\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"oncanplaythrough\":   { \"attribOption\": [], \"global\": \"true\" },\n    \"onchange\":           { \"attribOption\": [], \"global\": \"true\" },\n    \"onclick\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"oncontextmenu\":      { \"attribOption\": [], \"global\": \"true\" },\n    \"oncuechange\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"ondblclick\":         { \"attribOption\": [], \"global\": \"true\" },\n    \"ondrag\":             { \"attribOption\": [], \"global\": \"true\" },\n    \"ondragend\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"ondragenter\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"ondragleave\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"ondragover\":         { \"attribOption\": [], \"global\": \"true\" },\n    \"ondragstart\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"ondrop\":             { \"attribOption\": [], \"global\": \"true\" },\n    \"ondurationchange\":   { \"attribOption\": [], \"global\": \"true\" },\n    \"onemptied\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onended\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"onerror\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"onfocus\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"oninput\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"oninvalid\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onkeydown\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onkeypress\":         { \"attribOption\": [], \"global\": \"true\" },\n    \"onkeyup\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"onload\":             { \"attribOption\": [], \"global\": \"true\" },\n    \"onloadeddata\":       { \"attribOption\": [], \"global\": \"true\" },\n    \"onloadedmetadata\":   { \"attribOption\": [], \"global\": \"true\" },\n    \"onloadstart\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"onmousedown\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"onmousemove\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"onmouseout\":         { \"attribOption\": [], \"global\": \"true\" },\n    \"onmouseover\":        { \"attribOption\": [], \"global\": \"true\" },\n    \"onmouseup\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onmousewheel\":       { \"attribOption\": [], \"global\": \"true\" },\n    \"onpause\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"onplay\":             { \"attribOption\": [], \"global\": \"true\" },\n    \"onplaying\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onprogress\":         { \"attribOption\": [], \"global\": \"true\" },\n    \"onratechange\":       { \"attribOption\": [], \"global\": \"true\" },\n    \"onreadystatechange\": { \"attribOption\": [], \"global\": \"true\" },\n    \"onreset\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"onscroll\":           { \"attribOption\": [], \"global\": \"true\" },\n    \"onseeked\":           { \"attribOption\": [], \"global\": \"true\" },\n    \"onseeking\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onselect\":           { \"attribOption\": [], \"global\": \"true\" },\n    \"onshow\":             { \"attribOption\": [], \"global\": \"true\" },\n    \"onstalled\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"onsubmit\":           { \"attribOption\": [], \"global\": \"true\" },\n    \"onsuspend\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"ontimeupdate\":       { \"attribOption\": [], \"global\": \"true\" },\n    \"onvolumechange\":     { \"attribOption\": [], \"global\": \"true\" },\n    \"onwaiting\":          { \"attribOption\": [], \"global\": \"true\" },\n\n    \"aria-autocomplete\":        { \"attribOption\": [\"inline\", \"list\", \"both\", \"none\"] },\n    \"aria-activedescendant\":    { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-atomic\":              { \"attribOption\": [\"true\", \"false\"], \"global\": \"true\", \"type\": \"boolean\" },\n    \"aria-busy\":                { \"attribOption\": [], \"global\": \"true\", \"type\": \"boolean\" },\n    \"aria-checked\":             { \"attribOption\": [\"true\", \"false\", \"mixed\", \"undefined\"] },\n    \"aria-controls\":            { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-describedby\":         { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-disabled\":            { \"attribOption\": [\"true\", \"false\"], \"global\": \"true\" },\n    \"aria-dropeffect\":          { \"attribOption\": [\"copy\", \"move\", \"link\", \"execute\", \"popup\", \"none\"], \"global\": \"true\" },\n    \"aria-expanded\":            { \"attribOption\": [\"true\", \"false\", \"undefined\"] },\n    \"aria-flowto\":              { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-grabbed\":             { \"attribOption\": [\"true\", \"false\", \"undefined\"], \"global\": \"true\" },\n    \"aria-haspopup\":            { \"attribOption\": [\"true\", \"false\"], \"global\": \"true\", \"type\": \"boolean\" },\n    \"aria-hidden\":              { \"attribOption\": [\"true\", \"false\"], \"global\": \"true\", \"type\": \"boolean\" },\n    \"aria-invalid\":             { \"attribOption\": [\"grammar\", \"false\", \"spelling\", \"true\"], \"global\": \"true\" },\n    \"aria-label\":               { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-labelledby\":          { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-level\":               { \"attribOption\": [] },\n    \"aria-live\":                { \"attribOption\": [\"off\", \"polite\", \"assertive\"], \"global\": \"true\" },\n    \"aria-multiline\":           { \"attribOption\": [\"true\", \"false\"], \"type\": \"boolean\" },\n    \"aria-multiselectable\":     { \"attribOption\": [\"true\", \"false\"], \"type\": \"boolean\" },\n    \"aria-orientation\":         { \"attribOption\": [\"vertical\", \"horizontal\"] },\n    \"aria-owns\":                { \"attribOption\": [], \"global\": \"true\" },\n    \"aria-posinset\":            { \"attribOption\": [] },\n    \"aria-pressed\":             { \"attribOption\": [\"true\", \"false\", \"mixed\", \"undefined\"] },\n    \"aria-readonly\":            { \"attribOption\": [\"true\", \"false\"] },\n    \"aria-relevant\":            { \"attribOption\": [\"additions\", \"removals\", \"text\", \"all\", \"additions text\"], \"global\": \"true\" },\n    \"aria-required\":            { \"attribOption\": [\"true\", \"false\"], \"type\": \"boolean\" },\n    \"aria-selected\":            { \"attribOption\": [\"true\", \"false\", \"undefined\"] },\n    \"aria-setsize\":             { \"attribOption\": [] },\n    \"aria-sort\":                { \"attribOption\": [\"ascending\", \"descending\", \"none\", \"other\"] },\n    \"aria-valuemax\":            { \"attribOption\": [] },\n    \"aria-valuemin\":            { \"attribOption\": [] },\n    \"aria-valuenow\":            { \"attribOption\": [] },\n    \"aria-valuetext\": { \"attribOption\": [] },\n    \"accept\":             { \"attribOption\": [\"text/html\", \"text/plain\", \"application/msword\", \"application/msexcel\", \"application/postscript\",\n                                             \"application/x-zip-compressed\", \"application/pdf\", \"application/rtf\", \"video/x-msvideo\", \"video/quicktime\",\n                                             \"video/x-mpeg2\", \"audio/x-pn/realaudio\", \"audio/x-mpeg\", \"audio/x-waw\", \"audio/x-aiff\", \"audio/basic\",\n                                             \"image/tiff\", \"image/jpeg\", \"image/gif\", \"image/x-png\", \"image/x-photo-cd\", \"image/x-MS-bmp\", \"image/x-rgb\",\n                                             \"image/x-portable-pixmap\", \"image/x-portable-greymap\", \"image/x-portablebitmap\"] },\n    \"accept-charset\":     { \"attribOption\": [] },\n    \"action\":             { \"attribOption\": [] },\n    \"align\":              { \"attribOption\": [] },\n    \"alt\":                { \"attribOption\": [] },\n    \"archive\":            { \"attribOption\": [] },\n    \"async\":              { \"attribOption\": [], \"type\": \"flag\" },\n    \"autocomplete\":       { \"attribOption\": [\"additional-name\", \"address-level1\", \"address-level2\", \"address-level3\", \"address-level4\", \"address-line1\",\n                                             \"address-line2\", \"address-line3\", \"bday\", \"bday-year\", \"bday-day\", \"bday-month\", \"billing\",\n                                             \"cc-additional-name\", \"cc-csc\", \"cc-exp\", \"cc-exp-month\", \"cc-exp-year\", \"cc-family-name\", \"cc-given-name\",\n                                             \"cc-name\", \"cc-number\", \"cc-type\", \"country\", \"country-name\", \"current-password\", \"email\", \"family-name\",\n                                             \"fax\", \"given-name\", \"home\", \"honorific-prefix\", \"honorific-suffix\", \"impp\", \"language\", \"mobile\", \"name\",\n                                             \"new-password\", \"nickname\", \"off\", \"on\", \"organization\", \"organization-title\", \"pager\", \"photo\", \"postal-code\", \"sex\",\n                                             \"shipping\", \"street-address\", \"tel-area-code\", \"tel\", \"tel-country-code\", \"tel-extension\",\n                                             \"tel-local\", \"tel-local-prefix\", \"tel-local-suffix\", \"tel-national\", \"transaction-amount\",\n                                             \"transaction-currency\", \"url\", \"username\", \"work\"] },\n    \"autofocus\":          { \"attribOption\": [], \"type\": \"flag\" },\n    \"autoplay\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"behavior\":           { \"attribOption\": [\"scroll\", \"slide\", \"alternate\"] },\n    \"bgcolor\":            { \"attribOption\": [], \"type\": \"color\" },\n    \"border\":             { \"attribOption\": [] },\n    \"challenge\":          { \"attribOption\": [] },\n    \"charset\":            { \"attribOption\": [\"iso-8859-1\", \"utf-8\", \"shift_jis\", \"euc-jp\", \"big5\", \"gb2312\", \"euc-kr\", \"din_66003-kr\", \"ns_4551-1-kr\",\n                                             \"sen_850200_b\", \"csISO2022jp\", \"hz-gb-2312\", \"ibm852\", \"ibm866\", \"irv\", \"iso-2022-kr\", \"iso-8859-2\",\n                                             \"iso-8859-3\", \"iso-8859-4\", \"iso-8859-5\", \"iso-8859-6\", \"iso-8859-7\", \"iso-8859-8\", \"iso-8859-9\", \"koi8-r\",\n                                             \"ks_c_5601\", \"windows-1250\", \"windows-1251\", \"windows-1252\", \"windows-1253\", \"windows-1254\", \"windows-1255\",\n                                             \"windows-1256\", \"windows-1257\", \"windows-1258\", \"windows-874\", \"x-euc\", \"asmo-708\", \"dos-720\", \"dos-862\",\n                                             \"dos-874\", \"cp866\", \"cp1256\"] },\n    \"checked\":            { \"attribOption\": [], \"type\": \"flag\" },\n    \"cite\":               { \"attribOption\": [] },\n    \"codebase\":           { \"attribOption\": [] },\n    \"codetype\":           { \"attribOption\": [] },\n    \"cols\":               { \"attribOption\": [] },\n    \"colspan\":            { \"attribOption\": [] },\n    \"content\":            { \"attribOption\": [] },\n    \"controls\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"coords\":             { \"attribOption\": [] },\n    \"data\":               { \"attribOption\": [] },\n    \"datetime\":           { \"attribOption\": [] },\n    \"declare\":            { \"attribOption\": [], \"type\": \"flag\" },\n    \"default\":            { \"attribOption\": [], \"type\": \"flag\" },\n    \"defer\":              { \"attribOption\": [], \"type\": \"flag\" },\n    \"direction\":          { \"attribOption\": [\"left\", \"right\", \"up\", \"down\"] },\n    \"dirname\":            { \"attribOption\": [] },\n    \"disabled\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"enctype\":            { \"attribOption\": [\"application/x-www-form-urlencoded\", \"multipart/form-data\", \"text/plain\"] },\n    \"for\":                { \"attribOption\": [] },\n    \"form\":               { \"attribOption\": [] },\n    \"formaction\":         { \"attribOption\": [] },\n    \"formenctype\":        { \"attribOption\": [\"application/x-www-form-urlencoded\", \"multipart/form-data\", \"text/plain\"] },\n    \"formmethod\":         { \"attribOption\": [\"get\", \"post\"] },\n    \"formnovalidate\":     { \"attribOption\": [], \"type\": \"flag\" },\n    \"formtarget\":         { \"attribOption\": [\"_blank\", \"_parent\", \"_self\", \"_top\"] },\n    \"headers\":            { \"attribOption\": [] },\n    \"height\":             { \"attribOption\": [] },\n    \"high\":               { \"attribOption\": [] },\n    \"href\":               { \"attribOption\": [] },\n    \"hreflang\":           { \"attribOption\": [] },\n    \"hspace\":             { \"attribOption\": [] },\n    \"http-equiv\":         { \"attribOption\": [\"content-type\", \"default-style\", \"refresh\"] },\n    \"icon\":               { \"attribOption\": [] },\n    \"ismap\":              { \"attribOption\": [], \"type\": \"flag\" },\n    \"keytype\":            { \"attribOption\": [\"dsa\", \"ec\", \"rsa\"] },\n    \"kind\":               { \"attribOption\": [\"captions\", \"chapters\", \"descriptions\", \"metadata\", \"subtitles\"] },\n    \"label\":              { \"attribOption\": [] },\n    \"list\":               { \"attribOption\": [] },\n    \"longdesc\":           { \"attribOption\": [] },\n    \"loop\":               { \"attribOption\": [], \"type\": \"flag\" },\n    \"low\":                { \"attribOption\": [] },\n    \"manifest\":           { \"attribOption\": [] },\n    \"max\":                { \"attribOption\": [] },\n    \"maxlength\":          { \"attribOption\": [] },\n    \"media\":              { \"attribOption\": [\"screen\", \"tty\", \"tv\", \"projection\", \"handheld\", \"print\", \"aural\", \"braille\", \"embossed\", \"speech\", \"all\", \"width\",\n                                             \"min-width\", \"max-width\", \"height\", \"min-height\", \"max-height\", \"device-width\", \"min-device-width\", \"max-device-width\",\n                                             \"device-height\", \"min-device-height\", \"max-device-height\", \"orientation\", \"aspect-ratio\", \"min-aspect-ratio\",\n                                             \"max-aspect-ratio\", \"device-aspect-ratio\", \"min-device-aspect-ratio\", \"max-device-aspect-ratio\", \"color\",\n                                             \"min-color\", \"max-color\", \"color-index\", \"min-color-index\", \"max-color-index\", \"monochrome\", \"min-monochrome\",\n                                             \"max-monochrome\", \"resolution\", \"min-resolution\", \"max-resolution\", \"scan\", \"grid\"],\n                            \"allowMultipleValues\": \"true\" },\n    \"mediagroup\":         { \"attribOption\": [] },\n    \"method\":             { \"attribOption\": [\"get\", \"post\"] },\n    \"min\":                { \"attribOption\": [] },\n    \"multiple\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"muted\":              { \"attribOption\": [], \"type\": \"flag\" },\n    \"name\":               { \"attribOption\": [] },\n    \"meta/name\":          { \"attribOption\": [\"application-name\", \"author\", \"description\", \"generator\", \"keywords\"] },\n    \"novalidate\":         { \"attribOption\": [], \"type\": \"flag\" },\n    \"open\":               { \"attribOption\": [], \"type\": \"flag\" },\n    \"optimum\":            { \"attribOption\": [] },\n    \"pattern\":            { \"attribOption\": [] },\n    \"placeholder\":        { \"attribOption\": [] },\n    \"poster\":             { \"attribOption\": [] },\n    \"preload\":            { \"attribOption\": [\"auto\", \"metadata\", \"none\"] },\n    \"pubdate\":            { \"attribOption\": [] },\n    \"radiogroup\":         { \"attribOption\": [] },\n    \"rel\":                { \"attribOption\": [\"alternate\", \"author\", \"bookmark\", \"help\", \"license\", \"next\", \"nofollow\", \"noreferrer\", \"prefetch\",\n                                             \"prev\", \"search\", \"sidebar\", \"tag\", \"external\"] },\n    \"link/rel\":           { \"attribOption\": [\"alternate\", \"author\", \"help\", \"icon\", \"license\", \"next\", \"pingback\", \"prefetch\", \"prev\", \"search\",\n                                             \"sidebar\", \"stylesheet\", \"tag\"] },\n    \"readonly\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"required\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"reversed\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"rows\":               { \"attribOption\": [] },\n    \"rowspan\":            { \"attribOption\": [] },\n    \"sandbox\":            { \"attribOption\": [\"allow-forms\", \"allow-same-origin\", \"allow-scripts\", \"allow-top-navigation\"] },\n    \"seamless\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"selected\":           { \"attribOption\": [], \"type\": \"flag\" },\n    \"scope\":              { \"attribOption\": [\"col\", \"colgroup\", \"row\", \"rowgroup\"] },\n    \"scoped\":             { \"attribOption\": [], \"type\": \"boolean\" },\n    \"scrollamount\":       { \"attribOption\": [] },\n    \"scrolldelay\":        { \"attribOption\": [] },\n    \"shape\":              { \"attribOption\": [\"circle\", \"default\", \"poly\",\"rect\"] },\n    \"size\":               { \"attribOption\": [] },\n    \"sizes\":              { \"attribOption\": [\"any\"] },\n    \"span\":               { \"attribOption\": [] },\n    \"src\":                { \"attribOption\": [] },\n    \"srcdoc\":             { \"attribOption\": [] },\n    \"srclang\":            { \"attribOption\": [] },\n    \"standby\":            { \"attribOption\": [] },\n    \"start\":              { \"attribOption\": [] },\n    \"step\":               { \"attribOption\": [] },\n    \"target\":             { \"attribOption\": [\"_blank\", \"_parent\", \"_self\", \"_top\"] },\n    \"truespeed\":          { \"attribOption\": [], \"type\": \"flag\" },\n    \"type\":               { \"attribOption\": [] },\n    \"button/type\":        { \"attribOption\": [\"button\", \"reset\", \"submit\"] },\n    \"command/type\":       { \"attribOption\": [\"command\", \"checkbox\", \"radio\"] },\n    \"link/type\":          { \"attribOption\": [\"text/css\"] },\n    \"menu/type\":          { \"attribOption\": [\"context\", \"list\", \"toolbar\"] },\n    \"ol/type\":            { \"attribOption\": [\"1\", \"a\", \"A\", \"i\", \"I\"] },\n    \"script/type\":        { \"attribOption\": [\"text/javascript\", \"text/ecmascript\", \"text/jscript\", \"text/livescript\", \"text/tcl\", \"text/x-javascript\", \"text/x-ecmascript\",\n                                             \"application/x-javascript\", \"application/x-ecmascript\", \"application/javascript\", \"application/ecmascript\",\n                                             \"text/babel\", \"text/jsx\"] },\n    \"style/type\":         { \"attribOption\": [\"text/css\"] },\n    \"input/type\":         { \"attribOption\": [\"button\", \"checkbox\", \"color\", \"date\", \"datetime\", \"datetime-local\", \"email\", \"file\", \"hidden\", \"image\", \"month\",\n                                             \"number\", \"password\", \"radio\", \"range\", \"reset\", \"search\", \"submit\", \"tel\", \"text\", \"time\", \"url\", \"week\"] },\n    \"usemap\":             { \"attribOption\": [] },\n    \"value\":              { \"attribOption\": [] },\n    \"vspace\":             { \"attribOption\": [] },\n    \"width\":              { \"attribOption\": [] },\n    \"wrap\":               { \"attribOption\": [\"hard\", \"soft\"] },\n    \"xml:lang\":           { \"attribOption\": [] },\n    \"xmlns\":              { \"attribOption\": [] }\n}\n"
  },
  {
    "path": "src/extensions/default/HTMLCodeHints/HtmlTags.json",
    "content": "{     \n    \"a\":          { \"attributes\": [\"href\", \"hreflang\", \"media\", \"rel\", \"target\", \"type\"] },\n    \"abbr\":       { \"attributes\": [] },\n    \"address\":    { \"attributes\": [] },\n    \"area\":       { \"attributes\": [\"alt\", \"coords\", \"href\", \"hreflang\", \"media\", \"rel\", \"shape\", \"target\", \"type\"] },\n    \"article\":    { \"attributes\": [] },\n    \"aside\":      { \"attributes\": [] },\n    \"audio\":      { \"attributes\": [\"autoplay\", \"controls\", \"loop\", \"mediagroup\", \"muted\", \"preload\", \"src\"] },\n    \"b\":          { \"attributes\": [] },\n    \"base\":       { \"attributes\": [\"href\", \"target\"] },\n    \"bdi\":        { \"attributes\": [] },\n    \"bdo\":        { \"attributes\": [] },\n    \"big\":        { \"attributes\": [] },\n    \"blockquote\": { \"attributes\": [\"cite\"] },\n    \"body\":       { \"attributes\": [\"onafterprint\", \"onbeforeprint\", \"onbeforeunload\", \"onhashchange\", \"onmessage\", \"onoffline\", \"ononline\",\n                                   \"onpagehide\", \"onpageshow\", \"onpopstate\", \"onredo\", \"onresize\", \"onstorage\", \"onundo\", \"onunload\"] },\n    \"br\":         { \"attributes\": [] },\n    \"button\":     { \"attributes\": [\"autofocus\", \"disabled\", \"form\", \"formaction\", \"formenctype\", \"formmethod\", \"formnovalidate\", \"formtarget\", \n                                   \"name\", \"type\", \"value\"] },\n    \"canvas\":     { \"attributes\": [\"height\", \"width\"] },\n    \"caption\":    { \"attributes\": [] },\n    \"cite\":       { \"attributes\": [] },\n    \"code\":       { \"attributes\": [] },\n    \"col\":        { \"attributes\": [\"span\"] },\n    \"colgroup\":   { \"attributes\": [\"span\"] },\n    \"command\":    { \"attributes\": [\"checked\", \"disabled\", \"icon\", \"label\", \"radiogroup\", \"type\"] },\n    \"datalist\":   { \"attributes\": [] },\n    \"dd\":         { \"attributes\": [] },\n    \"del\":        { \"attributes\": [\"cite\", \"datetime\"] },\n    \"details\":    { \"attributes\": [\"open\"] },\n    \"dfn\":        { \"attributes\": [] },\n    \"dialog\":     { \"attributes\": [\"open\"] },\n    \"div\":        { \"attributes\": [] },\n    \"dl\":         { \"attributes\": [] },\n    \"dt\":         { \"attributes\": [] },\n    \"em\":         { \"attributes\": [] },\n    \"embed\":      { \"attributes\": [\"height\", \"src\", \"type\", \"width\"] },\n    \"fieldset\":   { \"attributes\": [\"disabled\", \"form\", \"name\"] },\n    \"figcaption\": { \"attributes\": [] },\n    \"figure\":     { \"attributes\": [] },\n    \"footer\":     { \"attributes\": [] },\n    \"form\":       { \"attributes\": [\"accept-charset\", \"action\", \"autocomplete\", \"enctype\", \"method\", \"name\", \"novalidate\", \"target\"] },\n    \"h1\":         { \"attributes\": [] },\n    \"h2\":         { \"attributes\": [] },\n    \"h3\":         { \"attributes\": [] },\n    \"h4\":         { \"attributes\": [] },\n    \"h5\":         { \"attributes\": [] },\n    \"h6\":         { \"attributes\": [] },\n    \"head\":       { \"attributes\": [] },\n    \"header\":     { \"attributes\": [] },\n    \"hgroup\":     { \"attributes\": [] },\n    \"hr\":         { \"attributes\": [] },\n    \"html\":       { \"attributes\": [\"manifest\", \"xml:lang\", \"xmlns\"] },\n    \"i\":          { \"attributes\": [] },\n    \"iframe\":     { \"attributes\": [\"height\", \"name\", \"sandbox\", \"seamless\", \"src\", \"srcdoc\", \"width\"] },\n    \"ilayer\":     { \"attributes\": [] },\n    \"img\":        { \"attributes\": [\"alt\", \"height\", \"ismap\", \"longdesc\", \"src\", \"usemap\", \"width\"] },\n    \"input\":      { \"attributes\": [\"accept\", \"alt\", \"autocomplete\", \"autofocus\", \"checked\", \"dirname\", \"disabled\", \"form\", \"formaction\", \"formenctype\", \"formmethod\", \n                                   \"formnovalidate\", \"formtarget\", \"height\", \"list\", \"max\", \"maxlength\", \"min\", \"multiple\", \"name\", \"pattern\", \"placeholder\", \"readonly\", \n                                   \"required\", \"size\", \"src\", \"step\", \"type\", \"value\", \"width\"] },\n    \"ins\":        { \"attributes\": [\"cite\", \"datetime\"] },\n    \"kbd\":        { \"attributes\": [] },\n    \"keygen\":     { \"attributes\": [\"autofocus\", \"challenge\", \"disabled\", \"form\", \"keytype\", \"name\"] },\n    \"label\":      { \"attributes\": [\"for\", \"form\"] },\n    \"legend\":     { \"attributes\": [] },\n    \"li\":         { \"attributes\": [\"value\"] },\n    \"link\":       { \"attributes\": [\"disabled\", \"href\", \"hreflang\", \"media\", \"rel\", \"sizes\", \"type\"] },\n    \"main\":       { \"attributes\": [] },\n    \"map\":        { \"attributes\": [\"name\"] },\n    \"mark\":       { \"attributes\": [] },\n    \"marquee\":    { \"attributes\": [\"align\", \"behavior\", \"bgcolor\", \"direction\", \"height\", \"hspace\", \"loop\", \"scrollamount\", \"scrolldelay\", \"truespeed\", \"vspace\", \"width\"] },\n    \"menu\":       { \"attributes\": [\"label\", \"type\"] },\n    \"meta\":       { \"attributes\": [\"charset\", \"content\", \"http-equiv\", \"name\"] },\n    \"meter\":      { \"attributes\": [\"form\", \"high\", \"low\", \"max\", \"min\", \"optimum\", \"value\"] },\n    \"nav\":        { \"attributes\": [] },\n    \"noscript\":   { \"attributes\": [] },\n    \"object\":     { \"attributes\": [\"archive\", \"codebase\", \"codetype\", \"data\", \"declare\", \"form\", \"height\", \"name\", \"standby\", \"type\", \"usemap\", \"width\"] },\n    \"ol\":         { \"attributes\": [\"reversed\", \"start\", \"type\"] },\n    \"optgroup\":   { \"attributes\": [\"disabled\", \"label\"] },\n    \"option\":     { \"attributes\": [\"disabled\", \"label\", \"selected\", \"value\"] },\n    \"output\":     { \"attributes\": [\"for\", \"form\", \"name\"] },\n    \"p\":          { \"attributes\": [] },\n    \"param\":      { \"attributes\": [\"name\", \"value\"] },\n    \"pre\":        { \"attributes\": [] },\n    \"progress\":   { \"attributes\": [\"form\", \"max\", \"value\"] },\n    \"q\":          { \"attributes\": [\"cite\"] },\n    \"rp\":         { \"attributes\": [] },\n    \"rt\":         { \"attributes\": [] },\n    \"ruby\":       { \"attributes\": [] },\n    \"samp\":       { \"attributes\": [] },\n    \"script\":     { \"attributes\": [\"async\", \"charset\", \"defer\", \"src\", \"type\"] },\n    \"section\":    { \"attributes\": [] },\n    \"select\":     { \"attributes\": [\"autofocus\", \"disabled\", \"form\", \"multiple\", \"name\", \"required\", \"size\"] },\n    \"small\":      { \"attributes\": [] },\n    \"source\":     { \"attributes\": [\"media\", \"src\", \"type\"] },\n    \"span\":       { \"attributes\": [] },\n    \"strong\":     { \"attributes\": [] },\n    \"style\":      { \"attributes\": [\"disabled\", \"media\", \"scoped\", \"type\"] },\n    \"sub\":        { \"attributes\": [] },\n    \"summary\":    { \"attributes\": [] },\n    \"sup\":        { \"attributes\": [] },\n    \"table\":      { \"attributes\": [\"border\"] },\n    \"tbody\":      { \"attributes\": [] },\n    \"td\":         { \"attributes\": [\"colspan\", \"headers\", \"rowspan\"] },\n    \"template\":   { \"attributes\": [\"content\"] },\n    \"textarea\":   { \"attributes\": [\"autofocus\", \"cols\", \"dirname\", \"disabled\", \"form\", \"label\", \"maxlength\", \"name\", \"placeholder\", \"readonly\", \"required\", \"rows\", \"wrap\"] },\n    \"tfoot\":      { \"attributes\": [] },\n    \"th\":         { \"attributes\": [\"colspan\", \"headers\", \"rowspan\", \"scope\"] },\n    \"thead\":      { \"attributes\": [] },\n    \"time\":       { \"attributes\": [\"datetime\", \"pubdate\"] },\n    \"title\":      { \"attributes\": [] },\n    \"tr\":         { \"attributes\": [] },\n    \"track\":      { \"attributes\": [\"default\", \"kind\", \"label\", \"src\", \"srclang\"] },\n    \"tt\":         { \"attributes\": [] },\n    \"ul\":         { \"attributes\": [] },\n    \"var\":        { \"attributes\": [] },\n    \"video\":      { \"attributes\": [\"autoplay\", \"controls\", \"height\", \"loop\", \"mediagroup\", \"muted\", \"poster\", \"preload\", \"src\", \"width\"] },\n    \"wbr\":        { \"attributes\": [] }\n}\n"
  },
  {
    "path": "src/extensions/default/HTMLCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        HTMLUtils           = brackets.getModule(\"language/HTMLUtils\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings             = brackets.getModule(\"strings\"),\n        HTMLTags            = require(\"text!HtmlTags.json\"),\n        HTMLAttributes      = require(\"text!HtmlAttributes.json\"),\n        tags,\n        attributes;\n\n    PreferencesManager.definePreference(\"codehint.TagHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_HTML_TAG_HINTS\n    });\n\n    PreferencesManager.definePreference(\"codehint.AttrHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_ATTR_HINTS\n    });\n\n    /**\n     * @constructor\n     */\n    function TagHints() {\n        this.exclusion = null;\n    }\n\n    /**\n     * Check whether the exclusion is still the same as text after the cursor.\n     * If not, reset it to null.\n     */\n    TagHints.prototype.updateExclusion = function () {\n        var textAfterCursor;\n        if (this.exclusion && this.tagInfo) {\n            textAfterCursor = this.tagInfo.tagName.substr(this.tagInfo.position.offset);\n            if (!CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                this.exclusion = null;\n            }\n        }\n    };\n\n    /**\n     * Determines whether HTML tag hints are available in the current editor\n     * context.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non- null,\n     * whether it is appropriate to do so.\n     */\n    TagHints.prototype.hasHints = function (editor, implicitChar) {\n        var pos = editor.getCursorPos();\n\n        this.tagInfo = HTMLUtils.getTagInfo(editor, pos);\n        this.editor = editor;\n        if (implicitChar === null) {\n            if (this.tagInfo.position.tokenType === HTMLUtils.TAG_NAME) {\n                if (this.tagInfo.position.offset >= 0) {\n                    if (this.tagInfo.position.offset === 0) {\n                        this.exclusion = this.tagInfo.tagName;\n                    } else {\n                        this.updateExclusion();\n                    }\n                    return true;\n                }\n            }\n            return false;\n        } else {\n            if (implicitChar === \"<\") {\n                this.exclusion = this.tagInfo.tagName;\n                return true;\n            }\n            return false;\n        }\n    };\n\n    /**\n     * Returns a list of availble HTML tag hints if possible for the current\n     * editor context.\n     *\n     * @return {jQuery.Deferred|{\n     *              hints: Array.<string|jQueryObject>,\n     *              match: string,\n     *              selectInitial: boolean,\n     *              handleWideResults: boolean}}\n     * Null if the provider wishes to end the hinting session. Otherwise, a\n     * response object that provides:\n     * 1. a sorted array hints that consists of strings\n     * 2. a string match that is used by the manager to emphasize matching\n     *    substrings when rendering the hint list\n     * 3. a boolean that indicates whether the first result, if one exists,\n     *    should be selected by default in the hint list window.\n     * 4. handleWideResults, a boolean (or undefined) that indicates whether\n     *    to allow result string to stretch width of display.\n     */\n    TagHints.prototype.getHints = function (implicitChar) {\n        var query,\n            result;\n\n        this.tagInfo = HTMLUtils.getTagInfo(this.editor, this.editor.getCursorPos());\n        if (this.tagInfo.position.tokenType === HTMLUtils.TAG_NAME) {\n            if (this.tagInfo.position.offset >= 0) {\n                this.updateExclusion();\n                query = this.tagInfo.tagName.slice(0, this.tagInfo.position.offset);\n                result = $.map(tags, function (value, key) {\n                    if (key.indexOf(query) === 0) {\n                        return key;\n                    }\n                }).sort();\n\n                return {\n                    hints: result,\n                    match: query,\n                    selectInitial: true,\n                    handleWideResults: false\n                };\n            }\n        }\n\n        return null;\n    };\n\n    /**\n     * Inserts a given HTML tag hint into the current editor context.\n     *\n     * @param {string} hint\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    TagHints.prototype.insertHint = function (completion) {\n        var start = {line: -1, ch: -1},\n            end = {line: -1, ch: -1},\n            cursor = this.editor.getCursorPos(),\n            charCount = 0;\n\n        if (this.tagInfo.position.tokenType === HTMLUtils.TAG_NAME) {\n            var textAfterCursor = this.tagInfo.tagName.substr(this.tagInfo.position.offset);\n            if (CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                charCount = this.tagInfo.position.offset;\n            } else {\n                charCount = this.tagInfo.tagName.length;\n            }\n        }\n\n        end.line = start.line = cursor.line;\n        start.ch = cursor.ch - this.tagInfo.position.offset;\n        end.ch = start.ch + charCount;\n\n        if (this.exclusion || completion !== this.tagInfo.tagName) {\n            if (start.ch !== end.ch) {\n                this.editor.document.replaceRange(completion, start, end);\n            } else {\n                this.editor.document.replaceRange(completion, start);\n            }\n            this.exclusion = null;\n        }\n\n        return false;\n    };\n\n    /**\n     * @constructor\n     */\n    function AttrHints() {\n        this.globalAttributes = this.readGlobalAttrHints();\n        this.cachedHints = null;\n        this.exclusion = \"\";\n    }\n\n    /**\n     * @private\n     * Parse the code hints from JSON data and extract all hints from property names.\n     * @return {!Array.<string>} An array of code hints read from the JSON data source.\n     */\n    AttrHints.prototype.readGlobalAttrHints = function () {\n        return $.map(attributes, function (value, key) {\n            if (value.global === \"true\") {\n                return key;\n            }\n        });\n    };\n\n    /**\n     * Helper function that determines the possible value hints for a given html tag/attribute name pair\n     *\n     * @param {{queryStr: string}} query\n     * The current query\n     *\n     * @param {string} tagName\n     * HTML tag name\n     *\n     * @param {string} attrName\n     * HTML attribute name\n     *\n     * @return {!Array.<string>|$.Deferred}\n     * The (possibly deferred) hints.\n     */\n    AttrHints.prototype._getValueHintsForAttr = function (query, tagName, attrName) {\n        // We look up attribute values with tagName plus a slash and attrName first.\n        // If the lookup fails, then we fall back to look up with attrName only. Most\n        // of the attributes in JSON are using attribute name only as their properties,\n        // but in some cases like \"type\" attribute, we have different properties like\n        // \"script/type\", \"link/type\" and \"button/type\".\n        var hints = [];\n\n        var tagPlusAttr = tagName + \"/\" + attrName,\n            attrInfo = attributes[tagPlusAttr] || attributes[attrName];\n\n        if (attrInfo) {\n            if (attrInfo.type === \"boolean\") {\n                hints = [\"false\", \"true\"];\n            } else if (attrInfo.attribOption) {\n                hints = attrInfo.attribOption;\n            }\n        }\n\n        return hints;\n    };\n\n    /**\n     * Check whether the exclusion is still the same as text after the cursor.\n     * If not, reset it to null.\n     *\n     * @param {boolean} attrNameOnly\n     * true to indicate that we update the exclusion only if the cursor is inside an attribute name context.\n     * Otherwise, we also update exclusion for attribute value context.\n     */\n    AttrHints.prototype.updateExclusion = function (attrNameOnly) {\n        if (this.exclusion && this.tagInfo) {\n            var tokenType = this.tagInfo.position.tokenType,\n                offset = this.tagInfo.position.offset,\n                textAfterCursor;\n\n            if (tokenType === HTMLUtils.ATTR_NAME) {\n                textAfterCursor = this.tagInfo.attr.name.substr(offset);\n            } else if (!attrNameOnly && tokenType === HTMLUtils.ATTR_VALUE) {\n                textAfterCursor = this.tagInfo.attr.value.substr(offset);\n            }\n            if (!CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                this.exclusion = null;\n            }\n        }\n    };\n\n    /**\n     * Determines whether HTML attribute hints are available in the current\n     * editor context.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non-null,\n     * whether it is appropriate to do so.\n     */\n    AttrHints.prototype.hasHints = function (editor, implicitChar) {\n        var pos = editor.getCursorPos(),\n            tokenType,\n            offset,\n            query;\n\n        this.editor = editor;\n        this.tagInfo = HTMLUtils.getTagInfo(editor, pos);\n        tokenType = this.tagInfo.position.tokenType;\n        offset = this.tagInfo.position.offset;\n        if (implicitChar === null) {\n            query = null;\n\n            if (tokenType === HTMLUtils.ATTR_NAME) {\n                if (offset >= 0) {\n                    query = this.tagInfo.attr.name.slice(0, offset);\n                }\n            } else if (tokenType === HTMLUtils.ATTR_VALUE) {\n                if (this.tagInfo.position.offset >= 0) {\n                    query = this.tagInfo.attr.value.slice(0, offset);\n                } else {\n                    // We get negative offset for a quoted attribute value with some leading whitespaces\n                    // as in <a rel= \"rtl\" where the cursor is just to the right of the \"=\".\n                    // So just set the queryStr to an empty string.\n                    query = \"\";\n                }\n\n                // If we're at an attribute value, check if it's an attribute name that has hintable values.\n                if (this.tagInfo.attr.name) {\n                    var hints = this._getValueHintsForAttr({queryStr: query},\n                                                           this.tagInfo.tagName,\n                                                           this.tagInfo.attr.name);\n                    if (hints instanceof Array) {\n                        // If we got synchronous hints, check if we have something we'll actually use\n                        var i, foundPrefix = false;\n                        for (i = 0; i < hints.length; i++) {\n                            if (hints[i].indexOf(query) === 0) {\n                                foundPrefix = true;\n                                break;\n                            }\n                        }\n                        if (!foundPrefix) {\n                            query = null;\n                        }\n                    }\n                }\n            }\n\n            if (offset >= 0) {\n                if (tokenType === HTMLUtils.ATTR_NAME && offset === 0) {\n                    this.exclusion = this.tagInfo.attr.name;\n                } else {\n                    this.updateExclusion(false);\n                }\n            }\n\n            return query !== null;\n        } else {\n            if (implicitChar === \" \" || implicitChar === \"'\" ||\n                    implicitChar === \"\\\"\" || implicitChar === \"=\") {\n                if (tokenType === HTMLUtils.ATTR_NAME) {\n                    this.exclusion = this.tagInfo.attr.name;\n                }\n                return true;\n            }\n            return false;\n        }\n    };\n\n    /**\n     * Returns a list of availble HTML attribute hints if possible for the\n     * current editor context.\n     *\n     * @return {jQuery.Deferred|{\n     *              hints: Array.<string|jQueryObject>,\n     *              match: string,\n     *              selectInitial: boolean,\n     *              handleWideResults: boolean}}\n     * Null if the provider wishes to end the hinting session. Otherwise, a\n     * response object that provides:\n     * 1. a sorted array hints that consists of strings\n     * 2. a string match that is used by the manager to emphasize matching\n     *    substrings when rendering the hint list\n     * 3. a boolean that indicates whether the first result, if one exists,\n     *    should be selected by default in the hint list window.\n     * 4. handleWideResults, a boolean (or undefined) that indicates whether\n     *    to allow result string to stretch width of display.\n     */\n    AttrHints.prototype.getHints = function (implicitChar) {\n        var cursor = this.editor.getCursorPos(),\n            query = {queryStr: null},\n            tokenType,\n            offset,\n            result = [];\n\n        this.tagInfo = HTMLUtils.getTagInfo(this.editor, cursor);\n        tokenType = this.tagInfo.position.tokenType;\n        offset = this.tagInfo.position.offset;\n        if (tokenType === HTMLUtils.ATTR_NAME || tokenType === HTMLUtils.ATTR_VALUE) {\n            query.tag = this.tagInfo.tagName;\n\n            if (offset >= 0) {\n                if (tokenType === HTMLUtils.ATTR_NAME) {\n                    query.queryStr = this.tagInfo.attr.name.slice(0, offset);\n                } else {\n                    query.queryStr = this.tagInfo.attr.value.slice(0, offset);\n                    query.attrName = this.tagInfo.attr.name;\n                }\n                this.updateExclusion(false);\n            } else if (tokenType === HTMLUtils.ATTR_VALUE) {\n                // We get negative offset for a quoted attribute value with some leading whitespaces\n                // as in <a rel= \"rtl\" where the cursor is just to the right of the \"=\".\n                // So just set the queryStr to an empty string.\n                query.queryStr = \"\";\n                query.attrName = this.tagInfo.attr.name;\n            }\n\n            query.usedAttr = HTMLUtils.getTagAttributes(this.editor, cursor);\n        }\n\n        if (query.tag && query.queryStr !== null) {\n            var tagName = query.tag,\n                attrName = query.attrName,\n                filter = query.queryStr,\n                unfiltered = [],\n                hints;\n\n            if (attrName) {\n                hints = this._getValueHintsForAttr(query, tagName, attrName);\n            } else if (tags && tags[tagName] && tags[tagName].attributes) {\n                unfiltered = tags[tagName].attributes.concat(this.globalAttributes);\n                hints = $.grep(unfiltered, function (attr, i) {\n                    return $.inArray(attr, query.usedAttr) < 0;\n                });\n            }\n\n            if (hints instanceof Array && hints.length) {\n                console.assert(!result.length);\n                result = $.map(hints, function (item) {\n                    if (item.indexOf(filter) === 0) {\n                        return item;\n                    }\n                }).sort();\n                return {\n                    hints: result,\n                    match: query.queryStr,\n                    selectInitial: true,\n                    handleWideResults: false\n                };\n            } else if (hints instanceof Object && hints.hasOwnProperty(\"done\")) { // Deferred hints\n                var deferred = $.Deferred();\n                hints.done(function (asyncHints) {\n                    deferred.resolveWith(this, [{\n                        hints: asyncHints,\n                        match: query.queryStr,\n                        selectInitial: true,\n                        handleWideResults: false\n                    }]);\n                });\n                return deferred;\n            } else {\n                return null;\n            }\n        }\n\n\n    };\n\n    /**\n     * Inserts a given HTML attribute hint into the current editor context.\n     *\n     * @param {string} hint\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    AttrHints.prototype.insertHint = function (completion) {\n        var cursor = this.editor.getCursorPos(),\n            start = {line: -1, ch: -1},\n            end = {line: -1, ch: -1},\n            tokenType = this.tagInfo.position.tokenType,\n            offset = this.tagInfo.position.offset,\n            charCount = 0,\n            insertedName = false,\n            replaceExistingOne = this.tagInfo.attr.valueAssigned,\n            endQuote = \"\",\n            shouldReplace = true,\n            textAfterCursor;\n\n        if (tokenType === HTMLUtils.ATTR_NAME) {\n            textAfterCursor = this.tagInfo.attr.name.substr(offset);\n            if (CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                charCount = offset;\n                replaceExistingOne = false;\n            } else {\n                charCount = this.tagInfo.attr.name.length;\n            }\n            // Append an equal sign and two double quotes if the current attr is not an empty attr\n            // and then adjust cursor location before the last quote that we just inserted.\n            if (!replaceExistingOne && attributes && attributes[completion] &&\n                    attributes[completion].type !== \"flag\") {\n                completion += \"=\\\"\\\"\";\n                insertedName = true;\n            } else if (completion === this.tagInfo.attr.name) {\n                shouldReplace = false;\n            }\n        } else if (tokenType === HTMLUtils.ATTR_VALUE) {\n            textAfterCursor = this.tagInfo.attr.value.substr(offset);\n            if (CodeHintManager.hasValidExclusion(this.exclusion, textAfterCursor)) {\n                charCount = offset;\n                // Set exclusion to null only after attribute value insertion,\n                // not after attribute name insertion since we need to keep it\n                // for attribute value insertion.\n                this.exclusion = null;\n            } else {\n                charCount = this.tagInfo.attr.value.length;\n            }\n\n            if (!this.tagInfo.attr.hasEndQuote) {\n                endQuote = this.tagInfo.attr.quoteChar;\n                if (endQuote) {\n                    completion += endQuote;\n                } else if (offset === 0) {\n                    completion = \"\\\"\" + completion + \"\\\"\";\n                }\n            } else if (completion === this.tagInfo.attr.value) {\n                shouldReplace = false;\n            }\n        }\n\n        end.line = start.line = cursor.line;\n        start.ch = cursor.ch - offset;\n        end.ch = start.ch + charCount;\n\n        if (shouldReplace) {\n            if (start.ch !== end.ch) {\n                this.editor.document.replaceRange(completion, start, end);\n            } else {\n                this.editor.document.replaceRange(completion, start);\n            }\n        }\n\n        if (insertedName) {\n            this.editor.setCursorPos(start.line, start.ch + completion.length - 1);\n\n            // Since we're now inside the double-quotes we just inserted,\n            // immediately pop up the attribute value hint.\n            return true;\n        } else if (tokenType === HTMLUtils.ATTR_VALUE && this.tagInfo.attr.hasEndQuote) {\n            // Move the cursor to the right of the existing end quote after value insertion.\n            this.editor.setCursorPos(start.line, start.ch + completion.length + 1);\n        }\n\n        return false;\n    };\n\n    AppInit.appReady(function () {\n        // Parse JSON files\n        tags = JSON.parse(HTMLTags);\n        attributes = JSON.parse(HTMLAttributes);\n\n        // Register code hint providers\n        var tagHints = new TagHints();\n        var attrHints = new AttrHints();\n        CodeHintManager.registerHintProvider(tagHints, [\"html\"], 0);\n        CodeHintManager.registerHintProvider(attrHints, [\"html\"], 0);\n\n        // For unit testing\n        exports.tagHintProvider = tagHints;\n        exports.attrHintProvider = attrHints;\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/HTMLCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, xit, expect, beforeEach, afterEach */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Modules from the SpecRunner window\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        Editor          = brackets.getModule(\"editor/Editor\").Editor,\n        HTMLCodeHints   = require(\"main\");\n\n    describe(\"HTML Code Hinting\", function () {\n\n        var defaultContent = \"<!doctype html>\\n\" +\n                             \"<html>\\n\" +\n                             \"<style type=\\\"text/css\\\">\\n\" +\n                             \"</style>\\n\" +\n                             \"<body>\\n\" +\n                             \"  <h1 id='foo'>Heading</h1>\\n\" +       // tag without whitespace\n                             \"  <h3 id  = 'bar' >Subheading</h3>\\n\" + // tag with whitespace\n                             \"  <p></p>\\n\" +                         // tag without attributes\n                             \"  <h5 id='aaa' class='bbb'></h5>\\n\" +  // tag with two attributes\n                             \"  <div \\n\" +                           // incomplete tag\n                             \"</body>\\n\" +\n                             \"</html>\\n\";\n\n        var testDocument, testEditor;\n\n        beforeEach(function () {\n            // create dummy Document for the Editor\n            testDocument = SpecRunnerUtils.createMockDocument(defaultContent, \"html\");\n\n            // create Editor instance (containing a CodeMirror instance)\n            $(\"body\").append(\"<div id='editor'/>\");\n            testEditor = new Editor(testDocument, true, $(\"#editor\").get(0));\n        });\n\n        afterEach(function () {\n            testEditor.destroy();\n            testEditor = null;\n            $(\"#editor\").remove();\n            testDocument = null;\n        });\n\n\n        // Ask provider for hints at current cursor position; expect it to return some\n        function expectHints(provider) {\n            expect(provider.hasHints(testEditor, null)).toBe(true);\n            var hintsObj = provider.getHints();\n            expect(hintsObj).toBeTruthy();\n            return hintsObj.hints; // return just the array of hints\n        }\n\n        // Ask provider for hints at current cursor position; expect it NOT to return any\n        function expectNoHints(provider) {\n            expect(provider.hasHints(testEditor, null)).toBe(false);\n        }\n\n        // Expect hintList to contain tag names, starting with given value (if unspecified, expects the default unfiltered list)\n        function verifyTagHints(hintList, expectedFirstHint) {\n            expect(hintList.indexOf(\"id\")).toBe(-1);   // make sure attribute names aren't sneaking in there\n\n            expectedFirstHint = expectedFirstHint || \"a\";  // assume unfiltered lists always start with \"a\"\n            expect(hintList[0]).toBe(expectedFirstHint);\n        }\n\n        // Expect hintList to contain attribute names, starting with given value (if unspecified, expects the default unfilered list)\n        function verifyAttrHints(hintList, expectedFirstHint) {\n            expect(hintList.indexOf(\"div\")).toBe(-1);   // make sure tag names aren't sneaking in there\n\n            expectedFirstHint = expectedFirstHint || \"accesskey\";  // assume unfiltered lists always start with \"accesskey\"\n            expect(hintList[0]).toBe(expectedFirstHint);\n        }\n\n\n        describe(\"Tag hint provider\", function () {\n\n            it(\"should not hint within <style> block\", function () {  // (bug #1277)\n                // Replace default test content with code containing a <style> block\n                testDocument.setText(\"<!doctype html>\\n\" +\n                                     \"<html>\\n\" +\n                                     \"<head>\\n\" +\n                                     \"  <style>\\n\" +\n                                     \"  </style>\\n\" +\n                                     \"</head>\\n\" +\n                                     \"<body>\\n\" +\n                                     \"</body>\\n\" +\n                                     \"</html>\\n\");\n\n                testEditor.setCursorPos({ line: 3, ch: 9 });        // cursor after the > in \"<style>\"\n                expectNoHints(HTMLCodeHints.tagHintProvider);\n            });\n\n            it(\"should hint for < just before existing tag\", function () {  // (bug #1260)\n                testDocument.replaceRange(\"<\", { line: 5, ch: 2 }); // insert text: \"<h1\" -> \"<<h1\"\n\n                testEditor.setCursorPos({ line: 5, ch: 3 });        // cursor between the two <s\n                var hintList = expectHints(HTMLCodeHints.tagHintProvider);\n                verifyTagHints(hintList);\n                expect(hintList.indexOf(\"div\")).not.toBe(-1);  // additional sanity check\n            });\n\n            it(\"should filter hints by prefix\", function () {  // (bug #1260)\n                testDocument.replaceRange(\"  <s\\n\", { line: 8, ch: 0 }); // insert new line \"<s\", after line \"<p></p>\"\n\n                testEditor.setCursorPos({ line: 8, ch: 4 });        // cursor at end of line\n                var hintList = expectHints(HTMLCodeHints.tagHintProvider);\n                verifyTagHints(hintList, \"samp\");\n                expect(hintList.indexOf(\"div\")).toBe(-1);\n                expect(hintList.indexOf(\"span\")).not.toBe(-1);\n            });\n\n            it(\"should list hints between '<' and some trailing spaces\", function () {  // (bug #1515)\n                // Replace line 9 with a complete div tag and insert a blank line and the closing div tag.\n                testDocument.replaceRange(\"<div>\\n   \\n</div>\", { line: 9, ch: 2 });\n                expect(testDocument.getLine(10)).toBe(\"   \");\n\n                // Insert a < on line 10\n                testDocument.replaceRange(\"<\", { line: 10, ch: 0 });\n                testEditor.setCursorPos({ line: 10, ch: 1 });   // cursor between < and some trailing whitespaces\n                var hintList = expectHints(HTMLCodeHints.tagHintProvider);\n                verifyTagHints(hintList);\n\n                // Replace '< ' on line 10 with '<\\t'\n                testDocument.replaceRange(\"<\\t\", { line: 10, ch: 0 }, { line: 10, ch: 2 });\n                testEditor.setCursorPos({ line: 10, ch: 1 });   // cursor between < and some trailing whitespaces\n                hintList = expectHints(HTMLCodeHints.tagHintProvider);\n                verifyTagHints(hintList);\n            });\n\n            //Test for issue #3339\n            it(\"should show HTML hints after HTML Entity on same line\", function () {\n                testDocument.replaceRange(\"&nbsp; Test <  \", { line: 8, ch: 0 });\n                testEditor.setCursorPos({ line: 8, ch: 13 });   // cursor between < and some trailing whitespaces\n                var hintList = expectHints(HTMLCodeHints.tagHintProvider);\n                verifyTagHints(hintList);\n            });\n        });\n\n        describe(\"Attribute name hint provider\", function () {\n\n            it(\"should list hints at start of existing attribute\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 6 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList);  // expect no filtering (bug #1311)\n            });\n            it(\"should list hints within existing attribute\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 7 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList, \"id\");  // filtered on \"i\"\n            });\n            it(\"should list hints at end of existing attribute\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 8 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList, \"id\");  // filtered on \"id\"\n            });\n            it(\"should list hints at end of existing attribute with whitespace\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 8 });        // cursor between end of attr (\"d\") and space\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList, \"id\");  // filtered on \"id\"\n            });\n            it(\"should list hints to right of attribute value and a space\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 18 });        // cursor between space (after attr value) and >\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList);  // expect no filtering\n            });\n\n            it(\"should NOT list hints to right of '=' sign on id attr\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 9 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should list hints to right of '=' sign\", function () {\n                testEditor.setCursorPos({ line: 2, ch: 12 });\n                expectHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            // TODO: Uncomment this after fixing issue #1521\n            xit(\"should NOT list hints to left of '=' sign with whitespace\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 9 });    // cursor between two spaces before =\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 6, ch: 10 });    // cursor between space and =\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should NOT list hints to right of '=' sign with whitespace on id attr\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 11 });   // cursor between = and space\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 6, ch: 12 });   // cursor between space and '\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should list hints to right of '=' sign with whitespace\", function () {\n                testDocument.setText('<style type = \"text/css\">');\n                testEditor.setCursorPos({ line: 0, ch: 13 });   // cursor between = and space\n                expectHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 0, ch: 14 });   // cursor between space and \"\n                expectHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should NOT list hints to right of attribute value with no separating space\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 14 });   // cursor between ' and >\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints within tag name\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 3 });   // cursor between < and start of tag name (\"h\")\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 5, ch: 4 });   // cursor in middle of tag name\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n\n                // two cases for end of tag name:\n                testEditor.setCursorPos({ line: 5, ch: 5 });   // cursor between end of tag name (\"1\") and space\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 7, ch: 4 });   // cursor between end of tag name (\"p\") and >\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should list hints to right of tag name and a space\", function () {  // (bug #1310)\n                testDocument.replaceRange(\" \", { line: 7, ch: 4 });  // insert a space: \"<p>\" -> \"<p >\"\n\n                testEditor.setCursorPos({ line: 7, ch: 5 });   // cursor between space and >\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList);  // expect no filtering\n            });\n            it(\"should list hints between tag name and attribute name (space on both sides of cursor)\", function () {\n                testDocument.replaceRange(\" \", { line: 5, ch: 5 });  // insert a space: \"<h1 id\" -> \"<h1  id\"\n\n                testEditor.setCursorPos({ line: 5, ch: 6 });   // cursor between two spaces, which are between end of tag name (\"p\") and start of attribute name\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList);  // expect no filtering\n            });\n            it(\"should list hints between prev attribute value and next attribute name (space on both sides of cursor)\", function () {\n                testDocument.replaceRange(\" \", { line: 8, ch: 14 });  // insert a space: \"'aaa' class\" -> \"'aaa'  class\"\n\n                testEditor.setCursorPos({ line: 8, ch: 15 });   // cursor between two spaces, which are between end of attribute value (\"p\") and start of attribute name\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList);  // expect no filtering\n            });\n\n            it(\"should NOT list hints to left of tag\", function () {\n                testEditor.setCursorPos({ line: 4, ch: 0 });    // tag starting at column zero\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n\n                testEditor.setCursorPos({ line: 5, ch: 2 });    // tag with whitespace indent after it\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should NOT list hints within text content or whitespace\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 0 });    // whitespace\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n\n                testEditor.setCursorPos({ line: 5, ch: 18 });   // plain text content\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints within doctype 'tag'\", function () {\n                testEditor.setCursorPos({ line: 0, ch: 10 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints within closing tag\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 23 });   // cursor between < and /\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 5, ch: 24 });   // cursor between / and start of tag name (\"h\")\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 5, ch: 25 });   // cursor in middle of tag name\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n                testEditor.setCursorPos({ line: 5, ch: 26 });   // cursor between end of tag name (\"1\") and >  (bug #1335)\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints between begin 'div' and end 'div' tag\", function () {  // (bug #1510)\n                // replace line 9 with a complete div tag and insert a blank line and the closing div tag.\n                testDocument.replaceRange(\"<div>\\n   \\n  </div>\", { line: 9, ch: 2 });\n\n                testEditor.setCursorPos({ line: 10, ch: 2 });   // cursor between whitespaces on the newly inserted blank line\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n\n                testEditor.setCursorPos({ line: 9, ch: 7 });   // cursor to the right of <div>\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n\n                testEditor.setCursorPos({ line: 11, ch: 2 });   // cursor to the left of </div>\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints between an empty tag and 'body' end tag\", function () {  // (bug #1519)\n                // replace line 9 with an input tag and insert two extra blank lines with some whitespaces.\n                testDocument.replaceRange(\"<input type='button' />\\n  \\n   \", { line: 9, ch: 2 }, { line: 9, ch: 7 });\n\n                // Set cursor between whitespaces on one of the newly inserted blank lines.\n                testEditor.setCursorPos({ line: 11, ch: 2 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints between the 'body' begin tag and 'h1' begin tag\", function () {  // (bug #1519)\n                // Insert two blank lines with some whitespaces before line 5.\n                testDocument.replaceRange(\"\\n  \\n   \", { line: 5, ch: 0 });\n\n                // Set cursor between whitespaces on one of the newly inserted blank lines.\n                testEditor.setCursorPos({ line: 7, ch: 2 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints between the 'h1' end tag and 'h3' begin tag\", function () {  // (bug #1519)\n                // Insert two blank lines with some whitespaces before line 5.\n                testDocument.replaceRange(\"\\n  \\n   \", { line: 6, ch: 0 });\n\n                // Set cursor between whitespaces on one of the newly inserted blank lines.\n                testEditor.setCursorPos({ line: 8, ch: 2 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list hints after an HTML comment\", function () {  // (bug #1440)\n                // replace line 9 with an HTML comment and some spaces\n                testDocument.replaceRange(\"<!-- some comments -->    \", { line: 9, ch: 2 });\n\n                testEditor.setCursorPos({ line: 9, ch: 25 });   // cursor between whitespaces at the end of line 9\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should list hints on incomplete tag, after tag name\", function () {\n                testEditor.setCursorPos({ line: 9, ch: 7 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n\n                verifyAttrHints(hintList);  // expect no filtering\n            });\n            it(\"should NOT list hints on incomplete tag, at end of tag name\", function () {\n                testEditor.setCursorPos({ line: 9, ch: 5 });    // end of tag name\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n\n                testEditor.setCursorPos({ line: 9, ch: 6 });    // within tag name\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should NOT list hints to left of incomplete tag\", function () {\n                testEditor.setCursorPos({ line: 9, ch: 2 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should list hints on incomplete attribute\", function () {\n                testDocument.replaceRange(\"i\", { line: 9, ch: 7 });  // insert start of attribute: \"<div \" -> \"<div i\"\n\n                testEditor.setCursorPos({ line: 9, ch: 8 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                verifyAttrHints(hintList, \"id\");  // filtered on \"i\"\n            });\n        });\n\n        describe(\"Attribute value hint provider\", function () {\n\n            it(\"should list attribute value hints for a single quote after the equal sign\", function () {\n                testDocument.replaceRange(\" dir='\", { line: 7, ch: 4 });  // insert dir=' between <p and >\n\n                testEditor.setCursorPos({ line: 7, ch: 10 });       // set cursor right after dir='\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                expect(hintList.indexOf(\"ltr\")).not.toBe(-1);       // additional sanity check\n            });\n            it(\"should list attribute value hints within an existing attribute value\", function () {\n                testDocument.replaceRange(\" dir=\\\"ltr\\\"\", { line: 7, ch: 4 });  // insert dir=\"ltr\" between <p and >\n\n                testEditor.setCursorPos({ line: 7, ch: 11 });       // set cursor right after dir=\"l\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                expect(hintList.indexOf(\"ltr\")).not.toBe(-1);       // additional sanity check\n            });\n            it(\"should list attribute value hints within an unquoted attribute value\", function () {\n                testDocument.replaceRange(\" dir=ltr\", { line: 7, ch: 4 });  // insert dir=ltr between <p and >\n\n                testEditor.setCursorPos({ line: 7, ch: 10 });       // set cursor right after dir=l\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                expect(hintList.indexOf(\"ltr\")).not.toBe(-1);       // additional sanity check\n            });\n\n            it(\"should list sorted boolean attribute value hints\", function () {\n                testDocument.replaceRange(\" spellcheck=\\\"\", { line: 7, ch: 4 });  // insert spellcheck=\" between <p and >\n\n                testEditor.setCursorPos({ line: 7, ch: 17 });       // set cursor right after spellcheck=\"\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                expect(hintList.indexOf(\"false\")).toBe(0);\n                expect(hintList.indexOf(\"true\")).toBe(1);\n                expect(hintList.length).toBe(2);\n            });\n\n            it(\"should NOT list attribute value hints to the right of a closing double quote\", function () {\n                testDocument.replaceRange(\" dir=\\\"ltr\\\"\", { line: 7, ch: 4 });  // insert dir=\"ltr\" between <p and >\n\n                testEditor.setCursorPos({ line: 7, ch: 14 });       // set cursor right after dir=\"ltr\"\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n            it(\"should NOT list attribute value hints to the right of a closing single quote\", function () {\n                testDocument.replaceRange(\" dir='ltr'\", { line: 6, ch: 5 });  // insert dir='ltr' between <h3 and id\n\n                testEditor.setCursorPos({ line: 4, ch: 15 });       // set cursor right after dir='ltr'\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should list attribute value hints for type attribute of style tag\", function () {\n                // set cursor to the right of type attribute but before the closing quote\n                testEditor.setCursorPos({ line: 2, ch: 21 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n                expect(hintList.indexOf(\"text/css\")).not.toBe(-1);\n            });\n            it(\"should NOT list any attribute value for type attribute of embed tag\", function () {\n                // set cursor to the right of type attribute but before the closing quote\n                testEditor.setCursorPos({ line: 9, ch: 3 });\n                // Replace div on line 9 with embed type=' (\"<div \" --> \"<embed type='\")\n                testDocument.replaceRange(\"embed type='\", { line: 9, ch: 3 }, { line: 9, ch: 7 });\n                testEditor.setCursorPos({ line: 9, ch: 15 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n\n            it(\"should NOT list any attribute value for an unknown attribute name\", function () {\n                testDocument.replaceRange(\"foo='\", { line: 9, ch: 7 });  // insert foo=' after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 12 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n        });\n\n\n        // CodeMirror doesn't correctly support valueless attributes, so none of them are included in the default\n        // test content above\n        describe(\"Valueless attributes\", function () {\n\n            it(\"should list hints after valueless attribute\", function () {  // (bug #1313)\n                testDocument.replaceRange(\"  <input checked >\\n\", { line: 9, ch: 0 });  // insert new line\n\n                testEditor.setCursorPos({ line: 9, ch: 17 });   // cursor between space and >\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n\n                // Expect no filtering - however, we offer some attributes (including first in the list) that\n                // are specific to the <input> tag, so we can't use the default \"no filtering\" empty arg here.\n                // (This smart filtering isn't officially part of the release, so no unit tests specifically\n                // targeting that functionality yet).\n                verifyAttrHints(hintList, \"accept\");\n            });\n\n            it(\"should list hints after attribute that follows a valueless attribute\", function () {  // (bug #1313)\n                testDocument.replaceRange(\"  <input checked accept='' >\\n\", { line: 9, ch: 0 });  // insert new line\n\n                testEditor.setCursorPos({ line: 9, ch: 27 });   // cursor between space and >\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n\n                // \"accept\" will get filtered and won't be the first one in the hints.\n                verifyAttrHints(hintList);\n            });\n\n            it(\"should list attribute value hints for an attribute that follows a valueless attribute\", function () {  // (bug #2804)\n                testDocument.replaceRange(\"  <input checked accept='' >\\n\", { line: 9, ch: 0 });  // insert new line\n\n                // cursor between quotes of accept attribute\n                testEditor.setCursorPos({ line: 9, ch: 25 });\n                var hintList = expectHints(HTMLCodeHints.attrHintProvider);\n\n                verifyAttrHints(hintList, \"application/msexcel\");\n\n                // cursor between equal sign and opening quote of accept attribute\n                testEditor.setCursorPos({ line: 9, ch: 24 });\n                hintList = expectHints(HTMLCodeHints.attrHintProvider);\n\n                verifyAttrHints(hintList, \"application/msexcel\");\n            });\n\n            it(\"should NOT list attribute value hints when the cursor is after the end quote of an attribute value\", function () {\n                testDocument.replaceRange(\"  <input checked accept='' >\\n\", { line: 9, ch: 0 });  // insert new line\n\n                // Set cursor after the closing quote of accept attribute\n                testEditor.setCursorPos({ line: 9, ch: 26 });\n                expectNoHints(HTMLCodeHints.attrHintProvider);\n            });\n        });\n\n\n        describe(\"Attribute insertion\", function () {\n\n            function selectHint(provider, expectedHint) {\n                var hintList = expectHints(provider);\n                expect(hintList.indexOf(expectedHint)).not.toBe(-1);\n                return provider.insertHint(expectedHint);\n            }\n\n            // Helper function for testing cursor position\n            function fixPos(pos) {\n                if (!(\"sticky\" in pos)) {\n                    pos.sticky = null;\n                }\n                return pos;\n            }\n            function expectCursorAt(pos) {\n                var selection = testEditor.getSelection();\n                expect(fixPos(selection.start)).toEqual(fixPos(selection.end));\n                expect(fixPos(selection.start)).toEqual(fixPos(pos));\n            }\n\n            it(\"should insert =\\\"\\\" after attribute\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 18 });   // cursor between space and >\n                selectHint(HTMLCodeHints.attrHintProvider, \"class\");\n                expect(testDocument.getLine(6)).toBe(\"  <h3 id  = 'bar' class=\\\"\\\">Subheading</h3>\");\n                expectCursorAt({ line: 6, ch: 25 });            // cursor between the two \"s\n            });\n\n            it(\"should make explicit request for new hints after attribute name has been inserted\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 18 });   // cursor between space and >\n                expect(selectHint(HTMLCodeHints.attrHintProvider, \"dir\")).toBe(true); // returning 'true' from insertHint (which is called by selectHint helper) initiates a new explicit hint request\n                expect(testDocument.getLine(6)).toBe(\"  <h3 id  = 'bar' dir=\\\"\\\">Subheading</h3>\");\n            });\n\n            it(\"should NOT insert =\\\"\\\" after valueless attribute\", function () {\n                testDocument.replaceRange(\"  <input \\n\", { line: 9, ch: 0 });  // insert new line\n\n                testEditor.setCursorPos({ line: 9, ch: 9 });    // cursor after trailing space\n                selectHint(HTMLCodeHints.attrHintProvider, \"checked\");\n                expect(testDocument.getLine(9)).toBe(\"  <input checked\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor at end of attr name\n            });\n\n            it(\"should insert a new attribute before the existing one that starts at cursor\", function () {  // (bug #1312)\n                testEditor.setCursorPos({ line: 5, ch: 6 });    // cursor between space and start of existing attribute name (\"id\")\n                selectHint(HTMLCodeHints.attrHintProvider, \"class\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 class=\\\"\\\"id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 13 });            // cursor between two double-quotes\n            });\n            it(\"should change nothing when cursor at end\", function () {  // (bug #1314)\n                testEditor.setCursorPos({ line: 5, ch: 8 });    // cursor between end of existing attribute name (\"id\") and =\n                selectHint(HTMLCodeHints.attrHintProvider, \"id\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 8 });            // cursor stays at end of attr name\n            });\n\n            it(\"should insert a valueless attribute before the existing attribute that starts at cursor\", function () {\n                testDocument.replaceRange(\"  <input id='foo'>\\n\", { line: 9, ch: 0 });  // insert new line\n\n                testEditor.setCursorPos({ line: 9, ch: 9 });    // cursor after between \"i\" and \"d\"\n                selectHint(HTMLCodeHints.attrHintProvider, \"checked\");\n                expect(testDocument.getLine(9)).toBe(\"  <input checkedid='foo'>\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor between end of attr name and =\n            });\n\n            it(\"should insert a new atribute with an empty value before the existing valueless attribute\", function () {\n                testDocument.replaceRange(\"  <input checked>\\n\", { line: 9, ch: 0 });  // insert new line\n\n                testEditor.setCursorPos({ line: 9, ch: 9 });    // cursor after trailing space\n                selectHint(HTMLCodeHints.attrHintProvider, \"class\");\n                expect(testDocument.getLine(9)).toBe(\"  <input class=\\\"\\\"checked>\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor between the two \"s\n            });\n\n            it(\"should insert the selected attribute value with the closing (single) quote\", function () {\n                testDocument.replaceRange(\"dir='\", { line: 9, ch: 7 });  // insert dir=' after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 12 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(9)).toBe(\"  <div dir='rtl'\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor after the closing quote\n            });\n\n            it(\"should insert the selected attribute value with the closing (double) quote\", function () {\n                testDocument.replaceRange(\"dir=\\\"\", { line: 9, ch: 7 });  // insert dir=\" after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 12 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(9)).toBe(\"  <div dir=\\\"rtl\\\"\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor after the closing quote\n            });\n\n            it(\"should insert the selected attribute value inside the existing quotes\", function () {\n                testDocument.replaceRange(\"dir=\\\"\\\"\", { line: 9, ch: 7 });  // insert dir=\"\" after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 12 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(9)).toBe(\"  <div dir=\\\"rtl\\\"\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor after the closing quote\n            });\n\n            it(\"should insert the selected attribute value wrapped in double quotes\", function () {\n                testDocument.replaceRange(\"dir=\", { line: 9, ch: 7 });  // insert dir= after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 11 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(9)).toBe(\"  <div dir=\\\"rtl\\\"\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor after the closing quote\n            });\n\n            it(\"should replace the partially typed attribute value with the selected attribute value\", function () {\n                testDocument.replaceRange(\"dir=\\\"lt\", { line: 9, ch: 7 });  // insert dir=\"lt after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 14 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"ltr\");\n                expect(testDocument.getLine(9)).toBe(\"  <div dir=\\\"ltr\\\"\");\n                expectCursorAt({ line: 9, ch: 16 });            // cursor after the closing quote\n            });\n\n            it(\"should replace the partially typed attribute value with the selected attribute value\", function () {\n                testDocument.replaceRange(\"dir=lt\", { line: 9, ch: 7 });  // insert dir=\"lt after <div tag\n                testEditor.setCursorPos({ line: 9, ch: 13 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"ltr\");\n                expect(testDocument.getLine(9)).toBe(\"  <div dir=ltr\");\n                expectCursorAt({ line: 9, ch: 14 });            // cursor after the closing quote\n            });\n\n            it(\"should replace an existing attribute value with the selected attribute value\", function () {\n                // Intentionally change the type of style attribute to an invalid value by replacing\n                // \"css\" with \"javascript\".\n                testDocument.replaceRange(\"javascript\", { line: 2, ch: 18 }, { line: 2, ch: 21 });\n                testEditor.setCursorPos({ line: 2, ch: 18 });\n                selectHint(HTMLCodeHints.attrHintProvider, \"text/css\");\n                expect(testDocument.getLine(2)).toBe(\"<style type=\\\"text/css\\\">\");\n                expectCursorAt({ line: 2, ch: 22 });            // cursor after the closing quote\n            });\n\n            it(\"should replace a quoted attribute value and keep the preceding space and quotes\", function () {\n                // Insert an unquoted attribute between <div and id on line 5.\n                testDocument.replaceRange(\"dir= \\\"ltr\\\" \", { line: 5, ch: 6 });\n                testEditor.setCursorPos({ line: 5, ch: 10 });   // Set the cursor between = and the space\n                // Select \"rtl\" to replace \"ltr\"\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 dir= \\\"rtl\\\" id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 16 });            // cursor after the closing quote\n\n                testEditor.setCursorPos({ line: 5, ch: 11 });   // Set the cursor between the space and the begin quote\n                // Select \"ltr\" to replace \"rtl\"\n                selectHint(HTMLCodeHints.attrHintProvider, \"ltr\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 dir= \\\"ltr\\\" id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 16 });            // cursor after the closing quote\n            });\n\n            it(\"should replace the unquoted attribute value with the selected attribute value in quotes\", function () {\n                // Insert an unquoted attribute between <div and id on line 5.\n                testDocument.replaceRange(\"dir=ltr \", { line: 5, ch: 6 });\n                testEditor.setCursorPos({ line: 5, ch: 10 });\n                // Select \"rtl\" to replace \"ltr\"\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 dir=\\\"rtl\\\" id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 15 });            // cursor after the inserted value\n            });\n\n            it(\"should replace an unquoted attribute value when the cursor is inside that value\", function () {\n                // Insert an unquoted attribute between <div and id on line 5.\n                // intentionally have an invalid attribute lttr here\n                testDocument.replaceRange(\"dir= lttr \", { line: 5, ch: 6 });\n                testEditor.setCursorPos({ line: 5, ch: 12 });   // Set cursor after l in the invalid attribute value\n                selectHint(HTMLCodeHints.attrHintProvider, \"ltr\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 dir= ltr id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 14 });            // cursor after the inserted value\n            });\n\n            it(\"should insert a quoted attribute value before an existing unquoted attribute value with preceding space character\", function () {\n                // Insert an unquoted attribute between <div and id on line 5.\n                testDocument.replaceRange(\"dir= ltr \", { line: 5, ch: 6 });\n                testEditor.setCursorPos({ line: 5, ch: 10 }); // Set cursor between = and the space\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 dir=\\\"rtl\\\" ltr id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 15 });          // cursor after the inserted value\n            });\n\n            it(\"should insert a quoted attribute value before an existing id attribute\", function () {\n                // Insert an unquoted attribute between <div and id on line 5.\n                testDocument.replaceRange(\"dir= \", { line: 5, ch: 6 });\n                testEditor.setCursorPos({ line: 5, ch: 10 }); // Set cursor between = and the space\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(5)).toBe(\"  <h1 dir=\\\"rtl\\\" id='foo'>Heading</h1>\");\n                expectCursorAt({ line: 5, ch: 15 });          // cursor after the inserted value\n            });\n\n            it(\"should insert a quoted attribute value right before the closing > of the tag\", function () {\n                // Insert an unquoted attribute between <p and > on line 7.\n                testDocument.replaceRange(\" dir=\", { line: 7, ch: 4 });\n                testEditor.setCursorPos({ line: 7, ch: 9 }); // Set cursor between = and >\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(7)).toBe(\"  <p dir=\\\"rtl\\\"></p>\");\n                expectCursorAt({ line: 7, ch: 14 });         // cursor after the inserted value\n            });\n\n            it(\"should insert a quoted attribute value without overwriting the closing > of the tag\", function () {\n                // Insert an attribute value right before > on line 7 with an opening double quote that\n                // creates an inbalanced string up to the first attribute value in the next tag.\n                testDocument.replaceRange(\"<a dir=\\\"><span class=\\\"foo\\\"></span></a>\", { line: 7, ch: 2 }, { line: 7, ch: 9 });\n                testEditor.setCursorPos({ line: 7, ch: 10 }); // Set cursor between dir=\" and >\n                selectHint(HTMLCodeHints.attrHintProvider, \"rtl\");\n                expect(testDocument.getLine(7)).toBe(\"  <a dir=\\\"rtl\\\"><span class=\\\"foo\\\"></span></a>\");\n                expectCursorAt({ line: 7, ch: 14 });          // cursor after the inserted value\n            });\n        });\n\n\n    }); // describe(\"HTML Code Hinting\"\n});\n"
  },
  {
    "path": "src/extensions/default/HandlebarsSupport/main.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var LanguageManager = brackets.getModule(\"language/LanguageManager\"),\n        CodeMirror      = brackets.getModule(\"thirdparty/CodeMirror/lib/codemirror\");\n\n    brackets.getModule([\"thirdparty/CodeMirror/mode/handlebars/handlebars\"], function () {\n        CodeMirror.defineMode(\"htmlhandlebars\", function (config) {\n            return CodeMirror.multiplexingMode(\n                CodeMirror.getMode(config, \"text/html\"),\n                {\n                    open: \"{{\",\n                    close: \"}}\",\n                    mode: CodeMirror.getMode(config, \"handlebars\"),\n                    parseDelimiters: true\n                }\n            );\n        });\n        CodeMirror.defineMIME(\"text/x-handlebars-template\", \"htmlhandlebars\");\n\n        LanguageManager.defineLanguage(\"handlebars\", {\n            name: \"Handlebars\",\n            mode: [\"htmlhandlebars\", \"text/x-handlebars-template\"],\n            fileExtensions: [\"hbs\", \"handlebars\"],\n            blockComment: [\"{{!\", \"}}\"]\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/HealthDataManager.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global define, $, brackets, console, appshell */\ndefine(function (require, exports, module) {\n    \"use strict\";\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CommandManager      = brackets.getModule(\"command/CommandManager\"),\n        HealthLogger        = brackets.getModule(\"utils/HealthLogger\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        UrlParams           = brackets.getModule(\"utils/UrlParams\").UrlParams,\n        Strings             = brackets.getModule(\"strings\"),\n        HealthDataUtils     = require(\"HealthDataUtils\"),\n        uuid                = require(\"thirdparty/uuid\"),\n        prefs               = PreferencesManager.getExtensionPrefs(\"healthData\"),\n        params              = new UrlParams(),\n        ONE_MINUTE          = 60 * 1000,\n        ONE_DAY             = 24 * 60 * ONE_MINUTE,\n        FIRST_LAUNCH_SEND_DELAY = 30 * ONE_MINUTE,\n        timeoutVar;\n\n    prefs.definePreference(\"healthDataTracking\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_HEALTH_DATA_TRACKING\n    });\n\n    params.parse();\n\n    /**\n     * Get the Health Data which will be sent to the server. Initially it is only one time data.\n     */\n    function getHealthData() {\n        var result = new $.Deferred(),\n            oneTimeHealthData = {};\n\n        oneTimeHealthData.snapshotTime = Date.now();\n        oneTimeHealthData.os = brackets.platform;\n        oneTimeHealthData.userAgent = window.navigator.userAgent;\n        oneTimeHealthData.osLanguage = brackets.app.language;\n        oneTimeHealthData.bracketsLanguage = brackets.getLocale();\n        oneTimeHealthData.bracketsVersion = brackets.metadata.version;\n        $.extend(oneTimeHealthData, HealthLogger.getAggregatedHealthData());\n        HealthDataUtils.getUserInstalledExtensions()\n            .done(function (userInstalledExtensions) {\n                oneTimeHealthData.installedExtensions = userInstalledExtensions;\n            })\n            .always(function () {\n                HealthDataUtils.getUserInstalledTheme()\n                    .done(function (bracketsTheme) {\n                        oneTimeHealthData.bracketsTheme = bracketsTheme;\n                    })\n                    .always(function () {\n                        var userUuid  = PreferencesManager.getViewState(\"UUID\");\n                        var olderUuid = PreferencesManager.getViewState(\"OlderUUID\");\n\n                        if (userUuid && olderUuid) {\n                            oneTimeHealthData.uuid      = userUuid;\n                            oneTimeHealthData.olderuuid = olderUuid;\n                            return result.resolve(oneTimeHealthData);\n                        } else {\n\n                            // So we are going to get the Machine hash in either of the cases.\n                            if (appshell.app.getMachineHash) {\n                                appshell.app.getMachineHash(function (err, macHash) {\n\n                                    var generatedUuid;\n                                    if (err) {\n                                        generatedUuid = uuid.v4();\n                                    } else {\n                                        generatedUuid = macHash;\n                                    }\n\n                                    if (!userUuid) {\n                                        // Could be a new user. In this case\n                                        // both will remain the same.\n                                        userUuid = olderUuid = generatedUuid;\n                                    } else {\n                                        // For existing user, we will still cache\n                                        // the older uuid, so that we can improve\n                                        // our reporting in terms of figuring out\n                                        // the new users accurately.\n                                        olderUuid = userUuid;\n                                        userUuid  = generatedUuid;\n                                    }\n\n                                    PreferencesManager.setViewState(\"UUID\", userUuid);\n                                    PreferencesManager.setViewState(\"OlderUUID\", olderUuid);\n\n                                    oneTimeHealthData.uuid      = userUuid;\n                                    oneTimeHealthData.olderuuid = olderUuid;\n                                    return result.resolve(oneTimeHealthData);\n                                });\n                            } else {\n                                // Probably running on older shell, in which case we will\n                                // assign the same uuid to olderuuid.\n                                if (!userUuid) {\n                                    oneTimeHealthData.uuid = oneTimeHealthData.olderuuid = uuid.v4();\n                                } else {\n                                    oneTimeHealthData.olderuuid = userUuid;\n                                }\n\n                                PreferencesManager.setViewState(\"UUID\",      oneTimeHealthData.uuid);\n                                PreferencesManager.setViewState(\"OlderUUID\", oneTimeHealthData.olderuuid);\n                                return result.resolve(oneTimeHealthData);\n                            }\n                        }\n                    });\n\n            });\n        return result.promise();\n    }\n\n    /**\n     *@param{Object} eventParams contails Event Data\n     * will return complete Analyics Data in Json Format\n     */\n    function getAnalyticsData(eventParams) {\n        var userUuid = PreferencesManager.getViewState(\"UUID\"),\n            olderUuid = PreferencesManager.getViewState(\"OlderUUID\");\n\n        //Create default Values\n        var defaultEventParams = {\n            eventCategory: \"pingData\",\n            eventSubCategory: \"\",\n            eventType: \"\",\n            eventSubType: \"\"\n        };\n        //Override with default values if not present\n        if (!eventParams) {\n            eventParams = defaultEventParams;\n        } else {\n            var e;\n            for (e in defaultEventParams) {\n                if (defaultEventParams.hasOwnProperty(e) && !eventParams[e]) {\n                    eventParams[e] = defaultEventParams[e];\n                }\n            }\n        }\n\n        return {\n            project: brackets.config.serviceKey,\n            environment: brackets.config.environment,\n            time: new Date().toISOString(),\n            ingesttype: \"dunamis\",\n            data: {\n                \"event.guid\": uuid.v4(),\n                \"event.user_guid\": olderUuid || userUuid,\n                \"event.dts_end\": new Date().toISOString(),\n                \"event.category\": eventParams.eventCategory,\n                \"event.subcategory\": eventParams.eventSubCategory,\n                \"event.type\": eventParams.eventType,\n                \"event.subtype\": eventParams.eventSubType,\n                \"event.user_agent\": window.navigator.userAgent || \"\",\n                \"event.language\": brackets.app.language,\n                \"source.name\": brackets.metadata.version,\n                \"source.platform\": brackets.platform,\n                \"source.version\": brackets.metadata.version\n            }\n        };\n    }\n\n    /**\n     * Send data to the server\n     */\n    function sendHealthDataToServer() {\n        var result = new $.Deferred();\n\n        getHealthData().done(function (healthData) {\n\n            var url = brackets.config.healthDataServerURL,\n                data = JSON.stringify(healthData);\n\n            $.ajax({\n                url: url,\n                type: \"POST\",\n                data: data,\n                dataType: \"text\",\n                contentType: \"text/plain\"\n            })\n                .done(function () {\n                    result.resolve();\n                })\n                .fail(function (jqXHR, status, errorThrown) {\n                    console.error(\"Error in sending Health Data. Response : \" + jqXHR.responseText + \". Status : \" + status + \". Error : \" + errorThrown);\n                    result.reject();\n                });\n        })\n            .fail(function () {\n                result.reject();\n            });\n\n        return result.promise();\n    }\n\n    // Send Analytics data to Server\n    function sendAnalyticsDataToServer(eventParams) {\n        var result = new $.Deferred();\n\n        var analyticsData = getAnalyticsData(eventParams);\n        $.ajax({\n            url: brackets.config.analyticsDataServerURL,\n            type: \"POST\",\n            data: JSON.stringify({events: [analyticsData]}),\n            headers: {\n                \"Content-Type\": \"application/json\",\n                \"x-api-key\": brackets.config.serviceKey\n            }\n        })\n            .done(function () {\n                result.resolve();\n            })\n            .fail(function (jqXHR, status, errorThrown) {\n                console.error(\"Error in sending Adobe Analytics Data. Response : \" + jqXHR.responseText + \". Status : \" + status + \". Error : \" + errorThrown);\n                result.reject();\n            });\n\n        return result.promise();\n    }\n\n    /*\n     * Check if the Health Data is to be sent to the server. If the user has enabled tracking, Health Data will be sent once every 24 hours.\n     * Send Health Data to the server if the period is more than 24 hours.\n     * We are sending the data as soon as the user launches brackets. The data will be sent to the server only after the notification dialog\n     * for opt-out/in is closed.\n     @param forceSend Flag for sending analytics data for testing purpose\n     */\n    function checkHealthDataSend(forceSend) {\n        var result         = new $.Deferred(),\n            isHDTracking   = prefs.get(\"healthDataTracking\"),\n            nextTimeToSend,\n            currentTime;\n\n        HealthLogger.setHealthLogsEnabled(isHDTracking);\n        window.clearTimeout(timeoutVar);\n        if (isHDTracking) {\n            nextTimeToSend = PreferencesManager.getViewState(\"nextHealthDataSendTime\");\n            currentTime    = Date.now();\n\n            // Never send data before FIRST_LAUNCH_SEND_DELAY has ellapsed on a fresh install. This gives the user time to read the notification\n            // popup, learn more, and opt out if desired\n            if (!nextTimeToSend) {\n                nextTimeToSend = currentTime + FIRST_LAUNCH_SEND_DELAY;\n                PreferencesManager.setViewState(\"nextHealthDataSendTime\", nextTimeToSend);\n                // don't return yet though - still want to set the timeout below\n            }\n\n            if (currentTime >= nextTimeToSend || forceSend) {\n                // Bump up nextHealthDataSendTime at the begining of chaining to avoid any chance of sending data again before 24 hours, // e.g. if the server request fails or the code below crashes\n                PreferencesManager.setViewState(\"nextHealthDataSendTime\", currentTime + ONE_DAY);\n                sendHealthDataToServer().always(function() {\n                    sendAnalyticsDataToServer()\n                    .done(function () {\n                        // We have already sent the health data, so can clear all health data\n                        // Logged till now\n                        HealthLogger.clearHealthData();\n                        result.resolve();\n                    })\n                    .fail(function () {\n                        result.reject();\n                    })\n                    .always(function () {\n                        timeoutVar = setTimeout(checkHealthDataSend, ONE_DAY);\n                    });\n                });\n            } else {\n                timeoutVar = setTimeout(checkHealthDataSend, nextTimeToSend - currentTime);\n                result.reject();\n            }\n        } else {\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * Check if the Analytic Data is to be sent to the server.\n     * If the user has enabled tracking, Analytic Data will be sent once per session\n     * Send Analytic Data to the server if the Data associated with the given Event is not yet sent in this session.\n     * We are sending the data as soon as the user triggers the event.\n     * The data will be sent to the server only after the notification dialog\n     * for opt-out/in is closed.\n     * @param{Object} event event object\n     * @param{Object} Eventparams Object Containg Data to be sent to Server\n     * @param{boolean} forceSend Flag for sending analytics data for testing purpose\n     **/\n    function checkAnalyticsDataSend(event, Eventparams, forceSend) {\n        var result         = new $.Deferred(),\n            isHDTracking   = prefs.get(\"healthDataTracking\"),\n            isEventDataAlreadySent;\n\n        if (isHDTracking) {\n            isEventDataAlreadySent = HealthLogger.analyticsEventMap.get(Eventparams.eventName);\n            HealthLogger.analyticsEventMap.set(Eventparams.eventName, true);\n            if (!isEventDataAlreadySent || forceSend) {\n                sendAnalyticsDataToServer(Eventparams)\n                    .done(function () {\n                        HealthLogger.analyticsEventMap.set(Eventparams.eventName, true);\n                        result.resolve();\n                    }).fail(function () {\n                        HealthLogger.analyticsEventMap.set(Eventparams.eventName, false);\n                        result.reject();\n                    });\n            } else {\n                result.reject();\n            }\n        } else {\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * This function is auto called after 24 hours to empty the map\n     * Map is used to make sure that we send an event only once per 24 hours\n     **/\n\n    function emptyAnalyticsMap() {\n        HealthLogger.analyticsEventMap.clear();\n        setTimeout(emptyAnalyticsMap, ONE_DAY);\n    }\n    setTimeout(emptyAnalyticsMap, ONE_DAY);\n\n    // Expose a command to test data sending capability, but limit it to dev environment only\n    CommandManager.register(\"Sends health data and Analytics data for testing purpose\", \"sendHealthData\", function() {\n        if (brackets.config.environment === \"stage\") {\n            return checkHealthDataSend(true);\n        } else {\n            return $.Deferred().reject().promise();\n        }\n    });\n\n    prefs.on(\"change\", \"healthDataTracking\", function () {\n        checkHealthDataSend();\n    });\n\n    HealthLogger.on(\"SendAnalyticsData\", checkAnalyticsDataSend);\n\n    window.addEventListener(\"online\", function () {\n        checkHealthDataSend();\n    });\n\n    window.addEventListener(\"offline\", function () {\n        window.clearTimeout(timeoutVar);\n    });\n\n    AppInit.appReady(function () {\n        checkHealthDataSend();\n    });\n\n    exports.getHealthData = getHealthData;\n    exports.getAnalyticsData = getAnalyticsData;\n    exports.checkHealthDataSend = checkHealthDataSend;\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/HealthDataNotification.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit                      = brackets.getModule(\"utils/AppInit\"),\n        PreferencesManager           = brackets.getModule(\"preferences/PreferencesManager\"),\n        UrlParams                    = brackets.getModule(\"utils/UrlParams\").UrlParams,\n        HealthDataPreview            = require(\"HealthDataPreview\"),\n        HealthDataPopup              = require(\"HealthDataPopup\");\n\n    // Parse URL params\n    var params = new UrlParams();\n\n    function handleHealthDataStatistics() {\n        HealthDataPreview.previewHealthData();\n    }\n\n    AppInit.appReady(function () {\n        params.parse();\n        // Check whether the notification dialog should be shown. It will be shown one time. Does not check in testing environment.\n        if (!params.get(\"testEnvironment\")) {\n            var alreadyShown = PreferencesManager.getViewState(\"healthDataNotificationShown\");\n            var prefs = PreferencesManager.getExtensionPrefs(\"healthData\");\n            if (!alreadyShown && prefs.get(\"healthDataTracking\")) {\n                HealthDataPopup.showFirstLaunchTooltip()\n                    .done(function () {\n                        PreferencesManager.setViewState(\"healthDataNotificationShown\", true);\n                    });\n            }\n        }\n    });\n\n\n    exports.handleHealthDataStatistics       = handleHealthDataStatistics;\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/HealthDataPopup.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var MainViewManager             = brackets.getModule(\"view/MainViewManager\"),\n        Dialogs                     = brackets.getModule(\"widgets/Dialogs\"),\n        Strings                     = brackets.getModule(\"strings\"),\n        Mustache                    = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        HealthDataNotificationHtml  = require(\"text!htmlContent/healthdata-popup.html\");\n\n    function closeCallout() {\n        var $callout = $(\"#healthdata-firstlaunch-popup\");\n\n        if (!$callout.hasClass(\"animateOpen\")) {\n            return;\n        }\n\n        // Animate out\n        $callout.removeClass(\"animateOpen\");\n        $callout\n            .addClass(\"animateClose\")\n            .one(\"webkitTransitionEnd\", function () {\n                // Normally we'd use AnimationUtils for this, but due to an apparent Chrome bug, calling .is(\":hidden\")\n                // causes the animation not to play (even though it returns false and that early-exit branch isn't taken).\n                $callout.removeClass(\"animateClose\");\n                $callout.remove();\n            });\n    }\n\n    function showFirstLaunchTooltip() {\n        var TOP_MARGIN = 7,\n            popupTop = $(\"#editor-holder\").offset().top + TOP_MARGIN,\n            result = new $.Deferred(),\n            $firstLaunchPopup = $(Mustache.render(HealthDataNotificationHtml, {\"Strings\": Strings}));\n\n        Dialogs.addLinkTooltips($firstLaunchPopup);\n\n        $firstLaunchPopup.appendTo(\"body\").hide()\n                         .css(\"top\", popupTop)\n                         .find(\".healthdata-popup-close-button\").click(function () {\n                closeCallout();\n                MainViewManager.focusActivePane();\n                result.resolve();\n            });\n        $firstLaunchPopup.show();\n\n        // Animate in\n        // Must wait a cycle for the \"display: none\" to drop out before CSS transitions will work\n        setTimeout(function () {\n            $(\"#healthdata-firstlaunch-popup\").addClass(\"animateOpen\");\n        }, 0);\n\n        return result.promise();\n    }\n\n    exports.showFirstLaunchTooltip          = showFirstLaunchTooltip;\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/HealthDataPreview.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                       = brackets.getModule(\"thirdparty/lodash\"),\n        Mustache                = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        PreferencesManager      = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        Dialogs                 = brackets.getModule(\"widgets/Dialogs\"),\n        ExtensionUtils          = brackets.getModule(\"utils/ExtensionUtils\"),\n\n        HealthDataPreviewDialog = require(\"text!htmlContent/healthdata-preview-dialog.html\"),\n        HealthDataManager       = require(\"HealthDataManager\");\n\n    var prefs = PreferencesManager.getExtensionPrefs(\"healthData\");\n\n    ExtensionUtils.loadStyleSheet(module, \"styles.css\");\n\n    /**\n     * Show the dialog for previewing the Health Data that will be sent.\n     */\n    function previewHealthData() {\n        var result = new $.Deferred();\n\n        HealthDataManager.getHealthData().done(function (healthDataObject) {\n            var combinedHealthAnalyticsData = HealthDataManager.getAnalyticsData(),\n                content;\n            combinedHealthAnalyticsData = [healthDataObject, combinedHealthAnalyticsData ];\n            content = JSON.stringify(combinedHealthAnalyticsData, null, 4);\n            content = _.escape(content);\n            content = content.replace(/ /g, \"&nbsp;\");\n            content = content.replace(/(?:\\r\\n|\\r|\\n)/g, \"<br />\");\n\n            var hdPref   = prefs.get(\"healthDataTracking\"),\n                template = Mustache.render(HealthDataPreviewDialog, {Strings: Strings, content: content, hdPref: hdPref}),\n                $template = $(template);\n\n            Dialogs.addLinkTooltips($template);\n\n            Dialogs.showModalDialogUsingTemplate($template).done(function (id) {\n\n                if (id === \"save\") {\n                    var newHDPref = $template.find(\"[data-target]:checkbox\").is(\":checked\");\n                    if (hdPref !== newHDPref) {\n                        prefs.set(\"healthDataTracking\", newHDPref);\n                    }\n                }\n            });\n\n            return result.resolve();\n        });\n\n        return result.promise();\n    }\n\n    exports.previewHealthData = previewHealthData;\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/HealthDataUtils.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                   = brackets.getModule(\"thirdparty/lodash\"),\n        ExtensionManager    = brackets.getModule(\"extensibility/ExtensionManager\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\");\n\n    var themesPref          = PreferencesManager.getExtensionPrefs(\"themes\");\n\n\n    /**\n     * @private\n     * Check for the extensions whether it is user installed and present in the registry.\n     * @param {Object} extensions synchronized with registry object\n     * return {Array} userInstalledExtensions\n    */\n    function getUserExtensionsPresentInRegistry(extensions) {\n        var userInstalledExtensions = [];\n        _.forEach(extensions, function (extension, extensionId) {\n            if (extension && extension.installInfo && extension.installInfo.locationType === ExtensionManager.LOCATION_USER && extension.registryInfo) {\n                userInstalledExtensions.push({\"name\" : extensionId, \"version\" : extension.installInfo.metadata.version});\n            }\n        });\n\n        return userInstalledExtensions;\n    }\n    /**\n     * Utility function to get the user installed extension which are present in the registry\n     */\n    function getUserInstalledExtensions() {\n        var result = new $.Deferred();\n\n        if (!ExtensionManager.hasDownloadedRegistry) {\n            ExtensionManager.downloadRegistry().done(function () {\n                result.resolve(getUserExtensionsPresentInRegistry(ExtensionManager.extensions));\n            })\n                .fail(function () {\n                    result.resolve([]);\n                });\n        } else {\n            result.resolve(getUserExtensionsPresentInRegistry(ExtensionManager.extensions));\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * Utility function to get the user installed theme which are present in the registry\n     */\n    function getUserInstalledTheme() {\n        var result = new $.Deferred();\n\n        var installedTheme = themesPref.get(\"theme\"),\n            bracketsTheme;\n\n        if (installedTheme === \"light-theme\" || installedTheme === \"dark-theme\") {\n            return result.resolve(installedTheme);\n        }\n\n        if (!ExtensionManager.hasDownloadedRegistry) {\n            ExtensionManager.downloadRegistry().done(function () {\n                bracketsTheme = ExtensionManager.extensions[installedTheme];\n                if (bracketsTheme && bracketsTheme.installInfo && bracketsTheme.installInfo.locationType === ExtensionManager.LOCATION_USER && bracketsTheme.registryInfo) {\n                    result.resolve(installedTheme);\n                } else {\n                    result.reject();\n                }\n            })\n                .fail(function () {\n                    result.reject();\n                });\n        } else {\n            bracketsTheme = ExtensionManager.extensions[installedTheme];\n            if (bracketsTheme && bracketsTheme.installInfo && bracketsTheme.installInfo.locationType === ExtensionManager.LOCATION_USER && bracketsTheme.registryInfo) {\n                result.resolve(installedTheme);\n            } else {\n                result.reject();\n            }\n        }\n\n        return result.promise();\n    }\n\n    exports.getUserInstalledExtensions      = getUserInstalledExtensions;\n    exports.getUserInstalledTheme           = getUserInstalledTheme;\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/htmlContent/healthdata-popup.html",
    "content": "<div id=\"healthdata-firstlaunch-popup\" class=\"healthdata-firstlaunch-container\">\n    <div>\n        <p class='healthdata-popup-close-button'>×</p>\n    </div>\n    <div >\n        <p class=\"healthdata-dialog-title\">{{Strings.HEALTH_FIRST_POPUP_TITLE}}</p>\n    </div>\n    <div>\n        <p class=\"healthdata-dialog-message\">{{{Strings.HEALTH_DATA_NOTIFICATION_MESSAGE}}}</p>\n    </div>\n</div>\n\n"
  },
  {
    "path": "src/extensions/default/HealthData/htmlContent/healthdata-preview-dialog.html",
    "content": "<div class=\"health-data-preview modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{Strings.HEALTH_DATA_PREVIEW}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        <div class=\"dialog-message\">{{{Strings.HEALTH_DATA_PREVIEW_INTRO}}}</div>\n\t\t<div class=\"dialog-message\">\n\t\t\t<label>\n\t            <input type=\"checkbox\" data-target=\"hdPref\" {{#hdPref}}checked{{/hdPref}} />\n\t            {{Strings.HEALTH_DATA_DO_TRACK}}\n\t        </label>\n    \t</div>\n\t    <div class=\"dialog-message preview-content-container\">\n\t        <p class=\"preview-content\">{{{content}}}</p>\n\t    </div>\n\t</div>\n    <div class=\"modal-footer\">\n         <button class=\"dialog-button btn\" data-button-id=\"cancel\">{{Strings.CANCEL}}</button>\n        <button class=\"dialog-button btn primary\" data-button-id=\"save\">{{Strings.DONE}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/HealthData/main.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit                 = brackets.getModule(\"utils/AppInit\"),\n        HealthLogger            = brackets.getModule(\"utils/HealthLogger\"),\n        Menus                   = brackets.getModule(\"command/Menus\"),\n        CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        Commands                = brackets.getModule(\"command/Commands\"),\n        PreferencesManager      = brackets.getModule(\"preferences/PreferencesManager\"),\n\n        HealthDataNotification  = require(\"HealthDataNotification\"),  // self-initializes to show first-launch notification\n        HealthDataManager       = require(\"HealthDataManager\"),  // self-initializes timer to send data\n        HealthDataPopup         = require(\"HealthDataPopup\");\n\n    var menu            = Menus.getMenu(Menus.AppMenuBar.HELP_MENU),\n        healthDataCmdId = \"healthData.healthDataStatistics\";\n\n    // Handles the command execution for Health Data menu item\n    function handleHealthDataStatistics() {\n        HealthDataNotification.handleHealthDataStatistics();\n    }\n\n    // Register the command and add the menu item for the Health Data Statistics\n    function addCommand() {\n        CommandManager.register(Strings.CMD_HEALTH_DATA_STATISTICS, healthDataCmdId, handleHealthDataStatistics);\n\n        menu.addMenuItem(healthDataCmdId, \"\", Menus.AFTER, Commands.HELP_SHOW_EXT_FOLDER);\n        menu.addMenuDivider(Menus.AFTER, Commands.HELP_SHOW_EXT_FOLDER);\n    }\n\n    function initTest() {\n        brackets.test.HealthDataPreview      = require(\"HealthDataPreview\");\n        brackets.test.HealthDataManager      = HealthDataManager;\n        brackets.test.HealthDataNotification = HealthDataNotification;\n        brackets.test.HealthDataPopup        = HealthDataPopup;\n\n        var prefs = PreferencesManager.getExtensionPrefs(\"healthData\");\n        HealthLogger.setHealthLogsEnabled(prefs.get(\"healthDataTracking\"));\n    }\n\n    AppInit.appReady(function () {\n        initTest();\n        HealthLogger.init();\n    });\n\n    addCommand();\n\n});\n"
  },
  {
    "path": "src/extensions/default/HealthData/styles.css",
    "content": "/* Dialog in the Help menu */\n\n.health-data-preview .modal-body {\n    max-height: none;\n}\n\n.health-data-preview .preview-content-container {\n    max-height: 300px;\n    overflow: auto;\n    background-color: #f0f0f0;\n    color: #0f0f0f;\n    border-radius: 3px;\n    padding: 8px;\n    margin-bottom: 0;\n}\n\n.health-data-preview input[type=\"checkbox\"] {\n    vertical-align: bottom;\n}\n\n.health-data-preview .preview-content {\n    -webkit-user-select: text;\n    cursor: text;\n}\n\n\n/* Notification popup seen on first launch */\n\n.healthdata-firstlaunch-container {\n    border-radius: 3px;\n    background: #005f8f;\n    box-shadow: 0 0 20px rgba(0, 0, 0, 0.24);\n\n    position: absolute;\n    padding: 9px 12px 9px 12px;\n    z-index: 100;\n\n    font-family: \"SourceSansPro\";\n    color: #eee;\n    line-height: 1.5;\n\n    /* animated properties */\n    opacity: 0;\n    transform: translateY(-50px);\n}\n\n#healthdata-firstlaunch-popup {\n    max-width: 250px;\n    right: 39px;\n}\n\n.healthdata-firstlaunch-container.animateOpen {\n    opacity: 1;\n    transition: transform 500ms, opacity 500ms;\n    transition-delay: 2s;\n    transform: translateY(0);\n}\n\n.healthdata-firstlaunch-container.animateClose {\n    transition: transform 500ms, opacity 500ms;\n}\n\n#healthdata-firstlaunch-popup p {\n    margin-bottom: 5px;\n}\n\n.healthdata-popup-close-button {\n    font-size: 16px;\n    font-weight: 900;\n    position: absolute;\n    top: 0;\n    right: 8px;\n    cursor: pointer;\n}\n.healthdata-popup-close-button:hover {\n    color: white;\n}\n\n.healthdata-dialog-title {\n    font-size: 16px;\n    font-weight: bold;\n    color: #ddd;\n}\n\n.healthdata-dialog-message strong {\n    color: white;\n}\n\n.healthdata-dialog-message a {\n    color: #00ccff;\n}"
  },
  {
    "path": "src/extensions/default/HealthData/thirdparty/uuid.js",
    "content": "//     uuid.js\n//\n//     Copyright (c) 2010-2012 Robert Kieffer\n//     MIT License - http://opensource.org/licenses/mit-license.php\n\n(function() {\n  var _global = this;\n\n  // Unique ID creation requires a high quality random # generator.  We feature\n  // detect to determine the best RNG source, normalizing to a function that\n  // returns 128-bits of randomness, since that's what's usually required\n  var _rng;\n\n  // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html\n  //\n  // Moderately fast, high quality\n  if (typeof(_global.require) == 'function') {\n    try {\n      var _rb = _global.require('crypto').randomBytes;\n      _rng = _rb && function() {return _rb(16);};\n    } catch(e) {}\n  }\n\n  if (!_rng && _global.crypto && crypto.getRandomValues) {\n    // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto\n    //\n    // Moderately fast, high quality\n    var _rnds8 = new Uint8Array(16);\n    _rng = function whatwgRNG() {\n      crypto.getRandomValues(_rnds8);\n      return _rnds8;\n    };\n  }\n\n  if (!_rng) {\n    // Math.random()-based (RNG)\n    //\n    // If all else fails, use Math.random().  It's fast, but is of unspecified\n    // quality.\n    var  _rnds = new Array(16);\n    _rng = function() {\n      for (var i = 0, r; i < 16; i++) {\n        if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n        _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n      }\n\n      return _rnds;\n    };\n  }\n\n  // Buffer class to use\n  var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array;\n\n  // Maps for number <-> hex string conversion\n  var _byteToHex = [];\n  var _hexToByte = {};\n  for (var i = 0; i < 256; i++) {\n    _byteToHex[i] = (i + 0x100).toString(16).substr(1);\n    _hexToByte[_byteToHex[i]] = i;\n  }\n\n  // **`parse()` - Parse a UUID into it's component bytes**\n  function parse(s, buf, offset) {\n    var i = (buf && offset) || 0, ii = 0;\n\n    buf = buf || [];\n    s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {\n      if (ii < 16) { // Don't overflow!\n        buf[i + ii++] = _hexToByte[oct];\n      }\n    });\n\n    // Zero out remaining bytes if string was short\n    while (ii < 16) {\n      buf[i + ii++] = 0;\n    }\n\n    return buf;\n  }\n\n  // **`unparse()` - Convert UUID byte array (ala parse()) into a string**\n  function unparse(buf, offset) {\n    var i = offset || 0, bth = _byteToHex;\n    return  bth[buf[i++]] + bth[buf[i++]] +\n            bth[buf[i++]] + bth[buf[i++]] + '-' +\n            bth[buf[i++]] + bth[buf[i++]] + '-' +\n            bth[buf[i++]] + bth[buf[i++]] + '-' +\n            bth[buf[i++]] + bth[buf[i++]] + '-' +\n            bth[buf[i++]] + bth[buf[i++]] +\n            bth[buf[i++]] + bth[buf[i++]] +\n            bth[buf[i++]] + bth[buf[i++]];\n  }\n\n  // **`v1()` - Generate time-based UUID**\n  //\n  // Inspired by https://github.com/LiosK/UUID.js\n  // and http://docs.python.org/library/uuid.html\n\n  // random #'s we need to init node and clockseq\n  var _seedBytes = _rng();\n\n  // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n  var _nodeId = [\n    _seedBytes[0] | 0x01,\n    _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]\n  ];\n\n  // Per 4.2.2, randomize (14 bit) clockseq\n  var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;\n\n  // Previous uuid creation time\n  var _lastMSecs = 0, _lastNSecs = 0;\n\n  // See https://github.com/broofa/node-uuid for API details\n  function v1(options, buf, offset) {\n    var i = buf && offset || 0;\n    var b = buf || [];\n\n    options = options || {};\n\n    var clockseq = options.clockseq != null ? options.clockseq : _clockseq;\n\n    // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n    // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so\n    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n    var msecs = options.msecs != null ? options.msecs : new Date().getTime();\n\n    // Per 4.2.1.2, use count of uuid's generated during the current clock\n    // cycle to simulate higher resolution clock\n    var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;\n\n    // Time since last uuid creation (in msecs)\n    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\n    // Per 4.2.1.2, Bump clockseq on clock regression\n    if (dt < 0 && options.clockseq == null) {\n      clockseq = clockseq + 1 & 0x3fff;\n    }\n\n    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n    // time interval\n    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {\n      nsecs = 0;\n    }\n\n    // Per 4.2.1.2 Throw error if too many uuids are requested\n    if (nsecs >= 10000) {\n      throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n    }\n\n    _lastMSecs = msecs;\n    _lastNSecs = nsecs;\n    _clockseq = clockseq;\n\n    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n    msecs += 12219292800000;\n\n    // `time_low`\n    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n    b[i++] = tl >>> 24 & 0xff;\n    b[i++] = tl >>> 16 & 0xff;\n    b[i++] = tl >>> 8 & 0xff;\n    b[i++] = tl & 0xff;\n\n    // `time_mid`\n    var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n    b[i++] = tmh >>> 8 & 0xff;\n    b[i++] = tmh & 0xff;\n\n    // `time_high_and_version`\n    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n    b[i++] = tmh >>> 16 & 0xff;\n\n    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n    b[i++] = clockseq >>> 8 | 0x80;\n\n    // `clock_seq_low`\n    b[i++] = clockseq & 0xff;\n\n    // `node`\n    var node = options.node || _nodeId;\n    for (var n = 0; n < 6; n++) {\n      b[i + n] = node[n];\n    }\n\n    return buf ? buf : unparse(b);\n  }\n\n  // **`v4()` - Generate random UUID**\n\n  // See https://github.com/broofa/node-uuid for API details\n  function v4(options, buf, offset) {\n    // Deprecated - 'format' argument, as supported in v1.2\n    var i = buf && offset || 0;\n\n    if (typeof(options) == 'string') {\n      buf = options == 'binary' ? new BufferClass(16) : null;\n      options = null;\n    }\n    options = options || {};\n\n    var rnds = options.random || (options.rng || _rng)();\n\n    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n    rnds[6] = (rnds[6] & 0x0f) | 0x40;\n    rnds[8] = (rnds[8] & 0x3f) | 0x80;\n\n    // Copy bytes to buffer, if provided\n    if (buf) {\n      for (var ii = 0; ii < 16; ii++) {\n        buf[i + ii] = rnds[ii];\n      }\n    }\n\n    return buf || unparse(rnds);\n  }\n\n  // Export public API\n  var uuid = v4;\n  uuid.v1 = v1;\n  uuid.v4 = v4;\n  uuid.parse = parse;\n  uuid.unparse = unparse;\n  uuid.BufferClass = BufferClass;\n\n  if (typeof(module) != 'undefined' && module.exports) {\n    // Publish as node.js module\n    module.exports = uuid;\n  } else  if (typeof define === 'function' && define.amd) {\n    // Publish as AMD module\n    define(function() {return uuid;});\n \n\n  } else {\n    // Publish as global (in browsers)\n    var _previousRoot = _global.uuid;\n\n    // **`noConflict()` - (browser only) to reset global 'uuid' var**\n    uuid.noConflict = function() {\n      _global.uuid = _previousRoot;\n      return uuid;\n    };\n\n    _global.uuid = uuid;\n  }\n}).call(this);"
  },
  {
    "path": "src/extensions/default/HealthData/unittests.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, runs, beforeEach, it, afterEach, expect, waitsForDone, waitsForFail */\n/*unittests: HealthData*/\n\ndefine(function (require, exports, module) {\n    'use strict';\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\");\n\n    var testWindow,\n        PreferencesManager;\n\n    describe(\"HealthData\", function () {\n\n        beforeEach(function () {\n            SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                testWindow = w;\n            });\n\n        });\n\n        afterEach(function () {\n            SpecRunnerUtils.closeTestWindow();\n            testWindow = null;\n        });\n\n\n        describe(\"Data Send to Server\", function () {\n            var ONE_DAY = 24 * 60 * 60 * 1000,\n                FIRST_LAUNCH_SEND_DELAY = 30 * 60 * 1000,\n                prefs,\n                HealthDataManager;\n\n            beforeEach(function () {\n                PreferencesManager = testWindow.brackets.test.PreferencesManager;\n                prefs = PreferencesManager.getExtensionPrefs(\"healthData\");\n                HealthDataManager = testWindow.brackets.test.HealthDataManager;\n\n                this.addMatchers({\n                    // Oddly, Jasmine has expect().toBeGreaterThan() built in, but not greater-or-equal\n                    toBeGreaterOrEqualTo: function (expected) {\n                        this.message = function () {\n                            return \"Expected \" + this.actual + \" to be >= \" + expected;\n                        };\n                        return this.actual >= expected;\n                    }\n                });\n            });\n\n            afterEach(function () {\n                HealthDataManager = null;\n                prefs = null;\n                PreferencesManager = null;\n            });\n\n            it(\"should send data to server when opted in\", function () {\n                var baseTime = Date.now();\n                PreferencesManager.setViewState(\"nextHealthDataSendTime\", baseTime);\n                PreferencesManager.setViewState(\"healthDataNotificationShown\", true);\n                var promise = HealthDataManager.checkHealthDataSend();\n                waitsForDone(promise, \"Send Data to Server\", 4000);\n                expect(PreferencesManager.getViewState(\"nextHealthDataSendTime\")).toBeGreaterOrEqualTo(baseTime + ONE_DAY);\n            });\n\n            it(\"should not send data right away on first launch\", function () {\n                var baseTime = Date.now();\n                PreferencesManager.setViewState(\"nextHealthDataSendTime\", null);\n                PreferencesManager.setViewState(\"healthDataNotificationShown\", true);\n                var promise = HealthDataManager.checkHealthDataSend();\n                waitsForFail(promise, \"Send Data to Server\", 4000);\n                expect(PreferencesManager.getViewState(\"nextHealthDataSendTime\")).toBeGreaterOrEqualTo(baseTime + FIRST_LAUNCH_SEND_DELAY);\n            });\n\n            it(\"should not send data to server when opted out\", function () {\n                PreferencesManager.setViewState(\"nextHealthDataSendTime\", Date.now());\n                prefs.set(\"healthDataTracking\", false);\n                var promise = HealthDataManager.checkHealthDataSend();\n                waitsForFail(promise, \"Send Data to Server\", 4000);\n            });\n\n        });\n\n        describe(\"Notification popup\", function () {\n            var HealthDataPopup;\n\n            beforeEach(function () {\n                HealthDataPopup = testWindow.brackets.test.HealthDataPopup;\n            });\n\n            afterEach(function () {\n                HealthDataPopup = null;\n            });\n\n            it(\"should show notification popup\", function () {\n                // TODO: write a test that verifies this actually shows *on a clean launch*, not just when API called...\n                HealthDataPopup.showFirstLaunchTooltip();\n                expect($(testWindow.document).find(\"#healthdata-firstlaunch-popup\").length).toBe(1);\n            });\n        });\n\n        describe(\"Health Data Statistics is displayed\", function () {\n            var HealthDataPreview;\n\n            beforeEach(function () {\n                HealthDataPreview = testWindow.brackets.test.HealthDataPreview;\n            });\n\n            afterEach(function () {\n                HealthDataPreview = null;\n            });\n\n            it(\"should show file preview dialog\", function () {\n\n                runs(function () {\n                    var promise = HealthDataPreview.previewHealthData();\n                    waitsForDone(promise, \"Health Data File Preview\", 4000);\n                });\n\n                runs(function () {\n                    expect($(testWindow.document).find(\".health-data-preview.instance\").length).toBe(1);\n                });\n\n            });\n        });\n    });\n\n});\n"
  },
  {
    "path": "src/extensions/default/HtmlEntityCodeHints/SpecialChars.json",
    "content": "[\n    \"&#33\",\n    \"&#35\",\n    \"&#36\",\n    \"&#37\",\n    \"&#39\",\n    \"&#40\",\n    \"&#41\",\n    \"&#42\",\n    \"&#43\",\n    \"&#44\",\n    \"&#45\",\n    \"&#46\",\n    \"&#58\",\n    \"&#59\",\n    \"&#61\",\n    \"&#63\",\n    \"&#64\",\n    \"&#91\",\n    \"&#92\",\n    \"&#93\",\n    \"&#94\",\n    \"&#95\",\n    \"&#96\",\n    \"&#123\",\n    \"&#124\",\n    \"&#125\",\n    \"&#126\",\n    \"&#8226\",\n    \"&#9679\",\n    \n    \"&aacute\",\n    \"&Aacute\",\n    \"&acirc\",\n    \"&Acirc\",\n    \"&acute\",\n    \"&aelig\",\n    \"&AElig\",\n    \"&agrave\",\n    \"&Agrave\",\n    \"&alefsym\",\n    \"&alpha\",\n    \"&Alpha\",\n    \"&amp\",\n    \"&and\",\n    \"&ang\",\n    \"&aring\",\n    \"&Aring\",\n    \"&asymp\",\n    \"&atilde\",\n    \"&Atilde\",\n    \"&auml\",\n    \"&Auml\",\n    \"&bdquo\",\n    \"&beta\",\n    \"&Beta\",\n    \"&brvbar\",\n    \"&bull\",\n    \"&cap\",\n    \"&ccedil\",\n    \"&Ccedil\",\n    \"&cedil\",\n    \"&cent\",\n    \"&chi\",\n    \"&Chi\",\n    \"&circ\",\n    \"&clubs\",\n    \"&cong\",\n    \"&copy\",\n    \"&crarr\",\n    \"&cup\",\n    \"&curren\",\n    \"&dagger\",\n    \"&Dagger\",\n    \"&darr\",\n    \"&dArr\",\n    \"&deg\",\n    \"&delta\",\n    \"&Delta\",\n    \"&diams\",\n    \"&die\",\n    \"&divide\",\n    \"&eacute\",\n    \"&Eacute\",\n    \"&ecirc\",\n    \"&Ecirc\",\n    \"&egrave\",\n    \"&Egrave\",\n    \"&empty\",\n    \"&emsp\",\n    \"&ensp\",\n    \"&epsilon\",\n    \"&Epsilon\",\n    \"&equiv\",\n    \"&eta\",\n    \"&Eta\",\n    \"&eth\",\n    \"&ETH\",\n    \"&euml\",\n    \"&Euml\",\n    \"&euro\",\n    \"&exist\",\n    \"&forall\",\n    \"&frac12\",\n    \"&frac14\",\n    \"&frac34\",\n    \"&frasl\",\n    \"&gamma\",\n    \"&Gamma\",\n    \"&ge\",\n    \"&gt\",\n    \"&harr\",\n    \"&hArr\",\n    \"&hearts\",\n    \"&hellip\",\n    \"&iacute\",\n    \"&Iacute\",\n    \"&icirc\",\n    \"&Icirc\",\n    \"&iexcl\",\n    \"&igrave\",\n    \"&Igrave\",\n    \"&image\",\n    \"&infin\",\n    \"&int\",\n    \"&iota\",\n    \"&Iota\",\n    \"&iquest\",\n    \"&isin\",\n    \"&iuml\",\n    \"&Iuml\",\n    \"&kappa\",\n    \"&Kappa\",\n    \"&lambda\",\n    \"&Lambda\",\n    \"&lang\",\n    \"&laquo\",\n    \"&larr\",\n    \"&lArr\",\n    \"&lceil\",\n    \"&ldquo\",\n    \"&le\",\n    \"&lfloor\",\n    \"&lowast\",\n    \"&loz\",\n    \"&lrm\",\n    \"&lsaquo\",\n    \"&lsquo\",\n    \"&lt\",\n    \"&macr\",\n    \"&mdash\",\n    \"&micro\",\n    \"&middot\",\n    \"&minus\",\n    \"&mu\",\n    \"&Mu\",\n    \"&nabla\",\n    \"&nbsp\",\n    \"&ndash\",\n    \"&ne\",\n    \"&ni\",\n    \"&not\",\n    \"&notin\",\n    \"&nsub\",\n    \"&ntilde\",\n    \"&Ntilde\",\n    \"&nu\",\n    \"&Nu\",\n    \"&oacute\",\n    \"&Oacute\",\n    \"&ocirc\",\n    \"&Ocirc\",\n    \"&ograve\",\n    \"&Ograve\",\n    \"&oline\",\n    \"&omega\",\n    \"&Omega\",\n    \"&omicron\",\n    \"&Omicron\",\n    \"&oplus\",\n    \"&or\",\n    \"&ordf\",\n    \"&ordm\",\n    \"&oslash\",\n    \"&Oslash\",\n    \"&otilde\",\n    \"&Otilde\",\n    \"&otimes\",\n    \"&ouml\",\n    \"&Ouml\",\n    \"&para\",\n    \"&part\",\n    \"&permil\",\n    \"&perp\",\n    \"&phi\",\n    \"&Phi\",\n    \"&pi\",\n    \"&Pi\",\n    \"&piv\",\n    \"&plusmn\",\n    \"&pound\",\n    \"&prime\",\n    \"&Prime\",\n    \"&prod\",\n    \"&prop\",\n    \"&psi\",\n    \"&Psi\",\n    \"&quot\",\n    \"&radic\",\n    \"&rang\",\n    \"&raquo\",\n    \"&rarr\",\n    \"&rArr\",\n    \"&rceil\",\n    \"&rdquo\",\n    \"&real\",\n    \"&reg\",\n    \"&rfloor\",\n    \"&rho\",\n    \"&Rho\",\n    \"&rlm\",\n    \"&rsaquo\",\n    \"&rsquo\",\n    \"&sbquo\",\n    \"&Scaron\",\n    \"&scaron\",\n    \"&sdot\",\n    \"&sect\",\n    \"&shy\",\n    \"&sigma\",\n    \"&Sigma\",\n    \"&sim\",\n    \"&spades\",\n    \"&sub\",\n    \"&sube\",\n    \"&sum\",\n    \"&sup\",\n    \"&supe\",\n    \"&sup1\",\n    \"&sup2\",\n    \"&sup3\",\n    \"&szlig\",\n    \"&tau\",\n    \"&Tau\",\n    \"&there4\",\n    \"&theta\",\n    \"&Theta\",\n    \"&thetasym\",\n    \"&thinsp\",\n    \"&thorn\",\n    \"&THORN\",\n    \"&times\",\n    \"&tilde\",\n    \"&trade\",\n    \"&uacute\",\n    \"&Uacute\",\n    \"&uarr\",\n    \"&uArr\",\n    \"&ucirc\",\n    \"&Ucirc\",\n    \"&ugrave\",\n    \"&Ugrave\",\n    \"&uml\",\n    \"&upsih\",\n    \"&upsilon\",\n    \"&Upsilon\",\n    \"&uuml\",\n    \"&Uuml\",\n    \"&weierp\",\n    \"&xi\",\n    \"&Xi\",\n    \"&yacute\",\n    \"&Yacute\",\n    \"&yen\",\n    \"&yuml\",\n    \"&zeta\",\n    \"&Zeta\",\n    \"&zwnj\"\n]"
  },
  {
    "path": "src/extensions/default/HtmlEntityCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        HTMLUtils           = brackets.getModule(\"language/HTMLUtils\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings             = brackets.getModule(\"strings\"),\n        HtmlSpecialChars    = require(\"text!SpecialChars.json\"),\n        specialChars;\n\n\n    PreferencesManager.definePreference(\"codehint.SpecialCharHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_SPECIAL_CHAR_HINTS\n    });\n\n    /**\n     * Encodes the special Char value given.\n     *\n     * @param {string} value\n     * The value to encode\n     *\n     * @return {string}\n     * The encoded string\n     */\n    function _encodeValue(value) {\n        return value.replace(\"&\", \"&amp;\").replace(\"#\", \"&#35;\");\n    }\n\n    /**\n     * Decodes the special Char value given.\n     *\n     * @param {string} value\n     * The value to decode\n     *\n     * @return {string}\n     * The decoded string\n     */\n    function _decodeValue(value) {\n        return value.replace(\"&amp;\", \"&\").replace(\"&#35;\", \"#\");\n    }\n\n    /**\n     * @constructor\n     */\n    function SpecialCharHints() {\n        this.primaryTriggerKeys = \"&ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#0123456789\";\n        this.currentQuery = \"\";\n    }\n\n    /**\n     * Determines whether HtmlSpecialChar hints are available in the current editor\n     * context.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non- null,\n     * whether it is appropriate to do so.\n     */\n    SpecialCharHints.prototype.hasHints = function (editor, implicitChar) {\n        this.editor = editor;\n\n        return this._getQuery() !== null;\n    };\n\n    /**\n     * Returns a list of available HtmlSpecialChar hints if possible for the current\n     * editor context.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {jQuery.Deferred|{\n     *              hints: Array.<string|jQueryObject>,\n     *              match: string,\n     *              selectInitial: boolean,\n     *              handleWideResults: boolean}}\n     * Null if the provider wishes to end the hinting session. Otherwise, a\n     * response object that provides:\n     * 1. a sorted array hints that consists of strings\n     * 2. a string match that is used by the manager to emphasize matching\n     *    substrings when rendering the hint list\n     * 3. a boolean that indicates whether the first result, if one exists,\n     *    should be selected by default in the hint list window.\n     * 4. handleWideResults, a boolean (or undefined) that indicates whether\n     *    to allow result string to stretch width of display.\n     */\n    SpecialCharHints.prototype.getHints = function (implicitChar) {\n        var query,\n            result;\n\n        if (implicitChar === null || this.primaryTriggerKeys.indexOf(implicitChar) !== -1) {\n            this.currentQuery = query = this._getQuery();\n            result = $.map(specialChars, function (value, index) {\n                if (value.indexOf(query) === 0) {\n                    var shownValue = _encodeValue(value);\n                    return shownValue  + \"; <span class='entity-display-character'>\" + value + \";</span>\";\n                }\n            }).sort(this._internalSort);\n\n            if (query !== null) {\n                query = _encodeValue(query);\n            }\n\n            return {\n                hints: result,\n                match: query,\n                selectInitial: true,\n                handleWideResults: false\n            };\n        }\n\n        return null;\n    };\n\n    /**\n     * Sort function used internally when sorting the Hints\n     *\n     * @param {string} value\n     * The value to decode\n     *\n     * @return {string}\n     * The decoded string\n     */\n    SpecialCharHints.prototype._internalSort = function (a, b) {\n        a = _decodeValue(a.slice(0, a.indexOf(\" \"))).toLowerCase();\n        b = _decodeValue(b.slice(0, b.indexOf(\" \"))).toLowerCase();\n\n        if (a.indexOf(\"#\") !== -1 && b.indexOf(\"#\") !== -1) {\n            var num1 = parseInt(a.slice(a.indexOf(\"#\") + 1, a.length - 1), 10),\n                num2 = parseInt(b.slice(b.indexOf(\"#\") + 1, b.length - 1), 10);\n\n            return (num1 - num2);\n        }\n\n        return a.localeCompare(b);\n    };\n\n    /**\n     * Returns a query for the Hints\n     *\n     * @return {string}\n     * The Query for which to search\n     */\n    SpecialCharHints.prototype._getQuery = function () {\n        var query,\n            lineContentBeforeCursor,\n            startChar,\n            endChar,\n            cursor = this.editor.getCursorPos();\n\n        if (HTMLUtils.getTagInfo(this.editor, cursor).tagName !== \"\") {\n            return null;\n        }\n\n        lineContentBeforeCursor = this.editor.document.getRange({\n            line: cursor.line,\n            ch: 0\n        }, cursor);\n\n        startChar = lineContentBeforeCursor.lastIndexOf(\"&\");\n        endChar = lineContentBeforeCursor.lastIndexOf(\";\");\n\n        // If no startChar was found or the endChar is greater than the startChar then it is no entity\n        if (startChar === -1 || endChar > startChar) {\n            return null;\n        }\n\n        query = this.editor.document.getRange({\n            line: cursor.line,\n            ch: startChar\n        }, cursor);\n\n        return query;\n    };\n\n    /**\n     * Inserts a given HtmlSpecialChar hint into the current editor context.\n     *\n     * @param {string} completition\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    SpecialCharHints.prototype.insertHint = function (completion) {\n        var start = {line: -1, ch: -1},\n            end = {line: -1, ch: -1},\n            cursor = this.editor.getCursorPos(),\n            line = this.editor.document.getLine(cursor.line),\n            subLine,\n            ampersandPos,\n            semicolonPos,\n            entityMatch;\n\n        end.line = start.line = cursor.line;\n        start.ch = cursor.ch - this.currentQuery.length;\n        subLine = line.slice(cursor.ch);\n        ampersandPos = subLine.indexOf(\"&\");\n        semicolonPos = subLine.indexOf(\";\");\n        end.ch = start.ch + this.currentQuery.length;\n\n        // We're looking for ';' in line before next '&'\n        if (semicolonPos !== -1 && (ampersandPos === -1 || ampersandPos > semicolonPos)) {\n\n            subLine = subLine.slice(0, semicolonPos);\n\n            // regexp must match entire subLine string\n            entityMatch = subLine.match(/^(#?[0-9]+)|([a-zA-Z]+)$/);\n            if (entityMatch && entityMatch.length > 0 && entityMatch.index === 0 &&\n                    entityMatch[0].length === subLine.length) {\n                // replace entity\n                end.ch = line.indexOf(\";\", start.ch) + 1;\n            }\n        }\n\n        completion = completion.slice(0, completion.indexOf(\" \"));\n        completion = _decodeValue(completion);\n        if (start.ch !== end.ch) {\n            this.editor.document.replaceRange(completion, start, end);\n        } else {\n            this.editor.document.replaceRange(completion, start);\n        }\n\n        return false;\n    };\n\n    AppInit.appReady(function () {\n        ExtensionUtils.loadStyleSheet(module, \"styles.css\");\n        // Parse JSON files\n        specialChars = JSON.parse(HtmlSpecialChars);\n\n        // Register code hint providers\n        var specialCharHints = new SpecialCharHints();\n\n        CodeHintManager.registerHintProvider(specialCharHints, [\"html\"], 1);\n    });\n\n    //Export Hints for Unit Tests\n    exports.SpecialCharHints = SpecialCharHints;\n});\n"
  },
  {
    "path": "src/extensions/default/HtmlEntityCodeHints/styles.css",
    "content": "span.entity-display-character {\n    float: right;\n}"
  },
  {
    "path": "src/extensions/default/HtmlEntityCodeHints/unittest-files/default.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n    </head>\n    <body>\n        <!-- Should show hints -->\n        <p>\n            Test&\n        </p>\n\n        <!-- Should show hints -->\n        <p>\n            Test&#33; &\n        </p>\n\n        <!-- Should show hints when cursor inside Entity -->\n        <p>\n            Test&acute; with more text and a subsequent entity such as &dagger;\n        </p>\n\n        <!-- Shouldn't show hints inside an opening tag-->\n        <p&></p>\n\n        <!-- Shouldn't show hints inside a closing tag-->\n        <p></p&>\n\n        <!-- Should show hints when semi-colon on the same line -->\n        <p>\n            Test ;  &\n        </p>\n    \n        <!-- Should not hint for & in attribute name -->\n        <p & ></p>\n    \n        <!-- Should not hint for & in attribute value -->\n        <p title=\"&\"></p>\n\n        <!-- Should not hint for & in url -->\n        <a href=\"https://github.com/adobe/brackets/issues?labels=low+priority&page=1&state=open\">link</a>\n        \n        <!-- Should show multiple hints in same line -->\n        <p>This &amp; that &amp; the other</p>\n    \n        <!-- Should sort &#xxxx hints numerically not alphabetically -->\n        <p>\n            &#\n        </p>\n    </body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/HtmlEntityCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Modules from the SpecRunner window\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        HTMLEntityHints = require(\"main\").SpecialCharHints,\n        defaultContent  = require(\"text!unittest-files/default.html\");\n\n    // Helper function for testing cursor position\n    function fixPos(pos) {\n        if (!(\"sticky\" in pos)) {\n            pos.sticky = null;\n        }\n        return pos;\n    }\n\n    describe(\"HTML Entity Hinting\", function () {\n\n        var testEditorAndDoc,\n            hintProvider = new HTMLEntityHints();\n\n        beforeEach(function () {\n            testEditorAndDoc = SpecRunnerUtils.createMockEditor(defaultContent, \"html\");\n        });\n\n        afterEach(function () {\n            SpecRunnerUtils.destroyMockEditor(testEditorAndDoc.doc);\n        });\n\n        // Ask provider for hints at current cursor position; expect it to return some\n        function expectHints(provider) {\n            expect(provider.hasHints(testEditorAndDoc.editor, null)).toBe(true);\n            var hintsObj = provider.getHints(null);\n            expect(hintsObj).toBeTruthy();\n            return hintsObj.hints; // return just the array of hints\n        }\n\n        // Ask provider for hints at current cursor position\n        function expectNoHints(provider) {\n            expect(provider.hasHints(testEditorAndDoc.editor, null)).toBe(false);\n        }\n\n        it(\"should show hints when in Text in paragraph\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 7, ch: 17});\n\n            expectHints(hintProvider);\n        });\n\n        it(\"should show hints when another entity is in the same line\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 12, ch: 23});\n\n            expectHints(hintProvider);\n        });\n\n        it(\"should show hints when cursor inside entity\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 17, ch: 19});\n\n            var hints = expectHints(hintProvider);\n            expect(hints).toEqual([\"&amp;acirc; <span class='entity-display-character'>&acirc;</span>\",\n                                   \"&amp;acute; <span class='entity-display-character'>&acute;</span>\"]);\n        });\n\n        it(\"shouldn't show hints when inside an opening tag\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 21, ch: 11});\n\n            expectNoHints(hintProvider);\n        });\n\n        it(\"shouldn't show hints when inside a closing tag\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 24, ch: 15});\n\n            expectNoHints(hintProvider);\n        });\n\n        it(\"should show hints when semi-colon on the same line\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 28, ch: 21});\n\n            expectHints(hintProvider);\n        });\n\n        it(\"shouldn't show hints in attribute name\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 32, ch: 12});\n\n            expectNoHints(hintProvider);\n        });\n\n        it(\"shouldn't show hints in attribute value\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 35, ch: 19});\n\n            expectNoHints(hintProvider);\n        });\n\n        it(\"shouldn't show hints in url\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 38, ch: 78});\n\n            expectNoHints(hintProvider);\n        });\n\n        it(\"should show multiple hints in the same line\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 41, ch: 17});\n\n            expectHints(hintProvider);\n\n            testEditorAndDoc.editor.setCursorPos({line: 41, ch: 29});\n\n            expectHints(hintProvider);\n        });\n\n        it(\"should sort &#xxxx hints numerically not alphabetically\", function () {\n            testEditorAndDoc.editor.setCursorPos({line: 45, ch: 14});\n\n            var hints = expectHints(hintProvider);\n            hintProvider.insertHint(hints[0]);\n            expect(testEditorAndDoc.editor.document.getRange({line: 45, ch: 12}, {line: 45, ch: 17})).toEqual(\"&#33;\");\n\n            testEditorAndDoc.editor.setCursorPos({line: 45, ch: 14});\n            hintProvider.insertHint(hints[23]);\n            expect(testEditorAndDoc.editor.document.getRange({line: 45, ch: 12}, {line: 45, ch: 18})).toEqual(\"&#123;\");\n        });\n\n        describe(\"Inserting Tests\", function () {\n\n            it(\"should replace entity with hint if inside entity\", function () {\n                testEditorAndDoc.editor.setCursorPos({line: 17, ch: 19});\n\n                var hints = expectHints(hintProvider);\n                hintProvider.insertHint(hints[0]);\n                expect(testEditorAndDoc.editor.document.getRange({line: 17, ch: 16}, {line: 17, ch: 23})).toEqual(\"&acirc;\");\n            });\n\n            it(\"should place cursor at the end of the replaced entity\", function () {\n                testEditorAndDoc.editor.setCursorPos({line: 17, ch: 19});\n\n                var hints = expectHints(hintProvider);\n                hintProvider.insertHint(hints[0]);\n                expect(fixPos(testEditorAndDoc.editor.getCursorPos())).toEqual(fixPos({line: 17, ch: 23}));\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/InAppNotifications/htmlContent/notificationContainer.html",
    "content": "<div id=\"notification-bar\" tabindex=\"0\">\n    <div class=\"content-container\">\n    </div>\n    <div class=\"close-icon-container\">\n        <button type=\"button\" class=\"close-icon\" tabIndex=\"0\">&times;</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/InAppNotifications/main.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n *  module for displaying in-app notifications\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit              = brackets.getModule(\"utils/AppInit\"),\n        PreferencesManager   = brackets.getModule(\"preferences/PreferencesManager\"),\n        ExtensionUtils       = brackets.getModule(\"utils/ExtensionUtils\"),\n        ExtensionManager     = brackets.getModule(\"extensibility/ExtensionManager\"),\n        HealthLogger         = brackets.getModule(\"utils/HealthLogger\"),\n        NotificationBarHtml  = require(\"text!htmlContent/notificationContainer.html\");\n\n    ExtensionUtils.loadStyleSheet(module, \"styles/styles.css\");\n\n    // duration of one day in milliseconds\n    var ONE_DAY = 1000 * 60 * 60 * 24;\n\n    // Init default last notification number\n    PreferencesManager.stateManager.definePreference(\"lastHandledNotificationNumber\", \"number\", 0);\n\n    // Init default last info URL fetch time\n    PreferencesManager.stateManager.definePreference(\"lastNotificationURLFetchTime\", \"number\", 0);\n\n    /**\n     * Constructs notification info URL for XHR\n     *\n     * @param {string=} localeParam - optional locale, defaults to 'brackets.getLocale()' when omitted.\n     * @returns {string} the new notification info url\n     */\n    function _getVersionInfoUrl(localeParam) {\n\n        var locale = localeParam || brackets.getLocale();\n\n        if (locale.length > 2) {\n            locale = locale.substring(0, 2);\n        }\n\n        return brackets.config.notification_info_url.replace(\"<locale>\", locale);\n    }\n\n    /**\n     * Get a data structure that has information for all Brackets targeted notifications.\n     *\n     * _notificationInfoUrl is used for unit testing.\n     */\n    function _getNotificationInformation(_notificationInfoUrl) {\n        // Last time the versionInfoURL was fetched\n        var lastInfoURLFetchTime = PreferencesManager.getViewState(\"lastNotificationURLFetchTime\");\n\n        var result = new $.Deferred();\n        var fetchData = false;\n        var data;\n\n        // If we don't have data saved in prefs, fetch\n        data = PreferencesManager.getViewState(\"notificationInfo\");\n        if (!data) {\n            fetchData = true;\n        }\n\n        // If more than 24 hours have passed since our last fetch, fetch again\n        if (Date.now() > lastInfoURLFetchTime + ONE_DAY) {\n            fetchData = true;\n        }\n\n        if (fetchData) {\n            var lookupPromise = new $.Deferred(),\n                localNotificationInfoUrl;\n\n            // If the current locale isn't \"en\" or \"en-US\", check whether we actually have a\n            // locale-specific notification target, and fall back to \"en\" if not.\n            var locale = brackets.getLocale().toLowerCase();\n            if (locale !== \"en\" && locale !== \"en-us\") {\n                localNotificationInfoUrl = _notificationInfoUrl || _getVersionInfoUrl();\n                // Check if we can reach a locale specific notifications source\n                $.ajax({\n                    url: localNotificationInfoUrl,\n                    cache: false,\n                    type: \"HEAD\"\n                }).fail(function (jqXHR, status, error) {\n                    // Fallback to \"en\" locale\n                    localNotificationInfoUrl = _getVersionInfoUrl(\"en\");\n                }).always(function (jqXHR, status, error) {\n                    lookupPromise.resolve();\n                });\n            } else {\n                localNotificationInfoUrl = _notificationInfoUrl || _getVersionInfoUrl(\"en\");\n                lookupPromise.resolve();\n            }\n\n            lookupPromise.done(function () {\n                $.ajax({\n                    url: localNotificationInfoUrl,\n                    dataType: \"json\",\n                    cache: false\n                }).done(function (notificationInfo, textStatus, jqXHR) {\n                    lastInfoURLFetchTime = (new Date()).getTime();\n                    PreferencesManager.setViewState(\"lastNotificationURLFetchTime\", lastInfoURLFetchTime);\n                    PreferencesManager.setViewState(\"notificationInfo\", notificationInfo);\n                    result.resolve(notificationInfo);\n                }).fail(function (jqXHR, status, error) {\n                    // When loading data for unit tests, the error handler is\n                    // called but the responseText is valid. Try to use it here,\n                    // but *don't* save the results in prefs.\n\n                    if (!jqXHR.responseText) {\n                        // Text is NULL or empty string, reject().\n                        result.reject();\n                        return;\n                    }\n\n                    try {\n                        data = JSON.parse(jqXHR.responseText);\n                        result.resolve(data);\n                    } catch (e) {\n                        result.reject();\n                    }\n                });\n            });\n        } else {\n            result.resolve(data);\n        }\n\n        return result.promise();\n    }\n\n\n    /**\n     * Check for notifications, notification overlays are always displayed\n     *\n     * @return {$.Promise} jQuery Promise object that is resolved or rejected after the notification check is complete.\n     */\n    function checkForNotification(versionInfoUrl) {\n        var result = new $.Deferred();\n\n        _getNotificationInformation(versionInfoUrl)\n            .done(function (notificationInfo) {\n                // Get all available notifications\n                var notifications = notificationInfo.notifications;\n                if (notifications && notifications.length > 0) {\n                    // Iterate through notifications and act only on the most recent\n                    // applicable notification\n                    notifications.every(function(notificationObj) {\n                        // Only show the notification overlay if the user hasn't been\n                        // alerted of this notification\n                        if (_checkNotificationValidity(notificationObj)) {\n                            if (notificationObj.silent) {\n                                // silent notifications, to gather user validity based on filters\n                                HealthLogger.sendAnalyticsData(\"notification\", notificationObj.sequence, \"handled\");\n                            } else {\n                                showNotification(notificationObj);\n                            }\n                            // Break, we have acted on one notification already\n                            return false;\n                        }\n                        // Continue, we haven't yet got a notification to act on\n                        return true;\n                    });\n                }\n                result.resolve();\n            })\n            .fail(function () {\n                // Error fetching the update data. If this is a forced check, alert the user\n                result.reject();\n            });\n\n        return result.promise();\n    }\n\n    function _checkPlatform(filters, _platform) {\n        return !filters.platforms || filters.platforms.length === 0 || filters.platforms.indexOf(_platform) >=0;\n    }\n\n    function _checkBuild(filters, _build) {\n        return !filters.builds || filters.builds.length === 0 || filters.builds.indexOf(_build) >=0;\n    }\n\n    function _checkVersion(filters, _version) {\n        var re = new RegExp(filters.version);\n        return re.exec(_version);\n    }\n\n    function _checkLocale(filters, _locale) {\n        return !filters.locales || filters.locales.length === 0 || filters.locales.indexOf(_locale) >=0;\n    }\n\n    function _checkExpiry(expiry) {\n        return Date.now() <= expiry;\n    }\n\n    function _checkExtensions(filters) {\n        //if no property called extensions then it's a universal notification\n        if (filters.extensions === undefined) {\n            return true;\n        }\n\n        var allExtensions = ExtensionManager.extensions,\n            allExtnsMatched = true,\n            userExtensionKeys = Object.keys(allExtensions).filter(function(k) {\n                return allExtensions[k].installInfo.locationType === 'user';\n            });\n\n        if (!filters.extensions) {\n            //if property called extensions exists but has a falsy value\n            //then number of user extensions must be zero\n            allExtnsMatched = userExtensionKeys.length === 0;\n        } else if (filters.extensions.length === 0) {\n            //if property called extensions exists but is an empty array\n            //then number of user extensions must greater than zero\n            allExtnsMatched = userExtensionKeys.length > 0;\n        } else {\n            //if property called extensions exists but is a non empty array\n            //then notification is targetted to users having the fitered extensions\n            var filteredExtns = filters.extensions,\n                extnIterator = null;\n            for (var i=0; i < filteredExtns.length; i++) {\n                extnIterator = filteredExtns[i];\n                if (userExtensionKeys.indexOf(extnIterator) === -1) {\n                    allExtnsMatched = false;\n                    break;\n                }\n            }\n        }\n        return allExtnsMatched;\n    }\n\n    function _checkNotificationValidity(notificationObj) {\n\n        var filters = notificationObj.filters,\n            _platform = brackets.getPlatformInfo(),\n            _locale = brackets.getLocale(),\n            _lastHandledNotificationNumber = PreferencesManager.getViewState(\"lastHandledNotificationNumber\"),\n            // Extract current build number from package.json version field 0.0.0-0\n            _buildNumber = Number(/-([0-9]+)/.exec(brackets.metadata.version)[1]),\n            _version = brackets.metadata.apiVersion;\n\n        if(_locale.length > 2) {\n            _locale = _locale.substring(0, 2);\n        }\n\n        return  notificationObj.sequence > _lastHandledNotificationNumber\n                && _checkExpiry(notificationObj.expiry)\n                && _checkPlatform(filters, _platform)\n                && _checkLocale(filters, _locale)\n                && _checkVersion(filters, _version)\n                && _checkBuild(filters, _buildNumber)\n                && _checkExtensions(filters);\n    }\n\n\n    /**\n     * Removes and cleans up the notification bar from DOM\n     */\n    function cleanNotificationBar() {\n        var $notificationBar = $('#notification-bar');\n        if ($notificationBar.length > 0) {\n            $notificationBar.remove();\n        }\n    }\n\n    /**\n     * Displays the Notification Bar UI\n     * @param   {object} msgObj - json object containing message info to be displayed\n     *\n     */\n    function showNotification(msgObj) {\n        var $htmlContent = $(msgObj.html),\n            $notificationBarElement = $(NotificationBarHtml);\n\n        // Remove any SCRIPT tag to avoid secuirity issues\n        $htmlContent.find('script').remove();\n\n        // Remove any STYLE tag to avoid styling impact on Brackets DOM\n        $htmlContent.find('style').remove();\n\n        cleanNotificationBar(); //Remove an already existing notification bar, if any\n        $notificationBarElement.prependTo(\".content\");\n\n        var $notificationBar = $('#notification-bar'),\n            $notificationContent = $notificationBar.find('.content-container'),\n            $closeIcon = $notificationBar.find('.close-icon');\n\n        $notificationContent.append($htmlContent);\n        HealthLogger.sendAnalyticsData(\"notification\", msgObj.sequence, \"shown\");\n\n        // Click handlers on actionable elements\n        if ($closeIcon.length > 0) {\n            $closeIcon.click(function () {\n                cleanNotificationBar();\n                PreferencesManager.setViewState(\"lastHandledNotificationNumber\", msgObj.sequence);\n                HealthLogger.sendAnalyticsData(\"notification\", msgObj.sequence, \"dismissedByClose\");\n            });\n        }\n\n        if (msgObj.actionables) {\n            $(msgObj.actionables).click(function () {\n                cleanNotificationBar();\n                PreferencesManager.setViewState(\"lastHandledNotificationNumber\", msgObj.sequence);\n                HealthLogger.sendAnalyticsData(\"notification\", msgObj.sequence, \"dismissedBy\" + this.id);\n            });\n        }\n    }\n\n\n    AppInit.appReady(function () {\n        checkForNotification();\n    });\n\n    // For unit tests only\n    exports.checkForNotification = checkForNotification;\n});\n"
  },
  {
    "path": "src/extensions/default/InAppNotifications/styles/styles.css",
    "content": "#notification-bar {\n    display: block;\n    background-color: #105F9C;\n    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.53);\n    padding: 5px 0px;\n    width: 100%;\n    min-height: 39px;\n    position: absolute;\n    z-index: 16;\n    left: 0px;\n    bottom: 25px;\n    outline: none;\n    overflow: hidden;\n    color: rgb(51, 51, 51);\n    background: rgb(223, 226, 226);\n}\n\n.dark #notification-bar {\n    color: #ccc;\n    background: #2c2c2c;\n}\n\n#notification-bar .content-container {\n    padding: 5px 10px;\n    float: left;\n    width: 100%;\n}\n\n#notification-bar .close-icon-container {\n    height: auto;\n    position: absolute;\n    float: right;\n    text-align: center;\n    width: auto;\n\tmin-width: 66px;\n\tright: 20px;\n    top: 10px;\n}\n\n#notification-bar .close-icon-container .close-icon {\n    display: block;\n    font-size: 18px;\n    line-height: 18px;\n    text-decoration: none;\n    width: 18px;\n    height: 18px;\n    background-color: transparent;\n    border: none;\n    padding: 0px; /*This is needed to center the icon*/\n\tfloat: right;\n}\n\n.dark #notification-bar .close-icon-container .close-icon {\n    color: #ccc;\n}\n\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/ColorEditor.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var KeyEvent           = brackets.getModule(\"utils/KeyEvent\"),\n        PreferencesManager = brackets.getModule(\"preferences/PreferencesManager\"),\n        StringUtils        = brackets.getModule(\"utils/StringUtils\"),\n        Strings            = brackets.getModule(\"strings\"),\n        Mustache           = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        tinycolor          = require(\"thirdparty/tinycolor-min\");\n\n    /** Mustache template that forms the bare DOM structure of the UI */\n    var ColorEditorTemplate = require(\"text!ColorEditorTemplate.html\");\n\n    /**\n     * @const @type {number}\n     */\n    var STEP_MULTIPLIER = 5;\n\n    /**\n     * Convert 0x notation into hex6 format for tinycolor\n     * compatibility: (\"0xFFAACC\" => \"#FFFFFF\")\n     * @param {string} str - String to ensure hex format for\n     * @returns {string} - str in hex format\n     */\n    function ensureHexFormat(str) {\n        return (/^0x/).test(str) ? str.replace(\"0x\",\"#\") : str;\n    }\n\n    /**\n     * Converts a color to a 0x-prefixed string\n     * @param {tinycolor} color - color to convert\n     * @returns {string} - color as 0x-prefixed string\n     */\n    function as0xString(color) {\n        return color.toHexString().replace(\"#\", \"0x\");\n    }\n\n    /**\n     * Converts 0x-prefixed color to hex\n     * @param {string} color - Color to convert\n     * @param {boolean} convertToString - true if color should \n     *                                    be returned as string\n     * @returns {tinycolor|string} - Hex color as a Tinycolor object\n     *                               or a hex string\n     */\n    function _0xColorToHex(color, convertToStr) {\n        var hexColor = tinycolor(color.replace(\"0x\", \"#\"));\n        hexColor._format = \"0x\";\n\n        if (convertToStr) {\n            return hexColor.toString();\n        }\n        return hexColor;\n    }\n\n    /**\n     * Ensures that a string is in Tinycolor supported format\n     * @param {string} color - Color to check the format for\n     * @param {boolean} convertToString - true if color should \n     *                                    be returned as string\n     * @returns {tinycolor|string} - Color as a Tinycolor object\n     *                               or a hex string\n     */\n    function checkSetFormat(color, convertToStr) {\n        if ((/^0x/).test(color)) {\n            return _0xColorToHex(color, convertToStr);\n        }\n        if (convertToStr) {\n            return tinycolor(color).toString();\n        }\n        return tinycolor(color);\n    }\n\n    /**\n     * Color picker control; may be used standalone or within an InlineColorEditor inline widget.\n     * @param {!jQuery} $parent  DOM node into which to append the root of the color picker UI\n     * @param {!string} color  Initially selected color\n     * @param {!function(string)} callback  Called whenever selected color changes\n     * @param {!Array.<{value:string, count:number}>} swatches  Quick-access color swatches to include in UI\n     */\n    function ColorEditor($parent, color, callback, swatches) {\n        // Create the DOM structure, filling in localized strings via Mustache\n        this.$element = $(Mustache.render(ColorEditorTemplate, Strings));\n        $parent.append(this.$element);\n\n        this._callback = callback;\n\n        this._handleKeydown = this._handleKeydown.bind(this);\n        this._handleOpacityKeydown = this._handleOpacityKeydown.bind(this);\n        this._handleHslKeydown = this._handleHslKeydown.bind(this);\n        this._handleHueKeydown = this._handleHueKeydown.bind(this);\n        this._handleSelectionKeydown = this._handleSelectionKeydown.bind(this);\n        this._handleOpacityDrag = this._handleOpacityDrag.bind(this);\n        this._handleHueDrag = this._handleHueDrag.bind(this);\n        this._handleSelectionFieldDrag = this._handleSelectionFieldDrag.bind(this);\n\n        this._originalColor = color;\n        this._color = checkSetFormat(color);\n\n        this._redoColor = null;\n        this._isUpperCase = PreferencesManager.get(\"uppercaseColors\");\n        PreferencesManager.on(\"change\", \"uppercaseColors\", function () {\n            this._isUpperCase = PreferencesManager.get(\"uppercaseColors\");\n        }.bind(this));\n\n        this.$colorValue = this.$element.find(\".color-value\");\n        this.$buttonList = this.$element.find(\"ul.button-bar\");\n        this.$rgbaButton = this.$element.find(\".rgba\");\n        this.$hexButton = this.$element.find(\".hex\");\n        this.$hslButton = this.$element.find(\".hsla\");\n        this.$0xButton = this.$element.find(\".0x\");\n        this.$currentColor = this.$element.find(\".current-color\");\n        this.$originalColor = this.$element.find(\".original-color\");\n        this.$selection = this.$element.find(\".color-selection-field\");\n        this.$selectionBase = this.$element.find(\".color-selection-field .selector-base\");\n        this.$hueBase = this.$element.find(\".hue-slider .selector-base\");\n        this.$opacityGradient = this.$element.find(\".opacity-gradient\");\n        this.$hueSlider = this.$element.find(\".hue-slider\");\n        this.$hueSelector = this.$element.find(\".hue-slider .selector-base\");\n        this.$opacitySlider = this.$element.find(\".opacity-slider\");\n        this.$opacitySelector = this.$element.find(\".opacity-slider .selector-base\");\n        this.$swatches = this.$element.find(\".swatches\");\n\n        // Create quick-access color swatches\n        this._addSwatches(swatches);\n\n        // Attach event listeners to main UI elements\n        this._addListeners();\n\n        // Initially selected color\n        this.$originalColor.css(\"background-color\", checkSetFormat(this._originalColor));\n        \n        this._commitColor(color);   \n    }\n\n    /**\n     * A string or tinycolor object representing the currently selected color\n     * TODO (#2201): type is unpredictable\n     * @type {tinycolor|string}\n     */\n    ColorEditor.prototype._color = null;\n\n    /**\n     * An HSV representation of the currently selected color.\n     * TODO (#2201): type of _hsv.s/.v is unpredictable\n     * @type {!{h:number, s:number|string, v:number|string, a:number}}\n     */\n    ColorEditor.prototype._hsv = tinycolor(\"rgba(0,0,0,1)\").toHsv();\n\n    /**\n     * Color that was selected before undo(), if undo was the last change made. Else null.\n     * @type {?string}\n     */\n    ColorEditor.prototype._redoColor = null;\n\n    /**\n     * Initial value the color picker was opened with\n     * @type {!string}\n     */\n    ColorEditor.prototype._originalColor = null;\n\n\n    /** Returns the root DOM node of the ColorPicker UI */\n    ColorEditor.prototype.getRootElement = function () {\n        return this.$element;\n    };\n\n    /** Attach event listeners for main UI elements */\n    ColorEditor.prototype._addListeners = function () {\n        this._bindColorFormatToRadioButton(\"rgba\");\n        this._bindColorFormatToRadioButton(\"hex\");\n        this._bindColorFormatToRadioButton(\"hsla\");\n        this._bindColorFormatToRadioButton(\"0x\");\n\n        this._bindInputHandlers();\n\n        this._bindOriginalColorButton();\n\n        this._registerDragHandler(this.$selection, this._handleSelectionFieldDrag);\n        this._registerDragHandler(this.$hueSlider, this._handleHueDrag);\n        this._registerDragHandler(this.$opacitySlider, this._handleOpacityDrag);\n        this._bindKeyHandler(this.$selectionBase, this._handleSelectionKeydown);\n        this._bindKeyHandler(this.$hueBase, this._handleHueKeydown);\n        this._bindKeyHandler(this.$opacitySelector, this._handleOpacityKeydown);\n        this._bindKeyHandler(this.$hslButton, this._handleHslKeydown);\n\n        // General key handler gets bubbling events from any focusable part of widget\n        this._bindKeyHandler(this.$element, this._handleKeydown);\n    };\n\n    /**\n     * Update all UI elements to reflect the selected color (_color and _hsv). It is usually\n     * incorrect to call this directly; use _commitColor() or setColorAsHsv() instead.\n     */\n\n    ColorEditor.prototype._synchronize = function () {\n        var colorValue  = this.getColor().getOriginalInput();\n        var colorObject = checkSetFormat(colorValue);\n        var hueColor    = \"hsl(\" + this._hsv.h + \", 100%, 50%)\";\n        this._updateColorTypeRadioButtons(colorObject.getFormat());\n        this.$colorValue.val(colorValue);\n        this.$currentColor.css(\"background-color\", checkSetFormat(colorValue, true));\n        this.$selection.css(\"background-color\", hueColor);\n        this.$hueBase.css(\"background-color\", hueColor);\n\n        // Update gradients in color square & opacity slider\n        this.$selectionBase.css(\"background-color\", colorObject.toHexString());\n        this.$opacityGradient.css(\"background-image\", \"linear-gradient(\" + hueColor + \", transparent)\");\n\n        // Update slider thumb positions\n        this.$hueSelector.css(\"bottom\", (this._hsv.h / 360 * 100) + \"%\");\n        this.$opacitySelector.css(\"bottom\", (this._hsv.a * 100) + \"%\");\n        if (!isNaN(this._hsv.s)) {      // TODO (#2201): type of _hsv.s/.v is unpredictable\n            this._hsv.s = (this._hsv.s * 100) + \"%\";\n        }\n        if (!isNaN(this._hsv.v)) {\n            this._hsv.v = (this._hsv.v * 100) + \"%\";\n        }\n        this.$selectionBase.css({\n            left: this._hsv.s,\n            bottom: this._hsv.v\n        });\n    };\n\n    /**\n     * Focus the main color square's thumb.\n     * @return {boolean} True if we focused the square, false otherwise.\n     */\n    ColorEditor.prototype.focus = function () {\n        if (!this.$selectionBase.is(\":focus\")) {\n            this.$selectionBase.focus();\n            return true;\n        }\n        return false;\n    };\n\n    /**\n     * Remove any preference listeners before destroying the editor.\n     */\n    ColorEditor.prototype.destroy = function () {\n        PreferencesManager.off(\"change\", \"uppercaseColors\");\n    };\n\n    /**\n     * @return {tinycolor|string} The currently selected color (TODO (#2201): type is unpredictable).\n     */\n    ColorEditor.prototype.getColor = function () {\n        return this._color;\n    };\n\n    /** Update the format button bar's selection */\n    ColorEditor.prototype._updateColorTypeRadioButtons = function (format) {\n        this.$buttonList.find(\"li\").removeClass(\"selected\");\n        switch (format) {\n        case \"rgb\":\n            this.$buttonList.find(\".rgba\").parent().addClass(\"selected\");\n            break;\n        case \"hex\":\n        case \"name\":\n            this.$buttonList.find(\".hex\").parent().addClass(\"selected\");\n            break;\n        case \"hsl\":\n            this.$buttonList.find(\".hsla\").parent().addClass(\"selected\");\n            break;\n        case \"0x\":\n            this.$buttonList.find(\".0x\").parent().addClass(\"selected\");\n            break;\n        }\n    };\n\n    /** Add event listeners to the format button bar */\n    ColorEditor.prototype._bindColorFormatToRadioButton = function (buttonClass, propertyName, value) {\n        var handler,\n            self = this;\n        handler = function (event) {\n            var newFormat   = $(event.currentTarget).html().toLowerCase().replace(\"%\", \"p\"),\n                newColor    = self.getColor().toString();\n\n            var colorObject = checkSetFormat(newColor);\n\n            switch (newFormat) {\n            case \"hsla\":\n                newColor = colorObject.toHslString();\n                break;\n            case \"rgba\":\n                newColor = colorObject.toRgbString();\n                break;\n            case \"prgba\":\n                newColor = colorObject.toPercentageRgbString();\n                break;\n            case \"hex\":\n                newColor = colorObject.toHexString();\n                self._hsv.a = 1;\n                break;\n            case \"0x\":\n                newColor = as0xString(colorObject);\n                self._hsv.a = 1;\n                self._format = \"0x\";\n                break;\n            }\n\n            // We need to run this again whenever RGB/HSL/Hex conversions\n            // are performed to preserve the case\n            newColor = self._isUpperCase ? newColor.toUpperCase() : newColor;\n            self._commitColor(newColor, false);\n        };\n        this.$element.find(\".\" + buttonClass).click(handler);\n    };\n\n    /** Add event listener to the \"original color value\" swatch */\n    ColorEditor.prototype._bindOriginalColorButton = function () {\n        var self = this;\n        this.$originalColor.click(function (event) {\n            self._commitColor(self._originalColor, true);\n        });\n    };\n\n    /**\n     * Convert percentage values in an RGB color into normal RGB values in the range of 0 - 255.\n     * If the original color is already in non-percentage format, does nothing.\n     * @param {string} color The color to be converted to non-percentage RGB color string.\n     * @return {string} an RGB color string in the normal format using non-percentage values\n     */\n    ColorEditor.prototype._convertToNormalRGB = function (color) {\n        var matches = color.match(/^rgb.*?([0-9]+)\\%.*?([0-9]+)\\%.*?([0-9]+)\\%/i);\n        if (matches) {\n            var i, percentStr, value;\n            for (i = 0; i < 3; i++) {\n                percentStr = matches[i + 1];\n                value = Math.round(255 * Number(percentStr) / 100);\n                if (!isNaN(value)) {\n                    color = color.replace(percentStr + \"%\", value);\n                }\n            }\n        }\n        return color;\n    };\n\n    /**\n     * Normalize the given color string into the format used by tinycolor, by adding a space\n     * after commas.\n     * @param {string} color The color to be corrected if it looks like an RGB or HSL color.\n     * @return {string} a normalized color string.\n     */\n    ColorEditor.prototype._normalizeColorString = function (color) {\n        var normalizedColor = color;\n\n        // Convert 6-digit hex to 3-digit hex as TinyColor (#ffaacc -> #fac)\n        if (color.match(/^#[0-9a-fA-F]{6}/)) {\n            return tinycolor(color).toString();\n        }\n        if (color.match(/^(rgb|hsl)/i)) {\n            normalizedColor = normalizedColor.replace(/,\\s*/g, \", \");\n            normalizedColor = normalizedColor.replace(/\\(\\s+/, \"(\");\n            normalizedColor = normalizedColor.replace(/\\s+\\)/, \")\");\n        }\n        return normalizedColor;\n    };\n\n    /** Handle changes in text field */\n    ColorEditor.prototype._handleTextFieldInput = function (losingFocus) {\n        var newColor    = $.trim(this.$colorValue.val()),\n            newColorObj = checkSetFormat(newColor),\n            newColorOk  = newColorObj.isValid();\n\n\n        // TinyColor will auto correct an incomplete rgb or hsl value into a valid color value.\n        // eg. rgb(0,0,0 -> rgb(0, 0, 0)\n        // We want to avoid having TinyColor do this, because we don't want to sync the color\n        // to the UI if it's incomplete. To accomplish this, we first normalize the original\n        // color string into the format TinyColor would generate, and then compare it to what\n        // TinyColor actually generates to see if it's different. If so, then we assume the color\n        // was incomplete to begin with.\n        if (newColorOk) {\n            newColorOk = (newColorObj.toString() === this._normalizeColorString(ensureHexFormat(newColor)));\n        }\n\n        // Restore to the previous valid color if the new color is invalid or incomplete.\n        if (losingFocus && !newColorOk) {\n            newColor = this.getColor().toString();\n        }\n\n        // Sync only if we have a valid color or we're restoring the previous valid color.\n        if (losingFocus || newColorOk) {\n            this._commitColor(newColor, true);\n        }\n    };\n\n    ColorEditor.prototype._bindInputHandlers = function () {\n        var self = this;\n\n        this.$colorValue.bind(\"input\", function (event) {\n            self._handleTextFieldInput(false);\n        });\n\n        this.$colorValue.bind(\"change\", function (event) {\n            self._handleTextFieldInput(true);\n        });\n    };\n\n    /**\n     * Populate the UI with the given color swatches and add listeners so they're selectable.\n     * @param {!Array.<{value:string, count:number}>} swatches\n     */\n    ColorEditor.prototype._addSwatches = function (swatches) {\n        var self = this;\n\n        // Create swatches\n        swatches.forEach(function (swatch) {\n            var swatchValue = checkSetFormat(swatch.value, true);\n            var stringFormat = (swatch.count > 1) ? Strings.COLOR_EDITOR_USED_COLOR_TIP_PLURAL : Strings.COLOR_EDITOR_USED_COLOR_TIP_SINGULAR,\n                usedColorTip = StringUtils.format(stringFormat, swatch.value, swatch.count);\n\n            self.$swatches.append(\"<li tabindex='0'><div class='swatch-bg'><div class='swatch' style='background-color: \" +\n                    swatchValue + \";' title='\" + usedColorTip + \"'></div></div> <span class='value'\" + \" title='\" +\n                    usedColorTip + \"'>\" + swatch.value + \"</span></li>\");\n        });\n\n        // Add key & click listeners to each\n        this.$swatches.find(\"li\").keydown(function (event) {\n            if (event.keyCode === KeyEvent.DOM_VK_RETURN ||\n                    event.keyCode === KeyEvent.DOM_VK_ENTER ||\n                    event.keyCode === KeyEvent.DOM_VK_SPACE) {\n                // Enter/Space is same as clicking on swatch\n\n                self._commitColor($(event.currentTarget).find(\".value\").html());\n            } else if (event.keyCode === KeyEvent.DOM_VK_TAB) {\n                // Tab on last swatch loops back to color square\n                if (!event.shiftKey && $(this).next(\"li\").length === 0) {\n                    self.$selectionBase.focus();\n                    return false;\n                }\n            }\n        });\n\n        this.$swatches.find(\"li\").click(function (event) {\n            self._commitColor($(event.currentTarget).find(\".value\").html());\n        });\n    };\n\n    /**\n     * Checks whether colorVal is a valid color\n     * @param {!string} colorVal\n     * @return {boolean} Whether colorVal is valid\n     */\n    ColorEditor.prototype.isValidColor = function (colorVal) {\n        return tinycolor(colorVal).isValid();\n    };\n\n    /**\n     * Sets _hsv and _color based on an HSV input, and updates the UI. Attempts to preserve\n     * the previous color format.\n     * @param {!{h:number=, s:number=, v:number=}} hsv  Any missing values use the previous color's values.\n     */\n    ColorEditor.prototype.setColorAsHsv = function (hsv) {\n        var colorVal, newColor,\n            oldFormat = tinycolor(this.getColor()).getFormat();\n\n        // Set our state to the new color\n        $.extend(this._hsv, hsv);\n        newColor = tinycolor(this._hsv);\n\n        switch (oldFormat) {\n        case \"hsl\":\n            colorVal = newColor.toHslString();\n            break;\n        case \"rgb\":\n            colorVal = newColor.toRgbString();\n            break;\n        case \"prgb\":\n            colorVal = newColor.toPercentageRgbString();\n            break;\n        case \"hex\":\n        case \"name\":\n            colorVal = this._hsv.a < 1 ? newColor.toRgbString() : newColor.toHexString();\n            break;\n        case \"0x\":\n            colorVal = as0xString(newColor);\n            break;\n        }\n        colorVal = this._isUpperCase ? colorVal.toUpperCase() : colorVal;\n        this._commitColor(colorVal, false);\n    };\n\n    /**\n     * Sets _color (and optionally _hsv) based on a string input, and updates the UI. The string's\n     * format determines the new selected color's format.\n     * @param {!string} colorVal\n     * @param {boolean=} resetHsv  Pass false ONLY if hsv set already been modified to match colorVal. Default: true.\n     */\n    ColorEditor.prototype._commitColor = function (colorVal, resetHsv) {\n\n        if (resetHsv === undefined) {\n            resetHsv = true;\n        }\n        this._callback(colorVal);\n\n        var colorObj = checkSetFormat(colorVal);\n        colorObj._originalInput = colorVal;\n        this._color = colorObj;\n\n        if (resetHsv) {\n            this._hsv = this._color.toHsv();\n        }\n\n        this._redoColor = null;  // if we had undone, this new value blows away the redo history\n        this._synchronize();\n    };\n\n    /**\n     * Sets _color and _hsv based on a string input, and updates the UI. The string's\n     * format determines the new selected color's format.\n     * @param {!string} colorVal\n     */\n    ColorEditor.prototype.setColorFromString = function (colorVal) {\n        this._commitColor(colorVal, true);  // TODO (#2204): make this less entangled with setColorAsHsv()\n    };\n\n    /** Converts a mouse coordinate to be relative to zeroPos, and clips to [0, maxOffset] */\n    function _getNewOffset(pos, zeroPos, maxOffset) {\n        var offset = pos - zeroPos;\n        offset = Math.min(maxOffset, Math.max(0, offset));\n        return offset;\n    }\n\n    /** Dragging color square's thumb */\n    ColorEditor.prototype._handleSelectionFieldDrag = function (event) {\n        var height  = this.$selection.height(),\n            width   = this.$selection.width(),\n            xOffset = _getNewOffset(event.clientX, this.$selection.offset().left, width),\n            yOffset = _getNewOffset(event.clientY, this.$selection.offset().top, height),\n            hsv     = {};\n        hsv.s = xOffset / width;\n        hsv.v = 1 - yOffset / height;\n        this.setColorAsHsv(hsv, false);\n        if (!this.$selection.find(\".selector-base\").is(\":focus\")) {\n            this.$selection.find(\".selector-base\").focus();\n        }\n    };\n\n    /** Dragging hue slider thumb */\n    ColorEditor.prototype._handleHueDrag = function (event) {\n        var height = this.$hueSlider.height(),\n            offset = _getNewOffset(event.clientY, this.$hueSlider.offset().top, height),\n            hsv    = {};\n        hsv.h = (1 - offset / height) * 360;\n        this.setColorAsHsv(hsv, false);\n        if (!this.$hueSlider.find(\".selector-base\").is(\":focus\")) {\n            this.$hueSlider.find(\".selector-base\").focus();\n        }\n    };\n\n    /** Dragging opacity slider thumb */\n    ColorEditor.prototype._handleOpacityDrag = function (event) {\n        var height = this.$opacitySlider.height(),\n            offset = _getNewOffset(event.clientY, this.$opacitySlider.offset().top, height),\n            hsv    = {};\n        hsv.a = 1 - (offset / height);\n        this.setColorAsHsv(hsv, false);\n        if (!this.$opacitySlider.find(\".selector-base\").is(\":focus\")) {\n            this.$opacitySlider.find(\".selector-base\").focus();\n        }\n    };\n\n    /**\n     * Helper for attaching drag-related mouse listeners to an element. It's up to\n     * 'handler' to actually move the element as mouse is dragged.\n     * @param {!function(jQuery.event)} handler  Called whenever drag position changes\n     */\n    ColorEditor.prototype._registerDragHandler = function ($element, handler) {\n        var mouseupHandler = function (event) {\n            $(window).unbind(\"mousemove\", handler);\n            $(window).unbind(\"mouseup\", mouseupHandler);\n        };\n        $element.mousedown(function (event) {\n            $(window).bind(\"mousemove\", handler);\n            $(window).bind(\"mouseup\", mouseupHandler);\n        });\n        $element.mousedown(handler);  // run drag-update handler on initial mousedown too\n    };\n\n    /**\n     * Handles undo gestures while color picker has focus. We don't want to let CodeMirror's\n     * usual undo logic run since it will destroy our marker.\n     */\n    ColorEditor.prototype.undo = function () {\n        if (this._originalColor.toString() !== this._color.toString()) {\n            this._commitColor(this._originalColor, true);\n            this._redoColor = this._color.toString();\n        }\n    };\n\n    /** Similarly, handle redo gestures while color picker has focus. */\n    ColorEditor.prototype.redo = function () {\n        if (this._redoColor) {\n            this._commitColor(this._redoColor, true);\n            this._redoColor = null;\n        }\n    };\n\n    /**\n     * Global handler for keys in the color editor. Catches undo/redo keys and traps\n     * arrow keys that would be handled by the scroller.\n     */\n    ColorEditor.prototype._handleKeydown = function (event) {\n        var hasCtrl = (brackets.platform === \"win\") ? (event.ctrlKey) : (event.metaKey);\n        if (hasCtrl) {\n            switch (event.keyCode) {\n            case KeyEvent.DOM_VK_Z:\n                if (event.shiftKey) {\n                    this.redo();\n                } else {\n                    this.undo();\n                }\n                return false;\n            case KeyEvent.DOM_VK_Y:\n                this.redo();\n                return false;\n            }\n        } else {\n            if (event.keyCode === KeyEvent.DOM_VK_LEFT ||\n                    event.keyCode === KeyEvent.DOM_VK_RIGHT ||\n                    event.keyCode === KeyEvent.DOM_VK_UP ||\n                    event.keyCode === KeyEvent.DOM_VK_DOWN) {\n                // Prevent arrow keys that weren't handled by a child control\n                // from being handled by a parent, either through bubbling or\n                // through default native behavior. There isn't a good general\n                // way to tell if the target would handle this event by default,\n                // so we look to see if the target is a text input control.\n                var preventDefault = false,\n                    $target = $(event.target);\n\n                // If the input has no \"type\" attribute, it defaults to text. So we\n                // have to check for both possibilities.\n                if ($target.is(\"input:not([type])\") || $target.is(\"input[type=text]\")) {\n                    // Text input control. In WebKit, if the cursor gets to the start\n                    // or end of a text field and can't move any further, the default\n                    // action doesn't take place in the text field, so the event is handled\n                    // by the outer scroller. We have to prevent in that case too.\n                    if ($target[0].selectionStart === $target[0].selectionEnd &&\n                            ((event.keyCode === KeyEvent.DOM_VK_LEFT && $target[0].selectionStart === 0) ||\n                             (event.keyCode === KeyEvent.DOM_VK_RIGHT && $target[0].selectionEnd === $target.val().length))) {\n                        preventDefault = true;\n                    }\n                } else {\n                    // Not a text input control, so we want to prevent default.\n                    preventDefault = true;\n                }\n\n                if (preventDefault) {\n                    event.stopPropagation();\n                    return false; // equivalent to event.preventDefault()\n                }\n            }\n        }\n    };\n\n    ColorEditor.prototype._handleHslKeydown = function (event) {\n        if (event.keyCode === KeyEvent.DOM_VK_TAB) {\n            // If we're the last focusable element (no color swatches), Tab wraps around to color square\n            if (!event.shiftKey) {\n                if (this.$swatches.children().length === 0) {\n                    this.$selectionBase.focus();\n                    return false;\n                }\n            }\n        }\n    };\n\n    /** Key events on the color square's thumb */\n    ColorEditor.prototype._handleSelectionKeydown = function (event) {\n        var hsv = {},\n            step = 1.5,\n            xOffset,\n            yOffset,\n            adjustedOffset;\n\n        switch (event.keyCode) {\n        case KeyEvent.DOM_VK_LEFT:\n        case KeyEvent.DOM_VK_RIGHT:\n            step = event.shiftKey ? step * STEP_MULTIPLIER : step;\n            xOffset = Number($.trim(this.$selectionBase[0].style.left.replace(\"%\", \"\")));\n            adjustedOffset = (event.keyCode === KeyEvent.DOM_VK_LEFT) ? (xOffset - step) : (xOffset + step);\n            xOffset = Math.min(100, Math.max(0, adjustedOffset));\n            hsv.s = xOffset / 100;\n            this.setColorAsHsv(hsv, false);\n            return false;\n        case KeyEvent.DOM_VK_DOWN:\n        case KeyEvent.DOM_VK_UP:\n            step = event.shiftKey ? step * STEP_MULTIPLIER : step;\n            yOffset = Number($.trim(this.$selectionBase[0].style.bottom.replace(\"%\", \"\")));\n            adjustedOffset = (event.keyCode === KeyEvent.DOM_VK_DOWN) ? (yOffset - step) : (yOffset + step);\n            yOffset = Math.min(100, Math.max(0, adjustedOffset));\n            hsv.v = yOffset / 100;\n            this.setColorAsHsv(hsv, false);\n            return false;\n        case KeyEvent.DOM_VK_TAB:\n            // Shift+Tab loops back to last focusable element: last swatch if any; format button bar if not\n            if (event.shiftKey) {\n                if (this.$swatches.children().length === 0) {\n                    this.$hslButton.focus();\n                } else {\n                    this.$swatches.find(\"li:last\").focus();\n                }\n                return false;\n            }\n            break;\n        }\n    };\n\n    /** Key events on the hue slider thumb */\n    ColorEditor.prototype._handleHueKeydown = function (event) {\n        var hsv = {},\n            hue = Number(this._hsv.h),\n            step = 3.6;\n\n        switch (event.keyCode) {\n        case KeyEvent.DOM_VK_DOWN:\n            step = event.shiftKey ? step * STEP_MULTIPLIER : step;\n            hsv.h = (hue - step) <= 0 ? 360 - step : hue - step;\n            this.setColorAsHsv(hsv, false);\n            return false;\n        case KeyEvent.DOM_VK_UP:\n            step = event.shiftKey ? step * STEP_MULTIPLIER : step;\n            hsv.h = (hue + step) >= 360 ? step : hue + step;\n            this.setColorAsHsv(hsv, false);\n            return false;\n        }\n    };\n\n    /** Key events on the opacity slider thumb */\n    ColorEditor.prototype._handleOpacityKeydown = function (event) {\n        var alpha = this._hsv.a,\n            hsv = {},\n            step = 0.01;\n\n        switch (event.keyCode) {\n        case KeyEvent.DOM_VK_DOWN:\n            step = event.shiftKey ? step * STEP_MULTIPLIER : step;\n            if (alpha > 0) {\n                hsv.a = (alpha - step) <= 0 ? 0 : alpha - step;\n                this.setColorAsHsv(hsv);\n            }\n            return false;\n        case KeyEvent.DOM_VK_UP:\n            step = event.shiftKey ? step * STEP_MULTIPLIER : step;\n            if (alpha < 100) {\n                hsv.a = (alpha + step) >= 1 ? 1 : alpha + step;\n                this.setColorAsHsv(hsv);\n            }\n            return false;\n        }\n    };\n\n    ColorEditor.prototype._bindKeyHandler = function ($element, handler) {\n        $element.bind(\"keydown\", handler);\n    };\n\n    // Prevent clicks on some UI elements (color selection field, slider and large swatch) from taking focus\n    $(window.document).on(\"mousedown\", \".color-selection-field, .slider, .large-swatch\", function (e) {\n        e.preventDefault();\n    });\n\n    exports.ColorEditor = ColorEditor;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/ColorEditorTemplate.html",
    "content": "\n<div tabindex=\"-1\" class=\"color-editor\">\n  <section>\n    <div class=\"sliders\">\n      <div class=\"color-selection-field\">\n        <div class=\"saturation-gradient gradient-overlay\"></div>\n        <div class=\"luminosity-gradient gradient-overlay\"></div>\n        <div tabindex=\"0\" class=\"selector-base\">\n          <div class=\"selector\"></div>\n        </div>\n      </div>\n      <div class=\"hue-slider slider\">\n        <div tabindex=\"0\" class=\"selector-base\">\n          <div class=\"selector\"></div>\n        </div>\n      </div>\n      <div class=\"opacity-slider slider\">\n        <div class=\"opacity-gradient gradient-overlay\"></div>\n        <div tabindex=\"0\" class=\"selector-base\">\n          <div class=\"selector\"></div>\n        </div>\n      </div>\n    </div>\n    <footer>\n      <input class=\"color-value\" />\n      <ul class=\"button-bar\">\n        <li class=\"selected\" title=\"{{COLOR_EDITOR_RGBA_BUTTON_TIP}}\"><a href=\"#\" tabindex=\"0\" class=\"rgba\">RGBa</a></li>\n        <li title=\"{{COLOR_EDITOR_HEX_BUTTON_TIP}}\"><a href=\"#\" tabindex=\"0\" class=\"hex\">Hex</a></li>\n        <li title=\"{{COLOR_EDITOR_HSLA_BUTTON_TIP}}\"><a href=\"#\" tabindex=\"0\" class=\"hsla\">HSLa</a></li>\n        <li title=\"{{COLOR_EDITOR_0X_BUTTON_TIP}}\"><a href=\"#\" tabindex=\"0\" class=\"0x\">0x</a></li>\n      </ul>\n    </footer>\n  </section>\n  <aside>\n    <header>\n      <div class=\"large-swatches\">\n        <div class=\"current-color large-swatch\" title=\"{{COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP}}\"></div>\n        <div class=\"original-color large-swatch\" title=\"{{COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP}}\"></div>\n      </div>\n    </header>\n    <ul class=\"swatches\"></ul>\n  </aside>\n</div>"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/InlineColorEditor.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var InlineWidget         = brackets.getModule(\"editor/InlineWidget\").InlineWidget,\n        ColorEditor          = require(\"ColorEditor\").ColorEditor,\n        ColorUtils           = brackets.getModule(\"utils/ColorUtils\");\n\n\n    /** @const @type {number} */\n    var MAX_USED_COLORS = 7;\n\n    /** @type {number} Global var used to provide a unique ID for each color editor instance's _origin field. */\n    var lastOriginId = 1;\n\n    /**\n     * Inline widget containing a ColorEditor control\n     * @param {!string} color  Initially selected color\n     * @param {!CodeMirror.TextMarker} marker\n     */\n    function InlineColorEditor(color, marker) {\n        this._color = color;\n        this._marker = marker;\n        this._isOwnChange = false;\n        this._isHostChange = false;\n        this._origin = \"+InlineColorEditor_\" + (lastOriginId++);\n\n        this._handleColorChange = this._handleColorChange.bind(this);\n        this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this);\n\n        InlineWidget.call(this);\n    }\n\n    InlineColorEditor.prototype = Object.create(InlineWidget.prototype);\n    InlineColorEditor.prototype.constructor = InlineColorEditor;\n    InlineColorEditor.prototype.parentClass = InlineWidget.prototype;\n\n    /** @type {!ColorPicker} ColorPicker instance */\n    InlineColorEditor.prototype.colorEditor = null;\n\n    /** @type {!string} Current value of the color picker control */\n    InlineColorEditor.prototype._color = null;\n\n    /**\n     * Range of code we're attached to; _marker.find() may by null if sync is lost.\n     * @type {!CodeMirror.TextMarker}\n     */\n    InlineColorEditor.prototype._marker = null;\n\n    /** @type {boolean} True while we're syncing a color picker change into the code editor */\n    InlineColorEditor.prototype._isOwnChange = null;\n\n    /** @type {boolean} True while we're syncing a code editor change into the color picker */\n    InlineColorEditor.prototype._isHostChange = null;\n\n    /** @type {number} ID used to identify edits coming from this inline widget for undo batching */\n    InlineColorEditor.prototype._origin = null;\n\n\n    /**\n     * Returns the current text range of the color we're attached to, or null if\n     * we've lost sync with what's in the code.\n     * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}}\n     */\n    InlineColorEditor.prototype.getCurrentRange = function () {\n        var pos, start, end;\n\n        pos = this._marker && this._marker.find();\n\n        start = pos && pos.from;\n        if (!start) {\n            return null;\n        }\n\n        end = pos.to;\n        if (!end) {\n            end = {line: start.line};\n        }\n\n        // Even if we think we have a good range end, we want to run the\n        // regexp match to see if there's a valid match that extends past the marker.\n        // This can happen if the user deletes the end of the existing color and then\n        // types some more.\n\n        var line = this.hostEditor.document.getLine(start.line),\n            matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX);\n\n        // Note that end.ch is exclusive, so we don't need to add 1 before comparing to\n        // the matched length here.\n        if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) {\n            end.ch = start.ch + matches[0].length;\n            this._marker.clear();\n            this._marker = this.hostEditor._codeMirror.markText(start, end);\n        }\n\n        if (end.ch === undefined) {\n            // We were unable to resync the marker.\n            return null;\n        } else {\n            return {start: start, end: end};\n        }\n    };\n\n    /**\n     * When the color picker's selected color changes, update text in code editor\n     * @param {!string} colorString\n     */\n    InlineColorEditor.prototype._handleColorChange = function (colorString) {\n        var self = this;\n        if (colorString !== this._color) {\n            var range = this.getCurrentRange();\n\n            if (!range) {\n                return;\n            }\n\n            // Don't push the change back into the host editor if it came from the host editor.\n            if (!this._isHostChange) {\n                var endPos = {\n                        line: range.start.line,\n                        ch: range.start.ch + colorString.length\n                    };\n                this._isOwnChange = true;\n                this.hostEditor.document.batchOperation(function () {\n                    // Replace old color in code with the picker's color, and select it\n                    self.hostEditor.setSelection(range.start, range.end); // workaround for #2805\n                    self.hostEditor.document.replaceRange(colorString, range.start, range.end, self._origin);\n                    self.hostEditor.setSelection(range.start, endPos);\n                    if (self._marker) {\n                        self._marker.clear();\n                        self._marker = self.hostEditor._codeMirror.markText(range.start, endPos);\n                    }\n                });\n                this._isOwnChange = false;\n            }\n\n            this._color = colorString;\n        }\n    };\n\n    /**\n     * @override\n     * @param {!Editor} hostEditor\n     */\n    InlineColorEditor.prototype.load = function (hostEditor) {\n        InlineColorEditor.prototype.parentClass.load.apply(this, arguments);\n\n        // Create color picker control\n        var allColorsInDoc = this.hostEditor.document.getText().match(ColorUtils.COLOR_REGEX);\n        var swatchInfo = this._collateColors(allColorsInDoc, MAX_USED_COLORS);\n        this.colorEditor = new ColorEditor(this.$htmlContent, this._color, this._handleColorChange, swatchInfo);\n    };\n\n    /**\n     * @override\n     * Perform sizing & focus once we've been added to Editor's DOM\n     */\n    InlineColorEditor.prototype.onAdded = function () {\n        InlineColorEditor.prototype.parentClass.onAdded.apply(this, arguments);\n\n        var doc = this.hostEditor.document;\n        doc.addRef();\n        doc.on(\"change\", this._handleHostDocumentChange);\n\n        this.hostEditor.setInlineWidgetHeight(this, this.colorEditor.getRootElement().outerHeight(), true);\n\n        this.colorEditor.focus();\n    };\n\n    /**\n     * @override\n     * Called whenever the inline widget is closed, whether automatically or explicitly\n     */\n    InlineColorEditor.prototype.onClosed = function () {\n        InlineColorEditor.prototype.parentClass.onClosed.apply(this, arguments);\n\n        if (this._marker) {\n            this._marker.clear();\n        }\n\n        var doc = this.hostEditor.document;\n        doc.off(\"change\", this._handleHostDocumentChange);\n        doc.releaseRef();\n        this.colorEditor.destroy();\n    };\n\n    /** Comparator to sort by which colors are used the most */\n    function _colorSort(a, b) {\n        if (a.count === b.count) {\n            return 0;\n        }\n        if (a.count > b.count) {\n            return -1;\n        }\n        if (a.count < b.count) {\n            return 1;\n        }\n    }\n\n    /**\n     * Counts how many times each color in originalArray occurs (ignoring case) and\n     * retuns the top 'maxLength' number of unique colors.\n     * @param {!Array.<string>} originalArray\n     * @param {number} maxLength\n     * @return {!Array.<{value:string, count:number}>}\n     */\n    InlineColorEditor.prototype._collateColors = function (originalArray, maxLength) {\n        // Maps from lowercase color name to swatch info (user-case color name & occurrence count)\n        /* @type {Object.<string, {value:string, count:number}>} */\n        var colorInfo = {};\n\n        // Count how many times each color is used\n        originalArray.forEach(function (originalColor) {\n            var key = originalColor.toLowerCase();\n            if (colorInfo[key]) {\n                colorInfo[key].count++;\n            } else {\n                colorInfo[key] = { value: originalColor, count: 1 };\n            }\n        });\n\n        // Convert to an array\n        var uniqueColors = $.map(colorInfo, function (info) {\n            return info;\n        });\n\n        // Sort by most-used and return the top N\n        uniqueColors.sort(_colorSort);\n        return uniqueColors.slice(0, maxLength);\n    };\n\n    /**\n     * When text in the code editor changes, update color picker to reflect it\n     */\n    InlineColorEditor.prototype._handleHostDocumentChange = function () {\n        // Don't push the change into the color editor if it came from the color editor.\n        if (this._isOwnChange) {\n            return;\n        }\n\n        var range = this.getCurrentRange();\n        if (range) {\n            var newColor = this.hostEditor.document.getRange(range.start, range.end);\n            if (newColor !== this._color) {\n                if (this.colorEditor.isValidColor(newColor)) { // only update the editor if the color string is valid\n                    this._isHostChange = true;\n                    this.colorEditor.setColorFromString(newColor);\n                    this._isHostChange = false;\n                }\n            }\n        } else {\n            // The edit caused our range to become invalid. Close the editor.\n            this.close();\n        }\n    };\n\n    exports.InlineColorEditor = InlineColorEditor;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/css/main.less",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n.color-editor {\n    font-size: 12px;\n    min-width: 450px;\n    height: 190px;\n    padding: 16px 16px 14px 46px;\n}\n.color-editor:focus {\n    outline: none;\n}\n.color-editor aside {\n    display: inline-block;\n    position: relative;\n    height: 100%;\n    overflow: visible;\n    margin-left: 6px;\n    vertical-align: top;\n}\n.color-editor aside header {\n    width: 100%;\n    overflow: hidden;\n    margin-bottom: 10px;\n}\n.color-editor aside header .large-swatches {\n    border-radius: 3px;\n    background-image: url(\"../img/color_thumb_back.png\");\n    background-size: 8px;\n    height: 35px;\n    width: 88px;\n    margin-right: 9px;\n    display: inline-block;\n    position: relative;\n    overflow: hidden;\n    -webkit-background-clip: padding-box;\n    background-clip: padding-box;\n    border-bottom: 1px solid rgba(255, 255, 255, 0.5);\n}\n.color-editor aside header .large-swatch {\n    width: 50%;\n    height: 100%;\n    position: absolute;\n    box-shadow: inset 0 1px 0 rgba(0,0,0,0.2);\n}\n.color-editor aside header .current-color {\n    border-radius: 3px 0px 0px 3px;\n    left: 0;\n    top: 0;\n}\n.color-editor aside header .original-color {\n    border-radius: 0px 3px 3px 0px;\n    right: 0;\n    top: 0;\n}\n.color-editor aside ul.swatches {\n    list-style: none;\n}\n.color-editor aside ul.swatches li {\n    height: 18px;\n    margin-bottom: 2px;\n    padding: 0 1px 1px 2px;\n}\n.color-editor aside ul.swatches li:focus {\n    outline: none;\n    box-shadow: 0 0 0 1px #94ceff;\n    border-radius: 2px;\n}\n.color-editor aside ul.swatches li .swatch-bg {\n    background-image: url(\"../img/color_thumb_back.png\");\n    background-size: 8px;\n    width: 15px;\n    height: 15px;\n    border-radius: 3px;\n    position: relative;\n    top: 2px;\n    display: inline-block;\n}\n.color-editor aside ul.swatches li .swatch-bg .swatch {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    border-radius: 3px;\n    box-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;\n    top: 0;\n}\n.color-editor aside ul.swatches li .value {\n    left: -3px;\n    position: relative;\n    top: -1px;\n}\n.color-editor section {\n    display: inline-block;\n    position: relative;\n    vertical-align: top;\n}\n.color-editor section .sliders {\n    position: relative;\n    clear: both;\n}\n.color-editor section .gradient-overlay {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    border-radius: 3px;\n    box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12), 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n.color-editor section .color-selection-field {\n    width: 181px;\n    height: 156px;\n    margin-right: 13px;\n    display: block;\n    border-radius: 4px;\n    position: relative;\n    float: left;\n}\n.color-editor section .color-selection-field .saturation-gradient {\n    background-image: linear-gradient(to left, hsla(0,0%,100%,0), #fff);\n}\n.color-editor section .color-selection-field .luminosity-gradient {\n    background-image: linear-gradient(hsla(0,0%,100%,0), #000);\n}\n.color-editor section .color-selection-field .selector-base {\n    width: 12px;\n    height: 12px;\n    background-color: #fff;\n    position: absolute;\n    margin-bottom: -8px;\n    margin-left: -5px;\n}\n.color-editor section .color-selection-field .selector-base:focus {\n    outline: none;\n    box-shadow: 0 0 0 5px #94ceff;\n    border-radius: 10px;\n}\n.color-editor section .color-selection-field .selector {\n    width: 19px;\n    height: 19px;\n    position: absolute;\n    left: -4px;\n    top: -4px;\n    background-image: url(\"../img/grabber_color-well.png\");\n}\n.color-editor section .slider {\n    border-radius: 3px;\n    border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n    box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);      \n    width: 12px;\n    height: 156px;\n    margin-right: 13px;\n    background-color: #ccc;\n    display: block;\n    box-shadow: 0 1px 0 #fff, inset 0 1px 0 rgba(0,0,0,0.2);\n    float: left;\n    position: relative;\n}\n.color-editor section .slider .selector-base {\n    width: 14px;\n    height: 6px;\n    background-color: transparent;\n    position: absolute;\n    margin: -1px -6px -4px -1px;\n}\n.color-editor section .slider .selector-base:focus {\n    outline: none;\n    box-shadow: 0 0 0 5px #94ceff;\n    border-radius: 1px;\n}\n.color-editor section .slider .selector {\n    width: 20px;\n    height: 12px;\n    left: -3px;\n    top: -3px;\n    position: absolute;\n    background-image: url(\"../img/grabber_color-slider.png\");\n}\n.color-editor section .slider.opacity-slider {\n    background-image: url(\"../img/color_thumb_back.png\");\n    background-size: 8px;\n    margin-right: 0px;  \n}\n.color-editor section .hue-slider {\n    background-image: linear-gradient(#f00, #f0f, #00f, #0ff, #0f0, #ff0, #f00);\n}\n.color-editor section footer {\n    font-size: 100%;\n    clear: both;\n    line-height: normal;\n    padding-top: 10px;\n}\n.color-editor section footer .color-value {\n    width: 118px;\n    height: 23px;\n    margin-right: 5px;\n    border-color: #b2b5b5;\n    box-sizing: border-box;\n    display: inline-block;\n    color: #222;\n}\n.color-editor section footer input {\n    display: inline-block;\n    height: 23px;\n    padding: 0 0 0 4px;\n    border: 1px solid #b2b5b5;\n    box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.06);\n    background: #fff;\n    font-family: \"SourceSansPro\";\n    font-size: 12px;\n    color: #454545;\n    border-radius: 3px;\n    margin: 0;\n    vertical-align: middle;\n}\n.color-editor section footer input:focus {\n    background: #fff;\n    outline: none;\n    box-shadow: 0 0 0 1px #94ceff;\n    border: 1px solid #2893ef;\n    z-index: 911;\n}\n@media all and (-webkit-min-device-pixel-ratio : 2), (min-device-pixel-ratio : 2) {\n    .color-editor aside header .large-swatches {\n        background-image: url(\"../img/color_thumb_back@2x.png\");\n    }\n    .color-editor aside ul.swatches li .swatch-bg {\n        background-image: url(\"../img/color_thumb_back@2x.png\");\n    }\n    .color-editor section .color-selection-field .selector {\n        background-image: url(\"../img/grabber_color-well@2x.png\");\n        background-size: 100% 100%;\n    }\n    .color-editor section .slider .selector {\n        background-image: url(\"../img/grabber_color-slider@2x.png\");\n        background-size: 200% 100%;\n    }\n    .color-editor section .slider.opacity-slider {\n        background-image: url(\"../img/color_thumb_back@2x.png\");\n    }\n}\n.color-editor ul, .color-editor li {\n    margin: 0;\n    padding: 0;\n    border: 0;\n    outline: 0;\n    font-size: 100%;\n    vertical-align: middle;\n    background: transparent;\n    -webkit-font-smoothing: antialiased;\n}\n.color-editor ul.button-bar {\n    list-style: none;\n    border-radius: 3px;\n    display: inline-block;\n    font-size: 12px;\n    margin-left: -3px;\n}\n.color-editor .button-bar li {\n    display: inline-block;\n    margin-left: -4px;\n}\n.color-editor .button-bar a {\n    text-decoration: none;\n    color: #454545;\n    cursor: default;\n    display: block;\n    padding: 2px 4px 4px;\n    height: 15px;\n    font-size: 12px;\n    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.76);\n    background-color: #e5e9e9;\n    border: 1px solid #b2b5b5;\n    border-right: 1px solid transparent;\n    margin-left: -3px;\n    \n    box-shadow: inset 0 1px 0 #f3f3f3;\n}\n\n.color-editor .button-bar a:focus, .color-editor .button-bar li.selected a:focus{\n    outline: none;\n    position: relative;\n    border: 1px solid #2893ef;\n    border-right: 1px solid #2893ef !important; /* we need this !important, sorry! */\n    box-shadow: 0 0 0 1px #94ceff;\n    z-index: 999;\n}\n.color-editor .button-bar li:first-child {\n    margin-left: 0;\n}\n.color-editor .button-bar li:first-child a {\n    margin-left: 0;\n    border-top-left-radius: 3px;\n    border-bottom-left-radius: 3px;\n}\n.color-editor .button-bar li:last-child a {\n    border-right: 1px solid #b2b5b5;\n    border-top-right-radius: 3px;\n    border-bottom-right-radius: 3px;\n}\n.color-editor .button-bar li.selected a {\n    background-color: #e0f0fa;\n    box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.06);\n    background-image: none;\n    color: #0083e8;\n}\n.color-editor .button-bar li.disabled a {\n    cursor: default;\n    opacity: 0.3;\n}\n\n\n.color-editor .platform-mac .CodeMirror {\n    font-family: \"SourceSansPro\" !important;\n}\n\n// Dark UI theme\n\n@dark-bc-bg-highlight: #2a3b50;\n@dark-bc-highlight: rgba(255, 255, 255, 0.06);\n@dark-bc-text: #ccc;\n@dark-bc-text-alt: #fff;\n@dark-bc-highlight-hard: rgba(255, 255, 255, 0.2);\n@dark-bc-btn-bg: #3f3f3f;\n@dark-bc-btn-border: #202020;\n@dark-bc-btn-border-focused: #2893ef;\n@dark-bc-btn-border-focused-glow: transparent;\n@dark-bc-shadow: rgba(0, 0, 0, 0.24);\n@dark-bc-shadow-small: rgba(0, 0, 0, 0.06);\n@dark-bc-shadow-medium: rgba(0, 0, 0, 0.12);\n@dark-bc-input-bg: #555;\n\n@dark-swatch-bg: url(\"../img/color_thumb_back_dark.png\");\n@dark-swatch-bg-2x: url(\"../img/color_thumb_back_dark@2x.png\");\n\n.dark {\n    .color-editor aside header .large-swatches,\n    .color-editor aside ul.swatches li .swatch-bg,\n    .color-editor section .slider.opacity-slider {\n        background-image: @dark-swatch-bg;\n    }\n    \n    .color-editor aside header .large-swatches {\n        border-bottom: 1px solid @dark-bc-highlight;\n    }\n\n    .color-editor ul.swatches li .value {\n        color: @dark-bc-text;\n    }\n\n    .color-editor section .gradient-overlay {\n        box-shadow: 0 1px 0 @dark-bc-highlight, inset 0 1px 0 @dark-bc-shadow-medium;\n    }\n\n    .color-editor aside ul.swatches li .swatch-bg .swatch {\n        box-shadow: 0 -1px 1px @dark-bc-shadow-small, 0 1px 0 @dark-bc-highlight;\n    }\n\n    .color-editor aside ul.swatches li:focus {\n        outline: 1px solid @dark-bc-btn-border-focused;\n        box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow;\n    }\n\n    .color-editor section .color-selection-field .selector-base {\n        color: @dark-bc-input-bg;\n    }\n\n    .color-editor section .color-selection-field .selector-base:focus {\n        box-shadow: 0 0 0 5px @dark-bc-btn-border-focused;\n    }\n\n    .color-editor section .slider {\n        border-bottom: 1px solid @dark-bc-highlight-hard;\n        box-shadow: 0 -1px 0 @dark-bc-shadow-small;\n        background-color: @dark-bc-highlight-hard;\n        box-shadow: 0 1px 0 @dark-bc-highlight-hard, inset 0 1px 0 @dark-bc-shadow;\n    }\n\n    .color-editor section .slider .selector-base:focus {\n        box-shadow: 0 0 0 5px @dark-bc-btn-border-focused;\n    }\n\n    .color-editor section footer .color-value {\n        border-color: @dark-bc-btn-border;\n        color: @dark-bc-text;\n    }\n\n    .color-editor section footer input {\n        border: 1px solid @dark-bc-btn-border;\n        box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n        background: @dark-bc-input-bg;\n        color: @dark-bc-text;\n    }\n\n    .color-editor section footer input:focus {\n        background: @dark-bc-input-bg;\n        box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow;\n        border: 1px solid @dark-bc-btn-border-focused;\n    }\n\n    .color-editor .button-bar a {\n        color: @dark-bc-text;\n        text-shadow: 0 1px 0 @dark-bc-highlight;\n        background-color: @dark-bc-btn-bg;\n        border: 1px solid @dark-bc-btn-border;\n        border-right: 1px solid transparent;\n        box-shadow: inset 0 1px 0 @dark-bc-highlight;\n    }\n\n    .color-editor .button-bar a:focus, .color-editor .button-bar li.selected a:focus {\n        border: 1px solid @dark-bc-btn-border-focused;\n        border-right: 1px solid @dark-bc-btn-border-focused !important; /* we need this !important, sorry! */\n        box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow;\n    }\n\n    .color-editor .button-bar li:last-child a {\n        border-right: 1px solid @dark-bc-btn-border;\n    }\n\n    .color-editor .button-bar li.selected a {\n        background-color: @dark-bc-bg-highlight;\n        box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n        color: @dark-bc-text-alt;\n    }\n}\n\n@media all and (-webkit-min-device-pixel-ratio : 2), (min-device-pixel-ratio : 2) {\n    .dark {\n        .color-editor aside header .large-swatches {\n            background-image: @dark-swatch-bg-2x;\n        }\n\n        .color-editor aside ul.swatches li .swatch-bg {\n            background-image: @dark-swatch-bg-2x;\n        }\n\n        .color-editor section .slider.opacity-slider {\n            background-image: @dark-swatch-bg-2x;\n        }\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        InlineColorEditor   = require(\"InlineColorEditor\").InlineColorEditor,\n        ColorUtils          = brackets.getModule(\"utils/ColorUtils\");\n\n\n    /**\n     * Prepare hostEditor for an InlineColorEditor at pos if possible. Return\n     * editor context if so; otherwise null.\n     *\n     * @param {Editor} hostEditor\n     * @param {{line:Number, ch:Number}} pos\n     * @return {?{color:String, marker:TextMarker}}\n     */\n    function prepareEditorForProvider(hostEditor, pos) {\n        var colorRegEx, cursorLine, match, sel, start, end, endPos, marker;\n\n        sel = hostEditor.getSelection();\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n\n        colorRegEx = new RegExp(ColorUtils.COLOR_REGEX);\n        cursorLine = hostEditor.document.getLine(pos.line);\n\n        // Loop through each match of colorRegEx and stop when the one that contains pos is found.\n        do {\n            match = colorRegEx.exec(cursorLine);\n            if (match) {\n                start = match.index;\n                end = start + match[0].length;\n            }\n        } while (match && (pos.ch < start || pos.ch > end));\n\n        if (!match) {\n            return null;\n        }\n\n        // Adjust pos to the beginning of the match so that the inline editor won't get\n        // dismissed while we're updating the color with the new values from user's inline editing.\n        pos.ch = start;\n        endPos = {line: pos.line, ch: end};\n\n        marker = hostEditor._codeMirror.markText(pos, endPos);\n        hostEditor.setSelection(pos, endPos);\n\n        return {\n            color: match[0],\n            marker: marker\n        };\n    }\n\n    /**\n     * Registered as an inline editor provider: creates an InlineEditorColor when the cursor\n     * is on a color value (in any flavor of code).\n     *\n     * @param {!Editor} hostEditor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {?$.Promise} synchronously resolved with an InlineWidget, or null if there's\n     *      no color at pos.\n     */\n    function inlineColorEditorProvider(hostEditor, pos) {\n        var context = prepareEditorForProvider(hostEditor, pos),\n            inlineColorEditor,\n            result;\n\n        if (!context) {\n            return null;\n        } else {\n            inlineColorEditor = new InlineColorEditor(context.color, context.marker);\n            inlineColorEditor.load(hostEditor);\n\n            result = new $.Deferred();\n            result.resolve(inlineColorEditor);\n            return result.promise();\n        }\n    }\n\n\n    // Initialize extension\n    ExtensionUtils.loadStyleSheet(module, \"css/main.less\");\n\n    EditorManager.registerInlineEditProvider(inlineColorEditorProvider);\n\n    // for use by other InlineColorEditors\n    exports.prepareEditorForProvider = prepareEditorForProvider;\n\n    // for unit tests only\n    exports.inlineColorEditorProvider = inlineColorEditorProvider;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/thirdparty/tinycolor-min.js",
    "content": "// TinyColor v1.1.1\n// https://github.com/bgrins/TinyColor\n// 2014-12-20, Brian Grinstead, MIT License\n!function(){function inputToRGB(color){var rgb={r:0,g:0,b:0},a=1,ok=!1,format=!1;return\"string\"==typeof color&&(color=stringInputToObject(color)),\"object\"==typeof color&&(color.hasOwnProperty(\"r\")&&color.hasOwnProperty(\"g\")&&color.hasOwnProperty(\"b\")?(rgb=rgbToRgb(color.r,color.g,color.b),ok=!0,format=\"%\"===String(color.r).substr(-1)?\"prgb\":\"rgb\"):color.hasOwnProperty(\"h\")&&color.hasOwnProperty(\"s\")&&color.hasOwnProperty(\"v\")?(color.s=convertToPercentage(color.s),color.v=convertToPercentage(color.v),rgb=hsvToRgb(color.h,color.s,color.v),ok=!0,format=\"hsv\"):color.hasOwnProperty(\"h\")&&color.hasOwnProperty(\"s\")&&color.hasOwnProperty(\"l\")&&(color.s=convertToPercentage(color.s),color.l=convertToPercentage(color.l),rgb=hslToRgb(color.h,color.s,color.l),ok=!0,format=\"hsl\"),color.hasOwnProperty(\"a\")&&(a=color.a)),a=boundAlpha(a),{ok:ok,format:color.format||format,r:mathMin(255,mathMax(rgb.r,0)),g:mathMin(255,mathMax(rgb.g,0)),b:mathMin(255,mathMax(rgb.b,0)),a:a}}function rgbToRgb(r,g,b){return{r:255*bound01(r,255),g:255*bound01(g,255),b:255*bound01(b,255)}}function rgbToHsl(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),l=(max+min)/2;if(max==min)h=s=0;else{var d=max-min;switch(s=l>.5?d/(2-max-min):d/(max+min),max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,l:l}}function hslToRgb(h,s,l){function hue2rgb(p,q,t){return 0>t&&(t+=1),t>1&&(t-=1),1/6>t?p+6*(q-p)*t:.5>t?q:2/3>t?p+(q-p)*(2/3-t)*6:p}var r,g,b;if(h=bound01(h,360),s=bound01(s,100),l=bound01(l,100),0===s)r=g=b=l;else{var q=.5>l?l*(1+s):l+s-l*s,p=2*l-q;r=hue2rgb(p,q,h+1/3),g=hue2rgb(p,q,h),b=hue2rgb(p,q,h-1/3)}return{r:255*r,g:255*g,b:255*b}}function rgbToHsv(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),v=max,d=max-min;if(s=0===max?0:d/max,max==min)h=0;else{switch(max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,v:v}}function hsvToRgb(h,s,v){h=6*bound01(h,360),s=bound01(s,100),v=bound01(v,100);var i=math.floor(h),f=h-i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s),mod=i%6,r=[v,q,p,p,t,v][mod],g=[t,v,v,q,p,p][mod],b=[p,p,t,v,v,q][mod];return{r:255*r,g:255*g,b:255*b}}function rgbToHex(r,g,b,allow3Char){var hex=[pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return allow3Char&&hex[0].charAt(0)==hex[0].charAt(1)&&hex[1].charAt(0)==hex[1].charAt(1)&&hex[2].charAt(0)==hex[2].charAt(1)?hex[0].charAt(0)+hex[1].charAt(0)+hex[2].charAt(0):hex.join(\"\")}function rgbaToHex(r,g,b,a){var hex=[pad2(convertDecimalToHex(a)),pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return hex.join(\"\")}function desaturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s-=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function saturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s+=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function greyscale(color){return tinycolor(color).desaturate(100)}function lighten(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l+=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function brighten(color,amount){amount=0===amount?0:amount||10;var rgb=tinycolor(color).toRgb();return rgb.r=mathMax(0,mathMin(255,rgb.r-mathRound(255*-(amount/100)))),rgb.g=mathMax(0,mathMin(255,rgb.g-mathRound(255*-(amount/100)))),rgb.b=mathMax(0,mathMin(255,rgb.b-mathRound(255*-(amount/100)))),tinycolor(rgb)}function darken(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l-=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function spin(color,amount){var hsl=tinycolor(color).toHsl(),hue=(mathRound(hsl.h)+amount)%360;return hsl.h=0>hue?360+hue:hue,tinycolor(hsl)}function complement(color){var hsl=tinycolor(color).toHsl();return hsl.h=(hsl.h+180)%360,tinycolor(hsl)}function triad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+120)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+240)%360,s:hsl.s,l:hsl.l})]}function tetrad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+90)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+180)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+270)%360,s:hsl.s,l:hsl.l})]}function splitcomplement(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+72)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+216)%360,s:hsl.s,l:hsl.l})]}function analogous(color,results,slices){results=results||6,slices=slices||30;var hsl=tinycolor(color).toHsl(),part=360/slices,ret=[tinycolor(color)];for(hsl.h=(hsl.h-(part*results>>1)+720)%360;--results;)hsl.h=(hsl.h+part)%360,ret.push(tinycolor(hsl));return ret}function monochromatic(color,results){results=results||6;for(var hsv=tinycolor(color).toHsv(),h=hsv.h,s=hsv.s,v=hsv.v,ret=[],modification=1/results;results--;)ret.push(tinycolor({h:h,s:s,v:v})),v=(v+modification)%1;return ret}function flip(o){var flipped={};for(var i in o)o.hasOwnProperty(i)&&(flipped[o[i]]=i);return flipped}function boundAlpha(a){return a=parseFloat(a),(isNaN(a)||0>a||a>1)&&(a=1),a}function bound01(n,max){isOnePointZero(n)&&(n=\"100%\");var processPercent=isPercentage(n);return n=mathMin(max,mathMax(0,parseFloat(n))),processPercent&&(n=parseInt(n*max,10)/100),math.abs(n-max)<1e-6?1:n%max/parseFloat(max)}function clamp01(val){return mathMin(1,mathMax(0,val))}function parseIntFromHex(val){return parseInt(val,16)}function isOnePointZero(n){return\"string\"==typeof n&&-1!=n.indexOf(\".\")&&1===parseFloat(n)}function isPercentage(n){return\"string\"==typeof n&&-1!=n.indexOf(\"%\")}function pad2(c){return 1==c.length?\"0\"+c:\"\"+c}function convertToPercentage(n){return 1>=n&&(n=100*n+\"%\"),n}function convertDecimalToHex(d){return Math.round(255*parseFloat(d)).toString(16)}function convertHexToDecimal(h){return parseIntFromHex(h)/255}function stringInputToObject(color){color=color.replace(trimLeft,\"\").replace(trimRight,\"\").toLowerCase();var named=!1;if(names[color])color=names[color],named=!0;else if(\"transparent\"==color)return{r:0,g:0,b:0,a:0,format:\"name\"};var match;return(match=matchers.rgb.exec(color))?{r:match[1],g:match[2],b:match[3]}:(match=matchers.rgba.exec(color))?{r:match[1],g:match[2],b:match[3],a:match[4]}:(match=matchers.hsl.exec(color))?{h:match[1],s:match[2],l:match[3]}:(match=matchers.hsla.exec(color))?{h:match[1],s:match[2],l:match[3],a:match[4]}:(match=matchers.hsv.exec(color))?{h:match[1],s:match[2],v:match[3]}:(match=matchers.hsva.exec(color))?{h:match[1],s:match[2],v:match[3],a:match[4]}:(match=matchers.hex8.exec(color))?{a:convertHexToDecimal(match[1]),r:parseIntFromHex(match[2]),g:parseIntFromHex(match[3]),b:parseIntFromHex(match[4]),format:named?\"name\":\"hex8\"}:(match=matchers.hex6.exec(color))?{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),format:named?\"name\":\"hex\"}:(match=matchers.hex3.exec(color))?{r:parseIntFromHex(match[1]+\"\"+match[1]),g:parseIntFromHex(match[2]+\"\"+match[2]),b:parseIntFromHex(match[3]+\"\"+match[3]),format:named?\"name\":\"hex\"}:!1}var trimLeft=/^[\\s,#]+/,trimRight=/\\s+$/,tinyCounter=0,math=Math,mathRound=math.round,mathMin=math.min,mathMax=math.max,mathRandom=math.random,tinycolor=function tinycolor(color,opts){if(color=color?color:\"\",opts=opts||{},color instanceof tinycolor)return color;if(!(this instanceof tinycolor))return new tinycolor(color,opts);var rgb=inputToRGB(color);this._originalInput=color,this._r=rgb.r,this._g=rgb.g,this._b=rgb.b,this._a=rgb.a,this._roundA=mathRound(100*this._a)/100,this._format=opts.format||rgb.format,this._gradientType=opts.gradientType,this._r<1&&(this._r=mathRound(this._r)),this._g<1&&(this._g=mathRound(this._g)),this._b<1&&(this._b=mathRound(this._b)),this._ok=rgb.ok,this._tc_id=tinyCounter++};tinycolor.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var rgb=this.toRgb();return(299*rgb.r+587*rgb.g+114*rgb.b)/1e3},setAlpha:function(value){return this._a=boundAlpha(value),this._roundA=mathRound(100*this._a)/100,this},toHsv:function(){var hsv=rgbToHsv(this._r,this._g,this._b);return{h:360*hsv.h,s:hsv.s,v:hsv.v,a:this._a}},toHsvString:function(){var hsv=rgbToHsv(this._r,this._g,this._b),h=mathRound(360*hsv.h),s=mathRound(100*hsv.s),v=mathRound(100*hsv.v);return 1==this._a?\"hsv(\"+h+\", \"+s+\"%, \"+v+\"%)\":\"hsva(\"+h+\", \"+s+\"%, \"+v+\"%, \"+this._roundA+\")\"},toHsl:function(){var hsl=rgbToHsl(this._r,this._g,this._b);return{h:360*hsl.h,s:hsl.s,l:hsl.l,a:this._a}},toHslString:function(){var hsl=rgbToHsl(this._r,this._g,this._b),h=mathRound(360*hsl.h),s=mathRound(100*hsl.s),l=mathRound(100*hsl.l);return 1==this._a?\"hsl(\"+h+\", \"+s+\"%, \"+l+\"%)\":\"hsla(\"+h+\", \"+s+\"%, \"+l+\"%, \"+this._roundA+\")\"},toHex:function(allow3Char){return rgbToHex(this._r,this._g,this._b,allow3Char)},toHexString:function(allow3Char){return\"#\"+this.toHex(allow3Char)},toHex8:function(){return rgbaToHex(this._r,this._g,this._b,this._a)},toHex8String:function(){return\"#\"+this.toHex8()},toRgb:function(){return{r:mathRound(this._r),g:mathRound(this._g),b:mathRound(this._b),a:this._a}},toRgbString:function(){return 1==this._a?\"rgb(\"+mathRound(this._r)+\", \"+mathRound(this._g)+\", \"+mathRound(this._b)+\")\":\"rgba(\"+mathRound(this._r)+\", \"+mathRound(this._g)+\", \"+mathRound(this._b)+\", \"+this._roundA+\")\"},toPercentageRgb:function(){return{r:mathRound(100*bound01(this._r,255))+\"%\",g:mathRound(100*bound01(this._g,255))+\"%\",b:mathRound(100*bound01(this._b,255))+\"%\",a:this._a}},toPercentageRgbString:function(){return 1==this._a?\"rgb(\"+mathRound(100*bound01(this._r,255))+\"%, \"+mathRound(100*bound01(this._g,255))+\"%, \"+mathRound(100*bound01(this._b,255))+\"%)\":\"rgba(\"+mathRound(100*bound01(this._r,255))+\"%, \"+mathRound(100*bound01(this._g,255))+\"%, \"+mathRound(100*bound01(this._b,255))+\"%, \"+this._roundA+\")\"},toName:function(){return 0===this._a?\"transparent\":this._a<1?!1:hexNames[rgbToHex(this._r,this._g,this._b,!0)]||!1},toFilter:function(secondColor){var hex8String=\"#\"+rgbaToHex(this._r,this._g,this._b,this._a),secondHex8String=hex8String,gradientType=this._gradientType?\"GradientType = 1, \":\"\";if(secondColor){var s=tinycolor(secondColor);secondHex8String=s.toHex8String()}return\"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=\"+hex8String+\",endColorstr=\"+secondHex8String+\")\"},toString:function(format){var formatSet=!!format;format=format||this._format;var formattedString=!1,hasAlpha=this._a<1&&this._a>=0,needsAlphaFormat=!formatSet&&hasAlpha&&(\"hex\"===format||\"hex6\"===format||\"hex3\"===format||\"name\"===format);return needsAlphaFormat?\"name\"===format&&0===this._a?this.toName():this.toRgbString():(\"rgb\"===format&&(formattedString=this.toRgbString()),\"prgb\"===format&&(formattedString=this.toPercentageRgbString()),(\"hex\"===format||\"hex6\"===format)&&(formattedString=this.toHexString()),\"hex3\"===format&&(formattedString=this.toHexString(!0)),\"hex8\"===format&&(formattedString=this.toHex8String()),\"name\"===format&&(formattedString=this.toName()),\"hsl\"===format&&(formattedString=this.toHslString()),\"hsv\"===format&&(formattedString=this.toHsvString()),formattedString||this.toHexString())},_applyModification:function(fn,args){var color=fn.apply(null,[this].concat([].slice.call(args)));return this._r=color._r,this._g=color._g,this._b=color._b,this.setAlpha(color._a),this},lighten:function(){return this._applyModification(lighten,arguments)},brighten:function(){return this._applyModification(brighten,arguments)},darken:function(){return this._applyModification(darken,arguments)},desaturate:function(){return this._applyModification(desaturate,arguments)},saturate:function(){return this._applyModification(saturate,arguments)},greyscale:function(){return this._applyModification(greyscale,arguments)},spin:function(){return this._applyModification(spin,arguments)},_applyCombination:function(fn,args){return fn.apply(null,[this].concat([].slice.call(args)))},analogous:function(){return this._applyCombination(analogous,arguments)},complement:function(){return this._applyCombination(complement,arguments)},monochromatic:function(){return this._applyCombination(monochromatic,arguments)},splitcomplement:function(){return this._applyCombination(splitcomplement,arguments)},triad:function(){return this._applyCombination(triad,arguments)},tetrad:function(){return this._applyCombination(tetrad,arguments)}},tinycolor.fromRatio=function(color,opts){if(\"object\"==typeof color){var newColor={};for(var i in color)color.hasOwnProperty(i)&&(newColor[i]=\"a\"===i?color[i]:convertToPercentage(color[i]));color=newColor}return tinycolor(color,opts)},tinycolor.equals=function(color1,color2){return color1&&color2?tinycolor(color1).toRgbString()==tinycolor(color2).toRgbString():!1},tinycolor.random=function(){return tinycolor.fromRatio({r:mathRandom(),g:mathRandom(),b:mathRandom()})},tinycolor.mix=function(color1,color2,amount){amount=0===amount?0:amount||50;var w1,rgb1=tinycolor(color1).toRgb(),rgb2=tinycolor(color2).toRgb(),p=amount/100,w=2*p-1,a=rgb2.a-rgb1.a;w1=w*a==-1?w:(w+a)/(1+w*a),w1=(w1+1)/2;var w2=1-w1,rgba={r:rgb2.r*w1+rgb1.r*w2,g:rgb2.g*w1+rgb1.g*w2,b:rgb2.b*w1+rgb1.b*w2,a:rgb2.a*p+rgb1.a*(1-p)};return tinycolor(rgba)},tinycolor.readability=function(color1,color2){var c1=tinycolor(color1),c2=tinycolor(color2),rgb1=c1.toRgb(),rgb2=c2.toRgb(),brightnessA=c1.getBrightness(),brightnessB=c2.getBrightness(),colorDiff=Math.max(rgb1.r,rgb2.r)-Math.min(rgb1.r,rgb2.r)+Math.max(rgb1.g,rgb2.g)-Math.min(rgb1.g,rgb2.g)+Math.max(rgb1.b,rgb2.b)-Math.min(rgb1.b,rgb2.b);return{brightness:Math.abs(brightnessA-brightnessB),color:colorDiff}},tinycolor.isReadable=function(color1,color2){var readability=tinycolor.readability(color1,color2);return readability.brightness>125&&readability.color>500},tinycolor.mostReadable=function(baseColor,colorList){for(var bestColor=null,bestScore=0,bestIsReadable=!1,i=0;i<colorList.length;i++){var readability=tinycolor.readability(baseColor,colorList[i]),readable=readability.brightness>125&&readability.color>500,score=3*(readability.brightness/125)+readability.color/500;(readable&&!bestIsReadable||readable&&bestIsReadable&&score>bestScore||!readable&&!bestIsReadable&&score>bestScore)&&(bestIsReadable=readable,bestScore=score,bestColor=tinycolor(colorList[i]))}return bestColor};var names=tinycolor.names={aliceblue:\"f0f8ff\",antiquewhite:\"faebd7\",aqua:\"0ff\",aquamarine:\"7fffd4\",azure:\"f0ffff\",beige:\"f5f5dc\",bisque:\"ffe4c4\",black:\"000\",blanchedalmond:\"ffebcd\",blue:\"00f\",blueviolet:\"8a2be2\",brown:\"a52a2a\",burlywood:\"deb887\",burntsienna:\"ea7e5d\",cadetblue:\"5f9ea0\",chartreuse:\"7fff00\",chocolate:\"d2691e\",coral:\"ff7f50\",cornflowerblue:\"6495ed\",cornsilk:\"fff8dc\",crimson:\"dc143c\",cyan:\"0ff\",darkblue:\"00008b\",darkcyan:\"008b8b\",darkgoldenrod:\"b8860b\",darkgray:\"a9a9a9\",darkgreen:\"006400\",darkgrey:\"a9a9a9\",darkkhaki:\"bdb76b\",darkmagenta:\"8b008b\",darkolivegreen:\"556b2f\",darkorange:\"ff8c00\",darkorchid:\"9932cc\",darkred:\"8b0000\",darksalmon:\"e9967a\",darkseagreen:\"8fbc8f\",darkslateblue:\"483d8b\",darkslategray:\"2f4f4f\",darkslategrey:\"2f4f4f\",darkturquoise:\"00ced1\",darkviolet:\"9400d3\",deeppink:\"ff1493\",deepskyblue:\"00bfff\",dimgray:\"696969\",dimgrey:\"696969\",dodgerblue:\"1e90ff\",firebrick:\"b22222\",floralwhite:\"fffaf0\",forestgreen:\"228b22\",fuchsia:\"f0f\",gainsboro:\"dcdcdc\",ghostwhite:\"f8f8ff\",gold:\"ffd700\",goldenrod:\"daa520\",gray:\"808080\",green:\"008000\",greenyellow:\"adff2f\",grey:\"808080\",honeydew:\"f0fff0\",hotpink:\"ff69b4\",indianred:\"cd5c5c\",indigo:\"4b0082\",ivory:\"fffff0\",khaki:\"f0e68c\",lavender:\"e6e6fa\",lavenderblush:\"fff0f5\",lawngreen:\"7cfc00\",lemonchiffon:\"fffacd\",lightblue:\"add8e6\",lightcoral:\"f08080\",lightcyan:\"e0ffff\",lightgoldenrodyellow:\"fafad2\",lightgray:\"d3d3d3\",lightgreen:\"90ee90\",lightgrey:\"d3d3d3\",lightpink:\"ffb6c1\",lightsalmon:\"ffa07a\",lightseagreen:\"20b2aa\",lightskyblue:\"87cefa\",lightslategray:\"789\",lightslategrey:\"789\",lightsteelblue:\"b0c4de\",lightyellow:\"ffffe0\",lime:\"0f0\",limegreen:\"32cd32\",linen:\"faf0e6\",magenta:\"f0f\",maroon:\"800000\",mediumaquamarine:\"66cdaa\",mediumblue:\"0000cd\",mediumorchid:\"ba55d3\",mediumpurple:\"9370db\",mediumseagreen:\"3cb371\",mediumslateblue:\"7b68ee\",mediumspringgreen:\"00fa9a\",mediumturquoise:\"48d1cc\",mediumvioletred:\"c71585\",midnightblue:\"191970\",mintcream:\"f5fffa\",mistyrose:\"ffe4e1\",moccasin:\"ffe4b5\",navajowhite:\"ffdead\",navy:\"000080\",oldlace:\"fdf5e6\",olive:\"808000\",olivedrab:\"6b8e23\",orange:\"ffa500\",orangered:\"ff4500\",orchid:\"da70d6\",palegoldenrod:\"eee8aa\",palegreen:\"98fb98\",paleturquoise:\"afeeee\",palevioletred:\"db7093\",papayawhip:\"ffefd5\",peachpuff:\"ffdab9\",peru:\"cd853f\",pink:\"ffc0cb\",plum:\"dda0dd\",powderblue:\"b0e0e6\",purple:\"800080\",rebeccapurple:\"663399\",red:\"f00\",rosybrown:\"bc8f8f\",royalblue:\"4169e1\",saddlebrown:\"8b4513\",salmon:\"fa8072\",sandybrown:\"f4a460\",seagreen:\"2e8b57\",seashell:\"fff5ee\",sienna:\"a0522d\",silver:\"c0c0c0\",skyblue:\"87ceeb\",slateblue:\"6a5acd\",slategray:\"708090\",slategrey:\"708090\",snow:\"fffafa\",springgreen:\"00ff7f\",steelblue:\"4682b4\",tan:\"d2b48c\",teal:\"008080\",thistle:\"d8bfd8\",tomato:\"ff6347\",turquoise:\"40e0d0\",violet:\"ee82ee\",wheat:\"f5deb3\",white:\"fff\",whitesmoke:\"f5f5f5\",yellow:\"ff0\",yellowgreen:\"9acd32\"},hexNames=tinycolor.hexNames=flip(names),matchers=function(){var CSS_INTEGER=\"[-\\\\+]?\\\\d+%?\",CSS_NUMBER=\"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\",CSS_UNIT=\"(?:\"+CSS_NUMBER+\")|(?:\"+CSS_INTEGER+\")\",PERMISSIVE_MATCH3=\"[\\\\s|\\\\(]+(\"+CSS_UNIT+\")[,|\\\\s]+(\"+CSS_UNIT+\")[,|\\\\s]+(\"+CSS_UNIT+\")\\\\s*\\\\)?\",PERMISSIVE_MATCH4=\"[\\\\s|\\\\(]+(\"+CSS_UNIT+\")[,|\\\\s]+(\"+CSS_UNIT+\")[,|\\\\s]+(\"+CSS_UNIT+\")[,|\\\\s]+(\"+CSS_UNIT+\")\\\\s*\\\\)?\";return{rgb:new RegExp(\"rgb\"+PERMISSIVE_MATCH3),rgba:new RegExp(\"rgba\"+PERMISSIVE_MATCH4),hsl:new RegExp(\"hsl\"+PERMISSIVE_MATCH3),hsla:new RegExp(\"hsla\"+PERMISSIVE_MATCH4),hsv:new RegExp(\"hsv\"+PERMISSIVE_MATCH3),hsva:new RegExp(\"hsva\"+PERMISSIVE_MATCH4),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();\"undefined\"!=typeof module&&module.exports?module.exports=tinycolor:\"function\"==typeof define&&define.amd?define(function(){return tinycolor}):window.tinycolor=tinycolor}();\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/unittest-files/unittests.css",
    "content": ".hex-rule {\n    background: #abcdef;\n}\n\n.hex-three-rule {\n    background: #abc;\n}\n\n.rgb-rule {\n    background: rgb(100, 200, 150);\n}\n\n.rgba-rule {\n    background: rgba(100, 200, 150, 0.5);\n}\n\n.hsl-rule {\n    background: hsl(180, 50%, 50%);\n}\n\n.hsla-rule {\n    background: hsla(180, 50%, 50%, 0.5);\n}\n\n.invalid-color {\n    background: rgb(150;\n}\n\n.multiple-colors {\n    background: linear-gradient(90deg, #aabbcc, #ddeeff);\n}\n\n.uppercase-hex {\n    background: #DEFCBA;\n}\n\n.missing-percent {\n    background: hsla(180, 50, 50, 0.5);\n}\n\n.in-shorthand {\n    border: 1px solid #0f0f0f;\n}\n\n.rgba-leading-period {\n    background: rgba(100, 200, 150, .5);\n}\n\n.hsla-leading-period {\n    background: hsla(180, 50%, 50%, .5);\n}\n"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/unittest-files/unittests.html",
    "content": "<!doctype html>\n<html>\n    <body>\n        <p>\n            <font color=\"#dead01\">\n                You're not supposed to put colors in your HTML, but we'll let you do it anyway.\n            </font>\n        </p>\n    </body>\n</html>"
  },
  {
    "path": "src/extensions/default/InlineColorEditor/unittests.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, waits, runs, waitsForDone, spyOn */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Modules from the SpecRunner window\n    var KeyEvent           = brackets.getModule(\"utils/KeyEvent\"),\n        PreferencesManager = brackets.getModule(\"preferences/PreferencesManager\"),\n        SpecRunnerUtils    = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        testContentCSS     = require(\"text!unittest-files/unittests.css\"),\n        testContentHTML    = require(\"text!unittest-files/unittests.html\"),\n        provider           = require(\"main\").inlineColorEditorProvider,\n        InlineColorEditor  = require(\"InlineColorEditor\").InlineColorEditor,\n        ColorEditor        = require(\"ColorEditor\").ColorEditor,\n        tinycolor          = require(\"thirdparty/tinycolor-min\");\n\n    // Helper functions for testing cursor position / selection range\n    function fixPos(pos) {\n        if (!(\"sticky\" in pos)) {\n            pos.sticky = null;\n        }\n        return pos;\n    }\n    function fixSel(sel) {\n        fixPos(sel.start);\n        fixPos(sel.end);\n        if (!(\"reversed\" in sel)) {\n            sel.reversed = false;\n        }\n        return sel;\n    }\n    function fixSels(sels) {\n        sels.forEach(function (sel) {\n            fixSel(sel);\n        });\n        return sels;\n    }\n\n    describe(\"Inline Color Editor - unit\", function () {\n\n        var testDocument, testEditor, inline;\n\n        /**\n         * Creates an inline color editor connected to the given cursor position in the test editor.\n         * Note that this does *not* actually open it as an inline editor in the test editor.\n         * Tests that use this must wrap their contents in a runs() block.\n         * @param {!{line:number, ch: number}} cursor Position for which to open the inline editor.\n         * if the provider did not create an inline editor.\n         */\n        function makeColorEditor(cursor) {\n            runs(function () {\n                var promise = provider(testEditor, cursor);\n                if (promise) {\n                    promise.done(function (inlineResult) {\n                        inlineResult.onAdded();\n                        inline = inlineResult;\n                    });\n                    waitsForDone(promise, \"open color editor\");\n                }\n            });\n        }\n\n        /**\n         * Expects an inline editor to be opened at the given cursor position and to have the\n         * given initial color (which should match the color at that position).\n         * @param {!{line:number, ch:number}} cursor The cursor position to try opening the inline at.\n         * @param {string} color The expected color.\n         */\n        function testOpenColor(cursor, color) {\n            makeColorEditor(cursor);\n            runs(function () {\n                expect(inline).toBeTruthy();\n                expect(inline._color).toBe(color);\n            });\n        }\n\n        /**\n         * Simulate the given event with clientX/clientY specified by the given\n         * ratios of the item's actual width/height (offset by the left/top of the\n         * item).\n         * @param {string} event The name of the event to simulate.\n         * @param {object} $item A jQuery object to trigger the event on.\n         * @param {Array.<number>} ratios Numbers between 0 and 1 indicating the x and y positions of the\n         *      event relative to the item's width and height.\n         */\n        function eventAtRatio(event, $item, ratios) {\n            $item.trigger($.Event(event, {\n                clientX: $item.offset().left + (ratios[0] * $item.width()),\n                clientY: $item.offset().top + (ratios[1] * $item.height())\n            }));\n        }\n\n        describe(\"Inline editor - CSS\", function () {\n\n            beforeEach(function () {\n                var mock = SpecRunnerUtils.createMockEditor(testContentCSS, \"css\");\n                testDocument = mock.doc;\n                testEditor = mock.editor;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n                inline = null;\n            });\n\n            describe(\"simple open cases\", function () {\n\n                it(\"should show the correct color when opened on an #rrggbb color\", function () {\n                    testOpenColor({line: 1, ch: 18}, \"#abcdef\");\n                });\n                it(\"should open when at the beginning of the color\", function () {\n                    testOpenColor({line: 1, ch: 16}, \"#abcdef\");\n                });\n                it(\"should open when at the end of the color\", function () {\n                    testOpenColor({line: 1, ch: 23}, \"#abcdef\");\n                });\n                it(\"should show the correct color when opened on an #rgb color\", function () {\n                    testOpenColor({line: 5, ch: 18}, \"#abc\");\n                });\n                it(\"should show the correct color when opened on an rgb() color\", function () {\n                    testOpenColor({line: 9, ch: 18}, \"rgb(100, 200, 150)\");\n                });\n                it(\"should show the correct color when opened on an rgba() color\", function () {\n                    testOpenColor({line: 13, ch: 18}, \"rgba(100, 200, 150, 0.5)\");\n                });\n                it(\"should show the correct color when opened on an hsl() color\", function () {\n                    testOpenColor({line: 17, ch: 18}, \"hsl(180, 50%, 50%)\");\n                });\n                it(\"should show the correct color when opened on an hsla() color\", function () {\n                    testOpenColor({line: 21, ch: 18}, \"hsla(180, 50%, 50%, 0.5)\");\n                });\n                it(\"should show the correct color when opened on an uppercase hex color\", function () {\n                    testOpenColor({line: 33, ch: 18}, \"#DEFCBA\");\n                });\n                it(\"should show the correct color when opened on a color in a shorthand property\", function () {\n                    testOpenColor({line: 41, ch: 27}, \"#0f0f0f\");\n                });\n                it(\"should show the correct color when opened on an rgba() color with a leading period in the alpha field\", function () {\n                    testOpenColor({line: 45, ch: 18}, \"rgba(100, 200, 150, .5)\");\n                });\n                it(\"should show the correct color when opened on an hsla() color with a leading period in the alpha field\", function () {\n                    testOpenColor({line: 49, ch: 18}, \"hsla(180, 50%, 50%, .5)\");\n                });\n\n                it(\"should not open when not on a color\", function () {\n                    makeColorEditor({line: 1, ch: 6});\n                    runs(function () {\n                        expect(inline).toEqual(null);\n                    });\n                });\n                it(\"should not open when on an invalid color\", function () {\n                    makeColorEditor({line: 25, ch: 18});\n                    runs(function () {\n                        expect(inline).toEqual(null);\n                    });\n                });\n                it(\"should not open when on an hsl color with missing percent signs\", function () {\n                    makeColorEditor({line: 37, ch: 18});\n                    runs(function (inline) {\n                        expect(inline).toEqual(null);\n                    });\n                });\n\n                it(\"should open on the second color when there are two colors in the same line\", function () {\n                    testOpenColor({line: 29, ch: 48}, \"#ddeeff\");\n                });\n\n                it(\"should properly add/remove ref to document when opened/closed\", function () {\n                    runs(function () {\n                        spyOn(testDocument, \"addRef\").andCallThrough();\n                        spyOn(testDocument, \"releaseRef\").andCallThrough();\n                    });\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        expect(testDocument.addRef).toHaveBeenCalled();\n                        expect(testDocument.addRef.callCount).toBe(1);\n\n                        inline.onClosed();\n                        expect(testDocument.releaseRef).toHaveBeenCalled();\n                        expect(testDocument.releaseRef.callCount).toBe(1);\n                    });\n                });\n\n            });\n\n            describe(\"update host document on edit in color editor\", function () {\n\n                it(\"should update host document when change is committed in color editor\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        inline.colorEditor.setColorFromString(\"#c0c0c0\");\n                        expect(testDocument.getRange({line: 1, ch: 16}, {line: 1, ch: 23})).toBe(\"#c0c0c0\");\n                    });\n                });\n\n                it(\"should update correct range of host document with color format of different length\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        inline.colorEditor.setColorFromString(\"rgb(20, 20, 20)\");\n                        expect(testDocument.getRange({line: 1, ch: 16}, {line: 1, ch: 31})).toBe(\"rgb(20, 20, 20)\");\n                    });\n                });\n\n                it(\"should not invalidate range when change is committed\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        inline.colorEditor.setColorFromString(\"rgb(20, 20, 20)\");\n                        expect(inline.getCurrentRange()).toBeTruthy();\n                    });\n                });\n\n                it(\"should update correct range of host document when the in-editor color string is invalid\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        testDocument.replaceRange(\"\", {line: 1, ch: 22}, {line: 1, ch: 24});\n                        inline.colorEditor.setColorFromString(\"#c0c0c0\");\n                        expect(fixSel(inline.getCurrentRange())).toEqual(fixSel({start: {line: 1, ch: 16}, end: {line: 1, ch: 23}}));\n                        expect(testDocument.getRange({line: 1, ch: 16}, {line: 1, ch: 23})).toBe(\"#c0c0c0\");\n                    });\n                });\n\n            });\n\n            describe(\"update color editor on edit in host editor\", function () {\n\n                it(\"should update when edit is made to color range in host editor\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        spyOn(inline, \"close\");\n\n                        testDocument.replaceRange(\"0\", {line: 1, ch: 18}, {line: 1, ch: 19});\n                        expect(inline._color).toBe(\"#a0cdef\");\n                        // TODO (#2201): this assumes getColor() is a tinycolor, but sometimes it's a string\n                        expect(inline.colorEditor.getColor().toHexString().toLowerCase()).toBe(\"#a0cdef\");\n                        expect(inline.close).not.toHaveBeenCalled();\n                        expect(fixSel(inline.getCurrentRange())).toEqual(fixSel({start: {line: 1, ch: 16}, end: {line: 1, ch: 23}}));\n                    });\n                });\n\n                it(\"should close itself if edit is made that destroys end textmark and leaves color invalid\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        spyOn(inline, \"close\");\n\n                        // Replace everything including the semicolon, so it crosses the textmark boundary.\n                        testDocument.replaceRange(\"rgb(255, 25\", {line: 1, ch: 16}, {line: 1, ch: 24});\n                        expect(inline.close).toHaveBeenCalled();\n                    });\n                });\n\n                it(\"should maintain the range if the user deletes the last character of the color and types a new one\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        spyOn(inline, \"close\");\n\n                        testDocument.replaceRange(\"\", {line: 1, ch: 22}, {line: 1, ch: 23});\n                        testDocument.replaceRange(\"0\", {line: 1, ch: 22}, {line: 1, ch: 22});\n                        expect(inline._color).toBe(\"#abcde0\");\n                        expect(inline.close).not.toHaveBeenCalled();\n                        expect(fixSel(inline.getCurrentRange())).toEqual(fixSel({start: {line: 1, ch: 16}, end: {line: 1, ch: 23}}));\n                    });\n                });\n\n                it(\"should not update the end textmark and the color shown to a shorter valid match if the marker still exists and the color becomes invalid\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        testDocument.replaceRange(\"\", {line: 1, ch: 22}, {line: 1, ch: 23});\n                        expect(inline._color).toBe(\"#abcdef\");\n                        expect(fixSel(inline.getCurrentRange())).toEqual(fixSel({start: {line: 1, ch: 16}, end: {line: 1, ch: 22}}));\n                    });\n                });\n\n                it(\"should not update the end textmark and the color shown to a shorter valid match if the marker no longer exists and the color becomes invalid\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        testDocument.replaceRange(\"\", {line: 1, ch: 22}, {line: 1, ch: 24});\n                        expect(inline._color).toBe(\"#abcdef\");\n                        expect(fixSel(inline.getCurrentRange())).toEqual(fixSel({start: {line: 1, ch: 16}, end: {line: 1, ch: 22}}));\n                    });\n                });\n\n            });\n\n            describe(\"edit batching\", function () {\n                it(\"should combine multiple edits within the same inline editor into a single undo in the host editor\", function () {\n                    makeColorEditor({line: 1, ch: 18});\n                    runs(function () {\n                        inline.colorEditor.setColorFromString(\"#010101\");\n                        inline.colorEditor.setColorFromString(\"#123456\");\n                        inline.colorEditor.setColorFromString(\"#bdafe0\");\n                        testDocument._masterEditor._codeMirror.undo();\n                        expect(testDocument.getRange({line: 1, ch: 16}, {line: 1, ch: 23})).toBe(\"#abcdef\");\n                    });\n                });\n            });\n        });\n\n        describe(\"Inline editor - HTML\", function () {\n\n            beforeEach(function () {\n                var mock = SpecRunnerUtils.createMockEditor(testContentHTML, \"html\");\n                testDocument = mock.doc;\n                testEditor = mock.editor;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n            });\n\n            it(\"should open on a color in an HTML file\", function () {\n                testOpenColor({line: 4, ch: 30}, \"#dead01\");\n            });\n        });\n\n        describe(\"Inline editor - used colors processing\", function () {\n\n            it(\"should trim the original array to the given length\", function () {\n                var inline = new InlineColorEditor();\n                var result = inline._collateColors([\"#abcdef\", \"#fedcba\", \"#aabbcc\", \"#bbccdd\"], 2);\n                expect(result).toEqual([\n                    {value: \"#abcdef\", count: 1},\n                    {value: \"#fedcba\", count: 1}\n                ]);\n            });\n\n            it(\"should remove duplicates from the original array and sort it by usage\", function () {\n                var inline = new InlineColorEditor();\n                var result = inline._collateColors([\"#abcdef\", \"#fedcba\", \"#123456\", \"#FEDCBA\", \"#123456\", \"#123456\", \"rgb(100, 100, 100)\"], 100);\n                expect(result).toEqual([\n                    {value: \"#123456\", count: 3},\n                    {value: \"#fedcba\", count: 2},\n                    {value: \"#abcdef\", count: 1},\n                    {value: \"rgb(100, 100, 100)\", count: 1}\n                ]);\n            });\n        });\n\n        describe(\"Color editor UI\", function () {\n            var colorEditor,\n                defaultSwatches = [{value: \"#abcdef\", count: 3}, {value: \"rgba(100, 200, 250, 0.5)\", count: 2}];\n\n            /**\n             * Creates a hidden ColorEditor and appends it to the body. Note that this is a standalone\n             * ColorEditor, not inside an InlineColorEditor.\n             * @param {string} initialColor The color that should be initially set in the ColorEditor.\n             * @param {?function} callback An optional callback to be passed as the ColorEditor's callback. If\n             *     none is supplied, a dummy function is passed.\n             * @param {?Array.<{value:string, count:number}>} swatches An optional array of swatches to display.\n             *     If none is supplied, a default set of two swatches is passed.\n             * @param {boolean=} hide Whether to hide the color picker; default is true.\n             */\n            function makeUI(initialColor, callback, swatches, hide) {\n                colorEditor = new ColorEditor($(window.document.body),\n                                              initialColor,\n                                              callback || function () { },\n                                              swatches || defaultSwatches);\n                if (hide !== false) {\n                    colorEditor.getRootElement().css(\"display\", \"none\");\n                }\n            }\n\n            afterEach(function () {\n                colorEditor.getRootElement().remove();\n            });\n\n            /**\n             * Checks whether the difference between val1 and val2 is within the given tolerance.\n             * (We can't use Jasmine's .toBeCloseTo() because that takes a precision in decimal places,\n             * whereas we often need to check an absolute distance.)\n             * @param {(number|string)} val1 The first value to check.\n             * @param {(number|string)} val2 The second value to check.\n             * @param {number} tolerance The desired tolerance.\n             */\n            function checkNear(val1, val2, tolerance) {\n                expect(Math.abs(Number(val1) - Number(val2)) < (tolerance || 1.0)).toBe(true);\n            }\n            /**\n             * Checks whether the given percentage string is near the given value.\n             * @param {string} pct The percentage to check. Assumed to be a string ending in \"%\".\n             * @param {number} val The value to check against. Assumed to be a percentage number, but not ending in \"%\".\n             */\n            function checkPercentageNear(pct, val) {\n                expect(checkNear(pct.substr(0, pct.length - 1), val));\n            }\n\n            /** Returns the colorEditor's current value as a string in its current format */\n            function getColorString() {\n                return tinycolor(colorEditor.getColor()).getOriginalInput();\n            }\n\n            describe(\"simple load/commit\", function () {\n\n                it(\"should load the initial color correctly\", function () {\n                    var colorStr    = \"rgba(77, 122, 31, 0.5)\";\n                    var colorStrRgb = \"rgb(77, 122, 31)\";\n\n                    runs(function () {\n                        makeUI(colorStr);\n                        expect(colorEditor.getColor().getOriginalInput()).toBe(colorStr);\n                        expect(colorEditor.$colorValue.val()).toBe(colorStr);\n                        expect(tinycolor.equals(colorEditor.$currentColor.css(\"background-color\"), colorStr)).toBe(true);\n\n                        // Not sure why the tolerances need to be larger for these.\n                        checkNear(tinycolor(colorEditor.$selection.css(\"background-color\")).toHsv().h, 90, 2.0);\n                        checkNear(tinycolor(colorEditor.$hueBase.css(\"background-color\")).toHsv().h, 90, 2.0);\n\n                        expect(tinycolor.equals(colorEditor.$selectionBase.css(\"background-color\"), colorStrRgb)).toBe(true);\n                    });\n\n                    // Need to do these on a timeout since we can't seem to read back CSS positions synchronously.\n                    waits(1);\n\n                    runs(function () {\n                        checkPercentageNear(colorEditor.$hueSelector[0].style.bottom, 25);\n                        checkPercentageNear(colorEditor.$opacitySelector[0].style.bottom, 50);\n                        checkPercentageNear(colorEditor.$selectionBase[0].style.left, 74);\n                        checkPercentageNear(colorEditor.$selectionBase[0].style.bottom, 47);\n                    });\n                });\n\n                it(\"should load a committed color correctly\", function () {\n                    var colorStr = \"rgba(77, 122, 31, 0.5)\";\n                    var colorStrRgb = \"rgb(77, 122, 31)\";\n\n                    runs(function () {\n                        makeUI(\"#0a0a0a\");\n                        colorEditor.setColorFromString(colorStr);\n                        expect(colorEditor.getColor().getOriginalInput()).toBe(colorStr);\n                        expect(colorEditor.$colorValue.val()).toBe(colorStr);\n                        expect(tinycolor.equals(colorEditor.$currentColor.css(\"background-color\"), colorStr)).toBe(true);\n                        checkNear(tinycolor(colorEditor.$selection.css(\"background-color\")).toHsv().h, tinycolor(colorStr).toHsv().h);\n                        checkNear(tinycolor(colorEditor.$hueBase.css(\"background-color\")).toHsv().h, tinycolor(colorStr).toHsv().h);\n                        expect(tinycolor.equals(colorEditor.$selectionBase.css(\"background-color\"), colorStrRgb)).toBe(true);\n                    });\n\n                    // Need to do these on a timeout since we can't seem to read back CSS positions synchronously.\n                    waits(1);\n\n                    runs(function () {\n                        checkPercentageNear(colorEditor.$hueSelector[0].style.bottom, 25);\n                        checkPercentageNear(colorEditor.$opacitySelector[0].style.bottom, 50);\n                        checkPercentageNear(colorEditor.$selectionBase[0].style.left, 74);\n                        checkPercentageNear(colorEditor.$selectionBase[0].style.bottom, 47);\n                    });\n                });\n\n                it(\"should call the callback when a new color is committed\", function () {\n                    var lastColor;\n                    makeUI(\"rgba(100, 100, 100, 0.5)\", function (color) {\n                        lastColor = color;\n                    });\n                    colorEditor.setColorFromString(\"#a0a0a0\");\n                    expect(lastColor).toBe(\"#a0a0a0\");\n                });\n\n            });\n\n            /**\n             * Test whether converting the given color to the given mode results in the expected color.\n             * @param {string} initialColor The color to convert.\n             * @param {string} mode The mode to convert to: must be \"rgba\", \"hsla\", or \"hex\".\n             * @param {string} result The expected result of the conversion.\n             */\n            function testConvert(initialColor, mode, result) {\n                makeUI(initialColor);\n                var buttonMap = {\n                    \"rgba\": \"$rgbaButton\",\n                    \"hsla\": \"$hslButton\",\n                    \"hex\": \"$hexButton\"\n                };\n                colorEditor[buttonMap[mode]].trigger(\"click\");\n                expect(colorEditor.getColor().getOriginalInput()).toBe(result);\n            }\n\n            describe(\"conversions in lower case\", function () {\n\n                it(\"should convert a hex color to rgb when mode button clicked\", function () {\n                    testConvert(\"#112233\", \"rgba\", \"rgb(17, 34, 51)\");\n                });\n                it(\"should convert a hex color to hsl when mode button clicked\", function () {\n                    testConvert(\"#112233\", \"hsla\", \"hsl(210, 50%, 13%)\");\n                });\n                it(\"should convert an rgb color to hex when mode button clicked\", function () {\n                    testConvert(\"rgb(15, 160, 21)\", \"hex\", \"#0fa015\");\n                });\n                it(\"should convert an rgba color to hex (dropping alpha) when mode button clicked\", function () {\n                    testConvert(\"rgba(15, 160, 21, 0.5)\", \"hex\", \"#0fa015\");\n                });\n                it(\"should convert an rgb color to hsl when mode button clicked\", function () {\n                    testConvert(\"rgb(15, 160, 21)\", \"hsla\", \"hsl(122, 83%, 34%)\");\n                });\n                it(\"should convert an rgba color to hsla when mode button clicked\", function () {\n                    testConvert(\"rgba(15, 160, 21, 0.3)\", \"hsla\", \"hsla(122, 83%, 34%, 0.3)\");\n                });\n                it(\"should convert an hsl color to hex when mode button clicked\", function () {\n                    testConvert(\"hsl(152, 12%, 22%)\", \"hex\", \"#313f39\");\n                });\n                it(\"should convert an hsla color to hex (dropping alpha) when mode button clicked\", function () {\n                    testConvert(\"hsla(152, 12%, 22%, 0.7)\", \"hex\", \"#313f39\");\n                });\n                it(\"should convert an hsl color to rgb when mode button clicked\", function () {\n                    testConvert(\"hsl(152, 12%, 22%)\", \"rgba\", \"rgb(49, 63, 57)\");\n                });\n                it(\"should convert an hsla color to rgba when mode button clicked\", function () {\n                    testConvert(\"hsla(152, 12%, 22%, 0.7)\", \"rgba\", \"rgba(49, 63, 57, 0.7)\");\n                });\n                it(\"should convert a mixed case hsla color to rgba when mode button clicked\", function () {\n                    testConvert(\"HsLa(152, 12%, 22%, 0.7)\", \"rgba\", \"rgba(49, 63, 57, 0.7)\");\n                });\n                it(\"should convert a mixed case hex color to rgb when mode button clicked\", function () {\n                    testConvert(\"#fFfFfF\", \"rgba\", \"rgb(255, 255, 255)\");\n                });\n\n            });\n\n            describe(\"conversions in UPPER CASE\", function () {\n\n                beforeEach(function () {\n                    // Enable uppercase colors\n                    PreferencesManager.set(\"uppercaseColors\", true);\n                });\n                afterEach(function () {\n                    // Re-disable uppercase colors\n                    PreferencesManager.set(\"uppercaseColors\", false);\n                });\n\n                it(\"should use uppercase colors\", function () {\n                    expect(PreferencesManager.get(\"uppercaseColors\")).toBe(true);\n                });\n                it(\"should convert a hex color to rgb in uppercase when mode button clicked\", function () {\n                    testConvert(\"#112233\", \"rgba\", \"RGB(17, 34, 51)\");\n                });\n                it(\"should convert a hex color to hsl in uppercase when mode button clicked\", function () {\n                    testConvert(\"#112233\", \"hsla\", \"HSL(210, 50%, 13%)\");\n                });\n                it(\"should convert an rgb color to hex in uppercase when mode button clicked\", function () {\n                    testConvert(\"RGB(15, 160, 21)\", \"hex\", \"#0FA015\");\n                });\n                it(\"should convert an rgba color to hex (dropping alpha) in uppercase when mode button clicked\", function () {\n                    testConvert(\"RGBA(15, 160, 21, 0.5)\", \"hex\", \"#0FA015\");\n                });\n                it(\"should convert an rgb color to hsl in uppercase when mode button clicked\", function () {\n                    testConvert(\"RGB(15, 160, 21)\", \"hsla\", \"HSL(122, 83%, 34%)\");\n                });\n                it(\"should convert an rgba color to hsla in uppercase when mode button clicked\", function () {\n                    testConvert(\"RGBA(15, 160, 21, 0.3)\", \"hsla\", \"HSLA(122, 83%, 34%, 0.3)\");\n                });\n                it(\"should convert an hsl color to hex in uppercase when mode button clicked\", function () {\n                    testConvert(\"HSL(152, 12%, 22%)\", \"hex\", \"#313F39\");\n                });\n                it(\"should convert an hsla color to hex (dropping alpha) in uppercase when mode button clicked\", function () {\n                    testConvert(\"HSLA(152, 12%, 22%, 0.7)\", \"hex\", \"#313F39\");\n                });\n                it(\"should convert an hsl color to rgb in uppercase when mode button clicked\", function () {\n                    testConvert(\"HSL(152, 12%, 22%)\", \"rgba\", \"RGB(49, 63, 57)\");\n                });\n                it(\"should convert an hsla color to rgba in uppercase when mode button clicked\", function () {\n                    testConvert(\"HSLA(152, 12%, 22%, 0.7)\", \"rgba\", \"RGBA(49, 63, 57, 0.7)\");\n                });\n                it(\"should convert a mixed case hsla color to rgba in uppercase when mode button clicked\", function () {\n                    testConvert(\"HsLa(152, 12%, 22%, 0.7)\", \"rgba\", \"RGBA(49, 63, 57, 0.7)\");\n                });\n                it(\"should convert a mixed case hex color to rgb in uppercase when mode button clicked\", function () {\n                    testConvert(\"#fFfFfF\", \"rgba\", \"RGB(255, 255, 255)\");\n                });\n\n            });\n\n            describe(\"parameter editing with mouse\", function () {\n\n                /**\n                 * Test a mouse down event on the given UI element.\n                 * @param {object} opts The parameters to test:\n                 *     item: The (string) name of the member of ColorEditor that references the element to test.\n                 *     clickAt: An [x, y] array specifying the simulated x/y mouse position as a fraction of the\n                 *          item's width/height. For example, [0.5, 0.5] would specify a click exactly in the\n                 *          center of the element.\n                 *     param: The (string) parameter whose value we're testing (h, s, v, or a).\n                 *     expected: The expected value for the parameter.\n                 *     tolerance: The tolerance in variation for the expected value.\n                 */\n                function testMousedown(opts) {\n                    makeUI(\"#0000ff\");\n                    eventAtRatio(\"mousedown\", colorEditor[opts.item], opts.clickAt);\n                    checkNear(tinycolor(colorEditor.getColor()).toHsv()[opts.param], opts.expected, opts.tolerance);\n                    colorEditor[opts.item].trigger(\"mouseup\");  // clean up drag state\n                }\n\n                /**\n                 * Test a drag event on the given UI element.\n                 * @param {object} opts The parameters to test:\n                 *     item: The (string) name of the member of ColorEditor that references the element to test.\n                 *     clickAt: An [x, y] array specifying the simulated x/y mouse position for the initial mouse down\n                 *          as a fraction of the item's width/height. For example, [0.5, 0.5] would specify a click\n                 *          exactly in the center of the element.\n                 *     dragTo: An [x, y] array specifying the location to drag to, using the same convention as clickAt.\n                 *     param: The (string) parameter whose value we're testing (h, s, v, or a).\n                 *     expected: The expected value for the parameter.\n                 *     tolerance: The tolerance in variation for the expected value.\n                 */\n                function testDrag(opts) {\n                    makeUI(\"#0000ff\");\n                    eventAtRatio(\"mousedown\", colorEditor[opts.item], opts.clickAt);\n                    eventAtRatio(\"mousemove\", colorEditor[opts.item], opts.dragTo);\n                    checkNear(tinycolor(colorEditor.getColor()).toHsv()[opts.param], opts.expected, opts.tolerance);\n                    colorEditor[opts.item].trigger(\"mouseup\");  // clean up drag state\n                }\n\n                it(\"should set saturation on mousedown\", function () {\n                    testMousedown({\n                        item:      \"$selection\",\n                        clickAt:   [0.25, 0], // x: saturation, y: 1.0 - value\n                        param:     \"s\",\n                        expected:  0.25,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should set saturation on drag\", function () {\n                    testDrag({\n                        item:      \"$selection\",\n                        clickAt:   [0.25, 0], // x: saturation, y: 1.0 - value\n                        dragTo:    [0.75, 0],\n                        param:     \"s\",\n                        expected:  0.75,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should clip saturation to min value\", function () {\n                    testDrag({\n                        item:      \"$selection\",\n                        clickAt:   [0.25, 0], // x: saturation, y: 1.0 - value\n                        dragTo:    [-0.25, 0],\n                        param:     \"s\",\n                        expected:  0,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should clip saturation to max value\", function () {\n                    testDrag({\n                        item:      \"$selection\",\n                        clickAt:   [0.25, 0], // x: saturation, y: 1.0 - value\n                        dragTo:    [1.25, 0],\n                        param:     \"s\",\n                        expected:  1,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should set value on mousedown\", function () {\n                    testMousedown({\n                        item:      \"$selection\",\n                        clickAt:   [1.0, 0.75], // x: saturation, y: 1.0 - value\n                        param:     \"v\",\n                        expected:  0.25,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should set value on drag\", function () {\n                    testDrag({\n                        item:      \"$selection\",\n                        clickAt:   [1.0, 0.75], // x: saturation, y: 1.0 - value\n                        dragTo:    [1.0, 0.25],\n                        param:     \"v\",\n                        expected:  0.75,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should clip value to min value\", function () {\n                    testDrag({\n                        item:      \"$selection\",\n                        clickAt:   [1.0, 0.75], // x: saturation, y: 1.0 - value\n                        dragTo:    [1.0, 1.25],\n                        param:     \"v\",\n                        expected:  0,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should clip value to max value\", function () {\n                    testDrag({\n                        item:      \"$selection\",\n                        clickAt:   [1.0, 0.75],\n                        dragTo:    [1.0, -0.25],\n                        param:     \"v\",\n                        expected:  1,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should set hue on mousedown\", function () {\n                    testMousedown({\n                        item:      \"$hueSlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - (hue / 360)\n                        param:     \"h\",\n                        expected:  90,\n                        tolerance: 1\n                    });\n                });\n                it(\"should set hue on drag\", function () {\n                    testDrag({\n                        item:      \"$hueSlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - (hue / 360)\n                        dragTo:    [0, 0.25],\n                        param:     \"h\",\n                        expected:  270,\n                        tolerance: 1\n                    });\n                });\n                it(\"should clip hue to min value\", function () {\n                    testDrag({\n                        item:      \"$hueSlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - (hue / 360)\n                        dragTo:    [0, 1.25],\n                        param:     \"h\",\n                        expected:  0,\n                        tolerance: 1\n                    });\n                });\n                it(\"should clip hue to max value\", function () {\n                    testDrag({\n                        item:      \"$hueSlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - (hue / 360)\n                        dragTo:    [0, -0.25],\n                        param:     \"h\",\n                        expected:  0,\n                        tolerance: 1\n                    });\n                });\n                it(\"should set opacity on mousedown\", function () {\n                    testMousedown({\n                        item:      \"$opacitySlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - opacity\n                        param:     \"a\",\n                        expected:  0.25,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should set opacity on drag\", function () {\n                    testDrag({\n                        item:      \"$opacitySlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - opacity\n                        dragTo:    [0, 0.25],\n                        param:     \"a\",\n                        expected:  0.75,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should clip opacity to min value\", function () {\n                    testDrag({\n                        item:      \"$opacitySlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - opacity\n                        dragTo:    [0, 1.25],\n                        param:     \"a\",\n                        expected:  0,\n                        tolerance: 0.1\n                    });\n                });\n                it(\"should clip opacity to max value\", function () {\n                    // A increases going up, so a clientY at -0.25 of the item's height corresponds to >100%.\n                    testDrag({\n                        item:      \"$opacitySlider\",\n                        clickAt:   [0, 0.75], // x: unused, y: 1.0 - opacity\n                        dragTo:    [0, -0.25],\n                        param:     \"a\",\n                        expected:  1,\n                        tolerance: 0.1\n                    });\n                });\n\n            });\n\n            describe(\"parameter editing with keyboard\", function () {\n\n                function makeKeyEvent(opts) {\n                    return $.Event(\"keydown\", { keyCode: opts.key, shiftKey: !!opts.shift });\n                }\n\n                /**\n                 * Test a key event on the given UI element.\n                 * @param {object} opts The parameters to test:\n                 *     color: An optional initial value to set in the ColorEditor. Defaults to \"hsla(50, 25%, 50%, 0.5)\".\n                 *     item: The (string) name of the member of ColorEditor that references the element to test.\n                 *     key: The KeyEvent key code to simulate.\n                 *     shift: Optional boolean specifying whether to simulate the shift key being down (default false).\n                 *     param: The (string) parameter whose value we're testing (h, s, v, or a).\n                 *     delta: The expected change in value for the parameter.\n                 *     tolerance: The tolerance in variation for the expected value.\n                 *     exact: True to compare the actual values stored in the _hsv object, false (default) to\n                 *          compare tinycolor's normalization of the color value.\n                 */\n                function testKey(opts) {\n\n                    function getParam() {\n                        if (opts.exact) {\n                            var result = colorEditor._hsv[opts.param];\n                            // Because of #2201, this is sometimes a string with a percentage value.\n                            if (typeof result === \"string\" && result.charAt(result.length - 1) === \"%\") {\n                                result = Number(result.substr(0, result.length - 1));\n                            }\n                            return result;\n                        } else {\n                            return tinycolor(colorEditor.getColor()).toHsv()[opts.param];\n                        }\n                    }\n\n                    makeUI(opts.color || \"hsla(50, 25%, 50%, 0.5)\");\n\n                    var before = getParam();\n                    colorEditor[opts.item].trigger(makeKeyEvent(opts));\n\n                    var after = getParam();\n                    checkNear(after, before + opts.delta, opts.tolerance);\n                }\n\n                /**\n                 * Test whether the given event's default is or isn't prevented on a given key.\n                 * @param {object} opts The parameters to test:\n                 *     color: An optional initial value to set in the ColorEditor. Defaults to \"hsla(50, 25%, 50%, 0.5)\".\n                 *     item: The (string) name of the member of ColorEditor that references the element to test.\n                 *     selection: An optional array ([start, end]) specifying the selection to set in the given element.\n                 *     key: The KeyEvent key code to simulate.\n                 *     shift: Optional boolean specifying whether to simulate the shift key being down (default false).\n                 *     expected: Whether the default is expected to be prevented.\n                 */\n                function testPreventDefault(opts) {\n                    var event, $item;\n\n                    // The color picker needs to be displayed for this test; otherwise the\n                    // selection won't be properly set, because you can only set the selection\n                    // when the text field has focus.\n                    makeUI(opts.color || \"hsla(50, 25%, 50%, 0.5)\", function () { }, defaultSwatches, false);\n\n                    $item = colorEditor[opts.item];\n                    $item.focus();\n                    if (opts.selection) {\n                        $item[0].setSelectionRange(opts.selection[0], opts.selection[1]);\n                    }\n\n                    event = makeKeyEvent(opts);\n                    $item.trigger(event);\n                    expect(event.isDefaultPrevented()).toBe(opts.expected);\n                }\n\n                it(\"should increase saturation by 1.5% on right arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        param:     \"s\",\n                        delta:     0.015,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip max saturation on right arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 100%, 50%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        param:     \"s\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should increase saturation by 7.5% on shift right arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        shift:     true,\n                        param:     \"s\",\n                        delta:     0.075,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip max saturation on shift right arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 100%, 50%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        shift:     true,\n                        param:     \"s\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should decrease saturation by 1.5% on left arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        param:     \"s\",\n                        delta:     -0.015,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip min saturation on left arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 0%, 50%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        param:     \"s\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should decrease saturation by 7.5% on shift left arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        shift:     true,\n                        param:     \"s\",\n                        delta:     -0.075,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip min saturation on shift left arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 0%, 50%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        shift:     true,\n                        param:     \"s\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should increase value by 1.5% on up arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        param:     \"v\",\n                        delta:     0.015,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip max value on up arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 25%, 100%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        param:     \"v\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should increase value by 7.5% on shift up arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"v\",\n                        delta:     0.075,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip max value on shift up arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 25%, 100%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"v\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should decrease value by 1.5% on down arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        param:     \"v\",\n                        delta:     -0.015,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip min value on down arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 25%, 0%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        param:     \"v\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should decrease value by 7.5% on shift down arrow\", function () {\n                    testKey({\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true,\n                        param:     \"v\",\n                        delta:     -0.075,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should clip min value on shift down arrow\", function () {\n                    testKey({\n                        color:     \"hsla(50, 25%, 0%, 0.5)\",\n                        item:      \"$selectionBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true,\n                        param:     \"v\",\n                        delta:     0,\n                        tolerance: 0.01\n                    });\n                });\n                it(\"should increase hue by 3.6 on up arrow\", function () {\n                    testKey({\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        param:     \"h\",\n                        delta:     3.6,\n                        tolerance: 1\n                    });\n                });\n                it(\"should wrap around max hue on up arrow\", function () {\n                    testKey({\n                        color:     \"hsla(359, 25%, 50%, 0.5)\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        param:     \"h\",\n                        delta:     -359 + 3.6,\n                        tolerance: 1\n                    });\n                });\n                it(\"should increase hue by 18 on shift up arrow\", function () {\n                    testKey({\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"h\",\n                        delta:     18,\n                        tolerance: 1\n                    });\n                });\n                it(\"should wrap around max hue on shift up arrow\", function () {\n                    testKey({\n                        color:     \"hsla(359, 25%, 50%, 0.5)\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"h\",\n                        delta:     -359 + 18,\n                        tolerance: 1\n                    });\n                });\n                it(\"should decrease hue by 3.6 on down arrow\", function () {\n                    testKey({\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        param:     \"h\",\n                        delta:     -3.6,\n                        tolerance: 1\n                    });\n                });\n                it(\"should wrap around min hue on down arrow\", function () {\n                    testKey({\n                        color:     \"hsla(0, 25%, 50%, 0.5)\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        param:     \"h\",\n                        delta:     360 - 3.6,\n                        tolerance: 1\n                    });\n                });\n                it(\"should decrease hue by 18 on shift down arrow\", function () {\n                    testKey({\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true,\n                        param:     \"h\",\n                        delta:     -18,\n                        tolerance: 1\n                    });\n                });\n                it(\"should wrap around min hue on shift down arrow\", function () {\n                    testKey({\n                        color:     \"hsla(0, 25%, 50%, 0.5)\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true,\n                        param:     \"h\",\n                        delta:     360 - 18,\n                        tolerance: 1\n                    });\n                });\n                it(\"should increase opacity by 0.01 on up arrow\", function () {\n                    testKey({\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        param:     \"a\",\n                        delta:     0.01,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should clip max opacity on up arrow\", function () {\n                    testKey({\n                        color:     \"hsla(90, 25%, 50%, 1.0)\",\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        param:     \"a\",\n                        delta:     0,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should increase opacity by 0.05 on shift up arrow\", function () {\n                    testKey({\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"a\",\n                        delta:     0.05,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should clip max opacity on shift up arrow\", function () {\n                    testKey({\n                        color:     \"hsla(90, 25%, 50%, 1.0)\",\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"a\",\n                        delta:     0,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should decrease opacity by 0.01 on down arrow\", function () {\n                    testKey({\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        param:     \"a\",\n                        delta:     -0.01,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should clip min opacity on down arrow\", function () {\n                    testKey({\n                        color:     \"hsla(90, 25%, 50%, 0)\",\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        param:     \"a\",\n                        delta:     0,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should decrease opacity by 0.05 on shift down arrow\", function () {\n                    testKey({\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true,\n                        param:     \"a\",\n                        delta:     -0.05,\n                        tolerance: 0.005\n                    });\n                });\n                it(\"should clip min opacity on shift down arrow\", function () {\n                    testKey({\n                        color:     \"hsla(90, 25%, 50%, 0)\",\n                        item:      \"$opacitySelector\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true,\n                        param:     \"a\",\n                        delta:     0,\n                        tolerance: 0.005\n                    });\n                });\n\n                // For #2138\n                it(\"should increase hue by 18 on shift up arrow even if saturation is 0\", function () {\n                    testKey({\n                        color:     \"hsl(180, 0, 0)\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"h\",\n                        delta:     18,\n                        tolerance: 1,\n                        exact:     true\n                    });\n                });\n                it(\"should increase hue by 18 on shift up arrow for a near-gray hex color\", function () {\n                    testKey({\n                        color:     \"#5c5b56\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"h\",\n                        delta:     18,\n                        tolerance: 1,\n                        exact:     true\n                    });\n                });\n                it(\"should not change value when hue changes\", function () {\n                    testKey({\n                        color:     \"#8e8247\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true,\n                        param:     \"v\",\n                        delta:     0,\n                        tolerance: 0.01,\n                        exact:     true\n                    });\n                });\n\n                // For #2193 and #2229\n                it(\"should prevent default on the key event for an unhandled arrow key on non-text-field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$hueBase\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        expected:  true\n                    });\n                });\n                it(\"should prevent default on left arrow at the start of the text field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [0, 0],\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        expected:  true\n                    });\n                });\n                it(\"should not prevent default on left arrow in the middle of the text field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [3, 3],\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        expected:  false\n                    });\n                });\n                it(\"should not prevent default on left arrow at the end of the text field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [7, 7],\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        expected:  false\n                    });\n                });\n                it(\"should not prevent default on left arrow with a range selection\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [0, 7],\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        expected:  false\n                    });\n                });\n                it(\"should not prevent default on right arrow at the start of the text field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [0, 0],\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        expected:  false\n                    });\n                });\n                it(\"should not prevent default on right arrow in the middle of the text field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [3, 3],\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        expected:  false\n                    });\n                });\n                it(\"should prevent default on right arrow at the end of the text field\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [7, 7],\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        expected:  true\n                    });\n                });\n                it(\"should not prevent default on right arrow with a range selection\", function () {\n                    testPreventDefault({\n                        color:     \"#8e8247\",\n                        item:      \"$colorValue\",\n                        selection: [0, 7],\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        expected:  false\n                    });\n                });\n\n            });\n\n            describe(\"color swatches and original color\", function () {\n\n                it(\"should restore to original color when clicked on\", function () {\n                    makeUI(\"#abcdef\");\n                    colorEditor.setColorFromString(\"#0000ff\");\n                    colorEditor.$originalColor.trigger(\"click\");\n                    expect(tinycolor(colorEditor.getColor()).toHexString()).toBe(\"#abcdef\");\n                });\n\n                it(\"should create swatches\", function () {\n                    makeUI(\"#abcdef\");\n                    expect($(\".swatch\").length).toBe(2);\n                });\n\n                it(\"should set color to a swatch when clicked on\", function () {\n                    makeUI(\"#fedcba\");\n                    $($(\".swatch\")[0]).trigger(\"click\");\n                    expect(tinycolor(colorEditor.getColor()).toHexString()).toBe(\"#abcdef\");\n                });\n\n            });\n\n            describe(\"input text field syncing\", function () {\n\n                it(\"should commit valid changes made in the input field on the input event\", function () {\n                    makeUI(\"#abcdef\");\n                    colorEditor.$colorValue.val(\"#fedcba\");\n                    colorEditor.$colorValue.trigger(\"input\");\n                    expect(tinycolor(colorEditor.getColor()).toHexString()).toBe(\"#fedcba\");\n                });\n                it(\"should commit valid changes made in the input field on the change event\", function () {\n                    makeUI(\"#abcdef\");\n                    colorEditor.$colorValue.val(\"#fedcba\");\n                    colorEditor.$colorValue.trigger(\"change\");\n                    expect(tinycolor(colorEditor.getColor()).toHexString()).toBe(\"#fedcba\");\n                });\n                it(\"should not commit changes on the input event while the value is invalid, but should keep them in the text field\", function () {\n                    makeUI(\"#abcdef\");\n                    colorEditor.$colorValue.val(\"rgb(0, 0, 0\");\n                    colorEditor.$colorValue.trigger(\"input\");\n                    expect(tinycolor(colorEditor.getColor()).toHexString()).toBe(\"#abcdef\");\n                    expect(colorEditor.$colorValue.val()).toBe(\"rgb(0, 0, 0\");\n                });\n                it(\"should revert to the previous value on the change event while the value is invalid\", function () {\n                    makeUI(\"#abcdef\");\n                    colorEditor.$colorValue.val(\"rgb(0, 0, 0\");\n                    colorEditor.$colorValue.trigger(\"change\");\n                    expect(tinycolor(colorEditor.getColor()).toHexString()).toBe(\"#abcdef\");\n                    expect(colorEditor.$colorValue.val()).toBe(\"#abcdef\");\n                });\n\n                it(\"should convert percentage RGB values to normal values\", function () {\n                    makeUI(\"#abcdef\");\n                    expect(colorEditor._convertToNormalRGB(\"rgb(25%, 50%, 75%)\")).toBe(\"rgb(64, 128, 191)\");\n                });\n                it(\"should normalize a string to match tinycolor's format\", function () {\n                    makeUI(\"#abcdef\");\n                    //Percentage based colors are now supported: the following test is obsolete\n                    //expect(colorEditor._normalizeColorString(\"rgb(25%,50%,75%)\")).toBe(\"rgb(64, 128, 191)\");\n                    expect(colorEditor._normalizeColorString(\"rgb(10,20,   30)\")).toBe(\"rgb(10, 20, 30)\");\n                });\n            });\n\n            describe(\"undo/redo\", function () {\n\n                function triggerCtrlKey($element, key, shift) {\n                    var ctrlKeyProperty = (brackets.platform === \"win\" ? \"ctrlKey\" : \"metaKey\"),\n                        eventProps = {keyCode: key, shiftKey: shift};\n                    eventProps[ctrlKeyProperty] = true;\n                    $element.trigger($.Event(\"keydown\", eventProps));\n                }\n\n                it(\"should undo when Ctrl-Z is pressed on a focused element in the color editor\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor.setColorFromString(\"#a0a0a0\");\n                        colorEditor.$hueBase.focus();\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"#abcdef\");\n                    });\n                });\n\n                it(\"should redo when Ctrl-Shift-Z is pressed on a focused element in the color editor\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor._commitColor(\"#a0a0a0\", true);\n                        colorEditor.$hueBase.focus();\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z, true);\n                        expect(getColorString()).toBe(\"#a0a0a0\");\n                    });\n                });\n\n                it(\"should redo when Ctrl-Y is pressed on a focused element in the color editor\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor._commitColor(\"#a0a0a0\", true);\n                        colorEditor.$hueBase.focus();\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Y);\n                        expect(getColorString()).toBe(\"#a0a0a0\");\n                    });\n                });\n\n                it(\"should redo when Ctrl-Y is pressed after two Ctrl-Zs (only one Ctrl-Z should take effect)\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor._commitColor(\"#a0a0a0\", true);\n                        colorEditor.$hueBase.focus();\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Y);\n                        expect(getColorString()).toBe(\"#a0a0a0\");\n                    });\n                });\n\n                it(\"should undo when Ctrl-Z is pressed after two Ctrl-Ys (only one Ctrl-Y should take effect)\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor._commitColor(\"#a0a0a0\", true);\n                        colorEditor.$hueBase.focus();\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Y);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Y);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"#abcdef\");\n                    });\n                });\n\n                it(\"should undo an rgba conversion\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor.$rgbaButton.click();\n                        triggerCtrlKey(colorEditor.$rgbaButton, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"#abcdef\");\n                    });\n                });\n                it(\"should undo an hsla conversion\", function () {\n                    makeUI(\"#abcdef\");\n                    runs(function () {\n                        colorEditor.$hslButton.click();\n                        triggerCtrlKey(colorEditor.$hslButton, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"#abcdef\");\n                    });\n                });\n                it(\"should undo a hex conversion\", function () {\n                    makeUI(\"rgba(12, 32, 65, 0.2)\");\n                    runs(function () {\n                        colorEditor.$hexButton.trigger(\"click\");\n                        triggerCtrlKey(colorEditor.$hexButton, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"rgba(12, 32, 65, 0.2)\");\n                    });\n                });\n\n                it(\"should undo a saturation/value change\", function () {\n                    makeUI(\"rgba(100, 150, 200, 0.3)\");\n                    runs(function () {\n                        eventAtRatio(\"mousedown\", colorEditor.$selectionBase, [0.5, 0.5]);\n                        triggerCtrlKey(colorEditor.$selectionBase, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"rgba(100, 150, 200, 0.3)\");\n                        colorEditor.$selectionBase.trigger(\"mouseup\");  // clean up drag state\n                    });\n                });\n                it(\"should undo a hue change\", function () {\n                    makeUI(\"rgba(100, 150, 200, 0.3)\");\n                    runs(function () {\n                        eventAtRatio(\"mousedown\", colorEditor.$hueBase, [0, 0.5]);\n                        triggerCtrlKey(colorEditor.$hueBase, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"rgba(100, 150, 200, 0.3)\");\n                        colorEditor.$hueBase.trigger(\"mouseup\");  // clean up drag state\n                    });\n                });\n                it(\"should undo an opacity change\", function () {\n                    makeUI(\"rgba(100, 150, 200, 0.3)\");\n                    runs(function () {\n                        eventAtRatio(\"mousedown\", colorEditor.$opacitySelector, [0, 0.5]);\n                        triggerCtrlKey(colorEditor.$opacitySelector, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"rgba(100, 150, 200, 0.3)\");\n                        colorEditor.$opacitySelector.trigger(\"mouseup\");  // clean up drag state\n                    });\n                });\n\n                it(\"should undo a text field change\", function () {\n                    makeUI(\"rgba(100, 150, 200, 0.3)\");\n                    runs(function () {\n                        colorEditor.$colorValue.val(\"rgba(50, 50, 50, 0.9)\");\n                        triggerCtrlKey(colorEditor.$colorValue, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"rgba(100, 150, 200, 0.3)\");\n                    });\n                });\n                it(\"should undo a swatch click\", function () {\n                    makeUI(\"rgba(100, 150, 200, 0.3)\");\n                    runs(function () {\n                        var $swatch = $(colorEditor.$swatches.find(\"li\")[0]);\n                        $swatch.trigger(\"click\");\n                        triggerCtrlKey($swatch, KeyEvent.DOM_VK_Z);\n                        expect(getColorString()).toBe(\"rgba(100, 150, 200, 0.3)\");\n                    });\n                });\n\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/BezierCurveEditor.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var KeyEvent        = brackets.getModule(\"utils/KeyEvent\"),\n        Strings         = brackets.getModule(\"strings\"),\n        Mustache        = brackets.getModule(\"thirdparty/mustache/mustache\");\n\n    var TimingFunctionUtils = require(\"TimingFunctionUtils\");\n\n    /** Mustache template that forms the bare DOM structure of the UI */\n    var BezierCurveEditorTemplate = require(\"text!BezierCurveEditorTemplate.html\");\n\n    /** @const @type {number} */\n    var HEIGHT_ABOVE    =  75,    // extra height above main grid\n        HEIGHT_BELOW    =  75,    // extra height below main grid\n        HEIGHT_MAIN     = 150,    // height of main grid\n        WIDTH_MAIN      = 150;    // width of main grid\n\n    var animationRequest = null;\n\n    /**\n     * CubicBezier object constructor\n     *\n     * @param {string|Array.number[4]} coordinates Four parameters passes to cubic-bezier()\n     *      either in string or array format.\n     */\n    function CubicBezier(coordinates) {\n        if (typeof coordinates === \"string\") {\n            this.coordinates = coordinates.split(\",\");\n        } else {\n            this.coordinates = coordinates;\n        }\n\n        if (!this.coordinates) {\n            throw \"No offsets were defined\";\n        }\n\n        this.coordinates = this.coordinates.map(function (n) { return +n; });\n\n        var i;\n        for (i = 3; i >= 0; i--) {\n            var xy = this.coordinates[i];\n            if (isNaN(xy) || (((i % 2) === 0) && (xy < 0 || xy > 1))) {\n                throw \"Wrong coordinate at \" + i + \"(\" + xy + \")\";\n            }\n        }\n    }\n\n    /**\n     * BezierCanvas object constructor\n     *\n     * @param {Element} canvas Inline editor <canvas> element\n     * @param {CubicBezier} bezier Associated CubicBezier object\n     * @param {number|Array.number} padding Element padding\n     */\n    function BezierCanvas(canvas, bezier, padding) {\n        this.canvas  = canvas;\n        this.bezier  = bezier;\n        this.padding = this.getPadding(padding);\n\n        // Convert to a cartesian coordinate system with axes from 0 to 1\n        var ctx = this.canvas.getContext(\"2d\"),\n            p = this.padding;\n\n        ctx.scale(canvas.width * (1 - p[1] - p[3]), -canvas.height * 0.5 * (1 - p[0] - p[2]));\n        ctx.translate(p[3] / (1 - p[1] - p[3]), (-1 - p[0] / (1 - p[0] - p[2])) - 0.5);\n    }\n\n    BezierCanvas.prototype = {\n\n        /**\n         * Calculates CSS offsets for <canvas> element\n         *\n         * @return {left:string, top:string}\n         */\n        getOffsets: function () {\n            var p = this.padding,\n                w = this.canvas.width,\n                h = this.canvas.height * 0.5;\n\n            return [{\n                left: w * (this.bezier.coordinates[0]     * (1 - p[3] - p[1]) - p[3]) + \"px\",\n                top:  h * (1 - this.bezier.coordinates[1] * (1 - p[0] - p[2]) - p[0]) + \"px\"\n            }, {\n                left: w * (this.bezier.coordinates[2]     * (1 - p[3] - p[1]) - p[3]) + \"px\",\n                top:  h * (1 - this.bezier.coordinates[3] * (1 - p[0] - p[2]) - p[0]) + \"px\"\n            }];\n        },\n\n        /**\n         * Round off number to hundreths place, convert to string, and strip leading zero\n         *\n         * @param {number} v Value\n         * @return {string}\n         */\n        prettify: function (v) {\n            return (Math.round(v * 100) / 100).toString().replace(/^0\\./, \".\");\n        },\n\n        /**\n         * Get CSS left, top offsets for endpoint handle\n         *\n         * @param {Element} element Endpoint handle <button> element\n         * @return {Array.string[2]}\n         */\n        offsetsToCoordinates: function (element) {\n            var p = this.padding,\n                w = this.canvas.width,\n                h = this.canvas.height * 0.5;\n\n            // Convert padding percentage to actual padding\n            p = p.map(function (a, i) {\n                return a * ((i % 2) ? w : h);\n            });\n\n            return [\n                this.prettify((parseInt($(element).css(\"left\"), 10)    - p[3]) / (w + p[1] + p[3])),\n                this.prettify((h - parseInt($(element).css(\"top\"), 10) - p[2]) / (h - p[0] - p[2]))\n            ];\n        },\n\n        /**\n         * Paint canvas\n         *\n         * @param {Object} settings Paint settings\n         */\n        plot: function (settings) {\n            var xy = this.bezier.coordinates,\n                ctx = this.canvas.getContext(\"2d\"),\n                setting;\n\n            var defaultSettings = {\n                handleTimingFunction: \"#2893ef\",\n                handleThickness: 0.008,\n                vBorderThickness: 0.02,\n                hBorderThickness: 0.01,\n                bezierTimingFunction: \"#2893ef\",\n                bezierThickness: 0.03\n            };\n\n            settings = settings || {};\n\n            for (setting in defaultSettings) {\n                if (defaultSettings.hasOwnProperty(setting)) {\n                    if (!settings.hasOwnProperty(setting)) {\n                        settings[setting] = defaultSettings[setting];\n                    }\n                }\n            }\n\n            ctx.clearRect(-0.5, -0.5, 2, 2);\n\n            // Draw control handles\n            ctx.beginPath();\n            ctx.fillStyle = settings.handleTimingFunction;\n            ctx.lineWidth = settings.handleThickness;\n            ctx.strokeStyle = settings.handleTimingFunction;\n\n            ctx.moveTo(0, 0);\n            ctx.lineTo(xy[0], xy[1]);\n            ctx.moveTo(1, 1);\n            ctx.lineTo(xy[2], xy[3]);\n\n            ctx.stroke();\n            ctx.closePath();\n\n            ctx.beginPath();\n            ctx.arc(xy[0], xy[1], 1.5 * settings.handleThickness, 0, 2 * Math.PI, false);\n            ctx.closePath();\n\n            ctx.fill();\n\n            ctx.beginPath();\n            ctx.arc(xy[2], xy[3], 1.5 * settings.handleThickness, 0, 2 * Math.PI, false);\n            ctx.closePath();\n\n            ctx.fill();\n\n            // Draw bezier curve\n            ctx.beginPath();\n            ctx.lineWidth = settings.bezierThickness;\n            ctx.strokeStyle = settings.bezierColor;\n            ctx.moveTo(0, 0);\n            ctx.bezierCurveTo(xy[0], xy[1], xy[2], xy[3], 1, 1);\n            ctx.stroke();\n            ctx.closePath();\n        },\n\n        /**\n         * Convert CSS padding shorthand to longhand\n         *\n         * @param {number|Array.number} padding Element padding\n         * @return {Array.number}\n         */\n        getPadding: function (padding) {\n            var p = (typeof padding === \"number\") ? [padding] : padding;\n\n            if (p.length === 1) {\n                p[1] = p[0];\n            }\n            if (p.length === 2) {\n                p[2] = p[0];\n            }\n            if (p.length === 3) {\n                p[3] = p[1];\n            }\n\n            return p;\n        }\n    };\n\n    // Event handlers\n\n    /**\n     * Handle click in <canvas> element\n     *\n     * @param {Event} e Mouse click event\n     */\n    function _curveClick(e) {\n        var self = e.target,\n            bezierEditor = self.bezierEditor;\n\n        var curveBoundingBox = bezierEditor._getCurveBoundingBox(),\n            left = curveBoundingBox.left,\n            top  = curveBoundingBox.top,\n            x    = e.pageX - left,\n            y    = e.pageY - top - HEIGHT_ABOVE,\n            $P1  = $(bezierEditor.P1),\n            $P2  = $(bezierEditor.P2);\n\n        // Helper function to calculate distance between 2-D points\n        function distance(x1, y1, x2, y2) {\n            return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));\n        }\n\n        // Find which point is closer\n        var distP1 = distance(x, y, parseInt($P1.css(\"left\"), 10), parseInt($P1.css(\"top\"), 10)),\n            distP2 = distance(x, y, parseInt($P2.css(\"left\"), 10), parseInt($P2.css(\"top\"), 10)),\n            $P     = (distP1 < distP2) ? $P1 : $P2;\n\n        $P.css({\n            left: x + \"px\",\n            top:  y + \"px\"\n        });\n        $P.get(0).focus();\n\n        // update coords\n        bezierEditor._cubicBezierCoords = bezierEditor.bezierCanvas\n            .offsetsToCoordinates(bezierEditor.P1)\n            .concat(bezierEditor.bezierCanvas.offsetsToCoordinates(bezierEditor.P2));\n\n        bezierEditor._commitTimingFunction();\n        bezierEditor._updateCanvas();\n    }\n\n    /**\n     * Helper function for handling point move\n     *\n     * @param {Event} e Mouse move event\n     * @param {number} x New horizontal position\n     * @param {number} y New vertical position\n     */\n    function handlePointMove(e, x, y) {\n        var self = e.target,\n            bezierEditor = self.bezierEditor;\n\n        // Helper function to redraw curve\n        function mouseMoveRedraw() {\n            if (!bezierEditor.dragElement) {\n                animationRequest = null;\n                return;\n            }\n\n            // Update code\n            bezierEditor._commitTimingFunction();\n\n            bezierEditor._updateCanvas();\n            animationRequest = window.requestAnimationFrame(mouseMoveRedraw);\n        }\n\n        // This is a dragging state, but left button is no longer down, so mouse\n        // exited element, was released, and re-entered element. Treat like a drop.\n        if (bezierEditor.dragElement && (e.which !== 1)) {\n            bezierEditor.dragElement = null;\n            bezierEditor._commitTimingFunction();\n            bezierEditor._updateCanvas();\n            bezierEditor = null;\n            return;\n        }\n\n        // Constrain time (x-axis) to 0 to 1 range. Progression (y-axis) is\n        // theoretically not constrained, although canvas to drawing curve is\n        // arbitrarily constrained to -0.5 to 1.5 range.\n        x = Math.min(Math.max(0, x), WIDTH_MAIN);\n\n        if (bezierEditor.dragElement) {\n            $(bezierEditor.dragElement).css({\n                left: x + \"px\",\n                top:  y + \"px\"\n            });\n        }\n\n        // update coords\n        bezierEditor._cubicBezierCoords = bezierEditor.bezierCanvas\n            .offsetsToCoordinates(bezierEditor.P1)\n            .concat(bezierEditor.bezierCanvas.offsetsToCoordinates(bezierEditor.P2));\n\n        if (!animationRequest) {\n            animationRequest = window.requestAnimationFrame(mouseMoveRedraw);\n        }\n    }\n\n    /**\n     * Update Time (x-axis) and Progression (y-axis) data for mouse position\n     *\n     * @param {Element} canvas <canvas> element\n     * @param {number} x Horizontal position\n     * @param {number} y Vertical position\n     */\n    function updateTimeProgression(curve, x, y) {\n        var percentX = Math.round(100 * x / WIDTH_MAIN),\n            percentY = Math.round(100 * ((HEIGHT_MAIN - y) / HEIGHT_MAIN));\n\n        // Constrain horizontal percentage to [0, 100] range\n        percentX = Math.min(Math.max(0, percentX), 100);\n\n        curve.parentNode.setAttribute(\"data-time\", percentX);\n        curve.parentNode.setAttribute(\"data-progression\", percentY);\n    }\n\n    /**\n     * Handle mouse move in <canvas> element\n     *\n     * @param {Event} e Mouse move event\n     */\n    function _curveMouseMove(e) {\n        var self = e.target,\n            bezierEditor = self.bezierEditor,\n            curveBoundingBox = bezierEditor._getCurveBoundingBox(),\n            left   = curveBoundingBox.left,\n            top    = curveBoundingBox.top,\n            x = e.pageX - left,\n            y = e.pageY - top - HEIGHT_ABOVE;\n\n        updateTimeProgression(self, x, y);\n\n        if (bezierEditor.dragElement) {\n            if (e.pageX === 0 && e.pageY === 0) {\n                return;\n            }\n\n            handlePointMove(e, x, y);\n        }\n    }\n\n    /**\n     * Handle mouse move in <button> element\n     *\n     * @param {Event} e Mouse move event\n     */\n    function _pointMouseMove(e) {\n        var self = e.target,\n            bezierEditor = self.bezierEditor,\n            curveBoundingBox = bezierEditor._getCurveBoundingBox(),\n            left = curveBoundingBox.left,\n            top  = curveBoundingBox.top,\n            x = e.pageX - left,\n            y = e.pageY - top - HEIGHT_ABOVE;\n\n        updateTimeProgression(bezierEditor.curve, x, y);\n\n        if (e.pageX === 0 && e.pageY === 0) {\n            return;\n        }\n\n        handlePointMove(e, x, y);\n    }\n\n    /**\n     * Handle mouse down in <button> element\n     *\n     * @param {Event} e Mouse down event\n     */\n    function _pointMouseDown(e) {\n        var self = e.target;\n\n        self.bezierEditor.dragElement = self;\n    }\n\n    /**\n     * Handle mouse up in <button> element\n     *\n     * @param {Event} e Mouse up event\n     */\n    function _pointMouseUp(e) {\n        var self = e.target;\n\n        self.focus();\n\n        if (self.bezierEditor.dragElement) {\n            self.bezierEditor.dragElement = null;\n            self.bezierEditor._commitTimingFunction();\n            self.bezierEditor._updateCanvas();\n        }\n    }\n\n    /**\n     * Handle key down in <button> element\n     *\n     * @param {Event} e Key down event\n     */\n    function _pointKeyDown(e) {\n        var code = e.keyCode,\n            self = e.target,\n            bezierEditor = self.bezierEditor;\n\n        if (code >= KeyEvent.DOM_VK_LEFT && code <= KeyEvent.DOM_VK_DOWN) {\n            e.preventDefault();\n\n            // Arrow keys pressed\n            var $this = $(e.target),\n                left = parseInt($this.css(\"left\"), 10),\n                top  = parseInt($this.css(\"top\"), 10),\n                offset = (e.shiftKey ? 15 : 3),\n                newVal;\n\n            switch (code) {\n            case KeyEvent.DOM_VK_LEFT:\n                newVal = Math.max(0, left - offset);\n                if (left === newVal) {\n                    return false;\n                }\n                $this.css({ left: newVal + \"px\" });\n                break;\n            case KeyEvent.DOM_VK_UP:\n                newVal = Math.max(-HEIGHT_ABOVE, top - offset);\n                if (top === newVal) {\n                    return false;\n                }\n                $this.css({ top: newVal + \"px\" });\n                break;\n            case KeyEvent.DOM_VK_RIGHT:\n                newVal = Math.min(WIDTH_MAIN, left + offset);\n                if (left === newVal) {\n                    return false;\n                }\n                $this.css({ left: newVal + \"px\" });\n                break;\n            case KeyEvent.DOM_VK_DOWN:\n                newVal = Math.min(HEIGHT_MAIN + HEIGHT_BELOW, top + offset);\n                if (top === newVal) {\n                    return false;\n                }\n                $this.css({ top: newVal + \"px\" });\n                break;\n            }\n\n            // update coords\n            bezierEditor._cubicBezierCoords = bezierEditor.bezierCanvas\n                .offsetsToCoordinates(bezierEditor.P1)\n                .concat(bezierEditor.bezierCanvas.offsetsToCoordinates(bezierEditor.P2));\n\n            bezierEditor._commitTimingFunction();\n            bezierEditor._updateCanvas();\n            return true;\n\n        } else if (code === KeyEvent.DOM_VK_ESCAPE) {\n            return true;\n        } else if (code === KeyEvent.DOM_VK_TAB && !e.ctrlKey && !e.metaKey && !e.altKey) {\n            // Switch between the two points by tabbing\n            if ($(e.target).hasClass(\"P1\")) {\n                $(\".P2\").focus();\n            } else {\n                $(\".P1\").focus();\n            }\n            e.preventDefault();\n            return true;\n        }\n\n        return false;\n    }\n\n\n    /**\n     * Constructor for BezierCurveEditor Object. This control may be used standalone\n     * or within an InlineTimingFunctionEditor inline widget.\n     *\n     * @param {!jQuery} $parent  DOM node into which to append the root of the bezier curve editor UI\n     * @param {!RegExpMatch} bezierCurve  RegExp match object of initially selected bezierCurve\n     * @param {!function(string)} callback  Called whenever selected bezierCurve changes\n     */\n    function BezierCurveEditor($parent, bezierCurve, callback) {\n        // Create the DOM structure, filling in localized strings via Mustache\n        this.$element = $(Mustache.render(BezierCurveEditorTemplate, Strings));\n        $parent.append(this.$element);\n\n        this._callback = callback;\n        this.dragElement = null;\n\n        // current cubic-bezier() function params\n        this._cubicBezierCoords = this._getCubicBezierCoords(bezierCurve);\n\n        this.hint = {};\n        this.hint.elem = $(\".hint\", this.$element);\n        // If function was auto-corrected, then originalString holds the original function,\n        // and an informational message needs to be shown\n        if (bezierCurve.originalString) {\n            TimingFunctionUtils.showHideHint(this.hint, true, bezierCurve.originalString, \"cubic-bezier(\" + this._cubicBezierCoords.join(\", \") + \")\");\n        } else {\n            TimingFunctionUtils.showHideHint(this.hint, false);\n        }\n\n        this.P1 = this.$element.find(\".P1\")[0];\n        this.P2 = this.$element.find(\".P2\")[0];\n        this.curve = this.$element.find(\".curve\")[0];\n\n        this.P1.bezierEditor = this.P2.bezierEditor = this.curve.bezierEditor = this;\n\n        this.bezierCanvas = new BezierCanvas(this.curve, null, [0, 0]);\n\n        // redraw canvas\n        this._updateCanvas();\n\n        $(this.curve)\n            .on(\"click\", _curveClick)\n            .on(\"mousemove\", _curveMouseMove);\n        $(this.P1)\n            .on(\"mousemove\", _pointMouseMove)\n            .on(\"mousedown\", _pointMouseDown)\n            .on(\"mouseup\", _pointMouseUp)\n            .on(\"keydown\", _pointKeyDown);\n        $(this.P2)\n            .on(\"mousemove\", _pointMouseMove)\n            .on(\"mousedown\", _pointMouseDown)\n            .on(\"mouseup\", _pointMouseUp)\n            .on(\"keydown\", _pointKeyDown);\n    }\n\n    /**\n     * Destructor called by InlineTimingFunctionEditor.onClosed()\n     */\n    BezierCurveEditor.prototype.destroy = function () {\n\n        this.P1.bezierEditor = this.P2.bezierEditor = this.curve.bezierEditor = null;\n\n        $(this.curve)\n            .off(\"click\", _curveClick)\n            .off(\"mousemove\", _curveMouseMove);\n        $(this.P1)\n            .off(\"mousemove\", _pointMouseMove)\n            .off(\"mousedown\", _pointMouseDown)\n            .off(\"mouseup\", _pointMouseUp)\n            .off(\"keydown\", _pointKeyDown);\n        $(this.P2)\n            .off(\"mousemove\", _pointMouseMove)\n            .off(\"mousedown\", _pointMouseDown)\n            .off(\"mouseup\", _pointMouseUp)\n            .off(\"keydown\", _pointKeyDown);\n    };\n\n\n    /** Returns the root DOM node of the BezierCurveEditor UI */\n    BezierCurveEditor.prototype.getRootElement = function () {\n        return this.$element;\n    };\n\n    /**\n     * Default focus needs to go somewhere, so give it to P1\n     */\n    BezierCurveEditor.prototype.focus = function () {\n        this.P1.focus();\n        return true;\n    };\n\n    /**\n     * Generates cubic-bezier function based on coords, and updates the doc\n     */\n    BezierCurveEditor.prototype._commitTimingFunction = function () {\n        var bezierCurveVal = \"cubic-bezier(\" +\n            this._cubicBezierCoords[0] + \", \" +\n            this._cubicBezierCoords[1] + \", \" +\n            this._cubicBezierCoords[2] + \", \" +\n            this._cubicBezierCoords[3] + \")\";\n        this._callback(bezierCurveVal);\n        TimingFunctionUtils.showHideHint(this.hint, false);\n    };\n\n    /**\n     * Handle all matches returned from TimingFunctionUtils.cubicBezierMatch() and\n     * return array of coords\n     *\n     * @param {RegExp.match} match Matches returned from cubicBezierMatch()\n     * @return {Array.number[4]}\n     */\n    BezierCurveEditor.prototype._getCubicBezierCoords = function (match) {\n\n        if (match[0].match(/^cubic-bezier/)) {\n            // cubic-bezier()\n            return match.slice(1, 5);\n        } else {\n            // handle special cases of cubic-bezier calls\n            switch (match[0]) {\n            case \"linear\":\n                return [ \"0\", \"0\", \"1\", \"1\" ];\n            case \"ease\":\n                return [ \".25\", \".1\", \".25\", \"1\" ];\n            case \"ease-in\":\n                return [ \".42\", \"0\", \"1\", \"1\" ];\n            case \"ease-out\":\n                return [ \"0\", \"0\", \".58\", \"1\" ];\n            case \"ease-in-out\":\n                return [ \".42\", \"0\", \".58\", \"1\" ];\n            }\n        }\n\n        window.console.log(\"brackets-cubic-bezier: getCubicBezierCoords() passed invalid RegExp match array\");\n        return [ \"0\", \"0\", \"0\", \"0\" ];\n    };\n\n    /**\n     * Get <canvas> element's bounding box\n     *\n     * @return {left: number, top: number, width: number, height: number}\n     */\n    BezierCurveEditor.prototype._getCurveBoundingBox = function () {\n        var $canvas = this.$element.find(\".curve\"),\n            canvasOffset = $canvas.offset();\n\n        return {\n            left:    canvasOffset.left,\n            top:     canvasOffset.top,\n            width:   $canvas.width(),\n            height:  $canvas.height()\n        };\n    };\n\n    /**\n     * Update <canvas> after a change\n     */\n    BezierCurveEditor.prototype._updateCanvas = function () {\n        // collect data, build model\n        if (this._cubicBezierCoords) {\n            this.bezierCanvas.bezier = window.bezier = new CubicBezier(this._cubicBezierCoords);\n\n            var offsets = this.bezierCanvas.getOffsets();\n\n            $(this.P1).css({\n                left: offsets[0].left,\n                top:  offsets[0].top\n            });\n            $(this.P2).css({\n                left: offsets[1].left,\n                top:  offsets[1].top\n            });\n\n            this.bezierCanvas.plot();\n        }\n    };\n\n    /**\n     * Handle external update\n     *\n     * @param {!RegExpMatch} bezierCurve  RegExp match object of updated bezierCurve\n     */\n    BezierCurveEditor.prototype.handleExternalUpdate = function (bezierCurve) {\n        this._cubicBezierCoords = this._getCubicBezierCoords(bezierCurve);\n        this._updateCanvas();\n        // If function was auto-corrected, then originalString holds the original function,\n        // and an informational message needs to be shown\n        if (bezierCurve.originalString) {\n            TimingFunctionUtils.showHideHint(this.hint, true, bezierCurve.originalString, \"cubic-bezier(\" + this._cubicBezierCoords.join(\", \") + \")\");\n        } else {\n            TimingFunctionUtils.showHideHint(this.hint, false);\n        }\n    };\n\n\n    exports.BezierCurveEditor = BezierCurveEditor;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/BezierCurveEditorTemplate.html",
    "content": "<div tabindex=\"-1\" class=\"bezier-curve-editor\">\n    <div class=\"cubic-bezier\">\n        <div class=\"coordinate-plane\">\n            <span   class=\"control-point P0\"></span>\n            <button class=\"control-point P1\"></button>\n            <button class=\"control-point P2\"></button>\n            <span   class=\"control-point P3\"></span>\n            <canvas height=\"300\" width=\"150\" class=\"curve\"></canvas>\n        </div>\n        <div class=\"info\">\n            <p>{{{BEZIER_EDITOR_INFO}}}</p>\n            <div class=\"hint\"></div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/InlineTimingFunctionEditor.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var InlineWidget         = brackets.getModule(\"editor/InlineWidget\").InlineWidget,\n        BezierCurveEditor    = require(\"BezierCurveEditor\").BezierCurveEditor,\n        StepEditor           = require(\"StepEditor\").StepEditor,\n        TimingFunctionUtils  = require(\"TimingFunctionUtils\");\n\n\n    /** @type {number} Global var used to provide a unique ID for each timingFunction editor instance's _origin field. */\n    var lastOriginId = 1;\n\n    /**\n     * Constructor for inline widget containing a BezierCurveEditor control\n     *\n     * @param {!RegExpMatch} timingFunction  RegExp match object of initially selected timingFunction\n     * @param {!CodeMirror.Bookmark} startBookmark\n     * @param {!CodeMirror.Bookmark} endBookmark\n     */\n    function InlineTimingFunctionEditor(timingFunction, startBookmark, endBookmark) {\n        this._timingFunction = timingFunction;\n        this._startBookmark = startBookmark;\n        this._endBookmark = endBookmark;\n        this._isOwnChange = false;\n        this._isHostChange = false;\n        this._origin = \"+InlineTimingFunctionEditor_\" + (lastOriginId++);\n\n        this._handleTimingFunctionChange = this._handleTimingFunctionChange.bind(this);\n        this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this);\n\n        InlineWidget.call(this);\n    }\n\n    InlineTimingFunctionEditor.prototype = Object.create(InlineWidget.prototype);\n    InlineTimingFunctionEditor.prototype.constructor = InlineTimingFunctionEditor;\n    InlineTimingFunctionEditor.prototype.parentClass = InlineWidget.prototype;\n\n    /** @type {!BezierCurveEditor} BezierCurveEditor instance */\n    InlineTimingFunctionEditor.prototype.timingFunctionEditor = null;\n\n    /** @type {!string} Current value of the timing function editor control */\n    InlineTimingFunctionEditor.prototype._timingFunction = null;\n\n    /**\n     * Start of the range of code we're attached to; _startBookmark.find() may by null if sync is lost.\n     * @type {!CodeMirror.Bookmark}\n     */\n    InlineTimingFunctionEditor.prototype._startBookmark = null;\n\n    /**\n     * End of the range of code we're attached to; _endBookmark.find() may by null if sync is lost or even\n     * in some cases when it's not. Call getCurrentRange() for the definitive text range we're attached to.\n     * @type {!CodeMirror.Bookmark}\n     */\n    InlineTimingFunctionEditor.prototype._endBookmark = null;\n\n    /** @type {boolean} True while we're syncing a timing function editor change into the code editor */\n    InlineTimingFunctionEditor.prototype._isOwnChange = null;\n\n    /** @type {boolean} True while we're syncing a code editor change into the timing function editor */\n    InlineTimingFunctionEditor.prototype._isHostChange = null;\n\n    /** @type {number} ID used to identify edits coming from this inline widget for undo batching */\n    InlineTimingFunctionEditor.prototype._origin = null;\n\n\n    /**\n     * Returns the current text range of the timingFunction we're attached to, or null if\n     * we've lost sync with what's in the code.\n     *\n     * @return {?{\n     *              start: {line:number, ch:number},\n     *              end:   {line:number, ch:number},\n     *              match: {RegExpMatch}\n     *          }}\n     */\n    InlineTimingFunctionEditor.prototype.getCurrentRange = function () {\n        var start, end;\n\n        start = this._startBookmark.find();\n        if (!start) {\n            return null;\n        }\n\n        end = this._endBookmark.find();\n        if (!end) {\n            end = { line: start.line };\n        }\n\n        // Even if we think we have a good end bookmark, we want to run the\n        // regexp match to see if there's a valid match that extends past the bookmark.\n        // This can happen if the user deletes the end of the existing timingFunction and then\n        // types some more.\n        // FUTURE: when we migrate to CodeMirror v3, we might be able to use markText()\n        // instead of two bookmarks to track the range. (In our current old version of\n        // CodeMirror v2, markText() isn't robust enough for this case.)\n        var line = this.hostEditor.document.getLine(start.line),\n            matches = TimingFunctionUtils.timingFunctionMatch(line.substr(start.ch), true),\n            originalLength;\n\n        // No longer have a match\n        if (!matches) {\n            return null;\n        }\n\n        originalLength = ((matches.originalString && matches.originalString.length) || matches[0].length);\n        // Note that end.ch is exclusive, so we don't need to add 1 before comparing to\n        // the matched length here.\n        if (end.ch === undefined || (end.ch - start.ch) !== originalLength) {\n            end.ch = start.ch + originalLength;\n            this._endBookmark.clear();\n            this._endBookmark = this.hostEditor._codeMirror.setBookmark(end);\n        }\n\n        if (end.ch === undefined) {\n            // We were unable to resync the end bookmark.\n            return null;\n        } else {\n            return {\n                start: start,\n                end:   end,\n                match: matches,\n                originalLength: originalLength\n            };\n        }\n    };\n\n    /**\n     * When the timing function editor's selected timingFunction changes, update text in code editor\n     * @param {!string} timingFunctionString\n     */\n    InlineTimingFunctionEditor.prototype._handleTimingFunctionChange = function (timingFunctionString) {\n        var self                = this,\n            timingFunctionMatch = TimingFunctionUtils.timingFunctionMatch(timingFunctionString, true);\n        if (timingFunctionMatch !== this._timingFunction) {\n            var range = this.getCurrentRange();\n            if (!range) {\n                return;\n            }\n\n            // Don't push the change back into the host editor if it came from the host editor.\n            if (!this._isHostChange) {\n                this._isOwnChange = true;\n                this.hostEditor.document.batchOperation(function () {\n                    // Replace old timingFunction in code with the editor's timing function, and select it\n                    self.hostEditor.document.replaceRange(timingFunctionString, range.start, range.end, self._origin);\n                    var newEnd = { line: range.start.line, ch: range.start.ch + timingFunctionString.length };\n                    self.hostEditor.setSelection(range.start, newEnd, false, 0, self._origin);\n                });\n                this._isOwnChange = false;\n            }\n\n            this._timingFunction = timingFunctionMatch;\n        }\n    };\n\n    /**\n     * @override\n     * @param {!Editor} hostEditor\n     */\n    InlineTimingFunctionEditor.prototype.load = function (hostEditor) {\n        InlineTimingFunctionEditor.prototype.parentClass.load.apply(this, arguments);\n\n        // Create appropriate timing function editor control\n        if (this._timingFunction.isBezier) {\n            this.timingFunctionEditor = new BezierCurveEditor(this.$htmlContent, this._timingFunction, this._handleTimingFunctionChange);\n        } else if (this._timingFunction.isStep) {\n            this.timingFunctionEditor = new StepEditor(this.$htmlContent, this._timingFunction, this._handleTimingFunctionChange);\n        } else {\n            window.console.log(\"InlineTimingFunctionEditor.load tried to load an unkown timing function type\");\n        }\n    };\n\n    /**\n     * @override\n     * Perform sizing & focus once we've been added to Editor's DOM\n     */\n    InlineTimingFunctionEditor.prototype.onAdded = function () {\n        InlineTimingFunctionEditor.prototype.parentClass.onAdded.apply(this, arguments);\n\n        var doc = this.hostEditor.document;\n        doc.addRef();\n        doc.on(\"change\", this._handleHostDocumentChange);\n\n        this.hostEditor.setInlineWidgetHeight(this, this.timingFunctionEditor.getRootElement().outerHeight(), true);\n\n        this.timingFunctionEditor.focus();\n    };\n\n    /**\n     * @override\n     * Called whenever the inline widget is closed, whether automatically or explicitly\n     */\n    InlineTimingFunctionEditor.prototype.onClosed = function () {\n        InlineTimingFunctionEditor.prototype.parentClass.onClosed.apply(this, arguments);\n\n        this.timingFunctionEditor.destroy();\n\n        if (this._startBookmark) {\n            this._startBookmark.clear();\n        }\n        if (this._endBookmark) {\n            this._endBookmark.clear();\n        }\n\n        var doc = this.hostEditor.document;\n        doc.off(\"change\", this._handleHostDocumentChange);\n        doc.releaseRef();\n    };\n\n    /**\n     * When text in the code editor changes, update timing function editor to reflect it\n     */\n    InlineTimingFunctionEditor.prototype._handleHostDocumentChange = function () {\n        // Don't push the change into the timingFunction editor if it came from the timingFunction editor.\n        if (this._isOwnChange) {\n            return;\n        }\n\n        var range = this.getCurrentRange();\n        if (range) {\n            if (range.match !== this._timingFunction) {\n                this._isHostChange = true;\n                this._isHostChange = false;\n                this._timingFunction = range.match;\n                this.timingFunctionEditor.handleExternalUpdate(range.match);\n            }\n        } else {\n            // The edit caused our range to become invalid. Close the editor.\n            this.close();\n        }\n    };\n\n    exports.InlineTimingFunctionEditor = InlineTimingFunctionEditor;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/Localized.css",
    "content": ".bezier-curve-editor .coordinate-plane:after,\n.step-editor .coordinate-plane:after {\n    content: '{{INLINE_TIMING_EDITOR_TIME}}';\n}\n\n.bezier-curve-editor .coordinate-plane:hover:before {\n    content: '{{INLINE_TIMING_EDITOR_PROGRESSION}} (' attr(data-progression) '%)';\n}\n\n.bezier-curve-editor .coordinate-plane:before,\n.step-editor .coordinate-plane:before {\n    content: '{{INLINE_TIMING_EDITOR_PROGRESSION}}';\n}\n\n.bezier-curve-editor .coordinate-plane:hover:after {\n    content: '{{INLINE_TIMING_EDITOR_TIME}} (' attr(data-time) '%)';\n}\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/StepEditor.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var KeyEvent    = brackets.getModule(\"utils/KeyEvent\"),\n        Strings     = brackets.getModule(\"strings\"),\n        Mustache    = brackets.getModule(\"thirdparty/mustache/mustache\");\n\n    var TimingFunctionUtils = require(\"TimingFunctionUtils\");\n\n    /** Mustache template that forms the bare DOM structure of the UI */\n    var StepEditorTemplate   = require(\"text!StepEditorTemplate.html\");\n\n    /** @const @type {number} */\n    var STEP_LINE   = 1,\n        DASH_LINE   = 2;\n\n    /**\n     * StepParameters object constructor\n     *\n     * @param {{ count: number, timing: string}} params Parameters passed to steps()\n     *      either in string or array format.\n     */\n    function StepParameters(params) {\n        if (!params) {\n            throw \"No parameters were defined\";\n        }\n\n        this.count  = params.count;\n        this.timing = params.timing;\n    }\n\n    /**\n     * StepCanvas object constructor\n     *\n     * @param {Element} canvas Inline editor <canvas> element\n     * @param {StepParameters} stepParams Associated StepParameters object\n     * @param {number|Array.number} padding Element padding\n     */\n    function StepCanvas(canvas, stepParams, padding) {\n        this.canvas     = canvas;\n        this.stepParams = stepParams;\n        this.padding    = this.getPadding(padding);\n\n        // Convert to a cartesian coordinate system with axes from 0 to 1\n        var ctx = this.canvas.getContext(\"2d\"),\n            p = this.padding;\n\n        ctx.scale(canvas.width * (1 - p[1] - p[3]), -canvas.height * (1 - p[0] - p[2]));\n        ctx.translate(p[3] / (1 - p[1] - p[3]), (-1 - p[0] / (1 - p[0] - p[2])));\n    }\n\n    StepCanvas.prototype = {\n\n        drawBackground: function () {\n            this.ctx.beginPath();\n            this.ctx.lineWidth   = this.settings.borderWidth;\n            this.ctx.strokeStyle = this.settings.borderColor;\n            this.ctx.fillStyle = this.settings.bgColor;\n            this.ctx.moveTo(0, 0);\n            this.ctx.lineTo(0, 1);\n            this.ctx.lineTo(1, 1);\n            this.ctx.lineTo(1, 0);\n            this.ctx.lineTo(0, 0);\n            this.ctx.stroke();\n            this.ctx.fill();\n            this.ctx.closePath();\n        },\n\n        drawPoint: function (x, y, isFilled) {\n            // Points are always step color\n            this.ctx.beginPath();\n            this.ctx.lineWidth   = this.settings.pointLineWidth;\n            this.ctx.strokeStyle = this.settings.stepColor;\n            this.ctx.arc(x, y, this.settings.pointRadius, 0, 2 * Math.PI, false);\n            this.ctx.stroke();\n            if (isFilled) {\n                this.ctx.fillStyle = this.settings.stepColor;\n                this.ctx.fill();\n            }\n            this.ctx.closePath();\n        },\n\n        drawLine: function (x1, y1, x2, y2, type) {\n            this.ctx.beginPath();\n            if (type === STEP_LINE) {\n                this.ctx.lineWidth   = this.settings.stepLineWidth;\n                this.ctx.strokeStyle = this.settings.stepColor;\n            } else if (type === DASH_LINE) {\n                this.ctx.lineWidth   = this.settings.dashLineWidth;\n                this.ctx.strokeStyle = this.settings.dashColor;\n            }\n            this.ctx.moveTo(x1, y1);\n            this.ctx.lineTo(x2, y2);\n            this.ctx.stroke();\n            this.ctx.closePath();\n        },\n\n        drawStartInterval: function (x1, y1, x2, y2) {\n            var pr = this.settings.pointRadius;\n\n            // Draw empty start point\n            this.drawPoint(x1, y1, false);\n\n            // Draw dashed line up to next step\n            this.drawLine(x1, y1 + pr, x1, y2, DASH_LINE);\n\n            // Draw filled mid point\n            this.drawPoint(x1, y2, true);\n\n            // Draw step line\n            this.drawLine(x1, y2, x2 - pr, y2, STEP_LINE);\n        },\n\n        drawEndInterval: function (x1, y1, x2, y2) {\n            var pr = this.settings.pointRadius;\n\n            // Draw filled start point\n            this.drawPoint(x1, y1, true);\n\n            // Draw step line\n            this.drawLine(x1, y1, x2 - pr, y1, STEP_LINE);\n\n            // Draw empty mid point\n            this.drawPoint(x2, y1, false);\n\n            // Draw dashed line up to next step\n            this.drawLine(x2, y1 + pr, x2, y2, DASH_LINE);\n        },\n\n        /**\n         * Paint canvas\n         *\n         * @param {Object} settings Paint settings\n         */\n        plot: function (settings) {\n            var setting, i, j, last, interval,\n                sp = this.stepParams,\n                isStart = (sp.timing === \"start\"),\n                p = [];\n\n            var defaultSettings = {\n                bgColor:        \"transparent\",\n                borderColor:    \"#bbb\",\n                stepColor:      \"#2893ef\",\n                dashColor:      \"#b8b8b8\",\n                borderWidth:    0.00667,\n                stepLineWidth:  0.02,\n                dashLineWidth:  0.008,\n                pointLineWidth: 0.008,\n                pointRadius:    0.015\n            };\n\n            this.settings = settings || {};\n\n            for (setting in defaultSettings) {\n                if (defaultSettings.hasOwnProperty(setting)) {\n                    if (!this.settings.hasOwnProperty(setting)) {\n                        this.settings[setting] = defaultSettings[setting];\n                    }\n                }\n            }\n\n            this.ctx = this.canvas.getContext(\"2d\");\n\n            // Build points array. There's a starting point at 0,0\n            // plus a point for each step\n            p[0] = { x: 0, y: 0 };\n            for (i = 1; i <= sp.count; i++) {\n                interval = i / sp.count;\n                p[i] = { x: interval, y: interval };\n            }\n\n            // Start with a clean slate\n            this.ctx.clearRect(-0.5, -0.5, 2, 2);\n            this.drawBackground();\n\n            // Draw each interval\n            last = p.length - 1;\n            for (i = 0, j = 1; i < last; i++, j++) {\n                if (isStart) {\n                    this.drawStartInterval(p[i].x, p[i].y, p[j].x, p[j].y);\n                } else {\n                    this.drawEndInterval(p[i].x, p[i].y, p[j].x, p[j].y);\n                }\n            }\n\n            // Each interval draws start and mid point for that interval,\n            // so we need to draw last point. It's always filled.\n            this.drawPoint(p[last].x, p[last].y, true);\n        },\n\n        /**\n         * Convert CSS padding shorthand to longhand\n         *\n         * @param {number|Array.number} padding Element padding\n         * @return {Array.number}\n         */\n        getPadding: function (padding) {\n            var p = (typeof padding === \"number\") ? [padding] : padding;\n\n            if (p.length === 1) {\n                p[1] = p[0];\n            }\n            if (p.length === 2) {\n                p[2] = p[0];\n            }\n            if (p.length === 3) {\n                p[3] = p[1];\n            }\n\n            return p;\n        }\n    };\n\n    // Event handlers\n\n    /**\n     * Handle key down in <canvas> element\n     *\n     * @param {Event} e Key down event\n     */\n    function _canvasKeyDown(e) {\n        var code = e.keyCode,\n            self = e.target,\n            stepEditor = self.stepEditor;\n\n        if (code >= KeyEvent.DOM_VK_LEFT && code <= KeyEvent.DOM_VK_DOWN) {\n            e.preventDefault();\n\n            // Arrow keys pressed\n            switch (code) {\n            case KeyEvent.DOM_VK_LEFT:\n                stepEditor.stepCanvas.stepParams.timing = \"start\";\n                break;\n            case KeyEvent.DOM_VK_UP:\n                // No upper limit\n                stepEditor.stepCanvas.stepParams.count++;\n                break;\n            case KeyEvent.DOM_VK_RIGHT:\n                stepEditor.stepCanvas.stepParams.timing = \"end\";\n                break;\n            case KeyEvent.DOM_VK_DOWN:\n                if (stepEditor.stepCanvas.stepParams.count > 1) {\n                    stepEditor.stepCanvas.stepParams.count--;\n                }\n                break;\n            }\n\n            // update step params\n            stepEditor._stepParams = stepEditor.stepCanvas.stepParams;\n\n            stepEditor._commitTimingFunction();\n            stepEditor._updateCanvas();\n            return true;\n\n        } else if (code === KeyEvent.DOM_VK_ESCAPE) {\n            return true;\n        }\n\n        return false;\n    }\n\n\n    /**\n     * Constructor for StepEditor Object. This control may be used standalone\n     * or within an InlineTimingFunctionEditor inline widget.\n     *\n     * @param {!jQuery} $parent  DOM node into which to append the root of the step editor UI\n     * @param {!RegExpMatch} stepMatch  RegExp match object of initially selected step function\n     * @param {!function(string)} callback  Called whenever selected step function changes\n     */\n    function StepEditor($parent, stepMatch, callback) {\n        // Create the DOM structure, filling in localized strings via Mustache\n        this.$element = $(Mustache.render(StepEditorTemplate, Strings));\n        $parent.append(this.$element);\n\n        this._callback = callback;\n\n        // current step function params\n        this._stepParams = this._getStepParams(stepMatch);\n\n        this.hint = {};\n        this.hint.elem = $(\".hint\", this.$element);\n        // If function was auto-corrected, then originalString holds the original function,\n        // and an informational message needs to be shown\n        if (stepMatch.originalString) {\n            TimingFunctionUtils.showHideHint(this.hint, true, stepMatch.originalString, \"steps(\" + this._stepParams.count.toString() + \", \" + this._stepParams.timing + \")\");\n        } else {\n            TimingFunctionUtils.showHideHint(this.hint, false);\n        }\n\n        this.canvas = this.$element.find(\".steps\")[0];\n\n        this.canvas.stepEditor = this;\n\n        // Padding (3rd param)is scaled, so 0.1 translates to 15px\n        // Note that this is rendered inside canvas CSS \"content\"\n        // (i.e. this does not map to CSS padding)\n        this.stepCanvas = new StepCanvas(this.canvas, null, [0.1]);\n\n        // redraw canvas\n        this._updateCanvas();\n\n        $(this.canvas).on(\"keydown\", _canvasKeyDown);\n    }\n\n    /**\n     * Destructor called by InlineTimingFunctionEditor.onClosed()\n     */\n    StepEditor.prototype.destroy = function () {\n        this.canvas.stepEditor = null;\n        $(this.canvas).off(\"keydown\", _canvasKeyDown);\n    };\n\n\n    /** Returns the root DOM node of the StepEditor UI */\n    StepEditor.prototype.getRootElement = function () {\n        return this.$element;\n    };\n\n    /**\n     * Default focus needs to go somewhere, so give it to canvas\n     */\n    StepEditor.prototype.focus = function () {\n        this.canvas.focus();\n        return true;\n    };\n\n    /**\n     * Generates step function based on parameters, and updates the doc\n     */\n    StepEditor.prototype._commitTimingFunction = function () {\n        var stepFuncVal = \"steps(\" +\n            this._stepParams.count.toString() + \", \" +\n            this._stepParams.timing + \")\";\n        this._callback(stepFuncVal);\n        TimingFunctionUtils.showHideHint(this.hint, false);\n    };\n\n    /**\n     * Handle all matches returned from TimingFunctionUtils.stepMatch() and\n     * return array of coords\n     *\n     * @param {RegExp.match} match Matches returned from stepMatch()\n     * @return {{count: number, timing: string}}\n     */\n    StepEditor.prototype._getStepParams = function (match) {\n\n        if (match[0].match(/^steps/)) {\n            // steps()\n            return {\n                count:  parseInt(match[1], 10),\n                timing: match[2] || \"end\"\n            };\n        } else {\n            // handle special cases of steps functions\n            switch (match[0]) {\n            case \"step-start\":\n                return { count: 1, timing: \"start\" };\n            case \"step-end\":\n                return { count: 1, timing: \"end\" };\n            }\n        }\n\n        window.console.log(\"step timing function: _getStepParams() passed invalid RegExp match array\");\n        return { count: 1, timing: \"end\" };\n    };\n\n    /**\n     * Get <canvas> element's bounding box\n     *\n     * @return {left: number, top: number, width: number, height: number}\n     */\n    StepEditor.prototype._getCanvasBoundingBox = function () {\n        var $canvas = this.$element.find(\".steps\"),\n            canvasOffset = $canvas.offset();\n\n        return {\n            left:    canvasOffset.left,\n            top:     canvasOffset.top,\n            width:   $canvas.width(),\n            height:  $canvas.height()\n        };\n    };\n\n    /**\n     * Update <canvas> after a change\n     */\n    StepEditor.prototype._updateCanvas = function () {\n        // collect data, build model\n        if (this._stepParams) {\n            this.stepCanvas.stepParams = window.stepParams = new StepParameters(this._stepParams);\n\n            this.stepCanvas.plot();\n        }\n    };\n\n    /**\n     * Handle external update\n     *\n     * @param {!RegExpMatch} stepMatch  RegExp match object of updated step function\n     */\n    StepEditor.prototype.handleExternalUpdate = function (stepMatch) {\n        this._stepParams = this._getStepParams(stepMatch);\n        this._updateCanvas();\n        // If function was auto-corrected, then originalString holds the original function,\n        // and an informational message needs to be shown\n        if (stepMatch.originalString) {\n            TimingFunctionUtils.showHideHint(this.hint, true, stepMatch.originalString, \"steps(\" + this._stepParams.count.toString() + \", \" + this._stepParams.timing + \")\");\n        } else {\n            TimingFunctionUtils.showHideHint(this.hint, false);\n        }\n    };\n\n\n    exports.StepEditor = StepEditor;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/StepEditorTemplate.html",
    "content": "<div tabindex=\"-1\" class=\"step-editor\">\n    <div class=\"steps-func\">\n        <div class=\"coordinate-plane\">\n            <canvas height=\"180\" width=\"180\" class=\"steps\" tabindex=\"1\"></canvas>\n        </div>\n        <div class=\"info\">\n            <p>{{{STEPS_EDITOR_INFO}}}</p>\n            <div class=\"hint\"></div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/TimingFunctionUtils.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\n/**\n *  Utilities functions related to color matching\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Strings         = brackets.getModule(\"strings\"),\n        StringUtils     = brackets.getModule(\"utils/StringUtils\"),\n        AnimationUtils  = brackets.getModule(\"utils/AnimationUtils\");\n\n    /**\n     * Regular expressions for matching timing functions\n     * @const @type {RegExp}\n     */\n    var BEZIER_CURVE_VALID_REGEX        = /cubic-bezier\\(\\s*(\\S+)\\s*,\\s*(\\S+)\\s*,\\s*(\\S+)\\s*,\\s*(\\S+)\\s*\\)/,\n        BEZIER_CURVE_GENERAL_REGEX      = /cubic-bezier\\((.*)\\)/,\n        EASE_STRICT_REGEX               = /[: ,]ease(?:-in)?(?:-out)?[ ,;]/,\n        EASE_LAX_REGEX                  = /ease(?:-in)?(?:-out)?/,\n        LINEAR_STRICT_REGEX             = /(transition|animation).*?[: ,]linear[ ,;]/,\n        LINEAR_LAX_REGEX                = /linear/,\n        STEPS_VALID_REGEX               = /steps\\(\\s*(\\d+)\\s*(?:,\\s*(\\w+)\\s*)?\\)/,\n        STEPS_GENERAL_REGEX             = /steps\\((.*)\\)/,\n        STEP_STRICT_REGEX               = /[: ,](?:step-start|step-end)[ ,;]/,\n        STEP_LAX_REGEX                  = /step-start|step-end/;\n\n    /**\n     * Type constants\n     * @const @type {number}\n     */\n    var BEZIER  = 1,\n        STEP    = 2;\n\n    /**\n     * If string is a number, then convert it.\n     *\n     * @param {string} str  value parsed from page.\n     * @return { isNumber: boolean, value: ?number }\n     */\n    function _convertToNumber(str) {\n        if (typeof str !== \"string\") {\n            return { isNumber: false, value: null };\n        }\n\n        var val = parseFloat(+str, 10),\n            isNum = (typeof val === \"number\") && !isNaN(val) &&\n                    (val !== Infinity) && (val !== -Infinity);\n\n        return {\n            isNumber: isNum,\n            value:    val\n        };\n    }\n\n    /**\n     * Get valid params for an invalid cubic-bezier.\n     *\n     * @param {RegExp.match} match (Invalid) matches from cubicBezierMatch()\n     * @return {?RegExp.match} Valid match or null if the output is not valid\n     */\n    function _getValidBezierParams(match) {\n        var param,\n            // take ease-in-out as default value in case there are no params yet (or they are invalid)\n            def = [ \".42\", \"0\", \".58\", \"1\" ],\n            oldIndex = match.index, // we need to store the old match.index to re-set the index afterwards\n            originalString = match[0],\n            i;\n\n        if (match) {\n            match = match[1].split(\",\");\n        }\n\n        if (match) {\n            for (i = 0; i <= 3; i++) {\n                if (match[i]) {\n                    match[i] = match[i].trim();\n                    param = _convertToNumber(match[i]);\n\n                    // Verify the param is a number\n                    // If not, replace it with the default value\n                    if (!param.isNumber) {\n                        match[i] = undefined;\n\n                    // Verify x coordinates are in 0-1 range\n                    // If not, set them to the closest value in range\n                    } else if (i === 0 || i === 2) {\n                        if (param.value < 0) {\n                            match[i] = \"0\";\n                        } else if (param.value > 1) {\n                            match[i] = \"1\";\n                        }\n                    }\n                }\n\n                if (!match[i]) {\n                    match[i] = def[i];\n                }\n            }\n        } else {\n            match = def;\n        }\n        match = match.splice(0, 4); // make sure there are only 4 params\n        match = \"cubic-bezier(\" + match.join(\", \") + \")\";\n        match = match.match(BEZIER_CURVE_VALID_REGEX);\n\n        if (match) {\n            match.index = oldIndex; // re-set the index here to get the right context\n            match.originalString = originalString;\n            return match;\n        }\n        return null;\n    }\n\n    /**\n     * Validate cubic-bezier function parameters that are not already validated by regex:\n     *\n     * @param {RegExp.match} match  RegExp Match object with cubic-bezier function parameters\n     *                              in array positions 1-4.\n     * @return {boolean} true if all parameters are valid, otherwise, false\n     */\n    function _validateCubicBezierParams(match) {\n        var x1 = _convertToNumber(match[1]),\n            y1 = _convertToNumber(match[2]),\n            x2 = _convertToNumber(match[3]),\n            y2 = _convertToNumber(match[4]);\n\n        // Verify all params are numbers\n        if (!x1.isNumber || !y1.isNumber || !x2.isNumber || !y2.isNumber) {\n            return false;\n        }\n\n        // Verify x params are in 0-1 range\n        if (x1.value < 0 || x1.value > 1 || x2.value < 0 || x2.value > 1) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Get valid params for an invalid steps function.\n     *\n     * @param {RegExp.match} match (Invalid) matches from stepsMatch()\n     * @return {?RegExp.match} Valid match or null if the output is not valid\n     */\n    function _getValidStepsParams(match) {\n        var param,\n            def = [ \"5\", \"end\" ],\n            params = def,\n            oldIndex = match.index, // we need to store the old match.index to re-set the index afterwards\n            originalString = match[0];\n\n        if (match) {\n            match = match[1].split(\",\");\n        }\n\n        if (match) {\n            if (match[0]) {\n                param = match[0].replace(/[\\s\\\"']/g, \"\"); // replace possible trailing whitespace or leading quotes\n                param = _convertToNumber(param);\n\n                // Verify number_of_params is a number\n                // If not, replace it with the default value\n                if (!param.isNumber) {\n                    param.value = def[0];\n\n                // Round number_of_params to an integer\n                } else if (param.value) {\n                    param.value = Math.floor(param.value);\n                }\n\n                // Verify number_of_steps is >= 1\n                // If not, set them to the default value\n                if (param.value < 1) {\n                    param.value = def[0];\n                }\n                params[0] = param.value;\n            }\n            if (match[1]) {\n                // little autocorrect feature: leading s gets 'start', everything else gets 'end'\n                param = match[1].replace(/[\\s\\\"']/g, \"\"); // replace possible trailing whitespace or leading quotes\n                param = param.substr(0, 1);\n                if (param === \"s\") {\n                    params[1] = \"start\";\n                } else {\n                    params[1] = \"end\";\n                }\n            }\n        }\n        params = \"steps(\" + params.join(\", \") + \")\";\n        params = params.match(STEPS_VALID_REGEX);\n\n        if (params) {\n            params.index = oldIndex; // re-set the index here to get the right context\n            params.originalString = originalString;\n            return params;\n        }\n        return null;\n    }\n\n    /**\n     * Validate steps function parameters that are not already validated by regex:\n     *\n     * @param {RegExp.match} match  RegExp Match object with steps function parameters\n     *                              in array position 1 (and optionally 2).\n     * @return {boolean} true if all parameters are valid, otherwise, false\n     */\n    function _validateStepsParams(match) {\n        var count = _convertToNumber(match[1]);\n\n        if (!count.isNumber || count.value < 1 || Math.floor(count.value) !== count.value) {\n            return false;\n        }\n\n        if (match[2] && match[2] !== \"start\" && match[2] !== \"end\") {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Show, hide or update the hint text\n     *\n     * @param {object} hint Editor.hint object of the current InlineTimingFunctionEditor\n     * @param {boolean} show Whether the hint should be shown or hidden\n     * @param {string=} documentCode The invalid code from the document (can be omitted when hiding)\n     * @param {string=} editorCode The valid code that is shown in the Inline Editor (can be omitted when hiding)\n     */\n    function showHideHint(hint, show, documentCode, editorCode) {\n        if (!hint || !hint.elem) {\n            return;\n        }\n\n        if (show) {\n            hint.shown = true;\n            hint.animationInProgress = false;\n            hint.elem.removeClass(\"fadeout\");\n            hint.elem.html(StringUtils.format(Strings.INLINE_TIMING_EDITOR_INVALID, documentCode, editorCode));\n            hint.elem.css(\"display\", \"block\");\n        } else if (hint.shown) {\n            hint.animationInProgress = true;\n            AnimationUtils.animateUsingClass(hint.elem[0], \"fadeout\", 750)\n                .done(function () {\n                    if (hint.animationInProgress) { // do this only if the animation was not cancelled\n                        hint.elem.hide();\n                    }\n                    hint.shown = false;\n                    hint.animationInProgress = false;\n                });\n        } else {\n            hint.elem.hide();\n        }\n    }\n\n    /**\n     * Tag this match with type and return it for chaining\n     *\n     * @param {!RegExp.match} match  RegExp Match object with steps function parameters\n     *                              in array position 1 (and optionally 2).\n     * @param {number} type Either BEZIER or STEP\n     * @return {RegExp.match} Same object that was passed in.\n     */\n    function _tagMatch(match, type) {\n        switch (type) {\n        case BEZIER:\n            match.isBezier = true;\n            break;\n        case STEP:\n            match.isStep = true;\n            break;\n        }\n\n        return match;\n    }\n\n    /**\n     * Match a bezier curve function value from a CSS Declaration or Value.\n     *\n     * Matches returned from this function must be handled in\n     * BezierCurveEditor._getCubicBezierCoords().\n     *\n     * @param {string} str  Input string.\n     * @param {!boolean} lax  Parsing mode where:\n     *          lax=false Input is a Full or partial line containing CSS Declaration.\n     *                    This is the more strict search used for initial detection.\n     *          lax=true  Input is a previously parsed value. This is the less strict search\n     *                    used to convert previously parsed values to RegExp match format.\n     * @return {!RegExpMatch}\n     */\n    function bezierCurveMatch(str, lax) {\n        var match;\n\n        // First look for any cubic-bezier().\n        match = str.match(BEZIER_CURVE_VALID_REGEX);\n        if (match && _validateCubicBezierParams(match)) { // cubic-bezier() with valid params\n            return _tagMatch(match, BEZIER);\n        }\n\n        match = str.match(BEZIER_CURVE_GENERAL_REGEX);\n        if (match) {\n            match = _getValidBezierParams(match);\n            if (match && _validateCubicBezierParams(match)) {\n                return _tagMatch(match, BEZIER);\n            } else { // this should not happen!\n                window.console.log(\"brackets-cubic-bezier: TimingFunctionUtils._getValidBezierParams created invalid code\");\n            }\n        }\n\n        // Next look for the ease functions (which are special cases of cubic-bezier())\n        if (lax) {\n            // For lax parsing, just look for the keywords\n            match = str.match(EASE_LAX_REGEX);\n            if (match) {\n                return _tagMatch(match, BEZIER);\n            }\n        } else {\n            // For strict parsing, start with a syntax verifying search\n            match = str.match(EASE_STRICT_REGEX);\n            if (match) {\n                // return exact match to keyword that we need for later replacement\n                return _tagMatch(str.match(EASE_LAX_REGEX), BEZIER);\n            }\n        }\n\n        // Final case is linear.\n        if (lax) {\n            // For lax parsing, just look for the keyword\n            match = str.match(LINEAR_LAX_REGEX);\n            if (match) {\n                return _tagMatch(match, BEZIER);\n            }\n        } else {\n            // The linear keyword can occur in other values, so for strict parsing we\n            // only detect when it's on same line as \"transition\" or \"animation\"\n            match = str.match(LINEAR_STRICT_REGEX);\n            if (match) {\n                // return exact match to keyword that we need for later replacement\n                return _tagMatch(str.match(LINEAR_LAX_REGEX), BEZIER);\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Match a steps function value from a CSS Declaration or Value.\n     *\n     * Matches returned from this function must be handled in\n     * BezierCurveEditor._getCubicBezierCoords().\n     *\n     * @param {string} str  Input string.\n     * @param {!boolean} lax  Parsing mode where:\n     *          lax=false Input is a Full or partial line containing CSS Declaration.\n     *                    This is the more strict search used for initial detection.\n     *          lax=true  Input is a previously parsed value. This is the less strict search\n     *                    used to convert previously parsed values to RegExp match format.\n     * @return {!RegExpMatch}\n     */\n    function stepsMatch(str, lax) {\n        var match;\n\n        // First look for any steps().\n        match = str.match(STEPS_VALID_REGEX);\n        if (match && _validateStepsParams(match)) { // cubic-bezier() with valid params\n            return _tagMatch(match, STEP);\n        }\n\n        match = str.match(STEPS_GENERAL_REGEX);\n        if (match) {\n            match = _getValidStepsParams(match);\n            if (match && _validateStepsParams(match)) {\n                return _tagMatch(match, STEP);\n            } else { // this should not happen!\n                window.console.log(\"brackets-steps: TimingFunctionUtils._getValidStepsParams created invalid code\");\n            }\n        }\n\n        // Next look for the step functions (which are special cases of steps())\n        if (lax) {\n            // For lax parsing, just look for the keywords\n            match = str.match(STEP_LAX_REGEX);\n            if (match) {\n                return _tagMatch(match, STEP);\n            }\n        } else {\n            // For strict parsing, start with a syntax verifying search\n            match = str.match(STEP_STRICT_REGEX);\n            if (match) {\n                // return exact match to keyword that we need for later replacement\n                return _tagMatch(str.match(STEP_LAX_REGEX), STEP);\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Match a timing function value from a CSS Declaration or Value.\n     *\n     * Matches returned from this function must be handled in\n     * BezierCurveEditor._getCubicBezierCoords().\n     *\n     * @param {string} str  Input string.\n     * @param {!boolean} lax  Parsing mode where:\n     *          lax=false Input is a Full or partial line containing CSS Declaration.\n     *                    This is the more strict search used for initial detection.\n     *          lax=true  Input is a previously parsed value. This is the less strict search\n     *                    used to convert previously parsed values to RegExp match format.\n     * @return {!RegExpMatch}\n     */\n    function timingFunctionMatch(str, lax) {\n        return bezierCurveMatch(str, lax) || stepsMatch(str, lax);\n    }\n\n    // Define public API\n    exports.timingFunctionMatch = timingFunctionMatch;\n    exports.bezierCurveMatch    = bezierCurveMatch;\n    exports.stepsMatch          = stepsMatch;\n    exports.showHideHint        = showHideHint;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/*\n * The timing function canvas and editing code was adapted from Lea Verou's cubic-bezier project:\n * - https://github.com/LeaVerou/cubic-bezier (cubic-bezier.com)\n *\n * The canvas exceeds the top and bottom of main grid so y-value of points can be\n * dragged outside of the 0-1 range.\n *\n *   . . . . . .\n *   .         .\n *   +---------+\n *   |         |\n *   |         |\n *   |         |\n *   |         |\n *   +---------+ <-- main grid has height of 150\n *   .         .\n *   . . . . . . <-- canvas has height of 300 (extra 75 above/below)\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        Mustache            = brackets.getModule(\"thirdparty/mustache/mustache\"),\n\n        InlineTimingFunctionEditor = require(\"InlineTimingFunctionEditor\").InlineTimingFunctionEditor,\n        TimingFunctionUtils        = require(\"TimingFunctionUtils\"),\n        Localized                  = require(\"text!Localized.css\");\n\n\n    // Functions\n\n\n    /**\n     * Prepare hostEditor for an InlineTimingFunctionEditor at pos if possible.\n     * Return editor context if so; otherwise null.\n     *\n     * @param {Editor} hostEditor\n     * @param {{line:Number, ch:Number}} pos\n     * @return {timingFunction:{?string}, reason:{?string}, start:{?TextMarker}, end:{?TextMarker}}\n     */\n    function prepareEditorForProvider(hostEditor, pos) {\n        var cursorLine, sel, startPos, endPos, startBookmark, endBookmark, currentMatch,\n            cm = hostEditor._codeMirror;\n\n        sel = hostEditor.getSelection();\n        if (sel.start.line !== sel.end.line) {\n            return {timingFunction: null, reason: null};\n        }\n\n        cursorLine = hostEditor.document.getLine(pos.line);\n\n        // code runs several matches complicated patterns, multiple times, so\n        // first do a quick, simple check to see make sure we may have a match\n        if (!cursorLine.match(/cubic-bezier|linear|ease|step/)) {\n            return {timingFunction: null, reason: null};\n        }\n\n        currentMatch = TimingFunctionUtils.timingFunctionMatch(cursorLine, false);\n        if (!currentMatch) {\n            return {timingFunction: null, reason: Strings.ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX};\n        }\n\n        // check for subsequent matches, and use first match after pos\n        var lineOffset = 0,\n            matchLength = ((currentMatch.originalString && currentMatch.originalString.length) || currentMatch[0].length);\n        while (pos.ch > (currentMatch.index + matchLength + lineOffset)) {\n            var restOfLine = cursorLine.substring(currentMatch.index + matchLength + lineOffset),\n                newMatch = TimingFunctionUtils.timingFunctionMatch(restOfLine, false);\n\n            if (newMatch) {\n                lineOffset += (currentMatch.index + matchLength);\n                currentMatch = $.extend(true, [], newMatch);\n            } else {\n                break;\n            }\n        }\n\n        currentMatch.lineOffset = lineOffset;\n\n        startPos = {line: pos.line, ch: lineOffset + currentMatch.index};\n        endPos   = {line: pos.line, ch: lineOffset + currentMatch.index + matchLength};\n\n        startBookmark = cm.setBookmark(startPos);\n        endBookmark   = cm.setBookmark(endPos);\n\n        // Adjust selection to the match so that the inline editor won't\n        // get dismissed while we're updating the timing function.\n        hostEditor.setSelection(startPos, endPos);\n\n        return {\n            timingFunction: currentMatch,\n            start: startBookmark,\n            end: endBookmark\n        };\n    }\n\n    /**\n     * Registered as an inline editor provider: creates an InlineTimingFunctionEditor\n     * when the cursor is on a timing function value.\n     *\n     * @param {!Editor} hostEditor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {?$.Promise} synchronously resolved with an InlineWidget, or\n     *         {string} if timing function with invalid syntax is detected at pos, or\n     *         null if there's no timing function at pos.\n     */\n    function inlineTimingFunctionEditorProvider(hostEditor, pos) {\n        var context = prepareEditorForProvider(hostEditor, pos),\n            inlineTimingFunctionEditor,\n            result;\n\n        if (!context.timingFunction) {\n            return context.reason || null;\n        } else {\n            inlineTimingFunctionEditor = new InlineTimingFunctionEditor(context.timingFunction, context.start, context.end);\n            inlineTimingFunctionEditor.load(hostEditor);\n\n            result = new $.Deferred();\n            result.resolve(inlineTimingFunctionEditor);\n            return result.promise();\n        }\n    }\n\n    /**\n     * Initialization code\n     */\n    function init() {\n        // Load our stylesheet\n        ExtensionUtils.loadStyleSheet(module, \"main.less\");\n        ExtensionUtils.addEmbeddedStyleSheet(Mustache.render(Localized, Strings));\n\n        EditorManager.registerInlineEditProvider(inlineTimingFunctionEditorProvider);\n    }\n\n    init();\n\n\n    // for unit tests only\n    exports.inlineTimingFunctionEditorProvider = inlineTimingFunctionEditorProvider;\n});\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/main.less",
    "content": "/**\n * All BezierCurveEditor selectors descend from .bezier-curve-editor to constrain styles to this extension\n */\n@cubic-bezier: url(grid.png);\n\n.bezier-curve-editor * {\n    margin: 0;\n}\n\n.bezier-curve-editor {\n    position: relative;\n    height: 300px;\n    margin: 0 25px;\n}\n\n.bezier-curve-editor:focus {\n    outline: none;\n}\n\n.bezier-curve-editor .cubic-bezier {\n    background: @cubic-bezier 0px -75px repeat-x;\n    background-size: 15px 450px;\n    height: 300px;\n    width: 149px;\n    margin: 0 0 0 25px;\n    position: absolute;\n    top: 0;\n    z-index: 2;\n}\n\n.bezier-curve-editor:after {\n    content: \"\";\n    display: block;\n    height: 300px;\n    width: 149px;\n    margin: 0 0 0 25px;\n    background: -webkit-linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, #fff 30%, #fff 70%, rgba(255, 255, 255, 0) 100%);\n    background-position: 2px 0;\n    position: absolute;\n    top: 0;\n    z-index: 1;\n}\n\n.bezier-curve-editor .coordinate-plane {\n    position: relative;\n    left: 0;\n    line-height: 0;\n    top: 75px;\n    width: 149px;\n    height: 149px;\n    -moz-box-sizing: content-box;\n    box-sizing: content-box;\n}\n\n.bezier-curve-editor .coordinate-plane:before,\n.bezier-curve-editor .coordinate-plane:after {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    width: 100%;\n    padding: .3em .5em;\n    \n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    \n    color: #454545;\n    font-size: 11px;\n    line-height: 1;\n}\n\n.bezier-curve-editor .coordinate-plane:before {\n    border-bottom: 1px solid transparent;\n       -moz-transform: rotate(-90deg);\n        -ms-transform: rotate(-90deg);\n         -o-transform: rotate(-90deg);\n    -webkit-transform: rotate(-90deg);\n            transform: rotate(-90deg);\n       -moz-transform-origin: bottom left;\n        -ms-transform-origin: bottom left;\n         -o-transform-origin: bottom left;\n    -webkit-transform-origin: bottom left;\n            transform-origin: bottom left;\n    white-space: nowrap;\n}\n\n.bezier-curve-editor .coordinate-plane:after {\n    margin-bottom: -1.5em;\n    white-space: nowrap;\n}\n\n.bezier-curve-editor .control-point {\n    background: #e5e9e9;\n    position: absolute;\n    z-index: 2;\n    height: 16px;\n    width: 16px;\n    border: 1px solid #b2b5b5;\n    margin: -8px 0 0 -8px;\n    outline: none;\n    padding: 0 !important;\n    box-sizing: border-box;\n    border-radius: 8px;\n}\n\n.bezier-curve-editor .control-point:focus {\n    border: 1px solid #2893ef !important;\n    box-shadow: 0 0 0 2px #94ceff;\n}\n\n.bezier-curve-editor .P0, .bezier-curve-editor .P3 {\n    background: #2893ef;\n    border-radius: 0;\n    border: none;\n    height: 12px;\n    width: 12px;\n    z-index: 1;\n}\n\n.bezier-curve-editor .P1, .bezier-curve-editor .P2 {\n    cursor: pointer;\n    z-index: 100;\n}\n\n.bezier-curve-editor .P0 {\n    left: 2px;\n    top: 151px;\n}\n\n.bezier-curve-editor .P3 {\n    right: -7px;\n    top: 1px;\n}\n\n.bezier-curve-editor canvas.curve {\n    position: absolute;\n    z-index: 1;\n    top: -75px;\n    left: 0;\n\n    -moz-user-select: none;\n    -webkit-user-select: none;\n    user-select: none;\n}\n\n\n/**\n * All StepEditor selectors descend from .step-editor to constrain styles to this extension\n */\n.step-editor * {\n    margin: 0;\n}\n\n.step-editor {\n    position: relative;\n    height: 190px;\n    margin: 0 25px;\n}\n\n.step-editor:focus, .step-editor canvas.steps:focus {\n    outline: none;\n}\n\n.step-editor .steps-func {\n    height: 179px;\n    width: 179px;\n    margin: 0 0 0 17px;\n    position: absolute;\n    top: 0;\n    z-index: 2;\n}\n\n.step-editor:after {\n    content: \"\";\n    display: block;\n    height: 179px;\n    width: 179px;\n    margin: 0 0 0 25px;\n    background-position: 2px 0;\n    position: absolute;\n    top: 0;\n    z-index: 1;\n}\n\n.step-editor .coordinate-plane {\n    background: #fff;\n    position: relative;\n    left: 0;\n    line-height: 0;\n    top: 0;\n    width: 179px;\n    height: 190px;\n    -moz-box-sizing: content-box;\n    box-sizing: content-box;\n}\n\n.step-editor .coordinate-plane:before,\n.step-editor .coordinate-plane:after {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    width: 100%;\n    \n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    \n    color: #454545;\n    font-size: 11px;\n    line-height: 1;\n}\n\n.step-editor .coordinate-plane:before {\n    border-bottom: 1px solid transparent;\n       -moz-transform: rotate(-90deg);\n        -ms-transform: rotate(-90deg);\n         -o-transform: rotate(-90deg);\n    -webkit-transform: rotate(-90deg);\n            transform: rotate(-90deg);\n       -moz-transform-origin: top left;\n        -ms-transform-origin: top left;\n         -o-transform-origin: top left;\n    -webkit-transform-origin: top left;\n            transform-origin: top left;\n    white-space: nowrap;\n    \n    padding: .3em .5em 0 1.3em;\n}\n\n.step-editor .coordinate-plane:after {\n    margin-left: 15px;\n    white-space: nowrap;\n    \n    bottom: 0.9em;\n    padding: 0 .5em 0 0.2em;\n}\n\n.step-editor canvas.steps {\n    position: absolute;\n    z-index: 1;\n    top: 0;\n    left: 0;\n\n    -moz-user-select: none;\n    -webkit-user-select: none;\n    user-select: none;\n}\n\n.bezier-curve-editor .info,\n.step-editor .info {\n    position: absolute;\n    z-index: 1;\n    top: 20px;\n    left: 170px;\n    width: 400px;\n\n    font-family: SourceSansPro;\n    font-size: 11px;\n    line-height: 2.2 !important;\n}\n\n.step-editor .info {\n    left: 205px;\n}\n\n.bezier-curve-editor kbd,\n.step-editor kbd {\n    font-size: 15px;\n    font-weight: bold;\n    color: #454545;\n    background: rgba(255, 255, 255, 0.5);\n    border: 1px solid rgba(0, 0, 0, 0.1);\n    display: inline-block;\n    margin: 0 2px 2px 0;\n    padding: 0 3px 2px;\n    border-radius: 2px;\n    vertical-align: top;\n    line-height: 1;\n}\n\n.bezier-curve-editor kbd.text,\n.step-editor kbd.text {\n    font-size: 10px;\n    font-family: SourceSansPro;\n    font-weight: normal;\n    padding: 4px 4px;\n}\n\n.bezier-curve-editor .info .hint,\n.step-editor .info .hint {\n    margin-top: 25px;\n    font-size: 13px;\n    display: none;\n    opacity: 1;\n    line-height: 1.5 !important;\n}\n\n.bezier-curve-editor .info .hint.fadeout,\n.step-editor .info .hint.fadeout {\n    transition: opacity 0.6s ease-in 0.1s;\n    opacity: 0;\n}\n\n/* Dark UI theme */\n\n@dark-bc-bg-highlight: #2a3b50;\n@dark-bc-highlight: rgba(255, 255, 255, 0.06);\n@dark-bc-text: #ccc;\n@dark-bc-text-alt: #fff;\n@dark-bc-btn-bg: #3f3f3f;\n@dark-bc-btn-border: #202020;\n@dark-bc-btn-border-focused: #2893ef;\n@dark-bc-btn-border-focused-glow: transparent;\n@dark-bc-shadow: rgba(0, 0, 0, 0.24);\n@dark-bc-shadow-small: rgba(0, 0, 0, 0.06);\n@dark-bc-shadow-medium: rgba(0, 0, 0, 0.12);\n@dark-bc-input-bg: #555;\n\n@dark-cubic-bezier: url(\"grid-dark.png\");\n\n.dark {\n    .bezier-curve-editor {\n        color: @dark-bc-text;\n\n        .cubic-bezier {\n            background: @dark-cubic-bezier 0px -75px repeat-x;\n            background-size: 15px 450px;\n        }\n\n        .control-point {\n            background: @dark-bc-btn-bg;\n            border: 1px solid @dark-bc-btn-border;\n        }\n\n        .control-point:focus {\n            border: 1px solid @dark-bc-btn-border-focused !important;\n            box-shadow: 0 0 0 2px @dark-bc-btn-border-focused-glow;\n        }\n\n        .P0, .P3 {\n            background: @dark-bc-btn-border-focused;\n        }\n\n        .coordinate-plane:before,\n        .coordinate-plane:after {\n            color: @dark-bc-text;\n        }\n\n        kbd {\n            background: #3D3D3D;\n            color: white;\n        }\n    }\n\n    .bezier-curve-editor:after {\n        background: -webkit-linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, @dark-bc-input-bg 30%, @dark-bc-input-bg 70%, rgba(255, 255, 255, 0) 100%);\n    }\n\n    .step-editor {\n        color: @dark-bc-text;\n\n        kbd {\n            background: #3D3D3D;\n            color: white;\n        }\n        \n        .coordinate-plane {\n            background: #2c2c2c;\n        }\n\n        .coordinate-plane:before,\n        .coordinate-plane:after {\n            color: @dark-bc-text;\n        }\n    }\n    \n    .bezier-curve-editor,\n    .step-editor {\n        code {\n            color: @dark-bc-text-alt;\n        }        \n    }\n}\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/unittest-files/unittests.css",
    "content": "/* */\n\n.foo {\n    transition-timing-function: cubic-bezier(.42, 0, .58, 1);\n    transition-timing-function: cubic-bezier(0, -0.2, 1, 1.3);\n    transition-timing-function: linear;\n    transition-timing-function: ease;\n    transition-timing-function: ease-in;\n    transition-timing-function: ease-out;\n    transition-timing-function: ease-in-out;\n}\n\n.bar {\n    transition: width 1s cubic-bezier(.86, .11, .18, .86) 0s, height 500ms cubic-bezier(.27, .75, .78, .14) 100ms;\n}\n\n.baz {\n    transition-timing-function: steps(4, end);\n    transition-timing-function: steps(12, start);\n    transition-timing-function: steps(24);\n    transition-timing-function: step-start;\n    transition-timing-function: step-end;\n}\n\n.qux {\n    transition-timing-function: cubic-bezier(-0.001, Infinity, 1.001, NaN);\n    transition-timing-function: cubic-bezier();\n}\n\n.quux {\n    transition-timing-function: steps(-5, s, 2, 3);\n    transition-timing-function: steps();\n}\n"
  },
  {
    "path": "src/extensions/default/InlineTimingFunctionEditor/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, runs, waitsForDone */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Modules from the SpecRunner window\n    var SpecRunnerUtils         = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        KeyEvent                = brackets.getModule(\"utils/KeyEvent\"),\n        testContentCSS          = require(\"text!unittest-files/unittests.css\"),\n        provider                = require(\"main\").inlineTimingFunctionEditorProvider,\n        TimingFunctionUtils     = require(\"TimingFunctionUtils\"),\n        BezierCurveEditor       = require(\"BezierCurveEditor\").BezierCurveEditor,\n        StepEditor              = require(\"StepEditor\").StepEditor;\n\n    describe(\"Inline Timing Function Editor\", function () {\n\n        var testDocument, testEditor, inline;\n\n        /**\n         * Creates an inline timing function editor connected to the given cursor position in the test editor.\n         * Note that this does *not* actually open it as an inline editor in the test editor.\n         * Tests that use this must wrap their contents in a runs() block.\n         * @param {!{line:number, ch: number}} cursor Position for which to open the inline editor.\n         *    if the provider did not create an inline editor.\n         */\n        function makeTimingFunctionEditor(cursor) {\n            runs(function () {\n                var promise = provider(testEditor, cursor);\n                if (promise) {\n                    promise.done(function (inlineResult) {\n                        inlineResult.onAdded();\n                        inline = inlineResult;\n                    });\n                    waitsForDone(promise, \"open timing function editor\");\n                }\n            });\n        }\n\n        /**\n         * Expects arrays to be of specified length and equal.\n         * @param {Array} a1 Result to test\n         * @param {Array} a2 Expected values.\n         * @param {number} len Expected length.\n         */\n        function expectArraysToBeEqual(a1, a2, len) {\n            expect(a2.length).toEqual(a1.length);\n            a2.forEach(function (entry, index) {\n                expect(entry).toEqual(a1[index]);\n            });\n        }\n\n        describe(\"TimingFunctionUtils for bezier curve functions\", function () {\n            var match;\n\n            /**\n             * Expects an invalid steps() function to be corrected the right way, with the right match\n             * and originalString given a string to match and an expectation of the output match.\n             * @param {string} str The string to match\n             * @param {Array} expectedArray The array that should equal the output match.\n             */\n            function testInvalidBezier(str, expectedArray) {\n                var match = TimingFunctionUtils.timingFunctionMatch(str, false);\n                runs(function () {\n                    expectArraysToBeEqual(match, expectedArray);\n                    expect(match.originalString).toEqual(str);\n                });\n            }\n\n            // Valid cubic-bezier function cases\n            it(\"should match bezier curve function in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier(.1, .2, .3, .4)\", false);\n                expect(match).toBeTruthy();\n                expectArraysToBeEqual(match, [\"cubic-bezier(.1, .2, .3, .4)\", \".1\", \".2\", \".3\", \".4\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier(.1, .2, .3, .4)\", true);\n                expect(match).toBeTruthy();\n                expectArraysToBeEqual(match, [\"cubic-bezier(.1, .2, .3, .4)\", \".1\", \".2\", \".3\", \".4\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function with negative value\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier(0, -.2, 1, 1.2)\", false);\n                expectArraysToBeEqual(match, [\"cubic-bezier(0, -.2, 1, 1.2)\", \"0\", \"-.2\", \"1\", \"1.2\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function in full line of longhand css\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"    transition-timing-function: cubic-bezier(.37, .28, .83, .94);\", false);\n                expectArraysToBeEqual(match, [\"cubic-bezier(.37, .28, .83, .94)\", \".37\", \".28\", \".83\", \".94\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function in full line of shorthand css\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"    transition: top 100ms cubic-bezier(.37, .28, .83, .94) 0;\", false);\n                expectArraysToBeEqual(match, [\"cubic-bezier(.37, .28, .83, .94)\", \".37\", \".28\", \".83\", \".94\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function with leading zeros\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier(0.1, 0.2, 0.3, 0.4)\", false);\n                expectArraysToBeEqual(match, [\"cubic-bezier(0.1, 0.2, 0.3, 0.4)\", \"0.1\", \"0.2\", \"0.3\", \"0.4\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function with no optional whitespace\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier(.1,.2,.3,.4)\", false);\n                expectArraysToBeEqual(match, [\"cubic-bezier(.1,.2,.3,.4)\", \".1\", \".2\", \".3\", \".4\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match bezier curve function with extra optional whitespace\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier( .1 , .2 , .3 , .4 )\", false);\n                expectArraysToBeEqual(match, [\"cubic-bezier( .1 , .2 , .3 , .4 )\", \".1\", \".2\", \".3\", \".4\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n\n            // Valid other functions\n            it(\"should match linear animation function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"animation-timing-function: linear;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"linear\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease animation function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"animation-timing-function: ease;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-in animation function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"animation-timing-function: ease-in;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-in\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-out animation function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"animation-timing-function: ease-out;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-out\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-in-out animation function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"animation-timing-function: ease-in-out;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-in-out\");\n                expect(match.originalString).toBeFalsy();\n            });\n\n            it(\"should match linear function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: linear;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"linear\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match linear function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"linear\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"linear\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: ease;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"ease\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-in function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: ease-in;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-in\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-in function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"ease-in\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-in\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-out function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: ease-out;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-out\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-out function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"ease-out\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-out\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-in-out function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: ease-in-out;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-in-out\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match ease-in-out function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"ease-in-out\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"ease-in-out\");\n                expect(match.originalString).toBeFalsy();\n            });\n\n            // Invalid cubic-beziers - they should be corrected automatically\n            it(\"should correct cubic-bezier function with out-of-range X parameters\", function () {\n                testInvalidBezier(\"cubic-bezier(-.2, 0, 1.2, 1)\", [\"cubic-bezier(0, 0, 1, 1)\", \"0\", \"0\", \"1\", \"1\"]);\n            });\n            it(\"should correct cubic-bezier function with Infinity parameters\", function () {\n                testInvalidBezier(\"cubic-bezier(0, Infinity, 1, -Infinity)\", [\"cubic-bezier(0, 0, 1, 1)\", \"0\", \"0\", \"1\", \"1\"]);\n            });\n            it(\"should correct cubic-bezier function with non-numeric parameters\", function () {\n                testInvalidBezier(\"cubic-bezier(x1, y1, x2, y2)\", [\"cubic-bezier(.42, 0, .58, 1)\", \".42\", \"0\", \".58\", \"1\"]);\n            });\n            it(\"should correct cubic-bezier function with no parameters\", function () {\n                testInvalidBezier(\"cubic-bezier()\", [\"cubic-bezier(.42, 0, .58, 1)\", \".42\", \"0\", \".58\", \"1\"]);\n            });\n            it(\"should correct cubic-bezier function with 3 parameters\", function () {\n                testInvalidBezier(\"cubic-bezier(0, 0, 1)\", [\"cubic-bezier(0, 0, 1, 1)\", \"0\", \"0\", \"1\", \"1\"]);\n            });\n            it(\"should correct cubic-bezier function with 5 parameters\", function () {\n                testInvalidBezier(\"cubic-bezier(0, 0, 1, 1, 1)\", [\"cubic-bezier(0, 0, 1, 1)\", \"0\", \"0\", \"1\", \"1\"]);\n            });\n            it(\"should correct cubic-bezier function with trailing comma\", function () {\n                testInvalidBezier(\"cubic-bezier(.42, 0, .58, .5,)\", [\"cubic-bezier(.42, 0, .58, .5)\", \".42\", \"0\", \".58\", \".5\"]);\n            });\n\n            // Real invalid cubic-beziers - they should NOT be corrected automatically\n            it(\"should not match cubic-bezier function with invalid whitespace\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier (0, 0, 1, 1)\", false);\n                expect(match).toBeFalsy();\n            });\n            it(\"should not match cubic-bezier function with UPPER-CASE\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"CUBIC-BEZIER(0, 0, 1, 1)\", false);\n                expect(match).toBeFalsy();\n            });\n            it(\"should not match unknown timing function\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"ease-out-in\", false);\n                expect(match).toBeFalsy();\n            });\n            it(\"should not match linear when not a timing function\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"background: linear-gradient(to bottom, blue, white);\", false);\n                expect(match).toBeFalsy();\n            });\n        });\n\n        describe(\"TimingFunctionUtils for step functions\", function () {\n            var match;\n\n            /**\n             * Expects an invalid steps() function to be corrected the right way, with the right match\n             * and originalString given a string to match and an expectation of the output match.\n             * @param {string} str The string to match\n             * @param {Array} expectedArray The array that should equal the output match.\n             */\n            function testInvalidStep(str, expectedArray) {\n                var match = TimingFunctionUtils.timingFunctionMatch(str, false);\n                runs(function () {\n                    expectArraysToBeEqual(match, expectedArray);\n                    expect(match.originalString).toEqual(str);\n                });\n            }\n\n            // Valid steps function cases\n            it(\"should match steps function in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(3, start)\", false);\n                expect(match).toBeTruthy();\n                expectArraysToBeEqual(match, [\"steps(3, start)\", \"3\", \"start\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(3, start)\", true);\n                expect(match).toBeTruthy();\n                expectArraysToBeEqual(match, [\"steps(3, start)\", \"3\", \"start\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with second parameter of end\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(12, end)\", false);\n                expectArraysToBeEqual(match, [\"steps(12, end)\", \"12\", \"end\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with only 1 parameter\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(8)\", false);\n                expectArraysToBeEqual(match, [\"steps(8)\", \"8\", undefined]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function in full line of longhand css\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"    transition-timing-function: steps(5, start);\", false);\n                expectArraysToBeEqual(match, [\"steps(5, start)\", \"5\", \"start\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function in full line of shorthand css\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"    transition: top 100ms steps(10) 0;\", false);\n                expectArraysToBeEqual(match, [\"steps(10)\", \"10\", undefined]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with leading zeros\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(04, end)\", false);\n                expectArraysToBeEqual(match, [\"steps(04, end)\", \"04\", \"end\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with no optional whitespace with 1 param\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(3)\", false);\n                expectArraysToBeEqual(match, [\"steps(3)\", \"3\", undefined]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with no optional whitespace with 2 params\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps(3,end)\", false);\n                expectArraysToBeEqual(match, [\"steps(3,end)\", \"3\", \"end\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with extra optional whitespace with 1 param\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps( 7 )\", false);\n                expectArraysToBeEqual(match, [\"steps( 7 )\", \"7\", undefined]);\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match steps function with extra optional whitespace with 2 params\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps( 8 , start )\", false);\n                expectArraysToBeEqual(match, [\"steps( 8 , start )\", \"8\", \"start\"]);\n                expect(match.originalString).toBeFalsy();\n            });\n\n            // Valid other functions\n            it(\"should match step-start function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: step-start;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"step-start\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match step-start function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"step-start\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"step-start\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match step-end function in declaration in strict mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"transition-timing-function: step-end;\", false);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"step-end\");\n                expect(match.originalString).toBeFalsy();\n            });\n            it(\"should match step-end function value in lax mode\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"step-end\", true);\n                expect(match.length).toEqual(1);\n                expect(match[0]).toEqual(\"step-end\");\n                expect(match.originalString).toBeFalsy();\n            });\n\n            // Invalid steps - they should be corrected automatically\n            it(\"should correct steps function with zero steps\", function () {\n                testInvalidStep(\"steps(0)\", [\"steps(5, end)\", \"5\", \"end\"]);\n            });\n            it(\"should correct steps function with a non-integer number of steps\", function () {\n                testInvalidStep(\"steps(3.0)\", [\"steps(3, end)\", \"3\", \"end\"]);\n            });\n            it(\"should correct steps function with a negative number of steps\", function () {\n                testInvalidStep(\"steps(-2)\", [\"steps(5, end)\", \"5\", \"end\"]);\n            });\n            it(\"should correct steps function with an infinite number of steps\", function () {\n                testInvalidStep(\"steps(Infinity,)\", [\"steps(5, end)\", \"5\", \"end\"]);\n            });\n            it(\"should correct steps function with NaN number of steps\", function () {\n                testInvalidStep(\"steps(NaN,)\", [\"steps(5, end)\", \"5\", \"end\"]);\n            });\n            it(\"should correct steps function with non-numeric number of steps\", function () {\n                testInvalidStep(\"steps(x)\", [\"steps(5, end)\", \"5\", \"end\"]);\n            });\n            it(\"should correct steps function with a string-value number of steps\", function () {\n                testInvalidStep(\"steps('3')\", [\"steps(3, end)\", \"3\", \"end\"]);\n            });\n            it(\"should correct steps function with no parameters\", function () {\n                testInvalidStep(\"steps()\", [\"steps(5, end)\", \"5\", \"end\"]);\n            });\n            it(\"should correct steps function with empty second parameter\", function () {\n                testInvalidStep(\"steps(1,)\", [\"steps(1, end)\", \"1\", \"end\"]);\n            });\n            it(\"should correct steps function with undefined second parameter\", function () {\n                testInvalidStep(\"steps(1, middle)\", [\"steps(1, end)\", \"1\", \"end\"]);\n            });\n            it(\"should correct steps function with typo in second parameter\", function () {\n                testInvalidStep(\"steps(1, satrt)\", [\"steps(1, start)\", \"1\", \"start\"]);\n            });\n            it(\"should correct steps function with a string as second parameter\", function () {\n                testInvalidStep(\"steps(1, 'start')\", [\"steps(1, start)\", \"1\", \"start\"]);\n            });\n            it(\"should correct steps function with 3 parameters\", function () {\n                testInvalidStep(\"steps(1, start, end)\", [\"steps(1, start)\", \"1\", \"start\"]);\n            });\n\n            // Real invalid cubic-beziers - they should NOT be corrected automatically\n            it(\"should not match steps function with no parens\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps\", false);\n                expect(match).toBeFalsy();\n            });\n            it(\"should not match steps function with invalid whitespace\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"steps (1, end)\", false);\n                expect(match).toBeFalsy();\n            });\n            it(\"should not match steps function with UPPER-CASE\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"STEPS(12)\", false);\n                expect(match).toBeFalsy();\n            });\n            it(\"should not match unknown timing function\", function () {\n                match = TimingFunctionUtils.timingFunctionMatch(\"step\", false);\n                expect(match).toBeFalsy();\n            });\n        });\n\n\n        describe(\"Bookmark Timing Function\", function () {\n            beforeEach(function () {\n                var mock = SpecRunnerUtils.createMockEditor(testContentCSS, \"css\");\n                testDocument = mock.doc;\n                testEditor = mock.editor;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n                inline = null;\n            });\n\n            /**\n             * Expects an inline editor to be opened at the given cursor position and to have the\n             * given initial timing function (which should match the timing function at that position).\n             * @param {!{line:number, ch:number}} cursor The cursor position to try opening the inline at.\n             * @param {number} start The expected start of timing function.\n             * @param {number} end The expected end of timing function.\n             */\n            function testOpenTimingFunction(cursor, start, end) {\n                makeTimingFunctionEditor(cursor);\n                runs(function () {\n                    expect(inline).toBeTruthy();\n                    expect(inline._startBookmark.find().ch).toBe(start);\n                    expect(inline._endBookmark.find().ch).toBe(end);\n                });\n            }\n\n            it(\"should bookmark cubic-bezier() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 3, ch: 34}, 32, 60);\n            });\n            it(\"should bookmark linear function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 5, ch: 35}, 32, 38);\n            });\n            it(\"should bookmark second cubic-bezier() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 13, ch: 80}, 75, 107);\n            });\n            it(\"should bookmark steps() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 17, ch: 37}, 32, 45);\n            });\n            it(\"should bookmark step-start function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 20, ch: 40}, 32, 42);\n            });\n            it(\"should bookmark long, invalid cubic-bezier() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 25, ch: 52}, 32, 74);\n            });\n            it(\"should bookmark empty, invalid cubic-bezier() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 26, ch: 47}, 32, 46);\n            });\n            it(\"should bookmark long, invalid steps() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 30, ch: 44}, 32, 50);\n            });\n            it(\"should bookmark empty, invalid steps() function when opened in inline editor\", function () {\n                testOpenTimingFunction({line: 31, ch: 45}, 32, 39);\n            });\n        });\n\n        describe(\"TimingFunction editor UI\", function () {\n            var timingFuncEditor;\n\n            /**\n             * Creates a hidden BezierCurveEditor and appends it to the body. Note that this is a\n             * standalone BezierCurveEditor, not inside an InlineTimingFunctionEditor.\n             * @param {string} initialTimingFunction The timingFunction that should be initially set\n             *     in the BezierCurveEditor.\n             * @param {?function} callback An optional callback to be passed as the BezierCurveEditor's\n             *     callback. If none is supplied, a dummy function is passed.\n             */\n            function makeTimingFuncUI(initialTimingFunction, callback) {\n                var parent = $(window.document.body),\n                    match = TimingFunctionUtils.timingFunctionMatch(initialTimingFunction, true),\n                    cb = callback || function () { };\n\n                if (match.isBezier) {\n                    timingFuncEditor = new BezierCurveEditor(parent, match, cb);\n                } else if (match.isStep) {\n                    timingFuncEditor = new StepEditor(parent, match, cb);\n                }\n\n                // Hide it\n                timingFuncEditor.getRootElement().css(\"display\", \"none\");\n            }\n\n            afterEach(function () {\n                timingFuncEditor.getRootElement().remove();\n                timingFuncEditor = null;\n            });\n\n\n            describe(\"Initial Load and External Update\", function () {\n\n                it(\"should load the initial cubic-bezier function correctly\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"cubic-bezier(.2, .3, .4, .5)\");\n                        expect(timingFuncEditor).toBeTruthy();\n                        expect(timingFuncEditor._cubicBezierCoords).toBeTruthy();\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".2\", \".3\", \".4\", \".5\"]);\n                    });\n                });\n                it(\"should load externally updated cubic-bezier function correctly\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"cubic-bezier(.1, .3, .5, .7)\");\n                        var matchUpdate = TimingFunctionUtils.timingFunctionMatch(\"cubic-bezier(.2, .4, .6, .8)\", true);\n                        timingFuncEditor.handleExternalUpdate(matchUpdate);\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".2\", \".4\", \".6\", \".8\"]);\n                    });\n                });\n                it(\"should load the initial steps function correctly\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"steps(5, start)\");\n                        expect(timingFuncEditor).toBeTruthy();\n                        expect(timingFuncEditor._stepParams).toBeTruthy();\n                        expect(timingFuncEditor._stepParams.count).toEqual(5);\n                        expect(timingFuncEditor._stepParams.timing).toEqual(\"start\");\n                    });\n                });\n                it(\"should load externally updated steps function correctly\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"steps(5, start)\");\n                        var matchUpdate = TimingFunctionUtils.timingFunctionMatch(\"steps(6, end)\", true);\n                        timingFuncEditor.handleExternalUpdate(matchUpdate);\n                        expect(timingFuncEditor._stepParams.count).toEqual(6);\n                        expect(timingFuncEditor._stepParams.timing).toEqual(\"end\");\n                    });\n                });\n            });\n\n            describe(\"Conversions\", function () {\n\n                it(\"should convert linear function to cubic-bezier function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"linear\");\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\"0\", \"0\", \"1\", \"1\"]);\n                    });\n                });\n                it(\"should convert ease function to cubic-bezier function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"ease\");\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".25\", \".1\", \".25\", \"1\"]);\n                    });\n                });\n                it(\"should convert ease-in function to cubic-bezier function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"ease-in\");\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".42\", \"0\", \"1\", \"1\"]);\n                    });\n                });\n                it(\"should convert ease-out function to cubic-bezier function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"ease-out\");\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\"0\", \"0\", \".58\", \"1\"]);\n                    });\n                });\n                it(\"should convert ease-in-out function to cubic-bezier function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"ease-in-out\");\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".42\", \"0\", \".58\", \"1\"]);\n                    });\n                });\n                it(\"should convert step-start function to steps function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"step-start\");\n                        expect(timingFuncEditor).toBeTruthy();\n                        expect(timingFuncEditor._stepParams).toBeTruthy();\n                        expect(timingFuncEditor._stepParams.count).toEqual(1);\n                        expect(timingFuncEditor._stepParams.timing).toEqual(\"start\");\n                    });\n                });\n                it(\"should convert step-end function to steps function parameters\", function () {\n                    runs(function () {\n                        makeTimingFuncUI(\"step-end\");\n                        expect(timingFuncEditor._stepParams.count).toEqual(1);\n                        expect(timingFuncEditor._stepParams.timing).toEqual(\"end\");\n                    });\n                });\n            });\n\n            describe(\"Editing with Mouse\", function () {\n\n                /**\n                 * Translate from a bezier-curve point (1.0 x 1.0 grid)\n                 *           to a canvas element point (150px x 150px grid).\n                 * @param  {Array} bezierPoint The bezier point [x, y].\n                 * @return {Array} canvas element point in [x, y]\n                 */\n                function translatePointFromBezierToCanvas(bezierPoint) {\n                    return [\n                        Math.round(bezierPoint[0] * 150),\n                        Math.round(((1 - bezierPoint[1]) * 150) + 75)\n                    ];\n                }\n                /**\n                 * Simulate the given event with clientX/clientY specified by the given\n                 * offsets by the left/top of the item.\n                 * @param {string} event The name of the event to simulate.\n                 * @param {object} $item A jQuery object to trigger the event on.\n                 * @param {Array.<number>} offsets Numbers the x and y positions of the\n                 *      event relative to the item's top and left.\n                 */\n                function eventAtOffset(event, $item, offsets) {\n                    $item.trigger($.Event(event, {\n                        pageX: $item.offset().left + offsets[0],\n                        pageY: $item.offset().top  + offsets[1],\n                        which: 1\n                    }));\n                }\n\n                /**\n                 * Test a mouse down event on the given UI element in a cubic-bezier function.\n                 * @param {object} opts The parameters to test:\n                 *     item: The (string) name of the member of BezierCurveEditor that\n                 *          references the element to test.\n                 *     clickAt: An [x, y] array specifying the simulated x/y mouse position as\n                 *          an offset of the item's width/height.\n                 *     expected: The expected array of values for _cubicBezierCoords.\n                 */\n                function testCubicBezierClick(opts) {\n                    makeTimingFuncUI(\"cubic-bezier(.42, 0, .58 ,1)\");\n                    var $item = $(timingFuncEditor[opts.item]);\n                    eventAtOffset(\"click\", $item, opts.clickAt);\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, opts.expected);\n                }\n\n                /**\n                 * Test a drag event on the given UI element.\n                 * @param {object} opts The parameters to test:\n                 *     downItem: The (string) name of the member of BezierCurveEditor\n                 *          that references the element to mousedown on to drag.\n                 *     clickAt: An [x, y] array specifying the simulated x/y mouse position as an offset of the\n                 *          item's width/height.\n                 *     dragItem: The (string) name of the member of BezierCurveEditor\n                 *          that references the element to drag item to.\n                 *     dragTo: An [x, y] array specifying the location to drag to, using the same convention as clickAt.\n                 *     expected: The expected array of values for _cubicBezierCoords.\n                 */\n                function testCubicBezierDrag(opts) {\n                    makeTimingFuncUI(\"cubic-bezier(.42, 0, .58 ,1)\");\n                    var $downItem = $(timingFuncEditor[opts.downItem]),\n                        $dragItem = $(timingFuncEditor[opts.dragItem]);\n\n                    eventAtOffset(\"mousedown\", $downItem, opts.clickAt);\n                    eventAtOffset(\"mousemove\", $dragItem, opts.dragTo);\n                    $downItem.trigger(\"mouseup\");\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, opts.expected);\n                }\n\n                it(\"should move point P1 on mousedown in curve\", function () {\n                    testCubicBezierClick({\n                        item:      \"curve\",\n                        clickAt:   translatePointFromBezierToCanvas([0.5, 0.1]),\n                        expected:  [\".5\", \".1\", \".58\", \"1\"]\n                    });\n                });\n                it(\"should move point P2 on mousedown in curve\", function () {\n                    testCubicBezierClick({\n                        item:      \"curve\",\n                        clickAt:   translatePointFromBezierToCanvas([0.6, 1.2]),\n                        expected:  [\".42\", \"0\", \".6\", \"1.2\"]\n                    });\n                });\n                it(\"should move point P1 on drag\", function () {\n                    testCubicBezierDrag({\n                        downItem:  \"P1\",        // mouse down on this element\n                        clickAt:   [5, 5],\n                        dragItem:  \"curve\",     // drag over this element\n                        dragTo:    translatePointFromBezierToCanvas([0.6, -0.1]),\n                        expected:  [\".6\", \"-0.1\", \".58\", \"1\"]\n                    });\n                });\n                it(\"should move point P2 on drag\", function () {\n                    testCubicBezierDrag({\n                        downItem:  \"P2\",        // mouse down on this element\n                        clickAt:   [5, 5],\n                        dragItem:  \"curve\",     // drag over this element\n                        dragTo:    translatePointFromBezierToCanvas([0.8, 0.9]),\n                        expected:  [\".42\", \"0\", \".8\", \".9\"]\n                    });\n                });\n                it(\"should not move point P2 x-value out-of-range on drag\", function () {\n                    testCubicBezierDrag({\n                        downItem:  \"P2\",        // mouse down on this element\n                        clickAt:   [5, 5],\n                        dragItem:  \"curve\",     // drag over this element\n                        dragTo:    translatePointFromBezierToCanvas([1.1, 1]),\n                        expected:  [\".42\", \"0\", \"1\", \"1\"]\n                    });\n                });\n            });\n\n            describe(\"Editing with Keyboard\", function () {\n\n                function makeKeyEvent(opts) {\n                    return $.Event(\"keydown\", { keyCode: opts.key, shiftKey: !!opts.shift });\n                }\n\n                /**\n                 * Create a timing function editor and trigger a key event on it.\n                 * @param {object} opts The parameters to test:\n                 *     func: The initial timing function\n                 *     item: The (string) name of the member of BezierCurveEditor\n                 *          that references the element to test.\n                 *     key: The KeyEvent key code to simulate.\n                 *     shift: Optional boolean specifying whether to simulate the shift\n                 *          key being down (default false).\n                 *     expected: The expected array of values for _cubicBezierCoords.\n                 */\n                function triggerTimingFunctionEditorKey(opts) {\n                    makeTimingFuncUI(opts.func, opts.callback);\n                    var $item = $(timingFuncEditor[opts.item]);\n                    $item.focus();\n                    $item.trigger(makeKeyEvent(opts));\n                }\n\n                // cubic-bezier() tests\n                it(\"should increase P1 x-value by .02 on right arrow in cubic-bezier()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"cubic-bezier(.42, 0, .58, 1)\",\n                        item:      \"P1\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        shift:     false\n                    });\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".44\", \"0\", \".58\", \"1\"]);\n                });\n                it(\"should increase P1 y-value by .1 on shift up arrow in cubic-bezier()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"cubic-bezier(.42, 0, .58, 1)\",\n                        item:      \"P1\",\n                        key:       KeyEvent.DOM_VK_UP,\n                        shift:     true\n                    });\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".42\", \".1\", \".58\", \"1\"]);\n                });\n                it(\"should decrease P2 x-value by .02 on left arrow in cubic-bezier()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"cubic-bezier(.42, 0, .58, 1)\",\n                        item:      \"P2\",\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        shift:     false\n                    });\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".42\", \"0\", \".56\", \"1\"]);\n                });\n                it(\"should decrease P2 y-value by .1 on shift down arrow in cubic-bezier()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"cubic-bezier(.42, 0, .58 ,1)\",\n                        item:      \"P2\",\n                        key:       KeyEvent.DOM_VK_DOWN,\n                        shift:     true\n                    });\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".42\", \"0\", \".58\", \".9\"]);\n                });\n                it(\"should not decrease P1 x-value below 0 on left arrow in cubic-bezier()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"cubic-bezier(0, 0, 1, 1)\",\n                        item:      \"P1\",\n                        key:       KeyEvent.DOM_VK_LEFT,\n                        shift:     false\n                    });\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\"0\", \"0\", \"1\", \"1\"]);\n                });\n                it(\"should not increase P2 x-value above 0 on shift right arrow in cubic-bezier()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"cubic-bezier(0, 0, 1, 1)\",\n                        item:      \"P2\",\n                        key:       KeyEvent.DOM_VK_RIGHT,\n                        shift:     true\n                    });\n                    expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\"0\", \"0\", \"1\", \"1\"]);\n                });\n                it(\"should call callback function after cubic-bezier edit in cubic-bezier()\", function () {\n                    var calledBack = false;\n\n                    var _callback = function (timingFunctionString) {\n                        calledBack = true;\n                        expect(timingFunctionString).toBe(\"cubic-bezier(.42, .1, .58, 1)\");\n                    };\n\n                    runs(function () {\n                        triggerTimingFunctionEditorKey({\n                            func:      \"cubic-bezier(.42, 0, .58 ,1)\",\n                            item:      \"P1\",\n                            key:       KeyEvent.DOM_VK_UP,\n                            shift:     true,\n                            callback:  _callback\n                        });\n                        expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [\".42\", \".1\", \".58\", \"1\"]);\n                    });\n\n                    runs(function () {\n                        expect(calledBack).toBeTruthy();\n                    });\n                });\n\n                // steps() tests\n                it(\"should increase count by 1 on up arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(5)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_UP\n                    });\n                    expect(timingFuncEditor._stepParams.count).toEqual(6);\n                });\n                it(\"should decrease count by 1 on down arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(5)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_DOWN\n                    });\n                    expect(timingFuncEditor._stepParams.count).toEqual(4);\n                });\n                it(\"should change start to end on right arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(5, start)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_RIGHT\n                    });\n                    expect(timingFuncEditor._stepParams.timing).toEqual(\"end\");\n                });\n                it(\"should change end to start on left arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(5, end)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_LEFT\n                    });\n                    expect(timingFuncEditor._stepParams.timing).toEqual(\"start\");\n                });\n                it(\"should not decrease count to be less than 1 on down arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(1)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_DOWN\n                    });\n                    expect(timingFuncEditor._stepParams.count).toEqual(1);\n                });\n                it(\"should not change start to end on left arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(5, start)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_LEFT\n                    });\n                    expect(timingFuncEditor._stepParams.timing).toEqual(\"start\");\n                });\n                it(\"should not change end to start on right arrow in steps()\", function () {\n                    triggerTimingFunctionEditorKey({\n                        func:      \"steps(5, end)\",\n                        item:      \"canvas\",\n                        key:       KeyEvent.DOM_VK_RIGHT\n                    });\n                    expect(timingFuncEditor._stepParams.timing).toEqual(\"end\");\n                });\n\n                it(\"should call callback function after steps function edit\", function () {\n                    var calledBack = false;\n\n                    var _callback = function (timingFunctionString) {\n                        calledBack = true;\n                        expect(timingFunctionString).toBe(\"steps(5, start)\");\n                    };\n\n                    runs(function () {\n                        triggerTimingFunctionEditorKey({\n                            func:      \"steps(4, start)\",\n                            item:      \"canvas\",\n                            key:       KeyEvent.DOM_VK_UP,\n                            callback:  _callback\n                        });\n                        expect(timingFuncEditor._stepParams.count).toEqual(5);\n                    });\n\n                    runs(function () {\n                        expect(calledBack).toBeTruthy();\n                    });\n                });\n\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JSLint/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global JSLINT */\n\n/**\n * Provides JSLint results via the core linting extension point\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load JSLint, a non-module lib\n    require(\"thirdparty/jslint/jslint\");\n\n    // Load dependent modules\n    var CodeInspection     = brackets.getModule(\"language/CodeInspection\"),\n        Editor             = brackets.getModule(\"editor/Editor\").Editor,\n        PreferencesManager = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings            = brackets.getModule(\"strings\"),\n        _                  = brackets.getModule(\"thirdparty/lodash\");\n\n    var prefs = PreferencesManager.getExtensionPrefs(\"jslint\");\n\n    /**\n     * @private\n     *\n     * Used to keep track of the last options JSLint was run with to avoid running\n     * again when there were no changes.\n     */\n    var _lastRunOptions;\n\n    prefs.definePreference(\"options\", \"object\", undefined, {\n        description: Strings.DESCRIPTION_JSLINT_OPTIONS,\n        keys: {\n            ass: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_ASS,\n                initial: false\n            },\n            bitwise: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_BITWISE,\n                initial: false\n            },\n            browser: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_BROWSER,\n                initial: false\n            },\n            closure: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_CLOSURE,\n                initial: false\n            },\n            \"continue\": {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_CONTINUE,\n                initial: false\n            },\n            couch: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_COUCH,\n                initial: false\n            },\n            debug: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_DEBUG,\n                initial: false\n            },\n            devel: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_DEVEL,\n                initial: false\n            },\n            eqeq: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_EQEQ,\n                initial: false\n            },\n            es6: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_ES6,\n                initial: false\n            },\n            evil: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_EVIL,\n                initial: false\n            },\n            forin: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_FORIN,\n                initial: false\n            },\n            indent: {\n                type: \"number\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_INDENT\n            },\n            maxerr: {\n                type: \"number\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_MAXERR\n            },\n            maxlen: {\n                type: \"number\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_MAXLEN\n            },\n            newcap: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_NEWCAP,\n                initial: false\n            },\n            node: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_NODE,\n                initial: false\n            },\n            nomen: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_NOMEN,\n                initial: false\n            },\n            passfail: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_PASSFAIL,\n                initial: false\n            },\n            plusplus: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS,\n                initial: false\n            },\n            regexp: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_REGEXP,\n                initial: false\n            },\n            rhino: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_RHINO,\n                initial: false\n            },\n            sloppy: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_SLOPPY,\n                initial: false\n            },\n            stupid: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_STUPID,\n                initial: false\n            },\n            sub: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_SUB,\n                initial: false\n            },\n            todo: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_TODO,\n                initial: false\n            },\n            unparam: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_UNPARAM,\n                initial: false\n            },\n            vars: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_VARS,\n                initial: false\n            },\n            white: {\n                type: \"boolean\",\n                description: Strings.DESCRIPTION_JSLINT_OPTIONS_WHITE,\n                initial: false\n            }\n        }\n    })\n        .on(\"change\", function (e, data) {\n            var options = prefs.get(\"options\");\n            if (!_.isEqual(options, _lastRunOptions)) {\n                CodeInspection.requestRun(Strings.JSLINT_NAME);\n            }\n        });\n\n    // Predefined environments understood by JSLint.\n    var ENVIRONMENTS = [\"browser\", \"node\", \"couch\", \"rhino\"];\n\n    // gets indentation size depending whether the tabs or spaces are used\n    function _getIndentSize(fullPath) {\n        return Editor.getUseTabChar(fullPath) ? Editor.getTabSize(fullPath) : Editor.getSpaceUnits(fullPath);\n    }\n\n    /**\n     * Run JSLint on the current document. Reports results to the main UI. Displays\n     * a gold star when no errors are found.\n     */\n    function lintOneFile(text, fullPath) {\n        // If a line contains only whitespace (here spaces or tabs), remove the whitespace\n        text = text.replace(/^[ \\t]+$/gm, \"\");\n\n        var options = prefs.get(\"options\");\n\n        _lastRunOptions = _.clone(options);\n\n        if (!options) {\n            options = {};\n        } else {\n            options = _.clone(options);\n        }\n\n        if (!options.indent) {\n            // default to using the same indentation value that the editor is using\n            options.indent = _getIndentSize(fullPath);\n        }\n\n        // If the user has not defined the environment, we use browser by default.\n        var hasEnvironment = _.some(ENVIRONMENTS, function (env) {\n            return options[env] !== undefined;\n        });\n\n        if (!hasEnvironment) {\n            options.browser = true;\n        }\n\n        var jslintResult = JSLINT(text, options);\n\n        if (!jslintResult) {\n            // Remove any trailing null placeholder (early-abort indicator)\n            var errors = JSLINT.errors.filter(function (err) { return err !== null; });\n\n            errors = errors.map(function (jslintError) {\n                return {\n                    // JSLint returns 1-based line/col numbers\n                    pos: { line: jslintError.line - 1, ch: jslintError.character - 1 },\n                    message: jslintError.reason,\n                    type: CodeInspection.Type.WARNING\n                };\n            });\n\n            var result = { errors: errors };\n\n            // If array terminated in a null it means there was a stop notice\n            if (errors.length !== JSLINT.errors.length) {\n                result.aborted = true;\n                errors[errors.length - 1].type = CodeInspection.Type.META;\n            }\n\n            return result;\n        }\n        return null;\n    }\n\n    // Register for JS files\n    CodeInspection.register(\"javascript\", {\n        name: Strings.JSLINT_NAME,\n        scanFile: lintOneFile\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JSLint/unittest-files/.brackets.json",
    "content": "{\n    \"jslint.options\": {\n    },\n    \"path\": {\n        \"different-indent.js\": {\n            \"spaceUnits\": 2,\n            \"linting.collapsed\": false\n        }\n    },\n    \"language\": {\n        \"javascript\": {\n            \"linting.prefer\": [\"JSLint\"],\n            \"linting.usePreferredOnly\": true\n        }\n    }\n}"
  },
  {
    "path": "src/extensions/default/JSLint/unittest-files/different-indent.js",
    "content": "function notAnError() {\n  \"use strict\";\n}"
  },
  {
    "path": "src/extensions/default/JSLint/unittest-files/errors.js",
    "content": "// mispelled function keyword\nfuntion foo() {};"
  },
  {
    "path": "src/extensions/default/JSLint/unittest-files/no-errors.js",
    "content": "function foo() {\n    \"use strict\";\n    var body = document.body;\n}"
  },
  {
    "path": "src/extensions/default/JSLint/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, runs, waitsForDone, spyOn */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        FileUtils       = brackets.getModule(\"file/FileUtils\");\n\n    describe(\"JSLint\", function () {\n        var testFolder = FileUtils.getNativeModuleDirectoryPath(module) + \"/unittest-files/\",\n            testWindow,\n            $,\n            brackets,\n            CodeInspection,\n            EditorManager;\n\n        var toggleJSLintResults = function (visible) {\n            $(\"#status-inspection\").triggerHandler(\"click\");\n            expect($(\"#problems-panel\").is(\":visible\")).toBe(visible);\n        };\n\n        beforeEach(function () {\n            runs(function () {\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow = w;\n                    // Load module instances from brackets.test\n                    $ = testWindow.$;\n                    brackets = testWindow.brackets;\n                    EditorManager = testWindow.brackets.test.EditorManager;\n                    CodeInspection = testWindow.brackets.test.CodeInspection;\n                    CodeInspection.toggleEnabled(true);\n                });\n            });\n\n            runs(function () {\n                SpecRunnerUtils.loadProjectInTestWindow(testFolder);\n            });\n        });\n\n        afterEach(function () {\n            testWindow    = null;\n            $             = null;\n            brackets      = null;\n            EditorManager = null;\n            SpecRunnerUtils.closeTestWindow();\n        });\n\n        it(\"should run JSLint linter when a JavaScript document opens\", function () {\n            runs(function () {\n                spyOn(testWindow, \"JSLINT\").andCallThrough();\n            });\n\n            waitsForDone(SpecRunnerUtils.openProjectFiles([\"errors.js\"]), \"open test file\");\n\n            runs(function () {\n                expect(testWindow.JSLINT).toHaveBeenCalled();\n            });\n        });\n\n        it(\"status icon should toggle Errors panel when errors present\", function () {\n            waitsForDone(SpecRunnerUtils.openProjectFiles([\"errors.js\"]), \"open test file\");\n\n            runs(function () {\n                toggleJSLintResults(false);\n                toggleJSLintResults(true);\n            });\n        });\n\n        it(\"status icon should not toggle Errors panel when no errors present\", function () {\n            waitsForDone(SpecRunnerUtils.openProjectFiles([\"no-errors.js\"]), \"open test file\");\n\n            runs(function () {\n                toggleJSLintResults(false);\n                toggleJSLintResults(false);\n            });\n        });\n\n        it(\"should default to the editor's indent\", function () {\n            waitsForDone(SpecRunnerUtils.openProjectFiles([\"different-indent.js\"]), \"open test file\");\n\n            runs(function () {\n                toggleJSLintResults(false);\n                toggleJSLintResults(false);\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/.gitignore",
    "content": "/node_modules/\n/node/node_modules/\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/HintUtils2.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * HintUtils2 was created as a place to put utilities that do not require third party dependencies so\n * they can be used by tern-worker.js and other JS files.\n * This is done because of the require config in tern-worker.js needed to load tern libraries. Libraries\n * that include, say \"acorn\", will fail to load.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * Format the given parameter array. Handles separators between\n     * parameters, syntax for optional parameters, and the order of the\n     * parameter type and parameter name.\n     *\n     * @param {!Array.<{name: string, type: string, isOptional: boolean}>} params -\n     * array of parameter descriptors\n     * @param {function(string)=} appendSeparators - callback function to append separators.\n     * The separator is passed to the callback.\n     * @param {function(string, number)=} appendParameter - callback function to append parameter.\n     * The formatted parameter type and name is passed to the callback along with the\n     * current index of the parameter.\n     * @param {boolean=} typesOnly - only show parameter types. The\n     * default behavior is to include both parameter names and types.\n     * @return {string} - formatted parameter hint\n     */\n    function formatParameterHint(params, appendSeparators, appendParameter, typesOnly) {\n        var result = \"\",\n            pendingOptional = false;\n\n        params.forEach(function (value, i) {\n            var param = value.type,\n                separators = \"\";\n\n            if (value.isOptional) {\n                // if an optional param is following by an optional parameter, then\n                // terminate the bracket. Otherwise enclose a required parameter\n                // in the same bracket.\n                if (pendingOptional) {\n                    separators += \"]\";\n                }\n\n                pendingOptional = true;\n            }\n\n            if (i > 0) {\n                separators += \", \";\n            }\n\n            if (value.isOptional) {\n                separators += \"[\";\n            }\n\n            if (appendSeparators) {\n                appendSeparators(separators);\n            }\n\n            result += separators;\n\n            if (!typesOnly) {\n                param += \" \" + value.name;\n            }\n\n            if (appendParameter) {\n                appendParameter(param, i);\n            }\n\n            result += param;\n\n        });\n\n        if (pendingOptional) {\n            if (appendSeparators) {\n                appendSeparators(\"]\");\n            }\n\n            result += \"]\";\n        }\n\n        return result;\n    }\n\n    exports.formatParameterHint = formatParameterHint;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/ParameterHintsProvider.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var ScopeManager = brackets.getModule(\"JSUtils/ScopeManager\"),\n        OVERWRITE_EXISTING_HINT = false;\n\n    function JSParameterHintsProvider() {\n        this.hintState = {};\n        this.hintStack = [];\n        this.preserveHintStack = null; // close a function hint without clearing stack\n        this.session = null; // current editor session, updated by main\n    }\n\n    /**\n     * Update the current session for use by the Function Hint Manager.\n     *\n     * @param {Session} value - current session.\n     */\n    JSParameterHintsProvider.prototype.setSession = function (value) {\n        this.session = value;\n    };\n\n    /**\n     * Test if a function hint is being displayed.\n     *\n     * @return {boolean} - true if a function hint is being displayed, false\n     * otherwise.\n     */\n    JSParameterHintsProvider.prototype.isHintDisplayed = function () {\n        return this.hintState.visible === true;\n    };\n\n    /**\n     * Save the state of the current hint. Called when popping up a parameter hint\n     * for a parameter, when the parameter already part of an existing parameter\n     * hint.\n     */\n    JSParameterHintsProvider.prototype.pushHintOnStack = function () {\n        this.hintStack.push(this.hintState);\n    };\n\n    /**\n     * Restore the state of the previous function hint.\n     *\n     * @return {boolean} - true the a parameter hint has been popped, false otherwise.\n     */\n    JSParameterHintsProvider.prototype.popHintFromStack = function () {\n        if (this.hintStack.length > 0) {\n            this.hintState = this.hintStack.pop();\n            this.hintState.visible = false;\n            return true;\n        }\n\n        return false;\n    };\n\n    /**\n     * Reset the function hint stack.\n     */\n    JSParameterHintsProvider.prototype.clearFunctionHintStack = function () {\n        this.hintStack = [];\n    };\n\n    /**\n     * Test if the function call at the cursor is different from the currently displayed\n     * function hint.\n     *\n     * @param {{line:number, ch:number}} functionCallPos - the offset of the function call.\n     * @return {boolean}\n     */\n    JSParameterHintsProvider.prototype.hasFunctionCallPosChanged = function (functionCallPos) {\n        var oldFunctionCallPos = this.hintState.functionCallPos;\n        return (oldFunctionCallPos === undefined ||\n            oldFunctionCallPos.line !== functionCallPos.line ||\n            oldFunctionCallPos.ch !== functionCallPos.ch);\n    };\n\n    /**\n     * Dismiss the function hint.\n     *\n     */\n    JSParameterHintsProvider.prototype.cleanHintState = function () {\n        if (this.hintState.visible) {\n            if (!this.preserveHintStack) {\n                this.clearFunctionHintStack();\n            }\n        }\n    };\n\n    /**\n     * Pop up a function hint on the line above the caret position.\n     *\n     * @param {boolean=} pushExistingHint - if true, push the existing hint on the stack. Default is false, not\n     * to push the hint.\n     * @param {string=} hint - function hint string from tern.\n     * @param {{inFunctionCall: boolean, functionCallPos:\n     * {line: number, ch: number}}=} functionInfo -\n     * if the functionInfo is already known, it can be passed in to avoid\n     * figuring it out again.\n     * @return {jQuery.Promise} - The promise will not complete until the\n     *      hint has completed. Returns null, if the function hint is already\n     *      displayed or there is no function hint at the cursor.\n     *\n     */\n    JSParameterHintsProvider.prototype._getParameterHint = function (pushExistingHint, hint, functionInfo) {\n        var result = $.Deferred();\n        functionInfo = functionInfo || this.session.getFunctionInfo();\n        if (!functionInfo.inFunctionCall) {\n            this.cleanHintState();\n            return result.reject(null);\n        }\n\n        if (this.hasFunctionCallPosChanged(functionInfo.functionCallPos)) {\n\n            var pushHint = pushExistingHint && this.isHintDisplayed();\n            if (pushHint) {\n                this.pushHintOnStack();\n                this.preserveHintStack = true;\n            }\n\n            this.cleanHintState();\n            this.preserveHintStack = false;\n        } else if (this.isHintDisplayed()) {\n            return result.reject(null);\n        }\n\n        this.hintState.functionCallPos = functionInfo.functionCallPos;\n\n        var request = null;\n        if (!hint) {\n            request = ScopeManager.requestParameterHint(this.session, functionInfo.functionCallPos);\n        } else {\n            this.session.setFnType(hint);\n            request = $.Deferred();\n            request.resolveWith(null, [hint]);\n        }\n\n        var self = this;\n        request.done(function (fnType) {\n            var hints = self.session.getParameterHint(functionInfo.functionCallPos);\n            hints.functionCallPos = functionInfo.functionCallPos;\n            result.resolve(hints);\n        }).fail(function () {\n            self.hintState = {};\n            result.reject(null);\n        });\n\n        return result;\n    };\n\n    JSParameterHintsProvider.prototype.hasParameterHints = function () {\n        var functionInfo = this.session.getFunctionInfo();\n\n        return functionInfo.inFunctionCall;\n    };\n\n    JSParameterHintsProvider.prototype.getParameterHints = function (explicit, onCursorActivity) {\n        var functionInfo = this.session.getFunctionInfo(),\n            result = null;\n\n        if (!onCursorActivity) {\n            if (functionInfo.inFunctionCall) {\n                var token = this.session.getToken();\n\n                if ((token && token.string === \"(\") || explicit) {\n                    return this._getParameterHint();\n                }\n            } else {\n                this.cleanHintState();\n            }\n\n            return $.Deferred().reject(null);\n        }\n\n        if (!functionInfo.inFunctionCall) {\n            this.cleanHintState();\n            return $.Deferred().reject(null);\n        }\n\n        // If in a different function hint, then dismiss the old one and\n        // display the new one if there is one on the stack\n        if (this.hasFunctionCallPosChanged(functionInfo.functionCallPos)) {\n            if (this.popHintFromStack()) {\n                var poppedFunctionCallPos = this.hintState.functionCallPos,\n                    currentFunctionCallPos = this.functionInfo.functionCallPos;\n\n                if (poppedFunctionCallPos.line === currentFunctionCallPos.line &&\n                        poppedFunctionCallPos.ch === currentFunctionCallPos.ch) {\n                    this.preserveHintStack = true;\n                    result = this._getParameterHint(OVERWRITE_EXISTING_HINT,\n                        this.hintState.fnType, functionInfo);\n                    this.preserveHintStack = false;\n                    return result;\n                }\n            } else {\n                this.cleanHintState();\n            }\n        }\n\n        var hints = this.session.getParameterHint(functionInfo.functionCallPos);\n        hints.functionCallPos = functionInfo.functionCallPos;\n        return $.Deferred().resolve(hints);\n    };\n\n    exports.JSParameterHintsProvider = JSParameterHintsProvider;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/fix-acorn.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar fs = require(\"fs\");\nvar path = require(\"path\");\nvar fpath = path.resolve(__dirname, \"node_modules\", \"acorn\", \"dist\", \"acorn_loose.js\");\nvar content = fs.readFileSync(fpath, \"utf8\");\ncontent = content.replace(/'\\.\\/acorn\\.js'/g, \"'./acorn'\");\nfs.writeFileSync(fpath, content, \"utf8\");\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = brackets.getModule(\"thirdparty/lodash\");\n\n    var CodeHintManager           = brackets.getModule(\"editor/CodeHintManager\"),\n        EditorManager             = brackets.getModule(\"editor/EditorManager\"),\n        Commands                  = brackets.getModule(\"command/Commands\"),\n        CommandManager            = brackets.getModule(\"command/CommandManager\"),\n        LanguageManager           = brackets.getModule(\"language/LanguageManager\"),\n        AppInit                   = brackets.getModule(\"utils/AppInit\"),\n        ExtensionUtils            = brackets.getModule(\"utils/ExtensionUtils\"),\n        StringMatch               = brackets.getModule(\"utils/StringMatch\"),\n        ProjectManager            = brackets.getModule(\"project/ProjectManager\"),\n        PreferencesManager        = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings                   = brackets.getModule(\"strings\"),\n        JSParameterHintsProvider  = require(\"./ParameterHintsProvider\").JSParameterHintsProvider,\n        ParameterHintsManager     = brackets.getModule(\"features/ParameterHintsManager\"),\n        HintUtils                 = brackets.getModule(\"JSUtils/HintUtils\"),\n        ScopeManager              = brackets.getModule(\"JSUtils/ScopeManager\"),\n        Session                   = brackets.getModule(\"JSUtils/Session\"),\n        JumpToDefManager          = brackets.getModule(\"features/JumpToDefManager\"),\n        Acorn                     = require(\"node_modules/acorn/dist/acorn\");\n\n    var session            = null,  // object that encapsulates the current session state\n        cachedCursor       = null,  // last cursor of the current hinting session\n        cachedHints        = null,  // sorted hints for the current hinting session\n        cachedType         = null,  // describes the lookup type and the object context\n        cachedToken        = null,  // the token used in the current hinting session\n        matcher            = null,  // string matcher for hints\n        jsHintsEnabled     = true,  // preference setting to enable/disable the hint session\n        hintDetailsEnabled = true,  // preference setting to enable/disable hint type details\n        noHintsOnDot       = false, // preference setting to prevent hints on dot\n        ignoreChange;           // can ignore next \"change\" event if true;\n\n    // Languages that support inline JavaScript\n    var _inlineScriptLanguages = [\"html\", \"php\"],\n        phProvider = new JSParameterHintsProvider();\n\n    // Define the detectedExclusions which are files that have been detected to cause Tern to run out of control.\n    PreferencesManager.definePreference(\"jscodehints.detectedExclusions\", \"array\", [], {\n        description: Strings.DESCRIPTION_DETECTED_EXCLUSIONS\n    });\n\n    // This preference controls when Tern will time out when trying to understand files\n    PreferencesManager.definePreference(\"jscodehints.inferenceTimeout\", \"number\", 30000, {\n        description: Strings.DESCRIPTION_INFERENCE_TIMEOUT\n    });\n\n    // This preference controls whether to prevent hints from being displayed when dot is typed\n    PreferencesManager.definePreference(\"jscodehints.noHintsOnDot\", \"boolean\", false, {\n        description: Strings.DESCRIPTION_NO_HINTS_ON_DOT\n    });\n\n    // This preference controls whether to create a session and process all JS files or not.\n    PreferencesManager.definePreference(\"codehint.JSHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_JS_HINTS\n    });\n\n    // This preference controls whether detailed type metadata will be displayed within hint list. Defaults to true.\n    PreferencesManager.definePreference(\"jscodehints.typedetails\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_JS_HINTS_TYPE_DETAILS\n    });\n\n    /**\n     * Check whether any of code hints preferences for JS Code Hints is disabled\n     * @return {boolean} enabled/disabled\n     */\n    function _areHintsEnabled() {\n        return (PreferencesManager.get(\"codehint.JSHints\") !== false) &&\n            (PreferencesManager.get(\"showCodeHints\") !== false);\n    }\n\n    PreferencesManager.on(\"change\", \"codehint.JSHints\", function () {\n        jsHintsEnabled = _areHintsEnabled();\n    });\n\n    PreferencesManager.on(\"change\", \"showCodeHints\", function () {\n        jsHintsEnabled = _areHintsEnabled();\n    });\n\n    PreferencesManager.on(\"change\", \"jscodehints.noHintsOnDot\", function () {\n        noHintsOnDot = !!PreferencesManager.get(\"jscodehints.noHintsOnDot\");\n    });\n\n    PreferencesManager.on(\"change\", \"jscodehints.typedetails\", function () {\n        hintDetailsEnabled = PreferencesManager.get(\"jscodehints.typedetails\");\n    });\n\n    /**\n     * Sets the configuration, generally for testing/debugging use.\n     * Configuration keys are merged into the current configuration.\n     * The Tern worker is automatically updated to the new config as well.\n     *\n     * * debug: Set to true if you want verbose logging\n     * * noReset: Set to true if you don't want the worker to restart periodically\n     *\n     * @param {Object} configUpdate keys/values to merge into the config\n     */\n    function setConfig(configUpdate) {\n        var config = setConfig.config;\n        Object.keys(configUpdate).forEach(function (key) {\n            config[key] = configUpdate[key];\n        });\n\n        ScopeManager._setConfig(configUpdate);\n    }\n\n    setConfig.config = {};\n\n    /**\n     *  Get the value of current session.\n     *  Used for unit testing.\n     * @return {Session} - the current session.\n     */\n    function getSession() {\n        return session;\n    }\n\n    /**\n     * Creates a hint response object. Filters the hint list using the query\n     * string, formats the hints for display, and returns a hint response\n     * object according to the CodeHintManager's API for code hint providers.\n     *\n     * @param {Array.<Object>} hints - hints to be included in the response\n     * @param {string} query - querystring with which to filter the hint list\n     * @param {Object} type - the type of query, property vs. identifier\n     * @return {Object} - hint response as defined by the CodeHintManager API\n     */\n    function getHintResponse(hints, query, type) {\n\n        var trimmedQuery,\n            formattedHints;\n\n        if (setConfig.config.debug) {\n            console.debug(\"Hints\", _.pluck(hints, \"label\"));\n        }\n\n        function formatTypeDataForToken($hintObj, token) {\n\n            if (!hintDetailsEnabled) {\n                return;\n            }\n\n            $hintObj.addClass('brackets-js-hints-with-type-details');\n\n            (function _appendLink() {\n                if (token.url) {\n                    $('<a></a>').appendTo($hintObj).addClass(\"jshint-link\").attr('href', token.url).on(\"click\", function (event) {\n                        event.stopImmediatePropagation();\n                        event.stopPropagation();\n                    });\n                }\n            }());\n\n            if (token.type) {\n                if (token.type.trim() !== '?') {\n                    if (token.type.length < 30) {\n                        $('<span>' + token.type.split('->').join(':').toString().trim() + '</span>').appendTo($hintObj).addClass(\"brackets-js-hints-type-details\");\n                    }\n                    $('<span>' + token.type.split('->').join(':').toString().trim() + '</span>').appendTo($hintObj).addClass(\"jshint-description\");\n                }\n            } else {\n                if (token.keyword) {\n                    $('<span>keyword</span>').appendTo($hintObj).addClass(\"brackets-js-hints-keyword\");\n                }\n            }\n\n            if (token.doc) {\n                $hintObj.attr('title', token.doc);\n                $('<span></span>').text(token.doc.trim()).appendTo($hintObj).addClass(\"jshint-jsdoc\");\n            }\n        }\n\n\n        /*\n         * Returns a formatted list of hints with the query substring\n         * highlighted.\n         *\n         * @param {Array.<Object>} hints - the list of hints to format\n         * @param {string} query - querystring used for highlighting matched\n         *      poritions of each hint\n         * @return {jQuery.Deferred|{\n         *              hints: Array.<string|jQueryObject>,\n         *              match: string,\n         *              selectInitial: boolean,\n         *              handleWideResults: boolean}}\n         */\n        function formatHints(hints, query) {\n            return hints.map(function (token) {\n                var $hintObj    = $(\"<span>\").addClass(\"brackets-js-hints\");\n\n                // level indicates either variable scope or property confidence\n                if (!type.property && !token.builtin && token.depth !== undefined) {\n                    switch (token.depth) {\n                    case 0:\n                        $hintObj.addClass(\"priority-high\");\n                        break;\n                    case 1:\n                        $hintObj.addClass(\"priority-medium\");\n                        break;\n                    case 2:\n                        $hintObj.addClass(\"priority-low\");\n                        break;\n                    default:\n                        $hintObj.addClass(\"priority-lowest\");\n                        break;\n                    }\n                }\n\n                if (token.guess) {\n                    $hintObj.addClass(\"guess-hint\");\n                }\n\n                // is the token a keyword?\n                if (token.keyword) {\n                    $hintObj.addClass(\"keyword-hint\");\n                }\n\n                if (token.literal) {\n                    $hintObj.addClass(\"literal-hint\");\n                }\n\n                // highlight the matched portion of each hint\n                if (token.stringRanges) {\n                    token.stringRanges.forEach(function (item) {\n                        if (item.matched) {\n                            $hintObj.append($(\"<span>\")\n                                .append(_.escape(item.text))\n                                .addClass(\"matched-hint\"));\n                        } else {\n                            $hintObj.append(_.escape(item.text));\n                        }\n                    });\n                } else {\n                    $hintObj.text(token.value);\n                }\n\n                $hintObj.data(\"token\", token);\n\n                formatTypeDataForToken($hintObj, token);\n\n                return $hintObj;\n            });\n        }\n\n        // trim leading and trailing string literal delimiters from the query\n        trimmedQuery = _.trim(query, HintUtils.SINGLE_QUOTE + HintUtils.DOUBLE_QUOTE);\n\n        if (hints) {\n            formattedHints = formatHints(hints, trimmedQuery);\n        } else {\n            formattedHints = [];\n        }\n\n        return {\n            hints: formattedHints,\n            match: null, // the CodeHintManager should not format the results\n            selectInitial: true,\n            handleWideResults: hints.handleWideResults\n        };\n    }\n\n    /**\n     * @constructor\n     */\n    function JSHints() {\n    }\n\n    /**\n     * determine if the cached hint information should be invalidated and re-calculated\n     *\n     * @param {Session} session - the active hinting session\n     * @return {boolean} - true if the hints should be recalculated\n     */\n    JSHints.prototype.needNewHints = function (session) {\n        var cursor  = session.getCursor(),\n            type    = session.getType();\n\n        return !cachedHints || !cachedCursor || !cachedType ||\n            cachedCursor.line !== cursor.line ||\n            type.property !== cachedType.property ||\n            type.context !== cachedType.context ||\n            type.showFunctionType !== cachedType.showFunctionType ||\n            (type.functionCallPos && cachedType.functionCallPos &&\n            type.functionCallPos.ch !== cachedType.functionCallPos.ch);\n    };\n\n    /**\n     *  Cache the hints and the hint's context.\n     *\n     *  @param {Array.<string>} hints - array of hints\n     *  @param {{line:number, ch:number}} cursor - the location where the hints\n     *  were created.\n     * @param {{property: boolean,\n                showFunctionType:boolean,\n                context: string,\n                functionCallPos: {line:number, ch:number}}} type -\n     *  type information about the hints\n     *  @param {Object} token - CodeMirror token\n     */\n    function setCachedHintContext(hints, cursor, type, token) {\n        cachedHints = hints;\n        cachedCursor = cursor;\n        cachedType = type;\n        cachedToken = token;\n    }\n\n    /**\n     *  Reset cached hint context.\n     */\n    function resetCachedHintContext() {\n        cachedHints = null;\n        cachedCursor = null;\n        cachedType = null;\n        cachedToken =  null;\n    }\n\n    /**\n     *  Have conditions have changed enough to justify closing the hints popup?\n     *\n     * @param {Session} session - the active hinting session\n     * @return {boolean} - true if the hints popup should be closed.\n     */\n    JSHints.prototype.shouldCloseHints = function (session) {\n\n        // close if the token className has changed then close the hints.\n        var cursor = session.getCursor(),\n            token = session.getToken(cursor),\n            lastToken = cachedToken;\n\n        // if the line has changed, then close the hints\n        if (!cachedCursor || cursor.line !== cachedCursor.line) {\n            return true;\n        }\n\n        if (token.type === null) {\n            token = session.getNextTokenOnLine(cursor);\n        }\n\n        if (lastToken && lastToken.type === null) {\n            lastToken = session.getNextTokenOnLine(cachedCursor);\n        }\n\n        // Both of the tokens should never be null (happens when token is off\n        // the end of the line), so one is null then close the hints.\n        if (!lastToken || !token ||\n                token.type !== lastToken.type) {\n            return true;\n        }\n\n        // Test if one token string is a prefix of the other.\n        // If one is a prefix of the other then consider it the\n        // same token and don't close the hints.\n        if (token.string.length >= lastToken.string.length) {\n            return token.string.indexOf(lastToken.string) !== 0;\n        } else {\n            return lastToken.string.indexOf(token.string) !== 0;\n        }\n    };\n\n    /**\n     * @return {boolean} - true if the document supports inline JavaScript\n     */\n    function isInlineScriptSupported(document) {\n        var language = LanguageManager.getLanguageForPath(document.file.fullPath).getId();\n        return _inlineScriptLanguages.indexOf(language) !== -1;\n    }\n\n    function isInlineScript(editor) {\n        return editor.getModeForSelection() === \"javascript\";\n    }\n\n    /**\n     *  Create a new StringMatcher instance, if needed.\n     *\n     * @return {StringMatcher} - a StringMatcher instance.\n     */\n    function getStringMatcher() {\n        if (!matcher) {\n            matcher = new StringMatch.StringMatcher({\n                preferPrefixMatches: true\n            });\n        }\n\n        return matcher;\n    }\n\n    /**\n     *  Check if a hint response is pending.\n     *\n     * @param {jQuery.Deferred} deferredHints - deferred hint response\n     * @return {boolean} - true if deferred hints are pending, false otherwise.\n     */\n    function hintsArePending(deferredHints) {\n        return (deferredHints && !deferredHints.hasOwnProperty(\"hints\") &&\n            deferredHints.state() === \"pending\");\n    }\n\n    /**\n     *  Common code to get the session hints. Will get guesses if there were\n     *  no completions for the query.\n     *\n     * @param {string} query - user text to search hints with\n     *  @param {{line:number, ch:number}} cursor - the location where the hints\n     *  were created.\n     * @param {{property: boolean,\n                 showFunctionType:boolean,\n                 context: string,\n                 functionCallPos: {line:number, ch:number}}} type -\n     *  type information about the hints\n     *  @param {Object} token - CodeMirror token\n     * @param {jQuery.Deferred=} $deferredHints - existing Deferred we need to\n     * resolve (optional). If not supplied a new Deferred will be created if\n     * needed.\n     * @return {Object + jQuery.Deferred} - hint response (immediate or\n     *     deferred) as defined by the CodeHintManager API\n     */\n    function getSessionHints(query, cursor, type, token, $deferredHints) {\n\n        var hintResults = session.getHints(query, getStringMatcher());\n        if (hintResults.needGuesses) {\n            var guessesResponse = ScopeManager.requestGuesses(session,\n                session.editor.document);\n\n            if (!$deferredHints) {\n                $deferredHints = $.Deferred();\n            }\n\n            guessesResponse.done(function () {\n                if (hintsArePending($deferredHints)) {\n                    hintResults = session.getHints(query, getStringMatcher());\n                    setCachedHintContext(hintResults.hints, cursor, type, token);\n                    var hintResponse = getHintResponse(cachedHints, query, type);\n                    $deferredHints.resolveWith(null, [hintResponse]);\n                }\n            }).fail(function () {\n                if (hintsArePending($deferredHints)) {\n                    $deferredHints.reject();\n                }\n            });\n\n            return $deferredHints;\n        } else if (hintsArePending($deferredHints)) {\n            setCachedHintContext(hintResults.hints, cursor, type, token);\n            var hintResponse    = getHintResponse(cachedHints, query, type);\n            $deferredHints.resolveWith(null, [hintResponse]);\n            return null;\n        } else {\n            setCachedHintContext(hintResults.hints, cursor, type, token);\n            return getHintResponse(cachedHints, query, type);\n        }\n    }\n\n    /**\n     * Determine whether hints are available for a given editor context\n     *\n     * @param {Editor} editor - the current editor context\n     * @param {string} key - charCode of the last pressed key\n     * @return {boolean} - can the provider provide hints for this session?\n     */\n    JSHints.prototype.hasHints = function (editor, key) {\n        if (session && HintUtils.hintableKey(key, !noHintsOnDot)) {\n\n            if (isInlineScriptSupported(session.editor.document)) {\n                if (!isInlineScript(session.editor)) {\n                    return false;\n                }\n            }\n            var cursor  = session.getCursor(),\n                token   = session.getToken(cursor);\n\n            // don't autocomplete within strings or comments, etc.\n            if (token && HintUtils.hintable(token)) {\n                if (session.isFunctionName()) {\n                    return false;\n                }\n\n                if (this.needNewHints(session)) {\n                    resetCachedHintContext();\n                    matcher = null;\n                }\n                return true;\n            }\n        }\n        return false;\n    };\n\n    /**\n      * Return a list of hints, possibly deferred, for the current editor\n      * context\n      *\n      * @param {string} key - charCode of the last pressed key\n      * @return {Object + jQuery.Deferred} - hint response (immediate or\n      *     deferred) as defined by the CodeHintManager API\n      */\n    JSHints.prototype.getHints = function (key) {\n        var cursor = session.getCursor(),\n            token = session.getToken(cursor);\n\n        if (token && HintUtils.hintableKey(key, !noHintsOnDot) && HintUtils.hintable(token)) {\n            var type    = session.getType(),\n                query   = session.getQuery();\n\n            // If the hint context is changed and the hints are open, then\n            // close the hints by returning null;\n            if (CodeHintManager.isOpen() && this.shouldCloseHints(session)) {\n                return null;\n            }\n\n            // Compute fresh hints if none exist, or if the session\n            // type has changed since the last hint computation\n            if (this.needNewHints(session)) {\n                if (key) {\n                    ScopeManager.handleFileChange([{from: cursor, to: cursor, text: [key]}]);\n                    ignoreChange = true;\n                }\n\n                var scopeResponse   = ScopeManager.requestHints(session, session.editor.document),\n                    $deferredHints  = $.Deferred(),\n                    scopeSession    = session;\n\n                scopeResponse.done(function () {\n                    if (hintsArePending($deferredHints)) {\n                        // Verify we are still in same session\n                        if (scopeSession === session) {\n                            getSessionHints(query, cursor, type, token, $deferredHints);\n                        } else {\n                            $deferredHints.reject();\n                        }\n                    }\n                    scopeSession = null;\n                }).fail(function () {\n                    if (hintsArePending($deferredHints)) {\n                        $deferredHints.reject();\n                    }\n                    scopeSession = null;\n                });\n\n                return $deferredHints;\n            }\n\n            if (cachedHints) {\n                return getSessionHints(query, cursor, type, token);\n            }\n        }\n\n        return null;\n    };\n\n    /**\n     * Inserts the hint selected by the user into the current editor.\n     *\n     * @param {jQuery.Object} $hintObj - hint object to insert into current editor\n     * @return {boolean} - should a new hinting session be requested\n     *      immediately after insertion?\n     */\n    JSHints.prototype.insertHint = function ($hintObj) {\n        var hint        = $hintObj.data(\"token\"),\n            completion  = hint.value,\n            cursor      = session.getCursor(),\n            query       = session.getQuery(),\n            start       = {line: cursor.line, ch: cursor.ch - query.length},\n            end         = {line: cursor.line, ch: cursor.ch},\n            invalidPropertyName = false;\n\n        if (session.getType().property) {\n            // if we're inserting a property name, we need to make sure the\n            // hint is a valid property name.\n            // to check this, run the hint through Acorns tokenizer\n            // it should result in one token, and that token should either be\n            // a 'name' or a 'keyword', as javascript allows keywords as property names\n            var tokenizer = Acorn.tokenizer(completion);\n            var currentToken = tokenizer.getToken();\n\n            // the name is invalid if the hint is not a 'name' or 'keyword' token\n            if (currentToken.type !== Acorn.tokTypes.name && !currentToken.type.keyword) {\n                invalidPropertyName = true;\n            } else {\n                // check for a second token - if there is one (other than 'eof')\n                // then the hint isn't a valid property name either\n                currentToken = tokenizer.getToken();\n                if (currentToken.type !== Acorn.tokTypes.eof) {\n                    invalidPropertyName = true;\n                }\n            }\n\n            if (invalidPropertyName) {\n                // need to walk back to the '.' and replace\n                // with '[\"<hint>\"]\n                var dotCursor = session.findPreviousDot();\n                if (dotCursor) {\n                    completion = \"[\\\"\" + completion + \"\\\"]\";\n                    start.line = dotCursor.line;\n                    start.ch = dotCursor.ch - 1;\n                }\n            }\n        }\n\n        // Replace the current token with the completion\n        // HACK (tracking adobe/brackets#1688): We talk to the private CodeMirror instance\n        // directly to replace the range instead of using the Document, as we should. The\n        // reason is due to a flaw in our current document synchronization architecture when\n        // inline editors are open.\n        session.editor._codeMirror.replaceRange(completion, start, end);\n\n        // Return false to indicate that another hinting session is not needed\n        return false;\n    };\n\n    // load the extension\n    AppInit.appReady(function () {\n\n        /*\n         * When the editor is changed, reset the hinting session and cached\n         * information, and reject any pending deferred requests.\n         *\n         * @param {!Editor} editor - editor context to be initialized.\n         * @param {?Editor} previousEditor - the previous editor.\n         */\n        function initializeSession(editor, previousEditor) {\n            session = new Session(editor);\n            ScopeManager.handleEditorChange(session, editor.document,\n                previousEditor ? previousEditor.document : null);\n            phProvider.setSession(session);\n            cachedHints = null;\n        }\n\n        /*\n         * Connects to the given editor, creating a new Session & adding listeners\n         *\n         * @param {?Editor} editor - editor context on which to listen for\n         *      changes. If null, 'session' is cleared.\n         * @param {?Editor} previousEditor - the previous editor\n         */\n        function installEditorListeners(editor, previousEditor) {\n            // always clean up cached scope and hint info\n            resetCachedHintContext();\n\n            if (!jsHintsEnabled) {\n                return;\n            }\n\n            if (editor && HintUtils.isSupportedLanguage(LanguageManager.getLanguageForPath(editor.document.file.fullPath).getId())) {\n                initializeSession(editor, previousEditor);\n                editor\n                    .on(HintUtils.eventName(\"change\"), function (event, editor, changeList) {\n                        if (!ignoreChange) {\n                            ScopeManager.handleFileChange(changeList);\n                        }\n                        ignoreChange = false;\n                    });\n            } else {\n                session = null;\n            }\n        }\n\n        /*\n         * Uninstall editor change listeners\n         *\n         * @param {Editor} editor - editor context on which to stop listening\n         *      for changes\n         */\n        function uninstallEditorListeners(editor) {\n            if (editor) {\n                editor.off(HintUtils.eventName(\"change\"));\n            }\n        }\n\n        /*\n         * Handle the activeEditorChange event fired by EditorManager.\n         * Uninstalls the change listener on the previous editor\n         * and installs a change listener on the new editor.\n         *\n         * @param {Event} event - editor change event (ignored)\n         * @param {Editor} current - the new current editor context\n         * @param {Editor} previous - the previous editor context\n         */\n        function handleActiveEditorChange(event, current, previous) {\n            // Uninstall \"languageChanged\" event listeners on previous editor's document & put them on current editor's doc\n            if (previous) {\n                previous.document\n                    .off(HintUtils.eventName(\"languageChanged\"));\n            }\n            if (current) {\n                current.document\n                    .on(HintUtils.eventName(\"languageChanged\"), function () {\n                        // If current doc's language changed, reset our state by treating it as if the user switched to a\n                        // different document altogether\n                        uninstallEditorListeners(current);\n                        installEditorListeners(current);\n                    });\n            }\n\n            uninstallEditorListeners(previous);\n            installEditorListeners(current, previous);\n        }\n\n        function setJumpPosition(curPos) {\n            EditorManager.getCurrentFullEditor().setCursorPos(curPos.line, curPos.ch, true);\n        }\n\n        function JSJumpToDefProvider() {\n        }\n\n        JSJumpToDefProvider.prototype.canJumpToDef = function (editor, implicitChar) {\n            return true;\n        };\n\n        /**\n         * Method to handle jump to definition feature.\n         */\n        JSJumpToDefProvider.prototype.doJumpToDef = function () {\n            var offset,\n                handleJumpResponse;\n\n\n            // Only provide jump-to-definition results when cursor is in JavaScript content\n            if (!session || session.editor.getModeForSelection() !== \"javascript\") {\n                return null;\n            }\n\n            var result = new $.Deferred();\n\n            /**\n             * Make a jump-to-def request based on the session and offset passed in.\n             * @param {Session} session - the session\n             * @param {number} offset - the offset of where to jump from\n             */\n            function requestJumpToDef(session, offset) {\n                var response = ScopeManager.requestJumptoDef(session, session.editor.document, offset);\n\n                if (response.hasOwnProperty(\"promise\")) {\n                    response.promise.done(handleJumpResponse).fail(function () {\n                        result.reject();\n                    });\n                }\n            }\n\n\n            /**\n             * Sets the selection to move the cursor to the result position.\n             * Assumes that the editor has already changed files, if necessary.\n             *\n             * Additionally, this will check to see if the selection looks like an\n             * assignment to a member expression - if it is, and the type is a function,\n             * then we will attempt to jump to the RHS of the expression.\n             *\n             * 'exports.foo = foo'\n             *\n             * if the selection is 'foo' in 'exports.foo', then we will attempt to jump to def\n             * on the rhs of the assignment.\n             *\n             * @param {number} start - the start of the selection\n             * @param {number} end - the end of the selection\n             * @param {boolean} isFunction - true if we are jumping to the source of a function def\n             */\n            function setJumpSelection(start, end, isFunction) {\n\n                /**\n                 * helper function to decide if the tokens on the RHS of an assignment\n                 * look like an identifier, or member expr.\n                 */\n                function validIdOrProp(token) {\n                    if (!token) {\n                        return false;\n                    }\n                    if (token.string === \".\") {\n                        return true;\n                    }\n                    var type = token.type;\n                    if (type === \"variable-2\" || type === \"variable\" || type === \"property\") {\n                        return true;\n                    }\n\n                    return false;\n                }\n\n                var madeNewRequest = false;\n\n                if (isFunction) {\n                    // When jumping to function defs, follow the chain back\n                    // to get to the original function def\n                    var cursor = {line: end.line, ch: end.ch},\n                        prev = session._getPreviousToken(cursor),\n                        next,\n                        offset;\n\n                    // see if the selection is preceded by a '.', indicating we're in a member expr\n                    if (prev.string === \".\") {\n                        cursor = {line: end.line, ch: end.ch};\n                        next = session.getNextToken(cursor, true);\n                        // check if the next token indicates an assignment\n                        if (next && next.string === \"=\") {\n                            next = session.getNextToken(cursor, true);\n                            // find the last token of the identifier, or member expr\n                            while (validIdOrProp(next)) {\n                                offset = session.getOffsetFromCursor({line: cursor.line, ch: next.end});\n                                next = session.getNextToken(cursor, false);\n                            }\n                            if (offset) {\n                                // trigger another jump to def based on the offset of the RHS\n                                requestJumpToDef(session, offset);\n                                madeNewRequest = true;\n                            }\n                        }\n                    }\n                }\n                // We didn't make a new jump-to-def request, so we can resolve the promise\n                // and set the selection\n                if (!madeNewRequest) {\n                    // set the selection\n                    session.editor.setSelection(start, end, true);\n                    result.resolve(true);\n                }\n            }\n\n            /**\n             * handle processing of the completed jump-to-def request.\n             * will open the appropriate file, and set the selection based\n             * on the response.\n             */\n            handleJumpResponse = function (jumpResp) {\n\n                if (jumpResp.resultFile) {\n                    if (jumpResp.resultFile !== jumpResp.file) {\n                        var resolvedPath = ScopeManager.getResolvedPath(jumpResp.resultFile);\n                        if (resolvedPath) {\n                            CommandManager.execute(Commands.FILE_OPEN, {fullPath: resolvedPath})\n                                .done(function () {\n                                    setJumpSelection(jumpResp.start, jumpResp.end, jumpResp.isFunction);\n                                });\n                        }\n                    } else {\n                        setJumpSelection(jumpResp.start, jumpResp.end, jumpResp.isFunction);\n                    }\n                } else {\n                    result.reject();\n                }\n            };\n\n            offset = session.getOffset();\n            // request a jump-to-def\n            requestJumpToDef(session, offset);\n\n            return result.promise();\n        };\n\n        /*\n         * Helper for QuickEdit jump-to-definition request.\n         */\n        function quickEditHelper() {\n            var offset     = session.getCursor(),\n                response   = ScopeManager.requestJumptoDef(session, session.editor.document, offset);\n\n            return response;\n        }\n\n        // Register quickEditHelper.\n        brackets._jsCodeHintsHelper = quickEditHelper;\n\n        // Configuration function used for debugging\n        brackets._configureJSCodeHints = setConfig;\n\n        ExtensionUtils.loadStyleSheet(module, \"styles/brackets-js-hints.css\");\n\n        // uninstall/install change listener as the active editor changes\n        EditorManager.on(HintUtils.eventName(\"activeEditorChange\"),\n                handleActiveEditorChange);\n\n        ProjectManager.on(\"beforeProjectClose\", function () {\n            ScopeManager.handleProjectClose();\n        });\n\n        ProjectManager.on(\"projectOpen\", function () {\n            ScopeManager.handleProjectOpen();\n        });\n\n        // immediately install the current editor\n        installEditorListeners(EditorManager.getActiveEditor());\n\n        ParameterHintsManager.registerHintProvider(phProvider, [\"javascript\"], 0);\n        // init\n        var jdProvider = new JSJumpToDefProvider();\n        JumpToDefManager.registerJumpToDefProvider(jdProvider, [\"javascript\"], 0);\n\n        var jsHints = new JSHints();\n        CodeHintManager.registerHintProvider(jsHints, HintUtils.SUPPORTED_LANGUAGES, 0);\n\n        // for unit testing\n        exports.getSession = getSession;\n        exports.jsHintProvider = jsHints;\n        exports.initializeSession = initializeSession;\n        exports.handleJumpToDefinition = jdProvider.doJumpToDef.bind(jdProvider);\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/npm-shrinkwrap.json",
    "content": "{\n  \"name\": \"brackets-javascript-code-hints\",\n  \"dependencies\": {\n    \"acorn\": {\n      \"version\": \"3.3.0\",\n      \"from\": \"acorn@3.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz\"\n    },\n    \"buffer-shims\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"buffer-shims@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz\"\n    },\n    \"core-util-is\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"core-util-is@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\"\n    },\n    \"enhanced-resolve\": {\n      \"version\": \"2.2.2\",\n      \"from\": \"enhanced-resolve@>=2.2.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.2.2.tgz\"\n    },\n    \"errno\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"errno@>=0.1.3 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/errno/-/errno-0.1.4.tgz\"\n    },\n    \"glob\": {\n      \"version\": \"3.2.11\",\n      \"from\": \"glob@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/glob/-/glob-3.2.11.tgz\",\n      \"dependencies\": {\n        \"minimatch\": {\n          \"version\": \"0.3.0\",\n          \"from\": \"minimatch@>=0.3.0 <0.4.0\",\n          \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz\"\n        }\n      }\n    },\n    \"graceful-fs\": {\n      \"version\": \"4.1.6\",\n      \"from\": \"graceful-fs@>=4.1.2 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz\"\n    },\n    \"inherits\": {\n      \"version\": \"2.0.1\",\n      \"from\": \"inherits@>=2.0.1 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz\"\n    },\n    \"isarray\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"isarray@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz\"\n    },\n    \"lru-cache\": {\n      \"version\": \"2.7.3\",\n      \"from\": \"lru-cache@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz\"\n    },\n    \"memory-fs\": {\n      \"version\": \"0.3.0\",\n      \"from\": \"memory-fs@>=0.3.0 <0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz\"\n    },\n    \"minimatch\": {\n      \"version\": \"0.2.14\",\n      \"from\": \"minimatch@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz\"\n    },\n    \"object-assign\": {\n      \"version\": \"4.1.0\",\n      \"from\": \"object-assign@>=4.0.1 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz\"\n    },\n    \"process-nextick-args\": {\n      \"version\": \"1.0.7\",\n      \"from\": \"process-nextick-args@>=1.0.6 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz\"\n    },\n    \"prr\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"prr@>=0.0.0 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/prr/-/prr-0.0.0.tgz\"\n    },\n    \"readable-stream\": {\n      \"version\": \"2.1.5\",\n      \"from\": \"readable-stream@>=2.0.1 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz\"\n    },\n    \"resolve-from\": {\n      \"version\": \"2.0.0\",\n      \"from\": \"resolve-from@2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz\"\n    },\n    \"sigmund\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"sigmund@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz\"\n    },\n    \"string_decoder\": {\n      \"version\": \"0.10.31\",\n      \"from\": \"string_decoder@>=0.10.0 <0.11.0\",\n      \"resolved\": \"https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz\"\n    },\n    \"tapable\": {\n      \"version\": \"0.2.4\",\n      \"from\": \"tapable@>=0.2.3 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/tapable/-/tapable-0.2.4.tgz\"\n    },\n    \"tern\": {\n      \"version\": \"0.20.0\",\n      \"from\": \"tern@0.20.0\",\n      \"resolved\": \"https://registry.npmjs.org/tern/-/tern-0.20.0.tgz\"\n    },\n    \"util-deprecate\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"util-deprecate@>=1.0.1 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/package.json",
    "content": "{\n  \"name\": \"brackets-javascript-code-hints\",\n  \"dependencies\": {\n    \"acorn\": \"3.3.0\",\n    \"tern\": \"0.20.0\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"node ./fix-acorn\"\n  }\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/styles/brackets-js-hints.css",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\nspan.brackets-js-hints-with-type-details {\n    width: 300px;\n    display: inline-block;\n}\n\n.brackets-js-hints.type-undetermined:before {\n    color: cornflowerblue;\n    content: '12';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    visibility: hidden;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-number:before {\n    color: cornflowerblue;\n    content: '12';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-string:before {\n    color: cornflowerblue;\n    content: 'ab';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-function:before {\n    color: cornflowerblue;\n    content: 'fn( )';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-array:before {\n    color: cornflowerblue;\n    content: '[  ]';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-object:before {\n    color: cornflowerblue;\n    content: '{ :}';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-num-array:before {\n    color: cornflowerblue;\n    content: '[12]';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-string-array:before {\n    color: cornflowerblue;\n    content: '[ab]';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints.type-boolean:before {\n    color: cornflowerblue;\n    content: 'bool';\n    border: 1px cornflowerblue solid;\n    float:left;\n    width:25px;\n    text-align: center;\n    margin-left:-5px;\n    margin-right:5px;\n    line-height: 1.2em;\n}\n\n.brackets-js-hints-type-details {\n    color: #a3a3a3 !important;\n    font-weight: 100;\n    font-style: italic !important;\n    margin-right: 5px;\n    float:right;\n}\n\n.jshint-description {\n    display: none;\n    color: #d4d4d4;\n    word-wrap: break-word;\t\n    white-space: normal;\n    box-sizing: border-box;\n}\n\n.dark .jshint-description {\n    color: #ccc;\n}\n\n.jshint-jsdoc {\n    display: none;\n    padding-right: 10px !important;\n    color: grey;\n    word-wrap: break-word;\n    white-space: normal;\n    box-sizing: border-box;\n    float: left;\n    clear: left;\n    max-height: 2em;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    line-height: 1em;\n    -webkit-line-clamp: 2;\n    -webkit-box-orient: vertical;\n}\n\n.dark .jshint-jsdoc {\n    color: #ccc;\n}\n\n.jshint-link {\n    display:none;\n    width:0px !important;\n    height:1px !important;\n    margin-left: 15px;\n    float:right;\n}\n\n.jshint-link:before {\n    position: relative;\n    float: left;\n    top:1px;\n    content: \"i\" !important;\n    width: 16px;\n    height: 16px;\n    margin-right:10px;\n    font-size: 14px;\n    font-weight: bold;\n    font-style: italic;\n    line-height: 15px;\n    text-align: center;\n    visibility: visible !important;\n    font-weight: 900;\n    color: #fff;\n    background-color: #2ea56c;\n    border-color: #177F42;\n    border-radius: 16px;\n    font-family: SourceSansPro-Semibold;\n}\n\n.dark .jshint-link:before {\n    background-color: #146a41;\n}\n\n.highlight .jshint-link {\n    display: inline-block !important;\n}\n\n.highlight .jshint-description {\n    display: block;\n    color: #6495ed !important;\n}\n\n.highlight .jshint-jsdoc {\n    display: -webkit-box;\n}\n\n.dark .brackets-js-hints-type-details {\n    color: #696969 !important;\n} \n\n.highlight .brackets-js-hints-type-details {\n    display:none;\n}\n\n.brackets-js-hints-keyword {\n    font-weight: 100;\n    font-style: italic !important;\n    margin-right: 5px;\n    float:right;\n    color: #6495ed !important;\n}\n\n\n.brackets-js-hints.priority-high {\n    color: #486c00; /* green */\n}\n\n.brackets-js-hints.priority-medium {\n    color: #0c50af; /* blue */\n}\n\n.brackets-js-hints.priority-low {\n    color: #6b24bd; /* violet */\n}\n\n.brackets-js-hints.priority-lowest {\n    color: #444; /* dark grey */\n}\n\n.brackets-js-hints.variable-hint {\n}\n\n.brackets-js-hints.property-hint {\n}\n\n.brackets-js-hints.literal-hint {\n    color: #444; /* dark grey */\n    font-family: SourceCodePro;\n}\n\n.brackets-js-hints.keyword-hint {\n    font-family: SourceCodePro; \n}\n\n.brackets-js-hints.keyword-hint .matched-hint {\n    font-family: SourceCodePro-Medium;\n    font-weight: 500; \n}\n\n.brackets-js-hints .matched-hint {\n    font-weight: 500;\n}\n\n.brackets-js-hints.guess-hint {\n    font-style: italic;\n}\n\n#function-hint-container {\n    display: none;\n\n    background: #fff;\n    position: absolute;\n    z-index: 15;\n    left: 200px;\n    top: 40px;\n    pointer-events: none;\n\n    padding: 1px 6px;\n    text-align: center;\n\n    border-radius: 3px;\n    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.24);\n}\n\n#function-hint-container .function-hint-content {\n}\n\n.brackets-js-hints .current-parameter {\n    font-weight: 500;\n}\n\n/* Dark Styles */\n\n.dark .brackets-js-hints.priority-high {\n    color: #a1f200; /* green */\n}\n\n.dark .brackets-js-hints.priority-medium {\n    color: #3ff8ff; /* blue */\n}\n\n.dark .brackets-js-hints.priority-low {\n    color: #e6adff; /* violet */\n}\n\n.dark .brackets-js-hints.priority-lowest {\n    color: #bbb; /* dark grey */\n}\n\n.dark .brackets-js-hints.literal-hint {\n    color: #bbb; /* dark grey */\n    font-family: SourceCodePro;\n}\n\n.dark #function-hint-container {\n    background: #000;\n    border: 1px solid rgba(255,255,255,0.15);\n    color: #fff;\n    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.24);\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/thirdparty/requirejs/LICENSE",
    "content": "RequireJS is released under two licenses: new BSD, and MIT. You may pick the\nlicense that best suits your development needs. The text of both licenses are\nprovided below.\n\n\nThe \"New\" BSD License:\n----------------------\n\nCopyright (c) 2010-2011, The Dojo Foundation\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright notice, this\n    list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright notice,\n    this list of conditions and the following disclaimer in the documentation\n    and/or other materials provided with the distribution.\n  * Neither the name of the Dojo Foundation nor the names of its contributors\n    may be used to endorse or promote products derived from this software\n    without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n\nMIT License\n-----------\n\nCopyright (c) 2010-2011, The Dojo Foundation\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/thirdparty/requirejs/require.js",
    "content": "/*\n RequireJS 2.1.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n Available via the MIT or new BSD license.\n see: http://github.com/jrburke/requirejs for details\n*/\nvar requirejs,require,define;\n(function(W){function D(b){return M.call(b)===\"[object Function]\"}function E(b){return M.call(b)===\"[object Array]\"}function t(b,c){if(b){var d;for(d=0;d<b.length;d+=1)if(b[d]&&c(b[d],d,b))break}}function N(b,c){if(b){var d;for(d=b.length-1;d>-1;d-=1)if(b[d]&&c(b[d],d,b))break}}function A(b,c){for(var d in b)if(b.hasOwnProperty(d)&&c(b[d],d))break}function O(b,c,d,g){c&&A(c,function(c,j){if(d||!F.call(b,j))g&&typeof c!==\"string\"?(b[j]||(b[j]={}),O(b[j],c,d,g)):b[j]=c});return b}function r(b,c){return function(){return c.apply(b,\narguments)}}function X(b){if(!b)return b;var c=W;t(b.split(\".\"),function(b){c=c[b]});return c}function G(b,c,d,g){c=Error(c+\"\\nhttp://requirejs.org/docs/errors.html#\"+b);c.requireType=b;c.requireModules=g;if(d)c.originalError=d;return c}function ba(){if(H&&H.readyState===\"interactive\")return H;N(document.getElementsByTagName(\"script\"),function(b){if(b.readyState===\"interactive\")return H=b});return H}var g,s,u,y,q,B,H,I,Y,Z,ca=/(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/mg,da=/[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g,\n$=/\\.js$/,ea=/^\\.\\//;s=Object.prototype;var M=s.toString,F=s.hasOwnProperty,fa=Array.prototype.splice,v=!!(typeof window!==\"undefined\"&&navigator&&document),aa=!v&&typeof importScripts!==\"undefined\",ga=v&&navigator.platform===\"PLAYSTATION 3\"?/^complete$/:/^(complete|loaded)$/,R=typeof opera!==\"undefined\"&&opera.toString()===\"[object Opera]\",w={},n={},P=[],J=!1;if(typeof define===\"undefined\"){if(typeof requirejs!==\"undefined\"){if(D(requirejs))return;n=requirejs;requirejs=void 0}typeof require!==\"undefined\"&&\n!D(require)&&(n=require,require=void 0);g=requirejs=function(b,c,d,p){var i,j=\"_\";!E(b)&&typeof b!==\"string\"&&(i=b,E(c)?(b=c,c=d,d=p):b=[]);if(i&&i.context)j=i.context;(p=w[j])||(p=w[j]=g.s.newContext(j));i&&p.configure(i);return p.require(b,c,d)};g.config=function(b){return g(b)};g.nextTick=typeof setTimeout!==\"undefined\"?function(b){setTimeout(b,4)}:function(b){b()};require||(require=g);g.version=\"2.1.1\";g.jsExtRegExp=/^\\/|:|\\?|\\.js$/;g.isBrowser=v;s=g.s={contexts:w,newContext:function(b){function c(a,\nf,x){var e,m,b,c,d,h,i,g=f&&f.split(\"/\");e=g;var j=k.map,l=j&&j[\"*\"];if(a&&a.charAt(0)===\".\")if(f){e=k.pkgs[f]?g=[f]:g.slice(0,g.length-1);f=a=e.concat(a.split(\"/\"));for(e=0;f[e];e+=1)if(m=f[e],m===\".\")f.splice(e,1),e-=1;else if(m===\"..\")if(e===1&&(f[2]===\"..\"||f[0]===\"..\"))break;else e>0&&(f.splice(e-1,2),e-=2);e=k.pkgs[f=a[0]];a=a.join(\"/\");e&&a===f+\"/\"+e.main&&(a=f)}else a.indexOf(\"./\")===0&&(a=a.substring(2));if(x&&(g||l)&&j){f=a.split(\"/\");for(e=f.length;e>0;e-=1){b=f.slice(0,e).join(\"/\");if(g)for(m=\ng.length;m>0;m-=1)if(x=j[g.slice(0,m).join(\"/\")])if(x=x[b]){c=x;d=e;break}if(c)break;!h&&l&&l[b]&&(h=l[b],i=e)}!c&&h&&(c=h,d=i);c&&(f.splice(0,d,c),a=f.join(\"/\"))}return a}function d(a){v&&t(document.getElementsByTagName(\"script\"),function(f){if(f.getAttribute(\"data-requiremodule\")===a&&f.getAttribute(\"data-requirecontext\")===h.contextName)return f.parentNode.removeChild(f),!0})}function p(a){var f=k.paths[a];if(f&&E(f)&&f.length>1)return d(a),f.shift(),h.require.undef(a),h.require([a]),!0}function i(a){var f,\nb=a?a.indexOf(\"!\"):-1;b>-1&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function j(a,f,b,e){var m,K,d=null,g=f?f.name:null,j=a,l=!0,k=\"\";a||(l=!1,a=\"_@r\"+(M+=1));a=i(a);d=a[0];a=a[1];d&&(d=c(d,g,e),K=o[d]);a&&(d?k=K&&K.normalize?K.normalize(a,function(a){return c(a,g,e)}):c(a,g,e):(k=c(a,g,e),a=i(k),d=a[0],k=a[1],b=!0,m=h.nameToUrl(k)));b=d&&!K&&!b?\"_unnormalized\"+(N+=1):\"\";return{prefix:d,name:k,parentMap:f,unnormalized:!!b,url:m,originalName:j,isDefine:l,id:(d?d+\"!\"+k:k)+b}}function n(a){var f=\na.id,b=l[f];b||(b=l[f]=new h.Module(a));return b}function q(a,f,b){var e=a.id,m=l[e];if(F.call(o,e)&&(!m||m.defineEmitComplete))f===\"defined\"&&b(o[e]);else n(a).on(f,b)}function z(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(t(b,function(f){if(f=l[f])f.error=a,f.events.error&&(e=!0,f.emit(\"error\",a))}),!e)g.onError(a)}function s(){P.length&&(fa.apply(C,[C.length-1,0].concat(P)),P=[])}function u(a,f,b){var e=a.map.id;a.error?a.emit(\"error\",a.error):(f[e]=!0,t(a.depMaps,function(e,c){var d=e.id,\ng=l[d];g&&!a.depMatched[c]&&!b[d]&&(f[d]?(a.defineDep(c,o[d]),a.check()):u(g,f,b))}),b[e]=!0)}function w(){var a,f,b,e,m=(b=k.waitSeconds*1E3)&&h.startTime+b<(new Date).getTime(),c=[],g=[],i=!1,j=!0;if(!S){S=!0;A(l,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||g.push(b),!b.error))if(!b.inited&&m)p(f)?i=e=!0:(c.push(f),d(f));else if(!b.inited&&b.fetched&&a.isDefine&&(i=!0,!a.prefix))return j=!1});if(m&&c.length)return b=G(\"timeout\",\"Load timeout for modules: \"+c,null,c),b.contextName=h.contextName,\nz(b);j&&t(g,function(a){u(a,{},{})});if((!m||e)&&i)if((v||aa)&&!T)T=setTimeout(function(){T=0;w()},50);S=!1}}function y(a){n(j(a[0],null,!0)).init(a[1],a[2])}function B(a){var a=a.currentTarget||a.srcElement,b=h.onScriptLoad;a.detachEvent&&!R?a.detachEvent(\"onreadystatechange\",b):a.removeEventListener(\"load\",b,!1);b=h.onScriptError;a.detachEvent&&!R||a.removeEventListener(\"error\",b,!1);return{node:a,id:a&&a.getAttribute(\"data-requiremodule\")}}function I(){var a;for(s();C.length;)if(a=C.shift(),a[0]===\nnull)return z(G(\"mismatch\",\"Mismatched anonymous define() module: \"+a[a.length-1]));else y(a)}var S,U,h,L,T,k={waitSeconds:7,baseUrl:\"./\",paths:{},pkgs:{},shim:{},map:{},config:{}},l={},V={},C=[],o={},Q={},M=1,N=1;L={require:function(a){return a.require?a.require:a.require=h.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=o[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return k.config&&\nk.config[a.map.id]||{}},exports:o[a.map.id]}}};U=function(a){this.events=V[a.id]||{};this.map=a;this.shim=k.shim[a.id];this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};U.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on(\"error\",c);else this.events.error&&(c=r(this,function(a){this.emit(\"error\",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},\ndefineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;h.startTime=(new Date).getTime();var a=this.map;if(this.shim)h.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],r(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;Q[a]||(Q[a]=!0,h.load(this.map.id,a))},check:function(){if(this.enabled&&\n!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,m=this.factory;if(this.inited)if(this.error)this.emit(\"error\",this.error);else{if(!this.defining){this.defining=!0;if(this.depCount<1&&!this.defined){if(D(m)){if(this.events.error)try{e=h.execCb(c,m,b,e)}catch(d){a=d}else e=h.execCb(c,m,b,e);if(this.map.isDefine)if((b=this.module)&&b.exports!==void 0&&b.exports!==this.exports)e=b.exports;else if(e===void 0&&this.usingExports)e=this.exports;if(a)return a.requireMap=this.map,\na.requireModules=[this.map.id],a.requireType=\"define\",z(this.error=a)}else e=m;this.exports=e;if(this.map.isDefine&&!this.ignore&&(o[c]=e,g.onResourceLoad))g.onResourceLoad(h,this.map,this.depMaps);delete l[c];this.defined=!0}this.defining=!1;if(this.defined&&!this.defineEmitted)this.defineEmitted=!0,this.emit(\"defined\",this.exports),this.defineEmitComplete=!0}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=j(a.prefix);this.depMaps.push(d);q(d,\"defined\",r(this,function(e){var m,\nd;d=this.map.name;var x=this.map.parentMap?this.map.parentMap.name:null,i=h.makeRequire(a.parentMap,{enableBuildCallback:!0,skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,x,!0)})||\"\"),e=j(a.prefix+\"!\"+d,this.map.parentMap),q(e,\"defined\",r(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=l[e.id]){this.depMaps.push(e);if(this.events.error)d.on(\"error\",r(this,function(a){this.emit(\"error\",a)}));d.enable()}}else m=r(this,\nfunction(a){this.init([],function(){return a},null,{enabled:!0})}),m.error=r(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];A(l,function(a){a.map.id.indexOf(b+\"_unnormalized\")===0&&delete l[a.map.id]});z(a)}),m.fromText=r(this,function(b,e){var f=a.name,c=j(f),d=J;e&&(b=e);d&&(J=!1);n(c);try{g.exec(b)}catch(x){throw Error(\"fromText eval for \"+f+\" failed: \"+x);}d&&(J=!0);this.depMaps.push(c);h.completeLoad(f);i([f],m)}),e.load(a.name,i,m,k)}));h.enable(d,this);this.pluginMaps[d.id]=\nd},enable:function(){this.enabling=this.enabled=!0;t(this.depMaps,r(this,function(a,b){var c,e;if(typeof a===\"string\"){a=j(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=L[a.id]){this.depExports[b]=c(this);return}this.depCount+=1;q(a,\"defined\",r(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&q(a,\"error\",this.errback)}c=a.id;e=l[c];!L[c]&&e&&!e.enabled&&h.enable(a,this)}));A(this.pluginMaps,r(this,function(a){var b=l[a.id];b&&!b.enabled&&\nh.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){t(this.events[a],function(a){a(b)});a===\"error\"&&delete this.events[a]}};h={config:k,contextName:b,registry:l,defined:o,urlFetched:Q,defQueue:C,Module:U,makeModuleMap:j,nextTick:g.nextTick,configure:function(a){a.baseUrl&&a.baseUrl.charAt(a.baseUrl.length-1)!==\"/\"&&(a.baseUrl+=\"/\");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};A(a,function(a,b){e[b]?\nb===\"map\"?O(k[b],a,!0,!0):O(k[b],a,!0):k[b]=a});if(a.shim)A(a.shim,function(a,b){E(a)&&(a={deps:a});if(a.exports&&!a.exportsFn)a.exportsFn=h.makeShimExports(a);c[b]=a}),k.shim=c;if(a.packages)t(a.packages,function(a){a=typeof a===\"string\"?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||\"main\").replace(ea,\"\").replace($,\"\")}}),k.pkgs=b;A(l,function(a,b){if(!a.inited&&!a.map.unnormalized)a.map=j(b)});if(a.deps||a.callback)h.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;\na.init&&(b=a.init.apply(W,arguments));return b||X(a.exports)}},makeRequire:function(a,f){function d(e,c,i){var k,p;if(f.enableBuildCallback&&c&&D(c))c.__requireJsBuild=!0;if(typeof e===\"string\"){if(D(c))return z(G(\"requireargs\",\"Invalid require call\"),i);if(a&&L[e])return L[e](l[a.id]);if(g.get)return g.get(h,e,a);k=j(e,a,!1,!0);k=k.id;return!F.call(o,k)?z(G(\"notloaded\",'Module name \"'+k+'\" has not been loaded yet for context: '+b+(a?\"\":\". Use require([])\"))):o[k]}I();h.nextTick(function(){I();p=\nn(j(null,a));p.skipMap=f.skipMap;p.init(e,c,i,{enabled:!0});w()});return d}f=f||{};O(d,{isBrowser:v,toUrl:function(b){var d=b.lastIndexOf(\".\"),f=null;d!==-1&&(f=b.substring(d,b.length),b=b.substring(0,d));return h.nameToUrl(c(b,a&&a.id,!0),f)},defined:function(b){b=j(b,a,!1,!0).id;return F.call(o,b)},specified:function(b){b=j(b,a,!1,!0).id;return F.call(o,b)||F.call(l,b)}});if(!a)d.undef=function(b){s();var c=j(b,a,!0),d=l[b];delete o[b];delete Q[c.url];delete V[b];if(d){if(d.events.defined)V[b]=\nd.events;delete l[b]}};return d},enable:function(a){l[a.id]&&n(a).enable()},completeLoad:function(a){var b,c,d=k.shim[a]||{},g=d.exports;for(s();C.length;){c=C.shift();if(c[0]===null){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);y(c)}c=l[a];if(!b&&!o[a]&&c&&!c.inited)if(k.enforceDefine&&(!g||!X(g)))if(p(a))return;else return z(G(\"nodefine\",\"No define call for \"+a,null,[a]));else y([a,d.deps||[],d.exportsFn]);w()},nameToUrl:function(a,b){var c,d,i,h,j,l;if(g.jsExtRegExp.test(a))h=a+(b||\"\");else{c=\nk.paths;d=k.pkgs;h=a.split(\"/\");for(j=h.length;j>0;j-=1)if(l=h.slice(0,j).join(\"/\"),i=d[l],l=c[l]){E(l)&&(l=l[0]);h.splice(0,j,l);break}else if(i){c=a===i.name?i.location+\"/\"+i.main:i.location;h.splice(0,j,c);break}h=h.join(\"/\");h+=b||(/\\?/.test(h)?\"\":\".js\");h=(h.charAt(0)===\"/\"||h.match(/^[\\w\\+\\.\\-]+:/)?\"\":k.baseUrl)+h}return k.urlArgs?h+((h.indexOf(\"?\")===-1?\"?\":\"&\")+k.urlArgs):h},load:function(a,b){g.load(h,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if(a.type===\n\"load\"||ga.test((a.currentTarget||a.srcElement).readyState))H=null,a=B(a),h.completeLoad(a.id)},onScriptError:function(a){var b=B(a);if(!p(b.id))return z(G(\"scripterror\",\"Script error\",a,[b.id]))}};h.require=h.makeRequire();return h}};g({});t([\"toUrl\",\"undef\",\"defined\",\"specified\"],function(b){g[b]=function(){var c=w._;return c.require[b].apply(c,arguments)}});if(v&&(u=s.head=document.getElementsByTagName(\"head\")[0],y=document.getElementsByTagName(\"base\")[0]))u=s.head=y.parentNode;g.onError=function(b){throw b;\n};g.load=function(b,c,d){var g=b&&b.config||{},i;if(v)return i=g.xhtml?document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"html:script\"):document.createElement(\"script\"),i.type=g.scriptType||\"text/javascript\",i.charset=\"utf-8\",i.async=!0,i.setAttribute(\"data-requirecontext\",b.contextName),i.setAttribute(\"data-requiremodule\",c),i.attachEvent&&!(i.attachEvent.toString&&i.attachEvent.toString().indexOf(\"[native code\")<0)&&!R?(J=!0,i.attachEvent(\"onreadystatechange\",b.onScriptLoad)):(i.addEventListener(\"load\",\nb.onScriptLoad,!1),i.addEventListener(\"error\",b.onScriptError,!1)),i.src=d,I=i,y?u.insertBefore(i,y):u.appendChild(i),I=null,i;else aa&&(importScripts(d),b.completeLoad(c))};v&&N(document.getElementsByTagName(\"script\"),function(b){if(!u)u=b.parentNode;if(q=b.getAttribute(\"data-main\")){if(!n.baseUrl)B=q.split(\"/\"),Y=B.pop(),Z=B.length?B.join(\"/\")+\"/\":\"./\",n.baseUrl=Z,q=Y;q=q.replace($,\"\");n.deps=n.deps?n.deps.concat(q):[q];return!0}});define=function(b,c,d){var g,i;typeof b!==\"string\"&&(d=c,c=b,b=\nnull);E(c)||(d=c,c=[]);!c.length&&D(d)&&d.length&&(d.toString().replace(ca,\"\").replace(da,function(b,d){c.push(d)}),c=(d.length===1?[\"require\"]:[\"require\",\"exports\",\"module\"]).concat(c));if(J&&(g=I||ba()))b||(b=g.getAttribute(\"data-requiremodule\")),i=w[g.getAttribute(\"data-requirecontext\")];(i?i.defQueue:P).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(n)}})(this);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/basic-test-files/MyModule.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function (require, exports, module) {\n    \"use strict\";\n    exports.a = function (a, b) {};\n    exports.b = function () {\n        return \"a string\";\n    };\n    exports.j = \"hi\";\n    \n\n    function c() {\n    }\n    \n    exports.c = \n        c;\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/basic-test-files/file1.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global brackets, require */\n\nvar A1 = { propA : 1 },\n    A2 = { propA : 2 },\n    A3 = A2;\n\nfunction funB(paramB1, paramB2) {\n    'use strict';\n    \n    var B1 = { propB : 1 },\n        B2 = { propB : 2 };\n\n    function funC(paramC1, paramC2) {\n        var C1 = { propC : 1 },\n            C2 = { propC : 2 };\n\n        B1.propB = 0;\n        C1.propC = 0;\n        B1.foo = 0;\n        console.log(\"hello\\\\\\\" world!\");\n    }\n    \n    var s = \"a string\";\n    var r = s;\n    var t = r;\n\n}\n\n/**\n * @param {string} a\n * @param {number} b\n */\nfunction funD(a, b) {\n    \"use strict\";\n    return {x: a, y: b};\n}\n\nrequire([\"MyModule\"], function (myModule) {\n    'use strict';\n    var x = myModule.a;\n});\n\nfunB();\nvar x = A1;\n\nvar arr = [];\narr[\"my-key\"] = 1;\narr[\"for\"] = 10;\n\nfunction MClass() {\n    \"use strict\";\n}\nMClass.prototype.calc = function (a4, b4) {\n    \"use strict\";\n    return a4 + b4;\n};\n\nvar ins1 = new MClass();\nins1.calc(10, 10);\n\nvar Person = function (name) {\n    \"use strict\";\n    this.name = name;\n};\n\nPerson.prototype.getName = function () {\n    \"use strict\";\n    return this.name;\n};\n\nvar Customer = function (name) {\n    \"use strict\";\n    this.name = name;\n};\n\nCustomer.prototype = new Person();\n\nvar myCustomer = new Customer('Dream Inc.');\nmyCustomer.getName();\n\nCustomer.prototype.setAmountDue = function (amountDue) {\n    \"use strict\";\n    this.amountDue = amountDue;\n};\nCustomer.prototype.getAmountDue = function () {\n    \"use strict\";\n    return this.amountDue;\n};\n\nfunction testInnerFunc() {\n    \"use strict\";\n    var t = \"test\";\n    function innerFunc(arg) {\n        return {t: function () {return arg; }};\n    }\n    var t2 = innerFunc(\"test\").t().toLocaleLowerCase();\n    \n}\n\n/**\n * @param {boolean} a\n * @param {Date} b\n */\n\nfunction funTypeAn1(a, b) {\n    \"use strict\";\n    return {x: a, y: b};\n}\n\n/**\n * @param {function(): number} f\n */\nfunction funFuncArg(f) {\n    \"use strict\";\n    return f();\n}\n\nfunction testRef1() {\n    \"use strict\";\n    return 100;\n}\n\nfunFuncArg(testRef1); //also test return type\n    \n/**\n * @param {function(string,number): string} f\n */\nfunction funFunc2Arg(f) {\n    \"use strict\";\n    var s = \"test\";\n    return f(s, 10);\n}\n\nfunction testRef2(s, n) {\n    \"use strict\";\n    return s + n;\n}\n\nfunFunc2Arg(testRef2);\n\nvar funArr = [];\nfunArr.index1 = testRef1;\nfunArr.index2 = testRef2;\n\nvar _A1 = A1;\n\nvar s = \"\", // string type\n    help;   // unknown type\n\nfunction testNonAscii() {\n    \"use strict\";\n    var hope;  // unknown type\n    hope[\"frenchçProp\"] = \"\";\n    \n}\n\nrequire([\"MyModule\"], function (myModule) {\n    'use strict';\n    var x = myModule.c;\n});\n\n\n/**\n *  Test record type google annoations.\n *\n *  @param {{index: number, name: string}} t\n */\nfunction testRecordTypeAnnotation(t) {\n    'use strict';\n    \n}\n\n// More parameter hint testing\nfunction functionHintTesting() {\n    \"use strict\";\n\n    // function with record type argument\n    testRecordTypeAnnotation();\n    \n    // function with a function argument\n    arr.sort();\n\n    // function with array argument\n    arr.concat();\n\n    s.lastIndexOf(s, 5);\n\n}\n\n/**\n *  Test Array annotation\n * \n *  @param {Array.<string>} a\n */\nfunction testArrayAnnotation(a) {\n    \"use strict\";\n    \n}\n\ntestArrayAnnotation();\n\n/**\n *  Test multiple optional args\n *\n * @param {number=} a\n * @param {string=} b\n *\n */\nfunction testOptionalArgs(a, b) {\n    \"use strict\";\n    \n}\n\ntestOptionalArgs();\n\n/* Add large comment to make this test over 250 lines which will trigger\n *  partial updates to be used.\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n *\n * end of large comment\n */\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/basic-test-files/file2.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, rhino: true, nomen: true, indent: 4, maxerr: 50 */\n/*global crazyGlobal, anotherCrazyGlobal */\n\nvar D1 = { propD : 1 },\n    D2 = { propD : 2 };\n\nfunction funE(paramE1, paramE2) {\n    'use strict';\n    \n    var E1 = { propE : 1 },\n        E2 = { propE : 2 };\n\n    console.log(\"a very nice string\");\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/basic-test-files/file3.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, describe, it, xit, expect, beforeEach, afterEach, waitsFor, runs, $, brackets, waitsForDone */\n\nfunction funD_file3(a, b) {\n    'use strict';\n    var f = function () {return {x: a, y: b}; };\n    return f;\n}\nvar kf3 = funD_file3(10, 20);\nkf3();\n\nvar hope = {frenchçProp2: \"test\", frenchçProp1: \" new value\", frenchçfun:frenchçProp() };\nfunction frenchçProp(){\n};\n\nfunction frenchçProp(){\n}\nfrenchçProp();\n\nvar 測试 = \"test\";\n測试 = \"new value\";\n// 測 test code hint\nfunction fun測试(){\n}\nfun測试();  // test function type\n\nfunction nonAsciiTest() {\n    var hope;  // unknown type\n    hope[\"frenchçProp\"] = \"\";\n    hope.frenchçProp2 = \"test\";\n    hope.frenchçProp = \"frenchçProp\";\n    fun測试();\n    var month = getMonthName(5);\n    A1.propA = \"test\";\n}\n\nfunction frenchçProp(){};\nfrenchçProp();\n\nfunction UserException(message) {\n   this.message = message;\n   this.name = \"UserException\";\n}\n\nfunction getMonthName(mo) {\n   mo = mo-1; // Adjust month number for array index (1=Jan, 12=Dec)\n   var months = new Array(\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\",\n      \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\");\n   if (months[mo] !== undefined) {\n      return months[mo];\n   } else {\n      throw new UserException(\"InvalidMonthNo\"); // test exception\n   }\n}\n\nfunction callOtherMethods() {\n    testTryCatch();\n    \n}\nfunction testTryCatch() {\n    \"use strict\";\n    try {\n        var myMonth = 15; // 15 is out of bound to raise the exception      \n    } catch (e) {\n        myMonth = 12;\n        console.log(e.message + e.name); // test e, e.message, e.name\n    }\n    try {\n        var myMonth = 15; // 15 is out of bound to raise the exception\n    } catch (e2) {\n        myMonth = 12; // test local variable\n        console.log(e2.message + e2.name); // test e, e.message, e.name\n    }\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/basic-test-files/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Test file for codehints in .html file</title>\n  </head>\n  <body>\n    <script src=\"file1.js\"></script>\n    <script src=\"file2.js\"></script>\n    <script>\n        var x100 = \"hi\";\n    </script>\n      some stuff\n\n    <input type=\"button\">\n      \n    <div class=\"content\">\n    </div>\n    <script>\n        function foo(a){\n            var y = x100;\n            k = a; \n            funD(\"test\", 100);\n            funE(D1, A2.propA);\n            return \"hi\";\n        }\n        var k = 100;\n        \n    </script>      \n      <style>\n          .style:hover { color: rgba(153, 102, 51, 0.63); }\n      </style>\n    some other stuff\n      <div class = \"content\">\n      </div>\n    <script>\n        foo(10);\n        \n    </script>\n\n  </body>\n</html>"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/basic-test-files/test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <script src=\"../module-test-files/Car.js\"></script>\n    <script src=\"../module-test-files/shirt.js\"></script>\n    <script src=\"../file1.js\"></script>\n    <script src=\"../file3.js\"></script>\n    <!-- leave follow empty line for later file including -->\n    \n    \n    \n    \n    \n<script>\n    var txt=\"\";\n    fun測试();  \n    frenchçProp();\n    nonAsciiTest(); // in quick editor, test jump, function type, code hint list\n    myTest();\n    callOtherMethods();\n</script>\n<script>\n    function myTest(){\n        monthName = \"test\";\n        simple1();\n    }\n    function simple1(){\n    }\n    \n</script>\n    \n</head>\n\n<body>\n    <input type=\"button\" value=\"View message\" onclick=\"message()\">\n</body>\n\n</html>"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/Car.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function (require, exports, module) {\n    \"use strict\";\n    exports.name = \"Honda\";\n    exports.model = \"2013 MDX\";\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/china/Cup.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function (require, exports, module) {\n    \"use strict\";\n    \n    function Cup() {\n        this.empty = true;\n    }\n\n    Cup.prototype.fill = function () {\n        this.empty = false;\n    };\n\n    Cup.prototype.emptyIt = function () {\n    };\n\n    Cup.prototype.full = function () {\n    };\n\n    Cup.prototype.empty = function () {\n    };\n\n    exports.Cup = Cup;\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/china/cupFiller.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function (require, exports, module) {\n    \"use strict\";\n    \n    var Cup = require('china/Cup').Cup;\n    \n    var coffeeCup = new Cup(false);\n    coffeeCup.\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/credits.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function () {\n\t'use strict';\n\treturn {\n\t\tgetCredits: function () {\n\t\t\tvar credits = \"100\";\n\t\t\treturn credits;\n\t\t}\n    };\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/module_tests.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, node: true, nomen: true, indent: 4, maxerr: 50 */\n/*global brackets, define, require, $ */\ndefine(function (require, exports, module) {\n    'use strict';\n     \n    var moduleName = (function () {\n        // this becomes public due to the reference exposure in the return below\n        var addMessage = function (test) {\n            this.publicMethod1();   // a test here to check the method showing\n        };\n        \n        var name = \"new name\";\n    \n        // this is the \"revealed\" part of the module\n        return {\n            addMessage: addMessage,\n            name:       name\n        };\n    }());\n    moduleName.publicMethod1 = function () { // test for methods:name, addMessage, publicMethod1, priv\n    };\n    \n    // extending a new module\n    var extendedModule = (function (oldModule) {\n        var parent = oldModule;\n        \n        parent.privilegedMethod = function () {\n        };\n        \n        var privateMethod2 = function () {\n        // test parent. make sure all methods defined in moduleName showing up here\n        };\n        return {\n            newMethod : function () {\n               // should see methods for oldModule oldModule., parent.\n               // should see privateMethod2(\n            }\n        };\n    }(moduleName || {}));//Module object is the existing module to extend. \n    \n    // test here: check extendedModule    \n    \n    moduleName.addMessage(\"test\");\n    moduleName.name = \" new name\";\n    \n    //parent module\n    var SearchEngine = (function () {\n        //Private Method.\n        var luckyAlgo = function () {\n            //create one random number.\n            return Math.floor(Math.random() * 11);\n        };\n        //Returning the object\n        return {\n            //privileged method.\n            getYourLuckyNumber : function () {\n                //Has access to its private method because of closure.\n                return luckyAlgo();\n            }\n        };\n    }());//Self executing method.\n    // test SearchEngine.getYourLuckyNumber().toExponential();\n  \n    \n    SearchEngine.subSearch = (function () {\n       //Private variable.\n        var defaultColor = \"Orange\";\n        //private method.\n        var myColorAlgo = function (num) {\n            switch (num) {\n            case 1:\n                defaultColor = \"Green\";\n                break;\n            }\n        };\n        return {\n            getYourLuckyColor : function () {\n                //access to private variable because of closure.\n                myColorAlgo(SearchEngine.getYourLuckyNumber());\n                return defaultColor;\n            }\n        };\n    }());\n    \n    require([\"shirt\"], function (myShirt) {\n        // myShirt. test here        \n    });\n    var t2 = require(\"shirt\");\n    var size   = t2.size;\n    var color  = t2.color;\n    t2.material();\n    \n    var purchaseModule = require('purchase');\n    purchaseModule.purchaseProduct();\n    \n    var hondaCar = require('Car');\n    \n});"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/products.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function (products) {\n    'use strict';\n\treturn {\n\t\treserveProduct: function () {\n\t\t\tconsole.log(\"Function : reserveProduct\");\n\t\t\treturn true;\n\t\t}\n    };\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/purchase.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine([\"credits\", \"products\"], function (credits, products) {\n    'use strict';\n    return {\n        purchaseProduct: function () {\n            var credit = credits.getCredits();\n            if (credit > 0) {\n                products.reserveProduct();\n                return true;\n            }\n            return false;\n        }\n    };\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/module-test-files/shirt.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\ndefine(function () {\n    'use strict';\n    return {\n        color: \"black\",\n        size: 10,\n        material: function () {\n            return \"cotton\";\n        }\n    };\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/.jscodehints",
    "content": "{\n\"excluded-directories\" : [\"/ex[\\\\w]*ed/\"],\n\"excluded-files\" : [\"require.js\", \"jquery*.js\", \"less*.min.js\", \"ember*.js\", \"d2?.js\", \"d3*\"],\n\"max-file-count\": 100,\n\"max-file-size\": 524288\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/a/a.js",
    "content": "var app = app || {};\n\n(function () {\n\t'use strict';\n\n    app.a = 1;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/app.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n\t'use strict';\n\n    app.d = 8;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/b/b.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n\t'use strict';\n\n    app.b = 2;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/b/b1/b1.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n\t'use strict';\n\n    app.b1 = 21;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/c/c.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n\t'use strict';\n\n    app.c = 3;\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/d/d.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n\t'use strict';\n\n    app.d = 4;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/d/d2.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n    'use strict';\n\n    app.d2 = 42;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/d/d23.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n    'use strict';\n\n    app.d23 = 423;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/d/d3-excluded.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n    'use strict';\n\n    app.d3Excluded = 43;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/non-module-test-files/excluded/e.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global */\n\nvar app = app || {};\n\n(function () {\n    'use strict';\n\n    app.e = 5;\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/preference-test-files/defaults-test/.jscodehints",
    "content": "{\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/preference-test-files/negative-test/.jscodehints",
    "content": "{\n    \"excluded-directories\" : [],\n    \"excluded-files\" : [],\n    \"max-file-count\": -100,\n    \"max-file-size\": 0\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittest-files/preference-test-files/positive-test/.jscodehints",
    "content": "{\n    \"excluded-directories\" : [\"excluded-dir1\", \"/^excluded-dir2-[\\\\d]$/\"],\n    \"excluded-files\" : [\"file1?.js\", \"file2*.js\", \"file3.js\", \"/file4[x|y|z]?.js/\"],\n    \"max-file-count\": 512,\n    \"max-file-size\": 100000\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*global describe, it, xit, expect, beforeEach, afterEach, waitsFor, runs, waitsForDone, waitsForFail, beforeFirst, afterLast */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Commands             = brackets.getModule(\"command/Commands\"),\n        CommandManager       = brackets.getModule(\"command/CommandManager\"),\n        MainViewManager      = brackets.getModule(\"view/MainViewManager\"),\n        DocumentManager      = brackets.getModule(\"document/DocumentManager\"),\n        EditorManager        = brackets.getModule(\"editor/EditorManager\"),\n        FileSystem           = brackets.getModule(\"filesystem/FileSystem\"),\n        FileUtils            = brackets.getModule(\"file/FileUtils\"),\n        PreferencesManager   = brackets.getModule(\"preferences/PreferencesManager\"),\n        SpecRunnerUtils      = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        JSCodeHints          = require(\"main\"),\n        Preferences          = brackets.getModule(\"JSUtils/Preferences\"),\n        ScopeManager         = brackets.getModule(\"JSUtils/ScopeManager\"),\n        HintUtils            = brackets.getModule(\"JSUtils/HintUtils\"),\n        HintUtils2           = require(\"HintUtils2\"),\n        ParameterHintProvider = require(\"ParameterHintsProvider\").JSParameterHintsProvider,\n        phProvider            = new ParameterHintProvider();\n\n    var extensionPath   = FileUtils.getNativeModuleDirectoryPath(module),\n        testPath        = extensionPath + \"/unittest-files/basic-test-files/file1.js\",\n        testHtmlPath    = extensionPath + \"/unittest-files/basic-test-files/index.html\",\n        testDoc         = null,\n        testEditor,\n        preTestText;\n\n    CommandManager.register(\"test-file-open\", Commands.FILE_OPEN, function (fileInfo) {\n        // Register a command for FILE_OPEN, which the jump to def code will call\n        return DocumentManager.getDocumentForPath(fileInfo.fullPath).done(function (doc) {\n            MainViewManager._edit(MainViewManager.ACTIVE_PANE, doc);\n        });\n    });\n\n    describe(\"JavaScript Code Hinting\", function () {\n\n        // Helper function for testing cursor position\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n\n        /*\n         * Ask provider for hints at current cursor position; expect it to\n         * return some\n         *\n         * @param {Object} provider - a CodeHintProvider object\n         * @param {string} key - the charCode of a key press that triggers the\n         *      CodeHint provider\n         * @return {boolean} - whether the provider has hints in the context of\n         *      the test editor\n         */\n        function expectHints(provider, key) {\n            if (key === undefined) {\n                key = null;\n            }\n\n            expect(provider.hasHints(testEditor, key)).toBe(true);\n            return provider.getHints(null);\n        }\n\n        /*\n         * Ask provider for hints at current cursor position; expect it NOT to\n         * return any\n         *\n         * @param {Object} provider - a CodeHintProvider object\n         * @param {string} key - the charCode of a key press that triggers the\n         *      CodeHint provider\n         */\n        function expectNoHints(provider, key) {\n\n            if (key === undefined) {\n                key = null;\n            }\n\n            expect(provider.hasHints(testEditor, key)).toBe(false);\n        }\n\n        /*\n         * Return the index at which hint occurs in hintList\n         *\n         * @param {Array.<Object>} hintList - the list of hints\n         * @param {string} hint - the hint to search for\n         * @return {number} - the index into hintList at which the hint occurs,\n         * or -1 if it does not\n         */\n        function _indexOf(hintList, hint) {\n            var index = -1,\n                counter = 0;\n\n            for (counter; counter < hintList.length; counter++) {\n                if (hintList[counter].data(\"token\").value === hint) {\n                    index = counter;\n                    break;\n                }\n            }\n            return index;\n        }\n\n        /*\n         * Wait for a hint response object to resolve, then apply a callback\n         * to the result\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Function} callback - the callback to apply to the resolved\n         *      hint response object\n         */\n        function _waitForHints(hintObj, callback) {\n            var complete = false,\n                hintList = null;\n\n            if (hintObj.hasOwnProperty(\"hints\")) {\n                complete = true;\n                hintList = hintObj.hints;\n            } else {\n                hintObj.done(function (obj) {\n                    complete = true;\n                    hintList = obj.hints;\n                });\n            }\n\n            waitsFor(function () {\n                return complete;\n            }, \"Expected hints did not resolve\", 3000);\n\n            runs(function () { callback(hintList); });\n        }\n\n        /*\n         * Test if hints should be closed or not closed at a given position.\n         *\n         * @param {Object} provider - a CodeHintProvider object\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {line: number, ch: number} newPos - new position to move to\n         * after hints are received.\n         * @param {boolean} expectedValue - true if hints should close,\n         * false otherwise.\n         */\n        function expectCloseHints(provider, hintObj, newPos, expectedValue) {\n            _waitForHints(hintObj, function (hintList) {\n                testEditor.setCursorPos(newPos);\n                expect(provider.shouldCloseHints(JSCodeHints.getSession())).toBe(expectedValue);\n            });\n        }\n\n        /*\n         * Expect a given list of hints to be absent from a given hint\n         * response object\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Array.<string>} absentHints - a list of hints that should not\n         *      be present in the hint response\n         */\n        function hintsAbsent(hintObj, absentHints) {\n            _waitForHints(hintObj, function (hintList) {\n                expect(hintList).toBeTruthy();\n                absentHints.forEach(function (absentHint) {\n                    expect(_indexOf(hintList, absentHint)).toBe(-1);\n                });\n            });\n        }\n\n        /*\n         * Expect a given list of hints to be present in a given hint\n         * response object\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Array.<string>} expectedHints - a list of hints that should be\n         *      present in the hint response\n         */\n        function hintsPresent(hintObj, expectedHints) {\n            _waitForHints(hintObj, function (hintList) {\n                expect(hintList).toBeTruthy();\n                expectedHints.forEach(function (expectedHint) {\n                    expect(_indexOf(hintList, expectedHint)).not.toBe(-1);\n                });\n            });\n        }\n\n        /*\n         * Expect a given list of hints to be present in the given order in a\n         * given hint response object\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Array.<string>} expectedHints - a list of hints that should be\n         *      present in the given order in the hint response\n         */\n        function hintsPresentOrdered(hintObj, expectedHints) {\n            var prevIndex = -1,\n                currIndex;\n\n            _waitForHints(hintObj, function (hintList) {\n                expect(hintList).toBeTruthy();\n                expectedHints.forEach(function (expectedHint) {\n                    currIndex = _indexOf(hintList, expectedHint);\n                    expect(currIndex).toBeGreaterThan(prevIndex);\n                    prevIndex = currIndex;\n                });\n            });\n        }\n\n        /*\n         * Expect a given list of hints to be present in a given hint\n         * response object, and no more.\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Array.<string>} expectedHints - a list of hints that should be\n         *      present in the hint response, and no more.\n         */\n        function hintsPresentExact(hintObj, expectedHints) {\n            _waitForHints(hintObj, function (hintList) {\n                expect(hintList).toBeTruthy();\n                expect(hintList.length).toBe(expectedHints.length);\n                expectedHints.forEach(function (expectedHint, index) {\n                    expect(hintList[index].data(\"token\").value).toBe(expectedHint);\n                });\n            });\n        }\n\n        /**\n         * Find the index of a string in a list of hints.\n         * @param {Array} hintList - the list of hints\n         * @param {string} hintSelection - the string represenation of the hint\n         *  to find the index of\n         * @return {number} the index of the hint corresponding to the hintSelection\n         */\n        function findHint(hintList, hintSelection) {\n            var i, l;\n            for (i = 0, l = hintList.length; i < l; ++i) {\n                var current = hintList[i].data(\"token\");\n                if (hintSelection === current.value) {\n                    return i;\n                }\n            }\n            return -1;\n        }\n        /*\n         * Simulation of selection of a particular hint in a hint list.\n         * Presumably results in side effects in the hint provider's\n         * current editor context.\n         *\n         * @param {Object} provider - a CodeHint provider object\n         * @param {Object} hintObj - a hint response object from that provider,\n         *      possibly deferred\n         * @param {string} hintSelection - the hint to select\n         */\n        function selectHint(provider, hintObj, hintSelection) {\n            expectHints(provider);\n            _waitForHints(hintObj, function (hintList) {\n                expect(hintList).toBeTruthy();\n                var index = findHint(hintList, hintSelection);\n                expect(hintList[index].data(\"token\")).toBeTruthy();\n                expect(provider.insertHint(hintList[index])).toBe(false);\n            });\n        }\n\n        /**\n         * Wait for the editor to change positions, such as after a jump to\n         * definition has been triggered.  Will timeout after 3 seconds\n         *\n         * @param {{line:number, ch:number}} oldLocation - the original line/col\n         * @param {Function} callback - the callback to apply once the editor has changed position\n         */\n        function _waitForJump(jumpPromise, callback) {\n            var cursor = null,\n                complete = false;\n\n            jumpPromise.done(function () {\n                complete = true;\n            });\n\n            waitsFor(function () {\n                var activeEditor = EditorManager.getActiveEditor();\n                cursor = activeEditor.getCursorPos();\n                return complete;\n            }, \"Expected jump did not occur\", 3000);\n\n            runs(function () { callback(cursor); });\n        }\n\n        /**\n         * Trigger a jump to definition, and verify that the editor jumped to\n         * the expected location. The new location is the variable definition\n         * or function definition of the variable or function at the current\n         * cursor location. Jumping to the new location will cause a new editor\n         * to be opened or open an existing editor.\n         *\n         * @param {{line:number, ch:number, file:string}} expectedLocation - the\n         *  line, column, and optionally the new file the editor should jump to.  If the\n         *  editor is expected to stay in the same file, then file may be omitted.\n         */\n        function editorJumped(expectedLocation) {\n            var jumpPromise = JSCodeHints.handleJumpToDefinition();\n\n\n            _waitForJump(jumpPromise, function (newCursor) {\n                expect(newCursor.line).toBe(expectedLocation.line);\n                expect(newCursor.ch).toBe(expectedLocation.ch);\n                if (expectedLocation.file) {\n                    var activeEditor = EditorManager.getActiveEditor();\n                    expect(activeEditor.document.file.name).toBe(expectedLocation.file);\n                }\n            });\n\n        }\n\n        /**\n         * Verify there is no parameter hint at the current cursor.\n         */\n        function expectNoParameterHint() {\n            var requestStatus = undefined;\n            runs(function () {\n                var request = phProvider._getParameterHint();\n                request.fail(function (status) {\n                    requestStatus = status;\n                });\n\n                waitsForFail(request, \"ParameterHints\");\n            });\n         \n            runs(function () {\n                expect(requestStatus).toBe(null);\n            });  \n        }\n\n        /**\n         * Verify the parameter hint is not visible.\n         */\n        function expectParameterHintClosed() {\n            expect(phProvider.isHintDisplayed()).toBe(false);\n        }\n\n        /**\n         * Show a function hint based on the code at the cursor. Verify the\n         * hint matches the passed in value.\n         *\n         * @param {Array<{name: string, type: string, isOptional: boolean}>}\n         * expectedParams - array of records, where each element of the array\n         * describes a function parameter. If null, then no hint is expected.\n         * @param {number} expectedParameter - the parameter at cursor.\n         */\n        function expectParameterHint(expectedParams, expectedParameter) {\n            var requestHints = undefined,\n                request = null;\n            \n            function expectHint(hint) {\n                var params = hint.parameters,\n                    n = params.length,\n                    i;\n\n                // compare params to expected params\n                expect(params.length).toBe(expectedParams.length);\n                expect(hint.currentIndex).toBe(expectedParameter);\n\n                for (i = 0; i < n; i++) {\n\n                    expect(params[i].name).toBe(expectedParams[i].name);\n                    expect(params[i].type).toBe(expectedParams[i].type);\n                    if (params[i].isOptional) {\n                        expect(expectedParams[i].isOptional).toBeTruthy();\n                    } else {\n                        expect(expectedParams[i].isOptional).toBeFalsy();\n                    }\n                }\n\n            }\n            \n            runs(function () {\n                request = phProvider._getParameterHint();\n                \n                if (expectedParams === null) {\n                    request.fail(function (result) {\n                        requestHints = result;\n                    });\n\n                    waitsForFail(request, \"ParameterHints\");\n                } else {\n                    request.done(function (result) {\n                        requestHints = result;\n                    });\n\n                    waitsForDone(request, \"ParameterHints\");\n                }\n            });\n\n            if (expectedParams === null) {\n                expect(requestHints).toBe(null);\n            } else {\n                expectHint(requestHints);\n            }\n        }\n\n        function setupTest(path, primePump) { // FIXME: primePump argument ignored even though used below\n            DocumentManager.getDocumentForPath(path).done(function (doc) {\n                testDoc = doc;\n            });\n\n            waitsFor(function () {\n                return testDoc !== null;\n            }, \"Unable to open test document\", 10000);\n\n            // create Editor instance (containing a CodeMirror instance)\n            runs(function () {\n                testEditor = SpecRunnerUtils.createMockEditorForDocument(testDoc);\n                preTestText = testDoc.getText();\n                waitsForDone(ScopeManager._readyPromise());\n                waitsForDone(ScopeManager._maybeReset(JSCodeHints.getSession(), testDoc, true));\n            });\n        }\n\n        function tearDownTest() {\n            // Restore the pre-test version of the text here because the hinter\n            // will update the contents of the previous document in tern.\n            testDoc.setText(preTestText);\n\n            // The following call ensures that the document is reloaded\n            // from disk before each test\n            MainViewManager._closeAll(MainViewManager.ALL_PANES);\n            SpecRunnerUtils.destroyMockEditor(testDoc);\n            testEditor = null;\n            testDoc = null;\n        }\n\n        describe(\"JavaScript Code Hinting Basic\", function () {\n            beforeFirst(function () {\n                brackets._configureJSCodeHints({\n                    noReset: true\n                });\n            });\n\n            afterLast(function () {\n                brackets._configureJSCodeHints({\n                    noReset: false\n                });\n            });\n\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should not list hints in string literal\", function () {\n                testEditor.setCursorPos({ line: 20, ch: 22 });\n                expectNoHints(JSCodeHints.jsHintProvider);\n            });\n\n            it(\"should list declared variable and function names in outer scope\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"A2\", \"A3\", \"funB\", \"A1\"]);\n            });\n\n            it(\"should filter hints by query\", function () {\n                testEditor.setCursorPos({ line: 5, ch: 10 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"A1\", \"A2\", \"A3\"]);\n                hintsAbsent(hintObj, [\"funB\"]);\n            });\n\n            it(\"should list keywords\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"break\", \"case\", \"catch\"]);\n            });\n\n            xit(\"should list explicitly defined globals from JSLint annotations\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"brackets\", \"$\"]);\n            });\n\n            xit(\"should list implicitly defined globals from JSLint annotations\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"alert\", \"console\", \"confirm\", \"navigator\", \"window\", \"frames\"]);\n            });\n\n            it(\"should NOT list implicitly defined globals from missing JSLint annotations\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"ActiveXObject\", \"CScript\", \"VBArray\"]);\n            });\n\n            it(\"should NOT list explicitly defined globals from JSLint annotations in other files\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"crazyGlobal\", \"anotherCrazyGlobal\"]);\n            });\n\n            it(\"should NOT list implicitly defined globals from JSLint annotations in other files\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"spawn\", \"version\", \"toint32\"]);\n            });\n\n            it(\"should list literal constants\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"null\", \"undefined\", \"true\", \"false\"]);\n            });\n\n            it(\"should NOT list variables, function names and parameter names out of scope\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"paramB2\", \"paramB1\"]);\n            });\n\n            it(\"should NOT list variables, function names and parameter names in other files\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"E1\", \"E2\"]);\n            });\n\n            it(\"should NOT list property names on value lookups\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"propA\", \"propB\", \"propC\"]);\n            });\n\n            it(\"should list declared variable, function and parameter names in inner scope\", function () {\n                testEditor.setCursorPos({ line: 12, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"B1\", \"B2\", \"funC\", \"paramB1\", \"paramB2\", \"funB\", \"A1\", \"A2\", \"A3\"]);\n            });\n\n            xit(\"should list string literals that occur in the file\", function () {\n                testEditor.setCursorPos({ line: 12, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"use strict\"]);\n            });\n\n            it(\"should NOT list string literals from other files\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"a very nice string\"]);\n            });\n\n            it(\"should list property names that have been declared in the file\", function () {\n                testEditor.setCursorPos({ line: 17, ch: 11 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"propB\"]);\n            });\n\n            it(\"should list identifier names that occur in other files\", function () {\n                testEditor.setCursorPos({ line: 16, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"D1\", \"D2\"]);\n            });\n\n            it(\"should NOT list variable, parameter or function names on property lookups\", function () {\n                testEditor.setCursorPos({ line: 17, ch: 11 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"A1\", \"A2\", \"funB\", \"paramB1\", \"paramB2\", \"B1\", \"B2\", \"funC\", \"paramC1\", \"paramC2\"]);\n            });\n\n            it(\"should NOT list keywords on property lookups\", function () {\n                testEditor.setCursorPos({ line: 17, ch: 11 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsAbsent(hintObj, [\"case\", \"function\", \"var\"]);\n            });\n\n            it(\"should close hints when move over '.' \", function () {\n                testEditor.setCursorPos({ line: 17, ch: 11 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 10 }, true);\n            });\n\n            it(\"should close hints only when move off the end of a property \", function () {\n                testEditor.setCursorPos({ line: 17, ch: 11 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 12 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 13 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 14 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 15 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 16 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 17 }, true);\n            });\n\n            it(\"should close hints only when move off the beginning of an identifier \", function () {\n                testEditor.setCursorPos({ line: 17, ch: 10 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 9 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 8 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 17, ch: 7 }, true);\n            });\n\n            it(\"should close hints only when move off the beginning of a keyword \", function () {\n                testEditor.setCursorPos({ line: 24, ch: 7 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"var\"]);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 24, ch: 6 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 24, ch: 5 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 24, ch: 4 }, false);\n                expectCloseHints(JSCodeHints.jsHintProvider, hintObj,\n                    { line: 24, ch: 3 }, true);\n            });\n\n            it(\"should NOT list implicit hints on left-brace\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                expectNoHints(JSCodeHints.jsHintProvider, \"{\");\n            });\n\n            it(\"should list explicit hints for variable and function names\", function () {\n                testEditor.setCursorPos({ line: 6, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider, null);\n                hintsPresent(hintObj, [\"A2\", \"A3\", \"funB\", \"A1\"]);\n            });\n\n            it(\"should list implicit hints when typing property lookups\", function () {\n                testEditor.setCursorPos({ line: 17, ch: 10 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider, \".\");\n                hintsPresent(hintObj, [\"B1\", \"paramB1\"]);\n            });\n\n            it(\"should give priority to identifier names associated with the current context\", function () {\n                testEditor.setCursorPos({ line: 16, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresentOrdered(hintObj, [\"C1\", \"B1\"]);\n                hintsPresentOrdered(hintObj, [\"C2\", \"B2\"]);\n            });\n\n            it(\"should give priority to property names associated with the current context from other files\", function () {\n                testEditor.setCursorPos({ line: 16, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresentOrdered(hintObj, [\"C1\", \"D1\"]);\n                hintsPresentOrdered(hintObj, [\"B1\", \"D1\"]);\n                hintsPresentOrdered(hintObj, [\"A1\", \"D1\"]);\n                hintsPresentOrdered(hintObj, [\"funB\", \"funE\"]);\n            });\n\n            xit(\"should choose the correct delimiter for string literal hints with no query\", function () {\n                var start = { line: 18, ch: 0 },\n                    end   = { line: 18, ch: 18 };\n\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, 13); // hint 13 is \"hello\\\\\\\"world!\"\n                runs(function () {\n                    expect(testEditor.getCursorPos()).toEqual(end);\n                    expect(testDoc.getRange(start, end)).toEqual('\"hello\\\\\\\\\\\\\" world!\"');\n                });\n            });\n\n            it(\"should insert value hints with no current query\", function () {\n                var start = { line: 6, ch: 0 },\n                    end   = { line: 6, ch: 2 };\n\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"A2\");\n                runs(function () {\n                    //expect(testEditor.getCursorPos()).toEqual(end);\n                    expect(testDoc.getRange(start, end)).toEqual(\"A2\");\n                });\n            });\n\n            it(\"should insert value hints replacing the current query\", function () {\n                var start   = { line: 5, ch: 10 }, // A3 = A<here>2;\n                    before  = { line: 5, ch: 9 },\n                    end     = { line: 5, ch: 11 };\n\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresent(hintObj, [\"A1\", \"A2\", \"A3\"]);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"A1\");\n                runs(function () {\n                    //expect(testEditor.getCursorPos()).toEqual(end);\n                    expect(testDoc.getRange(before, end)).toEqual(\"A1\");\n                });\n            });\n\n            it(\"should insert property hints with no current query\", function () {\n                var start   = { line: 6, ch: 0 },\n                    middle  = { line: 6, ch: 3 },\n                    end     = { line: 6, ch: 8 };\n\n                testDoc.replaceRange(\"A1.\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"propA\");\n\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, end)).toEqual(\"A1.propA\");\n                    expect(testDoc.getLine(end.line).length).toEqual(8);\n                });\n            });\n\n            it(\"should insert, not replace, property hints with no current query\", function () {\n                var start   = { line: 6, ch: 0 },\n                    middle  = { line: 6, ch: 3 },\n                    end     = { line: 6, ch: 8 },\n                    endplus = { line: 6, ch: 12 };\n\n                testDoc.replaceRange(\"A1.prop\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"propA\");\n\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, endplus)).toEqual(\"A1.propAprop\");\n                    expect(testDoc.getLine(end.line).length).toEqual(12);\n                });\n            });\n\n            it(\"should insert, not replace, property hints with a partial current query\", function () {\n                var start   = { line: 6, ch: 0 },\n                    middle  = { line: 6, ch: 6 },\n                    end     = { line: 6, ch: 8 };\n\n                testDoc.replaceRange(\"A1.pro\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"propA\");\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, end)).toEqual(\"A1.propA\");\n                    expect(testDoc.getLine(end.line).length).toEqual(8);\n                });\n            });\n\n            it(\"should replace property hints replacing a partial current query\", function () {\n                var start   = { line: 6, ch: 0 },\n                    middle  = { line: 6, ch: 6 },\n                    end     = { line: 6, ch: 8 },\n                    endplus = { line: 6, ch: 10 };\n\n                testDoc.replaceRange(\"A1.propB\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"propA\");\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, endplus)).toEqual(\"A1.propApB\");\n                    expect(testDoc.getLine(end.line).length).toEqual(10);\n                });\n            });\n\n            it(\"should replace property hints but not following delimiters\", function () {\n                var start   = { line: 6, ch: 0 },\n                    middle  = { line: 6, ch: 4 },\n                    end     = { line: 6, ch: 9 },\n                    endplus = { line: 6, ch: 14 };\n\n                testDoc.replaceRange(\"(A1.prop)\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"propA\");\n\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, endplus)).toEqual(\"(A1.propAprop)\");\n                    expect(testDoc.getLine(endplus.line).length).toEqual(14);\n                });\n            });\n\n            it(\"should list hints for string, as string assigned to 's', 's' assigned to 'r' and 'r' assigned to 't'\", function () {\n                var start = { line: 26, ch: 0 },\n                    middle = { line: 26, ch: 6 };\n\n                // pad spaces here as tern has issue,without space, no code hint\n                testDoc.replaceRange(\"    t.\", start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentOrdered(hintObj, [\"charAt\", \"charCodeAt\", \"concat\", \"indexOf\"]);\n                });\n            });\n\n            it(\"should list function type\", function () {\n                var start = { line: 37, ch: 0 },\n                    middle = { line: 37, ch: 5 };\n\n                testDoc.replaceRange(\"funD(\", start, start);\n                testEditor.setCursorPos(middle);\n                runs(function () {\n                    expectParameterHint([{name: \"a\", type: \"String\"},\n                        {name: \"b\", type: \"Number\"}], 0);\n                });\n            });\n\n            it(\"should list exports from a requirejs module\", function () {\n                var start = { line: 40, ch: 21 };\n\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentExact(hintObj, [\"a\", \"b\", \"c\", \"j\"]);\n                });\n            });\n\n            it(\"should list later defined property names\", function () {\n                var start = { line: 17, ch: 11 };\n\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentExact(hintObj, [\"foo\", \"propB\"]);\n                });\n            });\n\n            it(\"should list matching property names\", function () {\n                var cursor1 = { line: 12, ch: 0 },\n                    cursor2 = { line: 12, ch: 6 };\n\n                testDoc.replaceRange(\"paramB\", cursor1, cursor1);\n                testEditor.setCursorPos(cursor2);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentExact(hintObj, [\"paramB1\", \"paramB2\"]);\n                });\n            });\n\n            it(\"should take anotation parameter type:String\", function () {\n                var start = { line: 37, ch: 21 };\n\n                testDoc.replaceRange(\"var k= funD(10,11).x.\", start, start);\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentOrdered(hintObj, [\"charAt\", \"charCodeAt\", \"concat\", \"indexOf\"]);\n                });\n            });\n\n            it(\"should take anotation parameter type:Number\", function () {\n                var start = { line: 37, ch: 21 };\n\n                testDoc.replaceRange(\"var k= funD(10,11).y.\", start, start);\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentOrdered(hintObj, [\"toExponential\", \"toFixed\", \"toString\"]);\n                });\n            });\n\n            it(\"should add new method on String .prototype\", function () {\n                var start = { line: 37, ch: 0 };\n                var testPos = { line: 40, ch: 12 };\n                testDoc.replaceRange(\"String.prototype.times = function (count) {\\n\" + \"\\treturn count < 1 ? '' : new Array[count + 1].join(this);\\n};\\n\\\"hello\\\".tim\", start, start);\n                testEditor.setCursorPos(testPos);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentOrdered(hintObj, [\"times\", \"trim\"]);\n                });\n            });\n\n            it(\"should list function defined from .prototype\", function () {\n                var start = { line: 59, ch: 5 };\n\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentExact(hintObj, [\"calc\"]);\n                });\n            });\n\n            it(\"should list function type defined from .prototype\", function () {\n                var start = { line: 59, ch: 10 };\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    expectParameterHint([{name: \"a4\", type: \"Number\"}, {name: \"b4\", type: \"Number\"}], 0);\n                });\n            });\n\n            it(\"should list function inherited from super class\", function () {\n                var start = { line: 79, ch: 11 };\n                testEditor.setCursorPos(start);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentExact(hintObj, [\"amountDue\", \"getAmountDue\", \"getName\", \"name\", \"setAmountDue\"]);\n                });\n            });\n\n            it(\"should show argument from from .prototype.Method\", function () {\n                var start = { line: 80, ch: 0 },\n                    testPos = { line: 80, ch: 24 };\n\n                testDoc.replaceRange(\"myCustomer.setAmountDue(\", start);\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"amountDue\", type: \"Object\"}], 0);\n                });\n            });\n\n            it(\"should show inner function type\", function () {\n                var testPos = { line: 96, ch: 23 };\n\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"arg\", type: \"String\"}], 0);\n                });\n            });\n\n            it(\"should show type for inner function returned function\", function () {\n                var testPos = { line: 96, ch: 33 };\n\n                testEditor.setCursorPos(testPos);\n                expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    expectParameterHint([], 0);\n                });\n\n            });\n\n            // parameter type anotation tests, due to another bug #3670: first argument has ?\n            xit(\"should list parameter Date,boolean type\", function () {\n                var start = { line: 109, ch: 0 },\n                    testPos = { line: 109, ch: 11 };\n\n                testDoc.replaceRange(\"funTypeAn1(\", start);\n                testEditor.setCursorPos(testPos);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentExact(hintObj, [\"funTypeAn1((a: bool, b: Date) -> {x, y}\"]);\n                });\n            });\n\n            // parameter type anotation tests, due to another bug #3670: first argument has ?\n            xit(\"should list parameter function type and best guess for its argument/return types\", function () {\n                var testPos = { line: 123, ch: 11 };\n\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"f\", type: \"function(): number\"}], 0);\n                });\n            });\n\n            // parameter type annotation tests\n            it(\"should list parameter function type and best guess for function call/return types\", function () {\n                var testPos = { line: 139, ch: 12 };\n\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"f\", type: \"function(String, Number):String\"}], 0);\n                });\n            });\n\n            it(\"should list array containing functions\", function () {\n                var testPos = { line: 142, ch: 7 };\n\n                testEditor.setCursorPos(testPos);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresent(hintObj, [\"index1\", \"index2\"]);\n                });\n            });\n\n            it(\"should list function reference\", function () {\n                var start = { line: 144, ch: 0 },\n                    testPos = { line: 144, ch: 14 };\n\n                testDoc.replaceRange(\"funArr.index1(\", start);\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([], 0);\n                });\n            });\n\n            it(\"should insert hint as [\\\"my-key\\\"] since 'my-key' is not a valid property name\", function () {\n                var start = { line: 49, ch: 0 },\n                    middle = { line: 49, ch: 5 },\n                    end = { line: 49, ch: 13 };\n\n                testDoc.replaceRange(\"arr.m\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"my-key\");\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, end)).toEqual(\"arr[\\\"my-key\\\"]\");\n                    expect(testDoc.getLine(end.line).length).toEqual(13);\n                });\n            });\n\n            it(\"should insert hint as [\\\"my-key\\\"] make sure this works if nothing is typed after the '.'\", function () {\n                var start = { line: 49, ch: 0 },\n                    middle = { line: 49, ch: 4 },\n                    end = { line: 49, ch: 13 };\n\n                testDoc.replaceRange(\"arr.\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"my-key\");\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, end)).toEqual(\"arr[\\\"my-key\\\"]\");\n                    expect(testDoc.getLine(end.line).length).toEqual(13);\n                });\n            });\n\n            it(\"should insert hint as '.for' since keywords can be used as property names\", function () {\n                var start = { line: 49, ch: 0 },\n                    middle = { line: 49, ch: 5 },\n                    end = { line: 49, ch: 7 };\n\n                testDoc.replaceRange(\"arr.f\", start, start);\n                testEditor.setCursorPos(middle);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"for\");\n                runs(function () {\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(end));\n                    expect(testDoc.getRange(start, end)).toEqual(\"arr.for\");\n                    expect(testDoc.getLine(end.line).length).toEqual(7);\n                });\n            });\n\n            it(\"should jump to function\", function () {\n                var start = { line: 43, ch: 0 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 7, ch: 13});\n                });\n            });\n\n            it(\"should jump to var\", function () {\n                var start = { line: 44, ch: 10 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 3, ch: 6});\n                });\n            });\n\n            it(\"should jump to closure, early defined var\", function () {\n                var start = { line: 17, ch: 9 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 10, ch: 10});\n                });\n            });\n\n            it(\"should jump to the definition in new module file\", function () {\n                var start = { line: 40, ch: 22 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 4, ch: 13, file: \"MyModule.js\"}); //jump to another file\n                });\n            });\n\n            it(\"should jump to the method definition in .prototype\", function () {\n                var start = { line: 59, ch: 8 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 53, ch: 21}); //jump to prototype.calc\n                });\n            });\n\n            it(\"should jump to parameter passed in the method\", function () {\n                var start = { line: 63, ch: 20 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 61, ch: 27});\n                });\n            });\n\n            it(\"should jump to parameter passed in anonymous method\", function () {\n                var start = { line: 83, ch: 25 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 81, ch: 53});\n                });\n            });\n\n            it(\"should jump to inner method\", function () {\n                var start = { line: 96, ch: 32 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 94, ch: 17});\n                });\n            });\n\n            it(\"should jump to the actual function definition, and not the exports line\", function () {\n                var start = { line: 159, ch: 22 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 11, ch: 14, file: \"MyModule.js\"}); //jump to another file\n                });\n            });\n\n            it(\"should not hint function, variable, or param decls\", function () {\n                var func = { line: 7, ch: 12 },\n                    param = { line: 7, ch: 18 },\n                    variable = { line: 10, ch: 10 };\n\n                runs(function () {\n                    testEditor.setCursorPos(func);\n                    expectNoParameterHint();\n                    testEditor.setCursorPos(param);\n                    expectNoHints(JSCodeHints.jsHintProvider);\n                    testEditor.setCursorPos(variable);\n                    expectNoHints(JSCodeHints.jsHintProvider);\n                });\n            });\n\n            it(\"should sort underscore names to the bottom\", function () {\n                testEditor.setCursorPos({ line: 146, ch: 0 });\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                hintsPresentOrdered(hintObj, [\"A1\", \"A2\", \"A3\", \"funB\", \"_A1\"]);\n            });\n\n            it(\"should list all properties for unknown type\", function () {\n                var start = { line: 149, ch: 0 },\n                    end   = { line: 149, ch: 5 };\n\n                testDoc.replaceRange(\"help.\", start, start);\n                testEditor.setCursorPos(end);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                // check we have a properties from \"Function\", \"String\", and \"Array\"\n                hintsPresentOrdered(hintObj, [\"apply\", \"charCodeAt\", \"concat\"]);\n            });\n\n            it(\"should switch to guesses after typing a query that does not match any hints\", function () {\n                var start = { line: 150, ch: 0 },\n                    end   = { line: 150, ch: 5 };\n\n                testDoc.replaceRange(\"s.shift\", start, start);\n                testEditor.setCursorPos(end);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                // check we have a properties that start with \"shift\"\n                hintsPresentOrdered(hintObj, [\"shift\", \"shiftKey\"]);\n            });\n\n            it(\"should handle valid non-ascii characters in a property name\", function () {\n                var start = { line: 153, ch: 0 },\n                    end   = { line: 153, ch: 13 };\n\n                testDoc.replaceRange(\"hope.frenchçP\", start, start);\n                testEditor.setCursorPos(end);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                // check we have a properties that start with \"shift\"\n                hintsPresentOrdered(hintObj, [\"frenchçProp\"]);\n            });\n\n            it(\"should show guessed argument type from current passing parameter\", function () {\n                var start = { line: 80, ch: 0 },\n                    testPos = { line: 80, ch: 24 };\n                testDoc.replaceRange(\"myCustomer.setAmountDue(10)\", start);\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"amountDue\", type: \"Number\"}], 0);\n                });\n            });\n\n            it(\"should list parameter hint for record type annotation\", function () {\n                var testPos = { line: 178, ch: 25 };\n\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"t\", type: \"{index: Number, name: String}\"}], -1);\n                });\n            });\n\n            it(\"should list parameter hint for optional parameters\", function () {\n                var testPos = { line: 214, ch: 17 };\n\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"a\", type: \"Number\", isOptional: true}, {name: \"b\", type: \"String\", isOptional: true}], 0);\n                });\n            });\n\n            it(\"should list parameter hint for a function parameter\", function () {\n                var testPos = { line: 181, ch: 12 };\n\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"compare\",\n                        type: \"function(Object, Object):Number\",\n                        isOptional: true}], -1);\n                });\n            });\n\n            it(\"should list parameter hint for an array parameter\", function () {\n                var testPos = { line: 184, ch: 12 };\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"other\", type: \"Array.<Object>\"}], -1);\n                });\n            });\n\n            it(\"should list parameter hint for a source array annotation\", function () {\n                var testPos = { line: 200, ch: 20 };\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"a\", type: \"Array.<String>\"}], 0);\n                });\n            });\n\n            it(\"should close parameter hint when move off function\", function () {\n                var testPos = { line: 184, ch: 12 },\n                    endPos  = { line: 184, ch: 19 };\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"other\", type: \"Array.<Object>\"}], -1);\n                });\n\n                runs(function () {\n                    testEditor.setCursorPos(endPos);\n                    expectParameterHintClosed();\n                });\n            });\n\n            it(\"should close parameter hint when move off function to another function\", function () {\n                var testPos = { line: 184, ch: 12 },\n                    newPos  = { line: 181, ch: 12 };\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"other\", type: \"Array.<Object>\"}], -1);\n                });\n\n                runs(function () {\n                    testEditor.setCursorPos(newPos);\n                    expectParameterHintClosed();\n                });\n            });\n\n            it(\"should update current parameter as the cursor moves\", function () {\n                var testPos = { line: 186, ch: 19 },\n                    newPos  = { line: 186, ch: 20 };\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    expectParameterHint([{name: \"char\", type: \"String\"},\n                        {name: \"from\", type: \"Number\", isOptional: true}], 0);\n                });\n\n                runs(function () {\n                    testEditor.setCursorPos(newPos);\n                    expectParameterHint([{name: \"char\", type: \"String\"},\n                        {name: \"from\", type: \"Number\", isOptional: true}], 1);\n                });\n            });\n\n            // Test `jscodehints.noHintsOnDot` preference\n            it(\"should consider dot a hintable key based on preference\", function () {\n                var noHintsOnDot = PreferencesManager.get(\"jscodehints.noHintsOnDot\");\n\n                testEditor.setCursorPos({ line: 44, ch: 10 });\n\n                // Default is falsey\n                expect(noHintsOnDot).toBeFalsy();\n\n                // Should get hints after dot\n                expectHints(JSCodeHints.jsHintProvider, \".\");\n\n                // Set preference to true\n                PreferencesManager.set(\"jscodehints.noHintsOnDot\", true);\n\n                // Should no longer get hints after dot\n                expectNoHints(JSCodeHints.jsHintProvider, \".\");\n\n                // Set preference back to original value (converted to boolean)\n                PreferencesManager.set(\"jscodehints.noHintsOnDot\", !!noHintsOnDot);\n            });\n        });\n\n        describe(\"JavaScript Code Hinting in a HTML file\", function () {\n\n            beforeEach(function () {\n                setupTest(testHtmlPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"basic codehints in html file\", function () {\n                var start = { line: 37, ch: 9 },\n                    end   = { line: 37, ch: 13};\n\n                testDoc.replaceRange(\"x100.\", start);\n                testEditor.setCursorPos(end);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresentOrdered(hintObj, [\"charAt\", \"charCodeAt\", \"concat\", \"indexOf\"]);\n                });\n            });\n\n            it(\"function type hint in html file\", function () {\n                var start = { line: 36, ch: 12 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    expectParameterHint([{name: \"a\", type: \"Number\"}], 0);\n                });\n            });\n\n            it(\"should show function type code hint for function in script file inside html file\", function () {\n                var start = { line: 22, ch: 17 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    expectParameterHint([{name: \"a\", type: \"String\"}, {name: \"b\", type: \"Number\"}], 0);\n                });\n            });\n\n            it(\"should show function type code hint for function in another script file inside html file\", function () {\n                var start = { line: 23, ch: 17 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    expectParameterHint([{name: \"paramE1\", type: \"D1\"}, {name: \"paramE2\", type: \"Number\"}], 0);\n                });\n            });\n\n            it(\"should show global variable in another script file inside html file\", function () {\n                var start        = { line: 27, ch: 8 },\n                    end          = { line: 27, ch: 13},\n                    testPosStart = { line: 27, ch: 11},\n                    testPosEnd   = { line: 27, ch: 21};\n\n                testDoc.replaceRange(\"arr.m\", start);\n\n                testEditor.setCursorPos(end);\n                var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                runs(function () {\n                    hintsPresent(hintObj, [\"my-key\"]);\n                });\n                selectHint(JSCodeHints.jsHintProvider, hintObj, \"my-key\");\n                runs(function () {\n                    expect(testDoc.getRange(testPosStart, testPosEnd)).toEqual(\"[\\\"my-key\\\"]\");\n                });\n            });\n\n            it(\"should jump to definition inside html file\", function () {\n                var start = { line: 36, ch: 10 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 19, ch: 20});\n                });\n            });\n\n            it(\"should jump to funtion definition to loaded file1\", function () {\n                var start = { line: 22, ch: 15 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 33, ch: 13});\n                });\n            });\n\n            it(\"should jump to funtion definition to loaded file2\", function () {\n                var start = { line: 23, ch: 15 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 6, ch: 13});\n                });\n            });\n\n            it(\"should jump to property definition to loaded file1\", function () {\n                var start = { line: 23, ch: 28 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 4, ch: 16});\n                });\n            });\n\n            it(\"should jump to property definition to loaded file2\", function () {\n                var start = { line: 23, ch: 18 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 3, ch: 6});\n                });\n            });\n\n\n        });\n\n        describe(\"JavaScript Code Hinting without modules\", function () {\n            var testPath = extensionPath + \"/unittest-files/non-module-test-files/app.js\";\n            ScopeManager.handleProjectOpen(extensionPath + \"/unittest-files/non-module-test-files/\");\n\n            beforeEach(function () {\n                setupTest(testPath, true);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            // Test reading multiple files and subdirectories\n            // Turned for per #7646\n            xit(\"should handle reading all files when modules not used\", function () {\n                var start = { line: 8, ch: 8 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"a\", \"b\", \"b1\", \"c\", \"d\"]);\n                });\n            });\n        });\n\n        describe(\"JavaScript Code Hinting with modules\", function () {\n            var testPath = extensionPath + \"/unittest-files/module-test-files/module_tests.js\";\n\n            beforeEach(function () {\n                setupTest(testPath, true);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should read methods created in submodule on this\", function () {\n                var start = { line: 8, ch: 17 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"addMessage\", \"name\", \"privilegedMethod\", \"publicMethod1\"]);\n                });\n            });\n\n            // bug: wait for fix in tern\n            xit(\"should read methods created in submodule\", function () {\n                var start = { line: 19, ch: 15 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"addMessage\", \"name\", \"privilegedMethod\", \"publicMethod1\"]);\n                });\n            });\n\n            it(\"should read properties created in parent module\", function () {\n                var start        = { line: 30, ch: 8 },\n                    testPos          = { line: 30, ch: 15};\n\n                testDoc.replaceRange(\"parent.\", start);\n                runs(function () {\n                    testEditor.setCursorPos(testPos);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"addMessage\", \"name\", \"privilegedMethod\", \"publicMethod1\"]);\n                });\n            });\n\n            // bug: wait for tern\n            xit(\"should read methods created in submodule module\", function () {\n                var start        = { line: 62, ch: 0 },\n                    testPos          = { line: 62, ch: 13};\n\n                testDoc.replaceRange(\"SearchEngine.\", start);\n                runs(function () {\n                    testEditor.setCursorPos(testPos);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"getYourLuckyNumber\", \"subSearch\"]);\n                });\n            });\n\n            it(\"should read methods created in parent module\", function () {\n                var start        = { line: 78, ch: 41 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"getYourLuckyNumber\", \"subSearch\"]);\n                });\n            });\n\n            it(\"should load module by file path from require\", function () {\n                var start        = { line: 88, ch: 20 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"color\", \"material\", \"size\"]);\n                });\n            });\n\n            // tern bug: https://github.com/marijnh/tern/issues/147\n            xit(\"should read properties from exported module\", function () {\n                var start        = { line: 96, ch: 0 },\n                    testPos          = { line: 96, ch: 9};\n\n                testDoc.replaceRange(\"hondaCar.\", start);\n                runs(function () {\n                    testEditor.setCursorPos(testPos);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"model\", \"name\"]);\n                });\n            });\n\n            // bug in test framework? can't run sequential jump, verification is wrong\n            xit(\"should jump to a module, depending module\", function () {\n                var start        = { line: 93, ch: 25 },\n                    testPos      = { line: 8, ch: 35 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 5, ch: 23});\n                });\n                testEditor.setCursorPos(testPos);\n                runs(function () {\n                    editorJumped({line: 5, ch: 23});\n                });\n            });\n        });\n\n        describe(\"JavaScript Code Hinting preference tests\", function () {\n            var testPath = extensionPath + \"/unittest-files/preference-test-files/\",\n                preferences;\n\n            function getPreferences(path) {\n                preferences = null;\n\n                FileSystem.resolve(path, function (err, file) {\n                    if (!err) {\n                        FileUtils.readAsText(file).done(function (text) {\n                            var configObj = null;\n                            try {\n                                configObj = JSON.parse(text);\n                            } catch (e) {\n                                // continue with null configObj\n                                console.log(e);\n                            }\n                            preferences = new Preferences(configObj);\n                        }).fail(function (error) {\n                            preferences = new Preferences();\n                        });\n                    } else {\n                        preferences = new Preferences();\n                    }\n                });\n            }\n\n            // Test preferences file with no entries. Preferences should contain\n            // default values.\n            it(\"should handle reading an empty configuration file\", function () {\n                getPreferences(testPath + \"defaults-test/.jscodehints\");\n                waitsFor(function () {\n                    return preferences !== null;\n                });\n\n                runs(function () {\n                    expect(preferences.getExcludedDirectories()).toEqual(/node_modules/);\n                    expect(preferences.getExcludedFiles().source).\n                        toBe(/^require.*\\.js$|^jquery.*\\.js$/.source);\n                    expect(preferences.getMaxFileCount()).toBe(100);\n                    expect(preferences.getMaxFileSize()).toBe(512 * 1024);\n                });\n            });\n\n            // Test preferences file with empty or out of ranges values. Preferences\n            // should contain default values.\n            it(\"should handle reading an invalid configuration file\", function () {\n                getPreferences(testPath + \"negative-test/.jscodehints\");\n                waitsFor(function () {\n                    return preferences !== null;\n                });\n\n                runs(function () {\n                    expect(preferences.getExcludedDirectories()).toEqual(/node_modules/);\n                    expect(preferences.getExcludedFiles().source).\n                        toBe(/^require.*\\.js$|^jquery.*\\.js$/.source);\n                    expect(preferences.getMaxFileCount()).toBe(100);\n                    expect(preferences.getMaxFileSize()).toBe(512 * 1024);\n                });\n            });\n\n            // Positive test. Test pattern matching.\n            it(\"should handle a valid configuration file\", function () {\n                getPreferences(testPath + \"positive-test/.jscodehints\");\n                waitsFor(function () {\n                    return preferences !== null;\n                });\n\n                runs(function () {\n                    var excludedDirs = preferences.getExcludedDirectories(),\n                        excludedFiles = preferences.getExcludedFiles();\n\n                    // test \"excluded-dir1\"\n                    expect(excludedDirs.test(\"excluded-dir1\")).toBeTruthy();\n                    expect(excludedDirs.test(\"xexcluded-dir1\")).toBeFalsy();\n\n                    // test \"excluded-dir2-*\"\n                    expect(excludedDirs.test(\"excluded-dir2-1\")).toBeTruthy();\n                    expect(excludedDirs.test(\"excluded-dir2-12\")).toBeFalsy();\n                    expect(excludedDirs.test(\"excluded-dir2-z\")).toBeFalsy();\n                    expect(excludedDirs.test(\"excluded-dir2-\")).toBeFalsy();\n                    expect(excludedDirs.test(\"xexcluded-dir2-1\")).toBeFalsy();\n\n                    // test \"file1?.js\"\n                    expect(excludedFiles.test(\"file1.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file12.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file123.js\")).toBeFalsy();\n\n                    // test \"file2*.js\"\n                    expect(excludedFiles.test(\"file2.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file2xxx.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"filexxxx.js\")).toBeFalsy();\n\n                    // test \"file3.js\"\n                    expect(excludedFiles.test(\"file3.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"xfile3.js\")).toBeFalsy();\n\n                    // test \"/file4[x|y|z]?.js/\"\n                    expect(excludedFiles.test(\"file4.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file4x.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file4y.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file4z.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"file4b.js\")).toBeFalsy();\n                    expect(excludedFiles.test(\"file4xyz.js\")).toBeFalsy();\n                    expect(excludedFiles.test(\"xfile4.js\")).toBeTruthy();\n\n                    // test builtin exclusions are also present\n                    expect(excludedFiles.test(\"require.js\")).toBeTruthy();\n                    expect(excludedFiles.test(\"jquery.js\")).toBeTruthy();\n\n                    expect(preferences.getMaxFileCount()).toBe(512);\n                    expect(preferences.getMaxFileSize()).toBe(100000);\n                });\n            });\n        });\n\n        describe(\"regression tests\", function () {\n\n            it(\"should return true for valid identifier, false for invalid one\", function () {\n                var identifierList = [\"ᾩ\", \"ĦĔĽĻŎ\", \"〱〱〱〱\", \"जावास्क्रि\",\n                                      \"KingGeorgeⅦ\", \"π\", \"ಠ_ಠ\",\n                                      \"price_9̶9̶_89\", \"$_3423\", \"TRUE\", \"FALSE\", \"IV\"];\n                var invalidIdentifierList = [\" break\", \"\\tif\", \"\\ntrade\"];\n\n                invalidIdentifierList.forEach(function (element) {\n                    var result = HintUtils.maybeIdentifier(element);\n                    expect(result).toBe(false);\n                });\n\n                identifierList.forEach(function (element) {\n                    var result = HintUtils.maybeIdentifier(element);\n                    expect(result).toBe(true);\n                });\n            });\n        });\n\n        describe(\"JavaScript Code Hinting with test.html file\", function () {\n            var testFile = extensionPath + \"/unittest-files/basic-test-files/test.html\";\n\n            beforeEach(function () {\n                setupTest(testFile, true);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n\n            });\n\n            // FIXME (issue #3915)\n            xit(\"should read function name has double byte chars\", function () {\n                var start   = { line: 15, ch: 8 },\n                    testPos = { line: 15, ch: 10 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"fun測试\"]);\n                });\n                runs(function () {\n                    testEditor.setCursorPos(testPos);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"fun測试()\"]);\n                });\n            });\n\n            it(\"should jump to function name with double byte chars\", function () {\n                var start        = { line: 16, ch: 9 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 12, ch: 20});\n                });\n            });\n\n            // FIXME (issue #3915)\n            xit(\"should read function name has non ascii chars\", function () {\n                var start = { line: 16, ch: 16 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"frenchçProp()\"]);\n                });\n            });\n\n            it(\"should jump to function name with non ascii chars\", function () {\n                var start        = { line: 16, ch: 12 };\n\n                testEditor.setCursorPos(start);\n                runs(function () {\n                    editorJumped({line: 12, ch: 20});\n                });\n            });\n        });\n\n        describe(\"Code Hinting Regression\", function () {\n            var testFile = extensionPath + \"/unittest-files/module-test-files/china/cupFiller.js\";\n\n            beforeEach(function () {\n                setupTest(testFile, true);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            // The test is disabled, because the TernWorker will consult the ProjectManager to\n            // determine all the files in the project root. We don't have a project root for this\n            // testcase. Perhaps we need to change the testsetup or find another way of dealing with this\n            // Test makes sure that http://github.com/adobe/brackets/issue/6931 doesn't show up\n            xit(\"should show hints for members of referenced class\", function () {\n                var start = { line: 8, ch: 15 };\n\n                runs(function () {\n                    testEditor.setCursorPos(start);\n                    var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                    hintsPresentExact(hintObj, [\"empty\", \"emptyIt\", \"fill\", \"full\"]);\n                });\n            });\n        });\n\n        describe(\"JavaScript Code Hinting format parameters tests\", function () {\n\n            it(\"should format parameters with no params\", function () {\n                var params = [];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"\");\n            });\n\n            it(\"should format parameters with one param\", function () {\n                var params = [{name: \"param1\", type: \"String\"}];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"String param1\");\n            });\n\n            it(\"should format parameters with one optional param\", function () {\n                var params = [{name: \"param1\", type: \"String\", isOptional: true}];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"[String param1]\");\n            });\n\n            it(\"should format parameters with one required, one optional param\", function () {\n                var params = [{name: \"param1\", type: \"String\"},\n                              {name: \"param2\", type: \"String\", isOptional: true}];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"String param1, [String param2]\");\n            });\n\n            it(\"should format parameters with required param following an optional param\", function () {\n                var params = [{name: \"param1\", type: \"String\"},\n                    {name: \"param2\", type: \"String\", isOptional: true},\n                    {name: \"param3\", type: \"String\"}];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"String param1, [String param2, String param3]\");\n            });\n\n            it(\"should format parameters with optional param following an optional param\", function () {\n                var params = [{name: \"param1\", type: \"String\"},\n                    {name: \"param2\", type: \"String\", isOptional: true},\n                    {name: \"param3\", type: \"String\", isOptional: true}];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"String param1, [String param2], [String param3]\");\n            });\n\n            it(\"should format parameters with optional param following optional and required params\", function () {\n                var params = [{name: \"param1\", type: \"String\"},\n                    {name: \"param2\", type: \"String\", isOptional: true},\n                    {name: \"param3\", type: \"String\"},\n                    {name: \"param4\", type: \"String\", isOptional: true}];\n\n                expect(HintUtils2.formatParameterHint(params)).toBe(\"String param1, [String param2, String param3], [String param4]\");\n            });\n\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var MultiRangeInlineEditor  = brackets.getModule(\"editor/MultiRangeInlineEditor\").MultiRangeInlineEditor,\n        EditorManager           = brackets.getModule(\"editor/EditorManager\"),\n        JSUtils                 = brackets.getModule(\"language/JSUtils\"),\n        LanguageManager         = brackets.getModule(\"language/LanguageManager\"),\n        PerfUtils               = brackets.getModule(\"utils/PerfUtils\"),\n        ProjectManager          = brackets.getModule(\"project/ProjectManager\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        HealthLogger            = brackets.getModule(\"utils/HealthLogger\");\n\n    /**\n     * Return the token string that is at the specified position.\n     *\n     * @param hostEditor {!Editor} editor\n     * @param {!{line:number, ch:number}} pos\n     * @return {functionName: string, reason: string}\n     */\n    function _getFunctionName(hostEditor, pos) {\n        var token = hostEditor._codeMirror.getTokenAt(pos, true);\n\n        // If the pos is at the beginning of a name, token will be the\n        // preceding whitespace or dot. In that case, try the next pos.\n        if (!/\\S/.test(token.string) || token.string === \".\") {\n            token = hostEditor._codeMirror.getTokenAt({line: pos.line, ch: pos.ch + 1}, true);\n        }\n\n        // Return valid function expressions only (function call or reference)\n        if (!((token.type === \"variable\") ||\n              (token.type === \"variable-2\") ||\n              (token.type === \"property\"))) {\n            return {\n                functionName: null,\n                reason: Strings.ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\n            };\n        }\n\n        return {\n            functionName: token.string,\n            reason: null\n        };\n    }\n\n    /**\n     * @private\n     * For unit and performance tests. Allows lookup by function name instead of editor offset\n     * without constructing an inline editor.\n     *\n     * @param {!string} functionName\n     * @return {$.Promise} a promise that will be resolved with an array of function offset information\n     */\n    function _findInProject(functionName) {\n        var result = new $.Deferred();\n\n        PerfUtils.markStart(PerfUtils.JAVASCRIPT_FIND_FUNCTION);\n\n        function _nonBinaryFileFilter(file) {\n            return !LanguageManager.getLanguageForPath(file.fullPath).isBinary();\n        }\n\n        ProjectManager.getAllFiles(_nonBinaryFileFilter)\n            .done(function (files) {\n                JSUtils.findMatchingFunctions(functionName, files)\n                    .done(function (functions) {\n                        PerfUtils.addMeasurement(PerfUtils.JAVASCRIPT_FIND_FUNCTION);\n                        result.resolve(functions);\n                    })\n                    .fail(function () {\n                        PerfUtils.finalizeMeasurement(PerfUtils.JAVASCRIPT_FIND_FUNCTION);\n                        result.reject();\n                    });\n            })\n            .fail(function () {\n                result.reject();\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * For unit and performance tests. Allows lookup by function name instead of editor offset .\n     *\n     * @param {!Editor} hostEditor\n     * @param {!string} functionName\n     * @return {?$.Promise} synchronously resolved with an InlineWidget, or\n     *         {string} if js other than function is detected at pos, or\n     *         null if we're not ready to provide anything.\n     */\n    function _createInlineEditor(hostEditor, functionName) {\n        // Use Tern jump-to-definition helper, if it's available, to find InlineEditor target.\n        var helper = brackets._jsCodeHintsHelper;\n        if (helper === null) {\n            return null;\n        }\n\n        var result = new $.Deferred();\n        PerfUtils.markStart(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n\n        var response = helper();\n        if (response.hasOwnProperty(\"promise\")) {\n            response.promise.done(function (jumpResp) {\n                var resolvedPath = jumpResp.fullPath;\n                if (resolvedPath) {\n\n                    // Tern doesn't always return entire function extent.\n                    // Use QuickEdit search now that we know which file to look at.\n                    var fileInfos = [];\n                    fileInfos.push({name: jumpResp.resultFile, fullPath: resolvedPath});\n                    JSUtils.findMatchingFunctions(functionName, fileInfos, true)\n                        .done(function (functions) {\n                            if (functions && functions.length > 0) {\n                                var jsInlineEditor = new MultiRangeInlineEditor(functions);\n                                jsInlineEditor.load(hostEditor);\n\n                                PerfUtils.addMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                                result.resolve(jsInlineEditor);\n                            } else {\n                                // No matching functions were found\n                                PerfUtils.addMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                                result.reject();\n                            }\n                        })\n                        .fail(function () {\n                            PerfUtils.addMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                            result.reject();\n                        });\n\n                } else {        // no result from Tern.  Fall back to _findInProject().\n\n                    _findInProject(functionName).done(function (functions) {\n                        if (functions && functions.length > 0) {\n                            var jsInlineEditor = new MultiRangeInlineEditor(functions);\n                            jsInlineEditor.load(hostEditor);\n\n                            PerfUtils.addMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                            result.resolve(jsInlineEditor);\n                        } else {\n                            // No matching functions were found\n                            PerfUtils.addMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                            result.reject();\n                        }\n                    }).fail(function () {\n                        PerfUtils.finalizeMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                        result.reject();\n                    });\n                }\n\n            }).fail(function () {\n                PerfUtils.finalizeMeasurement(PerfUtils.JAVASCRIPT_INLINE_CREATE);\n                result.reject();\n            });\n\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * This function is registered with EditorManager as an inline editor provider. It creates an inline editor\n     * when the cursor is on a JavaScript function name, finds all functions that match the name\n     * and shows (one/all of them) in an inline editor.\n     *\n     * @param {!Editor} editor\n     * @param {!{line:number, ch:number}} pos\n     * @return {$.Promise} a promise that will be resolved with an InlineWidget\n     *      or null if we're not ready to provide anything.\n     */\n    function javaScriptFunctionProvider(hostEditor, pos) {\n        // Only provide a JavaScript editor when cursor is in JavaScript content\n        if (hostEditor.getModeForSelection() !== \"javascript\") {\n            return null;\n        }\n\n        //Send analytics data for Quick Edit open\n        HealthLogger.sendAnalyticsData(\n            \"QuickEditOpen\",\n            \"usage\",\n            \"quickEdit\",\n            \"open\"\n        );\n        // Only provide JavaScript editor if the selection is within a single line\n        var sel = hostEditor.getSelection();\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n\n        // Always use the selection start for determining the function name. The pos\n        // parameter is usually the selection end.\n        var functionResult = _getFunctionName(hostEditor, sel.start);\n        if (!functionResult.functionName) {\n            return functionResult.reason || null;\n        }\n\n        return _createInlineEditor(hostEditor, functionResult.functionName);\n    }\n\n    // init\n    EditorManager.registerInlineEditProvider(javaScriptFunctionProvider);\n    PerfUtils.createPerfMeasurement(\"JAVASCRIPT_INLINE_CREATE\", \"JavaScript Inline Editor Creation\");\n    PerfUtils.createPerfMeasurement(\"JAVASCRIPT_FIND_FUNCTION\", \"JavaScript Find Function\");\n\n    // for unit tests only\n    exports.javaScriptFunctionProvider  = javaScriptFunctionProvider;\n    exports._createInlineEditor         = _createInlineEditor;\n    exports._findInProject              = _findInProject;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/.editorconfig",
    "content": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://EditorConfig.org\n\nroot = true\n\n[grunt.js]\nindent_style = tab\n\n[ui/**.js]\nindent_style = tab\n\n[tests/unit/**.js]\nindent_style = tab\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/.jshintrc",
    "content": "{\n\t\"curly\": true,\n\t\"eqnull\": true,\n\t\"eqeqeq\": true,\n\t\"expr\": true,\n\t\"latedef\": true,\n\t\"noarg\": true,\n\t\"onevar\": true,\n\t\"smarttabs\": true,\n\t\"trailing\": true,\n\t\"undef\": true\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/AUTHORS.txt",
    "content": "Authors ordered by first contribution\nA list of current team members is available at http://jqueryui.com/about\n\nPaul Bakaus <paul.bakaus@googlemail.com>\nRichard Worth <rdworth@gmail.com>\nYehuda Katz <wycats@gmail.com>\nSean Catchpole <littlecooldude@gmail.com>\nJohn Resig <jeresig@gmail.com>\nTane Piper <tane@tanepiper.com>\nDmitri Gaskin <dmitrig01@gmail.com>\nKlaus Hartl <klaus.hartl@googlemail.com>\nStefan Petre <stefan.petre@gmail.com>\nGilles van den Hoven <gilles@webunity.nl>\nMicheil Smith <micheil@brandedcode.com>\nJörn Zaefferer <joern.zaefferer@gmail.com>\nMarc Grabanski <m@marcgrabanski.com>\nKeith Wood <kbwood.au@gmail.com>\nBrandon Aaron <brandon.aaron@gmail.com>\nScott González <scott.gonzalez@gmail.com>\nEduardo Lundgren <eduardolundgren@gmail.com>\nAaron Eisenberger <aaronchi@gmail.com>\nJoan Piedra <theneojp@gmail.com>\nBruno Basto <b.basto@gmail.com>\nRemy Sharp <remy@leftlogic.com>\nBohdan Ganicky <bohdan.ganicky@gmail.com>\nDavid Bolter <david.bolter@gmail.com>\nChi Cheng <cloudream@gmail.com>\nCa-Phun Ung <pazu2k@gmail.com>\nAriel Flesler <aflesler@gmail.com>\nMaggie Costello Wachs <fg.maggie@gmail.com>\nScott Jehl <scott@scottjehl.com>\nTodd Parker <fg.todd@gmail.com>\nAndrew Powell <powella@gmail.com>\nBrant Burnett <btburnett3@gmail.com>\nDouglas Neiner <doug@pixelgraphics.us>\nPaul Irish <paul.irish@gmail.com>\nRalph Whitbeck <ralph.whitbeck@gmail.com>\nThibault Duplessis <thibault.duplessis@gmail.com>\nDominique Vincent <dominique.vincent@toitl.com>\nJack Hsu <jack.hsu@gmail.com>\nAdam Sontag <ajpiano@ajpiano.com>\nCarl Fürstenberg <carl@excito.com>\nKevin Dalman <development@allpro.net>\nAlberto Fernández Capel <afcapel@gmail.com>\nJacek Jędrzejewski <jacek.jedrzejewski@gmail.com>\nTing Kuei <ting@kuei.com>\nSamuel Cormier-Iijima <sam@chide.it>\nJon Palmer <jonspalmer@gmail.com>\nBen Hollis <bhollis@amazon.com>\nJustin MacCarthy <Justin@Rubystars.biz>\nEyal Kobrigo <kobrigo@hotmail.com>\nTiago Freire <tiago.freire@gmail.com>\nDiego Tres <diegotres@gmail.com>\nHolger Rüprich <holger@rueprich.de>\nZiling Zhao <zizhao@cisco.com>\nMike Alsup <malsup@gmail.com>\nRobson Braga Araujo <robsonbraga@gmail.com>\nPierre-Henri Ausseil <ph.ausseil@gmail.com>\nChristopher McCulloh <cmcculloh@gmail.com>\nAndrew Newcomb <ext.github@preceptsoftware.co.uk>\nLim Chee Aun <cheeaun@gmail.com>\nJorge Barreiro <yortx.barry@gmail.com>\nDaniel Steigerwald <daniel@steigerwald.cz>\nJohn Firebaugh <john_firebaugh@bigfix.com>\nJohn Enters <github@darkdark.net>\nAndrey Kapitcyn <ru.m157y@gmail.com>\nDmitry Petrov <dpetroff@gmail.com>\nEric Hynds <eric@hynds.net>\nChairat Sunthornwiphat <pipo@sixhead.com>\nJosh Varner <josh.varner@gmail.com>\nStéphane Raimbault <stephane.raimbault@gmail.com>\nJay Merrifield <fracmak@gmail.com>\nJ. Ryan Stinnett <jryans@gmail.com>\nPeter Heiberg <peter@heiberg.se>\nAlex Dovenmuehle <adovenmuehle@gmail.com>\nJamie Gegerson <git@jamiegegerson.com>\nRaymond Schwartz <skeetergraphics@gmail.com>\nPhillip Barnes <philbar@gmail.com>\nKyle Wilkinson <kai@wikyd.org>\nKhaled AlHourani <me@khaledalhourani.com>\nMarian Rudzynski <mr@impaled.org>\nJean-Francois Remy <jfremy@virtuoz.com>\nDoug Blood <dougblood@gmail.com>\nFilippo Cavallarin <poplix@papuasia.org>\nHeiko Henning <h.henning@educa.ch>\nAliaxandr Rahalevich <saksmlz@gmail.com>\nMario Visic <mario@mariovisic.com>\nXavi Ramirez <xavi.rmz@gmail.com>\nMax Schnur <max.schnur@gmail.com>\nSaji Nediyanchath <saji89@gmail.com>\nCorey Frang <gnarf@gnarf.net>\nAaron Peterson <aaronp123@yahoo.com>\nIvan Peters <ivan@ivanpeters.com>\nMohamed Cherif Bouchelaghem <cherifbouchelaghem@yahoo.fr>\nMarcos Sousa <marcos.sousa@corp.globo.com>\nMichael DellaNoce <mdellanoce@mailtrust.com>\nGeorge Marshall <echosx@gmail.com>\nTobias Brunner <tobias@strongswan.org>\nMartin Solli <msolli@gmail.com>\nDavid Petersen <public@petersendidit.com>\nDan Heberden <danheberden@gmail.com>\nWilliam Kevin Manire <williamkmanire@gmail.com>\nGilmore Davidson <gilmoreorless@gmail.com>\nMichael Wu <michaelmwu@gmail.com>\nAdam Parod <mystic414@gmail.com>\nGuillaume Gautreau <guillaume+github@ghusse.com>\nMarcel Toele <EleotleCram@gmail.com>\nDan Streetman <ddstreet@ieee.org>\nMatt Hoskins <furlined@cat-basket.org>\nGiovanni Giacobbi <giovanni@giacobbi.net>\nKyle Florence <kyle.florence@gmail.com>\nPavol Hluchý <lopo@losys.sk>\nHans Hillen <hans.hillen@gmail.com>\nMark Johnson <virgofx@live.com>\nTrey Hunner <treyhunner@gmail.com>\nShane Whittet <whittet@gmail.com>\nEdward Faulkner <ef@alum.mit.edu>\nAdam Baratz <adam.baratz@gmail.com>\nKato Kazuyoshi <kato.kazuyoshi@gmail.com>\nEike Send <eike.send@gmail.com>\nKris Borchers <kris.borchers@gmail.com>\nEddie Monge <eddie@eddiemonge.com>\nIsrael Tsadok <itsadok@gmail.com>\nCarson McDonald <carson@ioncannon.net>\nJason Davies <jason@jasondavies.com>\nGarrison Locke <gplocke@gmail.com>\nDavid Murdoch <musicisair@yahoo.com>\nBen Boyle <benjamins.boyle@gmail.com>\nJesse Baird <jebaird@gmail.com>\nJonathan Vingiano <jvingiano@gmail.com>\nDylan Just <dev@ephox.com>\nTomy Kaira <tomykaira@gmail.com>\nGlenn Goodrich <glenn.goodrich@gmail.com>\nAshek Elahi <mail.ashek@gmail.com>\nRyan Neufeld <ryan@neufeldmail.com>\nMarc Neuwirth <marc.neuwirth@gmail.com>\nPhilip Graham <philip.robert.graham@gmail.com>\nBenjamin Sterling <benjamin.sterling@kenzomedia.com>\nWesley Walser <wwalser@atlassian.com>\nKouhei Sutou <kou@clear-code.com>\nKarl Kirch <karl.ctr.kirch@faa.gov>\nChris Kelly <ckdake@ckdake.com>\nJay Oster <jay@loyalize.com>\nAlex Polomoshnov <alex.polomoshnov@gmail.com>\nDavid Leal <dgleal@gmail.com>\nigor milla <igor.fsp.milla@gmail.com>\nDave Methvin <dave.methvin@gmail.com>\nFlorian Gutmann <blackfeet@gmx.at>\nMarwan Al Jubeh <marwan.aljubeh@gmail.com>\nMilan Broum <midlis@googlemail.com>\nSebastian Sauer <info@dynpages.de>\nGaëtan Muller <m.gaetan89@gmail.com>\nMichel Weimerskirch <michel@weimerskirch.net>\nWilliam Griffiths <william@ycymro.com>\nStojce Slavkovski <stojce@gmail.com>\nDavid Soms <david.soms@gmail.com>\nDavid De Sloovere <david.desloovere@hotmail.com>\nMichael P. Jung <michael.jung@terreon.de>\nShannon Pekary <spekary@gmail.com>\nMatthew Hutton <meh@corefiling.co.uk>\nJames Khoury <james@jameskhoury.com>\nRob Loach <robloach@gmail.com>\nAlberto Monteiro <betimbrasil@gmail.com>\nAlex Rhea <alex.rhea@gmail.com>\nKrzysztof Rosiński <rozwell69@gmail.com>\nRyan Olton <oltonr@gmail.com>\nGenie <386@mail.com>\nRick Waldron <waldron.rick@gmail.com>\nIan Simpson <spoonlikesham@gmail.com>\nLev Kitsis <spam4lev@gmail.com>\nTJ VanToll <tj.vantoll@gmail.com>\nJustin Domnitz <jdomnitz@gmail.com>\nDouglas Cerna <replaceafill@system76.(none)>\nBert ter Heide <bertjh@hotmail.com>\nJasvir Nagra <jasvir@gmail.com>\nPetr Hromadko <yuriy@tokyoscale.com>\nHarri Kilpiö <harri.kilpio@gmail.com>\nLado Lomidze <lado.lomidze@gmail.com>\nAmir E. Aharoni <amir.aharoni@mail.huji.ac.il>\nSimon Sattes <simon.sattes@gmail.com>\nJo Liss <joliss42@gmail.com>\nGuntupalli Karunakar <karunakarg@yahoo.com>\nShahyar Ghobadpour <shahyar@gmail.com>\nLukasz Lipinski <uzza17@gmail.com>\nTimo Tijhof <krinklemail@gmail.com>\nJason Moon <jmoon@socialcast.com>\nMartin Frost <martinf55@hotmail.com>\nEneko Illarramendi <eneko@illarra.com>\nEungJun Yi <semtlenori@gmail.com>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/GPL-LICENSE.txt",
    "content": "        GNU GENERAL PUBLIC LICENSE\n           Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n          Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n        GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n          NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/MIT-LICENSE.txt",
    "content": "Copyright (c) 2012 Paul Bakaus, http://jqueryui.com/\n\nThis software consists of voluntary contributions made by many\nindividuals (AUTHORS.txt, http://jqueryui.com/about) For exact\ncontribution history, see the revision history and logs, available\nat http://jquery-ui.googlecode.com/svn/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/README.md",
    "content": "[jQuery UI](http://jqueryui.com/) - Interactions and Widgets for the web\n================================\n\njQuery UI provides interactions like Drag and Drop and widgets like Autocomplete, Tabs and Slider and makes these as easy to use as jQuery itself.\n\nIf you want to use jQuery UI, go to [jqueryui.com](http://jqueryui.com) to get started. Or visit the [Using jQuery UI Forum](http://forum.jquery.com/using-jquery-ui) for discussions and questions.\n\nIf you are interested in helping develop jQuery UI, you are in the right place.\nTo discuss development with team members and the community, visit the [Developing jQuery UI Forum](http://forum.jquery.com/developing-jquery-ui) or in #jquery on irc.freednode.net.\n\n\nFor contributors\n---\n\nIf you want to help and provide a patch for a bugfix or new feature, please take\na few minutes and look at [our Getting Involved guide](http://wiki.jqueryui.com/w/page/35263114/Getting-Involved).\nIn particular check out the [Coding standards](http://wiki.jqueryui.com/w/page/12137737/Coding-standards)\nand [Commit Message Style Guide](http://wiki.jqueryui.com/w/page/25941597/Commit-Message-Style-Guide).\n\nIn general, fork the project, create a branch for a specific change and send a\npull request for that branch. Don't mix unrelated changes. You can use the commit\nmessage as the description for the pull request.\n\n\nRunning the Unit Tests\n---\n\nRun the unit tests with a local server that supports PHP. No database is required. Pre-configured php local servers are available for Windows and Mac. Here are some options:\n\n- Windows: [WAMP download](http://www.wampserver.com/en/)\n- Mac: [MAMP download](http://www.mamp.info/en/index.html)\n- Linux: [Setting up LAMP](https://www.linux.com/learn/tutorials/288158-easy-lamp-server-installation)\n- [Mongoose (most platforms)](http://code.google.com/p/mongoose/)\n\n\nBuilding jQuery UI\n---\n\njQuery UI uses the [grunt](http://github.com/cowboy/grunt) build system. Building jQuery UI requires node.js and a command line zip program.\n\nInstall grunt.\n\n`npm install grunt -g`\n\nClone the jQuery UI git repo.\n\n`git clone git://github.com/jquery/jquery-ui.git`\n\n`cd jquery-ui`\n\nInstall node modules.\n\n`npm install`\n\nRun grunt.\n\n`grunt build`\n\nThere are many other tasks that can be run through grunt. For a list of all tasks:\n\n`grunt --help`\n\n\nFor committers\n---\n\nWhen looking at pull requests, first check for [proper commit messages](http://wiki.jqueryui.com/w/page/12137724/Bug-Fixing-Guide).\n\nDo not merge pull requests directly through GitHub's interface.\nMost pull requests are a single commit; cherry-picking will avoid creating a merge commit.\nIt's also common for contributors to make minor fixes in an additional one or two commits.\nThese should be squashed before landing in master.\n\n**Make sure the author has a valid name and email address associated with the commit.**\n\nFetch the remote first:\n\n    git fetch [their-fork.git] [their-branch]\n\nThen cherry-pick the commit(s):\n\n\tgit cherry-pick [sha-of-commit]\n\nIf you need to edit the commit message:\n\n    git cherry-pick -e [sha-of-commit]\n\nIf you need to edit the changes:\n\n\tgit cherry-pick -n [sha-of-commit]\n\t# make changes\n\tgit commit --author=\"[author-name-and-email]\"\n\nIf it should go to the stable brach, cherry-pick it to stable:\n\n    git checkout 1-8-stable\n    git cherry-pick -x [sha-of-commit-from-master]\n\n*NOTE: Do not cherry-pick into 1-8-stable until you have pushed the commit from master upstream.*\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/build/release/changelog-shell",
    "content": "\nThis file contains a shell for the changelog, followed by a list of every commit for this release.\n\nChoose the appropriate line for the Summary section.\n\nMove all commit notes to the appropriate section.\n- Each line should be in the following format:\n  [Fixed|Added]: The ticket description. ([Ticket link], [Commit link])\n- If the commit is not related to a bug or feature, e.g., whitepsace cleanup, remove it.\n- If there is no ticket number, search Trac for the relevant ticket.\n  - If there is no ticket, create one (if needed), or leave just the commit link.\n\nDouble check that \"XXXX\" does not appear anywhere in the changelog.\n\nPost this changelog at: CHANGELOG_URL\n\n\n\nDELETE EVERYTHING ABOVE THE FOLLOWING LINE\n------------------------------------------\n\n= Summary =\nThis is the final release of jQuery UI 1.8.\n-- OR --\nThis is the second maintenance release for [[UI/Changelog/1.8|jQuery UI 1.8]].\n\n= Build =\n\n= Core &amp; Utilities =\n\n=== UI Core ===\n\n=== Mouse ===\n\n=== Widget Factory ===\n\n=== Position ===\n\n= Interactions =\n\n=== Draggable ===\n\n=== Droppable ===\n\n=== Resizable ===\n\n=== Selectable ===\n\n=== Sortable ===\n\n= Widgets =\n\n=== Accordion ===\n\n=== Autocomplete ===\n\n=== Button ===\n\n=== Datepicker ===\n\n=== Dialog ===\n\n=== Progressbar ===\n\n=== Slider ===\n\n=== Tabs ===\n\n= Effects =\n\n=== Individual effects ===\n\n= CSS Framework =\n\n= Demos =\n\n= Website =\n\n=== Download Builder ===\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/build/release/prepare-release",
    "content": "#!/bin/sh\n\nbase_dir=\"`pwd`/jquery-ui-release\"\nrepo_dir=\"$base_dir/jquery-ui\"\nrelease_dir=\"$repo_dir/build/release\"\n\ngithub_repo=\"git@github.com:jquery/jquery-ui.git\"\nremote_cmd=\"ssh jqadmin@ui-dev.jquery.com /srv/dev.jqueryui.com/prepare-release\"\n\n\n\n#\n# Setup environment\n#\n\necho\necho \"--------------------------\"\necho \"| SETTING UP ENVIRONMENT |\"\necho \"--------------------------\"\necho\n\nmkdir $base_dir\ncd $base_dir\n\necho \"Cloning repo from $github_repo...\"\ngit clone $github_repo\ncd $repo_dir\n\necho\necho \"Environment setup complete.\"\necho\n\n\n\n#\n# Figure out which versions we're dealing with\n#\n\necho\necho \"------------------------\"\necho \"| CALCULATING VERSIONS |\"\necho \"------------------------\"\necho\n\n# NOTE: this will be different for minor and major releases\nversion=`$remote_cmd/get-latest-version`\nmajor_minor=${version%.*}\npoint=${version##*.}\nversion_new=\"${major_minor}.$(($point + 1))\"\nversion_next=`cat version.txt`\n\necho \"We are going from $version to $version_new.\"\necho \"version.txt will be set to $version_next when complete.\"\necho \"Press enter to continue, or ctrl+c to cancel.\"\nread\n\n\n#\n# Generate shell for changelog\n#\n\necho\necho \"------------------------\"\necho \"| GENERATING CHANGELOG |\"\necho \"------------------------\"\necho\n\necho \"Creating shell for changelog...\"\nchangelog_url=\"http:\\/\\/docs.jquery.com\\/action\\/edit\\/UI\\/Changelog\\/$version_new\"\n`sed \"s/CHANGELOG_URL/$changelog_url/\" <$release_dir/changelog-shell >$base_dir/changelog`\n\n\n# find all commits\necho \"Adding commits to changelog...\"\nformat_ticket='[http://dev.jqueryui.com/ticket/XXXX #XXXX]'\nformat_commit='[http://github.com/jquery/jquery-ui/commit/%H %h]'\nformat_full=\"* %s ($format_ticket, $format_commit)\"\ngit whatchanged $version... --pretty=format:\"$format_full\" \\\n  -- ui themes demos build \\\n| sed '/^:/ d' \\\n| sed '/^$/ d' \\\n| sed 's/\\(Fixe[sd] #\\)\\([0-9][0-9]*\\)\\(.*\\)\\(XXXX #XXXX\\)/Fixed #\\2\\3\\2 #\\2/' \\\n| LC_ALL='C' sort -f \\\n>> $base_dir/changelog\n\n# find all fixed tickets\necho \"Adding Trac tickets to changelog...\"\n$remote_cmd/generate-changelog >> $base_dir/changelog\n\necho\necho \"Changelog complete.\"\necho\n\n\n\n#\n# Generate list of contributors\n#\n\necho\necho \"--------------------------\"\necho \"| GATHERING CONTRIBUTORS |\"\necho \"--------------------------\"\necho\n\n\n# find all committers and authors\necho \"Adding commiters and authors...\"\nformat_contributors='%aN%n%cN'\ngit whatchanged $version... --pretty=format:\"$format_contributors\" \\\n| sed '/^:/ d' \\\n| sed '/^$/ d' \\\n> $base_dir/thankyou\n\n# find all reporters and commenters from Trac\necho \"Adding reporters and commenters from Trac...\"\n$remote_cmd/generate-contributors >> $base_dir/thankyou\n\n# sort names\necho \"Sorting contributors...\"\nLC_ALL='C' sort -f $base_dir/thankyou | uniq > $base_dir/_thankyou\nmv $base_dir/_thankyou $base_dir/thankyou\n\n# find all people that were thanked\necho \"Adding people thanked in commits...\"\ngit whatchanged $version... \\\n| grep -i thank \\\n>> $base_dir/thankyou\n\necho\necho \"Find contributors from duplicates of fixed tickets and add them to:\"\necho \"$base_dir/thankyou\"\necho \"Press enter when done.\"\nread\n\necho\necho \"Contributors list complete.\"\necho\n\n\n\n#\n# Update version\n#\n\necho\necho \"--------------------\"\necho \"| UPDATING VERSION |\"\necho \"--------------------\"\necho\n\necho \"Updating version.txt to $version_new...\"\necho $version_new > version.txt\n\ngit commit -a -m \"Tagging the $version_new release.\"\nversion_new_time=`git log -1 --pretty=format:\"%ad\"`\necho \"Committed version.txt at $version_new_time...\"\n\necho \"Tagging $version_new...\"\ngit tag $version_new\n\necho \"Updating version.txt to $version_next...\"\necho $version_next > version.txt\n\ngit commit -a -m \"Updating the master version to $version_next\"\necho \"Committed version.txt...\"\n\necho\necho \"Version update complete.\"\necho\n\n\n\n#\n# Push to GitHub\n#\n\necho\necho \"---------------------\"\necho \"| PUSHING TO GITHUB |\"\necho \"---------------------\"\necho\n\necho \"Please review the output and generated files as a sanity check.\"\necho \"Press enter to continue or ctrl+c to abort.\"\nread\n\ngit push\ngit push --tags\n\necho\necho \"Push to GitHub complete.\"\necho\n\n\n\n#\n# Update Trac\n#\n\necho\necho \"-----------------\"\necho \"| UPDATING TRAC |\"\necho \"-----------------\"\necho\n\n# TODO: automate this\n# NOTE: this will be different for minor and major releases\nmilestone=`$remote_cmd/get-latest-milestone`\n\n# Create new milestrone and version\necho \"$version_new was tagged at $version_new_time.\"\necho \"Create and close the $version_new Milestone with the above date and time.\"\necho \"Create the $version_new Version with the above date and time.\"\necho \"Press enter when done.\"\nread\n\n# Update milestone for all fixed tickets\necho \"Change all $milestone fixed tickets to $version_new.\"\necho \"Press enter when done.\"\nread\n\necho\necho \"Trac updates complete.\"\necho\n\n\n\n#\n# Build jQuery UI\n#\n\necho\necho \"----------------------\"\necho \"| BUILDING JQUERY UI |\"\necho \"----------------------\"\necho\n\n# check out the tagged version\necho \"Checking out $version_new...\"\ngit checkout $version_new\ncd build\n\n# Update the link to the docs (never contains the patch version)\necho \"Updating URL for API docs...\"\nsed \"s/UI\\/API\\/\\${release\\.version}/UI\\/API\\/$major_minor/\" build.xml >build.xml.tmp\nmv build.xml.tmp build.xml\n\n# Run the build\necho \"Running build...\"\nant\n\necho\necho \"Build complete.\"\necho\n\n\n\n#\n# Upload zip to Google Code\n#\n\necho\necho \"----------------------\"\necho \"| UPDATE GOOGLE CODE |\"\necho \"----------------------\"\necho\n\necho \"Upload zip to Google Code.\"\necho \"  http://code.google.com/p/jquery-ui/downloads/entry\"\necho \"  Summary: jQuery UI $version_new (Source, demos, docs, themes, tests) STABLE\"\necho \"  Labels: Featured, Type-Source, OpSys-All\"\necho \"Modify the previous release to no longer say STABLE at the end.\"\necho \"Remove the featured label from the previous release.\"\necho \"Press enter when done.\"\nread\n\necho\necho \"Google Code update complete.\"\necho\n\n\n\n#\n# Update SVN\n#\n\necho\necho \"----------------\"\necho \"| UPDATING SVN |\"\necho \"----------------\"\necho\n\ncd $base_dir\nmkdir svn\ncd svn\n\necho \"Checking out SVN tags...\"\nsvn co --depth immediates https://jquery-ui.googlecode.com/svn/tags\ncd tags\n\necho \"Unzipping build into tags/$version_new...\"\nunzip $repo_dir/build/dist/jquery-ui-$version_new.zip\nmv jquery-ui-$version_new $version_new\n\necho \"Adding files to SVN...\"\nsvn add $version_new\n\necho \"Setting svn:mime-type...\"\nfind $version_new -name \\*.js -exec svn propset svn:mime-type text/javascript {} \\;\nfind $version_new -name \\*.css -exec svn propset svn:mime-type text/css {} \\;\nfind $version_new -name \\*.html -exec svn propset svn:mime-type text/html {} \\;\nfind $version_new -name \\*.png -exec svn propset svn:mime-type image/png {} \\;\nfind $version_new -name \\*.gif -exec svn propset svn:mime-type image/gif {} \\;\n\n# TODO: commit\necho\necho \"svn commit with the following message:\"\necho \"Created $version_new tag from http://jquery-ui.googlecode.com/files/jquery-ui-$version_new.zip\"\necho \"Press enter when done.\"\nread\n\necho\necho \"SVN update complete.\"\necho\n\n\n\n#\n# Generate themes\n# \n\n\n\n\n# ruby -e 'puts File.read(\"thankyou\").split(\"\\n\").join(\", \")' > thankyou2\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/build/tasks/build.js",
    "content": "module.exports = function( grunt ) {\n\nvar path = require( \"path\" );\n\ngrunt.registerMultiTask( \"copy\", \"Copy files to destination folder and replace @VERSION with pkg.version\", function() {\n\tfunction replaceVersion( source ) {\n\t\treturn source.replace( /@VERSION/g, grunt.config( \"pkg.version\" ) );\n\t}\n\tfunction copyFile( src, dest ) {\n\t\tif ( /(js|css)$/.test( src ) ) {\n\t\t\tgrunt.file.copy( src, dest, {\n\t\t\t\tprocess: replaceVersion\n\t\t\t});\n\t\t} else {\n\t\t\tgrunt.file.copy( src, dest );\n\t\t}\n\t}\n\tvar files = grunt.file.expandFiles( this.file.src ),\n\t\ttarget = this.file.dest + \"/\",\n\t\tstrip = this.data.strip,\n\t\trenameCount = 0,\n\t\tfileName;\n\tif ( typeof strip === \"string\" ) {\n\t\tstrip = new RegExp( \"^\" + grunt.template.process( strip, grunt.config() ).replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" ) );\n\t}\n\tfiles.forEach(function( fileName ) {\n\t\tvar targetFile = strip ? fileName.replace( strip, \"\" ) : fileName;\n\t\tcopyFile( fileName, target + targetFile );\n\t});\n\tgrunt.log.writeln( \"Copied \" + files.length + \" files.\" );\n\tfor ( fileName in this.data.renames ) {\n\t\trenameCount += 1;\n\t\tcopyFile( fileName, target + grunt.template.process( this.data.renames[ fileName ], grunt.config() ) );\n\t}\n\tif ( renameCount ) {\n\t\tgrunt.log.writeln( \"Renamed \" + renameCount + \" files.\" );\n\t}\n});\n\n\ngrunt.registerMultiTask( \"zip\", \"Create a zip file for release\", function() {\n\t// TODO switch back to adm-zip for better cross-platform compability once it actually works\n\t// 0.1.3 works, but result can't be unzipped\n\t// its also a lot slower then zip program, probably due to how its used...\n\t// var files = grunt.file.expandFiles( \"dist/\" + this.file.src + \"/**/*\" );\n\t// grunt.log.writeln( \"Creating zip file \" + this.file.dest );\n\n\t//var AdmZip = require( \"adm-zip\" );\n\t//var zip = new AdmZip();\n\t//files.forEach(function( file ) {\n\t//\tgrunt.verbose.writeln( \"Zipping \" + file );\n\t//\t// rewrite file names from dist folder (created by build), drop the /dist part\n\t//\tzip.addFile(file.replace(/^dist/, \"\" ), fs.readFileSync( file ) );\n\t//});\n\t//zip.writeZip( \"dist/\" + this.file.dest );\n\t//grunt.log.writeln( \"Wrote \" + files.length + \" files to \" + this.file.dest );\n\n\tvar done = this.async(),\n\t\tdest = this.file.dest,\n\t\tsrc = grunt.template.process( this.file.src, grunt.config() );\n\tgrunt.utils.spawn({\n\t\tcmd: \"zip\",\n\t\targs: [ \"-r\", dest, src ],\n\t\topts: {\n\t\t\tcwd: 'dist'\n\t\t}\n\t}, function( err, result ) {\n\t\tif ( err ) {\n\t\t\tgrunt.log.error( err );\n\t\t\tdone();\n\t\t\treturn;\n\t\t}\n\t\tgrunt.log.writeln( \"Zipped \" + dest );\n\t\tdone();\n\t});\n});\n\ngrunt.registerMultiTask( \"md5\", \"Create list of md5 hashes for CDN uploads\", function() {\n\t// remove dest file before creating it, to make sure itself is not included\n\tif ( path.existsSync( this.file.dest ) ) {\n\t\tfs.unlinkSync( this.file.dest );\n\t}\n\tvar crypto = require( \"crypto\" ),\n\t\tdir = this.file.src + \"/\",\n\t\thashes = [];\n\tgrunt.file.expandFiles( dir + \"**/*\" ).forEach(function( fileName ) {\n\t\tvar hash = crypto.createHash( \"md5\" );\n\t\thash.update( grunt.file.read( fileName, \"ascii\" ) );\n\t\thashes.push( fileName.replace( dir, \"\" ) + \" \" + hash.digest( \"hex\" ) );\n\t});\n\tgrunt.file.write( this.file.dest, hashes.join( \"\\n\" ) + \"\\n\" );\n\tgrunt.log.writeln( \"Wrote \" + this.file.dest + \" with \" + hashes.length + \" hashes\" );\n});\n\n// only needed for 1.8\ngrunt.registerTask( \"download_docs\", function() {\n\tfunction capitalize(value) {\n\t\treturn value[0].toUpperCase() + value.slice(1);\n\t}\n\t// should be grunt.config(\"pkg.version\")?\n\tvar version = \"1.8\",\n\t\tdocsDir = \"dist/docs\",\n\t\tfiles = \"draggable droppable resizable selectable sortable accordion autocomplete button datepicker dialog progressbar slider tabs position\"\n\t\t.split(\" \").map(function(widget) {\n\t\t\treturn {\n\t\t\t\turl: \"http://docs.jquery.com/action/render/UI/API/\" + version + \"/\" + capitalize(widget),\n\t\t\t\tdest: docsDir + '/' + widget + '.html'\n\t\t\t};\n\t\t});\n\tfiles = files.concat(\"animate addClass effect hide removeClass show switchClass toggle toggleClass\".split(\" \").map(function(widget) {\n\t\treturn {\n\t\t\turl: \"http://docs.jquery.com/action/render/UI/Effects/\" + widget,\n\t\t\tdest: docsDir + '/' + widget + '.html'\n\t\t};\n\t}));\n\tfiles = files.concat(\"Blind Clip Drop Explode Fade Fold Puff Slide Scale Bounce Highlight Pulsate Shake Size Transfer\".split(\" \").map(function(widget) {\n\t\treturn {\n\t\t\turl: \"http://docs.jquery.com/action/render/UI/Effects/\" + widget,\n\t\t\tdest: docsDir + '/effect-' + widget.toLowerCase() + '.html'\n\t\t};\n\t}));\n\tgrunt.file.mkdir( \"dist/docs\" );\n\tgrunt.utils.async.forEach( files, function( file, done ) {\n\t\tvar out = fs.createWriteStream( file.dest );\n\t\tout.on( \"close\", done );\n\t\trequest( file.url ).pipe( out );\n\t}, this.async() );\n});\n\ngrunt.registerTask( \"download_themes\", function() {\n\t// var AdmZip = require('adm-zip');\n\tvar done = this.async(),\n\t\tthemes = grunt.file.read( \"build/themes\" ).split(\",\"),\n\t\trequests = 0;\n\tgrunt.file.mkdir( \"dist/tmp\" );\n\tthemes.forEach(function( theme, index ) {\n\t\trequests += 1;\n\t\tgrunt.file.mkdir( \"dist/tmp/\" + index );\n\t\tvar zipFileName = \"dist/tmp/\" + index + \".zip\",\n\t\t\tout = fs.createWriteStream( zipFileName );\n\t\tout.on( \"close\", function() {\n\t\t\tgrunt.log.writeln( \"done downloading \" + zipFileName );\n\t\t\t// TODO AdmZip produces \"crc32 checksum failed\", need to figure out why\n\t\t\t// var zip = new AdmZip(zipFileName);\n\t\t\t// zip.extractAllTo('dist/tmp/' + index + '/');\n\t\t\t// until then, using cli unzip...\n\t\t\tgrunt.utils.spawn({\n\t\t\t\tcmd: \"unzip\",\n\t\t\t\targs: [ \"-d\", \"dist/tmp/\" + index, zipFileName ]\n\t\t\t}, function( err, result ) {\n\t\t\t\tgrunt.log.writeln( \"Unzipped \" + zipFileName + \", deleting it now\" );\n\t\t\t\tfs.unlinkSync( zipFileName );\n\t\t\t\trequests -= 1;\n\t\t\t\tif (requests === 0) {\n\t\t\t\t\tdone();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\trequest( \"http://ui-dev.jquery.com/download/?\" + theme ).pipe( out );\n\t});\n});\n\ngrunt.registerTask( \"copy_themes\", function() {\n\t// each package includes the base theme, ignore that\n\tvar filter = /themes\\/base/,\n\t\tfiles = grunt.file.expandFiles( \"dist/tmp/*/development-bundle/themes/**/*\" ).filter(function( file ) {\n\t\t\treturn !filter.test( file );\n\t\t}),\n\t\t// TODO the grunt.template.process call shouldn't be necessary\n\t\ttarget = \"dist/\" + grunt.template.process( grunt.config( \"files.themes\" ), grunt.config() ) + \"/\",\n\t\tdistFolder = \"dist/\" + grunt.template.process( grunt.config( \"files.dist\" ), grunt.config() );\n\tfiles.forEach(function( fileName ) {\n\t\tvar targetFile = fileName.replace( /dist\\/tmp\\/\\d+\\/development-bundle\\//, \"\" ).replace( \"jquery-ui-.custom\", \"jquery-ui\" );\n\t\tgrunt.file.copy( fileName, target + targetFile );\n\t});\n\n\t// copy minified base theme from regular release\n\tfiles = grunt.file.expandFiles( distFolder + \"/themes/base/**/*\" );\n\tfiles.forEach(function( fileName ) {\n\t\tgrunt.file.copy( fileName, target + fileName.replace( distFolder, \"\" ) );\n\t});\n});\n\ngrunt.registerTask( \"clean\", function() {\n\trequire( \"rimraf\" ).sync( \"dist\" );\n});\n\ngrunt.registerTask( \"authors\", function() {\n\tvar done = this.async();\n\n\tgrunt.utils.spawn({\n\t\tcmd: \"git\",\n\t\targs: [ \"log\", \"--pretty=%an <%ae>\" ]\n\t}, function( err, result ) {\n\t\tif ( err ) {\n\t\t\tgrunt.log.error( err );\n\t\t\treturn done( false );\n\t\t}\n\n\t\tvar authors,\n\t\t\ttracked = {};\n\t\tauthors = result.split( \"\\n\" ).reverse().filter(function( author ) {\n\t\t\tvar first = !tracked[ author ];\n\t\t\ttracked[ author ] = true;\n\t\t\treturn first;\n\t\t}).join( \"\\n\" );\n\t\tgrunt.log.writeln( authors );\n\t\tdone();\n\t});\n});\n\n};"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/build/tasks/testswarm.js",
    "content": "module.exports = function( grunt ) {\n\ngrunt.registerTask( \"testswarm\", function( commit, configFile ) {\n\tvar test,\n\t\ttestswarm = require( \"testswarm\" ),\n\t\tconfig = grunt.file.readJSON( configFile ).jqueryui,\n\t\ttestBase = \"http://swarm.jquery.org/git/jquery-ui/\" + commit + \"/tests/unit/\",\n\t\ttestUrls = [],\n\t\ttests = {\n\t\t\t\"Accordion\": \"accordion/accordion.html\",\n\t\t\t\"Accordion_deprecated\": \"accordion/accordion_deprecated.html\",\n\t\t\t\"Autocomplete\": \"autocomplete/autocomplete.html\",\n\t\t\t\"Button\": \"button/button.html\",\n\t\t\t\"Core\": \"core/core.html\",\n\t\t\t//\"datepicker/datepicker.html\",\n\t\t\t//\"dialog/dialog.html\",\n\t\t\t//\"draggable/draggable.html\",\n\t\t\t//\"droppable/droppable.html\",\n\t\t\t\"Effects\": \"effects/effects.html\",\n\t\t\t\"Menu\": \"menu/menu.html\",\n\t\t\t\"Position\": \"position/position.html\",\n\t\t\t\"Position_deprecated\": \"position/position_deprecated.html\",\n\t\t\t\"Progressbar\": \"progressbar/progressbar.html\",\n\t\t\t//\"resizable/resizable.html\",\n\t\t\t//\"selectable/selectable.html\",\n\t\t\t//\"slider/slider.html\",\n\t\t\t//\"sortable/sortable.html\",\n\t\t\t\"Spinner\": \"spinner/spinner.html\",\n\t\t\t\"Tabs\": \"tabs/tabs.html\",\n\t\t\t\"Tabs_deprecated\": \"tabs/tabs_deprecated.html\",\n\t\t\t\"Tooltip\": \"tooltip/tooltip.html\",\n\t\t\t\"Widget\": \"widget/widget.html\"\n\t\t};\n\tfor ( test in tests ) {\n\t\ttestUrls.push( testBase + tests[ test ] + \"?nojshint=true\" );\n\t}\n\ttestswarm({\n\t\turl: \"http://swarm.jquery.org/\",\n\t\tpollInterval: 10000,\n\t\ttimeout: 1000 * 60 * 30,\n\t\tdone: this.async()\n\t}, {\n\t\tauthUsername: \"jqueryui\",\n\t\tauthToken: config.authToken,\n\t\tjobName: 'jQuery UI commit #<a href=\"https://github.com/jquery/jquery-ui/commit/' + commit + '\">' + commit.substr( 0, 10 ) + '</a>',\n\t\trunMax: config.runMax,\n\t\t\"runNames[]\": Object.keys(tests),\n\t\t\"runUrls[]\": testUrls,\n\t\t\"browserSets[]\": [\"popular\"]\n\t});\n});\n\n};\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/build/themes",
    "content": "download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DTrebuchet%2BMS%2C%2BTahoma%2C%2BVerdana%2C%2BArial%2C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D4px%26bgColorHeader%3Df6a828%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D35%26borderColorHeader%3De78f08%26fcHeader%3Dffffff%26iconColorHeader%3Dffffff%26bgColorContent%3Deeeeee%26bgTextureContent%3D03_highlight_soft.png%26bgImgOpacityContent%3D100%26borderColorContent%3Ddddddd%26fcContent%3D333333%26iconColorContent%3D222222%26bgColorDefault%3Df6f6f6%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D100%26borderColorDefault%3Dcccccc%26fcDefault%3D1c94c4%26iconColorDefault%3Def8c08%26bgColorHover%3Dfdf5ce%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D100%26borderColorHover%3Dfbcb09%26fcHover%3Dc77405%26iconColorHover%3Def8c08%26bgColorActive%3Dffffff%26bgTextureActive%3D02_glass.png%26bgImgOpacityActive%3D65%26borderColorActive%3Dfbd850%26fcActive%3Deb8f00%26iconColorActive%3Def8c08%26bgColorHighlight%3Dffe45c%26bgTextureHighlight%3D03_highlight_soft.png%26bgImgOpacityHighlight%3D75%26borderColorHighlight%3Dfed22f%26fcHighlight%3D363636%26iconColorHighlight%3D228ef1%26bgColorError%3Db81900%26bgTextureError%3D08_diagonals_thick.png%26bgImgOpacityError%3D18%26borderColorError%3Dcd0a0a%26fcError%3Dffffff%26iconColorError%3Dffd27a%26bgColorOverlay%3D666666%26bgTextureOverlay%3D08_diagonals_thick.png%26bgImgOpacityOverlay%3D20%26opacityOverlay%3D50%26bgColorShadow%3D000000%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D10%26opacityShadow%3D20%26thicknessShadow%3D5px%26offsetTopShadow%3D-5px%26offsetLeftShadow%3D-5px%26cornerRadiusShadow%3D5px&scope=&t-name=ui-lightness&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DSegoe%2BUI%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3D333333%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D25%26borderColorHeader%3D333333%26fcHeader%3Dffffff%26iconColorHeader%3Dffffff%26bgColorContent%3D000000%26bgTextureContent%3D05_inset_soft.png%26bgImgOpacityContent%3D25%26borderColorContent%3D666666%26fcContent%3Dffffff%26iconColorContent%3Dcccccc%26bgColorDefault%3D555555%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D20%26borderColorDefault%3D666666%26fcDefault%3Deeeeee%26iconColorDefault%3Dcccccc%26bgColorHover%3D0078a3%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D40%26borderColorHover%3D59b4d4%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3Df58400%26bgTextureActive%3D05_inset_soft.png%26bgImgOpacityActive%3D30%26borderColorActive%3Dffaf0f%26fcActive%3Dffffff%26iconColorActive%3D222222%26bgColorHighlight%3Deeeeee%26bgTextureHighlight%3D03_highlight_soft.png%26bgImgOpacityHighlight%3D80%26borderColorHighlight%3Dcccccc%26fcHighlight%3D2e7db2%26iconColorHighlight%3D4b8e0b%26bgColorError%3Dffc73d%26bgTextureError%3D02_glass.png%26bgImgOpacityError%3D40%26borderColorError%3Dffb73d%26fcError%3D111111%26iconColorError%3Da83300%26bgColorOverlay%3D5c5c5c%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D50%26opacityOverlay%3D80%26bgColorShadow%3Dcccccc%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D30%26opacityShadow%3D60%26thicknessShadow%3D7px%26offsetTopShadow%3D-7px%26offsetLeftShadow%3D-7px%26cornerRadiusShadow%3D8px&scope=&t-name=ui-darkness&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DVerdana%2CArial%2Csans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1em%26cornerRadius%3D4px%26bgColorHeader%3Dcccccc%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D75%26borderColorHeader%3Daaaaaa%26fcHeader%3D222222%26iconColorHeader%3D222222%26bgColorContent%3Dffffff%26bgTextureContent%3D01_flat.png%26bgImgOpacityContent%3D75%26borderColorContent%3Daaaaaa%26fcContent%3D222222%26iconColorContent%3D222222%26bgColorDefault%3De6e6e6%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D75%26borderColorDefault%3Dd3d3d3%26fcDefault%3D555555%26iconColorDefault%3D888888%26bgColorHover%3Ddadada%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D75%26borderColorHover%3D999999%26fcHover%3D212121%26iconColorHover%3D454545%26bgColorActive%3Dffffff%26bgTextureActive%3D02_glass.png%26bgImgOpacityActive%3D65%26borderColorActive%3Daaaaaa%26fcActive%3D212121%26iconColorActive%3D454545%26bgColorHighlight%3Dfbf9ee%26bgTextureHighlight%3D02_glass.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dfcefa1%26fcHighlight%3D363636%26iconColorHighlight%3D2e83ff%26bgColorError%3Dfef1ec%26bgTextureError%3D02_glass.png%26bgImgOpacityError%3D95%26borderColorError%3Dcd0a0a%26fcError%3Dcd0a0a%26iconColorError%3Dcd0a0a%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D30%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=smoothness&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DVerdana%252CArial%252Csans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1em%26cornerRadius%3D5px%26bgColorHeader%3D2191c0%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D75%26borderColorHeader%3D4297d7%26fcHeader%3Deaf5f7%26iconColorHeader%3Dd8e7f3%26bgColorContent%3Dfcfdfd%26bgTextureContent%3D06_inset_hard.png%26bgImgOpacityContent%3D100%26borderColorContent%3Da6c9e2%26fcContent%3D222222%26iconColorContent%3D0078ae%26bgColorDefault%3D0078ae%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D45%26borderColorDefault%3D77d5f7%26fcDefault%3Dffffff%26iconColorDefault%3De0fdff%26bgColorHover%3D79c9ec%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D75%26borderColorHover%3D448dae%26fcHover%3D026890%26iconColorHover%3D056b93%26bgColorActive%3D6eac2c%26bgTextureActive%3D12_gloss_wave.png%26bgImgOpacityActive%3D50%26borderColorActive%3Dacdd4a%26fcActive%3Dffffff%26iconColorActive%3Df5e175%26bgColorHighlight%3Df8da4e%26bgTextureHighlight%3D02_glass.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dfcd113%26fcHighlight%3D915608%26iconColorHighlight%3Df7a50d%26bgColorError%3De14f1c%26bgTextureError%3D12_gloss_wave.png%26bgImgOpacityError%3D45%26borderColorError%3Dcd0a0a%26fcError%3Dffffff%26iconColorError%3Dfcd113%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D75%26opacityOverlay%3D30%26bgColorShadow%3D999999%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D55%26opacityShadow%3D45%26thicknessShadow%3D0px%26offsetTopShadow%3D5px%26offsetLeftShadow%3D5px%26cornerRadiusShadow%3D5px&scope=&t-name=start&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DLucida%2BGrande%2C%2BLucida%2BSans%2C%2BArial%2C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D5px%26bgColorHeader%3D5c9ccc%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D55%26borderColorHeader%3D4297d7%26fcHeader%3Dffffff%26iconColorHeader%3Dd8e7f3%26bgColorContent%3Dfcfdfd%26bgTextureContent%3D06_inset_hard.png%26bgImgOpacityContent%3D100%26borderColorContent%3Da6c9e2%26fcContent%3D222222%26iconColorContent%3D469bdd%26bgColorDefault%3Ddfeffc%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D85%26borderColorDefault%3Dc5dbec%26fcDefault%3D2e6e9e%26iconColorDefault%3D6da8d5%26bgColorHover%3Dd0e5f5%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D75%26borderColorHover%3D79b7e7%26fcHover%3D1d5987%26iconColorHover%3D217bc0%26bgColorActive%3Df5f8f9%26bgTextureActive%3D06_inset_hard.png%26bgImgOpacityActive%3D100%26borderColorActive%3D79b7e7%26fcActive%3De17009%26iconColorActive%3Df9bd01%26bgColorHighlight%3Dfbec88%26bgTextureHighlight%3D01_flat.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dfad42e%26fcHighlight%3D363636%26iconColorHighlight%3D2e83ff%26bgColorError%3Dfef1ec%26bgTextureError%3D02_glass.png%26bgImgOpacityError%3D95%26borderColorError%3Dcd0a0a%26fcError%3Dcd0a0a%26iconColorError%3Dcd0a0a%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D30%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=redmond&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DSegoe%2BUI%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D8px%26bgColorHeader%3D817865%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D45%26borderColorHeader%3D494437%26fcHeader%3Dffffff%26iconColorHeader%3Dfadc7a%26bgColorContent%3Dfeeebd%26bgTextureContent%3D03_highlight_soft.png%26bgImgOpacityContent%3D100%26borderColorContent%3D8e846b%26fcContent%3D383838%26iconColorContent%3Dd19405%26bgColorDefault%3Dfece2f%26bgTextureDefault%3D12_gloss_wave.png%26bgImgOpacityDefault%3D60%26borderColorDefault%3Dd19405%26fcDefault%3D4c3000%26iconColorDefault%3D3d3d3d%26bgColorHover%3Dffdd57%26bgTextureHover%3D12_gloss_wave.png%26bgImgOpacityHover%3D70%26borderColorHover%3Da45b13%26fcHover%3D381f00%26iconColorHover%3Dbd7b00%26bgColorActive%3Dffffff%26bgTextureActive%3D05_inset_soft.png%26bgImgOpacityActive%3D30%26borderColorActive%3D655e4e%26fcActive%3D0074c7%26iconColorActive%3Deb990f%26bgColorHighlight%3Dfff9e5%26bgTextureHighlight%3D12_gloss_wave.png%26bgImgOpacityHighlight%3D90%26borderColorHighlight%3Deeb420%26fcHighlight%3D1f1f1f%26iconColorHighlight%3Ded9f26%26bgColorError%3Dd34d17%26bgTextureError%3D07_diagonals_medium.png%26bgImgOpacityError%3D20%26borderColorError%3Dffb73d%26fcError%3Dffffff%26iconColorError%3Dffe180%26bgColorOverlay%3D5c5c5c%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D50%26opacityOverlay%3D80%26bgColorShadow%3Dcccccc%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D30%26opacityShadow%3D60%26thicknessShadow%3D7px%26offsetTopShadow%3D-7px%26offsetLeftShadow%3D-7px%26cornerRadiusShadow%3D8px&scope=&t-name=sunny&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DTrebuchet%2BMS%252C%2BHelvetica%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3Ddddddd%26bgTextureHeader%3D02_glass.png%26bgImgOpacityHeader%3D35%26borderColorHeader%3Dbbbbbb%26fcHeader%3D444444%26iconColorHeader%3D999999%26bgColorContent%3Dc9c9c9%26bgTextureContent%3D05_inset_soft.png%26bgImgOpacityContent%3D50%26borderColorContent%3Daaaaaa%26fcContent%3D333333%26iconColorContent%3D999999%26bgColorDefault%3Deeeeee%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D60%26borderColorDefault%3Dcccccc%26fcDefault%3D3383bb%26iconColorDefault%3D70b2e1%26bgColorHover%3Df8f8f8%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D100%26borderColorHover%3Dbbbbbb%26fcHover%3D599fcf%26iconColorHover%3D3383bb%26bgColorActive%3D999999%26bgTextureActive%3D06_inset_hard.png%26bgImgOpacityActive%3D75%26borderColorActive%3D999999%26fcActive%3Dffffff%26iconColorActive%3D454545%26bgColorHighlight%3Deeeeee%26bgTextureHighlight%3D01_flat.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dffffff%26fcHighlight%3D444444%26iconColorHighlight%3D3383bb%26bgColorError%3Dc0402a%26bgTextureError%3D01_flat.png%26bgImgOpacityError%3D55%26borderColorError%3Dc0402a%26fcError%3Dffffff%26iconColorError%3Dfbc856%26bgColorOverlay%3Deeeeee%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D80%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D60%26thicknessShadow%3D4px%26offsetTopShadow%3D-4px%26offsetLeftShadow%3D-4px%26cornerRadiusShadow%3D0pxdow%253D0px&scope=&t-name=overcast&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DLucida%2BGrande%252C%2BLucida%2BSans%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1em%26cornerRadius%3D10px%26bgColorHeader%3D3a8104%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D33%26borderColorHeader%3D3f7506%26fcHeader%3Dffffff%26iconColorHeader%3Dffffff%26bgColorContent%3D285c00%26bgTextureContent%3D05_inset_soft.png%26bgImgOpacityContent%3D10%26borderColorContent%3D72b42d%26fcContent%3Dffffff%26iconColorContent%3D72b42d%26bgColorDefault%3D4ca20b%26bgTextureDefault%3D03_highlight_soft.png%26bgImgOpacityDefault%3D60%26borderColorDefault%3D45930b%26fcDefault%3Dffffff%26iconColorDefault%3Dffffff%26bgColorHover%3D4eb305%26bgTextureHover%3D03_highlight_soft.png%26bgImgOpacityHover%3D50%26borderColorHover%3D8bd83b%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3D285c00%26bgTextureActive%3D04_highlight_hard.png%26bgImgOpacityActive%3D30%26borderColorActive%3D72b42d%26fcActive%3Dffffff%26iconColorActive%3Dffffff%26bgColorHighlight%3Dfbf5d0%26bgTextureHighlight%3D02_glass.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Df9dd34%26fcHighlight%3D363636%26iconColorHighlight%3D4eb305%26bgColorError%3Dffdc2e%26bgTextureError%3D08_diagonals_thick.png%26bgImgOpacityError%3D95%26borderColorError%3Dfad000%26fcError%3D2b2b2b%26iconColorError%3Dcd0a0a%26bgColorOverlay%3D444444%26bgTextureOverlay%3D08_diagonals_thick.png%26bgImgOpacityOverlay%3D15%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D07_diagonals_small.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D30%26thicknessShadow%3D0px%26offsetTopShadow%3D4px%26offsetLeftShadow%3D4px%26cornerRadiusShadow%3D4px&scope=&t-name=le-frog&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DHelvetica%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D2px%26bgColorHeader%3Ddddddd%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D50%26borderColorHeader%3Ddddddd%26fcHeader%3D444444%26iconColorHeader%3D0073ea%26bgColorContent%3Dffffff%26bgTextureContent%3D01_flat.png%26bgImgOpacityContent%3D75%26borderColorContent%3Ddddddd%26fcContent%3D444444%26iconColorContent%3Dff0084%26bgColorDefault%3Df6f6f6%26bgTextureDefault%3D03_highlight_soft.png%26bgImgOpacityDefault%3D100%26borderColorDefault%3Ddddddd%26fcDefault%3D0073ea%26iconColorDefault%3D666666%26bgColorHover%3D0073ea%26bgTextureHover%3D03_highlight_soft.png%26bgImgOpacityHover%3D25%26borderColorHover%3D0073ea%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3Dffffff%26bgTextureActive%3D02_glass.png%26bgImgOpacityActive%3D65%26borderColorActive%3Ddddddd%26fcActive%3Dff0084%26iconColorActive%3D454545%26bgColorHighlight%3Dffffff%26bgTextureHighlight%3D01_flat.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dcccccc%26fcHighlight%3D444444%26iconColorHighlight%3D0073ea%26bgColorError%3Dffffff%26bgTextureError%3D01_flat.png%26bgImgOpacityError%3D55%26borderColorError%3Dff0084%26fcError%3D222222%26iconColorError%3Dff0084%26bgColorOverlay%3Deeeeee%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D80%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D60%26thicknessShadow%3D4px%26offsetTopShadow%3D-4px%26offsetLeftShadow%3D-4px%26cornerRadiusShadow%3D0px&scope=&t-name=flick&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DTrebuchet%2BMS%252C%2BTahoma%252C%2BVerdana%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3Dffffff%26bgTextureHeader%3D23_fine_grain.png%26bgImgOpacityHeader%3D15%26borderColorHeader%3Dd4d1bf%26fcHeader%3D453821%26iconColorHeader%3Db83400%26bgColorContent%3Deceadf%26bgTextureContent%3D23_fine_grain.png%26bgImgOpacityContent%3D10%26borderColorContent%3Dd9d6c4%26fcContent%3D1f1f1f%26iconColorContent%3D222222%26bgColorDefault%3Df8f7f6%26bgTextureDefault%3D23_fine_grain.png%26bgImgOpacityDefault%3D10%26borderColorDefault%3Dcbc7bd%26fcDefault%3D654b24%26iconColorDefault%3Db83400%26bgColorHover%3D654b24%26bgTextureHover%3D23_fine_grain.png%26bgImgOpacityHover%3D65%26borderColorHover%3D654b24%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3Deceadf%26bgTextureActive%3D23_fine_grain.png%26bgImgOpacityActive%3D15%26borderColorActive%3Dd9d6c4%26fcActive%3D140f06%26iconColorActive%3D8c291d%26bgColorHighlight%3Df7f3de%26bgTextureHighlight%3D23_fine_grain.png%26bgImgOpacityHighlight%3D15%26borderColorHighlight%3Db2a266%26fcHighlight%3D3a3427%26iconColorHighlight%3D3572ac%26bgColorError%3Db83400%26bgTextureError%3D23_fine_grain.png%26bgImgOpacityError%3D68%26borderColorError%3D681818%26fcError%3Dffffff%26iconColorError%3Dfbdb93%26bgColorOverlay%3D6e4f1c%26bgTextureOverlay%3D16_diagonal_maze.png%26bgImgOpacityOverlay%3D20%26opacityOverlay%3D60%26bgColorShadow%3D000000%26bgTextureShadow%3D16_diagonal_maze.png%26bgImgOpacityShadow%3D40%26opacityShadow%3D60%26thicknessShadow%3D5px%26offsetTopShadow%3D0%26offsetLeftShadow%3D-10px%26cornerRadiusShadow%3D18px&scope=&t-name=pepper-grinder&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DLucida%2BGrande%252C%2BLucida%2BSans%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3D30273a%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D25%26borderColorHeader%3D231d2b%26fcHeader%3Dffffff%26iconColorHeader%3Da8a3ae%26bgColorContent%3D3d3644%26bgTextureContent%3D12_gloss_wave.png%26bgImgOpacityContent%3D30%26borderColorContent%3D7e7783%26fcContent%3Dffffff%26iconColorContent%3Dffffff%26bgColorDefault%3Ddcd9de%26bgTextureDefault%3D03_highlight_soft.png%26bgImgOpacityDefault%3D100%26borderColorDefault%3Ddcd9de%26fcDefault%3D665874%26iconColorDefault%3D8d78a5%26bgColorHover%3Deae6ea%26bgTextureHover%3D03_highlight_soft.png%26bgImgOpacityHover%3D100%26borderColorHover%3Dd1c5d8%26fcHover%3D734d99%26iconColorHover%3D734d99%26bgColorActive%3D5f5964%26bgTextureActive%3D03_highlight_soft.png%26bgImgOpacityActive%3D45%26borderColorActive%3D7e7783%26fcActive%3Dffffff%26iconColorActive%3D454545%26bgColorHighlight%3Dfafafa%26bgTextureHighlight%3D01_flat.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dffdb1f%26fcHighlight%3D333333%26iconColorHighlight%3D8d78a5%26bgColorError%3D994d53%26bgTextureError%3D01_flat.png%26bgImgOpacityError%3D55%26borderColorError%3D994d53%26fcError%3Dffffff%26iconColorError%3Debccce%26bgColorOverlay%3Deeeeee%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D80%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D60%26thicknessShadow%3D4px%26offsetTopShadow%3D-4px%26offsetLeftShadow%3D-4px%26cornerRadiusShadow%3D0px&scope=&t-name=eggplant&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DVerdana%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3D444444%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D44%26borderColorHeader%3D333333%26fcHeader%3Dffffff%26iconColorHeader%3Dffffff%26bgColorContent%3D000000%26bgTextureContent%3D14_loop.png%26bgImgOpacityContent%3D25%26borderColorContent%3D555555%26fcContent%3Dffffff%26iconColorContent%3Dcccccc%26bgColorDefault%3D222222%26bgTextureDefault%3D03_highlight_soft.png%26bgImgOpacityDefault%3D35%26borderColorDefault%3D444444%26fcDefault%3Deeeeee%26iconColorDefault%3Dcccccc%26bgColorHover%3D003147%26bgTextureHover%3D03_highlight_soft.png%26bgImgOpacityHover%3D33%26borderColorHover%3D0b93d5%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3D0972a5%26bgTextureActive%3D04_highlight_hard.png%26bgImgOpacityActive%3D20%26borderColorActive%3D26b3f7%26fcActive%3Dffffff%26iconColorActive%3D222222%26bgColorHighlight%3Deeeeee%26bgTextureHighlight%3D03_highlight_soft.png%26bgImgOpacityHighlight%3D80%26borderColorHighlight%3Dcccccc%26fcHighlight%3D2e7db2%26iconColorHighlight%3D4b8e0b%26bgColorError%3Dffc73d%26bgTextureError%3D02_glass.png%26bgImgOpacityError%3D40%26borderColorError%3Dffb73d%26fcError%3D111111%26iconColorError%3Da83300%26bgColorOverlay%3D5c5c5c%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D50%26opacityOverlay%3D80%26bgColorShadow%3Dcccccc%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D30%26opacityShadow%3D60%26thicknessShadow%3D7px%26offsetTopShadow%3D-7px%26offsetLeftShadow%3D-7px%26cornerRadiusShadow%3D8px&scope=&t-name=dark-hive&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DLucida%2BGrande%252C%2BLucida%2BSans%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3Ddeedf7%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D100%26borderColorHeader%3Daed0ea%26fcHeader%3D222222%26iconColorHeader%3D72a7cf%26bgColorContent%3Df2f5f7%26bgTextureContent%3D04_highlight_hard.png%26bgImgOpacityContent%3D100%26borderColorContent%3Ddddddd%26fcContent%3D362b36%26iconColorContent%3D72a7cf%26bgColorDefault%3Dd7ebf9%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D80%26borderColorDefault%3Daed0ea%26fcDefault%3D2779aa%26iconColorDefault%3D3d80b3%26bgColorHover%3De4f1fb%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D100%26borderColorHover%3D74b2e2%26fcHover%3D0070a3%26iconColorHover%3D2694e8%26bgColorActive%3D3baae3%26bgTextureActive%3D02_glass.png%26bgImgOpacityActive%3D50%26borderColorActive%3D2694e8%26fcActive%3Dffffff%26iconColorActive%3Dffffff%26bgColorHighlight%3Dffef8f%26bgTextureHighlight%3D03_highlight_soft.png%26bgImgOpacityHighlight%3D25%26borderColorHighlight%3Df9dd34%26fcHighlight%3D363636%26iconColorHighlight%3D2e83ff%26bgColorError%3Dcd0a0a%26bgTextureError%3D01_flat.png%26bgImgOpacityError%3D15%26borderColorError%3Dcd0a0a%26fcError%3Dffffff%26iconColorError%3Dffffff%26bgColorOverlay%3Deeeeee%26bgTextureOverlay%3D08_diagonals_thick.png%26bgImgOpacityOverlay%3D90%26opacityOverlay%3D80%26bgColorShadow%3D000000%26bgTextureShadow%3D04_highlight_hard.png%26bgImgOpacityShadow%3D70%26opacityShadow%3D30%26thicknessShadow%3D7px%26offsetTopShadow%3D-7px%26offsetLeftShadow%3D-7px%26cornerRadiusShadow%3D8px&scope=&t-name=cupertino&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3Dsegoe%2Bui%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3Dece8da%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D100%26borderColorHeader%3Dd4ccb0%26fcHeader%3D433f38%26iconColorHeader%3D847e71%26bgColorContent%3Df5f3e5%26bgTextureContent%3D04_highlight_hard.png%26bgImgOpacityContent%3D100%26borderColorContent%3Ddfd9c3%26fcContent%3D312e25%26iconColorContent%3D808080%26bgColorDefault%3D459e00%26bgTextureDefault%3D04_highlight_hard.png%26bgImgOpacityDefault%3D15%26borderColorDefault%3D327E04%26fcDefault%3Dffffff%26iconColorDefault%3Deeeeee%26bgColorHover%3D67b021%26bgTextureHover%3D03_highlight_soft.png%26bgImgOpacityHover%3D25%26borderColorHover%3D327E04%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3Dfafaf4%26bgTextureActive%3D04_highlight_hard.png%26bgImgOpacityActive%3D100%26borderColorActive%3Dd4ccb0%26fcActive%3D459e00%26iconColorActive%3D8DC262%26bgColorHighlight%3Dfcf0ba%26bgTextureHighlight%3D02_glass.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3De8e1b5%26fcHighlight%3D363636%26iconColorHighlight%3D8DC262%26bgColorError%3Dffedad%26bgTextureError%3D03_highlight_soft.png%26bgImgOpacityError%3D95%26borderColorError%3De3a345%26fcError%3Dcd5c0a%26iconColorError%3Dcd0a0a%26bgColorOverlay%3D2b2922%26bgTextureOverlay%3D05_inset_soft.png%26bgImgOpacityOverlay%3D15%26opacityOverlay%3D90%26bgColorShadow%3Dcccccc%26bgTextureShadow%3D04_highlight_hard.png%26bgImgOpacityShadow%3D95%26opacityShadow%3D20%26thicknessShadow%3D12px%26offsetTopShadow%3D-12px%26offsetLeftShadow%3D-12px%26cornerRadiusShadow%3D10px&scope=&t-name=south-street&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DArial%2Csans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3Dcc0000%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D15%26borderColorHeader%3De3a1a1%26fcHeader%3Dffffff%26iconColorHeader%3Dffffff%26bgColorContent%3Dffffff%26bgTextureContent%3D01_flat.png%26bgImgOpacityContent%3D75%26borderColorContent%3Deeeeee%26fcContent%3D333333%26iconColorContent%3Dcc0000%26bgColorDefault%3Deeeeee%26bgTextureDefault%3D04_highlight_hard.png%26bgImgOpacityDefault%3D100%26borderColorDefault%3Dd8dcdf%26fcDefault%3D004276%26iconColorDefault%3Dcc0000%26bgColorHover%3Df6f6f6%26bgTextureHover%3D04_highlight_hard.png%26bgImgOpacityHover%3D100%26borderColorHover%3Dcdd5da%26fcHover%3D111111%26iconColorHover%3Dcc0000%26bgColorActive%3Dffffff%26bgTextureActive%3D01_flat.png%26bgImgOpacityActive%3D65%26borderColorActive%3Deeeeee%26fcActive%3Dcc0000%26iconColorActive%3Dcc0000%26bgColorHighlight%3Dfbf8ee%26bgTextureHighlight%3D02_glass.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dfcd3a1%26fcHighlight%3D444444%26iconColorHighlight%3D004276%26bgColorError%3Df3d8d8%26bgTextureError%3D08_diagonals_thick.png%26bgImgOpacityError%3D75%26borderColorError%3Dcc0000%26fcError%3D2e2e2e%26iconColorError%3Dcc0000%26bgColorOverlay%3Da6a6a6%26bgTextureOverlay%3D09_dots_small.png%26bgImgOpacityOverlay%3D65%26opacityOverlay%3D40%26bgColorShadow%3D333333%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D10%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=blitzer&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3Ftr%3DffDefault%3DHelvetica%2CArial%2Csans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3Dcb842e%26bgTextureHeader%3D02_glass.png%26bgImgOpacityHeader%3D25%26borderColorHeader%3Dd49768%26fcHeader%3Dffffff%26iconColorHeader%3Dffffff%26bgColorContent%3Df4f0ec%26bgTextureContent%3D05_inset_soft.png%26bgImgOpacityContent%3D100%26borderColorContent%3De0cfc2%26fcContent%3D1e1b1d%26iconColorContent%3Dc47a23%26bgColorDefault%3Dede4d4%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D70%26borderColorDefault%3Dcdc3b7%26fcDefault%3D3f3731%26iconColorDefault%3Df08000%26bgColorHover%3Df5f0e5%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D100%26borderColorHover%3Df5ad66%26fcHover%3Da46313%26iconColorHover%3Df08000%26bgColorActive%3Df4f0ec%26bgTextureActive%3D04_highlight_hard.png%26bgImgOpacityActive%3D100%26borderColorActive%3De0cfc2%26fcActive%3Db85700%26iconColorActive%3Df35f07%26bgColorHighlight%3Df5f5b5%26bgTextureHighlight%3D04_highlight_hard.png%26bgImgOpacityHighlight%3D75%26borderColorHighlight%3Dd9bb73%26fcHighlight%3D060200%26iconColorHighlight%3Dcb672b%26bgColorError%3Dfee4bd%26bgTextureError%3D04_highlight_hard.png%26bgImgOpacityError%3D65%26borderColorError%3Df8893f%26fcError%3D592003%26iconColorError%3Dff7519%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D75%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D75%26opacityShadow%3D30%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=humanity&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DGill%2BSans%2CArial%2Csans-serif%26fwDefault%3Dbold%26fsDefault%3D1.2em%26cornerRadius%3D4px%26bgColorHeader%3D35414f%26bgTextureHeader%3D09_dots_small.png%26bgImgOpacityHeader%3D35%26borderColorHeader%3D2c4359%26fcHeader%3De1e463%26iconColorHeader%3De1e463%26bgColorContent%3Dffffff%26bgTextureContent%3D01_flat.png%26bgImgOpacityContent%3D75%26borderColorContent%3Daaaaaa%26fcContent%3D2c4359%26iconColorContent%3Dc02669%26bgColorDefault%3D93c3cd%26bgTextureDefault%3D07_diagonals_small.png%26bgImgOpacityDefault%3D50%26borderColorDefault%3D93c3cd%26fcDefault%3D333333%26iconColorDefault%3Dffffff%26bgColorHover%3Dccd232%26bgTextureHover%3D07_diagonals_small.png%26bgImgOpacityHover%3D75%26borderColorHover%3D999999%26fcHover%3D212121%26iconColorHover%3D454545%26bgColorActive%3Ddb4865%26bgTextureActive%3D07_diagonals_small.png%26bgImgOpacityActive%3D40%26borderColorActive%3Dff6b7f%26fcActive%3Dffffff%26iconColorActive%3Dffffff%26bgColorHighlight%3Dffff38%26bgTextureHighlight%3D10_dots_medium.png%26bgImgOpacityHighlight%3D80%26borderColorHighlight%3Db4d100%26fcHighlight%3D363636%26iconColorHighlight%3D88a206%26bgColorError%3Dff3853%26bgTextureError%3D07_diagonals_small.png%26bgImgOpacityError%3D50%26borderColorError%3Dff6b7f%26fcError%3Dffffff%26iconColorError%3Dffeb33%26bgColorOverlay%3Df7f7ba%26bgTextureOverlay%3D11_white_lines.png%26bgImgOpacityOverlay%3D85%26opacityOverlay%3D80%26bgColorShadow%3Dba9217%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D75%26opacityShadow%3D20%26thicknessShadow%3D10px%26offsetTopShadow%3D8px%26offsetLeftShadow%3D8px%26cornerRadiusShadow%3D5px&scope=&t-name=hot-sneaks&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3Dsegoe%2Bui%2C%2BArial%2C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D3px%26bgColorHeader%3Df9f9f9%26bgTextureHeader%3D03_highlight_soft.png%26bgImgOpacityHeader%3D100%26borderColorHeader%3Dcccccc%26fcHeader%3De69700%26iconColorHeader%3D5fa5e3%26bgColorContent%3Deeeeee%26bgTextureContent%3D06_inset_hard.png%26bgImgOpacityContent%3D100%26borderColorContent%3Daaaaaa%26fcContent%3D222222%26iconColorContent%3D0a82eb%26bgColorDefault%3D1484e6%26bgTextureDefault%3D08_diagonals_thick.png%26bgImgOpacityDefault%3D22%26borderColorDefault%3Dffffff%26fcDefault%3Dffffff%26iconColorDefault%3Dfcdd4a%26bgColorHover%3D2293f7%26bgTextureHover%3D08_diagonals_thick.png%26bgImgOpacityHover%3D26%26borderColorHover%3D2293f7%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3De69700%26bgTextureActive%3D08_diagonals_thick.png%26bgImgOpacityActive%3D20%26borderColorActive%3De69700%26fcActive%3Dffffff%26iconColorActive%3Dffffff%26bgColorHighlight%3Dc5ddfc%26bgTextureHighlight%3D07_diagonals_small.png%26bgImgOpacityHighlight%3D25%26borderColorHighlight%3Dffffff%26fcHighlight%3D333333%26iconColorHighlight%3D0b54d5%26bgColorError%3De69700%26bgTextureError%3D08_diagonals_thick.png%26bgImgOpacityError%3D20%26borderColorError%3De69700%26fcError%3Dffffff%26iconColorError%3Dffffff%26bgColorOverlay%3De6b900%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D30%26bgColorShadow%3De69700%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D20%26thicknessShadow%3D0px%26offsetTopShadow%3D6px%26offsetLeftShadow%3D6px%26cornerRadiusShadow%3D3px&scope=&t-name=excite-bike&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3Ftr%26ffDefault%3DHelvetica%2C%2BArial%2C%2Bsans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1%26fsDefaultUnit%3Dem%26cornerRadius%3D5%26cornerRadiusUnit%3Dpx%26bgColorHeader%3D888888%26bgTextureHeader%3D04_highlight_hard.png%26bgImgOpacityHeader%3D15%26borderColorHeader%3D404040%26fcHeader%3Dffffff%26iconColorHeader%3Dcccccc%26bgColorContent%3D121212%26bgTextureContent%3D12_gloss_wave.png%26bgImgOpacityContent%3D16%26borderColorContent%3D404040%26fcContent%3Deeeeee%26iconColorContent%3Dbbbbbb%26bgColorDefault%3Dadadad%26bgTextureDefault%3D03_highlight_soft.png%26bgImgOpacityDefault%3D35%26borderColorDefault%3Dcccccc%26fcDefault%3D333333%26iconColorDefault%3D666666%26bgColorHover%3Ddddddd%26bgTextureHover%3D03_highlight_soft.png%26bgImgOpacityHover%3D60%26borderColorHover%3Ddddddd%26fcHover%3D000000%26iconColorHover%3Dc98000%26bgColorActive%3D121212%26bgTextureActive%3D05_inset_soft.png%26bgImgOpacityActive%3D15%26borderColorActive%3D000000%26fcActive%3Dffffff%26iconColorActive%3Df29a00%26bgColorHighlight%3D555555%26bgTextureHighlight%3D04_highlight_hard.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3D404040%26fcHighlight%3Dcccccc%26iconColorHighlight%3Daaaaaa%26bgColorError%3Dfef1ec%26bgTextureError%3D02_glass.png%26bgImgOpacityError%3D95%26borderColorError%3Dcd0a0a%26fcError%3Dcd0a0a%26iconColorError%3Dcd0a0a&scope=&t-name=vader&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DArial%2C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.3em%26cornerRadius%3D4px%26bgColorHeader%3D0b3e6f%26bgTextureHeader%3D08_diagonals_thick.png%26bgImgOpacityHeader%3D15%26borderColorHeader%3D0b3e6f%26fcHeader%3Df6f6f6%26iconColorHeader%3D98d2fb%26bgColorContent%3D111111%26bgTextureContent%3D12_gloss_wave.png%26bgImgOpacityContent%3D20%26borderColorContent%3D000000%26fcContent%3Dd9d9d9%26iconColorContent%3D9ccdfc%26bgColorDefault%3D333333%26bgTextureDefault%3D09_dots_small.png%26bgImgOpacityDefault%3D20%26borderColorDefault%3D333333%26fcDefault%3Dffffff%26iconColorDefault%3D9ccdfc%26bgColorHover%3D00498f%26bgTextureHover%3D09_dots_small.png%26bgImgOpacityHover%3D40%26borderColorHover%3D222222%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3D292929%26bgTextureActive%3D01_flat.png%26bgImgOpacityActive%3D40%26borderColorActive%3D096ac8%26fcActive%3D75abff%26iconColorActive%3D00498f%26bgColorHighlight%3D0b58a2%26bgTextureHighlight%3D10_dots_medium.png%26bgImgOpacityHighlight%3D30%26borderColorHighlight%3D052f57%26fcHighlight%3Dffffff%26iconColorHighlight%3Dffffff%26bgColorError%3Da32d00%26bgTextureError%3D09_dots_small.png%26bgImgOpacityError%3D30%26borderColorError%3Dcd0a0a%26fcError%3Dffffff%26iconColorError%3Dffffff%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D30%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=dot-luv&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DSegoe%2BUI%252C%2BHelvetica%252C%2BArial%252C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D4px%26bgColorHeader%3D453326%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D25%26borderColorHeader%3D695649%26fcHeader%3De3ddc9%26iconColorHeader%3De3ddc9%26bgColorContent%3D201913%26bgTextureContent%3D05_inset_soft.png%26bgImgOpacityContent%3D10%26borderColorContent%3D9c947c%26fcContent%3Dffffff%26iconColorContent%3D222222%26bgColorDefault%3D1c160d%26bgTextureDefault%3D12_gloss_wave.png%26bgImgOpacityDefault%3D20%26borderColorDefault%3D695444%26fcDefault%3D9bcc60%26iconColorDefault%3D9bcc60%26bgColorHover%3D44372c%26bgTextureHover%3D12_gloss_wave.png%26bgImgOpacityHover%3D30%26borderColorHover%3D9c947c%26fcHover%3Dbaec7e%26iconColorHover%3Dadd978%26bgColorActive%3D201913%26bgTextureActive%3D03_highlight_soft.png%26bgImgOpacityActive%3D20%26borderColorActive%3D9c947c%26fcActive%3De3ddc9%26iconColorActive%3De3ddc9%26bgColorHighlight%3D619226%26bgTextureHighlight%3D03_highlight_soft.png%26bgImgOpacityHighlight%3D20%26borderColorHighlight%3Dadd978%26fcHighlight%3Dffffff%26iconColorHighlight%3Dffffff%26bgColorError%3D5f391b%26bgTextureError%3D02_glass.png%26bgImgOpacityError%3D15%26borderColorError%3D5f391b%26fcError%3Dffffff%26iconColorError%3Df1fd86%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D01_flat.png%26bgImgOpacityOverlay%3D0%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D30%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=mint-choc&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DVerdana%2C%2BArial%2C%2Bsans-serif%26fwDefault%3Dnormal%26fsDefault%3D1.1em%26cornerRadius%3D4px%26bgColorHeader%3D333333%26bgTextureHeader%3D08_diagonals_thick.png%26bgImgOpacityHeader%3D8%26borderColorHeader%3Da3a3a3%26fcHeader%3Deeeeee%26iconColorHeader%3Dbbbbbb%26bgColorContent%3Df9f9f9%26bgTextureContent%3D04_highlight_hard.png%26bgImgOpacityContent%3D100%26borderColorContent%3Dcccccc%26fcContent%3D222222%26iconColorContent%3D222222%26bgColorDefault%3D111111%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D40%26borderColorDefault%3D777777%26fcDefault%3De3e3e3%26iconColorDefault%3Dededed%26bgColorHover%3D1c1c1c%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D55%26borderColorHover%3D000000%26fcHover%3Dffffff%26iconColorHover%3Dffffff%26bgColorActive%3Dffffff%26bgTextureActive%3D01_flat.png%26bgImgOpacityActive%3D65%26borderColorActive%3Dcccccc%26fcActive%3D222222%26iconColorActive%3D222222%26bgColorHighlight%3Dffeb80%26bgTextureHighlight%3D06_inset_hard.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3Dffde2e%26fcHighlight%3D363636%26iconColorHighlight%3D4ca300%26bgColorError%3Dcd0a0a%26bgTextureError%3D06_inset_hard.png%26bgImgOpacityError%3D45%26borderColorError%3D9e0505%26fcError%3Dffffff%26iconColorError%3Dffcf29%26bgColorOverlay%3Daaaaaa%26bgTextureOverlay%3D04_highlight_hard.png%26bgImgOpacityOverlay%3D40%26opacityOverlay%3D30%26bgColorShadow%3Daaaaaa%26bgTextureShadow%3D03_highlight_soft.png%26bgImgOpacityShadow%3D50%26opacityShadow%3D20%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D8px&scope=&t-name=black-tie&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DSegoe%2BUI%2C%2BHelvetica%2C%2BArial%2C%2Bsans-serif%26fwDefault%3Dbold%26fsDefault%3D1.1em%26cornerRadius%3D6px%26bgColorHeader%3D9fda58%26bgTextureHeader%3D12_gloss_wave.png%26bgImgOpacityHeader%3D85%26borderColorHeader%3D000000%26fcHeader%3D222222%26iconColorHeader%3D1f1f1f%26bgColorContent%3D000000%26bgTextureContent%3D12_gloss_wave.png%26bgImgOpacityContent%3D55%26borderColorContent%3D4a4a4a%26fcContent%3Dffffff%26iconColorContent%3D9fda58%26bgColorDefault%3D0a0a0a%26bgTextureDefault%3D02_glass.png%26bgImgOpacityDefault%3D40%26borderColorDefault%3D1b1613%26fcDefault%3Db8ec79%26iconColorDefault%3Db8ec79%26bgColorHover%3D000000%26bgTextureHover%3D02_glass.png%26bgImgOpacityHover%3D60%26borderColorHover%3D000000%26fcHover%3D96f226%26iconColorHover%3Db8ec79%26bgColorActive%3D4c4c4c%26bgTextureActive%3D01_flat.png%26bgImgOpacityActive%3D0%26borderColorActive%3D696969%26fcActive%3Dffffff%26iconColorActive%3Dffffff%26bgColorHighlight%3Df1fbe5%26bgTextureHighlight%3D02_glass.png%26bgImgOpacityHighlight%3D55%26borderColorHighlight%3D8cce3b%26fcHighlight%3D030303%26iconColorHighlight%3D000000%26bgColorError%3Df6ecd5%26bgTextureError%3D12_gloss_wave.png%26bgImgOpacityError%3D95%26borderColorError%3Df1ac88%26fcError%3D74736d%26iconColorError%3Dcd0a0a%26bgColorOverlay%3D262626%26bgTextureOverlay%3D07_diagonals_small.png%26bgImgOpacityOverlay%3D50%26opacityOverlay%3D30%26bgColorShadow%3D303030%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D0%26opacityShadow%3D50%26thicknessShadow%3D6px%26offsetTopShadow%3D-6px%26offsetLeftShadow%3D-6px%26cornerRadiusShadow%3D12px&scope=&t-name=trontastic&ui-version=1.8.2,download=true&files%5B%5D=ui.core.js&files%5B%5D=ui.widget.js&files%5B%5D=ui.mouse.js&files%5B%5D=ui.position.js&files%5B%5D=ui.draggable.js&files%5B%5D=ui.droppable.js&files%5B%5D=ui.resizable.js&files%5B%5D=ui.selectable.js&files%5B%5D=ui.sortable.js&files%5B%5D=ui.accordion.js&files%5B%5D=ui.autocomplete.js&files%5B%5D=ui.button.js&files%5B%5D=ui.dialog.js&files%5B%5D=ui.slider.js&files%5B%5D=ui.tabs.js&files%5B%5D=ui.datepicker.js&files%5B%5D=ui.progressbar.js&files%5B%5D=effects.core.js&files%5B%5D=effects.blind.js&files%5B%5D=effects.bounce.js&files%5B%5D=effects.clip.js&files%5B%5D=effects.drop.js&files%5B%5D=effects.explode.js&files%5B%5D=effects.fold.js&files%5B%5D=effects.highlight.js&files%5B%5D=effects.pulsate.js&files%5B%5D=effects.scale.js&files%5B%5D=effects.shake.js&files%5B%5D=effects.slide.js&files%5B%5D=effects.transfer.js&theme=%3FffDefault%3DGeorgia%252C%2BVerdana%252CArial%252Csans-serif%26fwDefault%3Dbold%26fsDefault%3D1.2em%26cornerRadius%3D5px%26bgColorHeader%3D261803%26bgTextureHeader%3D13_diamond.png%26bgImgOpacityHeader%3D8%26borderColorHeader%3Dbaaa5a%26fcHeader%3Deacd86%26iconColorHeader%3De9cd86%26bgColorContent%3D443113%26bgTextureContent%3D13_diamond.png%26bgImgOpacityContent%3D8%26borderColorContent%3Defec9f%26fcContent%3Defec9f%26iconColorContent%3Defec9f%26bgColorDefault%3D4f4221%26bgTextureDefault%3D13_diamond.png%26bgImgOpacityDefault%3D10%26borderColorDefault%3D362917%26fcDefault%3Df8eec9%26iconColorDefault%3De8e2b5%26bgColorHover%3D675423%26bgTextureHover%3D13_diamond.png%26bgImgOpacityHover%3D25%26borderColorHover%3D362917%26fcHover%3Df8eec9%26iconColorHover%3Df2ec64%26bgColorActive%3D443113%26bgTextureActive%3D13_diamond.png%26bgImgOpacityActive%3D8%26borderColorActive%3Defec9f%26fcActive%3Df9f2bd%26iconColorActive%3Df9f2bd%26bgColorHighlight%3Dd5ac5d%26bgTextureHighlight%3D13_diamond.png%26bgImgOpacityHighlight%3D25%26borderColorHighlight%3D362917%26fcHighlight%3D060200%26iconColorHighlight%3D070603%26bgColorError%3Dfee4bd%26bgTextureError%3D04_highlight_hard.png%26bgImgOpacityError%3D65%26borderColorError%3Dc26629%26fcError%3D803f1e%26iconColorError%3Dff7519%26bgColorOverlay%3D372806%26bgTextureOverlay%3D13_diamond.png%26bgImgOpacityOverlay%3D20%26opacityOverlay%3D80%26bgColorShadow%3Dddd4b0%26bgTextureShadow%3D01_flat.png%26bgImgOpacityShadow%3D75%26opacityShadow%3D30%26thicknessShadow%3D8px%26offsetTopShadow%3D-8px%26offsetLeftShadow%3D-8px%26cornerRadiusShadow%3D12px&scope=&t-name=swanky-purse&ui-version=1.8.2"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/collapsible.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - Collapse content</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion\" ).accordion({\n\t\t\tcollapsible: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"accordion\">\n\t<h3>Section 1</h3>\n\t<div>\n\t\t<p>Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>\n\t</div>\n\t<h3>Section 2</h3>\n\t<div>\n\t\t<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>\n\t</div>\n\t<h3>Section 3</h3>\n\t<div>\n\t\t<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>\n\t\t<ul>\n\t\t\t<li>List item one</li>\n\t\t\t<li>List item two</li>\n\t\t\t<li>List item three</li>\n\t\t</ul>\n\t</div>\n\t<h3>Section 4</h3>\n\t<div>\n\t\t<p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>By default, accordions always keep one section open. To allow for all sections to be be collapsible, set the <code>collapsible</code> option to true. Click on the currently open section to collapse its content pane.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/custom-icons.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - Customize icons</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tvar icons = {\n\t\t\theader: \"ui-icon-circle-arrow-e\",\n\t\t\tactiveHeader: \"ui-icon-circle-arrow-s\"\n\t\t};\n\t\t$( \"#accordion\" ).accordion({\n\t\t\ticons: icons\n\t\t});\n\t\t$( \"#toggle\" ).button().click(function() {\n\t\t\tif ( $( \"#accordion\" ).accordion( \"option\", \"icons\" ) ) {\n\t\t\t\t$( \"#accordion\" ).accordion( \"option\", \"icons\", null );\n\t\t\t} else {\n\t\t\t\t$( \"#accordion\" ).accordion( \"option\", \"icons\", icons );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"accordion\">\n\t<h3>Section 1</h3>\n\t<div>\n\t\t<p>Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>\n\t</div>\n\t<h3>Section 2</h3>\n\t<div>\n\t\t<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>\n\t</div>\n\t<h3>Section 3</h3>\n\t<div>\n\t\t<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>\n\t\t<ul>\n\t\t\t<li>List item one</li>\n\t\t\t<li>List item two</li>\n\t\t\t<li>List item three</li>\n\t\t</ul>\n\t</div>\n\t<h3>Section 4</h3>\n\t<div>\n\t\t<p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>\n\t</div>\n</div>\n\n<button id=\"toggle\">Toggle icons</button>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Customize the header icons with the <code>icons</code> option, which accepts classes for the header's default and active (open) state.  Use any class from the UI CSS framework, or create custom classes with background images.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion\" ).accordion();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"accordion\">\n\t<h3>Section 1</h3>\n\t<div>\n\t\t<p>\n\t\tMauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer\n\t\tut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit\n\t\tamet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut\n\t\todio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.\n\t\t</p>\n\t</div>\n\t<h3>Section 2</h3>\n\t<div>\n\t\t<p>\n\t\tSed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet\n\t\tpurus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor\n\t\tvelit, faucibus interdum tellus libero ac justo. Vivamus non quam. In\n\t\tsuscipit faucibus urna.\n\t\t</p>\n\t</div>\n\t<h3>Section 3</h3>\n\t<div>\n\t\t<p>\n\t\tNam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis.\n\t\tPhasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero\n\t\tac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis\n\t\tlacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui.\n\t\t</p>\n\t\t<ul>\n\t\t\t<li>List item one</li>\n\t\t\t<li>List item two</li>\n\t\t\t<li>List item three</li>\n\t\t</ul>\n\t</div>\n\t<h3>Section 4</h3>\n\t<div>\n\t\t<p>\n\t\tCras dictum. Pellentesque habitant morbi tristique senectus et netus\n\t\tet malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in\n\t\tfaucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia\n\t\tmauris vel est.\n\t\t</p>\n\t\t<p>\n\t\tSuspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus.\n\t\tClass aptent taciti sociosqu ad litora torquent per conubia nostra, per\n\t\tinceptos himenaeos.\n\t\t</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n<div class=\"demo-description\">\n<p>\nClick headers to expand/collapse content that is broken into logical sections, much like tabs.\nOptionally, toggle sections open/closed on mouseover.\n</p>\n<p>\nThe underlying HTML markup is a series of headers (H3 tags) and content divs so the content is\nusable without JavaScript.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/fillspace.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - Fill space</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion\" ).accordion({\n\t\t\theightStyle: \"fill\"\n\t\t});\n\t});\n\t$(function() {\n\t\t$( \"#accordionResizer\" ).resizable({\n\t\t\tminHeight: 140,\n\t\t\tminWidth: 200,\n\t\t\tresize: function() {\n\t\t\t\t$( \"#accordion\" ).accordion( \"refresh\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<h3 class=\"docs\">Resize the outer container:</h3>\n \n<div id=\"accordionResizer\" style=\"padding:10px; width:350px; height:220px;\" class=\"ui-widget-content\">\n\n<div id=\"accordion\">\n\t<h3>Section 1</h3>\n\t<div>\n\t\t<p>Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>\n\t</div>\n\t<h3>Section 2</h3>\n\t<div>\n\t\t<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>\n\t</div>\n\t<h3>Section 3</h3>\n\t<div>\n\t\t<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>\n\t\t<ul>\n\t\t\t<li>List item one</li>\n\t\t\t<li>List item two</li>\n\t\t\t<li>List item three</li>\n\t\t</ul>\n\t</div>\n\t<h3>Section 4</h3>\n\t<div>\n\t\t<p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>\n\t</div>\n</div>\n\n<span class=\"ui-icon ui-icon-grip-dotted-horizontal\" style=\"margin:2px auto;\"></span>\n</div><!-- End accordionResizer -->\n\n<div style=\"margin-top:7px; padding:10px; width:350px; height:50px;\" class=\"ui-widget-content\">I'm another panel</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Because the accordion is comprised of block-level elements, by default its width fills the available horizontal space. To fill the vertical space allocated by its container, set the <code>heightStyle</code> option to <code>\"fill\"</code>, and the script will automatically set the dimensions of the accordion to the height of its parent container.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/hoverintent.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - Open on hoverintent</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$(\"#accordion\").accordion({\n\t\t\tevent: \"click hoverintent\"\n\t\t});\n\t});\n\t\n\tvar cfg = ($.hoverintent = {\n\t\tsensitivity: 7,\n\t\tinterval: 100\n\t});\n\n\t$.event.special.hoverintent = {\n\t\tsetup: function() {\n\t\t\t$( this ).bind( \"mouseover\", jQuery.event.special.hoverintent.handler );\n\t\t},\n\t\tteardown: function() {\n\t\t\t$( this ).unbind( \"mouseover\", jQuery.event.special.hoverintent.handler );\n\t\t},\n\t\thandler: function( event ) {\n\t\t\tvar that = this,\n\t\t\t\targs = arguments,\n\t\t\t\ttarget = $( event.target ),\n\t\t\t\tcX, cY, pX, pY;\n\t\t\t\n\t\t\tfunction track( event ) {\n\t\t\t\tcX = event.pageX;\n\t\t\t\tcY = event.pageY;\n\t\t\t};\n\t\t\tpX = event.pageX;\n\t\t\tpY = event.pageY;\n\t\t\tfunction clear() {\n\t\t\t\ttarget\n\t\t\t\t\t.unbind( \"mousemove\", track )\n\t\t\t\t\t.unbind( \"mouseout\", arguments.callee );\n\t\t\t\tclearTimeout( timeout );\n\t\t\t}\n\t\t\tfunction handler() {\n\t\t\t\tif ( ( Math.abs( pX - cX ) + Math.abs( pY - cY ) ) < cfg.sensitivity ) {\n\t\t\t\t\tclear();\n\t\t\t\t\tevent.type = \"hoverintent\";\n\t\t\t\t\t// prevent accessing the original event since the new event\n\t\t\t\t\t// is fired asynchronously and the old event is no longer\n\t\t\t\t\t// usable (#6028)\n\t\t\t\t\tevent.originalEvent = {};\n\t\t\t\t\tjQuery.event.handle.apply( that, args );\n\t\t\t\t} else {\n\t\t\t\t\tpX = cX;\n\t\t\t\t\tpY = cY;\n\t\t\t\t\ttimeout = setTimeout( handler, cfg.interval );\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar timeout = setTimeout( handler, cfg.interval );\n\t\t\ttarget.mousemove( track ).mouseout( clear );\n\t\t\treturn true;\n\t\t}\n\t};\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"accordion\">\n\t<h3>Section 1</h3>\n\t<div>\n\t\t<p>\n\t\tMauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer\n\t\tut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit\n\t\tamet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut\n\t\todio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.\n\t\t</p>\n\t</div>\n\t<h3>Section 2</h3>\n\t<div>\n\t\t<p>\n\t\tSed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet\n\t\tpurus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor\n\t\tvelit, faucibus interdum tellus libero ac justo. Vivamus non quam. In\n\t\tsuscipit faucibus urna.\n\t\t</p>\n\t</div>\n\t<h3>Section 3</h3>\n\t<div>\n\t\t<p>\n\t\tNam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis.\n\t\tPhasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero\n\t\tac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis\n\t\tlacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui.\n\t\t</p>\n\t\t<ul>\n\t\t\t<li>List item one</li>\n\t\t\t<li>List item two</li>\n\t\t\t<li>List item three</li>\n\t\t</ul>\n\t</div>\n\t<h3>Section 4</h3>\n\t<div>\n\t\t<p>\n\t\tCras dictum. Pellentesque habitant morbi tristique senectus et netus\n\t\tet malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in\n\t\tfaucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia\n\t\tmauris vel est.\n\t\t</p>\n\t\t<p>\n\t\tSuspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus.\n\t\tClass aptent taciti sociosqu ad litora torquent per conubia nostra, per\n\t\tinceptos himenaeos.\n\t\t</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n<div class=\"demo-description\">\n<p>\nClick headers to expand/collapse content that is broken into logical sections, much like tabs.\nOptionally, toggle sections open/closed on mouseover.\n</p>\n<p>\nThe underlying HTML markup is a series of headers (H3 tags) and content divs so the content is\nusable without JavaScript.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"fillspace.html\">Fill space</a></li>\n\t\t<li><a href=\"no-auto-height.html\">No auto height</a></li>\n\t\t<li><a href=\"collapsible.html\">Collapse content</a></li>\n\t\t<li><a href=\"hoverintent.html\">Open on hoverintent</a></li>\n\t\t<li><a href=\"custom-icons.html\">Customize icons</a></li>\n\t\t<li><a href=\"sortable.html\">Sortable</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/no-auto-height.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - No auto height</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion\" ).accordion({\n\t\t\theightStyle: \"content\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"accordion\">\n\t<h3>Section 1</h3>\n\t<div>\n\t\t<p>Mauris mauris ante, blandit et, ultrices a, susceros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>\n\t</div>\n\t<h3>Section 2</h3>\n\t<div>\n\t\t<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>\n\t</div>\n\t<h3>Section 3</h3>\n\t<div>\n\t\t<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>\n\t\t<ul>\n\t\t\t<li>List item</li>\n\t\t\t<li>List item</li>\n\t\t\t<li>List item</li>\n\t\t\t<li>List item</li>\n\t\t\t<li>List item</li>\n\t\t\t<li>List item</li>\n\t\t\t<li>List item</li>\n\t\t</ul>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Setting <code>heightStyle: \"content\"</code> allows the accordion panels to keep their native height.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/accordion/sortable.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion - Sortable</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t/* IE has layout issues when sorting (see #5413) */\n\t.group { zoom: 1 }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion\" )\n\t\t\t.accordion({\n\t\t\t\theader: \"> div > h3\"\n\t\t\t})\n\t\t\t.sortable({\n\t\t\t\taxis: \"y\",\n\t\t\t\thandle: \"h3\",\n\t\t\t\tstop: function( event, ui ) {\n\t\t\t\t\t// IE doesn't register the blur when sorting\n\t\t\t\t\t// so trigger focusout handlers to remove .ui-state-focus\n\t\t\t\t\tui.item.children( \"h3\" ).triggerHandler( \"focusout\" );\n\t\t\t\t}\n\t\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"accordion\">\n\t<div class=\"group\">\n\t\t<h3>Section 1</h3>\n\t\t<div>\n\t\t\t<p>Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>\n\t\t</div>\n\t</div>\n\t<div class=\"group\">\n\t\t<h3>Section 2</h3>\n\t\t<div>\n\t\t\t<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>\n\t\t</div>\n\t</div>\n\t<div class=\"group\">\n\t\t<h3>Section 3</h3>\n\t\t<div>\n\t\t\t<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>\n\t\t\t<ul>\n\t\t\t\t<li>List item one</li>\n\t\t\t\t<li>List item two</li>\n\t\t\t\t<li>List item three</li>\n\t\t\t</ul>\n\t\t</div>\n\t</div>\n\t<div class=\"group\">\n\t\t<h3>Section 4</h3>\n\t\t<div>\n\t\t\t<p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>\n\t\t</div>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Drag the header to re-order panels.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/addClass/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - addClass demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t\t.toggler { width: 500px; height: 200px; position: relative; }\n\t\t#button { padding: .5em 1em; text-decoration: none; }\n\t\t#effect { width: 240px;  padding: 1em;  font-size: 1.2em; border: 1px solid #000; background: #eee; color: #333; }\n\t\t.newClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.6em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#button\" ).click(function() {\n\t\t\t$( \"#effect\" ).addClass( \"newClass\", 1000, callback );\n\t\t\treturn false;\n\t\t});\n\n\t\tfunction callback() {\n\t\t\tsetTimeout(function() {\n\t\t\t\t$( \"#effect\" ).removeClass( \"newClass\" );\n\t\t\t}, 1500 );\n\t\t}\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"ui-corner-all\">\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede.\n\t</div>\n</div>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>This demo adds a class which animates: text-indent, letter-spacing, width, height, padding, margin, and font-size.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/addClass/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/animate/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - Animate demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t\t.toggler { width: 500px; height: 200px; position: relative; }\n\t\t#button { padding: .5em 1em; text-decoration: none; }\n\t\t#effect { width: 240px; height: 135px; padding: 0.4em; position: relative; background: #fff; }\n\t\t#effect h3 { margin: 0; padding: 0.4em; text-align: center; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar state = true;\n\t\t$( \"#button\" ).click(function() {\n\t\t\tif ( state ) {\n\t\t\t\t$( \"#effect\" ).animate({\n\t\t\t\t\tbackgroundColor: \"#aa0000\",\n\t\t\t\t\tcolor: \"#fff\",\n\t\t\t\t\twidth: 500\n\t\t\t\t}, 1000 );\n\t\t\t} else {\n\t\t\t\t$( \"#effect\" ).animate({\n\t\t\t\t\tbackgroundColor: \"#fff\",\n\t\t\t\t\tcolor: \"#000\",\n\t\t\t\t\twidth: 240\n\t\t\t\t}, 1000 );\n\t\t\t}\n\t\t\tstate = !state;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"ui-widget-content ui-corner-all\">\n\t\t<h3 class=\"ui-widget-header ui-corner-all\">Animate</h3>\n\t\t<p>\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. Nulla lorem metus, adipiscing ut, luctus sed, hendrerit vitae, mi.\n\t\t</p>\n\t</div>\n</div>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Toggle Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/animate/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/categories.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Categories</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete-category {\n\t\tfont-weight: bold;\n\t\tpadding: .2em .4em;\n\t\tmargin: .8em 0 .2em;\n\t\tline-height: 1.5;\n\t}\n\t</style>\n\t<script>\n\t$.widget( \"custom.catcomplete\", $.ui.autocomplete, {\n\t\t_renderMenu: function( ul, items ) {\n\t\t\tvar that = this,\n\t\t\t\tcurrentCategory = \"\";\n\t\t\t$.each( items, function( index, item ) {\n\t\t\t\tif ( item.category != currentCategory ) {\n\t\t\t\t\tul.append( \"<li class='ui-autocomplete-category'>\" + item.category + \"</li>\" );\n\t\t\t\t\tcurrentCategory = item.category;\n\t\t\t\t}\n\t\t\t\tthat._renderItem( ul, item );\n\t\t\t});\n\t\t}\n\t});\n\t</script>\n\t<script>\n\t$(function() {\n\t\tvar data = [\n\t\t\t{ label: \"anders\", category: \"\" },\n\t\t\t{ label: \"andreas\", category: \"\" },\n\t\t\t{ label: \"antal\", category: \"\" },\n\t\t\t{ label: \"annhhx10\", category: \"Products\" },\n\t\t\t{ label: \"annk K12\", category: \"Products\" },\n\t\t\t{ label: \"annttop C13\", category: \"Products\" },\n\t\t\t{ label: \"anders andersson\", category: \"People\" },\n\t\t\t{ label: \"andreas andersson\", category: \"People\" },\n\t\t\t{ label: \"andreas johnson\", category: \"People\" }\n\t\t];\n\n\t\t$( \"#search\" ).catcomplete({\n\t\t\tdelay: 0,\n\t\t\tsource: data\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t<label for=\"search\">Search: </label>\n\t<input id=\"search\">\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A categorized search result. Try typing \"a\" or \"n\".</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/combobox.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Combobox</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-combobox {\n\t\tposition: relative;\n\t\tdisplay: inline-block;\n\t}\n\t.ui-combobox-toggle {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tbottom: 0;\n\t\tmargin-left: -1px;\n\t\tpadding: 0;\n\t\t/* adjust styles for IE 6/7 */\n\t\t*height: 1.7em;\n\t\t*top: 0.1em;\n\t}\n\t.ui-combobox-input {\n\t\tmargin: 0;\n\t\tpadding: 0.3em;\n\t}\n\t</style>\n\t<script>\n\t(function( $ ) {\n\t\t$.widget( \"ui.combobox\", {\n\t\t\t_create: function() {\n\t\t\t\tvar input,\n\t\t\t\t\tthat = this,\n\t\t\t\t\tselect = this.element.hide(),\n\t\t\t\t\tselected = select.children( \":selected\" ),\n\t\t\t\t\tvalue = selected.val() ? selected.text() : \"\",\n\t\t\t\t\twrapper = this.wrapper = $( \"<span>\" )\n\t\t\t\t\t\t.addClass( \"ui-combobox\" )\n\t\t\t\t\t\t.insertAfter( select );\n\n\t\t\t\tfunction removeIfInvalid(element) {\n\t\t\t\t\tvar value = $( element ).val(),\n\t\t\t\t\t\tmatcher = new RegExp( \"^\" + $.ui.autocomplete.escapeRegex( value ) + \"$\", \"i\" ),\n\t\t\t\t\t\tvalid = false;\n\t\t\t\t\tselect.children( \"option\" ).each(function() {\n\t\t\t\t\t\tif ( $( this ).text().match( matcher ) ) {\n\t\t\t\t\t\t\tthis.selected = valid = true;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif ( !valid ) {\n\t\t\t\t\t\t// remove invalid value, as it didn't match anything\n\t\t\t\t\t\t$( element )\n\t\t\t\t\t\t\t.val( \"\" )\n\t\t\t\t\t\t\t.attr( \"title\", value + \" didn't match any item\" )\n\t\t\t\t\t\t\t.tooltip( \"open\" );\n\t\t\t\t\t\tselect.val( \"\" );\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tinput.tooltip( \"close\" ).attr( \"title\", \"\" );\n\t\t\t\t\t\t}, 2500 );\n\t\t\t\t\t\tinput.data( \"autocomplete\" ).term = \"\";\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tinput = $( \"<input>\" )\n\t\t\t\t\t.appendTo( wrapper )\n\t\t\t\t\t.val( value )\n\t\t\t\t\t.attr( \"title\", \"\" )\n\t\t\t\t\t.addClass( \"ui-state-default ui-combobox-input\" )\n\t\t\t\t\t.autocomplete({\n\t\t\t\t\t\tdelay: 0,\n\t\t\t\t\t\tminLength: 0,\n\t\t\t\t\t\tsource: function( request, response ) {\n\t\t\t\t\t\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), \"i\" );\n\t\t\t\t\t\t\tresponse( select.children( \"option\" ).map(function() {\n\t\t\t\t\t\t\t\tvar text = $( this ).text();\n\t\t\t\t\t\t\t\tif ( this.value && ( !request.term || matcher.test(text) ) )\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tlabel: text.replace(\n\t\t\t\t\t\t\t\t\t\t\tnew RegExp(\n\t\t\t\t\t\t\t\t\t\t\t\t\"(?![^&;]+;)(?!<[^<>]*)(\" +\n\t\t\t\t\t\t\t\t\t\t\t\t$.ui.autocomplete.escapeRegex(request.term) +\n\t\t\t\t\t\t\t\t\t\t\t\t\")(?![^<>]*>)(?![^&;]+;)\", \"gi\"\n\t\t\t\t\t\t\t\t\t\t\t), \"<strong>$1</strong>\" ),\n\t\t\t\t\t\t\t\t\t\tvalue: text,\n\t\t\t\t\t\t\t\t\t\toption: this\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\t\t\tui.item.option.selected = true;\n\t\t\t\t\t\t\tthat._trigger( \"selected\", event, {\n\t\t\t\t\t\t\t\titem: ui.item.option\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t\tchange: function( event, ui ) {\n\t\t\t\t\t\t\tif ( !ui.item )\n\t\t\t\t\t\t\t\treturn removeIfInvalid( this );\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.addClass( \"ui-widget ui-widget-content ui-corner-left\" );\n\n\t\t\t\tinput.data( \"autocomplete\" )._renderItem = function( ul, item ) {\n\t\t\t\t\treturn $( \"<li>\" )\n\t\t\t\t\t\t.data( \"item.autocomplete\", item )\n\t\t\t\t\t\t.append( \"<a>\" + item.label + \"</a>\" )\n\t\t\t\t\t\t.appendTo( ul );\n\t\t\t\t};\n\n\t\t\t\t$( \"<a>\" )\n\t\t\t\t\t.attr( \"tabIndex\", -1 )\n\t\t\t\t\t.attr( \"title\", \"Show All Items\" )\n\t\t\t\t\t.tooltip()\n\t\t\t\t\t.appendTo( wrapper )\n\t\t\t\t\t.button({\n\t\t\t\t\t\ticons: {\n\t\t\t\t\t\t\tprimary: \"ui-icon-triangle-1-s\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttext: false\n\t\t\t\t\t})\n\t\t\t\t\t.removeClass( \"ui-corner-all\" )\n\t\t\t\t\t.addClass( \"ui-corner-right ui-combobox-toggle\" )\n\t\t\t\t\t.click(function() {\n\t\t\t\t\t\t// close if already visible\n\t\t\t\t\t\tif ( input.autocomplete( \"widget\" ).is( \":visible\" ) ) {\n\t\t\t\t\t\t\tinput.autocomplete( \"close\" );\n\t\t\t\t\t\t\tremoveIfInvalid( input );\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// work around a bug (likely same cause as #5265)\n\t\t\t\t\t\t$( this ).blur();\n\n\t\t\t\t\t\t// pass empty string as value to search for, displaying all results\n\t\t\t\t\t\tinput.autocomplete( \"search\", \"\" );\n\t\t\t\t\t\tinput.focus();\n\t\t\t\t\t});\n\n\t\t\t\t\tinput\n\t\t\t\t\t\t.tooltip({\n\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\tof: this.button\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipClass: \"ui-state-highlight\"\n\t\t\t\t\t\t});\n\t\t\t},\n\n\t\t\tdestroy: function() {\n\t\t\t\tthis.wrapper.remove();\n\t\t\t\tthis.element.show();\n\t\t\t\t$.Widget.prototype.destroy.call( this );\n\t\t\t}\n\t\t});\n\t})( jQuery );\n\n\t$(function() {\n\t\t$( \"#combobox\" ).combobox();\n\t\t$( \"#toggle\" ).click(function() {\n\t\t\t$( \"#combobox\" ).toggle();\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label>Your preferred programming language: </label>\n\t<select id=\"combobox\">\n\t\t<option value=\"\">Select one...</option>\n\t\t<option value=\"ActionScript\">ActionScript</option>\n\t\t<option value=\"AppleScript\">AppleScript</option>\n\t\t<option value=\"Asp\">Asp</option>\n\t\t<option value=\"BASIC\">BASIC</option>\n\t\t<option value=\"C\">C</option>\n\t\t<option value=\"C++\">C++</option>\n\t\t<option value=\"Clojure\">Clojure</option>\n\t\t<option value=\"COBOL\">COBOL</option>\n\t\t<option value=\"ColdFusion\">ColdFusion</option>\n\t\t<option value=\"Erlang\">Erlang</option>\n\t\t<option value=\"Fortran\">Fortran</option>\n\t\t<option value=\"Groovy\">Groovy</option>\n\t\t<option value=\"Haskell\">Haskell</option>\n\t\t<option value=\"Java\">Java</option>\n\t\t<option value=\"JavaScript\">JavaScript</option>\n\t\t<option value=\"Lisp\">Lisp</option>\n\t\t<option value=\"Perl\">Perl</option>\n\t\t<option value=\"PHP\">PHP</option>\n\t\t<option value=\"Python\">Python</option>\n\t\t<option value=\"Ruby\">Ruby</option>\n\t\t<option value=\"Scala\">Scala</option>\n\t\t<option value=\"Scheme\">Scheme</option>\n\t</select>\n</div>\n<button id=\"toggle\">Show underlying select</button>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A custom widget built by composition of Autocomplete and Button. You can either type something into the field to get filtered suggestions based on your input, or use the button to get the full list of selections.</p>\n<p>The input is read from an existing select-element for progressive enhancement, passed to Autocomplete with a customized source-option.</p>\n<p>This is not a supported or even complete widget. Its purely for demoing what autocomplete can do with a bit of customization. <a href=\"http://www.learningjquery.com/2010/06/a-jquery-ui-combobox-under-the-hood\">For a detailed explanation of how the widget works, check out this Learning jQuery article.</a></p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/custom-data.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Custom data and display</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#project-label {\n\t\tdisplay: block;\n\t\tfont-weight: bold;\n\t\tmargin-bottom: 1em;\n\t}\n\t#project-icon {\n\t\tfloat: left;\n\t\theight: 32px;\n\t\twidth: 32px;\n\t}\n\t#project-description {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar projects = [\n\t\t\t{\n\t\t\t\tvalue: \"jquery\",\n\t\t\t\tlabel: \"jQuery\",\n\t\t\t\tdesc: \"the write less, do more, JavaScript library\",\n\t\t\t\ticon: \"jquery_32x32.png\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalue: \"jquery-ui\",\n\t\t\t\tlabel: \"jQuery UI\",\n\t\t\t\tdesc: \"the official user interface library for jQuery\",\n\t\t\t\ticon: \"jqueryui_32x32.png\"\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalue: \"sizzlejs\",\n\t\t\t\tlabel: \"Sizzle JS\",\n\t\t\t\tdesc: \"a pure-JavaScript CSS selector engine\",\n\t\t\t\ticon: \"sizzlejs_32x32.png\"\n\t\t\t}\n\t\t];\n\n\t\t$( \"#project\" ).autocomplete({\n\t\t\tminLength: 0,\n\t\t\tsource: projects,\n\t\t\tfocus: function( event, ui ) {\n\t\t\t\t$( \"#project\" ).val( ui.item.label );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tselect: function( event, ui ) {\n\t\t\t\t$( \"#project\" ).val( ui.item.label );\n\t\t\t\t$( \"#project-id\" ).val( ui.item.value );\n\t\t\t\t$( \"#project-description\" ).html( ui.item.desc );\n\t\t\t\t$( \"#project-icon\" ).attr( \"src\", \"images/\" + ui.item.icon );\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t})\n\t\t.data( \"autocomplete\" )._renderItem = function( ul, item ) {\n\t\t\treturn $( \"<li>\" )\n\t\t\t\t.data( \"item.autocomplete\", item )\n\t\t\t\t.append( \"<a>\" + item.label + \"<br>\" + item.desc + \"</a>\" )\n\t\t\t\t.appendTo( ul );\n\t\t};\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t<div id=\"project-label\">Select a project (type \"j\" for a start):</div>\n\t<img id=\"project-icon\" src=\"images/transparent_1x1.png\" class=\"ui-state-default\" alt=\"\">\n\t<input id=\"project\">\n\t<input type=\"hidden\" id=\"project-id\">\n\t<p id=\"project-description\"></p>\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>You can use your own custom data formats and displays by simply overriding the default focus and select actions.</p>\n<p>Try typing \"j\" to get a list of projects or just press the down arrow.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tvar availableTags = [\n\t\t\t\"ActionScript\",\n\t\t\t\"AppleScript\",\n\t\t\t\"Asp\",\n\t\t\t\"BASIC\",\n\t\t\t\"C\",\n\t\t\t\"C++\",\n\t\t\t\"Clojure\",\n\t\t\t\"COBOL\",\n\t\t\t\"ColdFusion\",\n\t\t\t\"Erlang\",\n\t\t\t\"Fortran\",\n\t\t\t\"Groovy\",\n\t\t\t\"Haskell\",\n\t\t\t\"Java\",\n\t\t\t\"JavaScript\",\n\t\t\t\"Lisp\",\n\t\t\t\"Perl\",\n\t\t\t\"PHP\",\n\t\t\t\"Python\",\n\t\t\t\"Ruby\",\n\t\t\t\"Scala\",\n\t\t\t\"Scheme\"\n\t\t];\n\t\t$( \"#tags\" ).autocomplete({\n\t\t\tsource: availableTags\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\t\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"tags\">Tags: </label>\n\t<input id=\"tags\">\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The Autocomplete widgets provides suggestions while you type into the field. Here the suggestions are tags for programming languages, give \"ja\" (for Java or JavaScript) a try.</p>\n<p>The datasource is a simple JavaScript array, provided to the widget using the source-option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/folding.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Accent folding</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tvar names = [ \"Jörn Zaefferer\", \"Scott González\", \"John Resig\" ];\n\n\t\tvar accentMap = {\n\t\t\t\"á\": \"a\",\n\t\t\t\"ö\": \"o\"\n\t\t};\n\t\tvar normalize = function( term ) {\n\t\t\tvar ret = \"\";\n\t\t\tfor ( var i = 0; i < term.length; i++ ) {\n\t\t\t\tret += accentMap[ term.charAt(i) ] || term.charAt(i);\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\n\t\t$( \"#developer\" ).autocomplete({\n\t\t\tsource: function( request, response ) {\n\t\t\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), \"i\" );\n\t\t\t\tresponse( $.grep( names, function( value ) {\n\t\t\t\t\tvalue = value.label || value.value || value;\n\t\t\t\t\treturn matcher.test( value ) || matcher.test( normalize( value ) );\n\t\t\t\t}) );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<form>\n\t<label for=\"developer\">Developer: </label>\n\t<input id=\"developer\">\n\t</form>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The autocomplete field uses a custom source option which will match results that have accented characters even when the text field doesn't contain accented characters. However if the you type in accented characters in the text field it is smart enough not to show results that aren't accented.</p>\n<p>Try typing \"Jo\" to see \"John\" and \"Jörn\", then type \"Jö\" to see only \"Jörn\".</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\t<div class=\"demos-nav\">\n\t\t<h4>Examples</h4>\n\t\t<ul>\n\t\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t\t<li><a href=\"remote.html\">Remote datasource</a></li>\n\t\t\t<li><a href=\"remote-with-cache.html\">Remote with caching</a></li>\n\t\t\t<li><a href=\"remote-jsonp.html\">Remote JSONP datasource</a></li>\n\t\t\t<li><a href=\"maxheight.html\">Scrollable results</a></li>\n\t\t\t<li><a href=\"combobox.html\">Combobox</a></li>\n\t\t\t<li><a href=\"custom-data.html\">Custom data and display</a></li>\n\t\t\t<li><a href=\"xml.html\">XML data parsed once</a></li>\n\t\t\t<li><a href=\"categories.html\">Categories</a></li>\n\t\t\t<li><a href=\"folding.html\">Accent folding</a></li>\n\t\t\t<li><a href=\"multiple.html\">Multiple values</a></li>\n\t\t\t<li><a href=\"multiple-remote.html\">Multiple, remote</a></li>\n\t\t</ul>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/london.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<geonames style=\"MEDIUM\">\n<totalResultsCount>6987</totalResultsCount>\n<geoname>\n<name>London</name>\n<lat>51.5084152563931</lat>\n<lng>-0.125532746315002</lng>\n<geonameId>2643743</geonameId>\n<countryCode>GB</countryCode>\n<countryName>United Kingdom</countryName>\n\n<fcl>P</fcl>\n<fcode>PPLC</fcode>\n</geoname>\n<geoname>\n<name>London</name>\n<lat>42.983389283</lat>\n<lng>-81.233042387</lng>\n<geonameId>6058560</geonameId>\n<countryCode>CA</countryCode>\n<countryName>Canada</countryName>\n\n<fcl>P</fcl>\n<fcode>PPL</fcode>\n</geoname>\n<geoname>\n<name>East London</name>\n<lat>-33.0152850934643</lat>\n<lng>27.9116249084473</lng>\n<geonameId>1006984</geonameId>\n<countryCode>ZA</countryCode>\n<countryName>South Africa</countryName>\n\n<fcl>P</fcl>\n<fcode>PPL</fcode>\n</geoname>\n<geoname>\n<name>City</name>\n<lat>51.5133363996235</lat>\n<lng>-0.0890064239501953</lng>\n<geonameId>2643744</geonameId>\n<countryCode>GB</countryCode>\n<countryName>United Kingdom</countryName>\n\n<fcl>A</fcl>\n<fcode>ADM2</fcode>\n</geoname>\n<geoname>\n<name>London</name>\n<lat>37.1289771</lat>\n<lng>-84.0832646</lng>\n<geonameId>4298960</geonameId>\n<countryCode>US</countryCode>\n<countryName>United States</countryName>\n\n<fcl>P</fcl>\n<fcode>PPL</fcode>\n</geoname>\n<geoname>\n<name>The Tower of London</name>\n<lat>51.5082349601834</lat>\n<lng>-0.0763034820556641</lng>\n<geonameId>6286786</geonameId>\n<countryCode>GB</countryCode>\n<countryName>United Kingdom</countryName>\n\n<fcl>S</fcl>\n<fcode>CSTL</fcode>\n</geoname>\n<geoname>\n<name>London Reefs</name>\n<lat>8.85</lat>\n<lng>112.5333333</lng>\n<geonameId>1879967</geonameId>\n<countryCode>  </countryCode>\n<countryName>  </countryName>\n\n<fcl>U</fcl>\n<fcode>RFSU</fcode>\n</geoname>\n<geoname>\n<name>Greater London</name>\n<lat>51.5</lat>\n<lng>-0.1666667</lng>\n<geonameId>2648110</geonameId>\n<countryCode>GB</countryCode>\n<countryName>United Kingdom</countryName>\n\n<fcl>A</fcl>\n<fcode>ADM2</fcode>\n</geoname>\n<geoname>\n<name>London</name>\n<lat>46.1666667</lat>\n<lng>6.0166667</lng>\n<geonameId>2661811</geonameId>\n<countryCode>CH</countryCode>\n<countryName>Switzerland</countryName>\n\n<fcl>H</fcl>\n<fcode>STM</fcode>\n</geoname>\n<geoname>\n<name>London Borough of Islington</name>\n<lat>51.5333333</lat>\n<lng>-0.1333333</lng>\n<geonameId>3333156</geonameId>\n<countryCode>GB</countryCode>\n<countryName>United Kingdom</countryName>\n\n<fcl>A</fcl>\n<fcode>ADM2</fcode>\n</geoname>\n</geonames>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/maxheight.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Scrollable results</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete {\n\t\tmax-height: 100px;\n\t\toverflow-y: auto;\n\t\t/* prevent horizontal scrollbar */\n\t\toverflow-x: hidden;\n\t}\n\t/* IE 6 doesn't support max-height\n\t * we use height instead, but this forces the menu to always be this tall\n\t */\n\t* html .ui-autocomplete {\n\t\theight: 100px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar availableTags = [\n\t\t\t\"ActionScript\",\n\t\t\t\"AppleScript\",\n\t\t\t\"Asp\",\n\t\t\t\"BASIC\",\n\t\t\t\"C\",\n\t\t\t\"C++\",\n\t\t\t\"Clojure\",\n\t\t\t\"COBOL\",\n\t\t\t\"ColdFusion\",\n\t\t\t\"Erlang\",\n\t\t\t\"Fortran\",\n\t\t\t\"Groovy\",\n\t\t\t\"Haskell\",\n\t\t\t\"Java\",\n\t\t\t\"JavaScript\",\n\t\t\t\"Lisp\",\n\t\t\t\"Perl\",\n\t\t\t\"PHP\",\n\t\t\t\"Python\",\n\t\t\t\"Ruby\",\n\t\t\t\"Scala\",\n\t\t\t\"Scheme\"\n\t\t];\n\t\t$( \"#tags\" ).autocomplete({\n\t\t\tsource: availableTags\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"tags\">Tags: </label>\n\t<input id=\"tags\">\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>When displaying a long list of options, you can simply set the max-height for the autocomplete menu to prevent the menu from growing too large. Try typing \"a\" or \"s\" above to get a long list of results that you can scroll through.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/multiple-remote.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Multiple, remote</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete-loading {\n\t\tbackground: white url('images/ui-anim_basic_16x16.gif') right center no-repeat;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tfunction split( val ) {\n\t\t\treturn val.split( /,\\s*/ );\n\t\t}\n\t\tfunction extractLast( term ) {\n\t\t\treturn split( term ).pop();\n\t\t}\n\n\t\t$( \"#birds\" )\n\t\t\t// don't navigate away from the field on tab when selecting an item\n\t\t\t.bind( \"keydown\", function( event ) {\n\t\t\t\tif ( event.keyCode === $.ui.keyCode.TAB &&\n\t\t\t\t\t\t$( this ).data( \"autocomplete\" ).menu.active ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.autocomplete({\n\t\t\t\tsource: function( request, response ) {\n\t\t\t\t\t$.getJSON( \"search.php\", {\n\t\t\t\t\t\tterm: extractLast( request.term )\n\t\t\t\t\t}, response );\n\t\t\t\t},\n\t\t\t\tsearch: function() {\n\t\t\t\t\t// custom minLength\n\t\t\t\t\tvar term = extractLast( this.value );\n\t\t\t\t\tif ( term.length < 2 ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tfocus: function() {\n\t\t\t\t\t// prevent value inserted on focus\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\tvar terms = split( this.value );\n\t\t\t\t\t// remove the current input\n\t\t\t\t\tterms.pop();\n\t\t\t\t\t// add the selected item\n\t\t\t\t\tterms.push( ui.item.value );\n\t\t\t\t\t// add placeholder to get the comma-and-space at the end\n\t\t\t\t\tterms.push( \"\" );\n\t\t\t\t\tthis.value = terms.join( \", \" );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"birds\">Birds: </label>\n\t<input id=\"birds\" size=\"50\">\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Usage: Enter at least two characters to get bird name suggestions. Select a value to continue adding more names.</p>\n<p>This is an example showing how to use the source-option along with some events to enable autocompleting multiple values into a single field.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/multiple.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Multiple values</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tvar availableTags = [\n\t\t\t\"ActionScript\",\n\t\t\t\"AppleScript\",\n\t\t\t\"Asp\",\n\t\t\t\"BASIC\",\n\t\t\t\"C\",\n\t\t\t\"C++\",\n\t\t\t\"Clojure\",\n\t\t\t\"COBOL\",\n\t\t\t\"ColdFusion\",\n\t\t\t\"Erlang\",\n\t\t\t\"Fortran\",\n\t\t\t\"Groovy\",\n\t\t\t\"Haskell\",\n\t\t\t\"Java\",\n\t\t\t\"JavaScript\",\n\t\t\t\"Lisp\",\n\t\t\t\"Perl\",\n\t\t\t\"PHP\",\n\t\t\t\"Python\",\n\t\t\t\"Ruby\",\n\t\t\t\"Scala\",\n\t\t\t\"Scheme\"\n\t\t];\n\t\tfunction split( val ) {\n\t\t\treturn val.split( /,\\s*/ );\n\t\t}\n\t\tfunction extractLast( term ) {\n\t\t\treturn split( term ).pop();\n\t\t}\n\n\t\t$( \"#tags\" )\n\t\t\t// don't navigate away from the field on tab when selecting an item\n\t\t\t.bind( \"keydown\", function( event ) {\n\t\t\t\tif ( event.keyCode === $.ui.keyCode.TAB &&\n\t\t\t\t\t\t$( this ).data( \"autocomplete\" ).menu.active ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.autocomplete({\n\t\t\t\tminLength: 0,\n\t\t\t\tsource: function( request, response ) {\n\t\t\t\t\t// delegate back to autocomplete, but extract the last term\n\t\t\t\t\tresponse( $.ui.autocomplete.filter(\n\t\t\t\t\t\tavailableTags, extractLast( request.term ) ) );\n\t\t\t\t},\n\t\t\t\tfocus: function() {\n\t\t\t\t\t// prevent value inserted on focus\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\tvar terms = split( this.value );\n\t\t\t\t\t// remove the current input\n\t\t\t\t\tterms.pop();\n\t\t\t\t\t// add the selected item\n\t\t\t\t\tterms.push( ui.item.value );\n\t\t\t\t\t// add placeholder to get the comma-and-space at the end\n\t\t\t\t\tterms.push( \"\" );\n\t\t\t\t\tthis.value = terms.join( \", \" );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"tags\">Tag programming languages: </label>\n\t<input id=\"tags\" size=\"50\">\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Usage: Type something, eg. \"j\" to see suggestions for tagging with programming languages. Select a value, then continue typing to add more.</p>\n<p>This is an example showing how to use the source-option along with some events to enable autocompleting multiple values into a single field.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/remote-jsonp.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Remote JSONP datasource</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete-loading {\n\t\tbackground: white url('images/ui-anim_basic_16x16.gif') right center no-repeat;\n\t}\n\t#city { width: 25em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\tfunction log( message ) {\n\t\t\t$( \"<div>\" ).text( message ).prependTo( \"#log\" );\n\t\t\t$( \"#log\" ).scrollTop( 0 );\n\t\t}\n\n\t\t$( \"#city\" ).autocomplete({\n\t\t\tsource: function( request, response ) {\n\t\t\t\t$.ajax({\n\t\t\t\t\turl: \"http://ws.geonames.org/searchJSON\",\n\t\t\t\t\tdataType: \"jsonp\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tfeatureClass: \"P\",\n\t\t\t\t\t\tstyle: \"full\",\n\t\t\t\t\t\tmaxRows: 12,\n\t\t\t\t\t\tname_startsWith: request.term\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\t\tresponse( $.map( data.geonames, function( item ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tlabel: item.name + (item.adminName1 ? \", \" + item.adminName1 : \"\") + \", \" + item.countryName,\n\t\t\t\t\t\t\t\tvalue: item.name\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t\tminLength: 2,\n\t\t\tselect: function( event, ui ) {\n\t\t\t\tlog( ui.item ?\n\t\t\t\t\t\"Selected: \" + ui.item.label :\n\t\t\t\t\t\"Nothing selected, input was \" + this.value);\n\t\t\t},\n\t\t\topen: function() {\n\t\t\t\t$( this ).removeClass( \"ui-corner-all\" ).addClass( \"ui-corner-top\" );\n\t\t\t},\n\t\t\tclose: function() {\n\t\t\t\t$( this ).removeClass( \"ui-corner-top\" ).addClass( \"ui-corner-all\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"city\">Your city: </label>\n\t<input id=\"city\">\n\tPowered by <a href=\"http://geonames.org\">geonames.org</a>\n</div>\n\n<div class=\"ui-widget\" style=\"margin-top:2em; font-family:Arial\">\n\tResult:\n\t<div id=\"log\" style=\"height: 200px; width: 300px; overflow: auto;\" class=\"ui-widget-content\"></div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The Autocomplete widgets provides suggestions while you type into the field. Here the suggestions are cities, displayed when at least two characters are entered into the field.</p>\n<p>In this case, the datasource is the <a href=\"http://geonames.org\">geonames.org webservice</a>. While only the city name itself ends up in the input after selecting an element, more info is displayed in the suggestions to help find the right entry. That data is also available in callbacks, as illustrated by the Result area below the input.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/remote-with-cache.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Remote with caching</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete-loading {\n\t\tbackground: white url('images/ui-anim_basic_16x16.gif') right center no-repeat;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar cache = {},\n\t\t\tlastXhr;\n\t\t$( \"#birds\" ).autocomplete({\n\t\t\tminLength: 2,\n\t\t\tsource: function( request, response ) {\n\t\t\t\tvar term = request.term;\n\t\t\t\tif ( term in cache ) {\n\t\t\t\t\tresponse( cache[ term ] );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlastXhr = $.getJSON( \"search.php\", request, function( data, status, xhr ) {\n\t\t\t\t\tcache[ term ] = data;\n\t\t\t\t\tif ( xhr === lastXhr ) {\n\t\t\t\t\t\tresponse( data );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"birds\">Birds: </label>\n\t<input id=\"birds\">\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The Autocomplete widgets provides suggestions while you type into the field. Here the suggestions are bird names, displayed when at least two characters are entered into the field.</p>\n<p>Similar to the remote datasource demo, though this adds some local caching to improve performance. The cache here saves just one query, and could be extended to cache multiple values, one for each term.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/remote.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - Remote datasource</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete-loading {\n\t\tbackground: white url('images/ui-anim_basic_16x16.gif') right center no-repeat;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tfunction log( message ) {\n\t\t\t$( \"<div>\" ).text( message ).prependTo( \"#log\" );\n\t\t\t$( \"#log\" ).scrollTop( 0 );\n\t\t}\n\n\t\t$( \"#birds\" ).autocomplete({\n\t\t\tsource: \"search.php\",\n\t\t\tminLength: 2,\n\t\t\tselect: function( event, ui ) {\n\t\t\t\tlog( ui.item ?\n\t\t\t\t\t\"Selected: \" + ui.item.value + \" aka \" + ui.item.id :\n\t\t\t\t\t\"Nothing selected, input was \" + this.value );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"birds\">Birds: </label>\n\t<input id=\"birds\">\n</div>\n\n<div class=\"ui-widget\" style=\"margin-top:2em; font-family:Arial\">\n\tResult:\n\t<div id=\"log\" style=\"height: 200px; width: 300px; overflow: auto;\" class=\"ui-widget-content\"></div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The Autocomplete widgets provides suggestions while you type into the field. Here the suggestions are bird names, displayed when at least two characters are entered into the field.</p>\n<p>The datasource is a server-side script which returns JSON data, specified via a simple URL for the source-option. In addition, the minLength-option is set to 2 to avoid queries that would return too many results and the select-event is used to display some feedback.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/search.php",
    "content": "<?php\n\nsleep( 3 );\n// no term passed - just exit early with no response\nif (empty($_GET['term'])) exit ;\n$q = strtolower($_GET[\"term\"]);\n// remove slashes if they were magically added\nif (get_magic_quotes_gpc()) $q = stripslashes($q);\n\n$items = array(\n\"Great Bittern\"=>\"Botaurus stellaris\",\n\"Little Grebe\"=>\"Tachybaptus ruficollis\",\n\"Black-necked Grebe\"=>\"Podiceps nigricollis\",\n\"Little Bittern\"=>\"Ixobrychus minutus\",\n\"Black-crowned Night Heron\"=>\"Nycticorax nycticorax\",\n\"Purple Heron\"=>\"Ardea purpurea\",\n\"White Stork\"=>\"Ciconia ciconia\",\n\"Spoonbill\"=>\"Platalea leucorodia\",\n\"Red-crested Pochard\"=>\"Netta rufina\",\n\"Common Eider\"=>\"Somateria mollissima\",\n\"Red Kite\"=>\"Milvus milvus\",\n\"Hen Harrier\"=>\"Circus cyaneus\",\n\"Montagu`s Harrier\"=>\"Circus pygargus\",\n\"Black Grouse\"=>\"Tetrao tetrix\",\n\"Grey Partridge\"=>\"Perdix perdix\",\n\"Spotted Crake\"=>\"Porzana porzana\",\n\"Corncrake\"=>\"Crex crex\",\n\"Common Crane\"=>\"Grus grus\",\n\"Avocet\"=>\"Recurvirostra avosetta\",\n\"Stone Curlew\"=>\"Burhinus oedicnemus\",\n\"Common Ringed Plover\"=>\"Charadrius hiaticula\",\n\"Kentish Plover\"=>\"Charadrius alexandrinus\",\n\"Ruff\"=>\"Philomachus pugnax\",\n\"Common Snipe\"=>\"Gallinago gallinago\",\n\"Black-tailed Godwit\"=>\"Limosa limosa\",\n\"Common Redshank\"=>\"Tringa totanus\",\n\"Sandwich Tern\"=>\"Sterna sandvicensis\",\n\"Common Tern\"=>\"Sterna hirundo\",\n\"Arctic Tern\"=>\"Sterna paradisaea\",\n\"Little Tern\"=>\"Sternula albifrons\",\n\"Black Tern\"=>\"Chlidonias niger\",\n\"Barn Owl\"=>\"Tyto alba\",\n\"Little Owl\"=>\"Athene noctua\",\n\"Short-eared Owl\"=>\"Asio flammeus\",\n\"European Nightjar\"=>\"Caprimulgus europaeus\",\n\"Common Kingfisher\"=>\"Alcedo atthis\",\n\"Eurasian Hoopoe\"=>\"Upupa epops\",\n\"Eurasian Wryneck\"=>\"Jynx torquilla\",\n\"European Green Woodpecker\"=>\"Picus viridis\",\n\"Crested Lark\"=>\"Galerida cristata\",\n\"White-headed Duck\"=>\"Oxyura leucocephala\",\n\"Pale-bellied Brent Goose\"=>\"Branta hrota\",\n\"Tawny Pipit\"=>\"Anthus campestris\",\n\"Whinchat\"=>\"Saxicola rubetra\",\n\"European Stonechat\"=>\"Saxicola rubicola\",\n\"Northern Wheatear\"=>\"Oenanthe oenanthe\",\n\"Savi`s Warbler\"=>\"Locustella luscinioides\",\n\"Sedge Warbler\"=>\"Acrocephalus schoenobaenus\",\n\"Great Reed Warbler\"=>\"Acrocephalus arundinaceus\",\n\"Bearded Reedling\"=>\"Panurus biarmicus\",\n\"Red-backed Shrike\"=>\"Lanius collurio\",\n\"Great Grey Shrike\"=>\"Lanius excubitor\",\n\"Woodchat Shrike\"=>\"Lanius senator\",\n\"Common Raven\"=>\"Corvus corax\",\n\"Yellowhammer\"=>\"Emberiza citrinella\",\n\"Ortolan Bunting\"=>\"Emberiza hortulana\",\n\"Corn Bunting\"=>\"Emberiza calandra\",\n\"Great Cormorant\"=>\"Phalacrocorax carbo\",\n\"Hawfinch\"=>\"Coccothraustes coccothraustes\",\n\"Common Shelduck\"=>\"Tadorna tadorna\",\n\"Bluethroat\"=>\"Luscinia svecica\",\n\"Grey Heron\"=>\"Ardea cinerea\",\n\"Barn Swallow\"=>\"Hirundo rustica\",\n\"Hooded Crow\"=>\"Corvus cornix\",\n\"Dunlin\"=>\"Calidris alpina\",\n\"Eurasian Pied Flycatcher\"=>\"Ficedula hypoleuca\",\n\"Eurasian Nuthatch\"=>\"Sitta europaea\",\n\"Short-toed Tree Creeper\"=>\"Certhia brachydactyla\",\n\"Wood Lark\"=>\"Lullula arborea\",\n\"Tree Pipit\"=>\"Anthus trivialis\",\n\"Eurasian Hobby\"=>\"Falco subbuteo\",\n\"Marsh Warbler\"=>\"Acrocephalus palustris\",\n\"Wood Sandpiper\"=>\"Tringa glareola\",\n\"Tawny Owl\"=>\"Strix aluco\",\n\"Lesser Whitethroat\"=>\"Sylvia curruca\",\n\"Barnacle Goose\"=>\"Branta leucopsis\",\n\"Common Goldeneye\"=>\"Bucephala clangula\",\n\"Western Marsh Harrier\"=>\"Circus aeruginosus\",\n\"Common Buzzard\"=>\"Buteo buteo\",\n\"Sanderling\"=>\"Calidris alba\",\n\"Little Gull\"=>\"Larus minutus\",\n\"Eurasian Magpie\"=>\"Pica pica\",\n\"Willow Warbler\"=>\"Phylloscopus trochilus\",\n\"Wood Warbler\"=>\"Phylloscopus sibilatrix\",\n\"Great Crested Grebe\"=>\"Podiceps cristatus\",\n\"Eurasian Jay\"=>\"Garrulus glandarius\",\n\"Common Redstart\"=>\"Phoenicurus phoenicurus\",\n\"Blue-headed Wagtail\"=>\"Motacilla flava\",\n\"Common Swift\"=>\"Apus apus\",\n\"Marsh Tit\"=>\"Poecile palustris\",\n\"Goldcrest\"=>\"Regulus regulus\",\n\"European Golden Plover\"=>\"Pluvialis apricaria\",\n\"Eurasian Bullfinch\"=>\"Pyrrhula pyrrhula\",\n\"Common Whitethroat\"=>\"Sylvia communis\",\n\"Meadow Pipit\"=>\"Anthus pratensis\",\n\"Greylag Goose\"=>\"Anser anser\",\n\"Spotted Flycatcher\"=>\"Muscicapa striata\",\n\"European Greenfinch\"=>\"Carduelis chloris\",\n\"Common Greenshank\"=>\"Tringa nebularia\",\n\"Great Spotted Woodpecker\"=>\"Dendrocopos major\",\n\"Greater Canada Goose\"=>\"Branta canadensis\",\n\"Mistle Thrush\"=>\"Turdus viscivorus\",\n\"Great Black-backed Gull\"=>\"Larus marinus\",\n\"Goosander\"=>\"Mergus merganser\",\n\"Great Egret\"=>\"Casmerodius albus\",\n\"Northern Goshawk\"=>\"Accipiter gentilis\",\n\"Dunnock\"=>\"Prunella modularis\",\n\"Stock Dove\"=>\"Columba oenas\",\n\"Common Wood Pigeon\"=>\"Columba palumbus\",\n\"Eurasian Woodcock\"=>\"Scolopax rusticola\",\n\"House Sparrow\"=>\"Passer domesticus\",\n\"Common House Martin\"=>\"Delichon urbicum\",\n\"Red Knot\"=>\"Calidris canutus\",\n\"Western Jackdaw\"=>\"Corvus monedula\",\n\"Brambling\"=>\"Fringilla montifringilla\",\n\"Northern Lapwing\"=>\"Vanellus vanellus\",\n\"European Reed Warbler\"=>\"Acrocephalus scirpaceus\",\n\"Lesser Black-backed Gull\"=>\"Larus fuscus\",\n\"Little Egret\"=>\"Egretta garzetta\",\n\"Little Stint\"=>\"Calidris minuta\",\n\"Common Linnet\"=>\"Carduelis cannabina\",\n\"Mute Swan\"=>\"Cygnus olor\",\n\"Common Cuckoo\"=>\"Cuculus canorus\",\n\"Black-headed Gull\"=>\"Larus ridibundus\",\n\"Greater White-fronted Goose\"=>\"Anser albifrons\",\n\"Great Tit\"=>\"Parus major\",\n\"Redwing\"=>\"Turdus iliacus\",\n\"Gadwall\"=>\"Anas strepera\",\n\"Fieldfare\"=>\"Turdus pilaris\",\n\"Tufted Duck\"=>\"Aythya fuligula\",\n\"Crested Tit\"=>\"Lophophanes cristatus\",\n\"Willow Tit\"=>\"Poecile montanus\",\n\"Eurasian Coot\"=>\"Fulica atra\",\n\"Common Blackbird\"=>\"Turdus merula\",\n\"Smew\"=>\"Mergus albellus\",\n\"Common Sandpiper\"=>\"Actitis hypoleucos\",\n\"Sand Martin\"=>\"Riparia riparia\",\n\"Purple Sandpiper\"=>\"Calidris maritima\",\n\"Northern Pintail\"=>\"Anas acuta\",\n\"Blue Tit\"=>\"Cyanistes caeruleus\",\n\"European Goldfinch\"=>\"Carduelis carduelis\",\n\"Eurasian Whimbrel\"=>\"Numenius phaeopus\",\n\"Common Reed Bunting\"=>\"Emberiza schoeniclus\",\n\"Eurasian Tree Sparrow\"=>\"Passer montanus\",\n\"Rook\"=>\"Corvus frugilegus\",\n\"European Robin\"=>\"Erithacus rubecula\",\n\"Bar-tailed Godwit\"=>\"Limosa lapponica\",\n\"Dark-bellied Brent Goose\"=>\"Branta bernicla\",\n\"Eurasian Oystercatcher\"=>\"Haematopus ostralegus\",\n\"Eurasian Siskin\"=>\"Carduelis spinus\",\n\"Northern Shoveler\"=>\"Anas clypeata\",\n\"Eurasian Wigeon\"=>\"Anas penelope\",\n\"Eurasian Sparrow Hawk\"=>\"Accipiter nisus\",\n\"Icterine Warbler\"=>\"Hippolais icterina\",\n\"Common Starling\"=>\"Sturnus vulgaris\",\n\"Long-tailed Tit\"=>\"Aegithalos caudatus\",\n\"Ruddy Turnstone\"=>\"Arenaria interpres\",\n\"Mew Gull\"=>\"Larus canus\",\n\"Common Pochard\"=>\"Aythya ferina\",\n\"Common Chiffchaff\"=>\"Phylloscopus collybita\",\n\"Greater Scaup\"=>\"Aythya marila\",\n\"Common Kestrel\"=>\"Falco tinnunculus\",\n\"Garden Warbler\"=>\"Sylvia borin\",\n\"Eurasian Collared Dove\"=>\"Streptopelia decaocto\",\n\"Eurasian Skylark\"=>\"Alauda arvensis\",\n\"Common Chaffinch\"=>\"Fringilla coelebs\",\n\"Common Moorhen\"=>\"Gallinula chloropus\",\n\"Water Pipit\"=>\"Anthus spinoletta\",\n\"Mallard\"=>\"Anas platyrhynchos\",\n\"Winter Wren\"=>\"Troglodytes troglodytes\",\n\"Common Teal\"=>\"Anas crecca\",\n\"Green Sandpiper\"=>\"Tringa ochropus\",\n\"White Wagtail\"=>\"Motacilla alba\",\n\"Eurasian Curlew\"=>\"Numenius arquata\",\n\"Song Thrush\"=>\"Turdus philomelos\",\n\"European Herring Gull\"=>\"Larus argentatus\",\n\"Grey Plover\"=>\"Pluvialis squatarola\",\n\"Carrion Crow\"=>\"Corvus corone\",\n\"Coal Tit\"=>\"Periparus ater\",\n\"Spotted Redshank\"=>\"Tringa erythropus\",\n\"Blackcap\"=>\"Sylvia atricapilla\",\n\"Egyptian Vulture\"=>\"Neophron percnopterus\",\n\"Razorbill\"=>\"Alca torda\",\n\"Alpine Swift\"=>\"Apus melba\",\n\"Long-legged Buzzard\"=>\"Buteo rufinus\",\n\"Audouin`s Gull\"=>\"Larus audouinii\",\n\"Balearic Shearwater\"=>\"Puffinus mauretanicus\",\n\"Upland Sandpiper\"=>\"Bartramia longicauda\",\n\"Greater Spotted Eagle\"=>\"Aquila clanga\",\n\"Ring Ouzel\"=>\"Turdus torquatus\",\n\"Yellow-browed Warbler\"=>\"Phylloscopus inornatus\",\n\"Blue Rock Thrush\"=>\"Monticola solitarius\",\n\"Buff-breasted Sandpiper\"=>\"Tryngites subruficollis\",\n\"Jack Snipe\"=>\"Lymnocryptes minimus\",\n\"White-rumped Sandpiper\"=>\"Calidris fuscicollis\",\n\"Ruddy Shelduck\"=>\"Tadorna ferruginea\",\n\"Cetti's Warbler\"=>\"Cettia cetti\",\n\"Citrine Wagtail\"=>\"Motacilla citreola\",\n\"Roseate Tern\"=>\"Sterna dougallii\",\n\"Black-legged Kittiwake\"=>\"Rissa tridactyla\",\n\"Pygmy Cormorant\"=>\"Phalacrocorax pygmeus\",\n\"Booted Eagle\"=>\"Aquila pennata\",\n\"Lesser White-fronted Goose\"=>\"Anser erythropus\",\n\"Little Bunting\"=>\"Emberiza pusilla\",\n\"Eleonora's Falcon\"=>\"Falco eleonorae\",\n\"European Serin\"=>\"Serinus serinus\",\n\"Twite\"=>\"Carduelis flavirostris\",\n\"Yellow-legged Gull\"=>\"Larus michahellis\",\n\"Gyr Falcon\"=>\"Falco rusticolus\",\n\"Greenish Warbler\"=>\"Phylloscopus trochiloides\",\n\"Red-necked Phalarope\"=>\"Phalaropus lobatus\",\n\"Mealy Redpoll\"=>\"Carduelis flammea\",\n\"Glaucous Gull\"=>\"Larus hyperboreus\",\n\"Great Skua\"=>\"Stercorarius skua\",\n\"Great Bustard\"=>\"Otis tarda\",\n\"Velvet Scoter\"=>\"Melanitta fusca\",\n\"Pine Grosbeak\"=>\"Pinicola enucleator\",\n\"House Crow\"=>\"Corvus splendens\",\n\"Hume`s Leaf Warbler\"=>\"Phylloscopus humei\",\n\"Great Northern Loon\"=>\"Gavia immer\",\n\"Long-tailed Duck\"=>\"Clangula hyemalis\",\n\"Lapland Longspur\"=>\"Calcarius lapponicus\",\n\"Northern Gannet\"=>\"Morus bassanus\",\n\"Eastern Imperial Eagle\"=>\"Aquila heliaca\",\n\"Little Auk\"=>\"Alle alle\",\n\"Lesser Spotted Woodpecker\"=>\"Dendrocopos minor\",\n\"Iceland Gull\"=>\"Larus glaucoides\",\n\"Parasitic Jaeger\"=>\"Stercorarius parasiticus\",\n\"Bewick`s Swan\"=>\"Cygnus bewickii\",\n\"Little Bustard\"=>\"Tetrax tetrax\",\n\"Little Crake\"=>\"Porzana parva\",\n\"Baillon`s Crake\"=>\"Porzana pusilla\",\n\"Long-tailed Jaeger\"=>\"Stercorarius longicaudus\",\n\"King Eider\"=>\"Somateria spectabilis\",\n\"Greater Short-toed Lark\"=>\"Calandrella brachydactyla\",\n\"Houbara Bustard\"=>\"Chlamydotis undulata\",\n\"Curlew Sandpiper\"=>\"Calidris ferruginea\",\n\"Common Crossbill\"=>\"Loxia curvirostra\",\n\"European Shag\"=>\"Phalacrocorax aristotelis\",\n\"Horned Grebe\"=>\"Podiceps auritus\",\n\"Common Quail\"=>\"Coturnix coturnix\",\n\"Bearded Vulture\"=>\"Gypaetus barbatus\",\n\"Lanner Falcon\"=>\"Falco biarmicus\",\n\"Middle Spotted Woodpecker\"=>\"Dendrocopos medius\",\n\"Pomarine Jaeger\"=>\"Stercorarius pomarinus\",\n\"Red-breasted Merganser\"=>\"Mergus serrator\",\n\"Eurasian Black Vulture\"=>\"Aegypius monachus\",\n\"Eurasian Dotterel\"=>\"Charadrius morinellus\",\n\"Common Nightingale\"=>\"Luscinia megarhynchos\",\n\"Northern willow warbler\"=>\"Phylloscopus trochilus acredula\",\n\"Manx Shearwater\"=>\"Puffinus puffinus\",\n\"Northern Fulmar\"=>\"Fulmarus glacialis\",\n\"Eurasian Eagle Owl\"=>\"Bubo bubo\",\n\"Orphean Warbler\"=>\"Sylvia hortensis\",\n\"Melodious Warbler\"=>\"Hippolais polyglotta\",\n\"Pallas's Leaf Warbler\"=>\"Phylloscopus proregulus\",\n\"Atlantic Puffin\"=>\"Fratercula arctica\",\n\"Black-throated Loon\"=>\"Gavia arctica\",\n\"Bohemian Waxwing\"=>\"Bombycilla garrulus\",\n\"Marsh Sandpiper\"=>\"Tringa stagnatilis\",\n\"Great Snipe\"=>\"Gallinago media\",\n\"Squacco Heron\"=>\"Ardeola ralloides\",\n\"Long-eared Owl\"=>\"Asio otus\",\n\"Caspian Tern\"=>\"Hydroprogne caspia\",\n\"Red-breasted Goose\"=>\"Branta ruficollis\",\n\"Red-throated Loon\"=>\"Gavia stellata\",\n\"Common Rosefinch\"=>\"Carpodacus erythrinus\",\n\"Red-footed Falcon\"=>\"Falco vespertinus\",\n\"Ross's Goose\"=>\"Anser rossii\",\n\"Red Phalarope\"=>\"Phalaropus fulicarius\",\n\"Pied Wagtail\"=>\"Motacilla yarrellii\",\n\"Rose-coloured Starling\"=>\"Sturnus roseus\",\n\"Rough-legged Buzzard\"=>\"Buteo lagopus\",\n\"Saker Falcon\"=>\"Falco cherrug\",\n\"European Roller\"=>\"Coracias garrulus\",\n\"Short-toed Eagle\"=>\"Circaetus gallicus\",\n\"Peregrine Falcon\"=>\"Falco peregrinus\",\n\"Merlin\"=>\"Falco columbarius\",\n\"Snow Goose\"=>\"Anser caerulescens\",\n\"Snowy Owl\"=>\"Bubo scandiacus\",\n\"Snow Bunting\"=>\"Plectrophenax nivalis\",\n\"Common Grasshopper Warbler\"=>\"Locustella naevia\",\n\"Golden Eagle\"=>\"Aquila chrysaetos\",\n\"Black-winged Stilt\"=>\"Himantopus himantopus\",\n\"Steppe Eagle\"=>\"Aquila nipalensis\",\n\"Pallid Harrier\"=>\"Circus macrourus\",\n\"European Storm-petrel\"=>\"Hydrobates pelagicus\",\n\"Horned Lark\"=>\"Eremophila alpestris\",\n\"Eurasian Treecreeper\"=>\"Certhia familiaris\",\n\"Taiga Bean Goose\"=>\"Anser fabalis\",\n\"Temminck`s Stint\"=>\"Calidris temminckii\",\n\"Terek Sandpiper\"=>\"Xenus cinereus\",\n\"Tundra Bean Goose\"=>\"Anser serrirostris\",\n\"European Turtle Dove\"=>\"Streptopelia turtur\",\n\"Leach`s Storm-petrel\"=>\"Oceanodroma leucorhoa\",\n\"Eurasian Griffon Vulture\"=>\"Gyps fulvus\",\n\"Paddyfield Warbler\"=>\"Acrocephalus agricola\",\n\"Osprey\"=>\"Pandion haliaetus\",\n\"Firecrest\"=>\"Regulus ignicapilla\",\n\"Water Rail\"=>\"Rallus aquaticus\",\n\"European Honey Buzzard\"=>\"Pernis apivorus\",\n\"Eurasian Golden Oriole\"=>\"Oriolus oriolus\",\n\"Whooper Swan\"=>\"Cygnus cygnus\",\n\"Two-barred Crossbill\"=>\"Loxia leucoptera\",\n\"White-tailed Eagle\"=>\"Haliaeetus albicilla\",\n\"Atlantic Murre\"=>\"Uria aalge\",\n\"Garganey\"=>\"Anas querquedula\",\n\"Black Redstart\"=>\"Phoenicurus ochruros\",\n\"Common Scoter\"=>\"Melanitta nigra\",\n\"Rock Pipit\"=>\"Anthus petrosus\",\n\"Lesser Spotted Eagle\"=>\"Aquila pomarina\",\n\"Cattle Egret\"=>\"Bubulcus ibis\",\n\"White-winged Black Tern\"=>\"Chlidonias leucopterus\",\n\"Black Stork\"=>\"Ciconia nigra\",\n\"Mediterranean Gull\"=>\"Larus melanocephalus\",\n\"Black Kite\"=>\"Milvus migrans\",\n\"Yellow Wagtail\"=>\"Motacilla flavissima\",\n\"Red-necked Grebe\"=>\"Podiceps grisegena\",\n\"Gull-billed Tern\"=>\"Gelochelidon nilotica\",\n\"Pectoral Sandpiper\"=>\"Calidris melanotos\",\n\"Barred Warbler\"=>\"Sylvia nisoria\",\n\"Red-throated Pipit\"=>\"Anthus cervinus\",\n\"Grey Wagtail\"=>\"Motacilla cinerea\",\n\"Richard`s Pipit\"=>\"Anthus richardi\",\n\"Black Woodpecker\"=>\"Dryocopus martius\",\n\"Little Ringed Plover\"=>\"Charadrius dubius\",\n\"Whiskered Tern\"=>\"Chlidonias hybrida\",\n\"Lesser Redpoll\"=>\"Carduelis cabaret\",\n\"Pallas' Bunting\"=>\"Emberiza pallasi\",\n\"Ferruginous Duck\"=>\"Aythya nyroca\",\n\"Whistling Swan\"=>\"Cygnus columbianus\",\n\"Black Brant\"=>\"Branta nigricans\",\n\"Marbled Teal\"=>\"Marmaronetta angustirostris\",\n\"Canvasback\"=>\"Aythya valisineria\",\n\"Redhead\"=>\"Aythya americana\",\n\"Lesser Scaup\"=>\"Aythya affinis\",\n\"Steller`s Eider\"=>\"Polysticta stelleri\",\n\"Spectacled Eider\"=>\"Somateria fischeri\",\n\"Harlequin Duck\"=>\"Histronicus histrionicus\",\n\"Black Scoter\"=>\"Melanitta americana\",\n\"Surf Scoter\"=>\"Melanitta perspicillata\",\n\"Barrow`s Goldeneye\"=>\"Bucephala islandica\",\n\"Falcated Duck\"=>\"Anas falcata\",\n\"American Wigeon\"=>\"Anas americana\",\n\"Blue-winged Teal\"=>\"Anas discors\",\n\"American Black Duck\"=>\"Anas rubripes\",\n\"Baikal Teal\"=>\"Anas formosa\",\n\"Green-Winged Teal\"=>\"Anas carolinensis\",\n\"Hazel Grouse\"=>\"Bonasa bonasia\",\n\"Rock Partridge\"=>\"Alectoris graeca\",\n\"Red-legged Partridge\"=>\"Alectoris rufa\",\n\"Yellow-billed Loon\"=>\"Gavia adamsii\",\n\"Cory`s Shearwater\"=>\"Calonectris borealis\",\n\"Madeiran Storm-Petrel\"=>\"Oceanodroma castro\",\n\"Great White Pelican\"=>\"Pelecanus onocrotalus\",\n\"Dalmatian Pelican\"=>\"Pelecanus crispus\",\n\"American Bittern\"=>\"Botaurus lentiginosus\",\n\"Glossy Ibis\"=>\"Plegadis falcinellus\",\n\"Spanish Imperial Eagle\"=>\"Aquila adalberti\",\n\"Lesser Kestrel\"=>\"Falco naumanni\",\n\"Houbara Bustard\"=>\"Chlamydotis undulata\",\n\"Crab-Plover\"=>\"Dromas ardeola\",\n\"Cream-coloured Courser\"=>\"Cursorius cursor\",\n\"Collared Pratincole\"=>\"Glareola pratincola\",\n\"Black-winged Pratincole\"=>\"Glareola nordmanni\",\n\"Killdeer\"=>\"Charadrius vociferus\",\n\"Lesser Sand Plover\"=>\"Charadrius mongolus\",\n\"Greater Sand Plover\"=>\"Charadrius leschenaultii\",\n\"Caspian Plover\"=>\"Charadrius asiaticus\",\n\"American Golden Plover\"=>\"Pluvialis dominica\",\n\"Pacific Golden Plover\"=>\"Pluvialis fulva\",\n\"Sharp-tailed Sandpiper\"=>\"Calidris acuminata\",\n\"Broad-billed Sandpiper\"=>\"Limicola falcinellus\",\n\"Spoon-Billed Sandpiper\"=>\"Eurynorhynchus pygmaeus\",\n\"Short-Billed Dowitcher\"=>\"Limnodromus griseus\",\n\"Long-billed Dowitcher\"=>\"Limnodromus scolopaceus\",\n\"Hudsonian Godwit\"=>\"Limosa haemastica\",\n\"Little Curlew\"=>\"Numenius minutus\",\n\"Lesser Yellowlegs\"=>\"Tringa flavipes\",\n\"Wilson`s Phalarope\"=>\"Phalaropus tricolor\",\n\"Pallas`s Gull\"=>\"Larus ichthyaetus\",\n\"Laughing Gull\"=>\"Larus atricilla\",\n\"Franklin`s Gull\"=>\"Larus pipixcan\",\n\"Bonaparte`s Gull\"=>\"Larus philadelphia\",\n\"Ring-billed Gull\"=>\"Larus delawarensis\",\n\"American Herring Gull\"=>\"Larus smithsonianus\",\n\"Caspian Gull\"=>\"Larus cachinnans\",\n\"Ivory Gull\"=>\"Pagophila eburnea\",\n\"Royal Tern\"=>\"Sterna maxima\",\n\"Brünnich`s Murre\"=>\"Uria lomvia\",\n\"Crested Auklet\"=>\"Aethia cristatella\",\n\"Parakeet Auklet\"=>\"Cyclorrhynchus psittacula\",\n\"Tufted Puffin\"=>\"Lunda cirrhata\",\n\"Laughing Dove\"=>\"Streptopelia senegalensis\",\n\"Great Spotted Cuckoo\"=>\"Clamator glandarius\",\n\"Great Grey Owl\"=>\"Strix nebulosa\",\n\"Tengmalm`s Owl\"=>\"Aegolius funereus\",\n\"Red-Necked Nightjar\"=>\"Caprimulgus ruficollis\",\n\"Chimney Swift\"=>\"Chaetura pelagica\",\n\"Green Bea-Eater\"=>\"Merops orientalis\",\n\"Grey-headed Woodpecker\"=>\"Picus canus\",\n\"Lesser Short-Toed Lark\"=>\"Calandrella rufescens\",\n\"Eurasian Crag Martin\"=>\"Hirundo rupestris\",\n\"Red-rumped Swallow\"=>\"Cecropis daurica\",\n\"Blyth`s Pipit\"=>\"Anthus godlewskii\",\n\"Pechora Pipit\"=>\"Anthus gustavi\",\n\"Grey-headed Wagtail\"=>\"Motacilla thunbergi\",\n\"Yellow-Headed Wagtail\"=>\"Motacilla lutea\",\n\"White-throated Dipper\"=>\"Cinclus cinclus\",\n\"Rufous-Tailed Scrub Robin\"=>\"Cercotrichas galactotes\",\n\"Thrush Nightingale\"=>\"Luscinia luscinia\",\n\"White-throated Robin\"=>\"Irania gutturalis\",\n\"Caspian Stonechat\"=>\"Saxicola maura variegata\",\n\"Western Black-eared Wheatear\"=>\"Oenanthe hispanica\",\n\"Rufous-tailed Rock Thrush\"=>\"Monticola saxatilis\",\n\"Red-throated Thrush/Black-throated\"=>\"Turdus ruficollis\",\n\"American Robin\"=>\"Turdus migratorius\",\n\"Zitting Cisticola\"=>\"Cisticola juncidis\",\n\"Lanceolated Warbler\"=>\"Locustella lanceolata\",\n\"River Warbler\"=>\"Locustella fluviatilis\",\n\"Blyth`s Reed Warbler\"=>\"Acrocephalus dumetorum\",\n\"Caspian Reed Warbler\"=>\"Acrocephalus fuscus\",\n\"Aquatic Warbler\"=>\"Acrocephalus paludicola\",\n\"Booted Warbler\"=>\"Acrocephalus caligatus\",\n\"Marmora's Warbler\"=>\"Sylvia sarda\",\n\"Dartford Warbler\"=>\"Sylvia undata\",\n\"Subalpine Warbler\"=>\"Sylvia cantillans\",\n\"Ménétries's Warbler\"=>\"Sylvia mystacea\",\n\"Rüppel's Warbler\"=>\"Sylvia rueppelli\",\n\"Asian Desert Warbler\"=>\"Sylvia nana\",\n\"Western Orphean Warbler\"=>\"Sylvia hortensis hortensis\",\n\"Arctic Warbler\"=>\"Phylloscopus borealis\",\n\"Radde`s Warbler\"=>\"Phylloscopus schwarzi\",\n\"Western Bonelli`s Warbler\"=>\"Phylloscopus bonelli\",\n\"Red-breasted Flycatcher\"=>\"Ficedula parva\",\n\"Eurasian Penduline Tit\"=>\"Remiz pendulinus\",\n\"Daurian Shrike\"=>\"Lanius isabellinus\",\n\"Long-Tailed Shrike\"=>\"Lanius schach\",\n\"Lesser Grey Shrike\"=>\"Lanius minor\",\n\"Southern Grey Shrike\"=>\"Lanius meridionalis\",\n\"Masked Shrike\"=>\"Lanius nubicus\",\n\"Spotted Nutcracker\"=>\"Nucifraga caryocatactes\",\n\"Daurian Jackdaw\"=>\"Corvus dauuricus\",\n\"Purple-Backed Starling\"=>\"Sturnus sturninus\",\n\"Red-Fronted Serin\"=>\"Serinus pusillus\",\n\"Arctic Redpoll\"=>\"Carduelis hornemanni\",\n\"Scottish Crossbill\"=>\"Loxia scotica\",\n\"Parrot Crossbill\"=>\"Loxia pytyopsittacus\",\n\"Black-faced Bunting\"=>\"Emberiza spodocephala\",\n\"Pink-footed Goose\"=>\"Anser brachyrhynchus\",\n\"Black-winged Kite\"=>\"Elanus caeruleus\",\n\"European Bee-eater\"=>\"Merops apiaster\",\n\"Sabine`s Gull\"=>\"Larus sabini\",\n\"Sooty Shearwater\"=>\"Puffinus griseus\",\n\"Lesser Canada Goose\"=>\"Branta hutchinsii\",\n\"Ring-necked Duck\"=>\"Aythya collaris\",\n\"Greater Flamingo\"=>\"Phoenicopterus roseus\",\n\"Iberian Chiffchaff\"=>\"Phylloscopus ibericus\",\n\"Ashy-headed Wagtail\"=>\"Motacilla cinereocapilla\",\n\"Stilt Sandpiper\"=>\"Calidris himantopus\",\n\"Siberian Stonechat\"=>\"Saxicola maurus\",\n\"Greater Yellowlegs\"=>\"Tringa melanoleuca\",\n\"Forster`s Tern\"=>\"Sterna forsteri\",\n\"Dusky Warbler\"=>\"Phylloscopus fuscatus\",\n\"Cirl Bunting\"=>\"Emberiza cirlus\",\n\"Olive-backed Pipit\"=>\"Anthus hodgsoni\",\n\"Sociable Lapwing\"=>\"Vanellus gregarius\",\n\"Spotted Sandpiper\"=>\"Actitis macularius\",\n\"Baird`s Sandpiper\"=>\"Calidris bairdii\",\n\"Rustic Bunting\"=>\"Emberiza rustica\",\n\"Yellow-browed Bunting\"=>\"Emberiza chrysophrys\",\n\"Great Shearwater\"=>\"Puffinus gravis\",\n\"Bonelli`s Eagle\"=>\"Aquila fasciata\",\n\"Calandra Lark\"=>\"Melanocorypha calandra\",\n\"Sardinian Warbler\"=>\"Sylvia melanocephala\",\n\"Ross's Gull\"=>\"Larus roseus\",\n\"Yellow-Breasted Bunting\"=>\"Emberiza aureola\",\n\"Pine Bunting\"=>\"Emberiza leucocephalos\",\n\"Black Guillemot\"=>\"Cepphus grylle\",\n\"Pied-billed Grebe\"=>\"Podilymbus podiceps\",\n\"Soft-plumaged Petrel\"=>\"Pterodroma mollis\",\n\"Bulwer's Petrel\"=>\"Bulweria bulwerii\",\n\"White-Faced Storm-Petrel\"=>\"Pelagodroma marina\",\n\"Pallas’s Fish Eagle\"=>\"Haliaeetus leucoryphus\",\n\"Sandhill Crane\"=>\"Grus canadensis\",\n\"Macqueen’s Bustard\"=>\"Chlamydotis macqueenii\",\n\"White-tailed Lapwing\"=>\"Vanellus leucurus\",\n\"Great Knot\"=>\"Calidris tenuirostris\",\n\"Semipalmated Sandpiper\"=>\"Calidris pusilla\",\n\"Red-necked Stint\"=>\"Calidris ruficollis\",\n\"Slender-billed Curlew\"=>\"Numenius tenuirostris\",\n\"Bridled Tern\"=>\"Onychoprion anaethetus\",\n\"Pallas’s Sandgrouse\"=>\"Syrrhaptes paradoxus\",\n\"European Scops Owl\"=>\"Otus scops\",\n\"Northern Hawk Owl\"=>\"Surnia ulula\",\n\"White-Throated Needletail\"=>\"Hirundapus caudacutus\",\n\"Belted Kingfisher\"=>\"Ceryle alcyon\",\n\"Blue-cheeked Bee-eater\"=>\"Merops persicus\",\n\"Black-headed Wagtail\"=>\"Motacilla feldegg\",\n\"Northern Mockingbird\"=>\"Mimus polyglottos\",\n\"Alpine Accentor\"=>\"Prunella collaris\",\n\"Red-flanked Bluetail\"=>\"Tarsiger cyanurus\",\n\"Isabelline Wheatear\"=>\"Oenanthe isabellina\",\n\"Pied Wheatear\"=>\"Oenanthe pleschanka\",\n\"Eastern Black-eared Wheatear\"=>\"Oenanthe melanoleuca\",\n\"Desert Wheatear\"=>\"Oenanthe deserti\",\n\"White`s Thrush\"=>\"Zoothera aurea\",\n\"Siberian Thrush\"=>\"Zoothera sibirica\",\n\"Eyebrowed Thrush\"=>\"Turdus obscurus\",\n\"Dusky Thrush\"=>\"Turdus eunomus\",\n\"Black-throated Thrush\"=>\"Turdus atrogularis\",\n\"Pallas`s Grasshopper Warbler\"=>\"Locustella certhiola\",\n\"Spectacled Warbler\"=>\"Sylvia conspicillata\",\n\"Two-barred Warbler\"=>\"Phylloscopus plumbeitarsus\",\n\"Eastern Bonelli’s Warbler\"=>\"Phylloscopus orientalis\",\n\"Collared Flycatcher\"=>\"Ficedula albicollis\",\n\"Wallcreeper\"=>\"Tichodroma muraria\",\n\"Turkestan Shrike\"=>\"Lanius phoenicuroides\",\n\"Steppe Grey Shrike\"=>\"Lanius pallidirostris\",\n\"Spanish Sparrow\"=>\"Passer hispaniolensis\",\n\"Red-eyed Vireo\"=>\"Vireo olivaceus\",\n\"Myrtle Warbler\"=>\"Dendroica coronata\",\n\"White-crowned Sparrow\"=>\"Zonotrichia leucophrys\",\n\"White-throated Sparrow\"=>\"Zonotrichia albicollis\",\n\"Cretzschmar`s Bunting\"=>\"Emberiza caesia\",\n\"Chestnut Bunting\"=>\"Emberiza rutila\",\n\"Red-headed Bunting\"=>\"Emberiza bruniceps\",\n\"Black-headed Bunting\"=>\"Emberiza melanocephala\",\n\"Indigo Bunting\"=>\"Passerina cyanea\",\n\"Balearic Woodchat Shrike\"=>\"Lanius senator badius\",\n\"Demoiselle Crane\"=>\"Grus virgo\",\n\"Chough\"=>\"Pyrrhocorax pyrrhocorax\",\n\"Red-Billed Chough\"=>\"Pyrrhocorax graculus\",\n\"Elegant Tern\"=>\"Sterna elegans\",\n\"Chukar\"=>\"Alectoris chukar\",\n\"Yellow-Billed Cuckoo\"=>\"Coccyzus americanus\",\n\"American Sandwich Tern\"=>\"Sterna sandvicensis acuflavida\",\n\"Olive-Tree Warbler\"=>\"Hippolais olivetorum\",\n\"Eastern Olivaceous Warbler\"=>\"Acrocephalus pallidus\",\n\"Indian Cormorant\"=>\"Phalacrocorax fuscicollis\",\n\"Spur-Winged Lapwing\"=>\"Vanellus spinosus\",\n\"Yelkouan Shearwater\"=>\"Puffinus yelkouan\",\n\"Trumpeter Finch\"=>\"Bucanetes githagineus\",\n\"Red Grouse\"=>\"Lagopus scoticus\",\n\"Rock Ptarmigan\"=>\"Lagopus mutus\",\n\"Long-Tailed Cormorant\"=>\"Phalacrocorax africanus\",\n\"Double-crested Cormorant\"=>\"Phalacrocorax auritus\",\n\"Magnificent Frigatebird\"=>\"Fregata magnificens\",\n\"Naumann's Thrush\"=>\"Turdus naumanni\",\n\"Oriental Pratincole\"=>\"Glareola maldivarum\",\n\"Bufflehead\"=>\"Bucephala albeola\",\n\"Snowfinch\"=>\"Montifrigilla nivalis\",\n\"Ural owl\"=>\"Strix uralensis\",\n\"Spanish Wagtail\"=>\"Motacilla iberiae\",\n\"Song Sparrow\"=>\"Melospiza melodia\",\n\"Rock Bunting\"=>\"Emberiza cia\",\n\"Siberian Rubythroat\"=>\"Luscinia calliope\",\n\"Pallid Swift\"=>\"Apus pallidus\",\n\"Eurasian Pygmy Owl\"=>\"Glaucidium passerinum\",\n\"Madeira Little Shearwater\"=>\"Puffinus baroli\",\n\"House Finch\"=>\"Carpodacus mexicanus\",\n\"Green Heron\"=>\"Butorides virescens\",\n\"Solitary Sandpiper\"=>\"Tringa solitaria\",\n\"Heuglin's Gull\"=>\"Larus heuglini\"\n);\n\n\n$result = array();\nforeach ($items as $key=>$value) {\n\tif (strpos(strtolower($key), $q) !== false) {\n\t\tarray_push($result, array(\"id\"=>$value, \"label\"=>$key, \"value\" => strip_tags($key)));\n\t}\n\tif (count($result) > 11)\n\t\tbreak;\n}\n\n// json_encode is available in PHP 5.2 and above, or you can install a PECL module in earlier versions\necho json_encode($result);\n\n?>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/autocomplete/xml.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete - XML data parsed once</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\tfunction log( message ) {\n\t\t\t$( \"<div/>\" ).text( message ).prependTo( \"#log\" );\n\t\t\t$( \"#log\" ).attr( \"scrollTop\", 0 );\n\t\t}\n\n\t\t$.ajax({\n\t\t\turl: \"london.xml\",\n\t\t\tdataType: \"xml\",\n\t\t\tsuccess: function( xmlResponse ) {\n\t\t\t\tvar data = $( \"geoname\", xmlResponse ).map(function() {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: $( \"name\", this ).text() + \", \" +\n\t\t\t\t\t\t\t( $.trim( $( \"countryName\", this ).text() ) || \"(unknown country)\" ),\n\t\t\t\t\t\tid: $( \"geonameId\", this ).text()\n\t\t\t\t\t};\n\t\t\t\t}).get();\n\t\t\t\t$( \"#birds\" ).autocomplete({\n\t\t\t\t\tsource: data,\n\t\t\t\t\tminLength: 0,\n\t\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\t\tlog( ui.item ?\n\t\t\t\t\t\t\t\"Selected: \" + ui.item.value + \", geonameId: \" + ui.item.id :\n\t\t\t\t\t\t\t\"Nothing selected, input was \" + this.value );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget\">\n\t<label for=\"birds\">London matches: </label>\n\t<input id=\"birds\" />\n</div>\n\n<div class=\"ui-widget\" style=\"margin-top:2em; font-family:Arial\">\n\tResult:\n\t<div id=\"log\" style=\"height: 200px; width: 300px; overflow: auto;\" class=\"ui-widget-content\"></div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>This demo shows how to retrieve some XML data, parse it using jQuery's methods, then provide it to the autocomplete as the datasource.</p>\n<p>This should also serve as a reference on how to parse a remote XML datasource - the parsing would just happen for each request within the source-callback.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/checkbox.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button - Checkboxes</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#check\" ).button();\n\t\t$( \"#format\" ).buttonset();\n\t});\n\t</script>\n\t<style>\n\t#format { margin-top: 2em; }\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<input type=\"checkbox\" id=\"check\" /><label for=\"check\">Toggle</label>\n\n<div id=\"format\">\n\t<input type=\"checkbox\" id=\"check1\" /><label for=\"check1\">B</label>\n\t<input type=\"checkbox\" id=\"check2\" /><label for=\"check2\">I</label>\n\t<input type=\"checkbox\" id=\"check3\" /><label for=\"check3\">U</label>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A checkbox is styled as a toggle button with the button widget. The label element associated with the checkbox is used for the button text.</p>\n<p>This demo also demonstrates three checkboxes styled as a button set by calling <code>.buttonset()</code> on a common container.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"input[type=submit], a, button\", \".demo\" ).button();\n\t\t$( \"a\", \".demo\" ).click(function() { return false; });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<button>A button element</button>\n\n<input type=\"submit\" value=\"A submit button\">\n\n<a href=\"#\">An anchor</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Examples of the markup that can be used for buttons: A button element, an input of type submit and an anchor.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/icons.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button - Icons</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \".demo button:first\" ).button({\n            icons: {\n                primary: \"ui-icon-locked\"\n            },\n            text: false\n        }).next().button({\n            icons: {\n                primary: \"ui-icon-locked\"\n            }\n        }).next().button({\n            icons: {\n                primary: \"ui-icon-gear\",\n                secondary: \"ui-icon-triangle-1-s\"\n            }\n        }).next().button({\n            icons: {\n                primary: \"ui-icon-gear\",\n                secondary: \"ui-icon-triangle-1-s\"\n            },\n            text: false\n        });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<button>Button with icon only</button>\n<button>Button with icon on the left</button>\n<button>Button with two icons</button>\n<button>Button with two icons and no text</button>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Some buttons with various combinations of text and icons, here specified via metadata.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"radio.html\">Radios</a></li>\n\t\t<li><a href=\"checkbox.html\">Checkboxes</a></li>\n\t\t<li><a href=\"icons.html\">Icons</a></li>\n\t\t<li><a href=\"toolbar.html\">Toolbar</a></li>\n\t\t<li><a href=\"splitbutton.html\">Split Button</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/radio.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button - Radios</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#radio\" ).buttonset();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<form>\n\t<div id=\"radio\">\n\t\t<input type=\"radio\" id=\"radio1\" name=\"radio\" /><label for=\"radio1\">Choice 1</label>\n\t\t<input type=\"radio\" id=\"radio2\" name=\"radio\" checked=\"checked\" /><label for=\"radio2\">Choice 2</label>\n\t\t<input type=\"radio\" id=\"radio3\" name=\"radio\" /><label for=\"radio3\">Choice 3</label>\n\t</div>\n</form>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A set of three radio buttons transformed into a button set.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/splitbutton.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button - Split button</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t\t.ui-menu { position: absolute; width: 100px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#rerun\" )\n\t\t\t.button()\n\t\t\t.click(function() {\n\t\t\t\talert( \"Running the last action\" );\n\t\t\t})\n\t\t\t.next()\n\t\t\t\t.button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: \"ui-icon-triangle-1-s\"\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.click(function() {\n\t\t\t\t\tvar menu = $( this ).parent().next().show().position({\n\t\t\t\t\t\tmy: \"left top\",\n\t\t\t\t\t\tat: \"left bottom\",\n\t\t\t\t\t\tof: this\n\t\t\t\t\t});\n\t\t\t\t\t$( document ).one( \"click\", function() {\n\t\t\t\t\t\tmenu.hide();\n\t\t\t\t\t});\n\t\t\t\t\treturn false;\n\t\t\t\t})\n\t\t\t\t.parent()\n\t\t\t\t\t.buttonset()\n\t\t\t\t\t.next()\n\t\t\t\t\t\t.hide()\n\t\t\t\t\t\t.menu();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n\t<div>\n\t\t<div>\n\t\t\t<button id=\"rerun\">Run last action</button>\n\t\t\t<button id=\"select\">Select an action</button>\n\t\t</div>\n\t\t<ul>\n\t\t\t<li><a href=\"#\">Open...</a></li>\n\t\t\t<li><a href=\"#\">Save</a></li>\n\t\t\t<li><a href=\"#\">Delete</a></li>\n\t\t</ul>\n\t</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n\n<p>An example of a split button built with two buttons: A plain button with just text, one with only a primary icon\nand no text. Both are grouped together in a set.</p>\n\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/button/toolbar.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button - Toolbar</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#toolbar {\n\t\tpadding: 10px 4px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#beginning\" ).button({\n\t\t\ttext: false,\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-seek-start\"\n\t\t\t}\n\t\t});\n\t\t$( \"#rewind\" ).button({\n\t\t\ttext: false,\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-seek-prev\"\n\t\t\t}\n\t\t});\n\t\t$( \"#play\" ).button({\n\t\t\ttext: false,\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-play\"\n\t\t\t}\n\t\t})\n\t\t.click(function() {\n\t\t\tvar options;\n\t\t\tif ( $( this ).text() === \"play\" ) {\n\t\t\t\toptions = {\n\t\t\t\t\tlabel: \"pause\",\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: \"ui-icon-pause\"\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\toptions = {\n\t\t\t\t\tlabel: \"play\",\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: \"ui-icon-play\"\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\t$( this ).button( \"option\", options );\n\t\t});\n\t\t$( \"#stop\" ).button({\n\t\t\ttext: false,\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-stop\"\n\t\t\t}\n\t\t})\n\t\t.click(function() {\n\t\t\t$( \"#play\" ).button( \"option\", {\n\t\t\t\tlabel: \"play\",\n\t\t\t\ticons: {\n\t\t\t\t\tprimary: \"ui-icon-play\"\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\t$( \"#forward\" ).button({\n\t\t\ttext: false,\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-seek-next\"\n\t\t\t}\n\t\t});\n\t\t$( \"#end\" ).button({\n\t\t\ttext: false,\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-seek-end\"\n\t\t\t}\n\t\t});\n\t\t$( \"#shuffle\" ).button();\n\t\t$( \"#repeat\" ).buttonset();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<span id=\"toolbar\" class=\"ui-widget-header ui-corner-all\">\n\t<button id=\"beginning\">go to beginning</button>\n\t<button id=\"rewind\">rewind</button>\n\t<button id=\"play\">play</button>\n\t<button id=\"stop\">stop</button>\n\t<button id=\"forward\">fast forward</button>\n\t<button id=\"end\">go to end</button>\n\t\n\t<input type=\"checkbox\" id=\"shuffle\" /><label for=\"shuffle\">Shuffle</label>\n\t\n\t<span id=\"repeat\">\n\t\t<input type=\"radio\" id=\"repeat0\" name=\"repeat\" checked=\"checked\" /><label for=\"repeat0\">No Repeat</label>\n\t\t<input type=\"radio\" id=\"repeat1\" name=\"repeat\" /><label for=\"repeat1\">Once</label>\n\t\t<input type=\"radio\" id=\"repeatall\" name=\"repeat\" /><label for=\"repeatall\">All</label>\n\t</span>\n</span>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tA mediaplayer toolbar. Take a look at the underlying markup: A few button elements,\n\tan input of type checkbox for the Shuffle button, and three inputs of type radio for the Repeat options. \n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/alt-field.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Populate alternate field</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\taltField: \"#alternate\",\n\t\t\taltFormat: \"DD, d MM, yy\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\">&nbsp;<input type=\"text\" id=\"alternate\" size=\"30\"/></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Populate an alternate field with its own date format whenever a date is selected using the <code>altField</code> and <code>altFormat</code> options.  This feature could be used to present a human-friendly date for user selection, while passing a more computer-friendly date through for further processing.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/animation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Animations</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../../ui/jquery.effects.slide.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker();\n\t\t$( \"#anim\" ).change(function() {\n\t\t\t$( \"#datepicker\" ).datepicker( \"option\", \"showAnim\", $( this ).val() );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\" size=\"30\"/></p>\n\n<p>Animations:<br />\n\t<select id=\"anim\">\n\t\t<option value=\"show\">Show (default)</option>\n\t\t<option value=\"slideDown\">Slide down</option>\n\t\t<option value=\"fadeIn\">Fade in</option>\n\t\t<option value=\"blind\">Blind (UI Effect)</option>\n\t\t<option value=\"bounce\">Bounce (UI Effect)</option>\n\t\t<option value=\"clip\">Clip (UI Effect)</option>\n\t\t<option value=\"drop\">Drop (UI Effect)</option>\n\t\t<option value=\"fold\">Fold (UI Effect)</option>\n\t\t<option value=\"slide\">Slide (UI Effect)</option>\n\t\t<option value=\"\">None</option>\n\t</select>\n</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Use different animations when opening or closing the datepicker.  Choose an animation from the dropdown, then click on the input to see its effect.  You can use one of the three standard animations or any of the UI Effects.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/buttonbar.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Display button bar</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\tshowButtonPanel: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Display a button for selecting Today's date and a Done button for closing the calendar with the boolean <code>showButtonPanel</code> option.  Each button is enabled by default when the bar is displayed, but can be turned off with additional options.  Button text is customizable.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/date-formats.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Format date</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker();\n\t\t$( \"#format\" ).change(function() {\n\t\t\t$( \"#datepicker\" ).datepicker( \"option\", \"dateFormat\", $( this ).val() );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\" size=\"30\"/></p>\n\n<p>Format options:<br />\n\t<select id=\"format\">\n\t\t<option value=\"mm/dd/yy\">Default - mm/dd/yy</option>\n\t\t<option value=\"yy-mm-dd\">ISO 8601 - yy-mm-dd</option>\n\t\t<option value=\"d M, y\">Short - d M, y</option>\n\t\t<option value=\"d MM, y\">Medium - d MM, y</option>\n\t\t<option value=\"DD, d MM, yy\">Full - DD, d MM, yy</option>\n\t\t<option value=\"'day' d 'of' MM 'in the year' yy\">With text - 'day' d 'of' MM 'in the year' yy</option>\n\t</select>\n</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Display date feedback in a variety of ways.  Choose a date format from the dropdown, then click on the input and select a date to see it in that format.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/date-range.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Select a Date Range</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#from\" ).datepicker({\n\t\t\tdefaultDate: \"+1w\",\n\t\t\tchangeMonth: true,\n\t\t\tnumberOfMonths: 3,\n\t\t\tonSelect: function( selectedDate ) {\n\t\t\t\t$( \"#to\" ).datepicker( \"option\", \"minDate\", selectedDate );\n\t\t\t}\n\t\t});\n\t\t$( \"#to\" ).datepicker({\n\t\t\tdefaultDate: \"+1w\",\n\t\t\tchangeMonth: true,\n\t\t\tnumberOfMonths: 3,\n\t\t\tonSelect: function( selectedDate ) {\n\t\t\t\t$( \"#from\" ).datepicker( \"option\", \"maxDate\", selectedDate );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<label for=\"from\">From</label>\n<input type=\"text\" id=\"from\" name=\"from\"/>\n<label for=\"to\">to</label>\n<input type=\"text\" id=\"to\" name=\"to\"/>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Select the date range to search for.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The datepicker is tied to a standard form input field.  Focus on the input (click, or use the tab key) to open an interactive calendar in a small overlay.  Choose a date, click elsewhere on the page (blur the input), or hit the Esc key to close. If a date is chosen, feedback is shown as the input's value.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/dropdown-month-year.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Display month &amp; year menus</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\tchangeMonth: true,\n\t\t\tchangeYear: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Show month and year dropdowns in place of the static month/year header to facilitate navigation through large timeframes.  Add the boolean <code>changeMonth</code> and <code>changeYear</code> options.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/icon-trigger.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Icon trigger</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\tshowOn: \"button\",\n\t\t\tbuttonImage: \"images/calendar.gif\",\n\t\t\tbuttonImageOnly: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the icon next to the input field to show the datepicker.  Set the datepicker to open on focus (default behavior), on icon click, or both.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"date-formats.html\">Format date</a></li>\n\t\t<li><a href=\"min-max.html\">Restrict date range</a></li>\n\t\t<li><a href=\"localization.html\">Localize calendar</a></li>\n\t\t<li><a href=\"alt-field.html\">Populate alternate field</a></li>\n\t\t<li><a href=\"inline.html\">Display inline</a></li>\n\t\t<li><a href=\"buttonbar.html\">Display button bar</a></li>\n\t\t<li><a href=\"dropdown-month-year.html\">Display month &amp; year menus</a></li>\t\t\n\t\t<li><a href=\"other-months.html\">Dates in other months</a></li>\t\t\n\t\t<li><a href=\"show-week.html\">Show week of the year</a></li>\t\t\n\t\t<li><a href=\"multiple-calendars.html\">Display multiple months</a></li>\t\t\n\t\t<li><a href=\"icon-trigger.html\">Icon trigger</a></li>\n\t\t<li><a href=\"animation.html\">Animations</a></li>\n\t\t<li><a href=\"date-range.html\">Date Range</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/inline.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Display inline</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\nDate: <div id=\"datepicker\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Display the datepicker embedded in the page instead of in an overlay.  Simply call .datepicker() on a div instead of an input.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/localization.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Localize calendar</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-af.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ar.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ar-DZ.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-az.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-bg.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-bs.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ca.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-cs.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-cy-GB.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-da.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-de.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-el.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-en-AU.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-en-GB.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-en-NZ.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-eo.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-es.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-et.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-eu.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-fa.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-fi.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-fo.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-fr.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-fr-CH.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-gl.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-he.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-hi.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-hr.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-hu.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-hy.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-id.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-is.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-it.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ja.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ka.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-kk.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-km.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ko.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-lb.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-lt.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-lv.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-mk.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ml.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ms.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-nl.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-nl-BE.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-no.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-pl.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-pt.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-pt-BR.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-rm.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ro.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ru.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-sk.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-sl.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-sq.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-sr.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-sr-SR.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-sv.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-ta.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-th.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-tj.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-tr.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-uk.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-vi.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-zh-CN.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-zh-HK.js\"></script>\n\t<script src=\"../../ui/i18n/jquery.ui.datepicker-zh-TW.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$.datepicker.setDefaults( $.datepicker.regional[ \"\" ] );\n\t\t$( \"#datepicker\" ).datepicker( $.datepicker.regional[ \"fr\" ] );\n\t\t$( \"#locale\" ).change(function() {\n\t\t\t$( \"#datepicker\" ).datepicker( \"option\",\n\t\t\t\t$.datepicker.regional[ $( this ).val() ] );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<p>Date: <input type=\"text\" id=\"datepicker\"/>&nbsp;\n\t<select id=\"locale\">\n\t\t<option value=\"af\">Afrikaans</option>\n\t\t<option value=\"sq\">Albanian (Gjuha shqipe)</option>\n\t\t<option value=\"ar-DZ\">Algerian Arabic</option>\n\t\t<option value=\"ar\">Arabic (&#8235;(&#1604;&#1593;&#1585;&#1576;&#1610;</option>\n\t\t<option value=\"hy\">Armenian (&#1344;&#1377;&#1397;&#1381;&#1408;&#1381;&#1398;)</option>\n\t\t<option value=\"az\">Azerbaijani (Az&#601;rbaycan dili)</option>\n\t\t<option value=\"eu\">Basque (Euskara)</option>\n\t\t<option value=\"bs\">Bosnian (Bosanski)</option>\n\t\t<option value=\"bg\">Bulgarian (&#1073;&#1098;&#1083;&#1075;&#1072;&#1088;&#1089;&#1082;&#1080; &#1077;&#1079;&#1080;&#1082;)</option>\n\t\t<option value=\"ca\">Catalan (Catal&agrave;)</option>\n\t\t<option value=\"zh-HK\">Chinese Hong Kong (&#32321;&#39636;&#20013;&#25991;)</option>\n\t\t<option value=\"zh-CN\">Chinese Simplified (&#31616;&#20307;&#20013;&#25991;)</option>\n\t\t<option value=\"zh-TW\">Chinese Traditional (&#32321;&#39636;&#20013;&#25991;)</option>\n\t\t<option value=\"hr\">Croatian (Hrvatski jezik)</option>\n\t\t<option value=\"cs\">Czech (&#269;e&#353;tina)</option>\n\t\t<option value=\"da\">Danish (Dansk)</option>\n\t\t<option value=\"nl-BE\">Dutch (Belgium)</option>\n\t\t<option value=\"nl\">Dutch (Nederlands)</option>\n\t\t<option value=\"en-AU\">English/Australia</option>\n\t\t<option value=\"en-NZ\">English/New Zealand</option>\n\t\t<option value=\"en-GB\">English/UK</option>\n\t\t<option value=\"eo\">Esperanto</option>\n\t\t<option value=\"et\">Estonian (eesti keel)</option>\n\t\t<option value=\"fo\">Faroese (f&oslash;royskt)</option>\n\t\t<option value=\"fa\">Farsi/Persian (&#8235;(&#1601;&#1575;&#1585;&#1587;&#1740;</option>\n\t\t<option value=\"fi\">Finnish (suomi)</option>\n\t\t<option value=\"fr\" selected=\"selected\">French (Fran&ccedil;ais)</option>\n\t\t<option value=\"fr-CH\">French/Swiss (Fran&ccedil;ais de Suisse)</option>\n\t\t<option value=\"gl\">Galician</option>\n\t\t<option value=\"ge\">Georgian</option>\n\t\t<option value=\"de\">German (Deutsch)</option>\n\t\t<option value=\"el\">Greek (&#917;&#955;&#955;&#951;&#957;&#953;&#954;&#940;)</option>\n\t\t<option value=\"he\">Hebrew (&#8235;(&#1506;&#1489;&#1512;&#1497;&#1514;</option>\n\t\t<option value=\"hi\">Hindi (&#2361;&#2367;&#2306;&#2342;&#2368;)</option>\n\t\t<option value=\"hu\">Hungarian (Magyar)</option>\n\t\t<option value=\"is\">Icelandic (&Otilde;slenska)</option>\n\t\t<option value=\"id\">Indonesian (Bahasa Indonesia)</option>\n\t\t<option value=\"it\">Italian (Italiano)</option>\n\t\t<option value=\"ja\">Japanese (&#26085;&#26412;&#35486;)</option>\n\t\t<option value=\"kk\">Kazakhstan (Kazakh)</option>\n\t\t<option value=\"km\">Khmer</option>\n\t\t<option value=\"ko\">Korean (&#54620;&#44397;&#50612;)</option>\n\t\t<option value=\"lv\">Latvian (Latvie&ouml;u Valoda)</option>\n\t\t<option value=\"lt\">Lithuanian (lietuviu kalba)</option>\n\t\t<option value=\"lb\">Luxembourgish</option>\n\t\t<option value=\"mk\">Macedonian</option>\n\t\t<option value=\"ml\">Malayalam</option>\n\t\t<option value=\"ms\">Malaysian (Bahasa Malaysia)</option>\n\t\t<option value=\"no\">Norwegian (Norsk)</option>\n\t\t<option value=\"pl\">Polish (Polski)</option>\n\t\t<option value=\"pt\">Portuguese (Portugu&ecirc;s)</option>\n\t\t<option value=\"pt-BR\">Portuguese/Brazilian (Portugu&ecirc;s)</option>\n\t\t<option value=\"rm\">Rhaeto-Romanic (Romansh)</option>\n\t\t<option value=\"ro\">Romanian (Rom&acirc;n&#259;)</option>\n\t\t<option value=\"ru\">Russian (&#1056;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;)</option>\n\t\t<option value=\"sr\">Serbian (&#1089;&#1088;&#1087;&#1089;&#1082;&#1080; &#1112;&#1077;&#1079;&#1080;&#1082;)</option>\n\t\t<option value=\"sr-SR\">Serbian (srpski jezik)</option>\n\t\t<option value=\"sk\">Slovak (Slovencina)</option>\n\t\t<option value=\"sl\">Slovenian (Slovenski Jezik)</option>\n\t\t<option value=\"es\">Spanish (Espa&ntilde;ol)</option>\n\t\t<option value=\"sv\">Swedish (Svenska)</option>\n\t\t<option value=\"ta\">Tamil (&#2980;&#2990;&#3007;&#2996;&#3021;)</option>\n\t\t<option value=\"th\">Thai (&#3616;&#3634;&#3625;&#3634;&#3652;&#3607;&#3618;)</option>\n\t\t<option value=\"tj\">Tajikistan</option>\n\t\t<option value=\"tr\">Turkish (T&uuml;rk&ccedil;e)</option>\n\t\t<option value=\"uk\">Ukranian (&#1059;&#1082;&#1088;&#1072;&#1111;&#1085;&#1089;&#1100;&#1082;&#1072;)</option>\n\t\t<option value=\"vi\">Vietnamese (Ti&#7871;ng Vi&#7879;t)</option>\n\t\t<option value=\"cy-GB\">Welsh/UK (Cymraeg)</option>\n\t</select></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Localize the datepicker calendar language and format (English / Western formatting is the default).  The datepicker includes built-in support for languages that read right-to-left, such as Arabic and Hebrew.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/min-max.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Restrict date range</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({ minDate: -20, maxDate: \"+1M +10D\" });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Restrict the range of selectable dates with the <code>minDate</code> and <code>maxDate</code> options.  Set the beginning and end dates as actual dates (new Date(2009, 1 - 1, 26)), as a numeric offset from today (-20), or as a string of periods and units ('+1M +10D').  For the last, use 'D' for days, 'W' for weeks, 'M' for months, or 'Y' for years.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/multiple-calendars.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Display multiple months</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\tnumberOfMonths: 3,\n\t\t\tshowButtonPanel: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Set the <code>numberOfMonths</code> option to an integer of 2 or more to show multiple months in a single datepicker.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/other-months.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Dates in other months</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\tshowOtherMonths: true,\n\t\t\tselectOtherMonths: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The datepicker can show dates that come from other than the main month\n\tbeing displayed. These other dates can also be made selectable.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/datepicker/show-week.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker - Show week of the year</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker({\n\t\t\tshowWeek: true,\n\t\t\tfirstDay: 1\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>Date: <input type=\"text\" id=\"datepicker\"></p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The datepicker can show the week of the year. The default calculation follows\n\tthe ISO 8601 definition: the week starts on Monday, the first week of the year\n\tcontains the first Thursday of the year. This means that some days from one\n\tyear may be placed into weeks 'belonging' to another year.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/demos.css",
    "content": "body {\n\tfont-size: 62.5%;\n}\n\ntable {\n\tfont-size: 1em;\n}\n\n/* Site\n   -------------------------------- */\n\nbody {\n\tfont-family: \"Trebuchet MS\", \"Helvetica\", \"Arial\",  \"Verdana\", \"sans-serif\";\n}\n\n/* Layout\n   -------------------------------- */\n\n.layout-grid {\n\twidth: 960px;\n\tborder-spacing: 0;\n\tborder-collapse: collapse;\n}\n\n.layout-grid td {\n\tvertical-align: top;\n}\n\n.layout-grid td.left-nav {\n\twidth: 140px;\n}\n\n.layout-grid td.normal {\n\tborder-left: 1px solid #eee;\n\tpadding: 20px 24px;\n\tfont-family: \"Trebuchet MS\", \"Helvetica\", \"Arial\",  \"Verdana\", \"sans-serif\";\n}\n\n.layout-grid td.demos {\n\tbackground: url('/images/demos_bg.jpg') no-repeat;\n\theight: 337px;\n\toverflow: hidden;\n}\n\n/* Normal\n   -------------------------------- */\n\n.normal h3,\n.normal h4 {\n\tmargin: 0;\n\tfont-weight: normal;\n}\n\n.normal h3 {\n\tpadding: 0 0 9px;\n\tfont-size: 1.8em;\n}\n\n.normal h4 {\n\tpadding-bottom: 21px;\n\tborder-bottom: 1px dashed #999;\n\tfont-size: 1.2em;\n\tfont-weight: bold;\n}\n\n.normal p {\n\tfont-size: 1.2em;\n}\n\n/* Demos */\n\n.demos-nav, .demos-nav dt, .demos-nav dd, .demos-nav ul, .demos-nav li {\n\tmargin: 0;\n\tpadding: 0\n}\n\n.demos-nav {\n\tfloat: left;\n\twidth: 170px;\n\tfont-size: 1.3em;\n}\n\n.demos-nav dt,\n.demos-nav h4 {\n\tmargin: 0;\n\tpadding: 0;\n\tfont: normal 1.1em \"Trebuchet MS\", \"Helvetica\", \"Arial\",  \"Verdana\", \"sans-serif\";\n\tcolor: #e87b10;\n}\n\n.demos-nav dt,\n.demos-nav h4 {\n\tmargin-top: 1.5em;\n\tmargin-bottom: 0;\n\tpadding-left: 8px;\n\tpadding-bottom:5px;\n\tline-height: 1.2em;\n\tborder-bottom: 1px solid #F4F4F4;\n}\n\n.demos-nav dd a,\n.demos-nav li a {\n\tborder-bottom: 1px solid #F4F4F4;\n\tdisplay:block;\n\tpadding: 4px 3px 4px 8px;\n\tfont-size: 90%;\n\ttext-decoration: none;\n\tcolor: #555 ;\n\tmargin:2px 0;\n\theight:13px;\n}\n\n.demos-nav dd a:hover,\n.demos-nav dd a:focus,\n.demos-nav dd a:hover,\n.demos-nav dd a:focus {\n\tbackground: #f3f3f3;\n\tcolor:#000;\n\t-moz-border-radius: 5px; -webkit-border-radius: 5px;\n}\n .demos-nav dd a.selected {\n\tbackground: #555;\n\tcolor:#ffffff;\n\t-moz-border-radius: 5px; -webkit-border-radius: 5px;\n}\n\n\n/* new styles for demo pages, added by Filament 12.29.08\neventually we should convert the font sizes to ems -- using px for now to minimize style conflicts\n*/\n\n.normal h3.demo-header { font-size:32px; padding:0 0 5px; border-bottom:1px solid #eee; text-transform: capitalize; }\n.normal h4.demo-subheader { font-size:10px; text-transform: uppercase; color:#999; padding:8px 0 3px; border:0; margin:0; }\n#demo-notes a, #demo-link a, #demo-source a { color:#1b75bb; text-decoration:none; }\n.normal a:hover,\n.normal a:active { color:#0b559b; }\n\n#demo-config { padding:20px 0 0; }\n\n#demo-frame { float:left; width:540px; height:380px; border:1px solid #ddd; overflow: auto; position: relative; }\n#demo-frame h3, #demo-frame h4 { padding: 0; font-weight: bold; font-size: 1em; }\n\n#demo-config-menu { float:right; width:180px;  }\n#demo-config-menu h4 { font-size:13px; color:#666; font-weight:normal; border:0; padding-left:18px; }\n\n#demo-config-menu ul { list-style: none; padding: 0; margin: 0; }\n\n#demo-config-menu li { font-size:12px; padding:0 0 0 10px; margin:3px 0; zoom: 1; }\n\n#demo-config-menu li a:link,\n#demo-config-menu li a:visited { display:block; padding:1px 8px 4px; border-bottom:1px dotted #b3b3b3; }\n* html #demo-config-menu li a:link,\n* html #demo-config-menu li a:visited { padding:1px 8px 2px; }\n#demo-config-menu li a:hover,\n#demo-config-menu li a:active { background-color:#f6f6f6; }\n\n#demo-config-menu li.demo-config-on { background: url(images/demo-config-on-tile.gif) repeat-x left center; }\n\n#demo-config-menu li.demo-config-on a:link,\n#demo-config-menu li.demo-config-on a:visited,\n#demo-config-menu li.demo-config-on a:hover,\n#demo-config-menu li.demo-config-on a:active { background: url(images/demo-config-on.gif) no-repeat left; padding-left:18px; color:#fff; border:0; margin-left:-10px; margin-top: 0px; margin-bottom: 0px; }\n\n#demo-source, #demo-notes {\n\tclear: both;\n\tpadding: 20px 0 0;\n\tfont-size: 1.3em;\n}\n\n#demo-notes { width:520px; color:#333; font-size: 1em; }\n#demo-notes p code, .demo-description p code { padding: 0; font-weight: bold; }\n#demo-source pre, #demo-source code { padding: 0; }\ncode, pre { padding:8px 0 8px 20px ; font-size: 1.2em; line-height:130%;  }\n\n#demo-source a:link,\n#demo-source a:visited,\n#demo-source a:hover,\n#demo-source a:active { font-size:12px; padding-left:13px; background-position: left center; background-repeat: no-repeat; }\n\n#demo-source a.source-open:link,\n#demo-source a.source-open:visited,\n#demo-source a.source-open:hover,\n#demo-source a.source-open:active { background-image: url(images/demo-spindown-open.gif); }\n\n#demo-source a.source-closed:link,\n#demo-source a.source-closed:visited,\n#demo-source a.source-closed:hover,\n#demo-source a.source-closed:active { background-image: url(images/demo-spindown-closed.gif); }\n\ndiv.demo {\n\tpadding:12px;\n\tfont-family: \"Trebuchet MS\", \"Arial\", \"Helvetica\", \"Verdana\", \"sans-serif\";\n}\n\ndiv.demo h3.docs { clear:left; font-size:12px; font-weight:normal; padding:0 0 1em; margin:0; }\n\ndiv.demo-description {\n\tclear:both;\n\tpadding:12px;\n\tfont-family: \"Trebuchet MS\", \"Arial\", \"Helvetica\", \"Verdana\", \"sans-serif\";\n\tfont-size: 1.3em;\n\tline-height: 1.4em;\n}\n\n.ui-draggable, .ui-droppable {\n\tbackground-position: top left;\n}\n\n.left-nav .demos-nav {\n\tpadding-right: 10px;\n}\n\n#demo-link { font-size:11px;  padding-top: 6px; clear: both; overflow: hidden; }\n#demo-link a span.ui-icon { float:left; margin-right:3px; }\n\n/* Component containers\n----------------------------------*/\n#widget-docs .ui-widget { font-family: Trebuchet MS,Verdana,Arial,sans-serif; font-size: 1em; }\n#widget-docs .ui-widget input, #widget-docs .ui-widget select, #widget-docs .ui-widget textarea, #widget-docs .ui-widget button { font-family: Trebuchet MS,Verdana,Arial,sans-serif; font-size: 1em; }\n#widget-docs .ui-widget-header { border: 1px solid #ffffff; background: #464646 url(images/464646_40x100_textures_01_flat_100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }\n#widget-docs .ui-widget-header a { color: #ffffff; }\n#widget-docs .ui-widget-content { border: 1px solid #ffffff; background: #ffffff url(images/ffffff_40x100_textures_01_flat_75.png) 50% 50% repeat-x; color: #222222; }\n#widget-docs .ui-widget-content a { color: #222222; }\n\n/* Interaction states\n----------------------------------*/\n#widget-docs .ui-state-default, #widget-docs .ui-widget-content #widget-docs .ui-state-default { border: 1px solid #666666; background: #555555 url(images/555555_40x100_textures_03_highlight_soft_75.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; outline: none; }\n#widget-docs .ui-state-default a { color: #ffffff; text-decoration: none; outline: none; }\n#widget-docs .ui-state-hover, #widget-docs .ui-widget-content #widget-docs .ui-state-hover, #widget-docs .ui-state-focus, #widget-docs .ui-widget-content #widget-docs .ui-state-focus { border: 1px solid #666666; background: #444444 url(images/444444_40x100_textures_03_highlight_soft_60.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; outline: none; }\n#widget-docs .ui-state-hover a { color: #ffffff; text-decoration: none; outline: none; }\n#widget-docs .ui-state-active, #widget-docs .ui-widget-content #widget-docs .ui-state-active { border: 1px solid #666666; background: #ffffff url(images/ffffff_40x100_textures_01_flat_65.png) 50% 50% repeat-x; font-weight: normal; color: #F6921E; outline: none; }\n#widget-docs .ui-state-active a { color: #F6921E; outline: none; text-decoration: none; }\n\n/* Interaction Cues\n----------------------------------*/\n#widget-docs .ui-state-highlight, #widget-docs .ui-widget-content #widget-docs .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/fbf9ee_40x100_textures_02_glass_55.png) 50% 50% repeat-x; color: #363636; }\n#widget-docs .ui-state-error, #widget-docs .ui-widget-content #widget-docs .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/fef1ec_40x100_textures_05_inset_soft_95.png) 50% bottom repeat-x; color: #cd0a0a; }\n#widget-docs .ui-state-error-text, #widget-docs .ui-widget-content #widget-docs .ui-state-error-text { color: #cd0a0a; }\n#widget-docs .ui-state-disabled, #widget-docs .ui-widget-content #widget-docs .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }\n#widget-docs .ui-priority-primary, #widget-docs .ui-widget-content #widget-docs .ui-priority-primary { font-weight: bold; }\n#widget-docs .ui-priority-secondary, #widget-docs .ui-widget-content #widget-docs .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n#demo-frame-wrapper .ui-icon, #widget-docs .ui-icon { width: 16px; height: 16px; background-image: url(images/222222_256x240_icons_icons.png); }\n#widget-docs .ui-widget-content .ui-icon {background-image: url(images/222222_256x240_icons_icons.png); }\n#widget-docs .ui-widget-header .ui-icon {background-image: url(images/222222_256x240_icons_icons.png); }\n#widget-docs .ui-state-default .ui-icon { background-image: url(images/888888_256x240_icons_icons.png); }\n#widget-docs .ui-state-hover .ui-icon, #widget-docs .ui-state-focus .ui-icon {background-image: url(images/454545_256x240_icons_icons.png); }\n#widget-docs .ui-state-active .ui-icon {background-image: url(images/454545_256x240_icons_icons.png); }\n#widget-docs .ui-state-highlight .ui-icon {background-image: url(images/2e83ff_256x240_icons_icons.png); }\n#widget-docs .ui-state-error .ui-icon, #widget-docs .ui-state-error-text .ui-icon {background-image: url(images/cd0a0a_256x240_icons_icons.png); }\n\n\n/* Misc visuals\n----------------------------------*/\n\n/* Corner radius */\n#widget-docs .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }\n#widget-docs .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }\n#widget-docs .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }\n#widget-docs .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }\n#widget-docs .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }\n#widget-docs .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }\n#widget-docs .ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }\n#widget-docs .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }\n#widget-docs .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }\n\n/* Overlays */\n#widget-docs .ui-widget-overlay { background: #aaaaaa url(images/aaaaaa_40x100_textures_01_flat_0.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }\n#widget-docs .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/aaaaaa_40x100_textures_01_flat_0.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }\n\n/*\n----------------------------------*/\n\n#widget-docs { margin:20px 0 0; border: none; }\n\n#widget-docs h2, #widget-docs h3, #widget-docs h4, #widget-docs p, #widget-docs ul, #widget-docs code { margin:0; padding:0; }\n#widget-docs code { display:block; color:#444; font-size:.9em; margin:0 0 1em; }\n#widget-docs code strong { color:#000; }\n#widget-docs p { margin:0 3em 1.2em 0; }\n#widget-docs p.intro { font-size:13px; color:#666; line-height:1.3; }\n#widget-docs ul { list-style-type: none; }\n\n#widget-docs h2 { font-size:16px; margin:1.2em 0 .5em; }\n#widget-docs h3 { font-size:14px; color:#e6820E; margin:1.5em 0 .5em; }\n.normal #widget-docs h4 { font-size:12px; color:#000; border:0; margin:0 0 .5em; }\n\n#docs-overview-main { width:400px; }\n#docs-overview-sidebar { float:right; width:200px; }\n#docs-overview-sidebar a span { color:#666; }\n#widget-docs #docs-overview-main p { margin-right:0; }\n#widget-docs #docs-overview-sidebar h4 { padding-left:0; }\n\n.docs-list-header { float:left; width:100%; margin:10px 0 0; border-bottom:1px solid #eee; }\n#widget-docs .docs-list-header h2 { float:left; margin:0; }\n#widget-docs .docs-list-header p { float:right; margin:5px 0; font-size:11px; }\n\n.docs-list { float:left; width:100%; padding:0 0 10px; }\n.docs-list .param-header { float:left; clear:left; width:100%; padding:8px 0; border-top:1px solid #eee; }\n#widget-docs .param-header h3, #widget-docs .param-header p { margin:0; float:left; }\n#widget-docs .param-header h3 { width:50%; }\n#widget-docs .param-header h3 span { background: url(images/demo-spindown-closed.gif) no-repeat left; padding-left:13px; }\n#widget-docs .param-open .param-header h3 span { background: url(images/demo-spindown-open.gif) no-repeat left; }\n#widget-docs .param-header p { width:24%; }\n#widget-docs .param-header p.param-type span { background: url(images/icon-docs-info.gif) no-repeat left; cursor:pointer; border-bottom:1px dashed #ccc; padding-left:15px; }\n\n.param-details { padding-left:13px; }\n.param-args { margin:0 0 1.5em; border-top:1px dotted #ccc;}\n.param-args td { padding:3px 30px 3px 5px; border-bottom:1px dotted #ccc;  }\n\n\n/* overrides for ui-tab styles */\n#widget-docs ul.ui-tabs-nav { padding:0 0 0 8px; }\n#widget-docs .ui-tabs-nav li { margin:5px 5px 0 0; }\n\n#widget-docs .ui-tabs-nav li a:link,\n#widget-docs .ui-tabs-nav li a:visited,\n#widget-docs .ui-tabs-nav li a:hover,\n#widget-docs .ui-tabs-nav li a:active { font-size:14px; padding:4px 1.2em 3px; color:#fff; }\n\n#widget-docs .ui-tabs-nav li.ui-tabs-active a:link,\n#widget-docs .ui-tabs-nav li.ui-tabs-active a:visited,\n#widget-docs .ui-tabs-nav li.ui-tabs-active a:hover,\n#widget-docs .ui-tabs-nav li.ui-tabs-active a:active { color:#e6820E; }\n\n#widget-docs .ui-tabs-panel { padding:20px 9px; font-size:12px; line-height:1.4; color:#000; }\n\n#widget-docs .ui-widget-content a:link,\n#widget-docs .ui-widget-content a:visited { color:#1b75bb; text-decoration:none; }\n#widget-docs .ui-widget-content a:hover,\n#widget-docs .ui-widget-content a:active { color:#0b559b; }\n\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/animated.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog - Animation</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../ui/jquery.effects.explode.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t// increase the default animation speed to exaggerate the effect\n\t$.fx.speeds._default = 1000;\n\t$(function() {\n\t\t$( \"#dialog\" ).dialog({\n\t\t\tautoOpen: false,\n\t\t\tshow: \"blind\",\n\t\t\thide: \"explode\"\n\t\t});\n\n\t\t$( \"#opener\" ).click(function() {\n\t\t\t$( \"#dialog\" ).dialog( \"open\" );\n\t\t\treturn false;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"dialog\" title=\"Basic dialog\">\n\t<p>This is an animated dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>\n</div>\n\n<button id=\"opener\">Open Dialog</button>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Dialogs may be animated by specifying an effect for the show and/or hide properties.  You must include the individual effects file for any effects you would like to use.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#dialog\" ).dialog();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"dialog\" title=\"Basic dialog\">\n\t<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>\n</div>\n\n<!-- Sample page content to illustrate the layering of the dialog -->\n<div class=\"hiddenInViewSource\" style=\"padding:20px;\">\n<p>Sed vel diam id libero <a href=\"http://example.com\">rutrum convallis</a>. Donec aliquet leo vel magna. Phasellus rhoncus faucibus ante. Etiam bibendum, enim faucibus aliquet rhoncus, arcu felis ultricies neque, sit amet auctor elit eros a lectus.</p>\n<form>\n\t<input value=\"text input\" /><br />\n\t<input type=\"checkbox\" />checkbox<br />\n\t<input type=\"radio\" />radio<br />\n\t<select>\n\t\t<option>select</option>\n\t</select><br /><br />\n\t<textarea>textarea</textarea><br />\n</form>\n</div><!-- End sample page content -->\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The basic dialog window is an overlay positioned within the viewport and is protected from page content (like select elements) shining through with an iframe.  It has a title bar and a content area, and can be moved, resized and closed with the 'x' icon by default.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"animated.html\">Animated dialog</a></li>\n\t\t<li><a href=\"modal.html\">Modal dialog</a></li>\n\t\t<li><a href=\"modal-message.html\">Modal message</a></li>\n\t\t<li><a href=\"modal-confirmation.html\">Modal confirmation</a></li>\n\t\t<li><a href=\"modal-form.html\">Modal form</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/modal-confirmation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog - Modal confirmation</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t// a workaround for a flaw in the demo system (http://dev.jqueryui.com/ticket/4375), ignore!\n\t\t$( \"#dialog:ui-dialog\" ).dialog( \"destroy\" );\n\t\n\t\t$( \"#dialog-confirm\" ).dialog({\n\t\t\tresizable: false,\n\t\t\theight:140,\n\t\t\tmodal: true,\n\t\t\tbuttons: {\n\t\t\t\t\"Delete all items\": function() {\n\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t},\n\t\t\t\tCancel: function() {\n\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"dialog-confirm\" title=\"Empty the recycle bin?\">\n\t<p><span class=\"ui-icon ui-icon-alert\" style=\"float:left; margin:0 7px 20px 0;\"></span>These items will be permanently deleted and cannot be recovered. Are you sure?</p>\n</div>\n\n<!-- Sample page content to illustrate the layering of the dialog -->\n<div class=\"hiddenInViewSource\" style=\"padding:20px;\">\n\t<p>Sed vel diam id libero <a href=\"http://example.com\">rutrum convallis</a>. Donec aliquet leo vel magna. Phasellus rhoncus faucibus ante. Etiam bibendum, enim faucibus aliquet rhoncus, arcu felis ultricies neque, sit amet auctor elit eros a lectus.</p>\n\t<form>\n\t\t<input value=\"text input\" /><br />\n\t\t<input type=\"checkbox\" />checkbox<br />\n\t\t<input type=\"radio\" />radio<br />\n\t\t<select>\n\t\t\t<option>select</option>\n\t\t</select><br /><br />\n\t\t<textarea>textarea</textarea><br />\n\t</form>\n</div><!-- End sample page content -->\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Confirm an action that may be destructive or important.  Set the <code>modal</code> option to true, and specify primary and secondary user actions with the <code>buttons</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/modal-form.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog - Modal form</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t\tbody { font-size: 62.5%; }\n\t\tlabel, input { display:block; }\n\t\tinput.text { margin-bottom:12px; width:95%; padding: .4em; }\n\t\tfieldset { padding:0; border:0; margin-top:25px; }\n\t\th1 { font-size: 1.2em; margin: .6em 0; }\n\t\tdiv#users-contain { width: 350px; margin: 20px 0; }\n\t\tdiv#users-contain table { margin: 1em 0; border-collapse: collapse; width: 100%; }\n\t\tdiv#users-contain table td, div#users-contain table th { border: 1px solid #eee; padding: .6em 10px; text-align: left; }\n\t\t.ui-dialog .ui-state-error { padding: .3em; }\n\t\t.validateTips { border: 1px solid transparent; padding: 0.3em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// a workaround for a flaw in the demo system (http://dev.jqueryui.com/ticket/4375), ignore!\n\t\t$( \"#dialog:ui-dialog\" ).dialog( \"destroy\" );\n\t\t\n\t\tvar name = $( \"#name\" ),\n\t\t\temail = $( \"#email\" ),\n\t\t\tpassword = $( \"#password\" ),\n\t\t\tallFields = $( [] ).add( name ).add( email ).add( password ),\n\t\t\ttips = $( \".validateTips\" );\n\n\t\tfunction updateTips( t ) {\n\t\t\ttips\n\t\t\t\t.text( t )\n\t\t\t\t.addClass( \"ui-state-highlight\" );\n\t\t\tsetTimeout(function() {\n\t\t\t\ttips.removeClass( \"ui-state-highlight\", 1500 );\n\t\t\t}, 500 );\n\t\t}\n\n\t\tfunction checkLength( o, n, min, max ) {\n\t\t\tif ( o.val().length > max || o.val().length < min ) {\n\t\t\t\to.addClass( \"ui-state-error\" );\n\t\t\t\tupdateTips( \"Length of \" + n + \" must be between \" +\n\t\t\t\t\tmin + \" and \" + max + \".\" );\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tfunction checkRegexp( o, regexp, n ) {\n\t\t\tif ( !( regexp.test( o.val() ) ) ) {\n\t\t\t\to.addClass( \"ui-state-error\" );\n\t\t\t\tupdateTips( n );\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\t$( \"#dialog-form\" ).dialog({\n\t\t\tautoOpen: false,\n\t\t\theight: 300,\n\t\t\twidth: 350,\n\t\t\tmodal: true,\n\t\t\tbuttons: {\n\t\t\t\t\"Create an account\": function() {\n\t\t\t\t\tvar bValid = true;\n\t\t\t\t\tallFields.removeClass( \"ui-state-error\" );\n\n\t\t\t\t\tbValid = bValid && checkLength( name, \"username\", 3, 16 );\n\t\t\t\t\tbValid = bValid && checkLength( email, \"email\", 6, 80 );\n\t\t\t\t\tbValid = bValid && checkLength( password, \"password\", 5, 16 );\n\n\t\t\t\t\tbValid = bValid && checkRegexp( name, /^[a-z]([0-9a-z_])+$/i, \"Username may consist of a-z, 0-9, underscores, begin with a letter.\" );\n\t\t\t\t\t// From jquery.validate.js (by joern), contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/\n\t\t\t\t\tbValid = bValid && checkRegexp( email, /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/i, \"eg. ui@jquery.com\" );\n\t\t\t\t\tbValid = bValid && checkRegexp( password, /^([0-9a-zA-Z])+$/, \"Password field only allow : a-z 0-9\" );\n\n\t\t\t\t\tif ( bValid ) {\n\t\t\t\t\t\t$( \"#users tbody\" ).append( \"<tr>\" +\n\t\t\t\t\t\t\t\"<td>\" + name.val() + \"</td>\" + \n\t\t\t\t\t\t\t\"<td>\" + email.val() + \"</td>\" + \n\t\t\t\t\t\t\t\"<td>\" + password.val() + \"</td>\" +\n\t\t\t\t\t\t\"</tr>\" ); \n\t\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tCancel: function() {\n\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\tclose: function() {\n\t\t\t\tallFields.val( \"\" ).removeClass( \"ui-state-error\" );\n\t\t\t}\n\t\t});\n\n\t\t$( \"#create-user\" )\n\t\t\t.button()\n\t\t\t.click(function() {\n\t\t\t\t$( \"#dialog-form\" ).dialog( \"open\" );\n\t\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"dialog-form\" title=\"Create new user\">\n\t<p class=\"validateTips\">All form fields are required.</p>\n\n\t<form>\n\t<fieldset>\n\t\t<label for=\"name\">Name</label>\n\t\t<input type=\"text\" name=\"name\" id=\"name\" class=\"text ui-widget-content ui-corner-all\" />\n\t\t<label for=\"email\">Email</label>\n\t\t<input type=\"text\" name=\"email\" id=\"email\" value=\"\" class=\"text ui-widget-content ui-corner-all\" />\n\t\t<label for=\"password\">Password</label>\n\t\t<input type=\"password\" name=\"password\" id=\"password\" value=\"\" class=\"text ui-widget-content ui-corner-all\" />\n\t</fieldset>\n\t</form>\n</div>\n\n\n<div id=\"users-contain\" class=\"ui-widget\">\n\t<h1>Existing Users:</h1>\n\t<table id=\"users\" class=\"ui-widget ui-widget-content\">\n\t\t<thead>\n\t\t\t<tr class=\"ui-widget-header \">\n\t\t\t\t<th>Name</th>\n\t\t\t\t<th>Email</th>\n\t\t\t\t<th>Password</th>\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr>\n\t\t\t\t<td>John Doe</td>\n\t\t\t\t<td>john.doe@example.com</td>\n\t\t\t\t<td>johndoe1</td>\n\t\t\t</tr>\n\t\t</tbody>\n\t</table>\n</div>\n<button id=\"create-user\">Create new user</button>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Use a modal dialog to require that the user enter data during a multi-step process.  Embed form markup in the content area, set the <code>modal</code> option to true, and specify primary and secondary user actions with the <code>buttons</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/modal-message.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog - Modal message</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t// a workaround for a flaw in the demo system (http://dev.jqueryui.com/ticket/4375), ignore!\n\t\t$( \"#dialog:ui-dialog\" ).dialog( \"destroy\" );\n\t\n\t\t$( \"#dialog-message\" ).dialog({\n\t\t\tmodal: true,\n\t\t\tbuttons: {\n\t\t\t\tOk: function() {\n\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"dialog-message\" title=\"Download complete\">\n\t<p>\n\t\t<span class=\"ui-icon ui-icon-circle-check\" style=\"float:left; margin:0 7px 50px 0;\"></span>\n\t\tYour files have downloaded successfully into the My Downloads folder.\n\t</p>\n\t<p>\n\t\tCurrently using <b>36% of your storage space</b>.\n\t</p>\n</div>\n\n<!-- Sample page content to illustrate the layering of the dialog -->\n<div class=\"hiddenInViewSource\" style=\"padding:20px;\">\n\t<p>Sed vel diam id libero <a href=\"http://example.com\">rutrum convallis</a>. Donec aliquet leo vel magna. Phasellus rhoncus faucibus ante. Etiam bibendum, enim faucibus aliquet rhoncus, arcu felis ultricies neque, sit amet auctor elit eros a lectus.</p>\n\t<form>\n\t\t<input value=\"text input\" /><br />\n\t\t<input type=\"checkbox\" />checkbox<br />\n\t\t<input type=\"radio\" />radio<br />\n\t\t<select>\n\t\t\t<option>select</option>\n\t\t</select><br /><br />\n\t\t<textarea>textarea</textarea><br />\n\t</form>\n</div><!-- End sample page content -->\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Use a modal dialog to explicitly acknowledge information or an action before continuing their work.  Set the <code>modal</code> option to true, and specify a primary action (Ok) with the <code>buttons</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/dialog/modal.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog - Basic modal</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t// a workaround for a flaw in the demo system (http://dev.jqueryui.com/ticket/4375), ignore!\n\t\t$( \"#dialog:ui-dialog\" ).dialog( \"destroy\" );\n\t\n\t\t$( \"#dialog-modal\" ).dialog({\n\t\t\theight: 140,\n\t\t\tmodal: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"dialog-modal\" title=\"Basic modal dialog\">\n\t<p>Adding the modal overlay screen makes the dialog look more prominent because it dims out the page content.</p>\n</div>\n\n<!-- Sample page content to illustrate the layering of the dialog -->\n<div class=\"hiddenInViewSource\" style=\"padding:20px;\">\n\t<p>Sed vel diam id libero <a href=\"http://example.com\">rutrum convallis</a>. Donec aliquet leo vel magna. Phasellus rhoncus faucibus ante. Etiam bibendum, enim faucibus aliquet rhoncus, arcu felis ultricies neque, sit amet auctor elit eros a lectus.</p>\n\t<form>\n\t\t<input value=\"text input\" /><br />\n\t\t<input type=\"checkbox\" />checkbox<br />\n\t\t<input type=\"radio\" />radio<br />\n\t\t<select>\n\t\t\t<option>select</option>\n\t\t</select><br /><br />\n\t\t<textarea>textarea</textarea><br />\n\t</form>\n</div><!-- End sample page content -->\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A modal dialog prevents the user from interacting with the rest of the page until it is closed.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/constrain-movement.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Constrain movement</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.draggable { width: 90px; height: 90px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t#draggable, #draggable2 { margin-bottom:20px; }\n\t#draggable { cursor: n-resize; }\n\t#draggable2 { cursor: e-resize; }\n\t#containment-wrapper { width: 95%; height:150px; border:2px solid #ccc; padding: 10px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ axis: \"y\" });\n\t\t$( \"#draggable2\" ).draggable({ axis: \"x\" });\n\n\t\t$( \"#draggable3\" ).draggable({ containment: \"#containment-wrapper\", scroll: false });\n\t\t$( \"#draggable4\" ).draggable({ containment: \"#demo-frame\" });\n\t\t$( \"#draggable5\" ).draggable({ containment: \"parent\" });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<h3 class=\"docs\">Constrain movement along an axis:</h3>\n\t\n<div id=\"draggable\" class=\"draggable ui-widget-content\">\n\t<p>I can be dragged only vertically</p>\n</div>\n\n<div id=\"draggable2\" class=\"draggable ui-widget-content\">\n\t<p>I can be dragged only horizontally</p>\n</div>\n\n<h3 class=\"docs\">Or to within another DOM element:</h3>\n<div id=\"containment-wrapper\">\n<div id=\"draggable3\" class=\"draggable ui-widget-content\">\n\t<p>I'm contained within the box</p>\n</div>\n\n<div id=\"draggable4\" class=\"draggable ui-widget-content\">\n\t<p>I'm contained within the box's parent</p>\n</div>\n\n<div class=\"draggable ui-widget-content\">\n\t<p id=\"draggable5\" class=\"ui-widget-header\">I'm contained within my parent</p>\n</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Constrain the movement of each draggable by defining the boundaries of the draggable area. Set the <code>axis</code> option to limit the draggable's path to the x- or y-axis, or use the <code>containment</code> option to specify a parent DOM element or a jQuery selector, like 'document.'</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/cursor-style.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Cursor style</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2, #draggable3 { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ cursor: \"move\", cursorAt: { top: 56, left: 56 } });\n\t\t$( \"#draggable2\" ).draggable({ cursor: \"crosshair\", cursorAt: { top: -5, left: -5 } });\n\t\t$( \"#draggable3\" ).draggable({ cursorAt: { bottom: 0 } });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>I will always stick to the center (relative to the mouse)</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>My cursor is at left -5 and top -5</p>\n</div>\n\n<div id=\"draggable3\" class=\"ui-widget-content\">\n\t<p>My cursor position is only controlled for the 'bottom' value</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Position the cursor while dragging the object. By default the cursor appears in the center of the dragged object; use the <code>cursorAt</code> option to specify another location relative to the draggable (specify a pixel value from the top, right, bottom, and/or left).  Customize the cursor's appearance by supplying the <code>cursor</code> option with a valid CSS cursor value: default, move, pointer, crosshair, etc.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable { width: 150px; height: 150px; padding: 0.5em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Drag me around</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Enable draggable functionality on any DOM element. Move the draggable object by clicking on it with the mouse and dragging it anywhere within the viewport.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/delay-start.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Delay start</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2 { width: 120px; height: 120px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ distance: 20 });\n\t\t$( \"#draggable2\" ).draggable({ delay: 1000 });\n\t\t$( \".ui-draggable\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Only if you drag me by 20 pixels, the dragging will start</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>Regardless of the distance, you have to drag and wait for 1000ms before dragging starts</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Delay the start of dragging for a number of milliseconds with the <code>delay</code> option; prevent dragging until the cursor is held down and dragged a specifed number of pixels with the <code>distance</code> option. </p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/events.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Events</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable { width: 16em; padding: 0 1em; }\n\t#draggable ul li { margin: 1em 0; padding: 0.5em 0; } * html #draggable ul li { height: 1%; }\n\t#draggable ul li span.ui-icon { float: left; }\n\t#draggable ul li span.count { font-weight: bold; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar $start_counter = $( \"#event-start\" ),\n\t\t\t$drag_counter = $( \"#event-drag\" ),\n\t\t\t$stop_counter = $( \"#event-stop\" ),\n\t\t\tcounts = [ 0, 0, 0 ];\n\n\t\t$( \"#draggable\" ).draggable({\n\t\t\tstart: function() {\n\t\t\t\tcounts[ 0 ]++;\n\t\t\t\tupdateCounterStatus( $start_counter, counts[ 0 ] );\n\t\t\t},\n\t\t\tdrag: function() {\n\t\t\t\tcounts[ 1 ]++;\n\t\t\t\tupdateCounterStatus( $drag_counter, counts[ 1 ] );\n\t\t\t},\n\t\t\tstop: function() {\n\t\t\t\tcounts[ 2 ]++;\n\t\t\t\tupdateCounterStatus( $stop_counter, counts[ 2 ] );\n\t\t\t}\n\t\t});\n\n\t\tfunction updateCounterStatus( $event_counter, new_count ) {\n\t\t\t// first update the status visually...\n\t\t\tif ( !$event_counter.hasClass( \"ui-state-hover\" ) ) {\n\t\t\t\t$event_counter.addClass( \"ui-state-hover\" )\n\t\t\t\t\t.siblings().removeClass( \"ui-state-hover\" );\n\t\t\t}\n\t\t\t// ...then update the numbers\n\t\t\t$( \"span.count\", $event_counter ).text( new_count );\n\t\t}\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"draggable\" class=\"ui-widget ui-widget-content\">\n\n\t<p>Drag me to trigger the chain of events.</p>\n\n\t<ul class=\"ui-helper-reset\">\n\t\t<li id=\"event-start\" class=\"ui-state-default ui-corner-all\"><span class=\"ui-icon ui-icon-play\"></span>\"start\" invoked <span class=\"count\">0</span>x</li>\n\t\t<li id=\"event-drag\" class=\"ui-state-default ui-corner-all\"><span class=\"ui-icon ui-icon-arrow-4\"></span>\"drag\" invoked <span class=\"count\">0</span>x</li>\n\t\t<li id=\"event-stop\" class=\"ui-state-default ui-corner-all\"><span class=\"ui-icon ui-icon-stop\"></span>\"stop\" invoked <span class=\"count\">0</span>x</li>\n\t</ul>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Layer functionality onto the draggable using the <code>start</code>, <code>drag</code>, and <code>stop</code> events.  Start is fired at the start of the drag; drag during the drag; and stop when dragging stops.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/handle.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Handles</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2 { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t#draggable p { cursor: move; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ handle: \"p\" });\n\t\t$( \"#draggable2\" ).draggable({ cancel: \"p.ui-widget-header\" });\n\t\t$( \"div, p\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p class=\"ui-widget-header\">I can be dragged only by this handle</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>You can drag me around&hellip;</p>\n\t<p class=\"ui-widget-header\">&hellip;but you can't drag me by this handle.</p>\n</div>\n\n<!-- ADD CANCEL DEMO -->\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Allow dragging only when the cursor is over a specific part of the draggable.  Use the <code>handle</code> option to specify the jQuery selector of an element (or group of elements) used to drag the object.</p>\n<p>Or prevent dragging when the cursor is over a specific element (or group of elements) within the draggable.  Use the <code>cancel</code> option to specify a jQuery selector over which to \"cancel\" draggable functionality.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"events.html\">Events</a></li>\n\t\t<li><a href=\"constrain-movement.html\">Constrain movement</a></li>\n\t\t<li><a href=\"delay-start.html\">Delay start</a></li>\n\t\t<li><a href=\"snap-to.html\">Snap to element or&#160;grid</a></li>\n\t\t<li><a href=\"scroll.html\">Auto-scroll</a></li>\n\t\t<li><a href=\"revert.html\">Revert position</a></li>\n\t\t<li><a href=\"visual-feedback.html\">Visual feedback</a></li>\n\t\t<li><a href=\"handle.html\">Drag handle</a></li>\n\t\t<li><a href=\"cursor-style.html\">Cursor style</a></li>\n\t\t<li><a href=\"sortable.html\">Draggable + Sortable</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/revert.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Revert position</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2 { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ revert: true });\n\t\t$( \"#draggable2\" ).draggable({ revert: true, helper: \"clone\" });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Revert the original</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>Revert the helper</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Return the draggable (or it's helper) to its original location when dragging stops with the boolean <code>revert</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/scroll.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Auto-scroll</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2, #draggable3 { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ scroll: true });\n\t\t$( \"#draggable2\" ).draggable({ scroll: true, scrollSensitivity: 100 });\n\t\t$( \"#draggable3\" ).draggable({ scroll: true, scrollSpeed: 100 });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Scroll set to true, default settings</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>scrollSensitivity set to 100</p>\n</div>\n\n<div id=\"draggable3\" class=\"ui-widget-content\">\n\t<p>scrollSpeed set to 100</p>\n</div>\n\n<div style='height: 5000px; width: 1px;'></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Automatically scroll the document when the draggable is moved beyond the viewport. Set the <code>scroll</code> option to true to enable auto-scrolling, and fine-tune when scrolling is triggered and its speed with the <code>scrollSensitivity</code> and <code>scrollSpeed</code> options.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/snap-to.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Snap to element or grid</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.draggable { width: 90px; height: 80px; padding: 5px; float: left; margin: 0 10px 10px 0; font-size: .9em; }\n\t.ui-widget-header p, .ui-widget-content p { margin: 0; }\n\t#snaptarget { height: 140px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ snap: true });\n\t\t$( \"#draggable2\" ).draggable({ snap: \".ui-widget-header\" });\n\t\t$( \"#draggable3\" ).draggable({ snap: \".ui-widget-header\", snapMode: \"outer\" });\n\t\t$( \"#draggable4\" ).draggable({ grid: [ 20,20 ] });\n\t\t$( \"#draggable5\" ).draggable({ grid: [ 80, 80 ] });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"snaptarget\" class=\"ui-widget-header\">\n\t<p>I'm a snap target</p>\n</div>\n\n<br style=\"clear:both\" />\n\n<div id=\"draggable\" class=\"draggable ui-widget-content\">\n\t<p>Default (snap: true), snaps to all other draggable elements</p>\n</div>\n\n<div id=\"draggable2\" class=\"draggable ui-widget-content\">\n\t<p>I only snap to the big box</p>\n</div>\n\n<div id=\"draggable3\" class=\"draggable ui-widget-content\">\n\t<p>I only snap to the outer edges of the big box</p>\n</div>\n\n<div id=\"draggable4\" class=\"draggable ui-widget-content\">\n\t<p>I snap to a 20 x 20 grid</p>\n</div>\n\n<div id=\"draggable5\" class=\"draggable ui-widget-content\">\n\t<p>I snap to a 80 x 80 grid</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Snap the draggable to the inner or outer boundaries of a DOM element.  Use the <code>snap</code>, <code>snapMode</code> (inner, outer, both), and <code>snapTolerance</code> (distance in pixels the draggable must be from the element when snapping is invoked) options. </p>\n<p>Or snap the draggable to a grid.  Set the dimensions of grid cells (height and width in pixels) with the <code>grid</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/sortable.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable + Sortable</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.demo ul { list-style-type: none; margin: 0; padding: 0; margin-bottom: 10px; }\n\t.demo li { margin: 5px; padding: 5px; width: 150px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable\" ).sortable({\n\t\t\trevert: true\n\t\t});\n\t\t$( \"#draggable\" ).draggable({\n\t\t\tconnectToSortable: \"#sortable\",\n\t\t\thelper: \"clone\",\n\t\t\trevert: \"invalid\"\n\t\t});\n\t\t$( \"ul, li\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<ul>\n\t<li id=\"draggable\" class=\"ui-state-highlight\">Drag me down</li>\n</ul>\n\n<ul id=\"sortable\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default\">Item 2</li>\n\t<li class=\"ui-state-default\">Item 3</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n\t<li class=\"ui-state-default\">Item 5</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Draggables are built to interact seamlessly with <a href=\"#\">sortables</a>.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/draggable/visual-feedback.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable - Visual feedback</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2, #draggable3, #set div { width: 90px; height: 90px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }\n\t#draggable, #draggable2, #draggable3 { margin-bottom:20px; }\n\t#set { clear:both; float:left; width: 368px; height: 120px; }\n\tp { clear:both; margin:0; padding:1em 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ helper: \"original\" });\n\t\t$( \"#draggable2\" ).draggable({ opacity: 0.7, helper: \"clone\" });\n\t\t$( \"#draggable3\" ).draggable({\n\t\t\tcursor: \"move\",\n\t\t\tcursorAt: { top: -12, left: -20 },\n\t\t\thelper: function( event ) {\n\t\t\t\treturn $( \"<div class='ui-widget-header'>I'm a custom helper</div>\" );\n\t\t\t}\n\t\t});\n\t\t$( \"#set div\" ).draggable({ stack: \"#set div\" });\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<h3 class=\"docs\">With helpers:</h3>\n\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Original</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>Semi-transparent clone</p>\n</div>\n\n<div id=\"draggable3\" class=\"ui-widget-content\">\n\t<p>Custom helper (in combination with cursorAt)</p>\n</div>\n\n<h3 class=\"docs\">Stacked:</h3>\n<div id=\"set\">\n\t<div class=\"ui-widget-content\">\n\t\t<p>We are draggables..</p>\n\t</div>\n\n\t<div class=\"ui-widget-content\">\n\t\t<p>..whose z-indexes are controlled automatically..</p>\n\t</div>\n\n\t<div class=\"ui-widget-content\">\n\t\t<p>..with the stack option.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Provide feedback to users as they drag an object in the form of a helper. The <code>helper</code> option accepts the values 'original' (the draggable object moves with the cursor), 'clone' (a duplicate of the draggable moves with the cursor), or a function that returns a DOM element (that element is shown near the cursor during drag). Control the helper's transparency with the <code>opacity</code> option.</p>\n<p>To clarify which draggable is in play, bring the draggable in motion to front. Use the <code>zIndex</code> option to set a higher z-index for the helper, if in play, or use the <code>stack</code> option to ensure that the last item dragged will appear on top of others in the same group on drag stop.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/accepted-elements.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Accept</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#droppable { width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px; }\n\t#draggable, #draggable-nonvalid { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 10px 10px 10px 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable, #draggable-nonvalid\" ).draggable();\n\t\t$( \"#droppable\" ).droppable({\n\t\t\taccept: \"#draggable\",\n\t\t\tactiveClass: \"ui-state-hover\",\n\t\t\thoverClass: \"ui-state-active\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable-nonvalid\" class=\"ui-widget-content\">\n\t<p>I'm draggable but can't be dropped</p>\n</div>\n\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Drag me to my target</p>\n</div>\n\n<div id=\"droppable\" class=\"ui-widget-header\">\n\t<p>accept: '#draggable'</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Specify using the <code>accept</code> option which element (or group of elements) is accepted by the target droppable.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 10px 10px 10px 0; }\n\t#droppable { width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable();\n\t\t$( \"#droppable\" ).droppable({\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Drag me to my target</p>\n</div>\n\n<div id=\"droppable\" class=\"ui-widget-header\">\n\t<p>Drop here</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Enable any DOM element to be droppable, a target for draggable elements.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"accepted-elements.html\">Accepted elements</a></li>\n\t\t<li><a href=\"propagation.html\">Prevent propagation</a></li>\n\t\t<li><a href=\"visual-feedback.html\">Visual feedback</a></li>\n\t\t<li><a href=\"revert.html\">Revert draggable position</a></li>\n\t\t<li><a href=\"shopping-cart.html\">Shopping Cart</a></li>\n\t\t<li><a href=\"photo-manager.html\">Simple photo manager</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/photo-manager.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Simple photo manager</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#gallery { float: left; width: 65%; min-height: 12em; } * html #gallery { height: 12em; } /* IE6 */\n\t.gallery.custom-state-active { background: #eee; }\n\t.gallery li { float: left; width: 96px; padding: 0.4em; margin: 0 0.4em 0.4em 0; text-align: center; }\n\t.gallery li h5 { margin: 0 0 0.4em; cursor: move; }\n\t.gallery li a { float: right; }\n\t.gallery li a.ui-icon-zoomin { float: left; }\n\t.gallery li img { width: 100%; cursor: move; }\n\n\t#trash { float: right; width: 32%; min-height: 18em; padding: 1%;} * html #trash { height: 18em; } /* IE6 */\n\t#trash h4 { line-height: 16px; margin: 0 0 0.4em; }\n\t#trash h4 .ui-icon { float: left; }\n\t#trash .gallery h5 { display: none; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// there's the gallery and the trash\n\t\tvar $gallery = $( \"#gallery\" ),\n\t\t\t$trash = $( \"#trash\" );\n\n\t\t// let the gallery items be draggable\n\t\t$( \"li\", $gallery ).draggable({\n\t\t\tcancel: \"a.ui-icon\", // clicking an icon won't initiate dragging\n\t\t\trevert: \"invalid\", // when not dropped, the item will revert back to its initial position\n\t\t\tcontainment: $( \"#demo-frame\" ).length ? \"#demo-frame\" : \"document\", // stick to demo-frame if present\n\t\t\thelper: \"clone\",\n\t\t\tcursor: \"move\"\n\t\t});\n\n\t\t// let the trash be droppable, accepting the gallery items\n\t\t$trash.droppable({\n\t\t\taccept: \"#gallery > li\",\n\t\t\tactiveClass: \"ui-state-highlight\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\tdeleteImage( ui.draggable );\n\t\t\t}\n\t\t});\n\n\t\t// let the gallery be droppable as well, accepting items from the trash\n\t\t$gallery.droppable({\n\t\t\taccept: \"#trash li\",\n\t\t\tactiveClass: \"custom-state-active\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\trecycleImage( ui.draggable );\n\t\t\t}\n\t\t});\n\n\t\t// image deletion function\n\t\tvar recycle_icon = \"<a href='link/to/recycle/script/when/we/have/js/off' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>\";\n\t\tfunction deleteImage( $item ) {\n\t\t\t$item.fadeOut(function() {\n\t\t\t\tvar $list = $( \"ul\", $trash ).length ?\n\t\t\t\t\t$( \"ul\", $trash ) :\n\t\t\t\t\t$( \"<ul class='gallery ui-helper-reset'/>\" ).appendTo( $trash );\n\n\t\t\t\t$item.find( \"a.ui-icon-trash\" ).remove();\n\t\t\t\t$item.append( recycle_icon ).appendTo( $list ).fadeIn(function() {\n\t\t\t\t\t$item\n\t\t\t\t\t\t.animate({ width: \"48px\" })\n\t\t\t\t\t\t.find( \"img\" )\n\t\t\t\t\t\t\t.animate({ height: \"36px\" });\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\t// image recycle function\n\t\tvar trash_icon = \"<a href='link/to/trash/script/when/we/have/js/off' title='Delete this image' class='ui-icon ui-icon-trash'>Delete image</a>\";\n\t\tfunction recycleImage( $item ) {\n\t\t\t$item.fadeOut(function() {\n\t\t\t\t$item\n\t\t\t\t\t.find( \"a.ui-icon-refresh\" )\n\t\t\t\t\t\t.remove()\n\t\t\t\t\t.end()\n\t\t\t\t\t.css( \"width\", \"96px\")\n\t\t\t\t\t.append( trash_icon )\n\t\t\t\t\t.find( \"img\" )\n\t\t\t\t\t\t.css( \"height\", \"72px\" )\n\t\t\t\t\t.end()\n\t\t\t\t\t.appendTo( $gallery )\n\t\t\t\t\t.fadeIn();\n\t\t\t});\n\t\t}\n\n\t\t// image preview function, demonstrating the ui.dialog used as a modal window\n\t\tfunction viewLargerImage( $link ) {\n\t\t\tvar src = $link.attr( \"href\" ),\n\t\t\t\ttitle = $link.siblings( \"img\" ).attr( \"alt\" ),\n\t\t\t\t$modal = $( \"img[src$='\" + src + \"']\" );\n\n\t\t\tif ( $modal.length ) {\n\t\t\t\t$modal.dialog( \"open\" );\n\t\t\t} else {\n\t\t\t\tvar img = $( \"<img alt='\" + title + \"' width='384' height='288' style='display: none; padding: 8px;' />\" )\n\t\t\t\t\t.attr( \"src\", src ).appendTo( \"body\" );\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\timg.dialog({\n\t\t\t\t\t\ttitle: title,\n\t\t\t\t\t\twidth: 400,\n\t\t\t\t\t\tmodal: true\n\t\t\t\t\t});\n\t\t\t\t}, 1 );\n\t\t\t}\n\t\t}\n\n\t\t// resolve the icons behavior with event delegation\n\t\t$( \"ul.gallery > li\" ).click(function( event ) {\n\t\t\tvar $item = $( this ),\n\t\t\t\t$target = $( event.target );\n\n\t\t\tif ( $target.is( \"a.ui-icon-trash\" ) ) {\n\t\t\t\tdeleteImage( $item );\n\t\t\t} else if ( $target.is( \"a.ui-icon-zoomin\" ) ) {\n\t\t\t\tviewLargerImage( $target );\n\t\t\t} else if ( $target.is( \"a.ui-icon-refresh\" ) ) {\n\t\t\t\trecycleImage( $item );\n\t\t\t}\n\n\t\t\treturn false;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo ui-widget ui-helper-clearfix\">\n\n<ul id=\"gallery\" class=\"gallery ui-helper-reset ui-helper-clearfix\">\n\t<li class=\"ui-widget-content ui-corner-tr\">\n\t\t<h5 class=\"ui-widget-header\">High Tatras</h5>\n\t\t<img src=\"images/high_tatras_min.jpg\" alt=\"The peaks of High Tatras\" width=\"96\" height=\"72\" />\n\t\t<a href=\"images/high_tatras.jpg\" title=\"View larger image\" class=\"ui-icon ui-icon-zoomin\">View larger</a>\n\t\t<a href=\"link/to/trash/script/when/we/have/js/off\" title=\"Delete this image\" class=\"ui-icon ui-icon-trash\">Delete image</a>\n\t</li>\n\t<li class=\"ui-widget-content ui-corner-tr\">\n\t\t<h5 class=\"ui-widget-header\">High Tatras 2</h5>\n\t\t<img src=\"images/high_tatras2_min.jpg\" alt=\"The chalet at the Green mountain lake\" width=\"96\" height=\"72\" />\n\t\t<a href=\"images/high_tatras2.jpg\" title=\"View larger image\" class=\"ui-icon ui-icon-zoomin\">View larger</a>\n\t\t<a href=\"link/to/trash/script/when/we/have/js/off\" title=\"Delete this image\" class=\"ui-icon ui-icon-trash\">Delete image</a>\n\t</li>\n\t<li class=\"ui-widget-content ui-corner-tr\">\n\t\t<h5 class=\"ui-widget-header\">High Tatras 3</h5>\n\t\t<img src=\"images/high_tatras3_min.jpg\" alt=\"Planning the ascent\" width=\"96\" height=\"72\" />\n\t\t<a href=\"images/high_tatras3.jpg\" title=\"View larger image\" class=\"ui-icon ui-icon-zoomin\">View larger</a>\n\t\t<a href=\"link/to/trash/script/when/we/have/js/off\" title=\"Delete this image\" class=\"ui-icon ui-icon-trash\">Delete image</a>\n\t</li>\n\t<li class=\"ui-widget-content ui-corner-tr\">\n\t\t<h5 class=\"ui-widget-header\">High Tatras 4</h5>\n\t\t<img src=\"images/high_tatras4_min.jpg\" alt=\"On top of Kozi kopka\" width=\"96\" height=\"72\" />\n\t\t<a href=\"images/high_tatras4.jpg\" title=\"View larger image\" class=\"ui-icon ui-icon-zoomin\">View larger</a>\n\t\t<a href=\"link/to/trash/script/when/we/have/js/off\" title=\"Delete this image\" class=\"ui-icon ui-icon-trash\">Delete image</a>\n\t</li>\n</ul>\n\n<div id=\"trash\" class=\"ui-widget-content ui-state-default\">\n\t<h4 class=\"ui-widget-header\"><span class=\"ui-icon ui-icon-trash\">Trash</span> Trash</h4>\n</div>\n\n</div><!-- End demo -->\n\n\n<div class=\"demo-description\">\n<p>You can delete an image either by dragging it to the Trash or by clicking the trash icon.</p>\n<p>You can \"recycle\" an image by dragging it back to the gallery or by clicking the recycle icon.</p>\n<p>You can view larger image by clicking the zoom icon. jQuery UI dialog widget is used for the modal window.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/propagation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Prevent propagation</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable { width: 100px; height: 40px; padding: 0.5em; float: left; margin: 10px 10px 10px 0; }\n\t#droppable, #droppable2 { width: 230px; height: 120px; padding: 0.5em; float: left; margin: 10px; }\n\t#droppable-inner, #droppable2-inner { width: 170px; height: 60px; padding: 0.5em; float: left; margin: 10px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable();\n\n\t\t$( \"#droppable, #droppable-inner\" ).droppable({\n\t\t\tactiveClass: \"ui-state-hover\",\n\t\t\thoverClass: \"ui-state-active\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"> p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\t$( \"#droppable2, #droppable2-inner\" ).droppable({\n\t\t\tgreedy: true,\n\t\t\tactiveClass: \"ui-state-hover\",\n\t\t\thoverClass: \"ui-state-active\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"> p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Drag me to my target</p>\n</div>\n\n<div id=\"droppable\" class=\"ui-widget-header\">\n\t<p>Outer droppable</p>\n\t<div id=\"droppable-inner\" class=\"ui-widget-header\">\n\t\t<p>Inner droppable (not greedy)</p>\n\t</div>\n</div>\n\n<div id=\"droppable2\" class=\"ui-widget-header\">\n\t<p>Outer droppable</p>\n\t<div id=\"droppable2-inner\" class=\"ui-widget-header\">\n\t\t<p>Inner droppable (greedy)</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>When working with nested droppables &#8212; for example, you may have an editable directory structure displayed as a tree, with folder and document nodes &#8212; the <code>greedy</code> option set to true prevents event propagation when a draggable is dropped on a child node (droppable).</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/revert.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Revert draggable position</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2 { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 10px 10px 10px 0; }\n\t#droppable { width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable({ revert: \"valid\" });\n\t\t$( \"#draggable2\" ).draggable({ revert: \"invalid\" });\n\n\t\t$( \"#droppable\" ).droppable({\n\t\t\tactiveClass: \"ui-state-hover\",\n\t\t\thoverClass: \"ui-state-active\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>I revert when I'm dropped</p>\n</div>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>I revert when I'm not dropped</p>\n</div>\n\n<div id=\"droppable\" class=\"ui-widget-header\">\n\t<p>Drop me here</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Return the draggable (or it's helper) to its original location when dragging stops with the boolean <code>revert</code> option set on the draggable.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/shopping-cart.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Shopping Cart Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\th1 { padding: .2em; margin: 0; }\n\t#products { float:left; width: 500px; margin-right: 2em; }\n\t#cart { width: 200px; float: left; }\n\t/* style the list to maximize the droppable hitarea */\n\t#cart ol { margin: 0; padding: 1em 0 1em 3em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#catalog\" ).accordion();\n\t\t$( \"#catalog li\" ).draggable({\n\t\t\tappendTo: \"body\",\n\t\t\thelper: \"clone\"\n\t\t});\n\t\t$( \"#cart ol\" ).droppable({\n\t\t\tactiveClass: \"ui-state-default\",\n\t\t\thoverClass: \"ui-state-hover\",\n\t\t\taccept: \":not(.ui-sortable-helper)\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this ).find( \".placeholder\" ).remove();\n\t\t\t\t$( \"<li></li>\" ).text( ui.draggable.text() ).appendTo( this );\n\t\t\t}\n\t\t}).sortable({\n\t\t\titems: \"li:not(.placeholder)\",\n\t\t\tsort: function() {\n\t\t\t\t// gets added unintentionally by droppable interacting with sortable\n\t\t\t\t// using connectWithSortable fixes this, but doesn't allow you to customize active/hoverClass options\n\t\t\t\t$( this ).removeClass( \"ui-state-default\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"products\">\n\t<h1 class=\"ui-widget-header\">Products</h1>\t\n\t<div id=\"catalog\">\n\t\t<h3><a href=\"#\">T-Shirts</a></h3>\n\t\t<div>\n\t\t\t<ul>\n\t\t\t\t<li>Lolcat Shirt</li>\n\t\t\t\t<li>Cheezeburger Shirt</li>\n\t\t\t\t<li>Buckit Shirt</li>\n\t\t\t</ul>\n\t\t</div>\n\t\t<h3><a href=\"#\">Bags</a></h3>\n\t\t<div>\n\t\t\t<ul>\n\t\t\t\t<li>Zebra Striped</li>\n\t\t\t\t<li>Black Leather</li>\n\t\t\t\t<li>Alligator Leather</li>\n\t\t\t</ul>\n\t\t</div>\n\t\t<h3><a href=\"#\">Gadgets</a></h3>\n\t\t<div>\n\t\t\t<ul>\n\t\t\t\t<li>iPhone</li>\n\t\t\t\t<li>iPod</li>\n\t\t\t\t<li>iPad</li>\n\t\t\t</ul>\n\t\t</div>\n\t</div>\n</div>\n\n<div id=\"cart\">\n\t<h1 class=\"ui-widget-header\">Shopping Cart</h1>\n\t<div class=\"ui-widget-content\">\n\t\t<ol>\n\t\t\t<li class=\"placeholder\">Add your items here</li>\n\t\t</ol>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Demonstrate how to use an accordion to structure products into a catalog and make use drag and drop for adding them to a shopping cart, where they are sortable.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/droppable/visual-feedback.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable - Visual feedback</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#draggable, #draggable2 { width: 90px; height: 90px; padding: 0.5em; float: left; margin: 10px 10px 10px 0; }\n\t#droppable, #droppable2 { width: 120px; height: 120px; padding: 0.5em; float: left; margin: 10px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#draggable\" ).draggable();\n\t\t$( \"#droppable\" ).droppable({\n\t\t\thoverClass: \"ui-state-active\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t}\n\t\t});\n\n\t\t$( \"#draggable2\" ).draggable();\n\t\t$( \"#droppable2\" ).droppable({\n\t\t\taccept: \"#draggable2\",\n\t\t\tactiveClass: \"ui-state-hover\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-state-highlight\" )\n\t\t\t\t\t.find( \"p\" )\n\t\t\t\t\t\t.html( \"Dropped!\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<h3 class=\"docs\">Feedback on hover:</h3>\n\t\n<div id=\"draggable\" class=\"ui-widget-content\">\n\t<p>Drag me to my target</p>\n</div>\n\n<div id=\"droppable\" class=\"ui-widget-header\">\n\t<p>Drop here</p>\n</div>\n\n<h3 class=\"docs\">Feedback on activating draggable:</h3>\n\n<div id=\"draggable2\" class=\"ui-widget-content\">\n\t<p>Drag me to my target</p>\n</div>\n\n<div id=\"droppable2\" class=\"ui-widget-header\">\n\t<p>Drop here</p>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Change the droppable's appearance on hover, or when the droppable is active (an acceptable draggable is dropped on it).  Use the <code>hoverClass</code> or <code>activeClass</code> options to specify respective classes.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/effect/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - Effect demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../ui/jquery.effects.explode.js\"></script>\n\t<script src=\"../../ui/jquery.effects.fade.js\"></script>\n\t<script src=\"../../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../../ui/jquery.effects.highlight.js\"></script>\n\t<script src=\"../../ui/jquery.effects.pulsate.js\"></script>\n\t<script src=\"../../ui/jquery.effects.scale.js\"></script>\n\t<script src=\"../../ui/jquery.effects.shake.js\"></script>\n\t<script src=\"../../ui/jquery.effects.slide.js\"></script>\n\t<script src=\"../../ui/jquery.effects.transfer.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t\t.toggler { width: 500px; height: 200px; position: relative; }\n\t\t#button { padding: .5em 1em; text-decoration: none; }\n\t\t#effect { width: 240px; height: 135px; padding: 0.4em; position: relative; }\n\t\t#effect h3 { margin: 0; padding: 0.4em; text-align: center; }\n\t\t.ui-effects-transfer { border: 2px dotted gray; } \n\t</style>\n\t<script>\n\t$(function() {\n\t\t// run the currently selected effect\n\t\tfunction runEffect() {\n\t\t\t// get effect type from \n\t\t\tvar selectedEffect = $( \"#effectTypes\" ).val();\n\t\t\t\n\t\t\t// most effect types need no options passed by default\n\t\t\tvar options = {};\n\t\t\t// some effects have required parameters\n\t\t\tif ( selectedEffect === \"scale\" ) {\n\t\t\t\toptions = { percent: 0 };\n\t\t\t} else if ( selectedEffect === \"transfer\" ) {\n\t\t\t\toptions = { to: \"#button\", className: \"ui-effects-transfer\" };\n\t\t\t} else if ( selectedEffect === \"size\" ) {\n\t\t\t\toptions = { to: { width: 200, height: 60 } };\n\t\t\t}\n\n\t\t\t// run the effect\n\t\t\t$( \"#effect\" ).effect( selectedEffect, options, 500, callback );\n\t\t};\n\n\t\t// callback function to bring a hidden box back\n\t\tfunction callback() {\n\t\t\tsetTimeout(function() {\n\t\t\t\t$( \"#effect\" ).removeAttr( \"style\" ).hide().fadeIn();\n\t\t\t}, 1000 );\n\t\t};\n\n\t\t// set effect from select menu value\n\t\t$( \"#button\" ).click(function() {\n\t\t\trunEffect();\n\t\t\treturn false;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"ui-widget-content ui-corner-all\">\n\t\t<h3 class=\"ui-widget-header ui-corner-all\">Effect</h3>\n\t\t<p>\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. Nulla lorem metus, adipiscing ut, luctus sed, hendrerit vitae, mi.\n\t\t</p>\n\t</div>\n</div>\n\n<select name=\"effects\" id=\"effectTypes\">\n\t<option value=\"blind\">Blind</option>\n\t<option value=\"bounce\">Bounce</option>\n\t<option value=\"clip\">Clip</option>\n\t<option value=\"drop\">Drop</option>\n\t<option value=\"explode\">Explode</option>\n\t<option value=\"fade\">Fade</option>\n\t<option value=\"fold\">Fold</option>\n\t<option value=\"highlight\">Highlight</option>\n\t<option value=\"puff\">Puff</option>\n\t<option value=\"pulsate\">Pulsate</option>\n\t<option value=\"scale\">Scale</option>\n\t<option value=\"shake\">Shake</option>\n\t<option value=\"size\">Size</option>\n\t<option value=\"slide\">Slide</option>\n\t<option value=\"transfer\">Transfer</option>\n</select>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to show the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/effect/easing.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - Easing demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.graph {\n\t\tfloat: left;\n\t\tmargin-left: 10px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tif ( !$( \"<canvas>\" )[0].getContext ) {\n\t\t\t$( \"<div>\" ).text(\n\t\t\t\t\"Your browser doesn't support canvas, which is required for this demo.\"\n\t\t\t).appendTo( \"#graphs\" );\n\t\t\treturn;\n\t\t}\n\n\t\tvar i = 0,\n\t\t\twidth = 100,\n\t\t\theight = 100;\n\n\t\t$.each( $.easing, function( name, impl ) {\n\t\t\tvar graph = $( \"<div>\" ).addClass( \"graph\" ).appendTo( \"#graphs\" ),\n\t\t\t\ttext = $( \"<div>\" ).text( ++i + \". \" + name ).appendTo( graph ),\n\t\t\t\twrap = $( \"<div>\" ).appendTo( graph ).css( 'overflow', 'hidden' ),\n\t\t\t\tcanvas = $( \"<canvas>\" ).appendTo( wrap )[ 0 ];\n\n\t\t\tcanvas.width = width;\n\t\t\tcanvas.height = height;\n\t\t\tvar drawHeight = height * 0.8,\n\t\t\t\tcradius = 10;\n\t\t\t\tctx = canvas.getContext( \"2d\" );\n\t\t\tctx.fillStyle = \"black\";\n\n\t\t\t// draw background\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo( cradius, 0 );\n\t\t\tctx.quadraticCurveTo( 0, 0, 0, cradius );\n\t\t\tctx.lineTo( 0, height - cradius );\n\t\t\tctx.quadraticCurveTo( 0, height, cradius, height );\n\t\t\tctx.lineTo( width - cradius, height );\n\t\t\tctx.quadraticCurveTo( width, height, width, height - cradius );\n\t\t\tctx.lineTo( width, 0 );\n\t\t\tctx.lineTo( cradius, 0 );\n\t\t\tctx.fill();\n\n\t\t\t// draw bottom line\n\t\t\tctx.strokeStyle = \"#555\";\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo( width * 0.1, drawHeight + .5 );\n\t\t\tctx.lineTo( width * 0.9, drawHeight + .5 );\n\t\t\tctx.stroke();\n\n\t\t\t// draw top line\n\t\t\tctx.strokeStyle = \"#555\";\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo( width * 0.1, drawHeight * .3 - .5 );\n\t\t\tctx.lineTo( width * 0.9, drawHeight * .3 - .5 );\n\t\t\tctx.stroke();\n\n\t\t\t// plot easing\n\t\t\tctx.strokeStyle = \"white\";\n\t\t\tctx.beginPath();\n\t\t\tctx.lineWidth = 2;\n\t\t\tctx.moveTo( width * 0.1, drawHeight );\n\t\t\t$.each( new Array( width ), function( position ) {\n\t\t\t\tvar state = position / width,\n\t\t\t\t\tval = impl( state, position, 0, 1, width );\n\t\t\t\tctx.lineTo( position * 0.8 + width * 0.1,\n\t\t\t\t\tdrawHeight - drawHeight * val * 0.7 );\n\t\t\t});\n\t\t\tctx.stroke();\n\n\t\t\t// animate on click\n\t\t\tgraph.click(function() {\n\t\t\t\twrap\n\t\t\t\t\t.animate( { height: \"hide\" }, 2000, name )\n\t\t\t\t\t.delay( 800 )\n\t\t\t\t\t.animate( { height: \"show\" }, 2000, name );\n\t\t\t});\n\n\t\t\tgraph.width( width ).height( height + text.height() + 10 );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"graphs\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p><strong>All easings provided by jQuery UI are drawn above, using a HTML canvas element</strong>. Click a diagram to see the easing in action.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/effect/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Effect showcase</a></li>\n\t\t<li><a href=\"easing.html\">Easing showcase</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/hide/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - Hide Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../ui/jquery.effects.explode.js\"></script>\n\t<script src=\"../../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../../ui/jquery.effects.highlight.js\"></script>\n\t<script src=\"../../ui/jquery.effects.pulsate.js\"></script>\n\t<script src=\"../../ui/jquery.effects.scale.js\"></script>\n\t<script src=\"../../ui/jquery.effects.shake.js\"></script>\n\t<script src=\"../../ui/jquery.effects.slide.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.toggler { width: 500px; height: 200px; }\n\t#button { padding: .5em 1em; text-decoration: none; }\n\t#effect { width: 240px; height: 135px; padding: 0.4em; position: relative; }\n\t#effect h3 { margin: 0; padding: 0.4em; text-align: center; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// run the currently selected effect\n\t\tfunction runEffect() {\n\t\t\t// get effect type from \n\t\t\tvar selectedEffect = $( \"#effectTypes\" ).val();\n\n\t\t\t// most effect types need no options passed by default\n\t\t\tvar options = {};\n\t\t\t// some effects have required parameters\n\t\t\tif ( selectedEffect === \"scale\" ) {\n\t\t\t\toptions = { percent: 0 };\n\t\t\t} else if ( selectedEffect === \"size\" ) {\n\t\t\t\toptions = { to: { width: 200, height: 60 } };\n\t\t\t}\n\n\t\t\t// run the effect\n\t\t\t$( \"#effect\" ).hide( selectedEffect, options, 1000, callback );\n\t\t};\n\n\t\t// callback function to bring a hidden box back\n\t\tfunction callback() {\n\t\t\tsetTimeout(function() {\n\t\t\t\t$( \"#effect\" ).removeAttr( \"style\" ).hide().fadeIn();\n\t\t\t}, 1000 );\n\t\t};\n\n\t\t// set effect from select menu value\n\t\t$( \"#button\" ).click(function() {\n\t\t\trunEffect();\n\t\t\treturn false;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"ui-widget-content ui-corner-all\">\n\t\t<h3 class=\"ui-widget-header ui-corner-all\">Hide</h3>\n\t\t<p>\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. Nulla lorem metus, adipiscing ut, luctus sed, hendrerit vitae, mi.\n\t\t</p>\n\t</div>\n</div>\n\n<select name=\"effects\" id=\"effectTypes\">\n\t<option value=\"blind\">Blind</option>\n\t<option value=\"bounce\">Bounce</option>\n\t<option value=\"clip\">Clip</option>\n\t<option value=\"drop\">Drop</option>\n\t<option value=\"explode\">Explode</option>\n\t<option value=\"fold\">Fold</option>\n\t<option value=\"highlight\">Highlight</option>\n\t<option value=\"puff\">Puff</option>\n\t<option value=\"pulsate\">Pulsate</option>\n\t<option value=\"scale\">Scale</option>\n\t<option value=\"shake\">Shake</option>\n\t<option value=\"size\">Size</option>\n\t<option value=\"slide\">Slide</option>\n</select>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/hide/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Demos</title>\n\t<link rel=\"stylesheet\" href=\"../themes/base/jquery.ui.all.css\">\n\t<link rel=\"stylesheet\" href=\"demos.css\">\n\t<script src=\"../jquery-1.7.2.js\"></script>\n\t<script src=\"../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../external/globalize.js\"></script>\n\t<script src=\"../external/globalize.culture.de-DE.js\"></script>\n\t<script src=\"../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../ui/jquery.ui.autocomplete.js\"></script>\n\t<script src=\"../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../ui/jquery.ui.datepicker.js\"></script>\n\t<script src=\"../ui/jquery.ui.dialog.js\"></script>\n\t<script src=\"../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../ui/jquery.ui.droppable.js\"></script>\n\t<script src=\"../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../ui/jquery.ui.progressbar.js\"></script>\n\t<script src=\"../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../ui/jquery.ui.selectable.js\"></script>\n\t<script src=\"../ui/jquery.ui.slider.js\"></script>\n\t<script src=\"../ui/jquery.ui.sortable.js\"></script>\n\t<script src=\"../ui/jquery.ui.spinner.js\"></script>\n\t<script src=\"../ui/jquery.ui.tabs.js\"></script>\n\t<script src=\"../ui/jquery.ui.tooltip.js\"></script>\n\t<script src=\"../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../ui/jquery.effects.explode.js\"></script>\n\t<script src=\"../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../ui/jquery.effects.highlight.js\"></script>\n\t<script src=\"../ui/jquery.effects.pulsate.js\"></script>\n\t<script src=\"../ui/jquery.effects.scale.js\"></script>\n\t<script src=\"../ui/jquery.effects.shake.js\"></script>\n\t<script src=\"../ui/jquery.effects.slide.js\"></script>\n\t<script src=\"../ui/jquery.effects.transfer.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-af.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ar.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ar-DZ.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-az.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-bs.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-bg.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ca.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-cs.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-cy-GB.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-da.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-de.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-el.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-en-AU.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-en-GB.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-en-NZ.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-eo.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-es.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-et.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-eu.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-fa.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-fi.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-fo.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-fr.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-fr-CH.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-gl.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-he.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-hi.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-hr.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-hu.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-hy.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-id.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-is.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-it.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ja.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ka.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-kk.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-km.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ko.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-lb.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-lt.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-lv.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-mk.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ml.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ms.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-nl.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-nl-BE.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-no.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-pl.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-pt.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-pt-BR.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-rm.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ro.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ru.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-sk.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-sl.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-sq.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-sr.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-sr-SR.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-sv.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-ta.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-th.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-tj.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-tr.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-uk.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-vi.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-zh-CN.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-zh-HK.js\"></script>\n\t<script src=\"../ui/i18n/jquery.ui.datepicker-zh-TW.js\"></script>\n\t<script>\n\t$(function() {\n\n\t\t$('.left-nav a').click(function(ev) {\n\t\t\twindow.location.hash = this.href.replace(/.+\\/([^\\/]+)\\/index\\.html/,'$1') + '|default';\n\t\t\tloadPage(this.href);\n\t\t\t$('.left-nav a.selected').removeClass('selected');\n\t\t\t$(this).addClass('selected');\n\t\t\tev.preventDefault();\n\t\t});\n\n\t\tif (window.location.hash) {\n\t\t\tif (window.location.hash.indexOf('|') === -1) {\n\t\t\t\twindow.location.hash += '|default';\n\t\t\t}\n\t\t\tvar path = window.location.href.replace(/(index\\.html)?#/,'');\n\t\t\tpath = path.replace('\\|','/') + '.html';\n\t\t\tloadPage(path);\n\t\t}\n\n\t\tfunction loadPage(path) {\n\t\t\tvar section = path.replace(/\\/[^\\/]+\\.html/,'');\n\t\t\tvar header = section.replace(/.+\\/([^\\/]+)/,'$1').replace(/_/, ' ');\n\n\t\t\t$('td.normal div.normal')\n\t\t\t\t.empty()\n\t\t\t\t.append('<h4 class=\"demo-subheader\">Functional demo:</h4>')\n\t\t\t\t.append('<h3 class=\"demo-header\">'+ header +'</h3>')\n\t\t\t\t.append('<div id=\"demo-config\"></div>')\n\t\t\t\t.find('#demo-config')\n\t\t\t\t\t.append('<div id=\"demo-frame\"></div><div id=\"demo-config-menu\"></div><div id=\"demo-link\"><a class=\"demoWindowLink\" href=\"#\"><span class=\"ui-icon ui-icon-newwin\"></span>Open demo in a new window</a></div>')\n\t\t\t\t\t.find('#demo-config-menu')\n\t\t\t\t\t\t.load(section + '/index.html .demos-nav', function() {\n\t\t\t\t\t\t\t$('#demo-config-menu a').each(function() {\n\t\t\t\t\t\t\t\tthis.setAttribute('href', section + '/' + this.getAttribute('href').replace(/.+\\/([^\\/]+)/,'$1'));\n\t\t\t\t\t\t\t\t$(this).attr('target', 'demo-frame');\n\t\t\t\t\t\t\t\t$(this).click(function() {\n\n\t\t\t\t\t\t\t\t\tresetDemos();\n\n\t\t\t\t\t\t\t\t\t$(this).parents('ul').find('li').removeClass('demo-config-on');\n\t\t\t\t\t\t\t\t\t$(this).parent().addClass('demo-config-on');\n\t\t\t\t\t\t\t\t\t$('#demo-notes').fadeOut();\n\n\t\t\t\t\t\t\t\t\t//Set the hash to the actual page without \".html\"\n\t\t\t\t\t\t\t\t\twindow.location.hash = header + '|' + this.getAttribute('href').match((/\\/([^\\/\\\\]+)\\.html/))[1];\n\n\t\t\t\t\t\t\t\t\tloadDemo(this.getAttribute('href'));\n\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (window.location.hash) {\n\t\t\t\t\t\t\t\tvar demo = window.location.hash.split('|')[1];\n\t\t\t\t\t\t\t\t$('#demo-config-menu a').each(function(){\n\t\t\t\t\t\t\t\t\tif (this.href.indexOf(demo + '.html') !== -1) {\n\t\t\t\t\t\t\t\t\t\t$(this).parents('ul').find('li').removeClass('demo-config-on');\n\t\t\t\t\t\t\t\t\t\t$(this).parent().addClass('demo-config-on');\n\t\t\t\t\t\t\t\t\t\tloadDemo(this.href);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tupdateDemoNotes();\n\t\t\t\t\t\t})\n\t\t\t\t\t.end()\n\t\t\t\t\t.find('#demo-link a')\n\t\t\t\t\t\t.bind('click', function(ev){\n\t\t\t\t\t\t\twindow.open(this.href);\n\t\t\t\t\t\t\tev.preventDefault();\n\t\t\t\t\t\t})\n\t\t\t\t\t.end()\n\t\t\t\t.end()\n\t\t\t;\n\n\t\t\tresetDemos();\n\t\t}\n\n\t\tfunction loadDemo(path) {\n\t\t\tvar directory = path.match(/([^\\/]+)\\/[^\\/\\.]+\\.html$/)[1];\n\t\t\t$.get(path, function(data) {\n\t\t\t\tvar source = data;\n\t\t\t\tdata = data.replace(/<script.*>.*<\\/script>/ig,\"\"); // Remove script tags\n\t\t\t\tdata = data.replace(/<\\/?link.*>/ig,\"\"); //Remove link tags\n\t\t\t\tdata = data.replace(/<\\/?html.*>/ig,\"\"); //Remove html tag\n\t\t\t\tdata = data.replace(/<\\/?body.*>/ig,\"\"); //Remove body tag\n\t\t\t\tdata = data.replace(/<\\/?head.*>/ig,\"\"); //Remove head tag\n\t\t\t\tdata = data.replace(/<\\/?!doctype.*>/ig,\"\"); //Remove doctype\n\t\t\t\tdata = data.replace(/<title.*>.*<\\/title>/ig,\"\"); // Remove title tags\n\t\t\t\tdata = data.replace(/((href|src)=[\"'])(?!(http|#))/ig, \"$1\" + directory + \"/\");\n\n\t\t\t\t$('#demo-style').remove();\n\t\t\t\t$('#demo-frame').empty().html(data);\n\t\t\t\t$('#demo-frame style').clone().appendTo('head').attr('id','demo-style');\n\t\t\t\t$('#demo-link a').attr('href', path);\n\t\t\t\tupdateDemoNotes();\n\t\t\t\tupdateDemoSource(source);\n\n\t\t\t\tif (/default.html$/.test(path)) {\n\t\t\t\t\t$.get(\"documentation/docs-\" + path.match(/demos\\/(.+)\\//)[1] + \".html\", function(html) {\n\t\t\t\t\t\t$(\"#demo-source\").after(html);\n\t\t\t\t\t\t$(\"#widget-docs\").tabs();\n\t\t\t\t\t\t$(\".param-header\").click(function() {\n\t\t\t\t\t\t\t$(this).parent().toggleClass(\"param-open\").end().next().toggle();\n\t\t\t\t\t\t});\n\t\t\t\t\t\t$(\".docs-list-header\").each(function() {\n\t\t\t\t\t\t\tvar header = $(this);\n\t\t\t\t\t\t\tvar details = header.next().find(\".param-details\").hide();\n\t\t\t\t\t\t\t$(\"a:first\", header).click(function() {\n\t\t\t\t\t\t\t\tdetails.show().parent().addClass(\"param-open\");\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t$(\"a:last\", header).click(function() {\n\t\t\t\t\t\t\t\tdetails.hide().parent().removeClass(\"param-open\");\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t}, \"html\" );\n\t\t\t\t}\n\t\t\t}, \"html\" );\n\t\t}\n\n\t\tfunction updateDemoNotes() {\n\t\t\tvar notes = $('#demo-frame .demo-description');\n\t\t\tif ($('#demo-notes').length == 0) {\n\t\t\t\t$('<div id=\"demo-notes\"></div>').insertAfter('#demo-config');\n\t\t\t}\n\t\t\t$('#demo-notes').hide().empty().html(notes.html());\n\t\t\t$('#demo-notes').show();\n\t\t\tnotes.hide();\n\t\t}\n\n\t\tfunction updateDemoSource(source) {\n\t\t\tif ($('#demo-source').length == 0) {\n\t\t\t\t$('<div id=\"demo-source\"><a href=\"#\" class=\"source-closed\">View Source</a><div><pre><code></code></pre></div></div>').insertAfter('#demo-notes');\n\t\t\t\t$('#demo-source').find(\">a\").click(function() {\n\t\t\t\t\t$(this).toggleClass(\"source-closed\").toggleClass(\"source-open\").next().toggle();\n\t\t\t\t\treturn false;\n\t\t\t\t}).end().find(\">div\").hide();\n\t\t\t}\n\t\t\tvar cleanedSource = source\n\t\t\t\t.replace('themes/base/jquery.ui.all.css', 'theme/jquery.ui.all.css')\n\t\t\t\t.replace(/\\s*\\x3Clink.*demos\\x2Ecss.*\\x3E\\s*/, '\\r\\n\\t')\n\t\t\t\t.replace(/\\x2E\\x2E\\x2F\\x2E\\x2E\\x2F/g, '');\n\n\t\t\t$('#demo-source code').empty().text(cleanedSource);\n\t\t}\n\n\t\tfunction resetDemos() {\n\t\t\t$.datepicker.setDefaults($.extend({showMonthAfterYear: false}, $.datepicker.regional['']));\n\t\t\t$(\".ui-dialog-content\").remove();\n\t\t}\n\n\t});\n\t</script>\n</head>\n<body>\n\n<table class=\"layout-grid\">\n\t<tr>\n\t\t<td class=\"left-nav\">\n\t\t\t<dl class=\"demos-nav\">\n\t\t\t\t<dt>Interactions</dt>\n\t\t\t\t\t<dd><a href=\"draggable/index.html\">Draggable</a></dd>\n\t\t\t\t\t<dd><a href=\"droppable/index.html\">Droppable</a></dd>\n\t\t\t\t\t<dd><a href=\"resizable/index.html\">Resizable</a></dd>\n\t\t\t\t\t<dd><a href=\"selectable/index.html\">Selectable</a></dd>\n\t\t\t\t\t<dd><a href=\"sortable/index.html\">Sortable</a></dd>\n\t\t\t\t<dt>Widgets</dt>\n\t\t\t\t\t<dd><a href=\"accordion/index.html\">Accordion</a></dd>\n\t\t\t\t\t<dd><a href=\"autocomplete/index.html\">Autocomplete</a></dd>\n\t\t\t\t\t<dd><a href=\"button/index.html\">Button</a></dd>\n\t\t\t\t\t<dd><a href=\"datepicker/index.html\">Datepicker</a></dd>\n\t\t\t\t\t<dd><a href=\"dialog/index.html\">Dialog</a></dd>\n\t\t\t\t\t<dd><a href=\"menu/index.html\">Menu</a></dd>\n\t\t\t\t\t<dd><a href=\"progressbar/index.html\">Progressbar</a></dd>\n\t\t\t\t\t<dd><a href=\"slider/index.html\">Slider</a></dd>\n\t\t\t\t\t<dd><a href=\"spinner/index.html\">Spinner</a></dd>\n\t\t\t\t\t<dd><a href=\"tabs/index.html\">Tabs</a></dd>\n\t\t\t\t\t<dd><a href=\"tooltip/index.html\">Tooltip</a></dd>\n\t\t\t\t<dt>Effects</dt>\n\t\t\t\t\t<dd><a href=\"animate/index.html\">Color Animation</a></dd>\n\t\t\t\t\t<dd><a href=\"toggleClass/index.html\">Toggle Class</a></dd>\n\t\t\t\t\t<dd><a href=\"addClass/index.html\">Add Class</a></dd>\n\t\t\t\t\t<dd><a href=\"removeClass/index.html\">Remove Class</a></dd>\n\t\t\t\t\t<dd><a href=\"switchClass/index.html\">Switch Class</a></dd>\n\t\t\t\t\t<dd><a href=\"effect/index.html\">Effect</a></dd>\n\t\t\t\t\t<dd><a href=\"toggle/index.html\">Toggle</a></dd>\n\t\t\t\t\t<dd><a href=\"hide/index.html\">Hide</a></dd>\n\t\t\t\t\t<dd><a href=\"show/index.html\">Show</a></dd>\n\t\t\t\t<dt>Utilities</dt>\n                    <dd><a href=\"position/index.html\">Position</a></dd>\n                    <dd><a href=\"widget/index.html\">Widget</a></dd>\n\t\t\t\t<dt>About jQuery UI</dt>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Getting_Started\">Getting Started</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Upgrade_Guide\">Upgrade Guide</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Changelog\">Changelog</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Roadmap\">Roadmap</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Subversion\">Subversion Access</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Developer_Guide\">UI Developer Guidelines</a></dd>\n\t\t\t\t<dt>Theming</dt>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Theming\">Theming jQuery UI</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Theming/API\">jQuery UI CSS Framework</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Theming/Themeroller\">ThemeRoller application</a></dd>\n\t\t\t\t\t<dd><a href=\"http://jqueryui.com/docs/Theming/ThemeSwitcher\">Theme Switcher Widget</a></dd>\n\n\t\t\t</dl>\n\t\t</td>\n\t\t<td class=\"normal\">\n\n\t\t\t<div class=\"normal\">\n\n\t\t\t\t\t<h3>Instructions</h3>\n\t\t\t\t\t<p>\n\t\t\t\t\t\tThese demos showcase some common uses of each jQuery UI plugin. Simply copy and paste code from the demos to get started. Have fun playing with them.\n\t\t\t\t\t</p>\n\n\t\t\t</div>\n\n\t\t</td>\n\t</tr>\n</table>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/menu/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Menu - Default demo</title>\n\t<link type=\"text/css\" href=\"../../themes/base/jquery.ui.all.css\" rel=\"stylesheet\" />\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<link href=\"../demos.css\" rel=\"stylesheet\" />\n\t<script>\n\t$(function() {\n\t\t$(\".demo ul\").menu();\n\t});\n\t</script>\n\t<style>\n\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n\t<ul>\n\t\t<li><a href=\"#Aberdeen\">Aberdeen</a></li>\n\t\t<li><a href=\"#Ada\">Ada</a></li>\n\t\t<li><a href=\"#Adamsville\">Adamsville</a></li>\n\t\t<li><a href=\"#Addyston\">Addyston</a></li>\n\t\t<li><a href=\"#Adelphi\">Adelphi</a></li>\n\t\t<li><a href=\"#Adena\">Adena</a></li>\n\t\t<li><a href=\"#Adrian\">Adrian</a></li>\n\t\t<li><a href=\"#Akron\">Akron</a></li>\n\t\t<li><a href=\"#Albany\">Albany</a></li>\n\t\t<li><a href=\"#Alexandria\">Alexandria</a></li>\n\t\t<li><a href=\"#Alger\">Alger</a></li>\n\t\t<li><a href=\"#Alledonia\">Alledonia</a></li>\n\t\t<li><a href=\"#Alliance\">Alliance</a></li>\n\t\t<li><a href=\"#Alpha\">Alpha</a></li>\n\t\t<li><a href=\"#Alvada\">Alvada</a></li>\n\t</ul>\n\n</div><!-- End demo -->\n\n<div class=\"demo-description\">\n\n<p>A menu with the default configuration. A list is transformed, adding themeing, mouse and keyboard navigation support. Try to tab to the menu and use the cursor keys to navigate.</p>\n\n</div><!-- End demo-description -->\n\n\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/menu/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"UTF-8\" />\n\t<title>jQuery UI Menu Demos</title>\n\t<link href=\"../demos.css\" rel=\"stylesheet\" />\n</head>\n<body>\n\t<div class=\"demos-nav\">\n\t\t<h4>Examples</h4>\n\t\t<ul>\n\t\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t\t<li><a href=\"topalignmenu.html\">Top-aligned sub menus</a></li>\n\t\t\t<li><a href=\"navigationmenu.html\">Navigation menu</a></li>\n\t\t</ul>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/menu/navigationmenu.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Menu - Navigation Menu demo</title>\n\t<link type=\"text/css\" href=\"../../themes/base/jquery.ui.all.css\" rel=\"stylesheet\" />\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<link href=\"../demos.css\" rel=\"stylesheet\" />\n\t<script>\n\t$(function() {\n\t\t$(\"#navMenu\").menu({\n\t\t\tselect: function( event, ui ) {\n\t\t\t\tvar link = ui.item.children( \"a:first\" );\n\t\t\t\tif ( link.attr( \"target\" ) || event.metaKey || event.shiftKey || event.ctrlKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlocation.href = link.attr( \"href\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n\t<style>\n\t\tbody { font-size:62.5%; }\n\t\t.ui-menu { width: 200px; margin-bottom: 2em; }\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n\t<ul id=\"navMenu\">\n\t\t<li><a href=\"?Aberdeen\">Aberdeen</a></li>\n\t\t<li><a href=\"?Ada\">Ada</a></li>\n\t\t<li><a href=\"?Adamsville\">Adamsville</a></li>\n\t\t<li><a href=\"?Addyston\">Addyston</a></li>\n\t\t<li>\n\t\t\t<a href=\"?Delphi\">Delphi</a>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?Ada\">Ada</a></li>\n\t\t\t\t<li><a href=\"?Saarland\">Saarland</a></li>\n\t\t\t\t<li><a href=\"?Salzburg\">Salzburg</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li><a href=\"?Saarland\">Saarland</a></li>\n\t\t<li>\n\t\t\t<a href=\"?Salzburg\">Salzburg</a>\n\t\t\t<ul>\n\t\t\t\t<li>\n\t\t\t\t\t<a href=\"?Delphi\">Delphi</a>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li><a href=\"?Ada\">Ada</a></li>\n\t\t\t\t\t\t<li><a href=\"?Saarland\">Saarland</a></li>\n\t\t\t\t\t\t<li><a href=\"?Salzburg\">Salzburg</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</li>\n\t\t\t\t<li>\n\t\t\t\t\t<a href=\"?Delphi\">Delphi</a>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li><a href=\"?Ada\">Ada</a></li>\n\t\t\t\t\t\t<li><a href=\"?Saarland\">Saarland</a></li>\n\t\t\t\t\t\t<li><a href=\"?Salzburg\">Salzburg</a></li>\n\t\t\t\t\t</ul>\n\t\t\t\t</li>\n\t\t\t\t<li><a href=\"?Perch\">Perch</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t</ul>\n\n</div><!-- End demo -->\n\n<div class=\"demo-description\">\n\n<p>A navigation menu. A list is transformed, adding themeing, mouse and keyboard navigation support. Try to tab to the menu and use the cursor keys to navigate.</p>\n\n</div><!-- End demo-description -->\n\n\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/menu/topalignmenu.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Menu Demo: Top-aligned Menu</title>\n\t<link type=\"text/css\" href=\"../demos.css\" rel=\"stylesheet\" />\n\t<link type=\"text/css\" href=\"../../themes/base/jquery.ui.all.css\" rel=\"stylesheet\" />\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$(\"#topMenu\").menu({\n\t\t\tposition: { of: \"ul:has(a.ui-state-focus):last\" }\n\t\t});\n\t});\n\t</script>\n\t<style>\n\t\t.ui-menu { width: 200px; margin-bottom: 2em; }\n\t</style>\n</head>\n<body>\n\n<ul id=\"topMenu\">\n\t<li><a href=\"#\">Aberdeen</a></li>\n\t<li><a href=\"#\">Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\">Addyston</a></li>\n\t<li>\n\t\t<a href=\"#\">Delphi</a>\n\t\t<ul>\n\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t</ul>\n\t</li>\n\t<li><a href=\"#\">Saarland</a></li>\n\t<li>\n\t\t<a href=\"#\">Salzburg</a>\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Adamsville</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Aberdeen</a></li>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\">Adamsville</a></li>\n\t\t\t\t\t<li><a href=\"#\">Addyston</a></li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li><a href=\"#\">Perch</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Addyston</a></li>\n\t\t\t\t\t<li><a href=\"#\">Delphi</a></li>\n\t\t\t\t\t<li><a href=\"#\">Perch</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t</ul>\n\t</li>\n</ul>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/position/cycler.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Position - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n    <style>\n   \thtml, body {\n   \t\tmargin: 0;\n\t\tpadding: 0\n   \t}\n    </style>\n\t<script>\n\t$(function() {\n\t\t// TODO refactor into a widget and get rid of these plugin methods\n\t\t$.fn.position2 = function( options ) {\n\t\t\treturn this.position( $.extend({\n\t\t\t\tof: window,\n\t\t\t\tusing: function( to ) {\n\t\t\t\t\t$( this ).css({\n\t\t\t\t\t\ttop: to.top,\n\t\t\t\t\t\tleft: to.left\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tcollision: \"none\"\n\t\t\t}, options));\n\t\t}\n\n\t\t$.fn.left = function( using ) {\n\t\t\treturn this.position2({\n\t\t\t\tmy: \"right middle\",\n\t\t\t\tat: \"left+25 middle\",\n\t\t\t\tusing: using\n\t\t\t});\n\t\t}\n\t\t$.fn.right = function( using ) {\n\t\t\treturn this.position2({\n\t\t\t\tmy: \"left middle\",\n\t\t\t\tat: \"right-25 middle\",\n\t\t\t\tusing: using\n\t\t\t});\n\t\t}\n\t\t$.fn.center = function( using ) {\n\t\t\treturn this.position2({\n\t\t\t\tmy: \"center middle\",\n\t\t\t\tat: \"center middle\",\n\t\t\t\tusing: using\n\t\t\t});\n\t\t};\n\n\t\t$( \"body\" ).css({\n\t\t\toverflow: \"hidden\"\n\t\t})\n\t\t$( \".demo\" ).css({\n\t\t\tposition: \"relative\",\n\t\t});\n\t\t$( \".demo img\" ).css({\n\t\t\tposition: \"absolute\",\n\t\t});\n\n\t\t$( \"img:eq(0)\" ).left();\n\t\t$( \"img:eq(1)\" ).center();\n\t\t$( \"img:eq(2)\" ).right();\n\n\t\tfunction animate( to ) {\n\t\t\t$(this).stop( true, false ).animate( to );\n\t\t}\n\t\tfunction next( event ) {\n\t\t\tevent.preventDefault();\n\t\t\t$( \"img:eq(2)\" ).center( animate );\n\t\t\t$( \"img:eq(1)\" ).left( animate )\n\t\t\t$( \"img:eq(0)\" ).right().appendTo( \".demo\" );\n\t\t}\n\t\tfunction previous( event ) {\n\t\t\tevent.preventDefault();\n\t\t\t$( \"img:eq(0)\" ).center( animate );\n\t\t\t$( \"img:eq(1)\" ).right( animate );\n\t\t\t$( \"img:eq(2)\" ).left().prependTo( \".demo\" );\n\t\t}\n\t\t$( \"#previous\" ).click( previous );\n\t\t$( \"#next\" ).click( next );\n\n\t\t$( \".demo img\" ).click(function( event ) {\n\t\t\t$( \".demo img\" ).index( this ) === 0 ? previous( event ) : next( event );\n\t\t});\n\n\t\t$( window ).resize(function() {\n\t\t\t$( \"img:eq(0)\" ).left( animate );\n\t\t\t$( \"img:eq(1)\" ).center( animate );\n\t\t\t$( \"img:eq(2)\" ).right( animate );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<img src=\"images/earth.jpg\" width=\"458\" height=\"308\" alt=\"earth\" />\n<img src=\"images/flight.jpg\" width=\"512\" height=\"307\" alt=\"flight\" />\n<img src=\"images/rocket.jpg\" width=\"300\" height=\"353\" alt=\"rocket\" />\n\n<a id=\"previous\" href=\"#\">Previous</a>\n<a id=\"next\" href=\"#\">Next</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A prototype for the <a href=\"http://wiki.jqueryui.com/Photoviewer\">Photoviewer</a> using Position to place images at the center, left and right and cycle them.\n<br/>Use the links at the top to cycle, or click on the images on the left and right.\n<br/>Note how the images are repositioned when resizing the window.\n<br/>Warning: Doesn't currently work inside the demo viewer; open in a new window instead!</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/position/default.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Position - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#parent {\n\t\twidth: 60%;\n\t\theight: 40px;\n\t\tmargin: 10px auto;\n\t\tpadding: 5px;\n\t\tborder: 1px solid #777;\n\t\tbackground-color: #fbca93;\n\t\ttext-align: center;\n\t}\n\t.positionable {\n\t\tposition: absolute;\n\t\tdisplay: block;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tbackground-color: #bcd5e6;\n\t\ttext-align: center;\n\t}\n\t#positionable1 {\n\t\twidth: 75px;\n\t\theight: 75px;\n\t}\n\t#positionable2 {\n\t\twidth: 120px;\n\t\theight: 40px;\n\t}\n\tselect, input {\n\t\tmargin-left: 15px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tfunction position() {\n\t\t\t$( \".positionable\" ).position({\n\t\t\t\tof: $( \"#parent\" ),\n\t\t\t\tmy: $( \"#my_horizontal\" ).val() + \" \" + $( \"#my_vertical\" ).val(),\n\t\t\t\tat: $( \"#at_horizontal\" ).val() + \" \" + $( \"#at_vertical\" ).val(),\n\t\t\t\toffset: $( \"#offset\" ).val(),\n\t\t\t\tcollision: $( \"#collision_horizontal\" ).val() + \" \" + $( \"#collision_vertical\" ).val()\n\t\t\t});\n\t\t}\n\n\t\t$( \".positionable\" ).css( \"opacity\", 0.5 );\n\n\t\t$( \"select, input\" ).bind( \"click keyup change\", position );\n\n\t\t$( \"#parent\" ).draggable({\n\t\t\tdrag: position\n\t\t});\n\n\t\tposition();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"parent\">\n\t<p>\n\tThis is the position parent element.\n\t</p>\n</div>\n\n<div class=\"positionable\" id=\"positionable1\">\n\t<p>\n\tto position\n\t</p>\n</div>\n\n<div class=\"positionable\" id=\"positionable2\">\n\t<p>\n\tto position 2\n\t</p>\n</div>\n\n<div style=\"padding: 20px; margin-top: 75px;\">\n\tposition...\n\t<div style=\"padding-bottom: 20px;\">\n\t\t<b>my:</b>\n\t\t<select id=\"my_horizontal\">\n\t\t\t<option value=\"left\">left</option>\n\t\t\t<option value=\"center\">center</option>\n\t\t\t<option value=\"right\">right</option>\n\t\t</select>\n\t\t<select id=\"my_vertical\">\n\t\t\t<option value=\"top\">top</option>\n\t\t\t<option value=\"middle\">center</option>\n\t\t\t<option value=\"bottom\">bottom</option>\n\t\t</select>\n\t</div>\n\t<div style=\"padding-bottom: 20px;\">\n\t\t<b>at:</b>\n\t\t<select id=\"at_horizontal\">\n\t\t\t<option value=\"left\">left</option>\n\t\t\t<option value=\"center\">center</option>\n\t\t\t<option value=\"right\">right</option>\n\t\t</select>\n\t\t<select id=\"at_vertical\">\n\t\t\t<option value=\"top\">top</option>\n\t\t\t<option value=\"middle\">center</option>\n\t\t\t<option value=\"bottom\">bottom</option>\n\t\t</select>\n\t</div>\n\t<div style=\"padding-bottom: 20px;\">\n\t\t<b>offset:</b>\n\t\t<input id=\"offset\">\n\t</div>\n\t<div style=\"padding-bottom: 20px;\">\n\t\t<b>collision:</b>\n\t\t<select id=\"collision_horizontal\">\n\t\t\t<option value=\"flip\">flip</option>\n\t\t\t<option value=\"fit\">fit</option>\n\t\t\t<option value=\"flipfit\">flipfit</option>\n\t\t\t<option value=\"none\">none</option>\n\t\t</select>\n\t\t<select id=\"collision_vertical\">\n\t\t\t<option value=\"flip\">flip</option>\n\t\t\t<option value=\"fit\">fit</option>\n\t\t\t<option value=\"flipfit\">flipfit</option>\n\t\t\t<option value=\"none\">none</option>\n\t\t</select>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Use the form controls to configure the positioning, or drag the positioned element to modify its offset.\n<br/>Drag around the parent element to see collision detection in action.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/position/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Position Demo</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"cycler.html\">Cycling images</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/progressbar/animated.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Progressbar - Animated</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.progressbar.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-progressbar .ui-progressbar-value { background-image: url(images/pbar-ani.gif); }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#progressbar\" ).progressbar({\n\t\t\tvalue: 59\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"progressbar\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\nThis progressbar has an animated fill by setting the\n<code>background-image</code>\non the\n<code>.ui-progressbar-value</code>\nelement, using css.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/progressbar/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Progressbar - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.progressbar.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#progressbar\" ).progressbar({\n\t\t\tvalue: 37\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"progressbar\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Default determinate progress bar.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/progressbar/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Progressbar Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"animated.html\">Animated</a></li>\n\t\t<li><a href=\"resize.html\">Resizable progressbar</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/progressbar/resize.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Progressbar - Resizable</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.progressbar.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#progressbar\" ).progressbar({\n\t\t\tvalue: 37\n\t\t});\n\t\t$( \"#progressbarWrapper\" ).resizable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"progressbarWrapper\" style=\"height:30px; \" class=\"ui-widget-default\">\n\t<div id=\"progressbar\" style=\"height:100%;\"></div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The progress bar's widths are specified in percentages for flexible sizing so it will resize to fit its container. Try resizing the height and width of this bar to see how it maintains the correct proportions. (This is not necessarily a real-world example, but it's a good illustration of how flexibly all the plugins are coded.)</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/removeClass/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - removeClass Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.toggler { width: 500px; height: 200px; position: relative; }\n\t#button { padding: .5em 1em; text-decoration: none; }\n\t#effect { position: relative;  width: 240px;  padding: 1em;  letter-spacing: 0; font-size: 1.2em; border: 1px solid #000; background: #eee; color: #333; }\n\t.newClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.6em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#button\" ).click(function() {\n\t\t\t$( \"#effect\" ).removeClass( \"newClass\", 1000, callback );\n\t\t\treturn false;\n\t\t});\n\n\t\tfunction callback() {\n\t\t\tsetTimeout(function() {\n\t\t\t\t$( \"#effect\" ).addClass( \"newClass\" );\n\t\t\t}, 1500 );\n\t\t}\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"newClass ui-corner-all\">\n\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. \n\t</div>\n</div>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/removeClass/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/animate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Animate</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 150px; height: 150px; padding: 0.5em; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t.ui-resizable-helper { border: 1px dotted gray; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\tanimate: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Animate</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Animate the resize action using the <code>animate</code> option (boolean). When this option is set to true, drag the outline to the desired location; the element animates to that size on drag stop.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/aspect-ratio.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Preserve aspect ratio</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 160px; height: 90px; padding: 0.5em; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\taspectRatio: 16 / 9\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Preserve aspect ratio</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Maintain the existing aspect ratio or set a new one to constrain the proportions on resize. Set the <code>aspectRatio</code> option to true, and optionally pass in a new ratio (i.e., 4/3)</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/constrain-area.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Constrain resize area</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#container { width: 300px; height: 300px; }\n\t#container h3 { text-align: center; margin: 0; margin-bottom: 10px; }\n\t#resizable { background-position: top left; width: 150px; height: 150px; }\n\t#resizable, #container { padding: 0.5em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\tcontainment: \"#container\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"container\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Containment</h3>\n\t<div id=\"resizable\" class=\"ui-state-active\">\n\t\t<h3 class=\"ui-widget-header\">Resizable</h3>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Define the boundaries of the resizable area. Use the <code>containment</code> option to specify a parent DOM element or a jQuery selector, like 'document.'</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 150px; height: 150px; padding: 0.5em; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Resizable</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Enable any DOM element to be resizable.  With the cursor grab the right or bottom border and drag to the desired width or height.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/delay-start.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Delay start</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable, #resizable2 { width: 150px; height: 150px; padding: 0.5em; }\n\t#resizable h3, #resizable2 h3 { text-align: center; margin: 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\tdelay: 1000\n\t\t});\n\t\t\n\t\t$( \"#resizable2\" ).resizable({\n\t\t\tdistance: 40\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<h3 class=\"docs\">Time delay (ms):</h3>\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Time</h3>\n</div>\n\n<h3 class=\"docs\">Distance delay (px):</h3>\n<div id=\"resizable2\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Distance</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Delay the start of resizng for a number of milliseconds with the <code>delay</code> option; prevent resizing until the cursor is held down and dragged a specifed number of pixels with the <code>distance</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/helper.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Helper</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 150px; height: 150px; padding: 0.5em; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t.ui-resizable-helper { border: 2px dotted #00F; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\thelper: \"ui-resizable-helper\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Helper</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Display only an outline of the element while resizing by setting the <code>helper</code> option to a CSS class.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"aspect-ratio.html\">Preserve aspect ratio</a></li>\n\t\t<li><a href=\"max-min.html\">Maximum / minimum size</a></li>\n\t\t<li><a href=\"constrain-area.html\">Constrain resize area</a></li>\n \t\t<li><a href=\"delay-start.html\">Delay start</a></li>\n\t\t<li><a href=\"snap-to-grid.html\">Snap to grid</a></li>\n\t\t<li><a href=\"visual-feedback.html\">Visual feedback</a></li>\n\t\t<li><a href=\"synchronous-resize.html\">Synchronous resize</a></li>\n\t\t<li><a href=\"animate.html\">Animate</a></li>\n\t\t<li><a href=\"helper.html\">Resize Helper</a></li>\n\t\t<li><a href=\"textarea.html\">Textarea</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/max-min.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Maximum / minimum size</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 200px; height: 150px; padding: 5px; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\tmaxHeight: 250,\n\t\t\tmaxWidth: 350,\n\t\t\tminHeight: 150,\n\t\t\tminWidth: 200\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Resize larger / smaller</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Limit the resizable element to a maximum or minimum height or width using the <code>maxHeight</code>, <code>maxWidth</code>, <code>minHeight</code>, and <code>minWidth</code> options.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/snap-to-grid.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Snap to grid</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 150px; height: 150px; padding: 0.5em; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\tgrid: 50\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Grid</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Snap the resizable element to a grid.  Set the dimensions of grid cells (height and width in pixels) with the <code>grid</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/synchronous-resize.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Synchronous resize</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { background-position: top left; }\n\t#resizable, #also { width: 150px; height: 120px; padding: 0.5em; }\n\t#resizable h3, #also h3 { text-align: center; margin: 0; }\n\t#also { margin-top: 1em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\talsoResize: \"#also\"\n\t\t});\n\t\t$( \"#also\" ).resizable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-header\">\n\t<h3 class=\"ui-state-active\">Resize</h3>\n</div>\n\n<div id=\"also\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">will also resize</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Resize multiple elements simultaneously by clicking and dragging the sides of one.  Pass a shared selector into the <code>alsoResize</code> option.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/textarea.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Textarea</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.ui-resizable-se {\n\t\tbottom: 17px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\thandles: \"se\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<textarea id=\"resizable\" rows=\"5\" cols=\"20\"></textarea>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Display only an outline of the element while resizing by setting the <code>helper</code> option to a CSS class.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/resizable/visual-feedback.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable - Visual feedback</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#resizable { width: 150px; height: 150px; padding: 0.5em; }\n\t#resizable h3 { text-align: center; margin: 0; }\n\t.ui-resizable-ghost { border: 1px dotted gray; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#resizable\" ).resizable({\n\t\t\tghost: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t\n<div id=\"resizable\" class=\"ui-widget-content\">\n\t<h3 class=\"ui-widget-header\">Ghost</h3>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Instead of showing the actual element during resize, set the <code>ghost</code> option to true to show a semi-transparent part of the element.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/selectable/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Selectable - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.selectable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t\n\t<style>\n\t#feedback { font-size: 1.4em; }\n\t#selectable .ui-selecting { background: #FECA40; }\n\t#selectable .ui-selected { background: #F39814; color: white; }\n\t#selectable { list-style-type: none; margin: 0; padding: 0; width: 60%; }\n\t#selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#selectable\" ).selectable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<ol id=\"selectable\">\n\t<li class=\"ui-widget-content\">Item 1</li>\n\t<li class=\"ui-widget-content\">Item 2</li>\n\t<li class=\"ui-widget-content\">Item 3</li>\n\t<li class=\"ui-widget-content\">Item 4</li>\n\t<li class=\"ui-widget-content\">Item 5</li>\n\t<li class=\"ui-widget-content\">Item 6</li>\n\t<li class=\"ui-widget-content\">Item 7</li>\n</ol>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Enable a DOM element (or group of elements) to be selectable. Draw a box with your cursor to select items. Hold down the Ctrl key to make multiple non-adjacent selections. </p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/selectable/display-grid.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Selectable - Display as grid</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.selectable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t\n\t<style>\n\t#feedback { font-size: 1.4em; }\n\t#selectable .ui-selecting { background: #FECA40; }\n\t#selectable .ui-selected { background: #F39814; color: white; }\n\t#selectable { list-style-type: none; margin: 0; padding: 0; }\n\t#selectable li { margin: 3px; padding: 1px; float: left; width: 100px; height: 80px; font-size: 4em; text-align: center; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#selectable\" ).selectable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<ol id=\"selectable\">\n\t<li class=\"ui-state-default\">1</li>\n\t<li class=\"ui-state-default\">2</li>\n\t<li class=\"ui-state-default\">3</li>\n\t<li class=\"ui-state-default\">4</li>\n\t<li class=\"ui-state-default\">5</li>\n\t<li class=\"ui-state-default\">6</li>\n\t<li class=\"ui-state-default\">7</li>\n\t<li class=\"ui-state-default\">8</li>\n\t<li class=\"ui-state-default\">9</li>\n\t<li class=\"ui-state-default\">10</li>\n\t<li class=\"ui-state-default\">11</li>\n\t<li class=\"ui-state-default\">12</li>\n</ol>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>To arrange selectable items as a grid, give them identical dimensions and float them using CSS.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/selectable/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Selectable Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"serialize.html\">Serialize</a></li>\n\t\t<li><a href=\"display-grid.html\">Display as grid</a></li>\t\t\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/selectable/serialize.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Selectable - Serialize</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.selectable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t\n\t<style>\n\t#feedback { font-size: 1.4em; }\n\t#selectable .ui-selecting { background: #FECA40; }\n\t#selectable .ui-selected { background: #F39814; color: white; }\n\t#selectable { list-style-type: none; margin: 0; padding: 0; width: 60%; }\n\t#selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#selectable\" ).selectable({\n\t\t\tstop: function() {\n\t\t\t\tvar result = $( \"#select-result\" ).empty();\n\t\t\t\t$( \".ui-selected\", this ).each(function() {\n\t\t\t\t\tvar index = $( \"#selectable li\" ).index( this );\n\t\t\t\t\tresult.append( \" #\" + ( index + 1 ) );\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p id=\"feedback\">\n<span>You've selected:</span> <span id=\"select-result\">none</span>.\n</p>\n\n<ol id=\"selectable\">\n\t<li class=\"ui-widget-content\">Item 1</li>\n\t<li class=\"ui-widget-content\">Item 2</li>\n\t<li class=\"ui-widget-content\">Item 3</li>\n\t<li class=\"ui-widget-content\">Item 4</li>\n\t<li class=\"ui-widget-content\">Item 5</li>\n\t<li class=\"ui-widget-content\">Item 6</li>\n</ol>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Write a function that fires on the <code>stop</code> event to collect the index values of selected items.  Present values as feedback, or pass as a data string.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/show/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - Show Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../ui/jquery.effects.explode.js\"></script>\n\t<script src=\"../../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../../ui/jquery.effects.highlight.js\"></script>\n\t<script src=\"../../ui/jquery.effects.pulsate.js\"></script>\n\t<script src=\"../../ui/jquery.effects.scale.js\"></script>\n\t<script src=\"../../ui/jquery.effects.shake.js\"></script>\n\t<script src=\"../../ui/jquery.effects.slide.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.toggler { width: 500px; height: 200px; }\n\t#button { padding: .5em 1em; text-decoration: none; }\n\t#effect { width: 240px; height: 135px; padding: 0.4em; position: relative; }\n\t#effect h3 { margin: 0; padding: 0.4em; text-align: center; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// run the currently selected effect\n\t\tfunction runEffect() {\n\t\t\t// get effect type from \n\t\t\tvar selectedEffect = $( \"#effectTypes\" ).val();\n\n\t\t\t// most effect types need no options passed by default\n\t\t\tvar options = {};\n\t\t\t// some effects have required parameters\n\t\t\tif ( selectedEffect === \"scale\" ) {\n\t\t\t\toptions = { percent: 100 };\n\t\t\t} else if ( selectedEffect === \"size\" ) {\n\t\t\t\toptions = { to: { width: 280, height: 185 } };\n\t\t\t}\n\n\t\t\t// run the effect\n\t\t\t$( \"#effect\" ).show( selectedEffect, options, 500, callback );\n\t\t};\n\n\t\t//callback function to bring a hidden box back\n\t\tfunction callback() {\n\t\t\tsetTimeout(function() {\n\t\t\t\t$( \"#effect:visible\" ).removeAttr( \"style\" ).fadeOut();\n\t\t\t}, 1000 );\n\t\t};\n\n\t\t// set effect from select menu value\n\t\t$( \"#button\" ).click(function() {\n\t\t\trunEffect();\n\t\t\treturn false;\n\t\t});\n\n\t\t$( \"#effect\" ).hide();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"ui-widget-content ui-corner-all\">\n\t\t<h3 class=\"ui-widget-header ui-corner-all\">Show</h3>\n\t\t<p>\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. Nulla lorem metus, adipiscing ut, luctus sed, hendrerit vitae, mi.\n\t\t</p>\n\t</div>\n</div>\n\n<select name=\"effects\" id=\"effectTypes\">\n\t<option value=\"blind\">Blind</option>\n\t<option value=\"bounce\">Bounce</option>\n\t<option value=\"clip\">Clip</option>\n\t<option value=\"drop\">Drop</option>\n\t<option value=\"explode\">Explode</option>\n\t<option value=\"fold\">Fold</option>\n\t<option value=\"highlight\">Highlight</option>\n\t<option value=\"puff\">Puff</option>\n\t<option value=\"pulsate\">Pulsate</option>\n\t<option value=\"scale\">Scale</option>\n\t<option value=\"shake\">Shake</option>\n\t<option value=\"size\">Size</option>\n\t<option value=\"slide\">Slide</option>\n</select>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/show/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/colorpicker.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Colorpicker</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#red, #green, #blue {\n\t\tfloat: left;\n\t\tclear: left;\n\t\twidth: 300px;\n\t\tmargin: 15px;\n\t}\n\t#swatch {\n\t\twidth: 120px;\n\t\theight: 100px;\n\t\tmargin-top: 18px;\n\t\tmargin-left: 350px;\n\t\tbackground-image: none;\n\t}\n\t#red .ui-slider-range { background: #ef2929; }\n\t#red .ui-slider-handle { border-color: #ef2929; }\n\t#green .ui-slider-range { background: #8ae234; }\n\t#green .ui-slider-handle { border-color: #8ae234; }\n\t#blue .ui-slider-range { background: #729fcf; }\n\t#blue .ui-slider-handle { border-color: #729fcf; }\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\tfunction hexFromRGB(r, g, b) {\n\t\tvar hex = [\n\t\t\tr.toString( 16 ),\n\t\t\tg.toString( 16 ),\n\t\t\tb.toString( 16 )\n\t\t];\n\t\t$.each( hex, function( nr, val ) {\n\t\t\tif ( val.length === 1 ) {\n\t\t\t\thex[ nr ] = \"0\" + val;\n\t\t\t}\n\t\t});\n\t\treturn hex.join( \"\" ).toUpperCase();\n\t}\n\tfunction refreshSwatch() {\n\t\tvar red = $( \"#red\" ).slider( \"value\" ),\n\t\t\tgreen = $( \"#green\" ).slider( \"value\" ),\n\t\t\tblue = $( \"#blue\" ).slider( \"value\" ),\n\t\t\thex = hexFromRGB( red, green, blue );\n\t\t$( \"#swatch\" ).css( \"background-color\", \"#\" + hex );\n\t}\n\t$(function() {\n\t\t$( \"#red, #green, #blue\" ).slider({\n\t\t\torientation: \"horizontal\",\n\t\t\trange: \"min\",\n\t\t\tmax: 255,\n\t\t\tvalue: 127,\n\t\t\tslide: refreshSwatch,\n\t\t\tchange: refreshSwatch\n\t\t});\n\t\t$( \"#red\" ).slider( \"value\", 255 );\n\t\t$( \"#green\" ).slider( \"value\", 140 );\n\t\t$( \"#blue\" ).slider( \"value\", 60 );\n\t});\n\t</script>\n</head>\n<body class=\"ui-widget-content\" style=\"border:0;\">\n\n<div class=\"demo\">\n\n<p class=\"ui-state-default ui-corner-all ui-helper-clearfix\" style=\"padding:4px;\">\n\t<span class=\"ui-icon ui-icon-pencil\" style=\"float:left; margin:-2px 5px 0 0;\"></span>\n\tSimple Colorpicker\n</p>\n\n<div id=\"red\"></div>\n<div id=\"green\"></div>\n<div id=\"blue\"></div>\n\n<div id=\"swatch\" class=\"ui-widget-content ui-corner-all\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\" style=\"clear:left;\">\n<p>Combine three sliders to create a simple RGB colorpicker.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" >\n\t<title>jQuery UI Slider - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider\" ).slider();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"slider\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>The basic slider is horizontal and has a single handle that can be moved with the mouse or by using the arrow keys.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/hotelrooms.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Range with fixed minimum</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar select = $( \"#minbeds\" );\n\t\tvar slider = $( \"<div id='slider'></div>\" ).insertAfter( select ).slider({\n\t\t\tmin: 1,\n\t\t\tmax: 6,\n\t\t\trange: \"min\",\n\t\t\tvalue: select[ 0 ].selectedIndex + 1,\n\t\t\tslide: function( event, ui ) {\n\t\t\t\tselect[ 0 ].selectedIndex = ui.value - 1;\n\t\t\t}\n\t\t});\n\t\t$( \"#minbeds\" ).change(function() {\n\t\t\tslider.slider( \"value\", this.selectedIndex + 1 );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<form id=\"reservation\">\n\t<label for=\"minbeds\">Minimum number of beds</label>\n\t<select name=\"minbeds\" id=\"minbeds\">\n\t\t<option>1</option>\n\t\t<option>2</option>\n\t\t<option>3</option>\n\t\t<option>4</option>\n\t\t<option>5</option>\n\t\t<option>6</option>\n\t</select>\n</form>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>How to bind a slider to an existing select element. The select stays visible to display the change. When the select is changed, the slider is updated, too.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"steps.html\">Snap to increments</a></li>\n\t\t<li><a href=\"range.html\">Range slider</a></li>\n\t\t<li><a href=\"rangemin.html\">Range with fixed minimum</a></li>\n\t\t<li><a href=\"hotelrooms.html\">Room reservation</a></li>\n\t\t<li><a href=\"rangemax.html\">Range with fixed maximum</a></li>\n\t\t<li><a href=\"slider-vertical.html\">Vertical slider</a></li>\n\t\t<li><a href=\"range-vertical.html\">Vertical range slider</a></li>\n\t\t<li><a href=\"multiple-vertical.html\">Multiple sliders</a></li>\n\t\t<li><a href=\"colorpicker.html\">Simple colorpicker</a></li>\n\t\t<li><a href=\"side-scroll.html\">Simple scrollbar</a></li>\n\t\t<li><a href=\"tabs.html\">Slider controls tabs</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/multiple-vertical.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Multiple sliders</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; }\n\t#eq span {\n\t\theight:120px; float:left; margin:15px\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// setup master volume\n\t\t$( \"#master\" ).slider({\n\t\t\tvalue: 60,\n\t\t\torientation: \"horizontal\",\n\t\t\trange: \"min\",\n\t\t\tanimate: true\n\t\t});\n\t\t// setup graphic EQ\n\t\t$( \"#eq > span\" ).each(function() {\n\t\t\t// read initial values from markup and remove that\n\t\t\tvar value = parseInt( $( this ).text(), 10 );\n\t\t\t$( this ).empty().slider({\n\t\t\t\tvalue: value,\n\t\t\t\trange: \"min\",\n\t\t\t\tanimate: true,\n\t\t\t\torientation: \"vertical\"\n\t\t\t});\n\t\t});\n\t});\n\t</script>\n</head>\n<body class=\"ui-widget-content\" style=\"border:0;\">\n\n<div class=\"demo\">\n\n<p class=\"ui-state-default ui-corner-all ui-helper-clearfix\" style=\"padding:4px;\">\n\t<span class=\"ui-icon ui-icon-volume-on\" style=\"float:left; margin:-2px 5px 0 0;\"></span>\n\tMaster volume\n</p>\n\n<div id=\"master\" style=\"width:260px; margin:15px;\"></div>\n\n<p class=\"ui-state-default ui-corner-all\" style=\"padding:4px;margin-top:4em;\">\n\t<span class=\"ui-icon ui-icon-signal\" style=\"float:left; margin:-2px 5px 0 0;\"></span>\n\tGraphic EQ\n</p>\n\n<div id=\"eq\">\n\t<span>88</span>\n\t<span>77</span>\n\t<span>55</span>\n\t<span>33</span>\n\t<span>40</span>\n\t<span>45</span>\n\t<span>70</span>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\" style=\"clear:left;\">\n<p>Combine horizontal and vertical sliders, each with their own options, to create the UI for a music player.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/range-vertical.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Vertical range slider</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider-range\" ).slider({\n\t\t\torientation: \"vertical\",\n\t\t\trange: true,\n\t\t\tvalues: [ 17, 67 ],\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#amount\" ).val( \"$\" + ui.values[ 0 ] + \" - $\" + ui.values[ 1 ] );\n\t\t\t}\n\t\t});\n\t\t$( \"#amount\" ).val( \"$\" + $( \"#slider-range\" ).slider( \"values\", 0 ) +\n\t\t\t\" - $\" + $( \"#slider-range\" ).slider( \"values\", 1 ) );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"amount\">Target sales goal (Millions):</label>\n\t<input type=\"text\" id=\"amount\" style=\"border:0; color:#f6931f; font-weight:bold;\" />\n</p>\n\n<div id=\"slider-range\" style=\"height:250px;\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Change the orientation of the range slider to vertical.  Assign a height value via <code>.height()</code> or by setting the height through CSS, and set the <code>orientation</code> option to \"vertical.\"</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/range.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Range slider</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider-range\" ).slider({\n\t\t\trange: true,\n\t\t\tmin: 0,\n\t\t\tmax: 500,\n\t\t\tvalues: [ 75, 300 ],\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#amount\" ).val( \"$\" + ui.values[ 0 ] + \" - $\" + ui.values[ 1 ] );\n\t\t\t}\n\t\t});\n\t\t$( \"#amount\" ).val( \"$\" + $( \"#slider-range\" ).slider( \"values\", 0 ) +\n\t\t\t\" - $\" + $( \"#slider-range\" ).slider( \"values\", 1 ) );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"amount\">Price range:</label>\n\t<input type=\"text\" id=\"amount\" style=\"border:0; color:#f6931f; font-weight:bold;\" />\n</p>\n\n<div id=\"slider-range\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Set the <code>range</code> option to true to capture a range of values with two drag handles.  The space between the handles is filled with a different background color to indicate those values are selected.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/rangemax.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Range with fixed maximum</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider-range-max\" ).slider({\n\t\t\trange: \"max\",\n\t\t\tmin: 1,\n\t\t\tmax: 10,\n\t\t\tvalue: 2,\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#amount\" ).val( ui.value );\n\t\t\t}\n\t\t});\n\t\t$( \"#amount\" ).val( $( \"#slider-range-max\" ).slider( \"value\" ) );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"amount\">Minimum number of bedrooms:</label>\n\t<input type=\"text\" id=\"amount\" style=\"border:0; color:#f6931f; font-weight:bold;\" />\n</p>\n<div id=\"slider-range-max\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Fix the maximum value of the range slider so that the user can only select a minimum.  Set the <code>range</code> option to \"max.\"</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/rangemin.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Range with fixed minimum</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider-range-min\" ).slider({\n\t\t\trange: \"min\",\n\t\t\tvalue: 37,\n\t\t\tmin: 1,\n\t\t\tmax: 700,\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#amount\" ).val( \"$\" + ui.value );\n\t\t\t}\n\t\t});\n\t\t$( \"#amount\" ).val( \"$\" + $( \"#slider-range-min\" ).slider( \"value\" ) );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"amount\">Maximum price:</label>\n\t<input type=\"text\" id=\"amount\" style=\"border:0; color:#f6931f; font-weight:bold;\" />\n</p>\n\n<div id=\"slider-range-min\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Fix the minimum value of the range slider so that the user can only select a maximum.  Set the <code>range</code> option to \"min.\"</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/side-scroll.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Slider scrollbar</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; }\n\t.scroll-pane { overflow: auto; width: 99%; float:left; }\n\t.scroll-content { width: 2440px; float: left; }\n\t.scroll-content-item { width: 100px; height: 100px; float: left; margin: 10px; font-size: 3em; line-height: 96px; text-align: center; }\n\t* html .scroll-content-item { display: inline; } /* IE6 float double margin bug */\n\t.scroll-bar-wrap { clear: left; padding: 0 4px 0 2px; margin: 0 -1px -1px -1px; }\n\t.scroll-bar-wrap .ui-slider { background: none; border:0; height: 2em; margin: 0 auto;  }\n\t.scroll-bar-wrap .ui-handle-helper-parent { position: relative; width: 100%; height: 100%; margin: 0 auto; }\n\t.scroll-bar-wrap .ui-slider-handle { top:.2em; height: 1.5em; }\n\t.scroll-bar-wrap .ui-slider-handle .ui-icon { margin: -8px auto 0; position: relative; top: 50%; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t//scrollpane parts\n\t\tvar scrollPane = $( \".scroll-pane\" ),\n\t\t\tscrollContent = $( \".scroll-content\" );\n\t\t\n\t\t//build slider\n\t\tvar scrollbar = $( \".scroll-bar\" ).slider({\n\t\t\tslide: function( event, ui ) {\n\t\t\t\tif ( scrollContent.width() > scrollPane.width() ) {\n\t\t\t\t\tscrollContent.css( \"margin-left\", Math.round(\n\t\t\t\t\t\tui.value / 100 * ( scrollPane.width() - scrollContent.width() )\n\t\t\t\t\t) + \"px\" );\n\t\t\t\t} else {\n\t\t\t\t\tscrollContent.css( \"margin-left\", 0 );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\t//append icon to handle\n\t\tvar handleHelper = scrollbar.find( \".ui-slider-handle\" )\n\t\t.mousedown(function() {\n\t\t\tscrollbar.width( handleHelper.width() );\n\t\t})\n\t\t.mouseup(function() {\n\t\t\tscrollbar.width( \"100%\" );\n\t\t})\n\t\t.append( \"<span class='ui-icon ui-icon-grip-dotted-vertical'></span>\" )\n\t\t.wrap( \"<div class='ui-handle-helper-parent'></div>\" ).parent();\n\t\t\n\t\t//change overflow to hidden now that slider handles the scrolling\n\t\tscrollPane.css( \"overflow\", \"hidden\" );\n\t\t\n\t\t//size scrollbar and handle proportionally to scroll distance\n\t\tfunction sizeScrollbar() {\n\t\t\tvar remainder = scrollContent.width() - scrollPane.width();\n\t\t\tvar proportion = remainder / scrollContent.width();\n\t\t\tvar handleSize = scrollPane.width() - ( proportion * scrollPane.width() );\n\t\t\tscrollbar.find( \".ui-slider-handle\" ).css({\n\t\t\t\twidth: handleSize,\n\t\t\t\t\"margin-left\": -handleSize / 2\n\t\t\t});\n\t\t\thandleHelper.width( \"\" ).width( scrollbar.width() - handleSize );\n\t\t}\n\t\t\n\t\t//reset slider value based on scroll content position\n\t\tfunction resetValue() {\n\t\t\tvar remainder = scrollPane.width() - scrollContent.width();\n\t\t\tvar leftVal = scrollContent.css( \"margin-left\" ) === \"auto\" ? 0 :\n\t\t\t\tparseInt( scrollContent.css( \"margin-left\" ) );\n\t\t\tvar percentage = Math.round( leftVal / remainder * 100 );\n\t\t\tscrollbar.slider( \"value\", percentage );\n\t\t}\n\t\t\n\t\t//if the slider is 100% and window gets larger, reveal content\n\t\tfunction reflowContent() {\n\t\t\t\tvar showing = scrollContent.width() + parseInt( scrollContent.css( \"margin-left\" ), 10 );\n\t\t\t\tvar gap = scrollPane.width() - showing;\n\t\t\t\tif ( gap > 0 ) {\n\t\t\t\t\tscrollContent.css( \"margin-left\", parseInt( scrollContent.css( \"margin-left\" ), 10 ) + gap );\n\t\t\t\t}\n\t\t}\n\t\t\n\t\t//change handle position on window resize\n\t\t$( window ).resize(function() {\n\t\t\tresetValue();\n\t\t\tsizeScrollbar();\n\t\t\treflowContent();\n\t\t});\n\t\t//init scrollbar size\n\t\tsetTimeout( sizeScrollbar, 10 );//safari wants a timeout\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"scroll-pane ui-widget ui-widget-header ui-corner-all\">\n\t<div class=\"scroll-content\">\n\t\t<div class=\"scroll-content-item ui-widget-header\">1</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">2</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">3</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">4</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">5</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">6</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">7</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">8</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">9</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">10</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">11</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">12</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">13</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">14</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">15</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">16</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">17</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">18</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">19</div>\n\t\t<div class=\"scroll-content-item ui-widget-header\">20</div>\n\t</div>\n\t<div class=\"scroll-bar-wrap ui-widget-content ui-corner-bottom\">\n\t\t<div class=\"scroll-bar\"></div>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Use a slider to manipulate the positioning of content on the page. In this case, it acts as a scrollbar with the potential to capture values if needed.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/slider-vertical.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Vertical slider</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider-vertical\" ).slider({\n\t\t\torientation: \"vertical\",\n\t\t\trange: \"min\",\n\t\t\tmin: 0,\n\t\t\tmax: 100,\n\t\t\tvalue: 60,\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#amount\" ).val( ui.value );\n\t\t\t}\n\t\t});\n\t\t$( \"#amount\" ).val( $( \"#slider-vertical\" ).slider( \"value\" ) );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"amount\">Volume:</label>\n\t<input type=\"text\" id=\"amount\" style=\"border:0; color:#f6931f; font-weight:bold;\" />\n</p>\n\n<div id=\"slider-vertical\" style=\"height:200px;\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Change the orientation of the slider to vertical.  Assign a height value via <code>.height()</code> or by setting the height through CSS, and set the <code>orientation</code> option to \"vertical.\"</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/steps.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Snap to increments</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; };\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#slider\" ).slider({\n\t\t\tvalue:100,\n\t\t\tmin: 0,\n\t\t\tmax: 500,\n\t\t\tstep: 50,\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#amount\" ).val( \"$\" + ui.value );\n\t\t\t}\n\t\t});\n\t\t$( \"#amount\" ).val( \"$\" + $( \"#slider\" ).slider( \"value\" ) );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"amount\">Donation amount ($50 increments):</label>\n\t<input type=\"text\" id=\"amount\" style=\"border:0; color:#f6931f; font-weight:bold;\" />\n</p>\n\n<div id=\"slider\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Increment slider values with the <code>step</code> option set to an integer, commonly a dividend of the slider's maximum value.  The default increment is 1.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/slider/tabs.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider - Snap to increments</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<script src=\"../../ui/jquery.ui.slider.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#demo-frame > div.demo { padding: 10px !important; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs({\n\t\t\tselect: function( event, ui ) {\n\t\t\t\t$( \"#slider\" ).slider( \"value\", ui.index );\n\t\t\t}\n\t\t});\n\t\t$( \"#slider\" ).slider({\n\t\t\tmin: 0,\n\t\t\tmax: $( \"#tabs\" ).tabs( \"length\" ) - 1,\n\t\t\tslide: function( event, ui ) {\n\t\t\t\t$( \"#tabs\" ).tabs( \"select\", ui.value );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"slider\" style=\"width:100px\"></div>\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Control tabs with a slider.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/connect-lists-through-tabs.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Connect lists with Tabs</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable1 li, #sortable2 li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.2em; width: 120px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable1, #sortable2\" ).sortable().disableSelection();\n\n\t\tvar $tabs = $( \"#tabs\" ).tabs();\n\n\t\tvar $tab_items = $( \"ul:first li\", $tabs ).droppable({\n\t\t\taccept: \".connectedSortable li\",\n\t\t\thoverClass: \"ui-state-hover\",\n\t\t\tdrop: function( event, ui ) {\n\t\t\t\tvar $item = $( this );\n\t\t\t\tvar $list = $( $item.find( \"a\" ).attr( \"href\" ) )\n\t\t\t\t\t.find( \".connectedSortable\" );\n\n\t\t\t\tui.draggable.hide( \"slow\", function() {\n\t\t\t\t\t$tabs.tabs( \"select\", $tab_items.index( $item ) );\n\t\t\t\t\t$( this ).appendTo( $list ).show( \"slow\" );\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<ul id=\"sortable1\" class=\"connectedSortable ui-helper-reset\">\n\t\t\t<li class=\"ui-state-default\">Item 1</li>\n\t\t\t<li class=\"ui-state-default\">Item 2</li>\n\t\t\t<li class=\"ui-state-default\">Item 3</li>\n\t\t\t<li class=\"ui-state-default\">Item 4</li>\n\t\t\t<li class=\"ui-state-default\">Item 5</li>\n\t\t</ul>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<ul id=\"sortable2\" class=\"connectedSortable ui-helper-reset\">\n\t\t\t<li class=\"ui-state-highlight\">Item 1</li>\n\t\t\t<li class=\"ui-state-highlight\">Item 2</li>\n\t\t\t<li class=\"ui-state-highlight\">Item 3</li>\n\t\t\t<li class=\"ui-state-highlight\">Item 4</li>\n\t\t\t<li class=\"ui-state-highlight\">Item 5</li>\n\t\t</ul>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Sort items from one list into another and vice versa, by dropping the list item on the appropriate tab above.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/connect-lists.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Connect lists</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable1, #sortable2 { list-style-type: none; margin: 0; padding: 0 0 2.5em; float: left; margin-right: 10px; }\n\t#sortable1 li, #sortable2 li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.2em; width: 120px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable1, #sortable2\" ).sortable({\n\t\t\tconnectWith: \".connectedSortable\"\n\t\t}).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<ul id=\"sortable1\" class=\"connectedSortable\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default\">Item 2</li>\n\t<li class=\"ui-state-default\">Item 3</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n\t<li class=\"ui-state-default\">Item 5</li>\n</ul>\n\n<ul id=\"sortable2\" class=\"connectedSortable\">\n\t<li class=\"ui-state-highlight\">Item 1</li>\n\t<li class=\"ui-state-highlight\">Item 2</li>\n\t<li class=\"ui-state-highlight\">Item 3</li>\n\t<li class=\"ui-state-highlight\">Item 4</li>\n\t<li class=\"ui-state-highlight\">Item 5</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tSort items from one list into another and vice versa, by passing a selector into\n\tthe <code>connectWith</code> option. The simplest way to do this is to\n\tgroup all related lists with a CSS class, and then pass that class into the\n\tsortable function (i.e., <code>connectWith: '.myclass'</code>).\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable { list-style-type: none; margin: 0; padding: 0; width: 60%; }\n\t#sortable li { margin: 0 3px 3px 3px; padding: 0.4em; padding-left: 1.5em; font-size: 1.4em; height: 18px; }\n\t#sortable li span { position: absolute; margin-left: -1.3em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable\" ).sortable();\n\t\t$( \"#sortable\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<ul id=\"sortable\">\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 1</li>\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 2</li>\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 3</li>\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 4</li>\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 5</li>\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 6</li>\n\t<li class=\"ui-state-default\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span>Item 7</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tEnable a group of DOM elements to be sortable. Click on and drag an\n\telement to a new spot within the list, and the other items will adjust to\n\tfit. By default, sortable items share <code>draggable</code> properties.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/delay-start.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Delay start</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable1, #sortable2 { list-style-type: none; margin: 0; padding: 0; margin-bottom: 15px;zoom: 1; }\n\t#sortable1 li, #sortable2 li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.2em; width: 95%; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable1\" ).sortable({\n\t\t\tdelay: 300\n\t\t});\n\t\t\n\t\t$( \"#sortable2\" ).sortable({\n\t\t\tdistance: 15\n\t\t});\n\n\t\t$( \"li\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<h3 class=\"docs\">Time delay of 300ms:</h3>\n\n<ul id=\"sortable1\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default\">Item 2</li>\n\t<li class=\"ui-state-default\">Item 3</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n</ul>\n\n<h3 class=\"docs\">Distance delay of 15px:</h3>\n\n<ul id=\"sortable2\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default\">Item 2</li>\n\t<li class=\"ui-state-default\">Item 3</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tPrevent accidental sorting either by delay (time) or distance. Set a number of\n\tmilliseconds the element needs to be dragged before sorting starts\n\twith the <code>delay</code> option. Set a distance in pixels the element\n\tneeds to be dragged before sorting starts with the <code>distance</code>\n\toption.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/display-grid.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Display as grid</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable { list-style-type: none; margin: 0; padding: 0; }\n\t#sortable li { margin: 3px 3px 3px 0; padding: 1px; float: left; width: 100px; height: 90px; font-size: 4em; text-align: center; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable\" ).sortable();\n\t\t$( \"#sortable\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<ul id=\"sortable\">\n\t<li class=\"ui-state-default\">1</li>\n\t<li class=\"ui-state-default\">2</li>\n\t<li class=\"ui-state-default\">3</li>\n\t<li class=\"ui-state-default\">4</li>\n\t<li class=\"ui-state-default\">5</li>\n\t<li class=\"ui-state-default\">6</li>\n\t<li class=\"ui-state-default\">7</li>\n\t<li class=\"ui-state-default\">8</li>\n\t<li class=\"ui-state-default\">9</li>\n\t<li class=\"ui-state-default\">10</li>\n\t<li class=\"ui-state-default\">11</li>\n\t<li class=\"ui-state-default\">12</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tTo arrange sortable items as a grid, give them identical dimensions and\n\tfloat them using CSS.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/empty-lists.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Handle empty lists</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable1, #sortable2, #sortable3 { list-style-type: none; margin: 0; padding: 0; float: left; margin-right: 10px; background: #eee; padding: 5px; width: 143px;}\n\t#sortable1 li, #sortable2 li, #sortable3 li { margin: 5px; padding: 5px; font-size: 1.2em; width: 120px; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"ul.droptrue\" ).sortable({\n\t\t\tconnectWith: \"ul\"\n\t\t});\n\n\t\t$( \"ul.dropfalse\" ).sortable({\n\t\t\tconnectWith: \"ul\",\n\t\t\tdropOnEmpty: false\n\t\t});\n\n\t\t$( \"#sortable1, #sortable2, #sortable3\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<ul id=\"sortable1\" class='droptrue'>\n\t<li class=\"ui-state-default\">Can be dropped..</li>\n\t<li class=\"ui-state-default\">..on an empty list</li>\n\t<li class=\"ui-state-default\">Item 3</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n\t<li class=\"ui-state-default\">Item 5</li>\n</ul>\n\n<ul id=\"sortable2\" class='dropfalse'>\n\t<li class=\"ui-state-highlight\">Cannot be dropped..</li>\n\t<li class=\"ui-state-highlight\">..on an empty list</li>\n\t<li class=\"ui-state-highlight\">Item 3</li>\n\t<li class=\"ui-state-highlight\">Item 4</li>\n\t<li class=\"ui-state-highlight\">Item 5</li>\n</ul>\n\n<ul id=\"sortable3\" class='droptrue'>\n</ul>\n\n<br style=\"clear:both\" />\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tPrevent all items in a list from being dropped into a separate, empty list\n\tusing the <code>dropOnEmpty</code> option set to <code>false</code>.  By default,\n\tsortable items can be dropped on empty lists.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"placeholder.html\">Drop placeholder</a></li>\n\t\t<li><a href=\"connect-lists.html\">Connect lists</a></li>\n\t\t<li><a href=\"connect-lists-through-tabs.html\">Connect lists through tabs</a></li>\n\t\t<li><a href=\"empty-lists.html\">Handle empty lists</a></li>\n\t\t<li><a href=\"items.html\">Include / exclude items</a></li>\n\t\t<li><a href=\"delay-start.html\">Delay start</a></li>\n\t\t<li><a href=\"display-grid.html\">Display as grid</a></li>\t\t\n\t\t<li><a href=\"portlets.html\">Portlets</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/items.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Include / exclude items</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable1, #sortable2 { list-style-type: none; margin: 0; padding: 0; zoom: 1; }\n\t#sortable1 li, #sortable2 li { margin: 0 5px 5px 5px; padding: 3px; width: 90%; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable1\" ).sortable({\n\t\t\titems: \"li:not(.ui-state-disabled)\"\n\t\t});\n\n\t\t$( \"#sortable2\" ).sortable({\n\t\t\tcancel: \".ui-state-disabled\"\n\t\t});\n\n\t\t$( \"#sortable1 li, #sortable2 li\" ).disableSelection();\t\t\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<h3 class=\"docs\">Specify which items are sortable:</h3>\n\n<ul id=\"sortable1\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default ui-state-disabled\">(I'm not sortable or a drop target)</li>\n\t<li class=\"ui-state-default ui-state-disabled\">(I'm not sortable or a drop target)</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n</ul>\n\n<h3 class=\"docs\">Cancel sorting (but keep as drop targets):</h3>\n\n<ul id=\"sortable2\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default ui-state-disabled\">(I'm not sortable)</li>\n\t<li class=\"ui-state-default ui-state-disabled\">(I'm not sortable)</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tSpecify which items are eligible to sort by passing a jQuery selector into\n\tthe <code>items</code> option. Items excluded from this option are not\n\tsortable, nor are they valid targets for sortable items.\n</p>\n<p>\n\tTo only prevent sorting on certain items, pass a jQuery selector into the\n\t<code>cancel</code> option. Cancelled items remain valid sort targets for\n\tothers.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/placeholder.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Drop placeholder</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#sortable { list-style-type: none; margin: 0; padding: 0; width: 60%; }\n\t#sortable li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.2em; height: 1.5em; }\n\thtml>body #sortable li { height: 1.5em; line-height: 1.2em; }\n\t.ui-state-highlight { height: 1.5em; line-height: 1.2em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#sortable\" ).sortable({\n\t\t\tplaceholder: \"ui-state-highlight\"\n\t\t});\n\t\t$( \"#sortable\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<ul id=\"sortable\">\n\t<li class=\"ui-state-default\">Item 1</li>\n\t<li class=\"ui-state-default\">Item 2</li>\n\t<li class=\"ui-state-default\">Item 3</li>\n\t<li class=\"ui-state-default\">Item 4</li>\n\t<li class=\"ui-state-default\">Item 5</li>\n\t<li class=\"ui-state-default\">Item 6</li>\n\t<li class=\"ui-state-default\">Item 7</li>\n</ul>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tWhen dragging a sortable item to a new location, other items will make room\n\tfor the that item by shifting to allow white space between them. Pass a\n\tclass into the <code>placeholder</code> option to style that space to\n\tbe visible.  Use the boolean <code>forcePlaceholderSize</code> option\n\tto set dimensions on the placeholder.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/sortable/portlets.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable - Portlets</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.column { width: 170px; float: left; padding-bottom: 100px; }\n\t.portlet { margin: 0 1em 1em 0; }\n\t.portlet-header { margin: 0.3em; padding-bottom: 4px; padding-left: 0.2em; }\n\t.portlet-header .ui-icon { float: right; }\n\t.portlet-content { padding: 0.4em; }\n\t.ui-sortable-placeholder { border: 1px dotted black; visibility: visible !important; height: 50px !important; }\n\t.ui-sortable-placeholder * { visibility: hidden; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \".column\" ).sortable({\n\t\t\tconnectWith: \".column\"\n\t\t});\n\n\t\t$( \".portlet\" ).addClass( \"ui-widget ui-widget-content ui-helper-clearfix ui-corner-all\" )\n\t\t\t.find( \".portlet-header\" )\n\t\t\t\t.addClass( \"ui-widget-header ui-corner-all\" )\n\t\t\t\t.prepend( \"<span class='ui-icon ui-icon-minusthick'></span>\")\n\t\t\t\t.end()\n\t\t\t.find( \".portlet-content\" );\n\n\t\t$( \".portlet-header .ui-icon\" ).click(function() {\n\t\t\t$( this ).toggleClass( \"ui-icon-minusthick\" ).toggleClass( \"ui-icon-plusthick\" );\n\t\t\t$( this ).parents( \".portlet:first\" ).find( \".portlet-content\" ).toggle();\n\t\t});\n\n\t\t$( \".column\" ).disableSelection();\n\t});\n\t</script>\n</head>\n<body>\n<div class=\"demo\">\n\n<div class=\"column\">\n\n\t<div class=\"portlet\">\n\t\t<div class=\"portlet-header\">Feeds</div>\n\t\t<div class=\"portlet-content\">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>\n\t</div>\n\t\n\t<div class=\"portlet\">\n\t\t<div class=\"portlet-header\">News</div>\n\t\t<div class=\"portlet-content\">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>\n\t</div>\n\n</div>\n\n<div class=\"column\">\n\n\t<div class=\"portlet\">\n\t\t<div class=\"portlet-header\">Shopping</div>\n\t\t<div class=\"portlet-content\">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>\n\t</div>\n\n</div>\n\n<div class=\"column\">\n\n\t<div class=\"portlet\">\n\t\t<div class=\"portlet-header\">Links</div>\n\t\t<div class=\"portlet-content\">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>\n\t</div>\n\t\n\t<div class=\"portlet\">\n\t\t<div class=\"portlet-header\">Images</div>\n\t\t<div class=\"portlet-content\">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>\n\t</div>\n\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tEnable portlets (styled divs) as sortables and use the <code>connectWith</code>\n\toption to allow sorting between columns.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/currency.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../external/globalize.js\"></script>\n\t<script src=\"../../external/globalize.culture.de-DE.js\"></script>\n\t<script src=\"../../external/globalize.culture.ja-JP.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.spinner.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#currency\" ).change(function() {\n\t\t\t$( \"#spinner\" ).spinner( \"option\", \"culture\", $( this ).val() );\n\t\t});\n\n\t\t$( \"#spinner\" ).spinner({\n\t\t\tmin: 5,\n\t\t\tmax: 2500,\n\t\t\tstep: 25,\n\t\t\tstart: 1000,\n\t\t\tnumberFormat: \"C\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"currency\">Currency to donate</label>\n\t<select id=\"currency\" name=\"currency\">\n\t\t<option value=\"en-US\">US $</option>\n\t\t<option value=\"de-DE\">EUR €</option>\n\t\t<option value=\"ja-JP\">YEN ¥</option>\n\t</select>\n</p>\n<p>\n\t<label for=\"spinner\">Amount to donate:</label>\n\t<input id=\"spinner\" name=\"spinner\" value=\"5\">\n</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Example of a donation form, with currency selection and amout spinner.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/decimal.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner - Decimal</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../external/globalize.js\"></script>\n\t<script src=\"../../external/globalize.culture.de-DE.js\"></script>\n\t<script src=\"../../external/globalize.culture.ja-JP.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.spinner.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#spinner\" ).spinner({\n\t\t\tstep: 0.01,\n\t\t\tnumberFormat: \"n\"\n\t\t});\n\n\t\t$( \"#culture\" ).change(function() {\n\t\t\tvar current = $( \"#spinner\" ).spinner( \"value\" );\n\t\t\tGlobalize.culture( $(this).val() );\n\t\t\t$( \"#spinner\" ).spinner( \"value\", current );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"spinner\">Decimal spinner:</label>\n\t<input id=\"spinner\" name=\"spinner\" value=\"5.06\">\n</p>\n<p>\n\t<label for=\"culture\">Select a culture to use for formatting:</label>\n\t<select id=\"culture\">\n\t\t<option value=\"en-EN\" selected=\"selected\">English</option>\n\t\t<option value=\"de-DE\">German</option>\n\t\t<option value=\"ja-JP\">Japanese</option>\n\t</select>\n</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tExample of a decimal spinner. Step is set to 0.01.\n\t<br>The code handling the culture change reads the current spinner value,\n\tthen changes the culture, then sets the value again, resulting in an updated\n\tformatting, based on the new culture.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/default.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.spinner.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tvar spinner = $( \"#spinner\" ).spinner();\n\n\t\t$( \"#disable\" ).click(function() {\n\t\t\tif ( spinner.spinner( \"option\", \"disabled\" ) ) {\n\t\t\t\tspinner.spinner( \"enable\" );\n\t\t\t} else {\n\t\t\t\tspinner.spinner( \"disable\" );\n\t\t\t}\n\t\t});\n\t\t$( \"#destroy\" ).click(function() {\n\t\t\tif ( spinner.data( \"ui-spinner\" ) ) {\n\t\t\t\tspinner.spinner( \"destroy\" );\n\t\t\t} else {\n\t\t\t\tspinner.spinner();\n\t\t\t}\n\t\t});\n\t\t$( \"#getvalue\" ).click(function() {\n\t\t\talert( spinner.spinner( \"value\" ) );\n\t\t});\n\t\t$( \"#setvalue\" ).click(function() {\n\t\t\tspinner.spinner( \"value\", 5 );\n\t\t});\n\n\t\t$( \"button\" ).button();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"spinner\">Select a value:</label>\n\t<input id=\"spinner\" name=\"value\">\n</p>\n\n<p>\n\t<button id=\"disable\">Toggle disable/enable</button>\n\t<button id=\"destroy\">Toggle widget</button>\n</p>\n\n<p>\n\t<button id=\"getvalue\">Get value</button>\n\t<button id=\"setvalue\">Set value to 5</button>\n</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Default spinner.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"decimal.html\">Decimal</a></li>\n\t\t<li><a href=\"currency.html\">Currency</a></li>\n\t\t<li><a href=\"latlong.html\">Map</a></li>\n\t\t<li><a href=\"time.html\">Time</a></li>\n\t\t<li><a href=\"overflow.html\">Overflow</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/latlong.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner - Map</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"http://maps.google.com/maps/api/js?sensor=false\"></script>\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.spinner.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tfunction latlong() {\n\t\t\treturn new google.maps.LatLng( $(\"#lat\").val(), $(\"#lng\").val() );\n\t\t}\n\t\tfunction position() {\n\t\t\tmap.setCenter( latlong() );\n\t\t}\n\t\t$( \"#lat, #lng\" ).spinner({\n\t\t\tstep: .001,\n\t\t\tchange: position,\n\t\t\tstop: position\n\t\t});\n\n\t\tvar map = new google.maps.Map( $(\"#map\")[0], {\n\t\t\tzoom: 8,\n\t\t\tcenter: latlong(),\n\t\t\tmapTypeId: google.maps.MapTypeId.ROADMAP\n\t\t});\n\t});\n\t</script>\n\t<style>\n\t#map {\n\t\twidth:500px;\n\t\theight:500px;\n\t}\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<label for=\"lat\">Latitude</label>\n<input id=\"lat\" name=\"lat\" value=\"44.797\">\n<br>\n<label for=\"lng\">Longitude</label>\n<input id=\"lng\" name=\"lng\" value=\"-93.278\">\n\n<div id=\"map\"></div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Google Maps integration, using spinners to change latidude and longitude.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/overflow.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner - Overflow</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.spinner.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#spinner\" ).spinner({\n\t\t\tspin: function( event, ui ) {\n\t\t\t\tif ( ui.value > 10 ) {\n\t\t\t\t\t$( this ).spinner( \"value\", -10 );\n\t\t\t\t\treturn false;\n\t\t\t\t} else if ( ui.value < -10 ) {\n\t\t\t\t\t$( this ).spinner( \"value\", 10 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>\n\t<label for=\"spinner\">Select a value:</label>\n\t<input id=\"spinner\" name=\"value\" />\n</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\nOverflowing spinner restricted to a range of -10 to 10.\nFor anything above 10, it'll overflow to -10, and the other way round.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/spinner/time.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner - Time</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../external/globalize.js\"></script>\n\t<script src=\"../../external/globalize.culture.de-DE.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.spinner.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$.widget( \"ui.timespinner\", $.ui.spinner, {\n\t\toptions: {\n\t\t\t// seconds\n\t\t\tstep: 60 * 1000,\n\t\t\t// hours\n\t\t\tpage: 60\n\t\t},\n\n\t\t_parse: function( value ) {\n\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\t// already a timestamp\n\t\t\t\tif ( Number( value ) == value ) {\n\t\t\t\t\treturn Number( value );\n\t\t\t\t}\n\t\t\t\treturn +Globalize.parseDate( value );\n\t\t\t}\n\t\t\treturn value;\n\t\t},\n\n\t\t_format: function( value ) {\n\t\t\treturn Globalize.format( new Date(value), \"t\" );\n\t\t}\n\t});\n\n\t$(function() {\n\t\t$( \"#spinner\" ).timespinner();\n\n\t\t$( \"#culture\" ).change(function() {\n\t\t\tvar current = $( \"#spinner\" ).timespinner( \"value\" );\n\t\t\tGlobalize.culture( $(this).val() );\n\t\t\t$( \"#spinner\" ).timespinner( \"value\", current );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n<p>\n\t<label for=\"spinner\">Time spinner:</label>\n\t<input id=\"spinner\" name=\"spinner\" value=\"08:30 PM\">\n</p>\n<p>\n\t<label for=\"culture\">Select a culture to use for formatting:</label>\n\t<select id=\"culture\">\n\t\t<option value=\"en-EN\" selected=\"selected\">English</option>\n\t\t<option value=\"de-DE\">German</option>\n\t</select>\n</p>\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>\n\tA custom widget extending spinner. Use the Globalization plugin to parse and output\n\ta timestamp, with custom step and page options. Cursor up/down spins minutes, page up/down\n\tspins hours.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/switchClass/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - switchClass Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.toggler { width: 500px; height: 200px; position: relative; }\n\t#button { padding: .5em 1em; text-decoration: none; }\n\t#effect {position: relative;   }\n\t.newClass { width: 240px;  padding: 1em; letter-spacing: 0; font-size: 1.2em; margin: 0; }\n\t.anotherNewClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.6em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#button\" ).click(function(){\n\t\t\t$( \".newClass\" ).switchClass( \"newClass\", \"anotherNewClass\", 1000 );\n\t\t\t$( \".anotherNewClass\" ).switchClass( \"anotherNewClass\", \"newClass\", 1000 );\n\t\t\treturn false;\t\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"newClass ui-corner-all\">\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. \n\t</div>\n</div>\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/switchClass/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/ajax/content1.html",
    "content": "<p><strong>This content was loaded via ajax.</strong></p>\n<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n<p>Mauris vitae ante. Curabitur augue. Nulla purus nibh, lobortis ut, feugiat at, aliquam id, purus. Sed venenatis, lorem venenatis volutpat commodo, purus quam lacinia justo, mattis interdum pede pede a odio. Fusce nibh. Morbi nisl mauris, dapibus in, tristique eget, accumsan et, pede. Donec mauris risus, pulvinar ut, faucibus eu, mollis in, nunc. In augue massa, commodo a, cursus vehicula, varius eu, dui. Suspendisse sodales suscipit lorem. Morbi malesuada, eros quis condimentum dignissim, lectus nibh tristique urna, non bibendum diam massa vel risus. Morbi suscipit. Proin egestas, eros at scelerisque scelerisque, dolor lacus fringilla lacus, ut ullamcorper mi magna at quam. Aliquam sed elit. Aliquam turpis purus, congue quis, iaculis id, ullamcorper sit amet, justo. Maecenas sed mauris. Proin magna justo, interdum in, tincidunt eu, viverra eu, turpis. Suspendisse mollis. In magna. Phasellus pellentesque, urna pellentesque convallis pellentesque, augue sem blandit pede, at rhoncus libero nisl a odio.</p>\n<p>Sed vitae nibh non magna semper tempor. Duis dolor. Nam congue laoreet arcu. Fusce lobortis enim quis ligula. Maecenas commodo odio id mi. Maecenas scelerisque tellus eu odio. Etiam dolor purus, lacinia a, imperdiet in, aliquam et, eros. In pellentesque. Nullam ac massa. Integer et turpis. Ut quam augue, congue non, imperdiet id, eleifend ac, nisi. Etiam ac arcu. Cras iaculis accumsan erat. Nullam vulputate sapien nec nisi pretium rhoncus. Aliquam a nibh. Vivamus est ante, fermentum a, tincidunt ut, imperdiet nec, velit. Aenean non tortor. Sed nec mauris eget tellus condimentum rutrum.</p>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/ajax/content2.html",
    "content": "<p><strong>This other content was loaded via ajax.</strong></p>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean nec turpis justo, et facilisis ligula. In congue interdum odio, a scelerisque eros posuere ac. Aenean massa tellus, dictum sit amet laoreet ut, aliquam in orci. Duis eu aliquam ligula. Nullam vel placerat ligula. Fusce venenatis viverra dictum. Phasellus dui dolor, imperdiet in sodales at, mattis sed libero. Morbi ac ipsum ligula. Quisque suscipit dui vel diam pretium nec cursus lacus malesuada. Donec sollicitudin, eros eget dignissim mollis, risus leo feugiat tellus, vel posuere nisl ipsum eu erat. Quisque posuere lacinia imperdiet. Quisque nunc leo, elementum quis ultricies et, vehicula sit amet turpis. Nullam sed nunc nec nibh condimentum mattis. Quisque sed ligula sit amet nisi ultricies bibendum eget id nisi.</p>\n<p>Proin ut erat vel nunc tincidunt commodo. Curabitur feugiat, nisi et vehicula viverra, nisl orci eleifend arcu, sed blandit lectus nisl quis nisi. In hac habitasse platea dictumst. In hac habitasse platea dictumst. Aenean rutrum gravida velit ac imperdiet. Integer vitae arcu risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin tincidunt orci at leo egestas porta. Vivamus ac augue et enim bibendum hendrerit ut id urna. Donec sollicitudin pulvinar turpis vitae scelerisque. Etiam tempor porttitor est sed blandit. Phasellus varius consequat leo eget tincidunt. Aliquam ac dui lectus. In et consectetur orci. Duis posuere nulla ac turpis faucibus vestibulum. Sed ut velit et dolor rhoncus dapibus. Sed sit amet pellentesque est.</p>\n<p>Nam in volutpat orci. Morbi sit amet orci in erat egestas dignissim. Etiam mi sapien, tempus sed iaculis a, adipiscing quis tellus. Suspendisse potenti. Nam malesuada tristique vestibulum. In tempor tellus dignissim neque consectetur eu vestibulum nisl pellentesque. Phasellus ultrices cursus velit, id aliquam nisl fringilla quis. Cras varius elit sed urna ultrices congue. Sed ornare odio sed velit pellentesque id varius nisl sodales. Sed auctor ligula egestas mi pharetra ut consectetur erat pharetra.</p>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/ajax/content3-slow.php",
    "content": "<?php\nsleep(1);\n?>\n<p><strong>This content was loaded via ajax, though it took a second.</strong></p>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean nec turpis justo, et facilisis ligula. In congue interdum odio, a scelerisque eros posuere ac. Aenean massa tellus, dictum sit amet laoreet ut, aliquam in orci. Duis eu aliquam ligula. Nullam vel placerat ligula. Fusce venenatis viverra dictum. Phasellus dui dolor, imperdiet in sodales at, mattis sed libero. Morbi ac ipsum ligula. Quisque suscipit dui vel diam pretium nec cursus lacus malesuada. Donec sollicitudin, eros eget dignissim mollis, risus leo feugiat tellus, vel posuere nisl ipsum eu erat. Quisque posuere lacinia imperdiet. Quisque nunc leo, elementum quis ultricies et, vehicula sit amet turpis. Nullam sed nunc nec nibh condimentum mattis. Quisque sed ligula sit amet nisi ultricies bibendum eget id nisi.</p>\n<p>Proin ut erat vel nunc tincidunt commodo. Curabitur feugiat, nisi et vehicula viverra, nisl orci eleifend arcu, sed blandit lectus nisl quis nisi. In hac habitasse platea dictumst. In hac habitasse platea dictumst. Aenean rutrum gravida velit ac imperdiet. Integer vitae arcu risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin tincidunt orci at leo egestas porta. Vivamus ac augue et enim bibendum hendrerit ut id urna. Donec sollicitudin pulvinar turpis vitae scelerisque. Etiam tempor porttitor est sed blandit. Phasellus varius consequat leo eget tincidunt. Aliquam ac dui lectus. In et consectetur orci. Duis posuere nulla ac turpis faucibus vestibulum. Sed ut velit et dolor rhoncus dapibus. Sed sit amet pellentesque est.</p>\n<p>Nam in volutpat orci. Morbi sit amet orci in erat egestas dignissim. Etiam mi sapien, tempus sed iaculis a, adipiscing quis tellus. Suspendisse potenti. Nam malesuada tristique vestibulum. In tempor tellus dignissim neque consectetur eu vestibulum nisl pellentesque. Phasellus ultrices cursus velit, id aliquam nisl fringilla quis. Cras varius elit sed urna ultrices congue. Sed ornare odio sed velit pellentesque id varius nisl sodales. Sed auctor ligula egestas mi pharetra ut consectetur erat pharetra.</p>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/ajax/content4-broken.php",
    "content": "<?php \nheader(\"HTTP/1.0 404 Not Found\");\n?>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/ajax.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Content via Ajax</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs({\n\t\t\tbeforeLoad: function( event, ui ) {\n\t\t\t\tui.jqXHR.error(function() {\n\t\t\t\t\tui.panel.html(\n\t\t\t\t\t\t\"Couldn't load this tab. We'll try to fix this as soon as possible. \" +\n\t\t\t\t\t\t\"If this wouldn't be a demo.\" );\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Preloaded</a></li>\n\t\t<li><a href=\"ajax/content1.html\">Tab 1</a></li>\n\t\t<li><a href=\"ajax/content2.html\">Tab 2</a></li>\n\t\t<li><a href=\"ajax/content3-slow.php\">Tab 3 (slow)</a></li>\n\t\t<li><a href=\"ajax/content4-broken.php\">Tab 4 (broken)</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Fetch external content via Ajax for the tabs by setting an href value in the tab links.  While the Ajax request is waiting for a response, the tab label changes to say \"Loading...\", then returns to the normal label once loaded.</p>\n<p>Tabs 3 and 4 demonstrate slow-loading and broken AJAX tabs, and how to handle serverside errors in those cases. Note: These two require a webserver to interpret PHP. They won't work from the filesystem.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/bottom.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Tabs at bottom</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs();\n\n\t\t// fix the classes\n\t\t$( \".tabs-bottom .ui-tabs-nav, .tabs-bottom .ui-tabs-nav > *\" )\n\t\t\t.removeClass( \"ui-corner-all ui-corner-top\" )\n\t\t\t.addClass( \"ui-corner-bottom\" );\n\n\t\t// move the nav to the bottom\n\t\t$( \".tabs-bottom .ui-tabs-nav\" ).appendTo( \".tabs-bottom\" );\n\t});\n\t</script>\n\t<style>\n\t/* force a height so the tabs don't jump as content height changes */\n\t#tabs .tabs-spacer { float: left; height: 200px; }\n\t.tabs-bottom .ui-tabs-nav { clear: left; padding: 0 .2em .2em .2em; }\n\t.tabs-bottom .ui-tabs-nav li { top: auto; bottom: 0; margin: 0 .2em 1px 0; border-bottom: auto; border-top: 0; }\n\t.tabs-bottom .ui-tabs-nav li.ui-tabs-active { margin-top: -1px; padding-top: 1px; }\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\" class=\"tabs-bottom\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div class=\"tabs-spacer\"></div>\n\t<div id=\"tabs-1\">\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>With some additional CSS (for positioning) and JS (to put the right classes on elements) the tabs can be placed below their content.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/collapsible.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Collapse content</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs({\n\t\t\tcollapsible: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<p><strong>Click this tab again to close the content pane.</strong></p>\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p><strong>Click this tab again to close the content pane.</strong></p>\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p><strong>Click this tab again to close the content pane.</strong></p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the selected tab to toggle its content closed/open.  To enable this functionality, set the <code>collapsible</code> option to true.</p>\n<pre><code>collapsible: true\n</code></pre>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs();\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click tabs to swap between content that is broken into logical sections.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"ajax.html\">Content via Ajax</a></li>\n\t\t<li><a href=\"mouseover.html\">Open on mouseover</a></li>\n\t\t<li><a href=\"collapsible.html\">Collapse content</a></li>\n\t\t<li><a href=\"sortable.html\">Sortable</a></li>\n\t\t<li><a href=\"manipulation.html\">Simple manipulation</a></li>\n\t\t<li><a href=\"bottom.html\">Tabs below content</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/manipulation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Simple manipulation</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<script src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t#dialog label, #dialog input { display:block; }\n\t#dialog label { margin-top: 0.5em; }\n\t#dialog input, #dialog textarea { width: 95%; }\n\t#tabs { margin-top: 1em; }\n\t#tabs li .ui-icon-close { float: left; margin: 0.4em 0.2em 0 0; cursor: pointer; }\n\t#add_tab { cursor: pointer; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar tabTitle = $( \"#tab_title\" ),\n\t\t\ttabContent = $( \"#tab_content\" ),\n\t\t\ttabTemplate = \"<li><a href='#{href}'>#{label}</a> <span class='ui-icon ui-icon-close'>Remove Tab</span></li>\",\n\t\t\ttabCounter = 2;\n\n\t\tvar tabs = $( \"#tabs\" ).tabs();\n\n\t\t// modal dialog init: custom buttons and a \"close\" callback reseting the form inside\n\t\tvar dialog = $( \"#dialog\" ).dialog({\n\t\t\tautoOpen: false,\n\t\t\tmodal: true,\n\t\t\tbuttons: {\n\t\t\t\tAdd: function() {\n\t\t\t\t\taddTab();\n\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t},\n\t\t\t\tCancel: function() {\n\t\t\t\t\t$( this ).dialog( \"close\" );\n\t\t\t\t}\n\t\t\t},\n\t\t\tclose: function() {\n\t\t\t\tform[ 0 ].reset();\n\t\t\t}\n\t\t});\n\n\t\t// addTab form: calls addTab function on submit and closes the dialog\n\t\tvar form = dialog.find( \"form\" ).submit(function( event ) {\n\t\t\taddTab();\n\t\t\tdialog.dialog( \"close\" );\n\t\t\tevent.preventDefault();\n\t\t});\n\n\t\t// actual addTab function: adds new tab using the input from the form above\n\t\tfunction addTab() {\n\t\t\tvar label = tabTitle.val() || \"Tab \" + tabCounter,\n\t\t\t\tid = \"tabs-\" + tabCounter,\n\t\t\t\tli = $( tabTemplate.replace( /#\\{href\\}/g, \"#\" + id ).replace( /#\\{label\\}/g, label ) ),\n\t\t\t\ttabContentHtml = tabContent.val() || \"Tab \" + tabCounter + \" content.\";\n\n\t\t\ttabs.find( \".ui-tabs-nav\" ).append( li );\n\t\t\ttabs.append( \"<div id='\" + id + \"'><p>\" + tabContentHtml + \"</p></div>\" );\n\t\t\ttabs.tabs( \"refresh\" );\n\t\t\ttabCounter++;\n\t\t}\n\n\t\t// addTab button: just opens the dialog\n\t\t$( \"#add_tab\" )\n\t\t\t.button()\n\t\t\t.click(function() {\n\t\t\t\tdialog.dialog( \"open\" );\n\t\t\t});\n\n\t\t// close icon: removing the tab on click\n\t\t$( \"#tabs span.ui-icon-close\" ).live( \"click\", function() {\n\t\t\tvar panelId = $( this ).closest( \"li\" ).remove().attr( \"aria-controls\" );\n\t\t\t$( \"#\" + panelId ).remove();\n\t\t\ttabs.tabs( \"refresh\" );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n\t<div id=\"dialog\" title=\"Tab data\">\n\t\t<form>\n\t\t\t<fieldset class=\"ui-helper-reset\">\n\t\t\t\t<label for=\"tab_title\">Title</label>\n\t\t\t\t<input type=\"text\" name=\"tab_title\" id=\"tab_title\" value=\"\" class=\"ui-widget-content ui-corner-all\" />\n\t\t\t\t<label for=\"tab_content\">Content</label>\n\t\t\t\t<textarea name=\"tab_content\" id=\"tab_content\" class=\"ui-widget-content ui-corner-all\"></textarea>\n\t\t\t</fieldset>\n\t\t</form>\n\t</div>\n\n\t<button id=\"add_tab\">Add Tab</button>\n\n\t<div id=\"tabs\">\n\t\t<ul>\n\t\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a> <span class=\"ui-icon ui-icon-close\">Remove Tab</span></li>\n\t\t</ul>\n\t\t<div id=\"tabs-1\">\n\t\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t\t</div>\n\t</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Simple tabs adding and removing.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/mouseover.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Open on mouseover</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs({\n\t\t\tevent: \"mouseover\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Toggle sections open/closed on mouseover with the <code>event</code> option. The default value for event is \"click.\"</p>\n<pre><code>event: 'mouseover'\n</code></pre>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/sortable.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Sortable</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\tvar tabs = $( \"#tabs\" ).tabs();\n\t\ttabs.find( \".ui-tabs-nav\" ).sortable({\n\t\t\taxis: \"x\",\n\t\t\tstop: function() {\n\t\t\t\ttabs.tabs( \"refresh\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Drag the tabs above to re-order them.</p>\n<p>\nMaking tabs sortable is as simple as calling\n<code>.sortable()</code>\non the\n<code>.ui-tabs-nav</code>\nelement.\n</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tabs/vertical.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs - Vertical Tabs functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs().addClass( \"ui-tabs-vertical ui-helper-clearfix\" );\n\t\t$( \"#tabs li\" ).removeClass( \"ui-corner-top\" ).addClass( \"ui-corner-left\" );\n\t});\n\t</script>\n\t<style>\n\t.ui-tabs-vertical { width: 55em; }\n\t.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; }\n\t.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }\n\t.ui-tabs-vertical .ui-tabs-nav li a { display:block; }\n\t.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }\n\t.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;}\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">Nunc tincidunt</a></li>\n\t\t<li><a href=\"#tabs-2\">Proin dolor</a></li>\n\t\t<li><a href=\"#tabs-3\">Aenean lacinia</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<h2>Content heading 1</h2>\n\t\t<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<h2>Content heading 2</h2>\n\t\t<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<h2>Content heading 3</h2>\n\t\t<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>\n\t\t<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>\n\t</div>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click tabs to swap between content that is broken into logical sections.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/toggle/default.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - Toggle Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../ui/jquery.effects.explode.js\"></script>\n\t<script src=\"../../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../../ui/jquery.effects.highlight.js\"></script>\n\t<script src=\"../../ui/jquery.effects.pulsate.js\"></script>\n\t<script src=\"../../ui/jquery.effects.scale.js\"></script>\n\t<script src=\"../../ui/jquery.effects.shake.js\"></script>\n\t<script src=\"../../ui/jquery.effects.slide.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.toggler {\n\t\twidth: 500px;\n\t\theight: 200px;\n\t}\n\t#button {\n\t\tpadding: .5em 1em;\n\t\ttext-decoration: none;\n\t}\n\t#effect {\n\t\tposition: relative;\n\t\twidth: 240px;\n\t\theight: 135px;\n\t\tpadding: 0.4em;\n\t}\n\t#effect h3 {\n\t\tmargin: 0;\n\t\tpadding: 0.4em;\n\t\ttext-align: center;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// run the currently selected effect\n\t\tfunction runEffect() {\n\t\t\t// get effect type from\n\t\t\tvar selectedEffect = $( \"#effectTypes\" ).val();\n\n\t\t\t// most effect types need no options passed by default\n\t\t\tvar options = {};\n\t\t\t// some effects have required parameters\n\t\t\tif ( selectedEffect === \"scale\" ) {\n\t\t\t\toptions = { percent: 0 };\n\t\t\t} else if ( selectedEffect === \"size\" ) {\n\t\t\t\toptions = { to: { width: 200, height: 60 } };\n\t\t\t}\n\n\t\t\t// run the effect\n\t\t\t$( \"#effect\" ).toggle( selectedEffect, options, 500 );\n\t\t};\n\n\t\t// set effect from select menu value\n\t\t$( \"#button\" ).click(function() {\n\t\t\trunEffect();\n\t\t\treturn false;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"ui-widget-content ui-corner-all\">\n\t\t<h3 class=\"ui-widget-header ui-corner-all\">Toggle</h3>\n\t\t<p>\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. Nulla lorem metus, adipiscing ut, luctus sed, hendrerit vitae, mi.\n\t\t</p>\n\t</div>\n</div>\n\n<select name=\"effects\" id=\"effectTypes\">\n\t<option value=\"blind\">Blind</option>\n\t<option value=\"bounce\">Bounce</option>\n\t<option value=\"clip\">Clip</option>\n\t<option value=\"drop\">Drop</option>\n\t<option value=\"explode\">Explode</option>\n\t<option value=\"fold\">Fold</option>\n\t<option value=\"highlight\">Highlight</option>\n\t<option value=\"puff\">Puff</option>\n\t<option value=\"pulsate\">Pulsate</option>\n\t<option value=\"scale\">Scale</option>\n\t<option value=\"shake\">Shake</option>\n\t<option value=\"size\">Size</option>\n\t<option value=\"slide\">Slide</option>\n</select>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/toggle/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/toggleClass/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects - toggleClass Demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.toggler { width: 500px; height: 200px; position: relative; }\n\t#button { padding: .5em 1em; text-decoration: none; }\n\t#effect {position: relative;  width: 240px;  padding: 1em; letter-spacing: 0; font-size: 1.2em; border: 1px solid #000; background: #eee; color: #333; }\n\t.newClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.6em; }\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#button\" ).click(function() {\n\t\t\t$( \"#effect\" ).toggleClass( \"newClass\", 1000 );\n\t\t\treturn false;\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"toggler\">\n\t<div id=\"effect\" class=\"newClass ui-corner-all\">\n\t\t\tEtiam libero neque, luctus a, eleifend nec, semper at, lorem. Sed pede. \n\t</div>\n</div>\n\n<a href=\"#\" id=\"button\" class=\"ui-state-default ui-corner-all\">Run Effect</a>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Click the button above to preview the effect.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/toggleClass/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/ajax/content1.html",
    "content": "<p><strong>This content was loaded via ajax.</strong></p>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/ajax/content2.html",
    "content": "<p><strong>This other content was loaded via ajax.</strong></p>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/custom-animation.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Custom animation demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.explode.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \"#show-option\" ).tooltip({\n\t\t\tshow: {\n\t\t\t\teffect: \"slideDown\",\n\t\t\t\tdelay: 250\n\t\t\t}\n\t\t});\n\t\t$( \"#hide-option\" ).tooltip({\n\t\t\thide: {\n\t\t\t\teffect: \"explode\",\n\t\t\t\tdelay: 250\n\t\t\t}\n\t\t});\n\t\t$( \"#open-event\" ).tooltip({\n\t\t\tshow: null,\n\t\t\tposition: {\n\t\t\t\tmy: \"left top\",\n\t\t\t\tat: \"left bottom\"\n\t\t\t},\n\t\t\topen: function( event, ui ) {\n\t\t\t\tui.tooltip.animate({ top: ui.tooltip.position().top + 10 }, \"fast\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p>There are various ways to customize the animation of a tooltip.</p>\n<p>You can use the <a id=\"show-option\" href=\"http://jqueryui.com/demos/tooltip/#option-show\" title=\"slide down on show\">show</a> and\n<a id=\"hide-option\" href=\"http://jqueryui.com/demos/tooltip/#option-hide\" title=\"explode on hide\">hide</a> options.</p>\n<p>You can also use the <a id=\"open-event\" href=\"http://jqueryui.com/demos/tooltip/#event-open\" title=\"move down on show\">open event</a>.</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>This demo shows how to customize animations using the show and hide options,\nas well as the open event.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/custom-content.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Custom content</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.photo {\n\t\twidth: 300px;\n\t\ttext-align: center;\n\t}\n\t.photo .ui-widget-header {\n\t\tmargin: 1em 0;\n\t}\n\t.map {\n\t\twidth: 350px;\n\t\theight: 350px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \".demo\" ).tooltip({\n\t\t\titems: \"img, [data-geo], [title]\",\n\t\t\tcontent: function() {\n\t\t\t\tvar element = $( this );\n\t\t\t\tif ( element.is( \"[data-geo]\" ) ) {\n\t\t\t\t\tvar text = element.text();\n\t\t\t\t\treturn \"<img class='map' alt='\" + text +\n\t\t\t\t\t\t\"' src='http://maps.google.com/maps/api/staticmap?\" +\n\t\t\t\t\t\t\"zoom=11&size=350x350&maptype=terrain&sensor=false&center=\" +\n\t\t\t\t\t\ttext + \"'>\";\n\t\t\t\t}\n\t\t\t\tif ( element.is( \"[title]\" ) ) {\n\t\t\t\t\treturn element.attr( \"title\" );\n\t\t\t\t}\n\t\t\t\tif ( element.is( \"img\" ) ) {\n\t\t\t\t\treturn element.attr( \"alt\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"ui-widget photo\">\n\t<div class=\"ui-widget-header ui-corner-all\">\n\t\t<h2>St. Stephen's Cathedral</h2>\n\t\t<h3><a href=\"http://maps.google.com/maps?q=vienna,+austria&amp;z=11\" data-geo>Vienna, Austria</a></h3>\n\t</div>\n\t<a href=\"http://en.wikipedia.org/wiki/File:Wien_Stefansdom_DSC02656.JPG\">\n\t\t<img src=\"images/st-stephens.jpg\" alt=\"St. Stephen's Cathedral\" class=\"ui-corner-all\">\n\t</a>\n</div>\n\n<div class=\"ui-widget photo\">\n\t<div class=\"ui-widget-header ui-corner-all\">\n\t\t<h2>Tower Bridge</h2>\n\t\t<h3><a href=\"http://maps.google.com/maps?q=london,+england&amp;z=11\" data-geo>London, England</a></h3>\n\t</div>\n\t<a href=\"http://en.wikipedia.org/wiki/File:Tower_bridge_London_Twilight_-_November_2006.jpg\">\n\t\t<img src=\"images/tower-bridge.jpg\" alt=\"Tower Bridge\" class=\"ui-corner-all\">\n\t</a>\n</div>\n\n<p>All images are part of <a href=\"http://commons.wikimedia.org/wiki/Main_Page\">Wikimedia Commons</a>\nand are licensed under <a href=\"http://creativecommons.org/licenses/by-sa/3.0/deed.en\" title=\"Creative Commons Attribution-ShareAlike 3.0\">CC BY-SA 3.0</a> by the copyright holder.</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Shows how to combine different event delegated tooltips into a single instance, by customizing the items and content options.</p>\n<p>We realize you may want to interact with the map tooltips. This is a planned feature for a future version.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/custom-style.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.tooltip.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \".demo\" ).tooltip({\n\t\t\tposition: {\n\t\t\t\tmy: \"center bottom-20\",\n\t\t\t\tat: \"center top\",\n\t\t\t\tusing: function( position, feedback ) {\n\t\t\t\t\t$( this ).css( position );\n\t\t\t\t\t$( \"<div>\" )\n\t\t\t\t\t\t.addClass( \"arrow\" )\n\t\t\t\t\t\t.addClass( feedback.vertical )\n\t\t\t\t\t\t.addClass( feedback.horizontal )\n\t\t\t\t\t\t.appendTo( this );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n\t<style>\n\t.ui-tooltip, .arrow:after {\n\t\tbackground: black;\n\t\tborder: 2px solid white;\n\t}\n\t.ui-tooltip {\n\t\tpadding: 10px 20px;\n\t\tcolor: white;\n\t\tborder-radius: 20px;\n\t\tfont: bold 14px \"Helvetica Neue\", Sans-Serif;\n\t\ttext-transform: uppercase;\n\t\tbox-shadow: 0 0 7px black;\n\t}\n\t.arrow {\n\t\twidth: 70px;\n\t\theight: 16px;\n\t\toverflow: hidden;\n\t\tposition: absolute;\n\t\tleft: 50%;\n\t\tmargin-left: -35px;\n\t\tbottom: -16px;\n\t}\n\t.arrow.top {\n\t\ttop: -16px;\n\t\tbottom: auto;\n\t}\n\t.arrow.left {\n\t\tleft: 20%;\n\t}\n\t.arrow:after {\n\t\tcontent: \"\";\n\t\tposition: absolute;\n\t\tleft: 20px;\n\t\ttop: -20px;\n\t\twidth: 25px;\n\t\theight: 25px;\n\t\tbox-shadow: 6px 5px 9px -9px black;\n\t\t-webkit-transform: rotate(45deg);\n\t\t-moz-transform: rotate(45deg);\n\t\t-ms-transform: rotate(45deg);\n\t\t-o-transform: rotate(45deg);\n\t\ttranform: rotate(45deg);\n\t}\n\t.arrow.top:after {\n\t\tbottom: -20px;\n\t\ttop: auto;\n\t}\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p><a href=\"#\" title=\"That's what this widget is\">Tooltips</a> can be attached to any element. When you hover\nthe element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip.</p>\n<p>But as it's not a native tooltip, it can be styled. Any themes built with\n<a href=\"http://themeroller.com\" title=\"ThemeRoller: jQuery UI's theme builder application\">ThemeRoller</a>\nwill also style tooltips accordingly.</p>\n<p>Tooltips are also useful for form elements, to show some additional information in the context of each field.</p>\n<p><label for=\"age\">Your age:</label><input id=\"age\" title=\"We ask for your age only for statistical purposes.\"></p>\n<p>Hover the field to see the tooltip.</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Hover the links above or use the tab key to cycle the focus on each element.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/default.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<script>\n\t$(function() {\n\t\t$( \".demo\" ).tooltip();\n\t});\n\t</script>\n\t<style>\n\tlabel {\n\t\tdisplay: inline-block;\n\t\twidth: 5em;\n\t}\n\t</style>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p><a href=\"#\" title=\"That's what this widget is\">Tooltips</a> can be attached to any element. When you hover\nthe element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip.</p>\n<p>But as it's not a native tooltip, it can be styled. Any themes built with\n<a href=\"http://themeroller.com\" title=\"ThemeRoller: jQuery UI's theme builder application\">ThemeRoller</a>\nwill also style tooltips accordingly.</p>\n<p>Tooltips are also useful for form elements, to show some additional information in the context of each field.</p>\n<p><label for=\"age\">Your age:</label><input id=\"age\" title=\"We ask for your age only for statistical purposes.\"></p>\n<p>Hover the field to see the tooltip.</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Hover the links above or use the tab key to cycle the focus on each element.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/forms.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Default demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\tlabel {\n\t\tdisplay: inline-block; width: 5em;\n\t}\n\tfieldset div {\n\t\tmargin-bottom: 2em;\n\t}\n\tfieldset .help {\n\t\tdisplay: inline-block;\n\t}\n\t.ui-tooltip {\n\t\twidth: 210px;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tvar tooltips = $( \"[title]\" ).tooltip();\n\t\t$( \"<button>\" )\n\t\t\t.text( \"Show help\" )\n\t\t\t.button()\n\t\t\t.click(function() {\n\t\t\t\ttooltips.tooltip( \"open\" );\n\t\t\t})\n\t\t\t.insertAfter( \"form\" );\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<form>\n\t<fieldset>\n\t\t<div>\n\t\t\t<label for=\"firstname\">Firstname</label>\n\t\t\t<input id=\"firstname\" name=\"firstname\" title=\"Please provide your firstname.\">\n\t\t</div>\n\t\t<div>\n\t\t\t<label for=\"lastname\">Lastname</label>\n\t\t\t<input id=\"lastname\" name=\"lastname\" title=\"Please provide also your lastname.\">\n\t\t</div>\n\t\t<div>\n\t\t\t<label for=\"address\">Address</label>\n\t\t\t<input id=\"address\" name=\"address\" title=\"Your home or work address.\">\n\t\t</div>\n\t</fieldset>\n</form>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Use the button below to display the help texts, or just focus or mouseover the indivdual inputs.</p>\n<p>A fixed width is defined in CSS to make the tooltips look consistent when displayed all at once.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip Demos</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t\t<li><a href=\"custom-style.html\">Custom style with arrow</a></li>\n\t\t<li><a href=\"forms.html\">Forms with tooltips</a></li>\n\t\t<li><a href=\"tracking.html\">Track the mouse</a></li>\n\t\t<li><a href=\"custom-animation.html\">Custom animation</a></li>\n\t\t<li><a href=\"custom-content.html\">Custom content</a></li>\n\t\t<li><a href=\"video-player.html\">Video Player</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/tracking.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Track the mouse</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\tlabel {\n\t\tdisplay: inline-block;\n\t\twidth: 5em;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \".demo\" ).tooltip({\n\t\t\tposition: {\n\t\t\t\tmy: \"left+25 center\",\n\t\t\t\tat: \"center\"\n\t\t\t},\n\t\t\topen: function( event ) {\n\t\t\t\tvar tooltip = $( \".ui-tooltip\" ),\n\t\t\t\t\tpositionOption = $( this ).tooltip( \"option\", \"position\" );\n\t\t\t\tfunction position( event ) {\n\t\t\t\t\tpositionOption.of = event;\n\t\t\t\t\ttooltip.position( positionOption );\n\t\t\t\t}\n\t\t\t\t$( document ).bind( \"mousemove.tooltip-position\", position );\n\t\t\t\t// trigger once to override element-relative positioning\n\t\t\t\tposition( event );\n\t\t\t},\n\t\t\tclose: function() {\n\t\t\t\t$( document ).unbind( \"mousemove.tooltip-position\" );\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<p><a href=\"#\" title=\"That's what this widget is\">Tooltips</a> can be attached to any element. When you hover\nthe element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip.</p>\n<p>But as it's not a native tooltip, it can be styled. Any themes built with\n<a href=\"http://themeroller.com\" title=\"ThemeRoller: jQuery UI's theme builder application\">ThemeRoller</a>\nwill also style tooltips accordingly.</p>\n<p>Tooltips are also useful for form elements, to show some additional information in the context of each field.</p>\n<p><label for=\"age\">Your age:</label><input id=\"age\" title=\"We ask for your age only for statistical purposes.\"></p>\n<p>Hover the field to see the tooltip.</p>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>Here the tooltips are positioned relative to the mouse, and follow the mouse while it moves above the element.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/tooltip/video-player.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip - Video Player demo</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.tooltip.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../ui/jquery.effects.blind.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.player {\n\t\twidth: 500px;\n\t\theight: 300px;\n\t\tborder: 2px groove gray;\n\t\tbackground: rgb(200, 200, 200);\n\t\ttext-align: center;\n\t\tline-height: 300px;\n\t}\n\t/* TODO load from jquery.ui.popup.css */\n\t.ui-popup {\n\t\tposition: absolute;\n\t\tz-index: 5000;\n\t}\n\t.ui-tooltip {\n\t\tborder: 1px solid white;\n\t\tbackground: rgba(20, 20, 20, 1);\n\t\tcolor: white;\n\t}\n\t.set {\n\t\tdisplay: inline-block;\n\t}\n\t.notification {\n\t\tposition: absolute;\n\t\tdisplay: inline-block;\n\t\tfont-size: 2em;\n\t\tpadding: .5em;\n\t\tbox-shadow: 2px 2px 5px -2px rgba(0,0,0,0.5);\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\tfunction notify( input ) {\n\t\t\tvar msg = \"Selected \" + $.trim( input.data( \"tooltip-title\" ) || input.text() );\n\t\t\t$( \"<div>\" )\n\t\t\t\t.appendTo( document.body )\n\t\t\t\t.text( msg )\n\t\t\t\t.addClass( \"notification ui-state-default ui-corner-bottom\" )\n\t\t\t\t.position({\n\t\t\t\t\tmy: \"center top\",\n\t\t\t\t\tat: \"center top\",\n\t\t\t\t\tof: window\n\t\t\t\t})\n\t\t\t\t.show({\n\t\t\t\t\teffect: \"blind\"\n\t\t\t\t})\n\t\t\t\t.delay( 1000 )\n\t\t\t\t.hide({\n\t\t\t\t\teffect: \"blind\",\n\t\t\t\t\tduration: \"slow\"\n\t\t\t\t}, function() {\n\t\t\t\t\t$( this ).remove();\n\t\t\t\t});\n\t\t}\n\n\t\t$( \"button\" ).each(function() {\n\t\t\tvar button = $( this ).button({\n\t\t\t\ticons: {\n\t\t\t\t\tprimary: $( this ).data( \"icon\" )\n\t\t\t\t},\n\t\t\t\ttext: !!$( this ).attr( \"title\" )\n\t\t\t});\n\t\t\tbutton.click(function() {\n\t\t\t\tnotify( button );\n\t\t\t});\n\t\t});\n\t\t$( \".set\" ).buttonset({\n\t\t\titems: \"button\"\n\t\t});\n\n\t\t$( \".demo\" ).tooltip({\n\t\t\tposition: {\n\t\t\t\tmy: \"center top\",\n\t\t\t\tat: \"center bottom+5\",\n\t\t\t},\n\t\t\tshow: {\n\t\t\t\tduration: \"fast\"\n\t\t\t},\n\t\t\thide: {\n\t\t\t\teffect: \"hide\"\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div class=\"player\">Here Be Video (HTML5?)</div>\n<div class=\"tools\">\n\t<span class=\"set\">\n\t\t<button data-icon=\"ui-icon-circle-arrow-n\" title=\"I like this\">Like</button>\n\t\t<button data-icon=\"ui-icon-circle-arrow-s\">I dislike this</button>\n\t</span>\n\t<div class=\"set\">\n\t\t<button data-icon=\"ui-icon-circle-plus\" title=\"Add to Watch Later\">Add to</button>\n\t\t<button class=\"menu\" data-icon=\"ui-icon-triangle-1-s\">Add to favorites or playlist</button>\n\t</div>\n\t<button title=\"Share this video\">Share</button>\n\t<button data-icon=\"ui-icon-alert\">Flag as inappropiate</button>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>A fake video player with like/share/stats button, each with a custom-styled tooltip.</p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/widget/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Widget - Default functionality</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../ui/jquery.ui.button.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n\t<style>\n\t.custom-colorize {\n\t\tfont-size: 20px;\n\t\tposition: relative;\n\t\twidth: 75px;\n\t\theight: 75px;\n\t}\n\t.custom-colorize-changer {\n\t\tfont-size: 10px;\n\t\tposition: absolute;\n\t\tright: 0;\n\t\tbottom: 0;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// the widget definition, where \"custom\" is the namespace,\n\t\t// \"colorize\" the widget name\n\t\t$.widget( \"custom.colorize\", {\n\t\t\t// default options\n\t\t\toptions: {\n\t\t\t\tred: 255,\n\t\t\t\tgreen: 0,\n\t\t\t\tblue: 0,\n\n\t\t\t\t// callbacks\n\t\t\t\tchange: null,\n\t\t\t\trandom: null\n\t\t\t},\n\n\t\t\t// the constructor\n\t\t\t_create: function() {\n\t\t\t\tthis.element\n\t\t\t\t\t// add a class for theming\n\t\t\t\t\t.addClass( \"custom-colorize\" )\n\t\t\t\t\t// prevent double click to select text\n\t\t\t\t\t.disableSelection();\n\n\t\t\t\tthis.changer = $( \"<button>\", {\n\t\t\t\t\ttext: \"change\",\n\t\t\t\t\t\"class\": \"custom-colorize-changer\"\n\t\t\t\t})\n\t\t\t\t.appendTo( this.element )\n\t\t\t\t.button();\n\n\t\t\t\t// bind click events on the changer button to the random method\n\t\t\t\tthis._bind( this.changer, {\n\t\t\t\t\t// _bind won't call random when widget is disabled\n\t\t\t\t\tclick: \"random\"\n\t\t\t\t});\n\t\t\t\tthis._refresh();\n\t\t\t},\n\n\t\t\t// called when created, and later when changing options\n\t\t\t_refresh: function() {\n\t\t\t\tthis.element.css( \"background-color\", \"rgb(\" +\n\t\t\t\t\tthis.options.red +\",\" +\n\t\t\t\t\tthis.options.green + \",\" +\n\t\t\t\t\tthis.options.blue + \")\"\n\t\t\t\t);\n\n\t\t\t\t// trigger a callback/event\n\t\t\t\tthis._trigger( \"change\" );\n\t\t\t},\n\n\t\t\t// a public method to change the color to a random value\n\t\t\t// can be called directly via .colorize( \"random\" )\n\t\t\trandom: function( event ) {\n\t\t\t\tvar colors = {\n\t\t\t\t\tred: Math.floor( Math.random() * 256 ),\n\t\t\t\t\tgreen: Math.floor( Math.random() * 256 ),\n\t\t\t\t\tblue: Math.floor( Math.random() * 256 )\n\t\t\t\t};\n\n\t\t\t\t// trigger an event, check if it's canceled\n\t\t\t\tif ( this._trigger( \"random\", event, colors ) !== false ) {\n\t\t\t\t\tthis.option( colors );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// events bound via _bind are removed automatically\n\t\t\t// revert other modifications here\n\t\t\t_destroy: function() {\n\t\t\t\t// remove generated elements\n\t\t\t\tthis.changer.remove();\n\n\t\t\t\tthis.element\n\t\t\t\t\t.removeClass( \"custom-colorize\" )\n\t\t\t\t\t.enableSelection()\n\t\t\t\t\t.css( \"background-color\", \"transparent\" );\n\t\t\t},\n\n\t\t\t// _setOptions is called with a hash of all options that are changing\n\t\t\t// always refresh when changing options\n\t\t\t_setOptions: function() {\n\t\t\t\t// _super and _superApply handle keeping the right this-context\n\t\t\t\tthis._superApply( arguments );\n\t\t\t\tthis._refresh();\n\t\t\t},\n\n\t\t\t// _setOption is called for each individual option that is changing\n\t\t\t_setOption: function( key, value ) {\n\t\t\t\t// prevent invalid color values\n\t\t\t\tif ( /red|green|blue/.test(key) && (value < 0 || value > 255) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._super( key, value );\n\t\t\t}\n\t\t});\n\n\t\t// initialize with default options\n\t\t$( \"#my-widget1\" ).colorize();\n\n\t\t// initialize with two customized options\n\t\t$( \"#my-widget2\" ).colorize({\n\t\t\tred: 60,\n\t\t\tblue: 60\n\t\t});\n\n\t\t// initialize with custom green value\n\t\t// and a random callback to allow only colors with enough green\n\t\t$( \"#my-widget3\" ).colorize( {\n\t\t\tgreen: 128,\n\t\t\trandom: function( event, ui ) {\n\t\t\t\treturn ui.green > 128;\n\t\t\t}\n\t\t});\n\n\t\t// click to toggle enabled/disabled\n\t\t$( \"#disable\" ).click(function() {\n\t\t\t// use the custom selector created for each widget to find all instances\n\t\t\t// all instances are toggled together, so we can check the state from the first\n\t\t\tif ( $( \":custom-colorize\" ).colorize( \"option\", \"disabled\" ) ) {\n\t\t\t\t$( \":custom-colorize\" ).colorize( \"enable\" );\n\t\t\t} else {\n\t\t\t\t$( \":custom-colorize\" ).colorize( \"disable\" );\n\t\t\t}\n\t\t});\n\n\t\t// click to set options after initalization\n\t\t$( \"#black\" ).click( function() {\n\t\t\t$( \":custom-colorize\" ).colorize( \"option\", {\n\t\t\t\tred: 0,\n\t\t\t\tgreen: 0,\n\t\t\t\tblue: 0\n\t\t\t});\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\n<div>\n\t<div id=\"my-widget1\">color me</div>\n\t<div id=\"my-widget2\">color me</div>\n\t<div id=\"my-widget3\">color me</div>\n\t<button id=\"disable\">Toggle disabled option</button>\n\t<button id=\"black\">Go black</button>\n</div>\n\n</div><!-- End demo -->\n\n\n\n<div class=\"demo-description\">\n<p>This demo shows a simple custom widget built using the widget factory (jquery.ui.widget.js).</p>\n<p>The three boxes are initialized in different ways. Clicking them changes their background color. View source to see how it works, its heavily commented</p>\n<p><a href=\"http://wiki.jqueryui.com/w/page/12138135/Widget-factory\">For more details on the widget factory, visit the jQuery UI planning wiki.</a></p>\n</div><!-- End demo-description -->\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/demos/widget/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Widget Demo</title>\n\t<link rel=\"stylesheet\" href=\"../demos.css\">\n</head>\n<body>\n\n<div class=\"demos-nav\">\n\t<h4>Examples</h4>\n\t<ul>\n\t\t<li class=\"demo-config-on\"><a href=\"default.html\">Default functionality</a></li>\n\t</ul>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/globalize.culture.de-DE.js",
    "content": "/*\n * Globalize Culture de-DE\n *\n * http://github.com/jquery/globalize\n *\n * Copyright Software Freedom Conservancy, Inc.\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * This file was generated by the Globalize Culture Generator\n * Translation: bugs found in this file need to be fixed in the generator\n */\n\n(function( window, undefined ) {\n\nvar Globalize;\n\nif ( typeof require !== \"undefined\"\n\t&& typeof exports !== \"undefined\"\n\t&& typeof module !== \"undefined\" ) {\n\t// Assume CommonJS\n\tGlobalize = require( \"globalize\" );\n} else {\n\t// Global variable\n\tGlobalize = window.Globalize;\n}\n\nGlobalize.addCultureInfo( \"de-DE\", \"default\", {\n\tname: \"de-DE\",\n\tenglishName: \"German (Germany)\",\n\tnativeName: \"Deutsch (Deutschland)\",\n\tlanguage: \"de\",\n\tnumberFormat: {\n\t\t\",\": \".\",\n\t\t\".\": \",\",\n\t\tNaN: \"n. def.\",\n\t\tnegativeInfinity: \"-unendlich\",\n\t\tpositiveInfinity: \"+unendlich\",\n\t\tpercent: {\n\t\t\tpattern: [\"-n%\",\"n%\"],\n\t\t\t\",\": \".\",\n\t\t\t\".\": \",\"\n\t\t},\n\t\tcurrency: {\n\t\t\tpattern: [\"-n $\",\"n $\"],\n\t\t\t\",\": \".\",\n\t\t\t\".\": \",\",\n\t\t\tsymbol: \"€\"\n\t\t}\n\t},\n\tcalendars: {\n\t\tstandard: {\n\t\t\t\"/\": \".\",\n\t\t\tfirstDay: 1,\n\t\t\tdays: {\n\t\t\t\tnames: [\"Sonntag\",\"Montag\",\"Dienstag\",\"Mittwoch\",\"Donnerstag\",\"Freitag\",\"Samstag\"],\n\t\t\t\tnamesAbbr: [\"So\",\"Mo\",\"Di\",\"Mi\",\"Do\",\"Fr\",\"Sa\"],\n\t\t\t\tnamesShort: [\"So\",\"Mo\",\"Di\",\"Mi\",\"Do\",\"Fr\",\"Sa\"]\n\t\t\t},\n\t\t\tmonths: {\n\t\t\t\tnames: [\"Januar\",\"Februar\",\"März\",\"April\",\"Mai\",\"Juni\",\"Juli\",\"August\",\"September\",\"Oktober\",\"November\",\"Dezember\",\"\"],\n\t\t\t\tnamesAbbr: [\"Jan\",\"Feb\",\"Mrz\",\"Apr\",\"Mai\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Okt\",\"Nov\",\"Dez\",\"\"]\n\t\t\t},\n\t\t\tAM: null,\n\t\t\tPM: null,\n\t\t\teras: [{\"name\":\"n. Chr.\",\"start\":null,\"offset\":0}],\n\t\t\tpatterns: {\n\t\t\t\td: \"dd.MM.yyyy\",\n\t\t\t\tD: \"dddd, d. MMMM yyyy\",\n\t\t\t\tt: \"HH:mm\",\n\t\t\t\tT: \"HH:mm:ss\",\n\t\t\t\tf: \"dddd, d. MMMM yyyy HH:mm\",\n\t\t\t\tF: \"dddd, d. MMMM yyyy HH:mm:ss\",\n\t\t\t\tM: \"dd MMMM\",\n\t\t\t\tY: \"MMMM yyyy\"\n\t\t\t}\n\t\t}\n\t}\n});\n\n}( this ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/globalize.culture.ja-JP.js",
    "content": "/*\n * Globalize Culture ja-JP\n *\n * http://github.com/jquery/globalize\n *\n * Copyright Software Freedom Conservancy, Inc.\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * This file was generated by the Globalize Culture Generator\n * Translation: bugs found in this file need to be fixed in the generator\n */\n\n(function( window, undefined ) {\n\nvar Globalize;\n\nif ( typeof require !== \"undefined\"\n\t&& typeof exports !== \"undefined\"\n\t&& typeof module !== \"undefined\" ) {\n\t// Assume CommonJS\n\tGlobalize = require( \"globalize\" );\n} else {\n\t// Global variable\n\tGlobalize = window.Globalize;\n}\n\nGlobalize.addCultureInfo( \"ja-JP\", \"default\", {\n\tname: \"ja-JP\",\n\tenglishName: \"Japanese (Japan)\",\n\tnativeName: \"日本語 (日本)\",\n\tlanguage: \"ja\",\n\tnumberFormat: {\n\t\tNaN: \"NaN (非数値)\",\n\t\tnegativeInfinity: \"-∞\",\n\t\tpositiveInfinity: \"+∞\",\n\t\tpercent: {\n\t\t\tpattern: [\"-n%\",\"n%\"]\n\t\t},\n\t\tcurrency: {\n\t\t\tpattern: [\"-$n\",\"$n\"],\n\t\t\tdecimals: 0,\n\t\t\tsymbol: \"¥\"\n\t\t}\n\t},\n\tcalendars: {\n\t\tstandard: {\n\t\t\tdays: {\n\t\t\t\tnames: [\"日曜日\",\"月曜日\",\"火曜日\",\"水曜日\",\"木曜日\",\"金曜日\",\"土曜日\"],\n\t\t\t\tnamesAbbr: [\"日\",\"月\",\"火\",\"水\",\"木\",\"金\",\"土\"],\n\t\t\t\tnamesShort: [\"日\",\"月\",\"火\",\"水\",\"木\",\"金\",\"土\"]\n\t\t\t},\n\t\t\tmonths: {\n\t\t\t\tnames: [\"1月\",\"2月\",\"3月\",\"4月\",\"5月\",\"6月\",\"7月\",\"8月\",\"9月\",\"10月\",\"11月\",\"12月\",\"\"],\n\t\t\t\tnamesAbbr: [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"\"]\n\t\t\t},\n\t\t\tAM: [\"午前\",\"午前\",\"午前\"],\n\t\t\tPM: [\"午後\",\"午後\",\"午後\"],\n\t\t\teras: [{\"name\":\"西暦\",\"start\":null,\"offset\":0}],\n\t\t\tpatterns: {\n\t\t\t\td: \"yyyy/MM/dd\",\n\t\t\t\tD: \"yyyy'年'M'月'd'日'\",\n\t\t\t\tt: \"H:mm\",\n\t\t\t\tT: \"H:mm:ss\",\n\t\t\t\tf: \"yyyy'年'M'月'd'日' H:mm\",\n\t\t\t\tF: \"yyyy'年'M'月'd'日' H:mm:ss\",\n\t\t\t\tM: \"M'月'd'日'\",\n\t\t\t\tY: \"yyyy'年'M'月'\"\n\t\t\t}\n\t\t},\n\t\tJapanese: {\n\t\t\tname: \"Japanese\",\n\t\t\tdays: {\n\t\t\t\tnames: [\"日曜日\",\"月曜日\",\"火曜日\",\"水曜日\",\"木曜日\",\"金曜日\",\"土曜日\"],\n\t\t\t\tnamesAbbr: [\"日\",\"月\",\"火\",\"水\",\"木\",\"金\",\"土\"],\n\t\t\t\tnamesShort: [\"日\",\"月\",\"火\",\"水\",\"木\",\"金\",\"土\"]\n\t\t\t},\n\t\t\tmonths: {\n\t\t\t\tnames: [\"1月\",\"2月\",\"3月\",\"4月\",\"5月\",\"6月\",\"7月\",\"8月\",\"9月\",\"10月\",\"11月\",\"12月\",\"\"],\n\t\t\t\tnamesAbbr: [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"\"]\n\t\t\t},\n\t\t\tAM: [\"午前\",\"午前\",\"午前\"],\n\t\t\tPM: [\"午後\",\"午後\",\"午後\"],\n\t\t\teras: [{\"name\":\"平成\",\"start\":null,\"offset\":1867},{\"name\":\"昭和\",\"start\":-1812153600000,\"offset\":1911},{\"name\":\"大正\",\"start\":-1357603200000,\"offset\":1925},{\"name\":\"明治\",\"start\":60022080000,\"offset\":1988}],\n\t\t\ttwoDigitYearMax: 99,\n\t\t\tpatterns: {\n\t\t\t\td: \"gg y/M/d\",\n\t\t\t\tD: \"gg y'年'M'月'd'日'\",\n\t\t\t\tt: \"H:mm\",\n\t\t\t\tT: \"H:mm:ss\",\n\t\t\t\tf: \"gg y'年'M'月'd'日' H:mm\",\n\t\t\t\tF: \"gg y'年'M'月'd'日' H:mm:ss\",\n\t\t\t\tM: \"M'月'd'日'\",\n\t\t\t\tY: \"gg y'年'M'月'\"\n\t\t\t}\n\t\t}\n\t}\n});\n\n}( this ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/globalize.js",
    "content": "/*!\n * Globalize\n *\n * http://github.com/jquery/globalize\n *\n * Copyright Software Freedom Conservancy, Inc.\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n */\n\n(function( window, undefined ) {\n\nvar Globalize,\n\t// private variables\n\tregexHex,\n\tregexInfinity,\n\tregexParseFloat,\n\tregexTrim,\n\t// private JavaScript utility functions\n\tarrayIndexOf,\n\tendsWith,\n\textend,\n\tisArray,\n\tisFunction,\n\tisObject,\n\tstartsWith,\n\ttrim,\n\ttruncate,\n\tzeroPad,\n\t// private Globalization utility functions\n\tappendPreOrPostMatch,\n\texpandFormat,\n\tformatDate,\n\tformatNumber,\n\tgetTokenRegExp,\n\tgetEra,\n\tgetEraYear,\n\tparseExact,\n\tparseNegativePattern;\n\n// Global variable (Globalize) or CommonJS module (globalize)\nGlobalize = function( cultureSelector ) {\n\treturn new Globalize.prototype.init( cultureSelector );\n};\n\nif ( typeof require !== \"undefined\"\n\t&& typeof exports !== \"undefined\"\n\t&& typeof module !== \"undefined\" ) {\n\t// Assume CommonJS\n\tmodule.exports = Globalize;\n} else {\n\t// Export as global variable\n\twindow.Globalize = Globalize;\n}\n\nGlobalize.cultures = {};\n\nGlobalize.prototype = {\n\tconstructor: Globalize,\n\tinit: function( cultureSelector ) {\n\t\tthis.cultures = Globalize.cultures;\n\t\tthis.cultureSelector = cultureSelector;\n\n\t\treturn this;\n\t}\n};\nGlobalize.prototype.init.prototype = Globalize.prototype;\n\n// 1.\t When defining a culture, all fields are required except the ones stated as optional.\n// 2.\t Each culture should have a \".calendars\" object with at least one calendar named \"standard\"\n//\t\t which serves as the default calendar in use by that culture.\n// 3.\t Each culture should have a \".calendar\" object which is the current calendar being used,\n//\t\t it may be dynamically changed at any time to one of the calendars in \".calendars\".\nGlobalize.cultures[ \"default\" ] = {\n\t// A unique name for the culture in the form <language code>-<country/region code>\n\tname: \"en\",\n\t// the name of the culture in the english language\n\tenglishName: \"English\",\n\t// the name of the culture in its own language\n\tnativeName: \"English\",\n\t// whether the culture uses right-to-left text\n\tisRTL: false,\n\t// \"language\" is used for so-called \"specific\" cultures.\n\t// For example, the culture \"es-CL\" means \"Spanish, in Chili\".\n\t// It represents the Spanish-speaking culture as it is in Chili,\n\t// which might have different formatting rules or even translations\n\t// than Spanish in Spain. A \"neutral\" culture is one that is not\n\t// specific to a region. For example, the culture \"es\" is the generic\n\t// Spanish culture, which may be a more generalized version of the language\n\t// that may or may not be what a specific culture expects.\n\t// For a specific culture like \"es-CL\", the \"language\" field refers to the\n\t// neutral, generic culture information for the language it is using.\n\t// This is not always a simple matter of the string before the dash.\n\t// For example, the \"zh-Hans\" culture is netural (Simplified Chinese).\n\t// And the \"zh-SG\" culture is Simplified Chinese in Singapore, whose lanugage\n\t// field is \"zh-CHS\", not \"zh\".\n\t// This field should be used to navigate from a specific culture to it's\n\t// more general, neutral culture. If a culture is already as general as it\n\t// can get, the language may refer to itself.\n\tlanguage: \"en\",\n\t// numberFormat defines general number formatting rules, like the digits in\n\t// each grouping, the group separator, and how negative numbers are displayed.\n\tnumberFormat: {\n\t\t// [negativePattern]\n\t\t// Note, numberFormat.pattern has no \"positivePattern\" unlike percent and currency,\n\t\t// but is still defined as an array for consistency with them.\n\t\t//   negativePattern: one of \"(n)|-n|- n|n-|n -\"\n\t\tpattern: [ \"-n\" ],\n\t\t// number of decimal places normally shown\n\t\tdecimals: 2,\n\t\t// string that separates number groups, as in 1,000,000\n\t\t\",\": \",\",\n\t\t// string that separates a number from the fractional portion, as in 1.99\n\t\t\".\": \".\",\n\t\t// array of numbers indicating the size of each number group.\n\t\t// TODO: more detailed description and example\n\t\tgroupSizes: [ 3 ],\n\t\t// symbol used for positive numbers\n\t\t\"+\": \"+\",\n\t\t// symbol used for negative numbers\n\t\t\"-\": \"-\",\n\t\t// symbol used for NaN (Not-A-Number)\n\t\tNaN: \"NaN\",\n\t\t// symbol used for Negative Infinity\n\t\tnegativeInfinity: \"-Infinity\",\n\t\t// symbol used for Positive Infinity\n\t\tpositiveInfinity: \"Infinity\",\n\t\tpercent: {\n\t\t\t// [negativePattern, positivePattern]\n\t\t\t//   negativePattern: one of \"-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %\"\n\t\t\t//   positivePattern: one of \"n %|n%|%n|% n\"\n\t\t\tpattern: [ \"-n %\", \"n %\" ],\n\t\t\t// number of decimal places normally shown\n\t\t\tdecimals: 2,\n\t\t\t// array of numbers indicating the size of each number group.\n\t\t\t// TODO: more detailed description and example\n\t\t\tgroupSizes: [ 3 ],\n\t\t\t// string that separates number groups, as in 1,000,000\n\t\t\t\",\": \",\",\n\t\t\t// string that separates a number from the fractional portion, as in 1.99\n\t\t\t\".\": \".\",\n\t\t\t// symbol used to represent a percentage\n\t\t\tsymbol: \"%\"\n\t\t},\n\t\tcurrency: {\n\t\t\t// [negativePattern, positivePattern]\n\t\t\t//   negativePattern: one of \"($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)\"\n\t\t\t//   positivePattern: one of \"$n|n$|$ n|n $\"\n\t\t\tpattern: [ \"($n)\", \"$n\" ],\n\t\t\t// number of decimal places normally shown\n\t\t\tdecimals: 2,\n\t\t\t// array of numbers indicating the size of each number group.\n\t\t\t// TODO: more detailed description and example\n\t\t\tgroupSizes: [ 3 ],\n\t\t\t// string that separates number groups, as in 1,000,000\n\t\t\t\",\": \",\",\n\t\t\t// string that separates a number from the fractional portion, as in 1.99\n\t\t\t\".\": \".\",\n\t\t\t// symbol used to represent currency\n\t\t\tsymbol: \"$\"\n\t\t}\n\t},\n\t// calendars defines all the possible calendars used by this culture.\n\t// There should be at least one defined with name \"standard\", and is the default\n\t// calendar used by the culture.\n\t// A calendar contains information about how dates are formatted, information about\n\t// the calendar's eras, a standard set of the date formats,\n\t// translations for day and month names, and if the calendar is not based on the Gregorian\n\t// calendar, conversion functions to and from the Gregorian calendar.\n\tcalendars: {\n\t\tstandard: {\n\t\t\t// name that identifies the type of calendar this is\n\t\t\tname: \"Gregorian_USEnglish\",\n\t\t\t// separator of parts of a date (e.g. \"/\" in 11/05/1955)\n\t\t\t\"/\": \"/\",\n\t\t\t// separator of parts of a time (e.g. \":\" in 05:44 PM)\n\t\t\t\":\": \":\",\n\t\t\t// the first day of the week (0 = Sunday, 1 = Monday, etc)\n\t\t\tfirstDay: 0,\n\t\t\tdays: {\n\t\t\t\t// full day names\n\t\t\t\tnames: [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ],\n\t\t\t\t// abbreviated day names\n\t\t\t\tnamesAbbr: [ \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\" ],\n\t\t\t\t// shortest day names\n\t\t\t\tnamesShort: [ \"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\" ]\n\t\t\t},\n\t\t\tmonths: {\n\t\t\t\t// full month names (13 months for lunar calendards -- 13th month should be \"\" if not lunar)\n\t\t\t\tnames: [ \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\", \"\" ],\n\t\t\t\t// abbreviated month names\n\t\t\t\tnamesAbbr: [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\", \"\" ]\n\t\t\t},\n\t\t\t// AM and PM designators in one of these forms:\n\t\t\t// The usual view, and the upper and lower case versions\n\t\t\t//   [ standard, lowercase, uppercase ]\n\t\t\t// The culture does not use AM or PM (likely all standard date formats use 24 hour time)\n\t\t\t//   null\n\t\t\tAM: [ \"AM\", \"am\", \"AM\" ],\n\t\t\tPM: [ \"PM\", \"pm\", \"PM\" ],\n\t\t\teras: [\n\t\t\t\t// eras in reverse chronological order.\n\t\t\t\t// name: the name of the era in this culture (e.g. A.D., C.E.)\n\t\t\t\t// start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.\n\t\t\t\t// offset: offset in years from gregorian calendar\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"A.D.\",\n\t\t\t\t\t\"start\": null,\n\t\t\t\t\t\"offset\": 0\n\t\t\t\t}\n\t\t\t],\n\t\t\t// when a two digit year is given, it will never be parsed as a four digit\n\t\t\t// year greater than this year (in the appropriate era for the culture)\n\t\t\t// Set it as a full year (e.g. 2029) or use an offset format starting from\n\t\t\t// the current year: \"+19\" would correspond to 2029 if the current year 2010.\n\t\t\ttwoDigitYearMax: 2029,\n\t\t\t// set of predefined date and time patterns used by the culture\n\t\t\t// these represent the format someone in this culture would expect\n\t\t\t// to see given the portions of the date that are shown.\n\t\t\tpatterns: {\n\t\t\t\t// short date pattern\n\t\t\t\td: \"M/d/yyyy\",\n\t\t\t\t// long date pattern\n\t\t\t\tD: \"dddd, MMMM dd, yyyy\",\n\t\t\t\t// short time pattern\n\t\t\t\tt: \"h:mm tt\",\n\t\t\t\t// long time pattern\n\t\t\t\tT: \"h:mm:ss tt\",\n\t\t\t\t// long date, short time pattern\n\t\t\t\tf: \"dddd, MMMM dd, yyyy h:mm tt\",\n\t\t\t\t// long date, long time pattern\n\t\t\t\tF: \"dddd, MMMM dd, yyyy h:mm:ss tt\",\n\t\t\t\t// month/day pattern\n\t\t\t\tM: \"MMMM dd\",\n\t\t\t\t// month/year pattern\n\t\t\t\tY: \"yyyy MMMM\",\n\t\t\t\t// S is a sortable format that does not vary by culture\n\t\t\t\tS: \"yyyy\\u0027-\\u0027MM\\u0027-\\u0027dd\\u0027T\\u0027HH\\u0027:\\u0027mm\\u0027:\\u0027ss\"\n\t\t\t}\n\t\t\t// optional fields for each calendar:\n\t\t\t/*\n\t\t\tmonthsGenitive:\n\t\t\t\tSame as months but used when the day preceeds the month.\n\t\t\t\tOmit if the culture has no genitive distinction in month names.\n\t\t\t\tFor an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx\n\t\t\tconvert:\n\t\t\t\tAllows for the support of non-gregorian based calendars. This convert object is used to\n\t\t\t\tto convert a date to and from a gregorian calendar date to handle parsing and formatting.\n\t\t\t\tThe two functions:\n\t\t\t\t\tfromGregorian( date )\n\t\t\t\t\t\tGiven the date as a parameter, return an array with parts [ year, month, day ]\n\t\t\t\t\t\tcorresponding to the non-gregorian based year, month, and day for the calendar.\n\t\t\t\t\ttoGregorian( year, month, day )\n\t\t\t\t\t\tGiven the non-gregorian year, month, and day, return a new Date() object\n\t\t\t\t\t\tset to the corresponding date in the gregorian calendar.\n\t\t\t*/\n\t\t}\n\t},\n\t// For localized strings\n\tmessages: {}\n};\n\nGlobalize.cultures[ \"default\" ].calendar = Globalize.cultures[ \"default\" ].calendars.standard;\n\nGlobalize.cultures[ \"en\" ] = Globalize.cultures[ \"default\" ];\n\nGlobalize.cultureSelector = \"en\";\n\n//\n// private variables\n//\n\nregexHex = /^0x[a-f0-9]+$/i;\nregexInfinity = /^[+-]?infinity$/i;\nregexParseFloat = /^[+-]?\\d*\\.?\\d*(e[+-]?\\d+)?$/;\nregexTrim = /^\\s+|\\s+$/g;\n\n//\n// private JavaScript utility functions\n//\n\narrayIndexOf = function( array, item ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( item );\n\t}\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[i] === item ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n};\n\nendsWith = function( value, pattern ) {\n\treturn value.substr( value.length - pattern.length ) === pattern;\n};\n\nextend = function( deep ) {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && isObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\nisArray = Array.isArray || function( obj ) {\n\treturn Object.prototype.toString.call( obj ) === \"[object Array]\";\n};\n\nisFunction = function( obj ) {\n\treturn Object.prototype.toString.call( obj ) === \"[object Function]\"\n}\n\nisObject = function( obj ) {\n\treturn Object.prototype.toString.call( obj ) === \"[object Object]\";\n};\n\nstartsWith = function( value, pattern ) {\n\treturn value.indexOf( pattern ) === 0;\n};\n\ntrim = function( value ) {\n\treturn ( value + \"\" ).replace( regexTrim, \"\" );\n};\n\ntruncate = function( value ) {\n\treturn value | 0;\n};\n\nzeroPad = function( str, count, left ) {\n\tvar l;\n\tfor ( l = str.length; l < count; l += 1 ) {\n\t\tstr = ( left ? (\"0\" + str) : (str + \"0\") );\n\t}\n\treturn str;\n};\n\n//\n// private Globalization utility functions\n//\n\nappendPreOrPostMatch = function( preMatch, strings ) {\n\t// appends pre- and post- token match strings while removing escaped characters.\n\t// Returns a single quote count which is used to determine if the token occurs\n\t// in a string literal.\n\tvar quoteCount = 0,\n\t\tescaped = false;\n\tfor ( var i = 0, il = preMatch.length; i < il; i++ ) {\n\t\tvar c = preMatch.charAt( i );\n\t\tswitch ( c ) {\n\t\t\tcase \"\\'\":\n\t\t\t\tif ( escaped ) {\n\t\t\t\t\tstrings.push( \"\\'\" );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tquoteCount++;\n\t\t\t\t}\n\t\t\t\tescaped = false;\n\t\t\t\tbreak;\n\t\t\tcase \"\\\\\":\n\t\t\t\tif ( escaped ) {\n\t\t\t\t\tstrings.push( \"\\\\\" );\n\t\t\t\t}\n\t\t\t\tescaped = !escaped;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstrings.push( c );\n\t\t\t\tescaped = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn quoteCount;\n};\n\nexpandFormat = function( cal, format ) {\n\t// expands unspecified or single character date formats into the full pattern.\n\tformat = format || \"F\";\n\tvar pattern,\n\t\tpatterns = cal.patterns,\n\t\tlen = format.length;\n\tif ( len === 1 ) {\n\t\tpattern = patterns[ format ];\n\t\tif ( !pattern ) {\n\t\t\tthrow \"Invalid date format string \\'\" + format + \"\\'.\";\n\t\t}\n\t\tformat = pattern;\n\t}\n\telse if ( len === 2 && format.charAt(0) === \"%\" ) {\n\t\t// %X escape format -- intended as a custom format string that is only one character, not a built-in format.\n\t\tformat = format.charAt( 1 );\n\t}\n\treturn format;\n};\n\nformatDate = function( value, format, culture ) {\n\tvar cal = culture.calendar,\n\t\tconvert = cal.convert;\n\n\tif ( !format || !format.length || format === \"i\" ) {\n\t\tvar ret;\n\t\tif ( culture && culture.name.length ) {\n\t\t\tif ( convert ) {\n\t\t\t\t// non-gregorian calendar, so we cannot use built-in toLocaleString()\n\t\t\t\tret = formatDate( value, cal.patterns.F, culture );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvar eraDate = new Date( value.getTime() ),\n\t\t\t\t\tera = getEra( value, cal.eras );\n\t\t\t\teraDate.setFullYear( getEraYear(value, cal, era) );\n\t\t\t\tret = eraDate.toLocaleString();\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tret = value.toString();\n\t\t}\n\t\treturn ret;\n\t}\n\n\tvar eras = cal.eras,\n\t\tsortable = format === \"s\";\n\tformat = expandFormat( cal, format );\n\n\t// Start with an empty string\n\tret = [];\n\tvar hour,\n\t\tzeros = [ \"0\", \"00\", \"000\" ],\n\t\tfoundDay,\n\t\tcheckedDay,\n\t\tdayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,\n\t\tquoteCount = 0,\n\t\ttokenRegExp = getTokenRegExp(),\n\t\tconverted;\n\n\tfunction padZeros( num, c ) {\n\t\tvar r, s = num + \"\";\n\t\tif ( c > 1 && s.length < c ) {\n\t\t\tr = ( zeros[c - 2] + s);\n\t\t\treturn r.substr( r.length - c, c );\n\t\t}\n\t\telse {\n\t\t\tr = s;\n\t\t}\n\t\treturn r;\n\t}\n\n\tfunction hasDay() {\n\t\tif ( foundDay || checkedDay ) {\n\t\t\treturn foundDay;\n\t\t}\n\t\tfoundDay = dayPartRegExp.test( format );\n\t\tcheckedDay = true;\n\t\treturn foundDay;\n\t}\n\n\tfunction getPart( date, part ) {\n\t\tif ( converted ) {\n\t\t\treturn converted[ part ];\n\t\t}\n\t\tswitch ( part ) {\n\t\t\tcase 0: return date.getFullYear();\n\t\t\tcase 1: return date.getMonth();\n\t\t\tcase 2: return date.getDate();\n\t\t}\n\t}\n\n\tif ( !sortable && convert ) {\n\t\tconverted = convert.fromGregorian( value );\n\t}\n\n\tfor ( ; ; ) {\n\t\t// Save the current index\n\t\tvar index = tokenRegExp.lastIndex,\n\t\t\t// Look for the next pattern\n\t\t\tar = tokenRegExp.exec( format );\n\n\t\t// Append the text before the pattern (or the end of the string if not found)\n\t\tvar preMatch = format.slice( index, ar ? ar.index : format.length );\n\t\tquoteCount += appendPreOrPostMatch( preMatch, ret );\n\n\t\tif ( !ar ) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// do not replace any matches that occur inside a string literal.\n\t\tif ( quoteCount % 2 ) {\n\t\t\tret.push( ar[0] );\n\t\t\tcontinue;\n\t\t}\n\n\t\tvar current = ar[ 0 ],\n\t\t\tclength = current.length;\n\n\t\tswitch ( current ) {\n\t\t\tcase \"ddd\":\n\t\t\t\t//Day of the week, as a three-letter abbreviation\n\t\t\tcase \"dddd\":\n\t\t\t\t// Day of the week, using the full name\n\t\t\t\tvar names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;\n\t\t\t\tret.push( names[value.getDay()] );\n\t\t\t\tbreak;\n\t\t\tcase \"d\":\n\t\t\t\t// Day of month, without leading zero for single-digit days\n\t\t\tcase \"dd\":\n\t\t\t\t// Day of month, with leading zero for single-digit days\n\t\t\t\tfoundDay = true;\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( getPart(value, 2), clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"MMM\":\n\t\t\t\t// Month, as a three-letter abbreviation\n\t\t\tcase \"MMMM\":\n\t\t\t\t// Month, using the full name\n\t\t\t\tvar part = getPart( value, 1 );\n\t\t\t\tret.push(\n\t\t\t\t\t( cal.monthsGenitive && hasDay() )\n\t\t\t\t\t?\n\t\t\t\t\tcal.monthsGenitive[ clength === 3 ? \"namesAbbr\" : \"names\" ][ part ]\n\t\t\t\t\t:\n\t\t\t\t\tcal.months[ clength === 3 ? \"namesAbbr\" : \"names\" ][ part ]\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"M\":\n\t\t\t\t// Month, as digits, with no leading zero for single-digit months\n\t\t\tcase \"MM\":\n\t\t\t\t// Month, as digits, with leading zero for single-digit months\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( getPart(value, 1) + 1, clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"y\":\n\t\t\t\t// Year, as two digits, but with no leading zero for years less than 10\n\t\t\tcase \"yy\":\n\t\t\t\t// Year, as two digits, with leading zero for years less than 10\n\t\t\tcase \"yyyy\":\n\t\t\t\t// Year represented by four full digits\n\t\t\t\tpart = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );\n\t\t\t\tif ( clength < 4 ) {\n\t\t\t\t\tpart = part % 100;\n\t\t\t\t}\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( part, clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"h\":\n\t\t\t\t// Hours with no leading zero for single-digit hours, using 12-hour clock\n\t\t\tcase \"hh\":\n\t\t\t\t// Hours with leading zero for single-digit hours, using 12-hour clock\n\t\t\t\thour = value.getHours() % 12;\n\t\t\t\tif ( hour === 0 ) hour = 12;\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( hour, clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"H\":\n\t\t\t\t// Hours with no leading zero for single-digit hours, using 24-hour clock\n\t\t\tcase \"HH\":\n\t\t\t\t// Hours with leading zero for single-digit hours, using 24-hour clock\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( value.getHours(), clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"m\":\n\t\t\t\t// Minutes with no leading zero for single-digit minutes\n\t\t\tcase \"mm\":\n\t\t\t\t// Minutes with leading zero for single-digit minutes\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( value.getMinutes(), clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"s\":\n\t\t\t\t// Seconds with no leading zero for single-digit seconds\n\t\t\tcase \"ss\":\n\t\t\t\t// Seconds with leading zero for single-digit seconds\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( value.getSeconds(), clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"t\":\n\t\t\t\t// One character am/pm indicator (\"a\" or \"p\")\n\t\t\tcase \"tt\":\n\t\t\t\t// Multicharacter am/pm indicator\n\t\t\t\tpart = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : \" \" ) : ( cal.PM ? cal.PM[0] : \" \" );\n\t\t\t\tret.push( clength === 1 ? part.charAt(0) : part );\n\t\t\t\tbreak;\n\t\t\tcase \"f\":\n\t\t\t\t// Deciseconds\n\t\t\tcase \"ff\":\n\t\t\t\t// Centiseconds\n\t\t\tcase \"fff\":\n\t\t\t\t// Milliseconds\n\t\t\t\tret.push(\n\t\t\t\t\tpadZeros( value.getMilliseconds(), 3 ).substr( 0, clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"z\":\n\t\t\t\t// Time zone offset, no leading zero\n\t\t\tcase \"zz\":\n\t\t\t\t// Time zone offset with leading zero\n\t\t\t\thour = value.getTimezoneOffset() / 60;\n\t\t\t\tret.push(\n\t\t\t\t\t( hour <= 0 ? \"+\" : \"-\" ) + padZeros( Math.floor(Math.abs(hour)), clength )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"zzz\":\n\t\t\t\t// Time zone offset with leading zero\n\t\t\t\thour = value.getTimezoneOffset() / 60;\n\t\t\t\tret.push(\n\t\t\t\t\t( hour <= 0 ? \"+\" : \"-\" ) + padZeros( Math.floor(Math.abs(hour)), 2 )\n\t\t\t\t\t// Hard coded \":\" separator, rather than using cal.TimeSeparator\n\t\t\t\t\t// Repeated here for consistency, plus \":\" was already assumed in date parsing.\n\t\t\t\t\t+ \":\" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"g\":\n\t\t\tcase \"gg\":\n\t\t\t\tif ( cal.eras ) {\n\t\t\t\t\tret.push(\n\t\t\t\t\t\tcal.eras[ getEra(value, eras) ].name\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\tcase \"/\":\n\t\t\tret.push( cal[\"/\"] );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow \"Invalid date format pattern \\'\" + current + \"\\'.\";\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn ret.join( \"\" );\n};\n\n// formatNumber\n(function() {\n\tvar expandNumber;\n\n\texpandNumber = function( number, precision, formatInfo ) {\n\t\tvar groupSizes = formatInfo.groupSizes,\n\t\t\tcurSize = groupSizes[ 0 ],\n\t\t\tcurGroupIndex = 1,\n\t\t\tfactor = Math.pow( 10, precision ),\n\t\t\trounded = Math.round( number * factor ) / factor;\n\n\t\tif ( !isFinite(rounded) ) {\n\t\t\trounded = number;\n\t\t}\n\t\tnumber = rounded;\n\n\t\tvar numberString = number+\"\",\n\t\t\tright = \"\",\n\t\t\tsplit = numberString.split( /e/i ),\n\t\t\texponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;\n\t\tnumberString = split[ 0 ];\n\t\tsplit = numberString.split( \".\" );\n\t\tnumberString = split[ 0 ];\n\t\tright = split.length > 1 ? split[ 1 ] : \"\";\n\n\t\tvar l;\n\t\tif ( exponent > 0 ) {\n\t\t\tright = zeroPad( right, exponent, false );\n\t\t\tnumberString += right.slice( 0, exponent );\n\t\t\tright = right.substr( exponent );\n\t\t}\n\t\telse if ( exponent < 0 ) {\n\t\t\texponent = -exponent;\n\t\t\tnumberString = zeroPad( numberString, exponent + 1 );\n\t\t\tright = numberString.slice( -exponent, numberString.length ) + right;\n\t\t\tnumberString = numberString.slice( 0, -exponent );\n\t\t}\n\n\t\tif ( precision > 0 ) {\n\t\t\tright = formatInfo[ \".\" ] +\n\t\t\t\t( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );\n\t\t}\n\t\telse {\n\t\t\tright = \"\";\n\t\t}\n\n\t\tvar stringIndex = numberString.length - 1,\n\t\t\tsep = formatInfo[ \",\" ],\n\t\t\tret = \"\";\n\n\t\twhile ( stringIndex >= 0 ) {\n\t\t\tif ( curSize === 0 || curSize > stringIndex ) {\n\t\t\t\treturn numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );\n\t\t\t}\n\t\t\tret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : \"\" );\n\n\t\t\tstringIndex -= curSize;\n\n\t\t\tif ( curGroupIndex < groupSizes.length ) {\n\t\t\t\tcurSize = groupSizes[ curGroupIndex ];\n\t\t\t\tcurGroupIndex++;\n\t\t\t}\n\t\t}\n\n\t\treturn numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;\n\t};\n\n\tformatNumber = function( value, format, culture ) {\n\t\tif ( !isFinite(value) ) {\n\t\t\tif ( value === Infinity ) {\n\t\t\t\treturn culture.numberFormat.positiveInfinity;\n\t\t\t}\n\t\t\tif ( value === -Infinity ) {\n\t\t\t\treturn culture.numberFormat.negativeInfinity;\n\t\t\t}\n\t\t\treturn culture.numberFormat.NaN;\n\t\t}\n\t\tif ( !format || format === \"i\" ) {\n\t\t\treturn culture.name.length ? value.toLocaleString() : value.toString();\n\t\t}\n\t\tformat = format || \"D\";\n\n\t\tvar nf = culture.numberFormat,\n\t\t\tnumber = Math.abs( value ),\n\t\t\tprecision = -1,\n\t\t\tpattern;\n\t\tif ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );\n\n\t\tvar current = format.charAt( 0 ).toUpperCase(),\n\t\t\tformatInfo;\n\n\t\tswitch ( current ) {\n\t\t\tcase \"D\":\n\t\t\t\tpattern = \"n\";\n\t\t\t\tnumber = truncate( number );\n\t\t\t\tif ( precision !== -1 ) {\n\t\t\t\t\tnumber = zeroPad( \"\" + number, precision, true );\n\t\t\t\t}\n\t\t\t\tif ( value < 0 ) number = \"-\" + number;\n\t\t\t\tbreak;\n\t\t\tcase \"N\":\n\t\t\t\tformatInfo = nf;\n\t\t\t\t// fall through\n\t\t\tcase \"C\":\n\t\t\t\tformatInfo = formatInfo || nf.currency;\n\t\t\t\t// fall through\n\t\t\tcase \"P\":\n\t\t\t\tformatInfo = formatInfo || nf.percent;\n\t\t\t\tpattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || \"n\" );\n\t\t\t\tif ( precision === -1 ) precision = formatInfo.decimals;\n\t\t\t\tnumber = expandNumber( number * (current === \"P\" ? 100 : 1), precision, formatInfo );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"Bad number format specifier: \" + current;\n\t\t}\n\n\t\tvar patternParts = /n|\\$|-|%/g,\n\t\t\tret = \"\";\n\t\tfor ( ; ; ) {\n\t\t\tvar index = patternParts.lastIndex,\n\t\t\t\tar = patternParts.exec( pattern );\n\n\t\t\tret += pattern.slice( index, ar ? ar.index : pattern.length );\n\n\t\t\tif ( !ar ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tswitch ( ar[0] ) {\n\t\t\t\tcase \"n\":\n\t\t\t\t\tret += number;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"$\":\n\t\t\t\t\tret += nf.currency.symbol;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"-\":\n\t\t\t\t\t// don't make 0 negative\n\t\t\t\t\tif ( /[1-9]/.test(number) ) {\n\t\t\t\t\t\tret += nf[ \"-\" ];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"%\":\n\t\t\t\t\tret += nf.percent.symbol;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n\n}());\n\ngetTokenRegExp = function() {\n\t// regular expression for matching date and time tokens in format strings.\n\treturn /\\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g;\n};\n\ngetEra = function( date, eras ) {\n\tif ( !eras ) return 0;\n\tvar start, ticks = date.getTime();\n\tfor ( var i = 0, l = eras.length; i < l; i++ ) {\n\t\tstart = eras[ i ].start;\n\t\tif ( start === null || ticks >= start ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn 0;\n};\n\ngetEraYear = function( date, cal, era, sortable ) {\n\tvar year = date.getFullYear();\n\tif ( !sortable && cal.eras ) {\n\t\t// convert normal gregorian year to era-shifted gregorian\n\t\t// year by subtracting the era offset\n\t\tyear -= cal.eras[ era ].offset;\n\t}\n\treturn year;\n};\n\n// parseExact\n(function() {\n\tvar expandYear,\n\t\tgetDayIndex,\n\t\tgetMonthIndex,\n\t\tgetParseRegExp,\n\t\toutOfRange,\n\t\ttoUpper,\n\t\ttoUpperArray;\n\n\texpandYear = function( cal, year ) {\n\t\t// expands 2-digit year into 4 digits.\n\t\tvar now = new Date(),\n\t\t\tera = getEra( now );\n\t\tif ( year < 100 ) {\n\t\t\tvar twoDigitYearMax = cal.twoDigitYearMax;\n\t\t\ttwoDigitYearMax = typeof twoDigitYearMax === \"string\" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;\n\t\t\tvar curr = getEraYear( now, cal, era );\n\t\t\tyear += curr - ( curr % 100 );\n\t\t\tif ( year > twoDigitYearMax ) {\n\t\t\t\tyear -= 100;\n\t\t\t}\n\t\t}\n\t\treturn year;\n\t};\n\n\tgetDayIndex = function\t( cal, value, abbr ) {\n\t\tvar ret,\n\t\t\tdays = cal.days,\n\t\t\tupperDays = cal._upperDays;\n\t\tif ( !upperDays ) {\n\t\t\tcal._upperDays = upperDays = [\n\t\t\t\ttoUpperArray( days.names ),\n\t\t\t\ttoUpperArray( days.namesAbbr ),\n\t\t\t\ttoUpperArray( days.namesShort )\n\t\t\t];\n\t\t}\n\t\tvalue = toUpper( value );\n\t\tif ( abbr ) {\n\t\t\tret = arrayIndexOf( upperDays[1], value );\n\t\t\tif ( ret === -1 ) {\n\t\t\t\tret = arrayIndexOf( upperDays[2], value );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tret = arrayIndexOf( upperDays[0], value );\n\t\t}\n\t\treturn ret;\n\t};\n\n\tgetMonthIndex = function( cal, value, abbr ) {\n\t\tvar months = cal.months,\n\t\t\tmonthsGen = cal.monthsGenitive || cal.months,\n\t\t\tupperMonths = cal._upperMonths,\n\t\t\tupperMonthsGen = cal._upperMonthsGen;\n\t\tif ( !upperMonths ) {\n\t\t\tcal._upperMonths = upperMonths = [\n\t\t\t\ttoUpperArray( months.names ),\n\t\t\t\ttoUpperArray( months.namesAbbr )\n\t\t\t];\n\t\t\tcal._upperMonthsGen = upperMonthsGen = [\n\t\t\t\ttoUpperArray( monthsGen.names ),\n\t\t\t\ttoUpperArray( monthsGen.namesAbbr )\n\t\t\t];\n\t\t}\n\t\tvalue = toUpper( value );\n\t\tvar i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );\n\t\tif ( i < 0 ) {\n\t\t\ti = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );\n\t\t}\n\t\treturn i;\n\t};\n\n\tgetParseRegExp = function( cal, format ) {\n\t\t// converts a format string into a regular expression with groups that\n\t\t// can be used to extract date fields from a date string.\n\t\t// check for a cached parse regex.\n\t\tvar re = cal._parseRegExp;\n\t\tif ( !re ) {\n\t\t\tcal._parseRegExp = re = {};\n\t\t}\n\t\telse {\n\t\t\tvar reFormat = re[ format ];\n\t\t\tif ( reFormat ) {\n\t\t\t\treturn reFormat;\n\t\t\t}\n\t\t}\n\n\t\t// expand single digit formats, then escape regular expression characters.\n\t\tvar expFormat = expandFormat( cal, format ).replace( /([\\^\\$\\.\\*\\+\\?\\|\\[\\]\\(\\)\\{\\}])/g, \"\\\\\\\\$1\" ),\n\t\t\tregexp = [ \"^\" ],\n\t\t\tgroups = [],\n\t\t\tindex = 0,\n\t\t\tquoteCount = 0,\n\t\t\ttokenRegExp = getTokenRegExp(),\n\t\t\tmatch;\n\n\t\t// iterate through each date token found.\n\t\twhile ( (match = tokenRegExp.exec(expFormat)) !== null ) {\n\t\t\tvar preMatch = expFormat.slice( index, match.index );\n\t\t\tindex = tokenRegExp.lastIndex;\n\n\t\t\t// don't replace any matches that occur inside a string literal.\n\t\t\tquoteCount += appendPreOrPostMatch( preMatch, regexp );\n\t\t\tif ( quoteCount % 2 ) {\n\t\t\t\tregexp.push( match[0] );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// add a regex group for the token.\n\t\t\tvar m = match[ 0 ],\n\t\t\t\tlen = m.length,\n\t\t\t\tadd;\n\t\t\tswitch ( m ) {\n\t\t\t\tcase \"dddd\": case \"ddd\":\n\t\t\t\tcase \"MMMM\": case \"MMM\":\n\t\t\t\tcase \"gg\": case \"g\":\n\t\t\t\t\tadd = \"(\\\\D+)\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"tt\": case \"t\":\n\t\t\t\t\tadd = \"(\\\\D*)\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"yyyy\":\n\t\t\t\tcase \"fff\":\n\t\t\t\tcase \"ff\":\n\t\t\t\tcase \"f\":\n\t\t\t\t\tadd = \"(\\\\d{\" + len + \"})\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"dd\": case \"d\":\n\t\t\t\tcase \"MM\": case \"M\":\n\t\t\t\tcase \"yy\": case \"y\":\n\t\t\t\tcase \"HH\": case \"H\":\n\t\t\t\tcase \"hh\": case \"h\":\n\t\t\t\tcase \"mm\": case \"m\":\n\t\t\t\tcase \"ss\": case \"s\":\n\t\t\t\t\tadd = \"(\\\\d\\\\d?)\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zzz\":\n\t\t\t\t\tadd = \"([+-]?\\\\d\\\\d?:\\\\d{2})\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zz\": case \"z\":\n\t\t\t\t\tadd = \"([+-]?\\\\d\\\\d?)\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"/\":\n\t\t\t\t\tadd = \"(\\\\\" + cal[ \"/\" ] + \")\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow \"Invalid date format pattern \\'\" + m + \"\\'.\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( add ) {\n\t\t\t\tregexp.push( add );\n\t\t\t}\n\t\t\tgroups.push( match[0] );\n\t\t}\n\t\tappendPreOrPostMatch( expFormat.slice(index), regexp );\n\t\tregexp.push( \"$\" );\n\n\t\t// allow whitespace to differ when matching formats.\n\t\tvar regexpStr = regexp.join( \"\" ).replace( /\\s+/g, \"\\\\s+\" ),\n\t\t\tparseRegExp = { \"regExp\": regexpStr, \"groups\": groups };\n\n\t\t// cache the regex for this format.\n\t\treturn re[ format ] = parseRegExp;\n\t};\n\n\toutOfRange = function( value, low, high ) {\n\t\treturn value < low || value > high;\n\t};\n\n\ttoUpper = function( value ) {\n\t\t// \"he-IL\" has non-breaking space in weekday names.\n\t\treturn value.split( \"\\u00A0\" ).join( \" \" ).toUpperCase();\n\t};\n\n\ttoUpperArray = function( arr ) {\n\t\tvar results = [];\n\t\tfor ( var i = 0, l = arr.length; i < l; i++ ) {\n\t\t\tresults[ i ] = toUpper( arr[i] );\n\t\t}\n\t\treturn results;\n\t};\n\n\tparseExact = function( value, format, culture ) {\n\t\t// try to parse the date string by matching against the format string\n\t\t// while using the specified culture for date field names.\n\t\tvalue = trim( value );\n\t\tvar cal = culture.calendar,\n\t\t\t// convert date formats into regular expressions with groupings.\n\t\t\t// use the regexp to determine the input format and extract the date fields.\n\t\t\tparseInfo = getParseRegExp( cal, format ),\n\t\t\tmatch = new RegExp( parseInfo.regExp ).exec( value );\n\t\tif ( match === null ) {\n\t\t\treturn null;\n\t\t}\n\t\t// found a date format that matches the input.\n\t\tvar groups = parseInfo.groups,\n\t\t\tera = null, year = null, month = null, date = null, weekDay = null,\n\t\t\thour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,\n\t\t\tpmHour = false;\n\t\t// iterate the format groups to extract and set the date fields.\n\t\tfor ( var j = 0, jl = groups.length; j < jl; j++ ) {\n\t\t\tvar matchGroup = match[ j + 1 ];\n\t\t\tif ( matchGroup ) {\n\t\t\t\tvar current = groups[ j ],\n\t\t\t\t\tclength = current.length,\n\t\t\t\t\tmatchInt = parseInt( matchGroup, 10 );\n\t\t\t\tswitch ( current ) {\n\t\t\t\t\tcase \"dd\": case \"d\":\n\t\t\t\t\t\t// Day of month.\n\t\t\t\t\t\tdate = matchInt;\n\t\t\t\t\t\t// check that date is generally in valid range, also checking overflow below.\n\t\t\t\t\t\tif ( outOfRange(date, 1, 31) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"MMM\": case \"MMMM\":\n\t\t\t\t\t\tmonth = getMonthIndex( cal, matchGroup, clength === 3 );\n\t\t\t\t\t\tif ( outOfRange(month, 0, 11) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"M\": case \"MM\":\n\t\t\t\t\t\t// Month.\n\t\t\t\t\t\tmonth = matchInt - 1;\n\t\t\t\t\t\tif ( outOfRange(month, 0, 11) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"y\": case \"yy\":\n\t\t\t\t\tcase \"yyyy\":\n\t\t\t\t\t\tyear = clength < 4 ? expandYear( cal, matchInt ) : matchInt;\n\t\t\t\t\t\tif ( outOfRange(year, 0, 9999) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"h\": case \"hh\":\n\t\t\t\t\t\t// Hours (12-hour clock).\n\t\t\t\t\t\thour = matchInt;\n\t\t\t\t\t\tif ( hour === 12 ) hour = 0;\n\t\t\t\t\t\tif ( outOfRange(hour, 0, 11) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"H\": case \"HH\":\n\t\t\t\t\t\t// Hours (24-hour clock).\n\t\t\t\t\t\thour = matchInt;\n\t\t\t\t\t\tif ( outOfRange(hour, 0, 23) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"m\": case \"mm\":\n\t\t\t\t\t\t// Minutes.\n\t\t\t\t\t\tmin = matchInt;\n\t\t\t\t\t\tif ( outOfRange(min, 0, 59) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"s\": case \"ss\":\n\t\t\t\t\t\t// Seconds.\n\t\t\t\t\t\tsec = matchInt;\n\t\t\t\t\t\tif ( outOfRange(sec, 0, 59) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"tt\": case \"t\":\n\t\t\t\t\t\t// AM/PM designator.\n\t\t\t\t\t\t// see if it is standard, upper, or lower case PM. If not, ensure it is at least one of\n\t\t\t\t\t\t// the AM tokens. If not, fail the parse for this format.\n\t\t\t\t\t\tpmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!pmHour && (\n\t\t\t\t\t\t\t\t!cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"f\":\n\t\t\t\t\t\t// Deciseconds.\n\t\t\t\t\tcase \"ff\":\n\t\t\t\t\t\t// Centiseconds.\n\t\t\t\t\tcase \"fff\":\n\t\t\t\t\t\t// Milliseconds.\n\t\t\t\t\t\tmsec = matchInt * Math.pow( 10, 3 - clength );\n\t\t\t\t\t\tif ( outOfRange(msec, 0, 999) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"ddd\":\n\t\t\t\t\t\t// Day of week.\n\t\t\t\t\tcase \"dddd\":\n\t\t\t\t\t\t// Day of week.\n\t\t\t\t\t\tweekDay = getDayIndex( cal, matchGroup, clength === 3 );\n\t\t\t\t\t\tif ( outOfRange(weekDay, 0, 6) ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"zzz\":\n\t\t\t\t\t\t// Time zone offset in +/- hours:min.\n\t\t\t\t\t\tvar offsets = matchGroup.split( /:/ );\n\t\t\t\t\t\tif ( offsets.length !== 2 ) return null;\n\t\t\t\t\t\thourOffset = parseInt( offsets[0], 10 );\n\t\t\t\t\t\tif ( outOfRange(hourOffset, -12, 13) ) return null;\n\t\t\t\t\t\tvar minOffset = parseInt( offsets[1], 10 );\n\t\t\t\t\t\tif ( outOfRange(minOffset, 0, 59) ) return null;\n\t\t\t\t\t\ttzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, \"-\") ? -minOffset : minOffset );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"z\": case \"zz\":\n\t\t\t\t\t\t// Time zone offset in +/- hours.\n\t\t\t\t\t\thourOffset = matchInt;\n\t\t\t\t\t\tif ( outOfRange(hourOffset, -12, 13) ) return null;\n\t\t\t\t\t\ttzMinOffset = hourOffset * 60;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"g\": case \"gg\":\n\t\t\t\t\t\tvar eraName = matchGroup;\n\t\t\t\t\t\tif ( !eraName || !cal.eras ) return null;\n\t\t\t\t\t\teraName = trim( eraName.toLowerCase() );\n\t\t\t\t\t\tfor ( var i = 0, l = cal.eras.length; i < l; i++ ) {\n\t\t\t\t\t\t\tif ( eraName === cal.eras[i].name.toLowerCase() ) {\n\t\t\t\t\t\t\t\tera = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// could not find an era with that name\n\t\t\t\t\t\tif ( era === null ) return null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvar result = new Date(), defaultYear, convert = cal.convert;\n\t\tdefaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();\n\t\tif ( year === null ) {\n\t\t\tyear = defaultYear;\n\t\t}\n\t\telse if ( cal.eras ) {\n\t\t\t// year must be shifted to normal gregorian year\n\t\t\t// but not if year was not specified, its already normal gregorian\n\t\t\t// per the main if clause above.\n\t\t\tyear += cal.eras[( era || 0 )].offset;\n\t\t}\n\t\t// set default day and month to 1 and January, so if unspecified, these are the defaults\n\t\t// instead of the current day/month.\n\t\tif ( month === null ) {\n\t\t\tmonth = 0;\n\t\t}\n\t\tif ( date === null ) {\n\t\t\tdate = 1;\n\t\t}\n\t\t// now have year, month, and date, but in the culture's calendar.\n\t\t// convert to gregorian if necessary\n\t\tif ( convert ) {\n\t\t\tresult = convert.toGregorian( year, month, date );\n\t\t\t// conversion failed, must be an invalid match\n\t\t\tif ( result === null ) return null;\n\t\t}\n\t\telse {\n\t\t\t// have to set year, month and date together to avoid overflow based on current date.\n\t\t\tresult.setFullYear( year, month, date );\n\t\t\t// check to see if date overflowed for specified month (only checked 1-31 above).\n\t\t\tif ( result.getDate() !== date ) return null;\n\t\t\t// invalid day of week.\n\t\t\tif ( weekDay !== null && result.getDay() !== weekDay ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\t// if pm designator token was found make sure the hours fit the 24-hour clock.\n\t\tif ( pmHour && hour < 12 ) {\n\t\t\thour += 12;\n\t\t}\n\t\tresult.setHours( hour, min, sec, msec );\n\t\tif ( tzMinOffset !== null ) {\n\t\t\t// adjust timezone to utc before applying local offset.\n\t\t\tvar adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );\n\t\t\t// Safari limits hours and minutes to the range of -127 to 127.\t We need to use setHours\n\t\t\t// to ensure both these fields will not exceed this range.\tadjustedMin will range\n\t\t\t// somewhere between -1440 and 1500, so we only need to split this into hours.\n\t\t\tresult.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );\n\t\t}\n\t\treturn result;\n\t};\n}());\n\nparseNegativePattern = function( value, nf, negativePattern ) {\n\tvar neg = nf[ \"-\" ],\n\t\tpos = nf[ \"+\" ],\n\t\tret;\n\tswitch ( negativePattern ) {\n\t\tcase \"n -\":\n\t\t\tneg = \" \" + neg;\n\t\t\tpos = \" \" + pos;\n\t\t\t// fall through\n\t\tcase \"n-\":\n\t\t\tif ( endsWith(value, neg) ) {\n\t\t\t\tret = [ \"-\", value.substr(0, value.length - neg.length) ];\n\t\t\t}\n\t\t\telse if ( endsWith(value, pos) ) {\n\t\t\t\tret = [ \"+\", value.substr(0, value.length - pos.length) ];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"- n\":\n\t\t\tneg += \" \";\n\t\t\tpos += \" \";\n\t\t\t// fall through\n\t\tcase \"-n\":\n\t\t\tif ( startsWith(value, neg) ) {\n\t\t\t\tret = [ \"-\", value.substr(neg.length) ];\n\t\t\t}\n\t\t\telse if ( startsWith(value, pos) ) {\n\t\t\t\tret = [ \"+\", value.substr(pos.length) ];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"(n)\":\n\t\t\tif ( startsWith(value, \"(\") && endsWith(value, \")\") ) {\n\t\t\t\tret = [ \"-\", value.substr(1, value.length - 2) ];\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn ret || [ \"\", value ];\n};\n\n//\n// public instance functions\n//\n\nGlobalize.prototype.findClosestCulture = function( cultureSelector ) {\n\treturn Globalize.findClosestCulture.call( this, cultureSelector );\n};\n\nGlobalize.prototype.format = function( value, format, cultureSelector ) {\n\treturn Globalize.format.call( this, value, format, cultureSelector );\n};\n\nGlobalize.prototype.localize = function( key, cultureSelector ) {\n\treturn Globalize.localize.call( this, key, cultureSelector );\n};\n\nGlobalize.prototype.parseInt = function( value, radix, cultureSelector ) {\n\treturn Globalize.parseInt.call( this, value, radix, cultureSelector );\n};\n\nGlobalize.prototype.parseFloat = function( value, radix, cultureSelector ) {\n\treturn Globalize.parseFloat.call( this, value, radix, cultureSelector );\n};\n\nGlobalize.prototype.culture = function( cultureSelector ) {\n\treturn Globalize.culture.call( this, cultureSelector );\n};\n\n//\n// public singleton functions\n//\n\nGlobalize.addCultureInfo = function( cultureName, baseCultureName, info ) {\n\n\tvar base = {},\n\t\tisNew = false;\n\n\tif ( typeof cultureName !== \"string\" ) {\n\t\t// cultureName argument is optional string. If not specified, assume info is first\n\t\t// and only argument. Specified info deep-extends current culture.\n\t\tinfo = cultureName;\n\t\tcultureName = this.culture().name;\n\t\tbase = this.cultures[ cultureName ];\n\t} else if ( typeof baseCultureName !== \"string\" ) {\n\t\t// baseCultureName argument is optional string. If not specified, assume info is second\n\t\t// argument. Specified info deep-extends specified culture.\n\t\t// If specified culture does not exist, create by deep-extending default\n\t\tinfo = baseCultureName;\n\t\tisNew = ( this.cultures[ cultureName ] == null );\n\t\tbase = this.cultures[ cultureName ] || this.cultures[ \"default\" ];\n\t} else {\n\t\t// cultureName and baseCultureName specified. Assume a new culture is being created\n\t\t// by deep-extending an specified base culture\n\t\tisNew = true;\n\t\tbase = this.cultures[ baseCultureName ];\n\t}\n\n\tthis.cultures[ cultureName ] = extend(true, {},\n\t\tbase,\n\t\tinfo\n\t);\n\t// Make the standard calendar the current culture if it's a new culture\n\tif ( isNew ) {\n\t\tthis.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;\n\t}\n};\n\nGlobalize.findClosestCulture = function( name ) {\n\tvar match;\n\tif ( !name ) {\n\t\treturn this.cultures[ this.cultureSelector ] || this.cultures[ \"default\" ];\n\t}\n\tif ( typeof name === \"string\" ) {\n\t\tname = name.split( \",\" );\n\t}\n\tif ( isArray(name) ) {\n\t\tvar lang,\n\t\t\tcultures = this.cultures,\n\t\t\tlist = name,\n\t\t\ti, l = list.length,\n\t\t\tprioritized = [];\n\t\tfor ( i = 0; i < l; i++ ) {\n\t\t\tname = trim( list[i] );\n\t\t\tvar pri, parts = name.split( \";\" );\n\t\t\tlang = trim( parts[0] );\n\t\t\tif ( parts.length === 1 ) {\n\t\t\t\tpri = 1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tname = trim( parts[1] );\n\t\t\t\tif ( name.indexOf(\"q=\") === 0 ) {\n\t\t\t\t\tname = name.substr( 2 );\n\t\t\t\t\tpri = parseFloat( name );\n\t\t\t\t\tpri = isNaN( pri ) ? 0 : pri;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpri = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprioritized.push({ lang: lang, pri: pri });\n\t\t}\n\t\tprioritized.sort(function( a, b ) {\n\t\t\treturn a.pri < b.pri ? 1 : -1;\n\t\t});\n\n\t\t// exact match\n\t\tfor ( i = 0; i < l; i++ ) {\n\t\t\tlang = prioritized[ i ].lang;\n\t\t\tmatch = cultures[ lang ];\n\t\t\tif ( match ) {\n\t\t\t\treturn match;\n\t\t\t}\n\t\t}\n\n\t\t// neutral language match\n\t\tfor ( i = 0; i < l; i++ ) {\n\t\t\tlang = prioritized[ i ].lang;\n\t\t\tdo {\n\t\t\t\tvar index = lang.lastIndexOf( \"-\" );\n\t\t\t\tif ( index === -1 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// strip off the last part. e.g. en-US => en\n\t\t\t\tlang = lang.substr( 0, index );\n\t\t\t\tmatch = cultures[ lang ];\n\t\t\t\tif ( match ) {\n\t\t\t\t\treturn match;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile ( 1 );\n\t\t}\n\n\t\t// last resort: match first culture using that language\n\t\tfor ( i = 0; i < l; i++ ) {\n\t\t\tlang = prioritized[ i ].lang;\n\t\t\tfor ( var cultureKey in cultures ) {\n\t\t\t\tvar culture = cultures[ cultureKey ];\n\t\t\t\tif ( culture.language == lang ) {\n\t\t\t\t\treturn culture;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if ( typeof name === \"object\" ) {\n\t\treturn name;\n\t}\n\treturn match || null;\n};\n\nGlobalize.format = function( value, format, cultureSelector ) {\n\tculture = this.findClosestCulture( cultureSelector );\n\tif ( value instanceof Date ) {\n\t\tvalue = formatDate( value, format, culture );\n\t}\n\telse if ( typeof value === \"number\" ) {\n\t\tvalue = formatNumber( value, format, culture );\n\t}\n\treturn value;\n};\n\nGlobalize.localize = function( key, cultureSelector ) {\n\treturn this.findClosestCulture( cultureSelector ).messages[ key ] ||\n\t\tthis.cultures[ \"default\" ].messages[ key ];\n};\n\nGlobalize.parseDate = function( value, formats, culture ) {\n\tculture = this.findClosestCulture( culture );\n\n\tvar date, prop, patterns;\n\tif ( formats ) {\n\t\tif ( typeof formats === \"string\" ) {\n\t\t\tformats = [ formats ];\n\t\t}\n\t\tif ( formats.length ) {\n\t\t\tfor ( var i = 0, l = formats.length; i < l; i++ ) {\n\t\t\t\tvar format = formats[ i ];\n\t\t\t\tif ( format ) {\n\t\t\t\t\tdate = parseExact( value, format, culture );\n\t\t\t\t\tif ( date ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tpatterns = culture.calendar.patterns;\n\t\tfor ( prop in patterns ) {\n\t\t\tdate = parseExact( value, patterns[prop], culture );\n\t\t\tif ( date ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn date || null;\n};\n\nGlobalize.parseInt = function( value, radix, cultureSelector ) {\n\treturn truncate( Globalize.parseFloat(value, radix, cultureSelector) );\n};\n\nGlobalize.parseFloat = function( value, radix, cultureSelector ) {\n\t// radix argument is optional\n\tif ( typeof radix !== \"number\" ) {\n\t\tcultureSelector = radix;\n\t\tradix = 10;\n\t}\n\n\tvar culture = this.findClosestCulture( cultureSelector );\n\tvar ret = NaN,\n\t\tnf = culture.numberFormat;\n\n\tif ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {\n\t\t// remove currency symbol\n\t\tvalue = value.replace( culture.numberFormat.currency.symbol, \"\" );\n\t\t// replace decimal seperator\n\t\tvalue = value.replace( culture.numberFormat.currency[\".\"], culture.numberFormat[\".\"] );\n\t}\n\n\t// trim leading and trailing whitespace\n\tvalue = trim( value );\n\n\t// allow infinity or hexidecimal\n\tif ( regexInfinity.test(value) ) {\n\t\tret = parseFloat( value );\n\t}\n\telse if ( !radix && regexHex.test(value) ) {\n\t\tret = parseInt( value, 16 );\n\t}\n\telse {\n\n\t\t// determine sign and number\n\t\tvar signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),\n\t\t\tsign = signInfo[ 0 ],\n\t\t\tnum = signInfo[ 1 ];\n\n\t\t// #44 - try parsing as \"(n)\"\n\t\tif ( sign === \"\" && nf.pattern[0] !== \"(n)\" ) {\n\t\t\tsignInfo = parseNegativePattern( value, nf, \"(n)\" );\n\t\t\tsign = signInfo[ 0 ];\n\t\t\tnum = signInfo[ 1 ];\n\t\t}\n\n\t\t// try parsing as \"-n\"\n\t\tif ( sign === \"\" && nf.pattern[0] !== \"-n\" ) {\n\t\t\tsignInfo = parseNegativePattern( value, nf, \"-n\" );\n\t\t\tsign = signInfo[ 0 ];\n\t\t\tnum = signInfo[ 1 ];\n\t\t}\n\n\t\tsign = sign || \"+\";\n\n\t\t// determine exponent and number\n\t\tvar exponent,\n\t\t\tintAndFraction,\n\t\t\texponentPos = num.indexOf( \"e\" );\n\t\tif ( exponentPos < 0 ) exponentPos = num.indexOf( \"E\" );\n\t\tif ( exponentPos < 0 ) {\n\t\t\tintAndFraction = num;\n\t\t\texponent = null;\n\t\t}\n\t\telse {\n\t\t\tintAndFraction = num.substr( 0, exponentPos );\n\t\t\texponent = num.substr( exponentPos + 1 );\n\t\t}\n\t\t// determine decimal position\n\t\tvar integer,\n\t\t\tfraction,\n\t\t\tdecSep = nf[ \".\" ],\n\t\t\tdecimalPos = intAndFraction.indexOf( decSep );\n\t\tif ( decimalPos < 0 ) {\n\t\t\tinteger = intAndFraction;\n\t\t\tfraction = null;\n\t\t}\n\t\telse {\n\t\t\tinteger = intAndFraction.substr( 0, decimalPos );\n\t\t\tfraction = intAndFraction.substr( decimalPos + decSep.length );\n\t\t}\n\t\t// handle groups (e.g. 1,000,000)\n\t\tvar groupSep = nf[ \",\" ];\n\t\tinteger = integer.split( groupSep ).join( \"\" );\n\t\tvar altGroupSep = groupSep.replace( /\\u00A0/g, \" \" );\n\t\tif ( groupSep !== altGroupSep ) {\n\t\t\tinteger = integer.split( altGroupSep ).join( \"\" );\n\t\t}\n\t\t// build a natively parsable number string\n\t\tvar p = sign + integer;\n\t\tif ( fraction !== null ) {\n\t\t\tp += \".\" + fraction;\n\t\t}\n\t\tif ( exponent !== null ) {\n\t\t\t// exponent itself may have a number patternd\n\t\t\tvar expSignInfo = parseNegativePattern( exponent, nf, \"-n\" );\n\t\t\tp += \"e\" + ( expSignInfo[0] || \"+\" ) + expSignInfo[ 1 ];\n\t\t}\n\t\tif ( regexParseFloat.test(p) ) {\n\t\t\tret = parseFloat( p );\n\t\t}\n\t}\n\treturn ret;\n};\n\nGlobalize.culture = function( cultureSelector ) {\n\t// setter\n\tif ( typeof cultureSelector !== \"undefined\" ) {\n\t\tthis.cultureSelector = cultureSelector;\n\t}\n\t// getter\n\treturn this.findClosestCulture( cultureSelector ) || this.culture[ \"default\" ];\n};\n\n}( this ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/jquery.bgiframe-2.1.2.js",
    "content": "/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)\n * Licensed under the MIT License (LICENSE.txt).\n *\n * Version 2.1.2\n */\n\n(function($){\n\n$.fn.bgiframe = ($.browser.msie && /msie 6\\.0/i.test(navigator.userAgent) ? function(s) {\n    s = $.extend({\n        top     : 'auto', // auto == .currentStyle.borderTopWidth\n        left    : 'auto', // auto == .currentStyle.borderLeftWidth\n        width   : 'auto', // auto == offsetWidth\n        height  : 'auto', // auto == offsetHeight\n        opacity : true,\n        src     : 'javascript:false;'\n    }, s);\n    var html = '<iframe class=\"bgiframe\"frameborder=\"0\"tabindex=\"-1\"src=\"'+s.src+'\"'+\n                   'style=\"display:block;position:absolute;z-index:-1;'+\n                       (s.opacity !== false?'filter:Alpha(Opacity=\\'0\\');':'')+\n                       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\\'px\\')':prop(s.top))+';'+\n                       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\\'px\\')':prop(s.left))+';'+\n                       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\\'px\\')':prop(s.width))+';'+\n                       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\\'px\\')':prop(s.height))+';'+\n                '\"/>';\n    return this.each(function() {\n        if ( $(this).children('iframe.bgiframe').length === 0 )\n            this.insertBefore( document.createElement(html), this.firstChild );\n    });\n} : function() { return this; });\n\n// old alias\n$.fn.bgIframe = $.fn.bgiframe;\n\nfunction prop(n) {\n    return n && n.constructor === Number ? n + 'px' : n;\n}\n\n})(jQuery);"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/jquery.cookie.js",
    "content": "/*jslint browser: true */ /*global jQuery: true */\n\n/**\n * jQuery Cookie plugin\n *\n * Copyright (c) 2010 Klaus Hartl (stilbuero.de)\n * Dual licensed under the MIT and GPL licenses:\n * http://www.opensource.org/licenses/mit-license.php\n * http://www.gnu.org/licenses/gpl.html\n *\n */\n\n// TODO JsDoc\n\n/**\n * Create a cookie with the given key and value and other optional parameters.\n *\n * @example $.cookie('the_cookie', 'the_value');\n * @desc Set the value of a cookie.\n * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });\n * @desc Create a cookie with all available options.\n * @example $.cookie('the_cookie', 'the_value');\n * @desc Create a session cookie.\n * @example $.cookie('the_cookie', null);\n * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain\n *       used when the cookie was set.\n *\n * @param String key The key of the cookie.\n * @param String value The value of the cookie.\n * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.\n * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.\n *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.\n *                             If set to null or omitted, the cookie will be a session cookie and will not be retained\n *                             when the the browser exits.\n * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).\n * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).\n * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will\n *                        require a secure protocol (like HTTPS).\n * @type undefined\n *\n * @name $.cookie\n * @cat Plugins/Cookie\n * @author Klaus Hartl/klaus.hartl@stilbuero.de\n */\n\n/**\n * Get the value of a cookie with the given key.\n *\n * @example $.cookie('the_cookie');\n * @desc Get the value of a cookie.\n *\n * @param String key The key of the cookie.\n * @return The value of the cookie.\n * @type String\n *\n * @name $.cookie\n * @cat Plugins/Cookie\n * @author Klaus Hartl/klaus.hartl@stilbuero.de\n */\njQuery.cookie = function (key, value, options) {\n\n    // key and value given, set cookie...\n    if (arguments.length > 1 && (value === null || typeof value !== \"object\")) {\n        options = jQuery.extend({}, options);\n\n        if (value === null) {\n            options.expires = -1;\n        }\n\n        if (typeof options.expires === 'number') {\n            var days = options.expires, t = options.expires = new Date();\n            t.setDate(t.getDate() + days);\n        }\n\n        return (document.cookie = [\n            encodeURIComponent(key), '=',\n            options.raw ? String(value) : encodeURIComponent(String(value)),\n            options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE\n            options.path ? '; path=' + options.path : '',\n            options.domain ? '; domain=' + options.domain : '',\n            options.secure ? '; secure' : ''\n        ].join(''));\n    }\n\n    // key and possibly options given, get cookie...\n    options = value || {};\n    var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;\n    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;\n};\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/jquery.metadata.js",
    "content": "/*\n * Metadata - jQuery plugin for parsing metadata from elements\n *\n * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan\n *\n * Dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n *\n * Revision: $Id: jquery.metadata.js 4187 2007-12-16 17:15:27Z joern.zaefferer $\n *\n */\n\n/**\n * Sets the type of metadata to use. Metadata is encoded in JSON, and each property\n * in the JSON will become a property of the element itself.\n *\n * There are three supported types of metadata storage:\n *\n *   attr:  Inside an attribute. The name parameter indicates *which* attribute.\n *          \n *   class: Inside the class attribute, wrapped in curly braces: { }\n *   \n *   elem:  Inside a child element (e.g. a script tag). The\n *          name parameter indicates *which* element.\n *          \n * The metadata for an element is loaded the first time the element is accessed via jQuery.\n *\n * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements\n * matched by expr, then redefine the metadata type and run another $(expr) for other elements.\n * \n * @name $.metadata.setType\n *\n * @example <p id=\"one\" class=\"some_class {item_id: 1, item_label: 'Label'}\">This is a p</p>\n * @before $.metadata.setType(\"class\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from the class attribute\n * \n * @example <p id=\"one\" class=\"some_class\" data=\"{item_id: 1, item_label: 'Label'}\">This is a p</p>\n * @before $.metadata.setType(\"attr\", \"data\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from a \"data\" attribute\n * \n * @example <p id=\"one\" class=\"some_class\"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>\n * @before $.metadata.setType(\"elem\", \"script\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from a nested script element\n * \n * @param String type The encoding type\n * @param String name The name of the attribute to be used to get metadata (optional)\n * @cat Plugins/Metadata\n * @descr Sets the type of encoding to be used when loading metadata for the first time\n * @type undefined\n * @see metadata()\n */\n\n(function($) {\n\n$.extend({\n\tmetadata : {\n\t\tdefaults : {\n\t\t\ttype: 'class',\n\t\t\tname: 'metadata',\n\t\t\tcre: /({.*})/,\n\t\t\tsingle: 'metadata'\n\t\t},\n\t\tsetType: function( type, name ){\n\t\t\tthis.defaults.type = type;\n\t\t\tthis.defaults.name = name;\n\t\t},\n\t\tget: function( elem, opts ){\n\t\t\tvar settings = $.extend({},this.defaults,opts);\n\t\t\t// check for empty string in single property\n\t\t\tif ( !settings.single.length ) settings.single = 'metadata';\n\t\t\t\n\t\t\tvar data = $.data(elem, settings.single);\n\t\t\t// returned cached data if it already exists\n\t\t\tif ( data ) return data;\n\t\t\t\n\t\t\tdata = \"{}\";\n\t\t\t\n\t\t\tif ( settings.type == \"class\" ) {\n\t\t\t\tvar m = settings.cre.exec( elem.className );\n\t\t\t\tif ( m )\n\t\t\t\t\tdata = m[1];\n\t\t\t} else if ( settings.type == \"elem\" ) {\n\t\t\t\tif( !elem.getElementsByTagName )\n\t\t\t\t\treturn undefined;\n\t\t\t\tvar e = elem.getElementsByTagName(settings.name);\n\t\t\t\tif ( e.length )\n\t\t\t\t\tdata = $.trim(e[0].innerHTML);\n\t\t\t} else if ( elem.getAttribute != undefined ) {\n\t\t\t\tvar attr = elem.getAttribute( settings.name );\n\t\t\t\tif ( attr )\n\t\t\t\t\tdata = attr;\n\t\t\t}\n\t\t\t\n\t\t\tif ( data.indexOf( '{' ) <0 )\n\t\t\tdata = \"{\" + data + \"}\";\n\t\t\t\n\t\t\tdata = eval(\"(\" + data + \")\");\n\t\t\t\n\t\t\t$.data( elem, settings.single, data );\n\t\t\treturn data;\n\t\t}\n\t}\n});\n\n/**\n * Returns the metadata object for the first member of the jQuery object.\n *\n * @name metadata\n * @descr Returns element's metadata object\n * @param Object opts An object contianing settings to override the defaults\n * @type jQuery\n * @cat Plugins/Metadata\n */\n$.fn.metadata = function( opts ){\n\treturn $.metadata.get( this[0], opts );\n};\n\n})(jQuery);"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/jquery.mousewheel-3.0.4.js",
    "content": "/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)\n * Licensed under the MIT License (LICENSE.txt).\n *\n * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.\n * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.\n * Thanks to: Seamus Leahy for adding deltaX and deltaY\n *\n * Version: 3.0.4\n * \n * Requires: 1.2.2+\n */\n\n(function($) {\n\nvar types = ['DOMMouseScroll', 'mousewheel'];\n\n$.event.special.mousewheel = {\n    setup: function() {\n        if ( this.addEventListener ) {\n            for ( var i=types.length; i; ) {\n                this.addEventListener( types[--i], handler, false );\n            }\n        } else {\n            this.onmousewheel = handler;\n        }\n    },\n    \n    teardown: function() {\n        if ( this.removeEventListener ) {\n            for ( var i=types.length; i; ) {\n                this.removeEventListener( types[--i], handler, false );\n            }\n        } else {\n            this.onmousewheel = null;\n        }\n    }\n};\n\n$.fn.extend({\n    mousewheel: function(fn) {\n        return fn ? this.bind(\"mousewheel\", fn) : this.trigger(\"mousewheel\");\n    },\n    \n    unmousewheel: function(fn) {\n        return this.unbind(\"mousewheel\", fn);\n    }\n});\n\n\nfunction handler(event) {\n    var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;\n    event = $.event.fix(orgEvent);\n    event.type = \"mousewheel\";\n    \n    // Old school scrollwheel delta\n    if ( event.wheelDelta ) { delta = event.wheelDelta/120; }\n    if ( event.detail     ) { delta = -event.detail/3; }\n    \n    // New school multidimensional scroll (touchpads) deltas\n    deltaY = delta;\n    \n    // Gecko\n    if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {\n        deltaY = 0;\n        deltaX = -1*delta;\n    }\n    \n    // Webkit\n    if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }\n    if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }\n    \n    // Add event and delta to the front of the arguments\n    args.unshift(event, delta, deltaX, deltaY);\n    \n    return $.event.handle.apply(this, args);\n}\n\n})(jQuery);"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/jshint.js",
    "content": "/*!\n * JSHint, by JSHint Community.\n *\n * Licensed under the same slightly modified MIT license that JSLint is.\n * It stops evil-doers everywhere.\n *\n * JSHint is a derivative work of JSLint:\n *\n *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n *\n *   Permission is hereby granted, free of charge, to any person obtaining\n *   a copy of this software and associated documentation files (the \"Software\"),\n *   to deal in the Software without restriction, including without limitation\n *   the rights to use, copy, modify, merge, publish, distribute, sublicense,\n *   and/or sell copies of the Software, and to permit persons to whom\n *   the Software is furnished to do so, subject to the following conditions:\n *\n *   The above copyright notice and this permission notice shall be included\n *   in all copies or substantial portions of the Software.\n *\n *   The Software shall be used for Good, not Evil.\n *\n *   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n *   DEALINGS IN THE SOFTWARE.\n *\n * JSHint was forked from 2010-12-16 edition of JSLint.\n *\n */\n\n/*\n JSHINT is a global function. It takes two parameters.\n\n     var myResult = JSHINT(source, option);\n\n The first parameter is either a string or an array of strings. If it is a\n string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n is assumed that each string represents one line. The source can be a\n JavaScript text or a JSON text.\n\n The second parameter is an optional object of options which control the\n operation of JSHINT. Most of the options are booleans: They are all\n optional and have a default value of false. One of the options, predef,\n can be an array of names, which will be used to declare global variables,\n or an object whose keys are used as global names, with a boolean value\n that determines if they are assignable.\n\n If it checks out, JSHINT returns true. Otherwise, it returns false.\n\n If false, you can inspect JSHINT.errors to find out the problems.\n JSHINT.errors is an array of objects containing these members:\n\n {\n     line      : The line (relative to 0) at which the lint was found\n     character : The character (relative to 0) at which the lint was found\n     reason    : The problem\n     evidence  : The text line in which the problem occurred\n     raw       : The raw message before the details were inserted\n     a         : The first detail\n     b         : The second detail\n     c         : The third detail\n     d         : The fourth detail\n }\n\n If a fatal error was found, a null will be the last element of the\n JSHINT.errors array.\n\n You can request a Function Report, which shows all of the functions\n and the parameters and vars that they use. This can be used to find\n implied global variables and other problems. The report is in HTML and\n can be inserted in an HTML <body>.\n\n     var myReport = JSHINT.report(limited);\n\n If limited is true, then the report will be limited to only errors.\n\n You can request a data structure which contains JSHint's results.\n\n     var myData = JSHINT.data();\n\n It returns a structure with this form:\n\n {\n     errors: [\n         {\n             line: NUMBER,\n             character: NUMBER,\n             reason: STRING,\n             evidence: STRING\n         }\n     ],\n     functions: [\n         name: STRING,\n         line: NUMBER,\n         last: NUMBER,\n         param: [\n             STRING\n         ],\n         closure: [\n             STRING\n         ],\n         var: [\n             STRING\n         ],\n         exception: [\n             STRING\n         ],\n         outer: [\n             STRING\n         ],\n         unused: [\n             STRING\n         ],\n         global: [\n             STRING\n         ],\n         label: [\n             STRING\n         ]\n     ],\n     globals: [\n         STRING\n     ],\n     member: {\n         STRING: NUMBER\n     },\n     unused: [\n         {\n             name: STRING,\n             line: NUMBER\n         }\n     ],\n     implieds: [\n         {\n             name: STRING,\n             line: NUMBER\n         }\n     ],\n     urls: [\n         STRING\n     ],\n     json: BOOLEAN\n }\n\n Empty arrays will not be included.\n\n*/\n\n/*jshint\n evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,\n undef: true, maxlen: 100, indent:4\n*/\n\n/*members \"\\b\", \"\\t\", \"\\n\", \"\\f\", \"\\r\", \"!=\", \"!==\", \"\\\"\", \"%\", \"(begin)\",\n \"(breakage)\", \"(context)\", \"(error)\", \"(global)\", \"(identifier)\", \"(last)\",\n \"(line)\", \"(loopage)\", \"(name)\", \"(onevar)\", \"(params)\", \"(scope)\",\n \"(statement)\", \"(verb)\", \"*\", \"+\", \"++\", \"-\", \"--\", \"\\/\", \"<\", \"<=\", \"==\",\n \"===\", \">\", \">=\", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,\n __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,\n Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas,\n CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,\n Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag,\n E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,\n Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,\n FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,\n HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,\n HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,\n HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,\n HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,\n HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,\n HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,\n HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,\n HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,\n HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,\n HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,\n HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,\n HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,\n HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,\n HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,\n Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,\n Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,\n MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native,\n NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI,\n POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError,\n Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,\n SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,\n ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,\n Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,\n SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,\n Timer, Tips, Type, TypeError, Toggle, Try, \"use strict\", unescape, URI, URIError, URL,\n VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator,\n XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, \"\\\\\", a,\n addEventListener, address, alert, apply, applicationCache, arguments, arity,\n asi, b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, c, call, callee,\n caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,\n close, closed, closure, comment, condition, confirm, console, constructor,\n content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,\n decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,\n dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent,\n entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,\n ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,\n forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,\n g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,\n hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,\n indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,\n isDigit, isFinite, isNaN, iterator, java, join, jshint,\n JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma,\n latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,\n log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,\n moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen,\n nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus,\n onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param,\n parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,\n proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp,\n readFile, readUrl, regexdash, removeEventListener, replace, report, require,\n reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,\n runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal,\n send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice,\n smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow,\n supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing,\n type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis,\n value, valueOf, var, version, WebSocket, white, window, Worker, wsh*/\n\n/*global exports: false */\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSHINT function itself.\n\nvar JSHINT = (function () {\n    \"use strict\";\n\n    var anonname,       // The guessed name for anonymous functions.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n        // These are the JSHint boolean options.\n        boolOptions = {\n            asi         : true, // if automatic semicolon insertion should be tolerated\n            bitwise     : true, // if bitwise operators should not be allowed\n            boss        : true, // if advanced usage of assignments should be allowed\n            browser     : true, // if the standard browser globals should be predefined\n            couch       : true, // if CouchDB globals should be predefined\n            curly       : true, // if curly braces around all blocks should be required\n            debug       : true, // if debugger statements should be allowed\n            devel       : true, // if logging globals should be predefined (console,\n                                // alert, etc.)\n            dojo        : true, // if Dojo Toolkit globals should be predefined\n            eqeqeq      : true, // if === should be required\n            eqnull      : true, // if == null comparisons should be tolerated\n            es5         : true, // if ES5 syntax should be allowed\n            esnext      : true, // if es.next specific syntax should be allowed\n            evil        : true, // if eval should be allowed\n            expr        : true, // if ExpressionStatement should be allowed as Programs\n            forin       : true, // if for in statements must filter\n            funcscope   : true, // if only function scope should be used for scope tests\n            globalstrict: true, // if global \"use strict\"; should be allowed (also\n                                // enables 'strict')\n            immed       : true, // if immediate invocations must be wrapped in parens\n            iterator    : true, // if the `__iterator__` property should be allowed\n            jquery      : true, // if jQuery globals should be predefined\n            lastsemic   : true, // if semicolons may be ommitted for the trailing\n                                // statements inside of a one-line blocks.\n            latedef     : true, // if the use before definition should not be tolerated\n            laxbreak    : true, // if line breaks should not be checked\n            laxcomma    : true, // if line breaks should not be checked around commas\n            loopfunc    : true, // if functions should be allowed to be defined within\n                                // loops\n            mootools    : true, // if MooTools globals should be predefined\n            multistr    : true, // allow multiline strings\n            newcap      : true, // if constructor names must be capitalized\n            noarg       : true, // if arguments.caller and arguments.callee should be\n                                // disallowed\n            node        : true, // if the Node.js environment globals should be\n                                // predefined\n            noempty     : true, // if empty blocks should be disallowed\n            nonew       : true, // if using `new` for side-effects should be disallowed\n            nonstandard : true, // if non-standard (but widely adopted) globals should\n                                // be predefined\n            nomen       : true, // if names should be checked\n            onevar      : true, // if only one var statement per function should be\n                                // allowed\n            onecase     : true, // if one case switch statements should be allowed\n            passfail    : true, // if the scan should stop on first error\n            plusplus    : true, // if increment/decrement should not be allowed\n            proto       : true, // if the `__proto__` property should be allowed\n            prototypejs : true, // if Prototype and Scriptaculous globals should be\n                                // predefined\n            regexdash   : true, // if unescaped first/last dash (-) inside brackets\n                                // should be tolerated\n            regexp      : true, // if the . should not be allowed in regexp literals\n            rhino       : true, // if the Rhino environment globals should be predefined\n            undef       : true, // if variables should be declared before used\n            scripturl   : true, // if script-targeted URLs should be tolerated\n            shadow      : true, // if variable shadowing should be tolerated\n            smarttabs   : true, // if smarttabs should be tolerated\n                                // (http://www.emacswiki.org/emacs/SmartTabs)\n            strict      : true, // require the \"use strict\"; pragma\n            sub         : true, // if all forms of subscript notation are tolerated\n            supernew    : true, // if `new function () { ... };` and `new Object;`\n                                // should be tolerated\n            trailing    : true, // if trailing whitespace rules apply\n            validthis   : true, // if 'this' inside a non-constructor function is valid.\n                                // This is a function scoped option only.\n            white       : true, // if strict whitespace rules apply\n            wsh         : true  // if the Windows Scripting Host environment globals\n                                // should be predefined\n        },\n\n        // browser contains a set of global names which are commonly provided by a\n        // web browser environment.\n        browser = {\n            ArrayBuffer              :  false,\n            ArrayBufferView          :  false,\n            Audio                    :  false,\n            addEventListener         :  false,\n            applicationCache         :  false,\n            blur                     :  false,\n            clearInterval            :  false,\n            clearTimeout             :  false,\n            close                    :  false,\n            closed                   :  false,\n            DataView                 :  false,\n            defaultStatus            :  false,\n            document                 :  false,\n            event                    :  false,\n            FileReader               :  false,\n            Float32Array             :  false,\n            Float64Array             :  false,\n            FormData                 :  false,\n            focus                    :  false,\n            frames                   :  false,\n            getComputedStyle         :  false,\n            HTMLElement              :  false,\n            HTMLAnchorElement        :  false,\n            HTMLBaseElement          :  false,\n            HTMLBlockquoteElement    :  false,\n            HTMLBodyElement          :  false,\n            HTMLBRElement            :  false,\n            HTMLButtonElement        :  false,\n            HTMLCanvasElement        :  false,\n            HTMLDirectoryElement     :  false,\n            HTMLDivElement           :  false,\n            HTMLDListElement         :  false,\n            HTMLFieldSetElement      :  false,\n            HTMLFontElement          :  false,\n            HTMLFormElement          :  false,\n            HTMLFrameElement         :  false,\n            HTMLFrameSetElement      :  false,\n            HTMLHeadElement          :  false,\n            HTMLHeadingElement       :  false,\n            HTMLHRElement            :  false,\n            HTMLHtmlElement          :  false,\n            HTMLIFrameElement        :  false,\n            HTMLImageElement         :  false,\n            HTMLInputElement         :  false,\n            HTMLIsIndexElement       :  false,\n            HTMLLabelElement         :  false,\n            HTMLLayerElement         :  false,\n            HTMLLegendElement        :  false,\n            HTMLLIElement            :  false,\n            HTMLLinkElement          :  false,\n            HTMLMapElement           :  false,\n            HTMLMenuElement          :  false,\n            HTMLMetaElement          :  false,\n            HTMLModElement           :  false,\n            HTMLObjectElement        :  false,\n            HTMLOListElement         :  false,\n            HTMLOptGroupElement      :  false,\n            HTMLOptionElement        :  false,\n            HTMLParagraphElement     :  false,\n            HTMLParamElement         :  false,\n            HTMLPreElement           :  false,\n            HTMLQuoteElement         :  false,\n            HTMLScriptElement        :  false,\n            HTMLSelectElement        :  false,\n            HTMLStyleElement         :  false,\n            HTMLTableCaptionElement  :  false,\n            HTMLTableCellElement     :  false,\n            HTMLTableColElement      :  false,\n            HTMLTableElement         :  false,\n            HTMLTableRowElement      :  false,\n            HTMLTableSectionElement  :  false,\n            HTMLTextAreaElement      :  false,\n            HTMLTitleElement         :  false,\n            HTMLUListElement         :  false,\n            HTMLVideoElement         :  false,\n            history                  :  false,\n            Int16Array               :  false,\n            Int32Array               :  false,\n            Int8Array                :  false,\n            Image                    :  false,\n            length                   :  false,\n            localStorage             :  false,\n            location                 :  false,\n            moveBy                   :  false,\n            moveTo                   :  false,\n            name                     :  false,\n            navigator                :  false,\n            onbeforeunload           :  true,\n            onblur                   :  true,\n            onerror                  :  true,\n            onfocus                  :  true,\n            onload                   :  true,\n            onresize                 :  true,\n            onunload                 :  true,\n            open                     :  false,\n            openDatabase             :  false,\n            opener                   :  false,\n            Option                   :  false,\n            parent                   :  false,\n            print                    :  false,\n            removeEventListener      :  false,\n            resizeBy                 :  false,\n            resizeTo                 :  false,\n            screen                   :  false,\n            scroll                   :  false,\n            scrollBy                 :  false,\n            scrollTo                 :  false,\n            sessionStorage           :  false,\n            setInterval              :  false,\n            setTimeout               :  false,\n            SharedWorker             :  false,\n            status                   :  false,\n            top                      :  false,\n            Uint16Array              :  false,\n            Uint32Array              :  false,\n            Uint8Array               :  false,\n            WebSocket                :  false,\n            window                   :  false,\n            Worker                   :  false,\n            XMLHttpRequest           :  false,\n            XPathEvaluator           :  false,\n            XPathException           :  false,\n            XPathExpression          :  false,\n            XPathNamespace           :  false,\n            XPathNSResolver          :  false,\n            XPathResult              :  false\n        },\n\n        couch = {\n            \"require\" : false,\n            respond   : false,\n            getRow    : false,\n            emit      : false,\n            send      : false,\n            start     : false,\n            sum       : false,\n            log       : false,\n            exports   : false,\n            module    : false,\n            provides  : false\n        },\n\n        devel = {\n            alert   : false,\n            confirm : false,\n            console : false,\n            Debug   : false,\n            opera   : false,\n            prompt  : false\n        },\n\n        dojo = {\n            dojo      : false,\n            dijit     : false,\n            dojox     : false,\n            define    : false,\n            \"require\" : false\n        },\n\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label',\n            'outer', 'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n\n        global,         // The global scope\n        implied,        // Implied globals\n        inblock,\n        indent,\n        jsonmode,\n\n        jquery = {\n            '$'    : false,\n            jQuery : false\n        },\n\n        lines,\n        lookahead,\n        member,\n        membersOnly,\n\n        mootools = {\n            '$'             : false,\n            '$$'            : false,\n            Assets          : false,\n            Browser         : false,\n            Chain           : false,\n            Class           : false,\n            Color           : false,\n            Cookie          : false,\n            Core            : false,\n            Document        : false,\n            DomReady        : false,\n            DOMReady        : false,\n            Drag            : false,\n            Element         : false,\n            Elements        : false,\n            Event           : false,\n            Events          : false,\n            Fx              : false,\n            Group           : false,\n            Hash            : false,\n            HtmlTable       : false,\n            Iframe          : false,\n            IframeShim      : false,\n            InputValidator  : false,\n            instanceOf      : false,\n            Keyboard        : false,\n            Locale          : false,\n            Mask            : false,\n            MooTools        : false,\n            Native          : false,\n            Options         : false,\n            OverText        : false,\n            Request         : false,\n            Scroller        : false,\n            Slick           : false,\n            Slider          : false,\n            Sortables       : false,\n            Spinner         : false,\n            Swiff           : false,\n            Tips            : false,\n            Type            : false,\n            typeOf          : false,\n            URI             : false,\n            Window          : false\n        },\n\n        nexttoken,\n\n        node = {\n            __filename    : false,\n            __dirname     : false,\n            Buffer        : false,\n            console       : false,\n            exports       : false,\n            GLOBAL        : false,\n            global        : false,\n            module        : false,\n            process       : false,\n            require       : false,\n            setTimeout    : false,\n            clearTimeout  : false,\n            setInterval   : false,\n            clearInterval : false\n        },\n\n        noreach,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prevtoken,\n\n        prototypejs = {\n            '$'               : false,\n            '$$'              : false,\n            '$A'              : false,\n            '$F'              : false,\n            '$H'              : false,\n            '$R'              : false,\n            '$break'          : false,\n            '$continue'       : false,\n            '$w'              : false,\n            Abstract          : false,\n            Ajax              : false,\n            Class             : false,\n            Enumerable        : false,\n            Element           : false,\n            Event             : false,\n            Field             : false,\n            Form              : false,\n            Hash              : false,\n            Insertion         : false,\n            ObjectRange       : false,\n            PeriodicalExecuter: false,\n            Position          : false,\n            Prototype         : false,\n            Selector          : false,\n            Template          : false,\n            Toggle            : false,\n            Try               : false,\n            Autocompleter     : false,\n            Builder           : false,\n            Control           : false,\n            Draggable         : false,\n            Draggables        : false,\n            Droppables        : false,\n            Effect            : false,\n            Sortable          : false,\n            SortableObserver  : false,\n            Sound             : false,\n            Scriptaculous     : false\n        },\n\n        rhino = {\n            defineClass  : false,\n            deserialize  : false,\n            gc           : false,\n            help         : false,\n            importPackage: false,\n            \"java\"       : false,\n            load         : false,\n            loadClass    : false,\n            print        : false,\n            quit         : false,\n            readFile     : false,\n            readUrl      : false,\n            runCommand   : false,\n            seal         : false,\n            serialize    : false,\n            spawn        : false,\n            sync         : false,\n            toint32      : false,\n            version      : false\n        },\n\n        scope,      // The current scope\n        stack,\n\n        // standard contains the global names that are provided by the\n        // ECMAScript standard.\n        standard = {\n            Array               : false,\n            Boolean             : false,\n            Date                : false,\n            decodeURI           : false,\n            decodeURIComponent  : false,\n            encodeURI           : false,\n            encodeURIComponent  : false,\n            Error               : false,\n            'eval'              : false,\n            EvalError           : false,\n            Function            : false,\n            hasOwnProperty      : false,\n            isFinite            : false,\n            isNaN               : false,\n            JSON                : false,\n            Math                : false,\n            Number              : false,\n            Object              : false,\n            parseInt            : false,\n            parseFloat          : false,\n            RangeError          : false,\n            ReferenceError      : false,\n            RegExp              : false,\n            String              : false,\n            SyntaxError         : false,\n            TypeError           : false,\n            URIError            : false\n        },\n\n        // widely adopted global names that are not part of ECMAScript standard\n        nonstandard = {\n            escape              : false,\n            unescape            : false\n        },\n\n        standard_member = {\n            E                   : true,\n            LN2                 : true,\n            LN10                : true,\n            LOG2E               : true,\n            LOG10E              : true,\n            MAX_VALUE           : true,\n            MIN_VALUE           : true,\n            NEGATIVE_INFINITY   : true,\n            PI                  : true,\n            POSITIVE_INFINITY   : true,\n            SQRT1_2             : true,\n            SQRT2               : true\n        },\n\n        directive,\n        syntax = {},\n        tab,\n        token,\n        urls,\n        useESNextSyntax,\n        warnings,\n\n        wsh = {\n            ActiveXObject             : true,\n            Enumerator                : true,\n            GetObject                 : true,\n            ScriptEngine              : true,\n            ScriptEngineBuildVersion  : true,\n            ScriptEngineMajorVersion  : true,\n            ScriptEngineMinorVersion  : true,\n            VBArray                   : true,\n            WSH                       : true,\n            WScript                   : true,\n            XDomainRequest            : true\n        };\n\n    // Regular expressions. Some of these are stupidly long.\n    var ax, cx, tx, nx, nxg, lx, ix, jx, ft;\n    (function () {\n        /*jshint maxlen:300 */\n\n        // unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i;\n\n        // unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n\n        // token\n        tx = /^\\s*([(){}\\[.,:;'\"~\\?\\]#@]|==?=?|\\/(\\*(jshint|jslint|members?|global)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|%=?|&[&=]?|\\|[|=]?|>>?>?=?|<([\\/=!]|\\!(\\[|--)?|<=?)?|\\^=?|\\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\\.[0-9]*)?([eE][+\\-]?[0-9]+)?)/;\n\n        // characters in strings that need escapement\n        nx = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n        nxg = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n\n        // star slash\n        lx = /\\*\\/|\\/\\*/;\n\n        // identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;\n\n        // javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i;\n\n        // catches /* falls through */ comments\n        ft = /^\\s*\\/\\*\\s*falls\\sthrough\\s*\\*\\/\\s*$/;\n    }());\n\n    function F() {}     // Used by Object.create\n\n    function is_own(object, name) {\n\n// The object.hasOwnProperty method fails when the property under consideration\n// is named 'hasOwnProperty'. So we have to use this more convoluted form.\n\n        return Object.prototype.hasOwnProperty.call(object, name);\n    }\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (typeof Object.create !== 'function') {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var a = [], k;\n            for (k in o) {\n                if (is_own(o, k)) {\n                    a.push(k);\n                }\n            }\n            return a;\n        };\n    }\n\n// Non standard methods\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var r = o[b];\n                return typeof r === 'string' || typeof r === 'number' ? r : a;\n            });\n        };\n    }\n\n    if (typeof String.prototype.name !== 'function') {\n        String.prototype.name = function () {\n\n// If the string looks like an identifier, then we can return it as is.\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can simply slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe\n// sequences.\n\n            if (ix.test(this)) {\n                return this;\n            }\n            if (nx.test(this)) {\n                return '\"' + this.replace(nxg, function (a) {\n                    var c = escapes[a];\n                    if (c) {\n                        return c;\n                    }\n                    return '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n                }) + '\"';\n            }\n            return '\"' + this + '\"';\n        };\n    }\n\n\n    function combine(t, o) {\n        var n;\n        for (n in o) {\n            if (is_own(o, n)) {\n                t[n] = o[n];\n            }\n        }\n    }\n\n    function assume() {\n        if (option.couch) {\n            combine(predefined, couch);\n        }\n\n        if (option.rhino) {\n            combine(predefined, rhino);\n        }\n\n        if (option.prototypejs) {\n            combine(predefined, prototypejs);\n        }\n\n        if (option.node) {\n            combine(predefined, node);\n        }\n\n        if (option.devel) {\n            combine(predefined, devel);\n        }\n\n        if (option.dojo) {\n            combine(predefined, dojo);\n        }\n\n        if (option.browser) {\n            combine(predefined, browser);\n        }\n\n        if (option.nonstandard) {\n            combine(predefined, nonstandard);\n        }\n\n        if (option.jquery) {\n            combine(predefined, jquery);\n        }\n\n        if (option.mootools) {\n            combine(predefined, mootools);\n        }\n\n        if (option.wsh) {\n            combine(predefined, wsh);\n        }\n\n        if (option.esnext) {\n            useESNextSyntax();\n        }\n\n        if (option.globalstrict && option.strict !== false) {\n            option.strict = true;\n        }\n    }\n\n\n    // Produce an error warning.\n    function quit(message, line, chr) {\n        var percentage = Math.floor((line / lines.length) * 100);\n\n        throw {\n            name: 'JSHintError',\n            line: line,\n            character: chr,\n            message: message + \" (\" + percentage + \"% scanned).\",\n            raw: message\n        };\n    }\n\n    function isundef(scope, m, t, a) {\n        return JSHINT.undefs.push([scope, m, t, a]);\n    }\n\n    function warning(m, t, a, b, c, d) {\n        var ch, l, w;\n        t = t || nexttoken;\n        if (t.id === '(end)') {  // `~\n            t = token;\n        }\n        l = t.line || 0;\n        ch = t.from || 0;\n        w = {\n            id: '(error)',\n            raw: m,\n            evidence: lines[l - 1] || '',\n            line: l,\n            character: ch,\n            a: a,\n            b: b,\n            c: c,\n            d: d\n        };\n        w.reason = m.supplant(w);\n        JSHINT.errors.push(w);\n        if (option.passfail) {\n            quit('Stopping. ', l, ch);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(\"Too many errors.\", l, ch);\n        }\n        return w;\n    }\n\n    function warningAt(m, l, ch, a, b, c, d) {\n        return warning(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n    function error(m, t, a, b, c, d) {\n        var w = warning(m, t, a, b, c, d);\n    }\n\n    function errorAt(m, l, ch, a, b, c, d) {\n        return error(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n\n\n// lexical analysis and token construction\n\n    var lex = (function lex() {\n        var character, from, line, s;\n\n// Private lex methods\n\n        function nextLine() {\n            var at,\n                tw; // trailing whitespace check\n\n            if (line >= lines.length)\n                return false;\n\n            character = 1;\n            s = lines[line];\n            line += 1;\n\n            // If smarttabs option is used check for spaces followed by tabs only.\n            // Otherwise check for any occurence of mixed tabs and spaces.\n            if (option.smarttabs)\n                at = s.search(/ \\t/);\n            else\n                at = s.search(/ \\t|\\t /);\n\n            if (at >= 0)\n                warningAt(\"Mixed spaces and tabs.\", line, at + 1);\n\n            s = s.replace(/\\t/g, tab);\n            at = s.search(cx);\n\n            if (at >= 0)\n                warningAt(\"Unsafe character.\", line, at);\n\n            if (option.maxlen && option.maxlen < s.length)\n                warningAt(\"Line too long.\", line, s.length);\n\n            // Check for trailing whitespaces\n            tw = /\\s+$/.test(s);\n            if (option.trailing && tw && !/^\\s+$/.test(s)) {\n                warningAt(\"Trailing whitespace.\", line, tw);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var i, t;\n            if (type === '(color)' || type === '(range)') {\n                t = {type: type};\n            } else if (type === '(punctuator)' ||\n                    (type === '(identifier)' && is_own(syntax, value))) {\n                t = syntax[value] || syntax['(error)'];\n            } else {\n                t = syntax[type];\n            }\n            t = Object.create(t);\n            if (type === '(string)' || type === '(range)') {\n                if (!option.scripturl && jx.test(value)) {\n                    warningAt(\"Script URL.\", line, from);\n                }\n            }\n            if (type === '(identifier)') {\n                t.identifier = true;\n                if (value === '__proto__' && !option.proto) {\n                    warningAt(\"The '{a}' property is deprecated.\",\n                        line, from, value);\n                } else if (value === '__iterator__' && !option.iterator) {\n                    warningAt(\"'{a}' is only available in JavaScript 1.7.\",\n                        line, from, value);\n                } else if (option.nomen && (value.charAt(0) === '_' ||\n                         value.charAt(value.length - 1) === '_')) {\n                    if (!option.node || token.id === '.' ||\n                            (value !== '__dirname' && value !== '__filename')) {\n                        warningAt(\"Unexpected {a} in '{b}'.\", line, from, \"dangling '_'\", value);\n                    }\n                }\n            }\n            t.value = value;\n            t.line = line;\n            t.character = character;\n            t.from = from;\n            i = t.id;\n            if (i !== '(endline)') {\n                prereg = i &&\n                    (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) ||\n                    i === 'return' ||\n                    i === 'case');\n            }\n            return t;\n        }\n\n        // Public lex methods\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source\n                        .replace(/\\r\\n/g, '\\n')\n                        .replace(/\\r/g, '\\n')\n                        .split('\\n');\n                } else {\n                    lines = source;\n                }\n\n                // If the first line is a shebang (#!), make it a blank and move on.\n                // Shebangs are used by Node scripts.\n                if (lines[0] && lines[0].substr(0, 2) === '#!')\n                    lines[0] = '';\n\n                line = 0;\n                nextLine();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (s.charAt(0) !== begin) {\n                    errorAt(\"Expected '{a}' and instead saw '{b}'.\",\n                            line, character, begin, s.charAt(0));\n                }\n                for (;;) {\n                    s = s.slice(1);\n                    character += 1;\n                    c = s.charAt(0);\n                    switch (c) {\n                    case '':\n                        errorAt(\"Missing '{a}'.\", line, character, c);\n                        break;\n                    case end:\n                        s = s.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case '\\\\':\n                        warningAt(\"Unexpected '{a}'.\", line, character, c);\n                    }\n                    value += c;\n                }\n\n            },\n\n\n            // token -- this is called by advance to get the next token\n            token: function () {\n                var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange;\n\n                function match(x) {\n                    var r = x.exec(s), r1;\n                    if (r) {\n                        l = r[0].length;\n                        r1 = r[1];\n                        c = r1.charAt(0);\n                        s = s.substr(l);\n                        from = character + l - r1.length;\n                        character += l;\n                        return r1;\n                    }\n                }\n\n                function string(x) {\n                    var c, j, r = '', allowNewLine = false;\n\n                    if (jsonmode && x !== '\"') {\n                        warningAt(\"Strings must use doublequote.\",\n                                line, character);\n                    }\n\n                    function esc(n) {\n                        var i = parseInt(s.substr(j + 1, n), 16);\n                        j += n;\n                        if (i >= 32 && i <= 126 &&\n                                i !== 34 && i !== 92 && i !== 39) {\n                            warningAt(\"Unnecessary escapement.\", line, character);\n                        }\n                        character += n;\n                        c = String.fromCharCode(i);\n                    }\n                    j = 0;\nunclosedString:     for (;;) {\n                        while (j >= s.length) {\n                            j = 0;\n\n                            var cl = line, cf = from;\n                            if (!nextLine()) {\n                                errorAt(\"Unclosed string.\", cl, cf);\n                                break unclosedString;\n                            }\n\n                            if (allowNewLine) {\n                                allowNewLine = false;\n                            } else {\n                                warningAt(\"Unclosed string.\", cl, cf);\n                            }\n                        }\n                        c = s.charAt(j);\n                        if (c === x) {\n                            character += 1;\n                            s = s.substr(j + 1);\n                            return it('(string)', r, x);\n                        }\n                        if (c < ' ') {\n                            if (c === '\\n' || c === '\\r') {\n                                break;\n                            }\n                            warningAt(\"Control character in string: {a}.\",\n                                    line, character + j, s.slice(0, j));\n                        } else if (c === '\\\\') {\n                            j += 1;\n                            character += 1;\n                            c = s.charAt(j);\n                            switch (c) {\n                            case '\\\\':\n                            case '\"':\n                            case '/':\n                                break;\n                            case '\\'':\n                                if (jsonmode) {\n                                    warningAt(\"Avoid \\\\'.\", line, character);\n                                }\n                                break;\n                            case 'b':\n                                c = '\\b';\n                                break;\n                            case 'f':\n                                c = '\\f';\n                                break;\n                            case 'n':\n                                c = '\\n';\n                                break;\n                            case 'r':\n                                c = '\\r';\n                                break;\n                            case 't':\n                                c = '\\t';\n                                break;\n                            case 'u':\n                                esc(4);\n                                break;\n                            case 'v':\n                                if (jsonmode) {\n                                    warningAt(\"Avoid \\\\v.\", line, character);\n                                }\n                                c = '\\v';\n                                break;\n                            case 'x':\n                                if (jsonmode) {\n                                    warningAt(\"Avoid \\\\x-.\", line, character);\n                                }\n                                esc(2);\n                                break;\n                            case '':\n                                // last character is escape character\n                                // always allow new line if escaped, but show\n                                // warning if option is not set\n                                allowNewLine = true;\n                                if (option.multistr) {\n                                    if (jsonmode) {\n                                        warningAt(\"Avoid EOL escapement.\", line, character);\n                                    }\n                                    c = '';\n                                    character -= 1;\n                                    break;\n                                }\n                                warningAt(\"Bad escapement of EOL. Use option multistr if needed.\",\n                                    line, character);\n                                break;\n                            default:\n                                warningAt(\"Bad escapement.\", line, character);\n                            }\n                        }\n                        r += c;\n                        character += 1;\n                        j += 1;\n                    }\n                }\n\n                for (;;) {\n                    if (!s) {\n                        return it(nextLine() ? '(endline)' : '(end)', '');\n                    }\n                    t = match(tx);\n                    if (!t) {\n                        t = '';\n                        c = '';\n                        while (s && s < '!') {\n                            s = s.substr(1);\n                        }\n                        if (s) {\n                            errorAt(\"Unexpected '{a}'.\", line, character, s.substr(0, 1));\n                            s = '';\n                        }\n                    } else {\n\n    //      identifier\n\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', t);\n                        }\n\n    //      number\n\n                        if (c.isDigit()) {\n                            if (!isFinite(Number(t))) {\n                                warningAt(\"Bad number '{a}'.\",\n                                    line, character, t);\n                            }\n                            if (s.substr(0, 1).isAlpha()) {\n                                warningAt(\"Missing space after '{a}'.\",\n                                        line, character, t);\n                            }\n                            if (c === '0') {\n                                d = t.substr(1, 1);\n                                if (d.isDigit()) {\n                                    if (token.id !== '.') {\n                                        warningAt(\"Don't use extra leading zeros '{a}'.\",\n                                            line, character, t);\n                                    }\n                                } else if (jsonmode && (d === 'x' || d === 'X')) {\n                                    warningAt(\"Avoid 0x-. '{a}'.\",\n                                            line, character, t);\n                                }\n                            }\n                            if (t.substr(t.length - 1) === '.') {\n                                warningAt(\n\"A trailing decimal point can be confused with a dot '{a}'.\", line, character, t);\n                            }\n                            return it('(number)', t);\n                        }\n                        switch (t) {\n\n    //      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(t);\n\n    //      // comment\n\n                        case '//':\n                            s = '';\n                            token.comment = true;\n                            break;\n\n    //      /* comment\n\n                        case '/*':\n                            for (;;) {\n                                i = s.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                if (!nextLine()) {\n                                    errorAt(\"Unclosed comment.\", line, character);\n                                }\n                            }\n                            character += i + 2;\n                            if (s.substr(i, 1) === '/') {\n                                errorAt(\"Nested comment.\", line, character);\n                            }\n                            s = s.substr(i + 2);\n                            token.comment = true;\n                            break;\n\n    //      /*members /*jshint /*global\n\n                        case '/*members':\n                        case '/*member':\n                        case '/*jshint':\n                        case '/*jslint':\n                        case '/*global':\n                        case '*/':\n                            return {\n                                value: t,\n                                type: 'special',\n                                line: line,\n                                character: character,\n                                from: from\n                            };\n\n                        case '':\n                            break;\n    //      /\n                        case '/':\n                            if (token.id === '/=') {\n                                errorAt(\"A regular expression literal can be confused with '/='.\",\n                                    line, from);\n                            }\n                            if (prereg) {\n                                depth = 0;\n                                captures = 0;\n                                l = 0;\n                                for (;;) {\n                                    b = true;\n                                    c = s.charAt(l);\n                                    l += 1;\n                                    switch (c) {\n                                    case '':\n                                        errorAt(\"Unclosed regular expression.\", line, from);\n                                        return quit('Stopping.', line, from);\n                                    case '/':\n                                        if (depth > 0) {\n                                            warningAt(\"{a} unterminated regular expression \" +\n                                                \"group(s).\", line, from + l, depth);\n                                        }\n                                        c = s.substr(0, l - 1);\n                                        q = {\n                                            g: true,\n                                            i: true,\n                                            m: true\n                                        };\n                                        while (q[s.charAt(l)] === true) {\n                                            q[s.charAt(l)] = false;\n                                            l += 1;\n                                        }\n                                        character += l;\n                                        s = s.substr(l);\n                                        q = s.charAt(0);\n                                        if (q === '/' || q === '*') {\n                                            errorAt(\"Confusing regular expression.\",\n                                                    line, from);\n                                        }\n                                        return it('(regexp)', c);\n                                    case '\\\\':\n                                        c = s.charAt(l);\n                                        if (c < ' ') {\n                                            warningAt(\n\"Unexpected control character in regular expression.\", line, from + l);\n                                        } else if (c === '<') {\n                                            warningAt(\n\"Unexpected escaped character '{a}' in regular expression.\", line, from + l, c);\n                                        }\n                                        l += 1;\n                                        break;\n                                    case '(':\n                                        depth += 1;\n                                        b = false;\n                                        if (s.charAt(l) === '?') {\n                                            l += 1;\n                                            switch (s.charAt(l)) {\n                                            case ':':\n                                            case '=':\n                                            case '!':\n                                                l += 1;\n                                                break;\n                                            default:\n                                                warningAt(\n\"Expected '{a}' and instead saw '{b}'.\", line, from + l, ':', s.charAt(l));\n                                            }\n                                        } else {\n                                            captures += 1;\n                                        }\n                                        break;\n                                    case '|':\n                                        b = false;\n                                        break;\n                                    case ')':\n                                        if (depth === 0) {\n                                            warningAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, ')');\n                                        } else {\n                                            depth -= 1;\n                                        }\n                                        break;\n                                    case ' ':\n                                        q = 1;\n                                        while (s.charAt(l) === ' ') {\n                                            l += 1;\n                                            q += 1;\n                                        }\n                                        if (q > 1) {\n                                            warningAt(\n\"Spaces are hard to count. Use {{a}}.\", line, from + l, q);\n                                        }\n                                        break;\n                                    case '[':\n                                        c = s.charAt(l);\n                                        if (c === '^') {\n                                            l += 1;\n                                            if (option.regexp) {\n                                                warningAt(\"Insecure '{a}'.\",\n                                                        line, from + l, c);\n                                            } else if (s.charAt(l) === ']') {\n                                                errorAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, '^');\n                                            }\n                                        }\n                                        if (c === ']') {\n                                            warningAt(\"Empty class.\", line,\n                                                    from + l - 1);\n                                        }\n                                        isLiteral = false;\n                                        isInRange = false;\nklass:                                  do {\n                                            c = s.charAt(l);\n                                            l += 1;\n                                            switch (c) {\n                                            case '[':\n                                            case '^':\n                                                warningAt(\"Unescaped '{a}'.\",\n                                                        line, from + l, c);\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case '-':\n                                                if (isLiteral && !isInRange) {\n                                                    isLiteral = false;\n                                                    isInRange = true;\n                                                } else if (isInRange) {\n                                                    isInRange = false;\n                                                } else if (s.charAt(l) === ']') {\n                                                    isInRange = true;\n                                                } else {\n                                                    if (option.regexdash !== (l === 2 || (l === 3 &&\n                                                        s.charAt(1) === '^'))) {\n                                                        warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l - 1, '-');\n                                                    }\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case ']':\n                                                if (isInRange && !option.regexdash) {\n                                                    warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l - 1, '-');\n                                                }\n                                                break klass;\n                                            case '\\\\':\n                                                c = s.charAt(l);\n                                                if (c < ' ') {\n                                                    warningAt(\n\"Unexpected control character in regular expression.\", line, from + l);\n                                                } else if (c === '<') {\n                                                    warningAt(\n\"Unexpected escaped character '{a}' in regular expression.\", line, from + l, c);\n                                                }\n                                                l += 1;\n\n                                                // \\w, \\s and \\d are never part of a character range\n                                                if (/[wsd]/i.test(c)) {\n                                                    if (isInRange) {\n                                                        warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l, '-');\n                                                        isInRange = false;\n                                                    }\n                                                    isLiteral = false;\n                                                } else if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case '/':\n                                                warningAt(\"Unescaped '{a}'.\",\n                                                        line, from + l - 1, '/');\n\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case '<':\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            default:\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                            }\n                                        } while (c);\n                                        break;\n                                    case '.':\n                                        if (option.regexp) {\n                                            warningAt(\"Insecure '{a}'.\", line,\n                                                    from + l, c);\n                                        }\n                                        break;\n                                    case ']':\n                                    case '?':\n                                    case '{':\n                                    case '}':\n                                    case '+':\n                                    case '*':\n                                        warningAt(\"Unescaped '{a}'.\", line,\n                                                from + l, c);\n                                    }\n                                    if (b) {\n                                        switch (s.charAt(l)) {\n                                        case '?':\n                                        case '+':\n                                        case '*':\n                                            l += 1;\n                                            if (s.charAt(l) === '?') {\n                                                l += 1;\n                                            }\n                                            break;\n                                        case '{':\n                                            l += 1;\n                                            c = s.charAt(l);\n                                            if (c < '0' || c > '9') {\n                                                warningAt(\n\"Expected a number and instead saw '{a}'.\", line, from + l, c);\n                                            }\n                                            l += 1;\n                                            low = +c;\n                                            for (;;) {\n                                                c = s.charAt(l);\n                                                if (c < '0' || c > '9') {\n                                                    break;\n                                                }\n                                                l += 1;\n                                                low = +c + (low * 10);\n                                            }\n                                            high = low;\n                                            if (c === ',') {\n                                                l += 1;\n                                                high = Infinity;\n                                                c = s.charAt(l);\n                                                if (c >= '0' && c <= '9') {\n                                                    l += 1;\n                                                    high = +c;\n                                                    for (;;) {\n                                                        c = s.charAt(l);\n                                                        if (c < '0' || c > '9') {\n                                                            break;\n                                                        }\n                                                        l += 1;\n                                                        high = +c + (high * 10);\n                                                    }\n                                                }\n                                            }\n                                            if (s.charAt(l) !== '}') {\n                                                warningAt(\n\"Expected '{a}' and instead saw '{b}'.\", line, from + l, '}', c);\n                                            } else {\n                                                l += 1;\n                                            }\n                                            if (s.charAt(l) === '?') {\n                                                l += 1;\n                                            }\n                                            if (low > high) {\n                                                warningAt(\n\"'{a}' should not be greater than '{b}'.\", line, from + l, low, high);\n                                            }\n                                        }\n                                    }\n                                }\n                                c = s.substr(0, l - 1);\n                                character += l;\n                                s = s.substr(l);\n                                return it('(regexp)', c);\n                            }\n                            return it('(punctuator)', t);\n\n    //      punctuator\n\n                        case '#':\n                            return it('(punctuator)', t);\n                        default:\n                            return it('(punctuator)', t);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function addlabel(t, type) {\n\n        if (t === 'hasOwnProperty') {\n            warning(\"'hasOwnProperty' is a really bad name.\");\n        }\n\n// Define t in the current function in the current scope.\n        if (is_own(funct, t) && !funct['(global)']) {\n            if (funct[t] === true) {\n                if (option.latedef)\n                    warning(\"'{a}' was used before it was defined.\", nexttoken, t);\n            } else {\n                if (!option.shadow && type !== \"exception\")\n                    warning(\"'{a}' is already defined.\", nexttoken, t);\n            }\n        }\n\n        funct[t] = type;\n        if (funct['(global)']) {\n            global[t] = funct;\n            if (is_own(implied, t)) {\n                if (option.latedef)\n                    warning(\"'{a}' was used before it was defined.\", nexttoken, t);\n                delete implied[t];\n            }\n        } else {\n            scope[t] = funct;\n        }\n    }\n\n\n    function doOption() {\n        var b, obj, filter, o = nexttoken.value, t, v;\n        switch (o) {\n        case '*/':\n            error(\"Unbegun comment.\");\n            break;\n        case '/*members':\n        case '/*member':\n            o = '/*members';\n            if (!membersOnly) {\n                membersOnly = {};\n            }\n            obj = membersOnly;\n            break;\n        case '/*jshint':\n        case '/*jslint':\n            obj = option;\n            filter = boolOptions;\n            break;\n        case '/*global':\n            obj = predefined;\n            break;\n        default:\n            error(\"What?\");\n        }\n        t = lex.token();\nloop:   for (;;) {\n            for (;;) {\n                if (t.type === 'special' && t.value === '*/') {\n                    break loop;\n                }\n                if (t.id !== '(endline)' && t.id !== ',') {\n                    break;\n                }\n                t = lex.token();\n            }\n            if (t.type !== '(string)' && t.type !== '(identifier)' &&\n                    o !== '/*members') {\n                error(\"Bad option.\", t);\n            }\n            v = lex.token();\n            if (v.id === ':') {\n                v = lex.token();\n                if (obj === membersOnly) {\n                    error(\"Expected '{a}' and instead saw '{b}'.\",\n                            t, '*/', ':');\n                }\n                if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.white = true;\n                    obj.indent = b;\n                } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.maxerr = b;\n                } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.maxlen = b;\n                } else if (t.value === 'validthis') {\n                    if (funct['(global)']) {\n                        error(\"Option 'validthis' can't be used in a global scope.\");\n                    } else {\n                        if (v.value === 'true' || v.value === 'false')\n                            obj[t.value] = v.value === 'true';\n                        else\n                            error(\"Bad option value.\", v);\n                    }\n                } else if (v.value === 'true') {\n                    obj[t.value] = true;\n                } else if (v.value === 'false') {\n                    obj[t.value] = false;\n                } else {\n                    error(\"Bad option value.\", v);\n                }\n                t = lex.token();\n            } else {\n                if (o === '/*jshint' || o === '/*jslint') {\n                    error(\"Missing option value.\", t);\n                }\n                obj[t.value] = false;\n                t = v;\n            }\n        }\n        if (filter) {\n            assume();\n        }\n    }\n\n\n// We need a peek function. If it has an argument, it peeks that much farther\n// ahead. It is used to distinguish\n//     for ( var i in ...\n// from\n//     for ( var i = ...\n\n    function peek(p) {\n        var i = p || 0, j = 0, t;\n\n        while (j <= i) {\n            t = lookahead[j];\n            if (!t) {\n                t = lookahead[j] = lex.token();\n            }\n            j += 1;\n        }\n        return t;\n    }\n\n\n\n// Produce the next token. It looks for programming errors.\n\n    function advance(id, t) {\n        switch (token.id) {\n        case '(number)':\n            if (nexttoken.id === '.') {\n                warning(\"A dot following a number can be confused with a decimal point.\", token);\n            }\n            break;\n        case '-':\n            if (nexttoken.id === '-' || nexttoken.id === '--') {\n                warning(\"Confusing minusses.\");\n            }\n            break;\n        case '+':\n            if (nexttoken.id === '+' || nexttoken.id === '++') {\n                warning(\"Confusing plusses.\");\n            }\n            break;\n        }\n\n        if (token.type === '(string)' || token.identifier) {\n            anonname = token.value;\n        }\n\n        if (id && nexttoken.id !== id) {\n            if (t) {\n                if (nexttoken.id === '(end)') {\n                    warning(\"Unmatched '{a}'.\", t, t.id);\n                } else {\n                    warning(\"Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.\",\n                            nexttoken, id, t.id, t.line, nexttoken.value);\n                }\n            } else if (nexttoken.type !== '(identifier)' ||\n                            nexttoken.value !== id) {\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, id, nexttoken.value);\n            }\n        }\n\n        prevtoken = token;\n        token = nexttoken;\n        for (;;) {\n            nexttoken = lookahead.shift() || lex.token();\n            if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {\n                return;\n            }\n            if (nexttoken.type === 'special') {\n                doOption();\n            } else {\n                if (nexttoken.id !== '(endline)') {\n                    break;\n                }\n            }\n        }\n    }\n\n\n// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n        var left, isArray = false;\n\n        if (nexttoken.id === '(end)')\n            error(\"Unexpected early end of program.\", token);\n\n        advance();\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.value;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (nexttoken.type === '(number)' && token.id === '.') {\n                    warning(\"A leading decimal point can be confused with a dot: '.{a}'.\",\n                            token, nexttoken.value);\n                    advance();\n                    return token;\n                } else {\n                    error(\"Expected an identifier and instead saw '{a}'.\",\n                            token, token.id);\n                }\n            }\n            while (rbp < nexttoken.lbp) {\n                isArray = token.value === 'Array';\n                advance();\n                if (isArray && token.id === '(' && nexttoken.id === ')')\n                    warning(\"Use the array literal notation [].\", token);\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    error(\"Expected an operator and instead saw '{a}'.\",\n                        token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functions for conformance of style.\n\n    function adjacent(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white) {\n            if (left.character !== right.from && left.line === right.line) {\n                left.from += (left.character - left.from);\n                warning(\"Unexpected space after '{a}'.\", left, left.value);\n            }\n        }\n    }\n\n    function nobreak(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white && (left.character !== right.from || left.line !== right.line)) {\n            warning(\"Unexpected space before '{a}'.\", right, right.value);\n        }\n    }\n\n    function nospace(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white && !left.comment) {\n            if (left.line === right.line) {\n                adjacent(left, right);\n            }\n        }\n    }\n\n    function nonadjacent(left, right) {\n        if (option.white) {\n            left = left || token;\n            right = right || nexttoken;\n            if (left.line === right.line && left.character === right.from) {\n                left.from += (left.character - left.from);\n                warning(\"Missing space after '{a}'.\",\n                        left, left.value);\n            }\n        }\n    }\n\n    function nobreaknonadjacent(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (!option.laxbreak && left.line !== right.line) {\n            warning(\"Bad line breaking before '{a}'.\", right, right.id);\n        } else if (option.white) {\n            left = left || token;\n            right = right || nexttoken;\n            if (left.character === right.from) {\n                left.from += (left.character - left.from);\n                warning(\"Missing space after '{a}'.\",\n                        left, left.value);\n            }\n        }\n    }\n\n    function indentation(bias) {\n        var i;\n        if (option.white && nexttoken.id !== '(end)') {\n            i = indent + (bias || 0);\n            if (nexttoken.from !== i) {\n                warning(\n\"Expected '{a}' to have an indentation at {b} instead at {c}.\",\n                        nexttoken, nexttoken.value, i, nexttoken.from);\n            }\n        }\n    }\n\n    function nolinebreak(t) {\n        t = t || token;\n        if (t.line !== nexttoken.line) {\n            warning(\"Line breaking error '{a}'.\", t, t.value);\n        }\n    }\n\n\n    function comma() {\n        if (token.line !== nexttoken.line) {\n            if (!option.laxcomma) {\n                if (comma.first) {\n                    warning(\"Comma warnings can be turned off with 'laxcomma'\");\n                    comma.first = false;\n                }\n                warning(\"Bad line breaking before '{a}'.\", token, nexttoken.id);\n            }\n        } else if (!token.comment && token.character !== nexttoken.from && option.white) {\n            token.from += (token.character - token.from);\n            warning(\"Unexpected space after '{a}'.\", token, token.value);\n        }\n        advance(',');\n        nonadjacent(token, nexttoken);\n    }\n\n    comma.first = true;\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p,\n                value: s\n            };\n        }\n        return x;\n    }\n\n\n    function delim(s) {\n        return symbol(s, 0);\n    }\n\n\n    function stmt(s, f) {\n        var x = delim(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n\n    function blockstmt(s, f) {\n        var x = stmt(s, f);\n        x.block = true;\n        return x;\n    }\n\n\n    function reserveName(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserveName(x);\n        x.nud = (typeof f === 'function') ? f : function () {\n            this.right = expression(150);\n            this.arity = 'unary';\n            if (this.id === '++' || this.id === '--') {\n                if (option.plusplus) {\n                    warning(\"Unexpected use of '{a}'.\", this, this.id);\n                } else if ((!this.right.identifier || this.right.reserved) &&\n                        this.right.id !== '.' && this.right.id !== '[') {\n                    warning(\"Bad operand.\", this);\n                }\n            }\n            return this;\n        };\n        return x;\n    }\n\n\n    function type(s, f) {\n        var x = delim(s);\n        x.type = s;\n        x.nud = f;\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = type(s, f);\n        x.identifier = x.reserved = true;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, f, p, w) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = function (left) {\n            if (!w) {\n                nobreaknonadjacent(prevtoken, token);\n                nonadjacent(token, nexttoken);\n            }\n            if (s === \"in\" && left.id === \"!\") {\n                warning(\"Confusing use of '{a}'.\", left, '!');\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            } else {\n                this.left = left;\n                this.right = expression(p);\n                return this;\n            }\n        };\n        return x;\n    }\n\n\n    function relation(s, f) {\n        var x = symbol(s, 100);\n        x.led = function (left) {\n            nobreaknonadjacent(prevtoken, token);\n            nonadjacent(token, nexttoken);\n            var right = expression(100);\n            if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) {\n                warning(\"Use the isNaN function to compare with NaN.\", this);\n            } else if (f) {\n                f.apply(this, [left, right]);\n            }\n            if (left.id === '!') {\n                warning(\"Confusing use of '{a}'.\", left, '!');\n            }\n            if (right.id === '!') {\n                warning(\"Confusing use of '{a}'.\", right, '!');\n            }\n            this.left = left;\n            this.right = right;\n            return this;\n        };\n        return x;\n    }\n\n\n    function isPoorRelation(node) {\n        return node &&\n              ((node.type === '(number)' && +node.value === 0) ||\n               (node.type === '(string)' && node.value === '') ||\n               (node.type === 'null' && !option.eqnull) ||\n                node.type === 'true' ||\n                node.type === 'false' ||\n                node.type === 'undefined');\n    }\n\n\n    function assignop(s, f) {\n        symbol(s, 20).exps = true;\n        return infix(s, function (left, that) {\n            var l;\n            that.left = left;\n            if (predefined[left.value] === false &&\n                    scope[left.value]['(global)'] === true) {\n                warning(\"Read only.\", left);\n            } else if (left['function']) {\n                warning(\"'{a}' is a function.\", left, left.value);\n            }\n            if (left) {\n                if (option.esnext && funct[left.value] === 'const') {\n                    warning(\"Attempting to override '{a}' which is a constant\", left, left.value);\n                }\n                if (left.id === '.' || left.id === '[') {\n                    if (!left.left || left.left.value === 'arguments') {\n                        warning('Bad assignment.', that);\n                    }\n                    that.right = expression(19);\n                    return that;\n                } else if (left.identifier && !left.reserved) {\n                    if (funct[left.value] === 'exception') {\n                        warning(\"Do not assign to the exception parameter.\", left);\n                    }\n                    that.right = expression(19);\n                    return that;\n                }\n                if (left === syntax['function']) {\n                    warning(\n\"Expected an identifier in an assignment and instead saw a function invocation.\",\n                                token);\n                }\n            }\n            error(\"Bad assignment.\", that);\n        }, 20);\n    }\n\n\n    function bitwise(s, f, p) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = (typeof f === 'function') ? f : function (left) {\n            if (option.bitwise) {\n                warning(\"Unexpected use of '{a}'.\", this, this.id);\n            }\n            this.left = left;\n            this.right = expression(p);\n            return this;\n        };\n        return x;\n    }\n\n\n    function bitwiseassignop(s) {\n        symbol(s, 20).exps = true;\n        return infix(s, function (left, that) {\n            if (option.bitwise) {\n                warning(\"Unexpected use of '{a}'.\", that, that.id);\n            }\n            nonadjacent(prevtoken, token);\n            nonadjacent(token, nexttoken);\n            if (left) {\n                if (left.id === '.' || left.id === '[' ||\n                        (left.identifier && !left.reserved)) {\n                    expression(19);\n                    return that;\n                }\n                if (left === syntax['function']) {\n                    warning(\n\"Expected an identifier in an assignment, and instead saw a function invocation.\",\n                                token);\n                }\n                return that;\n            }\n            error(\"Bad assignment.\", that);\n        }, 20);\n    }\n\n\n    function suffix(s, f) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            if (option.plusplus) {\n                warning(\"Unexpected use of '{a}'.\", this, this.id);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warning(\"Bad operand.\", this);\n            }\n            this.left = left;\n            return this;\n        };\n        return x;\n    }\n\n\n    // fnparam means that this identifier is being defined as a function\n    // argument (see identifier())\n    function optionalidentifier(fnparam) {\n        if (nexttoken.identifier) {\n            advance();\n            if (token.reserved && !option.es5) {\n                // `undefined` as a function param is a common pattern to protect\n                // against the case when somebody does `undefined = true` and\n                // help with minification. More info: https://gist.github.com/315916\n                if (!fnparam || token.value !== 'undefined') {\n                    warning(\"Expected an identifier and instead saw '{a}' (a reserved word).\",\n                            token, token.id);\n                }\n            }\n            return token.value;\n        }\n    }\n\n    // fnparam means that this identifier is being defined as a function\n    // argument\n    function identifier(fnparam) {\n        var i = optionalidentifier(fnparam);\n        if (i) {\n            return i;\n        }\n        if (token.id === 'function' && nexttoken.id === '(') {\n            warning(\"Missing name in function declaration.\");\n        } else {\n            error(\"Expected an identifier and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n        }\n    }\n\n\n    function reachable(s) {\n        var i = 0, t;\n        if (nexttoken.id !== ';' || noreach) {\n            return;\n        }\n        for (;;) {\n            t = peek(i);\n            if (t.reach) {\n                return;\n            }\n            if (t.id !== '(endline)') {\n                if (t.id === 'function') {\n                    if (!option.latedef) {\n                        break;\n                    }\n                    warning(\n\"Inner functions should be listed at the top of the outer function.\", t);\n                    break;\n                }\n                warning(\"Unreachable '{a}' after '{b}'.\", t, t.value, s);\n                break;\n            }\n            i += 1;\n        }\n    }\n\n\n    function statement(noindent) {\n        var i = indent, r, s = scope, t = nexttoken;\n\n        if (t.id === \";\") {\n            advance(\";\");\n            return;\n        }\n\n// Is this a labelled statement?\n\n        if (t.identifier && !t.reserved && peek().id === ':') {\n            advance();\n            advance(':');\n            scope = Object.create(s);\n            addlabel(t.value, 'label');\n            if (!nexttoken.labelled) {\n                warning(\"Label '{a}' on {b} statement.\",\n                        nexttoken, t.value, nexttoken.value);\n            }\n            if (jx.test(t.value + ':')) {\n                warning(\"Label '{a}' looks like a javascript url.\",\n                        t, t.value);\n            }\n            nexttoken.label = t.value;\n            t = nexttoken;\n        }\n\n// Parse the statement.\n\n        if (!noindent) {\n            indentation();\n        }\n        r = expression(0, true);\n\n        // Look for the final semicolon.\n        if (!t.block) {\n            if (!option.expr && (!r || !r.exps)) {\n                warning(\"Expected an assignment or function call and instead saw an expression.\",\n                    token);\n            } else if (option.nonew && r.id === '(' && r.left.id === 'new') {\n                warning(\"Do not use 'new' for side effects.\");\n            }\n\n            if (nexttoken.id !== ';') {\n                if (!option.asi) {\n                    // If this is the last statement in a block that ends on\n                    // the same line *and* option lastsemic is on, ignore the warning.\n                    // Otherwise, complain about missing semicolon.\n                    if (!option.lastsemic || nexttoken.id !== '}' ||\n                            nexttoken.line !== token.line) {\n                        warningAt(\"Missing semicolon.\", token.line, token.character);\n                    }\n                }\n            } else {\n                adjacent(token, nexttoken);\n                advance(';');\n                nonadjacent(token, nexttoken);\n            }\n        }\n\n// Restore the indentation.\n\n        indent = i;\n        scope = s;\n        return r;\n    }\n\n\n    function statements(startLine) {\n        var a = [], f, p;\n\n        while (!nexttoken.reach && nexttoken.id !== '(end)') {\n            if (nexttoken.id === ';') {\n                p = peek();\n                if (!p || p.id !== \"(\") {\n                    warning(\"Unnecessary semicolon.\");\n                }\n                advance(';');\n            } else {\n                a.push(statement(startLine === nexttoken.line));\n            }\n        }\n        return a;\n    }\n\n\n    /*\n     * read all directives\n     * recognizes a simple form of asi, but always\n     * warns, if it is used\n     */\n    function directives() {\n        var i, p, pn;\n\n        for (;;) {\n            if (nexttoken.id === \"(string)\") {\n                p = peek(0);\n                if (p.id === \"(endline)\") {\n                    i = 1;\n                    do {\n                        pn = peek(i);\n                        i = i + 1;\n                    } while (pn.id === \"(endline)\");\n\n                    if (pn.id !== \";\") {\n                        if (pn.id !== \"(string)\" && pn.id !== \"(number)\" &&\n                            pn.id !== \"(regexp)\" && pn.identifier !== true &&\n                            pn.id !== \"}\") {\n                            break;\n                        }\n                        warning(\"Missing semicolon.\", nexttoken);\n                    } else {\n                        p = pn;\n                    }\n                } else if (p.id === \"}\") {\n                    // directive with no other statements, warn about missing semicolon\n                    warning(\"Missing semicolon.\", p);\n                } else if (p.id !== \";\") {\n                    break;\n                }\n\n                indentation();\n                advance();\n                if (directive[token.value]) {\n                    warning(\"Unnecessary directive \\\"{a}\\\".\", token, token.value);\n                }\n\n                if (token.value === \"use strict\") {\n                    option.newcap = true;\n                    option.undef = true;\n                }\n\n                // there's no directive negation, so always set to true\n                directive[token.value] = true;\n\n                if (p.id === \";\") {\n                    advance(\";\");\n                }\n                continue;\n            }\n            break;\n        }\n    }\n\n\n    /*\n     * Parses a single block. A block is a sequence of statements wrapped in\n     * braces.\n     *\n     * ordinary - true for everything but function bodies and try blocks.\n     * stmt     - true if block can be a single statement (e.g. in if/for/while).\n     * isfunc   - true if block is a function body\n     */\n    function block(ordinary, stmt, isfunc) {\n        var a,\n            b = inblock,\n            old_indent = indent,\n            m,\n            s = scope,\n            t,\n            line,\n            d;\n\n        inblock = ordinary;\n        if (!ordinary || !option.funcscope) scope = Object.create(scope);\n        nonadjacent(token, nexttoken);\n        t = nexttoken;\n\n        if (nexttoken.id === '{') {\n            advance('{');\n            line = token.line;\n            if (nexttoken.id !== '}') {\n                indent += option.indent;\n                while (!ordinary && nexttoken.from > indent) {\n                    indent += option.indent;\n                }\n\n                if (isfunc) {\n                    m = {};\n                    for (d in directive) {\n                        if (is_own(directive, d)) {\n                            m[d] = directive[d];\n                        }\n                    }\n                    directives();\n\n                    if (option.strict && funct['(context)']['(global)']) {\n                        if (!m[\"use strict\"] && !directive[\"use strict\"]) {\n                            warning(\"Missing \\\"use strict\\\" statement.\");\n                        }\n                    }\n                }\n\n                a = statements(line);\n\n                if (isfunc) {\n                    directive = m;\n                }\n\n                indent -= option.indent;\n                if (line !== nexttoken.line) {\n                    indentation();\n                }\n            } else if (line !== nexttoken.line) {\n                indentation();\n            }\n            advance('}', t);\n            indent = old_indent;\n        } else if (!ordinary) {\n            error(\"Expected '{a}' and instead saw '{b}'.\",\n                  nexttoken, '{', nexttoken.value);\n        } else {\n            if (!stmt || option.curly)\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, '{', nexttoken.value);\n\n            noreach = true;\n            indent += option.indent;\n            // test indentation only if statement is in new line\n            a = [statement(nexttoken.line === token.line)];\n            indent -= option.indent;\n            noreach = false;\n        }\n        funct['(verb)'] = null;\n        if (!ordinary || !option.funcscope) scope = s;\n        inblock = b;\n        if (ordinary && option.noempty && (!a || a.length === 0)) {\n            warning(\"Empty block.\");\n        }\n        return a;\n    }\n\n\n    function countMember(m) {\n        if (membersOnly && typeof membersOnly[m] !== 'boolean') {\n            warning(\"Unexpected /*member '{a}'.\", token, m);\n        }\n        if (typeof member[m] === 'number') {\n            member[m] += 1;\n        } else {\n            member[m] = 1;\n        }\n    }\n\n\n    function note_implied(token) {\n        var name = token.value, line = token.line, a = implied[name];\n        if (typeof a === 'function') {\n            a = false;\n        }\n\n        if (!a) {\n            a = [line];\n            implied[name] = a;\n        } else if (a[a.length - 1] !== line) {\n            a.push(line);\n        }\n    }\n\n\n    // Build the syntax table by declaring the syntactic elements of the language.\n\n    type('(number)', function () {\n        return this;\n    });\n\n    type('(string)', function () {\n        return this;\n    });\n\n    syntax['(identifier)'] = {\n        type: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var v = this.value,\n                s = scope[v],\n                f;\n\n            if (typeof s === 'function') {\n                // Protection against accidental inheritance.\n                s = undefined;\n            } else if (typeof s === 'boolean') {\n                f = funct;\n                funct = functions[0];\n                addlabel(v, 'var');\n                s = funct;\n                funct = f;\n            }\n\n            // The name is in scope and defined in the current function.\n            if (funct === s) {\n                // Change 'unused' to 'var', and reject labels.\n                switch (funct[v]) {\n                case 'unused':\n                    funct[v] = 'var';\n                    break;\n                case 'unction':\n                    funct[v] = 'function';\n                    this['function'] = true;\n                    break;\n                case 'function':\n                    this['function'] = true;\n                    break;\n                case 'label':\n                    warning(\"'{a}' is a statement label.\", token, v);\n                    break;\n                }\n            } else if (funct['(global)']) {\n                // The name is not defined in the function.  If we are in the global\n                // scope, then we have an undefined variable.\n                //\n                // Operators typeof and delete do not raise runtime errors even if\n                // the base object of a reference is null so no need to display warning\n                // if we're inside of typeof or delete.\n\n                if (option.undef && typeof predefined[v] !== 'boolean') {\n                    // Attempting to subscript a null reference will throw an\n                    // error, even within the typeof and delete operators\n                    if (!(anonname === 'typeof' || anonname === 'delete') ||\n                        (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) {\n\n                        isundef(funct, \"'{a}' is not defined.\", token, v);\n                    }\n                }\n                note_implied(token);\n            } else {\n                // If the name is already defined in the current\n                // function, but not as outer, then there is a scope error.\n\n                switch (funct[v]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warning(\"'{a}' used out of scope.\", token, v);\n                    break;\n                case 'label':\n                    warning(\"'{a}' is a statement label.\", token, v);\n                    break;\n                case 'outer':\n                case 'global':\n                    break;\n                default:\n                    // If the name is defined in an outer function, make an outer entry,\n                    // and if it was unused, make it var.\n                    if (s === true) {\n                        funct[v] = true;\n                    } else if (s === null) {\n                        warning(\"'{a}' is not allowed.\", token, v);\n                        note_implied(token);\n                    } else if (typeof s !== 'object') {\n                        // Operators typeof and delete do not raise runtime errors even\n                        // if the base object of a reference is null so no need to\n                        // display warning if we're inside of typeof or delete.\n                        if (option.undef) {\n                            // Attempting to subscript a null reference will throw an\n                            // error, even within the typeof and delete operators\n                            if (!(anonname === 'typeof' || anonname === 'delete') ||\n                                (nexttoken &&\n                                    (nexttoken.value === '.' || nexttoken.value === '['))) {\n\n                                isundef(funct, \"'{a}' is not defined.\", token, v);\n                            }\n                        }\n                        funct[v] = true;\n                        note_implied(token);\n                    } else {\n                        switch (s[v]) {\n                        case 'function':\n                        case 'unction':\n                            this['function'] = true;\n                            s[v] = 'closure';\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'var':\n                        case 'unused':\n                            s[v] = 'closure';\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'closure':\n                        case 'parameter':\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'label':\n                            warning(\"'{a}' is a statement label.\", token, v);\n                        }\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            error(\"Expected an operator and instead saw '{a}'.\",\n                nexttoken, nexttoken.value);\n        }\n    };\n\n    type('(regexp)', function () {\n        return this;\n    });\n\n\n// ECMAScript parser\n\n    delim('(endline)');\n    delim('(begin)');\n    delim('(end)').reach = true;\n    delim('</').reach = true;\n    delim('<!');\n    delim('<!--');\n    delim('-->');\n    delim('(error)').reach = true;\n    delim('}').reach = true;\n    delim(')');\n    delim(']');\n    delim('\"').reach = true;\n    delim(\"'\").reach = true;\n    delim(';');\n    delim(':').reach = true;\n    delim(',');\n    delim('#');\n    delim('@');\n    reserve('else');\n    reserve('case').reach = true;\n    reserve('catch');\n    reserve('default').reach = true;\n    reserve('finally');\n    reservevar('arguments', function (x) {\n        if (directive['use strict'] && funct['(global)']) {\n            warning(\"Strict violation.\", x);\n        }\n    });\n    reservevar('eval');\n    reservevar('false');\n    reservevar('Infinity');\n    reservevar('NaN');\n    reservevar('null');\n    reservevar('this', function (x) {\n        if (directive['use strict'] && !option.validthis && ((funct['(statement)'] &&\n                funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {\n            warning(\"Possible strict violation.\", x);\n        }\n    });\n    reservevar('true');\n    reservevar('undefined');\n    assignop('=', 'assign', 20);\n    assignop('+=', 'assignadd', 20);\n    assignop('-=', 'assignsub', 20);\n    assignop('*=', 'assignmult', 20);\n    assignop('/=', 'assigndiv', 20).nud = function () {\n        error(\"A regular expression literal can be confused with '/='.\");\n    };\n    assignop('%=', 'assignmod', 20);\n    bitwiseassignop('&=', 'assignbitand', 20);\n    bitwiseassignop('|=', 'assignbitor', 20);\n    bitwiseassignop('^=', 'assignbitxor', 20);\n    bitwiseassignop('<<=', 'assignshiftleft', 20);\n    bitwiseassignop('>>=', 'assignshiftright', 20);\n    bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20);\n    infix('?', function (left, that) {\n        that.left = left;\n        that.right = expression(10);\n        advance(':');\n        that['else'] = expression(10);\n        return that;\n    }, 30);\n\n    infix('||', 'or', 40);\n    infix('&&', 'and', 50);\n    bitwise('|', 'bitor', 70);\n    bitwise('^', 'bitxor', 80);\n    bitwise('&', 'bitand', 90);\n    relation('==', function (left, right) {\n        var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null');\n\n        if (!eqnull && option.eqeqeq)\n            warning(\"Expected '{a}' and instead saw '{b}'.\", this, '===', '==');\n        else if (isPoorRelation(left))\n            warning(\"Use '{a}' to compare with '{b}'.\", this, '===', left.value);\n        else if (isPoorRelation(right))\n            warning(\"Use '{a}' to compare with '{b}'.\", this, '===', right.value);\n\n        return this;\n    });\n    relation('===');\n    relation('!=', function (left, right) {\n        var eqnull = option.eqnull &&\n                (left.value === 'null' || right.value === 'null');\n\n        if (!eqnull && option.eqeqeq) {\n            warning(\"Expected '{a}' and instead saw '{b}'.\",\n                    this, '!==', '!=');\n        } else if (isPoorRelation(left)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                    this, '!==', left.value);\n        } else if (isPoorRelation(right)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                    this, '!==', right.value);\n        }\n        return this;\n    });\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n    bitwise('<<', 'shiftleft', 120);\n    bitwise('>>', 'shiftright', 120);\n    bitwise('>>>', 'shiftrightunsigned', 120);\n    infix('in', 'in', 120);\n    infix('instanceof', 'instanceof', 120);\n    infix('+', function (left, that) {\n        var right = expression(130);\n        if (left && right && left.id === '(string)' && right.id === '(string)') {\n            left.value += right.value;\n            left.character = right.character;\n            if (!option.scripturl && jx.test(left.value)) {\n                warning(\"JavaScript URL.\", left);\n            }\n            return left;\n        }\n        that.left = left;\n        that.right = right;\n        return that;\n    }, 130);\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warning(\"Confusing pluses.\");\n        this.right = expression(150);\n        this.arity = 'unary';\n        return this;\n    });\n    infix('+++', function (left) {\n        warning(\"Confusing pluses.\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix('-', 'sub', 130);\n    prefix('-', 'neg');\n    prefix('---', function () {\n        warning(\"Confusing minuses.\");\n        this.right = expression(150);\n        this.arity = 'unary';\n        return this;\n    });\n    infix('---', function (left) {\n        warning(\"Confusing minuses.\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix('*', 'mult', 140);\n    infix('/', 'div', 140);\n    infix('%', 'mod', 140);\n\n    suffix('++', 'postinc');\n    prefix('++', 'preinc');\n    syntax['++'].exps = true;\n\n    suffix('--', 'postdec');\n    prefix('--', 'predec');\n    syntax['--'].exps = true;\n    prefix('delete', function () {\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warning(\"Variables should not be deleted.\");\n        }\n        this.first = p;\n        return this;\n    }).exps = true;\n\n    prefix('~', function () {\n        if (option.bitwise) {\n            warning(\"Unexpected '{a}'.\", this, '~');\n        }\n        expression(150);\n        return this;\n    });\n\n    prefix('!', function () {\n        this.right = expression(150);\n        this.arity = 'unary';\n        if (bang[this.right.id] === true) {\n            warning(\"Confusing use of '{a}'.\", this, '!');\n        }\n        return this;\n    });\n    prefix('typeof', 'typeof');\n    prefix('new', function () {\n        var c = expression(155), i;\n        if (c && c.id !== 'function') {\n            if (c.identifier) {\n                c['new'] = true;\n                switch (c.value) {\n                case 'Object':\n                    warning(\"Use the object literal notation {}.\", token);\n                    break;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warning(\"Do not use {a} as a constructor.\", token, c.value);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warning(\"The Function constructor is eval.\");\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        i = c.value.substr(0, 1);\n                        if (option.newcap && (i < 'A' || i > 'Z')) {\n                            warning(\"A constructor name should start with an uppercase letter.\",\n                                token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warning(\"Bad constructor.\", token);\n                }\n            }\n        } else {\n            if (!option.supernew)\n                warning(\"Weird construction. Delete 'new'.\", this);\n        }\n        adjacent(token, nexttoken);\n        if (nexttoken.id !== '(' && !option.supernew) {\n            warning(\"Missing '()' invoking a constructor.\");\n        }\n        this.first = c;\n        return this;\n    });\n    syntax['new'].exps = true;\n\n    prefix('void').exps = true;\n\n    infix('.', function (left, that) {\n        adjacent(prevtoken, token);\n        nobreak();\n        var m = identifier();\n        if (typeof m === 'string') {\n            countMember(m);\n        }\n        that.left = left;\n        that.right = m;\n        if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) {\n            if (option.noarg)\n                warning(\"Avoid arguments.{a}.\", left, m);\n            else if (directive['use strict'])\n                error('Strict violation.');\n        } else if (!option.evil && left && left.value === 'document' &&\n                (m === 'write' || m === 'writeln')) {\n            warning(\"document.write can be a form of eval.\", left);\n        }\n        if (!option.evil && (m === 'eval' || m === 'execScript')) {\n            warning('eval is evil.');\n        }\n        return that;\n    }, 160, true);\n\n    infix('(', function (left, that) {\n        if (prevtoken.id !== '}' && prevtoken.id !== ')') {\n            nobreak(prevtoken, token);\n        }\n        nospace();\n        if (option.immed && !left.immed && left.id === 'function') {\n            warning(\"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\");\n        }\n        var n = 0,\n            p = [];\n        if (left) {\n            if (left.type === '(identifier)') {\n                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                    if (left.value !== 'Number' && left.value !== 'String' &&\n                            left.value !== 'Boolean' &&\n                            left.value !== 'Date') {\n                        if (left.value === 'Math') {\n                            warning(\"Math is not a function.\", left);\n                        } else if (option.newcap) {\n                            warning(\n\"Missing 'new' prefix when invoking a constructor.\", left);\n                        }\n                    }\n                }\n            }\n        }\n        if (nexttoken.id !== ')') {\n            for (;;) {\n                p[p.length] = expression(10);\n                n += 1;\n                if (nexttoken.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        advance(')');\n        nospace(prevtoken, token);\n        if (typeof left === 'object') {\n            if (left.value === 'parseInt' && n === 1) {\n                warning(\"Missing radix parameter.\", left);\n            }\n            if (!option.evil) {\n                if (left.value === 'eval' || left.value === 'Function' ||\n                        left.value === 'execScript') {\n                    warning(\"eval is evil.\", left);\n                } else if (p[0] && p[0].id === '(string)' &&\n                       (left.value === 'setTimeout' ||\n                        left.value === 'setInterval')) {\n                    warning(\n    \"Implied eval is evil. Pass a function instead of a string.\", left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warning(\"Bad invocation.\", left);\n            }\n        }\n        that.left = left;\n        return that;\n    }, 155, true).exps = true;\n\n    prefix('(', function () {\n        nospace();\n        if (nexttoken.id === 'function') {\n            nexttoken.immed = true;\n        }\n        var v = expression(0);\n        advance(')', this);\n        nospace(prevtoken, token);\n        if (option.immed && v.id === 'function') {\n            if (nexttoken.id === '(' ||\n              (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) {\n                warning(\n\"Move the invocation into the parens that contain the function.\", nexttoken);\n            } else {\n                warning(\n\"Do not wrap function literals in parens unless they are to be immediately invoked.\",\n                        this);\n            }\n        }\n        return v;\n    });\n\n    infix('[', function (left, that) {\n        nobreak(prevtoken, token);\n        nospace();\n        var e = expression(0), s;\n        if (e && e.type === '(string)') {\n            if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) {\n                warning(\"eval is evil.\", that);\n            }\n            countMember(e.value);\n            if (!option.sub && ix.test(e.value)) {\n                s = syntax[e.value];\n                if (!s || !s.reserved) {\n                    warning(\"['{a}'] is better written in dot notation.\",\n                            e, e.value);\n                }\n            }\n        }\n        advance(']', that);\n        nospace(prevtoken, token);\n        that.left = left;\n        that.right = e;\n        return that;\n    }, 160, true);\n\n    prefix('[', function () {\n        var b = token.line !== nexttoken.line;\n        this.first = [];\n        if (b) {\n            indent += option.indent;\n            if (nexttoken.from === indent + option.indent) {\n                indent += option.indent;\n            }\n        }\n        while (nexttoken.id !== '(end)') {\n            while (nexttoken.id === ',') {\n                warning(\"Extra comma.\");\n                advance(',');\n            }\n            if (nexttoken.id === ']') {\n                break;\n            }\n            if (b && token.line !== nexttoken.line) {\n                indentation();\n            }\n            this.first.push(expression(10));\n            if (nexttoken.id === ',') {\n                comma();\n                if (nexttoken.id === ']' && !option.es5) {\n                    warning(\"Extra comma.\", token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        if (b) {\n            indent -= option.indent;\n            indentation();\n        }\n        advance(']', this);\n        return this;\n    }, 160);\n\n\n    function property_name() {\n        var id = optionalidentifier(true);\n        if (!id) {\n            if (nexttoken.id === '(string)') {\n                id = nexttoken.value;\n                advance();\n            } else if (nexttoken.id === '(number)') {\n                id = nexttoken.value.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function functionparams() {\n        var i, t = nexttoken, p = [];\n        advance('(');\n        nospace();\n        if (nexttoken.id === ')') {\n            advance(')');\n            return;\n        }\n        for (;;) {\n            i = identifier(true);\n            p.push(i);\n            addlabel(i, 'parameter');\n            if (nexttoken.id === ',') {\n                comma();\n            } else {\n                advance(')', t);\n                nospace(prevtoken, token);\n                return p;\n            }\n        }\n    }\n\n\n    function doFunction(i, statement) {\n        var f,\n            oldOption = option,\n            oldScope  = scope;\n\n        option = Object.create(option);\n        scope = Object.create(scope);\n\n        funct = {\n            '(name)'     : i || '\"' + anonname + '\"',\n            '(line)'     : nexttoken.line,\n            '(context)'  : funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(statement)': statement\n        };\n        f = funct;\n        token.funct = funct;\n        functions.push(funct);\n        if (i) {\n            addlabel(i, 'function');\n        }\n        funct['(params)'] = functionparams();\n\n        block(false, false, true);\n        scope = oldScope;\n        option = oldOption;\n        funct['(last)'] = token.line;\n        funct = funct['(context)'];\n        return f;\n    }\n\n\n    (function (x) {\n        x.nud = function () {\n            var b, f, i, j, p, t;\n            var props = {}; // All properties, including accessors\n\n            function saveProperty(name, token) {\n                if (props[name] && is_own(props, name))\n                    warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                else\n                    props[name] = {};\n\n                props[name].basic = true;\n                props[name].basicToken = token;\n            }\n\n            function saveSetter(name, token) {\n                if (props[name] && is_own(props, name)) {\n                    if (props[name].basic || props[name].setter)\n                        warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                } else {\n                    props[name] = {};\n                }\n\n                props[name].setter = true;\n                props[name].setterToken = token;\n            }\n\n            function saveGetter(name) {\n                if (props[name] && is_own(props, name)) {\n                    if (props[name].basic || props[name].getter)\n                        warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                } else {\n                    props[name] = {};\n                }\n\n                props[name].getter = true;\n                props[name].getterToken = token;\n            }\n\n            b = token.line !== nexttoken.line;\n            if (b) {\n                indent += option.indent;\n                if (nexttoken.from === indent + option.indent) {\n                    indent += option.indent;\n                }\n            }\n            for (;;) {\n                if (nexttoken.id === '}') {\n                    break;\n                }\n                if (b) {\n                    indentation();\n                }\n                if (nexttoken.value === 'get' && peek().id !== ':') {\n                    advance('get');\n                    if (!option.es5) {\n                        error(\"get/set are ES5 features.\");\n                    }\n                    i = property_name();\n                    if (!i) {\n                        error(\"Missing property name.\");\n                    }\n                    saveGetter(i);\n                    t = nexttoken;\n                    adjacent(token, nexttoken);\n                    f = doFunction();\n                    p = f['(params)'];\n                    if (p) {\n                        warning(\"Unexpected parameter '{a}' in get {b} function.\", t, p[0], i);\n                    }\n                    adjacent(token, nexttoken);\n                } else if (nexttoken.value === 'set' && peek().id !== ':') {\n                    advance('set');\n                    if (!option.es5) {\n                        error(\"get/set are ES5 features.\");\n                    }\n                    i = property_name();\n                    if (!i) {\n                        error(\"Missing property name.\");\n                    }\n                    saveSetter(i, nexttoken);\n                    t = nexttoken;\n                    adjacent(token, nexttoken);\n                    f = doFunction();\n                    p = f['(params)'];\n                    if (!p || p.length !== 1) {\n                        warning(\"Expected a single parameter in set {a} function.\", t, i);\n                    }\n                } else {\n                    i = property_name();\n                    saveProperty(i, nexttoken);\n                    if (typeof i !== 'string') {\n                        break;\n                    }\n                    advance(':');\n                    nonadjacent(token, nexttoken);\n                    expression(10);\n                }\n\n                countMember(i);\n                if (nexttoken.id === ',') {\n                    comma();\n                    if (nexttoken.id === ',') {\n                        warning(\"Extra comma.\", token);\n                    } else if (nexttoken.id === '}' && !option.es5) {\n                        warning(\"Extra comma.\", token);\n                    }\n                } else {\n                    break;\n                }\n            }\n            if (b) {\n                indent -= option.indent;\n                indentation();\n            }\n            advance('}', this);\n\n            // Check for lonely setters if in the ES5 mode.\n            if (option.es5) {\n                for (var name in props) {\n                    if (is_own(props, name) && props[name].setter && !props[name].getter) {\n                        warning(\"Setter is defined without getter.\", props[name].setterToken);\n                    }\n                }\n            }\n            return this;\n        };\n        x.fud = function () {\n            error(\"Expected to see a statement and instead saw a block.\", token);\n        };\n    }(delim('{')));\n\n// This Function is called when esnext option is set to true\n// it adds the `const` statement to JSHINT\n\n    useESNextSyntax = function () {\n        var conststatement = stmt('const', function (prefix) {\n            var id, name, value;\n\n            this.first = [];\n            for (;;) {\n                nonadjacent(token, nexttoken);\n                id = identifier();\n                if (funct[id] === \"const\") {\n                    warning(\"const '\" + id + \"' has already been declared\");\n                }\n                if (funct['(global)'] && predefined[id] === false) {\n                    warning(\"Redefinition of '{a}'.\", token, id);\n                }\n                addlabel(id, 'const');\n                if (prefix) {\n                    break;\n                }\n                name = token;\n                this.first.push(token);\n\n                if (nexttoken.id !== \"=\") {\n                    warning(\"const \" +\n                      \"'{a}' is initialized to 'undefined'.\", token, id);\n                }\n\n                if (nexttoken.id === '=') {\n                    nonadjacent(token, nexttoken);\n                    advance('=');\n                    nonadjacent(token, nexttoken);\n                    if (nexttoken.id === 'undefined') {\n                        warning(\"It is not necessary to initialize \" +\n                          \"'{a}' to 'undefined'.\", token, id);\n                    }\n                    if (peek(0).id === '=' && nexttoken.identifier) {\n                        error(\"Constant {a} was not declared correctly.\",\n                                nexttoken, nexttoken.value);\n                    }\n                    value = expression(0);\n                    name.first = value;\n                }\n\n                if (nexttoken.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n            return this;\n        });\n        conststatement.exps = true;\n    };\n\n    var varstatement = stmt('var', function (prefix) {\n        // JavaScript does not have block scope. It only has function scope. So,\n        // declaring a variable in a block can have unexpected consequences.\n        var id, name, value;\n\n        if (funct['(onevar)'] && option.onevar) {\n            warning(\"Too many var statements.\");\n        } else if (!funct['(global)']) {\n            funct['(onevar)'] = true;\n        }\n        this.first = [];\n        for (;;) {\n            nonadjacent(token, nexttoken);\n            id = identifier();\n            if (option.esnext && funct[id] === \"const\") {\n                warning(\"const '\" + id + \"' has already been declared\");\n            }\n            if (funct['(global)'] && predefined[id] === false) {\n                warning(\"Redefinition of '{a}'.\", token, id);\n            }\n            addlabel(id, 'unused');\n            if (prefix) {\n                break;\n            }\n            name = token;\n            this.first.push(token);\n            if (nexttoken.id === '=') {\n                nonadjacent(token, nexttoken);\n                advance('=');\n                nonadjacent(token, nexttoken);\n                if (nexttoken.id === 'undefined') {\n                    warning(\"It is not necessary to initialize '{a}' to 'undefined'.\", token, id);\n                }\n                if (peek(0).id === '=' && nexttoken.identifier) {\n                    error(\"Variable {a} was not declared correctly.\",\n                            nexttoken, nexttoken.value);\n                }\n                value = expression(0);\n                name.first = value;\n            }\n            if (nexttoken.id !== ',') {\n                break;\n            }\n            comma();\n        }\n        return this;\n    });\n    varstatement.exps = true;\n\n    blockstmt('function', function () {\n        if (inblock) {\n            warning(\"Function declarations should not be placed in blocks. \" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\", token);\n\n        }\n        var i = identifier();\n        if (option.esnext && funct[i] === \"const\") {\n            warning(\"const '\" + i + \"' has already been declared\");\n        }\n        adjacent(token, nexttoken);\n        addlabel(i, 'unction');\n        doFunction(i, true);\n        if (nexttoken.id === '(' && nexttoken.line === token.line) {\n            error(\n\"Function declarations are not invocable. Wrap the whole function invocation in parens.\");\n        }\n        return this;\n    });\n\n    prefix('function', function () {\n        var i = optionalidentifier();\n        if (i) {\n            adjacent(token, nexttoken);\n        } else {\n            nonadjacent(token, nexttoken);\n        }\n        doFunction(i);\n        if (!option.loopfunc && funct['(loopage)']) {\n            warning(\"Don't make functions within a loop.\");\n        }\n        return this;\n    });\n\n    blockstmt('if', function () {\n        var t = nexttoken;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(20);\n        if (nexttoken.id === '=') {\n            if (!option.boss)\n                warning(\"Expected a conditional expression and instead saw an assignment.\");\n            advance('=');\n            expression(20);\n        }\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n        if (nexttoken.id === 'else') {\n            nonadjacent(token, nexttoken);\n            advance('else');\n            if (nexttoken.id === 'if' || nexttoken.id === 'switch') {\n                statement(true);\n            } else {\n                block(true, true);\n            }\n        }\n        return this;\n    });\n\n    blockstmt('try', function () {\n        var b, e, s;\n\n        block(false);\n        if (nexttoken.id === 'catch') {\n            advance('catch');\n            nonadjacent(token, nexttoken);\n            advance('(');\n            s = scope;\n            scope = Object.create(s);\n            e = nexttoken.value;\n            if (nexttoken.type !== '(identifier)') {\n                warning(\"Expected an identifier and instead saw '{a}'.\",\n                    nexttoken, e);\n            } else {\n                addlabel(e, 'exception');\n            }\n            advance();\n            advance(')');\n            block(false);\n            b = true;\n            scope = s;\n        }\n        if (nexttoken.id === 'finally') {\n            advance('finally');\n            block(false);\n            return;\n        } else if (!b) {\n            error(\"Expected '{a}' and instead saw '{b}'.\",\n                    nexttoken, 'catch', nexttoken.value);\n        }\n        return this;\n    });\n\n    blockstmt('while', function () {\n        var t = nexttoken;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(20);\n        if (nexttoken.id === '=') {\n            if (!option.boss)\n                warning(\"Expected a conditional expression and instead saw an assignment.\");\n            advance('=');\n            expression(20);\n        }\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    }).labelled = true;\n\n    reserve('with');\n\n    blockstmt('switch', function () {\n        var t = nexttoken,\n            g = false;\n        funct['(breakage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        this.condition = expression(20);\n        advance(')', t);\n        nospace(prevtoken, token);\n        nonadjacent(token, nexttoken);\n        t = nexttoken;\n        advance('{');\n        nonadjacent(token, nexttoken);\n        indent += option.indent;\n        this.cases = [];\n        for (;;) {\n            switch (nexttoken.id) {\n            case 'case':\n                switch (funct['(verb)']) {\n                case 'break':\n                case 'case':\n                case 'continue':\n                case 'return':\n                case 'switch':\n                case 'throw':\n                    break;\n                default:\n                    // You can tell JSHint that you don't use break intentionally by\n                    // adding a comment /* falls through */ on a line just before\n                    // the next `case`.\n                    if (!ft.test(lines[nexttoken.line - 2])) {\n                        warning(\n                            \"Expected a 'break' statement before 'case'.\",\n                            token);\n                    }\n                }\n                indentation(-option.indent);\n                advance('case');\n                this.cases.push(expression(20));\n                g = true;\n                advance(':');\n                funct['(verb)'] = 'case';\n                break;\n            case 'default':\n                switch (funct['(verb)']) {\n                case 'break':\n                case 'continue':\n                case 'return':\n                case 'throw':\n                    break;\n                default:\n                    if (!ft.test(lines[nexttoken.line - 2])) {\n                        warning(\n                            \"Expected a 'break' statement before 'default'.\",\n                            token);\n                    }\n                }\n                indentation(-option.indent);\n                advance('default');\n                g = true;\n                advance(':');\n                break;\n            case '}':\n                indent -= option.indent;\n                indentation();\n                advance('}', t);\n                if (this.cases.length === 1 || this.condition.id === 'true' ||\n                        this.condition.id === 'false') {\n                    if (!option.onecase)\n                        warning(\"This 'switch' should be an 'if'.\", this);\n                }\n                funct['(breakage)'] -= 1;\n                funct['(verb)'] = undefined;\n                return;\n            case '(end)':\n                error(\"Missing '{a}'.\", nexttoken, '}');\n                return;\n            default:\n                if (g) {\n                    switch (token.id) {\n                    case ',':\n                        error(\"Each value should have its own case label.\");\n                        return;\n                    case ':':\n                        g = false;\n                        statements();\n                        break;\n                    default:\n                        error(\"Missing ':' on a case clause.\", token);\n                        return;\n                    }\n                } else {\n                    if (token.id === ':') {\n                        advance(':');\n                        error(\"Unexpected '{a}'.\", token, ':');\n                        statements();\n                    } else {\n                        error(\"Expected '{a}' and instead saw '{b}'.\",\n                            nexttoken, 'case', nexttoken.value);\n                        return;\n                    }\n                }\n            }\n        }\n    }).labelled = true;\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warning(\"All 'debugger' statements should be removed.\");\n        }\n        return this;\n    }).exps = true;\n\n    (function () {\n        var x = stmt('do', function () {\n            funct['(breakage)'] += 1;\n            funct['(loopage)'] += 1;\n            this.first = block(true);\n            advance('while');\n            var t = nexttoken;\n            nonadjacent(token, t);\n            advance('(');\n            nospace();\n            expression(20);\n            if (nexttoken.id === '=') {\n                if (!option.boss)\n                    warning(\"Expected a conditional expression and instead saw an assignment.\");\n                advance('=');\n                expression(20);\n            }\n            advance(')', t);\n            nospace(prevtoken, token);\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        });\n        x.labelled = true;\n        x.exps = true;\n    }());\n\n    blockstmt('for', function () {\n        var s, t = nexttoken;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') {\n            if (nexttoken.id === 'var') {\n                advance('var');\n                varstatement.fud.call(varstatement, true);\n            } else {\n                switch (funct[nexttoken.value]) {\n                case 'unused':\n                    funct[nexttoken.value] = 'var';\n                    break;\n                case 'var':\n                    break;\n                default:\n                    warning(\"Bad for in variable '{a}'.\",\n                            nexttoken, nexttoken.value);\n                }\n                advance();\n            }\n            advance('in');\n            expression(20);\n            advance(')', t);\n            s = block(true, true);\n            if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' ||\n                    s[0].value !== 'if')) {\n                warning(\"The body of a for in should be wrapped in an if statement to filter \" +\n                        \"unwanted properties from the prototype.\", this);\n            }\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        } else {\n            if (nexttoken.id !== ';') {\n                if (nexttoken.id === 'var') {\n                    advance('var');\n                    varstatement.fud.call(varstatement);\n                } else {\n                    for (;;) {\n                        expression(0, 'for');\n                        if (nexttoken.id !== ',') {\n                            break;\n                        }\n                        comma();\n                    }\n                }\n            }\n            nolinebreak(token);\n            advance(';');\n            if (nexttoken.id !== ';') {\n                expression(20);\n                if (nexttoken.id === '=') {\n                    if (!option.boss)\n                        warning(\"Expected a conditional expression and instead saw an assignment.\");\n                    advance('=');\n                    expression(20);\n                }\n            }\n            nolinebreak(token);\n            advance(';');\n            if (nexttoken.id === ';') {\n                error(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, ')', ';');\n            }\n            if (nexttoken.id !== ')') {\n                for (;;) {\n                    expression(0, 'for');\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n            }\n            advance(')', t);\n            nospace(prevtoken, token);\n            block(true, true);\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        }\n    }).labelled = true;\n\n\n    stmt('break', function () {\n        var v = nexttoken.value;\n\n        if (funct['(breakage)'] === 0)\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n\n        if (!option.asi)\n            nolinebreak(this);\n\n        if (nexttoken.id !== ';') {\n            if (token.line === nexttoken.line) {\n                if (funct[v] !== 'label') {\n                    warning(\"'{a}' is not a statement label.\", nexttoken, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"'{a}' is out of scope.\", nexttoken, v);\n                }\n                this.first = nexttoken;\n                advance();\n            }\n        }\n        reachable('break');\n        return this;\n    }).exps = true;\n\n\n    stmt('continue', function () {\n        var v = nexttoken.value;\n\n        if (funct['(breakage)'] === 0)\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n\n        if (!option.asi)\n            nolinebreak(this);\n\n        if (nexttoken.id !== ';') {\n            if (token.line === nexttoken.line) {\n                if (funct[v] !== 'label') {\n                    warning(\"'{a}' is not a statement label.\", nexttoken, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"'{a}' is out of scope.\", nexttoken, v);\n                }\n                this.first = nexttoken;\n                advance();\n            }\n        } else if (!funct['(loopage)']) {\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n        }\n        reachable('continue');\n        return this;\n    }).exps = true;\n\n\n    stmt('return', function () {\n        if (this.line === nexttoken.line) {\n            if (nexttoken.id === '(regexp)')\n                warning(\"Wrap the /regexp/ literal in parens to disambiguate the slash operator.\");\n\n            if (nexttoken.id !== ';' && !nexttoken.reach) {\n                nonadjacent(token, nexttoken);\n                if (peek().value === \"=\" && !option.boss) {\n                    warningAt(\"Did you mean to return a conditional instead of an assignment?\",\n                              token.line, token.character + 1);\n                }\n                this.first = expression(0);\n            }\n        } else if (!option.asi) {\n            nolinebreak(this); // always warn (Line breaking error)\n        }\n        reachable('return');\n        return this;\n    }).exps = true;\n\n\n    stmt('throw', function () {\n        nolinebreak(this);\n        nonadjacent(token, nexttoken);\n        this.first = expression(20);\n        reachable('throw');\n        return this;\n    }).exps = true;\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n    reserve('let');\n    reserve('yield');\n    reserve('implements');\n    reserve('interface');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n\n\n// Parse JSON\n\n    function jsonValue() {\n\n        function jsonObject() {\n            var o = {}, t = nexttoken;\n            advance('{');\n            if (nexttoken.id !== '}') {\n                for (;;) {\n                    if (nexttoken.id === '(end)') {\n                        error(\"Missing '}' to match '{' from line {a}.\",\n                                nexttoken, t.line);\n                    } else if (nexttoken.id === '}') {\n                        warning(\"Unexpected comma.\", token);\n                        break;\n                    } else if (nexttoken.id === ',') {\n                        error(\"Unexpected comma.\", nexttoken);\n                    } else if (nexttoken.id !== '(string)') {\n                        warning(\"Expected a string and instead saw {a}.\",\n                                nexttoken, nexttoken.value);\n                    }\n                    if (o[nexttoken.value] === true) {\n                        warning(\"Duplicate key '{a}'.\",\n                                nexttoken, nexttoken.value);\n                    } else if ((nexttoken.value === '__proto__' &&\n                        !option.proto) || (nexttoken.value === '__iterator__' &&\n                        !option.iterator)) {\n                        warning(\"The '{a}' key may produce unexpected results.\",\n                            nexttoken, nexttoken.value);\n                    } else {\n                        o[nexttoken.value] = true;\n                    }\n                    advance();\n                    advance(':');\n                    jsonValue();\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                }\n            }\n            advance('}');\n        }\n\n        function jsonArray() {\n            var t = nexttoken;\n            advance('[');\n            if (nexttoken.id !== ']') {\n                for (;;) {\n                    if (nexttoken.id === '(end)') {\n                        error(\"Missing ']' to match '[' from line {a}.\",\n                                nexttoken, t.line);\n                    } else if (nexttoken.id === ']') {\n                        warning(\"Unexpected comma.\", token);\n                        break;\n                    } else if (nexttoken.id === ',') {\n                        error(\"Unexpected comma.\", nexttoken);\n                    }\n                    jsonValue();\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                }\n            }\n            advance(']');\n        }\n\n        switch (nexttoken.id) {\n        case '{':\n            jsonObject();\n            break;\n        case '[':\n            jsonArray();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            if (token.character !== nexttoken.from) {\n                warning(\"Unexpected space after '-'.\", token);\n            }\n            adjacent(token, nexttoken);\n            advance('(number)');\n            break;\n        default:\n            error(\"Expected a JSON value.\", nexttoken);\n        }\n    }\n\n\n// The actual JSHINT function itself.\n\n    var itself = function (s, o, g) {\n        var a, i, k;\n        JSHINT.errors = [];\n        JSHINT.undefs = [];\n        predefined = Object.create(standard);\n        combine(predefined, g || {});\n        if (o) {\n            a = o.predef;\n            if (a) {\n                if (Array.isArray(a)) {\n                    for (i = 0; i < a.length; i += 1) {\n                        predefined[a[i]] = true;\n                    }\n                } else if (typeof a === 'object') {\n                    k = Object.keys(a);\n                    for (i = 0; i < k.length; i += 1) {\n                        predefined[k[i]] = !!a[k[i]];\n                    }\n                }\n            }\n            option = o;\n        } else {\n            option = {};\n        }\n        option.indent = option.indent || 4;\n        option.maxerr = option.maxerr || 50;\n\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        indent = 1;\n        global = Object.create(predefined);\n        scope = global;\n        funct = {\n            '(global)': true,\n            '(name)': '(global)',\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n        urls = [];\n        stack = null;\n        member = {};\n        membersOnly = null;\n        implied = {};\n        inblock = false;\n        lookahead = [];\n        jsonmode = false;\n        warnings = 0;\n        lex.init(s);\n        prereg = true;\n        directive = {};\n\n        prevtoken = token = nexttoken = syntax['(begin)'];\n        assume();\n\n        // combine the passed globals after we've assumed all our options\n        combine(predefined, g || {});\n\n        try {\n            advance();\n            switch (nexttoken.id) {\n            case '{':\n            case '[':\n                option.laxbreak = true;\n                jsonmode = true;\n                jsonValue();\n                break;\n            default:\n                directives();\n                if (directive[\"use strict\"] && !option.globalstrict) {\n                    warning(\"Use the function form of \\\"use strict\\\".\", prevtoken);\n                }\n\n                statements();\n            }\n            advance('(end)');\n\n            var markDefined = function (name, context) {\n                do {\n                    if (typeof context[name] === 'string') {\n                        // JSHINT marks unused variables as 'unused' and\n                        // unused function declaration as 'unction'. This\n                        // code changes such instances back 'var' and\n                        // 'closure' so that the code in JSHINT.data()\n                        // doesn't think they're unused.\n\n                        if (context[name] === 'unused')\n                            context[name] = 'var';\n                        else if (context[name] === 'unction')\n                            context[name] = 'closure';\n\n                        return true;\n                    }\n\n                    context = context['(context)'];\n                } while (context);\n\n                return false;\n            };\n\n            var clearImplied = function (name, line) {\n                if (!implied[name])\n                    return;\n\n                var newImplied = [];\n                for (var i = 0; i < implied[name].length; i += 1) {\n                    if (implied[name][i] !== line)\n                        newImplied.push(implied[name][i]);\n                }\n\n                if (newImplied.length === 0)\n                    delete implied[name];\n                else\n                    implied[name] = newImplied;\n            };\n\n            // Check queued 'x is not defined' instances to see if they're still undefined.\n            for (i = 0; i < JSHINT.undefs.length; i += 1) {\n                k = JSHINT.undefs[i].slice(0);\n\n                if (markDefined(k[2].value, k[0])) {\n                    clearImplied(k[2].value, k[2].line);\n                } else {\n                    warning.apply(warning, k.slice(1));\n                }\n            }\n        } catch (e) {\n            if (e) {\n                var nt = nexttoken || {};\n                JSHINT.errors.push({\n                    raw       : e.raw,\n                    reason    : e.message,\n                    line      : e.line || nt.line,\n                    character : e.character || nt.from\n                }, null);\n            }\n        }\n\n        return JSHINT.errors.length === 0;\n    };\n\n    // Data summary.\n    itself.data = function () {\n\n        var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j,\n            members = [], n, unused = [], v;\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (jsonmode) {\n            data.json = true;\n        }\n\n        for (n in implied) {\n            if (is_own(implied, n)) {\n                implieds.push({\n                    name: n,\n                    line: implied[n]\n                });\n            }\n        }\n        if (implieds.length > 0) {\n            data.implieds = implieds;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(scope);\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n        for (i = 1; i < functions.length; i += 1) {\n            f = functions[i];\n            fu = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                fu[functionicity[j]] = [];\n            }\n            for (n in f) {\n                if (is_own(f, n) && n.charAt(0) !== '(') {\n                    v = f[n];\n                    if (v === 'unction') {\n                        v = 'unused';\n                    }\n                    if (Array.isArray(fu[v])) {\n                        fu[v].push(n);\n                        if (v === 'unused') {\n                            unused.push({\n                                name: n,\n                                line: f['(line)'],\n                                'function': f['(name)']\n                            });\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (fu[functionicity[j]].length === 0) {\n                    delete fu[functionicity[j]];\n                }\n            }\n            fu.name = f['(name)'];\n            fu.param = f['(params)'];\n            fu.line = f['(line)'];\n            fu.last = f['(last)'];\n            data.functions.push(fu);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n\n        members = [];\n        for (n in member) {\n            if (typeof member[n] === 'number') {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n    itself.report = function (option) {\n        var data = itself.data();\n\n        var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s;\n\n        function detail(h, array) {\n            var b, i, singularity;\n            if (array) {\n                o.push('<div><i>' + h + '</i> ');\n                array = array.sort();\n                for (i = 0; i < array.length; i += 1) {\n                    if (array[i] !== singularity) {\n                        singularity = array[i];\n                        o.push((b ? ', ' : '') + singularity);\n                        b = true;\n                    }\n                }\n                o.push('</div>');\n            }\n        }\n\n\n        if (data.errors || data.implieds || data.unused) {\n            err = true;\n            o.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    c = data.errors[i];\n                    if (c) {\n                        e = c.evidence || '';\n                        o.push('<p>Problem' + (isFinite(c.line) ? ' at line ' +\n                                c.line + ' character ' + c.character : '') +\n                                ': ' + c.reason.entityify() +\n                                '</p><p class=evidence>' +\n                                (e && (e.length > 80 ? e.slice(0, 77) + '...' :\n                                e).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data.implieds) {\n                s = [];\n                for (i = 0; i < data.implieds.length; i += 1) {\n                    s[i] = '<code>' + data.implieds[i].name + '</code>&nbsp;<i>' +\n                        data.implieds[i].line + '</i>';\n                }\n                o.push('<p><i>Implied global:</i> ' + s.join(', ') + '</p>');\n            }\n\n            if (data.unused) {\n                s = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    s[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        data.unused[i].line + '</i> <code>' +\n                        data.unused[i]['function'] + '</code>';\n                }\n                o.push('<p><i>Unused variable:</i> ' + s.join(', ') + '</p>');\n            }\n            if (data.json) {\n                o.push('<p>JSON: bad.</p>');\n            }\n            o.push('</div>');\n        }\n\n        if (!option) {\n\n            o.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (data.json && !err) {\n                o.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                o.push('<div><i>Global</i> ' +\n                        data.globals.sort().join(', ') + '</div>');\n            } else {\n                o.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                f = data.functions[i];\n\n                o.push('<br><div class=function><i>' + f.line + '-' +\n                        f.last + '</i> ' + (f.name || '') + '(' +\n                        (f.param ? f.param.join(', ') : '') + ')</div>');\n                detail('<big><b>Unused</b></big>', f.unused);\n                detail('Closure', f.closure);\n                detail('Variable', f['var']);\n                detail('Exception', f.exception);\n                detail('Outer', f.outer);\n                detail('Global', f.global);\n                detail('Label', f.label);\n            }\n\n            if (data.member) {\n                a = Object.keys(data.member);\n                if (a.length) {\n                    a = a.sort();\n                    m = '<br><pre id=members>/*members ';\n                    l = 10;\n                    for (i = 0; i < a.length; i += 1) {\n                        k = a[i];\n                        n = k.name();\n                        if (l + n.length > 72) {\n                            o.push(m + '<br>');\n                            m = '    ';\n                            l = 1;\n                        }\n                        l += n.length + 2;\n                        if (data.member[k] === 1) {\n                            n = '<i>' + n + '</i>';\n                        }\n                        if (i < a.length - 1) {\n                            n += ', ';\n                        }\n                        m += n;\n                    }\n                    o.push(m + '<br>*/</pre>');\n                }\n                o.push('</div>');\n            }\n        }\n        return o.join('');\n    };\n\n    itself.jshint = itself;\n\n    return itself;\n}());\n\n// Make JSHINT a Node module, if possible.\nif (typeof exports === 'object' && exports)\n    exports.JSHINT = JSHINT;\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/qunit.css",
    "content": "/**\n * QUnit v1.6.0 - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 15px 15px 0 0;\n\t-moz-border-radius: 15px 15px 0 0;\n\t-webkit-border-top-right-radius: 15px;\n\t-webkit-border-top-left-radius: 15px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-header label {\n\tdisplay: inline-block;\n\tpadding-left: 0.5em;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests ol {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 15px;\n\t-moz-border-radius: 15px;\n\t-webkit-border-radius: 15px;\n\n\tbox-shadow: inset 0px 2px 13px #999;\n\t-moz-box-shadow: inset 0px 2px 13px #999;\n\t-webkit-box-shadow: inset 0px 2px 13px #999;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tmargin: 0.5em;\n\tpadding: 0.4em 0.5em 0.4em 0.5em;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #5E740B;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 15px 15px;\n\t-moz-border-radius: 0 0 15px 15px;\n\t-webkit-border-bottom-right-radius: 15px;\n\t-webkit-border-bottom-left-radius: 15px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/external/qunit.js",
    "content": "/**\n * QUnit v1.6.0 - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n(function( window ) {\n\nvar QUnit,\n\tconfig,\n\ttestId = 0,\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tdefined = {\n\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\tsessionStorage: (function() {\n\t\tvar x = \"qunit-test-string\";\n\t\ttry {\n\t\t\tsessionStorage.setItem( x, x );\n\t\t\tsessionStorage.removeItem( x );\n\t\t\treturn true;\n\t\t} catch( e ) {\n\t\t\treturn false;\n\t\t}\n\t}())\n};\n\nfunction Test( name, testName, expected, async, callback ) {\n\tthis.name = name;\n\tthis.testName = testName;\n\tthis.expected = expected;\n\tthis.async = async;\n\tthis.callback = callback;\n\tthis.assertions = [];\n}\n\nTest.prototype = {\n\tinit: function() {\n\t\tvar b, li,\n        tests = id( \"qunit-tests\" );\n\n\t\tif ( tests ) {\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = \"Running \" + this.name;\n\n\t\t\tli = document.createElement( \"li\" );\n\t\t\tli.appendChild( b );\n\t\t\tli.className = \"running\";\n\t\t\tli.id = this.id = \"qunit-test-output\" + testId++;\n\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif ( this.module !== config.previousModule ) {\n\t\t\tif ( config.previousModule ) {\n\t\t\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t});\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t} else if ( config.autorun ) {\n\t\t\trunLoggingCallbacks( \"moduleStart\", QUnit, {\n\t\t\t\tname: this.module\n\t\t\t});\n\t\t}\n\n\t\tconfig.current = this;\n\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment );\n\n\t\trunLoggingCallbacks( \"testStart\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t// allow utility functions to access the current test environment\n\t\t// TODO why??\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment );\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call( this.testEnvironment );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id( \"qunit-testresult\" );\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.name;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call( this.testEnvironment );\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.callback.call( this.testEnvironment );\n\t\t} catch( e ) {\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment );\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment );\n\t\t\t} catch( e ) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( this.expected != null && this.expected != this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\", this.stack );\n\t\t} else if ( this.expected == null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\", this.stack );\n\t\t}\n\n\t\tvar assertion, a, b, i, li, ol,\n\t\t\tgood = 0,\n\t\t\tbad = 0,\n\t\t\ttests = id( \"qunit-tests\" );\n\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tol = document.createElement( \"ol\" );\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tassertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement( \"li\" );\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || ( assertion.result ? \"okay\" : \"failed\" );\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif ( bad ) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-test-\" + this.module + \"-\" + this.testName, bad );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( bad === 0 ) {\n\t\t\t\tol.style.display = \"none\";\n\t\t\t}\n\n\t\t\t// `b` initialized at top of scope\n\t\t\tb = document.createElement( \"strong\" );\n\t\t\tb.innerHTML = this.name + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\t// `a` initialized at top of scope\n\t\t\ta = document.createElement( \"a\" );\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ filter: getText([b]).replace( /\\([^)]+\\)$/, \"\" ).replace( /(^\\s*|\\s*$)/g, \"\" ) });\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.nextSibling.nextSibling,\n\t\t\t\t\tdisplay = next.style.display;\n\t\t\t\tnext.style.display = display === \"none\" ? \"block\" : \"none\";\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function( e ) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() == \"span\" || target.nodeName.toLowerCase() == \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({\n\t\t\t\t\t\tfilter: getText([target]).replace( /\\([^)]+\\)$/, \"\" ).replace( /(^\\s*|\\s*$)/g, \"\" )\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// `li` initialized at top of scope\n\t\t\tli = id( this.id );\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunLoggingCallbacks( \"testDone\", QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length\n\t\t});\n\n\t\tQUnit.reset();\n\t},\n\n\tqueue: function() {\n\t\tvar bad,\n\t\t\ttest = this;\n\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\n\t\t// `bad` initialized at top of scope\n\t\t// defer when previous test run passed, if storage is available\n\t\tbad = QUnit.config.reorder && defined.sessionStorage &&\n\t\t\t\t\t\t+sessionStorage.getItem( \"qunit-test-\" + this.module + \"-\" + this.testName );\n\n\t\tif ( bad ) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize( run, true );\n\t\t}\n\t}\n};\n\n// `QUnit` initialized at top of scope\nQUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function( name, testEnvironment ) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnviroment = testEnvironment;\n\t},\n\n\tasyncTest: function( testName, expected, callback ) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test( testName, expected, callback, true );\n\t},\n\n\ttest: function( testName, expected, callback, async ) {\n\t\tvar test,\n\t\t\tname = \"<span class='test-name'>\" + escapeInnerText( testName ) + \"</span>\";\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tname = \"<span class='module-name'>\" + config.currentModule + \"</span>: \" + name;\n\t\t}\n\n\t\tif ( !validTest(config.currentModule + \": \" + testName) ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttest = new Test( name, testName, expected, async, callback );\n\t\ttest.module = config.currentModule;\n\t\ttest.moduleTestEnvironment = config.currentModuleTestEnviroment;\n\t\ttest.stack = sourceFromStacktrace( 2 );\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function( asserts ) {\n\t\tconfig.current.expected = asserts;\n\t},\n\n\t// Asserts true.\n\t// @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\tok: function( result, msg ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"ok() assertion outside test context, was \" + sourceFromStacktrace(2) );\n\t\t}\n\t\tresult = !!result;\n\n\t\tvar source,\n\t\t\tdetails = {\n\t\t\t\tresult: result,\n\t\t\t\tmessage: msg\n\t\t\t};\n\n\t\tmsg = escapeInnerText( msg || (result ? \"okay\" : \"failed\" ) );\n\t\tmsg = \"<span class='test-message'>\" + msg + \"</span>\";\n\n\t\tif ( !result ) {\n\t\t\tsource = sourceFromStacktrace( 2 );\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText( source ) + \"</pre></td></tr></table>\";\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t// Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values.\n\t// @example equal( format( \"Received {0} bytes.\", 2), \"Received 2 bytes.\" );\n\tequal: function( actual, expected, message ) {\n\t\tQUnit.push( expected == actual, actual, expected, message );\n\t},\n\n\tnotEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected != actual, actual, expected, message );\n\t},\n\n\tdeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\tnotDeepEqual: function( actual, expected, message ) {\n\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n\t},\n\n\tstrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected === actual, actual, expected, message );\n\t},\n\n\tnotStrictEqual: function( actual, expected, message ) {\n\t\tQUnit.push( expected !== actual, actual, expected, message );\n\t},\n\n\traises: function( block, expected, message ) {\n\t\tvar actual,\n\t\t\tok = false;\n\n\t\tif ( typeof expected === \"string\" ) {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\ttry {\n\t\t\tblock.call( config.current.testEnvironment );\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\n\t\tif ( actual ) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif ( !expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a regexp\n\t\t\t} else if ( QUnit.objectType( expected ) === \"regexp\" ) {\n\t\t\t\tok = expected.test( actual );\n\t\t\t// expected is a constructor\n\t\t\t} else if ( actual instanceof expected ) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if ( expected.call( {}, actual ) === true ) {\n\t\t\t\tok = true;\n\t\t\t}\n\t\t}\n\n\t\tQUnit.ok( ok, message );\n\t},\n\n\tstart: function( count ) {\n\t\tconfig.semaphore -= count || 1;\n\t\t// don't start until equal number of stop-calls\n\t\tif ( config.semaphore > 0 ) {\n\t\t\treturn;\n\t\t}\n\t\t// ignore if start is called more often then stop\n\t\tif ( config.semaphore < 0 ) {\n\t\t\tconfig.semaphore = 0;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\twindow.setTimeout(function() {\n\t\t\t\tif ( config.semaphore > 0 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout( config.timeout );\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess( true );\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess( true );\n\t\t}\n\t},\n\n\tstop: function( count ) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout( config.timeout );\n\t\t\tconfig.timeout = window.setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout );\n\t\t}\n\t}\n};\n\n// We want access to the constructor's prototype\n(function() {\n\tfunction F() {}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t// Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n// deprecated; still export them to window to provide clear error messages\n// next step: remove entirely\nQUnit.equals = function() {\n\tQUnit.push( false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\" );\n};\nQUnit.same = function() {\n\tQUnit.push( false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\" );\n};\n\n// Maintain internal state\n// `config` initialized at top of scope\nconfig = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\turlConfig: [ \"noglobals\", \"notrycatch\" ],\n\n\t// logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Load paramaters\n(function() {\n\tvar i,\n\t\tlocation = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\tconfig.filter = urlParams.filter;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === \"file:\";\n}());\n\n// Expose the API as global variables, unless an 'exports' object exists,\n// in that case we assume we're in CommonJS - export everything at the end\nif ( typeof exports === \"undefined\" ) {\n\textend( window, QUnit );\n\twindow.QUnit = QUnit;\n}\n\n// define these after exposing globals to keep them in these QUnit namespace only\nextend( QUnit, {\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend( config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 0\n\t\t});\n\n\t\tvar tests, banner, result,\n\t\t\tqunit = id( \"qunit\" );\n\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t\"<h1 id='qunit-header'>\" + escapeInnerText( document.title ) + \"</h1>\" +\n\t\t\t\t\"<h2 id='qunit-banner'></h2>\" +\n\t\t\t\t\"<div id='qunit-testrunner-toolbar'></div>\" +\n\t\t\t\t\"<h2 id='qunit-userAgent'></h2>\" +\n\t\t\t\t\"<ol id='qunit-tests'></ol>\";\n\t\t}\n\n\t\ttests = id( \"qunit-tests\" );\n\t\tbanner = id( \"qunit-banner\" );\n\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = \"Running...<br/>&nbsp;\";\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.\n\treset: function() {\n\t\tvar fixture;\n\n\t\tif ( window.jQuery ) {\n\t\t\tjQuery( \"#qunit-fixture\" ).html( config.fixture );\n\t\t} else {\n\t\t\tfixture = id( \"qunit-fixture\" );\n\t\t\tif ( fixture ) {\n\t\t\t\tfixture.innerHTML = config.fixture;\n\t\t\t}\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent( \"MouseEvents\" );\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\n\t\t\telem.dispatchEvent( event );\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent( \"on\" + type );\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) == type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif ( typeof obj === \"undefined\" ) {\n\t\t\t\treturn \"undefined\";\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif ( obj === null ) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar type = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/)[1] || \"\";\n\n\t\tswitch ( type ) {\n\t\t\tcase \"Number\":\n\t\t\t\tif ( isNaN(obj) ) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase \"String\":\n\t\t\tcase \"Boolean\":\n\t\t\tcase \"Array\":\n\t\t\tcase \"Date\":\n\t\t\tcase \"RegExp\":\n\t\t\tcase \"Function\":\n\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif ( typeof obj === \"object\" ) {\n\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function( result, actual, expected, message ) {\n\t\tif ( !config.current ) {\n\t\t\tthrow new Error( \"assertion outside test context, was \" + sourceFromStacktrace() );\n\t\t}\n\n\t\tvar output, source,\n\t\t\tdetails = {\n\t\t\t\tresult: result,\n\t\t\t\tmessage: message,\n\t\t\t\tactual: actual,\n\t\t\t\texpected: expected\n\t\t\t};\n\n\t\tmessage = escapeInnerText( message ) || ( result ? \"okay\" : \"failed\" );\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\tif ( !result ) {\n\t\t\texpected = escapeInnerText( QUnit.jsDump.parse(expected) );\n\t\t\tactual = escapeInnerText( QUnit.jsDump.parse(actual) );\n\t\t\toutput += \"<table><tr class='test-expected'><th>Expected: </th><td><pre>\" + expected + \"</pre></td></tr>\";\n\n\t\t\tif ( actual != expected ) {\n\t\t\t\toutput += \"<tr class='test-actual'><th>Result: </th><td><pre>\" + actual + \"</pre></td></tr>\";\n\t\t\t\toutput += \"<tr class='test-diff'><th>Diff: </th><td><pre>\" + QUnit.diff( expected, actual ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\tsource = sourceFromStacktrace();\n\n\t\t\tif ( source ) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += \"<tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText( source ) + \"</pre></td></tr>\";\n\t\t\t}\n\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function( message, source ) {\n\t\tvar output,\n\t\t\tdetails = {\n\t\t\t\tresult: false,\n\t\t\t\tmessage: message\n\t\t\t};\n\n\t\tmessage = escapeInnerText(message ) || \"error\";\n\t\tmessage = \"<span class='test-message'>\" + message + \"</span>\";\n\t\toutput = message;\n\n\t\tif ( source ) {\n\t\t\tdetails.source = source;\n\t\t\toutput += \"<table><tr class='test-source'><th>Source: </th><td><pre>\" + escapeInnerText( source ) + \"</pre></td></tr></table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( \"log\", QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar key,\n\t\t\tquerystring = \"?\";\n\n\t\tfor ( key in params ) {\n\t\t\tif ( !hasOwn.call( params, key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t}\n\t\treturn window.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent\n});\n\n// QUnit.constructor is set to the empty F() above so that we can add to it's prototype later\n// Doing this allows us to tell if the following methods have been overwritten on the actual\n// QUnit object, which is a deprecated way of using the callbacks.\nextend( QUnit.constructor.prototype, {\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback( \"begin\" ),\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback( \"done\" ),\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback( \"log\" ),\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback( \"testStart\" ),\n\t// testDone: { name, failed, passed, total }\n\ttestDone: registerLoggingCallback( \"testDone\" ),\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback( \"moduleStart\" ),\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback( \"moduleDone\" )\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( \"begin\", QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar banner, filter, i, label, len, main, ol, toolbar, userAgent, val,\n\t\turlConfigHtml = \"\",\n\t\toldconfig = extend( {}, config );\n\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tlen = config.urlConfig.length;\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tconfig[val] = QUnit.urlParams[val];\n\t\turlConfigHtml += \"<label><input name='\" + val + \"' type='checkbox'\" + ( config[val] ? \" checked='checked'\" : \"\" ) + \">\" + val + \"</label>\";\n\t}\n\n\t// `userAgent` initialized at top of scope\n\tuserAgent = id( \"qunit-userAgent\" );\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\n\t// `banner` initialized at top of scope\n\tbanner = id( \"qunit-header\" );\n\tif ( banner ) {\n\t\tbanner.innerHTML = \"<a href='\" + QUnit.url({ filter: undefined }) + \"'>\" + banner.innerHTML + \"</a> \" + urlConfigHtml;\n\t\taddEvent( banner, \"change\", function( event ) {\n\t\t\tvar params = {};\n\t\t\tparams[ event.target.name ] = event.target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t}\n\n\t// `toolbar` initialized at top of scope\n\ttoolbar = id( \"qunit-testrunner-toolbar\" );\n\tif ( toolbar ) {\n\t\t// `filter` initialized at top of scope\n\t\tfilter = document.createElement( \"input\" );\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar tmp,\n\t\t\t\tol = document.getElementById( \"qunit-tests\" );\n\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\ttmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace( / hidepass /, \" \" );\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem( \"qunit-filter-passed-tests\", \"true\" );\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem( \"qunit-filter-passed-tests\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( \"qunit-filter-passed-tests\" ) ) {\n\t\t\tfilter.checked = true;\n\t\t\t// `ol` initialized at top of scope\n\t\t\tol = document.getElementById( \"qunit-tests\" );\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\t// `label` initialized at top of scope\n\t\tlabel = document.createElement( \"label\" );\n\t\tlabel.setAttribute( \"for\", \"qunit-filter-pass\" );\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\t}\n\n\t// `main` initialized at top of scope\n\tmain = id( \"qunit-fixture\" );\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif ( config.autostart ) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent( window, \"load\", QUnit.load );\n\n// addEvent(window, \"error\" ) gives us a useless event object\nwindow.onerror = function( message, file, line ) {\n\tif ( QUnit.config.current ) {\n\t\tQUnit.pushFailure( message, file + \":\" + line );\n\t} else {\n\t\tQUnit.test( \"global failure\", function() {\n\t\t\tQUnit.pushFailure( message, file + \":\" + line );\n\t\t});\n\t}\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( \"moduleDone\", QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t});\n\t}\n\n\tvar i, key,\n\t\tbanner = id( \"qunit-banner\" ),\n\t\ttests = id( \"qunit-tests\" ),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t\"Tests completed in \",\n\t\t\truntime,\n\t\t\t\" milliseconds.<br/>\",\n\t\t\t\"<span class='passed'>\",\n\t\t\tpassed,\n\t\t\t\"</span> tests of <span class='total'>\",\n\t\t\tconfig.stats.all,\n\t\t\t\"</span> passed, <span class='failed'>\",\n\t\t\tconfig.stats.bad,\n\t\t\t\"</span> failed.\"\n\t\t].join( \"\" );\n\n\tif ( banner ) {\n\t\tbanner.className = ( config.stats.bad ? \"qunit-fail\" : \"qunit-pass\" );\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t( config.stats.bad ? \"\\u2716\" : \"\\u2714\" ),\n\t\t\tdocument.title.replace( /^[\\u2714\\u2716] /i, \"\" )\n\t\t].join( \" \" );\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\t// `key` & `i` initialized at top of scope\n\t\tfor ( i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf( \"qunit-test-\" ) === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\trunLoggingCallbacks( \"done\", QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t});\n}\n\nfunction validTest( name ) {\n\tvar not,\n\t\tfilter = config.filter,\n\t\trun = false;\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tnot = filter.charAt( 0 ) === \"!\";\n\n\tif ( not ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\tif ( name.indexOf( filter ) !== -1 ) {\n\t\treturn !not;\n\t}\n\n\tif ( not ) {\n\t\trun = true;\n\t}\n\n\treturn run;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset || 3;\n\n\tvar stack;\n\n\tif ( e.stacktrace ) {\n\t\t// Opera\n\t\treturn e.stacktrace.split( \"\\n\" )[ offset + 3 ];\n\t} else if ( e.stack ) {\n\t\t// Firefox, Chrome\n\t\tstack = e.stack.split( \"\\n\" );\n\t\tif (/^error$/i.test( stack[0] ) ) {\n\t\t\tstack.shift();\n\t\t}\n\t\treturn stack[ offset ];\n\t} else if ( e.sourceURL ) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace( offset ) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\nfunction escapeInnerText( s ) {\n\tif ( !s ) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\treturn s.replace( /[\\&<>]/g, function( s ) {\n\t\tswitch( s ) {\n\t\t\tcase \"&\": return \"&amp;\";\n\t\t\tcase \"<\": return \"&lt;\";\n\t\t\tcase \">\": return \"&gt;\";\n\t\t\tdefault: return s;\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess( last );\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\twindow.setTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\t// in Opera sometimes DOM element ids show up here, ignore them\n\t\t\tif ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconfig.pollution.push( key );\n\t\t}\n\t}\n}\n\nfunction checkPollution( name ) {\n\tvar newGlobals,\n\t\tdeletedGlobals,\n\t\told = config.pollution;\n\n\tsaveGlobal();\n\n\tnewGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tdeletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar i, j,\n\t\tresult = a.slice();\n\n\tfor ( i = 0; i < result.length; i++ ) {\n\t\tfor ( j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend( a, b ) {\n\tfor ( var prop in b ) {\n\t\tif ( b[ prop ] === undefined ) {\n\t\t\tdelete a[ prop ];\n\n\t\t// Avoid \"Member not found\" error in IE8 caused by setting window.constructor\n\t\t} else if ( prop !== \"constructor\" || a !== window ) {\n\t\t\ta[ prop ] = b[ prop ];\n\t\t}\n\t}\n\n\treturn a;\n}\n\nfunction addEvent( elem, type, fn ) {\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t} else if ( elem.attachEvent ) {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t} else {\n\t\tfn();\n\t}\n}\n\nfunction id( name ) {\n\treturn !!( typeof document !== \"undefined\" && document && document.getElementById ) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback( key ) {\n\treturn function( callback ) {\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks( key, scope, args ) {\n\t//debugger;\n\tvar i, callbacks;\n\tif ( QUnit.hasOwnProperty( key ) ) {\n\t\tQUnit[ key ].call(scope, args );\n\t} else {\n\t\tcallbacks = config[ key ];\n\t\tfor ( i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[ i ].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks( o, callbacks, args ) {\n\t\tvar prop = QUnit.objectType( o );\n\t\tif ( prop ) {\n\t\t\tif ( QUnit.objectType( callbacks[ prop ] ) === \"function\" ) {\n\t\t\t\treturn callbacks[ prop ].apply( callbacks, args );\n\t\t\t} else {\n\t\t\t\treturn callbacks[ prop ]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\t// the real equiv function\n\tvar innerEquiv,\n\t\t// stack to decide between skip/abort functions\n\t\tcallers = [],\n\t\t// stack to avoiding loops from circular referencing\n\t\tparents = [],\n\n\t\tgetProto = Object.getPrototypeOf || function ( obj ) {\n\t\t\treturn obj.__proto__;\n\t\t},\n\t\tcallbacks = (function () {\n\n\t\t\t// for string, boolean, number and null\n\t\t\tfunction useStrictEquality( b, a ) {\n\t\t\t\tif ( b instanceof a.constructor || a instanceof b.constructor ) {\n\t\t\t\t\t// to catch short annotaion VS 'new' annotation of a\n\t\t\t\t\t// declaration\n\t\t\t\t\t// e.g. var i = 1;\n\t\t\t\t\t// var j = new Number(1);\n\t\t\t\t\treturn a == b;\n\t\t\t\t} else {\n\t\t\t\t\treturn a === b;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"string\": useStrictEquality,\n\t\t\t\t\"boolean\": useStrictEquality,\n\t\t\t\t\"number\": useStrictEquality,\n\t\t\t\t\"null\": useStrictEquality,\n\t\t\t\t\"undefined\": useStrictEquality,\n\n\t\t\t\t\"nan\": function( b ) {\n\t\t\t\t\treturn isNaN( b );\n\t\t\t\t},\n\n\t\t\t\t\"date\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t\t},\n\n\t\t\t\t\"regexp\": function( b, a ) {\n\t\t\t\t\treturn QUnit.objectType( b ) === \"regexp\" &&\n\t\t\t\t\t\t// the regex itself\n\t\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t\t// and its modifers\n\t\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t\t// (gmi) ...\n\t\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\t\ta.multiline === b.multiline;\n\t\t\t\t},\n\n\t\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t\t// - abort otherwise,\n\t\t\t\t// initial === would have catch identical references anyway\n\t\t\t\t\"function\": function() {\n\t\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t\t},\n\n\t\t\t\t\"array\": function( b, a ) {\n\t\t\t\t\tvar i, j, len, loop;\n\n\t\t\t\t\t// b could be an object literal here\n\t\t\t\t\tif ( QUnit.objectType( b ) !== \"array\" ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tlen = a.length;\n\t\t\t\t\tif ( len !== b.length ) {\n\t\t\t\t\t\t// safe and faster\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\tif ( parents[j] === a[i] ) {\n\t\t\t\t\t\t\t\tloop = true;// dont rewalk array\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n\t\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparents.pop();\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\n\t\t\t\t\"object\": function( b, a ) {\n\t\t\t\t\tvar i, j, loop,\n\t\t\t\t\t\t// Default to true\n\t\t\t\t\t\teq = true,\n\t\t\t\t\t\taProperties = [],\n\t\t\t\t\t\tbProperties = [];\n\n\t\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t\t// instanceof\n\t\t\t\t\tif ( a.constructor !== b.constructor ) {\n\t\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\t\tif ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||\n\t\t\t\t\t\t\t( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// stack constructor before traversing properties\n\t\t\t\t\tcallers.push( a.constructor );\n\t\t\t\t\t// track reference to avoid circular references\n\t\t\t\t\tparents.push( a );\n\n\t\t\t\t\tfor ( i in a ) { // be strict: don't ensures hasOwnProperty\n\t\t\t\t\t\t\t\t\t// and go deep\n\t\t\t\t\t\tloop = false;\n\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n\t\t\t\t\t\t\tif ( parents[j] === a[i] ) {\n\t\t\t\t\t\t\t\t// don't go down the same path twice\n\t\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\taProperties.push(i); // collect a's properties\n\n\t\t\t\t\t\tif (!loop && !innerEquiv( a[i], b[i] ) ) {\n\t\t\t\t\t\t\teq = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallers.pop(); // unstack, we are done\n\t\t\t\t\tparents.pop();\n\n\t\t\t\t\tfor ( i in b ) {\n\t\t\t\t\t\tbProperties.push( i ); // collect b's properties\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensures identical properties name\n\t\t\t\t\treturn eq && innerEquiv( aProperties.sort(), bProperties.sort() );\n\t\t\t\t}\n\t\t\t};\n\t\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = [].slice.apply( arguments );\n\t\tif ( args.length < 2 ) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function( a, b ) {\n\t\t\tif ( a === b ) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if ( a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b) ) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) );\n\t};\n\n\treturn innerEquiv;\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn '\"' + str.toString().replace( /\"/g, '\\\\\"' ) + '\"';\n\t}\n\tfunction literal( o ) {\n\t\treturn o + \"\";\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( \",\" + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( \"[\", ret, \"]\" );\n\t}\n\n\tvar reName = /^function (\\w+)/,\n\t\tjsDump = {\n\t\t\tparse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance\n\t\t\t\tstack = stack || [ ];\n\t\t\t\tvar inStack, res,\n\t\t\t\t\tparser = this.parsers[ type || this.typeOf(obj) ];\n\n\t\t\t\ttype = typeof parser;\n\t\t\t\tinStack = inArray( obj, stack );\n\n\t\t\t\tif ( inStack != -1 ) {\n\t\t\t\t\treturn \"recursion(\" + (inStack - stack.length) + \")\";\n\t\t\t\t}\n\t\t\t\t//else\n\t\t\t\tif ( type == \"function\" )  {\n\t\t\t\t\tstack.push( obj );\n\t\t\t\t\tres = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t\t// else\n\t\t\t\treturn ( type == \"string\" ) ? parser : this.parsers.error;\n\t\t\t},\n\t\t\ttypeOf: function( obj ) {\n\t\t\t\tvar type;\n\t\t\t\tif ( obj === null ) {\n\t\t\t\t\ttype = \"null\";\n\t\t\t\t} else if ( typeof obj === \"undefined\" ) {\n\t\t\t\t\ttype = \"undefined\";\n\t\t\t\t} else if ( QUnit.is( \"RegExp\", obj) ) {\n\t\t\t\t\ttype = \"regexp\";\n\t\t\t\t} else if ( QUnit.is( \"Date\", obj) ) {\n\t\t\t\t\ttype = \"date\";\n\t\t\t\t} else if ( QUnit.is( \"Function\", obj) ) {\n\t\t\t\t\ttype = \"function\";\n\t\t\t\t} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\" ) {\n\t\t\t\t\ttype = \"window\";\n\t\t\t\t} else if ( obj.nodeType === 9 ) {\n\t\t\t\t\ttype = \"document\";\n\t\t\t\t} else if ( obj.nodeType ) {\n\t\t\t\t\ttype = \"node\";\n\t\t\t\t} else if (\n\t\t\t\t\t// native arrays\n\t\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t\t// NodeList objects\n\t\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t\t) {\n\t\t\t\t\ttype = \"array\";\n\t\t\t\t} else {\n\t\t\t\t\ttype = typeof obj;\n\t\t\t\t}\n\t\t\t\treturn type;\n\t\t\t},\n\t\t\tseparator: function() {\n\t\t\t\treturn this.multiline ?\tthis.HTML ? \"<br />\" : \"\\n\" : this.HTML ? \"&nbsp;\" : \" \";\n\t\t\t},\n\t\t\tindent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\t\tif ( !this.multiline ) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tvar chr = this.indentChar;\n\t\t\t\tif ( this.HTML ) {\n\t\t\t\t\tchr = chr.replace( /\\t/g, \"   \" ).replace( / /g, \"&nbsp;\" );\n\t\t\t\t}\n\t\t\t\treturn new Array( this._depth_ + (extra||0) ).join(chr);\n\t\t\t},\n\t\t\tup: function( a ) {\n\t\t\t\tthis._depth_ += a || 1;\n\t\t\t},\n\t\t\tdown: function( a ) {\n\t\t\t\tthis._depth_ -= a || 1;\n\t\t\t},\n\t\t\tsetParser: function( name, parser ) {\n\t\t\t\tthis.parsers[name] = parser;\n\t\t\t},\n\t\t\t// The next 3 are exposed so you can use them\n\t\t\tquote: quote,\n\t\t\tliteral: literal,\n\t\t\tjoin: join,\n\t\t\t//\n\t\t\t_depth_: 1,\n\t\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\t\tparsers: {\n\t\t\t\twindow: \"[Window]\",\n\t\t\t\tdocument: \"[Document]\",\n\t\t\t\terror: \"[ERROR]\", //when no parser is found, shouldn\"t happen\n\t\t\t\tunknown: \"[Unknown]\",\n\t\t\t\t\"null\": \"null\",\n\t\t\t\t\"undefined\": \"undefined\",\n\t\t\t\t\"function\": function( fn ) {\n\t\t\t\t\tvar ret = \"function\",\n\t\t\t\t\t\tname = \"name\" in fn ? fn.name : (reName.exec(fn) || [])[1];//functions never have name in IE\n\n\t\t\t\t\tif ( name ) {\n\t\t\t\t\t\tret += \" \" + name;\n\t\t\t\t\t}\n\t\t\t\t\tret += \"( \";\n\n\t\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, \"functionArgs\" ), \"){\" ].join( \"\" );\n\t\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,\"functionCode\" ), \"}\" );\n\t\t\t\t},\n\t\t\t\tarray: array,\n\t\t\t\tnodelist: array,\n\t\t\t\t\"arguments\": array,\n\t\t\t\tobject: function( map, stack ) {\n\t\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\t\tQUnit.jsDump.up();\n\t\t\t\t\tif ( Object.keys ) {\n\t\t\t\t\t\tkeys = Object.keys( map );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tkeys = [];\n\t\t\t\t\t\tfor ( key in map ) {\n\t\t\t\t\t\t\tkeys.push( key );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tkeys.sort();\n\t\t\t\t\tfor ( i = 0; i < keys.length; i++ ) {\n\t\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\t\tval = map[ key ];\n\t\t\t\t\t\tret.push( QUnit.jsDump.parse( key, \"key\" ) + \": \" + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t\t}\n\t\t\t\t\tQUnit.jsDump.down();\n\t\t\t\t\treturn join( \"{\", ret, \"}\" );\n\t\t\t\t},\n\t\t\t\tnode: function( node ) {\n\t\t\t\t\tvar a, val,\n\t\t\t\t\t\topen = QUnit.jsDump.HTML ? \"&lt;\" : \"<\",\n\t\t\t\t\t\tclose = QUnit.jsDump.HTML ? \"&gt;\" : \">\",\n\t\t\t\t\t\ttag = node.nodeName.toLowerCase(),\n\t\t\t\t\t\tret = open + tag;\n\n\t\t\t\t\tfor ( a in QUnit.jsDump.DOMAttrs ) {\n\t\t\t\t\t\tval = node[ QUnit.jsDump.DOMAttrs[a] ];\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\tret += \" \" + a + \"=\" + QUnit.jsDump.parse( val, \"attribute\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn ret + close + open + \"/\" + tag + close;\n\t\t\t\t},\n\t\t\t\tfunctionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function\n\t\t\t\t\tvar args,\n\t\t\t\t\t\tl = fn.length;\n\n\t\t\t\t\tif ( !l ) {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\targs = new Array(l);\n\t\t\t\t\twhile ( l-- ) {\n\t\t\t\t\t\targs[l] = String.fromCharCode(97+l);//97 is 'a'\n\t\t\t\t\t}\n\t\t\t\t\treturn \" \" + args.join( \", \" ) + \" \";\n\t\t\t\t},\n\t\t\t\tkey: quote, //object calls it internally, the key part of an item in a map\n\t\t\t\tfunctionCode: \"[code]\", //function calls it internally, it's the content of the function\n\t\t\t\tattribute: quote, //node calls it internally, it's an html attribute value\n\t\t\t\tstring: quote,\n\t\t\t\tdate: quote,\n\t\t\t\tregexp: literal, //regex\n\t\t\t\tnumber: literal,\n\t\t\t\t\"boolean\": literal\n\t\t\t},\n\t\t\tDOMAttrs: {\n\t\t\t\t//attributes to dump from nodes, name=>realName\n\t\t\t\tid: \"id\",\n\t\t\t\tname: \"name\",\n\t\t\t\t\"class\": \"className\"\n\t\t\t},\n\t\t\tHTML: false,//if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\t\tindentChar: \"  \",//indentation unit\n\t\t\tmultiline: true //if true, items in a collection, are separated by a \\n, else just a space.\n\t\t};\n\n\treturn jsDump;\n}());\n\n// from Sizzle.js\nfunction getText( elems ) {\n\tvar i, elem,\n\t\tret = \"\";\n\n\tfor ( i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n// from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff( \"the quick brown fox jumped over\", \"the quick fox jumps over\" ) == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\tfunction diff( o, n ) {\n\t\tvar i,\n\t\t\tns = {},\n\t\t\tos = {};\n\n\t\tfor ( i = 0; i < n.length; i++ ) {\n\t\t\tif ( ns[ n[i] ] == null ) {\n\t\t\t\tns[ n[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[ n[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i = 0; i < o.length; i++ ) {\n\t\t\tif ( os[ o[i] ] == null ) {\n\t\t\t\tos[ o[i] ] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[ o[i] ].rows.push( i );\n\t\t}\n\n\t\tfor ( i in ns ) {\n\t\t\tif ( !hasOwn.call( ns, i ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( ns[i].rows.length == 1 && typeof os[i] != \"undefined\" && os[i].rows.length == 1 ) {\n\t\t\t\tn[ ns[i].rows[0] ] = {\n\t\t\t\t\ttext: n[ ns[i].rows[0] ],\n\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t};\n\t\t\t\to[ os[i].rows[0] ] = {\n\t\t\t\t\ttext: o[ os[i].rows[0] ],\n\t\t\t\t\trow: ns[i].rows[0]\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = 0; i < n.length - 1; i++ ) {\n\t\t\tif ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&\n\t\t\t\t\t\tn[ i + 1 ] == o[ n[i].row + 1 ] ) {\n\n\t\t\t\tn[ i + 1 ] = {\n\t\t\t\t\ttext: n[ i + 1 ],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row + 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row + 1 ],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = n.length - 1; i > 0; i-- ) {\n\t\t\tif ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&\n\t\t\t\t\t\tn[ i - 1 ] == o[ n[i].row - 1 ]) {\n\n\t\t\t\tn[ i - 1 ] = {\n\t\t\t\t\ttext: n[ i - 1 ],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[ n[i].row - 1 ] = {\n\t\t\t\t\ttext: o[ n[i].row - 1 ],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function( o, n ) {\n\t\to = o.replace( /\\s+$/, \"\" );\n\t\tn = n.replace( /\\s+$/, \"\" );\n\n\t\tvar i, pre,\n\t\t\tstr = \"\",\n\t\t\tout = diff( o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/) ),\n\t\t\toSpace = o.match(/\\s+/g),\n\t\t\tnSpace = n.match(/\\s+/g);\n\n\t\tif ( oSpace == null ) {\n\t\t\toSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\toSpace.push( \" \" );\n\t\t}\n\n\t\tif ( nSpace == null ) {\n\t\t\tnSpace = [ \" \" ];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push( \" \" );\n\t\t}\n\n\t\tif ( out.n.length === 0 ) {\n\t\t\tfor ( i = 0; i < out.o.length; i++ ) {\n\t\t\t\tstr += \"<del>\" + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ( out.n[0].text == null ) {\n\t\t\t\tfor ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\tstr += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( i = 0; i < out.n.length; i++ ) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += \"<ins>\" + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// `pre` initialized at top of scope\n\t\t\t\t\tpre = \"\";\n\n\t\t\t\t\tfor ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {\n\t\t\t\t\t\tpre += \"<del>\" + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS enviroments, export everything\nif ( typeof exports !== \"undefined\" ) {\n\textend(exports, QUnit);\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/grunt.js",
    "content": "/*jshint node: true */\nmodule.exports = function( grunt ) {\n\nvar // modules\n\tfs = require( \"fs\" ),\n\tpath = require( \"path\" ),\n\trequest = require( \"request\" ),\n\n\t// files\n\tcoreFiles = [\n\t\t\"jquery.ui.core.js\",\n\t\t\"jquery.ui.widget.js\",\n\t\t\"jquery.ui.mouse.js\",\n\t\t\"jquery.ui.draggable.js\",\n\t\t\"jquery.ui.droppable.js\",\n\t\t\"jquery.ui.resizable.js\",\n\t\t\"jquery.ui.selectable.js\",\n\t\t\"jquery.ui.sortable.js\",\n\t\t\"jquery.effects.core.js\"\n\t],\n\n\tuiFiles = coreFiles.map(function( file ) {\n\t\treturn \"ui/\" + file;\n\t}).concat( grunt.file.expandFiles( \"ui/*.js\" ).filter(function( file ) {\n\t\treturn coreFiles.indexOf( file.substring(3) ) === -1;\n\t})),\n\n\tallI18nFiles = grunt.file.expandFiles( \"ui/i18n/*.js\" ),\n\n\tcssFiles = [\n\t\t\"core\",\n\t\t\"accordion\",\n\t\t\"autocomplete\",\n\t\t\"button\",\n\t\t\"datepicker\",\n\t\t\"dialog\",\n\t\t\"menu\",\n\t\t\"progressbar\",\n\t\t\"resizable\",\n\t\t\"selectable\",\n\t\t\"slider\",\n\t\t\"spinner\",\n\t\t\"tabs\",\n\t\t\"tooltip\",\n\t\t\"theme\"\n\t].map(function( component ) {\n\t\treturn \"themes/base/jquery.ui.\" + component + \".css\";\n\t}),\n\n\t// minified files\n\tminify = {\n\t\t\"dist/jquery-ui.min.js\": [ \"<banner:meta.bannerAll>\", \"dist/jquery-ui.js\" ],\n\t\t\"dist/i18n/jquery-ui-i18n.min.js\": [ \"<banner:meta.bannerI18n>\", \"dist/i18n/jquery-ui-i18n.js\" ]\n\t},\n\n\tminifyCSS = {\n\t\t\"dist/jquery-ui.min.css\": \"dist/jquery-ui.css\"\n\t},\n\n\tcompareFiles = {\n\t\tall: [\n\t\t\t\"dist/jquery-ui.js\",\n\t\t\t\"dist/jquery-ui.min.js\"\n\t\t]\n\t};\n\nfunction mapMinFile( file ) {\n\treturn \"dist/\" + file.replace( /\\.js$/, \".min.js\" ).replace( /ui\\//, \"minified/\" );\n}\n\nuiFiles.concat( allI18nFiles ).forEach(function( file ) {\n\tminify[ mapMinFile( file ) ] = [ \"<banner>\", file ];\n});\n\ncssFiles.forEach(function( file ) {\n\tminifyCSS[ \"dist/\" + file.replace( /\\.css$/, \".min.css\" ).replace( /themes\\/base\\//, \"themes/base/minified/\" ) ] = [ \"<banner>\", \"<strip_all_banners:\" + file + \">\" ];\n});\n\nuiFiles.forEach(function( file ) {\n\tcompareFiles[ file ] = [ file,  mapMinFile( file ) ];\n});\n\n// csslint and cssmin tasks\ngrunt.loadNpmTasks( \"grunt-css\" );\n// file size comparison tasks\ngrunt.loadNpmTasks( \"grunt-compare-size\" );\n// html validation task\ngrunt.loadNpmTasks( \"grunt-html\" );\n// local testswarm and build tasks\ngrunt.loadTasks( 'build/tasks');\n\ngrunt.registerHelper( \"strip_all_banners\", function( filepath ) {\n\treturn grunt.file.read( filepath ).replace( /^\\s*\\/\\*[\\s\\S]*?\\*\\/\\s*/g, \"\" );\n});\n\nfunction stripBanner( files ) {\n\treturn files.map(function( file ) {\n\t\treturn \"<strip_all_banners:\" + file + \">\";\n\t});\n}\n\nfunction stripDirectory( file ) {\n\t// TODO: we're receiving the directive, so we need to strip the trailing >\n\t// we should be receving a clean path without the directive\n\treturn file.replace( /.+\\/(.+?)>?$/, \"$1\" );\n}\n// allow access from banner template\nglobal.stripDirectory = stripDirectory;\n\nfunction createBanner( files ) {\n\t// strip folders\n\tvar fileNames = files && files.map( stripDirectory );\n\treturn \"/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - \" +\n\t\t\"<%= grunt.template.today('isoDate') %>\\n\" +\n\t\t\"<%= pkg.homepage ? '* ' + pkg.homepage + '\\n' : '' %>\" +\n\t\t\"* Includes: \" + (files ? fileNames.join(\", \") : \"<%= stripDirectory(grunt.task.current.file.src[1]) %>\") + \"\\n\" +\n\t\t\"* Copyright (c) <%= grunt.template.today('yyyy') %> <%= pkg.author.name %>;\" +\n\t\t\" Licensed <%= _.pluck(pkg.licenses, 'type').join(', ') %> */\";\n}\n\ngrunt.initConfig({\n\tpkg: \"<json:package.json>\",\n\tfiles: {\n\t\tdist: \"<%= pkg.name %>-<%= pkg.version %>\",\n\t\tcdn: \"<%= pkg.name %>-<%= pkg.version %>-cdn\",\n\t\tthemes: \"<%= pkg.name %>-themes-<%= pkg.version %>\"\n\t},\n\tmeta: {\n\t\tbanner: createBanner(),\n\t\tbannerAll: createBanner( uiFiles ),\n\t\tbannerI18n: createBanner( allI18nFiles ),\n\t\tbannerCSS: createBanner( cssFiles )\n\t},\n\tcompare_size: compareFiles,\n\tconcat: {\n\t\tui: {\n\t\t\tsrc: [ \"<banner:meta.bannerAll>\", stripBanner( uiFiles ) ],\n\t\t\tdest: \"dist/jquery-ui.js\"\n\t\t},\n\t\ti18n: {\n\t\t\tsrc: [ \"<banner:meta.bannerI18n>\", allI18nFiles ],\n\t\t\tdest: \"dist/i18n/jquery-ui-i18n.js\"\n\t\t},\n\t\tcss: {\n\t\t\tsrc: [ \"<banner:meta.bannerCSS>\", stripBanner( cssFiles ) ],\n\t\t\tdest: \"dist/jquery-ui.css\"\n\t\t}\n\t},\n\tmin: minify,\n\tcssmin: minifyCSS,\n\thtmllint: {\n\t\t// ignore files that contain invalid html, used only for ajax content testing\n\t\tall: grunt.file.expand( [ \"demos/**/*.html\", \"tests/**/*.html\" ] ).filter(function( file ) {\n\t\t\treturn !/(?:ajax\\/content\\d\\.html|tabs\\/data\\/test\\.html|tests\\/unit\\/core\\/core\\.html)/.test( file );\n\t\t})\n\t},\n\tcopy: {\n\t\tdist: {\n\t\t\tsrc: [\n\t\t\t\t\"AUTHORS.txt\",\n\t\t\t\t\"GPL-LICENSE.txt\",\n\t\t\t\t\"jquery-*.js\",\n\t\t\t\t\"MIT-LICENSE.txt\",\n\t\t\t\t\"README.md\",\n\t\t\t\t\"grunt.js\",\n\t\t\t\t\"package.json\",\n\t\t\t\t\"ui/**/*\",\n\t\t\t\t\"demos/**/*\",\n\t\t\t\t\"themes/**/*\",\n\t\t\t\t\"external/**/*\",\n\t\t\t\t\"tests/**/*\"\n\t\t\t],\n\t\t\trenames: {\n\t\t\t\t\"dist/jquery-ui.js\": \"ui/jquery-ui.js\",\n\t\t\t\t\"dist/jquery-ui.min.js\": \"ui/minified/jquery-ui.min.js\",\n\t\t\t\t\"dist/i18n/jquery-ui-i18n.js\": \"ui/i18n/jquery-ui-i18n.js\",\n\t\t\t\t\"dist/i18n/jquery-ui-i18n.min.js\": \"ui/minified/i18n/jquery-ui-i18n.min.js\",\n\t\t\t\t\"dist/jquery-ui.css\": \"themes/base/jquery-ui.css\",\n\t\t\t\t\"dist/jquery-ui.min.css\": \"themes/base/minified/jquery-ui.min.css\"\n\t\t\t},\n\t\t\tdest: \"dist/<%= files.dist %>\"\n\t\t},\n\t\tdist_min: {\n\t\t\tsrc: \"dist/minified/**/*\",\n\t\t\tstrip: /^dist/,\n\t\t\tdest: \"dist/<%= files.dist %>/ui\"\n\t\t},\n\t\tdist_css_min: {\n\t\t\tsrc: \"dist/themes/base/minified/*.css\",\n\t\t\tstrip: /^dist/,\n\t\t\tdest: \"dist/<%= files.dist %>\"\n\t\t},\n\t\tdist_units_images: {\n\t\t\tsrc: \"themes/base/images/*\",\n\t\t\tstrip: /^themes\\/base\\//,\n\t\t\tdest: \"dist/\"\n\t\t},\n\t\tdist_min_images: {\n\t\t\tsrc: \"themes/base/images/*\",\n\t\t\tstrip: /^themes\\/base\\//,\n\t\t\tdest: \"dist/<%= files.dist %>/themes/base/minified\"\n\t\t},\n\t\tcdn: {\n\t\t\tsrc: [\n\t\t\t\t\"AUTHORS.txt\",\n\t\t\t\t\"GPL-LICENSE.txt\",\n\t\t\t\t\"MIT-LICENSE.txt\",\n\t\t\t\t\"ui/*.js\",\n\t\t\t\t\"package.json\"\n\t\t\t],\n\t\t\trenames: {\n\t\t\t\t\"dist/jquery-ui.js\": \"jquery-ui.js\",\n\t\t\t\t\"dist/jquery-ui.min.js\": \"jquery-ui.min.js\",\n\t\t\t\t\"dist/i18n/jquery-ui-i18n.js\": \"i18n/jquery-ui-i18n.js\",\n\t\t\t\t\"dist/i18n/jquery-ui-i18n.min.js\": \"i18n/jquery-ui-i18n.min.js\",\n\t\t\t\t\"dist/jquery-ui.css\": \"themes/base/jquery-ui.css\",\n\t\t\t\t\"dist/jquery-ui.min.css\": \"themes/base/minified/jquery-ui.min.css\"\n\t\t\t},\n\t\t\tdest: \"dist/<%= files.cdn %>\"\n\t\t},\n\t\tcdn_i18n: {\n\t\t\tsrc: \"ui/i18n/jquery.ui.datepicker-*.js\",\n\t\t\tstrip: \"ui/\",\n\t\t\tdest: \"dist/<%= files.cdn %>\"\n\t\t},\n\t\tcdn_i18n_min: {\n\t\t\tsrc: \"dist/minified/i18n/jquery.ui.datepicker-*.js\",\n\t\t\tstrip: \"dist/minified\",\n\t\t\tdest: \"dist/<%= files.cdn %>\"\n\t\t},\n\t\tcdn_min: {\n\t\t\tsrc: \"dist/minified/*.js\",\n\t\t\tstrip: /^dist\\/minified/,\n\t\t\tdest: \"dist/<%= files.cdn %>/ui\"\n\t\t},\n\t\tcdn_min_images: {\n\t\t\tsrc: \"themes/base/images/*\",\n\t\t\tstrip: /^themes\\/base\\//,\n\t\t\tdest: \"dist/<%= files.cdn %>/themes/base/minified\"\n\t\t},\n\t\tcdn_themes: {\n\t\t\tsrc: \"dist/<%= files.themes %>/themes/**/*\",\n\t\t\tstrip: \"dist/<%= files.themes %>\",\n\t\t\tdest: \"dist/<%= files.cdn %>\"\n\t\t},\n\t\tthemes: {\n\t\t\tsrc: [\n\t\t\t\t\"AUTHORS.txt\",\n\t\t\t\t\"GPL-LICENSE.txt\",\n\t\t\t\t\"MIT-LICENSE.txt\",\n\t\t\t\t\"package.json\"\n\t\t\t],\n\t\t\tdest: \"dist/<%= files.themes %>\"\n\t\t}\n\t},\n\tzip: {\n\t\tdist: {\n\t\t\tsrc: \"<%= files.dist %>\",\n\t\t\tdest: \"<%= files.dist %>.zip\"\n\t\t},\n\t\tcdn: {\n\t\t\tsrc: \"<%= files.cdn %>\",\n\t\t\tdest: \"<%= files.cdn %>.zip\"\n\t\t},\n\t\tthemes: {\n\t\t\tsrc: \"<%= files.themes %>\",\n\t\t\tdest: \"<%= files.themes %>.zip\"\n\t\t}\n\t},\n\tmd5: {\n\t\tdist: {\n\t\t\tsrc: \"dist/<%= files.dist %>\",\n\t\t\tdest: \"dist/<%= files.dist %>/MANIFEST\"\n\t\t},\n\t\tcdn: {\n\t\t\tsrc: \"dist/<%= files.cdn %>\",\n\t\t\tdest: \"dist/<%= files.cdn %>/MANIFEST\"\n\t\t},\n\t\tthemes: {\n\t\t\tsrc: \"dist/<%= files.themes %>\",\n\t\t\tdest: \"dist/<%= files.themes %>/MANIFEST\"\n\t\t}\n\t},\n\tqunit: {\n\t\tfiles: grunt.file.expandFiles( \"tests/unit/**/*.html\" ).filter(function( file ) {\n\t\t\t// disabling everything that doesn't (quite) work with PhantomJS for now\n\t\t\t// TODO except for all|index|test, try to include more as we go\n\t\t\treturn !( /(all|all-active|index|test|draggable|droppable|selectable|resizable|sortable|dialog|slider|datepicker|tabs|tabs_deprecated)\\.html$/ ).test( file );\n\t\t})\n\t},\n\tlint: {\n\t\tui: grunt.file.expandFiles( \"ui/*.js\" ).filter(function( file ) {\n\t\t\t// TODO remove items from this list once rewritten\n\t\t\treturn !( /(mouse|datepicker|draggable|droppable|resizable|selectable|sortable)\\.js$/ ).test( file );\n\t\t}),\n\t\tgrunt: [ \"grunt.js\", \"build/tasks/*.js\" ],\n\t\ttests: \"tests/unit/**/*.js\"\n\t},\n\tcsslint: {\n\t\t// nothing: []\n\t\t// TODO figure out what to check for, then fix and enable\n\t\tbase_theme: {\n\t\t\tsrc: grunt.file.expandFiles( \"themes/base/*.css\" ).filter(function( file ) {\n\t\t\t\t// TODO remove items from this list once rewritten\n\t\t\t\treturn !( /(button|datepicker|core|dialog|theme)\\.css$/ ).test( file );\n\t\t\t}),\n\t\t\t// TODO consider reenabling some of these rules\n\t\t\trules: {\n\t\t\t\t\"import\": false,\n\t\t\t\t\"important\": false,\n\t\t\t\t\"outline-none\": false,\n\t\t\t\t// especially this one\n\t\t\t\t\"overqualified-elements\": false\n\t\t\t}\n\t\t}\n\t},\n\tjshint: (function() {\n\t\tfunction parserc( path ) {\n\t\t\tvar rc = grunt.file.readJSON( (path || \"\") + \".jshintrc\" ),\n\t\t\t\tsettings = {\n\t\t\t\t\toptions: rc,\n\t\t\t\t\tglobals: {}\n\t\t\t\t};\n\n\t\t\t(rc.predef || []).forEach(function( prop ) {\n\t\t\t\tsettings.globals[ prop ] = true;\n\t\t\t});\n\t\t\tdelete rc.predef;\n\n\t\t\treturn settings;\n\t\t}\n\n\t\treturn {\n\t\t\t// TODO: use \"faux strict mode\" https://github.com/jshint/jshint/issues/504\n\t\t\t// TODO: limit `smarttabs` to multi-line comments https://github.com/jshint/jshint/issues/503\n\t\t\toptions: parserc(),\n\t\t\tui: parserc( \"ui/\" ),\n\t\t\t// TODO: `evil: true` is only for document.write() https://github.com/jshint/jshint/issues/519\n\t\t\t// TODO: don't create so many globals in tests\n\t\t\ttests: parserc( \"tests/\" )\n\t\t};\n\t})()\n});\n\ngrunt.registerTask( \"default\", \"lint csslint htmllint qunit\" );\ngrunt.registerTask( \"sizer\", \"concat:ui min:dist/jquery-ui.min.js compare_size:all\" );\ngrunt.registerTask( \"sizer_all\", \"concat:ui min compare_size\" );\ngrunt.registerTask( \"build\", \"concat min cssmin copy:dist_units_images\" );\ngrunt.registerTask( \"release\", \"clean build copy:dist copy:dist_min copy:dist_min_images copy:dist_css_min md5:dist zip:dist\" );\ngrunt.registerTask( \"release_themes\", \"release download_themes copy_themes copy:themes md5:themes zip:themes\" );\ngrunt.registerTask( \"release_cdn\", \"release_themes copy:cdn copy:cdn_min copy:cdn_i18n copy:cdn_i18n_min copy:cdn_min_images copy:cdn_themes md5:cdn zip:cdn\" );\n\n};\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/jquery-1.7.2.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/package.json",
    "content": "{\n  \"name\": \"jquery-ui\",\n  \"title\": \"jQuery UI\",\n  \"description\": \"Abstractions for low-level interaction and animation, advanced effects and high-level, themeable widgets, built on top of the jQuery JavaScript Library, that you can use to build highly interactive web applications.\",\n  \"version\": \"1.9.0pre\",\n  \"homepage\": \"https://github.com/jquery/jquery-ui\",\n  \"author\": {\n    \"name\": \"AUTHORS.txt\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/jquery/jquery-ui.git\"\n  },\n  \"bugs\": {\n    \"url\": \"http://bugs.jqueryui.com/\"\n  },\n  \"licenses\": [\n    {\n      \"type\": \"MIT\",\n      \"url\": \"http://www.opensource.org/licenses/MIT\"\n    },\n    {\n      \"type\": \"GPL\",\n      \"url\": \"http://www.opensource.org/licenses/GPL-2.0\"\n    }\n  ],\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"grunt\": \"0.3.9\",\n    \"grunt-css\": \"0.2.0\",\n    \"grunt-compare-size\": \"0.1.4\",\n    \"grunt-html\": \"0.1.1\",\n    \"request\": \"2.9.153\",\n    \"rimraf\": \"2.0.1\",\n    \"testswarm\": \"0.2.2\"\n  },\n  \"keywords\": []\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/.jshintrc",
    "content": "{\n\t\"browser\": true,\n\t\"curly\": true,\n\t\"eqnull\": true,\n\t\"eqeqeq\": true,\n\t\"expr\": true,\n\t\"evil\": true,\n\t\"jquery\": true,\n\t\"latedef\": true,\n\t\"noarg\": true,\n\t\"onevar\": true,\n\t\"smarttabs\": true,\n\t\"trailing\": true,\n\t\"undef\": true,\n\t\"predef\": [\n\t\t\"addMonths\",\n\t\t\"asyncTest\",\n\t\t\"container\",\n\t\t\"deepEqual\",\n\t\t\"d1\",\n\t\t\"d2\",\n\t\t\"dlg\",\n\t\t\"domEqual\",\n\t\t\"drag\",\n\t\t\"dragged\",\n\t\t\"el\",\n\t\t\"equal\",\n\t\t\"equalsDate\",\n\t\t\"expect\",\n\t\t\"Globalize\",\n\t\t\"heightAfter\",\n\t\t\"init\",\n\t\t\"isNotOpen\",\n\t\t\"isOpen\",\n\t\t\"modal\",\n\t\t\"module\",\n\t\t\"moved\",\n\t\t\"notEqual\",\n\t\t\"offsetAfter\",\n\t\t\"offsetBefore\",\n\t\t\"ok\",\n\t\t\"PROP_NAME\",\n\t\t\"QUnit\",\n\t\t\"restoreScroll\",\n\t\t\"shouldBeDroppable\",\n\t\t\"shouldmove\",\n\t\t\"shouldNotBeDroppable\",\n\t\t\"shouldnotmove\",\n\t\t\"shouldnotresize\",\n\t\t\"shouldresize\",\n\t\t\"start\",\n\t\t\"strictEqual\",\n\t\t\"stop\",\n\t\t\"test\",\n\t\t\"TestHelpers\",\n\t\t\"widthAfter\",\n\t\t\"JSHINT\"\n\t]\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/index.css",
    "content": "body {\n\tfont-size: 62.5%;\n}\n.ui-widget-header {\n\tpadding: 0.2em 0.5em;\n\tmargin: 0;\n}\n.ui-widget-content {\n\tpadding: 1em;\n\tmargin-bottom: 1em;\n}\np {\n\tmargin: 0;\n}\nul {\n\tmargin: 0;\n\tlist-style: none;\n}\nli {\n\tline-height: 2em;\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tests</title>\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.core.css\">\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.theme.css\">\n\t<link rel=\"stylesheet\" href=\"index.css\">\n\t<script src=\"jquery-1.7.2.js\"></script>\n\t<script src=\"index.js\"></script>\n</head>\n<body>\n\n<div id=\"main\">\n\t<h1>jQuery UI Tests</h1>\n\t<div>\n\t\t<h2>Unit Tests</h2>\n\t\t<p><a href=\"unit/index.html\">Unit tests</a> exist for all functionality in jQuery UI.\n\t\tThe unit tests can be run locally (some tests require a web server with PHP)\n\t\tto ensure proper functionality before committing changes.\n\t\tThe unit tests are also run on <a href=\"http://swarm.jquery.com/user/jqueryui\">TestSwarm</a>\n\t\tfor every commit.</p>\n\n\t\t<h2>Visual Tests</h2>\n\t\t<p><a href=\"visual/index.html\">Visual tests</a> only exist in cases where we can't verify proper functionality\n\t\twith unit tests. These may be either purely visual or just hard to automate.\n\t\tMost visual tests will provide a description of what is happening on the page\n\t\tand what to look for.</p>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/index.js",
    "content": "$(function() {\n\n$( \"#main\" )\n\t.addClass( \"ui-widget\" )\n\t.find( \"h1, h2\" )\n\t\t.addClass( \"ui-widget-header ui-corner-top\" )\n\t\t.next()\n\t\t\t.addClass( \"ui-widget-content ui-corner-bottom\" );\n\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.6.1.js",
    "content": "/*!\n * jQuery JavaScript Library v1.6.1\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Thu May 12 15:04:36 2011 -0400\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// (both of which we optimize for)\n\tquickExpr = /^(?:[^<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Check for digits\n\trdigit = /\\d/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = (context ? context.ownerDocument || context : document);\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn (context || rootjQuery).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif (selector.selector !== undefined) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.6.1\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + (this.selector ? \" \" : \"\") + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, +i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).unbind( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery._Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNaN: function( obj ) {\n\t\treturn obj == null || !rdigit.test( obj ) || isNaN( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Not own constructor property must be Object\n\t\tif ( obj.constructor &&\n\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn (new Function( \"return \" + data ))();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\t// (xml & tmp used internally)\n\tparseXML: function( data , xml , tmp ) {\n\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\n\t\ttmp = xml.documentElement;\n\n\t\tif ( ! tmp || ! tmp.nodeName || tmp.nodeName === \"parsererror\" ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array ) {\n\n\t\tif ( indexOf ) {\n\t\t\treturn indexOf.call( array, elem );\n\t\t}\n\n\t\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\t\tif ( array[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can be optionally by executed if its a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn (new Date()).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\n// Expose jQuery to the global object\nreturn jQuery;\n\n})();\n\n\nvar // Promise methods\n\tpromiseMethods = \"done fail isResolved isRejected promise then always pipe\".split( \" \" ),\n\t// Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\t// Create a simple deferred (one callbacks list)\n\t_Deferred: function() {\n\t\tvar // callbacks list\n\t\t\tcallbacks = [],\n\t\t\t// stored [ context , args ]\n\t\t\tfired,\n\t\t\t// to avoid firing when already doing so\n\t\t\tfiring,\n\t\t\t// flag to know if the deferred has been cancelled\n\t\t\tcancelled,\n\t\t\t// the deferred itself\n\t\t\tdeferred  = {\n\n\t\t\t\t// done( f1, f2, ...)\n\t\t\t\tdone: function() {\n\t\t\t\t\tif ( !cancelled ) {\n\t\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t_fired;\n\t\t\t\t\t\tif ( fired ) {\n\t\t\t\t\t\t\t_fired = fired;\n\t\t\t\t\t\t\tfired = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\t\t\t\telem = args[ i ];\n\t\t\t\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t\t\t\tdeferred.done.apply( deferred, elem );\n\t\t\t\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tcallbacks.push( elem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( _fired ) {\n\t\t\t\t\t\t\tdeferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with given context and args\n\t\t\t\tresolveWith: function( context, args ) {\n\t\t\t\t\tif ( !cancelled && !fired && !firing ) {\n\t\t\t\t\t\t// make sure args are available (#8421)\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\tfiring = 1;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twhile( callbacks[ 0 ] ) {\n\t\t\t\t\t\t\t\tcallbacks.shift().apply( context, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally {\n\t\t\t\t\t\t\tfired = [ context, args ];\n\t\t\t\t\t\t\tfiring = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with this as context and given arguments\n\t\t\t\tresolve: function() {\n\t\t\t\t\tdeferred.resolveWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Has this deferred been resolved?\n\t\t\t\tisResolved: function() {\n\t\t\t\t\treturn !!( firing || fired );\n\t\t\t\t},\n\n\t\t\t\t// Cancel\n\t\t\t\tcancel: function() {\n\t\t\t\t\tcancelled = 1;\n\t\t\t\t\tcallbacks = [];\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn deferred;\n\t},\n\n\t// Full fledged deferred (two callbacks list)\n\tDeferred: function( func ) {\n\t\tvar deferred = jQuery._Deferred(),\n\t\t\tfailDeferred = jQuery._Deferred(),\n\t\t\tpromise;\n\t\t// Add errorDeferred methods, then and promise\n\t\tjQuery.extend( deferred, {\n\t\t\tthen: function( doneCallbacks, failCallbacks ) {\n\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\talways: function() {\n\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );\n\t\t\t},\n\t\t\tfail: failDeferred.done,\n\t\t\trejectWith: failDeferred.resolveWith,\n\t\t\treject: failDeferred.resolve,\n\t\t\tisRejected: failDeferred.isResolved,\n\t\t\tpipe: function( fnDone, fnFail ) {\n\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\tfail: [ fnFail, \"reject\" ]\n\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action ]( returned );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).promise();\n\t\t\t},\n\t\t\t// Get a promise for this deferred\n\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\tpromise: function( obj ) {\n\t\t\t\tif ( obj == null ) {\n\t\t\t\t\tif ( promise ) {\n\t\t\t\t\t\treturn promise;\n\t\t\t\t\t}\n\t\t\t\t\tpromise = obj = {};\n\t\t\t\t}\n\t\t\t\tvar i = promiseMethods.length;\n\t\t\t\twhile( i-- ) {\n\t\t\t\t\tobj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t});\n\t\t// Make sure only one callback list will be used\n\t\tdeferred.done( failDeferred.cancel ).fail( deferred.cancel );\n\t\t// Unexpose cancel\n\t\tdelete deferred.cancel;\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = arguments,\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tcount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t// Strange bug in FF4:\n\t\t\t\t\t// Values changed onto the arguments object sometimes end up as undefined values\n\t\t\t\t\t// outside the $.when method. Cloning the object into a fresh array solves the issue\n\t\t\t\t\tdeferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn deferred.promise();\n\t}\n});\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\tbodyStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName( \"tbody\" ).length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName( \"link\" ).length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute( \"href\" ) === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55$/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function click() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t\tdiv.detachEvent( \"onclick\", click );\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains it's value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\t// We use our own, invisible, body\n\tbody = document.createElement( \"body\" );\n\tbodyStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\t// Set background to avoid IE crashes when removing (#9028)\n\t\tbackground: \"none\"\n\t};\n\tfor ( i in bodyStyle ) {\n\t\tbody.style[ i ] = bodyStyle[ i ];\n\t}\n\tbody.appendChild( div );\n\tdocumentElement.insertBefore( body, documentElement.firstChild );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Remove the body element we added\n\tbody.innerHTML = \"\";\n\tdocumentElement.removeChild( body );\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t} ) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([a-z])([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar internalKey = jQuery.expando, getByName = typeof name === \"string\", thisCache,\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);\n\t\t\t} else {\n\t\t\t\tcache[ id ] = jQuery.extend(cache[ id ], name);\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Internal jQuery data is stored in a separate object inside the object's data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data\n\t\tif ( pvt ) {\n\t\t\tif ( !thisCache[ internalKey ] ) {\n\t\t\t\tthisCache[ internalKey ] = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache[ internalKey ];\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should\n\t\t// not attempt to inspect the internal events object using jQuery.data, as this\n\t\t// internal data object is undocumented and subject to change.\n\t\tif ( name === \"events\" && !thisCache[name] ) {\n\t\t\treturn thisCache[ internalKey ] && thisCache[ internalKey ].events;\n\t\t}\n\n\t\treturn getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar internalKey = jQuery.expando, isNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\t\t\tvar thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];\n\n\t\t\tif ( thisCache ) {\n\t\t\t\tdelete thisCache[ name ];\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !isEmptyDataObject(thisCache) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( pvt ) {\n\t\t\tdelete cache[ id ][ internalKey ];\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar internalCache = cache[ id ][ internalKey ];\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\tif ( jQuery.support.deleteExpando || cache != window ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the entire user cache at once because it's faster than\n\t\t// iterating through each key, but we need to continue to persist internal\n\t\t// data if it existed\n\t\tif ( internalCache ) {\n\t\t\tcache[ id ] = {};\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\n\t\t\tcache[ id ][ internalKey ] = internalCache;\n\n\t\t// Otherwise, we need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\t} else if ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar data = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 ) {\n\t\t\t    var attr = this[0].attributes, name;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tvar parts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"$1-$2\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t!jQuery.isNaN( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON\n// property to be considered empty objects; this property always exists in\n// order to make sure JSON.stringify does not expose internal metadata\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery.data( elem, deferDataKey, undefined, true );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&\n\t\t( src === \"mark\" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery.data( elem, queueDataKey, undefined, true ) &&\n\t\t\t\t!jQuery.data( elem, markDataKey, undefined, true ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.resolve();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"mark\";\n\t\t\tjQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery.data( elem, key, count, true );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"queue\";\n\t\t\tvar q = jQuery.data( elem, type, undefined, true );\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery.data( elem, type, jQuery.makeArray(data), true );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\tdefer;\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift(\"inprogress\");\n\t\t\t}\n\n\t\t\tfn.call(elem, function() {\n\t\t\t\tjQuery.dequeue(elem, type);\n\t\t\t});\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[time] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function() {\n\t\t\tvar elem = this;\n\t\t\tsetTimeout(function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, time );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.done( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\trinvalidChar = /\\:/,\n\tformHook, boolHook;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\t\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\t\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.addClass( value.call(this, i, self.attr(\"class\") || \"\") );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tvar classNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar elem = this[i];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar className = \" \" + elem.className + \" \",\n\t\t\t\t\t\t\tsetClass = elem.className;\n\n\t\t\t\t\t\tfor ( var c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( className.indexOf( \" \" + classNames[c] + \" \" ) < 0 ) {\n\t\t\t\t\t\t\t\tsetClass += \" \" + classNames[c];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.removeClass( value.call(this, i, self.attr(\"class\")) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tvar classNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar elem = this[i];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tvar className = (\" \" + elem.className + \" \").replace(rclass, \" \");\n\t\t\t\t\t\tfor ( var c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[c] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.toggleClass( value.call(this, i, self.attr(\"class\"), stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \";\n\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\tif ( (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret,\n\t\t\telem = this[0];\n\t\t\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\treturn (elem.value || \"\").replace(rreturn, \"\");\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar isFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\tvar option = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\t\n\tattrFix: {\n\t\t// Always normalize to ensure hook usage\n\t\ttabindex: \"tabIndex\"\n\t},\n\t\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = elem.nodeType;\n\t\t\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( !(\"getAttribute\" in elem) ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Normalize the name if needed\n\t\tname = notxml && jQuery.attrFix[ name ] || name;\n\n\t\thooks = jQuery.attrHooks[ name ];\n\n\t\tif ( !hooks ) {\n\t\t\t// Use boolHook for boolean attributes\n\t\t\tif ( rboolean.test( name ) &&\n\t\t\t\t(typeof value === \"boolean\" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) {\n\n\t\t\t\thooks = boolHook;\n\n\t\t\t// Use formHook for forms and if the name contains certain characters\n\t\t\t} else if ( formHook && (jQuery.nodeName( elem, \"form\" ) || rinvalidChar.test( name )) ) {\n\t\t\t\thooks = formHook;\n\t\t\t}\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn undefined;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml ) {\n\t\t\treturn hooks.get( elem, name );\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, name ) {\n\t\tvar propName;\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\t\t\n\t\t\tif ( jQuery.support.getSetAttribute ) {\n\t\t\t\t// Use removeAttribute in browsers that support it\n\t\t\t\telem.removeAttribute( name );\n\t\t\t} else {\n\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\telem.removeAttributeNode( elem.getAttributeNode( name ) );\n\t\t\t}\n\n\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\tif ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {\n\t\t\t\telem[ propName ] = false;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabIndex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\t\n\tprop: function( elem, name, value ) {\n\t\tvar nType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Try to normalize/fix the name\n\t\tname = notxml && jQuery.propFix[ name ] || name;\n\t\t\n\t\thooks = jQuery.propHooks[ name ];\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn (elem[ name ] = value);\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\t\n\tpropHooks: {}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\treturn elem[ jQuery.propFix[ name ] || name ] ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = value;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// Use the value property for back compat\n// Use the formHook for button elements in IE6/7 (#1954)\njQuery.attrHooks.value = {\n\tget: function( elem, name ) {\n\t\tif ( formHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\treturn formHook.get( elem, name );\n\t\t}\n\t\treturn elem.value;\n\t},\n\tset: function( elem, value, name ) {\n\t\tif ( formHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\treturn formHook.set( elem, value, name );\n\t\t}\n\t\t// Does not return so that setAttribute is also used\n\t\telem.value = value;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !jQuery.support.getSetAttribute ) {\n\n\t// propFix is more comprehensive and contains all fixes\n\tjQuery.attrFix = jQuery.propFix;\n\t\n\t// Use this for any attribute on a form in IE6/7\n\tformHook = jQuery.attrHooks.name = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\t// Return undefined if nodeValue is empty string\n\t\t\treturn ret && ret.nodeValue !== \"\" ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Check form objects in IE (multiple bugs related)\n\t\t\t// Only use nodeValue if the attribute node exists on the form\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret ) {\n\t\t\t\tret.nodeValue = value;\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn (elem.style.cssText = \"\" + value);\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar hasOwn = Object.prototype.hasOwnProperty,\n\trnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(rescape, \"\\\\$&\");\n\t};\n\n/*\n * A number of helper functions used for managing events.\n * Many of the ideas behind this code originated from\n * Dean Edwards' addEvent library.\n */\njQuery.event = {\n\n\t// Bind an event to an element\n\t// Original by Dean Edwards\n\tadd: function( elem, types, handler, data ) {\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t} else if ( !handler ) {\n\t\t\t// Fixes bug #7229. Fix recommended by jdalton\n\t\t\treturn;\n\t\t}\n\n\t\tvar handleObjIn, handleObj;\n\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the function being executed has a unique ID\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure\n\t\tvar elemData = jQuery._data( elem );\n\n\t\t// If no elemData is found then we must be trying to bind to one of the\n\t\t// banned noData elements\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar events = elemData.events,\n\t\t\teventHandle = elemData.handle;\n\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t}\n\n\t\t// Add elem as a property of the handle function\n\t\t// This is to prevent a memory leak with non-native events in IE.\n\t\teventHandle.elem = elem;\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\tvar type, i = 0, namespaces;\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\thandleObj = handleObjIn ?\n\t\t\t\tjQuery.extend({}, handleObjIn) :\n\t\t\t\t{ handler: handler, data: data };\n\n\t\t\t// Namespaced event handlers\n\t\t\tif ( type.indexOf(\".\") > -1 ) {\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\thandleObj.namespace = namespaces.slice(0).sort().join(\".\");\n\n\t\t\t} else {\n\t\t\t\tnamespaces = [];\n\t\t\t\thandleObj.namespace = \"\";\n\t\t\t}\n\n\t\t\thandleObj.type = type;\n\t\t\tif ( !handleObj.guid ) {\n\t\t\t\thandleObj.guid = handler.guid;\n\t\t\t}\n\n\t\t\t// Get the current list of functions bound to this event\n\t\t\tvar handlers = events[ type ],\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// Init the event handler queue\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\n\t\t\t\t// Check for a special event handler\n\t\t\t\t// Only use addEventListener/attachEvent if the special\n\t\t\t\t// events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the function to the element's handler list\n\t\t\thandlers.push( handleObj );\n\n\t\t\t// Keep track of which events have been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, pos ) {\n\t\t// don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t}\n\n\t\tvar ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tevents = elemData && elemData.events;\n\n\t\tif ( !elemData || !events ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// types is actually an event object here\n\t\tif ( types && types.type ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t}\n\n\t\t// Unbind all events for the element\n\t\tif ( !types || typeof types === \"string\" && types.charAt(0) === \".\" ) {\n\t\t\ttypes = types || \"\";\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tjQuery.event.remove( elem, type + types );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).unbind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\torigType = type;\n\t\t\thandleObj = null;\n\t\t\tall = type.indexOf(\".\") < 0;\n\t\t\tnamespaces = [];\n\n\t\t\tif ( !all ) {\n\t\t\t\t// Namespaced event handlers\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\n\t\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" +\n\t\t\t\t\tjQuery.map( namespaces.slice(0).sort(), fcleanup ).join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\t}\n\n\t\t\teventType = events[ type ];\n\n\t\t\tif ( !eventType ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( !handler ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, origType, handleObj.handler, j );\n\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tfor ( j = pos || 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( handler.guid === handleObj.guid ) {\n\t\t\t\t\t// remove the given handler for the given type\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tif ( pos == null ) {\n\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( pos != null ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove generic event handler if no more handlers exist\n\t\t\tif ( eventType.length === 0 || pos != null && eventType.length === 1 ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tret = null;\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tvar handle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\tdelete elemData.events;\n\t\t\tdelete elemData.handle;\n\n\t\t\tif ( jQuery.isEmptyObject( elemData ) ) {\n\t\t\t\tjQuery.removeData( elem, undefined, true );\n\t\t\t}\n\t\t}\n\t},\n\t\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\texclusive;\n\n\t\tif ( type.indexOf(\"!\") >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t// internalKey variable is just used to make it easier to find\n\t\t\t\t// and potentially change this stuff later; currently it just\n\t\t\t\t// points to jQuery.expando\n\t\t\t\tvar internalKey = jQuery.expando,\n\t\t\t\t\tinternalCache = this[ internalKey ];\n\t\t\t\tif ( internalCache && internalCache.events && internalCache.events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, internalCache.handle.elem );\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tevent.target = elem;\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\tvar cur = elem,\n\t\t\t// IE doesn't like method names with a colon (#3533, #8272)\n\t\t\tontype = type.indexOf(\":\") < 0 ? \"on\" + type : \"\";\n\n\t\t// Fire event on the current element, then bubble up the DOM tree\n\t\tdo {\n\t\t\tvar handle = jQuery._data( cur, \"handle\" );\n\n\t\t\tevent.currentTarget = cur;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Trigger an inline bound script\n\t\t\tif ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {\n\t\t\t\tevent.result = false;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\t// Bubble up to document, then to window\n\t\t\tcur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;\n\t\t} while ( cur && !event.isPropagationStopped() );\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tvar old,\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction)() check here because IE6/7 fails that test.\n\t\t\t\t// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.\n\t\t\t\ttry {\n\t\t\t\t\tif ( ontype && elem[ type ] ) {\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t}\n\t\t\t\t} catch ( ieError ) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = undefined;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn event.result;\n\t},\n\n\thandle: function( event ) {\n\t\tevent = jQuery.event.fix( event || window.event );\n\t\t// Snapshot the handlers list since a called handler may add/remove events.\n\t\tvar handlers = ((jQuery._data( this, \"events\" ) || {})[ event.type ] || []).slice(0),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\targs = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// Use the fix-ed Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.currentTarget = this;\n\n\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t// Triggered event must 1) be non-exclusive and have no namespace, or\n\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event.\n\t\t\tif ( run_all || event.namespace_re.test( handleObj.namespace ) ) {\n\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t// So that we can later remove it\n\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\tevent.data = handleObj.data;\n\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\tvar ret = handleObj.handler.apply( this, args );\n\n\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\tevent.result = ret;\n\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn event.result;\n\t},\n\n\tprops: \"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// store a copy of the original event object\n\t\t// and \"clone\" to set read-only properties\n\t\tvar originalEvent = event;\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( var i = this.props.length, prop; i; ) {\n\t\t\tprop = this.props[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary\n\t\tif ( !event.target ) {\n\t\t\t// Fixes #1925 where srcElement might not be defined either\n\t\t\tevent.target = event.srcElement || document;\n\t\t}\n\n\t\t// check if target is a textnode (safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Add relatedTarget, if necessary\n\t\tif ( !event.relatedTarget && event.fromElement ) {\n\t\t\tevent.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n\t\t}\n\n\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\tif ( event.pageX == null && event.clientX != null ) {\n\t\t\tvar eventDocument = event.target.ownerDocument || document,\n\t\t\t\tdoc = eventDocument.documentElement,\n\t\t\t\tbody = eventDocument.body;\n\n\t\t\tevent.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n\t\t\tevent.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && (event.charCode != null || event.keyCode != null) ) {\n\t\t\tevent.which = event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)\n\t\tif ( !event.metaKey && event.ctrlKey ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t// Note: button is not normalized, so don't use it\n\t\tif ( !event.which && event.button !== undefined ) {\n\t\t\tevent.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// Deprecated, use jQuery.guid instead\n\tguid: 1E8,\n\n\t// Deprecated, use jQuery.proxy instead\n\tproxy: jQuery.proxy,\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady,\n\t\t\tteardown: jQuery.noop\n\t\t},\n\n\t\tlive: {\n\t\t\tadd: function( handleObj ) {\n\t\t\t\tjQuery.event.add( this,\n\t\t\t\t\tliveConvert( handleObj.origType, handleObj.selector ),\n\t\t\t\t\tjQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );\n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tjQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !this.preventDefault ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// timeStamp is buggy for some events on Firefox(#3843)\n\t// So we won't rely on the native value\n\tthis.timeStamp = jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Checks if an event happened on an element within another element\n// Used in jQuery.event.special.mouseenter and mouseleave handlers\nvar withinElement = function( event ) {\n\t// Check if mouse(over|out) are still within the same parent element\n\tvar parent = event.relatedTarget;\n\n\t// set the correct event type\n\tevent.type = event.data;\n\n\t// Firefox sometimes assigns relatedTarget a XUL element\n\t// which we cannot access the parentNode property of\n\ttry {\n\n\t\t// Chrome does something similar, the parentNode property\n\t\t// can be accessed but is null.\n\t\tif ( parent && parent !== document && !parent.parentNode ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Traverse up the tree\n\t\twhile ( parent && parent !== this ) {\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\tif ( parent !== this ) {\n\t\t\t// handle event if we actually just moused on to a non sub-element\n\t\t\tjQuery.event.handle.apply( this, arguments );\n\t\t}\n\n\t// assuming we've left the element since we most likely mousedover a xul element\n\t} catch(e) { }\n},\n\n// In case of event delegation, we only need to rename the event.type,\n// liveHandler will take care of the rest.\ndelegate = function( event ) {\n\tevent.type = event.data;\n\tjQuery.event.handle.apply( this, arguments );\n};\n\n// Create mouseenter and mouseleave events\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tsetup: function( data ) {\n\t\t\tjQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );\n\t\t},\n\t\tteardown: function( data ) {\n\t\t\tjQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );\n\t\t}\n\t};\n});\n\n// submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( !jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"text\" || type === \"password\") && jQuery( elem ).closest(\"form\").length && e.keyCode === 13 ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialSubmit\" );\n\t\t}\n\t};\n\n}\n\n// change delegation, happens here so we have bind.\nif ( !jQuery.support.changeBubbles ) {\n\n\tvar changeFilters,\n\n\tgetVal = function( elem ) {\n\t\tvar type = elem.type, val = elem.value;\n\n\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\tval = elem.checked;\n\n\t\t} else if ( type === \"select-multiple\" ) {\n\t\t\tval = elem.selectedIndex > -1 ?\n\t\t\t\tjQuery.map( elem.options, function( elem ) {\n\t\t\t\t\treturn elem.selected;\n\t\t\t\t}).join(\"-\") :\n\t\t\t\t\"\";\n\n\t\t} else if ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\tval = elem.selectedIndex;\n\t\t}\n\n\t\treturn val;\n\t},\n\n\ttestChange = function testChange( e ) {\n\t\tvar elem = e.target, data, val;\n\n\t\tif ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdata = jQuery._data( elem, \"_change_data\" );\n\t\tval = getVal(elem);\n\n\t\t// the current data will be also retrieved by beforeactivate\n\t\tif ( e.type !== \"focusout\" || elem.type !== \"radio\" ) {\n\t\t\tjQuery._data( elem, \"_change_data\", val );\n\t\t}\n\n\t\tif ( data === undefined || val === data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data != null || val ) {\n\t\t\te.type = \"change\";\n\t\t\te.liveFired = undefined;\n\t\t\tjQuery.event.trigger( e, arguments[1], elem );\n\t\t}\n\t};\n\n\tjQuery.event.special.change = {\n\t\tfilters: {\n\t\t\tfocusout: testChange,\n\n\t\t\tbeforedeactivate: testChange,\n\n\t\t\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Change has to be called before submit\n\t\t\t// Keydown will be called before keypress, which is used in submit-event delegation\n\t\t\tkeydown: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( (e.keyCode === 13 && !jQuery.nodeName( elem, \"textarea\" ) ) ||\n\t\t\t\t\t(e.keyCode === 32 && (type === \"checkbox\" || type === \"radio\")) ||\n\t\t\t\t\ttype === \"select-multiple\" ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Beforeactivate happens also before the previous element is blurred\n\t\t\t// with this event you can't trigger a change event, but you can store\n\t\t\t// information\n\t\t\tbeforeactivate: function( e ) {\n\t\t\t\tvar elem = e.target;\n\t\t\t\tjQuery._data( elem, \"_change_data\", getVal(elem) );\n\t\t\t}\n\t\t},\n\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( this.type === \"file\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( var type in changeFilters ) {\n\t\t\t\tjQuery.event.add( this, type + \".specialChange\", changeFilters[type] );\n\t\t\t}\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialChange\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n\n\t// Handle when the input is .focus()'d\n\tchangeFilters.focus = changeFilters.beforeactivate;\n}\n\nfunction trigger( type, elem, args ) {\n\t// Piggyback on a donor event to simulate a different one.\n\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t// simulated event prevents default then we do the same on the donor.\n\t// Don't pass args or remember liveFired; they apply to the donor event.\n\tvar event = jQuery.extend( {}, args[ 0 ] );\n\tevent.type = type;\n\tevent.originalEvent = {};\n\tevent.liveFired = undefined;\n\tjQuery.event.handle.call( elem, event );\n\tif ( event.isDefaultPrevented() ) {\n\t\targs[ 0 ].preventDefault();\n\t}\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0;\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfunction handler( donor ) {\n\t\t\t// Donor event is always a native one; fix it and switch its type.\n\t\t\t// Let focusin/out handler cancel the donor focus/blur event.\n\t\t\tvar e = jQuery.event.fix( donor );\n\t\t\te.type = fix;\n\t\t\te.originalEvent = {};\n\t\t\tjQuery.event.trigger( e, null, e.target );\n\t\t\tif ( e.isDefaultPrevented() ) {\n\t\t\t\tdonor.preventDefault();\n\t\t\t}\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\n\t\tvar handler;\n\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis[ name ](key, data, type[key], fn);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( arguments.length === 2 || data === false ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tif ( name === \"one\" ) {\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t\thandler.guid = fn.guid || jQuery.guid++;\n\t\t} else {\n\t\t\thandler = fn;\n\t\t}\n\n\t\tif ( type === \"unload\" && name !== \"one\" ) {\n\t\t\tthis.one( type, data, fn );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( this[i], type, handler, data );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\njQuery.fn.extend({\n\tunbind: function( type, fn ) {\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" && !type.preventDefault ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis.unbind(key, type[key]);\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.remove( this[i], type, fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\treturn this.unbind( \"live\" );\n\n\t\t} else {\n\t\t\treturn this.die( types, null, fn, selector );\n\t\t}\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery.data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery.data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\nvar liveMap = {\n\tfocus: \"focusin\",\n\tblur: \"focusout\",\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n};\n\njQuery.each([\"live\", \"die\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {\n\t\tvar type, i = 0, match, namespaces, preType,\n\t\t\tselector = origSelector || this.selector,\n\t\t\tcontext = origSelector ? this : jQuery( this.context );\n\n\t\tif ( typeof types === \"object\" && !types.preventDefault ) {\n\t\t\tfor ( var key in types ) {\n\t\t\t\tcontext[ name ]( key, data, types[key], selector );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( name === \"die\" && !types &&\n\t\t\t\t\torigSelector && origSelector.charAt(0) === \".\" ) {\n\n\t\t\tcontext.unbind( origSelector );\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data === false || jQuery.isFunction( data ) ) {\n\t\t\tfn = data || returnFalse;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\ttypes = (types || \"\").split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) != null ) {\n\t\t\tmatch = rnamespaces.exec( type );\n\t\t\tnamespaces = \"\";\n\n\t\t\tif ( match )  {\n\t\t\t\tnamespaces = match[0];\n\t\t\t\ttype = type.replace( rnamespaces, \"\" );\n\t\t\t}\n\n\t\t\tif ( type === \"hover\" ) {\n\t\t\t\ttypes.push( \"mouseenter\" + namespaces, \"mouseleave\" + namespaces );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpreType = type;\n\n\t\t\tif ( liveMap[ type ] ) {\n\t\t\t\ttypes.push( liveMap[ type ] + namespaces );\n\t\t\t\ttype = type + namespaces;\n\n\t\t\t} else {\n\t\t\t\ttype = (liveMap[ type ] || type) + namespaces;\n\t\t\t}\n\n\t\t\tif ( name === \"live\" ) {\n\t\t\t\t// bind live handler\n\t\t\t\tfor ( var j = 0, l = context.length; j < l; j++ ) {\n\t\t\t\t\tjQuery.event.add( context[j], \"live.\" + liveConvert( type, selector ),\n\t\t\t\t\t\t{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// unbind live handler\n\t\t\t\tcontext.unbind( \"live.\" + liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\nfunction liveHandler( event ) {\n\tvar stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,\n\t\telems = [],\n\t\tselectors = [],\n\t\tevents = jQuery._data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)\n\tif ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === \"click\" ) {\n\t\treturn;\n\t}\n\n\tif ( event.namespace ) {\n\t\tnamespace = new RegExp(\"(^|\\\\.)\" + event.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t}\n\n\tevent.liveFired = this;\n\n\tvar live = events.live.slice(0);\n\n\tfor ( j = 0; j < live.length; j++ ) {\n\t\thandleObj = live[j];\n\n\t\tif ( handleObj.origType.replace( rnamespaces, \"\" ) === event.type ) {\n\t\t\tselectors.push( handleObj.selector );\n\n\t\t} else {\n\t\t\tlive.splice( j--, 1 );\n\t\t}\n\t}\n\n\tmatch = jQuery( event.target ).closest( selectors, event.currentTarget );\n\n\tfor ( i = 0, l = match.length; i < l; i++ ) {\n\t\tclose = match[i];\n\n\t\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {\n\t\t\t\telem = close.elem;\n\t\t\t\trelated = null;\n\n\t\t\t\t// Those two events require additional checking\n\t\t\t\tif ( handleObj.preType === \"mouseenter\" || handleObj.preType === \"mouseleave\" ) {\n\t\t\t\t\tevent.type = handleObj.preType;\n\t\t\t\t\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\n\n\t\t\t\t\t// Make sure not to accidentally match a child element with the same selector\n\t\t\t\t\tif ( related && jQuery.contains( elem, related ) ) {\n\t\t\t\t\t\trelated = elem;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !related || related !== elem ) {\n\t\t\t\t\telems.push({ elem: elem, handleObj: handleObj, level: close.level });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( i = 0, l = elems.length; i < l; i++ ) {\n\t\tmatch = elems[i];\n\n\t\tif ( maxLevel && match.level > maxLevel ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tret = match.handleObj.origHandler.apply( match.elem, arguments );\n\n\t\tif ( ret === false || event.isPropagationStopped() ) {\n\t\t\tmaxLevel = match.level;\n\n\t\t\tif ( ret === false ) {\n\t\t\t\tstop = false;\n\t\t\t}\n\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(rperiod, \"`\").replace(rspaces, \"&\");\n}\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.bind( name, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( var i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tvar pass = not ^ !!found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar type = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tvar first = match[2],\n\t\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent.sizcache = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar diff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Expr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Utility function for retreiving the text value of an array of DOM nodes\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( typeof selector === \"string\" ?\n\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar match, selector,\n\t\t\t\tmatches = {},\n\t\t\t\tlevel = 1;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( i = 0, l = selectors.length; i < l; i++ ) {\n\t\t\t\t\tselector = selectors[i];\n\n\t\t\t\t\tif ( !matches[ selector ] ) {\n\t\t\t\t\t\tmatches[ selector ] = POS.test( selector ) ?\n\t\t\t\t\t\t\tjQuery( selector, context || this.context ) :\n\t\t\t\t\t\t\tselector;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\t\tfor ( selector in matches ) {\n\t\t\t\t\t\tmatch = matches[ selector ];\n\n\t\t\t\t\t\tif ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {\n\t\t\t\t\t\t\tret.push({ selector: selector, elem: cur, level: level });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tlevel++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\t\tif ( !elem || typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0],\n\t\t\t\t// If it receives a string, the selector is used\n\t\t\t\t// If it receives nothing, the siblings are used\n\t\t\t\telem ? jQuery( elem ) : this.parent().children() );\n\t\t}\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until ),\n\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, args.join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn (elem === qualifier) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn (jQuery.inArray( elem, qualifier ) >= 0) === keep;\n\t});\n}\n\n\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery(arguments[0]);\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery(arguments[0]).toArray() );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnocache.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || (l > 1 && i < lastIndex) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar internalKey = jQuery.expando,\n\t\toldData = jQuery.data( src ),\n\t\tcurData = jQuery.data( dest, oldData );\n\n\t// Switch to use the internal data object, if it exists, for the next\n\t// stage of data copying\n\tif ( (oldData = oldData[ internalKey ]) ) {\n\t\tvar events = oldData.events;\n\t\t\t\tcurData = curData[ internalKey ] = jQuery.extend({}, oldData);\n\n\t\tif ( events ) {\n\t\t\tdelete curData.handle;\n\t\t\tcurData.events = {};\n\n\t\t\tfor ( var type in events ) {\n\t\t\t\tfor ( var i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults,\n\t\tdoc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\tif ( args.length === 1 && typeof args[0] === \"string\" && args[0].length < 512 && doc === document &&\n\t\targs[0].charAt(0) === \"<\" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ args[0] ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = (i > 0 ? this.clone(true) : this).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( \"getElementsByTagName\" in elem ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( \"querySelectorAll\" in elem ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\tfixDefaultChecked( elem );\n\t} else if ( elem.getElementsByTagName ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName\n\t\t\t// instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = (rtagName.exec( elem ) || [\"\", \"\"])[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ] && cache[ id ][ internalKey ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\trdashAlpha = /-([a-z])/ig,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^[+\\-]=/,\n\trrelNumFilter = /[^+\\-\\.\\de]+/g,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle,\n\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"zIndex\": true,\n\t\t\"fontWeight\": true,\n\t\t\"opacity\": true,\n\t\t\"zoom\": true,\n\t\t\"lineHeight\": true,\n\t\t\"widows\": true,\n\t\t\"orphans\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( type === \"number\" && isNaN( value ) || value == null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && rrelNum.test( value ) ) {\n\t\t\t\tvalue = +value.replace( rrelNumFilter, \"\" ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t},\n\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rdashAlpha, fcamelCase );\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\tval = getWH( elem, name, extra );\n\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif ( val <= 0 ) {\n\t\t\t\t\tval = curCSS( elem, name, name );\n\n\t\t\t\t\tif ( val === \"0px\" && currentStyle ) {\n\t\t\t\t\t\tval = currentStyle( elem, name, name );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( val != null ) {\n\t\t\t\t\t\t// Should return \"auto\" instead of 0, use 0 for\n\t\t\t\t\t\t// temporary backwards-compat\n\t\t\t\t\t\treturn val === \"\" || val === \"auto\" ? \"0px\" : val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( val < 0 || val == null ) {\n\t\t\t\t\tval = elem.style[ name ];\n\n\t\t\t\t\t// Should return \"auto\" instead of 0, use 0 for\n\t\t\t\t\t// temporary backwards-compat\n\t\t\t\t\treturn val === \"\" || val === \"auto\" ? \"0px\" : val;\n\t\t\t\t}\n\n\t\t\t\treturn typeof val === \"string\" ? val : val + \"px\";\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat(value);\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle;\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// Set the alpha filter to set the opacity\n\t\t\tvar opacity = jQuery.isNaN( value ) ?\n\t\t\t\t\"\" :\n\t\t\t\t\"alpha(opacity=\" + value * 100 + \")\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( !(defaultView = elem.ownerDocument.defaultView) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : (ret || 0);\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\tvar which = name === \"width\" ? cssWidth : cssHeight,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight;\n\n\tif ( extra === \"border\" ) {\n\t\treturn val;\n\t}\n\n\tjQuery.each( which, function() {\n\t\tif ( !extra ) {\n\t\t\tval -= parseFloat(jQuery.css( elem, \"padding\" + this )) || 0;\n\t\t}\n\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += parseFloat(jQuery.css( elem, \"margin\" + this )) || 0;\n\n\t\t} else {\n\t\t\tval -= parseFloat(jQuery.css( elem, \"border\" + this + \"Width\" )) || 0;\n\t\t}\n\t});\n\n\treturn val;\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts;\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor(; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor(; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function ( target, settings ) {\n\t\tif ( !settings ) {\n\t\t\t// Only one parameter, we extend ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.extend( true, jQuery.ajaxSettings, settings );\n\t\t} else {\n\t\t\t// target was provided, we extend into it\n\t\t\tjQuery.extend( true, target, jQuery.ajaxSettings, settings );\n\t\t}\n\t\t// Flatten fields we don't want deep extended\n\t\tfor( var field in { context: 1, url: 1 } ) {\n\t\t\tif ( field in settings ) {\n\t\t\t\ttarget[ field ] = settings[ field ];\n\t\t\t} else if( field in jQuery.ajaxSettings ) {\n\t\t\t\ttarget[ field ] = jQuery.ajaxSettings[ field ];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": \"*/*\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery._Deferred(),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, statusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = statusText;\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.done;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", */*; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( status < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.error( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor( key in s.converters ) {\n\t\t\t\tif( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow,\n\trequestAnimationFrame = window.webkitRequestAnimationFrame ||\n\t    window.mozRequestAnimationFrame ||\n\t    window.oRequestAnimationFrame;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css( elem, \"display\" ) === \"none\" ) {\n\t\t\t\t\t\tjQuery._data(elem, \"olddisplay\", defaultDisplay(elem.nodeName));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data(elem, \"olddisplay\") || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tvar display = jQuery.css( this[i], \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( this[i], \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( this[i], \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed(speed, easing, callback);\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p,\n\t\t\t\tdisplay, e,\n\t\t\t\tparts, start, end, unit;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height\n\t\t\t\t\t// animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = defaultDisplay( this.nodeName );\n\n\t\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\t\tif ( display === \"inline\" ) {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline\";\n\t\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test(val) ) {\n\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]();\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ((end || 1) / e.cur()) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t});\n\t},\n\n\tstop: function( clearQueue, gotoEnd ) {\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar timers = jQuery.timers,\n\t\t\t\ti = timers.length;\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( timers[i].elem === this ) {\n\t\t\t\t\tif (gotoEnd) {\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[i](true);\n\t\t\t\t\t}\n\n\t\t\t\t\ttimers.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// start the next in the queue if the last step wasn't forced\n\t\tif ( !gotoEnd ) {\n\t\t\tthis.dequeue();\n\t\t}\n\n\t\treturn this;\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\", 1),\n\tslideUp: genFx(\"hide\", 1),\n\tslideToggle: genFx(\"toggle\", 1),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend({}, speed) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction(easing) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery.dequeue( this );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx,\n\t\t\traf;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step(gotoEnd);\n\t\t}\n\n\t\tt.elem = this.elem;\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\t// Use requestAnimationFrame instead of setInterval if available\n\t\t\tif ( requestAnimationFrame ) {\n\t\t\t\ttimerId = 1;\n\t\t\t\traf = function() {\n\t\t\t\t\t// When timerId gets set to null at any point, this stops\n\t\t\t\t\tif ( timerId ) {\n\t\t\t\t\t\trequestAnimationFrame( raf );\n\t\t\t\t\t\tfx.tick();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trequestAnimationFrame( raf );\n\t\t\t} else {\n\t\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any\n\t\t// flash of content\n\t\tthis.custom(this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur());\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom(this.cur(), 0);\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar t = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options,\n\t\t\ti, n;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( i in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[i] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function (index, value) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[index];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery(elem).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( var p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[p] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\toptions.complete.call( elem );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ((this.end - this.start) * this.pos);\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tfor ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {\n\t\t\tif ( !timers[i]() ) {\n\t\t\t\ttimers.splice(i--, 1);\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = (fx.prop === \"width\" || fx.prop === \"height\" ? Math.max(0, fx.now) : fx.now) + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( \"body\" ),\n\t\t\tdisplay = elem.css( \"display\" );\n\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tdocument.body.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake html\n\t\t\t// document to it, Webkit & Firefox won't allow reusing the iframe document\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( \"<!doctype><html><body></body></html>\" );\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\tdocument.body.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tjQuery.offset.initialize();\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\tinitialize: function() {\n\t\tvar body = document.body, container = document.createElement(\"div\"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, \"marginTop\") ) || 0,\n\t\t\thtml = \"<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>\";\n\n\t\tjQuery.extend( container.style, { position: \"absolute\", top: 0, left: 0, margin: 0, border: 0, width: \"1px\", height: \"1px\", visibility: \"hidden\" } );\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\tinnerDiv = container.firstChild;\n\t\tcheckDiv = innerDiv.firstChild;\n\t\ttd = innerDiv.nextSibling.firstChild.firstChild;\n\n\t\tthis.doesNotAddBorder = (checkDiv.offsetTop !== 5);\n\t\tthis.doesAddBorderForTableAndCells = (td.offsetTop === 5);\n\n\t\tcheckDiv.style.position = \"fixed\";\n\t\tcheckDiv.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\tthis.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);\n\t\tcheckDiv.style.position = checkDiv.style.top = \"\";\n\n\t\tinnerDiv.style.overflow = \"hidden\";\n\t\tinnerDiv.style.position = \"relative\";\n\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = (position === \"absolute\" || position === \"fixed\") && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif (options.top != null) {\n\t\t\tprops.top = (options.top - curOffset.top) + curTop;\n\t\t}\n\t\tif (options.left != null) {\n\t\t\tprops.left = (options.left - curOffset.left) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[\"inner\" + name] = function() {\n\t\treturn this[0] ?\n\t\t\tparseFloat( jQuery.css( this[0], type, \"padding\" ) ) :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[\"outer\" + name] = function( margin ) {\n\t\treturn this[0] ?\n\t\t\tparseFloat( jQuery.css( this[0], type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ];\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\telem.document.body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNaN( ret ) ? orig : ret;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.6.2.js",
    "content": "/*!\n * jQuery JavaScript Library v1.6.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Thu Jun 30 14:16:56 2011 -0400\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// (both of which we optimize for)\n\tquickExpr = /^(?:[^<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Check for digits\n\trdigit = /\\d/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z])/ig,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = (context ? context.ownerDocument || context : document);\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn (context || rootjQuery).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif (selector.selector !== undefined) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.6.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + (this.selector ? \" \" : \"\") + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, +i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).unbind( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery._Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNaN: function( obj ) {\n\t\treturn obj == null || !rdigit.test( obj ) || isNaN( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Not own constructor property must be Object\n\t\tif ( obj.constructor &&\n\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn (new Function( \"return \" + data ))();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\t// (xml & tmp used internally)\n\tparseXML: function( data , xml , tmp ) {\n\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\n\t\ttmp = xml.documentElement;\n\n\t\tif ( ! tmp || ! tmp.nodeName || tmp.nodeName === \"parsererror\" ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Converts a dashed string to camelCased string;\n\t// Used by both the css and data modules\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array ) {\n\n\t\tif ( indexOf ) {\n\t\t\treturn indexOf.call( array, elem );\n\t\t}\n\n\t\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\t\tif ( array[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn (new Date()).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\nvar // Promise methods\n\tpromiseMethods = \"done fail isResolved isRejected promise then always pipe\".split( \" \" ),\n\t// Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\t// Create a simple deferred (one callbacks list)\n\t_Deferred: function() {\n\t\tvar // callbacks list\n\t\t\tcallbacks = [],\n\t\t\t// stored [ context , args ]\n\t\t\tfired,\n\t\t\t// to avoid firing when already doing so\n\t\t\tfiring,\n\t\t\t// flag to know if the deferred has been cancelled\n\t\t\tcancelled,\n\t\t\t// the deferred itself\n\t\t\tdeferred  = {\n\n\t\t\t\t// done( f1, f2, ...)\n\t\t\t\tdone: function() {\n\t\t\t\t\tif ( !cancelled ) {\n\t\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t_fired;\n\t\t\t\t\t\tif ( fired ) {\n\t\t\t\t\t\t\t_fired = fired;\n\t\t\t\t\t\t\tfired = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\t\t\t\telem = args[ i ];\n\t\t\t\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t\t\t\tdeferred.done.apply( deferred, elem );\n\t\t\t\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tcallbacks.push( elem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( _fired ) {\n\t\t\t\t\t\t\tdeferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with given context and args\n\t\t\t\tresolveWith: function( context, args ) {\n\t\t\t\t\tif ( !cancelled && !fired && !firing ) {\n\t\t\t\t\t\t// make sure args are available (#8421)\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\tfiring = 1;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twhile( callbacks[ 0 ] ) {\n\t\t\t\t\t\t\t\tcallbacks.shift().apply( context, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally {\n\t\t\t\t\t\t\tfired = [ context, args ];\n\t\t\t\t\t\t\tfiring = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with this as context and given arguments\n\t\t\t\tresolve: function() {\n\t\t\t\t\tdeferred.resolveWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Has this deferred been resolved?\n\t\t\t\tisResolved: function() {\n\t\t\t\t\treturn !!( firing || fired );\n\t\t\t\t},\n\n\t\t\t\t// Cancel\n\t\t\t\tcancel: function() {\n\t\t\t\t\tcancelled = 1;\n\t\t\t\t\tcallbacks = [];\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn deferred;\n\t},\n\n\t// Full fledged deferred (two callbacks list)\n\tDeferred: function( func ) {\n\t\tvar deferred = jQuery._Deferred(),\n\t\t\tfailDeferred = jQuery._Deferred(),\n\t\t\tpromise;\n\t\t// Add errorDeferred methods, then and promise\n\t\tjQuery.extend( deferred, {\n\t\t\tthen: function( doneCallbacks, failCallbacks ) {\n\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\talways: function() {\n\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );\n\t\t\t},\n\t\t\tfail: failDeferred.done,\n\t\t\trejectWith: failDeferred.resolveWith,\n\t\t\treject: failDeferred.resolve,\n\t\t\tisRejected: failDeferred.isResolved,\n\t\t\tpipe: function( fnDone, fnFail ) {\n\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\tfail: [ fnFail, \"reject\" ]\n\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action ]( returned );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).promise();\n\t\t\t},\n\t\t\t// Get a promise for this deferred\n\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\tpromise: function( obj ) {\n\t\t\t\tif ( obj == null ) {\n\t\t\t\t\tif ( promise ) {\n\t\t\t\t\t\treturn promise;\n\t\t\t\t\t}\n\t\t\t\t\tpromise = obj = {};\n\t\t\t\t}\n\t\t\t\tvar i = promiseMethods.length;\n\t\t\t\twhile( i-- ) {\n\t\t\t\t\tobj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t});\n\t\t// Make sure only one callback list will be used\n\t\tdeferred.done( failDeferred.cancel ).fail( deferred.cancel );\n\t\t// Unexpose cancel\n\t\tdelete deferred.cancel;\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = arguments,\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tcount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t// Strange bug in FF4:\n\t\t\t\t\t// Values changed onto the arguments object sometimes end up as undefined values\n\t\t\t\t\t// outside the $.when method. Cloning the object into a fresh array solves the issue\n\t\t\t\t\tdeferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn deferred.promise();\n\t}\n});\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\ttestElementParent,\n\t\ttestElement,\n\t\ttestElementStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName( \"tbody\" ).length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName( \"link\" ).length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute( \"href\" ) === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55$/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains it's value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t// We use our own, invisible, body unless the body is already present\n\t// in which case we use a div (#9239)\n\ttestElement = document.createElement( body ? \"div\" : \"body\" );\n\ttestElementStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0\n\t};\n\tif ( body ) {\n\t\tjQuery.extend( testElementStyle, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: -1000,\n\t\t\ttop: -1000\n\t\t});\n\t}\n\tfor ( i in testElementStyle ) {\n\t\ttestElement.style[ i ] = testElementStyle[ i ];\n\t}\n\ttestElement.appendChild( div );\n\ttestElementParent = body || documentElement;\n\ttestElementParent.insertBefore( testElement, testElementParent.firstChild );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Remove the body element we added\n\ttestElement.innerHTML = \"\";\n\ttestElementParent.removeChild( testElement );\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t} ) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\t// Null connected elements to avoid leaks in IE\n\ttestElement = fragment = select = opt = body = marginDiv = div = input = null;\n\n\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([a-z])([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar internalKey = jQuery.expando, getByName = typeof name === \"string\", thisCache,\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);\n\t\t\t} else {\n\t\t\t\tcache[ id ] = jQuery.extend(cache[ id ], name);\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Internal jQuery data is stored in a separate object inside the object's data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data\n\t\tif ( pvt ) {\n\t\t\tif ( !thisCache[ internalKey ] ) {\n\t\t\t\tthisCache[ internalKey ] = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache[ internalKey ];\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should\n\t\t// not attempt to inspect the internal events object using jQuery.data, as this\n\t\t// internal data object is undocumented and subject to change.\n\t\tif ( name === \"events\" && !thisCache[name] ) {\n\t\t\treturn thisCache[ internalKey ] && thisCache[ internalKey ].events;\n\t\t}\n\n\t\treturn getByName ? \n\t\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t\tthisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] :\n\t\t\tthisCache;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar internalKey = jQuery.expando, isNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\t\t\tvar thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];\n\n\t\t\tif ( thisCache ) {\n\t\t\t\tdelete thisCache[ name ];\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !isEmptyDataObject(thisCache) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( pvt ) {\n\t\t\tdelete cache[ id ][ internalKey ];\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar internalCache = cache[ id ][ internalKey ];\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\tif ( jQuery.support.deleteExpando || cache != window ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the entire user cache at once because it's faster than\n\t\t// iterating through each key, but we need to continue to persist internal\n\t\t// data if it existed\n\t\tif ( internalCache ) {\n\t\t\tcache[ id ] = {};\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\n\t\t\tcache[ id ][ internalKey ] = internalCache;\n\n\t\t// Otherwise, we need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\t} else if ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar data = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 ) {\n\t\t\t    var attr = this[0].attributes, name;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tvar parts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"$1-$2\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t!jQuery.isNaN( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON\n// property to be considered empty objects; this property always exists in\n// order to make sure JSON.stringify does not expose internal metadata\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery.data( elem, deferDataKey, undefined, true );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&\n\t\t( src === \"mark\" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery.data( elem, queueDataKey, undefined, true ) &&\n\t\t\t\t!jQuery.data( elem, markDataKey, undefined, true ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.resolve();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"mark\";\n\t\t\tjQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery.data( elem, key, count, true );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"queue\";\n\t\t\tvar q = jQuery.data( elem, type, undefined, true );\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery.data( elem, type, jQuery.makeArray(data), true );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\tdefer;\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift(\"inprogress\");\n\t\t\t}\n\n\t\t\tfn.call(elem, function() {\n\t\t\t\tjQuery.dequeue(elem, type);\n\t\t\t});\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[time] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function() {\n\t\t\tvar elem = this;\n\t\t\tsetTimeout(function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, time );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.done( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\trinvalidChar = /\\:|^on/,\n\tformHook, boolHook;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\t\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\t\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \";\n\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\tif ( (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret,\n\t\t\telem = this[0];\n\t\t\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ? \n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") : \n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar isFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\tvar option = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\t\n\tattrFix: {\n\t\t// Always normalize to ensure hook usage\n\t\ttabindex: \"tabIndex\"\n\t},\n\t\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = elem.nodeType;\n\t\t\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( !(\"getAttribute\" in elem) ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Normalize the name if needed\n\t\tif ( notxml ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\n\t\t\thooks = jQuery.attrHooks[ name ];\n\n\t\t\tif ( !hooks ) {\n\t\t\t\t// Use boolHook for boolean attributes\n\t\t\t\tif ( rboolean.test( name ) ) {\n\n\t\t\t\t\thooks = boolHook;\n\n\t\t\t\t// Use formHook for forms and if the name contains certain characters\n\t\t\t\t} else if ( formHook && name !== \"className\" &&\n\t\t\t\t\t(jQuery.nodeName( elem, \"form\" ) || rinvalidChar.test( name )) ) {\n\n\t\t\t\t\thooks = formHook;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn undefined;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, name ) {\n\t\tvar propName;\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\t\t\n\t\t\tif ( jQuery.support.getSetAttribute ) {\n\t\t\t\t// Use removeAttribute in browsers that support it\n\t\t\t\telem.removeAttribute( name );\n\t\t\t} else {\n\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\telem.removeAttributeNode( elem.getAttributeNode( name ) );\n\t\t\t}\n\n\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\tif ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {\n\t\t\t\telem[ propName ] = false;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabIndex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the formHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( formHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn formHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( formHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn formHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\t\n\tprop: function( elem, name, value ) {\n\t\tvar nType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn (elem[ name ] = value);\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\t\n\tpropHooks: {}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\treturn jQuery.prop( elem, name ) ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !jQuery.support.getSetAttribute ) {\n\n\t// propFix is more comprehensive and contains all fixes\n\tjQuery.attrFix = jQuery.propFix;\n\t\n\t// Use this for any attribute on a form in IE6/7\n\tformHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\t// Return undefined if nodeValue is empty string\n\t\t\treturn ret && ret.nodeValue !== \"\" ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Check form objects in IE (multiple bugs related)\n\t\t\t// Only use nodeValue if the attribute node exists on the form\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret ) {\n\t\t\t\tret.nodeValue = value;\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn (elem.style.cssText = \"\" + value);\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(rescape, \"\\\\$&\");\n\t};\n\n/*\n * A number of helper functions used for managing events.\n * Many of the ideas behind this code originated from\n * Dean Edwards' addEvent library.\n */\njQuery.event = {\n\n\t// Bind an event to an element\n\t// Original by Dean Edwards\n\tadd: function( elem, types, handler, data ) {\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t} else if ( !handler ) {\n\t\t\t// Fixes bug #7229. Fix recommended by jdalton\n\t\t\treturn;\n\t\t}\n\n\t\tvar handleObjIn, handleObj;\n\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the function being executed has a unique ID\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure\n\t\tvar elemData = jQuery._data( elem );\n\n\t\t// If no elemData is found then we must be trying to bind to one of the\n\t\t// banned noData elements\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar events = elemData.events,\n\t\t\teventHandle = elemData.handle;\n\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t}\n\n\t\t// Add elem as a property of the handle function\n\t\t// This is to prevent a memory leak with non-native events in IE.\n\t\teventHandle.elem = elem;\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\tvar type, i = 0, namespaces;\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\thandleObj = handleObjIn ?\n\t\t\t\tjQuery.extend({}, handleObjIn) :\n\t\t\t\t{ handler: handler, data: data };\n\n\t\t\t// Namespaced event handlers\n\t\t\tif ( type.indexOf(\".\") > -1 ) {\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\thandleObj.namespace = namespaces.slice(0).sort().join(\".\");\n\n\t\t\t} else {\n\t\t\t\tnamespaces = [];\n\t\t\t\thandleObj.namespace = \"\";\n\t\t\t}\n\n\t\t\thandleObj.type = type;\n\t\t\tif ( !handleObj.guid ) {\n\t\t\t\thandleObj.guid = handler.guid;\n\t\t\t}\n\n\t\t\t// Get the current list of functions bound to this event\n\t\t\tvar handlers = events[ type ],\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// Init the event handler queue\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\n\t\t\t\t// Check for a special event handler\n\t\t\t\t// Only use addEventListener/attachEvent if the special\n\t\t\t\t// events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the function to the element's handler list\n\t\t\thandlers.push( handleObj );\n\n\t\t\t// Keep track of which events have been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, pos ) {\n\t\t// don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t}\n\n\t\tvar ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tevents = elemData && elemData.events;\n\n\t\tif ( !elemData || !events ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// types is actually an event object here\n\t\tif ( types && types.type ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t}\n\n\t\t// Unbind all events for the element\n\t\tif ( !types || typeof types === \"string\" && types.charAt(0) === \".\" ) {\n\t\t\ttypes = types || \"\";\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tjQuery.event.remove( elem, type + types );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).unbind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\torigType = type;\n\t\t\thandleObj = null;\n\t\t\tall = type.indexOf(\".\") < 0;\n\t\t\tnamespaces = [];\n\n\t\t\tif ( !all ) {\n\t\t\t\t// Namespaced event handlers\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\n\t\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" +\n\t\t\t\t\tjQuery.map( namespaces.slice(0).sort(), fcleanup ).join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\t}\n\n\t\t\teventType = events[ type ];\n\n\t\t\tif ( !eventType ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( !handler ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, origType, handleObj.handler, j );\n\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tfor ( j = pos || 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( handler.guid === handleObj.guid ) {\n\t\t\t\t\t// remove the given handler for the given type\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tif ( pos == null ) {\n\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( pos != null ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove generic event handler if no more handlers exist\n\t\t\tif ( eventType.length === 0 || pos != null && eventType.length === 1 ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tret = null;\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tvar handle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\tdelete elemData.events;\n\t\t\tdelete elemData.handle;\n\n\t\t\tif ( jQuery.isEmptyObject( elemData ) ) {\n\t\t\t\tjQuery.removeData( elem, undefined, true );\n\t\t\t}\n\t\t}\n\t},\n\t\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\texclusive;\n\n\t\tif ( type.indexOf(\"!\") >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t// internalKey variable is just used to make it easier to find\n\t\t\t\t// and potentially change this stuff later; currently it just\n\t\t\t\t// points to jQuery.expando\n\t\t\t\tvar internalKey = jQuery.expando,\n\t\t\t\t\tinternalCache = this[ internalKey ];\n\t\t\t\tif ( internalCache && internalCache.events && internalCache.events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, internalCache.handle.elem );\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tevent.target = elem;\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\tvar cur = elem,\n\t\t\t// IE doesn't like method names with a colon (#3533, #8272)\n\t\t\tontype = type.indexOf(\":\") < 0 ? \"on\" + type : \"\";\n\n\t\t// Fire event on the current element, then bubble up the DOM tree\n\t\tdo {\n\t\t\tvar handle = jQuery._data( cur, \"handle\" );\n\n\t\t\tevent.currentTarget = cur;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Trigger an inline bound script\n\t\t\tif ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {\n\t\t\t\tevent.result = false;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\t// Bubble up to document, then to window\n\t\t\tcur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;\n\t\t} while ( cur && !event.isPropagationStopped() );\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tvar old,\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction)() check here because IE6/7 fails that test.\n\t\t\t\t// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.\n\t\t\t\ttry {\n\t\t\t\t\tif ( ontype && elem[ type ] ) {\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t}\n\t\t\t\t} catch ( ieError ) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = undefined;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn event.result;\n\t},\n\n\thandle: function( event ) {\n\t\tevent = jQuery.event.fix( event || window.event );\n\t\t// Snapshot the handlers list since a called handler may add/remove events.\n\t\tvar handlers = ((jQuery._data( this, \"events\" ) || {})[ event.type ] || []).slice(0),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\targs = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// Use the fix-ed Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.currentTarget = this;\n\n\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t// Triggered event must 1) be non-exclusive and have no namespace, or\n\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event.\n\t\t\tif ( run_all || event.namespace_re.test( handleObj.namespace ) ) {\n\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t// So that we can later remove it\n\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\tevent.data = handleObj.data;\n\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\tvar ret = handleObj.handler.apply( this, args );\n\n\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\tevent.result = ret;\n\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn event.result;\n\t},\n\n\tprops: \"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// store a copy of the original event object\n\t\t// and \"clone\" to set read-only properties\n\t\tvar originalEvent = event;\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( var i = this.props.length, prop; i; ) {\n\t\t\tprop = this.props[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary\n\t\tif ( !event.target ) {\n\t\t\t// Fixes #1925 where srcElement might not be defined either\n\t\t\tevent.target = event.srcElement || document;\n\t\t}\n\n\t\t// check if target is a textnode (safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Add relatedTarget, if necessary\n\t\tif ( !event.relatedTarget && event.fromElement ) {\n\t\t\tevent.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n\t\t}\n\n\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\tif ( event.pageX == null && event.clientX != null ) {\n\t\t\tvar eventDocument = event.target.ownerDocument || document,\n\t\t\t\tdoc = eventDocument.documentElement,\n\t\t\t\tbody = eventDocument.body;\n\n\t\t\tevent.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n\t\t\tevent.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && (event.charCode != null || event.keyCode != null) ) {\n\t\t\tevent.which = event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)\n\t\tif ( !event.metaKey && event.ctrlKey ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t// Note: button is not normalized, so don't use it\n\t\tif ( !event.which && event.button !== undefined ) {\n\t\t\tevent.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// Deprecated, use jQuery.guid instead\n\tguid: 1E8,\n\n\t// Deprecated, use jQuery.proxy instead\n\tproxy: jQuery.proxy,\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady,\n\t\t\tteardown: jQuery.noop\n\t\t},\n\n\t\tlive: {\n\t\t\tadd: function( handleObj ) {\n\t\t\t\tjQuery.event.add( this,\n\t\t\t\t\tliveConvert( handleObj.origType, handleObj.selector ),\n\t\t\t\t\tjQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );\n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tjQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !this.preventDefault ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// timeStamp is buggy for some events on Firefox(#3843)\n\t// So we won't rely on the native value\n\tthis.timeStamp = jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Checks if an event happened on an element within another element\n// Used in jQuery.event.special.mouseenter and mouseleave handlers\nvar withinElement = function( event ) {\n\n\t// Check if mouse(over|out) are still within the same parent element\n\tvar related = event.relatedTarget,\n\t\tinside = false,\n\t\teventType = event.type;\n\n\tevent.type = event.data;\n\n\tif ( related !== this ) {\n\n\t\tif ( related ) {\n\t\t\tinside = jQuery.contains( this, related );\n\t\t}\n\n\t\tif ( !inside ) {\n\n\t\t\tjQuery.event.handle.apply( this, arguments );\n\n\t\t\tevent.type = eventType;\n\t\t}\n\t}\n},\n\n// In case of event delegation, we only need to rename the event.type,\n// liveHandler will take care of the rest.\ndelegate = function( event ) {\n\tevent.type = event.data;\n\tjQuery.event.handle.apply( this, arguments );\n};\n\n// Create mouseenter and mouseleave events\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tsetup: function( data ) {\n\t\t\tjQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );\n\t\t},\n\t\tteardown: function( data ) {\n\t\t\tjQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );\n\t\t}\n\t};\n});\n\n// submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( !jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"text\" || type === \"password\") && jQuery( elem ).closest(\"form\").length && e.keyCode === 13 ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialSubmit\" );\n\t\t}\n\t};\n\n}\n\n// change delegation, happens here so we have bind.\nif ( !jQuery.support.changeBubbles ) {\n\n\tvar changeFilters,\n\n\tgetVal = function( elem ) {\n\t\tvar type = elem.type, val = elem.value;\n\n\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\tval = elem.checked;\n\n\t\t} else if ( type === \"select-multiple\" ) {\n\t\t\tval = elem.selectedIndex > -1 ?\n\t\t\t\tjQuery.map( elem.options, function( elem ) {\n\t\t\t\t\treturn elem.selected;\n\t\t\t\t}).join(\"-\") :\n\t\t\t\t\"\";\n\n\t\t} else if ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\tval = elem.selectedIndex;\n\t\t}\n\n\t\treturn val;\n\t},\n\n\ttestChange = function testChange( e ) {\n\t\tvar elem = e.target, data, val;\n\n\t\tif ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdata = jQuery._data( elem, \"_change_data\" );\n\t\tval = getVal(elem);\n\n\t\t// the current data will be also retrieved by beforeactivate\n\t\tif ( e.type !== \"focusout\" || elem.type !== \"radio\" ) {\n\t\t\tjQuery._data( elem, \"_change_data\", val );\n\t\t}\n\n\t\tif ( data === undefined || val === data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data != null || val ) {\n\t\t\te.type = \"change\";\n\t\t\te.liveFired = undefined;\n\t\t\tjQuery.event.trigger( e, arguments[1], elem );\n\t\t}\n\t};\n\n\tjQuery.event.special.change = {\n\t\tfilters: {\n\t\t\tfocusout: testChange,\n\n\t\t\tbeforedeactivate: testChange,\n\n\t\t\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Change has to be called before submit\n\t\t\t// Keydown will be called before keypress, which is used in submit-event delegation\n\t\t\tkeydown: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( (e.keyCode === 13 && !jQuery.nodeName( elem, \"textarea\" ) ) ||\n\t\t\t\t\t(e.keyCode === 32 && (type === \"checkbox\" || type === \"radio\")) ||\n\t\t\t\t\ttype === \"select-multiple\" ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Beforeactivate happens also before the previous element is blurred\n\t\t\t// with this event you can't trigger a change event, but you can store\n\t\t\t// information\n\t\t\tbeforeactivate: function( e ) {\n\t\t\t\tvar elem = e.target;\n\t\t\t\tjQuery._data( elem, \"_change_data\", getVal(elem) );\n\t\t\t}\n\t\t},\n\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( this.type === \"file\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( var type in changeFilters ) {\n\t\t\t\tjQuery.event.add( this, type + \".specialChange\", changeFilters[type] );\n\t\t\t}\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialChange\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n\n\t// Handle when the input is .focus()'d\n\tchangeFilters.focus = changeFilters.beforeactivate;\n}\n\nfunction trigger( type, elem, args ) {\n\t// Piggyback on a donor event to simulate a different one.\n\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t// simulated event prevents default then we do the same on the donor.\n\t// Don't pass args or remember liveFired; they apply to the donor event.\n\tvar event = jQuery.extend( {}, args[ 0 ] );\n\tevent.type = type;\n\tevent.originalEvent = {};\n\tevent.liveFired = undefined;\n\tjQuery.event.handle.call( elem, event );\n\tif ( event.isDefaultPrevented() ) {\n\t\targs[ 0 ].preventDefault();\n\t}\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0;\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfunction handler( donor ) {\n\t\t\t// Donor event is always a native one; fix it and switch its type.\n\t\t\t// Let focusin/out handler cancel the donor focus/blur event.\n\t\t\tvar e = jQuery.event.fix( donor );\n\t\t\te.type = fix;\n\t\t\te.originalEvent = {};\n\t\t\tjQuery.event.trigger( e, null, e.target );\n\t\t\tif ( e.isDefaultPrevented() ) {\n\t\t\t\tdonor.preventDefault();\n\t\t\t}\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\n\t\tvar handler;\n\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis[ name ](key, data, type[key], fn);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( arguments.length === 2 || data === false ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tif ( name === \"one\" ) {\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t\thandler.guid = fn.guid || jQuery.guid++;\n\t\t} else {\n\t\t\thandler = fn;\n\t\t}\n\n\t\tif ( type === \"unload\" && name !== \"one\" ) {\n\t\t\tthis.one( type, data, fn );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( this[i], type, handler, data );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\njQuery.fn.extend({\n\tunbind: function( type, fn ) {\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" && !type.preventDefault ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis.unbind(key, type[key]);\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.remove( this[i], type, fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\treturn this.unbind( \"live\" );\n\n\t\t} else {\n\t\t\treturn this.die( types, null, fn, selector );\n\t\t}\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery.data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery.data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\nvar liveMap = {\n\tfocus: \"focusin\",\n\tblur: \"focusout\",\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n};\n\njQuery.each([\"live\", \"die\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {\n\t\tvar type, i = 0, match, namespaces, preType,\n\t\t\tselector = origSelector || this.selector,\n\t\t\tcontext = origSelector ? this : jQuery( this.context );\n\n\t\tif ( typeof types === \"object\" && !types.preventDefault ) {\n\t\t\tfor ( var key in types ) {\n\t\t\t\tcontext[ name ]( key, data, types[key], selector );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( name === \"die\" && !types &&\n\t\t\t\t\torigSelector && origSelector.charAt(0) === \".\" ) {\n\n\t\t\tcontext.unbind( origSelector );\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data === false || jQuery.isFunction( data ) ) {\n\t\t\tfn = data || returnFalse;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\ttypes = (types || \"\").split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) != null ) {\n\t\t\tmatch = rnamespaces.exec( type );\n\t\t\tnamespaces = \"\";\n\n\t\t\tif ( match )  {\n\t\t\t\tnamespaces = match[0];\n\t\t\t\ttype = type.replace( rnamespaces, \"\" );\n\t\t\t}\n\n\t\t\tif ( type === \"hover\" ) {\n\t\t\t\ttypes.push( \"mouseenter\" + namespaces, \"mouseleave\" + namespaces );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpreType = type;\n\n\t\t\tif ( liveMap[ type ] ) {\n\t\t\t\ttypes.push( liveMap[ type ] + namespaces );\n\t\t\t\ttype = type + namespaces;\n\n\t\t\t} else {\n\t\t\t\ttype = (liveMap[ type ] || type) + namespaces;\n\t\t\t}\n\n\t\t\tif ( name === \"live\" ) {\n\t\t\t\t// bind live handler\n\t\t\t\tfor ( var j = 0, l = context.length; j < l; j++ ) {\n\t\t\t\t\tjQuery.event.add( context[j], \"live.\" + liveConvert( type, selector ),\n\t\t\t\t\t\t{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// unbind live handler\n\t\t\t\tcontext.unbind( \"live.\" + liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\nfunction liveHandler( event ) {\n\tvar stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,\n\t\telems = [],\n\t\tselectors = [],\n\t\tevents = jQuery._data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)\n\tif ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === \"click\" ) {\n\t\treturn;\n\t}\n\n\tif ( event.namespace ) {\n\t\tnamespace = new RegExp(\"(^|\\\\.)\" + event.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t}\n\n\tevent.liveFired = this;\n\n\tvar live = events.live.slice(0);\n\n\tfor ( j = 0; j < live.length; j++ ) {\n\t\thandleObj = live[j];\n\n\t\tif ( handleObj.origType.replace( rnamespaces, \"\" ) === event.type ) {\n\t\t\tselectors.push( handleObj.selector );\n\n\t\t} else {\n\t\t\tlive.splice( j--, 1 );\n\t\t}\n\t}\n\n\tmatch = jQuery( event.target ).closest( selectors, event.currentTarget );\n\n\tfor ( i = 0, l = match.length; i < l; i++ ) {\n\t\tclose = match[i];\n\n\t\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {\n\t\t\t\telem = close.elem;\n\t\t\t\trelated = null;\n\n\t\t\t\t// Those two events require additional checking\n\t\t\t\tif ( handleObj.preType === \"mouseenter\" || handleObj.preType === \"mouseleave\" ) {\n\t\t\t\t\tevent.type = handleObj.preType;\n\t\t\t\t\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\n\n\t\t\t\t\t// Make sure not to accidentally match a child element with the same selector\n\t\t\t\t\tif ( related && jQuery.contains( elem, related ) ) {\n\t\t\t\t\t\trelated = elem;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !related || related !== elem ) {\n\t\t\t\t\telems.push({ elem: elem, handleObj: handleObj, level: close.level });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( i = 0, l = elems.length; i < l; i++ ) {\n\t\tmatch = elems[i];\n\n\t\tif ( maxLevel && match.level > maxLevel ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tret = match.handleObj.origHandler.apply( match.elem, arguments );\n\n\t\tif ( ret === false || event.isPropagationStopped() ) {\n\t\t\tmaxLevel = match.level;\n\n\t\t\tif ( ret === false ) {\n\t\t\t\tstop = false;\n\t\t\t}\n\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(rperiod, \"`\").replace(rspaces, \"&\");\n}\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.bind( name, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( var i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tvar pass = not ^ !!found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar type = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tvar first = match[2],\n\t\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent.sizcache = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar diff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Expr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Utility function for retreiving the text value of an array of DOM nodes\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( typeof selector === \"string\" ?\n\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar match, selector,\n\t\t\t\tmatches = {},\n\t\t\t\tlevel = 1;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( i = 0, l = selectors.length; i < l; i++ ) {\n\t\t\t\t\tselector = selectors[i];\n\n\t\t\t\t\tif ( !matches[ selector ] ) {\n\t\t\t\t\t\tmatches[ selector ] = POS.test( selector ) ?\n\t\t\t\t\t\t\tjQuery( selector, context || this.context ) :\n\t\t\t\t\t\t\tselector;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\t\tfor ( selector in matches ) {\n\t\t\t\t\t\tmatch = matches[ selector ];\n\n\t\t\t\t\t\tif ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {\n\t\t\t\t\t\t\tret.push({ selector: selector, elem: cur, level: level });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tlevel++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\t\tif ( !elem || typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0],\n\t\t\t\t// If it receives a string, the selector is used\n\t\t\t\t// If it receives nothing, the siblings are used\n\t\t\t\telem ? jQuery( elem ) : this.parent().children() );\n\t\t}\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until ),\n\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, args.join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn (elem === qualifier) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn (jQuery.inArray( elem, qualifier ) >= 0) === keep;\n\t});\n}\n\n\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery(arguments[0]);\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery(arguments[0]).toArray() );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnocache.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || (l > 1 && i < lastIndex) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar internalKey = jQuery.expando,\n\t\toldData = jQuery.data( src ),\n\t\tcurData = jQuery.data( dest, oldData );\n\n\t// Switch to use the internal data object, if it exists, for the next\n\t// stage of data copying\n\tif ( (oldData = oldData[ internalKey ]) ) {\n\t\tvar events = oldData.events;\n\t\t\t\tcurData = curData[ internalKey ] = jQuery.extend({}, oldData);\n\n\t\tif ( events ) {\n\t\t\tdelete curData.handle;\n\t\t\tcurData.events = {};\n\n\t\t\tfor ( var type in events ) {\n\t\t\t\tfor ( var i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc;\n\n  // nodes may contain either an explicit document object,\n  // a jQuery collection or context object.\n  // If nodes[0] contains a valid object to assign to doc\n  if ( nodes && nodes[0] ) {\n    doc = nodes[0].ownerDocument || nodes[0];\n  }\n\n  // Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\tif ( args.length === 1 && typeof args[0] === \"string\" && args[0].length < 512 && doc === document &&\n\t\targs[0].charAt(0) === \"<\" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ args[0] ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = (i > 0 ? this.clone(true) : this).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( \"getElementsByTagName\" in elem ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( \"querySelectorAll\" in elem ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\tfixDefaultChecked( elem );\n\t} else if ( \"getElementsByTagName\" in elem ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName\n\t\t\t// instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = (rtagName.exec( elem ) || [\"\", \"\"])[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ] && cache[ id ][ internalKey ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^[+\\-]=/,\n\trrelNumFilter = /[^+\\-\\.\\de]+/g,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( type === \"number\" && isNaN( value ) || value == null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && rrelNum.test( value ) ) {\n\t\t\t\tvalue = +value.replace( rrelNumFilter, \"\" ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWH( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat( value );\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle;\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// Set the alpha filter to set the opacity\n\t\t\tvar opacity = jQuery.isNaN( value ) ?\n\t\t\t\t\"\" :\n\t\t\t\t\"alpha(opacity=\" + value * 100 + \")\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( !(defaultView = elem.ownerDocument.defaultView) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : (ret || 0);\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tjQuery.each( which, function() {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ] || 0;\n\t}\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tjQuery.each( which, function() {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn val + \"px\";\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts;\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor(; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor(; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function ( target, settings ) {\n\t\tif ( !settings ) {\n\t\t\t// Only one parameter, we extend ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.extend( true, jQuery.ajaxSettings, settings );\n\t\t} else {\n\t\t\t// target was provided, we extend into it\n\t\t\tjQuery.extend( true, target, jQuery.ajaxSettings, settings );\n\t\t}\n\t\t// Flatten fields we don't want deep extended\n\t\tfor( var field in { context: 1, url: 1 } ) {\n\t\t\tif ( field in settings ) {\n\t\t\t\ttarget[ field ] = settings[ field ];\n\t\t\t} else if( field in jQuery.ajaxSettings ) {\n\t\t\t\ttarget[ field ] = jQuery.ajaxSettings[ field ];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": \"*/*\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery._Deferred(),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, statusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = statusText;\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.done;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", */*; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( status < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.error( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor( key in s.converters ) {\n\t\t\t\tif( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow,\n\trequestAnimationFrame = window.webkitRequestAnimationFrame ||\n\t\twindow.mozRequestAnimationFrame ||\n\t\twindow.oRequestAnimationFrame;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css( elem, \"display\" ) === \"none\" ) {\n\t\t\t\t\t\tjQuery._data(elem, \"olddisplay\", defaultDisplay(elem.nodeName));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data(elem, \"olddisplay\") || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tvar display = jQuery.css( this[i], \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( this[i], \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( this[i], \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed(speed, easing, callback);\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p,\n\t\t\t\tdisplay, e,\n\t\t\t\tparts, start, end, unit;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height\n\t\t\t\t\t// animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = defaultDisplay( this.nodeName );\n\n\t\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\t\tif ( display === \"inline\" ) {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline\";\n\t\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test(val) ) {\n\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]();\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ((end || 1) / e.cur()) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t});\n\t},\n\n\tstop: function( clearQueue, gotoEnd ) {\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar timers = jQuery.timers,\n\t\t\t\ti = timers.length;\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( timers[i].elem === this ) {\n\t\t\t\t\tif (gotoEnd) {\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[i](true);\n\t\t\t\t\t}\n\n\t\t\t\t\ttimers.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// start the next in the queue if the last step wasn't forced\n\t\tif ( !gotoEnd ) {\n\t\t\tthis.dequeue();\n\t\t}\n\n\t\treturn this;\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\", 1),\n\tslideUp: genFx(\"hide\", 1),\n\tslideToggle: genFx(\"toggle\", 1),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend({}, speed) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction(easing) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery.dequeue( this );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx,\n\t\t\traf;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step(gotoEnd);\n\t\t}\n\n\t\tt.elem = this.elem;\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\t// Use requestAnimationFrame instead of setInterval if available\n\t\t\tif ( requestAnimationFrame ) {\n\t\t\t\ttimerId = true;\n\t\t\t\traf = function() {\n\t\t\t\t\t// When timerId gets set to null at any point, this stops\n\t\t\t\t\tif ( timerId ) {\n\t\t\t\t\t\trequestAnimationFrame( raf );\n\t\t\t\t\t\tfx.tick();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trequestAnimationFrame( raf );\n\t\t\t} else {\n\t\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any\n\t\t// flash of content\n\t\tthis.custom(this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur());\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom(this.cur(), 0);\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar t = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options,\n\t\t\ti, n;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( i in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[i] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function (index, value) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[index];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery(elem).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( var p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[p] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\toptions.complete.call( elem );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ((this.end - this.start) * this.pos);\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tfor ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {\n\t\t\tif ( !timers[i]() ) {\n\t\t\t\ttimers.splice(i--, 1);\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = (fx.prop === \"width\" || fx.prop === \"height\" ? Math.max(0, fx.now) : fx.now) + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( document.compatMode === \"CSS1Compat\" ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tjQuery.offset.initialize();\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\tinitialize: function() {\n\t\tvar body = document.body, container = document.createElement(\"div\"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, \"marginTop\") ) || 0,\n\t\t\thtml = \"<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>\";\n\n\t\tjQuery.extend( container.style, { position: \"absolute\", top: 0, left: 0, margin: 0, border: 0, width: \"1px\", height: \"1px\", visibility: \"hidden\" } );\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\tinnerDiv = container.firstChild;\n\t\tcheckDiv = innerDiv.firstChild;\n\t\ttd = innerDiv.nextSibling.firstChild.firstChild;\n\n\t\tthis.doesNotAddBorder = (checkDiv.offsetTop !== 5);\n\t\tthis.doesAddBorderForTableAndCells = (td.offsetTop === 5);\n\n\t\tcheckDiv.style.position = \"fixed\";\n\t\tcheckDiv.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\tthis.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);\n\t\tcheckDiv.style.position = checkDiv.style.top = \"\";\n\n\t\tinnerDiv.style.overflow = \"hidden\";\n\t\tinnerDiv.style.position = \"relative\";\n\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = (position === \"absolute\" || position === \"fixed\") && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif (options.top != null) {\n\t\t\tprops.top = (options.top - curOffset.top) + curTop;\n\t\t}\n\t\tif (options.left != null) {\n\t\t\tprops.left = (options.left - curOffset.left) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem && elem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem && elem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ];\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\telem.document.body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNaN( ret ) ? orig : ret;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.6.3.js",
    "content": "/*!\n * jQuery JavaScript Library v1.6.3\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Aug 31 10:35:15 2011 -0400\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Check for digits\n\trdigit = /\\d/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = (context ? context.ownerDocument || context : document);\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn (context || rootjQuery).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif (selector.selector !== undefined) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.6.3\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + (this.selector ? \" \" : \"\") + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, +i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).unbind( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery._Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNaN: function( obj ) {\n\t\treturn obj == null || !rdigit.test( obj ) || isNaN( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn (new Function( \"return \" + data ))();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array ) {\n\t\tif ( !array ) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif ( indexOf ) {\n\t\t\treturn indexOf.call( array, elem );\n\t\t}\n\n\t\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\t\tif ( array[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn (new Date()).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\nvar // Promise methods\n\tpromiseMethods = \"done fail isResolved isRejected promise then always pipe\".split( \" \" ),\n\t// Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\t// Create a simple deferred (one callbacks list)\n\t_Deferred: function() {\n\t\tvar // callbacks list\n\t\t\tcallbacks = [],\n\t\t\t// stored [ context , args ]\n\t\t\tfired,\n\t\t\t// to avoid firing when already doing so\n\t\t\tfiring,\n\t\t\t// flag to know if the deferred has been cancelled\n\t\t\tcancelled,\n\t\t\t// the deferred itself\n\t\t\tdeferred  = {\n\n\t\t\t\t// done( f1, f2, ...)\n\t\t\t\tdone: function() {\n\t\t\t\t\tif ( !cancelled ) {\n\t\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t_fired;\n\t\t\t\t\t\tif ( fired ) {\n\t\t\t\t\t\t\t_fired = fired;\n\t\t\t\t\t\t\tfired = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\t\t\t\telem = args[ i ];\n\t\t\t\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t\t\t\tdeferred.done.apply( deferred, elem );\n\t\t\t\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tcallbacks.push( elem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( _fired ) {\n\t\t\t\t\t\t\tdeferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with given context and args\n\t\t\t\tresolveWith: function( context, args ) {\n\t\t\t\t\tif ( !cancelled && !fired && !firing ) {\n\t\t\t\t\t\t// make sure args are available (#8421)\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\tfiring = 1;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twhile( callbacks[ 0 ] ) {\n\t\t\t\t\t\t\t\tcallbacks.shift().apply( context, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally {\n\t\t\t\t\t\t\tfired = [ context, args ];\n\t\t\t\t\t\t\tfiring = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with this as context and given arguments\n\t\t\t\tresolve: function() {\n\t\t\t\t\tdeferred.resolveWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Has this deferred been resolved?\n\t\t\t\tisResolved: function() {\n\t\t\t\t\treturn !!( firing || fired );\n\t\t\t\t},\n\n\t\t\t\t// Cancel\n\t\t\t\tcancel: function() {\n\t\t\t\t\tcancelled = 1;\n\t\t\t\t\tcallbacks = [];\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn deferred;\n\t},\n\n\t// Full fledged deferred (two callbacks list)\n\tDeferred: function( func ) {\n\t\tvar deferred = jQuery._Deferred(),\n\t\t\tfailDeferred = jQuery._Deferred(),\n\t\t\tpromise;\n\t\t// Add errorDeferred methods, then and promise\n\t\tjQuery.extend( deferred, {\n\t\t\tthen: function( doneCallbacks, failCallbacks ) {\n\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\talways: function() {\n\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );\n\t\t\t},\n\t\t\tfail: failDeferred.done,\n\t\t\trejectWith: failDeferred.resolveWith,\n\t\t\treject: failDeferred.resolve,\n\t\t\tisRejected: failDeferred.isResolved,\n\t\t\tpipe: function( fnDone, fnFail ) {\n\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\tfail: [ fnFail, \"reject\" ]\n\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).promise();\n\t\t\t},\n\t\t\t// Get a promise for this deferred\n\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\tpromise: function( obj ) {\n\t\t\t\tif ( obj == null ) {\n\t\t\t\t\tif ( promise ) {\n\t\t\t\t\t\treturn promise;\n\t\t\t\t\t}\n\t\t\t\t\tpromise = obj = {};\n\t\t\t\t}\n\t\t\t\tvar i = promiseMethods.length;\n\t\t\t\twhile( i-- ) {\n\t\t\t\t\tobj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t});\n\t\t// Make sure only one callback list will be used\n\t\tdeferred.done( failDeferred.cancel ).fail( deferred.cancel );\n\t\t// Unexpose cancel\n\t\tdelete deferred.cancel;\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = arguments,\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tcount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t// Strange bug in FF4:\n\t\t\t\t\t// Values changed onto the arguments object sometimes end up as undefined values\n\t\t\t\t\t// outside the $.when method. Cloning the object into a fresh array solves the issue\n\t\t\t\t\tdeferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn deferred.promise();\n\t}\n});\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\ttestElementParent,\n\t\ttestElement,\n\t\ttestElementStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type=checkbox>\";\n\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName( \"tbody\" ).length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName( \"link\" ).length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute( \"href\" ) === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55$/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains it's value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t// We use our own, invisible, body unless the body is already present\n\t// in which case we use a div (#9239)\n\ttestElement = document.createElement( body ? \"div\" : \"body\" );\n\ttestElementStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\tbackground: \"none\"\n\t};\n\tif ( body ) {\n\t\tjQuery.extend( testElementStyle, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: \"-1000px\",\n\t\t\ttop: \"-1000px\"\n\t\t});\n\t}\n\tfor ( i in testElementStyle ) {\n\t\ttestElement.style[ i ] = testElementStyle[ i ];\n\t}\n\ttestElement.appendChild( div );\n\ttestElementParent = body || documentElement;\n\ttestElementParent.insertBefore( testElement, testElementParent.firstChild );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Remove the body element we added\n\ttestElement.innerHTML = \"\";\n\ttestElementParent.removeChild( testElement );\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t} ) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\t// Null connected elements to avoid leaks in IE\n\ttestElement = fragment = select = opt = body = marginDiv = div = input = null;\n\n\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([a-z])([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);\n\t\t\t} else {\n\t\t\t\tcache[ id ] = jQuery.extend(cache[ id ], name);\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Internal jQuery data is stored in a separate object inside the object's data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data\n\t\tif ( pvt ) {\n\t\t\tif ( !thisCache[ internalKey ] ) {\n\t\t\t\tthisCache[ internalKey ] = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache[ internalKey ];\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should\n\t\t// not attempt to inspect the internal events object using jQuery.data, as this\n\t\t// internal data object is undocumented and subject to change.\n\t\tif ( name === \"events\" && !thisCache[name] ) {\n\t\t\treturn thisCache[ internalKey ] && thisCache[ internalKey ].events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support interoperable removal of hyphenated or camelcased keys\n\t\t\t\tif ( !thisCache[ name ] ) {\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t}\n\n\t\t\t\tdelete thisCache[ name ];\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !isEmptyDataObject(thisCache) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( pvt ) {\n\t\t\tdelete cache[ id ][ internalKey ];\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar internalCache = cache[ id ][ internalKey ];\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the entire user cache at once because it's faster than\n\t\t// iterating through each key, but we need to continue to persist internal\n\t\t// data if it existed\n\t\tif ( internalCache ) {\n\t\t\tcache[ id ] = {};\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\n\t\t\tcache[ id ][ internalKey ] = internalCache;\n\n\t\t// Otherwise, we need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\t} else if ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar data = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 ) {\n\t\t\t    var attr = this[0].attributes, name;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tvar parts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"$1-$2\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t!jQuery.isNaN( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON\n// property to be considered empty objects; this property always exists in\n// order to make sure JSON.stringify does not expose internal metadata\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery.data( elem, deferDataKey, undefined, true );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&\n\t\t( src === \"mark\" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery.data( elem, queueDataKey, undefined, true ) &&\n\t\t\t\t!jQuery.data( elem, markDataKey, undefined, true ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.resolve();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"mark\";\n\t\t\tjQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery.data( elem, key, count, true );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"queue\";\n\t\t\tvar q = jQuery.data( elem, type, undefined, true );\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery.data( elem, type, jQuery.makeArray(data), true );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\tdefer;\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift(\"inprogress\");\n\t\t\t}\n\n\t\t\tfn.call(elem, function() {\n\t\t\t\tjQuery.dequeue(elem, type);\n\t\t\t});\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[time] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function() {\n\t\t\tvar elem = this;\n\t\t\tsetTimeout(function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, time );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.done( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tnodeHook, boolHook;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\t\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\t\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \";\n\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret,\n\t\t\telem = this[0];\n\t\t\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ? \n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") : \n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar isFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\tvar option = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\t\n\tattrFix: {\n\t\t// Always normalize to ensure hook usage\n\t\ttabindex: \"tabIndex\"\n\t},\n\t\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = elem.nodeType;\n\t\t\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( !(\"getAttribute\" in elem) ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Normalize the name if needed\n\t\tif ( notxml ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\n\t\t\thooks = jQuery.attrHooks[ name ];\n\n\t\t\tif ( !hooks ) {\n\t\t\t\t// Use boolHook for boolean attributes\n\t\t\t\tif ( rboolean.test( name ) ) {\n\t\t\t\t\thooks = boolHook;\n\n\t\t\t\t// Use nodeHook if available( IE6/7 )\n\t\t\t\t} else if ( nodeHook ) {\n\t\t\t\t\thooks = nodeHook;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn undefined;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, name ) {\n\t\tvar propName;\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\n\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\telem.removeAttribute( name );\n\n\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\tif ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {\n\t\t\t\telem[ propName ] = false;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\t\n\tprop: function( elem, name, value ) {\n\t\tvar nType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn (elem[ name ] = value);\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\t\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabindex propHook to attrHooks for back-compat\njQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode;\n\t\treturn jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !jQuery.support.getSetAttribute ) {\n\t\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\t// Return undefined if nodeValue is empty string\n\t\t\treturn ret && ret.nodeValue !== \"\" ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn (ret.nodeValue = value + \"\");\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn (elem.style.cssText = \"\" + value);\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(rescape, \"\\\\$&\");\n\t};\n\n/*\n * A number of helper functions used for managing events.\n * Many of the ideas behind this code originated from\n * Dean Edwards' addEvent library.\n */\njQuery.event = {\n\n\t// Bind an event to an element\n\t// Original by Dean Edwards\n\tadd: function( elem, types, handler, data ) {\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t} else if ( !handler ) {\n\t\t\t// Fixes bug #7229. Fix recommended by jdalton\n\t\t\treturn;\n\t\t}\n\n\t\tvar handleObjIn, handleObj;\n\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the function being executed has a unique ID\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure\n\t\tvar elemData = jQuery._data( elem );\n\n\t\t// If no elemData is found then we must be trying to bind to one of the\n\t\t// banned noData elements\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar events = elemData.events,\n\t\t\teventHandle = elemData.handle;\n\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t}\n\n\t\t// Add elem as a property of the handle function\n\t\t// This is to prevent a memory leak with non-native events in IE.\n\t\teventHandle.elem = elem;\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\tvar type, i = 0, namespaces;\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\thandleObj = handleObjIn ?\n\t\t\t\tjQuery.extend({}, handleObjIn) :\n\t\t\t\t{ handler: handler, data: data };\n\n\t\t\t// Namespaced event handlers\n\t\t\tif ( type.indexOf(\".\") > -1 ) {\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\thandleObj.namespace = namespaces.slice(0).sort().join(\".\");\n\n\t\t\t} else {\n\t\t\t\tnamespaces = [];\n\t\t\t\thandleObj.namespace = \"\";\n\t\t\t}\n\n\t\t\thandleObj.type = type;\n\t\t\tif ( !handleObj.guid ) {\n\t\t\t\thandleObj.guid = handler.guid;\n\t\t\t}\n\n\t\t\t// Get the current list of functions bound to this event\n\t\t\tvar handlers = events[ type ],\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// Init the event handler queue\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\n\t\t\t\t// Check for a special event handler\n\t\t\t\t// Only use addEventListener/attachEvent if the special\n\t\t\t\t// events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the function to the element's handler list\n\t\t\thandlers.push( handleObj );\n\n\t\t\t// Keep track of which events have been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, pos ) {\n\t\t// don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t}\n\n\t\tvar ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tevents = elemData && elemData.events;\n\n\t\tif ( !elemData || !events ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// types is actually an event object here\n\t\tif ( types && types.type ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t}\n\n\t\t// Unbind all events for the element\n\t\tif ( !types || typeof types === \"string\" && types.charAt(0) === \".\" ) {\n\t\t\ttypes = types || \"\";\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tjQuery.event.remove( elem, type + types );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).unbind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\torigType = type;\n\t\t\thandleObj = null;\n\t\t\tall = type.indexOf(\".\") < 0;\n\t\t\tnamespaces = [];\n\n\t\t\tif ( !all ) {\n\t\t\t\t// Namespaced event handlers\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\n\t\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" +\n\t\t\t\t\tjQuery.map( namespaces.slice(0).sort(), fcleanup ).join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\t}\n\n\t\t\teventType = events[ type ];\n\n\t\t\tif ( !eventType ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( !handler ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, origType, handleObj.handler, j );\n\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tfor ( j = pos || 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( handler.guid === handleObj.guid ) {\n\t\t\t\t\t// remove the given handler for the given type\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tif ( pos == null ) {\n\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( pos != null ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove generic event handler if no more handlers exist\n\t\t\tif ( eventType.length === 0 || pos != null && eventType.length === 1 ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tret = null;\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tvar handle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\tdelete elemData.events;\n\t\t\tdelete elemData.handle;\n\n\t\t\tif ( jQuery.isEmptyObject( elemData ) ) {\n\t\t\t\tjQuery.removeData( elem, undefined, true );\n\t\t\t}\n\t\t}\n\t},\n\t\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\texclusive;\n\n\t\tif ( type.indexOf(\"!\") >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t// internalKey variable is just used to make it easier to find\n\t\t\t\t// and potentially change this stuff later; currently it just\n\t\t\t\t// points to jQuery.expando\n\t\t\t\tvar internalKey = jQuery.expando,\n\t\t\t\t\tinternalCache = this[ internalKey ];\n\t\t\t\tif ( internalCache && internalCache.events && internalCache.events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, internalCache.handle.elem );\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tevent.target = elem;\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\tvar cur = elem,\n\t\t\t// IE doesn't like method names with a colon (#3533, #8272)\n\t\t\tontype = type.indexOf(\":\") < 0 ? \"on\" + type : \"\";\n\n\t\t// Fire event on the current element, then bubble up the DOM tree\n\t\tdo {\n\t\t\tvar handle = jQuery._data( cur, \"handle\" );\n\n\t\t\tevent.currentTarget = cur;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Trigger an inline bound script\n\t\t\tif ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {\n\t\t\t\tevent.result = false;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\t// Bubble up to document, then to window\n\t\t\tcur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;\n\t\t} while ( cur && !event.isPropagationStopped() );\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tvar old,\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction)() check here because IE6/7 fails that test.\n\t\t\t\t// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.\n\t\t\t\ttry {\n\t\t\t\t\tif ( ontype && elem[ type ] ) {\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t}\n\t\t\t\t} catch ( ieError ) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = undefined;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn event.result;\n\t},\n\n\thandle: function( event ) {\n\t\tevent = jQuery.event.fix( event || window.event );\n\t\t// Snapshot the handlers list since a called handler may add/remove events.\n\t\tvar handlers = ((jQuery._data( this, \"events\" ) || {})[ event.type ] || []).slice(0),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\targs = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// Use the fix-ed Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.currentTarget = this;\n\n\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t// Triggered event must 1) be non-exclusive and have no namespace, or\n\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event.\n\t\t\tif ( run_all || event.namespace_re.test( handleObj.namespace ) ) {\n\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t// So that we can later remove it\n\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\tevent.data = handleObj.data;\n\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\tvar ret = handleObj.handler.apply( this, args );\n\n\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\tevent.result = ret;\n\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn event.result;\n\t},\n\n\tprops: \"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// store a copy of the original event object\n\t\t// and \"clone\" to set read-only properties\n\t\tvar originalEvent = event;\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( var i = this.props.length, prop; i; ) {\n\t\t\tprop = this.props[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary\n\t\tif ( !event.target ) {\n\t\t\t// Fixes #1925 where srcElement might not be defined either\n\t\t\tevent.target = event.srcElement || document;\n\t\t}\n\n\t\t// check if target is a textnode (safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Add relatedTarget, if necessary\n\t\tif ( !event.relatedTarget && event.fromElement ) {\n\t\t\tevent.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n\t\t}\n\n\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\tif ( event.pageX == null && event.clientX != null ) {\n\t\t\tvar eventDocument = event.target.ownerDocument || document,\n\t\t\t\tdoc = eventDocument.documentElement,\n\t\t\t\tbody = eventDocument.body;\n\n\t\t\tevent.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n\t\t\tevent.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && (event.charCode != null || event.keyCode != null) ) {\n\t\t\tevent.which = event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)\n\t\tif ( !event.metaKey && event.ctrlKey ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t// Note: button is not normalized, so don't use it\n\t\tif ( !event.which && event.button !== undefined ) {\n\t\t\tevent.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// Deprecated, use jQuery.guid instead\n\tguid: 1E8,\n\n\t// Deprecated, use jQuery.proxy instead\n\tproxy: jQuery.proxy,\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady,\n\t\t\tteardown: jQuery.noop\n\t\t},\n\n\t\tlive: {\n\t\t\tadd: function( handleObj ) {\n\t\t\t\tjQuery.event.add( this,\n\t\t\t\t\tliveConvert( handleObj.origType, handleObj.selector ),\n\t\t\t\t\tjQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );\n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tjQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !this.preventDefault ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// timeStamp is buggy for some events on Firefox(#3843)\n\t// So we won't rely on the native value\n\tthis.timeStamp = jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Checks if an event happened on an element within another element\n// Used in jQuery.event.special.mouseenter and mouseleave handlers\nvar withinElement = function( event ) {\n\n\t// Check if mouse(over|out) are still within the same parent element\n\tvar related = event.relatedTarget,\n\t\tinside = false,\n\t\teventType = event.type;\n\n\tevent.type = event.data;\n\n\tif ( related !== this ) {\n\n\t\tif ( related ) {\n\t\t\tinside = jQuery.contains( this, related );\n\t\t}\n\n\t\tif ( !inside ) {\n\n\t\t\tjQuery.event.handle.apply( this, arguments );\n\n\t\t\tevent.type = eventType;\n\t\t}\n\t}\n},\n\n// In case of event delegation, we only need to rename the event.type,\n// liveHandler will take care of the rest.\ndelegate = function( event ) {\n\tevent.type = event.data;\n\tjQuery.event.handle.apply( this, arguments );\n};\n\n// Create mouseenter and mouseleave events\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tsetup: function( data ) {\n\t\t\tjQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );\n\t\t},\n\t\tteardown: function( data ) {\n\t\t\tjQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );\n\t\t}\n\t};\n});\n\n// submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( !jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\t\tif ( (type === \"text\" || type === \"password\") && jQuery( elem ).closest(\"form\").length && e.keyCode === 13 ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialSubmit\" );\n\t\t}\n\t};\n\n}\n\n// change delegation, happens here so we have bind.\nif ( !jQuery.support.changeBubbles ) {\n\n\tvar changeFilters,\n\n\tgetVal = function( elem ) {\n\t\tvar type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\",\n\t\t\tval = elem.value;\n\n\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\tval = elem.checked;\n\n\t\t} else if ( type === \"select-multiple\" ) {\n\t\t\tval = elem.selectedIndex > -1 ?\n\t\t\t\tjQuery.map( elem.options, function( elem ) {\n\t\t\t\t\treturn elem.selected;\n\t\t\t\t}).join(\"-\") :\n\t\t\t\t\"\";\n\n\t\t} else if ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\tval = elem.selectedIndex;\n\t\t}\n\n\t\treturn val;\n\t},\n\n\ttestChange = function testChange( e ) {\n\t\tvar elem = e.target, data, val;\n\n\t\tif ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdata = jQuery._data( elem, \"_change_data\" );\n\t\tval = getVal(elem);\n\n\t\t// the current data will be also retrieved by beforeactivate\n\t\tif ( e.type !== \"focusout\" || elem.type !== \"radio\" ) {\n\t\t\tjQuery._data( elem, \"_change_data\", val );\n\t\t}\n\n\t\tif ( data === undefined || val === data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data != null || val ) {\n\t\t\te.type = \"change\";\n\t\t\te.liveFired = undefined;\n\t\t\tjQuery.event.trigger( e, arguments[1], elem );\n\t\t}\n\t};\n\n\tjQuery.event.special.change = {\n\t\tfilters: {\n\t\t\tfocusout: testChange,\n\n\t\t\tbeforedeactivate: testChange,\n\n\t\t\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Change has to be called before submit\n\t\t\t// Keydown will be called before keypress, which is used in submit-event delegation\n\t\t\tkeydown: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( (e.keyCode === 13 && !jQuery.nodeName( elem, \"textarea\" ) ) ||\n\t\t\t\t\t(e.keyCode === 32 && (type === \"checkbox\" || type === \"radio\")) ||\n\t\t\t\t\ttype === \"select-multiple\" ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Beforeactivate happens also before the previous element is blurred\n\t\t\t// with this event you can't trigger a change event, but you can store\n\t\t\t// information\n\t\t\tbeforeactivate: function( e ) {\n\t\t\t\tvar elem = e.target;\n\t\t\t\tjQuery._data( elem, \"_change_data\", getVal(elem) );\n\t\t\t}\n\t\t},\n\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( this.type === \"file\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( var type in changeFilters ) {\n\t\t\t\tjQuery.event.add( this, type + \".specialChange\", changeFilters[type] );\n\t\t\t}\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialChange\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n\n\t// Handle when the input is .focus()'d\n\tchangeFilters.focus = changeFilters.beforeactivate;\n}\n\nfunction trigger( type, elem, args ) {\n\t// Piggyback on a donor event to simulate a different one.\n\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t// simulated event prevents default then we do the same on the donor.\n\t// Don't pass args or remember liveFired; they apply to the donor event.\n\tvar event = jQuery.extend( {}, args[ 0 ] );\n\tevent.type = type;\n\tevent.originalEvent = {};\n\tevent.liveFired = undefined;\n\tjQuery.event.handle.call( elem, event );\n\tif ( event.isDefaultPrevented() ) {\n\t\targs[ 0 ].preventDefault();\n\t}\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0;\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfunction handler( donor ) {\n\t\t\t// Donor event is always a native one; fix it and switch its type.\n\t\t\t// Let focusin/out handler cancel the donor focus/blur event.\n\t\t\tvar e = jQuery.event.fix( donor );\n\t\t\te.type = fix;\n\t\t\te.originalEvent = {};\n\t\t\tjQuery.event.trigger( e, null, e.target );\n\t\t\tif ( e.isDefaultPrevented() ) {\n\t\t\t\tdonor.preventDefault();\n\t\t\t}\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\n\t\tvar handler;\n\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis[ name ](key, data, type[key], fn);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( arguments.length === 2 || data === false ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tif ( name === \"one\" ) {\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t\thandler.guid = fn.guid || jQuery.guid++;\n\t\t} else {\n\t\t\thandler = fn;\n\t\t}\n\n\t\tif ( type === \"unload\" && name !== \"one\" ) {\n\t\t\tthis.one( type, data, fn );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( this[i], type, handler, data );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\njQuery.fn.extend({\n\tunbind: function( type, fn ) {\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" && !type.preventDefault ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis.unbind(key, type[key]);\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.remove( this[i], type, fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\treturn this.unbind( \"live\" );\n\n\t\t} else {\n\t\t\treturn this.die( types, null, fn, selector );\n\t\t}\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery.data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery.data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\nvar liveMap = {\n\tfocus: \"focusin\",\n\tblur: \"focusout\",\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n};\n\njQuery.each([\"live\", \"die\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {\n\t\tvar type, i = 0, match, namespaces, preType,\n\t\t\tselector = origSelector || this.selector,\n\t\t\tcontext = origSelector ? this : jQuery( this.context );\n\n\t\tif ( typeof types === \"object\" && !types.preventDefault ) {\n\t\t\tfor ( var key in types ) {\n\t\t\t\tcontext[ name ]( key, data, types[key], selector );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( name === \"die\" && !types &&\n\t\t\t\t\torigSelector && origSelector.charAt(0) === \".\" ) {\n\n\t\t\tcontext.unbind( origSelector );\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data === false || jQuery.isFunction( data ) ) {\n\t\t\tfn = data || returnFalse;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\ttypes = (types || \"\").split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) != null ) {\n\t\t\tmatch = rnamespaces.exec( type );\n\t\t\tnamespaces = \"\";\n\n\t\t\tif ( match )  {\n\t\t\t\tnamespaces = match[0];\n\t\t\t\ttype = type.replace( rnamespaces, \"\" );\n\t\t\t}\n\n\t\t\tif ( type === \"hover\" ) {\n\t\t\t\ttypes.push( \"mouseenter\" + namespaces, \"mouseleave\" + namespaces );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpreType = type;\n\n\t\t\tif ( liveMap[ type ] ) {\n\t\t\t\ttypes.push( liveMap[ type ] + namespaces );\n\t\t\t\ttype = type + namespaces;\n\n\t\t\t} else {\n\t\t\t\ttype = (liveMap[ type ] || type) + namespaces;\n\t\t\t}\n\n\t\t\tif ( name === \"live\" ) {\n\t\t\t\t// bind live handler\n\t\t\t\tfor ( var j = 0, l = context.length; j < l; j++ ) {\n\t\t\t\t\tjQuery.event.add( context[j], \"live.\" + liveConvert( type, selector ),\n\t\t\t\t\t\t{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// unbind live handler\n\t\t\t\tcontext.unbind( \"live.\" + liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\nfunction liveHandler( event ) {\n\tvar stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,\n\t\telems = [],\n\t\tselectors = [],\n\t\tevents = jQuery._data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)\n\tif ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === \"click\" ) {\n\t\treturn;\n\t}\n\n\tif ( event.namespace ) {\n\t\tnamespace = new RegExp(\"(^|\\\\.)\" + event.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t}\n\n\tevent.liveFired = this;\n\n\tvar live = events.live.slice(0);\n\n\tfor ( j = 0; j < live.length; j++ ) {\n\t\thandleObj = live[j];\n\n\t\tif ( handleObj.origType.replace( rnamespaces, \"\" ) === event.type ) {\n\t\t\tselectors.push( handleObj.selector );\n\n\t\t} else {\n\t\t\tlive.splice( j--, 1 );\n\t\t}\n\t}\n\n\tmatch = jQuery( event.target ).closest( selectors, event.currentTarget );\n\n\tfor ( i = 0, l = match.length; i < l; i++ ) {\n\t\tclose = match[i];\n\n\t\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {\n\t\t\t\telem = close.elem;\n\t\t\t\trelated = null;\n\n\t\t\t\t// Those two events require additional checking\n\t\t\t\tif ( handleObj.preType === \"mouseenter\" || handleObj.preType === \"mouseleave\" ) {\n\t\t\t\t\tevent.type = handleObj.preType;\n\t\t\t\t\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\n\n\t\t\t\t\t// Make sure not to accidentally match a child element with the same selector\n\t\t\t\t\tif ( related && jQuery.contains( elem, related ) ) {\n\t\t\t\t\t\trelated = elem;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !related || related !== elem ) {\n\t\t\t\t\telems.push({ elem: elem, handleObj: handleObj, level: close.level });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( i = 0, l = elems.length; i < l; i++ ) {\n\t\tmatch = elems[i];\n\n\t\tif ( maxLevel && match.level > maxLevel ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tret = match.handleObj.origHandler.apply( match.elem, arguments );\n\n\t\tif ( ret === false || event.isPropagationStopped() ) {\n\t\t\tmaxLevel = match.level;\n\n\t\t\tif ( ret === false ) {\n\t\t\t\tstop = false;\n\t\t\t}\n\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(rperiod, \"`\").replace(rspaces, \"&\");\n}\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.bind( name, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( var i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tvar pass = not ^ !!found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar type = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tvar first = match[2],\n\t\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent.sizcache = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar diff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Expr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Utility function for retreiving the text value of an array of DOM nodes\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( typeof selector === \"string\" ?\n\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar match, selector,\n\t\t\t\tmatches = {},\n\t\t\t\tlevel = 1;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( i = 0, l = selectors.length; i < l; i++ ) {\n\t\t\t\t\tselector = selectors[i];\n\n\t\t\t\t\tif ( !matches[ selector ] ) {\n\t\t\t\t\t\tmatches[ selector ] = POS.test( selector ) ?\n\t\t\t\t\t\t\tjQuery( selector, context || this.context ) :\n\t\t\t\t\t\t\tselector;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\t\tfor ( selector in matches ) {\n\t\t\t\t\t\tmatch = matches[ selector ];\n\n\t\t\t\t\t\tif ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {\n\t\t\t\t\t\t\tret.push({ selector: selector, elem: cur, level: level });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tlevel++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until ),\n\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, args.join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn (elem === qualifier) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn (jQuery.inArray( elem, qualifier ) >= 0) === keep;\n\t});\n}\n\n\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery(arguments[0]);\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery(arguments[0]).toArray() );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnocache.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || (l > 1 && i < lastIndex) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar internalKey = jQuery.expando,\n\t\toldData = jQuery.data( src ),\n\t\tcurData = jQuery.data( dest, oldData );\n\n\t// Switch to use the internal data object, if it exists, for the next\n\t// stage of data copying\n\tif ( (oldData = oldData[ internalKey ]) ) {\n\t\tvar events = oldData.events;\n\t\t\t\tcurData = curData[ internalKey ] = jQuery.extend({}, oldData);\n\n\t\tif ( events ) {\n\t\t\tdelete curData.handle;\n\t\t\tcurData.events = {};\n\n\t\t\tfor ( var type in events ) {\n\t\t\t\tfor ( var i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc;\n\n  // nodes may contain either an explicit document object,\n  // a jQuery collection or context object.\n  // If nodes[0] contains a valid object to assign to doc\n  if ( nodes && nodes[0] ) {\n    doc = nodes[0].ownerDocument || nodes[0];\n  }\n\n  // Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\tif ( args.length === 1 && typeof args[0] === \"string\" && args[0].length < 512 && doc === document &&\n\t\targs[0].charAt(0) === \"<\" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ args[0] ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = (i > 0 ? this.clone(true) : this).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( \"getElementsByTagName\" in elem ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( \"querySelectorAll\" in elem ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\tfixDefaultChecked( elem );\n\t} else if ( \"getElementsByTagName\" in elem ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName\n\t\t\t// instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = (rtagName.exec( elem ) || [\"\", \"\"])[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ] && cache[ id ][ internalKey ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWH( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat( value );\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNaN( value ) ? \"\" : \"alpha(opacity=\" + value * 100 + \")\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( !(defaultView = elem.ownerDocument.defaultView) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : (ret || 0);\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tjQuery.each( which, function() {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ] || 0;\n\t}\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tjQuery.each( which, function() {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn val + \"px\";\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\t\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor(; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor(; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery._Deferred(),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.done;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.error( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor( key in s.converters ) {\n\t\t\t\tif( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css( elem, \"display\" ) === \"none\" ) {\n\t\t\t\t\t\tjQuery._data(elem, \"olddisplay\", defaultDisplay(elem.nodeName));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data(elem, \"olddisplay\") || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tvar display = jQuery.css( this[i], \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( this[i], \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( this[i], \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed(speed, easing, callback);\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p,\n\t\t\t\tdisplay, e,\n\t\t\t\tparts, start, end, unit;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height\n\t\t\t\t\t// animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = defaultDisplay( this.nodeName );\n\n\t\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\t\tif ( display === \"inline\" ) {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline\";\n\t\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test(val) ) {\n\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]();\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ((end || 1) / e.cur()) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t});\n\t},\n\n\tstop: function( clearQueue, gotoEnd ) {\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar timers = jQuery.timers,\n\t\t\t\ti = timers.length;\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( timers[i].elem === this ) {\n\t\t\t\t\tif (gotoEnd) {\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[i](true);\n\t\t\t\t\t}\n\n\t\t\t\t\ttimers.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// start the next in the queue if the last step wasn't forced\n\t\tif ( !gotoEnd ) {\n\t\t\tthis.dequeue();\n\t\t}\n\n\t\treturn this;\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\", 1),\n\tslideUp: genFx(\"hide\", 1),\n\tslideToggle: genFx(\"toggle\", 1),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend({}, speed) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction(easing) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery.dequeue( this );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step(gotoEnd);\n\t\t}\n\n\t\tt.elem = this.elem;\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any\n\t\t// flash of content\n\t\tthis.custom(this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur());\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom(this.cur(), 0);\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar t = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options,\n\t\t\ti, n;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( i in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[i] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function (index, value) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[index];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery(elem).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( var p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[p] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\toptions.complete.call( elem );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ((this.end - this.start) * this.pos);\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tfor ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {\n\t\t\tif ( !timers[i]() ) {\n\t\t\t\ttimers.splice(i--, 1);\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = (fx.prop === \"width\" || fx.prop === \"height\" ? Math.max(0, fx.now) : fx.now) + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( document.compatMode === \"CSS1Compat\" ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tjQuery.offset.initialize();\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\tinitialize: function() {\n\t\tvar body = document.body, container = document.createElement(\"div\"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, \"marginTop\") ) || 0,\n\t\t\thtml = \"<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>\";\n\n\t\tjQuery.extend( container.style, { position: \"absolute\", top: 0, left: 0, margin: 0, border: 0, width: \"1px\", height: \"1px\", visibility: \"hidden\" } );\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\tinnerDiv = container.firstChild;\n\t\tcheckDiv = innerDiv.firstChild;\n\t\ttd = innerDiv.nextSibling.firstChild.firstChild;\n\n\t\tthis.doesNotAddBorder = (checkDiv.offsetTop !== 5);\n\t\tthis.doesAddBorderForTableAndCells = (td.offsetTop === 5);\n\n\t\tcheckDiv.style.position = \"fixed\";\n\t\tcheckDiv.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\tthis.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);\n\t\tcheckDiv.style.position = checkDiv.style.top = \"\";\n\n\t\tinnerDiv.style.overflow = \"hidden\";\n\t\tinnerDiv.style.position = \"relative\";\n\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = (position === \"absolute\" || position === \"fixed\") && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif (options.top != null) {\n\t\t\tprops.top = (options.top - curOffset.top) + curTop;\n\t\t}\n\t\tif (options.left != null) {\n\t\t\tprops.left = (options.left - curOffset.left) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem && elem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem && elem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ],\n\t\t\t\tbody = elem.document.body;\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\tbody && body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNaN( ret ) ? orig : ret;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.6.4.js",
    "content": "/*!\n * jQuery JavaScript Library v1.6.4\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Mon Sep 12 18:54:48 2011 -0400\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Check for digits\n\trdigit = /\\d/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = (context ? context.ownerDocument || context : document);\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn (context || rootjQuery).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif (selector.selector !== undefined) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.6.4\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + (this.selector ? \" \" : \"\") + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, +i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).unbind( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery._Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNaN: function( obj ) {\n\t\treturn obj == null || !rdigit.test( obj ) || isNaN( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn (new Function( \"return \" + data ))();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array ) {\n\t\tif ( !array ) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif ( indexOf ) {\n\t\t\treturn indexOf.call( array, elem );\n\t\t}\n\n\t\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\t\tif ( array[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn (new Date()).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\nvar // Promise methods\n\tpromiseMethods = \"done fail isResolved isRejected promise then always pipe\".split( \" \" ),\n\t// Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\t// Create a simple deferred (one callbacks list)\n\t_Deferred: function() {\n\t\tvar // callbacks list\n\t\t\tcallbacks = [],\n\t\t\t// stored [ context , args ]\n\t\t\tfired,\n\t\t\t// to avoid firing when already doing so\n\t\t\tfiring,\n\t\t\t// flag to know if the deferred has been cancelled\n\t\t\tcancelled,\n\t\t\t// the deferred itself\n\t\t\tdeferred  = {\n\n\t\t\t\t// done( f1, f2, ...)\n\t\t\t\tdone: function() {\n\t\t\t\t\tif ( !cancelled ) {\n\t\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t_fired;\n\t\t\t\t\t\tif ( fired ) {\n\t\t\t\t\t\t\t_fired = fired;\n\t\t\t\t\t\t\tfired = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\t\t\t\telem = args[ i ];\n\t\t\t\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t\t\t\tdeferred.done.apply( deferred, elem );\n\t\t\t\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tcallbacks.push( elem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( _fired ) {\n\t\t\t\t\t\t\tdeferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with given context and args\n\t\t\t\tresolveWith: function( context, args ) {\n\t\t\t\t\tif ( !cancelled && !fired && !firing ) {\n\t\t\t\t\t\t// make sure args are available (#8421)\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\tfiring = 1;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twhile( callbacks[ 0 ] ) {\n\t\t\t\t\t\t\t\tcallbacks.shift().apply( context, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally {\n\t\t\t\t\t\t\tfired = [ context, args ];\n\t\t\t\t\t\t\tfiring = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with this as context and given arguments\n\t\t\t\tresolve: function() {\n\t\t\t\t\tdeferred.resolveWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Has this deferred been resolved?\n\t\t\t\tisResolved: function() {\n\t\t\t\t\treturn !!( firing || fired );\n\t\t\t\t},\n\n\t\t\t\t// Cancel\n\t\t\t\tcancel: function() {\n\t\t\t\t\tcancelled = 1;\n\t\t\t\t\tcallbacks = [];\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn deferred;\n\t},\n\n\t// Full fledged deferred (two callbacks list)\n\tDeferred: function( func ) {\n\t\tvar deferred = jQuery._Deferred(),\n\t\t\tfailDeferred = jQuery._Deferred(),\n\t\t\tpromise;\n\t\t// Add errorDeferred methods, then and promise\n\t\tjQuery.extend( deferred, {\n\t\t\tthen: function( doneCallbacks, failCallbacks ) {\n\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\talways: function() {\n\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );\n\t\t\t},\n\t\t\tfail: failDeferred.done,\n\t\t\trejectWith: failDeferred.resolveWith,\n\t\t\treject: failDeferred.resolve,\n\t\t\tisRejected: failDeferred.isResolved,\n\t\t\tpipe: function( fnDone, fnFail ) {\n\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\tfail: [ fnFail, \"reject\" ]\n\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).promise();\n\t\t\t},\n\t\t\t// Get a promise for this deferred\n\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\tpromise: function( obj ) {\n\t\t\t\tif ( obj == null ) {\n\t\t\t\t\tif ( promise ) {\n\t\t\t\t\t\treturn promise;\n\t\t\t\t\t}\n\t\t\t\t\tpromise = obj = {};\n\t\t\t\t}\n\t\t\t\tvar i = promiseMethods.length;\n\t\t\t\twhile( i-- ) {\n\t\t\t\t\tobj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t});\n\t\t// Make sure only one callback list will be used\n\t\tdeferred.done( failDeferred.cancel ).fail( deferred.cancel );\n\t\t// Unexpose cancel\n\t\tdelete deferred.cancel;\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = arguments,\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tcount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t// Strange bug in FF4:\n\t\t\t\t\t// Values changed onto the arguments object sometimes end up as undefined values\n\t\t\t\t\t// outside the $.when method. Cloning the object into a fresh array solves the issue\n\t\t\t\t\tdeferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn deferred.promise();\n\t}\n});\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\ttestElementParent,\n\t\ttestElement,\n\t\ttestElementStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName( \"tbody\" ).length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName( \"link\" ).length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute( \"href\" ) === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55$/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains it's value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t// We use our own, invisible, body unless the body is already present\n\t// in which case we use a div (#9239)\n\ttestElement = document.createElement( body ? \"div\" : \"body\" );\n\ttestElementStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\tbackground: \"none\"\n\t};\n\tif ( body ) {\n\t\tjQuery.extend( testElementStyle, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: \"-1000px\",\n\t\t\ttop: \"-1000px\"\n\t\t});\n\t}\n\tfor ( i in testElementStyle ) {\n\t\ttestElement.style[ i ] = testElementStyle[ i ];\n\t}\n\ttestElement.appendChild( div );\n\ttestElementParent = body || documentElement;\n\ttestElementParent.insertBefore( testElement, testElementParent.firstChild );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Remove the body element we added\n\ttestElement.innerHTML = \"\";\n\ttestElementParent.removeChild( testElement );\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t} ) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\t// Null connected elements to avoid leaks in IE\n\ttestElement = fragment = select = opt = body = marginDiv = div = input = null;\n\n\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);\n\t\t\t} else {\n\t\t\t\tcache[ id ] = jQuery.extend(cache[ id ], name);\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Internal jQuery data is stored in a separate object inside the object's data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data\n\t\tif ( pvt ) {\n\t\t\tif ( !thisCache[ internalKey ] ) {\n\t\t\t\tthisCache[ internalKey ] = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache[ internalKey ];\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should\n\t\t// not attempt to inspect the internal events object using jQuery.data, as this\n\t\t// internal data object is undocumented and subject to change.\n\t\tif ( name === \"events\" && !thisCache[name] ) {\n\t\t\treturn thisCache[ internalKey ] && thisCache[ internalKey ].events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support interoperable removal of hyphenated or camelcased keys\n\t\t\t\tif ( !thisCache[ name ] ) {\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t}\n\n\t\t\t\tdelete thisCache[ name ];\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !isEmptyDataObject(thisCache) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( pvt ) {\n\t\t\tdelete cache[ id ][ internalKey ];\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar internalCache = cache[ id ][ internalKey ];\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the entire user cache at once because it's faster than\n\t\t// iterating through each key, but we need to continue to persist internal\n\t\t// data if it existed\n\t\tif ( internalCache ) {\n\t\t\tcache[ id ] = {};\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\n\t\t\tcache[ id ][ internalKey ] = internalCache;\n\n\t\t// Otherwise, we need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\t} else if ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar data = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 ) {\n\t\t\t    var attr = this[0].attributes, name;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tvar parts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t!jQuery.isNaN( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON\n// property to be considered empty objects; this property always exists in\n// order to make sure JSON.stringify does not expose internal metadata\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery.data( elem, deferDataKey, undefined, true );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&\n\t\t( src === \"mark\" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery.data( elem, queueDataKey, undefined, true ) &&\n\t\t\t\t!jQuery.data( elem, markDataKey, undefined, true ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.resolve();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"mark\";\n\t\t\tjQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery.data( elem, key, count, true );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"queue\";\n\t\t\tvar q = jQuery.data( elem, type, undefined, true );\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery.data( elem, type, jQuery.makeArray(data), true );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\tdefer;\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift(\"inprogress\");\n\t\t\t}\n\n\t\t\tfn.call(elem, function() {\n\t\t\t\tjQuery.dequeue(elem, type);\n\t\t\t});\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[time] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function() {\n\t\t\tvar elem = this;\n\t\t\tsetTimeout(function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, time );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.done( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tnodeHook, boolHook;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\t\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\t\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \";\n\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret,\n\t\t\telem = this[0];\n\t\t\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ? \n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") : \n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar isFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\tvar option = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\t\n\tattrFix: {\n\t\t// Always normalize to ensure hook usage\n\t\ttabindex: \"tabIndex\"\n\t},\n\t\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = elem.nodeType;\n\t\t\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( !(\"getAttribute\" in elem) ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// Normalize the name if needed\n\t\tif ( notxml ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\n\t\t\thooks = jQuery.attrHooks[ name ];\n\n\t\t\tif ( !hooks ) {\n\t\t\t\t// Use boolHook for boolean attributes\n\t\t\t\tif ( rboolean.test( name ) ) {\n\t\t\t\t\thooks = boolHook;\n\n\t\t\t\t// Use nodeHook if available( IE6/7 )\n\t\t\t\t} else if ( nodeHook ) {\n\t\t\t\t\thooks = nodeHook;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn undefined;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, name ) {\n\t\tvar propName;\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\n\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\telem.removeAttribute( name );\n\n\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\tif ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {\n\t\t\t\telem[ propName ] = false;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\t\n\tprop: function( elem, name, value ) {\n\t\tvar nType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn (elem[ name ] = value);\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\t\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabindex propHook to attrHooks for back-compat\njQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode;\n\t\treturn jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !jQuery.support.getSetAttribute ) {\n\t\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\t// Return undefined if nodeValue is empty string\n\t\t\treturn ret && ret.nodeValue !== \"\" ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn (ret.nodeValue = value + \"\");\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn (elem.style.cssText = \"\" + value);\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(rescape, \"\\\\$&\");\n\t};\n\n/*\n * A number of helper functions used for managing events.\n * Many of the ideas behind this code originated from\n * Dean Edwards' addEvent library.\n */\njQuery.event = {\n\n\t// Bind an event to an element\n\t// Original by Dean Edwards\n\tadd: function( elem, types, handler, data ) {\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t} else if ( !handler ) {\n\t\t\t// Fixes bug #7229. Fix recommended by jdalton\n\t\t\treturn;\n\t\t}\n\n\t\tvar handleObjIn, handleObj;\n\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the function being executed has a unique ID\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure\n\t\tvar elemData = jQuery._data( elem );\n\n\t\t// If no elemData is found then we must be trying to bind to one of the\n\t\t// banned noData elements\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar events = elemData.events,\n\t\t\teventHandle = elemData.handle;\n\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t}\n\n\t\t// Add elem as a property of the handle function\n\t\t// This is to prevent a memory leak with non-native events in IE.\n\t\teventHandle.elem = elem;\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\tvar type, i = 0, namespaces;\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\thandleObj = handleObjIn ?\n\t\t\t\tjQuery.extend({}, handleObjIn) :\n\t\t\t\t{ handler: handler, data: data };\n\n\t\t\t// Namespaced event handlers\n\t\t\tif ( type.indexOf(\".\") > -1 ) {\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\thandleObj.namespace = namespaces.slice(0).sort().join(\".\");\n\n\t\t\t} else {\n\t\t\t\tnamespaces = [];\n\t\t\t\thandleObj.namespace = \"\";\n\t\t\t}\n\n\t\t\thandleObj.type = type;\n\t\t\tif ( !handleObj.guid ) {\n\t\t\t\thandleObj.guid = handler.guid;\n\t\t\t}\n\n\t\t\t// Get the current list of functions bound to this event\n\t\t\tvar handlers = events[ type ],\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// Init the event handler queue\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\n\t\t\t\t// Check for a special event handler\n\t\t\t\t// Only use addEventListener/attachEvent if the special\n\t\t\t\t// events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the function to the element's handler list\n\t\t\thandlers.push( handleObj );\n\n\t\t\t// Keep track of which events have been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, pos ) {\n\t\t// don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t}\n\n\t\tvar ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tevents = elemData && elemData.events;\n\n\t\tif ( !elemData || !events ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// types is actually an event object here\n\t\tif ( types && types.type ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t}\n\n\t\t// Unbind all events for the element\n\t\tif ( !types || typeof types === \"string\" && types.charAt(0) === \".\" ) {\n\t\t\ttypes = types || \"\";\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tjQuery.event.remove( elem, type + types );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).unbind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\torigType = type;\n\t\t\thandleObj = null;\n\t\t\tall = type.indexOf(\".\") < 0;\n\t\t\tnamespaces = [];\n\n\t\t\tif ( !all ) {\n\t\t\t\t// Namespaced event handlers\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\n\t\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" +\n\t\t\t\t\tjQuery.map( namespaces.slice(0).sort(), fcleanup ).join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\t}\n\n\t\t\teventType = events[ type ];\n\n\t\t\tif ( !eventType ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( !handler ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, origType, handleObj.handler, j );\n\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tfor ( j = pos || 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( handler.guid === handleObj.guid ) {\n\t\t\t\t\t// remove the given handler for the given type\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tif ( pos == null ) {\n\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( pos != null ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove generic event handler if no more handlers exist\n\t\t\tif ( eventType.length === 0 || pos != null && eventType.length === 1 ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tret = null;\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tvar handle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\tdelete elemData.events;\n\t\t\tdelete elemData.handle;\n\n\t\t\tif ( jQuery.isEmptyObject( elemData ) ) {\n\t\t\t\tjQuery.removeData( elem, undefined, true );\n\t\t\t}\n\t\t}\n\t},\n\t\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\texclusive;\n\n\t\tif ( type.indexOf(\"!\") >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t// internalKey variable is just used to make it easier to find\n\t\t\t\t// and potentially change this stuff later; currently it just\n\t\t\t\t// points to jQuery.expando\n\t\t\t\tvar internalKey = jQuery.expando,\n\t\t\t\t\tinternalCache = this[ internalKey ];\n\t\t\t\tif ( internalCache && internalCache.events && internalCache.events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, internalCache.handle.elem );\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tevent.target = elem;\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\tvar cur = elem,\n\t\t\t// IE doesn't like method names with a colon (#3533, #8272)\n\t\t\tontype = type.indexOf(\":\") < 0 ? \"on\" + type : \"\";\n\n\t\t// Fire event on the current element, then bubble up the DOM tree\n\t\tdo {\n\t\t\tvar handle = jQuery._data( cur, \"handle\" );\n\n\t\t\tevent.currentTarget = cur;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Trigger an inline bound script\n\t\t\tif ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {\n\t\t\t\tevent.result = false;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\t// Bubble up to document, then to window\n\t\t\tcur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;\n\t\t} while ( cur && !event.isPropagationStopped() );\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tvar old,\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction)() check here because IE6/7 fails that test.\n\t\t\t\t// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.\n\t\t\t\ttry {\n\t\t\t\t\tif ( ontype && elem[ type ] ) {\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t}\n\t\t\t\t} catch ( ieError ) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = undefined;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn event.result;\n\t},\n\n\thandle: function( event ) {\n\t\tevent = jQuery.event.fix( event || window.event );\n\t\t// Snapshot the handlers list since a called handler may add/remove events.\n\t\tvar handlers = ((jQuery._data( this, \"events\" ) || {})[ event.type ] || []).slice(0),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\targs = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// Use the fix-ed Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.currentTarget = this;\n\n\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t// Triggered event must 1) be non-exclusive and have no namespace, or\n\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event.\n\t\t\tif ( run_all || event.namespace_re.test( handleObj.namespace ) ) {\n\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t// So that we can later remove it\n\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\tevent.data = handleObj.data;\n\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\tvar ret = handleObj.handler.apply( this, args );\n\n\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\tevent.result = ret;\n\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn event.result;\n\t},\n\n\tprops: \"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// store a copy of the original event object\n\t\t// and \"clone\" to set read-only properties\n\t\tvar originalEvent = event;\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( var i = this.props.length, prop; i; ) {\n\t\t\tprop = this.props[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary\n\t\tif ( !event.target ) {\n\t\t\t// Fixes #1925 where srcElement might not be defined either\n\t\t\tevent.target = event.srcElement || document;\n\t\t}\n\n\t\t// check if target is a textnode (safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Add relatedTarget, if necessary\n\t\tif ( !event.relatedTarget && event.fromElement ) {\n\t\t\tevent.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n\t\t}\n\n\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\tif ( event.pageX == null && event.clientX != null ) {\n\t\t\tvar eventDocument = event.target.ownerDocument || document,\n\t\t\t\tdoc = eventDocument.documentElement,\n\t\t\t\tbody = eventDocument.body;\n\n\t\t\tevent.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n\t\t\tevent.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && (event.charCode != null || event.keyCode != null) ) {\n\t\t\tevent.which = event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)\n\t\tif ( !event.metaKey && event.ctrlKey ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t// Note: button is not normalized, so don't use it\n\t\tif ( !event.which && event.button !== undefined ) {\n\t\t\tevent.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// Deprecated, use jQuery.guid instead\n\tguid: 1E8,\n\n\t// Deprecated, use jQuery.proxy instead\n\tproxy: jQuery.proxy,\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady,\n\t\t\tteardown: jQuery.noop\n\t\t},\n\n\t\tlive: {\n\t\t\tadd: function( handleObj ) {\n\t\t\t\tjQuery.event.add( this,\n\t\t\t\t\tliveConvert( handleObj.origType, handleObj.selector ),\n\t\t\t\t\tjQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );\n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tjQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !this.preventDefault ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// timeStamp is buggy for some events on Firefox(#3843)\n\t// So we won't rely on the native value\n\tthis.timeStamp = jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Checks if an event happened on an element within another element\n// Used in jQuery.event.special.mouseenter and mouseleave handlers\nvar withinElement = function( event ) {\n\n\t// Check if mouse(over|out) are still within the same parent element\n\tvar related = event.relatedTarget,\n\t\tinside = false,\n\t\teventType = event.type;\n\n\tevent.type = event.data;\n\n\tif ( related !== this ) {\n\n\t\tif ( related ) {\n\t\t\tinside = jQuery.contains( this, related );\n\t\t}\n\n\t\tif ( !inside ) {\n\n\t\t\tjQuery.event.handle.apply( this, arguments );\n\n\t\t\tevent.type = eventType;\n\t\t}\n\t}\n},\n\n// In case of event delegation, we only need to rename the event.type,\n// liveHandler will take care of the rest.\ndelegate = function( event ) {\n\tevent.type = event.data;\n\tjQuery.event.handle.apply( this, arguments );\n};\n\n// Create mouseenter and mouseleave events\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tsetup: function( data ) {\n\t\t\tjQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );\n\t\t},\n\t\tteardown: function( data ) {\n\t\t\tjQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );\n\t\t}\n\t};\n});\n\n// submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( !jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\t// Avoid triggering error on non-existent type attribute in IE VML (#7071)\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.type : \"\";\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.type : \"\";\n\n\t\t\t\t\tif ( (type === \"text\" || type === \"password\") && jQuery( elem ).closest(\"form\").length && e.keyCode === 13 ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialSubmit\" );\n\t\t}\n\t};\n\n}\n\n// change delegation, happens here so we have bind.\nif ( !jQuery.support.changeBubbles ) {\n\n\tvar changeFilters,\n\n\tgetVal = function( elem ) {\n\t\tvar type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\",\n\t\t\tval = elem.value;\n\n\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\tval = elem.checked;\n\n\t\t} else if ( type === \"select-multiple\" ) {\n\t\t\tval = elem.selectedIndex > -1 ?\n\t\t\t\tjQuery.map( elem.options, function( elem ) {\n\t\t\t\t\treturn elem.selected;\n\t\t\t\t}).join(\"-\") :\n\t\t\t\t\"\";\n\n\t\t} else if ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\tval = elem.selectedIndex;\n\t\t}\n\n\t\treturn val;\n\t},\n\n\ttestChange = function testChange( e ) {\n\t\tvar elem = e.target, data, val;\n\n\t\tif ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdata = jQuery._data( elem, \"_change_data\" );\n\t\tval = getVal(elem);\n\n\t\t// the current data will be also retrieved by beforeactivate\n\t\tif ( e.type !== \"focusout\" || elem.type !== \"radio\" ) {\n\t\t\tjQuery._data( elem, \"_change_data\", val );\n\t\t}\n\n\t\tif ( data === undefined || val === data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data != null || val ) {\n\t\t\te.type = \"change\";\n\t\t\te.liveFired = undefined;\n\t\t\tjQuery.event.trigger( e, arguments[1], elem );\n\t\t}\n\t};\n\n\tjQuery.event.special.change = {\n\t\tfilters: {\n\t\t\tfocusout: testChange,\n\n\t\t\tbeforedeactivate: testChange,\n\n\t\t\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Change has to be called before submit\n\t\t\t// Keydown will be called before keypress, which is used in submit-event delegation\n\t\t\tkeydown: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( (e.keyCode === 13 && !jQuery.nodeName( elem, \"textarea\" ) ) ||\n\t\t\t\t\t(e.keyCode === 32 && (type === \"checkbox\" || type === \"radio\")) ||\n\t\t\t\t\ttype === \"select-multiple\" ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Beforeactivate happens also before the previous element is blurred\n\t\t\t// with this event you can't trigger a change event, but you can store\n\t\t\t// information\n\t\t\tbeforeactivate: function( e ) {\n\t\t\t\tvar elem = e.target;\n\t\t\t\tjQuery._data( elem, \"_change_data\", getVal(elem) );\n\t\t\t}\n\t\t},\n\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( this.type === \"file\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( var type in changeFilters ) {\n\t\t\t\tjQuery.event.add( this, type + \".specialChange\", changeFilters[type] );\n\t\t\t}\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialChange\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n\n\t// Handle when the input is .focus()'d\n\tchangeFilters.focus = changeFilters.beforeactivate;\n}\n\nfunction trigger( type, elem, args ) {\n\t// Piggyback on a donor event to simulate a different one.\n\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t// simulated event prevents default then we do the same on the donor.\n\t// Don't pass args or remember liveFired; they apply to the donor event.\n\tvar event = jQuery.extend( {}, args[ 0 ] );\n\tevent.type = type;\n\tevent.originalEvent = {};\n\tevent.liveFired = undefined;\n\tjQuery.event.handle.call( elem, event );\n\tif ( event.isDefaultPrevented() ) {\n\t\targs[ 0 ].preventDefault();\n\t}\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0;\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfunction handler( donor ) {\n\t\t\t// Donor event is always a native one; fix it and switch its type.\n\t\t\t// Let focusin/out handler cancel the donor focus/blur event.\n\t\t\tvar e = jQuery.event.fix( donor );\n\t\t\te.type = fix;\n\t\t\te.originalEvent = {};\n\t\t\tjQuery.event.trigger( e, null, e.target );\n\t\t\tif ( e.isDefaultPrevented() ) {\n\t\t\t\tdonor.preventDefault();\n\t\t\t}\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\n\t\tvar handler;\n\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis[ name ](key, data, type[key], fn);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( arguments.length === 2 || data === false ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tif ( name === \"one\" ) {\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t\thandler.guid = fn.guid || jQuery.guid++;\n\t\t} else {\n\t\t\thandler = fn;\n\t\t}\n\n\t\tif ( type === \"unload\" && name !== \"one\" ) {\n\t\t\tthis.one( type, data, fn );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( this[i], type, handler, data );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\njQuery.fn.extend({\n\tunbind: function( type, fn ) {\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" && !type.preventDefault ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis.unbind(key, type[key]);\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.remove( this[i], type, fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\treturn this.unbind( \"live\" );\n\n\t\t} else {\n\t\t\treturn this.die( types, null, fn, selector );\n\t\t}\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery.data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery.data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\nvar liveMap = {\n\tfocus: \"focusin\",\n\tblur: \"focusout\",\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n};\n\njQuery.each([\"live\", \"die\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {\n\t\tvar type, i = 0, match, namespaces, preType,\n\t\t\tselector = origSelector || this.selector,\n\t\t\tcontext = origSelector ? this : jQuery( this.context );\n\n\t\tif ( typeof types === \"object\" && !types.preventDefault ) {\n\t\t\tfor ( var key in types ) {\n\t\t\t\tcontext[ name ]( key, data, types[key], selector );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( name === \"die\" && !types &&\n\t\t\t\t\torigSelector && origSelector.charAt(0) === \".\" ) {\n\n\t\t\tcontext.unbind( origSelector );\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data === false || jQuery.isFunction( data ) ) {\n\t\t\tfn = data || returnFalse;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\ttypes = (types || \"\").split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) != null ) {\n\t\t\tmatch = rnamespaces.exec( type );\n\t\t\tnamespaces = \"\";\n\n\t\t\tif ( match )  {\n\t\t\t\tnamespaces = match[0];\n\t\t\t\ttype = type.replace( rnamespaces, \"\" );\n\t\t\t}\n\n\t\t\tif ( type === \"hover\" ) {\n\t\t\t\ttypes.push( \"mouseenter\" + namespaces, \"mouseleave\" + namespaces );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpreType = type;\n\n\t\t\tif ( liveMap[ type ] ) {\n\t\t\t\ttypes.push( liveMap[ type ] + namespaces );\n\t\t\t\ttype = type + namespaces;\n\n\t\t\t} else {\n\t\t\t\ttype = (liveMap[ type ] || type) + namespaces;\n\t\t\t}\n\n\t\t\tif ( name === \"live\" ) {\n\t\t\t\t// bind live handler\n\t\t\t\tfor ( var j = 0, l = context.length; j < l; j++ ) {\n\t\t\t\t\tjQuery.event.add( context[j], \"live.\" + liveConvert( type, selector ),\n\t\t\t\t\t\t{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// unbind live handler\n\t\t\t\tcontext.unbind( \"live.\" + liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\nfunction liveHandler( event ) {\n\tvar stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,\n\t\telems = [],\n\t\tselectors = [],\n\t\tevents = jQuery._data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)\n\tif ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === \"click\" ) {\n\t\treturn;\n\t}\n\n\tif ( event.namespace ) {\n\t\tnamespace = new RegExp(\"(^|\\\\.)\" + event.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t}\n\n\tevent.liveFired = this;\n\n\tvar live = events.live.slice(0);\n\n\tfor ( j = 0; j < live.length; j++ ) {\n\t\thandleObj = live[j];\n\n\t\tif ( handleObj.origType.replace( rnamespaces, \"\" ) === event.type ) {\n\t\t\tselectors.push( handleObj.selector );\n\n\t\t} else {\n\t\t\tlive.splice( j--, 1 );\n\t\t}\n\t}\n\n\tmatch = jQuery( event.target ).closest( selectors, event.currentTarget );\n\n\tfor ( i = 0, l = match.length; i < l; i++ ) {\n\t\tclose = match[i];\n\n\t\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {\n\t\t\t\telem = close.elem;\n\t\t\t\trelated = null;\n\n\t\t\t\t// Those two events require additional checking\n\t\t\t\tif ( handleObj.preType === \"mouseenter\" || handleObj.preType === \"mouseleave\" ) {\n\t\t\t\t\tevent.type = handleObj.preType;\n\t\t\t\t\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\n\n\t\t\t\t\t// Make sure not to accidentally match a child element with the same selector\n\t\t\t\t\tif ( related && jQuery.contains( elem, related ) ) {\n\t\t\t\t\t\trelated = elem;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !related || related !== elem ) {\n\t\t\t\t\telems.push({ elem: elem, handleObj: handleObj, level: close.level });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( i = 0, l = elems.length; i < l; i++ ) {\n\t\tmatch = elems[i];\n\n\t\tif ( maxLevel && match.level > maxLevel ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tret = match.handleObj.origHandler.apply( match.elem, arguments );\n\n\t\tif ( ret === false || event.isPropagationStopped() ) {\n\t\t\tmaxLevel = match.level;\n\n\t\t\tif ( ret === false ) {\n\t\t\t\tstop = false;\n\t\t\t}\n\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(rperiod, \"`\").replace(rspaces, \"&\");\n}\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.bind( name, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( var i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tvar pass = not ^ !!found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar type = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tvar first = match[2],\n\t\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent.sizcache = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar diff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Expr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Utility function for retreiving the text value of an array of DOM nodes\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( typeof selector === \"string\" ?\n\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar match, selector,\n\t\t\t\tmatches = {},\n\t\t\t\tlevel = 1;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( i = 0, l = selectors.length; i < l; i++ ) {\n\t\t\t\t\tselector = selectors[i];\n\n\t\t\t\t\tif ( !matches[ selector ] ) {\n\t\t\t\t\t\tmatches[ selector ] = POS.test( selector ) ?\n\t\t\t\t\t\t\tjQuery( selector, context || this.context ) :\n\t\t\t\t\t\t\tselector;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\t\tfor ( selector in matches ) {\n\t\t\t\t\t\tmatch = matches[ selector ];\n\n\t\t\t\t\t\tif ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {\n\t\t\t\t\t\t\tret.push({ selector: selector, elem: cur, level: level });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tlevel++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until ),\n\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, args.join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn (elem === qualifier) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn (jQuery.inArray( elem, qualifier ) >= 0) === keep;\n\t});\n}\n\n\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery(arguments[0]);\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery(arguments[0]).toArray() );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnocache.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || (l > 1 && i < lastIndex) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar internalKey = jQuery.expando,\n\t\toldData = jQuery.data( src ),\n\t\tcurData = jQuery.data( dest, oldData );\n\n\t// Switch to use the internal data object, if it exists, for the next\n\t// stage of data copying\n\tif ( (oldData = oldData[ internalKey ]) ) {\n\t\tvar events = oldData.events;\n\t\t\t\tcurData = curData[ internalKey ] = jQuery.extend({}, oldData);\n\n\t\tif ( events ) {\n\t\t\tdelete curData.handle;\n\t\t\tcurData.events = {};\n\n\t\t\tfor ( var type in events ) {\n\t\t\t\tfor ( var i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc;\n\n  // nodes may contain either an explicit document object,\n  // a jQuery collection or context object.\n  // If nodes[0] contains a valid object to assign to doc\n  if ( nodes && nodes[0] ) {\n    doc = nodes[0].ownerDocument || nodes[0];\n  }\n\n  // Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\tif ( args.length === 1 && typeof args[0] === \"string\" && args[0].length < 512 && doc === document &&\n\t\targs[0].charAt(0) === \"<\" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ args[0] ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = (i > 0 ? this.clone(true) : this).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( \"getElementsByTagName\" in elem ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( \"querySelectorAll\" in elem ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\tfixDefaultChecked( elem );\n\t} else if ( \"getElementsByTagName\" in elem ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName\n\t\t\t// instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = (rtagName.exec( elem ) || [\"\", \"\"])[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ] && cache[ id ][ internalKey ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWH( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat( value );\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNaN( value ) ? \"\" : \"alpha(opacity=\" + value * 100 + \")\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( !(defaultView = elem.ownerDocument.defaultView) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : (ret || 0);\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tjQuery.each( which, function() {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ] || 0;\n\t}\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tjQuery.each( which, function() {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn val + \"px\";\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\t\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor(; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor(; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery._Deferred(),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.done;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.error( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor( key in s.converters ) {\n\t\t\t\tif( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css( elem, \"display\" ) === \"none\" ) {\n\t\t\t\t\t\tjQuery._data(elem, \"olddisplay\", defaultDisplay(elem.nodeName));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data(elem, \"olddisplay\") || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tvar display = jQuery.css( this[i], \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( this[i], \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( this[i], \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed(speed, easing, callback);\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p,\n\t\t\t\tdisplay, e,\n\t\t\t\tparts, start, end, unit;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height\n\t\t\t\t\t// animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = defaultDisplay( this.nodeName );\n\n\t\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\t\tif ( display === \"inline\" ) {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline\";\n\t\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test(val) ) {\n\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]();\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ((end || 1) / e.cur()) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t});\n\t},\n\n\tstop: function( clearQueue, gotoEnd ) {\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar timers = jQuery.timers,\n\t\t\t\ti = timers.length;\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( timers[i].elem === this ) {\n\t\t\t\t\tif (gotoEnd) {\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[i](true);\n\t\t\t\t\t}\n\n\t\t\t\t\ttimers.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// start the next in the queue if the last step wasn't forced\n\t\tif ( !gotoEnd ) {\n\t\t\tthis.dequeue();\n\t\t}\n\n\t\treturn this;\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\", 1),\n\tslideUp: genFx(\"hide\", 1),\n\tslideToggle: genFx(\"toggle\", 1),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend({}, speed) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction(easing) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery.dequeue( this );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step(gotoEnd);\n\t\t}\n\n\t\tt.elem = this.elem;\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any\n\t\t// flash of content\n\t\tthis.custom(this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur());\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom(this.cur(), 0);\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar t = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options,\n\t\t\ti, n;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( i in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[i] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function (index, value) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[index];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery(elem).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( var p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[p] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\toptions.complete.call( elem );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ((this.end - this.start) * this.pos);\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tfor ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {\n\t\t\tif ( !timers[i]() ) {\n\t\t\t\ttimers.splice(i--, 1);\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = (fx.prop === \"width\" || fx.prop === \"height\" ? Math.max(0, fx.now) : fx.now) + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( document.compatMode === \"CSS1Compat\" ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tjQuery.offset.initialize();\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\tinitialize: function() {\n\t\tvar body = document.body, container = document.createElement(\"div\"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, \"marginTop\") ) || 0,\n\t\t\thtml = \"<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>\";\n\n\t\tjQuery.extend( container.style, { position: \"absolute\", top: 0, left: 0, margin: 0, border: 0, width: \"1px\", height: \"1px\", visibility: \"hidden\" } );\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\tinnerDiv = container.firstChild;\n\t\tcheckDiv = innerDiv.firstChild;\n\t\ttd = innerDiv.nextSibling.firstChild.firstChild;\n\n\t\tthis.doesNotAddBorder = (checkDiv.offsetTop !== 5);\n\t\tthis.doesAddBorderForTableAndCells = (td.offsetTop === 5);\n\n\t\tcheckDiv.style.position = \"fixed\";\n\t\tcheckDiv.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\tthis.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);\n\t\tcheckDiv.style.position = checkDiv.style.top = \"\";\n\n\t\tinnerDiv.style.overflow = \"hidden\";\n\t\tinnerDiv.style.position = \"relative\";\n\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = (position === \"absolute\" || position === \"fixed\") && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif (options.top != null) {\n\t\t\tprops.top = (options.top - curOffset.top) + curTop;\n\t\t}\n\t\tif (options.left != null) {\n\t\t\tprops.left = (options.left - curOffset.left) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem && elem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem && elem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ],\n\t\t\t\tbody = elem.document.body;\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\tbody && body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNaN( ret ) ? orig : ret;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.6.js",
    "content": "/*!\n * jQuery JavaScript Library v1.6\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Mon May 2 13:50:00 2011 -0400\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// (both of which we optimize for)\n\tquickExpr = /^(?:[^<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Check for digits\n\trdigit = /\\d/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = (context ? context.ownerDocument || context : document);\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn (context || rootjQuery).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif (selector.selector !== undefined) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.6\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + (this.selector ? \" \" : \"\") + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, +i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).unbind( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery._Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNaN: function( obj ) {\n\t\treturn obj == null || !rdigit.test( obj ) || isNaN( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Not own constructor property must be Object\n\t\tif ( obj.constructor &&\n\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn (new Function( \"return \" + data ))();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\t// (xml & tmp used internally)\n\tparseXML: function( data , xml , tmp ) {\n\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\n\t\ttmp = xml.documentElement;\n\n\t\tif ( ! tmp || ! tmp.nodeName || tmp.nodeName === \"parsererror\" ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array ) {\n\n\t\tif ( indexOf ) {\n\t\t\treturn indexOf.call( array, elem );\n\t\t}\n\n\t\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\t\tif ( array[ i ] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can be optionally by executed if its a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn (new Date()).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\n// Expose jQuery to the global object\nreturn jQuery;\n\n})();\n\n\nvar // Promise methods\n\tpromiseMethods = \"done fail isResolved isRejected promise then always pipe\".split( \" \" ),\n\t// Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\t// Create a simple deferred (one callbacks list)\n\t_Deferred: function() {\n\t\tvar // callbacks list\n\t\t\tcallbacks = [],\n\t\t\t// stored [ context , args ]\n\t\t\tfired,\n\t\t\t// to avoid firing when already doing so\n\t\t\tfiring,\n\t\t\t// flag to know if the deferred has been cancelled\n\t\t\tcancelled,\n\t\t\t// the deferred itself\n\t\t\tdeferred  = {\n\n\t\t\t\t// done( f1, f2, ...)\n\t\t\t\tdone: function() {\n\t\t\t\t\tif ( !cancelled ) {\n\t\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t_fired;\n\t\t\t\t\t\tif ( fired ) {\n\t\t\t\t\t\t\t_fired = fired;\n\t\t\t\t\t\t\tfired = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\t\t\t\telem = args[ i ];\n\t\t\t\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t\t\t\tdeferred.done.apply( deferred, elem );\n\t\t\t\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tcallbacks.push( elem );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( _fired ) {\n\t\t\t\t\t\t\tdeferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with given context and args\n\t\t\t\tresolveWith: function( context, args ) {\n\t\t\t\t\tif ( !cancelled && !fired && !firing ) {\n\t\t\t\t\t\t// make sure args are available (#8421)\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\tfiring = 1;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twhile( callbacks[ 0 ] ) {\n\t\t\t\t\t\t\t\tcallbacks.shift().apply( context, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinally {\n\t\t\t\t\t\t\tfired = [ context, args ];\n\t\t\t\t\t\t\tfiring = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// resolve with this as context and given arguments\n\t\t\t\tresolve: function() {\n\t\t\t\t\tdeferred.resolveWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Has this deferred been resolved?\n\t\t\t\tisResolved: function() {\n\t\t\t\t\treturn !!( firing || fired );\n\t\t\t\t},\n\n\t\t\t\t// Cancel\n\t\t\t\tcancel: function() {\n\t\t\t\t\tcancelled = 1;\n\t\t\t\t\tcallbacks = [];\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn deferred;\n\t},\n\n\t// Full fledged deferred (two callbacks list)\n\tDeferred: function( func ) {\n\t\tvar deferred = jQuery._Deferred(),\n\t\t\tfailDeferred = jQuery._Deferred(),\n\t\t\tpromise;\n\t\t// Add errorDeferred methods, then and promise\n\t\tjQuery.extend( deferred, {\n\t\t\tthen: function( doneCallbacks, failCallbacks ) {\n\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\talways: function() {\n\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );\n\t\t\t},\n\t\t\tfail: failDeferred.done,\n\t\t\trejectWith: failDeferred.resolveWith,\n\t\t\treject: failDeferred.resolve,\n\t\t\tisRejected: failDeferred.isResolved,\n\t\t\tpipe: function( fnDone, fnFail ) {\n\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\tfail: [ fnFail, \"reject\" ]\n\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action ]( returned );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).promise();\n\t\t\t},\n\t\t\t// Get a promise for this deferred\n\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\tpromise: function( obj ) {\n\t\t\t\tif ( obj == null ) {\n\t\t\t\t\tif ( promise ) {\n\t\t\t\t\t\treturn promise;\n\t\t\t\t\t}\n\t\t\t\t\tpromise = obj = {};\n\t\t\t\t}\n\t\t\t\tvar i = promiseMethods.length;\n\t\t\t\twhile( i-- ) {\n\t\t\t\t\tobj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t});\n\t\t// Make sure only one callback list will be used\n\t\tdeferred.done( failDeferred.cancel ).fail( deferred.cancel );\n\t\t// Unexpose cancel\n\t\tdelete deferred.cancel;\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = arguments,\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tcount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t// Strange bug in FF4:\n\t\t\t\t\t// Values changed onto the arguments object sometimes end up as undefined values\n\t\t\t\t\t// outside the $.when method. Cloning the object into a fresh array solves the issue\n\t\t\t\t\tdeferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn deferred.promise();\n\t}\n});\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\tbodyStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName( \"tbody\" ).length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName( \"link\" ).length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute( \"href\" ) === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55$/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function click() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t\tdiv.detachEvent( \"onclick\", click );\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains it's value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.firstChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\t// We use our own, invisible, body\n\tbody = document.createElement( \"body\" );\n\tbodyStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\t// Set background to avoid IE crashes when removing (#9028)\n\t\tbackground: \"none\"\n\t};\n\tfor ( i in bodyStyle ) {\n\t\tbody.style[ i ] = bodyStyle[ i ];\n\t}\n\tbody.appendChild( div );\n\tdocument.documentElement.appendChild( body );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( document.defaultView.getComputedStyle( marginDiv, null ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Remove the body element we added\n\tbody.innerHTML = \"\";\n\tdocument.documentElement.removeChild( body );\n\n\t// Technique from Juriy Zaytsev\n\t// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t} ) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([a-z])([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar internalKey = jQuery.expando, getByName = typeof name === \"string\", thisCache,\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);\n\t\t\t} else {\n\t\t\t\tcache[ id ] = jQuery.extend(cache[ id ], name);\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// Internal jQuery data is stored in a separate object inside the object's data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data\n\t\tif ( pvt ) {\n\t\t\tif ( !thisCache[ internalKey ] ) {\n\t\t\t\tthisCache[ internalKey ] = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache[ internalKey ];\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ name ] = data;\n\t\t}\n\n\t\t// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should\n\t\t// not attempt to inspect the internal events object using jQuery.data, as this\n\t\t// internal data object is undocumented and subject to change.\n\t\tif ( name === \"events\" && !thisCache[name] ) {\n\t\t\treturn thisCache[ internalKey ] && thisCache[ internalKey ].events;\n\t\t}\n\n\t\treturn getByName ? thisCache[ name ] : thisCache;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar internalKey = jQuery.expando, isNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\t\t\tvar thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];\n\n\t\t\tif ( thisCache ) {\n\t\t\t\tdelete thisCache[ name ];\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !isEmptyDataObject(thisCache) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( pvt ) {\n\t\t\tdelete cache[ id ][ internalKey ];\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar internalCache = cache[ id ][ internalKey ];\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\tif ( jQuery.support.deleteExpando || cache != window ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the entire user cache at once because it's faster than\n\t\t// iterating through each key, but we need to continue to persist internal\n\t\t// data if it existed\n\t\tif ( internalCache ) {\n\t\t\tcache[ id ] = {};\n\t\t\t// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery\n\t\t\t// metadata on plain JS objects when the object is serialized using\n\t\t\t// JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\n\t\t\tcache[ id ][ internalKey ] = internalCache;\n\n\t\t// Otherwise, we need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\t} else if ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar data = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 ) {\n\t\t\t    var attr = this[0].attributes, name;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tvar parts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"$1-$2\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t!jQuery.isNaN( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON\n// property to be considered empty objects; this property always exists in\n// order to make sure JSON.stringify does not expose internal metadata\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery.data( elem, deferDataKey, undefined, true );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&\n\t\t( src === \"mark\" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery.data( elem, queueDataKey, undefined, true ) &&\n\t\t\t\t!jQuery.data( elem, markDataKey, undefined, true ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.resolve();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"mark\";\n\t\t\tjQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery.data( elem, key, count, true );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tif ( elem ) {\n\t\t\ttype = (type || \"fx\") + \"queue\";\n\t\t\tvar q = jQuery.data( elem, type, undefined, true );\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery.data( elem, type, jQuery.makeArray(data), true );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\tdefer;\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift(\"inprogress\");\n\t\t\t}\n\n\t\t\tfn.call(elem, function() {\n\t\t\t\tjQuery.dequeue(elem, type);\n\t\t\t});\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[time] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function() {\n\t\t\tvar elem = this;\n\t\t\tsetTimeout(function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, time );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\";\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.done( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trspecial = /^(?:data-|aria-)/,\n\trinvalidChar = /\\:/,\n\tformHook;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\t\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\t\n\tremoveProp: function( name ) {\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.addClass( value.call(this, i, self.attr(\"class\") || \"\") );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tvar classNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar elem = this[i];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar className = \" \" + elem.className + \" \",\n\t\t\t\t\t\t\tsetClass = elem.className;\n\n\t\t\t\t\t\tfor ( var c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( className.indexOf( \" \" + classNames[c] + \" \" ) < 0 ) {\n\t\t\t\t\t\t\t\tsetClass += \" \" + classNames[c];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.removeClass( value.call(this, i, self.attr(\"class\")) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tvar classNames = (value || \"\").split( rspace );\n\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tvar elem = this[i];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tvar className = (\" \" + elem.className + \" \").replace(rclass, \" \");\n\t\t\t\t\t\tfor ( var c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[c] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\tself.toggleClass( value.call(this, i, self.attr(\"class\"), stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \";\n\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\tif ( (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret,\n\t\t\telem = this[0];\n\t\t\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\treturn (elem.value || \"\").replace(rreturn, \"\");\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar isFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || (\"set\" in hooks && hooks.set( this, val, \"value\" ) === undefined) ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar index = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {\n\t\t\t\t\tvar option = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\t\n\tattrFix: {\n\t\t// Always normalize to ensure hook usage\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\"\n\t},\n\t\n\tattr: function( elem, name, value, pass ) {\n\t\tvar nType = elem.nodeType;\n\t\t\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\t\t\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\t\t\n\t\t// Normalize the name if needed\n\t\tname = notxml && jQuery.attrFix[ name ] || name;\n\n\t\t// Get the appropriate hook, or the formHook\n\t\t// if getSetAttribute is not supported and we have form objects in IE6/7\n\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t( formHook && (jQuery.nodeName( elem, \"form\" ) || rinvalidChar.test( name )) ?\n\t\t\t\tformHook :\n\t\t\t\tundefined );\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null || (value === false && !rspecial.test( name )) ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn undefined;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\n\t\t\t\t// Set boolean attributes to the same name\n\t\t\t\tif ( value === true && !rspecial.test( name ) ) {\n\t\t\t\t\tvalue = name;\n\t\t\t\t}\n\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( hooks && \"get\" in hooks && notxml ) {\n\t\t\t\treturn hooks.get( elem, name );\n\n\t\t\t} else {\n\n\t\t\t\tret = elem.getAttribute( name );\n\n\t\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\t\treturn ret === null ?\n\t\t\t\t\tundefined :\n\t\t\t\t\tret;\n\t\t\t}\n\t\t}\n\t},\n\t\n\tremoveAttr: function( elem, name ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tname = jQuery.attrFix[ name ] || name;\n\t\t\n\t\t\tif ( jQuery.support.getSetAttribute ) {\n\t\t\t\t// Use removeAttribute in browsers that support it\n\t\t\t\telem.removeAttribute( name );\n\t\t\t} else {\n\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\telem.removeAttributeNode( elem.getAttributeNode( name ) );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.getAttribute(\"value\");\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabIndex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t},\n\t\n\tpropFix: {},\n\t\n\tprop: function( elem, name, value ) {\n\t\tvar nType = elem.nodeType;\n\t\t\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\t\t\n\t\tvar ret, hooks,\n\t\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\t\t\n\t\t// Try to normalize/fix the name\n\t\tname = notxml && jQuery.propFix[ name ] || name;\n\t\t\n\t\thooks = jQuery.propHooks[ name ];\n\t\t\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t\n\t\t\t} else {\n\t\t\t\treturn (elem[ name ] = value);\n\t\t\t}\n\t\t\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\t\n\tpropHooks: {}\n});\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !jQuery.support.getSetAttribute ) {\n\tjQuery.attrFix = jQuery.extend( jQuery.attrFix, {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\"\n\t});\n\t\n\t// Use this for any attribute on a form in IE6/7\n\tformHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tif ( name === \"value\" && !jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\treturn elem.getAttribute( name );\n\t\t\t}\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\t// Return undefined if not specified instead of empty string\n\t\t\treturn ret && ret.specified ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Check form objects in IE (multiple bugs related)\n\t\t\t// Only use nodeValue if the attribute node exists on the form\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret ) {\n\t\t\t\tret.nodeValue = value;\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn (elem.style.cssText = \"\" + value);\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar hasOwn = Object.prototype.hasOwnProperty,\n\trnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\tfcleanup = function( nm ) {\n\t\treturn nm.replace(rescape, \"\\\\$&\");\n\t};\n\n/*\n * A number of helper functions used for managing events.\n * Many of the ideas behind this code originated from\n * Dean Edwards' addEvent library.\n */\njQuery.event = {\n\n\t// Bind an event to an element\n\t// Original by Dean Edwards\n\tadd: function( elem, types, handler, data ) {\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t} else if ( !handler ) {\n\t\t\t// Fixes bug #7229. Fix recommended by jdalton\n\t\t\treturn;\n\t\t}\n\n\t\tvar handleObjIn, handleObj;\n\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the function being executed has a unique ID\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure\n\t\tvar elemData = jQuery._data( elem );\n\n\t\t// If no elemData is found then we must be trying to bind to one of the\n\t\t// banned noData elements\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar events = elemData.events,\n\t\t\teventHandle = elemData.handle;\n\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.handle.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t}\n\n\t\t// Add elem as a property of the handle function\n\t\t// This is to prevent a memory leak with non-native events in IE.\n\t\teventHandle.elem = elem;\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\tvar type, i = 0, namespaces;\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\thandleObj = handleObjIn ?\n\t\t\t\tjQuery.extend({}, handleObjIn) :\n\t\t\t\t{ handler: handler, data: data };\n\n\t\t\t// Namespaced event handlers\n\t\t\tif ( type.indexOf(\".\") > -1 ) {\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\thandleObj.namespace = namespaces.slice(0).sort().join(\".\");\n\n\t\t\t} else {\n\t\t\t\tnamespaces = [];\n\t\t\t\thandleObj.namespace = \"\";\n\t\t\t}\n\n\t\t\thandleObj.type = type;\n\t\t\tif ( !handleObj.guid ) {\n\t\t\t\thandleObj.guid = handler.guid;\n\t\t\t}\n\n\t\t\t// Get the current list of functions bound to this event\n\t\t\tvar handlers = events[ type ],\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// Init the event handler queue\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\n\t\t\t\t// Check for a special event handler\n\t\t\t\t// Only use addEventListener/attachEvent if the special\n\t\t\t\t// events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the function to the element's handler list\n\t\t\thandlers.push( handleObj );\n\n\t\t\t// Keep track of which events have been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, pos ) {\n\t\t// don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( handler === false ) {\n\t\t\thandler = returnFalse;\n\t\t}\n\n\t\tvar ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tevents = elemData && elemData.events;\n\n\t\tif ( !elemData || !events ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// types is actually an event object here\n\t\tif ( types && types.type ) {\n\t\t\thandler = types.handler;\n\t\t\ttypes = types.type;\n\t\t}\n\n\t\t// Unbind all events for the element\n\t\tif ( !types || typeof types === \"string\" && types.charAt(0) === \".\" ) {\n\t\t\ttypes = types || \"\";\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tjQuery.event.remove( elem, type + types );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).unbind(\"mouseover mouseout\", fn);\n\t\ttypes = types.split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) ) {\n\t\t\torigType = type;\n\t\t\thandleObj = null;\n\t\t\tall = type.indexOf(\".\") < 0;\n\t\t\tnamespaces = [];\n\n\t\t\tif ( !all ) {\n\t\t\t\t// Namespaced event handlers\n\t\t\t\tnamespaces = type.split(\".\");\n\t\t\t\ttype = namespaces.shift();\n\n\t\t\t\tnamespace = new RegExp(\"(^|\\\\.)\" +\n\t\t\t\t\tjQuery.map( namespaces.slice(0).sort(), fcleanup ).join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\t}\n\n\t\t\teventType = events[ type ];\n\n\t\t\tif ( !eventType ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( !handler ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, origType, handleObj.handler, j );\n\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tfor ( j = pos || 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( handler.guid === handleObj.guid ) {\n\t\t\t\t\t// remove the given handler for the given type\n\t\t\t\t\tif ( all || namespace.test( handleObj.namespace ) ) {\n\t\t\t\t\t\tif ( pos == null ) {\n\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( pos != null ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove generic event handler if no more handlers exist\n\t\t\tif ( eventType.length === 0 || pos != null && eventType.length === 1 ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tret = null;\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tvar handle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\tdelete elemData.events;\n\t\t\tdelete elemData.handle;\n\n\t\t\tif ( jQuery.isEmptyObject( elemData ) ) {\n\t\t\t\tjQuery.removeData( elem, undefined, true );\n\t\t\t}\n\t\t}\n\t},\n\t\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\texclusive;\n\n\t\tif ( type.indexOf(\"!\") >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t\t\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tjQuery.each( jQuery.cache, function() {\n\t\t\t\t// internalKey variable is just used to make it easier to find\n\t\t\t\t// and potentially change this stuff later; currently it just\n\t\t\t\t// points to jQuery.expando\n\t\t\t\tvar internalKey = jQuery.expando,\n\t\t\t\t\tinternalCache = this[ internalKey ];\n\t\t\t\tif ( internalCache && internalCache.events && internalCache.events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, internalCache.handle.elem );\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tevent.target = elem;\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\tvar cur = elem,\n\t\t\t// IE doesn't like method names with a colon (#3533, #8272)\n\t\t\tontype = type.indexOf(\":\") < 0 ? \"on\" + type : \"\";\n\n\t\t// Fire event on the current element, then bubble up the DOM tree\n\t\tdo {\n\t\t\tvar handle = jQuery._data( cur, \"handle\" );\n\n\t\t\tevent.currentTarget = cur;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Trigger an inline bound script\n\t\t\tif ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {\n\t\t\t\tevent.result = false;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\t// Bubble up to document, then to window\n\t\t\tcur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;\n\t\t} while ( cur && !event.isPropagationStopped() );\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tvar old,\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\tif ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction)() check here because IE6/7 fails that test.\n\t\t\t\t// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.\n\t\t\t\ttry {\n\t\t\t\t\tif ( ontype && elem[ type ] ) {\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t}\n\t\t\t\t} catch ( ieError ) {}\n\n\t\t\t\tif ( old ) {\n\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t}\n\n\t\t\t\tjQuery.event.triggered = undefined;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn event.result;\n\t},\n\n\thandle: function( event ) {\n\t\tevent = jQuery.event.fix( event || window.event );\n\t\t// Snapshot the handlers list since a called handler may add/remove events.\n\t\tvar handlers = ((jQuery._data( this, \"events\" ) || {})[ event.type ] || []).slice(0),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\targs = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// Use the fix-ed Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.currentTarget = this;\n\n\t\tfor ( var j = 0, l = handlers.length; j < l; j++ ) {\n\t\t\tvar handleObj = handlers[ j ];\n\n\t\t\t// Triggered event must 1) be non-exclusive and have no namespace, or\n\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event.\n\t\t\tif ( run_all || event.namespace_re.test( handleObj.namespace ) ) {\n\t\t\t\t// Pass in a reference to the handler function itself\n\t\t\t\t// So that we can later remove it\n\t\t\t\tevent.handler = handleObj.handler;\n\t\t\t\tevent.data = handleObj.data;\n\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\tvar ret = handleObj.handler.apply( this, args );\n\n\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\tevent.result = ret;\n\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn event.result;\n\t},\n\n\tprops: \"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// store a copy of the original event object\n\t\t// and \"clone\" to set read-only properties\n\t\tvar originalEvent = event;\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( var i = this.props.length, prop; i; ) {\n\t\t\tprop = this.props[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary\n\t\tif ( !event.target ) {\n\t\t\t// Fixes #1925 where srcElement might not be defined either\n\t\t\tevent.target = event.srcElement || document;\n\t\t}\n\n\t\t// check if target is a textnode (safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Add relatedTarget, if necessary\n\t\tif ( !event.relatedTarget && event.fromElement ) {\n\t\t\tevent.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n\t\t}\n\n\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\tif ( event.pageX == null && event.clientX != null ) {\n\t\t\tvar eventDocument = event.target.ownerDocument || document,\n\t\t\t\tdoc = eventDocument.documentElement,\n\t\t\t\tbody = eventDocument.body;\n\n\t\t\tevent.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n\t\t\tevent.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && (event.charCode != null || event.keyCode != null) ) {\n\t\t\tevent.which = event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)\n\t\tif ( !event.metaKey && event.ctrlKey ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t// Note: button is not normalized, so don't use it\n\t\tif ( !event.which && event.button !== undefined ) {\n\t\t\tevent.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// Deprecated, use jQuery.guid instead\n\tguid: 1E8,\n\n\t// Deprecated, use jQuery.proxy instead\n\tproxy: jQuery.proxy,\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady,\n\t\t\tteardown: jQuery.noop\n\t\t},\n\n\t\tlive: {\n\t\t\tadd: function( handleObj ) {\n\t\t\t\tjQuery.event.add( this,\n\t\t\t\t\tliveConvert( handleObj.origType, handleObj.selector ),\n\t\t\t\t\tjQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );\n\t\t\t},\n\n\t\t\tremove: function( handleObj ) {\n\t\t\t\tjQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !this.preventDefault ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// timeStamp is buggy for some events on Firefox(#3843)\n\t// So we won't rely on the native value\n\tthis.timeStamp = jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Checks if an event happened on an element within another element\n// Used in jQuery.event.special.mouseenter and mouseleave handlers\nvar withinElement = function( event ) {\n\t// Check if mouse(over|out) are still within the same parent element\n\tvar parent = event.relatedTarget;\n\n\t// Firefox sometimes assigns relatedTarget a XUL element\n\t// which we cannot access the parentNode property of\n\ttry {\n\n\t\t// Chrome does something similar, the parentNode property\n\t\t// can be accessed but is null.\n\t\tif ( parent && parent !== document && !parent.parentNode ) {\n\t\t\treturn;\n\t\t}\n\t\t// Traverse up the tree\n\t\twhile ( parent && parent !== this ) {\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\tif ( parent !== this ) {\n\t\t\t// set the correct event type\n\t\t\tevent.type = event.data;\n\n\t\t\t// handle event if we actually just moused on to a non sub-element\n\t\t\tjQuery.event.handle.apply( this, arguments );\n\t\t}\n\n\t// assuming we've left the element since we most likely mousedover a xul element\n\t} catch(e) { }\n},\n\n// In case of event delegation, we only need to rename the event.type,\n// liveHandler will take care of the rest.\ndelegate = function( event ) {\n\tevent.type = event.data;\n\tjQuery.event.handle.apply( this, arguments );\n};\n\n// Create mouseenter and mouseleave events\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tsetup: function( data ) {\n\t\t\tjQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );\n\t\t},\n\t\tteardown: function( data ) {\n\t\t\tjQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );\n\t\t}\n\t};\n});\n\n// submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( !jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\tjQuery.event.add(this, \"click.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"submit\" || type === \"image\") && jQuery( elem ).closest(\"form\").length ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tjQuery.event.add(this, \"keypress.specialSubmit\", function( e ) {\n\t\t\t\t\tvar elem = e.target,\n\t\t\t\t\t\ttype = elem.type;\n\n\t\t\t\t\tif ( (type === \"text\" || type === \"password\") && jQuery( elem ).closest(\"form\").length && e.keyCode === 13 ) {\n\t\t\t\t\t\ttrigger( \"submit\", this, arguments );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialSubmit\" );\n\t\t}\n\t};\n\n}\n\n// change delegation, happens here so we have bind.\nif ( !jQuery.support.changeBubbles ) {\n\n\tvar changeFilters,\n\n\tgetVal = function( elem ) {\n\t\tvar type = elem.type, val = elem.value;\n\n\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\tval = elem.checked;\n\n\t\t} else if ( type === \"select-multiple\" ) {\n\t\t\tval = elem.selectedIndex > -1 ?\n\t\t\t\tjQuery.map( elem.options, function( elem ) {\n\t\t\t\t\treturn elem.selected;\n\t\t\t\t}).join(\"-\") :\n\t\t\t\t\"\";\n\n\t\t} else if ( jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\tval = elem.selectedIndex;\n\t\t}\n\n\t\treturn val;\n\t},\n\n\ttestChange = function testChange( e ) {\n\t\tvar elem = e.target, data, val;\n\n\t\tif ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdata = jQuery._data( elem, \"_change_data\" );\n\t\tval = getVal(elem);\n\n\t\t// the current data will be also retrieved by beforeactivate\n\t\tif ( e.type !== \"focusout\" || elem.type !== \"radio\" ) {\n\t\t\tjQuery._data( elem, \"_change_data\", val );\n\t\t}\n\n\t\tif ( data === undefined || val === data ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data != null || val ) {\n\t\t\te.type = \"change\";\n\t\t\te.liveFired = undefined;\n\t\t\tjQuery.event.trigger( e, arguments[1], elem );\n\t\t}\n\t};\n\n\tjQuery.event.special.change = {\n\t\tfilters: {\n\t\t\tfocusout: testChange,\n\n\t\t\tbeforedeactivate: testChange,\n\n\t\t\tclick: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" || jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Change has to be called before submit\n\t\t\t// Keydown will be called before keypress, which is used in submit-event delegation\n\t\t\tkeydown: function( e ) {\n\t\t\t\tvar elem = e.target, type = jQuery.nodeName( elem, \"input\" ) ? elem.type : \"\";\n\n\t\t\t\tif ( (e.keyCode === 13 && !jQuery.nodeName( elem, \"textarea\" ) ) ||\n\t\t\t\t\t(e.keyCode === 32 && (type === \"checkbox\" || type === \"radio\")) ||\n\t\t\t\t\ttype === \"select-multiple\" ) {\n\t\t\t\t\ttestChange.call( this, e );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Beforeactivate happens also before the previous element is blurred\n\t\t\t// with this event you can't trigger a change event, but you can store\n\t\t\t// information\n\t\t\tbeforeactivate: function( e ) {\n\t\t\t\tvar elem = e.target;\n\t\t\t\tjQuery._data( elem, \"_change_data\", getVal(elem) );\n\t\t\t}\n\t\t},\n\n\t\tsetup: function( data, namespaces ) {\n\t\t\tif ( this.type === \"file\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( var type in changeFilters ) {\n\t\t\t\tjQuery.event.add( this, type + \".specialChange\", changeFilters[type] );\n\t\t\t}\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t},\n\n\t\tteardown: function( namespaces ) {\n\t\t\tjQuery.event.remove( this, \".specialChange\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n\n\tchangeFilters = jQuery.event.special.change.filters;\n\n\t// Handle when the input is .focus()'d\n\tchangeFilters.focus = changeFilters.beforeactivate;\n}\n\nfunction trigger( type, elem, args ) {\n\t// Piggyback on a donor event to simulate a different one.\n\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t// simulated event prevents default then we do the same on the donor.\n\t// Don't pass args or remember liveFired; they apply to the donor event.\n\tvar event = jQuery.extend( {}, args[ 0 ] );\n\tevent.type = type;\n\tevent.originalEvent = {};\n\tevent.liveFired = undefined;\n\tjQuery.event.handle.call( elem, event );\n\tif ( event.isDefaultPrevented() ) {\n\t\targs[ 0 ].preventDefault();\n\t}\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0;\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfunction handler( donor ) {\n\t\t\t// Donor event is always a native one; fix it and switch its type.\n\t\t\t// Let focusin/out handler cancel the donor focus/blur event.\n\t\t\tvar e = jQuery.event.fix( donor );\n\t\t\te.type = fix;\n\t\t\te.originalEvent = {};\n\t\t\tjQuery.event.trigger( e, null, e.target );\n\t\t\tif ( e.isDefaultPrevented() ) {\n\t\t\t\tdonor.preventDefault();\n\t\t\t}\n\t\t}\n\t});\n}\n\njQuery.each([\"bind\", \"one\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( type, data, fn ) {\n\t\tvar handler;\n\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis[ name ](key, data, type[key], fn);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( arguments.length === 2 || data === false ) {\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\tif ( name === \"one\" ) {\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery( this ).unbind( event, handler );\n\t\t\t\treturn fn.apply( this, arguments );\n\t\t\t};\n\t\t\thandler.guid = fn.guid || jQuery.guid++;\n\t\t} else {\n\t\t\thandler = fn;\n\t\t}\n\n\t\tif ( type === \"unload\" && name !== \"one\" ) {\n\t\t\tthis.one( type, data, fn );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( this[i], type, handler, data );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\njQuery.fn.extend({\n\tunbind: function( type, fn ) {\n\t\t// Handle object literals\n\t\tif ( typeof type === \"object\" && !type.preventDefault ) {\n\t\t\tfor ( var key in type ) {\n\t\t\t\tthis.unbind(key, type[key]);\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\tjQuery.event.remove( this[i], type, fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.live( types, data, fn, selector );\n\t},\n\n\tundelegate: function( selector, types, fn ) {\n\t\tif ( arguments.length === 0 ) {\n\t\t\treturn this.unbind( \"live\" );\n\n\t\t} else {\n\t\t\treturn this.die( types, null, fn, selector );\n\t\t}\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery.data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery.data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\nvar liveMap = {\n\tfocus: \"focusin\",\n\tblur: \"focusout\",\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n};\n\njQuery.each([\"live\", \"die\"], function( i, name ) {\n\tjQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {\n\t\tvar type, i = 0, match, namespaces, preType,\n\t\t\tselector = origSelector || this.selector,\n\t\t\tcontext = origSelector ? this : jQuery( this.context );\n\n\t\tif ( typeof types === \"object\" && !types.preventDefault ) {\n\t\t\tfor ( var key in types ) {\n\t\t\t\tcontext[ name ]( key, data, types[key], selector );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( name === \"die\" && !types &&\n\t\t\t\t\torigSelector && origSelector.charAt(0) === \".\" ) {\n\n\t\t\tcontext.unbind( origSelector );\n\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data === false || jQuery.isFunction( data ) ) {\n\t\t\tfn = data || returnFalse;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\ttypes = (types || \"\").split(\" \");\n\n\t\twhile ( (type = types[ i++ ]) != null ) {\n\t\t\tmatch = rnamespaces.exec( type );\n\t\t\tnamespaces = \"\";\n\n\t\t\tif ( match )  {\n\t\t\t\tnamespaces = match[0];\n\t\t\t\ttype = type.replace( rnamespaces, \"\" );\n\t\t\t}\n\n\t\t\tif ( type === \"hover\" ) {\n\t\t\t\ttypes.push( \"mouseenter\" + namespaces, \"mouseleave\" + namespaces );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpreType = type;\n\n\t\t\tif ( liveMap[ type ] ) {\n\t\t\t\ttypes.push( liveMap[ type ] + namespaces );\n\t\t\t\ttype = type + namespaces;\n\n\t\t\t} else {\n\t\t\t\ttype = (liveMap[ type ] || type) + namespaces;\n\t\t\t}\n\n\t\t\tif ( name === \"live\" ) {\n\t\t\t\t// bind live handler\n\t\t\t\tfor ( var j = 0, l = context.length; j < l; j++ ) {\n\t\t\t\t\tjQuery.event.add( context[j], \"live.\" + liveConvert( type, selector ),\n\t\t\t\t\t\t{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// unbind live handler\n\t\t\t\tcontext.unbind( \"live.\" + liveConvert( type, selector ), fn );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t};\n});\n\nfunction liveHandler( event ) {\n\tvar stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,\n\t\telems = [],\n\t\tselectors = [],\n\t\tevents = jQuery._data( this, \"events\" );\n\n\t// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)\n\tif ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === \"click\" ) {\n\t\treturn;\n\t}\n\n\tif ( event.namespace ) {\n\t\tnamespace = new RegExp(\"(^|\\\\.)\" + event.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\");\n\t}\n\n\tevent.liveFired = this;\n\n\tvar live = events.live.slice(0);\n\n\tfor ( j = 0; j < live.length; j++ ) {\n\t\thandleObj = live[j];\n\n\t\tif ( handleObj.origType.replace( rnamespaces, \"\" ) === event.type ) {\n\t\t\tselectors.push( handleObj.selector );\n\n\t\t} else {\n\t\t\tlive.splice( j--, 1 );\n\t\t}\n\t}\n\n\tmatch = jQuery( event.target ).closest( selectors, event.currentTarget );\n\n\tfor ( i = 0, l = match.length; i < l; i++ ) {\n\t\tclose = match[i];\n\n\t\tfor ( j = 0; j < live.length; j++ ) {\n\t\t\thandleObj = live[j];\n\n\t\t\tif ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {\n\t\t\t\telem = close.elem;\n\t\t\t\trelated = null;\n\n\t\t\t\t// Those two events require additional checking\n\t\t\t\tif ( handleObj.preType === \"mouseenter\" || handleObj.preType === \"mouseleave\" ) {\n\t\t\t\t\tevent.type = handleObj.preType;\n\t\t\t\t\trelated = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];\n\n\t\t\t\t\t// Make sure not to accidentally match a child element with the same selector\n\t\t\t\t\tif ( related && jQuery.contains( elem, related ) ) {\n\t\t\t\t\t\trelated = elem;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !related || related !== elem ) {\n\t\t\t\t\telems.push({ elem: elem, handleObj: handleObj, level: close.level });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( i = 0, l = elems.length; i < l; i++ ) {\n\t\tmatch = elems[i];\n\n\t\tif ( maxLevel && match.level > maxLevel ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tevent.currentTarget = match.elem;\n\t\tevent.data = match.handleObj.data;\n\t\tevent.handleObj = match.handleObj;\n\n\t\tret = match.handleObj.origHandler.apply( match.elem, arguments );\n\n\t\tif ( ret === false || event.isPropagationStopped() ) {\n\t\t\tmaxLevel = match.level;\n\n\t\t\tif ( ret === false ) {\n\t\t\t\tstop = false;\n\t\t\t}\n\t\t\tif ( event.isImmediatePropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn stop;\n}\n\nfunction liveConvert( type, selector ) {\n\treturn (type && type !== \"*\" ? type + \".\" : \"\") + selector.replace(rperiod, \"`\").replace(rspaces, \"&\");\n}\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.bind( name, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( var i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tvar pass = not ^ !!found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar type = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tvar first = match[2],\n\t\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent.sizcache = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar diff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Expr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Utility function for retreiving the text value of an array of DOM nodes\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( typeof selector === \"string\" ?\n\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar match, selector,\n\t\t\t\tmatches = {},\n\t\t\t\tlevel = 1;\n\n\t\t\tif ( cur && selectors.length ) {\n\t\t\t\tfor ( i = 0, l = selectors.length; i < l; i++ ) {\n\t\t\t\t\tselector = selectors[i];\n\n\t\t\t\t\tif ( !matches[ selector ] ) {\n\t\t\t\t\t\tmatches[ selector ] = POS.test( selector ) ?\n\t\t\t\t\t\t\tjQuery( selector, context || this.context ) :\n\t\t\t\t\t\t\tselector;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\t\tfor ( selector in matches ) {\n\t\t\t\t\t\tmatch = matches[ selector ];\n\n\t\t\t\t\t\tif ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {\n\t\t\t\t\t\t\tret.push({ selector: selector, elem: cur, level: level });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tlevel++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\t\tif ( !elem || typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0],\n\t\t\t\t// If it receives a string, the selector is used\n\t\t\t\t// If it receives nothing, the siblings are used\n\t\t\t\telem ? jQuery( elem ) : this.parent().children() );\n\t\t}\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until ),\n\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, args.join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn (elem === qualifier) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn (jQuery.inArray( elem, qualifier ) >= 0) === keep;\n\t});\n}\n\n\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery(arguments[0]);\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery(arguments[0]).toArray() );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnocache.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || (l > 1 && i < lastIndex) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar internalKey = jQuery.expando,\n\t\toldData = jQuery.data( src ),\n\t\tcurData = jQuery.data( dest, oldData );\n\n\t// Switch to use the internal data object, if it exists, for the next\n\t// stage of data copying\n\tif ( (oldData = oldData[ internalKey ]) ) {\n\t\tvar events = oldData.events;\n\t\t\t\tcurData = curData[ internalKey ] = jQuery.extend({}, oldData);\n\n\t\tif ( events ) {\n\t\t\tdelete curData.handle;\n\t\t\tcurData.events = {};\n\n\t\t\tfor ( var type in events ) {\n\t\t\t\tfor ( var i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults,\n\t\tdoc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\tif ( args.length === 1 && typeof args[0] === \"string\" && args[0].length < 512 && doc === document &&\n\t\targs[0].charAt(0) === \"<\" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ args[0] ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = (i > 0 ? this.clone(true) : this).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( \"getElementsByTagName\" in elem ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\t\n\t} else if ( \"querySelectorAll\" in elem ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\tfixDefaultChecked( elem );\n\t} else if ( elem.getElementsByTagName ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName\n\t\t\t// instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [];\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = (rtagName.exec( elem ) || [\"\", \"\"])[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( var j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tfindInputs( elem[i] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ] && cache[ id ][ internalKey ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || \"\" );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\trdashAlpha = /-([a-z])/ig,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^[+\\-]=/,\n\trrelNumFilter = /[^+\\-\\.\\de]+/g,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle,\n\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"zIndex\": true,\n\t\t\"fontWeight\": true,\n\t\t\"opacity\": true,\n\t\t\"zoom\": true,\n\t\t\"lineHeight\": true,\n\t\t\"widows\": true,\n\t\t\"orphans\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( type === \"number\" && isNaN( value ) || value == null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && rrelNum.test( value ) ) {\n\t\t\t\tvalue = +value.replace( rrelNumFilter, \"\" ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t},\n\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rdashAlpha, fcamelCase );\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\tval = getWH( elem, name, extra );\n\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif ( val <= 0 ) {\n\t\t\t\t\tval = curCSS( elem, name, name );\n\n\t\t\t\t\tif ( val === \"0px\" && currentStyle ) {\n\t\t\t\t\t\tval = currentStyle( elem, name, name );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( val != null ) {\n\t\t\t\t\t\t// Should return \"auto\" instead of 0, use 0 for\n\t\t\t\t\t\t// temporary backwards-compat\n\t\t\t\t\t\treturn val === \"\" || val === \"auto\" ? \"0px\" : val;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( val < 0 || val == null ) {\n\t\t\t\t\tval = elem.style[ name ];\n\n\t\t\t\t\t// Should return \"auto\" instead of 0, use 0 for\n\t\t\t\t\t// temporary backwards-compat\n\t\t\t\t\treturn val === \"\" || val === \"auto\" ? \"0px\" : val;\n\t\t\t\t}\n\n\t\t\t\treturn typeof val === \"string\" ? val : val + \"px\";\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat(value);\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle;\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// Set the alpha filter to set the opacity\n\t\t\tvar opacity = jQuery.isNaN( value ) ?\n\t\t\t\t\"\" :\n\t\t\t\t\"alpha(opacity=\" + value * 100 + \")\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( !(defaultView = elem.ownerDocument.defaultView) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : (ret || 0);\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\tvar which = name === \"width\" ? cssWidth : cssHeight,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight;\n\n\tif ( extra === \"border\" ) {\n\t\treturn val;\n\t}\n\n\tjQuery.each( which, function() {\n\t\tif ( !extra ) {\n\t\t\tval -= parseFloat(jQuery.css( elem, \"padding\" + this )) || 0;\n\t\t}\n\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += parseFloat(jQuery.css( elem, \"margin\" + this )) || 0;\n\n\t\t} else {\n\t\t\tval -= parseFloat(jQuery.css( elem, \"border\" + this + \"Width\" )) || 0;\n\t\t}\n\t});\n\n\treturn val;\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts;\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor(; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor(; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function ( target, settings ) {\n\t\tif ( !settings ) {\n\t\t\t// Only one parameter, we extend ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.extend( true, jQuery.ajaxSettings, settings );\n\t\t} else {\n\t\t\t// target was provided, we extend into it\n\t\t\tjQuery.extend( true, target, jQuery.ajaxSettings, settings );\n\t\t}\n\t\t// Flatten fields we don't want deep extended\n\t\tfor( var field in { context: 1, url: 1 } ) {\n\t\t\tif ( field in settings ) {\n\t\t\t\ttarget[ field ] = settings[ field ];\n\t\t\t} else if( field in jQuery.ajaxSettings ) {\n\t\t\t\ttarget[ field ] = jQuery.ajaxSettings[ field ];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": \"*/*\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery._Deferred(),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, statusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = statusText;\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.done;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", */*; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( status < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.error( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor( key in s.converters ) {\n\t\t\t\tif( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow,\n\trequestAnimationFrame = window.webkitRequestAnimationFrame ||\n\t    window.mozRequestAnimationFrame ||\n\t    window.oRequestAnimationFrame;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css( elem, \"display\" ) === \"none\" ) {\n\t\t\t\t\t\tjQuery._data(elem, \"olddisplay\", defaultDisplay(elem.nodeName));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data(elem, \"olddisplay\") || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tvar display = jQuery.css( this[i], \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( this[i], \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( this[i], \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed(speed, easing, callback);\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\treturn this[ optall.queue === false ? \"each\" : \"queue\" ](function() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend({}, optall),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p,\n\t\t\t\tdisplay, e,\n\t\t\t\tparts, start, end, unit;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[name];\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call(this);\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height\n\t\t\t\t\t// animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdisplay = defaultDisplay(this.nodeName);\n\n\t\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\t\tif ( display === \"inline\" ) {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.style.display = \"inline\";\n\t\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\topt.animatedProperties[name] = jQuery.isArray( val ) ?\n\t\t\t\t\tval[1]:\n\t\t\t\t\topt.specialEasing && opt.specialEasing[name] || opt.easing || 'swing';\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\n\t\t\t\tval = prop[p];\n\n\t\t\t\tif ( rfxtypes.test(val) ) {\n\t\t\t\t\te[ val === \"toggle\" ? hidden ? \"show\" : \"hide\" : val ]();\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec(val);\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ name ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ((end || 1) / e.cur()) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ((parts[1] === \"-=\" ? -1 : 1) * end) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t});\n\t},\n\n\tstop: function( clearQueue, gotoEnd ) {\n\t\tif ( clearQueue ) {\n\t\t\tthis.queue([]);\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar timers = jQuery.timers,\n\t\t\t\ti = timers.length;\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\t\t\t// go in reverse order so anything added to the queue during the loop is ignored\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( timers[i].elem === this ) {\n\t\t\t\t\tif (gotoEnd) {\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[i](true);\n\t\t\t\t\t}\n\n\t\t\t\t\ttimers.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// start the next in the queue if the last step wasn't forced\n\t\tif ( !gotoEnd ) {\n\t\t\tthis.dequeue();\n\t\t}\n\n\t\treturn this;\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\", 1),\n\tslideUp: genFx(\"hide\", 1),\n\tslideToggle: genFx(\"toggle\", 1),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend({}, speed) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction(easing) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( opt.queue !== false ) {\n\t\t\t\tjQuery.dequeue( this );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx,\n\t\t\traf;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.start = from;\n\t\tthis.end = to;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\t\tthis.now = this.start;\n\t\tthis.pos = this.state = 0;\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step(gotoEnd);\n\t\t}\n\n\t\tt.elem = this.elem;\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\t// Use requestAnimationFrame instead of setInterval if available\n\t\t\tif ( requestAnimationFrame ) {\n\t\t\t\ttimerId = 1;\n\t\t\t\traf = function() {\n\t\t\t\t\t// When timerId gets set to null at any point, this stops\n\t\t\t\t\tif ( timerId ) {\n\t\t\t\t\t\trequestAnimationFrame( raf );\n\t\t\t\t\t\tfx.tick();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trequestAnimationFrame( raf );\n\t\t\t} else {\n\t\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any\n\t\t// flash of content\n\t\tthis.custom(this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur());\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[this.prop] = jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom(this.cur(), 0);\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar t = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options,\n\t\t\ti, n;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( i in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[i] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function (index, value) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[index];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery(elem).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( var p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[p] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\toptions.complete.call( elem );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\n\t\t\t\tthis.state = n / options.duration;\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[options.animatedProperties[this.prop]](this.state, n, 0, 1, options.duration);\n\t\t\t\tthis.now = this.start + ((this.end - this.start) * this.pos);\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timers = jQuery.timers,\n\t\t\ti = timers.length;\n\t\twhile ( i-- ) {\n\t\t\tif ( !timers[i]() ) {\n\t\t\t\ttimers.splice(i, 1);\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = (fx.prop === \"width\" || fx.prop === \"height\" ? Math.max(0, fx.now) : fx.now) + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( \"body\" ),\n\t\t\tdisplay = elem.css( \"display\" );\n\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tdocument.body.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake html\n\t\t\t// document to it, Webkit & Firefox won't allow reusing the iframe document\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( \"<!doctype><html><body></body></html>\" );\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\tdocument.body.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tjQuery.offset.initialize();\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\tinitialize: function() {\n\t\tvar body = document.body, container = document.createElement(\"div\"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, \"marginTop\") ) || 0,\n\t\t\thtml = \"<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>\";\n\n\t\tjQuery.extend( container.style, { position: \"absolute\", top: 0, left: 0, margin: 0, border: 0, width: \"1px\", height: \"1px\", visibility: \"hidden\" } );\n\n\t\tcontainer.innerHTML = html;\n\t\tbody.insertBefore( container, body.firstChild );\n\t\tinnerDiv = container.firstChild;\n\t\tcheckDiv = innerDiv.firstChild;\n\t\ttd = innerDiv.nextSibling.firstChild.firstChild;\n\n\t\tthis.doesNotAddBorder = (checkDiv.offsetTop !== 5);\n\t\tthis.doesAddBorderForTableAndCells = (td.offsetTop === 5);\n\n\t\tcheckDiv.style.position = \"fixed\";\n\t\tcheckDiv.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\tthis.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);\n\t\tcheckDiv.style.position = checkDiv.style.top = \"\";\n\n\t\tinnerDiv.style.overflow = \"hidden\";\n\t\tinnerDiv.style.position = \"relative\";\n\n\t\tthis.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);\n\n\t\tthis.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);\n\n\t\tbody.removeChild( container );\n\t\tjQuery.offset.initialize = jQuery.noop;\n\t},\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tjQuery.offset.initialize();\n\n\t\tif ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = (position === \"absolute\" || position === \"fixed\") && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif (options.top != null) {\n\t\t\tprops.top = (options.top - curOffset.top) + curTop;\n\t\t}\n\t\tif (options.left != null) {\n\t\t\tprops.left = (options.left - curOffset.left) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[\"inner\" + name] = function() {\n\t\treturn this[0] ?\n\t\t\tparseFloat( jQuery.css( this[0], type, \"padding\" ) ) :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[\"outer\" + name] = function( margin ) {\n\t\treturn this[0] ?\n\t\t\tparseFloat( jQuery.css( this[0], type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ];\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\telem.document.body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNaN( ret ) ? orig : ret;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\nwindow.jQuery = window.$ = jQuery;\n})(window);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.7.1.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.1\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Mon Nov 21 21:11:03 2011 -0500\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.1\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!memory;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( window.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.style.width = \"2px\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = marginDiv = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tconMarginTop, ptlm, vb, style, html,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tptlm = \"position:absolute;top:0;left:0;width:1px;height:1px;margin:0;\";\n\t\tvb = \"visibility:hidden;border:0;\";\n\t\tstyle = \"style='\" + ptlm + \"border:5px solid #000;padding:0;'\";\n\t\thtml = \"<div \" + style + \"><div></div></div>\" +\n\t\t\t\"<table \" + style + \" cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = vb + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Figure out if the W3C box model works as expected\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\t\tjQuery.boxModel = support.boxModel = div.offsetWidth === 2;\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"\";\n\t\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t\t}\n\n\t\tdiv.style.cssText = ptlm + vb;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tbody.removeChild( container );\n\t\tdiv  = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, attr, name,\n\t\t\tdata = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 && !jQuery._data( this[0], \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = this[0].attributes;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( this[0], \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar self = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\tself.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( rboolean.test( name ) && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /\\bhover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !event.target.disabled && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\tselMatch = {};\n\t\t\t\tmatches = [];\n\t\t\t\tjqcur[0] = cur;\n\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( matches.length ) {\n\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on.call( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace? handleObj.type + \".\" + handleObj.namespace : handleObj.type,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( \n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ? \n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || !rnoshimcache.test( \"<\" + elem.nodeName ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWH( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat( value );\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret === null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ( ret || 0 );\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight,\n\t\ti = 0,\n\t\tlen = which.length;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + which[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + which[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ] || 0;\n\t}\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + which[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + which[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css(elem, \"display\") === \"none\" ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( self.options.hide && jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Adds width/height step functions\n// Do not set anything below 0\njQuery.each([ \"width\", \"height\" ], function( i, prop ) {\n\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t};\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( document.compatMode === \"CSS1Compat\" ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ],\n\t\t\t\tbody = elem.document.body;\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\tbody && body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.7.2.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfired = true;\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tpixelMargin: true\n\t};\n\n\t// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n\tjQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tmarginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n\t\t\tpaddingMarginBorderVisibility, paddingMarginBorder,\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tconMarginTop = 1;\n\t\tpaddingMarginBorder = \"padding:0;margin:0;border:\";\n\t\tpositionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n\t\tpaddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n\t\tstyle = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n\t\thtml = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n\t\t\t\"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t// gets computed margin-right based on width of container. For more\n\t\t// info see bug #3333\n\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tmarginDiv = document.createElement( \"div\" );\n\t\t\tmarginDiv.style.width = \"0\";\n\t\t\tmarginDiv.style.marginRight = \"0\";\n\t\t\tdiv.style.width = \"2px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.width = div.style.padding = \"1px\";\n\t\t\tdiv.style.border = 0;\n\t\t\tdiv.style.overflow = \"hidden\";\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div style='width:5px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\t\t}\n\n\t\tdiv.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdiv.style.marginTop = \"1%\";\n\t\t\tsupport.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n\t\t}\n\n\t\tif ( typeof container.style.zoom !== \"undefined\" ) {\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t\tmarginDiv = div = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( object );\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tquick: selector && quickParse( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process events on disabled elements (#6911, #8165)\n\t\t\t\tif ( cur.disabled !== true ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tjqcur[0] = cur;\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\t\t\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t/* falls through */\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.globalPOS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tnull;\n\t\t\t}\n\n\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\tdataType: \"script\"\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n\n\t// Clear flags for bubbling special change/submit events, they must\n\t// be reattached when the newly cloned events are first activated\n\tdest.removeAttribute( \"_submit_attached\" );\n\tdest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType, script, j,\n\t\t\t\tret = [];\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\"),\n\t\t\t\t\t\tsafeChildNodes = safeFragment.childNodes,\n\t\t\t\t\t\tremove;\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Clear elements from DocumentFragment (safeFragment or otherwise)\n\t\t\t\t\t// to avoid hoarding elements. Fixes #11356\n\t\t\t\t\tif ( div ) {\n\t\t\t\t\t\tdiv.parentNode.removeChild( div );\n\n\t\t\t\t\t\t// Guard against -1 index exceptions in FF3.6\n\t\t\t\t\t\tif ( safeChildNodes.length > 0 ) {\n\t\t\t\t\t\t\tremove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n\t\t\t\t\t\t\tif ( remove && remove.parentNode ) {\n\t\t\t\t\t\t\t\tremove.parentNode.removeChild( remove );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tscript = ret[i];\n\t\t\t\tif ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n\t\t\t\t\tscripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( script.nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( script );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n\trnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\trmargin = /^margin/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n\t// order is important!\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\treturn jQuery.access( this, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t}, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {},\n\t\t\tret, name;\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle, width,\n\t\t\tstyle = elem.style;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n\t\t// which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n\t\t\twidth = style.width;\n\t\t\tstyle.width = ret;\n\t\t\tret = computedStyle.width;\n\t\t\tstyle.width = width;\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( rnumnonpx.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\ti = name === \"width\" ? 1 : 0,\n\t\tlen = 4;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i += 2 ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ];\n\t}\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test(val) ) {\n\t\treturn val;\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i += 2 ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\treturn rnum.test( value ) ?\n\t\t\t\tvalue + \"px\" :\n\t\t\t\tvalue;\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"margin-right\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n});\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n\t\t\t\t\t\t!jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e, hooks, replace,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\t// first pass over propertys to expand / normalize\n\t\t\tfor ( p in prop ) {\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tif ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n\t\t\t\t\treplace = hooks.expand( prop[ name ] );\n\t\t\t\t\tdelete prop[ name ];\n\n\t\t\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t\t\t// also - reusing 'p' from above because we have the correct \"name\"\n\t\t\t\t\tfor ( p in replace ) {\n\t\t\t\t\t\tif ( ! ( p in prop ) ) {\n\t\t\t\t\t\t\tprop[ p ] = replace[ p ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( name in prop ) {\n\t\t\t\tval = prop[ name ];\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tif ( self.options.hide ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t\t} else if ( self.options.show ) {\n\t\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n\t// exclude marginTop, marginLeft, marginBottom and marginRight from this list\n\tif ( prop.indexOf( \"margin\" ) ) {\n\t\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t\t};\n\t}\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n\trtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tgetOffset = function( elem, doc, docElem, box ) {\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow( doc ),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tgetOffset = function( elem, doc, docElem ) {\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar elem = this[0],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn null;\n\t}\n\n\tif ( elem === doc.body ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\treturn getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tvar clientProp = \"client\" + name,\n\t\tscrollProp = \"scroll\" + name,\n\t\toffsetProp = \"offset\" + name;\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( value ) {\n\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\tvar doc, docElemProp, orig, ret;\n\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\t\tdoc = elem.document;\n\t\t\t\tdocElemProp = doc.documentElement[ clientProp ];\n\t\t\t\treturn jQuery.support.boxModel && docElemProp ||\n\t\t\t\t\tdoc.body && doc.body[ clientProp ] || docElemProp;\n\t\t\t}\n\n\t\t\t// Get document width or height\n\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t// when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n\t\t\t\t// so we can't use max, as it'll choose the incorrect offset[Width/Height]\n\t\t\t\t// instead we use the correct client[Width/Height]\n\t\t\t\t// support:IE6\n\t\t\t\tif ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n\t\t\t\t\treturn doc[ clientProp ];\n\t\t\t\t}\n\n\t\t\t\treturn Math.max(\n\t\t\t\t\telem.body[ scrollProp ], doc[ scrollProp ],\n\t\t\t\t\telem.body[ offsetProp ], doc[ offsetProp ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Get width or height on the element\n\t\t\tif ( value === undefined ) {\n\t\t\t\torig = jQuery.css( elem, type );\n\t\t\t\tret = parseFloat( orig );\n\t\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\t\t\t}\n\n\t\t\t// Set the width or height on the element\n\t\t\tjQuery( elem ).css( type, value );\n\t\t}, type, value, arguments.length, null );\n\t};\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery-1.7.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Thu Nov 3 16:18:21 2011 -0400\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Check for digits\n\trdigit = /\\d/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(\"#id\")\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.7\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn slice.call( this, 0 );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, +i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).unbind( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn obj != null && rdigit.test( obj ) && !isNaN( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow msg;\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// The extra typeof function check is to prevent crashes\n\t\t\t// in Safari 2 (See: #3039)\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in array && array[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar ret = [], retVal;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( var i = 0, length = elems.length; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar length = list.length;\n\t\t\t\t\tadd( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory || memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!memory;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\treturn deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar div = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tsupport,\n\t\tfragment,\n\t\tbody,\n\t\ttestElementParent,\n\t\ttestElement,\n\t\ttestElementStyle,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/><nav></nav>\";\n\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName( \"tbody\" ).length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName( \"link\" ).length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute( \"href\" ) === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.55/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure unknown elements (like HTML5 elems) are handled appropriately\n\t\tunknownElems: !!div.getElementsByTagName( \"nav\" ).length,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\tdiv.innerHTML = \"\";\n\n\t// Figure out if the W3C box model works as expected\n\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\n\t// We don't want to do body-related feature tests on frameset\n\t// documents, which lack a body. So we use\n\t// document.getElementsByTagName(\"body\")[0], which is undefined in\n\t// frameset documents, while document.body isn’t. (7398)\n\tbody = document.getElementsByTagName(\"body\")[ 0 ];\n\t// We use our own, invisible, body unless the body is already present\n\t// in which case we use a div (#9239)\n\ttestElement = document.createElement( body ? \"div\" : \"body\" );\n\ttestElementStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\tbackground: \"none\"\n\t};\n\tif ( body ) {\n\t\tjQuery.extend( testElementStyle, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: \"-999px\",\n\t\t\ttop: \"-999px\"\n\t\t});\n\t}\n\tfor ( i in testElementStyle ) {\n\t\ttestElement.style[ i ] = testElementStyle[ i ];\n\t}\n\ttestElement.appendChild( div );\n\ttestElementParent = body || documentElement;\n\ttestElementParent.insertBefore( testElement, testElementParent.firstChild );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tsupport.boxModel = div.offsetWidth === 2;\n\n\tif ( \"zoom\" in div.style ) {\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\t// (IE < 8 does this)\n\t\tdiv.style.display = \"inline\";\n\t\tdiv.style.zoom = 1;\n\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t// Check if elements with layout shrink-wrap their children\n\t\t// (IE 6 does this)\n\t\tdiv.style.display = \"\";\n\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t}\n\n\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\ttds = div.getElementsByTagName( \"td\" );\n\n\t// Check if table cells still have offsetWidth/Height when they are set\n\t// to display:none and there are still other visible table cells in a\n\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t// determining if an element has been hidden directly using\n\t// display:none (it is still safe to use offsets if a parent element is\n\t// hidden; don safety goggles and see bug #4512 for more information).\n\t// (only IE 8 fails this test)\n\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\ttds[ 0 ].style.display = \"\";\n\ttds[ 1 ].style.display = \"none\";\n\n\t// Check if empty table cells still have offsetWidth/Height\n\t// (IE < 8 fail this test)\n\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t} ) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\t// Run fixed position tests at doc ready to avoid a crash\n\t// related to the invisible body in IE8\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tconMarginTop = 1,\n\t\t\tptlm = \"position:absolute;top:0;left:0;width:1px;height:1px;margin:0;\",\n\t\t\tvb = \"visibility:hidden;border:0;\",\n\t\t\tstyle = \"style='\" + ptlm + \"border:5px solid #000;padding:0;'\",\n\t\t\thtml = \"<div \" + style + \"><div></div></div>\" +\n\t\t\t\t\t\t\t\"<table \" + style + \" cellpadding='0' cellspacing='0'>\" +\n\t\t\t\t\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\t// Reconstruct a container\n\t\tbody = document.getElementsByTagName(\"body\")[0];\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\t// These tests cannot be done\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = vb + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct a test element\n\t\ttestElement = document.createElement(\"div\");\n\t\ttestElement.style.cssText = ptlm + vb;\n\n\t\ttestElement.innerHTML = html;\n\t\tcontainer.appendChild( testElement );\n\t\touter = testElement.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tbody.removeChild( container );\n\t\ttestElement = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\ttestElement.innerHTML = \"\";\n\ttestElementParent.removeChild( testElement );\n\n\t// Null connected elements to avoid leaks in IE\n\ttestElement = fragment = select = opt = body = marginDiv = div = input = null;\n\n\treturn support;\n})();\n\n// Keep track of boxModel\njQuery.boxModel = jQuery.support.boxModel;\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ jQuery.expando ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = jQuery.expando;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support space separated names\n\t\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\t\tname = name;\n\t\t\t\t} else if ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ jQuery.expando ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t} else {\n\t\t\t\telem[ jQuery.expando ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, attr, name,\n\t\t\tdata = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 && !jQuery._data( this[0], \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = this[0].attributes;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( this[0], \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\t$this.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\t$this.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? parseFloat( data ) :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tfor ( var name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tfn = queue.shift(),\n\t\t\thooks = {};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.prop );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classNames, i, l, elem, className, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar self = jQuery(this), val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( !(\"getAttribute\" in elem) ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn undefined;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, \"\" + value );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, l,\n\t\t\ti = 0;\n\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tattrNames = ( value || \"\" ).split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ].toLowerCase();\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\tif ( rboolean.test( name ) && propName in elem ) {\n\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = \"\" + value );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\n\n\n\n\nvar rnamespaces = /\\.(.*)$/,\n\trformElems = /^(?:textarea|input|select)$/i,\n\trperiod = /\\./g,\n\trspaces = / /g,\n\trescape = /[^\\w\\s.|`]/g,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /\\bhover(\\.\\S+)?/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || elem.id === m[2]) &&\n\t\t\t(!m[3] || m[3].test( elem.className ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = hoverHack(types).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Delegated event; pre-analyze selector so it's processed quickly on event dispatch\n\t\t\tif ( selector ) {\n\t\t\t\thandleObj.quick = quickParse( selector );\n\t\t\t\tif ( !handleObj.quick && jQuery.expr.match.POS.test( selector ) ) {\n\t\t\t\t\thandleObj.isPositional = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector ) {\n\n\t\tvar elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = hoverHack( types || \"\" ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tnamespaces = namespaces? \".\" + namespaces : \"\";\n\t\t\t\tfor ( j in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, j + namespaces, handler, selector );\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Only need to loop for special events or selective removal\n\t\t\tif ( handler || namespaces || selector || special.remove ) {\n\t\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\t\tif ( !handler || handler.guid === handleObj.guid ) {\n\t\t\t\t\t\tif ( !namespaces || namespaces.test( handleObj.namespace ) ) {\n\t\t\t\t\t\t\tif ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) {\n\t\t\t\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Removing all events\n\t\t\t\teventType.length = 0;\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// triggerHandler() and global events don't bubble or run the default action\n\t\tif ( onlyHandlers || !elem ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\told = null;\n\t\t\tfor ( cur = elem.parentNode; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length; i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecialHandle = ( jQuery.event.special[ event.type ] || {} ).handle,\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, ret, selMatch, matched, matches, handleObj, sel, hit, related;\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !event.target.disabled && !(event.button && event.type === \"click\") ) {\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\tselMatch = {};\n\t\t\t\tmatches = [];\n\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\tsel = handleObj.selector;\n\t\t\t\t\thit = selMatch[ sel ];\n\n\t\t\t\t\tif ( handleObj.isPositional ) {\n\t\t\t\t\t\t// Since .is() does not work for positionals; see http://jsfiddle.net/eJ4yd/3/\n\t\t\t\t\t\thit = ( hit || (selMatch[ sel ] = jQuery( sel )) ).index( cur ) >= 0;\n\t\t\t\t\t} else if ( hit === undefined ) {\n\t\t\t\t\t\thit = selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jQuery( cur ).is( sel ) );\n\t\t\t\t\t}\n\t\t\t\t\tif ( hit ) {\n\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( matches.length ) {\n\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( specialHandle || handleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement wheelDelta\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\",\n\t\t\tnoBubble: true\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\",\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = jQuery.event.special[ fix ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\toldType, ret;\n\n\t\t\t// For a real mouseover/out, always call the handler; for\n\t\t\t// mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || handleObj.origType === event.type || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\toldType = event.type;\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = oldType;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\t// Form was submitted, bubble the event up the tree\n\t\t\t\t\t\tif ( this.parentNode ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\telem._change_attached = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on.call( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace? handleObj.type + \".\" + handleObj.namespace : handleObj.type,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( var type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.bind( name, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) \n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833) \n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && ( \n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\tPOS.test( selector ) ? \n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( elem.parentNode.firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.makeArray( elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until ),\n\t\t\t// The variable 'args' was introduced in\n\t\t\t// https://github.com/jquery/jquery/commit/52a0238\n\t\t\t// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.\n\t\t\t// http://code.google.com/p/v8/issues/detail?id=1050\n\t\t\targs = slice.call(arguments);\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, args.join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \" \" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr article aside audio canvas datalist details figcaption figure footer \" +\n\t\t\"header hgroup mark meter nav output progress section summary time video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames.replace(\" \", \"|\") + \")\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery( this ).wrapAll( html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery(arguments[0]);\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery(arguments[0]).toArray() );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\n\t\t}\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n  // Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(!jQuery.support.unknownElems && rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar clone = elem.cloneNode(true),\n\t\t\t\tsrcElements,\n\t\t\t\tdestElements,\n\t\t\t\ti;\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName\n\t\t\t// instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\n\t});\n};\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || origName;\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tcallback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWH( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat( value );\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( !(defaultView = elem.ownerDocument.defaultView) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret === null && style && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ( ret || 0 );\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tjQuery.each( which, function() {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ] || 0;\n\t}\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tjQuery.each( which, function() {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + this ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + this ) ) || 0;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn val + \"px\";\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.bind( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.error( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\n\t\t});\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( jsonpCallback + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occured\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css(elem, \"display\") === \"none\" ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar i,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, i ) {\n\t\t\t\tvar hooks = data[ i ];\n\t\t\t\tjQuery.removeData( elem, i, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( i in data ) {\n\t\t\t\t\tif ( data[ i ].stop && i.indexOf(\".run\") === i.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, i );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ i = type + \".run\" ] && data[ i ].stop ){\n\t\t\t\tstopQueue( this, data, i );\n\t\t\t}\n\n\t\t\tfor ( i = timers.length; i--; ) {\n\t\t\t\tif ( timers[ i ].elem === this && (type == null || timers[ i ].queue === type) ) {\n\t\t\t\t\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ i ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ i ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\n\t\t\t\t\ttimers.splice( i, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( self.options.hide && jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Adds width/height step functions\n// Do not set anything below 0\njQuery.each([ \"width\", \"height\" ], function( i, prop ) {\n\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) );\n\t};\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( document.compatMode === \"CSS1Compat\" ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ],\n\t\t\t\tbody = elem.document.body;\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\tbody && body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n})( window );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery.js",
    "content": "(function() {\n\nvar parts = document.location.search.slice( 1 ).split( \"&\" ),\n\tlength = parts.length,\n\ti = 0,\n\tcurrent,\n\tversion,\n\turl;\n\nfor ( ; i < length; i++ ) {\n\tcurrent = parts[ i ].split( \"=\" );\n\tif ( current[ 0 ] === \"jquery\" ) {\n\t\tversion = current[ 1 ];\n\t\tbreak;\n\t}\n}\n\nif ( version === \"git\" ) {\n\turl = \"http://code.jquery.com/jquery-git.js\";\n} else {\n\turl = \"../../jquery-\" + ( version || \"1.7.2\" ) + \".js\";\n}\n\ndocument.write( \"<script src='\" + url + \"'></script>\" );\n\n}() );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/jquery.simulate.js",
    "content": "/*\n * jquery.simulate - simulate browser mouse and keyboard events\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n */\n\n;(function( $ ) {\n\nvar rkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/;\n\n$.fn.simulate = function( type, options ) {\n\treturn this.each(function() {\n\t\tnew $.simulate( this, type, options );\n\t});\n};\n\n$.simulate = function( elem, type, options ) {\n\tvar method = $.camelCase( \"simulate-\" + type );\n\n\tthis.target = elem;\n\tthis.options = options;\n\n\tif ( this[ method ] ) {\n\t\tthis[ method ]();\n\t} else {\n\t\tthis.simulateEvent( elem, type, options );\n\t}\n};\n\n$.extend( $.simulate.prototype, {\n\tsimulateEvent: function( elem, type, options ) {\n\t\tvar event = this.createEvent( type, options );\n\t\tthis.dispatchEvent( elem, type, event, options );\n\t},\n\n\tcreateEvent: function( type, options ) {\n\t\tif ( rkeyEvent.test( type ) ) {\n\t\t\treturn this.keyEvent( type, options );\n\t\t}\n\n\t\tif ( rmouseEvent.test( type ) ) {\n\t\t\treturn this.mouseEvent( type, options );\n\t\t}\n\t},\n\n\tmouseEvent: function( type, options ) {\n\t\tvar event, eventDoc, doc, body;\n\t\toptions = $.extend({\n\t\t\tbubbles: true,\n\t\t\tcancelable: (type !== \"mousemove\"),\n\t\t\tview: window,\n\t\t\tdetail: 0,\n\t\t\tscreenX: 0,\n\t\t\tscreenY: 0,\n\t\t\t// TODO: default clientX/Y to a position within the target element\n\t\t\tclientX: 1,\n\t\t\tclientY: 1,\n\t\t\tctrlKey: false,\n\t\t\taltKey: false,\n\t\t\tshiftKey: false,\n\t\t\tmetaKey: false,\n\t\t\tbutton: 0,\n\t\t\trelatedTarget: undefined\n\t\t}, options );\n\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent( \"MouseEvents\" );\n\t\t\tevent.initMouseEvent( type, options.bubbles, options.cancelable,\n\t\t\t\toptions.view, options.detail,\n\t\t\t\toptions.screenX, options.screenY, options.clientX, options.clientY,\n\t\t\t\toptions.ctrlKey, options.altKey, options.shiftKey, options.metaKey,\n\t\t\t\toptions.button, options.relatedTarget || document.body.parentNode );\n\n\t\t\t// IE 9+ creates events with pageX and pageY set to 0.\n\t\t\t// Trying to modify the properties throws an error,\n\t\t\t// so we define getters to return the correct values.\n\t\t\tif ( event.pageX === 0 && event.pageY === 0 && Object.defineProperty ) {\n\t\t\t\teventDoc = event.relatedTarget.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tObject.defineProperty( event, \"pageX\", {\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\treturn options.clientX +\n\t\t\t\t\t\t\t( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -\n\t\t\t\t\t\t\t( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tObject.defineProperty( event, \"pageY\", {\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\treturn options.clientY +\n\t\t\t\t\t\t\t( doc && doc.scrollTop || body && body.scrollTop || 0 ) -\n\t\t\t\t\t\t\t( doc && doc.clientTop || body && body.clientTop || 0 );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} else if ( document.createEventObject ) {\n\t\t\tevent = document.createEventObject();\n\t\t\t$.extend( event, options );\n\t\t\t// TODO: what is this mapping for?\n\t\t\tevent.button = { 0:1, 1:4, 2:2 }[ event.button ] || event.button;\n\t\t}\n\n\t\treturn event;\n\t},\n\n\tkeyEvent: function( type, options ) {\n\t\tvar event;\n\t\toptions = $.extend({\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t\tview: window,\n\t\t\tctrlKey: false,\n\t\t\taltKey: false,\n\t\t\tshiftKey: false,\n\t\t\tmetaKey: false,\n\t\t\tkeyCode: 0,\n\t\t\tcharCode: undefined\n\t\t}, options );\n\n\t\tif ( document.createEvent ) {\n\t\t\ttry {\n\t\t\t\tevent = document.createEvent( \"KeyEvents\" );\n\t\t\t\tevent.initKeyEvent( type, options.bubbles, options.cancelable, options.view,\n\t\t\t\t\toptions.ctrlKey, options.altKey, options.shiftKey, options.metaKey,\n\t\t\t\t\toptions.keyCode, options.charCode );\n\t\t\t// TODO: what is this supporting?\n\t\t\t} catch( err ) {\n\t\t\t\tevent = document.createEvent( \"Events\" );\n\t\t\t\tevent.initEvent( type, options.bubbles, options.cancelable );\n\t\t\t\t$.extend( event, {\n\t\t\t\t\tview: options.view,\n\t\t\t\t\tctrlKey: options.ctrlKey,\n\t\t\t\t\taltKey: options.altKey,\n\t\t\t\t\tshiftKey: options.shiftKey,\n\t\t\t\t\tmetaKey: options.metaKey,\n\t\t\t\t\tkeyCode: options.keyCode,\n\t\t\t\t\tcharCode: options.charCode\n\t\t\t\t});\n\t\t\t}\n\t\t} else if ( document.createEventObject ) {\n\t\t\tevent = document.createEventObject();\n\t\t\t$.extend( event, options );\n\t\t}\n\n\t\t// TODO: can we hook into core's logic?\n\t\tif ( $.browser.msie || $.browser.opera ) {\n\t\t\t// TODO: is charCode ever <0 ? Can we just use charCode || keyCode?\n\t\t\tevent.keyCode = (options.charCode > 0) ? options.charCode : options.keyCode;\n\t\t\tevent.charCode = undefined;\n\t\t}\n\n\t\treturn event;\n\t},\n\n\t// TODO: does this need type? Can't we just check event.type?\n\tdispatchEvent: function( elem, type, event ) {\n\t\tif ( elem.dispatchEvent ) {\n\t\t\telem.dispatchEvent( event );\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent( \"on\" + type, event );\n\t\t}\n\t},\n\n\tsimulateFocus: function() {\n\t\tvar focusinEvent,\n\t\t\ttriggered = false,\n\t\t\telement = $( this.target );\n\n\t\tfunction trigger() {\n\t\t\ttriggered = true;\n\t\t}\n\n\t\telement.bind( \"focus\", trigger );\n\t\telement[ 0 ].focus();\n\n\t\tif ( !triggered ) {\n\t\t\tfocusinEvent = $.Event( \"focusin\" );\n\t\t\tfocusinEvent.preventDefault();\n\t\t\telement.trigger( focusinEvent );\n\t\t\telement.triggerHandler( \"focus\" );\n\t\t}\n\t\telement.unbind( \"focus\", trigger );\n\t},\n\n\tsimulateBlur: function() {\n\t\tvar focusoutEvent,\n\t\t\ttriggered = false,\n\t\t\telement = $( this.target );\n\n\t\tfunction trigger() {\n\t\t\ttriggered = true;\n\t\t}\n\n\t\telement.bind( \"blur\", trigger );\n\t\telement[ 0 ].blur();\n\n\t\t// blur events are async in IE\n\t\tsetTimeout(function() {\n\t\t\t// IE won't let the blur occur if the window is inactive\n\t\t\tif ( element[ 0 ].ownerDocument.activeElement === element[ 0 ] ) {\n\t\t\t\telement[ 0 ].ownerDocument.body.focus();\n\t\t\t}\n\n\t\t\t// Firefox won't trigger events if the window is inactive\n\t\t\t// IE doesn't trigger events if we had to manually focus the body\n\t\t\tif ( !triggered ) {\n\t\t\t\tfocusoutEvent = $.Event( \"focusout\" );\n\t\t\t\tfocusoutEvent.preventDefault();\n\t\t\t\telement.trigger( focusoutEvent );\n\t\t\t\telement.triggerHandler( \"blur\" );\n\t\t\t}\n\t\t\telement.unbind( \"blur\", trigger );\n\t\t}, 1 );\n\t}\n});\n\n\n\n/** complex events **/\n\nfunction findCenter( elem ) {\n\tvar offset,\n\t\tdocument = $( elem.ownerDocument );\n\telem = $( elem );\n\toffset = elem.offset();\n\t\n\treturn {\n\t\tx: offset.left + elem.outerWidth() / 2 - document.scrollLeft(),\n\t\ty: offset.top + elem.outerHeight() / 2 - document.scrollTop()\n\t};\n}\n\n$.extend( $.simulate.prototype, {\n\tsimulateDrag: function() {\n\t\tvar target = this.target,\n\t\t\toptions = this.options,\n\t\t\tcenter = findCenter( target ),\n\t\t\tx = Math.floor( center.x ),\n\t\t\ty = Math.floor( center.y ), \n\t\t\tdx = options.dx || 0,\n\t\t\tdy = options.dy || 0,\n\t\t\tcoord = { clientX: x, clientY: y };\n\t\tthis.simulateEvent( target, \"mousedown\", coord );\n\t\tcoord = { clientX: x + 1, clientY: y + 1 };\n\t\tthis.simulateEvent( document, \"mousemove\", coord );\n\t\tcoord = { clientX: x + dx, clientY: y + dy };\n\t\tthis.simulateEvent( document, \"mousemove\", coord );\n\t\tthis.simulateEvent( document, \"mousemove\", coord );\n\t\tthis.simulateEvent( target, \"mouseup\", coord );\n\t\tthis.simulateEvent( target, \"click\", coord );\n\t}\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script>\n\t$.uiBackCompat = false;\n\t</script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.accordion\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.accordion.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"accordion_test_helpers.js\"></script>\n\t<script src=\"accordion_common.js\"></script>\n\t<script src=\"accordion_core.js\"></script>\n\t<script src=\"accordion_events.js\"></script>\n\t<script src=\"accordion_methods.js\"></script>\n\t<script src=\"accordion_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t#list, #list1 *, #navigation, #navigation * {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tfont-size: 12px;\n\t\tline-height: 15px;\n\t}\n\t</style>\n</head>\n<body>\n<h1 id=\"qunit-header\">jQuery UI Accordion Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"list1\" class=\"foo\">\n\t<h3 class=\"bar\">There is one obvious advantage:</h3>\n\t<div class=\"foo\">\n\t\t<p>\n\t\t\tYou've seen it coming!\n\t\t\t<br>\n\t\t\tBuy now and get nothing for free!\n\t\t\t<br>\n\t\t\tWell, at least no free beer. Perhaps a bear, if you can afford it.\n\t\t</p>\n\t</div>\n\t<h3 class=\"bar\">Now that you've got...</h3>\n\t<div class=\"foo\">\n\t\t<p>\n\t\t\tyour bear, you have to admit it!\n\t\t\t<br>\n\t\t\tNo, we aren't <a href=\"#\">selling bears</a>.\n\t\t</p>\n\t\t<p>\n\t\t\tWe could talk about renting one.\n\t\t</p>\n\t</div>\n\t<h3 class=\"bar\">Rent one bear, ...</h3>\n\t<div class=\"foo\">\n\t\t<p>\n\t\t\tget two for three beer.\n\t\t</p>\n\t\t<p>\n\t\t\tAnd now, for something completely different.\n\t\t</p>\n\t</div>\n</div>\n\n<div id=\"navigationWrapper\">\n\t<ul id=\"navigation\">\n\t\t<li>\n\t\t\t<h2><a href=\"?p=1.1.1\">Guitar</a></h2>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?p=1.1.1.1\">Electric</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.2\">Acoustic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.3\">Amps</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.4\">Effects</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.5\">Accessories</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li>\n\t\t\t<h2><a href=\"?p=1.1.2\"><span>Bass</span></a></h2>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?p=1.1.2.1\">Electric</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.2\">Acoustic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.3\">Amps</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.4\">Effects</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.5\">Accessories</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.5\">Accessories</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.5\">Accessories</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li>\n\t\t\t<h2><a href=\"?p=1.1.3\">Drums</a></h2>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?p=1.1.3.2\">Acoustic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.3.3\">Electronic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.3.6\">Accessories</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t</ul>\n</div>\n\n<dl id=\"accordion-dl\">\n\t<dt>\n\t\tAccordion Header 1\n\t</dt>\n\t<dd>\n\t\tAccordion Content 1\n\t</dd>\n\t<dt>\n\t\tAccordion Header 2\n\t</dt>\n\t<dd>\n\t\tAccordion Content 2\n\t</dd>\n\t<dt>\n\t\tAccordion Header 3\n\t</dt>\n\t<dd>\n\t\tAccordion Content 3\n\t</dd>\n</dl>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_common.js",
    "content": "TestHelpers.commonWidgetTests( \"accordion\", {\n\tdefaults: {\n\t\tactive: 0,\n\t\tanimate: {},\n\t\tcollapsible: false,\n\t\tdisabled: false,\n\t\tevent: \"click\",\n\t\theader: \"> li > :first-child,> :not(li):even\",\n\t\theightStyle: \"auto\",\n\t\ticons: {\n\t\t\t\"activeHeader\": \"ui-icon-triangle-1-s\",\n\t\t\t\"header\": \"ui-icon-triangle-1-e\"\n\t\t},\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_common_deprecated.js",
    "content": "TestHelpers.commonWidgetTests( \"accordion\", {\n\tdefaults: {\n\t\tactive: 0,\n\t\tanimate: null,\n\t\tanimated: \"slide\",\n\t\tautoHeight: true,\n\t\tclearStyle: false,\n\t\tcollapsible: false,\n\t\tdisabled: false,\n\t\tevent: \"click\",\n\t\tfillSpace: false,\n\t\theader: \"> li > :first-child,> :not(li):even\",\n\t\theightStyle: null,\n\t\ticons: {\n\t\t\t\"activeHeader\": null,\n\t\t\t\"header\": \"ui-icon-triangle-1-e\",\n\t\t\t\"headerSelected\": \"ui-icon-triangle-1-s\"\n\t\t},\n\t\tnavigation: false,\n\t\tnavigationFilter: function() {},\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tchange: null,\n\t\tchangestart: null,\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_core.js",
    "content": "(function( $ ) {\n\nvar setupTeardown = TestHelpers.accordion.setupTeardown,\n\tstate = TestHelpers.accordion.state;\n\nmodule( \"accordion: core\", setupTeardown() );\n\n$.each( { div: \"#list1\", ul: \"#navigation\", dl: \"#accordion-dl\" }, function( type, selector ) {\n\ttest( \"markup structure: \" + type, function() {\n\t\texpect( 4 );\n\t\tvar element = $( selector ).accordion();\n\t\tok( element.hasClass( \"ui-accordion\" ), \"main element is .ui-accordion\" );\n\t\tequal( element.find( \".ui-accordion-header\" ).length, 3,\n\t\t\t\".ui-accordion-header elements exist, correct number\" );\n\t\tequal( element.find( \".ui-accordion-content\" ).length, 3,\n\t\t\t\".ui-accordion-content elements exist, correct number\" );\n\t\tdeepEqual( element.find( \".ui-accordion-header\" ).next().get(),\n\t\t\telement.find( \".ui-accordion-content\" ).get(),\n\t\t\t\"content panels come immediately after headers\" );\n\t});\n});\n\ntest( \"handle click on header-descendant\", function() {\n\texpect( 1 );\n\tvar element = $( \"#navigation\" ).accordion();\n\t$( \"#navigation h2:eq(1) a\" ).click();\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"accessibility\", function () {\n\texpect( 37 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: 1\n\t\t}),\n\t\theaders = element.find( \".ui-accordion-header\" );\n\n\tequal( element.attr( \"role\" ), \"tablist\", \"element role\" );\n\theaders.each(function( i ) {\n\t\tvar header = headers.eq( i ),\n\t\t\tpanel = header.next();\n\t\tequal( header.attr( \"role\" ), \"tab\", \"header \" + i + \" role\" );\n\t\tequal( header.attr( \"aria-controls\" ), panel.attr( \"id\" ), \"header \" + i + \" aria-controls\" );\n\t\tequal( panel.attr( \"role\" ), \"tabpanel\", \"panel \" + i + \" role\" );\n\t\tequal( panel.attr( \"aria-labelledby\" ), header.attr( \"id\" ), \"panel \" + i + \" aria-labelledby\" );\n\t});\n\n\tequal( headers.eq( 1 ).attr( \"tabindex\" ), 0, \"active header has tabindex=0\" );\n\tequal( headers.eq( 1 ).attr( \"aria-selected\" ), \"true\", \"active tab has aria-selected=true\" );\n\tequal( headers.eq( 1 ).next().attr( \"aria-expanded\" ), \"true\", \"active tabpanel has aria-expanded=true\" );\n\tequal( headers.eq( 1 ).next().attr( \"aria-hidden\" ), \"false\", \"active tabpanel has aria-hidden=false\" );\n\tequal( headers.eq( 0 ).attr( \"tabindex\" ), -1, \"inactive header has tabindex=-1\" );\n\tequal( headers.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( headers.eq( 0 ).next().attr( \"aria-expanded\" ), \"false\", \"inactive tabpanel has aria-expanded=false\" );\n\tequal( headers.eq( 0 ).next().attr( \"aria-hidden\" ), \"true\", \"inactive tabpanel has aria-hidden=true\" );\n\tequal( headers.eq( 2 ).attr( \"tabindex\" ), -1, \"inactive header has tabindex=-1\" );\n\tequal( headers.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( headers.eq( 2 ).next().attr( \"aria-expanded\" ), \"false\", \"inactive tabpanel has aria-expanded=false\" );\n\tequal( headers.eq( 2 ).next().attr( \"aria-hidden\" ), \"true\", \"inactive tabpanel has aria-hidden=true\" );\n\n\telement.accordion( \"option\", \"active\", 0 );\n\tequal( headers.eq( 0 ).attr( \"tabindex\" ), 0, \"active header has tabindex=0\" );\n\tequal( headers.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"active tab has aria-selected=true\" );\n\tequal( headers.eq( 0 ).next().attr( \"aria-expanded\" ), \"true\", \"active tabpanel has aria-expanded=true\" );\n\tequal( headers.eq( 0 ).next().attr( \"aria-hidden\" ), \"false\", \"active tabpanel has aria-hidden=false\" );\n\tequal( headers.eq( 1 ).attr( \"tabindex\" ), -1, \"inactive header has tabindex=-1\" );\n\tequal( headers.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( headers.eq( 1 ).next().attr( \"aria-expanded\" ), \"false\", \"inactive tabpanel has aria-expanded=false\" );\n\tequal( headers.eq( 1 ).next().attr( \"aria-hidden\" ), \"true\", \"inactive tabpanel has aria-hidden=true\" );\n\tequal( headers.eq( 2 ).attr( \"tabindex\" ), -1, \"inactive header has tabindex=-1\" );\n\tequal( headers.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( headers.eq( 2 ).next().attr( \"aria-expanded\" ), \"false\", \"inactive tabpanel has aria-expanded=false\" );\n\tequal( headers.eq( 2 ).next().attr( \"aria-hidden\" ), \"true\", \"inactive tabpanel has aria-hidden=true\" );\n});\n\nasyncTest( \"keyboard support\", function() {\n\texpect( 13 );\n\tvar element = $( \"#list1\" ).accordion(),\n\t\theaders = element.find( \".ui-accordion-header\" ),\n\t\tanchor = headers.eq( 1 ).next().find( \"a\" ).eq( 0 ),\n\t\tkeyCode = $.ui.keyCode;\n\tequal( headers.filter( \".ui-state-focus\" ).length, 0, \"no headers focused on init\" );\n\theaders.eq( 0 ).simulate( \"focus\" );\n\tsetTimeout(function() {\n\t\tok( headers.eq( 0 ).is( \".ui-state-focus\" ), \"first header has focus\" );\n\t\theaders.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.DOWN } );\n\t\tok( headers.eq( 1 ).is( \".ui-state-focus\" ), \"DOWN moves focus to next header\" );\n\t\theaders.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.RIGHT } );\n\t\tok( headers.eq( 2 ).is( \".ui-state-focus\" ), \"RIGHT moves focus to next header\" );\n\t\theaders.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.DOWN } );\n\t\tok( headers.eq( 0 ).is( \".ui-state-focus\" ), \"DOWN wraps focus to first header\" );\n\n\t\theaders.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.UP } );\n\t\tok( headers.eq( 2 ).is( \".ui-state-focus\" ), \"UP wraps focus to last header\" );\n\t\theaders.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.LEFT } );\n\t\tok( headers.eq( 1 ).is( \".ui-state-focus\" ), \"LEFT moves focus to previous header\" );\n\n\t\theaders.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.HOME } );\n\t\tok( headers.eq( 0 ).is( \".ui-state-focus\" ), \"HOME moves focus to first header\" );\n\t\theaders.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.END } );\n\t\tok( headers.eq( 2 ).is( \".ui-state-focus\" ), \"END moves focus to last header\" );\n\n\t\theaders.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.ENTER } );\n\t\tequal( element.accordion( \"option\", \"active\" ) , 2, \"ENTER activates panel\" );\n\t\theaders.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.SPACE } );\n\t\tequal( element.accordion( \"option\", \"active\" ), 1, \"SPACE activates panel\" );\n\n\t\tanchor.simulate( \"focus\" );\n\t\tsetTimeout(function() {\n\t\t\tok( !headers.eq( 1 ).is( \".ui-state-focus\" ), \"header loses focus when focusing inside the panel\" );\n\t\t\tanchor.simulate( \"keydown\", { keyCode: keyCode.UP, ctrlKey: true } );\n\t\t\tok( headers.eq( 1 ).is( \".ui-state-focus\" ), \"CTRL+UP moves focus to header\" );\n\t\t\tstart();\n\t\t}, 1 );\n\t}, 1 );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_deprecated.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.accordion\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.accordion.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"accordion_test_helpers.js\"></script>\n\t<script src=\"accordion_common_deprecated.js\"></script>\n\t<script src=\"accordion_core.js\"></script>\n\t<script src=\"accordion_events.js\"></script>\n\t<script src=\"accordion_methods.js\"></script>\n\t<script src=\"accordion_options.js\"></script>\n\t<script src=\"accordion_deprecated.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t#list, #list1 *, #navigation, #navigation * {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tfont-size: 12px;\n\t\tline-height: 15px;\n\t}\n\t</style>\n</head>\n<body>\n<h1 id=\"qunit-header\">jQuery UI Accordion Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"list1\" class=\"foo\">\n\t<h3 class=\"bar\">There is one obvious advantage:</h3>\n\t<div class=\"foo\">\n\t\t<p>\n\t\t\tYou've seen it coming!\n\t\t\t<br>\n\t\t\tBuy now and get nothing for free!\n\t\t\t<br>\n\t\t\tWell, at least no free beer. Perhaps a bear, if you can afford it.\n\t\t</p>\n\t</div>\n\t<h3 class=\"bar\">Now that you've got...</h3>\n\t<div class=\"foo\">\n\t\t<p>\n\t\t\tyour bear, you have to admit it!\n\t\t\t<br>\n\t\t\tNo, we aren't <a href=\"#\">selling bears</a>.\n\t\t</p>\n\t\t<p>\n\t\t\tWe could talk about renting one.\n\t\t</p>\n\t</div>\n\t<h3 class=\"bar\">Rent one bear, ...</h3>\n\t<div class=\"foo\">\n\t\t<p>\n\t\t\tget two for three beer.\n\t\t</p>\n\t\t<p>\n\t\t\tAnd now, for something completely different.\n\t\t</p>\n\t</div>\n</div>\n\n<div id=\"navigationWrapper\">\n\t<ul id=\"navigation\">\n\t\t<li>\n\t\t\t<h2><a href=\"?p=1.1.1\">Guitar</a></h2>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?p=1.1.1.1\">Electric</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.2\">Acoustic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.3\">Amps</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.4\">Effects</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.1.5\">Accessories</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li>\n\t\t\t<h2><a href=\"?p=1.1.2\"><span>Bass</span></a></h2>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?p=1.1.2.1\">Electric</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.2\">Acoustic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.3\">Amps</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.4\">Effects</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.5\">Accessories</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.5\">Accessories</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.2.5\">Accessories</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li>\n\t\t\t<h2><a href=\"?p=1.1.3\">Drums</a></h2>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"?p=1.1.3.2\">Acoustic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.3.3\">Electronic</a></li>\n\t\t\t\t<li><a href=\"?p=1.1.3.6\">Accessories</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t</ul>\n</div>\n\n<dl id=\"accordion-dl\">\n\t<dt>\n\t\tAccordion Header 1\n\t</dt>\n\t<dd>\n\t\tAccordion Content 1\n\t</dd>\n\t<dt>\n\t\tAccordion Header 2\n\t</dt>\n\t<dd>\n\t\tAccordion Content 2\n\t</dd>\n\t<dt>\n\t\tAccordion Header 3\n\t</dt>\n\t<dd>\n\t\tAccordion Content 3\n\t</dd>\n</dl>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_deprecated.js",
    "content": "(function( $ ) {\n\nvar equalHeight = TestHelpers.accordion.equalHeight,\n\tsetupTeardown = TestHelpers.accordion.setupTeardown,\n\tstate = TestHelpers.accordion.state;\n\nmodule( \"accordion (deprecated): expanded active option, activate method\", setupTeardown() );\n\ntest( \"activate, numeric\", function() {\n\texpect( 5 );\n\tvar element = $( \"#list1\" ).accordion({ active: 1 });\n\tstate( element, 0, 1, 0 );\n\telement.accordion( \"activate\", 2 );\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"activate\", 0 );\n\tstate( element, 1, 0, 0 );\n\telement.accordion( \"activate\", 1 );\n\tstate( element, 0, 1, 0 );\n\telement.accordion( \"activate\", 2 );\n\tstate( element, 0, 0, 1 );\n});\n\ntest( \"activate, numeric, collapsible:true\", function() {\n\texpect( 3 );\n\tvar element = $( \"#list1\" ).accordion({ collapsible: true });\n\telement.accordion( \"activate\", 2 );\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"activate\", 0 );\n\tstate( element, 1, 0, 0 );\n\telement.accordion( \"activate\", -1 );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"activate, boolean, collapsible: true\", function() {\n\texpect( 2 );\n\tvar element = $( \"#list1\" ).accordion({ collapsible: true });\n\telement.accordion( \"activate\", 2 );\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"activate\", false );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"activate, boolean, collapsible: false\", function() {\n\texpect( 2 );\n\tvar element = $( \"#list1\" ).accordion();\n\telement.accordion( \"activate\", 2 );\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"activate\", false );\n\tstate( element, 0, 0, 1 );\n});\n\ntest( \"activate, string expression\", function() {\n\texpect( 4 );\n\tvar element = $( \"#list1\" ).accordion({ active: \"h3:last\" });\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"activate\", \":first\" );\n\tstate( element, 1, 0, 0 );\n\telement.accordion( \"activate\", \":eq(1)\" );\n\tstate( element, 0, 1, 0 );\n\telement.accordion( \"activate\", \":last\" );\n\tstate( element, 0, 0, 1 );\n});\n\ntest( \"activate, jQuery or DOM element\", function() {\n\texpect( 3 );\n\tvar element = $( \"#list1\" ).accordion({ active: $( \"#list1 h3:last\" ) });\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"activate\", $( \"#list1 h3:first\" ) );\n\tstate( element, 1, 0, 0 );\n\telement.accordion( \"activate\", $( \"#list1 h3\" )[ 1 ] );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ active: Selector }\", function() {\n\texpect( 2 );\n\tvar element = $(\"#list1\").accordion({\n\t\tactive: \"h3:last\"\n\t});\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"option\", \"active\", \"h3:eq(1)\" );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ active: Element }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tactive: $( \"#list1 h3:last\" )[ 0 ]\n\t});\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"option\", \"active\", $( \"#list1 h3:eq(1)\" )[ 0 ] );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ active: jQuery Object }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tactive: $( \"#list1 h3:last\" )\n\t});\n\tstate( element, 0, 0, 1 );\n\telement.accordion( \"option\", \"active\", $( \"#list1 h3:eq(1)\" ) );\n\tstate( element, 0, 1, 0 );\n});\n\n\n\n\n\nmodule( \"accordion (deprecated) - height options\", setupTeardown() );\n\ntest( \"{ autoHeight: true }, default\", function() {\n\texpect( 3 );\n\tequalHeight( $( \"#navigation\" ).accordion({ autoHeight: true }), 105 );\n});\n\ntest( \"{ autoHeight: false }\", function() {\n\texpect( 3 );\n\tvar element = $( \"#navigation\" ).accordion({ autoHeight: false }),\n\t\tsizes = [];\n\telement.find( \".ui-accordion-content\" ).each(function() {\n\t\tsizes.push( $(this).height() );\n\t});\n\tok( sizes[0] >= 70 && sizes[0] <= 105, \"was \" + sizes[0] );\n\tok( sizes[1] >= 98 && sizes[1] <= 126, \"was \" + sizes[1] );\n\tok( sizes[2] >= 42 && sizes[2] <= 54, \"was \" + sizes[2] );\n});\n\ntest( \"{ fillSpace: true }\", function() {\n\texpect( 3 );\n\t$( \"#navigationWrapper\" ).height( 500 );\n\tvar element = $( \"#navigation\" ).accordion({ fillSpace: true });\n\tequalHeight( element, 455 );\n});\n\ntest( \"{ fillSapce: true } with sibling\", function() {\n\texpect( 3 );\n\t$( \"#navigationWrapper\" ).height( 500 );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\tvar element = $( \"#navigation\" ).accordion({ fillSpace: true });\n\tequalHeight( element , 355 );\n});\n\ntest( \"{ fillSpace: true } with multiple siblings\", function() {\n\texpect( 3 );\n\t$( \"#navigationWrapper\" ).height( 500 );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30,\n\t\t\tposition: \"absolute\"\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 25,\n\t\t\tmarginTop: 10,\n\t\t\tmarginBottom: 15\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\tvar element = $( \"#navigation\" ).accordion({ fillSpace: true });\n\tequalHeight( element, 305 );\n});\n\n\n\n\n\nmodule( \"accordion (deprecated) - icons\", setupTeardown() );\n\ntest( \"icons, headerSelected\", function() {\n\texpect( 3 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\ticons: { headerSelected: \"a1\", header: \"h1\" }\n\t});\n\tok( element.find( \".ui-accordion-header.ui-state-active span.ui-icon\" ).hasClass( \"a1\" ) );\n\telement.accordion( \"option\", \"icons\", { headerSelected: \"a2\", header: \"h2\" } );\n\tok( !element.find( \".ui-accordion-header.ui-state-active span.ui-icon\" ).hasClass( \"a1\" ) );\n\tok( element.find( \".ui-accordion-header.ui-state-active span.ui-icon\" ).hasClass( \"a2\" ) );\n});\n\n\n\n\n\nmodule( \"accordion (deprecated) - resize\", setupTeardown() );\n\ntest( \"resize\", function() {\n\texpect( 6 );\n\tvar element = $( \"#navigation\" )\n\t\t.parent()\n\t\t\t.height( 300 )\n\t\t.end()\n\t\t.accordion({\n\t\t\theightStyle: \"fill\"\n\t\t});\n\tequalHeight( element, 255 );\n\n\telement.parent().height( 500 );\n\telement.accordion( \"resize\" );\n\tequalHeight( element, 455 );\n});\n\n\n\n\n\nmodule( \"accordion (deprecated) - navigation\", setupTeardown() );\n\ntest( \"{ navigation: true, navigationFilter: header }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#navigation\" ).accordion({\n\t\tnavigation: true,\n\t\tnavigationFilter: function() {\n\t\t\treturn (/\\?p=1\\.1\\.3$/).test( this.href );\n\t\t}\n\t});\n\tequal( element.accordion( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n});\n\ntest( \"{ navigation: true, navigationFilter: content }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#navigation\" ).accordion({\n\t\tnavigation: true,\n\t\tnavigationFilter: function() {\n\t\t\treturn (/\\?p=1\\.1\\.3\\.2$/).test( this.href );\n\t\t}\n\t});\n\tequal( element.accordion( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n});\n\n\n\n\n\nmodule( \"accordion (deprecated) - changestart/change events\", setupTeardown() );\n\ntest( \"changestart\", function() {\n\texpect( 26 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\theaders = element.find( \".ui-accordion-header\" ),\n\t\tcontent = element.find( \".ui-accordion-content\" );\n\n\telement.one( \"accordionchangestart\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 0 );\n\t\tequal( ui.oldContent.length, 0 );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.newContent.length, 1 );\n\t\tstrictEqual( ui.newContent[ 0 ], content[ 0 ] );\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", 0 );\n\tstate( element, 1, 0, 0 );\n\n\telement.one( \"accordionchangestart\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.oldContent.length, 1 );\n\t\tstrictEqual( ui.oldContent[ 0 ], content[ 0 ] );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.newContent.length, 1 );\n\t\tstrictEqual( ui.newContent[ 0 ], content[ 1 ] );\n\t\tstate( element, 1, 0, 0 );\n\t});\n\theaders.eq( 1 ).click();\n\tstate( element, 0, 1, 0 );\n\n\telement.one( \"accordionchangestart\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.oldContent.length, 1 );\n\t\tstrictEqual( ui.oldContent[ 0 ], content[ 1 ] );\n\t\tequal( ui.newHeader.length, 0 );\n\t\tequal( ui.newContent.length, 0 );\n\t\tstate( element, 0, 1, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", false );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"change\", function() {\n\texpect( 20 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\theaders = element.find( \".ui-accordion-header\" ),\n\t\tcontent = element.find( \".ui-accordion-content\" );\n\n\telement.one( \"accordionchange\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 0 );\n\t\tequal( ui.oldContent.length, 0 );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.newContent.length, 1 );\n\t\tstrictEqual( ui.newContent[ 0 ], content[ 0 ] );\n\t});\n\telement.accordion( \"option\", \"active\", 0 );\n\n\telement.one( \"accordionchange\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.oldContent.length, 1 );\n\t\tstrictEqual( ui.oldContent[ 0 ], content[ 0 ] );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.newContent.length, 1 );\n\t\tstrictEqual( ui.newContent[ 0 ], content[ 1 ] );\n\t});\n\theaders.eq( 1 ).click();\n\n\telement.one( \"accordionchange\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.oldContent.length, 1 );\n\t\tstrictEqual( ui.oldContent[ 0 ], content[ 1 ] );\n\t\tequal( ui.newHeader.length, 0 );\n\t\tequal( ui.newContent.length, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", false );\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_events.js",
    "content": "(function( $ ) {\n\nvar setupTeardown = TestHelpers.accordion.setupTeardown,\n\tstate = TestHelpers.accordion.state;\n\nmodule( \"accordion: events\", setupTeardown() );\n\ntest( \"create\", function() {\n\texpect( 10 );\n\n\tvar element = $( \"#list1\" ),\n\t\theaders = element.children( \"h3\" ),\n\t\tcontents = headers.next();\n\n\telement.accordion({\n\t\tcreate: function( event, ui ) {\n\t\t\tequal( ui.header.length, 1, \"header length\" );\n\t\t\tstrictEqual( ui.header[ 0 ], headers[ 0 ], \"header\" );\n\t\t\tequal( ui.content.length, 1, \"content length\" );\n\t\t\tstrictEqual( ui.content[ 0 ], contents[ 0 ], \"content\" );\n\t\t}\n\t});\n\telement.accordion( \"destroy\" );\n\n\telement.accordion({\n\t\tactive: 2,\n\t\tcreate: function( event, ui ) {\n\t\t\tequal( ui.header.length, 1, \"header length\" );\n\t\t\tstrictEqual( ui.header[ 0 ], headers[ 2 ], \"header\" );\n\t\t\tequal( ui.content.length, 1, \"content length\" );\n\t\t\tstrictEqual( ui.content[ 0 ], contents[ 2 ], \"content\" );\n\t\t}\n\t});\n\telement.accordion( \"destroy\" );\n\n\telement.accordion({\n\t\tactive: false,\n\t\tcollapsible: true,\n\t\tcreate: function( event, ui ) {\n\t\t\tequal( ui.header.length, 0, \"header length\" );\n\t\t\tequal( ui.content.length, 0, \"content length\" );\n\t\t}\n\t});\n\telement.accordion( \"destroy\" );\n});\n\ntest( \"beforeActivate\", function() {\n\texpect( 38 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\theaders = element.find( \".ui-accordion-header\" ),\n\t\tcontent = element.find( \".ui-accordion-content\" );\n\n\telement.one( \"accordionbeforeactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ) );\n\t\tequal( ui.oldHeader.length, 0 );\n\t\tequal( ui.oldPanel.length, 0 );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.newPanel.length, 1 );\n\t\tstrictEqual( ui.newPanel[ 0 ], content[ 0 ] );\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", 0 );\n\tstate( element, 1, 0, 0 );\n\n\telement.one( \"accordionbeforeactivate\", function( event, ui ) {\n\t\tequal( event.originalEvent.type, \"click\" );\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.oldPanel.length, 1 );\n\t\tstrictEqual( ui.oldPanel[ 0 ], content[ 0 ] );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.newPanel.length, 1 );\n\t\tstrictEqual( ui.newPanel[ 0 ], content[ 1 ] );\n\t\tstate( element, 1, 0, 0 );\n\t});\n\theaders.eq( 1 ).click();\n\tstate( element, 0, 1, 0 );\n\n\telement.one( \"accordionbeforeactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ) );\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.oldPanel.length, 1 );\n\t\tstrictEqual( ui.oldPanel[ 0 ], content[ 1 ] );\n\t\tequal( ui.newHeader.length, 0 );\n\t\tequal( ui.newPanel.length, 0 );\n\t\tstate( element, 0, 1, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", false );\n\tstate( element, 0, 0, 0 );\n\n\telement.one( \"accordionbeforeactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ) );\n\t\tequal( ui.oldHeader.length, 0 );\n\t\tequal( ui.oldPanel.length, 0 );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 2 ] );\n\t\tequal( ui.newPanel.length, 1 );\n\t\tstrictEqual( ui.newPanel[ 0 ], content[ 2 ] );\n\t\tevent.preventDefault();\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", 2 );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"activate\", function() {\n\texpect( 21 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\theaders = element.find( \".ui-accordion-header\" ),\n\t\tcontent = element.find( \".ui-accordion-content\" );\n\n\telement.one( \"accordionactivate\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 0 );\n\t\tequal( ui.oldPanel.length, 0 );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.newPanel.length, 1 );\n\t\tstrictEqual( ui.newPanel[ 0 ], content[ 0 ] );\n\t});\n\telement.accordion( \"option\", \"active\", 0 );\n\n\telement.one( \"accordionactivate\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 0 ] );\n\t\tequal( ui.oldPanel.length, 1 );\n\t\tstrictEqual( ui.oldPanel[ 0 ], content[ 0 ] );\n\t\tequal( ui.newHeader.length, 1 );\n\t\tstrictEqual( ui.newHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.newPanel.length, 1 );\n\t\tstrictEqual( ui.newPanel[ 0 ], content[ 1 ] );\n\t});\n\theaders.eq( 1 ).click();\n\n\telement.one( \"accordionactivate\", function( event, ui ) {\n\t\tequal( ui.oldHeader.length, 1 );\n\t\tstrictEqual( ui.oldHeader[ 0 ], headers[ 1 ] );\n\t\tequal( ui.oldPanel.length, 1 );\n\t\tstrictEqual( ui.oldPanel[ 0 ], content[ 1 ] );\n\t\tequal( ui.newHeader.length, 0 );\n\t\tequal( ui.newPanel.length, 0 );\n\t});\n\telement.accordion( \"option\", \"active\", false );\n\n\t// prevent activation\n\telement.one( \"accordionbeforeactivate\", function( event ) {\n\t\tok( true );\n\t\tevent.preventDefault();\n\t});\n\telement.one( \"accordionactivate\", function() {\n\t\tok( false );\n\t});\n\telement.accordion( \"option\", \"active\", 1 );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_methods.js",
    "content": "(function( $ ) {\n\nvar equalHeight = TestHelpers.accordion.equalHeight,\n\tsetupTeardown = TestHelpers.accordion.setupTeardown,\n\tstate = TestHelpers.accordion.state;\n\nmodule( \"accordion: methods\", setupTeardown() );\n\ntest( \"destroy\", function() {\n\texpect( 1 );\n\tdomEqual( \"#list1\", function() {\n\t\t$( \"#list1\" ).accordion().accordion( \"destroy\" );\n\t});\n});\n\ntest( \"enable/disable\", function() {\n\texpect( 4 );\n\tvar element = $( \"#list1\" ).accordion();\n\tstate( element, 1, 0, 0 );\n\telement.accordion( \"disable\" );\n\t// event does nothing\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).trigger( \"click\" );\n\tstate( element, 1, 0, 0 );\n\t// option still works\n\telement.accordion( \"option\", \"active\", 1 );\n\tstate( element, 0, 1, 0 );\n\telement.accordion( \"enable\" );\n\telement.accordion( \"option\", \"active\", 2 );\n\tstate( element, 0, 0, 1 );\n});\n\ntest( \"refresh\", function() {\n\texpect( 6 );\n\tvar element = $( \"#navigation\" )\n\t\t.parent()\n\t\t\t.height( 300 )\n\t\t.end()\n\t\t.accordion({\n\t\t\theightStyle: \"fill\"\n\t\t});\n\tequalHeight( element, 255 );\n\n\telement.parent().height( 500 );\n\telement.accordion( \"refresh\" );\n\tequalHeight( element, 455 );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_options.js",
    "content": "(function( $ ) {\n\nvar equalHeight = TestHelpers.accordion.equalHeight,\n\tsetupTeardown = TestHelpers.accordion.setupTeardown,\n\tstate = TestHelpers.accordion.state;\n\nmodule( \"accordion: options\", setupTeardown() );\n\ntest( \"{ active: default }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#list1\" ).accordion();\n\tequal( element.accordion( \"option\", \"active\" ), 0 );\n\tstate( element, 1, 0, 0 );\n});\n\ntest( \"{ active: false }\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tactive: false,\n\t\tcollapsible: true\n\t});\n\tstate( element, 0, 0, 0 );\n\tequal( element.find( \".ui-accordion-header.ui-state-active\" ).length, 0, \"no headers selected\" );\n\tequal( element.accordion( \"option\", \"active\" ), false );\n\n\telement.accordion( \"option\", \"collapsible\", false );\n\tstate( element, 1, 0, 0 );\n\tequal( element.accordion( \"option\", \"active\" ), 0 );\n\n\telement.accordion( \"destroy\" );\n\telement.accordion({\n\t\tactive: false\n\t});\n\tstate( element, 1, 0, 0 );\n\tstrictEqual( element.accordion( \"option\", \"active\" ), 0 );\n});\n\ntest( \"{ active: Number }\", function() {\n\texpect( 8 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tactive: 2\n\t});\n\tequal( element.accordion( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.accordion( \"option\", \"active\", 0 );\n\tequal( element.accordion( \"option\", \"active\" ), 0 );\n\tstate( element, 1, 0, 0 );\n\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).click();\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.accordion( \"option\", \"active\", 10 );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\nif ( $.uiBackCompat === false ) {\n\ttest( \"{ active: -Number }\", function() {\n\t\texpect( 8 );\n\t\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: -1\n\t\t});\n\t\tequal( element.accordion( \"option\", \"active\" ), 2 );\n\t\tstate( element, 0, 0, 1 );\n\n\t\telement.accordion( \"option\", \"active\", -2 );\n\t\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\t\tstate( element, 0, 1, 0 );\n\n\t\telement.accordion( \"option\", \"active\", -10 );\n\t\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\t\tstate( element, 0, 1, 0 );\n\n\t\telement.accordion( \"option\", \"active\", -3 );\n\t\tequal( element.accordion( \"option\", \"active\" ), 0 );\n\t\tstate( element, 1, 0, 0 );\n\t});\n}\n\ntest( \"{ animate: false }\", function() {\n\texpect( 3 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tanimate: false\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t$.fn.animate = function() {\n\t\tok( false, \".animate() called\" );\n\t};\n\n\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 1 );\n\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel hidden\" );\n\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel visible\" );\n\t$.fn.animate = animate;\n});\n\nasyncTest( \"{ animate: Number }\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tanimate: 100\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t// called twice (both panels)\n\t$.fn.animate = function( props, duration, easing ) {\n\t\tequal( duration, 100, \"correct duration\" );\n\t\tequal( easing, undefined, \"default easing\" );\n\t\tanimate.apply( this, arguments );\n\t};\n\n\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 1 );\n\tpanels.promise().done(function() {\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel hidden\" );\n\t\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel visible\" );\n\t\t$.fn.animate = animate;\n\t\tstart();\n\t});\n});\n\nasyncTest( \"{ animate: String }\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tanimate: \"linear\"\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t// called twice (both panels)\n\t$.fn.animate = function( props, duration, easing ) {\n\t\tequal( duration, undefined, \"default duration\" );\n\t\tequal( easing, \"linear\", \"correct easing\" );\n\t\tanimate.apply( this, arguments );\n\t};\n\n\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 1 );\n\tpanels.promise().done(function() {\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel hidden\" );\n\t\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel visible\" );\n\t\t$.fn.animate = animate;\n\t\tstart();\n\t});\n});\n\nasyncTest( \"{ animate: {} }\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tanimate: {}\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t// called twice (both panels)\n\t$.fn.animate = function( props, duration, easing ) {\n\t\tequal( duration, undefined, \"default duration\" );\n\t\tequal( easing, undefined, \"default easing\" );\n\t\tanimate.apply( this, arguments );\n\t};\n\n\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 1 );\n\tpanels.promise().done(function() {\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel hidden\" );\n\t\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel visible\" );\n\t\t$.fn.animate = animate;\n\t\tstart();\n\t});\n});\n\nasyncTest( \"{ animate: { duration, easing } }\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tanimate: { duration: 100, easing: \"linear\" }\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t// called twice (both panels)\n\t$.fn.animate = function( props, duration, easing ) {\n\t\tequal( duration, 100, \"correct duration\" );\n\t\tequal( easing, \"linear\", \"correct easing\" );\n\t\tanimate.apply( this, arguments );\n\t};\n\n\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 1 );\n\tpanels.promise().done(function() {\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel hidden\" );\n\t\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel visible\" );\n\t\t$.fn.animate = animate;\n\t\tstart();\n\t});\n});\n\nasyncTest( \"{ animate: { duration, easing } }, animate down\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: 1,\n\t\t\tanimate: { duration: 100, easing: \"linear\" }\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t// called twice (both panels)\n\t$.fn.animate = function( props, duration, easing ) {\n\t\tequal( duration, 100, \"correct duration\" );\n\t\tequal( easing, \"linear\", \"correct easing\" );\n\t\tanimate.apply( this, arguments );\n\t};\n\n\tok( panels.eq( 1 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 0 );\n\tpanels.promise().done(function() {\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"first panel hidden\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"second panel visible\" );\n\t\t$.fn.animate = animate;\n\t\tstart();\n\t});\n});\n\nasyncTest( \"{ animate: { duration, easing, down } }, animate down\", function() {\n\texpect( 7 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\t\tactive: 1,\n\t\t\tanimate: {\n\t\t\t\tduration: 100,\n\t\t\t\teasing: \"linear\",\n\t\t\t\tdown: {\n\t\t\t\t\teasing: \"swing\"\n\t\t\t\t}\n\t\t\t}\n\t\t}),\n\t\tpanels = element.find( \".ui-accordion-content\" ),\n\t\tanimate = $.fn.animate;\n\t// called twice (both panels)\n\t$.fn.animate = function( props, duration, easing ) {\n\t\tequal( duration, 100, \"correct duration\" );\n\t\tequal( easing, \"swing\", \"correct easing\" );\n\t\tanimate.apply( this, arguments );\n\t};\n\n\tok( panels.eq( 1 ).is( \":visible\" ), \"first panel visible\" );\n\telement.accordion( \"option\", \"active\", 0 );\n\tpanels.promise().done(function() {\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"first panel hidden\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"second panel visible\" );\n\t\t$.fn.animate = animate;\n\t\tstart();\n\t});\n});\n\ntest( \"{ collapsible: false }\", function() {\n\texpect( 4 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tactive: 1\n\t});\n\telement.accordion( \"option\", \"active\", false );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).click();\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ collapsible: true }\", function() {\n\texpect( 6 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tactive: 1,\n\t\tcollapsible: true\n\t});\n\n\telement.accordion( \"option\", \"active\", false );\n\tequal( element.accordion( \"option\", \"active\" ), false );\n\tstate( element, 0, 0, 0 );\n\n\telement.accordion( \"option\", \"active\", 1 );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).click();\n\tequal( element.accordion( \"option\", \"active\" ), false );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"{ event: null }\", function() {\n\texpect( 5 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tevent: null\n\t});\n\tstate( element, 1, 0, 0 );\n\n\telement.accordion( \"option\", \"active\", 1 );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\t// ensure default click handler isn't bound\n\telement.find( \".ui-accordion-header\" ).eq( 2 ).click();\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ event: custom }\", function() {\n\texpect( 11 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\tevent: \"custom1 custom2\"\n\t});\n\tstate( element, 1, 0, 0 );\n\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).trigger( \"custom1\" );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\t// ensure default click handler isn't bound\n\telement.find( \".ui-accordion-header\" ).eq( 2 ).trigger( \"click\" );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.find( \".ui-accordion-header\" ).eq( 2 ).trigger( \"custom2\" );\n\tequal( element.accordion( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.accordion( \"option\", \"event\", \"custom3\" );\n\n\t// ensure old event handlers are unbound\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).trigger( \"custom1\" );\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).trigger( \"custom2\" );\n\tequal( element.accordion( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.find( \".ui-accordion-header\" ).eq( 1 ).trigger( \"custom3\" );\n\tequal( element.accordion( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ header: default }\", function() {\n\texpect( 2 );\n\t// default: > li > :first-child,> :not(li):even\n\t// > :not(li):even\n\tstate( $( \"#list1\" ).accordion(), 1, 0, 0);\n\t// > li > :first-child\n\tstate( $( \"#navigation\" ).accordion(), 1, 0, 0);\n});\n\ntest( \"{ header: custom }\", function() {\n\texpect( 6 );\n\tvar element = $( \"#navigationWrapper\" ).accordion({\n\t\theader: \"h2\"\n\t});\n\telement.find( \"h2\" ).each(function() {\n\t\tok( $( this ).hasClass( \"ui-accordion-header\" ) );\n\t});\n\tequal( element.find( \".ui-accordion-header\" ).length, 3 );\n\tstate( element, 1, 0, 0 );\n\telement.accordion( \"option\", \"active\", 2 );\n\tstate( element, 0, 0, 1 );\n});\n\ntest( \"{ heightStyle: 'auto' }\", function() {\n\texpect( 3 );\n\tvar element = $( \"#navigation\" ).accordion({ heightStyle: \"auto\" });\n\tequalHeight( element, 105 );\n});\n\ntest( \"{ heightStyle: 'content' }\", function() {\n\texpect( 3 );\n\tvar element = $( \"#navigation\" ).accordion({ heightStyle: \"content\" }),\n\t\tsizes = element.find( \".ui-accordion-content\" ).map(function() {\n\t\t\treturn $( this ).height();\n\t\t}).get();\n\tequal( sizes[ 0 ], 75 );\n\tequal( sizes[ 1 ], 105 );\n\tequal( sizes[ 2 ], 45 );\n});\n\ntest( \"{ heightStyle: 'fill' }\", function() {\n\texpect( 3 );\n\t$( \"#navigationWrapper\" ).height( 500 );\n\tvar element = $( \"#navigation\" ).accordion({ heightStyle: \"fill\" });\n\tequalHeight( element, 455 );\n});\n\ntest( \"{ heightStyle: 'fill' } with sibling\", function() {\n\texpect( 3 );\n\t$( \"#navigationWrapper\" ).height( 500 );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\tvar element = $( \"#navigation\" ).accordion({ heightStyle: \"fill\" });\n\tequalHeight( element , 355 );\n});\n\ntest( \"{ heightStyle: 'fill' } with multiple siblings\", function() {\n\texpect( 3 );\n\t$( \"#navigationWrapper\" ).height( 500 );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30,\n\t\t\tposition: \"absolute\"\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 25,\n\t\t\tmarginTop: 10,\n\t\t\tmarginBottom: 15\n\t\t})\n\t\t.prependTo( \"#navigationWrapper\" );\n\tvar element = $( \"#navigation\" ).accordion({ heightStyle: \"fill\" });\n\tequalHeight( element, 305 );\n});\n\ntest( \"{ icons: false }\", function() {\n\texpect( 8 );\n\tvar element = $( \"#list1\" );\n\tfunction icons( on ) {\n\t\tdeepEqual( element.find( \"span.ui-icon\").length, on ? 3 : 0 );\n\t\tdeepEqual( element.find( \".ui-accordion-header.ui-accordion-icons\" ).length, on ? 3 : 0 );\n\t}\n\telement.accordion();\n\ticons( true );\n\telement.accordion( \"destroy\" ).accordion({\n\t\ticons: false\n\t});\n\ticons( false );\n\telement.accordion( \"option\", \"icons\", { header: \"foo\", activeHeader: \"bar\" } );\n\ticons( true );\n\telement.accordion( \"option\", \"icons\", false );\n\ticons( false );\n});\n\ntest( \"{ icons: hash }\", function() {\n\texpect( 3 );\n\tvar element = $( \"#list1\" ).accordion({\n\t\ticons: { activeHeader: \"a1\", header: \"h1\" }\n\t});\n\tok( element.find( \".ui-accordion-header.ui-state-active span.ui-icon\" ).hasClass( \"a1\" ) );\n\telement.accordion( \"option\", \"icons\", { activeHeader: \"a2\", header: \"h2\" } );\n\tok( !element.find( \".ui-accordion-header.ui-state-active span.ui-icon\" ).hasClass( \"a1\" ) );\n\tok( element.find( \".ui-accordion-header.ui-state-active span.ui-icon\" ).hasClass( \"a2\" ) );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/accordion_test_helpers.js",
    "content": "TestHelpers.accordion = {\n\tequalHeight: function( accordion, height ) {\n\t\taccordion.find( \".ui-accordion-content\" ).each(function() {\n\t\t\tequal( $( this ).outerHeight(), height );\n\t\t});\n\t},\n\n\tsetupTeardown: function() {\n\t\tvar animate = $.ui.accordion.prototype.options.animate;\n\t\treturn {\n\t\t\tsetup: function() {\n\t\t\t\t$.ui.accordion.prototype.options.animate = false;\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\t$.ui.accordion.prototype.options.animate = animate;\n\t\t\t}\n\t\t};\n\t},\n\n\tstate: function( accordion ) {\n\t\tvar expected = $.makeArray( arguments ).slice( 1 ),\n\t\t\tactual = accordion.find( \".ui-accordion-content\" ).map(function() {\n\t\t\treturn $( this ).css( \"display\" ) === \"none\" ? 0 : 1;\n\t\t}).get();\n\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected );\n\t}\n};\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/accordion/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Accordion Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"accordion\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Accordion Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/all-active.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Test Suite</title>\n\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"qunit-composite.css\">\n\t<script src=\"../../external/qunit.js\"></script>\n\t<script src=\"qunit-composite.js\"></script>\n\n\t<script>\n\t(function() {\n\n\tvar params = [],\n\t\tsuites = [\n\t\t\t\"accordion/accordion.html\",\n\t\t\t\"accordion/accordion_deprecated.html\",\n\t\t\t\"autocomplete/autocomplete.html\",\n\t\t\t\"button/button.html\",\n\t\t\t\"core/core.html\",\n\t\t\t//\"datepicker/datepicker.html\",\n\t\t\t//\"dialog/dialog.html\",\n\t\t\t//\"draggable/draggable.html\",\n\t\t\t//\"droppable/droppable.html\",\n\t\t\t\"effects/effects.html\",\n\t\t\t\"menu/menu.html\",\n\t\t\t\"position/position.html\",\n\t\t\t\"position/position_deprecated.html\",\n\t\t\t\"progressbar/progressbar.html\",\n\t\t\t//\"resizable/resizable.html\",\n\t\t\t//\"selectable/selectable.html\",\n\t\t\t//\"slider/slider.html\",\n\t\t\t//\"sortable/sortable.html\",\n\t\t\t\"spinner/spinner.html\",\n\t\t\t\"tabs/tabs.html\",\n\t\t\t\"tabs/tabs_deprecated.html\",\n\t\t\t\"tooltip/tooltip.html\",\n\t\t\t\"widget/widget.html\"\n\t\t];\n\n\t$.each( QUnit.urlParams, function( key, value ) {\n\t\tif ( key === \"filter\" ) {\n\t\t\treturn;\n\t\t}\n\t\tparams.push( encodeURIComponent( key ) + \"=\" + encodeURIComponent( value ) );\n\t});\n\tif ( params.length ) {\n\t\tparams = \"?\" + params.join( \"&\" );\n\t\tsuites = $.map( suites, function( suite ) {\n\t\t\treturn suite + params;\n\t\t});\n\t}\n\tQUnit.testSuites( suites );\n\n\t}());\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Test Suite</title>\n\n\t<script src=\"../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"qunit-composite.css\">\n\t<script src=\"../../external/qunit.js\"></script>\n\t<script src=\"qunit-composite.js\"></script>\n\n\t<script>\n\t(function() {\n\n\tvar params = [],\n\t\tsuites = [\n\t\t\t\"accordion/accordion.html\",\n\t\t\t\"accordion/accordion_deprecated.html\",\n\t\t\t\"autocomplete/autocomplete.html\",\n\t\t\t\"button/button.html\",\n\t\t\t\"core/core.html\",\n\t\t\t\"datepicker/datepicker.html\",\n\t\t\t\"dialog/dialog.html\",\n\t\t\t//\"draggable/draggable.html\",\n\t\t\t//\"droppable/droppable.html\",\n\t\t\t\"effects/effects.html\",\n\t\t\t\"menu/menu.html\",\n\t\t\t\"position/position.html\",\n\t\t\t\"position/position_deprecated.html\",\n\t\t\t\"progressbar/progressbar.html\",\n\t\t\t//\"resizable/resizable.html\",\n\t\t\t//\"selectable/selectable.html\",\n\t\t\t\"slider/slider.html\",\n\t\t\t//\"sortable/sortable.html\",\n\t\t\t\"spinner/spinner.html\",\n\t\t\t\"tabs/tabs.html\",\n\t\t\t\"tabs/tabs_deprecated.html\",\n\t\t\t\"tooltip/tooltip.html\",\n\t\t\t\"widget/widget.html\"\n\t\t];\n\n\t$.each( QUnit.urlParams, function( key, value ) {\n\t\tif ( key === \"filter\" ) {\n\t\t\treturn;\n\t\t}\n\t\tparams.push( encodeURIComponent( key ) + \"=\" + encodeURIComponent( value ) );\n\t});\n\tif ( params.length ) {\n\t\tparams = \"?\" + params.join( \"&\" );\n\t\tsuites = $.map( suites, function( suite ) {\n\t\t\treturn suite + params;\n\t\t});\n\t}\n\tQUnit.testSuites( suites );\n\n\t}());\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"autocomplete\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Autocomplete Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/autocomplete.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Autocomplete Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.menu\", \"ui.autocomplete\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.position.js\",\n\t\t\t\"ui/jquery.ui.menu.js\",\n\t\t\t\"ui/jquery.ui.autocomplete.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"autocomplete_common.js\"></script>\n\t<script src=\"autocomplete_core.js\"></script>\n\t<script src=\"autocomplete_events.js\"></script>\n\t<script src=\"autocomplete_methods.js\"></script>\n\t<script src=\"autocomplete_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Autocomplete Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"ac-wrap1\" class=\"ac-wrap\"></div>\n<div id=\"ac-wrap2\" class=\"ac-wrap\"><input id=\"autocomplete\" class=\"foo\"></div>\n<div id=\"autocomplete-contenteditable\" contenteditable=\"\" tabindex=0></div>\n<textarea id=\"autocomplete-textarea\"></textarea>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/autocomplete_common.js",
    "content": "TestHelpers.commonWidgetTests( \"autocomplete\", {\n\tdefaults: {\n\t\tappendTo: \"body\",\n\t\tautoFocus: false,\n\t\tdelay: 300,\n\t\tdisabled: false,\n\t\tmessages: {\n\t\t\tnoResults: \"No search results.\",\n\t\t\tresults: $.ui.autocomplete.prototype.options.messages.results\n\t\t},\n\t\tminLength: 1,\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\tsource: null,\n\n\t\t// callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tcreate: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresponse: null,\n\t\tsearch: null,\n\t\tselect: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/autocomplete_core.js",
    "content": "(function( $ ) {\n\nmodule( \"autocomplete: core\" );\n\ntest( \"prevent form submit on enter when menu is active\", function() {\n\texpect( 2 );\n\tvar event,\n\t\telement = $( \"#autocomplete\" )\n\t\t\t.autocomplete({\n\t\t\t\tsource: [ \"java\", \"javascript\" ]\n\t\t\t})\n\t\t\t.val( \"ja\" )\n\t\t\t.autocomplete( \"search\" ),\n\t\tmenu = element.autocomplete( \"widget\" );\n\n\tevent = $.Event( \"keydown\" );\n\tevent.keyCode = $.ui.keyCode.DOWN;\n\telement.trigger( event );\n\tdeepEqual( menu.find( \".ui-menu-item:has(.ui-state-focus)\" ).length, 1, \"menu item is active\" );\n\n\tevent = $.Event( \"keydown\" );\n\tevent.keyCode = $.ui.keyCode.ENTER;\n\telement.trigger( event );\n\tok( event.isDefaultPrevented(), \"default action is prevented\" );\n});\n\ntest( \"allow form submit on enter when menu is not active\", function() {\n\texpect( 1 );\n\tvar event,\n\t\telement = $( \"#autocomplete\" )\n\t\t\t.autocomplete({\n\t\t\t\tautoFocus: false,\n\t\t\t\tsource: [ \"java\", \"javascript\" ]\n\t\t\t})\n\t\t\t.val( \"ja\" )\n\t\t\t.autocomplete( \"search\" );\n\n\tevent = $.Event( \"keydown\" );\n\tevent.keyCode = $.ui.keyCode.ENTER;\n\telement.trigger( event );\n\tok( !event.isDefaultPrevented(), \"default action is prevented\" );\n});\n\n(function() {\n\ttest( \"up arrow invokes search - input\", function() {\n\t\tarrowsInvokeSearch( \"#autocomplete\", true, true );\n\t});\n\n\ttest( \"down arrow invokes search - input\", function() {\n\t\tarrowsInvokeSearch( \"#autocomplete\", false, true );\n\t});\n\n\ttest( \"up arrow invokes search - textarea\", function() {\n\t\tarrowsInvokeSearch( \"#autocomplete-textarea\", true, false );\n\t});\n\n\ttest( \"down arrow invokes search - textarea\", function() {\n\t\tarrowsInvokeSearch( \"#autocomplete-textarea\", false, false );\n\t});\n\n\ttest( \"up arrow invokes search - contenteditable\", function() {\n\t\tarrowsInvokeSearch( \"#autocomplete-contenteditable\", true, false );\n\t});\n\n\ttest( \"down arrow invokes search - contenteditable\", function() {\n\t\tarrowsInvokeSearch( \"#autocomplete-contenteditable\", false, false );\n\t});\n\n\ttest( \"up arrow moves focus - input\", function() {\n\t\tarrowsMoveFocus( \"#autocomplete\", true );\n\t});\n\n\ttest( \"down arrow moves focus - input\", function() {\n\t\tarrowsMoveFocus( \"#autocomplete\", false );\n\t});\n\n\ttest( \"up arrow moves focus - textarea\", function() {\n\t\tarrowsMoveFocus( \"#autocomplete-textarea\", true );\n\t});\n\n\ttest( \"down arrow moves focus - textarea\", function() {\n\t\tarrowsMoveFocus( \"#autocomplete-textarea\", false );\n\t});\n\n\ttest( \"up arrow moves focus - contenteditable\", function() {\n\t\tarrowsMoveFocus( \"#autocomplete-contenteditable\", true );\n\t});\n\n\ttest( \"down arrow moves focus - contenteditable\", function() {\n\t\tarrowsMoveFocus( \"#autocomplete-contenteditable\", false );\n\t});\n\n\tfunction arrowsInvokeSearch( id, isKeyUp, shouldMove ) {\n\t\texpect( 1 );\n\n\t\tvar didMove = false,\n\t\t\telement = $( id ).autocomplete({\n\t\t\t\tsource: [ \"a\" ],\n\t\t\t\tdelay: 0,\n\t\t\t\tminLength: 0\n\t\t\t});\n\t\telement.data( \"autocomplete\" )._move = function() {\n\t\t\tdidMove = true;\n\t\t};\n\t\telement.simulate( \"keydown\", { keyCode: ( isKeyUp ? $.ui.keyCode.UP : $.ui.keyCode.DOWN ) } );\n\t\tequal( didMove, shouldMove, \"respond to arrow\" );\n\t}\n\n\tfunction arrowsMoveFocus( id, isKeyUp ) {\n\t\texpect( 1 );\n\n\t\tvar didMove = false,\n\t\t\telement = $( id ).autocomplete({\n\t\t\t\tsource: [ \"a\" ],\n\t\t\t\tdelay: 0,\n\t\t\t\tminLength: 0\n\t\t\t});\n\t\telement.data( \"autocomplete\" )._move = function() {\n\t\t\tok( true, \"repsond to arrow\" );\n\t\t};\n\t\telement.autocomplete( \"search\" );\n\t\telement.simulate( \"keydown\", { keyCode: ( isKeyUp ? $.ui.keyCode.UP : $.ui.keyCode.DOWN ) } );\n\t}\n})();\n\nasyncTest( \"handle race condition\", function() {\n\texpect( 3 );\n\tvar count = 0,\n\t\telement = $( \"#autocomplete\" ).autocomplete({\n\t\tsource: function( request, response ) {\n\t\t\tcount++;\n\t\t\tif ( request.term.length === 1 ) {\n\t\t\t\tequal( count, 1, \"request with 1 character is first\" );\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tresponse([ \"one\" ]);\n\t\t\t\t\tsetTimeout( checkResults, 1 );\n\t\t\t\t}, 1 );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tequal( count, 2, \"request with 2 characters is second\" );\n\t\t\tresponse([ \"two\" ]);\n\t\t}\n\t});\n\n\telement.autocomplete( \"search\", \"a\" );\n\telement.autocomplete( \"search\", \"ab\" );\n\n\tfunction checkResults() {\n\t\tequal( element.autocomplete( \"widget\" ).find( \".ui-menu-item\" ).text(), \"two\",\n\t\t\t\"correct results displayed\" );\n\t\tstart();\n\t}\n});\n\ntest( \"ARIA\", function() {\n\texpect( 7 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: [ \"java\", \"javascript\" ]\n\t\t}),\n\t\tliveRegion = element.data( \"ui-autocomplete\" ).liveRegion;\n\n\tequal( liveRegion.text(), \"\", \"Empty live region on create\" );\n\n\telement.autocomplete( \"search\", \"j\" );\n\tequal( liveRegion.text(), \"2 results are available, use up and down arrow keys to navigate.\",\n\t\t\"Live region for multiple values\" );\n\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\tequal( liveRegion.text(), \"2 results are available, use up and down arrow keys to navigate.\",\n\t\t\"Live region not changed on focus\" );\n\n\telement.one( \"autocompletefocus\", function( event ) {\n\t\tevent.preventDefault();\n\t});\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\tequal( liveRegion.text(), \"javascript\",\n\t\t\"Live region updated when default focus is prevented\" );\n\n\telement.autocomplete( \"search\", \"javas\" );\n\tequal( liveRegion.text(), \"1 result is available, use up and down arrow keys to navigate.\",\n\t\t\"Live region for one value\" );\n\n\telement.autocomplete( \"search\", \"z\" );\n\tequal( liveRegion.text(), \"No search results.\",\n\t\t\"Live region for no values\" );\n\n\telement.autocomplete( \"search\", \"j\" );\n\tequal( liveRegion.text(), \"2 results are available, use up and down arrow keys to navigate.\",\n\t\t\"Live region for multiple values\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/autocomplete_events.js",
    "content": "(function( $ ) {\n\nmodule( \"autocomplete: events\" );\n\nvar data = [ \"Clojure\", \"COBOL\", \"ColdFusion\", \"Java\", \"JavaScript\", \"Scala\", \"Scheme\" ];\n\n$.each([\n\t{\n\t\ttype: \"input\",\n\t\tselector: \"#autocomplete\",\n\t\tvalueMethod: \"val\"\n\t},\n\t{\n\t\ttype: \"textarea\",\n\t\tselector: \"#autocomplete-textarea\",\n\t\tvalueMethod: \"val\"\n\t},\n\t{\n\t\ttype: \"contenteditable\",\n\t\tselector: \"#autocomplete-contenteditable\",\n\t\tvalueMethod: \"text\"\n\t}\n], function( i, settings ) {\n\tasyncTest( \"all events - \" + settings.type, function() {\n\t\texpect( 13 );\n\t\tvar element = $( settings.selector )\n\t\t\t\t.autocomplete({\n\t\t\t\t\tautoFocus: false,\n\t\t\t\t\tdelay: 0,\n\t\t\t\t\tsource: data,\n\t\t\t\t\tsearch: function( event ) {\n\t\t\t\t\t\tequal( event.originalEvent.type, \"keydown\", \"search originalEvent\" );\n\t\t\t\t\t},\n\t\t\t\t\tresponse: function( event, ui ) {\n\t\t\t\t\t\tdeepEqual( ui.content, [\n\t\t\t\t\t\t\t{ label: \"Clojure\", value: \"Clojure\" },\n\t\t\t\t\t\t\t{ label: \"Java\", value: \"Java\" },\n\t\t\t\t\t\t\t{ label: \"JavaScript\", value: \"JavaScript\" }\n\t\t\t\t\t\t], \"response ui.content\" );\n\t\t\t\t\t\tui.content.splice( 0, 1 );\n\t\t\t\t\t},\n\t\t\t\t\topen: function( event ) {\n\t\t\t\t\t\tok( menu.is( \":visible\" ), \"menu open on open\" );\n\t\t\t\t\t},\n\t\t\t\t\tfocus: function( event, ui ) {\n\t\t\t\t\t\tequal( event.originalEvent.type, \"menufocus\", \"focus originalEvent\" );\n\t\t\t\t\t\tdeepEqual( ui.item, { label: \"Java\", value: \"Java\" }, \"focus ui.item\" );\n\t\t\t\t\t},\n\t\t\t\t\tclose: function( event ) {\n\t\t\t\t\t\tequal( event.originalEvent.type, \"menuselect\", \"close originalEvent\" );\n\t\t\t\t\t\tok( menu.is( \":hidden\" ), \"menu closed on close\" );\n\t\t\t\t\t},\n\t\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\t\tequal( event.originalEvent.type, \"menuselect\", \"select originalEvent\" );\n\t\t\t\t\t\tdeepEqual( ui.item, { label: \"Java\", value: \"Java\" }, \"select ui.item\" );\n\t\t\t\t\t},\n\t\t\t\t\tchange: function( event, ui ) {\n\t\t\t\t\t\tequal( event.originalEvent.type, \"blur\", \"change originalEvent\" );\n\t\t\t\t\t\tdeepEqual( ui.item, { label: \"Java\", value: \"Java\" }, \"change ui.item\" );\n\t\t\t\t\t\tok( menu.is( \":hidden\" ), \"menu closed on change\" );\n\t\t\t\t\t\tstart();\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\tmenu = element.autocomplete( \"widget\" );\n\n\t\telement.simulate( \"focus\" )[ settings.valueMethod ]( \"j\" ).keydown();\n\t\tsetTimeout(function() {\n\t\t\tok( menu.is( \":visible\" ), \"menu is visible after delay\" );\n\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\t\t\t// blur must be async for IE to handle it properly\n\t\t\tsetTimeout(function() {\n\t\t\t\telement.simulate( \"blur\" );\n\t\t\t}, 1 );\n\t\t}, 50 );\n\t});\n});\n\nasyncTest( \"change without selection\", function() {\n\texpect( 1 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\tdelay: 0,\n\t\tsource: data,\n\t\tchange: function( event, ui ) {\n\t\t\tstrictEqual( ui.item, null );\n\t\t\tstart();\n\t\t}\n\t});\n\telement.triggerHandler( \"focus\" );\n\telement.val( \"ja\" ).triggerHandler( \"blur\" );\n});\n\nasyncTest( \"cancel search\", function() {\n\texpect( 6 );\n\tvar first = true,\n\t\telement = $( \"#autocomplete\" ).autocomplete({\n\t\t\tdelay: 0,\n\t\t\tsource: data,\n\t\t\tsearch: function() {\n\t\t\t\tif ( first ) {\n\t\t\t\t\tequal( element.val(), \"ja\", \"val on first search\" );\n\t\t\t\t\tfirst = false;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tequal( element.val(), \"java\", \"val on second search\" );\n\t\t\t},\n\t\t\topen: function() {\n\t\t\t\tok( true, \"menu opened\" );\n\t\t\t}\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\telement.val( \"ja\" ).keydown();\n\tsetTimeout(function() {\n\t\tok( menu.is( \":hidden\" ), \"menu is hidden after first search\" );\n\t\telement.val( \"java\" ).keydown();\n\t\tsetTimeout(function() {\n\t\t\tok( menu.is( \":visible\" ), \"menu is visible after second search\" );\n\t\t\tequal( menu.find( \".ui-menu-item\" ).length, 2, \"# of menu items\" );\n\t\t\tstart();\n\t\t}, 50 );\n\t}, 50 );\n});\n\nasyncTest( \"cancel focus\", function() {\n\texpect( 1 );\n\tvar customVal = \"custom value\",\n\t\telement = $( \"#autocomplete\" ).autocomplete({\n\t\t\tdelay: 0,\n\t\t\tsource: data,\n\t\t\tfocus: function( event, ui ) {\n\t\t\t\t$( this ).val( customVal );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\telement.val( \"ja\" ).keydown();\n\tsetTimeout(function() {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\tequal( element.val(), customVal );\n\t\tstart();\n\t}, 50 );\n});\n\nasyncTest( \"cancel select\", function() {\n\texpect( 1 );\n\tvar customVal = \"custom value\",\n\t\telement = $( \"#autocomplete\" ).autocomplete({\n\t\t\tdelay: 0,\n\t\t\tsource: data,\n\t\t\tselect: function( event, ui ) {\n\t\t\t\t$( this ).val( customVal );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\telement.val( \"ja\" ).keydown();\n\tsetTimeout(function() {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\t\tequal( element.val(), customVal );\n\t\tstart();\n\t}, 50 );\n});\n\nasyncTest( \"blur during remote search\", function() {\n\texpect( 1 );\n\tvar ac = $( \"#autocomplete\" ).autocomplete({\n\t\tdelay: 0,\n\t\tsource: function( request, response ) {\n\t\t\tok( true, \"trigger request\" );\n\t\t\tac.simulate( \"blur\" );\n\t\t\tsetTimeout(function() {\n\t\t\t\tresponse([ \"result\" ]);\n\t\t\t\tstart();\n\t\t\t}, 100 );\n\t\t},\n\t\topen: function() {\n\t\t\tok( false, \"opened after a blur\" );\n\t\t}\n\t});\n\tac.val( \"ro\" ).keydown();\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/autocomplete_methods.js",
    "content": "(function( $ ) {\n\nmodule( \"autocomplete: methods\" );\n\ntest( \"destroy\", function() {\n\texpect( 1 );\n\tdomEqual( \"#autocomplete\", function() {\n\t\t$( \"#autocomplete\" ).autocomplete().autocomplete( \"destroy\" );\n\t});\n});\n\ntest( \"search, close\", function() {\n\texpect( 6 );\n\tvar data = [ \"c++\", \"java\", \"php\", \"coldfusion\", \"javascript\", \"asp\", \"ruby\", \"python\", \"c\", \"scala\", \"groovy\", \"haskell\", \"perl\" ],\n\t\telement = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: data,\n\t\t\tminLength: 0\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\n\tok( menu.is( \":hidden\" ), \"menu is hidden on init\" );\n\n\telement.autocomplete( \"search\" );\n\tok( menu.is( \":visible\" ), \"menu is visible after search\" );\n\tequal( menu.find( \".ui-menu-item\" ).length, data.length, \"all items for a blank search\" );\n\n\telement.val( \"has\" ).autocomplete( \"search\" );\n\tequal( menu.find( \".ui-menu-item\" ).text(), \"haskell\", \"only one item for set input value\" );\n\n\telement.autocomplete( \"search\", \"ja\" );\n\tequal( menu.find( \".ui-menu-item\" ).length, 2, \"only java and javascript for 'ja'\" );\n\n\telement.autocomplete( \"close\" );\n\tok( menu.is( \":hidden\" ), \"menu is hidden after close\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/autocomplete_options.js",
    "content": "(function( $ ) {\n\nmodule( \"autocomplete: options\" );\n\nvar data = [ \"c++\", \"java\", \"php\", \"coldfusion\", \"javascript\", \"asp\", \"ruby\", \"python\", \"c\", \"scala\", \"groovy\", \"haskell\", \"perl\" ];\n\ntest( \"appendTo\", function() {\n\texpect( 5 );\n\tvar element = $( \"#autocomplete\" ).autocomplete();\n\tequal( element.autocomplete( \"widget\" ).parent()[0], document.body, \"defaults to body\" );\n\telement.autocomplete( \"destroy\" );\n\n\telement.autocomplete({\n\t\tappendTo: \".ac-wrap\"\n\t});\n\tequal( element.autocomplete( \"widget\" ).parent()[0], $( \"#ac-wrap1\" )[0], \"first found element\" );\n\tequal( $( \"#ac-wrap2 .ui-autocomplete\" ).length, 0, \"only appends to one element\" );\n\telement.autocomplete( \"destroy\" );\n\n\telement.autocomplete({\n\t\tappendTo: null\n\t});\n\tequal( element.autocomplete( \"widget\" ).parent()[0], document.body, \"null\" );\n\telement.autocomplete( \"destroy\" );\n\n\telement.autocomplete().autocomplete( \"option\", \"appendTo\", \"#ac-wrap1\" );\n\tequal( element.autocomplete( \"widget\" ).parent()[0], $( \"#ac-wrap1\" )[0], \"modified after init\" );\n\telement.autocomplete( \"destroy\" );\n});\n\nfunction autoFocusTest( afValue, focusedLength ) {\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\tautoFocus: afValue,\n\t\tdelay: 0,\n\t\tsource: data,\n\t\topen: function( event, ui ) {\n\t\t\tequal( element.autocomplete( \"widget\" ).children( \".ui-menu-item:first\" ).find( \".ui-state-focus\" ).length,\n\t\t\t\tfocusedLength, \"first item is \" + (afValue ? \"\" : \"not\") + \" auto focused\" );\n\t\t\tstart();\n\t\t}\n\t});\n\telement.val( \"ja\" ).keydown();\n\tstop();\n}\n\ntest( \"autoFocus: false\", function() {\n\texpect( 1 );\n\tautoFocusTest( false, 0 );\n});\n\ntest( \"autoFocus: true\", function() {\n\texpect( 1 );\n\tautoFocusTest( true, 1 );\n});\n\nasyncTest( \"delay\", function() {\n\texpect( 2 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: data,\n\t\t\tdelay: 50\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\telement.val( \"ja\" ).keydown();\n\n\tok( menu.is( \":hidden\" ), \"menu is closed immediately after search\" );\n\n\tsetTimeout(function() {\n\t\tok( menu.is( \":visible\" ), \"menu is open after delay\" );\n\t\tstart();\n\t}, 100 );\n});\n\nasyncTest( \"disabled\", function() {\n\texpect( 2 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: data,\n\t\t\tdelay: 0,\n\t\t\tdisabled: true\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\telement.val( \"ja\" ).keydown();\n\n\tok( menu.is( \":hidden\" ) );\n\n\tsetTimeout(function() {\n\t\tok( menu.is( \":hidden\" ) );\n\t\tstart();\n\t}, 50 );\n});\n\ntest( \"minLength\", function() {\n\texpect( 2 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: data\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\telement.autocomplete( \"search\", \"\" );\n\tok( menu.is( \":hidden\" ), \"blank not enough for minLength: 1\" );\n\n\telement.autocomplete( \"option\", \"minLength\", 0 );\n\telement.autocomplete( \"search\", \"\" );\n\tok( menu.is( \":visible\" ), \"blank enough for minLength: 0\" );\n});\n\nasyncTest( \"minLength, exceed then drop below\", function() {\n\texpect( 4 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tminLength: 2,\n\t\t\tsource: function( req, res ) {\n\t\t\t\tequal( req.term, \"12\", \"correct search term\" );\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tres([ \"item\" ]);\n\t\t\t\t}, 1 );\n\t\t\t}\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\n\tok( menu.is( \":hidden\" ), \"menu is hidden before first search\" );\n\telement.autocomplete( \"search\", \"12\" );\n\n\tok( menu.is( \":hidden\" ), \"menu is hidden before second search\" );\n\telement.autocomplete( \"search\", \"1\" );\n\n\tsetTimeout(function() {\n\t\tok( menu.is( \":hidden\" ), \"menu is hidden after searches\" );\n\t\tstart();\n\t}, 50 );\n});\n\ntest( \"minLength, exceed then drop below then exceed\", function() {\n\texpect( 3 );\n\tvar _res = [],\n\t\telement = $( \"#autocomplete\" ).autocomplete({\n\t\t\tminLength: 2,\n\t\t\tsource: function( req, res ) {\n\t\t\t\t_res.push( res );\n\t\t\t}\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\n\t// trigger a valid search\n\tok( menu.is( \":hidden\" ), \"menu is hidden before first search\" );\n\telement.autocomplete( \"search\", \"12\" );\n\n\t// trigger a search below the minLength, to turn on cancelSearch flag\n\tok( menu.is( \":hidden\" ), \"menu is hidden before second search\" );\n\telement.autocomplete( \"search\", \"1\" );\n\n\t// trigger a valid search\n\telement.autocomplete( \"search\", \"13\" );\n\t// react as if the first search was cancelled (default ajax behavior)\n\t_res[ 0 ]([]);\n\t// react to second search\n\t_res[ 1 ]([ \"13\" ]);\n\n\tok( menu.is( \":visible\" ), \"menu is visible after searches\" );\n});\n\ntest( \"source, local string array\", function() {\n\texpect( 1 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: data\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\telement.val( \"ja\" ).autocomplete( \"search\" );\n\tequal( menu.find( \".ui-menu-item\" ).text(), \"javajavascript\" );\n});\n\nfunction sourceTest( source, async ) {\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: source\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\tfunction result() {\n\t\tequal( menu.find( \".ui-menu-item\" ).text(), \"javajavascript\" );\n\t\telement.autocomplete( \"destroy\" );\n\t\tif ( async ) {\n\t\t\tstart();\n\t\t}\n\t}\n\tif ( async ) {\n\t\tstop();\n\t\t$( document ).one( \"ajaxStop\", result );\n\t}\n\telement.val( \"ja\" ).autocomplete( \"search\" );\n\tif ( !async ) {\n\t\tresult();\n\t}\n}\n\ntest( \"source, local object array, only label property\", function() {\n\texpect( 1 );\n\tsourceTest([\n\t\t{ label: \"java\" },\n\t\t{ label: \"php\" },\n\t\t{ label: \"coldfusion\" },\n\t\t{ label: \"javascript\" }\n\t]);\n});\n\ntest( \"source, local object array, only value property\", function() {\n\texpect( 1 );\n\tsourceTest([\n\t\t{ value: \"java\" },\n\t\t{ value: \"php\" },\n\t\t{ value: \"coldfusion\" },\n\t\t{ value: \"javascript\" }\n\t]);\n});\n\ntest( \"source, url string with remote json string array\", function() {\n\texpect( 1 );\n\tsourceTest( \"remote_string_array.txt\", true );\n});\n\ntest( \"source, url string with remote json object array, only value properties\", function() {\n\texpect( 1 );\n\tsourceTest( \"remote_object_array_values.txt\", true );\n});\n\ntest( \"source, url string with remote json object array, only label properties\", function() {\n\texpect( 1 );\n\tsourceTest( \"remote_object_array_labels.txt\", true );\n});\n\ntest( \"source, custom\", function() {\n\texpect( 2 );\n\tsourceTest(function( request, response ) {\n\t\tequal( request.term, \"ja\" );\n\t\tresponse( [\"java\", \"javascript\"] );\n\t});\n});\n\ntest( \"source, update after init\", function() {\n\texpect( 2 );\n\tvar element = $( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: [ \"java\", \"javascript\", \"haskell\" ]\n\t\t}),\n\t\tmenu = element.autocomplete( \"widget\" );\n\telement.val( \"ja\" ).autocomplete( \"search\" );\n\tequal( menu.find( \".ui-menu-item\" ).text(), \"javajavascript\" );\n\telement.autocomplete( \"option\", \"source\", [ \"php\", \"asp\" ] );\n\telement.val( \"ph\" ).autocomplete( \"search\" );\n\tequal( menu.find( \".ui-menu-item\" ).text(), \"php\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/remote_object_array_labels.txt",
    "content": "[{\"label\":\"java\"},{\"label\":\"javascript\"}]"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/remote_object_array_values.txt",
    "content": "[{\"value\":\"java\"},{\"value\":\"javascript\"}]"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/autocomplete/remote_string_array.txt",
    "content": "[\"java\", \"javascript\"]"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"button\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Button Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Button Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.button\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.button.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"button_common.js\"></script>\n\t<script src=\"button_core.js\"></script>\n\t<script src=\"button_events.js\"></script>\n\t<script src=\"button_methods.js\"></script>\n\t<script src=\"button_options.js\"></script>\n\t<script src=\"button_tickets.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Button Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div><button id=\"button\" class=\"foo\">Label</button></div>\n\n<div id=\"radio0\" style=\"margin-top: 2em;\">\n\t<input type=\"radio\" id=\"radio01\" name=\"radio\" checked=\"checked\"><label for=\"radio01\">Choice 1</label>\n\t<input type=\"radio\" id=\"radio02\" name=\"radio\"><label for=\"radio02\">Choice 2</label>\n\t<input type=\"radio\" id=\"radio03\" name=\"radio\"><label for=\"radio03\">Choice 3</label>\n</div>\n<form>\n\t<div id=\"radio1\" style=\"margin-top: 2em;\">\n\t\t<input type=\"radio\" id=\"radio11\" name=\"radio\"><label for=\"radio11\">Choice 1</label>\n\t\t<input type=\"radio\" id=\"radio12\" name=\"radio\" checked=\"checked\"><label for=\"radio12\">Choice 2</label>\n\t\t<input type=\"radio\" id=\"radio13\" name=\"radio\"><label for=\"radio13\">Choice 3</label>\n\t</div>\n</form>\n<form>\n\t<div id=\"radio2\" style=\"margin-top: 2em;\">\n\t\t<input type=\"radio\" id=\"radio21\" name=\"radio\"><label for=\"radio21\">Choice 1</label>\n\t\t<input type=\"radio\" id=\"radio22\" name=\"radio\"><label for=\"radio22\">Choice 2</label>\n\t\t<input type=\"radio\" id=\"radio23\" name=\"radio\" checked=\"checked\"><label for=\"radio23\">Choice 3</label>\n\t</div>\n</form>\n\n<input type=\"checkbox\" id=\"check\"><label for=\"check\">Toggle</label>\n\n<div><input id=\"submit\" type=\"submit\" value=\"Label\"></div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button_common.js",
    "content": "TestHelpers.commonWidgetTests( \"button\", {\n\tdefaults: {\n\t\tdisabled: null,\n\t\ticons: {\n\t\t\tprimary: null,\n\t\t\tsecondary: null\n\t\t},\n\t\tlabel: null,\n\t\ttext: true,\n\n\t\t// callbacks\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button_core.js",
    "content": "/*\n * button_core.js\n */\n\n\n(function($) {\n\nmodule(\"button: core\");\n\ntest(\"checkbox\", function() {\n\tvar input = $(\"#check\"),\n\t\tlabel = $(\"label[for=check]\");\n\tok( input.is(\":visible\") );\n\tok( label.is(\":not(.ui-button)\") );\n\tinput.button();\n\tok( input.is(\".ui-helper-hidden-accessible\") );\n\tok( label.is(\".ui-button\") );\n});\n\ntest(\"radios\", function() {\n\tvar inputs = $(\"#radio0 input\"),\n\t\tlabels = $(\"#radio0 label\");\n\tok( inputs.is(\":visible\") );\n\tok( labels.is(\":not(.ui-button)\") );\n\tinputs.button();\n\tok( inputs.is(\".ui-helper-hidden-accessible\") );\n\tok( labels.is(\".ui-button\") );\n});\n\nfunction assert(noForm, form1, form2) {\n\tok( $(\"#radio0 .ui-button\" + noForm).is(\".ui-state-active\") );\n\tok( $(\"#radio1 .ui-button\" + form1).is(\".ui-state-active\") );\n\tok( $(\"#radio2 .ui-button\" + form2).is(\".ui-state-active\") );\n}\n\ntest(\"radio groups\", function() {\n\t$(\"input[type=radio]\").button();\n\tassert(\":eq(0)\", \":eq(1)\", \":eq(2)\");\n\n\t// click outside of forms\n\t$(\"#radio0 .ui-button:eq(1)\").click();\n\tassert(\":eq(1)\", \":eq(1)\", \":eq(2)\");\n\n\t// click in first form\n\t$(\"#radio1 .ui-button:eq(0)\").click();\n\tassert(\":eq(1)\", \":eq(0)\", \":eq(2)\");\n\n\t// click in second form\n\t$(\"#radio2 .ui-button:eq(0)\").click();\n\tassert(\":eq(1)\", \":eq(0)\", \":eq(0)\");\n});\n\ntest(\"input type submit, don't create child elements\", function() {\n\tvar input = $(\"#submit\");\n\tdeepEqual( input.children().length, 0 );\n\tinput.button();\n\tdeepEqual( input.children().length, 0 );\n});\n\ntest(\"buttonset\", function() {\n\tvar set = $(\"#radio1\").buttonset();\n\tok( set.is(\".ui-buttonset\") );\n\tdeepEqual( set.children(\".ui-button\").length, 3 );\n\tdeepEqual( set.children(\"input[type=radio].ui-helper-hidden-accessible\").length, 3 );\n\tok( set.children(\"label:eq(0)\").is(\".ui-button.ui-corner-left:not(.ui-corner-all)\") );\n\tok( set.children(\"label:eq(1)\").is(\".ui-button:not(.ui-corner-all)\") );\n\tok( set.children(\"label:eq(2)\").is(\".ui-button.ui-corner-right:not(.ui-corner-all)\") );\n});\n\ntest(\"buttonset (rtl)\", function() {\n\tvar set,\n\t\tparent = $(\"#radio1\").parent();\n\t// Set to rtl\n\tparent.attr(\"dir\", \"rtl\");\n\n\tset = $(\"#radio1\").buttonset();\n\tok( set.is(\".ui-buttonset\") );\n\tdeepEqual( set.children(\".ui-button\").length, 3 );\n\tdeepEqual( set.children(\"input[type=radio].ui-helper-hidden-accessible\").length, 3 );\n\tok( set.children(\"label:eq(0)\").is(\".ui-button.ui-corner-right:not(.ui-corner-all)\") );\n\tok( set.children(\"label:eq(1)\").is(\".ui-button:not(.ui-corner-all)\") );\n\tok( set.children(\"label:eq(2)\").is(\".ui-button.ui-corner-left:not(.ui-corner-all)\") );\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button_events.js",
    "content": "/*\n * button_events.js\n */\n(function($) {\n\nmodule(\"button: events\");\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button_methods.js",
    "content": "/*\n * button_methods.js\n */\n(function($) {\n\n\nmodule(\"button: methods\");\n\ntest(\"destroy\", function() {\n\tvar beforeHtml = $(\"#button\").parent().html(),\n\t\tafterHtml = $(\"#button\").button().button(\"destroy\").parent().html();\n\t// Opera 9 outputs role=\"\" instead of removing the attribute like everyone else\n\tif ($.browser.opera) {\n\t\tafterHtml = afterHtml.replace(/ role=\"\"/g, \"\");\n\t}\n\tequal( afterHtml, beforeHtml );\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button_options.js",
    "content": "/*\n * button_options.js\n */\n(function($) {\n\nmodule(\"button: options\");\n\ntest(\"disabled, explicit value\", function() {\n\t$(\"#radio01\").button({ disabled: false });\n\tdeepEqual(false, $(\"#radio01\").button(\"option\", \"disabled\"),\n\t\t\"disabled option set to false\");\n\tdeepEqual(false, $(\"#radio01\").prop(\"disabled\"), \"element is disabled\");\n\n\t$(\"#radio02\").button({ disabled: true });\n\tdeepEqual(true, $(\"#radio02\").button(\"option\", \"disabled\"),\n\t\t\"disabled option set to true\");\n\tdeepEqual(true, $(\"#radio02\").prop(\"disabled\"), \"element is not disabled\");\n});\n\ntest(\"disabled, null\", function() {\n\t$(\"#radio01\").button({ disabled: null });\n\tdeepEqual(false, $(\"#radio01\").button(\"option\", \"disabled\"),\n\t\t\"disabled option set to false\");\n\tdeepEqual(false, $(\"#radio01\").prop(\"disabled\"), \"element is disabled\");\n\n\t$(\"#radio02\").prop(\"disabled\", true).button({ disabled: null });\n\tdeepEqual(true, $(\"#radio02\").button(\"option\", \"disabled\"),\n\t\t\"disabled option set to true\");\n\tdeepEqual(true, $(\"#radio02\").prop(\"disabled\"), \"element is not disabled\");\n});\n\ntest(\"text false without icon\", function() {\n\t$(\"#button\").button({\n\t\ttext: false\n\t});\n\tok( $(\"#button\").is(\".ui-button-text-only:not(.ui-button-icon-only)\") );\n\n\t$(\"#button\").button(\"destroy\");\n});\n\ntest(\"text false with icon\", function() {\n\t$(\"#button\").button({\n\t\ttext: false,\n\t\ticons: {\n\t\t\tprimary: \"iconclass\"\n\t\t}\n\t});\n\tok( $(\"#button\").is(\".ui-button-icon-only:not(.ui-button-text):has(span.ui-icon.iconclass)\") );\n\n\t$(\"#button\").button(\"destroy\");\n});\n\ntest(\"label, default\", function() {\n\t$(\"#button\").button();\n\tdeepEqual( $(\"#button\").text(), \"Label\" );\n\tdeepEqual( $( \"#button\").button( \"option\", \"label\" ), \"Label\" );\n\n\t$(\"#button\").button(\"destroy\");\n});\n\ntest(\"label\", function() {\n\t$(\"#button\").button({\n\t\tlabel: \"xxx\"\n\t});\n\tdeepEqual( $(\"#button\").text(), \"xxx\" );\n\tdeepEqual( $(\"#button\").button( \"option\", \"label\" ), \"xxx\" );\n\n\t$(\"#button\").button(\"destroy\");\n});\n\ntest(\"label default with input type submit\", function() {\n\tdeepEqual( $(\"#submit\").button().val(), \"Label\" );\n\tdeepEqual( $(\"#submit\").button( \"option\", \"label\" ), \"Label\" );\n});\n\ntest(\"label with input type submit\", function() {\n\tvar label = $(\"#submit\").button({\n\t\tlabel: \"xxx\"\n\t}).val();\n\tdeepEqual( label, \"xxx\" );\n\tdeepEqual( $(\"#submit\").button( \"option\", \"label\" ), \"xxx\" );\n});\n\ntest(\"icons\", function() {\n\t$(\"#button\").button({\n\t\ttext: false,\n\t\ticons: {\n\t\t\tprimary: \"iconclass\",\n\t\t\tsecondary: \"iconclass2\"\n\t\t}\n\t});\n\tok( $(\"#button\").is(\":has(span.ui-icon.ui-button-icon-primary.iconclass):has(span.ui-icon.ui-button-icon-secondary.iconclass2)\") );\n\n\t$(\"#button\").button(\"destroy\");\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/button/button_tickets.js",
    "content": "/*\n * button_tickets.js\n */\n(function( $ ) {\n\nmodule( \"button: tickets\" );\n\ntest( \"#5946 - buttonset should ignore buttons that are not :visible\", function() {\n\t$( \"#radio01\" ).next().andSelf().hide();\n\tvar set = $( \"#radio0\" ).buttonset({ items: \"input[type=radio]:visible\" });\n\tok( set.find( \"label:eq(0)\" ).is( \":not(.ui-button):not(.ui-corner-left)\" ) );\n\tok( set.find( \"label:eq(1)\" ).is( \".ui-button.ui-corner-left\" ) );\n});\n\ntest( \"#6262 - buttonset not applying ui-corner to invisible elements\", function() {\n\t$( \"#radio0\" ).hide();\n\tvar set = $( \"#radio0\" ).buttonset();\n\tok( set.find( \"label:eq(0)\" ).is( \".ui-button.ui-corner-left\" ) );\n\tok( set.find( \"label:eq(1)\" ).is( \".ui-button\" ) );\n\tok( set.find( \"label:eq(2)\" ).is( \".ui-button.ui-corner-right\" ) );\n});\n\ntest( \"#6711 Checkbox/Radiobutton do not Show Focused State when using Keyboard Navigation\", function() {\n\tvar check = $( \"#check\" ).button(),\n\t\tlabel = $( \"label[for='check']\" );\n\tok( !label.is( \".ui-state-focus\" ) );\n\tcheck.focus();\n\tok( label.is( \".ui-state-focus\" ) );\n});\n\ntest( \"#7092 - button creation that requires a matching label does not find label in all cases\", function() {\n\tvar group = $( \"<span><label for='t7092a'></label><input type='checkbox' id='t7092a'></span>\" );\n\tgroup.find( \"input[type=checkbox]\" ).button();\n\tok( group.find( \"label\" ).is( \".ui-button\" ) );\n\n\tgroup = $( \"<input type='checkbox' id='t7092b'><label for='t7092b'></label>\" );\n\tgroup.filter( \"input[type=checkbox]\" ).button();\n\tok( group.filter( \"label\" ).is( \".ui-button\" ) );\n\n\tgroup = $( \"<span><input type='checkbox' id='t7092c'></span><label for='t7092c'></label>\" );\n\tgroup.find( \"input[type=checkbox]\" ).button();\n\tok( group.filter( \"label\" ).is( \".ui-button\" ) );\n\n\tgroup = $( \"<span><input type='checkbox' id='t7092d'></span><span><label for='t7092d'></label></span>\" );\n\tgroup.find( \"input[type=checkbox]\" ).button();\n\tok( group.find( \"label\" ).is( \".ui-button\" ) );\n\n\tgroup = $( \"<input type='checkbox' id='t7092e'><span><label for='t7092e'></label></span>\" );\n\tgroup.filter( \"input[type=checkbox]\" ).button();\n\tok( group.find( \"label\" ).is( \".ui-button\" ) );\n});\n\ntest( \"#7534 - Button label selector works for ids with \\\":\\\"\", function() {\n\tvar group = $( \"<span><input type='checkbox' id='check:7534'><label for='check:7534'>Label</label></span>\" );\n\tgroup.find( \"input\" ).button();\n\tok( group.find( \"label\" ).is( \".ui-button\" ), \"Found an id with a :\" );\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/core/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Core Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"core\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Core Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/core/core.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Core Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tjs: [ \"ui/jquery.ui.core.js\" ]\n\t});\n\t</script>\n\n\t<script src=\"core.js\"></script>\n\t<script src=\"selector.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t.zindex {\n\t\tz-index: 100;\n\t}\n\t.absolute {\n\t\tposition: absolute;\n\t}\n\t</style>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Core Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<img src=\"../images/jqueryui_32x32.png\" usemap=\"#mymap\" width=\"10\" height=\"10\" alt=\"\">\n<map name=\"mymap\">\n\t<area shape=\"rect\" coords=\"1,1,2,2\" href=\"foo.html\" id=\"areaCoordsHref\" alt=\"\">\n\t<area href=\"foo.html\" id=\"areaNoCoordsHref\" alt=\"\">\n</map>\n<map name=\"mymap2\">\n\t<area shape=\"rect\" coords=\"1,1,2,2\" href=\"foo.html\" id=\"areaNoImg\" alt=\"\">\n</map>\n\n<form id=\"formNoTabindex\"></form>\n<form id=\"formTabindex\" tabindex=\"1\"></form>\n\n<div>\n\t<input id=\"visibleAncestor-inputTypeNone\">\n\t<input type=\"text\" id=\"visibleAncestor-inputTypeText\">\n\t<input type=\"checkbox\" id=\"visibleAncestor-inputTypeCheckbox\">\n\t<input type=\"radio\" id=\"visibleAncestor-inputTypeRadio\">\n\t<input type=\"button\" id=\"visibleAncestor-inputTypeButton\" value=\"visibleAncestor-inputTypeButton\">\n\t<input type=\"hidden\" id=\"visibleAncestor-inputTypeHidden\">\n\t<button id=\"visibleAncestor-button\">x</button>\n\t<select id=\"visibleAncestor-select\">\n\t\t<option>option</option>\n\t</select>\n\t<textarea id=\"visibleAncestor-textarea\">x</textarea>\n\t<object id=\"visibleAncestor-object\" codebase=\"about:blank\">xxx</object>\n\t<a href=\"#\" id=\"visibleAncestor-anchorWithHref\">anchor</a>\n\t<a id=\"visibleAncestor-anchorWithoutHref\">anchor</a>\n\t<span id=\"visibleAncestor-span\">x</span>\n\t<div id=\"visibleAncestor-div\">x</div>\n\t<span id=\"visibleAncestor-spanWithTabindex\" tabindex=\"1\">x</span>\n\t<div id=\"visibleAncestor-divWithNegativeTabindex\" tabindex=\"-1\">x</div>\n</div>\n\n<div>\n\t<input id=\"disabledElement-inputTypeNone\" disabled=\"disabled\">\n\t<input type=\"text\" id=\"disabledElement-inputTypeText\" disabled=\"disabled\">\n\t<input type=\"checkbox\" id=\"disabledElement-inputTypeCheckbox\" disabled=\"disabled\">\n\t<input type=\"radio\" id=\"disabledElement-inputTypeRadio\" disabled=\"disabled\">\n\t<input type=\"button\" id=\"disabledElement-inputTypeButton\" disabled=\"disabled\" value=\"disabledElement-inputTypeButton\">\n\t<input type=\"hidden\" id=\"disabledElement-inputTypeHidden\" disabled=\"disabled\">\n\t<button id=\"disabledElement-button\" disabled=\"disabled\"></button>\n\t<select id=\"disabledElement-select\" disabled=\"disabled\"></select>\n\t<textarea id=\"disabledElement-textarea\" disabled=\"disabled\"></textarea>\n</div>\n\n<div>\n\t<div id=\"displayNoneAncestor\" style=\"display: none;\">\n\t\t<input id=\"displayNoneAncestor-input\">\n\t\t<span tabindex=\"1\" id=\"displayNoneAncestor-span\">.</span>\n\t</div>\n\n\t<div id=\"visibilityHiddenAncestor\" style=\"visibility: hidden;\">\n\t\t<input id=\"visibilityHiddenAncestor-input\">\n\t\t<span tabindex=\"1\" id=\"visibilityHiddenAncestor-span\">.</span>\n\t</div>\n\n\t<span tabindex=\"1\" id=\"displayNone-span\" style=\"display: none;\">.</span>\n\t<span tabindex=\"1\" id=\"visibilityHidden-span\" style=\"visibility: hidden;\">.</span>\n\n\t<input id=\"displayNone-input\" style=\"display: none;\">\n\t<input id=\"visibilityHidden-input\" style=\"visibility: hidden;\">\n</div>\n\n<div>\n\t<input id=\"inputTabindex0\" tabindex=\"0\">\n\t<input id=\"inputTabindex10\" tabindex=\"10\">\n\t<input id=\"inputTabindex-1\" tabindex=\"-1\">\n\t<input id=\"inputTabindex-50\" tabindex=\"-50\">\n\n\t<span id=\"spanTabindex0\" tabindex=\"0\">.</span>\n\t<span id=\"spanTabindex10\" tabindex=\"10\">.</span>\n\t<span id=\"spanTabindex-1\" tabindex=\"-1\">.</span>\n\t<span id=\"spanTabindex-50\" tabindex=\"-50\">.</span>\n</div>\n\n<div id=\"zIndex100\" style=\"z-index: 100; position: absolute\">\n\t<div id=\"zIndexAutoWithParent\">.</div>\n</div>\n<div id=\"zIndex100ViaCSS\" class=\"zindex\">\n\t<div id=\"zIndexAutoWithParentViaCSS\">.</div>\n</div>\n<div id=\"zIndex100ViaCSSPositioned\" class=\"zindex absolute\">\n\t<div id=\"zIndexAutoWithParentViaCSSPositioned\">.</div>\n</div>\n<div id=\"zIndexAutoNoParent\"></div>\n\n<div id=\"dimensions\" style=\"float: left; height: 50px; width: 100px; margin: 1px 12px 11px 2px; border-style: solid; border-width: 3px 14px 13px 4px; padding: 5px 16px 15px 6px;\"></div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/core/core.js",
    "content": "(function( $ ) {\n\nmodule( \"core - jQuery extensions\" );\n\nTestHelpers.testJshint( \"ui.core\" );\n\ntest( \"focus - original functionality\", function() {\n\texpect( 1 );\n\t$( \"#inputTabindex0\" )\n\t\t.focus(function() {\n\t\t\tok( true, \"event triggered\" );\n\t\t})\n\t\t.focus();\n});\n\nasyncTest( \"focus\", function() {\n\texpect( 2 );\n\t$( \"#inputTabindex0\" )\n\t\t.focus(function() {\n\t\t\tok( true, \"event triggered\" );\n\t\t})\n\t\t.focus( 500, function() {\n\t\t\t// prevent double focus event in IE\n\t\t\t$( this ).unbind( \"focus\" );\n\t\t\tok( true, \"callback triggered\" );\n\t\t\tstart();\n\t\t});\n});\n\ntest( \"zIndex\", function() {\n\tvar el = $( \"#zIndexAutoWithParent\" ),\n\t\tparent = el.parent();\n\tequal( el.zIndex(), 100, \"zIndex traverses up to find value\" );\n\tequal( parent.zIndex(200 ), parent, \"zIndex setter is chainable\" );\n\tequal( el.zIndex(), 200, \"zIndex setter changed zIndex\" );\n\n\tel = $( \"#zIndexAutoWithParentViaCSS\" );\n\tequal( el.zIndex(), 0, \"zIndex traverses up to find CSS value, not found because not positioned\" );\n\n\tel = $( \"#zIndexAutoWithParentViaCSSPositioned\" );\n\tequal( el.zIndex(), 100, \"zIndex traverses up to find CSS value\" );\n\tel.parent().zIndex( 200 );\n\tequal( el.zIndex(), 200, \"zIndex setter changed zIndex, overriding CSS\" );\n\n\tequal( $( \"#zIndexAutoNoParent\" ).zIndex(), 0, \"zIndex never explicitly set in hierarchy\" );\n});\n\ntest( \"innerWidth - getter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tequal( el.innerWidth(), 122, \"getter passthru\" );\n\tel.hide();\n\tequal( el.innerWidth(), 122, \"getter passthru when hidden\" );\n});\n\ntest( \"innerWidth - setter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tel.innerWidth( 120 );\n\tequal( el.width(), 98, \"width set properly\" );\n\tel.hide();\n\tel.innerWidth( 100 );\n\tequal( el.width(), 78, \"width set properly when hidden\" );\n});\n\ntest( \"innerHeight - getter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tequal( el.innerHeight(), 70, \"getter passthru\" );\n\tel.hide();\n\tequal( el.innerHeight(), 70, \"getter passthru when hidden\" );\n});\n\ntest( \"innerHeight - setter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tel.innerHeight( 60 );\n\tequal( el.height(), 40, \"height set properly\" );\n\tel.hide();\n\tel.innerHeight( 50 );\n\tequal( el.height(), 30, \"height set properly when hidden\" );\n});\n\ntest( \"outerWidth - getter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tequal( el.outerWidth(), 140, \"getter passthru\" );\n\tel.hide();\n\tequal( el.outerWidth(), 140, \"getter passthru when hidden\" );\n});\n\ntest( \"outerWidth - setter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tel.outerWidth( 130 );\n\tequal( el.width(), 90, \"width set properly\" );\n\tel.hide();\n\tel.outerWidth( 120 );\n\tequal( el.width(), 80, \"width set properly when hidden\" );\n});\n\ntest( \"outerWidth(true) - getter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tequal( el.outerWidth(true), 154, \"getter passthru w/ margin\" );\n\tel.hide();\n\tequal( el.outerWidth(true), 154, \"getter passthru w/ margin when hidden\" );\n});\n\ntest( \"outerWidth(true) - setter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tel.outerWidth( 130, true );\n\tequal( el.width(), 76, \"width set properly\" );\n\tel.hide();\n\tel.outerWidth( 120, true );\n\tequal( el.width(), 66, \"width set properly when hidden\" );\n});\n\ntest( \"outerHeight - getter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tequal( el.outerHeight(), 86, \"getter passthru\" );\n\tel.hide();\n\tequal( el.outerHeight(), 86, \"getter passthru when hidden\" );\n});\n\ntest( \"outerHeight - setter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tel.outerHeight( 80 );\n\tequal( el.height(), 44, \"height set properly\" );\n\tel.hide();\n\tel.outerHeight( 70 );\n\tequal( el.height(), 34, \"height set properly when hidden\" );\n});\n\ntest( \"outerHeight(true) - getter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tequal( el.outerHeight(true), 98, \"getter passthru w/ margin\" );\n\tel.hide();\n\tequal( el.outerHeight(true), 98, \"getter passthru w/ margin when hidden\" );\n});\n\ntest( \"outerHeight(true) - setter\", function() {\n\tvar el = $( \"#dimensions\" );\n\n\tel.outerHeight( 90, true );\n\tequal( el.height(), 42, \"height set properly\" );\n\tel.hide();\n\tel.outerHeight( 80, true );\n\tequal( el.height(), 32, \"height set properly when hidden\" );\n});\n\ntest( \"uniqueId / removeUniqueId\", function() {\n\tvar el = $( \"img\" ).eq( 0 );\n\n\tequal( el.attr( \"id\" ), undefined, \"element has no initial id\" );\n\tel.uniqueId();\n\tok( /ui-id-\\d+$/.test( el.attr( \"id\" ) ), \"element has generated id\" );\n\tel.removeUniqueId();\n\tequal( el.attr( \"id\" ), undefined, \"unique id has been removed from element\" );\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/core/selector.js",
    "content": "/*\n * selector unit tests\n */\n(function($) {\n\nmodule(\"core - selectors\");\n\nfunction isFocusable(selector, msg) {\n\tQUnit.push($(selector).is(':focusable'), null, null, msg + \" - selector \" + selector + \" is focusable\");\n}\n\nfunction isNotFocusable(selector, msg) {\n\tQUnit.push($(selector).length && !$(selector).is(':focusable'), null, null, msg + \" - selector \" + selector + \" is not focusable\");\n}\n\nfunction isTabbable(selector, msg) {\n\tQUnit.push($(selector).is(':tabbable'), null, null, msg + \" - selector \" + selector + \" is tabbable\");\n}\n\nfunction isNotTabbable(selector, msg) {\n\tQUnit.push($(selector).length && !$(selector).is(':tabbable'), null, null, msg + \" - selector \" + selector + \" is not tabbable\");\n}\n\ntest(\"data\", function() {\n\texpect(15);\n\n\tvar el;\n\tfunction shouldHaveData(msg) {\n\t\tok(el.is(':data(test)'), msg);\n\t}\n\tfunction shouldNotHaveData(msg) {\n\t\tok(!el.is(':data(test)'), msg);\n\t}\n\n\tel = $('<div>');\n\tshouldNotHaveData('data never set');\n\n\tel = $('<div>').data('test', null);\n\tshouldNotHaveData('data is null');\n\n\tel = $('<div>').data('test', true);\n\tshouldHaveData('data set to true');\n\n\tel = $('<div>').data('test', false);\n\tshouldNotHaveData('data set to false');\n\n\tel = $('<div>').data('test', 0);\n\tshouldNotHaveData('data set to 0');\n\n\tel = $('<div>').data('test', 1);\n\tshouldHaveData('data set to 1');\n\n\tel = $('<div>').data('test', '');\n\tshouldNotHaveData('data set to empty string');\n\n\tel = $('<div>').data('test', 'foo');\n\tshouldHaveData('data set to string');\n\n\tel = $('<div>').data('test', []);\n\tshouldHaveData('data set to empty array');\n\n\tel = $('<div>').data('test', [1]);\n\tshouldHaveData('data set to array');\n\n\tel = $('<div>').data('test', {});\n\tshouldHaveData('data set to empty object');\n\n\tel = $('<div>').data('test', {foo: 'bar'});\n\tshouldHaveData('data set to object');\n\n\tel = $('<div>').data('test', new Date());\n\tshouldHaveData('data set to date');\n\n\tel = $('<div>').data('test', /test/);\n\tshouldHaveData('data set to regexp');\n\n\tel = $('<div>').data('test', function() {});\n\tshouldHaveData('data set to function');\n});\n\ntest(\"focusable - visible, enabled elements\", function() {\n\texpect(18);\n\n\tisNotFocusable('#formNoTabindex', 'form');\n\tisFocusable('#formTabindex', 'form with tabindex');\n\tisFocusable('#visibleAncestor-inputTypeNone', 'input, no type');\n\tisFocusable('#visibleAncestor-inputTypeText', 'input, type text');\n\tisFocusable('#visibleAncestor-inputTypeCheckbox', 'input, type checkbox');\n\tisFocusable('#visibleAncestor-inputTypeRadio', 'input, type radio');\n\tisFocusable('#visibleAncestor-inputTypeButton', 'input, type button');\n\tisNotFocusable('#visibleAncestor-inputTypeHidden', 'input, type hidden');\n\tisFocusable('#visibleAncestor-button', 'button');\n\tisFocusable('#visibleAncestor-select', 'select');\n\tisFocusable('#visibleAncestor-textarea', 'textarea');\n\tisFocusable('#visibleAncestor-object', 'object');\n\tisFocusable('#visibleAncestor-anchorWithHref', 'anchor with href');\n\tisNotFocusable('#visibleAncestor-anchorWithoutHref', 'anchor without href');\n\tisNotFocusable('#visibleAncestor-span', 'span');\n\tisNotFocusable('#visibleAncestor-div', 'div');\n\tisFocusable(\"#visibleAncestor-spanWithTabindex\", 'span with tabindex');\n\tisFocusable(\"#visibleAncestor-divWithNegativeTabindex\", 'div with tabindex');\n});\n\ntest(\"focusable - disabled elements\", function() {\n\texpect(9);\n\n\tisNotFocusable('#disabledElement-inputTypeNone', 'input, no type');\n\tisNotFocusable('#disabledElement-inputTypeText', 'input, type text');\n\tisNotFocusable('#disabledElement-inputTypeCheckbox', 'input, type checkbox');\n\tisNotFocusable('#disabledElement-inputTypeRadio', 'input, type radio');\n\tisNotFocusable('#disabledElement-inputTypeButton', 'input, type button');\n\tisNotFocusable('#disabledElement-inputTypeHidden', 'input, type hidden');\n\tisNotFocusable('#disabledElement-button', 'button');\n\tisNotFocusable('#disabledElement-select', 'select');\n\tisNotFocusable('#disabledElement-textarea', 'textarea');\n});\n\ntest(\"focusable - hidden styles\", function() {\n\texpect(8);\n\n\tisNotFocusable('#displayNoneAncestor-input', 'input, display: none parent');\n\tisNotFocusable('#displayNoneAncestor-span', 'span with tabindex, display: none parent');\n\n\tisNotFocusable('#visibilityHiddenAncestor-input', 'input, visibility: hidden parent');\n\tisNotFocusable('#visibilityHiddenAncestor-span', 'span with tabindex, visibility: hidden parent');\n\n\tisNotFocusable('#displayNone-input', 'input, display: none');\n\tisNotFocusable('#visibilityHidden-input', 'input, visibility: hidden');\n\n\tisNotFocusable('#displayNone-span', 'span with tabindex, display: none');\n\tisNotFocusable('#visibilityHidden-span', 'span with tabindex, visibility: hidden');\n});\n\ntest(\"focusable - natively focusable with various tabindex\", function() {\n\texpect(4);\n\n\tisFocusable('#inputTabindex0', 'input, tabindex 0');\n\tisFocusable('#inputTabindex10', 'input, tabindex 10');\n\tisFocusable('#inputTabindex-1', 'input, tabindex -1');\n\tisFocusable('#inputTabindex-50', 'input, tabindex -50');\n});\n\ntest(\"focusable - not natively focusable with various tabindex\", function() {\n\texpect(4);\n\n\tisFocusable('#spanTabindex0', 'span, tabindex 0');\n\tisFocusable('#spanTabindex10', 'span, tabindex 10');\n\tisFocusable('#spanTabindex-1', 'span, tabindex -1');\n\tisFocusable('#spanTabindex-50', 'span, tabindex -50');\n});\n\ntest(\"focusable - area elements\", function() {\n\tisFocusable('#areaCoordsHref', 'coords and href');\n\tisFocusable('#areaNoCoordsHref', 'href but no coords');\n\tisNotFocusable('#areaNoImg', 'not associated with an image');\n});\n\ntest(\"tabbable - visible, enabled elements\", function() {\n\texpect(18);\n\n\tisNotTabbable('#formNoTabindex', 'form');\n\tisTabbable('#formTabindex', 'form with tabindex');\n\tisTabbable('#visibleAncestor-inputTypeNone', 'input, no type');\n\tisTabbable('#visibleAncestor-inputTypeText', 'input, type text');\n\tisTabbable('#visibleAncestor-inputTypeCheckbox', 'input, type checkbox');\n\tisTabbable('#visibleAncestor-inputTypeRadio', 'input, type radio');\n\tisTabbable('#visibleAncestor-inputTypeButton', 'input, type button');\n\tisNotTabbable('#visibleAncestor-inputTypeHidden', 'input, type hidden');\n\tisTabbable('#visibleAncestor-button', 'button');\n\tisTabbable('#visibleAncestor-select', 'select');\n\tisTabbable('#visibleAncestor-textarea', 'textarea');\n\tisTabbable('#visibleAncestor-object', 'object');\n\tisTabbable('#visibleAncestor-anchorWithHref', 'anchor with href');\n\tisNotTabbable('#visibleAncestor-anchorWithoutHref', 'anchor without href');\n\tisNotTabbable('#visibleAncestor-span', 'span');\n\tisNotTabbable('#visibleAncestor-div', 'div');\n\tisTabbable(\"#visibleAncestor-spanWithTabindex\", 'span with tabindex');\n\tisNotTabbable(\"#visibleAncestor-divWithNegativeTabindex\", 'div with tabindex');\n});\n\ntest(\"tabbable - disabled elements\", function() {\n\texpect(9);\n\n\tisNotTabbable('#disabledElement-inputTypeNone', 'input, no type');\n\tisNotTabbable('#disabledElement-inputTypeText', 'input, type text');\n\tisNotTabbable('#disabledElement-inputTypeCheckbox', 'input, type checkbox');\n\tisNotTabbable('#disabledElement-inputTypeRadio', 'input, type radio');\n\tisNotTabbable('#disabledElement-inputTypeButton', 'input, type button');\n\tisNotTabbable('#disabledElement-inputTypeHidden', 'input, type hidden');\n\tisNotTabbable('#disabledElement-button', 'button');\n\tisNotTabbable('#disabledElement-select', 'select');\n\tisNotTabbable('#disabledElement-textarea', 'textarea');\n});\n\ntest(\"tabbable - hidden styles\", function() {\n\texpect(8);\n\n\tisNotTabbable('#displayNoneAncestor-input', 'input, display: none parent');\n\tisNotTabbable('#displayNoneAncestor-span', 'span with tabindex, display: none parent');\n\n\tisNotTabbable('#visibilityHiddenAncestor-input', 'input, visibility: hidden parent');\n\tisNotTabbable('#visibilityHiddenAncestor-span', 'span with tabindex, visibility: hidden parent');\n\n\tisNotTabbable('#displayNone-input', 'input, display: none');\n\tisNotTabbable('#visibilityHidden-input', 'input, visibility: hidden');\n\n\tisNotTabbable('#displayNone-span', 'span with tabindex, display: none');\n\tisNotTabbable('#visibilityHidden-span', 'span with tabindex, visibility: hidden');\n});\n\ntest(\"tabbable -  natively tabbable with various tabindex\", function() {\n\texpect(4);\n\n\tisTabbable('#inputTabindex0', 'input, tabindex 0');\n\tisTabbable('#inputTabindex10', 'input, tabindex 10');\n\tisNotTabbable('#inputTabindex-1', 'input, tabindex -1');\n\tisNotTabbable('#inputTabindex-50', 'input, tabindex -50');\n});\n\ntest(\"tabbable -  not natively tabbable with various tabindex\", function() {\n\texpect(4);\n\n\tisTabbable('#spanTabindex0', 'span, tabindex 0');\n\tisTabbable('#spanTabindex10', 'span, tabindex 10');\n\tisNotTabbable('#spanTabindex-1', 'span, tabindex -1');\n\tisNotTabbable('#spanTabindex-50', 'span, tabindex -50');\n});\n\ntest(\"tabbable - area elements\", function() {\n\tisTabbable('#areaCoordsHref', 'coords and href');\n\tisTabbable('#areaNoCoordsHref', 'href but no coords');\n\tisNotTabbable('#areaNoImg', 'not associated with an image');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"datepicker\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Datepicker Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Datepicker Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.datepicker\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.datepicker.js\",\n\t\t\t\"ui/i18n/jquery.ui.datepicker-fr.js\",\n\t\t\t\"ui/i18n/jquery.ui.datepicker-he.js\",\n\t\t\t\"ui/i18n/jquery.ui.datepicker-zh-CN.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"datepicker_core.js\"></script>\n\t<script src=\"datepicker_defaults.js\"></script>\n\t<script src=\"datepicker_events.js\"></script>\n\t<script src=\"datepicker_methods.js\"></script>\n\t<script src=\"datepicker_options.js\"></script>\n\t<script src=\"datepicker_tickets.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"datepicker\", function() { ok(true, \"disabled datepicker testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Datepicker Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div><input type=\"text\" id=\"inp\"><input type=\"text\" id=\"alt\"><div id=\"inl\"></div></div>\n<p><input type=\"text\" id=\"inp2\"></p>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker_core.js",
    "content": "/*\n * datepicker_core.js\n */\n\nfunction equalsDate(d1, d2, message) {\n\tif (!d1 || !d2) {\n\t\tok(false, message + ' - missing date');\n\t\treturn;\n\t}\n\td1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate());\n\td2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate());\n\tequal(d1.toString(), d2.toString(), message);\n}\n\nfunction equalsDateArray(a1, a2, message) {\n\tif (!a1 || !a2) {\n\t\tok(false, message + ' - missing dates');\n\t\treturn;\n\t}\n\ta1[0] = (a1[0] ? new Date(a1[0].getFullYear(), a1[0].getMonth(), a1[0].getDate()) : '');\n\ta1[1] = (a1[1] ? new Date(a1[1].getFullYear(), a1[1].getMonth(), a1[1].getDate()) : '');\n\ta2[0] = (a2[0] ? new Date(a2[0].getFullYear(), a2[0].getMonth(), a2[0].getDate()) : '');\n\ta2[1] = (a2[1] ? new Date(a2[1].getFullYear(), a2[1].getMonth(), a2[1].getDate()) : '');\n\tdeepEqual(a1, a2, message);\n}\n\nfunction addMonths(date, offset) {\n\tvar maxDay = 32 - new Date(date.getFullYear(), date.getMonth() + offset, 32).getDate();\n\tdate.setDate(Math.min(date.getDate(), maxDay));\n\tdate.setMonth(date.getMonth() + offset);\n\treturn date;\n}\n\nfunction init(id, options) {\n\t$.datepicker.setDefaults($.datepicker.regional['']);\n\treturn $(id).datepicker($.extend({showAnim: ''}, options || {}));\n}\n\nvar PROP_NAME = 'datepicker';\n\n(function($) {\n\nmodule(\"datepicker: core\");\n\ntest( \"widget method - empty collection\", function() {\n\t$( \"#nonExist\" ).datepicker(); // should create nothing\n\tok( !$( \"#ui-datepicker-div\" ).length, \"Non init on empty collection\" );\n});\n\ntest(\"widget method\", function() {\n\tvar actual = $(\"#inp\").datepicker().datepicker(\"widget\")[0];\n\tdeepEqual($(\"body > #ui-datepicker-div:last-child\")[0], actual);\n});\n\ntest('baseStructure', function() {\n\tvar header, title, table, thead, week, panel, inl, child,\n\t\tinp = init('#inp').focus(),\n\t\tdp = $('#ui-datepicker-div'),\n\t\tiframe = ($.browser.msie && parseInt($.browser.version, 10) < 7);\n\tok(dp.is(':visible'), 'Structure - datepicker visible');\n\tok(!dp.is('.ui-datepicker-rtl'), 'Structure - not right-to-left');\n\tok(!dp.is('.ui-datepicker-multi'), 'Structure - not multi-month');\n\tequal(dp.children().length, 2 + (iframe ? 1 : 0), 'Structure - child count');\n\n\theader = dp.children(':first');\n\tok(header.is('div.ui-datepicker-header'), 'Structure - header division');\n\tequal(header.children().length, 3, 'Structure - header child count');\n\tok(header.children(':first').is('a.ui-datepicker-prev') && header.children(':first').html() !== '', 'Structure - prev link');\n\tok(header.children(':eq(1)').is('a.ui-datepicker-next') && header.children(':eq(1)').html() !== '', 'Structure - next link');\n\n\ttitle = header.children(':last');\n\tok(title.is('div.ui-datepicker-title') && title.html() !== '','Structure - title division');\n\tequal(title.children().length, 2, 'Structure - title child count');\n\tok(title.children(':first').is('span.ui-datepicker-month') && title.children(':first').text() !== '', 'Structure - month text');\n\tok(title.children(':last').is('span.ui-datepicker-year') && title.children(':last').text() !== '', 'Structure - year text');\n\n\ttable = dp.children(':eq(1)');\n\tok(table.is('table.ui-datepicker-calendar'), 'Structure - month table');\n\tok(table.children(':first').is('thead'), 'Structure - month table thead');\n\tthead = table.children(':first').children(':first');\n\tok(thead.is('tr'), 'Structure - month table title row');\n\tequal(thead.find('th').length, 7, 'Structure - month table title cells');\n\tok(table.children(':eq(1)').is('tbody'), 'Structure - month table body');\n\tok(table.children(':eq(1)').children('tr').length >= 4, 'Structure - month table week count');\n\tweek = table.children(':eq(1)').children(':first');\n\tok(week.is('tr'), 'Structure - month table week row');\n\tequal(week.children().length, 7, 'Structure - week child count');\n\tok(week.children(':first').is('td.ui-datepicker-week-end'), 'Structure - month table first day cell');\n\tok(week.children(':last').is('td.ui-datepicker-week-end'), 'Structure - month table second day cell');\n\tok(dp.children('iframe').length === (iframe ? 1 : 0), 'Structure - iframe');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Editable month/year and button panel\n\tinp = init('#inp', {changeMonth: true, changeYear: true, showButtonPanel: true});\n\tinp.focus();\n\n\ttitle = dp.find('div.ui-datepicker-title');\n\tok(title.children(':first').is('select.ui-datepicker-month'), 'Structure - month selector');\n\tok(title.children(':last').is('select.ui-datepicker-year'), 'Structure - year selector');\n\n\tpanel = dp.children(':last');\n\tok(panel.is('div.ui-datepicker-buttonpane'), 'Structure - button panel division');\n\tequal(panel.children().length, 2, 'Structure - button panel child count');\n\tok(panel.children(':first').is('button.ui-datepicker-current'), 'Structure - today button');\n\tok(panel.children(':last').is('button.ui-datepicker-close'), 'Structure - close button');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Multi-month 2\n\tinp = init('#inp', {numberOfMonths: 2});\n\tinp.focus();\n\tok(dp.is('.ui-datepicker-multi'), 'Structure multi [2] - multi-month');\n\tequal(dp.children().length, 3 + (iframe ? 1 : 0), 'Structure multi [2] - child count');\n\tchild = dp.children(':first');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-first'), 'Structure multi [2] - first month division');\n\tchild = dp.children(':eq(1)');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-last'), 'Structure multi [2] - second month division');\n\tchild = dp.children(':eq(2)');\n\tok(child.is('div.ui-datepicker-row-break'), 'Structure multi [2] - row break');\n\tok(dp.is('.ui-datepicker-multi-2'), 'Structure multi [2] - multi-2');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Multi-month 3\n\tinp = init('#inp', {numberOfMonths: 3});\n\tinp.focus();\n\tok(dp.is('.ui-datepicker-multi-3'), 'Structure multi [3] - multi-3');\n\tok(! dp.is('.ui-datepicker-multi-2'), 'Structure multi [3] - Trac #6704');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Multi-month [2, 2]\n\tinp = init('#inp', {numberOfMonths: [2, 2]});\n\tinp.focus();\n\tok(dp.is('.ui-datepicker-multi'), 'Structure multi - multi-month');\n\tequal(dp.children().length, 6 + (iframe ? 1 : 0), 'Structure multi [2,2] - child count');\n\tchild = dp.children(':first');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-first'), 'Structure multi [2,2] - first month division');\n\tchild = dp.children(':eq(1)');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-last'), 'Structure multi [2,2] - second month division');\n\tchild = dp.children(':eq(2)');\n\tok(child.is('div.ui-datepicker-row-break'), 'Structure multi [2,2] - row break');\n\tchild = dp.children(':eq(3)');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-first'), 'Structure multi [2,2] - third month division');\n\tchild = dp.children(':eq(4)');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-last'), 'Structure multi [2,2] - fourth month division');\n\tchild = dp.children(':eq(5)');\n\tok(child.is('div.ui-datepicker-row-break'), 'Structure multi [2,2] - row break');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Inline\n\tinl = init('#inl');\n\tdp = inl.children();\n\tok(dp.is('.ui-datepicker-inline'), 'Structure inline - main div');\n\tok(!dp.is('.ui-datepicker-rtl'), 'Structure inline - not right-to-left');\n\tok(!dp.is('.ui-datepicker-multi'), 'Structure inline - not multi-month');\n\tequal(dp.children().length, 2, 'Structure inline - child count');\n\theader = dp.children(':first');\n\tok(header.is('div.ui-datepicker-header'), 'Structure inline - header division');\n\tequal(header.children().length, 3, 'Structure inline - header child count');\n\ttable = dp.children(':eq(1)');\n\tok(table.is('table.ui-datepicker-calendar'), 'Structure inline - month table');\n\tok(table.children(':first').is('thead'), 'Structure inline - month table thead');\n\tok(table.children(':eq(1)').is('tbody'), 'Structure inline - month table body');\n\tinl.datepicker('destroy');\n\n\t// Inline multi-month\n\tinl = init('#inl', {numberOfMonths: 2});\n\tdp = inl.children();\n\tok(dp.is('.ui-datepicker-inline') && dp.is('.ui-datepicker-multi'), 'Structure inline multi - main div');\n\tequal(dp.children().length, 3 + (iframe ? 1 : 0), 'Structure inline multi - child count');\n\tchild = dp.children(':first');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-first'), 'Structure inline multi - first month division');\n\tchild = dp.children(':eq(1)');\n\tok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-last'), 'Structure inline multi - second month division');\n\tchild = dp.children(':eq(2)');\n\tok(child.is('div.ui-datepicker-row-break'), 'Structure inline multi - row break');\n\tinl.datepicker('destroy');\n});\n\ntest('customStructure', function() {\n\tvar iframe, header, panel, title, thead,\n\t\tdp = $('#ui-datepicker-div'),\n\t\t// Check right-to-left localisation\n\t\tinp = init('#inp', $.datepicker.regional.he);\n\tinp.data('showButtonPanel.datepicker',true);\n\tinp.focus();\n\tiframe = ($.browser.msie && parseInt($.browser.version, 10) < 7);\n\tok(dp.is('.ui-datepicker-rtl'), 'Structure RTL - right-to-left');\n\theader = dp.children(':first');\n\tok(header.is('div.ui-datepicker-header'), 'Structure RTL - header division');\n\tequal(header.children().length, 3, 'Structure RTL - header child count');\n\tok(header.children(':first').is('a.ui-datepicker-next'), 'Structure RTL - prev link');\n\tok(header.children(':eq(1)').is('a.ui-datepicker-prev'), 'Structure RTL - next link');\n\tpanel = dp.children(':last');\n\tok(panel.is('div.ui-datepicker-buttonpane'), 'Structure RTL - button division');\n\tequal(panel.children().length, 2, 'Structure RTL - button panel child count');\n\tok(panel.children(':first').is('button.ui-datepicker-close'), 'Structure RTL - close button');\n\tok(panel.children(':last').is('button.ui-datepicker-current'), 'Structure RTL - today button');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Hide prev/next\n\tinp = init('#inp', {hideIfNoPrevNext: true, minDate: new Date(2008, 2 - 1, 4), maxDate: new Date(2008, 2 - 1, 14)});\n\tinp.val('02/10/2008').focus();\n\theader = dp.children(':first');\n\tok(header.is('div.ui-datepicker-header'), 'Structure hide prev/next - header division');\n\tequal(header.children().length, 1, 'Structure hide prev/next - links child count');\n\tok(header.children(':first').is('div.ui-datepicker-title'), 'Structure hide prev/next - title division');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Changeable Month with read-only year\n\tinp = init('#inp', {changeMonth: true});\n\tinp.focus();\n\ttitle = dp.children(':first').children(':last');\n\tequal(title.children().length, 2, 'Structure changeable month - title child count');\n\tok(title.children(':first').is('select.ui-datepicker-month'), 'Structure changeable month - month selector');\n\tok(title.children(':last').is('span.ui-datepicker-year'), 'Structure changeable month - read-only year');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Changeable year with read-only month\n\tinp = init('#inp', {changeYear: true});\n\tinp.focus();\n\ttitle = dp.children(':first').children(':last');\n\tequal(title.children().length, 2, 'Structure changeable year - title child count');\n\tok(title.children(':first').is('span.ui-datepicker-month'), 'Structure changeable year - read-only month');\n\tok(title.children(':last').is('select.ui-datepicker-year'), 'Structure changeable year - year selector');\n\tinp.datepicker('hide').datepicker('destroy');\n\n\t// Read-only first day of week\n\tinp = init('#inp', {changeFirstDay: false});\n\tinp.focus();\n\tthead = dp.find('.ui-datepicker-calendar thead tr');\n\tequal(thead.children().length, 7, 'Structure read-only first day - thead child count');\n\tequal(thead.find('a').length, 0, 'Structure read-only first day - thead links count');\n\tinp.datepicker('hide').datepicker('destroy');\n});\n\ntest('keystrokes', function() {\n\tvar inp = init('#inp'),\n\t\tdate = new Date();\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke enter');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4),\n\t\t'Keystroke enter - preset');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.HOME}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+home');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.END});\n\tok(inp.datepicker('getDate') == null, 'Keystroke ctrl+end');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tok(inp.datepicker('getDate') == null, 'Keystroke esc');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4),\n\t\t'Keystroke esc - preset');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4),\n\t\t'Keystroke esc - abandoned');\n\t// Moving by day or week\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.LEFT}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 1);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+left');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.LEFT}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 1);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke left');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.RIGHT}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 1);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+right');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.RIGHT}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 1);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke right');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 7);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+up');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 7);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke up');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 7);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+down');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 7);\n\tequalsDate(inp.datepicker('getDate'), date, 'Keystroke down');\n\t// Moving by month or year\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 1 - 1, 4),\n\t\t'Keystroke pgup');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 3 - 1, 4),\n\t\t'Keystroke pgdn');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2007, 2 - 1, 4),\n\t\t'Keystroke ctrl+pgup');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2009, 2 - 1, 4),\n\t\t'Keystroke ctrl+pgdn');\n\t// Check for moving to short months\n\tinp.val('03/31/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 29),\n\t\t'Keystroke pgup - Feb');\n\tinp.val('01/30/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 29),\n\t\t'Keystroke pgdn - Feb');\n\tinp.val('02/29/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2007, 2 - 1, 28),\n\t\t'Keystroke ctrl+pgup - Feb');\n\tinp.val('02/29/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2009, 2 - 1, 28),\n\t\t'Keystroke ctrl+pgdn - Feb');\n\t// Goto current\n\tinp.datepicker('option', {gotoCurrent: true}).\n\t\tdatepicker('hide').val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.HOME}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4),\n\t\t'Keystroke ctrl+home');\n\t// Change steps\n\tinp.datepicker('option', {stepMonths: 2, gotoCurrent: false}).\n\t\tdatepicker('hide').val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2007, 12 - 1, 4),\n\t\t'Keystroke pgup step 2');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 4 - 1, 4),\n\t\t'Keystroke pgdn step 2');\n});\n\ntest('mouse', function() {\n\tvar inl,\n\t\tinp = init('#inp'),\n\t\tdp = $('#ui-datepicker-div'),\n\t\tdate = new Date();\n\tinp.val('').datepicker('show');\n\t$('.ui-datepicker-calendar tbody a:contains(10)', dp).simulate('click', {});\n\tdate.setDate(10);\n\tequalsDate(inp.datepicker('getDate'), date, 'Mouse click');\n\tinp.val('02/04/2008').datepicker('show');\n\t$('.ui-datepicker-calendar tbody a:contains(12)', dp).simulate('click', {});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 12),\n\t\t'Mouse click - preset');\n\tinp.val('02/04/2008').datepicker('show');\n\tinp.val('').datepicker('show');\n\t$('button.ui-datepicker-close', dp).simulate('click', {});\n\tok(inp.datepicker('getDate') == null, 'Mouse click - close');\n\tinp.val('02/04/2008').datepicker('show');\n\t$('button.ui-datepicker-close', dp).simulate('click', {});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4),\n\t\t'Mouse click - close + preset');\n\tinp.val('02/04/2008').datepicker('show');\n\t$('a.ui-datepicker-prev', dp).simulate('click', {});\n\t$('button.ui-datepicker-close', dp).simulate('click', {});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4),\n\t\t'Mouse click - abandoned');\n\t// Current/previous/next\n\tinp.val('02/04/2008').datepicker('option', {showButtonPanel: true}).datepicker('show');\n\t$('.ui-datepicker-current', dp).simulate('click', {});\n\t$('.ui-datepicker-calendar tbody a:contains(14)', dp).simulate('click', {});\n\tdate.setDate(14);\n\tequalsDate(inp.datepicker('getDate'), date, 'Mouse click - current');\n\tinp.val('02/04/2008').datepicker('show');\n\t$('.ui-datepicker-prev', dp).simulate('click');\n\t$('.ui-datepicker-calendar tbody a:contains(16)', dp).simulate('click');\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 1 - 1, 16),\n\t\t'Mouse click - previous');\n\tinp.val('02/04/2008').datepicker('show');\n\t$('.ui-datepicker-next', dp).simulate('click');\n\t$('.ui-datepicker-calendar tbody a:contains(18)', dp).simulate('click');\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 3 - 1, 18),\n\t\t'Mouse click - next');\n\t// Previous/next with minimum/maximum\n\tinp.datepicker('option', {minDate: new Date(2008, 2 - 1, 2),\n\t\tmaxDate: new Date(2008, 2 - 1, 26)}).val('02/04/2008').datepicker('show');\n\t$('.ui-datepicker-prev', dp).simulate('click');\n\t$('.ui-datepicker-calendar tbody a:contains(16)', dp).simulate('click');\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 16),\n\t\t'Mouse click - previous + min/max');\n\tinp.val('02/04/2008').datepicker('show');\n\t$('.ui-datepicker-next', dp).simulate('click');\n\t$('.ui-datepicker-calendar tbody a:contains(18)', dp).simulate('click');\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 18),\n\t\t'Mouse click - next + min/max');\n\t// Inline\n\tinl = init('#inl');\n\tdp = $('.ui-datepicker-inline', inl);\n\tdate = new Date();\n\tinl.datepicker('setDate', date);\n\t$('.ui-datepicker-calendar tbody a:contains(10)', dp).simulate('click', {});\n\tdate.setDate(10);\n\tequalsDate(inl.datepicker('getDate'), date, 'Mouse click inline');\n\tinl.datepicker('option', {showButtonPanel: true}).datepicker('setDate', new Date(2008, 2 - 1, 4));\n\t$('.ui-datepicker-calendar tbody a:contains(12)', dp).simulate('click', {});\n\tequalsDate(inl.datepicker('getDate'), new Date(2008, 2 - 1, 12), 'Mouse click inline - preset');\n\tinl.datepicker('option', {showButtonPanel: true});\n\t$('.ui-datepicker-current', dp).simulate('click', {});\n\t$('.ui-datepicker-calendar tbody a:contains(14)', dp).simulate('click', {});\n\tdate.setDate(14);\n\tequalsDate(inl.datepicker('getDate'), date, 'Mouse click inline - current');\n\tinl.datepicker('setDate', new Date(2008, 2 - 1, 4));\n\t$('.ui-datepicker-prev', dp).simulate('click');\n\t$('.ui-datepicker-calendar tbody a:contains(16)', dp).simulate('click');\n\tequalsDate(inl.datepicker('getDate'), new Date(2008, 1 - 1, 16),\n\t\t'Mouse click inline - previous');\n\tinl.datepicker('setDate', new Date(2008, 2 - 1, 4));\n\t$('.ui-datepicker-next', dp).simulate('click');\n\t$('.ui-datepicker-calendar tbody a:contains(18)', dp).simulate('click');\n\tequalsDate(inl.datepicker('getDate'), new Date(2008, 3 - 1, 18),\n\t\t'Mouse click inline - next');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker_defaults.js",
    "content": "/*\n * datepicker_defaults.js\n */\n\nvar datepicker_defaults = {\n\tdisabled: false\n};\n\n//TestHelpers.commonWidgetTests('datepicker', { defaults: datepicker_defaults });\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker_events.js",
    "content": "/*\n * datepicker_events.js\n */\n(function($) {\n\nmodule(\"datepicker: events\");\n\nvar selectedThis = null,\nselectedDate = null,\nselectedInst = null;\n\nfunction callback(date, inst) {\n\tselectedThis = this;\n\tselectedDate = date;\n\tselectedInst = inst;\n}\n\nfunction callback2(year, month, inst) {\n\tselectedThis = this;\n\tselectedDate = year + '/' + month;\n\tselectedInst = inst;\n}\n\ntest('events', function() {\n\tvar dateStr, newMonthYear, inp2,\n\t\tinp = init('#inp', {onSelect: callback}),\n\tdate = new Date();\n\t// onSelect\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequal(selectedThis, inp[0], 'Callback selected this');\n\tequal(selectedInst, $.data(inp[0], PROP_NAME), 'Callback selected inst');\n\tequal(selectedDate, $.datepicker.formatDate('mm/dd/yy', date),\n\t\t'Callback selected date');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 7);\n\tequal(selectedDate, $.datepicker.formatDate('mm/dd/yy', date),\n\t\t'Callback selected date - ctrl+down');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tequal(selectedDate, $.datepicker.formatDate('mm/dd/yy', date),\n\t\t'Callback selected date - esc');\n    dateStr = '02/04/2008';\n    inp.val(dateStr).datepicker('show').\n        simulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n    equal(dateStr, selectedDate,\n        'onSelect is called after enter keydown');\n\t// onChangeMonthYear\n\tinp.datepicker('option', {onChangeMonthYear: callback2, onSelect: null}).\n\t\tval('').datepicker('show');\n\tnewMonthYear = function(date) {\n\t\treturn date.getFullYear() + '/' + (date.getMonth() + 1);\n\t};\n\tdate = new Date();\n\tdate.setDate(1);\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP});\n\tdate.setMonth(date.getMonth() - 1);\n\tequal(selectedThis, inp[0], 'Callback change month/year this');\n\tequal(selectedInst, $.data(inp[0], PROP_NAME), 'Callback change month/year inst');\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year date - pgup');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN});\n\tdate.setMonth(date.getMonth() + 1);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year date - pgdn');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP});\n\tdate.setFullYear(date.getFullYear() - 1);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year date - ctrl+pgup');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.HOME});\n\tdate.setFullYear(date.getFullYear() + 1);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year date - ctrl+home');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN});\n\tdate.setFullYear(date.getFullYear() + 1);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year date - ctrl+pgdn');\n\tinp.datepicker('setDate', new Date(2007, 1 - 1, 26));\n\tequal(selectedDate, '2007/1', 'Callback change month/year date - setDate');\n\tselectedDate = null;\n\tinp.datepicker('setDate', new Date(2007, 1 - 1, 12));\n\tok(selectedDate == null, 'Callback change month/year date - setDate no change');\n\t// onChangeMonthYear step by 2\n\tinp.datepicker('option', {stepMonths: 2}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP});\n\tdate.setMonth(date.getMonth() - 14);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year by 2 date - pgup');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP});\n\tdate.setMonth(date.getMonth() - 12);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year by 2 date - ctrl+pgup');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN});\n\tdate.setMonth(date.getMonth() + 2);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year by 2 date - pgdn');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN});\n\tdate.setMonth(date.getMonth() + 12);\n\tequal(selectedDate, newMonthYear(date),\n\t\t'Callback change month/year by 2 date - ctrl+pgdn');\n\t// onClose\n\tinp.datepicker('option', {onClose: callback, onChangeMonthYear: null, stepMonths: 1}).\n\t\tval('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tequal(selectedThis, inp[0], 'Callback close this');\n\tequal(selectedInst, $.data(inp[0], PROP_NAME), 'Callback close inst');\n\tequal(selectedDate, '', 'Callback close date - esc');\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequal(selectedDate, $.datepicker.formatDate('mm/dd/yy', new Date()),\n\t\t'Callback close date - enter');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tequal(selectedDate, '02/04/2008', 'Callback close date - preset');\n\tinp.val('02/04/2008').datepicker('show').\n\t\tsimulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.END});\n\tequal(selectedDate, '', 'Callback close date - ctrl+end');\n\n\tinp2 = init('#inp2');\n\tinp2.datepicker().datepicker('option', {onClose: callback}).datepicker('show');\n\tinp.datepicker('show');\n\tequal(selectedThis, inp2[0], 'Callback close this');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker_methods.js",
    "content": "/*\n * datepicker_methods.js\n */\n(function($) {\n\nmodule(\"datepicker: methods\");\n\ntest('destroy', function() {\n\tvar inl,\n\t\tinp = init('#inp');\n\tok(inp.is('.hasDatepicker'), 'Default - marker class set');\n\tok($.data(inp[0], PROP_NAME), 'Default - instance present');\n\tok(inp.next().is('#alt'), 'Default - button absent');\n\tinp.datepicker('destroy');\n\tinp = $('#inp');\n\tok(!inp.is('.hasDatepicker'), 'Default - marker class cleared');\n\tok(!$.data(inp[0], PROP_NAME), 'Default - instance absent');\n\tok(inp.next().is('#alt'), 'Default - button absent');\n\t// With button\n\tinp= init('#inp', {showOn: 'both'});\n\tok(inp.is('.hasDatepicker'), 'Button - marker class set');\n\tok($.data(inp[0], PROP_NAME), 'Button - instance present');\n\tok(inp.next().text() === '...', 'Button - button added');\n\tinp.datepicker('destroy');\n\tinp = $('#inp');\n\tok(!inp.is('.hasDatepicker'), 'Button - marker class cleared');\n\tok(!$.data(inp[0], PROP_NAME), 'Button - instance absent');\n\tok(inp.next().is('#alt'), 'Button - button removed');\n\t// With append text\n\tinp = init('#inp', {appendText: 'Testing'});\n\tok(inp.is('.hasDatepicker'), 'Append - marker class set');\n\tok($.data(inp[0], PROP_NAME), 'Append - instance present');\n\tok(inp.next().text() === 'Testing', 'Append - append text added');\n\tinp.datepicker('destroy');\n\tinp = $('#inp');\n\tok(!inp.is('.hasDatepicker'), 'Append - marker class cleared');\n\tok(!$.data(inp[0], PROP_NAME), 'Append - instance absent');\n\tok(inp.next().is('#alt'), 'Append - append text removed');\n\t// With both\n\tinp= init('#inp', {showOn: 'both', buttonImageOnly: true,\n\t\tbuttonImage: 'img/calendar.gif', appendText: 'Testing'});\n\tok(inp.is('.hasDatepicker'), 'Both - marker class set');\n\tok($.data(inp[0], PROP_NAME), 'Both - instance present');\n\tok(inp.next()[0].nodeName.toLowerCase() === 'img', 'Both - button added');\n\tok(inp.next().next().text() === 'Testing', 'Both - append text added');\n\tinp.datepicker('destroy');\n\tinp = $('#inp');\n\tok(!inp.is('.hasDatepicker'), 'Both - marker class cleared');\n\tok(!$.data(inp[0], PROP_NAME), 'Both - instance absent');\n\tok(inp.next().is('#alt'), 'Both - button and append text absent');\n\t// Inline\n\tinl = init('#inl');\n\tok(inl.is('.hasDatepicker'), 'Inline - marker class set');\n\tok(inl.html() !== '', 'Inline - datepicker present');\n\tok($.data(inl[0], PROP_NAME), 'Inline - instance present');\n\tok(inl.next().length === 0 || inl.next().is('p'), 'Inline - button absent');\n\tinl.datepicker('destroy');\n\tinl = $('#inl');\n\tok(!inl.is('.hasDatepicker'), 'Inline - marker class cleared');\n\tok(inl.html() === '', 'Inline - datepicker absent');\n\tok(!$.data(inl[0], PROP_NAME), 'Inline - instance absent');\n\tok(inl.next().length === 0 || inl.next().is('p'), 'Inline - button absent');\n});\n\ntest('enableDisable', function() {\n\tvar inl, dp,\n\t\tinp = init('#inp');\n\tok(!inp.datepicker('isDisabled'), 'Enable/disable - initially marked as enabled');\n\tok(!inp[0].disabled, 'Enable/disable - field initially enabled');\n\tinp.datepicker('disable');\n\tok(inp.datepicker('isDisabled'), 'Enable/disable - now marked as disabled');\n\tok(inp[0].disabled, 'Enable/disable - field now disabled');\n\tinp.datepicker('enable');\n\tok(!inp.datepicker('isDisabled'), 'Enable/disable - now marked as enabled');\n\tok(!inp[0].disabled, 'Enable/disable - field now enabled');\n\tinp.datepicker('destroy');\n\t// With a button\n\tinp = init('#inp', {showOn: 'button'});\n\tok(!inp.datepicker('isDisabled'), 'Enable/disable button - initially marked as enabled');\n\tok(!inp[0].disabled, 'Enable/disable button - field initially enabled');\n\tok(!inp.next('button')[0].disabled, 'Enable/disable button - button initially enabled');\n\tinp.datepicker('disable');\n\tok(inp.datepicker('isDisabled'), 'Enable/disable button - now marked as disabled');\n\tok(inp[0].disabled, 'Enable/disable button - field now disabled');\n\tok(inp.next('button')[0].disabled, 'Enable/disable button - button now disabled');\n\tinp.datepicker('enable');\n\tok(!inp.datepicker('isDisabled'), 'Enable/disable button - now marked as enabled');\n\tok(!inp[0].disabled, 'Enable/disable button - field now enabled');\n\tok(!inp.next('button')[0].disabled, 'Enable/disable button - button now enabled');\n\tinp.datepicker('destroy');\n\t// With an image button\n\tinp = init('#inp', {showOn: 'button', buttonImageOnly: true,\n\t\tbuttonImage: 'img/calendar.gif'});\n\tok(!inp.datepicker('isDisabled'), 'Enable/disable image - initially marked as enabled');\n\tok(!inp[0].disabled, 'Enable/disable image - field initially enabled');\n\tok(parseFloat(inp.next('img').css('opacity')) === 1, 'Enable/disable image - image initially enabled');\n\tinp.datepicker('disable');\n\tok(inp.datepicker('isDisabled'), 'Enable/disable image - now marked as disabled');\n\tok(inp[0].disabled, 'Enable/disable image - field now disabled');\n\tok(parseFloat(inp.next('img').css('opacity')) !== 1, 'Enable/disable image - image now disabled');\n\tinp.datepicker('enable');\n\tok(!inp.datepicker('isDisabled'), 'Enable/disable image - now marked as enabled');\n\tok(!inp[0].disabled, 'Enable/disable image - field now enabled');\n\tok(parseFloat(inp.next('img').css('opacity')) === 1, 'Enable/disable image - image now enabled');\n\tinp.datepicker('destroy');\n\t// Inline\n\tinl = init('#inl', {changeYear: true});\n\tdp = $('.ui-datepicker-inline', inl);\n\tok(!inl.datepicker('isDisabled'), 'Enable/disable inline - initially marked as enabled');\n\tok(!dp.children().is('.ui-state-disabled'), 'Enable/disable inline - not visually disabled initially');\n\tok(!dp.find('select').prop('disabled'), 'Enable/disable inline - form element enabled initially');\n\tinl.datepicker('disable');\n\tok(inl.datepicker('isDisabled'), 'Enable/disable inline - now marked as disabled');\n\tok(dp.children().is('.ui-state-disabled'), 'Enable/disable inline - visually disabled');\n\tok(dp.find('select').prop('disabled'), 'Enable/disable inline - form element disabled');\n\tinl.datepicker('enable');\n\tok(!inl.datepicker('isDisabled'), 'Enable/disable inline - now marked as enabled');\n\tok(!dp.children().is('.ui-state-disabled'), 'Enable/disable inline - not visiually disabled');\n\tok(!dp.find('select').prop('disabled'), 'Enable/disable inline - form element enabled');\n\tinl.datepicker('destroy');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker_options.js",
    "content": "/*\n * datepicker_options.js\n */\n\n(function($) {\n\nmodule(\"datepicker: options\");\n\ntest('setDefaults', function() {\n\tvar inp = init('#inp');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Initial showOn');\n\t$.datepicker.setDefaults({showOn: 'button'});\n\tequal($.datepicker._defaults.showOn, 'button', 'Change default showOn');\n\t$.datepicker.setDefaults({showOn: 'focus'});\n\tequal($.datepicker._defaults.showOn, 'focus', 'Restore showOn');\n});\n\ntest('option', function() {\n\tvar inp = init('#inp'),\n\tinst = $.data(inp[0], PROP_NAME);\n\t// Set option\n\tequal(inst.settings.showOn, null, 'Initial setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'focus', 'Initial instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Initial default showOn');\n\tinp.datepicker('option', 'showOn', 'button');\n\tequal(inst.settings.showOn, 'button', 'Change setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'button', 'Change instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn');\n\tinp.datepicker('option', {showOn: 'both'});\n\tequal(inst.settings.showOn, 'both', 'Change setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'both', 'Change instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn');\n\tinp.datepicker('option', 'showOn', undefined);\n\tequal(inst.settings.showOn, null, 'Clear setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'focus', 'Restore instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn');\n\t// Get option\n\tinp = init('#inp');\n\tequal(inp.datepicker('option', 'showOn'), 'focus', 'Initial setting showOn');\n\tinp.datepicker('option', 'showOn', 'button');\n\tequal(inp.datepicker('option', 'showOn'), 'button', 'Change instance showOn');\n\tinp.datepicker('option', 'showOn', undefined);\n\tequal(inp.datepicker('option', 'showOn'), 'focus', 'Reset instance showOn');\n\tdeepEqual(inp.datepicker('option', 'all'), {showAnim: ''}, 'Get instance settings');\n\tdeepEqual(inp.datepicker('option', 'defaults'), $.datepicker._defaults,\n\t\t'Get default settings');\n});\n\ntest('change', function() {\n\tvar inp = init('#inp'),\n\tinst = $.data(inp[0], PROP_NAME);\n\tequal(inst.settings.showOn, null, 'Initial setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'focus', 'Initial instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Initial default showOn');\n\tinp.datepicker('change', 'showOn', 'button');\n\tequal(inst.settings.showOn, 'button', 'Change setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'button', 'Change instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn');\n\tinp.datepicker('change', {showOn: 'both'});\n\tequal(inst.settings.showOn, 'both', 'Change setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'both', 'Change instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn');\n\tinp.datepicker('change', 'showOn', undefined);\n\tequal(inst.settings.showOn, null, 'Clear setting showOn');\n\tequal($.datepicker._get(inst, 'showOn'), 'focus', 'Restore instance showOn');\n\tequal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn');\n});\n\ntest('invocation', function() {\n\tvar button, image,\n\t\tinp = init('#inp'),\n\t\tdp = $('#ui-datepicker-div'),\n\t\tbody = $('body');\n\t// On focus\n\tbutton = inp.siblings('button');\n\tok(button.length === 0, 'Focus - button absent');\n\timage = inp.siblings('img');\n\tok(image.length === 0, 'Focus - image absent');\n\tinp.focus();\n\tok(dp.is(':visible'), 'Focus - rendered on focus');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tok(!dp.is(':visible'), 'Focus - hidden on exit');\n\tinp.focus();\n\tok(dp.is(':visible'), 'Focus - rendered on focus');\n\tbody.simulate('mousedown', {});\n\tok(!dp.is(':visible'), 'Focus - hidden on external click');\n\tinp.datepicker('hide').datepicker('destroy');\n\t// On button\n\tinp = init('#inp', {showOn: 'button', buttonText: 'Popup'});\n\tok(!dp.is(':visible'), 'Button - initially hidden');\n\tbutton = inp.siblings('button');\n\timage = inp.siblings('img');\n\tok(button.length === 1, 'Button - button present');\n\tok(image.length === 0, 'Button - image absent');\n\tequal(button.text(), 'Popup', 'Button - button text');\n\tinp.focus();\n\tok(!dp.is(':visible'), 'Button - not rendered on focus');\n\tbutton.click();\n\tok(dp.is(':visible'), 'Button - rendered on button click');\n\tbutton.click();\n\tok(!dp.is(':visible'), 'Button - hidden on second button click');\n\tinp.datepicker('hide').datepicker('destroy');\n\t// On image button\n\tinp = init('#inp', {showOn: 'button', buttonImageOnly: true,\n\t\tbuttonImage: 'img/calendar.gif', buttonText: 'Cal'});\n\tok(!dp.is(':visible'), 'Image button - initially hidden');\n\tbutton = inp.siblings('button');\n\tok(button.length === 0, 'Image button - button absent');\n\timage = inp.siblings('img');\n\tok(image.length === 1, 'Image button - image present');\n\tequal(image.attr('src'), 'img/calendar.gif', 'Image button - image source');\n\tequal(image.attr('title'), 'Cal', 'Image button - image text');\n\tinp.focus();\n\tok(!dp.is(':visible'), 'Image button - not rendered on focus');\n\timage.click();\n\tok(dp.is(':visible'), 'Image button - rendered on image click');\n\timage.click();\n\tok(!dp.is(':visible'), 'Image button - hidden on second image click');\n\tinp.datepicker('hide').datepicker('destroy');\n\t// On both\n\tinp = init('#inp', {showOn: 'both', buttonImage: 'img/calendar.gif'});\n\tok(!dp.is(':visible'), 'Both - initially hidden');\n\tbutton = inp.siblings('button');\n\tok(button.length === 1, 'Both - button present');\n\timage = inp.siblings('img');\n\tok(image.length === 0, 'Both - image absent');\n\timage = button.children('img');\n\tok(image.length === 1, 'Both - button image present');\n\tinp.focus();\n\tok(dp.is(':visible'), 'Both - rendered on focus');\n\tbody.simulate('mousedown', {});\n\tok(!dp.is(':visible'), 'Both - hidden on external click');\n\tbutton.click();\n\tok(dp.is(':visible'), 'Both - rendered on button click');\n\tbutton.click();\n\tok(!dp.is(':visible'), 'Both - hidden on second button click');\n\tinp.datepicker('hide').datepicker('destroy');\n});\n\ntest('otherMonths', function() {\n\tvar inp = init('#inp'),\n\t\tpop = $('#ui-datepicker-div');\n\tinp.val('06/01/2009').datepicker('show');\n\tequal(pop.find('tbody').text(), '\\u00a0123456789101112131415161718192021222324252627282930\\u00a0\\u00a0\\u00a0\\u00a0',\n\t\t'Other months - none');\n\tok(pop.find('td:last *').length === 0, 'Other months - no content');\n\tinp.datepicker('hide').datepicker('option', 'showOtherMonths', true).datepicker('show');\n\tequal(pop.find('tbody').text(), '311234567891011121314151617181920212223242526272829301234',\n\t\t'Other months - show');\n\tok(pop.find('td:last span').length === 1, 'Other months - span content');\n\tinp.datepicker('hide').datepicker('option', 'selectOtherMonths', true).datepicker('show');\n\tequal(pop.find('tbody').text(), '311234567891011121314151617181920212223242526272829301234',\n\t\t'Other months - select');\n\tok(pop.find('td:last a').length === 1, 'Other months - link content');\n\tinp.datepicker('hide').datepicker('option', 'showOtherMonths', false).datepicker('show');\n\tequal(pop.find('tbody').text(), '\\u00a0123456789101112131415161718192021222324252627282930\\u00a0\\u00a0\\u00a0\\u00a0',\n\t\t'Other months - none');\n\tok(pop.find('td:last *').length === 0, 'Other months - no content');\n});\n\ntest('defaultDate', function() {\n\tvar inp = init('#inp'),\n\t\tdate = new Date();\n\tinp.val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date null');\n\t// Numeric values\n\tinp.datepicker('option', {defaultDate: -2}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 2);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date -2');\n\tinp.datepicker('option', {defaultDate: 3}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 5);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date 3');\n\tinp.datepicker('option', {defaultDate: 1 / 0}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 3);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date Infinity');\n\tinp.datepicker('option', {defaultDate: 1 / 'a'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date NaN');\n\t// String offset values\n\tinp.datepicker('option', {defaultDate: '-1d'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() - 1);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date -1d');\n\tinp.datepicker('option', {defaultDate: '+3D'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 4);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date +3D');\n\tinp.datepicker('option', {defaultDate: ' -2 w '}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = new Date();\n\tdate.setDate(date.getDate() - 14);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date -2 w');\n\tinp.datepicker('option', {defaultDate: '+1 W'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setDate(date.getDate() + 21);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date +1 W');\n\tinp.datepicker('option', {defaultDate: ' -1 m '}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = addMonths(new Date(), -1);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date -1 m');\n\tinp.datepicker('option', {defaultDate: '+2M'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = addMonths(new Date(), 2);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date +2M');\n\tinp.datepicker('option', {defaultDate: '-2y'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = new Date();\n\tdate.setFullYear(date.getFullYear() - 2);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date -2y');\n\tinp.datepicker('option', {defaultDate: '+1 Y '}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate.setFullYear(date.getFullYear() + 3);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date +1 Y');\n\tinp.datepicker('option', {defaultDate: '+1M +10d'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = addMonths(new Date(), 1);\n\tdate.setDate(date.getDate() + 10);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date +1M +10d');\n\t// String date values\n\tinp.datepicker('option', {defaultDate: '07/04/2007'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = new Date(2007, 7 - 1, 4);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date 07/04/2007');\n\tinp.datepicker('option', {dateFormat: 'yy-mm-dd', defaultDate: '2007-04-02'}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = new Date(2007, 4 - 1, 2);\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date 2007-04-02');\n\t// Date value\n\tdate = new Date(2007, 1 - 1, 26);\n\tinp.datepicker('option', {dateFormat: 'mm/dd/yy', defaultDate: date}).\n\t\tdatepicker('hide').val('').datepicker('show').\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date, 'Default date 01/26/2007');\n});\n\ntest('miscellaneous', function() {\n\tvar curYear, longNames, shortNames, date,\n\t\tdp = $('#ui-datepicker-div'),\n\t\tinp = init('#inp');\n\t// Year range\n\tfunction genRange(start, offset) {\n\t\tvar i = start,\n\t\t\trange = '';\n\t\tfor (; i < start + offset; i++) {\n\t\t\trange += i;\n\t\t}\n\t\treturn range;\n\t}\n\tcurYear = new Date().getFullYear();\n\tinp.val('02/04/2008').datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), '2008', 'Year range - read-only default');\n\tinp.datepicker('hide').datepicker('option', {changeYear: true}).datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), genRange(2008 - 10, 21), 'Year range - changeable default');\n\tinp.datepicker('hide').datepicker('option', {yearRange: 'c-6:c+2', changeYear: true}).datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), genRange(2008 - 6, 9), 'Year range - c-6:c+2');\n\tinp.datepicker('hide').datepicker('option', {yearRange: '2000:2010', changeYear: true}).datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), genRange(2000, 11), 'Year range - 2000:2010');\n\tinp.datepicker('hide').datepicker('option', {yearRange: '-5:+3', changeYear: true}).datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), genRange(curYear - 5, 9), 'Year range - -5:+3');\n\tinp.datepicker('hide').datepicker('option', {yearRange: '2000:-5', changeYear: true}).datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), genRange(2000, curYear - 2004), 'Year range - 2000:-5');\n\tinp.datepicker('hide').datepicker('option', {yearRange: '', changeYear: true}).datepicker('show');\n\tequal(dp.find('.ui-datepicker-year').text(), genRange(curYear, 1), 'Year range - -6:+2');\n\n\t// Navigation as date format\n\tinp.datepicker('option', {showButtonPanel: true});\n\tequal(dp.find('.ui-datepicker-prev').text(), 'Prev', 'Navigation prev - default');\n\tequal(dp.find('.ui-datepicker-current').text(), 'Today', 'Navigation current - default');\n\tequal(dp.find('.ui-datepicker-next').text(), 'Next', 'Navigation next - default');\n\tinp.datepicker('hide').datepicker('option', {navigationAsDateFormat: true, prevText: '< M', currentText: 'MM', nextText: 'M >'}).\n\t\tval('02/04/2008').datepicker('show');\n\tlongNames = $.datepicker.regional[''].monthNames;\n\tshortNames = $.datepicker.regional[''].monthNamesShort;\n\tdate = new Date();\n\tequal(dp.find('.ui-datepicker-prev').text(), '< ' + shortNames[0], 'Navigation prev - as date format');\n\tequal(dp.find('.ui-datepicker-current').text(),\n\t\tlongNames[date.getMonth()], 'Navigation current - as date format');\n\tequal(dp.find('.ui-datepicker-next').text(),\n\t\tshortNames[2] + ' >', 'Navigation next - as date format');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN});\n\tequal(dp.find('.ui-datepicker-prev').text(),\n\t\t'< ' + shortNames[1], 'Navigation prev - as date format + pgdn');\n\tequal(dp.find('.ui-datepicker-current').text(),\n\t\tlongNames[date.getMonth()], 'Navigation current - as date format + pgdn');\n\tequal(dp.find('.ui-datepicker-next').text(),\n\t\tshortNames[3] + ' >', 'Navigation next - as date format + pgdn');\n\tinp.datepicker('hide').datepicker('option', {gotoCurrent: true}).\n\t\tval('02/04/2008').datepicker('show');\n\tequal(dp.find('.ui-datepicker-prev').text(),\n\t\t'< ' + shortNames[0], 'Navigation prev - as date format + goto current');\n\tequal(dp.find('.ui-datepicker-current').text(),\n\t\tlongNames[1], 'Navigation current - as date format + goto current');\n\tequal(dp.find('.ui-datepicker-next').text(),\n\t\tshortNames[2] + ' >', 'Navigation next - as date format + goto current');\n});\n\ntest('minMax', function() {\n\tvar date,\n\t\tinp = init('#inp'),\n\t\tlastYear = new Date(2007, 6 - 1, 4),\n\t\tnextYear = new Date(2009, 6 - 1, 4),\n\t\tminDate = new Date(2008, 2 - 1, 29),\n\t\tmaxDate = new Date(2008, 12 - 1, 7);\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), lastYear,\n\t\t'Min/max - null, null - ctrl+pgup');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), nextYear,\n\t\t'Min/max - null, null - ctrl+pgdn');\n\tinp.datepicker('option', {minDate: minDate}).\n\t\tdatepicker('hide').val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), minDate,\n\t\t'Min/max - 02/29/2008, null - ctrl+pgup');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), nextYear,\n\t\t'Min/max - 02/29/2008, null - ctrl+pgdn');\n\tinp.datepicker('option', {maxDate: maxDate}).\n\t\tdatepicker('hide').val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), minDate,\n\t\t'Min/max - 02/29/2008, 12/07/2008 - ctrl+pgup');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), maxDate,\n\t\t'Min/max - 02/29/2008, 12/07/2008 - ctrl+pgdn');\n\tinp.datepicker('option', {minDate: null}).\n\t\tdatepicker('hide').val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), lastYear,\n\t\t'Min/max - null, 12/07/2008 - ctrl+pgup');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), maxDate,\n\t\t'Min/max - null, 12/07/2008 - ctrl+pgdn');\n\t// Relative dates\n\tdate = new Date();\n\tdate.setDate(date.getDate() - 7);\n\tinp.datepicker('option', {minDate: '-1w', maxDate: '+1 M +10 D '}).\n\t\tdatepicker('hide').val('').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date,\n\t\t'Min/max - -1w, +1 M +10 D - ctrl+pgup');\n\tdate = addMonths(new Date(), 1);\n\tdate.setDate(date.getDate() + 10);\n\tinp.val('').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequalsDate(inp.datepicker('getDate'), date,\n\t\t'Min/max - -1w, +1 M +10 D - ctrl+pgdn');\n\t// With existing date\n\tinp = init('#inp');\n\tinp.val('06/04/2008').datepicker('option', {minDate: minDate});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate > min');\n\tinp.datepicker('option', {minDate: null}).val('01/04/2008').datepicker('option', {minDate: minDate});\n\tequalsDate(inp.datepicker('getDate'), minDate, 'Min/max - setDate < min');\n\tinp.datepicker('option', {minDate: null}).val('06/04/2008').datepicker('option', {maxDate: maxDate});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate < max');\n\tinp.datepicker('option', {maxDate: null}).val('01/04/2009').datepicker('option', {maxDate: maxDate});\n\tequalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - setDate > max');\n\tinp.datepicker('option', {maxDate: null}).val('01/04/2008').datepicker('option', {minDate: minDate, maxDate: maxDate});\n\tequalsDate(inp.datepicker('getDate'), minDate, 'Min/max - setDate < min');\n\tinp.datepicker('option', {maxDate: null}).val('06/04/2008').datepicker('option', {minDate: minDate, maxDate: maxDate});\n\tequalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate > min, < max');\n\tinp.datepicker('option', {maxDate: null}).val('01/04/2009').datepicker('option', {minDate: minDate, maxDate: maxDate});\n\tequalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - setDate > max');\n});\n\ntest('setDate', function() {\n\tvar inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone,\n\t\tinp = init('#inp'),\n\t\tdate1 = new Date(2008, 6 - 1, 4),\n\t\tdate2 = new Date();\n\tok(inp.datepicker('getDate') == null, 'Set date - default');\n\tinp.datepicker('setDate', date1);\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date - 2008-06-04');\n\tdate1 = new Date();\n\tdate1.setDate(date1.getDate() + 7);\n\tinp.datepicker('setDate', +7);\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date - +7');\n\tdate2.setFullYear(date2.getFullYear() + 2);\n\tinp.datepicker('setDate', '+2y');\n\tequalsDate(inp.datepicker('getDate'), date2, 'Set date - +2y');\n\tinp.datepicker('setDate', date1, date2);\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date - two dates');\n\tinp.datepicker('setDate');\n\tok(inp.datepicker('getDate') == null, 'Set date - null');\n\t// Relative to current date\n\tdate1 = new Date();\n\tdate1.setDate(date1.getDate() + 7);\n\tinp.datepicker('setDate', 'c +7');\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date - c +7');\n\tdate1.setDate(date1.getDate() + 7);\n\tinp.datepicker('setDate', 'c+7');\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date - c+7');\n\tdate1.setDate(date1.getDate() - 21);\n\tinp.datepicker('setDate', 'c -3 w');\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date - c -3 w');\n\t// Inline\n\tinl = init('#inl');\n\tdate1 = new Date(2008, 6 - 1, 4);\n\tdate2 = new Date();\n\tequalsDate(inl.datepicker('getDate'), date2, 'Set date inline - default');\n\tinl.datepicker('setDate', date1);\n\tequalsDate(inl.datepicker('getDate'), date1, 'Set date inline - 2008-06-04');\n\tdate1 = new Date();\n\tdate1.setDate(date1.getDate() + 7);\n\tinl.datepicker('setDate', +7);\n\tequalsDate(inl.datepicker('getDate'), date1, 'Set date inline - +7');\n\tdate2.setFullYear(date2.getFullYear() + 2);\n\tinl.datepicker('setDate', '+2y');\n\tequalsDate(inl.datepicker('getDate'), date2, 'Set date inline - +2y');\n\tinl.datepicker('setDate', date1, date2);\n\tequalsDate(inl.datepicker('getDate'), date1, 'Set date inline - two dates');\n\tinl.datepicker('setDate');\n\tok(inl.datepicker('getDate') == null, 'Set date inline - null');\n\t// Alternate field\n\talt = $('#alt');\n\tinp.datepicker('option', {altField: '#alt', altFormat: 'yy-mm-dd'});\n\tdate1 = new Date(2008, 6 - 1, 4);\n\tinp.datepicker('setDate', date1);\n\tequal(inp.val(), '06/04/2008', 'Set date alternate - 06/04/2008');\n\tequal(alt.val(), '2008-06-04', 'Set date alternate - 2008-06-04');\n\t// With minimum/maximum\n\tinp = init('#inp');\n\tdate1 = new Date(2008, 1 - 1, 4);\n\tdate2 = new Date(2008, 6 - 1, 4);\n\tminDate = new Date(2008, 2 - 1, 29);\n\tmaxDate = new Date(2008, 3 - 1, 28);\n\tinp.val('').datepicker('option', {minDate: minDate}).datepicker('setDate', date2);\n\tequalsDate(inp.datepicker('getDate'), date2, 'Set date min/max - setDate > min');\n\tinp.datepicker('setDate', date1);\n\tequalsDate(inp.datepicker('getDate'), minDate, 'Set date min/max - setDate < min');\n\tinp.val('').datepicker('option', {maxDate: maxDate, minDate: null}).datepicker('setDate', date1);\n\tequalsDate(inp.datepicker('getDate'), date1, 'Set date min/max - setDate < max');\n\tinp.datepicker('setDate', date2);\n\tequalsDate(inp.datepicker('getDate'), maxDate, 'Set date min/max - setDate > max');\n\tinp.val('').datepicker('option', {minDate: minDate}).datepicker('setDate', date1);\n\tequalsDate(inp.datepicker('getDate'), minDate, 'Set date min/max - setDate < min');\n\tinp.datepicker('setDate', date2);\n\tequalsDate(inp.datepicker('getDate'), maxDate, 'Set date min/max - setDate > max');\n\tdateAndTimeToSet = new Date(2008, 3 - 1, 28, 1, 11, 0);\n\tdateAndTimeClone = new Date(2008, 3 - 1, 28, 1, 11, 0);\n\tinp.datepicker('setDate', dateAndTimeToSet);\n\tequal(dateAndTimeToSet.getTime(), dateAndTimeClone.getTime(), 'Date object passed should not be changed by setDate');\n});\n\ntest('altField', function() {\n\tvar inp = init('#inp'),\n\t\talt = $('#alt');\n\t// No alternate field set\n\talt.val('');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequal(inp.val(), '06/04/2008', 'Alt field - dp - enter');\n\tequal(alt.val(), '', 'Alt field - alt not set');\n\t// Alternate field set\n\talt.val('');\n\tinp.datepicker('option', {altField: '#alt', altFormat: 'yy-mm-dd'}).\n\t\tval('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequal(inp.val(), '06/04/2008', 'Alt field - dp - enter');\n\tequal(alt.val(), '2008-06-04', 'Alt field - alt - enter');\n\t// Move from initial date\n\talt.val('');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tequal(inp.val(), '07/04/2008', 'Alt field - dp - pgdn');\n\tequal(alt.val(), '2008-07-04', 'Alt field - alt - pgdn');\n\t// Alternate field set - closed\n\talt.val('');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}).\n\t\tsimulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n\tequal(inp.val(), '06/04/2008', 'Alt field - dp - pgdn/esc');\n\tequal(alt.val(), '', 'Alt field - alt - pgdn/esc');\n\t// Clear date and alternate\n\talt.val('');\n\tinp.val('06/04/2008').datepicker('show');\n\tinp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.END});\n\tequal(inp.val(), '', 'Alt field - dp - ctrl+end');\n\tequal(alt.val(), '', 'Alt field - alt - ctrl+end');\n});\n\ntest('autoSize', function() {\n\tvar inp = init('#inp');\n\tequal(inp.prop('size'), 20, 'Auto size - default');\n\tinp.datepicker('option', 'autoSize', true);\n\tequal(inp.prop('size'), 10, 'Auto size - mm/dd/yy');\n\tinp.datepicker('option', 'dateFormat', 'm/d/yy');\n\tequal(inp.prop('size'), 10, 'Auto size - m/d/yy');\n\tinp.datepicker('option', 'dateFormat', 'D M d yy');\n\tequal(inp.prop('size'), 15, 'Auto size - D M d yy');\n\tinp.datepicker('option', 'dateFormat', 'DD, MM dd, yy');\n\tequal(inp.prop('size'), 29, 'Auto size - DD, MM dd, yy');\n\t// French\n\tinp.datepicker('option', $.extend({autoSize: false}, $.datepicker.regional.fr));\n\tequal(inp.prop('size'), 29, 'Auto size - fr - default');\n\tinp.datepicker('option', 'autoSize', true);\n\tequal(inp.prop('size'), 10, 'Auto size - fr - dd/mm/yy');\n\tinp.datepicker('option', 'dateFormat', 'm/d/yy');\n\tequal(inp.prop('size'), 10, 'Auto size - fr - m/d/yy');\n\tinp.datepicker('option', 'dateFormat', 'D M d yy');\n\tequal(inp.prop('size'), 18, 'Auto size - fr - D M d yy');\n\tinp.datepicker('option', 'dateFormat', 'DD, MM dd, yy');\n\tequal(inp.prop('size'), 28, 'Auto size - fr - DD, MM dd, yy');\n\t// Hebrew\n\tinp.datepicker('option', $.extend({autoSize: false}, $.datepicker.regional.he));\n\tequal(inp.prop('size'), 28, 'Auto size - he - default');\n\tinp.datepicker('option', 'autoSize', true);\n\tequal(inp.prop('size'), 10, 'Auto size - he - dd/mm/yy');\n\tinp.datepicker('option', 'dateFormat', 'm/d/yy');\n\tequal(inp.prop('size'), 10, 'Auto size - he - m/d/yy');\n\tinp.datepicker('option', 'dateFormat', 'D M d yy');\n\tequal(inp.prop('size'), 16, 'Auto size - he - D M d yy');\n\tinp.datepicker('option', 'dateFormat', 'DD, MM dd, yy');\n\tequal(inp.prop('size'), 23, 'Auto size - he - DD, MM dd, yy');\n});\n\ntest('daylightSaving', function() {\n\tvar inp = init('#inp'),\n\t\tdp = $('#ui-datepicker-div');\n\tok(true, 'Daylight saving - ' + new Date());\n\t// Australia, Sydney - AM change, southern hemisphere\n\tinp.val('04/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(6) a', dp).simulate('click');\n\tequal(inp.val(), '04/05/2008', 'Daylight saving - Australia 04/05/2008');\n\tinp.val('04/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(7) a', dp).simulate('click');\n\tequal(inp.val(), '04/06/2008', 'Daylight saving - Australia 04/06/2008');\n\tinp.val('04/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(8) a', dp).simulate('click');\n\tequal(inp.val(), '04/07/2008', 'Daylight saving - Australia 04/07/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(6) a', dp).simulate('click');\n\tequal(inp.val(), '10/04/2008', 'Daylight saving - Australia 10/04/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(7) a', dp).simulate('click');\n\tequal(inp.val(), '10/05/2008', 'Daylight saving - Australia 10/05/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(8) a', dp).simulate('click');\n\tequal(inp.val(), '10/06/2008', 'Daylight saving - Australia 10/06/2008');\n\t// Brasil, Brasilia - midnight change, southern hemisphere\n\tinp.val('02/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(20) a', dp).simulate('click');\n\tequal(inp.val(), '02/16/2008', 'Daylight saving - Brasil 02/16/2008');\n\tinp.val('02/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(21) a', dp).simulate('click');\n\tequal(inp.val(), '02/17/2008', 'Daylight saving - Brasil 02/17/2008');\n\tinp.val('02/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(22) a', dp).simulate('click');\n\tequal(inp.val(), '02/18/2008', 'Daylight saving - Brasil 02/18/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(13) a', dp).simulate('click');\n\tequal(inp.val(), '10/11/2008', 'Daylight saving - Brasil 10/11/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(14) a', dp).simulate('click');\n\tequal(inp.val(), '10/12/2008', 'Daylight saving - Brasil 10/12/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(15) a', dp).simulate('click');\n\tequal(inp.val(), '10/13/2008', 'Daylight saving - Brasil 10/13/2008');\n\t// Lebanon, Beirut - midnight change, northern hemisphere\n\tinp.val('03/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(34) a', dp).simulate('click');\n\tequal(inp.val(), '03/29/2008', 'Daylight saving - Lebanon 03/29/2008');\n\tinp.val('03/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(35) a', dp).simulate('click');\n\tequal(inp.val(), '03/30/2008', 'Daylight saving - Lebanon 03/30/2008');\n\tinp.val('03/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(36) a', dp).simulate('click');\n\tequal(inp.val(), '03/31/2008', 'Daylight saving - Lebanon 03/31/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(27) a', dp).simulate('click');\n\tequal(inp.val(), '10/25/2008', 'Daylight saving - Lebanon 10/25/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(28) a', dp).simulate('click');\n\tequal(inp.val(), '10/26/2008', 'Daylight saving - Lebanon 10/26/2008');\n\tinp.val('10/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(29) a', dp).simulate('click');\n\tequal(inp.val(), '10/27/2008', 'Daylight saving - Lebanon 10/27/2008');\n\t// US, Eastern - AM change, northern hemisphere\n\tinp.val('03/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(13) a', dp).simulate('click');\n\tequal(inp.val(), '03/08/2008', 'Daylight saving - US 03/08/2008');\n\tinp.val('03/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(14) a', dp).simulate('click');\n\tequal(inp.val(), '03/09/2008', 'Daylight saving - US 03/09/2008');\n\tinp.val('03/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(15) a', dp).simulate('click');\n\tequal(inp.val(), '03/10/2008', 'Daylight saving - US 03/10/2008');\n\tinp.val('11/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(6) a', dp).simulate('click');\n\tequal(inp.val(), '11/01/2008', 'Daylight saving - US 11/01/2008');\n\tinp.val('11/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(7) a', dp).simulate('click');\n\tequal(inp.val(), '11/02/2008', 'Daylight saving - US 11/02/2008');\n\tinp.val('11/01/2008').datepicker('show');\n\t$('.ui-datepicker-calendar td:eq(8) a', dp).simulate('click');\n\tequal(inp.val(), '11/03/2008', 'Daylight saving - US 11/03/2008');\n});\n\nvar beforeShowThis = null,\n\tbeforeShowInput = null,\n\tbeforeShowInst = null,\n\tbeforeShowDayThis = null,\n\tbeforeShowDayOK = true;\n\n\nfunction beforeAll(input, inst) {\n\tbeforeShowThis = this;\n\tbeforeShowInput = input;\n\tbeforeShowInst = inst;\n\treturn {currentText: 'Current'};\n}\n\nfunction beforeDay(date) {\n\tbeforeShowDayThis = this;\n\tbeforeShowDayOK &= (date > new Date(2008, 1 - 1, 26) &&\n\t\tdate < new Date(2008, 3 - 1, 6));\n\treturn [(date.getDate() % 2 === 0), (date.getDate() % 10 === 0 ? 'day10' : ''),\n\t\t(date.getDate() % 3 === 0 ? 'Divisble by 3' : '')];\n}\n\nfunction calcWeek(date) {\n\tvar doy = date.getDate() + 6,\n\t\tm = date.getMonth() - 1;\n\tfor (; m >= 0; m--) {\n\t\tdoy += $.datepicker._getDaysInMonth(date.getFullYear(), m);\n\t}\n\t// Simple count from 01/01 starting at week 1\n\treturn Math.floor(doy / 7);\n}\n\ntest('callbacks', function() {\n\t// Before show\n\tvar dp, day20, day21,\n\t\tinp = init('#inp', {beforeShow: beforeAll}),\n\t\tinst = $.data(inp[0], 'datepicker');\n\tequal($.datepicker._get(inst, 'currentText'), 'Today', 'Before show - initial');\n\tinp.val('02/04/2008').datepicker('show');\n\tequal($.datepicker._get(inst, 'currentText'), 'Current', 'Before show - changed');\n\tok(beforeShowThis.id === inp[0].id, 'Before show - this OK');\n\tok(beforeShowInput.id === inp[0].id, 'Before show - input OK');\n\tdeepEqual(beforeShowInst, inst, 'Before show - inst OK');\n\tinp.datepicker('hide').datepicker('destroy');\n\t// Before show day\n\tinp = init('#inp', {beforeShowDay: beforeDay});\n\tdp = $('#ui-datepicker-div');\n\tinp.val('02/04/2008').datepicker('show');\n\tok(beforeShowDayThis.id === inp[0].id, 'Before show day - this OK');\n\tok(beforeShowDayOK, 'Before show day - dates OK');\n\tday20 = dp.find('.ui-datepicker-calendar td:contains(\"20\")');\n\tday21 = dp.find('.ui-datepicker-calendar td:contains(\"21\")');\n\tok(!day20.is('.ui-datepicker-unselectable'), 'Before show day - unselectable 20');\n\tok(day21.is('.ui-datepicker-unselectable'), 'Before show day - unselectable 21');\n\tok(day20.is('.day10'), 'Before show day - CSS 20');\n\tok(!day21.is('.day10'), 'Before show day - CSS 21');\n\tok(!day20.attr('title'), 'Before show day - title 20');\n\tok(day21.attr('title') === 'Divisble by 3', 'Before show day - title 21');\n\tinp.datepicker('hide').datepicker('destroy');\n});\n\ntest('localisation', function() {\n\tvar dp, month, day, date,\n\t\tinp = init('#inp', $.datepicker.regional.fr);\n\tinp.datepicker('option', {dateFormat: 'DD, d MM yy', showButtonPanel:true, changeMonth:true, changeYear:true}).val('').datepicker('show');\n\tdp = $('#ui-datepicker-div');\n\tequal($('.ui-datepicker-close', dp).text(), 'Fermer', 'Localisation - close');\n\t$('.ui-datepicker-close', dp).simulate('mouseover');\n\tequal($('.ui-datepicker-prev', dp).text(), 'Précédent', 'Localisation - previous');\n\tequal($('.ui-datepicker-current', dp).text(), 'Aujourd\\'hui', 'Localisation - current');\n\tequal($('.ui-datepicker-next', dp).text(), 'Suivant', 'Localisation - next');\n\tmonth = 0;\n\t$('.ui-datepicker-month option', dp).each(function() {\n\t\tequal($(this).text(), $.datepicker.regional.fr.monthNamesShort[month],\n\t\t\t'Localisation - month ' + month);\n\t\tmonth++;\n\t});\n\tday = 1;\n\t$('.ui-datepicker-calendar th', dp).each(function() {\n\t\tequal($(this).text(), $.datepicker.regional.fr.dayNamesMin[day],\n\t\t\t'Localisation - day ' + day);\n\t\tday = (day + 1) % 7;\n\t});\n\tinp.simulate('keydown', {keyCode: $.ui.keyCode.ENTER});\n\tdate = new Date();\n\tequal(inp.val(), $.datepicker.regional.fr.dayNames[date.getDay()] + ', ' +\n\t\tdate.getDate() + ' ' + $.datepicker.regional.fr.monthNames[date.getMonth()] +\n\t\t' ' + date.getFullYear(), 'Localisation - formatting');\n});\n\ntest('noWeekends', function() {\n\tvar i, date;\n\tfor (i = 1; i <= 31; i++) {\n\t\tdate = new Date(2001, 1 - 1, i);\n\t\tdeepEqual($.datepicker.noWeekends(date), [(i + 1) % 7 >= 2, ''],\n\t\t\t'No weekends ' + date);\n\t}\n});\n\ntest('iso8601Week', function() {\n\tvar date = new Date(2000, 12 - 1, 31);\n\tequal($.datepicker.iso8601Week(date), 52, 'ISO 8601 week ' + date);\n\tdate = new Date(2001, 1 - 1, 1);\n\tequal($.datepicker.iso8601Week(date), 1, 'ISO 8601 week ' + date);\n\tdate = new Date(2001, 1 - 1, 7);\n\tequal($.datepicker.iso8601Week(date), 1, 'ISO 8601 week ' + date);\n\tdate = new Date(2001, 1 - 1, 8);\n\tequal($.datepicker.iso8601Week(date), 2, 'ISO 8601 week ' + date);\n\tdate = new Date(2003, 12 - 1, 28);\n\tequal($.datepicker.iso8601Week(date), 52, 'ISO 8601 week ' + date);\n\tdate = new Date(2003, 12 - 1, 29);\n\tequal($.datepicker.iso8601Week(date), 1, 'ISO 8601 week ' + date);\n\tdate = new Date(2004, 1 - 1, 4);\n\tequal($.datepicker.iso8601Week(date), 1, 'ISO 8601 week ' + date);\n\tdate = new Date(2004, 1 - 1, 5);\n\tequal($.datepicker.iso8601Week(date), 2, 'ISO 8601 week ' + date);\n\tdate = new Date(2009, 12 - 1, 28);\n\tequal($.datepicker.iso8601Week(date), 53, 'ISO 8601 week ' + date);\n\tdate = new Date(2010, 1 - 1, 3);\n\tequal($.datepicker.iso8601Week(date), 53, 'ISO 8601 week ' + date);\n\tdate = new Date(2010, 1 - 1, 4);\n\tequal($.datepicker.iso8601Week(date), 1, 'ISO 8601 week ' + date);\n\tdate = new Date(2010, 1 - 1, 10);\n\tequal($.datepicker.iso8601Week(date), 1, 'ISO 8601 week ' + date);\n});\n\ntest('parseDate', function() {\n\tinit('#inp');\n\tvar currentYear, gmtDate, fr, settings, zh;\n\tok($.datepicker.parseDate('d m y', '') == null, 'Parse date empty');\n\tequalsDate($.datepicker.parseDate('d m y', '3 2 01'),\n\t\tnew Date(2001, 2 - 1, 3), 'Parse date d m y');\n\tequalsDate($.datepicker.parseDate('dd mm yy', '03 02 2001'),\n\t\tnew Date(2001, 2 - 1, 3), 'Parse date dd mm yy');\n\tequalsDate($.datepicker.parseDate('d m y', '13 12 01'),\n\t\tnew Date(2001, 12 - 1, 13), 'Parse date d m y');\n\tequalsDate($.datepicker.parseDate('dd mm yy', '13 12 2001'),\n\t\tnew Date(2001, 12 - 1, 13), 'Parse date dd mm yy');\n\tequalsDate($.datepicker.parseDate('y-o', '01-34'),\n\t\tnew Date(2001, 2 - 1, 3), 'Parse date y-o');\n\tequalsDate($.datepicker.parseDate('yy-oo', '2001-347'),\n\t\tnew Date(2001, 12 - 1, 13), 'Parse date yy-oo');\n\tequalsDate($.datepicker.parseDate('oo yy', '348 2004'),\n\t\tnew Date(2004, 12 - 1, 13), 'Parse date oo yy');\n\tequalsDate($.datepicker.parseDate('D d M y', 'Sat 3 Feb 01'),\n\t\tnew Date(2001, 2 - 1, 3), 'Parse date D d M y');\n\tequalsDate($.datepicker.parseDate('d MM DD yy', '3 February Saturday 2001'),\n\t\tnew Date(2001, 2 - 1, 3), 'Parse date dd MM DD yy');\n\tequalsDate($.datepicker.parseDate('DD, MM d, yy', 'Saturday, February 3, 2001'),\n\t\tnew Date(2001, 2 - 1, 3), 'Parse date DD, MM d, yy');\n\tequalsDate($.datepicker.parseDate('\\'day\\' d \\'of\\' MM (\\'\\'DD\\'\\'), yy',\n\t\t'day 3 of February (\\'Saturday\\'), 2001'), new Date(2001, 2 - 1, 3),\n\t\t'Parse date \\'day\\' d \\'of\\' MM (\\'\\'DD\\'\\'), yy');\n\tcurrentYear = new Date().getFullYear();\n\tequalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000) + '-02-03'),\n\t\t\tnew Date(currentYear, 2 - 1, 3), 'Parse date y-m-d - default cutuff');\n\tequalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 10) + '-02-03'),\n\t\t\tnew Date(currentYear+10, 2 - 1, 3), 'Parse date y-m-d - default cutuff');\n\tequalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 11) + '-02-03'),\n\t\t\tnew Date(currentYear-89, 2 - 1, 3), 'Parse date y-m-d - default cutuff');\n\tequalsDate($.datepicker.parseDate('y-m-d', '80-02-03', {shortYearCutoff: 80}),\n\t\tnew Date(2080, 2 - 1, 3), 'Parse date y-m-d - cutoff 80');\n\tequalsDate($.datepicker.parseDate('y-m-d', '81-02-03', {shortYearCutoff: 80}),\n\t\tnew Date(1981, 2 - 1, 3), 'Parse date y-m-d - cutoff 80');\n\tequalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 60) + '-02-03', {shortYearCutoff: '+60'}),\n\t\t\tnew Date(currentYear + 60, 2 - 1, 3), 'Parse date y-m-d - cutoff +60');\n\tequalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 61) + '-02-03', {shortYearCutoff: '+60'}),\n\t\t\tnew Date(currentYear - 39, 2 - 1, 3), 'Parse date y-m-d - cutoff +60');\n\tgmtDate = new Date(2001, 2 - 1, 3);\n\tgmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset());\n\tequalsDate($.datepicker.parseDate('@', '981158400000'), gmtDate, 'Parse date @');\n\tequalsDate($.datepicker.parseDate('!', '631167552000000000'), gmtDate, 'Parse date !');\n\tfr = $.datepicker.regional.fr;\n\tsettings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,\n\t\tmonthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};\n\tequalsDate($.datepicker.parseDate('D d M y', 'Lun. 9 Avril 01', settings),\n\t\tnew Date(2001, 4 - 1, 9), 'Parse date D M y with settings');\n\tequalsDate($.datepicker.parseDate('d MM DD yy', '9 Avril Lundi 2001', settings),\n\t\tnew Date(2001, 4 - 1, 9), 'Parse date d MM DD yy with settings');\n\tequalsDate($.datepicker.parseDate('DD, MM d, yy', 'Lundi, Avril 9, 2001', settings),\n\t\tnew Date(2001, 4 - 1, 9), 'Parse date DD, MM d, yy with settings');\n\tequalsDate($.datepicker.parseDate('\\'jour\\' d \\'de\\' MM (\\'\\'DD\\'\\'), yy',\n\t\t'jour 9 de Avril (\\'Lundi\\'), 2001', settings), new Date(2001, 4 - 1, 9),\n\t\t'Parse date \\'jour\\' d \\'de\\' MM (\\'\\'DD\\'\\'), yy with settings');\n\n\tzh = $.datepicker.regional['zh-CN'];\n\tequalsDate($.datepicker.parseDate('yy M d', '2011 十一 22', zh),\n\t\tnew Date(2011, 11 - 1, 22), 'Parse date yy M d with zh-CN');\n});\n\ntest('parseDateErrors', function() {\n\tinit('#inp');\n\tvar fr, settings;\n\tfunction expectError(expr, value, error) {\n\t\ttry {\n\t\t\texpr();\n\t\t\tok(false, 'Parsed error ' + value);\n\t\t}\n\t\tcatch (e) {\n\t\t\tequal(e, error, 'Parsed error ' + value);\n\t\t}\n\t}\n\texpectError(function() { $.datepicker.parseDate(null, 'Sat 2 01'); },\n\t\t'Sat 2 01', 'Invalid arguments');\n\texpectError(function() { $.datepicker.parseDate('d m y', null); },\n\t\t'null', 'Invalid arguments');\n\texpectError(function() { $.datepicker.parseDate('d m y', 'Sat 2 01'); },\n\t\t'Sat 2 01 - d m y', 'Missing number at position 0');\n\texpectError(function() { $.datepicker.parseDate('dd mm yy', 'Sat 2 01'); },\n\t\t'Sat 2 01 - dd mm yy', 'Missing number at position 0');\n\texpectError(function() { $.datepicker.parseDate('d m y', '3 Feb 01'); },\n\t\t'3 Feb 01 - d m y', 'Missing number at position 2');\n\texpectError(function() { $.datepicker.parseDate('dd mm yy', '3 Feb 01'); },\n\t\t'3 Feb 01 - dd mm yy', 'Missing number at position 2');\n\texpectError(function() { $.datepicker.parseDate('d m y', '3 2 AD01'); },\n\t\t'3 2 AD01 - d m y', 'Missing number at position 4');\n\texpectError(function() { $.datepicker.parseDate('d m yy', '3 2 AD01'); },\n\t\t'3 2 AD01 - dd mm yy', 'Missing number at position 4');\n\texpectError(function() { $.datepicker.parseDate('y-o', '01-D01'); },\n\t\t'2001-D01 - y-o', 'Missing number at position 3');\n\texpectError(function() { $.datepicker.parseDate('yy-oo', '2001-D01'); },\n\t\t'2001-D01 - yy-oo', 'Missing number at position 5');\n\texpectError(function() { $.datepicker.parseDate('D d M y', 'D7 3 Feb 01'); },\n\t\t'D7 3 Feb 01 - D d M y', 'Unknown name at position 0');\n\texpectError(function() { $.datepicker.parseDate('D d M y', 'Sat 3 M2 01'); },\n\t\t'Sat 3 M2 01 - D d M y', 'Unknown name at position 6');\n\texpectError(function() { $.datepicker.parseDate('DD, MM d, yy', 'Saturday- Feb 3, 2001'); },\n\t\t'Saturday- Feb 3, 2001 - DD, MM d, yy', 'Unexpected literal at position 8');\n\texpectError(function() { $.datepicker.parseDate('\\'day\\' d \\'of\\' MM (\\'\\'DD\\'\\'), yy',\n\t\t'day 3 of February (\"Saturday\"), 2001'); },\n\t\t'day 3 of Mon2 (\"Day7\"), 2001', 'Unexpected literal at position 19');\n\texpectError(function() { $.datepicker.parseDate('d m y', '29 2 01'); },\n\t\t'29 2 01 - d m y', 'Invalid date');\n\tfr = $.datepicker.regional.fr;\n\tsettings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,\n\t\tmonthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};\n\texpectError(function() { $.datepicker.parseDate('D d M y', 'Mon 9 Avr 01', settings); },\n\t\t'Mon 9 Avr 01 - D d M y', 'Unknown name at position 0');\n\texpectError(function() { $.datepicker.parseDate('D d M y', 'Lun. 9 Apr 01', settings); },\n\t\t'Lun. 9 Apr 01 - D d M y', 'Unknown name at position 7');\n});\n\ntest('formatDate', function() {\n\tinit('#inp');\n\tvar gmtDate, fr, settings;\n\tequal($.datepicker.formatDate('d m y', new Date(2001, 2 - 1, 3)),\n\t\t'3 2 01', 'Format date d m y');\n\tequal($.datepicker.formatDate('dd mm yy', new Date(2001, 2 - 1, 3)),\n\t\t'03 02 2001', 'Format date dd mm yy');\n\tequal($.datepicker.formatDate('d m y', new Date(2001, 12 - 1, 13)),\n\t\t'13 12 01', 'Format date d m y');\n\tequal($.datepicker.formatDate('dd mm yy', new Date(2001, 12 - 1, 13)),\n\t\t'13 12 2001', 'Format date dd mm yy');\n\tequal($.datepicker.formatDate('yy-o', new Date(2001, 2 - 1, 3)),\n\t\t'2001-34', 'Format date yy-o');\n\tequal($.datepicker.formatDate('yy-oo', new Date(2001, 2 - 1, 3)),\n\t\t'2001-034', 'Format date yy-oo');\n\tequal($.datepicker.formatDate('D M y', new Date(2001, 2 - 1, 3)),\n\t\t'Sat Feb 01', 'Format date D M y');\n\tequal($.datepicker.formatDate('DD MM yy', new Date(2001, 2 - 1, 3)),\n\t\t'Saturday February 2001', 'Format date DD MM yy');\n\tequal($.datepicker.formatDate('DD, MM d, yy', new Date(2001, 2 - 1, 3)),\n\t\t'Saturday, February 3, 2001', 'Format date DD, MM d, yy');\n\tequal($.datepicker.formatDate('\\'day\\' d \\'of\\' MM (\\'\\'DD\\'\\'), yy',\n\t\tnew Date(2001, 2 - 1, 3)), 'day 3 of February (\\'Saturday\\'), 2001',\n\t\t'Format date \\'day\\' d \\'of\\' MM (\\'\\'DD\\'\\'), yy');\n\tgmtDate = new Date(2001, 2 - 1, 3);\n\tgmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset());\n\tequal($.datepicker.formatDate('@', gmtDate), '981158400000', 'Format date @');\n\tequal($.datepicker.formatDate('!', gmtDate), '631167552000000000', 'Format date !');\n\tfr = $.datepicker.regional.fr;\n\tsettings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames,\n\t\tmonthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames};\n\tequal($.datepicker.formatDate('D M y', new Date(2001, 4 - 1, 9), settings),\n\t\t'Lun. Avril 01', 'Format date D M y with settings');\n\tequal($.datepicker.formatDate('DD MM yy', new Date(2001, 4 - 1, 9), settings),\n\t\t'Lundi Avril 2001', 'Format date DD MM yy with settings');\n\tequal($.datepicker.formatDate('DD, MM d, yy', new Date(2001, 4 - 1, 9), settings),\n\t\t'Lundi, Avril 9, 2001', 'Format date DD, MM d, yy with settings');\n\tequal($.datepicker.formatDate('\\'jour\\' d \\'de\\' MM (\\'\\'DD\\'\\'), yy',\n\t\tnew Date(2001, 4 - 1, 9), settings), 'jour 9 de Avril (\\'Lundi\\'), 2001',\n\t\t'Format date \\'jour\\' d \\'de\\' MM (\\'\\'DD\\'\\'), yy with settings');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/datepicker/datepicker_tickets.js",
    "content": "/*\n * datepicker_tickets.js\n */\n(function($) {\n\nmodule(\"datepicker: tickets\");\n\n// http://forum.jquery.com/topic/several-breaking-changes-in-jquery-ui-1-8rc1\ntest('beforeShowDay-getDate', function() {\n\tvar inp = init('#inp', {beforeShowDay: function(date) { inp.datepicker('getDate'); return [true, '']; }}),\n\t   dp = $('#ui-datepicker-div');\n\tinp.val('01/01/2010').datepicker('show');\n\t// contains non-breaking space\n\tequal($('div.ui-datepicker-title').text(), 'January 2010', 'Initial month');\n\t$('a.ui-datepicker-next', dp).click();\n\t$('a.ui-datepicker-next', dp).click();\n\t// contains non-breaking space\n\tequal($('div.ui-datepicker-title').text(), 'March 2010', 'After next clicks');\n\tinp.datepicker('hide').datepicker('show');\n\t$('a.ui-datepicker-prev', dp).click();\n\t$('a.ui-datepicker-prev', dp).click();\n\t// contains non-breaking space\n\tequal($('div.ui-datepicker-title').text(), 'November 2009', 'After prev clicks');\n\tinp.datepicker('hide');\n});\n\ntest('Ticket 7602: Stop datepicker from appearing with beforeShow event handler', function(){\n    var inp = init('#inp',{\n            beforeShow: function(){\n                return false;\n            }\n        }),\n        dp = $('#ui-datepicker-div');\n    inp.datepicker('show');\n    equal(dp.css('display'), 'none',\"beforeShow returns false\");\n    inp.datepicker('destroy');\n\n    inp = init('#inp',{\n        beforeShow: function(){\n        }\n    });\n    dp = $('#ui-datepicker-div');\n    inp.datepicker('show');\n    equal(dp.css('display'), 'block',\"beforeShow returns nothing\");\n\tinp.datepicker('hide');\n    inp.datepicker('destroy');\n\n    inp = init('#inp',{\n        beforeShow: function(){\n            return true;\n        }\n    });\n    dp = $('#ui-datepicker-div');\n    inp.datepicker('show');\n    equal(dp.css('display'), 'block',\"beforeShow returns true\");\n\tinp.datepicker('hide');\n    inp.datepicker('destroy');\n});\n\ntest('Ticket 6827: formatDate day of year calculation is wrong during day lights savings time', function(){\n    var time = $.datepicker.formatDate(\"oo\", new Date(\"2010/03/30 12:00:00 CDT\"));\n    equal(time, \"089\");\n});\n\ntest('Ticket #7244: date parser does not fail when too many numbers are passed into the date function', function() {\n    var date;\n    try{\n        date = $.datepicker.parseDate('dd/mm/yy', '18/04/19881');\n        ok(false, \"Did not properly detect an invalid date\");\n    }catch(e){\n        ok(\"invalid date detected\");\n    }\n\n    try {\n      date = $.datepicker.parseDate('dd/mm/yy', '18/04/1988 @ 2:43 pm');\n      equal(date.getDate(), 18);\n      equal(date.getMonth(), 3);\n      equal(date.getFullYear(), 1988);\n    } catch(e) {\n      ok(false, \"Did not properly parse date with extra text separated by whitespace\");\n    }\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"dialog\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Dialog Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Dialog Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script src=\"../../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.dialog\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.position.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.draggable.js\",\n\t\t\t\"ui/jquery.ui.resizable.js\",\n\t\t\t\"ui/jquery.ui.dialog.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"dialog_common.js\"></script>\n\t<script src=\"dialog_core.js\"></script>\n\t<script src=\"dialog_events.js\"></script>\n\t<script src=\"dialog_methods.js\"></script>\n\t<script src=\"dialog_options.js\"></script>\n\t<script src=\"dialog_tickets.js\"></script>\n\n\t<script>\n\t// disable this testsuite for testswarm only - until we fix it from freezing IE6\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"dialog\", function() { ok(true, \"disabled dialog testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Dialog Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog_common.js",
    "content": "TestHelpers.commonWidgetTests( \"dialog\", {\n\tdefaults: {\n\t\tautoOpen: true,\n\t\tbuttons: {},\n\t\tcloseOnEscape: true,\n\t\tcloseText: 'close',\n\t\tdisabled: false,\n\t\tdialogClass: '',\n\t\tdraggable: true,\n\t\theight: 'auto',\n\t\thide: null,\n\t\tmaxHeight: false,\n\t\tmaxWidth: false,\n\t\tminHeight: 150,\n\t\tminWidth: 150,\n\t\tmodal: false,\n\t\tposition: {\n\t\t\tmy: 'center',\n\t\t\tat: 'center',\n\t\t\tof: window,\n\t\t\tcollision: 'fit',\n\t\t\tusing: $.ui.dialog.prototype.options.position.using\n\t\t},\n\t\tresizable: true,\n\t\tshow: null,\n\t\tstack: true,\n\t\ttitle: '',\n\t\twidth: 300,\n\t\tzIndex: 1000,\n\n\t\t// callbacks\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog_core.js",
    "content": "/*\n * dialog_core.js\n */\n\nvar el,\n\toffsetBefore, offsetAfter,\n\theightBefore, heightAfter,\n\twidthBefore, widthAfter,\n\tdragged;\n\nfunction dlg() {\n\treturn el.dialog('widget');\n}\n\nfunction isOpen(why) {\n\tok(dlg().is(\":visible\"), why);\n}\n\nfunction isNotOpen(why) {\n\tok(!dlg().is(\":visible\"), why);\n}\n\nfunction drag(handle, dx, dy) {\n\tvar d = dlg();\n\toffsetBefore = d.offset();\n\theightBefore = d.height();\n\twidthBefore = d.width();\n\t//this mouseover is to work around a limitation in resizable\n\t//TODO: fix resizable so handle doesn't require mouseover in order to be used\n\t$(handle, d).simulate(\"mouseover\");\n\t$(handle, d).simulate(\"drag\", {\n\t\tdx: dx || 0,\n\t\tdy: dy || 0\n\t});\n\tdragged = { dx: dx, dy: dy };\n\toffsetAfter = d.offset();\n\theightAfter = d.height();\n\twidthAfter = d.width();\n}\n\nfunction moved(dx, dy, msg) {\n\tmsg = msg ? msg + \".\" : \"\";\n\tvar actual = { left: Math.round(offsetAfter.left), top: Math.round(offsetAfter.top) },\n\t\texpected = { left: Math.round(offsetBefore.left + dx), top: Math.round(offsetBefore.top + dy) };\n\tdeepEqual(actual, expected, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ' + msg);\n}\n\nfunction shouldmove(why) {\n\tvar handle = $(\".ui-dialog-titlebar\", dlg());\n\tdrag(handle, 50, -50);\n\tmoved(50, -50, why);\n}\n\nfunction shouldnotmove(why) {\n\tvar handle = $(\".ui-dialog-titlebar\", dlg());\n\tdrag(handle, 50, -50);\n\tmoved(0, 0, why);\n}\n\nfunction resized(dw, dh, msg) {\n\tmsg = msg ? msg + \".\" : \"\";\n\tvar actual = { width: widthAfter, height: heightAfter },\n\t\texpected = { width: widthBefore + dw, height: heightBefore + dh };\n\tdeepEqual(actual, expected, 'resized[' + dragged.dx + ', ' + dragged.dy + '] ' + msg);\n}\n\nfunction shouldresize(why) {\n\tvar handle = $(\".ui-resizable-se\", dlg());\n\tdrag(handle, 50, 50);\n\tresized(50, 50, why);\n}\n\nfunction shouldnotresize(why) {\n\tvar handle = $(\".ui-resizable-se\", dlg());\n\tdrag(handle, 50, 50);\n\tresized(0, 0, why);\n}\n\nfunction broder(el, side){\n\treturn parseInt(el.css('border-' + side + '-width'), 10);\n}\n\nfunction margin(el, side) {\n\treturn parseInt(el.css('margin-' + side), 10);\n}\n\n(function($) {\n\nmodule(\"dialog: core\");\n\ntest(\"title id\", function() {\n\texpect(1);\n\n\tel = $('<div></div>').dialog();\n\tvar titleId = dlg().find('.ui-dialog-title').attr('id');\n\tok( /ui-id-\\d+$/.test( titleId ), 'auto-numbered title id');\n\tel.remove();\n});\n\ntest(\"ARIA\", function() {\n\texpect(4);\n\n\tel = $('<div></div>').dialog();\n\n\tequal(dlg().attr('role'), 'dialog', 'dialog role');\n\n\tvar labelledBy = dlg().attr('aria-labelledby');\n\tok(labelledBy.length > 0, 'has aria-labelledby attribute');\n\tequal(dlg().find('.ui-dialog-title').attr('id'), labelledBy,\n\t\t'proper aria-labelledby attribute');\n\n\tequal(dlg().find('.ui-dialog-titlebar-close').attr('role'), 'button',\n\t\t'close link role');\n\n\tel.remove();\n});\n\ntest(\"widget method\", function() {\n\tvar dialog = $(\"<div>\").appendTo(\"#main\").dialog();\n\tdeepEqual(dialog.parent()[0], dialog.dialog(\"widget\")[0]);\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog_events.js",
    "content": "/*\n * dialog_events.js\n */\n(function($) {\n\nmodule(\"dialog: events\");\n\ntest(\"open\", function() {\n\texpect(13);\n\n\tel = $(\"<div></div>\");\n\tel.dialog({\n\t\topen: function(ev, ui) {\n\t\t\tok(el.data(\"dialog\")._isOpen, \"interal _isOpen flag is set\");\n\t\t\tok(true, 'autoOpen: true fires open callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogopen', 'event type in callback');\n\t\t\tdeepEqual(ui, {}, 'ui hash in callback');\n\t\t}\n\t});\n\tel.remove();\n\n\tel = $(\"<div></div>\");\n\tel.dialog({\n\t\tautoOpen: false,\n\t\topen: function(ev, ui) {\n\t\t\tok(true, '.dialog(\"open\") fires open callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogopen', 'event type in callback');\n\t\t\tdeepEqual(ui, {}, 'ui hash in callback');\n\t\t}\n\t}).bind('dialogopen', function(ev, ui) {\n\t\tok(el.data(\"dialog\")._isOpen, \"interal _isOpen flag is set\");\n\t\tok(true, 'dialog(\"open\") fires open event');\n\t\tequal(this, el[0], 'context of event');\n\t\tdeepEqual(ui, {}, 'ui hash in event');\n\t});\n\tel.dialog(\"open\");\n\tel.remove();\n});\n\ntest(\"dragStart\", function() {\n\texpect(9);\n\n\tel = $('<div></div>').dialog({\n\t\tdragStart: function(ev, ui) {\n\t\t\tok(true, 'dragging fires dragStart callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogdragstart', 'event type in callback');\n\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\tok(ui.offset !== undefined, \"ui.offset in callback\");\n\t\t}\n\t}).bind('dialogdragstart', function(ev, ui) {\n\t\tok(true, 'dragging fires dialogdragstart event');\n\t\tequal(this, el[0], 'context of event');\n\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\tok(ui.offset !== undefined, \"ui.offset in callback\");\n\t});\n\tvar handle = $(\".ui-dialog-titlebar\", dlg());\n\tdrag(handle, 50, 50);\n\tel.remove();\n});\n\ntest(\"drag\", function() {\n\texpect(9);\n\tvar handle,\n\t\thasDragged = false;\n\n\tel = $('<div></div>').dialog({\n\t\tdrag: function(ev, ui) {\n\t\t\tif (!hasDragged) {\n\t\t\t\tok(true, 'dragging fires drag callback');\n\t\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\t\tequal(ev.type, 'dialogdrag', 'event type in callback');\n\t\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\t\tok(ui.offset !== undefined, \"ui.offset in callback\");\n\n\t\t\t\thasDragged = true;\n\t\t\t}\n\t\t}\n\t}).one('dialogdrag', function(ev, ui) {\n\t\tok(true, 'dragging fires dialogdrag event');\n\t\tequal(this, el[0], 'context of event');\n\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\tok(ui.offset !== undefined, \"ui.offset in callback\");\n\t});\n\thandle = $(\".ui-dialog-titlebar\", dlg());\n\tdrag(handle, 50, 50);\n\tel.remove();\n});\n\ntest(\"dragStop\", function() {\n\texpect(9);\n\n\tel = $('<div></div>').dialog({\n\t\tdragStop: function(ev, ui) {\n\t\t\tok(true, 'dragging fires dragStop callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogdragstop', 'event type in callback');\n\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\tok(ui.offset !== undefined, \"ui.offset in callback\");\n\t\t}\n\t}).bind('dialogdragstop', function(ev, ui) {\n\t\tok(true, 'dragging fires dialogdragstop event');\n\t\tequal(this, el[0], 'context of event');\n\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\tok(ui.offset !== undefined, \"ui.offset in callback\");\n\t});\n\tvar handle = $(\".ui-dialog-titlebar\", dlg());\n\tdrag(handle, 50, 50);\n\tel.remove();\n});\n\ntest(\"resizeStart\", function() {\n\texpect(13);\n\n\tel = $('<div></div>').dialog({\n\t\tresizeStart: function(ev, ui) {\n\t\t\tok(true, 'resizing fires resizeStart callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogresizestart', 'event type in callback');\n\t\t\tok(ui.originalPosition !== undefined, \"ui.originalPosition in callback\");\n\t\t\tok(ui.originalSize !== undefined, \"ui.originalSize in callback\");\n\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\tok(ui.size !== undefined, \"ui.size in callback\");\n\t\t}\n\t}).bind('dialogresizestart', function(ev, ui) {\n\t\tok(true, 'resizing fires dialogresizestart event');\n\t\tequal(this, el[0], 'context of event');\n\t\tok(ui.originalPosition !== undefined, \"ui.originalPosition in callback\");\n\t\tok(ui.originalSize !== undefined, \"ui.originalSize in callback\");\n\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\tok(ui.size !== undefined, \"ui.size in callback\");\n\t});\n\tvar handle = $(\".ui-resizable-se\", dlg());\n\tdrag(handle, 50, 50);\n\tel.remove();\n});\n\ntest(\"resize\", function() {\n\texpect(13);\n\tvar handle,\n\t\thasResized = false;\n\n\tel = $('<div></div>').dialog({\n\t\tresize: function(ev, ui) {\n\t\t\tif (!hasResized) {\n\t\t\t\tok(true, 'resizing fires resize callback');\n\t\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\t\tequal(ev.type, 'dialogresize', 'event type in callback');\n\t\t\t\tok(ui.originalPosition !== undefined, \"ui.originalPosition in callback\");\n\t\t\t\tok(ui.originalSize !== undefined, \"ui.originalSize in callback\");\n\t\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\t\tok(ui.size !== undefined, \"ui.size in callback\");\n\n\t\t\t\thasResized = true;\n\t\t\t}\n\t\t}\n\t}).one('dialogresize', function(ev, ui) {\n\t\tok(true, 'resizing fires dialogresize event');\n\t\tequal(this, el[0], 'context of event');\n\t\tok(ui.originalPosition !== undefined, \"ui.originalPosition in callback\");\n\t\tok(ui.originalSize !== undefined, \"ui.originalSize in callback\");\n\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\tok(ui.size !== undefined, \"ui.size in callback\");\n\t});\n\thandle = $(\".ui-resizable-se\", dlg());\n\tdrag(handle, 50, 50);\n\tel.remove();\n});\n\ntest(\"resizeStop\", function() {\n\texpect(13);\n\n\tel = $('<div></div>').dialog({\n\t\tresizeStop: function(ev, ui) {\n\t\t\tok(true, 'resizing fires resizeStop callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogresizestop', 'event type in callback');\n\t\t\tok(ui.originalPosition !== undefined, \"ui.originalPosition in callback\");\n\t\t\tok(ui.originalSize !== undefined, \"ui.originalSize in callback\");\n\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\tok(ui.size !== undefined, \"ui.size in callback\");\n\t\t}\n\t}).bind('dialogresizestop', function(ev, ui) {\n\t\tok(true, 'resizing fires dialogresizestop event');\n\t\tequal(this, el[0], 'context of event');\n\t\t\tok(ui.originalPosition !== undefined, \"ui.originalPosition in callback\");\n\t\t\tok(ui.originalSize !== undefined, \"ui.originalSize in callback\");\n\t\t\tok(ui.position !== undefined, \"ui.position in callback\");\n\t\t\tok(ui.size !== undefined, \"ui.size in callback\");\n\t});\n\tvar handle = $(\".ui-resizable-se\", dlg());\n\tdrag(handle, 50, 50);\n\tel.remove();\n});\n\ntest(\"close\", function() {\n\texpect(7);\n\n\tel = $('<div></div>').dialog({\n\t\tclose: function(ev, ui) {\n\t\t\tok(true, '.dialog(\"close\") fires close callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogclose', 'event type in callback');\n\t\t\tdeepEqual(ui, {}, 'ui hash in callback');\n\t\t}\n\t}).bind('dialogclose', function(ev, ui) {\n\t\tok(true, '.dialog(\"close\") fires dialogclose event');\n\t\tequal(this, el[0], 'context of event');\n\t\tdeepEqual(ui, {}, 'ui hash in event');\n\t});\n\tel.dialog('close');\n\tel.remove();\n});\n\ntest(\"beforeClose\", function() {\n\texpect(14);\n\n\tel = $('<div></div>').dialog({\n\t\tbeforeClose: function(ev, ui) {\n\t\t\tok(true, '.dialog(\"close\") fires beforeClose callback');\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.type, 'dialogbeforeclose', 'event type in callback');\n\t\t\tdeepEqual(ui, {}, 'ui hash in callback');\n\t\t\treturn false;\n\t\t}\n\t});\n\tel.dialog('close');\n\tisOpen('beforeClose callback should prevent dialog from closing');\n\tel.remove();\n\n\tel = $('<div></div>').dialog();\n\tel.dialog('option', 'beforeClose', function(ev, ui) {\n\t\tok(true, '.dialog(\"close\") fires beforeClose callback');\n\t\tequal(this, el[0], \"context of callback\");\n\t\tequal(ev.type, 'dialogbeforeclose', 'event type in callback');\n\t\tdeepEqual(ui, {}, 'ui hash in callback');\n\t\treturn false;\n\t});\n\tel.dialog('close');\n\tisOpen('beforeClose callback should prevent dialog from closing');\n\tel.remove();\n\n\tel = $('<div></div>').dialog().bind('dialogbeforeclose', function(ev, ui) {\n\t\tok(true, '.dialog(\"close\") triggers dialogbeforeclose event');\n\t\tequal(this, el[0], \"context of event\");\n\t\tdeepEqual(ui, {}, 'ui hash in event');\n\t\treturn false;\n\t});\n\tel.dialog('close');\n\tisOpen('dialogbeforeclose event should prevent dialog from closing');\n\tel.remove();\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog_methods.js",
    "content": "/*\n * dialog_methods.js\n */\n(function($) {\n\nmodule(\"dialog: methods\", {\n\tteardown: function() {\n\t\t$(\"body>.ui-dialog\").remove();\n\t}\n});\n\ntest(\"init\", function() {\n\texpect(6);\n\n\t$(\"<div></div>\").appendTo('body').dialog().remove();\n\tok(true, '.dialog() called on element');\n\n\t$([]).dialog().remove();\n\tok(true, '.dialog() called on empty collection');\n\n\t$('<div></div>').dialog().remove();\n\tok(true, '.dialog() called on disconnected DOMElement - never connected');\n\n\t$('<div></div>').appendTo('body').remove().dialog().remove();\n\tok(true, '.dialog() called on disconnected DOMElement - removed');\n\n\tel = $('<div></div>').dialog();\n\tvar foo = el.dialog(\"option\", \"foo\");\n\tel.remove();\n\tok(true, 'arbitrary option getter after init');\n\n\t$('<div></div>').dialog().dialog(\"option\", \"foo\", \"bar\").remove();\n\tok(true, 'arbitrary option setter after init');\n});\n\ntest(\"destroy\", function() {\n\t$(\"<div></div>\").appendTo('body').dialog().dialog(\"destroy\").remove();\n\tok(true, '.dialog(\"destroy\") called on element');\n\n\t$([]).dialog().dialog(\"destroy\").remove();\n\tok(true, '.dialog(\"destroy\") called on empty collection');\n\n\t$('<div></div>').dialog().dialog(\"destroy\").remove();\n\tok(true, '.dialog(\"destroy\") called on disconnected DOMElement');\n\n\tvar expected = $('<div></div>').dialog(),\n\t\tactual = expected.dialog('destroy');\n\tequal(actual, expected, 'destroy is chainable');\n});\n\ntest(\"enable\", function() {\n\tvar expected = $('<div></div>').dialog(),\n\t\tactual = expected.dialog('enable');\n\tequal(actual, expected, 'enable is chainable');\n\n\tel = $('<div></div>').dialog({ disabled: true });\n\tel.dialog('enable');\n\tequal(el.dialog('option', 'disabled'), false, 'enable method sets disabled option to false');\n\tok(!dlg().hasClass('ui-dialog-disabled'), 'enable method removes ui-dialog-disabled class from ui-dialog element');\n});\n\ntest(\"disable\", function() {\n\tvar expected = $('<div></div>').dialog(),\n\t\tactual = expected.dialog('disable');\n\tequal(actual, expected, 'disable is chainable');\n\n\tel = $('<div></div>').dialog({ disabled: false });\n\tel.dialog('disable');\n\tequal(el.dialog('option', 'disabled'), true, 'disable method sets disabled option to true');\n\tok(dlg().hasClass('ui-dialog-disabled'), 'disable method adds ui-dialog-disabled class to ui-dialog element');\n});\n\ntest(\"close\", function() {\n\tvar expected = $('<div></div>').dialog(),\n\t\tactual = expected.dialog('close');\n\tequal(actual, expected, 'close is chainable');\n\n\tel = $('<div></div>').dialog();\n\tok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog visible before close method called');\n\tel.dialog('close');\n\tok(dlg().is(':hidden') && !dlg().is(':visible'), 'dialog hidden after close method called');\n});\n\ntest(\"isOpen\", function() {\n\texpect(4);\n\n\tel = $('<div></div>').dialog();\n\tequal(el.dialog('isOpen'), true, \"dialog is open after init\");\n\tel.dialog('close');\n\tequal(el.dialog('isOpen'), false, \"dialog is closed\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({autoOpen: false});\n\tequal(el.dialog('isOpen'), false, \"dialog is closed after init\");\n\tel.dialog('open');\n\tequal(el.dialog('isOpen'), true, \"dialog is open\");\n\tel.remove();\n});\n\ntest(\"moveToTop\", function() {\n\tvar d1, d2, dlg1, dlg2,\n\t\texpected = $('<div></div>').dialog(),\n\t\tactual = expected.dialog('moveToTop');\n\tequal(actual, expected, 'moveToTop is chainable');\n\n\td1 = $('<div></div>').dialog();\n\tdlg1 = d1.parents('.ui-dialog');\n\td1.dialog('close');\n\td1.dialog('open');\n\td2 = $('<div></div>').dialog();\n\tdlg2 = d2.parents('.ui-dialog');\n\td2.dialog('close');\n\td2.dialog('open');\n\tok(dlg1.css('zIndex') < dlg2.css('zIndex'), 'dialog 1 under dialog 2 before moveToTop method called');\n\td1.dialog('moveToTop');\n\tok(dlg1.css('zIndex') > dlg2.css('zIndex'), 'dialog 1 above dialog 2 after moveToTop method called');\n});\n\ntest(\"open\", function() {\n\tvar expected = $('<div></div>').dialog(),\n\t\tactual = expected.dialog('open');\n\tequal(actual, expected, 'open is chainable');\n\n\tel = $('<div></div>').dialog({ autoOpen: false });\n\tok(dlg().is(':hidden') && !dlg().is(':visible'), 'dialog hidden before open method called');\n\tel.dialog('open');\n\tok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog visible after open method called');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog_options.js",
    "content": "/*\n * dialog_options.js\n */\n(function($) {\n\nmodule(\"dialog: options\");\n\ntest(\"autoOpen\", function() {\n\texpect(2);\n\n\tel = $('<div></div>').dialog({ autoOpen: false });\n\t\tisNotOpen('.dialog({ autoOpen: false })');\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ autoOpen: true });\n\t\tisOpen('.dialog({ autoOpen: true })');\n\tel.remove();\n});\n\ntest(\"buttons\", function() {\n\texpect(21);\n\n\tvar btn, i, newButtons,\n\t\tbuttons = {\n\t\t\"Ok\": function(ev, ui) {\n\t\t\tok(true, \"button click fires callback\");\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.target, btn[0], \"event target\");\n\t\t},\n\t\t\"Cancel\": function(ev, ui) {\n\t\t\tok(true, \"button click fires callback\");\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.target, btn[1], \"event target\");\n\t\t}\n\t};\n\n\tel = $('<div></div>').dialog({ buttons: buttons });\n\tbtn = $(\"button\", dlg());\n\tequal(btn.length, 2, \"number of buttons\");\n\n\ti = 0;\n\t$.each(buttons, function(key, val) {\n\t\tequal(btn.eq(i).text(), key, \"text of button \" + (i+1));\n\t\ti++;\n\t});\n\n\tok(btn.parent().hasClass('ui-dialog-buttonset'), \"buttons in container\");\n\tok(el.parent().hasClass('ui-dialog-buttons'), \"dialog wrapper adds class about having buttons\");\n\n\tbtn.trigger(\"click\");\n\n\tnewButtons = {\n\t\t\"Close\": function(ev, ui) {\n\t\t\tok(true, \"button click fires callback\");\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t\tequal(ev.target, btn[0], \"event target\");\n\t\t}\n\t};\n\n\tdeepEqual(el.dialog(\"option\", \"buttons\"), buttons, '.dialog(\"option\", \"buttons\") getter');\n\tel.dialog(\"option\", \"buttons\", newButtons);\n\tdeepEqual(el.dialog(\"option\", \"buttons\"), newButtons, '.dialog(\"option\", \"buttons\", ...) setter');\n\n\tbtn = $(\"button\", dlg());\n\tequal(btn.length, 1, \"number of buttons after setter\");\n\tbtn.trigger('click');\n\n\ti = 0;\n\t$.each(newButtons, function(key, val) {\n\t\tequal(btn.eq(i).text(), key, \"text of button \" + (i+1));\n\t\ti += 1;\n\t});\n\n\tel.dialog(\"option\", \"buttons\", null);\n\tbtn = $(\"button\", dlg());\n\tequal(btn.length, 0, \"all buttons have been removed\");\n\tequal(el.find(\".ui-dialog-buttonset\").length, 0, \"buttonset has been removed\");\n\tequal(el.parent().hasClass('ui-dialog-buttons'), false, \"dialog wrapper removes class about having buttons\");\n\n\tel.remove();\n});\n\ntest(\"buttons - advanced\", function() {\n\texpect(5);\n\n\tel = $(\"<div></div>\").dialog({\n\t\tbuttons: [\n\t\t\t{\n\t\t\t\ttext: \"a button\",\n\t\t\t\t\"class\": \"additional-class\",\n\t\t\t\tid: \"my-button-id\",\n\t\t\t\tclick: function() {\n\t\t\t\t\tequal(this, el[0], \"correct context\");\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t});\n\tvar buttons = dlg().find(\"button\");\n\tequal(buttons.length, 1, \"correct number of buttons\");\n\tequal(buttons.attr(\"id\"), \"my-button-id\", \"correct id\");\n\tequal(buttons.text(), \"a button\", \"correct label\");\n\tok(buttons.hasClass(\"additional-class\"), \"additional classes added\");\n\tbuttons.click();\n\n\tel.remove();\n});\n\ntest(\"closeOnEscape\", function() {\n\tel = $('<div></div>').dialog({ closeOnEscape: false });\n\tok(true, 'closeOnEscape: false');\n\tok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog is open before ESC');\n\tel.simulate('keydown', { keyCode: $.ui.keyCode.ESCAPE })\n\t\t.simulate('keypress', { keyCode: $.ui.keyCode.ESCAPE })\n\t\t.simulate('keyup', { keyCode: $.ui.keyCode.ESCAPE });\n\tok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog is open after ESC');\n\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ closeOnEscape: true });\n\tok(true, 'closeOnEscape: true');\n\tok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog is open before ESC');\n\tel.simulate('keydown', { keyCode: $.ui.keyCode.ESCAPE })\n\t\t.simulate('keypress', { keyCode: $.ui.keyCode.ESCAPE })\n\t\t.simulate('keyup', { keyCode: $.ui.keyCode.ESCAPE });\n\tok(dlg().is(':hidden') && !dlg().is(':visible'), 'dialog is closed after ESC');\n});\n\ntest(\"closeText\", function() {\n\texpect(3);\n\n\tel = $('<div></div>').dialog();\n\t\tequal(dlg().find('.ui-dialog-titlebar-close span').text(), 'close',\n\t\t\t'default close text');\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ closeText: \"foo\" });\n\t\tequal(dlg().find('.ui-dialog-titlebar-close span').text(), 'foo',\n\t\t\t'closeText on init');\n\tel.remove();\n\n\tel = $('<div></div>').dialog().dialog('option', 'closeText', 'bar');\n\t\tequal(dlg().find('.ui-dialog-titlebar-close span').text(), 'bar',\n\t\t\t'closeText via option method');\n\tel.remove();\n});\n\ntest(\"dialogClass\", function() {\n\texpect(4);\n\n\tel = $('<div></div>').dialog();\n\t\tequal(dlg().is(\".foo\"), false, 'dialogClass not specified. foo class added');\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ dialogClass: \"foo\" });\n\t\tequal(dlg().is(\".foo\"), true, 'dialogClass in init. foo class added');\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ dialogClass: \"foo bar\" });\n\t\tequal(dlg().is(\".foo\"), true, 'dialogClass in init, two classes. foo class added');\n\t\tequal(dlg().is(\".bar\"), true, 'dialogClass in init, two classes. bar class added');\n\tel.remove();\n});\n\ntest(\"draggable\", function() {\n\texpect(4);\n\n\tel = $('<div></div>').dialog({ draggable: false });\n\t\tshouldnotmove();\n\t\tel.dialog('option', 'draggable', true);\n\t\tshouldmove();\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ draggable: true });\n\t\tshouldmove();\n\t\tel.dialog('option', 'draggable', false);\n\t\tshouldnotmove();\n\tel.remove();\n});\n\ntest(\"height\", function() {\n\texpect(4);\n\n\tel = $('<div></div>').dialog();\n\t\tequal(dlg().outerHeight(), 150, \"default height\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ height: 237 });\n\t\tequal(dlg().outerHeight(), 237, \"explicit height\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog();\n\t\tel.dialog('option', 'height', 238);\n\t\tequal(dlg().outerHeight(), 238, \"explicit height set after init\");\n\tel.remove();\n\n\tel = $('<div></div>').css(\"padding\", \"20px\")\n\t\t.dialog({ height: 240 });\n\t\tequal(dlg().outerHeight(), 240, \"explicit height with padding\");\n\tel.remove();\n});\n\ntest(\"maxHeight\", function() {\n\texpect(3);\n\n\tel = $('<div></div>').dialog({ maxHeight: 200 });\n\t\tdrag('.ui-resizable-s', 1000, 1000);\n\t\tequal(heightAfter, 200, \"maxHeight\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ maxHeight: 200 });\n\t\tdrag('.ui-resizable-n', -1000, -1000);\n\t\tequal(heightAfter, 200, \"maxHeight\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ maxHeight: 200 }).dialog('option', 'maxHeight', 300);\n\t\tdrag('.ui-resizable-s', 1000, 1000);\n\t\tequal(heightAfter, 300, \"maxHeight\");\n\tel.remove();\n});\n\ntest(\"maxWidth\", function() {\n\texpect(3);\n\n\tel = $('<div></div>').dialog({ maxWidth: 200 });\n\t\tdrag('.ui-resizable-e', 1000, 1000);\n\t\tequal(widthAfter, 200, \"maxWidth\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ maxWidth: 200 });\n\t\tdrag('.ui-resizable-w', -1000, -1000);\n\t\tequal(widthAfter, 200, \"maxWidth\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ maxWidth: 200 }).dialog('option', 'maxWidth', 300);\n\t\tdrag('.ui-resizable-w', -1000, -1000);\n\t\tequal(widthAfter, 300, \"maxWidth\");\n\tel.remove();\n});\n\ntest(\"minHeight\", function() {\n\texpect(3);\n\n\tel = $('<div></div>').dialog({ minHeight: 10 });\n\t\tdrag('.ui-resizable-s', -1000, -1000);\n\t\tequal(heightAfter, 10, \"minHeight\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ minHeight: 10 });\n\t\tdrag('.ui-resizable-n', 1000, 1000);\n\t\tequal(heightAfter, 10, \"minHeight\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ minHeight: 10 }).dialog('option', 'minHeight', 30);\n\t\tdrag('.ui-resizable-n', 1000, 1000);\n\t\tequal(heightAfter, 30, \"minHeight\");\n\tel.remove();\n});\n\ntest(\"minWidth\", function() {\n\texpect(3);\n\n\tel = $('<div></div>').dialog({ minWidth: 10 });\n\t\tdrag('.ui-resizable-e', -1000, -1000);\n\t\tequal(widthAfter, 10, \"minWidth\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ minWidth: 10 });\n\t\tdrag('.ui-resizable-w', 1000, 1000);\n\t\tequal(widthAfter, 10, \"minWidth\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ minWidth: 30 }).dialog('option', 'minWidth', 30);\n\t\tdrag('.ui-resizable-w', 1000, 1000);\n\t\tequal(widthAfter, 30, \"minWidth\");\n\tel.remove();\n});\n\ntest(\"position, default center on window\", function() {\n\tvar el = $('<div></div>').dialog(),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\tdeepEqual(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft());\n\tdeepEqual(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, top on window\", function() {\n\tvar el = $('<div></div>').dialog({ position: \"top\" }),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\tdeepEqual(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft());\n\tdeepEqual(offset.top, $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, left on window\", function() {\n\tvar el = $('<div></div>').dialog({ position: \"left\" }),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\tdeepEqual(offset.left, 0);\n\tdeepEqual(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, right bottom on window\", function() {\n\tvar el = $('<div></div>').dialog({ position: \"right bottom\" }),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\tdeepEqual(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft());\n\tdeepEqual(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, right bottom on window w/array\", function() {\n\tvar el = $('<div></div>').dialog({ position: [\"right\", \"bottom\"] }),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\tdeepEqual(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft());\n\tdeepEqual(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, offset from top left w/array\", function() {\n\tvar el = $('<div></div>').dialog({ position: [10, 10] }),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\tdeepEqual(offset.left, 10 + $(window).scrollLeft());\n\tdeepEqual(offset.top, 10 + $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, right bottom at right bottom via ui.position args\", function() {\n\tvar el = $('<div></div>').dialog({\n\t\t\tposition: {\n\t\t\t\tmy: \"right bottom\",\n\t\t\t\tat: \"right bottom\"\n\t\t\t}\n\t\t}),\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\n\tdeepEqual(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft());\n\tdeepEqual(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop());\n\tel.remove();\n});\n\ntest(\"position, at another element\", function() {\n\tvar parent = $('<div></div>').css({\n\t\t\tposition: 'absolute',\n\t\t\ttop: 400,\n\t\t\tleft: 600,\n\t\t\theight: 10,\n\t\t\twidth: 10\n\t\t}).appendTo('body'),\n\n\t\tel = $('<div></div>').dialog({\n\t\t\tposition: {\n\t\t\t\tmy: \"left top\",\n\t\t\t\tat: \"left top\",\n\t\t\t\tof: parent\n\t\t\t}\n\t\t}),\n\n\t\tdialog = el.dialog('widget'),\n\t\toffset = dialog.offset();\n\n\tdeepEqual(offset.left, 600);\n\tdeepEqual(offset.top, 400);\n\n\tel.dialog('option', 'position', {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"right bottom\",\n\t\t\tof: parent\n\t});\n\n\toffset = dialog.offset();\n\n\tdeepEqual(offset.left, 610);\n\tdeepEqual(offset.top, 410);\n\n\tel.remove();\n\tparent.remove();\n});\n\ntest(\"resizable\", function() {\n\texpect(4);\n\n\tel = $('<div></div>').dialog();\n\t\tshouldresize(\"[default]\");\n\t\tel.dialog('option', 'resizable', false);\n\t\tshouldnotresize('disabled after init');\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ resizable: false });\n\t\tshouldnotresize(\"disabled in init options\");\n\t\tel.dialog('option', 'resizable', true);\n\t\tshouldresize('enabled after init');\n\tel.remove();\n});\n\ntest(\"title\", function() {\n\texpect(9);\n\n\tfunction titleText() {\n\t\treturn dlg().find(\".ui-dialog-title\").html();\n\t}\n\n\tel = $('<div></div>').dialog();\n\t\t// some browsers return a non-breaking space and some return \"&nbsp;\"\n\t\t// so we get the text to normalize to the actual non-breaking space\n\t\tequal(dlg().find(\".ui-dialog-title\").text(), \" \", \"[default]\");\n\t\tequal(el.dialog(\"option\", \"title\"), \"\", \"option not changed\");\n\tel.remove();\n\n\tel = $('<div title=\"foo\">').dialog();\n\t\tequal(titleText(), \"foo\", \"title in element attribute\");\n\t\tequal(el.dialog(\"option\", \"title\"), \"foo\", \"option updated from attribute\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ title: 'foo' });\n\t\tequal(titleText(), \"foo\", \"title in init options\");\n\t\tequal(el.dialog(\"option\", \"title\"), \"foo\", \"opiton set from options hash\");\n\tel.remove();\n\n\tel = $('<div title=\"foo\">').dialog({ title: 'bar' });\n\t\tequal(titleText(), \"bar\", \"title in init options should override title in element attribute\");\n\t\tequal(el.dialog(\"option\", \"title\"), \"bar\", \"opiton set from options hash\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog().dialog('option', 'title', 'foo');\n\t\tequal(titleText(), 'foo', 'title after init');\n\tel.remove();\n});\n\ntest(\"width\", function() {\n\texpect(3);\n\n\tel = $('<div></div>').dialog();\n\t\tequal(dlg().width(), 300, \"default width\");\n\tel.remove();\n\n\tel = $('<div></div>').dialog({width: 437 });\n\t\tequal(dlg().width(), 437, \"explicit width\");\n\t\tel.dialog('option', 'width', 438);\n\t\tequal(dlg().width(), 438, 'explicit width after init');\n\tel.remove();\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/dialog/dialog_tickets.js",
    "content": "/*\n * dialog_tickets.js\n */\n(function($) {\n\nmodule( \"dialog: tickets\" );\n\nasyncTest( \"#3123: Prevent tabbing out of modal dialogs\", function() {\n\texpect( 3 );\n\n\tvar el = $( \"<div><input id='t3123-first'><input id='t3123-last'></div>\" ).dialog({ modal: true }),\n\t\tinputs = el.find( \"input\" ),\n\t\twidget = el.dialog( \"widget\" );\n\n\tfunction checkTab() {\n\t\tok( $.contains( widget, document.activeElement ), \"Tab key event moved focus within the modal\" );\n\n\t\t// check shift tab\n\t\t$( document.activeElement ).simulate( \"keydown\", { keyCode: $.ui.keyCode.TAB, shiftKey: true });\n\t\tsetTimeout( checkShiftTab, 2 );\n\t}\n\n\tfunction checkShiftTab() {\n\t\tok( $.contains( widget, document.activeElement ), \"Shift-Tab key event moved focus within the modal\" );\n\n\t\tel.remove();\n\t\tstart();\n\t}\n\n\tinputs.eq( 1 ).focus();\n\tequal( document.activeElement, inputs[1], \"Focus set on second input\" );\n\tinputs.eq( 1 ).simulate( \"keydown\", { keyCode: $.ui.keyCode.TAB });\n\n\tsetTimeout( checkTab, 2 );\n});\n\ntest(\"#4826: setting resizable false toggles resizable on dialog\", function() {\n\texpect(6);\n\tvar i;\n\n\tel = $('<div></div>').dialog({ resizable: false });\n\tshouldnotresize(\"[default]\");\n\tfor (i=0; i<2; i++) {\n\t\tel.dialog('close').dialog('open');\n\t\tshouldnotresize('initialized with resizable false toggle ('+ (i+1) +')');\n\t}\n\tel.remove();\n\n\tel = $('<div></div>').dialog({ resizable: true });\n\tshouldresize(\"[default]\");\n\tfor (i=0; i<2; i++) {\n\t\tel.dialog('close').dialog('option', 'resizable', false).dialog('open');\n\t\tshouldnotresize('set option resizable false toggle ('+ (i+1) +')');\n\t}\n\tel.remove();\n\n});\n\ntest(\"#5184: isOpen in dialogclose event is true\", function() {\n\texpect( 3 );\n\n\tel = $( \"<div></div>\" ).dialog({\n\t\tclose: function() {\n\t\t\tok( !el.dialog(\"isOpen\"), \"dialog is not open during close\" );\n\t\t}\n\t});\n\tok( el.dialog(\"isOpen\"), \"dialog is open after init\" );\n\tel.dialog( \"close\" );\n\tok( !el.dialog(\"isOpen\"), \"dialog is not open after close\" );\n\tel.remove();\n});\n\ntest(\"#5531: dialog width should be at least minWidth on creation\", function () {\n    el = $('<div></div>').dialog({\n            width: 200,\n            minWidth: 300\n        });\n\n    equal(el.dialog('option', 'width'), 300, \"width is minWidth\");\n    el.dialog('option', 'width', 200);\n    equal(el.dialog('option', 'width'), 300, \"width unchanged when set to < minWidth\");\n    el.dialog('option', 'width', 320);\n    equal(el.dialog('option', 'width'), 320, \"width changed if set to > minWidth\");\n    el.remove();\n\n    el = $('<div></div>').dialog({\n            minWidth: 300\n        });\n    ok(el.dialog('option', 'width') >=  300, \"width is at least 300\");\n    el.remove();\n\n});\n\ntest(\"#6137: dialog('open') causes form elements to reset on IE7\", function() {\n\texpect(2);\n\n\td1 = $('<form><input type=\"radio\" name=\"radio\" id=\"a\" value=\"a\" checked=\"checked\"></input>' +\n\t\t\t\t'<input type=\"radio\" name=\"radio\" id=\"b\" value=\"b\">b</input></form>').appendTo( \"body\" ).dialog({autoOpen: false});\n\n\td1.find('#b').prop( \"checked\", true );\n\tequal($('input:checked').val(), 'b', \"checkbox b is checked\");\n\n\td1.dialog('open');\n\tequal($('input:checked').val(), 'b', \"checkbox b is checked\");\n\n\td1.remove();\n});\n\ntest(\"#6645: Missing element not found check in overlay\", function(){\n    expect(2);\n    d1 = $('<div title=\"dialog 1\">Dialog 1</div>').dialog({modal: true});\n    d2 = $('<div title=\"dialog 2\">Dialog 2</div>').dialog({modal: true, close: function(){ d2.remove(); }});\n    equal($.ui.dialog.overlay.instances.length, 2, 'two overlays created');\n    d2.dialog('close');\n    equal($.ui.dialog.overlay.instances.length, 1, 'one overlay remains after closing the 2nd overlay');\n    d1.add(d2).remove();\n});\n\ntest(\"#6966: Escape key closes all dialogs, not the top one\", function(){\n\texpect(24);\n    // test with close function removing dialog triggered through the overlay\n    d1 = $('<div title=\"dialog 1\">Dialog 1</div>').dialog({modal: true, close: function(){ d1.remove(); }});\n    d2 = $('<div title=\"dialog 2\">Dialog 2</div>').dialog({modal: true, close: function(){ d2.remove(); }});\n\n    ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog is open');\n    ok(d2.data('dialog') && d2.dialog('isOpen'), 'second dialog is open');\n    \n    $( document ).simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n    ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog still open');\n    ok(!d2.data('dialog'), 'second dialog is closed');\n\n    $( document ).simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n    ok(!d1.data('dialog'), 'first dialog is closed');\n    ok(!d2.data('dialog'), 'second dialog is closed');\n\n    d2.remove();\n    d1.remove();\n    \n\t// test with close function removing dialog triggered through the dialog\n    d1 = $('<div title=\"dialog 1\">Dialog 1</div>').dialog({modal: true, close: function(){ d1.remove(); }});\n    d2 = $('<div title=\"dialog 2\">Dialog 2</div>').dialog({modal: true, close: function(){ d2.remove(); }});\n\n    ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog is open');\n    ok(d2.data('dialog') && d2.dialog('isOpen'), 'second dialog is open');\n    \n    d2.simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n    ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog still open');\n    ok(!d2.data('dialog'), 'second dialog is closed');\n\n    d1.simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE});\n    ok(!d1.data('dialog'), 'first dialog is closed');\n    ok(!d2.data('dialog'), 'second dialog is closed');\n\n    d2.remove();\n    d1.remove();\n\n    // test without close function removing dialog\n    d1 = $('<div title=\"dialog 1\">Dialog 1</div>').dialog({modal: true});\n    d2 = $('<div title=\"dialog 2\">Dialog 2</div>').dialog({modal: true});\n\n    ok(d1.dialog(\"isOpen\"), 'first dialog is open');\n    ok(d2.dialog(\"isOpen\"), 'second dialog is open');\n\n    d2.simulate(\"keydown\", {keyCode: $.ui.keyCode.ESCAPE});\n    ok(d1.dialog(\"isOpen\"), 'first dialog still open');\n    ok(!d2.dialog(\"isOpen\"), 'second dialog is closed');\n\n    d1.simulate(\"keydown\", {keyCode: $.ui.keyCode.ESCAPE});\n    ok(!d1.dialog(\"isOpen\"), 'first dialog is closed');\n    ok(!d2.dialog(\"isOpen\"), 'second dialog is closed');\n\n    d2.remove();\n    d1.remove();\n\n    // test without close function removing dialog triggered through the overlay\n    d1 = $('<div title=\"dialog 1\">Dialog 1</div>').dialog({modal: true});\n    d2 = $('<div title=\"dialog 2\">Dialog 2</div>').dialog({modal: true});\n\n    ok(d1.dialog(\"isOpen\"), 'first dialog is open');\n    ok(d2.dialog(\"isOpen\"), 'second dialog is open');\n\n    $( document ).simulate(\"keydown\", {keyCode: $.ui.keyCode.ESCAPE});\n    ok(d1.dialog(\"isOpen\"), 'first dialog still open');\n    ok(!d2.dialog(\"isOpen\"), 'second dialog is closed');\n\n    $( document ).simulate(\"keydown\", {keyCode: $.ui.keyCode.ESCAPE});\n    ok(!d1.dialog(\"isOpen\"), 'first dialog is closed');\n    ok(!d2.dialog(\"isOpen\"), 'second dialog is closed');\n\n    d2.remove();\n    d1.remove();\n});\n\ntest(\"#4980: Destroy should place element back in original DOM position\", function(){\n    container = $('<div id=\"container\"><div id=\"modal\">Content</div></div>');\n\tmodal = container.find('#modal');\n\tmodal.dialog();\n\tok(!$.contains(container[0], modal[0]), 'dialog should move modal element to outside container element');\n\tmodal.dialog('destroy');\n\tok($.contains(container[0], modal[0]), 'dialog(destroy) should place element back in original DOM position');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"draggable\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Draggable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/draggable.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Draggable Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.draggable.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"draggable_common.js\"></script>\n\t<script src=\"draggable_core.js\"></script>\n\t<script src=\"draggable_events.js\"></script>\n\t<script src=\"draggable_methods.js\"></script>\n\t<script src=\"draggable_options.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"draggable\", function() { ok(true, \"disabled draggable testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Draggable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"draggable1\" style=\"background: green; width: 200px; height: 100px;\">Relative</div>\n<div id=\"draggable2\" style=\"background: green; width: 200px; height: 100px; position: absolute; top: 10px; left: 10px;\"><span>Absolute</span></div>\n<div style='width: 1px; height: 1000px;'></div>\n<div style=\"position: absolute; width: 1px; height: 2000px;\"></div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/draggable_common.js",
    "content": "TestHelpers.commonWidgetTests( \"draggable\", {\n\tdefaults: {\n\t\taddClasses: true,\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tcancel: \"input,textarea,button,select,option\",\n\t\tconnectToSortable: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdelay: 0,\n\t\tdisabled: false,\n\t\tdistance: 1,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\tiframeFix: false,\n\t\topacity: false,\n\t\trefreshPositions: false,\n\t\trevert: false,\n\t\trevertDuration: 500,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\tsnap: false,\n\t\tsnapMode: \"both\",\n\t\tsnapTolerance: 20,\n\t\tstack: false,\n\t\tzIndex: false\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/draggable_core.js",
    "content": "/*\n * draggable_core.js\n */\n\nvar el, offsetBefore, offsetAfter, dragged;\n\nfunction drag(handle, dx, dy) {\n\tvar element = el.data(\"draggable\").element;\n\toffsetBefore = el.offset();\n\t$(handle).simulate(\"drag\", {\n\t\tdx: dx || 0,\n\t\tdy: dy || 0\n\t});\n\tdragged = { dx: dx, dy: dy };\n\toffsetAfter = el.offset();\n}\n\nfunction moved(dx, dy, msg) {\n\tmsg = msg ? msg + \".\" : \"\";\n\tvar actual = { left: offsetAfter.left, top: offsetAfter.top },\n\t\texpected = { left: offsetBefore.left + dx, top: offsetBefore.top + dy };\n\tdeepEqual(actual, expected, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ' + msg);\n}\n\nfunction restoreScroll(what) {\n\tif(what) {\n\t\t$(document).scrollTop(0); $(document).scrollLeft(0);\n\t} else {\n\t\t$(\"#main\")[0].scrollTop = 0; $(\"#main\")[0].scrollLeft = 0;\n\t}\n}\n\n(function($) {\n\nmodule(\"draggable\");\n\ntest(\"element types\", function() {\n\tvar typeNames = ('p,h1,h2,h3,h4,h5,h6,blockquote,ol,ul,dl,div,form' +\n\t\t',table,fieldset,address,ins,del,em,strong,q,cite,dfn,abbr' +\n\t\t',acronym,code,samp,kbd,var,img,object,hr' +\n\t\t',input,button,label,select,iframe').split(',');\n\n\t$.each(typeNames, function(i) {\n\t\tvar typeName = typeNames[i];\n\t\tel = $(document.createElement(typeName)).appendTo('body');\n\t\t(typeName === 'table' && el.append(\"<tr><td>content</td></tr>\"));\n\t\tel.draggable({ cancel: '' });\n\t\tdrag(el, 50, 50);\n\t\tmoved(50, 50, \"&lt;\" + typeName + \"&gt;\");\n\t\tel.draggable(\"destroy\");\n\t\tel.remove();\n\t});\n});\n\ntest(\"No options, relative\", function() {\n\tel = $(\"#draggable1\").draggable();\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n});\n\ntest(\"No options, absolute\", function() {\n\tel = $(\"#draggable2\").draggable();\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/draggable_events.js",
    "content": "/*\n * draggable_events.js\n */\n(function($) {\n\nmodule(\"draggable: events\");\n\ntest(\"callbacks occurrence count\", function() {\n\n\texpect(3);\n\n\tvar start = 0, stop = 0, dragc = 0;\n\tel = $(\"#draggable2\").draggable({\n\t\tstart: function() { start++; },\n\t\tdrag: function() { dragc++; },\n\t\tstop: function() { stop++; }\n\t});\n\n\tdrag(el, 10, 10);\n\n\tequal(start, 1, \"start callback should happen exactly once\");\n\tequal(dragc, 3, \"drag callback should happen exactly once per mousemove\");\n\tequal(stop, 1, \"stop callback should happen exactly once\");\n\n});\n\ntest(\"stopping the start callback\", function() {\n\n\texpect(3);\n\n\tvar start = 0, stop = 0, dragc = 0;\n\tel = $(\"#draggable2\").draggable({\n\t\tstart: function() { start++; return false; },\n\t\tdrag: function() { dragc++; },\n\t\tstop: function() { stop++; }\n\t});\n\n\tdrag(el, 10, 10);\n\n\tequal(start, 1, \"start callback should happen exactly once\");\n\tequal(dragc, 0, \"drag callback should not happen at all\");\n\tequal(stop, 0, \"stop callback should not happen if there wasnt even a start\");\n\n});\n\ntest(\"stopping the drag callback\", function() {\n\n\texpect(3);\n\n\tvar start = 0, stop = 0, dragc = 0;\n\tel = $(\"#draggable2\").draggable({\n\t\tstart: function() { start++;},\n\t\tdrag: function() { dragc++; return false;  },\n\t\tstop: function() { stop++; }\n\t});\n\n\tdrag(el, 10, 10);\n\n\tequal(start, 1, \"start callback should happen exactly once\");\n\tequal(dragc, 1, \"drag callback should happen exactly once\");\n\tequal(stop, 1, \"stop callback should happen, as we need to actively stop the drag\");\n\n});\n\ntest(\"stopping the stop callback\", function() {\n\n\texpect(1);\n\n\tel = $(\"#draggable2\").draggable({\n\t\thelper: 'clone',\n\t\tstop: function() { return false; }\n\t});\n\n\tdrag(el, 10, 10);\n\n\tok($(\"#draggable2\").data('draggable').helper, \"the clone should not be deleted if the stop callback is stopped\");\n\n\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/draggable_methods.js",
    "content": "/*\n * draggable_methods.js\n */\n(function($) {\n\nfunction shouldmove(why) {\n\tdrag(el, 50, 50);\n\tmoved(50, 50, why);\n}\n\nfunction shouldnotmove(why) {\n\tdrag(el, 50, 50);\n\tmoved(0, 0, why);\n}\n\nmodule(\"draggable: methods\");\n\ntest(\"init\", function() {\n\texpect(6);\n\n\t$(\"<div></div>\").appendTo('body').draggable().remove();\n\tok(true, '.draggable() called on element');\n\n\t$([]).draggable();\n\tok(true, '.draggable() called on empty collection');\n\n\t$(\"<div></div>\").draggable();\n\tok(true, '.draggable() called on disconnected DOMElement');\n\n\t$(\"<div></div>\").draggable().draggable(\"foo\");\n\tok(true, 'arbitrary method called after init');\n\n\t$(\"<div></div>\").draggable().draggable(\"option\", \"foo\");\n\tok(true, 'arbitrary option getter after init');\n\n\t$(\"<div></div>\").draggable().draggable(\"option\", \"foo\", \"bar\");\n\tok(true, 'arbitrary option setter after init');\n});\n\ntest(\"destroy\", function() {\n\t$(\"<div></div>\").appendTo('body').draggable().draggable(\"destroy\").remove();\n\tok(true, '.draggable(\"destroy\") called on element');\n\n\t$([]).draggable().draggable(\"destroy\");\n\tok(true, '.draggable(\"destroy\") called on empty collection');\n\n\t$(\"<div></div>\").draggable().draggable(\"destroy\");\n\tok(true, '.draggable(\"destroy\") called on disconnected DOMElement');\n\n\t$(\"<div></div>\").draggable().draggable(\"destroy\").draggable(\"foo\");\n\tok(true, 'arbitrary method called after destroy');\n\n\tvar expected = $('<div></div>').draggable(),\n\t\tactual = expected.draggable('destroy');\n\tequal(actual, expected, 'destroy is chainable');\n});\n\ntest(\"enable\", function() {\n\texpect(7);\n\tel = $(\"#draggable2\").draggable({ disabled: true });\n\tshouldnotmove('.draggable({ disabled: true })');\n\tel.draggable(\"enable\");\n\tshouldmove('.draggable(\"enable\")');\n\tequal(el.draggable(\"option\", \"disabled\"), false, \"disabled option getter\");\n\n\tel.draggable(\"destroy\");\n\tel.draggable({ disabled: true });\n\tshouldnotmove('.draggable({ disabled: true })');\n\tel.draggable(\"option\", \"disabled\", false);\n\tequal(el.draggable(\"option\", \"disabled\"), false, \"disabled option setter\");\n\tshouldmove('.draggable(\"option\", \"disabled\", false)');\n\n\tvar expected = $('<div></div>').draggable(),\n\t\tactual = expected.draggable('enable');\n\tequal(actual, expected, 'enable is chainable');\n});\n\ntest(\"disable\", function() {\n\texpect(7);\n\tel = $(\"#draggable2\").draggable({ disabled: false });\n\tshouldmove('.draggable({ disabled: false })');\n\tel.draggable(\"disable\");\n\tshouldnotmove('.draggable(\"disable\")');\n\tequal(el.draggable(\"option\", \"disabled\"), true, \"disabled option getter\");\n\n\tel.draggable(\"destroy\");\n\n\tel.draggable({ disabled: false });\n\tshouldmove('.draggable({ disabled: false })');\n\tel.draggable(\"option\", \"disabled\", true);\n\tequal(el.draggable(\"option\", \"disabled\"), true, \"disabled option setter\");\n\tshouldnotmove('.draggable(\"option\", \"disabled\", true)');\n\n\tvar expected = $('<div></div>').draggable(),\n\t\tactual = expected.draggable('disable');\n\tequal(actual, expected, 'disable is chainable');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/draggable/draggable_options.js",
    "content": "/*\n * draggable_options.js\n */\n(function($) {\n\nfunction testScroll(position) {\n\t$(\"#main\").css('position', position);\n\tdrag(el, 50, 50);\n\tmoved(50, 50, position+' parent');\n}\n\nfunction setScroll(what) {\n\tif(what) {\n\t\t$(document).scrollTop(100); $(document).scrollLeft(100);\n\t} else {\n\t\t$(\"#main\")[0].scrollTop = 100; $(\"#main\")[0].scrollLeft = 100;\n\t}\n}\n\nfunction border(el, side) {\n\treturn parseInt(el.css('border-' + side + '-width'), 10);\n}\nfunction margin(el, side) {\n\treturn parseInt(el.css('margin-' + side), 10);\n}\n\nmodule(\"draggable: options\");\n\ntest(\"{ addClasses: true }, default\", function() {\n\tel = $(\"<div></div>\").draggable({ addClasses: true });\n\tok(el.is(\".ui-draggable\"), \"'ui-draggable' class added\");\n\n\tel.draggable(\"destroy\");\n});\n\ntest(\"{ addClasses: false }\", function() {\n\tel = $(\"<div></div>\").draggable({ addClasses: false });\n\tok(!el.is(\".ui-draggable\"), \"'ui-draggable' class not added\");\n\n\tel.draggable(\"destroy\");\n});\n\ntest(\"{ appendTo: 'parent' }, default\", function() {\n\tel = $(\"#draggable2\").draggable({ appendTo: 'parent' });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n\n\tel = $(\"#draggable1\").draggable({ appendTo: 'parent' });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n\n});\n\ntest(\"{ appendTo: Element }\", function() {\n\tel = $(\"#draggable2\").draggable({ appendTo: $(\"#draggable2\").parent()[0] });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n\n\tel = $(\"#draggable1\").draggable({ appendTo: $(\"#draggable2\").parent()[0] });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n});\n\ntest(\"{ appendTo: Selector }\", function() {\n\tel = $(\"#draggable2\").draggable({ appendTo: \"#main\" });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n\n\tel = $(\"#draggable1\").draggable({ appendTo: \"#main\" });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n});\n\ntest(\"{ axis: false }, default\", function() {\n\tel = $(\"#draggable2\").draggable({ axis: false });\n\tdrag(el, 50, 50);\n\tmoved(50, 50);\n});\n\ntest(\"{ axis: 'x' }\", function() {\n\tel = $(\"#draggable2\").draggable({ axis: \"x\" });\n\tdrag(el, 50, 50);\n\tmoved(50, 0);\n});\n\ntest(\"{ axis: 'y' }\", function() {\n\tel = $(\"#draggable2\").draggable({ axis: \"y\" });\n\tdrag(el, 50, 50);\n\tmoved(0, 50);\n});\n\ntest(\"{ axis: ? }, unexpected\", function() {\n\tvar unexpected = {\n\t\t\"true\": true,\n\t\t\"{}\": {},\n\t\t\"[]\": [],\n\t\t\"null\": null,\n\t\t\"undefined\": undefined,\n\t\t\"function() {}\": function() {}\n\t};\n\t$.each(unexpected, function(key, val) {\n\t\tel = $(\"#draggable2\").draggable({ axis: val });\n\t\tdrag(el, 50, 50);\n\t\tmoved(50, 50, \"axis: \" + key);\n\t\tel.draggable(\"destroy\");\n\t});\n});\n\ntest(\"{ cancel: 'input,textarea,button,select,option' }, default\", function() {\n\t$('<div id=\"draggable-option-cancel-default\"><input type=\"text\"></div>').appendTo('#main');\n\n\tel = $(\"#draggable-option-cancel-default\").draggable({ cancel: \"input,textarea,button,select,option\" });\n\tdrag(\"#draggable-option-cancel-default\", 50, 50);\n\tmoved(50, 50);\n\n\tel = $(\"#draggable-option-cancel-default\").draggable({ cancel: \"input,textarea,button,select,option\" });\n\tdrag(\"#draggable-option-cancel-default input\", 50, 50);\n\tmoved(0, 0);\n\n\tel.draggable(\"destroy\");\n});\n\ntest(\"{ cancel: 'span' }\", function() {\n\tel = $(\"#draggable2\").draggable();\n\tdrag(\"#draggable2 span\", 50, 50);\n\tmoved(50, 50);\n\n\tel.draggable(\"destroy\");\n\n\tel = $(\"#draggable2\").draggable({ cancel: 'span' });\n\tdrag(\"#draggable2 span\", 50, 50);\n\tmoved(0, 0);\n});\n\ntest(\"{ cancel: ? }, unexpected\", function() {\n\tvar unexpected = {\n\t\t\"true\": true,\n\t\t\"false\": false,\n\t\t\"{}\": {},\n\t\t\"[]\": [],\n\t\t\"null\": null,\n\t\t\"undefined\": undefined,\n\t\t\"function() {return '';}\": function() {return '';},\n\t\t\"function() {return true;}\": function() {return true;},\n\t\t\"function() {return false;}\": function() {return false;}\n\t};\n\t$.each(unexpected, function(key, val) {\n\t\tel = $(\"#draggable2\").draggable({ cancel: val });\n\t\tdrag(el, 50, 50);\n\t\tvar expected = [50, 50];\n\t\tmoved(expected[0], expected[1], \"cancel: \" + key);\n\t\tel.draggable(\"destroy\");\n\t});\n});\n\ntest(\"{ containment: false }, default\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ containment: Element }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ containment: 'parent' }, relative\", function() {\n\tel = $(\"#draggable1\").draggable({ containment: 'parent' });\n\tvar p = el.parent(),\n\t\tpo = p.offset(),\n\t\texpected = {\n\t\t\tleft: po.left + border(p, 'left') + margin(el, 'left'),\n\t\t\ttop: po.top + border(p, 'top') + margin(el, 'top')\n\t\t};\n\tdrag(el, -100, -100);\n\tdeepEqual(offsetAfter, expected, 'compare offset to parent');\n});\n\ntest(\"{ containment: 'parent' }, absolute\", function() {\n\tel = $(\"#draggable2\").draggable({ containment: 'parent' });\n\tvar p = el.parent(),\n\t\tpo = p.offset(),\n\t\texpected = {\n\t\t\tleft: po.left + border(p, 'left') + margin(el, 'left'),\n\t\t\ttop: po.top + border(p, 'top') + margin(el, 'top')\n\t\t};\n\tdrag(el, -100, -100);\n\tdeepEqual(offsetAfter, expected, 'compare offset to parent');\n});\n\ntest(\"{ containment: 'document' }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ containment: 'window' }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ containment: Selector }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ containment: [x1, y1, x2, y2] }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ cursor: 'auto' }, default\", function() {\n\tfunction getCursor() { return $(\"#draggable2\").css(\"cursor\"); }\n\n\texpect(2);\n\n\tvar expected = \"auto\", actual, before, after;\n\n\tel = $(\"#draggable2\").draggable({\n\t\tcursor: expected,\n\t\tstart: function(event, ui) {\n\t\t\tactual = getCursor();\n\t\t}\n\t});\n\n\tbefore = getCursor();\n\tdrag(\"#draggable2\", -1, -1);\n\tafter = getCursor();\n\n\tequal(actual, expected, \"start callback: cursor '\" + expected + \"'\");\n\tequal(after, before, \"after drag: cursor restored\");\n\n});\n\ntest(\"{ cursor: 'move' }\", function() {\n\n\tfunction getCursor() { return $(\"body\").css(\"cursor\"); }\n\n\texpect(2);\n\n\tvar expected = \"move\", actual, before, after;\n\n\tel = $(\"#draggable2\").draggable({\n\t\tcursor: expected,\n\t\tstart: function(event, ui) {\n\t\t\tactual = getCursor();\n\t\t}\n\t});\n\n\tbefore = getCursor();\n\tdrag(\"#draggable2\", -1, -1);\n\tafter = getCursor();\n\n\tequal(actual, expected, \"start callback: cursor '\" + expected + \"'\");\n\tequal(after, before, \"after drag: cursor restored\");\n\n});\n\ntest(\"{ cursorAt: false}, default\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ cursorAt: { left: -5, top: -5 } }\", function() {\n\texpect(4);\n\n\tvar deltaX = -3, deltaY = -3,\n\t\toffsetX = 5, offsetY = 5,\n\t\tcursorAtX = -5, cursorAtY = -5;\n\n\t$.each(['relative', 'absolute'], function(i, position) {\n\t\tvar el = $('#draggable' + (i + 1)).draggable({\n\t\t\t\tcursorAt: { left: cursorAtX, top: cursorAtY },\n\t\t\t\tdrag: function(event, ui) {\n\t\t\t\t\tequal(ui.offset.left, expected.left, position + ' left');\n\t\t\t\t\tequal(ui.offset.top, expected.top, position + ' top');\n\t\t\t\t}\n\t\t\t}),\n\t\t\tbefore = el.offset(),\n\t\t\tpos = {\n\t\t\t\tclientX: before.left + offsetX,\n\t\t\t\tclientY: before.top + offsetY\n\t\t\t},\n\t\t\texpected = {\n\t\t\t\tleft: before.left + offsetX - cursorAtX + deltaX,\n\t\t\t\ttop: before.top + offsetY - cursorAtY + deltaY\n\t\t\t};\n\n\t\tel.simulate(\"mousedown\", pos);\n\t\tpos.clientX += deltaX;\n\t\tpos.clientY += deltaY;\n\t\t$(document).simulate(\"mousemove\", pos);\n\t\tel.simulate(\"mouseup\", pos);\n\t});\n});\n\ntest(\"{ cursorAt: { right: 10, bottom: 20 } }\", function() {\n\texpect(4);\n\n\tvar deltaX = -3, deltaY = -3,\n\t\toffsetX = 5, offsetY = 5,\n\t\tcursorAtX = 10, cursorAtY = 20;\n\n\t$.each(['relative', 'absolute'], function(i, position) {\n\t\tvar el = $('#draggable' + (i + 1)).draggable({\n\t\t\t\tcursorAt: { right: cursorAtX, bottom: cursorAtY },\n\t\t\t\tdrag: function(event, ui) {\n\t\t\t\t\tequal(ui.offset.left, expected.left, position + ' left');\n\t\t\t\t\tequal(ui.offset.top, expected.top, position + ' top');\n\t\t\t\t}\n\t\t\t}),\n\t\t\tbefore = el.offset(),\n\t\t\tpos = {\n\t\t\t\tclientX: before.left + offsetX,\n\t\t\t\tclientY: before.top + offsetY\n\t\t\t},\n\t\t\texpected = {\n\t\t\t\tleft: before.left + offsetX - el.width() + cursorAtX + deltaX,\n\t\t\t\ttop: before.top + offsetY - el.height() + cursorAtY + deltaY\n\t\t\t};\n\n\t\tel.simulate(\"mousedown\", pos);\n\t\tpos.clientX += deltaX;\n\t\tpos.clientY += deltaY;\n\t\t$(document).simulate(\"mousemove\", pos);\n\t\tel.simulate(\"mouseup\", pos);\n\t});\n});\n\ntest(\"{ cursorAt: [10, 20] }\", function() {\n\texpect(4);\n\n\tvar deltaX = -3, deltaY = -3,\n\t\toffsetX = 5, offsetY = 5,\n\t\tcursorAtX = 10, cursorAtY = 20;\n\n\t$.each(['relative', 'absolute'], function(i, position) {\n\t\tvar el = $('#draggable' + (i + 1)).draggable({\n\t\t\t\tcursorAt: { left: cursorAtX, top: cursorAtY },\n\t\t\t\tdrag: function(event, ui) {\n\t\t\t\t\tequal(ui.offset.left, expected.left, position + ' left');\n\t\t\t\t\tequal(ui.offset.top, expected.top, position + ' top');\n\t\t\t\t}\n\t\t\t}),\n\t\t\tbefore = el.offset(),\n\t\t\tpos = {\n\t\t\t\tclientX: before.left + offsetX,\n\t\t\t\tclientY: before.top + offsetY\n\t\t\t},\n\t\t\texpected = {\n\t\t\t\tleft: before.left + offsetX - cursorAtX + deltaX,\n\t\t\t\ttop: before.top + offsetY - cursorAtY + deltaY\n\t\t\t};\n\n\t\tel.simulate(\"mousedown\", pos);\n\t\tpos.clientX += deltaX;\n\t\tpos.clientY += deltaY;\n\t\t$(document).simulate(\"mousemove\", pos);\n\t\tel.simulate(\"mouseup\", pos);\n\t});\n});\n\ntest(\"{ cursorAt: '20, 40' }\", function() {\n\texpect(4);\n\n\tvar deltaX = -3, deltaY = -3,\n\t\toffsetX = 5, offsetY = 5,\n\t\tcursorAtX = 20, cursorAtY = 40;\n\n\t$.each(['relative', 'absolute'], function(i, position) {\n\t\tvar el = $('#draggable' + (i + 1)).draggable({\n\t\t\t\tcursorAt: { left: cursorAtX, top: cursorAtY },\n\t\t\t\tdrag: function(event, ui) {\n\t\t\t\t\tequal(ui.offset.left, expected.left, position + ' left');\n\t\t\t\t\tequal(ui.offset.top, expected.top, position + ' top');\n\t\t\t\t}\n\t\t\t}),\n\t\t\tbefore = el.offset(),\n\t\t\tpos = {\n\t\t\t\tclientX: before.left + offsetX,\n\t\t\t\tclientY: before.top + offsetY\n\t\t\t},\n\t\t\texpected = {\n\t\t\t\tleft: before.left + offsetX - cursorAtX + deltaX,\n\t\t\t\ttop: before.top + offsetY - cursorAtY + deltaY\n\t\t\t};\n\n\t\tel.simulate(\"mousedown\", pos);\n\t\tpos.clientX += deltaX;\n\t\tpos.clientY += deltaY;\n\t\t$(document).simulate(\"mousemove\", pos);\n\t\tel.simulate(\"mouseup\", pos);\n\t});\n});\n\ntest(\"{ distance: 10 }\", function() {\n\n\tel = $(\"#draggable2\").draggable({ distance: 10 });\n\tdrag(el, -9, -9);\n\tmoved(0, 0, 'distance not met');\n\n\tdrag(el, -10, -10);\n\tmoved(-10, -10, 'distance met');\n\n\tdrag(el, 9, 9);\n\tmoved(0, 0, 'distance not met');\n\n});\n\ntest(\"{ grid: [50, 50] }, relative\", function() {\n\tel = $(\"#draggable1\").draggable({ grid: [50, 50] });\n\tdrag(el, 24, 24);\n\tmoved(0, 0);\n\tdrag(el, 26, 25);\n\tmoved(50, 50);\n});\n\ntest(\"{ grid: [50, 50] }, absolute\", function() {\n\tel = $(\"#draggable2\").draggable({ grid: [50, 50] });\n\tdrag(el, 24, 24);\n\tmoved(0, 0);\n\tdrag(el, 26, 25);\n\tmoved(50, 50);\n});\n\ntest(\"{ handle: 'span' }\", function() {\n\tel = $(\"#draggable2\").draggable({ handle: 'span' });\n\n\tdrag(\"#draggable2 span\", 50, 50);\n\tmoved(50, 50, \"drag span\");\n\n\tdrag(\"#draggable2\", 50, 50);\n\tmoved(0, 0, \"drag element\");\n});\n\ntest(\"{ helper: 'clone' }, relative\", function() {\n\tel = $(\"#draggable1\").draggable({ helper: \"clone\" });\n\tdrag(el, 50, 50);\n\tmoved(0, 0);\n});\n\ntest(\"{ helper: 'clone' }, absolute\", function() {\n\tel = $(\"#draggable2\").draggable({ helper: \"clone\" });\n\tdrag(el, 50, 50);\n\tmoved(0, 0);\n});\n\ntest(\"{ helper: 'original' }, relative, with scroll offset on parent\", function() {\n\n\tel = $(\"#draggable1\").draggable({ helper: \"original\" });\n\n\tsetScroll();\n\ttestScroll('relative');\n\n\tsetScroll();\n\ttestScroll('static');\n\n\tsetScroll();\n\ttestScroll('absolute');\n\n\trestoreScroll();\n\n});\n\ntest(\"{ helper: 'original' }, relative, with scroll offset on root\", function() {\n\n\tel = $(\"#draggable1\").draggable({ helper: \"original\" });\n\n\tsetScroll('root');\n\ttestScroll('relative');\n\n\tsetScroll('root');\n\ttestScroll('static');\n\n\tsetScroll('root');\n\ttestScroll('absolute');\n\n\trestoreScroll('root');\n\n});\n\ntest(\"{ helper: 'original' }, relative, with scroll offset on root and parent\", function() {\n\n\tel = $(\"#draggable1\").draggable({ helper: \"original\" });\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('relative');\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('static');\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('absolute');\n\n\trestoreScroll();\n\trestoreScroll('root');\n\n});\n\ntest(\"{ helper: 'original' }, absolute, with scroll offset on parent\", function() {\n\n\tel = $(\"#draggable1\").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: \"original\" });\n\n\tsetScroll();\n\ttestScroll('relative');\n\n\tsetScroll();\n\ttestScroll('static');\n\n\tsetScroll();\n\ttestScroll('absolute');\n\n\trestoreScroll();\n\n});\n\ntest(\"{ helper: 'original' }, absolute, with scroll offset on root\", function() {\n\n\tel = $(\"#draggable1\").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: \"original\" });\n\n\tsetScroll('root');\n\ttestScroll('relative');\n\n\tsetScroll('root');\n\ttestScroll('static');\n\n\tsetScroll('root');\n\ttestScroll('absolute');\n\n\trestoreScroll('root');\n\n});\n\ntest(\"{ helper: 'original' }, absolute, with scroll offset on root and parent\", function() {\n\n\tel = $(\"#draggable1\").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: \"original\" });\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('relative');\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('static');\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('absolute');\n\n\trestoreScroll();\n\trestoreScroll('root');\n\n});\n\ntest(\"{ helper: 'original' }, fixed, with scroll offset on parent\", function() {\n\n\tel = $(\"#draggable1\").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: \"original\" });\n\n\tsetScroll();\n\ttestScroll('relative');\n\n\tsetScroll();\n\ttestScroll('static');\n\n\tsetScroll();\n\ttestScroll('absolute');\n\n\trestoreScroll();\n\n});\n\ntest(\"{ helper: 'original' }, fixed, with scroll offset on root\", function() {\n\n\tel = $(\"#draggable1\").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: \"original\" });\n\n\tsetScroll('root');\n\ttestScroll('relative');\n\n\tsetScroll('root');\n\ttestScroll('static');\n\n\tsetScroll('root');\n\ttestScroll('absolute');\n\n\trestoreScroll('root');\n});\n\ntest(\"{ helper: 'original' }, fixed, with scroll offset on root and parent\", function() {\n\n\tel = $(\"#draggable1\").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: \"original\" });\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('relative');\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('static');\n\n\tsetScroll();\n\tsetScroll('root');\n\ttestScroll('absolute');\n\n\trestoreScroll();\n\trestoreScroll('root');\n\n});\n\ntest(\"{ helper: 'clone' }, absolute\", function() {\n\n\tvar helperOffset = null,\n\t\torigOffset = $(\"#draggable1\").offset();\n\n\tel = $(\"#draggable1\").draggable({ helper: \"clone\", drag: function(event, ui) {\n\t\thelperOffset = ui.helper.offset();\n\t} });\n\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n});\n\ntest(\"{ helper: 'clone' }, absolute with scroll offset on parent\", function() {\n\n\tsetScroll();\n\tvar helperOffset = null,\n\torigOffset = null;\n\n\tel = $(\"#draggable1\").draggable({ helper: \"clone\", drag: function(event, ui) {\n\t\thelperOffset = ui.helper.offset();\n\t} });\n\n\t$(\"#main\").css('position', 'relative');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\t$(\"#main\").css('position', 'static');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\t$(\"#main\").css('position', 'absolute');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\trestoreScroll();\n\n});\n\ntest(\"{ helper: 'clone' }, absolute with scroll offset on root\", function() {\n\n\tsetScroll('root');\n\tvar helperOffset = null,\n\t\torigOffset = null;\n\n\tel = $(\"#draggable1\").draggable({ helper: \"clone\", drag: function(event, ui) {\n\t\thelperOffset = ui.helper.offset();\n\t} });\n\n\t$(\"#main\").css('position', 'relative');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\t$(\"#main\").css('position', 'static');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\t$(\"#main\").css('position', 'absolute');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\trestoreScroll('root');\n\n});\n\ntest(\"{ helper: 'clone' }, absolute with scroll offset on root and parent\", function() {\n\n\tsetScroll('root');\n\tsetScroll();\n\tvar helperOffset = null,\n\t\torigOffset = null;\n\n\tel = $(\"#draggable1\").draggable({ helper: \"clone\", drag: function(event, ui) {\n\t\thelperOffset = ui.helper.offset();\n\t} });\n\n\t$(\"#main\").css('position', 'relative');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\t$(\"#main\").css('position', 'static');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\t$(\"#main\").css('position', 'absolute');\n\torigOffset = $(\"#draggable1\").offset();\n\tdrag(el, 1, 1);\n\tdeepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ');\n\n\trestoreScroll('root');\n\trestoreScroll();\n\n});\n\ntest(\"{ opacity: 0.5 }\", function() {\n\n\texpect(1);\n\n\tvar opacity = null;\n\tel = $(\"#draggable2\").draggable({\n\t\topacity: 0.5,\n\t\tstart: function(event, ui) {\n\t\t\topacity = $(this).css(\"opacity\");\n\t\t}\n\t});\n\n\tdrag(\"#draggable2\", -1, -1);\n\n\tequal(opacity, 0.5, \"start callback: opacity is\");\n\n});\n\ntest(\"{ zIndex: 10 }\", function() {\n\n\texpect(1);\n\n\tvar actual,\n\t\texpected = 10,\n\t\tzIndex = null;\n\tel = $(\"#draggable2\").draggable({\n\t\tzIndex: expected,\n\t\tstart: function(event, ui) {\n\t\t\tactual = $(this).css(\"zIndex\");\n\t\t}\n\t});\n\n\tdrag(\"#draggable2\", -1, -1);\n\n\tequal(actual, expected, \"start callback: zIndex is\");\n\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"droppable\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Droppable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/droppable.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Droppable Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.draggable.js\",\n\t\t\t\"ui/jquery.ui.droppable.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"droppable_common.js\"></script>\n\t<script src=\"droppable_core.js\"></script>\n\t<script src=\"droppable_events.js\"></script>\n\t<script src=\"droppable_methods.js\"></script>\n\t<script src=\"droppable_options.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"droppable\", function() { ok(true, \"disabled droppable testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Droppable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"draggable1\" style=\"width: 25px; height: 25px;\">Draggable</div>\n<div id=\"droppable1\" style=\"width: 100px; height: 100px;\">Droppable</div>\n<div style='width:1000px;height:1000px;'>&nbsp;</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/droppable_common.js",
    "content": "TestHelpers.commonWidgetTests( \"droppable\", {\n\tdefaults: {\n\t\taccept: \"*\",\n\t\tactiveClass: false,\n\t\taddClasses: true,\n\t\tdisabled: false,\n\t\tgreedy: false,\n\t\thoverClass: false,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\"\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/droppable_core.js",
    "content": "/*\n * droppable_core.js\n */\n\nvar el, drg;\n\nfunction shouldBeDroppable() {\n\tok(false, 'missing test - untested code is broken code');\n}\n\nfunction shouldNotBeDroppable() {\n\tok(false, 'missing test - untested code is broken code');\n}\n\n(function($) {\n\nmodule(\"droppable: core\");\n\ntest(\"element types\", function() {\n\tvar typeNames = ('p,h1,h2,h3,h4,h5,h6,blockquote,ol,ul,dl,div,form' +\n\t\t',table,fieldset,address,ins,del,em,strong,q,cite,dfn,abbr' +\n\t\t',acronym,code,samp,kbd,var,img,object,hr' +\n\t\t',input,button,label,select,iframe').split(',');\n\n\t$.each(typeNames, function(i) {\n\t\tvar typeName = typeNames[i];\n\t\tel = $(document.createElement(typeName)).appendTo('body');\n\t\t(typeName === 'table' && el.append(\"<tr><td>content</td></tr>\"));\n\t\tel.droppable();\n\t\tshouldBeDroppable();\n\t\tel.droppable(\"destroy\");\n\t\tel.remove();\n\t});\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/droppable_events.js",
    "content": "/*\n * droppable_events.js\n */\n(function($) {\n\nmodule(\"droppable: events\");\n\ntest(\"activate\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"deactivate\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"over\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"out\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"drop\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/droppable_methods.js",
    "content": "/*\n * droppable_methods.js\n */\n(function($) {\n\nmodule(\"droppable: methods\");\n\ntest(\"init\", function() {\n\texpect(6);\n\n\t$(\"<div></div>\").appendTo('body').droppable().remove();\n\tok(true, '.droppable() called on element');\n\n\t$([]).droppable();\n\tok(true, '.droppable() called on empty collection');\n\n\t$(\"<div></div>\").droppable();\n\tok(true, '.droppable() called on disconnected DOMElement');\n\n\t$(\"<div></div>\").droppable().droppable(\"foo\");\n\tok(true, 'arbitrary method called after init');\n\n\t$(\"<div></div>\").droppable().droppable(\"option\", \"foo\");\n\tok(true, 'arbitrary option getter after init');\n\n\t$(\"<div></div>\").droppable().droppable(\"option\", \"foo\", \"bar\");\n\tok(true, 'arbitrary option setter after init');\n});\n\ntest(\"destroy\", function() {\n\t$(\"<div></div>\").appendTo('body').droppable().droppable(\"destroy\").remove();\n\tok(true, '.droppable(\"destroy\") called on element');\n\n\t$([]).droppable().droppable(\"destroy\");\n\tok(true, '.droppable(\"destroy\") called on empty collection');\n\n\t$(\"<div></div>\").droppable().droppable(\"destroy\");\n\tok(true, '.droppable(\"destroy\") called on disconnected DOMElement');\n\n\t$(\"<div></div>\").droppable().droppable(\"destroy\").droppable(\"foo\");\n\tok(true, 'arbitrary method called after destroy');\n\n\tvar expected = $('<div></div>').droppable(),\n\t\tactual = expected.droppable('destroy');\n\tequal(actual, expected, 'destroy is chainable');\n});\n\ntest(\"enable\", function() {\n\texpect(7);\n\tel = $(\"#droppable1\").droppable({ disabled: true });\n\tshouldNotBeDroppable();\n\tel.droppable(\"enable\");\n\tshouldBeDroppable();\n\tequal(el.droppable(\"option\", \"disabled\"), false, \"disabled option getter\");\n\tel.droppable(\"destroy\");\n\tel.droppable({ disabled: true });\n\tshouldNotBeDroppable();\n\tel.droppable(\"option\", \"disabled\", false);\n\tequal(el.droppable(\"option\", \"disabled\"), false, \"disabled option setter\");\n\tshouldBeDroppable();\n\n\tvar expected = $('<div></div>').droppable(),\n\t\tactual = expected.droppable('enable');\n\tequal(actual, expected, 'enable is chainable');\n});\n\ntest(\"disable\", function() {\n\texpect(7);\n\tel = $(\"#droppable1\").droppable({ disabled: false });\n\tshouldBeDroppable();\n\tel.droppable(\"disable\");\n\tshouldNotBeDroppable();\n\tequal(el.droppable(\"option\", \"disabled\"), true, \"disabled option getter\");\n\tel.droppable(\"destroy\");\n\tel.droppable({ disabled: false });\n\tshouldBeDroppable();\n\tel.droppable(\"option\", \"disabled\", true);\n\tequal(el.droppable(\"option\", \"disabled\"), true, \"disabled option setter\");\n\tshouldNotBeDroppable();\n\n\tvar expected = $('<div></div>').droppable(),\n\t\tactual = expected.droppable('disable');\n\tequal(actual, expected, 'disable is chainable');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/droppable/droppable_options.js",
    "content": "/*\n * droppable_options.js\n */\n(function($) {\n\nmodule(\"droppable: options\");\n\ntest(\"{ accept '*' }, default \", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ accept: Selector }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ accept: function(draggable) }\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"activeClass\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"{ addClasses: true }, default\", function() {\n\tel = $(\"<div></div>\").droppable({ addClasses: true });\n\tok(el.is(\".ui-droppable\"), \"'ui-droppable' class added\");\n\tel.droppable(\"destroy\");\n});\n\ntest(\"{ addClasses: false }\", function() {\n\tel = $(\"<div></div>\").droppable({ addClasses: false });\n\tok(!el.is(\".ui-droppable\"), \"'ui-droppable' class not added\");\n\tel.droppable(\"destroy\");\n});\n\ntest(\"greedy\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"hoverClass\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"scope\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"tolerance, fit\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"tolerance, intersect\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"tolerance, pointer\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\ntest(\"tolerance, touch\", function() {\n\tok(false, 'missing test - untested code is broken code');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/effects/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"effects\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Effects Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/effects/effects.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script>\n\t$.uiBackCompat = false;\n\t</script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tjs: [\n\t\t\t\"ui/jquery.effects.core.js\",\n\t\t\t\"ui/jquery.effects.blind.js\",\n\t\t\t\"ui/jquery.effects.bounce.js\",\n\t\t\t\"ui/jquery.effects.clip.js\",\n\t\t\t\"ui/jquery.effects.drop.js\",\n\t\t\t\"ui/jquery.effects.explode.js\",\n\t\t\t\"ui/jquery.effects.fade.js\",\n\t\t\t\"ui/jquery.effects.fold.js\",\n\t\t\t\"ui/jquery.effects.highlight.js\",\n\t\t\t\"ui/jquery.effects.pulsate.js\",\n\t\t\t\"ui/jquery.effects.scale.js\",\n\t\t\t\"ui/jquery.effects.shake.js\",\n\t\t\t\"ui/jquery.effects.slide.js\",\n\t\t\t\"ui/jquery.effects.transfer.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"effects_core.js\"></script>\n\t<script src=\"effects_scale.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t#qunit-fixture {\n\t\twidth: 1000px;\n\t\theight: 1000px;\n\t}\n\t.hidden {\n\t\tdisplay: none;\n\t}\n\t.test {\n\t\tbackground: #000;\n\t\tborder: 0;\n\t\twidth: 100px;\n\t\theight: 100px;\n\t}\n\t.testAddBorder {\n\t\tborder: 10px solid #000;\n\t}\n\t.testChildren,\n\t.testChangeBackground {\n\t\tbackground: #fff;\n\t}\n\t.test h2 {\n\t\tfont-size: 10px;\n\t}\n\t.testChildren h2 {\n\t\tfont-size: 20px;\n\t}\n\n\t.relWidth {\n\t\twidth: 50%;\n\t}\n\n\t.relHeight {\n\t\theight: 50%;\n\t}\n\n\t.testScale {\n\t\tborder: 5px solid #000;\n\t\tpadding: 5px;\n\t\tmargin: 5px;\n\t\twidth: 50px;\n\t\theight: 50px;\n\t}\n\n\t.ticket7106 {\n\t\twidth: 50px;\n\t\theight: 50px;\n\t}\n\t.ticket7106.animate {\n\t\twidth: 100px;\n\t}\n\n\t</style>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Effects Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n<div class=\"hidden test\"></div>\n<div class=\"animateClass test\">\n\t<h2>Child Element Test</h2>\n</div>\n<div class=\"relWidth relHeight testAddBorder\">\n\t<h2>Slide with relative width</h2>\n</div>\n<div class=\"testScale\">\n</div>\n<div class=\"ticket7106\">\n</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/effects/effects_core.js",
    "content": "(function($) {\n\nfunction present( value, array, message ) {\n\tQUnit.push( jQuery.inArray( value, array ) !== -1 , value, array, message );\n}\n\nfunction notPresent( value, array, message ) {\n\tQUnit.push( jQuery.inArray( value, array ) === -1 , value, array, message );\n}\n\n// minDuration is used for \"short\" animate tests where we are only concerned about the final\nvar minDuration = 15,\n\n\t// duration is used for \"long\" animates where we plan on testing properties during animation\n\tduration = 200,\n\n\t// mid is used for testing in the \"middle\" of the \"duration\" animations\n\tmid = duration / 2;\n\nmodule( \"effects.core\" );\n\ntest( \"Immediate Return Conditions\", function() {\n\tvar hidden = $( \"div.hidden\" ),\n\t\tcount = 0;\n\texpect( 3 );\n\thidden.hide( \"blind\", function() {\n\t\tequal( ++count, 1, \"Hide on hidden returned immediately\" );\n\t}).show().show( \"blind\", function() {\n\t\tequal( ++count, 2, \"Show on shown returned immediately\" );\n\t});\n\tequal( ++count, 3, \"Both Functions worked properly\" );\n});\n\n/* TODO: Disabled - Can't figure out why this is failing in IE 6/7\ntest( \"createWrapper and removeWrapper retain focused elements (#7595)\", function() {\n\texpect( 2 );\n\tvar test = $( \"div.hidden\" ).show(),\n\t\tinput = $( \"<input type='text'>\" ).appendTo( test ).focus();\n\n\t$.effects.createWrapper( test );\n\tequal( document.activeElement, input[ 0 ], \"Active element is still input after createWrapper\" );\n\t$.effects.removeWrapper( test );\n\tequal( document.activeElement, input[ 0 ], \"Active element is still input after removeWrapper\" );\n});\n*/\n\nmodule( \"effects.core: animateClass\" );\n\nasyncTest( \"animateClass works with borderStyle\", function() {\n\tvar test = $(\"div.animateClass\"),\n\t\tcount = 0;\n\texpect(3);\n\ttest.toggleClass(\"testAddBorder\", minDuration, function() {\n\t\ttest.toggleClass(\"testAddBorder\", minDuration, function() {\n\t\t\tequal( test.css(\"borderLeftStyle\"), \"none\", \"None border set\" );\n\t\t\tstart();\n\t\t});\n\t\tequal( test.css(\"borderLeftStyle\"), \"solid\", \"None border not immedately set\" );\n\t});\n\tequal( test.css(\"borderLeftStyle\"), \"solid\", \"Solid border immedately set\" );\n});\n\nasyncTest( \"animateClass works with colors\", function() {\n\tvar test = $(\"div.animateClass\"),\n\t\tcount = 0,\n\t\toldStep = jQuery.fx.step.backgroundColor;\n\texpect(2);\n\n\t// we want to catch the first frame of animation\n\tjQuery.fx.step.backgroundColor = function( fx ) {\n\t\toldStep.apply( this, arguments );\n\n\t\t// make sure it has animated somewhere we can detect\n\t\tif ( fx.pos > 255 / 2000 ) {\n\t\t\tjQuery.fx.step.backgroundColor = oldStep;\n\t\t\tnotPresent( test.css(\"backgroundColor\"),\n\t\t\t\t[ \"#000000\", \"#ffffff\", \"#000\", \"#fff\", \"rgb(0, 0, 0)\", \"rgb(255,255,255)\" ],\n\t\t\t\t\"Color is not endpoints in middle.\" );\n\t\t\ttest.stop( true, true );\n\t\t}\n\t};\n\n\ttest.toggleClass(\"testChangeBackground\", {\n\t\tduration: 2000,\n\t\tcomplete: function() {\n\t\t\tpresent( test.css(\"backgroundColor\"), [ \"#ffffff\", \"#fff\", \"rgb(255, 255, 255)\" ], \"Color is final\" );\n\t\t\tstart();\n\t\t}\n\t});\n});\n\nasyncTest( \"animateClass calls step option\", 1, function() {\n\tvar test = jQuery(\"div.animateClass\"),\n\t\tdone = function() {\n\t\t\tdone = jQuery.noop;\n\t\t\ttest.stop();\n\t\t\tstart();\n\t\t};\n\ttest.toggleClass( \"testChangeBackground\", {\n\t\tstep: function( fx ) {\n\t\t\tok( true, \"Step Function Called\" );\n\t\t\tsetTimeout( done, 0 );\n\t\t}\n\t});\n});\n\nasyncTest( \"animateClass works with children\", 3, function() {\n\tvar animatedChild,\n\t\ttest = $(\"div.animateClass\"),\n\t\th2 = test.find(\"h2\");\n\n\ttest.toggleClass(\"testChildren\", {\n\t\tchildren: true,\n\t\tduration: duration,\n\t\tcomplete: function() {\n\t\t\tequal( h2.css(\"fontSize\"), \"20px\", \"Text size is final during complete\");\n\t\t\ttest.toggleClass(\"testChildren\", {\n\t\t\t\tduration: duration,\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tequal( h2.css(\"fontSize\"), \"10px\", \"Text size revertted after class removed\");\n\n\t\t\t\t\tstart();\n\t\t\t\t},\n\t\t\t\tstep: function( val, fx ) {\n\t\t\t\t\tif ( fx.elem === h2[ 0 ] ) {\n\t\t\t\t\t\tok( false, \"Error - Animating property on h2\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tstep: function( val, fx ) {\n\t\t\tif ( fx.prop === \"fontSize\" && fx.elem === h2[ 0 ] && !animatedChild ) {\n\t\t\t\tequal( fx.end, 20, \"animating font size on child\" );\n\t\t\t\tanimatedChild = true;\n\t\t\t}\n\t\t}\n\t});\n});\n\nasyncTest( \"animateClass clears style properties when stopped\", function() {\n\tvar test = $(\"div.animateClass\"),\n\t\tstyle = test[0].style,\n\t\torig = style.cssText;\n\n\texpect( 2 );\n\n\ttest.addClass( \"testChangeBackground\", duration );\n\tnotEqual( orig, style.cssText, \"cssText is not the same after starting animation\" );\n\n\ttest.stop( true, true );\n\tequal( orig, $.trim( style.cssText ), \"cssText is the same after stopping animation midway\" );\n\tstart();\n});\n\nasyncTest( \"animateClass: css and class changes during animation are not lost (#7106)\", function() {\n\tvar test = $( \"div.ticket7106\" );\n\n\t// ensure the class stays and that the css property stays\n\tfunction animationComplete() {\n\t\tok( test.hasClass( \"testClass\" ), \"class change during animateClass was not lost\" );\n\t\tequal( test.height(), 100, \"css change during animateClass was not lost\" );\n\t\tstart();\n\t}\n\n\t// add a class and change a style property after starting an animated class\n\ttest.addClass( \"animate\", minDuration, animationComplete )\n\t\t.addClass( \"testClass\" )\n\t\t.height( 100 );\n});\n\n\n$.each( $.effects.effect, function( effect ) {\n\tmodule( \"effects.\" + effect );\n\n\t// puff and size are defined inside scale\n\tif ( effect !== \"puff\" && effect !== \"size\" ) {\n\t\tTestHelpers.testJshint( \"effects.\" + effect );\n\t}\n\n\tif ( effect === \"transfer\" ) {\n\t\treturn;\n\t}\n\tasyncTest( \"show/hide\", function() {\n\t\texpect( 8 );\n\t\tvar hidden = $( \"div.hidden\" ),\n\t\t\tcount = 0,\n\t\t\ttest = 0;\n\n\t\tfunction queueTest( fn ) {\n\t\t\tcount++;\n\t\t\tvar point = count;\n\t\t\treturn function( next ) {\n\t\t\t\ttest++;\n\t\t\t\tequal( point, test, \"Queue function fired in order\" );\n\t\t\t\tif ( fn ) {\n\t\t\t\t\tfn();\n\t\t\t\t} else {\n\t\t\t\t\tsetTimeout( next, minDuration );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\thidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() {\n\t\t\tequal( hidden.css(\"display\"), \"block\", \"Hidden is shown after .show(\\\"\" +effect+ \"\\\", time)\" );\n\t\t})).queue( queueTest() ).hide( effect, minDuration, queueTest(function() {\n\t\t\tequal( hidden.css(\"display\"), \"none\", \"Back to hidden after .hide(\\\"\" +effect+ \"\\\", time)\" );\n\t\t})).queue( queueTest(function(next) {\n\t\t\tdeepEqual( hidden.queue(), [\"inprogress\"], \"Only the inprogress sentinel remains\");\n\t\t\tstart();\n\t\t}));\n\t});\n\n\tasyncTest( \"relative width & height - properties are preserved\", function() {\n\t\tvar test = $(\"div.relWidth.relHeight\"),\n\t\t\twidth = test.width(), height = test.height(),\n\t\t\tcssWidth = test[0].style.width, cssHeight = test[0].style.height;\n\n\t\texpect( 4 );\n\t\ttest.toggle( effect, minDuration, function() {\n\t\t\tequal( test[0].style.width, cssWidth, \"Inline CSS Width has been reset after animation ended\" );\n\t\t\tequal( test[0].style.height, cssHeight, \"Inline CSS Height has been rest after animation ended\" );\n\t\t\tstart();\n\t\t});\n\t\tequal( test.width(), width, \"Width is the same px after animation started\" );\n\t\tequal( test.height(), height, \"Height is the same px after animation started\" );\n\t});\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/effects/effects_scale.js",
    "content": "(function( $ ) {\nmodule( \"effect.scale: Scale\" );\n\nfunction run( position, v, h, vo, ho ) {\n\tvar desc = \"End Position Correct: \" + position + \" (\" + v + \",\" + h + \") - origin: (\" + vo + \",\" + ho + \")\";\n\tasyncTest( desc, function() {\n\t\tfunction complete() {\n\t\t\tequal( parseInt( test.css( h ), 10 ), target[ h ], \"Horizontal Position Correct \" + desc );\n\t\t\tequal( parseInt( test.css( v ), 10 ), target[ v ], \"Vertical Position Correct \" + desc );\n\t\t\tstart();\n\t\t}\n\t\tvar test = $( \".testScale\" ),\n\t\t\tcss = {\n\t\t\t\tposition: position\n\t\t\t},\n\t\t\teffect = {\n\t\t\t\teffect: \"scale\",\n\t\t\t\tmode: \"effect\",\n\t\t\t\tpercent: 200,\n\t\t\t\torigin: [ vo, ho ],\n\t\t\t\tcomplete: complete,\n\t\t\t\tduration: 1\n\t\t\t},\n\t\t\ttarget = {},\n\t\t\trelative = position === \"relative\";\n\n\t\tcss[ h ] = 33;\n\t\tcss[ v ] = 33;\n\t\ttarget[ h ] = h === ho ? css[ h ] : ho === \"center\" ? css[ h ] - 35 : css[ h ] - 70;\n\t\ttarget[ v ] = v === vo ? css[ v ] : vo === \"middle\" ? css[ v ] - 35 : css[ v ] - 70;\n\t\tif ( relative && h === \"right\" ) {\n\t\t\ttarget[ h ] += 70;\n\t\t}\n\t\tif ( relative && v === \"bottom\" ) {\n\t\t\ttarget[ v ] += 70;\n\t\t}\n\t\ttest.css( css );\n\t\ttest.effect( effect );\n\t});\n}\n\nfunction suite( position ) {\n\trun( position, \"top\", \"left\", \"top\", \"left\" );\n\trun( position, \"top\", \"left\", \"middle\", \"center\" );\n\trun( position, \"top\", \"left\", \"bottom\", \"right\" );\n\t/* Firefox is currently not capable of supporting detection of bottom and right....\n\trun( position, \"bottom\", \"right\", \"top\", \"left\" );\n\trun( position, \"bottom\", \"right\", \"middle\", \"center\" );\n\trun( position, \"bottom\", \"right\", \"bottom\", \"right\" );\n\t*/\n}\n\n$(function() {\n\tsuite( \"absolute\" );\n\tsuite( \"relative\" );\n\tvar fixed = $.support.fixedPosition;\n\t// jQuery < 1.7 uses $.offset.supportsFixedPosition\n\tif ( fixed === undefined ) {\n\t\t$.offset.initialize();\n\t\tfixed = $.offset.supportsFixedPosition;\n\t}\n\tif ( fixed ) {\n\t\tsuite( \"fixed\" );\n\t}\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Unit Tests</title>\n\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.core.css\">\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.theme.css\">\n\t<link rel=\"stylesheet\" href=\"../index.css\">\n\t<script src=\"../jquery-1.7.2.js\"></script>\n\t<script src=\"../index.js\"></script>\n</head>\n<body>\n\n<div id=\"main\">\n\t<h1>jQuery UI Unit Tests</h1>\n\t<div>\n\t\t<h2>Full Test Suite</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"all.html\">All</a></li>\n\t\t</ul>\n\n\t\t<h2>Core</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"core/core.html\">Core</a></li>\n\t\t\t<li><a href=\"widget/widget.html\">Widget</a></li>\n\t\t</ul>\n\n\t\t<h2>Interactions</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"draggable/draggable.html\">Draggable</a></li>\n\t\t\t<li><a href=\"droppable/droppable.html\">Droppable</a></li>\n\t\t\t<li><a href=\"resizable/resizable.html\">Resizable</a></li>\n\t\t\t<li><a href=\"selectable/selectable.html\">Selectable</a></li>\n\t\t\t<li><a href=\"sortable/sortable.html\">Sortable</a></li>\n\t\t</ul>\n\n\t\t<h2>Widgets</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"accordion/accordion.html\">Accordion</a></li>\n\t\t\t<li><a href=\"autocomplete/autocomplete.html\">Autocomplete</a></li>\n\t\t\t<li><a href=\"button/button.html\">Button</a></li>\n\t\t\t<li><a href=\"datepicker/datepicker.html\">Datepicker</a></li>\n\t\t\t<li><a href=\"dialog/dialog.html\">Dialog</a></li>\n\t\t\t<li><a href=\"menu/menu.html\">Menu</a></li>\n\t\t\t<li><a href=\"progressbar/progressbar.html\">Progressbar</a></li>\n\t\t\t<li><a href=\"slider/slider.html\">Slider</a></li>\n\t\t\t<li><a href=\"spinner/spinner.html\">Spinner</a></li>\n\t\t\t<li><a href=\"tabs/tabs.html\">Tabs</a></li>\n\t\t\t<li><a href=\"tooltip/tooltip.html\">Tooltip</a></li>\n\t\t</ul>\n\n\t\t<h2>Utilities</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"position/position.html\">Position</a></li>\n\t\t</ul>\n\n\t\t<h2>Effects</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"effects/effects.html\">Effects</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Menu Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"menu\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Menu Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Menu Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.menu\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.menu.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"menu_test_helpers.js\"></script>\n\t<script src=\"menu_common.js\"></script>\n\t<script src=\"menu_core.js\"></script>\n\t<script src=\"menu_events.js\"></script>\n\t<script src=\"menu_methods.js\"></script>\n\t<script src=\"menu_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t.ui-menu {\n\t\tfont-size: 15px;\n\t}\n\t#menu3 {\n\t\theight: 250px;\n\t\toverflow: auto;\n\t}\n\t#menu4, #menu4 ul {\n\t\theight: 250px;\n\t\toverflow: auto;\n\t}\n\t</style>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Menu Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<ul class=\"foo\" id=\"menu1\">\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a id=\"testID1\" class=\"foo\" href=\"#\">Addyston</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n</ul>\n\n<ul id=\"menu2\">\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\"><span class=\"ui-icon ui-icon-print\"></span>Addyston</a></li>\n\t<li>\n\t\t<a href=\"#\">Delphi</a>\n\t\t<ul>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Saarland</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Salzburg</a></li>\n\t\t</ul>\n\t</li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Saarland</a></li>\n\t<li>\n\t\t<a href=\"#\">Salzburg</a>\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t\t\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t\t\t\t\t<li> - </li>\n\t\t\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li></li>\n\t\t\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Salzburg</a></li>\n\t\t\t\t\t<li>&ndash;</li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Perch</a></li>\n\t\t</ul>\n\t</li>\n</ul>\n\n<ul class=\"foo\" id=\"menu3\">\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adena</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adrian</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Akron</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Albany</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alexandria</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alger</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alledonia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alliance</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alpha</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvordton</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amanda</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amelia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amesville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adena</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adrian</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Akron</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Albany</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alexandria</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alger</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alledonia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alliance</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alpha</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvordton</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amanda</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amelia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amesville</a></li>\n</ul>\n\n<ul class=\"foo\" id=\"menu4\">\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo\">\n\t\t<a class=\"foo\" href=\"#\">Ada</a>\n\t\t<ul class=\"foo\">\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adena</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adrian</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Akron</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Albany</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alexandria</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alger</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alledonia</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alliance</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alpha</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvada</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvordton</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amanda</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amelia</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amesville</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adena</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adrian</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Akron</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Albany</a></li>\n\t\t</ul>\n\t</li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adena</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adrian</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Akron</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Albany</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alexandria</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alger</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alledonia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alliance</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alpha</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvordton</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amanda</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amelia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amesville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adelphi</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adena</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adrian</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Akron</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Albany</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alexandria</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alger</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alledonia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alliance</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alpha</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Alvordton</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amanda</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amelia</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Amesville</a></li>\n</ul>\n\n<div id=\"menu5\">\n\t<blockquote><a href=\"#\">Aberdeen</a></blockquote>\n\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t<blockquote><a href=\"#\">Adamsville</a></blockquote>\n\t<blockquote><a href=\"#\">Addyston</a></blockquote>\n\t<blockquote>\n\t\t<a href=\"#\">Delphi</a>\n\t\t<div>\n\t\t\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t\t\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t\t\t<blockquote><a href=\"#\">Salzburg</a></blockquote>\n\t\t</div>\n\t</blockquote>\n\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t<blockquote>\n\t\t<a href=\"#\">Salzburg</a>\n\t\t<div>\n\t\t\t<blockquote>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<div>\n\t\t\t\t\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t\t\t\t\t<blockquote><a id=\"testID2\" href=\"#\">Saarland</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Salzburg</a></blockquote>\n\t\t\t\t</div>\n\t\t\t</blockquote>\n\t\t\t<blockquote>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<div>\n\t\t\t\t\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Salzburg</a></blockquote>\n\t\t\t\t</div>\n\t\t\t</blockquote>\n\t\t\t<blockquote><a href=\"#\">Perch</a></blockquote>\n\t\t</div>\n\t</blockquote>\n</div>\n\n<ul id=\"menu6\">\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Aberdeen</a></li>\n\t<li class=\"foo ui-state-disabled\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Adamsville</a></li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Addyston</a></li>\n\t<li class=\"ui-state-disabled\">\n\t\t<a id=\"testID3\" href=\"#\">Delphi</a>\n\t\t<ul>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Ada</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Saarland</a></li>\n\t\t\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Salzburg</a></li>\n\t\t</ul>\n\t</li>\n\t<li class=\"foo\"><a class=\"foo\" href=\"#\">Saarland</a></li>\n</ul>\n\n<div id=\"log\"></div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu_common.js",
    "content": "TestHelpers.commonWidgetTests( \"menu\", {\n\tdefaults: {\n\t\tdisabled: false,\n\t\tmenus: \"ul\",\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"right top\"\n\t\t},\n\t\trole: \"menu\",\n\n\t\t// callbacks\n\t\tblur: null,\n\t\tcreate: null,\n\t\tfocus: null,\n\t\tselect: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu_core.js",
    "content": "/*\n * menu_core.js\n */\n\n\n(function($) {\n\nmodule(\"menu: core\");\n\ntest(\"accessibility\", function () {\n\texpect(5);\n\tvar item,\n\t\tmenu = $('#menu1').menu(),\n\t\titem0 = $(\"li:eq(0) a\");\n\n\tok( menu.hasClass(\"ui-menu ui-widget ui-widget-content ui-corner-all\"), \"menu class\");\n\tequal( menu.attr(\"role\"), \"menu\", \"main role\");\n\tok( !menu.attr(\"aria-activedescendant\"), \"aria attribute not yet active\");\n\n\titem = menu.find( \"li:first\" ).find( \"a\" ).attr( \"id\", \"xid\" ).end();\n\tmenu.menu( \"focus\", $.Event(), item );\n\tequal( menu.attr(\"aria-activedescendant\"), \"xid\", \"aria attribute, id from dom\");\n\n\titem = menu.find( \"li:last\" );\n\tmenu.menu( \"focus\", $.Event(), item );\n\tok( /^ui-id-\\d+$/.test( menu.attr( \"aria-activedescendant\" ) ), \"aria attribute, generated id\");\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu_events.js",
    "content": "/*\n * menu_events.js\n */\n(function($) {\n\nvar log = TestHelpers.menu.log,\n\tclick = TestHelpers.menu.click;\n\nmodule(\"menu: events\");\n\ntest(\"handle click on menu\", function() {\n\texpect(1);\n\tvar menu = $('#menu1').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog();\n\t\t}\n\t});\n\tlog(\"click\",true);\n\tclick($('#menu1'),\"1\");\n\tlog(\"afterclick\");\n\tclick( menu,\"2\");\n\tclick($('#menu1'),\"3\");\n\tclick( menu,\"1\");\n\tequal( $(\"#log\").html(), \"1,3,2,afterclick,1,click,\", \"Click order not valid.\");\n});\n\ntest(\"handle click on custom item menu\", function() {\n\texpect(1);\n\tvar menu = $('#menu5').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog();\n\t\t},\n\t\tmenus: \"div\"\n\t});\n\tlog(\"click\",true);\n\tclick($('#menu5'),\"1\");\n\tlog(\"afterclick\");\n\tclick( menu,\"2\");\n\tclick($('#menu5'),\"3\");\n\tclick( menu,\"1\");\n\tequal( $(\"#log\").html(), \"1,3,2,afterclick,1,click,\", \"Click order not valid.\");\n});\n\nasyncTest( \"handle blur\", function() {\n\texpect( 1 );\n\tvar blurHandled = false,\n\t\t$menu = $( \"#menu1\" ).menu({\n\t\t\tblur: function( event, ui ) {\n\t\t\t\t// Ignore duplicate blur event fired by IE\n\t\t\t\tif ( !blurHandled ) {\n\t\t\t\t\tblurHandled = true;\n\t\t\t\t\tequal( event.type, \"menublur\", \"blur event.type is 'menublur'\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\tclick( $menu, \"1\" );\n\tsetTimeout( function() {\n\t\t$menu.blur();\n\t\tstart();\n\t}, 350);\n});\n\nasyncTest( \"handle blur on click\", function() {\n\texpect( 1 );\n\tvar blurHandled = false,\n\t\t$menu = $( \"#menu1\" ).menu({\n\t\t\tblur: function( event, ui ) {\n\t\t\t\t// Ignore duplicate blur event fired by IE\n\t\t\t\tif ( !blurHandled ) {\n\t\t\t\t\tblurHandled = true;\n\t\t\t\t\tequal( event.type, \"menublur\", \"blur event.type is 'menublur'\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\tclick( $menu, \"1\" );\n\tsetTimeout( function() {\n\t\t$( \"<a>\", { id: \"remove\"} ).appendTo(\"body\").trigger( \"click\" );\n\t\t$(\"#remove\").remove();\n\t\tstart();\n\t}, 350);\n});\n\ntest( \"handle focus of menu with active item\", function() {\n\texpect( 1 );\n\tvar element = $( \"#menu1\" ).menu({\n\t\tfocus: function( event, ui ) {\n\t\t\tlog( $( event.target ).find( \".ui-state-focus\" ).parent().index() );\n\t\t}\n\t});\n\n\tlog( \"focus\", true );\n\telement.focus();\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\telement.focus();\n\tequal( $(\"#log\").html(), \"2,2,1,0,focus,\", \"current active item remains active\");\n});\n\nasyncTest( \"handle submenu auto collapse: mouseleave\", function() {\n\texpect( 4 );\n\tvar $menu = $( \"#menu2\" ).menu(),\n\t\tevent = $.Event( \"mouseenter\" );\n\n\tfunction menumouseleave1() {\n\t\tequal( $menu.find( \"ul[aria-expanded='true']\" ).length, 1, \"first submenu expanded\" );\n\t\t$menu.menu( \"focus\", event, $menu.find( \"li:nth-child(7) li:first\" ) );\n\t\tsetTimeout( menumouseleave2, 350 );\n\t}\n\tfunction menumouseleave2() {\n\t\tequal( $menu.find( \"ul[aria-expanded='true']\" ).length, 2, \"second submenu expanded\" );\n\t\t$menu.find( \"ul[aria-expanded='true']:first\" ).trigger( \"mouseleave\" );\n\t\tsetTimeout( menumouseleave3, 350 );\n\t}\n\tfunction menumouseleave3() {\n\t\tequal( $menu.find( \"ul[aria-expanded='true']\" ).length, 1, \"second submenu collapsed\" );\n\t\t$menu.trigger( \"mouseleave\" );\n\t\tsetTimeout( menumouseleave4, 350 );\n\t}\n\tfunction menumouseleave4() {\n\t\tequal( $menu.find( \"ul[aria-expanded='true']\" ).length, 0, \"first submenu collapsed\" );\n\t\tstart();\n\t}\n\n\t$menu.find( \"li:nth-child(7)\" ).trigger( \"mouseenter\" );\n\tsetTimeout( menumouseleave1, 350 );\n});\n\nasyncTest( \"handle submenu auto collapse: mouseleave\", function() {\n\texpect( 4 );\n\tvar $menu = $( \"#menu5\" ).menu( { menus: \"div\" } ),\n\t\tevent = $.Event( \"mouseenter\" );\n\n\tfunction menumouseleave1() {\n\t\tequal( $menu.find( \"div[aria-expanded='true']\" ).length, 1, \"first submenu expanded\" );\n\t\t$menu.menu( \"focus\", event, $menu.find( \":nth-child(7)\" ).find( \"div\" ).eq( 0 ).children().eq( 0 ) );\n\t\tsetTimeout( menumouseleave2, 350 );\n\t}\n\tfunction menumouseleave2() {\n\t\tequal( $menu.find( \"div[aria-expanded='true']\" ).length, 2, \"second submenu expanded\" );\n\t\t$menu.find( \"div[aria-expanded='true']:first\" ).trigger( \"mouseleave\" );\n\t\tsetTimeout( menumouseleave3, 350 );\n\t}\n\tfunction menumouseleave3() {\n\t\tequal( $menu.find( \"div[aria-expanded='true']\" ).length, 1, \"second submenu collapsed\" );\n\t\t$menu.trigger( \"mouseleave\" );\n\t\tsetTimeout( menumouseleave4, 350 );\n\t}\n\tfunction menumouseleave4() {\n\t\tequal( $menu.find( \"div[aria-expanded='true']\" ).length, 0, \"first submenu collapsed\" );\n\t\tstart();\n\t}\n\n\t$menu.find( \":nth-child(7)\" ).trigger( \"mouseenter\" );\n\tsetTimeout( menumouseleave1, 350 );\n\n});\n\n\ntest(\"handle keyboard navigation on menu without scroll and without submenus\", function() {\n\texpect(12);\n\tvar element = $('#menu1').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog($(ui.item[0]).text());\n\t\t},\n\t\tfocus: function( event, ui ) {\n\t\t\tlog($(event.target).find(\".ui-state-focus\").parent().index());\n\t\t}\n\t});\n\n\tlog(\"keydown\",true);\n\telement.focus();\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\tequal( $(\"#log\").html(), \"2,1,0,keydown,\", \"Keydown DOWN\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\tequal( $(\"#log\").html(), \"1,keydown,\", \"Keydown UP\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown LEFT (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown RIGHT (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\tequal( $(\"#log\").html(), \"4,keydown,\", \"Keydown PAGE_DOWN\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown PAGE_DOWN (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown PAGE_UP\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown PAGE_UP (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.END } );\n\tequal( $(\"#log\").html(), \"4,keydown,\", \"Keydown END\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.HOME } );\n\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown HOME\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ESCAPE } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown ESCAPE (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\tequal( $(\"#log\").html(), \"Aberdeen,keydown,\", \"Keydown ENTER\");\n});\n\nasyncTest(\"handle keyboard navigation on menu without scroll and with submenus\", function() {\n\texpect(16);\n\tvar element = $('#menu2').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog($(ui.item[0]).text());\n\t\t},\n\t\tfocus: function( event, ui ) {\n\t\t\tlog($(event.target).find(\".ui-state-focus\").parent().index());\n\t\t}\n\t});\n\n\tlog(\"keydown\",true);\n\telement.one( \"menufocus\", function( event, ui ) {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\tequal( $(\"#log\").html(), \"2,1,keydown,\", \"Keydown DOWN\");\n\t\tsetTimeout( menukeyboard1, 50 );\n\t});\n\telement.focus();\n\n\tfunction menukeyboard1() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t\tequal( $(\"#log\").html(), \"0,1,keydown,\", \"Keydown UP\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown LEFT (no effect)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\n\t\tsetTimeout( function() {\n\t\t\tequal( $(\"#log\").html(), \"0,4,3,2,1,keydown,\", \"Keydown RIGHT (open submenu)\");\n\t\t}, 50);\n\t\tsetTimeout( menukeyboard2, 50 );\n\t}\n\n\tfunction menukeyboard2() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\t\tequal( $(\"#log\").html(), \"4,keydown,\", \"Keydown LEFT (close submenu)\");\n\n\t\t//re-open submenu\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\t\tsetTimeout( menukeyboard3, 50 );\n\t}\n\n\tfunction menukeyboard3() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\t\tequal( $(\"#log\").html(), \"2,keydown,\", \"Keydown PAGE_DOWN\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown PAGE_DOWN (no effect)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\t\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown PAGE_UP\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown PAGE_UP (no effect)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.END } );\n\t\tequal( $(\"#log\").html(), \"2,keydown,\", \"Keydown END\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.HOME } );\n\t\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown HOME\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ESCAPE } );\n\t\tequal( $(\"#log\").html(), \"4,keydown,\", \"Keydown ESCAPE (close submenu)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.SPACE } );\n\t\tsetTimeout( menukeyboard4, 50 );\n\t}\n\n\tfunction menukeyboard4() {\n\t\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown SPACE (open submenu)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ESCAPE } );\n\t\tequal( $(\"#log\").html(), \"4,keydown,\", \"Keydown ESCAPE (close submenu)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\t\tsetTimeout( function() {\n\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\t\t\tsetTimeout( function() {\n\t\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\t\t\tequal( $(\"#log\").html(), \"0,4,2,0,1,0,6,5,keydown,\", \"Keydown skip dividers and items without anchors\");\n\n\t\t\t\tlog(\"keydown\",true);\n\t\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\t\t\t\tsetTimeout( menukeyboard6, 50 );\n\t\t\t}, 50 );\n\t\t}, 50 );\n\t}\n\n\tfunction menukeyboard6() {\n\t\tequal( $(\"#log\").html(), \"Ada,keydown,\", \"Keydown ENTER (open submenu)\");\n\n\t\tstart();\n\t}\n});\n\ntest(\"handle keyboard navigation on menu with scroll and without submenus\", function() {\n\texpect(14);\n\tvar element = $('#menu3').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog($(ui.item[0]).text());\n\t\t},\n\t\tfocus: function( event, ui ) {\n\t\t\tlog($(event.target).find(\".ui-state-focus\").parent().index());\n\t\t}\n\t});\n\n\tlog(\"keydown\",true);\n\telement.focus();\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\tequal( $(\"#log\").html(), \"2,1,0,keydown,\", \"Keydown DOWN\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\tequal( $(\"#log\").html(), \"0,1,keydown,\", \"Keydown UP\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown LEFT (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown RIGHT (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\tequal( $(\"#log\").html(), \"10,keydown,\", \"Keydown PAGE_DOWN\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\tequal( $(\"#log\").html(), \"20,keydown,\", \"Keydown PAGE_DOWN\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\tequal( $(\"#log\").html(), \"10,keydown,\", \"Keydown PAGE_UP\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown PAGE_UP\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown PAGE_UP (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.END } );\n\tequal( $(\"#log\").html(), \"37,keydown,\", \"Keydown END\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown PAGE_DOWN (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.HOME } );\n\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown HOME\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ESCAPE } );\n\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown ESCAPE (no effect)\");\n\n\tlog(\"keydown\",true);\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\tequal( $(\"#log\").html(), \"Aberdeen,keydown,\", \"Keydown ENTER\");\n});\n\nasyncTest(\"handle keyboard navigation on menu with scroll and with submenus\", function() {\n\texpect(14);\n\tvar element = $('#menu4').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog($(ui.item[0]).text());\n\t\t},\n\t\tfocus: function( event, ui ) {\n\t\t\tlog($(event.target).find(\".ui-state-focus\").parent().index());\n\t\t}\n\t});\n\n\tlog(\"keydown\",true);\n\telement.one( \"menufocus\", function( event, ui ) {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\tequal( $(\"#log\").html(), \"2,1,keydown,\", \"Keydown DOWN\");\n\t\tsetTimeout( menukeyboard1, 50 );\n\t});\n\telement.focus();\n\n\n\tfunction menukeyboard1() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t\tequal( $(\"#log\").html(), \"0,1,keydown,\", \"Keydown UP\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown LEFT (no effect)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\n\t\tsetTimeout( function() {\n\t\t\tequal( $(\"#log\").html(), \"0,1,keydown,\", \"Keydown RIGHT (open submenu)\");\n\t\t}, 50);\n\t\tsetTimeout( menukeyboard2, 50 );\n\t}\n\n\tfunction menukeyboard2() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\t\tequal( $(\"#log\").html(), \"1,keydown,\", \"Keydown LEFT (close submenu)\");\n\n\t\t//re-open submenu\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\t\tsetTimeout( menukeyboard3, 50 );\n\t}\n\n\tfunction menukeyboard3() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\t\tequal( $(\"#log\").html(), \"10,keydown,\", \"Keydown PAGE_DOWN\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\t\tequal( $(\"#log\").html(), \"20,keydown,\", \"Keydown PAGE_DOWN\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\t\tequal( $(\"#log\").html(), \"10,keydown,\", \"Keydown PAGE_UP\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\t\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown PAGE_UP\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.END } );\n\t\tequal( $(\"#log\").html(), \"27,keydown,\", \"Keydown END\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.HOME } );\n\t\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown HOME\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ESCAPE } );\n\t\tequal( $(\"#log\").html(), \"1,keydown,\", \"Keydown ESCAPE (close submenu)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\t\tsetTimeout( menukeyboard4, 50 );\n\t}\n\n\tfunction menukeyboard4() {\n\t\tequal( $(\"#log\").html(), \"0,keydown,\", \"Keydown ENTER (open submenu)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\t\tequal( $(\"#log\").html(), \"Aberdeen,keydown,\", \"Keydown ENTER (select item)\");\n\n\t\tstart();\n\t}\n});\n\nasyncTest(\"handle keyboard navigation and mouse click on menu with disabled items\", function() {\n\texpect(6);\n\tvar element = $('#menu6').menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog($(ui.item[0]).text());\n\t\t},\n\t\tfocus: function( event, ui ) {\n\t\t\tlog($(event.target).find(\".ui-state-focus\").parent().index());\n\t\t}\n\t});\n\n\tlog(\"keydown\",true);\n\telement.one( \"menufocus\", function( event, ui ) {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\t\tequal( $(\"#log\").html(), \"1,keydown,\", \"Keydown focus but not select disabled item\");\n\t\tsetTimeout( menukeyboard1, 50 );\n\t});\n\telement.focus();\n\n\n\tfunction menukeyboard1() {\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.DOWN } );\n\t\tequal( $(\"#log\").html(), \"4,3,2,keydown,\", \"Keydown focus disabled item with submenu\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } );\n\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown LEFT (no effect)\");\n\n\t\tlog(\"keydown\",true);\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.RIGHT } );\n\n\t\tsetTimeout( function() {\n\t\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown RIGHT (no effect on disabled sub-menu)\");\n\n\t\t\tlog(\"keydown\",true);\n\t\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.ENTER } );\n\n\t\t\tsetTimeout( function() {\n\t\t\t\tequal( $(\"#log\").html(), \"keydown,\", \"Keydown ENTER (no effect on disabled sub-menu)\");\n\t\t\t\tlog(\"click\",true);\n\t\t\t\tclick( element, \"1\" );\n\t\t\t\tequal( $(\"#log\").html(), \"click,\", \"Click disabled item (no effect)\");\n\t\t\t\tstart();\n\t\t\t}, 50);\n\t\t}, 50);\n\t}\n});\n\ntest(\"handle keyboard navigation with spelling of menu items\", function() {\n\texpect( 2 );\n\tvar element = $( \"#menu2\" ).menu({\n\t\tfocus: function( event, ui ) {\n\t\t\tlog( $( event.target ).find( \".ui-state-focus\" ).parent().index() );\n\t\t}\n\t});\n\n\tlog( \"keydown\", true );\n\telement.one( \"menufocus\", function( event, ui ) {\n\t\telement.simulate( \"keydown\", { keyCode: 65 } );\n\t\telement.simulate( \"keydown\", { keyCode: 68 } );\n\t\telement.simulate( \"keydown\", { keyCode: 68 } );\n\t\tequal( $(\"#log\").html(), \"3,1,0,keydown,\", \"Keydown focus Addyston by spelling the first 3 letters\");\n\t\telement.simulate( \"keydown\", { keyCode: 68 } );\n\t\tequal( $(\"#log\").html(), \"4,3,1,0,keydown,\", \"Keydown focus Delphi by repeating the 'd' again\");\n\t});\n\telement.focus();\n});\n\nasyncTest(\"handle page up and page down before the menu has focus\", function() {\n\texpect( 1 );\n\tvar element = $( \"#menu1\" ).menu({\n\t\tfocus: function( event, ui ) {\n\t\t\tlog( $( event.target ).find( \".ui-state-focus\" ).parent().index() );\n\t\t}\n\t});\n\n\tlog( \"keydown\", true );\n\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN } );\n\telement.blur();\n\tsetTimeout( function() {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.PAGE_UP } );\n\t\tequal( $(\"#log\").html(), \"0,0,keydown,\", \"Page Up and Page Down bring initial focus to first item\");\n\t\tstart();\n\t}, 500);\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu_methods.js",
    "content": "/*\n * menu_methods.js\n */\n(function($) {\n\nvar log = TestHelpers.menu.log,\n\tclick = TestHelpers.menu.click;\n\nmodule(\"menu: methods\");\n\ntest( \"enable/disable\", function() {\n\texpect( 3 );\n\tvar menu = $( \"#menu1\" ).menu({\n\t\tselect: function(event, ui) {\n\t\t\tlog();\n\t\t}\n\t});\n\tmenu.menu(\"disable\");\n\tok(menu.is(\".ui-state-disabled\"),\"Missing ui-state-disabled class\");\n\tlog(\"click\",true);\n\tclick(menu,\"1\");\n\tlog(\"afterclick\");\n\tmenu.menu(\"enable\");\n\tok(menu.not(\".ui-state-disabled\"),\"Has ui-state-disabled class\");\n\tlog(\"click\");\n\tclick(menu,\"1\");\n\tlog(\"afterclick\");\n\tequal( $(\"#log\").html(), \"afterclick,1,click,afterclick,click,\", \"Click order not valid.\");\n});\n\ntest( \"refresh\", function() {\n\texpect( 5 );\n\tvar menu = $( \"#menu1\" ).menu();\n\tequal(menu.find(\".ui-menu-item\").length,5,\"Incorrect number of menu items\");\n\tmenu.append(\"<li><a href='#'>test item</a></li>\").menu(\"refresh\");\n\tequal(menu.find(\".ui-menu-item\").length,6,\"Incorrect number of menu items\");\n\tmenu.find(\".ui-menu-item:last\").remove().end().menu(\"refresh\");\n\tequal(menu.find(\".ui-menu-item\").length,5,\"Incorrect number of menu items\");\n\tmenu.append(\"<li>---</li>\").menu(\"refresh\");\n\tequal(menu.find(\".ui-menu-item\").length,5,\"Incorrect number of menu items\");\n\tmenu.children(\":last\").remove().end().menu(\"refresh\");\n\tequal(menu.find(\".ui-menu-item\").length,5,\"Incorrect number of menu items\");\n});\n\ntest(\"destroy\", function() {\n\tdomEqual(\"#menu1\", function() {\n\t\t$(\"#menu1\").menu().menu(\"destroy\");\n\t});\n\tdomEqual(\"#menu2\", function() {\n\t\t$(\"#menu2\").menu().menu(\"destroy\");\n\t});\n\tdomEqual(\"#menu5\", function() {\n\t\t$(\"#menu5\").menu().menu(\"destroy\");\n\t});\n\tdomEqual(\"#menu6\", function() {\n\t\t$(\"#menu6\").menu().menu(\"destroy\");\n\t});\n});\n\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu_options.js",
    "content": "/*\n * menu_options.js\n */\n(function($) {\n\nvar log = TestHelpers.menu.log,\n\tclick = TestHelpers.menu.click;\n\nmodule(\"menu: options\");\n\ntest( \"{ disabled: true }\", function() {\n\texpect( 2 );\n\tvar menu = $( \"#menu1\" ).menu({\n\t\tdisabled: true,\n\t\tselect: function(event, ui) {\n\t\t\tlog();\n\t\t}\n\t});\n\tok(menu.is(\".ui-state-disabled\"),\"Missing ui-state-disabled class\");\n\tlog(\"click\",true);\n\tclick(menu,\"1\");\n\tlog(\"afterclick\");\n\tequal( $(\"#log\").html(), \"afterclick,click,\", \"Click order not valid.\");\n});\n\ntest( \"{ disabled: false }\", function() {\n\texpect( 2 );\n\tvar menu = $( \"#menu1\" ).menu({\n\t\tdisabled: false,\n\t\tselect: function(event, ui) {\n\t\t\tlog();\n\t\t}\n\t});\n\tok(menu.not(\".ui-state-disabled\"),\"Has ui-state-disabled class\");\n\tlog(\"click\",true);\n\tclick(menu,\"1\");\n\tlog(\"afterclick\");\n\tequal( $(\"#log\").html(), \"afterclick,1,click,\", \"Click order not valid.\");\n});\n\ntest(\"{ role: 'menu' } \", function () {\n\tvar menu = $('#menu1').menu();\n\texpect(2 + 5 * $(\"li\", menu).length);\n\tequal( menu.attr( \"role\" ), \"menu\" );\n\tok( $(\"li\", menu).length > 0, \"number of menu items\");\n\t$(\"li\", menu).each(function(item) {\n\t\tok( $(this).hasClass(\"ui-menu-item\"), \"menu item (\"+ item + \") class for item\");\n\t\tequal( $(this).attr(\"role\"), \"presentation\", \"menu item (\"+ item + \") role\");\n\t\tequal( $(\"a\", this).attr(\"role\"), \"menuitem\", \"menu item (\"+ item + \") role\");\n\t\tok( $(\"a\",this).hasClass(\"ui-corner-all\"), \"a element class for menu item (\"+ item + \") \");\n\t\tequal( $(\"a\",this).attr(\"tabindex\"), \"-1\", \"a element tabindex for menu item (\"+ item + \") \");\n\t});\n});\n\ntest(\"{ role: 'listbox' } \", function () {\n\tvar menu = $('#menu1').menu({\n\t\trole: \"listbox\"\n\t});\n\texpect(2 + $(\"li\", menu).length);\n\tequal( menu.attr( \"role\" ), \"listbox\" );\n\tok( ($(\"li\", menu).length > 0 ), \"number of menu items\");\n\t$(\"li\", menu).each(function(item) {\n\t\tequal( $(\"a\", this).attr(\"role\"), \"option\", \"menu item (\"+ item + \") role\");\n\t});\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/menu/menu_test_helpers.js",
    "content": "TestHelpers.menu = {\n\tlog: function( message, clear ) {\n\t\tif ( clear ) {\n\t\t\t$( \"#log\" ).empty();\n\t\t}\n\t\tif ( message === undefined ) {\n\t\t\tmessage = $( \"#log\" ).data( \"lastItem\" );\n\t\t}\n\t\t$( \"#log\" ).prepend( $.trim( message ) + \",\" );\n\t},\n\n\tclick: function( menu, item ) {\n\t\t$( \"#log\" ).data( \"lastItem\", item );\n\t\tmenu.children( \":eq(\" + item + \")\" ).find( \"a:first\" ).trigger( \"click\" );\n\t}\n};"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/position/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Position Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"position\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Position Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/position/position.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Position Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script>\n\t$.uiBackCompat = false;\n\t</script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tjs: [ \"ui/jquery.ui.position.js\" ]\n\t});\n\t</script>\n\n\t<script src=\"position_core.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n<div id=\"qunit\" style=\"position:relative; z-index:2;\"></div>\n\n<!--\nelements smaller than 20px have a line-height set on them to avoid a bug in IE6\n.height() returns the greater of the height and line-height\n-->\n\n<div id=\"qunit-fixture\" style=\"top: 0; left: 0; z-index:1\">\n\t<div id=\"el1\" style=\"position: absolute; width: 6px; height: 6px; line-height: 6px;\"></div>\n\t<div id=\"el2\" style=\"position: absolute; width: 6px; height: 6px; line-height: 6px;\"></div>\n\t<div id=\"parent\" style=\"position: absolute; width: 6px; height: 6px; top: 4px; left: 4px; line-height: 6px;\"></div>\n\t<div id=\"within\" style=\"position: absolute; width: 12px; height: 12px; top: 2px; left: 0px; line-height: 12px;\"></div>\n\n\t<div id=\"scrollx\" style=\"position: absolute; top: 0px; left: 0px\">\n\t\t<div id=\"elx\" style=\"position: absolute; width: 10px; height: 10px; line-height: 10px;\"></div>\n\t\t<div id=\"parentx\" style=\"position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;\"></div>\n\t</div>\n\n\t<div style=\"position: absolute; height: 5000px; width: 5000px;\"></div>\n\n\t<div id=\"fractions-parent\" style=\"position: absolute; left: 10.7432222px; top: 10.532325px; height: 30px; width: 201px;\">\n\t\t<div id=\"fractions-element\"></div>\n\t</div>\n\n\t<div id=\"bug-5280\" style=\"height: 30px; width: 201px;\">\n\t\t<div style=\"width: 50px; height: 10px;\"></div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/position/position_core.js",
    "content": "(function( $ ) {\n\nvar win = $( window ),\n\tscrollTopSupport = function() {\n\t\tvar support = win.scrollTop( 1 ).scrollTop() === 1;\n\t\twin.scrollTop( 0 );\n\t\tscrollTopSupport = function() {\n\t\t\treturn support;\n\t\t};\n\t\treturn support;\n\t};\n\nmodule( \"position\", {\n\tsetup: function() {\n\t\twin.scrollTop( 0 ).scrollLeft( 0 );\n\t}\n});\n\nTestHelpers.testJshint( \"ui.position\" );\n\ntest( \"my, at, of\", function() {\n\texpect( 4 );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left top\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 40, left: 40 }, \"left top, left top\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left bottom\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 60, left: 40 }, \"left top, left bottom\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left\",\n\t\tat: \"bottom\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 55, left: 50 }, \"left, bottom\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left foo\",\n\t\tat: \"bar baz\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 45, left: 50 }, \"left foo, bar baz\" );\n});\n\ntest( \"multiple elements\", function() {\n\texpect( 3 );\n\n\tvar elements = $( \"#el1, #el2\" ),\n\t\tresult = elements.position({\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tof: \"#parent\",\n\t\t\tcollision: \"none\"\n\t\t}),\n\t\texpected = { top: 10, left: 4 };\n\n\tdeepEqual( result, elements );\n\telements.each(function() {\n\t\tdeepEqual( $( this ).offset(), expected );\n\t});\n});\n\ntest( \"positions\", function() {\n\texpect( 18 );\n\n\tvar offsets = {\n\t\t\tleft: 0,\n\t\t\tcenter: 3,\n\t\t\tright: 6,\n\t\t\ttop: 0,\n\t\t\tbottom: 6\n\t\t},\n\t\tstart = { left: 4, top: 4 },\n\t\tel = $( \"#el1\" );\n\n\t$.each( [ 0, 1 ], function( my ) {\n\t\t$.each( [ \"top\", \"center\", \"bottom\" ], function( vindex, vertical ) {\n\t\t\t$.each( [ \"left\", \"center\", \"right\" ], function( hindex, horizontal ) {\n\t\t\t\tvar _my = my ? horizontal + \" \" + vertical : \"left top\",\n\t\t\t\t\t_at = !my ? horizontal + \" \" + vertical : \"left top\";\n\t\t\t\tel.position({\n\t\t\t\t\tmy: _my,\n\t\t\t\t\tat: _at,\n\t\t\t\t\tof: \"#parent\",\n\t\t\t\t\tcollision: \"none\"\n\t\t\t\t});\n\t\t\t\tdeepEqual( el.offset(), {\n\t\t\t\t\ttop: start.top + offsets[ vertical ] * (my ? -1 : 1),\n\t\t\t\t\tleft: start.left + offsets[ horizontal ] * (my ? -1 : 1)\n\t\t\t\t}, \"Position via \" + QUnit.jsDump.parse({ my: _my, at: _at }) );\n\t\t\t});\n\t\t});\n\t});\n});\n\ntest( \"of\", function() {\n\texpect( 9 + (scrollTopSupport() ? 1 : 0) );\n\n\tvar event;\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left top\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 40, left: 40 }, \"selector\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left bottom\",\n\t\tof: $( \"#parentx\"),\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 60, left: 40 }, \"jQuery object\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left top\",\n\t\tof: $( \"#parentx\" )[ 0 ],\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 40, left: 40 }, \"DOM element\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"right bottom\",\n\t\tat: \"right bottom\",\n\t\tof: document,\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\ttop: $( document ).height() - 10,\n\t\tleft: $( document ).width() - 10\n\t}, \"document\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"right bottom\",\n\t\tat: \"right bottom\",\n\t\tof: $( document ),\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\ttop: $( document ).height() - 10,\n\t\tleft: $( document ).width() - 10\n\t}, \"document as jQuery object\" );\n\n\twin.scrollTop( 0 );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"right bottom\",\n\t\tat: \"right bottom\",\n\t\tof: window,\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\ttop: win.height() - 10,\n\t\tleft: win.width() - 10\n\t}, \"window\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"right bottom\",\n\t\tat: \"right bottom\",\n\t\tof: win,\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\ttop: win.height() - 10,\n\t\tleft: win.width() - 10\n\t}, \"window as jQuery object\" );\n\n\tif ( scrollTopSupport() ) {\n\t\twin.scrollTop( 500 ).scrollLeft( 200 );\n\t\t$( \"#elx\" ).position({\n\t\t\tmy: \"right bottom\",\n\t\t\tat: \"right bottom\",\n\t\t\tof: window,\n\t\t\tcollision: \"none\"\n\t\t});\n\t\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\t\ttop: win.height() + 500 - 10,\n\t\t\tleft: win.width() + 200 - 10\n\t\t}, \"window, scrolled\" );\n\t\twin.scrollTop( 0 ).scrollLeft( 0 );\n\t}\n\n\tevent = $.extend( $.Event( \"someEvent\" ), { pageX: 200, pageY: 300 } );\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left top\",\n\t\tof: event,\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\ttop: 300,\n\t\tleft: 200\n\t}, \"event - left top, left top\" );\n\n\tevent = $.extend( $.Event( \"someEvent\" ), { pageX: 400, pageY: 600 } );\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"right bottom\",\n\t\tof: event,\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), {\n\t\ttop: 600,\n\t\tleft: 400\n\t}, \"event - left top, right bottom\" );\n});\n\ntest( \"offsets\", function() {\n\texpect( 4 );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left+10 bottom+10\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 70, left: 50 }, \"offsets in at\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left+10 top-10\",\n\t\tat: \"left bottom\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 50, left: 50 }, \"offsets in my\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left+50% bottom-10%\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 58, left: 50 }, \"percentage offsets in at\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left-30% top+50%\",\n\t\tat: \"left bottom\",\n\t\tof: \"#parentx\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 65, left: 37 }, \"percentage offsets in my\" );\n});\n\ntest( \"using\", function() {\n\texpect( 10 );\n\n\tvar count = 0,\n\t\telems = $( \"#el1, #el2\" ),\n\t\tof = $( \"#parentx\" ),\n\t\texpectedPosition = { top: 60, left: 60 },\n\t\texpectedFeedback = {\n\t\t\ttarget: {\n\t\t\t\telement: of,\n\t\t\t\twidth: 20,\n\t\t\t\theight: 20,\n\t\t\t\tleft: 40,\n\t\t\t\ttop: 40\n\t\t\t},\n\t\t\telement: {\n\t\t\t\twidth: 6,\n\t\t\t\theight: 6,\n\t\t\t\tleft: 60,\n\t\t\t\ttop: 60\n\t\t\t},\n\t\t\thorizontal: \"left\",\n\t\t\tvertical: \"top\",\n\t\t\timportant: \"vertical\"\n\t\t},\n\t\toriginalPosition = elems.position({\n\t\t\tmy: \"right bottom\",\n\t\t\tat: \"rigt bottom\",\n\t\t\tof: \"#parentx\",\n\t\t\tcollision: \"none\"\n\t\t}).offset();\n\n\telems.position({\n\t\tmy: \"left top\",\n\t\tat: \"center+10 bottom\",\n\t\tof: \"#parentx\",\n\t\tusing: function( position, feedback ) {\n\t\t\tdeepEqual( this, elems[ count ], \"correct context for call #\" + count );\n\t\t\tdeepEqual( position, expectedPosition, \"correct position for call #\" + count );\n\t\t\tdeepEqual( feedback.element.element[ 0 ], elems[ count ] );\n\t\t\tdelete feedback.element.element;\n\t\t\tdeepEqual( feedback, expectedFeedback );\n\t\t\tcount++;\n\t\t}\n\t});\n\n\telems.each(function() {\n\t\tdeepEqual( $( this ).offset(), originalPosition, \"elements not moved\" );\n\t});\n});\n\nfunction collisionTest( config, result, msg ) {\n\tvar elem = $( \"#elx\" ).position( $.extend({\n\t\tmy: \"left top\",\n\t\tat: \"right bottom\",\n\t\tof: \"#parent\"\n\t}, config ) );\n\tdeepEqual( elem.offset(), result, msg );\n}\n\nfunction collisionTest2( config, result, msg ) {\n\tcollisionTest( $.extend({\n\t\tmy: \"right bottom\",\n\t\tat: \"left top\"\n\t}, config ), result, msg );\n}\n\ntest( \"collision: fit, no collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest({\n\t\tcollision: \"fit\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"no offset\" );\n\n\tcollisionTest({\n\t\tcollision: \"fit\",\n\t\tat: \"right+2 bottom+3\"\n\t}, {\n\t\ttop: 13,\n\t\tleft: 12\n\t}, \"with offset\" );\n});\n\ntest( \"collision: fit, collision\", function() {\n\texpect( 2 + (scrollTopSupport() ? 1 : 0) );\n\n\tcollisionTest2({\n\t\tcollision: \"fit\"\n\t}, {\n\t\ttop: 0,\n\t\tleft: 0\n\t}, \"no offset\" );\n\n\tcollisionTest2({\n\t\tcollision: \"fit\",\n\t\tat: \"left+2 top+3\"\n\t}, {\n\t\ttop: 0,\n\t\tleft: 0\n\t}, \"with offset\" );\n\n\tif ( scrollTopSupport() ) {\n\t\twin.scrollTop( 300 ).scrollLeft( 200 );\n\t\tcollisionTest({\n\t\t\tcollision: \"fit\"\n\t\t}, {\n\t\t\ttop: 300,\n\t\t\tleft: 200\n\t\t}, \"window scrolled\" );\n\n\t\twin.scrollTop( 0 ).scrollLeft( 0 );\n\t}\n});\n\ntest( \"collision: flip, no collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest({\n\t\tcollision: \"flip\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"no offset\" );\n\n\tcollisionTest({\n\t\tcollision: \"flip\",\n\t\tat: \"right+2 bottom+3\"\n\t}, {\n\t\ttop: 13,\n\t\tleft: 12\n\t}, \"with offset\" );\n});\n\ntest( \"collision: flip, collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest2({\n\t\tcollision: \"flip\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"no offset\" );\n\n\tcollisionTest2({\n\t\tcollision: \"flip\",\n\t\tat: \"left+2 top+3\"\n\t}, {\n\t\ttop: 7,\n\t\tleft: 8\n\t}, \"with offset\" );\n});\n\ntest( \"collision: flipfit, no collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest({\n\t\tcollision: \"flipfit\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"no offset\" );\n\n\tcollisionTest({\n\t\tcollision: \"flipfit\",\n\t\tat: \"right+2 bottom+3\"\n\t}, {\n\t\ttop: 13,\n\t\tleft: 12\n\t}, \"with offset\" );\n});\n\ntest( \"collision: flipfit, collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest2({\n\t\tcollision: \"flipfit\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"no offset\" );\n\n\tcollisionTest2({\n\t\tcollision: \"flipfit\",\n\t\tat: \"left+2 top+3\"\n\t}, {\n\t\ttop: 7,\n\t\tleft: 8\n\t}, \"with offset\" );\n});\n\ntest( \"collision: none, no collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest({\n\t\tcollision: \"none\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"no offset\" );\n\n\tcollisionTest({\n\t\tcollision: \"none\",\n\t\tat: \"right+2 bottom+3\"\n\t}, {\n\t\ttop: 13,\n\t\tleft: 12\n\t}, \"with offset\" );\n});\n\ntest( \"collision: none, collision\", function() {\n\texpect( 2 );\n\n\tcollisionTest2({\n\t\tcollision: \"none\"\n\t}, {\n\t\ttop: -6,\n\t\tleft: -6\n\t}, \"no offset\" );\n\n\tcollisionTest2({\n\t\tcollision: \"none\",\n\t\tat: \"left+2 top+3\"\n\t}, {\n\t\ttop: -3,\n\t\tleft: -4\n\t}, \"with offset\" );\n});\n\ntest( \"collision: fit, with margin\", function() {\n\texpect( 2 );\n\n\t$( \"#elx\" ).css({\n\t\tmarginTop: 6,\n\t\tmarginLeft: 4\n\t});\n\n\tcollisionTest({\n\t\tcollision: \"fit\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"right bottom\" );\n\n\tcollisionTest2({\n\t\tcollision: \"fit\"\n\t}, {\n\t\ttop: 6,\n\t\tleft: 4\n\t}, \"left top\" );\n});\n\ntest( \"collision: flip, with margin\", function() {\n\texpect( 3 );\n\n\t$( \"#elx\" ).css({\n\t\tmarginTop: 6,\n\t\tmarginLeft: 4\n\t});\n\n\tcollisionTest({\n\t\tcollision: \"flip\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"left top\" );\n\n\tcollisionTest2({\n\t\tcollision: \"flip\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: 10\n\t}, \"right bottom\" );\n\n\tcollisionTest2({\n\t\tcollision: \"flip\",\n\t\tmy: \"left top\"\n\t}, {\n\t\ttop: 0,\n\t\tleft: 4\n\t}, \"right bottom\" );\n});\n\ntest( \"within\", function() {\n\texpect( 6 );\n\n\tcollisionTest({\n\t\twithin: \"#within\",\n\t\tcollision: \"fit\"\n\t}, {\n\t\ttop: 4,\n\t\tleft: 2\n\t}, \"fit - right bottom\" );\n\n\tcollisionTest2({\n\t\twithin: \"#within\",\n\t\tcollision: \"fit\"\n\t}, {\n\t\ttop: 2,\n\t\tleft: 0\n\t}, \"fit - left top\" );\n\n\tcollisionTest({\n\t\twithin: \"#within\",\n\t\tcollision: \"flip\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: -6\n\t}, \"flip - right bottom\" );\n\n\tcollisionTest2({\n\t\twithin: \"#within\",\n\t\tcollision: \"flip\"\n\t}, {\n\t\ttop: 10,\n\t\tleft: -6\n\t}, \"flip - left top\" );\n\n\tcollisionTest({\n\t\twithin: \"#within\",\n\t\tcollision: \"flipfit\"\n\t}, {\n\t\ttop: 4,\n\t\tleft: 0\n\t}, \"flipfit - right bottom\" );\n\n\tcollisionTest2({\n\t\twithin: \"#within\",\n\t\tcollision: \"flipfit\"\n\t}, {\n\t\ttop: 4,\n\t\tleft: 0\n\t}, \"flipfit - left top\" );\n});\n\ntest( \"with scrollbars\", function() {\n\texpect( 4 );\n\n\t$( \"#scrollx\" ).css({\n\t\twidth: 100,\n\t\theight: 100,\n\t\tleft: 0,\n\t\ttop: 0\n\t});\n\n\tcollisionTest({\n\t\tof: \"#scrollx\",\n\t\tcollision: \"fit\",\n\t\twithin: \"#scrollx\"\n\t}, {\n\t\ttop: 90,\n\t\tleft: 90\n\t}, \"visible\" );\n\n\t$( \"#scrollx\" ).css({\n\t\toverflow: \"scroll\"\n\t});\n\n\tvar scrollbarInfo = $.position.getScrollInfo( $.position.getWithinInfo( $( \"#scrollx\" ) ) );\n\n\tcollisionTest({\n\t\tof: \"#scrollx\",\n\t\tcollision: \"fit\",\n\t\twithin: \"#scrollx\"\n\t}, {\n\t\ttop: 90 - scrollbarInfo.height,\n\t\tleft: 90 - scrollbarInfo.width\n\t}, \"scroll\" );\n\n\t$( \"#scrollx\" ).css({\n\t\toverflow: \"auto\"\n\t});\n\n\tcollisionTest({\n\t\tof: \"#scrollx\",\n\t\tcollision: \"fit\",\n\t\twithin: \"#scrollx\"\n\t}, {\n\t\ttop: 90,\n\t\tleft: 90\n\t}, \"auto, no scroll\" );\n\n\t$( \"#scrollx\" ).css({\n\t\toverflow: \"auto\"\n\t}).append( $(\"<div>\").height(300).width(300) );\n\n\tcollisionTest({\n\t\tof: \"#scrollx\",\n\t\tcollision: \"fit\",\n\t\twithin: \"#scrollx\"\n\t}, {\n\t\ttop: 90 - scrollbarInfo.height,\n\t\tleft: 90 - scrollbarInfo.width\n\t}, \"auto, with scroll\" );\n});\n\ntest( \"fractions\", function() {\n\texpect( 1 );\n\n\t$( \"#fractions-element\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left top\",\n\t\tof: \"#fractions-parent\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#fractions-element\" ).offset(), $( \"#fractions-parent\" ).offset(), \"left top, left top\" );\n});\n\ntest( \"bug #5280: consistent results (avoid fractional values)\", function() {\n\texpect( 1 );\n\n\tvar wrapper = $( \"#bug-5280\" ),\n\t\telem = wrapper.children(),\n\t\toffset1 = elem.position({\n\t\t\tmy: \"center\",\n\t\t\tat: \"center\",\n\t\t\tof: wrapper,\n\t\t\tcollision: \"none\"\n\t\t}).offset(),\n\t\toffset2 = elem.position({\n\t\t\tmy: \"center\",\n\t\t\tat: \"center\",\n\t\t\tof: wrapper,\n\t\t\tcollision: \"none\"\n\t\t}).offset();\n\tdeepEqual( offset1, offset2 );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/position/position_deprecated.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Position Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\n\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tjs: [ \"ui/jquery.ui.position.js\" ]\n\t});\n\t</script>\n\n\t<script src=\"position_core.js\"></script>\n\t<script src=\"position_deprecated.js\"></script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n<div id=\"qunit\" style=\"position:relative; z-index:2;\"></div>\n\n<!--\nelements smaller than 20px have a line-height set on them to avoid a bug in IE6\n.height() returns the greater of the height and line-height\n-->\n\n<div id=\"qunit-fixture\" style=\"top: 0; left: 0; z-index:1\">\n\t<div id=\"el1\" style=\"position: absolute; width: 6px; height: 6px; line-height: 6px;\"></div>\n\t<div id=\"el2\" style=\"position: absolute; width: 6px; height: 6px; line-height: 6px;\"></div>\n\t<div id=\"parent\" style=\"position: absolute; width: 6px; height: 6px; top: 4px; left: 4px; line-height: 6px;\"></div>\n\t<div id=\"within\" style=\"position: absolute; width: 12px; height: 12px; top: 2px; left: 0px; line-height: 12px;\"></div>\n\n\t<div id=\"scrollx\" style=\"position: absolute; top: 0px; left: 0px\">\n\t\t<div id=\"elx\" style=\"position: absolute; width: 10px; height: 10px; line-height: 10px;\"></div>\n\t\t<div id=\"parentx\" style=\"position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;\"></div>\n\t</div>\n\n\t<div style=\"position: absolute; height: 5000px; width: 5000px;\"></div>\n\n\t<div id=\"fractions-parent\" style=\"position: absolute; left: 10.7432222px; top: 10.532325px; height: 30px; width: 201px;\">\n\t\t<div id=\"fractions-element\"></div>\n\t</div>\n\n\t<div id=\"bug-5280\" style=\"height: 30px; width: 201px;\">\n\t\t<div style=\"width: 50px; height: 10px;\"></div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/position/position_deprecated.js",
    "content": "(function( $ ) {\n\ntest( \"offset\", function() {\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left bottom\",\n\t\tof: \"#parentx\",\n\t\toffset: \"10\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 70, left: 50 }, \"single value\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left bottom\",\n\t\tof: \"#parentx\",\n\t\toffset: \"5 -3\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 57, left: 45 }, \"two values\" );\n\n\t$( \"#elx\" ).position({\n\t\tmy: \"left top\",\n\t\tat: \"left bottom\",\n\t\tof: \"#parentx\",\n\t\toffset: \"5px -3px\",\n\t\tcollision: \"none\"\n\t});\n\tdeepEqual( $( \"#elx\" ).offset(), { top: 57, left: 45 }, \"with units\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Progressbar Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"progressbar\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Progressbar Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/progressbar.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Progressbar Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.progressbar\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.progressbar.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"progressbar_common.js\"></script>\n\t<script src=\"progressbar_core.js\"></script>\n\t<script src=\"progressbar_events.js\"></script>\n\t<script src=\"progressbar_methods.js\"></script>\n\t<script src=\"progressbar_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Progressbar Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"progressbar\"></div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/progressbar_common.js",
    "content": "TestHelpers.commonWidgetTests( \"progressbar\", {\n\tdefaults: {\n\t\tdisabled: false,\n\t\tvalue: 0,\n\t\tmax: 100,\n\n\t\t//callbacks\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/progressbar_core.js",
    "content": "module( \"progressbar: core\" );\n\ntest( \"accessibility\", function() {\n\texpect( 7 );\n\tvar element = $( \"#progressbar\" ).progressbar();\n\n\tequal( element.attr( \"role\" ), \"progressbar\", \"aria role\" );\n\tequal( element.attr( \"aria-valuemin\" ), 0, \"aria-valuemin\" );\n\tequal( element.attr( \"aria-valuemax\" ), 100, \"aria-valuemax\" );\n\tequal( element.attr( \"aria-valuenow\" ), 0, \"aria-valuenow initially\" );\n\n\telement.progressbar( \"value\", 77 );\n\tequal( element.attr( \"aria-valuenow\" ), 77, \"aria-valuenow\" );\n\n\telement.progressbar( \"disable\" );\n\tequal( element.attr( \"aria-disabled\" ), \"true\", \"aria-disabled on\" );\n\n\telement.progressbar( \"enable\" );\n\tequal( element.attr( \"aria-disabled\" ), \"false\", \"aria-disabled off\" );\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/progressbar_events.js",
    "content": "module( \"progressbar: events\" );\n\ntest( \"create\", function() {\n\texpect( 1 );\n\t$( \"#progressbar\" ).progressbar({\n\t\tvalue: 5,\n\t\tcreate: function() {\n\t\t\tdeepEqual( 5, $( this ).progressbar( \"value\" ) );\n\t\t},\n\t\tchange: function() {\n\t\t\tok( false, \"create() has triggered change()\" );\n\t\t}\n\t});\n});\n\ntest( \"change\", function() {\n\texpect( 1 );\n\t$( \"#progressbar\" ).progressbar({\n\t\tchange: function() {\n\t\t\tdeepEqual( 5, $( this ).progressbar( \"value\" ) );\n\t\t}\n\t}).progressbar( \"value\", 5 );\n});\n\ntest( \"complete\", function() {\n\texpect( 3 );\n\tvar value,\n\t\tchanges = 0,\n\t\telement = $( \"#progressbar\" ).progressbar({\n\t\t\tchange: function() {\n\t\t\t\tchanges++;\n\t\t\t\tdeepEqual( element.progressbar( \"value\" ), value, \"change at \" + value );\n\t\t\t},\n\t\t\tcomplete: function() {\n\t\t\t\tequal( changes, 2, \"complete triggered after change\" );\n\t\t\t}\n\t\t});\n\n\tvalue = 5;\n\telement.progressbar( \"value\", value );\n\tvalue = 100;\n\telement.progressbar( \"value\", value );\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/progressbar_methods.js",
    "content": "module( \"progressbar: methods\" );\n\ntest( \"destroy\", function() {\n\texpect( 1 );\n\tdomEqual( \"#progressbar\", function() {\n\t\t$( \"#progressbar\" ).progressbar().progressbar( \"destroy\" );\n\t});\n});\n\ntest( \"value\", function() {\n\texpect( 3 );\n\n\tvar element = $( \"<div>\" ).progressbar({ value: 20 });\n\tequal( element.progressbar( \"value\" ), 20, \"correct value as getter\" );\n\tequal( element.progressbar( \"value\", 30), element, \"chainable as setter\" );\n\tequal( element.progressbar( \"option\", \"value\" ), 30, \"correct value after setter\" );\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/progressbar/progressbar_options.js",
    "content": "module( \"progressbar: options\" );\n\ntest( \"{ value : 0 }, default\", function() {\n\t$( \"#progressbar\" ).progressbar();\n\tequal( 0, $( \"#progressbar\" ).progressbar( \"value\" ) );\n});\n\n// Ticket #7231 - valueDiv should be hidden when value is at 0%\ntest( \"value: visibility of valueDiv\", function() {\n\texpect( 5 );\n\tvar element = $( \"#progressbar\" ).progressbar({\n\t\tvalue: 0\n\t});\n\tok( element.children( \".ui-progressbar-value\" ).is( \":hidden\" ),\n\t\t\"valueDiv hidden when value is initialized at 0\" );\n\telement.progressbar( \"value\", 1 );\n\tok( element.children( \".ui-progressbar-value\" ).is( \":visible\" ),\n\t\t\"valueDiv visible when value is set to 1\" );\n\telement.progressbar( \"value\", 100 );\n\tok( element.children( \".ui-progressbar-value\" ).is( \":visible\" ),\n\t\t\"valueDiv visible when value is set to 100\" );\n\telement.progressbar( \"value\", 0 );\n\tok( element.children( \".ui-progressbar-value\" ).is( \":hidden\" ),\n\t\t\"valueDiv hidden when value is set to 0\" );\n\telement.progressbar( \"value\", -1 );\n\tok( element.children( \".ui-progressbar-value\" ).is( \":hidden\" ),\n\t\t\"valueDiv hidden when value set to -1 (normalizes to 0)\" );\n});\n\ntest( \"{ value : 5 }\", function() {\n\t$( \"#progressbar\" ).progressbar({\n\t\tvalue: 5\n\t});\n\tequal( 5, $( \"#progressbar\" ).progressbar( \"value\" ) );\n});\n\ntest( \"{ value : -5 }\", function() {\n\t$( \"#progressbar\" ).progressbar({\n\t\tvalue: -5\n\t});\n\tdeepEqual( 0, $( \"#progressbar\" ).progressbar( \"value\" ) );\n});\n\ntest( \"{ value : 105 }\", function() {\n\t$( \"#progressbar\" ).progressbar({\n\t\tvalue: 105\n\t});\n\tdeepEqual( 100, $( \"#progressbar\" ).progressbar( \"value\" ) );\n});\n\ntest( \"{ max : 5, value : 10 }\", function() {\n\t$(\"#progressbar\").progressbar({\n\t\tmax: 5,\n\t\tvalue: 10\n\t});\n\tdeepEqual( 5, $( \"#progressbar\" ).progressbar( \"value\" ) );\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/qunit-composite.css",
    "content": "iframe.qunit-subsuite{\n    position: fixed;\n    bottom: 0;\n    left: 0;\n    \n    margin: 0;\n    padding: 0;\n    border-width: 1px 0 0;\n    height: 45%;\n    width: 100%;\n\n    background: #fff;\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/qunit-composite.js",
    "content": "(function( QUnit ) {\n\nQUnit.extend( QUnit, {\n\ttestSuites: function( suites ) {\n\t\tQUnit.begin(function() {\n\t\t\tQUnit.initIframe();\n\t\t});\n\n\t\tfor ( var i = 0; i < suites.length; i++ ) {\n\t\t\tQUnit.runSuite( suites[i] );\n\t\t}\n\n\t\tQUnit.done(function() {\n\t\t\tthis.iframe.style.display = \"none\";\n\t\t});\n\t},\n\n\trunSuite: function( suite ) {\n\t\tasyncTest( suite, function() {\n\t\t\tQUnit.iframe.setAttribute( \"src\", suite );\n\t\t});\n\t},\n\n\tinitIframe: function() {\n\t\tvar body = document.body,\n\t\t\tiframe = this.iframe = document.createElement( \"iframe\" ),\n\t\t\tiframeWin;\n\n\t\tiframe.className = \"qunit-subsuite\";\n\t\tbody.appendChild( iframe );\n\n\t\tfunction onIframeLoad() {\n\t\t\tvar module, test,\n\t\t\t\tcount = 0;\n\n\n\t\t\tiframeWin.QUnit.moduleStart(function( data ) {\n\t\t\t\t// capture module name for messages\n\t\t\t\tmodule = data.name;\n\t\t\t});\n\n\t\t\tiframeWin.QUnit.testStart(function( data ) {\n\t\t\t\t// capture test name for messages\n\t\t\t\ttest = data.name;\n\t\t\t});\n\t\t\tiframeWin.QUnit.testDone(function() {\n\t\t\t\ttest = null;\n\t\t\t});\n\n\t\t\tiframeWin.QUnit.log(function( data ) {\n\t\t\t\tif (test === null) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// pass all test details through to the main page\n\t\t\t\tvar message = module + \": \" + test + \": \" + data.message;\n\t\t\t\texpect( ++count );\n\t\t\t\tQUnit.push( data.result, data.actual, data.expected, message );\n\t\t\t});\n\n\t\t\tiframeWin.QUnit.done(function() {\n\t\t\t\t// start the wrapper test from the main page\n\t\t\t\tstart();\n\t\t\t});\n\t\t}\n\t\tQUnit.addEvent( iframe, \"load\", onIframeLoad );\n\n\t\tiframeWin = iframe.contentWindow;\n\t}\n});\n\nQUnit.testStart(function( data ) {\n\t// update the test status to show which test suite is running\n\tQUnit.id( \"qunit-testresult\" ).innerHTML = \"Running \" + data.name + \"...<br>&nbsp;\";\n});\n\nQUnit.testDone(function() {\n\tvar i,\n\t\tcurrent = QUnit.id( this.config.current.id ),\n\t\tchildren = current.children,\n\t\tsrc = this.iframe.src;\n\n\t// undo the auto-expansion of failed tests\n\tfor ( i = 0; i < children.length; i++ ) {\n\t\tif ( children[i].nodeName === \"OL\" ) {\n\t\t\tchildren[i].style.display = \"none\";\n\t\t}\n\t}\n\n\tQUnit.addEvent(current, \"dblclick\", function( e ) {\n\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\tif ( target.nodeName.toLowerCase() === \"span\" || target.nodeName.toLowerCase() === \"b\" ) {\n\t\t\ttarget = target.parentNode;\n\t\t}\n\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\twindow.location = src;\n\t\t}\n\t});\n\n\tcurrent.getElementsByTagName('a')[0].href = src;\n});\n\n}( QUnit ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"resizable\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Resizable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/resizable.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Resizable Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.resizable\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.resizable.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"resizable_common.js\"></script>\n\t<script src=\"resizable_core.js\"></script>\n\t<script src=\"resizable_events.js\"></script>\n\t<script src=\"resizable_methods.js\"></script>\n\t<script src=\"resizable_options.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"resizable\", function() { ok(true, \"disabled resizable testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Resizable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"resizable1\" style=\"background: green; width: 100px; height: 100px;\">I'm a resizable.</div>\n<img src=\"images/test.jpg\" id=\"resizable2\" style=\"width: 100px; height: 100px;\" alt=\"solid gray\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/resizable_common.js",
    "content": "TestHelpers.commonWidgetTests('resizable', {\n\tdefaults: {\n\t\talsoResize: false,\n\t\tanimate: false,\n\t\tanimateDuration: 'slow',\n\t\tanimateEasing: 'swing',\n\t\taspectRatio: false,\n\t\tautoHide: false,\n\t\tcancel: 'input,textarea,button,select,option',\n\t\tcontainment: false,\n\t\tdelay: 0,\n\t\tdisabled: false,\n\t\tdistance: 1,\n\t\tghost: false,\n\t\tgrid: false,\n\t\thandles: 'e,s,se',\n\t\thelper: false,\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 10,\n\t\tminWidth: 10,\n\t\tzIndex: 1000,\n\n\t\t// callbacks\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/resizable_core.js",
    "content": "/*\n * resizable_core.js\n */\n\nvar el;\n\nvar drag = function(el, dx, dy, complete) {\n\n\t// speed = sync -> Drag syncrhonously.\n\t// speed = fast|slow -> Drag asyncrhonously - animated.\n\n\t//this mouseover is to work around a limitation in resizable\n\t//TODO: fix resizable so handle doesn't require mouseover in order to be used\n\t$(el).simulate(\"mouseover\");\n\n\treturn $(el).simulate(\"drag\", {\n\t\tdx: dx||0, dy: dy||0, speed: 'sync', complete: complete\n\t});\n};\n\n(function($) {\n\nmodule(\"resizable: core\");\n\n/*\ntest(\"element types\", function() {\n\tvar typeNames = ('p,h1,h2,h3,h4,h5,h6,blockquote,ol,ul,dl,div,form'\n\t\t+ ',table,fieldset,address,ins,del,em,strong,q,cite,dfn,abbr'\n\t\t+ ',acronym,code,samp,kbd,var,img,object,hr'\n\t\t+ ',input,button,label,select,iframe').split(',');\n\n\t$.each(typeNames, function(i) {\n\t\tvar typeName = typeNames[i];\n\t\tel = $(document.createElement(typeName)).appendTo('body');\n\t\t(typeName == 'table' && el.append(\"<tr><td>content</td></tr>\"));\n\t\tel.resizable();\n\t\tok(true, '$(\"&lt;' + typeName + '/&gt\").resizable()');\n\t\tel.resizable(\"destroy\");\n\t\tel.remove();\n\t});\n});\n*/\n\ntest(\"n\", function() {\n\texpect(2);\n\n\tvar handle = '.ui-resizable-n', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, 0, -50);\n\tequal( target.height(), 150, \"compare height\" );\n\n\tdrag(handle, 0, 50);\n\tequal( target.height(), 100, \"compare height\" );\n});\n\ntest(\"s\", function() {\n\texpect(2);\n\n\tvar handle = '.ui-resizable-s', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, 0, 50);\n\tequal( target.height(), 150, \"compare height\" );\n\n\tdrag(handle, 0, -50);\n\tequal( target.height(), 100, \"compare height\" );\n});\n\ntest(\"e\", function() {\n\texpect(2);\n\n\tvar handle = '.ui-resizable-e', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, 50);\n\tequal( target.width(), 150, \"compare width\");\n\n\tdrag(handle, -50);\n\tequal( target.width(), 100, \"compare width\" );\n});\n\ntest(\"w\", function() {\n\texpect(2);\n\n\tvar handle = '.ui-resizable-w', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, -50);\n\tequal( target.width(), 150, \"compare width\" );\n\n\tdrag(handle, 50);\n\tequal( target.width(), 100, \"compare width\" );\n});\n\ntest(\"ne\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-ne', target = $('#resizable1').css({ overflow: 'hidden' }).resizable({ handles: 'all' });\n\n\tdrag(handle, -50, -50);\n\tequal( target.width(), 50, \"compare width\" );\n\tequal( target.height(), 150, \"compare height\" );\n\n\tdrag(handle, 50, 50);\n\tequal( target.width(), 100, \"compare width\" );\n\tequal( target.height(), 100, \"compare height\" );\n});\n\ntest(\"se\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-se', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, 50, 50);\n\tequal( target.width(), 150, \"compare width\" );\n\tequal( target.height(), 150, \"compare height\" );\n\n\tdrag(handle, -50, -50);\n\tequal( target.width(), 100, \"compare width\" );\n\tequal( target.height(), 100, \"compare height\" );\n});\n\ntest(\"sw\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-sw', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, -50, -50);\n\tequal( target.width(), 150, \"compare width\" );\n\tequal( target.height(), 50, \"compare height\" );\n\n\tdrag(handle, 50, 50);\n\tequal( target.width(), 100, \"compare width\" );\n\tequal( target.height(), 100, \"compare height\" );\n});\n\ntest(\"nw\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-nw', target = $('#resizable1').resizable({ handles: 'all' });\n\n\tdrag(handle, -50, -50);\n\tequal( target.width(), 150, \"compare width\" );\n\tequal( target.height(), 150, \"compare height\" );\n\n\tdrag(handle, 50, 50);\n\tequal( target.width(), 100, \"compare width\" );\n\tequal( target.height(), 100, \"compare height\" );\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/resizable_events.js",
    "content": "/*\n * resizable_events.js\n */\n(function($) {\n\nmodule(\"resizable: events\");\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/resizable_methods.js",
    "content": "/*\n * resizable_methods.js\n */\n(function($) {\n\nmodule(\"resizable: methods\");\n\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/resizable/resizable_options.js",
    "content": "/*\n * resizable_options.js\n */\n(function($) {\n\nmodule(\"resizable: options\");\n\ntest(\"aspectRatio: 'preserve' (e)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-e', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, 80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, -130);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"aspectRatio: 'preserve' (w)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-w', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, -80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, 130);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"aspectRatio: 'preserve' (n)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-n', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, 0, -80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, 0, 80);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"aspectRatio: 'preserve' (s)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-s', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, 0, 80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, 0, -80);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"aspectRatio: 'preserve' (se)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-se', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, 80, 80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, -80, -80);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"aspectRatio: 'preserve' (sw)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-sw', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, -80, 80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, 80, -80);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"aspectRatio: 'preserve' (ne)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-ne', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 });\n\n\tdrag(handle, 80, -80);\n\tequal( target.width(), 130, \"compare maxWidth\");\n\tequal( target.height(), 130, \"compare maxHeight\");\n\n\tdrag(handle, -80, 80);\n\tequal( target.width(), 70, \"compare minWidth\");\n\tequal( target.height(), 70, \"compare minHeight\");\n});\n\ntest(\"grid\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-se', target = $('#resizable1').resizable({ handles: 'all', grid: [0, 20] });\n\n\tdrag(handle, 3, 9);\n\tequal( target.width(), 103, \"compare width\");\n\tequal( target.height(), 100, \"compare height\");\n\n\tdrag(handle, 15, 11);\n\tequal( target.width(), 118, \"compare width\");\n\tequal( target.height(), 120, \"compare height\");\n});\n\ntest(\"grid (wrapped)\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-se', target = $('#resizable2').resizable({ handles: 'all', grid: [0, 20] });\n\n\tdrag(handle, 3, 9);\n\tequal( target.width(), 103, \"compare width\");\n\tequal( target.height(), 100, \"compare height\");\n\n\tdrag(handle, 15, 11);\n\tequal( target.width(), 118, \"compare width\");\n\tequal( target.height(), 120, \"compare height\");\n});\n\ntest(\"ui-resizable-se { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-se', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 });\n\n\tdrag(handle, -50, -50);\n\tequal( target.width(), 60, \"compare minWidth\" );\n\tequal( target.height(), 60, \"compare minHeight\" );\n\n\tdrag(handle, 70, 70);\n\tequal( target.width(), 100, \"compare maxWidth\" );\n\tequal( target.height(), 100, \"compare maxHeight\" );\n});\n\ntest(\"ui-resizable-sw { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-sw', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 });\n\n\tdrag(handle, 50, -50);\n\tequal( target.width(), 60, \"compare minWidth\" );\n\tequal( target.height(), 60, \"compare minHeight\" );\n\n\tdrag(handle, -70, 70);\n\tequal( target.width(), 100, \"compare maxWidth\" );\n\tequal( target.height(), 100, \"compare maxHeight\" );\n});\n\ntest(\"ui-resizable-ne { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-ne', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 });\n\n\tdrag(handle, -50, 50);\n\tequal( target.width(), 60, \"compare minWidth\" );\n\tequal( target.height(), 60, \"compare minHeight\" );\n\n\tdrag(handle, 70, -70);\n\tequal( target.width(), 100, \"compare maxWidth\" );\n\tequal( target.height(), 100, \"compare maxHeight\" );\n});\n\ntest(\"ui-resizable-nw { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }\", function() {\n\texpect(4);\n\n\tvar handle = '.ui-resizable-nw', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 });\n\n\tdrag(handle, 70, 70);\n\tequal( target.width(), 60, \"compare minWidth\" );\n\tequal( target.height(), 60, \"compare minHeight\" );\n\n\tdrag(handle, -70, -70);\n\tequal( target.width(), 100, \"compare maxWidth\" );\n\tequal( target.height(), 100, \"compare maxHeight\" );\n});\n\ntest(\"zIndex, applied to all handles\", function() {\n\texpect(8);\n\n\tvar target = $('<div></div>').resizable({ handles: 'all', zIndex: 100 });\n\ttarget.children( '.ui-resizable-handle' ).each( function( index, handle ) {\n\t\tequal( $( handle ).css( 'zIndex' ), 100, 'compare zIndex' );\n\t});\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Selectable Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"selectable\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Selectable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/selectable.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Selectable Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.selectable\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.selectable.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"selectable_common.js\"></script>\n\t<script src=\"selectable_core.js\"></script>\n\t<script src=\"selectable_events.js\"></script>\n\t<script src=\"selectable_methods.js\"></script>\n\t<script src=\"selectable_options.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"selectable\", function() { ok(true, \"disabled selectable testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Selectable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<ul id=\"selectable1\">\n\t<li>Item 1</li>\n\t<li>Item 2</li>\n\t<li class=\"special\">Item 3</li>\n\t<li>Item 4</li>\n\t<li>Item 5</li>\n</ul>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/selectable_common.js",
    "content": "TestHelpers.commonWidgetTests('selectable', {\n\tdefaults: {\n\t\tappendTo: 'body',\n\t\tautoRefresh: true,\n\t\tcancel: 'input,textarea,button,select,option',\n\t\tdelay: 0,\n\t\tdisabled: false,\n\t\tdistance: 0,\n\t\tfilter: '*',\n\t\ttolerance: 'touch'\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/selectable_core.js",
    "content": "/*\n * selectable_core.js\n */\n\nvar el;\n\nvar drag = function(dx, dy) {\n\tvar off = el.offset(), pos = { clientX: off.left, clientY: off.top };\n\tel.simulate(\"mousedown\", pos);\n\t$(document).simulate(\"mousemove\", pos);\n\tpos.clientX += dx;\n\tpos.clientY += dy;\n\t$(document).simulate(\"mousemove\", pos);\n\t$(document).simulate(\"mouseup\", pos);\n};\n\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/selectable_events.js",
    "content": "/*\n * selectable_events.js\n */\n(function($) {\n\nmodule(\"selectable: events\");\n\ntest(\"start\", function() {\n\texpect(2);\n\tel = $(\"#selectable1\");\n\tel.selectable({\n\t\tstart: function(ev, ui) {\n\t\t\tok(true, \"drag fired start callback\");\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t}\n\t});\n\tel.simulate(\"drag\", 20, 20);\n});\n\ntest(\"stop\", function() {\n\texpect(2);\n\tel = $(\"#selectable1\");\n\tel.selectable({\n\t\tstart: function(ev, ui) {\n\t\t\tok(true, \"drag fired stop callback\");\n\t\t\tequal(this, el[0], \"context of callback\");\n\t\t}\n\t});\n\tel.simulate(\"drag\", 20, 20);\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/selectable_methods.js",
    "content": "/*\n * selectable_methods.js\n */\n(function($) {\n\nmodule(\"selectable: methods\");\n\ntest(\"init\", function() {\n\texpect(6);\n\n\t$(\"<div></div>\").appendTo('body').selectable().remove();\n\tok(true, '.selectable() called on element');\n\n\t$([]).selectable().remove();\n\tok(true, '.selectable() called on empty collection');\n\n\t$(\"<div></div>\").selectable().remove();\n\tok(true, '.selectable() called on disconnected DOMElement');\n\n\t$(\"<div></div>\").selectable().selectable(\"foo\").remove();\n\tok(true, 'arbitrary method called after init');\n\n\tel = $(\"<div></div>\").selectable();\n\tvar foo = el.selectable(\"option\", \"foo\");\n\tel.remove();\n\tok(true, 'arbitrary option getter after init');\n\n\t$(\"<div></div>\").selectable().selectable(\"option\", \"foo\", \"bar\").remove();\n\tok(true, 'arbitrary option setter after init');\n});\n\ntest(\"destroy\", function() {\n\t$(\"<div></div>\").appendTo('body').selectable().selectable(\"destroy\").remove();\n\tok(true, '.selectable(\"destroy\") called on element');\n\n\t$([]).selectable().selectable(\"destroy\").remove();\n\tok(true, '.selectable(\"destroy\") called on empty collection');\n\n\t$(\"<div></div>\").selectable().selectable(\"destroy\").remove();\n\tok(true, '.selectable(\"destroy\") called on disconnected DOMElement');\n\n\t$(\"<div></div>\").selectable().selectable(\"destroy\").selectable(\"foo\").remove();\n\tok(true, 'arbitrary method called after destroy');\n\n\tvar expected = $('<div></div>').selectable(),\n\t\tactual = expected.selectable('destroy');\n\tequal(actual, expected, 'destroy is chainable');\n});\n\ntest(\"enable\", function() {\n\texpect(3);\n\tvar expected, actual,\n\t\tfired = false;\n\n\tel = $(\"#selectable1\");\n\tel.selectable({\n\t\tdisabled: true,\n\t\tstart: function() { fired = true; }\n\t});\n\tel.simulate(\"drag\", 20, 20);\n\tequal(fired, false, \"start fired\");\n\tel.selectable(\"enable\");\n\tel.simulate(\"drag\", 20, 20);\n\tequal(fired, true, \"start fired\");\n\tel.selectable(\"destroy\");\n\n\texpected = $('<div></div>').selectable();\n\tactual = expected.selectable('enable');\n\tequal(actual, expected, 'enable is chainable');\n});\n\ntest(\"disable\", function() {\n\texpect(3);\n\tvar expected, actual,\n\t\tfired = false;\n\n\tel = $(\"#selectable1\");\n\tel.selectable({\n\t\tdisabled: false,\n\t\tstart: function() { fired = true; }\n\t});\n\tel.simulate(\"drag\", 20, 20);\n\tequal(fired, true, \"start fired\");\n\tel.selectable(\"disable\");\n\tfired = false;\n\tel.simulate(\"drag\", 20, 20);\n\tequal(fired, false, \"start fired\");\n\tel.selectable(\"destroy\");\n\n\texpected = $('<div></div>').selectable();\n\tactual = expected.selectable('disable');\n\tequal(actual, expected, 'disable is chainable');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/selectable/selectable_options.js",
    "content": "/*\n * selectable_options.js\n */\n(function($) {\n\nmodule(\"selectable: options\");\n\ntest(\"autoRefresh\", function() {\n\texpect(3);\n\tel = $(\"#selectable1\");\n\tvar actual, sel = $(\"*\", el), selected = function() { actual += 1; };\n\n\tactual = 0;\n\tel = $(\"#selectable1\").selectable({ autoRefresh: false,\tselected: selected });\n\tsel.hide();\n\tdrag(1000, 1000);\n\tequal(actual, sel.length);\n\tel.selectable(\"destroy\");\n\n\tactual = 0;\n\tsel.show();\n\tel = $(\"#selectable1\").selectable({ autoRefresh: true,\tselected: selected });\n\tsel.hide();\n\tdrag(1000, 1000);\n\tequal(actual, 0);\n\tsel.show();\n\tdrag(1000, 1000);\n\tequal(actual, sel.length);\n\tel.selectable(\"destroy\");\n\tsel.show();\n});\n\ntest(\"filter\", function() {\n\texpect(2);\n\tel = $(\"#selectable1\");\n\tvar actual, sel = $(\"*\", el), selected = function() { actual += 1; };\n\n\tactual = 0;\n\tel = $(\"#selectable1\").selectable({ filter: '.special', selected: selected });\n\tdrag(1000, 1000);\n\tok(sel.length !== 1, \"this test assumes more than 1 selectee\");\n\tequal(actual, 1);\n\tel.selectable(\"destroy\");\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"slider\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Slider Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/slider.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Slider Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.slider\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.slider.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"slider_common.js\"></script>\n\t<script src=\"slider_core.js\"></script>\n\t<script src=\"slider_events.js\"></script>\n\t<script src=\"slider_methods.js\"></script>\n\t<script src=\"slider_options.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"slider\", function() { ok(true, \"disabled slider testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Slider Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"slider1\"></div>\n<div id=\"slider3\" style=\"position: relative; margin: 40px; width: 217px; height: 28px;\">\n\t<div class=\"ui-slider-handle\" style=\"position: absolute; height: 21px; left: 0px; bottom: 0px; width: 17px;\"></div>\n</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/slider_common.js",
    "content": "TestHelpers.commonWidgetTests( \"slider\", {\n\tdefaults: {\n\t\tanimate: false,\n\t\tcancel: 'input,textarea,button,select,option',\n\t\tdelay: 0,\n\t\tdisabled: false,\n\t\tdistance: 0,\n\t\tmax: 100,\n\t\tmin: 0,\n\t\torientation: 'horizontal',\n\t\trange: false,\n\t\tstep: 1,\n\t\tvalue: 0,\n\t\tvalues: null,\n\n\t\t// callbacks\n\t\tcreate: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/slider_core.js",
    "content": "/*\n * slider unit tests\n */\n(function($) {\n//\n// Slider Test Helper Functions\n//\n\nvar el, options;\n\nfunction handle() {\n\treturn el.find(\".ui-slider-handle\");\n}\n\n// Slider Tests\nmodule(\"slider: core\");\n\ntest(\"keydown HOME on handle sets value to min\", function() {\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'horizontal',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", 0);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.HOME });\n\tequal(el.slider(\"value\"), options.min);\n\n\tel.slider('destroy');\n\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'vertical',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", 0);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.HOME });\n\tequal(el.slider(\"value\"), options.min);\n\n\tel.slider('destroy');\n});\n\ntest(\"keydown END on handle sets value to max\", function() {\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'horizontal',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", 0);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.END });\n\tequal(el.slider(\"value\"), options.max);\n\n\tel.slider('destroy');\n\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'vertical',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", 0);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.END });\n\tequal(el.slider(\"value\"), options.max);\n\n\tel.slider('destroy');\n});\n\ntest(\"keydown PAGE_UP on handle increases value by 1/5 range, not greater than max\", function() {\n\t$.each(['horizontal', 'vertical'], function(i, orientation) {\n\t\tel = $('<div></div>');\n\t\toptions = {\n\t\t\tmax: 100,\n\t\t\tmin: 0,\n\t\t\torientation: orientation,\n\t\t\tstep: 1\n\t\t};\n\t\tel.slider(options);\n\n\t\tel.slider(\"value\", 70);\n\n\t\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.PAGE_UP });\n\t\tequal(el.slider(\"value\"), 90);\n\n\t\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.PAGE_UP });\n\t\tequal(el.slider(\"value\"), 100);\n\n\t\tel.slider(\"destroy\");\n\t});\n});\n\ntest(\"keydown PAGE_DOWN on handle decreases value by 1/5 range, not less than min\", function() {\n\t$.each(['horizontal', 'vertical'], function(i, orientation) {\n\t\tel = $('<div></div>');\n\t\toptions = {\n\t\t\tmax: 100,\n\t\t\tmin: 0,\n\t\t\torientation: orientation,\n\t\t\tstep: 1\n\t\t};\n\t\tel.slider(options);\n\n\t\tel.slider(\"value\", 30);\n\n\t\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN });\n\t\tequal(el.slider(\"value\"), 10);\n\n\t\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.PAGE_DOWN });\n\t\tequal(el.slider(\"value\"), 0);\n\n\t\tel.slider(\"destroy\");\n\t});\n});\n\ntest(\"keydown UP on handle increases value by step, not greater than max\", function() {\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'horizontal',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.max - options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.UP });\n\tequal(el.slider(\"value\"), options.max);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.UP });\n\tequal(el.slider(\"value\"), options.max);\n\n\tel.slider(\"destroy\");\n\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'vertical',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.max - options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.UP });\n\tequal(el.slider(\"value\"), options.max);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.UP });\n\tequal(el.slider(\"value\"), options.max);\n\n\tel.slider(\"destroy\");\n});\n\ntest(\"keydown RIGHT on handle increases value by step, not greater than max\", function() {\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'horizontal',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.max - options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.RIGHT });\n\tequal(el.slider(\"value\"), options.max);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.RIGHT });\n\tequal(el.slider(\"value\"), options.max);\n\n\tel.slider(\"destroy\");\n\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'vertical',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.max - options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.RIGHT });\n\tequal(el.slider(\"value\"), options.max);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.RIGHT });\n\tequal(el.slider(\"value\"), options.max);\n\n\tel.slider(\"destroy\");\n});\n\ntest(\"keydown DOWN on handle decreases value by step, not less than min\", function() {\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'horizontal',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.min + options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.DOWN });\n\tequal(el.slider(\"value\"), options.min);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.DOWN });\n\tequal(el.slider(\"value\"), options.min);\n\n\tel.slider(\"destroy\");\n\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'vertical',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.min + options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.DOWN });\n\tequal(el.slider(\"value\"), options.min);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.DOWN });\n\tequal(el.slider(\"value\"), options.min);\n\n\tel.slider(\"destroy\");\n});\n\ntest(\"keydown LEFT on handle decreases value by step, not less than min\", function() {\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'horizontal',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.min + options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.LEFT });\n\tequal(el.slider(\"value\"), options.min);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.LEFT });\n\tequal(el.slider(\"value\"), options.min);\n\n\tel.slider(\"destroy\");\n\n\tel = $('<div></div>');\n\toptions = {\n\t\tmax: 5,\n\t\tmin: -5,\n\t\torientation: 'vertical',\n\t\tstep: 1\n\t};\n\tel.slider(options);\n\n\tel.slider(\"value\", options.min + options.step);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.LEFT });\n\tequal(el.slider(\"value\"), options.min);\n\n\thandle().simulate(\"keydown\", { keyCode: $.ui.keyCode.LEFT });\n\tequal(el.slider(\"value\"), options.min);\n\n\tel.slider(\"destroy\");\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/slider_events.js",
    "content": "/*\n * slider_events.js\n */\n(function($) {\n\nmodule( \"slider: events\" );\n\n//Specs from http://wiki.jqueryui.com/Slider#specs\n//\"change callback: triggers when the slider has stopped moving and has a new\n// value (even if same as previous value), via mouse(mouseup) or keyboard(keyup)\n// or value method/option\"\ntest( \"mouse based interaction\", function() {\n\texpect(4);\n\n\tvar el = $( \"<div></div>\" )\n\t\t.appendTo( \"body\" )\n\t\t.slider({\n\t\t\tstart: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"mousedown\", \"start triggered by mousedown\" );\n\t\t\t},\n\t\t\tslide: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"mousemove\", \"slider triggered by mousemove\" );\n\t\t\t},\n\t\t\tstop: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"mouseup\", \"stop triggered by mouseup\" );\n\t\t\t},\n\t\t\tchange: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"mouseup\", \"change triggered by mouseup\" );\n\t\t\t}\n\t\t});\n\n\tel.find( \".ui-slider-handle\" ).eq( 0 )\n\t\t.simulate( \"drag\", { dx: 10, dy: 10 } );\n\n});\ntest( \"keyboard based interaction\", function() {\n\texpect(3);\n\n\t// Test keyup at end of handle slide (keyboard)\n\tvar el = $( \"<div></div>\" )\n\t\t.appendTo( \"body\" )\n\t\t.slider({\n\t\t\tstart: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"keydown\", \"start triggered by keydown\" );\n\t\t\t},\n\t\t\tslide: function(event, ui) {\n\t\t\t\tok( false, \"Slider never triggered by keys\" );\n\t\t\t},\n\t\t\tstop: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"keyup\", \"stop triggered by keyup\" );\n\t\t\t},\n\t\t\tchange: function(event, ui) {\n\t\t\t\tequal( event.originalEvent.type, \"keyup\", \"change triggered by keyup\" );\n\t\t\t}\n\t\t});\n\n\tel.find( \".ui-slider-handle\" ).eq( 0 )\n\t\t.simulate( \"keydown\", { keyCode: $.ui.keyCode.LEFT } )\n\t\t.simulate( \"keypress\", { keyCode: $.ui.keyCode.LEFT } )\n\t\t.simulate( \"keyup\", { keyCode: $.ui.keyCode.LEFT } );\n\n});\ntest( \"programmatic event triggers\", function() {\n\texpect(6);\n\n\t// Test value method\n\tvar el = $( \"<div></div>\" )\n\t\t.slider({\n\t\t\tchange: function(event, ui) {\n\t\t\t\tok( true, \"change triggered by value method\" );\n\t\t\t}\n\t\t})\n\t\t.slider( \"value\", 0 );\n\n\tQUnit.reset();\n\t// Test values method\n\tel = $( \"<div></div>\" )\n\t\t.slider({\n\t\t\tvalues: [ 10, 20 ],\n\t\t\tchange: function(event, ui) {\n\t\t\t\tok( true, \"change triggered by values method\" );\n\t\t\t}\n\t\t})\n\t\t.slider( \"values\", [80, 90] );\n\n\tQUnit.reset();\n\t// Test value option\n\tel = $( \"<div></div>\" )\n\t\t.slider({\n\t\t\tchange: function(event, ui) {\n\t\t\t\tok( true, \"change triggered by value option\" );\n\t\t\t}\n\t\t})\n\t\t.slider( \"option\", \"value\", 0 );\n\n\tQUnit.reset();\n\t// Test values option\n\tel = $( \"<div></div>\" )\n\t\t.slider({\n\t\t\tvalues: [ 10, 20 ],\n\t\t\tchange: function(event, ui) {\n\t\t\t\tok( true, \"change triggered by values option\" );\n\t\t\t}\n\t\t})\n\t\t.slider( \"option\", \"values\", [80, 90] );\n\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/slider_methods.js",
    "content": "/*\n * slider_methods.js\n */\n(function($) {\n\nmodule(\"slider: methods\");\n\ntest(\"init\", function() {\n\texpect(5);\n\n\t$(\"<div></div>\").appendTo('body').slider().remove();\n\tok(true, '.slider() called on element');\n\n\t$([]).slider().remove();\n\tok(true, '.slider() called on empty collection');\n\n\t$('<div></div>').slider().remove();\n\tok(true, '.slider() called on disconnected DOMElement');\n\n\tvar el = $('<div></div>').slider(),\n\t\tfoo = el.slider(\"option\", \"foo\");\n\tel.remove();\n\tok(true, 'arbitrary option getter after init');\n\n\t$('<div></div>').slider().slider(\"option\", \"foo\", \"bar\").remove();\n\tok(true, 'arbitrary option setter after init');\n});\n\ntest(\"destroy\", function() {\n\t$(\"<div></div>\").appendTo('body').slider().slider(\"destroy\").remove();\n\tok(true, '.slider(\"destroy\") called on element');\n\n\t$([]).slider().slider(\"destroy\").remove();\n\tok(true, '.slider(\"destroy\") called on empty collection');\n\n\t$('<div></div>').appendTo('body').remove().slider().slider(\"destroy\").remove();\n\tok(true, '.slider(\"destroy\") called on disconnected DOMElement');\n\n\tvar expected = $('<div></div>').slider(),\n\t\tactual = expected.slider('destroy');\n\tequal(actual, expected, 'destroy is chainable');\n});\n\ntest(\"enable\", function() {\n\tvar el,\n\t\texpected = $('<div></div>').slider(),\n\t\tactual = expected.slider('enable');\n\tequal(actual, expected, 'enable is chainable');\n\n\tel = $('<div></div>').slider({ disabled: true });\n\tok(el.hasClass('ui-disabled'), 'slider has ui-disabled class before enable method call');\n\tok(el.hasClass('ui-slider-disabled'), 'slider has ui-slider-disabled class before enable method call');\n\tel.slider('enable');\n\tok(!el.hasClass('ui-disabled'), 'slider does not have ui-disabled class after enable method call');\n\tok(!el.hasClass('ui-slider-disabled'), 'slider does not have ui-slider-disabled class after enable method call');\n});\n\ntest(\"disable\", function() {\n\tvar el,\n\t\texpected = $('<div></div>').slider(),\n\t\tactual = expected.slider('disable');\n\tequal(actual, expected, 'disable is chainable');\n\n\tel = $('<div></div>').slider({ disabled: false });\n\tok(!el.hasClass('ui-disabled'), 'slider does not have ui-disabled class before disabled method call');\n\tok(!el.hasClass('ui-slider-disabled'), 'slider does not have ui-slider-disabled class before disable method call');\n\tel.slider('disable');\n\tok(el.hasClass('ui-disabled'), 'slider has ui-disabled class after disable method call');\n\tok(el.hasClass('ui-slider-disabled'), 'slider has ui-slider-disabled class after disable method call');\n});\n\ntest(\"value\", function() {\n\t$([false, 'min', 'max']).each(function() {\n\t\tvar el = $('<div></div>').slider({\n\t\t\trange: this,\n\t\t\tvalue: 5\n\t\t});\n\t\tequal(el.slider('value'), 5, 'range: ' + this + ' slider method get');\n\t\tequal(el.slider('value', 10), el, 'value method is chainable');\n\t\tequal(el.slider('value'), 10, 'range: ' + this + ' slider method set');\n\t\tel.remove();\n\t});\n\tvar el = $('<div></div>').slider({\n\t\tmin: -1, value: 0, max: 1\n\t});\n\t// min with value option vs value method\n\tel.slider('option', 'value', -2);\n\tequal(el.slider('option', 'value'), -2, 'value option does not respect min');\n\tequal(el.slider('value'), -1, 'value method get respects min');\n\tequal(el.slider('value', -2), el, 'value method is chainable');\n\tequal(el.slider('option', 'value'), -1, 'value method set respects min');\n\t// max with value option vs value method\n\tel.slider('option', 'value', 2);\n\tequal(el.slider('option', 'value'), 2, 'value option does not respect max');\n\tequal(el.slider('value'), 1, 'value method get respects max');\n\tequal(el.slider('value', 2), el, 'value method is chainable');\n\tequal(el.slider('option', 'value'), 1, 'value method set respects max');\n});\n\n//test(\"values\", function() {\n//\tok(false, \"missing test - untested code is broken code.\");\n//});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/slider/slider_options.js",
    "content": "/*\n * slider_options.js\n */\n(function($) {\n\nvar el, options;\n\nfunction handle() {\n\treturn el.find(\".ui-slider-handle\");\n}\n\nmodule(\"slider: options\");\n\ntest(\"max\", function() {\n\tel = $('<div></div>');\n\n\toptions = {\n\t\tmax: 37,\n\t\tmin: 6,\n\t\torientation: 'horizontal',\n\t\tstep: 1,\n\t\tvalue: 50\n\t};\n\n\tel.slider(options);\n\tok(el.slider(\"option\", \"value\") === options.value, \"value option is not contained by max\");\n\tok(el.slider(\"value\") === options.max, \"value method is contained by max\");\n\tel.slider('destroy');\n\n});\n\ntest(\"min\", function() {\n\tel = $('<div></div>');\n\n\toptions = {\n\t\tmax: 37,\n\t\tmin: 6,\n\t\torientation: 'vertical',\n\t\tstep: 1,\n\t\tvalue: 2\n\t};\n\n\tel.slider(options);\n\tok(el.slider(\"option\", \"value\") === options.value, \"value option is not contained by min\");\n\tok(el.slider(\"value\") === options.min, \"value method is contained by min\");\n\tel.slider('destroy');\n\n});\n\ntest(\"orientation\", function() {\n\tel = $('<div></div>');\n\n\toptions = {\n\t\tmax: 2,\n\t\tmin: -2,\n\t\torientation: 'vertical',\n\t\tvalue: 1\n\t};\n\n\tvar percentVal = (options.value - options.min) / (options.max - options.min) * 100;\n\n\tel.slider(options).slider(\"option\", \"orientation\", \"horizontal\");\n\tok(el.is('.ui-slider-horizontal'), \"horizontal slider has class .ui-slider-horizontal\");\n\tok(!el.is('.ui-slider-vertical'), \"horizontal slider does not have class .ui-slider-vertical\");\n\tequal(handle().css('left'), percentVal + '%', \"horizontal slider handle is positioned with left: %\");\n\n\tel.slider('destroy');\n\n\toptions = {\n\t\tmax: 2,\n\t\tmin: -2,\n\t\torientation: 'horizontal',\n\t\tvalue: -1\n\t};\n\n\tpercentVal = (options.value - options.min) / (options.max - options.min) * 100;\n\n\tel.slider(options).slider(\"option\", \"orientation\", \"vertical\");\n\tok(el.is('.ui-slider-vertical'), \"vertical slider has class .ui-slider-vertical\");\n\tok(!el.is('.ui-slider-horizontal'), \"vertical slider does not have class .ui-slider-horizontal\");\n\tequal(handle().css('bottom'), percentVal + '%', \"vertical slider handle is positioned with bottom: %\");\n\n\tel.slider('destroy');\n\n});\n\n//test(\"range\", function() {\n//\tok(false, \"missing test - untested code is broken code.\");\n//});\n\n//spec: http://wiki.jqueryui.com/Slider#specs\n// value option/method: the value option is not restricted by min/max/step.\n// What is returned by the value method is restricted by min (>=), max (<=), and step (even multiple)\ntest(\"step\", function() {\n\tvar el = $('<div></div>').slider({\n\t\tmin: 0,\n\t\tvalue: 0,\n\t\tstep: 10,\n\t\tmax: 100\n\t});\n\tequal( el.slider(\"value\"), 0 );\n\n\tel.slider(\"value\", 1);\n\tequal( el.slider(\"value\"), 0 );\n\n\tel.slider(\"value\", 9);\n\tequal( el.slider(\"value\"), 10 );\n\n\tel.slider(\"value\", 11);\n\tequal( el.slider(\"value\"), 10 );\n\n\tel.slider(\"value\", 19);\n\tequal( el.slider(\"value\"), 20 );\n\nel = $('<div></div>').slider({\n\t\tmin: 0,\n\t\tvalue: 0,\n\t\tstep: 20,\n\t\tmax: 100\n\t});\n\tel.slider(\"value\", 0);\n\n\tel.slider(\"option\", \"value\", 1);\n\tequal( el.slider(\"value\"), 0 );\n\n\tel.slider(\"option\", \"value\", 9);\n\tequal( el.slider(\"value\"), 0 );\n\n\tel.slider(\"option\", \"value\", 11);\n\tequal( el.slider(\"value\"), 20 );\n\n\tel.slider(\"option\", \"value\", 19);\n\tequal( el.slider(\"value\"), 20 );\n\n\tel.slider('destroy');\n});\n\n//test(\"value\", function() {\n//\tok(false, \"missing test - untested code is broken code.\");\n//});\n\n//test(\"values\", function() {\n//\tok(false, \"missing test - untested code is broken code.\");\n//});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"sortable\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Sortable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Sortable Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.sortable\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.mouse.js\",\n\t\t\t\"ui/jquery.ui.sortable.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"sortable_common.js\"></script>\n\t<script src=\"sortable_core.js\"></script>\n\t<script src=\"sortable_events.js\"></script>\n\t<script src=\"sortable_methods.js\"></script>\n\t<script src=\"sortable_options.js\"></script>\n\t<script src=\"sortable_tickets.js\"></script>\n\n\t<script>\n\t// disable this stale testsuite for testswarm only\n\tvar url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( url && url.indexOf(\"http\") == 0 ) {\n\t\t// reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script\n\t\tQUnit.init();\n\t\ttest(\"sortable\", function() { ok(true, \"disabled sortable testsuite\"); });\n\t}\n\t</script>\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Sortable Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<ul id=\"sortable\">\n\t<li>Item 1</li>\n\t<li>Item 2</li>\n\t<li>Item 3</li>\n\t<li>Item 4</li>\n\t<li>Item 5</li>\n</ul>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable_common.js",
    "content": "TestHelpers.commonWidgetTests( \"sortable\", {\n\tdefaults: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tcancel: \"input,textarea,button,select,option\",\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdelay: 0,\n\t\tdisabled: false,\n\t\tdistance: 1,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: \"> *\",\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable_core.js",
    "content": "/*\n * sortable_core.js\n */\n\n(function($) {\n\nmodule(\"sortable: core\");\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable_events.js",
    "content": "/*\n * sortable_events.js\n */\n(function($) {\n\nmodule(\"sortable: events\");\n\ntest(\"start\", function() {\n\n\tvar hash;\n\t$(\"#sortable\")\n\t\t.sortable({ start: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 0, dy: 10 });\n\n\tok(hash, 'start event triggered');\n\tok(hash.helper, 'UI hash includes: helper');\n\tok(hash.placeholder, 'UI hash includes: placeholder');\n\tok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position');\n\tok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset');\n\tok(hash.item, 'UI hash includes: item');\n\tok(!hash.sender, 'UI hash does not include: sender');\n\n\n});\n\ntest(\"sort\", function() {\n\n\tvar hash;\n\t$(\"#sortable\")\n\t\t.sortable({ sort: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 0, dy: 10 });\n\n\tok(hash, 'sort event triggered');\n\tok(hash.helper, 'UI hash includes: helper');\n\tok(hash.placeholder, 'UI hash includes: placeholder');\n\tok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position');\n\tok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset');\n\tok(hash.item, 'UI hash includes: item');\n\tok(!hash.sender, 'UI hash does not include: sender');\n\n});\n\ntest(\"change\", function() {\n\n\tvar hash;\n\t$(\"#sortable\")\n\t\t.sortable({ change: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 1, dy: 1 });\n\n\tok(!hash, '1px drag, change event should not be triggered');\n\n\t$(\"#sortable\")\n\t\t.sortable({ change: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 0, dy: 20 });\n\n\tok(hash, 'change event triggered');\n\tok(hash.helper, 'UI hash includes: helper');\n\tok(hash.placeholder, 'UI hash includes: placeholder');\n\tok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position');\n\tok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset');\n\tok(hash.item, 'UI hash includes: item');\n\tok(!hash.sender, 'UI hash does not include: sender');\n\n});\n\ntest(\"beforeStop\", function() {\n\n\tvar hash;\n\t$(\"#sortable\")\n\t\t.sortable({ beforeStop: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 0, dy: 20 });\n\n\tok(hash, 'beforeStop event triggered');\n\tok(hash.helper, 'UI hash includes: helper');\n\tok(hash.placeholder, 'UI hash includes: placeholder');\n\tok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position');\n\tok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset');\n\tok(hash.item, 'UI hash includes: item');\n\tok(!hash.sender, 'UI hash does not include: sender');\n\n});\n\ntest(\"stop\", function() {\n\n\tvar hash;\n\t$(\"#sortable\")\n\t\t.sortable({ stop: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 0, dy: 20 });\n\n\tok(hash, 'stop event triggered');\n\tok(!hash.helper, 'UI should not include: helper');\n\tok(hash.placeholder, 'UI hash includes: placeholder');\n\tok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position');\n\tok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset');\n\tok(hash.item, 'UI hash includes: item');\n\tok(!hash.sender, 'UI hash does not include: sender');\n\n});\n\ntest(\"update\", function() {\n\n\tvar hash;\n\t$(\"#sortable\")\n\t\t.sortable({ update: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 1, dy: 1 });\n\n\tok(!hash, '1px drag, update event should not be triggered');\n\n\t$(\"#sortable\")\n\t\t.sortable({ update: function(e, ui) { hash = ui; } })\n\t\t.find('li:eq(0)').simulate(\"drag\", { dx: 0, dy: 20 });\n\n\tok(hash, 'update event triggered');\n\tok(!hash.helper, 'UI hash should not include: helper');\n\tok(hash.placeholder, 'UI hash includes: placeholder');\n\tok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position');\n\tok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset');\n\tok(hash.item, 'UI hash includes: item');\n\tok(!hash.sender, 'UI hash does not include: sender');\n\n});\n\ntest(\"receive\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"remove\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"over\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"out\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"activate\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"deactivate\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable_methods.js",
    "content": "/*\n * sortable_methods.js\n */\n(function($) {\n\nvar el, offsetBefore, offsetAfter, dragged;\n\nfunction drag(handle, dx, dy) {\n\toffsetBefore = $(handle).offset();\n\t$(handle).simulate(\"drag\", {\n\t\tdx: dx || 0,\n\t\tdy: dy || 0\n\t});\n\tdragged = { dx: dx, dy: dy };\n\toffsetAfter = $(handle).offset();\n}\n\nfunction sort(handle, dx, dy, index, msg) {\n\tdrag(handle, dx, dy);\n\tequal($(handle).parent().children().index(handle), index, msg);\n}\n\nmodule(\"sortable: methods\");\n\ntest(\"init\", function() {\n\texpect(6);\n\n\t$(\"<div></div>\").appendTo('body').sortable().remove();\n\tok(true, '.sortable() called on element');\n\n\t$([]).sortable();\n\tok(true, '.sortable() called on empty collection');\n\n\t$(\"<div></div>\").sortable();\n\tok(true, '.sortable() called on disconnected DOMElement');\n\n\t$(\"<div></div>\").sortable().sortable(\"foo\");\n\tok(true, 'arbitrary method called after init');\n\n\t$(\"<div></div>\").sortable().sortable(\"option\", \"foo\");\n\tok(true, 'arbitrary option getter after init');\n\n\t$(\"<div></div>\").sortable().sortable(\"option\", \"foo\", \"bar\");\n\tok(true, 'arbitrary option setter after init');\n});\n\ntest(\"destroy\", function() {\n\t$(\"<div></div>\").appendTo('body').sortable().sortable(\"destroy\").remove();\n\tok(true, '.sortable(\"destroy\") called on element');\n\n\t$([]).sortable().sortable(\"destroy\");\n\tok(true, '.sortable(\"destroy\") called on empty collection');\n\n\t$(\"<div></div>\").sortable().sortable(\"destroy\");\n\tok(true, '.sortable(\"destroy\") called on disconnected DOMElement');\n\n\t$(\"<div></div>\").sortable().sortable(\"destroy\").sortable(\"foo\");\n\tok(true, 'arbitrary method called after destroy');\n\n\tvar expected = $('<div></div>').sortable(),\n\t\tactual = expected.sortable('destroy');\n\tequal(actual, expected, 'destroy is chainable');\n});\n\ntest(\"enable\", function() {\n\texpect(5);\n\tel = $(\"#sortable\").sortable({ disabled: true });\n\n\tsort($(\"li\", el)[0], 0, 40, 0, '.sortable({ disabled: true })');\n\n\tel.sortable(\"enable\");\n\tequal(el.sortable(\"option\", \"disabled\"), false, \"disabled option getter\");\n\n\tel.sortable(\"destroy\");\n\tel.sortable({ disabled: true });\n\tel.sortable(\"option\", \"disabled\", false);\n\tequal(el.sortable(\"option\", \"disabled\"), false, \"disabled option setter\");\n\n\tsort($(\"li\", el)[0], 0, 40, 2, '.sortable(\"option\", \"disabled\", false)');\n\n\tvar expected = $('<div></div>').sortable(),\n\t\tactual = expected.sortable('enable');\n\tequal(actual, expected, 'enable is chainable');\n});\n\ntest(\"disable\", function() {\n\texpect(7);\n\tel = $(\"#sortable\").sortable({ disabled: false });\n\tsort($(\"li\", el)[0], 0, 40, 2, '.sortable({ disabled: false })');\n\n\tel.sortable(\"disable\");\n\tsort($(\"li\", el)[0], 0, 40, 0, 'disabled.sortable getter');\n\n\tel.sortable(\"destroy\");\n\n\tel.sortable({ disabled: false });\n\tsort($(\"li\", el)[0], 0, 40, 2, '.sortable({ disabled: false })');\n\tel.sortable(\"option\", \"disabled\", true);\n\tequal(el.sortable(\"option\", \"disabled\"), true, \"disabled option setter\");\n\tok(el.sortable(\"widget\").is(\":not(.ui-state-disabled)\"), \"sortable element does not get ui-state-disabled since it's an interaction\");\n\tsort($(\"li\", el)[0], 0, 40, 0, '.sortable(\"option\", \"disabled\", true)');\n\n\tvar expected = $('<div></div>').sortable(),\n\t\tactual = expected.sortable('disable');\n\tequal(actual, expected, 'disable is chainable');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable_options.js",
    "content": "/*\n * sortable_options.js\n */\n(function($) {\n\nmodule(\"sortable: options\");\n\ntest(\"{ appendTo: 'parent' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ appendTo: Selector }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ axis: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ axis: 'x' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ axis: 'y' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ axis: ? }, unexpected\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ cancel: 'input,textarea,button,select,option' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ cancel: Selector }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ connectWith: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ connectWith: Selector }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ containment: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ containment: Element }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ containment: 'document' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ containment: 'parent' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ containment: 'window' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ containment: Selector }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ cursor: 'auto' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ cursor: 'move' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ cursorAt: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ cursorAt: true }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ delay: 0 }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ delay: 100 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ distance: 1 }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ distance: 10 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ dropOnEmpty: true }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ dropOnEmpty: false }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ forcePlaceholderSize: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ forcePlaceholderSize: true }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ forceHelperSize: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ forceHelperSize: true }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ grid: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ grid: [17, 3] }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ grid: [3, 7] }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ handle: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ handle: Element }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ handle: Selector }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ helper: 'original' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ helper: Function }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ items: '> *' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ items: Selector }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ opacity: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ opacity: .37 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ opacity: 1 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ placeholder: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ placeholder: String }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ revert: false }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ revert: true }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scroll: true }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scroll: false }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scrollSensitivity: 20 }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scrollSensitivity: 2 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scrollSensitivity: 200 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scrollSpeed: 20 }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scrollSpeed: 2 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scrollSpeed: 200 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scope: 'default' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ scope: ??? }, unexpected\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ tolerance: 'intersect' }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ tolerance: 'pointer' }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ zIndex: 1000 }, default\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ zIndex: 1 }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\ntest(\"{ zIndex: false }\", function() {\n\tok(false, \"missing test - untested code is broken code.\");\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/sortable/sortable_tickets.js",
    "content": "/*\n * sortable_tickets.js\n */\n(function($) {\n\nvar el, offsetBefore, offsetAfter, dragged;\n\nfunction drag(handle, dx, dy) {\n\toffsetBefore = $(handle).offset();\n\t$(handle).simulate(\"drag\", {\n\t\tdx: dx || 0,\n\t\tdy: dy || 0\n\t});\n\tdragged = { dx: dx, dy: dy };\n\toffsetAfter = $(handle).offset();\n}\n\nfunction sort(handle, dx, dy, index, msg) {\n\tdrag(handle, dx, dy);\n\tequal($(handle).parent().children().index(handle), index, msg);\n}\n\nmodule(\"sortable: tickets\");\n\ntest(\"#3019: Stop fires too early\", function() {\n\n\tvar helper = null;\n\tel = $(\"#sortable\").sortable({\n\t\tstop: function(event, ui) {\n\t\t\thelper = ui.helper;\n\t\t}\n\t});\n\n\tsort($(\"li\", el)[0], 0, 40, 2, 'Dragging the sortable');\n\tequal(helper, null, \"helper should be false\");\n\n});\n\ntest('#4752: link event firing on sortable with connect list', function () {\n    var fired = {},\n        hasFired = function (type) { return (type in fired) && (true === fired[type]); };\n\n    $('#sortable').clone().attr('id', 'sortable2').insertAfter('#sortable');\n\n    $('#main ul').sortable({\n        connectWith: '#main ul',\n        change: function (e, ui) {\n            fired.change = true;\n        },\n        receive: function (e, ui) {\n            fired.receive = true;\n        },\n        remove: function (e, ui) {\n            fired.remove = true;\n        }\n    });\n\n    $('#main ul li').live('click.ui-sortable-test', function () {\n        fired.click = true;\n    });\n\n    $('#sortable li:eq(0)').simulate('click');\n    ok(!hasFired('change'), 'Click only, change event should not have fired');\n    ok(hasFired('click'), 'Click event should have fired');\n\n    // Drag an item within the first list\n    fired = {};\n    $('#sortable li:eq(0)').simulate('drag', { dx: 0, dy: 40 });\n    ok(hasFired('change'), '40px drag, change event should have fired');\n    ok(!hasFired('receive'), 'Receive event should not have fired');\n    ok(!hasFired('remove'), 'Remove event should not have fired');\n    ok(!hasFired('click'), 'Click event should not have fired');\n\n    // Drag an item from the first list to the second, connected list\n    fired = {};\n    $('#sortable li:eq(0)').simulate('drag', { dx: 0, dy: 150 });\n    ok(hasFired('change'), '150px drag, change event should have fired');\n    ok(hasFired('receive'), 'Receive event should have fired');\n    ok(hasFired('remove'), 'Remove event should have fired');\n    ok(!hasFired('click'), 'Click event should not have fired');\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"spinner\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Spinner Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Spinner Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script src=\"../../../external/jquery.mousewheel-3.0.4.js\"></script>\n\t<script src=\"../../../external/globalize.js\"></script>\n\t<script src=\"../../../external/globalize.culture.ja-JP.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.button\", \"ui.spinner\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.button.js\",\n\t\t\t\"ui/jquery.ui.spinner.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"spinner_test_helpers.js\"></script>\n\t<script src=\"spinner_common.js\"></script>\n\t<script src=\"spinner_core.js\"></script>\n\t<script src=\"spinner_events.js\"></script>\n\t<script src=\"spinner_methods.js\"></script>\n\t<script src=\"spinner_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Spinner Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<input id=\"spin\" class=\"foo\">\n<input id=\"spin2\" value=\"2\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner_common.js",
    "content": "TestHelpers.commonWidgetTests( \"spinner\", {\n\tdefaults: {\n\t\tculture: null,\n\t\tdisabled: false,\n\t\tincremental: true,\n\t\tmax: null,\n\t\tmin: null,\n\t\tnumberFormat: null,\n\t\tpage: 10,\n\t\tstep: 1,\n\n\t\t// callbacks\n\t\tchange: null,\n\t\tcreate: null,\n\t\tspin: null,\n\t\tstart: null,\n\t\tstop: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner_core.js",
    "content": "(function( $ ) {\n\nvar simulateKeyDownUp = TestHelpers.spinner.simulateKeyDownUp;\n\nmodule( \"spinner: core\" );\n\ntest( \"keydown UP on input, increases value not greater than max\", function() {\n\texpect( 5 );\n\tvar element = $( \"#spin\" ).val( 70 ).spinner({\n\t\tmax: 100,\n\t\tstep: 10\n\t});\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( element.val(), 80 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( element.val(), 90 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( element.val(), 100 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( element.val(), 100 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( element.val(), 100 );\n});\n\ntest( \"keydown DOWN on input, decreases value not less than min\", function() {\n\texpect( 5 );\n\tvar element = $( \"#spin\" ).val( 50 ).spinner({\n\t\tmin: 20,\n\t\tstep: 10\n\t});\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tequal( element.val(), 40 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tequal( element.val(), 30 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tequal( element.val(), 20 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tequal( element.val(), 20 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tequal( element.val(), 20 );\n});\n\ntest( \"keydown PAGE_UP on input, increases value not greater than max\", function() {\n\texpect( 5 );\n\tvar element = $( \"#spin\" ).val( 70 ).spinner({\n\t\tmax: 100,\n\t\tpage: 10\n\t});\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tequal( element.val(), 80 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tequal( element.val(), 90 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tequal( element.val(), 100 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tequal( element.val(), 100 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tequal( element.val(), 100 );\n});\n\ntest( \"keydown PAGE_DOWN on input, decreases value not less than min\", function() {\n\texpect( 5 );\n\tvar element = $( \"#spin\" ).val( 50 ).spinner({\n\t\tmin: 20,\n\t\tpage: 10\n\t});\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tequal( element.val(), 40 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tequal( element.val(), 30 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tequal( element.val(), 20 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tequal( element.val(), 20 );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tequal( element.val(), 20 );\n});\n\ntest( \"mouse click on up button, increases value not greater than max\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" ).val( 18 ).spinner({\n\t\t\tmax: 20\n\t\t}),\n\t\tbutton = element.spinner( \"widget\" ).find( \".ui-spinner-up\" );\n\n\tbutton.trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( element.val(), 19 );\n\tbutton.trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( element.val(), 20 );\n\tbutton.trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( element.val(), 20 );\n});\n\ntest( \"mouse click on up button, increases value not greater than max\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" ).val( 2 ).spinner({\n\t\tmin: 0\n\t}),\n\tbutton = element.spinner( \"widget\" ).find( \".ui-spinner-down\" );\n\n\tbutton.trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( element.val(), 1 );\n\tbutton.trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( element.val(), 0 );\n\tbutton.trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( element.val(), 0 );\n});\n\ntest( \"mousewheel on input\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({\n\t\tstep: 2\n\t});\n\n\telement.trigger( \"mousewheel\" );\n\tequal( element.val(), 0, \"mousewheel event without delta does not change value\" );\n\n\telement.trigger( \"mousewheel\", 1 );\n\tequal( element.val(), 2 );\n\n\telement.trigger( \"mousewheel\", -0.2 );\n\tequal( element.val(), 0 );\n\n\telement.trigger( \"mousewheel\", -15 );\n\tequal(element.val(), -2 );\n});\n\ntest( \"reading HTML5 attributes\", function() {\n\texpect( 6 );\n\tvar markup = \"<input type='number' min='-100' max='100' value='5' step='2'>\",\n\t\telement = $( markup ).spinner();\n\tequal( element.spinner( \"option\", \"min\" ), -100, \"min from markup\" );\n\tequal( element.spinner( \"option\", \"max\" ), 100, \"max from markup\" );\n\tequal( element.spinner( \"option\", \"step\" ), 2, \"step from markup\" );\n\n\telement = $( markup ).spinner({\n\t\tmin: -200,\n\t\tmax: 200,\n\t\tstep: 5\n\t});\n\tequal( element.spinner( \"option\", \"min\" ), -200, \"min from options\" );\n\tequal( element.spinner( \"option\", \"max\" ), 200, \"max from options\" );\n\tequal( element.spinner( \"option\", \"step\" ), 5, \"stop from options\" );\n});\n\ntest( \"ARIA attributes\", function() {\n\texpect( 9 );\n\tvar element = $( \"#spin\" ).val( 2 ).spinner({ min: -5, max: 5 });\n\n\tequal( element.attr( \"role\" ), \"spinbutton\", \"role\" );\n\tequal( element.attr( \"aria-valuemin\" ), \"-5\", \"aria-valuemin\" );\n\tequal( element.attr( \"aria-valuemax\" ), \"5\", \"aria-valuemax\" );\n\tequal( element.attr( \"aria-valuenow\" ), \"2\", \"aria-valuenow\" );\n\n\telement.spinner( \"stepUp\" );\n\n\tequal( element.attr( \"aria-valuenow\" ), \"3\", \"stepUp 1 step changes aria-valuenow\" );\n\n\telement.spinner( \"option\", { min: -10, max: 10 } );\n\n\tequal( element.attr( \"aria-valuemin\" ), \"-10\", \"min option changed aria-valuemin changes\" );\n\tequal( element.attr( \"aria-valuemax\" ), \"10\", \"max option changed aria-valuemax changes\" );\n\n\telement.spinner( \"option\", \"min\", null );\n\tequal( element.attr( \"aria-valuemin\" ), undefined, \"aria-valuemin not set when no min\" );\n\n\telement.spinner( \"option\", \"max\", null );\n\tequal( element.attr( \"aria-valuemax\" ), undefined, \"aria-valuemax not set when no max\" );\n});\n\ntest( \"focus text field when pressing button\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).spinner();\n\t$( \"body\" ).focus();\n\tok( element[ 0 ] !== document.activeElement, \"not focused before\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown();\n\tok( element[ 0 ] === document.activeElement, \"focused after\" );\n});\n\ntest( \"don't clear invalid value on blur\", function() {\n\texpect( 1 );\n\tvar element = $( \"#spin\" ).spinner();\n\telement.focus().val( \"a\" ).blur();\n\tequal( element.val(), \"a\" );\n});\n\ntest( \"precision\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 0.05 ).spinner({\n\t\tstep: 0.0001\n\t});\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"0.0501\", \"precision from step\" );\n\n\telement.val( 1.05 ).spinner( \"option\", {\n\t\tstep: 1,\n\t\tmin: -9.95\n\t});\n\telement.spinner( \"stepDown\" );\n\tequal( element.val(), \"0.05\", \"precision from min\" );\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner_events.js",
    "content": "(function( $ ) {\n\nvar simulateKeyDownUp = TestHelpers.spinner.simulateKeyDownUp;\n\nmodule( \"spinner: events\" );\n\ntest( \"start\", function() {\n\texpect( 6 );\n\tvar element = $( \"#spin\" ).spinner();\n\n\tfunction shouldStart( expectation, msg ) {\n\t\telement.spinner( \"option\", \"start\", function() {\n\t\t\tok( expectation, msg );\n\t\t});\n\t}\n\n\tshouldStart( true, \"key UP\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tshouldStart( true, \"key DOWN\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\n\tshouldStart( true, \"key PAGE_UP\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tshouldStart( true, \"key PAGE_DOWN\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\n\tshouldStart( true, \"button up\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown().mouseup();\n\tshouldStart( true, \"button down\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-down\" ).mousedown().mouseup();\n\n\tshouldStart( false, \"stepUp\" );\n\telement.spinner( \"stepUp\" );\n\tshouldStart( false, \"stepDown\" );\n\telement.spinner( \"stepDown\" );\n\n\tshouldStart( false, \"pageUp\" );\n\telement.spinner( \"pageUp\" );\n\tshouldStart( false, \"pageDown\" );\n\telement.spinner( \"pageDown\" );\n\n\tshouldStart( false, \"value\" );\n\telement.spinner( \"value\", 999 );\n});\n\ntest( \"spin\", function() {\n\texpect( 6 );\n\tvar element = $( \"#spin\" ).spinner();\n\n\tfunction shouldSpin( expectation, msg ) {\n\t\telement.spinner( \"option\", \"spin\", function() {\n\t\t\tok( expectation, msg );\n\t\t});\n\t}\n\n\tshouldSpin( true, \"key UP\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tshouldSpin( true, \"key DOWN\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\n\tshouldSpin( true, \"key PAGE_UP\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tshouldSpin( true, \"key PAGE_DOWN\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\n\tshouldSpin( true, \"button up\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown().mouseup();\n\tshouldSpin( true, \"button down\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-down\" ).mousedown().mouseup();\n\n\tshouldSpin( false, \"stepUp\" );\n\telement.spinner( \"stepUp\" );\n\tshouldSpin( false, \"stepDown\" );\n\telement.spinner( \"stepDown\" );\n\n\tshouldSpin( false, \"pageUp\" );\n\telement.spinner( \"pageUp\" );\n\tshouldSpin( false, \"pageDown\" );\n\telement.spinner( \"pageDown\" );\n\n\tshouldSpin( false, \"value\" );\n\telement.spinner( \"value\", 999 );\n});\n\ntest( \"stop\", function() {\n\texpect( 6 );\n\tvar element = $( \"#spin\" ).spinner();\n\n\tfunction shouldStop( expectation, msg ) {\n\t\telement.spinner( \"option\", \"stop\", function() {\n\t\t\tok( expectation, msg );\n\t\t});\n\t}\n\n\tshouldStop( true, \"key UP\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tshouldStop( true, \"key DOWN\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\n\tshouldStop( true, \"key PAGE_UP\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tshouldStop( true, \"key PAGE_DOWN\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\n\tshouldStop( true, \"button up\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown().mouseup();\n\tshouldStop( true, \"button down\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-down\" ).mousedown().mouseup();\n\n\tshouldStop( false, \"stepUp\" );\n\telement.spinner( \"stepUp\" );\n\tshouldStop( false, \"stepDown\" );\n\telement.spinner( \"stepDown\" );\n\n\tshouldStop( false, \"pageUp\" );\n\telement.spinner( \"pageUp\" );\n\tshouldStop( false, \"pageDown\" );\n\telement.spinner( \"pageDown\" );\n\n\tshouldStop( false, \"value\" );\n\telement.spinner( \"value\", 999 );\n});\n\nasyncTest( \"change\", function() {\n\texpect( 14 );\n\tvar element = $( \"#spin\" ).spinner();\n\n\tfunction shouldChange( expectation, msg ) {\n\t\telement.spinner( \"option\", \"change\", function() {\n\t\t\tok( expectation, msg );\n\t\t});\n\t}\n\n\telement.focus();\n\tshouldChange( false, \"key UP, before blur\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tshouldChange( true, \"blur after key UP\" );\n\telement.blur();\n\n\telement.focus();\n\tshouldChange( false, \"key DOWN, before blur\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tshouldChange( true, \"blur after key DOWN\" );\n\telement.blur();\n\n\telement.focus();\n\tshouldChange( false, \"key PAGE_UP, before blur\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tshouldChange( true, \"blur after key PAGE_UP\" );\n\telement.blur();\n\n\telement.focus();\n\tshouldChange( false, \"key PAGE_DOWN, before blur\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tshouldChange( true, \"blur after key PAGE_DOWN\" );\n\telement.blur();\n\n\tshouldChange( false, \"many keys, before blur\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tshouldChange( true, \"blur after many keys\" );\n\telement.blur();\n\n\tshouldChange( false, \"many keys, same final value, before blur\" );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tshouldChange( false, \"blur after many keys, same final value\" );\n\n\tshouldChange( false, \"button up, before blur\" );\n\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown().mouseup();\n\tshouldChange( true, \"blur after button up\" );\n\tsetTimeout(function() {\n\t\telement.blur();\n\n\t\tshouldChange( false, \"button down, before blur\" );\n\t\telement.spinner( \"widget\" ).find( \".ui-spinner-down\" ).mousedown().mouseup();\n\t\tshouldChange( true, \"blur after button down\" );\n\t\tsetTimeout(function() {\n\t\t\telement.blur();\n\n\t\t\tshouldChange( false, \"many buttons, same final value, before blur\" );\n\t\t\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown().mouseup();\n\t\t\telement.spinner( \"widget\" ).find( \".ui-spinner-up\" ).mousedown().mouseup();\n\t\t\telement.spinner( \"widget\" ).find( \".ui-spinner-down\" ).mousedown().mouseup();\n\t\t\telement.spinner( \"widget\" ).find( \".ui-spinner-down\" ).mousedown().mouseup();\n\t\t\tshouldChange( false, \"blur after many buttons, same final value\" );\n\t\t\telement.blur();\n\t\t\tsetTimeout(function() {\n\t\t\t\tshouldChange( true, \"stepUp\" );\n\t\t\t\telement.spinner( \"stepUp\" );\n\n\t\t\t\tshouldChange( true, \"stepDown\" );\n\t\t\t\telement.spinner( \"stepDown\" );\n\n\t\t\t\tshouldChange( true, \"pageUp\" );\n\t\t\t\telement.spinner( \"pageUp\" );\n\n\t\t\t\tshouldChange( true, \"pageDown\" );\n\t\t\t\telement.spinner( \"pageDown\" );\n\n\t\t\t\tshouldChange( true, \"value\" );\n\t\t\t\telement.spinner( \"value\", 999 );\n\n\t\t\t\tshouldChange( false, \"value, same value\" );\n\t\t\t\telement.spinner( \"value\", 999 );\n\n\t\t\t\tshouldChange( true, \"max, value changed\" );\n\t\t\t\telement.spinner( \"option\", \"max\", 900 );\n\n\t\t\t\tshouldChange( false, \"max, value not changed\" );\n\t\t\t\telement.spinner( \"option\", \"max\", 1000 );\n\n\t\t\t\tshouldChange( true, \"min, value changed\" );\n\t\t\t\telement.spinner( \"option\", \"min\", 950 );\n\n\t\t\t\tshouldChange( false, \"min, value not changed\" );\n\t\t\t\telement.spinner( \"option\", \"min\", 200 );\n\t\t\t\tstart();\n\t\t\t});\n\t\t});\n\t});\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner_methods.js",
    "content": "(function( $ ) {\n\nvar simulateKeyDownUp = TestHelpers.spinner.simulateKeyDownUp;\n\nmodule( \"spinner: methods\" );\n\ntest( \"destroy\", function() {\n\texpect( 1 );\n\tdomEqual( \"#spin\", function() {\n\t\t$( \"#spin\" ).spinner().spinner( \"destroy\" );\n\t});\n});\n\ntest( \"disable\", function() {\n\texpect( 14 );\n\tvar element = $( \"#spin\" ).val( 2 ).spinner(),\n\t\twrapper = $( \"#spin\" ).spinner( \"widget\" );\n\n\tok( !wrapper.hasClass( \"ui-spinner-disabled\" ), \"before: wrapper does not have ui-spinner-disabled class\" );\n\tok( !element.is( \":disabled\" ), \"before: input does not have disabled attribute\" );\n\n\telement.spinner( \"disable\" );\n\tok( wrapper.hasClass( \"ui-spinner-disabled\" ), \"after: wrapper has ui-spinner-disabled class\" );\n\tok( element.is( \":disabled\"), \"after: input has disabled attribute\" );\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( 2, element.val(), \"keyboard - value does not change on key UP\" );\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.DOWN );\n\tequal( 2, element.val(), \"keyboard - value does not change on key DOWN\" );\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_UP );\n\tequal( 2, element.val(), \"keyboard - value does not change on key PGUP\" );\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN );\n\tequal( 2, element.val(), \"keyboard - value does not change on key PGDN\" );\n\n\twrapper.find( \".ui-spinner-up\" ).trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( 2, element.val(), \"mouse - value does not change on clicking up button\" );\n\n\twrapper.find( \".ui-spinner-down\" ).trigger( \"mousedown\" ).trigger( \"mouseup\" );\n\tequal( 2, element.val(), \"mouse - value does not change on clicking down button\" );\n\n\telement.spinner( \"stepUp\", 6 );\n\tequal( 8, element.val(), \"script - stepUp 6 steps changes value\");\n\n\telement.spinner( \"stepDown\" );\n\tequal( 7, element.val(), \"script - stepDown 1 step changes value\" );\n\n\telement.spinner( \"pageUp\" );\n\tequal( 17, element.val(), \"script - pageUp 1 page changes value\" );\n\n\telement.spinner( \"pageDown\" );\n\tequal( 7, element.val(), \"script - pageDown 1 page changes value\" );\n});\n\ntest( \"enable\", function() {\n\texpect( 5 );\n\tvar element = $( \"#spin\" ).val( 1 ).spinner({ disabled: true }),\n\t\twrapper = element.spinner( \"widget\" );\n\n\tok( wrapper.hasClass( \"ui-spinner-disabled\" ), \"before: wrapper has ui-spinner-disabled class\" );\n\tok( element.is( \":disabled\" ), \"before: input has disabled attribute\" );\n\n\telement.spinner( \"enable\" );\n\n\tok( !wrapper.hasClass( \".ui-spinner-disabled\" ), \"after: wrapper does not have ui-spinner-disabled class\" );\n\tok( !element.is( \":disabled\" ), \"after: input does not have disabled attribute\" );\n\n\tsimulateKeyDownUp( element, $.ui.keyCode.UP );\n\tequal( 2, element.val(), \"keyboard - value changes on key UP\" );\n});\n\ntest( \"pageDown\", function() {\n\texpect( 4 );\n\tvar element = $( \"#spin\" ).val( -12 ).spinner({\n\t\tpage: 20,\n\t\tmin: -100\n\t});\n\n\telement.spinner( \"pageDown\" );\n\tequal( element.val(), -32, \"pageDown 1 page\" );\n\n\telement.spinner( \"pageDown\", 3 );\n\tequal( element.val(), -92, \"pageDown 3 pages\" );\n\n\telement.spinner( \"pageDown\" );\n\tequal( element.val(), -100, \"value close to min and pageDown 1 page\" );\n\n\telement.spinner( \"pageDown\", 10 );\n\tequal( element.val(), -100, \"value at min and pageDown 10 pages\" );\n});\n\ntest( \"pageUp\", function() {\n\texpect( 4 );\n\tvar element = $( \"#spin\" ).val( 12 ).spinner({\n\t\tpage: 20,\n\t\tmax: 100\n\t});\n\n\telement.spinner( \"pageUp\" );\n\tequal( element.val(), 32, \"pageUp 1 page\" );\n\n\telement.spinner( \"pageUp\", 3 );\n\tequal( element.val(), 92, \"pageUp 3 pages\" );\n\n\telement.spinner( \"pageUp\" );\n\tequal( element.val(), 100, \"value close to max and pageUp 1 page\" );\n\n\telement.spinner( \"pageUp\", 10 );\n\tequal( element.val(), 100, \"value at max and pageUp 10 pages\" );\n});\n\ntest( \"stepDown\", function() {\n\texpect( 4 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({\n\t\tstep: 2,\n\t\tmin: -15\n\t});\n\n\telement.spinner( \"stepDown\" );\n\tequal( element.val(), \"-1\", \"stepDown 1 step\" );\n\n\telement.spinner( \"stepDown\", 5 );\n\tequal( element.val(), \"-11\", \"stepDown 5 steps\" );\n\n\telement.spinner( \"stepDown\", 4 );\n\tequal( element.val(), \"-15\", \"close to min and stepDown 4 steps\" );\n\n\telement.spinner( \"stepDown\" );\n\tequal( element.val(), \"-15\", \"at min and stepDown 1 step\" );\n});\n\ntest( \"stepUp\", function() {\n\texpect( 4 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({\n\t\tstep: 2,\n\t\tmax: 16\n\t});\n\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), 2, \"stepUp 1 step\" );\n\n\telement.spinner( \"stepUp\", 5 );\n\tequal( element.val(), 12, \"stepUp 5 steps\" );\n\n\telement.spinner( \"stepUp\", 4 );\n\tequal( element.val(), 16, \"close to min and stepUp 4 steps\" );\n\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), 16, \"at max and stepUp 1 step\" );\n});\n\ntest( \"value\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({\n\t\tstep: 3\n\t});\n\n\telement.spinner( \"value\", 10 );\n\tequal( element.val(), 9, \"change value via value method\" );\n\n\tequal( element.spinner( \"value\" ), 9, \"get value via value method\" );\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner_options.js",
    "content": "(function( $ ) {\n\nvar simulateKeyDownUp = TestHelpers.spinner.simulateKeyDownUp;\n\nmodule( \"spinner: options\" );\n\n// culture is tested after numberFormat, since it depends on numberFormat\n\ntest( \"incremental, false\", function() {\n\texpect( 100 );\n\n\tvar i, diff,\n\t\tprev = 0,\n\t\telement = $( \"#spin\" ).val( prev ).spinner({\n\t\t\tincremental: false,\n\t\t\tspin: function( event, ui ) {\n\t\t\t\tequal( ui.value - prev, 1 );\n\t\t\t\tprev = ui.value;\n\t\t\t}\n\t\t});\n\n\tfor ( i = 0; i < 100; i++ ) {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t}\n\telement.simulate( \"keyup\", { keyCode: $.ui.keyCode.UP } );\n});\n\ntest( \"incremental, true\", function() {\n\texpect( 100 );\n\n\tfunction fill( num, val ) {\n\t\treturn $.map( new Array( num ), function() {\n\t\t\treturn val;\n\t\t});\n\t}\n\n\tvar i, diff,\n\t\tprev = 0,\n\t\texpected = [].concat( fill( 18, 1 ), fill( 37, 2 ), fill( 14, 3 ),\n\t\t\tfill( 9, 4 ), fill( 6, 5 ), fill( 5, 6 ), fill ( 5, 7 ),\n\t\t\tfill( 4, 8 ), fill( 2, 9 ) ),\n\t\telement = $( \"#spin\" ).val( prev ).spinner({\n\t\t\tincremental: true,\n\t\t\tspin: function( event, ui ) {\n\t\t\t\tequal( ui.value - prev, expected[ i ] );\n\t\t\t\tprev = ui.value;\n\t\t\t}\n\t\t});\n\n\tfor ( i = 0; i < 100; i++ ) {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t}\n\telement.simulate( \"keyup\", { keyCode: $.ui.keyCode.UP } );\n});\n\ntest( \"incremental, function\", function() {\n\texpect( 100 );\n\n\tvar i,\n\t\tprev = 0,\n\t\telement = $( \"#spin\" ).val( prev ).spinner({\n\t\t\tincremental: function( i ) {\n\t\t\t\treturn i;\n\t\t\t},\n\t\t\tspin: function( event, ui ) {\n\t\t\t\tequal( ui.value - prev, i + 1 );\n\t\t\t\tprev = ui.value;\n\t\t\t}\n\t\t});\n\n\tfor ( i = 0; i < 100; i++ ) {\n\t\telement.simulate( \"keydown\", { keyCode: $.ui.keyCode.UP } );\n\t}\n\telement.simulate( \"keyup\", { keyCode: $.ui.keyCode.UP } );\n});\n\ntest( \"numberFormat, number\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({ numberFormat: \"n\" });\n\tequal( element.val(), \"0.00\", \"formatted on init\" );\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"1.00\", \"formatted after step\" );\n});\n\ntest( \"numberFormat, number, simple\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({ numberFormat: \"n0\" });\n\tequal( element.val(), \"0\", \"formatted on init\" );\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"1\", \"formatted after step\" );\n});\n\ntest( \"numberFormat, currency\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({ numberFormat: \"C\" });\n\tequal( element.val(), \"$0.00\", \"formatted on init\" );\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"$1.00\", \"formatted after step\" );\n});\n\ntest( \"numberFormat, change\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 5 ).spinner({ numberFormat: \"n1\" });\n\tequal( element.val(), \"5.0\", \"formatted on init\" );\n\telement.spinner( \"option\", \"numberFormat\", \"c\" );\n\tequal( element.val(), \"$5.00\", \"formatted after change\" );\n});\n\ntest( \"culture, null\", function() {\n\texpect( 2 );\n\tGlobalize.culture( \"ja-JP\" );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({ numberFormat: \"C\" });\n\tequal( element.val(), \"¥0\", \"formatted on init\" );\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"¥1\", \"formatted after step\" );\n\n\t// reset culture\n\tGlobalize.culture( \"default\" );\n});\n\ntest( \"currency, ja-JP\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({\n\t\tnumberFormat: \"C\",\n\t\tculture: \"ja-JP\"\n\t});\n\tequal( element.val(), \"¥0\", \"formatted on init\" );\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"¥1\", \"formatted after step\" );\n});\n\ntest( \"currency, change\", function() {\n\texpect( 2 );\n\tvar element = $( \"#spin\" ).val( 5 ).spinner({\n\t\tnumberFormat: \"C\",\n\t\tculture: \"ja-JP\"\n\t});\n\tequal( element.val(), \"¥5\", \"formatted on init\" );\n\telement.spinner( \"option\", \"culture\", \"en\" );\n\tequal( element.val(), \"$5.00\", \"formatted after change\" );\n});\n\ntest( \"max\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" ).val( 1000 ).spinner({ max: 100 });\n\tequal( element.val(), 1000, \"value not constrained on init\" );\n\n\telement.spinner( \"value\", 1000 );\n\tequal( element.val(), 100, \"max constrained in value method\" );\n\n\telement.val( 1000 ).blur();\n\tequal( element.val(), 1000, \"max not constrained if manual entry\" );\n});\n\ntest( \"max, string\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" )\n\t\t.val( 1000 )\n\t\t.spinner({\n\t\t\tmax: \"$100.00\",\n\t\t\tnumberFormat: \"C\",\n\t\t\tculture: \"en\"\n\t\t});\n\tequal( element.val(), \"$1,000.00\", \"value not constrained on init\" );\n\tequal( element.spinner( \"option\", \"max\" ), 100, \"option converted to number\" );\n\n\telement.spinner( \"value\", 1000 );\n\tequal( element.val(), \"$100.00\", \"max constrained in value method\" );\n});\n\ntest( \"min\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" ).val( -1000 ).spinner({ min: -100 });\n\tequal( element.val(), -1000, \"value not constrained on init\" );\n\n\telement.spinner( \"value\", -1000 );\n\tequal( element.val(), -100, \"min constrained in value method\" );\n\n\telement.val( -1000 ).blur();\n\tequal( element.val(), -1000, \"min not constrained if manual entry\" );\n});\n\ntest( \"min, string\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" )\n\t\t.val( -1000 )\n\t\t.spinner({\n\t\t\tmin: \"-$100.00\",\n\t\t\tnumberFormat: \"C\",\n\t\t\tculture: \"en\"\n\t\t});\n\tequal( element.val(), \"($1,000.00)\", \"value not constrained on init\" );\n\tequal( element.spinner( \"option\", \"min\" ), -100, \"option converted to number\" );\n\n\telement.spinner( \"value\", -1000 );\n\tequal( element.val(), \"($100.00)\", \"min constrained in value method\" );\n});\n\ntest( \"step, 2\", function() {\n\texpect( 3 );\n\tvar element = $( \"#spin\" ).val( 0 ).spinner({ step: 2 });\n\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"2\", \"stepUp\" );\n\n\telement.spinner( \"value\", \"10.5\" );\n\tequal( element.val(), \"10\", \"value reset to 10\" );\n\n\telement.val( \"4.5\" );\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"6\", \"stepUp\" );\n});\n\ntest( \"step, 0.7\", function() {\n\texpect( 1 );\n\tvar element = $(\"#spin\").val( 0 ).spinner({\n\t\tstep: 0.7\n\t});\n\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"0.7\", \"stepUp\" );\n});\n\ntest( \"step, string\", function() {\n\texpect( 2 );\n\tvar element = $(\"#spin\").val( 0 ).spinner({\n\t\tstep: \"$0.70\",\n\t\tnumberFormat: \"C\",\n\t\tculture: \"en\"\n\t});\n\n\tequal( element.spinner( \"option\", \"step\" ), 0.7, \"option converted to number\" );\n\n\telement.spinner( \"stepUp\" );\n\tequal( element.val(), \"$0.70\", \"stepUp\" );\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/spinner/spinner_test_helpers.js",
    "content": "TestHelpers.spinner = {\n\tsimulateKeyDownUp: function( element, keyCode, shift ) {\n\t\telement\n\t\t\t.simulate( \"keydown\", { keyCode: keyCode, shiftKey: shift || false } )\n\t\t\t.simulate( \"keyup\", { keyCode: keyCode, shiftKey: shift || false } );\n\t}\n};\n\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/subsuite.js",
    "content": "(function() {\n\nvar versions = [ \"1.6\", \"1.6.1\", \"1.6.2\", \"1.6.3\", \"1.6.4\", \"1.7\", \"1.7.1\", \"1.7.2\", \"git\" ],\n\tadditionalTests = {\n\t\taccordion: [ \"accordion_deprecated.html\" ],\n\t\tposition: [ \"position_deprecated.html\" ],\n\t\ttabs: [ \"tabs_deprecated.html\" ]\n\t};\n\nwindow.testAllVersions = function( widget ) {\n\tQUnit.testSuites( $.map(\n\t\t[ widget + \".html\" ].concat( additionalTests[ widget ] || [] ),\n\t\tfunction( test ) {\n\t\t\treturn $.map( versions, function( version ) {\n\t\t\t\treturn test + \"?jquery=\" + version;\n\t\t\t});\n\t\t}));\n};\n\n}());\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/swarminject.js",
    "content": "// load testswarm agent\n(function() {\n    var url = window.location.search;\n\turl = decodeURIComponent( url.slice( url.indexOf(\"swarmURL=\") + 9 ) );\n\tif ( !url || url.indexOf(\"http\") !== 0 ) {\n\t\treturn;\n\t}\n    document.write( \"<scr\" + \"ipt src='http://swarm.jquery.org/js/inject.js?\" + (new Date()).getTime() + \"'></scr\" + \"ipt>\" );\n})();\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"tabs\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Tabs Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/data/test.html",
    "content": "<p>&#8230;content loaded via Ajax.</p>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script>\n\t$.uiBackCompat = false;\n\t</script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.tabs\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.tabs.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"tabs_test_helpers.js\"></script>\n\t<script src=\"tabs_common.js\"></script>\n\t<script src=\"tabs_core.js\"></script>\n\t<script src=\"tabs_events.js\"></script>\n\t<script src=\"tabs_methods.js\"></script>\n\t<script src=\"tabs_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t#tabs8, #tabs8 * {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tfont-size: 12px;\n\t\tline-height: 15px;\n\t}\n\t</style>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Tabs Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"tabs1\">\n\t<ul>\n\t\t<li><a href=\"#fragment-1\"><span>1</span></a></li>\n\t\t<li><a href=\"#fragment-2\"><span>2</span></a></li>\n\t\t<li><a href=\"#fragment-3\"><span>3</span></a></li>\n\t</ul>\n\t<div id=\"fragment-1\"></div>\n\t<div id=\"fragment-2\"></div>\n\t<div id=\"fragment-3\"></div>\n</div>\n\n<div id=\"tabs2\">\n\t<ul>\n\t\t<li><a href=\"#colon:test\"><span>1</span></a></li>\n\t\t<li><a href=\"#inline-style\"><span>2</span></a></li>\n\t\t<li><a href=\"data/test.html#test\"><span>3</span></a></li>\n\t\t<li aria-controls=\"custom-id\"><a href=\"data/test.html\"><span>4</span></a></li>\n\t\t<li><a href=\"data/test.html\" title=\"∫ßáö Սե\"><span>5</span></a></li>\n\t</ul>\n\t<div id=\"colon:test\"></div>\n\t<div style=\"height: 300px;\" id=\"inline-style\"></div>\n\t<div id=\"custom-id\"></div>\n</div>\n\n<div id=\"tabs3\">\n\t<div>\n\t\t<ul id=\"tabs3-list\">\n\t\t\t<li><a href=\"#tabs3-1\">1</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n<div id=\"tabs4\">\n\t<ul id=\"tabs4-list\">\n\t\t<li><a href=\"#tabs4-1\">1</a></li>\n\t</ul>\n\t<ol>\n\t\t<li><a href=\"#tabs4-1\">1</a></li>\n\t</ol>\n</div>\n\n<div id=\"tabs4a\">\n\t<ol id=\"tabs4a-list\">\n\t\t<li><a href=\"#tabs4a-1\">1</a></li>\n\t</ol>\n\t<ul>\n\t\t<li><a href=\"#tabs4a-1\">1</a></li>\n\t</ul>\n</div>\n\n<div id=\"tabs5\">\n\t<div>\n\t\t<ul id=\"tabs5-list\"></ul>\n\t</div>\n</div>\n\n<div id=\"tabs6\">\n\t<ul id=\"tabs6-list\">\n\t\t<li><a href=\"#tabs6-1\">1</a>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#item6-3\">3</a></li>\n\t\t\t\t<li><a href=\"#item6-4\">4</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li><a href=\"#tabs6-2\">2</a></li>\n\t</ul>\n\t<div id=\"tabs6-1\"></div>\n\t<div id=\"tabs6-2\"></div>\n</div>\n\n<div id=\"tabs7\">\n\t<ul id=\"tabs7-list\">\n\t\t<li><a href=\"#tabs7-1\">1</a></li>\n\t\t<li><a href=\"#tabs7-2\">2</a></li>\n\t</ul>\n\t<div id=\"tabs7-2\"></div>\n\t<div id=\"tabs7-1\"></div>\n</div>\n\n<div id=\"tabs8Wrapper\">\n\t<div id=\"tabs8\">\n\t\t<ul id=\"tabs8-list\">\n\t\t\t<li><a href=\"#tabs8-1\">1</a></li>\n\t\t\t<li><a href=\"#tabs8-2\">2</a></li>\n\t\t</ul>\n\t\t<div id=\"tabs8-1\">\n\t\t\t<p>Lorem ipsum</p>\n\t\t\t<p>Lorem ipsum</p>\n\t\t\t<p>Lorem ipsum</p>\n\t\t</div>\n\t\t<div id=\"tabs8-2\">\n\t\t\t<p>Lorem ipsum</p>\n\t\t</div>\n\t</div>\n</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_common.js",
    "content": "TestHelpers.commonWidgetTests( \"tabs\", {\n\tdefaults: {\n\t\tactive: null,\n\t\tcollapsible: false,\n\t\tdisabled: false,\n\t\tevent: \"click\",\n\t\theightStyle: \"content\",\n\t\thide: null,\n\t\tshow: null,\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tbeforeLoad: null,\n\t\tcreate: null,\n\t\tload: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_common_deprecated.js",
    "content": "TestHelpers.commonWidgetTests( \"tabs\", {\n\tdefaults: {\n\t\tactive: null,\n\t\tajaxOptions: null,\n\t\tcache: false,\n\t\tcollapsible: false,\n\t\tcookie: null,\n\t\tdisabled: false,\n\t\tevent: \"click\",\n\t\theightStyle: \"content\",\n\t\thide: null,\n\t\tfx: null,\n\t\tidPrefix: \"ui-tabs-\",\n\t\tpanelTemplate: \"<div></div>\",\n\t\t// show: null, // conflicts with old show callback\n\t\tspinner: \"<em>Loading&#8230;</em>\",\n\t\ttabTemplate: \"<li><a href='#{href}'><span>#{label}</span></a></li>\",\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tadd: null,\n\t\tbeforeActivate: null,\n\t\tbeforeLoad: null,\n\t\tcreate: null,\n\t\tdisable: null,\n\t\tenable: null,\n\t\tload: null,\n\t\tremove: null,\n\t\tselect: null,\n\t\tshow: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_core.js",
    "content": "(function( $ ) {\n\nvar state = TestHelpers.tabs.state;\n\nmodule( \"tabs: core\" );\n\ntest( \"markup structure\", function() {\n\texpect( 3 );\n\tvar element = $( \"#tabs1\" ).tabs();\n\tok( element.hasClass( \"ui-tabs\" ), \"main element is .ui-tabs\" );\n\tok( element.find( \"ul\" ).hasClass( \"ui-tabs-nav\" ), \"list item is .ui-tabs-nav\" );\n\tequal( element.find( \".ui-tabs-panel\" ).length, 3,\n\t\t\".ui-tabs-panel elements exist, correct number\" );\n});\n\n$.each({\n\t\"deep ul\": \"#tabs3\",\n\t\"multiple lists, ul first\": \"#tabs4\",\n\t\"multiple lists, ol first\": \"#tabs5\",\n\t\"empty list\": \"#tabs6\"\n}, function( type, selector ) {\n\ttest( \"markup structure: \" + type, function() {\n\t\texpect( 2 );\n\t\tvar element = $( selector ).tabs();\n\t\tok( element.hasClass( \"ui-tabs\" ), \"main element is .ui-tabs\" );\n\t\tok( $( selector + \"-list\" ).hasClass( \"ui-tabs-nav\" ),\n\t\t\t\"list item is .ui-tabs-nav\" );\n\t});\n});\n\n// #5893 - Sublist in the tab list are considered as tab\ntest( \"nested list\", function() {\n\texpect( 1 );\n\n\tvar element = $( \"#tabs6\" ).tabs();\n\tequal( element.data( \"tabs\" ).anchors.length, 2, \"should contain 2 tab\" );\n});\n\ntest( \"disconnected from DOM\", function() {\n\texpect( 2 );\n\n\tvar element = $( \"#tabs1\" ).remove().tabs();\n\tequal( element.find( \".ui-tabs-nav\" ).length, 1, \"should initialize nav\" );\n\tequal( element.find( \".ui-tabs-panel\" ).length, 3, \"should initialize panels\" );\n});\n\ntest( \"aria-controls\", function() {\n\texpect( 7 );\n\tvar element = $( \"#tabs1\" ).tabs(),\n\t\ttabs = element.find( \".ui-tabs-nav li\" );\n\ttabs.each(function() {\n\t\tvar tab = $( this ),\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" );\n\t\tequal( anchor.prop( \"hash\" ).substring( 1 ), tab.attr( \"aria-controls\" ) );\n\t});\n\n\telement = $( \"#tabs2\" ).tabs();\n\ttabs = element.find( \".ui-tabs-nav li\" );\n\tequal( tabs.eq( 0 ).attr( \"aria-controls\" ), \"colon:test\" );\n\tequal( tabs.eq( 1 ).attr( \"aria-controls\" ), \"inline-style\" );\n\tok( /^ui-tabs-\\d+$/.test( tabs.eq( 2 ).attr( \"aria-controls\" ) ), \"generated id\" );\n\tequal( tabs.eq( 3 ).attr( \"aria-controls\" ), \"custom-id\" );\n});\n\ntest( \"accessibility\", function() {\n\texpect( 49 );\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tactive: 1,\n\t\t\tdisabled: [ 2 ]\n\t\t}),\n\t\ttabs = element.find( \".ui-tabs-nav li\" ),\n\t\tanchors = tabs.find( \".ui-tabs-anchor\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" );\n\n\tequal( element.find( \".ui-tabs-nav\" ).attr( \"role\" ), \"tablist\", \"tablist role\" );\n\ttabs.each(function( index ) {\n\t\tvar tab = tabs.eq( index ),\n\t\t\tanchor = anchors.eq( index ),\n\t\t\tanchorId = anchor.attr( \"id\" ),\n\t\t\tpanel = panels.eq( index );\n\t\tequal( tab.attr( \"role\" ), \"tab\", \"tab \" + index + \" role\" );\n\t\tequal( tab.attr( \"aria-labelledby\" ), anchorId, \"tab \" + index + \" aria-labelledby\" );\n\t\tequal( anchor.attr( \"role\" ), \"presentation\", \"anchor \" + index + \" role\" );\n\t\tequal( anchor.attr( \"tabindex\" ), -1, \"anchor \" + index + \" tabindex\" );\n\t\tequal( panel.attr( \"role\" ), \"tabpanel\", \"panel \" + index + \" role\" );\n\t\tequal( panel.attr( \"aria-labelledby\" ), anchorId, \"panel \" + index + \" aria-labelledby\" );\n\t});\n\n\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"true\", \"active tab has aria-selected=true\" );\n\tequal( tabs.eq( 1 ).attr( \"tabindex\" ), 0, \"active tab has tabindex=0\" );\n\tequal( tabs.eq( 1 ).attr( \"aria-disabled\" ), null, \"enabled tab does not have aria-disabled\" );\n\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"true\", \"active panel has aria-expanded=true\" );\n\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"false\", \"active panel has aria-hidden=false\" );\n\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( tabs.eq( 0 ).attr( \"tabindex\" ), -1, \"inactive tab has tabindex=-1\" );\n\tequal( tabs.eq( 0 ).attr( \"aria-disabled\" ), null, \"enabled tab does not have aria-disabled\" );\n\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"inactive panel has aria-expanded=false\" );\n\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"inactive panel has aria-hidden=true\" );\n\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( tabs.eq( 2 ).attr( \"tabindex\" ), -1, \"inactive tab has tabindex=-1\" );\n\tequal( tabs.eq( 2 ).attr( \"aria-disabled\" ), \"true\", \"disabled tab has aria-disabled=true\" );\n\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"inactive panel has aria-expanded=false\" );\n\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"inactive panel has aria-hidden=true\" );\n\n\telement.tabs( \"option\", \"active\", 0 );\n\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"active tab has aria-selected=true\" );\n\tequal( tabs.eq( 0 ).attr( \"tabindex\" ), 0, \"active tab has tabindex=0\" );\n\tequal( tabs.eq( 0 ).attr( \"aria-disabled\" ), null, \"enabled tab does not have aria-disabled\" );\n\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"active panel has aria-expanded=true\" );\n\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"active panel has aria-hidden=false\" );\n\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( tabs.eq( 1 ).attr( \"tabindex\" ), -1, \"inactive tab has tabindex=-1\" );\n\tequal( tabs.eq( 1 ).attr( \"aria-disabled\" ), null, \"enabled tab does not have aria-disabled\" );\n\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"inactive panel has aria-expanded=false\" );\n\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"inactive panel has aria-hidden=true\" );\n\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"inactive tab has aria-selected=false\" );\n\tequal( tabs.eq( 2 ).attr( \"tabindex\" ), -1, \"inactive tab has tabindex=-1\" );\n\tequal( tabs.eq( 2 ).attr( \"aria-disabled\" ), \"true\", \"disabled tab has aria-disabled=true\" );\n\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"inactive panel has aria-expanded=false\" );\n\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"inactive panel has aria-hidden=true\" );\n\n\t// TODO: aria-live and aria-busy tests for ajax tabs\n});\n\nasyncTest( \"keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER\", function() {\n\texpect( 92 );\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tcollapsible: true\n\t\t}),\n\t\ttabs = element.find( \".ui-tabs-nav li\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" ),\n\t\tkeyCode = $.ui.keyCode;\n\n\telement.data( \"tabs\" ).delay = 50;\n\n\tequal( tabs.filter( \".ui-state-focus\" ).length, 0, \"no tabs focused on init\" );\n\ttabs.eq( 0 ).simulate( \"focus\" );\n\n\t// down, right, down (wrap), up (wrap)\n\tfunction step1() {\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"first tab has focus\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.DOWN } );\n\t\tok( tabs.eq( 1 ).is( \".ui-state-focus\" ), \"DOWN moves focus to next tab\" );\n\t\tok( !tabs.eq( 0 ).is( \".ui-state-focus\" ), \"first tab is no longer focused\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"true\", \"second tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"first tab has aria-selected=false\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is still hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\ttabs.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.RIGHT } );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"RIGHT moves focus to next tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"second tab has aria-selected=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is still hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.DOWN } );\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"DOWN wraps focus to first tab\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.UP } );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"UP wraps focus to last tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"first tab has aria-selected=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is still hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step2, 100 );\n\t}\n\n\t// left, home, space\n\tfunction step2() {\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"first tab has aria-selected=false\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel is hidden\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"first panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"first panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.LEFT } );\n\t\tok( tabs.eq( 1 ).is( \".ui-state-focus\" ), \"LEFT moves focus to previous tab\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"true\", \"second tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is still hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is still visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\n\t\ttabs.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.HOME } );\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"HOME moves focus to first tab\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"second tab has aria-selected=false\" );\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel is still hidden\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"first panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"first panel has aria-hidden=true\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is still visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\n\t\t// SPACE activates, cancels delay\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.SPACE } );\n\t\tsetTimeout( step3, 1 );\n\t}\n\n\t// end, enter\n\tfunction step3() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.END } );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"END moves focus to last tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"first tab has aria-selected=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is still hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\t// ENTER activates, cancels delay\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.ENTER } );\n\t\tsetTimeout( step4, 1 );\n\t}\n\n\t// enter (collapse)\n\tfunction step4() {\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel is hidden\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"first panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"first panel has aria-hidden=true\" );\n\n\t\t// ENTER collapses if active\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.ENTER } );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\t// support: Firefox 12\n\t\t// Firefox <13 passes arguments so we can't use setTimeout( start, 1 )\n\t\tsetTimeout(function() {\n\t\t\tstart();\n\t\t}, 1 );\n\t}\n\n\tsetTimeout( step1, 1 );\n});\n\nasyncTest( \"keyboard support - CTRL navigation\", function() {\n\texpect( 115 );\n\tvar element = $( \"#tabs1\" ).tabs(),\n\t\ttabs = element.find( \".ui-tabs-nav li\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" ),\n\t\tkeyCode = $.ui.keyCode;\n\n\telement.data( \"tabs\" ).delay = 50;\n\n\tequal( tabs.filter( \".ui-state-focus\" ).length, 0, \"no tabs focused on init\" );\n\ttabs.eq( 0 ).simulate( \"focus\" );\n\n\t// down\n\tfunction step1() {\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"first tab has focus\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.DOWN, ctrlKey: true } );\n\t\tok( tabs.eq( 1 ).is( \".ui-state-focus\" ), \"DOWN moves focus to next tab\" );\n\t\tok( !tabs.eq( 0 ).is( \".ui-state-focus\" ), \"first tab is no longer focused\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"second tab has aria-selected=false\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is still hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step2, 100 );\n\t}\n\n\t// right\n\tfunction step2() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.RIGHT, ctrlKey: true } );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"RIGHT moves focus to next tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is still hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step3, 100 );\n\t}\n\n\t// down (wrap)\n\tfunction step3() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.DOWN, ctrlKey: true } );\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"DOWN wraps focus to first tab\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step4, 100 );\n\t}\n\n\t// up (wrap)\n\tfunction step4() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.UP, ctrlKey: true } );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"UP wraps focus to last tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is still hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step5, 100 );\n\t}\n\n\t// left\n\tfunction step5() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.LEFT, ctrlKey: true } );\n\t\tok( tabs.eq( 1 ).is( \".ui-state-focus\" ), \"LEFT moves focus to previous tab\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"second tab has aria-selected=false\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is still hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step6, 100 );\n\t}\n\n\t// home\n\tfunction step6() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.HOME, ctrlKey: true } );\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"HOME moves focus to first tab\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"false\", \"second tab has aria-selected=false\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is still hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step7, 100 );\n\t}\n\n\t// end\n\tfunction step7() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\ttabs.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.END, ctrlKey: true } );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"END moves focus to last tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"false\", \"third tab has aria-selected=false\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is still hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is still visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\n\t\tsetTimeout( step8, 100 );\n\t}\n\n\t// space\n\tfunction step8() {\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.SPACE } );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"false\", \"first tab has aria-selected=false\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel is hidden\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"first panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"first panel has aria-hidden=true\" );\n\n\t\t// support: Firefox 12\n\t\t// Firefox <13 passes arguments so we can't use setTimeout( start, 1 )\n\t\tsetTimeout(function() {\n\t\t\tstart();\n\t\t}, 1 );\n\t}\n\n\tsetTimeout( step1, 1 );\n});\n\nasyncTest( \"keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP\", function() {\n\texpect( 50 );\n\tvar element = $( \"#tabs1\" ).tabs(),\n\t\ttabs = element.find( \".ui-tabs-nav li\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" ),\n\t\tkeyCode = $.ui.keyCode;\n\n\tequal( tabs.filter( \".ui-state-focus\" ).length, 0, \"no tabs focused on init\" );\n\tpanels.attr( \"tabindex\", -1 );\n\tpanels.eq( 0 ).simulate( \"focus\" );\n\n\tfunction step1() {\n\t\tstrictEqual( document.activeElement, panels[ 0 ], \"first panel is activeElement\" );\n\n\t\tpanels.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.PAGE_DOWN, altKey: true } );\n\t\tstrictEqual( document.activeElement, tabs[ 1 ], \"second tab is activeElement\" );\n\t\tok( tabs.eq( 1 ).is( \".ui-state-focus\" ), \"ALT+PAGE_DOWN moves focus to next tab\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"true\", \"second tab has aria-selected=true\" );\n\t\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel is visible\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"true\", \"second panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"false\", \"second panel has aria-hidden=false\" );\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel is hidden\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"first panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"first panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.PAGE_DOWN, altKey: true } );\n\t\tstrictEqual( document.activeElement, tabs[ 2 ], \"third tab is activeElement\" );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"ALT+PAGE_DOWN moves focus to next tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\t\tok( panels.eq( 1 ).is( \":hidden\" ), \"second panel is hidden\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"false\", \"second panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"true\", \"second panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.PAGE_DOWN, altKey: true } );\n\t\tstrictEqual( document.activeElement, tabs[ 0 ], \"first tab is activeElement\" );\n\t\tok( tabs.eq( 0 ).is( \".ui-state-focus\" ), \"ALT+PAGE_DOWN wraps focus to first tab\" );\n\t\tequal( tabs.eq( 0 ).attr( \"aria-selected\" ), \"true\", \"first tab has aria-selected=true\" );\n\t\tok( panels.eq( 0 ).is( \":visible\" ), \"first panel is visible\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"true\", \"first panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"false\", \"first panel has aria-hidden=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\tpanels.eq( 0 ).simulate( \"focus\" );\n\t\tsetTimeout( step2, 1 );\n\t}\n\n\tfunction step2() {\n\t\tstrictEqual( document.activeElement, panels[ 0 ], \"first panel is activeElement\" );\n\n\t\tpanels.eq( 0 ).simulate( \"keydown\", { keyCode: keyCode.PAGE_UP, altKey: true } );\n\t\tstrictEqual( document.activeElement, tabs[ 2 ], \"third tab is activeElement\" );\n\t\tok( tabs.eq( 2 ).is( \".ui-state-focus\" ), \"ALT+PAGE_UP wraps focus to last tab\" );\n\t\tequal( tabs.eq( 2 ).attr( \"aria-selected\" ), \"true\", \"third tab has aria-selected=true\" );\n\t\tok( panels.eq( 2 ).is( \":visible\" ), \"third panel is visible\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"true\", \"third panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"false\", \"third panel has aria-hidden=false\" );\n\t\tok( panels.eq( 0 ).is( \":hidden\" ), \"first panel is hidden\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-expanded\" ), \"false\", \"first panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 0 ).attr( \"aria-hidden\" ), \"true\", \"first panel has aria-hidden=true\" );\n\n\t\ttabs.eq( 2 ).simulate( \"keydown\", { keyCode: keyCode.PAGE_UP, altKey: true } );\n\t\tstrictEqual( document.activeElement, tabs[ 1 ], \"second tab is activeElement\" );\n\t\tok( tabs.eq( 1 ).is( \".ui-state-focus\" ), \"ALT+PAGE_UP moves focus to previous tab\" );\n\t\tequal( tabs.eq( 1 ).attr( \"aria-selected\" ), \"true\", \"second tab has aria-selected=true\" );\n\t\tok( panels.eq( 1 ).is( \":visible\" ), \"second panel is visible\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-expanded\" ), \"true\", \"second panel has aria-expanded=true\" );\n\t\tequal( panels.eq( 1 ).attr( \"aria-hidden\" ), \"false\", \"second panel has aria-hidden=false\" );\n\t\tok( panels.eq( 2 ).is( \":hidden\" ), \"third panel is hidden\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-expanded\" ), \"false\", \"third panel has aria-expanded=false\" );\n\t\tequal( panels.eq( 2 ).attr( \"aria-hidden\" ), \"true\", \"third panel has aria-hidden=true\" );\n\n\t\tpanels.eq( 1 ).simulate( \"focus\" );\n\t\tsetTimeout( step3, 1 );\n\t}\n\n\tfunction step3() {\n\t\tstrictEqual( document.activeElement, panels[ 1 ], \"second panel is activeElement\" );\n\n\t\tpanels.eq( 1 ).simulate( \"keydown\", { keyCode: keyCode.UP, ctrlKey: true } );\n\t\tstrictEqual( document.activeElement, tabs[ 1 ], \"second tab is activeElement\" );\n\n\t\t// support: Firefox 12\n\t\t// Firefox <13 passes arguments so we can't use setTimeout( start, 1 )\n\t\tsetTimeout(function() {\n\t\t\tstart();\n\t\t}, 1 );\n\t}\n\n\tsetTimeout( step1, 1 );\n});\n\ntest( \"#3627 - Ajax tab with url containing a fragment identifier fails to load\", function() {\n\texpect( 1 );\n\n\tvar element = $( \"#tabs2\" ).tabs({\n\t\tactive: 2,\n\t\tbeforeLoad: function( event, ui ) {\n\t\t\tevent.preventDefault();\n\t\t\tok( /test.html$/.test( ui.ajaxSettings.url ), \"should ignore fragment identifier\" );\n\t\t}\n\t});\n});\n\ntest( \"#4033 - IE expands hash to full url and misinterprets tab as ajax\", function() {\n\texpect( 2 );\n\n\tvar element = $( \"<div><ul><li><a href='#tab'>Tab</a></li></ul><div id='tab'></div></div>\" );\n\telement.appendTo( \"#main\" );\n\telement.tabs({\n\t\tbeforeLoad: function( event, ui ) {\n\t\t\tevent.preventDefault();\n\t\t\tok( false, \"should not be an ajax tab\" );\n\t\t}\n\t});\n\n\tequal( element.find( \".ui-tabs-nav li\" ).attr( \"aria-controls\" ), \"tab\", \"aria-contorls attribute is correct\" );\n\tstate( element, 1 );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_deprecated.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tabs Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<script src=\"../../../external/jquery.cookie.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.tabs\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.tabs.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"tabs_test_helpers.js\"></script>\n\t<script src=\"tabs_common_deprecated.js\"></script>\n\t<script src=\"tabs_core.js\"></script>\n\t<script src=\"tabs_events.js\"></script>\n\t<script src=\"tabs_methods.js\"></script>\n\t<script src=\"tabs_options.js\"></script>\n\t<script src=\"tabs_deprecated.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n\t<style>\n\t#tabs8, #tabs8 * {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tfont-size: 12px;\n\t\tline-height: 15px;\n\t}\n\t</style>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Tabs Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"tabs1\">\n\t<ul>\n\t\t<li><a href=\"#fragment-1\"><span>1</span></a></li>\n\t\t<li><a href=\"#fragment-2\"><span>2</span></a></li>\n\t\t<li><a href=\"#fragment-3\"><span>3</span></a></li>\n\t</ul>\n\t<div id=\"fragment-1\"></div>\n\t<div id=\"fragment-2\"></div>\n\t<div id=\"fragment-3\"></div>\n</div>\n\n<div id=\"tabs2\">\n\t<ul>\n\t\t<li><a href=\"#colon:test\"><span>1</span></a></li>\n\t\t<li><a href=\"#inline-style\"><span>2</span></a></li>\n\t\t<li><a href=\"data/test.html#test\"><span>3</span></a></li>\n\t\t<li aria-controls=\"custom-id\"><a href=\"data/test.html\"><span>4</span></a></li>\n\t\t<li><a href=\"data/test.html\" title=\"∫ßáö Սե\"><span>5</span></a></li>\n\t</ul>\n\t<div id=\"colon:test\"></div>\n\t<div style=\"height: 300px;\" id=\"inline-style\"></div>\n\t<div id=\"custom-id\"></div>\n</div>\n\n<div id=\"tabs3\">\n\t<div>\n\t\t<ul id=\"tabs3-list\">\n\t\t\t<li><a href=\"#tabs3-1\">1</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n<div id=\"tabs4\">\n\t<ul id=\"tabs4-list\">\n\t\t<li><a href=\"#tabs4-1\">1</a></li>\n\t</ul>\n\t<ol>\n\t\t<li><a href=\"#tabs4-1\">1</a></li>\n\t</ol>\n</div>\n\n<div id=\"tabs4a\">\n\t<ol id=\"tabs4a-list\">\n\t\t<li><a href=\"#tabs4a-1\">1</a></li>\n\t</ol>\n\t<ul>\n\t\t<li><a href=\"#tabs4a-1\">1</a></li>\n\t</ul>\n</div>\n\n<div id=\"tabs5\">\n\t<div>\n\t\t<ul id=\"tabs5-list\"></ul>\n\t</div>\n</div>\n\n<div id=\"tabs6\">\n\t<ul id=\"tabs6-list\">\n\t\t<li><a href=\"#tabs6-1\">1</a>\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#item6-3\">3</a></li>\n\t\t\t\t<li><a href=\"#item6-4\">4</a></li>\n\t\t\t</ul>\n\t\t</li>\n\t\t<li><a href=\"#tabs6-2\">2</a></li>\n\t</ul>\n\t<div id=\"tabs6-1\"></div>\n\t<div id=\"tabs6-2\"></div>\n</div>\n\n<div id=\"tabs7\">\n\t<ul id=\"tabs7-list\">\n\t\t<li><a href=\"#tabs7-1\">1</a></li>\n\t\t<li><a href=\"#tabs7-2\">2</a></li>\n\t</ul>\n\t<div id=\"tabs7-2\"></div>\n\t<div id=\"tabs7-1\"></div>\n</div>\n\n<div id=\"tabs8Wrapper\">\n\t<div id=\"tabs8\">\n\t\t<ul id=\"tabs8-list\">\n\t\t\t<li><a href=\"#tabs8-1\">1</a></li>\n\t\t\t<li><a href=\"#tabs8-2\">2</a></li>\n\t\t</ul>\n\t\t<div id=\"tabs8-1\">\n\t\t\t<p>Lorem ipsum</p>\n\t\t\t<p>Lorem ipsum</p>\n\t\t\t<p>Lorem ipsum</p>\n\t\t</div>\n\t\t<div id=\"tabs8-2\">\n\t\t\t<p>Lorem ipsum</p>\n\t\t</div>\n\t</div>\n</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_deprecated.js",
    "content": "(function( $ ) {\n\nvar state = TestHelpers.tabs.state;\n\nmodule( \"tabs (deprecated): core\" );\n\ntest( \"panel ids\", function() {\n\texpect( 2 );\n\n\tvar element = $( \"#tabs2\" ).tabs();\n\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\tequal( ui.panel.attr( \"id\" ), \"∫ßáö_Սե\", \"from title attribute\" );\n\t\tevent.preventDefault();\n\t});\n\telement.tabs( \"option\", \"active\", 4 );\n\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\tok( /^ui-tabs-\\d+$/.test( ui.panel.attr( \"id\" ) ), \"generated id\" );\n\t\tevent.preventDefault();\n\t});\n\telement.tabs( \"option\", \"active\", 2 );\n});\n\nmodule( \"tabs (deprecated): options\" );\n\nasyncTest( \"ajaxOptions\", function() {\n\texpect( 1 );\n\n\tvar element = $( \"#tabs2\" ).tabs({\n\t\tajaxOptions: {\n\t\t\tconverters: {\n\t\t\t\t\"text html\": function() {\n\t\t\t\t\treturn \"test\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\telement.one( \"tabsload\", function( event, ui ) {\n\t\tequal( $( ui.panel ).html(), \"test\" );\n\t\tstart();\n\t});\n\telement.tabs( \"option\", \"active\", 2 );\n});\n\nasyncTest( \"cache\", function() {\n\texpect( 5 );\n\n\tvar element = $( \"#tabs2\" ).tabs({\n\t\tcache: true\n\t});\n\telement.one( \"tabsshow\", function( event, ui ) {\n\t\tstate( element, 0, 0, 1, 0, 0 );\n\t});\n\telement.one( \"tabsload\", function( event, ui ) {\n\t\tok( true, \"tabsload\" );\n\n\t\tsetTimeout(function() {\n\t\t\telement.tabs( \"option\", \"active\", 0 );\n\t\t\tstate( element, 1, 0, 0, 0, 0 );\n\n\t\t\telement.one( \"tabsshow\", function( event, ui ) {\n\t\t\t\tstate( element, 0, 0, 1, 0, 0 );\n\t\t\t});\n\t\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\t\tok( false, \"should be cached\" );\n\t\t\t});\n\t\t\telement.tabs( \"option\", \"active\", 2 );\n\t\t\tstart();\n\t\t}, 1 );\n\t});\n\telement.tabs( \"option\", \"active\", 2 );\n\tstate( element, 0, 0, 1, 0, 0 );\n});\n\ntest( \"idPrefix\", function() {\n\texpect( 1 );\n\n\t$( \"#tabs2\" )\n\t\t.one( \"tabsbeforeload\", function( event, ui ) {\n\t\t\tok( /^testing-\\d+$/.test( ui.panel.attr( \"id\" ) ), \"generated id\" );\n\t\t\tevent.preventDefault();\n\t\t})\n\t\t.tabs({\n\t\t\tidPrefix: \"testing-\",\n\t\t\tactive: 2\n\t\t});\n});\n\ntest( \"tabTemplate + panelTemplate\", function() {\n\t// defaults are tested in the add method test\n\texpect( 11 );\n\n\tvar tab, anchor,\n\t\telement = $( \"#tabs2\" ).tabs({\n\t\t\ttabTemplate: \"<li class='customTab'><a href='http://example.com/#{href}'>#{label}</a></li>\",\n\t\t\tpanelTemplate: \"<div class='customPanel'></div>\"\n\t\t});\n\telement.one( \"tabsadd\", function( event, ui ) {\n\t\tvar anchor = $( ui.tab );\n\t\tequal( ui.index, 5, \"ui.index\" );\n\t\tequal( anchor.text(), \"New\", \"ui.tab\" );\n\t\tequal( anchor.attr( \"href\" ), \"http://example.com/#new\", \"tab href\" );\n\t\tok( anchor.parent().hasClass( \"customTab\" ), \"tab custom class\" );\n\t\tequal( ui.panel.id, \"new\", \"ui.panel\" );\n\t\tok( $( ui.panel ).hasClass( \"customPanel\" ), \"panel custom class\" );\n\t});\n\telement.tabs( \"add\", \"#new\", \"New\" );\n\ttab = element.find( \".ui-tabs-nav li\" ).last();\n\tanchor = tab.find( \".ui-tabs-anchor\" );\n\tequal( tab.text(), \"New\", \"label\" );\n\tok( tab.hasClass( \"customTab\" ), \"tab custom class\" );\n\tequal( anchor.attr( \"href\" ), \"http://example.com/#new\", \"href\" );\n\tequal( tab.attr( \"aria-controls\" ), \"new\", \"aria-controls\" );\n\tok( element.find( \"#new\" ).hasClass( \"customPanel\" ), \"panel custom class\" );\n});\n\ntest( \"cookie\", function() {\n\texpect( 6 );\n\n\tvar element = $( \"#tabs1\" ),\n\t\tcookieName = \"tabs_test\",\n\t\tcookieObj = { name: cookieName };\n\t$.cookie( cookieName, null );\n\tfunction cookie() {\n\t\treturn parseInt( $.cookie( cookieName ), 10 );\n\t}\n\n\telement.tabs({ cookie: cookieObj });\n\tequal( cookie(), 0, \"initial cookie value\" );\n\n\telement.tabs( \"destroy\" );\n\telement.tabs({ active: 1, cookie: cookieObj });\n\tequal( cookie(), 1, \"initial cookie value, from active property\" );\n\n\telement.tabs( \"option\", \"active\", 2 );\n\tequal( cookie(), 2, \"cookie value updated after activating\" );\n\n\telement.tabs( \"destroy\" );\n\t$.cookie( cookieName, 1 );\n\telement.tabs({ cookie: cookieObj });\n\tequal( cookie(), 1, \"initial cookie value, from existing cookie\" );\n\n\telement.tabs( \"destroy\" );\n\telement.tabs({ cookie: cookieObj, collapsible: true });\n\telement.tabs( \"option\", \"active\", false );\n\tequal( cookie(), -1, \"cookie value for all tabs unselected\" );\n\n\telement.tabs( \"destroy\" );\n\tok( $.cookie( cookieName ) === null, \"erase cookie after destroy\" );\n});\n\nasyncTest( \"spinner\", function() {\n\texpect( 2 );\n\n\tvar element = $( \"#tabs2\" ).tabs();\n\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\tequal( element.find( \".ui-tabs-nav li:eq(2) em\" ).length, 1, \"beforeload\" );\n\t});\n\telement.one( \"tabsload\", function( event, ui ) {\n\t\t// wait until after the load finishes before checking for the spinner to be removed\n\t\tsetTimeout(function() {\n\t\t\tequal( element.find( \".ui-tabs-nav li:eq(2) em\" ).length, 0, \"load\" );\n\t\t\tstart();\n\t\t}, 1 );\n\t});\n\telement.tabs( \"option\", \"active\", 2 );\n});\n\ntest( \"selected\", function() {\n\texpect( 19 );\n\n\tvar element = $( \"#tabs1\" ).tabs();\n\tequal( element.tabs( \"option\", \"selected\" ), 0, \"should be 0 by default\" );\n\tstate( element, 1, 0, 0 );\n\telement.tabs( \"destroy\" );\n\n\tlocation.hash = \"#fragment-3\";\n\telement = $( \"#tabs1\" ).tabs();\n\tequal( element.tabs( \"option\", \"selected\" ), 2, \"should be 2 based on URL\" );\n\tstate( element, 0, 0, 1 );\n\telement.tabs( \"destroy\" );\n\n\tel = $('#tabs1').tabs({\n\t\tselected: -1,\n\t\tcollapsible: true\n\t});\n\tstate( element, 0, 0, 0 );\n\tequal( element.find( \".ui-tabs-nav .ui-state-active\" ).length, 0, \"no tabs selected\" );\n\tstrictEqual( element.tabs( \"option\", \"selected\" ), -1 );\n\n\telement.tabs( \"option\", \"collapsible\", false );\n\tstate( element, 1, 0, 0 );\n\tequal( element.tabs( \"option\", \"selected\" ), 0 );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({\n\t\tselected: -1\n\t});\n\tstate( element, 1, 0, 0 );\n\tstrictEqual( element.tabs( \"option\", \"selected\" ), 0 );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({ selected: 2 });\n\tequal( element.tabs( \"option\", \"selected\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.tabs( \"option\", \"selected\", 0 );\n\tequal( element.tabs( \"option\", \"selected\" ), 0 );\n\tstate( element, 1, 0, 0 );\n\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 1 ).click();\n\tequal( element.tabs( \"option\", \"selected\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.tabs( \"option\", \"selected\", 10 );\n\tequal( element.tabs( \"option\", \"selected\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\tlocation.hash = \"#\";\n});\n\nmodule( \"tabs (deprecated): events\" );\n\nasyncTest( \"load\", function() {\n\texpect( 15 );\n\n\tvar tab, anchor, panelId, panel,\n\t\telement = $( \"#tabs2\" );\n\n\t// init\n\telement.one( \"tabsload\", function( event, ui ) {\n\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 2 );\n\t\tanchor = tab.find( \".ui-tabs-anchor\" );\n\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\tpanel = $( \"#\" + panelId );\n\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tstrictEqual( ui.tab, anchor[ 0 ], \"tab\" );\n\t\tstrictEqual( ui.panel, panel[ 0 ], \"panel\" );\n\t\tequal( $( ui.panel ).find( \"p\" ).length, 1, \"panel html\" );\n\t\tstate( element, 0, 0, 1, 0, 0 );\n\t\ttabsload1();\n\t});\n\telement.tabs({ active: 2 });\n\n\tfunction tabsload1() {\n\t\t// .option()\n\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 3 );\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" );\n\t\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\t\tstrictEqual( ui.tab, anchor[ 0 ], \"tab\" );\n\t\t\tstrictEqual( ui.panel, panel[ 0 ], \"panel\" );\n\t\t\tequal( $( ui.panel ).find( \"p\" ).length, 1, \"panel html\" );\n\t\t\tstate( element, 0, 0, 0, 1, 0 );\n\t\t\ttabsload2();\n\t\t});\n\t\telement.tabs( \"option\", \"active\", 3 );\n\t}\n\n\tfunction tabsload2() {\n\t\t// click, change panel content\n\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 4 );\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" );\n\t\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\t\tstrictEqual( ui.tab, anchor[ 0 ], \"tab\" );\n\t\t\tstrictEqual( ui.panel, panel[ 0 ], \"panel\" );\n\t\t\tequal( $( ui.panel ).find( \"p\" ).length, 1, \"panel html\" );\n\t\t\tstate( element, 0, 0, 0, 0, 1 );\n\t\t\tstart();\n\t\t});\n\t\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 4 ).click();\n\t}\n});\n\ntest( \"enable\", function() {\n\texpect( 3 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tdisabled: [ 0, 1 ],\n\t\tenable: function( event, ui ) {\n\t\t\tequal( ui.tab, element.find( \".ui-tabs-nav .ui-tabs-anchor\" )[ 1 ], \"ui.tab\" );\n\t\t\tequal( ui.panel, element.find( \".ui-tabs-panel\" )[ 1 ], \"ui.panel\" );\n\t\t\tequal( ui.index, 1, \"ui.index\" );\n\t\t}\n\t});\n\telement.tabs( \"enable\", 1 );\n\t// shouldn't trigger event\n\telement.tabs( \"enable\", 2 );\n});\n\ntest( \"disable\", function() {\n\texpect( 3 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tdisable: function( event, ui ) {\n\t\t\tequal( ui.tab, element.find( \".ui-tabs-nav .ui-tabs-anchor\" )[ 1 ], \"ui.tab\" );\n\t\t\tequal( ui.panel, element.find( \".ui-tabs-panel\" )[ 1 ], \"ui.panel\" );\n\t\t\tequal( ui.index, 1, \"ui.index\" );\n\t\t}\n\t});\n\telement.tabs( \"disable\", 1 );\n\t// shouldn't trigger event\n\telement.tabs( \"disable\", 1 );\n});\n\n\ntest( \"show\", function() {\n\texpect( 13 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\tanchors = element.find( \".ui-tabs-nav .ui-tabs-anchor\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" );\n\n\t// from collapsed\n\telement.one( \"tabsshow\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tstrictEqual( ui.tab, anchors[ 0 ], \"ui.tab\" );\n\t\tstrictEqual( ui.panel, panels[ 0 ], \"ui.panel\" );\n\t\tequal( ui.index, 0, \"ui.index\" );\n\t\tstate( element, 1, 0, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", 0 );\n\tstate( element, 1, 0, 0 );\n\n\t// switching tabs\n\telement.one( \"tabsshow\", function( event, ui ) {\n\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\tstrictEqual( ui.tab, anchors[ 1 ], \"ui.tab\" );\n\t\tstrictEqual( ui.panel, panels[ 1 ], \"ui.panel\" );\n\t\tequal( ui.index, 1, \"ui.index\" );\n\t\tstate( element, 0, 1, 0 );\n\t});\n\tanchors.eq( 1 ).click();\n\tstate( element, 0, 1, 0 );\n\n\t// collapsing\n\telement.one( \"tabsshow\", function( event, ui ) {\n\t\tok( false, \"collapsing\" );\n\t});\n\telement.tabs( \"option\", \"active\", false );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"select\", function() {\n\texpect( 13 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\tanchors = element.find( \".ui-tabs-nav .ui-tabs-anchor\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" );\n\n\t// from collapsed\n\telement.one( \"tabsselect\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tstrictEqual( ui.tab, anchors[ 0 ], \"ui.tab\" );\n\t\tstrictEqual( ui.panel, panels[ 0 ], \"ui.panel\" );\n\t\tequal( ui.index, 0, \"ui.index\" );\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", 0 );\n\tstate( element, 1, 0, 0 );\n\n\t// switching tabs\n\telement.one( \"tabsselect\", function( event, ui ) {\n\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\tstrictEqual( ui.tab, anchors[ 1 ], \"ui.tab\" );\n\t\tstrictEqual( ui.panel, panels[ 1 ], \"ui.panel\" );\n\t\tequal( ui.index, 1, \"ui.index\" );\n\t\tstate( element, 1, 0, 0 );\n\t});\n\tanchors.eq( 1 ).click();\n\tstate( element, 0, 1, 0 );\n\n\t// collapsing\n\telement.one( \"tabsselect\", function( event, ui ) {\n\t\tok( false, \"collapsing\" );\n\t});\n\telement.tabs( \"option\", \"active\", false );\n\tstate( element, 0, 0, 0 );\n});\n\nmodule( \"tabs (deprecated): methods\" );\n\ntest( \"add\", function() {\n\texpect( 28 );\n\n\tvar tab, anchor,\n\t\telement = $( \"#tabs1\" ).tabs();\n\n\tfunction stripLeadingSlash( str ) {\n\t\treturn str.substr( str.charAt( 0 ) === \"/\" ? 1 : 0 );\n\t}\n\n\tstate( element, 1, 0, 0 );\n\n\t// add without index\n\telement.one( \"tabsadd\", function( event, ui ) {\n\t\tequal( ui.index, 3, \"ui.index\" );\n\t\tequal( $( ui.tab ).text(), \"New\", \"ui.tab\" );\n\t\tequal( ui.panel.id, \"new\", \"ui.panel\" );\n\t});\n\telement.tabs( \"add\", \"#new\", \"New\" );\n\tstate( element, 1, 0, 0, 0 );\n\ttab = element.find( \".ui-tabs-nav li\" ).last();\n\tanchor = tab.find( \".ui-tabs-anchor\" );\n\tequal( tab.text(), \"New\", \"label\" );\n\tequal( stripLeadingSlash( anchor[0].pathname ), stripLeadingSlash( location.pathname ), \"href pathname\" );\n\tequal( anchor[0].hash, \"#new\", \"href hash\" );\n\tequal( tab.attr( \"aria-controls\" ), \"new\", \"aria-controls\" );\n\tok( !tab.hasClass( \"ui-state-hover\" ), \"not hovered\" );\n\tanchor.simulate( \"mouseover\" );\n\tok( tab.hasClass( \"ui-state-hover\" ), \"hovered\" );\n\tanchor.simulate( \"click\" );\n\tstate( element, 0, 0, 0, 1 );\n\n\t// add remote tab with index\n\telement.one( \"tabsadd\", function( event, ui ) {\n\t\tequal( ui.index, 1, \"ui.index\" );\n\t\tequal( $( ui.tab ).text(), \"New Remote\", \"ui.tab\" );\n\t\tequal( ui.panel.id, $( ui.tab ).closest( \"li\" ).attr( \"aria-controls\" ), \"ui.panel\" );\n\t});\n\telement.tabs( \"add\", \"data/test.html\", \"New Remote\", 1 );\n\tstate( element, 0, 0, 0, 0, 1 );\n\ttab = element.find( \".ui-tabs-nav li\" ).eq( 1 );\n\tanchor = tab.find( \".ui-tabs-anchor\" );\n\tequal( tab.text(), \"New Remote\", \"label\" );\n\tequal( stripLeadingSlash( stripLeadingSlash(\n\t\tanchor[0].pathname.replace( stripLeadingSlash( location.pathname ).split( \"/\" ).slice( 0, -1 ).join( \"/\" ), \"\" )\n\t) ), \"data/test.html\", \"href\" );\n\tok( /^ui-tabs-\\d+$/.test( tab.attr( \"aria-controls\" ) ), \"aria controls\" );\n\tok( !tab.hasClass( \"ui-state-hover\" ), \"not hovered\" );\n\tanchor.simulate( \"mouseover\" );\n\tok( tab.hasClass( \"ui-state-hover\" ), \"hovered\" );\n\tanchor.simulate( \"click\" );\n\tstate( element, 0, 1, 0, 0, 0 );\n\n\t// add to empty tab set\n\telement = $( \"<div><ul></ul></div>\" ).tabs();\n\tequal( element.tabs( \"option\", \"active\" ), false, \"active: false on init\" );\n\telement.one( \"tabsadd\", function( event, ui ) {\n\t\tequal( ui.index, 0, \"ui.index\" );\n\t\tequal( $( ui.tab ).text(), \"First\", \"ui.tab\" );\n\t\tequal( ui.panel.id, \"first\", \"ui.panel\" );\n\t});\n\telement.tabs( \"add\", \"#first\", \"First\" );\n\tstate( element, 1 );\n\tequal( element.tabs( \"option\", \"active\" ), 0, \"active: 0 after add\" );\n});\n\ntest( \"#5069 - ui.tabs.add creates two tab panels when using a full URL\", function() {\n\texpect( 2 );\n\n\tvar element = $( \"#tabs2\" ).tabs();\n\tequal( element.children( \"div\" ).length, element.find( \".ui-tabs-nav li\" ).length );\n\telement.tabs( \"add\", \"/new\", \"New\" );\n\tequal( element.children( \"div\" ).length, element.find( \".ui-tabs-nav li\" ).length );\n});\n\ntest( \"remove\", function() {\n\texpect( 17 );\n\n\tvar element = $( \"#tabs1\" ).tabs({ active: 1 });\n\tstate( element, 0, 1, 0 );\n\n\telement.one( \"tabsremove\", function( event, ui ) {\n\t\tequal( ui.index, -1, \"ui.index\" );\n\t\tequal( $( ui.tab ).text(), \"2\", \"ui.tab\" );\n\t\tequal( ui.panel.id, \"fragment-2\", \"ui.panel\" );\n\t});\n\telement.tabs( \"remove\", 1 );\n\tstate( element, 0, 1 );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tequal( element.find( \".ui-tabs-nav li a[href$='fragment-2']\" ).length, 0,\n\t\t\"remove correct list item\" );\n\tequal( element.find( \"#fragment-2\" ).length, 0, \"remove correct panel\" );\n\n\telement.one( \"tabsremove\", function( event, ui ) {\n\t\tequal( ui.index, -1, \"ui.index\" );\n\t\tequal( $( ui.tab ).text(), \"3\", \"ui.tab\" );\n\t\tequal( ui.panel.id, \"fragment-3\", \"ui.panel\" );\n\t});\n\telement.tabs( \"remove\", 1 );\n\tstate( element, 1 );\n\tequal( element.tabs( \"option\", \"active\"), 0 );\n\n\telement.one( \"tabsremove\", function( event, ui ) {\n\t\tequal( ui.index, -1, \"ui.index\" );\n\t\tequal( $( ui.tab ).text(), \"1\", \"ui.tab\" );\n\t\tequal( ui.panel.id, \"fragment-1\", \"ui.panel\" );\n\t});\n\telement.tabs( \"remove\", 0 );\n\tequal( element.tabs( \"option\", \"active\" ), false );\n});\n\ntest( \"select\", function() {\n\texpect( 23 );\n\n\tvar element = $( \"#tabs1\" ).tabs();\n\tstate( element, 1, 0, 0 );\n\telement.tabs( \"select\", 1 );\n\tstate( element, 0, 1, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 1, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), 1, \"selected\" );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({ collapsible: true });\n\tstate( element, 1, 0, 0 );\n\telement.tabs( \"select\", 0 );\n\tstate( element, 0, 0, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), false, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), -1, \"selected\" );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({ collapsible: true });\n\telement.tabs( \"select\", -1 );\n\tstate( element, 0, 0, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), false, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), -1, \"selected\" );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs();\n\tstate( element, 1, 0, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 0, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), 0, \"selected\" );\n\telement.tabs( \"select\", 0 );\n\tstate( element, 1, 0, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 0, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), 0, \"selected\" );\n\telement.tabs( \"select\", -1 );\n\tstate( element, 1, 0, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 0, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), 0, \"selected\" );\n\n\telement.tabs( \"select\", \"#fragment-2\" );\n\tstate( element, 0, 1, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 1, \"active\" );\n\tequal( element.tabs( \"option\", \"selected\" ), 1, \"selected\" );\n});\n\ntest( \"length\", function() {\n\texpect( 2 );\n\n\tequal( $( \"#tabs1\" ).tabs().tabs( \"length\" ), 3, \"basic tabs\" );\n\tequal( $( \"#tabs2\" ).tabs().tabs( \"length\" ), 5, \"ajax tabs with missing panels\" );\n});\n\ntest( \"url\", function() {\n\texpect( 2 );\n\n\tvar element = $( \"#tabs2\" ).tabs(),\n\t\tanchor = element.find( \".ui-tabs-anchor\" ).eq( 3 );\n\n\telement.tabs( \"url\", 3, \"data/test2.html\" );\n\tequal( anchor.attr( \"href\" ), \"data/test2.html\", \"href was updated\" );\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\tequal( ui.ajaxSettings.url, \"data/test2.html\", \"ajaxSettings.url\" );\n\t\tevent.preventDefault();\n\t});\n\telement.tabs( \"option\", \"active\", 3 );\n});\n\nasyncTest( \"abort\", function() {\n\texpect( 1 );\n\n\tvar element = $( \"#tabs2\" ).tabs();\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\tui.jqXHR.error(function( jqXHR, status ) {\n\t\t\tequal( status, \"abort\", \"aborted\" );\n\t\t\tstart();\n\t\t});\n\t});\n\t// prevent IE from caching the request, so that it won't resolve before we call abort\n\telement.find( \".ui-tabs-nav li:eq(2) .ui-tabs-anchor\" ).attr( \"href\", function( href ) {\n\t\treturn href + \"?\" + (+ new Date());\n\t});\n\telement.tabs( \"option\", \"active\", 2 );\n\telement.tabs( \"abort\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_events.js",
    "content": "(function( $ ) {\n\nvar state = TestHelpers.tabs.state;\n\nmodule( \"tabs: events\" );\n\ntest( \"create\", function() {\n\texpect( 10 );\n\n\tvar element = $( \"#tabs1\" ),\n\t\ttabs = element.find( \"ul li\" ),\n\t\tpanels = element.children( \"div\" );\n\n\telement.tabs({\n\t\tcreate: function( event, ui ) {\n\t\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\t\tstrictEqual( ui.tab[ 0 ], tabs[ 0 ], \"tab\" );\n\t\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\t\tstrictEqual( ui.panel[ 0 ], panels[ 0 ], \"panel\" );\n\t\t}\n\t});\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({\n\t\tactive: 2,\n\t\tcreate: function( event, ui ) {\n\t\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\t\tstrictEqual( ui.tab[ 0 ], tabs[ 2 ], \"tab\" );\n\t\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\t\tstrictEqual( ui.panel[ 0 ], panels[ 2 ], \"panel\" );\n\t\t}\n\t});\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({\n\t\tactive: false,\n\t\tcollapsible: true,\n\t\tcreate: function( event, ui ) {\n\t\t\tequal( ui.tab.length, 0, \"tab length\" );\n\t\t\tequal( ui.panel.length, 0, \"panel length\" );\n\t\t}\n\t});\n\telement.tabs( \"destroy\" );\n});\n\ntest( \"beforeActivate\", function() {\n\texpect( 38 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\ttabs = element.find( \".ui-tabs-nav li\" ),\n\t\tanchors = tabs.find( \".ui-tabs-anchor\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" );\n\n\t// from collapsed\n\telement.one( \"tabsbeforeactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 0, \"oldTab length\" );\n\t\tequal( ui.oldPanel.length, 0, \"oldPanel length\" );\n\t\tequal( ui.newTab.length, 1, \"newTab length\" );\n\t\tstrictEqual( ui.newTab[ 0 ], tabs[ 0 ], \"newTab\" );\n\t\tequal( ui.newPanel.length, 1, \"newPanel length\" );\n\t\tstrictEqual( ui.newPanel[ 0 ], panels[ 0 ], \"newPanel\" );\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", 0 );\n\tstate( element, 1, 0, 0 );\n\n\t// switching tabs\n\telement.one( \"tabsbeforeactivate\", function( event, ui ) {\n\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 1, \"oldTab length\" );\n\t\tstrictEqual( ui.oldTab[ 0 ], tabs[ 0 ], \"oldTab\" );\n\t\tequal( ui.oldPanel.length, 1, \"oldPanel length\" );\n\t\tstrictEqual( ui.oldPanel[ 0 ], panels[ 0 ], \"oldPanel\" );\n\t\tequal( ui.newTab.length, 1, \"newTab length\" );\n\t\tstrictEqual( ui.newTab[ 0 ], tabs[ 1 ], \"newTab\" );\n\t\tequal( ui.newPanel.length, 1, \"newPanel length\" );\n\t\tstrictEqual( ui.newPanel[ 0 ], panels[ 1 ], \"newPanel\" );\n\t\tstate( element, 1, 0, 0 );\n\t});\n\tanchors.eq( 1 ).click();\n\tstate( element, 0, 1, 0 );\n\n\t// collapsing\n\telement.one( \"tabsbeforeactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 1, \"oldTab length\" );\n\t\tstrictEqual( ui.oldTab[ 0 ], tabs[ 1 ], \"oldTab\" );\n\t\tequal( ui.oldPanel.length, 1, \"oldPanel length\" );\n\t\tstrictEqual( ui.oldPanel[ 0 ], panels[ 1 ], \"oldPanel\" );\n\t\tequal( ui.newTab.length, 0, \"newTab length\" );\n\t\tequal( ui.newPanel.length, 0, \"newPanel length\" );\n\t\tstate( element, 0, 1, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", false );\n\tstate( element, 0, 0, 0 );\n\n\t// prevent activation\n\telement.one( \"tabsbeforeactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 0, \"oldTab length\" );\n\t\tequal( ui.oldPanel.length, 0, \"oldTab\" );\n\t\tequal( ui.newTab.length, 1, \"newTab length\" );\n\t\tstrictEqual( ui.newTab[ 0 ], tabs[ 1 ], \"newTab\" );\n\t\tequal( ui.newPanel.length, 1, \"newPanel length\" );\n\t\tstrictEqual( ui.newPanel[ 0 ], panels[ 1 ], \"newPanel\" );\n\t\tevent.preventDefault();\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", 1 );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"activate\", function() {\n\texpect( 30 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tactive: false,\n\t\t\tcollapsible: true\n\t\t}),\n\t\ttabs = element.find( \".ui-tabs-nav li\" ),\n\t\tanchors = element.find( \".ui-tabs-anchor\" ),\n\t\tpanels = element.find( \".ui-tabs-panel\" );\n\n\t// from collapsed\n\telement.one( \"tabsactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 0, \"oldTab length\" );\n\t\tequal( ui.oldPanel.length, 0, \"oldPanel length\" );\n\t\tequal( ui.newTab.length, 1, \"newTab length\" );\n\t\tstrictEqual( ui.newTab[ 0 ], tabs[ 0 ], \"newTab\" );\n\t\tequal( ui.newPanel.length, 1, \"newPanel length\" );\n\t\tstrictEqual( ui.newPanel[ 0 ], panels[ 0 ], \"newPanel\" );\n\t\tstate( element, 1, 0, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", 0 );\n\tstate( element, 1, 0, 0 );\n\n\t// switching tabs\n\telement.one( \"tabsactivate\", function( event, ui ) {\n\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 1, \"oldTab length\" );\n\t\tstrictEqual( ui.oldTab[ 0 ], tabs[ 0 ], \"oldTab\" );\n\t\tequal( ui.oldPanel.length, 1, \"oldPanel length\" );\n\t\tstrictEqual( ui.oldPanel[ 0 ], panels[ 0 ], \"oldPanel\" );\n\t\tequal( ui.newTab.length, 1, \"newTab length\" );\n\t\tstrictEqual( ui.newTab[ 0 ], tabs[ 1 ], \"newTab\" );\n\t\tequal( ui.newPanel.length, 1, \"newPanel length\" );\n\t\tstrictEqual( ui.newPanel[ 0 ], panels[ 1 ], \"newPanel\" );\n\t\tstate( element, 0, 1, 0 );\n\t});\n\tanchors.eq( 1 ).click();\n\tstate( element, 0, 1, 0 );\n\n\t// collapsing\n\telement.one( \"tabsactivate\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( ui.oldTab.length, 1, \"oldTab length\" );\n\t\tstrictEqual( ui.oldTab[ 0 ], tabs[ 1 ], \"oldTab\" );\n\t\tequal( ui.oldPanel.length, 1, \"oldPanel length\" );\n\t\tstrictEqual( ui.oldPanel[ 0 ], panels[ 1 ], \"oldPanel\" );\n\t\tequal( ui.newTab.length, 0, \"newTab length\" );\n\t\tequal( ui.newPanel.length, 0, \"newPanel length\" );\n\t\tstate( element, 0, 0, 0 );\n\t});\n\telement.tabs( \"option\", \"active\", false );\n\tstate( element, 0, 0, 0 );\n\n\t// prevent activation\n\telement.one( \"tabsbeforeactivate\", function( event ) {\n\t\tok( true, \"tabsbeforeactivate\" );\n\t\tevent.preventDefault();\n\t});\n\telement.one( \"tabsactivate\", function() {\n\t\tok( false, \"tabsactivate\" );\n\t});\n\telement.tabs( \"option\", \"active\", 1 );\n});\n\ntest( \"beforeLoad\", function() {\n\texpect( 32 );\n\n\tvar tab, panelId, panel,\n\t\telement = $( \"#tabs2\" );\n\n\t// init\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 2 );\n\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\tpanel = $( \"#\" + panelId );\n\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tok( \"abort\" in ui.jqXHR, \"jqXHR\" );\n\t\tok( ui.ajaxSettings.url, \"data/test.html\", \"ajaxSettings.url\" );\n\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\tequal( ui.panel.html(), \"\", \"panel html\" );\n\t\tevent.preventDefault();\n\t\tstate( element, 0, 0, 1, 0, 0 );\n\t});\n\telement.tabs({ active: 2 });\n\tstate( element, 0, 0, 1, 0, 0 );\n\tequal( panel.html(), \"\", \"panel html after\" );\n\telement.tabs( \"destroy\" );\n\n\t// .option()\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 2 );\n\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\tpanel = $( \"#\" + panelId );\n\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tok( \"abort\" in ui.jqXHR, \"jqXHR\" );\n\t\tok( ui.ajaxSettings.url, \"data/test.html\", \"ajaxSettings.url\" );\n\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\tequal( ui.panel.html(), \"\", \"panel html\" );\n\t\tevent.preventDefault();\n\t\tstate( element, 1, 0, 0, 0, 0 );\n\t});\n\telement.tabs();\n\telement.tabs( \"option\", \"active\", 2 );\n\tstate( element, 0, 0, 1, 0, 0 );\n\tequal( panel.html(), \"\", \"panel html after\" );\n\n\t// click, change panel content\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 3 );\n\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\tpanel = $( \"#\" + panelId );\n\n\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\tok( \"abort\" in ui.jqXHR, \"jqXHR\" );\n\t\tok( ui.ajaxSettings.url, \"data/test.html\", \"ajaxSettings.url\" );\n\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\tui.panel.html( \"<p>testing</p>\" );\n\t\tevent.preventDefault();\n\t\tstate( element, 0, 0, 1, 0, 0 );\n\t});\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 3 ).click();\n\tstate( element, 0, 0, 0, 1, 0 );\n\t// .toLowerCase() is needed to convert <P> to <p> in old IEs\n\tequal( panel.html().toLowerCase(), \"<p>testing</p>\", \"panel html after\" );\n});\n\nif ( $.uiBackCompat === false ) {\n\tasyncTest( \"load\", function() {\n\t\texpect( 21 );\n\n\t\tvar tab, panelId, panel,\n\t\t\telement = $( \"#tabs2\" );\n\n\t\t// init\n\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 2 );\n\t\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\t\tequal( ui.panel.find( \"p\" ).length, 1, \"panel html\" );\n\t\t\tstate( element, 0, 0, 1, 0, 0 );\n\t\t\ttabsload1();\n\t\t});\n\t\telement.tabs({ active: 2 });\n\n\t\tfunction tabsload1() {\n\t\t\t// .option()\n\t\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 3 );\n\t\t\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\t\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\t\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\t\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\t\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\t\t\tequal( ui.panel.find( \"p\" ).length, 1, \"panel html\" );\n\t\t\t\tstate( element, 0, 0, 0, 1, 0 );\n\t\t\t\ttabsload2();\n\t\t\t});\n\t\t\telement.tabs( \"option\", \"active\", 3 );\n\t\t}\n\n\t\tfunction tabsload2() {\n\t\t\t// click, change panel content\n\t\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 4 );\n\t\t\t\tpanelId = tab.attr( \"aria-controls\" );\n\t\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\t\tequal( event.originalEvent.type, \"click\", \"originalEvent\" );\n\t\t\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\t\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\t\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\t\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\t\t\tequal( ui.panel.find( \"p\" ).length, 1, \"panel html\" );\n\t\t\t\tstate( element, 0, 0, 0, 0, 1 );\n\t\t\t\tstart();\n\t\t\t});\n\t\t\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 4 ).click();\n\t\t}\n\t});\n}\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_methods.js",
    "content": "(function( $ ) {\n\nvar disabled = TestHelpers.tabs.disabled,\n\tstate = TestHelpers.tabs.state;\n\nmodule( \"tabs: methods\" );\n\ntest( \"destroy\", function() {\n\tdomEqual( \"#tabs1\", function() {\n\t\t$( \"#tabs1\" ).tabs().tabs( \"destroy\" );\n\t});\n});\n\ntest( \"enable\", function() {\n\texpect( 8 );\n\n\tvar element = $( \"#tabs1\" ).tabs({ disabled: true });\n\tdisabled( element, true );\n\telement.tabs( \"enable\" );\n\tdisabled( element, false );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({ disabled: [ 0, 1 ] });\n\tdisabled( element, [ 0, 1 ] );\n\telement.tabs( \"enable\" );\n\tdisabled( element, false );\n});\n\ntest( \"enable( index )\", function() {\n    expect( 10 );\n\n\tvar element = $( \"#tabs1\" ).tabs({ disabled: true });\n\tdisabled( element, true );\n\t// fully disabled -> partially disabled\n\telement.tabs( \"enable\", 1 );\n\tdisabled( element, [ 0, 2 ] );\n\t// partially disabled -> partially disabled\n\telement.tabs( \"enable\", 2 );\n\tdisabled( element, [ 0 ] );\n\t// already enabled tab, no change\n\telement.tabs( \"enable\", 2 );\n\tdisabled( element, [ 0 ] );\n\t// partially disabled -> fully enabled\n\telement.tabs( \"enable\", 0 );\n\tdisabled( element, false );\n});\n\ntest( \"disable\", function() {\n\texpect( 8 );\n\n\tvar element = $( \"#tabs1\" ).tabs({ disabled: false });\n\tdisabled( element, false );\n\telement.tabs( \"disable\" );\n\tdisabled( element, true );\n\telement.tabs( \"destroy\" );\n\n\telement.tabs({ disabled: [ 0, 1 ] });\n\tdisabled( element, [ 0, 1 ] );\n\telement.tabs( \"disable\" );\n\tdisabled( element, true );\n});\n\ntest( \"disable( index )\", function() {\n    expect( 10 );\n\n\tvar element = $( \"#tabs1\" ).tabs({ disabled: false });\n\tdisabled( element, false );\n\t// fully enabled -> partially disabled\n\telement.tabs( \"disable\", 1 );\n\tdisabled( element, [ 1 ] );\n\t// partially disabled -> partially disabled\n\telement.tabs( \"disable\", 2 );\n\tdisabled( element, [ 1, 2 ] );\n\t// already disabled tab, no change\n\telement.tabs( \"disable\", 2 );\n\tdisabled( element, [ 1, 2 ] );\n\t// partially disabled -> fully disabled\n\telement.tabs( \"disable\", 0 );\n\tdisabled( element, true );\n});\n\ntest( \"refresh\", function() {\n\texpect( 27 );\n\n\tvar element = $( \"#tabs1\" ).tabs();\n\tstate( element, 1, 0, 0 );\n\tdisabled( element, false );\n\n\t// disable tab via markup\n\telement.find( \".ui-tabs-nav li\" ).eq( 1 ).addClass( \"ui-state-disabled\" );\n\telement.tabs( \"refresh\" );\n\tstate( element, 1, 0, 0 );\n\tdisabled( element, [ 1 ] );\n\n\t// add remote tab\n\telement.find( \".ui-tabs-nav\" ).append( \"<li id='newTab'><a href='data/test.html'>new</a></li>\" );\n\telement.tabs( \"refresh\" );\n\tstate( element, 1, 0, 0, 0 );\n\tdisabled( element, [ 1 ] );\n\tequal( element.find( \"#\" + $( \"#newTab\" ).attr( \"aria-controls\" ) ).length, 1,\n\t\t\"panel added for remote tab\" );\n\n\t// remove all tabs\n\telement.find( \".ui-tabs-nav li, .ui-tabs-panel\" ).remove();\n\telement.tabs( \"refresh\" );\n\tstate( element );\n\tequal( element.tabs( \"option\", \"active\" ), false, \"no active tab\" );\n\n\t// add tabs\n\telement.find( \".ui-tabs-nav\" )\n\t\t.append( \"<li class='ui-state-disabled'><a href='#newTab2'>new 2</a></li>\" )\n\t\t.append( \"<li><a href='#newTab3'>new 3</a></li>\" )\n\t\t.append( \"<li><a href='#newTab4'>new 4</a></li>\" )\n\t\t.append( \"<li><a href='#newTab5'>new 5</a></li>\" );\n\telement\n\t\t.append( \"<div id='newTab2'>new 2</div>\" )\n\t\t.append( \"<div id='newTab3'>new 3</div>\" )\n\t\t.append( \"<div id='newTab4'>new 4</div>\" )\n\t\t.append( \"<div id='newTab5'>new 5</div>\" );\n\telement.tabs( \"refresh\" );\n\tstate( element, 0, 0, 0, 0 );\n\tdisabled( element, [ 0 ] );\n\n\t// activate third tab\n\telement.tabs( \"option\", \"active\", 2 );\n\tstate( element, 0, 0, 1, 0 );\n\tdisabled( element, [ 0 ] );\n\n\t// remove fourth tab, third tab should stay active\n\telement.find( \".ui-tabs-nav li\" ).eq( 3 ).remove();\n\telement.find( \".ui-tabs-panel\" ).eq( 3 ).remove();\n\telement.tabs( \"refresh\" );\n\tstate( element, 0, 0, 1 );\n\tdisabled( element, [ 0 ] );\n\n\t// remove third (active) tab, second tab should become active\n\telement.find( \".ui-tabs-nav li\" ).eq( 2 ).remove();\n\telement.find( \".ui-tabs-panel\" ).eq( 2 ).remove();\n\telement.tabs( \"refresh\" );\n\tstate( element, 0, 1 );\n\tdisabled( element, [ 0 ] );\n\n\t// remove first tab, previously active tab (now first) should stay active\n\telement.find( \".ui-tabs-nav li\" ).eq( 0 ).remove();\n\telement.find( \".ui-tabs-panel\" ).eq( 0 ).remove();\n\telement.tabs( \"refresh\" );\n\tstate( element, 1 );\n\tdisabled( element, false );\n});\n\ntest( \"refresh - looping\", function() {\n\texpect( 6 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tdisabled: [ 0 ],\n\t\tactive: 1\n\t});\n\tstate( element, 0, 1, 0 );\n\tdisabled( element, [ 0 ] );\n\n\t// remove active, jump to previous\n\t// previous is disabled, just back one more\n\t// reached first tab, move to end\n\t// activate last tab\n\telement.find( \".ui-tabs-nav li\" ).eq( 2 ).remove();\n\telement.tabs( \"refresh\" );\n\tstate( element, 0, 1 );\n\tdisabled( element, [ 0 ] );\n});\n\nasyncTest( \"load\", function() {\n\texpect( 30 );\n\n\tvar element = $( \"#tabs2\" ).tabs();\n\n\t// load content of inactive tab\n\t// useful for preloading content with custom caching\n\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\tvar tab = element.find( \".ui-tabs-nav li\" ).eq( 3 ),\n\t\t\tpanelId = tab.attr( \"aria-controls\" ),\n\t\t\tpanel = $( \"#\" + panelId );\n\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\tstate( element, 1, 0, 0, 0, 0 );\n\t});\n\telement.one( \"tabsload\", function( event, ui ) {\n\t\t// TODO: remove wrapping in 2.0\n\t\tvar uiTab = $( ui.tab ),\n\t\t\tuiPanel = $( ui.panel ),\n\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 3 ),\n\t\t\tpanelId = tab.attr( \"aria-controls\" ),\n\t\t\tpanel = $( \"#\" + panelId );\n\n\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\tequal( uiTab.length, 1, \"tab length\" );\n\t\tif ( $.uiBackCompat === false ) {\n\t\t\tstrictEqual( uiTab[ 0 ], tab[ 0 ], \"tab\" );\n\t\t} else {\n\t\t\tstrictEqual( uiTab[ 0 ], tab.find( \".ui-tabs-anchor\" )[ 0 ], \"tab\" );\n\t\t}\n\t\tequal( uiPanel.length, 1, \"panel length\" );\n\t\tstrictEqual( uiPanel[ 0 ], panel[ 0 ], \"panel\" );\n\t\tequal( uiPanel.find( \"p\" ).length, 1, \"panel html\" );\n\t\tstate( element, 1, 0, 0, 0, 0 );\n\t\tsetTimeout( tabsload1, 100 );\n\t});\n\telement.tabs( \"load\", 3 );\n\tstate( element, 1, 0, 0, 0, 0 );\n\n\tfunction tabsload1() {\n\t\t// no need to test details of event (tested in events tests)\n\t\telement.one( \"tabsbeforeload\", function() {\n\t\t\tok( true, \"tabsbeforeload invoked\" );\n\t\t});\n\t\telement.one( \"tabsload\", function() {\n\t\t\tok( true, \"tabsload invoked\" );\n\t\t\tsetTimeout( tabsload2, 100 );\n\t\t});\n\t\telement.tabs( \"option\", \"active\", 3 );\n\t\tstate( element, 0, 0, 0, 1, 0 );\n\t}\n\n\tfunction tabsload2() {\n\t\t// reload content of active tab\n\t\telement.one( \"tabsbeforeload\", function( event, ui ) {\n\t\t\tvar tab = element.find( \".ui-tabs-nav li\" ).eq( 3 ),\n\t\t\t\tpanelId = tab.attr( \"aria-controls\" ),\n\t\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\t\tequal( ui.tab.length, 1, \"tab length\" );\n\t\t\tstrictEqual( ui.tab[ 0 ], tab[ 0 ], \"tab\" );\n\t\t\tequal( ui.panel.length, 1, \"panel length\" );\n\t\t\tstrictEqual( ui.panel[ 0 ], panel[ 0 ], \"panel\" );\n\t\t\tstate( element, 0, 0, 0, 1, 0 );\n\t\t});\n\t\telement.one( \"tabsload\", function( event, ui ) {\n\t\t\t// TODO: remove wrapping in 2.0\n\t\t\tvar uiTab = $( ui.tab ),\n\t\t\t\tuiPanel = $( ui.panel ),\n\t\t\t\ttab = element.find( \".ui-tabs-nav li\" ).eq( 3 ),\n\t\t\t\tpanelId = tab.attr( \"aria-controls\" ),\n\t\t\t\tpanel = $( \"#\" + panelId );\n\n\t\t\tok( !( \"originalEvent\" in event ), \"originalEvent\" );\n\t\t\tequal( uiTab.length, 1, \"tab length\" );\n\t\t\tif ( $.uiBackCompat === false ) {\n\t\t\t\tstrictEqual( uiTab[ 0 ], tab[ 0 ], \"tab\" );\n\t\t\t} else {\n\t\t\t\tstrictEqual( uiTab[ 0 ], tab.find( \".ui-tabs-anchor\" )[ 0 ], \"tab\" );\n\t\t\t}\n\t\t\tequal( uiPanel.length, 1, \"panel length\" );\n\t\t\tstrictEqual( uiPanel[ 0 ], panel[ 0 ], \"panel\" );\n\t\t\tstate( element, 0, 0, 0, 1, 0 );\n\t\t\tstart();\n\t\t});\n\t\telement.tabs( \"load\", 3 );\n\t\tstate( element, 0, 0, 0, 1, 0 );\n\t}\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_options.js",
    "content": "(function( $ ) {\n\nvar disabled = TestHelpers.tabs.disabled,\n\tequalHeight = TestHelpers.tabs.equalHeight,\n\tstate = TestHelpers.tabs.state;\n\nmodule( \"tabs: options\" );\n\ntest( \"{ active: default }\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#tabs1\" ).tabs();\n\tequal( element.tabs( \"option\", \"active\" ), 0, \"should be 0 by default\" );\n\tstate( element, 1, 0, 0 );\n\telement.tabs( \"destroy\" );\n\n\tlocation.hash = \"#fragment-3\";\n\telement = $( \"#tabs1\" ).tabs();\n\tequal( element.tabs( \"option\", \"active\" ), 2, \"should be 2 based on URL\" );\n\tstate( element, 0, 0, 1 );\n\telement.tabs( \"destroy\" );\n\tlocation.hash = \"#\";\n});\n\ntest( \"{ active: false }\", function() {\n\texpect( 7 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tactive: false,\n\t\tcollapsible: true\n\t});\n\tstate( element, 0, 0, 0 );\n\tequal( element.find( \".ui-tabs-nav .ui-state-active\" ).length, 0, \"no tabs selected\" );\n\tstrictEqual( element.tabs( \"option\", \"active\" ), false );\n\n\telement.tabs( \"option\", \"collapsible\", false );\n\tstate( element, 1, 0, 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 0 );\n\n\telement.tabs( \"destroy\" );\n\telement.tabs({\n\t\tactive: false\n\t});\n\tstate( element, 1, 0, 0 );\n\tstrictEqual( element.tabs( \"option\", \"active\" ), 0 );\n});\n\ntest( \"{ active: Number }\", function() {\n\texpect( 8 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tactive: 2\n\t});\n\tequal( element.tabs( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.tabs( \"option\", \"active\", 0 );\n\tequal( element.tabs( \"option\", \"active\" ), 0 );\n\tstate( element, 1, 0, 0 );\n\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 1 ).click();\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.tabs( \"option\", \"active\", 10 );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\nif ( $.uiBackCompat === false ) {\n\ttest( \"{ active: -Number }\", function() {\n\t\tvar element = $( \"#tabs1\" ).tabs({\n\t\t\tactive: -1\n\t\t});\n\t\tequal( element.tabs( \"option\", \"active\" ), 2 );\n\t\tstate( element, 0, 0, 1 );\n\n\t\telement.tabs( \"option\", \"active\", -2 );\n\t\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\t\tstate( element, 0, 1, 0 );\n\n\t\telement.tabs( \"option\", \"active\", -10 );\n\t\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\t\tstate( element, 0, 1, 0 );\n\n\t\telement.tabs( \"option\", \"active\", -3 );\n\t\tequal( element.tabs( \"option\", \"active\" ), 0 );\n\t\tstate( element, 1, 0, 0 );\n\t});\n}\n\ntest( \"active - mismatched tab/panel order\", function() {\n\texpect( 3 );\n\n\tlocation.hash = \"#tabs7-2\";\n\tvar element = $( \"#tabs7\" ).tabs();\n\tequal( element.tabs( \"option\", \"active\" ), 1, \"should be 1 based on URL\" );\n\tstate( element, 0, 1 );\n\telement.tabs( \"option\", \"active\", 0 );\n\tstate( element, 1, 0 );\n\tlocation.hash = \"#\";\n});\n\ntest( \"{ collapsible: false }\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tactive: 1\n\t});\n\telement.tabs( \"option\", \"active\", false );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.find( \".ui-state-active .ui-tabs-anchor\" ).eq( 1 ).click();\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ collapsible: true }\", function() {\n\texpect( 6 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tactive: 1,\n\t\tcollapsible: true\n\t});\n\n\telement.tabs( \"option\", \"active\", false );\n\tequal( element.tabs( \"option\", \"active\" ), false );\n\tstate( element, 0, 0, 0 );\n\n\telement.tabs( \"option\", \"active\", 1 );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.find( \".ui-state-active .ui-tabs-anchor\" ).click();\n\tequal( element.tabs( \"option\", \"active\" ), false );\n\tstate( element, 0, 0, 0 );\n});\n\ntest( \"disabled\", function() {\n\texpect( 10 );\n\n\t// fully enabled by default\n\tvar element = $( \"#tabs1\" ).tabs();\n\tdisabled( element, false );\n\n\t// disable single tab\n\telement.tabs( \"option\", \"disabled\", [ 1 ] );\n\tdisabled( element, [ 1 ] );\n\n\t// disabled active tab\n\telement.tabs( \"option\", \"disabled\", [ 0, 1 ] );\n\tdisabled( element, [ 0, 1 ] );\n\n\t// disable all tabs\n\telement.tabs( \"option\", \"disabled\", [ 0, 1, 2 ] );\n\tdisabled( element, true );\n\n\t// enable all tabs\n\telement.tabs( \"option\", \"disabled\", [] );\n\tdisabled( element, false );\n});\n\ntest( \"{ event: null }\", function() {\n\texpect( 5 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tevent: null\n\t});\n\tstate( element, 1, 0, 0 );\n\n\telement.tabs( \"option\", \"active\", 1 );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\t// ensure default click handler isn't bound\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 2 ).click();\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ event: custom }\", function() {\n\texpect( 11 );\n\n\tvar element = $( \"#tabs1\" ).tabs({\n\t\tevent: \"custom1 custom2\"\n\t});\n\tstate( element, 1, 0, 0 );\n\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 1 ).trigger( \"custom1\" );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\t// ensure default click handler isn't bound\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 2 ).trigger( \"click\" );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 2 ).trigger( \"custom2\" );\n\tequal( element.tabs( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.tabs( \"option\", \"event\", \"custom3\" );\n\n\t// ensure old event handlers are unbound\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 1 ).trigger( \"custom1\" );\n\tequal( element.tabs( \"option\", \"active\" ), 2 );\n\tstate( element, 0, 0, 1 );\n\n\telement.find( \".ui-tabs-nav .ui-tabs-anchor\" ).eq( 1 ).trigger( \"custom3\" );\n\tequal( element.tabs( \"option\", \"active\" ), 1 );\n\tstate( element, 0, 1, 0 );\n});\n\ntest( \"{ heightStyle: 'auto' }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#tabs8\" ).tabs({ heightStyle: \"auto\" });\n\tequalHeight( element, 45 );\n});\n\ntest( \"{ heightStyle: 'content' }\", function() {\n\texpect( 2 );\n\tvar element = $( \"#tabs8\" ).tabs({ heightStyle: \"content\" }),\n\t\tsizes = element.find( \".ui-tabs-panel\" ).map(function() {\n\t\t\treturn $( this ).height();\n\t\t}).get();\n\tequal( sizes[ 0 ], 45 );\n\tequal( sizes[ 1 ], 15 );\n});\n\ntest( \"{ heightStyle: 'fill' }\", function() {\n\texpect( 2 );\n\t$( \"#tabs8Wrapper\" ).height( 500 );\n\tvar element = $( \"#tabs8\" ).tabs({ heightStyle: \"fill\" });\n\tequalHeight( element, 485 );\n});\n\ntest( \"{ heightStyle: 'fill' } with sibling\", function() {\n\texpect( 2 );\n\t$( \"#tabs8Wrapper\" ).height( 500 );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30\n\t\t})\n\t\t.prependTo( \"#tabs8Wrapper\" );\n\tvar element = $( \"#tabs8\" ).tabs({ heightStyle: \"fill\" });\n\tequalHeight( element, 385 );\n});\n\ntest( \"{ heightStyle: 'fill' } with multiple siblings\", function() {\n\texpect( 2 );\n\t$( \"#tabs8Wrapper\" ).height( 500 );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30\n\t\t})\n\t\t.prependTo( \"#tabs8Wrapper\" );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 50,\n\t\t\tmarginTop: 20,\n\t\t\tmarginBottom: 30,\n\t\t\tposition: \"absolute\"\n\t\t})\n\t\t.prependTo( \"#tabs8Wrapper\" );\n\t$( \"<p>Lorem Ipsum</p>\" )\n\t\t.css({\n\t\t\theight: 25,\n\t\t\tmarginTop: 10,\n\t\t\tmarginBottom: 15\n\t\t})\n\t\t.prependTo( \"#tabs8Wrapper\" );\n\tvar element = $( \"#tabs8\" ).tabs({ heightStyle: \"fill\" });\n\tequalHeight( element, 335 );\n});\n\n// TODO: add animation tests\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tabs/tabs_test_helpers.js",
    "content": "TestHelpers.tabs = {\n\tdisabled: function( tabs, state ) {\n\t\tvar expected, actual,\n\t\t\tinternalState = tabs.tabs( \"option\", \"disabled\" );\n\n\t\tif ( internalState === false ) {\n\t\t\tinternalState = [];\n\t\t}\n\t\tif ( internalState === true ) {\n\t\t\tinternalState = $.map( new Array( tabs.find( \".ui-tabs-nav li\" ).length ), function( _, index ) {\n\t\t\t\treturn index;\n\t\t\t});\n\t\t}\n\n\t\texpected = $.map( new Array( tabs.find ( \".ui-tabs-nav li\" ).length ), function( _, index ) {\n\t\t\tif ( typeof state === \"boolean\" ) {\n\t\t\t\treturn state ? 1 : 0;\n\t\t\t} else {\n\t\t\t\treturn $.inArray( index, state ) !== -1 ? 1 : 0;\n\t\t\t}\n\t\t});\n\n\t\tactual = tabs.find( \".ui-tabs-nav li\" ).map(function( index ) {\n\t\t\tvar tab = $( this ),\n\t\t\t\ttabIsDisabled = tab.hasClass( \"ui-state-disabled\" );\n\n\t\t\tif ( tabIsDisabled && $.inArray( index, internalState ) !== -1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tif ( !tabIsDisabled && $.inArray( index, internalState ) === -1 ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t// mixed state - invalid\n\t\t\treturn -1;\n\t\t}).get();\n\n\t\tdeepEqual( tabs.tabs( \"option\", \"disabled\" ), state );\n\t\tdeepEqual( actual, expected );\n\t},\n\n\tequalHeight: function( tabs, height ) {\n\t\ttabs.find( \".ui-tabs-panel\" ).each(function() {\n\t\t\tequal( $( this ).outerHeight(), height );\n\t\t});\n\t},\n\n\tstate: function( tabs ) {\n\t\tvar expected = $.makeArray( arguments ).slice( 1 ),\n\t\t\tactual = tabs.find( \".ui-tabs-nav li\" ).map(function() {\n\t\t\t\tvar tab = $( this ),\n\t\t\t\t\tpanel = $( $.ui.tabs.prototype._sanitizeSelector(\n\t\t\t\t\t\t\"#\" + tab.attr( \"aria-controls\" ) ) ),\n\t\t\t\t\ttabIsActive = tab.hasClass( \"ui-state-active\" ),\n\t\t\t\t\tpanelIsActive = panel.css( \"display\" ) !== \"none\";\n\n\t\t\t\tif ( tabIsActive && panelIsActive ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif ( !tabIsActive && !panelIsActive ) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\treturn -1; // mixed state - invalid\n\t\t\t}).get();\n\t\tdeepEqual( actual, expected );\n\t}\n};\n\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/testsuite.js",
    "content": "(function( $ ) {\n\nwindow.TestHelpers = {};\n\nfunction includeStyle( url ) {\n\tdocument.write( \"<link rel='stylesheet' href='../../../\" + url + \"'>\" );\n}\n\nfunction includeScript( url ) {\n\tdocument.write( \"<script src='../../../\" + url + \"'></script>\" );\n}\n\nQUnit.config.urlConfig.push( \"min\" );\nTestHelpers.loadResources = QUnit.urlParams.min ?\n\tfunction() {\n\t\t// TODO: proper include with theme images\n\t\tincludeStyle( \"dist/jquery-ui.min.css\" );\n\t\tincludeScript( \"dist/jquery-ui.min.js\" );\n\t} :\n\tfunction( resources ) {\n\t\t$.each( resources.css || [], function( i, resource ) {\n\t\t\tincludeStyle( \"themes/base/jquery.\" + resource + \".css\" );\n\t\t});\n\t\t$.each( resources.js || [], function( i, resource ) {\n\t\t\tincludeScript( resource );\n\t\t});\n\t};\n\nQUnit.config.urlConfig.push( \"nojshint\" );\nvar jshintLoaded = false;\nTestHelpers.testJshint = function( module ) {\n\tif ( QUnit.urlParams.nojshint ) {\n\t\treturn;\n\t}\n\n\tif ( !jshintLoaded ) {\n\t\tincludeScript( \"external/jshint.js\" );\n\t\tjshintLoaded = true;\n\t}\n\n\tasyncTest( \"JSHint\", function() {\n\t\texpect( 1 );\n\n\t\t$.when(\n\t\t\t$.ajax({\n\t\t\t\turl: \"../../../ui/.jshintrc\",\n\t\t\t\tdataType: \"json\"\n\t\t\t}),\n\t\t\t$.ajax({\n\t\t\t\turl: \"../../../ui/jquery.\" + module + \".js\",\n\t\t\t\tdataType: \"text\"\n\t\t\t})\n\t\t).done(function( hintArgs, srcArgs ) {\n\t\t\tvar passed = JSHINT( srcArgs[ 0 ], hintArgs[ 0 ] ),\n\t\t\t\terrors = $.map( JSHINT.errors, function( error ) {\n\t\t\t\t\t// JSHINT may report null if there are too many errors\n\t\t\t\t\tif ( !error ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn \"[L\" + error.line + \":C\" + error.character + \"] \" +\n\t\t\t\t\t\terror.reason + \"\\n\" + error.evidence + \"\\n\";\n\t\t\t\t}).join( \"\\n\" );\n\t\t\tok( passed, errors );\n\t\t\tstart();\n\t\t})\n\t\t.fail(function() {\n\t\t\tok( false, \"error loading source\" );\n\t\t\tstart();\n\t\t});\n\t});\n};\n\nfunction testWidgetDefaults( widget, defaults ) {\n\tvar pluginDefaults = $.ui[ widget ].prototype.options;\n\n\t// ensure that all defaults have the correct value\n\ttest( \"defined defaults\", function() {\n\t\t$.each( defaults, function( key, val ) {\n\t\t\tif ( $.isFunction( val ) ) {\n\t\t\t\tok( $.isFunction( pluginDefaults[ key ] ), key );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdeepEqual( pluginDefaults[ key ], val, key );\n\t\t});\n\t});\n\n\t// ensure that all defaults were tested\n\ttest( \"tested defaults\", function() {\n\t\t$.each( pluginDefaults, function( key, val ) {\n\t\t\tok( key in defaults, key );\n\t\t});\n\t});\n}\n\nfunction testWidgetOverrides( widget ) {\n\tif ( $.uiBackCompat === false ) {\n\t\ttest( \"$.widget overrides\", function() {\n\t\t\t$.each([\n\t\t\t\t\"_createWidget\",\n\t\t\t\t\"destroy\",\n\t\t\t\t\"option\",\n\t\t\t\t\"_trigger\"\n\t\t\t], function( i, method ) {\n\t\t\t\tstrictEqual( $.ui[ widget ].prototype[ method ],\n\t\t\t\t\t$.Widget.prototype[ method ], \"should not override \" + method );\n\t\t\t});\n\t\t});\n\t}\n}\n\nfunction testBasicUsage( widget ) {\n\ttest( \"basic usage\", function() {\n\t\tvar defaultElement = $.ui[ widget ].prototype.defaultElement;\n\t\t$( defaultElement ).appendTo( \"body\" )[ widget ]().remove();\n\t\tok( true, \"initialized on element\" );\n\n\t\t$( defaultElement )[ widget ]().remove();\n\t\tok( true, \"initialized on disconnected DOMElement - never connected\" );\n\n\t\t$( defaultElement ).appendTo( \"body\" ).remove()[ widget ]().remove();\n\t\tok( true, \"initialized on disconnected DOMElement - removed\" );\n\t});\n}\n\nTestHelpers.commonWidgetTests = function( widget, settings ) {\n\tmodule( widget + \": common widget\" );\n\n\tTestHelpers.testJshint( \"ui.\" + widget );\n\ttestWidgetDefaults( widget, settings.defaults );\n\ttestWidgetOverrides( widget );\n\ttestBasicUsage( widget );\n\ttest( \"version\", function() {\n\t\tok( \"version\" in $.ui[ widget ].prototype, \"version property exists\" );\n\t});\n};\n\n/*\n * Experimental assertion for comparing DOM objects.\n *\n * Serializes an element and some properties and attributes and it's children if any, otherwise the text.\n * Then compares the result using deepEqual.\n */\nwindow.domEqual = function( selector, modifier, message ) {\n\tvar expected, actual,\n\t\tproperties = [\n\t\t\t\"disabled\",\n\t\t\t\"readOnly\"\n\t\t],\n\t\tattributes = [\n\t\t\t\"autocomplete\",\n\t\t\t\"aria-activedescendant\",\n\t\t\t\"aria-controls\",\n\t\t\t\"aria-describedby\",\n\t\t\t\"aria-disabled\",\n\t\t\t\"aria-expanded\",\n\t\t\t\"aria-haspopup\",\n\t\t\t\"aria-hidden\",\n\t\t\t\"aria-labelledby\",\n\t\t\t\"aria-pressed\",\n\t\t\t\"aria-selected\",\n\t\t\t\"aria-valuemax\",\n\t\t\t\"aria-valuemin\",\n\t\t\t\"aria-valuenow\",\n\t\t\t\"class\",\n\t\t\t\"href\",\n\t\t\t\"id\",\n\t\t\t\"nodeName\",\n\t\t\t\"role\",\n\t\t\t\"tabIndex\",\n\t\t\t\"title\"\n\t\t];\n\n\tfunction extract( elem ) {\n\t\tif ( !elem || !elem.length ) {\n\t\t\tQUnit.push( false, actual, expected,\n\t\t\t\t\"domEqual failed, can't extract \" + selector + \", message was: \" + message );\n\t\t\treturn;\n\t\t}\n\n\t\tvar children,\n\t\t\tresult = {};\n\t\t$.each( properties, function( index, attr ) {\n\t\t\tvar value = elem.prop( attr );\n\t\t\tresult[ attr ] = value !== undefined ? value : \"\";\n\t\t});\n\t\t$.each( attributes, function( index, attr ) {\n\t\t\tvar value = elem.attr( attr );\n\t\t\tresult[ attr ] = value !== undefined ? value : \"\";\n\t\t});\n\t\tresult.events = $._data( elem[ 0 ], \"events\" );\n\t\tresult.data = $.extend( {}, elem.data() );\n\t\tdelete result.data[ $.expando ];\n\t\tchildren = elem.children();\n\t\tif ( children.length ) {\n\t\t\tresult.children = elem.children().map(function( ind ) {\n\t\t\t\treturn extract( $( this ) );\n\t\t\t}).get();\n\t\t} else {\n\t\t\tresult.text = elem.text();\n\t\t}\n\t\treturn result;\n\t}\n\texpected = extract( $( selector ) );\n\tmodifier( $( selector ) );\n\n\tactual = extract( $( selector ) );\n\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n};\n\n}( jQuery ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"tooltip\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Tooltip Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/tooltip.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Tooltip Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\", \"ui.tooltip\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.core.js\",\n\t\t\t\"ui/jquery.ui.widget.js\",\n\t\t\t\"ui/jquery.ui.position.js\",\n\t\t\t\"ui/jquery.ui.tooltip.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"tooltip_common.js\"></script>\n\t<script src=\"tooltip_core.js\"></script>\n\t<script src=\"tooltip_events.js\"></script>\n\t<script src=\"tooltip_methods.js\"></script>\n\t<script src=\"tooltip_options.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Tooltip Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div>\n\t<a id=\"tooltipped1\" href=\"#\" title=\"anchortitle\">anchor</a>\n\t<input title=\"inputtitle\">\n\t<span id=\"multiple-describedby\" aria-describedby=\"fixture-span\" title=\"...\">aria-describedby</span>\n\t<span id=\"fixture-span\" title=\"title-text\">span</span>\n</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/tooltip_common.js",
    "content": "TestHelpers.commonWidgetTests( \"tooltip\", {\n\tdefaults: {\n\t\tcontent: function() {},\n\t\tdisabled: false,\n\t\thide: true,\n\t\titems: \"[title]\",\n\t\tposition: {\n\t\t\tmy: \"left+15 center\",\n\t\t\tat: \"right center\",\n\t\t\tcollision: \"flipfit flipfit\"\n\t\t},\n\t\tshow: true,\n\t\ttooltipClass: null,\n\n\t\t// callbacks\n\t\tclose: null,\n\t\tcreate: null,\n\t\topen: null\n\t}\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/tooltip_core.js",
    "content": "(function( $ ) {\n\nmodule( \"tooltip: core\" );\n\ntest( \"markup structure\", function() {\n\texpect( 7 );\n\tvar element = $( \"#tooltipped1\" ).tooltip(),\n\t\ttooltip = $( \".ui-tooltip\" );\n\n\tequal( element.attr( \"aria-describedby\" ), undefined, \"no aria-describedby on init\" );\n\tequal( tooltip.length, 0, \"no tooltip on init\" );\n\n\telement.tooltip( \"open\" );\n\ttooltip = $( \"#\" + element.data( \"ui-tooltip-id\" ) );\n\tequal( tooltip.length, 1, \"tooltip exists\" );\n\tequal( element.attr( \"aria-describedby\"), tooltip.attr( \"id\" ), \"aria-describedby\" );\n\tok( tooltip.hasClass( \"ui-tooltip\" ), \"tooltip is .ui-tooltip\" );\n\tequal( tooltip.length, 1, \".ui-tooltip exists\" );\n\tequal( tooltip.find( \".ui-tooltip-content\" ).length, 1,\n\t\t\".ui-tooltip-content exists\" );\n});\n\ntest( \"accessibility\", function() {\n\texpect( 5 );\n\n\tvar tooltipId,\n\t\ttooltip,\n\t\telement = $( \"#multiple-describedby\" ).tooltip();\n\n\telement.tooltip( \"open\" );\n\ttooltipId = element.data( \"ui-tooltip-id\" );\n\ttooltip = $( \"#\" + tooltipId );\n\tequal( tooltip.attr( \"role\" ), \"tooltip\", \"role\" );\n\tequal( element.attr( \"aria-describedby\" ), \"fixture-span \" + tooltipId,\n\t\t\"multiple describedby when open\" );\n\t// strictEqual to distinguish between .removeAttr( \"title\" ) and .attr( \"title\", \"\" )\n\tstrictEqual( element.attr( \"title\" ), undefined, \"no title when open\" );\n\telement.tooltip( \"close\" );\n\tequal( element.attr( \"aria-describedby\" ), \"fixture-span\",\n\t\t\"correct describedby when closed\" );\n\tequal( element.attr( \"title\" ), \"...\", \"title restored when closed\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/tooltip_events.js",
    "content": "(function( $ ) {\n\nmodule( \"tooltip: events\" );\n\ntest( \"programmatic triggers\", function() {\n\texpect( 4 );\n\tvar tooltip,\n\t\telement = $( \"#tooltipped1\" ).tooltip();\n\n\telement.one( \"tooltipopen\", function( event, ui ) {\n\t\ttooltip = ui.tooltip;\n\t\tok( !( \"originalEvent\" in event ), \"open\" );\n\t\tstrictEqual( ui.tooltip[0],\n\t\t\t$( \"#\" + element.data( \"ui-tooltip-id\" ) )[0], \"ui.tooltip\" );\n\t});\n\telement.tooltip( \"open\" );\n\n\telement.one( \"tooltipclose\", function( event, ui ) {\n\t\tok( !( \"originalEvent\" in event ), \"close\" );\n\t\tstrictEqual( ui.tooltip[0], tooltip[0], \"ui.tooltip\" );\n\t});\n\telement.tooltip( \"close\" );\n});\n\ntest( \"mouse events\", function() {\n\texpect( 2 );\n\tvar element = $( \"#tooltipped1\" ).tooltip();\n\n\telement.one( \"tooltipopen\", function( event ) {\n\t\tdeepEqual( event.originalEvent.type, \"mouseover\" );\n\t});\n\telement.trigger( \"mouseover\" );\n\n\telement.one( \"tooltipclose\", function( event ) {\n\t\tdeepEqual( event.originalEvent.type, \"mouseleave\" );\n\t});\n\telement.trigger( \"mouseleave\" );\n});\n\ntest( \"focus events\", function() {\n\texpect( 2 );\n\tvar element = $( \"#tooltipped1\" ).tooltip();\n\n\telement.one( \"tooltipopen\", function( event ) {\n\t\tdeepEqual( event.originalEvent.type, \"focusin\" );\n\t});\n\telement.trigger( \"focusin\" );\n\n\telement.one( \"tooltipclose\", function( event ) {\n\t\tdeepEqual( event.originalEvent.type, \"focusout\" );\n\t});\n\telement.trigger( \"focusout\" );\n});\n\nasyncTest( \"mixed events\", function() {\n\texpect( 2 );\n\tvar element = $( \"#tooltipped1\" ).tooltip();\n\n\telement.one( \"tooltipopen\", function( event ) {\n\t\tdeepEqual( event.originalEvent.type, \"focusin\" );\n\t});\n\telement.simulate( \"focus\" );\n\n\telement.one( \"tooltipopen\", function() {\n\t\tok( false, \"open triggered while already open\" );\n\t});\n\telement.trigger( \"mouseover\" );\n\n\telement.bind( \"tooltipclose\", function( event ) {\n\t\tok( false, \"close triggered while still focused\" );\n\t});\n\telement.trigger( \"mouseleave\" );\n\telement.unbind( \"tooltipclose\" );\n\n\t// blurring is async in IE\n\telement.one( \"tooltipclose\", function( event ) {\n\t\tdeepEqual( event.originalEvent.type, \"focusout\" );\n\t\tstart();\n\t});\n\telement.simulate( \"blur\" );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/tooltip_methods.js",
    "content": "(function( $ ) {\n\nmodule( \"tooltip: methods\" );\n\ntest( \"destroy\", function() {\n\texpect( 2 );\n\tdomEqual( \"#tooltipped1\", function() {\n\t\t$( \"#tooltipped1\" ).tooltip().tooltip( \"destroy\" );\n\t});\n\n\t// make sure that open tooltips are removed on destroy\n\t$( \"#tooltipped1\" ).tooltip().tooltip( \"open\" ).tooltip( \"destroy\" );\n\tequal( $( \".ui-tooltip\" ).length, 0 );\n});\n\ntest( \"open/close\", function() {\n\texpect( 3 );\n\t$.fx.off = true;\n\tvar tooltip,\n\t\telement = $( \"#tooltipped1\" ).tooltip();\n\tequal( $( \".ui-tooltip\" ).length, 0, \"no tooltip on init\" );\n\n\telement.tooltip( \"open\" );\n\ttooltip = $( \"#\" + element.data( \"ui-tooltip-id\" ) );\n\tok( tooltip.is( \":visible\" ) );\n\n\telement.tooltip( \"close\" );\n\tok( tooltip.is( \":hidden\" ) );\n\t$.fx.off = false;\n});\n\ntest( \"enable/disable\", function() {\n\texpect( 7 );\n\t$.fx.off = true;\n\tvar tooltip,\n\t\telement = $( \"#tooltipped1\" ).tooltip();\n\tequal( $( \".ui-tooltip\" ).length, 0, \"no tooltip on init\" );\n\n\telement.tooltip( \"open\" );\n\ttooltip = $( \"#\" + element.data( \"ui-tooltip-id\" ) );\n\tok( tooltip.is( \":visible\" ) );\n\n\telement.tooltip( \"disable\" );\n\tequal( $( \".ui-tooltip\" ).length, 0, \"no tooltip when disabled\" );\n\tequal( tooltip.attr( \"title\" ), undefined, \"title removed on disable\" );\n\n\telement.tooltip( \"open\" );\n\tequal( $( \".ui-tooltip\" ).length, 0, \"open does nothing when disabled\" );\n\n\telement.tooltip( \"enable\" );\n\tequal( element.attr( \"title\" ), \"anchortitle\", \"title restored on enable\" );\n\n\telement.tooltip( \"open\" );\n\ttooltip = $( \"#\" + element.data( \"ui-tooltip-id\" ) );\n\tok( tooltip.is( \":visible\" ) );\n\t$.fx.off = false;\n});\n\n/*\nTODO currently tooltip doesn't override widget\ncan't return anything useful if no element is kept around and there's no useful reference\ntest(\"widget\", function() {\n\tvar tooltip = $(\"#tooltipped1\").tooltip();\n\tdeepEqual(tooltip.tooltip(\"widget\")[0], $(\".ui-tooltip\")[0]);\n\tdeepEqual(tooltip.tooltip(\"widget\").end()[0], tooltip[0]);\n});\n*/\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/tooltip/tooltip_options.js",
    "content": "(function( $ ) {\n\nmodule( \"tooltip: options\" );\n\ntest( \"content: default\", function() {\n\tvar element = $( \"#tooltipped1\" ).tooltip().tooltip( \"open\" );\n\tdeepEqual( $( \"#\" + element.data( \"ui-tooltip-id\" ) ).text(), \"anchortitle\" );\n});\n\ntest( \"content: return string\", function() {\n\tvar element = $( \"#tooltipped1\" ).tooltip({\n\t\tcontent: function() {\n\t\t\treturn \"customstring\";\n\t\t}\n\t}).tooltip( \"open\" );\n\tdeepEqual( $( \"#\" + element.data( \"ui-tooltip-id\" ) ).text(), \"customstring\" );\n});\n\ntest( \"content: return jQuery\", function() {\n\tvar element = $( \"#tooltipped1\" ).tooltip({\n\t\tcontent: function() {\n\t\t\treturn $( \"<div>\" ).html( \"cu<b>s</b>tomstring\" );\n\t\t}\n\t}).tooltip( \"open\" );\n\tdeepEqual( $( \"#\" + element.data( \"ui-tooltip-id\" ) ).text(), \"customstring\" );\n});\n\nasyncTest( \"content: sync + async callback\", function() {\n\texpect( 2 );\n\tvar element = $( \"#tooltipped1\" ).tooltip({\n\t\tcontent: function( response ) {\n\t\t\tsetTimeout(function() {\n\t\t\t\tdeepEqual( $( \"#\" + element.data(\"ui-tooltip-id\") ).text(), \"loading...\" );\n\n\t\t\t\tresponse( \"customstring2\" );\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tdeepEqual( $( \"#\" + element.data(\"ui-tooltip-id\") ).text(), \"customstring2\" );\n\t\t\t\t\tstart();\n\t\t\t\t}, 13 );\n\t\t\t}, 13 );\n\t\t\treturn \"loading...\";\n\t\t}\n\t}).tooltip( \"open\" );\n});\n\ntest( \"items\", function() {\n\texpect( 2 );\n\tvar event,\n\t\telement = $( \"#qunit-fixture\" ).tooltip({\n\t\t\titems: \"#fixture-span\"\n\t\t});\n\n\tevent = $.Event( \"mouseenter\" );\n\tevent.target = $( \"#fixture-span\" )[ 0 ];\n\telement.tooltip( \"open\", event );\n\tdeepEqual( $( \"#\" + $( \"#fixture-span\" ).data( \"ui-tooltip-id\" ) ).text(), \"title-text\" );\n\n\t// make sure default [title] doesn't get used\n\tevent.target = $( \"#tooltipped1\" )[ 0 ];\n\telement.tooltip( \"open\", event );\n\tdeepEqual( $( \"#tooltipped1\" ).data( \"ui-tooltip-id\" ), undefined );\n\n\telement.tooltip( \"destroy\" );\n});\n\ntest( \"tooltipClass\", function() {\n\texpect( 1 );\n\tvar element = $( \"#tooltipped1\" ).tooltip({\n\t\ttooltipClass: \"custom\"\n\t}).tooltip( \"open\" );\n\tok( $( \"#\" + element.data( \"ui-tooltip-id\" ) ).hasClass( \"custom\" ) );\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/widget/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Widget Test Suite</title>\n\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<link rel=\"stylesheet\" href=\"../qunit-composite.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../qunit-composite.js\"></script>\n\t<script src=\"../subsuite.js\"></script>\n\n\t<script>\n\ttestAllVersions( \"widget\" );\n\t</script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Widget Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/widget/widget.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Widget Test Suite</title>\n\n\t<script src=\"../../jquery.js\"></script>\n\t<link rel=\"stylesheet\" href=\"../../../external/qunit.css\">\n\t<script src=\"../../../external/qunit.js\"></script>\n\t<script src=\"../../jquery.simulate.js\"></script>\n\t<script src=\"../testsuite.js\"></script>\n\t<script>\n\tTestHelpers.loadResources({\n\t\tcss: [ \"ui.core\" ],\n\t\tjs: [\n\t\t\t\"ui/jquery.ui.widget.js\"\n\t\t]\n\t});\n\t</script>\n\n\t<script src=\"widget_core.js\"></script>\n\t<script src=\"widget_extend.js\"></script>\n\t<script src=\"widget_animation.js\"></script>\n\n\t<script src=\"../swarminject.js\"></script>\n</head>\n<body>\n\n<h1 id=\"qunit-header\">jQuery UI Widget Test Suite</h1>\n<h2 id=\"qunit-banner\"></h2>\n<div id=\"qunit-testrunner-toolbar\"></div>\n<h2 id=\"qunit-userAgent\"></h2>\n<ol id=\"qunit-tests\"></ol>\n<div id=\"qunit-fixture\">\n\n<div id=\"widget-wrapper\">\n\t<div id=\"widget\">\n\t\t<div>...</div>\n\t</div>\n</div>\n\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/widget/widget_animation.js",
    "content": "\nmodule( \"widget animation\", (function() {\n\tvar show = $.fn.show,\n\t\tfadeIn = $.fn.fadeIn,\n\t\tslideDown = $.fn.slideDown;\n\treturn {\n\t\tsetup: function() {\n\t\t\t$.widget( \"ui.testWidget\", {\n\t\t\t\t_create: function() {\n\t\t\t\t\tthis.element.hide();\n\t\t\t\t},\n\t\t\t\tshow: function( fn ) {\n\t\t\t\t\tthis._show( this.element, this.options.show, fn );\n\t\t\t\t}\n\t\t\t});\n\t\t\t$.effects = { effect: { testEffect: $.noop } };\n\t\t},\n\t\tteardown: function() {\n\t\t\tdelete $.ui.testWidget;\n\t\t\tdelete $.effects.effect.testEffect;\n\t\t\t$.fn.show = show;\n\t\t\t$.fn.fadeIn = fadeIn;\n\t\t\t$.fn.slideDown = slideDown;\n\t\t}\n\t};\n}()));\n\nasyncTest( \"show: null\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#widget\" ).testWidget(),\n\t\thasRun = false;\n\t$.fn.show = function() {\n\t\tok( true, \"show called\" );\n\t\tequal( arguments.length, 0, \"no args passed to show\" );\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n\nasyncTest( \"show: true\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#widget\" ).testWidget({\n\t\t\tshow: true\n\t\t}),\n\t\thasRun = false;\n\t$.fn.fadeIn = function( duration, easing, complete ) {\n\t\treturn this.queue(function( next ) {\n\t\t\tstrictEqual( duration, undefined, \"duration\" );\n\t\t\tstrictEqual( easing, undefined, \"easing\" );\n\t\t\tcomplete();\n\t\t\tnext();\n\t\t});\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n\nasyncTest( \"show: number\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#widget\" ).testWidget({\n\t\tshow: 123\n\t}),\n\thasRun = false;\n\t$.fn.fadeIn = function( duration, easing, complete ) {\n\t\treturn this.queue(function( next ) {\n\t\t\tstrictEqual( duration, 123, \"duration\" );\n\t\t\tstrictEqual( easing, undefined, \"easing\" );\n\t\t\tcomplete();\n\t\t\tnext();\n\t\t});\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n\nasyncTest( \"show: core animation\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#widget\" ).testWidget({\n\t\tshow: \"slideDown\"\n\t}),\n\thasRun = false;\n\t$.fn.slideDown = function( duration, easing, complete ) {\n\t\treturn this.queue(function( next ) {\n\t\t\tstrictEqual( duration, undefined, \"duration\" );\n\t\t\tstrictEqual( easing, undefined, \"easing\" );\n\t\t\tcomplete();\n\t\t\tnext();\n\t\t});\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n\nasyncTest( \"show: effect\", function() {\n\texpect( 5 );\n\n\tvar element = $( \"#widget\" ).testWidget({\n\t\tshow: \"testEffect\"\n\t}),\n\thasRun = false;\n\t$.fn.show = function( options ) {\n\t\treturn this.queue(function( next ) {\n\t\t\tequal( options.effect, \"testEffect\", \"effect\" );\n\t\t\tok( !(\"duration\" in options), \"duration\" );\n\t\t\tok( !(\"easing\" in options), \"easing\" );\n\t\t\toptions.complete();\n\t\t\tnext();\n\t\t});\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n\nasyncTest( \"show: object(core animation)\", function() {\n\texpect( 4 );\n\n\tvar element = $( \"#widget\" ).testWidget({\n\t\tshow: {\n\t\t\teffect: \"slideDown\",\n\t\t\tduration: 123,\n\t\t\teasing: \"testEasing\"\n\t\t}\n\t}),\n\thasRun = false;\n\t$.fn.slideDown = function( duration, easing, complete ) {\n\t\treturn this.queue(function( next ) {\n\t\t\tequal( duration, 123, \"duration\" );\n\t\t\tequal( easing, \"testEasing\", \"easing\" );\n\t\t\tcomplete();\n\t\t\tnext();\n\t\t});\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n\nasyncTest( \"show: object(effect)\", function() {\n\texpect( 3 );\n\n\tvar element = $( \"#widget\" ).testWidget({\n\t\tshow: {\n\t\t\teffect: \"testEffect\",\n\t\t\tduration: 123,\n\t\t\teasing: \"testEasing\"\n\t\t}\n\t}),\n\thasRun = false;\n\t$.fn.show = function( options ) {\n\t\treturn this.queue(function( next ) {\n\t\t\tdeepEqual( options, {\n\t\t\t\teffect: \"testEffect\",\n\t\t\t\tduration: 123,\n\t\t\t\teasing: \"testEasing\",\n\t\t\t\tcomplete: options.complete\n\t\t\t});\n\t\t\toptions.complete();\n\t\t\tnext();\n\t\t});\n\t};\n\n\telement\n\t\t.delay( 50 )\n\t\t.queue(function( next ) {\n\t\t\tok( !hasRun, \"queue before show\" );\n\t\t\tnext();\n\t\t})\n\t\t.testWidget( \"show\", function() {\n\t\t\thasRun = true;\n\t\t})\n\t\t.queue(function( next ) {\n\t\t\tok( hasRun, \"queue after show\" );\n\t\t\tstart();\n\t\t\tnext();\n\t\t});\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/widget/widget_core.js",
    "content": "(function( $ ) {\n\nmodule( \"widget factory\", {\n\tteardown: function() {\n\t\tif ( $.ui ) {\n\t\t\tdelete $.ui.testWidget;\n\t\t}\n\t}\n});\n\nTestHelpers.testJshint( \"ui.widget\" );\n\ntest( \"widget creation\", function() {\n\tvar myPrototype = {\n\t\t_create: function() {},\n\t\tcreationTest: function() {}\n\t};\n\n\t$.widget( \"ui.testWidget\", myPrototype );\n\tok( $.isFunction( $.ui.testWidget ), \"constructor was created\" );\n\tequal( \"object\", typeof $.ui.testWidget.prototype, \"prototype was created\" );\n\tequal( $.ui.testWidget.prototype._create, myPrototype._create,\n\t\t\"create function is copied over\" );\n\tequal( $.ui.testWidget.prototype.creationTest, myPrototype.creationTest,\n\t\t\"random function is copied over\" );\n\tequal( $.ui.testWidget.prototype.option, $.Widget.prototype.option,\n\t\t\"option method copied over from base widget\" );\n});\n\ntest( \"element normalization\", function() {\n\texpect( 11 );\n\tvar elem;\n\t$.widget( \"ui.testWidget\", {} );\n\n\t$.ui.testWidget.prototype._create = function() {\n\t\t// workaround for core ticket #8381\n\t\tthis.element.appendTo( \"#qunit-fixture\" );\n\t\tok( this.element.is( \"div\" ), \"generated div\" );\n\t\tdeepEqual( this.element.data( \"ui-testWidget\" ), this, \"instance stored in .data()\" );\n\t};\n\t$.ui.testWidget();\n\n\t$.ui.testWidget.prototype.defaultElement = \"<span data-test='pass'></span>\";\n\t$.ui.testWidget.prototype._create = function() {\n\t\tok( this.element.is( \"span[data-test=pass]\" ), \"generated span with properties\" );\n\t\tdeepEqual( this.element.data( \"ui-testWidget\" ), this, \"instace stored in .data()\" );\n\t};\n\t$.ui.testWidget();\n\n\telem = $( \"<input>\" );\n\t$.ui.testWidget.prototype._create = function() {\n\t\tdeepEqual( this.element[ 0 ], elem[ 0 ], \"from element\" );\n\t\tdeepEqual( elem.data( \"ui-testWidget\" ), this, \"instace stored in .data()\" );\n\t};\n\t$.ui.testWidget( {}, elem[ 0 ] );\n\n\telem = $( \"<div>\" );\n\t$.ui.testWidget.prototype._create = function() {\n\t\tdeepEqual( this.element[ 0 ], elem[ 0 ], \"from jQuery object\" );\n\t\tdeepEqual( elem.data( \"ui-testWidget\" ), this, \"instace stored in .data()\" );\n\t};\n\t$.ui.testWidget( {}, elem );\n\n\telem = $( \"<div id='element-normalization-selector'></div>\" )\n\t\t.appendTo( \"#qunit-fixture\" );\n\t$.ui.testWidget.prototype._create = function() {\n\t\tdeepEqual( this.element[ 0 ], elem[ 0 ], \"from selector\" );\n\t\tdeepEqual( elem.data( \"ui-testWidget\" ), this, \"instace stored in .data()\" );\n\t};\n\t$.ui.testWidget( {}, \"#element-normalization-selector\" );\n\n\t$.ui.testWidget.prototype.defaultElement = null;\n\t$.ui.testWidget.prototype._create = function() {\n\t\t// using strictEqual throws an error (Maximum call stack size exceeded)\n\t\tok( this.element[ 0 ] === this, \"instance as element\" );\n\t};\n\t$.ui.testWidget();\n});\n\ntest( \"custom selector expression\", function() {\n\tvar elem = $( \"<div>\" ).appendTo( \"#qunit-fixture\" );\n\t$.widget( \"ui.testWidget\", {} );\n\telem.testWidget();\n\tdeepEqual( $( \":ui-testWidget\" )[0], elem[0] );\n\telem.testWidget( \"destroy\" );\n});\n\ntest( \"jQuery usage\", function() {\n\texpect( 16 );\n\n\tvar elem, instance, ret, bcInstance,\n\t\tshouldCreate = false;\n\n\t$.widget( \"ui.testWidget\", {\n\t\tgetterSetterVal: 5,\n\t\t_create: function() {\n\t\t\tok( shouldCreate, \"create called on instantiation\" );\n\t\t},\n\t\tmethodWithParams: function( param1, param2 ) {\n\t\t\tok( true, \"method called via .pluginName(methodName)\" );\n\t\t\tequal( param1, \"value1\",\n\t\t\t\t\"parameter passed via .pluginName(methodName, param)\" );\n\t\t\tequal( param2, \"value2\",\n\t\t\t\t\"multiple parameters passed via .pluginName(methodName, param, param)\" );\n\n\t\t\treturn this;\n\t\t},\n\t\tgetterSetterMethod: function( val ) {\n\t\t\tif ( val ) {\n\t\t\t\tthis.getterSetterVal = val;\n\t\t\t} else {\n\t\t\t\treturn this.getterSetterVal;\n\t\t\t}\n\t\t},\n\t\tjQueryObject: function() {\n\t\t\treturn $( \"body\" );\n\t\t}\n\t});\n\n\tshouldCreate = true;\n\telem = $( \"<div>\" )\n\t\t.bind( \"testwidgetcreate\", function() {\n\t\t\tok( shouldCreate, \"create event triggered on instantiation\" );\n\t\t})\n\t\t.testWidget();\n\tshouldCreate = false;\n\n\tinstance = elem.data( \"ui-testWidget\" );\n\tequal( typeof instance, \"object\", \"instance stored in .data(pluginName)\" );\n\tequal( instance.element[0], elem[0], \"element stored on widget\" );\n\tret = elem.testWidget( \"methodWithParams\", \"value1\", \"value2\" );\n\tequal( ret, elem, \"jQuery object returned from method call\" );\n\n\t// 1.9 BC for #7810\n\t// TODO remove\n\tbcInstance = elem.data(\"testWidget\");\n\tequal( typeof bcInstance, \"object\", \"instance stored in .data(pluginName)\" );\n\tequal( bcInstance.element[0], elem[0], \"element stored on widget\" );\n\n\tret = elem.testWidget( \"getterSetterMethod\" );\n\tequal( ret, 5, \"getter/setter can act as getter\" );\n\tret = elem.testWidget( \"getterSetterMethod\", 30 );\n\tequal( ret, elem, \"getter/setter method can be chainable\" );\n\tequal( instance.getterSetterVal, 30, \"getter/setter can act as setter\" );\n\tret = elem.testWidget( \"jQueryObject\" );\n\tequal( ret[ 0 ], document.body, \"returned jQuery object\" );\n\tequal( ret.end(), elem, \"stack preserved\" );\n\n\telem.testWidget( \"destroy\" );\n\tequal( elem.data( \"ui-testWidget\" ), null );\n});\n\ntest( \"direct usage\", function() {\n\texpect( 9 );\n\n\tvar elem, instance, ret,\n\t\tshouldCreate = false;\n\n\t$.widget( \"ui.testWidget\", {\n\t\tgetterSetterVal: 5,\n\t\t_create: function() {\n\t\t\tok( shouldCreate, \"create called on instantiation\" );\n\t\t},\n\t\tmethodWithParams: function( param1, param2 ) {\n\t\t\tok( true, \"method called dirctly\" );\n\t\t\tequal( param1, \"value1\", \"parameter passed via direct call\" );\n\t\t\tequal( param2, \"value2\", \"multiple parameters passed via direct call\" );\n\n\t\t\treturn this;\n\t\t},\n\t\tgetterSetterMethod: function( val ) {\n\t\t\tif ( val ) {\n\t\t\t\tthis.getterSetterVal = val;\n\t\t\t} else {\n\t\t\t\treturn this.getterSetterVal;\n\t\t\t}\n\t\t}\n\t});\n\n\telem = $( \"<div>\" )[ 0 ];\n\n\tshouldCreate = true;\n\tinstance = new $.ui.testWidget( {}, elem );\n\tshouldCreate = false;\n\n\tequal( $( elem ).data( \"ui-testWidget\" ), instance,\n\t\t\"instance stored in .data(pluginName)\" );\n\tequal( instance.element[ 0 ], elem, \"element stored on widget\" );\n\n\tret = instance.methodWithParams( \"value1\", \"value2\" );\n\tequal( ret, instance, \"plugin returned from method call\" );\n\n\tret = instance.getterSetterMethod();\n\tequal( ret, 5, \"getter/setter can act as getter\" );\n\tinstance.getterSetterMethod( 30 );\n\tequal( instance.getterSetterVal, 30, \"getter/setter can act as setter\" );\n});\n\ntest( \"error handling\", function() {\n\texpect( 3 );\n\tvar error = $.error;\n\t$.widget( \"ui.testWidget\", {\n\t\t_privateMethod: function () {}\n\t});\n\t$.error = function( msg ) {\n\t\tequal( msg, \"cannot call methods on testWidget prior to initialization; \" +\n\t\t\t\"attempted to call method 'missing'\", \"method call before init\" );\n\t};\n\t$( \"<div>\" ).testWidget( \"missing\" );\n\t$.error = function( msg ) {\n\t\tequal( msg, \"no such method 'missing' for testWidget widget instance\",\n\t\t\t\"invalid method call on widget instance\" );\n\t};\n\t$( \"<div>\" ).testWidget().testWidget( \"missing\" );\n\t$.error = function ( msg ) {\n\t\tequal( msg, \"no such method '_privateMethod' for testWidget widget instance\",\n\t\t\t\"invalid method call on widget instance\" );\n\t};\n\t$( \"<div>\" ).testWidget().testWidget( \"_privateMethod\" );\n\t$.error = error;\n});\n\ntest( \"merge multiple option arguments\", function() {\n\texpect( 1 );\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\t\tdeepEqual( this.options, {\n\t\t\t\tcreate: null,\n\t\t\t\tdisabled: false,\n\t\t\t\toption1: \"value1\",\n\t\t\t\toption2: \"value2\",\n\t\t\t\toption3: \"value3\",\n\t\t\t\toption4: {\n\t\t\t\t\toption4a: \"valuea\",\n\t\t\t\t\toption4b: \"valueb\"\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t$( \"<div>\" ).testWidget({\n\t\toption1: \"valuex\",\n\t\toption2: \"valuex\",\n\t\toption3: \"value3\",\n\t\toption4: {\n\t\t\toption4a: \"valuex\"\n\t\t}\n\t}, {\n\t\toption1: \"value1\",\n\t\toption2: \"value2\",\n\t\toption4: {\n\t\t\toption4b: \"valueb\"\n\t\t}\n\t}, {\n\t\toption4: {\n\t\t\toption4a: \"valuea\"\n\t\t}\n\t});\n});\n\ntest( \"._getCreateOptions()\", function() {\n\texpect( 1 );\n\t$.widget( \"ui.testWidget\", {\n\t\toptions: {\n\t\t\toption1: \"valuex\",\n\t\t\toption2: \"valuex\",\n\t\t\toption3: \"value3\"\n\t\t},\n\t\t_getCreateOptions: function() {\n\t\t\treturn {\n\t\t\t\toption1: \"override1\",\n\t\t\t\toption2: \"overideX\"\n\t\t\t};\n\t\t},\n\t\t_create: function() {\n\t\t\tdeepEqual( this.options, {\n\t\t\t\tcreate: null,\n\t\t\t\tdisabled: false,\n\t\t\t\toption1: \"override1\",\n\t\t\t\toption2: \"value2\",\n\t\t\t\toption3: \"value3\"\n\t\t\t});\n\t\t}\n\t});\n\t$( \"<div>\" ).testWidget({ option2: \"value2\" });\n});\n\ntest( \"._getCreateEventData()\", function() {\n\texpect( 1 );\n\tvar data = { foo: \"bar\" };\n\t$.widget( \"ui.testWidget\", {\n\t\t_getCreateEventData: function() {\n\t\t\treturn data;\n\t\t}\n\t});\n\t$( \"<div>\" ).testWidget({\n\t\tcreate: function( event, ui ) {\n\t\t\tstrictEqual( ui, data, \"event data\" );\n\t\t}\n\t});\n});\n\ntest( \"re-init\", function() {\n\tvar div = $( \"<div>\" ),\n\t\tactions = [];\n\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\t\tactions.push( \"create\" );\n\t\t},\n\t\t_init: function() {\n\t\t\tactions.push( \"init\" );\n\t\t},\n\t\t_setOption: function( key, value ) {\n\t\t\tactions.push( \"option\" + key );\n\t\t}\n\t});\n\n\tactions = [];\n\tdiv.testWidget({ foo: \"bar\" });\n\tdeepEqual( actions, [ \"create\", \"init\" ], \"correct methods called on init\" );\n\n\tactions = [];\n\tdiv.testWidget();\n\tdeepEqual( actions, [ \"init\" ], \"correct methods call on re-init\" );\n\n\tactions = [];\n\tdiv.testWidget({ foo: \"bar\" });\n\tdeepEqual( actions, [ \"optionfoo\", \"init\" ], \"correct methods called on re-init with options\" );\n});\n\ntest( \"inheritance - options\", function() {\n\t// #5830 - Widget: Using inheritance overwrites the base classes options\n\t$.widget( \"ui.testWidgetBase\", {\n\t\toptions: {\n\t\t\tobj: {\n\t\t\t\tkey1: \"foo\",\n\t\t\t\tkey2: \"bar\"\n\t\t\t},\n\t\t\tarr: [ \"testing\" ]\n\t\t}\n\t});\n\n\t$.widget( \"ui.testWidgetExtension\", $.ui.testWidgetBase, {\n\t\toptions: {\n\t\t\tobj: {\n\t\t\t\tkey1: \"baz\"\n\t\t\t},\n\t\t\tarr: [ \"alpha\", \"beta\" ]\n\t\t}\n\t});\n\n\tdeepEqual( $.ui.testWidgetBase.prototype.options.obj, {\n\t\tkey1: \"foo\",\n\t\tkey2: \"bar\"\n\t}, \"base class option object not overridden\");\n\tdeepEqual( $.ui.testWidgetBase.prototype.options.arr, [ \"testing\" ],\n\t\t\"base class option array not overridden\");\n\n\tdeepEqual( $.ui.testWidgetExtension.prototype.options.obj, {\n\t\tkey1: \"baz\",\n\t\tkey2: \"bar\"\n\t}, \"extension class option object extends base\");\n\tdeepEqual( $.ui.testWidgetExtension.prototype.options.arr, [ \"alpha\", \"beta\" ],\n\t\t\"extension class option array overwrites base\");\n\n\tdelete $.ui.testWidgetBase;\n\tdelete $.ui.testWidgetExtension;\n});\n\ntest( \"._super()\", function() {\n\texpect( 9 );\n\tvar instance;\n\t$.widget( \"ui.testWidget\", {\n\t\tmethod: function( a, b ) {\n\t\t\tdeepEqual( this, instance, \"this is correct in testWidget\" );\n\t\t\tdeepEqual( a, 5, \"parameter passed to testWidget\" );\n\t\t\tdeepEqual( b, 20, \"second parameter passed to testWidget\" );\n\t\t\treturn a + b;\n\t\t}\n\t});\n\n\t$.widget( \"ui.testWidget2\", $.ui.testWidget, {\n\t\tmethod: function( a, b ) {\n\t\t\tdeepEqual( this, instance, \"this is correct in testWidget2\" );\n\t\t\tdeepEqual( a, 5, \"parameter passed to testWidget2\" );\n\t\t\tdeepEqual( b, 10, \"parameter passed to testWidget2\" );\n\t\t\treturn this._super( a, b*2 );\n\t\t}\n\t});\n\n\t$.widget( \"ui.testWidget3\", $.ui.testWidget2, {\n\t\tmethod: function( a ) {\n\t\t\tdeepEqual( this, instance, \"this is correct in testWidget3\" );\n\t\t\tdeepEqual( a, 5, \"parameter passed to testWidget3\" );\n\t\t\tvar ret = this._super( a, a*2 );\n\t\t\tdeepEqual( ret, 25, \"super returned value\" );\n\t\t}\n\t});\n\n\tinstance = $( \"<div>\" ).testWidget3().data( \"ui-testWidget3\" );\n\tinstance.method( 5 );\n\tdelete $.ui.testWidget3;\n\tdelete $.ui.testWidget2;\n});\n\ntest( \"._superApply()\", function() {\n\texpect( 10 );\n\tvar instance;\n\t$.widget( \"ui.testWidget\", {\n\t\tmethod: function( a, b ) {\n\t\t\tdeepEqual( this, instance, \"this is correct in testWidget\" );\n\t\t\tdeepEqual( a, 5, \"parameter passed to testWidget\" );\n\t\t\tdeepEqual( b, 10, \"second parameter passed to testWidget\" );\n\t\t\treturn a + b;\n\t\t}\n\t});\n\n\t$.widget( \"ui.testWidget2\", $.ui.testWidget, {\n\t\tmethod: function( a, b ) {\n\t\t\tdeepEqual( this, instance, \"this is correct in testWidget2\" );\n\t\t\tdeepEqual( a, 5, \"parameter passed to testWidget2\" );\n\t\t\tdeepEqual( b, 10, \"second parameter passed to testWidget2\" );\n\t\t\treturn this._superApply( arguments );\n\t\t}\n\t});\n\n\t$.widget( \"ui.testWidget3\", $.ui.testWidget2, {\n\t\tmethod: function( a, b ) {\n\t\t\tdeepEqual( this, instance, \"this is correct in testWidget3\" );\n\t\t\tdeepEqual( a, 5, \"parameter passed to testWidget3\" );\n\t\t\tdeepEqual( b, 10, \"second parameter passed to testWidget3\" );\n\t\t\tvar ret = this._superApply( arguments );\n\t\t\tdeepEqual( ret, 15, \"super returned value\" );\n\t\t}\n\t});\n\n\tinstance = $( \"<div>\" ).testWidget3().data( \"ui-testWidget3\" );\n\tinstance.method( 5, 10 );\n\tdelete $.ui.testWidget3;\n\tdelete $.ui.testWidget2;\n});\n\ntest( \".option() - getter\", function() {\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {}\n\t});\n\n\tvar options,\n\t\tdiv = $( \"<div>\" ).testWidget({\n\t\t\tfoo: \"bar\",\n\t\t\tbaz: 5,\n\t\t\tqux: [ \"quux\", \"quuux\" ]\n\t\t});\n\n\tdeepEqual( div.testWidget( \"option\", \"x\" ), null, \"non-existent option\" );\n\tdeepEqual( div.testWidget( \"option\", \"foo\"), \"bar\", \"single option - string\" );\n\tdeepEqual( div.testWidget( \"option\", \"baz\"), 5, \"single option - number\" );\n\tdeepEqual( div.testWidget( \"option\", \"qux\"), [ \"quux\", \"quuux\" ],\n\t\t\"single option - array\" );\n\n\toptions = div.testWidget( \"option\" );\n\tdeepEqual( options, {\n\t\tcreate: null,\n\t\tdisabled: false,\n\t\tfoo: \"bar\",\n\t\tbaz: 5,\n\t\tqux: [ \"quux\", \"quuux\" ]\n\t}, \"full options hash returned\" );\n\toptions.foo = \"notbar\";\n\tdeepEqual( div.testWidget( \"option\", \"foo\"), \"bar\",\n\t\t\"modifying returned options hash does not modify plugin instance\" );\n});\n\ntest( \".option() - deep option getter\", function() {\n\t$.widget( \"ui.testWidget\", {} );\n\tvar div = $( \"<div>\" ).testWidget({\n\t\tfoo: {\n\t\t\tbar: \"baz\",\n\t\t\tqux: {\n\t\t\t\tquux: \"xyzzy\"\n\t\t\t}\n\t\t}\n\t});\n\tequal( div.testWidget( \"option\", \"foo.bar\" ), \"baz\", \"one level deep - string\" );\n\tdeepEqual( div.testWidget( \"option\", \"foo.qux\" ), { quux: \"xyzzy\" },\n\t\t\"one level deep - object\" );\n\tequal( div.testWidget( \"option\", \"foo.qux.quux\" ), \"xyzzy\", \"two levels deep - string\" );\n\tequal( div.testWidget( \"option\", \"x.y\" ), null, \"top level non-existent\" );\n\tequal( div.testWidget( \"option\", \"foo.x.y\" ), null, \"one level deep - non-existent\" );\n});\n\ntest( \".option() - delegate to ._setOptions()\", function() {\n\tvar div,\n\t\tcalls = [];\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\t_setOptions: function( options ) {\n\t\t\tcalls.push( options );\n\t\t}\n\t});\n\tdiv = $( \"<div>\" ).testWidget();\n\n\tcalls = [];\n\tdiv.testWidget( \"option\", \"foo\", \"bar\" );\n\tdeepEqual( calls, [{ foo: \"bar\" }], \"_setOptions called for single option\" );\n\n\tcalls = [];\n\tdiv.testWidget( \"option\", {\n\t\tbar: \"qux\",\n\t\tquux: \"quuux\"\n\t});\n\tdeepEqual( calls, [{ bar: \"qux\", quux: \"quuux\" }],\n\t\t\"_setOptions called with multiple options\" );\n});\n\ntest( \".option() - delegate to ._setOption()\", function() {\n\tvar div,\n\t\tcalls = [];\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\t_setOption: function( key, val ) {\n\t\t\tcalls.push({\n\t\t\t\tkey: key,\n\t\t\t\tval: val\n\t\t\t});\n\t\t}\n\t});\n\tdiv = $( \"<div>\" ).testWidget();\n\n\tcalls = [];\n\tdiv.testWidget( \"option\", \"foo\", \"bar\" );\n\tdeepEqual( calls, [{ key: \"foo\", val: \"bar\" }],\n\t\t\"_setOption called for single option\" );\n\n\tcalls = [];\n\tdiv.testWidget( \"option\", {\n\t\tbar: \"qux\",\n\t\tquux: \"quuux\"\n\t});\n\tdeepEqual( calls, [\n\t\t{ key: \"bar\", val: \"qux\" },\n\t\t{ key: \"quux\", val: \"quuux\" }\n\t], \"_setOption called with multiple options\" );\n});\n\ntest( \".option() - deep option setter\", function() {\n\t$.widget( \"ui.testWidget\", {} );\n\tvar div = $( \"<div>\" ).testWidget();\n\tfunction deepOption( from, to, msg ) {\n\t\tdiv.data( \"ui-testWidget\" ).options.foo = from;\n\t\t$.ui.testWidget.prototype._setOption = function( key, value ) {\n\t\t\tdeepEqual( key, \"foo\", msg + \": key\" );\n\t\t\tdeepEqual( value, to, msg + \": value\" );\n\t\t};\n\t}\n\n\tdeepOption( { bar: \"baz\" }, { bar: \"qux\" }, \"one deep\" );\n\tdiv.testWidget( \"option\", \"foo.bar\", \"qux\" );\n\n\tdeepOption( null, { bar: \"baz\" }, \"null\" );\n\tdiv.testWidget( \"option\", \"foo.bar\", \"baz\" );\n\n\tdeepOption(\n\t\t{ bar: \"baz\", qux: { quux: \"quuux\" } },\n\t\t{ bar: \"baz\", qux: { quux: \"quuux\", newOpt: \"newVal\" } },\n\t\t\"add property\" );\n\tdiv.testWidget( \"option\", \"foo.qux.newOpt\", \"newVal\" );\n});\n\ntest( \".enable()\", function() {\n\texpect( 2 );\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\t_setOption: function( key, val ) {\n\t\t\tdeepEqual( key, \"disabled\", \"_setOption called with disabled option\" );\n\t\t\tdeepEqual( val, false, \"disabled set to false\" );\n\t\t}\n\t});\n\t$( \"<div>\" ).testWidget().testWidget( \"enable\" );\n});\n\ntest( \".disable()\", function() {\n\texpect( 2 );\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\t_setOption: function( key, val ) {\n\t\t\tdeepEqual( key, \"disabled\", \"_setOption called with disabled option\" );\n\t\t\tdeepEqual( val, true, \"disabled set to true\" );\n\t\t}\n\t});\n\t$( \"<div>\" ).testWidget().testWidget( \"disable\" );\n});\n\ntest( \".widget() - base\", function() {\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {}\n\t});\n\tvar div = $( \"<div>\" ).testWidget();\n\tdeepEqual( div[0], div.testWidget( \"widget\" )[0]);\n});\n\ntest( \".widget() - overriden\", function() {\n\tvar wrapper = $( \"<div>\" );\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\twidget: function() {\n\t\t\treturn wrapper;\n\t\t}\n\t});\n\tdeepEqual( wrapper[0], $( \"<div>\" ).testWidget().testWidget( \"widget\" )[0] );\n});\n\ntest( \"._bind() to element (default)\", function() {\n\texpect( 12 );\n\tvar that, widget;\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\t\tthat = this;\n\t\t\tthis._bind({\n\t\t\t\tkeyup: this.keyup,\n\t\t\t\tkeydown: \"keydown\"\n\t\t\t});\n\t\t},\n\t\tkeyup: function( event ) {\n\t\t\tequal( that, this );\n\t\t\tequal( that.element[0], event.currentTarget );\n\t\t\tequal( \"keyup\", event.type );\n\t\t},\n\t\tkeydown: function( event ) {\n\t\t\tequal( that, this );\n\t\t\tequal( that.element[0], event.currentTarget );\n\t\t\tequal( \"keydown\", event.type );\n\t\t}\n\t});\n\twidget = $( \"<div></div>\" )\n\t\t.testWidget()\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\twidget\n\t\t.testWidget( \"disable\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\twidget\n\t\t.testWidget( \"enable\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\twidget\n\t\t.testWidget( \"destroy\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n});\n\ntest( \"._bind() to descendent\", function() {\n\texpect( 12 );\n\tvar that, widget, descendant;\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\t\tthat = this;\n\t\t\tthis._bind( this.element.find( \"strong\" ), {\n\t\t\t\tkeyup: this.keyup,\n\t\t\t\tkeydown: \"keydown\"\n\t\t\t});\n\t\t},\n\t\tkeyup: function( event ) {\n\t\t\tequal( that, this );\n\t\t\tequal( that.element.find( \"strong\" )[0], event.currentTarget );\n\t\t\tequal( \"keyup\", event.type );\n\t\t},\n\t\tkeydown: function(event) {\n\t\t\tequal( that, this );\n\t\t\tequal( that.element.find( \"strong\" )[0], event.currentTarget );\n\t\t\tequal( \"keydown\", event.type );\n\t\t}\n\t});\n\t// trigger events on both widget and descendent to ensure that only descendent receives them\n\twidget = $( \"<div><p><strong>hello</strong> world</p></div>\" )\n\t\t.testWidget()\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\tdescendant = widget.find( \"strong\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\twidget\n\t\t.testWidget( \"disable\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\tdescendant\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\twidget\n\t\t.testWidget( \"enable\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\tdescendant\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\tdescendant\n\t\t.addClass( \"ui-state-disabled\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\twidget\n\t\t.testWidget( \"destroy\" )\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n\tdescendant\n\t\t.trigger( \"keyup\" )\n\t\t.trigger( \"keydown\" );\n});\n\ntest( \"_bind() with delegate\", function() {\n\texpect( 8 );\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\t\tthis.element = {\n\t\t\t\tbind: function( event, handler ) {\n\t\t\t\t\tequal( event, \"click.testWidget\" );\n\t\t\t\t\tok( $.isFunction(handler) );\n\t\t\t\t},\n\t\t\t\ttrigger: $.noop\n\t\t\t};\n\t\t\tthis.widget = function() {\n\t\t\t\treturn {\n\t\t\t\t\tdelegate: function( selector, event, handler ) {\n\t\t\t\t\t\tequal( selector, \"a\" );\n\t\t\t\t\t\tequal( event, \"click.testWidget\" );\n\t\t\t\t\t\tok( $.isFunction(handler) );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\t\t\tthis._bind({\n\t\t\t\t\"click\": \"handler\",\n\t\t\t\t\"click a\": \"handler\"\n\t\t\t});\n\t\t\tthis.widget = function() {\n\t\t\t\treturn {\n\t\t\t\t\tdelegate: function( selector, event, handler ) {\n\t\t\t\t\t\tequal( selector, \"form fieldset > input\" );\n\t\t\t\t\t\tequal( event, \"change.testWidget\" );\n\t\t\t\t\t\tok( $.isFunction(handler) );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\t\t\tthis._bind({\n\t\t\t\t\"change form fieldset > input\": \"handler\"\n\t\t\t});\n\t\t}\n\t});\n\t$.ui.testWidget();\n});\n\ntest( \"._hoverable()\", function() {\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\t\tthis._hoverable( this.element.children() );\n\t\t}\n\t});\n\n\tvar div = $( \"#widget\" ).testWidget().children();\n\tok( !div.hasClass( \"ui-state-hover\" ), \"not hovered on init\" );\n\tdiv.trigger( \"mouseenter\" );\n\tok( div.hasClass( \"ui-state-hover\" ), \"hovered after mouseenter\" );\n\tdiv.trigger( \"mouseleave\" );\n\tok( !div.hasClass( \"ui-state-hover\" ), \"not hovered after mouseleave\" );\n\n\tdiv.trigger( \"mouseenter\" );\n\tok( div.hasClass( \"ui-state-hover\" ), \"hovered after mouseenter\" );\n\t$( \"#widget\" ).testWidget( \"disable\" );\n\tok( !div.hasClass( \"ui-state-hover\" ), \"not hovered while disabled\" );\n\tdiv.trigger( \"mouseenter\" );\n\tok( !div.hasClass( \"ui-state-hover\" ), \"can't hover while disabled\" );\n\t$( \"#widget\" ).testWidget( \"enable\" );\n\tok( !div.hasClass( \"ui-state-hover\" ), \"enabling doesn't reset hover\" );\n\n\tdiv.trigger( \"mouseenter\" );\n\tok( div.hasClass( \"ui-state-hover\" ), \"hovered after mouseenter\" );\n\t$( \"#widget\" ).testWidget( \"destroy\" );\n\tok( !div.hasClass( \"ui-state-hover\" ), \"not hovered after destroy\" );\n\tdiv.trigger( \"mouseenter\" );\n\tok( !div.hasClass( \"ui-state-hover\" ), \"event handler removed on destroy\" );\n});\n\ntest( \"._focusable()\", function() {\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {\n\t\tthis._focusable( this.element.children() );\n\t}\n\t});\n\n\tvar div = $( \"#widget\" ).testWidget().children();\n\tok( !div.hasClass( \"ui-state-focus\" ), \"not focused on init\" );\n\tdiv.trigger( \"focusin\" );\n\tok( div.hasClass( \"ui-state-focus\" ), \"focused after explicit focus\" );\n\tdiv.trigger( \"focusout\" );\n\tok( !div.hasClass( \"ui-state-focus\" ), \"not focused after blur\" );\n\n\tdiv.trigger( \"focusin\" );\n\tok( div.hasClass( \"ui-state-focus\" ), \"focused after explicit focus\" );\n\t$( \"#widget\" ).testWidget( \"disable\" );\n\tok( !div.hasClass( \"ui-state-focus\" ), \"not focused while disabled\" );\n\tdiv.trigger( \"focusin\" );\n\tok( !div.hasClass( \"ui-state-focus\" ), \"can't focus while disabled\" );\n\t$( \"#widget\" ).testWidget( \"enable\" );\n\tok( !div.hasClass( \"ui-state-focus\" ), \"enabling doesn't reset focus\" );\n\n\tdiv.trigger( \"focusin\" );\n\tok( div.hasClass( \"ui-state-focus\" ), \"focused after explicit focus\" );\n\t$( \"#widget\" ).testWidget( \"destroy\" );\n\tok( !div.hasClass( \"ui-state-focus\" ), \"not focused after destroy\" );\n\tdiv.trigger( \"focusin\" );\n\tok( !div.hasClass( \"ui-state-focus\" ), \"event handler removed on destroy\" );\n});\n\ntest( \"._trigger() - no event, no ui\", function() {\n\texpect( 7 );\n\tvar handlers = [];\n\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {}\n\t});\n\n\t$( \"#widget\" ).testWidget({\n\t\tfoo: function( event, ui ) {\n\t\t\tdeepEqual( event.type, \"testwidgetfoo\", \"correct event type in callback\" );\n\t\t\tdeepEqual( ui, {}, \"empty ui hash passed\" );\n\t\t\thandlers.push( \"callback\" );\n\t\t}\n\t});\n\t$( document ).add( \"#widget-wrapper\" ).add( \"#widget\" )\n\t\t.bind( \"testwidgetfoo\", function( event, ui ) {\n\t\t\tdeepEqual( ui, {}, \"empty ui hash passed\" );\n\t\t\thandlers.push( this );\n\t\t});\n\tdeepEqual( $( \"#widget\" ).data( \"ui-testWidget\" )._trigger( \"foo\" ), true,\n\t\t\"_trigger returns true when event is not cancelled\" );\n\tdeepEqual( handlers, [\n\t\t$( \"#widget\" )[ 0 ],\n\t\t$( \"#widget-wrapper\" )[ 0 ],\n\t\tdocument,\n\t\t\"callback\"\n\t], \"event bubbles and then invokes callback\" );\n\n\t$( document ).unbind( \"testwidgetfoo\" );\n});\n\ntest( \"._trigger() - cancelled event\", function() {\n\texpect( 3 );\n\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {}\n\t});\n\n\t$( \"#widget\" ).testWidget({\n\t\tfoo: function( event, ui ) {\n\t\t\tok( true, \"callback invoked even if event is cancelled\" );\n\t\t}\n\t})\n\t.bind( \"testwidgetfoo\", function( event, ui ) {\n\t\tok( true, \"event was triggered\" );\n\t\treturn false;\n\t});\n\tdeepEqual( $( \"#widget\" ).data( \"ui-testWidget\" )._trigger( \"foo\" ), false,\n\t\t\"_trigger returns false when event is cancelled\" );\n});\n\ntest( \"._trigger() - cancelled callback\", function() {\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {}\n\t});\n\n\t$( \"#widget\" ).testWidget({\n\t\tfoo: function( event, ui ) {\n\t\t\treturn false;\n\t\t}\n\t});\n\tdeepEqual( $( \"#widget\" ).data( \"ui-testWidget\" )._trigger( \"foo\" ), false,\n\t\t\"_trigger returns false when callback returns false\" );\n});\n\ntest( \"._trigger() - provide event and ui\", function() {\n\texpect( 7 );\n\n\tvar originalEvent = $.Event( \"originalTest\" );\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\ttestEvent: function() {\n\t\t\tvar ui = {\n\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\tbaz: {\n\t\t\t\t\t\tqux: 5,\n\t\t\t\t\t\tquux: 20\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\tthis._trigger( \"foo\", originalEvent, ui );\n\t\t\tdeepEqual( ui, {\n\t\t\t\tfoo: \"notbar\",\n\t\t\t\tbaz: {\n\t\t\t\t\tqux: 10,\n\t\t\t\t\tquux: \"jQuery\"\n\t\t\t\t}\n\t\t\t}, \"ui object modified\" );\n\t\t}\n\t});\n\t$( \"#widget\" ).bind( \"testwidgetfoo\", function( event, ui ) {\n\t\tequal( event.originalEvent, originalEvent, \"original event object passed\" );\n\t\tdeepEqual( ui, {\n\t\t\tfoo: \"bar\",\n\t\t\tbaz: {\n\t\t\t\tqux: 5,\n\t\t\t\tquux: 20\n\t\t\t}\n\t\t}, \"ui hash passed\" );\n\t\tui.foo = \"notbar\";\n\t});\n\t$( \"#widget-wrapper\" ).bind( \"testwidgetfoo\", function( event, ui ) {\n\t\tequal( event.originalEvent, originalEvent, \"original event object passed\" );\n\t\tdeepEqual( ui, {\n\t\t\tfoo: \"notbar\",\n\t\t\tbaz: {\n\t\t\t\tqux: 5,\n\t\t\t\tquux: 20\n\t\t\t}\n\t\t}, \"modified ui hash passed\" );\n\t\tui.baz.qux = 10;\n\t});\n\t$( \"#widget\" ).testWidget({\n\t\tfoo: function( event, ui ) {\n\t\t\tequal( event.originalEvent, originalEvent, \"original event object passed\" );\n\t\t\tdeepEqual( ui, {\n\t\t\t\tfoo: \"notbar\",\n\t\t\t\tbaz: {\n\t\t\t\t\tqux: 10,\n\t\t\t\t\tquux: 20\n\t\t\t\t}\n\t\t\t}, \"modified ui hash passed\" );\n\t\t\tui.baz.quux = \"jQuery\";\n\t\t}\n\t})\n\t.testWidget( \"testEvent\" );\n});\n\ntest( \"._trigger() - array as ui\", function() {\n\t// #6795 - Widget: handle array arguments to _trigger consistently\n\texpect( 4 );\n\n\t$.widget( \"ui.testWidget\", {\n\t\t_create: function() {},\n\t\ttestEvent: function() {\n\t\t\tvar ui = {\n\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\tbaz: {\n\t\t\t\t\t\tqux: 5,\n\t\t\t\t\t\tquux: 20\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\textra = {\n\t\t\t\t\tbar: 5\n\t\t\t\t};\n\t\t\tthis._trigger( \"foo\", null, [ ui, extra ] );\n\t\t}\n\t});\n\t$( \"#widget\" ).bind( \"testwidgetfoo\", function( event, ui, extra ) {\n\t\tdeepEqual( ui, {\n\t\t\tfoo: \"bar\",\n\t\t\tbaz: {\n\t\t\t\tqux: 5,\n\t\t\t\tquux: 20\n\t\t\t}\n\t\t}, \"event: ui hash passed\" );\n\t\tdeepEqual( extra, {\n\t\t\tbar: 5\n\t\t}, \"event: extra argument passed\" );\n\t});\n\t$( \"#widget\" ).testWidget({\n\t\tfoo: function( event, ui, extra ) {\n\t\t\tdeepEqual( ui, {\n\t\t\t\tfoo: \"bar\",\n\t\t\t\tbaz: {\n\t\t\t\t\tqux: 5,\n\t\t\t\t\tquux: 20\n\t\t\t\t}\n\t\t\t}, \"callback: ui hash passed\" );\n\t\t\tdeepEqual( extra, {\n\t\t\t\tbar: 5\n\t\t\t}, \"callback: extra argument passed\" );\n\t\t}\n\t})\n\t.testWidget( \"testEvent\" );\n});\n\ntest( \"._trigger() - instance as element\", function() {\n\texpect( 4 );\n\t$.widget( \"ui.testWidget\", {\n\t\tdefaultElement: null,\n\t\ttestEvent: function() {\n\t\t\tthis._trigger( \"foo\", null, { foo: \"bar\" } );\n\t\t}\n\t});\n\tvar instance = $.ui.testWidget({\n\t\tfoo: function( event, ui ) {\n\t\t\tequal( event.type, \"testwidgetfoo\", \"event object passed to callback\" );\n\t\t\tdeepEqual( ui, { foo: \"bar\" }, \"ui object passed to callback\" );\n\t\t}\n\t});\n\t$( instance ).bind( \"testwidgetfoo\", function( event, ui ) {\n\t\tequal( event.type, \"testwidgetfoo\", \"event object passed to event handler\" );\n\t\tdeepEqual( ui, { foo: \"bar\" }, \"ui object passed to event handler\" );\n\t});\n\tinstance.testEvent();\n});\n\n(function() {\n\tfunction shouldDestroy( expected, callback ) {\n\t\texpect( 1 );\n\t\tvar destroyed = false;\n\t\t$.widget( \"ui.testWidget\", {\n\t\t\t_create: function() {},\n\t\t\tdestroy: function() {\n\t\t\t\tdestroyed = true;\n\t\t\t}\n\t\t});\n\t\tcallback();\n\t\tequal( destroyed, expected );\n\t}\n\n\ttest( \"auto-destroy - .remove()\", function() {\n\t\tshouldDestroy( true, function() {\n\t\t\t$( \"#widget\" ).testWidget().remove();\n\t\t});\n\t});\n\n\ttest( \"auto-destroy - .remove() on parent\", function() {\n\t\tshouldDestroy( true, function() {\n\t\t\t$( \"#widget\" ).testWidget().parent().remove();\n\t\t});\n\t});\n\n\ttest( \"auto-destroy - .remove() on child\", function() {\n\t\tshouldDestroy( false, function() {\n\t\t\t$( \"#widget\" ).testWidget().children().remove();\n\t\t});\n\t});\n\n\ttest( \"auto-destroy - .empty()\", function() {\n\t\tshouldDestroy( false, function() {\n\t\t\t$( \"#widget\" ).testWidget().empty();\n\t\t});\n\t});\n\n\ttest( \"auto-destroy - .empty() on parent\", function() {\n\t\tshouldDestroy( true, function() {\n\t\t\t$( \"#widget\" ).testWidget().parent().empty();\n\t\t});\n\t});\n\n\ttest( \"auto-destroy - .detach()\", function() {\n\t\tshouldDestroy( false, function() {\n\t\t\t$( \"#widget\" ).testWidget().detach();\n\t\t});\n\t});\n}());\n\ntest( \"redefine\", function() {\n\texpect( 4 );\n\t$.widget( \"ui.testWidget\", {\n\t\tmethod: function( str ) {\n\t\t\tstrictEqual( this, instance, \"original invoked with correct this\" );\n\t\t\tequal( str, \"bar\", \"original invoked with correct parameter\" );\n\t\t}\n\t});\n\t$.ui.testWidget.foo = \"bar\";\n\t$.widget( \"ui.testWidget\", $.ui.testWidget, {\n\t\tmethod: function( str ) {\n\t\t\tequal( str, \"foo\", \"new invoked with correct parameter\" );\n\t\t\tthis._super( \"bar\" );\n\t\t}\n\t});\n\n\tvar instance = new $.ui.testWidget({});\n\tinstance.method( \"foo\" );\n\tequal( $.ui.testWidget.foo, \"bar\", \"static properties remain\" );\n});\n\ntest( \"redefine deep prototype chain\", function() {\n\texpect( 8 );\n\t$.widget( \"ui.testWidget\", {\n\t\tmethod: function( str ) {\n\t\t\tstrictEqual( this, instance, \"original invoked with correct this\" );\n\t\t\tequal( str, \"level 4\", \"original invoked with correct parameter\" );\n\t\t}\n\t});\n\t$.widget( \"ui.testWidget2\", $.ui.testWidget, {\n\t\tmethod: function( str ) {\n\t\t\tstrictEqual( this, instance, \"testWidget2 invoked with correct this\" );\n\t\t\tequal( str, \"level 2\", \"testWidget2 invoked with correct parameter\" );\n\t\t\tthis._super( \"level 3\" );\n\t\t}\n\t});\n\t$.widget( \"ui.testWidget3\", $.ui.testWidget2, {\n\t\tmethod: function( str ) {\n\t\t\tstrictEqual( this, instance, \"testWidget3 invoked with correct this\" );\n\t\t\tequal( str, \"level 1\", \"testWidget3 invoked with correct parameter\" );\n\t\t\tthis._super( \"level 2\" );\n\t\t}\n\t});\n\t// redefine testWidget after other widgets have inherited from it\n\t// this tests whether the inheriting widgets get updated prototype chains\n\t$.widget( \"ui.testWidget\", $.ui.testWidget, {\n\t\tmethod: function( str ) {\n\t\t\tstrictEqual( this, instance, \"new invoked with correct this\" );\n\t\t\tequal( str, \"level 3\", \"new invoked with correct parameter\" );\n\t\t\tthis._super( \"level 4\" );\n\t\t}\n\t});\n\t// redefine testWidget3 after it has been automatically redefined\n\t// this tests whether we properly handle _super() when the topmost prototype\n\t// doesn't have the method defined\n\t$.widget( \"ui.testWidget3\", $.ui.testWidget3, {} );\n\n\tvar instance = new $.ui.testWidget3({});\n\tinstance.method( \"level 1\" );\n\n\tdelete $.ui.testWidget3;\n\tdelete $.ui.testWidget2;\n});\n\nasyncTest( \"_delay\", function() {\n\texpect( 6 );\n\tvar order = 0,\n\t\tthat;\n\t$.widget( \"ui.testWidget\", {\n\t\tdefaultElement: null,\n\t\t_create: function() {\n\t\t\tthat = this;\n\t\t\tvar timer = this._delay(function() {\n\t\t\t\tstrictEqual( this, that );\n\t\t\t\tequal( order, 1 );\n\t\t\t\tstart();\n\t\t\t}, 500);\n\t\t\tok( timer !== undefined );\n\t\t\ttimer = this._delay(\"callback\");\n\t\t\tok( timer !== undefined );\n\t\t},\n\t\tcallback: function() {\n\t\t\tstrictEqual( this, that );\n\t\t\tequal( order, 0 );\n\t\t\torder += 1;\n\t\t}\n\t});\n\t$( \"#widget\" ).testWidget();\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/unit/widget/widget_extend.js",
    "content": "test( \"$.widget.extend()\", function() {\n\texpect( 26 );\n\n\tvar ret, empty, optionsWithLength, optionsWithDate, myKlass, customObject, optionsWithCustomObject, nullUndef,\n\t\ttarget, recursive, obj, input, output,\n\t\tsettings = { xnumber1: 5, xnumber2: 7, xstring1: \"peter\", xstring2: \"pan\" },\n\t\toptions = { xnumber2: 1, xstring2: \"x\", xxx: \"newstring\" },\n\t\toptionsCopy = { xnumber2: 1, xstring2: \"x\", xxx: \"newstring\" },\n\t\tmerged = { xnumber1: 5, xnumber2: 1, xstring1: \"peter\", xstring2: \"x\", xxx: \"newstring\" },\n\t\tdeep1 = { foo: { bar: true } },\n\t\tdeep2 = { foo: { baz: true }, foo2: document },\n\t\tdeep2copy = { foo: { baz: true }, foo2: document },\n\t\tdeepmerged = { foo: { bar: true, baz: true }, foo2: document },\n\t\tarr = [1, 2, 3],\n\t\tnestedarray = { arr: arr },\n\t\tdefaults = { xnumber1: 5, xnumber2: 7, xstring1: \"peter\", xstring2: \"pan\" },\n\t\tdefaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: \"peter\", xstring2: \"pan\" },\n\t\toptions1 = { xnumber2: 1, xstring2: \"x\" },\n\t\toptions1Copy = { xnumber2: 1, xstring2: \"x\" },\n\t\toptions2 = { xstring2: \"xx\", xxx: \"newstringx\" },\n\t\toptions2Copy = { xstring2: \"xx\", xxx: \"newstringx\" },\n\t\tmerged2 = { xnumber1: 5, xnumber2: 1, xstring1: \"peter\", xstring2: \"xx\", xxx: \"newstringx\" };\n\n\t$.widget.extend( settings, options );\n\tdeepEqual( settings, merged, \"Check if extended: settings must be extended\" );\n\tdeepEqual( options, optionsCopy, \"Check if not modified: options must not be modified\" );\n\n\t$.widget.extend( deep1, deep2 );\n\tdeepEqual( deep1.foo, deepmerged.foo, \"Check if foo: settings must be extended\" );\n\tdeepEqual( deep2.foo, deep2copy.foo, \"Check if not deep2: options must not be modified\" );\n\tequal( deep1.foo2, document, \"Make sure that a deep clone was not attempted on the document\" );\n\n\tstrictEqual( $.widget.extend({}, nestedarray).arr, arr, \"Don't clone arrays\" );\n\tok( $.isPlainObject( $.widget.extend({ arr: arr }, { arr: {} }).arr ), \"Cloned object heve to be an plain object\" );\n\n\tempty = {};\n\toptionsWithLength = { foo: { length: -1 } };\n\t$.widget.extend( empty, optionsWithLength );\n\tdeepEqual( empty.foo, optionsWithLength.foo, \"The length property must copy correctly\" );\n\n\tempty = {};\n\toptionsWithDate = { foo: { date: new Date() } };\n\t$.widget.extend( empty, optionsWithDate );\n\tdeepEqual( empty.foo, optionsWithDate.foo, \"Dates copy correctly\" );\n\n\tmyKlass = function() {};\n\tcustomObject = new myKlass();\n\toptionsWithCustomObject = { foo: { date: customObject } };\n\tempty = {};\n\t$.widget.extend( empty, optionsWithCustomObject );\n\tstrictEqual( empty.foo.date, customObject, \"Custom objects copy correctly (no methods)\" );\n\n\t// Makes the class a little more realistic\n\tmyKlass.prototype = { someMethod: function(){} };\n\tempty = {};\n\t$.widget.extend( empty, optionsWithCustomObject );\n\tstrictEqual( empty.foo.date, customObject, \"Custom objects copy correctly\" );\n\n\tret = $.widget.extend({ foo: 4 }, { foo: Number(5) } );\n\tequal( ret.foo, 5, \"Wrapped numbers copy correctly\" );\n\n\tnullUndef = $.widget.extend( {}, options, { xnumber2: null } );\n\tstrictEqual( nullUndef.xnumber2, null, \"Check to make sure null values are copied\");\n\n\tnullUndef = $.widget.extend( {}, options, { xnumber2: undefined } );\n\tstrictEqual( nullUndef.xnumber2, options.xnumber2, \"Check to make sure undefined values are not copied\");\n\n\tnullUndef = $.widget.extend( {}, options, { xnumber0: null } );\n\tstrictEqual( nullUndef.xnumber0, null, \"Check to make sure null values are inserted\");\n\n\ttarget = {};\n\trecursive = { foo:target, bar:5 };\n\t$.widget.extend( target, recursive );\n\tdeepEqual( target, { foo: {}, bar: 5 }, \"Check to make sure a recursive obj doesn't go never-ending loop by not copying it over\" );\n\n\tret = $.widget.extend( { foo: [] }, { foo: [0] } ); // 1907\n\tequal( ret.foo.length, 1, \"Check to make sure a value with coersion 'false' copies over when necessary to fix #1907\" );\n\n\tret = $.widget.extend( { foo: \"1,2,3\" }, { foo: [1, 2, 3] } );\n\tstrictEqual( typeof ret.foo, \"object\", \"Check to make sure values equal with coersion (but not actually equal) overwrite correctly\" );\n\n\tret = $.widget.extend( { foo:\"bar\" }, { foo:null } );\n\tstrictEqual( typeof ret.foo, \"object\", \"Make sure a null value doesn't crash with deep extend, for #1908\" );\n\n\tobj = { foo:null };\n\t$.widget.extend( obj, { foo:\"notnull\" } );\n\tequal( obj.foo, \"notnull\", \"Make sure a null value can be overwritten\" );\n\n\tsettings = $.widget.extend( {}, defaults, options1, options2 );\n\tdeepEqual( settings, merged2, \"Check if extended: settings must be extended\" );\n\tdeepEqual( defaults, defaultsCopy, \"Check if not modified: options1 must not be modified\" );\n\tdeepEqual( options1, options1Copy, \"Check if not modified: options1 must not be modified\" );\n\tdeepEqual( options2, options2Copy, \"Check if not modified: options2 must not be modified\" );\n\n\tinput = {\n\t\tkey: [ 1, 2, 3 ]\n\t};\n\toutput = $.widget.extend( {}, input );\n\tdeepEqual( input, output, \"don't clone arrays\" );\n\tinput.key[0] = 10;\n\tdeepEqual( input, output, \"don't clone arrays\" );\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/accordion/icons.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Accordion Visual Test</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion-ynynyn\" ).accordion({ icons: null });\n\t\t$( \"#accordion-ynyny\" ).accordion();\n\t\t$( \"#accordion-ynyn\" ).accordion({ icons: null });\n\t\t$( \"#accordion-yny\" ).accordion();\n\t\t$( \"#accordion-yn\" ).accordion({ icons: null });\n\t\t$( \"#accordion-y\" ).accordion();\n\n\t\t$( \"#accordion-nynyny\" ).accordion();\n\t\t$( \"#accordion-nynyn\" ).accordion({ icons: null });\n\t\t$( \"#accordion-nyny\" ).accordion();\n\t\t$( \"#accordion-nyn\" ).accordion({ icons: null });\n\t\t$( \"#accordion-ny\" ).accordion();\n\t\t$( \"#accordion-n\" ).accordion({ icons: null });\n\t});\n\t</script>\n</head>\n<body>\n\n<p>WHAT: The following set of nested accordions alternate between icons and no icons.</p>\n<p>EXPECTED: The padding on the headers should correctly account for the icon settings.</p>\n\n<div id=\"accordion-y\">\n\t<div>Icons</div>\n\t<div>\n\t\t<div id=\"accordion-yn\">\n\t\t\t<div>No Icons</div>\n\t\t\t<div>\n\t\t\t\t<div id=\"accordion-yny\">\n\t\t\t\t\t<div>Icons</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div id=\"accordion-ynyn\">\n\t\t\t\t\t\t\t<div>No Icons</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<div id=\"accordion-ynyny\">\n\t\t\t\t\t\t\t\t\t<div>Icons</div>\n\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t<div id=\"accordion-ynynyn\">\n\t\t\t\t\t\t\t\t\t\t\t<div>No Icons</div>\n\t\t\t\t\t\t\t\t\t\t\t<div></div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n<div id=\"accordion-n\">\n\t<div>No Icons</div>\n\t<div>\n\t\t<div id=\"accordion-ny\">\n\t\t\t<div>Icons</div>\n\t\t\t<div>\n\t\t\t\t<div id=\"accordion-nyn\">\n\t\t\t\t\t<div>No Icons</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div id=\"accordion-nyny\">\n\t\t\t\t\t\t\t<div>Icons</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<div id=\"accordion-nynyn\">\n\t\t\t\t\t\t\t\t\t<div>No Icons</div>\n\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t<div id=\"accordion-nynyny\">\n\t\t\t\t\t\t\t\t\t\t\t<div>Icons</div>\n\t\t\t\t\t\t\t\t\t\t\t<div></div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/addClass/queue.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>addClass Visual Test : Queue</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.core.js\"></script>\n\t<style>\n\t.box {\n\t\twidth: 100px;\n\t\theight: 100px;\n\t\tbackground-color: #000;\n\t}\n\t.red {\n\t\tbackground-color: #f00;\n\t}\n\t.green {\n\t\tbackground-color: #0f0;\n\t}\n\t.blue {\n\t\tbackground-color: #00f;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"#box1\" )\n\t\t\t.delay( 500 )\n\t\t\t.addClass( \"red\", 2000 )\n\t\t\t.delay( 500 )\n\t\t\t.addClass( \"green\", 2000 )\n\t\t\t.delay( 500 )\n\t\t\t.addClass( \"blue\", 2000 );\n\t\t$( \"#box2\" )\n\t\t\t.addClass( \"red\", 2000 )\n\t\t\t.delay( 500 )\n\t\t\t.addClass( \"green\", 2000 )\n\t\t\t.delay( 500 )\n\t\t\t.addClass( \"blue\", 2000 );\n\t});\n\t</script>\n</head>\n<body>\n\n<p>WHAT: The two boxes animate from black to red to green to blue.</p>\n<p>EXPECTED: The first box should start with a delay, the second box should start immediately.</p>\n\n<div id=\"box1\" class=\"box\"></div>\n<div id=\"box2\" class=\"box\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/button/button.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Button Visual Test</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.button.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \".buttons\" ).each(function() {\n\t\t\t$( this ).children()\n\t\t\t\t.eq( 0 )\n\t\t\t\t\t.button({\n\t\t\t\t\t\ttext: false,\n\t\t\t\t\t\ticons: {\n\t\t\t\t\t\t\tprimary: \"ui-icon-help\"\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t.end()\n\t\t\t\t.eq( 1 )\n\t\t\t\t\t.button({\n\t\t\t\t\t\ticons: {\n\t\t\t\t\t\t\tprimary: \"ui-icon-help\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdisabled: true\n\t\t\t\t\t})\n\t\t\t\t.end()\n\t\t\t\t.eq( 2 )\n\t\t\t\t\t.button();\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"buttons\">\n\t<button>button</button>\n\t<button>button</button>\n\t<button>button</button>\n</div>\n\n<div class=\"buttons\">\n\t<button type=\"button\">button button</button>\n\t<button type=\"button\">button button</button>\n\t<button type=\"button\">button button</button>\n</div>\n\n<div class=\"buttons\">\n\t<button type=\"submit\">button submit</button>\n\t<button type=\"submit\">button submit</button>\n\t<button type=\"submit\">button submit</button>\n</div>\n\n<div class=\"buttons\">\n\t<input type=\"button\" value=\"input button\">\n\t<input type=\"button\" value=\"input button\">\n\t<input type=\"button\" value=\"input button\">\n</div>\n\n<div class=\"buttons\">\n\t<input type=\"submit\" value=\"input submit\">\n\t<input type=\"submit\" value=\"input submit\">\n\t<input type=\"submit\" value=\"input submit\">\n</div>\n\n<div class=\"buttons\">\n\t<input type=\"checkbox\" id=\"input-checkbox0\">\n\t<input type=\"checkbox\" id=\"input-checkbox1\">\n\t<input type=\"checkbox\" id=\"input-checkbox2\">\n\t<label for=\"input-checkbox0\">input checkbox</label>\n\t<label for=\"input-checkbox1\">input checkbox</label>\n\t<label for=\"input-checkbox2\">input checkbox</label>\n</div>\n\n<div class=\"buttons\">\n\t<input type=\"radio\" id=\"input-radio0\" name=\"radio\">\n\t<input type=\"radio\" id=\"input-radio1\" name=\"radio\">\n\t<input type=\"radio\" id=\"input-radio2\" name=\"radio\">\n\t<label for=\"input-radio0\">input radio</label>\n\t<label for=\"input-radio1\">input radio</label>\n\t<label for=\"input-radio2\">input radio</label>\n</div>\n\n<div class=\"buttons\">\n\t<a href=\"#\">anchor</a>\n\t<a href=\"#\">anchor</a>\n\t<a href=\"#\">anchor</a>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/button/performance.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Button Visual Test: Initialization Performance</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.button.js\"></script>\n\t<script>\n\t$(function() {\n\t\tvar start,\n\t\t\thtml = new Array( 500 ).join( \"<button>button</button>\" );\n\t\t$( html ).appendTo( \"body\" );\n\n\t\tstart = $.now();\n\t\t$( \"button\" ).button();\n\t\t$( \"<p>\" ).text( \"Time to initialize: \" + ($.now() - start)  + \"ms\" ).prependTo( \"body\" );\n\t});\n\t</script>\n</head>\n<body>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/accordion_tabs.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Accordion in Tabs</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tabs.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion-1, #accordion-2\" ).accordion();\n\t\t$( \"#tabs\" ).tabs();\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">First</a></li>\n\t\t<li><a href=\"#tabs-2\">Second</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<div id=\"accordion-1\">\n\t\t\t<h3>Accordion Header 1</h3>\n\t\t\t<div>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t</div>\n\t\t\t<h3>Accordion Header 2</h3>\n\t\t\t<div>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t</div>\n\t\t\t<h3>Accordion Header 3</h3>\n\t\t\t<div>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<div id=\"accordion-2\">\n\t\t\t<h3>Accordion Header 1</h3>\n\t\t\t<div>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t</div>\n\t\t\t<h3>Accordion Header 2</h3>\n\t\t\t<div>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t</div>\n\t\t\t<h3>Accordion Header 3</h3>\n\t\t\t<div>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/datepicker_dialog.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Datepicker in Dialog</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.datepicker.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.dialog.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"#datepicker\" ).datepicker();\n\t\t$( \"#dialog\" ).dialog();\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"dialog\">\n\t<input id=\"datepicker\">\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/dialog_widgets.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : All Widgets in Dialog</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.menu.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.autocomplete.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.datepicker.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.dialog.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.progressbar.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.slider.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tabs.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tooltip.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"[title]\" ).tooltip();\n\t\t$( \"#accordion\" ).accordion();\n\t\t$( \"#autocomplete\" ).autocomplete({\n\t\t\tsource: [ \"c++\", \"java\", \"php\", \"coldfusion\", \"javascript\", \"asp\", \"ruby\", \"python\", \"c\", \"scala\", \"groovy\", \"haskell\", \"perl\" ]\n\t\t});\n\t\t$( \"button\" ).button().click(function() {\n\t\t\t$( \"#dialog2\" ).dialog( \"open\" );\n\t\t});\n\t\t$( \"#datepicker\" ).datepicker();\n\t\t$( \"#progressbar\" ).progressbar({\n\t\t\tvalue: 30\n\t\t});\n\t\t$( \"#slider\" ).slider({\n\t\t\tanimate: true,\n\t\t\tvalue: 30,\n\t\t\tslide: function(event, ui) {\n\t\t\t\t$( \"#progress\" ).val( ui.value );\n\t\t\t\t$( \"#progressbar\" ).progressbar( \"option\", \"value\", ui.value );\n\t\t\t}\n\t\t});\n\t\t$( \"#tabs\" ).tabs();\n\t\t$( \"#dialog\" ).dialog();\n\t\t$( \"#dialog2\" ).dialog({\n\t\t\tautoOpen: false,\n\t\t\twidth: 100,\n\t\t\theight: 75,\n\t\t\tmodal: true\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"dialog\">\n\t<div id=\"accordion\">\n\t\t<h3>Accordion Header 1</h3>\n\t\t<div>\n\t\t\tAccordion Content 1\n\t\t</div>\n\t\t<h3>Accordion Header 2</h3>\n\t\t<div>\n\t\t\tAccordion Content 2\n\t\t</div>\n\t\t<h3>Accordion Header 3</h3>\n\t\t<div>\n\t\t\tAccordion Content 3\n\t\t</div>\n\t</div>\n\t<input id=\"autocomplete\">\n\t<button>A Button</button>\n\t<input id=\"datepicker\">\n\t<button>Another button</button>\n\t<div>\n\t\t<label for=\"progress\">Progress: <input title=\"The progress we made so far\" id=\"progress\"></label>\n\t</div>\n\t<div id=\"progressbar\">\n\t</div>\n\t<div id=\"slider\" title=\"Sliding progress...\"></div>\n\t<div id=\"tabs\">\n\t\t<ul>\n\t\t\t<li><a href=\"#tabs-1\">First</a></li>\n\t\t\t<li><a href=\"#tabs-2\">Second</a></li>\n\t\t\t<li><a href=\"#tabs-3\">Third</a></li>\n\t\t</ul>\n\t\t<div id=\"tabs-1\">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>\n\t\t<div id=\"tabs-2\">Phasellus mattis tincidunt nibh.</div>\n\t\t<div id=\"tabs-3\">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>\n\t</div>\n</div>\n<div id=\"dialog2\">\n\tYay, another dialog.\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/draggable_accordion.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Draggable in Accordion</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.draggable.js\"></script>\n\t<style>\n\t.draggable {\n\t\twidth: 10em;\n\t\tmargin: 0.5em;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \".draggable\" ).addClass( \"ui-widget ui-widget-content ui-corner-all\" )\n\t\t$( \"#first .draggable\" ).draggable();\n\t\t$( \"#second .draggable\" ).draggable({\n\t\t\tappendTo: \"body\"\n\t\t});\n\t\t$( \"#third .draggable\" ).draggable({\n\t\t\thelper: \"clone\",\n\t\t\tappendTo: \"body\"\n\t\t});\n\t\t$( \"#accordion\" ).accordion();\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"accordion\">\n\t<h3>.draggable()</h3>\n\t<div id=\"first\">\n\t\t<div class=\"draggable\">Draggable 1-1</div>\n\t\t<div class=\"draggable\">Draggable 1-2</div>\n\t\t<div class=\"draggable\">Draggable 1-3</div>\n\t\t<div class=\"draggable\">Draggable 1-4</div>\n\t\t<div class=\"draggable\">Draggable 1-5</div>\n\t</div>\n\t<h3>.draggable({ appendTo: \"body\" })</h3>\n\t<div id=\"second\">\n\t\t<div class=\"draggable\">Draggable 2-1</div>\n\t\t<div class=\"draggable\">Draggable 2-2</div>\n\t\t<div class=\"draggable\">Draggable 2-3</div>\n\t\t<div class=\"draggable\">Draggable 2-4</div>\n\t\t<div class=\"draggable\">Draggable 2-5</div>\n\t</div>\n\t<h3>.draggable({ helper: \"clone\", appendTo: \"body\" })</h3>\n\t<div id=\"third\">\n\t\t<div class=\"draggable\">Draggable 3-1</div>\n\t\t<div class=\"draggable\">Draggable 3-2</div>\n\t\t<div class=\"draggable\">Draggable 3-3</div>\n\t\t<div class=\"draggable\">Draggable 3-4</div>\n\t\t<div class=\"draggable\">Draggable 3-5</div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/draggable_accordion_accordion_tabs_draggable.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Draggable in Accordion</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tabs.js\"></script>\n\t<style>\n\t#main-draggable {\n\t\twidth: 300px;\n\t\tposition: absolute;\n\t\tright: 100px;\n\t}\n\t#main-draggable-handle {\n\t\tpadding: 1em;\n\t\tmargin: 0;\n\t}\n\t.draggable {\n\t\twidth: 10em;\n\t\tmargin: 0.5em;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \".draggable\" )\n\t\t\t.addClass( \"ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.draggable({\n\t\t\t\thelper: \"clone\",\n\t\t\t\tappendTo: \"body\"\n\t\t\t});\n\n\t\t$( \"#accordion > div\" ).accordion();\n\t\t$( \"#accordion\" ).accordion();\n\n\t\t$( \"#tabs\" ).tabs();\n\n\t\t$( \"#main-draggable\" ).draggable({\n\t\t\thandle: \"#main-draggable-handle\"\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n<div id=\"main-draggable\" class=\"ui-widget ui-widget-content ui-corner-all\">\n\t<p id=\"main-draggable-handle\" class=\"ui-widget-header ui-corner-all\">Drag me around!</p>\n\t<div id=\"tabs\">\n\t\t<ul>\n\t\t\t<li><a href=\"#tabs-1\">First Tab</a></li>\n\t\t\t<li><a href=\"#tabs-2\">Second Tab</a></li>\n\t\t</ul>\n\t\t<div id=\"tabs-1\">\n\t\t\t<p>Click the other tab!</p>\n\t\t</div>\n\t\t<div id=\"tabs-2\">\n\t\t\t<div id=\"accordion\">\n\t\t\t\t<h3>Accordion Group 1</h3>\n\t\t\t\t<div id=\"accordion-1-1\">\n\t\t\t\t\t<h3>Header 1-1</h3>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-1</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-2</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-3</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-4</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-5</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3>Header 1-2</h3>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-1</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-2</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-3</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-4</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-5</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<h3>Accordion Group 2</h3>\n\t\t\t\t<div id=\"accordion-1-2\">\n\t\t\t\t\t<h3>Header 2-1</h3>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-1</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-2</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-3</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-4</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 1-5</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h3>Header 2-2</h3>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-1</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-2</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-3</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-4</div>\n\t\t\t\t\t\t<div class=\"draggable\">Draggable 2-5</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/sortable_accordion_sortable_tabs.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Accordion in Tabs</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.sortable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tabs.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"#accordion-1, #accordion-2\" )\n\t\t\t.accordion({\n\t\t\t\theader: \"> div > h3\"\n\t\t\t})\n\t\t\t.sortable();\n\n\t\t$( \"#tabs\" )\n\t\t\t.tabs()\n\t\t\t.find( \".ui-tabs-nav\" )\n\t\t\t\t.sortable();\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">1 - Accordion</a></li>\n\t\t<li><a href=\"#tabs-2\">2 - Empty</a></li>\n\t\t<li><a href=\"#tabs-3\">3 - Empty</a></li>\n\t\t<li><a href=\"#tabs-4\">4 - Accordion</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<div id=\"accordion-1\">\n\t\t\t<div>\n\t\t\t\t<h3>Accordion Header 1</h3>\n\t\t\t\t<div>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h3>Accordion Header 2</h3>\n\t\t\t\t<div>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h3>Accordion Header 3</h3>\n\t\t\t\t<div>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<p>Nothing to look at here...</p>\n\t</div>\n\t<div id=\"tabs-3\">\n\t\t<p>Nothing to look at here...</p>\n\t</div>\n\t<div id=\"tabs-4\">\n\t\t<div id=\"accordion-2\">\n\t\t\t<div>\n\t\t\t\t<h3>Accordion Header 1</h3>\n\t\t\t\t<div>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t\t<p>Accordion Content 1</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h3>Accordion Header 2</h3>\n\t\t\t\t<div>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t\t<p>Accordion Content 2</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h3>Accordion Header 3</h3>\n\t\t\t\t<div>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t\t<p>Accordion Content 3</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/tabs_tabs.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Tabs in Tabs</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.accordion.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tabs.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs, #tabs-a, #tabs-b\" ).tabs();\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\">First</a></li>\n\t\t<li><a href=\"#tabs-2\">Second</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<div id=\"tabs-a\">\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#tabs-a-1\">First</a></li>\n\t\t\t\t<li><a href=\"#tabs-a-2\">Second</a></li>\n\t\t\t</ul>\n\t\t\t<div id=\"tabs-a-1\">\n\t\t\t\t<p>nested tabs a-1</p>\n\t\t\t\t<p>nested tabs a-1</p>\n\t\t\t\t<p>nested tabs a-1</p>\n\t\t\t\t<p>nested tabs a-1</p>\n\t\t\t\t<p>nested tabs a-1</p>\n\t\t\t</div>\n\t\t\t<div id=\"tabs-a-2\">\n\t\t\t\t<p>nested tabs a-2</p>\n\t\t\t\t<p>nested tabs a-2</p>\n\t\t\t\t<p>nested tabs a-2</p>\n\t\t\t\t<p>nested tabs a-2</p>\n\t\t\t\t<p>nested tabs a-2</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<div id=\"tabs-b\">\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#tabs-b-1\">First</a></li>\n\t\t\t\t<li><a href=\"#tabs-b-2\">Second</a></li>\n\t\t\t</ul>\n\t\t\t<div id=\"tabs-b-1\">\n\t\t\t\t<p>nested tabs b-1</p>\n\t\t\t\t<p>nested tabs b-1</p>\n\t\t\t\t<p>nested tabs b-1</p>\n\t\t\t\t<p>nested tabs b-1</p>\n\t\t\t\t<p>nested tabs b-1</p>\n\t\t\t</div>\n\t\t\t<div id=\"tabs-b-2\">\n\t\t\t\t<p>nested tabs b-2</p>\n\t\t\t\t<p>nested tabs b-2</p>\n\t\t\t\t<p>nested tabs b-2</p>\n\t\t\t\t<p>nested tabs b-2</p>\n\t\t\t\t<p>nested tabs b-2</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/compound/tabs_tooltips.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Compound Visual Test : Tabs in Tabs</title>\n\t<link rel=\"stylesheet\" href=\"../visual.css\">\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tooltip.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tabs.js\"></script>\n\t<script>\n\t$(function() {\n\t\t$( \"#tabs\" ).tabs();\n\t\t$( \"a\" ).tooltip();\n\t});\n\t</script>\n</head>\n<body>\n\n<div id=\"tabs\">\n\t<ul>\n\t\t<li><a href=\"#tabs-1\" title=\"first tab tooltip\">First</a></li>\n\t\t<li><a href=\"#tabs-2\" title=\"second tab tooltip\">Second</a></li>\n\t</ul>\n\t<div id=\"tabs-1\">\n\t\t<a href=\"#\" title=\"title content\">label</a>\n\t</div>\n\t<div id=\"tabs-2\">\n\t\t<a href=\"#\" title=\"other title content\">other label</a>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/dialog/performance.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Dialog Visual Test - Modal Dialog in Large DOM</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../external/jquery.bgiframe-2.1.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.resizable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.dialog.js\"></script>\n\t<script>\n\t$(function() {\n\t\tvar start,\n\t\t\thtml = new Array( 500 ).join( $( \"#template\" ).html() );\n\t\t$( html ).appendTo( \"body\" );\n\n\t\tstart = $.now();\n\t\t$( \"#dialog\" ).dialog({\n\t\t\tmodal: true,\n\t\t\tautoOpen: false\n\t\t});\n\t\t$( \"<li>Create: \" + ($.now() - start) + \"ms</li>\" ).appendTo( \"#log\" );\n\n\t\t$( \"#opener\" ).click(function() {\n\t\t\tstart = $.now();\n\t\t\t$( \"#dialog\" ).dialog( \"open\" );\n\t\t\t$( \"<li>Open: \" + ($.now() - start) + \"ms</li>\" ).appendTo( \"#log\" );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<p>WHAT: A single dialog is created on a page with a large DOM.</p>\n<p>EXPECTED: Creating and opening the dialog should be fast, regardless of page size.</p>\n\n<button id=\"opener\">open dialog</button>\n<div id=\"dialog\" title=\"Dialog Title\">\n\t<p> Dialog Content </p>\n\t<input type=\"text\">\n</div>\n\n<ul id=\"log\"></ul>\n\n<script type=\"text/html\" id=\"template\">\n<div><div><div><div><div><div><div><div><div><div>\n<div><div><div><div><div><div><div><div><div><div>\n<div><div><div><div><div><div><div><div><div><div>\n<div><div><div><div><div><div><div><div><div><div>\n<div><div><div><div><div><div><div><div><div><div>\n<div><p>This <span>is</span> <span>a</span> <strong>large</strong> <abbr>DOM</abbr>.</p></div>\n<input>\n<select>\n\t<option>option 1</option>\n\t<option>option 2</option>\n\t<option>option 3</option>\n\t<option>option 4</option>\n\t<option>option 5</option>\n</select>\n</div></div></div></div></div></div></div></div></div></div>\n</div></div></div></div></div></div></div></div></div></div>\n</div></div></div></div></div></div></div></div></div></div>\n</div></div></div></div></div></div></div></div></div></div>\n</div></div></div></div></div></div></div></div></div></div>\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/effects/all.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Test Suite</title>\n\t<link rel=\"stylesheet\" href=\"effects.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.clip.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.explode.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.fade.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.fold.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.highlight.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.pulsate.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.scale.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.shake.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.slide.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.transfer.js\"></script>\n\t<script src=\"effects.js\"></script>\n</head>\n<body>\n\n<ul class=\"effects\">\n\n\t<li>\n\t\t<div class=\"effect\" id=\"blindUp\">\n\t\t\t<p>Blind up</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"blindDown\">\n\t\t\t<p>Blind down</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"blindLeft\">\n\t\t\t<p>Blind left</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"blindRight\">\n\t\t\t<p>Blind right</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"bounce3times\">\n\t\t<p>Bounce 3 times</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"clipHorizontally\">\n\t\t<p>Clip horizontally</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"clipVertically\">\n\t\t<p>Clip vertically</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"dropDown\">\n\t\t<p>Drop down</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"dropUp\">\n\t\t<p>Drop up</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"dropLeft\">\n\t\t<p>Drop left</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"dropRight\">\n\t\t<p>Drop right</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"explode9\">\n\t\t<p>Explode in 9 pieces</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"explode36\">\n\t\t<p>Explode in 36 pieces</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"fade\">\n\t\t<p>Fade</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"fold\">\n\t\t<p>Fold</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"highlight\">\n\t\t<p>Highlight</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"pulsate\">\n\t\t<p>Pulsate 2 times</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"puff\">\n\t\t<p>Puff</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"scale\">\n\t\t<p>Scale</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"shake\">\n\t\t<p>Shake</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"size\">\n\t\t<p>Size Default Show/Hide</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"sizeToggle\">\n\t\t<p>Size Toggle</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"slideDown\">\n\t\t<p>Slide down</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"slideUp\">\n\t\t<p>Slide up</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"slideLeft\">\n\t\t<p>Slide left</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"slideRight\">\n\t\t<p>Slide right</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"transfer\">\n\t\t<p>Transfer to first element</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"addClass\">\n\t\t<p>addClass</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"removeClass\">\n\t\t<p>removeClass</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"toggleClass\">\n\t\t<p>toggleClass</p>\n\t\t</div>\n\t</li>\n\n\t<li>\n\t\t<div class=\"effect\" id=\"hide\">\n\t\t<p>hide/show (jQuery)</p>\n\t\t</div>\n\t</li>\n\n</ul>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/effects/effects.css",
    "content": "body {\n\tmargin: 1em;\n\tpadding: 0;\n\tbackground: #191919;\n\tcolor: #fff;\n}\n\nul.effects {\n\tlist-style-type: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\nul.effects li {\n\tpadding: 0;\n\twidth: 120px;\n\theight: 100px;\n\tfloat: left;\n\tmargin-top: 20px;\n\tmargin-left: 20px;\n}\n\ndiv.effect {\n\twidth: 120px;\n\theight: 100px;\n\tbackground: #ccc;\n\tborder: 5px outset #aaa;\n\tfloat: left;\n\tcursor: pointer;\n\tcursor: hand;\n}\n\ndiv.current {\n\tborder: 5px outset #FF9C08;\n\tbackground: #FF9C08;\n}\n\ndiv.effect p {\n\tcolor: #191919;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 10px;\n}\n\n.ui-effects-transfer {\n\tborder: 1px dotted #fff;\n\tbackground: #666;\n\topacity: 0.5;\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/effects/effects.js",
    "content": "$(function() {\n\nvar duration = 1000,\n\twait = 500;\n\nfunction effect( elem, name, options ) {\n\t$.extend( options, {\n\t\teasing: \"easeOutQuint\"\n\t});\n\n\t$( elem ).click(function() {\n\t\t$( this )\n\t\t\t.addClass( \"current\" )\n\t\t\t// delaying the initial animation makes sure that the queue stays in tact\n\t\t\t.delay( 10 )\n\t\t\t.hide( name, options, duration )\n\t\t\t.delay( wait )\n\t\t\t.show( name, options, duration, function() {\n\t\t\t\t$( this ).removeClass( \"current\" );\n\t\t\t});\n\t});\n}\n\n$( \"#hide\" ).click(function() {\n\t$( this )\n\t\t.addClass( \"current\" )\n\t\t.hide( duration )\n\t\t.delay( wait )\n\t\t.show( duration, function() {\n\t\t\t$( this ).removeClass( \"current\" );\n\t\t});\n});\n\neffect( \"#blindLeft\", \"blind\", { direction: \"left\" } );\neffect( \"#blindUp\", \"blind\", { direction: \"up\" } );\neffect( \"#blindRight\", \"blind\", { direction: \"right\" } );\neffect( \"#blindDown\", \"blind\", { direction: \"down\" } );\n\neffect( \"#bounce3times\", \"bounce\", { times: 3 } );\n\neffect( \"#clipHorizontally\", \"clip\", { direction: \"horizontal\" } );\neffect( \"#clipVertically\", \"clip\", { direction: \"vertical\" } );\n\neffect( \"#dropDown\", \"drop\", { direction: \"down\" } );\neffect( \"#dropUp\", \"drop\", { direction: \"up\" } );\neffect( \"#dropLeft\", \"drop\", { direction: \"left\" } );\neffect( \"#dropRight\", \"drop\", { direction: \"right\" } );\n\neffect( \"#explode9\", \"explode\", {} );\neffect( \"#explode36\", \"explode\", { pieces: 36 } );\n\neffect( \"#fade\", \"fade\", {} );\n\neffect( \"#fold\", \"fold\", { size: 50 } );\n\neffect( \"#highlight\", \"highlight\", {} );\n\neffect( \"#pulsate\", \"pulsate\", { times: 2 } );\n\neffect( \"#puff\", \"puff\", { times: 2 } );\neffect( \"#scale\", \"scale\", {} );\neffect( \"#size\", \"size\", {} );\n$( \"#sizeToggle\" ).click(function() {\n\tvar options = { to: { width: 300, height: 300 } };\n\t$( this )\n\t\t.addClass( \"current\" )\n\t\t.toggle( \"size\", options, duration )\n\t\t.delay( wait )\n\t\t.toggle( \"size\", options, duration, function() {\n\t\t\t$( this ).removeClass( \"current\" );\n\t\t});\n});\n\n$( \"#shake\" ).click(function() {\n\t$( this )\n\t\t.addClass( \"current\" )\n\t\t.effect( \"shake\", {}, 100, function() {\n\t\t\t$( this ).removeClass( \"current\" );\n\t\t});\n});\n\neffect( \"#slideDown\", \"slide\", { direction: \"down\" } );\neffect( \"#slideUp\", \"slide\", { direction: \"up\" } );\neffect( \"#slideLeft\", \"slide\", { direction: \"left\" } );\neffect( \"#slideRight\", \"slide\", { direction: \"right\" } );\n\n$( \"#transfer\" ).click(function() {\n\t$( this )\n\t\t.addClass( \"current\" )\n\t\t.effect( \"transfer\", { to: \"div:eq(0)\" }, 1000, function() {\n\t\t\t$( this ).removeClass( \"current\" );\n\t\t});\n});\n\n$( \"#addClass\" ).click(function() {\n\t$( this ).addClass( \"current\", duration, function() {\n\t\t$( this ).removeClass( \"current\" );\n\t});\n});\n$( \"#removeClass\" ).click(function() {\n\t$( this ).addClass( \"current\" ).removeClass( \"current\", duration );\n});\n$( \"#toggleClass\" ).click(function() {\n\t$( this ).toggleClass( \"current\", duration );\n});\n\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/effects/scale.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Effects Test Suite</title>\n\t<link rel=\"stylesheet\" href=\"effects.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.scale.js\"></script>\n\t<script>\n\t$(function() {\n\t\tvar test = $( \"#testBox\" ),\n\t\t\topts = $( \".arg\" ),\n\t\t\toptsRev = $( opts.get().reverse() ),\n\t\t\tdoer = $( \"#doAnim\" ),\n\t\t\tcurrent = $( \"#current\" ),\n\t\t\tcleanStyle = test[0].style,\n\t\t\ttotal = 1;\n\n\t\topts.each(function() {\n\t\t\ttotal *= this.options.length;\n\t\t});\n\n\t\topts.change( doAnim );\n\t\tdoer.click( doAnim );\n\t\t$( \"#cyclePrev\" ).click(function() {\n\t\t\tcycle( -1 );\n\t\t});\n\t\t$( \"#cycleNext\" ).click(function() {\n\t\t\tcycle( 1 );\n\t\t});\n\n\t\tfunction cycle( direction ) {\n\t\t\toptsRev.each(function() {\n\t\t\t\tvar cur = this.selectedIndex,\n\t\t\t\t\tnext = cur + direction,\n\t\t\t\t\tlen = this.options.length;\n\n\t\t\t\tthis.selectedIndex = ( next + len ) % len;\n\n\t\t\t\tif ( ( next+len ) % len === next ) return false;\n\t\t\t});\n\t\t\tdoAnim();\n\t\t}\n\n\n\t\tfunction doAnim() {\n\t\t\tvar cur = 0;\n\t\t\topts.each(function() {\n\t\t\t\tcur *= this.options.length\n\t\t\t\tcur += this.selectedIndex;\n\t\t\t});\n\t\t\tcur++;\n\t\t\tcurrent.text( \"Configuration: \" + cur + \" of \" + total );\n\t\t\trun.apply(test, opts.map(function() {\n\t\t\t\treturn $(this).val();\n\t\t\t}).get());\n\t\t}\n\n\t\tfunction run( position, v, h, vo, ho ) {\n\t\t\tvar el = this,\n\t\t\t\tstyle = el[0].style,\n\t\t\t\teffect = {\n\t\t\t\t\teffect: \"scale\",\n\t\t\t\t\tmode: \"effect\",\n\t\t\t\t\tpercent: 200,\n\t\t\t\t\torigin: [ vo, ho ],\n\t\t\t\t\tduration: 500\n\t\t\t\t};\n\t\t\tel.stop(true, true);\n\t\t\tif ( typeof style === \"object\" ) {\n\t\t\t\tstyle.cssText = \"\";\n\t\t\t} else {\n\t\t\t\tel[0].style = \"\";\n\t\t\t}\n\t\t\tel.css( \"position\", position )\n\t\t\t\t.css( h, 5 )\n\t\t\t\t.css( v, 5 )\n\t\t\t\t.delay( 100 )\n\t\t\t\t.effect( effect );\n\t\t}\n\t});\n\t</script>\n\t<style>\n\t#testArea {\n\t\twidth: 200px;\n\t\theight: 200px;\n\t\tposition: relative;\n\t}\n\t#testBox {\n\t\twidth: 50px;\n\t\theight: 50px;\n\t\tbackground-color: #bada55;\n\t\tcolor: black;\n\t\tborder: 10px solid #fff;\n\t\tmargin: 10px;\n\t\tpadding: 10px;\n\t}\n\tlabel {\n\t\tdisplay: block;\n\t}\n\t#controls {\n\t\tposition: absolute;\n\t\tz-index: 300;\n\t\tleft: 50%;\n\t\ttop: 50%;\n\t\tmargin-left: -200px;\n\t\twidth: 400px;\n\t\topacity: 0.8;\n\t}\n\t</style>\n</head>\n<body>\n\t<div id=\"testArea\">\n\t\t<div id=\"testBox\">\n\t\t</div>\n\t</div>\n\t<div id=\"controls\">\n\t\t<label for=\"pos\">Positioning\n\t\t\t<select id=\"pos\" class=\"arg\">\n\t\t\t\t<option value=\"absolute\">absolute</option>\n\t\t\t\t<option value=\"relative\">relative</option>\n\t\t\t\t<option value=\"fixed\">fixed</option>\n\t\t\t</select>\n\t\t</label>\n\t\t<label for=\"vertPos\">Vertical Positioning\n\t\t\t<select id=\"vertPos\" class=\"arg\">\n\t\t\t\t<option value=\"top\">top</option>\n\t\t\t\t<option value=\"bottom\">bottom</option>\n\t\t\t</select>\n\t\t</label>\n\t\t<label for=\"horizPos\">Horizontal Positioning\n\t\t\t<select id=\"horizPos\" class=\"arg\">\n\t\t\t\t<option value=\"left\">left</option>\n\t\t\t\t<option value=\"right\">right</option>\n\t\t\t</select>\n\t\t</label>\n\t\t<label for=\"vertOrigin\">Vertical Origin\n\t\t\t<select id=\"vertOrigin\" class=\"arg\">\n\t\t\t\t<option value=\"top\">top</option>\n\t\t\t\t<option value=\"middle\">middle</option>\n\t\t\t\t<option value=\"bottom\">bottom</option>\n\t\t\t</select>\n\t\t</label>\n\t\t<label for=\"horizOrigin\">Horizontal Origin\n\t\t\t<select id=\"horizOrigin\" class=\"arg\">\n\t\t\t\t<option value=\"left\">left</option>\n\t\t\t\t<option value=\"center\">center</option>\n\t\t\t\t<option value=\"right\">right</option>\n\t\t\t</select>\n\t\t</label><br />\n\t\t<label id=\"current\">jQuery UI Scale Animation Test</label>\n\t\t<button id=\"cyclePrev\">Back</button>\n\t\t<button id=\"doAnim\">Run Animation</button>\n\t\t<button id=\"cycleNext\">Forward</button>\n\t</div>\n</body>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>jQuery UI Visual Tests</title>\n\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.core.css\">\n\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.theme.css\">\n\t<link rel=\"stylesheet\" href=\"../index.css\">\n\t<script src=\"../jquery-1.7.2.js\"></script>\n\t<script src=\"../index.js\"></script>\n</head>\n<body>\n\n<div id=\"main\">\n\t<h1>jQuery UI Visual Tests</h1>\n\t<div>\n\t\t<h2>Accordion</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"accordion/icons.html\">Icons</a></li>\n\t\t</ul>\n\n\t\t<h2>addClass</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"addClass/queue.html\">Queue</a></li>\n\t\t</ul>\n\n\t\t<h2>Button</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"button/button.html\">General</a></li>\n\t\t\t<li><a href=\"button/performance.html\">Performance</a></li>\n\t\t</ul>\n\n\t\t<h2>Dialog</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"dialog/performance.html\">Performance</a></li>\n\t\t</ul>\n\n\t\t<h2>Effects</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"effects/all.html\">All</a></li>\n\t\t\t<li><a href=\"effects/scale.html\">Scale</a></li>\n\t\t</ul>\n\n\t\t<h2>Menu</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"menu/menu.html\">General</a></li>\n\t\t</ul>\n\n\t\t<h2>Position</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"position/position.html\">General</a></li>\n\t\t\t<li><a href=\"position/position_feedback.html\">Feedback</a></li>\n\t\t</ul>\n\n\t\t<h2>Tooltip</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"tooltip/tooltip.html\">General</a></li>\n\t\t\t<li><a href=\"tooltip/animations.html\">Animations</a></li>\n\t\t</ul>\n\n\t\t<h2>Compound</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"compound/accordion_tabs.html\">Accordion in Tabs</a></li>\n\t\t\t<li><a href=\"compound/datepicker_dialog.html\">Datepicker in Dialog</a></li>\n\t\t\t<li><a href=\"compound/dialog_widgets.html\">Various Widgets in Dialog</a></li>\n\t\t\t<li><a href=\"compound/draggable_accordion.html\">Draggable Accordion</a></li>\n\t\t\t<li><a href=\"compound/draggable_accordion_accordion_tabs_draggable.html\">Nested Widgets</a></li>\n\t\t\t<li><a href=\"compound/sortable_accordion_sortable_tabs.html\">Sortable Tabs in Sortable Accordion</a></li>\n\t\t\t<li><a href=\"compound/tabs_tabs.html\">Nested Tabs</a></li>\n\t\t\t<li><a href=\"compound/tabs_tooltips.html\">Tabs with Tooltips</a></li>\n\t\t</ul>\n\n\t\t<h2>General</h2>\n\t\t<ul>\n\t\t\t<li><a href=\"theme.html\">Theme</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/menu/menu.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Menu Visual Test: Default</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.menu.js\"></script>\n\t<script>\n\t$(function() {\n\t\tfunction logger( event, ui ) {\n\t\t\t$( \"<p>\" ).text( \"Selected: \" + ui.item.text() ).appendTo( \"#log\" );\n\t\t}\n\n\t\t$( \"#menu1, #menu2, #menu3, .menu4, #menu7\" ).menu({\n\t\t\tselect: logger\n\t\t});\n\n\t\t$( \"#menu5\" ).menu({\n\t\t\tmenus: \"div\",\n\t\t\tselect: logger\n\t\t});\n\n\t\t$( \"#menu6\" ).menu({\n\t\t\tmenus: \".menuElement\",\n\t\t\tselect: logger\n\t\t});\n\t});\n\t</script>\n\t<style>\n\t\tbody { font-size:62.5%; }\n\t\t.ui-menu { width: 200px; margin-bottom: 2em; }\n\t\t.menu4 { height: 200px; overflow-y: auto; overflow-x: hidden; }\n\t\t.address-item { border-bottom: 1px solid #999; }\n\t\t.address-header { display: block; margin-bottom: .2em; font-weight: bold; }\n\t\t.address-content { display: block; margin-bottom: .2em; padding-left: 10px; }\n\t</style>\n</head>\n<body>\n\n<h2>Default inline menu</h2>\n<ul id=\"menu1\">\n\t<li><a href=\"#\">Aberdeen</a></li>\n\t<li><a href=\"#\">Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\">Addyston</a></li>\n\t<li><a href=\"#\">Delphi</a></li>\n\t<li><a href=\"#\">Saarland</a></li>\n\t<li><a href=\"#\">Salzburg</a></li>\n</ul>\n\n<h2>Inline with disabled items and submenus</h2>\n<ul id=\"menu2\">\n\t<li class=\"ui-state-disabled\"><a href=\"#\">Aberdeen</a></li>\n\t<li><a href=\"#\">Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\">Addyston</a></li>\n\t<li>\n\t\t<a href=\"#\">Delphi</a>\n\t\t<ul>\n\t\t\t<li class=\"ui-state-disabled\"><a href=\"#\">Ada</a></li>\n\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t</ul>\n\t</li>\n\t<li><a href=\"#\">Saarland</a></li>\n\t<li>\n\t\t<a href=\"#\">Salzburg</a>\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li><a href=\"#\">Perch</a></li>\n\t\t</ul>\n\t</li>\n\t<li class=\"ui-state-disabled\"><a href=\"#\">Amesville</a></li>\n</ul>\n\n<h2>Menu with icons</h2>\n<ul id=\"menu3\">\n\t<li><a href=\"#\"><span class=\"ui-icon ui-icon-print\"></span>Aberdeen</a></li>\n\t<li class=\"ui-state-disabled\"><a href=\"#\"><span class=\"ui-icon ui-icon-scissors\"></span>Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\"><span class=\"ui-icon ui-icon-wrench\"></span>Addyston</a></li>\n\t<li class=\"ui-state-disabled\">\n\t\t<a href=\"#\">Delphi</a>\n\t\t<ul>\n\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t<li><a href=\"#\"><span class=\"ui-icon ui-icon-wrench\"></span>Saarland</a></li>\n\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t</ul>\n\t</li>\n\t<li><a href=\"#\">Saarland</a></li>\n\t<li>\n\t\t<a href=\"#\"><span class=\"ui-icon ui-icon-print\"></span>Salzburg</a>\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\"><span class=\"ui-icon ui-icon-wrench\"></span>Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\"><span class=\"ui-icon ui-icon-wrench\"></span>Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\"><span class=\"ui-icon ui-icon-wrench\"></span>Saarland</a></li>\n\t\t\t\t\t<li><a href=\"#\"><span class=\"ui-icon ui-icon-wrench\"></span>Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li><a href=\"#\">Perch</a></li>\n\t\t</ul>\n\t</li>\n</ul>\n\n<h2>Long menu with scroll overflow, to test menu's scroll-on-keypress behaviour</h2>\n<ul class=\"menu4\">\n\t<li><a href=\"#\">Aberdeen</a></li>\n\t<li><a href=\"#\">Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\">Addyston</a></li>\n\t<li><a href=\"#\">Adelphi</a></li>\n\t<li><a href=\"#\">Adena</a></li>\n\t<li><a href=\"#\">Adrian</a></li>\n\t<li><a href=\"#\">Akron</a></li>\n\t<li><a href=\"#\">Albany</a></li>\n\t<li><a href=\"#\">Alexandria</a></li>\n\t<li><a href=\"#\">Alger</a></li>\n\t<li><a href=\"#\">Alledonia</a></li>\n\t<li><a href=\"#\">Alliance</a></li>\n\t<li><a href=\"#\">Alpha</a></li>\n\t<li><a href=\"#\">Alvada</a></li>\n\t<li><a href=\"#\">Alvordton</a></li>\n\t<li><a href=\"#\">Amanda</a></li>\n\t<li><a href=\"#\">Amelia</a></li>\n\t<li><a href=\"#\">Amesville</a></li>\n\t<li><a href=\"#\">Aberdeen</a></li>\n\t<li><a href=\"#\">Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\">Addyston</a></li>\n\t<li><a href=\"#\">Adelphi</a></li>\n\t<li><a href=\"#\">Adena</a></li>\n\t<li><a href=\"#\">Adrian</a></li>\n\t<li><a href=\"#\">Akron</a></li>\n\t<li><a href=\"#\">Albany</a></li>\n\t<li><a href=\"#\">Alexandria</a></li>\n\t<li><a href=\"#\">Alger</a></li>\n\t<li><a href=\"#\">Alledonia</a></li>\n\t<li><a href=\"#\">Alliance</a></li>\n\t<li><a href=\"#\">Alpha</a></li>\n\t<li><a href=\"#\">Alvada</a></li>\n\t<li><a href=\"#\">Alvordton</a></li>\n\t<li><a href=\"#\">Amanda</a></li>\n\t<li><a href=\"#\">Amelia</a></li>\n\t<li><a href=\"#\">Amesville</a></li>\n</ul>\n\n<h2>Menu with custom markup</h2>\n<div id=\"menu5\">\n\t<blockquote><a href=\"#\">Aberdeen</a></blockquote>\n\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t<blockquote class=\"ui-state-disabled\"><a href=\"#\">Adamsville</a></blockquote>\n\t<blockquote><a href=\"#\">Addyston</a></blockquote>\n\t<blockquote>\n\t\t<a href=\"#\">Delphi</a>\n\t\t<div>\n\t\t\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t\t\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t\t\t<blockquote><a href=\"#\">Salzburg</a></blockquote>\n\t\t</div>\n\t</blockquote>\n\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t<blockquote>\n\t\t<a href=\"#\">Salzburg</a>\n\t\t<div>\n\t\t\t<blockquote>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<div>\n\t\t\t\t\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Salzburg</a></blockquote>\n\t\t\t\t</div>\n\t\t\t</blockquote>\n\t\t\t<blockquote>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<div>\n\t\t\t\t\t<blockquote><a href=\"#\">Ada</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Saarland</a></blockquote>\n\t\t\t\t\t<blockquote><a href=\"#\">Salzburg</a></blockquote>\n\t\t\t\t</div>\n\t\t\t</blockquote>\n\t\t\t<blockquote><a href=\"#\">Perch</a></blockquote>\n\t\t</div>\n\t</blockquote>\n</div>\n\n<h2>Menu with custom markup, multi-line items</h2>\n<div class=\"menuElement\" id=\"menu6\">\n\t<div class=\"address-item\">\n\t\t<a href=\"#\">\n\t\t\t<span class=\"address-header\">John Doe</span>\n\t\t\t<span class=\"address-content\">78 West Main St Apt 3A</span>\n\t\t\t<span class=\"address-content\">Bloomsburg, PA 12345</span>\n\t\t</a>\n\t</div>\n\t<div class=\"address-item\">\n\t\t<a href=\"#\">\n\t\t\t<span class=\"address-header\">Jane Doe</span>\n\t\t\t<span class=\"address-content\">78 West Main St Apt 3A</span>\n\t\t\t<span class=\"address-content\">Bloomsburg, PA 12345</span>\n\t\t</a>\n\t</div>\n\t<div class=\"address-item ui-state-disabled\">\n\t\t<a href=\"#\">\n\t\t\t<span class=\"address-header\">James Doe</span>\n\t\t\t<span class=\"address-content\">78 West Main St Apt 3A</span>\n\t\t\t<span class=\"address-content\">Bloomsburg, PA 12345</span>\n\t\t</a>\n\t</div>\n\t<div class=\"address-item\">\n\t\t<a href=\"#\">\n\t\t\t<span class=\"address-header\">Jenny Doe</span>\n\t\t\t<span class=\"address-content\">78 West Main St Apt 3A</span>\n\t\t\t<span class=\"address-content\">Bloomsburg, PA 12345</span>\n\t\t</a>\n\t</div>\n\t<div class=\"address-item\">\n\t\t<a href=\"#\">\n\t\t\t<span class=\"address-header\">John Doe</span>\n\t\t\t<span class=\"address-content\">78 West Main St Apt 3A</span>\n\t\t\t<span class=\"address-content\">Bloomsburg, PA 12345</span>\n\t\t</a>\n\t\t<div class=\"menuElement\">\n\t\t\t<div><a href=\"#\">Ada</a></div>\n\t\t\t<div><a href=\"#\">Saarland</a></div>\n\t\t\t<div><a href=\"#\">Salzburg</a></div>\n\t\t</div>\n\t</div>\n</div>\n\n<h2>Inline with dividers and elements without anchors</h2>\n<ul id=\"menu7\">\n\t<li><strong>Group 1</strong></li>\n\t<li><a href=\"#\">Aberdeen</a></li>\n\t<li><a href=\"#\">Ada</a></li>\n\t<li><a href=\"#\">Adamsville</a></li>\n\t<li><a href=\"#\">Addyston</a></li>\n\t<li></li>\n\t<li><strong>Group 2</strong></li>\n\t<li>\n\t\t<a href=\"#\">Delphi</a>\n\t\t<ul>\n\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t</ul>\n\t</li>\n\t<li><a href=\"#\">Saarland</a></li>\n\t<li>---</li>\n\t<li><strong>Group 3</strong></li>\n\t<li>\n\t\t<a href=\"#\">Salzburg</a>\n\t\t<ul>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li> - </li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li>&mdash;</li>\n\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t\t<li>&ndash;</li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#\">Delphi</a>\n\t\t\t\t<ul>\n\t\t\t\t\t<li><a href=\"#\">Ada</a></li>\n\t\t\t\t\t<li><a href=\"#\">Saarland</a></li>\n\t\t\t\t\t<li><a href=\"#\">Salzburg</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li><a href=\"#\">Perch</a></li>\n\t\t</ul>\n\t</li>\n\t<li><a href=\"#\">Amesville</a></li>\n</ul>\n\n<div style=\"position: absolute; top: 1em; right: 1em;\">\n\tLog:\n\t<div id=\"log\" style=\"height: 400px; width: 300px; overflow: auto; border: 1px solid #000;\"></div>\n</div>\n\n</body>\n</html>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/position/position.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Position Visual Test</title>\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.mouse.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.draggable.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<style>\n\t\t.demo {\n\t\t\tposition: relative;\n\t\t\theight: 500px;\n\t\t\twidth: 80%;\n\t\t\tmargin: 20px auto;\n\t\t\tbackground: #eee;\n\t\t}\n\t\t#target {\n\t\t\twidth: 60%;\n\t\t\tmargin: 0 auto;\n\t\t\tborder: 1px solid #777;\n\t\t\tbackground-color: #fbca93;\n\t\t\ttext-align: center;\n\t\t\tcursor: move;\n\t\t}\n\t\t.positionable {\n\t\t\tposition: absolute;\n\t\t\tbackground-color: #bcd5e6;\n\t\t\ttext-align: center;\n\t\t}\n\t\t.extra-margin {\n\t\t\tmargin: 0 15px 15px 0;\n\t\t}\n\t</style>\n\t<script>\n\t\t$(function() {\n\t\t\tvar within = $( \".demo\" ),\n\t\t\t\tpositionable = $( \".positionable\" );\n\t\t\tfunction position() {\n\t\t\t\tpositionable.position({\n\t\t\t\t\tof: $( \"#target\" ),\n\t\t\t\t\tmy: $( \"#my_horizontal\" ).val() + \" \" + $( \"#my_vertical\" ).val(),\n\t\t\t\t\tat: $( \"#at_horizontal\" ).val() + \" \" + $( \"#at_vertical\" ).val(),\n\t\t\t\t\twithin: within,\n\t\t\t\t\tcollision: $( \"#collision_horizontal\" ).val() + \" \" + $( \"#collision_vertical\" ).val()\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tpositionable.css( \"opacity\", 0.5 );\n\n\t\t\t$( \"#target\" ).draggable({\n\t\t\t\tdrag: function() { position(); }\n\t\t\t});\n\n\t\t\t$( \"#within\" ).click(function() {\n\t\t\t\twithin = within.is( \".demo\" ) ? $( window ) : $( \".demo\" );\n\t\t\t\tposition();\n\t\t\t});\n\n\t\t\t$( \"#margin\" ).click(function() {\n\t\t\t\tpositionable.toggleClass( \"extra-margin\" );\n\t\t\t\tposition();\n\t\t\t});\n\n\t\t\t$( \"select, input\" ).bind( \"click keyup change\", function() { position(); } );\n\n\t\t\tposition();\n\t\t});\n\t</script>\n</head>\n<body>\n\n<div class=\"demo\">\n\t<div id=\"target\">\n\t\t<p>This is the position target element.</p>\n\t</div>\n\n\t<div class=\"positionable\" style=\"width: 75px; height: 75px;\">\n\t\t<p>to position</p>\n\t</div>\n\n\t<div class=\"positionable\" style=\"width:120px; height: 40px;\">\n\t\t<p>to position 2</p>\n\t</div>\n\n\t<form style=\"padding: 20px; margin-top: 75px;\">\n\t\t<h2>Position configuration:</h2>\n\t\t<div style=\"padding-bottom: 20px;\">\n\t\t\t<b>my:</b>\n\t\t\t<select id=\"my_horizontal\">\n\t\t\t\t<option value=\"left\">left</option>\n\t\t\t\t<option value=\"center\">center</option>\n\t\t\t\t<option value=\"right\" selected=\"selected\">right</option>\n\t\t\t</select>\n\t\t\t<select id=\"my_vertical\">\n\t\t\t\t<option value=\"top\">top</option>\n\t\t\t\t<option value=\"middle\">center</option>\n\t\t\t\t<option value=\"bottom\">bottom</option>\n\t\t\t</select>\n\t\t</div>\n\t\t<div style=\"padding-bottom: 20px;\">\n\t\t\t<b>at:</b>\n\t\t\t<select id=\"at_horizontal\">\n\t\t\t\t<option value=\"left\">left</option>\n\t\t\t\t<option value=\"center\">center</option>\n\t\t\t\t<option value=\"right\" selected=\"selected\">right</option>\n\t\t\t</select>\n\t\t\t<select id=\"at_vertical\">\n\t\t\t\t<option value=\"top\">top</option>\n\t\t\t\t<option value=\"middle\">center</option>\n\t\t\t\t<option value=\"bottom\">bottom</option>\n\t\t\t</select>\n\t\t</div>\n\t\t<div style=\"padding-bottom: 20px;\">\n\t\t\t<b>collision:</b>\n\t\t\t<select id=\"collision_horizontal\">\n\t\t\t\t<option value=\"flip\">flip</option>\n\t\t\t\t<option value=\"fit\">fit</option>\n\t\t\t\t<option value=\"flipfit\">flipfit</option>\n\t\t\t\t<option value=\"none\">none</option>\n\t\t\t</select>\n\t\t\t<select id=\"collision_vertical\">\n\t\t\t\t<option value=\"flip\">flip</option>\n\t\t\t\t<option value=\"fit\">fit</option>\n\t\t\t\t<option value=\"flipfit\">flipfit</option>\n\t\t\t\t<option value=\"none\">none</option>\n\t\t\t</select>\n\t\t</div>\n\t\t<div>\n\t\t\t<label for=\"within\">within:</label>\n\t\t\t<input id=\"within\" type=\"checkbox\" checked=\"checked\">\n\t\t</div>\n\t\t<div>\n\t\t\t<label for=\"margin\">extra margin:</label>\n\t\t\t<input id=\"margin\" type=\"checkbox\">\n\t\t</div>\n\t</form>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/position/position_feedback.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Position Visual Test: Feedback</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.menu.js\"></script>\n\t<script>\n\t$(function() {\n\t\tfunction using( position, feedback ) {\n\t\t\t$( this )\n\t\t\t\t.css( position )\n\t\t\t\t.text( feedback.horizontal + \" \" + feedback.vertical + \" \" + feedback.important )\n\t\t\t\t.removeClass( \"left right top bottom center middle vertical horizontal\" )\n\t\t\t\t.addClass( feedback.horizontal )\n\t\t\t\t.addClass( feedback.vertical )\n\t\t\t\t.addClass( feedback.important );\n\t\t}\n\n\t\tvar element = $( \".element\" ),\n\t\t\ttarget = $( \"#target\" ).position({\n\t\t\t\tmy: \"center\",\n\t\t\t\tat: \"center\",\n\t\t\t\tof: window\n\t\t\t}),\n\t\t\ttargetOffset = target.offset(),\n\t\t\toppositeElement = element.clone().width( 50 ).appendTo( \"body\" ),\n\t\t\tleftElement = element.clone().width( 50 ).height( 150 ).appendTo( \"body\" ),\n\t\t\trightElement = element.clone().height( 150 ).width( 150 ).appendTo( \"body\" );\n\n\t\t$.each([\n\t\t\t\"center top-100\",\n\t\t\t\"right+25 top-50\",\n\t\t\t\"right+75 top\",\n\t\t\t\"right+75 center\",\n\t\t\t\"right+75 bottom\",\n\t\t\t\"right+25 bottom+50\",\n\t\t\t\"center bottom+100\",\n\t\t\t\"left-25 bottom+50\",\n\t\t\t\"left-75 bottom\",\n\t\t\t\"left-75 center\",\n\t\t\t\"left-75 top\",\n\t\t\t\"left-25 top-50\"\n\t\t], function( index, direction ) {\n\t\t\telement.clone().insertAfter( target ).position({\n\t\t\t\tmy: \"center\",\n\t\t\t\tat: direction,\n\t\t\t\tof: target,\n\t\t\t\tusing: using\n\t\t\t});\n\t\t});\n\n\t\telement.width( 150 );\n\t\t$( document ).on( \"mousemove\", function( event ) {\n\t\t\tvar base = {\n\t\t\t\tmy: \"left top\",\n\t\t\t\tat: \"left top\",\n\t\t\t\tof: target,\n\t\t\t\tusing: using\n\t\t\t};\n\t\t\telement.position( $.extend({\n\t\t\t\toffset: (event.pageX - targetOffset.left) + \" \" + (event.pageY - targetOffset.top)\n\t\t\t}, base ));\n\t\t\toppositeElement.position( $.extend({\n\t\t\t\toffset: (-1 * (event.pageX - targetOffset.left)) + \" \" + (-1 * (event.pageY - targetOffset.top))\n\t\t\t}, base ));\n\t\t\tleftElement.position( $.extend({\n\t\t\t\toffset: (-0.9 * (event.pageX - targetOffset.left)) + \" \" + (0.9 * (event.pageY - targetOffset.top))\n\t\t\t}, base ));\n\t\t\trightElement.position( $.extend({\n\t\t\t\toffset: (0.9 * (event.pageX - targetOffset.left)) + \" \" + (-0.9 * (event.pageY - targetOffset.top))\n\t\t\t}, base) );\n\t\t});\n\t});\n\t</script>\n\t<style>\n\t#target, .element {\n\t\tposition: absolute;\n\t\tborder: 1px solid black;\n\t\tborder-radius: 5px;\n\t\twidth: 75px;\n\t\theight: 25px;\n\t\tpadding: 5px;\n\t\tfont-size: 62.5%;\n\t}\n\t#target {\n\t\theight: 75px;\n\t}\n\t.element:before {\n\t\tfont-size: 12pt;\n\t\tcontent: \"↑\";\n\t\tposition: absolute;\n\t\ttop: -19px;\n\t\tleft: 5px;\n\t}\n\t.right:before {\n\t\tleft: auto;\n\t\tright: 5px;\n\t}\n\t.bottom:before {\n\t\tcontent: \"↓\";\n\t\ttop: auto;\n\t\tbottom: -19px;\n\t}\n\t.center:before {\n\t\tleft: 50%;\n\t\tright: auto;\n\t}\n\t.middle:before {\n\t\ttop: 50%;\n\t\tbottom: auto;\n\t}\n\t.horizontal:before {\n\t\theight: 10px;\n\t\ttop: 50%;\n\t\tmargin-top: -8px;\n\t\tbottom: auto;\n\t\tleft: -18px;\n\t\tright: auto;\n\t\tcontent: \"←\";\n\t}\n\t.right.horizontal:before {\n\t\tleft: auto;\n\t\tright: -18px;\n\t\tcontent: \"→\";\n\t}\n\t.bottom.horizontal:before {\n\t\ttop: auto;\n\t\tbottom: 5px;\n\t}\n\t.top.horizontal:before {\n\t\ttop: 5px;\n\t}\n\t</style>\n</head>\n<body>\n\n<div id=\"target\">all around me</div>\n<div class=\"element\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/theme.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>jQuery UI Example Page</title>\n\t\t<link rel=\"stylesheet\" href=\"../../themes/base/jquery.ui.all.css\" type=\"text/css\">\n\t\t<script type=\"text/javascript\" src=\"../../jquery-1.7.2.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.core.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.widget.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.mouse.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.position.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.accordion.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.autocomplete.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.button.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.datepicker.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.dialog.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.draggable.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.droppable.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.progressbar.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.resizable.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.selectable.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.slider.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.sortable.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"../../ui/jquery.ui.tabs.js\"></script>\n\t\t<script type=\"text/javascript\">\n\t\t\t$(function(){\n\n\t\t\t\t// Accordion\n\t\t\t\t$(\".accordion\").accordion({ header: \"h3\" });\n\t\t\t\t$(\".accordion\").last().accordion(\"option\", \"icons\", false);\n\n\n\t\t\t\t// Tabs\n\t\t\t\t$('#tabs').tabs();\n\n\n\t\t\t\t// Dialog\n\t\t\t\t$('#dialog').dialog({\n\t\t\t\t\tautoOpen: false,\n\t\t\t\t\twidth: 600,\n\t\t\t\t\tbuttons: {\n\t\t\t\t\t\t\"Ok\": function() {\n\t\t\t\t\t\t\t$(this).dialog(\"close\");\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"Cancel\": function() {\n\t\t\t\t\t\t\t$(this).dialog(\"close\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Dialog Link\n\t\t\t\t$('#dialog_link').click(function(){\n\t\t\t\t\t$('#dialog').dialog('open');\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\t// Datepicker\n\t\t\t\t$('#datepicker').datepicker({\n\t\t\t\t\tinline: true,\n\t\t\t\t\tshowWeek: true\n\t\t\t\t});\n\n\t\t\t\t$('#multidatepicker').datepicker({\n\t\t\t\t\tnumberOfMonths: 3,\n\t\t\t\t\tshowButtonPanel: true,\n\t\t\t\t\tinline: true\n\t\t\t\t});\n\n\t\t\t\t// Slider\n\t\t\t\t$('.slider').slider({\n\t\t\t\t\trange: true,\n\t\t\t\t\tvalues: [17, 67]\n\t\t\t\t});\n\n\t\t\t\t$(\"#eq > span\").each(function() {\n\t\t\t\t\tvar value = parseInt($(this).text());\n\t\t\t\t\t$(this).empty().slider({\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\trange: \"min\",\n\t\t\t\t\t\tanimate: true,\n\t\t\t\t\t\torientation: \"vertical\"\n\t\t\t\t\t});\n\t\t\t\t});\n\n\n\t\t\t\t// Progressbar\n\t\t\t\t$(\"#progressbar\").progressbar({\n\t\t\t\t\tvalue: 20\n\t\t\t\t});\n\n\t\t\t\t//hover states on the static widgets\n\t\t\t\t$('#dialog_link, ul#icons li').hover(\n\t\t\t\t\tfunction() { $(this).addClass('ui-state-hover'); },\n\t\t\t\t\tfunction() { $(this).removeClass('ui-state-hover'); }\n\t\t\t\t);\n\n\t\t\t\t$(\".buttonset > button\").button()\n\t\t\t\t.next()\n\t\t\t\t.button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: \"ui-icon-triangle-1-s\"\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.parent()\n\t\t\t\t.buttonset();\n\n\n\t\t\t\t$('#beginning').button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: 'ui-icon-seek-start'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$('#rewind').button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: 'ui-icon-seek-prev'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$('#play').button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: 'ui-icon-play'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$('#stop').button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: 'ui-icon-stop'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$('#forward').button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: 'ui-icon-seek-next'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$('#end').button({\n\t\t\t\t\ttext: false,\n\t\t\t\t\ticons: {\n\t\t\t\t\t\tprimary: 'ui-icon-seek-end'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$(\"#shuffle\").button();\n\t\t\t\t$(\"#repeat\").buttonset();\n\n\t\t\t});\n\t\t</script>\n\t\t<style type=\"text/css\">\n\t\t\t/*demo page css*/\n\t\t\tbody{ font: 62.5% \"Trebuchet MS\", sans-serif; margin: 50px;}\n\t\t\t.demoHeaders { margin-top: 2em; clear:both; }\n\t\t\t#dialog_link {padding: .4em 1em .4em 20px;text-decoration: none;position: relative;}\n\t\t\t#dialog_link span.ui-icon {margin: 0 5px 0 0;position: absolute;left: .2em;top: 50%;margin-top: -8px;}\n\t\t\tul#icons {margin: 0; padding: 0;}\n\t\t\tul#icons li {margin: 2px; position: relative; padding: 4px 0; cursor: pointer; float: left;  list-style: none;}\n\t\t\tul#icons span.ui-icon {float: left; margin: 0 4px;}\n\t\t\t.columnbox { height: 150px; width: 48%; float:left; margin-right: 1%; }\n\t\t\t#eq span { \theight:120px; float:left; margin:15px \t}\n\t\t\t.buttonset {margin-bottom: 5px; }\n\t\t\t#toolbar { padding: 10px 4px;  }\n\t\t</style>\n\t</head>\n\t<body>\n\n\t<!-- <p style=\"font-size: 1.3em; line-height: 1.5; margin: 1em 0; width: 50%;\">This page demonstrates the widgets using a theme.</p> -->\n\t\t<div id=\"switcher\" style=\"position:absolute; right: 20px; top: 20px;\"></div>\n\n\t\t<!-- Accordion -->\n\t\t<h2 class=\"demoHeaders\">Accordion</h2>\n\t\t<div class=\"columnbox\">\n\t\t\t<div class=\"accordion\">\n\t\t\t\t<div>\n\t\t\t\t\t<h3><a href=\"#\">First</a></h3>\n\t\t\t\t\t<div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<h3><a href=\"#\">Second</a></h3>\n\t\t\t\t\t<div>Phasellus mattis tincidunt nibh.</div>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<h3><a href=\"#\">Third</a></h3>\n\t\t\t\t\t<div>Nam dui erat, auctor a, dignissim quis.</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"columnbox\">\n\t\t\t<div class=\"accordion\">\n\t\t\t\t<div>\n\t\t\t\t\t<h3><a href=\"#\">First no icons</a></h3>\n\t\t\t\t\t<div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<h3><a href=\"#\">Second no icons</a></h3>\n\t\t\t\t\t<div>Phasellus mattis tincidunt nibh.</div>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<h3><a href=\"#\">Third no icons</a></h3>\n\t\t\t\t\t<div>Nam dui erat, auctor a, dignissim quis.</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\n\t\t<!-- Tabs -->\n\t\t<h2 class=\"demoHeaders\">Tabs</h2>\n\t\t<div id=\"tabs\">\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#tabs-1\">First</a></li>\n\t\t\t\t<li><a href=\"#tabs-2\">Second</a></li>\n\t\t\t\t<li><a href=\"#tabs-3\">Third</a></li>\n\t\t\t</ul>\n\t\t\t<div id=\"tabs-1\">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>\n\t\t\t<div id=\"tabs-2\">Phasellus mattis tincidunt nibh. Cras orci urna, blandit id, pretium vel, aliquet ornare, felis. Maecenas scelerisque sem non nisl. Fusce sed lorem in enim dictum bibendum.</div>\n\t\t\t<div id=\"tabs-3\">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>\n\t\t</div>\n\n\t\t<!-- Dialog NOTE: Dialog is not generated by UI in this demo so it can be visually styled in themeroller-->\n\t\t<h2 class=\"demoHeaders\">Dialog</h2>\n\t\t<p><a href=\"#\" id=\"dialog_link\" class=\"ui-state-default ui-corner-all\"><span class=\"ui-icon ui-icon-newwin\"></span>Open Dialog</a></p>\n\n\t\t<div class=\"ui-dialog ui-widget ui-widget-content ui-corner-all  ui-draggable ui-resizable\" ><div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix\"><span class=\"ui-dialog-title\">Inline Dialog</span><a href=\"#\" class=\"ui-dialog-titlebar-close ui-corner-all\" ><span class=\"ui-icon ui-icon-closethick\" >close</span></a></div><div class=\"ui-dialog-content ui-widget-content\" >\n\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n\t\t</div><div class=\"ui-resizable-handle ui-resizable-n\" ></div><div class=\"ui-resizable-handle ui-resizable-e\" ></div><div class=\"ui-resizable-handle ui-resizable-s\" ></div><div class=\"ui-resizable-handle ui-resizable-w\" ></div><div class=\"ui-resizable-handle ui-resizable-se ui-icon ui-icon-gripsmall-diagonal-se ui-icon-grip-diagonal-se\" ></div><div class=\"ui-resizable-handle ui-resizable-sw\" ></div><div class=\"ui-resizable-handle ui-resizable-ne\" ></div><div class=\"ui-resizable-handle ui-resizable-nw\" ></div><div class=\"ui-dialog-buttonpane ui-widget-content ui-helper-clearfix\"><button type=\"button\" class=\"ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only\" role=\"button\" aria-disabled=\"false\"><span class=\"ui-button-text\">Ok</span></button><button type=\"button\" class=\"ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only\" role=\"button\" aria-disabled=\"false\"><span class=\"ui-button-text\">Cancel</span></button></div></div>\n\n\n\t\t<h2 class=\"demoHeaders\">Overlay and Shadow Classes <em>(not currently used in UI widgets)</em></h2>\n\t\t<div style=\"position: relative; width: 96%; height: 200px; padding:1% 4%; overflow:hidden;\" class=\"fakewindowcontain\">\n\t\t\t<p>Lorem ipsum dolor sit amet,  Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. </p><p>Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. </p><p>Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. </p><p>Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. </p>\n\n\t\t\t<!-- ui-dialog -->\n\t\t\t<div class=\"ui-overlay\"><div class=\"ui-widget-overlay\"></div><div class=\"ui-widget-shadow ui-corner-all\" style=\"width: 302px; height: 152px; position: absolute; left: 50px; top: 30px;\"></div></div>\n\t\t\t<div style=\"position: absolute; width: 280px; height: 130px;left: 50px; top: 30px; padding: 10px;\" class=\"ui-widget ui-widget-content ui-corner-all\">\n\t\t\t\t<div class=\"ui-dialog-content ui-widget-content\" style=\"background: none; border: 0;\">\n\t\t\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</div>\n\n\n\t\t<!-- ui-dialog -->\n\t\t<div id=\"dialog\" title=\"Dialog Title\">\n\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n\t\t</div>\n\n\n\n\t\t<h2 class=\"demoHeaders\">Framework Icons (content color preview)</h2>\n\t\t<ul id=\"icons\" class=\"ui-widget ui-helper-clearfix\">\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-n\"><span class=\"ui-icon ui-icon-carat-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-ne\"><span class=\"ui-icon ui-icon-carat-1-ne\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-e\"><span class=\"ui-icon ui-icon-carat-1-e\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-se\"><span class=\"ui-icon ui-icon-carat-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-s\"><span class=\"ui-icon ui-icon-carat-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-sw\"><span class=\"ui-icon ui-icon-carat-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-w\"><span class=\"ui-icon ui-icon-carat-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-nw\"><span class=\"ui-icon ui-icon-carat-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-2-n-s\"><span class=\"ui-icon ui-icon-carat-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-2-e-w\"><span class=\"ui-icon ui-icon-carat-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-n\"><span class=\"ui-icon ui-icon-triangle-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-ne\"><span class=\"ui-icon ui-icon-triangle-1-ne\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-e\"><span class=\"ui-icon ui-icon-triangle-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-se\"><span class=\"ui-icon ui-icon-triangle-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-s\"><span class=\"ui-icon ui-icon-triangle-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-sw\"><span class=\"ui-icon ui-icon-triangle-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-w\"><span class=\"ui-icon ui-icon-triangle-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-nw\"><span class=\"ui-icon ui-icon-triangle-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-2-n-s\"><span class=\"ui-icon ui-icon-triangle-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-2-e-w\"><span class=\"ui-icon ui-icon-triangle-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-n\"><span class=\"ui-icon ui-icon-arrow-1-n\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-ne\"><span class=\"ui-icon ui-icon-arrow-1-ne\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-e\"><span class=\"ui-icon ui-icon-arrow-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-se\"><span class=\"ui-icon ui-icon-arrow-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-s\"><span class=\"ui-icon ui-icon-arrow-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-sw\"><span class=\"ui-icon ui-icon-arrow-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-w\"><span class=\"ui-icon ui-icon-arrow-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-nw\"><span class=\"ui-icon ui-icon-arrow-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-n-s\"><span class=\"ui-icon ui-icon-arrow-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-ne-sw\"><span class=\"ui-icon ui-icon-arrow-2-ne-sw\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-e-w\"><span class=\"ui-icon ui-icon-arrow-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-se-nw\"><span class=\"ui-icon ui-icon-arrow-2-se-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-n\"><span class=\"ui-icon ui-icon-arrowstop-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-e\"><span class=\"ui-icon ui-icon-arrowstop-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-s\"><span class=\"ui-icon ui-icon-arrowstop-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-w\"><span class=\"ui-icon ui-icon-arrowstop-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-n\"><span class=\"ui-icon ui-icon-arrowthick-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-ne\"><span class=\"ui-icon ui-icon-arrowthick-1-ne\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-e\"><span class=\"ui-icon ui-icon-arrowthick-1-e\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-se\"><span class=\"ui-icon ui-icon-arrowthick-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-s\"><span class=\"ui-icon ui-icon-arrowthick-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-sw\"><span class=\"ui-icon ui-icon-arrowthick-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-w\"><span class=\"ui-icon ui-icon-arrowthick-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-nw\"><span class=\"ui-icon ui-icon-arrowthick-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-n-s\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-ne-sw\"><span class=\"ui-icon ui-icon-arrowthick-2-ne-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-e-w\"><span class=\"ui-icon ui-icon-arrowthick-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-se-nw\"><span class=\"ui-icon ui-icon-arrowthick-2-se-nw\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-n\"><span class=\"ui-icon ui-icon-arrowthickstop-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-e\"><span class=\"ui-icon ui-icon-arrowthickstop-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-s\"><span class=\"ui-icon ui-icon-arrowthickstop-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-w\"><span class=\"ui-icon ui-icon-arrowthickstop-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-w\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-n\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-e\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-s\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-w\"><span class=\"ui-icon ui-icon-arrowreturn-1-w\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-n\"><span class=\"ui-icon ui-icon-arrowreturn-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-e\"><span class=\"ui-icon ui-icon-arrowreturn-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-s\"><span class=\"ui-icon ui-icon-arrowreturn-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-w\"><span class=\"ui-icon ui-icon-arrowrefresh-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-n\"><span class=\"ui-icon ui-icon-arrowrefresh-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-e\"><span class=\"ui-icon ui-icon-arrowrefresh-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-s\"><span class=\"ui-icon ui-icon-arrowrefresh-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-4\"><span class=\"ui-icon ui-icon-arrow-4\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-4-diag\"><span class=\"ui-icon ui-icon-arrow-4-diag\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-extlink\"><span class=\"ui-icon ui-icon-extlink\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-newwin\"><span class=\"ui-icon ui-icon-newwin\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-refresh\"><span class=\"ui-icon ui-icon-refresh\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-shuffle\"><span class=\"ui-icon ui-icon-shuffle\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-transfer-e-w\"><span class=\"ui-icon ui-icon-transfer-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-transferthick-e-w\"><span class=\"ui-icon ui-icon-transferthick-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-folder-collapsed\"><span class=\"ui-icon ui-icon-folder-collapsed\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-folder-open\"><span class=\"ui-icon ui-icon-folder-open\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-document\"><span class=\"ui-icon ui-icon-document\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-document-b\"><span class=\"ui-icon ui-icon-document-b\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-note\"><span class=\"ui-icon ui-icon-note\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-mail-closed\"><span class=\"ui-icon ui-icon-mail-closed\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-mail-open\"><span class=\"ui-icon ui-icon-mail-open\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-suitcase\"><span class=\"ui-icon ui-icon-suitcase\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-comment\"><span class=\"ui-icon ui-icon-comment\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-person\"><span class=\"ui-icon ui-icon-person\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-print\"><span class=\"ui-icon ui-icon-print\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-trash\"><span class=\"ui-icon ui-icon-trash\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-locked\"><span class=\"ui-icon ui-icon-locked\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-unlocked\"><span class=\"ui-icon ui-icon-unlocked\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-bookmark\"><span class=\"ui-icon ui-icon-bookmark\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-tag\"><span class=\"ui-icon ui-icon-tag\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-home\"><span class=\"ui-icon ui-icon-home\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-flag\"><span class=\"ui-icon ui-icon-flag\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-calculator\"><span class=\"ui-icon ui-icon-calculator\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-cart\"><span class=\"ui-icon ui-icon-cart\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pencil\"><span class=\"ui-icon ui-icon-pencil\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-clock\"><span class=\"ui-icon ui-icon-clock\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-disk\"><span class=\"ui-icon ui-icon-disk\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-calendar\"><span class=\"ui-icon ui-icon-calendar\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-zoomin\"><span class=\"ui-icon ui-icon-zoomin\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-zoomout\"><span class=\"ui-icon ui-icon-zoomout\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-search\"><span class=\"ui-icon ui-icon-search\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-wrench\"><span class=\"ui-icon ui-icon-wrench\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-gear\"><span class=\"ui-icon ui-icon-gear\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-heart\"><span class=\"ui-icon ui-icon-heart\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-star\"><span class=\"ui-icon ui-icon-star\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-link\"><span class=\"ui-icon ui-icon-link\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-cancel\"><span class=\"ui-icon ui-icon-cancel\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-plus\"><span class=\"ui-icon ui-icon-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-plusthick\"><span class=\"ui-icon ui-icon-plusthick\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-minus\"><span class=\"ui-icon ui-icon-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-minusthick\"><span class=\"ui-icon ui-icon-minusthick\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-close\"><span class=\"ui-icon ui-icon-close\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-closethick\"><span class=\"ui-icon ui-icon-closethick\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-key\"><span class=\"ui-icon ui-icon-key\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-lightbulb\"><span class=\"ui-icon ui-icon-lightbulb\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-scissors\"><span class=\"ui-icon ui-icon-scissors\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-clipboard\"><span class=\"ui-icon ui-icon-clipboard\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-copy\"><span class=\"ui-icon ui-icon-copy\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-contact\"><span class=\"ui-icon ui-icon-contact\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-image\"><span class=\"ui-icon ui-icon-image\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-video\"><span class=\"ui-icon ui-icon-video\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-script\"><span class=\"ui-icon ui-icon-script\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-alert\"><span class=\"ui-icon ui-icon-alert\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-info\"><span class=\"ui-icon ui-icon-info\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-notice\"><span class=\"ui-icon ui-icon-notice\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-help\"><span class=\"ui-icon ui-icon-help\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-check\"><span class=\"ui-icon ui-icon-check\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-bullet\"><span class=\"ui-icon ui-icon-bullet\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-radio-off\"><span class=\"ui-icon ui-icon-radio-off\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-radio-on\"><span class=\"ui-icon ui-icon-radio-on\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pin-w\"><span class=\"ui-icon ui-icon-pin-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pin-s\"><span class=\"ui-icon ui-icon-pin-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-play\"><span class=\"ui-icon ui-icon-play\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pause\"><span class=\"ui-icon ui-icon-pause\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-next\"><span class=\"ui-icon ui-icon-seek-next\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-prev\"><span class=\"ui-icon ui-icon-seek-prev\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-end\"><span class=\"ui-icon ui-icon-seek-end\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-first\"><span class=\"ui-icon ui-icon-seek-first\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-stop\"><span class=\"ui-icon ui-icon-stop\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-eject\"><span class=\"ui-icon ui-icon-eject\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-volume-off\"><span class=\"ui-icon ui-icon-volume-off\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-volume-on\"><span class=\"ui-icon ui-icon-volume-on\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-power\"><span class=\"ui-icon ui-icon-power\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-signal-diag\"><span class=\"ui-icon ui-icon-signal-diag\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-signal\"><span class=\"ui-icon ui-icon-signal\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-0\"><span class=\"ui-icon ui-icon-battery-0\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-1\"><span class=\"ui-icon ui-icon-battery-1\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-2\"><span class=\"ui-icon ui-icon-battery-2\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-3\"><span class=\"ui-icon ui-icon-battery-3\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-plus\"><span class=\"ui-icon ui-icon-circle-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-minus\"><span class=\"ui-icon ui-icon-circle-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-close\"><span class=\"ui-icon ui-icon-circle-close\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-e\"><span class=\"ui-icon ui-icon-circle-triangle-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-s\"><span class=\"ui-icon ui-icon-circle-triangle-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-w\"><span class=\"ui-icon ui-icon-circle-triangle-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-n\"><span class=\"ui-icon ui-icon-circle-triangle-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-e\"><span class=\"ui-icon ui-icon-circle-arrow-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-s\"><span class=\"ui-icon ui-icon-circle-arrow-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-w\"><span class=\"ui-icon ui-icon-circle-arrow-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-n\"><span class=\"ui-icon ui-icon-circle-arrow-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-zoomin\"><span class=\"ui-icon ui-icon-circle-zoomin\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-zoomout\"><span class=\"ui-icon ui-icon-circle-zoomout\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-check\"><span class=\"ui-icon ui-icon-circle-check\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circlesmall-plus\"><span class=\"ui-icon ui-icon-circlesmall-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circlesmall-minus\"><span class=\"ui-icon ui-icon-circlesmall-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circlesmall-close\"><span class=\"ui-icon ui-icon-circlesmall-close\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-squaresmall-plus\"><span class=\"ui-icon ui-icon-squaresmall-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-squaresmall-minus\"><span class=\"ui-icon ui-icon-squaresmall-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-squaresmall-close\"><span class=\"ui-icon ui-icon-squaresmall-close\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-dotted-vertical\"><span class=\"ui-icon ui-icon-grip-dotted-vertical\"></span></li>\n\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-dotted-horizontal\"><span class=\"ui-icon ui-icon-grip-dotted-horizontal\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-solid-vertical\"><span class=\"ui-icon ui-icon-grip-solid-vertical\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-solid-horizontal\"><span class=\"ui-icon ui-icon-grip-solid-horizontal\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-gripsmall-diagonal-se\"><span class=\"ui-icon ui-icon-gripsmall-diagonal-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-diagonal-se\"><span class=\"ui-icon ui-icon-grip-diagonal-se\"></span></li>\n\t\t</ul>\n\n\n\t\t<!-- Slider -->\n\t\t<h2 class=\"demoHeaders\">Slider</h2>\n\t\t<div class=\"columnbox\">\n\t\t\t<div class=\"slider\"></div>\n\t\t</div>\n\t\t<div class=\"columnbox\">\n\t\t\t<div id=\"eq\">\n\t\t\t\t<span>88</span>\n\t\t\t\t<span>77</span>\n\t\t\t\t<span>55</span>\n\t\t\t\t<span>33</span>\n\t\t\t\t<span>40</span>\n\t\t\t\t<span>45</span>\n\t\t\t\t<span>70</span>\n\t\t\t</div>\n\t\t</div>\n\n\n\t\t<!-- Datepicker -->\n\t\t<h2 class=\"demoHeaders\">Datepicker</h2>\n\t\t<div class=\"columnbox\" style=\"width: 32%\">\n\t\t\t<div id=\"datepicker\"></div>\n\t\t</div>\n\t\t<div class=\"columnbox\" style=\"width: 66%; height: 220px;\">\n\t\t\t<div id=\"multidatepicker\"></div>\n\t\t</div>\n\n\n\t\t<!-- Progressbar -->\n\t\t<h2 class=\"demoHeaders\">Progressbar</h2>\n\t\t<div id=\"progressbar\"></div>\n\n\t\t<!-- Highlight / Error -->\n\t\t<h2 class=\"demoHeaders\">Highlight / Error</h2>\n\t\t<div class=\"ui-widget\">\n\t\t\t<div class=\"ui-state-highlight ui-corner-all\" style=\"margin-top: 20px; padding: 0 .7em;\">\n\t\t\t\t<p><span class=\"ui-icon ui-icon-info\" style=\"float: left; margin-right: .3em;\"></span>\n\t\t\t\t<strong>Hey!</strong> Sample ui-state-highlight style.</p>\n\t\t\t</div>\n\t\t</div>\n\t\t<br/>\n\t\t<div class=\"ui-widget\">\n\t\t\t<div class=\"ui-state-error ui-corner-all\" style=\"padding: 0 .7em;\">\n\t\t\t\t<p><span class=\"ui-icon ui-icon-alert\" style=\"float: left; margin-right: .3em;\"></span>\n\t\t\t\t<strong>Alert:</strong> Sample ui-state-error style.</p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<h2 class=\"demoHeaders\">Button</h2>\n\n\t\t<div class=\"buttonset\">\n\t\t\t<button id=\"rerun\">Run last action</button>\n\t\t\t<button id=\"select\">Select an action</button>\n\t\t</div>\n\n\t\t<span id=\"toolbar\" class=\"ui-widget-header ui-corner-all\">\n\t\t\t<button id=\"beginning\">go to beginning</button>\n\t\t\t<button id=\"rewind\">rewind</button>\n\t\t\t<button id=\"play\">play</button>\n\t\t\t<button id=\"stop\">stop</button>\n\t\t\t<button id=\"forward\">fast forward</button>\n\t\t\t<button id=\"end\">go to end</button>\n\n\t\t\t<input type=\"checkbox\" id=\"shuffle\" /><label for=\"shuffle\">Shuffle</label>\n\n\t\t\t<span id=\"repeat\">\n\t\t\t\t<input type=\"radio\" id=\"repeat0\" name=\"repeat\" checked=\"checked\" /><label for=\"repeat0\">No Repeat</label>\n\t\t\t\t<input type=\"radio\" id=\"repeat1\" name=\"repeat\" /><label for=\"repeat1\">Once</label>\n\t\t\t\t<input type=\"radio\" id=\"repeatall\" name=\"repeat\" /><label for=\"repeatall\">All</label>\n\t\t\t</span>\n\t\t</span>\n\n\t\t<!-- theme switcher -->\n\n\t<script src=\"http://jqueryui.com/themeroller/themeswitchertool/\"></script>\n\t<script>\n\t\t$('#switcher').themeswitcher();\n\t</script>\n\n\n\n\t</body>\n</html>\n\n\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/tooltip/animations.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Tooltip Visual Test: Animations</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tooltip.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.core.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.blind.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.bounce.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.drop.js\"></script>\n\t<script src=\"../../../ui/jquery.effects.explode.js\"></script>\n\t<style>\n\tpre {\n\t\twidth: 250px;\n\t\tborder: 1px solid #000;\n\t\tpadding: .5em;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t$( \"pre\" ).each(function( index, elem ) {\n\t\t\t$( elem )\n\t\t\t\t.attr( \"title\", \"animated tooltips\" )\n\t\t\t\t.tooltip( $.parseJSON( $( elem ).text() ) );\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<pre>{}</pre>\n<pre>{\n  \"show\": {\n    \"effect\": \"slideDown\"\n  },\n  \"hide\": {\n    \"effect\": \"slideUp\"\n  }\n}</pre>\n<pre>{\n  \"show\": {\n    \"effect\": \"explode\"\n  },\n  \"hide\": {\n    \"effect\": \"explode\"\n  }\n}</pre>\n<pre>{\n  \"show\": {\n    \"effect\": \"bounce\"\n  },\n  \"hide\": {\n    \"effect\": \"blind\"\n  }\n}</pre>\n<pre>{\n  \"show\": {\n    \"effect\": \"drop\",\n    \"direction\": \"right\"\n  },\n  \"hide\": {\n    \"effect\": \"drop\",\n    \"direction\": \"right\"\n  }\n}</pre>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/tooltip/tooltip.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Tooltip Visual Test: Default</title>\n\t<link rel=\"stylesheet\" href=\"../../../themes/base/jquery.ui.all.css\">\n\t<script src=\"../../../jquery-1.7.2.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.core.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.widget.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.position.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.button.js\"></script>\n\t<script src=\"../../../ui/jquery.ui.tooltip.js\"></script>\n\t<style>\n\t.group {\n\t\tmargin-top: 2em;\n\t}\n\t</style>\n\t<script>\n\t$(function() {\n\t\t// default\n\t\t$( \"#context1, form, #childish, #nested-input\" ).tooltip();\n\n\t\t// custom class, replaces ui-widget-content\n\t\t$( \"#context2\" ).tooltip({\n\t\t\ttooltipClass: \"ui-widget-header\"\n\t\t});\n\t\t$( \"#right1\" ).tooltip({\n\t\t\ttooltipClass: \"ui-state-error\"\n\t\t});\n\n\t\t// synchronous content\n\t\t$( \"#footnotes\" ).tooltip({\n\t\t\titems: \"[href^='#']\",\n\t\t\tcontent: function() {\n\t\t\t\treturn $( $( this ).attr( \"href\" ) ).html();\n\t\t\t}\n\t\t});\n\n\t\t// asynchronous content\n\t\t$( \"#async\" ).tooltip({\n\t\t\tcontent: function( response ) {\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tresponse( \"I loaded <strong>asyncrhonously</strong>!\" );\n\t\t\t\t}, 1000 );\n\t\t\t\treturn \"Loading...\";\n\t\t\t}\n\t\t});\n\n\t\t// asynchronous content with caching\n\t\tvar content;\n\t\t$( \"#async2\" ).tooltip({\n\t\t\tcontent: function( response ) {\n\t\t\t\tif ( content ) {\n\t\t\t\t\treturn content;\n\t\t\t\t}\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tcontent = \"<strong>Hello</strong> world!\";\n\t\t\t\t\tresponse( content );\n\t\t\t\t}, 1000 );\n\t\t\t\treturn \"Loading...\";\n\t\t\t}\n\t\t});\n\n\t\t// custom position\n\t\t$( \"#right2\" ).tooltip({\n\t\t\ttooltipClass: \"ui-state-highlight\",\n\t\t\tposition: {\n\t\t\t\tmy: \"center top\",\n\t\t\t\tat: \"center bottom\",\n\t\t\t\toffset: \"0 10\"\n\t\t\t}\n\t\t});\n\n\t\t$( \"#button1\" ).button();\n\t\t$( \"#button2\" ).button({\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-wrench\"\n\t\t\t}\n\t\t});\n\t\t$( \"#button3, #button4\" ).button({\n\t\t\ticons: {\n\t\t\t\tprimary: \"ui-icon-wrench\"\n\t\t\t},\n\t\t\ttext: false\n\t\t});\n\t\t$( \"#buttons\" ).tooltip({\n\t\t\tposition: {\n\t\t\t\tmy: \"center bottom\",\n\t\t\t\tat: \"center top\",\n\t\t\t\toffset: \"0 -5\"\n\t\t\t}\n\t\t});\n\t});\n\t</script>\n</head>\n<body>\n\n<div>\n\t<p>Lots of tooltipped elements close together.<br>\n\t\tMouse through them quickly and slowly.</p>\n\t<ul id=\"context1\">\n\t\t<li><a href=\"#\" title=\"Tooltip text 1\">Anchor 1</a></li>\n\t\t<li><a href=\"#\" title=\"Tooltip text 2\">Anchor 2</a></li>\n\t\t<li><a href=\"#\" title=\"Tooltip text 3\">Anchor 3</a></li>\n\t\t<li><a href=\"#\" title=\"Tooltip text 4 more Tooltip text Tooltip text \">Anchor 4</a></li>\n\t\t<li><a href=\"#\" title=\"Tooltip text 5 more Tooltip text Tooltip text \">Anchor 5</a></li>\n\t\t<li><a href=\"#\" title=\"Tooltip text 6 more Tooltip text Tooltip text \">Anchor 6</a></li>\n\t</ul>\n\n\t<div class=\"group\" style=\"position: absolute; right: 1em; text-align: right;\">\n\t\t<p>These elements are right aligned.<br>\n\t\t\tOne collides and one uses custom position.</p>\n\t\t<p id=\"right1\" title=\"right aligned element\">\n\t\t\tcollision detection should kick in around here\n\t\t</p>\n\t\t<p id=\"right2\" title=\"right aligned element with custom position\">\n\t\t\tright aligned with custom position\n\t\t</p>\n\t</div>\n\n\t<div class=\"group\">\n\t\t<p>These footnotes pull content form the elements they link to.</p>\n\t\t<div id=\"footnotes\">\n\t\t\t<a href=\"#footnote1\">I'm a link to a footnote.</a>\n\t\t\t<a href=\"#footnote2\">I'm another link to a footnote.</a>\n\t\t</div>\n\t</div>\n\n\t<div class=\"group\">\n\t\t<p>These elements load their content asynchronously.<br>\n\t\t\tThere should be a loading message while the content is retrieved.</p>\n\t\t<div id=\"async\" style=\"width: 100px;\" class=\"ui-widget-content\" title=\"never be seen\">\n\t\t\tasync\n\t\t</div>\n\t\t<div id=\"async2\" style=\"width: 100px;\" class=\"ui-widget-content\" title=\"never be seen\">\n\t\t\tasync + cache\n\t\t</div>\n\t</div>\n\n\t<div class=\"group\" style=\"width: 300px;\">\n\t\t<p>Nested elements.</p>\n\t\t<div id=\"context2\">\n\t\t\t<div title=\"something else\" style=\"border:1px solid red;\">\n\t\t\t\ttooltipped\n\t\t\t\t<span title=\"something more\" style=\"border:1px solid green; padding-left: 50px;\">nested tooltipped</span>\n\t\t\t</div>\n\t\t</div>\n\t\t<div id=\"childish\" style=\"border: 1px solid black;\" title=\"element with child elements\">\n\t\t\tText in <strong>bold</strong>.\n\t\t</div>\n\t</div>\n\n\t<div class=\"group\">\n\t\t<p>Play around with focusing and hovering of form elements.</p>\n\t\t<form>\n\t\t\t<div>\n\t\t\t\t<label for=\"first\">First Name:</label>\n\t\t\t\t<input id=\"first\" title=\"Your first name is optional\">\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<label for=\"last\">Last Name:</label>\n\t\t\t\t<input id=\"last\" title=\"Your last name is optional\">\n\t\t\t</div>\n\t\t</form>\n\n\t\t<p>Some inputs nested inside labels:</p>\n\t\t<div id=\"nested-input\">\n\t\t\t<label title=\"test\"><input type=\"checkbox\">This is a test</label>\n\t\t\t<label title=\"test2\"><input type=\"checkbox\">This is a test</label>\n\t\t\t<label><input type=\"checkbox\" title=\"test3\">This is a test</label>\n\t\t\t<label><input type=\"checkbox\" title=\"test4\">This is a test</label>\n\t\t</div>\n\n\t\t<p>Some button widgets:</p>\n\t\t<div id=\"buttons\">\n\t\t\t<button id=\"button1\" title=\"Button Tooltip\">Button Label</button>\n\t\t\t<button id=\"button2\" title=\"Icon Button\">Button with Icon</button>\n\t\t\t<button id=\"button3\">Icon Only Button 1</button>\n\t\t\t<button id=\"button4\">Icon Only Button 2</button>\n\t\t</div>\n\t</div>\n\n\t<div class=\"group\">\n\t\t<div id=\"footnote1\">This is <strong>the</strong> footnote, including other elements</div>\n\t\t<div id=\"footnote2\">This is <strong>the other</strong> footnote, including other elements</div>\n\t</div>\n</div>\n\n<div style=\"height: 2000px\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/tests/visual/visual.css",
    "content": "body { font-size: 62.5%; }\n#draggable, #resizable { width: 100px; height: 100px; background: #abc; }\n#droppable { width: 100px; height: 100px; background: #cde; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.accordion.css",
    "content": "/*!\n * jQuery UI Accordion @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Accordion#theming\n */\n.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }\n.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }\n.ui-accordion .ui-accordion-noicons { padding-left: .7em; }\n.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }\n.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }\n.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.all.css",
    "content": "/*!\n * jQuery UI CSS Framework @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Theming\n */\n@import \"jquery.ui.base.css\";\n@import \"jquery.ui.theme.css\";\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.autocomplete.css",
    "content": "/*!\n * jQuery UI Autocomplete @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Autocomplete#theming\n */\n.ui-autocomplete { position: absolute; cursor: default; }\t\n\n/* workarounds */\n* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.base.css",
    "content": "/*!\n * jQuery UI CSS Framework @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Theming\n */\n@import url(\"jquery.ui.core.css\");\n\n@import url(\"jquery.ui.accordion.css\");\n@import url(\"jquery.ui.autocomplete.css\");\n@import url(\"jquery.ui.button.css\");\n@import url(\"jquery.ui.datepicker.css\");\n@import url(\"jquery.ui.dialog.css\");\n@import url(\"jquery.ui.menu.css\");\n@import url(\"jquery.ui.progressbar.css\");\n@import url(\"jquery.ui.resizable.css\");\n@import url(\"jquery.ui.selectable.css\");\n@import url(\"jquery.ui.slider.css\");\n@import url(\"jquery.ui.spinner.css\");\n@import url(\"jquery.ui.tabs.css\");\n@import url(\"jquery.ui.tooltip.css\");\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.button.css",
    "content": "/*!\n * jQuery UI Button @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Button#theming\n */\n.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */\n.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */\nbutton.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */\n.ui-button-icons-only { width: 3.4em; } \nbutton.ui-button-icons-only { width: 3.7em; } \n\n/*button text element */\n.ui-button .ui-button-text { display: block; line-height: 1.4;  }\n.ui-button-text-only .ui-button-text { padding: .4em 1em; }\n.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }\n.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }\n.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }\n.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }\n/* no icon support for input elements, provide padding by default */\ninput.ui-button { padding: .4em 1em; }\n\n/*button icon element(s) */\n.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }\n.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }\n.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }\n.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }\n.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }\n\n/*button sets*/\n.ui-buttonset { margin-right: 7px; }\n.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }\n\n/* workarounds */\nbutton.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.core.css",
    "content": "/*!\n * jQuery UI CSS Framework @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Theming/API\n */\n\n/* Layout helpers\n----------------------------------*/\n.ui-helper-hidden { display: none; }\n.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }\n.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }\n.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: \"\"; display: table; }\n.ui-helper-clearfix:after { clear: both; }\n.ui-helper-clearfix { zoom: 1; }\n.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }\n\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-disabled { cursor: default !important; }\n\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }\n\n\n/* Misc visuals\n----------------------------------*/\n\n/* Overlays */\n.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.datepicker.css",
    "content": "/*!\n * jQuery UI Datepicker @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Datepicker#theming\n */\n.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }\n.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }\n.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }\n.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }\n.ui-datepicker .ui-datepicker-prev { left:2px; }\n.ui-datepicker .ui-datepicker-next { right:2px; }\n.ui-datepicker .ui-datepicker-prev-hover { left:1px; }\n.ui-datepicker .ui-datepicker-next-hover { right:1px; }\n.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }\n.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }\n.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }\n.ui-datepicker select.ui-datepicker-month-year {width: 100%;}\n.ui-datepicker select.ui-datepicker-month, \n.ui-datepicker select.ui-datepicker-year { width: 49%;}\n.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }\n.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }\n.ui-datepicker td { border: 0; padding: 1px; }\n.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }\n.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }\n.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }\n.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }\n\n/* with multiple calendars */\n.ui-datepicker.ui-datepicker-multi { width:auto; }\n.ui-datepicker-multi .ui-datepicker-group { float:left; }\n.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }\n.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }\n.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }\n.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }\n.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }\n.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }\n.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }\n.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }\n\n/* RTL support */\n.ui-datepicker-rtl { direction: rtl; }\n.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }\n.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }\n.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }\n.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }\n.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }\n.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }\n.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }\n.ui-datepicker-rtl .ui-datepicker-group { float:right; }\n.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }\n.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }\n\n/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */\n.ui-datepicker-cover {\n    display: none; /*sorry for IE5*/\n    display/**/: block; /*sorry for IE5*/\n    position: absolute; /*must have*/\n    z-index: -1; /*must have*/\n    filter: mask(); /*must have*/\n    top: -4px; /*must have*/\n    left: -4px; /*must have*/\n    width: 200px; /*must have*/\n    height: 200px; /*must have*/\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.dialog.css",
    "content": "/*!\n * jQuery UI Dialog @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Dialog#theming\n */\n.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }\n.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }\n.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }\n.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }\n.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }\n.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }\n.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }\n.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }\n.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }\n.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }\n.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }\n.ui-draggable .ui-dialog-titlebar { cursor: move; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.menu.css",
    "content": "/*!\n * jQuery UI Menu @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Menu#theming\n */\n.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }\n.ui-menu .ui-menu { margin-top: -3px; position: absolute; }\n.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }\n.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }\n.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }\n.ui-menu .ui-menu-item a.ui-state-focus,\n.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }\n\n.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }\n.ui-menu .ui-state-disabled a { cursor: default; }\n\n/* icon support */\n.ui-menu-icons { position: relative; }\n.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }\n\n/* left-aligned */\n.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }\n\n/* right-aligned */\n.ui-menu .ui-menu-icon { position: static; float: right; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.progressbar.css",
    "content": "/*!\n * jQuery UI Progressbar @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Progressbar#theming\n */\n.ui-progressbar { height:2em; text-align: left; overflow: hidden; }\n.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.resizable.css",
    "content": "/*!\n * jQuery UI Resizable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Resizable#theming\n */\n.ui-resizable { position: relative;}\n.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }\n.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }\n.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }\n.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }\n.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }\n.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }\n.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }\n.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }\n.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }\n.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.selectable.css",
    "content": "/*!\n * jQuery UI Selectable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Selectable#theming\n */\n.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.slider.css",
    "content": "/*!\n * jQuery UI Slider @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Slider#theming\n */\n.ui-slider { position: relative; text-align: left; }\n.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }\n.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }\n\n.ui-slider-horizontal { height: .8em; }\n.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }\n.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }\n.ui-slider-horizontal .ui-slider-range-min { left: 0; }\n.ui-slider-horizontal .ui-slider-range-max { right: 0; }\n\n.ui-slider-vertical { width: .8em; height: 100px; }\n.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }\n.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }\n.ui-slider-vertical .ui-slider-range-min { bottom: 0; }\n.ui-slider-vertical .ui-slider-range-max { top: 0; }"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.spinner.css",
    "content": "/*!\n * jQuery UI Spinner @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Spinner#theming\n */\n.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }\n.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }\n.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; z-index: 100; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }\n.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */\n.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */\n.ui-spinner-up { top: 0; }\n.ui-spinner-down { bottom: 0; }\n\n/* TR overrides */\nspan.ui-spinner { background: none; }\n.ui-spinner .ui-icon-triangle-1-s {\n\t/* need to fix icons sprite */\n\tbackground-position:-65px -16px;\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.tabs.css",
    "content": "/*!\n * jQuery UI Tabs @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Tabs#theming\n */\n.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }\n.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }\n.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }\n.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }\n.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }\n.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */\n.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.theme.css",
    "content": "/*!\n * jQuery UI CSS Framework @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Theming/API\n *\n * To view and modify this theme, visit http://jqueryui.com/themeroller/\n */\n\n\n/* Component containers\n----------------------------------*/\n.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }\n.ui-widget .ui-widget { font-size: 1em; }\n.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }\n.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }\n.ui-widget-content a { color: #222222/*{fcContent}*/; }\n.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }\n.ui-widget-header a { color: #222222/*{fcHeader}*/; }\n\n/* Interaction states\n----------------------------------*/\n.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }\n.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }\n.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }\n.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }\n.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }\n.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }\n.ui-widget :active { outline: none; }\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }\n.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }\n.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }\n.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }\n.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }\n.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }\n.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }\n.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }\n.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }\n.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }\n.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }\n.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }\n.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }\n.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }\n.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }\n\n/* positioning */\n.ui-icon-carat-1-n { background-position: 0 0; }\n.ui-icon-carat-1-ne { background-position: -16px 0; }\n.ui-icon-carat-1-e { background-position: -32px 0; }\n.ui-icon-carat-1-se { background-position: -48px 0; }\n.ui-icon-carat-1-s { background-position: -64px 0; }\n.ui-icon-carat-1-sw { background-position: -80px 0; }\n.ui-icon-carat-1-w { background-position: -96px 0; }\n.ui-icon-carat-1-nw { background-position: -112px 0; }\n.ui-icon-carat-2-n-s { background-position: -128px 0; }\n.ui-icon-carat-2-e-w { background-position: -144px 0; }\n.ui-icon-triangle-1-n { background-position: 0 -16px; }\n.ui-icon-triangle-1-ne { background-position: -16px -16px; }\n.ui-icon-triangle-1-e { background-position: -32px -16px; }\n.ui-icon-triangle-1-se { background-position: -48px -16px; }\n.ui-icon-triangle-1-s { background-position: -64px -16px; }\n.ui-icon-triangle-1-sw { background-position: -80px -16px; }\n.ui-icon-triangle-1-w { background-position: -96px -16px; }\n.ui-icon-triangle-1-nw { background-position: -112px -16px; }\n.ui-icon-triangle-2-n-s { background-position: -128px -16px; }\n.ui-icon-triangle-2-e-w { background-position: -144px -16px; }\n.ui-icon-arrow-1-n { background-position: 0 -32px; }\n.ui-icon-arrow-1-ne { background-position: -16px -32px; }\n.ui-icon-arrow-1-e { background-position: -32px -32px; }\n.ui-icon-arrow-1-se { background-position: -48px -32px; }\n.ui-icon-arrow-1-s { background-position: -64px -32px; }\n.ui-icon-arrow-1-sw { background-position: -80px -32px; }\n.ui-icon-arrow-1-w { background-position: -96px -32px; }\n.ui-icon-arrow-1-nw { background-position: -112px -32px; }\n.ui-icon-arrow-2-n-s { background-position: -128px -32px; }\n.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }\n.ui-icon-arrow-2-e-w { background-position: -160px -32px; }\n.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }\n.ui-icon-arrowstop-1-n { background-position: -192px -32px; }\n.ui-icon-arrowstop-1-e { background-position: -208px -32px; }\n.ui-icon-arrowstop-1-s { background-position: -224px -32px; }\n.ui-icon-arrowstop-1-w { background-position: -240px -32px; }\n.ui-icon-arrowthick-1-n { background-position: 0 -48px; }\n.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }\n.ui-icon-arrowthick-1-e { background-position: -32px -48px; }\n.ui-icon-arrowthick-1-se { background-position: -48px -48px; }\n.ui-icon-arrowthick-1-s { background-position: -64px -48px; }\n.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }\n.ui-icon-arrowthick-1-w { background-position: -96px -48px; }\n.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }\n.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }\n.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }\n.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }\n.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }\n.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }\n.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }\n.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }\n.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }\n.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }\n.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }\n.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }\n.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }\n.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }\n.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }\n.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }\n.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }\n.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }\n.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }\n.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }\n.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }\n.ui-icon-arrow-4 { background-position: 0 -80px; }\n.ui-icon-arrow-4-diag { background-position: -16px -80px; }\n.ui-icon-extlink { background-position: -32px -80px; }\n.ui-icon-newwin { background-position: -48px -80px; }\n.ui-icon-refresh { background-position: -64px -80px; }\n.ui-icon-shuffle { background-position: -80px -80px; }\n.ui-icon-transfer-e-w { background-position: -96px -80px; }\n.ui-icon-transferthick-e-w { background-position: -112px -80px; }\n.ui-icon-folder-collapsed { background-position: 0 -96px; }\n.ui-icon-folder-open { background-position: -16px -96px; }\n.ui-icon-document { background-position: -32px -96px; }\n.ui-icon-document-b { background-position: -48px -96px; }\n.ui-icon-note { background-position: -64px -96px; }\n.ui-icon-mail-closed { background-position: -80px -96px; }\n.ui-icon-mail-open { background-position: -96px -96px; }\n.ui-icon-suitcase { background-position: -112px -96px; }\n.ui-icon-comment { background-position: -128px -96px; }\n.ui-icon-person { background-position: -144px -96px; }\n.ui-icon-print { background-position: -160px -96px; }\n.ui-icon-trash { background-position: -176px -96px; }\n.ui-icon-locked { background-position: -192px -96px; }\n.ui-icon-unlocked { background-position: -208px -96px; }\n.ui-icon-bookmark { background-position: -224px -96px; }\n.ui-icon-tag { background-position: -240px -96px; }\n.ui-icon-home { background-position: 0 -112px; }\n.ui-icon-flag { background-position: -16px -112px; }\n.ui-icon-calendar { background-position: -32px -112px; }\n.ui-icon-cart { background-position: -48px -112px; }\n.ui-icon-pencil { background-position: -64px -112px; }\n.ui-icon-clock { background-position: -80px -112px; }\n.ui-icon-disk { background-position: -96px -112px; }\n.ui-icon-calculator { background-position: -112px -112px; }\n.ui-icon-zoomin { background-position: -128px -112px; }\n.ui-icon-zoomout { background-position: -144px -112px; }\n.ui-icon-search { background-position: -160px -112px; }\n.ui-icon-wrench { background-position: -176px -112px; }\n.ui-icon-gear { background-position: -192px -112px; }\n.ui-icon-heart { background-position: -208px -112px; }\n.ui-icon-star { background-position: -224px -112px; }\n.ui-icon-link { background-position: -240px -112px; }\n.ui-icon-cancel { background-position: 0 -128px; }\n.ui-icon-plus { background-position: -16px -128px; }\n.ui-icon-plusthick { background-position: -32px -128px; }\n.ui-icon-minus { background-position: -48px -128px; }\n.ui-icon-minusthick { background-position: -64px -128px; }\n.ui-icon-close { background-position: -80px -128px; }\n.ui-icon-closethick { background-position: -96px -128px; }\n.ui-icon-key { background-position: -112px -128px; }\n.ui-icon-lightbulb { background-position: -128px -128px; }\n.ui-icon-scissors { background-position: -144px -128px; }\n.ui-icon-clipboard { background-position: -160px -128px; }\n.ui-icon-copy { background-position: -176px -128px; }\n.ui-icon-contact { background-position: -192px -128px; }\n.ui-icon-image { background-position: -208px -128px; }\n.ui-icon-video { background-position: -224px -128px; }\n.ui-icon-script { background-position: -240px -128px; }\n.ui-icon-alert { background-position: 0 -144px; }\n.ui-icon-info { background-position: -16px -144px; }\n.ui-icon-notice { background-position: -32px -144px; }\n.ui-icon-help { background-position: -48px -144px; }\n.ui-icon-check { background-position: -64px -144px; }\n.ui-icon-bullet { background-position: -80px -144px; }\n.ui-icon-radio-on { background-position: -96px -144px; }\n.ui-icon-radio-off { background-position: -112px -144px; }\n.ui-icon-pin-w { background-position: -128px -144px; }\n.ui-icon-pin-s { background-position: -144px -144px; }\n.ui-icon-play { background-position: 0 -160px; }\n.ui-icon-pause { background-position: -16px -160px; }\n.ui-icon-seek-next { background-position: -32px -160px; }\n.ui-icon-seek-prev { background-position: -48px -160px; }\n.ui-icon-seek-end { background-position: -64px -160px; }\n.ui-icon-seek-start { background-position: -80px -160px; }\n/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */\n.ui-icon-seek-first { background-position: -80px -160px; }\n.ui-icon-stop { background-position: -96px -160px; }\n.ui-icon-eject { background-position: -112px -160px; }\n.ui-icon-volume-off { background-position: -128px -160px; }\n.ui-icon-volume-on { background-position: -144px -160px; }\n.ui-icon-power { background-position: 0 -176px; }\n.ui-icon-signal-diag { background-position: -16px -176px; }\n.ui-icon-signal { background-position: -32px -176px; }\n.ui-icon-battery-0 { background-position: -48px -176px; }\n.ui-icon-battery-1 { background-position: -64px -176px; }\n.ui-icon-battery-2 { background-position: -80px -176px; }\n.ui-icon-battery-3 { background-position: -96px -176px; }\n.ui-icon-circle-plus { background-position: 0 -192px; }\n.ui-icon-circle-minus { background-position: -16px -192px; }\n.ui-icon-circle-close { background-position: -32px -192px; }\n.ui-icon-circle-triangle-e { background-position: -48px -192px; }\n.ui-icon-circle-triangle-s { background-position: -64px -192px; }\n.ui-icon-circle-triangle-w { background-position: -80px -192px; }\n.ui-icon-circle-triangle-n { background-position: -96px -192px; }\n.ui-icon-circle-arrow-e { background-position: -112px -192px; }\n.ui-icon-circle-arrow-s { background-position: -128px -192px; }\n.ui-icon-circle-arrow-w { background-position: -144px -192px; }\n.ui-icon-circle-arrow-n { background-position: -160px -192px; }\n.ui-icon-circle-zoomin { background-position: -176px -192px; }\n.ui-icon-circle-zoomout { background-position: -192px -192px; }\n.ui-icon-circle-check { background-position: -208px -192px; }\n.ui-icon-circlesmall-plus { background-position: 0 -208px; }\n.ui-icon-circlesmall-minus { background-position: -16px -208px; }\n.ui-icon-circlesmall-close { background-position: -32px -208px; }\n.ui-icon-squaresmall-plus { background-position: -48px -208px; }\n.ui-icon-squaresmall-minus { background-position: -64px -208px; }\n.ui-icon-squaresmall-close { background-position: -80px -208px; }\n.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }\n.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }\n.ui-icon-grip-solid-vertical { background-position: -32px -224px; }\n.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }\n.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }\n.ui-icon-grip-diagonal-se { background-position: -80px -224px; }\n\n\n/* Misc visuals\n----------------------------------*/\n\n/* Corner radius */\n.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }\n.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }\n.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }\n.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }\n\n/* Overlays */\n.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }\n.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/themes/base/jquery.ui.tooltip.css",
    "content": "/*!\n * jQuery UI Tooltip @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n */\n.ui-tooltip {\n\tpadding:8px;\n\tposition:absolute;\n\tz-index:9999;\n\t-o-box-shadow: 0 0 5px #aaa;\n\t-moz-box-shadow: 0 0 5px #aaa;\n\t-webkit-box-shadow: 0 0 5px #aaa;\n\tbox-shadow: 0 0 5px #aaa;\n}\n/* Fades and background-images don't work well together in IE6, drop the image */\n* html .ui-tooltip {\n\tbackground-image: none;\n}\nbody .ui-tooltip { border-width:2px; }\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/.jshintrc",
    "content": "{\n\t\"browser\": true,\n\t\"curly\": true,\n\t\"eqnull\": true,\n\t\"eqeqeq\": true,\n\t\"expr\": true,\n\t\"jquery\": true,\n\t\"latedef\": true,\n\t\"noarg\": true,\n\t\"onevar\": true,\n\t\"smarttabs\": true,\n\t\"trailing\": true,\n\t\"undef\": true,\n\t\"predef\": [\n\t\t\"Globalize\"\n\t]\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-af.js",
    "content": "/* Afrikaans initialisation for the jQuery UI date picker plugin. */\n/* Written by Renier Pretorius. */\njQuery(function($){\n\t$.datepicker.regional['af'] = {\n\t\tcloseText: 'Selekteer',\n\t\tprevText: 'Vorige',\n\t\tnextText: 'Volgende',\n\t\tcurrentText: 'Vandag',\n\t\tmonthNames: ['Januarie','Februarie','Maart','April','Mei','Junie',\n\t\t'Julie','Augustus','September','Oktober','November','Desember'],\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun',\n\t\t'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],\n\t\tdayNames: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],\n\t\tdayNamesShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],\n\t\tdayNamesMin: ['So','Ma','Di','Wo','Do','Vr','Sa'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['af']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ar-DZ.js",
    "content": "/* Algerian Arabic Translation for jQuery UI date picker plugin. (can be used for Tunisia)*/\n/* Mohamed Cherif BOUCHELAGHEM -- cherifbouchelaghem@yahoo.fr */\n\njQuery(function($){\n\t$.datepicker.regional['ar-DZ'] = {\n\t\tcloseText: 'إغلاق',\n\t\tprevText: '&#x3C;السابق',\n\t\tnextText: 'التالي&#x3E;',\n\t\tcurrentText: 'اليوم',\n\t\tmonthNames: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان',\n\t\t'جويلية', 'أوت', 'سبتمبر','أكتوبر', 'نوفمبر', 'ديسمبر'],\n\t\tmonthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],\n\t\tdayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n\t\tdayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n\t\tdayNamesMin: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n\t\tweekHeader: 'أسبوع',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 6,\n  \t\tisRTL: true,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ar-DZ']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ar.js",
    "content": "/* Arabic Translation for jQuery UI date picker plugin. */\n/* Khaled Alhourani -- me@khaledalhourani.com */\n/* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */\njQuery(function($){\n\t$.datepicker.regional['ar'] = {\n\t\tcloseText: 'إغلاق',\n\t\tprevText: '&#x3C;السابق',\n\t\tnextText: 'التالي&#x3E;',\n\t\tcurrentText: 'اليوم',\n\t\tmonthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'مايو', 'حزيران',\n\t\t'تموز', 'آب', 'أيلول',\t'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],\n\t\tmonthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],\n\t\tdayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n\t\tdayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n\t\tdayNamesMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],\n\t\tweekHeader: 'أسبوع',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 6,\n  \t\tisRTL: true,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ar']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-az.js",
    "content": "/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Jamil Najafov (necefov33@gmail.com). */\njQuery(function($) {\n\t$.datepicker.regional['az'] = {\n\t\tcloseText: 'Bağla',\n\t\tprevText: '&#x3C;Geri',\n\t\tnextText: 'İrəli&#x3E;',\n\t\tcurrentText: 'Bugün',\n\t\tmonthNames: ['Yanvar','Fevral','Mart','Aprel','May','İyun',\n\t\t'İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'],\n\t\tmonthNamesShort: ['Yan','Fev','Mar','Apr','May','İyun',\n\t\t'İyul','Avq','Sen','Okt','Noy','Dek'],\n\t\tdayNames: ['Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'],\n\t\tdayNamesShort: ['B','Be','Ça','Ç','Ca','C','Ş'],\n\t\tdayNamesMin: ['B','B','Ç','С','Ç','C','Ş'],\n\t\tweekHeader: 'Hf',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['az']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-bg.js",
    "content": "/* Bulgarian initialisation for the jQuery UI date picker plugin. */\n/* Written by Stoyan Kyosev (http://svest.org). */\njQuery(function($){\n\t$.datepicker.regional['bg'] = {\n\t\tcloseText: 'затвори',\n\t\tprevText: '&#x3C;назад',\n\t\tnextText: 'напред&#x3E;',\n\t\tnextBigText: '&#x3E;&#x3E;',\n\t\tcurrentText: 'днес',\n\t\tmonthNames: ['Януари','Февруари','Март','Април','Май','Юни',\n\t\t'Юли','Август','Септември','Октомври','Ноември','Декември'],\n\t\tmonthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',\n\t\t'Юли','Авг','Сеп','Окт','Нов','Дек'],\n\t\tdayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],\n\t\tdayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],\n\t\tdayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['bg']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-bs.js",
    "content": "/* Bosnian i18n for the jQuery UI date picker plugin. */\n/* Written by Kenan Konjo. */\njQuery(function($){\n\t$.datepicker.regional['bs'] = {\n\t\tcloseText: 'Zatvori', \n\t\tprevText: '&#x3C;', \n\t\tnextText: '&#x3E;', \n\t\tcurrentText: 'Danas', \n\t\tmonthNames: ['Januar','Februar','Mart','April','Maj','Juni',\n\t\t'Juli','August','Septembar','Oktobar','Novembar','Decembar'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\n\t\t'Jul','Aug','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],\n\t\tdayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],\n\t\tdayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['bs']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ca.js",
    "content": "/* Inicialització en català per a l'extensió 'UI date picker' per jQuery. */\n/* Writers: (joan.leon@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['ca'] = {\n\t\tcloseText: 'Tanca',\n\t\tprevText: 'Anterior',\n\t\tnextText: 'Següent',\n\t\tcurrentText: 'Avui',\n\t\tmonthNames: ['gener','febrer','març','abril','maig','juny',\n\t\t'juliol','agost','setembre','octubre','novembre','desembre'],\n\t\tmonthNamesShort: ['gen','feb','març','abr','maig','juny',\n\t\t'jul','ag','set','oct','nov','des'],\n\t\tdayNames: ['diumenge','dilluns','dimarts','dimecres','dijous','divendres','dissabte'],\n\t\tdayNamesShort: ['dg','dl','dt','dc','dj','dv','ds'],\n\t\tdayNamesMin: ['dg','dl','dt','dc','dj','dv','ds'],\n\t\tweekHeader: 'Set',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ca']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-cs.js",
    "content": "/* Czech initialisation for the jQuery UI date picker plugin. */\n/* Written by Tomas Muller (tomas@tomas-muller.net). */\njQuery(function($){\n\t$.datepicker.regional['cs'] = {\n\t\tcloseText: 'Zavřít',\n\t\tprevText: '&#x3C;Dříve',\n\t\tnextText: 'Později&#x3E;',\n\t\tcurrentText: 'Nyní',\n\t\tmonthNames: ['leden','únor','březen','duben','květen','červen',\n\t\t'červenec','srpen','září','říjen','listopad','prosinec'],\n\t\tmonthNamesShort: ['led','úno','bře','dub','kvě','čer',\n\t\t'čvc','srp','zář','říj','lis','pro'],\n\t\tdayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],\n\t\tdayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],\n\t\tdayNamesMin: ['ne','po','út','st','čt','pá','so'],\n\t\tweekHeader: 'Týd',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['cs']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-cy-GB.js",
    "content": "/* Welsh/UK initialisation for the jQuery UI date picker plugin. */\n/* Written by William Griffiths. */\njQuery(function($){\n\t$.datepicker.regional['cy-GB'] = {\n\t\tcloseText: 'Done',\n\t\tprevText: 'Prev',\n\t\tnextText: 'Next',\n\t\tcurrentText: 'Today',\n\t\tmonthNames: ['Ionawr','Chwefror','Mawrth','Ebrill','Mai','Mehefin',\n\t\t'Gorffennaf','Awst','Medi','Hydref','Tachwedd','Rhagfyr'],\n\t\tmonthNamesShort: ['Ion', 'Chw', 'Maw', 'Ebr', 'Mai', 'Meh',\n\t\t'Gor', 'Aws', 'Med', 'Hyd', 'Tac', 'Rha'],\n\t\tdayNames: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],\n\t\tdayNamesShort: ['Sul', 'Llu', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],\n\t\tdayNamesMin: ['Su','Ll','Ma','Me','Ia','Gw','Sa'],\n\t\tweekHeader: 'Wy',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['cy-GB']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-da.js",
    "content": "/* Danish initialisation for the jQuery UI date picker plugin. */\n/* Written by Jan Christensen ( deletestuff@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['da'] = {\n\t\tcloseText: 'Luk',\n\t\tprevText: '&#x3C;Forrige',\n\t\tnextText: 'Næste&#x3E;',\n\t\tcurrentText: 'Idag',\n\t\tmonthNames: ['Januar','Februar','Marts','April','Maj','Juni',\n\t\t'Juli','August','September','Oktober','November','December'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\n\t\t'Jul','Aug','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],\n\t\tdayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],\n\t\tdayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],\n\t\tweekHeader: 'Uge',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['da']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-de.js",
    "content": "/* German initialisation for the jQuery UI date picker plugin. */\n/* Written by Milian Wolff (mail@milianw.de). */\njQuery(function($){\n\t$.datepicker.regional['de'] = {\n\t\tcloseText: 'schließen',\n\t\tprevText: '&#x3C;zurück',\n\t\tnextText: 'Vor&#x3E;',\n\t\tcurrentText: 'heute',\n\t\tmonthNames: ['Januar','Februar','März','April','Mai','Juni',\n\t\t'Juli','August','September','Oktober','November','Dezember'],\n\t\tmonthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',\n\t\t'Jul','Aug','Sep','Okt','Nov','Dez'],\n\t\tdayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],\n\t\tdayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],\n\t\tdayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],\n\t\tweekHeader: 'KW',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['de']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-el.js",
    "content": "/* Greek (el) initialisation for the jQuery UI date picker plugin. */\n/* Written by Alex Cicovic (http://www.alexcicovic.com) */\njQuery(function($){\n\t$.datepicker.regional['el'] = {\n\t\tcloseText: 'Κλείσιμο',\n\t\tprevText: 'Προηγούμενος',\n\t\tnextText: 'Επόμενος',\n\t\tcurrentText: 'Τρέχων Μήνας',\n\t\tmonthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',\n\t\t'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],\n\t\tmonthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',\n\t\t'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],\n\t\tdayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],\n\t\tdayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],\n\t\tdayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],\n\t\tweekHeader: 'Εβδ',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['el']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-en-AU.js",
    "content": "/* English/Australia initialisation for the jQuery UI date picker plugin. */\n/* Based on the en-GB initialisation. */\njQuery(function($){\n\t$.datepicker.regional['en-AU'] = {\n\t\tcloseText: 'Done',\n\t\tprevText: 'Prev',\n\t\tnextText: 'Next',\n\t\tcurrentText: 'Today',\n\t\tmonthNames: ['January','February','March','April','May','June',\n\t\t'July','August','September','October','November','December'],\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n\t\t'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t\tdayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n\t\tdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n\t\tdayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['en-AU']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-en-GB.js",
    "content": "/* English/UK initialisation for the jQuery UI date picker plugin. */\n/* Written by Stuart. */\njQuery(function($){\n\t$.datepicker.regional['en-GB'] = {\n\t\tcloseText: 'Done',\n\t\tprevText: 'Prev',\n\t\tnextText: 'Next',\n\t\tcurrentText: 'Today',\n\t\tmonthNames: ['January','February','March','April','May','June',\n\t\t'July','August','September','October','November','December'],\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n\t\t'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t\tdayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n\t\tdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n\t\tdayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['en-GB']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-en-NZ.js",
    "content": "/* English/New Zealand initialisation for the jQuery UI date picker plugin. */\n/* Based on the en-GB initialisation. */\njQuery(function($){\n\t$.datepicker.regional['en-NZ'] = {\n\t\tcloseText: 'Done',\n\t\tprevText: 'Prev',\n\t\tnextText: 'Next',\n\t\tcurrentText: 'Today',\n\t\tmonthNames: ['January','February','March','April','May','June',\n\t\t'July','August','September','October','November','December'],\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n\t\t'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t\tdayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n\t\tdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n\t\tdayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['en-NZ']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-eo.js",
    "content": "/* Esperanto initialisation for the jQuery UI date picker plugin. */\n/* Written by Olivier M. (olivierweb@ifrance.com). */\njQuery(function($){\n\t$.datepicker.regional['eo'] = {\n\t\tcloseText: 'Fermi',\n\t\tprevText: '&#x3C;Anta',\n\t\tnextText: 'Sekv&#x3E;',\n\t\tcurrentText: 'Nuna',\n\t\tmonthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',\n\t\t'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\n\t\t'Jul','Aŭg','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],\n\t\tdayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],\n\t\tdayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],\n\t\tweekHeader: 'Sb',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['eo']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-es.js",
    "content": "/* Inicialización en español para la extensión 'UI date picker' para jQuery. */\n/* Traducido por Vester (xvester@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['es'] = {\n\t\tcloseText: 'Cerrar',\n\t\tprevText: '&#x3C;Ant',\n\t\tnextText: 'Sig&#x3E;',\n\t\tcurrentText: 'Hoy',\n\t\tmonthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',\n\t\t'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],\n\t\tmonthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',\n\t\t'Jul','Ago','Sep','Oct','Nov','Dic'],\n\t\tdayNames: ['Domingo','Lunes','Martes','Mi&#xE9;rcoles','Jueves','Viernes','S&#xE1;bado'],\n\t\tdayNamesShort: ['Dom','Lun','Mar','Mi&#xE9;','Juv','Vie','S&#xE1;b'],\n\t\tdayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','S&#xE1;'],\n\t\tweekHeader: 'Sm',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['es']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-et.js",
    "content": "/* Estonian initialisation for the jQuery UI date picker plugin. */\n/* Written by Mart Sõmermaa (mrts.pydev at gmail com). */\njQuery(function($){\n\t$.datepicker.regional['et'] = {\n\t\tcloseText: 'Sulge',\n\t\tprevText: 'Eelnev',\n\t\tnextText: 'Järgnev',\n\t\tcurrentText: 'Täna',\n\t\tmonthNames: ['Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni',\n\t\t'Juuli','August','September','Oktoober','November','Detsember'],\n\t\tmonthNamesShort: ['Jaan', 'Veebr', 'Märts', 'Apr', 'Mai', 'Juuni',\n\t\t'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'],\n\t\tdayNames: ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],\n\t\tdayNamesShort: ['Pühap', 'Esmasp', 'Teisip', 'Kolmap', 'Neljap', 'Reede', 'Laup'],\n\t\tdayNamesMin: ['P','E','T','K','N','R','L'],\n\t\tweekHeader: 'näd',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['et']);\n}); "
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-eu.js",
    "content": "/* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */\n/* Karrikas-ek itzulia (karrikas@karrikas.com) */\njQuery(function($){\n\t$.datepicker.regional['eu'] = {\n\t\tcloseText: 'Egina',\n\t\tprevText: '&#x3C;Aur',\n\t\tnextText: 'Hur&#x3E;',\n\t\tcurrentText: 'Gaur',\n\t\tmonthNames: ['urtarrila','otsaila','martxoa','apirila','maiatza','ekaina',\n\t\t\t'uztaila','abuztua','iraila','urria','azaroa','abendua'],\n\t\tmonthNamesShort: ['urt.','ots.','mar.','api.','mai.','eka.',\n\t\t\t'uzt.','abu.','ira.','urr.','aza.','abe.'],\n\t\tdayNames: ['igandea','astelehena','asteartea','asteazkena','osteguna','ostirala','larunbata'],\n\t\tdayNamesShort: ['ig.','al.','ar.','az.','og.','ol.','lr.'],\n\t\tdayNamesMin: ['ig','al','ar','az','og','ol','lr'],\n\t\tweekHeader: 'As',\n\t\tdateFormat: 'yy-mm-dd',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['eu']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-fa.js",
    "content": "/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */\n/* Javad Mowlanezhad -- jmowla@gmail.com */\n/* Jalali calendar should supported soon! (Its implemented but I have to test it) */\njQuery(function($) {\n\t$.datepicker.regional['fa'] = {\n\t\tcloseText: 'بستن',\n\t\tprevText: '&#x3C;قبلی',\n\t\tnextText: 'بعدی&#x3E;',\n\t\tcurrentText: 'امروز',\n\t\tmonthNames: [\n\t\t\t'فروردين',\n\t\t\t'ارديبهشت',\n\t\t\t'خرداد',\n\t\t\t'تير',\n\t\t\t'مرداد',\n\t\t\t'شهريور',\n\t\t\t'مهر',\n\t\t\t'آبان',\n\t\t\t'آذر',\n\t\t\t'دی',\n\t\t\t'بهمن',\n\t\t\t'اسفند'\n\t\t],\n\t\tmonthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],\n\t\tdayNames: [\n\t\t\t'يکشنبه',\n\t\t\t'دوشنبه',\n\t\t\t'سه‌شنبه',\n\t\t\t'چهارشنبه',\n\t\t\t'پنجشنبه',\n\t\t\t'جمعه',\n\t\t\t'شنبه'\n\t\t],\n\t\tdayNamesShort: [\n\t\t\t'ی',\n\t\t\t'د',\n\t\t\t'س',\n\t\t\t'چ',\n\t\t\t'پ',\n\t\t\t'ج', \n\t\t\t'ش'\n\t\t],\n\t\tdayNamesMin: [\n\t\t\t'ی',\n\t\t\t'د',\n\t\t\t'س',\n\t\t\t'چ',\n\t\t\t'پ',\n\t\t\t'ج', \n\t\t\t'ش'\n\t\t],\n\t\tweekHeader: 'هف',\n\t\tdateFormat: 'yy/mm/dd',\n\t\tfirstDay: 6,\n\t\tisRTL: true,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['fa']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-fi.js",
    "content": "/* Finnish initialisation for the jQuery UI date picker plugin. */\n/* Written by Harri Kilpiö (harrikilpio@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['fi'] = {\n\t\tcloseText: 'Sulje',\n\t\tprevText: '&#xAB;Edellinen',\n\t\tnextText: 'Seuraava&#xBB;',\n\t\tcurrentText: 'T&#xE4;n&#xE4;&#xE4;n',\n\t\tmonthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&#xE4;kuu',\n\t\t'Hein&#xE4;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],\n\t\tmonthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&#xE4;',\n\t\t'Hein&#xE4;','Elo','Syys','Loka','Marras','Joulu'],\n\t\tdayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','La'],\n\t\tdayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],\n\t\tdayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],\n\t\tweekHeader: 'Vk',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['fi']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-fo.js",
    "content": "/* Faroese initialisation for the jQuery UI date picker plugin */\n/* Written by Sverri Mohr Olsen, sverrimo@gmail.com */\njQuery(function($){\n\t$.datepicker.regional['fo'] = {\n\t\tcloseText: 'Lat aftur',\n\t\tprevText: '&#x3C;Fyrra',\n\t\tnextText: 'Næsta&#x3E;',\n\t\tcurrentText: 'Í dag',\n\t\tmonthNames: ['Januar','Februar','Mars','Apríl','Mei','Juni',\n\t\t'Juli','August','September','Oktober','November','Desember'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',\n\t\t'Jul','Aug','Sep','Okt','Nov','Des'],\n\t\tdayNames: ['Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'],\n\t\tdayNamesShort: ['Sun','Mán','Týs','Mik','Hós','Frí','Ley'],\n\t\tdayNamesMin: ['Su','Má','Tý','Mi','Hó','Fr','Le'],\n\t\tweekHeader: 'Vk',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['fo']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-fr-CH.js",
    "content": "/* Swiss-French initialisation for the jQuery UI date picker plugin. */\n/* Written Martin Voelkle (martin.voelkle@e-tc.ch). */\njQuery(function($){\n\t$.datepicker.regional['fr-CH'] = {\n\t\tcloseText: 'Fermer',\n\t\tprevText: '&#x3C;Préc',\n\t\tnextText: 'Suiv&#x3E;',\n\t\tcurrentText: 'Courant',\n\t\tmonthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',\n\t\t'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],\n\t\tmonthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',\n\t\t'Jul','Aoû','Sep','Oct','Nov','Déc'],\n\t\tdayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],\n\t\tdayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],\n\t\tdayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],\n\t\tweekHeader: 'Sm',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['fr-CH']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-fr.js",
    "content": "/* French initialisation for the jQuery UI date picker plugin. */\n/* Written by Keith Wood (kbwood{at}iinet.com.au),\n\t\t\t  Stéphane Nahmani (sholby@sholby.net),\n\t\t\t  Stéphane Raimbault <stephane.raimbault@gmail.com> */\njQuery(function($){\n\t$.datepicker.regional['fr'] = {\n\t\tcloseText: 'Fermer',\n\t\tprevText: 'Précédent',\n\t\tnextText: 'Suivant',\n\t\tcurrentText: 'Aujourd\\'hui',\n\t\tmonthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',\n\t\t'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],\n\t\tmonthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin',\n\t\t'Juil.','Août','Sept.','Oct.','Nov.','Déc.'],\n\t\tdayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],\n\t\tdayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'],\n\t\tdayNamesMin: ['D','L','M','M','J','V','S'],\n\t\tweekHeader: 'Sem.',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['fr']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-gl.js",
    "content": "/* Galician localization for 'UI date picker' jQuery extension. */\n/* Translated by Jorge Barreiro <yortx.barry@gmail.com>. */\njQuery(function($){\n\t$.datepicker.regional['gl'] = {\n\t\tcloseText: 'Pechar',\n\t\tprevText: '&#x3C;Ant',\n\t\tnextText: 'Seg&#x3E;',\n\t\tcurrentText: 'Hoxe',\n\t\tmonthNames: ['Xaneiro','Febreiro','Marzo','Abril','Maio','Xuño',\n\t\t'Xullo','Agosto','Setembro','Outubro','Novembro','Decembro'],\n\t\tmonthNamesShort: ['Xan','Feb','Mar','Abr','Mai','Xuñ',\n\t\t'Xul','Ago','Set','Out','Nov','Dec'],\n\t\tdayNames: ['Domingo','Luns','Martes','M&#xE9;rcores','Xoves','Venres','S&#xE1;bado'],\n\t\tdayNamesShort: ['Dom','Lun','Mar','M&#xE9;r','Xov','Ven','S&#xE1;b'],\n\t\tdayNamesMin: ['Do','Lu','Ma','M&#xE9;','Xo','Ve','S&#xE1;'],\n\t\tweekHeader: 'Sm',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['gl']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-he.js",
    "content": "/* Hebrew initialisation for the UI Datepicker extension. */\n/* Written by Amir Hardon (ahardon at gmail dot com). */\njQuery(function($){\n\t$.datepicker.regional['he'] = {\n\t\tcloseText: 'סגור',\n\t\tprevText: '&#x3C;הקודם',\n\t\tnextText: 'הבא&#x3E;',\n\t\tcurrentText: 'היום',\n\t\tmonthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',\n\t\t'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],\n\t\tmonthNamesShort: ['ינו','פבר','מרץ','אפר','מאי','יוני',\n\t\t'יולי','אוג','ספט','אוק','נוב','דצמ'],\n\t\tdayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],\n\t\tdayNamesShort: ['א\\'','ב\\'','ג\\'','ד\\'','ה\\'','ו\\'','שבת'],\n\t\tdayNamesMin: ['א\\'','ב\\'','ג\\'','ד\\'','ה\\'','ו\\'','שבת'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: true,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['he']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-hi.js",
    "content": "/* Hindi initialisation for the jQuery UI date picker plugin. */\n/* Written by Michael Dawart. */\njQuery(function($){\n\t$.datepicker.regional['hi'] = {\n\t\tcloseText: 'बंद',\n\t\tprevText: 'पिछला',\n\t\tnextText: 'अगला',\n\t\tcurrentText: 'आज',\n\t\tmonthNames: ['जनवरी ','फरवरी','मार्च','अप्रेल','मई','जून',\n\t\t'जूलाई','अगस्त ','सितम्बर','अक्टूबर','नवम्बर','दिसम्बर'],\n\t\tmonthNamesShort: ['जन', 'फर', 'मार्च', 'अप्रेल', 'मई', 'जून',\n\t\t'जूलाई', 'अग', 'सित', 'अक्ट', 'नव', 'दि'],\n\t\tdayNames: ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],\n\t\tdayNamesShort: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],\n\t\tdayNamesMin: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],\n\t\tweekHeader: 'हफ्ता',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['hi']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-hr.js",
    "content": "/* Croatian i18n for the jQuery UI date picker plugin. */\n/* Written by Vjekoslav Nesek. */\njQuery(function($){\n\t$.datepicker.regional['hr'] = {\n\t\tcloseText: 'Zatvori',\n\t\tprevText: '&#x3C;',\n\t\tnextText: '&#x3E;',\n\t\tcurrentText: 'Danas',\n\t\tmonthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj',\n\t\t'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],\n\t\tmonthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',\n\t\t'Srp','Kol','Ruj','Lis','Stu','Pro'],\n\t\tdayNames: ['Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],\n\t\tdayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],\n\t\tdayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],\n\t\tweekHeader: 'Tje',\n\t\tdateFormat: 'dd.mm.yy.',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['hr']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-hu.js",
    "content": "/* Hungarian initialisation for the jQuery UI date picker plugin. */\n/* Written by Istvan Karaszi (jquery@spam.raszi.hu). */\njQuery(function($){\n\t$.datepicker.regional['hu'] = {\n\t\tcloseText: 'bezár',\n\t\tprevText: 'vissza',\n\t\tnextText: 'előre',\n\t\tcurrentText: 'ma',\n\t\tmonthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',\n\t\t'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',\n\t\t'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],\n\t\tdayNames: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],\n\t\tdayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],\n\t\tdayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],\n\t\tweekHeader: 'Hét',\n\t\tdateFormat: 'yy.mm.dd.',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: true,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['hu']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-hy.js",
    "content": "/* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/\njQuery(function($){\n\t$.datepicker.regional['hy'] = {\n\t\tcloseText: 'Փակել',\n\t\tprevText: '&#x3C;Նախ.',\n\t\tnextText: 'Հաջ.&#x3E;',\n\t\tcurrentText: 'Այսօր',\n\t\tmonthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',\n\t\t'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],\n\t\tmonthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',\n\t\t'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],\n\t\tdayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],\n\t\tdayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],\n\t\tdayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],\n\t\tweekHeader: 'ՇԲՏ',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['hy']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-id.js",
    "content": "/* Indonesian initialisation for the jQuery UI date picker plugin. */\n/* Written by Deden Fathurahman (dedenf@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['id'] = {\n\t\tcloseText: 'Tutup',\n\t\tprevText: '&#x3C;mundur',\n\t\tnextText: 'maju&#x3E;',\n\t\tcurrentText: 'hari ini',\n\t\tmonthNames: ['Januari','Februari','Maret','April','Mei','Juni',\n\t\t'Juli','Agustus','September','Oktober','Nopember','Desember'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',\n\t\t'Jul','Agus','Sep','Okt','Nop','Des'],\n\t\tdayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],\n\t\tdayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],\n\t\tdayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],\n\t\tweekHeader: 'Mg',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['id']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-is.js",
    "content": "/* Icelandic initialisation for the jQuery UI date picker plugin. */\n/* Written by Haukur H. Thorsson (haukur@eskill.is). */\njQuery(function($){\n\t$.datepicker.regional['is'] = {\n\t\tcloseText: 'Loka',\n\t\tprevText: '&#x3C; Fyrri',\n\t\tnextText: 'N&#xE6;sti &#x3E;',\n\t\tcurrentText: '&#xCD; dag',\n\t\tmonthNames: ['Jan&#xFA;ar','Febr&#xFA;ar','Mars','Apr&#xED;l','Ma&iacute','J&#xFA;n&#xED;',\n\t\t'J&#xFA;l&#xED;','&#xC1;g&#xFA;st','September','Okt&#xF3;ber','N&#xF3;vember','Desember'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Ma&#xED;','J&#xFA;n',\n\t\t'J&#xFA;l','&#xC1;g&#xFA;','Sep','Okt','N&#xF3;v','Des'],\n\t\tdayNames: ['Sunnudagur','M&#xE1;nudagur','&#xDE;ri&#xF0;judagur','Mi&#xF0;vikudagur','Fimmtudagur','F&#xF6;studagur','Laugardagur'],\n\t\tdayNamesShort: ['Sun','M&#xE1;n','&#xDE;ri','Mi&#xF0;','Fim','F&#xF6;s','Lau'],\n\t\tdayNamesMin: ['Su','M&#xE1;','&#xDE;r','Mi','Fi','F&#xF6;','La'],\n\t\tweekHeader: 'Vika',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['is']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-it.js",
    "content": "/* Italian initialisation for the jQuery UI date picker plugin. */\n/* Written by Antonello Pasella (antonello.pasella@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['it'] = {\n\t\tcloseText: 'Chiudi',\n\t\tprevText: '&#x3C;Prec',\n\t\tnextText: 'Succ&#x3E;',\n\t\tcurrentText: 'Oggi',\n\t\tmonthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',\n\t\t\t'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],\n\t\tmonthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',\n\t\t\t'Lug','Ago','Set','Ott','Nov','Dic'],\n\t\tdayNames: ['Domenica','Luned&#xEC;','Marted&#xEC;','Mercoled&#xEC;','Gioved&#xEC;','Venerd&#xEC;','Sabato'],\n\t\tdayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],\n\t\tdayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],\n\t\tweekHeader: 'Sm',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['it']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ja.js",
    "content": "/* Japanese initialisation for the jQuery UI date picker plugin. */\n/* Written by Kentaro SATO (kentaro@ranvis.com). */\njQuery(function($){\n\t$.datepicker.regional['ja'] = {\n\t\tcloseText: '閉じる',\n\t\tprevText: '&#x3C;前',\n\t\tnextText: '次&#x3E;',\n\t\tcurrentText: '今日',\n\t\tmonthNames: ['1月','2月','3月','4月','5月','6月',\n\t\t'7月','8月','9月','10月','11月','12月'],\n\t\tmonthNamesShort: ['1月','2月','3月','4月','5月','6月',\n\t\t'7月','8月','9月','10月','11月','12月'],\n\t\tdayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],\n\t\tdayNamesShort: ['日','月','火','水','木','金','土'],\n\t\tdayNamesMin: ['日','月','火','水','木','金','土'],\n\t\tweekHeader: '週',\n\t\tdateFormat: 'yy/mm/dd',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: true,\n\t\tyearSuffix: '年'};\n\t$.datepicker.setDefaults($.datepicker.regional['ja']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ka.js",
    "content": "/* Georgian (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Lado Lomidze (lado.lomidze@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['ka'] = {\n\t\tcloseText: 'დახურვა',\n\t\tprevText: '&#x3c; წინა',\n\t\tnextText: 'შემდეგი &#x3e;',\n\t\tcurrentText: 'დღეს',\n\t\tmonthNames: ['იანვარი','თებერვალი','მარტი','აპრილი','მაისი','ივნისი', 'ივლისი','აგვისტო','სექტემბერი','ოქტომბერი','ნოემბერი','დეკემბერი'],\n\t\tmonthNamesShort: ['იან','თებ','მარ','აპრ','მაი','ივნ', 'ივლ','აგვ','სექ','ოქტ','ნოე','დეკ'],\n\t\tdayNames: ['კვირა','ორშაბათი','სამშაბათი','ოთხშაბათი','ხუთშაბათი','პარასკევი','შაბათი'],\n\t\tdayNamesShort: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],\n\t\tdayNamesMin: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],\n\t\tweekHeader: 'კვირა',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ka']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-kk.js",
    "content": "/* Kazakh (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Dmitriy Karasyov (dmitriy.karasyov@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['kk'] = {\n\t\tcloseText: 'Жабу',\n\t\tprevText: '&#x3C;Алдыңғы',\n\t\tnextText: 'Келесі&#x3E;',\n\t\tcurrentText: 'Бүгін',\n\t\tmonthNames: ['Қаңтар','Ақпан','Наурыз','Сәуір','Мамыр','Маусым',\n\t\t'Шілде','Тамыз','Қыркүйек','Қазан','Қараша','Желтоқсан'],\n\t\tmonthNamesShort: ['Қаң','Ақп','Нау','Сәу','Мам','Мау',\n\t\t'Шіл','Там','Қыр','Қаз','Қар','Жел'],\n\t\tdayNames: ['Жексенбі','Дүйсенбі','Сейсенбі','Сәрсенбі','Бейсенбі','Жұма','Сенбі'],\n\t\tdayNamesShort: ['жкс','дсн','ссн','срс','бсн','жма','снб'],\n\t\tdayNamesMin: ['Жк','Дс','Сс','Ср','Бс','Жм','Сн'],\n\t\tweekHeader: 'Не',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['kk']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-km.js",
    "content": "/* Khmer initialisation for the jQuery calendar extension. */\n/* Written by Chandara Om (chandara.teacher@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['km'] = {\n\t\tcloseText: 'ធ្វើ​រួច',\n\t\tprevText: 'មុន',\n\t\tnextText: 'បន្ទាប់',\n\t\tcurrentText: 'ថ្ងៃ​នេះ',\n\t\tmonthNames: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',\n\t\t'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],\n\t\tmonthNamesShort: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',\n\t\t'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],\n\t\tdayNames: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],\n\t\tdayNamesShort: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],\n\t\tdayNamesMin: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],\n\t\tweekHeader: 'សប្ដាហ៍',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['km']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ko.js",
    "content": "/* Korean initialisation for the jQuery calendar extension. */\n/* Written by DaeKwon Kang (ncrash.dk@gmail.com), Edited by Genie. */\njQuery(function($){\n\t$.datepicker.regional['ko'] = {\n\t\tcloseText: '닫기',\n\t\tprevText: '이전달',\n\t\tnextText: '다음달',\n\t\tcurrentText: '오늘',\n\t\tmonthNames: ['1월','2월','3월','4월','5월','6월',\n\t\t'7월','8월','9월','10월','11월','12월'],\n\t\tmonthNamesShort: ['1월','2월','3월','4월','5월','6월',\n\t\t'7월','8월','9월','10월','11월','12월'],\n\t\tdayNames: ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'],\n\t\tdayNamesShort: ['일','월','화','수','목','금','토'],\n\t\tdayNamesMin: ['일','월','화','수','목','금','토'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'yy-mm-dd',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: true,\n\t\tyearSuffix: '년'};\n\t$.datepicker.setDefaults($.datepicker.regional['ko']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-lb.js",
    "content": "/* Luxembourgish initialisation for the jQuery UI date picker plugin. */\n/* Written by Michel Weimerskirch <michel@weimerskirch.net> */\njQuery(function($){\n\t$.datepicker.regional['lb'] = {\n\t\tcloseText: 'Fäerdeg',\n\t\tprevText: 'Zréck',\n\t\tnextText: 'Weider',\n\t\tcurrentText: 'Haut',\n\t\tmonthNames: ['Januar','Februar','Mäerz','Abrëll','Mee','Juni',\n\t\t'Juli','August','September','Oktober','November','Dezember'],\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun',\n\t\t'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],\n\t\tdayNames: ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],\n\t\tdayNamesShort: ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],\n\t\tdayNamesMin: ['So','Mé','Dë','Më','Do','Fr','Sa'],\n\t\tweekHeader: 'W',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['lb']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-lt.js",
    "content": "/* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* @author Arturas Paleicikas <arturas@avalon.lt> */\njQuery(function($){\n\t$.datepicker.regional['lt'] = {\n\t\tcloseText: 'Uždaryti',\n\t\tprevText: '&#x3C;Atgal',\n\t\tnextText: 'Pirmyn&#x3E;',\n\t\tcurrentText: 'Šiandien',\n\t\tmonthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',\n\t\t'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],\n\t\tmonthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',\n\t\t'Lie','Rugp','Rugs','Spa','Lap','Gru'],\n\t\tdayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],\n\t\tdayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],\n\t\tdayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'yy-mm-dd',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['lt']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-lv.js",
    "content": "/* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */\njQuery(function($){\n\t$.datepicker.regional['lv'] = {\n\t\tcloseText: 'Aizvērt',\n\t\tprevText: 'Iepr',\n\t\tnextText: 'Nāka',\n\t\tcurrentText: 'Šodien',\n\t\tmonthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',\n\t\t'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',\n\t\t'Jūl','Aug','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],\n\t\tdayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],\n\t\tdayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],\n\t\tweekHeader: 'Nav',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['lv']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-mk.js",
    "content": "/* Macedonian i18n for the jQuery UI date picker plugin. */\n/* Written by Stojce Slavkovski. */\njQuery(function($){\n\t$.datepicker.regional['mk'] = {\n\t\tcloseText: 'Затвори',\n\t\tprevText: '&#x3C;',\n\t\tnextText: '&#x3E;',\n\t\tcurrentText: 'Денес',\n\t\tmonthNames: ['Јануари','Февруари','Март','Април','Мај','Јуни',\n\t\t'Јули','Август','Септември','Октомври','Ноември','Декември'],\n\t\tmonthNamesShort: ['Јан','Фев','Мар','Апр','Мај','Јун',\n\t\t'Јул','Авг','Сеп','Окт','Ное','Дек'],\n\t\tdayNames: ['Недела','Понеделник','Вторник','Среда','Четврток','Петок','Сабота'],\n\t\tdayNamesShort: ['Нед','Пон','Вто','Сре','Чет','Пет','Саб'],\n\t\tdayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Са'],\n\t\tweekHeader: 'Сед',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['mk']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ml.js",
    "content": "/* Malayalam (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Saji Nediyanchath (saji89@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['ml'] = {\n\t\tcloseText: 'ശരി',\n\t\tprevText: 'മുന്നത്തെ',  \n\t\tnextText: 'അടുത്തത് ',\n\t\tcurrentText: 'ഇന്ന്',\n\t\tmonthNames: ['ജനുവരി','ഫെബ്രുവരി','മാര്‍ച്ച്','ഏപ്രില്‍','മേയ്','ജൂണ്‍',\n\t\t'ജൂലൈ','ആഗസ്റ്റ്','സെപ്റ്റംബര്‍','ഒക്ടോബര്‍','നവംബര്‍','ഡിസംബര്‍'],\n\t\tmonthNamesShort: ['ജനു', 'ഫെബ്', 'മാര്‍', 'ഏപ്രി', 'മേയ്', 'ജൂണ്‍',\n\t\t'ജൂലാ', 'ആഗ', 'സെപ്', 'ഒക്ടോ', 'നവം', 'ഡിസ'],\n\t\tdayNames: ['ഞായര്‍', 'തിങ്കള്‍', 'ചൊവ്വ', 'ബുധന്‍', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],\n\t\tdayNamesShort: ['ഞായ', 'തിങ്ക', 'ചൊവ്വ', 'ബുധ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],\n\t\tdayNamesMin: ['ഞാ','തി','ചൊ','ബു','വ്യാ','വെ','ശ'],\n\t\tweekHeader: 'ആ',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ml']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ms.js",
    "content": "/* Malaysian initialisation for the jQuery UI date picker plugin. */\n/* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */\njQuery(function($){\n\t$.datepicker.regional['ms'] = {\n\t\tcloseText: 'Tutup',\n\t\tprevText: '&#x3C;Sebelum',\n\t\tnextText: 'Selepas&#x3E;',\n\t\tcurrentText: 'hari ini',\n\t\tmonthNames: ['Januari','Februari','Mac','April','Mei','Jun',\n\t\t'Julai','Ogos','September','Oktober','November','Disember'],\n\t\tmonthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',\n\t\t'Jul','Ogo','Sep','Okt','Nov','Dis'],\n\t\tdayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],\n\t\tdayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],\n\t\tdayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],\n\t\tweekHeader: 'Mg',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ms']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-nl-BE.js",
    "content": "/* Dutch (Belgium) initialisation for the jQuery UI date picker plugin. */\n/* David De Sloovere @DavidDeSloovere */\njQuery(function($){\n\t$.datepicker.regional['nl-BE'] = {\n\t\tcloseText: 'Sluiten',\n\t\tprevText: '←',\n\t\tnextText: '→',\n\t\tcurrentText: 'Vandaag',\n\t\tmonthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',\n\t\t'juli', 'augustus', 'september', 'oktober', 'november', 'december'],\n\t\tmonthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',\n\t\t'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],\n\t\tdayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],\n\t\tdayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],\n\t\tdayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['nl-BE']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-nl.js",
    "content": "/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Mathias Bynens <http://mathiasbynens.be/> */\njQuery(function($){\n\t$.datepicker.regional.nl = {\n\t\tcloseText: 'Sluiten',\n\t\tprevText: '←',\n\t\tnextText: '→',\n\t\tcurrentText: 'Vandaag',\n\t\tmonthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',\n\t\t'juli', 'augustus', 'september', 'oktober', 'november', 'december'],\n\t\tmonthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',\n\t\t'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],\n\t\tdayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],\n\t\tdayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],\n\t\tdayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional.nl);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-no.js",
    "content": "/* Norwegian initialisation for the jQuery UI date picker plugin. */\n/* Written by Naimdjon Takhirov (naimdjon@gmail.com). */\n\njQuery(function($){\n\t$.datepicker.regional['no'] = {\n\t\tcloseText: 'Lukk',\n\t\tprevText: '&#xAB;Forrige',\n\t\tnextText: 'Neste&#xBB;',\n\t\tcurrentText: 'I dag',\n\t\tmonthNames: ['januar','februar','mars','april','mai','juni','juli','august','september','oktober','november','desember'],\n\t\tmonthNamesShort: ['jan','feb','mar','apr','mai','jun','jul','aug','sep','okt','nov','des'],\n\t\tdayNamesShort: ['søn','man','tir','ons','tor','fre','lør'],\n\t\tdayNames: ['søndag','mandag','tirsdag','onsdag','torsdag','fredag','lørdag'],\n\t\tdayNamesMin: ['sø','ma','ti','on','to','fr','lø'],\n\t\tweekHeader: 'Uke',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''\n\t};\n\t$.datepicker.setDefaults($.datepicker.regional['no']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-pl.js",
    "content": "/* Polish initialisation for the jQuery UI date picker plugin. */\n/* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['pl'] = {\n\t\tcloseText: 'Zamknij',\n\t\tprevText: '&#x3C;Poprzedni',\n\t\tnextText: 'Następny&#x3E;',\n\t\tcurrentText: 'Dziś',\n\t\tmonthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',\n\t\t'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],\n\t\tmonthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',\n\t\t'Lip','Sie','Wrz','Pa','Lis','Gru'],\n\t\tdayNames: ['Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'],\n\t\tdayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],\n\t\tdayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],\n\t\tweekHeader: 'Tydz',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['pl']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-pt-BR.js",
    "content": "/* Brazilian initialisation for the jQuery UI date picker plugin. */\n/* Written by Leonildo Costa Silva (leocsilva@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['pt-BR'] = {\n\t\tcloseText: 'Fechar',\n\t\tprevText: '&#x3C;Anterior',\n\t\tnextText: 'Pr&#xF3;ximo&#x3E;',\n\t\tcurrentText: 'Hoje',\n\t\tmonthNames: ['Janeiro','Fevereiro','Mar&#xE7;o','Abril','Maio','Junho',\n\t\t'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],\n\t\tmonthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',\n\t\t'Jul','Ago','Set','Out','Nov','Dez'],\n\t\tdayNames: ['Domingo','Segunda-feira','Ter&#xE7;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&#xE1;bado'],\n\t\tdayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&#xE1;b'],\n\t\tdayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&#xE1;b'],\n\t\tweekHeader: 'Sm',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['pt-BR']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-pt.js",
    "content": "/* Portuguese initialisation for the jQuery UI date picker plugin. */\njQuery(function($){\n\t$.datepicker.regional['pt'] = {\n\t\tcloseText: 'Fechar',\n\t\tprevText: '&#x3C;Anterior',\n\t\tnextText: 'Seguinte',\n\t\tcurrentText: 'Hoje',\n\t\tmonthNames: ['Janeiro','Fevereiro','Mar&#xE7;o','Abril','Maio','Junho',\n\t\t'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],\n\t\tmonthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',\n\t\t'Jul','Ago','Set','Out','Nov','Dez'],\n\t\tdayNames: ['Domingo','Segunda-feira','Ter&#xE7;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&#xE1;bado'],\n\t\tdayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&#xE1;b'],\n\t\tdayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&#xE1;b'],\n\t\tweekHeader: 'Sem',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['pt']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-rm.js",
    "content": "/* Romansh initialisation for the jQuery UI date picker plugin. */\n/* Written by Yvonne Gienal (yvonne.gienal@educa.ch). */\njQuery(function($){\n\t$.datepicker.regional['rm'] = {\n\t\tcloseText: 'Serrar',\n\t\tprevText: '&#x3C;Suandant',\n\t\tnextText: 'Precedent&#x3E;',\n\t\tcurrentText: 'Actual',\n\t\tmonthNames: ['Schaner','Favrer','Mars','Avrigl','Matg','Zercladur', 'Fanadur','Avust','Settember','October','November','December'],\n\t\tmonthNamesShort: ['Scha','Fev','Mar','Avr','Matg','Zer', 'Fan','Avu','Sett','Oct','Nov','Dec'],\n\t\tdayNames: ['Dumengia','Glindesdi','Mardi','Mesemna','Gievgia','Venderdi','Sonda'],\n\t\tdayNamesShort: ['Dum','Gli','Mar','Mes','Gie','Ven','Som'],\n\t\tdayNamesMin: ['Du','Gl','Ma','Me','Gi','Ve','So'],\n\t\tweekHeader: 'emna',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['rm']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ro.js",
    "content": "/* Romanian initialisation for the jQuery UI date picker plugin.\n *\n * Written by Edmond L. (ll_edmond@walla.com)\n * and Ionut G. Stan (ionut.g.stan@gmail.com)\n */\njQuery(function($){\n\t$.datepicker.regional['ro'] = {\n\t\tcloseText: 'Închide',\n\t\tprevText: '&#xAB; Luna precedentă',\n\t\tnextText: 'Luna următoare &#xBB;',\n\t\tcurrentText: 'Azi',\n\t\tmonthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',\n\t\t'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],\n\t\tmonthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',\n\t\t'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t\tdayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],\n\t\tdayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],\n\t\tdayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],\n\t\tweekHeader: 'Săpt',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ro']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ru.js",
    "content": "/* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Andrew Stromnov (stromnov@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['ru'] = {\n\t\tcloseText: 'Закрыть',\n\t\tprevText: '&#x3C;Пред',\n\t\tnextText: 'След&#x3E;',\n\t\tcurrentText: 'Сегодня',\n\t\tmonthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',\n\t\t'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],\n\t\tmonthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',\n\t\t'Июл','Авг','Сен','Окт','Ноя','Дек'],\n\t\tdayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],\n\t\tdayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],\n\t\tdayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],\n\t\tweekHeader: 'Нед',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ru']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-sk.js",
    "content": "/* Slovak initialisation for the jQuery UI date picker plugin. */\n/* Written by Vojtech Rinik (vojto@hmm.sk). */\njQuery(function($){\n\t$.datepicker.regional['sk'] = {\n\t\tcloseText: 'Zavrieť',\n\t\tprevText: '&#x3C;Predchádzajúci',\n\t\tnextText: 'Nasledujúci&#x3E;',\n\t\tcurrentText: 'Dnes',\n\t\tmonthNames: ['Január','Február','Marec','Apríl','Máj','Jún',\n\t\t'Júl','August','September','Október','November','December'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',\n\t\t'Júl','Aug','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['Nedeľa','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],\n\t\tdayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],\n\t\tdayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],\n\t\tweekHeader: 'Ty',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['sk']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-sl.js",
    "content": "/* Slovenian initialisation for the jQuery UI date picker plugin. */\n/* Written by Jaka Jancar (jaka@kubje.org). */\n/* c = &#x10D;, s = &#x161; z = &#x17E; C = &#x10C; S = &#x160; Z = &#x17D; */\njQuery(function($){\n\t$.datepicker.regional['sl'] = {\n\t\tcloseText: 'Zapri',\n\t\tprevText: '&#x3C;Prej&#x161;nji',\n\t\tnextText: 'Naslednji&#x3E;',\n\t\tcurrentText: 'Trenutni',\n\t\tmonthNames: ['Januar','Februar','Marec','April','Maj','Junij',\n\t\t'Julij','Avgust','September','Oktober','November','December'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\n\t\t'Jul','Avg','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['Nedelja','Ponedeljek','Torek','Sreda','&#x10C;etrtek','Petek','Sobota'],\n\t\tdayNamesShort: ['Ned','Pon','Tor','Sre','&#x10C;et','Pet','Sob'],\n\t\tdayNamesMin: ['Ne','Po','To','Sr','&#x10C;e','Pe','So'],\n\t\tweekHeader: 'Teden',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['sl']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-sq.js",
    "content": "/* Albanian initialisation for the jQuery UI date picker plugin. */\n/* Written by Flakron Bytyqi (flakron@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['sq'] = {\n\t\tcloseText: 'mbylle',\n\t\tprevText: '&#x3C;mbrapa',\n\t\tnextText: 'Përpara&#x3E;',\n\t\tcurrentText: 'sot',\n\t\tmonthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',\n\t\t'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],\n\t\tmonthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',\n\t\t'Kor','Gus','Sht','Tet','Nën','Dhj'],\n\t\tdayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],\n\t\tdayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],\n\t\tdayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],\n\t\tweekHeader: 'Ja',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['sq']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-sr-SR.js",
    "content": "/* Serbian i18n for the jQuery UI date picker plugin. */\n/* Written by Dejan Dimić. */\njQuery(function($){\n\t$.datepicker.regional['sr-SR'] = {\n\t\tcloseText: 'Zatvori',\n\t\tprevText: '&#x3C;',\n\t\tnextText: '&#x3E;',\n\t\tcurrentText: 'Danas',\n\t\tmonthNames: ['Januar','Februar','Mart','April','Maj','Jun',\n\t\t'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\n\t\t'Jul','Avg','Sep','Okt','Nov','Dec'],\n\t\tdayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],\n\t\tdayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],\n\t\tdayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],\n\t\tweekHeader: 'Sed',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['sr-SR']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-sr.js",
    "content": "/* Serbian i18n for the jQuery UI date picker plugin. */\n/* Written by Dejan Dimić. */\njQuery(function($){\n\t$.datepicker.regional['sr'] = {\n\t\tcloseText: 'Затвори',\n\t\tprevText: '&#x3C;',\n\t\tnextText: '&#x3E;',\n\t\tcurrentText: 'Данас',\n\t\tmonthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',\n\t\t'Јул','Август','Септембар','Октобар','Новембар','Децембар'],\n\t\tmonthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',\n\t\t'Јул','Авг','Сеп','Окт','Нов','Дец'],\n\t\tdayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],\n\t\tdayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],\n\t\tdayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],\n\t\tweekHeader: 'Сед',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['sr']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-sv.js",
    "content": "/* Swedish initialisation for the jQuery UI date picker plugin. */\n/* Written by Anders Ekdahl ( anders@nomadiz.se). */\njQuery(function($){\n\t$.datepicker.regional['sv'] = {\n\t\tcloseText: 'Stäng',\n\t\tprevText: '&#xAB;Förra',\n\t\tnextText: 'Nästa&#xBB;',\n\t\tcurrentText: 'Idag',\n\t\tmonthNames: ['Januari','Februari','Mars','April','Maj','Juni',\n\t\t'Juli','Augusti','September','Oktober','November','December'],\n\t\tmonthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',\n\t\t'Jul','Aug','Sep','Okt','Nov','Dec'],\n\t\tdayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],\n\t\tdayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],\n\t\tdayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],\n\t\tweekHeader: 'Ve',\n\t\tdateFormat: 'yy-mm-dd',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['sv']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-ta.js",
    "content": "/* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by S A Sureshkumar (saskumar@live.com). */\njQuery(function($){\n\t$.datepicker.regional['ta'] = {\n\t\tcloseText: 'மூடு',\n\t\tprevText: 'முன்னையது',\n\t\tnextText: 'அடுத்தது',\n\t\tcurrentText: 'இன்று',\n\t\tmonthNames: ['தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி',\n\t\t'ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'],\n\t\tmonthNamesShort: ['தை','மாசி','பங்','சித்','வைகா','ஆனி',\n\t\t'ஆடி','ஆவ','புர','ஐப்','கார்','மார்'],\n\t\tdayNames: ['ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'],\n\t\tdayNamesShort: ['ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'],\n\t\tdayNamesMin: ['ஞா','தி','செ','பு','வி','வெ','ச'],\n\t\tweekHeader: 'Не',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['ta']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-th.js",
    "content": "/* Thai initialisation for the jQuery UI date picker plugin. */\n/* Written by pipo (pipo@sixhead.com). */\njQuery(function($){\n\t$.datepicker.regional['th'] = {\n\t\tcloseText: 'ปิด',\n\t\tprevText: '&#xAB;&#xA0;ย้อน',\n\t\tnextText: 'ถัดไป&#xA0;&#xBB;',\n\t\tcurrentText: 'วันนี้',\n\t\tmonthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',\n\t\t'กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],\n\t\tmonthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',\n\t\t'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],\n\t\tdayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],\n\t\tdayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],\n\t\tdayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['th']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-tj.js",
    "content": "/* Tajiki (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Abdurahmon Saidov (saidovab@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['tj'] = {\n\t\tcloseText: 'Идома',\n\t\tprevText: '&#x3c;Қафо',\n\t\tnextText: 'Пеш&#x3e;',\n\t\tcurrentText: 'Имрӯз',\n\t\tmonthNames: ['Январ','Феврал','Март','Апрел','Май','Июн',\n\t\t'Июл','Август','Сентябр','Октябр','Ноябр','Декабр'],\n\t\tmonthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',\n\t\t'Июл','Авг','Сен','Окт','Ноя','Дек'],\n\t\tdayNames: ['якшанбе','душанбе','сешанбе','чоршанбе','панҷшанбе','ҷумъа','шанбе'],\n\t\tdayNamesShort: ['якш','душ','сеш','чор','пан','ҷум','шан'],\n\t\tdayNamesMin: ['Як','Дш','Сш','Чш','Пш','Ҷм','Шн'],\n\t\tweekHeader: 'Хф',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['tj']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-tr.js",
    "content": "/* Turkish initialisation for the jQuery UI date picker plugin. */\n/* Written by Izzet Emre Erkan (kara@karalamalar.net). */\njQuery(function($){\n\t$.datepicker.regional['tr'] = {\n\t\tcloseText: 'kapat',\n\t\tprevText: '&#x3C;geri',\n\t\tnextText: 'ileri&#x3e',\n\t\tcurrentText: 'bugün',\n\t\tmonthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',\n\t\t'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],\n\t\tmonthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',\n\t\t'Tem','Ağu','Eyl','Eki','Kas','Ara'],\n\t\tdayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],\n\t\tdayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],\n\t\tdayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],\n\t\tweekHeader: 'Hf',\n\t\tdateFormat: 'dd.mm.yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['tr']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-uk.js",
    "content": "/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Maxim Drogobitskiy (maxdao@gmail.com). */\n/* Corrected by Igor Milla (igor.fsp.milla@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['uk'] = {\n\t\tcloseText: 'Закрити',\n\t\tprevText: '&#x3C;',\n\t\tnextText: '&#x3E;',\n\t\tcurrentText: 'Сьогодні',\n\t\tmonthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',\n\t\t'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],\n\t\tmonthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',\n\t\t'Лип','Сер','Вер','Жов','Лис','Гру'],\n\t\tdayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],\n\t\tdayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],\n\t\tdayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],\n\t\tweekHeader: 'Тиж',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['uk']);\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-vi.js",
    "content": "/* Vietnamese initialisation for the jQuery UI date picker plugin. */\n/* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */\njQuery(function($){\n\t$.datepicker.regional['vi'] = {\n\t\tcloseText: 'Đóng',\n\t\tprevText: '&#x3C;Trước',\n\t\tnextText: 'Tiếp&#x3E;',\n\t\tcurrentText: 'Hôm nay',\n\t\tmonthNames: ['Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu',\n\t\t'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai'],\n\t\tmonthNamesShort: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6',\n\t\t'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'],\n\t\tdayNames: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],\n\t\tdayNamesShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],\n\t\tdayNamesMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],\n\t\tweekHeader: 'Tu',\n\t\tdateFormat: 'dd/mm/yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional['vi']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-zh-CN.js",
    "content": "/* Chinese initialisation for the jQuery UI date picker plugin. */\n/* Written by Cloudream (cloudream@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['zh-CN'] = {\n\t\tcloseText: '关闭',\n\t\tprevText: '&#x3C;上月',\n\t\tnextText: '下月&#x3E;',\n\t\tcurrentText: '今天',\n\t\tmonthNames: ['一月','二月','三月','四月','五月','六月',\n\t\t'七月','八月','九月','十月','十一月','十二月'],\n\t\tmonthNamesShort: ['一','二','三','四','五','六',\n\t\t'七','八','九','十','十一','十二'],\n\t\tdayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],\n\t\tdayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],\n\t\tdayNamesMin: ['日','一','二','三','四','五','六'],\n\t\tweekHeader: '周',\n\t\tdateFormat: 'yy-mm-dd',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: true,\n\t\tyearSuffix: '年'};\n\t$.datepicker.setDefaults($.datepicker.regional['zh-CN']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-zh-HK.js",
    "content": "/* Chinese initialisation for the jQuery UI date picker plugin. */\n/* Written by SCCY (samuelcychan@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['zh-HK'] = {\n\t\tcloseText: '關閉',\n\t\tprevText: '&#x3C;上月',\n\t\tnextText: '下月&#x3E;',\n\t\tcurrentText: '今天',\n\t\tmonthNames: ['一月','二月','三月','四月','五月','六月',\n\t\t'七月','八月','九月','十月','十一月','十二月'],\n\t\tmonthNamesShort: ['一','二','三','四','五','六',\n\t\t'七','八','九','十','十一','十二'],\n\t\tdayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],\n\t\tdayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],\n\t\tdayNamesMin: ['日','一','二','三','四','五','六'],\n\t\tweekHeader: '周',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 0,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: true,\n\t\tyearSuffix: '年'};\n\t$.datepicker.setDefaults($.datepicker.regional['zh-HK']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/i18n/jquery.ui.datepicker-zh-TW.js",
    "content": "/* Chinese initialisation for the jQuery UI date picker plugin. */\n/* Written by Ressol (ressol@gmail.com). */\njQuery(function($){\n\t$.datepicker.regional['zh-TW'] = {\n\t\tcloseText: '關閉',\n\t\tprevText: '&#x3C;上月',\n\t\tnextText: '下月&#x3E;',\n\t\tcurrentText: '今天',\n\t\tmonthNames: ['一月','二月','三月','四月','五月','六月',\n\t\t'七月','八月','九月','十月','十一月','十二月'],\n\t\tmonthNamesShort: ['一','二','三','四','五','六',\n\t\t'七','八','九','十','十一','十二'],\n\t\tdayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],\n\t\tdayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],\n\t\tdayNamesMin: ['日','一','二','三','四','五','六'],\n\t\tweekHeader: '周',\n\t\tdateFormat: 'yy/mm/dd',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: true,\n\t\tyearSuffix: '年'};\n\t$.datepicker.setDefaults($.datepicker.regional['zh-TW']);\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.blind.js",
    "content": "/*!\n * jQuery UI Effects Blind @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Blind\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\nvar rvertical = /up|down|vertical/,\n\trpositivemotion = /up|left|vertical|horizontal/;\n\n$.effects.effect.blind = function( o, done ) {\n\t// Create element\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"height\", \"width\" ],\n\t\tmode = $.effects.setMode( el, o.mode || \"hide\" ),\n\t\tdirection = o.direction || \"up\",\n\t\tvertical = rvertical.test( direction ),\n\t\tref = vertical ? \"height\" : \"width\",\n\t\tref2 = vertical ? \"top\" : \"left\",\n\t\tmotion = rpositivemotion.test( direction ),\n\t\tanimation = {},\n\t\tshow = mode === \"show\",\n\t\twrapper, distance, margin;\n\n\t// if already wrapped, the wrapper's properties are my property. #6245\n\tif ( el.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t$.effects.save( el.parent(), props );\n\t} else {\n\t\t$.effects.save( el, props );\n\t}\n\tel.show();\n\twrapper = $.effects.createWrapper( el ).css({\n\t\toverflow: \"hidden\"\n\t});\n\n\tdistance = wrapper[ ref ]();\n\tmargin = parseFloat( wrapper.css( ref2 ) );\n\n\tanimation[ ref ] = show ? distance : 0;\n\tif ( !motion ) {\n\t\tel\n\t\t\t.css( vertical ? \"bottom\" : \"right\", 0 )\n\t\t\t.css( vertical ? \"top\" : \"left\", \"auto\" )\n\t\t\t.css({ position: \"absolute\" });\n\n\tanimation[ ref2 ] = show ? margin : distance + margin;\n\t}\n\n\t// start at 0 if we are showing\n\tif ( show ) {\n\t\twrapper.css( ref, 0 );\n\t\tif ( ! motion ) {\n\t\t\twrapper.css( ref2, margin + distance );\n\t\t}\n\t}\n\n\t// Animate\n\twrapper.animate( animation, {\n\t\tduration: o.duration,\n\t\teasing: o.easing,\n\t\tqueue: false,\n\t\tcomplete: function() {\n\t\t\tif ( mode === \"hide\" ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, props );\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t}\n\t});\n\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.bounce.js",
    "content": "/*!\n * jQuery UI Effects Bounce @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Bounce\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.bounce = function( o, done ) {\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"height\", \"width\" ],\n\n\t\t// defaults:\n\t\tmode = $.effects.setMode( el, o.mode || \"effect\" ),\n\t\thide = mode === \"hide\",\n\t\tshow = mode === \"show\",\n\t\tdirection = o.direction || \"up\",\n\t\tdistance = o.distance,\n\t\ttimes = o.times || 5,\n\n\t\t// number of internal animations\n\t\tanims = times * 2 + ( show || hide ? 1 : 0 ),\n\t\tspeed = o.duration / anims,\n\t\teasing = o.easing,\n\n\t\t// utility:\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ),\n\t\ti,\n\t\tupAnim,\n\t\tdownAnim,\n\n\t\t// we will need to re-assemble the queue to stack our animations in place\n\t\tqueue = el.queue(),\n\t\tqueuelen = queue.length;\n\n\t// Avoid touching opacity to prevent clearType and PNG issues in IE\n\tif ( show || hide ) {\n\t\tprops.push( \"opacity\" );\n\t}\n\n\t$.effects.save( el, props );\n\tel.show();\n\t$.effects.createWrapper( el ); // Create Wrapper\n\n\t// default distance for the BIGGEST bounce is the outer Distance / 3\n\tif ( !distance ) {\n\t\tdistance = el[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]() / 3;\n\t}\n\n\tif ( show ) {\n\t\tdownAnim = { opacity: 1 };\n\t\tdownAnim[ ref ] = 0;\n\n\t\t// if we are showing, force opacity 0 and set the initial position\n\t\t// then do the \"first\" animation\n\t\tel.css( \"opacity\", 0 )\n\t\t\t.css( ref, motion ? -distance * 2 : distance * 2 )\n\t\t\t.animate( downAnim, speed, easing );\n\t}\n\n\t// start at the smallest distance if we are hiding\n\tif ( hide ) {\n\t\tdistance = distance / Math.pow( 2, times - 1 );\n\t}\n\n\tdownAnim = {};\n\tdownAnim[ ref ] = 0;\n\t// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here\n\tfor ( i = 0; i < times; i++ ) {\n\t\tupAnim = {};\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\tel.animate( upAnim, speed, easing )\n\t\t\t.animate( downAnim, speed, easing );\n\n\t\tdistance = hide ? distance * 2 : distance / 2;\n\t}\n\n\t// Last Bounce when Hiding\n\tif ( hide ) {\n\t\tupAnim = { opacity: 0 };\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\tel.animate( upAnim, speed, easing );\n\t}\n\n\tel.queue(function() {\n\t\tif ( hide ) {\n\t\t\tel.hide();\n\t\t}\n\t\t$.effects.restore( el, props );\n\t\t$.effects.removeWrapper( el );\n\t\tdone();\n\t});\n\n\t// inject all the animations we just queued to be first in line (after \"inprogress\")\n\tif ( queuelen > 1) {\n\t\tqueue.splice.apply( queue,\n\t\t\t[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );\n\t}\n\tel.dequeue();\n\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.clip.js",
    "content": "/*!\n * jQuery UI Effects Clip @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Clip\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.clip = function( o, done ) {\n\t// Create element\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"height\", \"width\" ],\n\t\tmode = $.effects.setMode( el, o.mode || \"hide\" ),\n\t\tshow = mode === \"show\",\n\t\tdirection = o.direction || \"vertical\",\n\t\tvert = direction === \"vertical\",\n\t\tsize = vert ? \"height\" : \"width\",\n\t\tposition = vert ? \"top\" : \"left\",\n\t\tanimation = {},\n\t\twrapper, animate, distance;\n\n\t// Save & Show\n\t$.effects.save( el, props );\n\tel.show();\n\n\t// Create Wrapper\n\twrapper = $.effects.createWrapper( el ).css({\n\t\toverflow: \"hidden\"\n\t});\n\tanimate = ( el[0].tagName === \"IMG\" ) ? wrapper : el;\n\tdistance = animate[ size ]();\n\n\t// Shift\n\tif ( show ) {\n\t\tanimate.css( size, 0 );\n\t\tanimate.css( position, distance / 2 );\n\t}\n\n\t// Create Animation Object:\n\tanimation[ size ] = show ? distance : 0;\n\tanimation[ position ] = show ? 0 : distance / 2;\n\n\t// Animate\n\tanimate.animate( animation, {\n\t\tqueue: false,\n\t\tduration: o.duration,\n\t\teasing: o.easing,\n\t\tcomplete: function() {\n\t\t\tif ( !show ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, props );\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t}\n\t});\n\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.core.js",
    "content": "/*!\n * jQuery UI Effects @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/\n */\n;(jQuery.effects || (function($, undefined) {\n\nvar backCompat = $.uiBackCompat !== false,\n\t// prefix used for storing data on .data()\n\tdataSpace = \"ui-effects-\";\n\n$.effects = {\n\teffect: {}\n};\n\n/******************************************************************************/\n/****************************** COLOR ANIMATIONS ******************************/\n/******************************************************************************/\n(function() {\n\n// override the animation for color styles\n$.each([\"backgroundColor\", \"borderBottomColor\", \"borderLeftColor\",\n\t\"borderRightColor\", \"borderTopColor\", \"borderColor\", \"color\", \"outlineColor\"],\nfunction(i, attr) {\n\t$.fx.step[attr] = function(fx) {\n\t\tif (!fx.colorInit) {\n\t\t\tfx.start = getColor(fx.elem, attr);\n\t\t\tfx.end = getRGB(fx.end);\n\t\t\tfx.colorInit = true;\n\t\t}\n\n\t\tfx.elem.style[attr] = \"rgb(\" +\n\t\t\tMath.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + \",\" +\n\t\t\tMath.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + \",\" +\n\t\t\tMath.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + \")\";\n\t};\n});\n\n// Color Conversion functions from highlightFade\n// By Blair Mitchelmore\n// http://jquery.offput.ca/highlightFade/\n\n// Parse strings looking for color tuples [255,255,255]\nfunction getRGB(color) {\n\t\tvar result;\n\n\t\t// Check if we're already dealing with an array of colors\n\t\tif ( color && color.constructor === Array && color.length === 3 ) {\n\t\t\treturn color;\n\t\t}\n\n\t\t// Look for rgb(num,num,num)\n\t\tif ( (result = /rgb\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)/.exec(color)) ) {\n\t\t\treturn [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];\n\t\t}\n\n\t\t// Look for rgb(num%,num%,num%)\n\t\tif ( (result = /rgb\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*\\)/.exec(color)) ) {\n\t\t\treturn [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];\n\t\t}\n\n\t\t// Look for #a0b1c2\n\t\tif ( (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) ) {\n\t\t\treturn [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];\n\t\t}\n\n\t\t// Look for #fff\n\t\tif ( (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) ) {\n\t\t\treturn [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];\n\t\t}\n\n\t\t// Look for rgba(0, 0, 0, 0) == transparent in Safari 3\n\t\tif ( (result = /rgba\\(0, 0, 0, 0\\)/.exec(color)) ) {\n\t\t\treturn colors.transparent;\n\t\t}\n\n\t\t// Otherwise, we're most likely dealing with a named color\n\t\treturn colors[$.trim(color).toLowerCase()];\n}\n\nfunction getColor(elem, attr) {\n\t\tvar color;\n\n\t\tdo {\n\t\t\t\tcolor = $.css(elem, attr);\n\n\t\t\t\t// Keep going until we find an element that has color, or we hit the body\n\t\t\t\tif ( color && color !== \"transparent\" || $.nodeName(elem, \"body\") ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tattr = \"backgroundColor\";\n\t\t} while ( (elem = elem.parentNode) );\n\n\t\treturn getRGB(color);\n}\n\n// Some named colors to work with\n// From Interface by Stefan Petre\n// http://interface.eyecon.ro/\n\nvar colors = {\n\taqua:[0,255,255],\n\tazure:[240,255,255],\n\tbeige:[245,245,220],\n\tblack:[0,0,0],\n\tblue:[0,0,255],\n\tbrown:[165,42,42],\n\tcyan:[0,255,255],\n\tdarkblue:[0,0,139],\n\tdarkcyan:[0,139,139],\n\tdarkgrey:[169,169,169],\n\tdarkgreen:[0,100,0],\n\tdarkkhaki:[189,183,107],\n\tdarkmagenta:[139,0,139],\n\tdarkolivegreen:[85,107,47],\n\tdarkorange:[255,140,0],\n\tdarkorchid:[153,50,204],\n\tdarkred:[139,0,0],\n\tdarksalmon:[233,150,122],\n\tdarkviolet:[148,0,211],\n\tfuchsia:[255,0,255],\n\tgold:[255,215,0],\n\tgreen:[0,128,0],\n\tindigo:[75,0,130],\n\tkhaki:[240,230,140],\n\tlightblue:[173,216,230],\n\tlightcyan:[224,255,255],\n\tlightgreen:[144,238,144],\n\tlightgrey:[211,211,211],\n\tlightpink:[255,182,193],\n\tlightyellow:[255,255,224],\n\tlime:[0,255,0],\n\tmagenta:[255,0,255],\n\tmaroon:[128,0,0],\n\tnavy:[0,0,128],\n\tolive:[128,128,0],\n\torange:[255,165,0],\n\tpink:[255,192,203],\n\tpurple:[128,0,128],\n\tviolet:[128,0,128],\n\tred:[255,0,0],\n\tsilver:[192,192,192],\n\twhite:[255,255,255],\n\tyellow:[255,255,0],\n\ttransparent: [255,255,255]\n};\n\n})();\n\n/******************************************************************************/\n/****************************** CLASS ANIMATIONS ******************************/\n/******************************************************************************/\n(function() {\n\nvar classAnimationActions = [ \"add\", \"remove\", \"toggle\" ],\n\tshorthandStyles = {\n\t\tborder: 1,\n\t\tborderBottom: 1,\n\t\tborderColor: 1,\n\t\tborderLeft: 1,\n\t\tborderRight: 1,\n\t\tborderTop: 1,\n\t\tborderWidth: 1,\n\t\tmargin: 1,\n\t\tpadding: 1\n\t};\n\n$.each([ \"borderLeftStyle\", \"borderRightStyle\", \"borderBottomStyle\", \"borderTopStyle\" ], function( _, prop ) {\n\t$.fx.step[ prop ] = function( fx ) {\n\t\tif ( fx.end !== \"none\" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {\n\t\t\tjQuery.style( fx.elem, prop, fx.end );\n\t\t\tfx.setAttr = true;\n\t\t}\n\t};\n});\n\nfunction getElementStyles() {\n\tvar style = this.ownerDocument.defaultView ?\n\t\t\tthis.ownerDocument.defaultView.getComputedStyle( this, null ) :\n\t\t\tthis.currentStyle,\n\t\tnewStyle = {},\n\t\tkey,\n\t\tcamelCase,\n\t\tlen;\n\n\t// webkit enumerates style porperties\n\tif ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {\n\t\tlen = style.length;\n\t\twhile ( len-- ) {\n\t\t\tkey = style[ len ];\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tnewStyle[ $.camelCase( key ) ] = style[ key ];\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor ( key in style ) {\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tnewStyle[ key ] = style[ key ];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newStyle;\n}\n\n\nfunction styleDifference( oldStyle, newStyle ) {\n\tvar diff = {},\n\t\tname, value;\n\n\tfor ( name in newStyle ) {\n\t\tvalue = newStyle[ name ];\n\t\tif ( oldStyle[ name ] !== value ) {\n\t\t\tif ( !shorthandStyles[ name ] ) {\n\t\t\t\tif ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {\n\t\t\t\t\tdiff[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn diff;\n}\n\n$.effects.animateClass = function( value, duration, easing, callback ) {\n\tvar o = $.speed( duration, easing, callback );\n\n\treturn this.queue( function() {\n\t\tvar animated = $( this ),\n\t\t\tbaseClass = animated.attr( \"class\" ) || \"\",\n\t\t\tapplyClassChange,\n\t\t\tallAnimations = o.children ? animated.find( \"*\" ).andSelf() : animated;\n\n\t\t// map the animated objects to store the original styles.\n\t\tallAnimations = allAnimations.map(function() {\n\t\t\tvar el = $( this );\n\t\t\treturn {\n\t\t\t\tel: el,\n\t\t\t\tstart: getElementStyles.call( this )\n\t\t\t};\n\t\t});\n\n\t\t// apply class change\n\t\tapplyClassChange = function() {\n\t\t\t$.each( classAnimationActions, function(i, action) {\n\t\t\t\tif ( value[ action ] ) {\n\t\t\t\t\tanimated[ action + \"Class\" ]( value[ action ] );\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\tapplyClassChange();\n\n\t\t// map all animated objects again - calculate new styles and diff\n\t\tallAnimations = allAnimations.map(function() {\n\t\t\tthis.end = getElementStyles.call( this.el[ 0 ] );\n\t\t\tthis.diff = styleDifference( this.start, this.end );\n\t\t\treturn this;\n\t\t});\n\n\t\t// apply original class\n\t\tanimated.attr( \"class\", baseClass );\n\n\t\t// map all animated objects again - this time collecting a promise\n\t\tallAnimations = allAnimations.map(function() {\n\t\t\tvar styleInfo = this,\n\t\t\t\tdfd = $.Deferred(),\n\t\t\t\topts = jQuery.extend({}, o, {\n\t\t\t\t\tqueue: false,\n\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\tdfd.resolve( styleInfo );\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\tthis.el.animate( this.diff, opts );\n\t\t\treturn dfd.promise();\n\t\t});\n\n\t\t// once all animations have completed:\n\t\t$.when.apply( $, allAnimations.get() ).done(function() {\n\n\t\t\t// set the final class\n\t\t\tapplyClassChange();\n\n\t\t\t// for each animated element,\n\t\t\t// clear all css properties that were animated\n\t\t\t$.each( arguments, function() {\n\t\t\t\tvar el = this.el;\n\t\t\t\t$.each( this.diff, function(key) {\n\t\t\t\t\tel.css( key, '' );\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// this is guarnteed to be there if you use jQuery.speed()\n\t\t\t// it also handles dequeuing the next anim...\n\t\t\to.complete.call( animated[ 0 ] );\n\t\t});\n\t});\n};\n\n$.fn.extend({\n\t_addClass: $.fn.addClass,\n\taddClass: function( classNames, speed, easing, callback ) {\n\t\treturn speed ?\n\t\t\t$.effects.animateClass.apply( this, [{ add: classNames }, speed, easing, callback ]) :\n\t\t\tthis._addClass(classNames);\n\t},\n\n\t_removeClass: $.fn.removeClass,\n\tremoveClass: function( classNames, speed, easing, callback ) {\n\t\treturn speed ?\n\t\t\t$.effects.animateClass.apply( this, [{ remove: classNames }, speed, easing, callback ]) :\n\t\t\tthis._removeClass(classNames);\n\t},\n\n\t_toggleClass: $.fn.toggleClass,\n\ttoggleClass: function( classNames, force, speed, easing, callback ) {\n\t\tif ( typeof force === \"boolean\" || force === undefined ) {\n\t\t\tif ( !speed ) {\n\t\t\t\t// without speed parameter;\n\t\t\t\treturn this._toggleClass( classNames, force );\n\t\t\t} else {\n\t\t\t\treturn $.effects.animateClass.apply( this, [( force ? { add:classNames } : { remove:classNames }), speed, easing, callback ]);\n\t\t\t}\n\t\t} else {\n\t\t\t// without force parameter;\n\t\t\treturn $.effects.animateClass.apply( this, [{ toggle: classNames }, force, speed, easing ]);\n\t\t}\n\t},\n\n\tswitchClass: function( remove, add, speed, easing, callback) {\n\t\treturn $.effects.animateClass.apply( this, [{\n\t\t\t\tadd: add,\n\t\t\t\tremove: remove\n\t\t\t}, speed, easing, callback ]);\n\t}\n});\n\n})();\n\n/******************************************************************************/\n/*********************************** EFFECTS **********************************/\n/******************************************************************************/\n\n(function() {\n\n$.extend( $.effects, {\n\tversion: \"@VERSION\",\n\n\t// Saves a set of properties in a data storage\n\tsave: function( element, set ) {\n\t\tfor( var i=0; i < set.length; i++ ) {\n\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\telement.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Restores a set of previously saved properties from a data storage\n\trestore: function( element, set ) {\n\t\tfor( var i=0; i < set.length; i++ ) {\n\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\telement.css( set[ i ], element.data( dataSpace + set[ i ] ) );\n\t\t\t}\n\t\t}\n\t},\n\n\tsetMode: function( el, mode ) {\n\t\tif (mode === \"toggle\") {\n\t\t\tmode = el.is( \":hidden\" ) ? \"show\" : \"hide\";\n\t\t}\n\t\treturn mode;\n\t},\n\n\t// Translates a [top,left] array into a baseline value\n\t// this should be a little more flexible in the future to handle a string & hash\n\tgetBaseline: function( origin, original ) {\n\t\tvar y, x;\n\t\tswitch ( origin[ 0 ] ) {\n\t\t\tcase \"top\": y = 0; break;\n\t\t\tcase \"middle\": y = 0.5; break;\n\t\t\tcase \"bottom\": y = 1; break;\n\t\t\tdefault: y = origin[ 0 ] / original.height;\n\t\t}\n\t\tswitch ( origin[ 1 ] ) {\n\t\t\tcase \"left\": x = 0; break;\n\t\t\tcase \"center\": x = 0.5; break;\n\t\t\tcase \"right\": x = 1; break;\n\t\t\tdefault: x = origin[ 1 ] / original.width;\n\t\t}\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y\n\t\t};\n\t},\n\n\t// Wraps the element around a wrapper that copies position properties\n\tcreateWrapper: function( element ) {\n\n\t\t// if the element is already wrapped, return it\n\t\tif ( element.parent().is( \".ui-effects-wrapper\" )) {\n\t\t\treturn element.parent();\n\t\t}\n\n\t\t// wrap the element\n\t\tvar props = {\n\t\t\t\twidth: element.outerWidth(true),\n\t\t\t\theight: element.outerHeight(true),\n\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t},\n\t\t\twrapper = $( \"<div></div>\" )\n\t\t\t\t.addClass( \"ui-effects-wrapper\" )\n\t\t\t\t.css({\n\t\t\t\t\tfontSize: \"100%\",\n\t\t\t\t\tbackground: \"transparent\",\n\t\t\t\t\tborder: \"none\",\n\t\t\t\t\tmargin: 0,\n\t\t\t\t\tpadding: 0\n\t\t\t\t}),\n\t\t\t// Store the size in case width/height are defined in % - Fixes #5245\n\t\t\tsize = {\n\t\t\t\twidth: element.width(),\n\t\t\t\theight: element.height()\n\t\t\t},\n\t\t\tactive = document.activeElement;\n\n\t\t// support: Firefox\n\t\t// Firefox incorrectly exposes anonymous content\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=561664\n\t\ttry {\n\t\t\tactive.id;\n\t\t} catch( e ) {\n\t\t\tactive = document.body;\n\t\t}\n\n\t\telement.wrap( wrapper );\n\n\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t$( active ).focus();\n\t\t}\n\n\t\twrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element\n\n\t\t// transfer positioning properties to the wrapper\n\t\tif ( element.css( \"position\" ) === \"static\" ) {\n\t\t\twrapper.css({ position: \"relative\" });\n\t\t\telement.css({ position: \"relative\" });\n\t\t} else {\n\t\t\t$.extend( props, {\n\t\t\t\tposition: element.css( \"position\" ),\n\t\t\t\tzIndex: element.css( \"z-index\" )\n\t\t\t});\n\t\t\t$.each([ \"top\", \"left\", \"bottom\", \"right\" ], function(i, pos) {\n\t\t\t\tprops[ pos ] = element.css( pos );\n\t\t\t\tif ( isNaN( parseInt( props[ pos ], 10 ) ) ) {\n\t\t\t\t\tprops[ pos ] = \"auto\";\n\t\t\t\t}\n\t\t\t});\n\t\t\telement.css({\n\t\t\t\tposition: \"relative\",\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\tright: \"auto\",\n\t\t\t\tbottom: \"auto\"\n\t\t\t});\n\t\t}\n\t\telement.css(size);\n\n\t\treturn wrapper.css( props ).show();\n\t},\n\n\tremoveWrapper: function( element ) {\n\t\tvar active = document.activeElement;\n\n\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\telement.parent().replaceWith( element );\n\n\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t$( active ).focus();\n\t\t\t}\n\t\t}\n\n\n\t\treturn element;\n\t},\n\n\tsetTransition: function( element, list, factor, value ) {\n\t\tvalue = value || {};\n\t\t$.each( list, function( i, x ) {\n\t\t\tvar unit = element.cssUnit( x );\n\t\t\tif ( unit[ 0 ] > 0 ) {\n\t\t\t\tvalue[ x ] = unit[ 0 ] * factor + unit[ 1 ];\n\t\t\t}\n\t\t});\n\t\treturn value;\n\t}\n});\n\n// return an effect options object for the given parameters:\nfunction _normalizeArguments( effect, options, speed, callback ) {\n\n\t// allow passing all optinos as the first parameter\n\tif ( $.isPlainObject( effect ) ) {\n\t\toptions = effect;\n\t\teffect = effect.effect;\n\t}\n\n\t// convert to an object\n\teffect = { effect: effect };\n\n\t// catch (effect)\n\tif ( options === undefined ) {\n\t\toptions = {};\n\t}\n\n\t// catch (effect, callback)\n\tif ( $.isFunction( options ) ) {\n\t\tcallback = options;\n\t\tspeed = null;\n\t\toptions = {};\n\t}\n\n\t// catch (effect, speed, ?)\n\tif ( typeof options === \"number\" || $.fx.speeds[ options ] ) {\n\t\tcallback = speed;\n\t\tspeed = options;\n\t\toptions = {};\n\t}\n\n\t// catch (effect, options, callback)\n\tif ( $.isFunction( speed ) ) {\n\t\tcallback = speed;\n\t\tspeed = null;\n\t}\n\n\t// add options to effect\n\tif ( options ) {\n\t\t$.extend( effect, options );\n\t}\n\n\tspeed = speed || options.duration;\n\teffect.duration = $.fx.off ? 0 :\n\t\ttypeof speed === \"number\" ? speed :\n\t\tspeed in $.fx.speeds ? $.fx.speeds[ speed ] :\n\t\t$.fx.speeds._default;\n\n\teffect.complete = callback || options.complete;\n\n\treturn effect;\n}\n\nfunction standardSpeed( speed ) {\n\t// valid standard speeds\n\tif ( !speed || typeof speed === \"number\" || $.fx.speeds[ speed ] ) {\n\t\treturn true;\n\t}\n\n\t// invalid strings - treat as \"normal\" speed\n\tif ( typeof speed === \"string\" && !$.effects.effect[ speed ] ) {\n\t\t// TODO: remove in 2.0 (#7115)\n\t\tif ( backCompat && $.effects[ speed ] ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n$.fn.extend({\n\teffect: function( effect, options, speed, callback ) {\n\t\tvar args = _normalizeArguments.apply( this, arguments ),\n\t\t\tmode = args.mode,\n\t\t\tqueue = args.queue,\n\t\t\teffectMethod = $.effects.effect[ args.effect ],\n\n\t\t\t// DEPRECATED: remove in 2.0 (#7115)\n\t\t\toldEffectMethod = !effectMethod && backCompat && $.effects[ args.effect ];\n\n\t\tif ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {\n\t\t\t// delegate to the original method (e.g., .show()) if possible\n\t\t\tif ( mode ) {\n\t\t\t\treturn this[ mode ]( args.duration, args.complete );\n\t\t\t} else {\n\t\t\t\treturn this.each( function() {\n\t\t\t\t\tif ( args.complete ) {\n\t\t\t\t\t\targs.complete.call( this );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfunction run( next ) {\n\t\t\tvar elem = $( this ),\n\t\t\t\tcomplete = args.complete,\n\t\t\t\tmode = args.mode;\n\n\t\t\tfunction done() {\n\t\t\t\tif ( $.isFunction( complete ) ) {\n\t\t\t\t\tcomplete.call( elem[0] );\n\t\t\t\t}\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if the element is hiddden and mode is hide,\n\t\t\t// or element is visible and mode is show\n\t\t\tif ( elem.is( \":hidden\" ) ? mode === \"hide\" : mode === \"show\" ) {\n\t\t\t\tdone();\n\t\t\t} else {\n\t\t\t\teffectMethod.call( elem[0], args, done );\n\t\t\t}\n\t\t}\n\n\t\t// TODO: remove this check in 2.0, effectMethod will always be true\n\t\tif ( effectMethod ) {\n\t\t\treturn queue === false ? this.each( run ) : this.queue( queue || \"fx\", run );\n\t\t} else {\n\t\t\t// DEPRECATED: remove in 2.0 (#7115)\n\t\t\treturn oldEffectMethod.call(this, {\n\t\t\t\toptions: args,\n\t\t\t\tduration: args.duration,\n\t\t\t\tcallback: args.complete,\n\t\t\t\tmode: args.mode\n\t\t\t});\n\t\t}\n\t},\n\n\t_show: $.fn.show,\n\tshow: function( speed ) {\n\t\tif ( standardSpeed( speed ) ) {\n\t\t\treturn this._show.apply( this, arguments );\n\t\t} else {\n\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\targs.mode = \"show\";\n\t\t\treturn this.effect.call( this, args );\n\t\t}\n\t},\n\n\t_hide: $.fn.hide,\n\thide: function( speed ) {\n\t\tif ( standardSpeed( speed ) ) {\n\t\t\treturn this._hide.apply( this, arguments );\n\t\t} else {\n\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\targs.mode = \"hide\";\n\t\t\treturn this.effect.call( this, args );\n\t\t}\n\t},\n\n\t// jQuery core overloads toggle and creates _toggle\n\t__toggle: $.fn.toggle,\n\ttoggle: function( speed ) {\n\t\tif ( standardSpeed( speed ) || typeof speed === \"boolean\" || $.isFunction( speed ) ) {\n\t\t\treturn this.__toggle.apply( this, arguments );\n\t\t} else {\n\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\targs.mode = \"toggle\";\n\t\t\treturn this.effect.call( this, args );\n\t\t}\n\t},\n\n\t// helper functions\n\tcssUnit: function(key) {\n\t\tvar style = this.css( key ),\n\t\t\tval = [];\n\n\t\t$.each( [ \"em\", \"px\", \"%\", \"pt\" ], function( i, unit ) {\n\t\t\tif ( style.indexOf( unit ) > 0 ) {\n\t\t\t\tval = [ parseFloat( style ), unit ];\n\t\t\t}\n\t\t});\n\t\treturn val;\n\t}\n});\n\n})();\n\n/******************************************************************************/\n/*********************************** EASING ***********************************/\n/******************************************************************************/\n\n(function() {\n\n// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)\n\nvar baseEasings = {};\n\n$.each( [ \"Quad\", \"Cubic\", \"Quart\", \"Quint\", \"Expo\" ], function( i, name ) {\n\tbaseEasings[ name ] = function( p ) {\n\t\treturn Math.pow( p, i + 2 );\n\t};\n});\n\n$.extend( baseEasings, {\n\tSine: function ( p ) {\n\t\treturn 1 - Math.cos( p * Math.PI / 2 );\n\t},\n\tCirc: function ( p ) {\n\t\treturn 1 - Math.sqrt( 1 - p * p );\n\t},\n\tElastic: function( p ) {\n\t\treturn p === 0 || p === 1 ? p :\n\t\t\t-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );\n\t},\n\tBack: function( p ) {\n\t\treturn p * p * ( 3 * p - 2 );\n\t},\n\tBounce: function ( p ) {\n\t\tvar pow2,\n\t\t\tbounce = 4;\n\n\t\twhile ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}\n\t\treturn 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );\n\t}\n});\n\n$.each( baseEasings, function( name, easeIn ) {\n\t$.easing[ \"easeIn\" + name ] = easeIn;\n\t$.easing[ \"easeOut\" + name ] = function( p ) {\n\t\treturn 1 - easeIn( 1 - p );\n\t};\n\t$.easing[ \"easeInOut\" + name ] = function( p ) {\n\t\treturn p < 0.5 ?\n\t\t\teaseIn( p * 2 ) / 2 :\n\t\t\t1 - easeIn( p * -2 + 2 ) / 2;\n\t};\n});\n\n})();\n\n})(jQuery));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.drop.js",
    "content": "/*!\n * jQuery UI Effects Drop @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Drop\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.drop = function( o, done ) {\n\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"opacity\", \"height\", \"width\" ],\n\t\tmode = $.effects.setMode( el, o.mode || \"hide\" ),\n\t\tshow = mode === \"show\",\n\t\tdirection = o.direction || \"left\",\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ) ? \"pos\" : \"neg\",\n\t\tanimation = {\n\t\t\topacity: show ? 1 : 0\n\t\t},\n\t\tdistance;\n\n\t// Adjust\n\t$.effects.save( el, props );\n\tel.show();\n\t$.effects.createWrapper( el );\n\n\tdistance = o.distance || el[ ref === \"top\" ? \"outerHeight\": \"outerWidth\" ]({ margin: true }) / 2;\n\n\tif ( show ) {\n\t\tel\n\t\t\t.css( \"opacity\", 0 )\n\t\t\t.css( ref, motion === \"pos\" ? -distance : distance );\n\t}\n\n\t// Animation\n\tanimation[ ref ] = ( show ?\n\t\t( motion === \"pos\" ? \"+=\" : \"-=\" ) :\n\t\t( motion === \"pos\" ? \"-=\" : \"+=\" ) ) +\n\t\tdistance;\n\n\t// Animate\n\tel.animate( animation, {\n\t\tqueue: false,\n\t\tduration: o.duration,\n\t\teasing: o.easing,\n\t\tcomplete: function() {\n\t\t\tif ( mode === \"hide\" ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, props );\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t}\n\t});\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.explode.js",
    "content": "/*!\n * jQuery UI Effects Explode @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Explode\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.explode = function( o, done ) {\n\n\tvar rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,\n\t\tcells = rows,\n\t\tel = $( this ),\n\t\tmode = $.effects.setMode( el, o.mode || \"hide\" ),\n\t\tshow = mode === \"show\",\n\n\t\t// show and then visibility:hidden the element before calculating offset\n\t\toffset = el.show().css( \"visibility\", \"hidden\" ).offset(),\n\n\t\t// width and height of a piece\n\t\twidth = Math.ceil( el.outerWidth() / cells ),\n\t\theight = Math.ceil( el.outerHeight() / rows ),\n\t\tpieces = [],\n\n\t\t// loop\n\t\ti, j, left, top, mx, my;\n\n\t// children animate complete:\n\tfunction childComplete() {\n\t\tpieces.push( this );\n\t\tif ( pieces.length === rows * cells ) {\n\t\t\tanimComplete();\n\t\t}\n\t}\n\n\t// clone the element for each row and cell.\n\tfor( i = 0; i < rows ; i++ ) { // ===>\n\t\ttop = offset.top + i * height;\n\t\tmy = i - ( rows - 1 ) / 2 ;\n\n\t\tfor( j = 0; j < cells ; j++ ) { // |||\n\t\t\tleft = offset.left + j * width;\n\t\t\tmx = j - ( cells - 1 ) / 2 ;\n\n\t\t\t// Create a clone of the now hidden main element that will be absolute positioned\n\t\t\t// within a wrapper div off the -left and -top equal to size of our pieces\n\t\t\tel\n\t\t\t\t.clone()\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.wrap( \"<div></div>\" )\n\t\t\t\t.css({\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\tvisibility: \"visible\",\n\t\t\t\t\tleft: -j * width,\n\t\t\t\t\ttop: -i * height\n\t\t\t\t})\n\n\t\t\t// select the wrapper - make it overflow: hidden and absolute positioned based on\n\t\t\t// where the original was located +left and +top equal to the size of pieces\n\t\t\t\t.parent()\n\t\t\t\t.addClass( \"ui-effects-explode\" )\n\t\t\t\t.css({\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\toverflow: \"hidden\",\n\t\t\t\t\twidth: width,\n\t\t\t\t\theight: height,\n\t\t\t\t\tleft: left + ( show ? mx * width : 0 ),\n\t\t\t\t\ttop: top + ( show ? my * height : 0 ),\n\t\t\t\t\topacity: show ? 0 : 1\n\t\t\t\t}).animate({\n\t\t\t\t\tleft: left + ( show ? 0 : mx * width ),\n\t\t\t\t\ttop: top + ( show ? 0 : my * height ),\n\t\t\t\t\topacity: show ? 1 : 0\n\t\t\t\t}, o.duration || 500, o.easing, childComplete );\n\t\t}\n\t}\n\n\tfunction animComplete() {\n\t\tel.css({\n\t\t\tvisibility: \"visible\"\n\t\t});\n\t\t$( pieces ).remove();\n\t\tif ( !show ) {\n\t\t\tel.hide();\n\t\t}\n\t\tdone();\n\t}\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.fade.js",
    "content": "/*!\n * jQuery UI Effects Fade @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Fade\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.fade = function( o, done ) {\n\tvar el = $( this ),\n\t\tmode = $.effects.setMode( el, o.mode || \"toggle\" ),\n\t\thide = mode === \"hide\";\n\n\tel.show();\n\tel.animate({\n\t\topacity: hide ? 0 : 1\n\t}, {\n\t\tqueue: false,\n\t\tduration: o.duration,\n\t\teasing: o.easing,\n\t\tcomplete: function() {\n\t\t\tif ( hide ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\tdone();\n\t\t}\n\t});\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.fold.js",
    "content": "/*!\n * jQuery UI Effects Fold @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Fold\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.fold = function( o, done ) {\n\n\t// Create element\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"height\", \"width\" ],\n\t\tmode = $.effects.setMode( el, o.mode || \"hide\" ),\n\t\tshow = mode === \"show\",\n\t\thide = mode === \"hide\",\n\t\tsize = o.size || 15,\n\t\tpercent = /([0-9]+)%/.exec( size ),\n\t\thorizFirst = !!o.horizFirst,\n\t\twidthFirst = show !== horizFirst,\n\t\tref = widthFirst ? [ \"width\", \"height\" ] : [ \"height\", \"width\" ],\n\t\tduration = o.duration / 2,\n\t\twrapper, distance,\n\t\tanimation1 = {},\n\t\tanimation2 = {};\n\n\t$.effects.save( el, props );\n\tel.show();\n\n\t// Create Wrapper\n\twrapper = $.effects.createWrapper( el ).css({\n\t\toverflow: \"hidden\"\n\t});\n\tdistance = widthFirst ?\n\t\t[ wrapper.width(), wrapper.height() ] :\n\t\t[ wrapper.height(), wrapper.width() ];\n\n\tif ( percent ) {\n\t\tsize = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];\n\t}\n\tif ( show ) {\n\t\twrapper.css( horizFirst ? {\n\t\t\theight: 0,\n\t\t\twidth: size\n\t\t} : {\n\t\t\theight: size,\n\t\t\twidth: 0\n\t\t});\n\t}\n\n\t// Animation\n\tanimation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;\n\tanimation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;\n\n\t// Animate\n\twrapper\n\t\t.animate( animation1, duration, o.easing )\n\t\t.animate( animation2, duration, o.easing, function() {\n\t\t\tif ( hide ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, props );\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t});\n\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.highlight.js",
    "content": "/*!\n * jQuery UI Effects Highlight @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Highlight\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.highlight = function( o, done ) {\n\tvar elem = $( this ),\n\t\tprops = [ \"backgroundImage\", \"backgroundColor\", \"opacity\" ],\n\t\tmode = $.effects.setMode( elem, o.mode || \"show\" ),\n\t\tanimation = {\n\t\t\tbackgroundColor: elem.css( \"backgroundColor\" )\n\t\t};\n\n\tif (mode === \"hide\") {\n\t\tanimation.opacity = 0;\n\t}\n\n\t$.effects.save( elem, props );\n\t\n\telem\n\t\t.show()\n\t\t.css({\n\t\t\tbackgroundImage: \"none\",\n\t\t\tbackgroundColor: o.color || \"#ffff99\"\n\t\t})\n\t\t.animate( animation, {\n\t\t\tqueue: false,\n\t\t\tduration: o.duration,\n\t\t\teasing: o.easing,\n\t\t\tcomplete: function() {\n\t\t\t\tif ( mode === \"hide\" ) {\n\t\t\t\t\telem.hide();\n\t\t\t\t}\n\t\t\t\t$.effects.restore( elem, props );\n\t\t\t\tdone();\n\t\t\t}\n\t\t});\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.pulsate.js",
    "content": "/*!\n * jQuery UI Effects Pulsate @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Pulsate\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.pulsate = function( o, done ) {\n\tvar elem = $( this ),\n\t\tmode = $.effects.setMode( elem, o.mode || \"show\" ),\n\t\tshow = mode === \"show\",\n\t\thide = mode === \"hide\",\n\t\tshowhide = ( show || mode === \"hide\" ),\n\n\t\t// showing or hiding leaves of the \"last\" animation\n\t\tanims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),\n\t\tduration = o.duration / anims,\n\t\tanimateTo = 0,\n\t\tqueue = elem.queue(),\n\t\tqueuelen = queue.length,\n\t\ti;\n\n\tif ( show || !elem.is(\":visible\")) {\n\t\telem.css( \"opacity\", 0 ).show();\n\t\tanimateTo = 1;\n\t}\n\n\t// anims - 1 opacity \"toggles\"\n\tfor ( i = 1; i < anims; i++ ) {\n\t\telem.animate({\n\t\t\topacity: animateTo\n\t\t}, duration, o.easing );\n\t\tanimateTo = 1 - animateTo;\n\t}\n\n\telem.animate({\n\t\topacity: animateTo\n\t}, duration, o.easing);\n\n\telem.queue(function() {\n\t\tif ( hide ) {\n\t\t\telem.hide();\n\t\t}\n\t\tdone();\n\t});\n\n\t// We just queued up \"anims\" animations, we need to put them next in the queue\n\tif ( queuelen > 1 ) {\n\t\tqueue.splice.apply( queue,\n\t\t\t[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );\n\t}\n\telem.dequeue();\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.scale.js",
    "content": "/*!\n * jQuery UI Effects Scale @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Scale\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.puff = function( o, done ) {\n\tvar elem = $( this ),\n\t\tmode = $.effects.setMode( elem, o.mode || \"hide\" ),\n\t\thide = mode === \"hide\",\n\t\tpercent = parseInt( o.percent, 10 ) || 150,\n\t\tfactor = percent / 100,\n\t\toriginal = {\n\t\t\theight: elem.height(),\n\t\t\twidth: elem.width()\n\t\t};\n\n\t$.extend( o, {\n\t\teffect: \"scale\",\n\t\tqueue: false,\n\t\tfade: true,\n\t\tmode: mode,\n\t\tcomplete: done,\n\t\tpercent: hide ? percent : 100,\n\t\tfrom: hide ?\n\t\t\toriginal :\n\t\t\t{\n\t\t\t\theight: original.height * factor,\n\t\t\t\twidth: original.width * factor\n\t\t\t}\n\t});\n\n\telem.effect( o );\n};\n\n$.effects.effect.scale = function( o, done ) {\n\n\t// Create element\n\tvar el = $( this ),\n\t\toptions = $.extend( true, {}, o ),\n\t\tmode = $.effects.setMode( el, o.mode || \"effect\" ),\n\t\tpercent = parseInt( o.percent, 10 ) ||\n\t\t\t( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === \"hide\" ? 0 : 100 ) ),\n\t\tdirection = o.direction || \"both\",\n\t\torigin = o.origin,\n\t\toriginal = {\n\t\t\theight: el.height(),\n\t\t\twidth: el.width(),\n\t\t\touterHeight: el.outerHeight(),\n\t\t\touterWidth: el.outerWidth()\n\t\t},\n\t\tfactor = {\n\t\t\ty: direction !== \"horizontal\" ? (percent / 100) : 1,\n\t\t\tx: direction !== \"vertical\" ? (percent / 100) : 1\n\t\t};\n\n\t// We are going to pass this effect to the size effect:\n\toptions.effect = \"size\";\n\toptions.queue = false;\n\toptions.complete = done;\n\n\t// Set default origin and restore for show/hide\n\tif ( mode !== \"effect\" ) {\n\t\toptions.origin = origin || [\"middle\",\"center\"];\n\t\toptions.restore = true;\n\t}\n\n\toptions.from = o.from || ( mode === \"show\" ? { height: 0, width: 0 } : original );\n\toptions.to = {\n\t\theight: original.height * factor.y,\n\t\twidth: original.width * factor.x,\n\t\touterHeight: original.outerHeight * factor.y,\n\t\touterWidth: original.outerWidth * factor.x\n\t};\n\n\t// Fade option to support puff\n\tif ( options.fade ) {\n\t\tif ( mode === \"show\" ) {\n\t\t\toptions.from.opacity = 0;\n\t\t\toptions.to.opacity = 1;\n\t\t}\n\t\tif ( mode === \"hide\" ) {\n\t\t\toptions.from.opacity = 1;\n\t\t\toptions.to.opacity = 0;\n\t\t}\n\t}\n\n\t// Animate\n\tel.effect( options );\n\n};\n\n$.effects.effect.size = function( o, done ) {\n\n\t// Create element\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"width\", \"height\", \"overflow\", \"opacity\" ],\n\n\t\t// Always restore\n\t\tprops1 = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"overflow\", \"opacity\" ],\n\n\t\t// Copy for children\n\t\tprops2 = [ \"width\", \"height\", \"overflow\" ],\n\t\tcProps = [ \"fontSize\" ],\n\t\tvProps = [ \"borderTopWidth\", \"borderBottomWidth\", \"paddingTop\", \"paddingBottom\" ],\n\t\thProps = [ \"borderLeftWidth\", \"borderRightWidth\", \"paddingLeft\", \"paddingRight\" ],\n\n\t\t// Set options\n\t\tmode = $.effects.setMode( el, o.mode || \"effect\" ),\n\t\trestore = o.restore || mode !== \"effect\",\n\t\tscale = o.scale || \"both\",\n\t\torigin = o.origin || [ \"middle\", \"center\" ],\n\t\toriginal, baseline, factor,\n\t\tposition = el.css( \"position\" );\n\n\tif ( mode === \"show\" ) {\n\t\tel.show();\n\t}\n\toriginal = {\n\t\theight: el.height(),\n\t\twidth: el.width(),\n\t\touterHeight: el.outerHeight(),\n\t\touterWidth: el.outerWidth()\n\t};\n\n\tel.from = o.from || original;\n\tel.to = o.to || original;\n\n\t// Set scaling factor\n\tfactor = {\n\t\tfrom: {\n\t\t\ty: el.from.height / original.height,\n\t\t\tx: el.from.width / original.width\n\t\t},\n\t\tto: {\n\t\t\ty: el.to.height / original.height,\n\t\t\tx: el.to.width / original.width\n\t\t}\n\t};\n\n\t// Scale the css box\n\tif ( scale === \"box\" || scale === \"both\" ) {\n\n\t\t// Vertical props scaling\n\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\tprops = props.concat( vProps );\n\t\t\tel.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );\n\t\t\tel.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );\n\t\t}\n\n\t\t// Horizontal props scaling\n\t\tif ( factor.from.x !== factor.to.x ) {\n\t\t\tprops = props.concat( hProps );\n\t\t\tel.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );\n\t\t\tel.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );\n\t\t}\n\t}\n\n\t// Scale the content\n\tif ( scale === \"content\" || scale === \"both\" ) {\n\n\t\t// Vertical props scaling\n\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\tprops = props.concat( cProps );\n\t\t\tel.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );\n\t\t\tel.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );\n\t\t}\n\t}\n\n\t$.effects.save( el, restore ? props : props1 );\n\tel.show();\n\t$.effects.createWrapper( el );\n\tel.css( \"overflow\", \"hidden\" ).css( el.from );\n\n\t// Adjust\n\tif (origin) { // Calculate baseline shifts\n\t\tbaseline = $.effects.getBaseline( origin, original );\n\t\tel.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;\n\t\tel.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;\n\t\tel.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;\n\t\tel.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;\n\t}\n\tel.css( el.from ); // set top & left\n\n\t// Animate\n\tif ( scale === \"content\" || scale === \"both\" ) { // Scale the children\n\n\t\t// Add margins/font-size\n\t\tvProps = vProps.concat([ \"marginTop\", \"marginBottom\" ]).concat(cProps);\n\t\thProps = hProps.concat([ \"marginLeft\", \"marginRight\" ]);\n\t\tprops2 = props.concat(vProps).concat(hProps);\n\n\t\tel.find( \"*[width]\" ).each( function(){\n\t\t\tvar child = $( this ),\n\t\t\t\tc_original = {\n\t\t\t\t\theight: child.height(),\n\t\t\t\t\twidth: child.width()\n\t\t\t\t};\n\t\t\tif (restore) {\n\t\t\t\t$.effects.save(child, props2);\n\t\t\t}\n\n\t\t\tchild.from = {\n\t\t\t\theight: c_original.height * factor.from.y,\n\t\t\t\twidth: c_original.width * factor.from.x\n\t\t\t};\n\t\t\tchild.to = {\n\t\t\t\theight: c_original.height * factor.to.y,\n\t\t\t\twidth: c_original.width * factor.to.x\n\t\t\t};\n\n\t\t\t// Vertical props scaling\n\t\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\t\tchild.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );\n\t\t\t\tchild.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );\n\t\t\t}\n\n\t\t\t// Horizontal props scaling\n\t\t\tif ( factor.from.x !== factor.to.x ) {\n\t\t\t\tchild.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );\n\t\t\t\tchild.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );\n\t\t\t}\n\n\t\t\t// Animate children\n\t\t\tchild.css( child.from );\n\t\t\tchild.animate( child.to, o.duration, o.easing, function() {\n\n\t\t\t\t// Restore children\n\t\t\t\tif ( restore ) {\n\t\t\t\t\t$.effects.restore( child, props2 );\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// Animate\n\tel.animate( el.to, {\n\t\tqueue: false,\n\t\tduration: o.duration,\n\t\teasing: o.easing,\n\t\tcomplete: function() {\n\t\t\tif ( el.to.opacity === 0 ) {\n\t\t\t\tel.css( \"opacity\", el.from.opacity );\n\t\t\t}\n\t\t\tif( mode === \"hide\" ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, restore ? props : props1 );\n\t\t\tif ( !restore ) {\n\n\t\t\t\t// we need to calculate our new positioning based on the scaling\n\t\t\t\tif ( position === \"static\" ) {\n\t\t\t\t\tel.css({\n\t\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\t\ttop: el.to.top,\n\t\t\t\t\t\tleft: el.to.left\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t$.each([ \"top\", \"left\" ], function( idx, pos ) {\n\t\t\t\t\t\tel.css( pos, function( _, str ) {\n\t\t\t\t\t\t\tvar val = parseInt( str, 10 ),\n\t\t\t\t\t\t\t\ttoRef = idx ? el.to.left : el.to.top;\n\n\t\t\t\t\t\t\t// if original was \"auto\", recalculate the new value from wrapper\n\t\t\t\t\t\t\tif ( str === \"auto\" ) {\n\t\t\t\t\t\t\t\treturn toRef + \"px\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn val + toRef + \"px\";\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t}\n\t});\n\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.shake.js",
    "content": "/*!\n * jQuery UI Effects Shake @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Shake\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.shake = function( o, done ) {\n\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"height\", \"width\" ],\n\t\tmode = $.effects.setMode( el, o.mode || \"effect\" ),\n\t\tdirection = o.direction || \"left\",\n\t\tdistance = o.distance || 20,\n\t\ttimes = o.times || 3,\n\t\tanims = times * 2 + 1,\n\t\tspeed = o.duration,\n\t\tref = (direction === \"up\" || direction === \"down\") ? \"top\" : \"left\",\n\t\tpositiveMotion = (direction === \"up\" || direction === \"left\"),\n\t\tanimation = {},\n\t\tanimation1 = {},\n\t\tanimation2 = {},\n\t\ti,\n\n\t\t// we will need to re-assemble the queue to stack our animations in place\n\t\tqueue = el.queue(),\n\t\tqueuelen = queue.length;\n\n\t$.effects.save( el, props );\n\tel.show();\n\t$.effects.createWrapper( el );\n\n\t// Animation\n\tanimation[ ref ] = ( positiveMotion ? \"-=\" : \"+=\" ) + distance;\n\tanimation1[ ref ] = ( positiveMotion ? \"+=\" : \"-=\" ) + distance * 2;\n\tanimation2[ ref ] = ( positiveMotion ? \"-=\" : \"+=\" ) + distance * 2;\n\n\t// Animate\n\tel.animate( animation, speed, o.easing );\n\n\t// Shakes\n\tfor ( i = 1; i < times; i++ ) {\n\t\tel.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );\n\t}\n\tel\n\t\t.animate( animation1, speed, o.easing )\n\t\t.animate( animation, speed / 2, o.easing )\n\t\t.queue(function() {\n\t\t\tif ( mode === \"hide\" ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, props );\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t});\n\n\t// inject all the animations we just queued to be first in line (after \"inprogress\")\n\tif ( queuelen > 1) {\n\t\tqueue.splice.apply( queue,\n\t\t\t[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );\n\t}\n\tel.dequeue();\n\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.slide.js",
    "content": "/*!\n * jQuery UI Effects Slide @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Slide\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.slide = function( o, done ) {\n\n\t// Create element\n\tvar el = $( this ),\n\t\tprops = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"width\", \"height\" ],\n\t\tmode = $.effects.setMode( el, o.mode || \"show\" ),\n\t\tshow = mode === \"show\",\n\t\tdirection = o.direction || \"left\",\n\t\tref = (direction === \"up\" || direction === \"down\") ? \"top\" : \"left\",\n\t\tpositiveMotion = (direction === \"up\" || direction === \"left\"),\n\t\tdistance,\n\t\tanimation = {};\n\n\t// Adjust\n\t$.effects.save( el, props );\n\tel.show();\n\tdistance = o.distance || el[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]({\n\t\tmargin: true\n\t});\n\n\t$.effects.createWrapper( el ).css({\n\t\toverflow: \"hidden\"\n\t});\n\n\tif ( show ) {\n\t\tel.css( ref, positiveMotion ? (isNaN(distance) ? \"-\" + distance : -distance) : distance );\n\t}\n\n\t// Animation\n\tanimation[ ref ] = ( show ?\n\t\t( positiveMotion ? \"+=\" : \"-=\") :\n\t\t( positiveMotion ? \"-=\" : \"+=\")) +\n\t\tdistance;\n\n\t// Animate\n\tel.animate( animation, {\n\t\tqueue: false,\n\t\tduration: o.duration,\n\t\teasing: o.easing,\n\t\tcomplete: function() {\n\t\t\tif ( mode === \"hide\" ) {\n\t\t\t\tel.hide();\n\t\t\t}\n\t\t\t$.effects.restore( el, props );\n\t\t\t$.effects.removeWrapper( el );\n\t\t\tdone();\n\t\t}\n\t});\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.effects.transfer.js",
    "content": "/*!\n * jQuery UI Effects Transfer @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Effects/Transfer\n *\n * Depends:\n *\tjquery.effects.core.js\n */\n(function( $, undefined ) {\n\n$.effects.effect.transfer = function( o, done ) {\n\tvar elem = $( this ),\n\t\ttarget = $( o.to ),\n\t\ttargetFixed = target.css( \"position\" ) === \"fixed\",\n\t\tbody = $(\"body\"),\n\t\tfixTop = targetFixed ? body.scrollTop() : 0,\n\t\tfixLeft = targetFixed ? body.scrollLeft() : 0,\n\t\tendPosition = target.offset(),\n\t\tanimation = {\n\t\t\ttop: endPosition.top - fixTop ,\n\t\t\tleft: endPosition.left - fixLeft ,\n\t\t\theight: target.innerHeight(),\n\t\t\twidth: target.innerWidth()\n\t\t},\n\t\tstartPosition = elem.offset(),\n\t\ttransfer = $( '<div class=\"ui-effects-transfer\"></div>' )\n\t\t\t.appendTo( document.body )\n\t\t\t.addClass( o.className )\n\t\t\t.css({\n\t\t\t\ttop: startPosition.top - fixTop ,\n\t\t\t\tleft: startPosition.left - fixLeft ,\n\t\t\t\theight: elem.innerHeight(),\n\t\t\t\twidth: elem.innerWidth(),\n\t\t\t\tposition: targetFixed ? \"fixed\" : \"absolute\"\n\t\t\t})\n\t\t\t.animate( animation, o.duration, o.easing, function() {\n\t\t\t\ttransfer.remove();\n\t\t\t\tdone();\n\t\t\t});\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.accordion.js",
    "content": "/*!\n * jQuery UI Accordion @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Accordion\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\nvar uid = 0,\n\thideProps = {},\n\tshowProps = {},\n\tshowPropsAdjust = {};\n\nhideProps.height = hideProps.paddingTop = hideProps.paddingBottom =\n\thideProps.borderTopWidth = hideProps.borderBottomWidth = \"hide\";\nshowProps.height = showProps.paddingTop = showProps.paddingBottom =\n\tshowProps.borderTopWidth = showProps.borderBottomWidth = \"show\";\n$.extend( showPropsAdjust, showProps, { accordionHeight: \"show\" } );\n\n$.fx.step.accordionHeight = function( fx ) {\n\tvar elem = $( fx.elem ),\n\t\tdata = elem.data( \"ui-accordion-height\" );\n\telem.height( data.total - elem.outerHeight() - data.toHide.outerHeight() + elem.height() );\n};\n\n$.widget( \"ui.accordion\", {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\tactive: 0,\n\t\tanimate: {},\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theader: \"> li > :first-child,> :not(li):even\",\n\t\theightStyle: \"auto\",\n\t\ticons: {\n\t\t\tactiveHeader: \"ui-icon-triangle-1-s\",\n\t\t\theader: \"ui-icon-triangle-1-e\"\n\t\t},\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null\n\t},\n\n\t_create: function() {\n\t\tvar accordionId = this.accordionId = \"ui-accordion-\" +\n\t\t\t\t(this.element.attr( \"id\" ) || ++uid),\n\t\t\toptions = this.options;\n\n\t\tthis.prevShow = this.prevHide = $();\n\t\tthis.element.addClass( \"ui-accordion ui-widget ui-helper-reset\" );\n\n\t\tthis.headers = this.element.find( options.header )\n\t\t\t.addClass( \"ui-accordion-header ui-helper-reset ui-state-default ui-corner-all\" );\n\t\tthis._hoverable( this.headers );\n\t\tthis._focusable( this.headers );\n\n\t\tthis.headers.next()\n\t\t\t.addClass( \"ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom\" )\n\t\t\t.hide();\n\n\t\t// don't allow collapsible: false and active: false\n\t\tif ( !options.collapsible && options.active === false ) {\n\t\t\toptions.active = 0;\n\t\t}\n\t\t// handle negative values\n\t\tif ( options.active < 0 ) {\n\t\t\toptions.active += this.headers.length;\n\t\t}\n\t\tthis.active = this._findActive( options.active )\n\t\t\t.addClass( \"ui-accordion-header-active ui-state-active\" )\n\t\t\t.toggleClass( \"ui-corner-all ui-corner-top\" );\n\t\tthis.active.next()\n\t\t\t.addClass( \"ui-accordion-content-active\" )\n\t\t\t.show();\n\n\t\tthis._createIcons();\n\t\tthis.originalHeight = this.element[0].style.height;\n\t\tthis.refresh();\n\n\t\t// ARIA\n\t\tthis.element.attr( \"role\", \"tablist\" );\n\n\t\tthis.headers\n\t\t\t.attr( \"role\", \"tab\" )\n\t\t\t.each(function( i ) {\n\t\t\t\tvar header = $( this ),\n\t\t\t\t\theaderId = header.attr( \"id\" ),\n\t\t\t\t\tpanel = header.next(),\n\t\t\t\t\tpanelId = panel.attr( \"id\" );\n\t\t\t\tif ( !headerId ) {\n\t\t\t\t\theaderId = accordionId + \"-header-\" + i;\n\t\t\t\t\theader.attr( \"id\", headerId );\n\t\t\t\t}\n\t\t\t\tif ( !panelId ) {\n\t\t\t\t\tpanelId = accordionId + \"-panel-\" + i;\n\t\t\t\t\tpanel.attr( \"id\", panelId );\n\t\t\t\t}\n\t\t\t\theader.attr( \"aria-controls\", panelId );\n\t\t\t\tpanel.attr( \"aria-labelledby\", headerId );\n\t\t\t})\n\t\t\t.next()\n\t\t\t\t.attr( \"role\", \"tabpanel\" );\n\n\t\tthis.headers\n\t\t\t.not( this.active )\n\t\t\t.attr({\n\t\t\t\t\"aria-selected\": \"false\",\n\t\t\t\ttabIndex: -1\n\t\t\t})\n\t\t\t.next()\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t})\n\t\t\t\t.hide();\n\n\t\t// make sure at least one header is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.headers.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active.attr({\n\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\ttabIndex: 0\n\t\t\t})\n\t\t\t.next()\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t});\n\t\t}\n\n\t\tthis._bind( this.headers, { keydown: \"_keydown\" });\n\t\tthis._bind( this.headers.next(), { keydown: \"_panelKeyDown\" });\n\t\tthis._setupEvents( options.event );\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\theader: this.active,\n\t\t\tcontent: !this.active.length ? $() : this.active.next()\n\t\t};\n\t},\n\n\t_createIcons: function() {\n\t\tvar icons = this.options.icons;\n\t\tif ( icons ) {\n\t\t\t$( \"<span>\" )\n\t\t\t\t.addClass( \"ui-accordion-header-icon ui-icon \" + icons.header )\n\t\t\t\t.prependTo( this.headers );\n\t\t\tthis.active.children( \".ui-accordion-header-icon\" )\n\t\t\t\t.removeClass( icons.header )\n\t\t\t\t.addClass( icons.activeHeader );\n\t\t\tthis.headers.addClass( \"ui-accordion-icons\" );\n\t\t}\n\t},\n\n\t_destroyIcons: function() {\n\t\tthis.headers\n\t\t\t.removeClass( \"ui-accordion-icons\" )\n\t\t\t.children( \".ui-accordion-header-icon\" )\n\t\t\t\t.remove();\n\t},\n\n\t_destroy: function() {\n\t\tvar contents;\n\n\t\t// clean up main element\n\t\tthis.element\n\t\t\t.removeClass( \"ui-accordion ui-widget ui-helper-reset\" )\n\t\t\t.removeAttr( \"role\" );\n\n\t\t// clean up headers\n\t\tthis.headers\n\t\t\t.removeClass( \"ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-selected\" )\n\t\t\t.removeAttr( \"aria-controls\" )\n\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t.each(function() {\n\t\t\t\tif ( /^ui-accordion/.test( this.id ) ) {\n\t\t\t\t\tthis.removeAttribute( \"id\" );\n\t\t\t\t}\n\t\t\t});\n\t\tthis._destroyIcons();\n\n\t\t// clean up content panels\n\t\tcontents = this.headers.next()\n\t\t\t.css( \"display\", \"\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-expanded\" )\n\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t.removeAttr( \"aria-labelledby\" )\n\t\t\t.removeClass( \"ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled\" )\n\t\t\t.each(function() {\n\t\t\t\tif ( /^ui-accordion/.test( this.id ) ) {\n\t\t\t\t\tthis.removeAttribute( \"id\" );\n\t\t\t\t}\n\t\t\t});\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tthis.element.css( \"height\", this.originalHeight );\n\t\t\tcontents.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tif ( this.options.event ) {\n\t\t\t\tthis.headers.unbind(\n\t\t\t\t\tthis.options.event.split( \" \" ).join( \".accordion \" ) + \".accordion\" );\n\t\t\t}\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\t// setting collapsible: false while collapsed; open first panel\n\t\tif ( key === \"collapsible\" && !value && this.options.active === false ) {\n\t\t\tthis._activate( 0 );\n\t\t}\n\n\t\tif ( key === \"icons\" ) {\n\t\t\tthis._destroyIcons();\n\t\t\tif ( value ) {\n\t\t\t\tthis._createIcons();\n\t\t\t}\n\t\t}\n\n\t\t// #5332 - opacity doesn't cascade to positioned elements in IE\n\t\t// so we need to add the disabled class to the headers and panels\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.headers.add( this.headers.next() )\n\t\t\t\t.toggleClass( \"ui-state-disabled\", !!value );\n\t\t}\n\t},\n\n\t_keydown: function( event ) {\n\t\tif ( event.altKey || event.ctrlKey ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar keyCode = $.ui.keyCode,\n\t\t\tlength = this.headers.length,\n\t\t\tcurrentIndex = this.headers.index( event.target ),\n\t\t\ttoFocus = false;\n\n\t\tswitch ( event.keyCode ) {\n\t\t\tcase keyCode.RIGHT:\n\t\t\tcase keyCode.DOWN:\n\t\t\t\ttoFocus = this.headers[ ( currentIndex + 1 ) % length ];\n\t\t\t\tbreak;\n\t\t\tcase keyCode.LEFT:\n\t\t\tcase keyCode.UP:\n\t\t\t\ttoFocus = this.headers[ ( currentIndex - 1 + length ) % length ];\n\t\t\t\tbreak;\n\t\t\tcase keyCode.SPACE:\n\t\t\tcase keyCode.ENTER:\n\t\t\t\tthis._eventHandler( event );\n\t\t\t\tbreak;\n\t\t\tcase keyCode.HOME:\n\t\t\t\ttoFocus = this.headers[ 0 ];\n\t\t\t\tbreak;\n\t\t\tcase keyCode.END:\n\t\t\t\ttoFocus = this.headers[ length - 1 ];\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ( toFocus ) {\n\t\t\t$( event.target ).attr( \"tabIndex\", -1 );\n\t\t\t$( toFocus ).attr( \"tabIndex\", 0 );\n\t\t\ttoFocus.focus();\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_panelKeyDown : function( event ) {\n\t\tif ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {\n\t\t\t$( event.currentTarget ).prev().focus();\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tvar maxHeight, overflow,\n\t\t\theightStyle = this.options.heightStyle,\n\t\t\tparent = this.element.parent();\n\n\t\tthis.element.css( \"height\", this.originalHeight );\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\t// IE 6 treats height like minHeight, so we need to turn off overflow\n\t\t\t// in order to get a reliable height\n\t\t\t// we use the minHeight support test because we assume that only\n\t\t\t// browsers that don't support minHeight will treat height as minHeight\n\t\t\tif ( !$.support.minHeight ) {\n\t\t\t\toverflow = parent.css( \"overflow\" );\n\t\t\t\tparent.css( \"overflow\", \"hidden\");\n\t\t\t}\n\t\t\tmaxHeight = parent.height();\n\t\t\tthis.element.siblings( \":visible\" ).each(function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t});\n\t\t\tif ( overflow ) {\n\t\t\t\tparent.css( \"overflow\", overflow );\n\t\t\t}\n\n\t\t\tthis.headers.each(function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t});\n\n\t\t\tthis.headers.next()\n\t\t\t\t.each(function() {\n\t\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t\t})\n\t\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.headers.next()\n\t\t\t\t.each(function() {\n\t\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( \"\" ).height() );\n\t\t\t\t})\n\t\t\t\t.height( maxHeight );\n\t\t}\n\n\t\tif ( heightStyle !== \"content\" ) {\n\t\t\tthis.element.height( this.element.height() );\n\t\t}\n\t},\n\n\t_activate: function( index ) {\n\t\tvar active = this._findActive( index )[ 0 ];\n\n\t\t// trying to activate the already active panel\n\t\tif ( active === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// trying to collapse, simulate a click on the currently active header\n\t\tactive = active || this.active[ 0 ];\n\n\t\tthis._eventHandler({\n\t\t\ttarget: active,\n\t\t\tcurrentTarget: active,\n\t\t\tpreventDefault: $.noop\n\t\t});\n\t},\n\n\t_findActive: function( selector ) {\n\t\treturn typeof selector === \"number\" ? this.headers.eq( selector ) : $();\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {};\n\t\tif ( !event ) {\n\t\t\treturn;\n\t\t}\n\t\t$.each( event.split(\" \"), function( index, eventName ) {\n\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t});\n\t\tthis._bind( this.headers, events );\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar options = this.options,\n\t\t\tactive = this.active,\n\t\t\tclicked = $( event.currentTarget ),\n\t\t\tclickedIsActive = clicked[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : clicked.next(),\n\t\t\ttoHide = active.next(),\n\t\t\teventData = {\n\t\t\t\toldHeader: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewHeader: collapsing ? $() : clicked,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif (\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.headers.index( clicked );\n\n\t\t// when the call to ._toggle() comes after the class changes\n\t\t// it causes a very odd bug in IE 8 (see #6720)\n\t\tthis.active = clickedIsActive ? $() : clicked;\n\t\tthis._toggle( eventData );\n\n\t\t// switch classes\n\t\t// corner classes on the previously active header stay after the animation\n\t\tactive.removeClass( \"ui-accordion-header-active ui-state-active\" );\n\t\tif ( options.icons ) {\n\t\t\tactive.children( \".ui-accordion-header-icon\" )\n\t\t\t\t.removeClass( options.icons.activeHeader )\n\t\t\t\t.addClass( options.icons.header );\n\t\t}\n\n\t\tif ( !clickedIsActive ) {\n\t\t\tclicked\n\t\t\t\t.removeClass( \"ui-corner-all\" )\n\t\t\t\t.addClass( \"ui-accordion-header-active ui-state-active ui-corner-top\" );\n\t\t\tif ( options.icons ) {\n\t\t\t\tclicked.children( \".ui-accordion-header-icon\" )\n\t\t\t\t\t.removeClass( options.icons.header )\n\t\t\t\t\t.addClass( options.icons.activeHeader );\n\t\t\t}\n\n\t\t\tclicked\n\t\t\t\t.next()\n\t\t\t\t.addClass( \"ui-accordion-content-active\" );\n\t\t}\n\t},\n\n\t_toggle: function( data ) {\n\t\tvar toShow = data.newPanel,\n\t\t\ttoHide = this.prevShow.length ? this.prevShow : data.oldPanel;\n\n\t\t// handle activating a panel during the animation for another activation\n\t\tthis.prevShow.add( this.prevHide ).stop( true, true );\n\t\tthis.prevShow = toShow;\n\t\tthis.prevHide = toHide;\n\n\t\tif ( this.options.animate ) {\n\t\t\tthis._animate( toShow, toHide, data );\n\t\t} else {\n\t\t\ttoHide.hide();\n\t\t\ttoShow.show();\n\t\t\tthis._toggleComplete( data );\n\t\t}\n\n\t\ttoHide.attr({\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\"aria-hidden\": \"true\"\n\t\t});\n\t\ttoHide.prev().attr( \"aria-selected\", \"false\" );\n\t\t// if we're switching panels, remove the old header from the tab order\n\t\t// if we're opening from collapsed state, remove the previous header from the tab order\n\t\t// if we're collapsing, then keep the collapsing header in the tab order\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\ttoHide.prev().attr( \"tabIndex\", -1 );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.headers.filter(function() {\n\t\t\t\treturn $( this ).attr( \"tabIndex\" ) === 0;\n\t\t\t})\n\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow\n\t\t\t.attr({\n\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t})\n\t\t\t.prev()\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t});\n\t},\n\n\t_animate: function( toShow, toHide, data ) {\n\t\tvar total, easing, duration,\n\t\t\tthat = this,\n\t\t\tdown = toShow.length &&\n\t\t\t\t( !toHide.length || ( toShow.index() < toHide.index() ) ),\n\t\t\tanimate = this.options.animate || {},\n\t\t\toptions = down && animate.down || animate,\n\t\t\tcomplete = function() {\n\t\t\t\ttoShow.removeData( \"ui-accordion-height\" );\n\t\t\t\tthat._toggleComplete( data );\n\t\t\t};\n\n\t\tif ( typeof options === \"number\" ) {\n\t\t\tduration = options;\n\t\t}\n\t\tif ( typeof options === \"string\" ) {\n\t\t\teasing = options;\n\t\t}\n\t\t// fall back from options to animation in case of partial down settings\n\t\teasing = easing || options.easing || animate.easing;\n\t\tduration = duration || options.duration || animate.duration;\n\n\t\tif ( !toHide.length ) {\n\t\t\treturn toShow.animate( showProps, duration, easing, complete );\n\t\t}\n\t\tif ( !toShow.length ) {\n\t\t\treturn toHide.animate( hideProps, duration, easing, complete );\n\t\t}\n\n\t\ttotal = toShow.show().outerHeight();\n\t\ttoHide.animate( hideProps, duration, easing );\n\t\ttoShow\n\t\t\t.hide()\n\t\t\t.data( \"ui-accordion-height\", {\n\t\t\t\ttotal: total,\n\t\t\t\ttoHide: toHide\n\t\t\t})\n\t\t\t.animate( this.options.heightStyle === \"content\" ? showProps : showPropsAdjust,\n\t\t\t\tduration, easing, complete );\n\t},\n\n\t_toggleComplete: function( data ) {\n\t\tvar toHide = data.oldPanel;\n\n\t\ttoHide\n\t\t\t.removeClass( \"ui-accordion-content-active\" )\n\t\t\t.prev()\n\t\t\t\t.removeClass( \"ui-corner-top\" )\n\t\t\t\t.addClass( \"ui-corner-all\" );\n\n\t\t// Work around for rendering bug in IE (#5421)\n\t\tif ( toHide.length ) {\n\t\t\ttoHide.parent()[0].className = toHide.parent()[0].className;\n\t\t}\n\n\t\tthis._trigger( \"activate\", null, data );\n\t}\n});\n\n\n\n// DEPRECATED\nif ( $.uiBackCompat !== false ) {\n\t// navigation options\n\t(function( $, prototype ) {\n\t\t$.extend( prototype.options, {\n\t\t\tnavigation: false,\n\t\t\tnavigationFilter: function() {\n\t\t\t\treturn this.href.toLowerCase() === location.href.toLowerCase();\n\t\t\t}\n\t\t});\n\n\t\tvar _create = prototype._create;\n\t\tprototype._create = function() {\n\t\t\tif ( this.options.navigation ) {\n\t\t\t\tvar that = this,\n\t\t\t\t\theaders = this.element.find( this.options.header ),\n\t\t\t\t\tcontent = headers.next(),\n\t\t\t\t\tcurrent = headers.add( content )\n\t\t\t\t\t\t.find( \"a\" )\n\t\t\t\t\t\t.filter( this.options.navigationFilter )\n\t\t\t\t\t\t[ 0 ];\n\t\t\t\tif ( current ) {\n\t\t\t\t\theaders.add( content ).each( function( index ) {\n\t\t\t\t\t\tif ( $.contains( this, current ) ) {\n\t\t\t\t\t\t\tthat.options.active = Math.floor( index / 2 );\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t_create.call( this );\n\t\t};\n\t}( jQuery, jQuery.ui.accordion.prototype ) );\n\n\t// height options\n\t(function( $, prototype ) {\n\t\t$.extend( prototype.options, {\n\t\t\theightStyle: null, // remove default so we fall back to old values\n\t\t\tautoHeight: true, // use heightStyle: \"auto\"\n\t\t\tclearStyle: false, // use heightStyle: \"content\"\n\t\t\tfillSpace: false // use heightStyle: \"fill\"\n\t\t});\n\n\t\tvar _create = prototype._create,\n\t\t\t_setOption = prototype._setOption;\n\n\t\t$.extend( prototype, {\n\t\t\t_create: function() {\n\t\t\t\tthis.options.heightStyle = this.options.heightStyle ||\n\t\t\t\t\tthis._mergeHeightStyle();\n\n\t\t\t\t_create.call( this );\n\t\t\t},\n\n\t\t\t_setOption: function( key, value ) {\n\t\t\t\tif ( key === \"autoHeight\" || key === \"clearStyle\" || key === \"fillSpace\" ) {\n\t\t\t\t\tthis.options.heightStyle = this._mergeHeightStyle();\n\t\t\t\t}\n\t\t\t\t_setOption.apply( this, arguments );\n\t\t\t},\n\n\t\t\t_mergeHeightStyle: function() {\n\t\t\t\tvar options = this.options;\n\n\t\t\t\tif ( options.fillSpace ) {\n\t\t\t\t\treturn \"fill\";\n\t\t\t\t}\n\n\t\t\t\tif ( options.clearStyle ) {\n\t\t\t\t\treturn \"content\";\n\t\t\t\t}\n\n\t\t\t\tif ( options.autoHeight ) {\n\t\t\t\t\treturn \"auto\";\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}( jQuery, jQuery.ui.accordion.prototype ) );\n\n\t// icon options\n\t(function( $, prototype ) {\n\t\t$.extend( prototype.options.icons, {\n\t\t\tactiveHeader: null, // remove default so we fall back to old values\n\t\t\theaderSelected: \"ui-icon-triangle-1-s\"\n\t\t});\n\n\t\tvar _createIcons = prototype._createIcons;\n\t\tprototype._createIcons = function() {\n\t\t\tif ( this.options.icons ) {\n\t\t\t\tthis.options.icons.activeHeader = this.options.icons.activeHeader ||\n\t\t\t\t\tthis.options.icons.headerSelected;\n\t\t\t}\n\t\t\t_createIcons.call( this );\n\t\t};\n\t}( jQuery, jQuery.ui.accordion.prototype ) );\n\n\t// expanded active option, activate method\n\t(function( $, prototype ) {\n\t\tprototype.activate = prototype._activate;\n\n\t\tvar _findActive = prototype._findActive;\n\t\tprototype._findActive = function( index ) {\n\t\t\tif ( index === -1 ) {\n\t\t\t\tindex = false;\n\t\t\t}\n\t\t\tif ( index && typeof index !== \"number\" ) {\n\t\t\t\tindex = this.headers.index( this.headers.filter( index ) );\n\t\t\t\tif ( index === -1 ) {\n\t\t\t\t\tindex = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn _findActive.call( this, index );\n\t\t};\n\t}( jQuery, jQuery.ui.accordion.prototype ) );\n\n\t// resize method\n\tjQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh;\n\n\t// change events\n\t(function( $, prototype ) {\n\t\t$.extend( prototype.options, {\n\t\t\tchange: null,\n\t\t\tchangestart: null\n\t\t});\n\n\t\tvar _trigger = prototype._trigger;\n\t\tprototype._trigger = function( type, event, data ) {\n\t\t\tvar ret = _trigger.apply( this, arguments );\n\t\t\tif ( !ret ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( type === \"beforeActivate\" ) {\n\t\t\t\tret = _trigger.call( this, \"changestart\", event, {\n\t\t\t\t\toldHeader: data.oldHeader,\n\t\t\t\t\toldContent: data.oldPanel,\n\t\t\t\t\tnewHeader: data.newHeader,\n\t\t\t\t\tnewContent: data.newPanel\n\t\t\t\t});\n\t\t\t} else if ( type === \"activate\" ) {\n\t\t\t\tret = _trigger.call( this, \"change\", event, {\n\t\t\t\t\toldHeader: data.oldHeader,\n\t\t\t\t\toldContent: data.oldPanel,\n\t\t\t\t\tnewHeader: data.newHeader,\n\t\t\t\t\tnewContent: data.newPanel\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\t}( jQuery, jQuery.ui.accordion.prototype ) );\n\n\t// animated option\n\t// NOTE: this only provides support for \"slide\", \"bounceslide\", and easings\n\t// not the full $.ui.accordion.animations API\n\t(function( $, prototype ) {\n\t\t$.extend( prototype.options, {\n\t\t\tanimate: null,\n\t\t\tanimated: \"slide\"\n\t\t});\n\n\t\tvar _create = prototype._create;\n\t\tprototype._create = function() {\n\t\t\tvar options = this.options;\n\t\t\tif ( options.animate === null ) {\n\t\t\t\tif ( !options.animated ) {\n\t\t\t\t\toptions.animate = false;\n\t\t\t\t} else if ( options.animated === \"slide\" ) {\n\t\t\t\t\toptions.animate = 300;\n\t\t\t\t} else if ( options.animated === \"bounceslide\" ) {\n\t\t\t\t\toptions.animate = {\n\t\t\t\t\t\tduration: 200,\n\t\t\t\t\t\tdown: {\n\t\t\t\t\t\t\teasing: \"easeOutBounce\",\n\t\t\t\t\t\t\tduration: 1000\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\toptions.animate = options.animated;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_create.call( this );\n\t\t};\n\t}( jQuery, jQuery.ui.accordion.prototype ) );\n}\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.autocomplete.js",
    "content": "/*!\n * jQuery UI Autocomplete @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Autocomplete\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n *\tjquery.ui.position.js\n *\tjquery.ui.menu.js\n */\n(function( $, undefined ) {\n\n// used to prevent race conditions with remote data sources\nvar requestIndex = 0;\n\n$.widget( \"ui.autocomplete\", {\n\tversion: \"@VERSION\",\n\tdefaultElement: \"<input>\",\n\toptions: {\n\t\tappendTo: \"body\",\n\t\tautoFocus: false,\n\t\tdelay: 300,\n\t\tminLength: 1,\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\tsource: null,\n\n\t\t// callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresponse: null,\n\t\tsearch: null,\n\t\tselect: null\n\t},\n\n\tpending: 0,\n\n\t_create: function() {\n\t\t// Some browsers only repeat keydown events, not keypress events,\n\t\t// so we use the suppressKeyPress flag to determine if we've already\n\t\t// handled the keydown event. #7269\n\t\t// Unfortunately the code for & in keypress is the same as the up arrow,\n\t\t// so we use the suppressKeyPressRepeat flag to avoid handling keypress\n\t\t// events when we know the keydown event was used to modify the\n\t\t// search term. #7799\n\t\tvar suppressKeyPress, suppressKeyPressRepeat, suppressInput;\n\n\t\tthis.isMultiLine = this.element.is( \"textarea,[contenteditable]\" );\n\t\tthis.valueMethod = this.element[ this.element.is( \"input,textarea\" ) ? \"val\" : \"text\" ];\n\t\tthis.isNewMenu = true;\n\n\t\tthis.element\n\t\t\t.addClass( \"ui-autocomplete-input\" )\n\t\t\t.attr( \"autocomplete\", \"off\" );\n\n\t\tthis._bind({\n\t\t\tkeydown: function( event ) {\n\t\t\t\tif ( this.element.prop( \"readOnly\" ) ) {\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tsuppressInput = true;\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsuppressKeyPress = false;\n\t\t\t\tsuppressInput = false;\n\t\t\t\tsuppressKeyPressRepeat = false;\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ENTER:\n\t\t\t\tcase keyCode.NUMPAD_ENTER:\n\t\t\t\t\t// when menu is open and has focus\n\t\t\t\t\tif ( this.menu.active ) {\n\t\t\t\t\t\t// #6055 - Opera still allows the keypress to occur\n\t\t\t\t\t\t// which causes forms to submit\n\t\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.TAB:\n\t\t\t\t\tif ( this.menu.active ) {\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ESCAPE:\n\t\t\t\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tthis._value( this.term );\n\t\t\t\t\t\tthis.close( event );\n\t\t\t\t\t\t// Different browsers have different default behavior for escape\n\t\t\t\t\t\t// Single press can mean undo or clear\n\t\t\t\t\t\t// Double press in IE means clear the whole form\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\t\t\t\t\t// search timeout should be triggered before the input value is changed\n\t\t\t\t\tthis._searchTimeout( event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tkeypress: function( event ) {\n\t\t\t\tif ( suppressKeyPress ) {\n\t\t\t\t\tsuppressKeyPress = false;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( suppressKeyPressRepeat ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// replicate some key handlers to allow them to repeat in Firefox and Opera\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tinput: function( event ) {\n\t\t\t\tif ( suppressInput ) {\n\t\t\t\t\tsuppressInput = false;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._searchTimeout( event );\n\t\t\t},\n\t\t\tfocus: function() {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.previous = this._value();\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tif ( this.cancelBlur ) {\n\t\t\t\t\tdelete this.cancelBlur;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tclearTimeout( this.searching );\n\t\t\t\tthis.close( event );\n\t\t\t\tthis._change( event );\n\t\t\t}\n\t\t});\n\n\t\tthis._initSource();\n\t\tthis.menu = $( \"<ul>\" )\n\t\t\t.addClass( \"ui-autocomplete\" )\n\t\t\t.appendTo( this.document.find( this.options.appendTo || \"body\" )[ 0 ] )\n\t\t\t.menu({\n\t\t\t\t// custom key handling for now\n\t\t\t\tinput: $(),\n\t\t\t\t// disable ARIA support, the live region takes care of that\n\t\t\t\trole: null\n\t\t\t})\n\t\t\t.zIndex( this.element.zIndex() + 1 )\n\t\t\t.hide()\n\t\t\t.data( \"menu\" );\n\t\tthis._bind( this.menu.element, {\n\t\t\tmousedown: function( event ) {\n\t\t\t\t// prevent moving focus out of the text field\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t\tthis.cancelBlur = true;\n\t\t\t\tthis._delay(function() {\n\t\t\t\t\tdelete this.cancelBlur;\n\t\t\t\t});\n\n\t\t\t\t// clicking on the scrollbar causes focus to shift to the body\n\t\t\t\t// but we can't detect a mouseup or a click immediately afterward\n\t\t\t\t// so we have to track the next mousedown and close the menu if\n\t\t\t\t// the user clicks somewhere outside of the autocomplete\n\t\t\t\tvar menuElement = this.menu.element[ 0 ];\n\t\t\t\tif ( !$( event.target ).closest( \".ui-menu-item\" ).length ) {\n\t\t\t\t\tthis._delay(function() {\n\t\t\t\t\t\tvar that = this;\n\t\t\t\t\t\tthis.document.one( \"mousedown\", function( event ) {\n\t\t\t\t\t\t\tif ( event.target !== that.element[ 0 ] &&\n\t\t\t\t\t\t\t\t\tevent.target !== menuElement &&\n\t\t\t\t\t\t\t\t\t!$.contains( menuElement, event.target ) ) {\n\t\t\t\t\t\t\t\tthat.close();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmenufocus: function( event, ui ) {\n\t\t\t\t// #7024 - Prevent accidental activation of menu items in Firefox\n\t\t\t\tif ( this.isNewMenu ) {\n\t\t\t\t\tthis.isNewMenu = false;\n\t\t\t\t\tif ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis.menu.blur();\n\n\t\t\t\t\t\tthis.document.one( \"mousemove\", function() {\n\t\t\t\t\t\t\t$( event.target ).trigger( event.originalEvent );\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// back compat for _renderItem using item.autocomplete, via #7810\n\t\t\t\t// TODO remove the fallback, see #8156\n\t\t\t\tvar item = ui.item.data( \"ui-autocomplete-item\" ) || ui.item.data( \"item.autocomplete\" );\n\t\t\t\tif ( false !== this._trigger( \"focus\", event, { item: item } ) ) {\n\t\t\t\t\t// use value to match what will end up in the input, if it was a key event\n\t\t\t\t\tif ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis._value( item.value );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Normally the input is populated with the item's value as the\n\t\t\t\t\t// menu is navigated, causing screen readers to notice a change and\n\t\t\t\t\t// announce the item. Since the focus event was canceled, this doesn't\n\t\t\t\t\t// happen, so we update the live region so that screen readers can\n\t\t\t\t\t// still notice the change and announce it.\n\t\t\t\t\tthis.liveRegion.text( item.value );\n\t\t\t\t}\n\t\t\t},\n\t\t\tmenuselect: function( event, ui ) {\n\t\t\t\t// back compat for _renderItem using item.autocomplete, via #7810\n\t\t\t\t// TODO remove the fallback, see #8156\n\t\t\t\tvar item = ui.item.data( \"ui-autocomplete-item\" ) || ui.item.data( \"item.autocomplete\" ),\n\t\t\t\t\tprevious = this.previous;\n\n\t\t\t\t// only trigger when focus was lost (click on menu)\n\t\t\t\tif ( this.element[0] !== this.document[0].activeElement ) {\n\t\t\t\t\tthis.element.focus();\n\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t// #6109 - IE triggers two focus events and the second\n\t\t\t\t\t// is asynchronous, so we need to reset the previous\n\t\t\t\t\t// term synchronously and asynchronously :-(\n\t\t\t\t\tthis._delay(function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t\tthis.selectedItem = item;\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif ( false !== this._trigger( \"select\", event, { item: item } ) ) {\n\t\t\t\t\tthis._value( item.value );\n\t\t\t\t}\n\t\t\t\t// reset the term after the select event\n\t\t\t\t// this allows custom select handling to work properly\n\t\t\t\tthis.term = this._value();\n\n\t\t\t\tthis.close( event );\n\t\t\t\tthis.selectedItem = item;\n\t\t\t}\n\t\t});\n\n\t\tthis.liveRegion = $( \"<span>\", {\n\t\t\t\trole: \"status\",\n\t\t\t\t\"aria-live\": \"polite\"\n\t\t\t})\n\t\t\t.addClass( \"ui-helper-hidden-accessible\" )\n\t\t\t.insertAfter( this.element );\n\n\t\tif ( $.fn.bgiframe ) {\n\t\t\t this.menu.element.bgiframe();\n\t\t}\n\n\t\t// turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._bind( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_destroy: function() {\n\t\tclearTimeout( this.searching );\n\t\tthis.element\n\t\t\t.removeClass( \"ui-autocomplete-input\" )\n\t\t\t.removeAttr( \"autocomplete\" );\n\t\tthis.menu.element.remove();\n\t\tthis.liveRegion.remove();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"source\" ) {\n\t\t\tthis._initSource();\n\t\t}\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.menu.element.appendTo( this.document.find( value || \"body\" )[0] );\n\t\t}\n\t\tif ( key === \"disabled\" && value && this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\t},\n\n\t_initSource: function() {\n\t\tvar array, url,\n\t\t\tthat = this;\n\t\tif ( $.isArray(this.options.source) ) {\n\t\t\tarray = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tresponse( $.ui.autocomplete.filter( array, request.term ) );\n\t\t\t};\n\t\t} else if ( typeof this.options.source === \"string\" ) {\n\t\t\turl = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tif ( that.xhr ) {\n\t\t\t\t\tthat.xhr.abort();\n\t\t\t\t}\n\t\t\t\tthat.xhr = $.ajax({\n\t\t\t\t\turl: url,\n\t\t\t\t\tdata: request,\n\t\t\t\t\tdataType: \"json\",\n\t\t\t\t\tsuccess: function( data, status ) {\n\t\t\t\t\t\tresponse( data );\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\tresponse( [] );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t};\n\t\t} else {\n\t\t\tthis.source = this.options.source;\n\t\t}\n\t},\n\n\t_searchTimeout: function( event ) {\n\t\tclearTimeout( this.searching );\n\t\tthis.searching = this._delay(function() {\n\t\t\t// only search if the value has changed\n\t\t\tif ( this.term !== this._value() ) {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.search( null, event );\n\t\t\t}\n\t\t}, this.options.delay );\n\t},\n\n\tsearch: function( value, event ) {\n\t\tvalue = value != null ? value : this._value();\n\n\t\t// always save the actual value, not the one passed as an argument\n\t\tthis.term = this._value();\n\n\t\tif ( value.length < this.options.minLength ) {\n\t\t\treturn this.close( event );\n\t\t}\n\n\t\tif ( this._trigger( \"search\", event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._search( value );\n\t},\n\n\t_search: function( value ) {\n\t\tthis.pending++;\n\t\tthis.element.addClass( \"ui-autocomplete-loading\" );\n\t\tthis.cancelSearch = false;\n\n\t\tthis.source( { term: value }, this._response() );\n\t},\n\n\t_response: function() {\n\t\tvar that = this,\n\t\t\tindex = ++requestIndex;\n\n\t\treturn function( content ) {\n\t\t\tif ( index === requestIndex ) {\n\t\t\t\tthat.__response( content );\n\t\t\t}\n\n\t\t\tthat.pending--;\n\t\t\tif ( !that.pending ) {\n\t\t\t\tthat.element.removeClass( \"ui-autocomplete-loading\" );\n\t\t\t}\n\t\t};\n\t},\n\n\t__response: function( content ) {\n\t\tif ( content ) {\n\t\t\tcontent = this._normalize( content );\n\t\t}\n\t\tthis._trigger( \"response\", null, { content: content } );\n\t\tif ( !this.options.disabled && content && content.length && !this.cancelSearch ) {\n\t\t\tthis._suggest( content );\n\t\t\tthis._trigger( \"open\" );\n\t\t} else {\n\t\t\t// use ._close() instead of .close() so we don't cancel future searches\n\t\t\tthis._close();\n\t\t}\n\t},\n\n\tclose: function( event ) {\n\t\tthis.cancelSearch = true;\n\t\tthis._close( event );\n\t},\n\n\t_close: function( event ) {\n\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.menu.element.hide();\n\t\t\tthis.menu.blur();\n\t\t\tthis.isNewMenu = true;\n\t\t\tthis._trigger( \"close\", event );\n\t\t}\n\t},\n\n\t_change: function( event ) {\n\t\tif ( this.previous !== this._value() ) {\n\t\t\tthis._trigger( \"change\", event, { item: this.selectedItem } );\n\t\t}\n\t},\n\n\t_normalize: function( items ) {\n\t\t// assume all items have the right format when the first item is complete\n\t\tif ( items.length && items[0].label && items[0].value ) {\n\t\t\treturn items;\n\t\t}\n\t\treturn $.map( items, function( item ) {\n\t\t\tif ( typeof item === \"string\" ) {\n\t\t\t\treturn {\n\t\t\t\t\tlabel: item,\n\t\t\t\t\tvalue: item\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn $.extend({\n\t\t\t\tlabel: item.label || item.value,\n\t\t\t\tvalue: item.value || item.label\n\t\t\t}, item );\n\t\t});\n\t},\n\n\t_suggest: function( items ) {\n\t\tvar ul = this.menu.element\n\t\t\t.empty()\n\t\t\t.zIndex( this.element.zIndex() + 1 );\n\t\tthis._renderMenu( ul, items );\n\t\t// TODO refresh should check if the active item is still in the dom, removing the need for a manual blur\n\t\tthis.menu.blur();\n\t\tthis.menu.refresh();\n\n\t\t// size and position menu\n\t\tul.show();\n\t\tthis._resizeMenu();\n\t\tul.position( $.extend({\n\t\t\tof: this.element\n\t\t}, this.options.position ));\n\n\t\tif ( this.options.autoFocus ) {\n\t\t\tthis.menu.next();\n\t\t}\n\t},\n\n\t_resizeMenu: function() {\n\t\tvar ul = this.menu.element;\n\t\tul.outerWidth( Math.max(\n\t\t\t// Firefox wraps long text (possibly a rounding bug)\n\t\t\t// so we add 1px to avoid the wrapping (#7513)\n\t\t\tul.width( \"\" ).outerWidth() + 1,\n\t\t\tthis.element.outerWidth()\n\t\t) );\n\t},\n\n\t_renderMenu: function( ul, items ) {\n\t\tvar that = this;\n\t\t$.each( items, function( index, item ) {\n\t\t\tthat._renderItemData( ul, item );\n\t\t});\n\t},\n\n\t_renderItemData: function( ul, item ) {\n\t\treturn this._renderItem( ul, item ).data( \"ui-autocomplete-item\", item );\n\t},\n\n\t_renderItem: function( ul, item ) {\n\t\treturn $( \"<li>\" )\n\t\t\t.append( $( \"<a>\" ).text( item.label ) )\n\t\t\t.appendTo( ul );\n\t},\n\n\t_move: function( direction, event ) {\n\t\tif ( !this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.search( null, event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.menu.isFirstItem() && /^previous/.test( direction ) ||\n\t\t\t\tthis.menu.isLastItem() && /^next/.test( direction ) ) {\n\t\t\tthis._value( this.term );\n\t\t\tthis.menu.blur();\n\t\t\treturn;\n\t\t}\n\t\tthis.menu[ direction ]( event );\n\t},\n\n\twidget: function() {\n\t\treturn this.menu.element;\n\t},\n\n\t_value: function( value ) {\n\t\treturn this.valueMethod.apply( this.element, arguments );\n\t},\n\n\t_keyEvent: function( keyEvent, event ) {\n\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis._move( keyEvent, event );\n\n\t\t\t// prevents moving cursor to beginning/end of the text field in some browsers\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n});\n\n$.extend( $.ui.autocomplete, {\n\tescapeRegex: function( value ) {\n\t\treturn value.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\");\n\t},\n\tfilter: function(array, term) {\n\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), \"i\" );\n\t\treturn $.grep( array, function(value) {\n\t\t\treturn matcher.test( value.label || value.value || value );\n\t\t});\n\t}\n});\n\n\n// live region extension, adding a `messages` option\n// NOTE: This is an experimental API. We are still investigating\n// a full solution for string manipulation and internationalization.\n$.widget( \"ui.autocomplete\", $.ui.autocomplete, {\n\toptions: {\n\t\tmessages: {\n\t\t\tnoResults: \"No search results.\",\n\t\t\tresults: function(amount) {\n\t\t\t\treturn amount + ( amount > 1 ? \" results are\" : \" result is\" ) +\n\t\t\t\t\t\" available, use up and down arrow keys to navigate.\";\n\t\t\t}\n\t\t}\n\t},\n\n\t__response: function( content ) {\n\t\tvar message;\n\t\tthis._superApply( arguments );\n\t\tif ( this.options.disabled || this.cancelSearch) {\n\t\t\treturn;\n\t\t}\n\t\tif ( content && content.length ) {\n\t\t\tmessage = this.options.messages.results( content.length );\n\t\t} else {\n\t\t\tmessage = this.options.messages.noResults;\n\t\t}\n\t\tthis.liveRegion.text( message );\n\t}\n});\n\n\n}( jQuery ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.button.js",
    "content": "/*!\n * jQuery UI Button @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Button\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\nvar lastActive, startXPos, startYPos, clickDragged,\n\tbaseClasses = \"ui-button ui-widget ui-state-default ui-corner-all\",\n\tstateClasses = \"ui-state-hover ui-state-active \",\n\ttypeClasses = \"ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only\",\n\tformResetHandler = function() {\n\t\tvar buttons = $( this ).find( \":ui-button\" );\n\t\tsetTimeout(function() {\n\t\t\tbuttons.button( \"refresh\" );\n\t\t}, 1 );\n\t},\n\tradioGroup = function( radio ) {\n\t\tvar name = radio.name,\n\t\t\tform = radio.form,\n\t\t\tradios = $( [] );\n\t\tif ( name ) {\n\t\t\tif ( form ) {\n\t\t\t\tradios = $( form ).find( \"[name='\" + name + \"']\" );\n\t\t\t} else {\n\t\t\t\tradios = $( \"[name='\" + name + \"']\", radio.ownerDocument )\n\t\t\t\t\t.filter(function() {\n\t\t\t\t\t\treturn !this.form;\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn radios;\n\t};\n\n$.widget( \"ui.button\", {\n\tversion: \"@VERSION\",\n\tdefaultElement: \"<button>\",\n\toptions: {\n\t\tdisabled: null,\n\t\ttext: true,\n\t\tlabel: null,\n\t\ticons: {\n\t\t\tprimary: null,\n\t\t\tsecondary: null\n\t\t}\n\t},\n\t_create: function() {\n\t\tthis.element.closest( \"form\" )\n\t\t\t.unbind( \"reset.button\" )\n\t\t\t.bind( \"reset.button\", formResetHandler );\n\n\t\tif ( typeof this.options.disabled !== \"boolean\" ) {\n\t\t\tthis.options.disabled = !!this.element.prop( \"disabled\" );\n\t\t} else {\n\t\t\tthis.element.prop( \"disabled\", this.options.disabled );\n\t\t}\n\n\t\tthis._determineButtonType();\n\t\tthis.hasTitle = !!this.buttonElement.attr( \"title\" );\n\n\t\tvar that = this,\n\t\t\toptions = this.options,\n\t\t\ttoggleButton = this.type === \"checkbox\" || this.type === \"radio\",\n\t\t\thoverClass = \"ui-state-hover\" + ( !toggleButton ? \" ui-state-active\" : \"\" ),\n\t\t\tfocusClass = \"ui-state-focus\";\n\n\t\tif ( options.label === null ) {\n\t\t\toptions.label = (this.type === \"input\" ? this.buttonElement.val() : this.buttonElement.html());\n\t\t}\n\n\t\tthis.buttonElement\n\t\t\t.addClass( baseClasses )\n\t\t\t.attr( \"role\", \"button\" )\n\t\t\t.bind( \"mouseenter.button\", function() {\n\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t$( this ).addClass( \"ui-state-hover\" );\n\t\t\t\tif ( this === lastActive ) {\n\t\t\t\t\t$( this ).addClass( \"ui-state-active\" );\n\t\t\t\t}\n\t\t\t})\n\t\t\t.bind( \"mouseleave.button\", function() {\n\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t$( this ).removeClass( hoverClass );\n\t\t\t})\n\t\t\t.bind( \"click.button\", function( event ) {\n\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.element\n\t\t\t.bind( \"focus.button\", function() {\n\t\t\t\t// no need to check disabled, focus won't be triggered anyway\n\t\t\t\tthat.buttonElement.addClass( focusClass );\n\t\t\t})\n\t\t\t.bind( \"blur.button\", function() {\n\t\t\t\tthat.buttonElement.removeClass( focusClass );\n\t\t\t});\n\n\t\tif ( toggleButton ) {\n\t\t\tthis.element.bind( \"change.button\", function() {\n\t\t\t\tif ( clickDragged ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthat.refresh();\n\t\t\t});\n\t\t\t// if mouse moves between mousedown and mouseup (drag) set clickDragged flag\n\t\t\t// prevents issue where button state changes but checkbox/radio checked state\n\t\t\t// does not in Firefox (see ticket #6970)\n\t\t\tthis.buttonElement\n\t\t\t\t.bind( \"mousedown.button\", function( event ) {\n\t\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tclickDragged = false;\n\t\t\t\t\tstartXPos = event.pageX;\n\t\t\t\t\tstartYPos = event.pageY;\n\t\t\t\t})\n\t\t\t\t.bind( \"mouseup.button\", function( event ) {\n\t\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ( startXPos !== event.pageX || startYPos !== event.pageY ) {\n\t\t\t\t\t\tclickDragged = true;\n\t\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif ( this.type === \"checkbox\" ) {\n\t\t\tthis.buttonElement.bind( \"click.button\", function() {\n\t\t\t\tif ( options.disabled || clickDragged ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t$( this ).toggleClass( \"ui-state-active\" );\n\t\t\t\tthat.buttonElement.attr( \"aria-pressed\", that.element[0].checked );\n\t\t\t});\n\t\t} else if ( this.type === \"radio\" ) {\n\t\t\tthis.buttonElement.bind( \"click.button\", function() {\n\t\t\t\tif ( options.disabled || clickDragged ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t$( this ).addClass( \"ui-state-active\" );\n\t\t\t\tthat.buttonElement.attr( \"aria-pressed\", \"true\" );\n\n\t\t\t\tvar radio = that.element[ 0 ];\n\t\t\t\tradioGroup( radio )\n\t\t\t\t\t.not( radio )\n\t\t\t\t\t.map(function() {\n\t\t\t\t\t\treturn $( this ).button( \"widget\" )[ 0 ];\n\t\t\t\t\t})\n\t\t\t\t\t.removeClass( \"ui-state-active\" )\n\t\t\t\t\t.attr( \"aria-pressed\", \"false\" );\n\t\t\t});\n\t\t} else {\n\t\t\tthis.buttonElement\n\t\t\t\t.bind( \"mousedown.button\", function() {\n\t\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t$( this ).addClass( \"ui-state-active\" );\n\t\t\t\t\tlastActive = this;\n\t\t\t\t\tthat.document.one( \"mouseup\", function() {\n\t\t\t\t\t\tlastActive = null;\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.bind( \"mouseup.button\", function() {\n\t\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t$( this ).removeClass( \"ui-state-active\" );\n\t\t\t\t})\n\t\t\t\t.bind( \"keydown.button\", function(event) {\n\t\t\t\t\tif ( options.disabled ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {\n\t\t\t\t\t\t$( this ).addClass( \"ui-state-active\" );\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( \"keyup.button\", function() {\n\t\t\t\t\t$( this ).removeClass( \"ui-state-active\" );\n\t\t\t\t});\n\n\t\t\tif ( this.buttonElement.is(\"a\") ) {\n\t\t\t\tthis.buttonElement.keyup(function(event) {\n\t\t\t\t\tif ( event.keyCode === $.ui.keyCode.SPACE ) {\n\t\t\t\t\t\t// TODO pass through original event correctly (just as 2nd argument doesn't work)\n\t\t\t\t\t\t$( this ).click();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// TODO: pull out $.Widget's handling for the disabled option into\n\t\t// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can\n\t\t// be overridden by individual plugins\n\t\tthis._setOption( \"disabled\", options.disabled );\n\t\tthis._resetButton();\n\t},\n\n\t_determineButtonType: function() {\n\t\tvar ancestor, labelSelector, checked;\n\n\t\tif ( this.element.is(\"[type=checkbox]\") ) {\n\t\t\tthis.type = \"checkbox\";\n\t\t} else if ( this.element.is(\"[type=radio]\") ) {\n\t\t\tthis.type = \"radio\";\n\t\t} else if ( this.element.is(\"input\") ) {\n\t\t\tthis.type = \"input\";\n\t\t} else {\n\t\t\tthis.type = \"button\";\n\t\t}\n\n\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t// we don't search against the document in case the element\n\t\t\t// is disconnected from the DOM\n\t\t\tancestor = this.element.parents().last();\n\t\t\tlabelSelector = \"label[for='\" + this.element.attr(\"id\") + \"']\";\n\t\t\tthis.buttonElement = ancestor.find( labelSelector );\n\t\t\tif ( !this.buttonElement.length ) {\n\t\t\t\tancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();\n\t\t\t\tthis.buttonElement = ancestor.filter( labelSelector );\n\t\t\t\tif ( !this.buttonElement.length ) {\n\t\t\t\t\tthis.buttonElement = ancestor.find( labelSelector );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.element.addClass( \"ui-helper-hidden-accessible\" );\n\n\t\t\tchecked = this.element.is( \":checked\" );\n\t\t\tif ( checked ) {\n\t\t\t\tthis.buttonElement.addClass( \"ui-state-active\" );\n\t\t\t}\n\t\t\tthis.buttonElement.prop( \"aria-pressed\", checked );\n\t\t} else {\n\t\t\tthis.buttonElement = this.element;\n\t\t}\n\t},\n\n\twidget: function() {\n\t\treturn this.buttonElement;\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass( \"ui-helper-hidden-accessible\" );\n\t\tthis.buttonElement\n\t\t\t.removeClass( baseClasses + \" \" + stateClasses + \" \" + typeClasses )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-pressed\" )\n\t\t\t.html( this.buttonElement.find(\".ui-button-text\").html() );\n\n\t\tif ( !this.hasTitle ) {\n\t\t\tthis.buttonElement.removeAttr( \"title\" );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"disabled\" ) {\n\t\t\tif ( value ) {\n\t\t\t\tthis.element.prop( \"disabled\", true );\n\t\t\t} else {\n\t\t\t\tthis.element.prop( \"disabled\", false );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tthis._resetButton();\n\t},\n\n\trefresh: function() {\n\t\tvar isDisabled = this.element.is( \":disabled\" );\n\t\tif ( isDisabled !== this.options.disabled ) {\n\t\t\tthis._setOption( \"disabled\", isDisabled );\n\t\t}\n\t\tif ( this.type === \"radio\" ) {\n\t\t\tradioGroup( this.element[0] ).each(function() {\n\t\t\t\tif ( $( this ).is( \":checked\" ) ) {\n\t\t\t\t\t$( this ).button( \"widget\" )\n\t\t\t\t\t\t.addClass( \"ui-state-active\" )\n\t\t\t\t\t\t.attr( \"aria-pressed\", \"true\" );\n\t\t\t\t} else {\n\t\t\t\t\t$( this ).button( \"widget\" )\n\t\t\t\t\t\t.removeClass( \"ui-state-active\" )\n\t\t\t\t\t\t.attr( \"aria-pressed\", \"false\" );\n\t\t\t\t}\n\t\t\t});\n\t\t} else if ( this.type === \"checkbox\" ) {\n\t\t\tif ( this.element.is( \":checked\" ) ) {\n\t\t\t\tthis.buttonElement\n\t\t\t\t\t.addClass( \"ui-state-active\" )\n\t\t\t\t\t.attr( \"aria-pressed\", \"true\" );\n\t\t\t} else {\n\t\t\t\tthis.buttonElement\n\t\t\t\t\t.removeClass( \"ui-state-active\" )\n\t\t\t\t\t.attr( \"aria-pressed\", \"false\" );\n\t\t\t}\n\t\t}\n\t},\n\n\t_resetButton: function() {\n\t\tif ( this.type === \"input\" ) {\n\t\t\tif ( this.options.label ) {\n\t\t\t\tthis.element.val( this.options.label );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tvar buttonElement = this.buttonElement.removeClass( typeClasses ),\n\t\t\tbuttonText = $( \"<span></span>\", this.document[0] )\n\t\t\t\t.addClass( \"ui-button-text\" )\n\t\t\t\t.html( this.options.label )\n\t\t\t\t.appendTo( buttonElement.empty() )\n\t\t\t\t.text(),\n\t\t\ticons = this.options.icons,\n\t\t\tmultipleIcons = icons.primary && icons.secondary,\n\t\t\tbuttonClasses = [];\n\n\t\tif ( icons.primary || icons.secondary ) {\n\t\t\tif ( this.options.text ) {\n\t\t\t\tbuttonClasses.push( \"ui-button-text-icon\" + ( multipleIcons ? \"s\" : ( icons.primary ? \"-primary\" : \"-secondary\" ) ) );\n\t\t\t}\n\n\t\t\tif ( icons.primary ) {\n\t\t\t\tbuttonElement.prepend( \"<span class='ui-button-icon-primary ui-icon \" + icons.primary + \"'></span>\" );\n\t\t\t}\n\n\t\t\tif ( icons.secondary ) {\n\t\t\t\tbuttonElement.append( \"<span class='ui-button-icon-secondary ui-icon \" + icons.secondary + \"'></span>\" );\n\t\t\t}\n\n\t\t\tif ( !this.options.text ) {\n\t\t\t\tbuttonClasses.push( multipleIcons ? \"ui-button-icons-only\" : \"ui-button-icon-only\" );\n\n\t\t\t\tif ( !this.hasTitle ) {\n\t\t\t\t\tbuttonElement.attr( \"title\", buttonText );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tbuttonClasses.push( \"ui-button-text-only\" );\n\t\t}\n\t\tbuttonElement.addClass( buttonClasses.join( \" \" ) );\n\t}\n});\n\n$.widget( \"ui.buttonset\", {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\titems: \"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)\"\n\t},\n\n\t_create: function() {\n\t\tthis.element.addClass( \"ui-buttonset\" );\n\t},\n\n\t_init: function() {\n\t\tthis.refresh();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.buttons.button( \"option\", key, value );\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\trefresh: function() {\n\t\tvar rtl = this.element.css( \"direction\" ) === \"rtl\";\n\n\t\tthis.buttons = this.element.find( this.options.items )\n\t\t\t.filter( \":ui-button\" )\n\t\t\t\t.button( \"refresh\" )\n\t\t\t.end()\n\t\t\t.not( \":ui-button\" )\n\t\t\t\t.button()\n\t\t\t.end()\n\t\t\t.map(function() {\n\t\t\t\treturn $( this ).button( \"widget\" )[ 0 ];\n\t\t\t})\n\t\t\t\t.removeClass( \"ui-corner-all ui-corner-left ui-corner-right\" )\n\t\t\t\t.filter( \":first\" )\n\t\t\t\t\t.addClass( rtl ? \"ui-corner-right\" : \"ui-corner-left\" )\n\t\t\t\t.end()\n\t\t\t\t.filter( \":last\" )\n\t\t\t\t\t.addClass( rtl ? \"ui-corner-left\" : \"ui-corner-right\" )\n\t\t\t\t.end()\n\t\t\t.end();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element.removeClass( \"ui-buttonset\" );\n\t\tthis.buttons\n\t\t\t.map(function() {\n\t\t\t\treturn $( this ).button( \"widget\" )[ 0 ];\n\t\t\t})\n\t\t\t\t.removeClass( \"ui-corner-left ui-corner-right\" )\n\t\t\t.end()\n\t\t\t.button( \"destroy\" );\n\t}\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.core.js",
    "content": "/*!\n * jQuery UI @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI\n */\n(function( $, undefined ) {\n\nvar uuid = 0,\n\truniqueId = /^ui-id-\\d+$/;\n\n// prevent duplicate loading\n// this is only a problem because we proxy existing functions\n// and we don't want to double proxy them\n$.ui = $.ui || {};\nif ( $.ui.version ) {\n\treturn;\n}\n\n$.extend( $.ui, {\n\tversion: \"@VERSION\",\n\n\tkeyCode: {\n\t\tBACKSPACE: 8,\n\t\tCOMMA: 188,\n\t\tDELETE: 46,\n\t\tDOWN: 40,\n\t\tEND: 35,\n\t\tENTER: 13,\n\t\tESCAPE: 27,\n\t\tHOME: 36,\n\t\tLEFT: 37,\n\t\tNUMPAD_ADD: 107,\n\t\tNUMPAD_DECIMAL: 110,\n\t\tNUMPAD_DIVIDE: 111,\n\t\tNUMPAD_ENTER: 108,\n\t\tNUMPAD_MULTIPLY: 106,\n\t\tNUMPAD_SUBTRACT: 109,\n\t\tPAGE_DOWN: 34,\n\t\tPAGE_UP: 33,\n\t\tPERIOD: 190,\n\t\tRIGHT: 39,\n\t\tSPACE: 32,\n\t\tTAB: 9,\n\t\tUP: 38\n\t}\n});\n\n// plugins\n$.fn.extend({\n\t_focus: $.fn.focus,\n\tfocus: function( delay, fn ) {\n\t\treturn typeof delay === \"number\" ?\n\t\t\tthis.each(function() {\n\t\t\t\tvar elem = this;\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t$( elem ).focus();\n\t\t\t\t\tif ( fn ) {\n\t\t\t\t\t\tfn.call( elem );\n\t\t\t\t\t}\n\t\t\t\t}, delay );\n\t\t\t}) :\n\t\t\tthis._focus.apply( this, arguments );\n\t},\n\n\tscrollParent: function() {\n\t\tvar scrollParent;\n\t\tif (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));\n\t\t\t}).eq(0);\n\t\t} else {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));\n\t\t\t}).eq(0);\n\t\t}\n\n\t\treturn (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;\n\t},\n\n\tzIndex: function( zIndex ) {\n\t\tif ( zIndex !== undefined ) {\n\t\t\treturn this.css( \"zIndex\", zIndex );\n\t\t}\n\n\t\tif ( this.length ) {\n\t\t\tvar elem = $( this[ 0 ] ), position, value;\n\t\t\twhile ( elem.length && elem[ 0 ] !== document ) {\n\t\t\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t\t\t// This makes behavior of this function consistent across browsers\n\t\t\t\t// WebKit always returns auto if the element is positioned\n\t\t\t\tposition = elem.css( \"position\" );\n\t\t\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\t\t\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t\t\t// other browsers return a string\n\t\t\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telem = elem.parent();\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t},\n\n\tuniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( !this.id ) {\n\t\t\t\tthis.id = \"ui-id-\" + (++uuid);\n\t\t\t}\n\t\t});\n\t},\n\n\tremoveUniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( runiqueId.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t});\n\t},\n\n\tdisableSelection: function() {\n\t\treturn this.bind( ( $.support.selectstart ? \"selectstart\" : \"mousedown\" ) +\n\t\t\t\".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t});\n\t},\n\n\tenableSelection: function() {\n\t\treturn this.unbind( \".ui-disableSelection\" );\n\t}\n});\n\n// support: jQuery <1.8\nif ( !$( \"<a>\" ).outerWidth( 1 ).jquery ) {\n\t$.each( [ \"Width\", \"Height\" ], function( i, name ) {\n\t\tvar side = name === \"Width\" ? [ \"Left\", \"Right\" ] : [ \"Top\", \"Bottom\" ],\n\t\t\ttype = name.toLowerCase(),\n\t\t\torig = {\n\t\t\t\tinnerWidth: $.fn.innerWidth,\n\t\t\t\tinnerHeight: $.fn.innerHeight,\n\t\t\t\touterWidth: $.fn.outerWidth,\n\t\t\t\touterHeight: $.fn.outerHeight\n\t\t\t};\n\n\t\tfunction reduce( elem, size, border, margin ) {\n\t\t\t$.each( side, function() {\n\t\t\t\tsize -= parseFloat( $.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\tif ( border ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( margin ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"margin\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn size;\n\t\t}\n\n\t\t$.fn[ \"inner\" + name ] = function( size ) {\n\t\t\tif ( size === undefined ) {\n\t\t\t\treturn orig[ \"inner\" + name ].call( this );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this ).css( type, reduce( this, size ) + \"px\" );\n\t\t\t});\n\t\t};\n\n\t\t$.fn[ \"outer\" + name] = function( size, margin ) {\n\t\t\tif ( typeof size !== \"number\" ) {\n\t\t\t\treturn orig[ \"outer\" + name ].call( this, size );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this).css( type, reduce( this, size, true, margin ) + \"px\" );\n\t\t\t});\n\t\t};\n\t});\n}\n\n// selectors\nfunction focusable( element, isTabIndexNotNaN ) {\n\tvar map, mapName, img,\n\t\tnodeName = element.nodeName.toLowerCase();\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap=#\" + mapName + \"]\" )[0];\n\t\treturn !!img && visible( img );\n\t}\n\treturn ( /input|select|textarea|button|object/.test( nodeName ) ?\n\t\t!element.disabled :\n\t\t\"a\" === nodeName ?\n\t\t\telement.href || isTabIndexNotNaN :\n\t\t\tisTabIndexNotNaN) &&\n\t\t// the element and all of its ancestors must be visible\n\t\tvisible( element );\n}\n\nfunction visible( element ) {\n\treturn !$( element ).parents().andSelf().filter(function() {\n\t\treturn $.css( this, \"visibility\" ) === \"hidden\" ||\n\t\t\t$.expr.filters.hidden( this );\n\t}).length;\n}\n\n$.extend( $.expr[ \":\" ], {\n\tdata: function( elem, i, match ) {\n\t\treturn !!$.data( elem, match[ 3 ] );\n\t},\n\n\tfocusable: function( element ) {\n\t\treturn focusable( element, !isNaN( $.attr( element, \"tabindex\" ) ) );\n\t},\n\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\tisTabIndexNaN = isNaN( tabIndex );\n\t\treturn ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );\n\t}\n});\n\n// support\n$(function() {\n\tvar body = document.body,\n\t\tdiv = body.appendChild( div = document.createElement( \"div\" ) );\n\n\t// access offsetHeight before setting the style to prevent a layout bug\n\t// in IE 9 which causes the element to continue to take up space even\n\t// after it is removed from the DOM (#8026)\n\tdiv.offsetHeight;\n\n\t$.extend( div.style, {\n\t\tminHeight: \"100px\",\n\t\theight: \"auto\",\n\t\tpadding: 0,\n\t\tborderWidth: 0\n\t});\n\n\t$.support.minHeight = div.offsetHeight === 100;\n\t$.support.selectstart = \"onselectstart\" in div;\n\n\t// set display to none to avoid a layout bug in IE\n\t// http://dev.jquery.com/ticket/4014\n\tbody.removeChild( div ).style.display = \"none\";\n});\n\n\n\n\n\n// deprecated\n$.extend( $.ui, {\n\t// $.ui.plugin is deprecated.  Use the proxy pattern instead.\n\tplugin: {\n\t\tadd: function( module, option, set ) {\n\t\t\tvar i,\n\t\t\t\tproto = $.ui[ module ].prototype;\n\t\t\tfor ( i in set ) {\n\t\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t\t}\n\t\t},\n\t\tcall: function( instance, name, args ) {\n\t\t\tvar i,\n\t\t\t\tset = instance.plugins[ name ];\n\t\t\tif ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\n\t\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\n\tcontains: $.contains,\n\t\n\t// only used by resizable\n\thasScroll: function( el, a ) {\n\t\n\t\t//If overflow is hidden, the element might have extra content, but the user wants to hide it\n\t\tif ( $( el ).css( \"overflow\" ) === \"hidden\") {\n\t\t\treturn false;\n\t\t}\n\t\n\t\tvar scroll = ( a && a === \"left\" ) ? \"scrollLeft\" : \"scrollTop\",\n\t\t\thas = false;\n\t\n\t\tif ( el[ scroll ] > 0 ) {\n\t\t\treturn true;\n\t\t}\n\t\n\t\t// TODO: determine which cases actually cause this to happen\n\t\t// if the element doesn't have the scroll set, see if it's possible to\n\t\t// set the scroll\n\t\tel[ scroll ] = 1;\n\t\thas = ( el[ scroll ] > 0 );\n\t\tel[ scroll ] = 0;\n\t\treturn has;\n\t},\n\t\n\t// these are odd functions, fix the API or move into individual plugins\n\tisOverAxis: function( x, reference, size ) {\n\t\t//Determines when x coordinate is over \"b\" element axis\n\t\treturn ( x > reference ) && ( x < ( reference + size ) );\n\t},\n\tisOver: function( y, x, top, left, height, width ) {\n\t\t//Determines when x, y coordinates is over \"b\" element\n\t\treturn $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );\n\t}\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.datepicker.js",
    "content": "/*!\n * jQuery UI Datepicker @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Datepicker\n *\n * Depends:\n *\tjquery.ui.core.js\n */\n(function( $, undefined ) {\n\n$.extend($.ui, { datepicker: { version: \"@VERSION\" } });\n\nvar PROP_NAME = 'datepicker';\nvar dpuuid = new Date().getTime();\nvar instActive;\n\n/* Date picker manager.\n   Use the singleton instance of this class, $.datepicker, to interact with the date picker.\n   Settings for (groups of) date pickers are maintained in an instance object,\n   allowing multiple different settings on the same page. */\n\nfunction Datepicker() {\n\tthis.debug = false; // Change this to true to start debugging\n\tthis._curInst = null; // The current instance in use\n\tthis._keyEvent = false; // If the last event was a key event\n\tthis._disabledInputs = []; // List of date picker inputs that have been disabled\n\tthis._datepickerShowing = false; // True if the popup picker is showing , false if not\n\tthis._inDialog = false; // True if showing within a \"dialog\", false if not\n\tthis._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division\n\tthis._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class\n\tthis._appendClass = 'ui-datepicker-append'; // The name of the append marker class\n\tthis._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class\n\tthis._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class\n\tthis._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class\n\tthis._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class\n\tthis._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class\n\tthis._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class\n\tthis.regional = []; // Available regional settings, indexed by language code\n\tthis.regional[''] = { // Default regional settings\n\t\tcloseText: 'Done', // Display text for close link\n\t\tprevText: 'Prev', // Display text for previous month link\n\t\tnextText: 'Next', // Display text for next month link\n\t\tcurrentText: 'Today', // Display text for current month link\n\t\tmonthNames: ['January','February','March','April','May','June',\n\t\t\t'July','August','September','October','November','December'], // Names of months for drop-down and formatting\n\t\tmonthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting\n\t\tdayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting\n\t\tdayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting\n\t\tdayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday\n\t\tweekHeader: 'Wk', // Column header for week of the year\n\t\tdateFormat: 'mm/dd/yy', // See format options on parseDate\n\t\tfirstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...\n\t\tisRTL: false, // True if right-to-left language, false if left-to-right\n\t\tshowMonthAfterYear: false, // True if the year select precedes month, false for month then year\n\t\tyearSuffix: '' // Additional text to append to the year in the month headers\n\t};\n\tthis._defaults = { // Global defaults for all the date picker instances\n\t\tshowOn: 'focus', // 'focus' for popup on focus,\n\t\t\t// 'button' for trigger button, or 'both' for either\n\t\tshowAnim: 'fadeIn', // Name of jQuery animation for popup\n\t\tshowOptions: {}, // Options for enhanced animations\n\t\tdefaultDate: null, // Used when field is blank: actual date,\n\t\t\t// +/-number for offset from today, null for today\n\t\tappendText: '', // Display text following the input box, e.g. showing the format\n\t\tbuttonText: '...', // Text for trigger button\n\t\tbuttonImage: '', // URL for trigger button image\n\t\tbuttonImageOnly: false, // True if the image appears alone, false if it appears on a button\n\t\thideIfNoPrevNext: false, // True to hide next/previous month links\n\t\t\t// if not applicable, false to just disable them\n\t\tnavigationAsDateFormat: false, // True if date formatting applied to prev/today/next links\n\t\tgotoCurrent: false, // True if today link goes back to current selection instead\n\t\tchangeMonth: false, // True if month can be selected directly, false if only prev/next\n\t\tchangeYear: false, // True if year can be selected directly, false if only prev/next\n\t\tyearRange: 'c-10:c+10', // Range of years to display in drop-down,\n\t\t\t// either relative to today's year (-nn:+nn), relative to currently displayed year\n\t\t\t// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)\n\t\tshowOtherMonths: false, // True to show dates in other months, false to leave blank\n\t\tselectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable\n\t\tshowWeek: false, // True to show week of the year, false to not show it\n\t\tcalculateWeek: this.iso8601Week, // How to calculate the week of the year,\n\t\t\t// takes a Date and returns the number of the week for it\n\t\tshortYearCutoff: '+10', // Short year values < this are in the current century,\n\t\t\t// > this are in the previous century,\n\t\t\t// string value starting with '+' for current year + value\n\t\tminDate: null, // The earliest selectable date, or null for no limit\n\t\tmaxDate: null, // The latest selectable date, or null for no limit\n\t\tduration: 'fast', // Duration of display/closure\n\t\tbeforeShowDay: null, // Function that takes a date and returns an array with\n\t\t\t// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',\n\t\t\t// [2] = cell title (optional), e.g. $.datepicker.noWeekends\n\t\tbeforeShow: null, // Function that takes an input field and\n\t\t\t// returns a set of custom settings for the date picker\n\t\tonSelect: null, // Define a callback function when a date is selected\n\t\tonChangeMonthYear: null, // Define a callback function when the month or year is changed\n\t\tonClose: null, // Define a callback function when the datepicker is closed\n\t\tnumberOfMonths: 1, // Number of months to show at a time\n\t\tshowCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)\n\t\tstepMonths: 1, // Number of months to step back/forward\n\t\tstepBigMonths: 12, // Number of months to step back/forward for the big links\n\t\taltField: '', // Selector for an alternate field to store selected dates into\n\t\taltFormat: '', // The date format to use for the alternate field\n\t\tconstrainInput: true, // The input is constrained by the current date format\n\t\tshowButtonPanel: false, // True to show button panel, false to not show it\n\t\tautoSize: false, // True to size the input for the date format, false to leave as is\n\t\tdisabled: false // The initial disabled state\n\t};\n\t$.extend(this._defaults, this.regional['']);\n\tthis.dpDiv = bindHover($('<div id=\"' + this._mainDivId + '\" class=\"ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all\"></div>'));\n}\n\n$.extend(Datepicker.prototype, {\n\t/* Class name added to elements to indicate already configured with a date picker. */\n\tmarkerClassName: 'hasDatepicker',\n\t\n\t//Keep track of the maximum number of rows displayed (see #7043)\n\tmaxRows: 4,\n\n\t/* Debug logging (if enabled). */\n\tlog: function () {\n\t\tif (this.debug)\n\t\t\tconsole.log.apply('', arguments);\n\t},\n\t\n\t// TODO rename to \"widget\" when switching to widget factory\n\t_widgetDatepicker: function() {\n\t\treturn this.dpDiv;\n\t},\n\n\t/* Override the default settings for all instances of the date picker.\n\t   @param  settings  object - the new settings to use as defaults (anonymous object)\n\t   @return the manager object */\n\tsetDefaults: function(settings) {\n\t\textendRemove(this._defaults, settings || {});\n\t\treturn this;\n\t},\n\n\t/* Attach the date picker to a jQuery selection.\n\t   @param  target    element - the target input field or division or span\n\t   @param  settings  object - the new settings to use for this date picker instance (anonymous) */\n\t_attachDatepicker: function(target, settings) {\n\t\t// check for settings on the control itself - in namespace 'date:'\n\t\tvar inlineSettings = null;\n\t\tfor (var attrName in this._defaults) {\n\t\t\tvar attrValue = target.getAttribute('date:' + attrName);\n\t\t\tif (attrValue) {\n\t\t\t\tinlineSettings = inlineSettings || {};\n\t\t\t\ttry {\n\t\t\t\t\tinlineSettings[attrName] = eval(attrValue);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tinlineSettings[attrName] = attrValue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvar nodeName = target.nodeName.toLowerCase();\n\t\tvar inline = (nodeName == 'div' || nodeName == 'span');\n\t\tif (!target.id) {\n\t\t\tthis.uuid += 1;\n\t\t\ttarget.id = 'dp' + this.uuid;\n\t\t}\n\t\tvar inst = this._newInst($(target), inline);\n\t\tinst.settings = $.extend({}, settings || {}, inlineSettings || {});\n\t\tif (nodeName == 'input') {\n\t\t\tthis._connectDatepicker(target, inst);\n\t\t} else if (inline) {\n\t\t\tthis._inlineDatepicker(target, inst);\n\t\t}\n\t},\n\n\t/* Create a new instance object. */\n\t_newInst: function(target, inline) {\n\t\tvar id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\\\\\$1'); // escape jQuery meta chars\n\t\treturn {id: id, input: target, // associated target\n\t\t\tselectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection\n\t\t\tdrawMonth: 0, drawYear: 0, // month being drawn\n\t\t\tinline: inline, // is datepicker inline or not\n\t\t\tdpDiv: (!inline ? this.dpDiv : // presentation div\n\t\t\tbindHover($('<div class=\"' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all\"></div>')))};\n\t},\n\n\t/* Attach the date picker to an input field. */\n\t_connectDatepicker: function(target, inst) {\n\t\tvar input = $(target);\n\t\tinst.append = $([]);\n\t\tinst.trigger = $([]);\n\t\tif (input.hasClass(this.markerClassName))\n\t\t\treturn;\n\t\tthis._attachments(input, inst);\n\t\tinput.addClass(this.markerClassName).keydown(this._doKeyDown).\n\t\t\tkeypress(this._doKeyPress).keyup(this._doKeyUp).\n\t\t\tbind(\"setData.datepicker\", function(event, key, value) {\n\t\t\t\tinst.settings[key] = value;\n\t\t\t}).bind(\"getData.datepicker\", function(event, key) {\n\t\t\t\treturn this._get(inst, key);\n\t\t\t});\n\t\tthis._autoSize(inst);\n\t\t$.data(target, PROP_NAME, inst);\n\t\t//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)\n\t\tif( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\t},\n\n\t/* Make attachments based on settings. */\n\t_attachments: function(input, inst) {\n\t\tvar appendText = this._get(inst, 'appendText');\n\t\tvar isRTL = this._get(inst, 'isRTL');\n\t\tif (inst.append)\n\t\t\tinst.append.remove();\n\t\tif (appendText) {\n\t\t\tinst.append = $('<span class=\"' + this._appendClass + '\">' + appendText + '</span>');\n\t\t\tinput[isRTL ? 'before' : 'after'](inst.append);\n\t\t}\n\t\tinput.unbind('focus', this._showDatepicker);\n\t\tif (inst.trigger)\n\t\t\tinst.trigger.remove();\n\t\tvar showOn = this._get(inst, 'showOn');\n\t\tif (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field\n\t\t\tinput.focus(this._showDatepicker);\n\t\tif (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked\n\t\t\tvar buttonText = this._get(inst, 'buttonText');\n\t\t\tvar buttonImage = this._get(inst, 'buttonImage');\n\t\t\tinst.trigger = $(this._get(inst, 'buttonImageOnly') ?\n\t\t\t\t$('<img/>').addClass(this._triggerClass).\n\t\t\t\t\tattr({ src: buttonImage, alt: buttonText, title: buttonText }) :\n\t\t\t\t$('<button type=\"button\"></button>').addClass(this._triggerClass).\n\t\t\t\t\thtml(buttonImage == '' ? buttonText : $('<img/>').attr(\n\t\t\t\t\t{ src:buttonImage, alt:buttonText, title:buttonText })));\n\t\t\tinput[isRTL ? 'before' : 'after'](inst.trigger);\n\t\t\tinst.trigger.click(function() {\n\t\t\t\tif ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\telse if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {\n\t\t\t\t\t$.datepicker._hideDatepicker(); \n\t\t\t\t\t$.datepicker._showDatepicker(input[0]);\n\t\t\t\t} else\n\t\t\t\t\t$.datepicker._showDatepicker(input[0]);\n\t\t\t\treturn false;\n\t\t\t});\n\t\t}\n\t},\n\n\t/* Apply the maximum length for the date format. */\n\t_autoSize: function(inst) {\n\t\tif (this._get(inst, 'autoSize') && !inst.inline) {\n\t\t\tvar date = new Date(2009, 12 - 1, 20); // Ensure double digits\n\t\t\tvar dateFormat = this._get(inst, 'dateFormat');\n\t\t\tif (dateFormat.match(/[DM]/)) {\n\t\t\t\tvar findMax = function(names) {\n\t\t\t\t\tvar max = 0;\n\t\t\t\t\tvar maxI = 0;\n\t\t\t\t\tfor (var i = 0; i < names.length; i++) {\n\t\t\t\t\t\tif (names[i].length > max) {\n\t\t\t\t\t\t\tmax = names[i].length;\n\t\t\t\t\t\t\tmaxI = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn maxI;\n\t\t\t\t};\n\t\t\t\tdate.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?\n\t\t\t\t\t'monthNames' : 'monthNamesShort'))));\n\t\t\t\tdate.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?\n\t\t\t\t\t'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());\n\t\t\t}\n\t\t\tinst.input.attr('size', this._formatDate(inst, date).length);\n\t\t}\n\t},\n\n\t/* Attach an inline date picker to a div. */\n\t_inlineDatepicker: function(target, inst) {\n\t\tvar divSpan = $(target);\n\t\tif (divSpan.hasClass(this.markerClassName))\n\t\t\treturn;\n\t\tdivSpan.addClass(this.markerClassName).append(inst.dpDiv).\n\t\t\tbind(\"setData.datepicker\", function(event, key, value){\n\t\t\t\tinst.settings[key] = value;\n\t\t\t}).bind(\"getData.datepicker\", function(event, key){\n\t\t\t\treturn this._get(inst, key);\n\t\t\t});\n\t\t$.data(target, PROP_NAME, inst);\n\t\tthis._setDate(inst, this._getDefaultDate(inst), true);\n\t\tthis._updateDatepicker(inst);\n\t\tthis._updateAlternate(inst);\n\t\t//If disabled option is true, disable the datepicker before showing it (see ticket #5665)\n\t\tif( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\t\t// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements\n\t\t// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height\n\t\tinst.dpDiv.css( \"display\", \"block\" );\n\t},\n\n\t/* Pop-up the date picker in a \"dialog\" box.\n\t   @param  input     element - ignored\n\t   @param  date      string or Date - the initial date to display\n\t   @param  onSelect  function - the function to call when a date is selected\n\t   @param  settings  object - update the dialog date picker instance's settings (anonymous object)\n\t   @param  pos       int[2] - coordinates for the dialog's position within the screen or\n\t                     event - with x/y coordinates or\n\t                     leave empty for default (screen centre)\n\t   @return the manager object */\n\t_dialogDatepicker: function(input, date, onSelect, settings, pos) {\n\t\tvar inst = this._dialogInst; // internal instance\n\t\tif (!inst) {\n\t\t\tthis.uuid += 1;\n\t\t\tvar id = 'dp' + this.uuid;\n\t\t\tthis._dialogInput = $('<input type=\"text\" id=\"' + id +\n\t\t\t\t'\" style=\"position: absolute; top: -100px; width: 0px; z-index: -10;\"/>');\n\t\t\tthis._dialogInput.keydown(this._doKeyDown);\n\t\t\t$('body').append(this._dialogInput);\n\t\t\tinst = this._dialogInst = this._newInst(this._dialogInput, false);\n\t\t\tinst.settings = {};\n\t\t\t$.data(this._dialogInput[0], PROP_NAME, inst);\n\t\t}\n\t\textendRemove(inst.settings, settings || {});\n\t\tdate = (date && date.constructor == Date ? this._formatDate(inst, date) : date);\n\t\tthis._dialogInput.val(date);\n\n\t\tthis._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);\n\t\tif (!this._pos) {\n\t\t\tvar browserWidth = document.documentElement.clientWidth;\n\t\t\tvar browserHeight = document.documentElement.clientHeight;\n\t\t\tvar scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;\n\t\t\tvar scrollY = document.documentElement.scrollTop || document.body.scrollTop;\n\t\t\tthis._pos = // should use actual width/height below\n\t\t\t\t[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];\n\t\t}\n\n\t\t// move input on screen for focus, but hidden behind dialog\n\t\tthis._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');\n\t\tinst.settings.onSelect = onSelect;\n\t\tthis._inDialog = true;\n\t\tthis.dpDiv.addClass(this._dialogClass);\n\t\tthis._showDatepicker(this._dialogInput[0]);\n\t\tif ($.blockUI)\n\t\t\t$.blockUI(this.dpDiv);\n\t\t$.data(this._dialogInput[0], PROP_NAME, inst);\n\t\treturn this;\n\t},\n\n\t/* Detach a datepicker from its control.\n\t   @param  target    element - the target input field or division or span */\n\t_destroyDatepicker: function(target) {\n\t\tvar $target = $(target);\n\t\tvar inst = $.data(target, PROP_NAME);\n\t\tif (!$target.hasClass(this.markerClassName)) {\n\t\t\treturn;\n\t\t}\n\t\tvar nodeName = target.nodeName.toLowerCase();\n\t\t$.removeData(target, PROP_NAME);\n\t\tif (nodeName == 'input') {\n\t\t\tinst.append.remove();\n\t\t\tinst.trigger.remove();\n\t\t\t$target.removeClass(this.markerClassName).\n\t\t\t\tunbind('focus', this._showDatepicker).\n\t\t\t\tunbind('keydown', this._doKeyDown).\n\t\t\t\tunbind('keypress', this._doKeyPress).\n\t\t\t\tunbind('keyup', this._doKeyUp);\n\t\t} else if (nodeName == 'div' || nodeName == 'span')\n\t\t\t$target.removeClass(this.markerClassName).empty();\n\t},\n\n\t/* Enable the date picker to a jQuery selection.\n\t   @param  target    element - the target input field or division or span */\n\t_enableDatepicker: function(target) {\n\t\tvar $target = $(target);\n\t\tvar inst = $.data(target, PROP_NAME);\n\t\tif (!$target.hasClass(this.markerClassName)) {\n\t\t\treturn;\n\t\t}\n\t\tvar nodeName = target.nodeName.toLowerCase();\n\t\tif (nodeName == 'input') {\n\t\t\ttarget.disabled = false;\n\t\t\tinst.trigger.filter('button').\n\t\t\t\teach(function() { this.disabled = false; }).end().\n\t\t\t\tfilter('img').css({opacity: '1.0', cursor: ''});\n\t\t}\n\t\telse if (nodeName == 'div' || nodeName == 'span') {\n\t\t\tvar inline = $target.children('.' + this._inlineClass);\n\t\t\tinline.children().removeClass('ui-state-disabled');\n\t\t\tinline.find(\"select.ui-datepicker-month, select.ui-datepicker-year\").\n\t\t\t\tprop(\"disabled\", false);\n\t\t}\n\t\tthis._disabledInputs = $.map(this._disabledInputs,\n\t\t\tfunction(value) { return (value == target ? null : value); }); // delete entry\n\t},\n\n\t/* Disable the date picker to a jQuery selection.\n\t   @param  target    element - the target input field or division or span */\n\t_disableDatepicker: function(target) {\n\t\tvar $target = $(target);\n\t\tvar inst = $.data(target, PROP_NAME);\n\t\tif (!$target.hasClass(this.markerClassName)) {\n\t\t\treturn;\n\t\t}\n\t\tvar nodeName = target.nodeName.toLowerCase();\n\t\tif (nodeName == 'input') {\n\t\t\ttarget.disabled = true;\n\t\t\tinst.trigger.filter('button').\n\t\t\t\teach(function() { this.disabled = true; }).end().\n\t\t\t\tfilter('img').css({opacity: '0.5', cursor: 'default'});\n\t\t}\n\t\telse if (nodeName == 'div' || nodeName == 'span') {\n\t\t\tvar inline = $target.children('.' + this._inlineClass);\n\t\t\tinline.children().addClass('ui-state-disabled');\n\t\t\tinline.find(\"select.ui-datepicker-month, select.ui-datepicker-year\").\n\t\t\t\tprop(\"disabled\", true);\n\t\t}\n\t\tthis._disabledInputs = $.map(this._disabledInputs,\n\t\t\tfunction(value) { return (value == target ? null : value); }); // delete entry\n\t\tthis._disabledInputs[this._disabledInputs.length] = target;\n\t},\n\n\t/* Is the first field in a jQuery collection disabled as a datepicker?\n\t   @param  target    element - the target input field or division or span\n\t   @return boolean - true if disabled, false if enabled */\n\t_isDisabledDatepicker: function(target) {\n\t\tif (!target) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (var i = 0; i < this._disabledInputs.length; i++) {\n\t\t\tif (this._disabledInputs[i] == target)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\t/* Retrieve the instance data for the target control.\n\t   @param  target  element - the target input field or division or span\n\t   @return  object - the associated instance data\n\t   @throws  error if a jQuery problem getting data */\n\t_getInst: function(target) {\n\t\ttry {\n\t\t\treturn $.data(target, PROP_NAME);\n\t\t}\n\t\tcatch (err) {\n\t\t\tthrow 'Missing instance data for this datepicker';\n\t\t}\n\t},\n\n\t/* Update or retrieve the settings for a date picker attached to an input field or division.\n\t   @param  target  element - the target input field or division or span\n\t   @param  name    object - the new settings to update or\n\t                   string - the name of the setting to change or retrieve,\n\t                   when retrieving also 'all' for all instance settings or\n\t                   'defaults' for all global defaults\n\t   @param  value   any - the new value for the setting\n\t                   (omit if above is an object or to retrieve a value) */\n\t_optionDatepicker: function(target, name, value) {\n\t\tvar inst = this._getInst(target);\n\t\tif (arguments.length == 2 && typeof name == 'string') {\n\t\t\treturn (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :\n\t\t\t\t(inst ? (name == 'all' ? $.extend({}, inst.settings) :\n\t\t\t\tthis._get(inst, name)) : null));\n\t\t}\n\t\tvar settings = name || {};\n\t\tif (typeof name == 'string') {\n\t\t\tsettings = {};\n\t\t\tsettings[name] = value;\n\t\t}\n\t\tif (inst) {\n\t\t\tif (this._curInst == inst) {\n\t\t\t\tthis._hideDatepicker();\n\t\t\t}\n\t\t\tvar date = this._getDateDatepicker(target, true);\n\t\t\tvar minDate = this._getMinMaxDate(inst, 'min');\n\t\t\tvar maxDate = this._getMinMaxDate(inst, 'max');\n\t\t\textendRemove(inst.settings, settings);\n\t\t\t// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided\n\t\t\tif (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)\n\t\t\t\tinst.settings.minDate = this._formatDate(inst, minDate);\n\t\t\tif (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)\n\t\t\t\tinst.settings.maxDate = this._formatDate(inst, maxDate);\n\t\t\tthis._attachments($(target), inst);\n\t\t\tthis._autoSize(inst);\n\t\t\tthis._setDate(inst, date);\n\t\t\tthis._updateAlternate(inst);\n\t\t\tthis._updateDatepicker(inst);\n\t\t}\n\t},\n\n\t// change method deprecated\n\t_changeDatepicker: function(target, name, value) {\n\t\tthis._optionDatepicker(target, name, value);\n\t},\n\n\t/* Redraw the date picker attached to an input field or division.\n\t   @param  target  element - the target input field or division or span */\n\t_refreshDatepicker: function(target) {\n\t\tvar inst = this._getInst(target);\n\t\tif (inst) {\n\t\t\tthis._updateDatepicker(inst);\n\t\t}\n\t},\n\n\t/* Set the dates for a jQuery selection.\n\t   @param  target   element - the target input field or division or span\n\t   @param  date     Date - the new date */\n\t_setDateDatepicker: function(target, date) {\n\t\tvar inst = this._getInst(target);\n\t\tif (inst) {\n\t\t\tthis._setDate(inst, date);\n\t\t\tthis._updateDatepicker(inst);\n\t\t\tthis._updateAlternate(inst);\n\t\t}\n\t},\n\n\t/* Get the date(s) for the first entry in a jQuery selection.\n\t   @param  target     element - the target input field or division or span\n\t   @param  noDefault  boolean - true if no default date is to be used\n\t   @return Date - the current date */\n\t_getDateDatepicker: function(target, noDefault) {\n\t\tvar inst = this._getInst(target);\n\t\tif (inst && !inst.inline)\n\t\t\tthis._setDateFromField(inst, noDefault);\n\t\treturn (inst ? this._getDate(inst) : null);\n\t},\n\n\t/* Handle keystrokes. */\n\t_doKeyDown: function(event) {\n\t\tvar inst = $.datepicker._getInst(event.target);\n\t\tvar handled = true;\n\t\tvar isRTL = inst.dpDiv.is('.ui-datepicker-rtl');\n\t\tinst._keyEvent = true;\n\t\tif ($.datepicker._datepickerShowing)\n\t\t\tswitch (event.keyCode) {\n\t\t\t\tcase 9: $.datepicker._hideDatepicker();\n\t\t\t\t\t\thandled = false;\n\t\t\t\t\t\tbreak; // hide on tab out\n\t\t\t\tcase 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + \n\t\t\t\t\t\t\t\t\t$.datepicker._currentClass + ')', inst.dpDiv);\n\t\t\t\t\t\tif (sel[0])\n\t\t\t\t\t\t\t$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);\n\t\t\t\t\t\t\tvar onSelect = $.datepicker._get(inst, 'onSelect');\n\t\t\t\t\t\t\tif (onSelect) {\n\t\t\t\t\t\t\t\tvar dateStr = $.datepicker._formatDate(inst);\n\n\t\t\t\t\t\t\t\t// trigger custom callback\n\t\t\t\t\t\t\t\tonSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t\treturn false; // don't submit the form\n\t\t\t\t\t\tbreak; // select the value on enter\n\t\t\t\tcase 27: $.datepicker._hideDatepicker();\n\t\t\t\t\t\tbreak; // hide on escape\n\t\t\t\tcase 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?\n\t\t\t\t\t\t\t-$.datepicker._get(inst, 'stepBigMonths') :\n\t\t\t\t\t\t\t-$.datepicker._get(inst, 'stepMonths')), 'M');\n\t\t\t\t\t\tbreak; // previous month/year on page up/+ ctrl\n\t\t\t\tcase 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?\n\t\t\t\t\t\t\t+$.datepicker._get(inst, 'stepBigMonths') :\n\t\t\t\t\t\t\t+$.datepicker._get(inst, 'stepMonths')), 'M');\n\t\t\t\t\t\tbreak; // next month/year on page down/+ ctrl\n\t\t\t\tcase 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // clear on ctrl or command +end\n\t\t\t\tcase 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // current on ctrl or command +home\n\t\t\t\tcase 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\t// -1 day on ctrl or command +left\n\t\t\t\t\t\tif (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?\n\t\t\t\t\t\t\t\t\t-$.datepicker._get(inst, 'stepBigMonths') :\n\t\t\t\t\t\t\t\t\t-$.datepicker._get(inst, 'stepMonths')), 'M');\n\t\t\t\t\t\t// next month/year on alt +left on Mac\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // -1 week on ctrl or command +up\n\t\t\t\tcase 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\t// +1 day on ctrl or command +right\n\t\t\t\t\t\tif (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?\n\t\t\t\t\t\t\t\t\t+$.datepicker._get(inst, 'stepBigMonths') :\n\t\t\t\t\t\t\t\t\t+$.datepicker._get(inst, 'stepMonths')), 'M');\n\t\t\t\t\t\t// next month/year on alt +right\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // +1 week on ctrl or command +down\n\t\t\t\tdefault: handled = false;\n\t\t\t}\n\t\telse if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home\n\t\t\t$.datepicker._showDatepicker(this);\n\t\telse {\n\t\t\thandled = false;\n\t\t}\n\t\tif (handled) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t},\n\n\t/* Filter entered characters - based on date format. */\n\t_doKeyPress: function(event) {\n\t\tvar inst = $.datepicker._getInst(event.target);\n\t\tif ($.datepicker._get(inst, 'constrainInput')) {\n\t\t\tvar chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));\n\t\t\tvar chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);\n\t\t\treturn event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);\n\t\t}\n\t},\n\n\t/* Synchronise manual entry and field/alternate field. */\n\t_doKeyUp: function(event) {\n\t\tvar inst = $.datepicker._getInst(event.target);\n\t\tif (inst.input.val() != inst.lastVal) {\n\t\t\ttry {\n\t\t\t\tvar date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),\n\t\t\t\t\t(inst.input ? inst.input.val() : null),\n\t\t\t\t\t$.datepicker._getFormatConfig(inst));\n\t\t\t\tif (date) { // only if valid\n\t\t\t\t\t$.datepicker._setDateFromField(inst);\n\t\t\t\t\t$.datepicker._updateAlternate(inst);\n\t\t\t\t\t$.datepicker._updateDatepicker(inst);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (err) {\n\t\t\t\t$.datepicker.log(err);\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\n\t/* Pop-up the date picker for a given input field.\n\t   If false returned from beforeShow event handler do not show. \n\t   @param  input  element - the input field attached to the date picker or\n\t                  event - if triggered by focus */\n\t_showDatepicker: function(input) {\n\t\tinput = input.target || input;\n\t\tif (input.nodeName.toLowerCase() != 'input') // find from button/image trigger\n\t\t\tinput = $('input', input.parentNode)[0];\n\t\tif ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here\n\t\t\treturn;\n\t\tvar inst = $.datepicker._getInst(input);\n\t\tif ($.datepicker._curInst && $.datepicker._curInst != inst) {\n\t\t\t$.datepicker._curInst.dpDiv.stop(true, true);\n\t\t\tif ( inst && $.datepicker._datepickerShowing ) {\n\t\t\t\t$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );\n\t\t\t}\n\t\t}\n\t\tvar beforeShow = $.datepicker._get(inst, 'beforeShow');\n\t\tvar beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};\n\t\tif(beforeShowSettings === false){\n\t\t\t//false\n\t\t\treturn;\n\t\t}\n\t\textendRemove(inst.settings, beforeShowSettings);\n\t\tinst.lastVal = null;\n\t\t$.datepicker._lastInput = input;\n\t\t$.datepicker._setDateFromField(inst);\n\t\tif ($.datepicker._inDialog) // hide cursor\n\t\t\tinput.value = '';\n\t\tif (!$.datepicker._pos) { // position below input\n\t\t\t$.datepicker._pos = $.datepicker._findPos(input);\n\t\t\t$.datepicker._pos[1] += input.offsetHeight; // add the height\n\t\t}\n\t\tvar isFixed = false;\n\t\t$(input).parents().each(function() {\n\t\t\tisFixed |= $(this).css('position') == 'fixed';\n\t\t\treturn !isFixed;\n\t\t});\n\t\tif (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled\n\t\t\t$.datepicker._pos[0] -= document.documentElement.scrollLeft;\n\t\t\t$.datepicker._pos[1] -= document.documentElement.scrollTop;\n\t\t}\n\t\tvar offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};\n\t\t$.datepicker._pos = null;\n\t\t//to avoid flashes on Firefox\n\t\tinst.dpDiv.empty();\n\t\t// determine sizing offscreen\n\t\tinst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});\n\t\t$.datepicker._updateDatepicker(inst);\n\t\t// fix width for dynamic number of date pickers\n\t\t// and adjust position before showing\n\t\toffset = $.datepicker._checkOffset(inst, offset, isFixed);\n\t\tinst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?\n\t\t\t'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',\n\t\t\tleft: offset.left + 'px', top: offset.top + 'px'});\n\t\tif (!inst.inline) {\n\t\t\tvar showAnim = $.datepicker._get(inst, 'showAnim');\n\t\t\tvar duration = $.datepicker._get(inst, 'duration');\n\t\t\tvar postProcess = function() {\n\t\t\t\tvar cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only\n\t\t\t\tif( !! cover.length ){\n\t\t\t\t\tvar borders = $.datepicker._getBorders(inst.dpDiv);\n\t\t\t\t\tcover.css({left: -borders[0], top: -borders[1],\n\t\t\t\t\t\twidth: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});\n\t\t\t\t}\n\t\t\t};\n\t\t\tinst.dpDiv.zIndex($(input).zIndex()+1);\n\t\t\t$.datepicker._datepickerShowing = true;\n\n\t\t\t// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed\n\t\t\tif ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )\n\t\t\t\tinst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);\n\t\t\telse\n\t\t\t\tinst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);\n\t\t\tif (!showAnim || !duration)\n\t\t\t\tpostProcess();\n\t\t\tif (inst.input.is(':visible') && !inst.input.is(':disabled'))\n\t\t\t\tinst.input.focus();\n\t\t\t$.datepicker._curInst = inst;\n\t\t}\n\t},\n\n\t/* Generate the date picker content. */\n\t_updateDatepicker: function(inst) {\n\t\tthis.maxRows = 4; //Reset the max number of rows being displayed (see #7043)\n\t\tvar borders = $.datepicker._getBorders(inst.dpDiv);\n\t\tinstActive = inst; // for delegate hover events\n\t\tinst.dpDiv.empty().append(this._generateHTML(inst));\n\t\tthis._attachHandlers(inst);\n\t\tvar cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only\n\t\tif( !!cover.length ){ //avoid call to outerXXXX() when not in IE6\n\t\t\tcover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})\n\t\t}\n\t\tinst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();\n\t\tvar numMonths = this._getNumberOfMonths(inst);\n\t\tvar cols = numMonths[1];\n\t\tvar width = 17;\n\t\tinst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');\n\t\tif (cols > 1)\n\t\t\tinst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');\n\t\tinst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +\n\t\t\t'Class']('ui-datepicker-multi');\n\t\tinst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +\n\t\t\t'Class']('ui-datepicker-rtl');\n\t\tif (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&\n\t\t\t\t// #6694 - don't focus the input if it's already focused\n\t\t\t\t// this breaks the change event in IE\n\t\t\t\tinst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)\n\t\t\tinst.input.focus();\n\t\t// deffered render of the years select (to avoid flashes on Firefox) \n\t\tif( inst.yearshtml ){\n\t\t\tvar origyearshtml = inst.yearshtml;\n\t\t\tsetTimeout(function(){\n\t\t\t\t//assure that inst.yearshtml didn't change.\n\t\t\t\tif( origyearshtml === inst.yearshtml && inst.yearshtml ){\n\t\t\t\t\tinst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);\n\t\t\t\t}\n\t\t\t\torigyearshtml = inst.yearshtml = null;\n\t\t\t}, 0);\n\t\t}\n\t},\n\n\t/* Retrieve the size of left and top borders for an element.\n\t   @param  elem  (jQuery object) the element of interest\n\t   @return  (number[2]) the left and top borders */\n\t_getBorders: function(elem) {\n\t\tvar convert = function(value) {\n\t\t\treturn {thin: 1, medium: 2, thick: 3}[value] || value;\n\t\t};\n\t\treturn [parseFloat(convert(elem.css('border-left-width'))),\n\t\t\tparseFloat(convert(elem.css('border-top-width')))];\n\t},\n\n\t/* Check positioning to remain on screen. */\n\t_checkOffset: function(inst, offset, isFixed) {\n\t\tvar dpWidth = inst.dpDiv.outerWidth();\n\t\tvar dpHeight = inst.dpDiv.outerHeight();\n\t\tvar inputWidth = inst.input ? inst.input.outerWidth() : 0;\n\t\tvar inputHeight = inst.input ? inst.input.outerHeight() : 0;\n\t\tvar viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();\n\t\tvar viewHeight = document.documentElement.clientHeight + $(document).scrollTop();\n\n\t\toffset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);\n\t\toffset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;\n\t\toffset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;\n\n\t\t// now check if datepicker is showing outside window viewport - move to a better place if so.\n\t\toffset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\n\t\t\tMath.abs(offset.left + dpWidth - viewWidth) : 0);\n\t\toffset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\n\t\t\tMath.abs(dpHeight + inputHeight) : 0);\n\n\t\treturn offset;\n\t},\n\n\t/* Find an object's position on the screen. */\n\t_findPos: function(obj) {\n\t\tvar inst = this._getInst(obj);\n\t\tvar isRTL = this._get(inst, 'isRTL');\n\t\twhile (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {\n\t\t\tobj = obj[isRTL ? 'previousSibling' : 'nextSibling'];\n\t\t}\n\t\tvar position = $(obj).offset();\n\t\treturn [position.left, position.top];\n\t},\n\n\t/* Hide the date picker from view.\n\t   @param  input  element - the input field attached to the date picker */\n\t_hideDatepicker: function(input) {\n\t\tvar inst = this._curInst;\n\t\tif (!inst || (input && inst != $.data(input, PROP_NAME)))\n\t\t\treturn;\n\t\tif (this._datepickerShowing) {\n\t\t\tvar showAnim = this._get(inst, 'showAnim');\n\t\t\tvar duration = this._get(inst, 'duration');\n\t\t\tvar postProcess = function() {\n\t\t\t\t$.datepicker._tidyDialog(inst);\n\t\t\t};\n\n\t\t\t// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed\n\t\t\tif ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )\n\t\t\t\tinst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);\n\t\t\telse\n\t\t\t\tinst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :\n\t\t\t\t\t(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);\n\t\t\tif (!showAnim)\n\t\t\t\tpostProcess();\n\t\t\tthis._datepickerShowing = false;\n\t\t\tvar onClose = this._get(inst, 'onClose');\n\t\t\tif (onClose)\n\t\t\t\tonClose.apply((inst.input ? inst.input[0] : null),\n\t\t\t\t\t[(inst.input ? inst.input.val() : ''), inst]);\n\t\t\tthis._lastInput = null;\n\t\t\tif (this._inDialog) {\n\t\t\t\tthis._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });\n\t\t\t\tif ($.blockUI) {\n\t\t\t\t\t$.unblockUI();\n\t\t\t\t\t$('body').append(this.dpDiv);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._inDialog = false;\n\t\t}\n\t},\n\n\t/* Tidy up after a dialog display. */\n\t_tidyDialog: function(inst) {\n\t\tinst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');\n\t},\n\n\t/* Close date picker if clicked elsewhere. */\n\t_checkExternalClick: function(event) {\n\t\tif (!$.datepicker._curInst)\n\t\t\treturn;\n\n\t\tvar $target = $(event.target),\n\t\t\tinst = $.datepicker._getInst($target[0]);\n\n\t\tif ( ( ( $target[0].id != $.datepicker._mainDivId &&\n\t\t\t\t$target.parents('#' + $.datepicker._mainDivId).length == 0 &&\n\t\t\t\t!$target.hasClass($.datepicker.markerClassName) &&\n\t\t\t\t!$target.closest(\".\" + $.datepicker._triggerClass).length &&\n\t\t\t\t$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||\n\t\t\t( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )\n\t\t\t$.datepicker._hideDatepicker();\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustDate: function(id, offset, period) {\n\t\tvar target = $(id);\n\t\tvar inst = this._getInst(target[0]);\n\t\tif (this._isDisabledDatepicker(target[0])) {\n\t\t\treturn;\n\t\t}\n\t\tthis._adjustInstDate(inst, offset +\n\t\t\t(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning\n\t\t\tperiod);\n\t\tthis._updateDatepicker(inst);\n\t},\n\n\t/* Action for current link. */\n\t_gotoToday: function(id) {\n\t\tvar target = $(id);\n\t\tvar inst = this._getInst(target[0]);\n\t\tif (this._get(inst, 'gotoCurrent') && inst.currentDay) {\n\t\t\tinst.selectedDay = inst.currentDay;\n\t\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth;\n\t\t\tinst.drawYear = inst.selectedYear = inst.currentYear;\n\t\t}\n\t\telse {\n\t\t\tvar date = new Date();\n\t\t\tinst.selectedDay = date.getDate();\n\t\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\t}\n\t\tthis._notifyChange(inst);\n\t\tthis._adjustDate(target);\n\t},\n\n\t/* Action for selecting a new month/year. */\n\t_selectMonthYear: function(id, select, period) {\n\t\tvar target = $(id);\n\t\tvar inst = this._getInst(target[0]);\n\t\tinst['selected' + (period == 'M' ? 'Month' : 'Year')] =\n\t\tinst['draw' + (period == 'M' ? 'Month' : 'Year')] =\n\t\t\tparseInt(select.options[select.selectedIndex].value,10);\n\t\tthis._notifyChange(inst);\n\t\tthis._adjustDate(target);\n\t},\n\n\t/* Action for selecting a day. */\n\t_selectDay: function(id, month, year, td) {\n\t\tvar target = $(id);\n\t\tif ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {\n\t\t\treturn;\n\t\t}\n\t\tvar inst = this._getInst(target[0]);\n\t\tinst.selectedDay = inst.currentDay = $('a', td).html();\n\t\tinst.selectedMonth = inst.currentMonth = month;\n\t\tinst.selectedYear = inst.currentYear = year;\n\t\tthis._selectDate(id, this._formatDate(inst,\n\t\t\tinst.currentDay, inst.currentMonth, inst.currentYear));\n\t},\n\n\t/* Erase the input field and hide the date picker. */\n\t_clearDate: function(id) {\n\t\tvar target = $(id);\n\t\tvar inst = this._getInst(target[0]);\n\t\tthis._selectDate(target, '');\n\t},\n\n\t/* Update the input field with the selected date. */\n\t_selectDate: function(id, dateStr) {\n\t\tvar target = $(id);\n\t\tvar inst = this._getInst(target[0]);\n\t\tdateStr = (dateStr != null ? dateStr : this._formatDate(inst));\n\t\tif (inst.input)\n\t\t\tinst.input.val(dateStr);\n\t\tthis._updateAlternate(inst);\n\t\tvar onSelect = this._get(inst, 'onSelect');\n\t\tif (onSelect)\n\t\t\tonSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback\n\t\telse if (inst.input)\n\t\t\tinst.input.trigger('change'); // fire the change event\n\t\tif (inst.inline)\n\t\t\tthis._updateDatepicker(inst);\n\t\telse {\n\t\t\tthis._hideDatepicker();\n\t\t\tthis._lastInput = inst.input[0];\n\t\t\tif (typeof(inst.input[0]) != 'object')\n\t\t\t\tinst.input.focus(); // restore focus\n\t\t\tthis._lastInput = null;\n\t\t}\n\t},\n\n\t/* Update any alternate field to synchronise with the main field. */\n\t_updateAlternate: function(inst) {\n\t\tvar altField = this._get(inst, 'altField');\n\t\tif (altField) { // update alternate field too\n\t\t\tvar altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');\n\t\t\tvar date = this._getDate(inst);\n\t\t\tvar dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));\n\t\t\t$(altField).each(function() { $(this).val(dateStr); });\n\t\t}\n\t},\n\n\t/* Set as beforeShowDay function to prevent selection of weekends.\n\t   @param  date  Date - the date to customise\n\t   @return [boolean, string] - is this date selectable?, what is its CSS class? */\n\tnoWeekends: function(date) {\n\t\tvar day = date.getDay();\n\t\treturn [(day > 0 && day < 6), ''];\n\t},\n\n\t/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.\n\t   @param  date  Date - the date to get the week for\n\t   @return  number - the number of the week within the year that contains this date */\n\tiso8601Week: function(date) {\n\t\tvar checkDate = new Date(date.getTime());\n\t\t// Find Thursday of this week starting on Monday\n\t\tcheckDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));\n\t\tvar time = checkDate.getTime();\n\t\tcheckDate.setMonth(0); // Compare with Jan 1\n\t\tcheckDate.setDate(1);\n\t\treturn Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\n\t},\n\n\t/* Parse a string value into a date object.\n\t   See formatDate below for the possible formats.\n\n\t   @param  format    string - the expected format of the date\n\t   @param  value     string - the date in the above format\n\t   @param  settings  Object - attributes include:\n\t                     shortYearCutoff  number - the cutoff year for determining the century (optional)\n\t                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)\n\t                     dayNames         string[7] - names of the days from Sunday (optional)\n\t                     monthNamesShort  string[12] - abbreviated names of the months (optional)\n\t                     monthNames       string[12] - names of the months (optional)\n\t   @return  Date - the extracted date value or null if value is blank */\n\tparseDate: function (format, value, settings) {\n\t\tif (format == null || value == null)\n\t\t\tthrow 'Invalid arguments';\n\t\tvalue = (typeof value == 'object' ? value.toString() : value + '');\n\t\tif (value == '')\n\t\t\treturn null;\n\t\tvar shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;\n\t\tshortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :\n\t\t\t\tnew Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));\n\t\tvar dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;\n\t\tvar dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;\n\t\tvar monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;\n\t\tvar monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;\n\t\tvar year = -1;\n\t\tvar month = -1;\n\t\tvar day = -1;\n\t\tvar doy = -1;\n\t\tvar literal = false;\n\t\t// Check whether a format character is doubled\n\t\tvar lookAhead = function(match) {\n\t\t\tvar matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);\n\t\t\tif (matches)\n\t\t\t\tiFormat++;\n\t\t\treturn matches;\n\t\t};\n\t\t// Extract a number from the string value\n\t\tvar getNumber = function(match) {\n\t\t\tvar isDoubled = lookAhead(match);\n\t\t\tvar size = (match == '@' ? 14 : (match == '!' ? 20 :\n\t\t\t\t(match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));\n\t\t\tvar digits = new RegExp('^\\\\d{1,' + size + '}');\n\t\t\tvar num = value.substring(iValue).match(digits);\n\t\t\tif (!num)\n\t\t\t\tthrow 'Missing number at position ' + iValue;\n\t\t\tiValue += num[0].length;\n\t\t\treturn parseInt(num[0], 10);\n\t\t};\n\t\t// Extract a name from the string value and convert to an index\n\t\tvar getName = function(match, shortNames, longNames) {\n\t\t\tvar names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {\n\t\t\t\treturn [ [k, v] ];\n\t\t\t}).sort(function (a, b) {\n\t\t\t\treturn -(a[1].length - b[1].length);\n\t\t\t});\n\t\t\tvar index = -1;\n\t\t\t$.each(names, function (i, pair) {\n\t\t\t\tvar name = pair[1];\n\t\t\t\tif (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {\n\t\t\t\t\tindex = pair[0];\n\t\t\t\t\tiValue += name.length;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (index != -1)\n\t\t\t\treturn index + 1;\n\t\t\telse\n\t\t\t\tthrow 'Unknown name at position ' + iValue;\n\t\t};\n\t\t// Confirm that a literal character matches the string value\n\t\tvar checkLiteral = function() {\n\t\t\tif (value.charAt(iValue) != format.charAt(iFormat))\n\t\t\t\tthrow 'Unexpected literal at position ' + iValue;\n\t\t\tiValue++;\n\t\t};\n\t\tvar iValue = 0;\n\t\tfor (var iFormat = 0; iFormat < format.length; iFormat++) {\n\t\t\tif (literal)\n\t\t\t\tif (format.charAt(iFormat) == \"'\" && !lookAhead(\"'\"))\n\t\t\t\t\tliteral = false;\n\t\t\t\telse\n\t\t\t\t\tcheckLiteral();\n\t\t\telse\n\t\t\t\tswitch (format.charAt(iFormat)) {\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tday = getNumber('d');\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'D':\n\t\t\t\t\t\tgetName('D', dayNamesShort, dayNames);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'o':\n\t\t\t\t\t\tdoy = getNumber('o');\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'm':\n\t\t\t\t\t\tmonth = getNumber('m');\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'M':\n\t\t\t\t\t\tmonth = getName('M', monthNamesShort, monthNames);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'y':\n\t\t\t\t\t\tyear = getNumber('y');\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '@':\n\t\t\t\t\t\tvar date = new Date(getNumber('@'));\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '!':\n\t\t\t\t\t\tvar date = new Date((getNumber('!') - this._ticksTo1970) / 10000);\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif (lookAhead(\"'\"))\n\t\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t}\n\t\tif (iValue < value.length){\n\t\t\tvar extra = value.substr(iValue);\n\t\t\tif (!/^\\s+/.test(extra)) {\n\t\t\t\tthrow \"Extra/unparsed characters found in date: \" + extra;\n\t\t\t}\n\t\t}\n\t\tif (year == -1)\n\t\t\tyear = new Date().getFullYear();\n\t\telse if (year < 100)\n\t\t\tyear += new Date().getFullYear() - new Date().getFullYear() % 100 +\n\t\t\t\t(year <= shortYearCutoff ? 0 : -100);\n\t\tif (doy > -1) {\n\t\t\tmonth = 1;\n\t\t\tday = doy;\n\t\t\tdo {\n\t\t\t\tvar dim = this._getDaysInMonth(year, month - 1);\n\t\t\t\tif (day <= dim)\n\t\t\t\t\tbreak;\n\t\t\t\tmonth++;\n\t\t\t\tday -= dim;\n\t\t\t} while (true);\n\t\t}\n\t\tvar date = this._daylightSavingAdjust(new Date(year, month - 1, day));\n\t\tif (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)\n\t\t\tthrow 'Invalid date'; // E.g. 31/02/00\n\t\treturn date;\n\t},\n\n\t/* Standard date formats. */\n\tATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)\n\tCOOKIE: 'D, dd M yy',\n\tISO_8601: 'yy-mm-dd',\n\tRFC_822: 'D, d M y',\n\tRFC_850: 'DD, dd-M-y',\n\tRFC_1036: 'D, d M y',\n\tRFC_1123: 'D, d M yy',\n\tRFC_2822: 'D, d M yy',\n\tRSS: 'D, d M y', // RFC 822\n\tTICKS: '!',\n\tTIMESTAMP: '@',\n\tW3C: 'yy-mm-dd', // ISO 8601\n\n\t_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +\n\t\tMath.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),\n\n\t/* Format a date object into a string value.\n\t   The format can be combinations of the following:\n\t   d  - day of month (no leading zero)\n\t   dd - day of month (two digit)\n\t   o  - day of year (no leading zeros)\n\t   oo - day of year (three digit)\n\t   D  - day name short\n\t   DD - day name long\n\t   m  - month of year (no leading zero)\n\t   mm - month of year (two digit)\n\t   M  - month name short\n\t   MM - month name long\n\t   y  - year (two digit)\n\t   yy - year (four digit)\n\t   @ - Unix timestamp (ms since 01/01/1970)\n\t   ! - Windows ticks (100ns since 01/01/0001)\n\t   '...' - literal text\n\t   '' - single quote\n\n\t   @param  format    string - the desired format of the date\n\t   @param  date      Date - the date value to format\n\t   @param  settings  Object - attributes include:\n\t                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)\n\t                     dayNames         string[7] - names of the days from Sunday (optional)\n\t                     monthNamesShort  string[12] - abbreviated names of the months (optional)\n\t                     monthNames       string[12] - names of the months (optional)\n\t   @return  string - the date in the above format */\n\tformatDate: function (format, date, settings) {\n\t\tif (!date)\n\t\t\treturn '';\n\t\tvar dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;\n\t\tvar dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;\n\t\tvar monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;\n\t\tvar monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;\n\t\t// Check whether a format character is doubled\n\t\tvar lookAhead = function(match) {\n\t\t\tvar matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);\n\t\t\tif (matches)\n\t\t\t\tiFormat++;\n\t\t\treturn matches;\n\t\t};\n\t\t// Format a number, with leading zero if necessary\n\t\tvar formatNumber = function(match, value, len) {\n\t\t\tvar num = '' + value;\n\t\t\tif (lookAhead(match))\n\t\t\t\twhile (num.length < len)\n\t\t\t\t\tnum = '0' + num;\n\t\t\treturn num;\n\t\t};\n\t\t// Format a name, short or long as requested\n\t\tvar formatName = function(match, value, shortNames, longNames) {\n\t\t\treturn (lookAhead(match) ? longNames[value] : shortNames[value]);\n\t\t};\n\t\tvar output = '';\n\t\tvar literal = false;\n\t\tif (date)\n\t\t\tfor (var iFormat = 0; iFormat < format.length; iFormat++) {\n\t\t\t\tif (literal)\n\t\t\t\t\tif (format.charAt(iFormat) == \"'\" && !lookAhead(\"'\"))\n\t\t\t\t\t\tliteral = false;\n\t\t\t\t\telse\n\t\t\t\t\t\toutput += format.charAt(iFormat);\n\t\t\t\telse\n\t\t\t\t\tswitch (format.charAt(iFormat)) {\n\t\t\t\t\t\tcase 'd':\n\t\t\t\t\t\t\toutput += formatNumber('d', date.getDate(), 2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'D':\n\t\t\t\t\t\t\toutput += formatName('D', date.getDay(), dayNamesShort, dayNames);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'o':\n\t\t\t\t\t\t\toutput += formatNumber('o',\n\t\t\t\t\t\t\t\tMath.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'm':\n\t\t\t\t\t\t\toutput += formatNumber('m', date.getMonth() + 1, 2);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'M':\n\t\t\t\t\t\t\toutput += formatName('M', date.getMonth(), monthNamesShort, monthNames);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'y':\n\t\t\t\t\t\t\toutput += (lookAhead('y') ? date.getFullYear() :\n\t\t\t\t\t\t\t\t(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase '@':\n\t\t\t\t\t\t\toutput += date.getTime();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase '!':\n\t\t\t\t\t\t\toutput += date.getTime() * 10000 + this._ticksTo1970;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\t\tif (lookAhead(\"'\"))\n\t\t\t\t\t\t\t\toutput += \"'\";\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\toutput += format.charAt(iFormat);\n\t\t\t\t\t}\n\t\t\t}\n\t\treturn output;\n\t},\n\n\t/* Extract all possible characters from the date format. */\n\t_possibleChars: function (format) {\n\t\tvar chars = '';\n\t\tvar literal = false;\n\t\t// Check whether a format character is doubled\n\t\tvar lookAhead = function(match) {\n\t\t\tvar matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);\n\t\t\tif (matches)\n\t\t\t\tiFormat++;\n\t\t\treturn matches;\n\t\t};\n\t\tfor (var iFormat = 0; iFormat < format.length; iFormat++)\n\t\t\tif (literal)\n\t\t\t\tif (format.charAt(iFormat) == \"'\" && !lookAhead(\"'\"))\n\t\t\t\t\tliteral = false;\n\t\t\t\telse\n\t\t\t\t\tchars += format.charAt(iFormat);\n\t\t\telse\n\t\t\t\tswitch (format.charAt(iFormat)) {\n\t\t\t\t\tcase 'd': case 'm': case 'y': case '@':\n\t\t\t\t\t\tchars += '0123456789';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'D': case 'M':\n\t\t\t\t\t\treturn null; // Accept anything\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif (lookAhead(\"'\"))\n\t\t\t\t\t\t\tchars += \"'\";\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tchars += format.charAt(iFormat);\n\t\t\t\t}\n\t\treturn chars;\n\t},\n\n\t/* Get a setting value, defaulting if necessary. */\n\t_get: function(inst, name) {\n\t\treturn inst.settings[name] !== undefined ?\n\t\t\tinst.settings[name] : this._defaults[name];\n\t},\n\n\t/* Parse existing date and initialise date picker. */\n\t_setDateFromField: function(inst, noDefault) {\n\t\tif (inst.input.val() == inst.lastVal) {\n\t\t\treturn;\n\t\t}\n\t\tvar dateFormat = this._get(inst, 'dateFormat');\n\t\tvar dates = inst.lastVal = inst.input ? inst.input.val() : null;\n\t\tvar date, defaultDate;\n\t\tdate = defaultDate = this._getDefaultDate(inst);\n\t\tvar settings = this._getFormatConfig(inst);\n\t\ttry {\n\t\t\tdate = this.parseDate(dateFormat, dates, settings) || defaultDate;\n\t\t} catch (event) {\n\t\t\tthis.log(event);\n\t\t\tdates = (noDefault ? '' : dates);\n\t\t}\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tinst.currentDay = (dates ? date.getDate() : 0);\n\t\tinst.currentMonth = (dates ? date.getMonth() : 0);\n\t\tinst.currentYear = (dates ? date.getFullYear() : 0);\n\t\tthis._adjustInstDate(inst);\n\t},\n\n\t/* Retrieve the default date shown on opening. */\n\t_getDefaultDate: function(inst) {\n\t\treturn this._restrictMinMax(inst,\n\t\t\tthis._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));\n\t},\n\n\t/* A date may be specified as an exact value or a relative one. */\n\t_determineDate: function(inst, date, defaultDate) {\n\t\tvar offsetNumeric = function(offset) {\n\t\t\tvar date = new Date();\n\t\t\tdate.setDate(date.getDate() + offset);\n\t\t\treturn date;\n\t\t};\n\t\tvar offsetString = function(offset) {\n\t\t\ttry {\n\t\t\t\treturn $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),\n\t\t\t\t\toffset, $.datepicker._getFormatConfig(inst));\n\t\t\t}\n\t\t\tcatch (e) {\n\t\t\t\t// Ignore\n\t\t\t}\n\t\t\tvar date = (offset.toLowerCase().match(/^c/) ?\n\t\t\t\t$.datepicker._getDate(inst) : null) || new Date();\n\t\t\tvar year = date.getFullYear();\n\t\t\tvar month = date.getMonth();\n\t\t\tvar day = date.getDate();\n\t\t\tvar pattern = /([+-]?[0-9]+)\\s*(d|D|w|W|m|M|y|Y)?/g;\n\t\t\tvar matches = pattern.exec(offset);\n\t\t\twhile (matches) {\n\t\t\t\tswitch (matches[2] || 'd') {\n\t\t\t\t\tcase 'd' : case 'D' :\n\t\t\t\t\t\tday += parseInt(matches[1],10); break;\n\t\t\t\t\tcase 'w' : case 'W' :\n\t\t\t\t\t\tday += parseInt(matches[1],10) * 7; break;\n\t\t\t\t\tcase 'm' : case 'M' :\n\t\t\t\t\t\tmonth += parseInt(matches[1],10);\n\t\t\t\t\t\tday = Math.min(day, $.datepicker._getDaysInMonth(year, month));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'y': case 'Y' :\n\t\t\t\t\t\tyear += parseInt(matches[1],10);\n\t\t\t\t\t\tday = Math.min(day, $.datepicker._getDaysInMonth(year, month));\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatches = pattern.exec(offset);\n\t\t\t}\n\t\t\treturn new Date(year, month, day);\n\t\t};\n\t\tvar newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :\n\t\t\t(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));\n\t\tnewDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);\n\t\tif (newDate) {\n\t\t\tnewDate.setHours(0);\n\t\t\tnewDate.setMinutes(0);\n\t\t\tnewDate.setSeconds(0);\n\t\t\tnewDate.setMilliseconds(0);\n\t\t}\n\t\treturn this._daylightSavingAdjust(newDate);\n\t},\n\n\t/* Handle switch to/from daylight saving.\n\t   Hours may be non-zero on daylight saving cut-over:\n\t   > 12 when midnight changeover, but then cannot generate\n\t   midnight datetime, so jump to 1AM, otherwise reset.\n\t   @param  date  (Date) the date to check\n\t   @return  (Date) the corrected date */\n\t_daylightSavingAdjust: function(date) {\n\t\tif (!date) return null;\n\t\tdate.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n\t\treturn date;\n\t},\n\n\t/* Set the date(s) directly. */\n\t_setDate: function(inst, date, noChange) {\n\t\tvar clear = !date;\n\t\tvar origMonth = inst.selectedMonth;\n\t\tvar origYear = inst.selectedYear;\n\t\tvar newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));\n\t\tinst.selectedDay = inst.currentDay = newDate.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();\n\t\tinst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();\n\t\tif ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)\n\t\t\tthis._notifyChange(inst);\n\t\tthis._adjustInstDate(inst);\n\t\tif (inst.input) {\n\t\t\tinst.input.val(clear ? '' : this._formatDate(inst));\n\t\t}\n\t},\n\n\t/* Retrieve the date(s) directly. */\n\t_getDate: function(inst) {\n\t\tvar startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :\n\t\t\tthis._daylightSavingAdjust(new Date(\n\t\t\tinst.currentYear, inst.currentMonth, inst.currentDay)));\n\t\t\treturn startDate;\n\t},\n\n\t/* Attach the onxxx handlers.  These are declared statically so\n\t * they work with static code transformers like Caja.\n\t */\n\t_attachHandlers: function(inst) {\n\t\tvar stepMonths = this._get(inst, 'stepMonths');\n\t\tvar id = '#' + inst.id;\n\t\tinst.dpDiv.find('[data-handler]').map(function () {\n\t\t\tvar handler = {\n\t\t\t\tprev: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');\n\t\t\t\t},\n\t\t\t\tnext: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');\n\t\t\t\t},\n\t\t\t\thide: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();\n\t\t\t\t},\n\t\t\t\ttoday: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);\n\t\t\t\t},\n\t\t\t\tselectDay: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectMonth: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectYear: function () {\n\t\t\t\t\twindow['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\t\t\t$(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);\n\t\t});\n\t},\n\t\n\t/* Generate the HTML for the current state of the date picker. */\n\t_generateHTML: function(inst) {\n\t\tvar today = new Date();\n\t\ttoday = this._daylightSavingAdjust(\n\t\t\tnew Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time\n\t\tvar isRTL = this._get(inst, 'isRTL');\n\t\tvar showButtonPanel = this._get(inst, 'showButtonPanel');\n\t\tvar hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');\n\t\tvar navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');\n\t\tvar numMonths = this._getNumberOfMonths(inst);\n\t\tvar showCurrentAtPos = this._get(inst, 'showCurrentAtPos');\n\t\tvar stepMonths = this._get(inst, 'stepMonths');\n\t\tvar isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);\n\t\tvar currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :\n\t\t\tnew Date(inst.currentYear, inst.currentMonth, inst.currentDay)));\n\t\tvar minDate = this._getMinMaxDate(inst, 'min');\n\t\tvar maxDate = this._getMinMaxDate(inst, 'max');\n\t\tvar drawMonth = inst.drawMonth - showCurrentAtPos;\n\t\tvar drawYear = inst.drawYear;\n\t\tif (drawMonth < 0) {\n\t\t\tdrawMonth += 12;\n\t\t\tdrawYear--;\n\t\t}\n\t\tif (maxDate) {\n\t\t\tvar maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),\n\t\t\t\tmaxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));\n\t\t\tmaxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);\n\t\t\twhile (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {\n\t\t\t\tdrawMonth--;\n\t\t\t\tif (drawMonth < 0) {\n\t\t\t\t\tdrawMonth = 11;\n\t\t\t\t\tdrawYear--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinst.drawMonth = drawMonth;\n\t\tinst.drawYear = drawYear;\n\t\tvar prevText = this._get(inst, 'prevText');\n\t\tprevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,\n\t\t\tthis._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),\n\t\t\tthis._getFormatConfig(inst)));\n\t\tvar prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?\n\t\t\t'<a class=\"ui-datepicker-prev ui-corner-all\" data-handler=\"prev\" data-event=\"click\"' +\n\t\t\t' title=\"' + prevText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '\">' + prevText + '</span></a>' :\n\t\t\t(hideIfNoPrevNext ? '' : '<a class=\"ui-datepicker-prev ui-corner-all ui-state-disabled\" title=\"'+ prevText +'\"><span class=\"ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '\">' + prevText + '</span></a>'));\n\t\tvar nextText = this._get(inst, 'nextText');\n\t\tnextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,\n\t\t\tthis._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),\n\t\t\tthis._getFormatConfig(inst)));\n\t\tvar next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?\n\t\t\t'<a class=\"ui-datepicker-next ui-corner-all\" data-handler=\"next\" data-event=\"click\"' +\n\t\t\t' title=\"' + nextText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '\">' + nextText + '</span></a>' :\n\t\t\t(hideIfNoPrevNext ? '' : '<a class=\"ui-datepicker-next ui-corner-all ui-state-disabled\" title=\"'+ nextText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '\">' + nextText + '</span></a>'));\n\t\tvar currentText = this._get(inst, 'currentText');\n\t\tvar gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);\n\t\tcurrentText = (!navigationAsDateFormat ? currentText :\n\t\t\tthis.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));\n\t\tvar controls = (!inst.inline ? '<button type=\"button\" class=\"ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all\" data-handler=\"hide\" data-event=\"click\">' +\n\t\t\tthis._get(inst, 'closeText') + '</button>' : '');\n\t\tvar buttonPanel = (showButtonPanel) ? '<div class=\"ui-datepicker-buttonpane ui-widget-content\">' + (isRTL ? controls : '') +\n\t\t\t(this._isInRange(inst, gotoDate) ? '<button type=\"button\" class=\"ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all\" data-handler=\"today\" data-event=\"click\"' +\n\t\t\t'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';\n\t\tvar firstDay = parseInt(this._get(inst, 'firstDay'),10);\n\t\tfirstDay = (isNaN(firstDay) ? 0 : firstDay);\n\t\tvar showWeek = this._get(inst, 'showWeek');\n\t\tvar dayNames = this._get(inst, 'dayNames');\n\t\tvar dayNamesShort = this._get(inst, 'dayNamesShort');\n\t\tvar dayNamesMin = this._get(inst, 'dayNamesMin');\n\t\tvar monthNames = this._get(inst, 'monthNames');\n\t\tvar monthNamesShort = this._get(inst, 'monthNamesShort');\n\t\tvar beforeShowDay = this._get(inst, 'beforeShowDay');\n\t\tvar showOtherMonths = this._get(inst, 'showOtherMonths');\n\t\tvar selectOtherMonths = this._get(inst, 'selectOtherMonths');\n\t\tvar calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;\n\t\tvar defaultDate = this._getDefaultDate(inst);\n\t\tvar html = '';\n\t\tfor (var row = 0; row < numMonths[0]; row++) {\n\t\t\tvar group = '';\n\t\t\tthis.maxRows = 4;\n\t\t\tfor (var col = 0; col < numMonths[1]; col++) {\n\t\t\t\tvar selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));\n\t\t\t\tvar cornerClass = ' ui-corner-all';\n\t\t\t\tvar calender = '';\n\t\t\t\tif (isMultiMonth) {\n\t\t\t\t\tcalender += '<div class=\"ui-datepicker-group';\n\t\t\t\t\tif (numMonths[1] > 1)\n\t\t\t\t\t\tswitch (col) {\n\t\t\t\t\t\t\tcase 0: calender += ' ui-datepicker-group-first';\n\t\t\t\t\t\t\t\tcornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;\n\t\t\t\t\t\t\tcase numMonths[1]-1: calender += ' ui-datepicker-group-last';\n\t\t\t\t\t\t\t\tcornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;\n\t\t\t\t\t\t\tdefault: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;\n\t\t\t\t\t\t}\n\t\t\t\t\tcalender += '\">';\n\t\t\t\t}\n\t\t\t\tcalender += '<div class=\"ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '\">' +\n\t\t\t\t\t(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +\n\t\t\t\t\t(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +\n\t\t\t\t\tthis._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\t\t\trow > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers\n\t\t\t\t\t'</div><table class=\"ui-datepicker-calendar\"><thead>' +\n\t\t\t\t\t'<tr>';\n\t\t\t\tvar thead = (showWeek ? '<th class=\"ui-datepicker-week-col\">' + this._get(inst, 'weekHeader') + '</th>' : '');\n\t\t\t\tfor (var dow = 0; dow < 7; dow++) { // days of the week\n\t\t\t\t\tvar day = (dow + firstDay) % 7;\n\t\t\t\t\tthead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class=\"ui-datepicker-week-end\"' : '') + '>' +\n\t\t\t\t\t\t'<span title=\"' + dayNames[day] + '\">' + dayNamesMin[day] + '</span></th>';\n\t\t\t\t}\n\t\t\t\tcalender += thead + '</tr></thead><tbody>';\n\t\t\t\tvar daysInMonth = this._getDaysInMonth(drawYear, drawMonth);\n\t\t\t\tif (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)\n\t\t\t\t\tinst.selectedDay = Math.min(inst.selectedDay, daysInMonth);\n\t\t\t\tvar leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;\n\t\t\t\tvar curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate\n\t\t\t\tvar numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)\n\t\t\t\tthis.maxRows = numRows;\n\t\t\t\tvar printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));\n\t\t\t\tfor (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows\n\t\t\t\t\tcalender += '<tr>';\n\t\t\t\t\tvar tbody = (!showWeek ? '' : '<td class=\"ui-datepicker-week-col\">' +\n\t\t\t\t\t\tthis._get(inst, 'calculateWeek')(printDate) + '</td>');\n\t\t\t\t\tfor (var dow = 0; dow < 7; dow++) { // create date picker days\n\t\t\t\t\t\tvar daySettings = (beforeShowDay ?\n\t\t\t\t\t\t\tbeforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);\n\t\t\t\t\t\tvar otherMonth = (printDate.getMonth() != drawMonth);\n\t\t\t\t\t\tvar unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||\n\t\t\t\t\t\t\t(minDate && printDate < minDate) || (maxDate && printDate > maxDate);\n\t\t\t\t\t\ttbody += '<td class=\"' +\n\t\t\t\t\t\t\t((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends\n\t\t\t\t\t\t\t(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months\n\t\t\t\t\t\t\t((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key\n\t\t\t\t\t\t\t(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?\n\t\t\t\t\t\t\t// or defaultDate is current printedDate and defaultDate is selectedDate\n\t\t\t\t\t\t\t' ' + this._dayOverClass : '') + // highlight selected day\n\t\t\t\t\t\t\t(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days\n\t\t\t\t\t\t\t(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates\n\t\t\t\t\t\t\t(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day\n\t\t\t\t\t\t\t(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '\"' + // highlight today (if different)\n\t\t\t\t\t\t\t((!otherMonth || showOtherMonths) && daySettings[2] ? ' title=\"' + daySettings[2] + '\"' : '') + // cell title\n\t\t\t\t\t\t\t(unselectable ? '' : ' data-handler=\"selectDay\" data-event=\"click\" data-month=\"' + printDate.getMonth() + '\" data-year=\"' + printDate.getFullYear() + '\"') + '>' + // actions\n\t\t\t\t\t\t\t(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months\n\t\t\t\t\t\t\t(unselectable ? '<span class=\"ui-state-default\">' + printDate.getDate() + '</span>' : '<a class=\"ui-state-default' +\n\t\t\t\t\t\t\t(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +\n\t\t\t\t\t\t\t(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day\n\t\t\t\t\t\t\t(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months\n\t\t\t\t\t\t\t'\" href=\"#\">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date\n\t\t\t\t\t\tprintDate.setDate(printDate.getDate() + 1);\n\t\t\t\t\t\tprintDate = this._daylightSavingAdjust(printDate);\n\t\t\t\t\t}\n\t\t\t\t\tcalender += tbody + '</tr>';\n\t\t\t\t}\n\t\t\t\tdrawMonth++;\n\t\t\t\tif (drawMonth > 11) {\n\t\t\t\t\tdrawMonth = 0;\n\t\t\t\t\tdrawYear++;\n\t\t\t\t}\n\t\t\t\tcalender += '</tbody></table>' + (isMultiMonth ? '</div>' + \n\t\t\t\t\t\t\t((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class=\"ui-datepicker-row-break\"></div>' : '') : '');\n\t\t\t\tgroup += calender;\n\t\t\t}\n\t\t\thtml += group;\n\t\t}\n\t\thtml += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?\n\t\t\t'<iframe src=\"javascript:false;\" class=\"ui-datepicker-cover\" frameborder=\"0\"></iframe>' : '');\n\t\tinst._keyEvent = false;\n\t\treturn html;\n\t},\n\n\t/* Generate the month and year header. */\n\t_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\tsecondary, monthNames, monthNamesShort) {\n\t\tvar changeMonth = this._get(inst, 'changeMonth');\n\t\tvar changeYear = this._get(inst, 'changeYear');\n\t\tvar showMonthAfterYear = this._get(inst, 'showMonthAfterYear');\n\t\tvar html = '<div class=\"ui-datepicker-title\">';\n\t\tvar monthHtml = '';\n\t\t// month selection\n\t\tif (secondary || !changeMonth)\n\t\t\tmonthHtml += '<span class=\"ui-datepicker-month\">' + monthNames[drawMonth] + '</span>';\n\t\telse {\n\t\t\tvar inMinYear = (minDate && minDate.getFullYear() == drawYear);\n\t\t\tvar inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);\n\t\t\tmonthHtml += '<select class=\"ui-datepicker-month\" data-handler=\"selectMonth\" data-event=\"change\">';\n\t\t\tfor (var month = 0; month < 12; month++) {\n\t\t\t\tif ((!inMinYear || month >= minDate.getMonth()) &&\n\t\t\t\t\t\t(!inMaxYear || month <= maxDate.getMonth()))\n\t\t\t\t\tmonthHtml += '<option value=\"' + month + '\"' +\n\t\t\t\t\t\t(month == drawMonth ? ' selected=\"selected\"' : '') +\n\t\t\t\t\t\t'>' + monthNamesShort[month] + '</option>';\n\t\t\t}\n\t\t\tmonthHtml += '</select>';\n\t\t}\n\t\tif (!showMonthAfterYear)\n\t\t\thtml += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');\n\t\t// year selection\n\t\tif ( !inst.yearshtml ) {\n\t\t\tinst.yearshtml = '';\n\t\t\tif (secondary || !changeYear)\n\t\t\t\thtml += '<span class=\"ui-datepicker-year\">' + drawYear + '</span>';\n\t\t\telse {\n\t\t\t\t// determine range of years to display\n\t\t\t\tvar years = this._get(inst, 'yearRange').split(':');\n\t\t\t\tvar thisYear = new Date().getFullYear();\n\t\t\t\tvar determineYear = function(value) {\n\t\t\t\t\tvar year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :\n\t\t\t\t\t\t(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :\n\t\t\t\t\t\tparseInt(value, 10)));\n\t\t\t\t\treturn (isNaN(year) ? thisYear : year);\n\t\t\t\t};\n\t\t\t\tvar year = determineYear(years[0]);\n\t\t\t\tvar endYear = Math.max(year, determineYear(years[1] || ''));\n\t\t\t\tyear = (minDate ? Math.max(year, minDate.getFullYear()) : year);\n\t\t\t\tendYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);\n\t\t\t\tinst.yearshtml += '<select class=\"ui-datepicker-year\" data-handler=\"selectYear\" data-event=\"change\">';\n\t\t\t\tfor (; year <= endYear; year++) {\n\t\t\t\t\tinst.yearshtml += '<option value=\"' + year + '\"' +\n\t\t\t\t\t\t(year == drawYear ? ' selected=\"selected\"' : '') +\n\t\t\t\t\t\t'>' + year + '</option>';\n\t\t\t\t}\n\t\t\t\tinst.yearshtml += '</select>';\n\t\t\t\t\n\t\t\t\thtml += inst.yearshtml;\n\t\t\t\tinst.yearshtml = null;\n\t\t\t}\n\t\t}\n\t\thtml += this._get(inst, 'yearSuffix');\n\t\tif (showMonthAfterYear)\n\t\t\thtml += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;\n\t\thtml += '</div>'; // Close datepicker_header\n\t\treturn html;\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustInstDate: function(inst, offset, period) {\n\t\tvar year = inst.drawYear + (period == 'Y' ? offset : 0);\n\t\tvar month = inst.drawMonth + (period == 'M' ? offset : 0);\n\t\tvar day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +\n\t\t\t(period == 'D' ? offset : 0);\n\t\tvar date = this._restrictMinMax(inst,\n\t\t\tthis._daylightSavingAdjust(new Date(year, month, day)));\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tif (period == 'M' || period == 'Y')\n\t\t\tthis._notifyChange(inst);\n\t},\n\n\t/* Ensure a date is within any min/max bounds. */\n\t_restrictMinMax: function(inst, date) {\n\t\tvar minDate = this._getMinMaxDate(inst, 'min');\n\t\tvar maxDate = this._getMinMaxDate(inst, 'max');\n\t\tvar newDate = (minDate && date < minDate ? minDate : date);\n\t\tnewDate = (maxDate && newDate > maxDate ? maxDate : newDate);\n\t\treturn newDate;\n\t},\n\n\t/* Notify change of month/year. */\n\t_notifyChange: function(inst) {\n\t\tvar onChange = this._get(inst, 'onChangeMonthYear');\n\t\tif (onChange)\n\t\t\tonChange.apply((inst.input ? inst.input[0] : null),\n\t\t\t\t[inst.selectedYear, inst.selectedMonth + 1, inst]);\n\t},\n\n\t/* Determine the number of months to show. */\n\t_getNumberOfMonths: function(inst) {\n\t\tvar numMonths = this._get(inst, 'numberOfMonths');\n\t\treturn (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));\n\t},\n\n\t/* Determine the current maximum date - ensure no time components are set. */\n\t_getMinMaxDate: function(inst, minMax) {\n\t\treturn this._determineDate(inst, this._get(inst, minMax + 'Date'), null);\n\t},\n\n\t/* Find the number of days in a given month. */\n\t_getDaysInMonth: function(year, month) {\n\t\treturn 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();\n\t},\n\n\t/* Find the day of the week of the first of a month. */\n\t_getFirstDayOfMonth: function(year, month) {\n\t\treturn new Date(year, month, 1).getDay();\n\t},\n\n\t/* Determines if we should allow a \"next/prev\" month display change. */\n\t_canAdjustMonth: function(inst, offset, curYear, curMonth) {\n\t\tvar numMonths = this._getNumberOfMonths(inst);\n\t\tvar date = this._daylightSavingAdjust(new Date(curYear,\n\t\t\tcurMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));\n\t\tif (offset < 0)\n\t\t\tdate.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));\n\t\treturn this._isInRange(inst, date);\n\t},\n\n\t/* Is the given date in the accepted range? */\n\t_isInRange: function(inst, date) {\n\t\tvar minDate = this._getMinMaxDate(inst, 'min');\n\t\tvar maxDate = this._getMinMaxDate(inst, 'max');\n\t\treturn ((!minDate || date.getTime() >= minDate.getTime()) &&\n\t\t\t(!maxDate || date.getTime() <= maxDate.getTime()));\n\t},\n\n\t/* Provide the configuration settings for formatting/parsing. */\n\t_getFormatConfig: function(inst) {\n\t\tvar shortYearCutoff = this._get(inst, 'shortYearCutoff');\n\t\tshortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :\n\t\t\tnew Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));\n\t\treturn {shortYearCutoff: shortYearCutoff,\n\t\t\tdayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),\n\t\t\tmonthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};\n\t},\n\n\t/* Format the given date for display. */\n\t_formatDate: function(inst, day, month, year) {\n\t\tif (!day) {\n\t\t\tinst.currentDay = inst.selectedDay;\n\t\t\tinst.currentMonth = inst.selectedMonth;\n\t\t\tinst.currentYear = inst.selectedYear;\n\t\t}\n\t\tvar date = (day ? (typeof day == 'object' ? day :\n\t\t\tthis._daylightSavingAdjust(new Date(year, month, day))) :\n\t\t\tthis._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));\n\t\treturn this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));\n\t}\n});\n\n/*\n * Bind hover events for datepicker elements.\n * Done via delegate so the binding only occurs once in the lifetime of the parent div.\n * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.\n */ \nfunction bindHover(dpDiv) {\n\tvar selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';\n\treturn dpDiv.delegate(selector, 'mouseout', function() {\n\t\t\t$(this).removeClass('ui-state-hover');\n\t\t\tif (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');\n\t\t\tif (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');\n\t\t})\n\t\t.delegate(selector, 'mouseover', function(){\n\t\t\tif (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {\n\t\t\t\t$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');\n\t\t\t\t$(this).addClass('ui-state-hover');\n\t\t\t\tif (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');\n\t\t\t\tif (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');\n\t\t\t}\n\t\t});\n}\n\n/* jQuery extend now ignores nulls! */\nfunction extendRemove(target, props) {\n\t$.extend(target, props);\n\tfor (var name in props)\n\t\tif (props[name] == null || props[name] == undefined)\n\t\t\ttarget[name] = props[name];\n\treturn target;\n};\n\n/* Determine whether an object is an array. */\nfunction isArray(a) {\n\treturn (a && (($.browser.safari && typeof a == 'object' && a.length) ||\n\t\t(a.constructor && a.constructor.toString().match(/\\Array\\(\\)/))));\n};\n\n/* Invoke the datepicker functionality.\n   @param  options  string - a command, optionally followed by additional parameters or\n\t                Object - settings for attaching new datepicker functionality\n   @return  jQuery object */\n$.fn.datepicker = function(options){\n\t\n\t/* Verify an empty collection wasn't passed - Fixes #6976 */\n\tif ( !this.length ) {\n\t\treturn this;\n\t}\n\t\n\t/* Initialise the date picker. */\n\tif (!$.datepicker.initialized) {\n\t\t$(document).mousedown($.datepicker._checkExternalClick).\n\t\t\tfind('body').append($.datepicker.dpDiv);\n\t\t$.datepicker.initialized = true;\n\t}\n\n\tvar otherArgs = Array.prototype.slice.call(arguments, 1);\n\tif (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))\n\t\treturn $.datepicker['_' + options + 'Datepicker'].\n\t\t\tapply($.datepicker, [this[0]].concat(otherArgs));\n\tif (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')\n\t\treturn $.datepicker['_' + options + 'Datepicker'].\n\t\t\tapply($.datepicker, [this[0]].concat(otherArgs));\n\treturn this.each(function() {\n\t\ttypeof options == 'string' ?\n\t\t\t$.datepicker['_' + options + 'Datepicker'].\n\t\t\t\tapply($.datepicker, [this].concat(otherArgs)) :\n\t\t\t$.datepicker._attachDatepicker(this, options);\n\t});\n};\n\n$.datepicker = new Datepicker(); // singleton instance\n$.datepicker.initialized = false;\n$.datepicker.uuid = new Date().getTime();\n$.datepicker.version = \"@VERSION\";\n\n// Workaround for #4055\n// Add another global to avoid noConflict issues with inline event handlers\nwindow['DP_jQuery_' + dpuuid] = $;\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.dialog.js",
    "content": "/*!\n * jQuery UI Dialog @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Dialog\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n *  jquery.ui.button.js\n *\tjquery.ui.draggable.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.position.js\n *\tjquery.ui.resizable.js\n */\n(function( $, undefined ) {\n\nvar uiDialogClasses = \"ui-dialog ui-widget ui-widget-content ui-corner-all \",\n\tsizeRelatedOptions = {\n\t\tbuttons: true,\n\t\theight: true,\n\t\tmaxHeight: true,\n\t\tmaxWidth: true,\n\t\tminHeight: true,\n\t\tminWidth: true,\n\t\twidth: true\n\t},\n\tresizableRelatedOptions = {\n\t\tmaxHeight: true,\n\t\tmaxWidth: true,\n\t\tminHeight: true,\n\t\tminWidth: true\n\t};\n\n$.widget(\"ui.dialog\", {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\tautoOpen: true,\n\t\tbuttons: {},\n\t\tcloseOnEscape: true,\n\t\tcloseText: \"close\",\n\t\tdialogClass: \"\",\n\t\tdraggable: true,\n\t\thide: null,\n\t\theight: \"auto\",\n\t\tmaxHeight: false,\n\t\tmaxWidth: false,\n\t\tminHeight: 150,\n\t\tminWidth: 150,\n\t\tmodal: false,\n\t\tposition: {\n\t\t\tmy: \"center\",\n\t\t\tat: \"center\",\n\t\t\tof: window,\n\t\t\tcollision: \"fit\",\n\t\t\t// ensure that the titlebar is never outside the document\n\t\t\tusing: function( pos ) {\n\t\t\t\tvar topOffset = $( this ).css( pos ).offset().top;\n\t\t\t\tif ( topOffset < 0 ) {\n\t\t\t\t\t$( this ).css( \"top\", pos.top - topOffset );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tresizable: true,\n\t\tshow: null,\n\t\tstack: true,\n\t\ttitle: \"\",\n\t\twidth: 300,\n\t\tzIndex: 1000\n\t},\n\n\t_create: function() {\n\t\tthis.originalTitle = this.element.attr( \"title\" );\n\t\t// #5742 - .attr() might return a DOMElement\n\t\tif ( typeof this.originalTitle !== \"string\" ) {\n\t\t\tthis.originalTitle = \"\";\n\t\t}\n\t\tthis.oldPosition = {\n\t\t\tparent: this.element.parent(),\n\t\t\tindex: this.element.parent().children().index( this.element )\n\t\t};\n\t\tthis.options.title = this.options.title || this.originalTitle;\n\t\tvar that = this,\n\t\t\toptions = this.options,\n\n\t\t\ttitle = options.title || \"&#160;\",\n\n\t\t\tuiDialog = ( this.uiDialog = $( \"<div>\" ) )\n\t\t\t\t.addClass( uiDialogClasses + options.dialogClass )\n\t\t\t\t.css({\n\t\t\t\t\tdisplay: \"none\",\n\t\t\t\t\toutline: 0, // TODO: move to stylesheet\n\t\t\t\t\tzIndex: options.zIndex\n\t\t\t\t})\n\t\t\t\t// setting tabIndex makes the div focusable\n\t\t\t\t.attr( \"tabIndex\", -1)\n\t\t\t\t.keydown(function( event ) {\n\t\t\t\t\tif ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&\n\t\t\t\t\t\t\tevent.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\t\tthat.close( event );\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.mousedown(function( event ) {\n\t\t\t\t\tthat.moveToTop( false, event );\n\t\t\t\t})\n\t\t\t\t.appendTo( \"body\" ),\n\n\t\t\tuiDialogContent = this.element\n\t\t\t\t.show()\n\t\t\t\t.removeAttr( \"title\" )\n\t\t\t\t.addClass( \"ui-dialog-content ui-widget-content\" )\n\t\t\t\t.appendTo( uiDialog ),\n\n\t\t\tuiDialogTitlebar = ( this.uiDialogTitlebar = $( \"<div>\" ) )\n\t\t\t\t.addClass( \"ui-dialog-titlebar  ui-widget-header  \" +\n\t\t\t\t\t\"ui-corner-all  ui-helper-clearfix\" )\n\t\t\t\t.prependTo( uiDialog ),\n\n\t\t\tuiDialogTitlebarClose = $( \"<a href='#'></a>\" )\n\t\t\t\t.addClass( \"ui-dialog-titlebar-close  ui-corner-all\" )\n\t\t\t\t.attr( \"role\", \"button\" )\n\t\t\t\t.click(function( event ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthat.close( event );\n\t\t\t\t})\n\t\t\t\t.appendTo( uiDialogTitlebar ),\n\n\t\t\tuiDialogTitlebarCloseText = ( this.uiDialogTitlebarCloseText = $( \"<span>\" ) )\n\t\t\t\t.addClass( \"ui-icon ui-icon-closethick\" )\n\t\t\t\t.text( options.closeText )\n\t\t\t\t.appendTo( uiDialogTitlebarClose ),\n\n\t\t\tuiDialogTitle = $( \"<span>\" )\n\t\t\t\t.uniqueId()\n\t\t\t\t.addClass( \"ui-dialog-title\" )\n\t\t\t\t.html( title )\n\t\t\t\t.prependTo( uiDialogTitlebar ),\n\n\t\t\tuiDialogButtonPane = ( this.uiDialogButtonPane = $( \"<div>\" ) )\n\t\t\t\t.addClass( \"ui-dialog-buttonpane ui-widget-content ui-helper-clearfix\" ),\n\n\t\t\tuiButtonSet = ( this.uiButtonSet = $( \"<div>\" ) )\n\t\t\t\t.addClass( \"ui-dialog-buttonset\" )\n\t\t\t\t.appendTo( uiDialogButtonPane );\n\n\t\tuiDialog.attr({\n\t\t\trole: \"dialog\",\n\t\t\t\"aria-labelledby\": uiDialogTitle.attr( \"id\" )\n\t\t});\n\n\t\tuiDialogTitlebar.find( \"*\" ).add( uiDialogTitlebar ).disableSelection();\n\t\tthis._hoverable( uiDialogTitlebarClose );\n\t\tthis._focusable( uiDialogTitlebarClose );\n\n\t\tif ( options.draggable && $.fn.draggable ) {\n\t\t\tthis._makeDraggable();\n\t\t}\n\t\tif ( options.resizable && $.fn.resizable ) {\n\t\t\tthis._makeResizable();\n\t\t}\n\n\t\tthis._createButtons( options.buttons );\n\t\tthis._isOpen = false;\n\n\t\tif ( $.fn.bgiframe ) {\n\t\t\tuiDialog.bgiframe();\n\t\t}\n\t},\n\n\t_init: function() {\n\t\tif ( this.options.autoOpen ) {\n\t\t\tthis.open();\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tvar next,\n\t\t\toldPosition = this.oldPosition;\n\n\t\tif ( this.overlay ) {\n\t\t\tthis.overlay.destroy();\n\t\t}\n\t\tthis.uiDialog.hide();\n\t\tthis.element\n\t\t\t.removeClass( \"ui-dialog-content ui-widget-content\" )\n\t\t\t.hide()\n\t\t\t.appendTo( \"body\" );\n\t\tthis.uiDialog.remove();\n\n\t\tif ( this.originalTitle ) {\n\t\t\tthis.element.attr( \"title\", this.originalTitle );\n\t\t}\n\n\t\tnext = oldPosition.parent.children().eq( oldPosition.index );\n\t\tif ( next.length ) {\n\t\t\tnext.before( this.element );\n\t\t} else {\n\t\t\toldPosition.parent.append( this.element );\n\t\t}\n\t},\n\n\twidget: function() {\n\t\treturn this.uiDialog;\n\t},\n\n\tclose: function( event ) {\n\t\tvar that = this,\n\t\t\tmaxZ, thisZ;\n\n\t\tif ( !this._isOpen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( false === this._trigger( \"beforeClose\", event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._isOpen = false;\n\n\t\tif ( this.overlay ) {\n\t\t\tthis.overlay.destroy();\n\t\t}\n\t\tthis.uiDialog.unbind( \"keypress.ui-dialog\" );\n\n\t\tif ( this.options.hide ) {\n\t\t\tthis.uiDialog.hide( this.options.hide, function() {\n\t\t\t\tthat._trigger( \"close\", event );\n\t\t\t});\n\t\t} else {\n\t\t\tthis.uiDialog.hide();\n\t\t\tthis._trigger( \"close\", event );\n\t\t}\n\n\t\t$.ui.dialog.overlay.resize();\n\n\t\t// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)\n\t\tif ( this.options.modal ) {\n\t\t\tmaxZ = 0;\n\t\t\t$( \".ui-dialog\" ).each(function() {\n\t\t\t\tif ( this !== that.uiDialog[0] ) {\n\t\t\t\t\tthisZ = $( this ).css( \"z-index\" );\n\t\t\t\t\tif ( !isNaN( thisZ ) ) {\n\t\t\t\t\t\tmaxZ = Math.max( maxZ, thisZ );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t$.ui.dialog.maxZ = maxZ;\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tisOpen: function() {\n\t\treturn this._isOpen;\n\t},\n\n\t// the force parameter allows us to move modal dialogs to their correct\n\t// position on open\n\tmoveToTop: function( force, event ) {\n\t\tvar options = this.options,\n\t\t\tsaveScroll;\n\n\t\tif ( ( options.modal && !force ) ||\n\t\t\t\t( !options.stack && !options.modal ) ) {\n\t\t\treturn this._trigger( \"focus\", event );\n\t\t}\n\n\t\tif ( options.zIndex > $.ui.dialog.maxZ ) {\n\t\t\t$.ui.dialog.maxZ = options.zIndex;\n\t\t}\n\t\tif ( this.overlay ) {\n\t\t\t$.ui.dialog.maxZ += 1;\n\t\t\t$.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;\n\t\t\tthis.overlay.$el.css( \"z-index\", $.ui.dialog.overlay.maxZ );\n\t\t}\n\n\t\t// Save and then restore scroll\n\t\t// Opera 9.5+ resets when parent z-index is changed.\n\t\t// http://bugs.jqueryui.com/ticket/3193\n\t\tsaveScroll = {\n\t\t\tscrollTop: this.element.scrollTop(),\n\t\t\tscrollLeft: this.element.scrollLeft()\n\t\t};\n\t\t$.ui.dialog.maxZ += 1;\n\t\tthis.uiDialog.css( \"z-index\", $.ui.dialog.maxZ );\n\t\tthis.element.attr( saveScroll );\n\t\tthis._trigger( \"focus\", event );\n\n\t\treturn this;\n\t},\n\n\topen: function() {\n\t\tif ( this._isOpen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar hasFocus,\n\t\t\toptions = this.options,\n\t\t\tuiDialog = this.uiDialog;\n\n\t\tthis._size();\n\t\tthis._position( options.position );\n\t\tuiDialog.show( options.show );\n\t\tthis.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null;\n\t\tthis.moveToTop( true );\n\n\t\t// prevent tabbing out of modal dialogs\n\t\tif ( options.modal ) {\n\t\t\tuiDialog.bind( \"keydown.ui-dialog\", function( event ) {\n\t\t\t\tif ( event.keyCode !== $.ui.keyCode.TAB ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar tabbables = $( \":tabbable\", this ),\n\t\t\t\t\tfirst = tabbables.filter( \":first\" ),\n\t\t\t\t\tlast  = tabbables.filter( \":last\" );\n\n\t\t\t\tif ( event.target === last[0] && !event.shiftKey ) {\n\t\t\t\t\tfirst.focus( 1 );\n\t\t\t\t\treturn false;\n\t\t\t\t} else if ( event.target === first[0] && event.shiftKey ) {\n\t\t\t\t\tlast.focus( 1 );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// set focus to the first tabbable element in the content area or the first button\n\t\t// if there are no tabbable elements, set focus on the dialog itself\n\t\thasFocus = this.element.find( \":tabbable\" );\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialogButtonPane.find( \":tabbable\" );\n\t\t\tif ( !hasFocus.length ) {\n\t\t\t\thasFocus = uiDialog;\n\t\t\t}\n\t\t}\n\t\thasFocus.eq( 0 ).focus();\n\n\t\tthis._isOpen = true;\n\t\tthis._trigger( \"open\" );\n\n\t\treturn this;\n\t},\n\n\t_createButtons: function( buttons ) {\n\t\tvar uiDialogButtonPane, uiButtonSet,\n\t\t\tthat = this,\n\t\t\thasButtons = false;\n\n\t\t// if we already have a button pane, remove it\n\t\tthis.uiDialogButtonPane.remove();\n\t\tthis.uiButtonSet.empty();\n\n\t\tif ( typeof buttons === \"object\" && buttons !== null ) {\n\t\t\t$.each( buttons, function() {\n\t\t\t\treturn !(hasButtons = true);\n\t\t\t});\n\t\t}\n\t\tif ( hasButtons ) {\n\t\t\t$.each( buttons, function( name, props ) {\n\t\t\t\tprops = $.isFunction( props ) ?\n\t\t\t\t\t{ click: props, text: name } :\n\t\t\t\t\tprops;\n\t\t\t\tvar button = $( \"<button type='button'>\" )\n\t\t\t\t\t.attr( props, true )\n\t\t\t\t\t.unbind( \"click\" )\n\t\t\t\t\t.click(function() {\n\t\t\t\t\t\tprops.click.apply( that.element[0], arguments );\n\t\t\t\t\t})\n\t\t\t\t\t.appendTo( that.uiButtonSet );\n\t\t\t\tif ( $.fn.button ) {\n\t\t\t\t\tbutton.button();\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.uiDialog.addClass( \"ui-dialog-buttons\" );\n\t\t\tthis.uiDialogButtonPane.appendTo( this.uiDialog );\n\t\t} else {\n\t\t\tthis.uiDialog.removeClass( \"ui-dialog-buttons\" );\n\t\t}\n\t},\n\n\t_makeDraggable: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tfunction filteredUi( ui ) {\n\t\t\treturn {\n\t\t\t\tposition: ui.position,\n\t\t\t\toffset: ui.offset\n\t\t\t};\n\t\t}\n\n\t\tthis.uiDialog.draggable({\n\t\t\tcancel: \".ui-dialog-content, .ui-dialog-titlebar-close\",\n\t\t\thandle: \".ui-dialog-titlebar\",\n\t\t\tcontainment: \"document\",\n\t\t\tstart: function( event, ui ) {\n\t\t\t\t$( this )\n\t\t\t\t\t.addClass( \"ui-dialog-dragging\" );\n\t\t\t\tthat._trigger( \"dragStart\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tdrag: function( event, ui ) {\n\t\t\t\tthat._trigger( \"drag\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tstop: function( event, ui ) {\n\t\t\t\toptions.position = [\n\t\t\t\t\tui.position.left - that.document.scrollLeft(),\n\t\t\t\t\tui.position.top - that.document.scrollTop()\n\t\t\t\t];\n\t\t\t\t$( this )\n\t\t\t\t\t.removeClass( \"ui-dialog-dragging\" );\n\t\t\t\tthat._trigger( \"dragStop\", event, filteredUi( ui ) );\n\t\t\t\t$.ui.dialog.overlay.resize();\n\t\t\t}\n\t\t});\n\t},\n\n\t_makeResizable: function( handles ) {\n\t\thandles = (handles === undefined ? this.options.resizable : handles);\n\t\tvar that = this,\n\t\t\toptions = this.options,\n\t\t\t// .ui-resizable has position: relative defined in the stylesheet\n\t\t\t// but dialogs have to use absolute or fixed positioning\n\t\t\tposition = this.uiDialog.css( \"position\" ),\n\t\t\tresizeHandles = typeof handles === 'string' ?\n\t\t\t\thandles\t:\n\t\t\t\t\"n,e,s,w,se,sw,ne,nw\";\n\n\t\tfunction filteredUi( ui ) {\n\t\t\treturn {\n\t\t\t\toriginalPosition: ui.originalPosition,\n\t\t\t\toriginalSize: ui.originalSize,\n\t\t\t\tposition: ui.position,\n\t\t\t\tsize: ui.size\n\t\t\t};\n\t\t}\n\n\t\tthis.uiDialog.resizable({\n\t\t\tcancel: \".ui-dialog-content\",\n\t\t\tcontainment: \"document\",\n\t\t\talsoResize: this.element,\n\t\t\tmaxWidth: options.maxWidth,\n\t\t\tmaxHeight: options.maxHeight,\n\t\t\tminWidth: options.minWidth,\n\t\t\tminHeight: this._minHeight(),\n\t\t\thandles: resizeHandles,\n\t\t\tstart: function( event, ui ) {\n\t\t\t\t$( this ).addClass( \"ui-dialog-resizing\" );\n\t\t\t\tthat._trigger( \"resizeStart\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tresize: function( event, ui ) {\n\t\t\t\tthat._trigger( \"resize\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tstop: function( event, ui ) {\n\t\t\t\t$( this ).removeClass( \"ui-dialog-resizing\" );\n\t\t\t\toptions.height = $( this ).height();\n\t\t\t\toptions.width = $( this ).width();\n\t\t\t\tthat._trigger( \"resizeStop\", event, filteredUi( ui ) );\n\t\t\t\t$.ui.dialog.overlay.resize();\n\t\t\t}\n\t\t})\n\t\t.css( \"position\", position )\n\t\t.find( \".ui-resizable-se\" )\n\t\t\t.addClass( \"ui-icon ui-icon-grip-diagonal-se\" );\n\t},\n\n\t_minHeight: function() {\n\t\tvar options = this.options;\n\n\t\tif ( options.height === \"auto\" ) {\n\t\t\treturn options.minHeight;\n\t\t} else {\n\t\t\treturn Math.min( options.minHeight, options.height );\n\t\t}\n\t},\n\n\t_position: function( position ) {\n\t\tvar myAt = [],\n\t\t\toffset = [ 0, 0 ],\n\t\t\tisVisible;\n\n\t\tif ( position ) {\n\t\t\t// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(\n\t//\t\tif (typeof position == 'string' || $.isArray(position)) {\n\t//\t\t\tmyAt = $.isArray(position) ? position : position.split(' ');\n\n\t\t\tif ( typeof position === \"string\" || (typeof position === \"object\" && \"0\" in position ) ) {\n\t\t\t\tmyAt = position.split ? position.split( \" \" ) : [ position[ 0 ], position[ 1 ] ];\n\t\t\t\tif ( myAt.length === 1 ) {\n\t\t\t\t\tmyAt[ 1 ] = myAt[ 0 ];\n\t\t\t\t}\n\n\t\t\t\t$.each( [ \"left\", \"top\" ], function( i, offsetPosition ) {\n\t\t\t\t\tif ( +myAt[ i ] === myAt[ i ] ) {\n\t\t\t\t\t\toffset[ i ] = myAt[ i ];\n\t\t\t\t\t\tmyAt[ i ] = offsetPosition;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tposition = {\n\t\t\t\t\tmy: myAt.join( \" \" ),\n\t\t\t\t\tat: myAt.join( \" \" ),\n\t\t\t\t\toffset: offset.join( \" \" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tposition = $.extend( {}, $.ui.dialog.prototype.options.position, position );\n\t\t} else {\n\t\t\tposition = $.ui.dialog.prototype.options.position;\n\t\t}\n\n\t\t// need to show the dialog to get the actual offset in the position plugin\n\t\tisVisible = this.uiDialog.is( \":visible\" );\n\t\tif ( !isVisible ) {\n\t\t\tthis.uiDialog.show();\n\t\t}\n\t\tthis.uiDialog.position( position );\n\t\tif ( !isVisible ) {\n\t\t\tthis.uiDialog.hide();\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar that = this,\n\t\t\tresizableOptions = {},\n\t\t\tresize = false;\n\n\t\t$.each( options, function( key, value ) {\n\t\t\tthat._setOption( key, value );\n\n\t\t\tif ( key in sizeRelatedOptions ) {\n\t\t\t\tresize = true;\n\t\t\t}\n\t\t\tif ( key in resizableRelatedOptions ) {\n\t\t\t\tresizableOptions[ key ] = value;\n\t\t\t}\n\t\t});\n\n\t\tif ( resize ) {\n\t\t\tthis._size();\n\t\t}\n\t\tif ( this.uiDialog.is( \":data(resizable)\" ) ) {\n\t\t\tthis.uiDialog.resizable( \"option\", resizableOptions );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar isDraggable, isResizable,\n\t\t\tuiDialog = this.uiDialog;\n\n\t\tswitch ( key ) {\n\t\t\tcase \"buttons\":\n\t\t\t\tthis._createButtons( value );\n\t\t\t\tbreak;\n\t\t\tcase \"closeText\":\n\t\t\t\t// ensure that we always pass a string\n\t\t\t\tthis.uiDialogTitlebarCloseText.text( \"\" + value );\n\t\t\t\tbreak;\n\t\t\tcase \"dialogClass\":\n\t\t\t\tuiDialog\n\t\t\t\t\t.removeClass( this.options.dialogClass )\n\t\t\t\t\t.addClass( uiDialogClasses + value );\n\t\t\t\tbreak;\n\t\t\tcase \"disabled\":\n\t\t\t\tif ( value ) {\n\t\t\t\t\tuiDialog.addClass( \"ui-dialog-disabled\" );\n\t\t\t\t} else {\n\t\t\t\t\tuiDialog.removeClass( \"ui-dialog-disabled\" );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"draggable\":\n\t\t\t\tisDraggable = uiDialog.is( \":data(draggable)\" );\n\t\t\t\tif ( isDraggable && !value ) {\n\t\t\t\t\tuiDialog.draggable( \"destroy\" );\n\t\t\t\t}\n\n\t\t\t\tif ( !isDraggable && value ) {\n\t\t\t\t\tthis._makeDraggable();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"position\":\n\t\t\t\tthis._position( value );\n\t\t\t\tbreak;\n\t\t\tcase \"resizable\":\n\t\t\t\t// currently resizable, becoming non-resizable\n\t\t\t\tisResizable = uiDialog.is( \":data(resizable)\" );\n\t\t\t\tif ( isResizable && !value ) {\n\t\t\t\t\tuiDialog.resizable( \"destroy\" );\n\t\t\t\t}\n\n\t\t\t\t// currently resizable, changing handles\n\t\t\t\tif ( isResizable && typeof value === \"string\" ) {\n\t\t\t\t\tuiDialog.resizable( \"option\", \"handles\", value );\n\t\t\t\t}\n\n\t\t\t\t// currently non-resizable, becoming resizable\n\t\t\t\tif ( !isResizable && value !== false ) {\n\t\t\t\t\tthis._makeResizable( value );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"title\":\n\t\t\t\t// convert whatever was passed in o a string, for html() to not throw up\n\t\t\t\t$( \".ui-dialog-title\", this.uiDialogTitlebar )\n\t\t\t\t\t.html( \"\" + ( value || \"&#160;\" ) );\n\t\t\t\tbreak;\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_size: function() {\n\t\t/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content\n\t\t * divs will both have width and height set, so we need to reset them\n\t\t */\n\t\tvar nonContentHeight, minContentHeight, autoHeight,\n\t\t\toptions = this.options,\n\t\t\tisVisible = this.uiDialog.is( \":visible\" );\n\n\t\t// reset content sizing\n\t\tthis.element.show().css({\n\t\t\twidth: \"auto\",\n\t\t\tminHeight: 0,\n\t\t\theight: 0\n\t\t});\n\n\t\tif ( options.minWidth > options.width ) {\n\t\t\toptions.width = options.minWidth;\n\t\t}\n\n\t\t// reset wrapper sizing\n\t\t// determine the height of all the non-content elements\n\t\tnonContentHeight = this.uiDialog.css({\n\t\t\t\theight: \"auto\",\n\t\t\t\twidth: options.width\n\t\t\t})\n\t\t\t.outerHeight();\n\t\tminContentHeight = Math.max( 0, options.minHeight - nonContentHeight );\n\n\t\tif ( options.height === \"auto\" ) {\n\t\t\t// only needed for IE6 support\n\t\t\tif ( $.support.minHeight ) {\n\t\t\t\tthis.element.css({\n\t\t\t\t\tminHeight: minContentHeight,\n\t\t\t\t\theight: \"auto\"\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.uiDialog.show();\n\t\t\t\tautoHeight = this.element.css( \"height\", \"auto\" ).height();\n\t\t\t\tif ( !isVisible ) {\n\t\t\t\t\tthis.uiDialog.hide();\n\t\t\t\t}\n\t\t\t\tthis.element.height( Math.max( autoHeight, minContentHeight ) );\n\t\t\t}\n\t\t} else {\n\t\t\tthis.element.height( Math.max( options.height - nonContentHeight, 0 ) );\n\t\t}\n\n\t\tif (this.uiDialog.is( \":data(resizable)\" ) ) {\n\t\t\tthis.uiDialog.resizable( \"option\", \"minHeight\", this._minHeight() );\n\t\t}\n\t}\n});\n\n$.extend($.ui.dialog, {\n\tuuid: 0,\n\tmaxZ: 0,\n\n\tgetTitleId: function($el) {\n\t\tvar id = $el.attr( \"id\" );\n\t\tif ( !id ) {\n\t\t\tthis.uuid += 1;\n\t\t\tid = this.uuid;\n\t\t}\n\t\treturn \"ui-dialog-title-\" + id;\n\t},\n\n\toverlay: function( dialog ) {\n\t\tthis.$el = $.ui.dialog.overlay.create( dialog );\n\t}\n});\n\n$.extend( $.ui.dialog.overlay, {\n\tinstances: [],\n\t// reuse old instances due to IE memory leak with alpha transparency (see #5185)\n\toldInstances: [],\n\tmaxZ: 0,\n\tevents: $.map(\n\t\t\"focus,mousedown,mouseup,keydown,keypress,click\".split( \",\" ),\n\t\tfunction( event ) {\n\t\t\treturn event + \".dialog-overlay\";\n\t\t}\n\t).join( \" \" ),\n\tcreate: function( dialog ) {\n\t\tif ( this.instances.length === 0 ) {\n\t\t\t// prevent use of anchors and inputs\n\t\t\t// we use a setTimeout in case the overlay is created from an\n\t\t\t// event that we're going to be cancelling (see #2804)\n\t\t\tsetTimeout(function() {\n\t\t\t\t// handle $(el).dialog().dialog('close') (see #4065)\n\t\t\t\tif ( $.ui.dialog.overlay.instances.length ) {\n\t\t\t\t\t$( document ).bind( $.ui.dialog.overlay.events, function( event ) {\n\t\t\t\t\t\t// stop events if the z-index of the target is < the z-index of the overlay\n\t\t\t\t\t\t// we cannot return true when we don't want to cancel the event (#3523)\n\t\t\t\t\t\tif ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, 1 );\n\n\t\t\t// handle window resize\n\t\t\t$( window ).bind( \"resize.dialog-overlay\", $.ui.dialog.overlay.resize );\n\t\t}\n\n\t\tvar $el = ( this.oldInstances.pop() || $( \"<div>\" ).addClass( \"ui-widget-overlay\" ) );\n\n\t\t// allow closing by pressing the escape key\n\t\t$( document ).bind( \"keydown.dialog-overlay\", function( event ) {\n\t\t\tvar instances = $.ui.dialog.overlay.instances;\n\t\t\t// only react to the event if we're the top overlay\n\t\t\tif ( instances.length !== 0 && instances[ instances.length - 1 ] === $el &&\n\t\t\t\tdialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&\n\t\t\t\tevent.keyCode === $.ui.keyCode.ESCAPE ) {\n\n\t\t\t\tdialog.close( event );\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t});\n\n\t\t$el.appendTo( document.body ).css({\n\t\t\twidth: this.width(),\n\t\t\theight: this.height()\n\t\t});\n\n\t\tif ( $.fn.bgiframe ) {\n\t\t\t$el.bgiframe();\n\t\t}\n\n\t\tthis.instances.push( $el );\n\t\treturn $el;\n\t},\n\n\tdestroy: function( $el ) {\n\t\tvar indexOf = $.inArray( $el, this.instances ),\n\t\t\tmaxZ = 0;\n\n\t\tif ( indexOf !== -1 ) {\n\t\t\tthis.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] );\n\t\t}\n\n\t\tif ( this.instances.length === 0 ) {\n\t\t\t$( [ document, window ] ).unbind( \".dialog-overlay\" );\n\t\t}\n\n\t\t$el.height( 0 ).width( 0 ).remove();\n\n\t\t// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)\n\t\t$.each( this.instances, function() {\n\t\t\tmaxZ = Math.max( maxZ, this.css( \"z-index\" ) );\n\t\t});\n\t\tthis.maxZ = maxZ;\n\t},\n\n\theight: function() {\n\t\tvar scrollHeight,\n\t\t\toffsetHeight;\n\t\t// handle IE\n\t\tif ( $.browser.msie ) {\n\t\t\tscrollHeight = Math.max(\n\t\t\t\tdocument.documentElement.scrollHeight,\n\t\t\t\tdocument.body.scrollHeight\n\t\t\t);\n\t\t\toffsetHeight = Math.max(\n\t\t\t\tdocument.documentElement.offsetHeight,\n\t\t\t\tdocument.body.offsetHeight\n\t\t\t);\n\n\t\t\tif ( scrollHeight < offsetHeight ) {\n\t\t\t\treturn $( window ).height() + \"px\";\n\t\t\t} else {\n\t\t\t\treturn scrollHeight + \"px\";\n\t\t\t}\n\t\t// handle \"good\" browsers\n\t\t} else {\n\t\t\treturn $( document ).height() + \"px\";\n\t\t}\n\t},\n\n\twidth: function() {\n\t\tvar scrollWidth,\n\t\t\toffsetWidth;\n\t\t// handle IE\n\t\tif ( $.browser.msie ) {\n\t\t\tscrollWidth = Math.max(\n\t\t\t\tdocument.documentElement.scrollWidth,\n\t\t\t\tdocument.body.scrollWidth\n\t\t\t);\n\t\t\toffsetWidth = Math.max(\n\t\t\t\tdocument.documentElement.offsetWidth,\n\t\t\t\tdocument.body.offsetWidth\n\t\t\t);\n\n\t\t\tif ( scrollWidth < offsetWidth ) {\n\t\t\t\treturn $( window ).width() + \"px\";\n\t\t\t} else {\n\t\t\t\treturn scrollWidth + \"px\";\n\t\t\t}\n\t\t// handle \"good\" browsers\n\t\t} else {\n\t\t\treturn $( document ).width() + \"px\";\n\t\t}\n\t},\n\n\tresize: function() {\n\t\t/* If the dialog is draggable and the user drags it past the\n\t\t * right edge of the window, the document becomes wider so we\n\t\t * need to stretch the overlay. If the user then drags the\n\t\t * dialog back to the left, the document will become narrower,\n\t\t * so we need to shrink the overlay to the appropriate size.\n\t\t * This is handled by shrinking the overlay before setting it\n\t\t * to the full document size.\n\t\t */\n\t\tvar $overlays = $( [] );\n\t\t$.each( $.ui.dialog.overlay.instances, function() {\n\t\t\t$overlays = $overlays.add( this );\n\t\t});\n\n\t\t$overlays.css({\n\t\t\twidth: 0,\n\t\t\theight: 0\n\t\t}).css({\n\t\t\twidth: $.ui.dialog.overlay.width(),\n\t\t\theight: $.ui.dialog.overlay.height()\n\t\t});\n\t}\n});\n\n$.extend( $.ui.dialog.overlay.prototype, {\n\tdestroy: function() {\n\t\t$.ui.dialog.overlay.destroy( this.$el );\n\t}\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.draggable.js",
    "content": "/*!\n * jQuery UI Draggable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Draggables\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\n$.widget(\"ui.draggable\", $.ui.mouse, {\n\tversion: \"@VERSION\",\n\twidgetEventPrefix: \"drag\",\n\toptions: {\n\t\taddClasses: true,\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectToSortable: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\tiframeFix: false,\n\t\topacity: false,\n\t\trefreshPositions: false,\n\t\trevert: false,\n\t\trevertDuration: 500,\n\t\tscope: \"default\",\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tsnap: false,\n\t\tsnapMode: \"both\",\n\t\tsnapTolerance: 20,\n\t\tstack: false,\n\t\tzIndex: false\n\t},\n\t_create: function() {\n\n\t\tif (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css(\"position\")))\n\t\t\tthis.element[0].style.position = 'relative';\n\n\t\t(this.options.addClasses && this.element.addClass(\"ui-draggable\"));\n\t\t(this.options.disabled && this.element.addClass(\"ui-draggable-disabled\"));\n\n\t\tthis._mouseInit();\n\n\t},\n\n\t_destroy: function() {\n\t\tthis.element.removeClass( \"ui-draggable ui-draggable-dragging ui-draggable-disabled\" );\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function(event) {\n\n\t\tvar o = this.options;\n\n\t\t// among others, prevent a drag on a resizable-handle\n\t\tif (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))\n\t\t\treturn false;\n\n\t\t//Quit if we're not on a valid handle\n\t\tthis.handle = this._getHandle(event);\n\t\tif (!this.handle)\n\t\t\treturn false;\n\t\t\n\t\t$(o.iframeFix === true ? \"iframe\" : o.iframeFix).each(function() {\n\t\t\t$('<div class=\"ui-draggable-iframeFix\" style=\"background: #fff;\"></div>')\n\t\t\t.css({\n\t\t\t\twidth: this.offsetWidth+\"px\", height: this.offsetHeight+\"px\",\n\t\t\t\tposition: \"absolute\", opacity: \"0.001\", zIndex: 1000\n\t\t\t})\n\t\t\t.css($(this).offset())\n\t\t\t.appendTo(\"body\");\n\t\t});\n\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function(event) {\n\n\t\tvar o = this.options;\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper(event);\n\n\t\tthis.helper.addClass(\"ui-draggable-dragging\");\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//If ddmanager is used for droppables, set the global draggable\n\t\tif($.ui.ddmanager)\n\t\t\t$.ui.ddmanager.current = this;\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Store the helper's css position\n\t\tthis.cssPosition = this.helper.css(\"position\");\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.positionAbs = this.element.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend(this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\n\t\t});\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this.position = this._generatePosition(event);\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied\n\t\t(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\n\n\t\t//Set a containment if given in the options\n\t\tif(o.containment)\n\t\t\tthis._setContainment();\n\n\t\t//Trigger event + callbacks\n\t\tif(this._trigger(\"start\", event) === false) {\n\t\t\tthis._clear();\n\t\t\treturn false;\n\t\t}\n\n\t\t//Recache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//Prepare the droppable offsets\n\t\tif ($.ui.ddmanager && !o.dropBehaviour)\n\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\n\t\t\n\t\tthis._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position\n\t\t\n\t\t//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)\n\t\tif ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);\n\t\t\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function(event, noPropagation) {\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition(event);\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\t//Call plugins and callbacks and use the resulting position if something is returned\n\t\tif (!noPropagation) {\n\t\t\tvar ui = this._uiHash();\n\t\t\tif(this._trigger('drag', event, ui) === false) {\n\t\t\t\tthis._mouseUp({});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.position = ui.position;\n\t\t}\n\n\t\tif(!this.options.axis || this.options.axis != \"y\") this.helper[0].style.left = this.position.left+'px';\n\t\tif(!this.options.axis || this.options.axis != \"x\") this.helper[0].style.top = this.position.top+'px';\n\t\tif($.ui.ddmanager) $.ui.ddmanager.drag(this, event);\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function(event) {\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tvar dropped = false;\n\t\tif ($.ui.ddmanager && !this.options.dropBehaviour)\n\t\t\tdropped = $.ui.ddmanager.drop(this, event);\n\n\t\t//if a drop comes from outside (a sortable)\n\t\tif(this.dropped) {\n\t\t\tdropped = this.dropped;\n\t\t\tthis.dropped = false;\n\t\t}\n\t\t\n\t\t//if the original element is no longer in the DOM don't bother to continue (see #8269)\n\t\tvar element = this.element[0], elementInDom = false;\n\t\twhile ( element && (element = element.parentNode) ) {\n\t\t\tif (element == document ) {\n\t\t\t\telementInDom = true;\n\t\t\t}\n\t\t}\n\t\tif ( !elementInDom && this.options.helper === \"original\" )\n\t\t\treturn false;\n\n\t\tif((this.options.revert == \"invalid\" && !dropped) || (this.options.revert == \"valid\" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {\n\t\t\tvar that = this;\n\t\t\t$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {\n\t\t\t\tif(that._trigger(\"stop\", event) !== false) {\n\t\t\t\t\tthat._clear();\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tif(this._trigger(\"stop\", event) !== false) {\n\t\t\t\tthis._clear();\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\t\n\t_mouseUp: function(event) {\n\t\tif (this.options.iframeFix === true) {\n\t\t\t$(\"div.ui-draggable-iframeFix\").each(function() { \n\t\t\t\tthis.parentNode.removeChild(this); \n\t\t\t}); //Remove frame helpers\n\t\t}\n\t\t\n\t\t//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)\n\t\tif( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);\n\t\t\n\t\treturn $.ui.mouse.prototype._mouseUp.call(this, event);\n\t},\n\t\n\tcancel: function() {\n\t\t\n\t\tif(this.helper.is(\".ui-draggable-dragging\")) {\n\t\t\tthis._mouseUp({});\n\t\t} else {\n\t\t\tthis._clear();\n\t\t}\n\t\t\n\t\treturn this;\n\t\t\n\t},\n\n\t_getHandle: function(event) {\n\n\t\tvar handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;\n\t\t$(this.options.handle, this.element)\n\t\t\t.find(\"*\")\n\t\t\t.andSelf()\n\t\t\t.each(function() {\n\t\t\t\tif(this == event.target) handle = true;\n\t\t\t});\n\n\t\treturn handle;\n\n\t},\n\n\t_createHelper: function(event) {\n\n\t\tvar o = this.options;\n\t\tvar helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);\n\n\t\tif(!helper.parents('body').length)\n\t\t\thelper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));\n\n\t\tif(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css(\"position\")))\n\t\t\thelper.css(\"position\", \"absolute\");\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function(obj) {\n\t\tif (typeof obj == 'string') {\n\t\t\tobj = obj.split(' ');\n\t\t}\n\t\tif ($.isArray(obj)) {\n\t\t\tobj = {left: +obj[0], top: +obj[1] || 0};\n\t\t}\n\t\tif ('left' in obj) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ('right' in obj) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ('top' in obj) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ('bottom' in obj) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that\n\t\t//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\n\t\tif(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\tif((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information\n\t\t|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix\n\t\t\tpo = { top: 0, left: 0 };\n\n\t\treturn {\n\t\t\ttop: po.top + (parseInt(this.offsetParent.css(\"borderTopWidth\"),10) || 0),\n\t\t\tleft: po.left + (parseInt(this.offsetParent.css(\"borderLeftWidth\"),10) || 0)\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif(this.cssPosition == \"relative\") {\n\t\t\tvar p = this.element.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - (parseInt(this.helper.css(\"top\"),10) || 0) + this.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - (parseInt(this.helper.css(\"left\"),10) || 0) + this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: (parseInt(this.element.css(\"marginLeft\"),10) || 0),\n\t\t\ttop: (parseInt(this.element.css(\"marginTop\"),10) || 0),\n\t\t\tright: (parseInt(this.element.css(\"marginRight\"),10) || 0),\n\t\t\tbottom: (parseInt(this.element.css(\"marginBottom\"),10) || 0)\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar o = this.options;\n\t\tif(o.containment == 'parent') o.containment = this.helper[0].parentNode;\n\t\tif(o.containment == 'document' || o.containment == 'window') this.containment = [\n\t\t\to.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,\n\t\t\to.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,\n\t\t\t(o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,\n\t\t\t(o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\n\t\t];\n\n\t\tif(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {\n\t\t\tvar c = $(o.containment);\n\t\t\tvar ce = c[0]; if(!ce) return;\n\t\t\tvar co = c.offset();\n\t\t\tvar over = ($(ce).css(\"overflow\") != 'hidden');\n\n\t\t\tthis.containment = [\n\t\t\t\t(parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingLeft\"),10) || 0),\n\t\t\t\t(parseInt($(ce).css(\"borderTopWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingTop\"),10) || 0),\n\t\t\t\t(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingRight\"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,\n\t\t\t\t(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingBottom\"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom\n\t\t\t];\n\t\t\tthis.relative_container = c;\n\n\t\t} else if(o.containment.constructor == Array) {\n\t\t\tthis.containment = o.containment;\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function(d, pos) {\n\n\t\tif(!pos) pos = this.position;\n\t\tvar mod = d == \"absolute\" ? 1 : -1;\n\t\tvar o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpos.top\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t+ this.offset.relative.top * mod\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t+ this.offset.parent.top * mod\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpos.left\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t+ this.offset.relative.left * mod\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t+ this.offset.parent.left * mod\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t- ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function(event) {\n\n\t\tvar o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\t\tvar pageX = event.pageX;\n\t\tvar pageY = event.pageY;\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif(this.originalPosition) { //If we are not dragging yet, we won't check for options\n\t\t\tvar containment;\n\t\t\tif(this.containment) {\n\t\t\tif (this.relative_container){\n\t\t\t\tvar co = this.relative_container.offset();\n\t\t\t\tcontainment = [ this.containment[0] + co.left,\n\t\t\t\t\tthis.containment[1] + co.top,\n\t\t\t\t\tthis.containment[2] + co.left,\n\t\t\t\t\tthis.containment[3] + co.top ];\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcontainment = this.containment;\n\t\t\t}\n\n\t\t\t\tif(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;\n\t\t\t\tif(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;\n\t\t\t\tif(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;\n\t\t\t\tif(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;\n\t\t\t}\n\n\t\t\tif(o.grid) {\n\t\t\t\t//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)\n\t\t\t\tvar top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;\n\t\t\t\tpageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;\n\n\t\t\t\tvar left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;\n\t\t\t\tpageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpageY\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t- this.offset.click.top\t\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\t- this.offset.relative.top\t\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t- this.offset.parent.top\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpageX\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t- this.offset.click.left\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\t- this.offset.relative.left\t\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t- this.offset.parent.left\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_clear: function() {\n\t\tthis.helper.removeClass(\"ui-draggable-dragging\");\n\t\tif(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();\n\t\t//if($.ui.ddmanager) $.ui.ddmanager.current = null;\n\t\tthis.helper = null;\n\t\tthis.cancelHelperRemoval = false;\n\t},\n\n\t// From now on bulk stuff - mainly helpers\n\n\t_trigger: function(type, event, ui) {\n\t\tui = ui || this._uiHash();\n\t\t$.ui.plugin.call(this, type, [event, ui]);\n\t\tif(type == \"drag\") this.positionAbs = this._convertPositionTo(\"absolute\"); //The absolute position has to be recalculated after plugins\n\t\treturn $.Widget.prototype._trigger.call(this, type, event, ui);\n\t},\n\n\tplugins: {},\n\n\t_uiHash: function(event) {\n\t\treturn {\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\toriginalPosition: this.originalPosition,\n\t\t\toffset: this.positionAbs\n\t\t};\n\t}\n\n});\n\n$.ui.plugin.add(\"draggable\", \"connectToSortable\", {\n\tstart: function(event, ui) {\n\n\t\tvar inst = $(this).data(\"draggable\"), o = inst.options,\n\t\t\tuiSortable = $.extend({}, ui, { item: inst.element });\n\t\tinst.sortables = [];\n\t\t$(o.connectToSortable).each(function() {\n\t\t\tvar sortable = $.data(this, 'sortable');\n\t\t\tif (sortable && !sortable.options.disabled) {\n\t\t\t\tinst.sortables.push({\n\t\t\t\t\tinstance: sortable,\n\t\t\t\t\tshouldRevert: sortable.options.revert\n\t\t\t\t});\n\t\t\t\tsortable.refreshPositions();\t// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).\n\t\t\t\tsortable._trigger(\"activate\", event, uiSortable);\n\t\t\t}\n\t\t});\n\n\t},\n\tstop: function(event, ui) {\n\n\t\t//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper\n\t\tvar inst = $(this).data(\"draggable\"),\n\t\t\tuiSortable = $.extend({}, ui, { item: inst.element });\n\n\t\t$.each(inst.sortables, function() {\n\t\t\tif(this.instance.isOver) {\n\n\t\t\t\tthis.instance.isOver = 0;\n\n\t\t\t\tinst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance\n\t\t\t\tthis.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)\n\n\t\t\t\t//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'\n\t\t\t\tif(this.shouldRevert) this.instance.options.revert = true;\n\n\t\t\t\t//Trigger the stop of the sortable\n\t\t\t\tthis.instance._mouseStop(event);\n\n\t\t\t\tthis.instance.options.helper = this.instance.options._helper;\n\n\t\t\t\t//If the helper has been the original item, restore properties in the sortable\n\t\t\t\tif(inst.options.helper == 'original')\n\t\t\t\t\tthis.instance.currentItem.css({ top: 'auto', left: 'auto' });\n\n\t\t\t} else {\n\t\t\t\tthis.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance\n\t\t\t\tthis.instance._trigger(\"deactivate\", event, uiSortable);\n\t\t\t}\n\n\t\t});\n\n\t},\n\tdrag: function(event, ui) {\n\n\t\tvar inst = $(this).data(\"draggable\"), that = this;\n\n\t\tvar checkPos = function(o) {\n\t\t\tvar dyClick = this.offset.click.top, dxClick = this.offset.click.left;\n\t\t\tvar helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;\n\t\t\tvar itemHeight = o.height, itemWidth = o.width;\n\t\t\tvar itemTop = o.top, itemLeft = o.left;\n\n\t\t\treturn $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);\n\t\t};\n\n\t\t$.each(inst.sortables, function(i) {\n\t\t\t\n\t\t\t//Copy over some variables to allow calling the sortable's native _intersectsWith\n\t\t\tthis.instance.positionAbs = inst.positionAbs;\n\t\t\tthis.instance.helperProportions = inst.helperProportions;\n\t\t\tthis.instance.offset.click = inst.offset.click;\n\t\t\t\n\t\t\tif(this.instance._intersectsWith(this.instance.containerCache)) {\n\n\t\t\t\t//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once\n\t\t\t\tif(!this.instance.isOver) {\n\n\t\t\t\t\tthis.instance.isOver = 1;\n\t\t\t\t\t//Now we fake the start of dragging for the sortable instance,\n\t\t\t\t\t//by cloning the list group item, appending it to the sortable and using it as inst.currentItem\n\t\t\t\t\t//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)\n\t\t\t\t\tthis.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data(\"sortable-item\", true);\n\t\t\t\t\tthis.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it\n\t\t\t\t\tthis.instance.options.helper = function() { return ui.helper[0]; };\n\n\t\t\t\t\tevent.target = this.instance.currentItem[0];\n\t\t\t\t\tthis.instance._mouseCapture(event, true);\n\t\t\t\t\tthis.instance._mouseStart(event, true, true);\n\n\t\t\t\t\t//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes\n\t\t\t\t\tthis.instance.offset.click.top = inst.offset.click.top;\n\t\t\t\t\tthis.instance.offset.click.left = inst.offset.click.left;\n\t\t\t\t\tthis.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;\n\t\t\t\t\tthis.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;\n\n\t\t\t\t\tinst._trigger(\"toSortable\", event);\n\t\t\t\t\tinst.dropped = this.instance.element; //draggable revert needs that\n\t\t\t\t\t//hack so receive/update callbacks work (mostly)\n\t\t\t\t\tinst.currentItem = inst.element;\n\t\t\t\t\tthis.instance.fromOutside = inst;\n\n\t\t\t\t}\n\n\t\t\t\t//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable\n\t\t\t\tif(this.instance.currentItem) this.instance._mouseDrag(event);\n\n\t\t\t} else {\n\n\t\t\t\t//If it doesn't intersect with the sortable, and it intersected before,\n\t\t\t\t//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval\n\t\t\t\tif(this.instance.isOver) {\n\n\t\t\t\t\tthis.instance.isOver = 0;\n\t\t\t\t\tthis.instance.cancelHelperRemoval = true;\n\t\t\t\t\t\n\t\t\t\t\t//Prevent reverting on this forced stop\n\t\t\t\t\tthis.instance.options.revert = false;\n\t\t\t\t\t\n\t\t\t\t\t// The out event needs to be triggered independently\n\t\t\t\t\tthis.instance._trigger('out', event, this.instance._uiHash(this.instance));\n\t\t\t\t\t\n\t\t\t\t\tthis.instance._mouseStop(event, true);\n\t\t\t\t\tthis.instance.options.helper = this.instance.options._helper;\n\n\t\t\t\t\t//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size\n\t\t\t\t\tthis.instance.currentItem.remove();\n\t\t\t\t\tif(this.instance.placeholder) this.instance.placeholder.remove();\n\n\t\t\t\t\tinst._trigger(\"fromSortable\", event);\n\t\t\t\t\tinst.dropped = false; //draggable revert needs that\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t});\n\n\t}\n});\n\n$.ui.plugin.add(\"draggable\", \"cursor\", {\n\tstart: function(event, ui) {\n\t\tvar t = $('body'), o = $(this).data('draggable').options;\n\t\tif (t.css(\"cursor\")) o._cursor = t.css(\"cursor\");\n\t\tt.css(\"cursor\", o.cursor);\n\t},\n\tstop: function(event, ui) {\n\t\tvar o = $(this).data('draggable').options;\n\t\tif (o._cursor) $('body').css(\"cursor\", o._cursor);\n\t}\n});\n\n$.ui.plugin.add(\"draggable\", \"opacity\", {\n\tstart: function(event, ui) {\n\t\tvar t = $(ui.helper), o = $(this).data('draggable').options;\n\t\tif(t.css(\"opacity\")) o._opacity = t.css(\"opacity\");\n\t\tt.css('opacity', o.opacity);\n\t},\n\tstop: function(event, ui) {\n\t\tvar o = $(this).data('draggable').options;\n\t\tif(o._opacity) $(ui.helper).css('opacity', o._opacity);\n\t}\n});\n\n$.ui.plugin.add(\"draggable\", \"scroll\", {\n\tstart: function(event, ui) {\n\t\tvar i = $(this).data(\"draggable\");\n\t\tif(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();\n\t},\n\tdrag: function(event, ui) {\n\n\t\tvar i = $(this).data(\"draggable\"), o = i.options, scrolled = false;\n\n\t\tif(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {\n\n\t\t\tif(!o.axis || o.axis != 'x') {\n\t\t\t\tif((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)\n\t\t\t\t\ti.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;\n\t\t\t\telse if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)\n\t\t\t\t\ti.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;\n\t\t\t}\n\n\t\t\tif(!o.axis || o.axis != 'y') {\n\t\t\t\tif((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)\n\t\t\t\t\ti.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;\n\t\t\t\telse if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)\n\t\t\t\t\ti.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif(!o.axis || o.axis != 'x') {\n\t\t\t\tif(event.pageY - $(document).scrollTop() < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\n\t\t\t\telse if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\n\t\t\t}\n\n\t\t\tif(!o.axis || o.axis != 'y') {\n\t\t\t\tif(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\n\t\t\t\telse if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\n\t\t\t}\n\n\t\t}\n\n\t\tif(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)\n\t\t\t$.ui.ddmanager.prepareOffsets(i, event);\n\n\t}\n});\n\n$.ui.plugin.add(\"draggable\", \"snap\", {\n\tstart: function(event, ui) {\n\n\t\tvar i = $(this).data(\"draggable\"), o = i.options;\n\t\ti.snapElements = [];\n\n\t\t$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {\n\t\t\tvar $t = $(this); var $o = $t.offset();\n\t\t\tif(this != i.element[0]) i.snapElements.push({\n\t\t\t\titem: this,\n\t\t\t\twidth: $t.outerWidth(), height: $t.outerHeight(),\n\t\t\t\ttop: $o.top, left: $o.left\n\t\t\t});\n\t\t});\n\n\t},\n\tdrag: function(event, ui) {\n\n\t\tvar inst = $(this).data(\"draggable\"), o = inst.options;\n\t\tvar d = o.snapTolerance;\n\n\t\tvar x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,\n\t\t\ty1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;\n\n\t\tfor (var i = inst.snapElements.length - 1; i >= 0; i--){\n\n\t\t\tvar l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,\n\t\t\t\tt = inst.snapElements[i].top, b = t + inst.snapElements[i].height;\n\n\t\t\t//Yes, I know, this is insane ;)\n\t\t\tif(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {\n\t\t\t\tif(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));\n\t\t\t\tinst.snapElements[i].snapping = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif(o.snapMode != 'inner') {\n\t\t\t\tvar ts = Math.abs(t - y2) <= d;\n\t\t\t\tvar bs = Math.abs(b - y1) <= d;\n\t\t\t\tvar ls = Math.abs(l - x2) <= d;\n\t\t\t\tvar rs = Math.abs(r - x1) <= d;\n\t\t\t\tif(ts) ui.position.top = inst._convertPositionTo(\"relative\", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;\n\t\t\t\tif(bs) ui.position.top = inst._convertPositionTo(\"relative\", { top: b, left: 0 }).top - inst.margins.top;\n\t\t\t\tif(ls) ui.position.left = inst._convertPositionTo(\"relative\", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;\n\t\t\t\tif(rs) ui.position.left = inst._convertPositionTo(\"relative\", { top: 0, left: r }).left - inst.margins.left;\n\t\t\t}\n\n\t\t\tvar first = (ts || bs || ls || rs);\n\n\t\t\tif(o.snapMode != 'outer') {\n\t\t\t\tvar ts = Math.abs(t - y1) <= d;\n\t\t\t\tvar bs = Math.abs(b - y2) <= d;\n\t\t\t\tvar ls = Math.abs(l - x1) <= d;\n\t\t\t\tvar rs = Math.abs(r - x2) <= d;\n\t\t\t\tif(ts) ui.position.top = inst._convertPositionTo(\"relative\", { top: t, left: 0 }).top - inst.margins.top;\n\t\t\t\tif(bs) ui.position.top = inst._convertPositionTo(\"relative\", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;\n\t\t\t\tif(ls) ui.position.left = inst._convertPositionTo(\"relative\", { top: 0, left: l }).left - inst.margins.left;\n\t\t\t\tif(rs) ui.position.left = inst._convertPositionTo(\"relative\", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;\n\t\t\t}\n\n\t\t\tif(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))\n\t\t\t\t(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));\n\t\t\tinst.snapElements[i].snapping = (ts || bs || ls || rs || first);\n\n\t\t};\n\n\t}\n});\n\n$.ui.plugin.add(\"draggable\", \"stack\", {\n\tstart: function(event, ui) {\n\n\t\tvar o = $(this).data(\"draggable\").options;\n\n\t\tvar group = $.makeArray($(o.stack)).sort(function(a,b) {\n\t\t\treturn (parseInt($(a).css(\"zIndex\"),10) || 0) - (parseInt($(b).css(\"zIndex\"),10) || 0);\n\t\t});\n\t\tif (!group.length) { return; }\n\t\t\n\t\tvar min = parseInt(group[0].style.zIndex) || 0;\n\t\t$(group).each(function(i) {\n\t\t\tthis.style.zIndex = min + i;\n\t\t});\n\n\t\tthis[0].style.zIndex = min + group.length;\n\n\t}\n});\n\n$.ui.plugin.add(\"draggable\", \"zIndex\", {\n\tstart: function(event, ui) {\n\t\tvar t = $(ui.helper), o = $(this).data(\"draggable\").options;\n\t\tif(t.css(\"zIndex\")) o._zIndex = t.css(\"zIndex\");\n\t\tt.css('zIndex', o.zIndex);\n\t},\n\tstop: function(event, ui) {\n\t\tvar o = $(this).data(\"draggable\").options;\n\t\tif(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);\n\t}\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.droppable.js",
    "content": "/*!\n * jQuery UI Droppable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Droppables\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.draggable.js\n */\n(function( $, undefined ) {\n\n$.widget(\"ui.droppable\", {\n\tversion: \"@VERSION\",\n\twidgetEventPrefix: \"drop\",\n\toptions: {\n\t\taccept: '*',\n\t\tactiveClass: false,\n\t\taddClasses: true,\n\t\tgreedy: false,\n\t\thoverClass: false,\n\t\tscope: 'default',\n\t\ttolerance: 'intersect'\n\t},\n\t_create: function() {\n\n\t\tvar o = this.options, accept = o.accept;\n\t\tthis.isover = 0; this.isout = 1;\n\n\t\tthis.accept = $.isFunction(accept) ? accept : function(d) {\n\t\t\treturn d.is(accept);\n\t\t};\n\n\t\t//Store the droppable's proportions\n\t\tthis.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };\n\n\t\t// Add the reference and positions to the manager\n\t\t$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];\n\t\t$.ui.ddmanager.droppables[o.scope].push(this);\n\n\t\t(o.addClasses && this.element.addClass(\"ui-droppable\"));\n\n\t},\n\n\t_destroy: function() {\n\t\tvar drop = $.ui.ddmanager.droppables[this.options.scope];\n\t\tfor ( var i = 0; i < drop.length; i++ )\n\t\t\tif ( drop[i] == this )\n\t\t\t\tdrop.splice(i, 1);\n\n\t\tthis.element.removeClass(\"ui-droppable ui-droppable-disabled\");\n\t},\n\n\t_setOption: function(key, value) {\n\n\t\tif(key == 'accept') {\n\t\t\tthis.accept = $.isFunction(value) ? value : function(d) {\n\t\t\t\treturn d.is(value);\n\t\t\t};\n\t\t}\n\t\t$.Widget.prototype._setOption.apply(this, arguments);\n\t},\n\n\t_activate: function(event) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\t\tif(this.options.activeClass) this.element.addClass(this.options.activeClass);\n\t\t(draggable && this._trigger('activate', event, this.ui(draggable)));\n\t},\n\n\t_deactivate: function(event) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\t\tif(this.options.activeClass) this.element.removeClass(this.options.activeClass);\n\t\t(draggable && this._trigger('deactivate', event, this.ui(draggable)));\n\t},\n\n\t_over: function(event) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\t\tif (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element\n\n\t\tif (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n\t\t\tif(this.options.hoverClass) this.element.addClass(this.options.hoverClass);\n\t\t\tthis._trigger('over', event, this.ui(draggable));\n\t\t}\n\n\t},\n\n\t_out: function(event) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\t\tif (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element\n\n\t\tif (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n\t\t\tif(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);\n\t\t\tthis._trigger('out', event, this.ui(draggable));\n\t\t}\n\n\t},\n\n\t_drop: function(event,custom) {\n\n\t\tvar draggable = custom || $.ui.ddmanager.current;\n\t\tif (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element\n\n\t\tvar childrenIntersection = false;\n\t\tthis.element.find(\":data(droppable)\").not(\".ui-draggable-dragging\").each(function() {\n\t\t\tvar inst = $.data(this, 'droppable');\n\t\t\tif(\n\t\t\t\tinst.options.greedy\n\t\t\t\t&& !inst.options.disabled\n\t\t\t\t&& inst.options.scope == draggable.options.scope\n\t\t\t\t&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))\n\t\t\t\t&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)\n\t\t\t) { childrenIntersection = true; return false; }\n\t\t});\n\t\tif(childrenIntersection) return false;\n\n\t\tif(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n\t\t\tif(this.options.activeClass) this.element.removeClass(this.options.activeClass);\n\t\t\tif(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);\n\t\t\tthis._trigger('drop', event, this.ui(draggable));\n\t\t\treturn this.element;\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tui: function(c) {\n\t\treturn {\n\t\t\tdraggable: (c.currentItem || c.element),\n\t\t\thelper: c.helper,\n\t\t\tposition: c.position,\n\t\t\toffset: c.positionAbs\n\t\t};\n\t}\n\n});\n\n$.ui.intersect = function(draggable, droppable, toleranceMode) {\n\n\tif (!droppable.offset) return false;\n\n\tvar x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,\n\t\ty1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;\n\tvar l = droppable.offset.left, r = l + droppable.proportions.width,\n\t\tt = droppable.offset.top, b = t + droppable.proportions.height;\n\n\tswitch (toleranceMode) {\n\t\tcase 'fit':\n\t\t\treturn (l <= x1 && x2 <= r\n\t\t\t\t&& t <= y1 && y2 <= b);\n\t\t\tbreak;\n\t\tcase 'intersect':\n\t\t\treturn (l < x1 + (draggable.helperProportions.width / 2) // Right Half\n\t\t\t\t&& x2 - (draggable.helperProportions.width / 2) < r // Left Half\n\t\t\t\t&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half\n\t\t\t\t&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half\n\t\t\tbreak;\n\t\tcase 'pointer':\n\t\t\tvar draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),\n\t\t\t\tdraggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),\n\t\t\t\tisOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);\n\t\t\treturn isOver;\n\t\t\tbreak;\n\t\tcase 'touch':\n\t\t\treturn (\n\t\t\t\t\t(y1 >= t && y1 <= b) ||\t// Top edge touching\n\t\t\t\t\t(y2 >= t && y2 <= b) ||\t// Bottom edge touching\n\t\t\t\t\t(y1 < t && y2 > b)\t\t// Surrounded vertically\n\t\t\t\t) && (\n\t\t\t\t\t(x1 >= l && x1 <= r) ||\t// Left edge touching\n\t\t\t\t\t(x2 >= l && x2 <= r) ||\t// Right edge touching\n\t\t\t\t\t(x1 < l && x2 > r)\t\t// Surrounded horizontally\n\t\t\t\t);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn false;\n\t\t\tbreak;\n\t\t}\n\n};\n\n/*\n\tThis manager tracks offsets of draggables and droppables\n*/\n$.ui.ddmanager = {\n\tcurrent: null,\n\tdroppables: { 'default': [] },\n\tprepareOffsets: function(t, event) {\n\n\t\tvar m = $.ui.ddmanager.droppables[t.options.scope] || [];\n\t\tvar type = event ? event.type : null; // workaround for #2317\n\t\tvar list = (t.currentItem || t.element).find(\":data(droppable)\").andSelf();\n\n\t\tdroppablesLoop: for (var i = 0; i < m.length; i++) {\n\n\t\t\tif(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;\t//No disabled and non-accepted\n\t\t\tfor (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item\n\t\t\tm[i].visible = m[i].element.css(\"display\") != \"none\"; if(!m[i].visible) continue; \t\t\t\t\t\t\t\t\t//If the element is not visible, continue\n\n\t\t\tif(type == \"mousedown\") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables\n\n\t\t\tm[i].offset = m[i].element.offset();\n\t\t\tm[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };\n\n\t\t}\n\n\t},\n\tdrop: function(draggable, event) {\n\n\t\tvar dropped = false;\n\t\t$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {\n\n\t\t\tif(!this.options) return;\n\t\t\tif (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))\n\t\t\t\tdropped = this._drop.call(this, event) || dropped;\n\n\t\t\tif (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n\t\t\t\tthis.isout = 1; this.isover = 0;\n\t\t\t\tthis._deactivate.call(this, event);\n\t\t\t}\n\n\t\t});\n\t\treturn dropped;\n\n\t},\n\tdragStart: function( draggable, event ) {\n\t\t//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)\n\t\tdraggable.element.parentsUntil( \"body\" ).bind( \"scroll.droppable\", function() {\n\t\t\tif( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t});\n\t},\n\tdrag: function(draggable, event) {\n\n\t\t//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.\n\t\tif(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);\n\n\t\t//Run through all droppables and check their positions based on specific tolerance options\n\t\t$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {\n\n\t\t\tif(this.options.disabled || this.greedyChild || !this.visible) return;\n\t\t\tvar intersects = $.ui.intersect(draggable, this, this.options.tolerance);\n\n\t\t\tvar c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);\n\t\t\tif(!c) return;\n\n\t\t\tvar parentInstance;\n\t\t\tif (this.options.greedy) {\n\t\t\t\tvar parent = this.element.parents(':data(droppable):eq(0)');\n\t\t\t\tif (parent.length) {\n\t\t\t\t\tparentInstance = $.data(parent[0], 'droppable');\n\t\t\t\t\tparentInstance.greedyChild = (c == 'isover' ? 1 : 0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// we just moved into a greedy child\n\t\t\tif (parentInstance && c == 'isover') {\n\t\t\t\tparentInstance['isover'] = 0;\n\t\t\t\tparentInstance['isout'] = 1;\n\t\t\t\tparentInstance._out.call(parentInstance, event);\n\t\t\t}\n\n\t\t\tthis[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;\n\t\t\tthis[c == \"isover\" ? \"_over\" : \"_out\"].call(this, event);\n\n\t\t\t// we just moved out of a greedy child\n\t\t\tif (parentInstance && c == 'isout') {\n\t\t\t\tparentInstance['isout'] = 0;\n\t\t\t\tparentInstance['isover'] = 1;\n\t\t\t\tparentInstance._over.call(parentInstance, event);\n\t\t\t}\n\t\t});\n\n\t},\n\tdragStop: function( draggable, event ) {\n\t\tdraggable.element.parentsUntil( \"body\" ).unbind( \"scroll.droppable\" );\n\t\t//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)\n\t\tif( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );\n\t}\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.menu.js",
    "content": "/*!\n * jQuery UI Menu @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Menu\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n */\n(function($) {\n\nvar currentEventTarget = null;\n\n$.widget( \"ui.menu\", {\n\tversion: \"@VERSION\",\n\tdefaultElement: \"<ul>\",\n\tdelay: 300,\n\toptions: {\n\t\tmenus: \"ul\",\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"right top\"\n\t\t},\n\t\trole: \"menu\",\n\n\t\t// callbacks\n\t\tblur: null,\n\t\tfocus: null,\n\t\tselect: null\n\t},\n\t_create: function() {\n\t\tthis.activeMenu = this.element;\n\t\tthis.element\n\t\t\t.uniqueId()\n\t\t\t.addClass( \"ui-menu ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.toggleClass( \"ui-menu-icons\", !!this.element.find( \".ui-icon\" ).length )\n\t\t\t.attr({\n\t\t\t\trole: this.options.role,\n\t\t\t\ttabIndex: 0\n\t\t\t})\n\t\t\t// need to catch all clicks on disabled menu\n\t\t\t// not possible through _bind\n\t\t\t.bind( \"click.menu\", $.proxy(function( event ) {\n\t\t\t\tif ( this.options.disabled ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}, this ));\n\n\t\tif ( this.options.disabled ) {\n\t\t\tthis.element\n\t\t\t\t.addClass( \"ui-state-disabled\" )\n\t\t\t\t.attr( \"aria-disabled\", \"true\" );\n\t\t}\n\n\t\tthis._bind({\n\t\t\t// Prevent focus from sticking to links inside menu after clicking\n\t\t\t// them (focus should always stay on UL during navigation).\n\t\t\t\"mousedown .ui-menu-item > a\": function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t},\n\t\t\t\"click .ui-state-disabled > a\": function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t},\n\t\t\t\"click .ui-menu-item:has(a)\": function( event ) {\n\t\t\t\tvar target = $( event.target );\n\t\t\t\tif ( target[0] !== currentEventTarget ) {\n\t\t\t\t\tcurrentEventTarget = target[0];\n\t\t\t\t\ttarget.one( \"click.menu\", function( event ) {\n\t\t\t\t\t\tcurrentEventTarget = null;\n\t\t\t\t\t});\n\t\t\t\t\t// Don't select disabled menu items\n\t\t\t\t\tif ( !target.closest( \".ui-menu-item\" ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\t\tthis.select( event );\n\t\t\t\t\t\t// Redirect focus to the menu with a delay for firefox\n\t\t\t\t\t\tthis._delay(function() {\n\t\t\t\t\t\t\tif ( !this.element.is(\":focus\") ) {\n\t\t\t\t\t\t\t\tthis.element.focus();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 20 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"mouseenter .ui-menu-item\": function( event ) {\n\t\t\t\tvar target = $( event.currentTarget );\n\t\t\t\t// Remove ui-state-active class from siblings of the newly focused menu item\n\t\t\t\t// to avoid a jump caused by adjacent elements both having a class with a border\n\t\t\t\ttarget.siblings().children( \".ui-state-active\" ).removeClass( \"ui-state-active\" );\n\t\t\t\tthis.focus( event, target );\n\t\t\t},\n\t\t\tmouseleave: \"collapseAll\",\n\t\t\t\"mouseleave .ui-menu\": \"collapseAll\",\n\t\t\tfocus: function( event ) {\n\t\t\t\tvar menu = this.element,\n\t\t\t\t\tfirstItem = menu.children( \".ui-menu-item\" ).eq( 0 );\n\t\t\t\tif ( this._hasScroll() && !this.active ) {\n\t\t\t\t\tmenu.children().each(function() {\n\t\t\t\t\t\tvar currentItem = $( this );\n\t\t\t\t\t\tif ( currentItem.offset().top - menu.offset().top >= 0 ) {\n\t\t\t\t\t\t\tfirstItem = currentItem;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else if ( this.active ) {\n\t\t\t\t\tfirstItem = this.active;\n\t\t\t\t}\n\t\t\t\tthis.focus( event, firstItem );\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tthis._delay(function() {\n\t\t\t\t\tif ( !$.contains( this.element[0], this.document[0].activeElement ) ) {\n\t\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t\tkeydown: \"_keydown\"\n\t\t});\n\n\t\tthis.refresh();\n\n\t\t// TODO: We probably shouldn't bind to document for each menu.\n\t\t// TODO: This isn't being cleaned up on destroy.\n\t\tthis._bind( this.document, {\n\t\t\tclick: function( event ) {\n\t\t\t\tif ( !$( event.target ).closest( \".ui-menu\" ).length ) {\n\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\t_destroy: function() {\n\t\t// destroy (sub)menus\n\t\tthis.element\n\t\t\t.removeAttr( \"aria-activedescendant\" )\n\t\t\t.find( \".ui-menu\" ).andSelf()\n\t\t\t\t.removeClass( \"ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons\" )\n\t\t\t\t.removeAttr( \"role\" )\n\t\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t\t.removeAttr( \"aria-labelledby\" )\n\t\t\t\t.removeAttr( \"aria-expanded\" )\n\t\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.show();\n\n\t\t// destroy menu items\n\t\tthis.element.find( \".ui-menu-item\" )\n\t\t\t.removeClass( \"ui-menu-item\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t.children( \"a\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.removeClass( \"ui-corner-all ui-state-hover\" )\n\t\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t\t.removeAttr( \"role\" )\n\t\t\t\t.removeAttr( \"aria-haspopup\" )\n\t\t\t\t.children().each( function() {\n\t\t\t\t\tvar elem = $( this );\n\t\t\t\t\tif ( elem.data( \"ui-menu-submenu-carat\" ) ) {\n\t\t\t\t\t\telem.remove();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t// destroy menu dividers\n\t\tthis.element.find( \".ui-menu-divider\" ).removeClass( \"ui-menu-divider ui-widget-content\" );\n\n\t\t// unbind currentEventTarget click event handler\n\t\t$( currentEventTarget ).unbind( \"click.menu\" );\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar match, prev, character, skip,\n\t\t\tpreventDefault = true;\n\n\t\tfunction escape( value ) {\n\t\t\treturn value.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" );\n\t\t}\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\tthis.previousPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\tthis.nextPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.HOME:\n\t\t\tthis._move( \"first\", \"first\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.END:\n\t\t\tthis._move( \"last\", \"last\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.UP:\n\t\t\tthis.previous( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.DOWN:\n\t\t\tthis.next( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.LEFT:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.RIGHT:\n\t\t\tif ( !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\t\tthis.expand( event );\n\t\t\t}\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ENTER:\n\t\t\tthis._activate( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.SPACE:\n\t\t\tthis._activate( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ESCAPE:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpreventDefault = false;\n\t\t\tprev = this.previousFilter || \"\";\n\t\t\tcharacter = String.fromCharCode( event.keyCode );\n\t\t\tskip = false;\n\n\t\t\tclearTimeout( this.filterTimer );\n\n\t\t\tif ( character === prev ) {\n\t\t\t\tskip = true;\n\t\t\t} else {\n\t\t\t\tcharacter = prev + character;\n\t\t\t}\n\n\t\t\tmatch = this.activeMenu.children( \".ui-menu-item\" ).filter(function() {\n\t\t\t\treturn new RegExp( \"^\" + escape( character ), \"i\" )\n\t\t\t\t\t.test( $( this ).children( \"a\" ).text() );\n\t\t\t});\n\t\t\tmatch = skip && match.index( this.active.next() ) !== -1 ?\n\t\t\t\tthis.active.nextAll( \".ui-menu-item\" ) :\n\t\t\t\tmatch;\n\n\t\t\t// If no matches on the current filter, reset to the last character pressed\n\t\t\t// to move down the menu to the first item that starts with that character\n\t\t\tif ( !match.length ) {\n\t\t\t\tcharacter = String.fromCharCode( event.keyCode );\n\t\t\t\tmatch = this.activeMenu.children( \".ui-menu-item\" ).filter(function() {\n\t\t\t\t\treturn new RegExp( \"^\" + escape(character), \"i\" )\n\t\t\t\t\t\t.test( $( this ).children( \"a\" ).text() );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( match.length ) {\n\t\t\t\tthis.focus( event, match );\n\t\t\t\tif ( match.length > 1 ) {\n\t\t\t\t\tthis.previousFilter = character;\n\t\t\t\t\tthis.filterTimer = this._delay(function() {\n\t\t\t\t\t\tdelete this.previousFilter;\n\t\t\t\t\t}, 1000 );\n\t\t\t\t} else {\n\t\t\t\t\tdelete this.previousFilter;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdelete this.previousFilter;\n\t\t\t}\n\t\t}\n\n\t\tif ( preventDefault ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_activate: function( event ) {\n\t\tif ( !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\tif ( this.active.children( \"a[aria-haspopup='true']\" ).length ) {\n\t\t\t\tthis.expand( event );\n\t\t\t} else {\n\t\t\t\tthis.select( event );\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\t// initialize nested menus\n\t\tvar menus,\n\t\t\tsubmenus = this.element.find( this.options.menus + \":not(.ui-menu)\" )\n\t\t\t\t.addClass( \"ui-menu ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t\t.hide()\n\t\t\t\t.attr({\n\t\t\t\t\trole: this.options.role,\n\t\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t\t});\n\n\t\t// don't refresh list items that are already adapted\n\t\tmenus = submenus.add( this.element );\n\n\t\tmenus.children( \":not( .ui-menu-item ):has( a )\" )\n\t\t\t.addClass( \"ui-menu-item\" )\n\t\t\t.attr( \"role\", \"presentation\" )\n\t\t\t.children( \"a\" )\n\t\t\t\t.uniqueId()\n\t\t\t\t.addClass( \"ui-corner-all\" )\n\t\t\t\t.attr({\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\trole: this._itemRole()\n\t\t\t\t});\n\n\t\t// initialize unlinked menu-items containing spaces and/or dashes only as dividers\n\t\tmenus.children( \":not(.ui-menu-item)\" ).each( function() {\n\t\t\tvar item = $( this );\n\t\t\t// hyphen, em dash, en dash\n\t\t\tif ( !/[^\\-—–\\s]/.test( item.text() ) ) {\n\t\t\t\titem.addClass( \"ui-widget-content ui-menu-divider\" );\n\t\t\t}\n\t\t});\n\n\t\t// add aria-disabled attribute to any disabled menu item\n\t\tmenus.children( \".ui-state-disabled\" ).attr( \"aria-disabled\", \"true\" );\n\n\t\tsubmenus.each(function() {\n\t\t\tvar menu = $( this ),\n\t\t\t\titem = menu.prev( \"a\" ),\n\t\t\t\tsubmenuCarat = $( '<span class=\"ui-menu-icon ui-icon ui-icon-carat-1-e\"></span>' ).data( \"ui-menu-submenu-carat\", true );\n\n\t\t\titem\n\t\t\t\t.attr( \"aria-haspopup\", \"true\" )\n\t\t\t\t.prepend( submenuCarat );\n\t\t\tmenu.attr( \"aria-labelledby\", item.attr( \"id\" ) );\n\t\t});\n\t},\n\n\t_itemRole: function() {\n\t\treturn {\n\t\t\tmenu: \"menuitem\",\n\t\t\tlistbox: \"option\"\n\t\t}[ this.options.role ];\n\t},\n\n\tfocus: function( event, item ) {\n\t\tvar nested, focused;\n\t\tthis.blur( event, event && event.type === \"focus\" );\n\n\t\tthis._scrollIntoView( item );\n\n\t\tthis.active = item.first();\n\t\tfocused = this.active.children( \"a\" ).addClass( \"ui-state-focus\" );\n\t\t// only update aria-activedescendant if there's a role\n\t\t// otherwise we assume focus is managed elsewhere\n\t\tif ( this.options.role ) {\n\t\t\tthis.element.attr( \"aria-activedescendant\", focused.attr( \"id\" ) );\n\t\t}\n\n\t\t// highlight active parent menu item, if any\n\t\tthis.active\n\t\t\t.parent()\n\t\t\t.closest( \".ui-menu-item\" )\n\t\t\t.children( \"a:first\" )\n\t\t\t.addClass( \"ui-state-active\" );\n\n\t\tif ( event && event.type === \"keydown\" ) {\n\t\t\tthis._close();\n\t\t} else {\n\t\t\tthis.timer = this._delay(function() {\n\t\t\t\tthis._close();\n\t\t\t}, this.delay );\n\t\t}\n\n\t\tnested = $( \"> .ui-menu\", item );\n\t\tif ( nested.length && ( /^mouse/.test( event.type ) ) ) {\n\t\t\tthis._startOpening(nested);\n\t\t}\n\t\tthis.activeMenu = item.parent();\n\n\t\tthis._trigger( \"focus\", event, { item: item } );\n\t},\n\n\t_scrollIntoView: function( item ) {\n\t\tvar borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;\n\t\tif ( this._hasScroll() ) {\n\t\t\tborderTop = parseFloat( $.css( this.activeMenu[0], \"borderTopWidth\" ) ) || 0;\n\t\t\tpaddingTop = parseFloat( $.css( this.activeMenu[0], \"paddingTop\" ) ) || 0;\n\t\t\toffset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;\n\t\t\tscroll = this.activeMenu.scrollTop();\n\t\t\telementHeight = this.activeMenu.height();\n\t\t\titemHeight = item.height();\n\n\t\t\tif ( offset < 0 ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset );\n\t\t\t} else if ( offset + itemHeight > elementHeight ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );\n\t\t\t}\n\t\t}\n\t},\n\n\tblur: function( event, fromFocus ) {\n\t\tif ( !fromFocus ) {\n\t\t\tclearTimeout( this.timer );\n\t\t}\n\n\t\tif ( !this.active ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.active.children( \"a\" ).removeClass( \"ui-state-focus\" );\n\t\tthis.active = null;\n\n\t\tthis._trigger( \"blur\", event, { item: this.active } );\n\t},\n\n\t_startOpening: function( submenu ) {\n\t\tclearTimeout( this.timer );\n\n\t\t// Don't open if already open fixes a Firefox bug that caused a .5 pixel\n\t\t// shift in the submenu position when mousing over the carat icon\n\t\tif ( submenu.attr( \"aria-hidden\" ) !== \"true\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.timer = this._delay(function() {\n\t\t\tthis._close();\n\t\t\tthis._open( submenu );\n\t\t}, this.delay );\n\t},\n\n\t_open: function( submenu ) {\n\t\tvar position = $.extend({\n\t\t\tof: this.active\n\t\t}, $.type( this.options.position ) === \"function\" ?\n\t\t\tthis.options.position( this.active ) :\n\t\t\tthis.options.position\n\t\t);\n\n\t\tclearTimeout( this.timer );\n\t\tthis.element.find( \".ui-menu\" ).not( submenu.parents() )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" );\n\n\t\tsubmenu\n\t\t\t.show()\n\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t.attr( \"aria-expanded\", \"true\" )\n\t\t\t.position( position );\n\t},\n\n\tcollapseAll: function( event, all ) {\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay(function() {\n\t\t\t// if we were passed an event, look for the submenu that contains the event\n\t\t\tvar currentMenu = all ? this.element :\n\t\t\t\t$( event && event.target ).closest( this.element.find( \".ui-menu\" ) );\n\n\t\t\t// if we found no valid submenu ancestor, use the main menu to close all sub menus anyway\n\t\t\tif ( !currentMenu.length ) {\n\t\t\t\tcurrentMenu = this.element;\n\t\t\t}\n\n\t\t\tthis._close( currentMenu );\n\n\t\t\tthis.blur( event );\n\t\t\tthis.activeMenu = currentMenu;\n\t\t}, this.delay );\n\t},\n\n\t// With no arguments, closes the currently active menu - if nothing is active\n\t// it closes all menus.  If passed an argument, it will search for menus BELOW\n\t_close: function( startMenu ) {\n\t\tif ( !startMenu ) {\n\t\t\tstartMenu = this.active ? this.active.parent() : this.element;\n\t\t}\n\n\t\tstartMenu\n\t\t\t.find( \".ui-menu\" )\n\t\t\t\t.hide()\n\t\t\t\t.attr( \"aria-hidden\", \"true\" )\n\t\t\t\t.attr( \"aria-expanded\", \"false\" )\n\t\t\t.end()\n\t\t\t.find( \"a.ui-state-active\" )\n\t\t\t\t.removeClass( \"ui-state-active\" );\n\t},\n\n\tcollapse: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active.parent().closest( \".ui-menu-item\", this.element );\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._close();\n\t\t\tthis.focus( event, newItem );\n\t\t\treturn true;\n\t\t}\n\t},\n\n\texpand: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active\n\t\t\t\t.children( \".ui-menu \" )\n\t\t\t\t.children( \".ui-menu-item\" )\n\t\t\t\t.first();\n\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._open( newItem.parent() );\n\n\t\t\t// timeout so Firefox will not hide activedescendant change in expanding submenu from AT\n\t\t\tthis._delay(function() {\n\t\t\t\tthis.focus( event, newItem );\n\t\t\t}, 20 );\n\t\t\treturn true;\n\t\t}\n\t},\n\n\tnext: function( event ) {\n\t\tthis._move( \"next\", \"first\", event );\n\t},\n\n\tprevious: function( event ) {\n\t\tthis._move( \"prev\", \"last\", event );\n\t},\n\n\tisFirstItem: function() {\n\t\treturn this.active && !this.active.prevAll( \".ui-menu-item\" ).length;\n\t},\n\n\tisLastItem: function() {\n\t\treturn this.active && !this.active.nextAll( \".ui-menu-item\" ).length;\n\t},\n\n\t_move: function( direction, filter, event ) {\n\t\tvar next;\n\t\tif ( this.active ) {\n\t\t\tif ( direction === \"first\" || direction === \"last\" ) {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction === \"first\" ? \"prevAll\" : \"nextAll\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( -1 );\n\t\t\t} else {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction + \"All\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( 0 );\n\t\t\t}\n\t\t}\n\t\tif ( !next || !next.length || !this.active ) {\n\t\t\tnext = this.activeMenu.children( \".ui-menu-item\" )[ filter ]();\n\t\t}\n\n\t\tthis.focus( event, next );\n\t},\n\n\tnextPage: function( event ) {\n\t\tif ( !this.active ) {\n\t\t\tthis._move( \"next\", \"first\", event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isLastItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tvar base = this.active.offset().top,\n\t\t\t\theight = this.element.height(),\n\t\t\t\tresult;\n\t\t\tthis.active.nextAll( \".ui-menu-item\" ).each(function() {\n\t\t\t\tresult = $( this );\n\t\t\t\treturn $( this ).offset().top - base - height < 0;\n\t\t\t});\n\n\t\t\tthis.focus( event, result );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.children( \".ui-menu-item\" )\n\t\t\t\t[ !this.active ? \"first\" : \"last\" ]() );\n\t\t}\n\t},\n\n\tpreviousPage: function( event ) {\n\t\tif ( !this.active ) {\n\t\t\tthis._move( \"next\", \"first\", event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isFirstItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tvar base = this.active.offset().top,\n\t\t\t\theight = this.element.height(),\n\t\t\t\tresult;\n\t\t\tthis.active.prevAll( \".ui-menu-item\" ).each(function() {\n\t\t\t\tresult = $( this );\n\t\t\t\treturn $(this).offset().top - base + height > 0;\n\t\t\t});\n\n\t\t\tthis.focus( event, result );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.children( \".ui-menu-item\" ).first() );\n\t\t}\n\t},\n\n\t_hasScroll: function() {\n\t\treturn this.element.outerHeight() < this.element.prop( \"scrollHeight\" );\n\t},\n\n\tselect: function( event ) {\n\t\t// save active reference before collapseAll triggers blur\n\t\tvar ui = {\n\t\t\titem: this.active\n\t\t};\n\t\tthis.collapseAll( event, true );\n\t\tthis._trigger( \"select\", event, ui );\n\t}\n});\n\n}( jQuery ));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.mouse.js",
    "content": "/*!\n * jQuery UI Mouse @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Mouse\n *\n * Depends:\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\nvar mouseHandled = false;\n$( document ).mouseup( function( e ) {\n\tmouseHandled = false;\n});\n\n$.widget(\"ui.mouse\", {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\tcancel: 'input,textarea,button,select,option',\n\t\tdistance: 1,\n\t\tdelay: 0\n\t},\n\t_mouseInit: function() {\n\t\tvar that = this;\n\n\t\tthis.element\n\t\t\t.bind('mousedown.'+this.widgetName, function(event) {\n\t\t\t\treturn that._mouseDown(event);\n\t\t\t})\n\t\t\t.bind('click.'+this.widgetName, function(event) {\n\t\t\t\tif (true === $.data(event.target, that.widgetName + '.preventClickEvent')) {\n\t\t\t\t\t$.removeData(event.target, that.widgetName + '.preventClickEvent');\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.started = false;\n\t},\n\n\t// TODO: make sure destroying one instance of mouse doesn't mess with\n\t// other instances of mouse\n\t_mouseDestroy: function() {\n\t\tthis.element.unbind('.'+this.widgetName);\n\t\t$(document)\n\t\t\t.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);\n\t},\n\n\t_mouseDown: function(event) {\n\t\t// don't let more than one widget handle mouseStart\n\t\tif( mouseHandled ) { return; }\n\n\t\t// we may have missed mouseup (out of window)\n\t\t(this._mouseStarted && this._mouseUp(event));\n\n\t\tthis._mouseDownEvent = event;\n\n\t\tvar that = this,\n\t\t\tbtnIsLeft = (event.which === 1),\n\t\t\t// event.target.nodeName works around a bug in IE 8 with\n\t\t\t// disabled inputs (#7620)\n\t\t\telIsCancel = (typeof this.options.cancel === \"string\" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);\n\t\tif (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.mouseDelayMet = !this.options.delay;\n\t\tif (!this.mouseDelayMet) {\n\t\t\tthis._mouseDelayTimer = setTimeout(function() {\n\t\t\t\tthat.mouseDelayMet = true;\n\t\t\t}, this.options.delay);\n\t\t}\n\n\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n\t\t\tthis._mouseStarted = (this._mouseStart(event) !== false);\n\t\t\tif (!this._mouseStarted) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Click event may never have fired (Gecko & Opera)\n\t\tif (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {\n\t\t\t$.removeData(event.target, this.widgetName + '.preventClickEvent');\n\t\t}\n\n\t\t// these delegates are required to keep context\n\t\tthis._mouseMoveDelegate = function(event) {\n\t\t\treturn that._mouseMove(event);\n\t\t};\n\t\tthis._mouseUpDelegate = function(event) {\n\t\t\treturn that._mouseUp(event);\n\t\t};\n\t\t$(document)\n\t\t\t.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);\n\n\t\tevent.preventDefault();\n\t\t\n\t\tmouseHandled = true;\n\t\treturn true;\n\t},\n\n\t_mouseMove: function(event) {\n\t\t// IE mouseup check - mouseup happened when mouse was out of window\n\t\tif ($.browser.msie && !(document.documentMode >= 9) && !event.button) {\n\t\t\treturn this._mouseUp(event);\n\t\t}\n\n\t\tif (this._mouseStarted) {\n\t\t\tthis._mouseDrag(event);\n\t\t\treturn event.preventDefault();\n\t\t}\n\n\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n\t\t\tthis._mouseStarted =\n\t\t\t\t(this._mouseStart(this._mouseDownEvent, event) !== false);\n\t\t\t(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));\n\t\t}\n\n\t\treturn !this._mouseStarted;\n\t},\n\n\t_mouseUp: function(event) {\n\t\t$(document)\n\t\t\t.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)\n\t\t\t.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);\n\n\t\tif (this._mouseStarted) {\n\t\t\tthis._mouseStarted = false;\n\n\t\t\tif (event.target === this._mouseDownEvent.target) {\n\t\t\t\t$.data(event.target, this.widgetName + '.preventClickEvent', true);\n\t\t\t}\n\n\t\t\tthis._mouseStop(event);\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseDistanceMet: function(event) {\n\t\treturn (Math.max(\n\t\t\t\tMath.abs(this._mouseDownEvent.pageX - event.pageX),\n\t\t\t\tMath.abs(this._mouseDownEvent.pageY - event.pageY)\n\t\t\t) >= this.options.distance\n\t\t);\n\t},\n\n\t_mouseDelayMet: function(event) {\n\t\treturn this.mouseDelayMet;\n\t},\n\n\t// These are placeholder methods, to be overriden by extending plugin\n\t_mouseStart: function(event) {},\n\t_mouseDrag: function(event) {},\n\t_mouseStop: function(event) {},\n\t_mouseCapture: function(event) { return true; }\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.position.js",
    "content": "/*!\n * jQuery UI Position @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Position\n */\n(function( $, undefined ) {\n\n$.ui = $.ui || {};\n\nvar cachedScrollbarWidth,\n\tmax = Math.max,\n\tabs = Math.abs,\n\tround = Math.round,\n\trhorizontal = /left|center|right/,\n\trvertical = /top|center|bottom/,\n\troffset = /[\\+\\-]\\d+%?/,\n\trposition = /^\\w+/,\n\trpercent = /%$/,\n\t_position = $.fn.position;\n\nfunction getOffsets( offsets, width, height ) {\n\treturn [\n\t\tparseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),\n\t\tparseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )\n\t];\n}\nfunction parseCss( element, property ) {\n\treturn parseInt( $.css( element, property ), 10 ) || 0;\n}\n\n$.position = {\n\tscrollbarWidth: function() {\n\t\tif ( cachedScrollbarWidth !== undefined ) {\n\t\t\treturn cachedScrollbarWidth;\n\t\t}\n\t\tvar w1, w2,\n\t\t\tdiv = $( \"<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>\" ),\n\t\t\tinnerDiv = div.children()[0];\n\n\t\t$( \"body\" ).append( div );\n\t\tw1 = innerDiv.offsetWidth;\n\t\tdiv.css( \"overflow\", \"scroll\" );\n\n\t\tw2 = innerDiv.offsetWidth;\n\n\t\tif ( w1 === w2 ) {\n\t\t\tw2 = div[0].clientWidth;\n\t\t}\n\n\t\tdiv.remove();\n\n\t\treturn (cachedScrollbarWidth = w1 - w2);\n\t},\n\tgetScrollInfo: function( within ) {\n\t\tvar overflowX = within.isWindow ? \"\" : within.element.css( \"overflow-x\" ),\n\t\t\toverflowY = within.isWindow ? \"\" : within.element.css( \"overflow-y\" ),\n\t\t\thasOverflowX = overflowX === \"scroll\" ||\n\t\t\t\t( overflowX === \"auto\" && within.width < within.element[0].scrollWidth ),\n\t\t\thasOverflowY = overflowY === \"scroll\" ||\n\t\t\t\t( overflowY === \"auto\" && within.height < within.element[0].scrollHeight );\n\t\treturn {\n\t\t\twidth: hasOverflowX ? $.position.scrollbarWidth() : 0,\n\t\t\theight: hasOverflowY ? $.position.scrollbarWidth() : 0\n\t\t};\n\t},\n\tgetWithinInfo: function( element ) {\n\t\tvar withinElement = $( element || window ),\n\t\t\tisWindow = $.isWindow( withinElement[0] );\n\t\treturn {\n\t\t\telement: withinElement,\n\t\t\tisWindow: isWindow,\n\t\t\toffset: withinElement.offset() || { left: 0, top: 0 },\n\t\t\tscrollLeft: withinElement.scrollLeft(),\n\t\t\tscrollTop: withinElement.scrollTop(),\n\t\t\twidth: isWindow ? withinElement.width() : withinElement.outerWidth(),\n\t\t\theight: isWindow ? withinElement.height() : withinElement.outerHeight()\n\t\t};\n\t}\n};\n\n$.fn.position = function( options ) {\n\tif ( !options || !options.of ) {\n\t\treturn _position.apply( this, arguments );\n\t}\n\n\t// make a copy, we don't want to modify arguments\n\toptions = $.extend( {}, options );\n\n\tvar atOffset, targetWidth, targetHeight, targetOffset, basePosition,\n\t\ttarget = $( options.of ),\n\t\twithin = $.position.getWithinInfo( options.within ),\n\t\tscrollInfo = $.position.getScrollInfo( within ),\n\t\ttargetElem = target[0],\n\t\tcollision = ( options.collision || \"flip\" ).split( \" \" ),\n\t\toffsets = {};\n\n\tif ( targetElem.nodeType === 9 ) {\n\t\ttargetWidth = target.width();\n\t\ttargetHeight = target.height();\n\t\ttargetOffset = { top: 0, left: 0 };\n\t} else if ( $.isWindow( targetElem ) ) {\n\t\ttargetWidth = target.width();\n\t\ttargetHeight = target.height();\n\t\ttargetOffset = { top: target.scrollTop(), left: target.scrollLeft() };\n\t} else if ( targetElem.preventDefault ) {\n\t\t// force left top to allow flipping\n\t\toptions.at = \"left top\";\n\t\ttargetWidth = targetHeight = 0;\n\t\ttargetOffset = { top: targetElem.pageY, left: targetElem.pageX };\n\t} else {\n\t\ttargetWidth = target.outerWidth();\n\t\ttargetHeight = target.outerHeight();\n\t\ttargetOffset = target.offset();\n\t}\n\t// clone to reuse original targetOffset later\n\tbasePosition = $.extend( {}, targetOffset );\n\n\t// force my and at to have valid horizontal and vertical positions\n\t// if a value is missing or invalid, it will be converted to center\n\t$.each( [ \"my\", \"at\" ], function() {\n\t\tvar pos = ( options[ this ] || \"\" ).split( \" \" ),\n\t\t\thorizontalOffset,\n\t\t\tverticalOffset;\n\n\t\tif ( pos.length === 1) {\n\t\t\tpos = rhorizontal.test( pos[ 0 ] ) ?\n\t\t\t\tpos.concat( [ \"center\" ] ) :\n\t\t\t\trvertical.test( pos[ 0 ] ) ?\n\t\t\t\t\t[ \"center\" ].concat( pos ) :\n\t\t\t\t\t[ \"center\", \"center\" ];\n\t\t}\n\t\tpos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : \"center\";\n\t\tpos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : \"center\";\n\n\t\t// calculate offsets\n\t\thorizontalOffset = roffset.exec( pos[ 0 ] );\n\t\tverticalOffset = roffset.exec( pos[ 1 ] );\n\t\toffsets[ this ] = [\n\t\t\thorizontalOffset ? horizontalOffset[ 0 ] : 0,\n\t\t\tverticalOffset ? verticalOffset[ 0 ] : 0\n\t\t];\n\n\t\t// reduce to just the positions without the offsets\n\t\toptions[ this ] = [\n\t\t\trposition.exec( pos[ 0 ] )[ 0 ],\n\t\t\trposition.exec( pos[ 1 ] )[ 0 ]\n\t\t];\n\t});\n\n\t// normalize collision option\n\tif ( collision.length === 1 ) {\n\t\tcollision[ 1 ] = collision[ 0 ];\n\t}\n\n\tif ( options.at[ 0 ] === \"right\" ) {\n\t\tbasePosition.left += targetWidth;\n\t} else if ( options.at[ 0 ] === \"center\" ) {\n\t\tbasePosition.left += targetWidth / 2;\n\t}\n\n\tif ( options.at[ 1 ] === \"bottom\" ) {\n\t\tbasePosition.top += targetHeight;\n\t} else if ( options.at[ 1 ] === \"center\" ) {\n\t\tbasePosition.top += targetHeight / 2;\n\t}\n\n\tatOffset = getOffsets( offsets.at, targetWidth, targetHeight );\n\tbasePosition.left += atOffset[ 0 ];\n\tbasePosition.top += atOffset[ 1 ];\n\n\treturn this.each(function() {\n\t\tvar collisionPosition, using,\n\t\t\telem = $( this ),\n\t\t\telemWidth = elem.outerWidth(),\n\t\t\telemHeight = elem.outerHeight(),\n\t\t\tmarginLeft = parseCss( this, \"marginLeft\" ),\n\t\t\tmarginTop = parseCss( this, \"marginTop\" ),\n\t\t\tcollisionWidth = elemWidth + marginLeft + parseCss( this, \"marginRight\" ) + scrollInfo.width,\n\t\t\tcollisionHeight = elemHeight + marginTop + parseCss( this, \"marginBottom\" ) + scrollInfo.height,\n\t\t\tposition = $.extend( {}, basePosition ),\n\t\t\tmyOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );\n\n\t\tif ( options.my[ 0 ] === \"right\" ) {\n\t\t\tposition.left -= elemWidth;\n\t\t} else if ( options.my[ 0 ] === \"center\" ) {\n\t\t\tposition.left -= elemWidth / 2;\n\t\t}\n\n\t\tif ( options.my[ 1 ] === \"bottom\" ) {\n\t\t\tposition.top -= elemHeight;\n\t\t} else if ( options.my[ 1 ] === \"center\" ) {\n\t\t\tposition.top -= elemHeight / 2;\n\t\t}\n\n\t\tposition.left += myOffset[ 0 ];\n\t\tposition.top += myOffset[ 1 ];\n\n\t\t// if the browser doesn't support fractions, then round for consistent results\n\t\tif ( !$.support.offsetFractions ) {\n\t\t\tposition.left = round( position.left );\n\t\t\tposition.top = round( position.top );\n\t\t}\n\n\t\tcollisionPosition = {\n\t\t\tmarginLeft: marginLeft,\n\t\t\tmarginTop: marginTop\n\t\t};\n\n\t\t$.each( [ \"left\", \"top\" ], function( i, dir ) {\n\t\t\tif ( $.ui.position[ collision[ i ] ] ) {\n\t\t\t\t$.ui.position[ collision[ i ] ][ dir ]( position, {\n\t\t\t\t\ttargetWidth: targetWidth,\n\t\t\t\t\ttargetHeight: targetHeight,\n\t\t\t\t\telemWidth: elemWidth,\n\t\t\t\t\telemHeight: elemHeight,\n\t\t\t\t\tcollisionPosition: collisionPosition,\n\t\t\t\t\tcollisionWidth: collisionWidth,\n\t\t\t\t\tcollisionHeight: collisionHeight,\n\t\t\t\t\toffset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],\n\t\t\t\t\tmy: options.my,\n\t\t\t\t\tat: options.at,\n\t\t\t\t\twithin: within,\n\t\t\t\t\telem : elem\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tif ( $.fn.bgiframe ) {\n\t\t\telem.bgiframe();\n\t\t}\n\n\t\tif ( options.using ) {\n\t\t\t// adds feedback as second argument to using callback, if present\n\t\t\tusing = function( props ) {\n\t\t\t\tvar left = targetOffset.left - position.left,\n\t\t\t\t\tright = left + targetWidth - elemWidth,\n\t\t\t\t\ttop = targetOffset.top - position.top,\n\t\t\t\t\tbottom = top + targetHeight - elemHeight,\n\t\t\t\t\tfeedback = {\n\t\t\t\t\t\ttarget: {\n\t\t\t\t\t\t\telement: target,\n\t\t\t\t\t\t\tleft: targetOffset.left,\n\t\t\t\t\t\t\ttop: targetOffset.top,\n\t\t\t\t\t\t\twidth: targetWidth,\n\t\t\t\t\t\t\theight: targetHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\telement: {\n\t\t\t\t\t\t\telement: elem,\n\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\twidth: elemWidth,\n\t\t\t\t\t\t\theight: elemHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\thorizontal: right < 0 ? \"left\" : left > 0 ? \"right\" : \"center\",\n\t\t\t\t\t\tvertical: bottom < 0 ? \"top\" : top > 0 ? \"bottom\" : \"middle\"\n\t\t\t\t\t};\n\t\t\t\tif ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {\n\t\t\t\t\tfeedback.horizontal = \"center\";\n\t\t\t\t}\n\t\t\t\tif ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {\n\t\t\t\t\tfeedback.vertical = \"middle\";\n\t\t\t\t}\n\t\t\t\tif ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {\n\t\t\t\t\tfeedback.important = \"horizontal\";\n\t\t\t\t} else {\n\t\t\t\t\tfeedback.important = \"vertical\";\n\t\t\t\t}\n\t\t\t\toptions.using.call( this, props, feedback );\n\t\t\t};\n\t\t}\n\n\t\telem.offset( $.extend( position, { using: using } ) );\n\t});\n};\n\n$.ui.position = {\n\tfit: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\touterWidth = within.width,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = withinOffset - collisionPosLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,\n\t\t\t\tnewOverRight;\n\n\t\t\t// element is wider than within\n\t\t\tif ( data.collisionWidth > outerWidth ) {\n\t\t\t\t// element is initially over the left side of within\n\t\t\t\tif ( overLeft > 0 && overRight <= 0 ) {\n\t\t\t\t\tnewOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;\n\t\t\t\t\tposition.left += overLeft - newOverRight;\n\t\t\t\t// element is initially over right side of within\n\t\t\t\t} else if ( overRight > 0 && overLeft <= 0 ) {\n\t\t\t\t\tposition.left = withinOffset;\n\t\t\t\t// element is initially over both left and right sides of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overLeft > overRight ) {\n\t\t\t\t\t\tposition.left = withinOffset + outerWidth - data.collisionWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.left = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t// too far left -> align with left edge\n\t\t\t} else if ( overLeft > 0 ) {\n\t\t\t\tposition.left += overLeft;\n\t\t\t// too far right -> align with right edge\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tposition.left -= overRight;\n\t\t\t// adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.left = max( position.left - collisionPosLeft, position.left );\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\touterHeight = data.within.height,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = withinOffset - collisionPosTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,\n\t\t\t\tnewOverBottom;\n\n\t\t\t// element is taller than within\n\t\t\tif ( data.collisionHeight > outerHeight ) {\n\t\t\t\t// element is initially over the top of within\n\t\t\t\tif ( overTop > 0 && overBottom <= 0 ) {\n\t\t\t\t\tnewOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;\n\t\t\t\t\tposition.top += overTop - newOverBottom;\n\t\t\t\t// element is initially over bottom of within\n\t\t\t\t} else if ( overBottom > 0 && overTop <= 0 ) {\n\t\t\t\t\tposition.top = withinOffset;\n\t\t\t\t// element is initially over both top and bottom of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overTop > overBottom ) {\n\t\t\t\t\t\tposition.top = withinOffset + outerHeight - data.collisionHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.top = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t// too far up -> align with top\n\t\t\t} else if ( overTop > 0 ) {\n\t\t\t\tposition.top += overTop;\n\t\t\t// too far down -> align with bottom edge\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tposition.top -= overBottom;\n\t\t\t// adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.top = max( position.top - collisionPosTop, position.top );\n\t\t\t}\n\t\t}\n\t},\n\tflip: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.left + within.scrollLeft,\n\t\t\t\touterWidth = within.width,\n\t\t\t\toffsetLeft = within.isWindow ? 0 : within.offset.left,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = collisionPosLeft - offsetLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,\n\t\t\t\tmyOffset = data.my[ 0 ] === \"left\" ?\n\t\t\t\t\t-data.elemWidth :\n\t\t\t\t\tdata.my[ 0 ] === \"right\" ?\n\t\t\t\t\t\tdata.elemWidth :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 0 ] === \"left\" ?\n\t\t\t\t\tdata.targetWidth :\n\t\t\t\t\tdata.at[ 0 ] === \"right\" ?\n\t\t\t\t\t\t-data.targetWidth :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 0 ],\n\t\t\t\tnewOverRight,\n\t\t\t\tnewOverLeft;\n\n\t\t\tif ( overLeft < 0 ) {\n\t\t\t\tnewOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;\n\t\t\t\tif ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( overRight > 0 ) {\n\t\t\t\tnewOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;\n\t\t\t\tif ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.top + within.scrollTop,\n\t\t\t\touterHeight = within.height,\n\t\t\t\toffsetTop = within.isWindow ? 0 : within.offset.top,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = collisionPosTop - offsetTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,\n\t\t\t\ttop = data.my[ 1 ] === \"top\",\n\t\t\t\tmyOffset = top ?\n\t\t\t\t\t-data.elemHeight :\n\t\t\t\t\tdata.my[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\tdata.elemHeight :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 1 ] === \"top\" ?\n\t\t\t\t\tdata.targetHeight :\n\t\t\t\t\tdata.at[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\t-data.targetHeight :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 1 ],\n\t\t\t\tnewOverTop,\n\t\t\t\tnewOverBottom;\n\t\t\tif ( overTop < 0 ) {\n\t\t\t\tnewOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;\n\t\t\t\tif ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( overBottom > 0 ) {\n\t\t\t\tnewOverTop = position.top -  data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;\n\t\t\t\tif ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tflipfit: {\n\t\tleft: function() {\n\t\t\t$.ui.position.flip.left.apply( this, arguments );\n\t\t\t$.ui.position.fit.left.apply( this, arguments );\n\t\t},\n\t\ttop: function() {\n\t\t\t$.ui.position.flip.top.apply( this, arguments );\n\t\t\t$.ui.position.fit.top.apply( this, arguments );\n\t\t}\n\t}\n};\n\n// fraction support test\n(function () {\n\tvar testElement, testElementParent, testElementStyle, offsetLeft, i,\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ],\n\t\tdiv = document.createElement( \"div\" );\n\n\t//Create a \"fake body\" for testing based on method used in jQuery.support\n\ttestElement = document.createElement( body ? \"div\" : \"body\" );\n\ttestElementStyle = {\n\t\tvisibility: \"hidden\",\n\t\twidth: 0,\n\t\theight: 0,\n\t\tborder: 0,\n\t\tmargin: 0,\n\t\tbackground: \"none\"\n\t};\n\tif ( body ) {\n\t\t$.extend( testElementStyle, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: \"-1000px\",\n\t\t\ttop: \"-1000px\"\n\t\t});\n\t}\n\tfor ( i in testElementStyle ) {\n\t\ttestElement.style[ i ] = testElementStyle[ i ];\n\t}\n\ttestElement.appendChild( div );\n\ttestElementParent = body || document.documentElement;\n\ttestElementParent.insertBefore( testElement, testElementParent.firstChild );\n\n\tdiv.style.cssText = \"position: absolute; left: 10.7432222px;\";\n\n\toffsetLeft = $( div ).offset().left;\n\t$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;\n\n\ttestElement.innerHTML = \"\";\n\ttestElementParent.removeChild( testElement );\n})();\n\n// DEPRECATED\nif ( $.uiBackCompat !== false ) {\n\t// offset option\n\t(function( $ ) {\n\t\tvar _position = $.fn.position;\n\t\t$.fn.position = function( options ) {\n\t\t\tif ( !options || !options.offset ) {\n\t\t\t\treturn _position.call( this, options );\n\t\t\t}\n\t\t\tvar offset = options.offset.split( \" \" ),\n\t\t\t\tat = options.at.split( \" \" );\n\t\t\tif ( offset.length === 1 ) {\n\t\t\t\toffset[ 1 ] = offset[ 0 ];\n\t\t\t}\n\t\t\tif ( /^\\d/.test( offset[ 0 ] ) ) {\n\t\t\t\toffset[ 0 ] = \"+\" + offset[ 0 ];\n\t\t\t}\n\t\t\tif ( /^\\d/.test( offset[ 1 ] ) ) {\n\t\t\t\toffset[ 1 ] = \"+\" + offset[ 1 ];\n\t\t\t}\n\t\t\tif ( at.length === 1 ) {\n\t\t\t\tif ( /left|center|right/.test( at[ 0 ] ) ) {\n\t\t\t\t\tat[ 1 ] = \"center\";\n\t\t\t\t} else {\n\t\t\t\t\tat[ 1 ] = at[ 0 ];\n\t\t\t\t\tat[ 0 ] = \"center\";\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn _position.call( this, $.extend( options, {\n\t\t\t\tat: at[ 0 ] + offset[ 0 ] + \" \" + at[ 1 ] + offset[ 1 ],\n\t\t\t\toffset: undefined\n\t\t\t} ) );\n\t\t};\n\t}( jQuery ) );\n}\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.progressbar.js",
    "content": "/*!\n * jQuery UI Progressbar @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Progressbar\n *\n * Depends:\n *   jquery.ui.core.js\n *   jquery.ui.widget.js\n */\n(function( $, undefined ) {\n\n$.widget( \"ui.progressbar\", {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\tvalue: 0,\n\t\tmax: 100\n\t},\n\n\tmin: 0,\n\n\t_create: function() {\n\t\tthis.element\n\t\t\t.addClass( \"ui-progressbar ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.attr({\n\t\t\t\trole: \"progressbar\",\n\t\t\t\t\"aria-valuemin\": this.min,\n\t\t\t\t\"aria-valuemax\": this.options.max,\n\t\t\t\t\"aria-valuenow\": this._value()\n\t\t\t});\n\n\t\tthis.valueDiv = $( \"<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>\" )\n\t\t\t.appendTo( this.element );\n\n\t\tthis.oldValue = this._value();\n\t\tthis._refreshValue();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass( \"ui-progressbar ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-valuemin\" )\n\t\t\t.removeAttr( \"aria-valuemax\" )\n\t\t\t.removeAttr( \"aria-valuenow\" );\n\n\t\tthis.valueDiv.remove();\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( newValue === undefined ) {\n\t\t\treturn this._value();\n\t\t}\n\n\t\tthis._setOption( \"value\", newValue );\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"value\" ) {\n\t\t\tthis.options.value = value;\n\t\t\tthis._refreshValue();\n\t\t\tif ( this._value() === this.options.max ) {\n\t\t\t\tthis._trigger( \"complete\" );\n\t\t\t}\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_value: function() {\n\t\tvar val = this.options.value;\n\t\t// normalize invalid value\n\t\tif ( typeof val !== \"number\" ) {\n\t\t\tval = 0;\n\t\t}\n\t\treturn Math.min( this.options.max, Math.max( this.min, val ) );\n\t},\n\n\t_percentage: function() {\n\t\treturn 100 * this._value() / this.options.max;\n\t},\n\n\t_refreshValue: function() {\n\t\tvar value = this.value(),\n\t\t\tpercentage = this._percentage();\n\n\t\tif ( this.oldValue !== value ) {\n\t\t\tthis.oldValue = value;\n\t\t\tthis._trigger( \"change\" );\n\t\t}\n\n\t\tthis.valueDiv\n\t\t\t.toggle( value > this.min )\n\t\t\t.toggleClass( \"ui-corner-right\", value === this.options.max )\n\t\t\t.width( percentage.toFixed(0) + \"%\" );\n\t\tthis.element.attr( \"aria-valuenow\", value );\n\t}\n});\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.resizable.js",
    "content": "/*!\n * jQuery UI Resizable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Resizables\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\n$.widget(\"ui.resizable\", $.ui.mouse, {\n\tversion: \"@VERSION\",\n\twidgetEventPrefix: \"resize\",\n\toptions: {\n\t\talsoResize: false,\n\t\tanimate: false,\n\t\tanimateDuration: \"slow\",\n\t\tanimateEasing: \"swing\",\n\t\taspectRatio: false,\n\t\tautoHide: false,\n\t\tcontainment: false,\n\t\tghost: false,\n\t\tgrid: false,\n\t\thandles: \"e,s,se\",\n\t\thelper: false,\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 10,\n\t\tminWidth: 10,\n\t\tzIndex: 1000\n\t},\n\t_create: function() {\n\n\t\tvar that = this, o = this.options;\n\t\tthis.element.addClass(\"ui-resizable\");\n\n\t\t$.extend(this, {\n\t\t\t_aspectRatio: !!(o.aspectRatio),\n\t\t\taspectRatio: o.aspectRatio,\n\t\t\toriginalElement: this.element,\n\t\t\t_proportionallyResizeElements: [],\n\t\t\t_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null\n\t\t});\n\n\t\t//Wrap the element if it cannot hold child nodes\n\t\tif(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {\n\n\t\t\t//Create a wrapper element and set the wrapper to the new current internal element\n\t\t\tthis.element.wrap(\n\t\t\t\t$('<div class=\"ui-wrapper\" style=\"overflow: hidden;\"></div>').css({\n\t\t\t\t\tposition: this.element.css('position'),\n\t\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\t\ttop: this.element.css('top'),\n\t\t\t\t\tleft: this.element.css('left')\n\t\t\t\t})\n\t\t\t);\n\n\t\t\t//Overwrite the original this.element\n\t\t\tthis.element = this.element.parent().data(\n\t\t\t\t\"resizable\", this.element.data('resizable')\n\t\t\t);\n\n\t\t\tthis.elementIsWrapper = true;\n\n\t\t\t//Move margins to the wrapper\n\t\t\tthis.element.css({ marginLeft: this.originalElement.css(\"marginLeft\"), marginTop: this.originalElement.css(\"marginTop\"), marginRight: this.originalElement.css(\"marginRight\"), marginBottom: this.originalElement.css(\"marginBottom\") });\n\t\t\tthis.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});\n\n\t\t\t//Prevent Safari textarea resize\n\t\t\tthis.originalResizeStyle = this.originalElement.css('resize');\n\t\t\tthis.originalElement.css('resize', 'none');\n\n\t\t\t//Push the actual element to our proportionallyResize internal array\n\t\t\tthis._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));\n\n\t\t\t// avoid IE jump (hard set the margin)\n\t\t\tthis.originalElement.css({ margin: this.originalElement.css('margin') });\n\n\t\t\t// fix handlers offset\n\t\t\tthis._proportionallyResize();\n\n\t\t}\n\n\t\tthis.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? \"e,s,se\" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });\n\t\tif(this.handles.constructor == String) {\n\n\t\t\tif(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';\n\t\t\tvar n = this.handles.split(\",\"); this.handles = {};\n\n\t\t\tfor(var i = 0; i < n.length; i++) {\n\n\t\t\t\tvar handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;\n\t\t\t\tvar axis = $('<div class=\"ui-resizable-handle ' + hname + '\"></div>');\n\n\t\t\t\t// Apply zIndex to all handles - see #7960\n\t\t\t\taxis.css({ zIndex: o.zIndex });\n\n\t\t\t\t//TODO : What's going on here?\n\t\t\t\tif ('se' == handle) {\n\t\t\t\t\taxis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');\n\t\t\t\t};\n\n\t\t\t\t//Insert into internal handles object and append to element\n\t\t\t\tthis.handles[handle] = '.ui-resizable-'+handle;\n\t\t\t\tthis.element.append(axis);\n\t\t\t}\n\n\t\t}\n\n\t\tthis._renderAxis = function(target) {\n\n\t\t\ttarget = target || this.element;\n\n\t\t\tfor(var i in this.handles) {\n\n\t\t\t\tif(this.handles[i].constructor == String)\n\t\t\t\t\tthis.handles[i] = $(this.handles[i], this.element).show();\n\n\t\t\t\t//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)\n\t\t\t\tif (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {\n\n\t\t\t\t\tvar axis = $(this.handles[i], this.element), padWrapper = 0;\n\n\t\t\t\t\t//Checking the correct pad and border\n\t\t\t\t\tpadWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();\n\n\t\t\t\t\t//The padding type i have to apply...\n\t\t\t\t\tvar padPos = [ 'padding',\n\t\t\t\t\t\t/ne|nw|n/.test(i) ? 'Top' :\n\t\t\t\t\t\t/se|sw|s/.test(i) ? 'Bottom' :\n\t\t\t\t\t\t/^e$/.test(i) ? 'Right' : 'Left' ].join(\"\");\n\n\t\t\t\t\ttarget.css(padPos, padWrapper);\n\n\t\t\t\t\tthis._proportionallyResize();\n\n\t\t\t\t}\n\n\t\t\t\t//TODO: What's that good for? There's not anything to be executed left\n\t\t\t\tif(!$(this.handles[i]).length)\n\t\t\t\t\tcontinue;\n\n\t\t\t}\n\t\t};\n\n\t\t//TODO: make renderAxis a prototype function\n\t\tthis._renderAxis(this.element);\n\n\t\tthis._handles = $('.ui-resizable-handle', this.element)\n\t\t\t.disableSelection();\n\n\t\t//Matching axis name\n\t\tthis._handles.mouseover(function() {\n\t\t\tif (!that.resizing) {\n\t\t\t\tif (this.className)\n\t\t\t\t\tvar axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);\n\t\t\t\t//Axis, default = se\n\t\t\t\tthat.axis = axis && axis[1] ? axis[1] : 'se';\n\t\t\t}\n\t\t});\n\n\t\t//If we want to auto hide the elements\n\t\tif (o.autoHide) {\n\t\t\tthis._handles.hide();\n\t\t\t$(this.element)\n\t\t\t\t.addClass(\"ui-resizable-autohide\")\n\t\t\t\t.mouseenter(function() {\n\t\t\t\t\tif (o.disabled) return;\n\t\t\t\t\t$(this).removeClass(\"ui-resizable-autohide\");\n\t\t\t\t\tthat._handles.show();\n\t\t\t\t})\n\t\t\t\t.mouseleave(function(){\n\t\t\t\t\tif (o.disabled) return;\n\t\t\t\t\tif (!that.resizing) {\n\t\t\t\t\t\t$(this).addClass(\"ui-resizable-autohide\");\n\t\t\t\t\t\tthat._handles.hide();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\n\t\t//Initialize the mouse interaction\n\t\tthis._mouseInit();\n\n\t},\n\n\t_destroy: function() {\n\n\t\tthis._mouseDestroy();\n\n\t\tvar _destroy = function(exp) {\n\t\t\t$(exp).removeClass(\"ui-resizable ui-resizable-disabled ui-resizable-resizing\")\n\t\t\t\t.removeData(\"resizable\").removeData(\"ui-resizable\").unbind(\".resizable\").find('.ui-resizable-handle').remove();\n\t\t};\n\n\t\t//TODO: Unwrap at same DOM position\n\t\tif (this.elementIsWrapper) {\n\t\t\t_destroy(this.element);\n\t\t\tvar wrapper = this.element;\n\t\t\twrapper.after(\n\t\t\t\tthis.originalElement.css({\n\t\t\t\t\tposition: wrapper.css('position'),\n\t\t\t\t\twidth: wrapper.outerWidth(),\n\t\t\t\t\theight: wrapper.outerHeight(),\n\t\t\t\t\ttop: wrapper.css('top'),\n\t\t\t\t\tleft: wrapper.css('left')\n\t\t\t\t})\n\t\t\t).remove();\n\t\t}\n\n\t\tthis.originalElement.css('resize', this.originalResizeStyle);\n\t\t_destroy(this.originalElement);\n\n\t\treturn this;\n\t},\n\n\t_mouseCapture: function(event) {\n\t\tvar handle = false;\n\t\tfor (var i in this.handles) {\n\t\t\tif ($(this.handles[i])[0] == event.target) {\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t}\n\n\t\treturn !this.options.disabled && handle;\n\t},\n\n\t_mouseStart: function(event) {\n\n\t\tvar o = this.options, iniPos = this.element.position(), el = this.element;\n\n\t\tthis.resizing = true;\n\t\tthis.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };\n\n\t\t// bugfix for http://dev.jquery.com/ticket/1749\n\t\tif (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {\n\t\t\tel.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });\n\t\t}\n\n\t\tthis._renderProxy();\n\n\t\tvar curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));\n\n\t\tif (o.containment) {\n\t\t\tcurleft += $(o.containment).scrollLeft() || 0;\n\t\t\tcurtop += $(o.containment).scrollTop() || 0;\n\t\t}\n\n\t\t//Store needed variables\n\t\tthis.offset = this.helper.offset();\n\t\tthis.position = { left: curleft, top: curtop };\n\t\tthis.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };\n\t\tthis.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };\n\t\tthis.originalPosition = { left: curleft, top: curtop };\n\t\tthis.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };\n\t\tthis.originalMousePosition = { left: event.pageX, top: event.pageY };\n\n\t\t//Aspect Ratio\n\t\tthis.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);\n\n\t\tvar cursor = $('.ui-resizable-' + this.axis).css('cursor');\n\t\t$('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);\n\n\t\tel.addClass(\"ui-resizable-resizing\");\n\t\tthis._propagate(\"start\", event);\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function(event) {\n\n\t\t//Increase performance, avoid regex\n\t\tvar el = this.helper, o = this.options, props = {},\n\t\t\tthat = this, smp = this.originalMousePosition, a = this.axis;\n\n\t\tvar dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;\n\t\tvar trigger = this._change[a];\n\t\tif (!trigger) return false;\n\n\t\t// Calculate the attrs that will be change\n\t\tvar data = trigger.apply(this, [event, dx, dy]);\n\n\t\t// Put this in the mouseDrag handler since the user can start pressing shift while resizing\n\t\tthis._updateVirtualBoundaries(event.shiftKey);\n\t\tif (this._aspectRatio || event.shiftKey)\n\t\t\tdata = this._updateRatio(data, event);\n\n\t\tdata = this._respectSize(data, event);\n\n\t\t// plugins callbacks need to be called first\n\t\tthis._propagate(\"resize\", event);\n\n\t\tel.css({\n\t\t\ttop: this.position.top + \"px\", left: this.position.left + \"px\",\n\t\t\twidth: this.size.width + \"px\", height: this.size.height + \"px\"\n\t\t});\n\n\t\tif (!this._helper && this._proportionallyResizeElements.length)\n\t\t\tthis._proportionallyResize();\n\n\t\tthis._updateCache(data);\n\n\t\t// calling the user callback at the end\n\t\tthis._trigger('resize', event, this.ui());\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function(event) {\n\n\t\tthis.resizing = false;\n\t\tvar o = this.options, that = this;\n\n\t\tif(this._helper) {\n\t\t\tvar pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),\n\t\t\t\tsoffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,\n\t\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width;\n\n\t\t\tvar s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) },\n\t\t\t\tleft = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,\n\t\t\t\ttop = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;\n\n\t\t\tif (!o.animate)\n\t\t\t\tthis.element.css($.extend(s, { top: top, left: left }));\n\n\t\t\tthat.helper.height(that.size.height);\n\t\t\tthat.helper.width(that.size.width);\n\n\t\t\tif (this._helper && !o.animate) this._proportionallyResize();\n\t\t}\n\n\t\t$('body').css('cursor', 'auto');\n\n\t\tthis.element.removeClass(\"ui-resizable-resizing\");\n\n\t\tthis._propagate(\"stop\", event);\n\n\t\tif (this._helper) this.helper.remove();\n\t\treturn false;\n\n\t},\n\n\t_updateVirtualBoundaries: function(forceAspectRatio) {\n\t\tvar o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;\n\n\t\tb = {\n\t\t\tminWidth: isNumber(o.minWidth) ? o.minWidth : 0,\n\t\t\tmaxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,\n\t\t\tminHeight: isNumber(o.minHeight) ? o.minHeight : 0,\n\t\t\tmaxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity\n\t\t};\n\n\t\tif(this._aspectRatio || forceAspectRatio) {\n\t\t\t// We want to create an enclosing box whose aspect ration is the requested one\n\t\t\t// First, compute the \"projected\" size for each dimension based on the aspect ratio and other dimension\n\t\t\tpMinWidth = b.minHeight * this.aspectRatio;\n\t\t\tpMinHeight = b.minWidth / this.aspectRatio;\n\t\t\tpMaxWidth = b.maxHeight * this.aspectRatio;\n\t\t\tpMaxHeight = b.maxWidth / this.aspectRatio;\n\n\t\t\tif(pMinWidth > b.minWidth) b.minWidth = pMinWidth;\n\t\t\tif(pMinHeight > b.minHeight) b.minHeight = pMinHeight;\n\t\t\tif(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;\n\t\t\tif(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;\n\t\t}\n\t\tthis._vBoundaries = b;\n\t},\n\n\t_updateCache: function(data) {\n\t\tvar o = this.options;\n\t\tthis.offset = this.helper.offset();\n\t\tif (isNumber(data.left)) this.position.left = data.left;\n\t\tif (isNumber(data.top)) this.position.top = data.top;\n\t\tif (isNumber(data.height)) this.size.height = data.height;\n\t\tif (isNumber(data.width)) this.size.width = data.width;\n\t},\n\n\t_updateRatio: function(data, event) {\n\n\t\tvar o = this.options, cpos = this.position, csize = this.size, a = this.axis;\n\n\t\tif (isNumber(data.height)) data.width = (data.height * this.aspectRatio);\n\t\telse if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);\n\n\t\tif (a == 'sw') {\n\t\t\tdata.left = cpos.left + (csize.width - data.width);\n\t\t\tdata.top = null;\n\t\t}\n\t\tif (a == 'nw') {\n\t\t\tdata.top = cpos.top + (csize.height - data.height);\n\t\t\tdata.left = cpos.left + (csize.width - data.width);\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_respectSize: function(data, event) {\n\n\t\tvar el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,\n\t\t\t\tismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),\n\t\t\t\t\tisminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);\n\n\t\tif (isminw) data.width = o.minWidth;\n\t\tif (isminh) data.height = o.minHeight;\n\t\tif (ismaxw) data.width = o.maxWidth;\n\t\tif (ismaxh) data.height = o.maxHeight;\n\n\t\tvar dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;\n\t\tvar cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);\n\n\t\tif (isminw && cw) data.left = dw - o.minWidth;\n\t\tif (ismaxw && cw) data.left = dw - o.maxWidth;\n\t\tif (isminh && ch)\tdata.top = dh - o.minHeight;\n\t\tif (ismaxh && ch)\tdata.top = dh - o.maxHeight;\n\n\t\t// fixing jump error on top/left - bug #2330\n\t\tvar isNotwh = !data.width && !data.height;\n\t\tif (isNotwh && !data.left && data.top) data.top = null;\n\t\telse if (isNotwh && !data.top && data.left) data.left = null;\n\n\t\treturn data;\n\t},\n\n\t_proportionallyResize: function() {\n\n\t\tvar o = this.options;\n\t\tif (!this._proportionallyResizeElements.length) return;\n\t\tvar element = this.helper || this.element;\n\n\t\tfor (var i=0; i < this._proportionallyResizeElements.length; i++) {\n\n\t\t\tvar prel = this._proportionallyResizeElements[i];\n\n\t\t\tif (!this.borderDif) {\n\t\t\t\tvar b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],\n\t\t\t\t\tp = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];\n\n\t\t\t\tthis.borderDif = $.map(b, function(v, i) {\n\t\t\t\t\tvar border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;\n\t\t\t\t\treturn border + padding;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))\n\t\t\t\tcontinue;\n\n\t\t\tprel.css({\n\t\t\t\theight: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,\n\t\t\t\twidth: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0\n\t\t\t});\n\n\t\t};\n\n\t},\n\n\t_renderProxy: function() {\n\n\t\tvar el = this.element, o = this.options;\n\t\tthis.elementOffset = el.offset();\n\n\t\tif(this._helper) {\n\n\t\t\tthis.helper = this.helper || $('<div style=\"overflow:hidden;\"></div>');\n\n\t\t\t// fix ie6 offset TODO: This seems broken\n\t\t\tvar ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),\n\t\t\tpxyoffset = ( ie6 ? 2 : -1 );\n\n\t\t\tthis.helper.addClass(this._helper).css({\n\t\t\t\twidth: this.element.outerWidth() + pxyoffset,\n\t\t\t\theight: this.element.outerHeight() + pxyoffset,\n\t\t\t\tposition: 'absolute',\n\t\t\t\tleft: this.elementOffset.left - ie6offset +'px',\n\t\t\t\ttop: this.elementOffset.top - ie6offset +'px',\n\t\t\t\tzIndex: ++o.zIndex //TODO: Don't modify option\n\t\t\t});\n\n\t\t\tthis.helper\n\t\t\t\t.appendTo(\"body\")\n\t\t\t\t.disableSelection();\n\n\t\t} else {\n\t\t\tthis.helper = this.element;\n\t\t}\n\n\t},\n\n\t_change: {\n\t\te: function(event, dx, dy) {\n\t\t\treturn { width: this.originalSize.width + dx };\n\t\t},\n\t\tw: function(event, dx, dy) {\n\t\t\tvar o = this.options, cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { left: sp.left + dx, width: cs.width - dx };\n\t\t},\n\t\tn: function(event, dx, dy) {\n\t\t\tvar o = this.options, cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { top: sp.top + dy, height: cs.height - dy };\n\t\t},\n\t\ts: function(event, dx, dy) {\n\t\t\treturn { height: this.originalSize.height + dy };\n\t\t},\n\t\tse: function(event, dx, dy) {\n\t\t\treturn $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));\n\t\t},\n\t\tsw: function(event, dx, dy) {\n\t\t\treturn $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));\n\t\t},\n\t\tne: function(event, dx, dy) {\n\t\t\treturn $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));\n\t\t},\n\t\tnw: function(event, dx, dy) {\n\t\t\treturn $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));\n\t\t}\n\t},\n\n\t_propagate: function(n, event) {\n\t\t$.ui.plugin.call(this, n, [event, this.ui()]);\n\t\t(n != \"resize\" && this._trigger(n, event, this.ui()));\n\t},\n\n\tplugins: {},\n\n\tui: function() {\n\t\treturn {\n\t\t\toriginalElement: this.originalElement,\n\t\t\telement: this.element,\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\tsize: this.size,\n\t\t\toriginalSize: this.originalSize,\n\t\t\toriginalPosition: this.originalPosition\n\t\t};\n\t}\n\n});\n\n/*\n * Resizable Extensions\n */\n\n$.ui.plugin.add(\"resizable\", \"alsoResize\", {\n\n\tstart: function (event, ui) {\n\t\tvar that = $(this).data(\"resizable\"), o = that.options;\n\n\t\tvar _store = function (exp) {\n\t\t\t$(exp).each(function() {\n\t\t\t\tvar el = $(this);\n\t\t\t\tel.data(\"resizable-alsoresize\", {\n\t\t\t\t\twidth: parseInt(el.width(), 10), height: parseInt(el.height(), 10),\n\t\t\t\t\tleft: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\n\t\tif (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {\n\t\t\tif (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }\n\t\t\telse { $.each(o.alsoResize, function (exp) { _store(exp); }); }\n\t\t}else{\n\t\t\t_store(o.alsoResize);\n\t\t}\n\t},\n\n\tresize: function (event, ui) {\n\t\tvar that = $(this).data(\"resizable\"), o = that.options, os = that.originalSize, op = that.originalPosition;\n\n\t\tvar delta = {\n\t\t\theight: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,\n\t\t\ttop: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0\n\t\t},\n\n\t\t_alsoResize = function (exp, c) {\n\t\t\t$(exp).each(function() {\n\t\t\t\tvar el = $(this), start = $(this).data(\"resizable-alsoresize\"), style = {}, \n\t\t\t\t\tcss = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];\n\n\t\t\t\t$.each(css, function (i, prop) {\n\t\t\t\t\tvar sum = (start[prop]||0) + (delta[prop]||0);\n\t\t\t\t\tif (sum && sum >= 0)\n\t\t\t\t\t\tstyle[prop] = sum || null;\n\t\t\t\t});\n\n\t\t\t\tel.css(style);\n\t\t\t});\n\t\t};\n\n\t\tif (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {\n\t\t\t$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });\n\t\t}else{\n\t\t\t_alsoResize(o.alsoResize);\n\t\t}\n\t},\n\n\tstop: function (event, ui) {\n\t\t$(this).removeData(\"resizable-alsoresize\");\n\t}\n});\n\n$.ui.plugin.add(\"resizable\", \"animate\", {\n\n\tstop: function(event, ui) {\n\t\tvar that = $(this).data(\"resizable\"), o = that.options;\n\n\t\tvar pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),\n\t\t\t\t\tsoffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,\n\t\t\t\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width;\n\n\t\tvar style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },\n\t\t\t\t\tleft = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,\n\t\t\t\t\t\ttop = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;\n\n\t\tthat.element.animate(\n\t\t\t$.extend(style, top && left ? { top: top, left: left } : {}), {\n\t\t\t\tduration: o.animateDuration,\n\t\t\t\teasing: o.animateEasing,\n\t\t\t\tstep: function() {\n\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\twidth: parseInt(that.element.css('width'), 10),\n\t\t\t\t\t\theight: parseInt(that.element.css('height'), 10),\n\t\t\t\t\t\ttop: parseInt(that.element.css('top'), 10),\n\t\t\t\t\t\tleft: parseInt(that.element.css('left'), 10)\n\t\t\t\t\t};\n\n\t\t\t\t\tif (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });\n\n\t\t\t\t\t// propagating resize, and updating values for each animation step\n\t\t\t\t\tthat._updateCache(data);\n\t\t\t\t\tthat._propagate(\"resize\", event);\n\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n});\n\n$.ui.plugin.add(\"resizable\", \"containment\", {\n\n\tstart: function(event, ui) {\n\t\tvar that = $(this).data(\"resizable\"), o = that.options, el = that.element;\n\t\tvar oc = o.containment,\tce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;\n\t\tif (!ce) return;\n\n\t\tthat.containerElement = $(ce);\n\n\t\tif (/document/.test(oc) || oc == document) {\n\t\t\tthat.containerOffset = { left: 0, top: 0 };\n\t\t\tthat.containerPosition = { left: 0, top: 0 };\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: $(document), left: 0, top: 0,\n\t\t\t\twidth: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight\n\t\t\t};\n\t\t}\n\n\t\t// i'm a node, so compute top, left, right, bottom\n\t\telse {\n\t\t\tvar element = $(ce), p = [];\n\t\t\t$([ \"Top\", \"Right\", \"Left\", \"Bottom\" ]).each(function(i, name) { p[i] = num(element.css(\"padding\" + name)); });\n\n\t\t\tthat.containerOffset = element.offset();\n\t\t\tthat.containerPosition = element.position();\n\t\t\tthat.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };\n\n\t\t\tvar co = that.containerOffset, ch = that.containerSize.height,\tcw = that.containerSize.width,\n\t\t\t\t\t\twidth = ($.ui.hasScroll(ce, \"left\") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: ce, left: co.left, top: co.top, width: width, height: height\n\t\t\t};\n\t\t}\n\t},\n\n\tresize: function(event, ui) {\n\t\tvar that = $(this).data(\"resizable\"), o = that.options,\n\t\t\t\tps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position,\n\t\t\t\tpRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement;\n\n\t\tif (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;\n\n\t\tif (cp.left < (that._helper ? co.left : 0)) {\n\t\t\tthat.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));\n\t\t\tif (pRatio) that.size.height = that.size.width / that.aspectRatio;\n\t\t\tthat.position.left = o.helper ? co.left : 0;\n\t\t}\n\n\t\tif (cp.top < (that._helper ? co.top : 0)) {\n\t\t\tthat.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);\n\t\t\tif (pRatio) that.size.width = that.size.height * that.aspectRatio;\n\t\t\tthat.position.top = that._helper ? co.top : 0;\n\t\t}\n\n\t\tthat.offset.left = that.parentData.left+that.position.left;\n\t\tthat.offset.top = that.parentData.top+that.position.top;\n\n\t\tvar woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ),\n\t\t\t\t\thoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );\n\n\t\tvar isParent = that.containerElement.get(0) == that.element.parent().get(0),\n\t\t\tisOffsetRelative = /relative|absolute/.test(that.containerElement.css('position'));\n\n\t\tif(isParent && isOffsetRelative) woset -= that.parentData.left;\n\n\t\tif (woset + that.size.width >= that.parentData.width) {\n\t\t\tthat.size.width = that.parentData.width - woset;\n\t\t\tif (pRatio) that.size.height = that.size.width / that.aspectRatio;\n\t\t}\n\n\t\tif (hoset + that.size.height >= that.parentData.height) {\n\t\t\tthat.size.height = that.parentData.height - hoset;\n\t\t\tif (pRatio) that.size.width = that.size.height * that.aspectRatio;\n\t\t}\n\t},\n\n\tstop: function(event, ui){\n\t\tvar that = $(this).data(\"resizable\"), o = that.options, cp = that.position,\n\t\t\t\tco = that.containerOffset, cop = that.containerPosition, ce = that.containerElement;\n\n\t\tvar helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height;\n\n\t\tif (that._helper && !o.animate && (/relative/).test(ce.css('position')))\n\t\t\t$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });\n\n\t\tif (that._helper && !o.animate && (/static/).test(ce.css('position')))\n\t\t\t$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });\n\n\t}\n});\n\n$.ui.plugin.add(\"resizable\", \"ghost\", {\n\n\tstart: function(event, ui) {\n\n\t\tvar that = $(this).data(\"resizable\"), o = that.options, cs = that.size;\n\n\t\tthat.ghost = that.originalElement.clone();\n\t\tthat.ghost\n\t\t\t.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })\n\t\t\t.addClass('ui-resizable-ghost')\n\t\t\t.addClass(typeof o.ghost == 'string' ? o.ghost : '');\n\n\t\tthat.ghost.appendTo(that.helper);\n\n\t},\n\n\tresize: function(event, ui){\n\t\tvar that = $(this).data(\"resizable\"), o = that.options;\n\t\tif (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width });\n\t},\n\n\tstop: function(event, ui){\n\t\tvar that = $(this).data(\"resizable\"), o = that.options;\n\t\tif (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0));\n\t}\n\n});\n\n$.ui.plugin.add(\"resizable\", \"grid\", {\n\n\tresize: function(event, ui) {\n\t\tvar that = $(this).data(\"resizable\"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey;\n\t\to.grid = typeof o.grid == \"number\" ? [o.grid, o.grid] : o.grid;\n\t\tvar ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);\n\n\t\tif (/^(se|s|e)$/.test(a)) {\n\t\t\tthat.size.width = os.width + ox;\n\t\t\tthat.size.height = os.height + oy;\n\t\t}\n\t\telse if (/^(ne)$/.test(a)) {\n\t\t\tthat.size.width = os.width + ox;\n\t\t\tthat.size.height = os.height + oy;\n\t\t\tthat.position.top = op.top - oy;\n\t\t}\n\t\telse if (/^(sw)$/.test(a)) {\n\t\t\tthat.size.width = os.width + ox;\n\t\t\tthat.size.height = os.height + oy;\n\t\t\tthat.position.left = op.left - ox;\n\t\t}\n\t\telse {\n\t\t\tthat.size.width = os.width + ox;\n\t\t\tthat.size.height = os.height + oy;\n\t\t\tthat.position.top = op.top - oy;\n\t\t\tthat.position.left = op.left - ox;\n\t\t}\n\t}\n\n});\n\nvar num = function(v) {\n\treturn parseInt(v, 10) || 0;\n};\n\nvar isNumber = function(value) {\n\treturn !isNaN(parseInt(value, 10));\n};\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.selectable.js",
    "content": "/*!\n * jQuery UI Selectable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Selectables\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\n$.widget(\"ui.selectable\", $.ui.mouse, {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\tappendTo: 'body',\n\t\tautoRefresh: true,\n\t\tdistance: 0,\n\t\tfilter: '*',\n\t\ttolerance: 'touch'\n\t},\n\t_create: function() {\n\t\tvar that = this;\n\n\t\tthis.element.addClass(\"ui-selectable\");\n\n\t\tthis.dragged = false;\n\n\t\t// cache selectee children based on filter\n\t\tvar selectees;\n\t\tthis.refresh = function() {\n\t\t\tselectees = $(that.options.filter, that.element[0]);\n\t\t\tselectees.addClass(\"ui-selectee\");\n\t\t\tselectees.each(function() {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tvar pos = $this.offset();\n\t\t\t\t$.data(this, \"selectable-item\", {\n\t\t\t\t\telement: this,\n\t\t\t\t\t$element: $this,\n\t\t\t\t\tleft: pos.left,\n\t\t\t\t\ttop: pos.top,\n\t\t\t\t\tright: pos.left + $this.outerWidth(),\n\t\t\t\t\tbottom: pos.top + $this.outerHeight(),\n\t\t\t\t\tstartselected: false,\n\t\t\t\t\tselected: $this.hasClass('ui-selected'),\n\t\t\t\t\tselecting: $this.hasClass('ui-selecting'),\n\t\t\t\t\tunselecting: $this.hasClass('ui-unselecting')\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tthis.refresh();\n\n\t\tthis.selectees = selectees.addClass(\"ui-selectee\");\n\n\t\tthis._mouseInit();\n\n\t\tthis.helper = $(\"<div class='ui-selectable-helper'></div>\");\n\t},\n\n\t_destroy: function() {\n\t\tthis.selectees\n\t\t\t.removeClass(\"ui-selectee\")\n\t\t\t.removeData(\"selectable-item\");\n\t\tthis.element\n\t\t\t.removeClass(\"ui-selectable ui-selectable-disabled\");\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseStart: function(event) {\n\t\tvar that = this;\n\n\t\tthis.opos = [event.pageX, event.pageY];\n\n\t\tif (this.options.disabled)\n\t\t\treturn;\n\n\t\tvar options = this.options;\n\n\t\tthis.selectees = $(options.filter, this.element[0]);\n\n\t\tthis._trigger(\"start\", event);\n\n\t\t$(options.appendTo).append(this.helper);\n\t\t// position helper (lasso)\n\t\tthis.helper.css({\n\t\t\t\"left\": event.clientX,\n\t\t\t\"top\": event.clientY,\n\t\t\t\"width\": 0,\n\t\t\t\"height\": 0\n\t\t});\n\n\t\tif (options.autoRefresh) {\n\t\t\tthis.refresh();\n\t\t}\n\n\t\tthis.selectees.filter('.ui-selected').each(function() {\n\t\t\tvar selectee = $.data(this, \"selectable-item\");\n\t\t\tselectee.startselected = true;\n\t\t\tif (!event.metaKey && !event.ctrlKey) {\n\t\t\t\tselectee.$element.removeClass('ui-selected');\n\t\t\t\tselectee.selected = false;\n\t\t\t\tselectee.$element.addClass('ui-unselecting');\n\t\t\t\tselectee.unselecting = true;\n\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\tthat._trigger(\"unselecting\", event, {\n\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t$(event.target).parents().andSelf().each(function() {\n\t\t\tvar selectee = $.data(this, \"selectable-item\");\n\t\t\tif (selectee) {\n\t\t\t\tvar doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');\n\t\t\t\tselectee.$element\n\t\t\t\t\t.removeClass(doSelect ? \"ui-unselecting\" : \"ui-selected\")\n\t\t\t\t\t.addClass(doSelect ? \"ui-selecting\" : \"ui-unselecting\");\n\t\t\t\tselectee.unselecting = !doSelect;\n\t\t\t\tselectee.selecting = doSelect;\n\t\t\t\tselectee.selected = doSelect;\n\t\t\t\t// selectable (UN)SELECTING callback\n\t\t\t\tif (doSelect) {\n\t\t\t\t\tthat._trigger(\"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthat._trigger(\"unselecting\", event, {\n\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t},\n\n\t_mouseDrag: function(event) {\n\t\tvar that = this;\n\t\tthis.dragged = true;\n\n\t\tif (this.options.disabled)\n\t\t\treturn;\n\n\t\tvar options = this.options;\n\n\t\tvar x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;\n\t\tif (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }\n\t\tif (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }\n\t\tthis.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});\n\n\t\tthis.selectees.each(function() {\n\t\t\tvar selectee = $.data(this, \"selectable-item\");\n\t\t\t//prevent helper from being selected if appendTo: selectable\n\t\t\tif (!selectee || selectee.element == that.element[0])\n\t\t\t\treturn;\n\t\t\tvar hit = false;\n\t\t\tif (options.tolerance == 'touch') {\n\t\t\t\thit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );\n\t\t\t} else if (options.tolerance == 'fit') {\n\t\t\t\thit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);\n\t\t\t}\n\n\t\t\tif (hit) {\n\t\t\t\t// SELECT\n\t\t\t\tif (selectee.selected) {\n\t\t\t\t\tselectee.$element.removeClass('ui-selected');\n\t\t\t\t\tselectee.selected = false;\n\t\t\t\t}\n\t\t\t\tif (selectee.unselecting) {\n\t\t\t\t\tselectee.$element.removeClass('ui-unselecting');\n\t\t\t\t\tselectee.unselecting = false;\n\t\t\t\t}\n\t\t\t\tif (!selectee.selecting) {\n\t\t\t\t\tselectee.$element.addClass('ui-selecting');\n\t\t\t\t\tselectee.selecting = true;\n\t\t\t\t\t// selectable SELECTING callback\n\t\t\t\t\tthat._trigger(\"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// UNSELECT\n\t\t\t\tif (selectee.selecting) {\n\t\t\t\t\tif ((event.metaKey || event.ctrlKey) && selectee.startselected) {\n\t\t\t\t\t\tselectee.$element.removeClass('ui-selecting');\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tselectee.$element.addClass('ui-selected');\n\t\t\t\t\t\tselectee.selected = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselectee.$element.removeClass('ui-selecting');\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tif (selectee.startselected) {\n\t\t\t\t\t\t\tselectee.$element.addClass('ui-unselecting');\n\t\t\t\t\t\t\tselectee.unselecting = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger(\"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (selectee.selected) {\n\t\t\t\t\tif (!event.metaKey && !event.ctrlKey && !selectee.startselected) {\n\t\t\t\t\t\tselectee.$element.removeClass('ui-selected');\n\t\t\t\t\t\tselectee.selected = false;\n\n\t\t\t\t\t\tselectee.$element.addClass('ui-unselecting');\n\t\t\t\t\t\tselectee.unselecting = true;\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger(\"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function(event) {\n\t\tvar that = this;\n\n\t\tthis.dragged = false;\n\n\t\tvar options = this.options;\n\n\t\t$('.ui-unselecting', this.element[0]).each(function() {\n\t\t\tvar selectee = $.data(this, \"selectable-item\");\n\t\t\tselectee.$element.removeClass('ui-unselecting');\n\t\t\tselectee.unselecting = false;\n\t\t\tselectee.startselected = false;\n\t\t\tthat._trigger(\"unselected\", event, {\n\t\t\t\tunselected: selectee.element\n\t\t\t});\n\t\t});\n\t\t$('.ui-selecting', this.element[0]).each(function() {\n\t\t\tvar selectee = $.data(this, \"selectable-item\");\n\t\t\tselectee.$element.removeClass('ui-selecting').addClass('ui-selected');\n\t\t\tselectee.selecting = false;\n\t\t\tselectee.selected = true;\n\t\t\tselectee.startselected = true;\n\t\t\tthat._trigger(\"selected\", event, {\n\t\t\t\tselected: selectee.element\n\t\t\t});\n\t\t});\n\t\tthis._trigger(\"stop\", event);\n\n\t\tthis.helper.remove();\n\n\t\treturn false;\n\t}\n\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.slider.js",
    "content": "/*!\n * jQuery UI Slider @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Slider\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\n// number of pages in a slider\n// (how many times can you page up/down to go through the whole range)\nvar numPages = 5;\n\n$.widget( \"ui.slider\", $.ui.mouse, {\n\tversion: \"@VERSION\",\n\twidgetEventPrefix: \"slide\",\n\n\toptions: {\n\t\tanimate: false,\n\t\tdistance: 0,\n\t\tmax: 100,\n\t\tmin: 0,\n\t\torientation: \"horizontal\",\n\t\trange: false,\n\t\tstep: 1,\n\t\tvalue: 0,\n\t\tvalues: null\n\t},\n\n\t_create: function() {\n\t\tvar i,\n\t\t\to = this.options,\n\t\t\texistingHandles = this.element.find( \".ui-slider-handle\" ).addClass( \"ui-state-default ui-corner-all\" ),\n\t\t\thandle = \"<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>\",\n\t\t\thandleCount = ( o.values && o.values.length ) || 1,\n\t\t\thandles = [];\n\n\t\tthis._keySliding = false;\n\t\tthis._mouseSliding = false;\n\t\tthis._animateOff = true;\n\t\tthis._handleIndex = null;\n\t\tthis._detectOrientation();\n\t\tthis._mouseInit();\n\n\t\tthis.element\n\t\t\t.addClass( \"ui-slider\" +\n\t\t\t\t\" ui-slider-\" + this.orientation +\n\t\t\t\t\" ui-widget\" +\n\t\t\t\t\" ui-widget-content\" +\n\t\t\t\t\" ui-corner-all\" +\n\t\t\t\t( o.disabled ? \" ui-slider-disabled ui-disabled\" : \"\" ) );\n\n\t\tthis.range = $([]);\n\n\t\tif ( o.range ) {\n\t\t\tif ( o.range === true ) {\n\t\t\t\tif ( !o.values ) {\n\t\t\t\t\to.values = [ this._valueMin(), this._valueMin() ];\n\t\t\t\t}\n\t\t\t\tif ( o.values.length && o.values.length !== 2 ) {\n\t\t\t\t\to.values = [ o.values[0], o.values[0] ];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.range = $( \"<div></div>\" )\n\t\t\t\t.appendTo( this.element )\n\t\t\t\t.addClass( \"ui-slider-range\" +\n\t\t\t\t// note: this isn't the most fittingly semantic framework class for this element,\n\t\t\t\t// but worked best visually with a variety of themes\n\t\t\t\t\" ui-widget-header\" +\n\t\t\t\t( ( o.range === \"min\" || o.range === \"max\" ) ? \" ui-slider-range-\" + o.range : \"\" ) );\n\t\t}\n\n\t\tfor ( i = existingHandles.length; i < handleCount; i++ ) {\n\t\t\thandles.push( handle );\n\t\t}\n\n\t\tthis.handles = existingHandles.add( $( handles.join( \"\" ) ).appendTo( this.element ) );\n\n\t\tthis.handle = this.handles.eq( 0 );\n\n\t\tthis.handles.add( this.range ).filter( \"a\" )\n\t\t\t.click(function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t})\n\t\t\t.mouseenter(function() {\n\t\t\t\tif ( !o.disabled ) {\n\t\t\t\t\t$( this ).addClass( \"ui-state-hover\" );\n\t\t\t\t}\n\t\t\t})\n\t\t\t.mouseleave(function() {\n\t\t\t\t$( this ).removeClass( \"ui-state-hover\" );\n\t\t\t})\n\t\t\t.focus(function() {\n\t\t\t\tif ( !o.disabled ) {\n\t\t\t\t\t$( \".ui-slider .ui-state-focus\" ).removeClass( \"ui-state-focus\" );\n\t\t\t\t\t$( this ).addClass( \"ui-state-focus\" );\n\t\t\t\t} else {\n\t\t\t\t\t$( this ).blur();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.blur(function() {\n\t\t\t\t$( this ).removeClass( \"ui-state-focus\" );\n\t\t\t});\n\n\t\tthis.handles.each(function( i ) {\n\t\t\t$( this ).data( \"ui-slider-handle-index\", i );\n\t\t});\n\n\t\tthis._bind( this.handles, {\n\t\t\tkeydown: function( event ) {\n\t\t\t\tvar allowed, curVal, newVal, step,\n\t\t\t\t\tindex = $( event.target ).data( \"ui-slider-handle-index\" );\n\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\t\tcase $.ui.keyCode.END:\n\t\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tif ( !this._keySliding ) {\n\t\t\t\t\t\t\tthis._keySliding = true;\n\t\t\t\t\t\t\t$( event.target ).addClass( \"ui-state-active\" );\n\t\t\t\t\t\t\tallowed = this._start( event, index );\n\t\t\t\t\t\t\tif ( allowed === false ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tstep = this.options.step;\n\t\t\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\t\t\tcurVal = newVal = this.values( index );\n\t\t\t\t} else {\n\t\t\t\t\tcurVal = newVal = this.value();\n\t\t\t\t}\n\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\t\t\tnewVal = this._valueMin();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.ui.keyCode.END:\n\t\t\t\t\t\tnewVal = this._valueMax();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\t\t\tnewVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\t\t\tnewVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\t\t\tif ( curVal === this._valueMax() ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewVal = this._trimAlignValue( curVal + step );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\t\t\tif ( curVal === this._valueMin() ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewVal = this._trimAlignValue( curVal - step );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._slide( event, index, newVal );\n\t\t\t},\n\t\t\tkeyup: function( event ) {\n\t\t\t\tvar index = $( event.target ).data( \"ui-slider-handle-index\" );\n\n\t\t\t\tif ( this._keySliding ) {\n\t\t\t\t\tthis._keySliding = false;\n\t\t\t\t\tthis._stop( event, index );\n\t\t\t\t\tthis._change( event, index );\n\t\t\t\t\t$( event.target ).removeClass( \"ui-state-active\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis._refreshValue();\n\n\t\tthis._animateOff = false;\n\t},\n\n\t_destroy: function() {\n\t\tthis.handles.remove();\n\t\tthis.range.remove();\n\n\t\tthis.element\n\t\t\t.removeClass( \"ui-slider\" +\n\t\t\t\t\" ui-slider-horizontal\" +\n\t\t\t\t\" ui-slider-vertical\" +\n\t\t\t\t\" ui-slider-disabled\" +\n\t\t\t\t\" ui-widget\" +\n\t\t\t\t\" ui-widget-content\" +\n\t\t\t\t\" ui-corner-all\" );\n\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,\n\t\t\tthat = this,\n\t\t\to = this.options;\n\n\t\tif ( o.disabled ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.elementSize = {\n\t\t\twidth: this.element.outerWidth(),\n\t\t\theight: this.element.outerHeight()\n\t\t};\n\t\tthis.elementOffset = this.element.offset();\n\n\t\tposition = { x: event.pageX, y: event.pageY };\n\t\tnormValue = this._normValueFromMouse( position );\n\t\tdistance = this._valueMax() - this._valueMin() + 1;\n\t\tthis.handles.each(function( i ) {\n\t\t\tvar thisDistance = Math.abs( normValue - that.values(i) );\n\t\t\tif ( distance > thisDistance ) {\n\t\t\t\tdistance = thisDistance;\n\t\t\t\tclosestHandle = $( this );\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t});\n\n\t\t// workaround for bug #3736 (if both handles of a range are at 0,\n\t\t// the first is always used as the one with least distance,\n\t\t// and moving it is obviously prevented by preventing negative ranges)\n\t\tif( o.range === true && this.values(1) === o.min ) {\n\t\t\tindex += 1;\n\t\t\tclosestHandle = $( this.handles[index] );\n\t\t}\n\n\t\tallowed = this._start( event, index );\n\t\tif ( allowed === false ) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._mouseSliding = true;\n\n\t\tthis._handleIndex = index;\n\n\t\tclosestHandle\n\t\t\t.addClass( \"ui-state-active\" )\n\t\t\t.focus();\n\n\t\toffset = closestHandle.offset();\n\t\tmouseOverHandle = !$( event.target ).parents().andSelf().is( \".ui-slider-handle\" );\n\t\tthis._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {\n\t\t\tleft: event.pageX - offset.left - ( closestHandle.width() / 2 ),\n\t\t\ttop: event.pageY - offset.top -\n\t\t\t\t( closestHandle.height() / 2 ) -\n\t\t\t\t( parseInt( closestHandle.css(\"borderTopWidth\"), 10 ) || 0 ) -\n\t\t\t\t( parseInt( closestHandle.css(\"borderBottomWidth\"), 10 ) || 0) +\n\t\t\t\t( parseInt( closestHandle.css(\"marginTop\"), 10 ) || 0)\n\t\t};\n\n\t\tif ( !this.handles.hasClass( \"ui-state-hover\" ) ) {\n\t\t\tthis._slide( event, index, normValue );\n\t\t}\n\t\tthis._animateOff = true;\n\t\treturn true;\n\t},\n\n\t_mouseStart: function( event ) {\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function( event ) {\n\t\tvar position = { x: event.pageX, y: event.pageY },\n\t\t\tnormValue = this._normValueFromMouse( position );\n\n\t\tthis._slide( event, this._handleIndex, normValue );\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\t\tthis.handles.removeClass( \"ui-state-active\" );\n\t\tthis._mouseSliding = false;\n\n\t\tthis._stop( event, this._handleIndex );\n\t\tthis._change( event, this._handleIndex );\n\n\t\tthis._handleIndex = null;\n\t\tthis._clickOffset = null;\n\t\tthis._animateOff = false;\n\n\t\treturn false;\n\t},\n\n\t_detectOrientation: function() {\n\t\tthis.orientation = ( this.options.orientation === \"vertical\" ) ? \"vertical\" : \"horizontal\";\n\t},\n\n\t_normValueFromMouse: function( position ) {\n\t\tvar pixelTotal,\n\t\t\tpixelMouse,\n\t\t\tpercentMouse,\n\t\t\tvalueTotal,\n\t\t\tvalueMouse;\n\n\t\tif ( this.orientation === \"horizontal\" ) {\n\t\t\tpixelTotal = this.elementSize.width;\n\t\t\tpixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );\n\t\t} else {\n\t\t\tpixelTotal = this.elementSize.height;\n\t\t\tpixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );\n\t\t}\n\n\t\tpercentMouse = ( pixelMouse / pixelTotal );\n\t\tif ( percentMouse > 1 ) {\n\t\t\tpercentMouse = 1;\n\t\t}\n\t\tif ( percentMouse < 0 ) {\n\t\t\tpercentMouse = 0;\n\t\t}\n\t\tif ( this.orientation === \"vertical\" ) {\n\t\t\tpercentMouse = 1 - percentMouse;\n\t\t}\n\n\t\tvalueTotal = this._valueMax() - this._valueMin();\n\t\tvalueMouse = this._valueMin() + percentMouse * valueTotal;\n\n\t\treturn this._trimAlignValue( valueMouse );\n\t},\n\n\t_start: function( event, index ) {\n\t\tvar uiHash = {\n\t\t\thandle: this.handles[ index ],\n\t\t\tvalue: this.value()\n\t\t};\n\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\tuiHash.value = this.values( index );\n\t\t\tuiHash.values = this.values();\n\t\t}\n\t\treturn this._trigger( \"start\", event, uiHash );\n\t},\n\n\t_slide: function( event, index, newVal ) {\n\t\tvar otherVal,\n\t\t\tnewValues,\n\t\t\tallowed;\n\n\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\totherVal = this.values( index ? 0 : 1 );\n\n\t\t\tif ( ( this.options.values.length === 2 && this.options.range === true ) &&\n\t\t\t\t\t( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )\n\t\t\t\t) {\n\t\t\t\tnewVal = otherVal;\n\t\t\t}\n\n\t\t\tif ( newVal !== this.values( index ) ) {\n\t\t\t\tnewValues = this.values();\n\t\t\t\tnewValues[ index ] = newVal;\n\t\t\t\t// A slide can be canceled by returning false from the slide callback\n\t\t\t\tallowed = this._trigger( \"slide\", event, {\n\t\t\t\t\thandle: this.handles[ index ],\n\t\t\t\t\tvalue: newVal,\n\t\t\t\t\tvalues: newValues\n\t\t\t\t} );\n\t\t\t\totherVal = this.values( index ? 0 : 1 );\n\t\t\t\tif ( allowed !== false ) {\n\t\t\t\t\tthis.values( index, newVal, true );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif ( newVal !== this.value() ) {\n\t\t\t\t// A slide can be canceled by returning false from the slide callback\n\t\t\t\tallowed = this._trigger( \"slide\", event, {\n\t\t\t\t\thandle: this.handles[ index ],\n\t\t\t\t\tvalue: newVal\n\t\t\t\t} );\n\t\t\t\tif ( allowed !== false ) {\n\t\t\t\t\tthis.value( newVal );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_stop: function( event, index ) {\n\t\tvar uiHash = {\n\t\t\thandle: this.handles[ index ],\n\t\t\tvalue: this.value()\n\t\t};\n\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\tuiHash.value = this.values( index );\n\t\t\tuiHash.values = this.values();\n\t\t}\n\n\t\tthis._trigger( \"stop\", event, uiHash );\n\t},\n\n\t_change: function( event, index ) {\n\t\tif ( !this._keySliding && !this._mouseSliding ) {\n\t\t\tvar uiHash = {\n\t\t\t\thandle: this.handles[ index ],\n\t\t\t\tvalue: this.value()\n\t\t\t};\n\t\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\t\tuiHash.value = this.values( index );\n\t\t\t\tuiHash.values = this.values();\n\t\t\t}\n\n\t\t\tthis._trigger( \"change\", event, uiHash );\n\t\t}\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( arguments.length ) {\n\t\t\tthis.options.value = this._trimAlignValue( newValue );\n\t\t\tthis._refreshValue();\n\t\t\tthis._change( null, 0 );\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._value();\n\t},\n\n\tvalues: function( index, newValue ) {\n\t\tvar vals,\n\t\t\tnewValues,\n\t\t\ti;\n\n\t\tif ( arguments.length > 1 ) {\n\t\t\tthis.options.values[ index ] = this._trimAlignValue( newValue );\n\t\t\tthis._refreshValue();\n\t\t\tthis._change( null, index );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( arguments.length ) {\n\t\t\tif ( $.isArray( arguments[ 0 ] ) ) {\n\t\t\t\tvals = this.options.values;\n\t\t\t\tnewValues = arguments[ 0 ];\n\t\t\t\tfor ( i = 0; i < vals.length; i += 1 ) {\n\t\t\t\t\tvals[ i ] = this._trimAlignValue( newValues[ i ] );\n\t\t\t\t\tthis._change( null, i );\n\t\t\t\t}\n\t\t\t\tthis._refreshValue();\n\t\t\t} else {\n\t\t\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\t\t\treturn this._values( index );\n\t\t\t\t} else {\n\t\t\t\t\treturn this.value();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._values();\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar i,\n\t\t\tvalsLength = 0;\n\n\t\tif ( $.isArray( this.options.values ) ) {\n\t\t\tvalsLength = this.options.values.length;\n\t\t}\n\n\t\t$.Widget.prototype._setOption.apply( this, arguments );\n\n\t\tswitch ( key ) {\n\t\t\tcase \"disabled\":\n\t\t\t\tif ( value ) {\n\t\t\t\t\tthis.handles.filter( \".ui-state-focus\" ).blur();\n\t\t\t\t\tthis.handles.removeClass( \"ui-state-hover\" );\n\t\t\t\t\tthis.handles.prop( \"disabled\", true );\n\t\t\t\t\tthis.element.addClass( \"ui-disabled\" );\n\t\t\t\t} else {\n\t\t\t\t\tthis.handles.prop( \"disabled\", false );\n\t\t\t\t\tthis.element.removeClass( \"ui-disabled\" );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"orientation\":\n\t\t\t\tthis._detectOrientation();\n\t\t\t\tthis.element\n\t\t\t\t\t.removeClass( \"ui-slider-horizontal ui-slider-vertical\" )\n\t\t\t\t\t.addClass( \"ui-slider-\" + this.orientation );\n\t\t\t\tthis._refreshValue();\n\t\t\t\tbreak;\n\t\t\tcase \"value\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refreshValue();\n\t\t\t\tthis._change( null, 0 );\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"values\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refreshValue();\n\t\t\t\tfor ( i = 0; i < valsLength; i += 1 ) {\n\t\t\t\t\tthis._change( null, i );\n\t\t\t\t}\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\t//internal value getter\n\t// _value() returns value trimmed by min and max, aligned by step\n\t_value: function() {\n\t\tvar val = this.options.value;\n\t\tval = this._trimAlignValue( val );\n\n\t\treturn val;\n\t},\n\n\t//internal values getter\n\t// _values() returns array of values trimmed by min and max, aligned by step\n\t// _values( index ) returns single value trimmed by min and max, aligned by step\n\t_values: function( index ) {\n\t\tvar val,\n\t\t\tvals,\n\t\t\ti;\n\n\t\tif ( arguments.length ) {\n\t\t\tval = this.options.values[ index ];\n\t\t\tval = this._trimAlignValue( val );\n\n\t\t\treturn val;\n\t\t} else {\n\t\t\t// .slice() creates a copy of the array\n\t\t\t// this copy gets trimmed by min and max and then returned\n\t\t\tvals = this.options.values.slice();\n\t\t\tfor ( i = 0; i < vals.length; i+= 1) {\n\t\t\t\tvals[ i ] = this._trimAlignValue( vals[ i ] );\n\t\t\t}\n\n\t\t\treturn vals;\n\t\t}\n\t},\n\n\t// returns the step-aligned value that val is closest to, between (inclusive) min and max\n\t_trimAlignValue: function( val ) {\n\t\tif ( val <= this._valueMin() ) {\n\t\t\treturn this._valueMin();\n\t\t}\n\t\tif ( val >= this._valueMax() ) {\n\t\t\treturn this._valueMax();\n\t\t}\n\t\tvar step = ( this.options.step > 0 ) ? this.options.step : 1,\n\t\t\tvalModStep = (val - this._valueMin()) % step,\n\t\t\talignValue = val - valModStep;\n\n\t\tif ( Math.abs(valModStep) * 2 >= step ) {\n\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n\t\t}\n\n\t\t// Since JavaScript has problems with large floats, round\n\t\t// the final value to 5 digits after the decimal point (see #4124)\n\t\treturn parseFloat( alignValue.toFixed(5) );\n\t},\n\n\t_valueMin: function() {\n\t\treturn this.options.min;\n\t},\n\n\t_valueMax: function() {\n\t\treturn this.options.max;\n\t},\n\n\t_refreshValue: function() {\n\t\tvar lastValPercent, valPercent, value, valueMin, valueMax,\n\t\t\toRange = this.options.range,\n\t\t\to = this.options,\n\t\t\tthat = this,\n\t\t\tanimate = ( !this._animateOff ) ? o.animate : false,\n\t\t\t_set = {};\n\n\t\tif ( this.options.values && this.options.values.length ) {\n\t\t\tthis.handles.each(function( i, j ) {\n\t\t\t\tvalPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;\n\t\t\t\t_set[ that.orientation === \"horizontal\" ? \"left\" : \"bottom\" ] = valPercent + \"%\";\n\t\t\t\t$( this ).stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( _set, o.animate );\n\t\t\t\tif ( that.options.range === true ) {\n\t\t\t\t\tif ( that.orientation === \"horizontal\" ) {\n\t\t\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( { left: valPercent + \"%\" }, o.animate );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( i === 1 ) {\n\t\t\t\t\t\t\tthat.range[ animate ? \"animate\" : \"css\" ]( { width: ( valPercent - lastValPercent ) + \"%\" }, { queue: false, duration: o.animate } );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( { bottom: ( valPercent ) + \"%\" }, o.animate );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( i === 1 ) {\n\t\t\t\t\t\t\tthat.range[ animate ? \"animate\" : \"css\" ]( { height: ( valPercent - lastValPercent ) + \"%\" }, { queue: false, duration: o.animate } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastValPercent = valPercent;\n\t\t\t});\n\t\t} else {\n\t\t\tvalue = this.value();\n\t\t\tvalueMin = this._valueMin();\n\t\t\tvalueMax = this._valueMax();\n\t\t\tvalPercent = ( valueMax !== valueMin ) ?\n\t\t\t\t\t( value - valueMin ) / ( valueMax - valueMin ) * 100 :\n\t\t\t\t\t0;\n\t\t\t_set[ this.orientation === \"horizontal\" ? \"left\" : \"bottom\" ] = valPercent + \"%\";\n\t\t\tthis.handle.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( _set, o.animate );\n\n\t\t\tif ( oRange === \"min\" && this.orientation === \"horizontal\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( { width: valPercent + \"%\" }, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"max\" && this.orientation === \"horizontal\" ) {\n\t\t\t\tthis.range[ animate ? \"animate\" : \"css\" ]( { width: ( 100 - valPercent ) + \"%\" }, { queue: false, duration: o.animate } );\n\t\t\t}\n\t\t\tif ( oRange === \"min\" && this.orientation === \"vertical\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( { height: valPercent + \"%\" }, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"max\" && this.orientation === \"vertical\" ) {\n\t\t\t\tthis.range[ animate ? \"animate\" : \"css\" ]( { height: ( 100 - valPercent ) + \"%\" }, { queue: false, duration: o.animate } );\n\t\t\t}\n\t\t}\n\t}\n\n});\n\n}(jQuery));\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.sortable.js",
    "content": "/*!\n * jQuery UI Sortable @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Sortables\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.mouse.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\n$.widget(\"ui.sortable\", $.ui.mouse, {\n\tversion: \"@VERSION\",\n\twidgetEventPrefix: \"sort\",\n\tready: false,\n\toptions: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: 'auto',\n\t\tcursorAt: false,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: '> *',\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000\n\t},\n\t_create: function() {\n\n\t\tvar o = this.options;\n\t\tthis.containerCache = {};\n\t\tthis.element.addClass(\"ui-sortable\");\n\n\t\t//Get the items\n\t\tthis.refresh();\n\n\t\t//Let's determine if the items are being displayed horizontally\n\t\tthis.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;\n\n\t\t//Let's determine the parent's offset\n\t\tthis.offset = this.element.offset();\n\n\t\t//Initialize mouse events for interaction\n\t\tthis._mouseInit();\n\n\t\t//We're ready to go\n\t\tthis.ready = true\n\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass(\"ui-sortable ui-sortable-disabled\");\n\t\tthis._mouseDestroy();\n\n\t\tfor ( var i = this.items.length - 1; i >= 0; i-- )\n\t\t\tthis.items[i].item.removeData(this.widgetName + \"-item\");\n\n\t\treturn this;\n\t},\n\n\t_setOption: function(key, value){\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.options[ key ] = value;\n\n\t\t\tthis.widget().toggleClass( \"ui-sortable-disabled\", !!value );\n\t\t} else {\n\t\t\t// Don't call widget base _setOption for disable as it adds ui-state-disabled class\n\t\t\t$.Widget.prototype._setOption.apply(this, arguments);\n\t\t}\n\t},\n\n\t_mouseCapture: function(event, overrideHandle) {\n\t\tvar that = this;\n\n\t\tif (this.reverting) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(this.options.disabled || this.options.type == 'static') return false;\n\n\t\t//We have to refresh the items data once first\n\t\tthis._refreshItems(event);\n\n\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n\t\tvar currentItem = null, nodes = $(event.target).parents().each(function() {\n\t\t\tif($.data(this, that.widgetName + '-item') == that) {\n\t\t\t\tcurrentItem = $(this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target);\n\n\t\tif(!currentItem) return false;\n\t\tif(this.options.handle && !overrideHandle) {\n\t\t\tvar validHandle = false;\n\n\t\t\t$(this.options.handle, currentItem).find(\"*\").andSelf().each(function() { if(this == event.target) validHandle = true; });\n\t\t\tif(!validHandle) return false;\n\t\t}\n\n\t\tthis.currentItem = currentItem;\n\t\tthis._removeCurrentsFromItems();\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function(event, overrideHandle, noActivation) {\n\n\t\tvar o = this.options;\n\t\tthis.currentContainer = this;\n\n\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture\n\t\tthis.refreshPositions();\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper(event);\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Get the next scrolling parent\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.currentItem.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend(this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\n\t\t});\n\n\t\t// Only after we got the offset, we can change the helper's position to absolute\n\t\t// TODO: Still need to figure out a way to make relative sorting possible\n\t\tthis.helper.css(\"position\", \"absolute\");\n\t\tthis.cssPosition = this.helper.css(\"position\");\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this._generatePosition(event);\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied\n\t\t(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\n\n\t\t//Cache the former DOM position\n\t\tthis.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };\n\n\t\t//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way\n\t\tif(this.helper[0] != this.currentItem[0]) {\n\t\t\tthis.currentItem.hide();\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthis._createPlaceholder();\n\n\t\t//Set a containment if given in the options\n\t\tif(o.containment)\n\t\t\tthis._setContainment();\n\n\t\tif(o.cursor) { // cursor option\n\t\t\tif ($('body').css(\"cursor\")) this._storedCursor = $('body').css(\"cursor\");\n\t\t\t$('body').css(\"cursor\", o.cursor);\n\t\t}\n\n\t\tif(o.opacity) { // opacity option\n\t\t\tif (this.helper.css(\"opacity\")) this._storedOpacity = this.helper.css(\"opacity\");\n\t\t\tthis.helper.css(\"opacity\", o.opacity);\n\t\t}\n\n\t\tif(o.zIndex) { // zIndex option\n\t\t\tif (this.helper.css(\"zIndex\")) this._storedZIndex = this.helper.css(\"zIndex\");\n\t\t\tthis.helper.css(\"zIndex\", o.zIndex);\n\t\t}\n\n\t\t//Prepare scrolling\n\t\tif(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')\n\t\t\tthis.overflowOffset = this.scrollParent.offset();\n\n\t\t//Call callbacks\n\t\tthis._trigger(\"start\", event, this._uiHash());\n\n\t\t//Recache the helper size\n\t\tif(!this._preserveHelperProportions)\n\t\t\tthis._cacheHelperProportions();\n\n\n\t\t//Post 'activate' events to possible containers\n\t\tif(!noActivation) {\n\t\t\t for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger(\"activate\", event, this._uiHash(this)); }\n\t\t}\n\n\t\t//Prepare possible droppables\n\t\tif($.ui.ddmanager)\n\t\t\t$.ui.ddmanager.current = this;\n\n\t\tif ($.ui.ddmanager && !o.dropBehaviour)\n\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\n\t\tthis.dragging = true;\n\n\t\tthis.helper.addClass(\"ui-sortable-helper\");\n\t\tthis._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position\n\t\treturn true;\n\n\t},\n\n\t_mouseDrag: function(event) {\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition(event);\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\tif (!this.lastPositionAbs) {\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t}\n\n\t\t//Do scrolling\n\t\tif(this.options.scroll) {\n\t\t\tvar o = this.options, scrolled = false;\n\t\t\tif(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {\n\n\t\t\t\tif((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)\n\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;\n\t\t\t\telse if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)\n\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;\n\n\t\t\t\tif((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)\n\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;\n\t\t\t\telse if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)\n\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;\n\n\t\t\t} else {\n\n\t\t\t\tif(event.pageY - $(document).scrollTop() < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\n\t\t\t\telse if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\n\n\t\t\t\tif(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\n\t\t\t\telse if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)\n\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\n\n\t\t\t}\n\n\t\t\tif(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)\n\t\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\t\t}\n\n\t\t//Regenerate the absolute position used for position checks\n\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\t//Set the helper position\n\t\tif(!this.options.axis || this.options.axis != \"y\") this.helper[0].style.left = this.position.left+'px';\n\t\tif(!this.options.axis || this.options.axis != \"x\") this.helper[0].style.top = this.position.top+'px';\n\n\t\t//Rearrange\n\t\tfor (var i = this.items.length - 1; i >= 0; i--) {\n\n\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\tvar item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);\n\t\t\tif (!intersection) continue;\n\n\t\t\tif(itemElement != this.currentItem[0] //cannot intersect with itself\n\t\t\t\t&&\tthis.placeholder[intersection == 1 ? \"next\" : \"prev\"]()[0] != itemElement //no useless actions that have been done before\n\t\t\t\t&&\t!$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked\n\t\t\t\t&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)\n\t\t\t\t//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container\n\t\t\t) {\n\n\t\t\t\tthis.direction = intersection == 1 ? \"down\" : \"up\";\n\n\t\t\t\tif (this.options.tolerance == \"pointer\" || this._intersectsWithSides(item)) {\n\t\t\t\t\tthis._rearrange(event, item);\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tthis._contactContainers(event);\n\n\t\t//Interconnect with droppables\n\t\tif($.ui.ddmanager) $.ui.ddmanager.drag(this, event);\n\n\t\t//Call callbacks\n\t\tthis._trigger('sort', event, this._uiHash());\n\n\t\tthis.lastPositionAbs = this.positionAbs;\n\t\treturn false;\n\n\t},\n\n\t_mouseStop: function(event, noPropagation) {\n\n\t\tif(!event) return;\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tif ($.ui.ddmanager && !this.options.dropBehaviour)\n\t\t\t$.ui.ddmanager.drop(this, event);\n\n\t\tif(this.options.revert) {\n\t\t\tvar that = this;\n\t\t\tvar cur = this.placeholder.offset();\n\n\t\t\tthis.reverting = true;\n\n\t\t\t$(this.helper).animate({\n\t\t\t\tleft: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),\n\t\t\t\ttop: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)\n\t\t\t}, parseInt(this.options.revert, 10) || 500, function() {\n\t\t\t\tthat._clear(event);\n\t\t\t});\n\t\t} else {\n\t\t\tthis._clear(event, noPropagation);\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tcancel: function() {\n\n\t\tif(this.dragging) {\n\n\t\t\tthis._mouseUp({ target: null });\n\n\t\t\tif(this.options.helper == \"original\")\n\t\t\t\tthis.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\");\n\t\t\telse\n\t\t\t\tthis.currentItem.show();\n\n\t\t\t//Post deactivating events to containers\n\t\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tthis.containers[i]._trigger(\"deactivate\", null, this._uiHash(this));\n\t\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\t\tthis.containers[i]._trigger(\"out\", null, this._uiHash(this));\n\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif (this.placeholder) {\n\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n\t\t\tif(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n\t\t\tif(this.options.helper != \"original\" && this.helper && this.helper[0].parentNode) this.helper.remove();\n\n\t\t\t$.extend(this, {\n\t\t\t\thelper: null,\n\t\t\t\tdragging: false,\n\t\t\t\treverting: false,\n\t\t\t\t_noFinalSort: null\n\t\t\t});\n\n\t\t\tif(this.domPosition.prev) {\n\t\t\t\t$(this.domPosition.prev).after(this.currentItem);\n\t\t\t} else {\n\t\t\t\t$(this.domPosition.parent).prepend(this.currentItem);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tserialize: function(o) {\n\n\t\tvar items = this._getItemsAsjQuery(o && o.connected);\n\t\tvar str = []; o = o || {};\n\n\t\t$(items).each(function() {\n\t\t\tvar res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));\n\t\t\tif(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));\n\t\t});\n\n\t\tif(!str.length && o.key) {\n\t\t\tstr.push(o.key + '=');\n\t\t}\n\n\t\treturn str.join('&');\n\n\t},\n\n\ttoArray: function(o) {\n\n\t\tvar items = this._getItemsAsjQuery(o && o.connected);\n\t\tvar ret = []; o = o || {};\n\n\t\titems.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });\n\t\treturn ret;\n\n\t},\n\n\t/* Be careful with the following core functions */\n\t_intersectsWith: function(item) {\n\n\t\tvar x1 = this.positionAbs.left,\n\t\t\tx2 = x1 + this.helperProportions.width,\n\t\t\ty1 = this.positionAbs.top,\n\t\t\ty2 = y1 + this.helperProportions.height;\n\n\t\tvar l = item.left,\n\t\t\tr = l + item.width,\n\t\t\tt = item.top,\n\t\t\tb = t + item.height;\n\n\t\tvar dyClick = this.offset.click.top,\n\t\t\tdxClick = this.offset.click.left;\n\n\t\tvar isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;\n\n\t\tif(\t   this.options.tolerance == \"pointer\"\n\t\t\t|| this.options.forcePointerForContainers\n\t\t\t|| (this.options.tolerance != \"pointer\" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])\n\t\t) {\n\t\t\treturn isOverElement;\n\t\t} else {\n\n\t\t\treturn (l < x1 + (this.helperProportions.width / 2) // Right Half\n\t\t\t\t&& x2 - (this.helperProportions.width / 2) < r // Left Half\n\t\t\t\t&& t < y1 + (this.helperProportions.height / 2) // Bottom Half\n\t\t\t\t&& y2 - (this.helperProportions.height / 2) < b ); // Top Half\n\n\t\t}\n\t},\n\n\t_intersectsWithPointer: function(item) {\n\n\t\tvar isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),\n\t\t\tisOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth,\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif (!isOverElement)\n\t\t\treturn false;\n\n\t\treturn this.floating ?\n\t\t\t( ((horizontalDirection && horizontalDirection == \"right\") || verticalDirection == \"down\") ? 2 : 1 )\n\t\t\t: ( verticalDirection && (verticalDirection == \"down\" ? 2 : 1) );\n\n\t},\n\n\t_intersectsWithSides: function(item) {\n\n\t\tvar isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),\n\t\t\tisOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif (this.floating && horizontalDirection) {\n\t\t\treturn ((horizontalDirection == \"right\" && isOverRightHalf) || (horizontalDirection == \"left\" && !isOverRightHalf));\n\t\t} else {\n\t\t\treturn verticalDirection && ((verticalDirection == \"down\" && isOverBottomHalf) || (verticalDirection == \"up\" && !isOverBottomHalf));\n\t\t}\n\n\t},\n\n\t_getDragVerticalDirection: function() {\n\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n\t\treturn delta != 0 && (delta > 0 ? \"down\" : \"up\");\n\t},\n\n\t_getDragHorizontalDirection: function() {\n\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n\t\treturn delta != 0 && (delta > 0 ? \"right\" : \"left\");\n\t},\n\n\trefresh: function(event) {\n\t\tthis._refreshItems(event);\n\t\tthis.refreshPositions();\n\t\treturn this;\n\t},\n\n\t_connectWith: function() {\n\t\tvar options = this.options;\n\t\treturn options.connectWith.constructor == String\n\t\t\t? [options.connectWith]\n\t\t\t: options.connectWith;\n\t},\n\n\t_getItemsAsjQuery: function(connected) {\n\n\t\tvar items = [];\n\t\tvar queries = [];\n\t\tvar connectWith = this._connectWith();\n\n\t\tif(connectWith && connected) {\n\t\t\tfor (var i = connectWith.length - 1; i >= 0; i--){\n\t\t\t\tvar cur = $(connectWith[i]);\n\t\t\t\tfor (var j = cur.length - 1; j >= 0; j--){\n\t\t\t\t\tvar inst = $.data(cur[j], this.widgetName);\n\t\t\t\t\tif(inst && inst != this && !inst.options.disabled) {\n\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(\".ui-sortable-helper\").not('.ui-sortable-placeholder'), inst]);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\t\t}\n\n\t\tqueries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(\".ui-sortable-helper\").not('.ui-sortable-placeholder'), this]);\n\n\t\tfor (var i = queries.length - 1; i >= 0; i--){\n\t\t\tqueries[i][0].each(function() {\n\t\t\t\titems.push(this);\n\t\t\t});\n\t\t};\n\n\t\treturn $(items);\n\n\t},\n\n\t_removeCurrentsFromItems: function() {\n\n\t\tvar list = this.currentItem.find(\":data(\" + this.widgetName + \"-item)\");\n\n\t\tfor (var i=0; i < this.items.length; i++) {\n\n\t\t\tfor (var j=0; j < list.length; j++) {\n\t\t\t\tif(list[j] == this.items[i].item[0])\n\t\t\t\t\tthis.items.splice(i,1);\n\t\t\t};\n\n\t\t};\n\n\t},\n\n\t_refreshItems: function(event) {\n\n\t\tthis.items = [];\n\t\tthis.containers = [this];\n\t\tvar items = this.items;\n\t\tvar queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];\n\t\tvar connectWith = this._connectWith();\n\n\t\tif(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down\n\t\t\tfor (var i = connectWith.length - 1; i >= 0; i--){\n\t\t\t\tvar cur = $(connectWith[i]);\n\t\t\t\tfor (var j = cur.length - 1; j >= 0; j--){\n\t\t\t\t\tvar inst = $.data(cur[j], this.widgetName);\n\t\t\t\t\tif(inst && inst != this && !inst.options.disabled) {\n\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);\n\t\t\t\t\t\tthis.containers.push(inst);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\t\t}\n\n\t\tfor (var i = queries.length - 1; i >= 0; i--) {\n\t\t\tvar targetData = queries[i][1];\n\t\t\tvar _queries = queries[i][0];\n\n\t\t\tfor (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {\n\t\t\t\tvar item = $(_queries[j]);\n\n\t\t\t\titem.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)\n\n\t\t\t\titems.push({\n\t\t\t\t\titem: item,\n\t\t\t\t\tinstance: targetData,\n\t\t\t\t\twidth: 0, height: 0,\n\t\t\t\t\tleft: 0, top: 0\n\t\t\t\t});\n\t\t\t};\n\t\t};\n\n\t},\n\n\trefreshPositions: function(fast) {\n\n\t\t//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change\n\t\tif(this.offsetParent && this.helper) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\tfor (var i = this.items.length - 1; i >= 0; i--){\n\t\t\tvar item = this.items[i];\n\n\t\t\t//We ignore calculating positions of all connected containers when we're not over them\n\t\t\tif(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])\n\t\t\t\tcontinue;\n\n\t\t\tvar t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;\n\n\t\t\tif (!fast) {\n\t\t\t\titem.width = t.outerWidth();\n\t\t\t\titem.height = t.outerHeight();\n\t\t\t}\n\n\t\t\tvar p = t.offset();\n\t\t\titem.left = p.left;\n\t\t\titem.top = p.top;\n\t\t};\n\n\t\tif(this.options.custom && this.options.custom.refreshContainers) {\n\t\t\tthis.options.custom.refreshContainers.call(this);\n\t\t} else {\n\t\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tvar p = this.containers[i].element.offset();\n\t\t\t\tthis.containers[i].containerCache.left = p.left;\n\t\t\t\tthis.containers[i].containerCache.top = p.top;\n\t\t\t\tthis.containers[i].containerCache.width\t= this.containers[i].element.outerWidth();\n\t\t\t\tthis.containers[i].containerCache.height = this.containers[i].element.outerHeight();\n\t\t\t};\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_createPlaceholder: function(that) {\n\t\tthat = that || this;\n\t\tvar o = that.options;\n\n\t\tif(!o.placeholder || o.placeholder.constructor == String) {\n\t\t\tvar className = o.placeholder;\n\t\t\to.placeholder = {\n\t\t\t\telement: function() {\n\n\t\t\t\t\tvar el = $(document.createElement(that.currentItem[0].nodeName))\n\t\t\t\t\t\t.addClass(className || that.currentItem[0].className+\" ui-sortable-placeholder\")\n\t\t\t\t\t\t.removeClass(\"ui-sortable-helper\")[0];\n\n\t\t\t\t\tif(!className)\n\t\t\t\t\t\tel.style.visibility = \"hidden\";\n\n\t\t\t\t\treturn el;\n\t\t\t\t},\n\t\t\t\tupdate: function(container, p) {\n\n\t\t\t\t\t// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that\n\t\t\t\t\t// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified\n\t\t\t\t\tif(className && !o.forcePlaceholderSize) return;\n\n\t\t\t\t\t//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item\n\t\t\t\t\tif(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); };\n\t\t\t\t\tif(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); };\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthat.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));\n\n\t\t//Append it after the actual current item\n\t\tthat.currentItem.after(that.placeholder);\n\n\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n\t\to.placeholder.update(that, that.placeholder);\n\n\t},\n\n\t_contactContainers: function(event) {\n\n\t\t// get innermost container that intersects with item\n\t\tvar innermostContainer = null, innermostIndex = null;\n\n\n\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\n\t\t\t// never consider a container that's located within the item itself\n\t\t\tif($.contains(this.currentItem[0], this.containers[i].element[0]))\n\t\t\t\tcontinue;\n\n\t\t\tif(this._intersectsWith(this.containers[i].containerCache)) {\n\n\t\t\t\t// if we've already found a container and it's more \"inner\" than this, then continue\n\t\t\t\tif(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))\n\t\t\t\t\tcontinue;\n\n\t\t\t\tinnermostContainer = this.containers[i];\n\t\t\t\tinnermostIndex = i;\n\n\t\t\t} else {\n\t\t\t\t// container doesn't intersect. trigger \"out\" event if necessary\n\t\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\t\tthis.containers[i]._trigger(\"out\", event, this._uiHash(this));\n\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t// if no intersecting containers found, return\n\t\tif(!innermostContainer) return;\n\n\t\t// move the item into the container if it's not there already\n\t\tif(this.containers.length === 1) {\n\t\t\tthis.containers[innermostIndex]._trigger(\"over\", event, this._uiHash(this));\n\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n\t\t} else if(this.currentContainer != this.containers[innermostIndex]) {\n\n\t\t\t//When entering a new container, we will find the item with the least distance and append our item near it\n\t\t\tvar dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];\n\t\t\tfor (var j = this.items.length - 1; j >= 0; j--) {\n\t\t\t\tif(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;\n\t\t\t\tvar cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top;\n\t\t\t\tif(Math.abs(cur - base) < dist) {\n\t\t\t\t\tdist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];\n\t\t\t\t\tthis.direction = (cur - base > 0) ? 'down' : 'up';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled\n\t\t\t\treturn;\n\n\t\t\tthis.currentContainer = this.containers[innermostIndex];\n\t\t\titemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);\n\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\tthis.containers[innermostIndex]._trigger(\"change\", event, this._uiHash(this));\n\n\t\t\t//Update the placeholder\n\t\t\tthis.options.placeholder.update(this.currentContainer, this.placeholder);\n\n\t\t\tthis.containers[innermostIndex]._trigger(\"over\", event, this._uiHash(this));\n\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n\t\t}\n\n\n\t},\n\n\t_createHelper: function(event) {\n\n\t\tvar o = this.options;\n\t\tvar helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);\n\n\t\tif(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already\n\t\t\t$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);\n\n\t\tif(helper[0] == this.currentItem[0])\n\t\t\tthis._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css(\"position\"), top: this.currentItem.css(\"top\"), left: this.currentItem.css(\"left\") };\n\n\t\tif(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());\n\t\tif(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function(obj) {\n\t\tif (typeof obj == 'string') {\n\t\t\tobj = obj.split(' ');\n\t\t}\n\t\tif ($.isArray(obj)) {\n\t\t\tobj = {left: +obj[0], top: +obj[1] || 0};\n\t\t}\n\t\tif ('left' in obj) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ('right' in obj) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ('top' in obj) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ('bottom' in obj) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that\n\t\t//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\n\t\tif(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\tif((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information\n\t\t|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix\n\t\t\tpo = { top: 0, left: 0 };\n\n\t\treturn {\n\t\t\ttop: po.top + (parseInt(this.offsetParent.css(\"borderTopWidth\"),10) || 0),\n\t\t\tleft: po.left + (parseInt(this.offsetParent.css(\"borderLeftWidth\"),10) || 0)\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif(this.cssPosition == \"relative\") {\n\t\t\tvar p = this.currentItem.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - (parseInt(this.helper.css(\"top\"),10) || 0) + this.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - (parseInt(this.helper.css(\"left\"),10) || 0) + this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: (parseInt(this.currentItem.css(\"marginLeft\"),10) || 0),\n\t\t\ttop: (parseInt(this.currentItem.css(\"marginTop\"),10) || 0)\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar o = this.options;\n\t\tif(o.containment == 'parent') o.containment = this.helper[0].parentNode;\n\t\tif(o.containment == 'document' || o.containment == 'window') this.containment = [\n\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n\t\t\t$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,\n\t\t\t($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\n\t\t];\n\n\t\tif(!(/^(document|window|parent)$/).test(o.containment)) {\n\t\t\tvar ce = $(o.containment)[0];\n\t\t\tvar co = $(o.containment).offset();\n\t\t\tvar over = ($(ce).css(\"overflow\") != 'hidden');\n\n\t\t\tthis.containment = [\n\t\t\t\tco.left + (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingLeft\"),10) || 0) - this.margins.left,\n\t\t\t\tco.top + (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) + (parseInt($(ce).css(\"paddingTop\"),10) || 0) - this.margins.top,\n\t\t\t\tco.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css(\"borderLeftWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingRight\"),10) || 0) - this.helperProportions.width - this.margins.left,\n\t\t\t\tco.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css(\"borderTopWidth\"),10) || 0) - (parseInt($(ce).css(\"paddingBottom\"),10) || 0) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function(d, pos) {\n\n\t\tif(!pos) pos = this.position;\n\t\tvar mod = d == \"absolute\" ? 1 : -1;\n\t\tvar o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpos.top\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t+ this.offset.relative.top * mod\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t+ this.offset.parent.top * mod\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpos.left\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t+ this.offset.relative.left * mod\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t+ this.offset.parent.left * mod\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function(event) {\n\n\t\tvar o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n\n\t\t// This is another very weird special case that only happens for relative elements:\n\t\t// 1. If the css position is relative\n\t\t// 2. and the scroll parent is the document or similar to the offset parent\n\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n\t\tif(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {\n\t\t\tthis.offset.relative = this._getRelativeOffset();\n\t\t}\n\n\t\tvar pageX = event.pageX;\n\t\tvar pageY = event.pageY;\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif(this.originalPosition) { //If we are not dragging yet, we won't check for options\n\n\t\t\tif(this.containment) {\n\t\t\t\tif(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;\n\t\t\t\tif(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;\n\t\t\t\tif(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;\n\t\t\t\tif(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;\n\t\t\t}\n\n\t\t\tif(o.grid) {\n\t\t\t\tvar top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];\n\t\t\t\tpageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;\n\n\t\t\t\tvar left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];\n\t\t\t\tpageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\t\t\t\tpageY\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t- this.offset.click.top\t\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\t- this.offset.relative.top\t\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t- this.offset.parent.top\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\n\t\t\t),\n\t\t\tleft: (\n\t\t\t\tpageX\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n\t\t\t\t- this.offset.click.left\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n\t\t\t\t- this.offset.relative.left\t\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\t- this.offset.parent.left\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\t+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_rearrange: function(event, i, a, hardRefresh) {\n\n\t\ta ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));\n\n\t\t//Various things done here to improve the performance:\n\t\t// 1. we create a setTimeout, that calls refreshPositions\n\t\t// 2. on the instance, we have a counter variable, that get's higher after every append\n\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same\n\t\t// 4. this lets only the last addition to the timeout stack through\n\t\tthis.counter = this.counter ? ++this.counter : 1;\n\t\tvar counter = this.counter;\n\n\t\tthis._delay(function() {\n\t\t\tif(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove\n\t\t});\n\n\t},\n\n\t_clear: function(event, noPropagation) {\n\n\t\tthis.reverting = false;\n\t\t// We delay all events that have to be triggered to after the point where the placeholder has been removed and\n\t\t// everything else normalized again\n\t\tvar delayedTriggers = [];\n\n\t\t// We first have to update the dom position of the actual currentItem\n\t\t// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)\n\t\tif(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);\n\t\tthis._noFinalSort = null;\n\n\t\tif(this.helper[0] == this.currentItem[0]) {\n\t\t\tfor(var i in this._storedCSS) {\n\t\t\t\tif(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';\n\t\t\t}\n\t\t\tthis.currentItem.css(this._storedCSS).removeClass(\"ui-sortable-helper\");\n\t\t} else {\n\t\t\tthis.currentItem.show();\n\t\t}\n\n\t\tif(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger(\"receive\", event, this._uiHash(this.fromOutside)); });\n\t\tif((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(\".ui-sortable-helper\")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger(\"update\", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed\n\t\tif(!$.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element\n\t\t\tif(!noPropagation) delayedTriggers.push(function(event) { this._trigger(\"remove\", event, this._uiHash()); });\n\t\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\t\t\t\tif($.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {\n\t\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"receive\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"update\", event, this._uiHash(this));  }; }).call(this, this.containers[i]));\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\n\t\t//Post events to containers\n\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n\t\t\tif(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger(\"deactivate\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\tif(this.containers[i].containerCache.over) {\n\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger(\"out\", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\n\t\t\t\tthis.containers[i].containerCache.over = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Do what was originally in plugins\n\t\tif(this._storedCursor) $('body').css(\"cursor\", this._storedCursor); //Reset cursor\n\t\tif(this._storedOpacity) this.helper.css(\"opacity\", this._storedOpacity); //Reset opacity\n\t\tif(this._storedZIndex) this.helper.css(\"zIndex\", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index\n\n\t\tthis.dragging = false;\n\t\tif(this.cancelHelperRemoval) {\n\t\t\tif(!noPropagation) {\n\t\t\t\tthis._trigger(\"beforeStop\", event, this._uiHash());\n\t\t\t\tfor (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events\n\t\t\t\tthis._trigger(\"stop\", event, this._uiHash());\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tif(!noPropagation) this._trigger(\"beforeStop\", event, this._uiHash());\n\n\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n\n\t\tif(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;\n\n\t\tif(!noPropagation) {\n\t\t\tfor (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events\n\t\t\tthis._trigger(\"stop\", event, this._uiHash());\n\t\t}\n\n\t\tthis.fromOutside = false;\n\t\treturn true;\n\n\t},\n\n\t_trigger: function() {\n\t\tif ($.Widget.prototype._trigger.apply(this, arguments) === false) {\n\t\t\tthis.cancel();\n\t\t}\n\t},\n\n\t_uiHash: function(_inst) {\n\t\tvar inst = _inst || this;\n\t\treturn {\n\t\t\thelper: inst.helper,\n\t\t\tplaceholder: inst.placeholder || $([]),\n\t\t\tposition: inst.position,\n\t\t\toriginalPosition: inst.originalPosition,\n\t\t\toffset: inst.positionAbs,\n\t\t\titem: inst.currentItem,\n\t\t\tsender: _inst ? _inst.element : null\n\t\t};\n\t}\n\n});\n\n})(jQuery);\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.spinner.js",
    "content": "/*!\n * jQuery UI Spinner @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Spinner\n *\n * Depends:\n *  jquery.ui.core.js\n *  jquery.ui.widget.js\n *  jquery.ui.button.js\n */\n(function( $ ) {\n\nfunction modifier( fn ) {\n\treturn function() {\n\t\tvar previous = this.element.val();\n\t\tfn.apply( this, arguments );\n\t\tthis._refresh();\n\t\tif ( previous !== this.element.val() ) {\n\t\t\tthis._trigger( \"change\" );\n\t\t}\n\t};\n}\n\n$.widget( \"ui.spinner\", {\n\tversion: \"@VERSION\",\n\tdefaultElement: \"<input>\",\n\twidgetEventPrefix: \"spin\",\n\toptions: {\n\t\tculture: null,\n\t\tincremental: true,\n\t\tmax: null,\n\t\tmin: null,\n\t\tnumberFormat: null,\n\t\tpage: 10,\n\t\tstep: 1,\n\n\t\tchange: null,\n\t\tspin: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t_create: function() {\n\t\t// handle string values that need to be parsed\n\t\tthis._setOption( \"max\", this.options.max );\n\t\tthis._setOption( \"min\", this.options.min );\n\t\tthis._setOption( \"step\", this.options.step );\n\n\t\t// format the value, but don't constrain\n\t\tthis._value( this.element.val(), true );\n\n\t\tthis._draw();\n\t\tthis._bind( this._events );\n\t\tthis._refresh();\n\n\t\t// turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._bind( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar options = {},\n\t\t\telement = this.element;\n\n\t\t$.each( [ \"min\", \"max\", \"step\" ], function( i, option ) {\n\t\t\tvar value = element.attr( option );\n\t\t\tif ( value !== undefined && value.length ) {\n\t\t\t\toptions[ option ] = value;\n\t\t\t}\n\t\t});\n\n\t\treturn options;\n\t},\n\n\t_events: {\n\t\tkeydown: function( event ) {\n\t\t\tif ( this._start( event ) && this._keydown( event ) ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t},\n\t\tkeyup: \"_stop\",\n\t\tfocus: function() {\n\t\t\tthis.uiSpinner.addClass( \"ui-state-active\" );\n\t\t\tthis.previous = this.element.val();\n\t\t},\n\t\tblur: function( event ) {\n\t\t\tif ( this.cancelBlur ) {\n\t\t\t\tdelete this.cancelBlur;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._refresh();\n\t\t\tthis.uiSpinner.removeClass( \"ui-state-active\" );\n\t\t\tif ( this.previous !== this.element.val() ) {\n\t\t\t\tthis._trigger( \"change\", event );\n\t\t\t}\n\t\t},\n\t\tmousewheel: function( event, delta ) {\n\t\t\tif ( !delta ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( !this.spinning && !this._start( event ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis._spin( (delta > 0 ? 1 : -1) * this.options.step, event );\n\t\t\tclearTimeout( this.mousewheelTimer );\n\t\t\tthis.mousewheelTimer = this._delay(function() {\n\t\t\t\tif ( this.spinning ) {\n\t\t\t\t\tthis._stop( event );\n\t\t\t\t}\n\t\t\t}, 100 );\n\t\t\tevent.preventDefault();\n\t\t},\n\t\t\"mousedown .ui-spinner-button\": function( event ) {\n\t\t\tvar previous;\n\n\t\t\t// We never want the buttons to have focus; whenever the user is\n\t\t\t// interacting with the spinner, the focus should be on the input.\n\t\t\t// If the input is focused then this.previous is properly set from\n\t\t\t// when the input first received focus. If the input is not focused\n\t\t\t// then we need to set this.previous based on the value before spinning.\n\t\t\tprevious = this.element[0] === this.document[0].activeElement ?\n\t\t\t\tthis.previous : this.element.val();\n\t\t\tfunction checkFocus() {\n\t\t\t\tvar isActive = this.element[0] === this.document[0].activeElement;\n\t\t\t\tif ( !isActive ) {\n\t\t\t\t\tthis.element.focus();\n\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t// support: IE\n\t\t\t\t\t// IE sets focus asynchronously, so we need to check if focus\n\t\t\t\t\t// moved off of the input because the user clicked on the button.\n\t\t\t\t\tthis._delay(function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ensure focus is on (or stays on) the text field\n\t\t\tevent.preventDefault();\n\t\t\tcheckFocus.call( this );\n\n\t\t\t// support: IE\n\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t// and check (again) if focus moved off of the input.\n\t\t\tthis.cancelBlur = true;\n\t\t\tthis._delay(function() {\n\t\t\t\tdelete this.cancelBlur;\n\t\t\t\tcheckFocus.call( this );\n\t\t\t});\n\n\t\t\tif ( this._start( event ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._repeat( null, $( event.currentTarget ).hasClass( \"ui-spinner-up\" ) ? 1 : -1, event );\n\t\t},\n\t\t\"mouseup .ui-spinner-button\": \"_stop\",\n\t\t\"mouseenter .ui-spinner-button\": function( event ) {\n\t\t\t// button will add ui-state-active if mouse was down while mouseleave and kept down\n\t\t\tif ( !$( event.currentTarget ).hasClass( \"ui-state-active\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this._start( event ) === false ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis._repeat( null, $( event.currentTarget ).hasClass( \"ui-spinner-up\" ) ? 1 : -1, event );\n\t\t},\n\t\t// TODO: do we really want to consider this a stop?\n\t\t// shouldn't we just stop the repeater and wait until mouseup before\n\t\t// we trigger the stop event?\n\t\t\"mouseleave .ui-spinner-button\": \"_stop\"\n\t},\n\n\t_draw: function() {\n\t\tvar uiSpinner = this.uiSpinner = this.element\n\t\t\t.addClass( \"ui-spinner-input\" )\n\t\t\t.attr( \"autocomplete\", \"off\" )\n\t\t\t.wrap( this._uiSpinnerHtml() )\n\t\t\t.parent()\n\t\t\t\t// add buttons\n\t\t\t\t.append( this._buttonHtml() );\n\t\tthis._hoverable( uiSpinner );\n\n\t\tthis.element.attr( \"role\", \"spinbutton\" );\n\n\t\t// button bindings\n\t\tthis.buttons = uiSpinner.find( \".ui-spinner-button\" )\n\t\t\t.attr( \"tabIndex\", -1 )\n\t\t\t.button()\n\t\t\t.removeClass( \"ui-corner-all\" );\n\n\t\t// IE 6 doesn't understand height: 50% for the buttons\n\t\t// unless the wrapper has an explicit height\n\t\tif ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&\n\t\t\t\tuiSpinner.height() > 0 ) {\n\t\t\tuiSpinner.height( uiSpinner.height() );\n\t\t}\n\n\t\t// disable spinner if element was already disabled\n\t\tif ( this.options.disabled ) {\n\t\t\tthis.disable();\n\t\t}\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar options = this.options,\n\t\t\tkeyCode = $.ui.keyCode;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase keyCode.UP:\n\t\t\tthis._repeat( null, 1, event );\n\t\t\treturn true;\n\t\tcase keyCode.DOWN:\n\t\t\tthis._repeat( null, -1, event );\n\t\t\treturn true;\n\t\tcase keyCode.PAGE_UP:\n\t\t\tthis._repeat( null, options.page, event );\n\t\t\treturn true;\n\t\tcase keyCode.PAGE_DOWN:\n\t\t\tthis._repeat( null, -options.page, event );\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_uiSpinnerHtml: function() {\n\t\treturn \"<span class='ui-spinner ui-state-default ui-widget ui-widget-content ui-corner-all'></span>\";\n\t},\n\n\t_buttonHtml: function() {\n\t\treturn \"\" +\n\t\t\t\"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>\" +\n\t\t\t\t\"<span class='ui-icon ui-icon-triangle-1-n'>&#9650;</span>\" +\n\t\t\t\"</a>\" +\n\t\t\t\"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>\" +\n\t\t\t\t\"<span class='ui-icon ui-icon-triangle-1-s'>&#9660;</span>\" +\n\t\t\t\"</a>\";\n\t},\n\n\t_start: function( event ) {\n\t\tif ( !this.spinning && this._trigger( \"start\", event ) === false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !this.counter ) {\n\t\t\tthis.counter = 1;\n\t\t}\n\t\tthis.spinning = true;\n\t\treturn true;\n\t},\n\n\t_repeat: function( i, steps, event ) {\n\t\ti = i || 500;\n\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay(function() {\n\t\t\tthis._repeat( 40, steps, event );\n\t\t}, i );\n\n\t\tthis._spin( steps * this.options.step, event );\n\t},\n\n\t_spin: function( step, event ) {\n\t\tvar value = this.value() || 0;\n\n\t\tif ( !this.counter ) {\n\t\t\tthis.counter = 1;\n\t\t}\n\n\t\tvalue = this._adjustValue( value + step * this._increment( this.counter ) );\n\n\t\tif ( !this.spinning || this._trigger( \"spin\", event, { value: value } ) !== false) {\n\t\t\tthis._value( value );\n\t\t\tthis.counter++;\n\t\t}\n\t},\n\n\t_increment: function( i ) {\n\t\tvar incremental = this.options.incremental;\n\n\t\tif ( incremental ) {\n\t\t\treturn $.isFunction( incremental ) ?\n\t\t\t\tincremental( i ) :\n\t\t\t\tMath.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );\n\t\t}\n\n\t\treturn 1;\n\t},\n\n\t_precision: function() {\n\t\tvar precision = this._precisionOf( this.options.step );\n\t\tif ( this.options.min !== null ) {\n\t\t\tprecision = Math.max( precision, this._precisionOf( this.options.min ) );\n\t\t}\n\t\treturn precision;\n\t},\n\n\t_precisionOf: function( num ) {\n\t\tvar str = num.toString(),\n\t\t\tdecimal = str.indexOf( \".\" );\n\t\treturn decimal === -1 ? 0 : str.length - decimal - 1;\n\t},\n\n\t_adjustValue: function( value ) {\n\t\tvar base, aboveMin,\n\t\t\toptions = this.options;\n\n\t\t// make sure we're at a valid step\n\t\t// - find out where we are relative to the base (min or 0)\n\t\tbase = options.min !== null ? options.min : 0;\n\t\taboveMin = value - base;\n\t\t// - round to the nearest step\n\t\taboveMin = Math.round(aboveMin / options.step) * options.step;\n\t\t// - rounding is based on 0, so adjust back to our base\n\t\tvalue = base + aboveMin;\n\n\t\t// fix precision from bad JS floating point math\n\t\tvalue = parseFloat( value.toFixed( this._precision() ) );\n\n\t\t// clamp the value\n\t\tif ( options.max !== null && value > options.max) {\n\t\t\treturn options.max;\n\t\t}\n\t\tif ( options.min !== null && value < options.min ) {\n\t\t\treturn options.min;\n\t\t}\n\n\t\treturn value;\n\t},\n\n\t_stop: function( event ) {\n\t\tif ( !this.spinning ) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout( this.timer );\n\t\tclearTimeout( this.mousewheelTimer );\n\t\tthis.counter = 0;\n\t\tthis.spinning = false;\n\t\tthis._trigger( \"stop\", event );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"culture\" || key === \"numberFormat\" ) {\n\t\t\tvar prevValue = this._parse( this.element.val() );\n\t\t\tthis.options[ key ] = value;\n\t\t\tthis.element.val( this._format( prevValue ) );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"max\" || key === \"min\" || key === \"step\" ) {\n\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\tvalue = this._parse( value );\n\t\t\t}\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tif ( value ) {\n\t\t\t\tthis.element.prop( \"disabled\", true );\n\t\t\t\tthis.buttons.button( \"disable\" );\n\t\t\t} else {\n\t\t\t\tthis.element.prop( \"disabled\", false );\n\t\t\t\tthis.buttons.button( \"enable\" );\n\t\t\t}\n\t\t}\n\t},\n\n\t_setOptions: modifier(function( options ) {\n\t\tthis._super( options );\n\t\tthis._value( this.element.val() );\n\t}),\n\n\t_parse: function( val ) {\n\t\tif ( typeof val === \"string\" && val !== \"\" ) {\n\t\t\tval = window.Globalize && this.options.numberFormat ?\n\t\t\t\tGlobalize.parseFloat( val, 10, this.options.culture ) : +val;\n\t\t}\n\t\treturn val === \"\" || isNaN( val ) ? null : val;\n\t},\n\n\t_format: function( value ) {\n\t\tif ( value === \"\" ) {\n\t\t\treturn \"\";\n\t\t}\n\t\treturn window.Globalize && this.options.numberFormat ?\n\t\t\tGlobalize.format( value, this.options.numberFormat, this.options.culture ) :\n\t\t\tvalue;\n\t},\n\n\t_refresh: function() {\n\t\tthis.element.attr({\n\t\t\t\"aria-valuemin\": this.options.min,\n\t\t\t\"aria-valuemax\": this.options.max,\n\t\t\t// TODO: what should we do with values that can't be parsed?\n\t\t\t\"aria-valuenow\": this._parse( this.element.val() )\n\t\t});\n\t},\n\n\t// update the value without triggering change\n\t_value: function( value, allowAny ) {\n\t\tvar parsed;\n\t\tif ( value !== \"\" ) {\n\t\t\tparsed = this._parse( value );\n\t\t\tif ( parsed !== null ) {\n\t\t\t\tif ( !allowAny ) {\n\t\t\t\t\tparsed = this._adjustValue( parsed );\n\t\t\t\t}\n\t\t\t\tvalue = this._format( parsed );\n\t\t\t}\n\t\t}\n\t\tthis.element.val( value );\n\t\tthis._refresh();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass( \"ui-spinner-input\" )\n\t\t\t.prop( \"disabled\", false )\n\t\t\t.removeAttr( \"autocomplete\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-valuemin\" )\n\t\t\t.removeAttr( \"aria-valuemax\" )\n\t\t\t.removeAttr( \"aria-valuenow\" );\n\t\tthis.uiSpinner.replaceWith( this.element );\n\t},\n\n\tstepUp: modifier(function( steps ) {\n\t\tthis._stepUp( steps );\n\t}),\n\t_stepUp: function( steps ) {\n\t\tthis._spin( (steps || 1) * this.options.step );\n\t},\n\n\tstepDown: modifier(function( steps ) {\n\t\tthis._stepDown( steps );\n\t}),\n\t_stepDown: function( steps ) {\n\t\tthis._spin( (steps || 1) * -this.options.step );\n\t},\n\n\tpageUp: modifier(function( pages ) {\n\t\tthis._stepUp( (pages || 1) * this.options.page );\n\t}),\n\n\tpageDown: modifier(function( pages ) {\n\t\tthis._stepDown( (pages || 1) * this.options.page );\n\t}),\n\n\tvalue: function( newVal ) {\n\t\tif ( !arguments.length ) {\n\t\t\treturn this._parse( this.element.val() );\n\t\t}\n\t\tmodifier( this._value ).call( this, newVal );\n\t},\n\n\twidget: function() {\n\t\treturn this.uiSpinner;\n\t}\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.tabs.js",
    "content": "/*!\n * jQuery UI Tabs @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Tabs\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\nvar tabId = 0,\n\trhash = /#.*$/;\n\nfunction getNextTabId() {\n\treturn ++tabId;\n}\n\nfunction isLocal( anchor ) {\n\t// clone the node to work around IE 6 not normalizing the href property\n\t// if it's manually set, i.e., a.href = \"#foo\" kills the normalization\n\tanchor = anchor.cloneNode( false );\n\treturn anchor.hash.length > 1 &&\n\t\tanchor.href.replace( rhash, \"\" ) === location.href.replace( rhash, \"\" );\n}\n\n$.widget( \"ui.tabs\", {\n\tversion: \"@VERSION\",\n\tdelay: 300,\n\toptions: {\n\t\tactive: null,\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theightStyle: \"content\",\n\t\thide: null,\n\t\tshow: null,\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tbeforeLoad: null,\n\t\tload: null\n\t},\n\n\t_create: function() {\n\t\tvar panel,\n\t\t\tthat = this,\n\t\t\toptions = this.options,\n\t\t\tactive = options.active;\n\n\t\tthis.running = false;\n\n\t\tthis.element\n\t\t\t.addClass( \"ui-tabs ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.toggleClass( \"ui-tabs-collapsible\", options.collapsible )\n\t\t\t// Prevent users from focusing disabled tabs via click\n\t\t\t.delegate( \".ui-tabs-nav > li\", \"mousedown.tabs\", function( event ) {\n\t\t\t\tif ( $( this ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t\t// support: IE <9\n\t\t\t// Preventing the default action in mousedown doesn't prevent IE\n\t\t\t// from focusing the element, so if the anchor gets focused, blur.\n\t\t\t// We don't have to worry about focusing the previously focused\n\t\t\t// element since clicking on a non-focusable element should focus\n\t\t\t// the body anyway.\n\t\t\t.delegate( \".ui-tabs-anchor\", \"focus.tabs\", function() {\n\t\t\t\tif ( $( this ).closest( \"li\" ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis._processTabs();\n\n\t\tif ( active === null ) {\n\t\t\t// check the fragment identifier in the URL\n\t\t\tif ( location.hash ) {\n\t\t\t\tthis.anchors.each(function( i, anchor ) {\n\t\t\t\t\tif ( anchor.hash === location.hash ) {\n\t\t\t\t\t\tactive = i;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// check for a tab marked active via a class\n\t\t\tif ( active === null ) {\n\t\t\t\tactive = this.tabs.filter( \".ui-tabs-active\" ).index();\n\t\t\t}\n\n\t\t\t// no active tab, set to false\n\t\t\tif ( active === null || active === -1 ) {\n\t\t\t\tactive = this.tabs.length ? 0 : false;\n\t\t\t}\n\t\t}\n\n\t\t// handle numbers: negative, out of range\n\t\tif ( active !== false ) {\n\t\t\tactive = this.tabs.eq( active ).index();\n\t\t\tif ( active === -1 ) {\n\t\t\t\tactive = options.collapsible ? false : 0;\n\t\t\t}\n\t\t}\n\t\toptions.active = active;\n\n\t\t// don't allow collapsible: false and active: false\n\t\tif ( !options.collapsible && options.active === false && this.anchors.length ) {\n\t\t\toptions.active = 0;\n\t\t}\n\n\t\t// Take disabling tabs via class attribute from HTML\n\t\t// into account and update option properly.\n\t\tif ( $.isArray( options.disabled ) ) {\n\t\t\toptions.disabled = $.unique( options.disabled.concat(\n\t\t\t\t$.map( this.tabs.filter( \".ui-state-disabled\" ), function( li ) {\n\t\t\t\t\treturn that.tabs.index( li );\n\t\t\t\t})\n\t\t\t) ).sort();\n\t\t}\n\n\t\t// check for length avoids error when initializing empty list\n\t\tif ( this.options.active !== false && this.anchors.length ) {\n\t\t\tthis.active = this._findActive( this.options.active );\n\t\t} else {\n\t\t\tthis.active = $();\n\t\t}\n\n\t\tthis._refresh();\n\n\t\tif ( this.active.length ) {\n\t\t\tthis.load( options.active );\n\t\t}\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\ttab: this.active,\n\t\t\tpanel: !this.active.length ? $() : this._getPanelForTab( this.active )\n\t\t};\n\t},\n\n\t_tabKeydown: function( event ) {\n\t\tvar focusedTab = $( this.document[0].activeElement ).closest( \"li\" ),\n\t\t\tselectedIndex = this.tabs.index( focusedTab ),\n\t\t\tgoingForward = true;\n\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( event.keyCode ) {\n\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tselectedIndex++;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.UP:\n\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\tgoingForward = false;\n\t\t\t\tselectedIndex--;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.END:\n\t\t\t\tselectedIndex = this.anchors.length - 1;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\tselectedIndex = 0;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.SPACE:\n\t\t\t\t// Activate only, no collapsing\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearTimeout( this.activating );\n\t\t\t\tthis._activate( selectedIndex );\n\t\t\t\treturn;\n\t\t\tcase $.ui.keyCode.ENTER:\n\t\t\t\t// Toggle (cancel delayed activation, allow collapsing)\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearTimeout( this.activating );\n\t\t\t\t// Determine if we should collapse or activate\n\t\t\t\tthis._activate( selectedIndex === this.options.active ? false : selectedIndex );\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Focus the appropriate tab, based on which key was pressed\n\t\tevent.preventDefault();\n\t\tclearTimeout( this.activating );\n\t\tselectedIndex = this._focusNextTab( selectedIndex, goingForward );\n\n\t\t// Navigating with control key will prevent automatic activation\n\t\tif ( !event.ctrlKey ) {\n\t\t\t// Update aria-selected immediately so that AT think the tab is already selected.\n\t\t\t// Otherwise AT may confuse the user by stating that they need to activate the tab,\n\t\t\t// but the tab will already be activated by the time the announcement finishes.\n\t\t\tfocusedTab.attr( \"aria-selected\", \"false\" );\n\t\t\tthis.tabs.eq( selectedIndex ).attr( \"aria-selected\", \"true\" );\n\n\t\t\tthis.activating = this._delay(function() {\n\t\t\t\tthis.option( \"active\", selectedIndex );\n\t\t\t}, this.delay );\n\t\t}\n\t},\n\n\t_panelKeydown: function( event ) {\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+up moves focus to the current tab\n\t\tif ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.active.focus();\n\t\t}\n\t},\n\n\t// Alt+page up/down moves focus to the previous/next tab (and activates)\n\t_handlePageNav: function( event ) {\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active - 1, false ) );\n\t\t\treturn true;\n\t\t}\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active + 1, true ) );\n\t\t\treturn true;\n\t\t}\n\t},\n\n\t_findNextTab: function( index, goingForward ) {\n\t\tvar lastTabIndex = this.tabs.length - 1;\n\n\t\tfunction constrain() {\n\t\t\tif ( index > lastTabIndex ) {\n\t\t\t\tindex = 0;\n\t\t\t}\n\t\t\tif ( index < 0 ) {\n\t\t\t\tindex = lastTabIndex;\n\t\t\t}\n\t\t\treturn index;\n\t\t}\n\n\t\twhile ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {\n\t\t\tindex = goingForward ? index + 1 : index - 1;\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_focusNextTab: function( index, goingForward ) {\n\t\tindex = this._findNextTab( index, goingForward );\n\t\tthis.tabs.eq( index ).focus();\n\t\treturn index;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\t// don't use the widget factory's disabled handling\n\t\t\tthis._setupDisabled( value );\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value);\n\n\t\tif ( key === \"collapsible\" ) {\n\t\t\tthis.element.toggleClass( \"ui-tabs-collapsible\", value );\n\t\t\t// Setting collapsible: false while collapsed; open first panel\n\t\t\tif ( !value && this.options.active === false ) {\n\t\t\t\tthis._activate( 0 );\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tif ( key === \"heightStyle\" ) {\n\t\t\tthis._setupHeightStyle( value );\n\t\t}\n\t},\n\n\t_tabId: function( tab ) {\n\t\treturn tab.attr( \"aria-controls\" ) || \"ui-tabs-\" + getNextTabId();\n\t},\n\n\t_sanitizeSelector: function( hash ) {\n\t\treturn hash ? hash.replace( /[!\"$%&'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g, \"\\\\$&\" ) : \"\";\n\t},\n\n\trefresh: function() {\n\t\tvar next,\n\t\t\toptions = this.options,\n\t\t\tlis = this.tablist.children( \":has(a[href])\" );\n\n\t\t// get disabled tabs from class attribute from HTML\n\t\t// this will get converted to a boolean if needed in _refresh()\n\t\toptions.disabled = $.map( lis.filter( \".ui-state-disabled\" ), function( tab ) {\n\t\t\treturn lis.index( tab );\n\t\t});\n\n\t\tthis._processTabs();\n\n\t\t// was collapsed or no tabs\n\t\tif ( options.active === false || !this.anchors.length ) {\n\t\t\toptions.active = false;\n\t\t\tthis.active = $();\n\t\t// was active, but active tab is gone\n\t\t} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {\n\t\t\t// all remaining tabs are disabled\n\t\t\tif ( this.tabs.length === options.disabled.length ) {\n\t\t\t\toptions.active = false;\n\t\t\t\tthis.active = $();\n\t\t\t// activate previous tab\n\t\t\t} else {\n\t\t\t\tthis._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );\n\t\t\t}\n\t\t// was active, active tab still exists\n\t\t} else {\n\t\t\t// make sure active index is correct\n\t\t\toptions.active = this.tabs.index( this.active );\n\t\t}\n\n\t\tthis._refresh();\n\t},\n\n\t_refresh: function() {\n\t\tthis._setupDisabled( this.options.disabled );\n\t\tthis._setupEvents( this.options.event );\n\t\tthis._setupHeightStyle( this.options.heightStyle );\n\n\t\tthis.tabs.not( this.active ).attr({\n\t\t\t\"aria-selected\": \"false\",\n\t\t\ttabIndex: -1\n\t\t});\n\t\tthis.panels.not( this._getPanelForTab( this.active ) )\n\t\t\t.hide()\n\t\t\t.attr({\n\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t});\n\n\t\t// Make sure one tab is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.tabs.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active\n\t\t\t\t.addClass( \"ui-tabs-active ui-state-active\" )\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t});\n\t\t\tthis._getPanelForTab( this.active )\n\t\t\t\t.show()\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t});\n\t\t}\n\t},\n\n\t_processTabs: function() {\n\t\tvar that = this;\n\n\t\tthis.tablist = this._getList()\n\t\t\t.addClass( \"ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all\" )\n\t\t\t.attr( \"role\", \"tablist\" );\n\n\t\tthis.tabs = this.tablist.find( \"> li:has(a[href])\" )\n\t\t\t.addClass( \"ui-state-default ui-corner-top\" )\n\t\t\t.attr({\n\t\t\t\trole: \"tab\",\n\t\t\t\ttabIndex: -1\n\t\t\t});\n\n\t\tthis.anchors = this.tabs.map(function() {\n\t\t\t\treturn $( \"a\", this )[ 0 ];\n\t\t\t})\n\t\t\t.addClass( \"ui-tabs-anchor\" )\n\t\t\t.attr({\n\t\t\t\trole: \"presentation\",\n\t\t\t\ttabIndex: -1\n\t\t\t});\n\n\t\tthis.panels = $();\n\n\t\tthis.anchors.each(function( i, anchor ) {\n\t\t\tvar selector, panel, panelId,\n\t\t\t\tanchorId = $( anchor ).uniqueId().attr( \"id\" ),\n\t\t\t\ttab = $( anchor ).closest( \"li\" ),\n\t\t\t\toriginalAriaControls = tab.attr( \"aria-controls\" );\n\n\t\t\t// inline tab\n\t\t\tif ( isLocal( anchor ) ) {\n\t\t\t\tselector = anchor.hash;\n\t\t\t\tpanel = that.element.find( that._sanitizeSelector( selector ) );\n\t\t\t// remote tab\n\t\t\t} else {\n\t\t\t\tpanelId = that._tabId( tab );\n\t\t\t\tselector = \"#\" + panelId;\n\t\t\t\tpanel = that.element.find( selector );\n\t\t\t\tif ( !panel.length ) {\n\t\t\t\t\tpanel = that._createPanel( panelId );\n\t\t\t\t\tpanel.insertAfter( that.panels[ i - 1 ] || that.tablist );\n\t\t\t\t}\n\t\t\t\tpanel.attr( \"aria-live\", \"polite\" );\n\t\t\t}\n\n\t\t\tif ( panel.length) {\n\t\t\t\tthat.panels = that.panels.add( panel );\n\t\t\t}\n\t\t\tif ( originalAriaControls ) {\n\t\t\t\ttab.data( \"ui-tabs-aria-controls\", originalAriaControls );\n\t\t\t}\n\t\t\ttab.attr({\n\t\t\t\t\"aria-controls\": selector.substring( 1 ),\n\t\t\t\t\"aria-labelledby\": anchorId\n\t\t\t});\n\t\t\tpanel.attr( \"aria-labelledby\", anchorId );\n\t\t});\n\n\t\tthis.panels\n\t\t\t.addClass( \"ui-tabs-panel ui-widget-content ui-corner-bottom\" )\n\t\t\t.attr( \"role\", \"tabpanel\" );\n\t},\n\n\t// allow overriding how to find the list for rare usage scenarios (#7715)\n\t_getList: function() {\n\t\treturn this.element.find( \"ol,ul\" ).eq( 0 );\n\t},\n\n\t_createPanel: function( id ) {\n\t\treturn $( \"<div>\" )\n\t\t\t.attr( \"id\", id )\n\t\t\t.addClass( \"ui-tabs-panel ui-widget-content ui-corner-bottom\" )\n\t\t\t.data( \"ui-tabs-destroy\", true );\n\t},\n\n\t_setupDisabled: function( disabled ) {\n\t\tif ( $.isArray( disabled ) ) {\n\t\t\tif ( !disabled.length ) {\n\t\t\t\tdisabled = false;\n\t\t\t} else if ( disabled.length === this.anchors.length ) {\n\t\t\t\tdisabled = true;\n\t\t\t}\n\t\t}\n\n\t\t// disable tabs\n\t\tfor ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {\n\t\t\tif ( disabled === true || $.inArray( i, disabled ) !== -1 ) {\n\t\t\t\t$( li )\n\t\t\t\t\t.addClass( \"ui-state-disabled\" )\n\t\t\t\t\t.attr( \"aria-disabled\", \"true\" );\n\t\t\t} else {\n\t\t\t\t$( li )\n\t\t\t\t\t.removeClass( \"ui-state-disabled\" )\n\t\t\t\t\t.removeAttr( \"aria-disabled\" );\n\t\t\t}\n\t\t}\n\n\t\tthis.options.disabled = disabled;\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {\n\t\t\tclick: function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t};\n\t\tif ( event ) {\n\t\t\t$.each( event.split(\" \"), function( index, eventName ) {\n\t\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t\t});\n\t\t}\n\n\t\tthis.anchors.add( this.tabs ).add( this.panels ).unbind( \".tabs\" );\n\t\tthis._bind( this.anchors, events );\n\t\tthis._bind( this.tabs, { keydown: \"_tabKeydown\" } );\n\t\tthis._bind( this.panels, { keydown: \"_panelKeydown\" } );\n\n\t\tthis._focusable( this.tabs );\n\t\tthis._hoverable( this.tabs );\n\t},\n\n\t_setupHeightStyle: function( heightStyle ) {\n\t\tvar maxHeight, overflow,\n\t\t\tparent = this.element.parent();\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\t// IE 6 treats height like minHeight, so we need to turn off overflow\n\t\t\t// in order to get a reliable height\n\t\t\t// we use the minHeight support test because we assume that only\n\t\t\t// browsers that don't support minHeight will treat height as minHeight\n\t\t\tif ( !$.support.minHeight ) {\n\t\t\t\toverflow = parent.css( \"overflow\" );\n\t\t\t\tparent.css( \"overflow\", \"hidden\");\n\t\t\t}\n\t\t\tmaxHeight = parent.height();\n\t\t\tthis.element.siblings( \":visible\" ).each(function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t});\n\t\t\tif ( overflow ) {\n\t\t\t\tparent.css( \"overflow\", overflow );\n\t\t\t}\n\n\t\t\tthis.element.children().not( this.panels ).each(function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t});\n\n\t\t\tthis.panels.each(function() {\n\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t})\n\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.panels.each(function() {\n\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( \"\" ).height() );\n\t\t\t}).height( maxHeight );\n\t\t}\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar options = this.options,\n\t\t\tactive = this.active,\n\t\t\tanchor = $( event.currentTarget ),\n\t\t\ttab = anchor.closest( \"li\" ),\n\t\t\tclickedIsActive = tab[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : this._getPanelForTab( tab ),\n\t\t\ttoHide = !active.length ? $() : this._getPanelForTab( active ),\n\t\t\teventData = {\n\t\t\t\toldTab: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewTab: collapsing ? $() : tab,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif ( tab.hasClass( \"ui-state-disabled\" ) ||\n\t\t\t\t// tab is already loading\n\t\t\t\ttab.hasClass( \"ui-tabs-loading\" ) ||\n\t\t\t\t// can't switch durning an animation\n\t\t\t\tthis.running ||\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.tabs.index( tab );\n\n\t\tthis.active = clickedIsActive ? $() : tab;\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tif ( !toHide.length && !toShow.length ) {\n\t\t\t$.error( \"jQuery UI Tabs: Mismatching fragment identifier.\" );\n\t\t}\n\n\t\tif ( toShow.length ) {\n\t\t\tthis.load( this.tabs.index( tab ), event );\n\t\t}\n\t\tthis._toggle( event, eventData );\n\t},\n\n\t// handles show/hide for selecting tabs\n\t_toggle: function( event, eventData ) {\n\t\tvar that = this,\n\t\t\ttoShow = eventData.newPanel,\n\t\t\ttoHide = eventData.oldPanel;\n\n\t\tthis.running = true;\n\n\t\tfunction complete() {\n\t\t\tthat.running = false;\n\t\t\tthat._trigger( \"activate\", event, eventData );\n\t\t}\n\n\t\tfunction show() {\n\t\t\teventData.newTab.closest( \"li\" ).addClass( \"ui-tabs-active ui-state-active\" );\n\n\t\t\tif ( toShow.length && that.options.show ) {\n\t\t\t\tthat._show( toShow, that.options.show, complete );\n\t\t\t} else {\n\t\t\t\ttoShow.show();\n\t\t\t\tcomplete();\n\t\t\t}\n\t\t}\n\n\t\t// start out by hiding, then showing, then completing\n\t\tif ( toHide.length && this.options.hide ) {\n\t\t\tthis._hide( toHide, this.options.hide, function() {\n\t\t\t\teventData.oldTab.closest( \"li\" ).removeClass( \"ui-tabs-active ui-state-active\" );\n\t\t\t\tshow();\n\t\t\t});\n\t\t} else {\n\t\t\teventData.oldTab.closest( \"li\" ).removeClass( \"ui-tabs-active ui-state-active\" );\n\t\t\ttoHide.hide();\n\t\t\tshow();\n\t\t}\n\n\t\ttoHide.attr({\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\"aria-hidden\": \"true\"\n\t\t});\n\t\teventData.oldTab.attr( \"aria-selected\", \"false\" );\n\t\t// If we're switching tabs, remove the old tab from the tab order.\n\t\t// If we're opening from collapsed state, remove the previous tab from the tab order.\n\t\t// If we're collapsing, then keep the collapsing tab in the tab order.\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\teventData.oldTab.attr( \"tabIndex\", -1 );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.tabs.filter(function() {\n\t\t\t\treturn $( this ).attr( \"tabIndex\" ) === 0;\n\t\t\t})\n\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow.attr({\n\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\"aria-hidden\": \"false\"\n\t\t});\n\t\teventData.newTab.attr({\n\t\t\t\"aria-selected\": \"true\",\n\t\t\ttabIndex: 0\n\t\t});\n\t},\n\n\t_activate: function( index ) {\n\t\tvar anchor,\n\t\t\tactive = this._findActive( index );\n\n\t\t// trying to activate the already active panel\n\t\tif ( active[ 0 ] === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// trying to collapse, simulate a click on the current active header\n\t\tif ( !active.length ) {\n\t\t\tactive = this.active;\n\t\t}\n\n\t\tanchor = active.find( \".ui-tabs-anchor\" )[ 0 ];\n\t\tthis._eventHandler({\n\t\t\ttarget: anchor,\n\t\t\tcurrentTarget: anchor,\n\t\t\tpreventDefault: $.noop\n\t\t});\n\t},\n\n\t_findActive: function( index ) {\n\t\treturn index === false ? $() : this.tabs.eq( index );\n\t},\n\n\t_getIndex: function( index ) {\n\t\t// meta-function to give users option to provide a href string instead of a numerical index.\n\t\tif ( typeof index === \"string\" ) {\n\t\t\tindex = this.anchors.index( this.anchors.filter( \"[href$='\" + index + \"']\" ) );\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_destroy: function() {\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tthis.element.removeClass( \"ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible\" );\n\n\t\tthis.tablist\n\t\t\t.removeClass( \"ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all\" )\n\t\t\t.removeAttr( \"role\" );\n\n\t\tthis.anchors\n\t\t\t.removeClass( \"ui-tabs-anchor\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t.unbind( \".tabs\" )\n\t\t\t.removeData( \"href.tabs\" )\n\t\t\t.removeData( \"load.tabs\" )\n\t\t\t.removeUniqueId();\n\n\t\tthis.tabs.unbind( \".tabs\" ).add( this.panels ).each(function() {\n\t\t\tif ( $.data( this, \"ui-tabs-destroy\" ) ) {\n\t\t\t\t$( this ).remove();\n\t\t\t} else {\n\t\t\t\t$( this )\n\t\t\t\t\t.removeClass([\n\t\t\t\t\t\t\"ui-state-default\",\n\t\t\t\t\t\t\"ui-corner-top\",\n\t\t\t\t\t\t\"ui-tabs-active\",\n\t\t\t\t\t\t\"ui-state-active\",\n\t\t\t\t\t\t\"ui-state-disabled\",\n\t\t\t\t\t\t\"ui-tabs-panel\",\n\t\t\t\t\t\t\"ui-widget-content\",\n\t\t\t\t\t\t\"ui-corner-bottom\"\n\t\t\t\t\t].join( \" \" ) )\n\t\t\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t\t\t.removeAttr( \"aria-live\" )\n\t\t\t\t\t.removeAttr( \"aria-busy\" )\n\t\t\t\t\t.removeAttr( \"aria-selected\" )\n\t\t\t\t\t.removeAttr( \"aria-labelledby\" )\n\t\t\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t\t\t.removeAttr( \"aria-expanded\" )\n\t\t\t\t\t.removeAttr( \"role\" );\n\t\t\t}\n\t\t});\n\n\t\tthis.tabs.each(function() {\n\t\t\tvar li = $( this ),\n\t\t\t\tprev = li.data( \"ui-tabs-aria-controls\" );\n\t\t\tif ( prev ) {\n\t\t\t\tli.attr( \"aria-controls\", prev );\n\t\t\t} else {\n\t\t\t\tli.removeAttr( \"aria-controls\" );\n\t\t\t}\n\t\t});\n\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tthis.panels.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\tenable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = false;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.map( disabled, function( num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tdisabled = $.map( this.tabs, function( li, num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis._setupDisabled( disabled );\n\t},\n\n\tdisable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === true ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = true;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.inArray( index, disabled ) !== -1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.merge( [ index ], disabled ).sort();\n\t\t\t} else {\n\t\t\t\tdisabled = [ index ];\n\t\t\t}\n\t\t}\n\t\tthis._setupDisabled( disabled );\n\t},\n\n\tload: function( index, event ) {\n\t\tindex = this._getIndex( index );\n\t\tvar that = this,\n\t\t\ttab = this.tabs.eq( index ),\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" ),\n\t\t\tpanel = this._getPanelForTab( tab ),\n\t\t\teventData = {\n\t\t\t\ttab: tab,\n\t\t\t\tpanel: panel\n\t\t\t};\n\n\t\t// not remote\n\t\tif ( isLocal( anchor[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.xhr = $.ajax({\n\t\t\turl: anchor.attr( \"href\" ),\n\t\t\tbeforeSend: function( jqXHR, settings ) {\n\t\t\t\treturn that._trigger( \"beforeLoad\", event,\n\t\t\t\t\t$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );\n\t\t\t}\n\t\t});\n\n\t\t// support: jQuery <1.8\n\t\t// jQuery <1.8 returns false if the request is canceled in beforeSend,\n\t\t// but as of 1.8, $.ajax() always returns a jqXHR object.\n\t\tif ( this.xhr && this.xhr.statusText !== \"canceled\" ) {\n\t\t\ttab.addClass( \"ui-tabs-loading\" );\n\t\t\tpanel.attr( \"aria-busy\", \"true\" );\n\n\t\t\tthis.xhr\n\t\t\t\t.success(function( response ) {\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tpanel.html( response );\n\t\t\t\t\t\tthat._trigger( \"load\", event, eventData );\n\t\t\t\t\t}, 1 );\n\t\t\t\t})\n\t\t\t\t.complete(function( jqXHR, status ) {\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tif ( status === \"abort\" ) {\n\t\t\t\t\t\t\tthat.panels.stop( false, true );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttab.removeClass( \"ui-tabs-loading\" );\n\t\t\t\t\t\tpanel.removeAttr( \"aria-busy\" );\n\n\t\t\t\t\t\tif ( jqXHR === that.xhr ) {\n\t\t\t\t\t\t\tdelete that.xhr;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 1 );\n\t\t\t\t});\n\t\t}\n\t},\n\n\t_getPanelForTab: function( tab ) {\n\t\tvar id = $( tab ).attr( \"aria-controls\" );\n\t\treturn this.element.find( this._sanitizeSelector( \"#\" + id ) );\n\t}\n});\n\n// DEPRECATED\nif ( $.uiBackCompat !== false ) {\n\n\t// helper method for a lot of the back compat extensions\n\t$.ui.tabs.prototype._ui = function( tab, panel ) {\n\t\treturn {\n\t\t\ttab: tab,\n\t\t\tpanel: panel,\n\t\t\tindex: this.anchors.index( tab )\n\t\t};\n\t};\n\n\t// url method\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\turl: function( index, url ) {\n\t\t\tthis.anchors.eq( index ).attr( \"href\", url );\n\t\t}\n\t});\n\n\t// ajaxOptions and cache options\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tajaxOptions: null,\n\t\t\tcache: false\n\t\t},\n\n\t\t_create: function() {\n\t\t\tthis._super();\n\n\t\t\tvar that = this;\n\n\t\t\tthis.element.bind( \"tabsbeforeload.tabs\", function( event, ui ) {\n\t\t\t\t// tab is already cached\n\t\t\t\tif ( $.data( ui.tab[ 0 ], \"cache.tabs\" ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$.extend( ui.ajaxSettings, that.options.ajaxOptions, {\n\t\t\t\t\terror: function( xhr, s, e ) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Passing index avoid a race condition when this method is\n\t\t\t\t\t\t\t// called after the user has selected another tab.\n\t\t\t\t\t\t\t// Pass the anchor that initiated this request allows\n\t\t\t\t\t\t\t// loadError to manipulate the tab content panel via $(a.hash)\n\t\t\t\t\t\t\tthat.options.ajaxOptions.error( xhr, s, ui.tab.closest( \"li\" ).index(), ui.tab[ 0 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch ( e ) {}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tui.jqXHR.success(function() {\n\t\t\t\t\tif ( that.options.cache ) {\n\t\t\t\t\t\t$.data( ui.tab[ 0 ], \"cache.tabs\", true );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t},\n\n\t\t_setOption: function( key, value ) {\n\t\t\t// reset cache if switching from cached to not cached\n\t\t\tif ( key === \"cache\" && value === false ) {\n\t\t\t\tthis.anchors.removeData( \"cache.tabs\" );\n\t\t\t}\n\t\t\tthis._super( key, value );\n\t\t},\n\n\t\t_destroy: function() {\n\t\t\tthis.anchors.removeData( \"cache.tabs\" );\n\t\t\tthis._super();\n\t\t},\n\n\t\turl: function( index, url ){\n\t\t\tthis.anchors.eq( index ).removeData( \"cache.tabs\" );\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t});\n\n\t// abort method\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\tabort: function() {\n\t\t\tif ( this.xhr ) {\n\t\t\t\tthis.xhr.abort();\n\t\t\t}\n\t\t}\n\t});\n\n\t// spinner\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tspinner: \"<em>Loading&#8230;</em>\"\n\t\t},\n\t\t_create: function() {\n\t\t\tthis._super();\n\t\t\tthis._bind({\n\t\t\t\ttabsbeforeload: function( event, ui ) {\n\t\t\t\t\tif ( !this.options.spinner ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar span = ui.tab.find( \"span\" ),\n\t\t\t\t\t\thtml = span.html();\n\t\t\t\t\tspan.html( this.options.spinner );\n\t\t\t\t\tui.jqXHR.complete(function() {\n\t\t\t\t\t\tspan.html( html );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t// enable/disable events\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tenable: null,\n\t\t\tdisable: null\n\t\t},\n\n\t\tenable: function( index ) {\n\t\t\tvar options = this.options,\n\t\t\t\ttrigger;\n\n\t\t\tif ( index && options.disabled === true ||\n\t\t\t\t\t( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) {\n\t\t\t\ttrigger = true;\n\t\t\t}\n\n\t\t\tthis._superApply( arguments );\n\n\t\t\tif ( trigger ) {\n\t\t\t\tthis._trigger( \"enable\", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );\n\t\t\t}\n\t\t},\n\n\t\tdisable: function( index ) {\n\t\t\tvar options = this.options,\n\t\t\t\ttrigger;\n\n\t\t\tif ( index && options.disabled === false ||\n\t\t\t\t\t( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) {\n\t\t\t\ttrigger = true;\n\t\t\t}\n\n\t\t\tthis._superApply( arguments );\n\n\t\t\tif ( trigger ) {\n\t\t\t\tthis._trigger( \"disable\", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );\n\t\t\t}\n\t\t}\n\t});\n\n\t// add/remove methods and events\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tadd: null,\n\t\t\tremove: null,\n\t\t\ttabTemplate: \"<li><a href='#{href}'><span>#{label}</span></a></li>\"\n\t\t},\n\n\t\tadd: function( url, label, index ) {\n\t\t\tif ( index === undefined ) {\n\t\t\t\tindex = this.anchors.length;\n\t\t\t}\n\n\t\t\tvar doInsertAfter, panel,\n\t\t\t\toptions = this.options,\n\t\t\t\tli = $( options.tabTemplate\n\t\t\t\t\t.replace( /#\\{href\\}/g, url )\n\t\t\t\t\t.replace( /#\\{label\\}/g, label ) ),\n\t\t\t\tid = !url.indexOf( \"#\" ) ?\n\t\t\t\t\turl.replace( \"#\", \"\" ) :\n\t\t\t\t\tthis._tabId( li );\n\n\t\t\tli.addClass( \"ui-state-default ui-corner-top\" ).data( \"ui-tabs-destroy\", true );\n\t\t\tli.attr( \"aria-controls\", id );\n\n\t\t\tdoInsertAfter = index >= this.tabs.length;\n\n\t\t\t// try to find an existing element before creating a new one\n\t\t\tpanel = this.element.find( \"#\" + id );\n\t\t\tif ( !panel.length ) {\n\t\t\t\tpanel = this._createPanel( id );\n\t\t\t\tif ( doInsertAfter ) {\n\t\t\t\t\tif ( index > 0 ) {\n\t\t\t\t\t\tpanel.insertAfter( this.panels.eq( -1 ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpanel.appendTo( this.element );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpanel.insertBefore( this.panels[ index ] );\n\t\t\t\t}\n\t\t\t}\n\t\t\tpanel.addClass( \"ui-tabs-panel ui-widget-content ui-corner-bottom\" ).hide();\n\n\t\t\tif ( doInsertAfter ) {\n\t\t\t\tli.appendTo( this.tablist );\n\t\t\t} else {\n\t\t\t\tli.insertBefore( this.tabs[ index ] );\n\t\t\t}\n\n\t\t\toptions.disabled = $.map( options.disabled, function( n ) {\n\t\t\t\treturn n >= index ? ++n : n;\n\t\t\t});\n\n\t\t\tthis.refresh();\n\t\t\tif ( this.tabs.length === 1 && options.active === false ) {\n\t\t\t\tthis.option( \"active\", 0 );\n\t\t\t}\n\n\t\t\tthis._trigger( \"add\", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );\n\t\t\treturn this;\n\t\t},\n\n\t\tremove: function( index ) {\n\t\t\tindex = this._getIndex( index );\n\t\t\tvar options = this.options,\n\t\t\t\ttab = this.tabs.eq( index ).remove(),\n\t\t\t\tpanel = this._getPanelForTab( tab ).remove();\n\n\t\t\t// If selected tab was removed focus tab to the right or\n\t\t\t// in case the last tab was removed the tab to the left.\n\t\t\t// We check for more than 2 tabs, because if there are only 2,\n\t\t\t// then when we remove this tab, there will only be one tab left\n\t\t\t// so we don't need to detect which tab to activate.\n\t\t\tif ( tab.hasClass( \"ui-tabs-active\" ) && this.anchors.length > 2 ) {\n\t\t\t\tthis._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );\n\t\t\t}\n\n\t\t\toptions.disabled = $.map(\n\t\t\t\t$.grep( options.disabled, function( n ) {\n\t\t\t\t\treturn n !== index;\n\t\t\t\t}),\n\t\t\t\tfunction( n ) {\n\t\t\t\t\treturn n >= index ? --n : n;\n\t\t\t\t});\n\n\t\t\tthis.refresh();\n\n\t\t\tthis._trigger( \"remove\", null, this._ui( tab.find( \"a\" )[ 0 ], panel[ 0 ] ) );\n\t\t\treturn this;\n\t\t}\n\t});\n\n\t// length method\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\tlength: function() {\n\t\t\treturn this.anchors.length;\n\t\t}\n\t});\n\n\t// panel ids (idPrefix option + title attribute)\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tidPrefix: \"ui-tabs-\"\n\t\t},\n\n\t\t_tabId: function( tab ) {\n\t\t\tvar a = tab.is( \"li\" ) ? tab.find( \"a[href]\" ) : tab;\n\t\t\ta = a[0];\n\t\t\treturn $( a ).closest( \"li\" ).attr( \"aria-controls\" ) ||\n\t\t\t\ta.title && a.title.replace( /\\s/g, \"_\" ).replace( /[^\\w\\u00c0-\\uFFFF\\-]/g, \"\" ) ||\n\t\t\t\tthis.options.idPrefix + getNextTabId();\n\t\t}\n\t});\n\n\t// _createPanel method\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tpanelTemplate: \"<div></div>\"\n\t\t},\n\n\t\t_createPanel: function( id ) {\n\t\t\treturn $( this.options.panelTemplate )\n\t\t\t\t.attr( \"id\", id )\n\t\t\t\t.addClass( \"ui-tabs-panel ui-widget-content ui-corner-bottom\" )\n\t\t\t\t.data( \"ui-tabs-destroy\", true );\n\t\t}\n\t});\n\n\t// selected option\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\t_create: function() {\n\t\t\tvar options = this.options;\n\t\t\tif ( options.active === null && options.selected !== undefined ) {\n\t\t\t\toptions.active = options.selected === -1 ? false : options.selected;\n\t\t\t}\n\t\t\tthis._super();\n\t\t\toptions.selected = options.active;\n\t\t\tif ( options.selected === false ) {\n\t\t\t\toptions.selected = -1;\n\t\t\t}\n\t\t},\n\n\t\t_setOption: function( key, value ) {\n\t\t\tif ( key !== \"selected\" ) {\n\t\t\t\treturn this._super( key, value );\n\t\t\t}\n\n\t\t\tvar options = this.options;\n\t\t\tthis._super( \"active\", value === -1 ? false : value );\n\t\t\toptions.selected = options.active;\n\t\t\tif ( options.selected === false ) {\n\t\t\t\toptions.selected = -1;\n\t\t\t}\n\t\t},\n\n\t\t_eventHandler: function( event ) {\n\t\t\tthis._superApply( arguments );\n\t\t\tthis.options.selected = this.options.active;\n\t\t\tif ( this.options.selected === false ) {\n\t\t\t\tthis.options.selected = -1;\n\t\t\t}\n\t\t}\n\t});\n\n\t// show and select event\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tshow: null,\n\t\t\tselect: null\n\t\t},\n\t\t_create: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.active !== false ) {\n\t\t\t\tthis._trigger( \"show\", null, this._ui(\n\t\t\t\t\tthis.active.find( \".ui-tabs-anchor\" )[ 0 ],\n\t\t\t\t\tthis._getPanelForTab( this.active )[ 0 ] ) );\n\t\t\t}\n\t\t},\n\t\t_trigger: function( type, event, data ) {\n\t\t\tvar ret = this._superApply( arguments );\n\t\t\tif ( !ret ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif ( type === \"beforeActivate\" && data.newTab.length ) {\n\t\t\t\tret = this._super( \"select\", event, {\n\t\t\t\t\ttab: data.newTab.find( \".ui-tabs-anchor\" )[ 0],\n\t\t\t\t\tpanel: data.newPanel[ 0 ],\n\t\t\t\t\tindex: data.newTab.closest( \"li\" ).index()\n\t\t\t\t});\n\t\t\t} else if ( type === \"activate\" && data.newTab.length ) {\n\t\t\t\tret = this._super( \"show\", event, {\n\t\t\t\t\ttab: data.newTab.find( \".ui-tabs-anchor\" )[ 0 ],\n\t\t\t\t\tpanel: data.newPanel[ 0 ],\n\t\t\t\t\tindex: data.newTab.closest( \"li\" ).index()\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t});\n\n\t// select method\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\tselect: function( index ) {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( index === -1 ) {\n\t\t\t\tif ( this.options.collapsible && this.options.selected !== -1 ) {\n\t\t\t\t\tindex = this.options.selected;\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.anchors.eq( index ).trigger( this.options.event + \".tabs\" );\n\t\t}\n\t});\n\n\t// cookie option\n\t(function() {\n\n\tvar listId = 0;\n\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tcookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }\n\t\t},\n\t\t_create: function() {\n\t\t\tvar options = this.options,\n\t\t\t\tactive;\n\t\t\tif ( options.active == null && options.cookie ) {\n\t\t\t\tactive = parseInt( this._cookie(), 10 );\n\t\t\t\tif ( active === -1 ) {\n\t\t\t\t\tactive = false;\n\t\t\t\t}\n\t\t\t\toptions.active = active;\n\t\t\t}\n\t\t\tthis._super();\n\t\t},\n\t\t_cookie: function( active ) {\n\t\t\tvar cookie = [ this.cookie ||\n\t\t\t\t( this.cookie = this.options.cookie.name || \"ui-tabs-\" + (++listId) ) ];\n\t\t\tif ( arguments.length ) {\n\t\t\t\tcookie.push( active === false ? -1 : active );\n\t\t\t\tcookie.push( this.options.cookie );\n\t\t\t}\n\t\t\treturn $.cookie.apply( null, cookie );\n\t\t},\n\t\t_refresh: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.cookie ) {\n\t\t\t\tthis._cookie( this.options.active, this.options.cookie );\n\t\t\t}\n\t\t},\n\t\t_eventHandler: function( event ) {\n\t\t\tthis._superApply( arguments );\n\t\t\tif ( this.options.cookie ) {\n\t\t\t\tthis._cookie( this.options.active, this.options.cookie );\n\t\t\t}\n\t\t},\n\t\t_destroy: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.cookie ) {\n\t\t\t\tthis._cookie( null, this.options.cookie );\n\t\t\t}\n\t\t}\n\t});\n\n\t})();\n\n\t// load event\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\t_trigger: function( type, event, data ) {\n\t\t\tvar _data = $.extend( {}, data );\n\t\t\tif ( type === \"load\" ) {\n\t\t\t\t_data.panel = _data.panel[ 0 ];\n\t\t\t\t_data.tab = _data.tab.find( \".ui-tabs-anchor\" )[ 0 ];\n\t\t\t}\n\t\t\treturn this._super( type, event, _data );\n\t\t}\n\t});\n\n\t// fx option\n\t// The new animation options (show, hide) conflict with the old show callback.\n\t// The old fx option wins over show/hide anyway (always favor back-compat).\n\t// If a user wants to use the new animation API, they must give up the old API.\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\toptions: {\n\t\t\tfx: null // e.g. { height: \"toggle\", opacity: \"toggle\", duration: 200 }\n\t\t},\n\n\t\t_getFx: function() {\n\t\t\tvar hide, show,\n\t\t\t\tfx = this.options.fx;\n\n\t\t\tif ( fx ) {\n\t\t\t\tif ( $.isArray( fx ) ) {\n\t\t\t\t\thide = fx[ 0 ];\n\t\t\t\t\tshow = fx[ 1 ];\n\t\t\t\t} else {\n\t\t\t\t\thide = show = fx;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn fx ? { show: show, hide: hide } : null;\n\t\t},\n\n\t\t_toggle: function( event, eventData ) {\n\t\t\tvar that = this,\n\t\t\t\ttoShow = eventData.newPanel,\n\t\t\t\ttoHide = eventData.oldPanel,\n\t\t\t\tfx = this._getFx();\n\n\t\t\tif ( !fx ) {\n\t\t\t\treturn this._super( event, eventData );\n\t\t\t}\n\n\t\t\tthat.running = true;\n\n\t\t\tfunction complete() {\n\t\t\t\tthat.running = false;\n\t\t\t\tthat._trigger( \"activate\", event, eventData );\n\t\t\t}\n\n\t\t\tfunction show() {\n\t\t\t\teventData.newTab.closest( \"li\" ).addClass( \"ui-tabs-active ui-state-active\" );\n\n\t\t\t\tif ( toShow.length && fx.show ) {\n\t\t\t\t\ttoShow\n\t\t\t\t\t\t.animate( fx.show, fx.show.duration, function() {\n\t\t\t\t\t\t\tcomplete();\n\t\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\ttoShow.show();\n\t\t\t\t\tcomplete();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start out by hiding, then showing, then completing\n\t\t\tif ( toHide.length && fx.hide ) {\n\t\t\t\ttoHide.animate( fx.hide, fx.hide.duration, function() {\n\t\t\t\t\teventData.oldTab.closest( \"li\" ).removeClass( \"ui-tabs-active ui-state-active\" );\n\t\t\t\t\tshow();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\teventData.oldTab.closest( \"li\" ).removeClass( \"ui-tabs-active ui-state-active\" );\n\t\t\t\ttoHide.hide();\n\t\t\t\tshow();\n\t\t\t}\n\t\t}\n\t});\n}\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.tooltip.js",
    "content": "/*!\n * jQuery UI Tooltip @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n *\tjquery.ui.position.js\n */\n(function( $ ) {\n\nvar increments = 0;\n\nfunction addDescribedBy( elem, id ) {\n\tvar describedby = (elem.attr( \"aria-describedby\" ) || \"\").split( /\\s+/ );\n\tdescribedby.push( id );\n\telem\n\t\t.data( \"ui-tooltip-id\", id )\n\t\t.attr( \"aria-describedby\", $.trim( describedby.join( \" \" ) ) );\n}\n\nfunction removeDescribedBy( elem ) {\n\tvar id = elem.data( \"ui-tooltip-id\" ),\n\t\tdescribedby = (elem.attr( \"aria-describedby\" ) || \"\").split( /\\s+/ ),\n\t\tindex = $.inArray( id, describedby );\n\tif ( index !== -1 ) {\n\t\tdescribedby.splice( index, 1 );\n\t}\n\n\telem.removeData( \"ui-tooltip-id\" );\n\tdescribedby = $.trim( describedby.join( \" \" ) );\n\tif ( describedby ) {\n\t\telem.attr( \"aria-describedby\", describedby );\n\t} else {\n\t\telem.removeAttr( \"aria-describedby\" );\n\t}\n}\n\n$.widget( \"ui.tooltip\", {\n\tversion: \"@VERSION\",\n\toptions: {\n\t\tcontent: function() {\n\t\t\treturn $( this ).attr( \"title\" );\n\t\t},\n\t\thide: true,\n\t\titems: \"[title]\",\n\t\tposition: {\n\t\t\tmy: \"left+15 center\",\n\t\t\tat: \"right center\",\n\t\t\tcollision: \"flipfit flipfit\"\n\t\t},\n\t\tshow: true,\n\t\ttooltipClass: null,\n\n\t\t// callbacks\n\t\tclose: null,\n\t\topen: null\n\t},\n\n\t_create: function() {\n\t\tthis._bind({\n\t\t\tmouseover: \"open\",\n\t\t\tfocusin: \"open\"\n\t\t});\n\n\t\t// IDs of generated tooltips, needed for destroy\n\t\tthis.tooltips = {};\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis[ value ? \"_disable\" : \"_enable\" ]();\n\t\t\tthis.options[ key ] = value;\n\t\t\t// disable element style changes\n\t\t\treturn;\n\t\t}\n\t\tthis._super( key, value );\n\t},\n\n\t_disable: function() {\n\t\tvar that = this;\n\n\t\t// close open tooltips\n\t\t$.each( this.tooltips, function( id, element ) {\n\t\t\tvar event = $.Event( \"blur\" );\n\t\t\tevent.target = event.currentTarget = element[0];\n\t\t\tthat.close( event, true );\n\t\t});\n\n\t\t// remove title attributes to prevent native tooltips\n\t\tthis.element.find( this.options.items ).andSelf().each(function() {\n\t\t\tvar element = $( this );\n\t\t\tif ( element.is( \"[title]\" ) ) {\n\t\t\t\telement\n\t\t\t\t\t.data( \"ui-tooltip-title\", element.attr( \"title\" ) )\n\t\t\t\t\t.attr( \"title\", \"\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_enable: function() {\n\t\t// restore title attributes\n\t\tthis.element.find( this.options.items ).andSelf().each(function() {\n\t\t\tvar element = $( this );\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t}\n\t\t});\n\t},\n\n\topen: function( event ) {\n\t\tvar content,\n\t\t\tthat = this,\n\t\t\ttarget = $( event ? event.target : this.element )\n\t\t\t\t.closest( this.options.items );\n\n\t\t// if ui-tooltip-id exists, then the tooltip is already open\n\t\tif ( !target.length || target.data( \"ui-tooltip-id\" ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( target.attr( \"title\" ) ) {\n\t\t\ttarget.data( \"ui-tooltip-title\", target.attr( \"title\" ) );\n\t\t}\n\n\t\ttarget.data( \"tooltip-open\", true );\n\n\t\tcontent = this.options.content.call( target[0], function( response ) {\n\t\t\t// ignore async response if tooltip was closed already\n\t\t\tif ( !target.data( \"tooltip-open\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// IE may instantly serve a cached response for ajax requests\n\t\t\t// delay this call to _open so the other call to _open runs first\n\t\t\tsetTimeout(function() {\n\t\t\t\tthat._open( event, target, response );\n\t\t\t}, 1 );\n\t\t});\n\t\tif ( content ) {\n\t\t\tthat._open( event, target, content );\n\t\t}\n\t},\n\n\t_open: function( event, target, content ) {\n\t\tif ( !content ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if we have a title, clear it to prevent the native tooltip\n\t\t// we have to check first to avoid defining a title if none exists\n\t\t// (we don't want to cause an element to start matching [title])\n\t\t//\n\t\t// We use removeAttr only for key events, to allow IE to export the correct\n\t\t// accessible attributes. For mouse events, set to empty string to avoid\n\t\t// native tooltip showing up (happens only when removing inside mouseover).\n\t\tif ( target.is( \"[title]\" ) ) {\n\t\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\t\ttarget.attr( \"title\", \"\" );\n\t\t\t} else {\n\t\t\t\ttarget.removeAttr( \"title\" );\n\t\t\t}\n\t\t}\n\n\t\t// ajaxy tooltip can update an existing one\n\t\tvar tooltip = this._find( target );\n\t\tif ( !tooltip.length ) {\n\t\t\ttooltip = this._tooltip( target );\n\t\t\taddDescribedBy( target, tooltip.attr( \"id\" ) );\n\t\t}\n\t\ttooltip.find( \".ui-tooltip-content\" ).html( content );\n\t\ttooltip\n\t\t\t.stop( true )\n\t\t\t.position( $.extend({\n\t\t\t\tof: target\n\t\t\t}, this.options.position ) )\n\t\t\t.hide();\n\n\t\tthis._show( tooltip, this.options.show );\n\n\t\tthis._trigger( \"open\", event, { tooltip: tooltip } );\n\n\t\tthis._bind( target, {\n\t\t\tmouseleave: \"close\",\n\t\t\tfocusout: \"close\",\n\t\t\tkeyup: function( event ) {\n\t\t\t\tif ( event.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\tvar fakeEvent = $.Event(event);\n\t\t\t\t\tfakeEvent.currentTarget = target[0];\n\t\t\t\t\tthis.close( fakeEvent, true );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclose: function( event, force ) {\n\t\tvar that = this,\n\t\t\ttarget = $( event ? event.currentTarget : this.element ),\n\t\t\ttooltip = this._find( target );\n\n\t\t// disabling closes the tooltip, so we need to track when we're closing\n\t\t// to avoid an infinite loop in case the tooltip becomes disabled on close\n\t\tif ( this.closing ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// don't close if the element has focus\n\t\t// this prevents the tooltip from closing if you hover while focused\n\t\t//\n\t\t// we have to check the event type because tabbing out of the document\n\t\t// may leave the element as the activeElement\n\t\tif ( !force && event && event.type !== \"focusout\" &&\n\t\t\t\tthis.document[0].activeElement === target[0] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// only set title if we had one before (see comment in _open())\n\t\tif ( target.data( \"ui-tooltip-title\" ) ) {\n\t\t\ttarget.attr( \"title\", target.data( \"ui-tooltip-title\" ) );\n\t\t}\n\n\t\tremoveDescribedBy( target );\n\n\t\ttooltip.stop( true );\n\t\tthis._hide( tooltip, this.options.hide, function() {\n\t\t\t$( this ).remove();\n\t\t\tdelete that.tooltips[ this.id ];\n\t\t});\n\n\t\ttarget.removeData( \"tooltip-open\" );\n\t\ttarget.unbind( \"mouseleave.tooltip focusout.tooltip keyup.tooltip\" );\n\n\t\tthis.closing = true;\n\t\tthis._trigger( \"close\", event, { tooltip: tooltip } );\n\t\tthis.closing = false;\n\t},\n\n\t_tooltip: function( element ) {\n\t\tvar id = \"ui-tooltip-\" + increments++,\n\t\t\ttooltip = $( \"<div>\" )\n\t\t\t\t.attr({\n\t\t\t\t\tid: id,\n\t\t\t\t\trole: \"tooltip\"\n\t\t\t\t})\n\t\t\t\t.addClass( \"ui-tooltip ui-widget ui-corner-all ui-widget-content \" +\n\t\t\t\t\t( this.options.tooltipClass || \"\" ) );\n\t\t$( \"<div>\" )\n\t\t\t.addClass( \"ui-tooltip-content\" )\n\t\t\t.appendTo( tooltip );\n\t\ttooltip.appendTo( this.document[0].body );\n\t\tif ( $.fn.bgiframe ) {\n\t\t\ttooltip.bgiframe();\n\t\t}\n\t\tthis.tooltips[ id ] = element;\n\t\treturn tooltip;\n\t},\n\n\t_find: function( target ) {\n\t\tvar id = target.data( \"ui-tooltip-id\" );\n\t\treturn id ? $( \"#\" + id ) : $();\n\t},\n\n\t_destroy: function() {\n\t\t$.each( this.tooltips, function( id ) {\n\t\t\t$( \"#\" + id ).remove();\n\t\t});\n\t}\n});\n\n}( jQuery ) );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/jquery-ui/ui/jquery.ui.widget.js",
    "content": "/*!\n * jQuery UI Widget @VERSION\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Widget\n */\n(function( $, undefined ) {\n\nvar slice = Array.prototype.slice,\n\t_cleanData = $.cleanData;\n$.cleanData = function( elems ) {\n\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\ttry {\n\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t// http://bugs.jquery.com/ticket/8235\n\t\t} catch( e ) {}\n\t}\n\t_cleanData( elems );\n};\n\n$.widget = function( name, base, prototype ) {\n\tvar fullName, existingConstructor, constructor, basePrototype,\n\t\tnamespace = name.split( \".\" )[ 0 ];\n\n\tname = name.split( \".\" )[ 1 ];\n\tfullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\t// create selector for plugin\n\t$.expr[ \":\" ][ fullName ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\t\t// allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\t// extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\t\t// copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\t\t// track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t});\n\n\tbasePrototype = new base();\n\t// we need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( $.isFunction( value ) ) {\n\t\t\tprototype[ prop ] = (function() {\n\t\t\t\tvar _super = function() {\n\t\t\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t\t\t},\n\t\t\t\t\t_superApply = function( args ) {\n\t\t\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t\t\t};\n\t\t\t\treturn function() {\n\t\t\t\t\tvar __super = this._super,\n\t\t\t\t\t\t__superApply = this._superApply,\n\t\t\t\t\t\treturnValue;\n\n\t\t\t\t\tthis._super = _super;\n\t\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\t\tthis._super = __super;\n\t\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\t\treturn returnValue;\n\t\t\t\t};\n\t\t\t})();\n\t\t}\n\t});\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: name\n\t}, prototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\t// TODO remove widgetBaseClass, see #8155\n\t\twidgetBaseClass: fullName,\n\t\twidgetFullName: fullName\n\t});\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor, child._proto );\n\t\t});\n\t\t// remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n};\n\n$.widget.extend = function( target ) {\n\tvar input = slice.call( arguments, 1 ),\n\t\tinputIndex = 0,\n\t\tinputLength = input.length,\n\t\tkey,\n\t\tvalue;\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif (input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\t\t\t\ttarget[ key ] = $.isPlainObject( value ) ? $.widget.extend( {}, target[ key ], value ) : value;\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\",\n\t\t\targs = slice.call( arguments, 1 ),\n\t\t\treturnValue = this;\n\n\t\t// allow multiple hashes to be passed on init\n\t\toptions = !isMethodCall && args.length ?\n\t\t\t$.widget.extend.apply( null, [ options ].concat(args) ) :\n\t\t\toptions;\n\n\t\tif ( isMethodCall ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar methodValue,\n\t\t\t\t\tinstance = $.data( this, fullName );\n\t\t\t\tif ( !instance ) {\n\t\t\t\t\treturn $.error( \"cannot call methods on \" + name + \" prior to initialization; \" +\n\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t}\n\t\t\t\tif ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name + \" widget instance\" );\n\t\t\t\t}\n\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\tmethodValue;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} )._init();\n\t\t\t\t} else {\n\t\t\t\t\tnew object( options, this );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( options, element ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\toptions: {\n\t\tdisabled: false,\n\n\t\t// callbacks\n\t\tcreate: null\n\t},\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\n\t\tif ( element !== this ) {\n\t\t\t// 1.9 BC for #7810\n\t\t\t// TODO remove dual storage\n\t\t\t$.data( element, this.widgetName, this );\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._bind({ remove: \"destroy\" });\n\t\t\tthis.document = $( element.style ?\n\t\t\t\t// element within the document\n\t\t\t\telement.ownerDocument :\n\t\t\t\t// element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[0].defaultView || this.document[0].parentWindow );\n\t\t}\n\n\t\tthis._create();\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\t_getCreateOptions: $.noop,\n\t_getCreateEventData: $.noop,\n\t_create: $.noop,\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tthis._destroy();\n\t\t// we can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._bind()\n\t\tthis.element\n\t\t\t.unbind( \".\" + this.widgetName )\n\t\t\t// 1.9 BC for #7810\n\t\t\t// TODO remove dual storage\n\t\t\t.removeData( this.widgetName )\n\t\t\t.removeData( this.widgetFullName )\n\t\t\t// support: jquery <1.6.3\n\t\t\t// http://bugs.jquery.com/ticket/9413\n\t\t\t.removeData( $.camelCase( this.widgetFullName ) );\n\t\tthis.widget()\n\t\t\t.unbind( \".\" + this.widgetName )\n\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t.removeClass(\n\t\t\t\tthis.widgetFullName + \"-disabled \" +\n\t\t\t\t\"ui-state-disabled\" );\n\n\t\t// clean up events and states\n\t\tthis.bindings.unbind( \".\" + this.widgetName );\n\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t},\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key,\n\t\t\tparts,\n\t\t\tcurOption,\n\t\t\ti;\n\n\t\tif ( arguments.length === 0 ) {\n\t\t\t// don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\t\t\t// handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\t_setOption: function( key, value ) {\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.widget()\n\t\t\t\t.toggleClass( this.widgetFullName + \"-disabled ui-state-disabled\", !!value )\n\t\t\t\t.attr( \"aria-disabled\", value );\n\t\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tenable: function() {\n\t\treturn this._setOption( \"disabled\", false );\n\t},\n\tdisable: function() {\n\t\treturn this._setOption( \"disabled\", true );\n\t},\n\n\t_bind: function( element, handlers ) {\n\t\t// no element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t} else {\n\t\t\t// accept selectors, DOM elements\n\t\t\telement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\tvar instance = this;\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\t\t\t\t// allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( instance.options.disabled === true ||\n\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || jQuery.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^(\\w+)\\s*(.*)$/ ),\n\t\t\t\teventName = match[1] + \".\" + instance.widgetName,\n\t\t\t\tselector = match[2];\n\t\t\tif ( selector ) {\n\t\t\t\tinstance.widget().delegate( selector, eventName, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.bind( eventName, handlerProxy );\n\t\t\t}\n\t\t});\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._bind( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-hover\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._bind( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-focus\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig,\n\t\t\tcallback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\t\t// the original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[0], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\t\tvar hasOptions,\n\t\t\teffectName = !options ?\n\t\t\t\tmethod :\n\t\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\t\tdefaultEffect :\n\t\t\t\t\toptions.effect || defaultEffect;\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\t\tif ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue(function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t});\n\t\t}\n\t};\n});\n\n// DEPRECATED\nif ( $.uiBackCompat !== false ) {\n\t$.Widget.prototype._getCreateOptions = function() {\n\t\treturn $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];\n\t};\n}\n\n})( jQuery );\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/syntax/file1.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global brackets, require */\n\nvar A1 = { propA : 1 },\n    A2 = { propA : 2 },\n    A3 = A2;\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/syntax/file2.js",
    "content": "/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, describe, it, xit, expect, beforeEach, afterEach, waitsFor, runs, $, brackets, waitsForDone */\n\nfunction nonAsciiTest() {\n    var hope;  // unknown type\n    var month = getMonthName(5);\n    A1.propA = \"test\";\n}\n\nfunction getMonthName(mo) {\n   mo = mo-1; // Adjust month number for array index (1=Jan, 12=Dec)\n   var months = new Array(\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\",\n      \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\");\n   if (months[mo] !== undefined) {\n      return months[mo];\n   } else {\n      return null;\n   }\n}\n\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/syntax/test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <script src=\"./file1.js\"></script>\n    <script src=\"./file2.js\"></script>\n    <!-- leave follow empty line for later file including -->\n    \n    \n    \n    \n    \n<script>\n    var txt=\"\";\n    nonAsciiTest(); // in quick editor, test jump, function type, code hint list\n    myTest();\n    callOtherMethods();\n</script>\n<script>\n    function myTest(){\n        monthName = \"test\";\n        simple1();\n    }\n    function simple1(){\n    }\n    \n</script>\n    \n</head>\n\n<body>\n    <input type=\"button\" value=\"View message\" onclick=\"message()\">\n</body>\n\n</html>"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/syntax/test1inline.js",
    "content": "{{0}}function func1() {\n    // comment\n}\n\n/*\n * comment\n */\n{{1}}var func2 = function() {\n\n{{2}}    func3: function() {\n        /* comment */\n    }\n\n}\n\nfunction func4() {\n    return func1();\n}\n\nfunction func5() {\n    return true;\n}\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/syntax/test1main.js",
    "content": "\n/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global func1: false, func2: false, func3: false */\n\nvar a = {{0}}func1();\nvar b = fun{{1}}c2();\nvar c = func3{{2}}();\n"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittest-files/syntax/tokens.js",
    "content": "function foo () {\n}\n\nvar regExp = /{{0}}foo()/;\n/*\n{{1}}foo()\n*/\n// {{2}}foo()\nvar str1 = \"{{3}}foo()\", str2 = '{{4}}foo()';"
  },
  {
    "path": "src/extensions/default/JavaScriptQuickEdit/unittests.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, xit, expect, beforeEach, afterEach, waitsFor, runs, waitsForDone, waitsForFail */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CommandManager,         // loaded from brackets.test\n        EditorManager,          // loaded from brackets.test\n        PerfUtils,              // loaded from brackets.test\n        JSUtils,                // loaded from brackets.test\n\n        FileUtils           = brackets.getModule(\"file/FileUtils\"),\n        SpecRunnerUtils     = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        UnitTestReporter    = brackets.getModule(\"test/UnitTestReporter\");\n\n    var extensionPath = FileUtils.getNativeModuleDirectoryPath(module),\n        testPath = extensionPath + \"/unittest-files/syntax\",\n        tempPath = SpecRunnerUtils.getTempDirectory(),\n        testWindow,\n        initInlineTest;\n\n    function rewriteProject(spec) {\n        var result = new $.Deferred(),\n            infos = {},\n            options = {\n                parseOffsets    : true,\n                infos           : infos,\n                removePrefix    : true\n            };\n\n        SpecRunnerUtils.copyPath(testPath, tempPath, options).done(function () {\n            spec.infos = infos;\n            result.resolve();\n        }).fail(function () {\n            result.reject();\n        });\n\n        return result.promise();\n    }\n\n    // Helper function for testing cursor position\n    function fixPos(pos) {\n        if (!(\"sticky\" in pos)) {\n            pos.sticky = null;\n        }\n        return pos;\n    }\n\n    /**\n     * Performs setup for an inline editor test. Parses offsets (saved to Spec.offsets) for all files in\n     * the test project (testPath) and saves files back to disk without offset markup.\n     * When finished, open an editor for the specified project relative file path\n     * then attempts opens an inline editor at the given offset. Installs an after()\n     * function restore all file content back to original state with offset markup.\n     *\n     * @param {!string} openFile Project relative file path to open in a main editor.\n     * @param {!number} openOffset The offset index location within openFile to open an inline editor.\n     * @param {?boolean} expectInline Use false to verify that an inline editor should not be opened. Omit otherwise.\n     */\n    var _initInlineTest = function (openFile, openOffset, expectInline, filesToOpen) {\n        var spec = this;\n\n        filesToOpen = filesToOpen || [];\n        expectInline = (expectInline !== undefined) ? expectInline : true;\n\n        runs(function () {\n            waitsForDone(rewriteProject(spec), \"rewriteProject\");\n        });\n\n        SpecRunnerUtils.loadProjectInTestWindow(tempPath);\n\n        runs(function () {\n            filesToOpen.push(openFile);\n            waitsForDone(SpecRunnerUtils.openProjectFiles(filesToOpen), \"openProjectFiles\");\n        });\n\n        if (openOffset !== undefined) {\n            runs(function () {\n                // open inline editor at specified offset index\n                waitsForDone(SpecRunnerUtils.toggleQuickEditAtOffset(\n                    EditorManager.getCurrentFullEditor(),\n                    spec.infos[openFile].offsets[openOffset]\n                ), \"toggleQuickEditAtOffset\");\n            });\n        }\n    };\n\n    describe(\"JSQuickEdit\", function () {\n\n        /*\n         *\n         */\n        describe(\"javaScriptFunctionProvider\", function () {\n\n            beforeEach(function () {\n                initInlineTest = _initInlineTest.bind(this);\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow          = w;\n                    EditorManager       = testWindow.brackets.test.EditorManager;\n                    CommandManager      = testWindow.brackets.test.CommandManager;\n                    JSUtils             = testWindow.brackets.test.JSUtils;\n                });\n\n                this.addMatchers({\n\n                    toHaveInlineEditorRange: function (range) {\n                        var i = 0,\n                            editor = this.actual,\n                            hidden,\n                            lineCount = editor.lineCount(),\n                            shouldHide = [],\n                            shouldShow = [],\n                            startLine = range.startLine,\n                            endLine = range.endLine,\n                            visibleRangeCheck;\n\n                        for (i = 0; i < lineCount; i++) {\n                            hidden = editor._codeMirror.getLineHandle(i).hidden || false;\n\n                            if (i < startLine) {\n                                if (!hidden) {\n                                    shouldHide.push(i); // lines above start line should be hidden\n                                }\n                            } else if ((i >= startLine) && (i <= endLine)) {\n                                if (hidden) {\n                                    shouldShow.push(i); // lines in the range should be visible\n                                }\n                            } else if (i > endLine) {\n                                if (!hidden) {\n                                    shouldHide.push(i); // lines below end line should be hidden\n                                }\n                            }\n                        }\n\n                        visibleRangeCheck = (editor._visibleRange.startLine === startLine) &&\n                            (editor._visibleRange.endLine === endLine);\n\n                        this.message = function () {\n                            var msg = \"\";\n\n                            if (shouldHide.length > 0) {\n                                msg += \"Expected inline editor to hide [\" + shouldHide.toString() + \"].\\n\";\n                            }\n\n                            if (shouldShow.length > 0) {\n                                msg += \"Expected inline editor to show [\" + shouldShow.toString() + \"].\\n\";\n                            }\n\n                            if (!visibleRangeCheck) {\n                                msg += \"Editor._visibleRange [\" +\n                                    editor._visibleRange.startLine + \",\" +\n                                    editor._visibleRange.endLine + \"] should be [\" +\n                                    startLine + \",\" + endLine + \"].\";\n                            }\n\n                            return msg;\n                        };\n\n                        return (shouldHide.length === 0) &&\n                            (shouldShow.length === 0) &&\n                            visibleRangeCheck;\n                    }\n                });\n            });\n\n            afterEach(function () {\n                //debug visual confirmation of inline editor\n                //waits(1000);\n\n                // revert files to original content with offset markup\n                initInlineTest      = null;\n                testWindow          = null;\n                EditorManager       = null;\n                CommandManager      = null;\n                JSUtils             = null;\n                SpecRunnerUtils.closeTestWindow();\n            });\n\n            it(\"should ignore tokens that are not function calls or references\", function () {\n                var editor,\n                    extensionRequire,\n                    jsQuickEditMain,\n                    tokensFile = \"tokens.js\",\n                    promise,\n                    offsets;\n\n                initInlineTest(tokensFile);\n\n                runs(function () {\n                    extensionRequire = testWindow.brackets.getModule(\"utils/ExtensionLoader\").getRequireContextForExtension(\"JavaScriptQuickEdit\");\n                    jsQuickEditMain = extensionRequire(\"main\");\n                    editor = EditorManager.getCurrentFullEditor();\n                    offsets = this.infos[tokensFile];\n\n                    // regexp token\n                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[0]);\n                    expect(promise).toBe(Strings.ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND);\n\n                    // multi-line comment\n                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[1]);\n                    expect(promise).toBe(Strings.ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND);\n\n                    // single-line comment\n                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[2]);\n                    expect(promise).toBe(Strings.ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND);\n\n                    // string, double quotes\n                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[3]);\n                    expect(promise).toBe(Strings.ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND);\n\n                    // string, single quotes\n                    promise = jsQuickEditMain.javaScriptFunctionProvider(editor, offsets[4]);\n                    expect(promise).toBe(Strings.ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND);\n                });\n            });\n\n            it(\"should open a function with  form: function functionName()\", function () {\n                initInlineTest(\"test1main.js\", 0);\n\n                runs(function () {\n                    var inlineWidget = EditorManager.getCurrentFullEditor().getInlineWidgets()[0];\n                    var inlinePos = inlineWidget.editor.getCursorPos();\n\n                    // verify cursor position in inline editor\n                    expect(fixPos(inlinePos)).toEqual(fixPos(this.infos[\"test1inline.js\"].offsets[0]));\n                });\n            });\n\n            it(\"should open a function with  form: functionName = function()\", function () {\n                initInlineTest(\"test1main.js\", 1);\n\n                runs(function () {\n                    var inlineWidget = EditorManager.getCurrentFullEditor().getInlineWidgets()[0];\n                    var inlinePos = inlineWidget.editor.getCursorPos();\n\n                    // verify cursor position in inline editor\n                    expect(fixPos(inlinePos)).toEqual(fixPos(this.infos[\"test1inline.js\"].offsets[1]));\n                });\n            });\n\n            it(\"should open a function with  form: functionName: function()\", function () {\n                initInlineTest(\"test1main.js\", 2);\n\n                runs(function () {\n                    var inlineWidget = EditorManager.getCurrentFullEditor().getInlineWidgets()[0];\n                    var inlinePos = inlineWidget.editor.getCursorPos();\n\n                    // verify cursor position in inline editor\n                    expect(fixPos(inlinePos)).toEqual(fixPos(this.infos[\"test1inline.js\"].offsets[2]));\n                });\n            });\n\n            describe(\"Code hints tests within quick edit window \", function () {\n                var JSCodeHints,\n                    ParameterHintProvider;\n\n                /*\n                 * Ask provider for hints at current cursor position; expect it to\n                 * return some\n                 *\n                 * @param {Object} provider - a CodeHintProvider object\n                 * @param {string} key - the charCode of a key press that triggers the\n                 *      CodeHint provider\n                 * @return {boolean} - whether the provider has hints in the context of\n                 *      the test editor\n                 */\n                function expectHints(provider, key) {\n                    if (key === undefined) {\n                        key = null;\n                    }\n\n                    expect(provider.hasHints(EditorManager.getActiveEditor(), key)).toBe(true);\n                    return provider.getHints(null);\n                }\n\n                /*\n                 * Wait for a hint response object to resolve, then apply a callback\n                 * to the result\n                 *\n                 * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n                 *      possibly deferred\n                 * @param {Function} callback - the callback to apply to the resolved\n                 *      hint response object\n                 */\n                function _waitForHints(hintObj, callback) {\n                    var complete = false,\n                        hintList = null;\n\n                    if (hintObj.hasOwnProperty(\"hints\")) {\n                        complete = true;\n                        hintList = hintObj.hints;\n                    } else {\n                        hintObj.done(function (obj) {\n                            complete = true;\n                            hintList = obj.hints;\n                        });\n                    }\n\n                    waitsFor(function () {\n                        return complete;\n                    }, \"Expected hints did not resolve\", 3000);\n\n                    runs(function () { callback(hintList); });\n                }\n\n                /*\n                 * Expect a given list of hints to be present in a given hint\n                 * response object, and no more.\n                 *\n                 * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n                 *      possibly deferred\n                 * @param {Array.<string>} expectedHints - a list of hints that should be\n                 *      present in the hint response, and no more.\n                 */\n                function hintsPresentExact(hintObj, expectedHints) {\n                    _waitForHints(hintObj, function (hintList) {\n                        expect(hintList).toBeTruthy();\n                        expect(hintList.length).toBe(expectedHints.length);\n                        expectedHints.forEach(function (expectedHint, index) {\n                            expect(hintList[index].data(\"token\").value).toBe(expectedHint);\n                        });\n                    });\n                }\n\n                /**\n                 * Show a function hint based on the code at the cursor. Verify the\n                 * hint matches the passed in value.\n                 *\n                 * @param {Array<{name: string, type: string, isOptional: boolean}>}\n                 * expectedParams - array of records, where each element of the array\n                 * describes a function parameter. If null, then no hint is expected.\n                 * @param {number} expectedParameter - the parameter at cursor.\n                 */\n                function expectParameterHint(expectedParams, expectedParameter) {\n                    var requestHints = undefined,\n                        request = null;\n\n                    function expectHint(hint) {\n                        var params = hint.parameters,\n                            n = params.length,\n                            i;\n\n                        // compare params to expected params\n                        expect(params.length).toBe(expectedParams.length);\n                        expect(hint.currentIndex).toBe(expectedParameter);\n\n                        for (i = 0; i < n; i++) {\n\n                            expect(params[i].name).toBe(expectedParams[i].name);\n                            expect(params[i].type).toBe(expectedParams[i].type);\n                            if (params[i].isOptional) {\n                                expect(expectedParams[i].isOptional).toBeTruthy();\n                            } else {\n                                expect(expectedParams[i].isOptional).toBeFalsy();\n                            }\n                        }\n\n                    }\n\n                    runs(function () {\n                        request = ParameterHintProvider._getParameterHint();\n\n                        if (expectedParams === null) {\n                            request.fail(function (result) {\n                                requestHints = result;\n                            });\n\n                            waitsForFail(request, \"ParameterHints\");\n                        } else {\n                            request.done(function (result) {\n                                requestHints = result;\n                            });\n\n                            waitsForDone(request, \"ParameterHints\");\n                        }\n                    });\n\n                    if (expectedParams === null) {\n                        expect(requestHints).toBe(null);\n                    } else {\n                        expectHint(requestHints);\n                    }\n                }\n\n                /**\n                 * Wait for the editor to change positions, such as after a jump to\n                 * definition has been triggered.  Will timeout after 3 seconds\n                 *\n                 * @param {{line:number, ch:number}} oldLocation - the original line/col\n                 * @param {Function} callback - the callback to apply once the editor has changed position\n                 */\n                function _waitForJump(oldLocation, callback) {\n                    var cursor = null;\n                    waitsFor(function () {\n                        var activeEditor = EditorManager.getActiveEditor();\n                        cursor = activeEditor.getCursorPos();\n                        return (cursor.line !== oldLocation.line) ||\n                            (cursor.ch !== oldLocation.ch);\n                    }, \"Expected jump did not occur\", 3000);\n\n                    runs(function () { callback(cursor); });\n                }\n\n                /**\n                 * Trigger a jump to definition, and verify that the editor jumped to\n                 * the expected location.\n                 *\n                 * @param {{line:number, ch:number, file:string}} expectedLocation - the\n                 *  line, column, and optionally the new file the editor should jump to.  If the\n                 *  editor is expected to stay in the same file, then file may be omitted.\n                 */\n                function editorJumped(jsCodeHints, testEditor, expectedLocation) {\n                    var oldLocation = testEditor.getCursorPos();\n\n                    jsCodeHints.handleJumpToDefinition();\n\n\n                    _waitForJump(oldLocation, function (newCursor) {\n                        expect(newCursor.line).toBe(expectedLocation.line);\n                        expect(newCursor.ch).toBe(expectedLocation.ch);\n                        if (expectedLocation.file) {\n                            var activeEditor = EditorManager.getActiveEditor();\n                            expect(activeEditor.document.file.name).toBe(expectedLocation.file);\n                        }\n                    });\n                }\n\n                function initJSCodeHints() {\n                    var extensionRequire = testWindow.brackets.getModule(\"utils/ExtensionLoader\").\n                                getRequireContextForExtension(\"JavaScriptCodeHints\");\n                    JSCodeHints = extensionRequire(\"main\");\n                    ParameterHintProvider = extensionRequire(\"ParameterHintsProvider\").JSParameterHintsProvider();\n                }\n\n                beforeEach(function () {\n                    initInlineTest(\"test.html\");\n                    initJSCodeHints();\n                });\n\n                afterEach(function () {\n                    JSCodeHints = null;\n                    ParameterHintProvider = null;\n                });\n\n                it(\"should see code hint lists in quick editor\", function () {\n                    var start        = {line: 13, ch: 11 },\n                        testPos      = {line: 5, ch: 29},\n                        testEditor;\n\n                    runs(function () {\n                        var openQuickEditor = SpecRunnerUtils.toggleQuickEditAtOffset(EditorManager.getCurrentFullEditor(), start);\n                        waitsForDone(openQuickEditor, \"Open quick editor\");\n                    });\n\n                    runs(function () {\n                        testEditor = EditorManager.getActiveEditor();\n                        testEditor.setCursorPos(testPos);\n                        expectParameterHint([{name: \"mo\", type: \"Number\"}], 0);\n                    });\n                });\n\n                it(\"should see jump to definition on variable working in quick editor\", function () {\n                    var start        = {line: 13, ch: 10 },\n                        testPos      = {line: 6, ch: 7},\n                        testJumpPos  = {line: 6, ch: 5},\n                        jumpPos      = {line: 3, ch: 6},\n                        testEditor;\n\n                    runs(function () {\n                        var openQuickEditor = SpecRunnerUtils.toggleQuickEditAtOffset(EditorManager.getCurrentFullEditor(), start);\n                        waitsForDone(openQuickEditor, \"Open quick editor\");\n                    });\n\n                    runs(function () {\n                        testEditor = EditorManager.getActiveEditor();\n                        testEditor.setCursorPos(testPos);\n                        var hintObj = expectHints(JSCodeHints.jsHintProvider);\n                        hintsPresentExact(hintObj, [\"propA\"]);\n                    });\n\n                    runs(function () {\n                        testEditor = EditorManager.getActiveEditor();\n                        testEditor.setCursorPos(testJumpPos);\n                        editorJumped(JSCodeHints, testEditor, jumpPos);\n                    });\n                });\n\n                // FIXME (issue #3951): jump to method inside quick editor doesn't jump\n                xit(\"should see jump to definition on method working in quick editor\", function () {\n                    var start        = {line: 13, ch: 13 },\n                        testPos      = {line: 5,  ch: 25},\n                        jumpPos      = {line: 9, ch: 21},\n                        testEditor;\n\n                    runs(function () {\n                        var openQuickEditor = SpecRunnerUtils.toggleQuickEditAtOffset(EditorManager.getCurrentFullEditor(), start);\n                        waitsForDone(openQuickEditor, \"Open quick editor\");\n                    });\n\n                    runs(function () {\n                        testEditor = EditorManager.getActiveEditor();\n                        testEditor.setCursorPos(testPos);\n                        editorJumped(jumpPos);\n                    });\n\n                });\n\n            });\n        });\n\n        describe(\"Performance suite\", function () {\n\n            this.category = \"performance\";\n\n            var testPath = extensionPath + \"/unittest-files/jquery-ui\";\n\n            beforeEach(function () {\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow = w;\n                    CommandManager      = testWindow.brackets.test.CommandManager;\n                    EditorManager       = testWindow.brackets.test.EditorManager;\n                    PerfUtils           = testWindow.brackets.test.PerfUtils;\n                });\n            });\n\n            afterEach(function () {\n                testWindow      = null;\n                CommandManager  = null;\n                EditorManager   = null;\n                PerfUtils       = null;\n                SpecRunnerUtils.closeTestWindow();\n            });\n\n            it(\"should open inline editors\", function () {\n                SpecRunnerUtils.loadProjectInTestWindow(testPath);\n\n                var extensionRequire,\n                    JavaScriptQuickEdit,\n                    i,\n                    perfMeasurements;\n\n                runs(function () {\n                    perfMeasurements = [\n                        {\n                            measure: PerfUtils.JAVASCRIPT_INLINE_CREATE,\n                            children: [\n                                {\n                                    measure: PerfUtils.JAVASCRIPT_FIND_FUNCTION,\n                                    children: [\n                                        {\n                                            measure: PerfUtils.JSUTILS_GET_ALL_FUNCTIONS,\n                                            children: [\n                                                {\n                                                    measure: PerfUtils.DOCUMENT_MANAGER_GET_DOCUMENT_FOR_PATH,\n                                                    name: \"Document creation during this search\",\n                                                    operation: \"sum\"\n                                                },\n                                                {\n                                                    measure: PerfUtils.JSUTILS_REGEXP,\n                                                    operation: \"sum\"\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            measure: PerfUtils.JSUTILS_END_OFFSET,\n                                            operation: \"sum\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    ];\n                });\n\n                runs(function () {\n                    extensionRequire = testWindow.brackets.getModule(\"utils/ExtensionLoader\").getRequireContextForExtension(\"JavaScriptQuickEdit\");\n                    JavaScriptQuickEdit = extensionRequire(\"main\");\n\n                    waitsForDone(SpecRunnerUtils.openProjectFiles([\"ui/jquery.effects.core.js\"]), \"openProjectFiles\");\n                });\n\n                var runCreateInlineEditor = function () {\n                    var editor = EditorManager.getCurrentFullEditor();\n                    // Set the cursor in the middle of a call to \"extend\" so the JS helper function works correctly.\n                    editor.setCursorPos(271, 20);\n                    waitsForDone(\n                        JavaScriptQuickEdit._createInlineEditor(editor, \"extend\"),\n                        \"createInlineEditor\",\n                        5000\n                    );\n                };\n\n                function logPerf() {\n                    var reporter = UnitTestReporter.getActiveReporter();\n                    reporter.logTestWindow(perfMeasurements);\n                    reporter.clearTestWindow();\n                }\n\n                // repeat 5 times\n                for (i = 0; i < 5; i++) {\n                    runs(runCreateInlineEditor);\n                    runs(logPerf);\n                }\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/ExtractToFunction.js",
    "content": "/*\n* Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining a\n* copy of this software and associated documentation files (the \"Software\"),\n* to deal in the Software without restriction, including without limitation\n* the rights to use, copy, modify, merge, publish, distribute, sublicense,\n* and/or sell copies of the Software, and to permit persons to whom the\n* Software is furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n* DEALINGS IN THE SOFTWARE.\n*\n*/\n\ndefine(function(require, exports, module) {\n    'use strict';\n\n    var ASTWalker           = brackets.getModule(\"thirdparty/acorn/dist/walk\"),\n        EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        _                   = brackets.getModule(\"thirdparty/lodash\"),\n        StringUtils         = brackets.getModule(\"utils/StringUtils\"),\n        Session             = brackets.getModule(\"JSUtils/Session\"),\n        RefactoringUtils    = require(\"RefactoringUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        InlineMenu          = brackets.getModule(\"widgets/InlineMenu\").InlineMenu;\n\n    var template = JSON.parse(require(\"text!Templates.json\"));\n\n    var session = null;\n\n    /**\n     * Analyzes the code and finds values required for extract to function\n     * @param {!string} text - text to be extracted\n     * @param {!Array.<Scope>} - scopes\n     * @param {!Scope} srcScope - source scope of the extraction\n     * @param {!Scope} destScope - destination scope of the extraction\n     * @param {!number} start - the start offset\n     * @param {!number} end - the end offset\n     * @return {!{\n     *          passParams: Array.<string>,\n     *          retParams: Array.<string>,\n     *          thisPointerUsed: boolean,\n     *          varaibleDeclarations: {} // variable-name: kind\n     * }}\n     */\n    function analyzeCode(text, scopes, srcScope, destScope, start, end) {\n        var identifiers          = {},\n            inThisScope          = {},\n            thisPointerUsed      = false,\n            returnStatementUsed  = false,\n            variableDeclarations = {},\n            changedValues        = {},\n            dependentValues      = {},\n            ast                  = RefactoringUtils.getAST(text),\n            doc                  = session.editor.document,\n            restScopeStr;\n\n        ASTWalker.full(ast, function(node) {\n            var value, name;\n            switch (node.type) {\n                case \"AssignmentExpression\":\n                    value = node.left;\n                    break;\n                case \"VariableDeclarator\":\n                    inThisScope[node.id.name] = true;\n                    value = node.init && node.id;\n                    var variableDeclarationNode = RefactoringUtils.findSurroundASTNode(ast, node, [\"VariableDeclaration\"]);\n                    variableDeclarations[node.id.name] = variableDeclarationNode.kind;\n                    break;\n                case \"ThisExpression\":\n                    thisPointerUsed = true;\n                    break;\n                case \"UpdateExpression\":\n                    value = node.argument;\n                    break;\n                case \"Identifier\":\n                    identifiers[node.name] = true;\n                    break;\n                case \"ReturnStatement\":\n                    returnStatementUsed = true;\n                    break;\n            }\n            if (value){\n                if (value.type === \"MemberExpression\") {\n                    name = value.object.name;\n                } else {\n                    name = value.name;\n                }\n                changedValues[name] = true;\n            }\n        });\n\n        if (srcScope.originNode) {\n            restScopeStr = doc.getText().substr(end, srcScope.originNode.end - end);\n        } else {\n            restScopeStr = doc.getText().substr(end);\n        }\n\n        ASTWalker.simple(RefactoringUtils.getAST(restScopeStr), {\n            Identifier: function(node) {\n                var name = node.name;\n                dependentValues[name] = true;\n            },\n            Expression: function(node) {\n                if (node.type === \"MemberExpression\") {\n                    var name = node.object.name;\n                    dependentValues[name] = true;\n                }\n            }\n        });\n\n        var passProps = scopes.slice(srcScope.id, destScope.id).reduce(function(props, scope) {\n            return _.union(props, _.keys(scope.props));\n        }, []);\n\n        var retProps = scopes.slice(srcScope.id, destScope.id + 1).reduce(function(props, scope) {\n            return _.union(props, _.keys(scope.props));\n        }, []);\n\n        return {\n            passParams:           _.intersection(_.difference(_.keys(identifiers), _.keys(inThisScope)), passProps),\n            retParams:            _.intersection( _.keys(changedValues), _.keys(dependentValues), retProps),\n            thisPointerUsed:      thisPointerUsed,\n            returnStatementUsed:  returnStatementUsed,\n            variableDeclarations: variableDeclarations\n        };\n    }\n\n    /**\n     * Does the actual extraction. i.e Replacing the text, Creating a function\n     * and multi select function names\n     */\n    function extract(ast, text, scopes, srcScope, destScope, start, end, isExpression) {\n        var retObj               = analyzeCode(text, scopes, srcScope, destScope, start, end),\n            passParams           = retObj.passParams,\n            retParams            = retObj.retParams,\n            thisPointerUsed      = retObj.thisPointerUsed,\n            returnStatementUsed  = retObj.returnStatementUsed,\n            variableDeclarations = retObj.variableDeclarations,\n            doc                  = session.editor.document,\n            fnBody               = text,\n            fnName               = RefactoringUtils.getUniqueIdentifierName(scopes, \"extracted\"),\n            fnDeclaration,\n            fnCall;\n\n        function appendVarDeclaration(identifier) {\n            if (variableDeclarations.hasOwnProperty(identifier)) {\n                 return variableDeclarations[identifier] + \" \" + identifier;\n            }\n            else {\n                 return identifier;\n            }\n        }\n\n        if (destScope.isClass) {\n            fnCall = StringUtils.format(template.functionCall.class, fnName, passParams.join(\", \"));\n        } else if (thisPointerUsed) {\n            passParams.unshift(\"this\");\n            fnCall = StringUtils.format(template.functionCall.thisPointer, fnName, passParams.join(\", \"));\n            passParams.shift();\n        } else {\n            fnCall = StringUtils.format(template.functionCall.normal, fnName, passParams.join(\", \"));\n        }\n\n        // Append return to the fnCall, if the extracted text contains return statement\n        // Ideally in this case retParams should be empty.\n        if (returnStatementUsed) {\n            fnCall = \"return \" + fnCall;\n        }\n\n        if (isExpression) {\n            fnBody = StringUtils.format(template.returnStatement.single, fnBody);\n        } else {\n\n            var retParamsStr = \"\";\n            if (retParams.length > 1) {\n                retParamsStr = StringUtils.format(template.returnStatement.multiple, retParams.join(\", \"));\n                fnCall = \"var ret = \" + fnCall + \";\\n\";\n                fnCall += retParams.map(function (param) {\n                    return StringUtils.format(template.assignment, appendVarDeclaration(param),  \"ret.\" + param);\n                }).join(\"\\n\");\n            } else if (retParams.length === 1) {\n                retParamsStr = StringUtils.format(template.returnStatement.single, retParams.join(\", \"));\n                fnCall = StringUtils.format(template.assignment, appendVarDeclaration(retParams[0]), fnCall);\n            } else {\n                fnCall += \";\";\n            }\n\n            fnBody = fnBody + \"\\n\" + retParamsStr;\n        }\n\n        if (destScope.isClass) {\n            fnDeclaration = StringUtils.format(template.functionDeclaration.class, fnName, passParams.join(\", \"), fnBody);\n        } else {\n            fnDeclaration = StringUtils.format(template.functionDeclaration.normal, fnName, passParams.join(\", \"), fnBody);\n        }\n\n        start = session.editor.posFromIndex(start);\n        end   = session.editor.posFromIndex(end);\n\n        // Get the insertion pos for function declaration\n        var insertPos = _.clone(start);\n        var fnScopes = scopes.filter(RefactoringUtils.isFnScope);\n\n        for (var i = 0; i < fnScopes.length; ++i) {\n            if (fnScopes[i].id === destScope.id) {\n                if (fnScopes[i - 1]) {\n                     insertPos = session.editor.posFromIndex(fnScopes[i - 1].originNode.start);\n                     // If the origin node of the destination scope is a function expression or a arrow function expression,\n                     // get the surrounding statement to get the position\n                     if (fnScopes[i - 1].originNode.type === \"FunctionExpression\" || fnScopes[i - 1].originNode.type === \"ArrowFunctionExpression\") {\n                         var surroundStatement = RefactoringUtils.findSurroundASTNode(ast, { start: session.editor.indexFromPos(insertPos)}, [\"Statement\"]);\n                         insertPos = session.editor.posFromIndex(surroundStatement.start);\n                     }\n                }\n                break;\n            }\n        }\n\n        insertPos.ch = 0;\n\n        // Replace and multi-select and indent\n        doc.batchOperation(function() {\n            // Replace\n            doc.replaceRange(fnCall, start, end);\n            doc.replaceRange(fnDeclaration, insertPos);\n\n            // Set selections\n            start = doc.adjustPosForChange(start, fnDeclaration.split(\"\\n\"), insertPos, insertPos);\n            end   = doc.adjustPosForChange(end, fnDeclaration.split(\"\\n\"), insertPos, insertPos);\n\n            session.editor.setSelections([\n                {\n                    start: session.editor.posFromIndex(session.editor.indexFromPos(start) + fnCall.indexOf(fnName)),\n                    end:   session.editor.posFromIndex(session.editor.indexFromPos(start) + fnCall.indexOf(fnName) + fnName.length)\n                },\n                {\n                    start: session.editor.posFromIndex(session.editor.indexFromPos(insertPos) + fnDeclaration.indexOf(fnName)),\n                    end:   session.editor.posFromIndex(session.editor.indexFromPos(insertPos) + fnDeclaration.indexOf(fnName) + fnName.length)\n                }\n            ]);\n\n            // indent\n            for (var i = start.line; i < start.line + RefactoringUtils.numLines(fnCall); ++i) {\n                session.editor._codeMirror.indentLine(i, \"smart\");\n            }\n            for (var i = insertPos.line; i < insertPos.line + RefactoringUtils.numLines(fnDeclaration); ++i) {\n                session.editor._codeMirror.indentLine(i, \"smart\");\n            }\n        });\n    }\n\n    /**\n     * Main function that handles extract to function\n     */\n    function handleExtractToFunction() {\n        var editor = EditorManager.getActiveEditor();\n        var result = new $.Deferred(); // used only for testing purpose\n\n        if (editor.getSelections().length > 1) {\n            editor.displayErrorMessageAtCursor(Strings.ERROR_EXTRACTTO_FUNCTION_MULTICURSORS);\n            result.resolve(Strings.ERROR_EXTRACTTO_FUNCTION_MULTICURSORS);\n            return;\n        }\n        initializeSession(editor);\n\n        var selection = editor.getSelection(),\n            doc       = editor.document,\n            retObj    = RefactoringUtils.normalizeText(editor.getSelectedText(), editor.indexFromPos(selection.start), editor.indexFromPos(selection.end)),\n            text      = retObj.text,\n            start     = retObj.start,\n            end       = retObj.end,\n            ast,\n            scopes,\n            expns,\n            inlineMenu;\n\n        RefactoringUtils.getScopeData(session, editor.posFromIndex(start)).done(function(scope) {\n            ast = RefactoringUtils.getAST(doc.getText());\n\n            var isExpression = false;\n            if (!RefactoringUtils.checkStatement(ast, start, end, doc.getText())) {\n                isExpression = RefactoringUtils.getExpression(ast, start, end, doc.getText());\n                if (!isExpression) {\n                    editor.displayErrorMessageAtCursor(Strings.ERROR_EXTRACTTO_FUNCTION_NOT_VALID);\n                    result.resolve(Strings.ERROR_EXTRACTTO_FUNCTION_NOT_VALID);\n                    return;\n                }\n            }\n            scopes = RefactoringUtils.getAllScopes(ast, scope, doc.getText());\n\n            // if only one scope, extract without menu\n            if (scopes.length === 1) {\n                extract(ast, text, scopes, scopes[0], scopes[0], start, end, isExpression);\n                result.resolve();\n                return;\n            }\n\n            inlineMenu = new InlineMenu(editor, Strings.EXTRACTTO_FUNCTION_SELECT_SCOPE);\n\n            inlineMenu.open(scopes.filter(RefactoringUtils.isFnScope));\n\n            result.resolve(inlineMenu);\n\n            inlineMenu.onSelect(function (scopeId) {\n                extract(ast, text, scopes, scopes[0], scopes[scopeId], start, end, isExpression);\n                inlineMenu.close();\n            });\n\n            inlineMenu.onClose(function(){\n                inlineMenu.close();\n            });\n        }).fail(function() {\n            editor.displayErrorMessageAtCursor(Strings.ERROR_TERN_FAILED);\n            result.resolve(Strings.ERROR_TERN_FAILED);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Creates a new session from editor and stores it in session global variable\n     */\n    function initializeSession(editor) {\n        session = new Session(editor);\n    }\n\n    exports.handleExtractToFunction = handleExtractToFunction;\n});"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/ExtractToVariable.js",
    "content": "/*\n* Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining a\n* copy of this software and associated documentation files (the \"Software\"),\n* to deal in the Software without restriction, including without limitation\n* the rights to use, copy, modify, merge, publish, distribute, sublicense,\n* and/or sell copies of the Software, and to permit persons to whom the\n* Software is furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n* DEALINGS IN THE SOFTWARE.\n*\n*/\n\ndefine(function(require, exports, module) {\n    'use strict';\n\n    var ASTWalker           = brackets.getModule(\"thirdparty/acorn/dist/walk\"),\n        EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        Session             = brackets.getModule(\"JSUtils/Session\"),\n        RefactoringUtils    = require(\"RefactoringUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        InlineMenu          = brackets.getModule(\"widgets/InlineMenu\").InlineMenu;\n\n    var session = null;\n\n    /**\n     * Does the actual extraction. i.e Replacing the text, Creating a variable\n     * and multi select variable names\n     */\n    function extract(scopes, parentStatement, expns, text, insertPosition) {\n        var varType          = \"var\",\n            varName          = RefactoringUtils.getUniqueIdentifierName(scopes, \"extracted\"),\n            varDeclaration   = varType + \" \" + varName + \" = \" + text + \";\\n\",\n            parentStatementStartPos = session.editor.posFromIndex(parentStatement.start),\n            insertStartPos   = insertPosition || parentStatementStartPos,\n            selections       = [],\n            doc              = session.editor.document,\n            replaceExpnIndex = 0,\n            posToIndent,\n            edits            = [];\n\n        // If parent statement is expression statement, then just append var declaration\n        // Ex: \"add(1, 2)\" will become \"var extracted = add(1, 2)\"\n        if (parentStatement.type === \"ExpressionStatement\" &&\n                RefactoringUtils.isEqual(parentStatement.expression, expns[0]) &&\n                insertStartPos.line === parentStatementStartPos.line &&\n                insertStartPos.ch === parentStatementStartPos.ch) {\n            varDeclaration = varType + \" \" + varName + \" = \";\n            replaceExpnIndex = 1;\n        }\n\n        posToIndent = doc.adjustPosForChange(insertStartPos, varDeclaration.split(\"\\n\"), insertStartPos, insertStartPos);\n\n        // adjust pos for change\n        for (var i = replaceExpnIndex; i < expns.length; ++i) {\n            expns[i].start  = session.editor.posFromIndex(expns[i].start);\n            expns[i].end    = session.editor.posFromIndex(expns[i].end);\n            expns[i].start  = doc.adjustPosForChange(expns[i].start, varDeclaration.split(\"\\n\"), insertStartPos, insertStartPos);\n            expns[i].end    = doc.adjustPosForChange(expns[i].end, varDeclaration.split(\"\\n\"), insertStartPos, insertStartPos);\n\n            edits.push({\n                edit: {\n                    text: varName,\n                    start: expns[i].start,\n                    end: expns[i].end\n                },\n                selection: {\n                    start: expns[i].start,\n                    end: {line: expns[i].start.line, ch: expns[i].start.ch + varName.length}\n                }\n            });\n        }\n\n        // Replace and multi-select\n        doc.batchOperation(function() {\n            doc.replaceRange(varDeclaration, insertStartPos);\n\n            selections = doc.doMultipleEdits(edits);\n            selections.push({\n                start: {line: insertStartPos.line, ch: insertStartPos.ch + varType.length + 1},\n                end:   {line: insertStartPos.line, ch: insertStartPos.ch + varType.length + varName.length + 1},\n                primary: true\n            });\n            session.editor.setSelections(selections);\n            session.editor._codeMirror.indentLine(posToIndent.line, \"smart\");\n        });\n    }\n\n    /**\n     * Find all expressions in the parentBlockStatement that are same as expn\n     * @param {!ASTNode} parentBlockStatement\n     * @param {!ASTNode} expn\n     * @param {!string} text - text of the expression\n     * @return {!Array.<ASTNode>}\n     */\n    function findAllExpressions(parentBlockStatement, expn, text) {\n        var doc   = session.editor.document,\n            obj   = {},\n            expns = [];\n\n        // find all references of the expression\n        obj[expn.type] = function(node) {\n            if (text === doc.getText().substr(node.start, node.end - node.start)) {\n                expns.push(node);\n            }\n        };\n        ASTWalker.simple(parentBlockStatement, obj);\n\n        return expns;\n    }\n\n    /**\n     * Gets the surrounding expressions of start and end offset\n     * @param {!ASTNode} ast - the ast of the complete file\n     * @param {!number} start - the start offset\n     * @param {!number} end - the end offset\n     * @return {!Array.<ASTNode>}\n     */\n    function getExpressions(ast, start, end) {\n        var expns = [],\n            s     = start,\n            e     = end,\n            expn;\n\n        while (true) {\n            expn = RefactoringUtils.findSurroundExpression(ast, {start: s, end: e});\n            if (!expn) {\n                break;\n            }\n            expns.push(expn);\n            s = expn.start - 1;\n        }\n\n        s = start;\n        e = end;\n\n        function checkExpnEquality(e) {\n            return e.start === expn.start && e.end === expn.end;\n        }\n\n        while (true) {\n            expn = RefactoringUtils.findSurroundExpression(ast, {start: s, end: e});\n            if (!expn) {\n                break;\n            }\n            e = expn.end + 1;\n\n            // if expn already added, continue\n            if (expns.find(checkExpnEquality)) {\n                 continue;\n            }\n\n            expns.push(expn);\n        }\n\n        return expns;\n    }\n\n    /**\n     * Creates params needed for extraction and calls extract\n     * extract() does the actual extraction\n     */\n    function extractToVariable(ast, start, end, text, scopes) {\n        var doc                   = session.editor.document,\n            editor = EditorManager.getActiveEditor(),\n            parentExpn            = RefactoringUtils.getExpression(ast, start, end, doc.getText()),\n            expns                 = [],\n            parentBlockStatement,\n            parentStatement;\n\n        if (!parentExpn) {\n            session.editor.displayErrorMessageAtCursor(Strings.ERROR_EXTRACTTO_VARIABLE_NOT_VALID);\n            return;\n        }\n\n        // Find all expressions only if selected expn is not a subexpression\n        // In case of subexpressions, ast cannot be used to find all expressions\n        if (doc.getText().substr(parentExpn.start, parentExpn.end - parentExpn.start) === text) {\n            parentBlockStatement = RefactoringUtils.findSurroundASTNode(ast, parentExpn, [\"BlockStatement\", \"Program\"]);\n            expns                = findAllExpressions(parentBlockStatement, parentExpn, text);\n\n            RefactoringUtils.getScopeData(session, editor.posFromIndex(expns[0].start)).done(function(scope) {\n                var firstExpnsScopes = RefactoringUtils.getAllScopes(ast, scope, doc.getText()),\n                    insertPostion;\n                parentStatement = RefactoringUtils.findSurroundASTNode(ast, expns[0], [\"Statement\"]);\n                if (scopes.length < firstExpnsScopes.length) {\n                    var parentScope;\n                    if (expns[0].body && expns[0].body.type === \"BlockStatement\") {\n                        parentScope = firstExpnsScopes[firstExpnsScopes.length - scopes.length];\n                    } else {\n                        parentScope = firstExpnsScopes[firstExpnsScopes.length - scopes.length - 1];\n                    }\n\n                    var insertNode = RefactoringUtils.findSurroundASTNode(ast, parentScope.originNode, [\"Statement\"]);\n                    if (insertNode) {\n                        insertPostion = session.editor.posFromIndex(insertNode.start);\n                    }\n                }\n                extract(scopes, parentStatement, expns, text, insertPostion);\n            });\n        } else {\n            parentStatement = RefactoringUtils.findSurroundASTNode(ast, parentExpn, [\"Statement\"]);\n            extract(scopes, parentStatement, [{ start: start, end: end }], text);\n        }\n    }\n\n\n    /**\n     * Main function that handles extract to variable\n     */\n    function handleExtractToVariable() {\n        var editor = EditorManager.getActiveEditor();\n\n        if (editor.getSelections().length > 1) {\n            editor.displayErrorMessageAtCursor(Strings.ERROR_EXTRACTTO_VARIABLE_MULTICURSORS);\n            return;\n        }\n\n        initializeSession(editor);\n\n        var selection = editor.getSelection(),\n            doc       = editor.document,\n            retObj    = RefactoringUtils.normalizeText(editor.getSelectedText(), editor.indexFromPos(selection.start),\n                        editor.indexFromPos(selection.end), true),\n            text      = retObj.text,\n            start     = retObj.start,\n            end       = retObj.end,\n            ast,\n            scopes,\n            expns,\n            inlineMenu;\n\n        function callExtractToVariable(startPos, endPos, value) {\n            RefactoringUtils.getScopeData(session, editor.posFromIndex(startPos))\n                .done(function(expnscope) {\n                    scopes = RefactoringUtils.getAllScopes(ast, expnscope, doc.getText());\n                    extractToVariable(ast, startPos, endPos, value, scopes);\n                }).fail(function() {\n                    editor.displayErrorMessageAtCursor(Strings.ERROR_TERN_FAILED);\n                });\n        }\n\n        RefactoringUtils.getScopeData(session, editor.posFromIndex(start)).done(function(scope) {\n            ast = RefactoringUtils.getAST(doc.getText());\n            scopes = RefactoringUtils.getAllScopes(ast, scope, doc.getText());\n\n            if (editor.hasSelection()) {\n                extractToVariable(ast, start, end, text, scopes);\n            } else {\n                expns = getExpressions(ast, start, end);\n\n                expns.forEach(function(expn, index) {\n                    expn.value = doc.getText().substr(expn.start, expn.end - expn.start);\n                });\n\n                // Sort expressions by their length\n                expns.sort(function(a, b) {\n                    return a.value.length - b.value.length;\n                });\n\n                if (!expns || !expns.length) {\n                    session.editor.displayErrorMessageAtCursor(Strings.ERROR_EXTRACTTO_VARIABLE_NOT_VALID);\n                    return;\n                }\n\n                // Filter expns based on length of first surrounding expression\n                var firstExpnLength = RefactoringUtils.numLines(expns[0].value);\n                expns = expns.filter(function(expn) {\n                    return RefactoringUtils.numLines(expn.value) === firstExpnLength;\n                });\n\n                // Add name for the expression based on its value\n                expns.forEach(function(expn, index) {\n                    // If expn name is multi-line, display only first line\n                    if (RefactoringUtils.numLines(expn.value) > 1) {\n                        expn.name = expn.value.substr(0, expn.value.indexOf(\"\\n\")) + \"...\";\n                    } else {\n                        expn.name = expn.value;\n                    }\n                });\n\n                // If only one surround expression, extract\n                if (expns.length === 1) {\n                    callExtractToVariable(expns[0].start, expns[0].end, expns[0].value);\n                    return;\n                }\n\n                expns.forEach(function(expn, index) {\n                    expn.id = index;\n                });\n\n                // UI for extract to variable\n                inlineMenu = new InlineMenu(session.editor, Strings.EXTRACTTO_VARIABLE_SELECT_EXPRESSION);\n\n                inlineMenu.onHover(function (expnId) {\n                    // Remove the scroll Handlers If already Attached.\n                    editor.off(\"scroll.inlinemenu\");\n                    // Add a scroll handler If Selection Range is not View.\n                    // This is Added for a Bug, where Menu used not to open for the first Time\n                    if(!editor.isLineVisible(editor.posFromIndex(expns[expnId].end).line)) {\n                        editor.on(\"scroll.inlinemenu\", function() {\n                            // Remove the Handlers so that If scroll event is triggerd again by any other operation\n                            // Menu should not be reopened.\n                            // Menu Should be reopened only if Scroll event is triggered by onHover.\n                            editor.off(\"scroll.inlinemenu\");\n                            inlineMenu.openRemovedMenu();\n                        });\n                    }\n                    editor.setSelection(editor.posFromIndex(expns[expnId].start), editor.posFromIndex(expns[expnId].end));\n                });\n\n                inlineMenu.open(expns);\n\n                inlineMenu.onSelect(function (expnId) {\n                    callExtractToVariable(expns[expnId].start, expns[expnId].end, expns[expnId].value);\n                    inlineMenu.close();\n                });\n\n                inlineMenu.onClose(function () {\n                    inlineMenu.close();\n                });\n            }\n        }).fail(function() {\n            editor.displayErrorMessageAtCursor(Strings.ERROR_TERN_FAILED);\n        });\n    }\n\n    /**\n     * Creates a new session from editor and stores it in session global variable\n     */\n    function initializeSession(editor) {\n        session = new Session(editor);\n    }\n\n    exports.handleExtractToVariable = handleExtractToVariable;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/RefactoringUtils.js",
    "content": "/*\n* Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining a\n* copy of this software and associated documentation files (the \"Software\"),\n* to deal in the Software without restriction, including without limitation\n* the rights to use, copy, modify, merge, publish, distribute, sublicense,\n* and/or sell copies of the Software, and to permit persons to whom the\n* Software is furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n* DEALINGS IN THE SOFTWARE.\n*\n*/\n\n/*\n * Utilities functions related to refactoring\n */\ndefine(function (require, exports, module) {\n    'use strict';\n\n    var Acorn         = brackets.getModule(\"thirdparty/acorn/dist/acorn\"),\n        ASTWalker     = brackets.getModule(\"thirdparty/acorn/dist/walk\"),\n        MessageIds    = brackets.getModule(\"JSUtils/MessageIds\"),\n        _             = brackets.getModule(\"thirdparty/lodash\"),\n        AcornLoose    = brackets.getModule(\"thirdparty/acorn/dist/acorn_loose\"),\n        ScopeManager  = brackets.getModule(\"JSUtils/ScopeManager\");\n\n\n    var templates = JSON.parse(require(\"text!Templates.json\"));\n\n\n\n    // Length of the function body used as function name for nameless functions\n    var FUNCTION_BODY_PREFIX_LENGTH = 30;\n\n    /**\n     * Checks whether two ast nodes are equal\n     * @param {!ASTNode} a\n     * @param {!ASTNode} b\n     * @return {boolean}\n     */\n    function isEqual(a, b) {\n        return a.start === b.start && a.end === b.end;\n    }\n\n    /**\n     * Gets a expression surrounding start and end (if any)\n     * @param {!ASTNode} ast - the ast of the complete file\n     * @param {!number} start - the start offset\n     * @param {!number} end - the end offset\n     * @param {!string} fileText - the entire file text\n     * @return {ASTNode|boolean}\n     */\n    function getExpression(ast, start, end, fileText) {\n        var expn = findSurroundExpression(ast, {start: start, end: end});\n        if (!expn) {\n             return false;\n        }\n\n        // Class Expression also includes the trailing semicolon\n        // Add special case for it\n        if (expn.type === \"ClassExpression\" && expn.start === start && expn.end - end <= 1) {\n            expn.end = end;\n            return expn;\n        }\n        else if (expn.start === start && expn.end === end) {\n            return expn;\n        }\n\n        // Subexpressions are possible only for BinaryExpression, LogicalExpression and SequenceExpression\n        if (!([\"BinaryExpression\", \"LogicalExpression\", \"SequenceExpression\"].includes(expn.type))) {\n            return false;\n        }\n\n        // Check subexpression\n        var parentExpn = expn;\n        var parentExpStr = fileText.substr(parentExpn.start, parentExpn.end - parentExpn.start);\n\n        // Check whether the parentExpn forms a valid expression after replacing the sub expression\n        var str = parentExpStr.substr(0, start - parentExpn.start) + \"placeHolder\" + parentExpStr.substr(end - parentExpn.start);\n        var node = isStandAloneExpression(str);\n        if (node && node.type === parentExpn.type) {\n            return parentExpn;\n        }\n\n        return false;\n    }\n\n    function getAST(text) {\n        var ast;\n        try {\n            ast = Acorn.parse(text, {ecmaVersion: 9});\n        } catch(e) {\n            ast = Acorn.parse_dammit(text, {ecmaVersion: 9});\n        }\n        return ast;\n    }\n\n    /*\n     * Checks whether the text between start and end offsets form a valid set of statements\n     * @param {!ASTNode} ast - the ast of the complete file\n     * @param {!number} start - the start offset\n     * @param {!number} end - the end offset\n     * @param {!string} fileText - the entire file text\n     * @return {boolean}\n     */\n    function checkStatement(ast, start, end, fileText) {\n        // Do not allow function or class nodes\n        var notStatement = false;\n        ASTWalker.simple(getAST(fileText.substr(start, end - start)), {\n            FunctionDeclaration: function (node) {\n                notStatement = true;\n            },\n            ClassDeclaration: function (node) {\n                notStatement = true;\n            }\n        });\n\n        if (notStatement) {\n             return false;\n        }\n\n        var startStatement = findSurroundASTNode(ast, {start: start}, [\"Statement\"]);\n        var endStatement   = findSurroundASTNode(ast, {start: end}, [\"Statement\"]);\n\n        return startStatement && endStatement && startStatement.start === start &&\n            startStatement.end <= end && endStatement.start >= start &&\n            endStatement.end === end;\n    }\n\n    /**\n     * Gets a unique identifier name in the scope that starts with prefix\n     * @param {!Scope} scopes - an array of all scopes returned from tern (each element contains 'props' with identifiers\n     *  in that scope)\n     * @param {!string} prefix - prefix of the identifier\n     * @param {number} num - number to start checking for\n     * @return {!string} identifier name\n     */\n    function getUniqueIdentifierName(scopes, prefix, num) {\n        if (!scopes) {\n            return prefix;\n        }\n\n        var props = scopes.reduce(function(props, scope) {\n            return _.union(props, _.keys(scope.props));\n        }, []);\n\n        if (!props) {\n            return prefix;\n        }\n\n        num = num || \"1\";\n        var name;\n        while (num < 100) { // limit search length\n            name = prefix + num;\n            if (props.indexOf(name) === -1) {\n                break;\n            }\n            ++num;\n        }\n        return name;\n    }\n\n    /**\n     * Returns the no of lines in the text\n     * @param {!string} text\n     * @return {number}\n     */\n    function numLines(text) {\n        return text.split(\"\\n\").length;\n    }\n\n    /**\n     * Checks whether the text forms a stand alone expression without considering the context of text\n     * @param {!string} text\n     * @return {boolean}\n     */\n    function isStandAloneExpression(text) {\n        var found = ASTWalker.findNodeAt(getAST(text), 0, text.length, function (nodeType, node) {\n            if (nodeType === \"Expression\") {\n                return true;\n            }\n            return false;\n        });\n        return found && found.node;\n    }\n\n    /**\n     * Requests scope data from tern\n     * @param {!Session} session\n     * @param {!{line: number, ch: number}} offset\n     * @return {!$.Promise} a jQuery promise that will be resolved with the scope data\n     */\n    function getScopeData(session, offset) {\n        var path = session.path,\n            fileInfo = {\n                type: MessageIds.TERN_FILE_INFO_TYPE_FULL,\n                name: path,\n                offsetLines: 0,\n                text: ScopeManager.filterText(session.getJavascriptText())\n            };\n\n        ScopeManager.postMessage({\n            type: MessageIds.TERN_SCOPEDATA_MSG,\n            fileInfo: fileInfo,\n            offset: offset\n        });\n\n        var ternPromise = ScopeManager.addPendingRequest(fileInfo.name, offset, MessageIds.TERN_SCOPEDATA_MSG);\n\n        var result = new $.Deferred();\n\n        ternPromise.done(function (response) {\n            result.resolveWith(null, [response.scope]);\n        }).fail(function () {\n            result.reject();\n        });\n\n        return result;\n    }\n\n    /**\n    * Normalize text by removing leading and trailing whitespace characters\n    * and moves the start and end offset to reflect the new offset\n    * @param {!string} text - selected text\n    * @param {!number} start - the start offset of the text\n    * @param {!number} end - the end offset of the text\n    * @param {!boolean} removeTrailingSemiColons - removes trailing semicolons also if true\n    * @return {!{text: string, start: number, end: number}}\n    */\n    function normalizeText(text, start, end, removeTrailingSemiColons) {\n        var trimmedText;\n\n        // Remove leading spaces\n        trimmedText = _.trimLeft(text);\n\n        if (trimmedText.length < text.length) {\n            start += (text.length - trimmedText.length);\n        }\n\n        text = trimmedText;\n\n        // Remove trailing spaces\n        trimmedText = _.trimRight(text);\n\n        if (trimmedText.length < text.length) {\n            end -= (text.length - trimmedText.length);\n        }\n\n        text = trimmedText;\n\n        // Remove trailing semicolons\n        if (removeTrailingSemiColons) {\n            trimmedText = _.trimRight(text, ';');\n\n            if (trimmedText.length < text.length) {\n                end -= (text.length - trimmedText.length);\n            }\n        }\n\n        return {\n            text: trimmedText,\n            start: start,\n            end: end\n        };\n    }\n\n    /**\n     * Checks whether the scope is a function scope\n     */\n    function isFnScope(scope) {\n        return !scope.isBlock && !scope.isCatch;\n    }\n\n    function findSurroundExpression(ast, expn) {\n        var start = expn.start;\n        var end = expn.end;\n        var surroundExpn;\n\n        while (true) {\n            surroundExpn = findSurroundASTNode(ast, {start: start, end: end}, [\"Expression\"]);\n\n            if (!surroundExpn) {\n                return null;\n            }\n\n            // Do not allow sequence expressions\n            if (surroundExpn.type === \"SequenceExpression\") {\n                start = surroundExpn.start - 1;\n            }\n            else if (surroundExpn.type === \"FunctionExpression\") { // Do not allow method definition expressions\n                var methodDefinitionNode = findSurroundASTNode(ast, surroundExpn, [\"MethodDefinition\"]);\n                if (methodDefinitionNode && isEqual(methodDefinitionNode.value, surroundExpn)) {\n                    start = surroundExpn.start - 1;\n                } else {\n                    return surroundExpn;\n                }\n            } else {\n                return surroundExpn;\n            }\n        }\n\n        return surroundExpn;\n    }\n\n    /**\n     * Finds the surrounding ast node of the given expression of any of the given types\n     * @param {!ASTNode} ast\n     * @param {!{start: number, end: number}} expn - contains start and end offsets of expn\n     * @param {!Array.<string>} types\n     * @return {?ASTNode}\n     */\n    function findSurroundASTNode(ast, expn, types) {\n        var foundNode = ASTWalker.findNodeAround(ast, expn.start, function (nodeType, node) {\n            if (expn.end) {\n                return types.includes(nodeType) && node.end >= expn.end;\n            } else {\n                return types.includes(nodeType);\n            }\n        });\n        return foundNode && _.clone(foundNode.node);\n    }\n\n    /**\n     * Converts the scopes returned from tern to an array of scopes and adds id and name to the scope\n     * Also checks for class scopes\n     * @param {!ASTNode} ast - ast of the complete file\n     * @param {!Scope} scope - scope returned from tern\n     * @param {!string} fullText - the complete text of a file\n     * @return {!Array.<Scope>}\n     */\n    function getAllScopes(ast, scope, fullText) {\n        var curScope = scope;\n        var cnt = 0;\n        var scopes = [];\n\n        while (curScope) {\n            curScope.id = cnt++;\n            scopes.push(curScope);\n\n            if (curScope.fnType) {\n                // Check for class scopes surrounding the function\n                if (curScope.fnType === \"FunctionExpression\") {\n                    var methodDefinitionNode = findSurroundASTNode(ast, curScope.originNode, [\"MethodDefinition\"]);\n                    // class scope found\n                    if (methodDefinitionNode && isEqual(methodDefinitionNode.value, curScope.originNode)) {\n                        // Change curScope name and originNode to that of methodDefinitionNode\n                        curScope.name = methodDefinitionNode.key.name;\n                        curScope.originNode = methodDefinitionNode;\n\n                        var classNode = findSurroundASTNode(ast, methodDefinitionNode, [\"ClassDeclaration\", \"ClassExpression\"]);\n\n                        if (classNode) {\n                            // Class Declaration found add it to scopes\n                            var temp = curScope.prev;\n                            var newScope = {};\n                            newScope.isClass = true;\n\n                            // if the class is class expression, check if it has a name\n                            if (classNode.type === \"ClassExpression\") {\n                                var assignmentExpNode = findSurroundASTNode(ast, classNode, [\"AssignmentExpression\"]);\n                                if (assignmentExpNode && assignmentExpNode.left && assignmentExpNode.left.name) {\n                                    newScope.name = \"class \" + assignmentExpNode.left.name;\n                                } else {\n                                    var varDeclaratorNode = findSurroundASTNode(ast, classNode, [\"VariableDeclarator\"]);\n                                    if (varDeclaratorNode && varDeclaratorNode.id && varDeclaratorNode.id.name) {\n                                        newScope.name = \"class \" + varDeclaratorNode.id.name;\n                                    } else {\n                                        newScope.name = \"class null\";\n                                    }\n                                }\n                            } else {\n                                newScope.name = \"class \" + (classNode.id && classNode.id.name);\n                            }\n                            newScope.originNode = classNode;\n                            curScope.prev = newScope;\n                            newScope.prev = temp;\n                        }\n                    } else {\n                        // For function expressions, assign name to prefix of the function body\n                        curScope.name = \"function starting with \" +\n                            fullText.substr(\n                                curScope.originNode.body.start,\n                                Math.min(\n                                    FUNCTION_BODY_PREFIX_LENGTH,\n                                    curScope.originNode.body.end - curScope.originNode.body.start\n                                )\n                            );\n                    }\n                } else {\n                    // Acorn parse_dammit marks name with '✖' under erroneous declarations, check it\n                    if (curScope.fnType === \"✖\") {\n                        curScope.name = \"function starting with \" +\n                            fullText.substr(\n                                curScope.originNode.body.start,\n                                Math.min(\n                                    FUNCTION_BODY_PREFIX_LENGTH,\n                                    curScope.originNode.body.end - curScope.originNode.body.start\n                                )\n                            );\n                    } else {\n                        curScope.name = curScope.fnType;\n                    }\n                }\n            } else if (!curScope.originNode) {\n                curScope.name = \"global\";\n            }\n\n            curScope = curScope.prev;\n        }\n        return scopes;\n    }\n\n    /**\n     * Note - To use these state defined in Refactoring Session,\n     * Please reinitialize this RefactoringSession after performing any of the below operations\n     * (i.e. replaceRange, setSelection or indentLine) \n     * \n     * RefactoringSession objects encapsulate state associated with a refactoring session\n     * and This will help finding information around documents, selection,\n     * position, ast, and queries around AST nodes\n     *\n     * @constructor\n     * @param {Editor} editor - the editor context for the session\n     */\n    function RefactoringSession(editor) {\n        this.editor = editor;\n        this.document = editor.document;\n        this.selection = editor.getSelection();\n        this.text = this.document.getText();\n        this.selectedText = editor.getSelectedText();\n        this.cm = editor._codeMirror;\n        this.startIndex = editor.indexFromPos(this.selection.start);\n        this.endIndex = editor.indexFromPos(this.selection.end);\n        this.startPos = this.selection.start;\n        this.endPos = this.selection.end;\n        this.ast = this.createAstOfCurrentDoc();\n    }\n\n    /**\n     * Get the end position of given line\n     *\n     * @param {number} line - line number\n     * @return {{line: number, ch: number}} - line end position\n     */\n    RefactoringSession.prototype.lineEndPosition = function (line) {\n        var lineText = this.document.getLine(line);\n\n        return {\n            line: line,\n            ch: lineText.length\n        };\n    };\n\n    /**\n     * Get the ast of current opened document in focused editor\n     *\n     * @return {Object} - Ast of current opened doc\n     */\n    RefactoringSession.prototype.createAstOfCurrentDoc = function () {\n        var ast,\n            text = this.document.getText();\n        try {\n            ast = Acorn.parse(text);\n        } catch(e) {\n            ast = Acorn.parse_dammit(text);\n        }\n        return ast;\n    };\n\n    /**\n     * This will add template at given position/selection\n     *\n     * @param {string} template - name of the template defined in templates.json\n     * @param {Array} args- Check all arguments that exist in defined templated pass all that args as array\n     * @param {{line: number, ch: number}} rangeToReplace - Range which we want to replace\n     * @param {string} subTemplate - If template written under some category\n     */\n    RefactoringSession.prototype.replaceTextFromTemplate = function (template, args, rangeToReplace, subTemplate) {\n        var templateText = templates[template];\n\n        if (subTemplate) {\n            templateText = templateText[subTemplate];\n        }\n\n        var compiled = _.template(templateText),\n            formattedText = compiled(args);\n\n        if (!rangeToReplace) {\n            rangeToReplace = this.editor.getSelection();\n        }\n\n        this.document.replaceRange(formattedText, rangeToReplace.start, rangeToReplace.end);\n\n        var startLine = rangeToReplace.start.line,\n            endLine = startLine + formattedText.split(\"\\n\").length;\n\n        for (var i = startLine + 1; i < endLine; i++) {\n            this.cm.indentLine(i);\n        }\n    };\n\n    /**\n     * Get Params of selected function\n     *\n     * @param {number} start- start offset\n     * @param {number} end - end offset\n     * @param {string} selectedText - Create ast for only selected node\n     * @return {Array} param - Array of all parameters in function\n     */\n    RefactoringSession.prototype.getParamsOfFunction = function getParamsOfFunction(start, end, selectedText) {\n        var param = [];\n        ASTWalker.simple(AcornLoose.parse_dammit(selectedText), {\n            Function: function (node) {\n                if (node.type === \"FunctionDeclaration\") {\n                    node.params.forEach(function (item) {\n                        param.push(item.name);\n                    });\n                }\n            }\n        });\n\n        return param;\n    };\n\n    /**\n     * Get the Parent node\n     *\n     * @param {Object} ast - ast of full document\n     * @param {number} start - start Offset\n     * @return {Object} node - Returns the parent node of node which is at offset start\n     */\n    RefactoringSession.prototype.getParentNode = function (ast, start) {\n        var foundNode = ASTWalker.findNodeAround(ast, start, function(nodeType, node) {\n            return (nodeType === \"ObjectExpression\");\n        });\n        return foundNode && foundNode.node;\n    };\n\n    /**\n     * Checks weather the node at start is last in that scope or not\n     *\n     * @param {Object} ast - ast of full document\n     * @param {number} start - start Offset\n     * @return {boolean} - is last node in that scope\n     */\n    RefactoringSession.prototype.isLastNodeInScope = function (ast, start) {\n        var parentNode = this.getParentNode(ast, start),\n            currentNodeStart;\n\n        ASTWalker.simple(parentNode, {\n            Property: function (node) {\n                currentNodeStart = node.start;\n            }\n        });\n\n        return start >= currentNodeStart;\n    };\n\n\n    // Define public api\n    exports.isEqual = isEqual;\n    exports.getUniqueIdentifierName = getUniqueIdentifierName;\n    exports.isStandAloneExpression = isStandAloneExpression;\n    exports.numLines = numLines;\n    exports.getScopeData = getScopeData;\n    exports.normalizeText = normalizeText;\n    exports.getExpression = getExpression;\n    exports.isFnScope = isFnScope;\n    exports.getAllScopes = getAllScopes;\n    exports.checkStatement = checkStatement;\n    exports.findSurroundASTNode = findSurroundASTNode;\n    exports.getAST = getAST;\n    exports.findSurroundExpression = findSurroundExpression;\n    exports.RefactoringSession = RefactoringSession;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/RenameIdentifier.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager        = brackets.getModule(\"editor/EditorManager\"),\n        ScopeManager         = brackets.getModule(\"JSUtils/ScopeManager\"),\n        Session              = brackets.getModule(\"JSUtils/Session\"),\n        MessageIds           = brackets.getModule(\"JSUtils/MessageIds\"),\n        TokenUtils           = brackets.getModule(\"utils/TokenUtils\"),\n        Strings              = brackets.getModule(\"strings\"),\n        ProjectManager      = brackets.getModule(\"project/ProjectManager\");\n\n    var session             = null,  // object that encapsulates the current session state\n        keywords = [\"define\", \"alert\", \"exports\", \"require\", \"module\", \"arguments\"];\n\n    //Create new session\n    function initializeSession(editor) {\n        session = new Session(editor);\n    }\n\n    //Post message to tern node domain that will request tern server to find refs\n    function getRefs(fileInfo, offset) {\n        ScopeManager.postMessage({\n            type: MessageIds.TERN_REFS,\n            fileInfo: fileInfo,\n            offset: offset\n        });\n\n        return ScopeManager.addPendingRequest(fileInfo.name, offset, MessageIds.TERN_REFS);\n    }\n\n    //Create info required to find reference\n    function requestFindRefs(session, document, offset) {\n        if (!document || !session) {\n            return;\n        }\n        var path    = document.file.fullPath,\n            fileInfo = {\n                type: MessageIds.TERN_FILE_INFO_TYPE_FULL,\n                name: path,\n                offsetLines: 0,\n                text: ScopeManager.filterText(session.getJavascriptText())\n            };\n        var ternPromise = getRefs(fileInfo, offset);\n\n        return {promise: ternPromise};\n    }\n\n    //Do rename of identifier which is at cursor\n    function handleRename() {\n        var editor = EditorManager.getActiveEditor(),\n            offset, handleFindRefs, token;\n\n        if (!editor) {\n            return;\n        }\n\n        if (editor.getSelections().length > 1) {\n            editor.displayErrorMessageAtCursor(Strings.ERROR_RENAME_MULTICURSOR);\n            return;\n        }\n        initializeSession(editor);\n\n\n        if (!editor || editor.getModeForSelection() !== \"javascript\") {\n            return;\n        }\n\n        token = TokenUtils.getTokenAt(editor._codeMirror, editor._codeMirror.posFromIndex(session.getOffset()));\n\n        if (keywords.indexOf(token.string) >= 0) {\n            editor.displayErrorMessageAtCursor(Strings.ERROR_RENAME_GENERAL);\n            return;\n        }\n\n        var result = new $.Deferred();\n\n        function isInSameFile(obj, refsResp) {\n            var projectRoot = ProjectManager.getProjectRoot(),\n                projectDir,\n                fileName = \"\";\n            if (projectRoot) {\n                projectDir = projectRoot.fullPath;\n            }\n\n            // get the relative path of File as Tern can also return\n            // references with file name as a relative path wrt projectRoot\n            // so refernce file name will be compared with both relative and absolute path to check if it is same file\n            if (projectDir && refsResp && refsResp.file && refsResp.file.indexOf(projectDir) === 0) {\n                fileName = refsResp.file.slice(projectDir.length);\n            }\n            // In case of unsaved files, After renameing once Tern is returning filename without forward slash\n            return (obj && (obj.file === refsResp.file || obj.file === fileName\n                            || obj.file === refsResp.file.slice(1, refsResp.file.length)));\n        }\n\n        /**\n         * Check if references are in this file only\n         * If yes then select all references\n         */\n        function handleFindRefs (refsResp) {\n            if (!refsResp || !refsResp.references || !refsResp.references.refs) {\n                return;\n            }\n\n            var inlineWidget = EditorManager.getFocusedInlineWidget(),\n                editor = EditorManager.getActiveEditor(),\n                refs = refsResp.references.refs,\n                type = refsResp.references.type;\n\n            //In case of inline widget if some references are outside widget's text range then don't allow for rename\n            if (inlineWidget) {\n                var isInTextRange  = !refs.find(function(item) {\n                    return (item.start.line < inlineWidget._startLine || item.end.line > inlineWidget._endLine);\n                });\n                \n                if (!isInTextRange) {\n                    editor.displayErrorMessageAtCursor(Strings.ERROR_RENAME_QUICKEDIT);\n                    return;\n                }\n            }\n\n            var currentPosition = editor.posFromIndex(refsResp.offset),\n                refsArray = refs;\n            if (type !== \"local\") {\n                refsArray = refs.filter(function (element) {\n                    return isInSameFile(element, refsResp);\n                });\n            }\n\n            // Finding the Primary Reference in Array\n            var primaryRef = refsArray.find(function (element) {\n                return ((element.start.line === currentPosition.line || element.end.line === currentPosition.line)\n                        && currentPosition.ch <= element.end.ch && currentPosition.ch >= element.start.ch);\n            });\n            // Setting the primary flag of Primary Refence to true\n            primaryRef.primary = true;\n\n            editor.setSelections(refsArray);\n        }\n\n        /**\n         * Make a find ref request.\n         * @param {Session} session - the session\n         * @param {number} offset - the offset of where to jump from\n         */\n        function requestFindReferences(session, offset) {\n            var response = requestFindRefs(session, session.editor.document, offset);\n\n            if (response && response.hasOwnProperty(\"promise\")) {\n                response.promise.done(handleFindRefs).fail(function () {\n                    result.reject();\n                });\n            }\n        }\n\n        offset = session.getOffset();\n        requestFindReferences(session, offset);\n\n        return result.promise();\n    }\n\n    exports.handleRename = handleRename;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/Templates.json",
    "content": "{\n    \"functionCall\": {\n        \"thisPointer\": \"{0}.call({1})\",\n        \"normal\": \"{0}({1})\",\n        \"class\": \"this.{0}({1})\"\n    },\n\n    \"functionDeclaration\": {\n        \"class\" : \"{0}({1}) {\\n {2}}\\n\\n\",\n        \"normal\": \"function {0}({1}) {\\n {2}}\\n\\n\"\n    },\n\n    \"returnStatement\": {\n        \"single\": \"return {0};\\n\",\n        \"multiple\": \"return {{0}};\\n\"\n    },\n\n    \"assignment\": \"{0} = {1};\",\n\n    \"wrapCondition\": \"if (Condition) {\\n${body}\\n}\",\n\n    \"arrowFunction\": {\n        \"oneParamOneStament\": \"${params} => ${statement}\",\n        \"oneParamManyStament\": \"${params} => \",\n        \"manyParamOneStament\": \"(${params}) => ${statement}\",\n        \"manyParamManyStament\": \"(${params}) => \"\n    },\n\n    \"tryCatch\": \"try {\\n${body}\\n} catch (e) {\\n\\/\\/Catch Statement\\n}\",\n\n    \"gettersSetters\": \"\\nget ${getName}() {\\nreturn this.${tokenName};\\n},\\n\\nset ${setName}(val) {\\nthis.${tokenName} = val;\\n}\"\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/WrapSelection.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = brackets.getModule(\"thirdparty/lodash\");\n\n    var EditorManager        = brackets.getModule(\"editor/EditorManager\"),\n        TokenUtils           = brackets.getModule(\"utils/TokenUtils\"),\n        Strings              = brackets.getModule(\"strings\"),\n        RefactoringUtils     = require(\"RefactoringUtils\"),\n        RefactoringSession   = RefactoringUtils.RefactoringSession;\n\n    //Template keys mentioned in Templates.json\n    var WRAP_IN_CONDITION       = \"wrapCondition\",\n        ARROW_FUNCTION          = \"arrowFunction\",\n        GETTERS_SETTERS         = \"gettersSetters\",\n        TRY_CATCH               = \"tryCatch\";\n\n    //Active session which will contain information about editor, selection etc\n    var current = null;\n\n    /**\n     * Initialize session\n     */\n    function initializeRefactoringSession(editor) {\n        current = new RefactoringSession(editor);\n    }\n\n    /**\n     * Wrap selected statements\n     *\n     * @param {string} wrapperName - template name where we want wrap selected statements\n     * @param {string} err- error message if we can't wrap selected code\n     */\n    function _wrapSelectedStatements (wrapperName, err) {\n        var editor = EditorManager.getActiveEditor();\n        if (!editor) {\n            return;\n        }\n        initializeRefactoringSession(editor);\n\n        var startIndex = current.startIndex,\n            endIndex = current.endIndex,\n            selectedText = current.selectedText,\n            pos;\n\n        if (selectedText.length === 0) {\n            var statementNode = RefactoringUtils.findSurroundASTNode(current.ast, {start: startIndex}, [\"Statement\"]);\n            if (!statementNode) {\n                current.editor.displayErrorMessageAtCursor(err);\n                return;\n            }\n            selectedText = current.text.substr(statementNode.start, statementNode.end - statementNode.start);\n            startIndex = statementNode.start;\n            endIndex = statementNode.end;\n        } else {\n            var selectionDetails = RefactoringUtils.normalizeText(selectedText, startIndex, endIndex);\n            selectedText = selectionDetails.text;\n            startIndex = selectionDetails.start;\n            endIndex = selectionDetails.end;\n        }\n\n        if (!RefactoringUtils.checkStatement(current.ast, startIndex, endIndex, selectedText)) {\n            current.editor.displayErrorMessageAtCursor(err);\n            return;\n        }\n\n        pos = {\n            \"start\": current.cm.posFromIndex(startIndex),\n            \"end\": current.cm.posFromIndex(endIndex)\n        };\n\n        current.document.batchOperation(function() {\n            current.replaceTextFromTemplate(wrapperName, {body: selectedText}, pos);\n        });\n\n        if (wrapperName === TRY_CATCH) {\n            var cursorLine = current.editor.getSelection().end.line - 1,\n                startCursorCh = current.document.getLine(cursorLine).indexOf(\"\\/\\/\"),\n                endCursorCh = current.document.getLine(cursorLine).length;\n\n            current.editor.setSelection({\"line\": cursorLine, \"ch\": startCursorCh}, {\"line\": cursorLine, \"ch\": endCursorCh});\n        } else if (wrapperName === WRAP_IN_CONDITION) {\n            current.editor.setSelection({\"line\": pos.start.line, \"ch\": pos.start.ch + 4}, {\"line\": pos.start.line, \"ch\": pos.start.ch + 13});\n        }\n    }\n\n\n     //Wrap selected statements in try catch block\n    function wrapInTryCatch() {\n        _wrapSelectedStatements(TRY_CATCH, Strings.ERROR_TRY_CATCH);\n    }\n\n    //Wrap selected statements in try condition\n    function wrapInCondition() {\n        _wrapSelectedStatements(WRAP_IN_CONDITION, Strings.ERROR_WRAP_IN_CONDITION);\n    }\n\n    //Convert function to arrow function\n    function convertToArrowFunction() {\n        var editor = EditorManager.getActiveEditor();\n        if (!editor) {\n            return;\n        }\n        initializeRefactoringSession(editor);\n        \n        var funcExprNode = RefactoringUtils.findSurroundASTNode(current.ast, {start: current.startIndex}, [\"Function\"]);\n\n        if (!funcExprNode || funcExprNode.type !== \"FunctionExpression\" || funcExprNode.id) {\n            current.editor.displayErrorMessageAtCursor(Strings.ERROR_ARROW_FUNCTION);\n            return;\n        }\n\n        if (funcExprNode === \"FunctionDeclaration\") {\n            current.editor.displayErrorMessageAtCursor(Strings.ERROR_ARROW_FUNCTION);\n            return;\n        }\n\n        if (!funcExprNode.body) {\n            return;\n        }\n\n        var noOfStatements = funcExprNode.body.body.length,\n            selectedText = current.text.substr(funcExprNode.start, funcExprNode.end - funcExprNode.start),\n            param = [],\n            dontChangeParam = false,\n            numberOfParams = funcExprNode.params.length,\n            treatAsManyParam = false;\n\n            funcExprNode.params.forEach(function (item) {\n                if (item.type === \"Identifier\") {\n                    param.push(item.name);\n                } else if (item.type === \"AssignmentPattern\") {\n                    dontChangeParam = true;\n                }\n            });\n\n        //In case defaults params keep params as it is\n        if (dontChangeParam) {\n            if (numberOfParams >= 1) {\n                param.splice(0,param.length);\n                param.push(current.text.substr(funcExprNode.params[0].start, funcExprNode.params[numberOfParams-1].end - funcExprNode.params[0].start));\n                // In case default param, treat them as many paramater because to use\n                // one parameter template, That param should be an identifier\n                if (numberOfParams === 1) {\n                    treatAsManyParam = true;\n                }\n            }\n            dontChangeParam = false;\n        }\n\n        var loc = {\n                \"fullFunctionScope\": {\n                    start: funcExprNode.start,\n                    end: funcExprNode.end\n                },\n                \"functionsDeclOnly\": {\n                    start: funcExprNode.start,\n                    end: funcExprNode.body.start\n                }\n            },\n            locPos = {\n                \"fullFunctionScope\": {\n                    \"start\": current.cm.posFromIndex(loc.fullFunctionScope.start),\n                    \"end\": current.cm.posFromIndex(loc.fullFunctionScope.end)\n                },\n                \"functionsDeclOnly\": {\n                    \"start\": current.cm.posFromIndex(loc.functionsDeclOnly.start),\n                    \"end\": current.cm.posFromIndex(loc.functionsDeclOnly.end)\n                }\n            },\n            isReturnStatement = (noOfStatements >= 1 && funcExprNode.body.body[0].type === \"ReturnStatement\"),\n            bodyStatements = funcExprNode.body.body[0],\n            params;\n\n            // If there is nothing in function body, then get the text b/w curly braces\n            // In this case, We will update params only as per Arrow function expression\n            if (!bodyStatements) {\n                bodyStatements = funcExprNode.body;\n            }\n            params = {\n                \"params\": param.join(\", \"),\n                \"statement\": _.trimRight(current.text.substr(bodyStatements.start, bodyStatements.end - bodyStatements.start), \";\")\n            };\n\n        if (isReturnStatement) {\n            params.statement = params.statement.substr(7).trim();\n        }\n\n        if (noOfStatements === 1) {\n            current.document.batchOperation(function() {\n                (numberOfParams === 1 && !treatAsManyParam) ?  current.replaceTextFromTemplate(ARROW_FUNCTION, params, locPos.fullFunctionScope, \"oneParamOneStament\") :\n                current.replaceTextFromTemplate(ARROW_FUNCTION, params, locPos.fullFunctionScope, \"manyParamOneStament\");\n\n            });\n        } else {\n            current.document.batchOperation(function() {\n                (numberOfParams === 1 && !treatAsManyParam) ?  current.replaceTextFromTemplate(ARROW_FUNCTION, {params: param},\n                locPos.functionsDeclOnly, \"oneParamManyStament\") :\n                current.replaceTextFromTemplate(ARROW_FUNCTION, {params: param.join(\", \")}, locPos.functionsDeclOnly, \"manyParamManyStament\");\n            });\n        }\n\n        current.editor.setCursorPos(locPos.functionsDeclOnly.end.line, locPos.functionsDeclOnly.end.ch, false);\n    }\n\n    // Create gtteres and setters for a property\n    function createGettersAndSetters() {\n        var editor = EditorManager.getActiveEditor();\n        if (!editor) {\n            return;\n        }\n        initializeRefactoringSession(editor);\n\n        var startIndex = current.startIndex,\n            endIndex = current.endIndex,\n            selectedText = current.selectedText;\n\n        if (selectedText.length >= 1) {\n            var selectionDetails = RefactoringUtils.normalizeText(selectedText, startIndex, endIndex);\n            selectedText = selectionDetails.text;\n            startIndex = selectionDetails.start;\n            endIndex = selectionDetails.end;\n        }\n\n        var token = TokenUtils.getTokenAt(current.cm, current.cm.posFromIndex(endIndex)),\n            commaString = \",\",\n            isLastNode,\n            templateParams,\n            parentNode,\n            propertyEndPos;\n\n        //Create getters and setters only if selected reference is a property\n        if (token.type !== \"property\") {\n            current.editor.displayErrorMessageAtCursor(Strings.ERROR_GETTERS_SETTERS);\n            return;\n        }\n\n        parentNode = current.getParentNode(current.ast, endIndex);\n        // Check if selected propery is child of a object expression\n        if (!parentNode || !parentNode.properties) {\n            current.editor.displayErrorMessageAtCursor(Strings.ERROR_GETTERS_SETTERS);\n            return;\n        }\n\n\n        var propertyNodeArray = parentNode.properties;\n        // Find the last Propery Node before endIndex\n        var properyNodeIndex = propertyNodeArray.findIndex(function (element) {\n            return (endIndex >= element.start && endIndex < element.end);\n        });\n\n        var propertyNode = propertyNodeArray[properyNodeIndex];\n\n        //Get Current Selected Property End Index;\n        propertyEndPos = editor.posFromIndex(propertyNode.end);\n\n\n        //We have to add ',' so we need to find position of current property selected\n        isLastNode = current.isLastNodeInScope(current.ast, endIndex);\n        var nextPropertNode, nextPropertyStartPos;\n        if(!isLastNode && properyNodeIndex + 1 <= propertyNodeArray.length - 1) {\n            nextPropertNode = propertyNodeArray[properyNodeIndex + 1];\n            nextPropertyStartPos = editor.posFromIndex(nextPropertNode.start);\n\n            if(propertyEndPos.line !== nextPropertyStartPos.line) {\n                propertyEndPos = current.lineEndPosition(current.startPos.line);\n            } else {\n                propertyEndPos = nextPropertyStartPos;\n                commaString = \", \";\n            }\n        }\n\n        var getSetPos;\n        if (isLastNode) {\n            getSetPos = current.document.adjustPosForChange(propertyEndPos, commaString.split(\"\\n\"),\n                                                            propertyEndPos, propertyEndPos);\n        } else {\n            getSetPos = propertyEndPos;\n        }\n        templateParams = {\n            \"getName\": token.string,\n            \"setName\": token.string,\n            \"tokenName\": token.string\n        };\n\n        // Replace, setSelection, IndentLine\n        // We need to call batchOperation as indentLine don't have option to add origin as like replaceRange\n        current.document.batchOperation(function() {\n            if (isLastNode) {\n                //Add ',' in the end of current line\n                current.document.replaceRange(commaString, propertyEndPos, propertyEndPos);\n            }\n\n            current.editor.setSelection(getSetPos); //Selection on line end\n\n            // Add getters and setters for given token using template at current cursor position\n            current.replaceTextFromTemplate(GETTERS_SETTERS, templateParams);\n\n            if (!isLastNode) {\n                // Add ',' at the end setter\n                current.document.replaceRange(commaString, current.editor.getSelection().start, current.editor.getSelection().start);\n            }\n        });\n    }\n\n    exports.wrapInCondition         = wrapInCondition;\n    exports.wrapInTryCatch          = wrapInTryCatch;\n    exports.convertToArrowFunction  = convertToArrowFunction;\n    exports.createGettersAndSetters = createGettersAndSetters;\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/keyboard.json",
    "content": "{\n    \"extractToVariable\":  [\n        \"Ctrl-Alt-V\"\n    ],\n    \"extractToFunction\":  [\n        \"Ctrl-Alt-M\"\n    ],\n    \"renameIdentifier\": [\n        {\n            \"key\": \"Ctrl-R\", \"platform\": \"mac\"\n        },\n        {\n            \"key\": \"Ctrl-R\", \"platform\": \"win\"\n        },\n        {\n            \"key\": \"Ctrl-R\", \"platform\": \"linux\"\n        }\n    ]\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n\n    var AppInit              = brackets.getModule(\"utils/AppInit\"),\n        PreferencesManager   = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings              = brackets.getModule(\"strings\"),\n        RenameIdentifier     = require(\"RenameIdentifier\"),\n        ExtractToVariable    = require(\"ExtractToVariable\"),\n        ExtractToFunction    = require(\"ExtractToFunction\"),\n        WrapSelection        = require(\"WrapSelection\"),\n        CommandManager       = brackets.getModule(\"command/CommandManager\"),\n        Menus                = brackets.getModule(\"command/Menus\"),\n        HealthLogger         = brackets.getModule(\"utils/HealthLogger\"),\n        _                    = brackets.getModule(\"thirdparty/lodash\"),\n        EditorManager        = brackets.getModule(\"editor/EditorManager\");\n\n    var jsRefactoringEnabled     = true;\n\n    var KeyboardPrefs = JSON.parse(require(\"text!keyboard.json\"));\n\n    // Command ids\n    var EXTRACTTO_VARIABLE       = \"refactoring.extractToVariable\",\n        EXTRACTTO_FUNCTION       = \"refactoring.extractToFunction\",\n        REFACTOR_RENAME          = \"refactoring.renamereference\",\n        REFACTORWRAPINTRYCATCH   = \"refactoring.wrapintrycatch\",\n        REFACTORWRAPINCONDITION  = \"refactoring.wrapincondition\",\n        REFACTORCONVERTTOARROWFN = \"refactoring.converttoarrowfunction\",\n        REFACTORCREATEGETSET     = \"refactoring.creategettersandsetters\";\n\n    // This preference controls whether to create a session and process all JS files or not.\n    PreferencesManager.definePreference(\"refactoring.JSRefactoring\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_CODE_REFACTORING\n    });\n\n\n    /**\n     * Check whether any of refactoring hints preferences for JS Refactoring is disabled\n     * @return {boolean} enabled/disabled\n     */\n    function _isRefactoringEnabled() {\n        return (PreferencesManager.get(\"refactoring.JSRefactoring\") !== false);\n    }\n\n    PreferencesManager.on(\"change\", \"refactoring.JSRefactoring\", function () {\n        jsRefactoringEnabled = _isRefactoringEnabled();\n    });\n\n    function _handleRefactor(functionName) {\n        var eventName, eventType = \"\";\n        \n        switch (functionName) {\n        case REFACTOR_RENAME:\n            eventName = REFACTOR_RENAME;\n            eventType = \"rename\";\n            RenameIdentifier.handleRename();\n            break;\n        case EXTRACTTO_VARIABLE:\n            eventName = EXTRACTTO_VARIABLE;\n            eventType = \"extractToVariable\";\n            ExtractToVariable.handleExtractToVariable();\n            break;\n        case EXTRACTTO_FUNCTION:\n            eventName = EXTRACTTO_FUNCTION;\n            eventType = \"extractToFunction\";\n            ExtractToFunction.handleExtractToFunction();\n            break;\n        case REFACTORWRAPINTRYCATCH:\n            eventName = REFACTORWRAPINTRYCATCH;\n            eventType = \"tryCatch\";\n            WrapSelection.wrapInTryCatch();\n            break;\n        case REFACTORWRAPINCONDITION:\n            eventName = REFACTORWRAPINCONDITION;\n            eventType = \"wrapInCondition\";\n            WrapSelection.wrapInCondition();\n            break;\n        case REFACTORCONVERTTOARROWFN:\n            eventName = REFACTORCONVERTTOARROWFN;\n            eventType = \"convertToFunction\";\n            WrapSelection.convertToArrowFunction();\n            break;\n        case REFACTORCREATEGETSET:\n            eventName = REFACTORCREATEGETSET;\n            eventType = \"createGetterSetter\";\n            WrapSelection.createGettersAndSetters();\n            break;\n        }\n        if (eventName) {\n            var editor = EditorManager.getActiveEditor();\n        \n            // Logging should be done only when the context is javascript\n            if (!editor || editor.getModeForSelection() !== \"javascript\") {\n                return;\n            }\n            // Send analytics data for js refactoring\n            HealthLogger.sendAnalyticsData(\n                eventName,\n                \"usage\",\n                \"jsRefactor\",\n                eventType\n            );\n        }\n    }\n\n    AppInit.appReady(function () {\n\n        if (jsRefactoringEnabled) {\n            var subMenu = Menus.getContextMenu(Menus.ContextMenuIds.EDITOR_MENU).addSubMenu(Strings.CMD_REFACTOR, \"refactor-submenu\");\n\n            var menuLocation = Menus.AppMenuBar.EDIT_MENU;\n\n            Menus.getMenu(menuLocation).addMenuDivider();\n\n            // Rename Identifier\n            CommandManager.register(Strings.CMD_REFACTORING_RENAME, REFACTOR_RENAME, _.partial(_handleRefactor, REFACTOR_RENAME));\n            subMenu.addMenuItem(REFACTOR_RENAME);\n            Menus.getMenu(menuLocation).addMenuItem(REFACTOR_RENAME, KeyboardPrefs.renameIdentifier);\n\n            // Extract to Variable\n            CommandManager.register(Strings.CMD_EXTRACTTO_VARIABLE, EXTRACTTO_VARIABLE, _.partial(_handleRefactor, EXTRACTTO_VARIABLE));\n            subMenu.addMenuItem(EXTRACTTO_VARIABLE);\n            Menus.getMenu(menuLocation).addMenuItem(EXTRACTTO_VARIABLE, KeyboardPrefs.extractToVariable);\n\n            // Extract to Function\n            CommandManager.register(Strings.CMD_EXTRACTTO_FUNCTION, EXTRACTTO_FUNCTION, _.partial(_handleRefactor, EXTRACTTO_FUNCTION));\n            subMenu.addMenuItem(EXTRACTTO_FUNCTION);\n            Menus.getMenu(menuLocation).addMenuItem(EXTRACTTO_FUNCTION, KeyboardPrefs.extractToFunction);\n\n            // Wrap Selection\n            CommandManager.register(Strings.CMD_REFACTORING_TRY_CATCH, REFACTORWRAPINTRYCATCH, _.partial(_handleRefactor, REFACTORWRAPINTRYCATCH));\n            subMenu.addMenuItem(REFACTORWRAPINTRYCATCH);\n            Menus.getMenu(menuLocation).addMenuItem(REFACTORWRAPINTRYCATCH);\n\n            CommandManager.register(Strings.CMD_REFACTORING_CONDITION, REFACTORWRAPINCONDITION, _.partial(_handleRefactor, REFACTORWRAPINCONDITION));\n            subMenu.addMenuItem(REFACTORWRAPINCONDITION);\n            Menus.getMenu(menuLocation).addMenuItem(REFACTORWRAPINCONDITION);\n\n            CommandManager.register(Strings.CMD_REFACTORING_ARROW_FUNCTION, REFACTORCONVERTTOARROWFN, _.partial(_handleRefactor, REFACTORCONVERTTOARROWFN));\n            subMenu.addMenuItem(REFACTORCONVERTTOARROWFN);\n            Menus.getMenu(menuLocation).addMenuItem(REFACTORCONVERTTOARROWFN);\n\n            CommandManager.register(Strings.CMD_REFACTORING_GETTERS_SETTERS, REFACTORCREATEGETSET, _.partial(_handleRefactor, REFACTORCREATEGETSET));\n            subMenu.addMenuItem(REFACTORCREATEGETSET);\n            Menus.getMenu(menuLocation).addMenuItem(REFACTORCREATEGETSET);\n        }\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/unittest-files/test.js",
    "content": "// Extract to Variable\n\n// Declarations\nvar x;\nvar y = 34;\n\nfunction test() {\n    console.log(\"Testing\");\n}\n\n// Literal\nx = 923;\n\n// Array\nx = [1, 2, 3];\n\n// Object\nx = {\n    test1: 12,\n    test2: 45\n};\n\n// Property\nx = x.test1;\n\n// Function Expression\nx = function() {\n    console.log(\"hello world\");\n};\n\n// Unary Expression\nx = ++y;\n\n// Binary Expression\nx = 1 + 2 + 3;\nx = 2 ** 3;\n\n// Assignment Expression\nx = 23;\n\n// Logical Expression\nx = true || false;\n\n// Conditional Expression\nx = (2 < 3)? 34: 45;\n\n// Call Expression\ntest();\n\n// New Expression\nx = new Square();\n\n// Sequence Expression\nx = 1, 2, 3;\n\n// Arrow functions\nx = y => y ** 2;\nx = (a, b) => {\n    return a + b;\n};\n\n// Template Literals\nx = `Template Literal`;\n\n// Tagged Template Literal\nx = String.raw`Hi${2 + 3}!`;\n\n// Await Expression example\nfunction resolveAfter2Seconds(x) {\n    return new Promise(resolve => {\n        setTimeout(() => {\n            resolve(x);\n        }, 2000);\n    });\n}\n\nasync function f1() {\n    var x = await resolveAfter2Seconds(10);\n}\n\n// Yield expression syntax\nfunction* countAppleSales () {\n    var saleList = [3, 7, 5];\n    for (var i = 0; i < saleList.length; i++) {\n        yield saleList[i];\n    }\n}\n\n// Super expression example\nclass Polygon {\n    constructor(height, width) {\n        this.name = 'Polygon';\n        this.height = height;\n        this.width = width;\n    }\n    sayName() {\n        console.log('Hi, I am a ', this.name + '.');\n    }\n}\n\nclass Square extends Polygon {\n    constructor(length) {\n        // the expression\n        super(length, length);\n        this.name = 'Square';\n    }\n}\n\n// Class Expression\nx = class {\n    constructor (height, width) {\n        this.a = height;\n        this.b = width;\n    }\n};\n\n// Multiple references of 34\nfunction MultiReferences() {\n    var x = 34;\n    var y = 34;\n    var z = 34;\n}\n\n// Unique name\nfunction testUniqueName() {\n    var extracted1 = 23;\n    var x = 45;\n}\n\n\n//Test Cases For Rename/Wrap Selection\n\nfunction addNumbers(a, b) {\n    return a + b;\n}\n\nfunction playWithNumbers() {\n    var a = 7,\n        b = 7,\n        c = 6;\n    return addNumbers(a, c) * b;\n}\n\n//Test for Convert to arrow function\n\nvar sum = function (a, b) {\n        return a+b;\n    };\n\nvar num = function (a) {\n        return a;\n    };\n\nvar sumAll = function (a, b) {\n        var c = a + b;\n        return c;\n    };\n\n//Create Getters and Setters\n\ntest = {\n    docCurrent         : \"mydoc\",\n    isReadOnly  : false\n};\n\nvar myVar = 7;\n\nfunction getVar() {\n    return myVar;\n}"
  },
  {
    "path": "src/extensions/default/JavaScriptRefactoring/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*global describe, it, xit, expect, beforeEach, afterEach, waitsFor, runs, waitsForDone, beforeFirst, afterLast */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var MainViewManager      = brackets.getModule(\"view/MainViewManager\"),\n        DocumentManager      = brackets.getModule(\"document/DocumentManager\"),\n        FileUtils            = brackets.getModule(\"file/FileUtils\"),\n        SpecRunnerUtils      = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        Strings              = brackets.getModule(\"strings\"),\n        KeyEvent             = brackets.getModule(\"utils/KeyEvent\"),\n        ExtractToVariable    = require(\"ExtractToVariable\"),\n        ExtractToFunction    = require(\"ExtractToFunction\"),\n        TokenUtils           = brackets.getModule(\"utils/TokenUtils\"),\n        WrapSelection        = require(\"WrapSelection\"),\n        RenameIdentifier     = require(\"RenameIdentifier\");\n\n    var extensionPath   = FileUtils.getNativeModuleDirectoryPath(module),\n        testPath        = extensionPath + \"/unittest-files/test.js\",\n        testDoc         = null,\n        testEditor;\n\n    describe(\"Javascript Refactoring \", function () {\n\n        function setupTest(path, primePump) { // FIXME: primePump argument ignored even though used below\n            DocumentManager.getDocumentForPath(path).done(function (doc) {\n                testDoc = doc;\n            });\n\n            waitsFor(function () {\n                return testDoc !== null;\n            }, \"Unable to open test document\", 10000);\n\n            // create Editor instance (containing a CodeMirror instance)\n            runs(function () {\n                testEditor = SpecRunnerUtils.createMockEditorForDocument(testDoc);\n            });\n        }\n\n        function tearDownTest() {\n            // The following call ensures that the document is reloaded\n            // from disk before each test\n            MainViewManager._closeAll(MainViewManager.ALL_PANES);\n            SpecRunnerUtils.destroyMockEditor(testDoc);\n            testEditor = null;\n            testDoc = null;\n        }\n\n        function _waitForRefactoring(prevDocLength, numberOfLines, callback) {\n            if (!callback || numberOfLines instanceof Function) {\n                callback = numberOfLines;\n                numberOfLines = null;\n            }\n            waitsFor(function() {\n                return (testDoc.getText().length !== prevDocLength || (numberOfLines && testDoc.getText().split(\"\\n\").length !== numberOfLines));\n            }, 3000);\n            runs(function() {callback();});\n        }\n\n        function _waitForRename(prevSelections, callback) {\n            waitsFor(function() {\n                return testEditor.getSelections().length !== prevSelections;\n            }, 3000);\n            runs(function() {callback();});\n        }\n\n        describe(\"Extract to variable\", function () {\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should extract literal expression\", function () {\n                testEditor.setSelection({line: 11, ch: 4}, {line: 11, ch: 7});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(11)).toBe(\"var extracted1 = 923;\");\n                    expect(testDoc.getLine(12)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract array expression\", function () {\n                testEditor.setSelection({line: 14, ch: 4}, {line: 14, ch: 13});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(14)).toBe(\"var extracted1 = [1, 2, 3];\");\n                    expect(testDoc.getLine(15)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract object expression\", function () {\n                testEditor.setSelection({line: 17, ch: 4}, {line: 20, ch: 1});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getRange({line: 17, ch: 0}, {line: 20, ch: 2}))\n                        .toBe(\n                            \"var extracted1 = {\\n\" +\n                            \"    test1: 12,\\n\"     +\n                            \"    test2: 45\\n\"      +\n                            \"};\"\n                        );\n                    expect(testDoc.getLine(21)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract property expression\", function () {\n                testEditor.setSelection({line: 23, ch: 4}, {line: 23, ch: 11});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(23)).toBe(\"var extracted1 = x.test1;\");\n                    expect(testDoc.getLine(24)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract function expression\", function () {\n                testEditor.setSelection({line: 26, ch: 4}, {line: 28, ch: 1});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getRange({line: 26, ch: 0}, {line: 28, ch: 2}))\n                        .toBe(\n                            \"var extracted1 = function() {\\n\"      +\n                            \"    console.log(\\\"hello world\\\");\\n\"  +\n                            \"};\"\n                        );\n                    expect(testDoc.getLine(29)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract unary expression\", function () {\n                testEditor.setSelection({line: 31, ch: 4}, {line: 31, ch: 7});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(31)).toBe(\"var extracted1 = ++y;\");\n                    expect(testDoc.getLine(32)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract binary expression\", function () {\n                testEditor.setSelection({line: 34, ch: 4}, {line: 34, ch: 13});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(34)).toBe(\"var extracted1 = 1 + 2 + 3;\");\n                    expect(testDoc.getLine(35)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract assignment expression\", function () {\n                testEditor.setSelection({line: 38, ch: 0}, {line: 38, ch: 6});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(38)).toBe(\"var extracted1 = x = 23;\");\n                });\n            });\n\n            it(\"should extract assignment expression\", function () {\n                testEditor.setSelection({line: 41, ch: 3}, {line: 41, ch: 17});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(41)).toBe(\"var extracted1 = true || false;\");\n                    expect(testDoc.getLine(42)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract conditional expression\", function () {\n                testEditor.setSelection({line: 44, ch: 4}, {line: 44, ch: 19});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(44)).toBe(\"var extracted1 = (2 < 3)? 34: 45;\");\n                    expect(testDoc.getLine(45)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract new expression\", function () {\n                testEditor.setSelection({line: 50, ch: 4}, {line: 50, ch: 16});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(50)).toBe(\"var extracted1 = new Square();\");\n                    expect(testDoc.getLine(51)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract arrow function\", function () {\n                testEditor.setSelection({line: 56, ch: 4}, {line: 56, ch: 16});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(56)).toBe(\"var extracted1 = y => y ** 2;\");\n                    expect(testDoc.getLine(57)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract template literal\", function () {\n                testEditor.setSelection({line: 62, ch: 4}, {line: 62, ch: 22});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(62)).toBe(\"var extracted1 = `Template Literal`;\");\n                    expect(testDoc.getLine(63)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract tagged template literal\", function () {\n                testEditor.setSelection({line: 65, ch: 4}, {line: 65, ch: 29});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(65)).toBe(\"var extracted1 = String.raw`Hi${2 + 3}!`;\");\n                    expect(testDoc.getLine(66)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract await expression\", function () {\n                testEditor.setSelection({line: 77, ch: 12}, {line: 77, ch: 42});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(77)).toBe(\"    var extracted1 = await resolveAfter2Seconds(10);\");\n                    expect(testDoc.getLine(78)).toBe(\"    var x = extracted1;\");\n                });\n            });\n\n            it(\"should extract yield expression\", function () {\n                testEditor.setSelection({line: 84, ch: 8}, {line: 84, ch: 26});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(84)).toBe(\"        var extracted1 = yield saleList[i];\");\n                });\n            });\n\n            it(\"should extract super expression\", function () {\n                testEditor.setSelection({line: 103, ch: 8}, {line: 103, ch: 29});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(103)).toBe(\"        var extracted1 = super(length, length);\");\n                });\n            });\n\n            it(\"should extract class expression\", function () {\n                testEditor.setSelection({line: 109, ch: 4}, {line: 114, ch: 1});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getRange({line: 109, ch: 0}, {line: 114, ch: 2}))\n                    .toBe(\n                        \"var extracted1 = class {\\n\"          +\n                        \"    constructor (height, width) {\\n\" +\n                        \"        this.a = height;\\n\"          +\n                        \"        this.b = width;\\n\"           +\n                        \"    }\\n\"                            +\n                        \"};\"\n                    );\n                    expect(testDoc.getLine(115)).toBe(\"x = extracted1;\");\n                });\n            });\n\n            it(\"should extract all the references of expression in a scope\", function() {\n                testEditor.setSelection({line: 118, ch: 12}, {line: 118, ch: 14});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(118)).toBe(\"    var extracted1 = 34;\");\n                    expect(testDoc.getLine(119)).toBe(\"    var x = extracted1;\");\n                    expect(testDoc.getLine(120)).toBe(\"    var y = extracted1;\");\n                    expect(testDoc.getLine(121)).toBe(\"    var z = extracted1;\");\n                });\n            });\n\n            it(\"should create variable with unique name\", function() {\n                testEditor.setSelection({line: 126, ch: 12}, {line: 126, ch: 14});\n\n                var prevDocLength = testDoc.getText().length;\n\n                ExtractToVariable.handleExtractToVariable();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(126)).toBe(\"    var extracted2 = 45;\");\n                    expect(testDoc.getLine(127)).toBe(\"    var x = extracted2;\");\n                });\n            });\n        });\n\n        describe(\"Extract to function\", function () {\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should display correct scopes for line inside a function declaration\", function () {\n                testEditor.setSelection({line: 7, ch: 4}, {line: 7, ch: 28});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                   scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu.items.length).toBe(2);\n                    expect(scopeMenu.items[0].name).toBe(\"test\");\n                    expect(scopeMenu.items[1].name).toBe(\"global\");\n                });\n            });\n\n            it(\"should display correct scopes for line inside a function expression\", function () {\n                testEditor.setSelection({line: 27, ch: 4}, {line: 27, ch: 31});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                   scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu.items.length).toBe(2);\n                    expect(scopeMenu.items[0].name).toBe(\"x\");\n                    expect(scopeMenu.items[1].name).toBe(\"global\");\n                });\n            });\n\n            it(\"should display correct scopes for line inside a arrow function\", function () {\n                testEditor.setSelection({line: 58, ch: 4}, {line: 58, ch: 17});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                   scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu.items.length).toBe(2);\n                    expect(scopeMenu.items[0].name).toBe(\"x\");\n                    expect(scopeMenu.items[1].name).toBe(\"global\");\n                });\n            });\n\n            it(\"should display correct scopes for line inside a nested function\", function () {\n                testEditor.setSelection({line: 71, ch: 12}, {line: 71, ch: 23});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                   scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu.items.length).toBe(4);\n                    expect(scopeMenu.items[0].name).toBe(\"function starting with {\\n            resolve(x);\\n    \");\n                    expect(scopeMenu.items[1].name).toBe(\"function starting with {\\n        setTimeout(() => {\\n \");\n                    expect(scopeMenu.items[2].name).toBe(\"resolveAfter2Seconds\");\n                    expect(scopeMenu.items[3].name).toBe(\"global\");\n                });\n            });\n\n            it(\"should display correct scopes for line inside a class declaration\", function () {\n                testEditor.setSelection({line: 93, ch: 8}, {line: 93, ch: 27});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                   scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu.items.length).toBe(3);\n                    expect(scopeMenu.items[0].name).toBe(\"constructor\");\n                    expect(scopeMenu.items[1].name).toBe(\"class Polygon\");\n                    expect(scopeMenu.items[2].name).toBe(\"global\");\n                });\n            });\n\n            it(\"should display correct scopes for line inside a class expression\", function () {\n                testEditor.setSelection({line: 112, ch: 8}, {line: 112, ch: 23});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                    scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu.items.length).toBe(3);\n                    expect(scopeMenu.items[0].name).toBe(\"constructor\");\n                    expect(scopeMenu.items[1].name).toBe(\"class x\");\n                    expect(scopeMenu.items[2].name).toBe(\"global\");\n                });\n            });\n\n            it(\"should extract line in global scope without displaying scopes\", function () {\n                testEditor.setSelection({line: 4, ch: 0}, {line: 4, ch: 11});\n\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                    scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu).toBeUndefined();\n                    expect(testDoc.getRange({line: 4, ch: 0}, {line: 7, ch: 1}))\n                        .toBe(\n                            \"function extracted1() {\\n\" +\n                            \"    var y = 34;\\n\"     +\n                            \"    return y;\\n\"      +\n                            \"}\"\n                        );\n                    expect(testDoc.getLine(9)).toBe(\"var y = extracted1();\");\n                });\n            });\n\n            it(\"should extract a line inside a function declaration\", function () {\n                testEditor.setSelection({line: 7, ch: 4}, {line: 7, ch: 27});\n\n                var prevDocLength = testDoc.getText().length;\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                    scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu).toBeDefined();\n                    var scopeElement = scopeMenu.$menu.find(\".inlinemenu-item\")[0];\n                    expect(scopeElement).toBeDefined();\n                    $(scopeElement).trigger(\"click\");\n                });\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getRange({line: 7, ch: 0}, {line: 9, ch: 6}))\n                        .toBe(\n                            \"    function extracted1() {\\n\"       +\n                            \"        console.log(\\\"Testing\\\");\\n\" +\n                            \"    }\"\n                        );\n                });\n            });\n\n            it(\"should extract a line inside a class to a class method\", function () {\n                testEditor.setSelection({line: 104, ch: 8}, {line: 104, ch: 29});\n\n                var prevDocLength = testDoc.getText().length;\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                    scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu).toBeDefined();\n                    var scopeElement = scopeMenu.$menu.find(\".inlinemenu-item\")[1];\n                    expect(scopeElement).toBeDefined();\n                    $(scopeElement).trigger(\"click\");\n                });\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getRange({line: 101, ch: 0}, {line: 103, ch: 6}))\n                        .toBe(\n                            \"    extracted1() {\\n\"            +\n                            \"        this.name = 'Square';\\n\" +\n                            \"    }\"\n                        );\n                    expect(testDoc.getLine(108)).toBe(\"        this.extracted1();\");\n                });\n            });\n\n            it(\"should extract a line inside a class to global scope\", function () {\n                testEditor.setSelection({line: 104, ch: 8}, {line: 104, ch: 29});\n\n                var prevDocLength = testDoc.getText().length;\n                var result = ExtractToFunction.handleExtractToFunction();\n                var scopeMenu;\n\n                waitsForDone(result.then(function(inlineMenu) {\n                    scopeMenu = inlineMenu;\n                }), \"Scope not displayed in extract to function\", 3000);\n\n                runs(function() {\n                    expect(scopeMenu).toBeDefined();\n                    var scopeElement = scopeMenu.$menu.find(\".inlinemenu-item\")[2];\n                    expect(scopeElement).toBeDefined();\n                    $(scopeElement).trigger(\"click\");\n                });\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getRange({line: 100, ch: 0}, {line: 102, ch: 2}))\n                        .toBe(\n                            \"function extracted1() {\\n\"            +\n                            \"    this.name = 'Square';\\n\" +\n                            \"}\"\n                        );\n                    expect(testDoc.getLine(108)).toBe(\"        extracted1.call(this);\");\n                });\n            });\n        });\n\n\n        describe(\"Rename\", function () {\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should rename function name\", function() {\n                testEditor.setSelection({line: 140, ch: 17}, {line: 140, ch: 17});\n\n                var selections = testEditor.getSelections();\n\n                RenameIdentifier.handleRename();\n\n\n                _waitForRename(selections.length, function() {\n                    var selections = testEditor.getSelections(),\n                        token1 = TokenUtils.getTokenAt(testEditor._codeMirror,{line: 132, ch: 14}, {line: 132, ch: 14}),\n                        token2 = TokenUtils.getTokenAt(testEditor._codeMirror, {line: 140, ch: 17}, {line: 140, ch: 17});\n\n                    expect(selections[0].start.line).toEqual(132);\n                    expect(selections[1].start.line).toEqual(140);\n                });\n            });\n\n            it(\"should rename variable name\", function() {\n                testEditor.setSelection({line: 165, ch: 6}, {line: 165, ch: 6});\n\n                var selections = testEditor.getSelections();\n\n                RenameIdentifier.handleRename();\n\n\n                _waitForRename(selections.length, function() {\n                    var selections = testEditor.getSelections(),\n                        token1 = TokenUtils.getTokenAt(testEditor._codeMirror,{line: 149, ch: 6}, {line: 149, ch: 6}),\n                        token2 = TokenUtils.getTokenAt(testEditor._codeMirror, {line: 150, ch: 13}, {line: 150, ch: 13});\n\n                    expect(selections[0].start.line).toEqual(165);\n                    expect(selections[1].start.line).toEqual(168);\n                });\n            });\n        });\n\n        describe(\"Wrap Selection\", function () {\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should wrap selection in Try-Catch block\", function() {\n                testEditor.setSelection({line: 140, ch: 17}, {line: 140, ch: 17});\n\n                var prevDocLength = testDoc.getText().length;\n\n                WrapSelection.wrapInTryCatch();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(140)).toBe(\"    try {\");\n                    expect(testDoc.getLine(141)).toBe(\"        return addNumbers(a, c) * b;\");\n                    expect(testDoc.getLine(142)).toBe(\"    } catch (e) {\");\n                    expect(testDoc.getLine(143)).toBe(\"        //Catch Statement\");\n                    expect(testDoc.getLine(144)).toBe(\"    }\");\n                });\n            });\n\n            it(\"should wrap selection in Condition block\", function() {\n                testEditor.setSelection({line: 140, ch: 17}, {line: 140, ch: 17});\n\n                var prevDocLength = testDoc.getText().length;\n\n                WrapSelection.wrapInCondition();\n\n                _waitForRefactoring(prevDocLength, function() {\n                    expect(testDoc.getLine(140)).toBe(\"    if (Condition) {\");\n                    expect(testDoc.getLine(141)).toBe(\"        return addNumbers(a, c) * b;\");\n                    expect(testDoc.getLine(142)).toBe(\"    }\");\n                });\n            });\n        });\n\n        describe(\"Arrow Function\", function () {\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should convert selected function to arrow function with two param and one return statement\", function() {\n                testEditor.setSelection({line: 146, ch: 6}, {line: 146, ch: 6});\n\n                var prevDoc = testDoc.getText();\n\n                WrapSelection.convertToArrowFunction();\n\n                _waitForRefactoring(prevDoc.length, prevDoc.split(\"\\n\").length, function() {\n                    expect(testDoc.getLine(145)).toBe(\"var sum = (a, b) => a+b;\");\n                });\n            });\n\n            it(\"should convert selected function to arrow function with one param and one return statement\", function() {\n                testEditor.setSelection({line: 150, ch: 6}, {line: 150, ch: 6});\n\n                var prevDoc = testDoc.getText();\n\n                WrapSelection.convertToArrowFunction();\n\n                _waitForRefactoring(prevDoc.length, prevDoc.split(\"\\n\").length, function() {\n                    expect(testDoc.getLine(149)).toBe(\"var num = a => a;\");\n                });\n            });\n\n            it(\"should convert selected function to arrow function with two param and two statements\", function() {\n                testEditor.setSelection({line: 154, ch: 6}, {line: 154, ch: 6});\n\n                var prevDoc = testDoc.getText();\n\n                WrapSelection.convertToArrowFunction();\n\n                _waitForRefactoring(prevDoc.length, prevDoc.split(\"\\n\").length, function() {\n                    expect(testDoc.getLine(153)).toBe(\"var sumAll = (a, b) => {\");\n                });\n            });\n        });\n\n        describe(\"Getters-Setters\", function () {\n            beforeEach(function () {\n                setupTest(testPath, false);\n            });\n\n            afterEach(function () {\n                tearDownTest();\n            });\n\n            it(\"should create Getters Setters for selected property\", function() {\n                testEditor.setSelection({line: 161, ch: 12}, {line: 161, ch: 12});\n\n                var prevDoc = testDoc.getText();\n\n                WrapSelection.createGettersAndSetters();\n\n                _waitForRefactoring(prevDoc.length, prevDoc.split(\"\\n\").length, function() {\n                    expect(testDoc.getLine(162)).toBe(\"    get docCurrent() {\");\n                    expect(testDoc.getLine(163)).toBe(\"        return this.docCurrent;\");\n                    expect(testDoc.getLine(164)).toBe(\"    },\");\n                    expect(testDoc.getLine(166)).toBe(\"    set docCurrent(val) {\");\n                    expect(testDoc.getLine(167)).toBe(\"        this.docCurrent = val;\");\n                    expect(testDoc.getLine(168)).toBe(\"    },\");\n                });\n            });\n\n            it(\"should create Getters Setters for last property in context\", function() {\n                testEditor.setSelection({line: 162, ch: 12}, {line: 162, ch: 12});\n\n                var prevDoc = testDoc.getText();\n\n                WrapSelection.createGettersAndSetters();\n\n                _waitForRefactoring(prevDoc.length, prevDoc.split(\"\\n\").length, function() {\n                    expect(testDoc.getLine(162)).toBe(\"    isReadOnly  : false,\");\n                    expect(testDoc.getLine(163)).toBe(\"    get isReadOnly() {\");\n                    expect(testDoc.getLine(164)).toBe(\"        return this.isReadOnly;\");\n                    expect(testDoc.getLine(165)).toBe(\"    },\");\n                    expect(testDoc.getLine(167)).toBe(\"    set isReadOnly(val) {\");\n                    expect(testDoc.getLine(168)).toBe(\"        this.isReadOnly = val;\");\n                    expect(testDoc.getLine(169)).toBe(\"    }\");\n                });\n            });\n        });\n    });\n});"
  },
  {
    "path": "src/extensions/default/LESSSupport/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var LanguageManager = brackets.getModule(\"language/LanguageManager\");\n\n    LanguageManager.defineLanguage(\"less\", {\n        name: \"LESS\",\n        mode: [\"css\", \"text/x-less\"],\n        fileExtensions: [\"less\"],\n        blockComment: [\"/*\", \"*/\"],\n        lineComment: [\"//\"]\n    }).done(function (lessLanguage) {\n        // Hack to make it so that when we see a \"css\" mode inside a LESS file,\n        // we know that it's really LESS. Ideally we would have a way to get the\n        // actual mime type from CodeMirror, so we know what mode configuration is\n        // in use (see #7345).\n        lessLanguage._setLanguageForMode(\"css\", lessLanguage);\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/LESSSupport/unittests.js",
    "content": "define(function (require, exports, module) {\n    \"use strict\";\n    \n    // To make sure we load this extension in order to define LESS mode for tests\n    require(\"main\");\n});"
  },
  {
    "path": "src/extensions/default/LightTheme/main.less",
    "content": "// Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n// This is the default theme and doesn't need to do anything!\n"
  },
  {
    "path": "src/extensions/default/LightTheme/package.json",
    "content": "{\n    \"title\": \"Brackets Light (Default)\",\n    \"name\": \"light-theme\",\n    \"description\": \"Built-in light theme for Brackets\",\n    \"version\": \"0.42.0\",\n    \"author\": \"Miguel Castillo <mahchagnu@gmail.com>\",\n    \"engines\": {\n        \"brackets\": \">=0.42.0\"\n    },\n    \"theme\": {\n        \"file\": \"main.less\"\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/InlineDocsViewer.html",
    "content": "<div class=\"css-prop-defn {{#fullscreenSummary}}fullscreen-summary{{/fullscreenSummary}}\" tabIndex=\"0\"> <!-- tabIndex needed: otherwise click focuses CodeMirror scroller and Esc won't work -->\n    <div class=\"css-prop-summary\">\n        <h1>{{propName}}</h1>\n        <div>{{{summary}}}</div>\n    </div>\n    <div class=\"divider-holder no-focus\">\n        <div class=\"divider\"></div>\n    </div>\n    <div class=\"css-prop-values quiet-scrollbars\">\n        <div class=\"scroller\" tabIndex=\"0\"> <!-- tabIndex needed: otherwise can't be focused on open or via click -->\n            <dl>\n                {{#propValues}}\n                <dt>{{{value}}}</dt>\n                <dd>{{{description}}}</dd>\n                {{/propValues}}\n            </dl>\n        </div>\n    </div>\n    <div class=\"content-bottom\"></div>\n    <a class=\"more-info\" href=\"{{url}}\" title=\"{{url}}\">{{Strings.DOCS_MORE_LINK}}</a>\n</div>"
  },
  {
    "path": "src/extensions/default/MDNDocs/InlineDocsViewer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Inline widget to display MDNDocs JSON data nicely formatted\n */\ndefine(function (require, exports, module) {\n    'use strict';\n\n    // Load Brackets modules\n    var Dialogs         = brackets.getModule(\"widgets/Dialogs\"),\n        ExtensionUtils  = brackets.getModule(\"utils/ExtensionUtils\"),\n        InlineWidget    = brackets.getModule(\"editor/InlineWidget\").InlineWidget,\n        KeyEvent        = brackets.getModule(\"utils/KeyEvent\"),\n        Strings         = brackets.getModule(\"strings\"),\n        Mustache        = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        HealthLogger    = brackets.getModule(\"utils/HealthLogger\");\n\n    // Load template\n    var inlineEditorTemplate = require(\"text!InlineDocsViewer.html\");\n\n    // Lines height for scrolling\n    var SCROLL_LINE_HEIGHT = 40;\n\n    // Load CSS\n    ExtensionUtils.loadStyleSheet(module, \"MDNDocs.less\");\n\n\n    /**\n     * @param {!string} cssPropName\n     * @param {!{SUMMARY:string, URL:string, VALUES:?Array.<{value:string, description:string}>}} cssPropDetails\n     */\n    function InlineDocsViewer(PropName, PropDetails) {\n        InlineWidget.call(this);\n\n        var templateVars = {\n            propName            : PropName,\n            summary             : PropDetails.SUMMARY,\n            fullscreenSummary   : !(PropDetails.VALUES && PropDetails.VALUES.length),\n            propValues          : PropDetails.VALUES || [],\n            url                 : PropDetails.URL,\n            Strings             : Strings\n        };\n\n        var html = Mustache.render(inlineEditorTemplate, templateVars);\n\n        this.$wrapperDiv = $(html);\n        this.$htmlContent.append(this.$wrapperDiv);\n\n        Dialogs.addLinkTooltips(this.$wrapperDiv);\n\n        this._sizeEditorToContent   = this._sizeEditorToContent.bind(this);\n        this._handleWheelScroll     = this._handleWheelScroll.bind(this);\n\n        this.$scroller = this.$wrapperDiv.find(\".scroller\");\n        this.$scroller.on(\"mousewheel\", this._handleWheelScroll);\n        this.$moreinfo = this.$wrapperDiv.find(\".more-info\");\n        this.$moreinfo.on(\"click\", this._logAnalyticsData);\n        this._onKeydown = this._onKeydown.bind(this);\n    }\n\n    InlineDocsViewer.prototype = Object.create(InlineWidget.prototype);\n    InlineDocsViewer.prototype.constructor = InlineDocsViewer;\n    InlineDocsViewer.prototype.parentClass = InlineWidget.prototype;\n\n    InlineDocsViewer.prototype.$wrapperDiv = null;\n    InlineDocsViewer.prototype.$scroller = null;\n\n    /**\n     * Handle scrolling.\n     *\n     * @param {Event} event Keyboard event or mouse scrollwheel event\n     * @param {boolean} scrollingUp Is event to scroll up?\n     * @param {DOMElement} scroller Element to scroll\n     * @return {boolean} indication whether key was handled\n     */\n    InlineDocsViewer.prototype._handleScrolling = function (event, scrollingUp, scroller) {\n        // We need to block the event from both the host CodeMirror code (by stopping bubbling) and the\n        // browser's native behavior (by preventing default). We preventDefault() *only* when the docs\n        // scroller is at its limit (when an ancestor would get scrolled instead); otherwise we'd block\n        // normal scrolling of the docs themselves.\n        event.stopPropagation();\n        if (scrollingUp && scroller.scrollTop === 0) {\n            event.preventDefault();\n            return true;\n        } else if (!scrollingUp && scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight) {\n            event.preventDefault();\n            return true;\n        }\n\n        return false;\n    };\n\n    /** Don't allow scrollwheel/trackpad to bubble up to host editor - makes scrolling docs painful */\n    InlineDocsViewer.prototype._handleWheelScroll = function (event) {\n        var scrollingUp = (event.originalEvent.wheelDeltaY > 0),\n            scroller = event.currentTarget;\n\n        // If content has no scrollbar, let host editor scroll normally\n        if (scroller.clientHeight >= scroller.scrollHeight) {\n            return;\n        }\n\n        this._handleScrolling(event, scrollingUp, scroller);\n    };\n\n\n    /**\n     * Convert keydown events into navigation actions.\n     *\n     * @param {KeyboardEvent} event\n     * @return {boolean} indication whether key was handled\n     */\n    InlineDocsViewer.prototype._onKeydown = function (event) {\n        var keyCode  = event.keyCode,\n            scroller = this.$scroller[0],\n            scrollPos;\n\n        // Ignore key events with modifier keys\n        if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n            return false;\n        }\n\n        // Handle keys that we're interested in\n        scrollPos = scroller.scrollTop;\n\n        switch (keyCode) {\n        case KeyEvent.DOM_VK_UP:\n            scrollPos = Math.max(0, scrollPos - SCROLL_LINE_HEIGHT);\n            break;\n        case KeyEvent.DOM_VK_PAGE_UP:\n            scrollPos = Math.max(0, scrollPos - scroller.clientHeight);\n            break;\n        case KeyEvent.DOM_VK_DOWN:\n            scrollPos = Math.min(scroller.scrollHeight - scroller.clientHeight,\n                                 scrollPos + SCROLL_LINE_HEIGHT);\n            break;\n        case KeyEvent.DOM_VK_PAGE_DOWN:\n            scrollPos = Math.min(scroller.scrollHeight - scroller.clientHeight,\n                                 scrollPos + scroller.clientHeight);\n            break;\n        default:\n            // Ignore other keys\n            return false;\n        }\n\n        scroller.scrollTop = scrollPos;\n\n        // Disallow further processing\n        event.stopPropagation();\n        event.preventDefault();\n        return true;\n    };\n\n    InlineDocsViewer.prototype.onAdded = function () {\n        InlineDocsViewer.prototype.parentClass.onAdded.apply(this, arguments);\n\n        // Set height initially, and again whenever width might have changed (word wrap)\n        this._sizeEditorToContent();\n        $(window).on(\"resize\", this._sizeEditorToContent);\n\n        // Set focus\n        this.$scroller[0].focus();\n        this.$wrapperDiv[0].addEventListener(\"keydown\", this._onKeydown, true);\n    };\n\n    InlineDocsViewer.prototype.onClosed = function () {\n        InlineDocsViewer.prototype.parentClass.onClosed.apply(this, arguments);\n\n        $(window).off(\"resize\", this._sizeEditorToContent);\n        this.$wrapperDiv[0].removeEventListener(\"keydown\", this._onKeydown, true);\n    };\n\n    InlineDocsViewer.prototype._sizeEditorToContent = function () {\n        this.hostEditor.setInlineWidgetHeight(this, this.$wrapperDiv.height() + 20, true);\n    };\n    \n    /**\n     * Send analytics data for Quick Doc \"readMore\" action\n     *\n     * @return {boolean} false\n     */\n    InlineDocsViewer.prototype._logAnalyticsData = function () {\n        HealthLogger.sendAnalyticsData(\n            \"QuickDocReadMore\",\n            \"usage\",\n            \"quickDoc\",\n            \"readMore\"\n        );\n        return false;\n    };\n\n\n    module.exports = InlineDocsViewer;\n});\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/LICENSE",
    "content": "The following files are licensed under the \"Creative Commons Attribution\n(CC-BY)\" license:\n\n    * css.json\n    * logo.svg\n\n\nThe license is as follows:\n==============================================================================\n\nCreative Commons Legal Code\n\nAttribution 3.0 Unported\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN\n    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS\n    INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES\n    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR\n    DAMAGES RESULTING FROM ITS USE.\n\nLicense\n\nTHE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE\nCOMMONS PUBLIC LICENSE (\"CCPL\" OR \"LICENSE\"). THE WORK IS PROTECTED BY\nCOPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS\nAUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.\n\nBY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE\nTO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY\nBE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS\nCONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND\nCONDITIONS.\n\n1. Definitions\n\n a. \"Adaptation\" means a work based upon the Work, or upon the Work and\n    other pre-existing works, such as a translation, adaptation,\n    derivative work, arrangement of music or other alterations of a\n    literary or artistic work, or phonogram or performance and includes\n    cinematographic adaptations or any other form in which the Work may be\n    recast, transformed, or adapted including in any form recognizably\n    derived from the original, except that a work that constitutes a\n    Collection will not be considered an Adaptation for the purpose of\n    this License. For the avoidance of doubt, where the Work is a musical\n    work, performance or phonogram, the synchronization of the Work in\n    timed-relation with a moving image (\"synching\") will be considered an\n    Adaptation for the purpose of this License.\n b. \"Collection\" means a collection of literary or artistic works, such as\n    encyclopedias and anthologies, or performances, phonograms or\n    broadcasts, or other works or subject matter other than works listed\n    in Section 1(f) below, which, by reason of the selection and\n    arrangement of their contents, constitute intellectual creations, in\n    which the Work is included in its entirety in unmodified form along\n    with one or more other contributions, each constituting separate and\n    independent works in themselves, which together are assembled into a\n    collective whole. A work that constitutes a Collection will not be\n    considered an Adaptation (as defined above) for the purposes of this\n    License.\n c. \"Distribute\" means to make available to the public the original and\n    copies of the Work or Adaptation, as appropriate, through sale or\n    other transfer of ownership.\n d. \"Licensor\" means the individual, individuals, entity or entities that\n    offer(s) the Work under the terms of this License.\n e. \"Original Author\" means, in the case of a literary or artistic work,\n    the individual, individuals, entity or entities who created the Work\n    or if no individual or entity can be identified, the publisher; and in\n    addition (i) in the case of a performance the actors, singers,\n    musicians, dancers, and other persons who act, sing, deliver, declaim,\n    play in, interpret or otherwise perform literary or artistic works or\n    expressions of folklore; (ii) in the case of a phonogram the producer\n    being the person or legal entity who first fixes the sounds of a\n    performance or other sounds; and, (iii) in the case of broadcasts, the\n    organization that transmits the broadcast.\n f. \"Work\" means the literary and/or artistic work offered under the terms\n    of this License including without limitation any production in the\n    literary, scientific and artistic domain, whatever may be the mode or\n    form of its expression including digital form, such as a book,\n    pamphlet and other writing; a lecture, address, sermon or other work\n    of the same nature; a dramatic or dramatico-musical work; a\n    choreographic work or entertainment in dumb show; a musical\n    composition with or without words; a cinematographic work to which are\n    assimilated works expressed by a process analogous to cinematography;\n    a work of drawing, painting, architecture, sculpture, engraving or\n    lithography; a photographic work to which are assimilated works\n    expressed by a process analogous to photography; a work of applied\n    art; an illustration, map, plan, sketch or three-dimensional work\n    relative to geography, topography, architecture or science; a\n    performance; a broadcast; a phonogram; a compilation of data to the\n    extent it is protected as a copyrightable work; or a work performed by\n    a variety or circus performer to the extent it is not otherwise\n    considered a literary or artistic work.\n g. \"You\" means an individual or entity exercising rights under this\n    License who has not previously violated the terms of this License with\n    respect to the Work, or who has received express permission from the\n    Licensor to exercise rights under this License despite a previous\n    violation.\n h. \"Publicly Perform\" means to perform public recitations of the Work and\n    to communicate to the public those public recitations, by any means or\n    process, including by wire or wireless means or public digital\n    performances; to make available to the public Works in such a way that\n    members of the public may access these Works from a place and at a\n    place individually chosen by them; to perform the Work to the public\n    by any means or process and the communication to the public of the\n    performances of the Work, including by public digital performance; to\n    broadcast and rebroadcast the Work by any means including signs,\n    sounds or images.\n i. \"Reproduce\" means to make copies of the Work by any means including\n    without limitation by sound or visual recordings and the right of\n    fixation and reproducing fixations of the Work, including storage of a\n    protected performance or phonogram in digital form or other electronic\n    medium.\n\n2. Fair Dealing Rights. Nothing in this License is intended to reduce,\nlimit, or restrict any uses free from copyright or rights arising from\nlimitations or exceptions that are provided for in connection with the\ncopyright protection under copyright law or other applicable laws.\n\n3. License Grant. Subject to the terms and conditions of this License,\nLicensor hereby grants You a worldwide, royalty-free, non-exclusive,\nperpetual (for the duration of the applicable copyright) license to\nexercise the rights in the Work as stated below:\n\n a. to Reproduce the Work, to incorporate the Work into one or more\n    Collections, and to Reproduce the Work as incorporated in the\n    Collections;\n b. to create and Reproduce Adaptations provided that any such Adaptation,\n    including any translation in any medium, takes reasonable steps to\n    clearly label, demarcate or otherwise identify that changes were made\n    to the original Work. For example, a translation could be marked \"The\n    original work was translated from English to Spanish,\" or a\n    modification could indicate \"The original work has been modified.\";\n c. to Distribute and Publicly Perform the Work including as incorporated\n    in Collections; and,\n d. to Distribute and Publicly Perform Adaptations.\n e. For the avoidance of doubt:\n\n     i. Non-waivable Compulsory License Schemes. In those jurisdictions in\n        which the right to collect royalties through any statutory or\n        compulsory licensing scheme cannot be waived, the Licensor\n        reserves the exclusive right to collect such royalties for any\n        exercise by You of the rights granted under this License;\n    ii. Waivable Compulsory License Schemes. In those jurisdictions in\n        which the right to collect royalties through any statutory or\n        compulsory licensing scheme can be waived, the Licensor waives the\n        exclusive right to collect such royalties for any exercise by You\n        of the rights granted under this License; and,\n   iii. Voluntary License Schemes. The Licensor waives the right to\n        collect royalties, whether individually or, in the event that the\n        Licensor is a member of a collecting society that administers\n        voluntary licensing schemes, via that society, from any exercise\n        by You of the rights granted under this License.\n\nThe above rights may be exercised in all media and formats whether now\nknown or hereafter devised. The above rights include the right to make\nsuch modifications as are technically necessary to exercise the rights in\nother media and formats. Subject to Section 8(f), all rights not expressly\ngranted by Licensor are hereby reserved.\n\n4. Restrictions. The license granted in Section 3 above is expressly made\nsubject to and limited by the following restrictions:\n\n a. You may Distribute or Publicly Perform the Work only under the terms\n    of this License. You must include a copy of, or the Uniform Resource\n    Identifier (URI) for, this License with every copy of the Work You\n    Distribute or Publicly Perform. You may not offer or impose any terms\n    on the Work that restrict the terms of this License or the ability of\n    the recipient of the Work to exercise the rights granted to that\n    recipient under the terms of the License. You may not sublicense the\n    Work. You must keep intact all notices that refer to this License and\n    to the disclaimer of warranties with every copy of the Work You\n    Distribute or Publicly Perform. When You Distribute or Publicly\n    Perform the Work, You may not impose any effective technological\n    measures on the Work that restrict the ability of a recipient of the\n    Work from You to exercise the rights granted to that recipient under\n    the terms of the License. This Section 4(a) applies to the Work as\n    incorporated in a Collection, but this does not require the Collection\n    apart from the Work itself to be made subject to the terms of this\n    License. If You create a Collection, upon notice from any Licensor You\n    must, to the extent practicable, remove from the Collection any credit\n    as required by Section 4(b), as requested. If You create an\n    Adaptation, upon notice from any Licensor You must, to the extent\n    practicable, remove from the Adaptation any credit as required by\n    Section 4(b), as requested.\n b. If You Distribute, or Publicly Perform the Work or any Adaptations or\n    Collections, You must, unless a request has been made pursuant to\n    Section 4(a), keep intact all copyright notices for the Work and\n    provide, reasonable to the medium or means You are utilizing: (i) the\n    name of the Original Author (or pseudonym, if applicable) if supplied,\n    and/or if the Original Author and/or Licensor designate another party\n    or parties (e.g., a sponsor institute, publishing entity, journal) for\n    attribution (\"Attribution Parties\") in Licensor's copyright notice,\n    terms of service or by other reasonable means, the name of such party\n    or parties; (ii) the title of the Work if supplied; (iii) to the\n    extent reasonably practicable, the URI, if any, that Licensor\n    specifies to be associated with the Work, unless such URI does not\n    refer to the copyright notice or licensing information for the Work;\n    and (iv) , consistent with Section 3(b), in the case of an Adaptation,\n    a credit identifying the use of the Work in the Adaptation (e.g.,\n    \"French translation of the Work by Original Author,\" or \"Screenplay\n    based on original Work by Original Author\"). The credit required by\n    this Section 4 (b) may be implemented in any reasonable manner;\n    provided, however, that in the case of a Adaptation or Collection, at\n    a minimum such credit will appear, if a credit for all contributing\n    authors of the Adaptation or Collection appears, then as part of these\n    credits and in a manner at least as prominent as the credits for the\n    other contributing authors. For the avoidance of doubt, You may only\n    use the credit required by this Section for the purpose of attribution\n    in the manner set out above and, by exercising Your rights under this\n    License, You may not implicitly or explicitly assert or imply any\n    connection with, sponsorship or endorsement by the Original Author,\n    Licensor and/or Attribution Parties, as appropriate, of You or Your\n    use of the Work, without the separate, express prior written\n    permission of the Original Author, Licensor and/or Attribution\n    Parties.\n c. Except as otherwise agreed in writing by the Licensor or as may be\n    otherwise permitted by applicable law, if You Reproduce, Distribute or\n    Publicly Perform the Work either by itself or as part of any\n    Adaptations or Collections, You must not distort, mutilate, modify or\n    take other derogatory action in relation to the Work which would be\n    prejudicial to the Original Author's honor or reputation. Licensor\n    agrees that in those jurisdictions (e.g. Japan), in which any exercise\n    of the right granted in Section 3(b) of this License (the right to\n    make Adaptations) would be deemed to be a distortion, mutilation,\n    modification or other derogatory action prejudicial to the Original\n    Author's honor and reputation, the Licensor will waive or not assert,\n    as appropriate, this Section, to the fullest extent permitted by the\n    applicable national law, to enable You to reasonably exercise Your\n    right under Section 3(b) of this License (right to make Adaptations)\n    but not otherwise.\n\n5. Representations, Warranties and Disclaimer\n\nUNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR\nOFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY\nKIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,\nINCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,\nFITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF\nLATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,\nWHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION\nOF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.\n\n6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE\nLAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR\nANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES\nARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS\nBEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n7. Termination\n\n a. This License and the rights granted hereunder will terminate\n    automatically upon any breach by You of the terms of this License.\n    Individuals or entities who have received Adaptations or Collections\n    from You under this License, however, will not have their licenses\n    terminated provided such individuals or entities remain in full\n    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will\n    survive any termination of this License.\n b. Subject to the above terms and conditions, the license granted here is\n    perpetual (for the duration of the applicable copyright in the Work).\n    Notwithstanding the above, Licensor reserves the right to release the\n    Work under different license terms or to stop distributing the Work at\n    any time; provided, however that any such election will not serve to\n    withdraw this License (or any other license that has been, or is\n    required to be, granted under the terms of this License), and this\n    License will continue in full force and effect unless terminated as\n    stated above.\n\n8. Miscellaneous\n\n a. Each time You Distribute or Publicly Perform the Work or a Collection,\n    the Licensor offers to the recipient a license to the Work on the same\n    terms and conditions as the license granted to You under this License.\n b. Each time You Distribute or Publicly Perform an Adaptation, Licensor\n    offers to the recipient a license to the original Work on the same\n    terms and conditions as the license granted to You under this License.\n c. If any provision of this License is invalid or unenforceable under\n    applicable law, it shall not affect the validity or enforceability of\n    the remainder of the terms of this License, and without further action\n    by the parties to this agreement, such provision shall be reformed to\n    the minimum extent necessary to make such provision valid and\n    enforceable.\n d. No term or provision of this License shall be deemed waived and no\n    breach consented to unless such waiver or consent shall be in writing\n    and signed by the party to be charged with such waiver or consent.\n e. This License constitutes the entire agreement between the parties with\n    respect to the Work licensed here. There are no understandings,\n    agreements or representations with respect to the Work not specified\n    here. Licensor shall not be bound by any additional provisions that\n    may appear in any communication from You. This License may not be\n    modified without the mutual written agreement of the Licensor and You.\n f. The rights granted under, and the subject matter referenced, in this\n    License were drafted utilizing the terminology of the Berne Convention\n    for the Protection of Literary and Artistic Works (as amended on\n    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright\n    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996\n    and the Universal Copyright Convention (as revised on July 24, 1971).\n    These rights and subject matter take effect in the relevant\n    jurisdiction in which the License terms are sought to be enforced\n    according to the corresponding provisions of the implementation of\n    those treaty provisions in the applicable national law. If the\n    standard suite of rights granted under applicable copyright law\n    includes additional rights not granted under this License, such\n    additional rights are deemed to be included in the License; this\n    License is not intended to restrict the license of any rights under\n    applicable law.\n\n\nCreative Commons Notice\n\n    Creative Commons is not a party to this License, and makes no warranty\n    whatsoever in connection with the Work. Creative Commons will not be\n    liable to You or any party on any legal theory for any damages\n    whatsoever, including without limitation any general, special,\n    incidental or consequential damages arising in connection to this\n    license. Notwithstanding the foregoing two (2) sentences, if Creative\n    Commons has expressly identified itself as the Licensor hereunder, it\n    shall have all rights and obligations of Licensor.\n\n    Except for the limited purpose of indicating to the public that the\n    Work is licensed under the CCPL, Creative Commons does not authorize\n    the use by either party of the trademark \"Creative Commons\" or any\n    related trademark or logo of Creative Commons without the prior\n    written consent of Creative Commons. Any permitted use will be in\n    compliance with Creative Commons' then-current trademark usage\n    guidelines, as may be published on its website or otherwise made\n    available upon request from time to time. For the avoidance of doubt,\n    this trademark restriction does not form part of this License.\n\n    Creative Commons may be contacted at http://creativecommons.org/.\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/MDNDocs.less",
    "content": "/* Colors */\n@bc-btn-bg: #e5e9e9;\n@bc-btn-border: #b2b5b5;\n@bc-highlight: rgba(255, 255, 255, 0.12);\n@bc-panel-separator: #c3c6c5;\n@bc-text: #333;\n@bc-text-link: #0083e8;\n@bc-text-thin-quiet: #777;\n\n/* Typography */\n@font-weight-semibold: 500;\n\n\n/* Overall inline widget content container */\n.css-prop-defn {\n    margin-left: 20px;\n    \n    color: @bc-text-thin-quiet;\n    \n    /* Enable text selection */\n    cursor: auto;\n    -webkit-user-select: text;\n    -khtml-user-select: text;\n    -moz-user-select: text;\n    -ms-user-select: text;\n    -o-user-select: text;\n    user-select: text;\n    \n    &:focus {\n        outline: none;\n    }\n    \n    font-family: SourceSansPro;\n    font-size: 14px;\n    \n    h1 {\n        color: @bc-text;\n        font-size: 16px;\n        font-weight: @font-weight-semibold;\n        line-height: normal;\n        margin: 15px 0 9px 0;\n    }\n    \n    a {\n        color: @bc-text-link;\n    }\n    \n    code {\n        font-family: SourceCodePro;\n        font-size: 12px;\n        color: @bc-text;\n        background: none;   // revert Bootstrap's styling\n        padding: 0;\n        white-space: normal;\n    }\n    \n    b {\n        font-weight: @font-weight-semibold;\n    }\n\n    table {\n        width: 100%;\n        margin-bottom: 1em;\n        th, td {\n            border: 1px solid lighten(@bc-text-thin-quiet, 20%);\n            padding: 0 .15em;\n        }\n    }\n}\n\n/* Left-hand column */\n.css-prop-summary {\n    box-sizing: border-box;\n    float: left;\n    padding-left: 20px;\n    width: 35%;\n    word-wrap: break-word;\n    -webkit-hyphens: auto;\n    hyphens: auto;\n    \n    p {\n        line-height: 18px;\n    }\n}\n\n// Used to avoid overlapping CM scrollbar - TODO (#3460): need a cleaner way to do this\n@scrollbar-wid: 17px;\n\n/* Right-hand column */\n.css-prop-values {\n    box-sizing: border-box; //for exact dimension        \n    float: right;\n    width: 60%;\n    \n    .scroller {\n        max-height: 300px;\n        overflow-y: auto;\n        \n        margin: 20px (@scrollbar-wid + 4px) 0 0;\n        \n        &:focus {\n            outline: none;\n        }\n    }\n        \n    dl {\n        margin-top: 0px;\n        \n        dt {\n            color: @bc-text;\n            font-size: 13px;\n            font-weight: @font-weight-semibold;\n            margin-bottom: 3px;\n        }\n        \n        dd {\n            // some styles must specifically be on <p> to override Bootstrap\n            p, li, b {\n                font-size: 13px;\n                font-style: normal;\n                line-height: 18px;\n                margin-bottom: 15px;\n            }\n            line-height: 18px;\n            margin-left: 20px;\n            margin-right: 0px;\n            margin-bottom: -2px; // remove extra spacing between dt-dd pairs\n            padding-bottom: 0px;\n        }\n    }\n}\n\n.divider-holder {\n    // This nesting lets us effectively have 'left: (37% + 12px)'\n    position: absolute;\n    left: 37%;\n    top: 0;\n    height: 100%;\n    .divider {\n        margin-left: 12px;\n        width: 0px;\n        height: 100%;\n        border-left: 1px solid @bc-panel-separator;\n    }\n}\n\n.fullscreen-summary {\n    .css-prop-summary {\n        width: 95%;\n    }\n    \n    .css-prop-values, .divider-holder {\n        display: none;\n    }\n}\n\n.content-bottom {\n    // Used to pull bottom edge of .css-prop-defn down below its two floated children.\n    // Also prevents .more-info (after us in DOM order) from overlapping the float: right content.\n    clear: both;\n}\n\n/* Link to full docs, at bottom */\na.more-info {\n    position: absolute;\n    bottom: 0px;\n    right: (33px + @scrollbar-wid);\n    padding: 4px 10px 4px 28px;\n    \n    background: @bc-btn-bg url(\"logo.svg\");\n    background-repeat: no-repeat;\n    background-size: 15px 15px;\n    background-position: 8px 4px;\n    \n    border: 1px solid @bc-btn-border;\n    border-radius: 3px 3px 0 0;\n    border-bottom: none;\n    box-shadow: inset 0 1px 0 @bc-highlight;  // white chisel along top edge\n    \n    font-size: 12px;\n    font-weight: @font-weight-semibold;\n    color: @bc-text;\n    text-shadow: 0 1px 0 @bc-highlight;\n    &:hover {\n        text-decoration: none;\n    }\n}\n\n/* Dark UI Theme */\n@dark-bc-highlight: rgba(255, 255, 255, 0.06);\n@dark-bc-text: #ccc;\n@dark-bc-text-link: #6bbeff;\n@dark-bc-text-thin-quiet: #bbb;\n@dark-bc-btn-bg: #3f3f3f;\n@dark-bc-btn-border: #202020;\n@dark-bc-panel-separator: #343434;\n\n.dark {\n    .css-prop-defn {\n        color: @dark-bc-text-thin-quiet;\n        \n        h1, b {\n            color: @dark-bc-text;\n        }\n\n        a {\n            color: @dark-bc-text-link;\n        }\n\n        code {\n            color: @dark-bc-text;\n        }\n\n        dl dt {\n            color: @dark-bc-text;\n        }\n\n        .divider-holder .divider {\n            border-left: 1px solid @dark-bc-panel-separator;\n        }\n\n        a.more-info {\n            background-color: @dark-bc-btn-bg;\n            border: 1px solid @dark-bc-btn-border;\n            box-shadow: inset 0 1px 0 @dark-bc-highlight;\n            color: @dark-bc-text;\n            text-shadow: 0 1px 0 @dark-bc-highlight;\n        }\n\n        table {\n            th, td {\n                border-color: darken(@dark-bc-text-thin-quiet, 35%);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/README.md",
    "content": "# Updating the Docs\n* Use the Node script [scrape-mdn](https://github.com/mozilla/brackets/tree/master/src/extensions/extra/MDNDocs/tools/scrape-mdn) to update the `css.json` and `html.json` contents:\n* Both the JSON files will have URL and Summary, but for css.json we need to have possible values of each css property along with small description, so use this Node script [MDNDocsScrapper](https://github.com/saurabh95/MDNDocsScrapper), this takes css.json as input and then creates a newcss.json with the desired content.\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/css.json",
    "content": "{\n    \"-moz-appearance (-webkit-appearance, appearance)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-appearance\",\n        \"SUMMARY\": \"The <code>-moz-appearance</code> CSS property is used in Gecko (Firefox) to display an element using a platform-native styling based on the operating system's theme.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"<code>&lt;appearance&gt;</code> is one of the following keywords:\"\n        }]\n    },\n    \"-moz-binding\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding\",\n        \"SUMMARY\": \"The <code>-moz-binding</code> CSS property is used by Mozilla-based applications to attach an <a href=\\\"https://developer.mozilla.org/en-US/docs/XBL\\\">XBL</a> binding to a DOM element.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;uri&gt;\",\n            \"description\": \"The URI for the XBL binding (including the fragment identifier).\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No XBL binding is applied to the element.\"\n        }]\n    },\n    \"-moz-border-bottom-colors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-bottom-colors\",\n        \"SUMMARY\": \"In Mozilla applications like Firefox, the <code>-moz-border-bottom-colors</code> CSS property sets a list of colors for the bottom border.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Specifies the color of a line of pixels of the bottom border. <code>transparent</code> is valid. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> values for possible units.\"\n        }, {\n            \"value\": \"none\",\n            \"description\": \"Default, no colors are drawn or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a> is used, if specified.\"\n        }]\n    },\n    \"-moz-border-left-colors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-left-colors\",\n        \"SUMMARY\": \"In Mozilla applications like Firefox, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-left-colors\\\" title=\\\"In Mozilla applications like Firefox, the -moz-border-left-colors CSS property sets a list of colors for the left border.\\\"><code>-moz-border-left-colors</code></a> CSS property sets a list of colors for the left border.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Specifies the color of a line of pixels of the left border. <code>transparent</code> is valid. See <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\"><code>&lt;color&gt;</code></a> values for possible units.\"\n        }, {\n            \"value\": \"none\",\n            \"description\": \"Default, no colors are drawn or <a title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\"><code>border-color</code></a> is used, if specified.\"\n        }]\n    },\n    \"-moz-border-right-colors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-right-colors\",\n        \"SUMMARY\": \"In Mozilla applications like Firefox, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-right-colors\\\" title=\\\"In Mozilla applications like Firefox, the -moz-border-right-colors CSS property sets a list of colors for the right border.\\\"><code>-moz-border-right-colors</code></a> CSS property sets a list of colors for the right border.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Specifies the color of a line of pixels of the right border. <code>transparent</code> is valid. See <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\"><code>&lt;color&gt;</code></a> values for possible units.\"\n        }, {\n            \"value\": \"none\",\n            \"description\": \"Default, no colors are drawn or <a title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\"><code>border-color</code></a> is used, if specified.\"\n        }]\n    },\n    \"-moz-border-top-colors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-top-colors\",\n        \"SUMMARY\": \"In Mozilla applications like Firefox, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-top-colors\\\" title=\\\"In Mozilla applications like Firefox, the -moz-border-top-colors CSS property sets a list of colors for the top border.\\\"><code>-moz-border-top-colors</code></a> CSS property sets a list of colors for the top border.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Specifies the color of a line of pixels of the top border. <code>transparent</code> is valid. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> values for possible units.\"\n        }, {\n            \"value\": \"none\",\n            \"description\": \"Default, no colors are drawn or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a> is used, if specified.\"\n        }]\n    },\n    \"-moz-box-ordinal-group\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-box-ordinal-group\",\n        \"SUMMARY\": \"Indicates the ordinal group the element belongs to. Elements with a lower ordinal group are displayed before those with a higher ordinal group.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"Values must be integers greater than zero. The default value for this property is 1.\"\n        }]\n    },\n    \"-moz-cell\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-cell\",\n        \"SUMMARY\": \"<em>Don't use this value! </em> Use the <code>cursor</code> value <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#cell\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>cell</code></a> instead.\",\n        \"VALUES\": []\n    },\n    \"-moz-float-edge\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-float-edge\",\n        \"SUMMARY\": \"The non-standard <strong><code>-moz-float-edge</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies whether the height and width properties of the element include the margin, border, or padding thickness.\",\n        \"VALUES\": [{\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"The height and width properties include the content, padding and border but not the margin.\"\n        }, {\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"The height and width properties include the content, but not the padding, border or margin.\"\n        }, {\n            \"value\": \"<code>margin-box</code>\",\n            \"description\": \"The height and width properties include the content, padding, border and margin.\"\n        }, {\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"The height and width properties include the content and padding but not the border or margin.\"\n        }]\n    },\n    \"-moz-force-broken-image-icon\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-force-broken-image-icon\",\n        \"SUMMARY\": \"<code>-moz-force-broken-image-icon</code> is an extended CSS property. The value <code>1</code> forces a broken image icon even if the image has an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-alt\\\" title=\\\"The HTML &lt;img&gt; element represents an image in the document.\\\"><code>alt</code></a> attribute. When the value <code>0</code> is used the image will act as usual and only display the <code>alt</code> attribute.\",\n        \"VALUES\": [{\n            \"value\": \"<a title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\"><code>&lt;integer&gt;</code></a>\",\n            \"description\": \"A value of <code>1</code> means that the broken image icon is even shown if the image has an <a title=\\\"The HTML &lt;img&gt; element represents an image in the document.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-alt\\\"><code>alt</code></a> attribute. A value of <code>0</code> only displays the <code>alt</code> attribute.\"\n        }]\n    },\n    \"-moz-image-rect\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-rect\",\n        \"SUMMARY\": \"This value for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"The CSS background-image property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\\\"><code>background-image</code></a> lets you use a portion of a larger image as a background. This allows you to, for example, use different parts of one larger image as backgrounds in different parts of your content.\",\n        \"VALUES\": [{\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/uri\\\"><code>&lt;uri&gt;</code></a>\",\n            \"description\": \"The URI of the image from which to take the sub-image.\"\n        }, {\n            \"value\": \"<code>top</code>\",\n            \"description\": \"The top edge, specified as a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a>, of the sub-image within the specified image.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The right edge, specified as a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a>, of the sub-image within the specified image.\"\n        }, {\n            \"value\": \"<code>bottom</code>\",\n            \"description\": \"The bottom edge, specified as a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a>, of the sub-image within the specified image.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The left edge, specified as a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a>, of the sub-image within the specified image.\"\n        }]\n    },\n    \"-moz-image-region\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region\",\n        \"SUMMARY\": \"For certain XUL elements and pseudo-elements that use an image from the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-image\\\" title=\\\"The list-style-image property specifies an image to be used as the list item marker.\\\"><code>list-style-image</code></a> property, this property specifies a region of the image that is used in place of the whole image. This allows elements to use different pieces of the same image to improve performance.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Automatically defines the region of the image to use.\"\n        }, {\n            \"value\": \"<code>&lt;shape&gt;</code>\",\n            \"description\": \"A shape defining the part of the image to use. The <code>rect()</code> function defines a rectangle to use as shape. Its parameters define the top, right, bottom, and left offsets of the edges of the image, in this order.\"\n        }]\n    },\n    \"-moz-orient\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient\",\n        \"SUMMARY\": \"The <code>-moz-orient</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the orientation of the element to which it's applied.\",\n        \"VALUES\": [{\n            \"value\": \"<code>inline</code>\",\n            \"description\": \"The element is rendered in the same direction as the axis of the text: horizontally for horizontal writing modes, vertically for vertical writing modes.\"\n        }, {\n            \"value\": \"<code>block</code>\",\n            \"description\": \"The element is rendered orthogonally to the axis of the text: vertically for horizontal writing modes, horizontal for vertical writing modes.\"\n        }, {\n            \"value\": \"<code>horizontal</code>\",\n            \"description\": \"The element is rendered horizontally.\"\n        }, {\n            \"value\": \"<code>vertical</code>\",\n            \"description\": \"The element is rendered vertically.\"\n        }]\n    },\n    \"-moz-outline-radius\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius\",\n        \"SUMMARY\": \"In Mozilla applications like Firefox, the <code>-moz-outline-radius</code> CSS property can be used to give outlines rounded corners. An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline\\\" title=\\\"The CSS outline property is a shorthand property for setting one or more of the individual outline properties outline-style, outline-width and outline-color in a single declaration. In most cases the use of this shortcut is preferable and more convenient.\\\"><code>outline</code></a> is a line that is drawn around elements, outside the border edge, to make the element stand out.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;length&gt;\",\n            \"description\": \"See <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> for possible values.\"\n        }, {\n            \"value\": \"&lt;percentage&gt;\",\n            \"description\": \"A <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a>; see <a title=\\\"The border-radius CSS property allows Web authors to define how rounded border corners are. The curve of each corner is defined using one or two radii, defining its shape: circle or ellipse.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius\\\"><code>border-radius</code></a> for details.\"\n        }]\n    },\n    \"-moz-outline-radius-bottomleft\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius-bottomleft\",\n        \"SUMMARY\": \"The <code>-moz-outline-radius-bottomleft</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property sets the rounding of the bottom-left corner of the outline within Mozilla applications.\",\n        \"VALUES\": []\n    },\n    \"-moz-outline-radius-bottomright\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius-bottomright\",\n        \"SUMMARY\": \"The <code>-moz-outline-radius-bottomright</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property sets the rounding of the bottom-right corner of the outline within Mozilla applications.\",\n        \"VALUES\": []\n    },\n    \"-moz-outline-radius-topleft\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius-topleft\",\n        \"SUMMARY\": \"The <code>-moz-outline-radius-topleft</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property sets the rounding of the top-left corner of the outline within Mozilla applications.\",\n        \"VALUES\": []\n    },\n    \"-moz-outline-radius-topright\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius-topright\",\n        \"SUMMARY\": \"The <code>-moz-outline-radius-topright</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property sets the rounding of the top-right corner of the outline within Mozilla applications.\",\n        \"VALUES\": []\n    },\n    \"-moz-stack-sizing\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-stack-sizing\",\n        \"SUMMARY\": \"<code>-moz-stack-sizing</code> is an extended CSS property. Normally, a <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/stack\\\" title=\\\"stack\\\">stack</a></code> will change its size so that all of its child elements are completely visible. For example, moving a child of the stack far to the right will widen the stack so the child remains visible.\",\n        \"VALUES\": [{\n            \"value\": \"stretch-to-fit\",\n            \"description\": \"The child will influence the stack&apos;s size.\"\n        }, {\n            \"value\": \"ignore\",\n            \"description\": \"The stack won&apos;t consider this child when calculating the its size.\"\n        }]\n    },\n    \"-moz-text-blink\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-text-blink\",\n        \"SUMMARY\": \"The <code>-moz-text-blink</code> non-standard Mozilla CSS extension specifies the blink mode.\",\n        \"VALUES\": [{\n            \"value\": \"none\",\n            \"description\": \"Produces no blinking.\"\n        }, {\n            \"value\": \"blink\",\n            \"description\": \"Text blinks. Note that <em>not</em> blinking the text is one technique to satisfy <a href=\\\"http://www.w3.org/TR/UAAG/guidelines.html#tech-on-off-blinking-text\\\" rel=\\\"external nofollow\\\" class=\\\"external\\\" title=\\\"http://www.w3.org/TR/UAAG/guidelines.html#tech-on-off-blinking-text\\\">checkpoint 3.3 of WAI-UAAG</a>.\"\n        }]\n    },\n    \"-moz-user-focus\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus\",\n        \"SUMMARY\": \"The <code>-moz-user-focus</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property is used to indicate whether the element can have the focus.\",\n        \"VALUES\": [{\n            \"value\": \"<code>ignore</code>\",\n            \"description\": \"The element does not accept the keyboard focus and will be skipped in the tab order.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The element can accept the keyboard focus.\"\n        }, {\n            \"value\": \"<code>select-after</code>\",\n            \"description\": \"?\"\n        }, {\n            \"value\": \"<code>select-before</code>\",\n            \"description\": \"?\"\n        }, {\n            \"value\": \"<code>select-menu</code>\",\n            \"description\": \"?\"\n        }, {\n            \"value\": \"<code>select-same</code>\",\n            \"description\": \"?\"\n        }, {\n            \"value\": \"<code>select-all</code>\",\n            \"description\": \"?\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"?\"\n        }]\n    },\n    \"-moz-user-input\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input\",\n        \"SUMMARY\": \"In Mozilla applications, <code>-moz-user-input</code> determines if an element will accept user input. A similar property <code>user-focus</code> was proposed in <a href=\\\"http://www.w3.org/TR/2000/WD-css3-userint-20000216\\\" class=\\\"external\\\">early drafts of a predecessor of the CSS3 UI specification</a> but was rejected by the working group.\",\n        \"VALUES\": [{\n            \"value\": \"none\",\n            \"description\": \"The element does not respond to user input, and it does not become <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:active\\\" title=\\\"The :active CSS pseudo-class matches when an element is being activated by the user. It allows the page to give a feedback that the activation has been detected by the browser. When interacting with a mouse, this is typically the time between the user presses the mouse button and releases it. The :active pseudo-class is also typically matched when using the keyboard tab key. It is frequently used on &lt;a&gt; and &lt;button&gt; HTML&#xA0;elements, but may not be limited to just those.\\\"><code>:active</code></a>.\"\n        }, {\n            \"value\": \"enabled\",\n            \"description\": \"The element accepts user input. For textboxes, this is the default behavior.\"\n        }, {\n            \"value\": \"disabled\",\n            \"description\": \"The element does not accept user input. However, this is not the same as setting <code id=\\\"a-disabled\\\"><a href=\\\"https://developer.mozilla.org/en-US/docs/XUL/Attribute/disabled\\\">disabled</a></code> to true, in that the element is drawn normally.\"\n        }]\n    },\n    \"-moz-user-modify\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify\",\n        \"SUMMARY\": \"The <code>-moz-user-modify</code> property has no effect.\",\n        \"VALUES\": [{\n            \"value\": \"read-only\",\n            \"description\": \"Default value. Contents are read-only.\"\n        }, {\n            \"value\": \"read-write\",\n            \"description\": \"The user is able to read and write contents.\"\n        }, {\n            \"value\": \"write-only\",\n            \"description\": \"The user is able to edit the content, but not to read it.\"\n        }]\n    },\n    \"-moz-window-shadow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-window-shadow\",\n        \"SUMMARY\": \"The <code>-moz-window-shadow</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies whether a window will have a shadow. It only works on Mac OS X.\",\n        \"VALUES\": [{\n            \"value\": \"default\",\n            \"description\": \"The window will have a shadow with the default window shadow style.\"\n        }, {\n            \"value\": \"menu \",\n            \"description\": \"The window will have the shadow style that&apos;s appropriate for menus.\"\n        }, {\n            \"value\": \"tooltip \",\n            \"description\": \"The window will have the shadow style that&apos;s appropriate for tooltips.\"\n        }, {\n            \"value\": \"sheet \",\n            \"description\": \"The window will have the shadow style that&apos;s appropriate for sheet windows.\"\n        }, {\n            \"value\": \"none\",\n            \"description\": \"The window won&apos;t have a shadow.\"\n        }]\n    },\n    \"-ms-overflow-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-overflow-style\",\n        \"SUMMARY\": \"<strong><code>-ms-overflow-style</code></strong> is a proprietary CSS property, specific to Internet Explorer and Microsoft Edge, which controls the behavior of scrollbars when an element's content overflows.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Initial value. Same as <code>inherit</code>.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Scrollbars are never displayed, although the element can still be scrolled if the element&apos;s content overflows.\"\n        }, {\n            \"value\": \"<code>scrollbar</code>\",\n            \"description\": \"&quot;Traditional&quot; scrollbars are displayed if the element&apos;s content overflows. &quot;Traditional&quot; scrollbars don&apos;t auto-hide and never overlap the element&apos;s content. Accordingly, the dimensions of the layout area for the content are reduced by the girth of the scrollbar(s).\"\n        }, {\n            \"value\": \"<code>-ms-autohiding-scrollbar</code>\",\n            \"description\": \"Auto-hiding scrollbars are used if the element&apos;s content overflows. Auto-hiding scrollbars are displayed during scrolling or shortly after the pointer interacts with the page, and are hidden shortly after scrolling and pointer interaction stops. When they are visible, auto-hiding scrollbars overlap the element&apos;s content.\"\n        }]\n    },\n    \"-webkit-border-before\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-border-before\",\n        \"SUMMARY\": \"Technical review completed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property sets the width of the border of a box. Using the shorthand property border is often more convenient.\\\"><code>border-width</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"Technical review completed. Editorial review completed.\\\"><code>color</code></a>\"\n        }]\n    },\n    \"-webkit-box-reflect\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-box-reflect\",\n        \"SUMMARY\": \"The <code>-webkit-box-reflect</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property lets you reflect the content of an element in one specific direction.\",\n        \"VALUES\": [{\n            \"value\": \"<code>above</code><em>, </em><code>below</code><em>, </em><code>right</code><em>, </em><code>left</code>\",\n            \"description\": \"Are keywords indicating in which direction the reflection is to happen.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Indicates the size of the reflection.\"\n        }, {\n            \"value\": \"<code>&lt;image&gt;</code>\",\n            \"description\": \"Describes the mask to be applied to the reflection.\"\n        }]\n    },\n    \"-webkit-mask-attachment\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-attachment\",\n        \"SUMMARY\": \"If a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-image\\\" title=\\\"The -webkit-mask-image CSS property sets the mask image for an element. A mask image clips the visible portion of an element according to the mask image's transparency.\\\"><code>-webkit-mask-image</code></a> is specified, <code>-webkit-mask-attachment</code> determines whether the mask image's position is fixed within the viewport, or scrolls along with its containing block.\",\n        \"VALUES\": [{\n            \"value\": \"scroll\",\n            \"description\": \"If <code>scroll</code> is specified, the mask image scrolls within the viewport along with the block that contains the mask image.\"\n        }, {\n            \"value\": \"fixed\",\n            \"description\": \"If <code>fixed</code> is specified, the mask image does not scroll with its containing element, instead remaining stationary within the viewport.\"\n        }]\n    },\n    \"-webkit-mask-box-image\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image\",\n        \"SUMMARY\": \"<code>-webkit-mask-box-image</code> sets the mask image for an element's border box.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;mask-box-image&gt;\",\n            \"description\": \"<code style=\\\"font: normal normal normal 100%/normal &apos;Courier New&apos;, &apos;Andale Mono&apos;, monospace; color: inherit; font-weight: inherit;\\\"><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/uri\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;uri&gt;</code></a> | &lt;gradient&gt; | none</code>\"\n        }, {\n            \"value\": \"&lt;top&gt; &lt;right&gt; &lt;bottom&gt; &lt;left&gt;\",\n            \"description\": \"<code style=\\\"font: normal normal normal 100%/normal &apos;Courier New&apos;, &apos;Andale Mono&apos;, monospace; color: inherit; font-weight: inherit;\\\">&lt;length&gt; | &lt;percentage&gt;</code>\"\n        }, {\n            \"value\": \"&lt;x-repeat&gt; &lt;y-repeat&gt;\",\n            \"description\": \"<code style=\\\"font: normal normal normal 100%/normal &apos;Courier New&apos;, &apos;Andale Mono&apos;, monospace; color: inherit; font-weight: inherit;\\\">repeat | stretch | round</code>\"\n        }, {\n            \"value\": \"&lt;uri&gt;\",\n            \"description\": \"The location of the image resource to be used as a mask image.\"\n        }, {\n            \"value\": \"&lt;gradient&gt;\",\n            \"description\": \"A <span style=\\\"font-family: courier new;\\\">-webkit-gradient</span> function to be used as a mask image.\"\n        }, {\n            \"value\": \"none\",\n            \"description\": \"Used to specify that a border box is to have no mask image.\"\n        }, {\n            \"value\": \"&lt;length&gt;\",\n            \"description\": \"The size of the mask image&apos;s offset. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units.\"\n        }, {\n            \"value\": \"&lt;percentage&gt;\",\n            \"description\": \"The mask image&apos;s offset has a percentage value relative to the border box&apos;s corresponding dimension (width or height).\"\n        }, {\n            \"value\": \"repeat\",\n            \"description\": \"The mask image is repeated as many times as is necessary to span the border box. May include a partial image if the mask image does not divide evenly into the border box.\"\n        }, {\n            \"value\": \"stretch\",\n            \"description\": \"&#xA0;The mask image is stretched to contain the border box exactly.\"\n        }, {\n            \"value\": \"round\",\n            \"description\": \"&#xA0;The mask image is stretched somewhat and repeated such that there is no partial mask image at the end of the border box.\"\n        }]\n    },\n    \"-webkit-mask-composite\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-composite\",\n        \"SUMMARY\": \"The <strong><code>-webkit-mask-composite</code></strong> property specifies the manner in which multiple mask images applied to the same element are composited with one another.\",\n        \"VALUES\": [{\n            \"value\": \"clear\",\n            \"description\": \"Overlapping pixels in the source mask image and the destination mask image are cleared.\"\n        }, {\n            \"value\": \"copy\",\n            \"description\": \"The source mask image replaces the destination mask image.\"\n        }, {\n            \"value\": \"source-over\",\n            \"description\": \"The source mask image is rendered over the destination mask image.\"\n        }, {\n            \"value\": \"source-in\",\n            \"description\": \"Overlapping pixels in the source mask image and the destination mask image are replaced by the pixels of the source mask image; all other pixels are cleared.\"\n        }, {\n            \"value\": \"source-out\",\n            \"description\": \"Overlapping pixels in the source mask image and the destination mask image are cleared; all remaining pixels of the source mask image are rendered.\"\n        }, {\n            \"value\": \"source-atop\",\n            \"description\": \"The pixels of the destination mask image are rendered. The pixels of the source mask image are rendered only if they overlap a nontransparent portion of the destination mask image. This causes the source mask image to have no effect.\"\n        }, {\n            \"value\": \"destination-over\",\n            \"description\": \"The destination mask image is rendered over the source mask image.\"\n        }, {\n            \"value\": \"destination-in\",\n            \"description\": \"Overlapping pixels in the source mask image and the destination mask image remain the pixels of the destination mask image; all other pixels are cleared.\"\n        }, {\n            \"value\": \"destination-out\",\n            \"description\": \"Overlapping pixels in the source mask image and the destination mask image are cleared; all remaining pixels of the source mask image are rendered.\"\n        }, {\n            \"value\": \"destination-atop\",\n            \"description\": \"The pixels of the source mask image are rendered. The pixels of the destination mask image are rendered only if they overlap a nontransparent portion of the destination mask image. This causes the destination mask image to have no effect.\"\n        }, {\n            \"value\": \"xor\",\n            \"description\": \"Overlapping pixels in the source mask image and the destination mask image become fully transparent if they are both fully opaque.\"\n        }]\n    },\n    \"-webkit-mask-position-x\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-position-x\",\n        \"SUMMARY\": \"The <code>-webkit-mask-position-x</code> CSS property sets the initial horizontal position of a mask image.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"A length indicating the position of the left edge of the image relative to the box&apos;s left padding edge. Percentages are calculated against the horizontal dimension of the box padding area. That means, a value of <code>0%</code> means the left edge of the image is aligned with the box&apos;s left padding edge and a value of <code>100%</code> means the right edge of the image is aligned with the box&apos;s right padding edge.\"\n        }, {\n            \"value\": \"<code><strong>left</strong></code>\",\n            \"description\": \"Equivalent to <code>0%</code>.\"\n        }, {\n            \"value\": \"<code><strong>center</strong></code>\",\n            \"description\": \"Equivalent to <code>50%</code>.\"\n        }, {\n            \"value\": \"<code><strong>right</strong></code>\",\n            \"description\": \"Equivalent to <code>100%</code>.\"\n        }]\n    },\n    \"-webkit-mask-position-y\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-position-y\",\n        \"SUMMARY\": \"The <code>-webkit-mask-position-y</code> CSS property sets the initial vertical position of a mask image.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"A length indicating the position of the top side of the image relative to the box&apos;s top padding edge. Percentages are calculated against the vertical dimension of the box padding area. A value of <code>0%</code> means the top edge of the image is aligned with the box&apos;s top padding edge and a value of <code>100%</code> means the bottom edge of the image is aligned with the box&apos;s bottom padding edge.\"\n        }, {\n            \"value\": \"<code><strong>top</strong></code>\",\n            \"description\": \"Equivalent to <code>0%</code>.\"\n        }, {\n            \"value\": \"<code><strong>bottom</strong></code>\",\n            \"description\": \"Equivalent to <code>100%</code>.\"\n        }, {\n            \"value\": \"<code><strong>center</strong></code>\",\n            \"description\": \"Equivalent to <code>50%</code>.\"\n        }]\n    },\n    \"-webkit-mask-repeat-x\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-repeat-x\",\n        \"SUMMARY\": \"The <code>-webkit-mask-repeat-x</code> property specifies whether and how a mask image is repeated (tiled) horizontally.\",\n        \"VALUES\": [{\n            \"value\": \"repeat\",\n            \"description\": \"The mask image is repeated both horizontally and vertically.\"\n        }, {\n            \"value\": \"no-repeat\",\n            \"description\": \"The mask image is not repeated; only one copy of the mask image is drawn. The remainder of the masked element&apos;s content is not displayed.\"\n        }, {\n            \"value\": \"repeat\",\n            \"description\": \"The mask image is repeated both horizontally and vertically.\"\n        }, {\n            \"value\": \"space\",\n            \"description\": \"The image is repeated as much as possible without clipping. The first and last images are pinned to either side of the element, and whitespace is distributed evenly between the images. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\\\" title=\\\"The mask-position CSS property sets the initial position, relative to the mask position layer defined by mask-origin for each defined mask image.\\\"><code>mask-position</code></a> property is ignored unless only one image can be displayed without clipping. The only case where clipping happens using space is when there isn&apos;t enough room to display one image.\"\n        }, {\n            \"value\": \"round\",\n            \"description\": \"As the allowed space increases in size, the repeated images will stretch (leaving no gaps) until there is room for another one to be added. When the next image is added, all of the current ones compress to allow room. Example: An image with an original width of 260px, repeated three times, might stretch until each repetition is 300px wide, and then another image will be added. They will then compress to 225px.\"\n        }]\n    },\n    \"-webkit-mask-repeat-y\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-repeat-y\",\n        \"SUMMARY\": \"The <code>-webkit-mask-repeat-y</code> property specifies whether and how a mask image is repeated (tiled) vertically.\",\n        \"VALUES\": [{\n            \"value\": \"repeat\",\n            \"description\": \"The mask image is repeated vertically.\"\n        }, {\n            \"value\": \"no-repeat\",\n            \"description\": \"The mask image is not repeated vertically; only one copy of the mask image is drawn in vertical direction. The vertical remainder of the masked element&apos;s content is not displayed.\"\n        }, {\n            \"value\": \"repeat\",\n            \"description\": \"The mask image is repeated vertically.\"\n        }, {\n            \"value\": \"space\",\n            \"description\": \"The image is repeated as much as possible without clipping. The first and last images are pinned to the top and bottom edge of the element, and whitespace is distributed evenly between the images. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\\\" title=\\\"The mask-position CSS property sets the initial position, relative to the mask position layer defined by mask-origin for each defined mask image.\\\"><code>mask-position</code></a> property is ignored unless only one image can be displayed without clipping. The only case where clipping happens using space is when there isn&apos;t enough room to display one image.\"\n        }, {\n            \"value\": \"round\",\n            \"description\": \"As the allowed vertical space increases in size, the repeated images will stretch (leaving no gaps) until there is room for another one to be added. When the next image is added, all of the current ones compress to allow room. Example: An image with an original height of 260px, repeated three times, might stretch until each repetition is 300px high, and then another image will be added. They will then compress to a height of 225px.\"\n        }]\n    },\n    \"-webkit-overflow-scrolling\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-overflow-scrolling\",\n        \"SUMMARY\": \"The <code>-webkit-overflow-scrolling</code> CSS property controls whether or not touch devices use momentum-based scrolling for the given element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Use &quot;regular&quot; scrolling, where the content immediately ceases to scroll when you remove your finger from the touchscreen.\"\n        }, {\n            \"value\": \"<code>touch</code>\",\n            \"description\": \"Use momentum-based scrolling, where the content continues to scroll for a while after finishing the scroll gesture and removing your finger from the touchscreen. The speed and duration of the continued scrolling is proportional to how vigorous the scroll gesture was. Also creates a new stacking context.\"\n        }]\n    },\n    \"-webkit-print-color-adjust\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust\",\n        \"SUMMARY\": \"The <code>-webkit-print-color-adjust</code> property is a non-standard CSS extension that can be used to force printing of background colors and images in browsers based on the WebKit engine.\",\n        \"VALUES\": [{\n            \"value\": \"<code>economy</code>\",\n            \"description\": \"Normal behavior.&#xA0; Background colors and images are only printed if the user explicitly allows it in their browser&apos;s print settings dialog.\"\n        }, {\n            \"value\": \"<code>exact</code>\",\n            \"description\": \"Background colors and images of the element to which this rule is applied are always printed, user&apos;s print settings are overridden.\"\n        }]\n    },\n    \"-webkit-tap-highlight-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-tap-highlight-color\",\n        \"SUMMARY\": \"<strong><code>-webkit-tap-highlight-color</code></strong> is a non-standard CSS property that sets the color of the highlight that appears over a link while it's being tapped. The highlighting indicates to the user that their tap is being successfully recognized, and indicates which element they're tapping on.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"A <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color value\\\" class=\\\"new\\\"><code>&lt;color value&gt;</code></a>.\"\n        }]\n    },\n    \"-webkit-text-fill-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-fill-color\",\n        \"SUMMARY\": \"The <strong><code>-webkit-text-fill-color</code></strong> CSS property specifies the fill <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\">color</a> of characters of text. If this property is not set, the value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element's text content, and its decorations. It doesn't affect any other characteristic of the element; it should really be called text-color and would have been named so, save for historical reasons and its appearance in CSS Level 1.\\\"><code>color</code></a> property is used.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"The foreground fill color of the element&apos;s text content.\"\n        }]\n    },\n    \"-webkit-text-stroke\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-stroke\",\n        \"SUMMARY\": \"The <strong><code>-webkit-text-stroke</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\">width</a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\">color</a> of strokes for text characters. This is a shorthand property for the longhand properties <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-stroke-width\\\" title=\\\"The -webkit-text-stroke-width CSS property specifies the width of the stroke for text.\\\"><code>-webkit-text-stroke-width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-stroke-color\\\" title=\\\"The -webkit-text-stroke-color CSS property specifies the stroke color of characters of text. If this property is not set, the value of the color property is used.\\\"><code>-webkit-text-stroke-color</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"The width of the stroke.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"The color of the stroke.\"\n        }]\n    },\n    \"-webkit-text-stroke-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-stroke-color\",\n        \"SUMMARY\": \"The <strong><code>-webkit-text-stroke-color</code></strong> CSS property specifies the stroke <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\">color</a> of characters of text. If this property is not set, the value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element's text content, and its decorations. It doesn't affect any other characteristic of the element; it should really be called text-color and would have been named so, save for historical reasons and its appearance in CSS Level 1.\\\"><code>color</code></a> property is used.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"The color of the stroke.\"\n        }]\n    },\n    \"-webkit-text-stroke-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-stroke-width\",\n        \"SUMMARY\": \"The <strong><code>-webkit-text-stroke-width</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the width of the stroke for text.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;line-width&gt;</code>\",\n            \"description\": \"The width of the stroke.\"\n        }]\n    },\n    \"-webkit-touch-callout\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-touch-callout\",\n        \"SUMMARY\": \"The <code>-webkit-touch-callout</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property controls the display of the default callout shown when you touch and hold a touch target.\",\n        \"VALUES\": [{\n            \"value\": \"<code>default</code>\",\n            \"description\": \"The default callout is displayed.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The callout is disabled.\"\n        }]\n    },\n    \":-moz-broken\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-broken\",\n        \"SUMMARY\": \"The <code>:-moz-broken</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches elements representing broken image links.\",\n        \"VALUES\": []\n    },\n    \":-moz-drag-over\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-drag-over\",\n        \"SUMMARY\": \"The <code>:-moz-drag-over</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> is used to edit an element when a drag-over event is called on it.\",\n        \"VALUES\": []\n    },\n    \":-moz-first-node\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-first-node\",\n        \"SUMMARY\": \"The <code>:-moz-first-node</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any element that is the first child node of some other element. It differs from <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child\\\" title=\\\"The :first-child CSS pseudo-class represents any element that is the first child element of its parent.\\\"><code>:first-child</code></a> because it does not match a first child element with (non-whitespace) text before it.\",\n        \"VALUES\": []\n    },\n    \":-moz-focusring\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-focusring\",\n        \"SUMMARY\": \"The <code>:-moz-focusring</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> is similar to the <a title=\\\"The :focus CSS pseudo-class is applied when an element has received focus, either from the user selecting it with the use of a keyboard or by activating with the mouse (e.g. a form input).\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:focus\\\"><code>:focus</code></a> pseudo-class, but it only matches an element if the element is currently focused <strong>and</strong> a focus ring or other indicator should be drawn for that element. If <code>:-moz-focusring</code> matches, then <code>:focus</code> also matches, but the converse is not always true - it depends on whether the user agent has focus ring drawing enabled and how the element was focused. Whether the user agent has focus ring drawing enabled can depend on things like the settings of the operating system the user is using, so the precise behavior of this pseudo-class can vary from platform to platform depending on each platforms' particular focus best practices (defaults) or user modified settings.\",\n        \"VALUES\": []\n    },\n    \":-moz-full-screen-ancestor\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-full-screen-ancestor\",\n        \"SUMMARY\": \"The <code>:-moz-full-screen-ancestor</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> applies to all ancestors of the full-screen element, except containing frames in parent documents, which are the full-screen element in their own documents. However, those elements' ancestors have this class applied to them.\",\n        \"VALUES\": []\n    },\n    \":-moz-handler-blocked\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-handler-blocked\",\n        \"SUMMARY\": \"<code>:-moz-handler-blocked</code> matches elements that cannot be displayed because their handlers have been blocked.\",\n        \"VALUES\": []\n    },\n    \":-moz-handler-crashed\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-handler-crashed\",\n        \"SUMMARY\": \"<code>:-moz-handler-crashed</code> matches elements that cannot be displayed because the plugin responsible for drawing them has crashed.\",\n        \"VALUES\": []\n    },\n    \":-moz-handler-disabled\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-handler-disabled\",\n        \"SUMMARY\": \"<code>:-moz-handler-disabled</code> matches elements that cannot be displayed because their handlers have been disabled by the user.\",\n        \"VALUES\": []\n    },\n    \":-moz-last-node\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-last-node\",\n        \"SUMMARY\": \"The <code>:-moz-last-node</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches an element that is the last child node of some other element. It differs from <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child\\\" title=\\\"The :last-child CSS pseudo-class represents any element that is the last child element of its parent.\\\"><code>:last-child</code></a> because it does not match a last child element with (non-whitespace) text after it.\",\n        \"VALUES\": []\n    },\n    \":-moz-loading\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-loading\",\n        \"SUMMARY\": \"The <code>:-moz-loading</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches elements, which can't be displayed, because they have not started loading, such as images that haven't started to arrive yet. Note that images that are <em>in the process</em> of loading <em>are not</em> matched by this pseudo-class.\",\n        \"VALUES\": []\n    },\n    \":-moz-locale-dir(ltr)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-locale-dir(ltr)\",\n        \"SUMMARY\": \"The <code>:-moz-locale-dir(ltr)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-classes\\\">pseudo-class</a> matches an element if the user interface is being displayed left-to-right. This is determined by the preference <code>intl.uidirection.<em>locale</em></code> (where <code><em>locale</em></code> is the current locale) being set to \\\"ltr\\\".\",\n        \"VALUES\": []\n    },\n    \":-moz-locale-dir(rtl)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-locale-dir(rtl)\",\n        \"SUMMARY\": \"The <code>:-moz-locale-dir(rtl)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-classes\\\">pseudo-class</a> matches an element if the user interface is being displayed right-to-left. This is determined by the preference <code>intl.uidirection.</code><em><code>locale</code></em> (where <em><code>locale</code></em> is the current locale) being set to \\\"rtl\\\".\",\n        \"VALUES\": []\n    },\n    \":-moz-lwtheme\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-lwtheme\",\n        \"SUMMARY\": \"The <code>:-moz-lwtheme</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches in chrome documents when the root element's <code id=\\\"a-lightweightthemes\\\"><a href=\\\"https://developer.mozilla.org/en-US/docs/XUL/Attribute/lightweightthemes\\\">lightweightthemes</a></code> attribute is <code>true</code> and a theme is selected.\",\n        \"VALUES\": []\n    },\n    \":-moz-lwtheme-brighttext\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-lwtheme-brighttext\",\n        \"SUMMARY\": \"The <code>:-moz-lwtheme-brighttext</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches in chrome documents when <a title=\\\"The :-moz-lwtheme pseudo-class matches in chrome documents when the root element's lightweightthemes attribute is true and a theme is selected.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-lwtheme\\\"><code>:-moz-lwtheme</code></a> is true and a lightweight theme with a bright text color is selected.\",\n        \"VALUES\": []\n    },\n    \":-moz-lwtheme-darktext\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-lwtheme-darktext\",\n        \"SUMMARY\": \"The <code>:-moz-lwtheme-darktext</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches in chrome documents when <a title=\\\"The :-moz-lwtheme pseudo-class matches in chrome documents when the root element's lightweightthemes attribute is true and a theme is selected.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-lwtheme\\\"><code>:-moz-lwtheme</code></a> is <code>true</code> and a lightweight theme with a dark text color is selected.\",\n        \"VALUES\": []\n    },\n    \":-moz-only-whitespace\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-only-whitespace\",\n        \"SUMMARY\": \"The <code>:-moz-only-whitespace</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches an element that has no child nodes at all or empty text nodes or text nodes that have only white-space in them. Only when there are element nodes or text nodes with one or more characters inside the element, the element doesn't match this pseudo-class anymore.\",\n        \"VALUES\": []\n    },\n    \":-moz-placeholder\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-placeholder\",\n        \"SUMMARY\": \"The <code>:-moz-placeholder</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\">pseudo-class</a> represents any form element displaying <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML#The_placeholder_attribute\\\">placeholder text</a>. This allows web developers and theme designers to customize the appearance of placeholder text, which is a light grey color by default. This may not work well if you've changed the background color of your form fields to be a similar color, for example, so you can use this pseudo-class to change the placeholder text color.\",\n        \"VALUES\": []\n    },\n    \":-moz-submit-invalid\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-submit-invalid\",\n        \"SUMMARY\": \"The <code>:-moz-submit-invalid</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> represents any submit button on forms whose contents aren't valid based on their <a href=\\\"/en/HTML/Forms_in_HTML#Constraint_Validation\\\" title=\\\"en/HTML/HTML5/Forms in HTML5#Constraint Validation\\\">validation constraints</a>.\",\n        \"VALUES\": []\n    },\n    \":-moz-suppressed\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-suppressed\",\n        \"SUMMARY\": \"The <code>:-moz-suppressed</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches elements representing images that were not loaded because loading images from that site has been blocked.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(images-in-menus)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(images-in-menus)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(images-in-menus)</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches an element if the computer's user interface supports images in menus.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(mac-graphite-theme)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(mac-graphite-theme)\",\n        \"SUMMARY\": \"<code>:-moz-system-metric(mac-graphite-theme)</code> will match an element if the user has chosen the \\\"Graphite\\\" appearance in the \\\"Appearance\\\" prefpane of the Mac OS X System Preferences.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(scrollbar-end-backward)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(scrollbar-end-backward)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(scrollbar-end-backward)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the computer's user interface includes a backward arrow button at the end of scrollbars.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(scrollbar-end-forward)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(scrollbar-end-forward)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(scrollbar-end-forward)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the computer's user interface includes a forward arrow button at the end of scrollbars.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(scrollbar-start-backward)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(scrollbar-start-backward)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(scrollbar-start-backward)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the computer's user interface includes a backward arrow button at the start of scrollbars.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(scrollbar-start-forward)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(scrollbar-start-forward)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(scrollbar-start-forward)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the computer's user interface includes a forward arrow button at the start of scrollbars.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(scrollbar-thumb-proportional)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(scrollbar-thumb-proportional)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(scrollbar-thumb-proportional)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the computer's user interface uses proportional scrollbar thumbs; that is, the draggable thumb on the scrollbar resizes to indicate the relative size of the visible area of the document.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(touch-enabled)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(touch-enabled)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(touch-enabled)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the device on which the content is being rendered offers a supported touch-screen interface.\",\n        \"VALUES\": []\n    },\n    \":-moz-system-metric(windows-default-theme)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-system-metric(windows-default-theme)\",\n        \"SUMMARY\": \"The <code>:-moz-system-metric(windows-default-theme)</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches an element if the user is currently using one of the following themes in Windows: Luna, Royale, Zune, or Aero (i.e., Vista Basic, Vista Standard, or Aero Glass). This will exclude Windows Classic themes as well as third-party themes.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-cell\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-cell\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-cell-text\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-cell-text\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-cell-text(hover)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-cell-text(hover)\",\n        \"SUMMARY\": \"The <code>:-moz-tree-cell-text(hover)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the mouse cursor is presently hovering over text in a tree cell.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-column\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-column\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-drop-feedback\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-drop-feedback\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-image\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-image\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-indentation\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-indentation\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-line\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-line\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-progressmeter\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-progressmeter\",\n        \"SUMMARY\": \"Activated when the <code>type</code> attribute is set to <code>progressmeter</code>.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-row\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-row\",\n        \"SUMMARY\": \"The <code>::-moz-tree-row</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> is used to select rows and apply styles to tree rows.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-row(hover)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-row(hover)\",\n        \"SUMMARY\": \"The <code>:-moz-tree-row(hover)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> will match an element if the mouse cursor is presently hovering over a tree row.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-separator\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-separator\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-tree-twisty\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-tree-twisty\",\n        \"SUMMARY\": \"Activated by the <code>properties</code> attribute.\",\n        \"VALUES\": []\n    },\n    \":-moz-ui-invalid\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-ui-invalid\",\n        \"SUMMARY\": \"The <code>:-moz-ui-invalid</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any validated form element whose value isn't valid based on their <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML#Constraint_Validation\\\">validation constraints</a>, in certain circumstances. This pseudo-class is applied according to the following rules:\",\n        \"VALUES\": []\n    },\n    \":-moz-ui-valid\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-ui-valid\",\n        \"SUMMARY\": \"The <code>:-moz-ui-valid</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any validated form element whose value validates correctly based on its <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML#Constraint_Validation\\\">validation constraints</a>.\",\n        \"VALUES\": []\n    },\n    \":-moz-user-disabled\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-user-disabled\",\n        \"SUMMARY\": \"The <code>:-moz-user-disabled</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches elements representing images that were not loaded because images have been entirely disabled by the user's preferences.\",\n        \"VALUES\": []\n    },\n    \":-moz-window-inactive\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-window-inactive\",\n        \"SUMMARY\": \"The <code>:-moz-window-inactive</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches any element while it's in an inactive window.\",\n        \"VALUES\": []\n    },\n    \":-ms-input-placeholder\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-ms-input-placeholder\",\n        \"SUMMARY\": \"The non-standard proprietary <code>:-ms-input-placeholder</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Forms_in_HTML#The_placeholder_attribute\\\">placeholder text</a> of a form element. This allows web developers and theme designers to customize the appearance of placeholder text. This pseudo-class is only supported by Internet Explorer and Microsoft Edge.\",\n        \"VALUES\": []\n    },\n    \":-webkit-autofill\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-webkit-autofill\",\n        \"SUMMARY\": \"The <code>:-webkit-autofill</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches when an <a title=\\\"The HTML element&#xA0;&lt;input&gt;&#xA0;is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\"><code>&lt;input&gt;</code></a> element has its value autofilled by the browser.\",\n        \"VALUES\": []\n    },\n    \"::-moz-list-bullet\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-list-bullet\",\n        \"SUMMARY\": \"The non-standard <code>::-moz-list-bullet</code> Mozilla <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> is used to style the bullet of a list element.\",\n        \"VALUES\": []\n    },\n    \"::-moz-list-number\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-list-number\",\n        \"SUMMARY\": \"The <code>::-moz-list-number</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> lets you customize the appearance of numbers on list items (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li\\\" title=\\\"The HTML List Item Element (&lt;li&gt;) is used to represent an item in a list. It must be contained in a parent element: an ordered list (&lt;ol&gt;), an unordered list (&lt;ul&gt;), or a menu (&lt;menu&gt;). In menus and unordered lists, list items are usually displayed using bullet points. In ordered lists, they are usually displayed with an ascending counter on the left, such as a number or letter.\\\"><code>&lt;li&gt;</code></a>) occurring in ordered lists (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol\\\" title=\\\"The HTML &lt;ol&gt; Element (or HTML Ordered List Element) represents an ordered list of items. Typically, ordered-list items are displayed with a preceding numbering, which can be of any form, like numerals, letters or Romans numerals or even simple bullets. This numbered style is not defined in the HTML description of the page, but in its associated CSS, using the list-style-type property.\\\"><code>&lt;ol&gt;</code></a>).\",\n        \"VALUES\": []\n    },\n    \"::-moz-page\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-page\",\n        \"SUMMARY\": \"The <code>::-moz-page</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> applies to an individual page in print or print preview.\",\n        \"VALUES\": []\n    },\n    \"::-moz-page-sequence\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-page-sequence\",\n        \"SUMMARY\": \"The <code>::-moz-page-sequence</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the background of the print preview.\",\n        \"VALUES\": []\n    },\n    \"::-moz-placeholder\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-placeholder\",\n        \"SUMMARY\": \"The <code>::-moz-placeholder</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents any form element displaying <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Forms_in_HTML#The_placeholder_attribute\\\">placeholder text</a>. This allows web developers and theme designers to customize the appearance of placeholder text, which is a light grey color by default. This may not work well if you've changed the background color of your form fields to be a similar color, for example, so you can use this pseudo-element to change the placeholder text color.\",\n        \"VALUES\": []\n    },\n    \"::-moz-progress-bar\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-progress-bar\",\n        \"SUMMARY\": \"The <code>::-moz-progress-bar</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> applies to the area of an HTML <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress\\\" title=\\\"The HTML &lt;progress&gt; Element is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar. Javascript can be used to manipulate the value of progress bar.\\\"><code>&lt;progress&gt;</code></a> element that represents the amount of progress that has happened so far. This lets you, for example, change the color of progress bars.\",\n        \"VALUES\": []\n    },\n    \"::-moz-range-progress\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-range-progress\",\n        \"SUMMARY\": \"The <strong><code>::-moz-range-progress</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the portion of the \\\"track\\\" (the groove in which the indicator aka thumb slides) of an <a title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"range\\\"</code>, which corresponds to values lower than the value currently selected by the thumb.\",\n        \"VALUES\": []\n    },\n    \"::-moz-range-thumb\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-range-thumb\",\n        \"SUMMARY\": \"The <strong><code>::-moz-range-thumb</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the <em>thumb</em>, the virtual knob the user can move within the <em>groove</em>, or track, of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"range\\\"</code> to alter its numerical value.\",\n        \"VALUES\": []\n    },\n    \"::-moz-range-track\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-range-track\",\n        \"SUMMARY\": \"The <strong><code>::-moz-range-track</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\" title=\\\"en/CSS/Pseudo-elements\\\">pseudo-element</a> represents the <em>track</em>, that is the groove in which the indicator of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"range\\\"</code> slides.\",\n        \"VALUES\": []\n    },\n    \"::-moz-scrolled-page-sequence\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-scrolled-page-sequence\",\n        \"SUMMARY\": \"The <code>::-moz-scrolled-page-sequence</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the background of the print preview.\",\n        \"VALUES\": []\n    },\n    \"::-ms-browse\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-browse\",\n        \"SUMMARY\": \"The <strong><code>::-ms-browse</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the button to open the file picker of an <a title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"file\\\"</code>.\",\n        \"VALUES\": []\n    },\n    \"::-ms-check\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-check\",\n        \"SUMMARY\": \"The <strong><code>::-ms-check</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the checkmark of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"checkbox\\\"</code> or <code>type=\\\"radio\\\"</code>.\",\n        \"VALUES\": []\n    },\n    \"::-ms-clear\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-clear\",\n        \"SUMMARY\": \"The <strong><code>::-ms-clear</code></strong> CSS <a href=\\\"/en/CSS/Pseudo-elements\\\" title=\\\"en/CSS/Pseudo-elements\\\">pseudo-element</a> represents a button (the \\\"clear button\\\") at the edge of a text <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> which clears away the current value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> element. This button and pseudo-element are non-standard, supported only in Internet Explorer 10 and 11 and Edge 12+, hence the vendor prefix (`-ms` for Microsoft). The clear button is only shown on focused, non-empty text <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> elements.\",\n        \"VALUES\": []\n    },\n    \"::-ms-expand\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-expand\",\n        \"SUMMARY\": \"Technical review completed.\",\n        \"VALUES\": []\n    },\n    \"::-ms-fill\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-fill\",\n        \"SUMMARY\": \"The <strong><code>::-ms-fill</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\" title=\\\"en/CSS/Pseudo-elements\\\">pseudo-element</a> represents the filled-in portion of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress\\\" title=\\\"The HTML &lt;progress&gt; Element is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar. Javascript can be used to manipulate the value of progress bar.\\\"><code>&lt;progress&gt;</code></a> element. This pseudo-element is non-standard and specific to Internet Explorer 10+, hence the vendor prefix.\",\n        \"VALUES\": []\n    },\n    \"::-ms-fill-lower\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-fill-lower\",\n        \"SUMMARY\": \"The <strong><code>::-ms-fill-lower</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the portion of the \\\"track\\\" (the groove in which the indicator aka thumb slides) of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element&#xA0;&lt;input&gt;&#xA0;is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"range\\\"</code>, which corresponds to values lower than the value currently selected by the thumb.\",\n        \"VALUES\": []\n    },\n    \"::-ms-fill-upper\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-fill-upper\",\n        \"SUMMARY\": \"The <strong><code>::-ms-fill-upper</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the portion of the \\\"track\\\" (the groove in which the indicator aka thumb slides) of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element&#xA0;&lt;input&gt;&#xA0;is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"range\\\"</code>, which corresponds to values greater than the value currently selected by the thumb.\",\n        \"VALUES\": []\n    },\n    \"::-ms-reveal\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-reveal\",\n        \"SUMMARY\": \"The <strong><code>::-ms-reveal</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> is used to display and apply styles to the \\\"password reveal button\\\" usually displayed at the edge of an <a title=\\\"The HTML element&#xA0;&lt;input&gt;&#xA0;is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\"><code>&lt;input&gt;</code></a> element of <code>type=\\\"password\\\"</code> in Internet Explorer 10+. The password reveal button displays the value of the password field in plain text (instead of the usual obscured-for-privacy all-asterisks display). This button and the pseudo-element are non-standard and specific to Internet Explorer 10+, hence the vendor prefix.\",\n        \"VALUES\": []\n    },\n    \"::-ms-thumb\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-thumb\",\n        \"SUMMARY\": \"Technical review completed.\",\n        \"VALUES\": []\n    },\n    \"::-ms-track\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-track\",\n        \"SUMMARY\": \"Technical review completed.\",\n        \"VALUES\": []\n    },\n    \"::-ms-value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-ms-value\",\n        \"SUMMARY\": \"The <strong><code>::-ms-value</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> applies rules to the value/content of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element&#xA0;&lt;input&gt;&#xA0;is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\\\" title=\\\"The HTML select (&lt;select&gt;) element represents a control that presents a menu of options. The options within the menu are represented by &lt;option&gt; elements, which can be grouped by &lt;optgroup&gt; elements. Options can be pre-selected for the user.\\\"><code>&lt;select&gt;</code></a>. Only certain properties can be set on this pseudo-element; others will have no effect.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-file-upload-button\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-file-upload-button\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-file-upload-button</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the button of an <a title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\"><code>&lt;input&gt;</code></a> of  <code>type=\\\"file\\\"</code>.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-inner-spin-button\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-inner-spin-button\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-inner-spin-button</code></strong> CSS pseudo-element is used to style the inner part of the spinner button of number picker input elements.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-input-placeholder\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-input-placeholder\",\n        \"SUMMARY\": \"Technical review completed. Editorial review completed.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-meter-bar\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-meter-bar\",\n        \"SUMMARY\": \"The <code>::-webkit-meter-bar</code> pseudo-class sets the styling for the background of the element. Container of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter\\\" title=\\\"The HTML &lt;meter&gt; Element represents either a scalar value within a known range or a fractional value.\\\"><code>&lt;meter&gt;</code></a> gauge that holds the value.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-meter-even-less-good-value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-meter-even-less-good-value\",\n        \"SUMMARY\": \"The <code>::-webkit-meter-even-less-good-value</code> gives a red color to the meter element when the value and the optimum attributes fall outside the low-high range but in opposite zones. For example, value &lt; low &lt; high &lt; optimum or value&gt; high &gt; low &gt; optimum.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-meter-inner-element\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-meter-inner-element\",\n        \"SUMMARY\": \"<code>::-webkit-meter-inner-element</code> is a proprietary WebKit CSS pseudo-element for selecting and applying styles to to the outer containing element of a <a title=\\\"The HTML &lt;meter&gt; Element represents either a scalar value within a known range or a fractional value.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter\\\"><code>&lt;meter&gt;</code></a> element. Additional markup to render the meter element as read-only.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-meter-optimum-value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-meter-optimum-value\",\n        \"SUMMARY\": \"The <code>::-webkit-meter-optimum-value</code> pseudo-element  styles the meter element when its value is inside the low-high range.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-meter-suboptimum-value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-meter-suboptimum-value\",\n        \"SUMMARY\": \"The <code>::-webkit-meter-suboptimum-value</code> gives a yellow color to the meter element when the value attribute falls outside of the low-high range.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-outer-spin-button\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-outer-spin-button\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-outer-spin-button</code></strong> CSS pseudo-element is used to style the outer part of the spinner button of number picker input elements.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-progress-bar\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-bar\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-progress-bar</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the entire bar of a <a title=\\\"The HTML &lt;progress&gt; Element is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar. Javascript can be used to manipulate the value of progress bar.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress\\\"><code>&lt;progress&gt;</code></a> element. Normally it's only visible as the unfilled portion of the bar, since by default it's rendered below the <a title=\\\"The ::-webkit-progress-value CSS pseudo-element represents the filled-in portion of the bar of a &lt;progress&gt; element. It is a child of the ::-webkit-progress-bar pseudo-element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-value\\\"><code>::-webkit-progress-value</code></a> pseudo-element. It is a child of the <a title=\\\"The ::-webkit-progress-inner-element CSS pseudo-element represents the outermost, container pseudo-element of the &lt;progress&gt; element. It is the parent of the ::-webkit-progress-bar pseudo-element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-inner-element\\\"><code>::-webkit-progress-inner-element</code></a> pseudo-element and the parent of the <a title=\\\"The ::-webkit-progress-value CSS pseudo-element represents the filled-in portion of the bar of a &lt;progress&gt; element. It is a child of the ::-webkit-progress-bar pseudo-element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-value\\\"><code>::-webkit-progress-value</code></a> pseudo-element.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-progress-inner-element\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-inner-element\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-progress-inner-element</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the outermost, container pseudo-element of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress\\\" title=\\\"The HTML &lt;progress&gt; Element is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar. Javascript can be used to manipulate the value of progress bar.\\\"><code>&lt;progress&gt;</code></a> element. It is the parent of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-bar\\\" title=\\\"The ::-webkit-progress-bar CSS pseudo-element represents the entire bar of a &lt;progress&gt; element. Normally it's only visible as the unfilled portion of the bar, since by default it's rendered below the ::-webkit-progress-value pseudo-element. It is a child of the ::-webkit-progress-inner-element pseudo-element and the parent of the ::-webkit-progress-value pseudo-element.\\\"><code>::-webkit-progress-bar</code></a> pseudo-element.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-progress-value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-value\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-progress-value</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the filled-in portion of the bar of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress\\\" title=\\\"The HTML &lt;progress&gt; Element is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar. Javascript can be used to manipulate the value of progress bar.\\\"><code>&lt;progress&gt;</code></a> element. It is a child of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-bar\\\" title=\\\"The ::-webkit-progress-bar CSS pseudo-element represents the entire bar of a &lt;progress&gt; element. Normally it's only visible as the unfilled portion of the bar, since by default it's rendered below the ::-webkit-progress-value pseudo-element. It is a child of the ::-webkit-progress-inner-element pseudo-element and the parent of the ::-webkit-progress-value pseudo-element.\\\"><code>::-webkit-progress-bar</code></a> pseudo-element.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-scrollbar\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-scrollbar\",\n        \"SUMMARY\": \"The <font face=\\\"Consolas, Liberation Mono, Courier, monospace\\\">::-webkit-scrollbar</font> CSS pseudo-element affects the style of the scrollbar of an element.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-search-cancel-button\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-search-cancel-button\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-search-cancel-button</code></strong> CSS <a href=\\\"/en/CSS/Pseudo-elements\\\">pseudo-element</a> represents a button (the \\\"cancel button\\\") at the edge of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"search\\\"</code> which clears away the current value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> element. This button and pseudo-element are non-standard, supported only in WebKit and Blink, hence the vendor prefix. The clear button is only shown on non-empty search <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> elements.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-search-results-button\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-search-results-button\",\n        \"SUMMARY\": \"The <strong><code>::-webkit-search-results-button</code></strong> CSS <a href=\\\"/en/CSS/Pseudo-elements\\\">pseudo-element</a> represents a button (the \\\"search results button\\\") at the left edge of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> of <code>type=\\\"search\\\"</code> which when clicked displays a menu which allows the user to choose from previous recent search queries. This button and pseudo-element are non-standard, supported only in WebKit and Blink, hence the vendor prefix. The search results button is only shown on search <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> elements which have a <a href=\\\"/en/docs/Web/HTML/Element/Input#attr-results\\\"><code>results</code> attribute</a>.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-slider-runnable-track\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-slider-runnable-track\",\n        \"SUMMARY\": \"Technical review completed. Editorial review completed.\",\n        \"VALUES\": []\n    },\n    \"::-webkit-slider-thumb\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-slider-thumb\",\n        \"SUMMARY\": \"Technical review completed. Editorial review completed.\",\n        \"VALUES\": []\n    },\n    \"::after (:after)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::after\",\n        \"SUMMARY\": \"The CSS <code>::after</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> matches a virtual last child of the selected element. It is typically used to add cosmetic content to an element by using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/content\\\" title=\\\"The content CSS property is used with the ::before and ::after pseudo-elements to generate content in an element. Objects inserted using the content property are anonymous replaced elements.\\\"><code>content</code></a> CSS property. This element is inline by default.\",\n        \"VALUES\": []\n    },\n    \"::backdrop\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::backdrop\",\n        \"SUMMARY\": \"Each element in the <a href=\\\"https://fullscreen.spec.whatwg.org/#top-layer\\\">top layer</a>'s stack has a <dfn><code>::backdrop</code></dfn> <a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-elements\\\"><code>pseudo-element</code></a>. This pseudo-element is a box rendered immediately below the element (and above the element below the element in the stack, if any), within the same top layer.\",\n        \"VALUES\": []\n    },\n    \"::before (:before)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::before\",\n        \"SUMMARY\": \"<code>::before</code> creates a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> that is the first child of the element matched. It is often used to add cosmetic content to an element by using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/content\\\" title=\\\"The content CSS property is used with the ::before and ::after pseudo-elements to generate content in an element. Objects inserted using the content property are anonymous replaced elements.\\\"><code>content</code></a> property. This element is inline by default.\",\n        \"VALUES\": []\n    },\n    \"::first-letter (:first-letter)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::first-letter\",\n        \"SUMMARY\": \"The <code>::first-letter</code> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> <a href=\\\"/en/CSS/Pseudo-elements\\\" title=\\\"Pseudo-elements\\\">pseudo-element</a> selects the first letter of the first line of a block, if it is not preceded by any other content (such as images or inline tables) on its line.\",\n        \"VALUES\": []\n    },\n    \"::first-line (:first-line)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::first-line\",\n        \"SUMMARY\": \"The <strong><code>::first-line</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> applies styles only to the first line of an element. The amount of the text on the first line depends of numerous factors, like the width of the element, width of the document, and the font size of the text. As all pseudo-elements, <code>::first-line</code> does not match any real HTML element.\",\n        \"VALUES\": []\n    },\n    \"::grammar-error\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::grammar-error\",\n        \"SUMMARY\": \"Editorial review completed.\",\n        \"VALUES\": []\n    },\n    \"::marker\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::marker\",\n        \"SUMMARY\": \"The <code>::marker</code> CSS pseudo-element represents the marker box of a list item (e.g. the bullet point or item number).\",\n        \"VALUES\": []\n    },\n    \"::placeholder\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::placeholder\",\n        \"SUMMARY\": \"The <strong><code>::placeholder</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a> represents the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Forms_in_HTML#The_placeholder_attribute\\\">placeholder text</a> of a form element. This allows web developers and theme designers to customize the appearance of placeholder text.\",\n        \"VALUES\": []\n    },\n    \"::selection\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::selection\",\n        \"SUMMARY\": \"The <code>::selection</code> CSS pseudo-element applies rules to the portion of a document that has been highlighted (e.g. selected with the mouse or another pointing device) by the user.\",\n        \"VALUES\": []\n    },\n    \"::spelling-error\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/::spelling-error\",\n        \"SUMMARY\": \"Editorial review completed.\",\n        \"VALUES\": []\n    },\n    \":active\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:active\",\n        \"SUMMARY\": \"The <code>:active</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches when an element is being activated by the user. It allows the page to give a feedback that the activation has been detected by the browser. When interacting with a mouse, this is typically the time between the user pressing the mouse button and releasing it. The <code>:active</code> pseudo-class is also typically matched when using the keyboard tab key. It is frequently used on <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a\\\" title=\\\"The HTML &lt;a&gt; element (or anchor element) creates a hyperlink to other web pages, files, locations within the same page, email addresses, or any other URL.\\\"><code>&lt;a&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button\\\" title=\\\"The HTML &lt;button&gt; element represents a clickable button.\\\"><code>&lt;button&gt;</code></a> HTML elements, but may not be limited to just those.\",\n        \"VALUES\": []\n    },\n    \":any\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:any\",\n        \"SUMMARY\": \"The <code>:any()</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"CSS/Pseudo-classes\\\">pseudo-class</a> lets you quickly construct sets of similar selectors by establishing groups from which any of the included items will match. This is an alternative to having to repeat the entire selector for the one item that varies.\",\n        \"VALUES\": [{\n            \"value\": \"<code>selector</code>\",\n            \"description\": \"A selector. This may be a simple selector or a multiple selector comprised of <a title=\\\"http://www.w3.org/TR/css3-selectors/#simple-selectors\\\" href=\\\"http://www.w3.org/TR/css3-selectors/#simple-selectors\\\" class=\\\"external\\\">CSS 3 simple selectors</a>&#xA0;and may include the descendant combinator.\"\n        }]\n    },\n    \":any-link\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:any-link\",\n        \"SUMMARY\": \"The <code>:any-link</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents an element that acts as the source anchor of a hyperlink independent of whether it has been visited, that is, it matches every <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a\\\" title=\\\"The HTML Anchor Element (&lt;a&gt;) defines a hyperlink to a location on the same page or any other page on the Web. It can also be used (in an obsolete way) to create an anchor point&#x2014;a destination for hyperlinks within the content of a page, so that links aren't limited to connecting simply to the top of a page.\\\"><code>&lt;a&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area\\\" title=\\\"The HTML &lt;area&gt; element defines a hot-spot region on an image, and optionally associates it with a hypertext link. This element is used only within a &lt;map&gt; element.\\\"><code>&lt;area&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link\\\" title=\\\"The HTML &lt;link&gt; element specifies relationships between the current document and an external resource. Possible uses for this element include defining a relational framework for navigation. This Element is most used to link to style sheets.\\\"><code>&lt;link&gt;</code></a> elements with an <code>href</code> attribute. So, it matches all elements that match <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:link\\\" title=\\\"The :link CSS pseudo-class lets you select links inside elements. This will select any link which has not yet been visited, even those already styled using selector with other link-related pseudo-classes like :hover, :active or :visited. In order to appropriately style links, you need to put the :link rule before the other ones, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active. The :focus pseudo-class is usually placed right before or right after :hover, depending on the expected effect.\\\"><code>:link</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:visited\\\" title=\\\"The :visited CSS pseudo-class lets you select only links that have been visited. This style may be overridden by any other link-related pseudo-classes, that is :link, :hover, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :visited rule after the :link rule but before the other ones, defined in the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:visited</code></a>.\",\n        \"VALUES\": []\n    },\n    \":checked\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:checked\",\n        \"SUMMARY\": \"The <strong><code>:checked</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> selector represents any <strong>radio </strong>(<code>&lt;input type=\\\"radio\\\"&gt;</code>), <strong>checkbox </strong>(<code>&lt;input type=\\\"checkbox\\\"&gt;</code>) or <strong>option</strong> (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option\\\" title=\\\"The HTML &lt;option&gt; element is used to create a control representing an item within a &lt;select&gt;, an &lt;optgroup&gt; or a &lt;datalist&gt; HTML5 element.\\\"><code>&lt;option&gt;</code></a> in a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\\\" title=\\\"The HTML &lt;select&gt; element represents a control that provides a menu of options.\\\"><code>&lt;select&gt;</code></a>) element that is checked or toggled to an <code>on</code> state. The user can change this state by clicking on the element, or selecting a different value, in which case the <code>:checked</code> pseudo-class no longer applies to this element, but will to the relevant one.\",\n        \"VALUES\": [{\n            \"value\": \"<code>input[type=&quot;radio&quot;]:checked</code>\",\n            \"description\": \"Represents all radio buttons on the page that are checked\"\n        }, {\n            \"value\": \"<code>input[type=&quot;checkbox&quot;]:checked</code>\",\n            \"description\": \"Represents all checkboxes on the page that are checked\"\n        }, {\n            \"value\": \"<code>option:checked</code>\",\n            \"description\": \"Represents all select&apos;s options on the page that are selected\"\n        }]\n    },\n    \":default\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:default\",\n        \"SUMMARY\": \"The <code>:default</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any user interface element that is the default among a group of similar elements.\",\n        \"VALUES\": []\n    },\n    \":dir()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:dir\",\n        \"SUMMARY\": \"The <code>:dir</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches elements based on the directionality of the text contained in it. In HTML, the direction is determined by the <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html#attr-dir\\\">dir</a></code> attribute. For other document types there may be other document methods for determining the language.\",\n        \"VALUES\": []\n    },\n    \":disabled\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:disabled\",\n        \"SUMMARY\": \"The <code>:disabled</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any disabled element. An element is disabled if it can't be activated (e.g. selected, clicked on or accept text input) or accept focus. The element also has an enabled state, in which it can be activated or accept focus.\",\n        \"VALUES\": [{\n            \"value\": \"input:disabled\",\n            \"description\": \"Selects all disabled inputs\"\n        }, {\n            \"value\": \"select.country:disabled\",\n            \"description\": \"Targets a select element with class country that is disabled\"\n        }]\n    },\n    \":empty\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:empty\",\n        \"SUMMARY\": \"The <code>:empty</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-classes\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>pseudo-class</code></a> represents any element that has no children at all. Only element nodes and text (including whitespace) are considered. Comments or processing instructions do not affect whether an element is considered empty or not.\",\n        \"VALUES\": []\n    },\n    \":enabled\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:enabled\",\n        \"SUMMARY\": \"The <code>:enabled</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any enabled element. An element is enabled if it can be activated (e.g. selected, clicked on or accept text input) or accept focus. The element also has a disabled state, in which it can't be activated or accept focus.\",\n        \"VALUES\": []\n    },\n    \":first\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:first\",\n        \"SUMMARY\": \"The <code>:first</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@page\\\" title=\\\"The @page CSS at-rule is used to modify some CSS properties when printing a document. You can't change all CSS properties with @page. You can only change the margins, orphans, widows, and page breaks of the document. Attempts to change any other CSS properties will be ignored.\\\"><code>@page</code></a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> describes the styling of the first page when printing a document.\",\n        \"VALUES\": []\n    },\n    \":first-child\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child\",\n        \"SUMMARY\": \"The <code>:first-child</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any element that is the first child element of its parent.\",\n        \"VALUES\": []\n    },\n    \":first-of-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type\",\n        \"SUMMARY\": \"The <code>:first-of-type</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents the first sibling of its type in the list of children of its parent element.\",\n        \"VALUES\": []\n    },\n    \":focus\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:focus\",\n        \"SUMMARY\": \"The <code>:focus</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> is applied when an element has received focus, either from the user selecting it with the use of a keyboard or by activating with the mouse (e.g. a form input).\",\n        \"VALUES\": []\n    },\n    \":focus-within\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within\",\n        \"SUMMARY\": \"The <strong><code>:focus-within</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches any element that <a title=\\\"The :focus CSS pseudo-class is applied when an element has received focus, either from the user selecting it with the use of a keyboard or by activating with the mouse (e.g. a form input).\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:focus\\\"><code>:focus</code></a> pseudo-class matches or that has a descendant that the <a title=\\\"The :focus CSS pseudo-class is applied when an element has received focus, either from the user selecting it with the use of a keyboard or by activating with the mouse (e.g. a form input).\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:focus\\\"><code>:focus</code></a> pseudo-class matches.  (This includes descendants in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM\\\">shadow trees</a>.)\",\n        \"VALUES\": []\n    },\n    \":fullscreen\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:fullscreen\",\n        \"SUMMARY\": \"The<code> :fullscreen </code>CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> applies to any element that's currently being displayed in full-screen mode. It selects not only to the top level element, but to the whole stack of elements that appears.\",\n        \"VALUES\": []\n    },\n    \":has\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:has\",\n        \"SUMMARY\": \"The <strong><code>:has()</code> </strong>CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents an element if any of the selectors, relative to the<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:scope\\\" title=\\\"The :scope CSS  pseudo-class matches the elements that are a reference point for selectors to match against. In HTML, a new reference point can be defined using the scoped attribute of the &lt;style&gt;. If no such attribute is used on an HTML page, the reference point is the &lt;html&gt; element.\\\"><code>:scope</code></a> of the given element, passed as parameters, matches at least one element. The <code>:has()</code> pseudo-class takes a selector list as an argument.\",\n        \"VALUES\": []\n    },\n    \":hover\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:hover\",\n        \"SUMMARY\": \"The <code>:hover</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches when the user designates an element with a pointing device, but does not necessarily activate it. This style may be overridden by any other link-related pseudo-classes, that is <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:link\\\" title=\\\"The :link CSS pseudo-class lets you select links inside elements. This will select any link which has not yet been visited, even those already styled using selector with other link-related pseudo-classes like :hover, :active or :visited. In order to appropriately style links, you need to put the :link rule before the other ones, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active. The :focus pseudo-class is usually placed right before or right after :hover, depending on the expected effect.\\\"><code>:link</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:visited\\\" title=\\\"The :visited CSS pseudo-class lets you select only links that have been visited. This style may be overridden by any other link-related pseudo-classes, that is :link, :hover, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :visited rule after the :link rule but before the other ones, defined in the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:visited</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:active\\\" title=\\\"The :active CSS pseudo-class matches when an element is being activated by the user. It allows the page to give a feedback that the activation has been detected by the browser. When interacting with a mouse, this is typically the time between the user presses the mouse button and releases it. The :active pseudo-class is also typically matched when using the keyboard tab key. It is frequently used on &lt;a&gt; and &lt;button&gt; HTML&#xA0;elements, but may not be limited to just those.\\\"><code>:active</code></a>, appearing in subsequent rules. In order to style appropriately links, you need to put the <code>:hover</code> rule after the <code>:link</code> and <code>:visited</code> rules but before the <code>:active</code> one, as defined by the <em>LVHA-order</em>: <code>:link</code> — <code>:visited</code> — <code>:hover</code> — <code>:active</code>.\",\n        \"VALUES\": []\n    },\n    \":in-range\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:in-range\",\n        \"SUMMARY\": \"The <code>:in-range</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches when an element has its value attribute inside the specified range limitations for this element. It allows the page to give a feedback that the value currently defined using the element is inside the range limits.\",\n        \"VALUES\": []\n    },\n    \":indeterminate\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:indeterminate\",\n        \"SUMMARY\": \"The <code>:indeterminate</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents:\",\n        \"VALUES\": []\n    },\n    \":invalid\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid\",\n        \"SUMMARY\": \"The <code>:invalid</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> represents any <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML &lt;input&gt; element is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form\\\" title=\\\"The HTML &lt;form&gt; element represents a document section that contains interactive controls to submit information to a web server.\\\"><code>&lt;form&gt;</code></a> element whose content fails to <a href=\\\"/en/HTML/HTML5/Constraint_validation\\\" title=\\\"en/HTML/HTML5/Constraint_validation\\\">validate</a> according to the input's type setting. This allows you to easily have invalid fields adopt an appearance that helps the user identify and correct errors.\",\n        \"VALUES\": []\n    },\n    \":lang\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:lang\",\n        \"SUMMARY\": \"The <code>:lang</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches elements based on the language the element is determined to be in. In HTML, the language is determined by a combination of the <code>lang</code> attribute, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta\\\" title=\\\"The HTML &lt;meta&gt; element represents any metadata information that cannot be represented by one of the other HTML meta-related elements (&lt;base&gt;, &lt;link&gt;, &lt;script&gt;, &lt;style&gt; or &lt;title&gt;).\\\"><code>&lt;meta&gt;</code></a> element, and possibly by information from the protocol (such as HTTP headers).\",\n        \"VALUES\": []\n    },\n    \":last-child\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child\",\n        \"SUMMARY\": \"The <code>:last-child</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any element that is the last child element of its parent.\",\n        \"VALUES\": []\n    },\n    \":last-of-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type\",\n        \"SUMMARY\": \"The <code>:last-of-type</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents the last sibling with the given element name in the list of children of its parent element.\",\n        \"VALUES\": []\n    },\n    \":left\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:left\",\n        \"SUMMARY\": \"The <code>:left</code> CSS <a href=\\\"/en/CSS/@page\\\" title=\\\"@page\\\">page</a> <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches any left page when printing a page. It allows to describe the styling of left-side pages.\",\n        \"VALUES\": []\n    },\n    \":link\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:link\",\n        \"SUMMARY\": \"The <code>:link</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> lets you select links inside elements. This will select any link which has not yet been visited, even those already styled using selector with other link-related pseudo-classes like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:hover\\\" title=\\\"The :hover CSS pseudo-class matches when the user designates an element with a pointing device, but does not necessarily activate it. This style may be overridden by any other link-related pseudo-classes, that is :link, :visited, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :hover rule after the :link and :visited rules but before the :active one, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:hover</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:active\\\" title=\\\"The :active CSS pseudo-class matches when an element is being activated by the user. It allows the page to give a feedback that the activation has been detected by the browser. When interacting with a mouse, this is typically the time between the user pressing&#xA0;the mouse button and releasing&#xA0;it. The :active pseudo-class is also typically matched when using the keyboard tab key. It is frequently used on &lt;a&gt; and &lt;button&gt; HTML&#xA0;elements, but may not be limited to just those.\\\"><code>:active</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:visited\\\" title=\\\"The :visited CSS pseudo-class lets you select only links that have been visited. This style may be overridden by any other link-related pseudo-classes, that is :link, :hover, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :visited rule after the :link rule but before the other ones, defined in the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:visited</code></a>. In order to appropriately style links, you need to put the <code>:link</code> rule before the other ones, as defined by the <em>LVHA-order</em>: <code>:link</code> — <code>:visited</code> — <code>:hover</code> — <code>:active</code>. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:focus\\\" title=\\\"The :focus CSS pseudo-class is applied when an element has received focus, either from the user selecting it with the use of a keyboard or by activating with the mouse (e.g. a form input).\\\"><code>:focus</code></a> pseudo-class is usually placed right before or right after <code>:hover</code>, depending on the expected effect.\",\n        \"VALUES\": []\n    },\n    \":not()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:not\",\n        \"SUMMARY\": \"The <strong>negation </strong><a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">CSS pseudo-class</a>, <code>:not(X)</code>, is a functional notation taking a simple selector <var>X</var> as an argument. It matches an element that is not represented by the argument. <var>X</var> must not contain another negation selector.\",\n        \"VALUES\": []\n    },\n    \":nth-child\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child\",\n        \"SUMMARY\": \"The <code>:nth-child(an+b)</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches an element that has <code><em>a</em>n+<em>b</em>-1</code> siblings before it in the document tree, for a given positive or zero value for <code>n</code>, and has a parent element. More simply stated, the selector matches a number of child elements whose numeric position in the series of children matches the pattern <em>an+b</em>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>tr:nth-child(2n+1)</code>\",\n            \"description\": \"Represents the odd rows of an HTML table.\"\n        }, {\n            \"value\": \"<code>tr:nth-child(odd)</code>\",\n            \"description\": \"Represents the odd rows of an HTML table.\"\n        }, {\n            \"value\": \"<code>tr:nth-child(2n)</code>\",\n            \"description\": \"Represents the even rows of an HTML table.\"\n        }, {\n            \"value\": \"<code>tr:nth-child(even)</code>\",\n            \"description\": \"Represents the even rows of an HTML table.\"\n        }, {\n            \"value\": \"<code>span:nth-child(0n+1)</code>\",\n            \"description\": \"Represents a span element which is the first child of its parent; this is the same as the <a title=\\\"The :first-child CSS pseudo-class represents any element that is the first among a group of sibling elements.&#xA0;In level 3 implementations, the matching element&#xA0;is required to have a parent. In level 4 implementations it does not.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child\\\"><code>:first-child</code></a> selector.\"\n        }, {\n            \"value\": \"<code>span:nth-child(1)</code>\",\n            \"description\": \"Equivalent to the above.\"\n        }, {\n            \"value\": \"<code>span:nth-child(-n+3)</code>\",\n            \"description\": \"Matches if the element is one of the first three children of its parent and also a span.\"\n        }]\n    },\n    \":nth-last-child\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-child\",\n        \"SUMMARY\": \"The <code>:nth-last-child(an+b)</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches an element that has <code><em>a</em>n+<em>b</em>-1</code> siblings after it in the document tree, for a given positive or zero value for <code>n</code>, and has a parent element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>tr:nth-last-child(-n+4)</code>\",\n            \"description\": \"Matches the last four rows of an HTML table.\"\n        }, {\n            \"value\": \"<code>span:nth-last-child(even)</code>\",\n            \"description\": \"Matches the even elements in their parent element, starting at the last element and working backward.\"\n        }]\n    },\n    \":nth-last-of-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type\",\n        \"SUMMARY\": \"The <code>:nth-last-of-type</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches an element that has <code><em>a</em>n+<em>b</em>-1</code> siblings with the same element name after it in the document tree, for a given positive or zero value for <code>n</code>, and has a parent element.\",\n        \"VALUES\": []\n    },\n    \":nth-of-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type\",\n        \"SUMMARY\": \"The <code>:nth-of-type(an+b)</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> matches an element that has <code><em>a</em>n+<em>b</em>-1</code> siblings with the same element name before it in the document tree, for a given positive or zero value for <code>n</code>, and has a parent element.\",\n        \"VALUES\": []\n    },\n    \":only-child\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child\",\n        \"SUMMARY\": \"The <code>:only-child</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> represents any element which is the only child of its parent. This is the same as <code>:first-child:last-child</code> or <code>:nth-child(1):nth-last-child(1)</code>, but with a lower specificity.\",\n        \"VALUES\": []\n    },\n    \":only-of-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type\",\n        \"SUMMARY\": \"The <code>:only-of-type</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents any element that has no siblings of the given type.\",\n        \"VALUES\": []\n    },\n    \":optional\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:optional\",\n        \"SUMMARY\": \"The <code>:optional</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> represents any <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML &lt;input&gt; element is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea\\\" title=\\\"The HTML &lt;textarea&gt; element represents a multi-line plain-text editing control.\\\"><code>&lt;textarea&gt;</code></a> element that does not have the <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-required\\\">required</a></code> attribute set on it. This allows forms to easily indicate optional fields, and to style them accordingly.\",\n        \"VALUES\": []\n    },\n    \":out-of-range\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:out-of-range\",\n        \"SUMMARY\": \"The <code>:out-of-range</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches when an element has its value attribute outside the specified range limitations for this element. It allows the page to give a feedback that the value currently defined using the element is outside the range limits. A value can be outside of a range if it is either smaller or larger than maximum and minimum set values.\",\n        \"VALUES\": []\n    },\n    \":placeholder-shown\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:placeholder-shown\",\n        \"SUMMARY\": \"The <strong><code>:placeholder-shown</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\">pseudo-class</a> represents any form element displaying <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML#The_placeholder_attribute\\\">placeholder text</a>.\",\n        \"VALUES\": []\n    },\n    \":read-only\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:read-only\",\n        \"SUMMARY\": \"The <code>:read-only</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches when an element is not writable by the user.\",\n        \"VALUES\": []\n    },\n    \":read-write\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:read-write\",\n        \"SUMMARY\": \"The <code>:read-write</code> CSS <a title=\\\"Pseudo-classes\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\">pseudo-class</a> matches when an element is editable by user like text input elements.\",\n        \"VALUES\": []\n    },\n    \":required\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:required\",\n        \"SUMMARY\": \"The <code>:required</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> represents any <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML &lt;input&gt; element is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> element that has the <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-required\\\">required</a></code> attribute set on it. This allows forms to easily indicate which fields must have valid data before the form can be submitted.\",\n        \"VALUES\": []\n    },\n    \":right\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:right\",\n        \"SUMMARY\": \"The <code>:right</code> CSS <a href=\\\"/en/CSS/@page\\\" title=\\\"@page\\\">page</a> <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> matches any right page when printing a page. It allows to describe the styling of right-side page.\",\n        \"VALUES\": []\n    },\n    \":root\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:root\",\n        \"SUMMARY\": \"The <code>:root</code> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\"> pseudo-class</a> matches the root element of a tree representing the document. Applied to HTML, <code>:root</code> represents the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html\\\" title=\\\"The HTML &lt;html&gt; element represents the root (top-level element) of an HTML document, so it is also referred to as the root element. All other elements must be descendants of this element.\\\"><code>&lt;html&gt;</code></a> element and is identical to the selector <code>html</code>, except that its <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity\\\">specificity</a> is higher.\",\n        \"VALUES\": []\n    },\n    \":scope\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:scope\",\n        \"SUMMARY\": \"The <code>:scope</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\"> pseudo-class</a> matches the elements that are a reference point for selectors to match against. In HTML, a new reference point can be defined using the <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style#attr-scoped\\\">scoped</a></code> attribute of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style\\\" title=\\\"The HTML &lt;style&gt; element contains style information for a document, or part of a document. By default, the style instructions written inside that element are expected to be CSS.\\\"><code>&lt;style&gt;</code></a>. If no such attribute is used on an HTML page, the reference point is the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html\\\" title=\\\"The HTML &lt;html&gt; element (or HTML root element) represents the root of an HTML document. All other elements must be descendants of this element.\\\"><code>&lt;html&gt;</code></a> element.\",\n        \"VALUES\": []\n    },\n    \":target\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:target\",\n        \"SUMMARY\": \"The <strong><code>:target</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\">pseudo-class</a> represents the unique element, if any, with an <code>id</code> matching the fragment identifier of the URI of the document.\",\n        \"VALUES\": []\n    },\n    \":valid\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:valid\",\n        \"SUMMARY\": \"The <code>:valid</code> CSS <a href=\\\"/en/CSS/Pseudo-classes\\\" title=\\\"Pseudo-classes\\\">pseudo-class</a> represents any <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML &lt;input&gt; element is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form\\\" title=\\\"The HTML &lt;form&gt; element represents a document section that contains interactive controls to submit information to a web server.\\\"><code>&lt;form&gt;</code></a> element whose content <a href=\\\"/en/HTML/HTML5/Constraint_validation\\\" title=\\\"en/HTML/HTML5/Constraint_validation\\\">validates</a> correctly according to the input's type setting. This allows to easily make valid fields adopt an appearance that helps the user confirm that their data is formatted properly.\",\n        \"VALUES\": []\n    },\n    \":visited\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/:visited\",\n        \"SUMMARY\": \"The <code>:visited</code> CSS <a title=\\\"Pseudo-classes\\\" href=\\\"/en/CSS/Pseudo-classes\\\">pseudo-class</a> lets you select only links that have been visited. This style may be overridden by any other link-related pseudo-classes, that is <a title=\\\"The :link CSS pseudo-class lets you select links inside elements. This will select any link which has not yet been visited, even those already styled using selector with other link-related pseudo-classes like :hover, :active or :visited. In order to appropriately style links, you need to put the :link rule before the other ones, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active. The :focus pseudo-class is usually placed right before or right after :hover, depending on the expected effect.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:link\\\"><code>:link</code></a>, <a title=\\\"The :hover CSS pseudo-class matches when the user designates an element with a pointing device, but does not necessarily activate it. This style may be overridden by any other link-related pseudo-classes, that is :link, :visited, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :hover rule after the :link and :visited rules but before the :active one, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:hover\\\"><code>:hover</code></a>, and <a title=\\\"The :active CSS pseudo-class matches when an element is being activated by the user. It allows the page to give a feedback that the activation has been detected by the browser. When interacting with a mouse, this is typically the time between the user presses the mouse button and releases it. The :active pseudo-class is also typically matched when using the keyboard tab key. It is frequently used on &lt;a&gt; and &lt;button&gt; HTML&#xA0;elements, but may not be limited to just those.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:active\\\"><code>:active</code></a>, appearing in subsequent rules. In order to style appropriately links, you need to put the <code>:visited</code> rule after the <code>:link</code> rule but before the other ones, defined in the <em>LVHA-order</em>: <code>:link</code> — <code>:visited</code> — <code>:hover</code> — <code>:active</code>.\",\n        \"VALUES\": []\n    },\n    \"<angle>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\",\n        \"SUMMARY\": \"The <code>&lt;angle&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> data type represents angle values. It is used, for example, in <code>rotate</code> and <code>skew</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform\\\" title=\\\"The CSS transform property lets you modify the coordinate space of the CSS visual formatting model. Using it, elements can be translated, rotated, scaled, and skewed.\\\"><code>transform</code></a>s.\",\n        \"VALUES\": []\n    },\n    \"<basic-shape>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape\",\n        \"SUMMARY\": \"The <strong><code>&lt;basic-shape&gt;</code></strong> type can be specified using basic shape functions. When using this syntax to define shapes, the reference box is defined by each property that uses <code>&lt;basic-shape&gt;</code> values. The coordinate system for the shape has its origin on the top-left corner of the reference box with the x-axis running to the right and the y-axis running downwards. All the lengths expressed in percentages are resolved from the used dimensions of the reference box.\",\n        \"VALUES\": [{\n            \"value\": \"<code><a name=\\\"inset\\\"></a>inset()</code>\",\n            \"description\": \"\\n <pre class=\\\"syntaxbox\\\"><code>inset( &lt;shape-arg&gt;{1,4} [round &lt;border-radius&gt;]? )</code></pre>\\n\\n <p>Defines an inset rectangle.</p>\\n\\n <p>When all of the first four arguments are supplied they represent the top, right, bottom and left offsets from the reference box inward that define the positions of the edges of the inset rectangle. These arguments follow the syntax of the margin shorthand, that let you set all four insets with one, two or four values.</p>\\n\\n <p>The optional <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius\\\"><code>&lt;border-radius&gt;</code></a> argument(s) define rounded corners for the inset rectangle using the border-radius shorthand syntax.</p>\\n\\n <p>A pair of insets in either dimension that add up to more than the used dimension (such as left and right insets of 75% apiece) define a shape enclosing no area. For this specification, this results in an empty float area.</p>\\n \"\n        }, {\n            \"value\": \"<code><a name=\\\"polygon\\\"></a>polygon()</code>\",\n            \"description\": \"\\n <pre class=\\\"syntaxbox\\\"><code>polygon( [&lt;fill-rule&gt;,]? [&lt;shape-arg&gt; &lt;shape-arg&gt;]# )</code></pre>\\n\\n <p><code>&lt;fill-rule&gt;</code> represents the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule\\\">filling rule</a> used to determine the interior of the polygon. Possible values are <code>nonzero</code> and <code>evenodd</code>. Default value when omitted is <code>nonzero</code>.</p>\\n\\n <p>Each pair argument in the list represents <em>x<sub>i</sub></em> and <em>y<sub>i</sub></em> - the x and y axis coordinates of the i<sup>th</sup> vertex of the polygon.</p>\\n \"\n        }, {\n            \"value\": \"<code><a name=\\\"circle\\\"></a>circle(</code>)\",\n            \"description\": \"\\n <pre class=\\\"syntaxbox\\\"><code><code><code>circle( [&lt;shape-radius&gt;]? [at &lt;position&gt;]? )</code></code></code></pre>\\n\\n <p>The <code>&lt;shape-radius&gt;</code> argument represents <em>r</em>, the radius of the circle. Negative values are invalid. A percentage value here is resolved from the used width and height of the reference box as <code>sqrt(width^2+height^2)/sqrt(2)</code>.</p>\\n\\n <p>The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\\\" title=\\\"The &lt;position&gt; CSS data type denotes a coordinate in a 2D space used to set a location relative to a box.\\\"><code>&lt;position&gt;</code></a> argument defines the center of the circle. This defaults to center if omitted.</p>\\n \"\n        }, {\n            \"value\": \"<code><a name=\\\"ellipse\\\"></a>ellipse()</code>\",\n            \"description\": \"\\n <pre class=\\\"syntaxbox\\\"><code><code><code>ellipse( [&lt;shape-radius&gt;{2}]? [at &lt;position&gt;]? )</code></code></code></pre>\\n\\n <p>The <code>&lt;shape-radius&gt;</code> arguments represent r<sub>x</sub> and r<sub>y</sub>, the x-axis and y-axis radii of the ellipse, in that order. Negative values for either radius are invalid. Percentage values here are resolved against the used width (for the r<sub>x</sub> value) and the used height (for the r<sub>y</sub> value) of the reference box.</p>\\n\\n <p>The position argument defines the center of the ellipse. This defaults to center if omitted.</p>\\n \"\n        }]\n    },\n    \"<blend-mode>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode\",\n        \"SUMMARY\": \"The <strong><code>&lt;blend-mode&gt;</code></strong> type is a collection of keywords describing blend modes.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"\\n <p>The final color is the top color, whatever the bottom color may be.<br>\\n  The effect is similar to two opaque pieces of paper overlapping.</p>\\n\\n <div id=\\\"normal\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: normal;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_normal\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/normal?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>multiply</code>\",\n            \"description\": \"\\n <p>The final color is the result of multiplying the top and bottom colors.<br>\\n  A black layer leads to a black final layer, and a white layer leads to no change.<br>\\n  The effect is similar to two images printed on transparent film overlapping.</p>\\n\\n <div id=\\\"multiply\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: multiply;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_multiply\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/multiply?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>screen</code>\",\n            \"description\": \"\\n <p>The final color is the result of inverting the colors, multiplying them and inverting that color value.<br>\\n  A black layer leads to no change, and a white layer leads to a white final layer.<br>\\n  The effect is similar to two images shone onto a projection screen.</p>\\n\\n <div id=\\\"screen\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: screen;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_screen\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/screen?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>overlay</code>\",\n            \"description\": \"The final color is the result of <code>multiply</code> if the bottom color is darker, or <code>screen</code> if the bottom color is lighter.<br>\\n This blend mode is equivalent to <code>hard-light</code> but with the layers swapped.\\n <div id=\\\"overlay\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: overlay;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_overlay\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/overlay?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>darken</code>\",\n            \"description\": \"\\n <p>The final color is a color composed of the darkest values per color channel.</p>\\n\\n <div id=\\\"darken\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: darken;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_darken\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/darken?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>lighten</code>\",\n            \"description\": \"\\n <p>The final color is a color composed of the lightest values per color channel.</p>\\n\\n <div id=\\\"lighten\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: lighten;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_lighten\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/lighten?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>color-dodge</code>\",\n            \"description\": \"\\n <p>The final color is the result of dividing the bottom color by the inverse of the top color.<br>\\n  A black foreground leads to no change. A foreground with the inverse color of the backdrop leads to a fully lit color.<br>\\n  This blend mode is similar to screen, but the foreground need only be as light as the inverse of the backdrop to reach a fully lit color.</p>\\n\\n <div id=\\\"color-dodge\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: color-dodge;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_color-dodge\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/color-dodge?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>color-burn</code>\",\n            \"description\": \"\\n <p>This final color is the result of inverting the bottom color, dividing the value by the top color, and inverting that value.<br>\\n  A white foreground leads to no change. A foreground with the inverse color of the backdrop leads to a black final image.<br>\\n  This blend mode is similar to multiply, but the foreground need only be as dark as the inverse of the backdrop to make the final image black.</p>\\n\\n <div id=\\\"color-burn\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: color-burn;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_color-burn\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/color-burn?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>hard-light</code>\",\n            \"description\": \"\\n <p>The final color is the result of <code>multiply</code> if the top color is darker, or <code>screen</code> if the top color is lighter.<br>\\n  This blend mode is equivalent to <code>overlay</code> but with the layers swapped.<br>\\n  The effect is similar to shining a <em>harsh</em> spotlight on the backdrop.</p>\\n\\n <div id=\\\"hard-light\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: hard-light;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_hard-light\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/hard-light?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>soft-light</code>\",\n            \"description\": \"\\n <p>The final color is similar to hard-light, but softer.<br>\\n  This blend mode behaves similar to <code>hard-light</code>.<br>\\n  The effect is similar to shining a <em>diffused</em> spotlight on the backdrop<em><code>.</code></em></p>\\n\\n <div id=\\\"soft-light\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: soft-light;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_soft-light\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/soft-light?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>difference</code>\",\n            \"description\": \"\\n <p>The final color is the result of subtracting the darker of the two colors from the lighter one.<br>\\n  A black layer has no effect, while a white layer inverts the other layer&apos;s color.</p>\\n\\n <div id=\\\"difference\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: difference;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_difference\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/difference?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>exclusion</code>\",\n            \"description\": \"\\n <p>The final color is similar to <code>difference,</code> but with less contrast.<br>\\n  As with <code>difference</code>,&#xA0; a black layer has no effect, while a white layer inverts the other layer&apos;s color.</p>\\n\\n <div id=\\\"exclusion\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: exclusion;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_exclusion\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/exclusion?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>hue</code>\",\n            \"description\": \"\\n <p>The final color has the <em>hue</em> of the top color, while using the <em>saturation</em> and <em>luminosity</em> of the bottom color.</p>\\n\\n <div id=\\\"hue\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: hue;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_hue\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/hue?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>saturation</code>\",\n            \"description\": \"\\n <p>The final color has the <em>saturation</em> of the top color, while using the <em>hue</em> and <em>luminosity</em> of the bottom color.<br>\\n  A pure gray backdrop, having no saturation, will have no effect.</p>\\n\\n <div id=\\\"saturation\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: saturation;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_saturation\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/saturation?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>color</code>\",\n            \"description\": \"\\n <p>The final color has the<em> <em>hue</em></em> and <em><em>saturation</em> </em>of the top color, while using the <em>luminosity</em> of the bottom color.<br>\\n  The effect preserves gray levels and can be used to colorize the foreground.</p>\\n\\n <div id=\\\"color\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: color;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_color\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/color?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }, {\n            \"value\": \"<code>luminosity</code>\",\n            \"description\": \"\\n <p>The final color has the <em>luminosity</em> of the top color, while using the <em>hue</em> and <em>saturation</em> of the bottom color.<br>\\n  This blend mode is equivalent to color, but with the layers swapped.</p>\\n\\n <div id=\\\"luminosity\\\">\\n <pre class=\\\"brush: html\\\" style=\\\"display: none;\\\">&lt;div id=&quot;div&quot;&gt;&lt;/div&gt;</pre>\\n\\n <pre class=\\\"brush: css\\\" style=\\\"display: none;\\\">#div {\\n&#xA0;&#xA0;&#xA0; width: 300px;\\n&#xA0;&#xA0;&#xA0; height: 300px;\\n&#xA0;&#xA0;&#xA0; background: url(&apos;https://mdn.mozillademos.org/files/8543/br.png&apos;),\\n                url(&apos;https://mdn.mozillademos.org/files/8545/tr.png&apos;);\\n&#xA0;&#xA0;&#xA0; background-blend-mode: luminosity;\\n}</pre>\\n </div>\\n\\n <p><iframe id=\\\"frame_luminosity\\\" height=\\\"300\\\" src=\\\"https://mdn.mozillademos.org/en-US/docs/Web/CSS/blend-mode$samples/luminosity?revision=1134293\\\" frameborder=\\\"0\\\" width=\\\"300\\\" class=\\\"live-sample-frame sample-code-frame\\\"></iframe></p>\\n \"\n        }]\n    },\n    \"<color>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\",\n        \"SUMMARY\": \"The <code>&lt;color&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type denotes a color in the <a href=\\\"https://en.wikipedia.org/wiki/SRGB\\\" class=\\\"external\\\">sRGB color space</a>. A color can be described in any of these ways:\",\n        \"VALUES\": [{\n            \"value\": \"Hexadecimal notation <code>#RRGGBB,</code> <code>#RGB</code>\",\n            \"description\": \"\\n <ul style=\\\"margin-bottom: 0;\\\">\\n  <li>&quot;<code>#</code>&quot;, followed by six hexadecimal characters (0-9, A-F), where the first two digits represent the red part, the second two the green part and the last two the blue part.</li>\\n  <li>&quot;<code>#</code>&quot;, followed by three hexadecimal characters (0-9, A-F), where the first digit represents the red part, the second the green part and the last one the blue part.</li>\\n </ul>\\n The three-digit RGB notation (<code>#RGB</code>) and the six-digit form (<code>#RRGGBB</code>) are equal, for example <code>#f03</code> and <code>#ff0033</code> represent the same color.\"\n        }, {\n            \"value\": \"Functional Notation <code>rgb(R,G,B)</code>\",\n            \"description\": \"&quot;<code>rgb</code>&quot;, followed by three <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> or three <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values, plus an optional alpha value that specifies the transparency of the color (this can be a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> between 0 and 1, or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a>)<br>\\n The integer number 255 corresponds to 100%, and to F or FF in the hexadecimal notation.\"\n        }, {\n            \"value\": \"Hexadecimal notation <code>#RRGGBBAA and #RGBA</code>\",\n            \"description\": \"\\n <ul style=\\\"margin-bottom: 0;\\\">\\n  <li>&quot;<code>#</code>&quot;, followed by eight hexadecimal characters (0-9, A-F), where the first two digits represent the red part, the second two the green part, the third two the blue part and the last two the transparency.</li>\\n  <li>&quot;<code>#</code>&quot;, followed by four hexadecimal characters (0-9, A-F), where the first digit represents the red part, the second the green part, the third one the blue part and the last one the transparency.</li>\\n </ul>\\n The four-digit RGB notation (<code>#RGBA</code>) and the eight-digit form (<code>#RRGGBBAA</code>) are equal, for example, <code>#f038</code> and <code>#ff003388</code> represent the same color.\"\n        }, {\n            \"value\": \"using the <code>rgba()</code> functional notation.\",\n            \"description\": \"RGBa extends the RGB color model to include the alpha channel, allowing specification of the opacity of a color.<br>\\n <strong>a</strong> means opacity: 0=transparent; 1=opaque;\"\n        }, {\n            \"value\": \"ActiveBorder\",\n            \"description\": \"Active window border.\"\n        }, {\n            \"value\": \"ActiveCaption\",\n            \"description\": \"Active window caption. Should be used with <code>CaptionText</code> as foreground color.\"\n        }, {\n            \"value\": \"AppWorkspace\",\n            \"description\": \"Background color of multiple document interface.\"\n        }, {\n            \"value\": \"Background\",\n            \"description\": \"Desktop background.\"\n        }, {\n            \"value\": \"ButtonFace\",\n            \"description\": \"Face background color for 3-D elements that appear 3-D due to one layer of surrounding border.&#xA0; Should be used with the <code>ButtonText</code> foreground color.\"\n        }, {\n            \"value\": \"ButtonHighlight\",\n            \"description\": \"The color of the border facing the light source for 3-D elements that appear 3-D due to that layer of surrounding border.\"\n        }, {\n            \"value\": \"ButtonShadow\",\n            \"description\": \"The color of the border away from the light source for 3-D elements that appear 3-D due to that layer of surrounding border.\"\n        }, {\n            \"value\": \"ButtonText\",\n            \"description\": \"Text on push buttons. Should be used with the <code>ButtonFace</code> or <code>ThreeDFace</code> background color.\"\n        }, {\n            \"value\": \"CaptionText\",\n            \"description\": \"Text in caption, size box, and scrollbar arrow box. Should be used with the <code>ActiveCaption</code> background color.\"\n        }, {\n            \"value\": \"GrayText\",\n            \"description\": \"Grayed (disabled) text.\"\n        }, {\n            \"value\": \"Highlight\",\n            \"description\": \"Item(s) selected in a control.&#xA0; Should be used with the <code>HighlightText</code> foreground color.\"\n        }, {\n            \"value\": \"HighlightText\",\n            \"description\": \"Text of item(s) selected in a control. Should be used with the <code>Highlight</code> background color.\"\n        }, {\n            \"value\": \"InactiveBorder\",\n            \"description\": \"Inactive window border.\"\n        }, {\n            \"value\": \"InactiveCaption\",\n            \"description\": \"Inactive window caption. Should be used with the <code>InactiveCaptionText</code> foreground color.\"\n        }, {\n            \"value\": \"InactiveCaptionText\",\n            \"description\": \"Color of text in an inactive caption.&#xA0; Should be used with the <code>InactiveCaption</code> background color.\"\n        }, {\n            \"value\": \"InfoBackground\",\n            \"description\": \"Background color for tooltip controls. Should be used with the <code>InfoText</code> foreground color.\"\n        }, {\n            \"value\": \"InfoText\",\n            \"description\": \"Text color for tooltip controls.&#xA0; Should be used with the <code>InfoBackground</code> background color.\"\n        }, {\n            \"value\": \"Menu\",\n            \"description\": \"Menu background. Should be used with the <code>MenuText</code> or&#xA0; <code>-moz-MenuBarText</code> foreground color.\"\n        }, {\n            \"value\": \"MenuText\",\n            \"description\": \"Text in menus. Should be used with the <code>Menu</code> background color.\"\n        }, {\n            \"value\": \"Scrollbar\",\n            \"description\": \"Background color of scroll bars.\"\n        }, {\n            \"value\": \"ThreeDDarkShadow\",\n            \"description\": \"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\"\n        }, {\n            \"value\": \"ThreeDFace\",\n            \"description\": \"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border. Should be used with the <code>ButtonText</code> foreground color.\"\n        }, {\n            \"value\": \"ThreeDHighlight\",\n            \"description\": \"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two<br>\\n concentric layers of surrounding border.\"\n        }, {\n            \"value\": \"ThreeDLightShadow\",\n            \"description\": \"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two<br>\\n concentric layers of surrounding border.\"\n        }, {\n            \"value\": \"ThreeDShadow\",\n            \"description\": \"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\"\n        }, {\n            \"value\": \"Window\",\n            \"description\": \"Window background. Should be used with the <code>WindowText</code> foreground color.\"\n        }, {\n            \"value\": \"WindowFrame\",\n            \"description\": \"Window frame.\"\n        }, {\n            \"value\": \"WindowText\",\n            \"description\": \"Text in windows. Should be used with the <code>Window</code> background color.\"\n        }, {\n            \"value\": \"-moz-ButtonDefault\",\n            \"description\": \"The border color that goes around buttons that represent the default action for a dialog box.\"\n        }, {\n            \"value\": \"-moz-ButtonHoverFace\",\n            \"description\": \"The background color of a button that the mouse pointer is over (which would be <code>ThreeDFace</code> or <code>ButtonFace</code> when the mouse pointer is not over it). Should be used with the <code>-moz-ButtonHoverText</code> foreground color.\"\n        }, {\n            \"value\": \"-moz-ButtonHoverText\",\n            \"description\": \"The text color of a button that the mouse pointer is over (which would be ButtonText when the mouse pointer is not over it).&#xA0; Should be used with the <code>-moz-ButtonHoverFace background</code> color.\"\n        }, {\n            \"value\": \"-moz-CellHighlight\",\n            \"description\": \"Background color for selected item in a tree widget.&#xA0; Should be used with the <code>-moz-CellHighlightText</code> foreground color. See also <code>-moz-html-CellHighlight</code>.\"\n        }, {\n            \"value\": \"-moz-CellHighlightText\",\n            \"description\": \"Text color for a selected item in a tree. Should be used with the <code>-moz-CellHighlight background</code> color. See also <code>-moz-html-CellHighlightText</code>.\"\n        }, {\n            \"value\": \"-moz-Combobox\",\n            \"description\": \" Background color for combo-boxes.&#xA0; Should be used with the <code>-moz-ComboboxText</code> foreground color. In versions prior to 1.9.2, use <code>-moz-Field</code> instead.\"\n        }, {\n            \"value\": \"-moz-ComboboxText\",\n            \"description\": \" Text color for combo-boxes. Should be used with the <code>-moz-Combobox</code> background color.&#xA0; In versions prior to 1.9.2, use <code>-moz-FieldText</code> instead.\"\n        }, {\n            \"value\": \"-moz-Dialog\",\n            \"description\": \"Background color for dialog boxes.&#xA0; Should be used with the <code>-moz-DialogText</code> foreground color.\"\n        }, {\n            \"value\": \"-moz-DialogText\",\n            \"description\": \"Text color for dialog boxes. Should be used with the <code>-moz-Dialog</code> background color.\"\n        }, {\n            \"value\": \"-moz-dragtargetzone\",\n            \"description\": \"-moz-EvenTreeRow\"\n        }, {\n            \"value\": \" Background color for even-numbered rows in a tree.&#xA0; Should be used with the <code>-moz-FieldText</code> foreground color. In Gecko versions prior to 1.9, use <code>-moz-Field</code>.&#xA0; See also <code>-moz-OddTreeRow</code>.\",\n            \"description\": \"-moz-Field\"\n        }, {\n            \"value\": \"Text field background color.&#xA0; Should be used with the <code>-moz-FieldText</code> foreground color.\",\n            \"description\": \"-moz-FieldText\"\n        }, {\n            \"value\": \"Text field text color. Should be used with the <code>-moz-Field</code>, <code>-moz-EvenTreeRow</code>, or <code>-moz-OddTreeRow</code> background color.\",\n            \"description\": \"-moz-html-CellHighlight\"\n        }, {\n            \"value\": \" Background color for highlighted item in HTML <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\\\" title=\\\"The HTML &lt;select&gt; element represents a control that provides a menu of options.\\\"><code>&lt;select&gt;</code></a>s. Should be used with the <code>-moz-html-CellHighlightText</code> foreground color. Prior to Gecko 1.9, use <code>-moz-CellHighlight</code>.\",\n            \"description\": \"-moz-html-CellHighlightText\"\n        }, {\n            \"value\": \" Text color for highlighted items in HTML <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\\\" title=\\\"The HTML &lt;select&gt; element represents a control that provides a menu of options.\\\"><code>&lt;select&gt;</code></a>s.&#xA0; Should be used with the <code>-moz-html-CellHighlight</code> background color. Prior to Gecko 1.9, use <code>-moz-CellHighlightText</code>.\",\n            \"description\": \"-moz-mac-accentdarkestshadow\"\n        }, {\n            \"value\": \"-moz-mac-accentdarkshadow\",\n            \"description\": \"-moz-mac-accentface\"\n        }, {\n            \"value\": \"-moz-mac-accentlightesthighlight\",\n            \"description\": \"-moz-mac-accentlightshadow\"\n        }, {\n            \"value\": \"-moz-mac-accentregularhighlight\",\n            \"description\": \"-moz-mac-accentregularshadow\"\n        }, {\n            \"value\": \"-moz-mac-chrome-active\",\n            \"description\": \"\"\n        }, {\n            \"value\": \"-moz-mac-chrome-inactive\",\n            \"description\": \"\"\n        }, {\n            \"value\": \"-moz-mac-focusring\",\n            \"description\": \"-moz-mac-menuselect\"\n        }, {\n            \"value\": \"-moz-mac-menushadow\",\n            \"description\": \"-moz-mac-menutextselect\"\n        }, {\n            \"value\": \"-moz-MenuHover\",\n            \"description\": \"Background color for hovered menu items. Often similar to <code>Highlight</code>. Should be used with the <code>-moz-MenuHoverText</code> or <code>-moz-MenuBarHoverText</code> foreground color.\"\n        }, {\n            \"value\": \"-moz-MenuHoverText\",\n            \"description\": \"Text color for hovered menu items. Often similar to <code>HighlightText</code>.&#xA0; Should be used with the <code>-moz-MenuHover</code> background color.\"\n        }, {\n            \"value\": \"-moz-MenuBarText\",\n            \"description\": \" Text color in menu bars. Often similar to <code>MenuText</code>. Should be used on top of <code>Menu</code> background.\"\n        }, {\n            \"value\": \"-moz-MenuBarHoverText\",\n            \"description\": \"Color for hovered text in menu bars. Often similar to <code>-moz-MenuHoverText</code>. Should be used on top of <code>-moz-MenuHover</code> background.\"\n        }, {\n            \"value\": \"-moz-nativehyperlinktext\",\n            \"description\": \" Default platform hyperlink color.\"\n        }, {\n            \"value\": \"-moz-OddTreeRow\",\n            \"description\": \" Background color for odd-numbered rows in a tree.&#xA0; Should be used with the <code>-moz-FieldText</code> foreground color. In Gecko versions prior to 1.9, use <code>-moz-Field</code>. See also <code>-moz-EvenTreeRow</code>.\"\n        }, {\n            \"value\": \"-moz-win-communicationstext\",\n            \"description\": \" Should be used for text in objects with <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-appearance\\\" title=\\\"The -moz-appearance CSS property is used in Gecko (Firefox) to display an element using a platform-native styling based on the operating system&apos;s theme.\\\"><code>-moz-appearance</code></a>: -moz-win-communications-toolbox;</code>.\"\n        }, {\n            \"value\": \"-moz-win-mediatext\",\n            \"description\": \" Should be used for text in objects with <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-appearance\\\" title=\\\"The -moz-appearance CSS property is used in Gecko (Firefox) to display an element using a platform-native styling based on the operating system&apos;s theme.\\\"><code>-moz-appearance</code></a>: -moz-win-media-toolbox</code>.\"\n        }, {\n            \"value\": \"-moz-activehyperlinktext\",\n            \"description\": \"User&apos;s preference for text color of active links. Should be used with the default document background color.\"\n        }, {\n            \"value\": \"-moz-default-background-color\",\n            \"description\": \" User&apos;s preference for the document background color.\"\n        }, {\n            \"value\": \"-moz-default-color\",\n            \"description\": \" User&apos;s preference for the text color.\"\n        }, {\n            \"value\": \"-moz-hyperlinktext\",\n            \"description\": \"User&apos;s preference for the text color of unvisited links. Should be used with the default document background color.\"\n        }, {\n            \"value\": \"-moz-visitedhyperlinktext\",\n            \"description\": \"User&apos;s preference for the text color of visited links. Should be used with the default document background color.\"\n        }]\n    },\n    \"<custom-ident>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\",\n        \"SUMMARY\": \"The <code>&lt;custom-ident&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data value denotes an arbitrary user-defined string used as an identifier. It is case-sensitive and in each context, several values are excluded to prevent misinterpretations.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-name\\\" title=\\\"The animation-name CSS property specifies a list of animations that should be applied to the selected element. Each name indicates a @keyframes at-rule that defines the property values for the animation sequence.\\\"><code>animation-name</code></a>\",\n            \"description\": \"Forbids the global CSS values, <code>unset</code>, <code>initial</code>, and <code>inherit</code>, and the value <code>none</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-reset\\\" title=\\\"The counter-reset CSS property is used to reset CSS Counters to a given value.\\\"><code>counter-reset</code></a>\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-increment\\\" title=\\\"The counter-increment CSS property is used to increase the value of CSS Counters by a given value. The counter&apos;s value can be reset using the counter-reset CSS property.\\\"><code>counter-increment</code></a>\"\n        }, {\n            \"value\": \"Forbids the global CSS values, <code>unset</code>, <code>initial</code>, and <code>inherit</code>, and the value <code>none</code>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\\\" title=\\\"The @counter-style CSS at-rule&#xA0;lets authors define&#xA0;specific counter styles that are not part of the predefined set of styles. A @counter-style rule defines how to convert a counter value into a string representation.\\\"><code>@counter-style</code></a>\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\\\" title=\\\"The list-style-type property specifies the appearance of a list item element. Because it is the only property that&#xA0;defaults to display:list-item, this is usually a &lt;li&gt; element, but can be any element with this display value.\\\"><code>list-style-type</code></a>\",\n            \"description\": \"Forbids the global CSS values, <code>unset</code>, <code>initial</code>, and <code>inherit</code>, as well as the values <code>none</code>, <code>inline</code>, and <code>outside</code>. Also quite a few predefined values are implemented by the different browsers: <code>disc</code>, <code>circle</code>, <code>square</code>, <code>decimal</code>, <code>cjk-decimal</code>, <code>decimal-leading-zero</code>, <code>lower-roman</code>, <code>upper-roman</code>, <code>lower-greek</code>, <code>lower-alpha</code>, <code>lower-latin</code>, <code>upper-alpha</code>, <code>upper-latin</code>, <code>arabic-indic</code>, <code>armenian</code>, <code>bengali</code>, <code>cambodian</code>, <code>cjk-earthly-branch</code>, <code>cjk-heavenly-stem</code>, <code>cjk-ideographic</code>, <code>devanagari</code>, <code>ethiopic-numeric</code>, <code>georgian</code>, <code>gujarati</code>, <code>gurmukhi</code>, <code>hebrew</code>, <code>hiragana</code>, <code>hiragana-iroha</code>, <code>japanese-formal</code>, <code>japanese-informal</code>, <code>kannada</code>, <code>katakana</code>, <code>katakana-iroha</code>, <code>khmer</code>, <code>korean-hangul-formal</code>, <code>korean-hanja-formal</code>, <code>korean-hanja-informal</code>, <code>lao</code>, <code>lower-armenian</code>, <code>malayalam</code>, <code>mongolian</code>, <code>myanmar</code>, <code>oriya</code>, <code>persian</code>, <code>simp-chinese-formal</code>, <code>simp-chinese-informal</code>, <code>tamil</code>, <code>telugu</code>, <code>thai</code>, <code>tibetan</code>, <code>trad-chinese-formal</code>, <code>trad-chinese-informal</code>, <code>upper-armenian</code>, <code>disclosure-open</code>, and <code>disclosure-close</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start\\\" title=\\\"The grid-row-start CSS property specifies a grid item&#x2019;s start position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start edge of its grid area.\\\"><code>grid-row-start</code></a><br>\\n <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-end\\\" title=\\\"The grid-row-end CSS property specifies a grid item&#x2019;s end position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-end edge of its grid area.\\\"><code>grid-row-end</code></a><br>\\n <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-start\\\" title=\\\"The grid-column-start CSS property specifies a grid item&#x2019;s start position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-start edge of its grid area.\\\"><code>grid-column-start</code></a><br>\\n <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-end\\\" title=\\\"The grid-column-end CSS property specifies a grid item&#x2019;s end position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-end edge of its grid area.\\\"><code>grid-column-end</code></a>\",\n            \"description\": \"Forbids the <code>span</code> value.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/will-change\\\" title=\\\"The will-change CSS property provides a way for authors to hint browsers about the kind of changes to be expected on an element, so that the browser can set up appropriate optimizations ahead of time before the element is actually changed.\\\"><code>will-change</code></a>\",\n            \"description\": \"Forbids the global CSS values, <code>unset</code>, <code>initial</code>, <code>inherit</code>, as well as the values <code>will-change</code>, <code>auto</code>, <code>scroll-position</code>, and <code>contents</code>.\"\n        }]\n    },\n    \"<flex>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex_value\",\n        \"SUMMARY\": \"The <strong><code>&lt;flex&gt;</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type denotes a flexible length within a grid container, which is declared as dimension with the unit <code>fr</code>.\",\n        \"VALUES\": []\n    },\n    \"<frequency>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/frequency\",\n        \"SUMMARY\": \"The <code>&lt;frequency&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> data type denotes a frequency dimension, like the pitch of a speaking voice.\",\n        \"VALUES\": []\n    },\n    \"<gradient>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/gradient\",\n        \"SUMMARY\": \"The <code>&lt;gradient&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> data type denotes a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> made of a progressive transition between two or more colors. A CSS gradient is not a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> but an image with <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/image#no_intrinsic\\\" title=\\\"CSS/image#no_intrinsic\\\">no intrinsic dimensions</a>; that is, it has no natural or preferred size, nor a preferred ratio. Its concrete size will match the one of the element it applies to.\",\n        \"VALUES\": []\n    },\n    \"<image>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/image\",\n        \"SUMMARY\": \"The <code>&lt;image&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\",\n        \"VALUES\": []\n    },\n    \"<integer>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\",\n        \"SUMMARY\": \"The <code>&lt;integer&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\",\n        \"VALUES\": []\n    },\n    \"<length>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/length\",\n        \"SUMMARY\": \"The <code>&lt;length&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type denotes distance measurements. It is a <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a '.' followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn't any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a> immediately followed by a length unit (<code>px</code>, <code>em</code>, <code>pc</code>, <code>in</code>, <code>mm</code>, …). Like for any CSS dimension, there is no space between the unit literal and the number. The length unit is optional after the <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a '.' followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn't any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a> <code>0</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>em</code>\",\n            \"description\": \"This unit represents the calculated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> of the element. If used on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> property itself, it represents the <em>inherited</em> font-size of the element.\\n <div class=\\\"note\\\">This unit is often used to create scalable layouts, which keep the <a href=\\\"http://24ways.org/2006/compose-to-a-vertical-rhythm\\\" class=\\\"external\\\">vertical rhythm of the page</a>, even when the user changes the size of the fonts. The CSS properties <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\\\" title=\\\"On block level elements, the line-height property specifies the minimum height of line boxes within the element.\\\"><code>line-height</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\" title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\"><code>margin-bottom</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\" title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\"><code>margin-top</code></a> often have&#xA0;values expressed in <strong>em</strong>.</div>\\n \"\n        }, {\n            \"value\": \"<code>ex</code>\",\n            \"description\": \"This unit represents the <a href=\\\"http://en.wikipedia.org/wiki/X-height\\\" class=\\\"external\\\">x-height</a> of the element&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font\\\" title=\\\"The font CSS property is either a shorthand property for setting font-style, font-variant, font-weight, font-size, line-height and font-family, or a way to set the element&apos;s font to a system font, using specific keywords.\\\"><code>font</code></a>. On fonts with the &apos;x&apos; letter, this is generally the height of lowercase letters in the font;<code style=\\\"white-space: nowrap;\\\"> 1ex &#x2248; 0.5em </code>in many fonts.\"\n        }, {\n            \"value\": \"<code>ch</code>\",\n            \"description\": \"This unit represents the width, or more precisely the advance measure, of the glyph &apos;0&apos; (zero, the Unicode character U+0030) in the element&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font\\\" title=\\\"The font CSS property is either a shorthand property for setting font-style, font-variant, font-weight, font-size, line-height and font-family, or a way to set the element&apos;s font to a system font, using specific keywords.\\\"><code>font</code></a>.\"\n        }, {\n            \"value\": \"<code>ic</code>\",\n            \"description\": \"Equal to the used advance measure of the &#x201C;&#x6C34;&#x201D; (CJK water ideograph, U+6C34) glyph found in the font used to render it.\"\n        }, {\n            \"value\": \"<code>rem</code>\",\n            \"description\": \"This unit represents the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> of the root element (e.g. the font-size of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html\\\" title=\\\"The HTML &lt;html&gt; element represents the root (top-level element) of an HTML document, so it is also referred to as the root element. All other elements must be descendants of this element.\\\"><code>&lt;html&gt;</code></a> element). When used on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> on this root element, it represents its initial value.\\n <div class=\\\"note\\\">This unit is practical in creating perfectly scalable layout. If not supported by the targeted browsers, such layout can be achieved using the <strong>em</strong> unit, though this is slightly more complex.</div>\\n \"\n        }, {\n            \"value\": \"<code>lh</code>\",\n            \"description\": \"Equal to the computed value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height \\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>line-height </code></a> property of the element on which it is used, converted to an absolute length.\"\n        }, {\n            \"value\": \"<code>rlh</code>\",\n            \"description\": \"Equal to the computed value of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height \\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>line-height </code></a> property on the root element, converted to an absolute length. When specified on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height \\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>line-height </code></a> properties of the root element, the rlh units refer to the properties&apos; initial value.\"\n        }, {\n            \"value\": \"<code>vh</code>\",\n            \"description\": \"1/100th of the height of the viewport.\"\n        }, {\n            \"value\": \"<code>vw</code>\",\n            \"description\": \"1/100th of the width of the viewport.\"\n        }, {\n            \"value\": \"<code>vi</code>\",\n            \"description\": \"Equal to 1% of the size of the initial containing block in the direction of the root element&#x2019;s <strong>inline axis</strong>.\"\n        }, {\n            \"value\": \"<code>vb</code>\",\n            \"description\": \"Equal to 1% of the size of the initial containing block in the direction of the root element&#x2019;s <strong>block axis</strong>.\"\n        }, {\n            \"value\": \"<code>vmin</code>\",\n            \"description\": \"1/100th of the minimum value of the height and the width of the viewport.\"\n        }, {\n            \"value\": \"<code>vmax</code>\",\n            \"description\": \"1/100th of the maximum value of the height and the width of the viewport.\"\n        }, {\n            \"value\": \"<code>px</code>\",\n            \"description\": \"Relative to the viewing device.<br>\\n For screen display, typically one device pixel (dot) of the display.<br>\\n For <em>printers</em> and very <em>high resolution screens</em> one CSS pixel implies multiple device pixels, so that the number of pixel per inch stays around 96.\"\n        }, {\n            \"value\": \"<code>mm</code>\",\n            \"description\": \"One millimeter.\"\n        }, {\n            \"value\": \"<code>q</code>\",\n            \"description\": \"A quarter of a millimeter (1/40th of a centimeter).\"\n        }, {\n            \"value\": \"<code>cm</code>\",\n            \"description\": \"One centimeter (10 millimeters).\"\n        }, {\n            \"value\": \"<code>in</code>\",\n            \"description\": \"One inch (2.54 centimeters).\"\n        }, {\n            \"value\": \"<code>pt</code>\",\n            \"description\": \"One point (1/72th of an inch).\"\n        }, {\n            \"value\": \"<code>pc</code>\",\n            \"description\": \"One pica (12 points).\"\n        }, {\n            \"value\": \"<code>mozmm</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"An experimental unit which attempts to render at exactly one millimeter regardless of the size or resolution of the display. This is rarely actually what you want, but may be useful in particular for mobile devices.\"\n        }]\n    },\n    \"<number>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/number\",\n        \"SUMMARY\": \"The <code>&lt;number&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> data type represents a number, either integer or fractional. Its syntax extends the one of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> data value. To represent a fractional value, add the fractional part — a '.' followed by one or several decimal digits — to any <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> data value. Like for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> data type, there isn't any unit associated to a <code>&lt;number&gt;</code>, which is not a CSS dimension.\",\n        \"VALUES\": []\n    },\n    \"<percentage>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\",\n        \"SUMMARY\": \"The <code>&lt;percentage&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data types represent a percentage value. Many <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference\\\">CSS properties</a> can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a '.' followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn't any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> immediately followed by the percentage sign <code>%</code>. Just as is the case with all other units in CSS, there isn't a space between the '%' and the number.\",\n        \"VALUES\": []\n    },\n    \"<position>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\",\n        \"SUMMARY\": \"The <code>&lt;position&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type denotes a coordinate in a 2D space used to set a location relative to a box.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"/* 1-value syntax */\\n<var>keyword</var>                  /* The corresponding edge, the other direction is corresponding to center, the middle of the edge */\\n<var>&lt;length&gt;</var> or <var>&lt;percentage&gt;</var> /* The position on the x-axis, 50% for the y-axis */\\n\\n/* 2-value syntax */\\n<var>keyword</var> <var>keyword</var>          /* A keyword for each direction, the order is irrelevant */\\n<var>keyword</var> <var>value</var>            /* The value is the offset for the edge defined by the keyword */\\n\"\n        }]\n    },\n    \"<ratio>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/ratio\",\n        \"SUMMARY\": \"The <code>&lt;ratio&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type, used for describing aspect ratios in <a class=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries\\\">media queries</a>, denotes the proportion between two unitless values. It is a strictly positive <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> followed by a slash ('/', Unicode<code> U+002F SOLIDUS</code>) and a second strictly positive <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a>. There may be spaces before and after the solidus.\",\n        \"VALUES\": []\n    },\n    \"<resolution>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/resolution\",\n        \"SUMMARY\": \"The <code>&lt;resolution&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data types, used in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries\\\">media queries</a>, denotes the density of pixels of an output device, its resolution. It is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a '.' followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn't any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> immediately followed by a unit of resolution (<code>dpi</code>, <code>dpcm</code>, ...). Like for any CSS dimension, there is no space between the unit literal and the number.\",\n        \"VALUES\": [{\n            \"value\": \"<code><a name=\\\"dpi\\\">dpi</a></code>\",\n            \"description\": \"This unit represents the number of <a href=\\\"http://en.wikipedia.org/wiki/Dots_per_inch\\\" class=\\\"external\\\">dots per inch</a>. A screen typically contains 72 or 96 dpi; a printed document usually reach much greater dpi. As 1 inch is 2.54 cm, <code>1dpi &#x2248; 0.39dpcm</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"dpcm\\\">dpcm</a></code>\",\n            \"description\": \"This unit represents the number of <a href=\\\"http://en.wikipedia.org/wiki/Dots_per_centimetre\\\" class=\\\"external\\\">dots per centimeter</a>. As 1 inch is 2.54 cm, <code>1dpcm &#x2248; 2.54dpi</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"dppx\\\">dppx</a></code>\",\n            \"description\": \"This unit represents the number of dots per <code>px</code> unit. Due to the 1:96 fixed ratio of CSS <code class=\\\"css\\\">in</code> to CSS <code class=\\\"css\\\">px</code>, <code class=\\\"css\\\">1dppx</code> is equivalent to <code class=\\\"css\\\">96dpi</code>, that corresponds to the default resolution of images displayed in CSS as defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image-resolution\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>image-resolution</code></a>.\"\n        }]\n    },\n    \"<shape-box>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-box\",\n        \"SUMMARY\": \"Shapes can be specified for <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-outside\\\">shape-outside</a></code> with a <strong><code>&lt;shape-box&gt;</code></strong> type, which is a reference to edges in the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/box_model\\\">CSS Box Model</a>.\",\n        \"VALUES\": [{\n            \"value\": \"\\n  <code>border-box</code>\",\n            \"description\": \"\\n  <p>Defines the shape enclosed by the outside border edge. This shape follows the normal border radius shaping rules for the outside of the border.</p>\\n \"\n        }, {\n            \"value\": \"\\n  <code>padding-box</code>\",\n            \"description\": \"\\n  <p>Defines the shape enclosed by the outside padding edge. The shape follows the normal border radius shaping rules for the inside of the border.</p>\\n \"\n        }, {\n            \"value\": \"\\n  <code>content-box</code>\",\n            \"description\": \"\\n  <p>Defines the shape enclosed by the outside content edge. Each corner radius of this box is the larger of 0 or <code>border-radius</code> - <code>border-width</code> - <code>padding</code>.</p>\\n \"\n        }]\n    },\n    \"<shape>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/shape\",\n        \"SUMMARY\": \"The <code>&lt;shape&gt;</code> <a title=\\\"CSS\\\" href=\\\"/en/CSS\\\">CSS</a> data type denotes the specific form of a region. This region is used to define on which part of an element some properties like <a title=\\\"The clip CSS property defines what portion of an element is visible. The clip property applies only to absolutely positioned elements, that is elements with position:absolute or position:fixed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/clip\\\"><code>clip</code></a> do apply.\",\n        \"VALUES\": [{\n            \"value\": \"<em>top</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>  representing the offset for the top of the rectangle relative to the top border of the element&apos;s box.&lt;/length&gt;\"\n        }, {\n            \"value\": \"<em>right</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> } representing the offset for the right of the rectangle relative to the left border of the element&apos;s box.&lt;/length&gt;\"\n        }, {\n            \"value\": \"<em>bottom</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>  representing the offset for the bottom of the rectangle relative to the top border of the element&apos;s box.&lt;/length&gt;\"\n        }, {\n            \"value\": \"<em>left</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>  representing the offset for the left of the rectangle relative to the left border of the element&apos;s box.&lt;/length&gt;\"\n        }]\n    },\n    \"<single-transition-timing-function>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/single-transition-timing-function\",\n        \"SUMMARY\": \"The <strong><code>&lt;single-transition-timing-function&gt;</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type denotes a mathematical function that describes how fast one-dimensional values change during transitions or animations. This in essence lets you establish an acceleration curve, so that the speed of the animation can vary over its duration. These functions are often called <em>easing functions<code>.</code></em>\",\n        \"VALUES\": [{\n            \"value\": \"<strong><em>x<sub>1</sub></em>, <em>y<sub>1</sub></em>, <em>x<sub>2</sub></em>, <em>y<sub>2</sub></em></strong>\",\n            \"description\": \"Are <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a> values representing the abscissas and ordinates of the P<sub>1</sub> and P<sub>2</sub> points defining the cubic B&#xE9;zier curve. x<sub>1</sub> and x<sub>2</sub> must be in the range [0, 1] or the value is invalid.\"\n        }, {\n            \"value\": \"<var>number_of_steps</var>\",\n            \"description\": \"Is a strictly positive <a title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\"><code>&lt;integer&gt;</code></a> representing the amount of equidistant treads composing the stepping function.\"\n        }, {\n            \"value\": \"<var>direction</var>\",\n            \"description\": \"Is a keyword indicating if it the function is <a href=\\\"https://en.wikipedia.org/wiki/Left-continuous#Directional_and_semi-continuity\\\" class=\\\"external\\\">left- or right-continuous</a>:\\n <ul>\\n  <li><code>start</code> denotes a left-continuous function, so that the first step happens when the animation begins;</li>\\n  <li><code>end</code> denotes a right-continuous function, so that the last step happens when the animation ends.</li>\\n </ul>\\n <code>end</code> is the default.\"\n        }]\n    },\n    \"<string>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/string\",\n        \"SUMMARY\": \"The <code>&lt;string&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type represents a string. It is formed by a <a class=\\\"external\\\" href=\\\"http://en.wikipedia.org/wiki/Unicode\\\">Unicode</a> characters delimited by either double (\\\") or single (') quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\",\n        \"VALUES\": []\n    },\n    \"<time>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/time\",\n        \"SUMMARY\": \"The <code>&lt;time&gt;</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> data type denotes time dimensions expressed in seconds or milliseconds. They consists of a​ ​​​​​​<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a '.' followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn't any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\",\n        \"VALUES\": []\n    },\n    \"<transform-function>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function\",\n        \"SUMMARY\": \"The <code>&lt;transform-function&gt;</code> CSS data type denotes a function applied to an element's representation in order to modify it. Usually such transform may be expressed by matrices and the resulting images can be determined using matrix multiplication on each point.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>matrix()</code></a>\",\n            \"description\": \"The <code>matrix()</code> CSS function specifies a homogeneous 2D transformation matrix comprised of the specified six values. The constant values of such matrices are implied and not passed as parameters; the other parameters are described in the column-major order.\"\n        }, {\n            \"value\": \"<code>matrix(a, b, c, d, tx, ty)</code> is a shorthand for <code>matrix3d(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1)</code>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>matrix3d()</code></a>\"\n        }, {\n            \"value\": \"The <code>matrix3d()</code> CSS function describes a 3D transform as a 4x4 homogeneous matrix. The 16 parameters are described in the column-major order.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>perspective()</code></a>\"\n        }, {\n            \"value\": \"The <code>perspective()</code> CSS function defines the distance between the z=0 plane and the user in order to give to the 3D-positioned element some perspective. Each 3D element with z&gt;0 becomes larger; each 3D-element with z&lt;0 becomes smaller. The strength of the effect is determined by the value of this property.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>rotate()</code></a>\"\n        }, {\n            \"value\": \"The <code>rotate()</code> CSS function defines a transformation that moves the element around a fixed point (as specified by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> property) without deforming it. The amount of movement is defined by the specified angle; if positive, the movement will be clockwise, if negative, it will be counter-clockwise. A rotation by 180&#xB0; is called <em>point reflection</em>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>rotate3d()</code></a>\"\n        }, {\n            \"value\": \"The <code>rotate3d()</code>CSS function defines a transformation that moves the element around a fixed axis without deforming it. The amount of movement is defined by the specified angle; if positive, the movement will be clockwise, if negative, it will be counter-clockwise.In opposition to rotations in the plane, the composition of 3D rotations is usually not commutative; it means that the order in which the rotations are applied is crucial.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateX\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>rotatex()</code></a>\"\n        }, {\n            \"value\": \"The <code>rotateX()</code>CSS function defines a transformation that moves the element around the abscissa without deforming it. The amount of movement is defined by the specified angle; if positive, the movement will be clockwise, if negative, it will be counter-clockwise. The axis of rotation passes by the origin, defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> CSS property.\",\n            \"description\": \"<code>rotateX(a)</code>is a shorthand for <code>rotate3D(1, 0, 0, a)</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateY\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>rotatey()</code></a>\",\n            \"description\": \"The <code>rotateY()</code>CSS function defines a transformation that moves the element around the ordinate without deforming it. The amount of movement is defined by the specified angle; if positive, the movement will be clockwise, if negative, it will be counter-clockwise. The axis of rotation passes by the origin, defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>rotateY(a)</code>is a shorthand for <code>rotate3D(0, 1, 0, a)</code>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateZ\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>rotatez()</code></a>\"\n        }, {\n            \"value\": \"The <code>rotateZ()</code>CSS function defines a transformation that moves the element around the z-axis without deforming it. The amount of movement is defined by the specified angle; if positive, the movement will be clockwise, if negative, it will be counter-clockwise. The axis of rotation passes by the origin, defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> CSS property.\",\n            \"description\": \"<code>rotateZ(a)</code>is a shorthand for <code>rotate3D(0, 0, 1, a)</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>scale()</code></a>\",\n            \"description\": \"The <code>scale()</code> CSS function modifies the size of the element. It can either augment or decrease its size and as the amount of scaling is defined by a vector, it can do so more in one direction than in another one. This transformation is characterized by a vector whose coordinates define how much scaling is done in each direction. If both coordinates of the vector are equal, the scaling is uniform, or isotropic, and the shape of the element is preserved. In that case, the scaling function defines a homothetic transformation.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale3d\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>scale3d()</code></a>\",\n            \"description\": \"The <code>scale3d()</code> CSS function modifies the size of an element. Because the amount of scaling is defined by a vector, it can resize different dimensions at different scales. This transformation is characterized by a vector whose coordinates define how much scaling is done in each direction. If all three coordinates of the vector are equal, the scaling is uniform, or isotropic, and the shape of the element is preserved. In that case, the scaling function defines a homothetic transformation.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleX\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>scalex()</code></a>\",\n            \"description\": \"The <code>scaleX()</code> CSS function modifies the abscissa of each element point by a constant factor, except if this scale factor is <code>1</code>, in which case the function is the identity transform. The scaling is not isotropic and the angles of the element are not conserved. <code>scaleX(-1)</code> defines an <a href=\\\"https://en.wikipedia.org/wiki/Axial_symmetry\\\" class=\\\"external\\\">axial symmetry</a> with a vertical axis passing by the origin (as specified by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> property).\"\n        }, {\n            \"value\": \"<code>scaleX(sx)</code> is a shorthand for <code>scale(sx, 1)</code> or for <code>scale3d(sx, 1, 1)</code>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>scaley()</code></a>\"\n        }, {\n            \"value\": \"The <code>scaleY()</code> CSS function modifies the ordinate of each element point by a constant factor except if this scale factor is <code>1</code>, in which case the function is the identity transform. The scaling is not isotropic and the angles of the element are not conserved. <code>scaleY(-1)</code> defines an <a href=\\\"https://en.wikipedia.org/wiki/Axial_symmetry\\\" class=\\\"external\\\">axial symmetry</a> with a horizontal axis passing by the origin (as specified by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> property).\",\n            \"description\": \"<code>scaleY(sy)</code> is a shorthand for <code>scale(1, sy)</code> or for <code>scale3d(1, sy, 1)</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleZ\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>scalez()</code></a>\",\n            \"description\": \"The <code>scaleZ()</code> CSS function modifies the z-coordinate of each element point by a constant factor, except if this scale factor is <code>1</code>, in which case the function is the identity transform. The scaling is not isotropic and the angles of the element are not conserved. <code>scaleZ(-1)</code> defines an <a href=\\\"https://en.wikipedia.org/wiki/Axial_symmetry\\\" class=\\\"external\\\">axial symmetry</a> along the z-axis passing by the origin (as specified by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a> property).\"\n        }, {\n            \"value\": \"<code>scaleZ(sz)</code> is a shorthand for <code>scale3d(1, 1, sz)</code>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skew\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>skew()</code></a>\"\n        }, {\n            \"value\": \"The <code>skew()</code> CSS function is a shear mapping, or transvection, distorting each point of an element by a certain angle in each direction. It is done by increasing each coordinate by a value proportionate to the specified angle and to the distance to the origin. The more far from the origin, the more away the point is, the greater will be the value added to it.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewX\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>skewx()</code></a>\"\n        }, {\n            \"value\": \"The <code>skewX()</code> CSS function is a horizontal shear mapping distorting each point of an element by a certain angle in the horizontal direction. It is done by increasing the abscissa coordinate by a value proportionate to the specified angle and to the distance to the origin. The more far from the origin, the more away the point is, the greater will be the value added to it.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>skewy()</code></a>\"\n        }, {\n            \"value\": \"The <code>skewY()</code> CSS function is a vertical shear mapping distorting each point of an element by a certain angle in the vertical direction. It is done by increasing the ordinate coordinate by a value proportionate to the specified angle and to the distance to the origin. The more far from the origin, the more away the point is, the greater will be the value added to it.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>translate()</code></a>\"\n        }, {\n            \"value\": \"The <code>translate()</code> CSS function moves the position of the element on the plane. This transformation is characterized by a vector whose coordinates define how much it moves in each direction.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate3d\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>translate3d()</code></a>\"\n        }, {\n            \"value\": \"The <code>translate3d()</code> CSS function moves the position of the element in the 3D space. This transformation is characterized by a 3-dimension vector whose coordinates define how much it moves in each direction.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>translatex()</code></a>\"\n        }, {\n            \"value\": \"The <code>translateX()</code> CSS function moves the element horizontally on the plane. This transformation is characterized by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> defining how much it moves horizontally.\",\n            \"description\": \"<code>translateX(tx)</code> is a shortcut for <code>translate(tx, 0)</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>translatey()</code></a>\",\n            \"description\": \"The <code>translateY()</code> CSS function moves the element vertically on the plane. This transformation is characterized by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> defining how much it moves vertically.\"\n        }, {\n            \"value\": \"<code>translateY(ty)</code> is a shortcut for <code>translate(0, ty)</code>.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateZ\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>translatez()</code></a>\"\n        }, {\n            \"value\": \"The <code>translateZ()</code> CSS function moves the element along the z-axis of the 3D space. This transformation is characterized by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> defining how much it moves.\",\n            \"description\": \"<code>translateZ(tz)</code> is a shorthand for <code>translate3d(0, 0, tz)</code>.\"\n        }]\n    },\n    \"<url>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/url\",\n        \"SUMMARY\": \"The <code>&lt;url&gt;</code> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> data type denotes a pointer to a resource. It has no proper syntax and can only be expressed through the <code>url()</code> functional notation.\",\n        \"VALUES\": []\n    },\n    \"@charset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@charset\",\n        \"SUMMARY\": \"The <strong><code>@charset</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> <a href=\\\"/en/CSS/At-rule\\\" title=\\\"At-rule\\\">at-rule</a> specifies the character encoding used in the style sheet. It must be the first element in the style sheet and not be preceded by any character; as it is not a <a href=\\\"/en/CSS/Syntax#nested_statements\\\" title=\\\"en/CSS/Syntax#nested_statements\\\">nested statement</a>, it cannot be used inside <a href=\\\"/en/CSS/At-rule#Conditional_Group_Rules\\\" title=\\\"en/CSS/At-rule#Conditional_Group_Rules\\\">conditional group at-rules</a>. If several <code>@charset</code> at-rules are defined, only the first one is used, and it cannot be used inside a <code>style</code> attribute on an HTML element or inside the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style\\\" title=\\\"The HTML &lt;style&gt; element contains style information for a document, or part of a document. By default, the style instructions written inside that element are expected to be CSS.\\\"><code>&lt;style&gt;</code></a> element where the character set of the HTML page is relevant.\",\n        \"VALUES\": [{\n            \"value\": \"<em>charset</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a> denoting the character encoding to be used. It must be the name of a web-safe character encoding defined in the <a href=\\\"http://www.iana.org/assignments/character-sets\\\" class=\\\"external\\\">IANA-registry</a>, and must be double-quoted, following exactly one space character (U+0020), and immediately terminated with a semicolon.&#xA0;If several names are associated with an encoding, only the one marked with&#xA0;<em>preferred</em> must be used.\"\n        }]\n    },\n    \"@counter-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\",\n        \"SUMMARY\": \"The<strong> <code>@counter-style</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> <a href=\\\"/en/CSS/At-rule\\\" title=\\\"en/CSS/At-rule\\\">at-rule</a> lets authors define specific counter styles that are not part of the predefined set of styles. A <code>@counter-style</code> rule defines how to convert a counter value into a string representation.\",\n        \"VALUES\": [{\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/system\\\"><code>system</code></a>\",\n            \"description\": \"Specifies the algorithm to be used for converting the integer value of a counter to a string representation.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/negative\\\"><code>negative</code></a>\",\n            \"description\": \"Lets the author specify symbols to be appended or prepended to the counter representation if the value is negative.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/prefix\\\"><code>prefix</code></a>\",\n            \"description\": \"Specifies a symbol that should be prepended to the marker representation. Prefixes are added to the representation in the final stage, so in the final representation of the counter, it comes before the negative sign.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/suffix\\\"><code>suffix</code></a>\",\n            \"description\": \"Specifies,&#xA0;similar to the prefix descriptor, a symbol that is appended to the marker representation. Prefixes come after the marker representation.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/range\\\"><code>range</code></a>\",\n            \"description\": \"Defines the range of values over which the counter style is applicable. If a counter style is used to represent a counter value outside of its ranges, the counter style will drop back to its fallback style.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/pad\\\"><code>pad</code></a>\",\n            \"description\": \"Is used when you need the marker representations to be of a minimum length. For example if you want the counters to start start at 01 and go through 02, 03, 04 etc, then the pad descriptor is to be used. For representations larger than the specified pad value, the marker is constructed as normal.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/fallback\\\"><code>fallback</code></a>\",\n            \"description\": \"Specifies a system to fall back into if either the specified system is unable to construct the representation of or a counter value or if the counter value outside the specified range. If the specified fallback also fails to represent the value, then the fallback style&apos;s fallback is used, if one is specified. If there are either no fallback systems described or if the chain of fallback systems are unable to represent a counter value, then it will ultimately fall back to the decimal style.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/symbols\\\"><code>symbols</code></a>\",\n            \"description\": \"Specifies the symbols that are to be used for the marker representations. Symbols can contain string, images or custom identifiers. How the symbols are used to construct the marker representation is up to the algorithm specified in the system descriptor. For example, if the system specified is fixed, then each of the N symbols specified in the descriptor will be used to represent the first N counter symbols. Once the specified set of symbols have exhausted, the fallback style will be used for the rest of the list.<br>\\n <br>\\n The below <code>@counter-style</code> rule uses images instead of character symbols.<br>\\n &#xA0;\\n <pre class=\\\"brush: css\\\">@counter-style winners-list {\\n  system: fixed;\\n  symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg);\\n  suffix: &quot; &quot;;\\n}</pre>\\n \"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/additive-symbols\\\"><code>additive-symbols</code></a>\",\n            \"description\": \"While the symbols specified in the symbols descriptor is used for constructing marker representation by most algorithms, some systems such as &apos;additive&apos; rely on <em>additive tuples</em> described in this descriptor. Each additive tuple consists of a counter symbol and a non negative integer weight. The additive tuples must be specified in the descending order of their weights.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/speak-as\\\"><code>speak-as</code></a>\",\n            \"description\": \"Describes how to read out the counter style in speech synthesizers, such as screen readers. For example, the value of the marker symbol can be read out as numbers or alphabets for ordered lists or as audio cues for unordered lists, based on the value of this descriptor.\"\n        }]\n    },\n    \"@document\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@document\",\n        \"SUMMARY\": \"The <strong><code>@document</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\\\">at-rule</a> restricts the style rules contained within it based on the URL of the document. It is designed primarily for user style sheets. A <code>@document</code> rule can specify one or more matching functions. If any of the functions apply to a URL, the rule will take effect on that URL.\",\n        \"VALUES\": []\n    },\n    \"@font-face\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face\",\n        \"SUMMARY\": \"The <strong><code>@font-face</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/At-rule\\\">at-rule</a> allows authors to specify online fonts to display text on their web pages. By allowing authors to provide their own fonts, <code>@font-face</code> eliminates the need to depend on the limited number of fonts users have installed on their computers. The <code>@font-face</code> at-rule may be used not only at the top level of a CSS, but also inside any <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/At-rule#Conditional_Group_Rules\\\">CSS conditional-group at-rule</a>.\",\n        \"VALUES\": [{\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family\\\"><code>font-family</code></a>\",\n            \"description\": \"Specifies a name that will be used as the font face value for font properties.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src\\\"><code>src</code></a>\",\n            \"description\": \"Specifies the resource containing the font data. This can be a URL to a remote font file location or the name of a font on the user&apos;s computer.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variant\\\" class=\\\"new\\\"><code>font-variant</code></a>\",\n            \"description\": \"A <a title=\\\"The font-variant property acts as a shorthand for the longhand properties: font-variant-caps, font-variant-numeric, font-variant-alternates, font-variant-ligatures, and font-variant-east-asian. You can also set the CSS Level 2 (Revision 1) values of font-variant, (that is, normal or small-caps), by using the font shorthand.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant\\\"><code>font-variant</code></a> value.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch\\\" class=\\\"new\\\"><code>font-stretch</code></a>\",\n            \"description\": \"A <a title=\\\"The font-stretch property selects a normal, condensed, or expanded face from a font.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch\\\"><code>font-stretch</code></a> value.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-weight\\\" class=\\\"new\\\"><code>font-weight</code></a>\",\n            \"description\": \"A <a title=\\\"The font-weight CSS property specifies the weight or boldness of the font. Some fonts are only available in normal and bold.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight\\\"><code>font-weight</code></a> value.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-style\\\"><code>font-style</code></a>\",\n            \"description\": \"A <a title=\\\"The font-style CSS property lets you select italic or oblique faces within a font-family. Italic forms are generally cursive in nature, usually using less horizontal space than their unstyled counterparts, while oblique faces are usually just sloped versions of the regular face. Both italic and oblique faces are simulated by artificially sloping the glyphs of the regular face (see font-synthesis for control over this).\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-style\\\"><code>font-style</code></a> value.\"\n        }, {\n            \"value\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range\\\"><code>unicode-range</code></a>\",\n            \"description\": \"The range of Unicode code points to be used from the font.\"\n        }]\n    },\n    \"@font-feature-values\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-feature-values\",\n        \"SUMMARY\": \"The <strong><code>@font-feature-values</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a title=\\\"At-rule\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\\\">at-rule</a> allows authors to use a common name in <a title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\"><code>font-variant-alternates</code></a> for feature activated differently in OpenType. It allows to simplify the CSS when using several fonts.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"@swash\\\"><code>@swash</code></a>\",\n            \"description\": \"Specifies a feature name that will work with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates#swash()\\\"><code>swash()</code></a> functional notation of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>. A swash feature value definition allows only one value: <code>ident1: 2</code> is valid when <code>ident2: 2 4</code> isn&apos;t.\"\n        }, {\n            \"value\": \"<a name=\\\"@annotation\\\"><code>@annotation</code></a>\",\n            \"description\": \"Specifies a feature name that will work with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates#annotation()\\\"><code>annotation()</code></a> functional notation of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>. An annotation feature value definition allows only one value: <code>ident1: 2</code> is valid when <code>ident2: 2 4</code> isn&apos;t.\"\n        }, {\n            \"value\": \"<a name=\\\"@ornaments\\\"><code>@ornaments</code></a>\",\n            \"description\": \"Specifies a feature name that will work with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates#ornaments()\\\"><code>ornaments()</code></a> functional notation of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>. An ornaments feature value definition allows only one value: <code>ident1: 2</code> is valid when <code>ident2: 2 4</code> isn&apos;t.\"\n        }, {\n            \"value\": \"<a name=\\\"@stylistic\\\"><code>@stylistic</code></a>\",\n            \"description\": \"Specifies a feature name that will work with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates#stylistic()\\\"><code>stylistic()</code></a> functional notation of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>. A stylistice feature value definition allows only one value: <code>ident1: 2</code> is valid when <code>ident2: 2 4</code> isn&apos;t.\"\n        }, {\n            \"value\": \"<a name=\\\"@styleset\\\"><code>@styleset</code></a>\",\n            \"description\": \"Specifies a feature name that will work with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates#styleset()\\\"><code>styleset()</code></a> functional notation of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>. A stylset feature value definition allows and illimited amount of values: <code>ident1: 2 4 12 1</code>maps to the OpenType values <code>ss02</code>, <code>ss04</code>, <code>ss12</code>, <code>ss01</code>. Note that values higher than <code>99</code> are valid, but doesn&apos;t map to any OpenType values and are ignored.\"\n        }, {\n            \"value\": \"<a name=\\\"@character-variant\\\"><code>@character-variant</code></a>\",\n            \"description\": \"Specifies a feature name that will work with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates#character-variant()\\\"><code>character-variant()</code></a> functional notation of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>. A character-variant feature value definition allows one or two values: <code>ident1: 2</code>&#xA0; maps to <code>cv02=1</code> and <code>ident2: 2 4</code> maps to <code>cv02)4</code> and <code>ident2: 2 4 5</code> isn&apos;t valid.\"\n        }]\n    },\n    \"@import\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@import\",\n        \"SUMMARY\": \"The <strong><code>@import</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\\\">at-rule</a> is used to import style rules from other style sheets. These rules must precede all other types of rules, except <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@charset\\\" title=\\\"The @charset CSS at-rule specifies the character encoding used in the style sheet. It must be the first element in the style sheet and not be preceded by any character; as it is not a nested statement, it cannot be used inside conditional group at-rules. If several @charset at-rules are defined, only the first one is used, and it cannot be used inside a style attribute on an HTML element or inside the &lt;style&gt; element where the character set of the HTML page is relevant.\\\"><code>@charset</code></a> rules; as it is not a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax#nested_statements\\\">nested statement</a>, <code>@import</code> cannot be used inside <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule#Conditional_Group_Rules\\\">conditional group at-rules</a>.\",\n        \"VALUES\": [{\n            \"value\": \"<em>url</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\"><code>&lt;string&gt;</code></a>&#xA0;or a <a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/uri\\\"><code>&lt;uri&gt;</code></a> representing the location of the resource to import. The URL may be absolute or relative. Note that the URL need not actually specify a file; it can just specify the package name and part, and the appropriate file is chosen automatically (e.g. <strong>chrome://communicator/skin/</strong>). <a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/The_Chrome_URL\\\">See here</a> for more information.\"\n        }, {\n            \"value\": \"<em>list-of-media-queries</em>\",\n            \"description\": \"Is a comma-separated list of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries\\\">media queries</a> conditioning the application of the CSS rules defined in the linked URL. If the browser does not support any these queries, it does not load the linked resource.\"\n        }]\n    },\n    \"@keyframes\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes\",\n        \"SUMMARY\": \"The <strong><code>@keyframes</code></strong> CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\\\">at-rule</a> lets authors control the intermediate steps in a CSS animation sequence by establishing keyframes (or waypoints) along the animation sequence that must be reached by certain points during the animation. This gives you more specific control over the intermediate steps of the animation sequence than you'd get when letting the browser handle everything automatically.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;identifier&gt;</code>\",\n            \"description\": \"A name identifying the keyframe list. This must match the identifier production in CSS syntax.\"\n        }, {\n            \"value\": \"<code>from</code>\",\n            \"description\": \"A starting offset of <code>0%</code>.\"\n        }, {\n            \"value\": \"<code>to</code>\",\n            \"description\": \"An ending offset of <code>100%</code>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a>\",\n            \"description\": \"A percentage of the time through the animation sequence at which the specified keyframe should occur.\"\n        }]\n    },\n    \"@media\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@media\",\n        \"SUMMARY\": \"The <code>@media</code> <a title=\\\"CSS\\\" href=\\\"/en/CSS\\\">CSS</a> <a title=\\\"en/CSS/At-rule\\\" href=\\\"/en/CSS/At-rule\\\">at-rule</a> associates a set of nested statements, in a CSS block that is delimited by curly braces, with a condition defined by a <a title=\\\"CSS media queries\\\" href=\\\"/en/CSS/Media_queries\\\">media query</a>. The <code>@media</code> at-rule may be used not only at the top level of a CSS, but also inside any <a title=\\\"en/CSS/At-rule#Conditional_Group_Rules\\\" href=\\\"/en/CSS/At-rule#Conditional_Group_Rules\\\">CSS conditional-group at-rule</a>.\",\n        \"VALUES\": [{\n            \"value\": \"all\",\n            \"description\": \"Suitable for all devices.\"\n        }, {\n            \"value\": \"print\",\n            \"description\": \"Intended for paged material and for documents viewed on screen in print preview mode. Please consult the section on <a title=\\\"https://developer.mozilla.org/en/CSS/Paged_Media\\\" href=\\\"/en/CSS/Paged_Media\\\">paged media</a>, and the <a title=\\\"https://developer.mozilla.org/en/CSS/Getting_Started/Media\\\" href=\\\"/en/CSS/Getting_Started/Media\\\">media section of the Getting Started tutorial</a> for information about formatting issues that are specific to paged media.\"\n        }, {\n            \"value\": \"screen\",\n            \"description\": \"Intended primarily for color computer screens.\"\n        }, {\n            \"value\": \"speech\",\n            \"description\": \"Intended for speech synthesizers. Note: CSS2 had a similar media type called &apos;aural&apos; for this purpose. See the appendix on aural style sheets for details.\"\n        }]\n    },\n    \"@namespace\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@namespace\",\n        \"SUMMARY\": \"<strong><code>@namespace</code></strong> is an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\\\" title=\\\"CSS at-rules\\\">at-rule</a> that defines <a href=\\\"https://developer.mozilla.org/en-US/docs/Namespaces\\\">XML namespaces</a> to be used in a <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/CSS\\\">CSS</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet\\\">style sheet</a>. The defined namespaces can be used to restrict the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors\\\">universal</a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors\\\">type</a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors\\\">attribute</a> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors\\\">selectors</a> to only select elements within that namespace. The <code>@namespace</code> rule is generally only useful when dealing with documents containing multiple namespaces—such as HTML5 with inline SVG or MathML, or XML that mixes multiple vocabularies.\",\n        \"VALUES\": []\n    },\n    \"@page\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@page\",\n        \"SUMMARY\": \"The <code>@page</code> CSS at-rule is used to modify some CSS properties when printing a document.<strong> </strong>You can't change all CSS properties with <code>@page</code>. You can only change the margins, orphans, widows, and page breaks of the document. Attempts to change any other CSS properties will be ignored.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@page/size\\\"><code>size</code></a>\",\n            \"description\": \"Specifies the target size and orientation of the page box&#x2019;s containing block. In the general case, where one page box is rendered onto one page sheet, it also indicates the size of the destination page sheet.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@page/marks\\\"><code>marks</code></a>\",\n            \"description\": \"Adds crop and/or registration marks to the document.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@page/bleed\\\"><code>bleed</code></a>\",\n            \"description\": \"Specifies the extent beyond the page box at which the page rendering is clipped.\"\n        }]\n    },\n    \"@styleset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@styleset\",\n        \"SUMMARY\": \"Editorial review completed.\",\n        \"VALUES\": []\n    },\n    \"@supports\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@supports\",\n        \"SUMMARY\": \"The <code>@supports</code> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> <a href=\\\"/en/CSS/At-rule\\\" title=\\\"en/CSS/At-rule\\\">at-rule</a> associates a set of nested statements, in a CSS block, that is delimited by curly braces, with a condition consisting of testing of CSS declarations, that is property-value pairs, combined with arbitrary conjunctions, disjunctions, and negations of them. Such a condition is called a <em>supports condition</em>.\",\n        \"VALUES\": []\n    },\n    \"@viewport\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport\",\n        \"SUMMARY\": \"The<strong> <code>@viewport</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> <a href=\\\"/en/CSS/At-rule\\\" title=\\\"en/CSS/At-rule\\\">at-rule</a> contains a set of nested descriptors in a CSS block that is delimited by curly braces. These descriptors control viewport settings, primarily on mobile devices.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/min-width\\\"><code>min-width</code></a>\",\n            \"description\": \"Used in the determination of the width of the viewport when the document is first displayed.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/max-width\\\"><code>max-width</code></a>\",\n            \"description\": \"Used in the determination of the width of the viewport when the document is first displayed.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/width\\\"><code>width</code></a>\",\n            \"description\": \"A shorthand descriptor for setting both <code>min-width</code> and <code>max-width</code>\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/min-height\\\"><code>min-height</code></a>\",\n            \"description\": \"Used in the determination of the height of the viewport when the document is first displayed.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/max-height\\\"><code>max-height</code></a>\",\n            \"description\": \"Used in the determination of the height of the viewport when the document is first displayed.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/height\\\"><code>height</code></a>\",\n            \"description\": \"A shorthand descriptor for setting both <code>min-height</code> and <code>max-height</code>\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/zoom\\\"><code>zoom</code></a>\",\n            \"description\": \"Sets the initial zoom factor.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/min-zoom\\\"><code>min-zoom</code></a>\",\n            \"description\": \"Sets the minimum zoom factor.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/max-zoom\\\"><code>max-zoom</code></a>\",\n            \"description\": \"Sets the maximum zoom factor.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/user-zoom\\\"><code>user-zoom</code></a>\",\n            \"description\": \"Controls whether or not the user should be able to change the zoom factor.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/orientation\\\"><code>orientation</code></a>\",\n            \"description\": \"Controls the document&apos;s orientation.\"\n        }]\n    },\n    \"Adjacent sibling selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors\",\n        \"SUMMARY\": \"This is referred to as an adjacent selector or next-sibling selector. It will select only the specified element that immediately follows the former specified element.\",\n        \"VALUES\": []\n    },\n    \"Alternative Style Sheets\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Alternative_style_sheets\",\n        \"SUMMARY\": \"Specifying <strong>alternative style sheets</strong> in a web page provides a way for users to see multiple versions of a page, based on their needs or preferences.\",\n        \"VALUES\": []\n    },\n    \"At-rule\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\",\n        \"SUMMARY\": \"An <strong>at-rule</strong> is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax#CSS_statements\\\">CSS statement</a> beginning with an at sign, '<code>@</code>' (<code>U+0040 COMMERCIAL AT</code>), followed by an identifier and includes everything up to the next semi-colon, '<code>;</code>' (<code>U+003B SEMICOLON</code>), or the next <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax#CSS_declarations_blocks\\\">CSS block</a>, whichever comes first.\",\n        \"VALUES\": []\n    },\n    \"Attribute selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors\",\n        \"SUMMARY\": \"Attribute selectors select an element using the presence of a given attribute or attribute value.\",\n        \"VALUES\": [{\n            \"value\": \"<code>[<em>attr</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em>=<em>value</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr and whose value is exactly &quot;value&quot;.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em>~=<em>value</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr whose value is a whitespace-separated list of words, one of which is exactly &quot;value&quot;.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em>|=<em>value</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr. Its value can be exactly &#x201C;value&#x201D; or can begin with &#x201C;value&#x201D; immediately followed by &#x201C;-&#x201D; (U+002D). It can be used for language subcode matches.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em>^=<em>value</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr and whose first value is prefixed by &quot;value&quot;.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em>$=<em>value</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr and whose last value is suffixed by &quot;value&quot;.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em>*=<em>value</em>]</code>\",\n            \"description\": \"Represents an element with an attribute name of attr and whose value contains at least one occurrence of string &quot;value&quot; as substring.\"\n        }, {\n            \"value\": \"<code>[<em>attr</em> <em>operator</em> <em>value</em> i]</code>\",\n            \"description\": \"Adding an <code>i</code> (or <code>I</code>) before the closing bracket causes the value to be compared case-insensitively (for characters within the ASCII range).\"\n        }]\n    },\n    \"CSS Animations\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations\",\n        \"SUMMARY\": \"<strong>CSS Animations</strong> is a module of CSS that defines how to animate the values of CSS properties over time, using keyframes. The behavior of these keyframe animations can be controlled by specifying their duration, their number of repetitions, and how they repeat.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Detecting_CSS_animation_support\\\">Detecting CSS animation support</a>\",\n            \"description\": \"Describes a technique for detecting if the browser supports CSS animations.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations\\\">Using CSS animations</a>\",\n            \"description\": \"Step-by-step tutorial about how to create animations using CSS, this article describes each relevant CSS property and at-rule and explains how they interact.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Tips\\\">CSS animations tips</a>\",\n            \"description\": \"Tips and tricks to help you make the most of CSS animations in your content. Currently offers a technique for re-playing an animation which has already run through to completion, which the API doesn&apos;t support inherently.\"\n        }]\n    },\n    \"CSS Background and Borders\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Background_and_Borders\",\n        \"SUMMARY\": \"<strong>CSS Background and Borders</strong> is a module of CSS that defines how background and borders of elements are described. Borders can be lines or images, boxes can have one or multiple backgrounds, have rounded corners, and shadows.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Background_and_Borders/Using_CSS_multiple_backgrounds\\\">Using CSS multiple backgrounds</a>\",\n            \"description\": \"Explains how to set backgrounds on elements and how they will interact with it.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Background_and_Borders/Scaling_background_images\\\">Scaling background images</a>\",\n            \"description\": \"Describes how to change the appearance of the background images, by stretching them or repeating them, to cover the whole background of the element, or not.\"\n        }]\n    },\n    \"CSS Box Model\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model\",\n        \"SUMMARY\": \"<strong>CSS Box Model</strong> is a CSS module that defines the rectangular boxes, including their padding and margin, that are generated for elements and laid out according to the visual formatting model.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">Introduction to the CSS box model</a>\",\n            \"description\": \"Explains one of the fundamental concept of CSS, the box model: describes the meaning of the margin, padding, as well as the different areas of a box.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing\\\">Mastering margin collapsing</a>\",\n            \"description\": \"In several cases, two adjacent margins are collapsed into one. This article describes when this is happening and how to control it.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Box-shadow_generator\\\">Box-shadow generator</a>\",\n            \"description\": \"An interactive tool that allows to visually create shadows and to generate the needed syntax for the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow\\\" title=\\\"The box-shadow property describes one or more shadow effects as a comma-separated list.\\\"><code>box-shadow</code></a> property.\"\n        }]\n    },\n    \"CSS Charsets\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Charsets\",\n        \"SUMMARY\": \"<strong>CSS Charsets</strong> is a module of CSS that allow to define the character set used in the stylesheet.\",\n        \"VALUES\": []\n    },\n    \"CSS Colors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Colors\",\n        \"SUMMARY\": \"<strong>CSS Colors</strong> is a module of CSS that deals with colors, color types and transparency.\",\n        \"VALUES\": []\n    },\n    \"CSS Columns\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Columns\",\n        \"SUMMARY\": \"<strong>CSS Columns</strong> is a module of CSS that defines a multi-column layout, allowing to express how content should flow between columns and how gaps and rules are handled.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Columns/Using_multi-column_layouts\\\">Using CSS multi-column layouts</a>\",\n            \"description\": \"Step-by-step tutorial about how to build layouts using several columns.\"\n        }]\n    },\n    \"CSS Compositing and Blending\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Compositing_and_Blending\",\n        \"SUMMARY\": \"<strong>CSS Compositing and Blending</strong> is a CSS module that defines how shapes of different elements are combined into a single image.\",\n        \"VALUES\": []\n    },\n    \"CSS Conditional Rules\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Conditional_Rules\",\n        \"SUMMARY\": \"<strong>CSS Conditional Rules</strong> is a CSS module that allows to define a set of rules that will only apply based on the capabilities of the processor or the document the style sheet is being applied to.\",\n        \"VALUES\": []\n    },\n    \"CSS Device Adaptation\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Device_Adaptation\",\n        \"SUMMARY\": \"<strong>CSS Device Adaptation</strong> is a CSS module that allows to define the size, zoom factor, and orientation of the viewport.\",\n        \"VALUES\": []\n    },\n    \"CSS Display\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Display\",\n        \"SUMMARY\": \"<strong>CSS Display</strong> is a module of CSS that defines how the CSS formatting box tree is generated from the document element tree and defines properties controlling it.\",\n        \"VALUES\": []\n    },\n    \"CSS Flexible Box Layout\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout\",\n        \"SUMMARY\": \"<strong>CSS Flexible Box Layout</strong> is a module of CSS that defines a CSS box model optimized for user interface design. In the flex layout model, the children of a flex container can be laid out in any direction, and can “flex” their sizes, either growing to fill unused space or shrinking to avoid overflowing the parent. Both horizontal and vertical alignment of the children can be easily manipulated. Nesting of these boxes (horizontal inside vertical, or vertical inside horizontal) can be used to build layouts in two dimensions.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes\\\">Using CSS flexible boxes</a>\",\n            \"description\": \"Step-by-step tutorial about how to build layouts using this feature.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_flexbox_to_lay_out_web_applications\\\">Using flexbox to lay out Web applications</a>\",\n            \"description\": \"Tutorial explaining how to use flexbox in the specific context of Web applications.\"\n        }]\n    },\n    \"CSS Fonts\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts\",\n        \"SUMMARY\": \"<strong>CSS Fonts</strong> is a module of CSS that defines font-related properties and how font resources are loaded. It allows to define the style of a font, like its family, its size or its weight, and the variant of the glyph to be used, for a font that has several glyphs for one character. It also allows to define the height of a line.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face\\\" title=\\\"Technical review completed.\\\"><code>@font-face</code></a>\",\n            \"description\": \"\\n <div class=\\\"index\\\">\\n <ul>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>font-family</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>font-feature-settings</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-style\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>font-style</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variant\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>font-variant</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-weight\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>font-weight</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>font-stretch</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>src</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>unicode-range</code></a></li>\\n </ul>\\n </div>\\n \"\n        }]\n    },\n    \"CSS Generated Content\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Generated_Content\",\n        \"SUMMARY\": \"<strong>CSS Generated Content</strong> is a module of CSS that defines how to add content to an element.\",\n        \"VALUES\": []\n    },\n    \"CSS Grid Layout\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout\",\n        \"SUMMARY\": \"<strong>CSS Grid layout</strong> has been designed to provide a two-dimensional layout method for CSS, with the ability to lay out items in rows and columns. The CSS grid can be used to achieve many different layouts. It excels at dividing a page into major regions, or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.\",\n        \"VALUES\": []\n    },\n    \"CSS Images\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Images\",\n        \"SUMMARY\": \"<strong>CSS Images</strong> is a module of CSS that defines what types of images can be used (the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> type, containing URLs, gradients and other types of images), how to resize them and how they, and other replaced content, interact with the different layout models.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Images/Using_CSS_gradients\\\">Using CSS gradients</a>\",\n            \"description\": \"Presents a specific type of CSS images, <em>gradients</em>, and how to create and use these.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Images/Implementing_image_sprites_in_CSS\\\">Implementing image sprites in CSS</a>\",\n            \"description\": \"Describes the common technique grouping several images in one single document to save download requests and speed up the availability of a page.\"\n        }]\n    },\n    \"CSS Lists and Counters\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters\",\n        \"SUMMARY\": \"<strong>CSS Lists and Counters</strong> is a module of CSS that defines how lists are laid out, how the list marker can be styled and how authors can create new counters.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\\\" title=\\\"The @counter-style CSS at-rule&#xA0;lets authors define&#xA0;specific counter styles that are not part of the predefined set of styles. A @counter-style rule defines how to convert a counter value into a string representation.\\\"><code>@counter-style</code></a>\",\n            \"description\": \"\\n <div class=\\\"index\\\">\\n <ul>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/system\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>system</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/additive-symbols\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>additive-symbols</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/negative\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>negative</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/prefix\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>prefix</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/suffix\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>suffix</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/range\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>range</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/pad\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>pad</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/speak-as\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>speak-as</code></a></li>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style/fallback\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>fallback</code></a></li>\\n </ul>\\n </div>\\n \"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Consistent_list_indentation\\\">Consistent list indentation</a>\",\n            \"description\": \"Explains how to reach a consistent indentation between different browsers.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters\\\">Using CSS counters</a>\",\n            \"description\": \"Describes how to use counters to be able to use numbering outside of traditional list elements or to perform complex counting.\"\n        }]\n    },\n    \"CSS Logical Properties\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties\",\n        \"SUMMARY\": \"<strong>CSS Logical Properties</strong> is a module of CSS that defines logical mapping to physical properties to control the layout.\",\n        \"VALUES\": []\n    },\n    \"CSS Masks\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Masks\",\n        \"SUMMARY\": \"<strong>CSS Masks</strong> is a CSS module that defines means, including masking and clipping, for partially or fully hiding portions of visual elements.\",\n        \"VALUES\": []\n    },\n    \"CSS Miscellaneous\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Miscellaneous\",\n        \"SUMMARY\": \"These pages contain CSS properties that are highly experimental or don't fit in any other categories.\",\n        \"VALUES\": []\n    },\n    \"CSS Namespaces\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Namespaces\",\n        \"SUMMARY\": \"<strong>CSS Namespaces</strong> is a CSS module that allows authors to specify <a href=\\\"https://developer.mozilla.org/en-US/docs/Namespaces\\\">XML namespaces</a> in CSS.\",\n        \"VALUES\": []\n    },\n    \"CSS Pages\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Pages\",\n        \"SUMMARY\": \"<strong>CSS Pages</strong> is a module of CSS that defines how page switches are handled, as well as orphans and widows.\",\n        \"VALUES\": []\n    },\n    \"CSS Positioning\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning\",\n        \"SUMMARY\": \"<strong>CSS Positioning</strong> is a module of CSS that defines how to absolutely and relavitely position elements on the page.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index\\\">Understanding CSS z-index</a>\",\n            \"description\": \"Presents the notion of stacking context and explain how z-ordering works, with several examples.\"\n        }]\n    },\n    \"CSS Properties Reference\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference\",\n        \"SUMMARY\": \"The following is a basic list of the most common CSS properties with the equivalent of the DOM notation which is usually accessed from JavaScript:\",\n        \"VALUES\": []\n    },\n    \"CSS Ruby\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Ruby\",\n        \"SUMMARY\": \"<strong>CSS Ruby</strong> is a module of CSS that provides the rendering model and formatting controls related to display ruby annotation, a form of interlinear annotation, short runs of text alongside the base text.\",\n        \"VALUES\": []\n    },\n    \"CSS Scroll Snap Points\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap_Points\",\n        \"SUMMARY\": \"<strong>CSS Scroll Snap Points</strong> is a module of CSS that defines properties and values that provide the author with the ability to control layout through logical, rather than physical, direction and dimension mappings\",\n        \"VALUES\": []\n    },\n    \"CSS Selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors\",\n        \"SUMMARY\": \"<strong>Selectors</strong> define to which elements a set of CSS rules apply.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors\\\">Type selectors</a>\",\n            \"description\": \"This basic selector chooses all elements that matches the given <em>name</em>.<br>\\n <strong>Syntax:</strong> <code><var>eltname</var></code><br>\\n <strong>Example:</strong> <code>input</code> will match any <a title=\\\"The HTML &lt;input&gt; element is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\"><code>&lt;input&gt;</code></a> element.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors\\\">Class selectors</a>\",\n            \"description\": \"This basic selector chooses elements based on the value of their <code>class</code> attribute.<br>\\n <strong>Syntax:</strong> <code>.<var>classname</var></code><br>\\n <strong>Example:</strong> <code>.index</code> will match any element that has the class <code>index</code> (likely defined by a <code>class=&quot;index&quot;</code> attribute or similar).\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors\\\">ID selectors</a>\",\n            \"description\": \"This basic selector chooses nodes based on the value of its <code>id</code> attribute. There should be only one element with a given ID in a document.<br>\\n <strong>Syntax:</strong> <code>#<var>idname</var></code><br>\\n <strong>Example:</strong> <code>#toc</code> will match the element that has the id toc (likely defined by a <code>id=&quot;toc&quot;</code> attribute or similar).\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors\\\">Universal selectors</a>\",\n            \"description\": \"This basic selector chooses all nodes. It also exists in a one-namespace only and in an all-namespace variant too.<br>\\n <strong>Syntax:</strong> <code>*&#xA0;ns|*&#xA0;*|*</code><br>\\n <strong>Example:</strong> <code>*</code> will match all the elements of the document.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors\\\">Attribute selectors</a>\",\n            \"description\": \"This basic selector chooses nodes based on the value of one of its attributes.<br>\\n <strong>Syntax:</strong> <code>[attr] [attr=value] [attr~=value] [attr|=value] [attr^=value] [attr$=value] [attr*=value]</code><br>\\n <strong>Example:</strong> <code>[autoplay]</code> will match all the elements that have the <code>autoplay</code> attribute set (to any value).\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors\\\">Adjacent sibling selectors</a>\",\n            \"description\": \"The <code>&apos;+&apos;</code> combinator selects nodes that immediately follow the former specified element.<br>\\n <strong>Syntax:</strong> <code><var>A</var> + <var>B</var></code><br>\\n <strong>Example:</strong>&#xA0;div<code>&#xA0;+ p</code>&#xA0;will match any <a title=\\\"The HTML &lt;p&gt; element represents a paragraph of text.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p\\\"><code>&lt;p&gt;</code></a> that immediately follows a <a title=\\\"The HTML &lt;div&gt; element is the generic container for flow content and does not inherently represent anything. Use it to group elements for purposes such as styling (using the class or id attributes), marking a section of a document in a different language (using the lang attribute), and so on.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div\\\"><code>&lt;div&gt;</code></a>.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors\\\">General sibling selectors</a>\",\n            \"description\": \"The <code>&apos;~&apos;</code> combinator selects nodes that follow (not necessarily immediately) the former specified element, if both elements shared the same parent.<br>\\n <strong>Syntax:</strong> <code><var>A</var> ~ <var>B</var></code><br>\\n <strong>Example:</strong> <code>p ~ span</code> will match all <a title=\\\"The HTML &lt;span&gt; element is a generic inline container for phrasing content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values, such as lang.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span\\\"><code>&lt;span&gt;</code></a> elements that follow a <a title=\\\"The HTML &lt;p&gt; element represents a paragraph of text.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p\\\"><code>&lt;p&gt;</code></a> element inside the same element.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors\\\">Child selectors</a>\",\n            \"description\": \"The <code>&apos;&gt;&apos;</code> combinator selects nodes that are direct children of the former specified element.<br>\\n <strong>Syntax:</strong> <code><var>A</var> &gt; <var>B</var></code><br>\\n <strong>Example:</strong> <code>ul &gt; li</code> will match all <a title=\\\"The HTML &lt;li&gt; element is used to represent an item in a list. It must be contained in a parent element: an ordered list (&lt;ol&gt;), an unordered list (&lt;ul&gt;), or a menu (&lt;menu&gt;). In menus and unordered lists, list items are usually displayed using bullet points. In ordered lists, they are usually displayed with an ascending counter on the left, such as a number or letter.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li\\\"><code>&lt;li&gt;</code></a> elements that are inside a <a title=\\\"The HTML &lt;ul&gt; element represents an unordered list of items, typically rendered as a bulleted list.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul\\\"><code>&lt;ul&gt;</code></a> element.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors\\\">Descendant selectors</a>\",\n            \"description\": \"The <code>&apos; &apos;</code> combinator selects nodes that are children (not necessary direct children) of the former specified element.<br>\\n <strong>Syntax:</strong> <code>A B</code><br>\\n <strong>Example:</strong> <code>div span</code> will match any <a title=\\\"The HTML &lt;span&gt; element is a generic inline container for phrasing content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values, such as lang.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span\\\"><code>&lt;span&gt;</code></a> element that is inside a <a title=\\\"The HTML &lt;div&gt; element is the generic container for flow content and does not inherently represent anything. Use it to group elements for purposes such as styling (using the class or id attributes), marking a section of a document in a different language (using the lang attribute), and so on.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div\\\"><code>&lt;div&gt;</code></a> element.\"\n        }]\n    },\n    \"CSS Shapes\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Shapes\",\n        \"SUMMARY\": \"<strong>CSS Shapes</strong> is a CSS module that defines geometric shapes for use in CSS values.\",\n        \"VALUES\": []\n    },\n    \"CSS Table\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Table\",\n        \"SUMMARY\": \"<strong>CSS Table</strong> is a CSS module that defines how to lay out table data.\",\n        \"VALUES\": []\n    },\n    \"CSS Text\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Text\",\n        \"SUMMARY\": \"<strong>CSS Text</strong> is a module of CSS that defines how to perform text manipulation, like line breaking, justification and alignment, white space handling, and text transformation.\",\n        \"VALUES\": []\n    },\n    \"CSS Text Decoration\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Text_Decoration\",\n        \"SUMMARY\": \"<strong>CSS Text Decoration</strong> is a module of CSS that defines features relating to text decoration, such as underlines, text shadows, and emphasis marks.\",\n        \"VALUES\": []\n    },\n    \"CSS Transforms\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transforms\",\n        \"SUMMARY\": \"<strong>CSS Transforms</strong> is a module of CSS that defines how elements styled with CSS can be transformed in two-dimensional or three-dimensional space.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transforms/Using_CSS_transforms\\\">Using CSS transforms</a>\",\n            \"description\": \"Step-by-step tutorial about how to transform elements styled with CSS.\"\n        }]\n    },\n    \"CSS Transitions\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions\",\n        \"SUMMARY\": \"<strong>CSS Transitions</strong> is a module of CSS that defines how to create smooth transitions between values of given CSS properties. It allows to create them but also to define their evolution, using timing functions.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions\\\">Using CSS transitions</a>\",\n            \"description\": \"Step-by-step tutorial about how to create smooth transitions using CSS. This article describes each relevant CSS property and explains how they interact.\"\n        }]\n    },\n    \"CSS Tutorials\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Tutorials\",\n        \"SUMMARY\": \"Learning CSS may be a daunting task. In order to help you, we have written numerous <strong>tutorials about CSS</strong>. Some are aimed at complete beginners, while others present complex features to be used by more experienced users.\",\n        \"VALUES\": [{\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Getting_Started\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Getting_Started\\\">Getting started</a>\",\n            \"description\": \"\\n    This guide is aimed at <u>complete beginners</u>: You haven&apos;t written one single line of CSS? &#x2014; this is for you. It explains the fundamental concepts of the language and guides you in writing basic stylesheets.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_multiple_backgrounds\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_multiple_backgrounds\\\">Using multiple backgrounds</a>\",\n            \"description\": \"\\n    Backgrounds are fundamental for nice styling: CSS allows you to set several of them on each box. This tutorial explains how they interact and how to achieve nice effects.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Scaling_background_images\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Scaling_background_images\\\">Scaling background images</a>\",\n            \"description\": \"\\n    CSS allows you to resize images used as an element&apos;s background. This tutorial describes how to achieve this in a simple way.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Media_queries\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Media_queries\\\">Media queries</a>\",\n            \"description\": \"\\n    The size of the screens, or the kind of devices like touchscreens or printed sheets vary greatly nowadays. Media queries are the fundamental building blocks in achieving Web sites that render everywhere in their best quality.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Understanding_z-index\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Understanding_z-index\\\">Understanding z-index</a>\",\n            \"description\": \"\\n    Controlling superposition of boxes is a basic feature that is very quickly needed by Web developers. Though not that difficult, it requires a basic knowledge of CSS.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Counters\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Counters\\\">CSS Counters</a>\",\n            \"description\": \"\\n    Counting items and pages is an easy task in CSS. Learn to use <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-reset\\\" title=\\\"\\\"><code>counter-reset</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-increment\\\" title=\\\"\\\"><code>counter-increment</code></a>, <a class=\\\"new\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counters\\\" title=\\\"\\\"><code>counters()</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter\\\" title=\\\"\\\"><code>counter()</code></a>.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Tutorials/Using_CSS_animations\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_animations\\\">CSS Animations</a>\",\n            \"description\": \"\\n    CSS3 Animations allow you to define configurations of style, as <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/@keyframes\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/@keyframes\\\">keyframes</a>, and to transition between them defining an animation.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Tutorials/Using_CSS_transitions\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_transitions\\\">CSS Transitions</a>\",\n            \"description\": \"\\n    CSS3 Transitions allow you to define an animation between several styles and to control the way this transition happens.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Tutorials/Using_CSS_transforms\\\">CSS Transforms</a>\",\n            \"description\": \"\\n    Transforms allow you to change the position of elements by modifying their coordinate space: it allows for translating, rotating, and deforming them in the 2D or 3D spaces.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_gradients\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_gradients\\\">CSS Gradients</a>\",\n            \"description\": \"\\n    Gradients are images that transition smoothly from one color to another. There are several types of gradients allowed in CSS: linear or radial, repeating or not. This tutorial describes how to use them.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_multi-column_layouts\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_multi-column_layouts\\\">CSS multi-column layouts</a>\",\n            \"description\": \"\\n    CSS3 introduces a new layout allowing you to easily define multiple columns in an element. Though multi-column text is not that common on devices like screens, this is particularly useful on printed pages, or for indexes.\"\n        }, {\n            \"value\": \"\\n    <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_flexible_boxes\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_flexible_boxes\\\">CSS flexible boxes layouts</a>\",\n            \"description\": \"\\n    This new layout allow you to give boxes flexibility, allowing them to be resized smoothly. It is a powerful way to describe complex interfaces.\"\n        }]\n    },\n    \"CSS Types\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types\",\n        \"SUMMARY\": \"\",\n        \"VALUES\": []\n    },\n    \"CSS User Interface\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_User_Interface\",\n        \"SUMMARY\": \"<strong>CSS User Interface</strong> is a CSS module that allows to define the rendering and functionality of user interface related features.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_User_Interface/Using_URL_values_for_the_cursor_property\\\">Using URL values for the <code>cursor</code> property</a>\",\n            \"description\": \"Explains and shows how URL can be used with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\\\" title=\\\"The cursor CSS property specifies the mouse cursor displayed when the mouse pointer is over an element.\\\"><code>cursor</code></a> property to produce custom cursors.\"\n        }]\n    },\n    \"CSS Writing Modes\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Writing_Modes\",\n        \"SUMMARY\": \"<strong>CSS Writing Modes</strong> is a CSS module that defines various international writing modes, such as left-to-right (e.g. used by Latin and Indic scripts), right-to-left (e.g. used by Hebrew or Arabic scripts), bidirectional (used when mixing left-to-right and right-to-left scripts) and vertical (e.g. used by some Asian scripts).\",\n        \"VALUES\": []\n    },\n    \"CSS animated properties\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties\",\n        \"SUMMARY\": \"Some CSS properties can be animated, that is can change in a smooth way when its value change, either when used by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations\\\">CSS Animations</a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions\\\">CSS Transitions</a>.\",\n        \"VALUES\": []\n    },\n    \"CSS documentation index\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Index\",\n        \"SUMMARY\": \"<strong>Found 767 pages:</strong>\",\n        \"VALUES\": []\n    },\n    \"CSS reference\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference\",\n        \"SUMMARY\": \"Technical review completed.\",\n        \"VALUES\": []\n    },\n    \"CSS3\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS3\",\n        \"SUMMARY\": \"<strong>CSS3</strong> is the latest evolution of the <em>Cascading Style Sheets</em> language and aims at extending CSS2.1. It brings a lot of long-awaited novelties, like rounded corners, shadows, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_gradients\\\" title=\\\"Using CSS gradients\\\">gradients</a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions\\\" title=\\\"CSS transitions\\\">transitions</a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations\\\" title=\\\"CSS animations\\\">animations</a>, as well as new layouts like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_multi-column_layouts\\\" title=\\\"Using CSS multi-column layouts\\\">multi-columns</a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes\\\">flexible box</a> or grid layouts.\",\n        \"VALUES\": []\n    },\n    \"CSSOM View\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View\",\n        \"SUMMARY\": \"<strong>CSSOM View</strong> is a module that allows to manipulate the visual view of a document, in particular its scrolling behavior.\",\n        \"VALUES\": []\n    },\n    \"Cascade\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade\",\n        \"SUMMARY\": \"The <em>cascade</em> is a fundamental feature of CSS. It is an algorithm defining how to combine properties values originating from different sources. It lies at the core of CSS as stressed by its name: <em>Cascading</em> Style Sheets.\",\n        \"VALUES\": []\n    },\n    \"Child selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors\",\n        \"SUMMARY\": \"The <code>&gt;</code> combinator separates two selectors and matches only those elements matched by the second selector that are <strong>direct</strong> children of elements matched by the first. By contrast, when two selectors are combined with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors\\\">descendant selector</a>, the combined selector expression matches those elements matched by the second selector for which there exists an ancestor element matched by the first selector, regardless of the number of \\\"hops\\\" up the DOM.\",\n        \"VALUES\": []\n    },\n    \"Class selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors\",\n        \"SUMMARY\": \"In an HTML document, CSS class selectors match an element based on the contents of the element's class attribute. The <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#attr-class\\\">class</a></code> attribute is defined as a space-separated list of items, and one of those items must match exactly the class name given in the selector.\",\n        \"VALUES\": []\n    },\n    \"Comments\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Comments\",\n        \"SUMMARY\": \"Comments are used to add explanatory notes or prevent the browser from interpreting parts of the style sheet.\",\n        \"VALUES\": []\n    },\n    \"Computed value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/computed_value\",\n        \"SUMMARY\": \"The <strong>computed value</strong> of a CSS property is computed from the specified value by:\",\n        \"VALUES\": []\n    },\n    \"Custom properties (--*)\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/--*\",\n        \"SUMMARY\": \"Property names that are prefixed with <code>--</code>, like <code>--example-name</code>, represent <em>custom properties</em> that contain a value than can be reused throughout the document using the (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/var\\\" title=\\\"The var() function can be used instead of any part of a value in any property on an element. The var() function can not be used as property names, selectors&#xA0;or anything else besides property values. (Doing so usually produces invalid syntax&#xA0;or else a value whose meaning has no connection to the variable.)\\\"><code>var()</code></a>) function.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;declaration-value&gt;</code>\",\n            \"description\": \"This value matches any sequence of one or more tokens, so long as the sequence does not contain an unallowed tokens. It represents the entirety of what a valid declaration can have as its value.\"\n        }]\n    },\n    \"Descendant selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors\",\n        \"SUMMARY\": \"The <strong>descendant combinator</strong> — typically represented by a single space ( ) character — combines two selectors such that elements matched by the second selector are selected if they have an ancestor element matching the first selector. Selectors that utilize a descendant combinator are called <dfn>descendant selectors</dfn>.\",\n        \"VALUES\": []\n    },\n    \"Draft Implementations of CSS Features\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Draft_Implementations_of_CSS_Features\",\n        \"SUMMARY\": \"Mozilla supports a number of extensions to <a href=\\\"/en/CSS\\\" title=\\\"en/CSS\\\">CSS</a> that are prefixed with<code> -moz-</code>. The following list contains all Mozilla extensions that are implementations of features that are being standardized by the W3C. Proprietary features are omitted.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"...\"\n        }]\n    },\n    \"Filters Effects\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Filters_Effects\",\n        \"SUMMARY\": \"<strong>Filter Effects</strong> is a module of CSS that defines a way of processing an element’s rendering before it is displayed in the document.\",\n        \"VALUES\": []\n    },\n    \"General sibling selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors\",\n        \"SUMMARY\": \"The <code>~</code> combinator separates two selectors and matches the second element only if it is preceded by the first, and both share a common parent.\",\n        \"VALUES\": []\n    },\n    \"ID selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors\",\n        \"SUMMARY\": \"In an HTML document, CSS ID selectors match an element based on the contents of that element's <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#attr-id\\\">id</a></code> attribute, which must match exactly the value given in the selector.\",\n        \"VALUES\": []\n    },\n    \"Layout mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Layout_mode\",\n        \"SUMMARY\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <strong>layout mode</strong>, sometimes abbreviated as <em>layout</em>, is an algorithm determining the position and the size of boxes based on the way they interact with their sibling and ancestor boxes. There are several of them:\",\n        \"VALUES\": []\n    },\n    \"List of Proprietary CSS Features\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/List_of_Proprietary_CSS_Features\",\n        \"SUMMARY\": \"This list includes proprietary extensions to CSS in different browser engines which are not experimental implementations of features being standardized (see <a href=\\\"/en/CSS/Draft_Implementations_of_CSS_Features\\\" title=\\\"en/CSS/Draft_Implementations_of_CSS_Features\\\">Draft Implementations of CSS Features</a> for a list of these).\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"\\\"><code>background-image</code></a>\"\n        }]\n    },\n    \"Media queries\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries\",\n        \"SUMMARY\": \"<strong>Media Queries</strong> is a module of CSS that defines expressions allowing to tailor presentations to a specific range of output devices without changing the content itself.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries\\\">Using media queries</a>\",\n            \"description\": \"Presents what media queries are doing and explains the possible expressions.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Testing_media_queries\\\">Testing media queries</a>\",\n            \"description\": \"Explains how to test a media query programmatically, from JavaScript.\"\n        }]\n    },\n    \"Motion Path\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Motion_Path\",\n        \"SUMMARY\": \"<strong>Motion Path</strong> is a module that allows authors to animate any graphical object along a custom path.\",\n        \"VALUES\": []\n    },\n    \"Mozilla CSS Extensions\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_Extensions\",\n        \"SUMMARY\": \"Mozilla supports a number of extensions to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> that are prefixed with <code>-moz-</code>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"For all properties\"\n        }]\n    },\n    \"Mozilla CSS support chart\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_support_chart\",\n        \"SUMMARY\": \"This page lists supported CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla_CSS_support_chart#Selectors\\\" title=\\\"Mozilla_CSS_support_chart#Selectors\\\">selectors</a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla_CSS_support_chart#properties\\\" title=\\\"Mozilla_CSS_support_chart#properties\\\">properties</a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla_CSS_support_chart#.40-rules\\\" title=\\\"Mozilla_CSS_support_chart#.40-rules\\\">@-rules</a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla_CSS_support_chart#Media_queries\\\" title=\\\"Mozilla_CSS_support_chart#Media_queries\\\">Media queries</a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Mozilla_CSS_support_chart#values_and_units\\\" title=\\\"Mozilla_CSS_support_chart#values_and_units\\\">values</a> in alphabetical order.\",\n        \"VALUES\": []\n    },\n    \"Paged Media\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Paged_Media\",\n        \"SUMMARY\": \"Paged media properties control the presentation of content for print or any other media that splits content into discrete pages. It allows you to set page breaks, control printable area, style left and right pages differently, and control breaks inside elements. Popularly supported properties include\",\n        \"VALUES\": []\n    },\n    \"Privacy and the :visited selector\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Privacy_and_the_:visited_selector\",\n        \"SUMMARY\": \"Historically, the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:visited\\\" title=\\\"The :visited CSS pseudo-class lets you select only links that have been visited. This style may be overridden by any other link-related pseudo-classes, that is :link, :hover, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :visited rule after the :link rule but before the other ones, defined in the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:visited</code></a> selector has been a way for sites to query the user's history, by using <code>getComputedStyle()</code> or other techniques to walk through the user's history to figure out what sites the user has visited. This can be done quickly, and makes it possible not only to determine where the user has been on the web, but can also be used to guess a lot of information about a user's identity.\",\n        \"VALUES\": []\n    },\n    \"Pseudo-classes\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\",\n        \"SUMMARY\": \"A CSS <strong><em><dfn>pseudo-class</dfn></em></strong> is a keyword added to selectors that specifies a special state of the element to be selected. For example <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:hover\\\" title=\\\"The :hover CSS pseudo-class matches when the user designates an element with a pointing device, but does not necessarily activate it. This style may be overridden by any other link-related pseudo-classes, that is :link, :visited, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :hover rule after the :link and :visited rules but before the :active one, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:hover</code></a> will apply a style when the user hovers over the element specified by the selector.\",\n        \"VALUES\": []\n    },\n    \"Pseudo-elements\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\",\n        \"SUMMARY\": \"Just like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-classes\\\" title=\\\"A CSS pseudo-class is a keyword added to selectors that specifies a special state of the element to be selected. For example :hover will apply a style when the user hovers over the element specified by the selector.\\\"><code>pseudo-classes</code></a>, pseudo-elements are added to selectors but instead of describing a special state, they allow you to style certain parts of an element. For example, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::first-line\\\" title=\\\"The ::first-line CSS pseudo-element applies styles only to the first line of an element. The amount of the text on the first line depends of numerous factors, like the width of the element, width of the document, and the font size of the text. As all pseudo-elements, ::first-line does not match any real HTML element.\\\"><code>::first-line</code></a> pseudo-element targets only  the first line of an element specified by the selector.\",\n        \"VALUES\": []\n    },\n    \"Questions about CSS\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/FAQ\",\n        \"SUMMARY\": \"\",\n        \"VALUES\": []\n    },\n    \"Replaced element\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element\",\n        \"SUMMARY\": \"In CSS, a <strong>replaced element</strong> is an element whose representation is outside the scope of CSS. These are a type of external object whose representation is independent of the CSS. Typical replaced elements are <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img\\\" title=\\\"The HTML &lt;img&gt; element represents an image in the document.\\\"><code>&lt;img&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object\\\" title=\\\"The&#xA0;HTML Embedded Object Element&#xA0;(&lt;object&gt;) represents an external resource, which can be treated as an image, a nested browsing context, or a resource to be handled by a plugin.\\\"><code>&lt;object&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video\\\" title=\\\"Use the &#xA0;HTML &lt;video&gt; element&#xA0;to embed video content in a document. The video element contains one or more video sources. To specify a video source, use either the src attribute or the &lt;source&gt; element; the browser will choose the most suitable one.\\\"><code>&lt;video&gt;</code></a> or form elements like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea\\\" title=\\\"The HTML &lt;textarea&gt; element represents a multi-line plain-text editing control.\\\"><code>&lt;textarea&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\\\" title=\\\"The HTML element &lt;input&gt; is used to create interactive controls for web-based forms in order to accept data from the user. How an &lt;input&gt; works varies considerably depending on the value of its type attribute.\\\"><code>&lt;input&gt;</code></a>. Some elements, like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio\\\" title=\\\"The HTML &lt;audio&gt; element is used to embed sound content in documents. It may contain one or more audio sources, represented using the src attribute or the &lt;source&gt; element; the browser will choose the most suitable one.\\\"><code>&lt;audio&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas\\\" title=\\\"The HTML &lt;canvas&gt; Element can be used to draw graphics via scripting (usually JavaScript). For example, it can be used to draw graphs, make photo compositions or even perform animations. You may (and should) provide alternate content inside the &lt;canvas&gt; block. That content will be rendered both on older browsers that don't support canvas and in browsers with JavaScript disabled.\\\"><code>&lt;canvas&gt;</code></a> are replaced elements only in specific cases. Objects inserted using the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/content\\\" title=\\\"The content CSS property is used with the ::before and ::after pseudo-elements to generate content in an element. Objects inserted using the content property are anonymous replaced elements.\\\"><code>content</code></a> properties are <em>anonymous replaced elements</em>.\",\n        \"VALUES\": []\n    },\n    \"Resolved value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/resolved_value\",\n        \"SUMMARY\": \"The <strong>resolved value</strong> of a CSS property is the value returned by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle\\\" title=\\\"The Window.getComputedStyle() method gives the values of all the CSS properties of an element after applying the active stylesheets and resolving any basic computation those values may contain.\\\"><code>getComputedStyle()</code></a>. For most properties, it is the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/computed_value\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>computed value</code></a>, but for a few legacy properties (including <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a>), it is instead the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/used_value\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>used value</code></a>. See the specification link below for more per-property details.\",\n        \"VALUES\": []\n    },\n    \"Scaling of SVG backgrounds\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Scaling_of_SVG_backgrounds\",\n        \"SUMMARY\": \"Given the flexibility of SVG images, there's a lot to keep in mind when using them as background images with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\"><code>background-image</code></a> property, and even more to keep in mind when also scaling them using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-size\\\"><code>background-size</code></a> property. This article describes how scaling of SVG images is handled when using these properties.\",\n        \"VALUES\": []\n    },\n    \"Shorthand properties\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\",\n        \"SUMMARY\": \"<dfn>Shorthand properties</dfn> are CSS properties that let you set the values of several other CSS properties simultaneously. Using a shorthand property, a Web developer can write more concise and often more readable style sheets, saving time and energy.\",\n        \"VALUES\": []\n    },\n    \"Specificity\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity\",\n        \"SUMMARY\": \"Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of different sorts of <a title=\\\"en/CSS/CSS_Reference#Selectors\\\" href=\\\"/en/CSS/CSS_Reference#Selectors\\\">CSS selectors</a>.\",\n        \"VALUES\": []\n    },\n    \"Syntax\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax\",\n        \"SUMMARY\": \"The basic goal of the Cascading Stylesheet (<a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a>) language is to allow a browser engine to paint elements of the page with specific features, like colors, positioning, or decorations. The <em>CSS syntax</em> reflects this goal and its basic building blocks are:\",\n        \"VALUES\": []\n    },\n    \"Tools\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Tools\",\n        \"SUMMARY\": \"CSS offers a number of powerful features that can be tricky to use, or have a number of parameters, so that it's helpful to be able to visualize them while you work on them. This page offers links to a number of useful tools that will help you build the CSS to style your content using these features.\",\n        \"VALUES\": [{\n            \"value\": \"<dt class=\\\"landingPageList\\\"><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Tools/Cubic_Bezier_Generator\\\">Cubic Bezier Generator</a></dt><dd class=\\\"landingPageList\\\">This is a sample tool; it lets you edit Bezier curves. This is not really yet a useful tool, but will be!</dd><dt class=\\\"landingPageList\\\"><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Tools/Linear-gradient_Generator\\\">Linear-gradient Generator</a></dt><dd class=\\\"landingPageList\\\">This tool can be used to create custom CSS3 <a title=\\\"The CSS linear-gradient() function creates an &lt;image&gt; which represents a linear gradient of colors. The result of this function is an object of the CSS &lt;gradient&gt; data type. Like any other gradient, a CSS linear gradient is not a CSS &lt;color&gt; but an image with no intrinsic dimensions; that is, it has neither natural or preferred size, nor ratio. Its concrete size will match the size&#xA0;of the element it applies to.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient\\\"><code>linear-gradient()</code></a> backgrounds.</dd>\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Tools/Cubic_Bezier_Generator\\\">Cubic Bezier Generator</a>\"\n        }, {\n            \"value\": \"This is a sample tool; it lets you edit Bezier curves. This is not really yet a useful tool, but will be!\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Tools/Linear-gradient_Generator\\\">Linear-gradient Generator</a>\"\n        }, {\n            \"value\": \"This tool can be used to create custom CSS3 <a title=\\\"The CSS linear-gradient() function creates an &lt;image&gt; which represents a linear gradient of colors. The result of this function is an object of the CSS &lt;gradient&gt; data type. Like any other gradient, a CSS linear gradient is not a CSS &lt;color&gt; but an image with no intrinsic dimensions; that is, it has neither natural or preferred size, nor ratio. Its concrete size will match the size&#xA0;of the element it applies to.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient\\\"><code>linear-gradient()</code></a> backgrounds.\",\n            \"description\": \"\"\n        }]\n    },\n    \"Type selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors\",\n        \"SUMMARY\": \"CSS type selectors match elements by node name. Used alone, therefore, a type selector for a particular node name selects all elements of that type — that is, with that node name — in the document.\",\n        \"VALUES\": []\n    },\n    \"Universal selectors\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors\",\n        \"SUMMARY\": \"An asterisk (<code>*</code>) is the universal selector for CSS. It matches a single element of any type. Omitting the asterisk with simple selectors has the same effect. For instance, <code>*.warning</code> and <code>.warning</code> are considered equal.\",\n        \"VALUES\": []\n    },\n    \"Used value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/used_value\",\n        \"SUMMARY\": \"The used value of any CSS property is the final value of that property after all calculations have been performed. For some properties, used values can be retrieved by calling <a href=\\\"https://developer.mozilla.org/en-US/docs/DOM/window.getComputedStyle\\\" title=\\\"en/DOM/window.getComputedStyle\\\" style=\\\"text-decoration: none; color: rgb(4, 137, 183) !important; cursor: default;\\\">window.getComputedStyle</a>. Dimensions (e.g., <code>width</code>, <code>line-height</code>) are all in pixels, shorthand properties (e.g., background) are consistent with their component properties (e.g., <code>background-color</code>, <code>display)</code> and consistent with <code>position</code> and <code>float</code>, and every CSS property has a value.\",\n        \"VALUES\": []\n    },\n    \"Using CSS variables\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables\",\n        \"SUMMARY\": \"<strong>CSS Variables</strong> are entities defined by CSS authors which contain specific values to be reused throughout a document. They are set using custom property notation (e.g. <strong><code>--main-color: black;</code></strong>) and are accessed using the <code>var()</code> function (e.g. <code>color: <strong>var(--main-color)</strong>;</code>) .\",\n        \"VALUES\": []\n    },\n    \"Value definition syntax\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Value_definition_syntax\",\n        \"SUMMARY\": \"\",\n        \"VALUES\": []\n    },\n    \"Visual formatting model\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Visual_formatting_model\",\n        \"SUMMARY\": \"The CSS <em>visual formatting model</em> is an algorithm that processes a document and displays it on visual media.\",\n        \"VALUES\": []\n    },\n    \"WebKit extensions\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Webkit_Extensions\",\n        \"SUMMARY\": \"WebKit supports a number of extensions to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> that are prefixed with <code>-webkit</code>. All <code>-webkit</code> prefixed properties also work with an <code>-apple</code> prefix.\",\n        \"VALUES\": []\n    },\n    \"actual value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/actual_value\",\n        \"SUMMARY\": \"The <strong>actual value</strong> of a CSS property is the used value after all approximations have been applied. For example, a user agent may only be able to render borders with a integer pixel value and may be forced to approximate the computed width of the border.\",\n        \"VALUES\": []\n    },\n    \"align-content\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/align-content\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <strong><code>align-content</code></strong> property defines how the browser distributes space between and around content items along the main-axis of their container.\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The items are packed flush to each other toward the start edge of the alignment container in the cross axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The items are packed flush to each other toward the end edge of the alignment container in the cross axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The items are packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s cross-start side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The items are packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s cross-end side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>end</code>.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container along the cross axis.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container in the cross axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the cross axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>space-between</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container along the cross axis. The spacing between each pair of adjacent items is the same. The first item is flush with the main-start edge, and the last item is flush with the main-end edge.\"\n        }, {\n            \"value\": \"<code>space-around</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container along the cross axis. The spacing between each pair of adjacent items is the same. The empty space before the first and after the last item equals half of the space between each pair of adjacent items.\"\n        }, {\n            \"value\": \"<code>space-evenly</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container along the cross axis. The spacing between each pair of adjacent items, the main-start edge and the first item, and the main-end edge and the last item, are all exactly the same.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items&#xA0;along the cross axis is less than the size of the alignment container, any <code>auto</code>-sized items have their size increased equally (not proportionally), while still respecting the constraints imposed by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\" title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\"><code>max-height</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\" title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size exactly fills the alignment container&#xA0;along the cross axis.\"\n        }, {\n            \"value\": \"<code>safe</code>\",\n            \"description\": \"If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were <code>start</code>.\"\n        }, {\n            \"value\": \"<code>unsafe</code>\",\n            \"description\": \"Regardless of the relative sizes of the item and alignment container, the given alignment value is honored.\"\n        }]\n    },\n    \"align-items\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/align-items\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <strong><code>align-items</code></strong> property defines how the browser distributes space between and around flex items along the cross-axis of their container. This means it works like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content\\\" title=\\\"The CSS justify-content property defines how the browser distributes space between and around content items along the main axis of their container.\\\"><code>justify-content</code></a> but in the perpendicular direction.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The effect of this keyword is dependent of the layout mode we are in:\\n <ul>\\n  <li>In absolutely-positioned layouts, the keyword behaves like <code>start</code> on <em>replaced</em> absolutely-positioned boxes, and as <code>stretch</code> on <em>all other</em> absolutely-positioned boxes. <span style=\\\"display: none;\\\"> </span><span style=\\\"display: none;\\\">&#xA0;</span><span style=\\\"display: none;\\\"> </span></li>\\n  <li>In static position of absolutely-positioned layouts, the keyword behaves as <code>stretch</code>.</li>\\n  <li>For flex items, the keyword behaves as <code>stretch</code>.</li>\\n  <li>For grid items, this keyword leads to a behavior similar to the one of <code>stretch</code>, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like <code>start</code>.</li>\\n  <li>The property doesn&apos;t apply to block-level boxes, and to table cells.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The cross-start margin edge of the flex item is flushed with the cross-start edge of the line.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The cross-end margin edge of the flex item is flushed with the cross-end edge of the line.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The flex item&apos;s margin box is centered within the line on the cross-axis. If the cross-size of the item is larger than the flex container, it will overflow equally in both directions.\"\n        }, {\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The item is packed flush to each other toward the start edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The item is packed flush to each other toward the end edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the appropriate axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>self-start</code>\",\n            \"description\": \"The items is packed flush to the edge of the alignment container of the start side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>self-end</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the end side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>baseline</code>\",\n            \"description\": \"<code>first baseline<br>\\n last baseline</code>\"\n        }, {\n            \"value\": \"All flex items are aligned such that their baselines align. The item with the largest distance between its cross-start margin edge and its baseline is flushed with the cross-start edge of the line.\",\n            \"description\": \"<code>stretch</code>\"\n        }, {\n            \"value\": \"Flex items are stretched such as the cross-size of the item&apos;s margin box is the same as the line while respecting width and height constraints.\",\n            \"description\": \"<code>safe</code>\"\n        }, {\n            \"value\": \"If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were <code>start</code>.\",\n            \"description\": \"<code>unsafe</code>\"\n        }]\n    },\n    \"align-self\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/align-self\",\n        \"SUMMARY\": \"The <strong><code>align-self</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property aligns flex items of the current flex line overriding the <a title=\\\"The CSS align-items property defines how the browser distributes space between and around flex items along the cross-axis of their container. This means it works like justify-content but in the perpendicular direction.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-items\\\"><code>align-items</code></a> value. If any of the item's cross-axis margin is set to <code>auto</code>, then <code>align-self</code> is ignored.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Computes to the parent&apos;s <a title=\\\"The CSS align-items property defines how the browser distributes space between and around flex items along the cross-axis of their container. This means it works like justify-content but in the perpendicular direction.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-items\\\"><code>align-items</code></a> value.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The effect of this keyword is dependent of the layout mode we are in:\\n <ul>\\n  <li>In absolutely-positioned layouts, the keyword behaves like <code>start</code> on <em>replaced</em> absolutely-positioned boxes, and as <code>stretch</code> on <em>all other</em> absolutely-positioned boxes. <span style=\\\"display: none;\\\"> </span><span style=\\\"display: none;\\\">&#xA0;</span><span style=\\\"display: none;\\\"> </span></li>\\n  <li>In static position of absolutely-positioned layouts, the keyword behaves as <code>stretch</code>.</li>\\n  <li>For flex items, the keyword behaves as <code>stretch</code>.</li>\\n  <li>For grid items, this keyword leads to a behavior similar to the one of <code>stretch</code>, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like <code>start</code>.</li>\\n  <li>The property doesn&apos;t apply to block-level boxes, and to table cells.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>self-start</code>\",\n            \"description\": \"Aligns the items to be flush with the edge of the alignment container corresponding to the item&apos;s start side in the cross axis.\"\n        }, {\n            \"value\": \"<code>self-end</code>\",\n            \"description\": \"Aligns the items to be flush with the edge of the alignment container corresponding to the item&apos;s end side in the cross axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The cross-start margin edge of the flex item is flushed with the cross-start edge of the line.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The cross-end margin edge of the flex item is flushed with the cross-end edge of the line.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The flex item&apos;s margin box is centered within the line on the cross-axis. If the cross-size of the item is larger than the flex container, it will overflow equally in both directions.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items along the cross axis is less than the size of the alignment container and the item is <code>auto</code>-sized, its size is increased equally (not proportionally), while still respecting the constraints imposed by <a title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\"><code>max-height</code></a>/<a title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size of all <code>auto</code>-sized items exactly fills the alignment container along the cross axis.\"\n        }, {\n            \"value\": \"<code>safe</code>\",\n            \"description\": \"If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were <code>start</code>.\"\n        }, {\n            \"value\": \"<code>unsafe</code>\",\n            \"description\": \"Regardless of the relative sizes of the item and alignment container, the given alignment value is honored.\"\n        }]\n    },\n    \"all\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/all\",\n        \"SUMMARY\": \"The CSS<em> </em><code><strong>all</strong></code> shorthand property resets all properties, apart from <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi\\\" title=\\\"The unicode-bidi CSS property together with the direction property relates to the handling of bidirectional text in a document. For example, if a block of text contains both left-to-right and right-to-left text then the user-agent uses a complex Unicode algorithm to decide how to display the text. This property overrides this algorithm and allows the developer to control the text embedding.\\\"><code>unicode-bidi</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, to their initial or inherited value.\",\n        \"VALUES\": [{\n            \"value\": \"<code>initial</code>\",\n            \"description\": \"This keyword indicates to change all the properties applying to the element or the element&apos;s parent to their initial value. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi\\\" title=\\\"The unicode-bidi CSS property together with the direction property relates to the handling of bidirectional text in a document. For example, if a block of text contains both left-to-right and right-to-left text then the user-agent uses a complex Unicode algorithm to decide how to display the text. This property overrides this algorithm and allows the developer to control the text embedding.\\\"><code>unicode-bidi</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> values are not affected.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"This keyword indicates to change all the properties applying to the element or the element&apos;s parent to their parent value. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi\\\" title=\\\"The unicode-bidi CSS property together with the direction property relates to the handling of bidirectional text in a document. For example, if a block of text contains both left-to-right and right-to-left text then the user-agent uses a complex Unicode algorithm to decide how to display the text. This property overrides this algorithm and allows the developer to control the text embedding.\\\"><code>unicode-bidi</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> values are not affected.\"\n        }, {\n            \"value\": \"<code>unset</code>\",\n            \"description\": \"This keyword indicates to change all the properties applying to the element or the element&apos;s parent to their parent value if they are inheritable or to their initial value if not. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi\\\" title=\\\"The unicode-bidi CSS property together with the direction property relates to the handling of bidirectional text in a document. For example, if a block of text contains both left-to-right and right-to-left text then the user-agent uses a complex Unicode algorithm to decide how to display the text. This property overrides this algorithm and allows the developer to control the text embedding.\\\"><code>unicode-bidi</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> values are not affected.\"\n        }, {\n            \"value\": \"<code>revert</code>\",\n            \"description\": \"If the cascaded value of a property is the revert keyword, the behavior depends on the origin to which the declaration belongs:\\n <dl>\\n  <dt>user-agent origin</dt>\\n  <dd>Equivalent to unset.</dd>\\n  <dt>user origin</dt>\\n  <dd>Rolls back the cascade to the user-agent level, so that the specified value is calculated as if no author-level or user-level rules were specified for this property.</dd>\\n  <dt>author origin</dt>\\n  <dd>Rolls back the cascade to the user level, so that the specified value is calculated as if no author-level rules were specified for this property. For the purpose of revert, this origin includes the Override and Animation origins.</dd>\\n </dl>\\n \"\n        }, {\n            \"value\": \"user-agent origin\",\n            \"description\": \"Equivalent to unset.\"\n        }, {\n            \"value\": \"user origin\",\n            \"description\": \"Rolls back the cascade to the user-agent level, so that the specified value is calculated as if no author-level or user-level rules were specified for this property.\"\n        }, {\n            \"value\": \"author origin\",\n            \"description\": \"Rolls back the cascade to the user level, so that the specified value is calculated as if no author-level rules were specified for this property. For the purpose of revert, this origin includes the Override and Animation origins.\"\n        }]\n    },\n    \"animation\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation\",\n        \"SUMMARY\": \"The <strong><code>animation</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand property</a> for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-name\\\" title=\\\"The animation-name CSS property specifies a list of animations that should be applied to the selected element. Each name indicates a @keyframes at-rule that defines the property values for the animation sequence.\\\"><code>animation-name</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-duration\\\" title=\\\"The animation-duration CSS property specifies the length of time that an animation should take to complete one cycle.\\\"><code>animation-duration</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function\\\" title=\\\"The animation-timing-function CSS property specifies how a CSS animation should progress over the duration of each cycle. The possible values are one or several &lt;timing-function&gt;.\\\"><code>animation-timing-function</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay\\\" title=\\\"The animation-delay CSS property specifies when the animation should start. This lets the animation sequence begin some time after it's applied to an element.\\\"><code>animation-delay</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-iteration-count\\\" title=\\\"The animation-iteration-count CSS property defines the number of times an animation cycle should be played before stopping. If multiple values are specified, each time the animation is played, the next value in the list is used, cycling back to the first value after the last one is used.\\\"><code>animation-iteration-count</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction\\\" title=\\\"The animation-direction CSS property indicates whether the animation should play in reverse on alternate cycles.\\\"><code>animation-direction</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode\\\" title=\\\"The animation-fill-mode CSS property specifies how a CSS animation should apply styles to its target before and after it is executing.\\\"><code>animation-fill-mode</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-play-state\\\" title=\\\"The animation-play-state CSS property determines whether an animation is running or paused. This can be queried to determine whether or not the animation is currently running. In addition, its value can be set to pause and resume playback of an animation.\\\"><code>animation-play-state</code></a>.\",\n        \"VALUES\": []\n    },\n    \"animation-delay\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay\",\n        \"SUMMARY\": \"The <strong><code>animation-delay</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies when the animation should start. This lets the animation sequence begin some time after it's applied to an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;time&gt;</code>\",\n            \"description\": \"The time offset from the time at which the animation is applied to the element at which the animation should begin. This may be specified in either seconds (by specifying <code>s</code> as the unit) or milliseconds (by specifying <code>ms</code> as the unit). If you don&apos;t specify a unit, the statement is invalid.\"\n        }]\n    },\n    \"animation-direction\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction\",\n        \"SUMMARY\": \"The <strong><code>animation-direction</code></strong> CSS property indicates whether the animation should play in reverse on alternate cycles.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The animation should play forward each cycle. In other words, each time the animation cycles, the animation will reset to the beginning state and start over again. This is the default animation direction setting.\"\n        }, {\n            \"value\": \"<code>reverse</code>\",\n            \"description\": \"The animation plays backward each cycle. Each time the animation cycles, the animation resets to the end state and starts over again.\"\n        }, {\n            \"value\": \"<code>alternate</code>\",\n            \"description\": \"The animation should reverse direction each cycle. When playing in reverse, the animation steps are performed backward. In addition, timing functions are also reversed; for example, an <code>ease-in</code> animation is replaced with an <code>ease-out</code> animation when played in reverse. The count to determine if it is an even or an odd iteration starts at one.\"\n        }, {\n            \"value\": \"<code>alternate-reverse</code>\",\n            \"description\": \"The animation plays backward on the first play-through, then forward on the next, then continues to alternate. The count to determinate if it is an even or an odd iteration starts at one.\"\n        }]\n    },\n    \"animation-duration\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-duration\",\n        \"SUMMARY\": \"The <strong><code>animation-duration</code></strong> CSS property specifies the length of time that an animation should take to complete one cycle.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;time&gt;</code>\",\n            \"description\": \"The duration that an animation should take to complete one cycle. This may be specified in either seconds (by specifying <code>s</code> as the unit) or milliseconds (by specifying <code>ms</code> as the unit). If you don&apos;t specify a unit, the declaration will be invalid.\"\n        }]\n    },\n    \"animation-fill-mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode\",\n        \"SUMMARY\": \"The <strong><code>animation-fill-mode</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies how a CSS animation should apply styles to its target before and after it is executing.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The animation will not apply any styles to the target when it&apos;s not executing; it will instead be displayed using its state based on all other CSS rules applied to it.\"\n        }, {\n            \"value\": \"<code>forwards</code>\",\n            \"description\": \"The target will retain the computed values set by the last keyframe encountered during execution. The last keyframe encountered depends on the value of <a title=\\\"The animation-direction CSS property indicates whether the animation should play in reverse on alternate cycles.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction\\\"><code>animation-direction</code></a> and <a title=\\\"The animation-iteration-count CSS property defines the number of times an animation cycle should be played before stopping. If multiple values are specified, each time the animation is played, the next value in the list is used, cycling back to the first value after the last one is used.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-iteration-count\\\"><code>animation-iteration-count</code></a>:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <th scope=\\\"col\\\"><code>animation-direction</code></th>\\n    <th scope=\\\"col\\\"><code>animation-iteration-count</code></th>\\n    <th scope=\\\"col\\\">last keyframe encountered</th>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>normal</code></td>\\n    <td>even or odd</td>\\n    <td><code>100%</code> or <code>to</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>reverse</code></td>\\n    <td>even or odd</td>\\n    <td><code>0%</code> or <code>from</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>alternate</code></td>\\n    <td>even</td>\\n    <td><code>0%</code> or <code>from</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>alternate</code></td>\\n    <td>odd</td>\\n    <td><code>100%</code> or <code>to</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>alternate-reverse</code></td>\\n    <td>even</td>\\n    <td><code>100%</code> or <code>to</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>alternate-reverse</code></td>\\n    <td>odd</td>\\n    <td><code>0%</code> or <code>from</code></td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>backwards</code>\",\n            \"description\": \"The animation will apply the values defined in the first relevant <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/@keyframes\\\">keyframe</a> as soon as it is applied to the target, and retain this during the <a title=\\\"The animation-delay CSS property specifies when the animation should start. This lets the animation sequence begin some time after it&apos;s applied to an element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay\\\"><code>animation-delay</code></a> period. The first relevant keyframe depends on the value of <a title=\\\"The animation-direction CSS property indicates whether the animation should play in reverse on alternate cycles.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction\\\"><code>animation-direction</code></a>:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <th scope=\\\"col\\\"><code>animation-direction</code></th>\\n    <th scope=\\\"col\\\">first relevant keyframe</th>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>normal</code> or <code>alternate</code></td>\\n    <td><code>0%</code> or <code>from</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>reverse</code> or <code>alternate-reverse</code></td>\\n    <td><code>100%</code> or <code>to</code></td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>both</code>\",\n            \"description\": \"The animation will follow the rules for both forwards and backwards, thus extending the animation properties in both directions.\"\n        }]\n    },\n    \"animation-iteration-count\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-iteration-count\",\n        \"SUMMARY\": \"The <strong><code>animation-iteration-count</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the number of times an animation cycle should be played before stopping. If multiple values are specified, each time the animation is played, the next value in the list is used, cycling back to the first value after the last one is used.\",\n        \"VALUES\": [{\n            \"value\": \"<code>infinite</code>\",\n            \"description\": \"The animation will repeat forever.\"\n        }, {\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"The number of times the animation should repeat; this is <code>1</code> by default. Negative values are invalid. You may specify non-integer values to play part of an animation cycle (for example <code>0.5</code> will play half of the animation cycle).\"\n        }]\n    },\n    \"animation-name\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-name\",\n        \"SUMMARY\": \"The <strong><code>animation-name</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property specifies a list of animations that should be applied to the selected element. Each name indicates a <a title=\\\"The @keyframes CSS at-rule lets authors control the intermediate steps in a CSS animation sequence by establishing keyframes (or waypoints) along the animation sequence that must be reached by certain points during the animation. This gives you more specific control over the intermediate steps of the animation sequence than you'd get when letting the browser handle everything automatically.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes\\\"><code>@keyframes</code></a> at-rule that defines the property values for the animation sequence.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a special keyword denoting no keyframes. It can be used to deactivate an animation without changing the ordering of the other identifiers, or to deactivate animations coming from the cascade.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;custom-ident&gt;</code></a>\",\n            \"description\": \"A string identifying the animation. This identifier is composed by a combination of case-insensitive letters&#xA0;<code>a</code> to <code>z</code>, numbers <code>0</code> to <code>9</code>, underscores (<code>_</code>), and/or dashes (<code>-</code>). The first non-dash character must be a letter (that is, no number at the beginning of it, even if preceded by a dash.) Also, two dashes are forbidden at the beginning of the identifier. It can&apos;t be <code>none</code>, <code>unset</code>, <code>initial</code>, or <code>inherit</code> in any combination of cases.\"\n        }]\n    },\n    \"animation-play-state\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-play-state\",\n        \"SUMMARY\": \"The <strong><code>animation-play-state</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property determines whether an animation is running or paused. This can be queried to determine whether or not the animation is currently running. In addition, its value can be set to pause and resume playback of an animation.\",\n        \"VALUES\": [{\n            \"value\": \"<code>running</code>\",\n            \"description\": \"The animation is currently playing.\"\n        }, {\n            \"value\": \"<code>paused</code>\",\n            \"description\": \"The animation is currently paused.\"\n        }]\n    },\n    \"animation-timing-function\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function\",\n        \"SUMMARY\": \"The <code><strong>animation-timing-function</strong></code> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property specifies how a CSS animation should progress over the duration of each cycle. The possible values are one or several <a title=\\\"The &lt;single-transition-timing-function&gt; CSS data type denotes a mathematical function that describes how fast one-dimensional values change during transitions or animations. This in essence lets you establish an acceleration curve, so that the speed of the animation can vary over its duration. These functions are often called easing functions.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/timing-function\\\"><code>&lt;timing-function&gt;</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;timingfunction&gt;</code>\",\n            \"description\": \"Each <a title=\\\"The &lt;single-transition-timing-function&gt; CSS data type denotes a mathematical function that describes how fast one-dimensional values change during transitions or animations. This in essence lets you establish an acceleration curve, so that the speed of the animation can vary over its duration. These functions are often called easing functions.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/timing-function\\\"><code>&lt;timing-function&gt;</code></a> represents the timing function to link to the corresponding property to animate, as defined in <a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation-property\\\" class=\\\"new\\\"><code>animation-property</code></a>.\"\n        }]\n    },\n    \"appearance\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/appearance\",\n        \"SUMMARY\": \"The <strong><code>appearance</code></strong> CSS property indicates whether to display an element using platform-native styling based on the operating system's theme or not.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The user agent may render form controls using native controls of the host operating system or with a look and feel not otherwise expressible in CSS. On form control elements where the computed value is <code>auto</code> UAs may disregard some CSS properties to ensure that the intended appearance is preserved, or because these properties may not be meaningful for the chosen appearance. However, the following properties must still be honored:\\n <ul>\\n  <li><a title=\\\"The CSS all shorthand property resets all properties, apart from&#xA0;unicode-bidi and direction, to their initial or inherited value.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/all\\\"><code>all</code></a></li>\\n  <li><a title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\"><code>bottom</code></a></li>\\n  <li><a title=\\\"The appearance CSS property indicates whether to&#xA0;display an element using platform-native styling based on the operating system&apos;s theme or not.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/appearance\\\"><code>appearance</code></a></li>\\n  <li><a title=\\\"The clear CSS property specifies whether an element can be next to floating elements that precede it or must be moved down (cleared) below them. The clear property applies to both floating and non-floating elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/clear\\\"><code>clear</code></a></li>\\n  <li><a title=\\\"The cursor CSS property specifies the mouse cursor displayed when the mouse pointer is over an element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\\\"><code>cursor</code></a></li>\\n  <li><a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a></li>\\n  <li><a title=\\\"The display CSS property specifies the type of rendering box used for an element. In HTML, default display property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is inline.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display\\\"><code>display</code></a></li>\\n  <li><a title=\\\"The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/float\\\"><code>float</code></a></li>\\n  <li><a title=\\\"The left CSS property specifies part of the position of positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\"><code>left</code></a></li>\\n  <li><a title=\\\"The margin CSS property sets the margin for all four sides. It is a shorthand to avoid setting each side separately with the other margin properties: margin-top, margin-right, margin-bottom and margin-left.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin\\\"><code>margin</code></a> and related long-hand properties</li>\\n  <li><a title=\\\"The position CSS property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\"><code>position</code></a></li>\\n  <li><a title=\\\"The right CSS property specifies part of the position of positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\"><code>right</code></a></li>\\n  <li><a title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\"><code>top</code></a></li>\\n  <li><a title=\\\"The unicode-bidi CSS property together with the direction property relates to the handling of bidirectional text in a document. For example, if a block of text contains both left-to-right and right-to-left text then the user-agent uses a complex Unicode algorithm to decide how to display the text. This property overrides this algorithm and allows the developer to control the text embedding.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi\\\"><code>unicode-bidi</code></a></li>\\n  <li><a title=\\\"The visibility property can be used to hide an element while leaving the space where it would have been. It can also hide rows or columns of a table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/visibility\\\"><code>visibility</code></a></li>\\n  <li><a title=\\\"The z-index property specifies the z-order of a positioned element and its descendants. When elements overlap, z-order determines which one covers the other. An element with a larger z-index generally covers an element with a lower one.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/z-index\\\"><code>z-index</code></a></li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Form controls are not made to look like native controls, making them non-replaced elements. The element is rendered following the usual rules of CSS.&#xA0; No other replaced elements other than form controls are affected.\"\n        }]\n    },\n    \"attr\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/attr\",\n        \"SUMMARY\": \"The <code>attr()</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> function is used to retrieve the value of an attribute of the selected element and use it in the style sheet. It can be used on pseudo-elements too and, in this case, the value of the attribute on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements\\\">pseudo-element</a>'s originated element is returned.\",\n        \"VALUES\": [{\n            \"value\": \"<code>attribute-name</code>\",\n            \"description\": \"Is the name of an attribute on the HTML element referenced in the CSS.\"\n        }, {\n            \"value\": \"<code>&lt;type-</code>or-unit&gt; <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Is a keyword representing either the type of the attribute&apos;s value, or its unit, as in HTML some attributes have implicit units. If the use of <code>&lt;type-or-unit&gt;</code> as a value for the given attribute is invalid, the <code>attr()</code> expression will be invalid too. If omitted, it defaults to <code>string</code>. The list of valid values are:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <th scope=\\\"col\\\">Keyword</th>\\n    <th scope=\\\"col\\\">Associated type</th>\\n    <th scope=\\\"col\\\">Comment</th>\\n    <th scope=\\\"col\\\">Default value</th>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>string</code></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a></td>\\n    <td>The attribute value is treated as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a>.&#xA0; It is NOT reparsed, and in particular the characters are used as-is instead of CSS escapes being turned into different characters.</td>\\n    <td>An empty string</td>\\n   </tr>\\n   <tr>\\n    <td><code>color</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a></td>\\n    <td>The attribute value is parsed as a hash (3- or 6-value hash) or a keyword. It must be a valid CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a> value.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>currentColor</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>url</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/uri\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;uri&gt;</code></a></td>\\n    <td>The attribute value is parsed as a string that is used inside a CSS <code>url()</code>function.<br>\\n     Relative URL are resolved relatively to the original document, not relatively to the style sheet.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td>The url <code>about:invalid</code> that points to a non-existent document with a generic error condition.</td>\\n   </tr>\\n   <tr>\\n    <td><code>integer</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a>. If it is not valid, that is not an integer or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0</code>, or, if <code>0</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>number</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>. If it is not valid, that is not a number or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0</code>, or, if <code>0</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>length</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> dimension, that is including the unit (e.g. <code>12.5em</code>). If it is not valid, that is not a length or out of the range accepted by the CSS property, the default value is used.<br>\\n     If the given unit is a relative length, <code>attr()</code>computes it to an absolute length.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0</code>, or, if <code>0</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>em</code>, <code>ex</code>, <code>px</code>, <code>rem</code>, <code>vw</code>, <code>vh</code>, <code>vmin</code>, <code>vmax</code>, <code>mm</code>, <code>cm</code>, <code>in</code>, <code>pt</code>, or <code>pc</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>, that is without the unit (e.g. <code>12.5</code>), and interpreted as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> with the specified unit. If it is not valid, that is not a number or out of the range accepted by the CSS property, the default value is used.<br>\\n     If the given unit is a relative length, <code>attr()</code>computes it to an absolute length.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0</code>, or, if <code>0</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>angle</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. It is used, for example, in rotate and skew transforms.\\\"><code>&lt;angle&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. It is used, for example, in rotate and skew transforms.\\\"><code>&lt;angle&gt;</code></a> dimension, that is including the unit (e.g. <code>30.5deg</code>). If it is not valid, that is not an angle or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0deg</code>, or, if <code>0deg</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>deg</code>, <code>grad</code>, <code>rad</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. It is used, for example, in rotate and skew transforms.\\\"><code>&lt;angle&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>, that is without the unit (e.g. <code>12.5</code>), and interpreted as an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. It is used, for example, in rotate and skew transforms.\\\"><code>&lt;angle&gt;</code></a> with the specified unit. If it is not valid, that is not a number or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0deg</code>, or, if <code>0deg</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>time</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a> dimension, that is including the unit (e.g. <code>30.5ms</code>). If it is not valid, that is not a time or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0s</code>, or, if <code>0s</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>s</code>, <code>ms</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>, that is without the unit (e.g. <code>12.5</code>), and interpreted as an<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a> with the specified unit. If it is not valid, that is not a number or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0s</code>, or, if <code>0s</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>frequency</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/frequency\\\" title=\\\"The &lt;frequency&gt; CSS data type denotes a frequency dimension, like the pitch of a speaking voice.\\\"><code>&lt;frequency&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/frequency\\\" title=\\\"The &lt;frequency&gt; CSS data type denotes a frequency dimension, like the pitch of a speaking voice.\\\"><code>&lt;frequency&gt;</code></a> dimension, that is including the unit (e.g. <code>30.5kHz</code>). If it is not valid, that is not a frequency or out of the range accepted by the CSS property, the default value is used.</td>\\n    <td><code>0Hz</code>, or, if <code>0Hz</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>Hz</code>, <code>kHz</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/frequency\\\" title=\\\"The &lt;frequency&gt; CSS data type denotes a frequency dimension, like the pitch of a speaking voice.\\\"><code>&lt;frequency&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>, that is without the unit (e.g. <code>12.5</code>), and interpreted as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/frequency\\\" title=\\\"The &lt;frequency&gt; CSS data type denotes a frequency dimension, like the pitch of a speaking voice.\\\"><code>&lt;frequency&gt;</code></a> with the specified unit. If it is not valid, that is not a number or out of the range accepted by the CSS property, the default value is used.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0Hz</code>, or, if <code>0Hz</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n   <tr>\\n    <td><code>%</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a></td>\\n    <td>The attribute value is parsed as a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>, that is without the unit (e.g. <code>12.5</code>), and interpreted as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a>. If it is not valid, that is not a number or out of the range accepted by the CSS property, the default value is used.<br>\\n     If the given value is used as a length, <code>attr()</code>computes it to an absolute length.<br>\\n     Leading and trailing spaces are stripped.</td>\\n    <td><code>0%</code>, or, if <code>0%</code> is not a valid value for the property, the property&apos;s minimum value.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>&lt;fallback&gt;</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The value to be used if the associated attribute is missing or contains an invalid value. The fallback value must be valid where <code>attr()</code> is used, even if it is not used, and must not contain another <code>attr()</code> expression. If <code>attr()</code> is not the sole component value of a property, its <code>&lt;fallback&gt;</code> value must be of the type defined by <code>&lt;type-or-unit&gt;</code>. If not set, CSS will use the default value defined for each <code>&lt;type-or-unit&gt;</code>.\"\n        }]\n    },\n    \"aural\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/Aural\",\n        \"SUMMARY\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/@media#Media_groups\\\" title=\\\"CSS/@media#Media_groups\\\">media group</a> defined by the <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> standards.\",\n        \"VALUES\": []\n    },\n    \"azimuth\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/azimuth\",\n        \"SUMMARY\": \"In combination with<code> elevation</code>, <code>azimuth</code> enables different audio sources to be positioned spatially for aural presentation. This is important in that it provides a natural way to tell several voices apart, as each can be positioned to originate at a different location on the sound stage. Stereo output produce a lateral sound stage, while binaural headphones and multi-speaker setups allow for a fully three-dimensional stage.\",\n        \"VALUES\": [{\n            \"value\": \"angle\",\n            \"description\": \"Audible source position is described as an angle within the range <code>-360deg</code> to <code>360deg</code>. The value <code>0deg</code> means directly ahead in the center of the sound stage (this is the default value). <code>90deg</code> is to the right, <code>180deg</code> is behind, and <code>270deg</code> or <code>-90deg</code> is to the left.\"\n        }]\n    },\n    \"backdrop-filter\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter\",\n        \"SUMMARY\": \"The <code>backdrop-filter</code> property provides for effects like blurring or color shifting the area behind an element, which can then be seen through that element by adjusting the element's transparency/opacity.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Keyword indicating that no filter is applied to the backdrop.\"\n        }, {\n            \"value\": \"<code>&lt;filter-function-list&gt;</code>\",\n            \"description\": \"Space-separated list of filter functions, which will be applied to the backdrop. The different filter functions are the same as for the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/filter#Functions\\\"><code>filter</code></a> property.\"\n        }]\n    },\n    \"backface-visibility\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/backface-visibility\",\n        \"SUMMARY\": \"The <strong><code>backface-visibility</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property determines whether or not the back face of the element is visible when facing the user. The back face of an element is always a transparent background, letting, when visible, a mirror image of the front face be displayed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>visible</code>\",\n            \"description\": \"This keyword means that the back face is visible, allowing the front face to be displayed mirrored.\"\n        }, {\n            \"value\": \"<code>hidden</code>\",\n            \"description\": \"This keyword means that the back face is not visible, hiding the front face.\"\n        }]\n    },\n    \"background\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background\",\n        \"SUMMARY\": \"The <strong><code>background</code></strong> CSS property is a shorthand for setting the individual background values in a single place in the style sheet. <code>background</code> can be used to set the values for one or more of: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip\\\" title=\\\"The background-clip CSS property specifies whether an element's background, either the color or image, extends underneath its border.\\\"><code>background-clip</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-color\\\" title=\\\"The background-color CSS property sets the background color of an element, either through a color value or the keyword transparent.\\\"><code>background-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"The CSS background-image property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\\\"><code>background-image</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-origin\\\" title=\\\"The background-origin CSS property determines the background positioning area, that is the position of the origin of an image specified using the background-image CSS property.\\\"><code>background-origin</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\\\" title=\\\"The background-position CSS property sets the initial position for each defined background image, relative to the background position layer defined by background-origin.\\\"><code>background-position</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat\\\" title=\\\"The background-repeat CSS property defines how background images are repeated. A background image can be repeated along the horizontal axis, the vertical axis, both axes, or not repeated at all.\\\"><code>background-repeat</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-size\\\" title=\\\"The background-size CSS property specifies the size of the background images. The size of the image can be fully constrained or only partially in order to preserve its intrinsic ratio.\\\"><code>background-size</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment\\\" title=\\\"If a background-image is specified, the background-attachment CSS property determines whether that image's position is fixed within the viewport, or scrolls along with its containing block.\\\"><code>background-attachment</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;attachment&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment\\\" title=\\\"If a background-image is specified, the background-attachment CSS property determines whether that image&apos;s position is fixed within the viewport, or scrolls along with its containing block.\\\"><code>background-attachment</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;box&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip\\\" title=\\\"The background-clip CSS property specifies whether an element&apos;s background, either the color or image, extends underneath its border.\\\"><code>background-clip</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;background-color&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-color\\\" title=\\\"The background-color CSS property sets the background color of an element, either through a color value or the keyword transparent.\\\"><code>background-color</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;bg-image&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"The CSS background-image property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\\\"><code>background-image</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\\\" title=\\\"The background-position CSS property sets the initial position for each defined background image, relative to the background position layer defined by background-origin.\\\"><code>background-position</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;repeat-style&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat\\\" title=\\\"The background-repeat CSS property defines how background images are repeated. A background image can be repeated along the horizontal axis, the vertical axis, both axes, or not repeated at all.\\\"><code>background-repeat</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;bg-size&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-size\\\" title=\\\"The background-size CSS property specifies the size of the background images. The size of the image can be fully constrained or only partially in order to preserve its intrinsic ratio.\\\"><code>background-size</code></a>. This property must be specified after <strong>&lt;position&gt;</strong>, separated with the &apos;/&apos; character.\"\n        }]\n    },\n    \"background-attachment\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment\",\n        \"SUMMARY\": \"If a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"The CSS background-image property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\\\"><code>background-image</code></a> is specified, the <strong><code>background-attachment</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property determines whether that image's position is fixed within the viewport, or scrolls along with its containing block.\",\n        \"VALUES\": [{\n            \"value\": \"<code>fixed</code>\",\n            \"description\": \"This keyword means that the background is fixed with regard to the viewport. Even if an element has a scrolling mechanism, a &#x2018;fixed&#x2019; background doesn&apos;t move with the element.\"\n        }, {\n            \"value\": \"<code>local</code>\",\n            \"description\": \"This keyword means that the background is fixed with regard to the element&apos;s contents: if the element has a scrolling mechanism, the background scrolls with the element&apos;s contents, and the background painting area and background positioning area are relative to the scrollable area of the element rather than to the border framing them.\"\n        }, {\n            \"value\": \"<code>scroll</code>\",\n            \"description\": \"This keyword means that the background is fixed with regard to the element itself and does not scroll with its contents. (It is effectively attached to the element&apos;s border.)\"\n        }]\n    },\n    \"background-blend-mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-blend-mode\",\n        \"SUMMARY\": \"The <strong><code>background-blend-mode</code></strong> CSS property describes how the element's background images should blend with each other and the element's background color.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;blend-mode&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode\\\" title=\\\"The &lt;blend-mode&gt;&#xA0;type is a collection of keywords describing blend modes.\\\"><code>&lt;blend-mode&gt;</code></a> denoting the blending mode to be applied. There can be several values, separated by commas.\"\n        }]\n    },\n    \"background-clip\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip\",\n        \"SUMMARY\": \"The <strong><code>background-clip</code></strong> CSS property specifies whether an element's background, either the color or image, extends underneath its border.\",\n        \"VALUES\": [{\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"The background extends to the outside edge of the border (but underneath the border in z-ordering).\"\n        }, {\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"No background is drawn below the border (background extends to the outside edge of the padding).\"\n        }, {\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"The background is painted within (clipped to) the content box.\"\n        }, {\n            \"value\": \"<code>text </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The background is painted within (clipped to) the foreground text.\"\n        }]\n    },\n    \"background-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-color\",\n        \"SUMMARY\": \"The <strong><code>background-color</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the background color of an element, either through a color value or the keyword <code>transparent</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"Is a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> that describes the uniform color of the background. Even if one or several <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"The CSS background-image property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\\\"><code>background-image</code></a> are defined, this color can be affect the rendering, by transparency if the images aren&apos;t opaque. In CSS, <code>transparent</code> is a color.\"\n        }]\n    },\n    \"background-image\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> <strong><code>background-image</code></strong> property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"none\\\" id=\\\"none\\\"><code>none</code></a>\",\n            \"description\": \"Is a keyword denoting the absence of images.\"\n        }, {\n            \"value\": \"<a name=\\\"image\\\" id=\\\"image\\\"><code>&lt;image&gt;</code></a>\",\n            \"description\": \"Is an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> denoting the image to display. There can be several of them, separated by commas, as <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Multiple_backgrounds\\\" title=\\\"Multiple backgrounds\\\">multiple backgrounds</a> are supported.\"\n        }]\n    },\n    \"background-origin\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-origin\",\n        \"SUMMARY\": \"The <strong><code>background-origin</code></strong> CSS property determines the background positioning area, that is the position of the origin of an image specified using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-image\\\" title=\\\"The CSS background-image property sets one or several background images for an element. The images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.\\\"><code>background-image</code></a> CSS property.\",\n        \"VALUES\": [{\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"The background extends to the outside edge of the border (but underneath the border in z-ordering).\"\n        }, {\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"No background is drawn below the border (background extends to the outside edge of the padding).\"\n        }, {\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"The background is painted within (clipped to) the content box.\"\n        }]\n    },\n    \"background-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\",\n        \"SUMMARY\": \"The <strong><code>background-position</code></strong> CSS property sets the initial position for each defined background image, relative to the background position layer defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-origin\\\" title=\\\"The background-origin CSS property determines the background positioning area, that is the position of the origin of an image specified using the background-image CSS property.\\\"><code>background-origin</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\\\" title=\\\"The &lt;position&gt; CSS data type denotes a coordinate in a 2D space used to set a location relative to a box.\\\"><code>&lt;position&gt;</code></a>&#x2014;that is, one to four values representing a 2D position in relation to&#xA0;the edges of the element&apos;s box. Relative or absolute offsets can be given. Note that the position can be set outside of the element&apos;s box.\"\n        }]\n    },\n    \"background-position-x\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position-x\",\n        \"SUMMARY\": \"Technical review completed. Editorial review completed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Aligns the left edge of the background image with the left edge of the background position layer.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"Aligns the center of the background image with the center of the background position layer.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Aligns the right edge of the background image with the right edge of the background position layer.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value defines&#xA0;the offset of the given background image&apos;s horizontal edge from the corresponding background position layer&apos;s horitzontal edge. If no edge is mentioned, it refers to the left edge.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> value defining the offset of the given background image&apos;s horitzontal edge from the corresponding background position layer&apos;s horitzontal edge relative to its width. If no edge is given, it refers to the left edge by default.\"\n        }]\n    },\n    \"background-position-y\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position-y\",\n        \"SUMMARY\": \"Technical review completed. Editorial review completed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>top</code>\",\n            \"description\": \"Aligns the top edge of the background image with the top edge of the background position layer.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"Aligns the vertical center of the background image with the vertical center of the background position layer.\"\n        }, {\n            \"value\": \"<code>bottom</code>\",\n            \"description\": \"Aligns the bottom edge of the background image with the bottom edge of the background position layer.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value defining the offset of the given background image&apos;s vertical edge from the corresponding background position layer&apos;s vertical edge. If no edge is given, it refers to the top edge.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> value defining the offset of the given background image&apos;s vertical edge from the corresponding background position layer&apos;s vertical edge relative to its height. If no edge is given, it refers to the top edge.\"\n        }]\n    },\n    \"background-repeat\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat\",\n        \"SUMMARY\": \"The <strong><code>background-repeat</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property defines how background images are repeated. A background image can be repeated along the horizontal axis, the vertical axis, both axes, or not repeated at all.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;repeat-style&gt;</code>\",\n            \"description\": \"The one-value syntax is a shorthand for the full two-value syntax:\"\n        }, {\n            \"value\": \"\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td><strong>Single value</strong></td>\\n    <td><strong>Two-value equivalent</strong></td>\\n   </tr>\\n   <tr>\\n    <td><code>repeat-x</code></td>\\n    <td><code>repeat no-repeat</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>repeat-y</code></td>\\n    <td><code>no-repeat repeat</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>repeat</code></td>\\n    <td><code>repeat repeat</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>space</code></td>\\n    <td><code>space space</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>round</code></td>\\n    <td><code>round round</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>no-repeat</code></td>\\n    <td><code>no-repeat no-repeat</code></td>\\n   </tr>\\n  </tbody>\\n </table>\\n In the two-value syntax, the first value represents the horizontal repetition behavior and the second value represents the vertical behavior. Here is an explanation of how each option works for either direction:\",\n            \"description\": \"\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td><code>repeat</code></td>\\n    <td>The image is repeated as much as needed to cover the whole background image painting area. The last image will be clipped if it doesn&apos;t fit.</td>\\n   </tr>\\n   <tr>\\n    <td><code>space</code></td>\\n    <td>The image is repeated as much as possible without clipping. The first and last images are pinned to either side of the element, and whitespace is distributed evenly between the images. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\\\" title=\\\"The background-position CSS property sets the initial position for each defined background image, relative to the background position layer defined by background-origin.\\\"><code>background-position</code></a> property is ignored unless only one image can be displayed without clipping. The only case where clipping happens using <code>space</code> is when there isn&apos;t enough room to display one image.</td>\\n   </tr>\\n   <tr>\\n    <td><code>round</code></td>\\n    <td>As the allowed space increases in size, the repeated images will stretch (leaving no gaps) until there is room (space left &gt;= half of the image width) for another one to be added. When the next image is added, all of the current ones compress to allow room. Example: An image with an original width of 260px, repeated three times, might stretch until each repetition is 300px wide, and then another image will be added. They will then compress to 225px.</td>\\n   </tr>\\n   <tr>\\n    <td><code>no-repeat</code></td>\\n    <td>The image is not repeated (and hence the background image painting area will not necessarily be entirely covered). The position of the non-repeated background image is defined by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\\\" title=\\\"The background-position CSS property sets the initial position for each defined background image, relative to the background position layer defined by background-origin.\\\"><code>background-position</code></a> CSS property.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"background-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/background-size\",\n        \"SUMMARY\": \"The <strong><code>background-size</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property specifies the size of the background images. The size of the image can be fully constrained or only partially in order to preserve its intrinsic ratio.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"length\\\" id=\\\"length\\\"><code>&lt;length&gt;</code></a>\",\n            \"description\": \"A <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a></code> value that scales the background image to the specified length in the corresponding dimension. Negative lengths are not allowed.\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;percentage&gt;\\\" id=\\\"&lt;percentage&gt;\\\"><code>&lt;percentage&gt;</code></a>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> value that scales the background image in the corresponding dimension to the specified percentage of the background positioning area, which is determined by the value of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-origin\\\" title=\\\"The background-origin CSS property determines the background positioning area, that is the position of the origin of an image specified using the background-image CSS property.\\\"><code>background-origin</code></a>. The background positioning area is, by default, the area containing the content of the box and its padding; the area may also be changed to just the content or to the area containing borders, padding, and content. If the background&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>attachment</code></a> is <code>fixed</code>, the background positioning area is instead the entire area of the browser window, not including the area covered by scrollbars if they are present. Negative percentages are not allowed.\"\n        }, {\n            \"value\": \"<a name=\\\"auto\\\" id=\\\"auto\\\"><code>auto</code></a>\",\n            \"description\": \"A keyword that scales the background image in the corresponding direction such that its intrinsic proportion is maintained.\"\n        }, {\n            \"value\": \"<a name=\\\"contain\\\" id=\\\"contain\\\"><code>contain</code></a>\",\n            \"description\": \"A keyword that scales the image as large as possible and maintains image aspect ratio (image doesn&apos;t get squished). Image is <strong> letterboxed</strong> within the container. When the image and container have different dimensions, the empty areas (either top/bottom of left/right) are filled with the background-color.\"\n        }, {\n            \"value\": \"<a name=\\\"cover\\\" id=\\\"cover\\\"><code>cover</code></a>\",\n            \"description\": \"A keyword that is the inverse of <code>contain</code>. Scales the image as large as possible and maintains image aspect ratio (image doesn&apos;t get squished). The image &quot;covers&quot; the entire width or height of the container. When the image and container have different dimensions, <em>the image is clipped</em> either left/right or top/bottom.\"\n        }, {\n            \"value\": \"If both components of <code>background-size</code> are specified and are not <code>auto</code>:\",\n            \"description\": \"The background image renders at the specified size.\"\n        }, {\n            \"value\": \"If the <code>background-size</code> is <code>contain</code> or <code>cover</code>:\",\n            \"description\": \"The image is rendered, preserving its intrinsic proportion, at the largest size contained within, or covering, the background positioning area.&#xA0; If the image has no intrinsic proportion, then it is rendered at the size of the background positioning area.\"\n        }, {\n            \"value\": \"If the <code>background-size</code> is <code>auto</code> or <code>auto auto</code>:\",\n            \"description\": \"If the image has both intrinsic dimensions, it is rendered at that size.&#xA0; If it has no intrinsic dimensions and no intrinsic proportion, it is rendered at the size of the background positioning area.&#xA0; If it has no dimensions but has a proportion, it&apos;s rendered as if <code>contain</code> had been specified instead.&#xA0; If the image has one intrinsic dimension and a proportion, it&apos;s rendered at the size determined by that one dimension and the proportion.&#xA0; If the image has one intrinsic dimension but no proportion, it&apos;s rendered using the intrinsic dimension and the corresponding dimension of the background positioning area.\\n <div class=\\\"note\\\"><strong>Note:</strong> SVG images have a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio\\\">preserveAspectRatio</a> attribute which defaults to the equivalent of &apos;contain&apos;. On Firefox 43, as opposed to Chrome 52,&#xA0;an explicit background-size&#xA0;causes preserveAspectRatio to be ignored.</div>\\n \"\n        }, {\n            \"value\": \"If the background-size has one <code>auto</code> component and one non-<code>auto</code> component:\",\n            \"description\": \"If the image has an intrinsic proportion, then render it using the specified dimension, and compute the other dimension from the specified dimension and the intrinsic proportion.&#xA0; If the image has no intrinsic proportion, use the specified dimension for that dimension.&#xA0; For the other dimension, use the image&apos;s corresponding intrinsic dimension if there is one.&#xA0; If there is no such intrinsic dimension, use the corresponding dimension of the background positioning area.\"\n        }]\n    },\n    \"block-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/block-size\",\n        \"SUMMARY\": \"The <strong><code>block-size</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the horizontal or vertical size of an element's block depending on its writing mode. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> or the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> property depending on the value defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>block-size</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> properties.\"\n        }]\n    },\n    \"border\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border\",\n        \"SUMMARY\": \"The <code>border</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand property</a> for setting the individual border property values in a single place in the style sheet. <code>border</code> can be used to set the values for one or more of: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element's border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;</code>\",\n            \"description\": \"Default value <code>medium</code> is used if absent. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;br-style&gt;</code>\",\n            \"description\": \"Default value <code>none</code> is used if absent. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> denoting the color of the border. If not set, its default value is the value of the element&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element&apos;s text content, and its decorations. It also sets the &lt;currentcolor&gt; value which may be used as an indirect value on other properties, and is the default for other color properties, such as border-color.\\\"><code>color</code></a> property (the text color, not the background color). See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a>.\"\n        }]\n    },\n    \"border-block-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end\",\n        \"SUMMARY\": \"The<strong> <code>border-block-end</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand property for setting the individual logical block end border property values in a single place in the style sheet. <code>border-block-end</code> can be used to set the values for one or more of: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end-width\\\" title=\\\"The border-block-end-width CSS property defines the width of the logical block end border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width, or border-left-width property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-block-end-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end-style\\\" title=\\\"The border-block-end-style CSS property defines the style of the logical block end border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-style,&#xA0;border-right-style,&#xA0;border-bottom-style, or border-left-style property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-block-end-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end-color\\\" title=\\\"The border-block-end-color CSS property defines the color of the logical block end border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-color,&#xA0;border-right-color,&#xA0;border-bottom-color, or border-left-color property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-block-end-color</code></a>. It maps to a physical border depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top\\\" title=\\\"The border-top CSS property is a shorthand that sets the values of border-top-color, border-top-style, and border-top-width. These properties describe the top border of elements.\\\"><code>border-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right\\\" title=\\\"The border-right CSS property is a shorthand that sets the values of border-right-color, border-right-style, and border-right-width. These properties describe the right border of elements.\\\"><code>border-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom\\\" title=\\\"The border-bottom CSS property is a shorthand that sets the values of border-bottom-color, border-bottom-style, and border-bottom-width. These properties describe the bottom border of elements.\\\"><code>border-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left\\\" title=\\\"The border-left CSS property is a shorthand that sets the values of border-left-color, border-left-style, and border-left-width. These properties describe the left border of elements.\\\"><code>border-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element&apos;s text content, and its decorations. It doesn&apos;t affect any other characteristic of the element; it should really be called text-color and would have been named so, save for historical reasons and its appearance in CSS Level 1.\\\"><code>color</code></a>\"\n        }]\n    },\n    \"border-block-end-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end-color\",\n        \"SUMMARY\": \"The <code>border-block-end-color</code> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the color of the logical block end border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\"><code>border-top-color</code></a>, <a title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\"><code>border-right-color</code></a>, <a title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\"><code>border-bottom-color</code></a>, or <a title=\\\"The border-left-color CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\"><code>border-left-color</code></a> property depending on the values defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>, <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a>, and <a title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a>\"\n        }]\n    },\n    \"border-block-end-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end-style\",\n        \"SUMMARY\": \"The<strong> <code>border-block-end-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the style of the logical block end border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\\\" title=\\\"The border-top-style CSS property sets the line style of the top border of a box.\\\"><code>border-top-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\\\" title=\\\"The border-right-style CSS property sets the line style of the right border of a box.\\\"><code>border-right-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\\\" title=\\\"The border-bottom-style CSS property sets the line style of the bottom border of a box.\\\"><code>border-bottom-style</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\\\" title=\\\"The border-left-style CSS property sets the line style of the left border of a box.\\\"><code>border-left-style</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>\"\n        }]\n    },\n    \"border-block-end-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-end-width\",\n        \"SUMMARY\": \"The <strong><code>border-block-end-width</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the width of the logical block end border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>\"\n        }]\n    },\n    \"border-block-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start\",\n        \"SUMMARY\": \"The<strong> <code>border-block-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand property for setting the individual logical block start border property values in a single place in the style sheet. <code>border-block-start</code> can be used to set the values for one or more of: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-width\\\" title=\\\"The border-block-start-width CSS property defines the width of the logical block start border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width, or border-left-width property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-block-start-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-style\\\" title=\\\"The border-block-start-style CSS property defines the style of the logical block start border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-style,&#xA0;border-right-style,&#xA0;border-bottom-style, or border-left-style property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-block-start-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-color\\\" title=\\\"The border-block-start-color CSS property defines the color of the logical block start border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-color,&#xA0;border-right-color,&#xA0;border-bottom-color, or border-left-color property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-block-start-color</code></a>. It maps to a physical border depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top\\\" title=\\\"The border-top CSS property is a shorthand that sets the values of border-top-color, border-top-style, and border-top-width. These properties describe the top border of elements.\\\"><code>border-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right\\\" title=\\\"The border-right CSS property is a shorthand that sets the values of border-right-color, border-right-style, and border-right-width. These properties describe the right border of elements.\\\"><code>border-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom\\\" title=\\\"The border-bottom CSS property is a shorthand that sets the values of border-bottom-color, border-bottom-style, and border-bottom-width. These properties describe the bottom border of elements.\\\"><code>border-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left\\\" title=\\\"The border-left CSS property is a shorthand that sets the values of border-left-color, border-left-style, and border-left-width. These properties describe the left border of elements.\\\"><code>border-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element&apos;s text content, and its decorations. It doesn&apos;t affect any other characteristic of the element; it should really be called text-color and would have been named so, save for historical reasons and its appearance in CSS Level 1.\\\"><code>color</code></a>\"\n        }]\n    },\n    \"border-block-start-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-color\",\n        \"SUMMARY\": \"The <strong><code>border-block-start-color</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the color of the logical block start border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\" title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\"><code>border-top-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\" title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\"><code>border-right-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\" title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\"><code>border-bottom-color</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\" title=\\\"The border-left-color CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\"><code>border-left-color</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a>\"\n        }]\n    },\n    \"border-block-start-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-style\",\n        \"SUMMARY\": \"The <strong><code>border-block-start-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the style of the logical block start border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\\\" title=\\\"The border-top-style CSS property sets the line style of the top border of a box.\\\"><code>border-top-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\\\" title=\\\"The border-right-style CSS property sets the line style of the right border of a box.\\\"><code>border-right-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\\\" title=\\\"The border-bottom-style CSS property sets the line style of the bottom border of a box.\\\"><code>border-bottom-style</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\\\" title=\\\"The border-left-style CSS property sets the line style of the left border of a box.\\\"><code>border-left-style</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a>\"\n        }]\n    },\n    \"border-block-start-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-width\",\n        \"SUMMARY\": \"The <strong><code>border-block-start-width</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the width of the logical block start border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\"><code>border-top-width</code></a>, <a title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\"><code>border-right-width</code></a>, <a title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\"><code>border-bottom-width</code></a>, or <a title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\"><code>border-left-width</code></a> property depending on the values defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>, <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a>, and <a title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>\"\n        }]\n    },\n    \"border-bottom\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom\",\n        \"SUMMARY\": \"The <code>border-bottom</code> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand that sets the values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\" title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\"><code>border-bottom-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\\\" title=\\\"The border-bottom-style CSS property sets the line style of the bottom border of a box.\\\"><code>border-bottom-style</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a>. These properties describe the bottom border of elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;br-style&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\\\" title=\\\"The border-bottom-style CSS property sets the line style of the bottom border of a box.\\\"><code>border-bottom-style</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\" title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\"><code>border-bottom-color</code></a>.\"\n        }]\n    },\n    \"border-bottom-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\",\n        \"SUMMARY\": \"The<strong> <code>border-bottom-color</code></strong> CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element's border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom\\\" title=\\\"The border-bottom CSS property is a shorthand that sets the values of border-bottom-color, border-bottom-style, and border-bottom-width. These properties describe the bottom border of elements.\\\"><code>border-bottom</code></a> are more convenient and preferable.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> CSS value describing the color of the bottom border.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword denoting the color of the bottom border of the parent&apos;s element (which may be different from the <code>border-bottom-color</code> default value)\"\n        }]\n    },\n    \"border-bottom-left-radius\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-left-radius\",\n        \"SUMMARY\": \"The<strong> <code>border-bottom-left-radius</code></strong> CSS property sets the rounding of the bottom-left corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n        \"VALUES\": [{\n            \"value\": \"<em>radius</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the radius of the circle to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the horizontal semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the vertical semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Denotes the size of the circle radius or the semi-major and semi-minor axes of the ellipsis. As absolute length it can be expressed in any unit allowed by the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> data type. Percentages for the horizontal axis refer to the width of the box, percentages for the vertical axis refer to the height of the box. Negative values are invalid.\"\n        }]\n    },\n    \"border-bottom-right-radius\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius\",\n        \"SUMMARY\": \"The <strong><code>border-bottom-right-radius</code></strong> CSS property sets the rounding of the bottom-right corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n        \"VALUES\": [{\n            \"value\": \"<em>radius</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> denoting the radius of the circle to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> denoting the horizontal semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> denoting the vertical semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Denotes the size of the circle radius or the semi-major and semi-minor axes of the ellipsis. As absolute length it can be expressed in any unit allowed by the CSS <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> data type. Percentages for the horizontal axis refer to the width of the box, percentages for the vertical axis refer to the height of the box. Negative values are invalid.\"\n        }]\n    },\n    \"border-bottom-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\",\n        \"SUMMARY\": \"The <strong><code>border-bottom-style</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the line style of the bottom border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-style&gt;</code>\",\n            \"description\": \"Is a keyword describing the style of the bottom border. It can have the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>none</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: none; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Like for the <code>hidden</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>none</code> value has the lowest priority: it means that if any other conflicting border is set, it will be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>hidden</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: hidden; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Like for the <code>none</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>hidden</code> value has the highest priority: it means that if any other conflicting border is set, it won&apos;t be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>dotted</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: dotted; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a series of rounded dots. The spacing of the dots are not defined by the specification and are implementation-specific. The radius of the dots is half the calculated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>dashed</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: dashed; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a series of short square-ended dashes or line segments. The exact size and length of the segments are not defined by the specification and are implementation-specific.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>solid</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: solid; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a single, straight, solid line.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>double</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: double; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays two straight lines that add up to the pixel amount defined as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\"><code>border-bottom-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>groove</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: groove; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border leading to a carved effect. It is the opposite of <code>ridge</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>ridge</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: ridge; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border with a 3D effect, like if it is coming out of the page. It is the opposite of <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>inset</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: inset; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border that makes the box appear embedded. It is the opposite of <code>outset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>outset</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-bottom-style: outset; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <p>Displays a border that makes the box appear in 3D, embossed. It is the opposite of <code>inset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>ridge</code>.</p>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the border style used by the parent of the current element.\"\n        }]\n    },\n    \"border-bottom-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\",\n        \"SUMMARY\": \"The <strong><code>border-bottom-width</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the width of the bottom border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;<code>br-width&gt;</code>\",\n            \"description\": \"Is either a non-negative explicit <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value or a keyword denoting the thickness of the bottom border. The keyword must be one of the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thin</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-bottom-style: solid; border-bottom-width: thin; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thin border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>medium</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-bottom-style: solid; border-bottom-width: medium; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A medium border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thick</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-bottom-style: solid; border-bottom-width: thick; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thick border</td>\\n   </tr>\\n  </tbody>\\n </table>\\n The specification doesn&apos;t precisely define the thickness of each of the keywords, which is therefore implementation specific. Nevertheless, it requests that the thickness does follow the <code>thin &#x2264; medium &#x2264; thick</code> inequality and that the values are constant on a single document.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the calculated value of the <code>border-bottom-width</code> of the parent&apos;s element.\"\n        }]\n    },\n    \"border-collapse\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\",\n        \"SUMMARY\": \"The <strong><code>border-collapse</code></strong> CSS property determines whether a table's borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\",\n        \"VALUES\": [{\n            \"value\": \"<code>separate</code>\",\n            \"description\": \"Is a keyword requesting the use of the separated-border table rendering model. It is the default value.\"\n        }, {\n            \"value\": \"<code>collapse</code>\",\n            \"description\": \"Is a keyword requesting the use of the collapsed-border table rendering model.\"\n        }]\n    },\n    \"border-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\",\n        \"SUMMARY\": \"The <strong><code>border-color</code></strong> CSS property is a shorthand for setting the color of the four sides of an element's border: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\" title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\"><code>border-top-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\" title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\"><code>border-right-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\" title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\"><code>border-bottom-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\" title=\\\"The border-left-color CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\"><code>border-left-color</code></a>\",\n        \"VALUES\": [{\n            \"value\": \"<code>color</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\"><code>&lt;color&gt;</code></a> denoting the color to apply to the edges.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that all four values are inherited from their parent&apos;s element calculated value.\"\n        }]\n    },\n    \"border-image\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image\",\n        \"SUMMARY\": \"The <strong><code>border-image</code></strong> CSS property allows drawing an image on the borders of elements. This makes drawing complex looking widgets much simpler than it has been and removes the need for nine boxes in some cases. The <code>border-image</code> is used instead of the border styles given by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a> properties. Though the specification requires that <code>border-style</code> must be present if <code>border-image</code> is used, some browsers may not implement this.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"See the respective properties for the different values.\"\n        }]\n    },\n    \"border-image-outset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-outset\",\n        \"SUMMARY\": \"The <strong><code>border-image-outset</code></strong> property describes by what amount the <dfn>border image area</dfn> extends beyond the border box.\",\n        \"VALUES\": [{\n            \"value\": \"<em>sides</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box in all four directions.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box in both horizontal directions&#xA0;(left and right).\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box in both vertical directions&#xA0;(top and bottom).\"\n        }, {\n            \"value\": \"<em>top</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box past its top edge.\"\n        }, {\n            \"value\": \"<em>bottom</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box past its bottom edge.\"\n        }, {\n            \"value\": \"<em>right</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box past its right edge.\"\n        }, {\n            \"value\": \"<em>left</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> of the amount by which the border image area extends beyond the border box past its left edge.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that all four values are inherited from each parent&#xA0;elements&apos; calculated value.\"\n        }]\n    },\n    \"border-image-repeat\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-repeat\",\n        \"SUMMARY\": \"The <strong><code>border-image-repeat</code></strong> CSS property defines how the middle part of a border image is handled so that it can match the size of the border. It has a one-value syntax that describes the behavior of all the sides, and a two-value syntax that sets a different value for the horizontal and vertical behavior.\",\n        \"VALUES\": [{\n            \"value\": \"<em>type</em>\",\n            \"description\": \"One of the <code>stretch</code>, <code>repeat</code>, or <code>round</code> keywords denoting how the image is treated both horizontally and vertically.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"One of the <code>stretch</code>, <code>repeat</code>, or <code>round</code> keywords denoting how the image is treated horizontally.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"One of the <code>stretch</code>, <code>repeat</code>, or <code>round</code> keywords denoting how the image is treated vertically.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"Keyword indicating that the image must be stretched to fill the gap between the two borders.\"\n        }, {\n            \"value\": \"<code>repeat</code>\",\n            \"description\": \"Keyword indicating that the image must be repeated until it fills the gap between the two borders.\"\n        }, {\n            \"value\": \"<code>round</code>\",\n            \"description\": \"Keyword indicating that the image must be repeated until it fills the gap between the two borders. If the image doesn&apos;t fit after being repeated for an integral number of times, the image is rescaled to fit.\"\n        }, {\n            \"value\": \"<code>space</code>\",\n            \"description\": \"The image is tiled (repeated) to fill the area. If it does not fill the area with a whole number of tiles, the extra space is distributed around the tiles.\"\n        }]\n    },\n    \"border-image-slice\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-slice\",\n        \"SUMMARY\": \"The <strong><code>border-image-slice</code></strong> CSS property divides the image specified by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-source\\\" title=\\\"The border-image-source CSS property defines the &lt;image&gt; to use instead of the style of the border. If this property is set to none, the style defined by border-style is used instead.\\\"><code>border-image-source</code></a> in nine regions: the four corners, the four edges and the middle. It does this by specifying 4 inwards offsets.\",\n        \"VALUES\": [{\n            \"value\": \"<em>slice</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the four slicing lines. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the two slicing lines corresponding to the horizontal edges, the right and the left ones. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the two slicing lines corresponding to the vertical edges, the top and the bottom ones. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<em>top</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the top slicing line. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<em>bottom</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the bottom slicing line. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<em>right</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the right slicing line. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<em>left</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the offset for the left slicing line. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> represents <em>pixels</em> for raster images and <em>coordinates</em> for vector images. Also, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the height or width of the image, whichever is adequate. Negative values are invalid and values greater than the relevant size, height or width, are clamped to <code>100%</code>.\"\n        }, {\n            \"value\": \"<code>fill</code>\",\n            \"description\": \"Is a keyword whose presence forces the use of the middle image slice to be displayed over the background image, its size and height are resized like those of the top and left image slices, respectively.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that all four values are inherited from their parent&apos;s element calculated value.\"\n        }]\n    },\n    \"border-image-source\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-source\",\n        \"SUMMARY\": \"The <strong><code>border-image-source</code></strong> CSS property defines the <a title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\"><code>&lt;image&gt;</code></a> to use instead of the style of the border. If this property is set to <code>none</code>, the style defined by <a title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\"><code>border-style</code></a> is used instead.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Specifies that no image should be used for the border. Instead the style defined by <a title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\"><code>border-style</code></a> is used.\"\n        }, {\n            \"value\": \"<code>&lt;image&gt;</code>\",\n            \"description\": \"Image reference to use for the border.\"\n        }]\n    },\n    \"border-image-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-width\",\n        \"SUMMARY\": \"The <strong><code>border-image-width</code></strong> CSS property defines the width of the border image by defining inward offsets from the border edges. If the <code>border-image-width</code> is greater than the <a title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\"><code>border-width</code></a>, then the border image extends beyond the padding (and/or content) edge.\",\n        \"VALUES\": [{\n            \"value\": \"<em>width</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to all four edges. It is used only in the one-value syntax.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to all vertical edges, that is the top and bottom edges. It is used only in the two-value syntax.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to all horizontal edges, that is the right and left edges. It is used only in the two- and three-value syntaxes.\"\n        }, {\n            \"value\": \"<em>top</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to the top edge. It is used only in the three- and four-value syntaxes.\"\n        }, {\n            \"value\": \"<em>bottom</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to the bottom edge. It is used only in the three- and four-value syntaxes.\"\n        }, {\n            \"value\": \"<em>right</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to the right edge. It is used only in the four-value syntax.\"\n        }, {\n            \"value\": \"<em>left</em>\",\n            \"description\": \"Is a value denoting the width of the image used as a border to apply to the left edge. It is used only in the four-value syntax.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that all four values are inherited from their parent&apos;s element calculated value.\"\n        }, {\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Represents the width of the border. It can be an absolute or relative length. Percentages refer to the width of the border image area for horizontal offsets and the height of the border image area for vertical offsets. This length must not be negative.\"\n        }, {\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"Represents a multiple of the computed value of the element&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> property to be used as the border width. The number must not be negative.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Causes the border image width to equal the intrinsic width or height (whichever is applicable) of the corresponding <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-slice\\\" title=\\\"The border-image-slice CSS property divides the image specified by border-image-source in nine regions: the four corners, the four edges and the middle. It does this by specifying 4 inwards offsets.\\\"><code>border-image-slice</code></a>. If the image does not have the required intrinsic dimension then the corresponding computed border-width is used instead.\"\n        }]\n    },\n    \"border-inline-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end\",\n        \"SUMMARY\": \"The <strong><code>border-inline-end</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand property for setting the individual logical inline end border property values in a single place in the style sheet. <code>border-inline-end</code> can be used to set the values for one or more of: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-width\\\" title=\\\"The border-inline-end-width CSS property defines the width of the logical inline end border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width, or border-left-width property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-inline-end-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-style\\\" title=\\\"The border-inline-end-style CSS property defines the style of the logical inline end border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-style,&#xA0;border-right-style,&#xA0;border-bottom-style, or border-left-style property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-inline-end-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-color\\\" title=\\\"The border-inline-end-color CSS property defines the color of the logical inline end border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-color,&#xA0;border-right-color,&#xA0;border-bottom-color, or border-left-color property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-inline-end-color</code></a>. It maps to a physical border depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top\\\" title=\\\"The border-top CSS property is a shorthand that sets the values of border-top-color, border-top-style, and border-top-width. These properties describe the top border of elements.\\\"><code>border-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right\\\" title=\\\"The border-right CSS property is a shorthand that sets the values of border-right-color, border-right-style, and border-right-width. These properties describe the right border of elements.\\\"><code>border-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom\\\" title=\\\"The border-bottom CSS property is a shorthand that sets the values of border-bottom-color, border-bottom-style, and border-bottom-width. These properties describe the bottom border of elements.\\\"><code>border-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left\\\" title=\\\"The border-left CSS property is a shorthand that sets the values of border-left-color, border-left-style, and border-left-width. These properties describe the left border of elements.\\\"><code>border-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property sets the width of the border of a box. Using the shorthand property border is often more convenient.\\\"><code>border-width</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the elements border.\\\"><code>border-style</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"Technical review completed. Editorial review completed.\\\"><code>color</code></a>\"\n        }]\n    },\n    \"border-inline-end-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-color\",\n        \"SUMMARY\": \"The <strong><code>border-inline-end-color</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the color of the logical inline end border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\" title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\"><code>border-top-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\" title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\"><code>border-right-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\" title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\"><code>border-bottom-color</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\" title=\\\"The border-left-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\"><code>border-left-color</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a>\"\n        }]\n    },\n    \"border-inline-end-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-style\",\n        \"SUMMARY\": \"The <strong><code>border-inline-end-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the style of the logical inline end border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\\\" title=\\\"The border-top-style CSS property sets the line style of the top border of a box.\\\"><code>border-top-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\\\" title=\\\"The border-right-style CSS property sets the line style of the right border of a box.\\\"><code>border-right-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\\\" title=\\\"The border-bottom-style CSS property sets the line style of the bottom border of a box.\\\"><code>border-bottom-style</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\\\" title=\\\"The border-left-style CSS property sets the line style of the left border of a box.\\\"><code>border-left-style</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the elements border.\\\"><code>border-style</code></a>\"\n        }]\n    },\n    \"border-inline-end-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-width\",\n        \"SUMMARY\": \"The<strong> <code>border-inline-end-width</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the width of the logical inline end border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>border-bottom-width</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property sets the width of the border of a box. Using the shorthand property border is often more convenient.\\\"><code>border-width</code></a>\"\n        }]\n    },\n    \"border-inline-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start\",\n        \"SUMMARY\": \"The<strong> <code>border-inline-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand property for setting the individual logical inline start border property values in a single place in the style sheet. <code>border-inline-start</code> can be used to set the values for one or more of: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-width\\\" title=\\\"The border-inline-start-width CSS property defines the width of the logical inline start border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width, or border-left-width property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-inline-start-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-style\\\" title=\\\"The border-inline-start-style CSS property defines the style of the logical inline start border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-style,&#xA0;border-right-style,&#xA0;border-bottom-style, or border-left-style property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-inline-start-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-color\\\" title=\\\"The border-inline-start-color CSS property defines the color of the logical inline start border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the border-top-color,&#xA0;border-right-color,&#xA0;border-bottom-color, or border-left-color property depending on the values defined for writing-mode, direction, and text-orientation.\\\"><code>border-inline-start-color</code></a>. It maps to a physical border depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top\\\" title=\\\"The border-top CSS property is a shorthand that sets the values of border-top-color, border-top-style, and border-top-width. These properties describe the top border of elements.\\\"><code>border-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right\\\" title=\\\"The border-right CSS property is a shorthand that sets the values of border-right-color, border-right-style, and border-right-width. These properties describe the right border of elements.\\\"><code>border-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom\\\" title=\\\"The border-bottom CSS property is a shorthand that sets the values of border-bottom-color, border-bottom-style, and border-bottom-width. These properties describe the bottom border of elements.\\\"><code>border-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left\\\" title=\\\"The border-left CSS property is a shorthand that sets the values of border-left-color, border-left-style, and border-left-width. These properties describe the left border of elements.\\\"><code>border-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property sets the width of the border of a box. Using the shorthand property border is often more convenient.\\\"><code>border-width</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the elements border.\\\"><code>border-style</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"Technical review completed. Editorial review completed.\\\"><code>color</code></a>\"\n        }]\n    },\n    \"border-inline-start-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-color\",\n        \"SUMMARY\": \"The <strong><code>border-inline-start-color</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the color of the logical inline start border of an element, which maps to a physical border color depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\"><code>border-top-color</code></a>, <a title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\"><code>border-right-color</code></a>, <a title=\\\"The border-bottom-color CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties border-color or border-bottom are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-color\\\"><code>border-bottom-color</code></a>, or <a title=\\\"The border-left-color CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\"><code>border-left-color</code></a> property depending on the values defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>, <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a>, and <a title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-color&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element&apos;s border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a>\"\n        }]\n    },\n    \"border-inline-start-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-style\",\n        \"SUMMARY\": \"The <strong><code>border-inline-start-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the style of the logical inline start border of an element, which maps to a physical border style depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\\\" title=\\\"The border-top-style CSS property sets the line style of the top border of a box.\\\"><code>border-top-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\\\" title=\\\"The border-right-style CSS property sets the line style of the right border of a box.\\\"><code>border-right-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-style\\\" title=\\\"The border-bottom-style CSS property sets the line style of the bottom border of a box.\\\"><code>border-bottom-style</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\\\" title=\\\"The border-left-style CSS property sets the line style of the left border of a box.\\\"><code>border-left-style</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the elements border.\\\"><code>border-style</code></a>\"\n        }]\n    },\n    \"border-inline-start-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-width\",\n        \"SUMMARY\": \"The <strong><code>border-inline-start-width</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the width of the logical inline start border of an element, which maps to a physical border width depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>border-bottom-width</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;border-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property sets the width of the border of a box. Using the shorthand property border is often more convenient.\\\"><code>border-width</code></a>\"\n        }]\n    },\n    \"border-left\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left\",\n        \"SUMMARY\": \"The <strong><code>border-left</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand that sets the values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\" title=\\\"The border-left-color CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\"><code>border-left-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\\\" title=\\\"The border-left-style CSS property sets the line style of the left border of a box.\\\"><code>border-left-style</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a>. These properties describe the left border of elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;br-style&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\\\" title=\\\"The border-left-style CSS property sets the line style of the left border of a box.\\\"><code>border-left-style</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\\\" title=\\\"The border-left-color CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties border-color or border-left are more convenient and preferable.\\\"><code>border-left-color</code></a>.\"\n        }]\n    },\n    \"border-left-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-color\",\n        \"SUMMARY\": \"The <strong><code>border-left-color</code></strong> CSS property sets the color of the left border of an element. Note that in many cases the shorthand CSS properties <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element's border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left\\\" title=\\\"The border-left CSS property is a shorthand that sets the values of border-left-color, border-left-style, and border-left-width. These properties describe the left border of elements.\\\"><code>border-left</code></a> are more convenient and preferable.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> CSS value describing the color of the left border.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword denoting the color of the bottom border of the parent&apos;s element (which may be different from the <code>border-left-color</code> default value)\"\n        }]\n    },\n    \"border-left-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-style\",\n        \"SUMMARY\": \"The <strong><code>border-left-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the line style of the left border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-style&gt;</code>\",\n            \"description\": \"Is a keyword describing the style of the left border. It can have the following values:\\n <table>\\n  <tbody>\\n   <tr>\\n    <td><code>none</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: none; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Like for the <code>hidden</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>none</code> value has the lowest priority: it means that if any other conflicting border is set, it will be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td><code>hidden</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: hidden; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Like for the <code>none</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>hidden</code> value has the highest priority: it means that if any other conflicting border is set, it won&apos;t be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td><code>dotted</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: dotted; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays a series of rounded dots. The spacing of the dots are not defined by the specification and are implementation-specific. The radius of the dots is half the calculated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>dashed</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: dashed; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays a series of short square-ended dashes or line segments. The exact size and length of the segments are not defined by the specification and are implementation-specific.</td>\\n   </tr>\\n   <tr>\\n    <td><code>solid</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: solid; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays a single, straight, solid line.</td>\\n   </tr>\\n   <tr>\\n    <td><code>double</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: double; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays two straight lines that add up to the pixel amount defined as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\" title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\"><code>border-left-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>groove</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: groove; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays a border leading to a carved effect. It is the opposite of <code>ridge</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ridge</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: ridge; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays a border with a 3D effect, like if it is coming out of the page. It is the opposite of <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>inset</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: inset; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>Displays a border that makes the box appear embedded. It is the opposite of <code>outset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>outset</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-left-style: outset; background-color: palegreen;\\\"><span style=\\\"display: none;\\\">fake</span></div>\\n    </td>\\n    <td>\\n     <p>Displays a border that makes the box appear in 3D, embossed. It is the opposite of <code>inset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>ridge</code>.</p>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"inherit\",\n            \"description\": \"Represents the border style used by the parent of the current element.\"\n        }]\n    },\n    \"border-left-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\",\n        \"SUMMARY\": \"The <strong><code>border-left-width</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property sets the width of the left border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;</code>\",\n            \"description\": \"Is either a non-negative explicit <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value or a keyword denoting the thickness of the left border. The keyword must be one of the following values:\\n <table>\\n  <tbody>\\n   <tr>\\n    <td><code>thin</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-left-style: solid; border-left-width: thin; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>A thin border</td>\\n   </tr>\\n   <tr>\\n    <td><code>medium</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-left-style: solid; border-left-width: medium; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>A medium border</td>\\n   </tr>\\n   <tr>\\n    <td><code>thick</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-left-style: solid; border-left-width: thick; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>A thick border</td>\\n   </tr>\\n  </tbody>\\n </table>\\n The specification doesn&apos;t define precisely the thickness of each fo the keywords, which is therefore implementation specific. Nevertheless, it requests that the thickness does follow the <code>thin &#x2264; medium &#x2264; thick</code> pattern and is constant on a single document.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the calculated value of the <code>border-left-width</code> of the parent&apos;s element.\"\n        }]\n    },\n    \"border-radius\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius\",\n        \"SUMMARY\": \"The <strong><code>border-radius</code></strong> CSS property allows Web authors to define how rounded border corners are. The curve of each corner is defined using one or two radii, defining its shape: circle or ellipse.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Denotes the size of the circle radius or the semi-major and semi-minor axes of the ellipsis. It can be expressed in any unit allowed by the CSS <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> data types. Negative values are invalid.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Denotes the size of the circle radius, or the semi-major and semi-minor axes of the ellipsis, using percentage values. Percentages for the horizontal axis refer to the width of the box, percentages for the vertical axis refer to the height of the box. Negative values are invalid.\"\n        }]\n    },\n    \"border-right\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right\",\n        \"SUMMARY\": \"The <strong><code>border-right</code></strong> <a title=\\\"CSS\\\" href=\\\"/en/CSS\\\">CSS</a> property is a shorthand that sets the values of <a title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\"><code>border-right-color</code></a>, <a title=\\\"The border-right-style CSS property sets the line style of the right border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\\\"><code>border-right-style</code></a>, and <a title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\"><code>border-right-width</code></a>. These properties describe the right border of elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;br-style&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\\\" title=\\\"The border-right-style CSS property sets the line style of the right border of a box.\\\"><code>border-right-style</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\\\" title=\\\"The border-right-color CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties&#xA0; border-color or border-right are more convenient and preferable.\\\"><code>border-right-color</code></a>.\"\n        }]\n    },\n    \"border-right-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-color\",\n        \"SUMMARY\": \"The <strong><code>border-right-color</code></strong> CSS property sets the color of the right border of an element. Note that in many cases the shorthand CSS properties  <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\" title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element's border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\"><code>border-color</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right\\\" title=\\\"The border-right CSS property is a shorthand that sets the values of border-right-color, border-right-style, and border-right-width. These properties describe the right border of elements.\\\"><code>border-right</code></a> are more convenient and preferable.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color</code>&gt;\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> CSS value describing the color of the right border.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword denoting the color of the bottom border of the parent&apos;s element (which may be different from the <code>border-right-color</code> default value)\"\n        }]\n    },\n    \"border-right-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-style\",\n        \"SUMMARY\": \"The <strong><code>border-right-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the line style of the right border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-style&gt;</code>\",\n            \"description\": \"Is a keyword describing the style of the bottom border. It can have the following values:\\n <table>\\n  <tbody>\\n   <tr>\\n    <td><code>none</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: none; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Like for the <code>hidden</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>none</code> value has the lowest priority: it means that if any other conflicting border is set, it will be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td><code>hidden</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: hidden; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Like for the <code>none</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>hidden</code> value has the highest priority: it means that if any other conflicting border is set, it won&apos;t be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td><code>dotted</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: dotted; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays a series of rounded dots. The spacing of the dots are not defined by the specification and are implementation-specific. The radius of the dots is half the calculated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>dashed</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: dashed; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays a series of short square-ended dashes or line segments. The exact size and length of the segments are not defined by the specification and are implementation-specific.</td>\\n   </tr>\\n   <tr>\\n    <td><code>solid</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: solid; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays a single, straight, solid line.</td>\\n   </tr>\\n   <tr>\\n    <td><code>double</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: double; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays two straight lines that add up to the pixel amount defined as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\" title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\"><code>border-right-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>groove</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-right-style: groove; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays a border leading to a carved effect. It is the opposite of <code>ridge</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ridge</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: ridge; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays a border with a 3D effect, like if it is coming out of the page. It is the opposite of <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>inset</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: inset; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>Displays a border that makes the box appear embedded. It is the opposite of <code>outset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>outset</code></td>\\n    <td>\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-right-style: outset; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td>\\n     <p>Displays a border that makes the box appear in 3D, embossed. It is the opposite of <code>inset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>ridge</code>.</p>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the border style used by the parent of the current element.\"\n        }]\n    },\n    \"border-right-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\",\n        \"SUMMARY\": \"The <strong><code>border-right-width</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the width of the right border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;</code>\",\n            \"description\": \"Is either a non-negative explicit <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value or a keyword denoting the thickness of the right border. The keyword must be one of the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thin</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-right-style: solid; border-right-width: thin; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thin border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>medium</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-right-style: solid; border-right-width: medium; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A medium border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thick</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-right-style: solid; border-right-width: thick; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thick border</td>\\n   </tr>\\n  </tbody>\\n </table>\\n The specification doesn&apos;t define precisely the thickness of each fo the keywords, which is therefore implementation specific. Nevertheless, it requests that the thickness does follow the rule&#xA0;<code>thin &#x2264; medium &#x2264; thick</code>, and is constant on a single document.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the calculated value of the <code>border-right-width</code> of the parent&apos;s element.\"\n        }]\n    },\n    \"border-spacing\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-spacing\",\n        \"SUMMARY\": \"The <strong><code>border-spacing</code></strong> CSS property specifies the distance between the borders of adjacent table cells (only for the <a href=\\\"/en/CSS/border-collapse\\\" title=\\\"en/CSS/border-collapse\\\">separated borders model</a>). This is equivalent to the <code>cellspacing</code> attribute in presentational HTML, but an optional second value can be used to set different horizontal and vertical spacing.\",\n        \"VALUES\": [{\n            \"value\": \"<em>length</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value that describes both the horizontal and vertical spacings between cells. It is used only in the one-value syntax.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value that describes the horizontal spacing between cells, that is the space between cells in adjacent columns. It is used only in the two-value syntax.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value that describes the vertical spacing between cells, that is the space between cells in adjacent rows. It is used only in the two-value syntax.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that the calculated value of <code>border-spacing</code> of the parent&apos;s element must be used.\"\n        }]\n    },\n    \"border-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\",\n        \"SUMMARY\": \"The <strong><code>border-style</code></strong> property is a shorthand property for setting the line style for all four sides of the element´s border.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-style&gt;</code>\",\n            \"description\": \"Is a keyword describing the style of the bottom border. It can have the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>none</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Like for the <code>hidden</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>none</code> value has the lowest priority: it means that if any other conflicting border is set, it will be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>hidden</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: hidden; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Like for the <code>none</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>hidden</code> value has the highest priority: it means that if any other conflicting border is set, it won&apos;t be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>dotted</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: dotted; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a series of rounded dots. The spacing of the dots is not defined by the specification and is implementation-specific. The radius of the dots is half the calculated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>dashed</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: dashed; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a series of short square-ended dashes or line segments. The exact size and length of the segments are not defined by the specification and are implementation-specific.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>solid</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: solid; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a single, straight, solid line.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>double</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: double; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays two straight lines that add up to the pixel amount defined as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> .</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>groove</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: groove; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border leading to a carved effect. It is the opposite of <code>ridge</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>ridge</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: ridge; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border with a 3D effect, like if it is coming out of the page. It is the opposite of <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>inset</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: inset; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border that makes the box appear embedded. It is the opposite of <code>outset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>outset</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"border-width: 3px; border-style: outset; margin: 0.5em; width: 3em; height: 3em; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <p>Displays a border that makes the box appear in 3D, embossed. It is the opposite of <code>inset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>ridge</code>.</p>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"border-top\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top\",\n        \"SUMMARY\": \"The <strong><code>border-top</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand that sets the values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\" title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\"><code>border-top-color</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\\\" title=\\\"The border-top-style CSS property sets the line style of the top border of a box.\\\"><code>border-top-style</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>. These properties describe the top border of elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;br-style&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\\\" title=\\\"The border-top-style CSS property sets the line style of the top border of a box.\\\"><code>border-top-style</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;&#xA0;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\\\" title=\\\"The border-top-color CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties border-color or border-top are more convenient and preferable.\\\"><code>border-top-color</code></a>.\"\n        }]\n    },\n    \"border-top-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-color\",\n        \"SUMMARY\": \"The <strong><code>border-top-color</code></strong> CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties <a title=\\\"The border-color CSS property is a shorthand for setting the color of the four sides of an element's border: border-top-color, border-right-color, border-bottom-color, border-left-color\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\"><code>border-color</code></a> or <a title=\\\"The border-top CSS property is a shorthand that sets the values of border-top-color, border-top-style, and border-top-width. These properties describe the top border of elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top\\\"><code>border-top</code></a> are more convenient and preferable.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;<code>color&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> CSS value describing the color of the top border.\"\n        }, {\n            \"value\": \"inherit\",\n            \"description\": \"Is a keyword denoting the color of the top border of the parent&apos;s element (which may be different from the <code>border-top-color</code> default value)\"\n        }]\n    },\n    \"border-top-left-radius\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-left-radius\",\n        \"SUMMARY\": \"The <strong><code>border-top-left-radius</code></strong> CSS property sets the rounding of the top-left corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0,</code>no rounding is done and the corner is square.\",\n        \"VALUES\": [{\n            \"value\": \"<em>radius</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the radius of the circle to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the horizontal semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the vertical semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Denotes the size of the circle radius or the semi-major and semi-minor axes of the ellipsis. As absolute length it can be expressed in any unit allowed by the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> data type. Percentages for the horizontal axis refer to the width of the box, percentages for the vertical axis refer to the height of the box. Negative values are invalid.\"\n        }]\n    },\n    \"border-top-right-radius\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-right-radius\",\n        \"SUMMARY\": \"The <strong><code>border-top-right-radius</code></strong> CSS property sets the rounding of the top-right corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n        \"VALUES\": [{\n            \"value\": \"<em>radius</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the radius of the circle to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>horizontal</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the horizontal semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<em>vertical</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> denoting the vertical semi-major axis of the ellipsis to use for the border in that corner.\"\n        }, {\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Denotes the size of the circle radius or the semi-major and semi-minor axes of the ellipsis. As absolute length it can be expressed in any unit allowed by the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> data type. Percentages for the horizontal axis refer to the width of the box, percentages for the vertical axis refer to the height of the box. Negative values are invalid.\"\n        }]\n    },\n    \"border-top-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-style\",\n        \"SUMMARY\": \"The<strong> <code>border-top-style</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property sets the line style of the top border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-style&gt;</code>\",\n            \"description\": \"Is a keyword describing the style of the top border. It can have the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>none</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-top-style: none; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Like for the <code>hidden</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>none</code> value has the lowest priority: it means that if any other conflicting border is set, it will be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>hidden</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: hidden; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Like for the <code>none</code> keyword, displays no border. In that case, except if a background image is set, the calculated values of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a> will be <code>0</code>, even if specified otherwise through the property. In case of table cell and border collapsing, the <code>hidden</code> value has the highest priority: it means that if any other conflicting border is set, it won&apos;t be displayed.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>dotted</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: dotted; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a series of rounded dots. The spacing of the dots are not defined by the specification and are implementation-specific. The radius of the dots is half the calculated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>dashed</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: dashed; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a series of short square-ended dashes or line segments. The exact size and length of the segments are not defined by the specification and are implementation-specific.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>solid</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: solid; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a single, straight, solid line.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>double</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: double; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays two straight lines that add up to the pixel amount defined as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\" title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\"><code>border-top-width</code></a>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>groove</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: groove; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border leading to a carved effect. It is the opposite of <code>ridge</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>ridge</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: ridge; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border with a 3D effect, like if it is coming out of the page. It is the opposite of <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>inset</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: inset; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">Displays a border that makes the box appear embedded. It is the opposite of <code>outset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>groove</code>.</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>outset</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-width: 3px; border-top-style: outset; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <p>Displays a border that makes the box appear in 3D, embossed. It is the opposite of <code>inset</code>. When applied to a table cell with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse\\\" title=\\\"The border-collapse CSS property determines whether a table&apos;s borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.\\\"><code>border-collapse</code></a> set to <code>collapsed</code>, this value behaves like <code>ridge</code>.</p>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the border style used by the parent of the current element.\"\n        }]\n    },\n    \"border-top-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\",\n        \"SUMMARY\": \"The <strong><code>border-top-width</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property sets the width of the top border of a box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;</code>\",\n            \"description\": \"Is either a non-negative explicit <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value or a keyword denoting the thickness of the bottom border. The keyword must be one of the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thin</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-top-style: solid; border-top-width: thin; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thin border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>medium</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-top-style: solid; border-top-width: medium; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A medium border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thick</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-top-style: solid; border-top-width: thick; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thick border</td>\\n   </tr>\\n  </tbody>\\n </table>\\n The specification doesn&apos;t precisely define the thickness of each of the keywords, which is therefore implementation specific. Nevertheless, it requests that the thickness does follow the <code>thin &#x2264; medium &#x2264; thick</code> inequality and that the values are constant on a single document.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Represents the calculated value of the <code>border-top-width</code> of the parent&apos;s element.\"\n        }]\n    },\n    \"border-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\",\n        \"SUMMARY\": \"The <strong><code>border-width</code></strong> property is a shorthand property for setting <a title=\\\"The border-top-width CSS property sets the width of the top border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width\\\"><code>border-top-width</code></a>, <a title=\\\"The border-right-width CSS property sets the width of the right border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width\\\"><code>border-right-width</code></a>, <a title=\\\"The border-bottom-width CSS property sets the width of the bottom border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width\\\"><code>border-bottom-width</code></a> and <a title=\\\"The border-left-width CSS property sets the width of the left border of a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width\\\"><code>border-left-width</code></a> of a box at the same place.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;br-width&gt;</code>\",\n            \"description\": \"Is either a non-negative explicit <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value or a keyword denoting the thickness of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">border area</a> of a box. The keyword must be one of the following values:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thin</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-style: solid; border-width: thin; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thin border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>medium</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-style: solid; border-width: medium; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A medium border</td>\\n   </tr>\\n   <tr>\\n    <td style=\\\"vertical-align: middle;\\\"><code>thick</code></td>\\n    <td style=\\\"vertical-align: middle;\\\">\\n     <div style=\\\"margin: 0.5em; width: 3em; height: 3em; border-style: solid; border-width: thick; background-color: palegreen;\\\">&#xA0;</div>\\n    </td>\\n    <td style=\\\"vertical-align: middle;\\\">A thick border</td>\\n   </tr>\\n  </tbody>\\n </table>\\n The specification doesn&apos;t precisely define the thickness of each of the keywords, which is therefore implementation specific. Nevertheless, it requests that the thickness does follow the <code>thin &#x2264; medium &#x2264; thick</code> inequality and that the values are constant on a single document.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that all four values are inherited from their parent&apos;s element calculated value.\"\n        }]\n    },\n    \"bottom\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\",\n        \"SUMMARY\": \"The <strong><code>bottom</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property participates in specifying the position of <strong>positioned elements</strong>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"A negative, <code>null</code>, or positive <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> that represents:\\n <ul>\\n  <li>for <strong>absolutely positioned elements</strong>, the distance to the bottom edge of the containing block;</li>\\n  <li>for <strong>relatively positioned elements</strong>, the offset that the element is moved above its position in the normal flow if it wasn&apos;t positioned.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> of the containing block&apos;s height, used as described in the <a href=\\\"#Summary\\\">summary</a>.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Specifies that:\\n <ul>\\n  <li>for <strong>absolutely positioned elements</strong>, the position of the element is based on the <a title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\"><code>top</code></a> property, and <code>height: auto</code> is treated as a height based on the content.</li>\\n  <li>for <strong>relatively positioned elements</strong>, the offset the element from its original position is based on the <a title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\"><code>top</code></a> property, or if <code>top</code> is also <code>auto</code>, the element is not moved vertically at all.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Indicates that the value is the same as the computed value from its parent element (which may not be its containing block). This computed value is then handled as if it were a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a>, <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a>, or the <code>auto</code> keyword.\"\n        }]\n    },\n    \"box-align\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-align\",\n        \"SUMMARY\": \"The CSS <code>box-align</code> property specifies how an element aligns its contents across (perpendicular to) the direction of its layout. The effect of this is only visible if there is extra space in the box. See <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Flexbox\\\" title=\\\"CSS/Flexible_boxes\\\">Flexbox</a> for more about the properties of flexbox elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The box aligns contents at the start, leaving any extra space at the end.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The box aligns contents in the center, dividing any extra space equally between the start and the end.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The box aligns contents at the end, leaving any extra space at the start.\"\n        }, {\n            \"value\": \"<code>baseline</code>\",\n            \"description\": \"The box aligns the baselines of the contents (lining up the text). This only applies if the box&apos;s orientation is horizontal.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"The box stretches the contents so that there is no extra space in the box.\"\n        }]\n    },\n    \"box-decoration-break\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-decoration-break\",\n        \"SUMMARY\": \"The <strong><code>box-decoration-break</code></strong> CSS property specifies how the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background\\\" title=\\\"The background CSS property is a shorthand for setting the individual background values in a single place in the style sheet. background can be used to set the values for one or more of: background-clip, background-color, background-image, background-origin, background-position, background-repeat, background-size, and background-attachment.\\\"><code>background</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding\\\" title=\\\"The padding property sets the padding space on all sides of an element. The padding area is the space between the content of the element and its border. Negative values are not allowed.\\\"><code>padding</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border\\\" title=\\\"The border CSS property is a shorthand property for setting the individual border property values in a single place in the style sheet. border can be used to set the values for one or more of: border-width, border-style, border-color.\\\"><code>border</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image\\\" title=\\\"The border-image CSS property allows drawing an image on the borders of elements. This makes drawing complex looking widgets much simpler than it has been and removes the need for nine boxes in some cases. The border-image is used instead of the border styles given by the border-style properties. Though the specification requires that border-style must be present if border-image is used, some browsers many not implement this.\\\"><code>border-image</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow\\\" title=\\\"The box-shadow property describes one or more shadow effects as a comma-separated list.\\\"><code>box-shadow</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin\\\" title=\\\"The margin CSS property sets the margin for all four sides. It is a shorthand to avoid setting each side separately with the other margin properties: margin-top, margin-right, margin-bottom and margin-left.\\\"><code>margin</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/clip\\\" title=\\\"The clip CSS property defines what portion of an element is visible. The clip property applies only to absolutely positioned elements, that is elements with position:absolute or position:fixed.\\\"><code>clip</code></a> of an element is applied when the box for the element is fragmented.  Fragmentation occurs when an inline box wraps onto multiple lines, or when a block spans more than one column inside a column layout container, or spans a page break when printed.  Each piece of the rendering for the element is called a fragment.\",\n        \"VALUES\": [{\n            \"value\": \"<code>slice</code>\",\n            \"description\": \"The element is rendered as if its box were not fragmented, and then the rendering for this hypothetical box is sliced into pieces for each line/column/page. Note that the hypothetical box can be different for each fragment since it uses its own height if the break occurs in the inline direction, and its own width if the break occurs in the block direction. See the CSS specification for details.\"\n        }, {\n            \"value\": \"<code>clone</code>\",\n            \"description\": \"Each box fragment is rendered independently with the specified border, padding and margin wrapping each fragment. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius\\\" title=\\\"The border-radius CSS property allows Web authors to define how rounded border corners are. The curve of each corner is defined using one or two radii, defining its shape: circle or ellipse.\\\"><code>border-radius</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-image\\\" title=\\\"The border-image CSS property allows drawing an image on the borders of elements. This makes drawing complex looking widgets much simpler than it has been and removes the need for nine boxes in some cases. The border-image is used instead of the border styles given by the border-style properties. Though the specification requires that border-style must be present if border-image is used, some browsers many not implement this.\\\"><code>border-image</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow\\\" title=\\\"The box-shadow property describes one or more shadow effects as a comma-separated list.\\\"><code>box-shadow</code></a>, are applied to each fragment independently. The background is drawn independently in each fragment which means that a background image with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat\\\" title=\\\"The background-repeat CSS property defines how background images are repeated. A background image can be repeated along the horizontal axis, the vertical axis, both axes, or not repeated at all.\\\"><code>background-repeat</code></a>: <code>no-repeat</code> may be repeated multiple times.\"\n        }]\n    },\n    \"box-direction\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-direction\",\n        \"SUMMARY\": \"The CSS <code>box-direction</code> property specifies whether a box lays out its contents normally (from the top or left edge), or in reverse (from the bottom or right edge). See <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Flexbox\\\" title=\\\"CSS/Flexible_boxes\\\">Flexbox</a> for more about the properties of flexbox elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The box lays out its contents from the start (the left or top edge).\"\n        }, {\n            \"value\": \"<code>reverse</code>\",\n            \"description\": \"The box lays out its contents from the end (the right or bottom edge).\"\n        }]\n    },\n    \"box-flex\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex\",\n        \"SUMMARY\": \"The <code>-moz-box-flex</code> and <code>-webkit-box-flex</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> properties specify how a <code>-moz-box</code> or <code>-webkit-box</code> grows to fill the box that contains it, in the direction of the containing box's layout. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes\\\">Flexbox</a> for more about the properties of flexbox elements.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;number&gt;\",\n            \"description\": \"If the value is 0, the box does not grow. If it is greater than 0, the box grows to fill a proportion of the available space.\"\n        }]\n    },\n    \"box-flex-group\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex-group\",\n        \"SUMMARY\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes\\\">Flexbox</a> for more information.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"Any positive integer.\"\n        }]\n    },\n    \"box-lines\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-lines\",\n        \"SUMMARY\": \"See <a href=\\\"/en/CSS/Flexbox\\\">Flexbox</a> for more information.\",\n        \"VALUES\": [{\n            \"value\": \"single\",\n            \"description\": \"Box elements lay out in a single row or column.\"\n        }, {\n            \"value\": \"multiple\",\n            \"description\": \"Box elements layout in multiple rows or columns.\"\n        }]\n    },\n    \"box-ordinal-group\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-ordinal-group\",\n        \"SUMMARY\": \"The CSS <code>box-ordinal-group</code> property assigns the flexbox's child elements to an ordinal group. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes#Flexible_box_properties\\\">Flexbox</a> for more about the properties of flexbox elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"Any positive integer.\"\n        }]\n    },\n    \"box-orient\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-orient\",\n        \"SUMMARY\": \"The CSS <code>box-orient</code> property specifies whether an element lays out its contents horizontally or vertically. See <a href=\\\"/en/CSS/Flexible_boxes#box-_implementation\\\" rel=\\\"internal\\\" title=\\\"/en/CSS/Flexible_boxes#box-_implementation\\\">Flexbox</a> for more about the properties of flexbox elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>horizontal</code>\",\n            \"description\": \"The box lays out its contents horizontally.\"\n        }, {\n            \"value\": \"<code>vertical</code>\",\n            \"description\": \"The box lays out its contents vertically.\"\n        }, {\n            \"value\": \"<code>inline-axis</code> (HTML)\",\n            \"description\": \"The box displays its children along the inline axis.\"\n        }, {\n            \"value\": \"<code>block-axis</code> (HTML)\",\n            \"description\": \"The box displays its children along the block axis.\"\n        }]\n    },\n    \"box-pack\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-pack\",\n        \"SUMMARY\": \"The <code>-moz-box-pack</code> and <code>-webkit-box-pack</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> properties specify how a <code>-moz-box</code> or <code>-webkit-box</code> packs its contents in the direction of its layout. The effect of this is only visible if there is extra space in the box. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes#Flexible_box_properties\\\">Flexbox</a> for more about the properties of flexbox elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The box packs contents at the start, leaving any extra space at the end.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The box packs contents in the center, dividing any extra space equally between the start and the end.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The box packs contents at the end, leaving any extra space at the start.\"\n        }, {\n            \"value\": \"<code>justify</code>\",\n            \"description\": \"The space is divided evenly in-between each child, with none of the extra space placed before the first child or after the last child. If there is only one child, treat the value as if it were <code>start</code>.\"\n        }]\n    },\n    \"box-shadow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow\",\n        \"SUMMARY\": \"The <code>box-shadow</code> property describes one or more shadow effects as a comma-separated list.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"inset\\\" id=\\\"inset\\\"><code>inset</code></a>\",\n            \"description\": \"If not specified (default), the shadow is assumed to be a drop shadow (as if the box were raised above the content).<br>\\n The presence of the <code>inset</code> keyword changes the shadow to one inside the frame (as if the content was depressed inside the box). Inset shadows are drawn inside the border (even transparent ones), above the background, but below content.\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;offset-x&gt; &lt;offset-y&gt;\\\" id=\\\"&lt;offset-x&gt; &lt;offset-y&gt;\\\"><code>&lt;offset-x&gt;</code> <code>&lt;offset-y&gt;</code></a>\",\n            \"description\": \"These are two <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> values to set the shadow offset. <code>&lt;offset-x&gt;</code> specifies the horizontal distance. Negative values place the shadow to the left of the element. <code>&lt;offset-y&gt;</code> specifies the vertical distance. Negative values place the shadow above the element. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units.<br>\\n If both values are <code>0</code>, the shadow is placed behind the element (and may generate a blur effect if <code>&lt;blur-radius&gt;</code> and/or <code>&lt;spread-radius&gt;</code> is set).\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;blur-radius&gt;\\\" id=\\\"&lt;blur-radius&gt;\\\"><code>&lt;blur-radius&gt;</code></a>\",\n            \"description\": \"This is a third <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value. The larger this value, the bigger the blur, so the shadow becomes bigger and lighter. Negative values are not allowed. If not specified, it will be <code>0</code> (the shadow&apos;s edge is sharp). The specification does not include an exact algorithm for how the blur radius should be calculated, however, it does elaborate as follows:\"\n        }, {\n            \"value\": \"\\n <blockquote>&#x2026;for a long, straight shadow edge, this should create a color transition the length of the blur distance that is perpendicular to and centered on the shadow&#x2019;s edge, and that ranges from the full shadow color at the radius endpoint inside the shadow to fully transparent at the endpoint outside it.</blockquote>\\n \",\n            \"description\": \"<a name=\\\"&lt;spread-radius&gt;\\\" id=\\\"&lt;spread-radius&gt;\\\"><code>&lt;spread-radius&gt;</code></a>\"\n        }, {\n            \"value\": \"This is a fourth <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value. Positive values will cause the shadow to expand and grow bigger, negative values will cause the shadow to shrink. If not specified, it will be <code>0</code> (the shadow will be the same size as the element).\",\n            \"description\": \"<a name=\\\"&lt;color&gt;\\\" id=\\\"&lt;color&gt;\\\"><code>&lt;color&gt;</code></a>\"\n        }]\n    },\n    \"box-sizing\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing\",\n        \"SUMMARY\": \"The <strong><code>box-sizing</code></strong> property is used to alter the default <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">CSS box model</a> used to calculate width and height of the elements. It is possible to use this property to emulate the behavior of browsers that do not correctly support the CSS box model specification.\",\n        \"VALUES\": [{\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"This is the initial and default value as specified by the CSS standard. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> properties are measured including only the content, but not the padding, border or margin. Note: Padding, border &amp; margin will be outside of the box e.g. IF <code>.box {width: 350px;}</code>&#xA0;THEN you apply <code>{border: 10px solid black;}</code> RESULT {rendered in the browser} a&#xA0;<code>box of width: 370px.</code>\"\n        }, {\n            \"value\": \"So simply the dimension of element is calculated as, <em>width = width of the content</em>, and <em>height = height of the content (excluding the values of border and padding)</em>.\",\n            \"description\": \"<code>border-box</code>\"\n        }, {\n            \"value\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> properties include the content, the padding and border, but not the margin. This is the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">box model</a> used by Internet Explorer when the document is in Quirks mode.&#xA0;Note that padding and border will be inside of the box e.g.&#xA0; <code>.box {width: 350px; border: 10px solid black;}</code> leads to a box rendered in the browser of <code>width: 350px</code>. The content box can&apos;t be negative and is floored to 0, making it impossible to use border-box to make the element disappear.\",\n            \"description\": \"Here the dimension is calculated as, <em>width = border + padding + width of the content</em>, and <em>height = border + padding + height of the content</em>.\"\n        }, {\n            \"value\": \"<code>padding-box</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span> <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> properties include the content, the padding but neither the border, nor the margin. Only Firefox implemented this value, and it was&#xA0;removed in Firefox 50.\"\n        }]\n    },\n    \"box-suppress\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/box-suppress\",\n        \"SUMMARY\": \"The <code>box-suppress</code> CSS property controls the box generation of an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>show</code>\",\n            \"description\": \"The element generates boxes as normal, per its <code>display-*</code> properties.\"\n        }, {\n            \"value\": \"<code>discard</code>\",\n            \"description\": \"The element generates no boxes at all.\"\n        }, {\n            \"value\": \"<code>hide</code>\",\n            \"description\": \"The element generates boxes as normal, but those boxes do not participate in layout in any way, and must not be displayed.\"\n        }, {\n            \"value\": \"For the purpose of any layout-related information, such as querying for the computed value of the element&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> property, it must be treated as if it did not generate any boxes.\",\n            \"description\": \"Properties that rely on boxes but do not rely on layout, such as animations, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-increment\\\" title=\\\"The counter-increment CSS property is used to increase the value of CSS Counters by a given value. The counter&apos;s value can be reset using the counter-reset CSS property.\\\"><code>counter-increment</code></a>, etc., must work as normal on this element and its descendants.\"\n        }]\n    },\n    \"break-after\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/break-after\",\n        \"SUMMARY\": \"The <strong><code>break-after</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property describes the page, column, or region break behavior (in other words, how and whether to break) after the generated box. If there is no generated box, the property is ignored.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Initial value. Allows, meaning neither forbid nor force, any break (either page, column or region) to be&#xA0;inserted after the principal box.\"\n        }, {\n            \"value\": \"<code>always</code>\",\n            \"description\": \"Always force page breaks after the principal box. This is a synonym of <code>page</code>, it has been kept to facilitate transition from <a title=\\\"The page-break-after CSS property adjusts page breaks after the current element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-after\\\"><code>page-break-after</code></a> which is subset of this property.\"\n        }, {\n            \"value\": \"<code>avoid</code>\",\n            \"description\": \"Prevent any break, either page, column or region, to be inserted right after the principal box.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Force one or two page breaks right after the principal box so that the next page is formatted as a left page.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Force one or two page breaks right after the principal box so that the next page is formatted as a right page.\"\n        }, {\n            \"value\": \"<code>page</code>\",\n            \"description\": \"Always force one page break right after the principal box.\"\n        }, {\n            \"value\": \"<code>column</code>\",\n            \"description\": \"Always force one column break right after the principal box.\"\n        }, {\n            \"value\": \"<code>region </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Always force one region break right after the principal box.\"\n        }, {\n            \"value\": \"<code>recto</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Force one or two page breaks right after the principal box so that next page is formatted as a recto page, that is a right page in a left-to-right spread or a left page in a right-to-left spread.\"\n        }, {\n            \"value\": \"<code>verso </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Force one or two page breaks right after the principal box so that next page is formatted as a verso page, that is a left page in a left-to-right spread or a left right in a right-to-left spread.\"\n        }, {\n            \"value\": \"<code>avoid-page</code>\",\n            \"description\": \"Avoid any page break right after the principal box.\"\n        }, {\n            \"value\": \"<code>avoid-column</code>\",\n            \"description\": \"Avoid any column break right after the principal box.\"\n        }, {\n            \"value\": \"<code>avoid-region </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Avoid any region break right after the principal box.\"\n        }]\n    },\n    \"break-before\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/break-before\",\n        \"SUMMARY\": \"The<strong> <code>break-before</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property describes the page, column or region break behavior before the generated box. If there is no generated box, the property is ignored.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Initial value. Allows, meaning neither forbid nor force, any break (either page, column or region) to be be inserted before the principle box.\"\n        }, {\n            \"value\": \"<code>always</code>\",\n            \"description\": \"Always force page breaks before the principle box. This is a synonym of <code>page</code>, it has been kept to facilitate transition from <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-before\\\" title=\\\"The page-break-before CSS property adjusts page breaks before the current element.\\\"><code>page-break-before</code></a> which is subset of this property.\"\n        }, {\n            \"value\": \"<code>avoid</code>\",\n            \"description\": \"Prevent any break, either page, column or region, to be inserted right before the principle box.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Force one or two page breaks right before the principle box so that the next page is formatted as a left page.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Force one or two page breaks right before the principle box so that the next page is formatted as a right page.\"\n        }, {\n            \"value\": \"<code>page</code>\",\n            \"description\": \"Always force one page break right before the principle box.\"\n        }, {\n            \"value\": \"<code>column</code>\",\n            \"description\": \"Always force one column break right before the principle box.\"\n        }, {\n            \"value\": \"<code>region </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Always force one region break right before the principle box.\"\n        }, {\n            \"value\": \"<code>recto</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Force one or two page breaks right before the principle box so that next page is formatted as a recto page, that is a right page in a left-to-right spread or a left page in a right-to-left spread.\"\n        }, {\n            \"value\": \"<code>verso </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Force one or two page breaks right before the principle box so that next page is formatted as a verso page, that is a left page in a left-to-right spread or a right page in a right-to-left spread.\"\n        }, {\n            \"value\": \"<code>avoid-page</code>\",\n            \"description\": \"Avoid any page break right before the principle box.\"\n        }, {\n            \"value\": \"<code>avoid-column</code>\",\n            \"description\": \"Avoid any column break right before the principle box.\"\n        }, {\n            \"value\": \"<code>avoid-region </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Avoid any region break right before the principle box.\"\n        }]\n    },\n    \"break-inside\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside\",\n        \"SUMMARY\": \"The <strong><code>break-inside</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property describes how the page, column or region break inside the generated box. If there is no generated box, the property is ignored.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Allows, meaning neither forbid nor force, any break (either page, column or region) to be be inserted within the principle box.\"\n        }, {\n            \"value\": \"<code>avoid-page</code>\",\n            \"description\": \"Avoid any page break within the principle box.\"\n        }, {\n            \"value\": \"<code>avoid-column</code>\",\n            \"description\": \"Avoid any column break within the principle box.\"\n        }, {\n            \"value\": \"<code>avoid-region </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Avoid any region break within the principle box.\"\n        }]\n    },\n    \"calc()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/calc\",\n        \"SUMMARY\": \"The <code>calc()</code> CSS function can be used anywhere a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/frequency\\\" title=\\\"The &lt;frequency&gt; CSS data type denotes a frequency dimension, like the pitch of a speaking voice.\\\"><code>&lt;frequency&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. Positive angles represent clockwise angles, negative angles represent counterclockwise angles. Its syntax is a &lt;number&gt; data type immediately followed by the unit (deg, grad, rad or turn). Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;angle&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a '.' followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn't any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn't any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> is required. With <code>calc()</code>, you can perform calculations to determine CSS property values.\",\n        \"VALUES\": [{\n            \"value\": \"expression\",\n            \"description\": \"A mathematical expression, the result of which is used as the value.\"\n        }, {\n            \"value\": \"<strong>+</strong>\",\n            \"description\": \"Addition.\"\n        }, {\n            \"value\": \"<strong>-</strong>\",\n            \"description\": \"Subtraction.\"\n        }, {\n            \"value\": \"<strong>*</strong>\",\n            \"description\": \"Multiplication. At least one of the arguments must be a <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a>.\"\n        }, {\n            \"value\": \"<strong>/</strong>\",\n            \"description\": \"Division. The right-hand side must be a <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a>.\"\n        }]\n    },\n    \"caption-side\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/caption-side\",\n        \"SUMMARY\": \"The <strong><code>caption-side</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property positions the content of a table's <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption\\\" title=\\\"The HTML &lt;caption&gt; element represents the title of a table. Though it is always the first descendant of a &lt;table&gt;, its styling, using CSS, may place it elsewhere, relative to the table.\\\"><code>&lt;caption&gt;</code></a> on the specified side.\",\n        \"VALUES\": [{\n            \"value\": \"<code>top</code>\",\n            \"description\": \"Is a keyword indicating that the caption box should be positioned above the table.\"\n        }, {\n            \"value\": \"<code>bottom</code>\",\n            \"description\": \"Is a keyword indicating that the caption box should be positioned below the table.\"\n        }, {\n            \"value\": \"<code>left</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the caption box should be positioned on the left side of the table.<br>\\n <div class=\\\"note\\\"><strong>Note:</strong>&#xA0;This value was proposed for CSS 2, but removed from the final CSS 2.1 specification. It is non-standard.</div>\"\n        }, {\n            \"value\": \"<code>right</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the caption box should be positioned on the right side of the table.<br>\\n <div class=\\\"note\\\"><strong>Note:</strong>&#xA0;This value was proposed for CSS 2, but removed from the final CSS 2.1 specification. It is non-standard.</div>\"\n        }, {\n            \"value\": \"<code>top-outside</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the caption box should be positioned above the table, while the width and horizontal alignment behavior are not bound to the table&apos;s horizontal layout.<br>\\n <div class=\\\"note\\\"><strong>Note:</strong>&#xA0;The CSS 2.1 specification notes that the CSS 2 specification described a different behavior for the <code>top</code> value, which will be reintroduced by this value in a future specification.</div>\"\n        }, {\n            \"value\": \"<code>bottom-outside</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the caption box should be positioned below the table, while the width and horizontal alignment behavior are not bound to the table&apos;s horizontal layout.<br>\\n <div class=\\\"note\\\"><strong>Note:</strong>&#xA0;The CSS 2.1 specification notes that the CSS 2 specification described a different behavior for the <code>bottom</code> value, which will be reintroduced by this value in a future specification.</div>\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that the <code>caption-side</code> value defined on the parent&apos;s element must be used.\"\n        }]\n    },\n    \"caret-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/caret-color\",\n        \"SUMMARY\": \"The <strong><code>caret-color</code></strong> CSS property specifies the color of the caret, the visible indicator of the insertion point in an element where text and other content is inserted by the user's typing or editing.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"User agents should use <code>currentcolor</code> but may automatically adjust the color of the caret to ensure good visibility and contrast with the surrounding content, possibly based on <code>currentcolor</code>, the background, shadows, etc.\\n\\t<div class=\\\"note\\\"><strong>Note:</strong> While user agents may use <code>currentcolor</code> for the <code>auto</code> value, in opposite to the <code>currentcolor</code> value, <code>auto</code> is not interpolated on transitions/animations.</div>\\n\\t\"\n        }, {\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Use the specified color as the caret color.\"\n        }]\n    },\n    \"clear\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/clear\",\n        \"SUMMARY\": \"The <strong><code>clear</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies whether an element can be next to <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/float\\\" title=\\\"CSS/float\\\">floating</a> elements that precede it or must be moved down (cleared) below them. The <code>clear</code> property applies to both floating and non-floating elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword indicating that the element is <em>not</em> moved down to clear past floating elements.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Is a keyword indicating that the element is moved down to clear past <em>left</em> floats.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Is a keyword indicating that the element is moved down to clear past <em>right</em> floats.\"\n        }, {\n            \"value\": \"<code>both</code>\",\n            \"description\": \"Is a keyword indicating that the element is moved down to clear past <em>both</em> left and right floats.\"\n        }, {\n            \"value\": \"<code>inline-start</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the element is moved down to clear floats on <em>start side of its containing block</em>, that is the <em>left</em> floats on ltr scripts and the <em>right</em> floats on rtl scripts.\"\n        }, {\n            \"value\": \"<code>inline-end</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the element is moved down to clear floats on <em>end side of its containing block</em>, that is the <em>right</em> floats on ltr scripts and the <em>left</em> floats on rtl scripts.\"\n        }]\n    },\n    \"clip\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/clip\",\n        \"SUMMARY\": \"The <strong><code>clip</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines what portion of an element is visible. The <code>clip</code> property applies only to absolutely positioned elements, that is elements with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>position:absolute</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>position:fixed</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;shape&gt;</code>\",\n            \"description\": \"A rectangular <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/shape\\\" title=\\\"The &lt;shape&gt; CSS data type denotes the specific form of a region. This region is used to define on which part of an element some properties like clip do apply.\\\"><code>&lt;shape&gt;</code></a> of the form <code>rect(&lt;top&gt;, &lt;right&gt;, &lt;bottom&gt;, &lt;left&gt;)</code> or of the form <code>rect(&lt;top&gt; &lt;right&gt; &lt;bottom&gt; &lt;left&gt;)</code> (which is a more backwards compatible syntax) <code>&lt;top&gt;</code> and <code>&lt;bottom&gt;</code> specify offsets from the <em>inside top border edge</em> of the box, and <code>&lt;right&gt;</code>, and <code>&lt;left&gt;</code> specify offsets from the <em>inside left border edge</em> of the box &#x2014; that is, the extent of the padding box.\"\n        }, {\n            \"value\": \"<code>&lt;top&gt;</code>, <code>&lt;right&gt;</code>, <code>&lt;bottom&gt;</code>, and <code>&lt;left&gt;</code> may either have a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value or<code> auto</code>. If any side&apos;s value is <code>auto</code>, the element is clipped to that side&apos;s <em>inside border edge</em>.\",\n            \"description\": \"<code>auto</code>\"\n        }]\n    },\n    \"clip-path\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path\",\n        \"SUMMARY\": \"The <code><strong>clip-path</strong></code> CSS property prevents a portion of an element from getting displayed by defining a clipping region to be displayed i.e, only a specific region of the element is displayed. The clipping region is a path specified as a URL referencing an inline or external SVG, or shape method such as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle\\\">circle()</a>. The clip-path property replaces the now deprecated <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/clip\\\">clip</a> property.\",\n        \"VALUES\": [{\n            \"value\": \"<code>url()</code>\",\n            \"description\": \"Represents a URL referencing a clip path element.\"\n        }, {\n            \"value\": \"<code>inset()</code>, <code>circle()</code>, <code>ellipse()</code>, <code>polygon()</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape\\\" title=\\\"The &lt;basic-shape&gt;&#xA0;type can be specified using basic shape functions. When using this syntax to define shapes, the reference box is defined by each property that uses &lt;basic-shape&gt; values. The coordinate system for the shape has its origin on the top-left corner of the reference box with the x-axis running to the right and the y-axis running downwards. All the lengths expressed in percentages are resolved from the used dimensions of the reference box.\\\"><code>&lt;basic-shape&gt;</code></a> function. Such a shape will make use of the specified <code>&lt;geometry-box&gt;</code> to size and position the basic shape. If no geometry box is specified, the <code>border-box</code> will be used as reference box.\"\n        }, {\n            \"value\": \"<code>&lt;geometry-box&gt;</code>\",\n            \"description\": \"If specified in combination with a <code>&lt;basic-shape&gt;</code>, it provides the reference box for the basic shape. If specified by itself, it uses the edges of the specified box including any corner shaping (e.g. defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius\\\" title=\\\"The border-radius CSS property allows Web authors to define how rounded border corners are. The curve of each corner is defined using one or two radii, defining its shape: circle or ellipse.\\\"><code>border-radius</code></a>) as clipping path. The geometry box can be one of the following values:\\n <dl>\\n  <dt><code>fill-box</code></dt>\\n  <dd>Uses the object bounding box as reference box.</dd>\\n  <dt><code>stroke-box</code></dt>\\n  <dd>Uses the stroke bounding box as reference box.</dd>\\n  <dt><code>view-box</code></dt>\\n  <dd>Uses the nearest SVG viewport as reference box. If a <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox\\\">viewBox</a></code> attribute is specified for the element creating the SVG viewport, the reference box is positioned at the origin of the coordinate system established by the <code>viewBox</code> attribute and the dimension of the reference box is set to the width and height values of the <code>viewBox</code> attribute.</dd>\\n  <dt><code>margin-box</code></dt>\\n  <dd>Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">margin box</a> as the reference box.</dd>\\n  <dt><code>border-box</code></dt>\\n  <dd>Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">border box</a> as the reference box.</dd>\\n  <dt><code>padding-box</code></dt>\\n  <dd>Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">padding box</a> as the reference box.</dd>\\n  <dt><code>content-box</code></dt>\\n  <dd>Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">content box</a> as the reference box.</dd>\\n </dl>\\n \"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"There is no clipping path created.\"\n        }, {\n            \"value\": \"<code>fill-box</code>\",\n            \"description\": \"Uses the object bounding box as reference box.\"\n        }, {\n            \"value\": \"<code>stroke-box</code>\",\n            \"description\": \"Uses the stroke bounding box as reference box.\"\n        }, {\n            \"value\": \"<code>view-box</code>\",\n            \"description\": \"Uses the nearest SVG viewport as reference box. If a <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox\\\">viewBox</a></code> attribute is specified for the element creating the SVG viewport, the reference box is positioned at the origin of the coordinate system established by the <code>viewBox</code> attribute and the dimension of the reference box is set to the width and height values of the <code>viewBox</code> attribute.\"\n        }, {\n            \"value\": \"<code>margin-box</code>\",\n            \"description\": \"Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">margin box</a> as the reference box.\"\n        }, {\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">border box</a> as the reference box.\"\n        }, {\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">padding box</a> as the reference box.\"\n        }, {\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"Uses the <a href=\\\"CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">content box</a> as the reference box.\"\n        }]\n    },\n    \"color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/color\",\n        \"SUMMARY\": \"The <strong><code>color</code></strong> property sets the foreground <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\">color</a> of an element's text content, and its <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration\\\">decorations</a>. It also sets the <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/currentColor\\\"><code>&lt;currentcolor&gt;</code></a> value which may be used as an indirect value on <em>other</em> properties, and is the default for other color properties, such as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-color\\\">border-color</a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> value giving the color of the textual elements of the element.\"\n        }]\n    },\n    \"column-count\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-count\",\n        \"SUMMARY\": \"The <strong><code>column-count</code></strong> CSS property describes the number of columns of the element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the number of columns should be determined by other CSS properties, like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-width\\\" title=\\\"The column-width CSS property suggests an optimal column width. The column-width is the maximum width a column will become before adding another column. For instance, a 300px column width a gap of 0px would be a single column at 599px, but at 600px it would be split into 2 columns.&#xA0;This allows us&#xA0;to achieve scalable designs that fit different screen sizes. Especially in presence of the column-count CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are width, column-width, column-gap, and column-rule-width.\\\"><code>column-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"Is a strictly positive <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> describing the ideal number of columns into which the content of the element will be flowed. If the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-width\\\" title=\\\"The column-width CSS property suggests an optimal column width. The column-width is the maximum width a column will become before adding another column. For instance, a 300px column width a gap of 0px would be a single column at 599px, but at 600px it would be split into 2 columns.&#xA0;This allows us&#xA0;to achieve scalable designs that fit different screen sizes. Especially in presence of the column-count CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are width, column-width, column-gap, and column-rule-width.\\\"><code>column-width</code></a> is also set to a non-<strong>auto</strong> value, it merely indicates the maximum allowed number of columns.\"\n        }]\n    },\n    \"column-fill\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-fill\",\n        \"SUMMARY\": \"The <strong><code>column-fill</code></strong> CSS property controls how contents are partitioned into columns. Contents are either balanced, which means that contents in all columns will have the same height or, when using <code>auto</code>, just take up the room the content needs.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that columns are filled sequentially.\"\n        }, {\n            \"value\": \"<code>balance</code>\",\n            \"description\": \"Is a keyword indicating that content is equally divided between columns.\"\n        }]\n    },\n    \"column-gap\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap\",\n        \"SUMMARY\": \"The <strong><code>column-gap</code></strong> CSS property sets the size of the gap between columns for elements which are specified to be displayed as multi-column elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Is a keyword indicating to use the browser-defined default spacing between columns. The specification, which most modern browsers follow, recommends that this&#xA0;be equal to a length of <code>1em</code>.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value defining the size of the gap between columns. It must not be negative, but may be equal to <code>0</code>.\"\n        }]\n    },\n    \"column-rule\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule\",\n        \"SUMMARY\": \"In multi-column layouts, the <strong><code>column-rule</code></strong> CSS property specifies a straight line, or \\\"rule\\\", to be drawn between each column. It is a convenient shorthand to avoid setting each of the individual <code>column-rule-*</code> properties separately: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-width\\\" title=\\\"The column-rule-width CSS property lets you set the width of the rule drawn between columns in multi-column layouts.\\\"><code>column-rule-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-style\\\" title=\\\"The column-rule-style CSS property lets you set the style of the rule drawn between columns in multi-column layouts.\\\"><code>column-rule-style</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-color\\\" title=\\\"The column-rule-color CSS property lets you set the color of the &quot;rule&quot; or line drawn between columns in multi-column layouts.\\\"><code>column-rule-color</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;column-rule-width&apos;&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or one of the three keywords, <code>thin</code>, <code>medium</code>, or <code>thick</code>. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-width\\\" title=\\\"The border-width property is a shorthand property for setting border-top-width,&#xA0;border-right-width,&#xA0;border-bottom-width and&#xA0;border-left-width&#xA0;of a box at the same place.\\\"><code>border-width</code></a> for details.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;column-rule-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a> for possible values and details.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;column-rule-color&apos;&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> value.\"\n        }]\n    },\n    \"column-rule-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-color\",\n        \"SUMMARY\": \"The<strong> <code>column-rule-color</code></strong> CSS property lets you set the color of the \\\"rule\\\" or line drawn between columns in multi-column layouts.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> value representing the color of the rule separating columns.\"\n        }]\n    },\n    \"column-rule-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-style\",\n        \"SUMMARY\": \"The <strong><code>column-rule-style</code></strong> CSS property lets you set the style of the rule drawn between columns in multi-column layouts.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;br-style&gt;&#xA0;\",\n            \"description\": \"Is a keyword defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-style\\\" title=\\\"The border-style property is a shorthand property for setting the line style for all four sides of the element&#xB4;s border.\\\"><code>border-style</code></a> describing the style of the rule. The styling must be interpreted as in the collapsing border model.\"\n        }]\n    },\n    \"column-rule-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-width\",\n        \"SUMMARY\": \"The <strong><code>column-rule-width</code></strong> CSS property lets you set the width of the rule drawn between columns in multi-column layouts.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;br-width&gt;&#xA0;\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or one of the <code>thin</code>, <code>medium</code> or <code>thick</code> keyword describing the width of the rule separating two columns.\"\n        }]\n    },\n    \"column-span\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-span\",\n        \"SUMMARY\": \"The <strong><code>column-span</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property makes it possible for an element to span across all columns when its value is set to <code>all</code>. An element that spans more than one column is called a <strong>spanning element</strong>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The element does not span multiple columns.\"\n        }, {\n            \"value\": \"<code>all</code>\",\n            \"description\": \"The element spans across all columns. Content in the normal flow that appears before the element is automatically balanced across all columns before the element appears. The element establishes a new block formatting context.\"\n        }]\n    },\n    \"column-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/column-width\",\n        \"SUMMARY\": \"The <strong><code>column-width</code></strong> CSS property suggests an optimal column width. The column-width is the maximum width a column will become before adding another column. For instance, a 300px column width a gap of 0px would be a single column at 599px, but at 600px it would be split into 2 columns. This allows us to achieve scalable designs that fit different screen sizes. Especially in presence of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-count\\\" title=\\\"The column-count CSS property describes the number of columns of the element.\\\"><code>column-count</code></a> CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-width\\\" title=\\\"The column-width CSS property suggests an optimal column width. The column-width is the maximum width a column will become before adding another column. For instance, a 300px column width a gap of 0px would be a single column at 599px, but at 600px it would be split into 2 columns.&#xA0;This allows us&#xA0;to achieve scalable designs that fit different screen sizes. Especially in presence of the column-count CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are width, column-width, column-gap, and column-rule-width.\\\"><code>column-width</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap\\\" title=\\\"The column-gap CSS property sets the size of the gap between columns for elements which are specified to be displayed as multi-column elements.\\\"><code>column-gap</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-width\\\" title=\\\"The column-rule-width CSS property lets you set the width of the rule drawn between columns in multi-column layouts.\\\"><code>column-rule-width</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value giving a hint of the optimal width of the column. The actual column width may be wider (to fill the available space), or narrower (only if the available space is smaller than the specified column width). The length must be strictly positive or the declaration is invalid.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the width of the column should be determined by other CSS properties, like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-count\\\" title=\\\"The column-count CSS property describes the number of columns of the element.\\\"><code>column-count</code></a>.\"\n        }]\n    },\n    \"columns\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/columns\",\n        \"SUMMARY\": \"The <strong><code>columns</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property is a shorthand property allowing to set both the <a title=\\\"The column-width CSS property suggests an optimal column width. The column-width is the maximum width a column will become before adding another column. For instance, a 300px column width a gap of 0px would be a single column at 599px, but at 600px it would be split into 2 columns.&#xA0;This allows us&#xA0;to achieve scalable designs that fit different screen sizes. Especially in presence of the column-count CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are width, column-width, column-gap, and column-rule-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-width\\\"><code>column-width</code></a> and the <a title=\\\"The column-count CSS property describes the number of columns of the element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-count\\\"><code>column-count</code></a> properties at the same time.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;column-width&apos;&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> value giving a hint of the optimal width of the column. The actual column width may be wider (to fill the available space), or narrower (only if the available space is smaller than the specified column width). The length must be strictly positive or the declaration is invalid.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;column-count&apos;&gt;</code>\",\n            \"description\": \"Is a strictly positive <a title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\"><code>&lt;integer&gt;</code></a> describing the ideal number of columns into which the content of the element will be flowed. If the <a title=\\\"The column-width CSS property suggests an optimal column width. The column-width is the maximum width a column will become before adding another column. For instance, a 300px column width a gap of 0px would be a single column at 599px, but at 600px it would be split into 2 columns.&#xA0;This allows us&#xA0;to achieve scalable designs that fit different screen sizes. Especially in presence of the column-count CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are width, column-width, column-gap, and column-rule-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/column-width\\\"><code>column-width</code></a> is also set to a non-<strong>auto</strong> value, it merely indicates the maximum allowed number of columns.\"\n        }]\n    },\n    \"contain\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/contain\",\n        \"SUMMARY\": \"The <strong><code>contain</code></strong> property allows an author to indicate that an element and its contents are, as much as possible, <em>independent</em> of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page. This property is useful on pages that contain a lot of widgets that are all independent as it can be used to prevent one widget's CSS rules from changing other things on the page.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Indicates the&#xA0;element renders as normal, with no containment applied.\"\n        }, {\n            \"value\": \"strict\",\n            \"description\": \"Indicates that all containment rules are applied to the element. This is equivalent to <code>contain: size layout style paint</code>.\"\n        }, {\n            \"value\": \"content\",\n            \"description\": \"Indicates that all containment rules except size are applied to the element. This is equivalent to <code>contain: layout style paint</code>.\"\n        }, {\n            \"value\": \"size\",\n            \"description\": \"Indicates that the element can be sized without the need to examine its dependants for size changes.\"\n        }, {\n            \"value\": \"layout\",\n            \"description\": \"Indicates that nothing outside the element may affect its internal layout and vice versa.&#xA0;\"\n        }, {\n            \"value\": \"style\",\n            \"description\": \"Indicates that, for properties that can have effects on more than just an element and its descendants, those effects don&apos;t escape the containing element.\"\n        }, {\n            \"value\": \"paint\",\n            \"description\": \"Indicates that descendents of the element don&apos;t display outside its bounds. If an element is off-screen or otherwise not visible, it&apos;s descendants are also guaranteed to not be visible.\"\n        }]\n    },\n    \"content\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/content\",\n        \"SUMMARY\": \"The <strong><code>content</code></strong> CSS property is used with the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::before\\\" title=\\\"::before creates a pseudo-element that is the first child of the element matched. It is often used to add cosmetic content to an element by using the content property. This element is inline by default.\\\"><code>::before</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/::after\\\" title=\\\"The CSS ::after pseudo-element matches a virtual last child of the selected element. It is typically used to add cosmetic content to an element by using the content CSS property. This element is inline by default.\\\"><code>::after</code></a> pseudo-elements to generate content in an element. Objects inserted using the <code>content</code> property are <em>anonymous <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Replaced_element\\\" title=\\\"CSS/Replaced_element\\\">replaced elements</a>.</em>\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The pseudo-element is not generated.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Computes to <code>none</code> for the <code>:before</code> and <code>:after</code> pseudo-elements.\"\n        }, {\n            \"value\": \"<code>&lt;string&gt;</code>\",\n            \"description\": \"Text content.\"\n        }, {\n            \"value\": \"<code>&lt;uri&gt;</code> or <code>url()</code>\",\n            \"description\": \"The value is a URI that designates an external resource (such as an image). If the resource or image can&apos;t be displayed, it is either ignored or some placeholder shows up.\"\n        }, {\n            \"value\": \"<code>counter()</code>&#xA0;or <code>counters()</code>\",\n            \"description\": \"Counters may be specified with two different functions: &apos;counter()&apos; or &apos;counters()&apos;. The former has two forms: &apos;counter(<var>name</var>)&apos; or &apos;counter(<var>name</var>, <var>style</var>)&apos;. The generated text is the value of the innermost counter of the given name in scope at this pseudo-element; it is formatted in the indicated style (&apos;decimal&apos; by default). The latter function also has two forms: &apos;counters(<var>name</var>, <var>string</var>)&apos; or &apos;counters(<var>name</var>, <var>string</var>, <var>style</var>)&apos;. The generated text is the value of all counters with the given name in scope at this pseudo-element, from outermost to innermost separated by the specified string. The counters are rendered in the indicated style (&apos;decimal&apos; by default). See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter\\\">section on automatic counters and numbering</a> for more information. The name must not be &apos;none&apos;, &apos;inherit&apos; or &apos;initial&apos;. Such a name causes the declaration to be ignored.\"\n        }, {\n            \"value\": \"<code>attr(X)</code>\",\n            \"description\": \"Returns the value of the element&apos;s attribute X as a string. If there is no attribute X, an empty string is returned. The case-sensitivity of attribute names depends on the document language.\"\n        }, {\n            \"value\": \"<code>open-quote</code> | <code>close-quote</code>\",\n            \"description\": \"These values are replaced by the appropriate string from the <a title=\\\"The quotes CSS property indicates how user agents should render quotation marks.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/quotes\\\"><code>quotes</code></a> property.\"\n        }, {\n            \"value\": \"<code>no-open-quote</code> | <code>no-close-quote</code>\",\n            \"description\": \"Introduces no content, but increments (decrements) the level of nesting for quotes.\"\n        }]\n    },\n    \"counter-increment\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-increment\",\n        \"SUMMARY\": \"The <strong><code>counter-increment</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property is used to increase the value of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters\\\">CSS Counters</a> by a given value. The counter's value can be reset using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-reset\\\" title=\\\"The counter-reset CSS property is used to reset CSS Counters to a given value.\\\"><code>counter-reset</code></a> CSS property.\",\n        \"VALUES\": [{\n            \"value\": \"<a title=\\\"The &lt;custom-ident&gt; CSS data value denotes an arbitrary user-defined string used as an identifier. It is case-sensitive and in each context, several values are excluded to prevent misinterpretations.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\"><code>&lt;custom-ident&gt;</code></a>\",\n            \"description\": \"The name of the counter to increment. This identifier is composed by a combination of case-insensitive letters <code>a</code>&#xA0;to&#xA0;<code>z</code>, numbers <code>0</code>&#xA0;to&#xA0;<code>9</code>, underscores (<code>_</code>), and/or dashes (<code>-</code>). The first non-dash character must be a letter (that is, no number at the beginning of it, even if preceded by a dash.) Also, two dashes are forbidden at the beginning of the identifier. It can&apos;t be <code>none</code>, <code>unset</code>, <code>initial</code>, or <code>inherit</code> in any combination of cases.\"\n        }, {\n            \"value\": \"<a title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\"><code>&lt;integer&gt;</code></a>\",\n            \"description\": \"The value to add to the counter. Defaults to 1 if not given.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No counter must be incremented. This is used as the default value, or to cancel an increment in more specific rules.\"\n        }]\n    },\n    \"counter-reset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/counter-reset\",\n        \"SUMMARY\": \"The <strong><code>counter-reset</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property is used to reset <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Counters\\\">CSS Counters</a> to a given value.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;custom-ident&gt;</code></a>\",\n            \"description\": \"The name of the counter to increment. This identifier is composed by a combination of case-insensitive letters <code>a</code> to <code>z</code>, numbers <code>0</code> to <code>9</code>, underscores (<code>_</code>), and/or dashes (<code>-</code>). The first non-dash character must be a letter (that is, no number at the beginning of it, even if preceded by a dash.) Also, two dashes are forbidden at the beginning of the identifier. It can&apos;t be <code>none</code>, <code>unset</code>, <code>initial</code>, or <code>inherit</code> in any combination of cases.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a>\",\n            \"description\": \"The value to reset the counter to on each occurrence of the element. Defaults to <code>0</code> if not given.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword indicating that no counter reset is to be performed. It can be used to hide <code>counter-reset</code> defined in less specific rules.\"\n        }]\n    },\n    \"cursor\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\",\n        \"SUMMARY\": \"The <strong><code>cursor</code></strong> CSS property specifies the mouse cursor displayed when the mouse pointer is over an element.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"&lt;uri&gt;\\\" id=\\\"&lt;uri&gt;\\\">&lt;<code>uri</code>&gt;</a>\",\n            \"description\": \"A <code>url(&#x2026;)</code> or a comma separated list <code>url(&#x2026;), url(&#x2026;), &#x2026;</code>, pointing to an image file. More than one <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/uri\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;uri&gt;</code></a> may be provided as fallback, in case some cursor image types are not supported. A non-URL fallback (one or more of the other values) <strong>must</strong> be at the end of the fallback list. See <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Using_URL_values_for_the_cursor_property\\\" title=\\\"Using_URL_values_for_the_cursor_property\\\">Using URL values for the cursor property</a> for more details.\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;x&gt; &lt;y&gt;\\\"><code>&lt;x&gt;</code> <code>&lt;y&gt;</code> </a><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Optional x- and y-coordinates. Two unit-less non-negative numbers less than 32.\"\n        }, {\n            \"value\": \"<a name=\\\"Keyword values\\\" id=\\\"Keyword values\\\">Keyword values</a>\",\n            \"description\": \"\\n <p><strong style=\\\"color: red; font-size: big;\\\">Move mouse over value for testing:</strong></p>\\n\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <th>Category</th>\\n    <th style=\\\"width: 7.5em;\\\">CSS value</th>\\n   <th>Description</th>\\n   </tr>\\n   <tr style=\\\"cursor: auto;\\\">\\n    <td rowspan=\\\"3\\\">General</td>\\n    <td><code>auto</code></td>\\n    <td>The browser determines the cursor to display based on the current context.<br>\\n     E.g. equivalent to <code>text</code> when hovering text.</td>\\n   </tr>\\n   <tr style=\\\"cursor: default;\\\">\\n    <td><code>default</code></td>\\n    <td>Default cursor, typically an arrow.</td>\\n   </tr>\\n   <tr style=\\\"cursor: none;\\\">\\n    <td><code>none</code></td>\\n    <td>No cursor is rendered.</td>\\n   </tr>\\n   <tr style=\\\"cursor: context-menu;\\\">\\n    <td rowspan=\\\"5\\\" style=\\\"cursor: auto;\\\">Links &amp; status</td>\\n    <td><code>context-menu</code></td>\\n    <td>A context menu is available under the cursor.<br>\\n     Only IE 10 and up have implemented this on Windows: <a href=\\\"https://bugzilla.mozilla.org/show_bug.cgi?id=258960\\\" class=\\\"external\\\" title=\\\"&apos;context-menu&apos; cursor glyph missing for Windows\\\">bug&#xA0;258960</a>.</td>\\n   </tr>\\n   <tr style=\\\"cursor: help;\\\">\\n    <td><code>help</code></td>\\n    <td>Indicating help is available.</td>\\n   </tr>\\n   <tr style=\\\"cursor: pointer;\\\">\\n    <td><code>pointer</code></td>\\n    <td>E.g. used when hovering over links, typically a hand.</td>\\n   </tr>\\n   <tr style=\\\"cursor: progress;\\\">\\n    <td><code>progress</code></td>\\n    <td>The program is busy in the background but the user can still interact with the interface (unlike for <code>wait</code>).</td>\\n   </tr>\\n   <tr style=\\\"cursor: wait;\\\">\\n    <td><code>wait</code></td>\\n    <td>The program is busy (sometimes an hourglass or a watch).</td>\\n   </tr>\\n   <tr style=\\\"cursor: cell;\\\">\\n    <td rowspan=\\\"4\\\" style=\\\"cursor: auto;\\\">Selection</td>\\n    <td><code>cell</code></td>\\n    <td>Indicating that cells can be selected.</td>\\n   </tr>\\n   <tr style=\\\"cursor: crosshair;\\\">\\n    <td><code>crosshair</code></td>\\n    <td>Cross cursor, often used to indicate selection in a bitmap.</td>\\n   </tr>\\n   <tr style=\\\"cursor: text;\\\">\\n    <td><code>text</code></td>\\n   <td>Indicating text can be selected, typically an I-beam.</td>\\n   </tr>\\n   <tr style=\\\"cursor: vertical-text;\\\">\\n    <td><code>vertical-text</code></td>\\n    <td>Indicating that vertical text can be selected, typically a sideways I-beam.</td>\\n   </tr>\\n   <tr style=\\\"cursor: alias;\\\">\\n    <td rowspan=\\\"5\\\" style=\\\"cursor: auto;\\\">Drag and drop</td>\\n    <td><code>alias</code></td>\\n        <td>Indicating an alias or shortcut is to be created.</td>\\n   </tr>\\n   <tr style=\\\"cursor: copy;\\\">\\n    <td><code>copy</code></td>\\n    <td>Indicating that something can be copied.</td>\\n   </tr>\\n   <tr style=\\\"cursor: move;\\\">\\n    <td><code>move</code></td>\\n    <td>The hovered object may be moved.</td>\\n   </tr>\\n   <tr style=\\\"cursor: no-drop;\\\">\\n    <td><code>no-drop</code></td>\\n    <td>Cursor showing that a drop is not allowed at the current location.<br>\\n     <a href=\\\"https://bugzilla.mozilla.org/show_bug.cgi?id=275173\\\" class=\\\"external\\\" title=\\\"Cursor glyph for CSS3 &apos;no-drop&apos; is the same as for &apos;not-allowed&apos;\\\">bug&#xA0;275173</a> on Windows&#xA0;and Mac OS X, &quot;no-drop is the same as not-allowed&quot;.</td>\\n   </tr>\\n   <tr style=\\\"cursor: not-allowed;\\\">\\n    <td><code>not-allowed</code></td>\\n     <td>Cursor showing that something cannot be done.</td>\\n   </tr>\\n   <tr style=\\\"cursor: all-scroll;\\\">\\n    <td rowspan=\\\"15\\\" style=\\\"cursor: auto;\\\">Resize &amp; scrolling</td>\\n    <td><code>all-scroll</code></td>\\n    <td>Cursor showing that something can be scrolled in any direction (panned).<br>\\n     <a href=\\\"https://bugzilla.mozilla.org/show_bug.cgi?id=275174\\\" class=\\\"external\\\" title=\\\"Cursor glyph for CSS3 &apos;all-scroll&apos; is the same as for &apos;move&apos;\\\">bug&#xA0;275174</a> on Windows, &quot;<em>all-scroll</em> is the same as <em>move</em>&quot;.</td>\\n   </tr>\\n   <tr style=\\\"cursor: col-resize;\\\">\\n    <td><code>col-resize</code></td>\\n    <td>The item/column can be resized horizontally. Often rendered as arrows pointing left and right with a vertical bar separating.</td>\\n   </tr>\\n   <tr style=\\\"cursor: row-resize;\\\">\\n    <td><code>row-resize</code></td>\\n    <td>The item/row can be resized vertically. Often rendered as arrows pointing up and down with a horizontal bar separating them.</td>\\n   </tr>\\n   <tr style=\\\"cursor: n-resize;\\\">\\n    <td><code>n-resize</code></td>\\n    <td rowspan=\\\"8\\\" style=\\\"cursor: auto;\\\">Some edge is to be moved. For example, the <code>se-resize</code> cursor is used when the movement starts from the <em>south-east</em> corner of the box.<br>\\n     In some environments, an equivalent bidirectional resize cursor is shown. For example, <code>n-resize</code> and <code>s-resize</code> are the same as <code>ns-resize</code>.</td>\\n   </tr>\\n   <tr style=\\\"cursor: e-resize;\\\">\\n    <td><code>e-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: s-resize;\\\">\\n    <td><code>s-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: w-resize;\\\">\\n    <td><code>w-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: ne-resize;\\\">\\n    <td><code>ne-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: nw-resize;\\\">\\n    <td><code>nw-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: se-resize;\\\">\\n    <td><code>se-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: sw-resize;\\\">\\n    <td><code>sw-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: ew-resize;\\\">\\n    <td><code>ew-resize</code></td>\\n    <td rowspan=\\\"4\\\" style=\\\"cursor: auto;\\\">Indicates a bidirectional resize cursor.</td>\\n   </tr>\\n   <tr style=\\\"cursor: ns-resize;\\\">\\n    <td><code>ns-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: nesw-resize;\\\">\\n    <td><code>nesw-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: nwse-resize;\\\">\\n    <td><code>nwse-resize</code></td>\\n    </tr>\\n   <tr style=\\\"cursor: -webkit-zoom-in; cursor: zoom-in;\\\">\\n    <td rowspan=\\\"2\\\">Zoom</td>\\n    <td><code>zoom-in</code></td>\\n    <td rowspan=\\\"2\\\" style=\\\"cursor: auto;\\\">\\n     <p>Indicates that something can be zoomed (magnified) in or out.</p>\\n    </td>\\n   </tr>\\n   <tr style=\\\"cursor: -webkit-zoom-out; cursor: zoom-out;\\\">\\n    <td><code>zoom-out</code></td>\\n    </tr>\\n   <tr id=\\\"grab\\\" style=\\\"cursor: -moz-grab; cursor: -webkit-grab; cursor: grab;\\\">\\n    <td rowspan=\\\"2\\\">Grab</td>\\n    <td><code>grab</code></td>\\n    <td rowspan=\\\"2\\\" style=\\\"cursor: auto;\\\">\\n     <p>Indicates that something can be grabbed (dragged to be moved).</p>\\n    </td>\\n   </tr>\\n   <tr style=\\\"cursor: -moz-grabbing; cursor: -webkit-grabbing; cursor: grabbing;\\\">\\n    <td><code>grabbing</code></td>\\n    </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"direction\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\",\n        \"SUMMARY\": \"Set the <strong><code>direction</code></strong> CSS property to match the direction of the text: <code>rtl</code> for languages written from right-to-left (like Hebrew or Arabic) text and <code>ltr</code> for other scripts. This is typically done as part of the document (e.g., using the <code>dir</code> attribute in HTML) rather than through direct use of CSS.\",\n        \"VALUES\": [{\n            \"value\": \"<code>ltr</code>\",\n            \"description\": \"The initial value of <code>direction</code> (that is, if not otherwise specified). Text and other elements go from left to right.\"\n        }, {\n            \"value\": \"<code>rtl</code>\",\n            \"description\": \"Text and other elements go from right to left\"\n        }]\n    },\n    \"display\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/display\",\n        \"SUMMARY\": \"The <strong><code>display</code></strong> CSS property specifies the type of rendering box used for an element. In HTML, default <code>display</code> property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is <code>inline</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"display-outside\\\" id=\\\"display-outside\\\">&lt;display-outside&gt;</a>\",\n            \"description\": \"These keywords specify the element&#x2019;s outer display type, which is essentially its role in flow layout. They are defined as follows:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <td class=\\\"header\\\">Value</td>\\n    <td class=\\\"header\\\">Description</td>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>block</code></td>\\n    <td>The element generates a block element box.</td>\\n   </tr>\\n   <tr>\\n    <td><code>inline</code></td>\\n    <td>The element generates one or more inline element boxes.</td>\\n   </tr>\\n   <tr>\\n    <td><code>run-in</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>The element generates a run-in box. Run-in elements act like inlines or blocks, depending on the surrounding elements. That is:\\n     <ul>\\n      <li>If the run-in box contains a block box, same as block.</li>\\n      <li>If a block box follows the run-in box, the run-in box becomes the first inline box of the block box.</li>\\n      <li>If an inline box follows, the run-in box becomes a block box.</li>\\n     </ul>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<a name=\\\"display-inside\\\" id=\\\"display-inside\\\">&lt;display-inside&gt;</a>\",\n            \"description\": \"These keywords specify the element&#x2019;s inner display type, which defines the type of formatting context that lays out its contents (assuming it is a non-replaced element). They are defined as follows:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <td class=\\\"header\\\">Value</td>\\n    <td class=\\\"header\\\">Description</td>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>flow</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>The element lays out its contents using flow layout (block-and-inline layout).\\n     <p>If its outer display type is inline or run-in, and it is participating in a block or inline formatting context, then it generates an inline box. Otherwise it generates a block container box.</p>\\n\\n     <p>Depending on the value of other properties (such as <a title=\\\"The position CSS property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\"><code>position</code></a>, <a title=\\\"The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/float\\\"><code>float</code></a>, or <a title=\\\"The overflow property specifies whether to clip content, render scrollbars or just display content when it overflows its block level container.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow\\\"><code>overflow</code></a>) and whether it is itself participating in a block or inline formatting context, it either establishes a new <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context\\\">block formatting context</a> for its contents or integrates its contents into its parent formatting context.</p>\\n    </td>\\n   </tr>\\n   <tr>\\n    <td><code>flow-root</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>The element generates a block element box that establishes a new <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context\\\">block formatting context</a>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;table&gt; element represents tabular data &#x2014;that is, information expressed via a two-dimensional data table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table\\\"><code>&lt;table&gt;</code></a> HTML elements. It defines a block-level box.</td>\\n   </tr>\\n   <tr>\\n    <td><code>flex</code></td>\\n    <td>The element behaves like a block element and lays out its content according to the flexbox model.</td>\\n   </tr>\\n   <tr>\\n    <td><code>-webkit-flex</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span></td>\\n    <td>Alias for <code>flex</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>-moz-box</code> / <code>-webkit-box</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span></td>\\n    <td>The element behaves like a flexible box according to an outdated Flexbox specification.</td>\\n   </tr>\\n   <tr>\\n    <td><code>grid</code></td>\\n    <td>The element behaves like a block element and lays out its content according to the grid model.</td>\\n   </tr>\\n   <tr>\\n    <td><code>subgrid</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>If the parent element has <code>display:grid</code>, the element itself and its content are laid out according to the grid model.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ruby</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>The element behaves like an inline element and lays out its content according to the ruby formatting model. It behaves like the corresponding <a title=\\\"The HTML &lt;ruby&gt; element represents a ruby annotation. Ruby annotations are for showing pronunciation of East Asian characters.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby\\\"><code>&lt;ruby&gt;</code></a> HTML elements.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<a name=\\\"display-listitem\\\" id=\\\"display-listitem\\\">&lt;display-listitem&gt;</a>\",\n            \"description\": \"\\n <p>The element generates a block box for the content and a separate list-item inline box.</p>\\n\\n <p>If no <code>&lt;display-inside&gt;</code> value is specified, the principal box&#x2019;s inner display type defaults to <code>flow</code>. If no <code>&lt;display-outside&gt;</code> value is specified, the principal box&#x2019;s outer display type defaults to <code>block</code>.</p>\\n \"\n        }, {\n            \"value\": \"<a name=\\\"display-internal\\\" id=\\\"display-internal\\\">&lt;display-internal&gt;</a>\",\n            \"description\": \"\\n <p>Some layout models, such as <span class=\\\"css\\\">table</span> and ruby, have a complex internal structure, with several different roles that their children and descendants can fill. This section defines those &quot;internal&quot; display values, which only have meaning within that particular layout mode.</p>\\n\\n <p>Unless otherwise specified, both the inner display type and the outer display type of elements using these display values are set to the given keyword.</p>\\n\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <td class=\\\"header\\\">Value</td>\\n    <td class=\\\"header\\\">Description</td>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>table-row-group</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;tbody&gt; element groups one or more &lt;tr&gt; elements as the body of a &lt;table&gt; element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody\\\"><code>&lt;tbody&gt;</code></a> HTML elements</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-header-group</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;thead&gt; element defines a set of rows defining the head of the columns of the table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead\\\"><code>&lt;thead&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-footer-group</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;tfoot&gt; element defines a set of rows summarizing the columns of the table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot\\\"><code>&lt;tfoot&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-row</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;tr&gt; element defines a row of cells in a table. Those can be a mix of &lt;td&gt; and &lt;th&gt; elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr\\\"><code>&lt;tr&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-cell</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;td&gt; element defines a cell of a table that contains data. It participates in the table model.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td\\\"><code>&lt;td&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-column-group</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;colgroup&gt; element defines a group of columns within a table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup\\\"><code>&lt;colgroup&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-column</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;col&gt; element defines a column within a table and is used for defining common semantics on all common cells. It is generally found within a &lt;colgroup&gt; element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col\\\"><code>&lt;col&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>table-caption</code></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;caption&gt; element represents the title of a table. Though it is always the first descendant of a &lt;table&gt;, its styling, using CSS, may place it elsewhere, relative to the table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption\\\"><code>&lt;caption&gt;</code></a> HTML elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ruby-base</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>These elements behave like <a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb\\\" class=\\\"new\\\"><code>&lt;rb&gt;</code></a> elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ruby-text</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;rt&gt; element embraces pronunciation of characters presented in a ruby annotations, which are used to describe the pronunciation of East Asian characters. This element is always used inside a &lt;ruby&gt; element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt\\\"><code>&lt;rt&gt;</code></a> elements.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ruby-base-container</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>These elements behave like <a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rbc\\\" class=\\\"new\\\"><code>&lt;rbc&gt;</code></a> elements generated as anonymous boxes.</td>\\n   </tr>\\n   <tr>\\n    <td><code>ruby-text-container</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>These elements behave like <a title=\\\"The HTML &lt;rtc&gt; element embraces semantic annotations of characters presented in a ruby of &lt;rb&gt; elements used inside of &lt;ruby&gt; element. &lt;rb&gt; elements can have both pronunciation (&lt;rt&gt;) and semantic (&lt;rtc&gt;) annotations.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc\\\"><code>&lt;rtc&gt;</code></a> elements.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<a name=\\\"display-box\\\" id=\\\"display-box\\\">&lt;display-box&gt;</a>\",\n            \"description\": \"These values define whether an element generates display boxes at all.\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <td class=\\\"header\\\">Value</td>\\n    <td class=\\\"header\\\">Description</td>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>contents</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>These elements don&apos;t produce a specific box by themselves. They are replaced by their pseudo-box and their child boxes.</td>\\n   </tr>\\n   <tr>\\n    <td><code>none</code></td>\\n    <td>\\n     <p>Turns off the display of an element (it has no effect on layout); all descendant elements also have their display turned off. The document is rendered as though the element did not exist.</p>\\n\\n     <p>To render an element box&apos;s dimensions, yet have its contents be invisible, see the <a title=\\\"The visibility property can be used to hide an element while leaving the space where it would have been. It can also hide rows or columns of a table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/visibility\\\"><code>visibility</code></a> property.</p>\\n    </td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<a name=\\\"display-legacy\\\" id=\\\"display-legacy\\\">&lt;display-legacy&gt;</a>\",\n            \"description\": \"CSS 2 used a single-keyword syntax for the <code>display</code> property, requiring separate keywords for block-level and inline-level variants of the same layout mode. They are defined as follows:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <td class=\\\"header\\\">Value</td>\\n    <td class=\\\"header\\\">Description</td>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>inline-block</code></td>\\n    <td>\\n     <p>The element generates a block element box that will be flowed with surrounding content as if it were a single inline box (behaving much like a replaced element would)</p>\\n\\n     <p>It is equivalent to <code>inline flow-root</code>.</p>\\n    </td>\\n   </tr>\\n   <tr>\\n    <td><code>inline-list-item</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span></td>\\n    <td>This value makes the element a list item, with the effects described above. Additionally, the <code>outside</code> value of <a title=\\\"The list-style-position property specifies the position of the marker box in the principal block box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-position\\\"><code>list-style-position</code></a> computes to <code>inside</code> on this element. Otherwise, this display value is treated identically to inline.</td>\\n   </tr>\\n   <tr>\\n    <td><code>inline-table</code></td>\\n    <td>\\n     <p>The<code> inline-table </code>value does not have a direct mapping in HTML. It behaves like a <a title=\\\"The HTML &lt;table&gt; element represents tabular data &#x2014;that is, information expressed via a two-dimensional data table.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table\\\"><code>&lt;table&gt;</code></a> HTML element, but as an inline box, rather than a block-level box. Inside the table box is a block-level context.</p>\\n\\n     <p>It is equivalent to <code>inline table</code>.</p>\\n    </td>\\n   </tr>\\n   <tr>\\n    <td><code>inline-flex</code></td>\\n    <td>\\n     <p>The element behaves like an inline element and lays out its content according to the flexbox model.</p>\\n\\n     <p>It is equivalent to <code>inline flex</code>.</p>\\n    </td>\\n   </tr>\\n   <tr>\\n    <td><code>-webkit-inline-flex</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span></td>\\n    <td>Alias for <code>inline-flex</code>.</td>\\n   </tr>\\n   <tr>\\n    <td><code>-moz-inline-box</code> / <code>-webkit-inline-box</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span></td>\\n    <td>The element behaves like a inline flexible box according to an outdated Flexbox specification.</td>\\n   </tr>\\n   <tr>\\n    <td><code>inline-grid</code></td>\\n    <td>The element behaves like an inline element and lays out its content according to the grid model.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"display-inside\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/display-inside\",\n        \"SUMMARY\": \"The <code>display-inside</code> CSS property specifies the inner display type of the box generated by an element, dictating how its contents lay out inside the box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"If the element&apos;s computed <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display-outside\\\" title=\\\"The display-outside CSS property specifies the outer display type of the box generated by an element, dictating how the element participates in its parent formatting context.\\\"><code>display-outside</code></a> value is <code>inline-level</code>, the element is an inline element, and lays out its contents using inline layout. If the element&apos;s computed <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display-outside\\\" title=\\\"The display-outside CSS property specifies the outer display type of the box generated by an element, dictating how the element participates in its parent formatting context.\\\"><code>display-outside</code></a> value is an layout-specific internal type, this elements acts as normal for its given <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display-outside\\\" title=\\\"The display-outside CSS property specifies the outer display type of the box generated by an element, dictating how the element participates in its parent formatting context.\\\"><code>display-outside</code></a> value. Otherwise, this value computes to block.\"\n        }, {\n            \"value\": \"<code>block</code>\",\n            \"description\": \"The element lays out its contents using block layout.\"\n        }, {\n            \"value\": \"<code>table</code>\",\n            \"description\": \"The element lays out its contents using table layout.\"\n        }, {\n            \"value\": \"<code>flex</code>\",\n            \"description\": \"The element lays out its contents using flex layout.\"\n        }, {\n            \"value\": \"<code>grid</code>\",\n            \"description\": \"The element lays out its contents using grid layout.\"\n        }, {\n            \"value\": \"<code>ruby</code>\",\n            \"description\": \"The element lays out its contents using ruby layout.\"\n        }]\n    },\n    \"display-list\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/display-list\",\n        \"SUMMARY\": \"The <code>display-list</code> CSS property specifies whether a list marker should be displayed for an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"There is no list marker displayed for the element.\"\n        }, {\n            \"value\": \"<code>list-item</code>\",\n            \"description\": \"The element generates a <code>::marker</code> pseudo-element and is considered a list item.\"\n        }]\n    },\n    \"display-outside\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/display-outside\",\n        \"SUMMARY\": \"The <code>display-outside</code> CSS property specifies the outer display type of the box generated by an element, dictating how the element participates in its parent formatting context.\",\n        \"VALUES\": [{\n            \"value\": \"<code>block-level</code>\",\n            \"description\": \"The element generates a block-level box, and participates in a block formatting context. Other formatting contexts, such as flex formatting contexts, may also work with block-level elements.\"\n        }, {\n            \"value\": \"<code>inline-level</code>\",\n            \"description\": \"The element generates an inline-level box, and participates in an inline formatting context.\"\n        }, {\n            \"value\": \"<code>run-in</code>\",\n            \"description\": \"The element generates a run-in box. Run-in elements act like inlines or blocks, depending on the surrounding elements.\"\n        }, {\n            \"value\": \"<code>contents</code>\",\n            \"description\": \"The element lays out its contents using flex layout.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The element generates no boxes, and does not participate in any formatting context.\"\n        }, {\n            \"value\": \"<code>table-row-group, table-header-group, table-footer-group, table-row, table-cell, table-column-group, table-column, table-caption</code>\",\n            \"description\": \"The element is an internal table element, and participates in a table layout context.<br>\\n <br>\\n <code>table-cell</code> and <code>table-caption</code> are layout-specific leaf types; the rest are <a href=\\\"#layout-internal\\\">layout-specific internal types</a>.\"\n        }, {\n            \"value\": \"<code>ruby-base, ruby-text, ruby-base-container, ruby-text-container</code>\",\n            \"description\": \"The element is an internal ruby element, and participates in a ruby layout context.<br>\\n <br>\\n <code>ruby-base</code> and <code>ruby-text</code> are <a href=\\\"#layout-leaf\\\">layout-specific leaf types</a>; <code>ruby-base-container</code> and <code>ruby-text-container</code> are <a href=\\\"#layout-internal\\\">layout-specific internal types</a>.\"\n        }, {\n            \"value\": \"<a name=\\\"layout-internal\\\">layout-specific internal types</a>\",\n            \"description\": \"These display types require their parent and children to be of particular display types. For example, a <code>table-row</code> box requires its parent to be a table row group box and its children to be <code>table-cell</code> boxes.\"\n        }, {\n            \"value\": \"<a name=\\\"layout-leaf\\\">layout-specific leaf types</a>\",\n            \"description\": \"These display types require their parent to be of a particular display type, but can accept any <code>display-inside</code> value. For example, a <code>table-caption</code> box must have a <code>table</code> parent, but can establish any kind of formatting context for its children.\"\n        }]\n    },\n    \"element\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/element\",\n        \"SUMMARY\": \"The <code>element()</code> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> function defines an <a title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\"><code>&lt;image&gt;</code></a> value generated from an arbitrary HTML element. This image is live, meaning that if the HTML element is changed, the CSS properties using the resulting value are automatically updated.\",\n        \"VALUES\": [{\n            \"value\": \"<strong><code>id</code></strong>\",\n            \"description\": \"The ID of an element to use as the background, specified using the HTML attribute #<em>id</em> on the element.\"\n        }]\n    },\n    \"empty-cells\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/empty-cells\",\n        \"SUMMARY\": \"The <strong><code>empty-cells</code></strong> CSS property specifies how user agents should render borders and backgrounds around cells that have no visible content.\",\n        \"VALUES\": [{\n            \"value\": \"<code>show</code>\",\n            \"description\": \"Is a keyword indicating that borders and backgrounds should be drawn like in normal cells.\"\n        }, {\n            \"value\": \"<code>hide</code>\",\n            \"description\": \"Is a keyword indicating that no borders or backgrounds should be drawn.\"\n        }]\n    },\n    \"filter\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/filter\",\n        \"SUMMARY\": \"The <strong><code>filter</code></strong> property provides graphical effects like blurring, sharpening, or color shifting an element. Filters are commonly used to adjust the rendering of images, backgrounds, and borders.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;offset-x&gt;</code> <code>&lt;offset-y&gt;</code> <small>(required)</small>\",\n            \"description\": \"These are two <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> values to set the shadow offset. <code>&lt;offset-x&gt;</code> specifies the horizontal distance. Negative values place the shadow to the left of the element. <code>&lt;offset-y&gt;</code> specifies the vertical distance. Negative values place the shadow above the element. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units.<br>\\n If both values are <code>0</code>, the shadow is placed behind the element (and may generate a blur effect if <code>&lt;blur-radius&gt;</code> and/or <code>&lt;spread-radius&gt;</code> is set).\"\n        }, {\n            \"value\": \"<code>&lt;blur-radius&gt;</code> <small>(optional)</small>\",\n            \"description\": \"This is a third <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value. The larger this value, the bigger the blur, so the shadow becomes bigger and lighter. Negative values are not allowed. If not specified, it will be <code>0</code> (the shadow&apos;s edge is sharp).\"\n        }, {\n            \"value\": \"<code>&lt;spread-radius&gt;</code> <small>(optional)</small>\",\n            \"description\": \"This is a fourth <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value. Positive values will cause the shadow to expand and grow bigger, and negative values will cause the shadow to shrink. If not specified, it will be <code>0</code> (the shadow will be the same size as the element).&#xA0;<br>\\n Note: Webkit, and maybe other browsers, do not support this 4th length; it will not render if added.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;</code> <small>(optional)</small>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> values for possible keywords and notations. If not specified, the color depends on the browser. In Gecko (Firefox), Presto (Opera) and Trident (Internet Explorer), the value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element&apos;s text content, and its decorations. It doesn&apos;t affect any other characteristic of the element; it should really be called text-color and would have been named so, save for historical reasons and its appearance in CSS Level 1.\\\"><code>color</code></a> property is used. On the other hand, WebKit&apos;s shadow is transparent and therefore useless if <code>&lt;color&gt;</code> is omitted.\"\n        }]\n    },\n    \"fit-content()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content\",\n        \"SUMMARY\": \"The <strong><code>fit-content()</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> function clamps a given size to an available size according to the formula <code>min(<var>maximum size</var>, max(<var>minimum size</var>, <var>argument</var>))</code>.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;length&gt;\",\n            \"description\": \"An absolute length.\"\n        }, {\n            \"value\": \"&lt;percentage&gt;\",\n            \"description\": \"A percentage relative to the available space in the given axis.\"\n        }]\n    },\n    \"flex\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex\",\n        \"SUMMARY\": \"The <strong><code>flex</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property specifying the ability of a flex item to alter its dimensions to fill available space. Flex items can be stretched to use available space proportional to their flex grow factor or their flex shrink factor to prevent overflow.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"&lt;&apos;flex-grow&apos;&gt;\\\" id=\\\"&lt;&apos;flex-grow&apos;&gt;\\\"><code>&lt;&apos;flex-grow&apos;&gt;</code></a>\",\n            \"description\": \"Defines the&#xA0;<code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow\\\">flex-grow</a></code>&#xA0;of the flex item. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> for more details. Negative values are considered invalid. Defaults to <code>0</code> when omitted.\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;&apos;flex-shrink&apos;&gt;\\\" id=\\\"&lt;&apos;flex-shrink&apos;&gt;\\\"><code>&lt;&apos;flex-shrink&apos;&gt;</code></a>\",\n            \"description\": \"Defines the&#xA0;<code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink\\\">flex-shrink</a></code>&#xA0;of the flex item. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> for more details. Negative values are considered invalid. Defaults to <code>1</code> when omitted.\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;&apos;flex-basis&apos;&gt;\\\" id=\\\"&lt;&apos;flex-basis&apos;&gt;\\\"><code>&lt;&apos;flex-basis&apos;&gt;</code></a>\",\n            \"description\": \"Defines the&#xA0;<a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/flex-basis\\\" title=\\\"CSS/flex-basis\\\"><code>flex-basis</code></a>&#xA0;of the flex item. Any value valid for <code>width</code> and <code>height</code> properties are accepted. A preferred size of <code>0</code> must have a unit to avoid being interpreted as a flexibility. Defaults to <code>auto</code>&#xA0;when omitted.\"\n        }, {\n            \"value\": \"<a name=\\\"none\\\" id=\\\"none\\\"><code>none</code></a>\",\n            \"description\": \"This keyword computes to <code>0 0 auto</code>.\"\n        }]\n    },\n    \"flex-basis\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis\",\n        \"SUMMARY\": \"The <strong><code>flex-basis</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the flex basis which is the initial <strong>main size</strong> of a flex item. This property determines the size of the content-box unless specified otherwise using <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing\\\" title=\\\"The box-sizing property is used to alter the default CSS box model used to calculate width and height of the elements. It is possible to use this property to emulate the behavior of browsers that do not correctly support the CSS box model specification.\\\"><code>box-sizing</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;width&apos;&gt;</code>\",\n            \"description\": \"Defined as a number followed by a absolute unit such as <code>px</code>, <code>mm</code> or <code>pt</code>, or a percentage of the parent flex container main size property. Negative values are invalid.\"\n        }, {\n            \"value\": \"<code>content</code>\",\n            \"description\": \"Indicates automatic sizing, based on the flex item&#x2019;s content.\"\n        }]\n    },\n    \"flex-direction\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction\",\n        \"SUMMARY\": \"The <strong><code>flex-direction</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies how flex items are placed in the flex container defining the main axis and the direction (normal or reversed).\",\n        \"VALUES\": [{\n            \"value\": \"<code>row</code>\",\n            \"description\": \"The flex container&apos;s main-axis is defined to be the same as the text direction. The <strong>main-start</strong> and <strong>main-end</strong> points are the same as the content direction.\"\n        }, {\n            \"value\": \"<code>row-reverse</code>\",\n            \"description\": \"Behaves the same as <code>row</code> but the <strong>main-start</strong> and <strong>main-end</strong> points are permuted.\"\n        }, {\n            \"value\": \"<code>column</code>\",\n            \"description\": \"The flex container&apos;s main-axis is the same as the block-axis. The <strong>main-start</strong> and <strong>main-end</strong> points are the same as the <strong>before</strong> and <strong>after</strong> points of the writing-mode.\"\n        }, {\n            \"value\": \"<code>column-reverse</code>\",\n            \"description\": \"Behaves the same as <code>column</code> but the <strong>main-start</strong> and <strong>main-end</strong> are permuted.\"\n        }]\n    },\n    \"flex-flow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-flow\",\n        \"SUMMARY\": \"The <strong><code>flex-flow</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a shorthand property for <code>flex-direction</code> and <code>flex-wrap</code> individual properties.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/flex-direction\\\" title=\\\"en-US/docs/CSS/flex-direction\\\"><code>flex-direction</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/flex-wrap\\\" title=\\\"flex-wrap\\\"><code>flex-wrap</code></a> for details on the values.\"\n        }]\n    },\n    \"flex-grow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow\",\n        \"SUMMARY\": \"The <strong><code>flex-grow</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the flex grow factor of a flex item. It specifies what amount of space inside the flex container the item should take up.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"See <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a>. Negative values are invalid.\"\n        }]\n    },\n    \"flex-shrink\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink\",\n        \"SUMMARY\": \"The <strong><code>flex-shrink</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies the flex shrink factor of a flex item.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;number</code>&gt;\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a>. Negative values are invalid.\"\n        }]\n    },\n    \"flex-wrap\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> <strong><code>flex-wrap</code></strong> property specifies whether flex items are forced into a single line or can be wrapped onto multiple lines. If wrapping is allowed, this property also enables you to control the direction in which lines are stacked.\",\n        \"VALUES\": [{\n            \"value\": \"<code>nowrap</code>\",\n            \"description\": \"The flex items are laid out in a single line which may cause the flex container to overflow. The <strong>cross-start</strong> is either equivalent to <strong>start</strong> or <strong>before</strong> depending <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction\\\" title=\\\"The flex-direction CSS property specifies how flex items are placed in the flex container defining the main axis and the direction (normal or reversed).\\\"><code>flex-direction</code></a> value.\"\n        }, {\n            \"value\": \"<code>wrap</code>\",\n            \"description\": \"The flex items break into multiple lines. The <strong>cross-start</strong> is either equivalent to <strong>start</strong> or <strong>before</strong> depending <code>flex-direction</code> value and the <strong>cross-end</strong> is the opposite of the specified <strong>cross-start</strong>.\"\n        }, {\n            \"value\": \"<code>wrap-reverse</code>\",\n            \"description\": \"Behaves the same as <code>wrap</code> but <strong>cross-start</strong> and <strong>cross-end</strong> are permuted.\"\n        }]\n    },\n    \"float\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/float\",\n        \"SUMMARY\": \"The <strong><code>float</code></strong> CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.\",\n        \"VALUES\": [{\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Is a keyword indicating that the element must float on the left side of its containing block.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Is a keyword indicating that the element must float on the right side of its containing block.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword indicating that the element must not float.\"\n        }, {\n            \"value\": \"<code>inline-start</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the element must float on the start side of its containing block, that is the left side on ltr scripts and the right side on rtl scripts.\"\n        }, {\n            \"value\": \"<code>inline-end</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Is a keyword indicating that the element must float on the end side of its containing block, that is the right side on ltr scripts and the left side on rtl scripts.\"\n        }]\n    },\n    \"font\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font\",\n        \"SUMMARY\": \"The <code>font</code> CSS property is either a shorthand property for setting <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-style\\\" title=\\\"The font-style CSS property lets you select italic or oblique faces within a font-family. Italic forms are generally cursive in nature, usually using less horizontal space than their unstyled counterparts, while oblique faces are usually just sloped versions of the regular face. Both italic and oblique faces are simulated by artificially sloping the glyphs of the regular face (see font-synthesis for control over this).\\\"><code>font-style</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant\\\" title=\\\"The font-variant property acts as a shorthand for the longhand properties: font-variant-caps, font-variant-numeric, font-variant-alternates, font-variant-ligatures, and font-variant-east-asian. You can also set the CSS Level 2 (Revision 1) values of font-variant, (that is, normal or small-caps), by using the font shorthand.\\\"><code>font-variant</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight\\\" title=\\\"The font-weight CSS property specifies the weight or boldness of the font. Some fonts are only available in normal and bold.\\\"><code>font-weight</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font (historically the width of the capital &quot;M&quot;). Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\\\" title=\\\"On block level elements, the line-height property specifies the minimum height of line boxes within the element.\\\"><code>line-height</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-family\\\" title=\\\"The font-family CSS property lets you specify a prioritized list of font family names and/or generic family names for the selected element. Values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer or that can be downloaded using a @font-face at-rule.\\\"><code>font-family</code></a>, or a way to set the element's font to a system font, using specific keywords.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;font-style&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-style\\\" title=\\\"The font-style CSS property lets you select italic or oblique faces within a font-family. Italic forms are generally cursive in nature, usually using less horizontal space than their unstyled counterparts, while oblique faces are usually just sloped versions of the regular face. Both italic and oblique faces are simulated by artificially sloping the glyphs of the regular face (see font-synthesis for control over this).\\\"><code>font-style</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;font-variant&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant\\\" title=\\\"The font-variant property acts as a shorthand for the longhand properties: font-variant-caps, font-variant-numeric, font-variant-alternates, font-variant-ligatures, and font-variant-east-asian. You can also set the CSS Level 2 (Revision 1) values of font-variant, (that is, normal or small-caps), by using the font shorthand.\\\"><code>font-variant</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;font-weight&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight\\\" title=\\\"The font-weight CSS property specifies the weight or boldness of the font. Some fonts are only available in normal and bold.\\\"><code>font-weight</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;font-stretch&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch\\\" title=\\\"The font-stretch property selects a normal, condensed, or expanded face from a font.\\\"><code>font-stretch</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;font-size&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;line-height&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\\\" title=\\\"On block level elements, the line-height property specifies the minimum height of line boxes within the element.\\\"><code>line-height</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;font-family&apos;&gt;</code>\",\n            \"description\": \"See the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-family\\\" title=\\\"The font-family CSS property lets you specify a prioritized list of font family names and/or generic family names for the selected element. Values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer or that can be downloaded using a @font-face at-rule.\\\"><code>font-family</code></a> CSS property.\"\n        }, {\n            \"value\": \"<code>caption</code> <code>icon</code> <code>menu</code> <code>message-box</code> <code>small-caption</code> <code>status-bar</code>\",\n            \"description\": \"Instead of specifying individual longhand properties, a keyword can be used to represent a specific system font:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td><code>caption</code></td>\\n    <td>The font used for captioned controls (e.g., buttons, drop-downs, etc.).</td>\\n   </tr>\\n   <tr>\\n    <td><code>icon</code></td>\\n    <td>The font used to label icons.</td>\\n   </tr>\\n   <tr>\\n    <td><code>menu</code></td>\\n    <td>The font used in menus (e.g., dropdown menus and menu lists).</td>\\n   </tr>\\n   <tr>\\n    <td><code>message-box</code></td>\\n    <td>The font used in dialog boxes.</td>\\n   </tr>\\n   <tr>\\n    <td><code>small-caption</code></td>\\n    <td>The font used for labeling small controls.</td>\\n   </tr>\\n   <tr>\\n    <td><code>status-bar</code></td>\\n    <td>The font used in window status bars.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n Browsers implementing these often implement several more, prefixed, values; Gecko implements <code>-moz-window</code>, <code>-moz-document</code>, <code>-moz-desktop</code>, <code>-moz-info</code>, <code>-moz-dialog</code>, <code>-moz-button</code>, <code>-moz-pull-down-menu</code>, <code>-moz-list</code> and <code>-moz-field</code>.\"\n        }]\n    },\n    \"font-family\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-family\",\n        \"SUMMARY\": \"The <strong><code>font-family</code></strong> CSS property lets you specify a prioritized list of font family names and/or generic family names for the selected element. Values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer or that can be downloaded using a <a title=\\\"The @font-face CSS at-rule allows authors to specify online fonts to display text on their web pages. By allowing authors to provide their own fonts, @font-face eliminates the need to depend on the limited number of fonts users have installed on their computers. The @font-face at-rule may be used not only at the top level of a CSS, but also inside any CSS conditional-group at-rule.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face\\\"><code>@font-face</code></a> at-rule.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"&lt;family-name&gt;\\\" id=\\\"&lt;family-name&gt;\\\"><code>&lt;family-name&gt;</code></a>\",\n            \"description\": \"The name of a font family. For example, &quot;Times&quot; and &quot;Helvetica&quot; are font families. Font family names containing whitespace should be quoted.\"\n        }, {\n            \"value\": \"<a name=\\\"&lt;generic-name&gt;\\\" id=\\\"&lt;generic-name&gt;\\\"><code>&lt;generic-name&gt;</code></a>\",\n            \"description\": \"\\n <p>Generic font families are a fallback mechanism, a means of preserving some of the style sheet author&apos;s intent when none of the specified fonts are available. Generic family names are keywords and must not be quoted. A generic font family should be the last item in the list of font family names. The following keywords are defined:</p>\\n\\n <dl>\\n  <dt><code>serif</code></dt>\\n  <dd style=\\\"font-family: serif;\\\">Glyphs have finishing strokes, flared or tapering ends, or have actual serifed endings.<br>\\n  E.g. <span style=\\\"font-family: lucida bright,serif;\\\">Lucida Bright</span>, <span style=\\\"font-family: lucida fax,serif;\\\">Lucida Fax</span>, <span style=\\\"font-family: palatino,serif;\\\">Palatino</span>, <span style=\\\"font-family: palatino linotype,serif;\\\">&quot;Palatino Linotype&quot;</span>, <span style=\\\"font-family: palladio,serif;\\\">Palladio</span>, <span style=\\\"font-family: urw palladio,serif;\\\">&quot;URW Palladio&quot;</span>, <span style=\\\"font-family: serif;\\\">serif</span>.</dd>\\n  <dt><code>sans-serif</code></dt>\\n  <dd style=\\\"font-family: sans-serif;\\\">Glyphs have stroke endings that are plain.<br>\\n  E.g. <span style=\\\"font-family: open sans,sans-serif;\\\">&quot;Open Sans&quot;</span>, <span style=\\\"font-family: fira sans,sans-serif;\\\">&quot;Fira Sans&quot;</span>, <span style=\\\"font-family: lucida sans,sans-serif;\\\">&quot;Lucida Sans&quot;</span>, <span style=\\\"font-family: lucida sans unicode,sans-serif;\\\">&quot;Lucida Sans Unicode&quot;</span>, <span style=\\\"font-family: trebuchet ms,sans-serif;\\\">&quot;Trebuchet MS&quot;</span>, <span style=\\\"font-family: liberation sans,sans-serif;\\\">&quot;Liberation Sans&quot;</span>, <span style=\\\"font-family: nimbus sans l,sans-serif;\\\">&quot;Nimbus Sans L&quot;</span>, <span style=\\\"font-family: sans-serif;\\\">sans-serif</span>.</dd>\\n  <dt><code>monospace</code></dt>\\n  <dd style=\\\"font-family: monospace;\\\">All glyphs have the same fixed width.<br>\\n  E.g. <span style=\\\"font-family: fira mono,monospace;\\\">&quot;Fira Mono&quot;</span>, <span style=\\\"font-family: dejavu sans mono,monospace;\\\">&quot;DejaVu Sans Mono&quot;</span>, <span style=\\\"font-family: menlo,monospace;\\\">Menlo</span>, <span style=\\\"font-family: consolas,monospace;\\\">Consolas</span>, <span style=\\\"font-family: liberation mono,monospace;\\\">&quot;Liberation Mono&quot;</span>, <span style=\\\"font-family: monaco,monospace;\\\">Monaco</span>, <span style=\\\"font-family: lucida console,monospace;\\\">&quot;Lucida Console&quot;</span>, <span style=\\\"font-family: monospace;\\\">monospace.</span></dd>\\n  <dt><code>cursive</code></dt>\\n  <dd style=\\\"font-family: cursive;\\\">Glyphs in cursive fonts generally have either joining strokes or other cursive characteristics beyond those of italic typefaces. The glyphs are partially or completely connected, and the result looks more like handwritten pen or brush writing than printed letterwork.<br>\\n  E.g. <span style=\\\"font-family: brush script mt,cursive;\\\">&quot;Brush Script MT</span>&quot;, <span style=\\\"font-family: brush script std,cursive;\\\">&quot;Brush Script Std</span>&quot;, <span>&quot;Lucida Calligraphy&quot;</span>, <span>&quot;Lucida Handwriting&quot;</span>, <span style=\\\"font-family: apple chancery,cursive;\\\">&quot;Apple Chancery&quot;</span>, <span style=\\\"font-family: cursive;\\\">cursive</span>.</dd>\\n  <dt><code>fantasy</code></dt>\\n  <dd style=\\\"font-family: fantasy;\\\">Fantasy fonts are primarily decorative fonts that contain playful representations of characters.<br>\\n  E.g. <span style=\\\"font-family: papyrus,fantasy;\\\">Papyrus</span>, <span style=\\\"font-family: herculanum,fantasy;\\\">Herculanum</span>, <span style=\\\"font-family: party let,fantasy;\\\">Party LET</span>, <span style=\\\"font-family: curlz mt,fantasy;\\\">Curlz MT</span>, <span style=\\\"font-family: harrington,fantasy;\\\">Harrington</span>, <span style=\\\"font-family: fantasy;\\\">fantasy</span>.</dd>\\n  <dt><code>system-ui</code></dt>\\n  <dd style=\\\"\\\">Glyphs are taken from the default user interface font on a given platform. Because typographic traditions vary widely across the world, this generic is provided for typefaces that don&apos;t map cleanly into the other generics.</dd>\\n </dl>\\n \"\n        }, {\n            \"value\": \"<code>serif</code>\",\n            \"description\": \"Glyphs have finishing strokes, flared or tapering ends, or have actual serifed endings.<br>\\n  E.g. <span style=\\\"font-family: lucida bright,serif;\\\">Lucida Bright</span>, <span style=\\\"font-family: lucida fax,serif;\\\">Lucida Fax</span>, <span style=\\\"font-family: palatino,serif;\\\">Palatino</span>, <span style=\\\"font-family: palatino linotype,serif;\\\">&quot;Palatino Linotype&quot;</span>, <span style=\\\"font-family: palladio,serif;\\\">Palladio</span>, <span style=\\\"font-family: urw palladio,serif;\\\">&quot;URW Palladio&quot;</span>, <span style=\\\"font-family: serif;\\\">serif</span>.\"\n        }, {\n            \"value\": \"<code>sans-serif</code>\",\n            \"description\": \"Glyphs have stroke endings that are plain.<br>\\n  E.g. <span style=\\\"font-family: open sans,sans-serif;\\\">&quot;Open Sans&quot;</span>, <span style=\\\"font-family: fira sans,sans-serif;\\\">&quot;Fira Sans&quot;</span>, <span style=\\\"font-family: lucida sans,sans-serif;\\\">&quot;Lucida Sans&quot;</span>, <span style=\\\"font-family: lucida sans unicode,sans-serif;\\\">&quot;Lucida Sans Unicode&quot;</span>, <span style=\\\"font-family: trebuchet ms,sans-serif;\\\">&quot;Trebuchet MS&quot;</span>, <span style=\\\"font-family: liberation sans,sans-serif;\\\">&quot;Liberation Sans&quot;</span>, <span style=\\\"font-family: nimbus sans l,sans-serif;\\\">&quot;Nimbus Sans L&quot;</span>, <span style=\\\"font-family: sans-serif;\\\">sans-serif</span>.\"\n        }, {\n            \"value\": \"<code>monospace</code>\",\n            \"description\": \"All glyphs have the same fixed width.<br>\\n  E.g. <span style=\\\"font-family: fira mono,monospace;\\\">&quot;Fira Mono&quot;</span>, <span style=\\\"font-family: dejavu sans mono,monospace;\\\">&quot;DejaVu Sans Mono&quot;</span>, <span style=\\\"font-family: menlo,monospace;\\\">Menlo</span>, <span style=\\\"font-family: consolas,monospace;\\\">Consolas</span>, <span style=\\\"font-family: liberation mono,monospace;\\\">&quot;Liberation Mono&quot;</span>, <span style=\\\"font-family: monaco,monospace;\\\">Monaco</span>, <span style=\\\"font-family: lucida console,monospace;\\\">&quot;Lucida Console&quot;</span>, <span style=\\\"font-family: monospace;\\\">monospace.</span>\"\n        }, {\n            \"value\": \"<code>cursive</code>\",\n            \"description\": \"Glyphs in cursive fonts generally have either joining strokes or other cursive characteristics beyond those of italic typefaces. The glyphs are partially or completely connected, and the result looks more like handwritten pen or brush writing than printed letterwork.<br>\\n  E.g. <span style=\\\"font-family: brush script mt,cursive;\\\">&quot;Brush Script MT</span>&quot;, <span style=\\\"font-family: brush script std,cursive;\\\">&quot;Brush Script Std</span>&quot;, <span>&quot;Lucida Calligraphy&quot;</span>, <span>&quot;Lucida Handwriting&quot;</span>, <span style=\\\"font-family: apple chancery,cursive;\\\">&quot;Apple Chancery&quot;</span>, <span style=\\\"font-family: cursive;\\\">cursive</span>.\"\n        }, {\n            \"value\": \"<code>fantasy</code>\",\n            \"description\": \"Fantasy fonts are primarily decorative fonts that contain playful representations of characters.<br>\\n  E.g. <span style=\\\"font-family: papyrus,fantasy;\\\">Papyrus</span>, <span style=\\\"font-family: herculanum,fantasy;\\\">Herculanum</span>, <span style=\\\"font-family: party let,fantasy;\\\">Party LET</span>, <span style=\\\"font-family: curlz mt,fantasy;\\\">Curlz MT</span>, <span style=\\\"font-family: harrington,fantasy;\\\">Harrington</span>, <span style=\\\"font-family: fantasy;\\\">fantasy</span>.\"\n        }, {\n            \"value\": \"<code>system-ui</code>\",\n            \"description\": \"Glyphs are taken from the default user interface font on a given platform. Because typographic traditions vary widely across the world, this generic is provided for typefaces that don&apos;t map cleanly into the other generics.\"\n        }]\n    },\n    \"font-feature-settings\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings\",\n        \"SUMMARY\": \"The <strong><code>font-feature-settings</code></strong> CSS property gives you control over advanced typographic features in OpenType fonts.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Text is laid out using default settings.\"\n        }, {\n            \"value\": \"<code>&lt;feature-tag-value&gt;</code>\",\n            \"description\": \"When rendering text, the list of OpenType feature tag value is passed to the text layout engine to enable or disable font features. The tag is always a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a> of 4 ASCII characters. If it has more or less characters or contains characters outside the U+20 - U+7E codepoint range, the whole property is invalid.<br>\\n The value is a positive integer. The two keywords <code>on</code> and <code>off</code> are synonyms for <code>1</code> and <code>0</code> respectively. If no value is set, the default is <code>1</code>. For non-Boolean OpenType features (e.g. <a href=\\\"http://www.microsoft.com/typography/otspec/features_pt.htm#salt\\\" class=\\\"external\\\" title=\\\"http://www.microsoft.com/typography/otspec/features_pt.htm#salt\\\">stylistic alternates</a>), the value implies a particular glyph to be selected; for Boolean values, it is a switch.\"\n        }]\n    },\n    \"font-kerning\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-kerning\",\n        \"SUMMARY\": \"The <strong><code>font-kerning</code></strong> CSS property controls the usage of the kerning information; that is, it controls how letters are spaced. The kerning information is stored in the font, and if the font is <em>well-kerned</em>, this feature allows spacing between characters to be very similar, whatever the characters are.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"This keyword defers to the browser regarding whether to use kerning. When the font size is small, font kerning may look strange and browsers will disable it. This is the default value.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword requires kerning to be applied.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"This keyword prevents the browser from using the kerning information stored in the font.\"\n        }]\n    },\n    \"font-language-override\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-language-override\",\n        \"SUMMARY\": \"The <strong><code>font-language-override</code></strong> CSS property controls the usage of language-specific glyphs in a typeface.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword forces the browser to use glyphs defined for the given language in the font.\"\n        }, {\n            \"value\": \"<code>&lt;string&gt;</code>\",\n            \"description\": \"This keyword forces the browser to use the language defined by the string. The values are the <a href=\\\"http://www.microsoft.com/typography/otspec/languagetags.htm\\\" class=\\\"external\\\">OpenType language system</a> strings.\"\n        }]\n    },\n    \"font-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\",\n        \"SUMMARY\": \"The <strong><code>font-size</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property specifies the size of the font . Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the <code>em</code> and <code>ex</code> <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> units.\",\n        \"VALUES\": [{\n            \"value\": \"<code>xx-small, x-small, small, medium, large, x-large, xx-large</code>\",\n            \"description\": \"A set of absolute size keywords based on the user&apos;s default font size (which is <code>medium</code>). Similar to presentational HTML&apos;s <code>&lt;font size=&quot;1&quot;&gt;</code> through <code>&lt;font size=&quot;7&quot;&gt;</code> where the user&apos;s default font size is <code>&lt;font size=&quot;3&quot;&gt;</code>.\"\n        }, {\n            \"value\": \"<code>larger, smaller</code>\",\n            \"description\": \"Larger or smaller than the parent element&apos;s font size, by roughly the ratio used to separate the absolute size keywords above.\"\n        }, {\n            \"value\": \"<code>&lt;length-percentage&gt;</code><em> </em>\",\n            \"description\": \"\\n <p>A positive <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> value. When the units of <code>&lt;length&gt;</code> values are specified in <code>em</code> or <code>ex</code>, the size is defined relative to the size of the font on the parent element of the element in question. For example, 0.5em is half the font size of the parent of the current element. When the units are specified in <code>rem</code>, the size is defined relative to the size of the font used by the <a title=\\\"The HTML &lt;html&gt; element represents the root (top-level element) of an HTML document, so it is also referred to as the root element. All other elements must be descendants of this element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html\\\"><code>&lt;html&gt;</code></a> (root) element.</p>\\n\\n <p>&lt;percentage&gt; values refer to the parent element&apos;s font size.</p>\\n \"\n        }]\n    },\n    \"font-size-adjust\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust\",\n        \"SUMMARY\": \"The <strong><code>font-size-adjust</code></strong> CSS property specifies that font size should be chosen based on the height of lowercase letters rather than the height of capital letters. This is useful since the legibility of fonts, especially at small sizes, is determined more by the size of lowercase letters than by the size of capital letters.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Choose the size of the font based only on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font (historically the width of the capital &quot;M&quot;). Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a> property.\"\n        }, {\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"\\n <p>Choose the size of the font so that its lowercase letters (as determined by the x-height of the font) are the specified number times the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-size\\\" title=\\\"The font-size CSS property specifies the size of the font (historically the width of the capital &quot;M&quot;). Setting the font size may, in turn, change the size of other items, since it is used to compute the value of the em and ex &lt;length&gt; units.\\\"><code>font-size</code></a>.</p>\\n\\n <p>The number specified should generally be the aspect ratio (ratio of x-height to font size) of the first choice <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-family\\\" title=\\\"The font-family CSS property lets you specify a prioritized list of font family names and/or generic family names for the selected element. Values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer or that can be downloaded using a @font-face at-rule.\\\"><code>font-family</code></a>. This means that the first choice font, when available, will appear the same size in browsers, whether or not they support <code>font-size-adjust</code>.</p>\\n\\n <p><code>0</code> yields text of zero height (hidden text). Note that some old browsers, like Firefox prior version 40, treated <code>0</code> as <code>none</code>.</p>\\n \"\n        }]\n    },\n    \"font-smooth\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth\",\n        \"SUMMARY\": \"The <code>font-smooth</code> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property controls the application of anti-aliasing when fonts are rendered.\",\n        \"VALUES\": []\n    },\n    \"font-stretch\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch\",\n        \"SUMMARY\": \"The <strong><code>font-stretch</code></strong> property selects a normal, condensed, or expanded face from a font.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Specifies a normal font face.\"\n        }, {\n            \"value\": \"<code>semi-condensed</code>, <code>condensed</code>, <code>extra-condensed</code>, <code>ultra-condensed</code>\",\n            \"description\": \"Specifies a font face more condensed than normal, with ultra-condensed as the most condensed.\"\n        }, {\n            \"value\": \"<code>semi-expanded</code>, <code>expanded</code>, <code>extra-expanded</code>, <code>ultra-expanded</code>\",\n            \"description\": \"Specifies a font face more expanded than normal, with ultra-expanded as the most expanded.\"\n        }]\n    },\n    \"font-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-style\",\n        \"SUMMARY\": \"The<strong> <code>font-style</code></strong> CSS property lets you select <code>italic</code> or <code>oblique</code> faces within a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-family\\\" title=\\\"The font-family CSS property lets you specify a prioritized list of font family names and/or generic family names for the selected element. Values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer or that can be downloaded using a @font-face at-rule.\\\"><code>font-family</code></a>. <strong>Italic</strong> forms are generally cursive in nature, usually using less horizontal space than their unstyled counterparts, while <strong>oblique</strong> faces are usually just sloped versions of the regular face. Both italic and oblique faces are simulated by artificially sloping the glyphs of the regular face (see <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-synthesis\\\" title=\\\"The font-synthesis CSS property controls which missing typefaces, bold or italic, may be synthesized by the browser.\\\"><code>font-synthesis</code></a> for control over this).\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Selects a font that is classified as <code>normal</code> within a <a title=\\\"The font-family CSS property lets you specify a prioritized list of font family names and/or generic family names for the selected element. Values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer or that can be downloaded using a @font-face at-rule.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-family\\\"><code>font-family</code></a>.\"\n        }, {\n            \"value\": \"<code>italic</code>\",\n            \"description\": \"Selects a font that is labeled <code>italic</code>, or, if no italic version of the face is available, one labeled <code>oblique</code> is selected instead.\"\n        }, {\n            \"value\": \"<code>oblique</code>\",\n            \"description\": \"Selects a font that is labeled <code>oblique</code>, or, if no oblique version of the face is available, one labeled <code>italic</code> is selected instead.\"\n        }]\n    },\n    \"font-synthesis\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-synthesis\",\n        \"SUMMARY\": \"The <strong><code>font-synthesis</code></strong> CSS property controls which missing typefaces, bold or italic, may be synthesized by the browser.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"This keyword indicates that neither bold nor italic typeface must be synthesized.\"\n        }, {\n            \"value\": \"<code>weight</code>\",\n            \"description\": \"This keyword indicates that a bold typeface may be synthesized if needed.\"\n        }, {\n            \"value\": \"<code>style</code>\",\n            \"description\": \"This keyword indicates that an italic typeface may be synthesized if needed.\"\n        }]\n    },\n    \"font-variant\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant\",\n        \"SUMMARY\": \"The <strong>font-variant</strong> property acts as a shorthand for the longhand properties: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps\\\" title=\\\"The font-variant-caps CSS property controls the usage of alternate glyphs for capital letters. Scripts can have capital letter glyphs of different sizes, the normal uppercase glyphs, small capital glyphs, and petite capital glyphs. This property controls which alternate glyphs to use.\\\"><code>font-variant-caps</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric\\\" title=\\\"The font-variant-numeric CSS property controls the usage of alternate glyphs for numbers, fractions, and ordinal markers.\\\"><code>font-variant-numeric</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures\\\" title=\\\"The font-variant-ligatures CSS property controls which ligatures and contextual forms are used in textual content of the elements it applies to. This leads to more harmonized forms in the resulting text.\\\"><code>font-variant-ligatures</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-east-asian\\\" title=\\\"The font-variant-east-asian CSS property controls the usage of alternate glyphs for East Asian scripts, like Japanese and Chinese.\\\"><code>font-variant-east-asian</code></a>. You can also set the CSS Level 2 (Revision 1) values of <code>font-variant</code>, (that is, <code>normal</code> or <code>small-caps</code>), by using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font\\\" title=\\\"The font CSS property is either a shorthand property for setting font-style, font-variant, font-weight, font-size, line-height and font-family, or a way to set the element's font to a system font, using specific keywords.\\\"><code>font</code></a> shorthand.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Specifies a normal font face; each of the longhand properties has an initial value of normal. Longhand properties of <code>font-variant</code> are: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps\\\" title=\\\"The font-variant-caps CSS property controls the usage of alternate glyphs for capital letters. Scripts can have capital letter glyphs of different sizes, the normal uppercase glyphs, small capital glyphs, and petite capital glyphs. This property controls which alternate glyphs to use.\\\"><code>font-variant-caps</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric\\\" title=\\\"The font-variant-numeric CSS property controls the usage of alternate glyphs for numbers, fractions, and ordinal markers.\\\"><code>font-variant-numeric</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures\\\" title=\\\"The font-variant-ligatures CSS property controls which ligatures and contextual forms are used in textual content of the elements it applies to. This leads to more harmonized forms in the resulting text.\\\"><code>font-variant-ligatures</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-east-asian\\\" title=\\\"The font-variant-east-asian CSS property controls the usage of alternate glyphs for East Asian scripts, like Japanese and Chinese.\\\"><code>font-variant-east-asian</code></a>.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Sets the value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures\\\" title=\\\"The font-variant-ligatures CSS property controls which ligatures and contextual forms are used in textual content of the elements it applies to. This leads to more harmonized forms in the resulting text.\\\"><code>font-variant-ligatures</code></a> to <code>none</code> and the values of the other longhand property as <code>normal</code>, their initial value.\"\n        }, {\n            \"value\": \"<code>&lt;common-lig-values&gt;</code>, <code>&lt;discretionary-lig-values&gt;</code>, <code>&lt;historical-lig-values&gt;</code>, <code>&lt;contextual-alt-values&gt;</code>\",\n            \"description\": \"Specifies the keywords related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures\\\" title=\\\"The font-variant-ligatures CSS property controls which ligatures and contextual forms are used in textual content of the elements it applies to. This leads to more harmonized forms in the resulting text.\\\"><code>font-variant-ligatures</code></a> longhand property. The possible values are: <code>common-ligatures</code>, <code>no-common-ligatures</code>, <code>discretionary-ligatures</code>, <code>no-discretionary-ligatures</code>, <code>historical-ligatures</code>, <code>no-historical-ligatures</code>, <code>contextual</code>, and <code>no-contextual</code>.\"\n        }, {\n            \"value\": \"<code>stylistic()</code>,&#xA0; <code>historical-forms</code>, <code>styleset()</code>, <code>character-variant()</code>, <code>swash()</code>, <code>ornaments()</code>, <code>annotation()</code>\",\n            \"description\": \"Specifies the keywords and functions related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\\\" title=\\\"The font-variant-alternates CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in @font-feature-values.\\\"><code>font-variant-alternates</code></a> longhand property.\"\n        }, {\n            \"value\": \"<code>small-caps</code>, <code>all-small-caps</code>, <code>petite-caps</code>, <code>all-petite-caps</code>, <code>unicase</code>, <code>titling-caps</code>\",\n            \"description\": \"Specifies the keywords and functions related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps\\\" title=\\\"The font-variant-caps CSS property controls the usage of alternate glyphs for capital letters. Scripts can have capital letter glyphs of different sizes, the normal uppercase glyphs, small capital glyphs, and petite capital glyphs. This property controls which alternate glyphs to use.\\\"><code>font-variant-caps</code></a> longhand property.\"\n        }, {\n            \"value\": \"<code>&lt;numeric-figure-values&gt;</code>, <code>&lt;numeric-spacing-values&gt;</code>, <code>&lt;numeric-fraction-values&gt;</code>, <code>ordinal</code>, <code>slashed-zero</code>\",\n            \"description\": \"Specifies the keywords related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric\\\" title=\\\"The font-variant-numeric CSS property controls the usage of alternate glyphs for numbers, fractions, and ordinal markers.\\\"><code>font-variant-numeric</code></a> longhand property. The possible values are:&#xA0; <code>lining-nums</code>, <code>oldstyle-nums</code>, <code>proportional-nums</code>, <code>tabular-nums</code>, <code>diagonal-fractions</code>, <code>stacked-fractions</code>, <code>ordinal</code>, and <code>slashed-zero</code>.\"\n        }, {\n            \"value\": \"<code>&lt;east-asian-variant-values&gt;</code>, <code>&lt;east-asian-width-values&gt;</code>, <code>ruby</code>\",\n            \"description\": \"Specifies the keywords related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-east-asian\\\" title=\\\"The font-variant-east-asian CSS property controls the usage of alternate glyphs for East Asian scripts, like Japanese and Chinese.\\\"><code>font-variant-east-asian</code></a> longhand property. The possible values are: <code>jis78</code>, <code>jis83</code>, <code>jis90</code>, <code>jis04</code>, <code>simplified</code>, <code>traditional</code>, <code>full-width</code>, <code>proportional-width</code>, <code>ruby</code>.\"\n        }]\n    },\n    \"font-variant-alternates\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-alternates\",\n        \"SUMMARY\": \"The <strong><code>font-variant-alternates</code></strong> CSS property controls the usage of alternate glyphs. These alternate glyphs may be referenced by alternative names defined in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@font-feature-values\\\" title=\\\"The @font-feature-values CSS at-rule allows authors to use a common name in font-variant-alternates for feature activated differently in OpenType. It allows to simplify the CSS when using several fonts.\\\"><code>@font-feature-values</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword deactivates alternate glyphs.\"\n        }, {\n            \"value\": \"<code>historical-forms</code>\",\n            \"description\": \"This keyword enables historical forms &#x2014; glyphs that were common in the past but not today. It corresponds to the OpentType value <code>hist</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"stylistic()\\\"></a>stylistic()</code>\",\n            \"description\": \"This function enables stylistic alternates for individual characters. The parameter is a font-specific name mapped to a number. It corresponds to the OpenType value <code>salt</code>, like <code>salt 2</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"styleset()\\\"></a>styleset()</code>\",\n            \"description\": \"This function enables stylistic alternatives for sets of characters. The parameter is a font-specific name mapped to a number. It corresponds to the OpenType value <code>ssXY</code>, like <code>ss02</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"character-variant()\\\"></a>character-variant()</code>\",\n            \"description\": \"This function enables set of stylistic alternatives for characters. It is similar to <code>styleset()</code>, but doesn&apos;t create coherent glyphs for a set of characters; individual characters will have independent and not necessarily coherent styles. The parameter is a font-specific name mapped to a number. It corresponds to the OpenType value <code>cvXY</code>, like <code>cv02</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"swash()\\\"></a>swash()</code>\",\n            \"description\": \"This function enables <a href=\\\"http://en.wikipedia.org/wiki/Swash_%28typography%29\\\" class=\\\"external\\\">swash</a> glyphs. The parameter is a font-specific name mapped to a number. It corresponds to the OpenType values <code>swsh</code> and <code>cswh</code>, like <code>swsh 2</code> and <code>cswh 2</code>.\"\n        }, {\n            \"value\": \"<code><a name=\\\"ornaments()\\\"></a>ornaments()</code>\",\n            \"description\": \"This function enables ornaments, like <a href=\\\"http://en.wikipedia.org/wiki/Fleuron_%28typography%29\\\" class=\\\"external\\\">fleurons</a> and other dingbat glyphs. The parameter is a font-specific names mapped to a number. It corresponds to the OpenType value <code>ornm</code> like <code>ornm 2</code>.\\n <div class=\\\"note\\\"><strong>Note: </strong>in order to preserve text semantics, font designer should include ornaments that don&apos;t match Unicode dingbat characters as ornamental variants of the bullet character (U+2022). Well-formed fonts do that, but some existing fonts don&apos;t.</div>\\n \"\n        }, {\n            \"value\": \"<code><a name=\\\"annotation()\\\"></a>annotation()</code>\",\n            \"description\": \"This function enables annotations, like circled digits or inverted characters. The parameter is a font-specific name mapped to a number. It corresponds to the OpenType value <code>nalt</code>, like <code>nalt 2</code>.\"\n        }]\n    },\n    \"font-variant-caps\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps\",\n        \"SUMMARY\": \"The <strong><code>font-variant-caps</code></strong> CSS property controls the usage of alternate glyphs for capital letters. Scripts can have capital letter glyphs of different sizes, the normal uppercase glyphs, small capital glyphs, and petite capital glyphs. This property controls which alternate glyphs to use.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword leads to the deactivation of the use of such alternate glyphs.\"\n        }, {\n            \"value\": \"<code>small-caps</code>\",\n            \"description\": \"This keyword forces the use of small capitals letters for lower case characters. It corresponds to the OpenType value <code>smcp</code>; if the font doesn&apos;t support them, it synthesizes the glyphs.\"\n        }, {\n            \"value\": \"<code>all-small-caps</code>\",\n            \"description\": \"This keyword forces the use of small capital letters for lower case characters. It corresponds to the OpenType values <code>smcp</code> and <code>c2sc</code>; if the font doesn&apos;t support them, it synthesizes the glyphs.\"\n        }, {\n            \"value\": \"<code>petite-caps</code>\",\n            \"description\": \"This keyword forces the use of petite capital letters for lower case characters. It corresponds to the OpenType value <code>pcap</code>; if the font doesn&apos;t support them, small caps glyphs are used instead.\"\n        }, {\n            \"value\": \"<code>all-petite-caps</code>\",\n            \"description\": \"This keyword forces the use of petite capital letters for lower case characters. It corresponds to the OpenType values <code>pcap</code> and <code>c2pc</code>; if the font doesn&apos;t support them, small caps glyphs are used instead.\"\n        }, {\n            \"value\": \"<code>unicase</code>\",\n            \"description\": \"This keyword forces the use of small capital letters for upper case characters. It corresponds to the OpenType value <code>unic</code>; if the font doesn&apos;t support them, small caps glyphs are used for the upper case characters instead.\"\n        }, {\n            \"value\": \"<code>titling-caps</code>\",\n            \"description\": \"This keyword forces the use of special capitals for titling, for both lower and uppercase letters. Regular uppercase glyphs are usually designed to be rendered with lowercase glyphs: they tend to appear too bold when a long run of text use such glyphs. The special glyphs used here are designed not to produce this effect. This keyword corresponds to the OpenType value <code>titl</code>; if the font doesn&apos;t support it, the keyword has no visible action.\"\n        }]\n    },\n    \"font-variant-east-asian\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-east-asian\",\n        \"SUMMARY\": \"The <strong><code>font-variant-east-asian</code></strong> CSS property controls the usage of alternate glyphs for East Asian scripts, like Japanese and Chinese.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword leads to the deactivation of the use of such alternate glyphs.\"\n        }, {\n            \"value\": \"<code>ruby</code>\",\n            \"description\": \"This keyword forces the use of special glyphs for ruby characters. As these are usually smaller, font creators often designs specific forms, usually slightly bolder to improve the contrast. This keyword corresponds to the OpenType values <code>ruby</code>.\"\n        }, {\n            \"value\": \"<em>&lt;east-asian-variant-values</em>&gt;\",\n            \"description\": \"These values activates the figures defined in specific standard. Possible values are:\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <th>Keyword</th>\\n    <th>Standard defining the glyphs</th>\\n    <th>OpenType equivalent</th>\\n   </tr>\\n   <tr>\\n    <td><code>jis78</code></td>\\n    <td><a href=\\\"http://en.wikipedia.org/wiki/JIS_X_0208\\\" class=\\\"external\\\">JIS X 208 version 1978</a></td>\\n    <td><code>jp78</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>jis83</code></td>\\n    <td><a href=\\\"http://en.wikipedia.org/wiki/JIS_X_0208\\\" class=\\\"external\\\">JIS X 208 version 1983</a></td>\\n    <td><code>jp83</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>jis90</code></td>\\n    <td><a href=\\\"http://en.wikipedia.org/wiki/JIS_X_0208\\\" class=\\\"external\\\">JIS X 208 version 1990</a></td>\\n    <td><code>jp90</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>jis04</code></td>\\n    <td><a href=\\\"http://en.wikipedia.org/wiki/JIS_X_0208\\\" class=\\\"external\\\">JIS X 208 version 2004</a></td>\\n    <td><code>jp04</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>simplified</code></td>\\n    <td>None, use the simplified Chinese glyphs</td>\\n    <td><code>smpl</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>traditional</code></td>\\n    <td>None, use the traditional Chinese glyphs</td>\\n    <td><code>trad</code></td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<em>&lt;<em>east-asian-width-values</em></em>&gt;\",\n            \"description\": \"These values controls the sizing of figures used for East Asian characters. Two values are possible:\\n <ul>\\n  <li><code>proportional-width</code> activating the set of figures where numbers are not all of the same size. It corresponds to the OpenType values <code>pwid</code>.</li>\\n  <li><code>full-width</code> activating the set of figures where numbers are all of the same size, allowing them to be easily aligned like in tables. It corresponds to the OpenType values <code>fwid</code>.</li>\\n </ul>\\n \"\n        }]\n    },\n    \"font-variant-ligatures\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures\",\n        \"SUMMARY\": \"The <strong><code>font-variant-ligatures</code></strong> CSS property controls which <a title=\\\"ligatures: A ligature&#xA0;is a joining of two characters into one shape. For example, in French &quot;&#x153;&quot; is a ligature of &quot;oe&quot;.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/ligature\\\" class=\\\"glossaryLink\\\">ligatures</a> and <a title=\\\"The definition of that term (contextual forms) has not been written yet; please consider contributing it!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/contextual_forms\\\" class=\\\"glossaryLink\\\">contextual forms</a> are used in textual content of the elements it applies to. This leads to more harmonized forms in the resulting text.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword leads to the activation of the usual ligatures and contextual forms needed for correct rendering. The ligatures and forms activated depend on the font, language and kind of script. This is the default value.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"This keyword specifies that all ligatures and contextual forms are disabled, even common ones.\"\n        }, {\n            \"value\": \"&lt;<em>common-lig-values&gt;</em>\",\n            \"description\": \"These values control the most common ligatures, like for <code>fi</code>, <code>ffi</code>, <code>th</code> or similar. They correspond to the OpenType values <code>liga</code> and <code>clig</code>. Two values are possible:\\n <ul>\\n  <li><code>common-ligatures</code> activating these ligatures. Note that the keyword <code>normal</code> activates these ligatures.</li>\\n  <li><code>no-common-ligatures</code> deactivating these ligatures.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"&lt;<em>discretionary-lig-values</em>&gt;\",\n            \"description\": \"These values control specific ligatures, specific to the font and defined by the type designer. They correspond to the OpenType values <code>dlig</code>. Two values are possible:\\n <ul>\\n  <li><code>discretionary-ligatures</code> activating these ligatures.</li>\\n  <li><code>no-discretionary-ligatures</code> deactivating the ligatures. Note that the keyword <code>normal</code> usually deactivates these ligatures.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<em>&lt;historical-lig-values&gt;</em>\",\n            \"description\": \"These values control the ligatures used historically, in old books, like the German tz digraph being displayed &#xDF;. They correspond to the OpenType values <code>hlig</code>. Two values are possible:\\n <ul>\\n  <li><code>historical-ligatures</code> activating these ligatures.</li>\\n  <li><code>no-historical-ligatures</code> deactivating the ligatures. Note that the keyword <code>normal</code> usually deactivates these ligatures.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<em>&lt;contextual-alt-values&gt;</em>\",\n            \"description\": \"These values control whether letters adapt to their context&#x2014;that is, whether they adapt to the surrounding letters. These values correspond to the OpenType values <code>calt</code>. Two values are possible:\\n <ul>\\n  <li><code>contextual</code> specifies that the contextual alternates are to be used. Note that the keyword <code>normal</code> usually activates these ligatures too.</li>\\n  <li><code>no-contextual</code> prevents their use.</li>\\n </ul>\\n \"\n        }]\n    },\n    \"font-variant-numeric\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric\",\n        \"SUMMARY\": \"The <strong><code>font-variant-numeric</code></strong> CSS property controls the usage of alternate glyphs for numbers, fractions, and ordinal markers.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword leads to the deactivation of the use of such alternate glyphs.\"\n        }, {\n            \"value\": \"<code>ordinal</code>\",\n            \"description\": \"This keyword forces the use of special glyphs for the ordinal markers, like 1<sup>st</sup>, 2<sup>nd</sup>, 3<sup>rd</sup>, 4<sup>th</sup> in English or a 1<sup>a</sup> in Italian. It corresponds to the OpenType values <code>ordn</code>.\"\n        }, {\n            \"value\": \"<code>slashed-zero</code>\",\n            \"description\": \"This keyword forces the use of a 0 with a slash; this is useful when a clear distinction between O and 0 is needed. It corresponds to the OpenType values <code>zero</code>.\"\n        }, {\n            \"value\": \"<em>&lt;numeric-figure-values</em>&gt;\",\n            \"description\": \"These values control&#xA0;the figures used for numbers. Two values are possible:\\n <ul>\\n  <li><code>lining-nums</code> activating the set of figures where numbers are all lying on the baseline. It corresponds to the OpenType values <code>lnum</code>.</li>\\n  <li><code>oldstyle-nums</code> activating the set of figures where some numbers, like 3, 4, 7, 9 have descenders. It corresponds to the OpenType values <code>onum</code>.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<em>&lt;numeric-spacing-values</em>&gt;\",\n            \"description\": \"These values controls the sizing of figures used for numbers. Two values are possible:\\n <ul>\\n  <li><code>proportional-nums</code> activating the set of figures where numbers are not all of the same size. It corresponds to the OpenType values <code>pnum</code>.</li>\\n  <li><code>tabular-nums</code> activating the set of figures where numbers are all of the same size, allowing them to be easily aligned like in tables. It corresponds to the OpenType values <code>tnum</code>.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<em>&lt;numeric-fraction-values</em>&gt;\",\n            \"description\": \"These values controls the glyphs used to display fractions. Two values are possible:\\n <ul>\\n  <li><code>diagonal-fractions</code> activating the set of figures where the numerator and denominator are made smaller and separated by a slash. It corresponds to the OpenType values <code>frac</code>.</li>\\n  <li><code>stacked-fractions</code> activating the set of figures where the numerator and denominator are made smaller, stacked and separated by a horizontal line. It corresponds to the OpenType values <code>afrc</code>.</li>\\n </ul>\\n \"\n        }]\n    },\n    \"font-variant-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-position\",\n        \"SUMMARY\": \"The <strong><code>font-variant-position</code></strong> CSS property controls the usage of alternate glyphs of smaller size positioned as superscript or subscript regarding the baseline of the font, which is set unchanged. These glyphs are likely to be used in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub\\\" title=\\\"The HTML Subscript Element (&lt;sub&gt;) defines a span of text that should be displayed, for typographic reasons, lower, and often smaller, than the main span of text.\\\"><code>&lt;sub&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup\\\" title=\\\"The HTML Superscript Element (&lt;sup&gt;) defines a span of text that should be displayed, for typographic reasons, higher, and often smaller, than the main span of text.\\\"><code>&lt;sup&gt;</code></a> elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"This keyword leads to the deactivation of the use of such alternate glyphs.\"\n        }, {\n            \"value\": \"<code>sub</code>\",\n            \"description\": \"This keyword forces the use of subscript alternate glyphs. If, in a given run, one such glyph is not available for a character, the whole characters in the run is rendered using synthesized appropriate glyphs.\"\n        }, {\n            \"value\": \"<code>super</code>\",\n            \"description\": \"This keyword forces the use of superscript alternate glyphs. If, in a given run, one such glyph is not available for a character, the whole characters in the run is rendered using synthesized appropriate glyphs.\"\n        }]\n    },\n    \"font-variation-settings\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings\",\n        \"SUMMARY\": \"The <strong><code>font-variation-settings</code></strong> CSS property provides low-level control over OpenType or TrueType font typographic features, by specifying the four letter axis names of the features you want to vary, along with their variation values.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Text is laid out using default settings.\"\n        }, {\n            \"value\": \"<code>&lt;string&gt; &lt;number&gt;</code>\",\n            \"description\": \"When rendering text, the list of OpenType axis names is passed to the text layout engine to enable or disable font features. Each setting is always a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a> of 4 ASCII characters, followed by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> indicating the axis value.\"\n        }]\n    },\n    \"font-weight\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight\",\n        \"SUMMARY\": \"The <strong><code>font-weight</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies the weight or boldness of the font. Some fonts are only available in <code>normal</code> and <code>bold</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Normal font weight. Same as <code>400</code>.\"\n        }, {\n            \"value\": \"<code>bold</code>\",\n            \"description\": \"Bold font weight. Same as <code>700</code>.\"\n        }, {\n            \"value\": \"<code>lighter</code>\",\n            \"description\": \"One font weight lighter than the parent element (among the available weights of the font).\"\n        }, {\n            \"value\": \"<code>bolder</code>\",\n            \"description\": \"One font weight darker than the parent element (among the available weights of the font).\"\n        }, {\n            \"value\": \"<code>100</code>, <code>200</code>, <code>300</code>, <code>400</code>, <code>500</code>, <code>600</code>, <code>700</code>, <code>800</code>, <code>900</code>\",\n            \"description\": \"Numeric font weights for fonts that provide more than just normal and bold.\"\n        }, {\n            \"value\": \"<code>100</code>\",\n            \"description\": \"Thin (Hairline)\"\n        }, {\n            \"value\": \"<code>200</code>\",\n            \"description\": \"Extra Light (Ultra Light)\"\n        }, {\n            \"value\": \"<code>300</code>\",\n            \"description\": \"Light\"\n        }, {\n            \"value\": \"<code>400</code>\",\n            \"description\": \"Normal\"\n        }, {\n            \"value\": \"<code>500</code>\",\n            \"description\": \"Medium\"\n        }, {\n            \"value\": \"<code>600</code>\",\n            \"description\": \"Semi Bold (Demi Bold)\"\n        }, {\n            \"value\": \"<code>700</code>\",\n            \"description\": \"Bold\"\n        }, {\n            \"value\": \"<code>800</code>\",\n            \"description\": \"Extra Bold (Ultra Bold)\"\n        }, {\n            \"value\": \"<code>900</code>\",\n            \"description\": \"Black (Heavy)\"\n        }]\n    },\n    \"grid\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid\",\n        \"SUMMARY\": \"The <strong><code>grid</code></strong> CSS property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property that sets all of the explicit grid properties (<a title=\\\"The grid-template-rows CSS property defines the line names and track sizing functions of the grid's rows.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\\\"><code>grid-template-rows</code></a>, <a title=\\\"The grid-template-columns CSS property defines the line names and track sizing functions of the grid's columns.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\\\"><code>grid-template-columns</code></a>, and <a title=\\\"The grid-template-areas CSS property specifies named grid areas.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas\\\"><code>grid-template-areas</code></a>), all the implicit grid properties (<a title=\\\"The grid-auto-rows CSS property specifies the size of an implicitly-created grid row track.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows\\\"><code>grid-auto-rows</code></a>, <a title=\\\"The grid-auto-columns CSS property specifies the size of an implicitly-created grid column track.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns\\\"><code>grid-auto-columns</code></a>, and <a title=\\\"The grid-auto-flow CSS property controls how the auto-placement algorithm works, specifying exactly how auto-placed items get flowed into the grid.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow\\\"><code>grid-auto-flow</code></a>), and the gutter properties (<a title=\\\"The grid-column-gap CSS property specifies the gutter between grid columns.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-gap\\\"><code>grid-column-gap</code></a> and <a title=\\\"The grid-row-gap CSS property specifies the gutter between grid rows.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-gap\\\"><code>grid-row-gap</code></a>) in a single declaration.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;grid-template&apos;&gt;</code>\",\n            \"description\": \"Defines the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template\\\" title=\\\"The grid-template CSS property is a shorthand property for defining grid columns, rows and areas.\\\"><code>grid-template</code></a> including <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\\\" title=\\\"The grid-template-columns CSS property defines the line names and track sizing functions of the grid columns.\\\"><code>grid-template-columns</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\\\" title=\\\"The grid-template-rows CSS property defines the line names and track sizing functions of the grid rows.\\\"><code>grid-template-rows</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas\\\" title=\\\"The grid-template-areas CSS property specifies named grid areas.\\\"><code>grid-template-areas</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;grid-template-rows&apos;&gt; / [ auto-flow &amp;&amp; dense? ] &lt;&apos;grid-auto-columns&apos;&gt;?</code>\",\n            \"description\": \"Sets up an auto-flow by setting the row tracks explicitly via the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\\\" title=\\\"The grid-template-rows CSS property defines the line names and track sizing functions of the grid rows.\\\"><code>grid-template-rows</code></a> property (and the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\\\" title=\\\"The grid-template-columns CSS property defines the line names and track sizing functions of the grid columns.\\\"><code>grid-template-columns</code></a> property to <code>none</code>) and specifying how to auto-repeat the column tracks via <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns\\\" title=\\\"The grid-auto-columns CSS property specifies the size of an implicitly-created grid column track.\\\"><code>grid-auto-columns</code></a> (and setting <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows\\\" title=\\\"The grid-auto-rows CSS property specifies the size of an implicitly-created grid row track.\\\"><code>grid-auto-rows</code></a> to <code>auto</code>). <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow\\\" title=\\\"The grid-auto-flow CSS property controls how the auto-placement algorithm works, specifying exactly how auto-placed items get flowed into the grid.\\\"><code>grid-auto-flow</code></a> is also set to <code>column</code> accordingly, with <code>dense</code> if it&#x2019;s specified.\\n <p>All other <code>grid</code> sub-properties are reset to their initial values.</p>\\n \"\n        }, {\n            \"value\": \"<code>[ auto-flow &amp;&amp; dense? ] &lt;&apos;grid-auto-rows&apos;&gt;? / &lt;&apos;grid-template-columns&apos;&gt;</code>\",\n            \"description\": \"Sets up an auto-flow by setting the column tracks explicitly via the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\\\" title=\\\"The grid-template-columns CSS property defines the line names and track sizing functions of the grid columns.\\\"><code>grid-template-columns</code></a> property (and the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\\\" title=\\\"The grid-template-rows CSS property defines the line names and track sizing functions of the grid rows.\\\"><code>grid-template-rows</code></a> property to <code>none</code>) and specifying how to auto-repeat the row tracks via <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows\\\" title=\\\"The grid-auto-rows CSS property specifies the size of an implicitly-created grid row track.\\\"><code>grid-auto-rows</code></a> (and setting <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns\\\" title=\\\"The grid-auto-columns CSS property specifies the size of an implicitly-created grid column track.\\\"><code>grid-auto-columns</code></a> to <code>auto</code>). <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow\\\" title=\\\"The grid-auto-flow CSS property controls how the auto-placement algorithm works, specifying exactly how auto-placed items get flowed into the grid.\\\"><code>grid-auto-flow</code></a> is also set to <code>row</code> accordingly, with <code>dense</code> if it&#x2019;s specified.\\n <p>All other <code>grid</code> sub-properties are reset to their initial values.</p>\\n \"\n        }]\n    },\n    \"grid-area\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-area\",\n        \"SUMMARY\": \"The <strong><code>grid-area</code></strong> CSS property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start\\\" title=\\\"The grid-row-start CSS property specifies a grid item&#x2019;s start position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start edge of its grid area.\\\"><code>grid-row-start</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-end\\\" title=\\\"The grid-row-end CSS property specifies a grid item&#x2019;s end position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-end edge of its grid area.\\\"><code>grid-row-end</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-start\\\" title=\\\"The grid-column-start CSS property specifies a grid item&#x2019;s start position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-start edge of its grid area.\\\"><code>grid-column-start</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-end\\\" title=\\\"The grid-column-end CSS property specifies a grid item&#x2019;s end position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-end edge of its grid area.\\\"><code>grid-column-end</code></a>, specifying a grid item’s size and location within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the edges of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;<code>&lt;custom-ident&gt;-start</code>&apos;/&apos;<code>&lt;custom-ident&gt;-end</code>&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-area: foo;</code> will choose the start/end edge of that named grid area (unless another line named <code>foo-start</code>/<code>foo-end</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the <em>n</em>th grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\" title=\\\"The &lt;custom-ident&gt; CSS data value denotes an arbitrary user-defined string used as an identifier. It is case-sensitive and in each context, several values are excluded to prevent misinterpretations.\\\"><code>&lt;custom-ident&gt;</code></a>, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement such that the corresponding edge of the grid item&#x2019;s grid area is <em>n</em> lines from the opposite edge.\\n <p>If a name is given as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\" title=\\\"The &lt;custom-ident&gt; CSS data value denotes an arbitrary user-defined string used as an identifier. It is case-sensitive and in each context, several values are excluded to prevent misinterpretations.\\\"><code>&lt;custom-ident&gt;</code></a>, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n \"\n        }]\n    },\n    \"grid-auto-columns\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns\",\n        \"SUMMARY\": \"The <strong><code>grid-auto-columns</code></strong> CSS property specifies the size of an implicitly-created grid column track.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a non-negative length.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a non-negative <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;percentage&gt;</code></a> value relative to the block size of the grid container. If the block size of the grid container is indefinite, the percentage value is treated like <code>auto</code>.\"\n        }, {\n            \"value\": \"<code>&lt;flex&gt;</code>\",\n            \"description\": \"Is a non-negative dimension with the unit <code>fr</code> specifying the track&#x2019;s flex factor. Each <code>&lt;flex&gt;</code>-sized track takes a share of the remaining space in proportion to its flex factor.\\n <p>When appearing outside a <code>minmax()</code> notation, it implies an automatic minimum (i.e. <code>minmax(auto, &lt;flex&gt;)</code>).</p>\\n \"\n        }, {\n            \"value\": \"<code>max-content</code>\",\n            \"description\": \"Is a keyword representing the largest maximal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code>min-content</code>\",\n            \"description\": \"Is a keyword representing the largest minimal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code>minmax(min, max)</code>\",\n            \"description\": \"Is a functional notation that defines a size range greater than or equal to <em>min</em> and less than or equal to <em>max</em>. If <em>max</em> is smaller than <em>min</em>, then <em>max</em> is ignored and the function is treated as <em>min</em>. As a maximum, a <code>&lt;flex&gt;</code> value sets the track&#x2019;s flex factor. As a minimum, it is treated as zero (or minimal content, if the grid container is sized under a minimal content constraint).\"\n        }, {\n            \"value\": \"<code>fit-content(min, max)</code>\",\n            \"description\": \"Represents the formula <code>min(max-content, max(auto, <var>argument</var>))</code>, which is calculated similar to <code>auto</code> (i.e. <code>minmax(auto, max-content)</code>), except that the track size is clamped at <var>argument</var> if it is greater than the <code>auto</code> minimum.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that is identical to maximal content if it&apos;s a maximum. As a minimum it represents the largest minimum size (as specified by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"The min-height property is used to set the minimum height of a given element. It prevents the used value of the height property from becoming smaller than the value specified for min-height.\\\"><code>min-height</code></a>) of the grid items occupying the grid track.\"\n        }]\n    },\n    \"grid-auto-flow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow\",\n        \"SUMMARY\": \"The <code>grid-auto-flow</code> CSS property controls how the auto-placement algorithm works, specifying exactly how auto-placed items get flowed into the grid.\",\n        \"VALUES\": [{\n            \"value\": \"<code>row</code>\",\n            \"description\": \"Is a keyword specifying that the auto-placement algorithm places items by filling each row in turn, adding new rows as necessary. If neither <code>row</code> nor <code>column</code> is provided, <code>row</code> is assumed.\"\n        }, {\n            \"value\": \"<code>column</code>\",\n            \"description\": \"Is a keyword specifying that the auto-placement algorithm places items by filling each column in turn, adding new columns as necessary.\"\n        }, {\n            \"value\": \"<code>dense</code>\",\n            \"description\": \"Is a keyword specifying that the auto-placement algorithm uses a &#x201C;dense&#x201D; packing algorithm, which attempts to fill in holes earlier in the grid if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items.\\n <p>If omitted, a &#x201C;sparse&#x201D; algorithm is used, where the placement algorithm only ever moves &#x201C;forward&#x201D; in the grid when placing items, never backtracking to fill holes. This ensures that all of the auto-placed items appear &#x201C;in order&#x201D;, even if this leaves holes that could have been filled by later items.</p>\\n \"\n        }]\n    },\n    \"grid-auto-rows\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows\",\n        \"SUMMARY\": \"The <code>grid-auto-rows</code> CSS property specifies the size of an implicitly-created grid row track.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a non-negative length.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a non-negative <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;percentage&gt;</code></a> value relative to the block size of the grid container. If the block size of the grid container is indefinite, the percentage value is treated like <code>auto</code>.\"\n        }, {\n            \"value\": \"<code>&lt;flex&gt;</code>\",\n            \"description\": \"Is a non-negative dimension with the unit <code>fr</code> specifying the track&#x2019;s flex factor. Each <code>&lt;flex&gt;</code>-sized track takes a share of the remaining space in proportion to its flex factor.\\n <p>When appearing outside a <code>minmax()</code> notation, it implies an automatic minimum (i.e. <code>minmax(auto, &lt;flex&gt;)</code>).</p>\\n \"\n        }, {\n            \"value\": \"<code>max-content</code>\",\n            \"description\": \"Is a keyword representing the largest maximal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code>min-content</code>\",\n            \"description\": \"Is a keyword representing the largest minimal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code>minmax(min, max)</code>\",\n            \"description\": \"Is a functional notation that defines a size range greater than or equal to <em>min</em> and less than or equal to <em>max</em>. If <em>max</em> is smaller than <em>min</em>, then <em>max</em> is ignored and the function is treated as <em>min</em>. As a maximum, a <code>&lt;flex&gt;</code> value sets the track&#x2019;s flex factor. As a minimum, it is treated as zero (or minimal content, if the grid container is sized under a minimal content constraint).\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that is identical to maximal content if it&apos;s a maximum. As a minimum it represents the largest minimum size (as specified by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"The min-height property is used to set the minimum height of a given element. It prevents the used value of the height property from becoming smaller than the value specified for min-height.\\\"><code>min-height</code></a>) of the grid items occupying the grid track.\"\n        }]\n    },\n    \"grid-column\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column\",\n        \"SUMMARY\": \"The <code>grid-column</code> CSS property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-start\\\" title=\\\"The grid-column-start CSS property specifies a grid item&#x2019;s start position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-start edge of its grid area.\\\"><code>grid-column-start</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-end\\\" title=\\\"The grid-column-end CSS property specifies a grid item&#x2019;s end position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-end edge of its grid area.\\\"><code>grid-column-end</code></a> specifying a grid item’s size and location within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start and inline-end edge of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement, an automatic span, or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;&lt;custom-ident&gt;-start&apos;/&apos;&lt;custom-ident&gt;-end&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-column: foo;</code> will choose the start/end edge of that named grid area (unless another line named <code>foo-start</code>/<code>foo-end</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the nth grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement such that the corresponding edge of the grid item&#x2019;s grid area is n lines from the opposite edge.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the &lt;integer&gt; is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n \"\n        }]\n    },\n    \"grid-column-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-end\",\n        \"SUMMARY\": \"The <code>grid-column-end</code> CSS property specifies a grid item’s end position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-end edge of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement, an automatic span, or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;&lt;custom-ident&gt;-end&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-column-end: foo;</code> will choose the end edge of that named grid area (unless another line named <code>foo-end</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the nth grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement such that the column end edge of the grid item&#x2019;s grid area is n lines from the start edge.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the &lt;integer&gt; is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n\\n <p>The <code>&lt;custom-ident&gt;</code> cannot take the <code>span</code> value.</p>\\n \"\n        }]\n    },\n    \"grid-column-gap\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-gap\",\n        \"SUMMARY\": \"The <code>grid-column-gap</code> CSS property specifies the gutter between grid columns.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Is the width of the gutter separating the grid columns. <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> values are relative to the dimension of the element.\"\n        }]\n    },\n    \"grid-column-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-start\",\n        \"SUMMARY\": \"The <code>grid-column-start</code> CSS property specifies a grid item’s start position within the grid column by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the block-start edge of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement, an automatic span, or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;&lt;custom-ident&gt;-start&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-column-start: foo;</code> will choose the start edge of that named grid area (unless another line named <code>foo-start</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the nth grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement, such that the column start edge of the grid item&#x2019;s grid area is n lines from the end edge.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the &lt;integer&gt; is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n\\n <p>The <code>&lt;custom-ident&gt;</code> cannot take the <code>span</code> value.</p>\\n \"\n        }]\n    },\n    \"grid-gap\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-gap\",\n        \"SUMMARY\": \"The <code>grid-gap</code> CSS property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-gap\\\" title=\\\"The grid-row-gap CSS property specifies the gutter between grid rows.\\\"><code>grid-row-gap</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column-gap\\\" title=\\\"The grid-column-gap CSS property specifies the gutter between grid columns.\\\"><code>grid-column-gap</code></a> specifying the gutters between grid rows and columns.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is the width of the gutter separating the grid lines.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is the width of the gutter separating the grid lines, relative to the dimension of the element.\"\n        }]\n    },\n    \"grid-row\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row\",\n        \"SUMMARY\": \"The <code>grid-row</code> CSS property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property for <a title=\\\"The grid-row-start CSS property specifies a grid item&#x2019;s start position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start edge of its grid area.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start\\\"><code>grid-row-start</code></a> and <a title=\\\"The grid-row-end CSS property specifies a grid item&#x2019;s end position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-end edge of its grid area.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-end\\\"><code>grid-row-end</code></a> specifying a grid item’s size and location within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start and inline-end edge of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement, an automatic span, or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;&lt;custom-ident&gt;-start&apos;/&apos;&lt;custom-ident&gt;-end&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-row: foo;</code> will choose the start/end edge of that named grid area (unless another line named <code>foo-start</code>/<code>foo-end</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the nth grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement such that the corresponding edge of the grid item&#x2019;s grid area is n lines from the opposite edge.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the &lt;integer&gt; is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n \"\n        }]\n    },\n    \"grid-row-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-end\",\n        \"SUMMARY\": \"The <code>grid-row-end</code> CSS property specifies a grid item’s end position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-end edge of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement, an automatic span, or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;&lt;custom-ident&gt;-end&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-row-end: foo;</code> will choose the end edge of that named grid area (unless another line named <code>foo-end</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n\\n <p>The <code>&lt;custom-ident&gt;</code> cannot take the <code>span</code> value.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the nth grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement such that the row end edge of the grid item&#x2019;s grid area is n lines from the start edge.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the &lt;integer&gt; is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n \"\n        }]\n    },\n    \"grid-row-gap\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-gap\",\n        \"SUMMARY\": \"The <code>grid-row-gap</code> CSS property specifies the gutter between grid rows.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length-percentage&gt;</code>\",\n            \"description\": \"Is the width of the gutter separating the grid rows. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> values are relative to the dimension of the element.\"\n        }]\n    },\n    \"grid-row-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start\",\n        \"SUMMARY\": \"The <code>grid-row-start</code> CSS property specifies a grid item’s start position within the grid row by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the inline-start edge of its grid area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the property contributes nothing to the grid item&#x2019;s placement, indicating auto-placement, an automatic span, or a default span of <code>1</code>.\"\n        }, {\n            \"value\": \"<code>&lt;custom-ident&gt;</code>\",\n            \"description\": \"If there is a named line with the name &apos;&lt;custom-ident&gt;-start&apos;, it contributes the first such line to the grid item&#x2019;s placement.\\n <p class=\\\"note\\\"><strong>Note:</strong> Named grid areas automatically generate implicit named lines of this form, so specifying <code>grid-row-start: foo;</code> will choose the start edge of that named grid area (unless another line named <code>foo-start</code> was explicitly specified before it).</p>\\n\\n <p>Otherwise, this is treated as if the integer <code>1</code> had been specified along with the <code>&lt;custom-ident&gt;</code>.</p>\\n \"\n        }, {\n            \"value\": \"<code>&lt;integer&gt; &amp;&amp; &lt;custom-ident&gt;?</code>\",\n            \"description\": \"Contributes the nth grid line to the grid item&#x2019;s placement. If a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines are assumed to have that name for the purpose of finding this position.</p>\\n\\n <p>An <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a> value of <code>0</code> is invalid.</p>\\n \"\n        }, {\n            \"value\": \"<code>span &amp;&amp; [ &lt;integer&gt; || &lt;custom-ident&gt; ]</code>\",\n            \"description\": \"Contributes a grid span to the grid item&#x2019;s placement such that the row start edge of the grid item&#x2019;s grid area is n lines from the end edge.\\n <p>If a name is given as a &lt;custom-ident&gt;, only lines with that name are counted. If not enough lines with that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search direction are assumed to have that name for the purpose of counting this span.</p>\\n\\n <p>If the &lt;integer&gt; is omitted, it defaults to <code>1</code>. Negative integers or 0 are invalid.</p>\\n\\n <p>The <code>&lt;custom-ident&gt;</code> cannot take the <code>span</code> value.</p>\\n \"\n        }]\n    },\n    \"grid-template\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template\",\n        \"SUMMARY\": \"The <code>grid-template</code> CSS property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property for defining grid columns, rows and areas.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword that sets&#xA0;all three longhand properties to <code>none</code>, meaning there is no explicit grid. There are no named grid areas. Rows and columns will be implicitly generated; their size will be determined by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows\\\" title=\\\"The grid-auto-rows CSS property specifies the size of an implicitly-created grid row track.\\\"><code>grid-auto-rows</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns\\\" title=\\\"The grid-auto-columns CSS property specifies the size of an implicitly-created grid column track.\\\"><code>grid-auto-columns</code></a> properties.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;grid-template-rows&apos;&gt; / &lt;&apos;grid-template-columns&apos;&gt;</code>\",\n            \"description\": \"Sets <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\\\" title=\\\"The grid-template-rows CSS property defines the line names and track sizing functions of the grid rows.\\\"><code>grid-template-rows</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\\\" title=\\\"The grid-template-columns CSS property defines the line names and track sizing functions of the grid columns.\\\"><code>grid-template-columns</code></a> to the specified values, and sets <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas\\\" title=\\\"The grid-template-areas CSS property specifies named grid areas.\\\"><code>grid-template-areas</code></a> to <code>none</code>.\"\n        }, {\n            \"value\": \"<code>[ &lt;line-names&gt;? &lt;string&gt; &lt;track-size&gt;? &lt;line-names&gt;? ]+ [ / &lt;explicit-track-list&gt; ]?</code>\",\n            \"description\": \"Sets <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas\\\" title=\\\"The grid-template-areas CSS property specifies named grid areas.\\\"><code>grid-template-areas</code></a> to the strings listed, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\\\" title=\\\"The grid-template-rows CSS property defines the line names and track sizing functions of the grid rows.\\\"><code>grid-template-rows</code></a> to the track sizes following each string (filling in <code>auto</code> for any missing sizes), and splicing in the named lines defined before/after each size, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\\\" title=\\\"The grid-template-columns CSS property defines the line names and track sizing functions of the grid columns.\\\"><code>grid-template-columns</code></a> to the track listing specified after the slash (or <code>none</code>, if not specified).<br>\\n &#xA0;\\n <p class=\\\"note\\\">Note: The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/repeat()\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>repeat()</code></a> function isn&#x2019;t allowed in these track listings, as the tracks are intended to visually line up one-to-one with the rows/columns in the &#x201C;ASCII art&#x201D;.</p>\\n \"\n        }]\n    },\n    \"grid-template-areas\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas\",\n        \"SUMMARY\": \"The <code>grid-template-areas</code> CSS property specifies named grid areas.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The grid container doesn&#x2019;t define any named grid areas.\"\n        }, {\n            \"value\": \"<code>&lt;string&gt;+</code>\",\n            \"description\": \"A row is created for every separate string listed, and a column is created for each cell in the string. Multiple named cell tokens within and between rows create a single named grid area that spans the corresponding grid cells. Unless those cells&#xA0;form a rectangle, the declaration is invalid.\"\n        }]\n    },\n    \"grid-template-columns\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\",\n        \"SUMMARY\": \"The <code>grid-template-columns</code> CSS property defines the line names and track sizing functions of the grid's columns.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword meaning that there is no explicit grid. Any columns will be implicitly generated and their size will be determined by the <a title=\\\"The grid-auto-columns CSS property specifies the size of an implicitly-created grid column track.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns\\\"><code>grid-auto-columns</code></a> property.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a non-negative length.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a non-negative <a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> value relative to the inline size of the grid container. If the size of the grid container depends on the size of its tracks, then the percentage must be treated as <code>auto</code>.<br>\\n The intrinsic size contributions of the track may be adjusted to the size of the grid container and increase the final size of the track by the minimum amount that would result in honoring the percentage.\"\n        }, {\n            \"value\": \"<code>&lt;flex&gt;</code>\",\n            \"description\": \"Is a non-negative dimension with the unit <code>fr</code> specifying the track&#x2019;s flex factor. Each <code>&lt;flex&gt;</code>-sized track takes a share of the remaining space in proportion to its flex factor.\\n <p>When appearing outside a <code>minmax()</code> notation, it implies an automatic minimum (i.e. <code>minmax(auto, &lt;flex&gt;)</code>).</p>\\n \"\n        }, {\n            \"value\": \"<code>max-content</code>\",\n            \"description\": \"Is a keyword representing the largest maximal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code>min-content</code>\",\n            \"description\": \"Is a keyword representing the largest minimal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code><a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/minmax\\\"><code>minmax(min, max)</code></a></code>\",\n            \"description\": \"Is a functional notation that defines a size range greater than or equal to <em>min</em> and less than or equal to <em>max</em>. If <em>max</em> is smaller than <em>min</em>, then <em>max</em> is ignored and the function is treated as <em>min</em>. As a maximum, a <code>&lt;flex&gt;</code> value sets the track&#x2019;s flex factor. It is invalid as a minimum.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that is identical to maximal content if it&apos;s a maximum. As a minimum it represents the largest minimum size (as specified by <a title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\"><code>min-width</code></a>/<a title=\\\"The min-height property is used to set the minimum height of a given element. It prevents the used value of the height property from becoming smaller than the value specified for min-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\"><code>min-height</code></a>) of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"\\n <p class=\\\"note\\\">Note: <code>auto</code> track sizes (and only <code>auto</code> track sizes) can be stretched by the <a title=\\\"The CSS align-content property defines how the browser distributes space between and around content items along the main-axis of their container.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-content\\\"><code>align-content</code></a> and <a title=\\\"The CSS justify-content property defines how the browser distributes space between and around content items along the main axis of their container.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content\\\"><code>justify-content</code></a> properties.</p>\\n \",\n            \"description\": \"<code><a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content\\\"><code>fit-content( [ &lt;length&gt; | &lt;percentage&gt; ] )</code></a></code>\"\n        }, {\n            \"value\": \"Represents the formula <code>min(max-content, max(auto, <var>argument</var>))</code>, which is calculated similar to <code>auto</code> (i.e. <code>minmax(auto, max-content)</code>), except that the track size is clamped at <var>argument</var> if it is greater than the <code>auto</code> minimum.\",\n            \"description\": \"<a title=\\\"The documentation about this has not yet been written; please consider contributing!\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/repeat\\\"><code>repeat( [ &lt;positive-integer&gt; | auto-fill | auto-fit ] , &lt;track-list&gt; )</code></a>\"\n        }]\n    },\n    \"grid-template-rows\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows\",\n        \"SUMMARY\": \"The <code>grid-template-rows</code> CSS property defines the line names and track sizing functions of the grid's rows.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword meaning that there is no explicit grid. Any rows will be implicitly generated and their size will be determined by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows\\\" title=\\\"The grid-auto-rows CSS property specifies the size of an implicitly-created grid row track.\\\"><code>grid-auto-rows</code></a> property.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a non-negative length.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a non-negative <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;percentage&gt;</code></a> value relative to the block size of the grid container. If the size of the grid container depends on the size of its tracks, then the percentage must be treated as <code>auto</code>.<br>\\n The intrinsic size contributions of the track may be adjusted to the size of the grid container and increase the final size of the track by the minimum amount that would result in honoring the percentage.\"\n        }, {\n            \"value\": \"<code>&lt;flex&gt;</code>\",\n            \"description\": \"Is a non-negative dimension with the unit <code>fr</code> specifying the track&#x2019;s flex factor. Each <code>&lt;flex&gt;</code>-sized track takes a share of the remaining space in proportion to its flex factor.\\n <p>When appearing outside a <code>minmax()</code> notation, it implies an automatic minimum (i.e. <code>minmax(auto, &lt;flex&gt;)</code>).</p>\\n \"\n        }, {\n            \"value\": \"<code>max-content</code>\",\n            \"description\": \"Is a keyword representing the largest maximal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<code>min-content</code>\",\n            \"description\": \"Is a keyword representing the largest minimal content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/minmax\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>minmax(min, max)</code></a>\",\n            \"description\": \"Is a functional notation that defines a size range greater than or equal to <em>min</em> and less than or equal to <em>max</em>. If <em>max</em> is smaller than <em>min</em>, then <em>max</em> is ignored and the function is treated as <em>min</em>. As a maximum, a <code>&lt;flex&gt;</code> value sets the track&#x2019;s flex factor. It is invalid as a minimum.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that is identical to maximal content if it&apos;s a maximum. As a minimum it represents the largest minimum size (as specified by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"The min-height property is used to set the minimum height of a given element. It prevents the used value of the height property from becoming smaller than the value specified for min-height.\\\"><code>min-height</code></a>) of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"\\n <p class=\\\"note\\\">Note: <code>auto</code> track sizes (and only <code>auto</code> track sizes) can be stretched by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-content\\\" title=\\\"The CSS align-content property defines how the browser distributes space between and around content items along the main-axis of their container.\\\"><code>align-content</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content\\\" title=\\\"The CSS justify-content property defines how the browser distributes space between and around content items along the main axis of their container.\\\"><code>justify-content</code></a> properties.</p>\\n \",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>fit-content( [ &lt;length&gt; | &lt;percentage&gt; ] )</code></a>\"\n        }, {\n            \"value\": \"Represents the formula <code>min(max-content, max(auto, <var>argument</var>))</code>, which is calculated similar to <code>auto</code> (i.e. <code>minmax(auto, max-content)</code>), except that the track size is clamped at <var>argument</var> if it is greater than the <code>auto</code> minimum.\",\n            \"description\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/repeat\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>repeat( [ &lt;positive-integer&gt; | auto-fill | auto-fit ] , &lt;track-list&gt; )</code></a>\"\n        }]\n    },\n    \"height\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/height\",\n        \"SUMMARY\": \"The <strong><code>height</code></strong> CSS property specifies the height of the content area of an element. The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/box_model#content\\\">content area</a> is <em>inside</em> the padding, border, and margin of the element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"See <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Specified as a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> of containing block&apos;s height.\"\n        }, {\n            \"value\": \"<code>border-box&#xA0;</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If present, the preceding <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> is applied to the element&apos;s border box.\"\n        }, {\n            \"value\": \"<code>content-box</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If present, the preceding <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> is applied to the element&apos;s content box.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The browser will calculate and select a height for the specified element.\"\n        }, {\n            \"value\": \"fill <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Use the&#xA0;<code>fill-available</code>&#xA0;inline size&#xA0;or&#xA0;<code>fill-available</code>&#xA0;block size, as appropriate to the writing mode.\"\n        }, {\n            \"value\": \"<code>max-content</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic preferred height.\"\n        }, {\n            \"value\": \"<code>min-content</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic minimum height.\"\n        }, {\n            \"value\": \"<code>available</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The containing block height minus vertical margin, border and padding.\"\n        }, {\n            \"value\": \"<code>fit-content</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The larger of:\\n <ul>\\n  <li>the intrinsic minimum&#xA0;height</li>\\n  <li>the smaller of the intrinsic preferred height and the available height</li>\\n </ul>\\n \"\n        }]\n    },\n    \"hyphens\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/hyphens\",\n        \"SUMMARY\": \"The <strong><code>hyphens</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property tells the browser how to hyphenate words when line-wrapping. You can prevent hyphenation entirely, control when the browser should hyphenate, or let the browser control when to hyphenate.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Words are not broken at line breaks, even if characters inside the words suggest line break points. Lines will only wrap at whitespace.\"\n        }, {\n            \"value\": \"<code>manual</code>\",\n            \"description\": \"Words are broken for line-wrapping only where characters inside the word suggest line break opportunities. See <a href=\\\"#Suggesting_line_break_opportunities\\\">Suggesting line break opportunities</a> for details.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The browser is free to automatically break words at appropriate hyphenation points, following whatever rules it chooses to use. Suggested line break opportunities, as covered in <a href=\\\"#Suggesting_line_break_opportunities\\\">Suggesting line break opportunities</a>, should be preferred over automatically selecting break points whenever possible.\"\n        }, {\n            \"value\": \"U+2010 (HYPHEN)\",\n            \"description\": \"The &quot;hard&quot; hyphen character indicates a visible line break opportunity. Even if the line is not actually broken at that point, the hyphen is still rendered.\"\n        }, {\n            \"value\": \"U+00AD (SHY)\",\n            \"description\": \"An invisible, &quot;soft&quot; hyphen. This character is not rendered visibly; instead, it suggests a place where the browser might choose to break the word if necessary. In HTML, you can use <code>&amp;shy;</code> to insert a soft hyphen.\"\n        }]\n    },\n    \"image-orientation\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation\",\n        \"SUMMARY\": \"The <strong><code>image-orientation</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property describes how to correct the default orientation of an image.\",\n        \"VALUES\": [{\n            \"value\": \"<code>from-image</code>\",\n            \"description\": \"The EXIF information contained in the image will be used to rotate the image appropriately.\"\n        }, {\n            \"value\": \"<code>&lt;angle&gt;</code>\",\n            \"description\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. Positive angles represent right angles, negative angles represent left angles. Its syntax is a &lt;number&gt; data type immediately followed by the unit (deg, grad, rad or turn). Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;angle&gt;</code></a> of rotation to apply to the image. It is rounded to the nearest <code>90deg</code> (<code>0.25turn</code>).\"\n        }, {\n            \"value\": \"<code>flip</code>\",\n            \"description\": \"The image is flipped horizontally, that is reflected, after the rotation given by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. Positive angles represent right angles, negative angles represent left angles. Its syntax is a &lt;number&gt; data type immediately followed by the unit (deg, grad, rad or turn). Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;angle&gt;</code></a> value. If no <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. Positive angles represent right angles, negative angles represent left angles. Its syntax is a &lt;number&gt; data type immediately followed by the unit (deg, grad, rad or turn). Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;angle&gt;</code></a> is given, <code>0deg</code> is used.\"\n        }]\n    },\n    \"image-rendering\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering\",\n        \"SUMMARY\": \"The <strong><code>image-rendering</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property provides a hint to the browser about the algorithm it should use to scale images. It applies to the element itself as well as any images supplied in other properties for the element. It has no effect on non-scaled images.\",\n        \"VALUES\": [{\n            \"value\": \"<code><strong>auto</strong></code>\",\n            \"description\": \"Default value, the image should be scaled with an algorithm that maximizes the appearance of the image. In particular, scaling algorithms that &quot;smooth&quot; colors are acceptable, such as bilinear interpolation. This is intended for images such as photos.&#xA0;Since version 1.9 (Firefox 3.0), Gecko uses<em> bilinear </em>resampling (high quality).\"\n        }, {\n            \"value\": \"<code><strong>crisp-edges</strong></code>\",\n            \"description\": \"The image must be scaled with an algorithm that preserves contrast and edges in the image, and which does not smooth colors or introduce blur to the image in the process. This is intended for images such as pixel art.\"\n        }, {\n            \"value\": \"<code><strong>pixelated</strong></code>\",\n            \"description\": \"When scaling the image up, the &quot;nearest neighbor&quot; or similar algorithm must be used, so that the image appears to be composed of large pixels. When scaling down, this is the same as &apos;auto&apos;.\"\n        }]\n    },\n    \"ime-mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/ime-mode\",\n        \"SUMMARY\": \"The <strong><code>ime-mode</code></strong> CSS property controls the state of the input method editor for text fields. According to the spec:\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"No change is made to the current input method editor state. This is the default.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The IME state should be normal; this value can be used in a user style sheet to override the page&apos;s setting. <em>This value is not supported by Internet Explorer.</em>\"\n        }, {\n            \"value\": \"<code>active</code>\",\n            \"description\": \"The input method editor is initially active; text entry is performed through it unless the user specifically dismisses it. <em>Not supported on Linux.</em>\"\n        }, {\n            \"value\": \"<code>inactive</code>\",\n            \"description\": \"The input method editor is initially inactive, but the user may activate it if they wish. <em>Not supported on Linux.</em>\"\n        }, {\n            \"value\": \"<code>disabled</code>\",\n            \"description\": \"The input method editor is disabled and may not be activated by the user.\"\n        }]\n    },\n    \"inherit\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/inherit\",\n        \"SUMMARY\": \"The <code>inherit</code> CSS-value causes the element for which it is specified to take the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/computed_value\\\">computed value</a> of the property from its parent element. It is allowed on every CSS property.\",\n        \"VALUES\": []\n    },\n    \"inheritance\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/inheritance\",\n        \"SUMMARY\": \"The summary of every <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/CSS_Reference\\\" title=\\\"en/CSS_Reference\\\">CSS property definition</a> says whether that property is inherited by default (\\\"Inherited: Yes\\\") or not inherited by default (\\\"Inherited: no\\\"). This controls what happens when no value is specified for a property on an element.\",\n        \"VALUES\": []\n    },\n    \"initial\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/initial\",\n        \"SUMMARY\": \"The <code>initial</code> CSS keyword applies the initial value of a property to an element. It is allowed on every CSS property and causes the element for which it is specified to use the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/initial_value\\\">initial value</a> of the property.\",\n        \"VALUES\": []\n    },\n    \"initial value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/initial_value\",\n        \"SUMMARY\": \"The <strong>initial value</strong> given in the summary of the definition of <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/CSS_Reference\\\" title=\\\"en/CSS_Reference\\\">each CSS property</a> has different meaning for <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/inheritance\\\" title=\\\"en/CSS/inheritance\\\">inherited and non-inherited properties</a>.\",\n        \"VALUES\": []\n    },\n    \"initial-letter\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/initial-letter\",\n        \"SUMMARY\": \"The <code>initial-letter</code> CSS property specifies styling for dropped, raised, and sunken initial letters.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"No special initial-letter effect. Text behaves as normal.\"\n        }, {\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"Defines the size of the initial letter, in terms of how many lines it occupies. Negative values are not allowed.\"\n        }, {\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"Defines the number of lines the initial letter should sink when the size of it is given. Values must be greater than zero. If omitted, it duplicates the size value, floored to the nearest positive whole number.\"\n        }]\n    },\n    \"initial-letter-align\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/initial-letter-align\",\n        \"SUMMARY\": \"The <code>initial-letter-align</code> CSS property specifies the alignment of initial letters within a paragraph.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The user agent selects the value which corresponds to the language of the text. Western languages would default to alphabetic, CJK languages to ideographic, and some Indic languages to hanging.\"\n        }, {\n            \"value\": \"<code>alphabetic</code>\",\n            \"description\": \"As described above, the cap height of the initial letter aligns with the cap height of the first line of text. The baseline of the initial letter aligns with the baseline of the Nth text baseline.\"\n        }, {\n            \"value\": \"<code>hanging</code>\",\n            \"description\": \"The hanging baseline of the initial letter aligns with the hanging baseline of the first line of text.\"\n        }, {\n            \"value\": \"<code>ideographic</code>\",\n            \"description\": \"The initial letter is centered in the N-line area.\"\n        }]\n    },\n    \"inline-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size\",\n        \"SUMMARY\": \"The <strong><code>inline-size</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the horizontal or vertical size of an element's block depending on its writing mode. It corresponds to the <a title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\"><code>width</code></a> or the <a title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\"><code>height</code></a> property depending on the value defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>inline-size</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> properties.\"\n        }]\n    },\n    \"isolation\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/isolation\",\n        \"SUMMARY\": \"The <strong><code>isolation</code></strong> CSS property defines if the element must create a new <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/stacking_context\\\" class=\\\"glossaryLink\\\" title=\\\"stacking context: Stacking context&#xA0;refers to how&#xA0;elements on a webpage appear to sit&#xA0;on top of other elements, just as you can arrange index cards on your desk to lie side-by-side or overlap each other.\\\">stacking context</a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that a new stacking context has to be created only if one properties applied to the element requires it.\"\n        }, {\n            \"value\": \"<code>isolate</code>\",\n            \"description\": \"Is a keyword indicating that a new stacking context must be created.\"\n        }]\n    },\n    \"justify-content\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> <strong><code>justify-content</code></strong> property defines how the browser distributes space between and around content items along the main axis of their container.\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The items are packed flush to each other toward the start edge of the alignment container in the main axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The items are packed flush to each other toward the end edge of the alignment container in the main axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The items are packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-start side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The items are packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-end side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>end</code>.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container along the main axis.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the appropriate axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>space-between</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container along the main axis. The spacing between each pair of adjacent items is the same. The first item is flush with the main-start edge, and the last item is flush with the main-end edge.\"\n        }, {\n            \"value\": \"<code>space-around</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container along the main axis. The spacing between each pair of adjacent items is the same. The empty space before the first and after the last item equals half of the space between each pair of adjacent items.\"\n        }, {\n            \"value\": \"<code>space-evenly</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container along the main axis. The spacing between each pair of adjacent items, the main-start edge and the first item, and the main-end edge and the last item, are all exactly the same.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items is less than the size of the alignment container, any <code>auto</code>-sized items have their size increased equally (not proportionally), while still respecting the constraints imposed by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\" title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\"><code>max-height</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\" title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size exactly fills the alignment container along the main axis.\"\n        }, {\n            \"value\": \"<code>safe</code>\",\n            \"description\": \"If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were <code>start</code>.\"\n        }, {\n            \"value\": \"<code>unsafe</code>\",\n            \"description\": \"Regardless of the relative sizes of the item and alignment container, the given alignment value is honored.\"\n        }]\n    },\n    \"justify-items\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> <strong><code>justify-items</code></strong> property defines the default <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self\\\" title=\\\"The CSS justify-self property defines the way of justifying a box inside its containeralong the appropriate axis.\\\"><code>justify-self</code></a> for all items of the box, given them the default way of justifying each box along the appropriate axis.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The value used is the value of the <code>justiy-items</code> property of the parents box, unless the box has no parent, or is absolutely positioned, in these cases, <code>auto</code> represents <code>normal</code>.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The effect of this keyword is dependent of the layout mode we are in:\\n <ul>\\n  <li>In block-level layouts, the keyword is a synonym of <code>start</code>.</li>\\n  <li>In absolutely-positioned layouts, the keyword behaved like <code>start</code> on <em>replaced</em> absolutely-positioned boxes, and as <code>stretch</code> on <em>all other</em> absolutely-positioned boxes. <span style=\\\"display: none;\\\"> </span><span style=\\\"display: none;\\\">&#xA0;</span><span style=\\\"display: none;\\\"> </span></li>\\n  <li>In table cell layouts, this keyword has no meaning as this property is <em>ignored</em>.</li>\\n  <li>In flexbox layouts, this keyword has no meaning as this property is <em>ignored.</em></li>\\n  <li>In grid layouts, this keyword leads to a behavior similar to the one of <code>stretch</code>, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like <code>start</code>.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The item is packed flush to each other toward the start edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The item is packed flush to each other toward the end edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The item ispacked flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-start or cross-start side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The item is packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-end or cross-end side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>end</code>.\"\n        }, {\n            \"value\": \"<code>self-start</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the start side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>self-end</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the end side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the appropriate axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items is less than the size of the alignment container, any <code>auto</code>-sized items have their size increased equally (not proportionally), while still respecting the constraints imposed by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\" title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\"><code>max-height</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\" title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size exactly fills the alignment container.\"\n        }, {\n            \"value\": \"<code>safe</code>\",\n            \"description\": \"If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were <code>start</code>.\"\n        }, {\n            \"value\": \"<code>unsafe</code>\",\n            \"description\": \"Regardless of the relative sizes of the item and alignment container, the given alignment value is honored.\"\n        }, {\n            \"value\": \"<code>legacy</code>\",\n            \"description\": \"Makes the value inherited by the box descendants. Note that if a descendant has a <code>justify-self: auto</code> value, the <code>legacy</code> keyword is not considered by the descend, only the <code>left</code>, <code>right</code>, or <code>center</code> value associated to it.\"\n        }]\n    },\n    \"justify-self\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self\",\n        \"SUMMARY\": \"The <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> <strong><code>justify-self</code></strong> property defines the way of justifying a box inside its containeralong the appropriate axis.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The value used is the value of the <code>justify-items</code> property of the parents box, unless the box has no parent, or is absolutely positioned, in these cases, <code>auto</code> represents <code>normal</code>.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The effect of this keyword is dependent of the layout mode we are in:\\n <ul>\\n  <li>In block-level layouts, the keyword is a synonym of <code>start</code>.</li>\\n  <li>In absolutely-positioned layouts, the keyword behaves like <code>start</code> on <em>replaced</em> absolutely-positioned boxes, and as <code>stretch</code> on <em>all other</em> absolutely-positioned boxes. <span style=\\\"display: none;\\\"> </span><span style=\\\"display: none;\\\">&#xA0;</span><span style=\\\"display: none;\\\"> </span></li>\\n  <li>In table cell layouts, this keyword has no meaning as this property is <em>ignored</em>.</li>\\n  <li>In flexbox layouts, this keyword has no meaning as this property is <em>ignored.</em></li>\\n  <li>In grid layouts, this keyword leads to a behavior similar to the one of <code>stretch</code>, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like <code>start</code>.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The item is packed flush to each other toward the start edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The item is packed flush to each other toward the end edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The item is packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-start or cross-start side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The item is packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-end or cross-end side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>end</code>.\"\n        }, {\n            \"value\": \"<code>self-start</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the start side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>self-end</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the end side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the appropriate axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items is less than the size of the alignment container, any <code>auto</code>-sized items have their size increased equally (not proportionally), while still respecting the constraints imposed by <a title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\"><code>max-height</code></a>/<a title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size exactly fills the alignment container.\"\n        }, {\n            \"value\": \"<code>safe</code>\",\n            \"description\": \"If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were <code>start</code>.\"\n        }, {\n            \"value\": \"<code>unsafe</code>\",\n            \"description\": \"Regardless of the relative sizes of the item and alignment container, the given alignment value is honored.\"\n        }]\n    },\n    \"left\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/left\",\n        \"SUMMARY\": \"The <strong><code>left</code></strong> CSS property specifies part of the position of positioned elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a negative, null, or positive <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> that represents:\\n <ul>\\n  <li>for <em>absolutely positioned elements</em>, the distance to the left edge of the containing block</li>\\n  <li>for <em>relatively positioned elements</em>, the offset that the element is moved left from its position in the normal flow if it wasn&apos;t positioned.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the containing block&apos;s width, used as described in the <a href=\\\"#Summary\\\">summary</a>.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that represents:\\n <ul>\\n  <li>for absolutely positioned elements, the position of the element based on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\" title=\\\"The right CSS property specifies part of the position of positioned elements.\\\"><code>right</code></a> property and treat <code>width: auto</code> as a width based on the content.</li>\\n  <li>for relatively positioned elements, the left offset of the element from its original position based on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\" title=\\\"The right CSS property specifies part of the position of positioned elements.\\\"><code>right</code></a> property, or if <code>right</code> is also <code>auto</code>, do not offset it at all.</li>\\n </ul>\\n \"\n        }]\n    },\n    \"letter-spacing\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing\",\n        \"SUMMARY\": \"The <strong><code>letter-spacing</code></strong> CSS property specifies spacing behavior between text characters.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The spacing is the normal spacing for the current font. Unlike a value of 0, this value allows the user agent to alter the space between characters in order to justify text.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Indicates inter-character space <strong><em>in addition to</em></strong> the default space between characters. Values may be negative, but there may be implementation-specific limits. User agents may not further increase or decrease the inter-character space in order to justify text.<br>\\n See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> values for possible units.\"\n        }]\n    },\n    \"line-break\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/line-break\",\n        \"SUMMARY\": \"The <strong><code>line-break</code></strong> CSS property is used to specify how (or if) to break lines.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"break text using&#xA0; the default line break rule.\"\n        }, {\n            \"value\": \"<code>loose</code>\",\n            \"description\": \"break text using the line break rule that the line is shorter like a newspaper.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"break text using the common line break rule.\"\n        }, {\n            \"value\": \"<code>strict</code>\",\n            \"description\": \"break text using the stringent line break rule.\"\n        }]\n    },\n    \"line-height\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\",\n        \"SUMMARY\": \"On block level elements, the <code>line-height</code> property specifies the minimum height of line boxes within the element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Depends on the user agent. Desktop browsers (including Firefox) use a default value of roughly<strong><code> 1.2</code></strong>, depending on the element&apos;s<code> font-family</code>.\"\n        }, {\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"The used value is this unitless <a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a> multiplied by the element&apos;s font size. The computed value is the same as the specified<code> &lt;number&gt;</code>. In most cases <strong>this is the preferred way</strong> to set <code>line-height</code> with no unexpected results in case of inheritance.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"The specified <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> is used in the calculation of the line box height. See <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> values for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Relative to the font size of the element itself. The computed value is this percentage multiplied by the element&apos;s computed font size.<br>\\n <strong>Percentage</strong> and <strong>em</strong> values may have unexpected results, see &quot;Notes&quot; section.\"\n        }]\n    },\n    \"linear-gradient()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient\",\n        \"SUMMARY\": \"The CSS <code>linear-gradient()</code> function creates an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> which represents a linear gradient of colors. The result of this function is an object of the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/gradient\\\" title=\\\"The &lt;gradient&gt; CSS data type denotes a CSS &lt;image&gt; made of a progressive transition between two or more colors. A CSS gradient is not a CSS &lt;color&gt; but an image with no intrinsic dimensions; that is, it has no natural or preferred size, nor a preferred ratio. Its concrete size will match the one of the element it applies to.\\\"><code>&lt;gradient&gt;</code></a> data type. Like any other gradient, a CSS linear gradient is not a CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> but an image with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image#no_intrinsic\\\">no intrinsic dimensions</a>; that is, it has neither natural or preferred size, nor ratio. Its concrete size will match the size of the element it applies to.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;side-or-corner&gt;</code>\",\n            \"description\": \"Represents the position of the starting-point of the gradient line. It consists of two keywords: the first one indicates the horizontal side, <code>left</code> or <code>right</code>, and the second one the vertical side, <code>top</code> or <code>bottom</code>. The order is not relevant and each of the keyword is optional. If omitted, it defaults to <code><span class=\\\"css\\\">to bottom</span></code>.<br>\\n The values <code>to top</code>, <code>to bottom</code>, <code>to left</code> and <code>to right</code> are translated into the angles <code>0deg</code>, <code>180deg</code>, <code>270deg</code>, <code>90deg</code> respectively. The others are translated into an angle that starts from <code>to top</code> and rotate clockwisely. The end-point of the gradient line is the symmetrical point of the starting-point on the other direction of the center box.\"\n        }, {\n            \"value\": \"<code>&lt;angle&gt;</code>\",\n            \"description\": \"An angle of direction for the gradient. The angle starts from <code>to&#xA0;top</code> and rotates clockwise. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. It is used, for example, in rotate and skew transforms.\\\"><code>&lt;angle&gt;</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color-stop&gt;</code>\",\n            \"description\": \"This value is comprised of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> value, followed by an optional stop position (either a percentage or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> along the gradient&apos;s axis).<br>\\n Rendering of <a href=\\\"#Gradient_with_multiple_color_stops\\\">color stops in CSS gradients</a> follows the same rules as color stops in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Gradients\\\">SVG gradients</a>.\"\n        }]\n    },\n    \"list-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style\",\n        \"SUMMARY\": \"The <strong><code>list-style</code></strong> property is a shorthand property for setting <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\\\" title=\\\"The list-style-type property specifies the appearance of a list item element. Because it is the only property that&#xA0;defaults to display:list-item, this is usually a &lt;li&gt; element, but can be any element with this display value.\\\"><code>list-style-type</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-image\\\" title=\\\"The list-style-image property specifies an image to be used as the list item marker.\\\"><code>list-style-image</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-position\\\" title=\\\"The list-style-position property specifies the position of the marker box in the principal block box.\\\"><code>list-style-position</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;list-style-type&apos;&gt;</code>\",\n            \"description\": \"See <a title=\\\"The list-style-type property specifies the appearance of a list item element. Because it is the only property that&#xA0;defaults to display:list-item, this is usually a &lt;li&gt; element, but can be any element with this display value.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\\\"><code>list-style-type</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;list-style-image&apos;&gt;</code>\",\n            \"description\": \"See <a title=\\\"The list-style-image property specifies an image to be used as the list item marker.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-image\\\"><code>list-style-image</code></a>\"\n        }, {\n            \"value\": \"<code>&lt;&apos;list-style-position&apos;&gt;</code>\",\n            \"description\": \"See <a title=\\\"The list-style-position property specifies the position of the marker box in the principal block box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-position\\\"><code>list-style-position</code></a>\"\n        }]\n    },\n    \"list-style-image\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-image\",\n        \"SUMMARY\": \"The <strong><code>list-style-image</code></strong> property specifies an image to be used as the list item marker.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;uri&gt;</code>\",\n            \"description\": \"Location of image to use as the marker.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Specifies that no image is used as the marker. If this value is set, the marker defined in <a title=\\\"The list-style-type property specifies the appearance of a list item element. Because it is the only property that&#xA0;defaults to display:list-item, this is usually a &lt;li&gt; element, but can be any element with this display value.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\\\"><code>list-style-type</code></a> will be used instead.\"\n        }]\n    },\n    \"list-style-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-position\",\n        \"SUMMARY\": \"The <strong><code>list-style-position</code></strong> property specifies the position of the marker box in the principal block box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>outside</code>\",\n            \"description\": \"The marker box is outside the principal block box.\"\n        }, {\n            \"value\": \"<code>inside</code>\",\n            \"description\": \"The marker box is the first inline box in the principal block box, after which the element&apos;s content flows.\"\n        }]\n    },\n    \"list-style-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\",\n        \"SUMMARY\": \"The<strong> <code>list-style-type</code></strong> property specifies the appearance of a list item element. Because it is the only property that defaults to <code>display:list-item</code>, this is usually a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li\\\" title=\\\"The HTML &lt;li&gt; element is used to represent an item in a list. It must be contained in a parent element: an ordered list (&lt;ol&gt;), an unordered list (&lt;ul&gt;), or a menu (&lt;menu&gt;). In menus and unordered lists, list items are usually displayed using bullet points. In ordered lists, they are usually displayed with an ascending counter on the left, such as a number or letter.\\\"><code>&lt;li&gt;</code></a> element, but can be any element with this <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display\\\" title=\\\"The display CSS property specifies the type of rendering box used for an element. In HTML, default display property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is inline.\\\"><code>display</code></a> value.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/symbols()\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>symbols()</code></a>\",\n            \"description\": \"Defines an anonymous style of the list.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No item marker is shown.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a>\",\n            \"description\": \"The specified string will be used as the item&apos;s marker.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;custom-ident&gt;</code></a>\",\n            \"description\": \"A identifier matching the value of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\\\" title=\\\"The @counter-style CSS at-rule&#xA0;lets authors define&#xA0;specific counter styles that are not part of the predefined set of styles. A @counter-style rule defines how to convert a counter value into a string representation.\\\"><code>@counter-style</code></a> or one of the predefined styles:\"\n        }, {\n            \"value\": \"<code>disc</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: disc;\\\">\\n  <li>A filled circle (default value)</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>circle</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: circle;\\\">\\n  <li>A hollow circle</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>square</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: square;\\\">\\n  <li>A filled square</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>decimal</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: decimal;\\\">\\n  <li>Decimal numbers</li>\\n  <li>Beginning with 1</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>cjk-decimal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"\\n <ul>\\n  <li>Han decimal numbers</li>\\n  <li>E.g. &#x4E00;, &#x4E8C;, &#x4E09;, ..., &#x4E5D;&#x516B;, &#x4E5D;&#x4E5D;, &#x4E00;&#x3007;&#x3007;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>decimal-leading-zero</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: decimal-leading-zero;\\\">\\n  <li>Decimal numbers</li>\\n  <li>Padded by initial zeros</li>\\n  <li>E.g. 01, 02, 03, &#x2026; 98, 99</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>lower-roman</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: lower-roman;\\\">\\n  <li>Lowercase roman numerals</li>\\n  <li>E.g. i, ii, iii, iv, v&#x2026;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>upper-roman</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: upper-roman;\\\">\\n  <li>Uppercase roman numerals</li>\\n  <li>E.g. I, II, III, IV, V&#x2026;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>lower-greek</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: lower-greek;\\\">\\n  <li>Lowercase classical Greek</li>\\n  <li>alpha, beta, gamma&#x2026;</li>\\n  <li>E.g. &#x3B1;, &#x3B2;, &#x3B3;&#x2026;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>lower-alpha</code>\",\n            \"description\": \"<code>lower-latin</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: lower-alpha;\\\">\\n  <li>Lowercase ASCII letters</li>\\n  <li>E.g. a, b, c, &#x2026; z</li>\\n  <li><code>lower-latin</code> is unsupported in IE7 and earlier</li>\\n  <li>See <a href=\\\"#Browser_compatibility\\\">Browser compatibility</a> section.</li>\\n </ul>\\n \",\n            \"description\": \"<code>upper-alpha</code>\"\n        }, {\n            \"value\": \"<code>upper-latin</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: upper-alpha;\\\">\\n  <li>Uppercase ASCII letters</li>\\n  <li>E.g. A, B, C, &#x2026; Z</li>\\n  <li><code>upper-latin</code> is unsupported in IE7 and earlier</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>arabic-indic</code>\",\n            \"description\": \"<code>-moz-arabic-indic</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-arabic-indic; list-style-type: arabic-indic;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>armenian</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: armenian;\\\">\\n  <li>Traditional Armenian numbering</li>\\n  <li>(ayb/ayp, ben/pen, gim/keem&#x2026;</li>\\n </ul>\\n \",\n            \"description\": \"<code>bengali</code>\"\n        }, {\n            \"value\": \"<code>-moz-bengali</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-bengali; list-style-type: bengali;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>cambodian</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>*\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: cambodian;\\\">\\n  <li>Example</li>\\n  <li>Is a synonym for <code>khmer</code></li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>cjk-earthly-branch</code>\",\n            \"description\": \"<code>-moz-cjk-earthly-branch</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-cjk-earthly-branch; list-style-type: cjk-earthly-branch;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>cjk-heavenly-stem</code>\"\n        }, {\n            \"value\": \"<code>-moz-cjk-heavenly-stem</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-cjk-heavenly-stem; list-style-type: cjk-heavenly-stem;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>cjk-ideographic</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: cjk-ideographic;\\\">\\n  <li>Identical to <code>trad-chinese-informal</code></li>\\n  <li>E.g. &#x4E00;&#x842C;&#x4E00;&#x5343;&#x4E00;&#x767E;&#x4E00;&#x5341;&#x4E00;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>devanagari</code>\",\n            \"description\": \"<code>-moz-devanagari</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-devanagari; list-style-type: devanagari;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>ethiopic-numeric</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: ethiopic-numeric;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>georgian</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: georgian;\\\">\\n  <li>Traditional Georgian numbering</li>\\n  <li>E.g. an, ban, gan, &#x2026; he, tan, in&#x2026;</li>\\n </ul>\\n \",\n            \"description\": \"<code>gujarati</code>\"\n        }, {\n            \"value\": \"<code>-moz-gujarati</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-gujarati; list-style-type: gujarati;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>gurmukhi</code>\",\n            \"description\": \"<code>-moz-gurmukhi</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-gurmukhi; list-style-type: gurmukhi;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>hebrew</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: hebrew;\\\">\\n  <li>Traditional Hebrew numbering</li>\\n </ul>\\n \",\n            \"description\": \"<code>hiragana</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: hiragana;\\\">\\n  <li>a, i, u, e, o, ka, ki, &#x2026;</li>\\n  <li>(Japanese)</li>\\n </ul>\\n \",\n            \"description\": \"<code>hiragana-iroha</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: hiragana-iroha;\\\">\\n  <li>i, ro, ha, ni, ho, he, to, &#x2026;</li>\\n  <li><a href=\\\"https://en.wikipedia.org/wiki/Iroha\\\" class=\\\"external\\\" title=\\\"Iroha\\\">Iroha</a> is the old japanese ordering of syllabs.</li>\\n </ul>\\n \",\n            \"description\": \"<code>japanese-formal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: japanese-formal;\\\">\\n  <li>Japanese formal numbering to be used in legal or financial document.</li>\\n  <li>E.g., &#x58F1;&#x842C;&#x58F1;&#x9621;&#x58F1;&#x767E;&#x58F1;&#x62FE;&#x58F1;</li>\\n  <li>The kanjis are designed so that they can&apos;t be modified to look like another correct one</li>\\n </ul>\\n \",\n            \"description\": \"<code>japanese-informal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: japanese-informal;\\\">\\n  <li>Japanese informal numbering</li>\\n </ul>\\n \",\n            \"description\": \"<code>kannada</code>\"\n        }, {\n            \"value\": \"<code>-moz-kannada</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-kannada; list-style-type: kannada;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>katakana</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: katakana;\\\">\\n  <li>A, I, U, E, O, KA, KI, &#x2026;</li>\\n  <li>(Japanese)</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>katakana-iroha</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: katakana-iroha;\\\">\\n  <li>I, RO, HA, NI, HO, HE, TO, &#x2026;</li>\\n  <li><a href=\\\"https://en.wikipedia.org/wiki/Iroha\\\" class=\\\"external\\\" title=\\\"Iroha\\\">Iroha</a> is the old japanese ordering of syllabs.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>khmer</code>\",\n            \"description\": \"<code>-moz-khmer</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-khmer; list-style-type: khmer;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>korean-hangul-formal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: korean-hangul-formal;\\\">\\n  <li>Korean hangul numbering.</li>\\n  <li>E.g., &#xC77C;&#xB9CC; &#xC77C;&#xCC9C;&#xC77C;&#xBC31;&#xC77C;&#xC2ED;&#xC77C;</li>\\n </ul>\\n \",\n            \"description\": \"<code>korean-hanja-formal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: korean-hanja-formal;\\\">\\n  <li>Formal Korean Han&#xA0;numbering.</li>\\n  <li>E.g. &#x58F9;&#x842C; &#x58F9;&#x4EDF;&#x58F9;&#x767E;&#x58F9;&#x62FE;&#x58F9;</li>\\n </ul>\\n \",\n            \"description\": \"<code>korean-hanja-informal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: korean-hanja-informal;\\\">\\n  <li>Korean hanja numbering.</li>\\n  <li>E.g., &#x842C; &#x4E00;&#x5343;&#x767E;&#x5341;&#x4E00;</li>\\n </ul>\\n \",\n            \"description\": \"<code>lao</code>\"\n        }, {\n            \"value\": \"<code>-moz-lao</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-lao; list-style-type: lao;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>lower-armenian</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>*\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: lower-armenian;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>malayalam</code>\",\n            \"description\": \"<code>-moz-malayalam</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-malayalam; list-style-type: malayalam;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>mongolian</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: mongolian;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>myanmar</code>\"\n        }, {\n            \"value\": \"<code>-moz-myanmar</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-myanmar; list-style-type: myanmar;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>oriya</code>\",\n            \"description\": \"<code>-moz-oriya</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-oriya; list-style-type: oriya;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>persian</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"<code>-moz-persian</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-persian; list-style-type: persian;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>simp-chinese-formal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: simp-chinese-formal;\\\">\\n  <li>Simplified Chinese formal&#xA0;numbering.</li>\\n  <li>E.g. &#x58F9;&#x4E07;&#x58F9;&#x4EDF;&#x58F9;&#x4F70;&#x58F9;&#x62FE;&#x58F9;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>simp-chinese-informal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: simp-chinese-informal;\\\">\\n  <li>Simplified Chinese informal&#xA0;numbering.</li>\\n  <li>E.g. &#x4E00;&#x4E07;&#x4E00;&#x5343;&#x4E00;&#x767E;&#x4E00;&#x5341;&#x4E00;</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>tamil</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"<code>-moz-tamil</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-tamil; list-style-type: tamil;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>telugu</code>\"\n        }, {\n            \"value\": \"<code>-moz-telugu</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-telugu; list-style-type: telugu;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>thai</code>\",\n            \"description\": \"<code>-moz-thai</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-thai; list-style-type: thai;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>tibetan</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>*\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: tibetan;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>trad-chinese-formal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: trad-chinese-formal;\\\">\\n  <li>Traditional Chinese formal numbering.</li>\\n  <li>E.g. &#x58F9;&#x842C;&#x58F9;&#x4EDF;&#x58F9;&#x4F70;&#x58F9;&#x62FE;&#x58F9;</li>\\n </ul>\\n \",\n            \"description\": \"<code>trad-chinese-informal</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: trad-chinese-informal;\\\">\\n  <li>Traditional Chinese informal&#xA0;numbering.</li>\\n  <li>E.g. &#x4E00;&#x842C;&#x4E00;&#x5343;&#x4E00;&#x767E;&#x4E00;&#x5341;&#x4E00;</li>\\n </ul>\\n \",\n            \"description\": \"<code>upper-armenian</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>*\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: upper-armenian;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>disclosure-open</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: disclosure-open;\\\">\\n  <li>Symbol indicating that a disclosure widget such as&#xA0;<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details\\\" title=\\\"The HTML &lt;details&gt; element is used as a disclosure widget from which the user can retrieve additional information.\\\"><code>&lt;details&gt;</code></a> is opened.</li>\\n </ul>\\n \",\n            \"description\": \"<code>disclosure-closed</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: disclosure-closed;\\\">\\n  <li>Symbol indicating that a disclosure widget, like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details\\\" title=\\\"The HTML &lt;details&gt; element is used as a disclosure widget from which the user can retrieve additional information.\\\"><code>&lt;details&gt;</code></a> is closed.</li>\\n </ul>\\n \",\n            \"description\": \"<code>-moz-ethiopic-halehame</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-ethiopic-halehame;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>-moz-ethiopic-halehame-am</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-ethiopic-halehame-am;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>ethiopic-halehame-ti-er</code>\"\n        }, {\n            \"value\": \"<code>-moz-ethiopic-halehame-ti-er</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-ethiopic-halehame-ti-er;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>ethiopic-halehame-ti-et</code>\",\n            \"description\": \"<code>-moz-ethiopic-halehame-ti-et</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-ethiopic-halehame-ti-et;\\\">\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>hangul</code>\"\n        }, {\n            \"value\": \"<code>-moz-hangul</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-hangul;\\\">\\n  <li>Example</li>\\n  <li>Example</li>\\n  <li>Example</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>hangul-consonant</code>\",\n            \"description\": \"<code>-moz-hangul-consonant</code>\"\n        }, {\n            \"value\": \"\\n <ul style=\\\"list-style-type: -moz-hangul-consonant;\\\">\\n  <li>Example</li>\\n  <li>Example</li>\\n  <li>Example</li>\\n </ul>\\n \",\n            \"description\": \"<code>urdu</code>\"\n        }, {\n            \"value\": \"<code>-moz-urdu</code>\",\n            \"description\": \"\\n <ul style=\\\"list-style-type: -moz-urdu;\\\">\\n  <li>Example</li>\\n </ul>\\n \"\n        }]\n    },\n    \"margin\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin\",\n        \"SUMMARY\": \"The <strong><code>margin</code></strong> CSS property sets the margin for all four sides. It is a shorthand to avoid setting each side separately with the other margin properties: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\" title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\"><code>margin-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\\\" title=\\\"The margin-right CSS property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\\\"><code>margin-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\" title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\"><code>margin-bottom</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies a fixed width. Negative Values are allowed. See for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> relative to the <strong>width</strong> of the containing block. Negative values are allowed.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"<code>auto </code>is replaced by some suitable value, e.g. it can be used for centering of blocks.<br>\\n <code>div { width:50%;&#xA0; margin:0 auto; }</code> centers the div container horizontally.\"\n        }]\n    },\n    \"margin-block-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-block-end\",\n        \"SUMMARY\": \"The <strong><code>margin-block-end</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the logical block end margin of an element, which maps to a physical margin depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\"><code>margin-top</code></a>, <a title=\\\"The margin-right CSS property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\\\"><code>margin-right</code></a>, <a title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\"><code>margin-bottom</code></a>, or <a title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\"><code>margin-left</code></a> property depending on the values defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>, <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a>, and <a title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>margin-block-end</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a> property.\"\n        }]\n    },\n    \"margin-block-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-block-start\",\n        \"SUMMARY\": \"The <strong><code>margin-block-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical block start margin of an element, which maps to a physical margin depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\" title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\"><code>margin-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\\\" title=\\\"The margin-right CSS property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\\\"><code>margin-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\" title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\"><code>margin-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>margin-block-start</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a> property.\"\n        }]\n    },\n    \"margin-bottom\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\",\n        \"SUMMARY\": \"The <code>margin-bottom</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies a fixed width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible values.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> always relative to the <strong>width</strong> of the containing block.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin\\\" title=\\\"The margin CSS property sets the margin for all four sides. It is a shorthand to avoid setting each side separately with the other margin properties: margin-top, margin-right, margin-bottom and margin-left.\\\"><code>margin</code></a>.\"\n        }]\n    },\n    \"margin-inline-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline-end\",\n        \"SUMMARY\": \"The<strong> <code>margin-inline-end</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical inline end margin of an element, which maps to a physical margin depending on the element's writing mode, directionality, and text orientation. In other words, it corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\" title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\"><code>margin-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\\\" title=\\\"The margin-right CSS property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\\\"><code>margin-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\" title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\"><code>margin-bottom</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>margin-inline-end</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a> property.\"\n        }]\n    },\n    \"margin-inline-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline-start\",\n        \"SUMMARY\": \"The <strong><code>margin-inline-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical inline start margin of an element, which maps to a physical margin depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\" title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\"><code>margin-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\\\" title=\\\"The margin-right CSS property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\\\"><code>margin-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\" title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\"><code>margin-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\" title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\"><code>margin-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>margin-inline-start</code> property takes the same values as the <a title=\\\"The margin-left CSS property sets the margin space required on the left side of a box associated with an element. A negative value is also allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\\\"><code>margin-left</code></a> property.\"\n        }]\n    },\n    \"margin-left\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\",\n        \"SUMMARY\": \"The <strong><code>margin-left</code></strong> <a title=\\\"CSS\\\" href=\\\"/en/CSS\\\">CSS</a> property sets the margin space required on the left side of a <a title=\\\"https://developer.mozilla.org/en-US/docs/CSS/box_model\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS/box_model\\\">box</a> associated with an element. A negative value is also allowed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> specifying a fixed width: it can be absolute width, e.g. in <code>px</code>, or a width relative to the text size, e.g. in <code>em</code>, or relative to the viewport size, e.g. in <code>vh</code>.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> relative to the <em>width</em> of the nearest containing block.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the left margin receives a share of the remaining space, defined mainly by the current layout mode.. If there several <code>auto</code> values for <code>margin-left</code> or <code>margin-right</code>, the calculated space is evenly distributed between all the <code>auto</code> values. This table summarizes the different cases:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <th scope=\\\"col\\\">Value of <a title=\\\"The display CSS property specifies the type of rendering box used for an element. In HTML, default display property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is inline.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display\\\"><code>display</code></a></th>\\n    <th scope=\\\"col\\\">Value of <a title=\\\"The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/float\\\"><code>float</code></a></th>\\n    <th scope=\\\"col\\\">Value of <a title=\\\"The position CSS property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\"><code>position</code></a></th>\\n    <th scope=\\\"col\\\">Computed value of <code>auto</code></th>\\n    <th scope=\\\"col\\\">Comment</th>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <th><code>inline</code>, <code>inline-block</code>, <code>inline-table</code></th>\\n    <th><em>any</em></th>\\n    <th><code>static</code> or <code>relative</code></th>\\n    <td><code>0</code></td>\\n    <td>Inline layout mode</td>\\n   </tr>\\n   <tr>\\n    <th><code>block</code>, <code>inline</code>, <code>inline-block</code>, <code>block</code>, <code>table</code>, <code>inline-table</code>, <code>list-item</code>, <code>table-caption</code></th>\\n    <th><em>any</em></th>\\n    <th><code>static</code> or <code>relative</code></th>\\n    <td><code>0</code>, except if both <code>margin-left</code> and <code>margin-right</code> are set to <code>auto</code>. In this case, it is set to the value centering the element inside its parent.</td>\\n    <td>Block layout mode</td>\\n   </tr>\\n   <tr>\\n    <th><code>block</code>, <code>inline</code>, <code>inline-block</code>, <code>block</code>, <code>table</code>, <code>inline-table</code>, <code>list-item</code>, <code>table-caption</code></th>\\n    <th><code>left</code> or <code>right</code></th>\\n    <th><code>static</code> or <code>relative</code></th>\\n    <td><code>0</code></td>\\n    <td>Block layout mode (floating element)</td>\\n   </tr>\\n   <tr>\\n    <th><em>any </em><code>table-*</code><em>, except </em><code>table-caption</code></th>\\n    <th><em>any</em></th>\\n    <th><em>any</em></th>\\n    <td><code>0</code></td>\\n    <td>Internal <code>table-*</code> elements don&apos;t have margins, use <a title=\\\"The border-spacing CSS property specifies the distance between the borders of adjacent table cells (only for the separated borders model). This is equivalent to the cellspacing attribute in presentational HTML, but an optional second value can be used to set different horizontal and vertical spacing.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-spacing\\\"><code>border-spacing</code></a> instead</td>\\n   </tr>\\n   <tr>\\n    <th><em>any, except <code>flex</code>,</em> <code>inline-flex</code><em>, or </em><code>table-*</code></th>\\n    <th><em>any</em></th>\\n    <th><em><code>fixed</code></em> or <code>absolute</code></th>\\n    <td><code>0</code>, except if both <code>margin-left</code> and <code>margin-right</code> are set to <code>auto</code>. In this case, it is set to the value centering the border area inside the available <code>width</code>, if fixed.</td>\\n    <td>Absolutely positioned layout mode</td>\\n   </tr>\\n   <tr>\\n    <th><code>flex</code>, <code>inline-flex</code></th>\\n    <th><em>any</em></th>\\n    <th><em>any</em></th>\\n    <td><code>0</code>, except if there is any positive horizontal free space. In this case, it is evenly distributed to all horizontal <code>auto</code> margins.</td>\\n    <td>Flexbox layout mode</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"margin-right\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\",\n        \"SUMMARY\": \"The <strong><code>margin-right</code></strong> <a href=\\\"mailto:setiawan345@rocketmail.com?subject=%5Berrkk%5D&amp;body=terrreeh\\\" title=\\\"CSS\\\">CSS</a> property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> specifying a fixed width: it can be absolute width, e.g. in <code>px</code>, or a width relative to the text size, e.g. in <code>em</code>, or relative to the viewport size, e.g. in <code>vh</code>.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> relative to the <em>width</em> of the nearest containing block.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword indicating that the right margin receives a share of the remaining space, defined mainly by the current layout mode.. If there several <code>auto</code> values for <code>margin-left</code> or <code>margin-right</code>, the calculated space is evenly distributed between all the <code>auto</code> values. This table summarizes the different cases:\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <th scope=\\\"col\\\">Value of <a title=\\\"The display CSS property specifies the type of rendering box used for an element. In HTML, default display property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is inline.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display\\\"><code>display</code></a></th>\\n    <th scope=\\\"col\\\">Value of <a title=\\\"The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/float\\\"><code>float</code></a></th>\\n    <th scope=\\\"col\\\">Value of <a title=\\\"The position CSS property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\"><code>position</code></a></th>\\n    <th scope=\\\"col\\\">Computed value of <code>auto</code></th>\\n    <th scope=\\\"col\\\">Comment</th>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <th><code>inline</code>, <code>inline-block</code>, <code>inline-table</code></th>\\n    <th><em>any</em></th>\\n    <th><code>static</code> or <code>relative</code></th>\\n    <td><code>0</code></td>\\n    <td>Inline layout mode</td>\\n   </tr>\\n   <tr>\\n    <th><code>block</code>, <code>inline</code>, <code>inline-block</code>, <code>block</code>, <code>table</code>, <code>inline-table</code>, <code>list-item</code>, <code>table-caption</code></th>\\n    <th><em>any</em></th>\\n    <th><code>static</code> or <code>relative</code></th>\\n    <td><code>0</code>, except if both <code>margin-left</code> and <code>margin-right</code> are set to <code>auto</code>. In this case, it is set to the value centering the element inside its parent.</td>\\n    <td>Block layout mode</td>\\n   </tr>\\n   <tr>\\n    <th><code>block</code>, <code>inline</code>, <code>inline-block</code>, <code>block</code>, <code>table</code>, <code>inline-table</code>, <code>list-item</code>, <code>table-caption</code></th>\\n    <th><code>left</code> or <code>right</code></th>\\n    <th><code>static</code> or <code>relative</code></th>\\n    <td><code>0</code></td>\\n    <td>Block layout mode (floating element)</td>\\n   </tr>\\n   <tr>\\n    <th><em>any </em><code>table-*</code><em>, except </em><code>table-caption</code></th>\\n    <th><em>any</em></th>\\n    <th><em>any</em></th>\\n    <td><code>0</code></td>\\n    <td>Internal <code>table-*</code> elements don&apos;t have margins, use <a title=\\\"The border-spacing CSS property specifies the distance between the borders of adjacent table cells (only for the separated borders model). This is equivalent to the cellspacing attribute in presentational HTML, but an optional second value can be used to set different horizontal and vertical spacing.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-spacing\\\"><code>border-spacing</code></a> instead</td>\\n   </tr>\\n   <tr>\\n    <th><em>any, except <code>flex</code>,</em> <code>inline-flex</code><em>, or </em><code>table-*</code></th>\\n    <th><em>any</em></th>\\n    <th><em><code>fixed</code></em> or <code>absolute</code></th>\\n    <td><code>0</code>, except if both <code>margin-left</code> and <code>margin-right</code> are set to <code>auto</code>. In this case, it is set to the value centering the border area inside the available <code>width</code>, if fixed.</td>\\n    <td>Absolutely positioned layout mode</td>\\n   </tr>\\n   <tr>\\n    <th><code>flex</code>, <code>inline-flex</code></th>\\n    <th><em>any</em></th>\\n    <th><em>any</em></th>\\n    <td><code>0</code>, except if there is any positive horizontal free space. In this case, it is evenly distributed to all horizontal <code>auto</code> margins.</td>\\n    <td>Flexbox layout mode</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"margin-top\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\",\n        \"SUMMARY\": \"The <strong><code>margin-top</code></strong> CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies a fixed width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible values.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> always relative to the <strong>width</strong> of the containing block.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin\\\" title=\\\"The margin CSS property sets the margin for all four sides. It is a shorthand to avoid setting each side separately with the other margin properties: margin-top, margin-right, margin-bottom and margin-left.\\\"><code>margin</code></a>.\"\n        }]\n    },\n    \"marker-offset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/marker-offset\",\n        \"SUMMARY\": \"The <code>marker-offset</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property describes the distance between the nearest border edges of a marker-box and the target node.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The browser will calculate and select an offset.\"\n        }]\n    },\n    \"mask\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask\",\n        \"SUMMARY\": \"The <code>mask</code> property in CSS allows users to alter the visibility of an item by either partially or fully hiding it. This is accomplished by either masking or clipping the image at specific points.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;mask-reference&gt;</code>\",\n            \"description\": \"Sets the mask image source. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-image\\\" title=\\\"The mask-image CSS property sets the image that is used as mask layer for an element.\\\"><code>mask-image</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;masking-mode&gt;</code>\",\n            \"description\": \"Sets the masking mode of the mask image. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-mode\\\" title=\\\"The mask-mode CSS property indicates whether the mask reference defined by mask-image is treated as a luminance or alpha mask.\\\"><code>mask-mode</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"Sets the position of the mask image. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\\\" title=\\\"The mask-position CSS property sets the initial position, relative to the mask position layer defined by mask-origin for each defined mask image.\\\"><code>mask-position</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;bg-size&gt;</code>\",\n            \"description\": \"Sets the size of the mask image. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-size\\\" title=\\\"The mask-size CSS property specifies the sizes of the mask images. The size of the image can be fully or partially constrained&#xA0;in order to preserve its intrinsic ratio.\\\"><code>mask-size</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;repeat-style&gt;</code>\",\n            \"description\": \"Sets the repetition of the mask image. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-repeat\\\" title=\\\"The mask-repeat CSS property defines how mask images are repeated. A mask image can be repeated along the horizontal axis, the vertical axis, both axes, or not repeated at all.\\\"><code>mask-repeat</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;geometry-box&gt;</code>\",\n            \"description\": \"If only one &lt;geometry-box&gt; value is given, it sets both <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-origin\\\" title=\\\"The mask-origin CSS property determines the origin of a mask.\\\"><code>mask-origin</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-clip\\\" title=\\\"The mask-clip CSS property determines the area, which is affected by a mask. The painted content of an element must be restricted to this area.\\\"><code>mask-clip</code></a>. If two &lt;geometry-box&gt; values are present, then the first sets <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-origin\\\" title=\\\"The mask-origin CSS property determines the origin of a mask.\\\"><code>mask-origin</code></a> and the second <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-clip\\\" title=\\\"The mask-clip CSS property determines the area, which is affected by a mask. The painted content of an element must be restricted to this area.\\\"><code>mask-clip</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;geometry-box&gt; | no-clip</code>\",\n            \"description\": \"Sets the area, which is affected by the mask image. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-clip\\\" title=\\\"The mask-clip CSS property determines the area, which is affected by a mask. The painted content of an element must be restricted to this area.\\\"><code>mask-clip</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;compositing-operator&gt;</code>\",\n            \"description\": \"Sets the compositing operation used on the current mask layer. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-composite\\\" title=\\\"The mask-composite CSS property represents a compositing operation used on the current mask layer with the mask layers below it.\\\"><code>mask-composite</code></a>.\"\n        }]\n    },\n    \"mask-clip\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-clip\",\n        \"SUMMARY\": \"The <strong><code>mask-clip</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property determines the area, which is affected by a mask. The painted content of an element must be restricted to this area.\",\n        \"VALUES\": [{\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"The painted content is clipped to the content box.\"\n        }, {\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"The painted content is clipped to the padding box.\"\n        }, {\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"The painted content is clipped to the border box.\"\n        }, {\n            \"value\": \"<code>margin-box</code>\",\n            \"description\": \"The painted content is clipped to the margin box.\"\n        }, {\n            \"value\": \"<code>fill-box</code>\",\n            \"description\": \"The painted content is clipped to the object bounding box.\"\n        }, {\n            \"value\": \"<code>stroke-box</code>\",\n            \"description\": \"The painted content is clipped to the stroke bounding box.\"\n        }, {\n            \"value\": \"<code>view-box</code>\",\n            \"description\": \"Uses the nearest SVG viewport as reference box. If a <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox\\\">viewBox</a></code> attribute is specified for the element creating the SVG viewport, the reference box is positioned at the origin of the coordinate system established by the <code>viewBox</code> attribute and the dimension of the reference box is set to the width and height values of the <code>viewBox</code> attribute.\"\n        }, {\n            \"value\": \"<code>no-clip</code>\",\n            \"description\": \"The painted content is not clipped.\"\n        }, {\n            \"value\": \"<code>border</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword behaves the same as <code>border-box</code>.\"\n        }, {\n            \"value\": \"<code>padding</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword behaves the same as <code>padding-box</code>.\"\n        }, {\n            \"value\": \"<code>content</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword behaves the same as <code>content-box</code>.\"\n        }, {\n            \"value\": \"<code>text</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword clips the mask image to the text of the element.\"\n        }]\n    },\n    \"mask-composite\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-composite\",\n        \"SUMMARY\": \"The <strong><code>mask-composite</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property represents a compositing operation used on the current mask layer with the mask layers below it.\",\n        \"VALUES\": [{\n            \"value\": \"<code>add</code>\",\n            \"description\": \"The source is placed over the destination.\"\n        }, {\n            \"value\": \"<code>subtract</code>\",\n            \"description\": \"The source is placed, where it falls outside of the destination.\"\n        }, {\n            \"value\": \"<code>intersect</code>\",\n            \"description\": \"The parts of source that overlap the destination, replace the destination.\"\n        }, {\n            \"value\": \"<code>exclude</code>\",\n            \"description\": \"The non-overlapping regions of source and destination are combined.\"\n        }]\n    },\n    \"mask-image\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-image\",\n        \"SUMMARY\": \"The <strong><code>mask-image</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property sets the image that is used as mask layer for an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"This keyword is interpreted as a transparent black image layer.\"\n        }, {\n            \"value\": \"<code>&lt;mask-source&gt;</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/url\\\" title=\\\"The &lt;url&gt; CSS data type denotes a pointer to a resource. It has no proper syntax and can only be expressed through the url() functional notation.\\\"><code>&lt;url&gt;</code></a> reference to a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mask\\\" title=\\\"In SVG, you can specify that any other graphics object or &lt;g&gt; element can be used as an alpha mask for compositing the current object into the background. A mask is defined with the &lt;mask&gt; element. A mask is used/referenced using the mask property.\\\"><code>&lt;mask&gt;</code></a> or to a CSS image.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a>\",\n            \"description\": \"An image value used as mask image layer.\"\n        }]\n    },\n    \"mask-mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-mode\",\n        \"SUMMARY\": \"The <strong><code>mask-mode</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property indicates whether the mask reference defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-image\\\" title=\\\"The mask-image CSS property sets the image that is used as mask layer for an element.\\\"><code>mask-image</code></a> is treated as a luminance or alpha mask.\",\n        \"VALUES\": [{\n            \"value\": \"<code>alpha</code>\",\n            \"description\": \"This keyword indicates that the transparency (alpha channel) values of the mask layer image should be used as the mask values.\"\n        }, {\n            \"value\": \"<code>luminance</code>\",\n            \"description\": \"This keyword indicates that the luminance values of the mask layer image should be used as the mask values.\"\n        }, {\n            \"value\": \"<code>match-source</code>\",\n            \"description\": \"\\n <p>If the <a title=\\\"The mask-image CSS property sets the image that is used as mask layer for an element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-image\\\"><code>mask-image</code></a> property is of type &lt;mask-source&gt;, the luminance values of the mask layer image should be used as the mask values.</p>\\n\\n <p>If it is of type <a title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\"><code>&lt;image&gt;</code></a>, the alpha values of the mask layer image should be used as the mask values.</p>\\n \"\n        }]\n    },\n    \"mask-origin\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-origin\",\n        \"SUMMARY\": \"The <strong><code>mask-origin</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property determines the origin of a mask.\",\n        \"VALUES\": [{\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"The position is relative to the content box.\"\n        }, {\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"The position is relative to the padding box. For single boxes <code>0 0</code> is the upper left corner of the padding edge, <code>100% 100%</code> is the lower right corner.\"\n        }, {\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"The position is relative to the border box.\"\n        }, {\n            \"value\": \"<code>margin-box</code>\",\n            \"description\": \"The position is relative to the margin box.\"\n        }, {\n            \"value\": \"<code>fill-box</code>\",\n            \"description\": \"The position is relative to the object bounding box.\"\n        }, {\n            \"value\": \"<code>stroke-box</code>\",\n            \"description\": \"The position is relative to the stroke bounding box.\"\n        }, {\n            \"value\": \"<code>view-box</code>\",\n            \"description\": \"Uses the nearest SVG viewport as reference box. If a <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox\\\">viewBox</a></code> attribute is specified for the element creating the SVG viewport, the reference box is positioned at the origin of the coordinate system established by the <code>viewBox</code> attribute and the dimension of the reference box is set to the width and height values of the <code>viewBox</code> attribute.\"\n        }, {\n            \"value\": \"<code>content</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Same as <code>content-box</code>.\"\n        }, {\n            \"value\": \"<code>padding</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Same as <code>padding-box</code>.\"\n        }, {\n            \"value\": \"<code>border</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Same as <code>border-box</code>.\"\n        }]\n    },\n    \"mask-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\",\n        \"SUMMARY\": \"The <strong><code>mask-position</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property sets the initial position, relative to the mask position layer defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-origin\\\" title=\\\"The mask-origin CSS property determines the origin of a mask.\\\"><code>mask-origin</code></a> for each defined mask image.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;position&gt; CSS data type denotes a coordinate in a 2D space used to set a location relative to a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\\\"><code>&lt;position&gt;</code></a>, that is one to four values representing a 2D position regarding the edges of the element&apos;s box. Relative or absolute offsets can be given. Note that the position can be set outside of the element&apos;s box.\"\n        }]\n    },\n    \"mask-repeat\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-repeat\",\n        \"SUMMARY\": \"The <strong><code>mask-repeat</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines how mask images are repeated. A mask image can be repeated along the horizontal axis, the vertical axis, both axes, or not repeated at all.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;repeat-style&gt;</code>\",\n            \"description\": \"The one-value syntax is a shorthand for the full two-value syntax:\"\n        }, {\n            \"value\": \"\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td><strong>Single value</strong></td>\\n    <td><strong>Two-value equivalent</strong></td>\\n   </tr>\\n   <tr>\\n    <td><code>repeat-x</code></td>\\n    <td><code>repeat no-repeat</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>repeat-y</code></td>\\n    <td><code>no-repeat repeat</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>repeat</code></td>\\n    <td><code>repeat repeat</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>space</code></td>\\n    <td><code>space space</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>round</code></td>\\n    <td><code>round round</code></td>\\n   </tr>\\n   <tr>\\n    <td><code>no-repeat</code></td>\\n    <td><code>no-repeat no-repeat</code></td>\\n   </tr>\\n  </tbody>\\n </table>\\n In the two-value syntax, the first value represents the horizontal repetition behavior and the second value represents the vertical behavior. Here is an explanation of how each option works for either direction:\",\n            \"description\": \"\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <td><code>repeat</code></td>\\n    <td>The image is repeated as much as needed to cover the whole mask painting area. The last image will be clipped if it doesn&apos;t fit.</td>\\n   </tr>\\n   <tr>\\n    <td><code>space</code></td>\\n    <td>The image is repeated as much as possible without clipping. The first and last images are pinned to either side of the element, and whitespace is distributed evenly between the images. The <a title=\\\"The mask-position CSS property sets the initial position, relative to the mask position layer defined by mask-origin for each defined mask image.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\\\"><code>mask-position</code></a> property is ignored unless only one image can be displayed without clipping. The only case where clipping happens using <code>space</code> is when there isn&apos;t enough room to display one image.</td>\\n   </tr>\\n   <tr>\\n    <td><code>round</code></td>\\n    <td>As the allowed space increases in size, the repeated images will stretch (leaving no gaps) until there is room for another one to be added. When the next image is added, all of the current ones compress to allow room. Example: An image with an original width of 260px, repeated three times, might stretch until each repetition is 300px wide, and then another image will be added. They will then compress to 225px.</td>\\n   </tr>\\n   <tr>\\n    <td><code>no-repeat</code></td>\\n    <td>The image is not repeated (and hence the mask painting area will not necessarily be entirely covered). The position of the non-repeated mask image is defined by the <a title=\\\"The mask-position CSS property sets the initial position, relative to the mask position layer defined by mask-origin for each defined mask image.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\\\"><code>mask-position</code></a> CSS property.</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"mask-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-size\",\n        \"SUMMARY\": \"The <strong><code>mask-size</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the sizes of the mask images. The size of the image can be fully or partially constrained in order to preserve its intrinsic ratio.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"A <code><a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a></code> value&#xA0;scales the mask image to the specified length in the corresponding dimension. Negative lengths are not allowed.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> value scales the mask image in the corresponding dimension to the specified percentage of the mask positioning area, which is determined by the value of <a title=\\\"The mask-origin CSS property determines the origin of a mask.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-origin\\\"><code>mask-origin</code></a>. The mask positioning area is, by default, the area containing the content of the box and its padding; the area may also be changed to just the content or to the area containing borders, padding&#xA0;and content. Negative percentages are not allowed.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"A keyword that scales the mask image in the corresponding directions in order to maintain&#xA0;its intrinsic proportion.\"\n        }, {\n            \"value\": \"<code>contain</code>\",\n            \"description\": \"A keyword that scales the image as large as possible and maintains image aspect ratio (image doesn&apos;t get squished). The image is <strong>letterboxed</strong> within the container. The image is automatically centered unless over-ridden by another property such as <a title=\\\"The mask-position CSS property sets the initial position, relative to the mask position layer defined by mask-origin for each defined mask image.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-position\\\"><code>mask-position</code></a>.\"\n        }, {\n            \"value\": \"<code>cover</code>\",\n            \"description\": \"A keyword that is the inverse of <code>contain</code>. Scales the image as large as possible and maintains image aspect ratio (image doesn&apos;t get squished). The image &quot;covers&quot; the entire width or height of the container. When the image and container have different dimensions, <em>the image is clipped</em> either on left/right or &#xA0;at&#xA0;top/bottom.\"\n        }, {\n            \"value\": \"If both components of <code>mask-size</code> are specified and are not <code>auto</code>:\",\n            \"description\": \"The mask image renders at the specified size.\"\n        }, {\n            \"value\": \"If the <code>mask-size</code> is <code>contain</code> or <code>cover</code>:\",\n            \"description\": \"The image is rendered by&#xA0;preserving its intrinsic proportion&#xA0;at the largest size contained within&#xA0;or covering&#xA0;the mask positioning area. If the image has no intrinsic proportion, then it is rendered at the size of the mask positioning area.\"\n        }, {\n            \"value\": \"If the <code>mask-size</code> is <code>auto</code> or <code>auto auto</code>:\",\n            \"description\": \"If the image has both intrinsic dimensions, it is rendered at that size. If it has no intrinsic dimensions and no intrinsic proportion, it is rendered at the size of the mask positioning area. If it has no dimensions but has a proportion, it&apos;s rendered as if <code>contain</code> had been specified instead. If the image has one intrinsic dimension and a proportion, it&apos;s rendered at the size determined by that one dimension and the proportion. If the image has one intrinsic dimension but no proportion, it&apos;s rendered using the intrinsic dimension and the corresponding dimension of the mask positioning area.\"\n        }, {\n            \"value\": \"If <code>mask-size</code> has one <code>auto</code> component and one non-<code>auto</code> component:\",\n            \"description\": \"If the image has an intrinsic proportion, then render it using the specified dimension&#xA0;and compute the other dimension from the specified dimension and the intrinsic proportion. If the image has no intrinsic proportion, use the specified dimension for that dimension. For the other dimension, use the image&apos;s corresponding intrinsic dimension if there is one.&#xA0; If there is no such intrinsic dimension, use the corresponding dimension of the mask positioning area.\"\n        }]\n    },\n    \"mask-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mask-type\",\n        \"SUMMARY\": \"The CSS <strong><code>mask-type</code></strong> properties defines if a mask is used as a <em>luminance</em> or an <em>alpha</em> mask.\",\n        \"VALUES\": [{\n            \"value\": \"<code>luminance</code>\",\n            \"description\": \"Is a keyword indicating that the associated mask image is a luminance mask, that is that its <a href=\\\"https://en.wikipedia.org/wiki/Luminance_%28relative%29\\\" class=\\\"external\\\">relative luminance</a> values must be used when applying it.\"\n        }, {\n            \"value\": \"<code>alpha</code>\",\n            \"description\": \"Is a keyword indicating that the associated mask image is an alpha mask, that is that its <a href=\\\"https://en.wikipedia.org/wiki/Alpha_compositing\\\" class=\\\"external\\\">alpha channel</a> values must be used when applying it.\"\n        }]\n    },\n    \"max-block-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/max-block-size\",\n        \"SUMMARY\": \"The<strong> <code>max-block-size</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the horizontal or vertical maximal size of an element's block depending on its writing mode. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\" title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\"><code>max-width</code></a> or the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\" title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\"><code>max-height</code></a> property, depending on the value defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>. If the writing mode is vertically oriented, the value of <code>max-block-size</code> relates to the maximal width of the element, otherwise it relates to the maximal height of the element. It relates to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-inline-size\\\" title=\\\"The max-inline-size CSS property defines the horizontal or vertical maximal size of an element's block depending on its writing mode. It corresponds to the max-width or the max-height property depending on the value defined for writing-mode. If the writing mode is vertically oriented, the value of max-inline-size relates to the maximal height of the element, otherwise it relates to the maximal width of the element. It relates to max-block-size, which defines the other dimension of the element.\\\"><code>max-inline-size</code></a>, which defines the other dimension of the element.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>max-block-size</code> property takes the same values as the <a title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\"><code>max-width</code></a> and <a title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\"><code>max-height</code></a> properties.\"\n        }]\n    },\n    \"max-height\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\",\n        \"SUMMARY\": \"The <strong><code>max-height</code></strong> property is used to set the maximum height of an element. It prevents the used value of the <a title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\"><code>height</code></a> property from becoming larger than the value specified for <code>max-height</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"A fixed maximum height. See <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"The <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> is calculated with respect to the height of the containing block. If the height of the containing block is not specified explicitly, the percentage value is treated as <code>zero</code>.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No limit on the height of the box.\"\n        }, {\n            \"value\": \"<code>max-content</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic preferred height.\"\n        }, {\n            \"value\": \"<code>min-content</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic minimum height.\"\n        }, {\n            \"value\": \"<code>fill-available</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The containing block height minus vertical margin, border and padding. Some browsers implement an ancient name for this keyword, <code>available</code>.\"\n        }, {\n            \"value\": \"<code>fit-content</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The same as <code>max-content.</code>\"\n        }]\n    },\n    \"max-inline-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/max-inline-size\",\n        \"SUMMARY\": \"The <strong><code>max-inline-size</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the horizontal or vertical maximal size of an element's block depending on its writing mode. It corresponds to the <a title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\"><code>max-width</code></a> or the <a title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\"><code>max-height</code></a> property depending on the value defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>. If the writing mode is vertically oriented, the value of <code>max-inline-size</code> relates to the maximal height of the element, otherwise it relates to the maximal width of the element. It relates to <a title=\\\"The max-block-size CSS property defines the horizontal or vertical maximal size of an element's block depending on its writing mode. It corresponds to the max-width or the max-height property, depending on the value defined for writing-mode. If the writing mode is vertically oriented, the value of max-block-size relates to the maximal width of the element, otherwise it relates to the maximal height of the element. It relates to max-inline-size, which defines the other dimension of the element.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-block-size\\\"><code>max-block-size</code></a>, which defines the other dimension of the element.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>max-inline-size</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\" title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\"><code>max-width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\" title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\"><code>max-height</code></a> properties.\"\n        }]\n    },\n    \"max-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\",\n        \"SUMMARY\": \"The <strong><code>max-width</code></strong> property is used to set the maximum width of a given element. It prevents the used value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> property from becoming larger than the value specified for <code>max-width</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The width has no maximum value.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Specified as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of containing block&apos;s width.\"\n        }, {\n            \"value\": \"<code>max-content</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic preferred width.\"\n        }, {\n            \"value\": \"<code>min-content</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic minimum width.\"\n        }, {\n            \"value\": \"<code>fill-available</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The containing block width minus horizontal margin, border, and padding. Some browsers implement an ancient name for this keyword, <code>available</code>.\"\n        }, {\n            \"value\": \"<code>fit-content</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The same as <code>max-content.</code>\"\n        }]\n    },\n    \"min-block-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/min-block-size\",\n        \"SUMMARY\": \"The<strong> <code>min-block-size</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the horizontal or vertical minimal size of an element's block depending on its writing mode. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a> or the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"Technical review completed.\\\"><code>min-height</code></a> property, depending on the value defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>. If the writing mode is vertically oriented, the value of <code>min-block-size</code> relates to the minimal width of the element, otherwise it relates to the minimal height of the element. It relates to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-inline-size\\\" title=\\\"The min-inline-size CSS property defines the horizontal or vertical minimal size of an element's block depending on its writing mode. It corresponds to the min-width or the min-height property, depending on the value defined for writing-mode. If the writing mode is vertically oriented, the value of min-inline-size relates to the minimal height of the element, otherwise it relates to the minimal width of the element. It relates to min-block-size, which defines the other dimension of the element.\\\"><code>min-inline-size</code></a>, which defines the other dimension of the element.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>min-block-size</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"Technical review completed.\\\"><code>min-height</code></a> properties.\"\n        }]\n    },\n    \"min-height\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\",\n        \"SUMMARY\": \"The<strong> <code>min-height</code></strong> property is used to set the minimum height of a given element. It prevents the used value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/height\\\" title=\\\"The height CSS property specifies the height of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>height</code></a> property from becoming smaller than the value specified for <code>min-height</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"The fixed minimum height. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units. Negative values make the declaration invalid.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"The fixed minimum height expressed as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of containing block&apos;s height. Negative values make the declaration invalid.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The default minimum size for flex items, providing a more reasonable default than 0 for other layouts.\"\n        }, {\n            \"value\": \"<code>max-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic preferred height.\"\n        }, {\n            \"value\": \"<code>min-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic minimum height.\"\n        }, {\n            \"value\": \"<code>fill-available</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The containing block height minus horizontal margin, border and padding. Some browsers implement an ancient name for this keyword, <code>available</code>.\"\n        }, {\n            \"value\": \"<code>fit-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"According CSS3 Box, this is a synonym of <code>min-content.</code> CSS3 Sizing defines a more complex algorithm, but no browser implements it, even in an experimental way.\"\n        }]\n    },\n    \"min-inline-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/min-inline-size\",\n        \"SUMMARY\": \"The <strong><code>min-inline-size</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the horizontal or vertical minimal size of an element's block depending on its writing mode. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a> or the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"Technical review completed.\\\"><code>min-height</code></a> property, depending on the value defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>. If the writing mode is vertically oriented, the value of <code>min-inline-size</code> relates to the minimal height of the element, otherwise it relates to the minimal width of the element. It relates to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-block-size\\\" title=\\\"The min-block-size CSS property defines the horizontal or vertical minimal size of an element's block depending on its writing mode. It corresponds to the min-width or the min-height property, depending on the value defined for writing-mode. If the writing mode is vertically oriented, the value of min-block-size relates to the minimal width of the element, otherwise it relates to the minimal height of the element. It relates to min-inline-size, which defines the other dimension of the element.\\\"><code>min-block-size</code></a>, which defines the other dimension of the element.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>min-inline-size</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"Technical review completed.\\\"><code>min-height</code></a> properties.\"\n        }]\n    },\n    \"min-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\",\n        \"SUMMARY\": \"The <strong><code>min-width</code></strong> property is used to set the minimum width of a given element. It prevents the used value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>width</code></a> property from becoming smaller than the value specified for <code>min-width</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"The fixed minimum width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units. Negative values make the declaration invalid.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"The fixed minimum width expressed as a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of containing block&apos;s width. Negative values make the declaration invalid.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The default minimum size for flex items, providing a more reasonable default than 0 for other layouts.\"\n        }, {\n            \"value\": \"<code>max-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic preferred width.\"\n        }, {\n            \"value\": \"<code>min-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic minimum width.\"\n        }, {\n            \"value\": \"<code>fill-available</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The containing block width minus horizontal margin, border and padding. Some browsers implement an ancient name for this keyword, <code>available</code>.\"\n        }, {\n            \"value\": \"<code>fit-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Defined as <code>min(max-content, max(min-content, fill-available)</code>.\"\n        }]\n    },\n    \"minmax()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/minmax\",\n        \"SUMMARY\": \"The <code><strong>minmax</strong></code><strong><code>()</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> function defines a size range greater than or equal to <var>min</var> and less than or equal to <var>max</var>. If <var>max</var> &lt; <var>min</var>, then <var>max</var> is ignored and <code>minmax(min,max)</code> is treated as <var>min</var>. As a maximum, a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/flex\\\" title=\\\"The flex CSS property is a shorthand property specifying the ability of a flex item to alter its dimensions to fill available space. Flex items can be stretched to use available space proportional to their flex grow factor or their flex shrink factor to prevent overflow.\\\"><code>&lt;flex&gt;</code></a> value sets the flex factor of a grid track; it is invalid as a minimum.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;length&gt;\",\n            \"description\": \"A non-negative length.\"\n        }, {\n            \"value\": \"&lt;percentage&gt;\",\n            \"description\": \"A non-negative percentage relative to the inline size of the grid container in column grid tracks, and the block size of the grid container in row grid tracks. If the size of the grid container depends on the size of its tracks, then the <code>&lt;percentage&gt;</code> must be treated as <code>auto</code>. The UA may adjust the intrinsic size contributions of the track to the size of the grid container and increase the final size of the track by the minimum amount that would result in honoring the percentage.\"\n        }, {\n            \"value\": \"&lt;flex&gt;\",\n            \"description\": \"A non-negative dimension with the unit <code>fr</code> specifying the track&#x2019;s flex factor. Each <code>&lt;flex&gt;</code>-sized track takes a share of the remaining space in proportion to its flex factor.\"\n        }, {\n            \"value\": \"max-content\",\n            \"description\": \"Represents the largest max-content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"min-content\",\n            \"description\": \"Represents the largest min-content contribution of the grid items occupying the grid track.\"\n        }, {\n            \"value\": \"auto\",\n            \"description\": \"As a maximum, identical to <code>max-content</code>. As a minimum it represents the largest minimum size (as specified by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\\\" title=\\\"The min-width property is used to set the minimum width of a given element. It prevents the used value of the width property from becoming smaller than the value specified for min-width.\\\"><code>min-width</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\\\" title=\\\"The min-height property is used to set the minimum height of a given element. It prevents the used value of the height property from becoming smaller than the value specified for min-height.\\\"><code>min-height</code></a>) of the grid items occupying the grid track.\"\n        }]\n    },\n    \"mix-blend-mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode\",\n        \"SUMMARY\": \"The <strong><code>mix-blend-mode</code></strong> CSS property describes how an element's content should blend with the content of the element's direct parent and the element's background.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;blend-mode&gt;</code>\",\n            \"description\": \"Is a <a title=\\\"The &lt;blend-mode&gt;&#xA0;type is a collection of keywords describing blend modes.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode\\\"><code>&lt;blend-mode&gt;</code></a> denoting the blending mode that should be applied. There can be several values, separated by commas.\"\n        }]\n    },\n    \"object-fit\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit\",\n        \"SUMMARY\": \"The <strong><code>object-fit</code></strong> CSS property specifies how the contents of a replaced element should be fitted to the box established by its used height and width.\",\n        \"VALUES\": [{\n            \"value\": \"<code>fill</code>\",\n            \"description\": \"The replaced content is sized to fill the element&#x2019;s content box: the object&#x2019;s concrete object size is the element&#x2019;s used width and height.\"\n        }, {\n            \"value\": \"<code>contain</code>\",\n            \"description\": \"The replaced content is sized to maintain its aspect ratio while fitting within the element&#x2019;s content box: its concrete object size is resolved as a contain constraint against the element&#x2019;s used width and height.\"\n        }, {\n            \"value\": \"<code>cover</code>\",\n            \"description\": \"The replaced content is sized to maintain its aspect ratio while filling the element&#x2019;s entire content box: its concrete object size is resolved as a cover constraint against the element&#x2019;s used width and height.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The replaced content is not resized to fit inside the element&#x2019;s content box: the object&#x2019;s concrete object size is determined using the default sizing algorithm with no specified size, and a default object size equal to the replaced element&#x2019;s used width and height.\"\n        }, {\n            \"value\": \"<code>scale-down</code>\",\n            \"description\": \"The content is sized as if <code>none</code> or <code>contain</code> were specified, whichever would result in a smaller concrete object size.\"\n        }]\n    },\n    \"object-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/object-position\",\n        \"SUMMARY\": \"The <strong><code>object-position</code></strong> property determines the alignment of the replaced element inside its box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\\\" title=\\\"The &lt;position&gt; CSS data type denotes a coordinate in a 2D space used to set a location relative to a box.\\\"><code>&lt;position&gt;</code></a>, that is one to four values representing a 2D position regarding the edges of the element&apos;s box. Relative or absolute offsets can be given. Note that the position can be set outside of the element&apos;s box.\"\n        }]\n    },\n    \"offset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset\",\n        \"SUMMARY\": \"The <strong><code>offset</code></strong> CSS property is a shorthand property for animating an element along a defined path.\",\n        \"VALUES\": []\n    },\n    \"offset-block-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-block-end\",\n        \"SUMMARY\": \"The<strong> <code>offset-block-end</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the logical block end offset of an element, which maps to a physical offset depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\"><code>top</code></a>, <a title=\\\"Technical review completed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\"><code>right</code></a>, <a title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\"><code>bottom</code></a>, or <a title=\\\"The left CSS property specifies part of the position of positioned elements.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\"><code>left</code></a> property depending on the values defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>, <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a>, and <a title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>offset-block-end</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property.\"\n        }]\n    },\n    \"offset-block-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-block-start\",\n        \"SUMMARY\": \"The <strong><code>offset-block-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical block start offset of an element, which maps to a physical offset depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\" title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\"><code>top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\" title=\\\"Technical review completed.\\\"><code>right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\" title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\"><code>bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>offset-block-start</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property.\"\n        }]\n    },\n    \"offset-distance\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-distance\",\n        \"SUMMARY\": \"The <strong><code>offset-distance</code></strong> CSS property specifies a position along an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-path\\\" title=\\\"The offset-path CSS property specifies the&#xA0;offset path where the element gets positioned. The exact element&#x2019;s position on the offset path is determined by the offset-distance property. An offset&#xA0;path&#xA0;is either a specified path with one or multiple sub-paths or the geometry of a not-styled basic shape. Each shape or path must define an&#xA0;initial position&#xA0;for the computed value of &quot;0&quot; for offset-distance and an&#xA0;initial direction&#xA0;which specifies the rotation of the object to the initial position.\\\"><code>offset-path</code></a>.\",\n        \"VALUES\": []\n    },\n    \"offset-inline-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-inline-end\",\n        \"SUMMARY\": \"The <strong><code>offset-inline-end</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical inline end offset of an element, which maps to a physical offset depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\" title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\"><code>top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\" title=\\\"Technical review completed.\\\"><code>right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\" title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\"><code>bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>offset-inline-end</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property.\"\n        }]\n    },\n    \"offset-inline-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-inline-start\",\n        \"SUMMARY\": \"The <strong><code>offset-inline-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical inline start offset of an element, which maps to a physical offset depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/top\\\" title=\\\"The top CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\\\"><code>top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/right\\\" title=\\\"Technical review completed.\\\"><code>right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\" title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\"><code>bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>offset-inline-start</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property.\"\n        }]\n    },\n    \"offset-path\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-path\",\n        \"SUMMARY\": \"The <strong><code>offset-path</code></strong> CSS property specifies the offset path where the element gets positioned. The exact element’s position on the offset path is determined by the <a title=\\\"The&#xA0;offset-distance CSS property specifies a position along an offset-path.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-distance\\\"><code>offset-distance</code></a> property. An offset path is either a specified path with one or multiple sub-paths or the geometry of a not-styled basic shape. Each shape or path must define an initial position for the computed value of \\\"0\\\" for <a title=\\\"The&#xA0;offset-distance CSS property specifies a position along an offset-path.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-distance\\\"><code>offset-distance</code></a> and an initial direction which specifies the rotation of the object to the initial position.\",\n        \"VALUES\": []\n    },\n    \"offset-rotate\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/offset-rotate\",\n        \"SUMMARY\": \"The <strong><code>offset-rotate</code></strong> CSS property defines the direction of the element while positioning along the offset path.\",\n        \"VALUES\": []\n    },\n    \"opacity\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/opacity\",\n        \"SUMMARY\": \"The <strong><code>opacity</code></strong> CSS property specifies the transparency of an element, that is, the degree to which the background behind the element is overlaid.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;number&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> in the range <code>0.0</code> to <code>1.0</code>, both included, representing the opacity of the channel, that is the value of its alpha channel. Any value outside the interval, though valid, is clamped to the nearest limit in the range.\\n <table class=\\\"standard-table\\\">\\n  <tbody>\\n   <tr>\\n    <th>Value</th>\\n    <th>Meaning</th>\\n   </tr>\\n   <tr>\\n    <td><code>0</code></td>\\n    <td>The element is fully transparent (that is, invisible).</td>\\n   </tr>\\n   <tr>\\n    <td>Any <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\" title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\"><code>&lt;number&gt;</code></a> strictly between <code>0</code> and <code>1</code></td>\\n    <td>The element is translucent (that is, background can be seen).</td>\\n   </tr>\\n   <tr>\\n    <td><code>1</code></td>\\n    <td>The element is fully opaque (solid).</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }]\n    },\n    \"order\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/order\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <strong><code>order</code></strong> property specifies the order used to lay out flex items in their flex container. Elements are laid out in the ascending order of the <code>order</code> value. Elements with the same <code>order</code> value are laid out in the order in which they appear in the source code.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"Represents the ordinal group the flex item has been assigned.\"\n        }]\n    },\n    \"orphans\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/orphans\",\n        \"SUMMARY\": \"The <strong><code>orphans</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property refers to the <em>minimum</em> number of lines in a block container that must be left at the bottom of the page. This property is normally used to control how page breaks occur.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"Only positive values are allowed.\"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Takes the same specified value as the property for the element&apos;s parent.\"\n        }]\n    },\n    \"outline\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/outline\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> <strong><code>outline</code></strong> property is a shorthand property for setting one or more of the individual outline properties <a title=\\\"The outline-style CSS property is used to set the style of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-style\\\"><code>outline-style</code></a>, <a title=\\\"The outline-width CSS property is used to set the width of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width\\\"><code>outline-width</code></a> and <a title=\\\"The outline-color CSS property sets the color of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-color\\\"><code>outline-color</code></a> in a single declaration. In most cases the use of this shortcut is preferable and more convenient.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;&apos;outline-width&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width\\\" title=\\\"The outline-width CSS property is used to set the width of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out:\\\"><code>outline-width</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;outline-style&apos;&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-style\\\" title=\\\"The outline-style CSS property is used to set the style of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\\\"><code>outline-style</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;&apos;outline-color&apos;&gt;</code>\",\n            \"description\": \"Since Gecko 1.9 (Firefox 3), the value of the element&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color\\\" title=\\\"The color property sets the foreground color of an element&apos;s text content, and its decorations. It doesn&apos;t affect any other characteristic of the element; it should really be called text-color and would have been named so, save for historical reasons and its appearance in CSS Level 1.\\\"><code>color</code></a> property (foreground color) is used. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-color\\\" title=\\\"The outline-color CSS property sets the color of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\\\"><code>outline-color</code></a>.\"\n        }]\n    },\n    \"outline-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-color\",\n        \"SUMMARY\": \"The <strong><code>outline-color</code></strong> CSS property sets the color of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> for the various color keywords and notations.\"\n        }, {\n            \"value\": \"<code>invert</code>\",\n            \"description\": \"To ensure the outline is visible, performs a color inversion of the background. This makes the focus border more salient, regardless of the color in the background. Note that browsers are not required to support it. If not, they just consider the statement as invalid\"\n        }]\n    },\n    \"outline-offset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-offset\",\n        \"SUMMARY\": \"The <strong><code>outline-offset</code></strong> CSS property is used to set space between an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline\\\" title=\\\"The CSS outline property is a shorthand property for setting one or more of the individual outline properties outline-style, outline-width and outline-color in a single declaration. In most cases the use of this shortcut is preferable and more convenient.\\\"><code>outline</code></a> and the edge or border of an element. An outline is a line that is drawn around elements, outside the border edge.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"The width of the space. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for possible units. Negative values place the outline inside the element.\"\n        }]\n    },\n    \"outline-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-style\",\n        \"SUMMARY\": \"The <strong><code>outline-style</code></strong> CSS property is used to set the style of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\",\n        \"VALUES\": [{\n            \"value\": \"none\",\n            \"description\": \"\"\n        }, {\n            \"value\": \"No outline (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width\\\" title=\\\"The outline-width CSS property is used to set the width of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out:\\\"><code>outline-width</code></a> is<code> 0</code>).\",\n            \"description\": \"dotted\"\n        }, {\n            \"value\": \"\",\n            \"description\": \"The outline is a series of dots.\"\n        }, {\n            \"value\": \"dashed\",\n            \"description\": \"\"\n        }, {\n            \"value\": \"The outline is a series of short line segments.\",\n            \"description\": \"solid\"\n        }, {\n            \"value\": \"\",\n            \"description\": \"The outline is a single line.\"\n        }, {\n            \"value\": \"double\",\n            \"description\": \"\"\n        }, {\n            \"value\": \"The outline is two single lines. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width\\\" title=\\\"The outline-width CSS property is used to set the width of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out:\\\"><code>outline-width</code></a> is the sum of the two lines and the space between them.\",\n            \"description\": \"groove\"\n        }, {\n            \"value\": \"\",\n            \"description\": \"The outline looks as though it were carved into the canvas.\"\n        }, {\n            \"value\": \"ridge\",\n            \"description\": \"\"\n        }, {\n            \"value\": \"The opposite of<code> groove</code>: the outline looks as though it were coming out of the canvas.\",\n            \"description\": \"inset\"\n        }, {\n            \"value\": \"\",\n            \"description\": \"The outline makes the box look as though it were embeded in the canvas.\"\n        }, {\n            \"value\": \"outset\",\n            \"description\": \"\"\n        }]\n    },\n    \"outline-width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/outline-width\",\n        \"SUMMARY\": \"The <strong><code>outline-width</code></strong> CSS property is used to set the width of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out:\",\n        \"VALUES\": [{\n            \"value\": \"<code>thin</code>\",\n            \"description\": \"Depends on the UA. Typically <strong>1px</strong> in desktop browsers like Firefox.\"\n        }, {\n            \"value\": \"<code>medium</code>\",\n            \"description\": \"Depends on the UA. Typically <strong>3px</strong> in desktop browsers like Firefox.\"\n        }, {\n            \"value\": \"<code>thick</code>\",\n            \"description\": \"Depends on the UA. Typically <strong>5px</strong> in desktop browsers like Firefox.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> values.\"\n        }]\n    },\n    \"overflow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow\",\n        \"SUMMARY\": \"The <strong><code>overflow</code></strong> property specifies whether to clip content, render scrollbars or just display content when it overflows its block level container.\",\n        \"VALUES\": [{\n            \"value\": \"<code>visible</code>\",\n            \"description\": \"Default value. Content is not clipped, it may be rendered outside the content box.\"\n        }, {\n            \"value\": \"<code>hidden</code>\",\n            \"description\": \"The content is clipped and no scrollbars are provided.\"\n        }, {\n            \"value\": \"<code>scroll</code>\",\n            \"description\": \"The content is clipped and desktop browsers use scrollbars, whether or not any content is clipped. This avoids any problem with scrollbars appearing and disappearing in a dynamic environment. Printers may print overflowing content.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Depends on the user agent. Desktop browsers like Firefox provide scrollbars if content overflows.\"\n        }, {\n            \"value\": \"<code>-moz-scrollbars-none </code><span title=\\\"This is an obsolete API and is no longer guaranteed to work.\\\"><i class=\\\"icon-trash\\\"> </i></span>\",\n            \"description\": \"Use <code>overflow:hidden</code> instead.\"\n        }, {\n            \"value\": \"<code>-moz-scrollbars-horizontal </code><span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Use of <a title=\\\"The overflow-x property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the left and right edges.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-x\\\"><code>overflow-x</code></a> and <a title=\\\"The overflow-y property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the top and bottom edges.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y\\\"><code>overflow-y</code></a> is preferred.\"\n        }, {\n            \"value\": \"<code>-moz-scrollbars-vertical </code><span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Use of <a title=\\\"The overflow-x property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the left and right edges.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-x\\\"><code>overflow-x</code></a> and <a title=\\\"The overflow-y property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the top and bottom edges.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y\\\"><code>overflow-y</code></a> is preferred.\"\n        }, {\n            \"value\": \"-moz-hidden-unscrollable <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Is intended mainly for internal use and by themes. Disables scrolling of XML root elements and <code>&lt;html&gt;</code>, <code> &lt;body&gt;</code> by arrow keys and mouse wheel.\"\n        }]\n    },\n    \"overflow-clip-box\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-box\",\n        \"SUMMARY\": \"The <code>overflow-clip-box</code> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies relative to which box the clipping happens when there is an overflow.\",\n        \"VALUES\": [{\n            \"value\": \"<code>padding-box</code>\",\n            \"description\": \"This keyword makes the clipping be related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model#padding-area\\\">padding box</a>.\"\n        }, {\n            \"value\": \"<code>content-box</code>\",\n            \"description\": \"This keyword makes the clipping be related to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model#content-area\\\">content box</a>.\"\n        }]\n    },\n    \"overflow-wrap\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap\",\n        \"SUMMARY\": \"The <code><strong>overflow</strong></code><strong><code>-wrap</code></strong> property is used to specify whether or not the browser may break lines within words in order to prevent overflow when an otherwise unbreakable string is too long to fit in its containing box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Indicates that lines may only break at normal word break points.\"\n        }, {\n            \"value\": \"<code>break-word</code>\",\n            \"description\": \"Indicates that normally unbreakable words may be broken at arbitrary points if there are no otherwise acceptable break points in the line.\"\n        }]\n    },\n    \"overflow-x\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-x\",\n        \"SUMMARY\": \"The<strong> <code>overflow-x</code></strong> property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the left and right edges.\",\n        \"VALUES\": [{\n            \"value\": \"<code>visible</code>\",\n            \"description\": \"Content is not clipped, it may be rendered outside the content box.\"\n        }, {\n            \"value\": \"<code>hidden</code>\",\n            \"description\": \"The content is clipped and no scrollbars are provided.\"\n        }, {\n            \"value\": \"<code>scroll</code>\",\n            \"description\": \"The content is clipped and desktop browsers use scrollbars, whether or not any content is clipped. This avoids any problem with scrollbars appearing and disappearing in a dynamic environment. Printers may print overflowing content.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Depends on the user agent. Desktop browsers like Firefox provide scrollbars if content overflows.\"\n        }]\n    },\n    \"overflow-y\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y\",\n        \"SUMMARY\": \"The <strong><code>overflow-y</code></strong> property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the top and bottom edges.\",\n        \"VALUES\": [{\n            \"value\": \"<code>visible</code>\",\n            \"description\": \"Content is not clipped, it may be rendered outside the content box.\"\n        }, {\n            \"value\": \"<code>hidden</code>\",\n            \"description\": \"The content is clipped and no scrollbars are provided.\"\n        }, {\n            \"value\": \"<code>scroll</code>\",\n            \"description\": \"The content is clipped and desktop browsers use scrollbars, whether or not any content is clipped. This avoids any problem with scrollbars appearing and disappearing in a dynamic environment. Printers may print overflowing content.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Depends on the user agent. Desktop browsers like Firefox provide scrollbars if content overflows.\"\n        }]\n    },\n    \"padding\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding\",\n        \"SUMMARY\": \"The <strong><code>padding</code></strong> property sets the padding space on all sides of an element. The <a href=\\\"/en/CSS/box_model#padding\\\" title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\">padding area</a> is the space between the content of the element and its border. Negative values are not allowed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies a non-negative fixed width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for details.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"With respect to the<strong> width </strong>of the containing block.\"\n        }]\n    },\n    \"padding-block-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-block-end\",\n        \"SUMMARY\": \"The <strong><code>padding-block-end</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical block end padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top\\\" title=\\\"The padding-top CSS property of an element sets the padding space required on the top of an element. The padding area is the space between the content of the element and its border. Contrary to margin-top values, negative values of padding-top are invalid.\\\"><code>padding-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right\\\" title=\\\"The padding-right CSS property of an element sets the padding space required on the right side of an element. The padding area is the space between the content of the element and its border. Negative values are not allowed.\\\"><code>padding-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom\\\" title=\\\"The padding-bottom CSS property of an element sets the height of the padding area at the bottom of an element. The padding area is the space between the content of the element and its border. Contrary to margin-bottom values, negative values of padding-bottom are invalid.\\\"><code>padding-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it's border. A negative value is not allowed.\\\"><code>padding-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>padding-block-end</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it&apos;s border. A negative value is not allowed.\\\"><code>padding-left</code></a> property.\"\n        }]\n    },\n    \"padding-block-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-block-start\",\n        \"SUMMARY\": \"The <strong><code>padding-block-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the logical block start padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top\\\" title=\\\"The padding-top CSS property of an element sets the padding space required on the top of an element. The padding area is the space between the content of the element and its border. Contrary to margin-top values, negative values of padding-top are invalid.\\\"><code>padding-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right\\\" title=\\\"The padding-right CSS property of an element sets the padding space required on the right side of an element. The padding area is the space between the content of the element and its border. Negative values are not allowed.\\\"><code>padding-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom\\\" title=\\\"The padding-bottom CSS property of an element sets the height of the padding area at the bottom of an element. The padding area is the space between the content of the element and its border. Contrary to margin-bottom values, negative values of padding-bottom are invalid.\\\"><code>padding-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it's border. A negative value is not allowed.\\\"><code>padding-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>padding-block-start</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it&apos;s border. A negative value is not allowed.\\\"><code>padding-left</code></a> property.\"\n        }]\n    },\n    \"padding-bottom\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom\",\n        \"SUMMARY\": \"The <strong><code>padding-bottom</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property of an element sets the height of the padding area at the bottom of an element. The <a href=\\\"/en/CSS/box_model#padding\\\" title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\">padding area</a> is the space between the content of the element and its border. Contrary to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\\\" title=\\\"The margin-bottom CSS property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\\\"><code>margin-bottom</code></a> values, negative values of <code>padding-bottom</code> are invalid.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;length&gt;\",\n            \"description\": \"Specifies a positive fixed width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for details.\"\n        }, {\n            \"value\": \"&lt;percentage&gt;\",\n            \"description\": \"A percentage with respect to the width of the containing block.\"\n        }]\n    },\n    \"padding-inline-end\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-inline-end\",\n        \"SUMMARY\": \"The <strong><code>padding-inline-end</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the logical inline end padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a title=\\\"The padding-top CSS property of an element sets the padding space required on the top of an element. The padding area is the space between the content of the element and its border. Contrary to margin-top values, negative values of padding-top are invalid.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top\\\"><code>padding-top</code></a>, <a title=\\\"The padding-right CSS property of an element sets the padding space required on the right side of an element. The padding area is the space between the content of the element and its border. Negative values are not allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right\\\"><code>padding-right</code></a>, <a title=\\\"The padding-bottom CSS property of an element sets the height of the padding area at the bottom of an element. The padding area is the space between the content of the element and its border. Contrary to margin-bottom values, negative values of padding-bottom are invalid.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom\\\"><code>padding-bottom</code></a>, or <a title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it's border. A negative value is not allowed.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\"><code>padding-left</code></a> property depending on the values defined for <a title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\"><code>writing-mode</code></a>, <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a>, and <a title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>padding-inline-end</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it&apos;s border. A negative value is not allowed.\\\"><code>padding-left</code></a> property.\"\n        }]\n    },\n    \"padding-inline-start\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-inline-start\",\n        \"SUMMARY\": \"The<strong> <code>padding-inline-start</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the logical inline start padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation. It corresponds to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top\\\" title=\\\"The padding-top CSS property of an element sets the padding space required on the top of an element. The padding area is the space between the content of the element and its border. Contrary to margin-top values, negative values of padding-top are invalid.\\\"><code>padding-top</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right\\\" title=\\\"The padding-right CSS property of an element sets the padding space required on the right side of an element. The padding area is the space between the content of the element and its border. Negative values are not allowed.\\\"><code>padding-right</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom\\\" title=\\\"The padding-bottom CSS property of an element sets the height of the padding area at the bottom of an element. The padding area is the space between the content of the element and its border. Contrary to margin-bottom values, negative values of padding-bottom are invalid.\\\"><code>padding-bottom</code></a>, or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it's border. A negative value is not allowed.\\\"><code>padding-left</code></a> property depending on the values defined for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\\\" title=\\\"The text-orientation CSS property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when writing-mode is not horizontal-tb. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\\\"><code>text-orientation</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>padding-inline-start</code> property takes the same values as the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\\\" title=\\\"The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and it&apos;s border. A negative value is not allowed.\\\"><code>padding-left</code></a> property.\"\n        }]\n    },\n    \"padding-left\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\",\n        \"SUMMARY\": \"The <strong><code>padding-left</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property of an element sets the padding space required on the left side of an element. The <a href=\\\"/en/CSS/box_model#padding\\\" title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\">padding area</a> is the space between the content of the element and it's border. A negative value is not allowed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies a positive fixed width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for details.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A percentage with respect to the width of the containing block.\"\n        }]\n    },\n    \"padding-right\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right\",\n        \"SUMMARY\": \"The<strong> <code>padding-right</code> </strong><a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property of an element sets the padding space required on the right side of an element. The <a href=\\\"/en/CSS/box_model#padding\\\" title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\">padding area</a> is the space between the content of the element and its border. Negative values are not allowed.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;length&gt;\",\n            \"description\": \"Specifies a positive fixed width. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> for details.\"\n        }, {\n            \"value\": \"&lt;percentage&gt;\",\n            \"description\": \"A percentage with respect to the width of the containing block.\"\n        }]\n    },\n    \"padding-top\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top\",\n        \"SUMMARY\": \"The <strong><code>padding-top</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property of an element sets the padding space required on the top of an element. The <a href=\\\"/en/CSS/box_model#padding\\\" title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\">padding area</a> is the space between the content of the element and its border. Contrary to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\\\" title=\\\"The margin-top CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\\\"><code>margin-top</code></a> values, negative values of <code>padding-top</code> are invalid.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies a positive fixed width. See <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> for details.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"A percentage with respect to the width of the containing block.\"\n        }]\n    },\n    \"page-break-after\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-after\",\n        \"SUMMARY\": \"The <strong><code>page-break-after</code></strong> CSS property adjusts page breaks <em>after</em> the current element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Initial value. Automatic page breaks (neither forced nor forbidden).\"\n        }, {\n            \"value\": \"<code>always</code>\",\n            \"description\": \"Always force page breaks after the element.\"\n        }, {\n            \"value\": \"<code>avoid</code>\",\n            \"description\": \"Avoid page breaks after the element.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Force page breaks after the element so that the next page is formatted as a left page.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Force page breaks after the element so that the next page is formatted as a right page.\"\n        }, {\n            \"value\": \"<code>recto</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If pages progress left-to-right, then this acts like <code>right</code>. If pages progress right-to-left, then this acts like <code>left</code>.\"\n        }, {\n            \"value\": \"<code>verso</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If pages progress left-to-right, then this acts like <code>left</code>. If pages progress right-to-left, then this acts like <code>right</code>.\"\n        }]\n    },\n    \"page-break-before\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-before\",\n        \"SUMMARY\": \"The <strong><code>page-break-before</code></strong> CSS property adjusts page breaks <em>before</em> the current element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Initial value. Automatic page breaks (neither forced nor forbidden).\"\n        }, {\n            \"value\": \"<code>always</code>\",\n            \"description\": \"Always force page breaks before the element.\"\n        }, {\n            \"value\": \"<code>avoid</code>\",\n            \"description\": \"Avoid page breaks before the element.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"Force page breaks before the element so that the next page is formatted as a left page.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"Force page breaks before the element so that the next page is formatted as a right page.\"\n        }, {\n            \"value\": \"<code>recto</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If pages progress left-to-right, then this acts like <code>right</code>. If pages progress right-to-left, then this acts like <code>left</code>.\"\n        }, {\n            \"value\": \"<code>verso</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If pages progress left-to-right, then this acts like <code>left</code>. If pages progress right-to-left, then this acts like <code>right</code>.\"\n        }]\n    },\n    \"page-break-inside\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-inside\",\n        \"SUMMARY\": \"The<strong> <code>page-break-inside</code></strong> CSS property adjusts page breaks <em>inside</em> the current element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Initial value. Automatic page breaks (neither forced nor forbidden).\"\n        }, {\n            \"value\": \"<code>avoid</code>\",\n            \"description\": \"Avoid page breaks inside the element.\"\n        }]\n    },\n    \"perspective\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/perspective\",\n        \"SUMMARY\": \"The <strong><code>perspective</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property determines the distance between the z=0 plane and the user in order to give to the 3D-positioned element some perspective. Each 3D element with z&gt;0 becomes larger; each 3D-element with z&lt;0 becomes smaller. The strength of the effect is determined by the value of this property.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword indicating that no perspective transform has to be applied.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> giving the distance from the user to the z=0 plane. It is used to apply a perspective transform to the element and its content. If it <code>0</code> or a negative value, no perspective transform is applied.\"\n        }]\n    },\n    \"perspective-origin\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/perspective-origin\",\n        \"SUMMARY\": \"The <strong><code>perspective-origin</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property determines the position the viewer is looking at. It is used as the <em>vanishing point</em> by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/perspective\\\" title=\\\"The perspective CSS property determines the distance between the z=0 plane and the user in order to give to the 3D-positioned element some perspective. Each 3D element with z&gt;0 becomes larger; each 3D-element with z&lt;0 becomes smaller. The strength of the effect is determined by the value of this property.\\\"><code>perspective</code></a> property.\",\n        \"VALUES\": [{\n            \"value\": \"<em>x-position</em>\",\n            \"description\": \"Indicates the position of the abscissa of the <em>vanishing point</em>. It can have one of the following values:\\n <ul>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length-percentage\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;length-percentage&gt;</code></a> indicating the position as an absolute length value or relative to the width of the element. The value may be negative.</li>\\n  <li><code>left</code>, a keyword being a shortcut for the <code>0</code> length value.</li>\\n  <li><code>center</code>, a keyword being a shortcut for the <code>50%</code> percentage value.</li>\\n  <li><code>right</code>, a keyword being a shortcut for the <code>100%</code> percentage value.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<em>y-position</em>\",\n            \"description\": \"Indicates the position of the ordinate of the <em>vanishing point</em>. It can have one of the following values:\\n <ul>\\n  <li><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length-percentage\\\" class=\\\"new\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;length-percentage&gt;</code></a> indicating the position as an absolute length value or relative to the height of the element. The value may be negative.</li>\\n  <li><code>top</code>, a keyword being a shortcut for the <code>0</code> length value.</li>\\n  <li><code>center</code>, a keyword being a shortcut for the <code>50%</code> percentage value.</li>\\n  <li><code>bottom</code>, a keyword being a shortcut for the <code>100%</code> percentage value.</li>\\n </ul>\\n \"\n        }]\n    },\n    \"place-content\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/place-content\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <code><strong>place</strong></code><strong><code>-content</code></strong> shorthand property sets both the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-content\\\" title=\\\"The CSS align-content property defines how the browser distributes space between and around content items along the main-axis of their container.\\\"><code>align-content</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content\\\" title=\\\"The CSS justify-content property defines how the browser distributes space between and around content items along the main axis of their container.\\\"><code>justify-content</code></a> properties. The first value is the <code>align-content</code> property value, the second the <code>justify-content</code> one. If the second value is not present, the first value is also used for it.\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The items are packed flush to each other toward the start edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The items are packed flush to each other toward the end edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The items are packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-start or cross-start side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The items are packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-end or cross-end side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>end</code>.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the appropriate axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>space-between</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container. The spacing between each pair of adjacent items is the same. The first item is flush with the main-start edge, and the last item is flush with the main-end edge.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>space-around</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container. The spacing between each pair of adjacent items is the same. The empty space before the first and after the last item equals half of the space between each pair of adjacent items.\"\n        }, {\n            \"value\": \"<code>space-evenly</code>\",\n            \"description\": \"The items are evenly distributed within the alignment container. The spacing between each pair of adjacent items, the main-start edge and the first item, and the main-end edge and the last item, are all exactly the same.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items is less than the size of the alignment container, any <code>auto</code>-sized items have their size increased equally (not proportionally), while still respecting the constraints imposed by <a title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\"><code>max-height</code></a>/<a title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size exactly fills the alignment container\"\n        }]\n    },\n    \"place-items\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/place-items\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> <code><strong>place</strong></code><strong><code>-items</code></strong> shorthand property sets both the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-items\\\" title=\\\"The CSS align-items property defines how the browser distributes space between and around flex items along the cross-axis of their container. This means it works like justify-content but in the perpendicular direction.\\\"><code>align-items</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items\\\" title=\\\"The CSS justify-items property defines the default justify-self for all items of the box, given them the default way of justifying each box along the appropriate axis.\\\"><code>justify-items</code></a> properties. The first value is the <code>align-items</code> property value, the second the <code>justify-items</code> one. If the second value is not present, the first value is also used for it.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The value used is the value of the <code>justiy-items</code> property of the parents box, unless the box has no parent, or is absolutely positioned, in these cases, <code>auto</code> represents <code>normal</code>.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The effect of this keyword is dependent of the layout mode we are in:\\n <ul>\\n  <li>In block-level layouts, the keyword is a synonym of <code>start</code>.</li>\\n  <li>In absolutely-positioned layouts, the keyword behaved like <code>start</code> on <em>replaced</em> absolutely-positioned boxes, and as <code>stretch</code> on <em>all other</em> absolutely-positioned boxes. <span style=\\\"display: none;\\\"> </span><span style=\\\"display: none;\\\">&#xA0;</span><span style=\\\"display: none;\\\"> </span></li>\\n  <li>In table cell layouts, this keyword has no meaning as this property is <em>ignored</em>.</li>\\n  <li>In flexbox layouts, this keyword has no meaning as this property is <em>ignored.</em></li>\\n  <li>In grid layouts, this keyword leads to a behavior similar to the one of <code>stretch</code>, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like <code>start</code>.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The item is packed flush to each other toward the start edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The item is packed flush to each other toward the end edge of the alignment container in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The item ispacked flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-start or cross-start side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The item is packed flush to each other toward the edge of the alignment container depending on the flex container&apos;s main-end or cross-end side.<br>\\n This only applies to flex layout items. For items that are not children of a flex container, this value is treated like <code>end</code>.\"\n        }, {\n            \"value\": \"<code>self-start</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the start side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>self-end</code>\",\n            \"description\": \"The item is packed flush to the edge of the alignment container of the end side of the item, in the appropriate axis.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The items are packed flush to each other toward the center of the of the alignment container.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The items are packed flush to each other toward the left edge of the alignment container. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The items are packed flush to each other toward the right edge of the alignment container in the appropriate axis. If the property&#x2019;s axis is not parallel with the inline axis, this value behaves like <code>start</code>.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items is less than the size of the alignment container, any <code>auto</code>-sized items have their size increased equally (not proportionally), while still respecting the constraints imposed by <a title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\"><code>max-height</code></a>/<a title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size exactly fills the alignment container.\"\n        }]\n    },\n    \"place-self\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/place-self\",\n        \"SUMMARY\": \"The <code><strong>place</strong></code><strong><code>-self</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property shorthand property sets both the <a title=\\\"The align-self CSS property aligns flex items of the current flex line overriding the align-items value. If any of the item's cross-axis margin is set to auto, then align-self is ignored.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-self\\\"><code>align-self</code></a> and <a title=\\\"The CSS justify-self property defines the way of justifying a box inside its containeralong the appropriate axis.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self\\\"><code>justify-self</code></a> properties. The first value is the <code>align-self</code> property value, the second the <code>justify-self</code> one. If the second value is not present, the first value is also used for it.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Computes to the parent&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/align-items\\\" title=\\\"The CSS align-items property defines how the browser distributes space between and around flex items along the cross-axis of their container. This means it works like justify-content but in the perpendicular direction.\\\"><code>align-items</code></a> value.\"\n        }, {\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The effect of this keyword is dependent of the layout mode we are in:\\n <ul>\\n  <li>In absolutely-positioned layouts, the keyword behaves like <code>start</code> on <em>replaced</em> absolutely-positioned boxes, and as <code>stretch</code> on <em>all other</em> absolutely-positioned boxes. <span style=\\\"display: none;\\\"> </span><span style=\\\"display: none;\\\">&#xA0;</span><span style=\\\"display: none;\\\"> </span></li>\\n  <li>In static position of absolutely-positioned layouts, the keyword behaves as <code>stretch</code>.</li>\\n  <li>For flex items, the keyword behaves as <code>stretch</code>.</li>\\n  <li>For grid items, this keyword leads to a behavior similar to the one of <code>stretch</code>, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like <code>start</code>.</li>\\n  <li>The property doesn&apos;t apply to block-level boxes, and to table cells.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>self-start</code>\",\n            \"description\": \"Aligns the items to be flush with the edge of the alignment container corresponding to the item&apos;s start side in the cross axis.\"\n        }, {\n            \"value\": \"<code>self-end</code>\",\n            \"description\": \"Aligns the items to be flush with the edge of the alignment container corresponding to the item&apos;s end side in the cross axis.\"\n        }, {\n            \"value\": \"<code>flex-start</code>\",\n            \"description\": \"The cross-start margin edge of the flex item is flushed with the cross-start edge of the line.\"\n        }, {\n            \"value\": \"<code>flex-end</code>\",\n            \"description\": \"The cross-end margin edge of the flex item is flushed with the cross-end edge of the line.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The flex item&apos;s margin box is centered within the line on the cross-axis. If the cross-size of the item is larger than the flex container, it will overflow equally in both directions.\"\n        }, {\n            \"value\": \"<code>baseline<br>\\n first baseline</code><br>\\n <code>last baseline</code>\",\n            \"description\": \"Specifies participation in first- or last-baseline alignment: aligns the alignment baseline of the box&#x2019;s first or last baseline set with the corresponding baseline in the shared first or last baseline set of all the boxes in its baseline-sharing group.<br>\\n The fallback alignment for <code>first baseline</code> is <code>start</code>, the one for <code>last baseline</code> is <code>end</code>.\"\n        }, {\n            \"value\": \"<code>stretch</code>\",\n            \"description\": \"If the combined size of the items along the cross axis is less than the size of the alignment container and the item is <code>auto</code>-sized, its size is increased equally (not proportionally), while still respecting the constraints imposed by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\\\" title=\\\"The max-height property is used to set the maximum height of an element. It prevents the used value of the height property from becoming larger than the value specified for max-height.\\\"><code>max-height</code></a>/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\\\" title=\\\"The max-width property is used to set the maximum width of a given element. It prevents the used value of the width property from becoming larger than the value specified for max-width.\\\"><code>max-width</code></a> (or equivalent functionality), so that the combined size of all <code>auto</code>-sized items exactly fills the alignment container along the cross axis.\"\n        }]\n    },\n    \"pointer-events\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events\",\n        \"SUMMARY\": \"The CSS property<strong> <code>pointer-events</code></strong> allows authors to control under what circumstances (if any) a particular graphic element can become the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/event.target\\\">target</a> of mouse events. When this property is unspecified, the same characteristics of the <code>visiblePainted</code> value apply to SVG content.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The element behaves as it would if the <code>pointer-events</code> property were not specified. In SVG content, this value and the value <code>visiblePainted</code> have the same effect.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The element is never the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/event.target\\\">target</a> of mouse events; however, mouse events may target its descendant elements if those descendants have <code>pointer-events</code> set to some other value. In these circumstances, mouse events will trigger event listeners on this parent element as appropriate on their way to/from the descendant during the event capture/<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/event.bubbles\\\">bubble</a> phases.\"\n        }, {\n            \"value\": \"<code>visiblePainted</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the <code>visibility</code> property is set to <code>visible</code> and when the mouse cursor is over the interior (i.e., &apos;fill&apos;) of the element and the <code>fill</code> property is set to a value other than <code>none</code>, or when the mouse cursor is over the perimeter (i.e., &apos;stroke&apos;) of the element and the <code>stroke</code> property is set to a value other than <code>none</code>.\"\n        }, {\n            \"value\": \"<code>visibleFill</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the <code>visibility</code> property is set to <code>visible</code> and when the mouse cursor is over the interior (i.e., fill) of the element. The value of the <code>fill</code> property does not affect event processing.\"\n        }, {\n            \"value\": \"<code>visibleStroke</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the <code>visibility</code> property is set to <code>visible</code> and when the mouse cursor is over the perimeter (i.e., stroke) of the element. The value of the <code>stroke</code> property does not affect event processing.\"\n        }, {\n            \"value\": \"<code>visible</code>\",\n            \"description\": \"SVG only. The element can be the target of a mouse event when the <code>visibility</code> property is set to <code>visible</code> and the mouse cursor is over either the interior (i.e., fill) or the perimeter (i.e., stroke) of the element. The values of the <code>fill</code> and <code>stroke</code> do not affect event processing.\"\n        }, {\n            \"value\": \"<code>painted</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the mouse cursor is over the interior (i.e., &apos;fill&apos;) of the element and the <code>fill</code> property is set to a value other than <code>none</code>, or when the mouse cursor is over the perimeter (i.e., &apos;stroke&apos;) of the element and the <code>stroke</code> property is set to a value other than <code>none</code>. The value of the <code>visibility</code> property does not affect event processing.\"\n        }, {\n            \"value\": \"<code>fill</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the pointer is over the interior (i.e., fill) of the element. The values of the <code>fill</code> and <code>visibility</code> properties do not affect event processing.\"\n        }, {\n            \"value\": \"<code>stroke</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the pointer is over the perimeter (i.e., stroke) of the element. The values of the <code>stroke</code> and <code>visibility</code> properties do not affect event processing.\"\n        }, {\n            \"value\": \"<code>all</code>\",\n            \"description\": \"SVG only. The element can only be the target of a mouse event when the pointer is over the interior (i.e., fill) or the perimeter (i.e., stroke) of the element. The values of the <code>fill</code>, <code>stroke</code> and <code>visibility</code> properties do not affect event processing.\"\n        }]\n    },\n    \"position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/position\",\n        \"SUMMARY\": \"The <strong><code>position</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.\",\n        \"VALUES\": [{\n            \"value\": \"<code>static</code>\",\n            \"description\": \"This keyword lets the element use the normal behavior.&#xA0;That is, it is laid out in its current position in the flow.&#xA0; The<code> top</code>,<code> right</code>,<code> bottom</code>, <code>left</code> and <code>z-index</code> properties do not apply.\"\n        }, {\n            \"value\": \"<code>relative</code>\",\n            \"description\": \"This keyword lays out all elements as though the element were not positioned, and then adjusts the element&apos;s position, without changing layout (and thus leaving a gap for the element where it would have been had it not been positioned). The effect of <code>position:relative</code> on <code>table-*-group</code>, <code>table-row</code>, <code>table-column</code>, <code>table-cell</code>, and <code>table-caption</code> elements is undefined.\"\n        }, {\n            \"value\": \"<code>absolute</code>\",\n            \"description\": \"Do not leave space for the element. Instead, position it at a specified position relative to its closest positioned ancestor if any, or otherwise&#xA0;relative&#xA0;to the initial containing block. Absolutely positioned boxes can have margins, and they do not collapse with any other margins.\"\n        }, {\n            \"value\": \"<span style=\\\"font-family: courier new,andale mono,monospace; font-weight: inherit; line-height: normal;\\\">fixed</span>\",\n            \"description\": \"Do not leave space for the element. Instead, position it at a specified position relative to the screen&apos;s&#xA0;viewport and don&apos;t move it when scrolled. When printing, position it at that fixed position on <em>every page</em>. This value always creates a new stacking context. When an ancestor has the <code>transform</code> property set to something different from&#xA0;<code>none</code> then this ancestor is used as container instead of the viewport (see <a href=\\\"https://www.w3.org/TR/css-transforms-1/#propdef-transform\\\" class=\\\"external\\\">CSS Transforms Spec</a>).\"\n        }, {\n            \"value\": \"<code style=\\\"font-size: 14px;\\\">sticky</code>&#xA0;<span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The box position is calculated according to the normal flow (this is called the position in normal flow). Then the box is offset relative to its flow root and containing block and in all cases, including&#xA0;<code style=\\\"font-size: 14px;\\\">table</code>&#xA0;elements, does not affect the position of any following boxes. When a box B is stickily positioned, the position of the following box is calculated as though B were not offset. The effect of &#x2018;<code style=\\\"font-size: 14px;\\\">position: sticky</code>&#x2019; on&#xA0;table related elements is the same as for &#x2018;<code style=\\\"font-size: 14px;\\\">position: relative</code>&#x2019;.\"\n        }]\n    },\n    \"quotes\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/quotes\",\n        \"SUMMARY\": \"The <code>quotes</code> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> property indicates how user agents should render quotation marks.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The <code>open-quote</code> and <code>close-quote</code> values of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/content\\\" title=\\\"The content CSS property is used with the ::before and ::after pseudo-elements to generate content in an element. Objects inserted using the content property are anonymous replaced elements.\\\"><code>content</code></a> property produce no quotation marks.\"\n        }, {\n            \"value\": \"<code>[&lt;string&gt; &lt;string&gt;]+</code>\",\n            \"description\": \"One or more pairs of&#xA0;<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\" title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\"><code>&lt;string&gt;</code></a> values for <code>open-quote</code> and <code>close-quote</code>. The first pair represents the outer level of quotation, the second pair is for the first nested level, next pair for third level and so on.\"\n        }]\n    },\n    \"radial-gradient()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/radial-gradient\",\n        \"SUMMARY\": \"The CSS <code>radial-gradient()</code> function creates an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> which represents a gradient of colors radiating from an origin, the <em>center</em> of the gradient. The result of this function is an object of the CSS <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/gradient\\\" title=\\\"The &lt;gradient&gt; CSS data type denotes a CSS &lt;image&gt; made of a progressive transition between two or more colors. A CSS gradient is not a CSS &lt;color&gt; but an image with no intrinsic dimensions; that is, it has no natural or preferred size, nor a preferred ratio. Its concrete size will match the one of the element it applies to.\\\"><code>&lt;gradient&gt;</code></a> data type.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"A <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\\\" title=\\\"The &lt;position&gt; CSS data type denotes a coordinate in a 2D space used to set a location relative to a box.\\\"><code>&lt;position&gt;</code></a>, interpreted in the same way as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\\\" title=\\\"Technical review completed.\\\"><code>background-position</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\"><code>transform-origin</code></a>. If omitted, the default is <code>center</code>.\"\n        }, {\n            \"value\": \"<code>&lt;shape&gt;</code>\",\n            \"description\": \"The gradient&apos;s shape. This is one of <code>circle</code> (meaning that the gradient&apos;s shape is a circle with constant radius) or <code>ellipse</code> (meaning that the shape is an axis-aligned ellipse). The default value is <code>ellipse</code>.\"\n        }, {\n            \"value\": \"<code>&lt;color-stop&gt;</code>\",\n            \"description\": \"Representing a fixed color at a precise position, this value is composed by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> value, followed by an optional stop position (either a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> along the virtual gradient ray). A percentage of <code>0%</code>, or a length of <code>0</code>, represents the center of the gradient, the value <code>100%</code> of the intersection of the ending shape with the virtual gradient ray. Percentage values in-between are linearly positioned on the gradient ray.\"\n        }, {\n            \"value\": \"<code>&lt;extent-keyword&gt;</code>\",\n            \"description\": \"Keywords describing how big the ending shape must be. The possible keywords are:\"\n        }]\n    },\n    \"repeating-linear-gradient()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/repeating-linear-gradient\",\n        \"SUMMARY\": \"The CSS <code>repeating-linear-gradient</code> function creates an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> consisting of repeating gradients. It works similarly to the basic linear gradients as described by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient\\\" title=\\\"The CSS linear-gradient() function creates an &lt;image&gt; which represents a linear gradient of colors. The result of this function is an object of the CSS &lt;gradient&gt; data type. Like any other gradient, a CSS linear gradient is not a CSS &lt;color&gt; but an image with no intrinsic dimensions; that is, it has neither natural or preferred size, nor ratio. Its concrete size will match the size&#xA0;of the element it applies to.\\\"><code>linear-gradient()</code></a>, and takes the same arguments. However, it automatically repeats the color stops infinitely in both directions. The color stops' positions shift by multiples of the length of a basic linear gradient (the difference between the last color stops' position and the first).\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;side-or-corner&gt;</code>\",\n            \"description\": \"Represents the position of the starting-point of the gradient line. It consists of two keywords: the first one indicates the horizontal side, <code>left</code> or <code>right</code>, and the second one the vertical side, <code>top</code> or <code>bottom</code>. The order is not relevant and each of the keyword is optional.<br>\\n The values <code>to top</code>, <code>to bottom</code>, <code>to left</code> and <code>to right</code> are translated into the angles <code>0deg</code>, <code>180deg</code>, <code>270deg</code>, <code>90deg</code> respectively. The others are translated into an angle that causes the starting-point to be in the same quadrant as the described corner so that the line defined by the starting-point and the corner is perpendicular to the gradient line. That way, the color described by the <code>&lt;color-stop&gt;</code> will exactly apply to the corner point. This is sometimes called the &quot;<em>magic corner</em>&quot; property. The end-point of the gradient line is the symmetrical point of the starting-point on the other direction of the center box.\"\n        }, {\n            \"value\": \"<code>&lt;angle&gt;</code>\",\n            \"description\": \"An angle of direction for the gradient. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/angle\\\" title=\\\"The &lt;angle&gt; CSS data type represents angle values. Positive angles represent clockwise angles, negative angles represent counterclockwise angles. Its syntax is a &lt;number&gt; data type immediately followed by the unit (deg, grad, rad or turn). Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;angle&gt;</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;color-stop&gt;</code>\",\n            \"description\": \"This value is comprised of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\" title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\"><code>&lt;color&gt;</code></a> value, followed by an optional stop position (either a percentage between 0% and 100% or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> along the gradient axis).<br>\\n Rendering of color-stops in CSS gradients follows the same rules as color-stops in SVG gradients.\"\n        }]\n    },\n    \"repeating-radial-gradient()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/repeating-radial-gradient\",\n        \"SUMMARY\": \"This works similarly to the standard radial gradients as described by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/radial-gradient\\\" title=\\\"The CSS radial-gradient() function creates an &lt;image&gt; which represents a gradient of colors radiating from an origin, the center of the gradient. The result of this function is an object of the CSS &lt;gradient&gt; data type.\\\"><code>radial-gradient()</code></a>, but it automatically repeats the color stops infinitely in both directions, with their positions shifted by multiples of the difference between the last color stop's position and the first one's position.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"A <a title=\\\"The &lt;position&gt; CSS data type denotes a coordinate in a 2D space used to set a location relative to a box.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position_value\\\"><code>&lt;position&gt;</code></a>, interpreted in the same way as <a title=\\\"The background-position CSS property sets the initial position for each defined background image, relative to the background position layer defined by background-origin.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-position\\\"><code>background-position</code></a> or <a title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element&apos;s transform, then translating by the property value.)\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\"><code>transform-origin</code></a>. If omitted, the default is <code>center</code>.\"\n        }, {\n            \"value\": \"&lt;<code>angle</code>&gt;\",\n            \"description\": \"An angle establishing the gradient line, which extends from the starting point at this angle; this is <code>0deg</code> by default.\"\n        }, {\n            \"value\": \"<code>&lt;shape&gt;</code>\",\n            \"description\": \"The gradient&apos;s shape. This is one of <code>circle</code> (meaning that the gradient&apos;s shape is a circle with constant radius) or <code>ellipse</code> (meaning that the shape is an axis-aligned ellipse). The default value is <code>ellipse</code>.\"\n        }, {\n            \"value\": \"<code>&lt;size&gt;</code>\",\n            \"description\": \"The size of the gradient. This is one of the <a href=\\\"#Size_constants\\\">Size constants</a> listed below.\"\n        }, {\n            \"value\": \"<code>&lt;color-stop&gt;</code>\",\n            \"description\": \"Representing a fixed color at a precise position, this value is composed by a <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\"><code>&lt;color&gt;</code></a> value, followed by an optional stop position (either a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> or a <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> along the virtual gradient ray). A percentage of <code>0%</code>, or a length of <code>0</code>, represents the center of the gradient, the value <code>100%</code> the intersection of the ending shape with the virtual gradient ray. Percentage values in-between. are linearily positioned on the gradient ray.\"\n        }, {\n            \"value\": \"<code>&lt;extent-keyword&gt;</code>\",\n            \"description\": \"Are keywords describing how big the ending shape must be. The possible keywords are:\"\n        }]\n    },\n    \"resize\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/resize\",\n        \"SUMMARY\": \"The <strong><code>resize</code></strong> CSS property lets you control the resizability of an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The element offers no user-controllable method for resizing the element.\"\n        }, {\n            \"value\": \"<code>both</code>\",\n            \"description\": \"The element displays a mechanism for allowing the user to resize the element, which may be resized both horizontally and vertically.\"\n        }, {\n            \"value\": \"<code>horizontal</code>\",\n            \"description\": \"The element displays a mechanism for allowing the user to resize the element, which may only be resized horizontally.\"\n        }, {\n            \"value\": \"<code>vertical</code>\",\n            \"description\": \"The element displays a mechanism for allowing the user to resize the element, which may only be resized vertically.\"\n        }, {\n            \"value\": \"<code>block</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Depending on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> value, the element displays a mechanism for allowing the user to resize the element either horizontally or vertically in block direction.\"\n        }, {\n            \"value\": \"<code>inline</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Depending on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> value, the element displays a mechanism for allowing the user to resize the element either horizontally or vertically in inline direction.\"\n        }]\n    },\n    \"revert\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/revert\",\n        \"SUMMARY\": \"The <strong><code>revert</code></strong> CSS keyword rolls back the cascade so that the property takes on the value it would have had if there were no styles in the current style origin (author, user, or user-agent). In author stylesheets (the normal case), for the purposes of the given declaration, it's as if there were no author-level styles, thus resetting the property to the default value established by the user-agent stylesheet (or by user styles, if any exist).\",\n        \"VALUES\": []\n    },\n    \"right\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/right\",\n        \"SUMMARY\": \"The <code>right</code> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies part of the position of positioned elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a negative, null or positive <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> that represents:\\n <ul>\\n  <li>for <em>absolutely positioned elements</em>, the distance to the right edge of the containing block;</li>\\n  <li>for <em>relatively positioned elements</em>, the offset that the element is moved right from its position in the normal flow if it wasn&apos;t positioned.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the containing block&apos;s width, used as described in the <a href=\\\"#Summary\\\">summary</a>.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that represents:\\n <ul>\\n  <li>for absolutely positioned elements, the position the element based on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property and treat <code>width: auto</code> as a width based on the content.</li>\\n  <li>for relatively positioned elements, the right offset the element from its original position based on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/left\\\" title=\\\"The left CSS property specifies part of the position of positioned elements.\\\"><code>left</code></a> property, or if <code>left</code> is also <code>auto</code>, do not offset it at all.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that the value is the same than the computed value from its parent element (which may not be its containing block). This computed value is then handled like it was a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> or the <code>auto</code> keyword.\"\n        }]\n    },\n    \"ruby-align\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-align\",\n        \"SUMMARY\": \"The <code><strong>ruby-align</strong></code> CSS property defines the distribution of the different ruby elements over the base.\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code>\",\n            \"description\": \"Is a keyword indicating that the ruby will be aligned with the start of the base text.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"Is a keyword indicating that the ruby will be aligned at the middle of the base text\"\n        }, {\n            \"value\": \"<code>space-between</code>\",\n            \"description\": \"Is a keyword indicating that the extra space will be distributed between the elements of the ruby.\"\n        }, {\n            \"value\": \"<code>space-around</code>\",\n            \"description\": \"Is a keyword indicating that the extra space will be distributed between the elements of the ruby, and around it.\"\n        }]\n    },\n    \"ruby-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-position\",\n        \"SUMMARY\": \"The <code><strong>ruby-position</strong></code> CSS property defines the position of a ruby element relatives to its base element. It can be position over the element (<code>over</code>), under it (<code>under</code>), or between the characters, on their right side (<code>inter-character</code>).\",\n        \"VALUES\": [{\n            \"value\": \"<code>over</code>\",\n            \"description\": \"<img src=\\\"https://mdn.mozillademos.org/files/10251/Screen%20Shot%202015-03-04%20at%2013.02.20.png\\\" style=\\\"height: 31px; width: 77px;\\\" alt=\\\"Over example\\\">Is a keyword indicating that the ruby has to be placed over the main text for horizontal scripts and right to it for vertical scripts.\"\n        }, {\n            \"value\": \"<code>under</code>\",\n            \"description\": \"<img src=\\\"https://mdn.mozillademos.org/files/10249/Screen%20Shot%202015-03-04%20at%2013.02.07.png\\\" style=\\\"height: 34px; width: 78px;\\\" alt=\\\"Under example\\\">Is a keyword indicating that the ruby has to be placed under the main text for horizontal scripts and left to it for vertical scripts.\"\n        }, {\n            \"value\": \"<code>inter-character</code>\",\n            \"description\": \"Is a keyword indicating that the ruby has to be placed between the different characters.\"\n        }]\n    },\n    \"scroll-behavior\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior\",\n        \"SUMMARY\": \"The<strong> <code>scroll-behavior</code></strong> CSS property specifies the scrolling behavior for a scrolling box, when scrolling happens due to navigation or CSSOM scrolling APIs. Any other scrolls, e.g. those that are performed by the user, are not affected by this property. When this property is specified on the root element, it applies to the viewport instead.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The scrolling box is scrolled in an instant fashion.\"\n        }, {\n            \"value\": \"<code>smooth</code>\",\n            \"description\": \"The scrolling box is scrolled in a smooth fashion using a user-agent-defined timing function over a user-agent-defined period of time. User agents should follow platform conventions, if any.\"\n        }]\n    },\n    \"scroll-snap-coordinate\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-coordinate\",\n        \"SUMMARY\": \"The<strong> <code>scroll-snap-coordinate</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the positions in x and y coordinates within the element which will align with the nearest ancestor scroll container's <a title=\\\"The scroll-snap-destination CSS property defines the position in x and y coordinates within the scroll container's visual viewport which element snap points align with.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination\\\"><code>scroll-snap-destination</code></a> for the respective axis.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Specifies that the element does not contribute to a snap point.\"\n        }, {\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"Specifies the offset of the snap coordinates from the start edge of the element&#x2019;s border box. For each pairing, the first value gives the x coordinate of the snap coordinate, the second value its y coordinate.\"\n        }]\n    },\n    \"scroll-snap-destination\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination\",\n        \"SUMMARY\": \"The <strong><code>scroll-snap-destination</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the position in x and y coordinates within the scroll container's visual <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/viewport\\\" class=\\\"glossaryLink\\\" title=\\\"viewport: A viewport represents a polygonal (normally rectangular) area in computer graphics that is currently being viewed. In web browser terms, it refers to the part of the browser that is taken up by visible website content.\\\">viewport</a> which element snap points align with.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;position&gt;</code>\",\n            \"description\": \"Specifies the offset of the snap destination from the start edge of the scroll container&#x2019;s visual viewport. The first value gives the x coordinate of the snap destination, the second value its y coordinate.\"\n        }]\n    },\n    \"scroll-snap-points-x\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-points-x\",\n        \"SUMMARY\": \"The <strong><code>scroll-snap-points-x</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the horizontal positioning of snap points within the content of the scroll container they are applied to.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The scroll container does not define any snap points. Elements within the scroll container may still define snap points on behalf of the scroll container.\"\n        }, {\n            \"value\": \"<code>repeat(&lt;length-percentage&gt;)</code>\",\n            \"description\": \"Defines an interval at which snap points are defined, starting from the container&apos;s relevant start edge. Only positive lengths are allowed. Percentages refer to the width of the container.\"\n        }]\n    },\n    \"scroll-snap-points-y\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-points-y\",\n        \"SUMMARY\": \"The <strong><code>scroll-snap-points-y</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the vertical positioning of snap points within the content of the scroll container they are applied to.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The scroll container does not define any snap points. Elements within the scroll container may still define snap points on behalf of the scroll container.\"\n        }, {\n            \"value\": \"<code>repeat(&lt;length-percentage&gt;)</code>\",\n            \"description\": \"Defines an interval at which snap points are defined, starting from the container&apos;s relevant start edge. Only positive lengths are allowed. Percentages refer to the width of the container.\"\n        }]\n    },\n    \"scroll-snap-type\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type\",\n        \"SUMMARY\": \"The <strong><code>scroll-snap-type</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines how strictly snap points are enforced on the scroll container in case there is one.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"When the visual <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/viewport\\\" class=\\\"glossaryLink\\\" title=\\\"viewport: A viewport represents a polygonal (normally rectangular) area in computer graphics that is currently being viewed. In web browser terms, it refers to the part of the browser that is taken up by visible website content.\\\">viewport</a> of this scroll container is scrolled, it must ignore snap points.\"\n        }, {\n            \"value\": \"<code>mandatory</code>\",\n            \"description\": \"The visual viewport of this scroll container will rest on a snap point if it isn&apos;t currently scrolled. That means it snaps on that point when the scroll action finished, if possible. If content is added, moved, deleted or resized the scroll offset will be adjusted to maintain the resting on that snap point.\"\n        }, {\n            \"value\": \"<code>proximity</code>\",\n            \"description\": \"The visual viewport of this scroll container may come to rest on a snap point if it isn&apos;t currently scrolled considering the user agent&apos;s scroll parameters. If content is added, moved, deleted or resized the scroll offset may be adjusted to maintain the resting on that snap point.\"\n        }]\n    },\n    \"scroll-snap-type-x\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-x\",\n        \"SUMMARY\": \"The <strong><code>scroll-snap-type-x</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines how strictly snap points are enforced on the horizontal axis of the scroll container in case there is one.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"When the visual <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/viewport\\\" class=\\\"glossaryLink\\\" title=\\\"viewport: A viewport represents a polygonal (normally rectangular) area in computer graphics that is currently being viewed. In web browser terms, it refers to the part of the browser that is taken up by visible website content.\\\">viewport</a> of this scroll container is scrolled horizontally, it must ignore snap points.\"\n        }, {\n            \"value\": \"<code>mandatory</code>\",\n            \"description\": \"The visual viewport of this scroll container will rest on a snap point if it isn&apos;t currently scrolled horizontally. That means it snaps on that point when the scroll action finished, if possible. If content is added, moved, deleted or resized the scroll offset will be adjusted to maintain the resting on that snap point.\"\n        }, {\n            \"value\": \"<code>proximity</code>\",\n            \"description\": \"The visual viewport of this scroll container may come to rest on a snap point if it isn&apos;t currently scrolled horizontally considering the user agent&apos;s scroll parameters. If content is added, moved, deleted or resized the scroll offset may be adjusted to maintain the resting on that snap point.\"\n        }]\n    },\n    \"scroll-snap-type-y\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-y\",\n        \"SUMMARY\": \"The <strong><code>scroll-snap-type-y</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines how strictly snap points are enforced on the vertical axis of the scroll container in case there is one.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"When the visual <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/viewport\\\" class=\\\"glossaryLink\\\" title=\\\"viewport: A viewport represents a polygonal (normally rectangular) area in computer graphics that is currently being viewed. In web browser terms, it refers to the part of the browser that is taken up by visible website content.\\\">viewport</a> of this scroll container is scrolled vertically, it must ignore snap points.\"\n        }, {\n            \"value\": \"<code>mandatory</code>\",\n            \"description\": \"The visual viewport of this scroll container will rest on a snap point if it isn&apos;t currently scrolled vertically. That means it snaps on that point when the scroll action finished, if possible. If content is added, moved, deleted or resized the scroll offset will be adjusted to maintain the resting on that snap point.\"\n        }, {\n            \"value\": \"<code>proximity</code>\",\n            \"description\": \"The visual viewport of this scroll container may come to rest on a snap point if it isn&apos;t currently scrolled vertically considering the user agent&apos;s scroll parameters. If content is added, moved, deleted or resized the scroll offset may be adjusted to maintain the resting on that snap point.\"\n        }]\n    },\n    \"shape-image-threshold\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-image-threshold\",\n        \"SUMMARY\": \"The <strong><code>shape-image-threshold</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the alpha channel threshold used to extract the shape using an image as the value for <a href=\\\"https://developer.mozilla.org/en-US/docs/\\\"><code>shape-outside</code></a>. A value of 0.5 means that the shape will enclose all the pixels that are more than 50% opaque.\",\n        \"VALUES\": [{\n            \"value\": \"<span style=\\\"font-family: courier new,andale mono,monospace; font-style: inherit; font-weight: inherit; line-height: 1.5;\\\">&lt;number&gt;</span>\",\n            \"description\": \"Sets the threshold used for extracting a shape from an image. The shape is defined by the pixels whose alpha value is greater than the threshold. A threshold value outside the range 0.0 (fully transparent) to 1.0 (fully opaque) will be clamped to this range.\"\n        }]\n    },\n    \"shape-margin\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-margin\",\n        \"SUMMARY\": \"The<strong> <code>shape-margin</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property adds a margin to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-outside\\\" title=\\\"The shape-outside CSS property uses shape values to define the float area for a float and will cause inline content to wrap around the shape instead of the float's bounding box.\\\"><code>shape-outside</code></a>.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;length-percentage&gt;\",\n            \"description\": \"Sets the margin of the shape to a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value or to a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the width of the element&apos;s containing block.\"\n        }]\n    },\n    \"shape-outside\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-outside\",\n        \"SUMMARY\": \"The <strong><code>shape-outside</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property uses shape values to define the float area for a float and will cause inline content to wrap around the shape instead of the float's bounding box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The float area is unaffected.\"\n        }, {\n            \"value\": \"<code>&lt;shape-box&gt;</code>\",\n            \"description\": \"If one of the values <code>margin-box</code>, <code>border-box</code>, <code>padding-box</code> or <code>content-box</code> is specified, the shape is computed based on it. The shape uses their respective box including curvature from <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius\\\" title=\\\"The border-radius CSS property allows Web authors to define how rounded border corners are. The curve of each corner is defined using one or two radii, defining its shape: circle or ellipse.\\\"><code>border-radius</code></a>, similar to <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip\\\" title=\\\"The background-clip CSS property specifies whether an element&apos;s background, either the color or image, extends underneath its border.\\\"><code>background-clip</code></a>.\"\n        }, {\n            \"value\": \"<code>&lt;basic-shape&gt;</code>\",\n            \"description\": \"The shape is computed based on the values of one of <code>inset()</code>, <code>circle()</code>, <code>ellipse()</code> or <code>polygon()</code>. If also a <code>&lt;shape-box&gt;</code> is supplied, this defines the reference box for the <code>&lt;basic-shape&gt;</code> function. If <code>&lt;shape-box&gt;</code> is not supplied, then the reference box defaults to <code>margin-box</code>.\"\n        }, {\n            \"value\": \"<code>&lt;image&gt;</code>\",\n            \"description\": \"The shape is extracted and computed based on the alpha channel of the specified <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/image\\\" title=\\\"The &lt;image&gt; CSS data type represents a 2D image. There are two kinds of images in CSS: plain static images, often referenced using a URL, and dynamically-generated images like gradients or representations of parts of the tree.\\\"><code>&lt;image&gt;</code></a> as defined by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/shape-image-threshold\\\" title=\\\"The shape-image-threshold&#xA0;CSS property defines the alpha channel threshold used to extract the shape using an image as the value for shape-outside. A value of 0.5 means that the shape will enclose all the pixels that are more than 50% opaque.\\\"><code>shape-image-threshold</code></a>.\"\n        }]\n    },\n    \"specified value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/specified_value\",\n        \"SUMMARY\": \"The <strong>specified value</strong> of a CSS property is set in one out of three ways.\",\n        \"VALUES\": []\n    },\n    \"symbols()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/symbols\",\n        \"SUMMARY\": \"The <code>symbols()</code> function allows counter styles to be defined inline, directly as the value of the CSS property. Unlike styles defines with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\\\" title=\\\"The @counter-style CSS at-rule defines a specific counter style that are not part of the predefined set of styles. A @counter-style rule defines how to convert a counter value into a string representation.\\\"><code>@counter-style</code></a>, these styles are anonymous. The <code>symbols()</code> function doesn't have all the capabilities and options of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\\\" title=\\\"The @counter-style CSS at-rule defines a specific counter style that are not part of the predefined set of styles. A @counter-style rule defines how to convert a counter value into a string representation.\\\"><code>@counter-style</code></a> at-rule, but is useful in cases such as when the style is used only once and you don't need all the the options provided by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style\\\" title=\\\"The @counter-style CSS at-rule defines a specific counter style that are not part of the predefined set of styles. A @counter-style rule defines how to convert a counter value into a string representation.\\\"><code>@counter-style</code></a>.\",\n        \"VALUES\": []\n    },\n    \"tab-size\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/tab-size\",\n        \"SUMMARY\": \"The<strong> <code>tab-size</code></strong> CSS property is used to customize the width of a tab (<code>U+0009</code>) character.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/integer\\\" title=\\\"The &lt;integer&gt; CSS data type denotes an integer number, positive or negative. There isn&apos;t any associated unit with the value. An integer consists of one or several decimal digits, 0 to 9, optionally preceded by one single + or - sign.\\\"><code>&lt;integer&gt;</code></a>\",\n            \"description\": \"The number of spaces in a tab. Must be nonnegative.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>\",\n            \"description\": \"The width of a tab. Must be nonnegative.\"\n        }]\n    },\n    \"table-layout\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout\",\n        \"SUMMARY\": \"The <strong><code>table-layout</code></strong> CSS property defines the algorithm to be used to lay out table cells, rows, and columns.\",\n        \"VALUES\": [{\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/auto\\\" title=\\\"The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.\\\"><code>auto</code></a>\",\n            \"description\": \"An automatic table layout algorithm is commonly used by most browsers for table layout. The widths of the table and its cells depend&#xA0;on the content thereof.\"\n        }, {\n            \"value\": \"<code>fixed</code>\",\n            \"description\": \"Table and column widths are set by the widths of <code>table</code> and <code>col</code> elements or by the width of the first row of cells. Cells in subsequent rows do not affect column widths.<br>\\n <br>\\n Under the &quot;fixed&quot; layout method, the entire table can be rendered once the first table row has been downloaded and analyzed. This can speed up rendering time over the &quot;automatic&quot; layout method, but subsequent cell content may not fit in the column widths provided. Any cell that has content that overflows uses the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/overflow\\\" title=\\\"The overflow property specifies whether to clip content, render scrollbars or just display content when it overflows its block level container.\\\"><code>overflow</code></a> property to determine whether to clip the overflow content, but only if the table has a known width, otherwise it won&apos;t overflow the cells.\"\n        }]\n    },\n    \"text-align\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-align\",\n        \"SUMMARY\": \"Summary\",\n        \"VALUES\": [{\n            \"value\": \"<code>start</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The same as <code>left</code> if direction is left-to-right and <code>right</code> if direction is right-to-left.\"\n        }, {\n            \"value\": \"<code>end</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The same as <code>right</code> if direction is left-to-right and <code>left</code> if direction is right-to-left.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The inline contents are aligned to the left edge of the line box.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The inline contents are aligned to the right edge of the line box.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The inline contents are centered within the line box.\"\n        }, {\n            \"value\": \"<code>justify</code>\",\n            \"description\": \"The inline contents are justified. Text should be spaced to line up its left and right edges to the left and right edges of the line box, except for the last line.\"\n        }, {\n            \"value\": \"<code>justify-all</code>\",\n            \"description\": \"Same as <code>justify</code>, but also forces the last line to be justified.\"\n        }, {\n            \"value\": \"<code>match-parent</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Similar to <code>inherit</code>, but the values <code>start</code> and <code>end</code> are calculated according the parent&apos;s <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> and are replaced by the adequate <code>left</code> or <code>right</code> value.\"\n        }]\n    },\n    \"text-align-last\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-align-last\",\n        \"SUMMARY\": \"The<strong> <code>text-align-last</code></strong> CSS property describes how the last line of a block or a line, right before a forced line break, is aligned.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The affected line is aligned per the value of <a title=\\\"Summary\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-align\\\"><code>text-align</code></a>, unless <a title=\\\"Summary\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-align\\\"><code>text-align</code></a> is <code>justify</code>, in which case the effect is the same as setting <code>text-align-last</code> to <code>start</code>.\"\n        }, {\n            \"value\": \"<code>start</code>\",\n            \"description\": \"The same as <code>left</code> if direction is left-to-right and <code>right</code> if direction is right-to-left.\"\n        }, {\n            \"value\": \"<code>end</code>\",\n            \"description\": \"The same as <code>right</code> if direction is left-to-right and <code>left</code> if direction is right-to-left.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"The inline contents are aligned to the left edge of the line box.\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"The inline contents are aligned to the right edge of the line box.\"\n        }, {\n            \"value\": \"<code>center</code>\",\n            \"description\": \"The inline contents are centered within the line box.\"\n        }, {\n            \"value\": \"<code>justify</code>\",\n            \"description\": \"The text is justified. Text should line up their left and right edges to the left and right content edges of the paragraph.\"\n        }]\n    },\n    \"text-combine-upright\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-combine-upright\",\n        \"SUMMARY\": \"The <strong><code>text-combine-upright</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the combination of multiple characters into the space of a single character. If the combined text is wider than 1em, the user agent must fit the contents within 1em. The resulting composition is treated as a single upright glyph for layout and decoration. This property only has an effect in vertical writing modes.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"There is no special processing.\"\n        }, {\n            \"value\": \"<code>all</code>\",\n            \"description\": \"Attempts to typeset all consecutive characters within the box horizontally, such that they take up the space of a single character within the vertical line of the&#xA0;box.\"\n        }, {\n            \"value\": \"<code>digits &lt;integer&gt;?</code>\",\n            \"description\": \"Attempts to display a sequence of consecutive ASCII digits (U+0030&#x2013;U+0039) that has as many or fewer characters than the specified integer, such that it takes up the space of a single character within the vertical line box. If the integer is omitted, it computes to 2. Integers outside the range of 2-4 are invalid.\"\n        }]\n    },\n    \"text-decoration\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration\",\n        \"SUMMARY\": \"The <strong><code>text-decoration</code></strong> CSS property is used to set the text formatting to <code>underline</code>, <code>overline</code>, <code>line-through</code> or <code>blink</code>. Underline and overline decorations are positioned under the text, line-through over it.\",\n        \"VALUES\": [{\n            \"value\": \"\",\n            \"description\": \"The <code>text-decoration</code> property is a shorthand and can use the values of each of the three longhand properties: <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line\\\" title=\\\"The text-decoration-line CSS property sets what kind of line decorations are added to an element.\\\"><code>text-decoration-line</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-color\\\" title=\\\"The CSS text-decoration-color property sets the line color used when drawing underlines, overlines, and strikethrough lines specified by the corresponding text-decoration-line property. The color specified will be the same for all three line&#xA0;types.\\\"><code>text-decoration-color</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-style\\\" title=\\\"The text-decoration-style CSS property defines the style of the lines specified by text-decoration-line. The style applies to all lines: there is no way to define different styles for each of the lines defined by text-decoration-line.\\\"><code>text-decoration-style</code></a>\"\n        }]\n    },\n    \"text-decoration-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-color\",\n        \"SUMMARY\": \"The CSS <strong><code>text-decoration-color</code></strong> property sets the line color used when drawing underlines, overlines, and strikethrough lines specified by the corresponding <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line\\\" title=\\\"The text-decoration-line CSS property sets what kind of line decorations are added to an element.\\\"><code>text-decoration-line</code></a> property. The color specified will be the same for all three line types.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"The <code>color</code> property accepts various keywords and numeric notations. See <a title=\\\"The &lt;color&gt; CSS data type denotes a color in the sRGB color space. A color can be described in any of these ways:\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\\\"><code>&lt;color&gt;</code></a> values for more details.\"\n        }]\n    },\n    \"text-decoration-line\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line\",\n        \"SUMMARY\": \"The <strong><code>text-decoration-line</code></strong> CSS property sets what kind of line decorations are added to an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Produces no text decoration.\"\n        }, {\n            \"value\": \"<code>underline</code>\",\n            \"description\": \"Each line of text is underlined.\"\n        }, {\n            \"value\": \"<code>overline</code>\",\n            \"description\": \"Each line of text has a line above it.\"\n        }, {\n            \"value\": \"<code>line-through</code>\",\n            \"description\": \"Each line of text has a line through the middle.\"\n        }, {\n            \"value\": \"<code>blink <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span></code>\",\n            \"description\": \"The text blinks (alternates between visible and invisible). Conforming user agents may simply not blink the text. This value is <strong>deprecated</strong> in favor of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/animation\\\">Animations</a>.\"\n        }, {\n            \"value\": \"<code>-moz-anchor-decoration </code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"The text is decorated as an anchor; not suitable for web content.\"\n        }]\n    },\n    \"text-decoration-skip\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-skip\",\n        \"SUMMARY\": \"The <strong><code>text-decoration-skip</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies what parts of the element’s content any text decoration affecting the element must skip over.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Nothing is skipped, i.e. text decoration is drawn for all text content and across atomic inline-level boxes.\"\n        }, {\n            \"value\": \"<code>objects</code>\",\n            \"description\": \"The entire margin box of the element is skipped if it is an atomic inline such as an image or inline-block.\"\n        }, {\n            \"value\": \"<code>spaces</code>\",\n            \"description\": \"All spacing is skipped, i.e. all <a class=\\\"external\\\" href=\\\"http://www.unicode.org/reports/tr44/#White_Space\\\">Unicode white space characters</a> and all word separators, plus any adjacent <a title=\\\"The letter-spacing CSS property specifies spacing behavior between text characters.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing\\\"><code>letter-spacing</code></a> or <a title=\\\"The word-spacing CSS property specifies the spacing behavior between tags and words.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/word-spacing\\\"><code>word-spacing</code></a>.\"\n        }, {\n            \"value\": \"<code>ink</code>\",\n            \"description\": \"The text decoration is only drawn where it does not touch or closely approach a glyph. I.e. it is interrupted where it would otherwise cross over a glyph.\"\n        }, {\n            \"value\": \"<img src=\\\"https://mdn.mozillademos.org/files/13464/decoration-skip-ink.png\\\" alt=\\\"An example of &quot;text-decoration-skip: ink;&quot;.\\\">\",\n            \"description\": \"<code>edges</code>\"\n        }, {\n            \"value\": \"The start and end of the text decoration is placed slightly inward (e.g. by half of the line thickness) from the content edge of the decorating box. E.g. two underlined elements side-by-side do not appear to have a single underline. (This is important in Chinese, where underlining is a form of punctuation.)\",\n            \"description\": \"<img src=\\\"https://mdn.mozillademos.org/files/13466/decoration-skip-edges.png\\\" alt=\\\"An example of &quot;text-decoration-skip: edges;&quot;.\\\">\"\n        }, {\n            \"value\": \"<code>box-decoration</code>\",\n            \"description\": \"The text decoration is skipped over the box&apos;s margin, border and padding areas. This only has an effect on decorations imposed by an ancestor; a <em>decorating box</em> never draws over its own box decoration.\"\n        }]\n    },\n    \"text-decoration-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-style\",\n        \"SUMMARY\": \"The <strong><code>text-decoration-style</code></strong> CSS property defines the style of the lines specified by <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line\\\" title=\\\"The text-decoration-line CSS property sets what kind of line decorations are added to an element.\\\"><code>text-decoration-line</code></a>. The style applies to all lines: there is no way to define different styles for each of the lines defined by <code>text-decoration-line</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>solid double dotted dashed wavy</code>\",\n            \"description\": \"Is one of the following keywords :\\n <table class=\\\"standard-table\\\">\\n  <thead>\\n   <tr>\\n    <th scope=\\\"col\\\">Keyword</th>\\n    <th scope=\\\"col\\\">Description</th>\\n    <th scope=\\\"col\\\">Comment</th>\\n   </tr>\\n  </thead>\\n  <tbody>\\n   <tr>\\n    <td><code>solid</code></td>\\n    <td>Draws a single line</td>\\n    <td>&#xA0;</td>\\n   </tr>\\n   <tr>\\n    <td><code>double</code></td>\\n    <td>Draws a double line</td>\\n    <td>&#xA0;</td>\\n   </tr>\\n   <tr>\\n    <td><code>dotted</code></td>\\n    <td>Draws a dotted line</td>\\n    <td>&#xA0;</td>\\n   </tr>\\n   <tr>\\n    <td><code>dashed</code></td>\\n    <td>Draws a dashed line</td>\\n    <td>&#xA0;</td>\\n   </tr>\\n   <tr>\\n    <td><code>wavy</code></td>\\n    <td>Draws a wavy line</td>\\n    <td>&#xA0;</td>\\n   </tr>\\n   <tr>\\n    <td><code>-moz-none</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span><code> </code></td>\\n    <td>Do not draw a line</td>\\n    <td><strong>Do not use</strong><strong> :</strong> use <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line\\\" title=\\\"The text-decoration-line CSS property sets what kind of line decorations are added to an element.\\\"><code>text-decoration-line</code></a><code>: none</code> instead</td>\\n   </tr>\\n  </tbody>\\n </table>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating to reuse the value calculated on the parent element.\"\n        }]\n    },\n    \"text-emphasis\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis\",\n        \"SUMMARY\": \"The <strong><code>text-emphasis</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\">shorthand</a> property for setting <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-style\\\" title=\\\"The text-emphasis-style CSS property defines the type of emphasis used. It can also be set, and reset, using the text-emphasis shorthand.\\\"><code>text-emphasis-style</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-color\\\" title=\\\"The text-emphasis-color CSS property defines the color used to draw an emphasis mark. It can also be set, and reset, using the text-emphasis shorthand.\\\"><code>text-emphasis-color</code></a> in one declaration. This property will apply the specified emphasis mark to each character of the element's text, except separator characters, like spaces,  and control characters.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No emphasis marks.\"\n        }, {\n            \"value\": \"<code>filled</code>\",\n            \"description\": \"The shape is filled with solid color. If neither <code>filled</code> nor <code>open</code> is present, this is the default.\"\n        }, {\n            \"value\": \"<code>open</code>\",\n            \"description\": \"The shape is hollow.\"\n        }, {\n            \"value\": \"<code>dot</code>\",\n            \"description\": \"Display small circles as marks. The filled dot is <code>&apos;&#x2022;&apos;</code> (<code>U+2022</code>), and the open dot is <code>&apos;&#x25E6;&apos;</code> (<code>U+25E6</code>).\"\n        }, {\n            \"value\": \"<code>circle</code>\",\n            \"description\": \"Display large circles as marks. The filled circle is <code>&apos;&#x25CF;&apos;</code> (<code>U+25CF</code>), and the open circle is <code>&apos;&#x25CB;&apos;</code> (<code>U+25CB</code>). This is the default shape in horizontal writing modes when no other shape is given.\"\n        }, {\n            \"value\": \"<code>double-circle</code>\",\n            \"description\": \"Display double circles as marks. The filled double-circle is <code>&apos;&#x25C9;&apos;</code> (<code>U+25C9</code>), and the open double-circle is <code>&apos;&#x25CE;&apos;</code> (<code>U+25CE</code>).\"\n        }, {\n            \"value\": \"<code>triangle</code>\",\n            \"description\": \"Display triangles as marks. The filled triangle is <code>&apos;&#x25B2;&apos;</code> (<code>U+25B2</code>), and the open triangle is <code>&apos;&#x25B3;&apos;</code> (<code>U+25B3</code>).\"\n        }, {\n            \"value\": \"<code>sesame</code>\",\n            \"description\": \"Display sesames as marks. The filled sesame is <code>&apos;&#xFE45;&apos;</code> (<code>U+FE45</code>), and the open sesame is <code>&apos;&#xFE46;&apos;</code> (<code>U+FE46</code>). This is the default shape in vertical writing modes when no other shape is given.\"\n        }, {\n            \"value\": \"<code>&lt;string&gt;</code>\",\n            \"description\": \"Display the given string as marks. Authors should not specify more than one<em> character</em> in <code>&lt;string&gt;</code>. The UA may truncate or ignore strings consisting of more than one grapheme cluster.\"\n        }, {\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"Defines the color of the mark. If no color is present, it defaults to <code>currentColor</code>.\"\n        }]\n    },\n    \"text-emphasis-color\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-color\",\n        \"SUMMARY\": \"The <strong><code>text-emphasis-color</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the color used to draw an emphasis mark. It can also be set, and reset, using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis\\\" title=\\\"The text-emphasis CSS property is a shorthand&#xA0;property for setting text-emphasis-style and text-emphasis-color in one declaration. This property will apply the specified emphasis mark to each character of the element's text, except separator characters, like spaces,&#xA0; and control characters.\\\"><code>text-emphasis</code></a> shorthand.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;color&gt;</code>\",\n            \"description\": \"Defines the color of the mark. If no color is present, it defaults to <code>currentColor</code>.\"\n        }]\n    },\n    \"text-emphasis-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-position\",\n        \"SUMMARY\": \"The <strong><code>text-emphasis-position</code></strong> <a title=\\\"CSS\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property describes where emphasis marks are drawn at. The effect of emphasis marks on the line height is the same as for ruby text: if there isn't enough place, the line height is increased.\",\n        \"VALUES\": [{\n            \"value\": \"<code><dfn>over</dfn></code>\",\n            \"description\": \"Draw marks over the text in horizontal writing mode.\"\n        }, {\n            \"value\": \"<code><dfn>under</dfn></code>\",\n            \"description\": \"Draw marks under the text in horizontal writing mode.\"\n        }, {\n            \"value\": \"<code><dfn>right</dfn></code>\",\n            \"description\": \"Draws marks to the right of the text in vertical writing mode.\"\n        }, {\n            \"value\": \"<code><dfn>left</dfn></code>\",\n            \"description\": \"Draw marks to the left of the text in vertical writing mode.\"\n        }]\n    },\n    \"text-emphasis-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-style\",\n        \"SUMMARY\": \"The <strong><code>text-emphasis-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the type of emphasis used. It can also be set, and reset, using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis\\\" title=\\\"The text-emphasis CSS property is a shorthand&#xA0;property for setting text-emphasis-style and text-emphasis-color in one declaration. This property will apply the specified emphasis mark to each character of the element's text, except separator characters, like spaces,&#xA0; and control characters.\\\"><code>text-emphasis</code></a> shorthand.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No emphasis marks.\"\n        }, {\n            \"value\": \"<code>filled</code>\",\n            \"description\": \"The shape is filled with solid color. If neither <code>filled</code> nor <code>open</code> is present, this is the default.\"\n        }, {\n            \"value\": \"<code>open</code>\",\n            \"description\": \"The shape is hollow.\"\n        }, {\n            \"value\": \"<code>dot</code>\",\n            \"description\": \"Display small circles as marks. The filled dot is <code>&apos;&#x2022;&apos;</code> (<code>U+2022</code>), and the open dot is <code>&apos;&#x25E6;&apos;</code> (<code>U+25E6</code>).\"\n        }, {\n            \"value\": \"<code>circle</code>\",\n            \"description\": \"Display large circles as marks. The filled circle is <code>&apos;&#x25CF;&apos;</code> (<code>U+25CF</code>), and the open circle is <code>&apos;&#x25CB;&apos;</code> (<code>U+25CB</code>).\"\n        }, {\n            \"value\": \"<code>double-circle</code>\",\n            \"description\": \"Display double circles as marks. The filled double-circle is <code>&apos;&#x25C9;&apos;</code> (<code>U+25C9</code>), and the open double-circle is <code>&apos;&#x25CE;&apos;</code> (<code>U+25CE</code>).\"\n        }, {\n            \"value\": \"<code>triangle</code>\",\n            \"description\": \"Display triangles as marks. The filled triangle is <code>&apos;&#x25B2;&apos;</code> (<code>U+25B2</code>), and the open triangle is <code>&apos;&#x25B3;&apos;</code> (<code>U+25B3</code>).\"\n        }, {\n            \"value\": \"<code>sesame</code>\",\n            \"description\": \"Display sesames as marks. The filled sesame is <code>&apos;&#xFE45;&apos;</code> (<code>U+FE45</code>), and the open sesame is <code>&apos;&#xFE46;&apos;</code> (<code>U+FE46</code>).\"\n        }, {\n            \"value\": \"<code>&lt;string&gt;</code>\",\n            \"description\": \"Display the given string as marks. Authors should not specify more than one<em> character</em> in <code>&lt;string&gt;</code>. The UA may truncate or ignore strings consisting of more than one grapheme cluster.\"\n        }]\n    },\n    \"text-indent\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-indent\",\n        \"SUMMARY\": \"The <strong><code>text-indent</code></strong> property specifies the amount of indentation (empty space) should be left before lines of text in a block. By default, this controls the indentation of only the first formatted line of the block, but the <code>hanging</code> and <code>each-line</code> keywords can be used to change this behavior.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Indentation is specified as an absolute <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>. Negative values are allowed. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> values for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Indentation is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the containing block width.\"\n        }, {\n            \"value\": \"<code>each-line</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Indentation affects the first line of the block container as well as each line after a <em>forced line break</em> , but does not affect lines after a <em>soft wrap break</em> .\"\n        }, {\n            \"value\": \"<code>hanging</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Inverts which lines are indented. All lines <em>except</em> the first line will be indented.\"\n        }]\n    },\n    \"text-orientation\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation\",\n        \"SUMMARY\": \"The <strong><code>text-orientation</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property defines the orientation of the text in a line. This property only has an effect in vertical mode, that is when <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a> is not <code>horizontal-tb</code>. It is useful to control the display of writing in languages using vertical script, but also to deal with vertical table headers.\",\n        \"VALUES\": [{\n            \"value\": \"<code>mixed</code>\",\n            \"description\": \"This keyword leads to have characters for horizontal-only scripts being turned 90&#xB0;, while the glyphs for vertical scripts are laid out naturally.\"\n        }, {\n            \"value\": \"<code>upright</code>\",\n            \"description\": \"This keyword leads to have characters for horizontal-only scripts to be laid out naturally (upright), as well as the glyphs for vertical scripts. Note that this keyword lead all characters to be considered as ltr: the used value of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> is <code>ltr</code>, whatever the user could try to set it to.\"\n        }, {\n            \"value\": \"<code>sideways</code>\",\n            \"description\": \"This keyword leads to have characters laid out like if they were laid out horizontally, but with the whole line rotated 90&#xB0; to the right if <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\\\" title=\\\"The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\\\"><code>writing-mode</code></a> is <code>vertical-rl</code> or to the left, if it is <code>vertical-lr</code>.\"\n        }, {\n            \"value\": \"<code>sideways-right</code>\",\n            \"description\": \"An alias to <code>sideways</code> that is kept for compatibility purpose.\"\n        }, {\n            \"value\": \"<code>use-glyph-orientation</code>\",\n            \"description\": \"On SVG elements, this keyword leads to use the value of the deprecated SVG properties <code>glyph-orientation-vertical</code> and <code>glyph-orientation-horizontal</code>.\"\n        }]\n    },\n    \"text-overflow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow\",\n        \"SUMMARY\": \"The <strong><code>text-overflow</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property determines how overflowed content that is not displayed is signaled to users. It can be clipped, display an ellipsis ('<code>…</code>', <code style=\\\"text-transform: uppercase;\\\">U+2026 Horizontal Ellipsis</code>), or display a custom string.\",\n        \"VALUES\": [{\n            \"value\": \"<code>clip</code>\",\n            \"description\": \"This keyword value indicates to truncate the text at the limit of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">content area</a>, therefore the truncation can happen in the middle of a character. To truncate at the transition between two characters, the empty string value (<code>&apos;&apos;</code>) must be used. The value <code>clip</code> is the default for this property.\"\n        }, {\n            \"value\": \"<code>ellipsis</code>\",\n            \"description\": \"This keyword value indicates to display an ellipsis (<code>&apos;&#x2026;&apos;</code>, <code style=\\\"text-transform: uppercase;\\\">U+2026 Horizontal Ellipsis</code>) to represent clipped text. The ellipsis is displayed inside the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">content area</a>, decreasing the amount of text displayed. If there is not enough space to display the ellipsis, it is clipped.\"\n        }, {\n            \"value\": \"<code>&lt;string&gt;</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The <a title=\\\"The &lt;string&gt; CSS data type represents a string. It is formed by a Unicode characters delimited by either double (&quot;) or single (&apos;) quotes. A double quoted string cannot contain double quotes unless escaped using a backslash (\\\\). The same practice applies for single quoted strings, they cannot contain single quotes unless escaped using a backslash (\\\\). The backslash character must be escaped to be part of the string.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/string\\\"><code>&lt;string&gt;</code></a> to be used to represent clipped text. The string is displayed inside the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model\\\">content area</a>, shortening more the size of the displayed text. If there is not enough place to display the string itself, it is clipped.\"\n        }, {\n            \"value\": \"<code>fade</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"This keyword clips the overflowing inline content and applies a fade-out effect near the edge of the line box with complete transparency at the edge.\"\n        }, {\n            \"value\": \"<code>fade(&#xA0;&lt;length&gt; | &lt;percentage&gt; )</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"This function clips the overflowing inline content and applies a fade-out effect near the edge of the line box with complete transparency at the edge.\"\n        }]\n    },\n    \"text-rendering\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering\",\n        \"SUMMARY\": \"The <strong><code>text-rendering</code></strong> CSS property provides information to the rendering engine about what to optimize for when rendering text.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The browser makes educated guesses about when to optimize for speed, legibility, and geometric precision while drawing text. For differences in how this value is interpreted by the browser, see the compatibility table.\"\n        }, {\n            \"value\": \"<code>optimizeSpeed</code>\",\n            \"description\": \"The browser emphasizes rendering speed over legibility and geometric precision when drawing text. It disables kerning and ligatures.\"\n        }, {\n            \"value\": \"<code>optimizeLegibility</code>\",\n            \"description\": \"The browser emphasizes legibility over rendering speed and geometric precision. This enables kerning and optional ligatures.\"\n        }, {\n            \"value\": \"<code>geometricPrecision</code>\",\n            \"description\": \"\\n <p>The browser emphasizes geometric precision over rendering speed and legibility. Certain aspects of fonts &#x2014; such as kerning &#x2014; don&apos;t scale linearly. So this value can make text using those fonts look good.</p>\\n\\n <p>In SVG, when text is scaled up or down, browsers calculate the final size of the text (which is determined by the specified font size and the applied scale) and request a font of that computed size from the platform&apos;s font system. But if you request a font size of, say, 9 with a scale of 140%, the resulting font size of 12.6 doesn&apos;t explicitly exist in the font system, so the browser rounds the font size to 12 instead. This results in stair-step scaling of text.</p>\\n\\n <p>But the <code>geometricPrecision</code> property &#x2014; when fully supported by the rendering engine &#x2014; lets you scale your text fluidly. For large scale factors, you might see less-than-beautiful text rendering, but the size is what you would expect&#x2014;neither rounded up nor down to the nearest font size supported by Windows or Linux.</p>\\n\\n <p class=\\\"note\\\"><strong>Hinweis</strong>: WebKit precisely applies the specified value, but Gecko treats the value the same as <code>optimizeLegibility</code>.</p>\\n \"\n        }]\n    },\n    \"text-shadow\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow\",\n        \"SUMMARY\": \"The <strong><code>text-shadow</code></strong> property adds shadows to text. It accepts a comma-separated list of shadows to be applied to the text and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>text-decorations</code></a> of the element.\",\n        \"VALUES\": [{\n            \"value\": \"&lt;color&gt;\",\n            \"description\": \"Optional. Can be specified either before or after the offset values. If the color is not specified, a UA-chosen color will be used. <div class=\\\"note\\\"><strong>Note:</strong>&#xA0;If you want to ensure consistency across browsers, explicitly specify a color.</div>\"\n        }, {\n            \"value\": \"&lt;offset-x&gt; &lt;offset-y&gt;\",\n            \"description\": \"Required. These <code>length</code>&#xA0;values specify the shadow&apos;s offset from the text. <code>&lt;offset-x&gt;</code> specifies the horizontal distance; a negative value places the shadow to the left of the text. <code>&lt;offset-y&gt;</code> specifies the vertical distance; a negative value places the shadow above the text. If both values are <code>0</code>, then the shadow is placed behind the text (and may generate a blur effect when <code>&lt;blur-radius&gt;</code> is set).<br>\\n To find out what units you can use, see <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>.\"\n        }, {\n            \"value\": \"&lt;blur-radius&gt;\",\n            \"description\": \"Optional. This is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value. If not specified, it defaults to <code>0</code>. The higher this value, the bigger the blur; the shadow becomes wider and lighter.\"\n        }]\n    },\n    \"text-size-adjust\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust\",\n        \"SUMMARY\": \"The <strong><code>text-size-adjust</code></strong> property allows control over the text inflation algorithm used on some mobile devices. As this property is non-standard, it must be prefixed: <code>-moz-text-size-adjust</code>, <code>-webkit-text-size-adjust</code>, and <code>-ms-text-size-adjust</code>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Disables the browser&apos;s inflation algorithm. On old WebKit-based desktop browsers (Chrome&#x2264;26, Safari&#x2264;5), this will instead prevent the user from zooming the webpage in or out.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Enables the browser&apos;s inflation algorithm. This value is used to cancel a <code>none</code> value previously set with CSS.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Enables the browser&apos;s inflation algorithm, specifying a percentage value with which to increase the font size.\"\n        }]\n    },\n    \"text-transform\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform\",\n        \"SUMMARY\": \"The <strong><code>text-transform</code></strong> CSS property specifies how to capitalize an element's text. It can be used to make text appear in all-uppercase or all-lowercase, or with each word capitalized.\",\n        \"VALUES\": [{\n            \"value\": \"<code>capitalize</code>\",\n            \"description\": \"\\n <p>Is a keyword forcing the first <em>letter</em> of each word to be converted to uppercase. Other characters are unchanged; that is, they retain their original case as written in the element&apos;s text. A letter is any Unicode character part of the Letter or Number general categories <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span> : it excludes any punctuation marks or symbols at the beginning of the word.</p>\\n\\n <div class=\\\"note\\\">Authors should not expect <code class=\\\"css\\\">capitalize</code> to follow language-specific titlecasing conventions (such as skipping articles in English).</div>\\n \"\n        }, {\n            \"value\": \"<code>uppercase</code>\",\n            \"description\": \"Is a keyword forcing all characters to be converted to uppercase.\"\n        }, {\n            \"value\": \"<code>lowercase</code>\",\n            \"description\": \"Is a keyword forcing all characters to be converted to lowercase.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Is a keyword preventing the case of all characters to be changed.\"\n        }, {\n            \"value\": \"<code>full-width</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Is a keyword forcing the writing of a character, mainly ideograms and latin scripts inside a square, allowing them to be aligned in the usual East Asian scripts (like Chinese or Japanese).\"\n        }]\n    },\n    \"text-underline-position\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/text-underline-position\",\n        \"SUMMARY\": \"The <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\">CSS</a> <strong><code>text-underline-position</code></strong> property specifies the position of the underline which is set using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration\\\" title=\\\"The text-decoration CSS property is used to set the text formatting to underline, overline, line-through or blink. Underline and overline decorations are positioned under the text, line-through over it.\\\"><code>text-decoration</code></a> property <code>underline</code> value.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"This keyword allows the browser to use an algorithm to choose between <code>under</code> and <code>alphabetic</code>.\"\n        }, {\n            \"value\": \"<code>under</code>\",\n            \"description\": \"This keyword forces the line to be set below the <em>alphabetic baseline</em>, at a position where it won&apos;t cross any descender. This is useful to prevent chemical or mathematical formulas, which make a large use of subscripts, to be illegible.\"\n        }, {\n            \"value\": \"<code>left</code>\",\n            \"description\": \"In vertical writing-modes, this keyword forces the line to be placed on the <em>left</em> of the characters. In horizontal writing-modes, it is a synonym of <code>under.</code>\"\n        }, {\n            \"value\": \"<code>right</code>\",\n            \"description\": \"In vertical writing-modes, this keyword forces the line to be placed on the <em>right</em> of the characters. In horizontal writing-modes, it is a synonym of <code>under.</code>\"\n        }, {\n            \"value\": \"<code>auto-pos</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword is a synonym of <code>auto</code> which must be used instead\"\n        }, {\n            \"value\": \"<code>above</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword forces the line to be above the text. When used with East-Asian text, using the <code>auto</code> keyword will lead to a similar effect.\"\n        }, {\n            \"value\": \"<code>below</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"This keyword forces the line to be under the text. When used with alphabetic text, using the <code>auto</code> keyword will lead to a similar effect.\"\n        }]\n    },\n    \"top\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/top\",\n        \"SUMMARY\": \"The <strong><code>top</code></strong> CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Is a negative, null or positive <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> that represents:\\n <ul>\\n  <li>for <em>absolutely positioned elements</em>, the distance to the top edge of the containing block;</li>\\n  <li>for <em>relatively positioned elements</em>, the offset that the element is moved below its position in the normal flow if it wasn&apos;t positioned.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> of the containing block&apos;s height, used as described in the <a href=\\\"#Summary\\\">summary</a>.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Is a keyword that represents:\\n <ul>\\n  <li>for absolutely positioned elements, the position the element based on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\" title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\"><code>bottom</code></a> property and treat <code>height: auto</code> as a height based on the content.</li>\\n  <li>for relatively positioned elements, the offset the element from its original position based on the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\\\" title=\\\"The bottom CSS property participates in specifying the position of positioned elements.\\\"><code>bottom</code></a> property, or if <code>bottom</code> is also <code>auto</code>, do not offset it at all.</li>\\n </ul>\\n \"\n        }, {\n            \"value\": \"<code>inherit</code>\",\n            \"description\": \"Is a keyword indicating that the value is the same than the computed value from its parent element (which may not be its containing block). This computed value is then handled like it was a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> or the <code>auto</code> keyword.\"\n        }]\n    },\n    \"touch-action\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action\",\n        \"SUMMARY\": \"The <strong><code>touch-action</code></strong> CSS property specifies whether, and in what ways, a given region can be manipulated by the user via a touchscreen (for instance, by panning or zooming features built into the browser).\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"Enable browser handling of all panning and zooming gestures.\"\n        }, {\n            \"value\": \"<code>none</code>\",\n            \"description\": \"Disable browser handling of all panning and zooming gestures.\"\n        }, {\n            \"value\": \"<code>pan-x</code>\",\n            \"description\": \"Enable single-finger horizontal panning gestures. May be combined with&#xA0;<strong>pan-y, pan-up,</strong>&#xA0;<strong>pan-down&#xA0;</strong>and/or&#xA0;<strong>pinch-zoom</strong>.\"\n        }, {\n            \"value\": \"<code>pan-y</code>\",\n            \"description\": \"Enable single-finger vertical panning gestures. May be combined with&#xA0;<strong>pan-x, pan-left, </strong><strong>pan-right</strong>&#xA0;and/or&#xA0;<strong>pinch-zoom</strong>.\"\n        }, {\n            \"value\": \"<code>manipulation</code>\",\n            \"description\": \"Enable panning and pinch zoom gestures, but disable additional non-standard gestures such as double-tap to zoom.&#xA0;Disabling double-tap to zoom removes the need for browsers to delay&#xA0;the generation of <strong>click</strong>&#xA0;events when the user taps the screen. This is an alias for &quot;<strong>pan-x pan-y pinch-zoom</strong>&quot; (which, for compatibility, is itself still valid).\"\n        }, {\n            \"value\": \"<code>pan-left</code>, <code>pan-right,pan-up,pan-down</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Enable single-finger gestures that begin by scrolling in the given direction(s). Once scrolling has started, the direction may still be reversed. Note that scrolling &quot;up&quot; (<strong>pan-up</strong>)&#xA0;means that the user is dragging their finger downward on the screen surface, and likewise&#xA0;<strong>pan-left</strong>&#xA0;means the user is dragging their finger to the right. Multiple directions may be combined except when there is a simpler representation (for example,&#xA0;<strong>&quot;</strong><strong>pan-left pan-right</strong>&quot; is invalid since&#xA0;&quot;<strong>pan-x</strong>&quot; is simpler, but&#xA0;&quot;<strong>pan-left pan-down</strong>&quot; is valid).\"\n        }, {\n            \"value\": \"<code>pinch-zoom</code>\",\n            \"description\": \"Enable multi-finger panning and zooming of the page. This may be combined with any of the&#xA0;<strong>pan-</strong>&#xA0;values.\"\n        }]\n    },\n    \"transform\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transform\",\n        \"SUMMARY\": \"The CSS <strong><code>transform</code></strong> property lets you modify the coordinate space of the CSS visual formatting model. Using it, elements can be translated, rotated, scaled, and skewed.\",\n        \"VALUES\": [{\n            \"value\": \"<a name=\\\"&lt;transform-function&gt;\\\" id=\\\"&lt;transform-function&gt;\\\"><code>&lt;transform-function&gt;</code></a>\",\n            \"description\": \"One or more of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function\\\">CSS transform functions</a> to be applied, see below. Composite transforms are effectively applied in order from right to left.\"\n        }, {\n            \"value\": \"<a name=\\\"none\\\" id=\\\"none\\\"><code>none</code></a>\",\n            \"description\": \"Specifies that no transform should be applied.\"\n        }]\n    },\n    \"transform-box\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-box\",\n        \"SUMMARY\": \"The <strong><code>transform-box</code></strong> property defines the layout box, to which the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform\\\" title=\\\"The CSS transform property lets you modify the coordinate space of the CSS visual formatting model. Using it, elements can be translated, rotated, scaled, and skewed.\\\"><code>transform</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\\\" title=\\\"The transform-origin property lets you modify the origin for transformations of an element. For example, the transform-origin of the rotate() function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element's transform, then translating by the property value.)\\\"><code>transform-origin</code></a> properties relate to.\",\n        \"VALUES\": [{\n            \"value\": \"<code>border-box</code>\",\n            \"description\": \"Uses the border box as reference box. The reference box of a table is the border box of its table wrapper box, not its table box.\"\n        }, {\n            \"value\": \"<code>fill-box</code>\",\n            \"description\": \"Uses the object bounding box as reference box.\"\n        }, {\n            \"value\": \"<code>view-box</code>\",\n            \"description\": \"Uses the nearest <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/SVG\\\" class=\\\"glossaryLink\\\" title=\\\"SVG: Scalable Vector Graphics (SVG) is a 2D vector image format based on an XML syntax.\\\">SVG</a> viewport as reference box. If a <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox\\\">viewBox</a></code> attribute is specified for the SVG viewport creating element, the reference box is positioned at the origin of the coordinate system established by the <code>viewBox</code> attribute and the dimension of the reference box is set to the width and height values of the <code>viewBox</code> attribute.\"\n        }]\n    },\n    \"transform-origin\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin\",\n        \"SUMMARY\": \"The <code>transform-origin</code> property lets you modify the origin for transformations of an element. For example, the transform-origin of the <code>rotate()</code> function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element's transform, then translating by the property value.)\",\n        \"VALUES\": [{\n            \"value\": \"<em>x-offset</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> describing how far from the left edge of the box the origin of the transform is set.\"\n        }, {\n            \"value\": \"<em>offset-keyword</em>\",\n            \"description\": \"Is one of the <code>left</code>, <code>right</code>, <code>top</code>, <code>bottom</code> or <code>center</code> keyword describing the corresponding offset.\"\n        }, {\n            \"value\": \"<em>y-offset</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> describing how far from the top edge of the box the origin of the transform is set.\"\n        }, {\n            \"value\": \"<em>x-offset-keyword</em>\",\n            \"description\": \"Is one of the <code>left</code>, <code>right</code> or <code>center</code> keyword describing how far from the left edge of the box the origin of the transform is set.\"\n        }, {\n            \"value\": \"<em>y-offset-keyword</em>\",\n            \"description\": \"Is one of the <code>top</code>, <code>bottom</code> or <code>center</code> keyword describing how far from the top edge of the box the origin of the transform is set.\"\n        }, {\n            \"value\": \"<em>z-offset</em>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> (and never a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a> which would make the statement invalid) describing how far from the user eye the z=0 origin is set.\"\n        }]\n    },\n    \"transform-style\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style\",\n        \"SUMMARY\": \"The<strong> <code>transform-style</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property determines if the children of the element are positioned in the 3D-space or are flattened in the plane of the element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>preserve-3d</code>\",\n            \"description\": \"Indicates that the children of the element should be positioned in the 3D-space.\"\n        }, {\n            \"value\": \"<code>flat</code>\",\n            \"description\": \"Indicates that the children of the element are lying in the plane of the element itself.\"\n        }]\n    },\n    \"transition\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transition\",\n        \"SUMMARY\": \"The <strong><code>transition</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS </a>property is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Shorthand_properties\\\">shorthand property</a> for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-property\\\" title=\\\"The transition-property CSS property is used to specify the names of CSS properties to which a transition effect should be applied.\\\"><code>transition-property</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-duration\\\" title=\\\"The transition-duration CSS property specifies the number of seconds or milliseconds a transition animation should take to complete. By default, the value is 0s, meaning that no animation will occur.\\\"><code>transition-duration</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-timing-function\\\" title=\\\"The transition-timing-function CSS property is used to describe how the intermediate values of the CSS&#xA0;properties being affected by a transition effect are calculated. This in essence lets you establish an acceleration curve, so that the speed of the transition can vary over its duration.\\\"><code>transition-timing-function</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-delay\\\" title=\\\"The transition-delay CSS property specifies the amount of time to wait between a change being requested to a property that is to be transitioned and the start of the transition effect.\\\"><code>transition-delay</code></a>. It enables you to define the transition between two states of an element. Different states may be defined using <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes\\\" title=\\\"https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes\\\">pseudo-classes</a> like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:hover\\\" title=\\\"The :hover CSS pseudo-class matches when the user designates an element with a pointing device, but does not necessarily activate it. This style may be overridden by any other link-related pseudo-classes, that is :link, :visited, and :active, appearing in subsequent rules. In order to style appropriately links, you need to put the :hover rule after the :link and :visited rules but before the :active one, as defined by the LVHA-order: :link &#x2014; :visited &#x2014; :hover &#x2014; :active.\\\"><code>:hover</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/:active\\\" title=\\\"The :active CSS pseudo-class matches when an element is being activated by the user. It allows the page to give a feedback that the activation has been detected by the browser. When interacting with a mouse, this is typically the time between the user pressing&#xA0;the mouse button and releasing&#xA0;it. The :active pseudo-class is also typically matched when using the keyboard tab key. It is frequently used on &lt;a&gt; and &lt;button&gt; HTML&#xA0;elements, but may not be limited to just those.\\\"><code>:active</code></a> or dynamically set using JavaScript.\",\n        \"VALUES\": []\n    },\n    \"transition-delay\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-delay\",\n        \"SUMMARY\": \"The <strong><code>transition-delay</code></strong> CSS property specifies the amount of time to wait between a change being requested to a property that is to be transitioned and the start of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions\\\">transition effect</a>.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;time&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a> denoting the amount of time to wait between a property&apos;s value changing and the start of the animation effect.\"\n        }]\n    },\n    \"transition-duration\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-duration\",\n        \"SUMMARY\": \"The <strong><code>transition-duration</code></strong> <a href=\\\"/en/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies the number of seconds or milliseconds a transition animation should take to complete. By default, the value is <code>0s</code>, meaning that no animation will occur.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;time&gt;</code>\",\n            \"description\": \"Is a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/time\\\" title=\\\"The &lt;time&gt; CSS data type denotes time dimensions expressed in seconds or milliseconds. They consists of a&#x200B; &#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&#x200B;&lt;number&gt; immediately followed by the unit. Like for any CSS dimension, there is no space between the unit literal and the number.\\\"><code>&lt;time&gt;</code></a> denoting the amount of time the transition from the old value of a property to the new value should take. A time of <code>0s</code> indicates that no transition will happen, that is the switch between the two states will be instantaneous. A negative value for the time renders the declaration invalid.\"\n        }]\n    },\n    \"transition-property\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-property\",\n        \"SUMMARY\": \"The <strong><code>transition-property</code> </strong>CSS property is used to specify the names of CSS properties to which a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions\\\">transition effect</a> should be applied.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"No properties will transition.\"\n        }, {\n            \"value\": \"<code>all</code>\",\n            \"description\": \"All properties that can have an animated transition will do so.\"\n        }, {\n            \"value\": \"<code>IDENT</code>\",\n            \"description\": \"A string identifying the property to which a transition effect should be applied when its value changes. This identifier is composed by case-insensitive letters&#xA0;<code>a</code> to <code>z</code>, numbers <code>0</code> to <code>9</code>, an underscore (<code>_</code>) or a dash(<code>-</code>). The first non-dash character must be a letter (that is:&#xA0;no number at the beginning of it, even preceded by a dash). Also, two dashes are forbidden at the beginning of the identifier.\"\n        }]\n    },\n    \"transition-timing-function\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-timing-function\",\n        \"SUMMARY\": \"The <strong><code>transition-timing-function</code></strong> CSS property is used to describe how the intermediate values of the CSS properties being affected by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions\\\" title=\\\"en/CSS/CSS transitions\\\">transition effect</a> are calculated. This in essence lets you establish an acceleration curve, so that the speed of the transition can vary over its duration.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;timing-function&gt;</code>\",\n            \"description\": \"Each <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/timing-function\\\" title=\\\"The &lt;single-transition-timing-function&gt; CSS data type denotes a mathematical function that describes how fast one-dimensional values change during transitions or animations. This in essence lets you establish an acceleration curve, so that the speed of the animation can vary over its duration. These functions are often called easing functions.\\\"><code>&lt;timing-function&gt;</code></a> represents the timing function to link to the corresponding property to transition, as defined in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/transition-property\\\" title=\\\"The transition-property CSS property is used to specify the names of CSS properties to which a transition effect should be applied.\\\"><code>transition-property</code></a>.\"\n        }]\n    },\n    \"translation-value\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/translation-value\",\n        \"SUMMARY\": \"Technical review completed.\",\n        \"VALUES\": []\n    },\n    \"unicode-bidi\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi\",\n        \"SUMMARY\": \"The <strong><code>unicode-bidi</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property together with the <a title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\"><code>direction</code></a> property relates to the handling of bidirectional text in a document. For example, if a block of text contains both left-to-right and right-to-left text then the user-agent uses a complex Unicode algorithm to decide how to display the text. This property overrides this algorithm and allows the developer to control the text embedding.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The element does not offer a additional level of embedding with respect to the bidirectional algorithm. For inline elements implicit reordering works across element boundaries.\"\n        }, {\n            \"value\": \"<code>embed</code>\",\n            \"description\": \"If the element is inline, this value opens an additional level of embedding with respect to the bidirectional algorithm. The direction of this embedding level is given by the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> property.\"\n        }, {\n            \"value\": \"<code>bidi-override</code>\",\n            \"description\": \"For inline elements this creates an override. For block container elements this creates an override for inline-level descendants not within another block container element. This means that inside the element, reordering is strictly in sequence according to the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> property; the implicit part of the bidirectional algorithm is ignored.\"\n        }, {\n            \"value\": \"<code>isolate</code>\",\n            \"description\": \"This keyword indicates that the element&apos;s container directionality should be calculated without considering the content of this element. The element is therefore <em>isolated</em> from its siblings. When applying its bidirectional-resolution algorithm, its container element treats it as one or several <code>U+FFFC Object Replacement Character</code>, i.e. like an image.\"\n        }, {\n            \"value\": \"<code>isolate-override</code>\",\n            \"description\": \"This keyword applies the isolation behavior of the <code>isolate</code> keyword to the surrounding content and the override behavior of the <code>bidi-override</code> keyword to the inner content.\"\n        }, {\n            \"value\": \"<code>plaintext</code>\",\n            \"description\": \"This keyword makes the elements directionality calculated without considering its parent bidirectional state or the value of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/direction\\\" title=\\\"Set the direction CSS property to match the direction of the text: rtl for languages written from right-to-left (like Hebrew or Arabic) text and ltr for other scripts. This is typically done as part of the document (e.g., using the dir attribute in HTML) rather than through direct use of CSS.\\\"><code>direction</code></a> property. The directionality is calculated using the P2 and P3 rules of the Unicode Bidirectional Algorithm.<br>\\n This value allows to display data which has already formatted using a tool following the Unicode Bidirectional Algorithm.\"\n        }]\n    },\n    \"unset\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/unset\",\n        \"SUMMARY\": \"The <code>unset</code> CSS keyword is the combination of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/initial\\\" title=\\\"The initial CSS keyword applies the initial value of a property to an element. It is allowed on every CSS property and causes the element for which it is specified to use the initial value of the property.\\\"><code>initial</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/inherit\\\" title=\\\"The inherit CSS-value causes the element for which it is specified to take the computed value of the property from its parent element. It is allowed on every CSS property.\\\"><code>inherit</code></a> keywords. Like these two other CSS-wide keywords, it can be applied to any CSS property, including the CSS shorthand <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/all\\\" title=\\\"The CSS all shorthand property resets all properties, apart from&#xA0;unicode-bidi and direction, to their initial or inherited value.\\\"><code>all</code></a>. This keyword <em>resets</em> the property to its inherited value if it inherits from its parent or to its initial value if not. In other words, it behaves like the <code>inherit</code> keyword in the first case and like the <code>initial</code> keyword in the second case.\",\n        \"VALUES\": []\n    },\n    \"user-select\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/user-select\",\n        \"SUMMARY\": \"Controls the actual <a href=\\\"https://developer.mozilla.org/en-US/docs/DOM/Selection\\\">Selection</a> operation. This doesn't have any effect on content loaded as chrome, except in textboxes. A similar property <code>user-focus</code> was proposed in <a href=\\\"http://www.w3.org/TR/2000/WD-css3-userint-20000216\\\">early drafts of a predecessor of css3-ui</a> but was rejected by the working group.\",\n        \"VALUES\": [{\n            \"value\": \"<code>none</code>\",\n            \"description\": \"The text of the element and sub-elements will not be able to be selected. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/Selection\\\">Selection</a> can contain these elements. Starting with Firefox 21 <code>none</code> behaves like <code>-moz-none</code>, so selection can be re-enabled on sub-elements using <code>-moz-user-select:text</code>.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The text will be selected according to the browser&apos;s default properties.\"\n        }, {\n            \"value\": \"<code>text</code>\",\n            \"description\": \"The text can be selected by the user.\"\n        }, {\n            \"value\": \"<code>-moz-none</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"The text of the element and sub-elements will appear as if they cannot be selected. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/Selection\\\">Selection</a> can contain these elements. Selection can be re-enabled on sub-elements using <code>-moz-user-select:text</code>. Starting with Firefox 21 <code>none</code> behaves like <code>-moz-none</code>.\"\n        }, {\n            \"value\": \"<code>all</code>\",\n            \"description\": \"In an HTML editor, if a double-click or context-click occurred in sub-elements, the highest ancestor with this value will be selected.\"\n        }, {\n            \"value\": \"<code>contain</code><br>\\n <code>element</code><span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span> (IE-specific alias)\",\n            \"description\": \"Enables selection to start within the element; however, the selection will be contained by the bounds of that element. Supported only in Internet Explorer.\"\n        }]\n    },\n    \"var()\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/var\",\n        \"SUMMARY\": \"The <strong><code>var()</code></strong> function can be used instead of any part of a value in any property on an element. The var() function can not be used as property names, selectors or anything else besides property values. (Doing so usually produces invalid syntax or else a value whose meaning has no connection to the variable.)\",\n        \"VALUES\": [{\n            \"value\": \"&lt;custom-property-name&gt;\",\n            \"description\": \"The production corresponds to this: It&#x2019;s defined as any valid identifier that starts with two dashes. Custom properties are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here.\"\n        }, {\n            \"value\": \"&lt;declaration-value&gt;\",\n            \"description\": \"The &lt;declaration-value&gt; production matches any sequence of one or more tokens.&#xA0; So, as long as the sequence does not contain &lt;bad-string-token&gt;, &lt;bad-url-token&gt;, unmatched &lt;)-token&gt;, &lt;]-token&gt;, or &lt;}-token&gt;, or top-level &lt;semicolon-token&gt; tokens or &lt;delim-token&gt; tokens with a value of &quot;!&quot; ,it represents the entirety of what a valid declaration can have as its value.\"\n        }]\n    },\n    \"vertical-align\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align\",\n        \"SUMMARY\": \"The <strong><code>vertical-align</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property specifies the vertical alignment of an inline or table-cell box.\",\n        \"VALUES\": [{\n            \"value\": \"<code>baseline</code>\",\n            \"description\": \"Aligns the baseline of the element with the baseline of its parent. The baseline of some <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS/Replaced_element\\\" title=\\\"CSS/Replaced_element\\\">replaced elements</a>, like <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea\\\" title=\\\"The HTML &lt;textarea&gt; element represents a multi-line plain-text editing control.\\\"><code>&lt;textarea&gt;</code></a>, is not specified by the HTML specification, meaning that their behavior with this keyword may change from one browser to the other.\"\n        }, {\n            \"value\": \"<code>sub</code>\",\n            \"description\": \"Aligns the baseline of the element with the subscript-baseline of its parent.\"\n        }, {\n            \"value\": \"<code>super</code>\",\n            \"description\": \"Aligns the baseline of the element with the superscript-baseline of its parent.\"\n        }, {\n            \"value\": \"<code>text-top</code>\",\n            \"description\": \"Aligns the top of the element with the top of the parent element&apos;s font.\"\n        }, {\n            \"value\": \"<code>text-bottom</code>\",\n            \"description\": \"Aligns the bottom of the element with the bottom of the parent element&apos;s font.\"\n        }, {\n            \"value\": \"<code>middle</code>\",\n            \"description\": \"Aligns the middle of the element with the baseline plus half the x-height of the parent.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a>\",\n            \"description\": \"Aligns the baseline of the element at the given length above the baseline of its parent.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\" title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\"><code>&lt;percentage&gt;</code></a>\",\n            \"description\": \"Like &lt;length&gt; values, with the percentage being a percent of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\\\" title=\\\"On block level elements, the line-height property specifies the minimum height of line boxes within the element.\\\"><code>line-height</code></a> property.\"\n        }, {\n            \"value\": \"<code>top</code>\",\n            \"description\": \"Align the top of the element and its descendants with the top of the entire line.\"\n        }, {\n            \"value\": \"<code>bottom</code>\",\n            \"description\": \"Align the bottom of the element and its descendants with the bottom of the entire line.\"\n        }, {\n            \"value\": \"<code>baseline</code> (and <code>sub</code>, <code>super</code>, <code>text-top</code>, <code>text-bottom</code>, <code>&lt;length&gt;</code>, and <code>&lt;percentage&gt;</code>)\",\n            \"description\": \"Align the baseline of the cell with the baseline of all other cells in the row that are baseline-aligned.\"\n        }, {\n            \"value\": \"<code>top</code>\",\n            \"description\": \"Align the top padding edge of the cell with the top of the row.\"\n        }, {\n            \"value\": \"<code>middle</code>\",\n            \"description\": \"Center the padding box of the cell within the row.\"\n        }, {\n            \"value\": \"<code>bottom</code>\",\n            \"description\": \"Align the bottom padding edge of the cell with the bottom of the row.\"\n        }]\n    },\n    \"visibility\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/visibility\",\n        \"SUMMARY\": \"The <strong><code>visibility</code></strong> property can be used to hide an element while leaving the space where it would have been. It can also hide rows or columns of a table.\",\n        \"VALUES\": [{\n            \"value\": \"<code>visible</code>\",\n            \"description\": \"Default value, the box is visible.\"\n        }, {\n            \"value\": \"<code>hidden</code>\",\n            \"description\": \"The box is invisible (fully transparent, nothing is drawn), but still affects layout.&#xA0; Descendants of the element will be visible if they have <code>visibility:visible</code> (this doesn&apos;t work in IE up to version 7).\"\n        }, {\n            \"value\": \"<code>collapse</code>\",\n            \"description\": \"For table rows, columns, column groups, and row groups the row(s) or column(s) are hidden and the space they would have occupied is removed (as if <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/display\\\" title=\\\"The display CSS property specifies the type of rendering box used for an element. In HTML, default display property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is inline.\\\"><code>display</code></a>: none</code> were applied to the column/row of the table). However, the size of other rows and columns is still calculated as though the cells in the collapsed row(s) or column(s) are present. This was designed for fast removal of a row/column from a table without having to recalculate widths and heights for every portion of the table. For XUL&#xA0;elements, the computed size of the element is always zero, regardless of other styles that would normally affect the size, although margins still take effect. For other elements, <code>collapse</code> is treated the same as <code>hidden</code>.\"\n        }]\n    },\n    \"white-space\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/white-space\",\n        \"SUMMARY\": \"The <strong><code>white-space</code></strong> property is used to describe how whitespace inside the element is handled.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Sequences of whitespace are collapsed. Newline characters in the source are handled as other whitespace. Breaks lines as necessary to fill line boxes.\"\n        }, {\n            \"value\": \"<code>nowrap</code>\",\n            \"description\": \"Collapses whitespace as for <code>normal</code>, but suppresses line breaks (text wrapping) within text.\"\n        }, {\n            \"value\": \"<code>pre</code>\",\n            \"description\": \"Sequences of whitespace are preserved.&#xA0;Lines are only broken at newline characters in the source and at <a title=\\\"The HTML &lt;br&gt; element produces a line break in text (carriage-return). It is useful for writing a poem or an address, where the division of lines is significant.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br\\\"><code>&lt;br&gt;</code></a> elements.\"\n        }, {\n            \"value\": \"<code>pre-wrap</code>\",\n            \"description\": \"Sequences of whitespace are preserved. Lines are broken at newline characters, at <a title=\\\"The HTML &lt;br&gt; element produces a line break in text (carriage-return). It is useful for writing a poem or an address, where the division of lines is significant.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br\\\"><code>&lt;br&gt;</code></a>, and as necessary to fill line boxes.\"\n        }, {\n            \"value\": \"<code>pre-line</code>\",\n            \"description\": \"Sequences of whitespace are collapsed. Lines are broken at newline characters, at <a title=\\\"The HTML &lt;br&gt; element produces a line break in text (carriage-return). It is useful for writing a poem or an address, where the division of lines is significant.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br\\\"><code>&lt;br&gt;</code></a>, and as necessary to fill line boxes.\"\n        }]\n    },\n    \"widows\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/widows\",\n        \"SUMMARY\": \"When a paragraph is split over two pages in <code>paged</code> media, the <strong><code>widows</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/CSS\\\" title=\\\"CSS\\\">CSS</a> property defines the minimum number of lines that must be left at the top of the second page. In typography, a <em>widow</em> is the last line of a paragraph appearing alone at the top of a new page. Setting the <code>widows</code> property allows the prevention of single-line widows.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"Denotes the minimum number of lines that can stay alone on the top of a new page when a paragraph is split. If the value is not <strong>positive</strong>, the declaration is invalid.\"\n        }]\n    },\n    \"width\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/width\",\n        \"SUMMARY\": \"The <strong><code>width</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the width of the content area of an element. The <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model#content-area\\\">content area</a> is <em>inside</em> the padding, border, and margin of the element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"See <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Specified as a <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> of containing block&apos;s width. If the width of the containing block depends on the width of the element, the resulting layout is undefined.\"\n        }, {\n            \"value\": \"<code>border-box </code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If present, the preceding <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> is applied to the element&apos;s border box.\"\n        }, {\n            \"value\": \"<code>content-box</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"If present, the preceding <a title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\"><code>&lt;length&gt;</code></a> or <a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a> is applied to the element&apos;s content box.\"\n        }, {\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The browser will calculate and select a width for the specified element.\"\n        }, {\n            \"value\": \"fill <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Use the&#xA0;<code>fill-available</code> inline size&#xA0;or&#xA0;<code>fill-available</code> block size, as appropriate to the writing mode.\"\n        }, {\n            \"value\": \"<code>max-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic preferred width.\"\n        }, {\n            \"value\": \"<code>min-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The intrinsic minimum width.\"\n        }, {\n            \"value\": \"<code>available</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The containing block width minus horizontal margin, border and padding.\"\n        }, {\n            \"value\": \"<code>fit-content</code> <span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"The larger of:\\n <ul>\\n  <li>the intrinsic minimum width</li>\\n  <li>the smaller of the intrinsic preferred width and the available width</li>\\n </ul>\\n \"\n        }]\n    },\n    \"will-change\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/will-change\",\n        \"SUMMARY\": \"The <strong><code>will-change</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property provides a way for authors to hint browsers about the kind of changes to be expected on an element, so that the browser can set up appropriate optimizations ahead of time before the element is actually changed.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"This keyword expresses no particular intent; the user agent should apply whatever heuristics and optimizations it normally does.\"\n        }, {\n            \"value\": \"<code>scroll-position</code>\",\n            \"description\": \"Indicates that the author expects to animate or change the scroll position of the element in the near future.\"\n        }, {\n            \"value\": \"<code>contents</code>\",\n            \"description\": \"Indicates that the author expects to animate or change something about the element&#x2019;s contents in the near future.\"\n        }, {\n            \"value\": \"<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident\\\" title=\\\"The documentation about this has not yet been written; please consider contributing!\\\"><code>&lt;custom-ident&gt;</code></a>\",\n            \"description\": \"Indicates that the author expects to animate or change the property with the given name on the element in the near future. If the property given is a shorthand, it indicates the expectation for all the longhands the shorthand expands to. It cannot be one of the following values: <code>unset</code>, <code>initial</code>, <code>inherit</code>, <code>will-change</code>, <code>auto</code>, <code>scroll-position</code>, or <code>contents</code>. The spec doesn&apos;t define the behavior of particular value, but it is common for <code>transform</code> to be a compositing layer hint. <a href=\\\"https://github.com/operasoftware/devopera/pull/330\\\" class=\\\"external\\\">Chrome currently takes two actions</a>, given particular CSS property idents: establish a new compositing layer or a new <a href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/stacking_context\\\" class=\\\"glossaryLink\\\" title=\\\"stacking context: Stacking context&#xA0;refers to how&#xA0;elements on a webpage appear to sit&#xA0;on top of other elements, just as you can arrange index cards on your desk to lie side-by-side or overlap each other.\\\">stacking context</a>.\"\n        }]\n    },\n    \"word-break\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/word-break\",\n        \"SUMMARY\": \"The<strong> <code>word-break</code></strong> CSS property is used to specify whether to break lines within words.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Use the default line break rule.\"\n        }, {\n            \"value\": \"<code>break-all</code>\",\n            \"description\": \"Word breaks may be inserted between any character for non-CJK (Chinese/Japanese/Korean) text.\"\n        }, {\n            \"value\": \"<code>keep-all</code>\",\n            \"description\": \"Don&apos;t allow word breaks for CJK text.&#xA0; Non-CJK text behavior is the same as for <code>normal</code>.\"\n        }]\n    },\n    \"word-spacing\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/word-spacing\",\n        \"SUMMARY\": \"The <strong><code>word-spacing</code></strong> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a> property specifies the spacing behavior between tags and words.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"The normal inter-word space, as defined by the current font and/or the browser.\"\n        }, {\n            \"value\": \"<code>&lt;length&gt;</code>\",\n            \"description\": \"Specifies extra spacing in addition to the intrinsic inter-word spacing defined by the font. See <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/length\\\" title=\\\"The &lt;length&gt; CSS data type denotes distance measurements. It is a &lt;number&gt; immediately followed by a length unit (px, em, pc, in, mm, &#x2026;). Like for any CSS dimension, there is no space between the unit literal and the number.&#xA0;The length unit is optional after the &lt;number&gt; 0.\\\"><code>&lt;length&gt;</code></a> value for possible units.\"\n        }, {\n            \"value\": \"<code>&lt;percentage&gt;</code>\",\n            \"description\": \"Specifies the additional spacing as a percentage of the affected character&#x2019;s advance width.\"\n        }]\n    },\n    \"writing-mode\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode\",\n        \"SUMMARY\": \"The <strong><code>writing-mode</code></strong> property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress.\",\n        \"VALUES\": [{\n            \"value\": \"<code>horizontal-tb</code>\",\n            \"description\": \"Content flows horizontally from left to right, vertically from top to bottom. The next horizontal line is positioned below the previous line.\"\n        }, {\n            \"value\": \"<code>vertical-rl</code>\",\n            \"description\": \"Content flows vertically from top to bottom, horizontally from right to left. The next vertical line is positioned to the left of the previous line.\"\n        }, {\n            \"value\": \"<code>vertical-lr</code>\",\n            \"description\": \"Content flows vertically from top to bottom, horizontally from left to right. The next vertical line is positioned to the right of the previous line.\"\n        }, {\n            \"value\": \"<code>sideways-rl</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Content flows vertically from top to bottom and all the glyphs, even those in vertical scripts, are set sideways toward the right.\"\n        }, {\n            \"value\": \"<code>sideways-lr</code><span title=\\\"This is an experimental API that should not be used in production code.\\\"><i class=\\\"icon-beaker\\\"> </i></span>\",\n            \"description\": \"Content flows vertically from top to bottom and all the glyphs, even those in vertical scripts, are set sideways toward the left.\"\n        }, {\n            \"value\": \"<code>lr</code> <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Deprecated except for SVG1 documents. For CSS, use <code>horizontal-tb</code>.\"\n        }, {\n            \"value\": \"<code>lr-tb</code> <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Deprecated except for SVG1 documents. For CSS, use <code>horizontal-tb</code>.\"\n        }, {\n            \"value\": \"<code>rl</code> <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Deprecated except for SVG1 documents. For CSS, use <code>horizontal-tb</code>.\"\n        }, {\n            \"value\": \"<code>tb</code> <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Deprecated except for SVG1 documents. For CSS, use <code>vertical-lr</code>.\"\n        }, {\n            \"value\": \"<code>tb-rl</code> <span title=\\\"This deprecated API should no longer be used, but will probably still work.\\\"><i class=\\\"icon-thumbs-down-alt\\\"> </i></span>\",\n            \"description\": \"Deprecated except for SVG1 documents. For CSS, use <code>vertical-rl</code>.\"\n        }]\n    },\n    \"z-index\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/z-index\",\n        \"SUMMARY\": \"The <strong><code>z-index</code></strong> property specifies the z-order of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/position\\\">positioned</a> element and its descendants. When elements overlap, z-order determines which one covers the other. An element with a larger z-index generally covers an element with a lower one.\",\n        \"VALUES\": [{\n            \"value\": \"<code>auto</code>\",\n            \"description\": \"The box does not establish a new local stacking context. The stack level of the generated box in the current stacking context is the same as its parent&apos;s box.\"\n        }, {\n            \"value\": \"<code>&lt;integer&gt;</code>\",\n            \"description\": \"This integer is the stack level of the generated box in the current stacking context. The box also establishes a local stacking context in which its stack level is <code>0</code>. This means that the z-indexes of descendants are not compared to the z-indexes of elements outside this element.\"\n        }]\n    },\n    \"zoom\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/CSS/zoom\",\n        \"SUMMARY\": \"The non-standard <dfn><code>zoom</code></dfn> CSS property can be used to control the magnification scale of an element.\",\n        \"VALUES\": [{\n            \"value\": \"<code>normal</code>\",\n            \"description\": \"Render this element at its normal size.\"\n        }, {\n            \"value\": \"<code>reset</code> <span title=\\\"This API has not been standardized.\\\"><i class=\\\"icon-warning-sign\\\"> </i></span>\",\n            \"description\": \"Do not (de)magnify this element if the user applies non-pinch-based zooming (e.g. by pressing <kbd>Ctrl</kbd>-<kbd>-</kbd> or <kbd>Ctrl</kbd>+<kbd>+</kbd> keyboard shortcuts) to the document. Only supported by WebKit (and possibly Blink).\"\n        }, {\n            \"value\": \"<a title=\\\"The &lt;percentage&gt; CSS data types represent a percentage value. Many CSS properties can take percentage values, often to define sizes in terms of parent objects. Percentages are formed by a &lt;number&gt; immediately followed by the percentage sign %. Just as is the case with all other units in CSS, there isn&apos;t a space between the &apos;%&apos; and the number.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/percentage\\\"><code>&lt;percentage&gt;</code></a>\",\n            \"description\": \"Zoom factor. <code>100%</code> is equivalent to <code>normal</code>. Values larger than <code>100%</code> zoom in. Values smaller than <code>100%</code> zoom out.\"\n        }, {\n            \"value\": \"<a title=\\\"The &lt;number&gt; CSS data type represents a number, either integer or fractional. Its syntax extends the one of the &lt;integer&gt; data value. To represent a fractional value, add the fractional part &#x2014; a &apos;.&apos; followed by one or several decimal digits &#x2014; to any &lt;integer&gt; data value. Like for &lt;integer&gt; data type, there isn&apos;t any unit associated to a &lt;number&gt;, which is not a CSS dimension.\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/number\\\"><code>&lt;number&gt;</code></a>\",\n            \"description\": \"Zoom factor. Equivalent to the corresponding percentage (<code>1.0</code> = <code>100%</code> = <code>normal</code>). Values larger than <code>1.0</code> zoom in. Values smaller than <code>1.0</code> zoom out.\"\n        }]\n    }\n}"
  },
  {
    "path": "src/extensions/default/MDNDocs/html.json",
    "content": "{\n    \"<a>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a\",\n        \"SUMMARY\": \"The <em>HTML <code>&lt;a&gt;</code> Element</em> (or the HTML Anchor Element) defines a hyperlink, the named target destination for a hyperlink, or both.\"\n    },\n    \"<abbr>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr\",\n        \"SUMMARY\": \"The <em>HTML Abbreviation element</em> (<strong>&lt;abbr&gt;</strong>) represents an abbreviation and optionally provides a full description for it. If present, the <code>title</code> attribute must contain this full description and nothing else.\"\n    },\n    \"<acronym>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/acronym\",\n        \"SUMMARY\": \"The HTML Acronym Element (<code>&lt;acronym&gt;)</code> allows authors to clearly indicate a sequence of characters that compose an acronym or abbreviation for a word.\"\n    },\n    \"<address>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address\",\n        \"SUMMARY\": \"The <em>HTML <code>Address</code> Element</em> (<strong>&lt;address&gt;</strong>) should be used by authors to supply contact information for its nearest <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article\\\" title=\\\"The HTML Article Element (&lt;article&gt;) represents a self-contained composition in a document, page, application, or site, which is intended to be independently distributable or reusable, e.g., in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, or any other independent item of content. Each &lt;article&gt; should be identified, typically by including a heading (h1-h6 element) as a child of the &lt;article&gt; element.\\\"><code>&lt;article&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body\\\" title=\\\"The HTML Body Element (&lt;body&gt;) represents the content of an HTML&#xA0;document. There can be only one &lt;body&gt; element in a document.\\\"><code>&lt;body&gt;</code></a> ancestor; in the latter case, it applies to the whole document.\"\n    },\n    \"<applet>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/applet\",\n        \"SUMMARY\": \"The HTML Applet Element (<code>&lt;applet&gt;</code>) identifies the inclusion of a Java applet.\"\n    },\n    \"<area>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area\",\n        \"SUMMARY\": \"The <em>HTML <code>&lt;area&gt;</code> element</em> defines a hot-spot region on an image, and optionally associates it with a <a class=\\\"glossaryLink\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/Hyperlink\\\" title=\\\"hypertext link: Hyperlinks connect web pages, or data items, to one another. In HTML, anchor elements define the hyperlinks from a part of a Web page, such as a text string or image, to another site, page or even a particular point within a page.\\\">hypertext link</a>. This element is used only within a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map\\\" title=\\\"The HTML &lt;map&gt; element is used with &lt;area&gt; elements to define an image map (a clickable link area).\\\"><code>&lt;map&gt;</code></a> element.\"\n    },\n    \"<article>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article\",\n        \"SUMMARY\": \"The <em>HTML <code>Article</code> Element</em> (<strong>&lt;article&gt;</strong>) represents a self-contained composition in a document, page, application, or site, which is intended to be independently distributable or reusable, e.g., in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, or any other independent item of content. Each <em><code>&lt;article&gt;</code></em> should be identified, typically by including a heading (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements\\\">h1-h6</a> element) as a child of the <em><code>&lt;article&gt;</code></em> element.\"\n    },\n    \"<aside>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside\",\n        \"SUMMARY\": \"The <em>HTML <code>&lt;aside&gt;</code> element</em> represents a section of the page with content connected tangentially to the rest, which could be considered separate from that content. These sections are often represented as sidebars or inserts. They often contain the definitions on the sidebars, such as definitions from the glossary; there may also be other types of information, such as related advertisements; the biography of the author; web applications; profile information or related links on the blog.\"\n    },\n    \"<audio>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;audio&gt;</code> element</strong> is used to embed sound content in documents. It may contain several audio sources, represented using the <code>src</code> attribute or the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source\\\" title=\\\"The HTML &lt;source&gt; element is used to specify multiple media resources for &lt;picture&gt;, &lt;audio&gt; and &lt;video&gt; elements. It is an empty element. It is commonly used to serve the same media in multiple formats supported by different browsers.\\\"><code>&lt;source&gt;</code></a> element; the browser will choose the most suitable one.\"\n    },\n    \"<b>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;b&gt;</code> Element</strong> represents a span of text stylistically different from normal text, without conveying any special importance or relevance. It is typically used for keywords in a summary, product names in a review, or other spans of text whose typical presentation would be boldfaced. Another example of its use is to mark the lead sentence of each paragraph of an article.\"\n    },\n    \"<base>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base\",\n        \"SUMMARY\": \"The <em>HTML Base Element</em> (<strong>&lt;base&gt;</strong>) specifies the base URL to use for all relative URLs contained within a document. There can be only one &lt;base&gt; element in a document.\"\n    },\n    \"<basefont>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/basefont\",\n        \"SUMMARY\": \"The HTML basefont element (<code>&lt;basefont&gt;</code>) establishes a default font size for a document. Font size then can be varied relative to the base font size using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/font\\\" title=\\\"The HTML Font Element (&lt;font&gt;) defines the font size, color and face for its content.\\\"><code>&lt;font&gt;</code></a> element.\"\n    },\n    \"<bdi>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi\",\n        \"SUMMARY\": \"The <em>HTML <code>&lt;bdi&gt;</code> Element</em> (or Bi-Directional Isolation Element) isolates a span of text that might be formatted in a different direction from other text outside it.\"\n    },\n    \"<bdo>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;bdo&gt;</code> Element</strong> (or <em>HTML bidirectional override element</em>) is used to override the current directionality of text. It causes the directionality of the characters to be ignored in favor of the specified directionality.\"\n    },\n    \"<bgsound>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bgsound\",\n        \"SUMMARY\": \"The HTML Background Sound Element (<bgsound>) is an Internet Explorer element associating a background sound with a page.\"\n    },\n    \"<big>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/big\",\n        \"SUMMARY\": \"The HTML Big Element (<code>&lt;big&gt;</code>) makes the text <em>font size</em> one size bigger (for example, from small to medium, or from large to x-large) up to the browser's maximum font size.\"\n    },\n    \"<blink>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blink\",\n        \"SUMMARY\": \"The HTML Blink Element (<code>&lt;blink&gt;</code>) is a non-standard element causing the enclosed text to flash slowly.\"\n    },\n    \"<blockquote>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block Quotation Element</em>) indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation (see <a href=\\\"https://developer.mozilla.org/en-US/docs/HTML/Element/blockquote#Notes\\\" title=\\\"HTML/Element/blockquote#Notes\\\">Notes</a> for how to change it). A URL for the source of the quotation may be given using the <strong>cite</strong> attribute, while a text representation of the source can be given using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite\\\" title=\\\"The&#xA0;HTML Citation Element&#xA0;(&lt;cite&gt;) represents a reference to a creative work. It must include the title of a work or a URL reference,&#xA0;which may be in an abbreviated form according to the conventions used for the addition of citation metadata.\\\"><code>&lt;cite&gt;</code></a> element.\"\n    },\n    \"<body>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body\",\n        \"SUMMARY\": \"The <em>HTML Body Element</em> (<strong>&lt;body&gt;</strong>) represents the content of an HTML document. There can be only one <code>&lt;body&gt;</code> element in a document.\"\n    },\n    \"<br>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;br&gt;</code> Element</strong> (or <em>HTML </em><em>Line Break Element</em>) produces a line break in text (carriage-return). It is useful for writing a poem or an address, where the division of lines is significant.\"\n    },\n    \"<button>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button\",\n        \"SUMMARY\": \"The <strong>HTML <em><code>&lt;button&gt;</code></em> Element</strong> represents a clickable button.\"\n    },\n    \"<canvas>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;canvas&gt;</code> Element</strong> can be used to draw graphics via scripting (usually <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/JavaScript\\\" title=\\\"JavaScript\\\">JavaScript</a>). For example, it can be used to draw graphs, make photo compositions or even perform animations. You may (and should) provide alternate content inside the <code>&lt;canvas&gt;</code> block. That content will be rendered both on older browsers that don't support canvas <strong>and</strong> in browsers with JavaScript disabled.\"\n    },\n    \"<caption>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;caption&gt;</code> Element</strong> (or <em>HTML Table Caption Element</em>) represents the title of a table. Though it is always the first descendant of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table\\\" title=\\\"The HTML Table Element (&lt;table&gt;) represents data in two dimensions or more.\\\"><code>&lt;table&gt;</code></a>, its styling, using CSS, may place it elsewhere, relative to the table.\"\n    },\n    \"<center>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/center\",\n        \"SUMMARY\": \"The HTML Center Element (<code>&lt;center&gt;</code>) is a <a href=\\\"https://developer.mozilla.org/en-US/docs/HTML/Block-level_elements\\\" title=\\\"HTML/Block-level_elements\\\">block-level element</a> that can contain paragraphs and other block-level and inline elements. The entire content of this element is centered horizontally within its containing element (typically, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body\\\" title=\\\"The HTML Body Element (&lt;body&gt;) represents the content of an HTML&#xA0;document. There can be only one &lt;body&gt; element in a document.\\\"><code>&lt;body&gt;</code></a>).\"\n    },\n    \"<cite>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite\",\n        \"SUMMARY\": \"The <em>HTML Citation Element</em> (<strong>&lt;cite&gt;</strong>) represents a reference to a creative work. It must include the title of a work or a URL reference, which may be in an abbreviated form according to the conventions used for the addition of citation metadata.\"\n    },\n    \"<code>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code\",\n        \"SUMMARY\": \"The <em>HTML Code Element</em> (<strong>&lt;code&gt;</strong>) represents a fragment of computer code. By default, it is displayed in the browser's default monospace font.\"\n    },\n    \"<col>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col\",\n        \"SUMMARY\": \"The <em>HTML Table Column Element</em> (<strong>&lt;col&gt;</strong>) defines a column within a table and is used for defining common semantics on all common cells. It is generally found within a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup\\\" title=\\\"The HTML &lt;colgroup&gt; Element (or HTML Table Column Group Element) defines a group of columns within a table.\\\"><code>&lt;colgroup&gt;</code></a> element.\"\n    },\n    \"<colgroup>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup\",\n        \"SUMMARY\": \"The <em>HTML Table Column Group Element</em> (<strong>&lt;colgroup&gt;</strong>) defines a group of columns within a table.\"\n    },\n    \"<command>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/command\",\n        \"SUMMARY\": \"The <code>command</code> element represents a command which the user can invoke.\"\n    },\n    \"<content>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/content\",\n        \"SUMMARY\": \"The <strong><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML\\\">HTML</a> <code>&lt;content&gt;</code></strong> element is used inside of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM\\\">Shadow DOM</a> as an <a class=\\\"glossaryLink\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/insertion_point\\\" title=\\\"The definition of that term (insertion point) has not been written yet; please consider contributing it!\\\">insertion point</a>. It is not intended to be used in ordinary HTML. It is used with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Web_Components\\\">Web Components</a>.\"\n    },\n    \"<data>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;data&gt;</code> Element</strong> links a given content with a machine-readable translation. If the content is time- or date-related, the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time\\\" title=\\\"The HTML &lt;time&gt; element represents either a time on a 24-hour clock or a precise date in the Gregorian calendar (with optional time and timezone information).\\\"><code>&lt;time&gt;</code></a> must be used.\"\n    },\n    \"<datalist>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist\",\n        \"SUMMARY\": \"The <em>HTML Datalist Element</em> (<strong>&lt;datalist&gt;</strong>) contains a set of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option\\\" title=\\\"In a Web form, the HTML &lt;option&gt; element is used to create a control representing an item within a &lt;select&gt;, an &lt;optgroup&gt; or a &lt;datalist&gt; HTML5 element.\\\"><code>&lt;option&gt;</code></a> elements that represent the values available for other controls.\"\n    },\n    \"<dd>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd\",\n        \"SUMMARY\": \"The <em>HTML Description Element</em> (<strong>&lt;dd&gt;</strong>) indicates the description of a term in a description list (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl\\\" title=\\\"The HTML &lt;dl&gt; Element (or HTML Description List Element) encloses a list of pairs of terms and descriptions. Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs).\\\"><code>&lt;dl&gt;</code></a>) element. This element can occur only as a child element of a definition list and it must follow a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt\\\" title=\\\"The HTML &lt;dt&gt; element (or HTML Definition Term Element) identifies a term in a definition list. This element can occur only as a child element of a &lt;dl&gt;. It is usually followed by a &lt;dd&gt; element; however, multiple &lt;dt&gt; elements in a row indicate several terms that are all defined by the immediate next &lt;dd&gt; element.\\\"><code>&lt;dt&gt;</code></a> element.\"\n    },\n    \"<del>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del\",\n        \"SUMMARY\": \"The <em>HTML Deleted Text Element</em> (<strong>&lt;del&gt;</strong>) represents a range of text that has been deleted from a document. This element is often (but need not be) rendered with strike-through text.\"\n    },\n    \"<details>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details\",\n        \"SUMMARY\": \"The <em>HTML Details Element</em> (<strong>&lt;details&gt;</strong>) is used as a disclosure widget from which the user can retrieve additional information.\"\n    },\n    \"<dfn>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn\",\n        \"SUMMARY\": \"The <em>HTML Definition Element</em> (<strong>&lt;dfn&gt;</strong>) represents the defining instance of a term.\"\n    },\n    \"<dialog>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;dialog&gt;</code> element</strong> represents a dialog box or other interactive component, such as an inspector or window. <code>&lt;form&gt;</code> elements can be integrated within a dialog by specifying them with the attribute <code>method=\\\"dialog\\\"</code>. When such a form is submitted, the dialog is closed with a <code>returnValue</code> attribute set to the <code>value</code> of the submit button used.\"\n    },\n    \"<dir>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dir\",\n        \"SUMMARY\": \"The <em>HTML directory element</em> (<code>&lt;dir&gt;</code>) represents a directory, namely a collection of filenames.\"\n    },\n    \"<div>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div\",\n        \"SUMMARY\": \"The <strong><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML\\\">HTML</a> <code>&lt;div&gt;</code> element</strong> (or <em>HTML Document Division Element</em>) is the generic container for flow content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the <strong>class</strong> or <strong>id</strong> attributes), or because they share attribute values, such as <strong>lang</strong>. It should be used only when no other semantic element (such as <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article\\\" title=\\\"The HTML &lt;article&gt; Element represents a self-contained composition in a document, page, application, or site, which is intended to be independently distributable or reusable, e.g., in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content.\\\"><code>&lt;article&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav\\\" title=\\\"The HTML Navigation Element (&lt;nav&gt;) represents a section of a page that links to other pages or to parts within the page: a section with navigation links.\\\"><code>&lt;nav&gt;</code></a>) is appropriate.\"\n    },\n    \"<dl>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;dl&gt;</code> Element</strong> (or <em>HTML</em> <em>Description List Element</em>) encloses a list of pairs of terms and descriptions. Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs).\"\n    },\n    \"<dt>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;dt&gt;</code> element</strong> (or HTML Definition Term Element) identifies a term in a definition list. This element can occur only as a child element of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl\\\" title=\\\"The HTML &lt;dl&gt; Element (or HTML Description List Element) encloses a list of pairs of terms and descriptions. Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs).\\\"><code>&lt;dl&gt;</code></a>. It is usually followed by a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd\\\" title=\\\"The HTML &lt;dd&gt; Element (or HTML Description Element) indicates the description of a term in a description list (&lt;dl&gt;) element. This element can occur only as a child element of a definition list and it must follow a &lt;dt&gt; element.\\\"><code>&lt;dd&gt;</code></a> element; however, multiple <code>&lt;dt&gt;</code> elements in a row indicate several terms that are all defined by the immediate next <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd\\\" title=\\\"The HTML &lt;dd&gt; Element (or HTML Description Element) indicates the description of a term in a description list (&lt;dl&gt;) element. This element can occur only as a child element of a definition list and it must follow a &lt;dt&gt; element.\\\"><code>&lt;dd&gt;</code></a> element.\"\n    },\n    \"<element>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/element\",\n        \"SUMMARY\": \"The <strong><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML\\\">HTML</a> <code>&lt;element&gt;</code> element</strong> is used to define new custom DOM elements.\"\n    },\n    \"<em>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em\",\n        \"SUMMARY\": \"The <em>HTML Emphasis Element</em> (<strong>&lt;em&gt;</strong>) marks text that has stress emphasis. The <code>&lt;em&gt;</code> element can be nested, with each level of nesting indicating a greater degree of emphasis.\"\n    },\n    \"<embed>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;embed&gt;</code> Element</strong> represents an integration point for an external application or interactive content (in other words, a plug-in).\"\n    },\n    \"<fieldset>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;fieldset&gt;</code> element</strong> is used to group several controls as well as labels (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label\\\" title=\\\"The HTML Label&#xA0;Element (&lt;label&gt;) represents a caption for an item in a user interface. It can be associated with a control either by placing the control element inside the &lt;label&gt; element, or by using the for attribute. Such a control is called the labeled control of the label element.\\\"><code>&lt;label&gt;</code></a>) within a web form.\"\n    },\n    \"<figcaption>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;figcaption&gt;</code> Element</strong> represents a caption or a legend associated with a figure or an illustration described by the rest of the data of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure\\\" title=\\\"The HTML &lt;figure&gt; Element represents self-contained content, frequently with a caption&#xA0;(&lt;figcaption&gt;), and is&#xA0;typically referenced as a single unit. While it is related to the main flow, its position is independent of the main flow. Usually this is an image, an illustration, a diagram, a code snippet, or a schema that is referenced in the main text, but that can be moved to another page or to an appendix without affecting the main flow.\\\"><code>&lt;figure&gt;</code></a> element which is its immediate ancestor which means <code>&lt;figcaption&gt;</code> can be the first or last element inside a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure\\\" title=\\\"The HTML &lt;figure&gt; Element represents self-contained content, frequently with a caption&#xA0;(&lt;figcaption&gt;), and is&#xA0;typically referenced as a single unit. While it is related to the main flow, its position is independent of the main flow. Usually this is an image, an illustration, a diagram, a code snippet, or a schema that is referenced in the main text, but that can be moved to another page or to an appendix without affecting the main flow.\\\"><code>&lt;figure&gt;</code></a> block. Also, the <em>HTML Figcaption Element </em>is optional; if not provided, then the parent figure element will have no caption.\"\n    },\n    \"<figure>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;figure&gt;</code> Element</strong> represents self-contained content, frequently with a caption (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption\\\" title=\\\"The HTML &lt;figcaption&gt; Element represents a caption or a legend associated with a figure or an illustration described by the rest of the data of the &lt;figure&gt; element which is its immediate ancestor which means &lt;figcaption&gt; can be the first or last element inside a &lt;figure&gt; block.&#xA0;Also, the HTML Figcaption Element&#xA0;is optional; if not provided, then the parent figure element will have no caption.\\\"><code>&lt;figcaption&gt;</code></a>)<em><code>,</code></em> and is typically referenced as a single unit. While it is related to the main flow, its position is independent of the main flow. Usually this is an image, an illustration, a diagram, a code snippet, or a schema that is referenced in the main text, but that can be moved to another page or to an appendix without affecting the main flow.\"\n    },\n    \"<font>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/font\",\n        \"SUMMARY\": \"The <em>HTML Font Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;font&gt;</span>) defines the font size, color and face for its content.\"\n    },\n    \"<footer>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer\",\n        \"SUMMARY\": \"The <em>HTML Footer Element</em> (<strong>&lt;footer&gt;</strong>) represents a footer for its nearest <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Sections_and_Outlines_of_an_HTML5_document#Defining_Sections_in_HTML5\\\">sectioning content</a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Sections_and_Outlines_of_an_HTML5_document#Sectioning_root\\\" title=\\\"Sections and Outlines of an HTML5 document#Sectioning root\\\">sectioning root</a> element. A footer typically contains information about the author of the section, copyright data or links to related documents.\"\n    },\n    \"<form>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;form&gt;</code> element</strong> represents a document section that contains interactive controls to submit information to a web server.\"\n    },\n    \"<frame>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame\",\n        \"SUMMARY\": \"<code>&lt;frame&gt;</code> is an HTML element which defines a particular area in which another HTML document can be displayed. A frame should be used within a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frameset\\\" title=\\\"&lt;frameset&gt; is an HTML element which is used to contain &lt;frame&gt; elements.\\\"><code>&lt;frameset&gt;</code></a>.\"\n    },\n    \"<frameset>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frameset\",\n        \"SUMMARY\": \"<code>&lt;frameset&gt;</code> is an HTML element which is used to contain <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame\\\" title=\\\"&lt;frame&gt; is an HTML element which defines a particular area in which another HTML document can be displayed. A frame should be used within a &lt;frameset&gt;.\\\"><code>&lt;frame&gt;</code></a> elements.\"\n    },\n    \"<head>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head\",\n        \"SUMMARY\": \"The <em>HTML Head Element</em> (<strong>&lt;head&gt;</strong>) provides general information (metadata) about the document, including its title and links to or definitions of scripts and style sheets\"\n    },\n    \"<header>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;header&gt;</code> Element</strong> represents a group of introductory or navigational aids. It may contain some heading elements but also other elements like a logo, wrapped section's header, a search form, and so on.\"\n    },\n    \"<hgroup>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;hgroup&gt;</code> Element</strong> (<em>HTML Headings Group Element</em>) represents the heading of a section. It defines a single title that participates in <a href=\\\"https://developer.mozilla.org/en-US/docs/Sections_and_Outlines_of_an_HTML5_document\\\" title=\\\"Sections and Outlines of an HTML5 document\\\">the outline of the document</a> as the heading of the implicit or explicit section that it belongs to.\"\n    },\n    \"<hr>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;hr&gt;</code> element</strong> represents a thematic break between paragraph-level elements (for example, a change of scene in a story, or a shift of topic with a section). In previous versions of HTML, it represented a horizontal rule. It may still be displayed as a horizontal rule in visual browsers, but is now defined in semantic terms, rather than presentational terms.\"\n    },\n    \"<html>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html\",\n        \"SUMMARY\": \"The <em>HTML Root Element</em> (<strong><code>&lt;html&gt;</code></strong>) represents the root of an HTML document. All other elements must be descendants of this element.\"\n    },\n    \"<i>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;i&gt;</code> Element</strong> represents a range of text that is set off from the normal text for some reason, for example, technical terms, foreign language phrases, or fictional character thoughts. It is typically displayed in italic type.\"\n    },\n    \"<iframe>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe\",\n        \"SUMMARY\": \"The <em>HTML Inline Frame Element</em> (<code><strong>&lt;iframe&gt;</strong></code>) represents a nested browsing context, effectively embedding another HTML page into the current page. In HTML 4.01, a document may contain a <code>head</code> and a <code>body</code> or a <code>head</code> and a <code>frame-set</code>, but not both a <code>body</code> and a <code>frame-set</code>. However, an <code>&lt;iframe&gt;</code> can be used within a normal document body. Each browsing context has its own session history and active document. The browsing context that contains the embedded content is called the <dfn>parent</dfn> browsing context. The <dfn>top-level</dfn> browsing context (which has no parent) is typically the browser window.\"\n    },\n    \"<image>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/image\",\n        \"SUMMARY\": \"The HTML <code>&lt;image&gt;</code> element was an experimental element designed to display pictures. It never was implemented and the standard <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img\\\" title=\\\"The HTML &lt;img&gt; Element (or HTML Image Element) represents an image of the document.\\\"><code>&lt;img&gt;</code></a> element must be used.\"\n    },\n    \"<img>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img\",\n        \"SUMMARY\": \"The <em>HTML Image Element</em> (<strong>&lt;img&gt;</strong>) represents an image of the document.\"\n    },\n    \"<input>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input\",\n        \"SUMMARY\": \"The HTML <strong><code>&lt;input&gt;</code> element</strong> is used to create interactive controls for web-based forms in order to accept data from the user. The semantics of an <code>&lt;input&gt;</code> varies considerably depending on the value of its <code>type</code> attribute.\"\n    },\n    \"<ins>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;ins&gt;</code> Element</strong> (or <em>HTML Inserted Text</em>) HTML represents a range of text that has been added to a document.\"\n    },\n    \"<isindex>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/isindex\",\n        \"SUMMARY\": \"<code>&lt;isindex&gt;</code> is an HTML element which is used for putting a text field in the document for querying document. <code>&lt;isindex&gt;</code> is intented to use inside of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head\\\" title=\\\"The HTML &lt;head&gt; element represents a collection of metadata about the document, including links to or definitions of scripts and style sheets\\\"><code>&lt;head&gt;</code></a> element by W3C, however browsers provide support wherever it is used in the document.\"\n    },\n    \"<kbd>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd\",\n        \"SUMMARY\": \"The <em>HTML Keyboard Input Element</em> (<strong>&lt;kbd&gt;</strong>) represents user input and produces an inline element displayed in the browser's default monospace font.\"\n    },\n    \"<keygen>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen\",\n        \"SUMMARY\": \"The HTML <code>&lt;keygen&gt;</code> element exists to facilitate generation of key material, and submission of the public key as part of an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms\\\">HTML form</a>. This mechanism is designed for use with Web-based certificate management systems. It is expected that the <code>&lt;keygen&gt;</code> element will be used in an HTML form along with other information needed to construct a certificate request, and that the result of the process will be a signed certificate.\"\n    },\n    \"<label>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label\",\n        \"SUMMARY\": \"The<em> </em><em>HTML Label Element</em> (<code><strong>&lt;label&gt;</strong></code>) represents a caption for an item in a user interface. It can be associated with a control either by placing the control element inside the <code>&lt;label&gt;</code> element, or by using the <code>for</code> attribute. Such a control is called the <em>labeled control</em> of the label element.\"\n    },\n    \"<legend>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend\",\n        \"SUMMARY\": \"The <strong>HTML <span style=\\\"font-family: Courier New;\\\">&lt;legend&gt;</span> Element</strong> (or <em>HTML Legend Field Element</em>) represents a caption for the content of its parent <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset\\\" title=\\\"The HTML &lt;fieldset&gt; element is used to group several controls as well as labels (&lt;label&gt;) within a web form.\\\"><code>&lt;fieldset&gt;</code></a>.\"\n    },\n    \"<li>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li\",\n        \"SUMMARY\": \"The <em>HTML List Item Element</em> (<code>&lt;li&gt;</code>) is used to represent an item in a list. It must be contained in a parent element: an ordered list (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol\\\" title=\\\"The HTML &lt;ol&gt; Element (or HTML Ordered List Element) represents an ordered list of items. Typically, ordered-list items are displayed with a preceding numbering, which can be of any form, like numerals, letters or Romans numerals or even simple bullets. This numbered style is not defined in the HTML description of the page, but in its associated CSS, using the list-style-type property.\\\"><code>&lt;ol&gt;</code></a>), an unordered list (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul\\\" title=\\\"The HTML unordered list element (&lt;ul&gt;) represents an unordered list of items, namely a collection of items that do not have a numerical ordering, and their order in the list is meaningless. Typically, unordered-list items are displayed with a bullet, which can be of several forms, like a dot, a circle or a squared. The bullet style is not defined in the HTML description of the page, but in its associated CSS, using the list-style-type property.\\\"><code>&lt;ul&gt;</code></a>), or a menu (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu\\\" title=\\\"The HTML &lt;menu&gt; element represents a group of commands that a user can perform or activate. This includes both list menus, which might appear across the top of a screen, as well as context menus, such as those that might appear underneath a button after it has been clicked.\\\"><code>&lt;menu&gt;</code></a>). In menus and unordered lists, list items are usually displayed using bullet points. In ordered lists, they are usually displayed with an ascending counter on the left, such as a number or letter.\"\n    },\n    \"<link>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link\",\n        \"SUMMARY\": \"The <em>HTML Link Element</em> (<strong>&lt;link&gt;</strong>) specifies relationships between the current document and an external resource. Possible uses for this element include defining a relational framework for navigation. This Element is most used to link to style sheets.\"\n    },\n    \"<listing>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/listing\",\n        \"SUMMARY\": \"The <em>HTML Listing Element</em> (<code>&lt;listing&gt;</code>) renders text between the start and end tags without interpreting the HTML in between and using a monospaced font. The HTML 2 standard recommended that lines shouldn't be broken when not greater than 132 characters.\"\n    },\n    \"<main>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main\",\n        \"SUMMARY\": \"The <em>HTML Main Element</em> (<strong>&lt;main&gt;</strong>) represents the main content of  the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body\\\" title=\\\"The HTML Body Element (&lt;body&gt;) represents the content of an HTML&#xA0;document. There can be only one &lt;body&gt; element in a document.\\\"><code>&lt;body&gt;</code></a> of a document or application. The main content area consists of content that is directly related to, or expands upon the central topic of a document or the central functionality of an application. This content should be unique to the document, excluding any content that is repeated across a set of documents such as sidebars, navigation links, copyright information, site logos, and search forms (unless, of course, the document's main function is as a search form).\"\n    },\n    \"<map>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;map&gt;</code> element</strong> is used with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area\\\" title=\\\"The HTML &lt;area&gt; element defines a hot-spot region on an image, and optionally associates it with a hypertext link. This element is used only within a &lt;map&gt; element.\\\"><code>&lt;area&gt;</code></a> elements to define an image map (a clickable link area).\"\n    },\n    \"<mark>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark\",\n        \"SUMMARY\": \"The <em>HTML Mark Element</em> (&lt;mark&gt;) represents highlighted text, i.e., a run of text marked for reference purpose, due to its <em>relevance</em> in a particular context. For example it can be used in a page showing search results to highlight every instance of the searched-for word.\"\n    },\n    \"<marquee>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee\",\n        \"SUMMARY\": \"The HTML <code>&lt;marquee&gt;</code> element is used to insert a scrolling area of text.\"\n    },\n    \"<menu>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;menu&gt;</code> element</strong> represents a group of commands that a user can perform or activate. This includes both list menus, which might appear across the top of a screen, as well as context menus, such as those that might appear underneath a button after it has been clicked.\"\n    },\n    \"<menuitem>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menuitem\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;menuitem&gt;</code> element</strong> represents a command that a user is able to invoke through a popup menu. This includes context menus, as well as menus that might be attached to a menu button.\"\n    },\n    \"<meta>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta\",\n        \"SUMMARY\": \"The <em><a class=\\\"glossaryLink\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/HTML\\\" title=\\\"HTML: HTML (hypertext markup language) is a descriptive language that specifies webpage structure.\\\">HTML</a> Meta Element </em>(<strong>&lt;meta&gt;</strong>) represents any metadata information that cannot be represented by one of the other HTML meta-related elements (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base\\\" title=\\\"The HTML Base Element (&lt;base&gt;) specifies the base URL to use for all relative URLs contained within a document. There can be only one &lt;base&gt; element in a document.\\\"><code>&lt;base&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link\\\" title=\\\"The HTML Link Element (&lt;link&gt;) specifies relationships between the current document and an external resource. Possible uses for this element include defining a relational framework for navigation. This Element is most used to link to style sheets.\\\"><code>&lt;link&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script\\\" title=\\\"The HTML &lt;script&gt; element is used to embed or reference an executable script within an HTML or XHTML document.\\\"><code>&lt;script&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style\\\" title=\\\"The HTML Style Element (&lt;style&gt;) contains style information for a document, or part of a document. By default, the style instructions written inside that element are expected to be CSS.\\\"><code>&lt;style&gt;</code></a> or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title\\\" title=\\\"The HTML Title Element (&lt;title&gt;) defines the title of the document, shown in a browser's title bar or on the page's tab. It can only contain text and any contained tags are not interpreted.\\\"><code>&lt;title&gt;</code></a>).\"\n    },\n    \"<meter>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;meter&gt;</code> Element</strong> represents either a scalar value within a known range or a fractional value.\"\n    },\n    \"<multicol>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/multicol\",\n        \"SUMMARY\": \"The HTML <code>&lt;multicol&gt;</code> element was an experimental element designed to allow multi-column layouts. It never got any significant traction and is not implemented in any major browsers.\"\n    },\n    \"<nav>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav\",\n        \"SUMMARY\": \"The <em>HTML Navigation Element</em> (<code>&lt;nav&gt;</code>) represents a section of a page that links to other pages or to parts within the page: a section with navigation links.\"\n    },\n    \"<nobr>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nobr\",\n        \"SUMMARY\": \"The HTML <code>&lt;nobr&gt;</code> element prevents a text from breaking into a new line automatically, so it is displayed on one long line and scrolling might be necessary. This tag is not standard HTML and should not be used.\"\n    },\n    \"<noembed>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noembed\",\n        \"SUMMARY\": \"The <code><strong>&lt;noembed&gt;</strong></code> element is a deprecated and non-standard way to provide alternative, or \\\"fallback\\\", content for browsers that do not support the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed\\\" title=\\\"The HTML &lt;embed&gt; Element represents an integration point for an external application or interactive content (in other words, a plug-in).\\\"><code>&lt;embed&gt;</code></a> element or do not support <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Embedded_content\\\">embedded content</a> an author wishes to use.\"\n    },\n    \"<noframes>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noframes\",\n        \"SUMMARY\": \"<code>&lt;noframes&gt;</code> is an HTML element which is used to supporting browsers which are not able to support <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame\\\" title=\\\"&lt;frame&gt; is an HTML element which defines a particular area in which another HTML document can be displayed. A frame should be used within a &lt;frameset&gt;.\\\"><code>&lt;frame&gt;</code></a> elements or configured to do so.\"\n    },\n    \"<noscript>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;noscript&gt;</code> Element</strong> defines a section of html to be inserted if a script type on the page is unsupported or if scripting is currently turned off in the browser.\"\n    },\n    \"<object>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object\",\n        \"SUMMARY\": \"The <em>HTML Embedded Object Element</em> (<strong>&lt;object&gt;</strong>) represents an external resource, which can be treated as an image, a nested browsing context, or a resource to be handled by a plugin.\"\n    },\n    \"<ol>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;ol&gt;</code> Element</strong> (or <em>HTML Ordered List Element</em>) represents an ordered list of items. Typically, ordered-list items are displayed with a preceding numbering, which can be of any form, like numerals, letters or Romans numerals or even simple bullets. This numbered style is not defined in the HTML description of the page, but in its associated CSS, using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\\\" title=\\\"The list-style-type property specifies the appearance of a list item element. Because it is the only property that&#xA0;defaults to display:list-item, this is usually a &lt;li&gt; element, but can be any element with this display value.\\\"><code>list-style-type</code></a> property.\"\n    },\n    \"<optgroup>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup\",\n        \"SUMMARY\": \"In a Web form, the <strong>HTML <code>&lt;optgroup&gt;</code> element</strong>  creates a grouping of options within a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\\\" title=\\\"The HTML select (&lt;select&gt;) element represents a control that presents a menu of options. The options within the menu are represented by &lt;option&gt; elements, which can be grouped by &lt;optgroup&gt; elements. Options can be pre-selected for the user.\\\"><code>&lt;select&gt;</code></a> element.\"\n    },\n    \"<option>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option\",\n        \"SUMMARY\": \"In a Web form, the <strong>HTML<em> </em><code>&lt;option&gt;</code><em> </em>element</strong> is used to create a control representing an item within a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\\\" title=\\\"The HTML select (&lt;select&gt;) element represents a control that presents a menu of options. The options within the menu are represented by &lt;option&gt; elements, which can be grouped by &lt;optgroup&gt; elements. Options can be pre-selected for the user.\\\"><code>&lt;select&gt;</code></a>, an <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup\\\" title=\\\"In a Web form, the HTML &lt;optgroup&gt; element&#xA0; creates a grouping of options within a &lt;select&gt; element.\\\"><code>&lt;optgroup&gt;</code></a> or a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist\\\" title=\\\"The HTML &lt;datalist&gt; Element contains a set of &lt;option&gt; elements that represent the values available for other controls.\\\"><code>&lt;datalist&gt;</code></a> HTML5 element.\"\n    },\n    \"<output>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;output&gt;</code> element</strong> represents the result of a calculation or user action.\"\n    },\n    \"<p>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;p&gt;</code> element</strong> <em>(</em>or <em>HTML Paragraph Element)</em> represents a paragraph of text.\"\n    },\n    \"<param>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;param&gt;</code> Element</strong> (or <em>HTML Parameter Element)</em> defines parameters for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object\\\" title=\\\"The HTML &lt;object&gt; Element (or HTML Embedded Object Element) represents an external resource, which can be treated as an image, a nested browsing context, or a resource to be handled by a plugin.\\\"><code>&lt;object&gt;</code></a>.\"\n    },\n    \"<picture>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;picture&gt;</code> element</strong> is a container used to specify multiple <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source\\\" title=\\\"The HTML &lt;source&gt; element is used to specify multiple media resources for &lt;picture&gt;, &lt;audio&gt; and &lt;video&gt; elements. It is an empty element. It is commonly used to serve the same media in multiple formats supported by different browsers.\\\"><code>&lt;source&gt;</code></a>s for a specific <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img\\\" title=\\\"The&#xA0;HTML Image Element&#xA0;(&lt;img&gt;) represents an image of the document.\\\"><code>&lt;img&gt;</code></a> contained in it. The browser will choose the most suitable source according to the current layout of the page (the constraints of the box the image will appear in) and the device it will be displayed on (e.g. a normal or hiDPI device).\"\n    },\n    \"<plaintext>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/plaintext\",\n        \"SUMMARY\": \"The <em>HTML Plaintext Element</em> (<code>&lt;plaintext&gt;</code>) renders everything following the start tag as raw text, without interpreting any HTML. There is no closing tag, since everything after it is considered raw text.\"\n    },\n    \"<pre>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre\",\n        \"SUMMARY\": \"The <em>HTML Preformatted Text</em> (<strong>&lt;pre&gt;</strong>) represents preformatted text. Text within this element is typically displayed in a non-proportional font exactly as it is laid out in the file. Whitespaces inside this element are displayed as typed.\"\n    },\n    \"<progress>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress\",\n        \"SUMMARY\": \"The <strong>HTML<em> </em><code>&lt;progress&gt;</code> Element</strong> is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar. Javascript can be used to manipulate the value of progress bar.\"\n    },\n    \"<q>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q\",\n        \"SUMMARY\": \"The <em>HTML Quote Element</em> (<strong>&lt;q&gt;</strong>) indicates that the enclosed text is a short inline quotation. This element is intended for short quotations that don't require paragraph breaks; for long quotations use <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote\\\" title=\\\"The HTML &lt;blockquote&gt; Element (or HTML Block Quotation Element) indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation (see Notes for how to change it). A URL for the source of the quotation may be given using the cite attribute, while a text representation of the source can be given using the &lt;cite&gt; element.\\\"><code>&lt;blockquote&gt;</code></a> element.\"\n    },\n    \"<rp>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;rp&gt;</code> element</strong> is used to provide fall-back parenthesis for browsers non-supporting ruby annotations. Ruby annotations are for showing pronounciation of East Asian characters, like using Japanese furigana or Taiwainese bopomofo characters. The <code>&lt;rp&gt;</code> element is used in the case of lack of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby\\\" title=\\\"The HTML &lt;ruby&gt; Element represents a ruby annotation. Ruby annotations are for showing pronounciation of East Asian characters.\\\"><code>&lt;ruby&gt;</code></a> element support its content has what should be displayed in order to indicate the presence of a ruby annotation, usually parentheses.\"\n    },\n    \"<rt>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;rt&gt;</code> Element</strong> embraces pronunciation of character presented in a ruby annotations, which are for showing pronunciation of East Asian characters and the <code>&lt;rt&gt;</code> element is used inside of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby\\\" title=\\\"The HTML &lt;ruby&gt; Element represents a ruby annotation. Ruby annotations are for showing pronunciation of East Asian characters.\\\"><code>&lt;ruby&gt;</code></a> element.\"\n    },\n    \"<rtc>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;rtc&gt;</code> Element</strong> embraces semantic annotations of characters presented in a ruby of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb\\\" title=\\\"This article hasn't been written yet. Please consider contributing!\\\"><code>&lt;rb&gt;</code></a> elements used inside of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby\\\" title=\\\"The HTML &lt;ruby&gt; Element represents a ruby annotation. Ruby annotations are for showing pronounciation of East Asian characters.\\\"><code>&lt;ruby&gt;</code></a> element. <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb\\\" title=\\\"This article hasn't been written yet. Please consider contributing!\\\"><code>&lt;rb&gt;</code></a> elements can have both pronunciation (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt\\\" title=\\\"The HTML &lt;rt&gt; Element embraces pronunciation of character presented in a ruby annotations, which are for showing pronunciation of East Asian characters and the &lt;rt&gt; element is used inside of &lt;ruby&gt; element.\\\"><code>&lt;rt&gt;</code></a> and semantic (<code>&lt;rtc&gt;</code>) annotations.\"\n    },\n    \"<ruby>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;ruby&gt;</code> Element</strong> represents a ruby annotation. Ruby annotations are for showing pronunciation of East Asian characters.\"\n    },\n    \"<s>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s\",\n        \"SUMMARY\": \"The <em>HTML Strikethrough Element</em> (<code>&lt;s&gt;</code>) renders text with a strikethrough, or a line through it. Use the <code>&lt;s&gt;</code> element to represent things that are no longer relevant or no longer accurate. However, <code>&lt;s&gt;</code> is not appropriate when indicating document edits; for that, use the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del\\\" title=\\\"The HTML &lt;del&gt; element (or HTML Deleted Text Element) represents a range of text that has been deleted from a document. This element is often (but need not be) rendered with strike-through text.\\\"><code>&lt;del&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins\\\" title=\\\"The HTML &lt;ins&gt; Element (or HTML Inserted Text) HTML represents a range of text that has been added to a document.\\\"><code>&lt;ins&gt;</code></a> elements, as appropriate.\"\n    },\n    \"<samp>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp\",\n        \"SUMMARY\": \"The HTML <span style=\\\"font-family: Courier New;\\\">&lt;samp&gt;</span> element is an element intended to identify sample output from a computer program. It is usually displayed in the browser's default monotype font (such as Lucida Console).\"\n    },\n    \"<script>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;script&gt;</code> element</strong> is used to embed or reference an executable script within an <abbr title=\\\"Hypertext Markup Language\\\">HTML</abbr> or <abbr title=\\\"Extensible Hypertext Markup Language\\\">XHTML</abbr> document.\"\n    },\n    \"<section>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section\",\n        \"SUMMARY\": \"The <em>HTML Section Element</em> (<code>&lt;section&gt;</code>) represents a generic section of a document, i.e., a thematic grouping of content, typically with a heading. Each <code>&lt;section&gt;</code> should be identified, typically by including a heading (<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1\\\" title=\\\"Heading elements implement six levels of document headings, &lt;h1&gt; is the most important and &lt;h6&gt; is the least. A heading element briefly describes the topic of the section it introduces. Heading information may be used by user agents, for example, to construct a table of contents for a document automatically.\\\"><code>&lt;h1&gt;</code></a>-<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6\\\" title=\\\"Heading elements implement six levels of document headings, &lt;h1&gt; is the most important and &lt;h6&gt; is the least. A heading element briefly describes the topic of the section it introduces. Heading information may be used by user agents, for example, to construct a table of contents for a document automatically.\\\"><code>&lt;h6&gt;</code></a> element) as a child of the <code>&lt;section&gt;</code> element.\"\n    },\n    \"<select>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select\",\n        \"SUMMARY\": \"The HTML <em>select</em> (<code>&lt;select&gt;</code>) element represents a control that presents a menu of options. The options within the menu are represented by <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option\\\" title=\\\"In a Web form, the HTML &lt;option&gt; element is used to create a control representing an item within a &lt;select&gt;, an &lt;optgroup&gt; or a &lt;datalist&gt; HTML5 element.\\\"><code>&lt;option&gt;</code></a></code> elements, which can be grouped by <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup\\\" title=\\\"In a Web form, the HTML &lt;optgroup&gt; element  creates a grouping of options within a &lt;select&gt; element.\\\"><code>&lt;optgroup&gt;</code></a></code> elements. Options can be pre-selected for the user.\"\n    },\n    \"<shadow>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Shadow\",\n        \"SUMMARY\": \"The <strong><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML\\\">HTML</a> <code>&lt;shadow&gt;</code></strong> element is used as a shadow DOM <a class=\\\"glossaryLink\\\" href=\\\"https://developer.mozilla.org/en-US/docs/Glossary/insertion_point\\\" title=\\\"The definition of that term (insertion point) has not been written yet; please consider contributing it!\\\">insertion point</a>. You might use it if you have created multiple shadow roots under a shadow host. It is not useful in ordinary HTML. It is used with <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/Web_Components\\\">Web Components</a>.\"\n    },\n    \"<small>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small\",\n        \"SUMMARY\": \"The HTML Small Element (<span style=\\\"font-family: Courier New;\\\">&lt;small&gt;</span>) makes the text <em>font size</em> one size smaller (for example, from large to medium, or from small to x-small) down to the browser's minimum font size.  In HTML5, this element is repurposed to represent side-comments and small print, including copyright and legal text, independent of its styled presentation.\"\n    },\n    \"<source>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;source&gt;</code> element</strong> is used to specify multiple media resources for <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture\\\" title=\\\"The HTML &lt;picture&gt; element is a container used to specified multiple {{HTMLElement(&quot;source&quot;)}} for a specific {{HTMLElement(&quot;img&quot;)}} contained in it. The browser will choose the most suitable source according to the current layout (constraints of the box the image will appear in) of the page and the device it will be displayed on (like a normal or hiDPI device).\\\"><code>&lt;picture&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio\\\" title=\\\"The HTML &lt;audio&gt; element is used to embed sound content in documents. It may contain several audio sources, represented using the src attribute or the &lt;source&gt; element; the browser will choose the most suitable one.\\\"><code>&lt;audio&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video\\\" title=\\\"The HTML &lt;video&gt; element is used to embed video content. It may contain several video sources, represented using the src attribute or the &lt;source&gt; element; the browser will choose the most suitable one.\\\"><code>&lt;video&gt;</code></a> elements. It is an empty element. It is commonly used to serve the same media in <a href=\\\"https://developer.mozilla.org/en-US/docs/Media_formats_supported_by_the_audio_and_video_elements\\\" title=\\\"Media formats supported by the audio and video elements\\\">multiple formats supported by different browsers</a>.\"\n    },\n    \"<spacer>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/spacer\",\n        \"SUMMARY\": \"<code>&lt;spacer&gt;</code> is an HTML element which is used for inserting white spaces to web pages. It was created by NetScape for achieving same effect as a single-pixel layout GIF image, which was something web designers used to use to add white spaces to web pages, without actually using a GIF. However <code>&lt;spacer&gt; </code>is not supported by any major browser and same effects can be created with various CSS rules. In Mozilla applications, support for this element was removed in <span title=\\\"(Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)\\\">Gecko 2.0</span>. Therefore usage of <code>&lt;spacer&gt;</code> is unnecessary.\"\n    },\n    \"<span>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;span&gt;</code> element</strong> is a generic inline container for phrasing content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the <code>class</code> or <code>id</code> attributes), or because they share attribute values, such as <code>lang</code>. It should be used only when no other semantic element is appropriate. <code>&lt;span&gt;</code> is very much like a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div\\\" title=\\\"The HTML &lt;div&gt; element (or HTML Document Division Element) is the generic container for flow content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values, such as lang. It should be used only when no other semantic element (such as &lt;article&gt; or &lt;nav&gt;) is appropriate.\\\"><code>&lt;div&gt;</code></a> element, but <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div\\\" title=\\\"The HTML &lt;div&gt; element (or HTML Document Division Element) is the generic container for flow content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values, such as lang. It should be used only when no other semantic element (such as &lt;article&gt; or &lt;nav&gt;) is appropriate.\\\"><code>&lt;div&gt;</code></a> is a <a href=\\\"https://developer.mozilla.org/en-US/docs/HTML/Block-level_elements\\\">block-level element</a> whereas a <code>&lt;span&gt;</code> is an<a href=\\\"https://developer.mozilla.org/en-US/docs/HTML/Inline_elements\\\"> inline element</a>.\"\n    },\n    \"<strike>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strike\",\n        \"SUMMARY\": \"The <em>HTML Strikethrough Element</em> (<code>&lt;strike&gt;</code>) renders text with a strikethrough, or a line through it.\"\n    },\n    \"<strong>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong\",\n        \"SUMMARY\": \"The HTML Strong Element (<code>&lt;strong&gt;</code>) gives text strong importance, and is typically displayed in bold.\"\n    },\n    \"<style>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style\",\n        \"SUMMARY\": \"The <em>HTML Style Element</em> (<strong>&lt;style&gt;</strong>) contains style information for a document, or part of a document. By default, the style instructions written inside that element are expected to be <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS\\\">CSS</a>.\"\n    },\n    \"<sub>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub\",\n        \"SUMMARY\": \"The <em>HTML Subscript Element</em> (<code>&lt;sub&gt;</code>) defines a span of text that should be displayed, for typographic reasons, lower, and often smaller, than the main span of text.\"\n    },\n    \"<summary>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary\",\n        \"SUMMARY\": \"The HTML <em>summary </em>element (<code>&lt;summary&gt;</code>) is used as a summary, caption, or legend for the content of a <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details\\\" title=\\\"The HTML &lt;details&gt; Element is used as a disclosure widget from which the user can retrieve additional information.\\\"><code>&lt;details&gt;</code></a> element.\"\n    },\n    \"<sup>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup\",\n        \"SUMMARY\": \"The <em>HTML Superscript Element</em> (<code>&lt;sup&gt;</code>) defines a span of text that should be displayed, for typographic reasons, higher, and often smaller, than the main span of text.\"\n    },\n    \"<table>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table\",\n        \"SUMMARY\": \"The <em>HTML Table Element </em>(<code>&lt;table&gt;</code>) represents data in two dimensions or more.\"\n    },\n    \"<tbody>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody\",\n        \"SUMMARY\": \"The HTML Table Body Element (<tbody>) defines one or more <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr\\\" title=\\\"The HTML Table Row Element (&lt;tr&gt;) defines a row of cells in a table. Those can be a mix of &lt;td&gt; and &lt;th&gt; elements.\\\"><code>&lt;tr&gt;</code></a> element data-rows to be the body of its parent <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table\\\" title=\\\"The HTML Table Element (&lt;table&gt;) represents data in two dimensions or more.\\\"><code>&lt;table&gt;</code></a> element (as long as no &lt;tr&gt; elements are immediate children of that table element.)  In conjunction with a preceding <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead\\\" title=\\\"The HTML Table Head Element (&lt;thead&gt;) defines a set of rows defining the head of the columns of the table.\\\"><code>&lt;thead&gt;</code></a> and/or <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot\\\" title=\\\"The HTML Table Foot Element (&lt;tfoot&gt;) defines a set of rows summarizing the columns of the table.\\\"><code>&lt;tfoot&gt;</code></a> element, &lt;tbody&gt; provides additional semantic information for devices such as printers and displays. Of the parent table's child elements, &lt;tbody&gt; represents the content which, when longer than a page, will most likely differ for each page printed; while the content of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead\\\" title=\\\"The HTML Table Head Element (&lt;thead&gt;) defines a set of rows defining the head of the columns of the table.\\\"><code>&lt;thead&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot\\\" title=\\\"The HTML Table Foot Element (&lt;tfoot&gt;) defines a set of rows summarizing the columns of the table.\\\"><code>&lt;tfoot&gt;</code></a> will be the same or similar for each page printed. For displays, &lt;tbody&gt; will enable separate scrolling of the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead\\\" title=\\\"The HTML Table Head Element (&lt;thead&gt;) defines a set of rows defining the head of the columns of the table.\\\"><code>&lt;thead&gt;</code></a>, <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot\\\" title=\\\"The HTML Table Foot Element (&lt;tfoot&gt;) defines a set of rows summarizing the columns of the table.\\\"><code>&lt;tfoot&gt;</code></a>, and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption\\\" title=\\\"The HTML &lt;caption&gt; Element (or HTML Table Caption Element) represents the title of a table. Though it is always the first descendant of a &lt;table&gt;, its styling, using CSS, may place it elsewhere, relative to the table.\\\"><code>&lt;caption&gt;</code></a> elements of the same parent <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table\\\" title=\\\"The HTML Table Element (&lt;table&gt;) represents data in two dimensions or more.\\\"><code>&lt;table&gt;</code></a> element.  Note that unlike the &lt;thead&gt;, &lt;tfoot&gt;, and &lt;caption&gt; elements however, multiple<strong> </strong><span style=\\\"font-family: consolas,monaco,andale mono,monospace;\\\">&lt;tbody&gt; </span>elements are permitted (if consecutive), allowing the data-rows in long tables to be divided into different sections, each separately formatted as needed.\"\n    },\n    \"<td>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td\",\n        \"SUMMARY\": \"The <em>Table cell</em> <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML\\\">HTML</a> element (<strong><code>&lt;td&gt;</code></strong>) defines a cell of a table that contains data. It participates in the <em>table model</em>.\"\n    },\n    \"<template>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template\",\n        \"SUMMARY\": \"The <strong><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML\\\">HTML</a> template element <code>&lt;template&gt;</code></strong> is a mechanism for holding client-side content that is not to be rendered when a page is loaded but may subsequently be instantiated during runtime using JavaScript. \"\n    },\n    \"<textarea>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;textarea&gt; </code>element</strong> represents a multi-line plain-text editing control.\"\n    },\n    \"<tfoot>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot\",\n        \"SUMMARY\": \"The <em>HTML Table Foot Element</em> (<code>&lt;tfoot&gt;</code>) defines a set of rows summarizing the columns of the table.\"\n    },\n    \"<th>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th\",\n        \"SUMMARY\": \"The <em>HTML Table Header Cell Element</em> (<code>&lt;th&gt;</code>) defines a cell that is a header for a group of cells of a table. The group of cells that the header refers to is defined by the <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th#attr-scope\\\">scope</a></code> and <code><a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th#attr-headers\\\">headers</a></code> attribute.\"\n    },\n    \"<thead>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead\",\n        \"SUMMARY\": \"The <em>HTML Table Head Element</em> (<code>&lt;thead&gt;</code>) defines a set of rows defining the head of the columns of the table.\"\n    },\n    \"<time>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;time&gt;</code> element</strong> represents either a time on a 24-hour clock or a precise date in the <a class=\\\"external\\\" href=\\\"http://en.wikipedia.org/wiki/Gregorian_calendar\\\" title=\\\"http://en.wikipedia.org/wiki/Gregorian_calendar\\\">Gregorian calendar</a> (with optional time and timezone information).\"\n    },\n    \"<title>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title\",\n        \"SUMMARY\": \"The <em>HTML Title Element</em> (<strong>&lt;title&gt;</strong>) defines the title of the document, shown in a browser's title bar or on the page's tab. It can only contain text and any contained tags are not interpreted.\"\n    },\n    \"<tr>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr\",\n        \"SUMMARY\": \"The <em>HTML Table Row Element</em> (<code>&lt;tr&gt;</code>) defines a row of cells in a table. Those can be a mix of <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td\\\" title=\\\"The Table cell HTML element (&lt;td&gt;) defines a cell of a table that contains data. It participates in the table model.\\\"><code>&lt;td&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th\\\" title=\\\"The HTML Table Header Cell Element (&lt;th&gt;) defines a cell that is a header for a group of cells of a table. The group of cells that the header refers to is defined by the scope and headers attribute.\\\"><code>&lt;th&gt;</code></a> elements.\"\n    },\n    \"<track>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;track&gt;</code> element</strong> is used as a child of the media elements—<a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio\\\" title=\\\"The HTML &lt;audio&gt; element is used to embed sound content in documents. It may contain several audio sources, represented using the src attribute or the &lt;source&gt; element; the browser will choose the most suitable one.\\\"><code>&lt;audio&gt;</code></a> and <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video\\\" title=\\\"The HTML &lt;video&gt; element is used to embed video content. It may contain several video sources, represented using the src attribute or the &lt;source&gt; element; the browser will choose the most suitable one.\\\"><code>&lt;video&gt;</code></a>. It lets you specify timed text tracks (or time-based data), for example to automatically handle subtitles. The tracks are formatted in <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Video_Text_Tracks_Format\\\">WebVTT format</a> (<code>.vtt</code> files) — Web Video Text Tracks.\"\n    },\n    \"<tt>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tt\",\n        \"SUMMARY\": \"The HTML Teletype Text Element (<code>&lt;tt&gt;</code>) produces an inline element displayed in the browser's default monotype font. This element was intended to style text as it would display on a fixed width display, such as a teletype. It probably is more common to display fixed width type using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code\\\" title=\\\"The HTML &lt;code&gt; Element represents a fragment of computer code. By default, it is displayed in the browser's default monospace font.\\\"><code>&lt;code&gt;</code></a> element.\"\n    },\n    \"<u>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u\",\n        \"SUMMARY\": \"The <em>HTML Underline Element</em> (<code>&lt;u&gt;</code>) renders text with an underline, a line under the baseline of its content.\"\n    },\n    \"<ul>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul\",\n        \"SUMMARY\": \"The HTML <em>unordered list</em> element (<code>&lt;ul&gt;</code>) represents an unordered list of items, namely a collection of items that do not have a numerical ordering, and their order in the list is meaningless. Typically, unordered-list items are displayed with a bullet, which can be of several forms, like a dot, a circle or a squared. The bullet style is not defined in the HTML description of the page, but in its associated CSS, using the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type\\\" title=\\\"The list-style-type property specifies the appearance of a list item element. Because it is the only property that&#xA0;defaults to display:list-item, this is usually a &lt;li&gt; element, but can be any element with this display value.\\\"><code>list-style-type</code></a> property.\"\n    },\n    \"<var>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var\",\n        \"SUMMARY\": \"The HTML Variable Element (<code>&lt;var&gt;</code>) represents a variable in a mathematical expression or a programming context.\"\n    },\n    \"<video>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video\",\n        \"SUMMARY\": \"The <strong>HTML <code>&lt;video&gt;</code> element</strong> is used to embed video content. It may contain several video sources, represented using the <code>src</code> attribute or the <a href=\\\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source\\\" title=\\\"The HTML &lt;source&gt; element is used to specify multiple media resources for &lt;picture&gt;, &lt;audio&gt; and &lt;video&gt; elements. It is an empty element. It is commonly used to serve the same media in multiple formats supported by different browsers.\\\"><code>&lt;source&gt;</code></a> element; the browser will choose the most suitable one.\"\n    },\n    \"<wbr>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr\",\n        \"SUMMARY\": \"The <em>Word Break Opportunit</em><em>y</em> (<code>&lt;wbr&gt;</code>) HTML element represents a position within text where the browser may optionally break a line, though its line-breaking rules would not otherwise create a break at that location.\"\n    },\n    \"<xmp>\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/xmp\",\n        \"SUMMARY\": \"The <em>HTML Example Element</em> (<code>&lt;xmp&gt;</code>) renders text between the start and end tags without interpreting the HTML in between and using a monospaced font. The HTML2 specification recommended that it should be rendered wide enough to allow 80 characters per line.\"\n    },\n    \"Heading elements\": {\n        \"URL\": \"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements\",\n        \"SUMMARY\": \"<strong>Heading</strong> elements implement six levels of document headings, <code>&lt;h1&gt;</code> is the most important and <code>&lt;h6&gt;</code> is the least. A heading element briefly describes the topic of the section it introduces. Heading information may be used by user agents, for example, to construct a table of contents for a document automatically.\"\n    }\n}"
  },
  {
    "path": "src/extensions/default/MDNDocs/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Core modules\n    var _                    = brackets.getModule(\"thirdparty/lodash\"),\n        EditorManager        = brackets.getModule(\"editor/EditorManager\"),\n        FileSystem           = brackets.getModule(\"filesystem/FileSystem\"),\n        FileUtils            = brackets.getModule(\"file/FileUtils\"),\n        CSSUtils             = brackets.getModule(\"language/CSSUtils\"),\n        HTMLUtils            = brackets.getModule(\"language/HTMLUtils\"),\n        ExtensionUtils       = brackets.getModule(\"utils/ExtensionUtils\"),\n        HealthLogger         = brackets.getModule(\"utils/HealthLogger\");\n\n    // Extension modules\n    var InlineDocsViewer = require(\"InlineDocsViewer\");\n\n\n    /*\n     * Caches docs promises\n     */\n    var promiseCache = {};\n\n    /**\n     * Lazily loads JSON docs files. Returns a Promise the is resolved with the parsed Object, or\n     * rejected if the file is missing/corrupt.\n     * @param {string} fileName JSON file to load\n     * @return {!$.Promise}\n     */\n    function getDocs(fileName) {\n        if (!promiseCache[fileName]) {\n            var result = new $.Deferred();\n\n            var path = ExtensionUtils.getModulePath(module, fileName),\n                file = FileSystem.getFileForPath(path);\n\n            FileUtils.readAsText(file)\n                .done(function (text) {\n                    var jsonData;\n                    try {\n                        jsonData = JSON.parse(text);\n                    } catch (ex) {\n                        console.error(\"Malformed documentation database: \", ex);\n                        result.reject();\n                    }\n                    result.resolve(jsonData);  // ignored if we already reject()ed above\n                })\n                .fail(function (err) {\n                    console.error(\"Unable to load documentation database: \", err);\n                    result.reject();\n                });\n\n            promiseCache[fileName] = result.promise();\n        }\n\n        return promiseCache[fileName];\n    }\n\n\n    /**\n     * Inline docs provider.\n     *\n     * @param {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {?$.Promise} resolved with an InlineWidget; null if we're not going to provide anything\n     */\n    function inlineProvider(hostEditor, pos) {\n        var jsonFile, propInfo,\n            propQueue = [], // priority queue of propNames to try\n            langId = hostEditor.getLanguageForSelection().getId(),\n            supportedLangs = {\n                \"css\": true,\n                \"scss\": true,\n                \"less\": true,\n                \"html\": true\n            },\n            isQuickDocAvailable = langId ? supportedLangs[langId] : -1; // fail if langId is falsy\n\n        // Only provide docs when cursor is in supported language\n        if (!isQuickDocAvailable) {\n            return null;\n        }\n\n        // Send analytics data for Quick Doc open\n        HealthLogger.sendAnalyticsData(\n            \"cssQuickDoc\",\n            \"usage\",\n            \"quickDoc\",\n            \"open\"\n        );\n\n        // Only provide docs if the selection is within a single line\n        var sel = hostEditor.getSelection();\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n\n        if (langId === \"html\") { // HTML\n            jsonFile = \"html.json\";\n            propInfo = HTMLUtils.getTagInfo(hostEditor, sel.start);\n            if (propInfo.position.tokenType === HTMLUtils.ATTR_NAME && propInfo.attr && propInfo.attr.name) {\n                // we're on an HTML attribute (and not on its value)\n                propQueue.push(propInfo.attr.name.toLowerCase());\n            }\n            if (propInfo.tagName) { // we're somehow on an HTML tag (no matter where exactly)\n                propInfo = propInfo.tagName.toLowerCase();\n                propQueue.push(\"<\" + propInfo + \">\");\n            }\n        } else { // CSS-like language\n            jsonFile = \"css.json\";\n            propInfo = CSSUtils.getInfoAtPos(hostEditor, sel.start);\n            if (propInfo.name) {\n                propQueue.push(propInfo.name);\n                // remove possible vendor prefixes\n                propQueue.push(propInfo.name.replace(/^-(?:webkit|moz|ms|o)-/, \"\"));\n            }\n        }\n\n        // Are we on a supported property? (no matter if info is available for the property)\n        if (propQueue.length) {\n            var result = new $.Deferred();\n\n            // Load JSON file if not done yet\n            getDocs(jsonFile)\n                .done(function (docs) {\n                    // Construct inline widget (if we have docs for this property)\n\n                    var displayName, propDetails,\n                        propName = _.find(propQueue, function (propName) { // find the first property where info is available\n                            return docs.hasOwnProperty(propName);\n                        });\n\n                    if (propName) {\n                        propDetails = docs[propName];\n                        displayName = propName.substr(propName.lastIndexOf(\"/\") + 1);\n                    }\n                    if (propDetails) {\n                        var inlineWidget = new InlineDocsViewer(displayName, propDetails);\n                        inlineWidget.load(hostEditor);\n                        result.resolve(inlineWidget);\n                    } else {\n                        result.reject();\n                    }\n                })\n                .fail(function () {\n                    result.reject();\n                });\n\n            return result.promise();\n\n        } else {\n            return null;\n        }\n    }\n\n    // Register as inline docs provider\n    EditorManager.registerInlineDocsProvider(inlineProvider);\n\n    exports._getDocs         = getDocs;\n    exports._inlineProvider  = inlineProvider;\n});\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/unittest-files/test1.css",
    "content": "{{0}}div {\n    {{1}}border: 1px solid black{{2}};\n    {{3}}does-not-exist: 0;\n    /* {{5}}color: #000 */\n    background: border{{4}};\n    {{6}}-webkit-animation: none;\n    {{7}}-border-width: 2px;\n}\n"
  },
  {
    "path": "src/extensions/default/MDNDocs/unittest-files/test1.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <style>\n            body {\n                {{0}}border: 1px solid black;\n            }\n        </style>\n    </head>\n    <body style=\"background-color{{1}}: #000\">\n        <{{2}}nonexistent></nonexistent>\n        <div>{{3}}some text</div>\n        <!-- <{{4}}div></div> -->\n        <div {{5}}class=\"{{6}}muted\" {{7}}nonexistent=\"false\"></div>\n        <nonexistent {{8}}nonexistent=\"false\"></nonexistent>\n    </body>\n</html>"
  },
  {
    "path": "src/extensions/default/MDNDocs/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, waitsFor, runs, waitsForDone, waitsForFail */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\");\n\n    var main                = require(\"main\"),\n        InlineDocsViewer    = require(\"InlineDocsViewer\"),\n        testCSS             = require(\"text!unittest-files/test1.css\"),\n        testHTML            = require(\"text!unittest-files/test1.html\");\n\n    describe(\"MDNDocs\", function () {\n\n        var testCSSInfo     = SpecRunnerUtils.parseOffsetsFromText(testCSS),\n            testHTMLInfo    = SpecRunnerUtils.parseOffsetsFromText(testHTML),\n            editor,\n            doc,\n            pos;\n\n        function queryInlineAtPos(info, offset, expectInline, expectedProperty) {\n            var widget = null,\n                promise;\n\n            runs(function () {\n                // set cursor position in editor\n                pos = info.offsets[offset];\n                editor.setSelection(pos);\n\n                // fetch inline editor\n                promise = main._inlineProvider(editor, pos);\n\n                if (expectInline) {\n                    expect(promise).toBeTruthy();\n                }\n\n                if (promise) {\n                    promise.done(function (result) {\n                        widget = result;\n                    });\n\n                    if (expectInline) {\n                        // expecting a valid CSS property\n                        waitsForDone(promise, \"MDNDocs _inlineProvider\", 1000);\n                    } else {\n                        // expecting an invalid css property\n                        waitsForFail(promise, \"MDNDocs _inlineProvider\", 1000);\n                    }\n                }\n            });\n\n            runs(function () {\n                if (promise) {\n                    if (expectInline) {\n                        expect(widget).toBeTruthy();\n                        expect(widget.$htmlContent.find(\".css-prop-summary h1\").text()).toBe(expectedProperty);\n                    } else {\n                        expect(widget).toBeNull();\n                    }\n                }\n            });\n        }\n\n        describe(\"InlineDocsProvider database\", function () {\n\n            it(\"should retrieve the CSS docs database\", function () {\n                var json;\n\n                runs(function () {\n                    main._getDocs(\"css.json\").done(function (result) {\n                        json = result;\n                    });\n                });\n\n                waitsFor(function () { return json !== undefined; }, \"read css.json database\", 5000);\n\n                runs(function () {\n                    expect(Object.keys(json).length).toBeGreaterThan(0);\n                });\n            });\n            \n            it(\"should retrieve the HTML docs database\", function () {\n                var json;\n                \n                runs(function () {\n                    main._getDocs(\"html.json\").done(function (result) {\n                        json = result;\n                    });\n                });\n                \n                waitsFor(function () { return json !== undefined; }, \"read html.json database\", 5000);\n                \n                runs(function () {\n                    expect(Object.keys(json).length).toBeGreaterThan(0);\n                });\n            });\n\n        });\n\n        describe(\"InlineDocsProvider parsing in CSS\", function () {\n\n            beforeEach(function () {\n                var mock = SpecRunnerUtils.createMockEditor(testCSSInfo.text, \"css\");\n                editor = mock.editor;\n                doc = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(doc);\n            });\n\n            it(\"should open docs when the selection is on a CSS property\", function () {\n                /* css property */\n                queryInlineAtPos(testCSSInfo, 1, true, \"border\");\n\n                /* css value */\n                queryInlineAtPos(testCSSInfo, 2, true, \"border\");\n            });\n\n            it(\"should not open docs when the selection is not on a CSS property\", function () {\n                /* css selector */\n                queryInlineAtPos(testCSSInfo, 0, false);\n\n                /* css comment */\n                queryInlineAtPos(testCSSInfo, 5, false);\n            });\n\n            it(\"should not open docs for an invalid CSS property\", function () {\n                /* css invalid property */\n                queryInlineAtPos(testCSSInfo, 3, false);\n            });\n\n            it(\"should open docs for a vendor-prefixed CSS property\", function () {\n                /* css -webkit- prefixed property */\n                queryInlineAtPos(testCSSInfo, 6, true, \"animation\");\n            });\n\n            it(\"should not open docs for an invalid CSS property (looking like a vendor-prefixed one)\", function () {\n                /* css property invalidly prefixed */\n                queryInlineAtPos(testCSSInfo, 7, false);\n            });\n\n        });\n\n        describe(\"InlineDocsProvider parsing in HTML\", function () {\n\n            beforeEach(function () {\n                var mock = SpecRunnerUtils.createMockEditor(testHTMLInfo.text, \"html\");\n                editor = mock.editor;\n                doc = mock.doc;\n            });\n\n            afterEach(function () {\n                SpecRunnerUtils.destroyMockEditor(doc);\n            });\n\n            it(\"should open docs for CSS in a <style> block\", function () {\n                queryInlineAtPos(testHTMLInfo, 0, true, \"border\");\n            });\n\n            it(\"should open docs when the selection is on an HTML tag\", function () {\n                queryInlineAtPos(testHTMLInfo, 1, true, \"<body>\");\n            });\n            \n            it(\"should not open docs when the selection is on an invalid HTML tag\", function () {\n                queryInlineAtPos(testHTMLInfo, 2, false);\n            });\n            \n            it(\"should not open docs when the selection is not an HTML tag\", function () {\n                /* Text */\n                queryInlineAtPos(testHTMLInfo, 3, false);\n                \n                /* Commented tag */\n                queryInlineAtPos(testHTMLInfo, 4, false);\n            });\n            \n            it(\"should open docs when the selection is on an HTML attribute\", function () {\n                queryInlineAtPos(testHTMLInfo, 5, true, \"<div>\");\n            });\n            \n            it(\"should open docs for tag (fallback) when the selection is on an HTML attribute's value\", function () {\n                queryInlineAtPos(testHTMLInfo, 6, true, \"<div>\");\n            });\n            \n            it(\"should open docs for tag (fallback) when the selection is on an invalid HTML attribute\", function () {\n                queryInlineAtPos(testHTMLInfo, 7, true, \"<div>\");\n            });\n            \n            it(\"should not open docs when the selection is on an invalid HTML attribute on an invalid HTML tag\", function () {\n                queryInlineAtPos(testHTMLInfo, 8, false);\n            });\n\n        });\n\n        describe(\"InlineDocsViewer\", function () {\n\n            function createCssPropDetails(summary, url, valuesArr) {\n                var values = [],\n                    details = {\n                        SUMMARY: summary,\n                        URL: url,\n                        VALUES: values\n                    };\n\n                valuesArr.forEach(function (value) {\n                    values.push({\n                        title: value[0] || undefined,\n                        description: value[1] || undefined\n                    });\n                });\n\n                return details;\n            }\n\n            it(\"should add titles to all links\", function () {\n                var prop    = \"my-css-prop\",\n                    url     = \"http://dev.brackets.io/wiki/css/properties/my-css-prop\",\n                    details = createCssPropDetails(\n                        prop,\n                        url,\n                        [[\"normal\", \"See <a href='http://dev.brackets.io/wiki/css/properties/foo-css-prop'>foo-css-prop</a>\"]]\n                    ),\n                    viewer = new InlineDocsViewer(prop, details),\n                    $a,\n                    $links = viewer.$htmlContent.find(\"a:not(.close)\");\n\n                // 1 link in the description, 1 \"more info\" link in template\n                expect($links.length).toBe(2);\n\n                $links.each(function (i, anchor) {\n                    $a = $(anchor);\n\n                    // all links should have a title\n                    expect($a.attr(\"title\")).toBe($a.attr(\"href\"));\n                });\n            });\n\n        });\n\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/NavigationAndHistory/NavigationProvider.js",
    "content": "/*\n * Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n \n/**\n * Manages Editor navigation history to aid back/fwd movement between the edit positions \n * in the active project context. The navigation history is purely in-memory and not \n * persisted to file system when a project is being closed.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Strings                 = brackets.getModule(\"strings\"),\n        MainViewManager         = brackets.getModule(\"view/MainViewManager\"),\n        Document                = brackets.getModule(\"document/Document\"),\n        DocumentManager         = brackets.getModule(\"document/DocumentManager\"),\n        DocumentCommandHandlers = brackets.getModule(\"document/DocumentCommandHandlers\"),\n        EditorManager           = brackets.getModule(\"editor/EditorManager\"),\n        Editor                  = brackets.getModule(\"editor/Editor\"),\n        ProjectManager          = brackets.getModule(\"project/ProjectManager\"),\n        CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        Commands                = brackets.getModule(\"command/Commands\"),\n        Menus                   = brackets.getModule(\"command/Menus\"),\n        KeyBindingManager       = brackets.getModule(\"command/KeyBindingManager\"),\n        FileSystem              = brackets.getModule(\"filesystem/FileSystem\");\n    \n    var KeyboardPrefs = JSON.parse(require(\"text!keyboard.json\"));\n    \n    // Command constants for navigation history\n    var NAVIGATION_JUMP_BACK      = \"navigation.jump.back\",\n        NAVIGATION_JUMP_FWD       = \"navigation.jump.fwd\";\n    \n    // The latency time to capture an explicit cursor movement as a navigation frame\n    var NAV_FRAME_CAPTURE_LATENCY = 2000,\n        MAX_NAV_FRAMES_COUNT = 30;\n    \n   /**\n    * Contains list of most recently known cursor positions.\n    * @private\n    * @type {Array.<Object>}\n    */\n    var jumpBackwardStack = [];\n    \n   /**\n    * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command.\n    * @private\n    * @type {Array.<Object>}\n    */\n    var jumpForwardStack = [],\n        activePosNotSynced = false,\n        captureTimer = null,\n        currentEditPos = null,\n        jumpInProgress = false,\n        commandJumpBack,\n        commandJumpFwd;\n        \n   /**\n    * Function to check if there are any navigatable frame backward.\n    * @private\n    */\n    function _hasNavBackFrames() {\n        return (jumpForwardStack.length > 0 && jumpBackwardStack.length > 0)\n            || (!jumpForwardStack.length && jumpBackwardStack.length > 1);\n    }\n     \n   /**\n    * Function to enable/disable navigation command based on cursor positions availability.\n    * @private\n    */\n    function _validateNavigationCmds() {\n        commandJumpBack.setEnabled(_hasNavBackFrames());\n        commandJumpFwd.setEnabled(jumpForwardStack.length > 0);\n    }\n    \n   /**\n    * Function to check existence of a file entry, validity of markers\n    * @private\n    */\n    function _validateFrame(entry) {\n        var deferred = new $.Deferred(),\n            fileEntry = FileSystem.getFileForPath(entry.filePath);\n\n        if (entry.inMem) {\n            var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.filePath);\n            // Remove entry if InMemoryFile is not found in Working set\n            if (indexInWS === -1) {\n                deferred.reject();\n            } else {\n                deferred.resolve();\n            }\n        } else {\n            fileEntry.exists(function (err, exists) {\n                if (!err && exists) {\n                    // Additional check to handle external modification and mutation of the doc text affecting markers\n                    if (fileEntry._hash !== entry._hash) {\n                        deferred.reject();\n                    } else if (!entry._validateMarkers()) {\n                        deferred.reject();\n                    } else {\n                        deferred.resolve();\n                    }\n                } else {\n                    deferred.reject();\n                }\n            });\n        }\n\n        return deferred.promise();\n    }\n        \n   /**\n    * Prototype to capture a navigation frame and it's various data/functional attributues\n    */\n    function NavigationFrame(editor, selectionObj) {\n        this.cm = editor._codeMirror;\n        this.filePath = editor.document.file._path;\n        this.inMem = editor.document.file.constructor.name === \"InMemoryFile\";\n        this.paneId = editor._paneId;\n        this._hash = editor.document.file._hash;\n        this.uId = (new Date()).getTime();\n        this.selections = [];\n        this.bookMarkIds = [];\n        this._createMarkers(selectionObj.ranges);\n    }\n    \n   /**\n    * Lifecycle event handler of the editor for which this frame is captured\n    */\n    NavigationFrame.prototype._handleEditorDestroy = function (editor) {\n        this._backupSelectionRanges();\n        this._clearMarkers();\n        this.cm = null;\n        this.bookMarkIds = null;\n    };\n    \n    /**\n    * Function to re-create CM TextMarkers for previously backed up ranges\n    * This logic is required to ensure that the captured navigation positions \n    * stay valid and contextual even when the actual document text mutates.\n    * The mutations which are handled here :\n    * -> Addition/Deletion of lines before the captured position\n    * -> Addition/Updation of characters in the captured selection\n    */\n    NavigationFrame.prototype._reinstateMarkers = function (editor) {\n        this.cm = editor._codeMirror;\n        this.paneId = editor._paneId;\n        this._createMarkers(this.selections);\n    };\n    \n    \n    /**\n    * Function to validate an existing frame against a file '_hash' to detect\n    * external change so that the frame can be discarded\n    */\n    NavigationFrame.prototype._validateFileHash = function (file) {\n        return this.filePath === file._path ? this._hash === file._hash : true;\n    };\n    \n   /**\n    * Function to create CM TextMarkers for the navigated positions/selections.\n    * This logic is required to ensure that the captured navigation positions \n    * stay valid and contextual even when the actual document text mutates.\n    * The mutations which are handled here :\n    * -> Addition/Deletion of lines before the captured position\n    * -> Addition/Updation of characters in the captured selection\n    */\n    NavigationFrame.prototype._createMarkers = function (ranges) {\n        var range,\n            rangeStart,\n            rangeEnd,\n            index,\n            bookMark;\n\n        this.bookMarkIds = [];\n        for (index in ranges) {\n            range = ranges[index];\n            rangeStart = range.anchor || range.start;\n            rangeEnd = range.head || range.end;\n            // 'markText' has to used for a non-zero length position, if current selection is \n            // of zero length use bookmark instead.\n            if (rangeStart.line === rangeEnd.line && rangeStart.ch === rangeEnd.ch) {\n                bookMark = this.cm.setBookmark(rangeStart, rangeEnd);\n                this.bookMarkIds.push(bookMark.id);\n            } else {\n                this.cm.markText(rangeStart, rangeEnd, {className: (this.uId)});\n            }\n        }\n    };\n    \n   /**\n    * Function to actually convert the CM markers to CM positions which can be used to \n    * set selections or cursor positions in Editor.\n    */\n    NavigationFrame.prototype._backupSelectionRanges = function () {\n        if (!this.cm) {\n            return;\n        }\n        \n        var marker,\n            selection,\n            index;\n        \n        // Reset selections first.\n        this.selections = [];\n        var self = this;\n\n        // Collate only the markers we used to mark selections/cursors\n        var markers = this.cm.getAllMarks().filter(function (entry) {\n            if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) {\n                return entry;\n            }\n        });\n\n        // Iterate over CM textmarkers and collate the updated(if?) positions\n        for (index in markers) {\n            marker = markers[index];\n            selection = marker.find();\n            if (marker.type === \"bookmark\") {\n                this.selections.push({start: selection, end: selection});\n            } else {\n                this.selections.push({start: selection.from, end: selection.to});\n            }\n        }\n    };\n    \n   /**\n    * Function to clean up the markers in cm\n    */\n    NavigationFrame.prototype._clearMarkers = function () {\n        if (!this.cm) {\n            return;\n        }\n        var self = this;\n        \n        // clear only the markers we used to mark selections/cursors\n        this.cm.getAllMarks().filter(function (entry) {\n            if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) {\n                entry.clear();\n            }\n        });\n    };\n    \n    /**\n    * Function to check if we have valid markers in cm for this frame\n    */\n    NavigationFrame.prototype._validateMarkers = function () {\n        this._backupSelectionRanges();\n        return this.selections.length;\n    };\n\n   /**\n    * Function to actually navigate to the position(file,selections) captured in this frame\n    */\n    NavigationFrame.prototype.goTo = function () {\n        var self = this;\n        this._backupSelectionRanges();\n        jumpInProgress = true;\n        \n        // To ensure we don't reopen the same doc in the last known pane\n        // rather bring it to the same pane where user has opened it\n        var thisDoc = DocumentManager.getOpenDocumentForPath(this.filePath);\n        if (thisDoc && thisDoc._masterEditor) {\n            this.paneId = thisDoc._masterEditor._paneId;\n        }\n        \n        CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.filePath, paneId: this.paneId}).done(function () {\n            EditorManager.getCurrentFullEditor().setSelections(self.selections, true);\n            _validateNavigationCmds();\n        }).always(function () {\n            jumpInProgress = false;\n        });\n    };\n    \n    \n   /**\n    * Function to capture a non-zero set of selections as a navigation frame.\n    * The assumptions behind capturing a frame as a navigation frame are :\n    *\n    * -> If it's set by user explicitly (using mouse click or jump to definition)\n    * -> By clicking on search results\n    * -> Change of cursor by keyboard navigation keys or actual edits are not captured.\n    *\n    * @private\n    */\n    function _recordJumpDef(event, selectionObj) {\n        // Don't capture frames if we are navigating or document text is being refreshed(fileSync in progress)\n        if (jumpInProgress || (event.target && event.target.document._refreshInProgress)) {\n            return;\n        }\n        // Reset forward navigation stack if we are capturing a new event\n        jumpForwardStack = [];\n        if (captureTimer) {\n            window.clearTimeout(captureTimer);\n            captureTimer = null;\n        }\n        \n        // Ensure cursor activity has not happened because of arrow keys or edit\n        if (selectionObj.origin !== \"+move\" && (!window.event || window.event.type !== \"input\")) {\n            captureTimer = window.setTimeout(function () {\n                // Check if we have reached MAX_NAV_FRAMES_COUNT\n                // If yes, control overflow\n                if (jumpBackwardStack.length === MAX_NAV_FRAMES_COUNT) {\n                    var navFrame = jumpBackwardStack.shift();\n                    navFrame._clearMarkers();\n                }\n\n                currentEditPos = new NavigationFrame(event.target, selectionObj);\n                jumpBackwardStack.push(currentEditPos);\n                _validateNavigationCmds();\n                activePosNotSynced = false;\n            }, NAV_FRAME_CAPTURE_LATENCY);\n        } else {\n            activePosNotSynced = true;\n        }\n    }\n    \n   /**\n    * Command handler to navigate backward\n    */\n    function _navigateBack() {\n        if (!jumpForwardStack.length) {\n            if (activePosNotSynced) {\n                currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()});\n                jumpForwardStack.push(currentEditPos);\n            }\n        }\n        \n        var navFrame = jumpBackwardStack.pop();\n        \n        // Check if the poped frame is the current active frame or doesn't have any valid marker information\n        // if true, jump again\n        if (navFrame && navFrame === currentEditPos) {\n            jumpForwardStack.push(navFrame);\n            _validateNavigationCmds();\n            CommandManager.execute(NAVIGATION_JUMP_BACK);\n            return;\n        }\n        \n        if (navFrame) {\n            // We will check for the file existence now, if it doesn't exist we will jump back again\n            // but discard the popped frame as invalid.\n            _validateFrame(navFrame).done(function () {\n                jumpForwardStack.push(navFrame);\n                navFrame.goTo();\n                currentEditPos = navFrame;\n            }).fail(function () {\n                CommandManager.execute(NAVIGATION_JUMP_BACK);\n            }).always(function () {\n                _validateNavigationCmds();\n            });\n        }\n    }\n    \n   /**\n    * Command handler to navigate forward\n    */\n    function _navigateForward() {\n        var navFrame = jumpForwardStack.pop();\n        \n        if (!navFrame) {\n            return;\n        }\n        \n        // Check if the poped frame is the current active frame or doesn't have any valid marker information\n        // if true, jump again\n        if (navFrame === currentEditPos) {\n            jumpBackwardStack.push(navFrame);\n            _validateNavigationCmds();\n            CommandManager.execute(NAVIGATION_JUMP_FWD);\n            return;\n        }\n        \n        // We will check for the file existence now, if it doesn't exist we will jump back again\n        // but discard the popped frame as invalid.\n        _validateFrame(navFrame).done(function () {\n            jumpBackwardStack.push(navFrame);\n            navFrame.goTo();\n            currentEditPos = navFrame;\n        }).fail(function () {\n            _validateNavigationCmds();\n            CommandManager.execute(NAVIGATION_JUMP_FWD);\n        }).always(function () {\n            _validateNavigationCmds();\n        });\n        \n    }\n    \n   /**\n    * Function to initialize navigation menu items.\n    * @private\n    */\n    function _initNavigationMenuItems() {\n        var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU);\n        menu.addMenuItem(NAVIGATION_JUMP_BACK, \"\", Menus.AFTER, Commands.NAVIGATE_PREV_DOC);\n        menu.addMenuItem(NAVIGATION_JUMP_FWD, \"\", Menus.AFTER, NAVIGATION_JUMP_BACK);\n    }\n    \n   /**\n    * Function to initialize navigation commands and it's keyboard shortcuts.\n    * @private\n    */\n    function _initNavigationCommands() {\n        CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack);\n        CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateForward);\n        commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK);\n        commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD);\n        commandJumpBack.setEnabled(false);\n        commandJumpFwd.setEnabled(false);\n        KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]);\n        KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]);\n        _initNavigationMenuItems();\n    }\n    \n   /**\n    * Function to request a navigation frame creation explicitly.\n    * @private\n    */\n    function _captureFrame(editor) {\n        // Capture the active position now if it was not captured earlier\n        if ((activePosNotSynced || !jumpBackwardStack.length) && !jumpInProgress) {\n            jumpBackwardStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()}));\n        }\n    }\n    \n    /**\n    * Create snapshot of last known live markers.\n    * @private\n    */\n    function _backupLiveMarkers(frames, editor) {\n        var index, frame;\n        for (index in frames) {\n            frame = frames[index];\n            if (frame.cm === editor._codeMirror) {\n                frame._handleEditorDestroy();\n            }\n        }\n    }\n    \n    /**\n    * Handle Editor destruction to create backup of live marker positions\n    * @private\n    */\n    function _handleEditorCleanup(event, editor) {\n        _backupLiveMarkers(jumpBackwardStack, editor);\n        _backupLiveMarkers(jumpForwardStack, editor);\n    }\n    \n    /**\n    * Removes all frames from backward navigation stack for the given file only if the file is changed on disk.\n    * @private\n    */\n    function _removeBackwardFramesForFile(file) {\n        jumpBackwardStack = jumpBackwardStack.filter(function (frame) {\n            return frame._validateFileHash(file);\n        });\n    }\n    \n    /**\n    * Removes all frames from forward navigation stack for the given file only if the file is changed on disk.\n    * @private\n    */\n    function _removeForwardFramesForFile(file) {\n        jumpForwardStack = jumpForwardStack.filter(function (frame) {\n            return frame._validateFileHash(file);\n        });\n    }\n    \n    /**\n    * Handles explicit content reset for a document caused by external changes \n    * @private\n    */\n    function _handleExternalChange(evt, doc) {\n        if (doc) {\n            _removeBackwardFramesForFile(doc.file);\n            _removeForwardFramesForFile(doc.file);\n            _validateNavigationCmds();\n        }\n    }\n    \n    function _handleProjectOpen() {\n        jumpBackwardStack = [];\n        jumpForwardStack = [];\n    }\n    \n    /**\n     * Required to make offline markers alive again to track document mutation\n     * @private\n     */\n    function _reinstateMarkers(editor, frames) {\n        var index, frame;\n        for (index in frames) {\n            frame = frames[index];\n            if (!frame.cm && frame.filePath === editor.document.file._path) {\n                frame._reinstateMarkers(editor);\n            }\n        }\n    }\n    \n    /**\n     * Handle Active Editor change to update navigation information\n     * @private\n     */\n    function _handleActiveEditorChange(event, current, previous) {\n        if (previous && previous._paneId) { // Handle only full editors\n            previous.off(\"beforeSelectionChange\", _recordJumpDef);\n            _captureFrame(previous);\n            _validateNavigationCmds();\n        }\n        \n        if (current && current._paneId) { // Handle only full editors\n            activePosNotSynced = true;\n            current.off(\"beforeSelectionChange\", _recordJumpDef);\n            current.on(\"beforeSelectionChange\", _recordJumpDef);\n            current.off(\"beforeDestroy\", _handleEditorCleanup);\n            current.on(\"beforeDestroy\", _handleEditorCleanup);\n        }\n    }\n    \n    function _initHandlers() {\n        EditorManager.on(\"activeEditorChange\", _handleActiveEditorChange);\n        ProjectManager.on(\"projectOpen\", _handleProjectOpen);\n        EditorManager.on(\"_fullEditorCreatedForDocument\", function (event, document, editor) {\n            _handleExternalChange(event, {file: document.file});\n            _reinstateMarkers(editor, jumpBackwardStack);\n            _reinstateMarkers(editor, jumpForwardStack);\n        });\n        FileSystem.on(\"change\", function (event, entry) {\n            if (entry) {\n                _handleExternalChange(event, {file: entry});\n            }\n        });\n        Document.on(\"_documentRefreshed\", function (event, doc) {\n            _handleExternalChange(event, {file: doc.file});\n        });\n    }\n\n    function init() {\n        _initNavigationCommands();\n        _initHandlers();\n    }\n    \n    exports.init = init;\n});\n"
  },
  {
    "path": "src/extensions/default/NavigationAndHistory/html/recentfiles-template.html",
    "content": "<div id=\"mrof-container\">\n    <div id=\"mrof-list-wrapper\" class=\"quiet-scrollbars\">\n        <div class=\"header\">\n            <span>{{Strings.RECENT_FILES_DLG_HEADER}}</span>\n            <a class=\"close\" id=\"mrof-list-close\">×</a>\n        </div>\n        <span class=\"first pane-label\"></span>\n        <span class=\"second pane-label\"></span>\n        <ul id=\"mrof-list\"></ul>\n        <div class=\"footer\">\n            <span id=\"recent-file-path\"></span>\n            <div class=\"btn-alt-quiet\" id=\"clear-mrof-list\" title=\"{{Strings.RECENT_FILES_DLG_CLEAR_BUTTON_TITLE}}\">{{Strings.RECENT_FILES_DLG_CLEAR_BUTTON_LABEL}}</div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/extensions/default/NavigationAndHistory/keyboard.json",
    "content": "{\n    \"recent-files.show\": [\n        \"Alt-O\"\n    ],\n    \"recent-files.next\":  [\n        {\n            \"key\": \"Ctrl-Tab\"\n        },\n        {\n            \"key\": \"Ctrl-Tab\",\n            \"platform\": \"mac\"\n        },\n        {\n            \"key\": \"Cmd-Shift-]\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"recent-files.prev\":  [\n        {\n            \"key\": \"Ctrl-Shift-Tab\"\n        },\n        {\n            \"key\": \"Ctrl-Shift-Tab\",\n            \"platform\": \"mac\"\n        },\n        {\n            \"key\": \"Cmd-Shift-[\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"navigation.jump.back\":  [\n        {\n            \"key\": \"Alt-I\"\n        },\n        {\n            \"key\": \"Cmd-Alt-Left\",\n            \"platform\": \"mac\"\n        }\n    ],\n    \"navigation.jump.fwd\":  [\n        {\n            \"key\": \"Alt-Shift-I\"\n        },\n        {\n            \"key\": \"Cmd-Alt-Right\",\n            \"platform\": \"mac\"\n        }\n    ]\n}\n"
  },
  {
    "path": "src/extensions/default/NavigationAndHistory/main.js",
    "content": "/*\n * Copyright (c) 2016 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                       = brackets.getModule(\"thirdparty/lodash\"),\n        AppInit                 = brackets.getModule(\"utils/AppInit\"),\n        Async                   = brackets.getModule(\"utils/Async\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        MainViewManager         = brackets.getModule(\"view/MainViewManager\"),\n        DocumentManager         = brackets.getModule(\"document/DocumentManager\"),\n        DocumentCommandHandlers = brackets.getModule(\"document/DocumentCommandHandlers\"),\n        EditorManager           = brackets.getModule(\"editor/EditorManager\"),\n        ProjectManager          = brackets.getModule(\"project/ProjectManager\"),\n        CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        Commands                = brackets.getModule(\"command/Commands\"),\n        Dialogs                 = brackets.getModule(\"widgets/Dialogs\"),\n        Menus                   = brackets.getModule(\"command/Menus\"),\n        FileSystem              = brackets.getModule(\"filesystem/FileSystem\"),\n        FileUtils               = brackets.getModule(\"file/FileUtils\"),\n        ViewUtils               = brackets.getModule(\"utils/ViewUtils\"),\n        KeyEvent                = brackets.getModule(\"utils/KeyEvent\"),\n        WorkingSetView          = brackets.getModule(\"project/WorkingSetView\"),\n        PreferencesManager      = brackets.getModule(\"preferences/PreferencesManager\"),\n        KeyBindingManager       = brackets.getModule(\"command/KeyBindingManager\"),\n        ExtensionUtils          = brackets.getModule(\"utils/ExtensionUtils\"),\n        Mustache                = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        NavigationProvider      = require(\"NavigationProvider\");\n\n    var KeyboardPrefs = JSON.parse(require(\"text!keyboard.json\"));\n    \n    // Command constants for recent files\n    var PREFS_RECENT_FILES      = \"recent-files.navigation\",\n        SHOW_RECENT_FILES       = \"recent-files.show\",\n        NEXT_IN_RECENT_FILES    = \"recent-files.next\",\n        PREV_IN_RECENT_FILES    = \"recent-files.prev\",\n        OPEN_FILES_VIEW_STATE   = \"openFiles\";\n    \n    var htmlTemplate = require(\"text!html/recentfiles-template.html\"),\n        dirtyDotTemplate = \"<div class='file-status-icon dirty' style='position: absolute;margin-left: -2px;'></div>\";\n    \n    var MAX_ENTRY_COUNT    = 50;\n    \n    var isRecentFilesNavEnabled = true;\n\n    /*\n    * Contains list of most recently opened files and their last known cursor position\n    * @private\n    * @type {Array.<Object>}\n    */\n    var _mrofList = [],\n        $mrofContainer = null;\n    \n    \n    var $currentContext,\n        activeEditor;\n    \n    var _hideMROFList;\n    \n    PreferencesManager.definePreference(PREFS_RECENT_FILES, \"boolean\", true, {\n        description: Strings.DESCRIPTION_RECENT_FILES_NAV\n    });\n\n    /**\n     * Returns a 'context' object for getting/setting project-specific preferences\n     */\n    function _getPrefsContext() {\n        var projectRoot = ProjectManager.getProjectRoot();\n        return { location : { scope: \"user\", layer: \"project\", layerID: projectRoot && projectRoot.fullPath } };\n    }\n\n    /**\n     * Opens a full editor for the given context\n     * @private\n     * @param {Object.<path, paneId, cursor>} contextData - wrapper to provide the information required to open a full editor\n     * @return {$.Promise} - from the commandmanager \n     */\n    function _openEditorForContext(contextData) {\n        // Open the file in the current active pane to prevent unwanted scenarios if we are not in split view, fallback\n        // to the persisted paneId when specified and we are in split view or unable to determine the paneid\n        var activePaneId = MainViewManager.getActivePaneId(),\n            targetPaneId = contextData.paneId; // Assume we are going to use the last associated paneID\n\n        // Detect if we are not in split mode\n        if (MainViewManager.getPaneCount() === 1) {\n            // Override the targetPaneId with activePaneId as we are not yet in split mode\n            targetPaneId = activePaneId;\n        }\n\n        // If hide of MROF list is a context parameter, hide the MROF list on successful file open\n        if (contextData.hideOnOpenFile) {\n            _hideMROFList();\n        }\n\n        return CommandManager\n            .execute(Commands.FILE_OPEN,\n                    {   fullPath: contextData.path,\n                        paneId: targetPaneId\n                    }\n                )\n            .done(function () {\n                if (contextData.cursor) {\n                    activeEditor = EditorManager.getActiveEditor();\n                    activeEditor.setCursorPos(contextData.cursor);\n                    activeEditor.centerOnCursor();\n                }\n            });\n    }\n    \n    /**\n     * Creates an entry for MROF list\n     * @private\n     * @param {String} path - full path of a doc\n     * @param {String} pane - the pane holding the editor for the doc\n     * @param {Object} cursorPos - current cursor position\n     * @return {Object} a frame containing file path, pane and last known cursor\n     */\n    function _makeMROFListEntry(path, pane, cursorPos) {\n        return {\n            file: path,\n            paneId: pane,\n            cursor: cursorPos\n        };\n    }\n    \n    /**\n     * Determines if a file is dirty\n     * @private\n     * @param {!File} file - file to test\n     * @return {boolean} true if the file is dirty, false otherwise\n     */\n    function _isOpenAndDirty(file) {\n        // working set item might never have been opened; if so, then it's definitely not dirty\n        var docIfOpen = DocumentManager.getOpenDocumentForPath(file.fullPath);\n        return (docIfOpen && docIfOpen.isDirty);\n    }\n\n    function _checkExt(entry, index) {\n        var deferred = new $.Deferred(),\n            fileEntry = FileSystem.getFileForPath(entry.file);\n\n        if (entry.inMem) {\n            var indxInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file);\n            // Remove entry if InMemoryFile is not found in Working set\n            if (indxInWS === -1) {\n                _mrofList[index] = null;\n                deferred.reject();\n            } else {\n                deferred.resolve();\n            }\n        } else {\n            fileEntry.exists(function (err, exists) {\n                if (!err && exists) {\n                    deferred.resolve();\n                } else {\n                    _mrofList[index] = null;\n                    deferred.reject();\n                }\n\t\t    });\n\t    }\n\n        return deferred.promise();\n    }\n    \n    /**\n     * Checks whether entries in MROF list actually exists in fileSystem to prevent access to deleted files \n     * @private\n     */\n    function _syncWithFileSystem() {\n        _mrofList = _mrofList.filter(function (e) {return e; });\n        return Async.doSequentially(_mrofList, _checkExt, false);\n    }\n    \n    function _getFileListForEntries(entries) {\n        return $.map(entries, function (value, index) {\n            return FileSystem.getFileForPath(value.file);\n        });\n    }\n\n    function _addDirectoriesForDuplicateBaseNames() {\n        var checked = {}, baseName;\n        // Find duplicates first\n        $.map(_mrofList, function (value, index) {\n            baseName = FileUtils.getBaseName(value.file);\n            if (!checked[baseName]) {\n                checked[baseName] = [];\n            }\n            checked[baseName].push(value);\n        });\n\n        // Go through the map and solve the arrays with length over 1. Ignore the rest.\n        _.forEach(checked, function (value) {\n            if (value.length > 1) {\n                var dirs = ViewUtils.getDirNamesForDuplicateFiles(_getFileListForEntries(value));\n                $.map(value, function (value, index) {\n                    // Go through recent files and add directories to appropriate entries\n                    $mrofContainer.find(\"#mrof-list > li\").each(function () {\n                        var $li = $(this);\n                        if ($li.data(\"path\") === value.file) {\n                            var dirSplit = dirs[index].split(\"/\");\n                            if (dirSplit.length > 3) {\n                                dirs[index] = dirSplit[0] + \"/\\u2026/\" + dirSplit[dirSplit.length - 1];\n                            }\n                            var $dir = $(\"<span class='directory'/>\").html(\" &mdash; \" + dirs[index]);\n                            $li.children(\"a.mroitem\").find(\"span.directory\").remove();\n                            $li.children(\"a.mroitem\").append($dir);\n                        }\n                    });\n                });\n            }\n        });\n    }\n\n    function _createFileEntries($mrofList) {\n        var data, fileEntry, $link, $newItem;\n        // Iterate over the MROF list and create the pop over UI items\n\n        // If we are in split view we might want to show the panes corresponding to the entries\n        var isPaneLabelReqd = MainViewManager.getPaneCount() > 1;\n\n        if (isPaneLabelReqd) {\n            $mrofContainer.addClass(\"split-mode\");\n            $(\".first.pane-label\", $mrofContainer).text(MainViewManager.getPaneTitle(\"first-pane\"));\n            $(\".second.pane-label\", $mrofContainer).text(MainViewManager.getPaneTitle(\"second-pane\"));\n        }\n\n        $.each(_mrofList, function (index, value) {\n            \n            if (!isPaneLabelReqd && value.paneId !== MainViewManager.getActivePaneId()) {\n                // Try to see if we have same doc split\n                // Check existing list for this doc path and active pane entry\n                var entryIndex = _.findIndex(_mrofList, function (record) {\n                    return (record && record.file === value.file && record.paneId === MainViewManager.getActivePaneId());\n                });\n\n                // If found don't process this entry, as the document is already present in active pane\n                if (entryIndex >= 0) {\n                    return true;\n                } else {\n                    // Process this for active pane id\n                    value.paneId = MainViewManager.getActivePaneId();\n                }\n            }\n\n            var indxInWS = MainViewManager.findInWorkingSet(value.paneId, value.file);\n\n            data = {fullPath: value.file,\n                    name: FileUtils.getBaseName(value.file),\n                    isFile: true};\n            \n            fileEntry = FileSystem.getFileForPath(value.file);\n            \n            // Create new list item with a link\n            $link = $(\"<a href='#' class='mroitem'></a>\").html(ViewUtils.getFileEntryDisplay({name: FileUtils.getBaseName(value.file)}));\n            \n            // Use the file icon providers\n            WorkingSetView.useIconProviders(data, $link);\n            \n            $newItem = $(\"<li></li>\").append($link);\n            \n            if (indxInWS !== -1) { // in working set show differently\n                $newItem.addClass(\"working-set\");\n            }\n\n            $newItem.data(\"path\", value.file);\n            $newItem.data(\"paneId\", value.paneId);\n            $newItem.data(\"cursor\", value.cursor);\n            $newItem.data(\"file\", fileEntry);\n            $newItem.attr(\"title\", value.file);\n            \n            if (isPaneLabelReqd && value.paneId) {\n                $newItem.addClass(value.paneId);\n                $newItem.css('top', ($('.' + value.paneId, $mrofList).length * 22) + 'px');\n            }\n\n            // Use the class providers(git e.t.c)\n            WorkingSetView.useClassProviders(data, $newItem);\n            \n            // If a file is dirty , mark it in the list\n            if (_isOpenAndDirty(fileEntry)) {\n                $(dirtyDotTemplate).prependTo($newItem);\n            }\n            \n            $mrofList.append($newItem);\n\n            if (index === MAX_ENTRY_COUNT - 1) {\n                // We have reached the max number of entries we can display, break out\n                return false;\n            }\n        });\n        _addDirectoriesForDuplicateBaseNames();\n    }\n    \n    /**\n     * This function is used to create mrof when a project is opened for the firt time with the recent files feature\n     * This routine acts as a logic to migrate existing viewlist to mrof structure\n     * @private\n     */\n    function _createMROFList() {\n\n        var paneList = MainViewManager.getPaneIdList(),\n            mrofList = [],\n            fileList,\n            index;\n\n        var pane, file, mrofEntry, paneCount, fileCount;\n        // Iterate over the pane ID list\n        for (paneCount = 0; paneCount < paneList.length; paneCount++) {\n            pane = paneList[paneCount];\n            fileList = MainViewManager.getWorkingSet(pane);\n            // Iterate over the file list for this pane\n            for (fileCount = 0; fileCount < fileList.length; fileCount++) {\n                file = fileList[fileCount];\n                mrofEntry = _makeMROFListEntry(file.fullPath, pane, null);\n                // Add it in the MRU list order\n                index = MainViewManager.findInGlobalMRUList(pane, file);\n                mrofList[index] = mrofEntry;\n            }\n        }\n\n        return mrofList;\n    }\n    \n    function _handleArrowKeys(event) {\n        var UP = 38,\n            DOWN = 40;\n\n        var $context, $nextContext;\n        if ($mrofContainer && (event.which === UP || event.which === DOWN)) {\n            $context = $currentContext || $(\"#mrof-container #mrof-list > li.highlight\");\n            if ($context.length > 0) {\n                $nextContext = event.which === UP ? $context.prev() : $context.next();\n                if ($nextContext.length > 0) {\n                    $currentContext = $nextContext;\n                    //_resetOpenFileTimer();\n                    $nextContext.find(\"a.mroitem\").trigger(\"focus\");\n                }\n            } else {\n                //WTF! (Worse than failure). We should not get here.\n                $(\"#mrof-container #mrof-list > li > a.mroitem:visited\").last().trigger(\"focus\");\n            }\n            // If we don't prevent this then scrolling happens by the browser(user agent behaviour)\n            // as well as a result of moving focus in the ul\n            event.preventDefault();\n            event.stopImmediatePropagation();\n        }\n    }\n\n    function _hideMROFListOnEscape(event) {\n        if ($mrofContainer && event.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n            _hideMROFList();\n        }\n    }\n\n    /**\n     * Shows the current MROF list\n     * @private\n     */\n    function _createMROFDisplayList(refresh) {\n        var $def = $.Deferred();\n        \n        var $mrofList, $link, $newItem;\n\n        /**\n         * Clears the MROF list in memory and pop over but retains the working set entries\n         * @private\n         */\n        function _purgeAllExceptWorkingSet() {\n            _mrofList = _createMROFList();\n            $mrofList.empty();\n            _createMROFDisplayList(true);\n            $currentContext = null;\n            PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n        }\n\n        if (!refresh) {\n            // Call hide first to make sure we are not creating duplicate lists\n            _hideMROFList();\n            $mrofContainer = $(Mustache.render(htmlTemplate, {Strings: Strings})).appendTo('body');\n            $(\"#mrof-list-close\").one(\"click\", _hideMROFList);\n            // Attach clear list handler to the 'Clear All' button\n            $(\"#mrof-container .footer > div#clear-mrof-list\").on(\"click\", _purgeAllExceptWorkingSet);\n            $(window).on(\"keydown\", _handleArrowKeys);\n            $(window).on(\"keyup\", _hideMROFListOnEscape);\n        }\n        \n        $mrofList = $mrofContainer.find(\"#mrof-list\");\n        \n        /**\n         * Focus handler for the link in list item \n         * @private\n         */\n        function _onFocus(event) {\n            var $scope = $(event.target).parent();\n            $(\"#mrof-container #mrof-list > li.highlight\").removeClass(\"highlight\");\n            $(event.target).parent().addClass(\"highlight\");\n            $mrofContainer.find(\"#recent-file-path\").text($scope.data(\"path\"));\n            $mrofContainer.find(\"#recent-file-path\").attr('title', ($scope.data(\"path\")));\n            $currentContext = $scope;\n        }\n        \n        /**\n         * Click handler for the link in list item \n         * @private\n         */\n        function _onClick(event) {\n            var $scope = $(event.delegateTarget).parent();\n            _openEditorForContext({\n                path: $scope.data(\"path\"),\n                paneId: $scope.data(\"paneId\"),\n                cursor: $scope.data(\"cursor\"),\n                hideOnOpenFile: true\n            });\n        }\n\n        var data, fileEntry;\n        \n        _syncWithFileSystem().always(function () {\n            _mrofList = _mrofList.filter(function (e) {return e; });\n            _createFileEntries($mrofList);\n            var $fileLinks = $(\"#mrof-container #mrof-list > li > a.mroitem\");\n            // Handlers for mouse events on the list items\n            $fileLinks.on(\"focus\", _onFocus);\n            $fileLinks.on(\"click\", _onClick);\n            $fileLinks.on(\"select\", _onClick);\n\n            // Put focus on the Most recent file link in the list\n            $fileLinks.first().trigger(\"focus\");\n\n            $def.resolve();\n        });\n\n        return $def.promise();\n    }\n    \n    function _openFile() {\n        if ($currentContext) {\n            _openEditorForContext({\n                path: $currentContext.data(\"path\"),\n                paneId: $currentContext.data(\"paneId\"),\n                cursor: $currentContext.data(\"cursor\")\n            });\n        }\n    }\n    \n    function _hideMROFListOnNavigationEnd(event) {\n        if ($mrofContainer && event.keyCode === KeyEvent.DOM_VK_CONTROL) {\n            _openFile();\n            _hideMROFList();\n        }\n    }\n\n\n    /**\n     * Opens the next item in MROF list if pop over is visible else displays the pop over \n     * @private\n     */\n    function _moveNext() {\n        var $context, $next;\n\n        $context = $currentContext || $(\"#mrof-container #mrof-list > li.highlight\");\n        if ($context.length > 0) {\n            $next = $context.next();\n            if ($next.length === 0) {\n                $next = $(\"#mrof-container #mrof-list > li\").first();\n            }\n            if ($next.length > 0) {\n                $currentContext = $next;\n                $next.find(\"a.mroitem\").trigger(\"focus\");\n            }\n        } else {\n            //WTF! (Worse than failure). We should not get here.\n            $(\"#mrof-container #mrof-list > li > a.mroitem:visited\").last().trigger(\"focus\");\n        }\n    }\n\n    function _cmdMoveNext() {\n        var $displayPromise;\n        if (!$mrofContainer) {\n            $displayPromise = _createMROFDisplayList();\n            $mrofContainer.addClass(\"confirmation-mode\");\n            $(window).on(\"keyup\", _hideMROFListOnNavigationEnd);\n        }\n\n        if ($displayPromise) {\n            $displayPromise.always(function () {\n                _moveNext();\n            });\n        } else {\n            _moveNext();\n        }\n    }\n\n    /**\n     * Opens the previous item in MROF list if pop over is visible else displays the pop over \n     * @private\n     */\n    function _movePrev() {\n        var $context, $prev;\n\n        $context = $currentContext || $(\"#mrof-container #mrof-list > li.highlight\");\n        if ($context.length > 0) {\n            $prev = $context.prev();\n            if ($prev.length === 0) {\n                $prev = $(\"#mrof-container #mrof-list > li\").last();\n            }\n            if ($prev.length > 0) {\n                $currentContext = $prev;\n                $prev.find(\"a.mroitem\").trigger(\"focus\");\n            }\n        } else {\n            //WTF! (Worse than failure). We should not get here.\n            $(\"#mrof-container #mrof-list > li > a.mroitem:visited\").last().trigger(\"focus\");\n        }\n    }\n    \n    function _cmdMovePrev() {\n        var $displayPromise;\n        if (!$mrofContainer) {\n            $displayPromise = _createMROFDisplayList();\n            $mrofContainer.addClass(\"confirmation-mode\");\n            $(window).on(\"keyup\", _hideMROFListOnNavigationEnd);\n        }\n\n        if ($displayPromise) {\n            $displayPromise.always(function () {\n                _movePrev();\n            });\n        } else {\n            _movePrev();\n        }\n    }\n\n    function _updateCursorPosition(filePath, paneId, cursorPos) {\n        if (!paneId) { // Don't handle this if not a full view/editor\n            return;\n        }\n\n        // Check existing list for this doc path and pane entry\n        var index = _.findIndex(_mrofList, function (record) {\n            return (record && record.file === filePath && record.paneId === paneId);\n        });\n\n        var entry;\n\n        if (index !== -1) {\n            _mrofList[index].cursor = cursorPos;\n        }\n\n        PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n    }\n\n    /**\n     * Adds an entry to MROF list\n     * @private\n     * @param {Editor} editor - editor to extract file information\n     */\n    function _addToMROFList(file, paneId, cursorPos) {\n\n        var filePath = file.fullPath;\n        \n        if (!paneId) { // Don't handle this if not a full view/editor\n            return;\n        }\n\n\n        // Check existing list for this doc path and pane entry\n        var index = _.findIndex(_mrofList, function (record) {\n            return (record && record.file === filePath && record.paneId === paneId);\n        });\n\n        var entry;\n        if (index !== -1) {\n            entry = _mrofList[index];\n            if (entry.cursor && !cursorPos) {\n                cursorPos = entry.cursor;\n            }\n        }\n\n        entry = _makeMROFListEntry(filePath, paneId, cursorPos);\n\n        // Check if the file is an InMemoryFile\n        if (file.constructor.name === \"InMemoryFile\") {\n            // Mark the entry as inMem, so that we can knock it off from the list when removed from working set\n            entry.inMem = true;\n        }\n\n\n        if (index !== -1) {\n            _mrofList.splice(index, 1);\n        }\n\n        // add it to the front of the list\n        _mrofList.unshift(entry);\n\n        PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n    }\n\n    // To update existing entry if a move has happened\n    function _handleWorkingSetMove(event, file, sourcePaneId, destinationPaneId) {\n        // Check existing list for this doc path and source pane entry\n        var index = _.findIndex(_mrofList, function (record) {\n            return (record && record.file === file.fullPath && record.paneId === sourcePaneId);\n        }), tIndex;\n        // If an entry is found update the pane info\n        if (index >= 0) {\n            // But an entry with the target pane Id should not exist\n            tIndex = _.findIndex(_mrofList, function (record) {\n                return (record && record.file === file.fullPath && record.paneId === destinationPaneId);\n            });\n            if (tIndex === -1) {\n                _mrofList[index].paneId = destinationPaneId;\n            } else {\n                // Remove this entry as it has been moved.\n                _mrofList.splice(index, 1);\n            }\n        }\n    }\n    \n    // Handle project close or app close to set view state\n    function _handleAppClose() {\n        PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n        _mrofList = [];\n    }\n    \n    function _initRecentFilesList() {\n        _mrofList = PreferencesManager.getViewState(OPEN_FILES_VIEW_STATE, _getPrefsContext()) || [];\n        \n        _mrofList = _mrofList.filter(function (entry) {\n            return entry;\n        });\n        // Have a check on the number of entries to fallback to working set if we detect corruption\n        if (_mrofList.length < MainViewManager.getWorkingSetSize(MainViewManager.ALL_PANES)) {\n            _mrofList = _createMROFList();\n        }\n    }\n\n    function _handleProjectOpen() {\n        _mrofList = [];\n        // We will do a late initialization once we get the first editor change or file open notification\n    }\n\n    ProjectManager.on(\"projectOpen\", _handleProjectOpen);\n\n    \n    function _showRecentFileList() {\n        if (isRecentFilesNavEnabled) {\n            _createMROFDisplayList();\n        }\n    }\n    \n    /**\n     * Hides the current MROF list if visible\n     * @private\n     */\n    _hideMROFList = function () {\n\n        if ($mrofContainer) {\n            $mrofContainer.remove();\n            $mrofContainer = null;\n            $currentContext = null;\n            activeEditor = EditorManager.getActiveEditor();\n            if (activeEditor) {\n                activeEditor.focus();\n            }\n        }\n\n        $(window).off(\"keydown\", _handleArrowKeys);\n        $(window).off(\"keyup\", _hideMROFListOnNavigationEnd);\n        $(window).off(\"keyup\", _hideMROFListOnEscape);\n    };\n\n    // To take care of hiding the popover during app navigation in os using key board shortcuts\n    $(window).on(\"blur focus\", function () {\n        _hideMROFList();\n    });\n    \n    // Merges the entries to a single pane if split view have been merged\n    // Then purges duplicate entries in mrof list\n    function _handlePaneMerge(e, paneId) {\n        var index;\n        var targetPaneId = MainViewManager.FIRST_PANE;\n\n        $.each(_mrofList, function (itrIndex, value) {\n            if (value && value.paneId === paneId) { // We have got an entry which needs merge\n                // Before modifying the actual pane info check if an entry exists with same target pane\n                index = _.findIndex(_mrofList, function (record) {\n                    return (record && record.file === value.file && record.paneId === targetPaneId);\n                });\n                if (index !== -1) { // A duplicate entry found, remove the current one instead of updating\n                    _mrofList[index] = null;\n                } else { // Update with merged pane info\n                    _mrofList[itrIndex].paneId = targetPaneId;\n                }\n            }\n        });\n\n        // Clean the null/undefined entries\n        _mrofList = _mrofList.filter(function (e) {return e; });\n\n        PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n    }\n\n    function _initRecentFileMenusAndCommands() {\n        // Command to show recent files list\n\n        if (!CommandManager.get(SHOW_RECENT_FILES)) {\n            CommandManager.register(Strings.CMD_RECENT_FILES_OPEN, SHOW_RECENT_FILES, _showRecentFileList);\n            KeyBindingManager.addBinding(SHOW_RECENT_FILES, KeyboardPrefs[SHOW_RECENT_FILES]);\n        }\n        \n        // Keyboard only - Navigate to the next doc in MROF list\n        if (!CommandManager.get(NEXT_IN_RECENT_FILES)) {\n            CommandManager.register(Strings.CMD_NEXT_DOC, NEXT_IN_RECENT_FILES, _cmdMoveNext);\n        }\n        KeyBindingManager.addBinding(NEXT_IN_RECENT_FILES, KeyboardPrefs[NEXT_IN_RECENT_FILES]);\n       \n        // Keyboard only - Navigate to the prev doc in MROF list\n        if (!CommandManager.get(PREV_IN_RECENT_FILES)) {\n            CommandManager.register(Strings.CMD_PREV_DOC, PREV_IN_RECENT_FILES, _cmdMovePrev);\n        }\n        KeyBindingManager.addBinding(PREV_IN_RECENT_FILES, KeyboardPrefs[PREV_IN_RECENT_FILES]);\n        \n        var menu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU);\n        menu.addMenuItem(SHOW_RECENT_FILES, \"\", Menus.AFTER, Commands.FILE_OPEN_FOLDER);\n    }\n\n    function _initDefaultNavigationCommands() {\n        KeyBindingManager.addBinding(Commands.NAVIGATE_NEXT_DOC, KeyboardPrefs[NEXT_IN_RECENT_FILES]);\n        KeyBindingManager.addBinding(Commands.NAVIGATE_PREV_DOC, KeyboardPrefs[PREV_IN_RECENT_FILES]);\n    }\n\n    function _removeKeys(keys) {\n        _.forEach(keys, function (config) {\n            KeyBindingManager.removeBinding(config.key);\n        });\n    }\n\n    function _removeNavigationKeys() {\n        _removeKeys(KeyboardPrefs[NEXT_IN_RECENT_FILES]);\n        _removeKeys(KeyboardPrefs[PREV_IN_RECENT_FILES]);\n    }\n\n    function _deregisterSortcutsAndMenus() {\n        _removeNavigationKeys();\n        Menus.getMenu(Menus.AppMenuBar.FILE_MENU).removeMenuItem(SHOW_RECENT_FILES);\n    }\n\n    // Handle current file change\n    function handleCurrentFileChange(e, newFile, newPaneId, oldFile) {\n        if (newFile) {\n            if (_mrofList.length === 0) {\n                _initRecentFilesList();\n            }\n\n\t        _addToMROFList(newFile, newPaneId);\n        }\n    }\n\n    // Handle Active Editor change to update mrof information\n    function _handleActiveEditorChange(event, current, previous) {\n        if (current) { // Handle only full editors\n            if (_mrofList.length === 0) {\n                _initRecentFilesList();\n            }\n\n            var file = current.document.file;\n            var paneId = current._paneId;\n            _addToMROFList(file, paneId, current.getCursorPos(true, \"first\"));\n        }\n\n        if (previous) { // Capture the last know cursor position\n            _updateCursorPosition(previous.document.file.fullPath, previous._paneId, previous.getCursorPos(true, \"first\"));\n        }\n    }\n\n    function _attachListners() {\n        MainViewManager.on(\"workingSetMove.pane-first-pane\", _handleWorkingSetMove);\n        MainViewManager.on(\"currentFileChange\", handleCurrentFileChange);\n        MainViewManager.on(\"paneDestroy\", _handlePaneMerge);\n        EditorManager.on(\"activeEditorChange\", _handleActiveEditorChange);\n        ProjectManager.on(\"beforeProjectClose beforeAppClose\", _handleAppClose);\n    }\n\n    function _detachListners() {\n        MainViewManager.off(\"workingSetMove.pane-first-pane\", _handleWorkingSetMove);\n        MainViewManager.off(\"currentFileChange\", handleCurrentFileChange);\n        MainViewManager.off(\"paneDestroy\", _handlePaneMerge);\n        EditorManager.off(\"activeEditorChange\", _handleActiveEditorChange);\n        ProjectManager.off(\"beforeProjectClose beforeAppClose\", _handleAppClose);\n    }\n\n    PreferencesManager.on(\"change\", PREFS_RECENT_FILES, function () {\n        if (PreferencesManager.get(PREFS_RECENT_FILES)) {\n            _removeNavigationKeys();\n            _initRecentFileMenusAndCommands();\n            _mrofList = [];\n            _initRecentFilesList();\n            PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n            _detachListners();\n            _attachListners();\n            isRecentFilesNavEnabled = true;\n        } else {\n            // Reset the view state to empty\n            _mrofList = [];\n            PreferencesManager.setViewState(OPEN_FILES_VIEW_STATE, _mrofList, _getPrefsContext(), true);\n            _deregisterSortcutsAndMenus();\n            _initDefaultNavigationCommands();\n            _detachListners();\n            isRecentFilesNavEnabled = false;\n        }\n    });\n\n    AppInit.appReady(function () {\n        ExtensionUtils.loadStyleSheet(module, \"styles/recent-files.css\");\n        NavigationProvider.init();\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/NavigationAndHistory/styles/recent-files.css",
    "content": "#mrof-container {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top:0px;\n    left:0px;\n    z-index: 1051;\n}\n\n#mrof-list-wrapper {\n    display:block;\n    height:50%;\n    background: #2c2c2c;\n    position:absolute;\n    left:calc(50% - 250px);\n    top:25%;\n    width: 550px;\n    z-index: 1050;\n    border-radius: 6px;\n}\n\n.dark #mrof-list-wrapper {\n    box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.5);\n}\n\n#mrof-container #mrof-list {\n    display: block;\n    width: 100%;\n    height: calc(100% - 60px);\n    position: absolute;\n    left: 0%;\n    top: 30px;\n    padding: 10px;\n    overflow-y: auto;\n    overflow-x: hidden;\n    margin: 0px;\n    box-sizing: border-box; \n}\n\n#mrof-container.split-mode #mrof-list {\n    top:60px;\n    height: calc(100% - 90px);\n}\n\n#mrof-container #mrof-list > li {\n    position: relative;\n    display: block;\n    height: 22px;\n    margin-left: 5px;\n    float: left;\n    width: calc(100% - 20px);\n    min-width: 230px;\n    padding: 1px 5px;\n    white-space: nowrap;\n    opacity:0.5;\n}\n\n#mrof-container #mrof-list > li.working-set {\n    opacity: 1;\n}\n\n#mrof-container #mrof-list > li.first-pane {\n    position:absolute;\n    left:0px;\n    width: calc(50% - 30px);\n}\n\n#mrof-container #mrof-list > li.second-pane {\n    position:absolute;\n    right:5px;\n    width: calc(50% - 30px);\n}\n\n#mrof-container #mrof-list > li.highlight {\n    background: #3c3f41;\n}\n\n#mrof-container #mrof-list > li > a.mroitem {\n    color: #ffffff;\n    font-size: 13px;\n    height: 22px;\n    text-decoration: none;\n    display: block;\n    line-height: 15px;\n    padding: 3px;\n    cursor: default;\n    padding-left: 10px;\n    width: 100%;\n    box-sizing: border-box;\n    text-overflow: ellipsis;\n    overflow-wrap: normal;\n    overflow: hidden;\n}\n\n#mrof-container #mrof-list > li > a.mroitem > .extension {\n    color: #adb9bd;\n}\n\n#mrof-container #mrof-list > li > a.mroitem > .directory {\n    color: #adb9bd;\n}\n\n#mrof-container #mrof-list > li > a.mroitem:focus {\n    background: transparent;\n    color:#8fddff;\n    box-shadow: none !important;\n    padding-left: 10px;\n}\n\n#mrof-container #mrof-list > li.highlight > a.mroitem {\n    background: transparent;\n    color:#8fddff;\n    box-shadow: none !important;\n    padding-left: 10px;\n}\n\n#mrof-container #mrof-list > li.highlight > a.mroitem > .extension {\n    color:#8fddff;\n}\n\n#mrof-container .header {\n    color: #adb9bd;\n    width: 100%;\n    height: 30px;\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    padding-right: 15px;\n    box-sizing: border-box;\n    padding: 5px 15px;\n    border-bottom: 1px solid #44464C;\n    border-radius: 6px 6px 0px 0px;\n}\n\n#mrof-container .header > span {\n    color: #adb9bd;\n    float:left;\n    font-weight: 800;\n}\n\n#mrof-container .footer {\n    color: #adb9bd;\n    width: 100%;\n    height: 30px;\n    position: absolute;\n    bottom: 0px;\n    left: 0px;\n    padding: 5px 15px;\n    padding-left: 20px;\n    border-top: 1px solid #44464C;\n    box-sizing: border-box;\n    overflow:hidden;\n    border-radius: 0px 0px 6px 6px;\n}\n\n#mrof-container .header > .close {\n    color: #adb9bd;\n    margin: 0px;\n}\n\n#mrof-container.confirmation-mode .header > .close {\n    display: none;\n}\n\n#mrof-container.confirmation-mode #clear-mrof-list {\n    display: none;\n}\n\n#mrof-container > .hseperator {\n    width: 100%;\n    height:10px;\n    position: absolute;\n    top:30px;\n    left:0px;\n}\n\n#mrof-container > .vseperator {\n    width: 100%;\n    height:10px;\n    position:absolute;\n    bottom:30px;\n    left:0px;\n}\n\n#mrof-container #clear-mrof-list {\n    display: block;\n    position: absolute;\n    top: 1px;\n    right: 15px;\n    width: 80px;\n    height: 25px;\n    padding: 3px;\n    text-align: center;\n    box-sizing: border-box;\n}\n\n#mrof-container #recent-file-path {\n    float: left;\n    width: calc(100% - 90px);\n    box-sizing: border-box;\n    text-overflow: ellipsis;\n    overflow-wrap: normal;\n    overflow: hidden;\n    white-space: nowrap;\n    font-size: 11px;\n}\n\n.pane-label {\n    position:absolute;\n    display:none;\n    width:50%;\n    text-align: center;\n    top: 30px;\n    padding:4px;\n}\n\n.split-mode .pane-label {\n    display: block;\n    color: #adb9bd;\n}\n\n.pane-label.first {\n    left:0px;\n}\n\n.pane-label.second {\n    right:0px;\n}\n\n#mrof-container .header {\n    background: #222222;\n    border-bottom: 1px solid #343434;\n    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);\n}\n\n#mrof-container .footer {\n    background-color: #2c2c2c;\n    border-top: 1px solid #343434;\n}\n"
  },
  {
    "path": "src/extensions/default/NoDistractions/main.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Menus               = brackets.getModule(\"command/Menus\"),\n        CommandManager      = brackets.getModule(\"command/CommandManager\"),\n        Commands            = brackets.getModule(\"command/Commands\"),\n        Strings             = brackets.getModule(\"strings\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        ViewUtils           = brackets.getModule(\"utils/ViewUtils\"),\n        KeyBindingManager   = brackets.getModule(\"command/KeyBindingManager\"),\n        HealthLogger        = brackets.getModule(\"utils/HealthLogger\"),\n        WorkspaceManager    = brackets.getModule(\"view/WorkspaceManager\");\n\n    // Constants\n    var PREFS_PURE_CODE           = \"noDistractions\",\n        CMD_TOGGLE_PURE_CODE      = \"view.togglePureCode\",\n        CMD_TOGGLE_PANELS         = \"view.togglePanels\",\n        HEALTH_NO_DISTRACTION     = \"noDistractionModeUsed\",\n        HEALTH_TOGGLE_PANELS      = \"togglePanels\";\n\n    //key binding keys\n    var togglePureCodeKey         = \"Ctrl-Shift-2\",\n        togglePureCodeKeyMac      = \"Cmd-Shift-2\",\n        togglePanelsKey           = \"Ctrl-Shift-1\",\n        togglePanelsKeyMac        = \"Cmd-Shift-1\",\n        togglePanelsKey_EN        = \"Ctrl-Shift-`\",\n        togglePanelsKeyMac_EN     = \"Cmd-Shift-`\";\n\n    //locals\n    var _previouslyOpenPanelIDs = [],\n        panelsToggled = false,\n        layoutUpdated = false;\n\n    /**\n     * @private\n     * Updates the command checked status based on the preference for noDestraction mode\n     */\n    function _updateCheckedState() {\n        CommandManager.get(CMD_TOGGLE_PURE_CODE).setChecked(PreferencesManager.get(PREFS_PURE_CODE));\n    }\n\n    /**\n     * @private\n     * toggles noDisraction preference\n     */\n    function _togglePureCode() {\n        PreferencesManager.set(PREFS_PURE_CODE, !PreferencesManager.get(PREFS_PURE_CODE));\n        HealthLogger.setHealthDataLog(HEALTH_NO_DISTRACTION, true);\n    }\n\n    /**\n     * hide all open panels\n     */\n    function _hidePanelsIfRequired() {\n        var panelIDs = WorkspaceManager.getAllPanelIDs();\n        _previouslyOpenPanelIDs = [];\n        panelIDs.forEach(function (panelID) {\n            var panel = WorkspaceManager.getPanelForID(panelID);\n            if (panel && panel.isVisible()) {\n                panel.hide();\n                _previouslyOpenPanelIDs.push(panelID);\n            }\n        });\n    }\n\n    /**\n     * show all open panels that was previously hidden by _hidePanelsIfRequired()\n     */\n    function _showPanelsIfRequired() {\n        var panelIDs = _previouslyOpenPanelIDs;\n        panelIDs.forEach(function (panelID) {\n            var panel = WorkspaceManager.getPanelForID(panelID);\n            if (panel) {\n                panel.show();\n            }\n        });\n        _previouslyOpenPanelIDs = [];\n    }\n\n    function _updateLayout() {\n        layoutUpdated = true;\n        panelsToggled = false;\n    }\n\n    /**\n     * We toggle panels in certain cases only :\n     * 1. if a panel is shown, toggle can hide it, and successive toggle can show the panel and repeat.\n     * 2. if a panel is hidden by toggle, and say the workspace changed making another panel visible by some operation;\n     * we reset toggle states so that toggle would hide the panel already present in the workspace.\n     * The already hidden panel should not be shown in the specific case for better UX.\n     */\n    function _togglePanels() {\n        var togglePanelCount;\n        panelsToggled = !panelsToggled;\n        if (panelsToggled) {\n            _hidePanelsIfRequired();\n            layoutUpdated = false;\n            panelsToggled = true;\n        } else if (!layoutUpdated) {\n            _showPanelsIfRequired();\n        }\n\n        //log health data\n        togglePanelCount = HealthLogger.getHealthDataLog(HEALTH_TOGGLE_PANELS);\n        togglePanelCount = (typeof togglePanelCount === 'number') ? togglePanelCount + 1 : 0;\n        HealthLogger.setHealthDataLog(HEALTH_TOGGLE_PANELS, togglePanelCount);\n    }\n\n    PreferencesManager.definePreference(PREFS_PURE_CODE, \"boolean\", false, {\n        description: Strings.DESCRIPTION_PURE_CODING_SURFACE\n    });\n\n    PreferencesManager.on(\"change\", PREFS_PURE_CODE, function () {\n        if (PreferencesManager.get(PREFS_PURE_CODE)) {\n            ViewUtils.hideMainToolBar();\n            CommandManager.execute(Commands.HIDE_SIDEBAR);\n            _hidePanelsIfRequired();\n        } else {\n            ViewUtils.showMainToolBar();\n            CommandManager.execute(Commands.SHOW_SIDEBAR);\n            _showPanelsIfRequired();\n        }\n        _updateCheckedState();\n    });\n\n    WorkspaceManager.on(WorkspaceManager.EVENT_WORKSPACE_PANEL_SHOWN, _updateLayout);\n\n    /**\n     * Register the Commands , add the Menu Items and key bindings\n     */\n    function initializeCommands() {\n        CommandManager.register(Strings.CMD_TOGGLE_PURE_CODE, CMD_TOGGLE_PURE_CODE, _togglePureCode);\n        CommandManager.register(Strings.CMD_TOGGLE_PANELS, CMD_TOGGLE_PANELS, _togglePanels);\n\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(CMD_TOGGLE_PANELS, \"\", Menus.AFTER, Commands.VIEW_HIDE_SIDEBAR);\n        Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(CMD_TOGGLE_PURE_CODE, \"\", Menus.AFTER, CMD_TOGGLE_PANELS);\n\n        KeyBindingManager.addBinding(CMD_TOGGLE_PURE_CODE, [ {key: togglePureCodeKey}, {key: togglePureCodeKeyMac, platform: \"mac\"} ]);\n\n        //default toggle panel shortcut was ctrl+shift+` as it is present in one vertical line in the keyboard. However, we later learnt\n        //from IQE team than non-English keyboards does not have the ` char. So added one more shortcut ctrl+shift+1 which will be preferred\n        KeyBindingManager.addBinding(CMD_TOGGLE_PANELS, [ {key: togglePanelsKey}, {key: togglePanelsKeyMac, platform: \"mac\"} ]);\n        KeyBindingManager.addBinding(CMD_TOGGLE_PANELS, [ {key: togglePanelsKey_EN}, {key: togglePanelsKeyMac_EN, platform: \"mac\"} ]);\n    }\n\n    initializeCommands();\n\n});\n"
  },
  {
    "path": "src/extensions/default/OpenWithExternalApplication/GraphicsFile.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n\n    var PreferencesManager   = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings              = brackets.getModule(\"strings\"),\n        StringsUtils         = brackets.getModule(\"utils/StringUtils\"),\n        ProjectManager       = brackets.getModule(\"project/ProjectManager\"),\n        Dialogs              = brackets.getModule(\"widgets/Dialogs\"),\n        DefaultDialogs       = brackets.getModule(\"widgets/DefaultDialogs\"),\n        HealthLogger            = brackets.getModule(\"utils/HealthLogger\");\n\n\n    var _requestID = 0,\n        _initialized = false;\n\n    var _graphicsFileTypes = [\"jpg\", \"jpeg\", \"png\", \"svg\", \"xd\", \"psd\", \"ai\"];\n\n    var _nodeDomain;\n\n    function init(nodeDomain) {\n\n        if (_initialized) {\n            return;\n        }\n        _initialized = true;\n\n        _nodeDomain = nodeDomain;\n\n        _nodeDomain.on('checkFileTypesInFolderResponse', function (event, response) {\n            if (response.id !== _requestID) {\n                return;\n            }\n            _graphicsFilePresentInProject(response.present);\n        });\n\n        ProjectManager.on(\"projectOpen\", function () {\n            _checkForGraphicsFileInPrjct();\n        });\n\n        _checkForGraphicsFileInPrjct();\n\n    }\n\n\n    function _checkForGraphicsFileInPrjct() {\n\n        if (PreferencesManager.getViewState(\"AssociateGraphicsFileDialogShown\")) {\n            return;\n        }\n\n        var userUuid = PreferencesManager.getViewState(\"UUID\"),\n            olderUuid = PreferencesManager.getViewState(\"OlderUUID\");\n\n        if(!(userUuid || olderUuid)) {\n            return;\n        }\n\n        _nodeDomain.exec(\"checkFileTypesInFolder\", {\n            extensions: _graphicsFileTypes.join(),\n            folder: ProjectManager.getProjectRoot().fullPath,\n            reqId: ++_requestID\n        });\n\n    }\n\n    function _graphicsFilePresentInProject(isPresent) {\n\n        if (!isPresent) {\n            return;\n        }\n\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_INFO,\n            Strings.ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_TITLE,\n            Strings.ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_MSG,\n            [\n                { className: Dialogs.DIALOG_BTN_CLASS_NORMAL, id: Dialogs.DIALOG_BTN_CANCEL,\n                    text: Strings.CANCEL\n                },\n                { className: Dialogs.DIALOG_BTN_CLASS_PRIMARY, id: Dialogs.DIALOG_BTN_OK,\n                    text: Strings.OK\n                }\n            ]\n        ).done(function (id) {\n\n            if (id !== Dialogs.DIALOG_BTN_OK) {\n                HealthLogger.sendAnalyticsData(\n                    \"externalEditorsCancelled\",\n                    \"usage\",\n                    \"externalEditors\",\n                    \"Cancelled\",\n                    \"\"\n                );\n                return;\n            }\n            HealthLogger.sendAnalyticsData(\n                \"LinkExternalEditors\",\n                \"usage\",\n                \"externalEditors\",\n                \"LinkExternalEditors\",\n                \"\"\n            );\n\n            brackets.app.getSystemDefaultApp(_graphicsFileTypes.join(), function (err, out) {\n\n                if (err) {\n                    return;\n                }\n                var associateApp = out.split(','),\n                    fileTypeToAppMap = {},\n                    AppToFileTypeMap = {};\n\n                associateApp.forEach(function (item) {\n\n                    var filetype = item.split('##')[0],\n                        app = item.split('##')[1];\n\n                    if (!filetype) {\n                        return;\n                    }\n\n                    if (filetype === \"xd\") {\n                        if (app.toLowerCase() !== \"adobe xd\" && app.toLowerCase() !== \"adobe.cc.xd\") {\n                            return;\n                        }\n                        \n                        app = \"Adobe XD\";\n                    }\n                    fileTypeToAppMap[filetype] = app;\n\n                    if (brackets.platform === \"win\" && app.toLowerCase().endsWith('.exe')) {\n                        app = app.substring(app.lastIndexOf('\\\\') + 1, app.length - 4);\n                    }\n                    if (AppToFileTypeMap[app]) {\n                        AppToFileTypeMap[app].push(filetype);\n                    } else {\n                        AppToFileTypeMap[app] = [filetype];\n                    }\n                });\n\n                var prefs = PreferencesManager.get('externalApplications');\n\n                for (var key in fileTypeToAppMap) {\n                    if (fileTypeToAppMap.hasOwnProperty(key)) {\n                        if(key && !prefs[key]) {\n                            prefs[key] = fileTypeToAppMap[key];\n                            if(brackets.platform === \"win\" && !fileTypeToAppMap[key].toLowerCase().endsWith('.exe')) {\n                                prefs[key] = \"default\";\n                            }\n                            HealthLogger.sendAnalyticsData(\n                                \"AddExternalEditorForFileType_\" + key.toUpperCase(),\n                                \"usage\",\n                                \"externalEditors\",\n                                \"AddExternalEditorForFileType_\" + key.toUpperCase(),\n                                \"\"\n                            );\n                        }\n                    }\n                }\n\n                PreferencesManager.set('externalApplications', prefs);\n\n                var str = \"\";\n                for(var app in AppToFileTypeMap) {\n                    str += AppToFileTypeMap[app].join() + \"->\" + app + \"<br/>\";\n                }\n\n                if(!str) {\n                    return;\n                }\n\n                str+=\"<br/>\";\n\n                Dialogs.showModalDialog(\n                    DefaultDialogs.DIALOG_ID_INFO,\n                    Strings.ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_TITLE,\n                    StringsUtils.format(Strings.ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_CNF_MSG, str),\n                    [\n                        { className: Dialogs.DIALOG_BTN_CLASS_PRIMARY, id: Dialogs.DIALOG_BTN_OK,\n                            text: Strings.OK\n                        }\n                    ]\n                );\n            });\n        });\n        PreferencesManager.setViewState(\"AssociateGraphicsFileDialogShown\", true);\n\n    }\n\n    exports.init = init;\n\n});\n"
  },
  {
    "path": "src/extensions/default/OpenWithExternalApplication/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n\n    var AppInit              = brackets.getModule(\"utils/AppInit\"),\n        PreferencesManager   = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings              = brackets.getModule(\"strings\"),\n        FileViewController   = brackets.getModule(\"project/FileViewController\"),\n        ExtensionUtils       = brackets.getModule(\"utils/ExtensionUtils\"),\n        NodeDomain           = brackets.getModule(\"utils/NodeDomain\"),\n        FileUtils            = brackets.getModule(\"file/FileUtils\"),\n        FileSystem           = brackets.getModule(\"filesystem/FileSystem\"),\n        GraphicsFile         = require(\"GraphicsFile\");\n\n    /**\n     * @private\n     * @type {string} fullPath of the OpenWithExternalEditor Domain implementation\n     */\n    var _domainPath = ExtensionUtils.getModulePath(module, \"node/OpenWithExternalApplicationDomain\");\n\n    /**\n     * @private\n     * @type {NodeDomain}\n     */\n    var _nodeDomain = new NodeDomain(\"OpenWithExternalApplication\", _domainPath);\n\n    var extensionToExtApplicationMap = {};\n\n    function convertUnixPathToWindowsPath(path) {\n        if (brackets.platform === \"win\" && path && FileSystem.isAbsolutePath(path)) {\n           path = path.replace(RegExp('/','g'), '\\\\');\n        }\n        return path;\n    }\n\n    function _openWithExternalApplication(event, path) {\n        _nodeDomain.exec(\"open\", {\n            path: convertUnixPathToWindowsPath(path),\n            app: extensionToExtApplicationMap[FileUtils.getFileExtension(path).toLowerCase()]\n        });\n    }\n\n    PreferencesManager.definePreference(\"externalApplications\", \"object\", {}, {\n        description: Strings.DESCRIPTION_EXTERNAL_APPLICATION_ASSOCIATE\n    });\n\n    PreferencesManager.on(\"change\", \"externalApplications\", function () {\n        extensionToExtApplicationMap = PreferencesManager.get(\"externalApplications\");\n        FileUtils.addExtensionToExternalAppList(Object.keys(extensionToExtApplicationMap));\n    });\n\n    FileViewController.on(\"openWithExternalApplication\", _openWithExternalApplication);\n\n    AppInit.appReady(function () {\n        \n        GraphicsFile.init(_nodeDomain);\n        extensionToExtApplicationMap = PreferencesManager.get(\"externalApplications\");\n        FileUtils.addExtensionToExternalAppList(Object.keys(extensionToExtApplicationMap));\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/OpenWithExternalApplication/node/OpenWithExternalApplicationDomain.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nvar open     = require(\"open\"),\n    Glob     = require(\"glob\").Glob,\n    path     = require('path');\n\nvar _domainManager;\n\n/**\n * @private\n *\n * @param {Object} params Object to use\n */\nfunction _openWithExternalApplication(params) {\n    var application =  \"default\" === params.app ? \"\": params.app;\n    open(params.path, application);\n}\n\n/**\n * @private\n *\n * @param {Object} params Object to use\n */\nfunction _checkFileTypesInFolder(params) {\n\n    var extList = params.extensions,\n        dirPath = path.normalize(params.folder),\n\n        pattern = dirPath + \"/**/*.+(\" + extList.replace(/,/g, \"|\") + \")\";\n\n    var globMgr = new Glob(pattern, function (err, matches) {\n\n        var respObj = {\n            id: params.reqId,\n            present: matches.length > 0 ? true : false\n        };\n        _domainManager.emitEvent('OpenWithExternalApplication', 'checkFileTypesInFolderResponse', [respObj]);\n    });\n\n    globMgr.on(\"match\", function() {\n        globMgr.abort();\n        var respObj = {\n            id: params.reqId,\n            present: true\n        };\n        _domainManager.emitEvent('OpenWithExternalApplication', 'checkFileTypesInFolderResponse', [respObj]);\n    });\n\n}\n\n\n/**\n * Initializes the OpenWithExternalEditor domain with its commands.\n * @param {DomainManager} domainManager The DomainManager for the server\n */\nfunction init(domainManager) {\n    _domainManager = domainManager;\n\n    if (!domainManager.hasDomain(\"OpenWithExternalApplication\")) {\n        domainManager.registerDomain(\"OpenWithExternalApplication\", {major: 0, minor: 1});\n    }\n\n    _domainManager.registerCommand(\n        \"OpenWithExternalApplication\",\n        \"open\",\n        _openWithExternalApplication,\n        true,\n        \"open document with External Application.\",\n        [{\n            name: \"params\",\n            type: \"object\",\n            description: \"Params Object having document and App Path.\"\n        }],\n        []\n    );\n\n    _domainManager.registerCommand(\n        \"OpenWithExternalApplication\",\n        \"checkFileTypesInFolder\",\n        _checkFileTypesInFolder,\n        true,\n        \"looks for File Types in a folder.\",\n        [{\n            name: \"params\",\n            type: \"object\",\n            description: \"Params Object having File Extensions and Folder Path.\"\n        }],\n        []\n    );\n\n    _domainManager.registerEvent(\n        \"OpenWithExternalApplication\",\n        \"checkFileTypesInFolderResponse\",\n        [\n            {\n                name: \"msgObj\",\n                type: \"object\",\n                description: \"json object containing message info to pass to brackets\"\n            }\n        ]\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/extensions/default/OpenWithExternalApplication/node/package.json",
    "content": "{\n  \"name\": \"brackets-open-external_application\",\n  \"dependencies\": {\n    \"open\": \"0.0.5\",\n    \"glob\": \"7.1.1\"\n  }\n}\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/CodeHintsProvider.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* eslint-disable indent */\n/* eslint max-len: [\"error\", { \"code\": 200 }]*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = brackets.getModule(\"thirdparty/lodash\");\n\n    var DefaultProviders = brackets.getModule(\"languageTools/DefaultProviders\"),\n        EditorManager = brackets.getModule('editor/EditorManager'),\n        TokenUtils = brackets.getModule(\"utils/TokenUtils\"),\n        StringMatch = brackets.getModule(\"utils/StringMatch\"),\n        matcher = new StringMatch.StringMatcher({\n            preferPrefixMatches: true\n        });\n\n    var phpSuperGlobalVariables = JSON.parse(require(\"text!phpGlobals.json\")),\n        hintType = {\n             \"2\": \"Method\",\n             \"3\": \"Function\",\n             \"4\": \"Constructor\",\n             \"6\": \"Variable\",\n             \"7\": \"Class\",\n             \"8\": \"Interface\",\n             \"9\": \"Module\",\n             \"10\": \"Property\",\n             \"14\": \"Keyword\",\n             \"21\": \"Constant\"\n        };\n\n    function CodeHintsProvider(client) {\n        this.defaultCodeHintProviders = new DefaultProviders.CodeHintsProvider(client);\n    }\n\n    CodeHintsProvider.prototype.setClient = function (client) {\n        this.defaultCodeHintProviders.setClient(client);\n    };\n\n    function setStyleAndCacheToken($hintObj, token) {\n        $hintObj.addClass('brackets-hints-with-type-details');\n        $hintObj.data('completionItem', token);\n    }\n\n    function filterWithQueryAndMatcher(hints, query) {\n        var matchResults = $.map(hints, function (hint) {\n            var searchResult = matcher.match(hint.label, query);\n            if (searchResult) {\n                for (var key in hint) {\n                    searchResult[key] = hint[key];\n                }\n            }\n\n            return searchResult;\n        });\n\n        return matchResults;\n    }\n\n    CodeHintsProvider.prototype.hasHints = function (editor, implicitChar) {\n        return this.defaultCodeHintProviders.hasHints(editor, implicitChar);\n    };\n\n    CodeHintsProvider.prototype.getHints = function (implicitChar) {\n        if (!this.defaultCodeHintProviders.client) {\n            return null;\n        }\n\n        var editor = EditorManager.getActiveEditor(),\n            pos = editor.getCursorPos(),\n            docPath = editor.document.file._path,\n            $deferredHints = $.Deferred(),\n            self = this.defaultCodeHintProviders,\n            client = this.defaultCodeHintProviders.client;\n\n        //Make sure the document is in sync with the server\n        client.notifyTextDocumentChanged({\n            filePath: docPath,\n            fileContent: editor.document.getText()\n        });\n        client.requestHints({\n            filePath: docPath,\n            cursorPos: pos\n        }).done(function (msgObj) {\n            var context = TokenUtils.getInitialContext(editor._codeMirror, pos),\n                hints = [];\n\n            self.query = context.token.string.slice(0, context.pos.ch - context.token.start);\n            if (msgObj) {\n                var res = msgObj.items || [],\n                    trimmedQuery = self.query.trim(),\n                    hasIgnoreCharacters = self.ignoreQuery.includes(implicitChar) || self.ignoreQuery.includes(trimmedQuery),\n                    isExplicitInvokation = implicitChar === null;\n\n                // There is a bug in Php Language Server, Php Language Server does not provide superGlobals\n                // Variables as completion. so these variables are being explicity put in response objects\n                // below code should be removed if php server fix this bug.\n                if((isExplicitInvokation || trimmedQuery) && !hasIgnoreCharacters) {\n                    for(var key in phpSuperGlobalVariables) {\n                        res.push({\n                            label: key,\n                            documentation: phpSuperGlobalVariables[key].description,\n                            detail: phpSuperGlobalVariables[key].type\n                        });\n                    }\n                }\n\n                var filteredHints = [];\n                if (hasIgnoreCharacters || (isExplicitInvokation && !trimmedQuery)) {\n                    filteredHints = filterWithQueryAndMatcher(res, \"\");\n                } else {\n                    filteredHints = filterWithQueryAndMatcher(res, self.query);\n                }\n\n                StringMatch.basicMatchSort(filteredHints);\n                filteredHints.forEach(function (element) {\n                    var $fHint = $(\"<span>\")\n                        .addClass(\"brackets-hints\");\n\n                    if (element.stringRanges) {\n                        element.stringRanges.forEach(function (item) {\n                            if (item.matched) {\n                                $fHint.append($(\"<span>\")\n                                    .append(_.escape(item.text))\n                                    .addClass(\"matched-hint\"));\n                            } else {\n                                $fHint.append(_.escape(item.text));\n                            }\n                        });\n                    } else {\n                        $fHint.text(element.label);\n                    }\n\n                    $fHint.data(\"token\", element);\n                    setStyleAndCacheToken($fHint, element);\n                    hints.push($fHint);\n                });\n            }\n\n            var token = self.query;\n            $deferredHints.resolve({\n                \"hints\": hints,\n                \"enableDescription\": true,\n                \"selectInitial\": token && /\\S/.test(token) && isNaN(parseInt(token, 10)) // If the active token is blank then don't put default selection\n            });\n        }).fail(function () {\n            $deferredHints.reject();\n        });\n\n        return $deferredHints;\n    };\n\n    CodeHintsProvider.prototype.insertHint = function ($hint) {\n        return this.defaultCodeHintProviders.insertHint($hint);\n    };\n\n    CodeHintsProvider.prototype.updateHintDescription = function ($hint, $hintDescContainer) {\n        var $hintObj = $hint.find('.brackets-hints-with-type-details'),\n            token = $hintObj.data('completionItem'),\n            $desc = $('<div>');\n\n        if(!token) {\n            $hintDescContainer.empty();\n            return;\n        }\n\n        if (token.detail) {\n            if (token.detail.trim() !== '?') {\n                $('<div>' + token.detail.split('->').join(':').toString().trim() + '</div>').appendTo($desc).addClass(\"codehint-desc-type-details\");\n            }\n        } else {\n            if (hintType[token.kind]) {\n                $('<div>' + hintType[token.kind] + '</div>').appendTo($desc).addClass(\"codehint-desc-type-details\");\n            }\n        }\n        if (token.documentation) {\n            $('<div></div>').html(token.documentation.trim()).appendTo($desc).addClass(\"codehint-desc-documentation\");\n        }\n\n        //To ensure CSS reflow doesn't cause a flicker.\n        $hintDescContainer.empty();\n        $hintDescContainer.append($desc);\n    };\n\n    exports.CodeHintsProvider = CodeHintsProvider;\n});\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/PHPSymbolProviders.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*eslint no-invalid-this: 0, max-len: 0*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager = brackets.getModule(\"editor/EditorManager\"),\n        QuickOpen = brackets.getModule(\"search/QuickOpen\"),\n        Commands = brackets.getModule(\"command/Commands\"),\n        CommandManager = brackets.getModule(\"command/CommandManager\"),\n        PathConverters = brackets.getModule(\"languageTools/PathConverters\");\n\n    var SymbolKind = QuickOpen.SymbolKind;\n\n    function setClient(client) {\n        if (client) {\n            this.client = client;\n        }\n    }\n\n    function convertRangePosToEditorPos(rangePos) {\n        return {\n            line: rangePos.line,\n            ch: rangePos.character\n        };\n    }\n\n    function SymbolInformation(label, fullPath, selectionRange, type, scope, isDocumentSymbolRequest) {\n        this.label = label;\n        this.fullPath = fullPath;\n        this.selectionRange = selectionRange;\n        this.type = type;\n        this.scope = scope;\n        this.isDocumentSymbolRequest = isDocumentSymbolRequest;\n    }\n\n    function createList(list, isDocumentSymbolRequest) {\n        var newlist = [];\n        for (var i = 0; i < list.length; i++) {\n            var symbolInfo = list[i],\n                label = symbolInfo.name,\n                type = SymbolKind[symbolInfo.kind.toString()],\n                fullPath = null,\n                selectionRange = null,\n                scope = symbolInfo.containerName,\n                range = null;\n\n            if (!isDocumentSymbolRequest) {\n                fullPath = PathConverters.uriToPath(symbolInfo.location.uri);\n            } else {\n                if (symbolInfo.selectionRange) {\n                    range = symbolInfo.selectionRange;\n                    selectionRange = {\n                        from: convertRangePosToEditorPos(range.start),\n                        to: convertRangePosToEditorPos(range.end)\n                    };\n                }\n            }\n\n            if (!selectionRange) {\n                range = symbolInfo.location.range;\n                selectionRange = {\n                    from: convertRangePosToEditorPos(range.start),\n                    to: convertRangePosToEditorPos(range.end)\n                };\n            }\n\n            newlist.push(new SymbolInformation(label, fullPath, selectionRange, type, scope, isDocumentSymbolRequest));\n        }\n\n        return newlist;\n    }\n\n    function transFormToSymbolList(query, matcher, results, isDocumentSymbolRequest) {\n        var list = createList(results, isDocumentSymbolRequest);\n\n        // Filter and rank how good each match is\n        var filteredList = $.map(list, function (symbolInfo) {\n            var searchResult = matcher.match(symbolInfo.label, query);\n            if (searchResult) {\n                searchResult.symbolInfo = symbolInfo;\n            }\n            return searchResult;\n        });\n\n        // Sort based on ranking & basic alphabetical order\n        QuickOpen.basicMatchSort(filteredList);\n\n        return filteredList;\n    }\n\n    /**\n     * Provider for Document Symbols\n     */\n    function DocumentSymbolsProvider(client) {\n        this.client = client;\n    }\n\n    DocumentSymbolsProvider.prototype.setClient = setClient;\n\n    DocumentSymbolsProvider.prototype.match = function (query) {\n        return query.startsWith(\"@\");\n    };\n\n    DocumentSymbolsProvider.prototype.search = function (query, matcher) {\n        if (!this.client) {\n            return $.Deferred().reject();\n        }\n\n        var serverCapabilities = this.client.getServerCapabilities();\n        if (!serverCapabilities || !serverCapabilities.documentSymbolProvider) {\n            return $.Deferred().reject();\n        }\n\n        var editor = EditorManager.getActiveEditor(),\n            docPath = editor.document.file._path,\n            retval = $.Deferred();\n        query = query.slice(1);\n\n        this.client.requestSymbolsForDocument({\n            filePath: docPath\n        }).done(function (results) {\n            var resultList = transFormToSymbolList(query, matcher, results, true);\n            retval.resolve(resultList);\n        });\n\n        return retval;\n    };\n\n    DocumentSymbolsProvider.prototype.itemFocus = function (selectedItem, query, explicit) {\n        if (!selectedItem || (query.length < 2 && !explicit)) {\n            return;\n        }\n\n        var range = selectedItem.symbolInfo.selectionRange;\n        EditorManager.getCurrentFullEditor().setSelection(range.from, range.to, true);\n    };\n\n    DocumentSymbolsProvider.prototype.itemSelect = function (selectedItem, query) {\n        this.itemFocus(selectedItem, query, true);\n    };\n\n    DocumentSymbolsProvider.prototype.resultsFormatter = function (item, query) {\n        var displayName = QuickOpen.highlightMatch(item);\n        query = query.slice(1);\n\n        if (item.symbolInfo.scope) {\n            return \"<li>\" + displayName + \" (\" + item.symbolInfo.type + \")\" + \"<br /><span class='quick-open-path'>\" + item.symbolInfo.scope + \"</span></li>\";\n        }\n        return \"<li>\" + displayName + \" (\" + item.symbolInfo.type + \")\" + \"</li>\";\n    };\n\n    /**\n     * Provider for Project Symbols\n     */\n    function ProjectSymbolsProvider(client) {\n        this.client = client;\n    }\n\n    ProjectSymbolsProvider.prototype.setClient = setClient;\n\n    ProjectSymbolsProvider.prototype.match = function (query) {\n        return query.startsWith(\"#\");\n    };\n\n    ProjectSymbolsProvider.prototype.search = function (query, matcher) {\n        if (!this.client) {\n            return $.Deferred().reject();\n        }\n\n        var serverCapabilities = this.client.getServerCapabilities();\n        if (!serverCapabilities || !serverCapabilities.workspaceSymbolProvider) {\n            return $.Deferred().reject();\n        }\n\n        var retval = $.Deferred();\n        query = query.slice(1);\n\n        this.client.requestSymbolsForWorkspace({\n            query: query\n        }).done(function (results) {\n            var resultList = transFormToSymbolList(query, matcher, results);\n            retval.resolve(resultList);\n        });\n\n        return retval;\n    };\n\n    ProjectSymbolsProvider.prototype.itemFocus = function (selectedItem, query, explicit) {\n        if (!selectedItem || (query.length < 2 && !explicit)) {\n            return;\n        }\n    };\n\n    ProjectSymbolsProvider.prototype.itemSelect = function (selectedItem, query) {\n        var fullPath = selectedItem.symbolInfo.fullPath,\n            range = selectedItem.symbolInfo.selectionRange;\n\n        if (fullPath) {\n            CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {\n                fullPath: fullPath\n            })\n                .done(function () {\n                    if (range.from) {\n                        var editor = EditorManager.getCurrentFullEditor();\n                        editor.setCursorPos(range.from.line, range.from.ch, true);\n                    }\n                });\n        }\n    };\n\n    ProjectSymbolsProvider.prototype.resultsFormatter = function (item, query) {\n        var displayName = QuickOpen.highlightMatch(item);\n        query = query.slice(1);\n\n        if (item.symbolInfo.scope) {\n            return \"<li>\" + displayName + \" (\" + item.symbolInfo.type + \")\" + \"<br /><span class='quick-open-path'>\" + item.symbolInfo.scope + \"</span><br /><br /><span class='quick-open-path'>\" + item.symbolInfo.fullPath + \"</span></li>\";\n        }\n        return \"<li>\" + displayName + \" (\" + item.symbolInfo.type + \")\" + \"<br /><br /><span class='quick-open-path'>\" + item.symbolInfo.fullPath + \"</span></li>\";\n    };\n\n    exports.SymbolProviders = {\n        DocumentSymbolsProvider: DocumentSymbolsProvider,\n        ProjectSymbolsProvider: ProjectSymbolsProvider\n    };\n});\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/client.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n/*global exports */\n/*global process */\n/*eslint-env es6, node*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\n\"use strict\";\n\nvar LanguageClient = require(global.LanguageClientInfo.languageClientPath).LanguageClient,\n    net = require(\"net\"),\n    cp = require(\"child_process\"),\n    execa = require(\"execa\"),\n    semver = require('semver'),\n    clientName = \"PhpClient\",\n    executablePath = \"\",\n    memoryLimit = \"\";\n\nfunction validatePhpExecutable(confParams) {\n    executablePath = confParams[\"executablePath\"] ||\n        (process.platform === 'win32' ? 'php.exe' : 'php');\n\n    memoryLimit = confParams[\"memoryLimit\"] || '4095M';\n\n    return new Promise(function (resolve, reject) {\n        if (memoryLimit !== '-1' && !/^\\d+[KMG]?$/.exec(memoryLimit)) {\n            reject(\"PHP_SERVER_MEMORY_LIMIT_INVALID\");\n            return;\n        }\n\n        execa.stdout(executablePath, ['--version']).then(function (output) {\n            var matchStr = output.match(/^PHP ([^\\s]+)/m);\n            if (!matchStr) {\n                reject(\"PHP_VERSION_INVALID\");\n                return;\n            }\n            var version = matchStr[1].split('-')[0];\n            if (!/^\\d+.\\d+.\\d+$/.test(version)) {\n                version = version.replace(/(\\d+.\\d+.\\d+)/, '$1-');\n            }\n            if (semver.lt(version, '7.0.0')) {\n                reject([\"PHP_UNSUPPORTED_VERSION\", version]);\n                return;\n            }\n            resolve();\n        }).catch(function (err) {\n            if (err.code === 'ENOENT') {\n                reject(\"PHP_EXECUTABLE_NOT_FOUND\");\n            } else {\n                reject([\"PHP_PROCESS_SPAWN_ERROR\", err.code]);\n                console.error(err);\n            }\n            return;\n        });\n    });\n}\n\nvar serverOptions = function () {\n        return new Promise(function (resolve, reject) {\n            var server = net.createServer(function (socket) {\n                console.log('PHP process connected');\n                socket.on('end', function () {\n                    console.log('PHP process disconnected');\n                });\n                server.close();\n                resolve({\n                    reader: socket,\n                    writer: socket\n                });\n            });\n            server.listen(0, '127.0.0.1', function () {\n                var pathToPHP = __dirname + \"/vendor/felixfbecker/language-server/bin/php-language-server.php\";\n                var childProcess = cp.spawn(executablePath, [\n                    pathToPHP,\n                    '--tcp=127.0.0.1:' + server.address().port,\n                    '--memory-limit=' + memoryLimit\n                ]);\n                childProcess.stderr.on('data', function (chunk) {\n                    var str = chunk.toString();\n                    console.log('PHP Language Server:', str);\n                });\n                childProcess.on('exit', function (code, signal) {\n                    console.log(\n                        \"Language server exited \" + (signal ? \"from signal \" + signal : \"with exit code \" + code)\n                    );\n                });\n                return childProcess;\n            });\n        });\n    },\n    options = {\n        serverOptions: serverOptions\n    };\n\n\nfunction init(domainManager) {\n    var client = new LanguageClient(clientName, domainManager, options);\n    client.addOnRequestHandler('validatePhpExecutable', validatePhpExecutable);\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/composer.json",
    "content": "{\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true,\n    \"require\": {\n        \"felixfbecker/language-server\": \"^5.4\"\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/main.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var LanguageTools = brackets.getModule(\"languageTools/LanguageTools\"),\n        ClientLoader = brackets.getModule(\"languageTools/ClientLoader\"),\n        AppInit = brackets.getModule(\"utils/AppInit\"),\n        ExtensionUtils = brackets.getModule(\"utils/ExtensionUtils\"),\n        ProjectManager = brackets.getModule(\"project/ProjectManager\"),\n        EditorManager =  brackets.getModule(\"editor/EditorManager\"),\n        LanguageManager =  brackets.getModule(\"language/LanguageManager\"),\n        CodeHintManager = brackets.getModule(\"editor/CodeHintManager\"),\n        QuickOpen = brackets.getModule(\"search/QuickOpen\"),\n        ParameterHintManager = brackets.getModule(\"features/ParameterHintsManager\"),\n        JumpToDefManager = brackets.getModule(\"features/JumpToDefManager\"),\n        FindReferencesManager = brackets.getModule(\"features/FindReferencesManager\"),\n        CodeInspection = brackets.getModule(\"language/CodeInspection\"),\n        DefaultProviders = brackets.getModule(\"languageTools/DefaultProviders\"),\n        CodeHintsProvider = require(\"CodeHintsProvider\").CodeHintsProvider,\n        SymbolProviders = require(\"PHPSymbolProviders\").SymbolProviders,\n        DefaultEventHandlers = brackets.getModule(\"languageTools/DefaultEventHandlers\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings             = brackets.getModule(\"strings\"),\n        Dialogs             = brackets.getModule(\"widgets/Dialogs\"),\n        DefaultDialogs      = brackets.getModule(\"widgets/DefaultDialogs\"),\n        Commands               = brackets.getModule(\"command/Commands\"),\n        CommandManager         = brackets.getModule(\"command/CommandManager\"),\n        StringUtils             = brackets.getModule(\"utils/StringUtils\");\n\n    var clientFilePath = ExtensionUtils.getModulePath(module, \"client.js\"),\n        clientName = \"PhpClient\",\n        _client = null,\n        evtHandler,\n        phpConfig = {\n            enablePhpTooling: true,\n            executablePath: \"php\",\n            memoryLimit: \"4095M\",\n            validateOnType: \"false\"\n        },\n        DEBUG_OPEN_PREFERENCES_IN_SPLIT_VIEW  = \"debug.openPrefsInSplitView\",\n        phpServerRunning = false,\n        serverCapabilities,\n        currentRootPath,\n        chProvider = null,\n        phProvider = null,\n        lProvider = null,\n        jdProvider = null,\n        dSymProvider = null,\n        pSymProvider = null,\n        refProvider = null,\n        providersRegistered = false;\n\n    PreferencesManager.definePreference(\"php\", \"object\", phpConfig, {\n        description: Strings.DESCRIPTION_PHP_TOOLING_CONFIGURATION\n    });\n\n    PreferencesManager.on(\"change\", \"php\", function () {\n        var newPhpConfig = PreferencesManager.get(\"php\");\n\n        if (lProvider && newPhpConfig[\"validateOnType\"] !== phpConfig[\"validateOnType\"]) {\n            lProvider._validateOnType = !(newPhpConfig[\"validateOnType\"] === \"false\");\n        }\n        if ((newPhpConfig[\"executablePath\"] !== phpConfig[\"executablePath\"])\n                || (newPhpConfig[\"enablePhpTooling\"] !== phpConfig[\"enablePhpTooling\"])) {\n            phpConfig = newPhpConfig;\n            runPhpServer();\n            return;\n        }\n        phpConfig = newPhpConfig;\n    });\n\n    var handleProjectOpen = function (event, directory) {\n        lProvider.clearExistingResults();\n        if(serverCapabilities[\"workspace\"] && serverCapabilities[\"workspace\"][\"workspaceFolders\"]) {\n            _client.notifyProjectRootsChanged({\n                foldersAdded: [directory.fullPath],\n                foldersRemoved: [currentRootPath]\n            });\n            currentRootPath = directory.fullPath;\n        } else {\n            _client.restart({\n                rootPath: directory.fullPath\n            }).done(handlePostPhpServerStart);\n        }\n    };\n\n    function resetClientInProviders() {\n        var logErr = \"PhpTooling: Can't reset client for : \";\n        chProvider ? chProvider.setClient(_client) : console.log(logErr, \"CodeHintsProvider\");\n        phProvider ? phProvider.setClient(_client) : console.log(logErr, \"ParameterHintsProvider\");\n        jdProvider ? jdProvider.setClient(_client) : console.log(logErr, \"JumpToDefProvider\");\n        dSymProvider ? dSymProvider.setClient(_client) : console.log(logErr, \"DocumentSymbolsProvider\");\n        pSymProvider ? pSymProvider.setClient(_client) : console.log(logErr, \"ProjectSymbolsProvider\");\n        refProvider ? refProvider.setClient(_client) : console.log(logErr, \"FindReferencesProvider\");\n        lProvider ? lProvider.setClient(_client) : console.log(logErr, \"LintingProvider\");\n        _client.addOnCodeInspection(lProvider.setInspectionResults.bind(lProvider));\n    }\n\n    function registerToolingProviders() {\n        chProvider = new CodeHintsProvider(_client),\n        phProvider = new DefaultProviders.ParameterHintsProvider(_client),\n        lProvider = new DefaultProviders.LintingProvider(_client),\n        jdProvider = new DefaultProviders.JumpToDefProvider(_client);\n        dSymProvider = new SymbolProviders.DocumentSymbolsProvider(_client);\n        pSymProvider = new SymbolProviders.ProjectSymbolsProvider(_client);\n        refProvider = new DefaultProviders.ReferencesProvider(_client);\n\n        JumpToDefManager.registerJumpToDefProvider(jdProvider, [\"php\"], 0);\n        CodeHintManager.registerHintProvider(chProvider, [\"php\"], 0);\n        ParameterHintManager.registerHintProvider(phProvider, [\"php\"], 0);\n        FindReferencesManager.registerFindReferencesProvider(refProvider, [\"php\"], 0);\n        FindReferencesManager.setMenuItemStateForLanguage();\n        CodeInspection.register([\"php\"], {\n            name: \"\",\n            scanFileAsync: lProvider.getInspectionResultsAsync.bind(lProvider)\n        });\n        //Attach plugin for Document Symbols\n        QuickOpen.addQuickOpenPlugin({\n            name: \"PHP Document Symbols\",\n            label: Strings.CMD_FIND_DOCUMENT_SYMBOLS + \"\\u2026\",\n            languageIds: [\"php\"],\n            search: dSymProvider.search.bind(dSymProvider),\n            match: dSymProvider.match.bind(dSymProvider),\n            itemFocus: dSymProvider.itemFocus.bind(dSymProvider),\n            itemSelect: dSymProvider.itemSelect.bind(dSymProvider),\n            resultsFormatter: dSymProvider.resultsFormatter.bind(dSymProvider)\n        });\n        CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(true);\n        //Attach plugin for Project Symbols\n        QuickOpen.addQuickOpenPlugin({\n            name: \"PHP Project Symbols\",\n            label: Strings.CMD_FIND_PROJECT_SYMBOLS + \"\\u2026\",\n            languageIds: [\"php\"],\n            search: pSymProvider.search.bind(pSymProvider),\n            match: pSymProvider.match.bind(pSymProvider),\n            itemFocus: pSymProvider.itemFocus.bind(pSymProvider),\n            itemSelect: pSymProvider.itemSelect.bind(pSymProvider),\n            resultsFormatter: pSymProvider.resultsFormatter.bind(pSymProvider)\n        });\n        CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(true);\n\n        _client.addOnCodeInspection(lProvider.setInspectionResults.bind(lProvider));\n\n        providersRegistered = true;\n    }\n\n    function addEventHandlers() {\n        _client.addOnLogMessage(function () {});\n        _client.addOnShowMessage(function () {});\n        evtHandler = new DefaultEventHandlers.EventPropagationProvider(_client);\n        evtHandler.registerClientForEditorEvent();\n\n\n        if (phpConfig[\"validateOnType\"] !== \"false\") {\n            lProvider._validateOnType = true;\n        }\n\n        _client.addOnProjectOpenHandler(handleProjectOpen);\n    }\n\n    function validatePhpExecutable() {\n        var result = $.Deferred();\n\n        _client.sendCustomRequest({\n            messageType: \"brackets\",\n            type: \"validatePhpExecutable\",\n            params: phpConfig\n        }).done(result.resolve).fail(result.reject);\n\n        return result;\n    }\n\n    function showErrorPopUp(err) {\n        if(!err) {\n            return;\n        }\n        var localizedErrStr = \"\";\n        if (typeof (err) === \"string\") {\n            localizedErrStr = Strings[err];\n        } else {\n            localizedErrStr = StringUtils.format(Strings[err[0]], err[1]);\n        }\n        if(!localizedErrStr) {\n            console.error(\"Php Tooling Error: \" + err);\n            return;\n        }\n        var Buttons = [\n            { className: Dialogs.DIALOG_BTN_CLASS_NORMAL, id: Dialogs.DIALOG_BTN_CANCEL,\n                text: Strings.CANCEL },\n            { className: Dialogs.DIALOG_BTN_CLASS_PRIMARY, id: Dialogs.DIALOG_BTN_DOWNLOAD,\n                text: Strings.OPEN_PREFERENNCES}\n        ];\n        Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.PHP_SERVER_ERROR_TITLE,\n            localizedErrStr,\n            Buttons\n        ).done(function (id) {\n            if (id === Dialogs.DIALOG_BTN_DOWNLOAD) {\n                if (CommandManager.get(DEBUG_OPEN_PREFERENCES_IN_SPLIT_VIEW)) {\n                    CommandManager.execute(DEBUG_OPEN_PREFERENCES_IN_SPLIT_VIEW);\n                } else {\n                    CommandManager.execute(Commands.CMD_OPEN_PREFERENCES);\n                }\n            }\n        });\n    }\n\n    function handlePostPhpServerStart() {\n        if (!phpServerRunning) {\n            phpServerRunning = true;\n\n            if (providersRegistered) {\n                resetClientInProviders();\n            } else {\n                registerToolingProviders();\n            }\n\n            addEventHandlers();\n            EditorManager.off(\"activeEditorChange.php\");\n            LanguageManager.off(\"languageModified.php\");\n        }\n        evtHandler.handleActiveEditorChange(null, EditorManager.getActiveEditor());\n        currentRootPath = ProjectManager.getProjectRoot()._path;\n    }\n\n    function runPhpServer() {\n        if (_client && phpConfig[\"enablePhpTooling\"]) {\n            validatePhpExecutable()\n                .done(function () {\n                    var startFunc = _client.start.bind(_client);\n                    if (phpServerRunning) {\n                        startFunc = _client.restart.bind(_client);\n                    }\n                    currentRootPath = ProjectManager.getProjectRoot()._path;\n                    startFunc({\n                        rootPath: currentRootPath\n                    }).done(function (result) {\n                        console.log(\"php Language Server started\");\n                        serverCapabilities = result.capabilities;\n                        handlePostPhpServerStart();\n                    });\n                }).fail(showErrorPopUp);\n        }\n    }\n\n    function activeEditorChangeHandler(event, current) {\n        if (current) {\n            var language = current.document.getLanguage();\n            if (language.getId() === \"php\") {\n                runPhpServer();\n                EditorManager.off(\"activeEditorChange.php\");\n                LanguageManager.off(\"languageModified.php\");\n            }\n        }\n    }\n\n    function languageModifiedHandler(event, language) {\n        if (language && language.getId() === \"php\") {\n            runPhpServer();\n            EditorManager.off(\"activeEditorChange.php\");\n            LanguageManager.off(\"languageModified.php\");\n        }\n    }\n\n    function initiateService(evt, onAppReady) {\n        if (onAppReady) {\n            console.log(\"Php tooling: Starting the service\");\n        } else {\n            console.log(\"Php tooling: Something went wrong. Restarting the service\");\n        }\n\n        phpServerRunning = false;\n        LanguageTools.initiateToolingService(clientName, clientFilePath, ['php']).done(function (client) {\n            _client = client;\n            //Attach only once\n            EditorManager.off(\"activeEditorChange.php\");\n            EditorManager.on(\"activeEditorChange.php\", activeEditorChangeHandler);\n            //Attach only once\n            LanguageManager.off(\"languageModified.php\");\n            LanguageManager.on(\"languageModified.php\", languageModifiedHandler);\n            activeEditorChangeHandler(null, EditorManager.getActiveEditor());\n        });\n    }\n\n    AppInit.appReady(function () {\n        initiateService(null, true);\n        ClientLoader.on(\"languageClientModuleInitialized\", initiateService);\n    });\n\n    //Only for Unit testing\n    exports.getClient = function() { return _client; };\n});\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/package.json",
    "content": "{\n  \"name\": \"php-Tooling\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Advanced Tooling support for PHP\",\n  \"author\": \"niteskum\",\n  \"main\": \"main.js\",\n  \"scripts\": {\n    \"postinstall\": \"composer require felixfbecker/language-server && composer run-script --working-dir=vendor/felixfbecker/language-server parse-stubs\"\n  },\n  \"dependencies\": {\n    \"execa\": \"1.0.0\",\n    \"semver\": \"5.6.0\"\n  }\n}\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/phpGlobals.json",
    "content": "{\n\t\"$GLOBALS\": {\n\t\t\"description\": \"An associative array containing references to all variables which are currently defined in the global scope of the script. The variable names are the keys of the array.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_SERVER\": {\n\t\t\"description\": \"$_SERVER is an array containing information such as headers, paths, and script locations. The entries in this array are created by the web server. There is no guarantee that every web server will provide any of these; servers may omit some, or provide others not listed here. That said, a large number of these variables are accounted for in the CGI/1.1 specification, so you should be able to expect those.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_GET\": {\n\t\t\"description\": \"An associative array of variables passed to the current script via the URL parameters.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_POST\": {\n\t\t\"description\": \"An associative array of variables passed to the current script via the HTTP POST method.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_FILES\": {\n\t\t\"description\": \"An associative array of items uploaded to the current script via the HTTP POST method.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_REQUEST\": {\n\t\t\"description\": \"An associative array that by default contains the contents of $_GET, $_POST and $_COOKIE.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_SESSION\": {\n\t\t\"description\": \"An associative array containing session variables available to the current script. See the Session functions documentation for more information on how this is used.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_ENV\": {\n\t\t\"description\": \"An associative array of variables passed to the current script via the environment method. \\r\\n\\r\\nThese variables are imported into PHP\\\"s global namespace from the environment under which the PHP parser is running. Many are provided by the shell under which PHP is running and different systems are likely running different kinds of shells, a definitive list is impossible. Please see your shell\\\"s documentation for a list of defined environment variables. \\r\\n\\r\\nOther environment variables include the CGI variables, placed there regardless of whether PHP is running as a server module or CGI processor.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$_COOKIE\": {\n\t\t\"description\": \"An associative array of variables passed to the current script via HTTP Cookies.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$php_errormsg\": {\n\t\t\"description\": \"$php_errormsg is a variable containing the text of the last error message generated by PHP. This variable will only be available within the scope in which the error occurred, and only if the track_errors configuration option is turned on (it defaults to off).\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$HTTP_RAW_POST_DATA\": {\n\t\t\"description\": \"$HTTP_RAW_POST_DATA contains the raw POST data. See always_populate_raw_post_data\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$http_response_header\": {\n\t\t\"description\": \"The $http_response_header array is similar to the get_headers() function. When using the HTTP wrapper, $http_response_header will be populated with the HTTP response headers. $http_response_header will be created in the local scope.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$argc\": {\n\t\t\"description\": \"Contains the number of arguments passed to the current script when running from the command line.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$argv\": {\n\t\t\"description\": \"Contains an array of all the arguments passed to the script when running from the command line.\",\n\t\t\"type\": \"array\"\n\t},\n\t\"$this\": {\n\t\t\"description\": \"Refers to the current object\",\n\t\t\"type\": \"array\"\n\t},\n\t\"parent\": {\n\t\t\"description\": \"\",\n\t\t\"type\": \"\"\n\t},\n\t\"self\": {\n\t\t\"description\": \"\",\n\t\t\"type\": \"\"\n\t},\n\t\"_destruct\": {\n\t\t\"description\": \"\",\n\t\t\"type\": \"\"\n\t}\n\n}"
  },
  {
    "path": "src/extensions/default/PhpTooling/unittest-files/test/test1.php",
    "content": "<?php\necho \"Hello World!\""
  },
  {
    "path": "src/extensions/default/PhpTooling/unittest-files/test/test2.php",
    "content": "<?php\n\n$x = 75;\n\n$x = 34;\n\nnamespace test;\nabstract class TestCase extends testA\n{\n    use testA;\n}\n\n$A11 = 23;\n$A12 = 34;\n$A13 = 45;\n$A1\n\nfo\n\n    \n$\n\nfunction watchparameterhint() {\n    echo \"Hello World!\";\n}\n$A11()\nfopen(\"\",)\nwatchparameterhint()\n    \n\nfunction watchReferences() {\n    echo \"Hello World!\";\n}\n\nwatchReferences();\n\nwatchReferences();\n\n\nfunction ReferencesInMultipleFile() {\n    echo \"Hello World!\";\n}\n\nReferencesInMultipleFile();\n\nReferencesInMultipleFile();\n?>\n"
  },
  {
    "path": "src/extensions/default/PhpTooling/unittest-files/test/test3.php",
    "content": "<?php\n\nnamespace test;\n\nclass testA\n{\n    protected $B = [\n        'A1', 'A2'\n    ];\n}\n\nReferencesInMultipleFile();"
  },
  {
    "path": "src/extensions/default/PhpTooling/unittest-files/test/test4.php",
    "content": "<?php\n\nclass MyClass{\n    public static $staticValue = 'static';\n    const constantValue = 'const';\n    public $publicValue = 'public';\n    public static function staticMethod(){}\n    public function publicFunction(){}\n}\n    \n$myclass = new MyClass();\n\n?>"
  },
  {
    "path": "src/extensions/default/PhpTooling/unittests.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n/*global describe, runs, beforeEach, it, expect, waitsFor, waitsForDone, beforeFirst, afterLast */\ndefine(function (require, exports, module) {\n    'use strict';\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        Strings         = brackets.getModule(\"strings\"),\n        FileUtils       = brackets.getModule(\"file/FileUtils\"),\n        StringUtils     = brackets.getModule(\"utils/StringUtils\"),\n        StringMatch     = brackets.getModule(\"utils/StringMatch\");\n\n    var extensionRequire,\n        phpToolingExtension,\n        testWindow,\n        $,\n        PreferencesManager,\n        CodeInspection,\n        DefaultProviders,\n        CodeHintsProvider,\n        SymbolProviders,\n        EditorManager,\n        testEditor,\n        testFolder = FileUtils.getNativeModuleDirectoryPath(module) + \"/unittest-files/\",\n        testFile1 = \"test1.php\",\n        testFile2 =  \"test2.php\",\n        testFile4 =  \"test4.php\";\n\n    describe(\"PhpTooling\", function () {\n\n        beforeFirst(function () {\n\n            // Create a new window that will be shared by ALL tests in this spec.\n            SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                testWindow = w;\n                $ = testWindow.$;\n                var brackets = testWindow.brackets;\n                extensionRequire = brackets.test.ExtensionLoader.getRequireContextForExtension(\"PhpTooling\");\n                phpToolingExtension = extensionRequire(\"main\");\n            });\n        });\n\n        afterLast(function () {\n            waitsForDone(phpToolingExtension.getClient().stop(), \"stoping php server\");\n            testEditor       = null;\n            testWindow       = null;\n            brackets         = null;\n            EditorManager    = null;\n            SpecRunnerUtils.closeTestWindow();\n        });\n\n\n        beforeEach(function () {\n            EditorManager      = testWindow.brackets.test.EditorManager;\n            PreferencesManager = testWindow.brackets.test.PreferencesManager;\n            CodeInspection = testWindow.brackets.test.CodeInspection;\n            CodeInspection.toggleEnabled(true);\n            DefaultProviders = testWindow.brackets.getModule(\"languageTools/DefaultProviders\");\n            CodeHintsProvider = extensionRequire(\"CodeHintsProvider\");\n            SymbolProviders = extensionRequire(\"PHPSymbolProviders\").SymbolProviders;\n        });\n\n        /**\n         * Does a busy wait for a given number of milliseconds\n         * @param {Number} milliSeconds - number of milliSeconds to wait\n         */\n        function waitForMilliSeconds(milliSeconds) {\n            var flag = false;\n\n            setTimeout(function () {\n                flag = true;\n            }, milliSeconds);\n\n            waitsFor(function () {\n                return flag;\n            }, \"This should not fail. Please check the timeout values.\",\n                milliSeconds + 10); // We give 10 milliSeconds as grace period\n        }\n\n        /**\n         * Check the presence of a Button in Error Prompt\n         * @param {String} btnId - \"CANCEL\" or \"OPEN\"\n         */\n        function checkPopUpButton(clickbtnId) {\n            var doc = $(testWindow.document),\n                errorPopUp = doc.find(\".error-dialog.instance\"),\n                btn = errorPopUp.find('.dialog-button');\n\n            // Test if the update bar button has been displayed.\n            expect(btn.length).toBe(2);\n            if (clickbtnId) {\n                clickButton(clickbtnId);\n            }\n        }\n\n        /**\n         * Check the presence of a Button in Error Prompt\n         * @param {String} btnId - Button OPEN or Cancel Button\n         */\n        function clickButton(btnId) {\n            var doc = $(testWindow.document),\n                errorPopUp = doc.find(\".error-dialog.instance\"),\n                btn = errorPopUp.find('.dialog-button'),\n                openBtn,\n                cancelBtn,\n                clickBtn;\n            if (btn[0].classList.contains(\"primary\")) {\n                openBtn = btn[0];\n                cancelBtn = btn[1];\n            }\n\n            if (btn[1].classList.contains(\"primary\")) {\n                openBtn = btn[1];\n                cancelBtn = btn[0];\n            }\n            clickBtn = cancelBtn;\n\n            if(btnId === \"OPEN\") {\n                clickBtn = openBtn;\n            }\n\n            if(clickBtn) {\n                clickBtn.click();\n                waitForMilliSeconds(3000);\n                runs(function() {\n                    expect(doc.find(\".error-dialog.instance\").length).toBe(0);\n                });\n            }\n        }\n\n        /**\n         * Check the presence of Error Prompt String on Brackets Window\n         * @param {String} title - Title String Which will be matched with Update Bar heading.\n         * @param {String} description - description String Which will be matched with Update Bar description.\n         */\n        function checkPopUpString(title, titleDescription) {\n            var doc = $(testWindow.document),\n                errorPopUp = doc.find(\".error-dialog.instance\"),\n                heading = errorPopUp.find('.dialog-title'),\n                description = errorPopUp.find('.dialog-message');\n\n            // Test if the update bar has been displayed.\n            //expect(errorPopUp.length).toBe(1);\n            if (title) {\n                expect(heading.text()).toBe(title);\n            }\n            if (titleDescription) {\n                expect(description.text()).toBe(titleDescription);\n            }\n        }\n\n        function toggleDiagnosisResults(visible) {\n            var doc = $(testWindow.document),\n                problemsPanel = doc.find(\"#problems-panel\"),\n                statusInspection = $(\"#status-inspection\");\n            statusInspection.triggerHandler(\"click\");\n            expect(problemsPanel.is(\":visible\")).toBe(visible);\n        }\n\n        /**\n         * Wait for the editor to change positions, such as after a jump to\n         * definition has been triggered.  Will timeout after 3 seconds\n         *\n         * @param {{line:number, ch:number}} oldLocation - the original line/col\n         * @param {Function} callback - the callback to apply once the editor has changed position\n         */\n        function _waitForJump(jumpPromise, callback) {\n            var cursor = null,\n                complete = false;\n\n            jumpPromise.done(function () {\n                complete = true;\n            });\n\n            waitsFor(function () {\n                var activeEditor = EditorManager.getActiveEditor();\n                cursor = activeEditor.getCursorPos();\n                return complete;\n            }, \"Expected jump did not occur\", 3000);\n\n            runs(function () { callback(cursor); });\n        }\n\n        /*\n         * Expect a given list of hints to be present in a given hint\n         * response object\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Array.<string>} expectedHints - a list of hints that should be\n         *      present in the hint response\n         */\n        function expecthintsPresent(expectedHints) {\n            var hintObj = (new CodeHintsProvider.CodeHintsProvider(phpToolingExtension.getClient())).getHints(null);\n            _waitForHints(hintObj, function (hintList) {\n                expect(hintList).toBeTruthy();\n                expectedHints.forEach(function (expectedHint) {\n                    expect(_indexOf(hintList, expectedHint)).not.toBe(-1);\n                });\n            });\n        }\n\n        /*\n         * Return the index at which hint occurs in hintList\n         *\n         * @param {Array.<Object>} hintList - the list of hints\n         * @param {string} hint - the hint to search for\n         * @return {number} - the index into hintList at which the hint occurs,\n         * or -1 if it does not\n         */\n        function _indexOf(hintList, hint) {\n            var index = -1,\n                counter = 0;\n\n            for (counter; counter < hintList.length; counter++) {\n                if (hintList[counter].data(\"token\").label === hint) {\n                    index = counter;\n                    break;\n                }\n            }\n            return index;\n        }\n\n        /*\n         * Wait for a hint response object to resolve, then apply a callback\n         * to the result\n         *\n         * @param {Object + jQuery.Deferred} hintObj - a hint response object,\n         *      possibly deferred\n         * @param {Function} callback - the callback to apply to the resolved\n         *      hint response object\n         */\n        function _waitForHints(hintObj, callback) {\n            var complete = false,\n                hintList = null;\n\n            if (hintObj.hasOwnProperty(\"hints\")) {\n                complete = true;\n                hintList = hintObj.hints;\n            } else {\n                hintObj.done(function (obj) {\n                    complete = true;\n                    hintList = obj.hints;\n                });\n            }\n\n            waitsFor(function () {\n                return complete;\n            }, \"Expected hints did not resolve\", 3000);\n\n            runs(function () { callback(hintList); });\n        }\n\n        /**\n         * Show a function hint based on the code at the cursor. Verify the\n         * hint matches the passed in value.\n         *\n         * @param {Array<{name: string, type: string, isOptional: boolean}>}\n         * expectedParams - array of records, where each element of the array\n         * describes a function parameter. If null, then no hint is expected.\n         * @param {number} expectedParameter - the parameter at cursor.\n         */\n        function expectParameterHint(expectedParams, expectedParameter) {\n            var requestStatus = null;\n            var request,\n                complete = false;\n            runs(function () {\n                request = (new DefaultProviders.ParameterHintsProvider(phpToolingExtension.getClient()))\n                    .getParameterHints();\n                request.done(function (status) {\n                    complete = true;\n                    requestStatus = status;\n                }).fail(function(){\n                    complete = true;\n                });\n            });\n\n            waitsFor(function () {\n                return complete;\n            }, \"Expected Parameter hints did not resolve\", 3000);\n\n            if (expectedParams === null) {\n                expect(requestStatus).toBe(null);\n                return;\n            }\n\n            function expectHint(hint) {\n                var params = hint.parameters,\n                    n = params.length,\n                    i;\n\n                // compare params to expected params\n                expect(params.length).toBe(expectedParams.length);\n                expect(hint.currentIndex).toBe(expectedParameter);\n\n                for (i = 0; i < n; i++) {\n                    expect(params[i].label).toBe(expectedParams[i]);\n                }\n\n            }\n            runs(function() {\n                expectHint(requestStatus);\n            });\n        }\n\n        /**\n         * Show the document/project symbols for a language type.\n         *\n         * @param   {SymbolProvider} provider        The symbol provider to use for the request.\n         * @param   {string}         query           The query string for the request.\n         * @param   {Array}          expectedSymbols Expected results for the request.\n         */\n        function expectSymbols(provider, query, expectedSymbols) {\n            var requestStatus = null;\n            var request,\n                matcher;\n\n            runs(function () {\n                matcher = new StringMatch.StringMatcher();\n                request = new provider(phpToolingExtension.getClient()).search(query, matcher);\n                request.done(function (status) {\n                    requestStatus = status;\n                });\n\n                waitsForDone(request, \"Expected Symbols did not resolve\", 3000);\n            });\n\n            if (expectedSymbols === []) {\n                expect(requestStatus).toBe([]);\n                return;\n            }\n\n            function matchSymbols(symbols) {\n                var n = symbols.length > 4 ? 4 : symbols.length,\n                    i;\n\n                for (i = 0; i < n; i++) {\n                    var symbolInfo = symbols[i].symbolInfo;\n                    expect(symbolInfo.label).toBe(expectedSymbols[i].label);\n                    expect(symbolInfo.type).toBe(expectedSymbols[i].type);\n                    expect(symbolInfo.scope).toBe(expectedSymbols[i].scope);\n\n                    if (expectedSymbols[i].fullPath === null) {\n                        expect(symbolInfo.fullPath).toBe(null);\n                    } else {\n                        expect(symbolInfo.fullPath.includes(expectedSymbols[i].fullPath)).toBe(true);\n                    }\n                }\n\n            }\n            runs(function() {\n                matchSymbols(requestStatus);\n            });\n        }\n\n        /**\n         * Trigger a jump to definition, and verify that the editor jumped to\n         * the expected location. The new location is the variable definition\n         * or function definition of the variable or function at the current\n         * cursor location. Jumping to the new location will cause a new editor\n         * to be opened or open an existing editor.\n         *\n         * @param {{line:number, ch:number, file:string}} expectedLocation - the\n         *  line, column, and optionally the new file the editor should jump to.  If the\n         *  editor is expected to stay in the same file, then file may be omitted.\n         */\n        function editorJumped(expectedLocation) {\n            var jumpPromise = (new DefaultProviders.JumpToDefProvider(phpToolingExtension.getClient())).doJumpToDef();\n\n            _waitForJump(jumpPromise, function (newCursor) {\n                expect(newCursor.line).toBe(expectedLocation.line);\n                expect(newCursor.ch).toBe(expectedLocation.ch);\n                if (expectedLocation.file) {\n                    var activeEditor = EditorManager.getActiveEditor();\n                    expect(activeEditor.document.file.name).toBe(expectedLocation.file);\n                }\n            });\n\n        }\n\n        function expectReferences(referencesExpected) {\n            var refPromise,\n                results = null,\n                complete = false;\n            runs(function () {\n                refPromise = (new DefaultProviders.ReferencesProvider(phpToolingExtension.getClient())).getReferences();\n                refPromise.done(function (resp) {\n                    complete = true;\n                    results = resp;\n                }).fail(function(){\n                    complete = true;\n                });\n            });\n\n            waitsFor(function () {\n                return complete;\n            }, \"Expected Reference Promise did not resolve\", 3000);\n\n            if(referencesExpected === null) {\n                expect(results).toBeNull();\n                return;\n            }\n\n            runs(function() {\n                expect(results.numFiles).toBe(referencesExpected.numFiles);\n                expect(results.numMatches).toBe(referencesExpected.numMatches);\n                expect(results.allResultsAvailable).toBe(referencesExpected.allResultsAvailable);\n                expect(results.results).not.toBeNull();\n                for(var key in results.keys) {\n                    expect(results.results.key).toBe(referencesExpected.results.key);\n                }\n            });\n        }\n\n        /**\n         * Check the presence of Error Prompt on Brackets Window\n         */\n        function checkErrorPopUp() {\n            var doc = $(testWindow.document),\n                errorPopUp = doc.find(\".error-dialog.instance\"),\n                errorPopUpHeader = errorPopUp.find(\".modal-header\"),\n                errorPopUpBody = errorPopUp.find(\".modal-body\"),\n                errorPopUpFooter = errorPopUp.find(\".modal-footer\"),\n                errorPopUpPresent = false;\n\n            runs(function () {\n                expect(errorPopUp.length).toBe(1);\n                expect(errorPopUpHeader).not.toBeNull();\n                expect(errorPopUpBody).not.toBeNull();\n                expect(errorPopUpFooter).not.toBeNull();\n            });\n\n            if (errorPopUp && errorPopUp.length > 0) {\n                errorPopUpPresent =  true;\n            }\n            return errorPopUpPresent;\n        }\n\n        it(\"phpTooling Exiension should be loaded Successfully\", function () {\n            waitForMilliSeconds(5000);\n            runs(function () {\n                expect(phpToolingExtension).not.toBeNull();\n            });\n        });\n\n        it(\"should attempt to start php server and fail due to lower version of php\", function () {\n            var phpExecutable = testWindow.brackets.platform === \"mac\" ? \"/mac/invalidphp\" : \"/win/invalidphp\";\n            PreferencesManager.set(\"php\", {\n                \"executablePath\": testFolder + phpExecutable\n            }, {\n                locations: {scope: \"session\"}\n            });\n            waitForMilliSeconds(5000);\n            runs(function () {\n                checkErrorPopUp();\n                checkPopUpString(Strings.PHP_SERVER_ERROR_TITLE,\n                                 StringUtils.format(Strings.PHP_UNSUPPORTED_VERSION, \"5.6.30\"));\n                checkPopUpButton(\"CANCEL\");\n            });\n        });\n\n        it(\"should attempt to start php server and fail due to invaild executable\", function () {\n            PreferencesManager.set(\"php\", {\"executablePath\": \"/invalidPath/php\"}, {locations: {scope: \"session\"}});\n            waitForMilliSeconds(5000);\n            runs(function () {\n                checkErrorPopUp();\n                checkPopUpString(Strings.PHP_SERVER_ERROR_TITLE, Strings.PHP_EXECUTABLE_NOT_FOUND);\n                checkPopUpButton(\"CANCEL\");\n            });\n        });\n\n        it(\"should attempt to start php server and fail due to invaild memory limit in prefs settings\", function () {\n            PreferencesManager.set(\"php\", {\"memoryLimit\": \"invalidValue\"}, {locations: {scope: \"session\"}});\n            waitForMilliSeconds(5000);\n            runs(function () {\n                checkErrorPopUp();\n                checkPopUpString(Strings.PHP_SERVER_ERROR_TITLE, Strings.PHP_SERVER_MEMORY_LIMIT_INVALID);\n                checkPopUpButton(\"CANCEL\");\n            });\n\n            runs(function () {\n                SpecRunnerUtils.loadProjectInTestWindow(testFolder + \"test\");\n            });\n        });\n\n        it(\"should attempt to start php server and success\", function () {\n            PreferencesManager.set(\"php\", {\"memoryLimit\": \"4095M\"}, {locations: {scope: \"session\"}});\n\n            waitsForDone(SpecRunnerUtils.openProjectFiles([testFile1]), \"open test file: \" + testFile1);\n            waitForMilliSeconds(5000);\n            runs(function () {\n                toggleDiagnosisResults(false);\n                toggleDiagnosisResults(true);\n            });\n        });\n\n        it(\"should filter hints by query\", function () {\n            waitsForDone(SpecRunnerUtils.openProjectFiles([testFile2]), \"open test file: \" + testFile2);\n            runs(function() {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos({ line: 15, ch: 3 });\n                expecthintsPresent([\"$A11\", \"$A12\", \"$A13\"]);\n            });\n        });\n\n        it(\"should show inbuilt functions in hints\", function () {\n            runs(function() {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos({ line: 17, ch: 2 });\n                expecthintsPresent([\"fopen\", \"for\", \"foreach\"]);\n            });\n        });\n\n        it(\"should show static global variables in hints\", function () {\n            runs(function() {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos({ line: 20, ch: 1 });\n                expecthintsPresent([\"$_COOKIE\", \"$_ENV\"]);\n            });\n        });\n\n        it(\"should not show parameter hints\", function () {\n            runs(function() {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos({ line: 25, ch: 5 });\n                expectParameterHint(null);\n            });\n        });\n\n        it(\"should show no parameter as a hint\", function () {\n            runs(function() {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos({ line: 27, ch: 19 });\n                expectParameterHint([], 0);\n            });\n        });\n\n        it(\"should show parameters hints\", function () {\n            runs(function() {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos({ line: 26, ch: 9 });\n                expectParameterHint([\n                    \"string $filename\",\n                    \"string $mode\",\n                    \"bool $use_include_path = null\",\n                    \"resource $context = null\"], 1);\n            });\n        });\n\n        it(\"should not show any references\", function () {\n            var start = { line: 6, ch: 4 };\n\n            runs(function () {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos(start);\n                expectReferences(null);\n            });\n        });\n\n        it(\"should  show  reference present in single file\", function () {\n            var start = { line: 22, ch: 18 },\n                results = {};\n\n            runs(function () {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos(start);\n                results[testFolder + \"test/test2.php\"] = {matches: [\n                    {\n                        start: {line: 27, ch: 0},\n                        end: {line: 27, ch: 18},\n                        line: \"watchparameterhint()\"\n                    }\n                ]\n                };\n                expectReferences({\n                    numFiles: 1,\n                    numMatches: 1,\n                    allResultsAvailable: true,\n                    queryInfo: \"watchparameterhint\",\n                    keys: [testFolder + \"test/test2.php\"],\n                    results: results\n                });\n            });\n        });\n\n        it(\"should  show  references present in single file\", function () {\n            var start = { line: 34, ch: 8 },\n                results = {};\n\n            runs(function () {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos(start);\n                results[testFolder + \"test/test2.php\"] = {matches: [\n                    {\n                        start: {line: 34, ch: 0},\n                        end: {line: 34, ch: 17},\n                        line: \"watchReferences();\"\n                    },\n                    {\n                        start: {line: 36, ch: 0},\n                        end: {line: 36, ch: 17},\n                        line: \"watchReferences();\"\n                    }\n                ]\n                };\n                expectReferences({\n                    numFiles: 1,\n                    numMatches: 2,\n                    allResultsAvailable: true,\n                    queryInfo: \"watchparameterhint\",\n                    keys: [testFolder + \"test/test2.php\"],\n                    results: results\n                });\n            });\n        });\n\n        it(\"should  show  references present in multiple files\", function () {\n            var start = { line: 39, ch: 21 },\n                results = {};\n\n            runs(function () {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos(start);\n                results[testFolder + \"test/test2.php\"] = {matches: [\n                    {\n                        start: {line: 34, ch: 0},\n                        end: {line: 34, ch: 26},\n                        line: \"watchReferences();\"\n                    },\n                    {\n                        start: {line: 36, ch: 0},\n                        end: {line: 36, ch: 26},\n                        line: \"watchReferences();\"\n                    }\n                ]\n                };\n                results[testFolder + \"test/test3.php\"] = {matches: [\n                    {\n                        start: {line: 11, ch: 0},\n                        end: {line: 11, ch: 26},\n                        line: \"watchReferences();\"\n                    }\n                ]\n                };\n                expectReferences({\n                    numFiles: 2,\n                    numMatches: 3,\n                    allResultsAvailable: true,\n                    queryInfo: \"watchparameterhint\",\n                    keys: [testFolder + \"test/test2.php\", testFolder + \"test/test3.php\"],\n                    results: results\n                });\n            });\n        });\n\n        it(\"should jump to earlier defined variable\", function () {\n            var start = { line: 4, ch: 2 };\n\n            runs(function () {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos(start);\n                editorJumped({line: 2, ch: 0});\n            });\n        });\n\n        it(\"should jump to class declared in other module file\", function () {\n            var start = { line: 9, ch: 11 };\n\n            runs(function () {\n                testEditor = EditorManager.getActiveEditor();\n                testEditor.setCursorPos(start);\n                editorJumped({line: 4, ch: 0, file: \"test3.php\"});\n            });\n        });\n\n        it(\"should fetch document symbols for a given file\", function () {\n            waitsForDone(SpecRunnerUtils.openProjectFiles([testFile4]), \"open test file: \" + testFile4);\n            runs(function () {\n                var provider = SymbolProviders.DocumentSymbolsProvider,\n                    query = \"@\",\n                    expectedSymbols = [\n                        {\n                            \"label\": \"constantValue\",\n                            \"fullPath\": null,\n                            \"type\": \"Constant\",\n                            \"scope\": \"MyClass\"\n                        },\n                        {\n                            \"label\": \"MyClass\",\n                            \"fullPath\": null,\n                            \"type\": \"Class\",\n                            \"scope\": \"\"\n                        },\n                        {\n                            \"label\": \"publicFunction\",\n                            \"fullPath\": null,\n                            \"type\": \"Method\",\n                            \"scope\": \"MyClass\"\n                        },\n                        {\n                            \"label\": \"publicValue\",\n                            \"fullPath\": null,\n                            \"type\": \"Property\",\n                            \"scope\": \"MyClass\"\n                        }\n                    ];\n                expectSymbols(provider, query, expectedSymbols);\n            });\n        });\n\n        it(\"should fetch no document symbols for a given file\", function () {\n            waitsForDone(SpecRunnerUtils.openProjectFiles([testFile1]), \"open test file: \" + testFile1);\n            runs(function () {\n                var provider = SymbolProviders.DocumentSymbolsProvider,\n                    query = \"@\",\n                    expectedSymbols = [];\n                expectSymbols(provider, query, expectedSymbols);\n            });\n        });\n\n        it(\"should fetch project symbols for a given file\", function () {\n            runs(function () {\n                var provider = SymbolProviders.ProjectSymbolsProvider,\n                    query = \"#as\",\n                    expectedSymbols = [\n                        {\n                            \"label\": \"MyClass\",\n                            \"fullPath\": \"test4.php\",\n                            \"type\": \"Class\",\n                            \"scope\": \"\"\n                        },\n                        {\n                            \"label\": \"TestCase\",\n                            \"fullPath\": \"test2.php\",\n                            \"type\": \"Class\",\n                            \"scope\": \"test\"\n                        }\n                    ];\n                expectSymbols(provider, query, expectedSymbols);\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/PrefsCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependencies.\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        StringMatch         = brackets.getModule(\"utils/StringMatch\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        LanguageManager     = brackets.getModule(\"language/LanguageManager\"),\n        JSONUtils           = brackets.getModule(\"language/JSONUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        ThemeManager        = brackets.getModule(\"view/ThemeManager\"),\n        CodeInspection      = brackets.getModule(\"language/CodeInspection\"),\n        _                   = brackets.getModule(\"thirdparty/lodash\"),\n        languages           = LanguageManager.getLanguages(),\n        isPrefDocument      = false,\n        isPrefHintsEnabled  = false;\n\n    // Stores data of preferences used by Brackets and its core/thirdparty extensions.\n    var data = {\n        language: {\n            type: \"object\",\n            description: Strings.DESCRIPTION_LANGUAGE\n        },\n        path: {\n            type: \"object\",\n            description: Strings.DESCRIPTION_PATH\n        }\n    };\n\n    var stringMatcherOptions = {\n        preferPrefixMatches: true\n    };\n\n    // List of parent keys for which no key hints will be provided.\n    var parentKeyBlacklist = [\n        \"language.fileExtensions\",\n        \"language.fileNames\",\n        \"path\"\n    ];\n\n    // Define a preference for code hinting.\n    PreferencesManager.definePreference(\"codehint.PrefHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_PREF_HINTS\n    });\n\n    /**\n     * @private\n     *\n     * Determines whether or not the current document is a preferences document and\n     * user has enabled code hints\n     *\n     * @return {Boolean}\n     */\n    function _isPrefHintsEnabled() {\n        return (isPrefDocument &&\n                PreferencesManager.get(\"showCodeHints\") !== false &&\n                PreferencesManager.get(\"codehint.PrefHints\") !== false);\n    }\n\n    /**\n     * @private\n     *\n     * Determines whether or not the name of a file matches the preferences files\n     *\n     * @param {!Document} document\n     * @return {Boolean}\n     */\n    function _isPrefDocument(document) {\n        return (/^\\.?brackets\\.json$/).test(document.file._name);\n    }\n\n    // Set listeners on preference, editor and language changes.\n    PreferencesManager.on(\"change\", \"showCodeHints\", function () {\n        isPrefHintsEnabled = _isPrefHintsEnabled();\n    });\n    PreferencesManager.on(\"change\", \"codehint.PrefHints\", function () {\n        isPrefHintsEnabled = _isPrefHintsEnabled();\n    });\n    EditorManager.on(\"activeEditorChange\", function (e, editor) {\n        if (editor) {\n            isPrefDocument = _isPrefDocument(editor.document);\n        }\n        isPrefHintsEnabled = _isPrefHintsEnabled();\n    });\n    LanguageManager.on(\"languageAdded\", function () {\n        languages = LanguageManager.getLanguages();\n    });\n\n    /*\n     * Returns a sorted and formatted list of hints with the query substring\n     * highlighted.\n     *\n     * @param {Array.<Object>} hints - the list of hints to format\n     * @param {string} query - querystring used for highlighting matched\n     *      portions of each hint\n     * @return {Array.jQuery} sorted Array of jQuery DOM elements to insert\n     */\n    function formatHints(hints, query) {\n\n        var hasMetadata = hints.some(function (token) {\n            return token.type || token.description;\n        });\n\n        StringMatch.basicMatchSort(hints);\n        return hints.map(function (token) {\n            var $hintItem = $(\"<span>\").addClass(\"brackets-pref-hints\"),\n                $hintObj  = $(\"<span>\").addClass(\"hint-obj\");\n\n            // highlight the matched portion of each hint\n            if (token.stringRanges) {\n                token.stringRanges.forEach(function (item) {\n                    if (item.matched) {\n                        $hintObj.append($(\"<span>\")\n                            .text(item.text)\n                            .addClass(\"matched-hint\"));\n                    } else {\n                        $hintObj.append(item.text);\n                    }\n                });\n            } else {\n                $hintObj.text(token.value);\n            }\n\n            $hintItem.append($hintObj);\n\n            if (hasMetadata) {\n                $hintItem.data(\"type\", token.type);\n                if (token.description) {\n                    $hintItem.append($(\"<span>\")\n                                        .addClass(\"hint-description\")\n                                        .text(token.description));\n                }\n            }\n            return $hintItem;\n        });\n    }\n\n    /**\n     * @constructor\n     */\n    function PrefsCodeHints() {\n        this.ctxInfo = null;\n\n        // Add all the preferences defined except the excluded ones.\n        var preferences = PreferencesManager.getAllPreferences(),\n            preference;\n        Object.keys(preferences).forEach(function (pref) {\n            preference = preferences[pref];\n            if (preference.excludeFromHints) {\n                return;\n            }\n            data[pref] = $.extend(data[pref], preference);\n\n            // If child keys found, add them.\n            if (preference.keys) {\n                data[pref].keys = _.clone(preference.keys);\n            }\n        });\n    }\n\n    /**\n     * Determines whether or not hints are available in the current context\n     *\n     * @param {!Editor} editor\n     * @param {String} implicitChar\n     * @return {Boolean}\n     */\n    PrefsCodeHints.prototype.hasHints = function (editor, implicitChar) {\n        if (isPrefHintsEnabled && editor.getModeForSelection() === \"application/json\") {\n            this.editor = editor;\n            this.ctxInfo = JSONUtils.getContextInfo(this.editor, this.editor.getCursorPos(), true);\n\n            if (this.ctxInfo && this.ctxInfo.tokenType) {\n                // Disallow hints for blacklisted keys.\n                if (this.ctxInfo.tokenType === JSONUtils.TOKEN_KEY &&\n                        parentKeyBlacklist.indexOf(this.ctxInfo.parentKeyName) !== -1) {\n                    return false;\n                }\n                return true;\n            }\n        }\n        return false;\n    };\n\n    /**\n     * Returns a list of hints available in the current context\n     *\n     * @param {String} implicitChar\n     * @return {!{hints: Array.<jQueryObject>, match: string, selectInitial: boolean, handleWideResults: boolean}}\n     */\n    PrefsCodeHints.prototype.getHints = function (implicitChar) {\n        var hints = [], ctxInfo, query, keys, values, option = {type: null, description: null, values: null};\n\n        ctxInfo = this.ctxInfo = JSONUtils.getContextInfo(this.editor, this.editor.getCursorPos(), true);\n\n        if (ctxInfo && ctxInfo.token) {\n            query = JSONUtils.stripQuotes(ctxInfo.token.string.substr(0, ctxInfo.offset)).trim();\n            if (JSONUtils.regexAllowedChars.test(query)) {\n                query = \"\";\n            }\n\n            if (ctxInfo.tokenType === JSONUtils.TOKEN_KEY) {\n                // Provide hints for keys\n\n                // Get options for parent key else use general options.\n                if (data[ctxInfo.parentKeyName] && data[ctxInfo.parentKeyName].keys) {\n                    keys = data[ctxInfo.parentKeyName].keys;\n                } else if (ctxInfo.parentKeyName === \"language\") {\n                    keys = languages;\n                    option.type = \"object\";\n                } else {\n                    keys = data;\n                }\n\n                hints = $.map(Object.keys(keys), function (key) {\n                    if (ctxInfo.exclusionList.indexOf(key) === -1) {\n                        var match = StringMatch.stringMatch(key, query, stringMatcherOptions);\n                        if (match) {\n                            match.type = keys[key].type || option.type;\n                            match.description = keys[key].description || null;\n                            return match;\n                        }\n                    }\n                });\n            } else if (ctxInfo.tokenType === JSONUtils.TOKEN_VALUE) {\n                // Provide hints for values.\n\n                // Get the key from data.\n                if (data[ctxInfo.parentKeyName] && data[ctxInfo.parentKeyName].keys &&\n                        data[ctxInfo.parentKeyName].keys[ctxInfo.keyName]) {\n                    option = data[ctxInfo.parentKeyName].keys[ctxInfo.keyName];\n                } else if (data[ctxInfo.keyName]) {\n                    option = data[ctxInfo.keyName];\n                }\n\n                // Get the values depending on the selected key.\n                if (option && option.type === \"boolean\") {\n                    values = [\"false\", \"true\"];\n                } else if (option && option.values && ([\"number\", \"string\"].indexOf(option.type) !== -1 ||\n                                                       (option.type === \"array\" && ctxInfo.isArray))) {\n                    values = option.values;\n                } else if (ctxInfo.isArray && ctxInfo.keyName === \"linting.prefer\" && languages[ctxInfo.parentKeyName]) {\n                    values = CodeInspection.getProviderIDsForLanguage(ctxInfo.parentKeyName);\n                } else if (ctxInfo.keyName === \"themes.theme\") {\n                    values = ThemeManager.getAllThemes().map(function (theme) {\n                        return theme.name;\n                    });\n                } else if (ctxInfo.parentKeyName === \"language.fileExtensions\" ||\n                           ctxInfo.parentKeyName === \"language.fileNames\") {\n                    values = Object.keys(languages);\n                } else {\n                    return null;\n                }\n\n                // Convert integers to strings, so StringMatch.stringMatch can match it.\n                if (option.type === \"number\" || option.valueType === \"number\") {\n                    values = values.map(function (val) {\n                        return val.toString();\n                    });\n                }\n\n                // filter through the values.\n                hints = $.map(values, function (value) {\n                    var match = StringMatch.stringMatch(value, query, stringMatcherOptions);\n                    if (match) {\n                        match.type = option.valueType || option.type;\n                        match.description = option.description || null;\n                        return match;\n                    }\n                });\n            }\n\n            return {\n                hints: formatHints(hints, query),\n                match: null,\n                selectInitial: true,\n                handleWideResults: false\n            };\n        }\n        return null;\n    };\n\n    /**\n     * Inserts a completion at current position\n     *\n     * @param {!String} completion\n     * @return {Boolean}\n     */\n    PrefsCodeHints.prototype.insertHint = function (completion) {\n        var ctxInfo = JSONUtils.getContextInfo(this.editor, this.editor.getCursorPos(), false, true),\n            pos     = this.editor.getCursorPos(),\n            start   = {line: -1, ch: -1},\n            end     = {line: -1, ch: -1},\n            startChar,\n            quoteChar,\n            type;\n\n        if (completion.jquery) {\n            type = completion.data(\"type\");\n            completion = completion.find(\".hint-obj\").text();\n        }\n        start.line = end.line = pos.line;\n\n        if (ctxInfo.tokenType === JSONUtils.TOKEN_KEY) {\n            startChar = ctxInfo.token.string.charAt(0);\n\n            // Get the quote char.\n            if (/^['\"]$/.test(startChar)) {\n                quoteChar = startChar;\n            }\n\n            // Put quotes around completion.\n            completion = quoteChar + completion + quoteChar;\n\n            // Append colon and braces, brackets and quotes.\n            if (!ctxInfo.shouldReplace) {\n                completion += \": \";\n\n                switch (type) {\n                case \"object\":\n                    completion += \"{}\";\n                    break;\n\n                case \"array\":\n                    completion += \"[]\";\n                    break;\n\n                case \"string\":\n                    completion += \"\\\"\\\"\";\n                    break;\n                }\n            }\n\n            start.ch = pos.ch - ctxInfo.offset;\n            end.ch = ctxInfo.token.end;\n            this.editor.document.replaceRange(completion, start, end);\n\n            // Place cursor inside the braces, brackets or quotes.\n            if ([\"object\", \"array\", \"string\"].indexOf(type) !== -1) {\n                this.editor.setCursorPos(start.line, start.ch + completion.length - 1);\n\n                // Start a new session in case it is an array or string.\n                if (type !== \"object\" && !ctxInfo.shouldReplace) {\n                    return true;\n                }\n                return false;\n            }\n            return true;\n        } else if (ctxInfo.tokenType === JSONUtils.TOKEN_VALUE) {\n            // In case the current token is a white-space, start and end will be same.\n            if (JSONUtils.regexAllowedChars.test(ctxInfo.token.string)) {\n                start.ch = end.ch = pos.ch;\n            } else if (ctxInfo.shouldReplace) {\n                start.ch = ctxInfo.token.start;\n                end.ch = ctxInfo.token.end;\n            } else {\n                start.ch = pos.ch - ctxInfo.offset;\n                end.ch = ctxInfo.token.end;\n            }\n\n            if (!type || type === \"string\") {\n                startChar = ctxInfo.token.string.charAt(0);\n                if (/^['\"]$/.test(startChar)) {\n                    quoteChar = startChar;\n                } else {\n                    quoteChar = \"\\\"\";\n                }\n                completion = quoteChar + completion + quoteChar;\n            }\n\n            this.editor.document.replaceRange(completion, start, end);\n            return false;\n        }\n    };\n\n    /**\n     * @private\n     *\n     * `isPrefHintsEnabled` must be set to true to allow code hints\n     *\n     * It also loads a set of preferences that we need for running unit tests, this\n     * will not break unit tests in case we add new preferences in the future.\n     *\n     * @param {!Document} testDocument\n     * @param {!Object} testPreferences\n     */\n    function _setupTestEnvironment(testDocument, testPreferences) {\n        isPrefHintsEnabled = _isPrefDocument(testDocument);\n        data = testPreferences;\n    }\n\n    AppInit.appReady(function () {\n        var hintProvider = new PrefsCodeHints();\n        CodeHintManager.registerHintProvider(hintProvider, [\"json\"], 0);\n        ExtensionUtils.loadStyleSheet(module, \"styles/brackets-prefs-hints.css\");\n\n        // For unit tests only.\n        exports.hintProvider            = hintProvider;\n        exports._setupTestEnvironment   = _setupTestEnvironment;\n    });\n\n});\n"
  },
  {
    "path": "src/extensions/default/PrefsCodeHints/styles/brackets-prefs-hints.css",
    "content": ".brackets-pref-hints .matched-hint {\n    font-weight: 500;\n}\n.dark .brackets-pref-hints .matched-hint {\n    color: #ccc;\n}\n\n.brackets-pref-hints .hint-obj {\n    display: inline-block;\n    min-width: 250px;\n}\n\n.brackets-pref-hints .hint-description {\n    line-height: 1.3;\n    display: none;\n    width: 250px;\n    padding-bottom: 3px;\n    padding-left: 14px;\n    white-space: pre-wrap;\n    color: #6e6e64;\n}\n\n.dark .brackets-pref-hints .hint-description {\n    color: #ccc;\n}\n\n.highlight .brackets-pref-hints .hint-description {\n    display: block;\n}\n"
  },
  {
    "path": "src/extensions/default/PrefsCodeHints/unittest-files/preferences.json",
    "content": "{\n    \"closeBrackets\": {\n        \"type\": \"boolean\"\n    },\n    \"closeOthers.above\": {\n        \"type\": \"boolean\"\n    },\n    \"closeOthers.below\": {\n        \"type\": \"boolean\"\n    },\n    \"closeTags\": {\n        \"type\": \"object\",\n        \"keys\": {\n            \"dontCloseTags\": {\n                \"type\": \"array\"\n            },\n            \"whenOpening\": {\n                \"type\": \"boolean\"\n            },\n            \"whenClosing\": {\n                \"type\": \"boolean\"\n            },\n            \"indentTags\": {\n                \"type\": \"array\"\n            }\n        }\n    },\n    \"insertHintOnTab\": {\n        \"type\": \"boolean\"\n    },\n    \"language\": {\n        \"type\": \"object\"\n    },\n    \"linting.prefer\": {\n        \"type\": \"array\",\n        \"values\": [\"JSHint\", \"JSLint\"],\n        \"valueType\": \"string\"\n    },\n    \"spaceUnits\": {\n        \"type\": \"number\"\n    },\n    \"useTabChar\": {\n        \"type\": \"boolean\"\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/PrefsCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, beforeEach, afterEach, it, expect*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependencies.\n    var SpecRunnerUtils     = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        PrefsCodeHints      = require(\"./main\"),\n        testPreferences     = JSON.parse(require(\"text!./unittest-files/preferences.json\"));\n\n    describe(\"Preferences Code Hints\", function () {\n        var testContent, testDocument, testEditor, mockEditor;\n\n        // A sample preferences file to run tests against.\n        testContent =   \"{\\n\" +\n                        \"    \\\"closeBrackets\\\": true,\\n\" +\n                        \"    \\\"insertHintOnTab\\\": false,\\n\" +\n                        \"    \\\"language.fileExtensions\\\": {\\n\" +\n                        \"        \\\"txt\\\": \\\"markdown\\\"\\n\" +\n                        \"    },\\n\" +\n                        \"    \\\"language.fileNames\\\": {\\n\" +\n                        \"        \\\"README.txt\\\": \\\"markdown\\\"\\n\" +\n                        \"    },\\n\" +\n                        \"    \\\"language\\\": {\\n\" +\n                        \"        \\\"javascript\\\": {\\n\" +\n                        \"            \\\"spaceUnits\\\": 4,\\n\" +\n                        \"            \\\"useTabChar\\\": false\\n\" +\n                        \"        },\\n\" +\n                        \"        \\\"php\\\": {\\n\" +\n                        \"            \\\"tabSize\\\": 4,\\n\" +\n                        \"            \\\"useTabChar\\\":true,\\n\" +\n                        \"            \\\"closeBrackets\\\":false\\n\" +\n                        \"        }\\n\" +\n                        \"    },\\n\" +\n                        \"    \\\"jslint.options\\\": {\\n\" +\n                        \"        \\\"devel\\\": true,\\n\" +\n                        \"        \\\"regexp\\\": true\\n\" +\n                        \"    },\\n\" +\n                        \"    \\\"linting.prefer\\\": [\\\"JSHint\\\",\\\"JSLint\\\"],\\n\" +\n                        \"    \\n\" +\n                        \"    \\\"linting.usePreferredOnly\\\" false,\" +\n                        \"    \\n\" +\n                        \"}\";\n\n        beforeEach(function () {\n            mockEditor = SpecRunnerUtils.createMockEditor(testContent, \"json\", {\n                startLine: 0,\n                endLine: 30\n            });\n            testEditor = mockEditor.editor;\n            testDocument = mockEditor.doc;\n\n            // Rename the file to preferences file.\n            testDocument.file._name = \".brackets.json\";\n\n            // Setup a test environment by loading minimum preferences required to run unit tests.\n            PrefsCodeHints._setupTestEnvironment(testDocument, testPreferences);\n        });\n\n        afterEach(function () {\n            testEditor.destroy();\n            testDocument = null;\n        });\n\n        // Extracts hints out of their DOM nodes.\n        function extractHintList(hintList) {\n            return $.map(hintList, function ($node) {\n                return $node.find(\".hint-obj\").text();\n            });\n        }\n\n        // Determines the availability of hints.\n        function expectHints(provider) {\n            expect(provider.hasHints(testEditor, null)).toBe(true);\n            var hintObj = provider.getHints();\n            expect(hintObj).toBeTruthy();\n            return hintObj.hints;\n        }\n\n        // Determines the non-availability of hints.\n        function expectNoHints(provider) {\n            var hasHints = provider.hasHints(testEditor, null);\n            if (!hasHints) {\n                expect(hasHints).toBe(false);\n            } else {\n                expect(provider.getHints(null)).toBe(null);\n            }\n        }\n\n        // Determines the presence of a hint in the hint list.\n        function verifyHints(hintList, expectedHint) {\n            var hints = extractHintList(hintList);\n            expect(hints[0]).toBe(expectedHint);\n        }\n\n        // Determines the exclusion of a hint in the hint list.\n        function verifyHintsExcluded(hintList, unexpectedHint) {\n            var hints = extractHintList(hintList);\n            expect(hints.indexOf(unexpectedHint)).toBe(-1);\n        }\n\n        // Inserts the selected hint.\n        function selectHint(provider, expectedHint) {\n            var hintList = expectHints(provider),\n                hints = extractHintList(hintList),\n                index = hints.indexOf(expectedHint);\n            expect(index).not.toBe(-1);\n            return provider.insertHint(hintList[index]);\n        }\n\n        // Determines a token at any given position.\n        function expectTokenAt(pos, string, type) {\n            var token = testEditor._codeMirror.getTokenAt(pos);\n            expect(token.string).toBe(string);\n            expect(token.type).toBe(type);\n        }\n\n        // Helper functions for testing cursor position / selection range\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n\n        // Determines the position of the cursor.\n        function expectCursorAt(pos) {\n            var selection = testEditor.getSelection();\n            expect(fixPos(selection.start)).toEqual(fixPos(selection.end));\n            expect(fixPos(selection.start)).toEqual(fixPos(pos));\n        }\n\n        describe(\"File name based hinting\", function () {\n\n            it(\"it should hint in .brackets.json\", function () {\n                // Between \" and closeBrackets\"\n                testEditor.setCursorPos({line: 1, ch: 5});\n                expectHints(PrefsCodeHints.hintProvider);\n\n                testEditor.setCursorPos({line: 1, ch: 20});\n                expectHints(PrefsCodeHints.hintProvider);\n            });\n\n            it(\"it should hint in brackets.json\", function () {\n                testDocument.file._name = \"brackets.json\";\n                PrefsCodeHints._setupTestEnvironment(testDocument, testPreferences);\n\n                // Between \" and closeBrackets\"\n                testEditor.setCursorPos({line: 1, ch: 5});\n                expectHints(PrefsCodeHints.hintProvider);\n\n                // After \"closeBrackets\":\n                testEditor.setCursorPos({line: 1, ch: 20});\n                expectHints(PrefsCodeHints.hintProvider);\n            });\n\n            it(\"it should NOT hint in other JSON files\", function () {\n                testDocument.file._name = \"package.json\";\n                PrefsCodeHints._setupTestEnvironment(testDocument, testPreferences);\n\n                // Between \" and closeBrackets\"\n                testEditor.setCursorPos({line: 1, ch: 5});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"closeBrackets\":\n                testEditor.setCursorPos({line: 1, ch: 20});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n        });\n\n        describe(\"Key Hints\", function () {\n            it(\"should hint at the begininng of a key\", function () {\n                var hintList;\n\n                // Between \" and language\"\n                testEditor.setCursorPos({line: 9, ch: 5});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"closeOthers.above\");\n\n                // Between \" and javascript\"\n                testEditor.setCursorPos({line: 10, ch: 9});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"audio\");\n\n                // Between \" and spaceUnits\"\n                testEditor.setCursorPos({line: 11, ch: 13});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"closeBrackets\");\n            });\n            it(\"should hint in the center of a key\", function () {\n                var hintList;\n\n                // In \"language\"\n                testEditor.setCursorPos({line: 9, ch: 9});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"language\");\n\n                // In \"javascript\"\n                testEditor.setCursorPos({line: 10, ch: 14});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"javascript\");\n\n                // In \"spaceUnits\"\n                testEditor.setCursorPos({line: 11, ch: 18});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"spaceUnits\");\n            });\n            it(\"should hint at the end of a key\", function () {\n                var hintList;\n\n                // Between \"language and \"\n                testEditor.setCursorPos({line: 9, ch: 13});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"language\");\n\n                // Between \"javascript and \"\n                testEditor.setCursorPos({line: 10, ch: 19});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"javascript\");\n\n                // Between \"spaceUnits and \"\n                testEditor.setCursorPos({line: 11, ch: 23});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"spaceUnits\");\n            });\n\n            it(\"should NOT hint for blacklisted parent keys\", function () {\n                // Between \" and txt\"\n                testEditor.setCursorPos({line: 4, ch: 9});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // In \"txt\"\n                testEditor.setCursorPos({line: 4, ch: 11});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // Between \" and README.txt\"\n                testEditor.setCursorPos({line: 7, ch: 9});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // In \"README.txt\"\n                testEditor.setCursorPos({line: 7, ch: 15});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint before initial quote of a key\", function () {\n                // Before \"closeBrackets\"\n                testEditor.setCursorPos({line: 1, ch: 4});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // Before \"language\"\n                testEditor.setCursorPos({line: 9, ch: 4});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // Before \"javascript\"\n                testEditor.setCursorPos({line: 10, ch: 8});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // Before \"spaceUnits\"\n                testEditor.setCursorPos({line: 11, ch: 12});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n            it(\"should NOT hint after final quote of a key\", function () {\n                // After \"closeBrackets\"\n                testEditor.setCursorPos({line: 1, ch: 19});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"language\"\n                testEditor.setCursorPos({line: 9, ch: 14});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"javascript\"\n                testEditor.setCursorPos({line: 10, ch: 20});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"spaceUnits\"\n                testEditor.setCursorPos({line: 11, ch: 24});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n\n            it(\"should NOT include keys already used in the context of current object\", function () {\n                var hintList;\n\n                // Between \" and insertHintOnTab\"\n                testEditor.setCursorPos({line: 2, ch: 5});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHintsExcluded(hintList, \"closeBrackets\");\n                verifyHintsExcluded(hintList, \"language.fileExtensions\");\n                verifyHintsExcluded(hintList, \"language.fileNames\");\n                verifyHintsExcluded(hintList, \"language\");\n                verifyHintsExcluded(hintList, \"jslint.options\");\n                verifyHintsExcluded(hintList, \"linting.prefer\");\n                verifyHintsExcluded(hintList, \"linting.usePreferredOnly\");\n\n                // Between \" and insertHintOnTab\"\n                testEditor.setCursorPos({line: 15, ch: 13});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHintsExcluded(hintList, \"useTabChar\");\n                verifyHintsExcluded(hintList, \"closeBrackets\");\n            });\n        });\n\n        describe(\"Value Hints\", function () {\n            it(\"should hint after a colon\", function () {\n                var hintList;\n\n                // After \"closeBrackets\":\n                testEditor.setCursorPos({line: 1, ch: 20});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"insertHintOnTab\":\n                testEditor.setCursorPos({line: 2, ch: 22});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"useTabChar\":\n                testEditor.setCursorPos({line: 12, ch: 25});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n            });\n            it(\"should hint after after a space followed by a colon\", function () {\n                var hintList;\n\n                // After \"closeBrackets\":+space\n                testEditor.setCursorPos({line: 1, ch: 21});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"insertHintOnTab\":+space\n                testEditor.setCursorPos({line: 2, ch: 23});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"useTabChar\":+space\n                testEditor.setCursorPos({line: 12, ch: 26});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n            });\n            it(\"should hint even if space is missing after a colon\", function () {\n                var hintList;\n\n                // After \"useTabChar\":\n                testEditor.setCursorPos({line: 16, ch: 25});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"closeBrackets\":\n                testEditor.setCursorPos({line: 17, ch: 28});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n            });\n            it(\"should hint at the beginning of value\", function () {\n                var hintList;\n\n                // After \"closeBrackets\": t\n                testEditor.setCursorPos({line: 1, ch: 22});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"true\");\n\n                // After \"insertHintOnTab\": f\n                testEditor.setCursorPos({line: 2, ch: 24});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"useTabChar\": f\n                testEditor.setCursorPos({line: 12, ch: 27});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n            });\n            it(\"should hint at the center of value\", function () {\n                var hintList;\n\n                // After \"closeBrackets\": tru\n                testEditor.setCursorPos({line: 1, ch: 24});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"true\");\n\n                // After \"insertHintOnTab\": fal\n                testEditor.setCursorPos({line: 2, ch: 26});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"useTabChar\": fal\n                testEditor.setCursorPos({line: 12, ch: 29});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n            });\n            it(\"should hint at the end of the value\", function () {\n                var hintList;\n\n                // After \"closeBrackets\": true\n                testEditor.setCursorPos({line: 1, ch: 25});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"true\");\n\n                // After \"insertHintOnTab\": false\n                testEditor.setCursorPos({line: 2, ch: 28});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n\n                // After \"useTabChar\": false\n                testEditor.setCursorPos({line: 12, ch: 31});\n                hintList = expectHints(PrefsCodeHints.hintProvider);\n                verifyHints(hintList, \"false\");\n            });\n\n            it(\"should NOT hint if the corresponding colon is missing\", function () {\n                // After \"linting.usePreferredOnly\"\n                testEditor.setCursorPos({line: 26, ch: 30});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"linting.usePreferredOnly\"+space\n                testEditor.setCursorPos({line: 26, ch: 31});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"linting.usePreferredOnly\" f\n                testEditor.setCursorPos({line: 26, ch: 32});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"linting.usePreferredOnly\" fal\n                testEditor.setCursorPos({line: 26, ch: 34});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"linting.usePreferredOnly\" false\n                testEditor.setCursorPos({line: 26, ch: 36});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n            it(\"should NOT hint after a comma\", function () {\n                // After \"closeBrackets\": true,\n                testEditor.setCursorPos({line: 1, ch: 26});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"insertHintOnTab\": false,\n                testEditor.setCursorPos({line: 2, ch: 29});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"javascript\": { [rules] },\n                testEditor.setCursorPos({line: 13, ch: 10});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"language\": { [languages] },\n                testEditor.setCursorPos({line: 19, ch: 6});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n            it(\"should NOT hint before opening braces\", function () {\n                // Between \"javascript\": and {\n                testEditor.setCursorPos({line: 10, ch: 22});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"javascript\": {\n                testEditor.setCursorPos({line: 10, ch: 23});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n            it(\"should NOT hint after closing braces\", function () {\n                // After \"javascript\": { [rules] }\n                testEditor.setCursorPos({line: 13, ch: 9});\n                expectNoHints(PrefsCodeHints.hintProvider);\n\n                // After \"language\": { [languages] }\n                testEditor.setCursorPos({line: 19, ch: 5});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n            it(\"should NOT hint before opening brackets\", function () {\n                testEditor.setCursorPos({line: 10, ch: 22});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n            it(\"should NOT hint after closing brackets\", function () {\n                testEditor.setCursorPos({line: 10, ch: 22});\n                expectNoHints(PrefsCodeHints.hintProvider);\n            });\n        });\n\n        describe(\"Key Insertion\", function () {\n            it(\"should enter entire key after initial quote is typed\", function () {\n                testDocument.replaceRange(\"\\\"\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 5});\n                selectHint(PrefsCodeHints.hintProvider, \"closeOthers.above\");\n                expectTokenAt({line: 25, ch: 22}, \"\\\"closeOthers.above\\\"\", \"string property\");\n                expectTokenAt({line: 25, ch: 24}, \":\", null);\n                expectCursorAt({line: 25, ch: 25});\n            });\n            it(\"should enter entire key after first letter of a key is typed\", function () {\n                testDocument.replaceRange(\"\\\"c\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 6});\n                selectHint(PrefsCodeHints.hintProvider, \"closeOthers.above\");\n                expectTokenAt({line: 25, ch: 22}, \"\\\"closeOthers.above\\\"\", \"string property\");\n                expectTokenAt({line: 25, ch: 24}, \":\", null);\n                expectCursorAt({line: 25, ch: 25});\n            });\n            it(\"should enter entire key after few initial letters are typed\", function () {\n                testDocument.replaceRange(\"\\\"close\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 10});\n                selectHint(PrefsCodeHints.hintProvider, \"closeOthers.above\");\n                expectTokenAt({line: 25, ch: 22}, \"\\\"closeOthers.above\\\"\", \"string property\");\n                expectTokenAt({line: 25, ch: 24}, \":\", null);\n                expectCursorAt({line: 25, ch: 25});\n            });\n            it(\"should replace existing key after few initial letter are typed\", function () {\n                testDocument.replaceRange(\"\\\"closeOthers.above\\\": true,\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 17});\n                selectHint(PrefsCodeHints.hintProvider, \"closeOthers.below\");\n                expectTokenAt({line: 25, ch: 22}, \"\\\"closeOthers.below\\\"\", \"string property\");\n                expectTokenAt({line: 25, ch: 24}, \":\", null);\n                expectCursorAt({line: 25, ch: 23});\n            });\n            it(\"should append braces to a hint in case it is an object\", function () {\n                testDocument.replaceRange(\"\\\"\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 5});\n                selectHint(PrefsCodeHints.hintProvider, \"closeTags\");\n                expectTokenAt({line: 25, ch: 14}, \"\\\"closeTags\\\"\", \"string property\");\n                expectTokenAt({line: 25, ch: 16}, \":\", null);\n                expectTokenAt({line: 25, ch: 18}, \"{\", null);\n                expectTokenAt({line: 25, ch: 19}, \"}\", null);\n                expectCursorAt({line: 25, ch: 18});\n            });\n            it(\"should append brackets to a hint in case it in an array\", function () {\n                testDocument.replaceRange(\"\\\"closeTags\\\": { \\\"\\\" }\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 20});\n                selectHint(PrefsCodeHints.hintProvider, \"indentTags\");\n                expectTokenAt({line: 25, ch: 30}, \"\\\"indentTags\\\"\", \"string property\");\n                expectTokenAt({line: 25, ch: 32}, \":\", null);\n                expectTokenAt({line: 25, ch: 34}, \"[\", null);\n                expectTokenAt({line: 25, ch: 35}, \"]\", null);\n                expectCursorAt({line: 25, ch: 34});\n            });\n\n            it(\"should NOT replace colon and braces/brackets if they already exists\", function () {\n                // After close in \"closeBrackets\": true\n                testEditor.setCursorPos({line: 1, ch: 10});\n                expectTokenAt({line: 1, ch: 20}, \":\", null);\n                selectHint(PrefsCodeHints.hintProvider, \"closeOthers.above\");\n                expectTokenAt({line: 1, ch: 24}, \":\", null);\n            });\n        });\n\n        describe(\"Value Insertion\", function () {\n            it(\"should insert a value of type Boolean\", function () {\n                testDocument.replaceRange(\"\\\"closeOthers.above\\\":,\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 24});\n                selectHint(PrefsCodeHints.hintProvider, \"true\");\n                expectTokenAt({line: 25, ch: 28}, \"true\", \"atom\");\n                expectCursorAt({line: 25, ch: 28});\n            });\n            it(\"should replace current token when editing\", function () {\n                testDocument.replaceRange(\"\\\"closeOthers.above\\\": tru\", {line: 25, ch: 4});\n                testEditor.setCursorPos({line: 25, ch: 28});\n                selectHint(PrefsCodeHints.hintProvider, \"true\");\n                expectTokenAt({line: 25, ch: 28}, \"true\", \"atom\");\n                expectCursorAt({line: 25, ch: 29});\n            });\n            it(\"should insert a value of type String\", function () {\n                testDocument.replaceRange(\",\\n        \\\"pavement\\\":\", {line: 7, ch: 32});\n                testEditor.setCursorPos({line: 8, ch: 19});\n                selectHint(PrefsCodeHints.hintProvider, \"python\");\n                expectTokenAt({line: 8, ch: 27}, \"\\\"python\\\"\", \"string\");\n                expectCursorAt({line: 8, ch: 27});\n            });\n            it(\"should insert a value if the next token is also a value\", function () {\n                // Before true\n                testEditor.setCursorPos({line: 1, ch: 21});\n                selectHint(PrefsCodeHints.hintProvider, \"false\");\n                expectTokenAt({line: 1, ch: 26}, \"false\", \"atom\");\n                expectCursorAt({line: 1, ch: 26});\n\n                // Before \"JSHint\"\n                testEditor.setCursorPos({line: 24, ch: 23});\n                selectHint(PrefsCodeHints.hintProvider, \"JSLint\");\n                expectTokenAt({line: 24, ch: 31}, \"\\\"JSLint\\\"\", \"string\");\n                expectCursorAt({line: 24, ch: 31});\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/QuickOpenCSS/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        QuickOpen           = brackets.getModule(\"search/QuickOpen\"),\n        QuickOpenHelper     = brackets.getModule(\"search/QuickOpenHelper\"),\n        CSSUtils            = brackets.getModule(\"language/CSSUtils\"),\n        DocumentManager     = brackets.getModule(\"document/DocumentManager\"),\n        StringMatch         = brackets.getModule(\"utils/StringMatch\");\n\n\n    /**\n     * Returns a list of information about selectors for a single document. This array is populated\n     * by createSelectorList()\n     * @return {?Array.<FileLocation>}\n     */\n    function createSelectorList() {\n        var doc = DocumentManager.getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        var docText = doc.getText();\n        return CSSUtils.extractAllSelectors(docText, doc.getLanguage().getMode());\n    }\n\n\n    /**\n     * @param {string} query what the user is searching for\n     * @return {Array.<SearchResult>} sorted and filtered results that match the query\n     */\n    function search(query, matcher) {\n        var selectorList = matcher.selectorList;\n        if (!selectorList) {\n            selectorList = createSelectorList();\n            matcher.selectorList = selectorList;\n        }\n        query = query.slice(query.indexOf(\"@\") + 1, query.length);\n\n        // Filter and rank how good each match is\n        var filteredList = $.map(selectorList, function (itemInfo) {\n            var searchResult = matcher.match(CSSUtils.getCompleteSelectors(itemInfo), query);\n            if (searchResult) {\n                searchResult.selectorInfo = itemInfo;\n            }\n            return searchResult;\n        });\n\n        // Sort based on ranking & basic alphabetical order\n        StringMatch.basicMatchSort(filteredList);\n\n        return filteredList;\n    }\n\n    /**\n     * Scroll to the selected item in the current document (unless no query string entered yet,\n     * in which case the topmost list item is irrelevant)\n     * @param {?SearchResult} selectedItem\n     * @param {string} query\n     * @param {boolean} explicit False if this is only highlighted due to being at top of list after search()\n     */\n    function itemFocus(selectedItem, query, explicit) {\n        if (!selectedItem || (query.length < 2 && !explicit)) {\n            return;\n        }\n        var selectorInfo = selectedItem.selectorInfo;\n\n        var from = {line: selectorInfo.selectorStartLine, ch: selectorInfo.selectorStartChar};\n        var to = {line: selectorInfo.selectorStartLine, ch: selectorInfo.selectorEndChar};\n        EditorManager.getCurrentFullEditor().setSelection(from, to, true);\n    }\n\n    function itemSelect(selectedItem, query) {\n        itemFocus(selectedItem, query, true);\n    }\n\n\n\n    QuickOpen.addQuickOpenPlugin(\n        {\n            name: \"CSS Selectors\",\n            languageIds: [\"css\", \"less\", \"scss\"],\n            search: search,\n            match: QuickOpenHelper.match,\n            itemFocus: itemFocus,\n            itemSelect: itemSelect\n        }\n    );\n\n\n});\n"
  },
  {
    "path": "src/extensions/default/QuickOpenHTML/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        QuickOpen           = brackets.getModule(\"search/QuickOpen\"),\n        QuickOpenHelper     = brackets.getModule(\"search/QuickOpenHelper\"),\n        DocumentManager     = brackets.getModule(\"document/DocumentManager\"),\n        StringMatch         = brackets.getModule(\"utils/StringMatch\");\n\n\n   /**\n    * FileLocation class\n    * @constructor\n    * @param {string} fullPath\n    * @param {number} line\n    * @param {number} chFrom column start position\n    * @param {number} chTo column end position\n    * @param {string} id\n    */\n    function FileLocation(fullPath, line, chFrom, chTo, id) {\n        this.fullPath = fullPath;\n        this.line = line;\n        this.chFrom = chFrom;\n        this.chTo = chTo;\n        this.id = id;\n    }\n\n    /**\n     * Returns a list of information about ID's for a single document. This array is populated\n     * by createIDList()\n     * @type {?Array.<FileLocation>}\n     */\n    function createIDList() {\n        var doc = DocumentManager.getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        var idList = [];\n        var docText = doc.getText();\n        var lines = docText.split(\"\\n\");\n\n        var regex = new RegExp(/\\s+id\\s*?=\\s*?[\"'](.*?)[\"']/gi);\n        var id, chFrom, chTo, i, line;\n        for (i = 0; i < lines.length; i++) {\n            line = lines[i];\n            var info;\n            while ((info = regex.exec(line)) !== null) {\n                id = info[1];\n                // TODO: this doesn't handle id's that share the\n                // same portion of a name on the same line or when\n                // the id and value are on different lines\n                chFrom = line.indexOf(id);\n                chTo = chFrom + id.length;\n                idList.push(new FileLocation(null, i, chFrom, chTo, id));\n            }\n        }\n        return idList;\n    }\n\n\n    /**\n     * @param {string} query what the user is searching for\n     * @return {Array.<SearchResult>} sorted and filtered results that match the query\n     */\n    function search(query, matcher) {\n        var idList = matcher.idList;\n        if (!idList) {\n            idList = createIDList();\n            matcher.idList = idList;\n        }\n        query = query.slice(query.indexOf(\"@\") + 1, query.length);\n\n        // Filter and rank how good each match is\n        var filteredList = $.map(idList, function (fileLocation) {\n            var searchResult = matcher.match(fileLocation.id, query);\n            if (searchResult) {\n                searchResult.fileLocation = fileLocation;\n            }\n            return searchResult;\n        });\n\n        // Sort based on ranking & basic alphabetical order\n        StringMatch.basicMatchSort(filteredList);\n\n        return filteredList;\n    }\n\n    QuickOpen.addQuickOpenPlugin(\n        {\n            name: \"html ids\",\n            languageIds: [\"html\"],\n            search: search,\n            match: QuickOpenHelper.match,\n            itemFocus: QuickOpenHelper.itemFocus,\n            itemSelect: QuickOpenHelper.itemSelect\n        }\n    );\n\n});\n"
  },
  {
    "path": "src/extensions/default/QuickOpenJavaScript/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        QuickOpen           = brackets.getModule(\"search/QuickOpen\"),\n        QuickOpenHelper     = brackets.getModule(\"search/QuickOpenHelper\"),\n        JSUtils             = brackets.getModule(\"language/JSUtils\"),\n        DocumentManager     = brackets.getModule(\"document/DocumentManager\"),\n        StringMatch         = brackets.getModule(\"utils/StringMatch\");\n\n\n   /**\n    * FileLocation class\n    * @constructor\n    * @param {string} fullPath\n    * @param {number} line\n    * @param {number} chFrom column start position\n    * @param {number} chTo column end position\n    * @param {string} functionName\n    */\n    function FileLocation(fullPath, line, chFrom, chTo, functionName) {\n        this.fullPath = fullPath;\n        this.line = line;\n        this.chFrom = chFrom;\n        this.chTo = chTo;\n        this.functionName = functionName;\n    }\n\n    /**\n     * Contains a list of information about functions for a single document.\n     *\n     * @return {?Array.<FileLocation>}\n     */\n    function createFunctionList() {\n        var doc = DocumentManager.getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        var functionList = [];\n        var docText = doc.getText();\n        var lines = docText.split(\"\\n\");\n        var functions = JSUtils.findAllMatchingFunctionsInText(docText, \"*\");\n        functions.forEach(function (funcEntry) {\n            functionList.push(new FileLocation(null, funcEntry.nameLineStart, funcEntry.columnStart, funcEntry.columnEnd, funcEntry.label || funcEntry.name));\n        });\n        return functionList;\n    }\n\n\n\n    /**\n     * @param {string} query what the user is searching for\n     * @param {StringMatch.StringMatcher} matcher object that caches search-in-progress data\n     * @return {Array.<SearchResult>} sorted and filtered results that match the query\n     */\n    function search(query, matcher) {\n        var functionList = matcher.functionList;\n        if (!functionList) {\n            functionList = createFunctionList();\n            matcher.functionList = functionList;\n        }\n        query = query.slice(query.indexOf(\"@\") + 1, query.length);\n\n        // Filter and rank how good each match is\n        var filteredList = $.map(functionList, function (fileLocation) {\n            var searchResult = matcher.match(fileLocation.functionName, query);\n            if (searchResult) {\n                searchResult.fileLocation = fileLocation;\n            }\n            return searchResult;\n        });\n\n        // Sort based on ranking & basic alphabetical order\n        StringMatch.basicMatchSort(filteredList);\n\n        return filteredList;\n    }\n\n    QuickOpen.addQuickOpenPlugin(\n        {\n            name: \"JavaScript functions\",\n            languageIds: [\"javascript\"],\n            search: search,\n            match: QuickOpenHelper.match,\n            itemFocus: QuickOpenHelper.itemFocus,\n            itemSelect: QuickOpenHelper.itemSelect\n        }\n    );\n\n});\n"
  },
  {
    "path": "src/extensions/default/QuickView/QuickView.less",
    "content": "@bc-highlight:                  rgba(255, 255, 255, 0.12);\n@bc-panel-bg:                   #dfe2e2;\n@bc-panel-bg-promoted:          #d4d7d7;\n@bc-shadow-large:               rgba(0, 0, 0, 0.5);\n@bc-shadow-small:               rgba(0, 0, 0, 0.06);\n@bc-text:                       #333;\n\n@dark-bc-highlight:             rgba(255, 255, 255, 0.06);\n@dark-bc-panel-bg:              #2c2c2c;\n@dark-bc-panel-bg-promoted:     #222;\n@dark-bc-shadow-large:          rgba(0, 0, 0, 0.5);\n@dark-bc-shadow-small:          rgba(0, 0, 0, 0.06);\n@dark-bc-text:                  #ccc;\n\n#quick-view-container {\n    display: none;\n\n    -webkit-transition: opacity 0.125s ease-in, -webkit-transform 0.125s;\n    transition: opacity 0.125s ease-in, transform 0.125s;\n\n    -webkit-transform: scale(0);\n    transform: scale(0);\n    opacity: 0;\n\n    background: @bc-panel-bg;\n    position: absolute;\n    z-index: 5000;\n    pointer-events: none;\n\n    padding: 8px;\n    text-align: center;\n\n    border-radius: 4px;\n    box-shadow: 0 4px 15px @bc-shadow-large;\n\n    .dark & {\n        background: @dark-bc-panel-bg;\n        box-shadow: 0 4px 15px @dark-bc-shadow-large;\n    }\n}\n\n#quick-view-container.active {\n    -webkit-transform: scale(1);\n    transform: scale(1);\n    opacity: 1;\n}\n\n#quick-view-container .preview-content {\n    background-image: url(preview-bg.svg);\n    border-radius: 2px;\n    box-shadow: 0 -1px 2px @bc-shadow-small, 0 1px 0 @bc-highlight;\n\n    .dark & {\n        box-shadow: 0 -1px 2px @dark-bc-shadow-small, 0 1px 0 @dark-bc-highlight;\n        background-image: url(preview-bg-dark.svg);\n    }\n}\n\n\n#quick-view-container .color-swatch {\n    width: 40px;\n    height: 40px;\n    background-size: 100%;\n}\n\n#quick-view-container .image-preview {\n    line-height: 0;\n}\n\n#quick-view-container .image-preview img {\n    min-width: 100px;\n    max-width: 200px;\n    max-height: 200px;\n}\n\n#quick-view-container .img-size {\n    background-color: @bc-panel-bg-promoted;\n    border-top: 1px solid @bc-highlight;\n    font-size: 0.9em;\n    color: @bc-text;\n    padding-left: 3px;\n    margin-top: 0;\n    text-align: left;\n    text-shadow: 0 1px 0px @bc-highlight;\n\n    .dark & {\n        background-color: @dark-bc-panel-bg-promoted;\n        border-top: 1px solid @dark-bc-highlight;\n        color: @dark-bc-text;\n        text-shadow: 0 1px 0px @dark-bc-highlight;\n    }\n}\n\n#quick-view-container.preview-bubble-above {\n    -webkit-transform-origin: center bottom;\n}\n\n#quick-view-container.preview-bubble-above:before {\n    display: none;\n}\n\n#quick-view-container.preview-bubble-above:after,\n#quick-view-container.preview-bubble-below:before {\n    width: 0;\n    height: 0;\n    content: '';\n    position: absolute;\n    left: 50%;\n    bottom: -9px;\n    margin-left: -10px;\n    z-index: 999;\n    display: block;\n    border-top: 10px solid @bc-panel-bg;\n    border-left: 10px solid transparent;\n    border-right: 10px solid transparent;\n    -webkit-filter: drop-shadow(0px 1px 0 rgba(0, 0, 0, 0.18));\n\n    .dark & {\n        border-top: 10px solid @dark-bc-panel-bg;\n    }\n}\n\n#quick-view-container.preview-bubble-below {\n    -webkit-transform-origin: center top;\n}\n\n#quick-view-container.preview-bubble-below:before {\n    -webkit-filter: drop-shadow(0px 1px 0 rgba(255, 255, 255, 0.18));\n    -webkit-transform: rotate(180deg);\n    top: -9px;\n}\n\n#quick-view-container.preview-bubble-below:after {\n    display: none;\n}\n\n.quick-view-highlight {\n    background-color: rgba(200, 200, 150, 0.4);\n}\n"
  },
  {
    "path": "src/extensions/default/QuickView/QuickViewTemplate.html",
    "content": "<div id=\"quick-view-container\">\n    <div class=\"preview-content\">\n    </div>\n</div>"
  },
  {
    "path": "src/extensions/default/QuickView/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var ColorUtils          = brackets.getModule(\"utils/ColorUtils\"),\n        CommandManager      = brackets.getModule(\"command/CommandManager\"),\n        Commands            = brackets.getModule(\"command/Commands\"),\n        CSSUtils            = brackets.getModule(\"language/CSSUtils\"),\n        EditorManager       = brackets.getModule(\"editor/EditorManager\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        FileUtils           = brackets.getModule(\"file/FileUtils\"),\n        Menus               = brackets.getModule(\"command/Menus\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        LanguageManager     = brackets.getModule(\"language/LanguageManager\"),\n        Strings             = brackets.getModule(\"strings\"),\n        ViewUtils           = brackets.getModule(\"utils/ViewUtils\"),\n        TokenUtils          = brackets.getModule(\"utils/TokenUtils\"),\n        PathUtils           = brackets.getModule(\"thirdparty/path-utils/path-utils\");\n\n    var previewContainerHTML       = require(\"text!QuickViewTemplate.html\");\n\n    var enabled,                             // Only show preview if true\n        prefs                      = null,   // Preferences\n        $previewContainer,                   // Preview container\n        $previewContent,                     // Preview content holder\n        lastMousePos,                        // Last mouse position\n        animationRequest,                    // Request for animation frame\n        extensionlessImagePreview;           // Whether to try and preview extensionless URLs\n\n    // Constants\n    var CMD_ENABLE_QUICK_VIEW       = \"view.enableQuickView\",\n        HOVER_DELAY                 = 350,  // Time (ms) mouse must remain over a provider's matched text before popover appears\n        POINTER_HEIGHT              = 15,   // Pointer height, used to shift popover above pointer (plus a little bit of space)\n        POPOVER_HORZ_MARGIN         =  5;   // Horizontal margin\n\n    var styleLanguages = [\"css\", \"text/x-less\", \"sass\", \"text/x-scss\", \"stylus\"];\n\n    // List of protocols which we will support for image preview urls\n    var validProtocols = [\"data:\", \"http:\", \"https:\", \"ftp:\", \"file:\"];\n\n    prefs = PreferencesManager.getExtensionPrefs(\"quickview\");\n    prefs.definePreference(\"enabled\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_QUICK_VIEW_ENABLED\n    });\n\n    // Whether or not to try and show image previews for URLs missing extensions\n    // (e.g., https://avatars2.githubusercontent.com/u/476009?v=3&s=200)\n    prefs.definePreference(\"extensionlessImagePreview\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\n    });\n\n    /**\n     * There are three states for this var:\n     * 1. If null, there is no provider result for the given mouse position.\n     * 2. If non-null, and visible==true, there is a popover currently showing.\n     * 3. If non-null, but visible==false, we're waiting for HOVER_DELAY, which\n     *    is tracked by hoverTimer. The state changes to visible==true as soon as\n     *    there is a provider. If the mouse moves before then, timer is restarted.\n     *\n     * @type {{\n     *      visible: boolean,\n     *      editor: !Editor,\n     *      hoverTimer: number,             - setTimeout() token\n     *      start: !{line, ch},             - start of matched text range\n     *      end: !{line, ch},               - end of matched text range\n     *      content: !string,               - HTML content to display in popover\n     *      onShow: ?function():void,       - called once popover content added to the DOM (may never be called)\n     *        - if specified, must call positionPreview()\n     *      xpos: number,                   - x of center of popover\n     *      ytop: number,                   - y of top of matched text (when popover placed above text, normally)\n     *      ybot: number,                   - y of bottom of matched text (when popover moved below text, avoiding window top)\n     *      marker: ?CodeMirror.TextMarker  - only set once visible==true\n     * }}\n     */\n    var popoverState = null;\n\n\n\n    // Popover widget management ----------------------------------------------\n\n    /**\n     * Cancels whatever popoverState was currently pending and sets it back to null. If the popover was visible,\n     * hides it; if the popover was invisible and still pending, cancels hoverTimer so it will never be shown.\n     */\n    function hidePreview() {\n        if (!popoverState) {\n            return;\n        }\n\n        if (popoverState.visible) {\n            popoverState.marker.clear();\n\n            $previewContent.empty();\n            $previewContainer.hide();\n            $previewContainer.removeClass(\"active\");\n        } else {\n            window.clearTimeout(popoverState.hoverTimer);\n        }\n        popoverState = null;\n    }\n\n    function positionPreview(editor, xpos, ypos, ybot) {\n        var previewWidth  = $previewContainer.outerWidth(),\n            top           = ypos - $previewContainer.outerHeight() - POINTER_HEIGHT,\n            left          = xpos - previewWidth / 2,\n            elementRect = {\n                top:    top,\n                left:   left - POPOVER_HORZ_MARGIN,\n                height: $previewContainer.outerHeight() + POINTER_HEIGHT,\n                width:  previewWidth + 2 * POPOVER_HORZ_MARGIN\n            },\n            clip = ViewUtils.getElementClipSize($(editor.getRootElement()), elementRect);\n\n        // Prevent horizontal clipping\n        if (clip.left > 0) {\n            left += clip.left;\n        } else if (clip.right > 0) {\n            left -= clip.right;\n        }\n\n        // If clipped on top, flip popover below line\n        if (clip.top > 0) {\n            top = ybot + POINTER_HEIGHT;\n            $previewContainer\n                .removeClass(\"preview-bubble-above\")\n                .addClass(\"preview-bubble-below\");\n        } else {\n            $previewContainer\n                .removeClass(\"preview-bubble-below\")\n                .addClass(\"preview-bubble-above\");\n        }\n\n        $previewContainer\n            .css({\n                left: left,\n                top: top\n            })\n            .addClass(\"active\");\n    }\n\n    function divContainsMouse($div, mousePos) {\n        var offset = $div.offset();\n\n        return (mousePos.clientX >= offset.left &&\n                mousePos.clientX <= offset.left + $div.width() &&\n                mousePos.clientY >= offset.top &&\n                mousePos.clientY <= offset.top + $div.height());\n    }\n\n\n    // Color & gradient preview provider --------------------------------------\n\n    function colorAndGradientPreviewProvider(editor, pos, token, line) {\n\n        // Check for gradient. -webkit-gradient() can have parens in parameters\n        // nested 2 levels. Other gradients can only nest 1 level.\n        var gradientRegEx = /-webkit-gradient\\((?:[^\\(]*?(?:\\((?:[^\\(]*?(?:\\([^\\)]*?\\))*?)*?\\))*?)*?\\)|(?:(?:-moz-|-ms-|-o-|-webkit-|:|\\s)((repeating-)?linear-gradient)|(?:-moz-|-ms-|-o-|-webkit-|:|\\s)((repeating-)?radial-gradient))(\\((?:[^\\)]*?(?:\\([^\\)]*?\\))*?)*?\\))/gi,\n            colorRegEx    = new RegExp(ColorUtils.COLOR_REGEX),\n            mode          = TokenUtils.getModeAt(editor._codeMirror, pos, false),\n            isStyleSheet  = (styleLanguages.indexOf(mode) !== -1);\n\n        function areParensBalanced(str) {\n            var i,\n                nestLevel = 0,\n                len;\n\n            if (isStyleSheet) {\n                // Remove comments & strings from style sheets\n                str = CSSUtils.reduceStyleSheetForRegExParsing(str);\n            }\n            len = str.length;\n\n            for (i = 0; i < len; i++) {\n                switch (str[i]) {\n                case \"(\":\n                    nestLevel++;\n                    break;\n                case \")\":\n                    nestLevel--;\n                    break;\n                case \"\\\\\":\n                    i++;    // next char is escaped, so skip it\n                    break;\n                }\n            }\n\n            // if parens are balanced, nest level will be 0\n            return (nestLevel === 0);\n        }\n\n        function execGradientMatch(line, parensBalanced) {\n            // Unbalanced parens cause infinite loop (see issue #4650)\n            var gradientMatch = (parensBalanced ? gradientRegEx.exec(line) : null),\n                prefix = \"\",\n                colorValue;\n\n            if (gradientMatch) {\n                if (gradientMatch[0].indexOf(\"@\") !== -1) {\n                    // If the gradient match has \"@\" in it, it is most likely a less or\n                    // sass variable. Ignore it since it won't be displayed correctly.\n                    gradientMatch = null;\n\n                } else {\n                    // If it was a linear-gradient or radial-gradient variant with a vendor prefix\n                    // add \"-webkit-\" so it shows up correctly in Brackets.\n                    if (gradientMatch[0].match(/-o-|-moz-|-ms-|-webkit-/i)) {\n                        prefix = \"-webkit-\";\n                    }\n\n                    // For prefixed gradients, use the non-prefixed value as the color value.\n                    // \"-webkit-\" will be added before this value later\n                    if (gradientMatch[1]) {\n                        colorValue = gradientMatch[1] + gradientMatch[5];    // linear gradiant\n                    } else if (gradientMatch[3]) {\n                        colorValue = gradientMatch[3] + gradientMatch[5];    // radial gradiant\n                    } else if (gradientMatch[0]) {\n                        colorValue = gradientMatch[0];                       // -webkit-gradient\n                        prefix = \"\";                                         // do not prefix\n                    }\n                }\n            }\n\n            return {\n                match:      gradientMatch,\n                prefix:     prefix,\n                colorValue: colorValue\n            };\n        }\n\n        function execColorMatch(editor, line, pos) {\n            var colorMatch,\n                ignoreNamedColors;\n\n            function hyphenOnMatchBoundary(match, line) {\n                var beforeIndex, afterIndex;\n                if (match) {\n                    beforeIndex = match.index - 1;\n                    if (beforeIndex >= 0 && line[beforeIndex] === \"-\") {\n                        return true;\n                    } else {\n                        afterIndex = match.index + match[0].length;\n                        if (afterIndex < line.length && line[afterIndex] === \"-\") {\n                            return true;\n                        }\n                    }\n                }\n\n                return false;\n            }\n            function isNamedColor(match) {\n                if (match && match[0] && /^[a-z]+$/i.test(match[0])) { // only for color names, not for hex-/rgb-values\n                    return true;\n                }\n            }\n\n            // Hyphens do not count as a regex word boundary (\\b), so check for those here\n            do {\n                colorMatch = colorRegEx.exec(line);\n                if (!colorMatch) {\n                    break;\n                }\n                if (ignoreNamedColors === undefined) {\n                    var mode = TokenUtils.getModeAt(editor._codeMirror, pos, false).name;\n                    ignoreNamedColors = styleLanguages.indexOf(mode) === -1;\n                }\n            } while (hyphenOnMatchBoundary(colorMatch, line) ||\n                    (ignoreNamedColors && isNamedColor(colorMatch)));\n\n            return colorMatch;\n        }\n\n        // simple css property splitter (used to find color stop arguments in gradients)\n        function splitStyleProperty(property) {\n            var token = /((?:[^\"']|\".*?\"|'.*?')*?)([(,)]|$)/g;\n            var recurse = function () {\n                var array = [];\n                for (;;) {\n                    var result = token.exec(property);\n                    if (result[2] === \"(\") {\n                        var str = result[1].trim() + \"(\" + recurse().join(\",\") + \")\";\n                        result = token.exec(property);\n                        str += result[1];\n                        array.push(str);\n                    } else {\n                        array.push(result[1].trim());\n                    }\n                    if (result[2] !== \",\") {\n                        return array;\n                    }\n                }\n            };\n            return (recurse());\n        }\n\n        // color stop helpers\n        function isGradientColorStop(args) {\n            return (args.length > 0 && args[0].match(colorRegEx) !== null);\n        }\n\n        function hasLengthInPixels(args) {\n            return (args.length > 1 && args[1].indexOf(\"px\") > 0);\n        }\n        \n        // Ensures that input is in usable hex format\n        function ensureHexFormat(str) {\n            return (/^0x/).test(str) ? str.replace(\"0x\",\"#\") : str;\n        }\n\n        // Normalizes px color stops to %\n        function normalizeGradientExpressionForQuickview(expression) {\n            if (expression.indexOf(\"px\") > 0) {\n                var paramStart = expression.indexOf(\"(\") + 1,\n                    paramEnd = expression.lastIndexOf(\")\"),\n                    parameters = expression.substring(paramStart, paramEnd),\n                    params = splitStyleProperty(parameters),\n                    lowerBound = 0,\n                    upperBound = $previewContainer.width(),\n                    args,\n                    thisSize,\n                    i;\n\n                // find lower bound\n                for (i = 0; i < params.length; i++) {\n                    args = params[i].split(\" \");\n\n                    if (hasLengthInPixels(args)) {\n                        thisSize = parseFloat(args[1]);\n\n                        upperBound = Math.max(upperBound, thisSize);\n                        // we really only care about converting negative\n                        //  pixel values -- so take the smallest negative pixel\n                        //  value and use that as baseline for display purposes\n                        if (thisSize < 0) {\n                            lowerBound = Math.min(lowerBound, thisSize);\n                        }\n                    }\n                }\n\n                // convert negative lower bound to positive and adjust all pixel values\n                //  so that -20px is now 0px and 100px is now 120px\n                lowerBound = Math.abs(lowerBound);\n\n                // Offset the upperbound by the lowerBound to give us a corrected context\n                upperBound += lowerBound;\n\n                // convert to %\n                for (i = 0; i < params.length; i++) {\n                    args = params[i].split(\" \");\n                    if (isGradientColorStop(args) && hasLengthInPixels(args)) {\n                        if (upperBound === 0) {\n                            thisSize = 0;\n                        } else {\n                            thisSize = ((parseFloat(args[1]) + lowerBound) / upperBound) * 100;\n                        }\n                        args[1] = thisSize + \"%\";\n                    }\n                    params[i] = args.join(\" \");\n                }\n\n                // put it back together.\n                expression = expression.substring(0, paramStart) + params.join(\", \") + expression.substring(paramEnd);\n            }\n            return expression;\n        }\n\n        var parensBalanced = areParensBalanced(line),\n            gradientMatch = execGradientMatch(line, parensBalanced),\n            match = gradientMatch.match || execColorMatch(editor, line, pos),\n            cm = editor._codeMirror;\n\n        while (match) {\n            if (pos.ch < match.index) {\n                // Gradients are matched first, then colors, so...\n                if (gradientMatch.match) {\n                    // ... gradient match is past cursor -- stop looking for gradients, start searching for colors\n                    gradientMatch = { match: null, prefix: \"\", colorValue: null };\n                } else {\n                    // ... color match is past cursor -- stop looping\n                    break;\n                }\n            } else if (pos.ch <= match.index + match[0].length) {\n                // build the css for previewing the gradient from the regex result\n                var previewCSS = gradientMatch.prefix + (gradientMatch.colorValue || match[0]); \n\n                // normalize the arguments to something that we can display to the user\n                // NOTE: we need both the div and the popover's _previewCSS member\n                //          (used by unit tests) to match so normalize the css for both\n                previewCSS = normalizeGradientExpressionForQuickview(ensureHexFormat(previewCSS));\n\n                var preview = \"<div class='color-swatch' style='background:\" + previewCSS + \"'>\" + \"</div>\";\n                var startPos = {line: pos.line, ch: match.index},\n                    endPos = {line: pos.line, ch: match.index + match[0].length},\n                    startCoords = cm.charCoords(startPos),\n                    xPos;\n\n                xPos = (cm.charCoords(endPos).left - startCoords.left) / 2 + startCoords.left;\n\n                return {\n                    start: startPos,\n                    end: endPos,\n                    content: preview,\n                    xpos: xPos,\n                    ytop: startCoords.top,\n                    ybot: startCoords.bottom,\n                    _previewCSS: previewCSS\n                };\n            }\n\n            // Get next match\n            if (gradientMatch.match) {\n                gradientMatch = execGradientMatch(line, parensBalanced);\n            }\n            match = gradientMatch.match || execColorMatch(editor, line, pos);\n        }\n\n        return null;\n    }\n\n\n    // Image preview provider -------------------------------------------------\n\n    function imagePreviewProvider(editor, pos, token, line) {\n        var cm = editor._codeMirror;\n\n        // Check for image name\n        var urlRegEx = /url\\(([^\\)]*)\\)/gi,\n            tokenString,\n            urlMatch;\n\n        if (token.type === \"string\") {\n            tokenString = token.string;\n        } else {\n            urlMatch = urlRegEx.exec(line);\n            while (urlMatch) {\n                if (pos.ch < urlMatch.index) {\n                    // match is past cursor, so stop looping\n                    break;\n                } else if (pos.ch <= urlMatch.index + urlMatch[0].length) {\n                    tokenString = urlMatch[1];\n                    break;\n                }\n                urlMatch = urlRegEx.exec(line);\n            }\n        }\n\n        if (!tokenString) {\n            return null;\n        }\n\n        // Strip leading/trailing quotes, if present\n        tokenString = tokenString.replace(/(^['\"])|(['\"]$)/g, \"\");\n\n        var sPos, ePos;\n        var docPath = editor.document.file.fullPath;\n        var imgPath;\n\n        // Determine whether or not this URL/path is likely to be an image.\n        var parsed = PathUtils.parseUrl(tokenString);\n        // If the URL has a protocol, check if it's one of the supported protocols\n        var hasProtocol = parsed.protocol !== \"\" && validProtocols.indexOf(parsed.protocol.trim().toLowerCase()) !== -1;\n        var ext = parsed.filenameExtension.replace(/^\\./, '');\n        var language = LanguageManager.getLanguageForExtension(ext);\n        var id = language && language.getId();\n        var isImage = id === \"image\" || id === \"svg\";\n\n        // Use this URL if this is an absolute URL and either points to a\n        // filename with a known image extension, or lacks an extension (e.g.,\n        // a web service that returns an image). Honour the extensionlessImagePreview\n        // preference as well in the latter case.\n        if (hasProtocol && (isImage || (!ext && extensionlessImagePreview))) {\n            imgPath = tokenString;\n        }\n        // Use this filename if this is a path with a known image extension.\n        else if (!hasProtocol && isImage) {\n            imgPath = \"file:///\" + FileUtils.getDirectoryPath(docPath) + tokenString;\n        }\n\n        if (!imgPath) {\n            return null;\n        }\n\n        if (urlMatch) {\n            sPos = {line: pos.line, ch: urlMatch.index};\n            ePos = {line: pos.line, ch: urlMatch.index + urlMatch[0].length};\n        } else {\n            sPos = {line: pos.line, ch: token.start};\n            ePos = {line: pos.line, ch: token.end};\n        }\n\n        var imgPreview = \"<div class='image-preview'>\"          +\n                         \"    <img src=\\\"\" + imgPath + \"\\\">\"    +\n                         \"</div>\";\n        var coord = cm.charCoords(sPos);\n        var xpos = (cm.charCoords(ePos).left - coord.left) / 2 + coord.left;\n\n        var showHandler = function () {\n            // Hide the preview container until the image is loaded.\n            $previewContainer.hide();\n\n            $previewContainer.find(\".image-preview > img\").on(\"load\", function () {\n                $previewContent\n                    .append(\"<div class='img-size'>\" +\n                                this.naturalWidth + \" &times; \" + this.naturalHeight + \" \" + Strings.UNIT_PIXELS +\n                            \"</div>\"\n                        );\n                $previewContainer.show();\n                positionPreview(editor, popoverState.xpos, popoverState.ytop, popoverState.ybot);\n            }).on(\"error\", function (e) {\n                e.preventDefault();\n                hidePreview();\n            });\n        };\n\n        return {\n            start: sPos,\n            end: ePos,\n            content: imgPreview,\n            onShow: showHandler,\n            xpos: xpos,\n            ytop: coord.top,\n            ybot: coord.bottom,\n            _imgPath: imgPath\n        };\n    }\n\n\n    // Preview hide/show logic ------------------------------------------------\n\n    /**\n     * Returns a 'ready for use' popover state object:\n     * { visible: false, editor, start, end, content, ?onShow, xpos, ytop, ybot }\n     * Lacks only hoverTimer (supplied by handleMouseMove()) and marker (supplied by showPreview()).\n     */\n    function queryPreviewProviders(editor, pos, token) {\n        var line = editor.document.getLine(pos.line);\n\n        // FUTURE: Support plugin providers. For now we just hard-code...\n        var popover = colorAndGradientPreviewProvider(editor, pos, token, line) ||\n                      imagePreviewProvider(editor, pos, token, line);\n\n        if (popover) {\n            // Providers return just { start, end, content, ?onShow, xpos, ytop, ybot }\n            popover.visible = false;\n            popover.editor  = editor;\n            return popover;\n        }\n\n        return null;\n    }\n\n    function getHoveredEditor(mousePos) {\n        // Figure out which editor we are over\n        var fullEditor = EditorManager.getCurrentFullEditor();\n\n        if (!fullEditor || !mousePos) {\n            return;\n        }\n\n        // Check for inline Editor instances first\n        var inlines = fullEditor.getInlineWidgets(),\n            i,\n            editor;\n\n        for (i = 0; i < inlines.length; i++) {\n            var $inlineEditorRoot = inlines[i].editor && $(inlines[i].editor.getRootElement()), // see MultiRangeInlineEditor\n                $otherDiv = inlines[i].$htmlContent;\n\n            if ($inlineEditorRoot && divContainsMouse($inlineEditorRoot, mousePos)) {\n                editor = inlines[i].editor;\n                break;\n            } else if ($otherDiv && divContainsMouse($otherDiv, mousePos)) {\n                // Mouse inside unsupported inline editor like Quick Docs or Color Editor\n                return;\n            }\n        }\n\n        // Check main editor\n        if (!editor) {\n            if (divContainsMouse($(fullEditor.getRootElement()), mousePos)) {\n                editor = fullEditor;\n            }\n        }\n\n        return editor;\n    }\n\n    /**\n     * Changes the current hidden popoverState to visible, showing it in the UI and highlighting\n     * its matching text in the editor.\n     */\n    function showPreview(editor, popover) {\n        var token, cm;\n\n        // Figure out which editor we are over\n        if (!editor) {\n            editor = getHoveredEditor(lastMousePos);\n        }\n\n        if (!editor || !editor._codeMirror) {\n            hidePreview();\n            return;\n        }\n\n        cm = editor._codeMirror;\n\n        // Find char mouse is over\n        var pos = cm.coordsChar({left: lastMousePos.clientX, top: lastMousePos.clientY});\n\n        // No preview if mouse is past last char on line\n        if (pos.ch >= editor.document.getLine(pos.line).length) {\n            return;\n        }\n\n        if (popover) {\n            popoverState = popover;\n        } else {\n            // Query providers and append to popoverState\n            token = TokenUtils.getTokenAt(cm, pos);\n            popoverState = $.extend({}, popoverState, queryPreviewProviders(editor, pos, token));\n        }\n\n        if (popoverState && popoverState.start && popoverState.end) {\n            popoverState.marker = cm.markText(\n                popoverState.start,\n                popoverState.end,\n                {className: \"quick-view-highlight\"}\n            );\n\n            $previewContent.append(popoverState.content);\n            $previewContainer.show();\n\n            popoverState.visible = true;\n\n            if (popoverState.onShow) {\n                popoverState.onShow();\n            } else {\n                positionPreview(editor, popoverState.xpos, popoverState.ytop, popoverState.ybot);\n            }\n        }\n    }\n\n    function processMouseMove() {\n        animationRequest = null;\n\n        if (!lastMousePos) {\n            return;         // should never get here, but safety first!\n        }\n\n        var showImmediately = false,\n            editor = null;\n\n        if (popoverState && popoverState.visible) {\n            // Only figure out which editor we are over when there is already a popover\n            // showing (otherwise wait until after delay to minimize processing)\n            editor = getHoveredEditor(lastMousePos);\n            if (editor && editor._codeMirror) {\n                // Find char mouse is over\n                var cm = editor._codeMirror,\n                    pos = cm.coordsChar({left: lastMousePos.clientX, top: lastMousePos.clientY});\n\n                if (popoverState.start && popoverState.end &&\n                        editor.posWithinRange(pos, popoverState.start, popoverState.end, true) &&\n                        (pos.ch < editor.document.getLine(pos.line).length)) {\n\n                    // That one's still relevant - nothing more to do\n                    // Note: posWithinRange() includes mouse past end of line, so need to check for that case\n                    return;\n                }\n            }\n\n            // That one doesn't cover this pos - hide it and start anew\n            showImmediately = true;\n        }\n\n        // Initialize popoverState\n        hidePreview();\n        popoverState = {};\n\n        // Set timer to scan and show. This will get cancelled (in hidePreview())\n        // if mouse movement rendered this popover inapplicable before timer fires.\n        // When showing \"immediately\", still use setTimeout() to make this async\n        // so we return from this mousemove event handler ASAP.\n        popoverState.hoverTimer = window.setTimeout(function () {\n            showPreview(editor);\n        }, showImmediately ? 0 : HOVER_DELAY);\n    }\n\n    function handleMouseMove(event) {\n        lastMousePos = null;\n\n        if (!enabled) {\n            return;\n        }\n\n        if (event.which) {\n            // Button is down - don't show popovers while dragging\n            hidePreview();\n            return;\n        }\n\n        // Keep track of last mouse position\n        lastMousePos = {\n            clientX: event.clientX,\n            clientY: event.clientY\n        };\n\n        // Prevent duplicate animation frame requests\n        if (!animationRequest) {\n            animationRequest = window.requestAnimationFrame(processMouseMove);\n        }\n    }\n\n    function onActiveEditorChange(event, current, previous) {\n        // Hide preview when editor changes\n        hidePreview();\n\n        if (previous && previous.document) {\n            previous.document.off(\"change\", hidePreview);\n        }\n\n        if (current && current.document) {\n            current.document.on(\"change\", hidePreview);\n        }\n    }\n\n    // Menu command handlers\n    function updateMenuItemCheckmark() {\n        CommandManager.get(CMD_ENABLE_QUICK_VIEW).setChecked(enabled);\n    }\n\n    function setExtensionlessImagePreview(_extensionlessImagePreview, doNotSave) {\n        if (extensionlessImagePreview !== _extensionlessImagePreview) {\n            extensionlessImagePreview = _extensionlessImagePreview;\n            if (!doNotSave) {\n                prefs.set(\"extensionlessImagePreview\", enabled);\n                prefs.save();\n            }\n        }\n    }\n\n    function setEnabled(_enabled, doNotSave) {\n        if (enabled !== _enabled) {\n            enabled = _enabled;\n            var editorHolder = $(\"#editor-holder\")[0];\n            if (enabled) {\n                // Note: listening to \"scroll\" also catches text edits, which bubble a scroll event up from the hidden text area. This means\n                // we auto-hide on text edit, which is probably actually a good thing.\n                editorHolder.addEventListener(\"mousemove\", handleMouseMove, true);\n                editorHolder.addEventListener(\"scroll\", hidePreview, true);\n                editorHolder.addEventListener(\"mouseout\", hidePreview, true);\n\n                // Setup doc \"change\" listener\n                onActiveEditorChange(null, EditorManager.getActiveEditor(), null);\n                EditorManager.on(\"activeEditorChange\", onActiveEditorChange);\n\n            } else {\n                editorHolder.removeEventListener(\"mousemove\", handleMouseMove, true);\n                editorHolder.removeEventListener(\"scroll\", hidePreview, true);\n                editorHolder.removeEventListener(\"mouseout\", hidePreview, true);\n\n                // Cleanup doc \"change\" listener\n                onActiveEditorChange(null, null, EditorManager.getActiveEditor());\n                EditorManager.off(\"activeEditorChange\", onActiveEditorChange);\n\n                hidePreview();\n            }\n            if (!doNotSave) {\n                prefs.set(\"enabled\", enabled);\n                prefs.save();\n            }\n        }\n        // Always update the checkmark, even if the enabled flag hasn't changed.\n        updateMenuItemCheckmark();\n    }\n\n    function toggleEnableQuickView() {\n        setEnabled(!enabled);\n    }\n\n    function _forceShow(popover) {\n        hidePreview();\n        lastMousePos = {\n            clientX: popover.xpos,\n            clientY: Math.floor((popover.ybot + popover.ytop) / 2)\n        };\n        showPreview(popover.editor, popover);\n    }\n\n    // Create the preview container\n    $previewContainer = $(previewContainerHTML).appendTo($(\"body\"));\n    $previewContent = $previewContainer.find(\".preview-content\");\n\n    // Load our stylesheet\n    ExtensionUtils.loadStyleSheet(module, \"QuickView.less\");\n\n    // Register command\n    // Insert menu at specific pos since this may load before OR after code folding extension\n    CommandManager.register(Strings.CMD_ENABLE_QUICK_VIEW, CMD_ENABLE_QUICK_VIEW, toggleEnableQuickView);\n    Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(CMD_ENABLE_QUICK_VIEW, null, Menus.AFTER, Commands.VIEW_TOGGLE_INSPECTION);\n\n    // Setup initial UI state\n    setEnabled(prefs.get(\"enabled\"), true);\n    setExtensionlessImagePreview(prefs.get(\"extensionlessImagePreview\"), true);\n\n    prefs.on(\"change\", \"enabled\", function () {\n        setEnabled(prefs.get(\"enabled\"), true);\n    });\n\n    prefs.on(\"change\", \"extensionlessImagePreview\", function () {\n        setExtensionlessImagePreview(prefs.get(\"extensionlessImagePreview\"));\n    });\n\n    // For unit testing\n    exports._queryPreviewProviders  = queryPreviewProviders;\n    exports._forceShow              = _forceShow;\n});\n"
  },
  {
    "path": "src/extensions/default/QuickView/unittest-files/test.css",
    "content": "/* Sample CSS for testing the QuickView extension. */\n\n.hex_values {\n    color: #369;\n    color: #2491F5;\n}\n\n#invalid_hex_values {\n    color: #web;\n}\n\n.rgb_rgba_values {\n    color: rgb(255,0,0);            /* no whitespace */\n    color: rgb(100%,   0%,   0%);   /* extra whitespace */\n    color: rgb(50%, 75%, 25%);\n    color: rgba(255, 0, 0, 0.5);\n    color: rgba(255, 0, 0, 1);\n    color: rgba(255, 0, 0, .5);\n    color: rgba(100%, 0%, 0%, 0.5);\n    color: rgba(50%,75%,25%, 0.5);\n    color: rgba(80%, 50%, 50%, 1);\n    color: rgba(50%, 75%, 25%, 1.0);\n}\n\n.unsupported_rgb_rgba_values {\n    color: rgb(300, 0, 0);\n    color: rgb(0, 95.5, 0);\n    color: rgba(-0, 0, 0, 0.5);\n}\n\n.hsl_hsla_values {\n    color: hsl(0, 100%, 50%);\n    color: hsla(0, 100%, 50%, 0.5);\n    color: hsla(0, 100%, 50%, .5);\n    color: hsl(390, 100%, 50%);\n}\n\n.unsupported_hsl_hsla_values {\n    color: hsla(90, 100%, 50%, 2);\n    color: hsla(0, 200%, 50%, 0.5);\n    color: hsla(0.0, 100%, 50%, .5);\n}\n\n.color_names {\n    color: aliceblue;\n    color: blanchedalmond;\n    color: blue;\n    color: blueviolet;\n    color: brown;\n    color: darkgoldenrod;\n    color: darkgray;\n    color: firebrick;\n    color: floralwhite;\n    color: honeydew;\n    color: hotpink;\n    color: khaki;\n    color: lavenderblush;\n    color: lightgreen;\n    color: lightsalmon;\n    color: lightseagreen;\n    color: olive;\n    color: salmon;\n    color: sandybrown;\n    color: seagreen;\n    color: teal;\n    color: thistle;\n    color: tomato;\n    color: turquoise;\n    color: whitesmoke;\n}\n\n.invalid_color_names {\n    color: redsox;\n    color: pinky;\n    color: blue-cheese;\n    color: @bc-bg-highlight;\n}\n\n.gradients {\n\nbackground: -moz-linear-gradient(top,  #d2dfed 0%, #c8d7eb 26%, #bed0ea 51%, #a6c0e3 51%, #afc7e8 62%, #bad0ef 75%, #99b5db 88%, #799bc8 100%); /* FF3.6+ */\nbackground: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#d2dfed), color-stop(26%,#c8d7eb), color-stop(51%,#bed0ea), color-stop(51%,#a6c0e3), color-stop(62%,#afc7e8), color-stop(75%,#bad0ef), color-stop(88%,#99b5db), color-stop(100%,#799bc8)); /* Chrome,Safari4+ */\nbackground: -webkit-linear-gradient(top,  #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 51%,#afc7e8 62%,#bad0ef 75%,#99b5db 88%,#799bc8 100%); /* Chrome10+,Safari5.1+ */\nbackground: -o-linear-gradient(top,  #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 51%,#afc7e8 62%,#bad0ef 75%,#99b5db 88%,#799bc8 100%); /* Opera 11.10+ */\nbackground: -ms-linear-gradient(top,  #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 51%,#afc7e8 62%,#bad0ef 75%,#99b5db 88%,#799bc8 100%); /* IE10+ */\n}\n\n/* From css3please.com */\n.box_gradient {\n    background-color: #333;\n    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(51,51,51)), to(rgb(204,204,204))); /* Chrome, Safari 4+ */\n    background-image: -webkit-linear-gradient(top, #333, #CCC); /* Chrome 10-25, iOS 5+, Safari 5.1+ */\n    background-image:    -moz-linear-gradient(top, #333, #CCC); /* Firefox 3.6-15 */\n    background-image:      -o-linear-gradient(top, #333, #CCC); /* Opera 11.10-12.00 */\n    background-image:         linear-gradient(to bottom, #333, #CCC); /* Chrome 26, Firefox 16+, IE 10+, Opera 12.10+ */\n}\n\n/* other forms supported by spec */\n.box_gradient1 { background-image: linear-gradient(to right, #333, #CCC); }\n.box_gradient2 { background-image: linear-gradient(#333, #CCC); }\n.box_gradient3 { background-image: linear-gradient(to bottom right, #333, #CCC); }\n.box_gradient4 { background-image: linear-gradient(135deg, #333, #CCC); }\n\n/* multiple colors */\n.box_gradient5 { background-image: linear-gradient(#333, #CCC, #333); }\n.box_gradient6 { background-image: linear-gradient(#333 0%, #CCC 33%, #333 100%); }\n.box_gradient7 { background-image: linear-gradient(yellow, blue 20%, #0f0); }\n\n/* www.impressivewebs.com */\n.radial_gradient {\n    background-image: -webkit-gradient(radial, center center, 0, center center, 141, from(black), to(white), color-stop(25%, blue), color-stop(40%, green), color-stop(60%, red), color-stop(80%, purple));\n    background-image: -webkit-radial-gradient(center center, circle contain, black 0%, blue 25%, green 40%, red 60%, purple 80%, white 100%);\n    background-image: -moz-radial-gradient(center center, circle contain, black 0%, blue 25%, green 40%, red 60%, purple 80%, white 100%);\n    background-image: -ms-radial-gradient(center center, circle contain, black 0%, blue 25%, green 40%, red 60%, purple 80%, white 100%); /* IE10+ */\n    background-image: -o-radial-gradient(center center, circle contain, black 0%, blue 25%, green 40%, red 60%, purple 80%, white 100%); /* Opera (13?) */\n}\n\n.new_radial_gradient {\n    background-image: radial-gradient(yellow, green);\n}\n\n.repeating_linear_gradient {\n    background-image: repeating-linear-gradient(red, blue 20px, red 40px);\n    background-image: repeating-linear-gradient(red 0px, white 0px, blue 0px);\n    background-image: repeating-linear-gradient(red 0px, white .1px, blue .2px);\n}\n\n.repeating_linear_gradient {\n    background-image: repeating-radial-gradient(circle closest-side at 20px 30px, red, yellow, green 100%, yellow 150%, red 200%);\n    background-image: repeating-radial-gradient(red, blue 20px, red 40px);\n}\n\n/* lea.verou.me/css3patterns */\n.gradient_pattern {\n    background:\n        linear-gradient(63deg, #999 23%, transparent 23%) 7px 0,\n        linear-gradient(63deg, transparent 74%, #999 78%), linear-gradient(63deg, transparent 0%, #999 38%, #999 58%, transparent 100%), #444;\n}\n\n.images {\n    background: url(img/grabber_color-well.png);\n    background: url(\"img/Color.png\");\n    background: url(img/throbber.gif);\n    background: url('img/update_large_icon.svg');\n\n    background: \"https://raw.github.com/gruehle/HoverPreview/master/screenshots/Image.png\";\n\n    background: \"img/med_hero.jpg\";\n    background: 'img/Gradient.png';\n    background: 'img/specials.jpeg';\n}\n\n.foo {\n    background: -webkit-image-set(url(\"img/specials.jpeg\") 1x, url(\"img/Gradient.png\") 2x);\n    background: -webkit-image-set(url(img/specials.jpeg) 1x,   url(img/Gradient.png) 2x);\n    background: -webkit-image-set(\"img/specials.jpeg\" 1x,      \"img/Gradient.png\" 2x);\n}\n\n.data {\n    background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAABq0lEQVQoU11RPUgcURD+Zt/unnrcCf4QIugRMcS7a2xjmmArRlRIFRBFgrVtGgmBRFCwTBoLsQiBGMxiJ4iksLRSFEzQRC2EAwm5g727feP3LpyFy1tm5s33zcz7RnDvG4x0zFgMJRY/jiewhy/w8FKSJkyaTuG7Fumvi+ARbQiLpcMDvH/Qj1S6Bf6vI5SxKPUG4fGm5kMf6wr08MKHILCKldoZlk0OIeuHjNuDBBcNAqvvENTLwKii1ZFoF/7G2PQDpNo8dFUt1AcSGfymz42PVfI8ghxht1bHh9MpucCiegMFdJoUOtSD+MxLPtI5T/GaHWhg+NjRk3G5utPikwb5bjzhq40JSChs6Sx1eOYAojg/fCFv7yvnBLGCLPMqxS2dZrtXnDthhySuYebnpFw3ST2RtmUVIx5z1sIKdX9qgDcOTJAj7WsNa8eTUhrY0Gwqg2FldeZiduH5r9JHvqEDigzDS/4VJvYJfMh9VLmbNO9+s9hNg5D/qjkJ8I6uW0yFtkrwHydCg+AhVgsp/8Pnu00XI+0jYJ7gjANRiEsmQ3aNOXuJhG035i1QA6g+uONCrgAAAABJRU5ErkJggg==\");\n}\n\n.pixelGradient {\n    background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%, green 300px, red 600px); \n    background-image: repeating-linear-gradient(red, blue 20px, red 40px);\n    background-image: repeating-radial-gradient(red, blue 20px, red 40px);    \n}\n\n.whitespaceCheck_linear_gradient { \n    background : linear-gradient(to bottom, black 0%, white 100%); \n    background: linear-gradient(to bottom, black 0%, white 100%);\n    background :linear-gradient(to bottom, black 0%, white 100%);\n    background:linear-gradient(to bottom, black 0%, white 100%);\n}\n\n.whitespaceCheck_radial_gradient {\n    background : radial-gradient(red, white 50%, blue 100%);\n    background: radial-gradient(red, white 50%, blue 100%);\n    background :radial-gradient(red, white 50%, blue 100%);\n    background:radial-gradient(red, white 50%, blue 100%);\n}\n\n.quotes {\n    background: url(img/don't.png);\n    background: url(\"img/don't.png\");\n    background:url(\"data:image/svg+xml;utf8, <svg version='1.1' xmlns='http://www.w3.org/2000/svg'></svg>\");\n}\n\n.unbalanced-parens {\n    background-image: linear-gradient(to bottom, #333, #CCC;\n    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(51,51,51)), to(rgb(204,204,204));\n}\n\n.good-preview-image-urls {\n    background: \"http://example.com/image.gif\";\n    background: \"http://example.com/image.png\";\n    background: \"http://example.com/image.jpe\";\n    background: \"http://example.com/image.jpeg\";\n    background: \"http://example.com/image.jpg\";\n    background: \"http://example.com/image.ico\";\n    background: \"http://example.com/image.bmp\";\n    background: \"http://example.com/image.svg\";\n\n    background: \"https://image.service.com/id/1234513\";\n    background: \"http://image.service.com/id/1234513\";\n    background: \"https://image.service.com/id/1234513?w=300&h=400\";\n}\n\n.ignored-preview-image-urls {\n    background: \"https://website.com/index.html\";\n    background: \"https://website.com/style.css\";\n    background: \"https://website.com/script.js\";\n    background: \"https://website.com/package.json\";\n    background: \"https://website.com/readme.md\";\n    background: \"https://website.com/data.xml\";\n    background: \"https://website.com/music.mp3\";\n    background: \"https://website.com/video.ogv\";\n    background: \"https://website.com/video.mp4\";\n    background: \"https://website.com/video.mpeg\";\n    background: \"https://website.com/video.webm\";\n    background: \"https://website.com/archive.zip\";\n    background: \"https://website.com/archive.tgz\";\n}\n"
  },
  {
    "path": "src/extensions/default/QuickView/unittest-files/test.js",
    "content": "/* Sample JS for testing the QuickView extension. */\n\nfunction green() { // generate green colors\n    var color = \"green\",\n        tan = Math.tan;\n    return tan(array[\"red\"], array[red]);\n}\ndarkgray\n// #123456\n// :rgb(65, 43, 21)\n"
  },
  {
    "path": "src/extensions/default/QuickView/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, runs, waitsForDone */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils    = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        FileUtils          = brackets.getModule(\"file/FileUtils\"),\n        PreferencesManager = brackets.getModule(\"preferences/PreferencesManager\"),\n        prefs              = PreferencesManager.getExtensionPrefs(\"quickview\");\n\n    describe(\"Quick View\", function () {\n        var testFolder = FileUtils.getNativeModuleDirectoryPath(module) + \"/unittest-files/\";\n\n        // load from testWindow\n        var testWindow,\n            brackets,\n            extensionRequire,\n            CommandManager,\n            Commands,\n            EditorManager,\n            QuickView,\n            editor,\n            testFile = \"test.css\",\n            oldFile;\n\n        beforeEach(function () {\n            // Create a new window that will be shared by ALL tests in this spec.\n            if (!testWindow) {\n                runs(function () {\n                    SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                        testWindow = w;\n                        // Load module instances from brackets.test\n                        brackets = testWindow.brackets;\n                        CommandManager = brackets.test.CommandManager;\n                        Commands = brackets.test.Commands;\n                        EditorManager = brackets.test.EditorManager;\n                        extensionRequire = brackets.test.ExtensionLoader.getRequireContextForExtension(\"QuickView\");\n                        QuickView = extensionRequire(\"main\");\n                    });\n                });\n\n                runs(function () {\n                    SpecRunnerUtils.loadProjectInTestWindow(testFolder);\n                });\n            }\n\n            if (testFile !== oldFile) {\n                runs(function () {\n                    waitsForDone(SpecRunnerUtils.openProjectFiles([testFile]), \"open test file: \" + testFile);\n                });\n\n                runs(function () {\n                    editor  = EditorManager.getCurrentFullEditor();\n                    oldFile = testFile;\n                });\n            }\n        });\n\n        function getPopoverAtPos(lineNum, columnNum) {\n            var cm = editor._codeMirror,\n                pos = { line: lineNum, ch: columnNum },\n                token;\n\n            editor.setCursorPos(pos);\n            token = cm.getTokenAt(pos, true);\n\n            return QuickView._queryPreviewProviders(editor, pos, token);\n        }\n\n        function expectNoPreviewAtPos(line, ch) {\n            var popoverInfo = getPopoverAtPos(line, ch);\n            expect(popoverInfo).toBeFalsy();\n        }\n\n        function checkColorAtPos(expectedColor, line, ch) {\n            var popoverInfo = getPopoverAtPos(line, ch);\n            expect(popoverInfo._previewCSS).toBe(expectedColor);\n        }\n\n        function checkGradientAtPos(expectedGradient, line, ch) {\n            // Just call checkColorAtPos since both have the same function calls.\n            checkColorAtPos(expectedGradient, line, ch);\n        }\n\n        function checkImagePathAtPos(expectedPathEnding, line, ch) {\n            var popoverInfo = getPopoverAtPos(line, ch),\n                imagePath = popoverInfo._imgPath;\n\n            // Just check end of path - local drive location prefix unimportant\n            expect(imagePath.substr(imagePath.length - expectedPathEnding.length)).toBe(expectedPathEnding);\n        }\n\n        function checkImageDataAtPos(expectedData, line, ch) {\n            var popoverInfo = getPopoverAtPos(line, ch);\n            expect(popoverInfo._imgPath).toBe(expectedData);\n        }\n\n        describe(\"Quick view colors\", function () {\n            it(\"should show preview of hex colors either in 3 digit hex or or 6-digit hex\", function () {\n                runs(function () {\n                    checkColorAtPos(\"#369\", 3, 12);\n                    checkColorAtPos(\"#2491F5\", 4, 13);\n                });\n            });\n\n            it(\"should NOT show preview of color on words start with #\", function () {\n                runs(function () {\n                    expectNoPreviewAtPos(7, 7);     // cursor on #invalid_hex\n                    expectNoPreviewAtPos(8, 15);    // cursor on #web\n                });\n            });\n\n            it(\"should show preview of valid rgb/rgba colors\", function () {\n                runs(function () {\n                    checkColorAtPos(\"rgb(255,0,0)\",           12, 12);  // no whitespace\n                    checkColorAtPos(\"rgb(100%,   0%,   0%)\",  13, 17);  // extra whitespace\n                    checkColorAtPos(\"rgb(50%, 75%, 25%)\",     14, 24);\n\n                    // rgba with values of 0-255\n                    checkColorAtPos(\"rgba(255, 0, 0, 0.5)\", 15, 23);\n                    checkColorAtPos(\"rgba(255, 0, 0, 1)\",   16, 22);\n                    checkColorAtPos(\"rgba(255, 0, 0, .5)\",  17, 19);\n\n                    // rgba with percentage values\n                    checkColorAtPos(\"rgba(100%, 0%, 0%, 0.5)\",  18, 32);\n                    checkColorAtPos(\"rgba(80%, 50%, 50%, 1)\",   20, 33);\n                    checkColorAtPos(\"rgba(50%, 75%, 25%, 1.0)\", 21, 23);\n                });\n            });\n\n            it(\"should NOT show preview of unsupported rgb/rgba colors\", function () {\n                runs(function () {\n                    expectNoPreviewAtPos(25, 14);    // cursor on rgb(300, 0, 0)\n                    expectNoPreviewAtPos(26, 15);    // cursor on rgb(0, 95.5, 0)\n                    expectNoPreviewAtPos(27, 15);    // cursor on rgba(-0, 0, 0, 0.5)\n                });\n            });\n\n            it(\"should show preview of valid hsl/hsla colors\", function () {\n                runs(function () {\n                    checkColorAtPos(\"hsl(0, 100%, 50%)\",       31, 22);\n                    checkColorAtPos(\"hsla(0, 100%, 50%, 0.5)\", 32, 23);\n                    checkColorAtPos(\"hsla(0, 100%, 50%, .5)\",  33, 23);\n                    checkColorAtPos(\"hsl(390, 100%, 50%)\",     34, 24);\n                });\n            });\n\n            it(\"should NOT show preview of unsupported hsl/hsla colors\", function () {\n                runs(function () {\n                    expectNoPreviewAtPos(38, 25);    // cursor on hsla(90, 100%, 50%, 2)\n                    expectNoPreviewAtPos(39, 24);    // cursor on hsla(0, 200%, 50%, 0.5)\n                    expectNoPreviewAtPos(40, 25);    // cursor on hsla(0.0, 100%, 50%, .5)\n                });\n            });\n\n            it(\"should show preview of colors with valid names\", function () {\n                runs(function () {\n                    checkColorAtPos(\"blueviolet\",    47, 15);\n                    checkColorAtPos(\"darkgoldenrod\", 49, 16);\n                    checkColorAtPos(\"darkgray\",      50, 16);\n                    checkColorAtPos(\"firebrick\",     51, 15);\n                    checkColorAtPos(\"honeydew\",      53, 16);\n                    checkColorAtPos(\"lavenderblush\", 56, 16);\n                    checkColorAtPos(\"salmon\",        61, 16);\n                    checkColorAtPos(\"tomato\",        66, 16);\n                });\n            });\n\n            it(\"should NOT show preview of colors with invalid names\", function () {\n                runs(function () {\n                    expectNoPreviewAtPos(72, 15);    // cursor on redsox\n                    expectNoPreviewAtPos(73, 16);    // cursor on pinky\n                    expectNoPreviewAtPos(74, 16);    // cursor on blue in hyphenated word blue-cheese\n                    expectNoPreviewAtPos(75, 18);    // cursor on white in hyphenated word @bc-bg-highlight\n                });\n            });\n\n            describe(\"JavaScript file\", function () {\n                runs(function () {\n                    testFile = \"test.js\";\n                });\n\n                it(\"should NOT show preview of color-named functions and object/array keys\", function () {\n                    runs(function () {\n                        expectNoPreviewAtPos(2, 12);    // cursor on green()\n                        expectNoPreviewAtPos(4, 22);    // cursor on Math.tan\n                        expectNoPreviewAtPos(5, 14);    // cursor on tan()\n                        expectNoPreviewAtPos(5, 38);    // cursor on array[red]\n                    });\n                });\n                it(\"should not show preview of literal color names\", function () {\n                    runs(function () {\n                        expectNoPreviewAtPos(2, 36);  // green\n                        expectNoPreviewAtPos(3, 21);  // green\n                        expectNoPreviewAtPos(4, 11);  // tan\n                        expectNoPreviewAtPos(5, 25);  // red\n                        expectNoPreviewAtPos(7,  1);  // darkgray\n                    });\n                });\n                it(\"should show preview of non-literal color codes\", function () {\n                    runs(function () {\n                        checkColorAtPos(\"#123456\",          8, 7);\n                        checkColorAtPos(\"rgb(65, 43, 21)\",  9, 8);\n                    });\n                });\n            });\n        });\n\n        describe(\"Quick view gradients\", function () {\n            runs(function () {\n                testFile = \"test.css\";\n            });\n\n            it(\"Should show linear gradient preview for those with vendor prefix\", function () {\n                runs(function () {\n                    var expectedGradient1 = \"-webkit-linear-gradient(top,  #d2dfed 0%, #c8d7eb 26%, #bed0ea 51%, #a6c0e3 51%, #afc7e8 62%, #bad0ef 75%, #99b5db 88%, #799bc8 100%)\",\n                        expectedGradient2 = \"-webkit-gradient(linear, left top, left bottom, color-stop(0%,#d2dfed), color-stop(26%,#c8d7eb), color-stop(51%,#bed0ea), color-stop(51%,#a6c0e3), color-stop(62%,#afc7e8), color-stop(75%,#bad0ef), color-stop(88%,#99b5db), color-stop(100%,#799bc8))\",\n                        expectedGradient3 = \"-webkit-linear-gradient(top,  #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 51%,#afc7e8 62%,#bad0ef 75%,#99b5db 88%,#799bc8 100%)\",\n                        expectedGradient4 = \"-webkit-gradient(linear, left top, left bottom, from(rgb(51,51,51)), to(rgb(204,204,204)))\";\n                    checkGradientAtPos(expectedGradient1, 80, 36);   // -moz- prefix gets stripped\n                    checkGradientAtPos(expectedGradient2, 81, 36);   // Old webkit syntax\n                    checkGradientAtPos(expectedGradient3, 82, 36);   // -webkit- prefix gets stripped\n                    checkGradientAtPos(expectedGradient3, 83, 36);   // -o- prefix gets stripped\n                    checkGradientAtPos(expectedGradient3, 84, 36);   // -ms- prefix gets stripped\n                    checkGradientAtPos(expectedGradient4, 90, 36);   // test parameters with 2 levels of nested parens\n                });\n            });\n\n            it(\"Should show linear gradient preview for those with colon or space before\", function () {\n                runs(function () {\n                    var expectedGradient = \"linear-gradient(to bottom, black 0%, white 100%)\";\n                    checkGradientAtPos(expectedGradient, 169, 25);   // space colon space\n                    checkGradientAtPos(expectedGradient, 170, 25);   // colon space\n                    checkGradientAtPos(expectedGradient, 171, 25);   // space colon\n                    checkGradientAtPos(expectedGradient, 172, 25);   // colon\n                });\n            });\n\n            it(\"Should show radial gradient preview for those with colon or space before\", function () {\n                runs(function () {\n                    var expectedGradient = \"radial-gradient(red, white 50%, blue 100%)\";\n                    checkGradientAtPos(expectedGradient, 176, 25);   // space colon space\n                    checkGradientAtPos(expectedGradient, 177, 25);   // colon space\n                    checkGradientAtPos(expectedGradient, 178, 25);   // space colon\n                    checkGradientAtPos(expectedGradient, 179, 25);   // colon\n                });\n            });\n\n            it(\"Should show linear gradient preview for those with w3c standard syntax (no prefix)\", function () {\n                runs(function () {\n                    checkGradientAtPos(\"linear-gradient(#333, #CCC)\",                  99, 50);\n                    checkGradientAtPos(\"linear-gradient(135deg, #333, #CCC)\",          101, 50);\n\n                    checkGradientAtPos(\"linear-gradient(to right, #333, #CCC)\",        98, 50);\n                    checkGradientAtPos(\"linear-gradient(to bottom right, #333, #CCC)\", 100, 50);\n\n\n                    // multiple colors\n                    checkGradientAtPos(\"linear-gradient(#333, #CCC, #333)\",             104, 50);\n                    checkGradientAtPos(\"linear-gradient(#333 0%, #CCC 33%, #333 100%)\", 105, 50);\n                    checkGradientAtPos(\"linear-gradient(yellow, blue 20%, #0f0)\",       106, 50);\n                });\n            });\n\n            it(\"Should show radial gradient preview for those with vendor prefix syntax\", function () {\n                runs(function () {\n                    var expectedGradient1 = \"-webkit-gradient(radial, center center, 0, center center, 141, from(black), to(white), color-stop(25%, blue), color-stop(40%, green), color-stop(60%, red), color-stop(80%, purple))\",\n                        expectedGradient2 = \"-webkit-radial-gradient(center center, circle contain, black 0%, blue 25%, green 40%, red 60%, purple 80%, white 100%)\";\n                    checkGradientAtPos(expectedGradient1, 110, 93);   // old webkit syntax\n                    checkGradientAtPos(expectedGradient2, 111, 36);   // -webkit- prefix preserved\n                    checkGradientAtPos(expectedGradient2, 112, 36);   // -moz- prefix gets stripped\n                    checkGradientAtPos(expectedGradient2, 113, 36);   // -ms- prefix gets stripped\n                    checkGradientAtPos(expectedGradient2, 114, 36);   // -0- prefix gets stripped\n                });\n            });\n\n            it(\"Should show radial gradient preview for those with w3c standard syntax (no prefix)\", function () {\n                runs(function () {\n                    checkGradientAtPos(\"radial-gradient(yellow, green)\", 118, 35);\n                    checkGradientAtPos(\"radial-gradient(yellow, green)\", 118, 40);\n                });\n            });\n\n            it(\"Should show repeating linear gradient preview\", function () {\n                runs(function () {\n                    checkGradientAtPos(\"repeating-linear-gradient(red, blue 50%, red 100%)\", 122, 50);\n                    checkGradientAtPos(\"repeating-linear-gradient(red 0%, white 0%, blue 0%)\", 123, 50);\n                    checkGradientAtPos(\"repeating-linear-gradient(red 0%, white 50%, blue 100%)\", 124, 50);\n                });\n            });\n\n            it(\"Should show repeating radial gradient preview\", function () {\n                runs(function () {\n                    checkGradientAtPos(\"repeating-radial-gradient(circle closest-side at 20px 30px, red, yellow, green 100%, yellow 150%, red 200%)\", 128, 40);\n                    checkGradientAtPos(\"repeating-radial-gradient(red, blue 50%, red 100%)\", 129, 40);\n                });\n            });\n\n            it(\"Should show comma-separated gradients\", function () {\n                runs(function () {\n                    // line ending in comma\n                    checkGradientAtPos(\"linear-gradient(63deg, #999 23%, transparent 23%)\", 135,  50);\n\n                    // multiple gradients on a line\n                    checkGradientAtPos(\"linear-gradient(63deg, transparent 74%, #999 78%)\", 136,  50);\n                    checkGradientAtPos(\"linear-gradient(63deg, transparent 0%, #999 38%, #999 58%, transparent 100%)\",   136, 100);\n                });\n            });\n\n            it(\"Should convert gradients arguments from pixel to percent\", function () {\n                runs(function () {\n                    // linear gradient in px\n                    checkGradientAtPos(\"-webkit-linear-gradient(top, rgba(0,0,0,0) 0%, green 50%, red 100%)\", 163, 40);\n                    // repeating linear-gradient in pixels (no prefix)\n                    checkGradientAtPos(\"repeating-linear-gradient(red, blue 50%, red 100%)\", 164, 40);\n                    // repeating radial-gradient in pixels (no prefix)\n                    checkGradientAtPos(\"repeating-radial-gradient(red, blue 50%, red 100%)\", 165, 40);\n                });\n            });\n\n            it(\"Should not go into infinite loop on unbalanced parens\", function () {\n                runs(function () {\n                    // no preview, and no infinite loop\n                    expectNoPreviewAtPos(189, 30);\n                    expectNoPreviewAtPos(190, 40);\n                });\n            });\n        });\n\n        describe(\"Quick view display\", function () {\n\n            function showPopoverAtPos(line, ch) {\n                var popoverInfo = getPopoverAtPos(line, ch);\n                QuickView._forceShow(popoverInfo);\n            }\n\n            function getBounds(object, useOffset) {\n                var left = (useOffset ? object.offset().left : parseInt(object.css(\"left\"), 10)),\n                    top = (useOffset ? object.offset().top : parseInt(object.css(\"top\"), 10));\n                return {\n                    left:   left,\n                    top:    top,\n                    right:  left + object.outerWidth(),\n                    bottom: top + object.outerHeight()\n                };\n            }\n\n            function boundsInsideWindow(object) {\n                // For the popover, we can't use offset(), because jQuery gets confused by the\n                // scale factor and transform origin that the animation uses. Instead, we rely\n                // on the fact that its offset parent is body, and just test its explicit left/top\n                // values.\n                var bounds = getBounds(object, false),\n                    editorBounds = getBounds(testWindow.$(\"#editor-holder\"), true);\n                return bounds.left   >= editorBounds.left   &&\n                    bounds.right  <= editorBounds.right  &&\n                    bounds.top    >= editorBounds.top    &&\n                    bounds.bottom <= editorBounds.bottom;\n            }\n\n            function toggleOption(commandID, text) {\n                runs(function () {\n                    var promise = CommandManager.execute(commandID);\n                    waitsForDone(promise, text);\n                });\n            }\n\n            it(\"popover is positioned within window bounds\", function () {\n                var $popover  = testWindow.$(\"#quick-view-container\");\n                expect($popover.length).toEqual(1);\n\n                runs(function () {\n                    // Popover should be below item\n                    showPopoverAtPos(3, 12);\n                    expect(boundsInsideWindow($popover)).toBeTruthy();\n\n                    // Popover should above item\n                    showPopoverAtPos(20, 33);\n                    expect(boundsInsideWindow($popover)).toBeTruthy();\n                });\n\n                runs(function () {\n                    // Turn off word wrap for next tests\n                    toggleOption(Commands.TOGGLE_WORD_WRAP, \"Toggle word-wrap\");\n                });\n\n                runs(function () {\n                    // Popover should be inside right edge\n                    showPopoverAtPos(81, 36);\n                    expect(boundsInsideWindow($popover)).toBeTruthy();\n\n                    // Popover should be inside left edge\n                    var scrollX = editor._codeMirror.defaultCharWidth()  * 80,\n                        scrollY = editor._codeMirror.defaultTextHeight() * 70;\n\n                    editor.setScrollPos(scrollX, scrollY);      // Scroll right\n                    showPopoverAtPos(82, 136);\n                    expect(boundsInsideWindow($popover)).toBeTruthy();\n\n                    // restore word wrap\n                    toggleOption(Commands.TOGGLE_WORD_WRAP, \"Toggle word-wrap\");\n                });\n            });\n\n            it(\"highlight matched text when popover shown\", function () {\n                showPopoverAtPos(4, 14);\n                var markers = editor._codeMirror.findMarksAt({line: 4, ch: 14});\n                expect(markers.length).toBe(1);\n                var range = markers[0].find();\n                expect(range.from.ch).toBe(11);\n                expect(range.to.ch).toBe(18);\n            });\n\n        });\n\n        describe(\"Quick view images\", function () {\n            it(\"Should show image preview for file path inside url()\", function () {\n                runs(function () {\n                    checkImagePathAtPos(\"img/grabber_color-well.png\", 140, 26);\n                    checkImagePathAtPos(\"img/Color.png\",              141, 26);\n                    checkImagePathAtPos(\"img/throbber.gif\",           142, 26);\n                    checkImagePathAtPos(\"img/update_large_icon.svg\",  143, 26);\n                });\n            });\n\n            it(\"Should show image preview for urls with http/https\", function () {\n                runs(function () {\n                    checkImagePathAtPos(\"https://raw.github.com/gruehle/HoverPreview/master/screenshots/Image.png\", 145, 26);\n                });\n            });\n\n            it(\"Should show image preview for file path inside single or double quotes\", function () {\n                runs(function () {\n                    checkImagePathAtPos(\"img/med_hero.jpg\",  147, 26);\n                    checkImagePathAtPos(\"img/Gradient.png\",  148, 26);\n                    checkImagePathAtPos(\"img/specials.jpeg\", 149, 26);\n                });\n            });\n\n            it(\"Should show image preview for subsequent images in a line\", function () {\n                runs(function () {\n                    checkImagePathAtPos(\"img/Gradient.png\", 153, 80);    // url(\"\")\n                    checkImagePathAtPos(\"img/Gradient.png\", 154, 80);    // url()\n                    checkImagePathAtPos(\"img/Gradient.png\", 155, 80);    // \"\"\n                });\n            });\n\n            it(\"Should show image preview for URIs containing quotes\", function () {\n                checkImagePathAtPos(\"img/don't.png\", 183, 26);  // url() containing '\n                checkImagePathAtPos(\"img/don't.png\", 184, 26);  // url(\"\") containing '\n                checkImageDataAtPos(\"data:image/svg+xml;utf8, <svg version='1.1' xmlns='http://www.w3.org/2000/svg'></svg>\", 185, 26);  // data url(\"\") containing '\n            });\n\n            it(\"Should show image preview for URLs with known image extensions\", function () {\n                checkImageDataAtPos(\"http://example.com/image.gif\", 194, 20);\n                checkImageDataAtPos(\"http://example.com/image.png\", 195, 20);\n                checkImageDataAtPos(\"http://example.com/image.jpe\", 196, 20);\n                checkImageDataAtPos(\"http://example.com/image.jpeg\", 197, 20);\n                checkImageDataAtPos(\"http://example.com/image.jpg\", 198, 20);\n                checkImageDataAtPos(\"http://example.com/image.ico\", 199, 20);\n                checkImageDataAtPos(\"http://example.com/image.bmp\", 200, 20);\n                checkImageDataAtPos(\"http://example.com/image.svg\", 201, 20);\n            });\n\n            it(\"Should show image preview for extensionless URLs (with protocol) with pref set\", function () {\n                // Flip the pref on and restore when done\n                var original = prefs.get(\"extensionlessImagePreview\");\n                prefs.set(\"extensionlessImagePreview\", true);\n\n                checkImageDataAtPos(\"https://image.service.com/id/1234513\", 203, 20); // https\n                checkImageDataAtPos(\"http://image.service.com/id/1234513\", 204, 20);  // http\n                checkImageDataAtPos(\"https://image.service.com/id/1234513?w=300&h=400\", 205, 20); // qs params\n\n                prefs.set(\"extensionlessImagePreview\", original);\n            });\n\n            it(\"Should not show image preview for extensionless URLs (with protocol) without pref set\", function () {\n                // Flip the pref off and restore when done\n                var original = prefs.get(\"extensionlessImagePreview\");\n                prefs.set(\"extensionlessImagePreview\", false);\n\n                checkImageDataAtPos(\"https://image.service.com/id/1234513\", 203, 20); // https\n                checkImageDataAtPos(\"http://image.service.com/id/1234513\", 204, 20);  // http\n                checkImageDataAtPos(\"https://image.service.com/id/1234513?w=300&h=400\", 205, 20); // qs params\n\n                prefs.set(\"extensionlessImagePreview\", original);\n            });\n\n            it(\"Should ignore URLs for common non-image extensions\", function () {\n                expectNoPreviewAtPos(209, 20); // .html\n                expectNoPreviewAtPos(210, 20); // .css\n                expectNoPreviewAtPos(211, 20); // .js\n                expectNoPreviewAtPos(212, 20); // .json\n                expectNoPreviewAtPos(213, 20); // .md\n                expectNoPreviewAtPos(214, 20); // .xml\n                expectNoPreviewAtPos(215, 20); // .mp3\n                expectNoPreviewAtPos(216, 20); // .ogv\n                expectNoPreviewAtPos(217, 20); // .mp4\n                expectNoPreviewAtPos(218, 20); // .mpeg\n                expectNoPreviewAtPos(219, 20); // .webm\n                expectNoPreviewAtPos(220, 20); // .zip\n                expectNoPreviewAtPos(221, 20); // .tgz\n            });\n\n            it(\"Should show image preview for a data URI inside url()\", function () {\n                runs(function () {\n                    checkImageDataAtPos(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAABq0lEQVQoU11RPUgcURD+Zt/unnrcCf4QIugRMcS7a2xjmmArRlRIFRBFgrVtGgmBRFCwTBoLsQiBGMxiJ4iksLRSFEzQRC2EAwm5g727feP3LpyFy1tm5s33zcz7RnDvG4x0zFgMJRY/jiewhy/w8FKSJkyaTuG7Fumvi+ARbQiLpcMDvH/Qj1S6Bf6vI5SxKPUG4fGm5kMf6wr08MKHILCKldoZlk0OIeuHjNuDBBcNAqvvENTLwKii1ZFoF/7G2PQDpNo8dFUt1AcSGfymz42PVfI8ghxht1bHh9MpucCiegMFdJoUOtSD+MxLPtI5T/GaHWhg+NjRk3G5utPikwb5bjzhq40JSChs6Sx1eOYAojg/fCFv7yvnBLGCLPMqxS2dZrtXnDthhySuYebnpFw3ST2RtmUVIx5z1sIKdX9qgDcOTJAj7WsNa8eTUhrY0Gwqg2FldeZiduH5r9JHvqEDigzDS/4VJvYJfMh9VLmbNO9+s9hNg5D/qjkJ8I6uW0yFtkrwHydCg+AhVgsp/8Pnu00XI+0jYJ7gjANRiEsmQ3aNOXuJhG035i1QA6g+uONCrgAAAABJRU5ErkJggg==\",  159, 26);\n                });\n\n                // This must be in the last spec in the suite.\n                runs(function () {\n                    this.after(function () {\n                        testWindow       = null;\n                        brackets         = null;\n                        CommandManager   = null;\n                        Commands         = null;\n                        EditorManager    = null;\n                        extensionRequire = null;\n                        QuickView        = null;\n                        SpecRunnerUtils.closeTestWindow();\n                    });\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/README.md",
    "content": "# Brackets Default Extensions\n\nThis directory contains extensions that ship with <strong>Brackets</strong> and are enabled\nby default. Examples include extensions for QuickOpen.\n\n(<code>README.md</code> serves as a dummy file so this directory can be added to git.)\n"
  },
  {
    "path": "src/extensions/default/RecentProjects/htmlContent/projects-menu.html",
    "content": "<ul id=\"project-dropdown\" class=\"dropdown-menu\" tabindex=\"-1\">\n    <li><a id=\"open-folder-link\">{{Strings.CMD_OPEN_FOLDER}}</a></li>\n    \n    {{#projectList.length}}\n    <li class=\"divider\"></li>\n    {{/projectList.length}}\n    \n    {{#projectList}}\n    <li>\n        <a class=\"recent-folder-link\" data-path=\"{{path}}\">\n            <span class=\"recent-folder\">{{folder}}</span>\n            <span class=\"recent-folder-path\">{{rest}}</span>\n        </a>\n    </li>\n    {{/projectList}}\n</ul>\n"
  },
  {
    "path": "src/extensions/default/RecentProjects/keyboard.json",
    "content": "{\n    \"recentProjects\": [\n        {\n            \"key\": \"Ctrl-Alt-R\"\n        }\n    ]\n}"
  },
  {
    "path": "src/extensions/default/RecentProjects/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var ProjectManager          = brackets.getModule(\"project/ProjectManager\"),\n        SidebarView             = brackets.getModule(\"project/SidebarView\"),\n        PreferencesManager      = brackets.getModule(\"preferences/PreferencesManager\"),\n        Commands                = brackets.getModule(\"command/Commands\"),\n        CommandManager          = brackets.getModule(\"command/CommandManager\"),\n        KeyBindingManager       = brackets.getModule(\"command/KeyBindingManager\"),\n        Menus                   = brackets.getModule(\"command/Menus\"),\n        MainViewManager         = brackets.getModule(\"view/MainViewManager\"),\n        ExtensionUtils          = brackets.getModule(\"utils/ExtensionUtils\"),\n        FileSystem              = brackets.getModule(\"filesystem/FileSystem\"),\n        AppInit                 = brackets.getModule(\"utils/AppInit\"),\n        KeyEvent                = brackets.getModule(\"utils/KeyEvent\"),\n        FileUtils               = brackets.getModule(\"file/FileUtils\"),\n        PopUpManager            = brackets.getModule(\"widgets/PopUpManager\"),\n        Strings                 = brackets.getModule(\"strings\"),\n        Mustache                = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        ProjectsMenuTemplate    = require(\"text!htmlContent/projects-menu.html\");\n\n    var KeyboardPrefs = JSON.parse(require(\"text!keyboard.json\"));\n\n\n    /** @const {string} Recent Projects commands ID */\n    var TOGGLE_DROPDOWN = \"recentProjects.toggle\";\n\n    /** @const {number} Maximum number of displayed recent projects */\n    var MAX_PROJECTS = 20;\n\n    /** @type {$.Element} jQuery elements used for the dropdown menu */\n    var $dropdownItem,\n        $dropdown,\n        $links;\n\n    /**\n     * Get the stored list of recent projects, fixing up paths as appropriate.\n     * Warning: unlike most paths in Brackets, these lack a trailing \"/\"\n     */\n    function getRecentProjects() {\n        var recentProjects = PreferencesManager.getViewState(\"recentProjects\") || [],\n            i;\n\n        for (i = 0; i < recentProjects.length; i++) {\n            // We have to canonicalize & then de-canonicalize the path here, since our pref format uses no trailing \"/\"\n            recentProjects[i] = FileUtils.stripTrailingSlash(ProjectManager.updateWelcomeProjectPath(recentProjects[i] + \"/\"));\n        }\n        return recentProjects;\n    }\n\n    /**\n     * Add a project to the stored list of recent projects, up to MAX_PROJECTS.\n     */\n    function add() {\n        var root = FileUtils.stripTrailingSlash(ProjectManager.getProjectRoot().fullPath),\n            recentProjects = getRecentProjects(),\n            index = recentProjects.indexOf(root);\n\n        if (index !== -1) {\n            recentProjects.splice(index, 1);\n        }\n        recentProjects.unshift(root);\n        if (recentProjects.length > MAX_PROJECTS) {\n            recentProjects = recentProjects.slice(0, MAX_PROJECTS);\n        }\n        PreferencesManager.setViewState(\"recentProjects\", recentProjects);\n    }\n\n    /**\n     * Check the list of items to see if any of them are hovered, and if so trigger a mouseenter.\n     * Normally the mouseenter event handles this, but when a previous item is deleted and the next\n     * item moves up to be underneath the mouse, we don't get a mouseenter event for that item.\n     */\n    function checkHovers(pageX, pageY) {\n        $dropdown.children().each(function () {\n            var offset = $(this).offset(),\n                width  = $(this).outerWidth(),\n                height = $(this).outerHeight();\n\n            if (pageX >= offset.left && pageX <= offset.left + width &&\n                    pageY >= offset.top && pageY <= offset.top + height) {\n                $(\".recent-folder-link\", this).triggerHandler(\"mouseenter\");\n            }\n        });\n    }\n\n    /**\n     * Create the \"delete\" button that shows up when you hover over a project.\n     */\n    function renderDelete() {\n        return $(\"<div id='recent-folder-delete' class='trash-icon'>&times;</div>\")\n            .mouseup(function (e) {\n                // Don't let the click bubble upward.\n                e.stopPropagation();\n\n                // Remove the project from the preferences.\n                var recentProjects = getRecentProjects(),\n                    index = recentProjects.indexOf($(this).parent().data(\"path\")),\n                    newProjects = [],\n                    i;\n                for (i = 0; i < recentProjects.length; i++) {\n                    if (i !== index) {\n                        newProjects.push(recentProjects[i]);\n                    }\n                }\n                PreferencesManager.setViewState(\"recentProjects\", newProjects);\n                $(this).closest(\"li\").remove();\n                checkHovers(e.pageX, e.pageY);\n\n                if (newProjects.length === 1) {\n                    $dropdown.find(\".divider\").remove();\n                }\n            });\n    }\n\n    /**\n     * Hide the delete button.\n     */\n    function removeDeleteButton() {\n        $(\"#recent-folder-delete\").remove();\n    }\n\n    /**\n     * Show the delete button over a given target.\n     */\n    function addDeleteButton($target) {\n        removeDeleteButton();\n        renderDelete()\n            .css(\"top\", $target.position().top + 6)\n            .appendTo($target);\n    }\n\n\n    /**\n     * Selects the next or previous item in the list\n     * @param {number} direction  +1 for next, -1 for prev\n     */\n    function selectNextItem(direction) {\n        var $links   = $dropdown.find(\"a\"),\n            index    = $dropdownItem ? $links.index($dropdownItem) : (direction > 0 ? -1 : 0),\n            $newItem = $links.eq((index + direction) % $links.length);\n\n        if ($dropdownItem) {\n            $dropdownItem.removeClass(\"selected\");\n        }\n        $newItem.addClass(\"selected\");\n\n        $dropdownItem = $newItem;\n        removeDeleteButton();\n    }\n\n    /**\n     * Deletes the selected item and\n     * move the focus to next item in list.\n     *\n     * @return {boolean} TRUE if project is removed\n     */\n    function removeSelectedItem(e) {\n        var recentProjects = getRecentProjects(),\n            $cacheItem = $dropdownItem,\n            index = recentProjects.indexOf($cacheItem.data(\"path\"));\n\n        // When focus is not on project item\n        if (index === -1) {\n            return false;\n        }\n\n        // remove project\n        recentProjects.splice(index, 1);\n        PreferencesManager.setViewState(\"recentProjects\", recentProjects);\n        checkHovers(e.pageX, e.pageY);\n\n        if (recentProjects.length === 1) {\n            $dropdown.find(\".divider\").remove();\n        }\n        selectNextItem(+1);\n        $cacheItem.closest(\"li\").remove();\n        return true;\n    }\n\n    /**\n     * Handles the Key Down events\n     * @param {KeyboardEvent} event\n     * @return {boolean} True if the key was handled\n     */\n    function keydownHook(event) {\n        var keyHandled = false;\n\n        switch (event.keyCode) {\n        case KeyEvent.DOM_VK_UP:\n            selectNextItem(-1);\n            keyHandled = true;\n            break;\n        case KeyEvent.DOM_VK_DOWN:\n            selectNextItem(+1);\n            keyHandled = true;\n            break;\n        case KeyEvent.DOM_VK_ENTER:\n        case KeyEvent.DOM_VK_RETURN:\n            if ($dropdownItem) {\n                $dropdownItem.trigger(\"click\");\n            }\n            keyHandled = true;\n            break;\n        case KeyEvent.DOM_VK_BACK_SPACE:\n        case KeyEvent.DOM_VK_DELETE:\n            if ($dropdownItem) {\n                removeSelectedItem(event);\n                keyHandled = true;\n            }\n            break;\n        }\n\n        if (keyHandled) {\n            event.stopImmediatePropagation();\n            event.preventDefault();\n        }\n        return keyHandled;\n    }\n\n\n    /**\n     * Close the dropdown.\n     */\n    function closeDropdown() {\n        // Since we passed \"true\" for autoRemove to addPopUp(), this will\n        // automatically remove the dropdown from the DOM. Also, PopUpManager\n        // will call cleanupDropdown().\n        if ($dropdown) {\n            PopUpManager.removePopUp($dropdown);\n        }\n    }\n\n    /**\n     * Remove the various event handlers that close the dropdown. This is called by the\n     * PopUpManager when the dropdown is closed.\n     */\n    function cleanupDropdown() {\n        $(\"html\").off(\"click\", closeDropdown);\n        $(\"#project-files-container\").off(\"scroll\", closeDropdown);\n        $(\"#titlebar .nav\").off(\"click\", closeDropdown);\n        $dropdown = null;\n\n        MainViewManager.focusActivePane();\n\n        $(window).off(\"keydown\", keydownHook);\n    }\n\n\n    /**\n     * Adds the click and mouse enter/leave events to the dropdown\n     */\n    function _handleListEvents() {\n        $dropdown\n            .on(\"click\", \"a\", function () {\n                var $link = $(this),\n                    id    = $link.attr(\"id\"),\n                    path  = $link.data(\"path\");\n\n                if (path) {\n                    ProjectManager.openProject(path)\n                        .fail(function () {\n                            // Remove the project from the list only if it does not exist on disk\n                            var recentProjects = getRecentProjects(),\n                                index = recentProjects.indexOf(path);\n                            if (index !== -1) {\n                                FileSystem.resolve(path, function (err, item) {\n                                    if (err) {\n                                        recentProjects.splice(index, 1);\n                                    }\n                                });\n                            }\n                        });\n                    closeDropdown();\n\n                } else if (id === \"open-folder-link\") {\n                    CommandManager.execute(Commands.FILE_OPEN_FOLDER);\n                }\n\n            })\n            .on(\"mouseenter\", \"a\", function () {\n                if ($dropdownItem) {\n                    $dropdownItem.removeClass(\"selected\");\n                }\n                $dropdownItem = $(this).addClass(\"selected\");\n\n                if ($dropdownItem.hasClass(\"recent-folder-link\")) {\n                    // Note: we can't depend on the event here because this can be triggered\n                    // manually from checkHovers().\n                    addDeleteButton($(this));\n                }\n            })\n            .on(\"mouseleave\", \"a\", function () {\n                var $link = $(this).removeClass(\"selected\");\n\n                if ($link.get(0) === $dropdownItem.get(0)) {\n                    $dropdownItem = null;\n                }\n                if ($link.hasClass(\"recent-folder-link\")) {\n                    removeDeleteButton();\n                }\n            });\n    }\n\n    /**\n     * Parses the path and returns an object with the full path, the folder name and the path without the folder.\n     * @param {string} path The full path to the folder.\n     * @return {{path: string, folder: string, rest: string}}\n     */\n    function parsePath(path) {\n        var lastSlash = path.lastIndexOf(\"/\"), folder, rest;\n        if (lastSlash === path.length - 1) {\n            lastSlash = path.slice(0, path.length - 1).lastIndexOf(\"/\");\n        }\n        if (lastSlash >= 0) {\n            rest = \" - \" + (lastSlash ? path.slice(0, lastSlash) : \"/\");\n            folder = path.slice(lastSlash + 1);\n        } else {\n            rest = \"/\";\n            folder = path;\n        }\n\n        return {path: path, folder: folder, rest: rest};\n    }\n\n    /**\n     * Create the list of projects in the dropdown menu.\n     * @return {string} The html content\n     */\n    function renderList() {\n        var recentProjects = getRecentProjects(),\n            currentProject = FileUtils.stripTrailingSlash(ProjectManager.getProjectRoot().fullPath),\n            templateVars   = {\n                projectList : [],\n                Strings     : Strings\n            };\n\n        recentProjects.forEach(function (root) {\n            if (root !== currentProject) {\n                templateVars.projectList.push(parsePath(root));\n            }\n        });\n\n        return Mustache.render(ProjectsMenuTemplate, templateVars);\n    }\n\n    /**\n     * Show or hide the recent projects dropdown.\n     *\n     * @param {{pageX:number, pageY:number}} position - the absolute position where to open the dropdown\n     */\n    function showDropdown(position) {\n        // If the dropdown is already visible, just return (so the root click handler on html\n        // will close it).\n        if ($dropdown) {\n            return;\n        }\n\n        Menus.closeAll();\n\n        $dropdown = $(renderList())\n            .css({\n                left: position.pageX,\n                top: position.pageY\n            })\n            .appendTo($(\"body\"));\n\n        PopUpManager.addPopUp($dropdown, cleanupDropdown, true);\n\n        // TODO: should use capture, otherwise clicking on the menus doesn't close it. More fallout\n        // from the fact that we can't use the Boostrap (1.4) dropdowns.\n        $(\"html\").on(\"click\", closeDropdown);\n\n        // Hide the menu if the user scrolls in the project tree. Otherwise the Lion scrollbar\n        // overlaps it.\n        // TODO: This duplicates logic that's already in ProjectManager (which calls Menus.close()).\n        // We should fix this when the popup handling is centralized in PopupManager, as well\n        // as making Esc close the dropdown. See issue #1381.\n        $(\"#project-files-container\").on(\"scroll\", closeDropdown);\n\n        // Note: PopUpManager will automatically hide the sidebar in other cases, such as when a\n        // command is run, Esc is pressed, or the menu is focused.\n\n        // Hacky: if we detect a click in the menubar, close ourselves.\n        // TODO: again, we should have centralized popup management.\n        $(\"#titlebar .nav\").on(\"click\", closeDropdown);\n\n        _handleListEvents();\n        $(window).on(\"keydown\", keydownHook);\n    }\n\n\n    /**\n     * Show or hide the recent projects dropdown from the toogle command.\n     */\n    function handleKeyEvent() {\n        if (!$dropdown) {\n            if (!SidebarView.isVisible()) {\n                SidebarView.show();\n            }\n\n            $(\"#project-dropdown-toggle\").trigger(\"click\");\n\n            $dropdown.focus();\n            $links = $dropdown.find(\"a\");\n            // By default, select the most recent project (which is at the top of the list underneath Open Folder),\n            // but if there are none, select Open Folder instead.\n            $dropdownItem = $links.eq($links.length > 1 ? 1 : 0);\n            $dropdownItem.addClass(\"selected\");\n\n            // If focusing the dropdown caused a modal bar to close, we need to refocus the dropdown\n            window.setTimeout(function () {\n                $dropdown.focus();\n            }, 0);\n        }\n    }\n\n    // Register command handlers\n    CommandManager.register(Strings.CMD_TOGGLE_RECENT_PROJECTS, TOGGLE_DROPDOWN, handleKeyEvent);\n    KeyBindingManager.addBinding(TOGGLE_DROPDOWN, KeyboardPrefs.recentProjects);\n\n    // Initialize extension\n    AppInit.appReady(function () {\n        ExtensionUtils.loadStyleSheet(module, \"styles/styles.less\");\n\n        ProjectManager.on(\"projectOpen\", add);\n        ProjectManager.on(\"beforeProjectClose\", add);\n    });\n\n    AppInit.htmlReady(function () {\n        $(\"#project-title\")\n            .wrap(\"<div id='project-dropdown-toggle' class='btn-alt-quiet'></div>\")\n            .after(\"<span class='dropdown-arrow'></span>\");\n\n        var cmenuAdapter = {\n            open: showDropdown,\n            close: closeDropdown,\n            isOpen: function () {\n                return !!$dropdown;\n            }\n        };\n        Menus.ContextMenu.assignContextMenuToSelector(\"#project-dropdown-toggle\", cmenuAdapter);\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/RecentProjects/styles/styles.less",
    "content": "@bc-bg-highlight:               #e0f0fa;\n@bc-menu-text:                  #000;\n@bc-text-quiet:                 #aaa;\n@bc-text-thin:                  #000;\n@bc-text-thin-quiet:            #777;\n\n@dark-bc-bg-highlight:          #2a3b50;\n@dark-bc-menu-text:             #fff;\n@dark-bc-text-quiet:            #aaa;\n@dark-bc-text-thin:             #fff;\n@dark-bc-text-thin-quiet:       #bbb;\n\n.dropdown-arrow {\n    display: inline-block;\n    width: 7px;\n    height: 5px;\n    margin-left: 4px;\n    background-image: url(\"down-arrow.svg\");\n    background-repeat: no-repeat;\n    position: relative;\n    top: 0;\n}\n\n.trash-icon {\n    position: absolute;\n    left: 7px;\n    width: 16px;\n    height: 16px;\n    font-size: 20px;\n    color: @bc-text-thin-quiet;\n    line-height: 15px;\n    text-align: center;\n\n    .dark & {\n        color: @dark-bc-text-thin-quiet;\n    }\n}\n\n.trash-icon:hover {\n    color: @bc-text-thin;\n\n    .dark & {\n        color: @dark-bc-text-thin;\n    }\n}\n\n#project-dropdown-toggle {\n    display: inline-block;\n    /* adjust margins to keep position #project-title position stable after extension is loaded */\n    margin: -3px 5px -2px -6px;\n    overflow: hidden;\n    padding: 0 5px;\n    white-space: nowrap;\n}\n\n#project-title {\n    /* vertical align center text */\n    height: 21px;\n    line-height: 21px;\n}\n\n#project-dropdown-toggle:hover .dropdown-arrow {\n    background-image: url(\"down-arrow.svg\");\n}\n\n#project-dropdown.dropdown-menu:focus {\n    outline: none;\n}\n\n/* TODO: style the dropdown content */\n#project-dropdown.dropdown-menu {\n    position: absolute;\n\n    /* offset for better alignment with the button */\n    margin-top: -1px;\n    margin-left: 1px;\n\n    display: block;\n    max-width: none;\n    z-index: 100;\n}\n\n#project-dropdown.dropdown-menu .divider {\n    margin: 5px 1px;\n}\n\n.recent-folder-link, .recent-folder, .recent-folder-path {\n    white-space: nowrap;\n}\n\n#project-dropdown.dropdown-menu li a {\n    padding: 5px 15px;\n}\n\n#project-dropdown.dropdown-menu .recent-folder-link, #project-dropdown.dropdown-menu #open-folder-link {\n\tdisplay: block;\n\tpadding: 5px 26px 5px 26px;\n}\n\n.recent-folder, #open-folder-link {\n    color: @bc-menu-text;\n\n    .dark & {\n        color: @dark-bc-menu-text;\n    }\n}\n\n.recent-folder-path {\n    color: @bc-text-thin-quiet;\n\n    .dark & {\n        color: @dark-bc-text-thin-quiet;\n    }\n}\n\n#project-dropdown.dropdown-menu a.selected {\n     background: @bc-bg-highlight;\n\n    .dark & {\n        background: @dark-bc-bg-highlight;\n    }\n}\n#project-dropdown.dropdown-menu a:not(.selected):hover {\n     background: none;\n}\n"
  },
  {
    "path": "src/extensions/default/RecentProjects/unittests.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeFirst, afterLast, runs, waitsFor, spyOn */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        FileUtils       = brackets.getModule(\"file/FileUtils\"),\n        KeyEvent        = brackets.getModule(\"utils/KeyEvent\"),\n        _               = brackets.getModule(\"thirdparty/lodash\");\n\n    describe(\"Recent Projects\", function () {\n        var extensionPath = FileUtils.getNativeModuleDirectoryPath(module),\n            testWindow,\n            $,\n            CommandManager,\n            PreferencesManager;\n\n        beforeFirst(function () {\n            runs(function () {\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow = w;\n                    $ = testWindow.$;\n                    CommandManager  = testWindow.brackets.test.CommandManager;\n                    PreferencesManager = testWindow.brackets.test.PreferencesManager;\n                });\n            });\n        });\n\n        afterLast(function () {\n            testWindow = null;\n            SpecRunnerUtils.closeTestWindow();\n        });\n\n        function openRecentProjectDropDown() {\n            CommandManager.execute(\"recentProjects.toggle\");\n            waitsFor(function () {\n                return $(\"#project-dropdown\").is(\":visible\");\n            });\n        }\n\n        function setupRecentProjectsSpy(howManyProjects) {\n            spyOn(PreferencesManager, \"getViewState\").andCallFake(function (prefId) {\n                if (prefId === \"recentProjects\") {\n                    // return howManyProjects number of fake recent projects entries\n                    return _.map(_.range(1, howManyProjects + 1), function (num) { return extensionPath + \"/Test-Project-\" + num; });\n                } else {\n                    return [];\n                }\n            });\n        }\n\n        describe(\"UI\", function () {\n            it(\"should open the recent projects list with only the getting started project\", function () {\n                runs(function () {\n                    openRecentProjectDropDown();\n                });\n\n                runs(function () {\n                    var $dropDown = $(\"#project-dropdown\");\n                    expect($dropDown.children().length).toEqual(1);\n                });\n            });\n\n            it(\"should open the recent project list and show 5 recent projects\", function () {\n                setupRecentProjectsSpy(5);\n\n                runs(function () {\n                    openRecentProjectDropDown();\n                });\n\n                runs(function () {\n                    var $dropDown = $(\"#project-dropdown\");\n                    expect($dropDown.find(\".recent-folder-link\").length).toEqual(5);\n                });\n            });\n\n            it(\"should delete one project from recent project list when delete key is pressed on\", function () {\n                setupRecentProjectsSpy(5);\n\n                runs(function () {\n                    openRecentProjectDropDown();\n                });\n\n                runs(function () {\n                    var $dropDown = $(\"#project-dropdown\");\n                    SpecRunnerUtils.simulateKeyEvent(KeyEvent.DOM_VK_DOWN, \"keydown\", $dropDown[0]);\n                    SpecRunnerUtils.simulateKeyEvent(KeyEvent.DOM_VK_DELETE, \"keydown\", $dropDown[0]);\n                });\n\n                runs(function () {\n                    var $dropDown = $(\"#project-dropdown\");\n                    expect($dropDown.find(\".recent-folder-link\").length).toEqual(4);\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/RemoteFileAdapter/RemoteFile.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileSystemError = brackets.getModule(\"filesystem/FileSystemError\"),\n        FileSystemStats = brackets.getModule(\"filesystem/FileSystemStats\");\n\n    var SESSION_START_TIME = new Date();\n\n    /**\n     * Create a new file stat. See the FileSystemStats class for more details.\n     *\n     * @param {!string} fullPath The full path for this File.\n     * @return {FileSystemStats} stats.\n     */\n    function _getStats(uri) {\n        return new FileSystemStats({\n            isFile: true,\n            mtime: SESSION_START_TIME.toISOString(),\n            size: 0,\n            realPath: uri,\n            hash: uri\n        });\n    }\n    \n    function _getFileName(filePath) {\n        var fileName = filePath.split('/').pop();\n        \n        if (!fileName.trim()) {\n            fileName = filePath.trim().slice(0, -1);\n            fileName = fileName.split('/').pop();\n        }\n        \n        return fileName;\n    }\n\n    /**\n     * Model for a RemoteFile.\n     *\n     * This class should *not* be instantiated directly. Use FileSystem.getFileForPath\n     *\n     * See the FileSystem class for more details.\n     *\n     * @constructor\n     * @param {!string} fullPath The full path for this File.\n     * @param {!FileSystem} fileSystem The file system associated with this File.\n     */\n    function RemoteFile(protocol, fullPath, fileSystem) {\n        this._isFile = true;\n        this._isDirectory = false;\n        this.readOnly = true;\n        this._path = fullPath;\n        this._stat = _getStats(fullPath);\n        this._id = fullPath;\n        this._name = _getFileName(fullPath);\n        this._fileSystem = fileSystem;\n        this.donotWatch = true;\n        this.protocol = protocol;\n        this.encodedPath = fullPath;\n    }\n\n    // Add \"fullPath\", \"name\", \"parent\", \"id\", \"isFile\" and \"isDirectory\" getters\n    Object.defineProperties(RemoteFile.prototype, {\n        \"fullPath\": {\n            get: function () { return this._path; },\n            set: function () { throw new Error(\"Cannot set fullPath\"); }\n        },\n        \"name\": {\n            get: function () { return this._name; },\n            set: function () { throw new Error(\"Cannot set name\"); }\n        },\n        \"parentPath\": {\n            get: function () { return this._parentPath; },\n            set: function () { throw new Error(\"Cannot set parentPath\"); }\n        },\n        \"id\": {\n            get: function () { return this._id; },\n            set: function () { throw new Error(\"Cannot set id\"); }\n        },\n        \"isFile\": {\n            get: function () { return this._isFile; },\n            set: function () { throw new Error(\"Cannot set isFile\"); }\n        },\n        \"isDirectory\": {\n            get: function () { return this._isDirectory; },\n            set: function () { throw new Error(\"Cannot set isDirectory\"); }\n        },\n        \"_impl\": {\n            get: function () { return this._fileSystem._impl; },\n            set: function () { throw new Error(\"Cannot set _impl\"); }\n        }\n    });\n\n    /**\n     * Helpful toString for debugging and equality check purposes\n     */\n    RemoteFile.prototype.toString = function () {\n        return \"[RemoteFile \" + this._path + \"]\";\n    };\n\n    /**\n     * Returns the stats for the remote entry.\n     *\n     * @param {function (?string, FileSystemStats=)} callback Callback with a\n     *      FileSystemError string or FileSystemStats object.\n     */\n    RemoteFile.prototype.stat = function (callback) {\n        if (this._stat) {\n            callback(null, this._stat);\n        } else {\n            callback(FileSystemError.NOT_FOUND);\n        }\n    };\n\n    RemoteFile.prototype.constructor = RemoteFile;\n\n    /**\n     * Cached contents of this file. This value is nullable but should NOT be undefined.\n     * @private\n     * @type {?string}\n     */\n    RemoteFile.prototype._contents = null;\n\n\n    /**\n     * @private\n     * @type {?string}\n     */\n    RemoteFile.prototype._encoding = \"utf8\";\n\n    /**\n     * @private\n     * @type {?bool}\n     */\n    RemoteFile.prototype._preserveBOM = false;\n\n\n    /**\n     * Clear any cached data for this file. Note that this explicitly does NOT\n     * clear the file's hash.\n     * @private\n     */\n    RemoteFile.prototype._clearCachedData = function () {\n        // no-op\n    };\n\n    /**\n     * Reads a remote file.\n     *\n     * @param {Object=} options Currently unused.\n     * @param {function (?string, string=, FileSystemStats=)} callback Callback that is passed the\n     *              FileSystemError string or the file's contents and its stats.\n     */\n    RemoteFile.prototype.read = function (options, callback) {\n        if (typeof (options) === \"function\") {\n            callback = options;\n        }\n        this._encoding = \"utf8\";\n\n        if (this._contents !== null && this._stat) {\n            callback(null, this._contents, this._encoding, this._stat);\n            return;\n        }\n\n        var self = this;\n        $.ajax({\n            url: this.fullPath\n        })\n        .done(function (data) {\n            self._contents = data;\n            callback(null, data, self._encoding, self._stat);\n        })\n        .fail(function (e) {\n            callback(FileSystemError.NOT_FOUND);\n        });\n    };\n\n    /**\n     * Write a file.\n     *\n     * @param {string} data Data to write.\n     * @param {object=} options Currently unused.\n     * @param {function (?string, FileSystemStats=)=} callback Callback that is passed the\n     *              FileSystemError string or the file's new stats.\n     */\n    RemoteFile.prototype.write = function (data, encoding, callback) {\n        if (typeof (encoding) === \"function\") {\n            callback = encoding;\n        }\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    RemoteFile.prototype.exists = function (callback) {\n        callback(null, true);\n    };\n\n    RemoteFile.prototype.unlink = function (callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    RemoteFile.prototype.rename = function (newName, callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    RemoteFile.prototype.moveToTrash = function (callback) {\n        callback(FileSystemError.NOT_FOUND);\n    };\n\n    // Export this class\n    module.exports = RemoteFile;\n});\n"
  },
  {
    "path": "src/extensions/default/RemoteFileAdapter/main.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit         = brackets.getModule(\"utils/AppInit\"),\n        FileSystem      = brackets.getModule(\"filesystem/FileSystem\"),\n        QuickOpen       = brackets.getModule(\"search/QuickOpen\"),\n        PathUtils       = brackets.getModule(\"thirdparty/path-utils/path-utils\"),\n        CommandManager  = brackets.getModule(\"command/CommandManager\"),\n        Commands        = brackets.getModule(\"command/Commands\"),\n        ExtensionUtils = brackets.getModule(\"utils/ExtensionUtils\"),\n        WorkingSetView = brackets.getModule(\"project/WorkingSetView\"),\n        MainViewManager = brackets.getModule(\"view/MainViewManager\"),\n        Menus           = brackets.getModule(\"command/Menus\"),\n        RemoteFile      = require(\"RemoteFile\");\n\n    var HTTP_PROTOCOL = \"http:\",\n        HTTPS_PROTOCOL = \"https:\";\n    \n    ExtensionUtils.loadStyleSheet(module, \"styles.css\");\n    \n    function protocolClassProvider(data) {\n        if (data.fullPath.startsWith(\"http://\")) {\n            return \"http\";\n        }\n\n        if (data.fullPath.startsWith(\"https://\")) {\n            return \"https\";\n        }\n        \n        return \"\";\n    }\n    \n    /**\n     * Disable context menus which are not useful for remote file\n     */\n    function _setMenuItemsVisible() {\n        var file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE),\n            cMenuItems = [Commands.FILE_SAVE, Commands.FILE_RENAME, Commands.NAVIGATE_SHOW_IN_FILE_TREE, Commands.NAVIGATE_SHOW_IN_OS],\n            // Enable menu options when no file is present in active pane\n            enable = !file || (file.constructor.name !== \"RemoteFile\");\n        \n            // Enable or disable commands based on whether the file is a remoteFile or not.\n            cMenuItems.forEach(function (item) {\n                CommandManager.get(item).setEnabled(enable);\n            });\n    }\n\n    AppInit.htmlReady(function () {\n        \n        Menus.getContextMenu(Menus.ContextMenuIds.WORKING_SET_CONTEXT_MENU).on(\"beforeContextMenuOpen\", _setMenuItemsVisible);\n        MainViewManager.on(\"currentFileChange\", _setMenuItemsVisible);\n        \n        var protocolAdapter = {\n            priority: 0, // Default priority\n            fileImpl: RemoteFile,\n            canRead: function (filePath) {\n                return true; // Always claim true, we are the default adpaters\n            }\n        };\n\n        // Register the custom object as HTTP and HTTPS protocol adapter\n        FileSystem.registerProtocolAdapter(HTTP_PROTOCOL, protocolAdapter);\n        FileSystem.registerProtocolAdapter(HTTPS_PROTOCOL, protocolAdapter);\n\n        // Register as quick open plugin for file URI's having HTTP:|HTTPS: protocol\n        QuickOpen.addQuickOpenPlugin(\n            {\n                name: \"Remote file URI input\",\n                languageIds: [], // for all language modes\n                search: function () {\n                    return $.Deferred().resolve([arguments[0]]);\n                },\n                match: function (query) {\n                    var protocol = PathUtils.parseUrl(query).protocol;\n                    return [HTTP_PROTOCOL, HTTPS_PROTOCOL].indexOf(protocol) !== -1;\n                },\n                itemFocus: function (query) {\n                }, // no op\n                itemSelect: function () {\n                    CommandManager.execute(Commands.FILE_OPEN, {fullPath: arguments[0]});\n                }\n            }\n        );\n        \n        WorkingSetView.addClassProvider(protocolClassProvider);\n    });\n\n});\n"
  },
  {
    "path": "src/extensions/default/RemoteFileAdapter/styles.css",
    "content": ".http a:after,\n.https a:after {\n    margin-left: 5px;\n    border: 1px solid;\n    border-radius: 2px;\n    padding: 0px 5px;\n    font-size: 11px;\n    color: #adb9bd;\n}\n\n.http a:after {\n    content: \"http\";\n}\n\n.https a:after {\n    content: \"https\";\n}\n\n\n\n\n"
  },
  {
    "path": "src/extensions/default/RemoteFileAdapter/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, runs, waitsForDone, spyOn */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        FileUtils\t\t= brackets.getModule(\"file/FileUtils\"),\n        CommandManager,\n        Commands,\n        Dialogs,\n        EditorManager,\n        DocumentManager,\n        MainViewManager,\n        FileSystem;\n\n    var REMOTE_FILE_PATH = \"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css\",\n        INVALID_REMOTE_FILE_PATH = \"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/invalid.min.css\";\n\n\n\n    describe(\"RemoteFileAdapter\", function () {\n        var testWindow,\n            $,\n            brackets;\n\n        function createRemoteFile(filePath) {\n            return CommandManager.execute(Commands.FILE_OPEN, {fullPath: filePath});\n        }\n\n        function deleteCurrentRemoteFile() {\n            CommandManager.execute(Commands.FILE_DELETE);\n        }\n\n        function saveRemoteFile() {\n            CommandManager.execute(Commands.FILE_SAVE);\n        }\n\n        function renameRemoteFile(filePath) {\n            CommandManager.execute(Commands.FILE_RENAME);\n        }\n\n        function closeRemoteFile(filePath) {\n            CommandManager.execute(Commands.FILE_CLOSE, {fullPath: filePath});\n        }\n\n        beforeEach(function () {\n            runs(function () {\n                SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                    testWindow = w;\n                    $ = testWindow.$;\n                    brackets\t\t= testWindow.brackets;\n                    DocumentManager = testWindow.brackets.test.DocumentManager;\n                    MainViewManager = testWindow.brackets.test.MainViewManager;\n                    CommandManager  = testWindow.brackets.test.CommandManager;\n                    EditorManager   = testWindow.brackets.test.EditorManager;\n                    Dialogs\t\t\t= testWindow.brackets.test.Dialogs;\n                    Commands        = testWindow.brackets.test.Commands;\n                    FileSystem      = testWindow.brackets.test.FileSystem;\n                });\n            });\n        });\n\n        afterEach(function () {\n            testWindow    = null;\n            $             = null;\n            brackets      = null;\n            EditorManager = null;\n            SpecRunnerUtils.closeTestWindow();\n        });\n\n\n        it(\"Open/close remote https file\", function () {\n            createRemoteFile(REMOTE_FILE_PATH).done(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(1);\n                closeRemoteFile(REMOTE_FILE_PATH).done(function () {\n                    expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(0);\n                });\n            });\n        });\n\n        it(\"Open invalid remote file\", function () {\n            spyOn(Dialogs, 'showModalDialog').andCallFake(function (dlgClass, title, message, buttons) {\n                console.warn(title, message);\n                return {done: function (callback) { callback(Dialogs.DIALOG_BTN_OK); } };\n            });\n            createRemoteFile(INVALID_REMOTE_FILE_PATH).always(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(0);\n                expect(Dialogs.showModalDialog).toHaveBeenCalled();\n                expect(Dialogs.showModalDialog.callCount).toBe(1);\n            });\n        });\n\n        it(\"Save remote file\", function () {\n            createRemoteFile(REMOTE_FILE_PATH).done(function () {\n                spyOn(Dialogs, 'showModalDialog').andCallFake(function (dlgClass, title, message, buttons) {\n                    console.warn(title, message);\n                    return {done: function (callback) { callback(Dialogs.DIALOG_BTN_OK); } };\n                });\n                saveRemoteFile();\n                expect(Dialogs.showModalDialog).toHaveBeenCalled();\n                expect(Dialogs.showModalDialog.callCount).toBe(1);\n                closeRemoteFile(REMOTE_FILE_PATH).done(function () {\n                    expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(0);\n                });\n            });\n        });\n\n        it(\"Delete remote file\", function () {\n            createRemoteFile(REMOTE_FILE_PATH).done(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(1);\n                spyOn(Dialogs, 'showModalDialog').andCallFake(function (dlgClass, title, message, buttons) {\n                    console.warn(title, message);\n                    return {done: function (callback) { callback(Dialogs.DIALOG_BTN_OK); } };\n                });\n                deleteCurrentRemoteFile();\n                expect(Dialogs.showModalDialog).toHaveBeenCalled();\n                expect(Dialogs.showModalDialog.callCount).toBe(1);\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(1);\n                closeRemoteFile(REMOTE_FILE_PATH).done(function () {\n                    expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(0);\n                });\n            });\n        });\n\n        it(\"Rename remote file\", function () {\n            createRemoteFile(REMOTE_FILE_PATH).done(function () {\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(1);\n                spyOn(Dialogs, 'showModalDialog').andCallFake(function (dlgClass, title, message, buttons) {\n                    console.warn(title, message);\n                    return {done: function (callback) { callback(Dialogs.DIALOG_BTN_OK); } };\n                });\n                renameRemoteFile();\n                expect(Dialogs.showModalDialog).toHaveBeenCalled();\n                expect(Dialogs.showModalDialog.callCount).toBe(1);\n                expect(MainViewManager.getWorkingSet(MainViewManager.ACTIVE_PANE).length).toEqual(1);\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/SVGCodeHints/SVGAttributes.json",
    "content": "{\n    \"accumulate\": {\n        \"attribOptions\": [\"none\", \"sum\"]\n    },\n    \"additive\": {\n        \"attribOptions\": [\"replace\", \"sum\"]\n    },\n    \"alignment-baseline\": {\n        \"attribOptions\": [\"after-edge\", \"alphabetic\", \"auto\", \"baseline\", \"before-edge\", \"central\", \"hanging\", \"ideographic\", \"inherit\", \"mathematical\", \"middle\", \"text-after-edge\", \"text-before-edge\"]\n    },\n    \"animate/fill\": {\n        \"attribOptions\": [\"freeze\", \"remove\"]\n    },\n    \"animateColor/fill\": {\n        \"attribOptions\": [\"freeze\", \"remove\"]\n    },\n    \"animateMotion/fill\": {\n        \"attribOptions\": [\"freeze\", \"remove\"]\n    },\n    \"animateMotion/rotate\": {\n        \"attribOptions\": [\"auto\", \"auto-reverse\"]\n    },\n    \"animateTransform/fill\": {\n        \"attribOptions\": [\"freeze\", \"remove\"]\n    },\n    \"animateTransform/type\": {\n        \"attribOptions\": [\"rotate\", \"scale\", \"skewX\", \"skewY\", \"translate\"]\n    },\n    \"arabic-form\": {\n        \"attribOptions\": [\"initial\", \"isolated\", \"medial\", \"terminal\"]\n    },\n    \"attributeType\": {\n        \"attribOptions\": [\"auto\", \"CSS\", \"XML\"]\n    },\n    \"baseline-shift\": {\n        \"attribOptions\": [\"baseline\", \"inherit\", \"sub\", \"super\"]\n    },\n    \"calcMode\": {\n        \"attribOptions\": [\"discrete\", \"linear\", \"paced\", \"spline\"]\n    },\n    \"clip\": {\n        \"attribOptions\": [\"auto\", \"inherit\"]\n    },\n    \"clip-path\": {\n        \"attribOptions\": [\"auto\", \"inherit\"]\n    },\n    \"clip-rule\": {\n        \"attribOptions\": [\"evenodd\", \"inherit\", \"nonzero\"]\n    },\n    \"clipPathUnits\": {\n        \"attribOptions\": [\"objectBoundingBox\", \"userSpaceOnUse\"]\n    },\n    \"color\": {\n        \"type\": \"color\"\n    },\n    \"color-interpolation\": {\n        \"attribOptions\": [\"auto\", \"inherit\", \"linearRGB\", \"sRGB\"]\n    },\n    \"color-interpolation-filters\": {\n        \"attribOptions\": [\"auto\", \"inherit\", \"linearRGB\", \"sRGB\"]\n    },\n    \"color-profile\": {\n        \"attribOptions\": [\"auto\", \"inherit\", \"sRGB\"]\n    },\n    \"color-rendering\": {\n        \"attribOptions\": [\"auto\", \"inherit\", \"optimizeQuality\", \"optimizeSpeed\"]\n    },\n    \"contentScriptType\": {\n        \"attribOptions\": [\"application/ecmascript\", \"application/javascript\", \"application/x-ecmascript\", \"application/x-javascript\", \"text/ecmascript\", \"text/javascript\", \"text/jscript\", \"text/livescript\", \"text/tcl\", \"text/x-ecmascript\", \"text/x-javascript\", \"text/babel\", \"text/jsx\"]\n    },\n    \"contentStyleType\": {\n        \"attribOptions\": [\"text/css\"]\n    },\n    \"cursor\": {\n        \"attribOptions\": [\"auto\", \"crosshair\", \"default\", \"e-resize\", \"help\", \"inherit\", \"move\", \"n-resize\", \"ne-resize\", \"nw-resize\", \"pointer\", \"s-resize\", \"se-resize\", \"sw-resize\", \"text\", \"w-resize\", \"wait\"]\n    },\n    \"direction\": {\n        \"attribOptions\": [\"inherit\", \"ltr\", \"rtl\"]\n    },\n    \"display\": {\n        \"attribOptions\": [\"block\", \"compact\", \"inherit\", \"inline\", \"inline-table\", \"list-item\", \"marker\", \"none\", \"run-in\", \"table\", \"table-caption\", \"table-cell\", \"table-column\", \"table-column-group\", \"table-footer-group\", \"table-header-group\", \"table-row\", \"table-row-group\"]\n    },\n    \"dominant-baseline\": {\n        \"attribOptions\": [\"alphabetic\", \"auto\", \"central\", \"hanging\", \"ideographic\", \"inherit\", \"mathematical\", \"middle\", \"no-change\", \"reset-size\", \"text-after-edge\", \"text-before-edge\", \"use-script\"]\n    },\n    \"dur\": {\n        \"attribOptions\": [\"indefinite\", \"media\"]\n    },\n    \"edgeMode\": {\n        \"attribOptions\": [\"duplicate\", \"none\", \"wrap\"]\n    },\n    \"enable-background\": {\n        \"attribOptions\": [\"accumulate\", \"inherit\", \"new\"]\n    },\n    \"externalResourcesRequired\": {\n        \"attribOptions\": [\"false\", \"true\"]\n    },\n    \"feColorMatrix/type\": {\n        \"attribOptions\": [\"hueRotate\", \"luminanceToAlpha\", \"matrix\", \"saturate\"]\n    },\n    \"feComposite/operator\": {\n        \"attribOptions\": [\"arithmetic\", \"atop\", \"in\", \"out\", \"over\", \"xor\"]\n    },\n    \"feFuncA/type\": {\n        \"attribOptions\": [\"discrete\", \"gamma\", \"identity\", \"linear\", \"table\"]\n    },\n    \"feFuncB/type\": {\n        \"attribOptions\": [\"discrete\", \"gamma\", \"identity\", \"linear\", \"table\"]\n    },\n    \"feFuncG/type\": {\n        \"attribOptions\": [\"discrete\", \"gamma\", \"identity\", \"linear\", \"table\"]\n    },\n    \"feFuncR/type\": {\n        \"attribOptions\": [\"discrete\", \"gamma\", \"identity\", \"linear\", \"table\"]\n    },\n    \"feMorphology/operator\": {\n        \"attribOptions\": [\"dilate\", \"erode\"]\n    },\n    \"feTurbulence/type\": {\n        \"attribOptions\": [\"fractalNoise\", \"turbulence\"]\n    },\n    \"fill\": {\n        \"type\": \"color\"\n    },\n    \"fill-opacity\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"fill-rule\": {\n        \"attribOptions\": [\"evenodd\", \"inherit\", \"nonzero\"]\n    },\n    \"filter\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"filterUnits\": {\n        \"attribOptions\": [\"objectBoundingBox\", \"userSpaceOnUse\"]\n    },\n    \"flood-color\": {\n        \"type\": \"color\"\n    },\n    \"flood-opacity\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"font-family\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"font-size\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"font-size-adjust\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"font-stretch\": {\n        \"attribOptions\": [\"all\", \"condensed\", \"expanded\", \"extra-condensed\", \"extra-expanded\", \"inherit\", \"narrower\", \"normal\", \"semi-condensed\", \"semi-expanded\", \"ultra-condensed\", \"ultra-expanded\", \"wider\"]\n    },\n    \"font-style\": {\n        \"attribOptions\": [\"all\", \"inherit\", \"italic\", \"normal\", \"oblique\"]\n    },\n    \"font-variant\": {\n        \"attribOptions\": [\"inherit\", \"normal\", \"small-caps\"]\n    },\n    \"font-weight\": {\n        \"attribOptions\": [\"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\", \"all\", \"bold\", \"bolder\", \"inherit\", \"lighter\", \"normal\"]\n    },\n    \"glyph-orientation-horizontal\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"glyph-orientation-vertical\": {\n        \"attribOptions\": [\"auto\", \"inherit\"]\n    },\n    \"gradientTransform\": {\n        \"attribOptions\": [\"matrix()\", \"rotate()\", \"scale()\", \"skewX()\", \"skewY()\", \"translate()\"],\n        \"multiple\": true\n    },\n    \"gradientUnits\": {\n        \"attribOptions\": [\"objectBoundingBox\", \"userSpaceOnUse\"]\n    },\n    \"image-rendering\": {\n        \"attribOptions\": [\"auto\", \"inherit\", \"optimizeQuality\", \"optimizeSpeed\"]\n    },\n    \"in\": {\n        \"attribOptions\": [\"BackgroundAlpha\", \"BackgroundImage\", \"FillPaint\", \"SourceAlpha\", \"SourceGraphic\", \"StrokePaint\"]\n    },\n    \"in2\": {\n        \"attribOptions\": [\"BackgroundAlpha\", \"BackgroundImage\", \"FillPaint\", \"SourceAlpha\", \"SourceGraphic\", \"StrokePaint\"]\n    },\n    \"kerning\": {\n        \"attribOptions\": [\"auto\", \"inherit\"]\n    },\n    \"lang\": {\n        \"attribOptions\": [\"aa\", \"ab\", \"af\", \"am\", \"ar\", \"as\", \"ay\", \"az\", \"ba\", \"be\", \"bg\", \"bh\", \"bi\", \"bn\", \"bo\", \"br\", \"ca\", \"co\", \"cs\", \"cy\", \"da\", \"de\", \"dz\", \"el\", \"en\", \"eo\", \"es\", \"et\", \"eu\", \"fa\", \"fi\", \"fj\", \"fo\", \"fr\", \"fy\", \"ga\", \"gd\", \"gl\", \"gn\", \"gu\", \"ha\", \"hi\", \"hr\", \"hu\", \"hy\", \"ia\", \"ie\", \"ik\", \"in\", \"is\", \"it\", \"iw\", \"ja\", \"ji\", \"jw\", \"ka\", \"kk\", \"kl\", \"km\", \"kn\", \"ko\", \"ks\", \"ku\", \"ky\", \"la\", \"ln\", \"lo\", \"lt\", \"lv\", \"mg\", \"mi\", \"mk\", \"ml\", \"mn\", \"mo\", \"mr\", \"ms\", \"mt\", \"my\", \"na\", \"ne\", \"nl\", \"no\", \"oc\", \"om\", \"or\", \"pa\", \"pl\", \"ps\", \"pt\", \"qu\", \"rm\", \"rn\", \"ro\", \"ru\", \"rw\", \"sa\", \"sd\", \"sg\", \"sh\", \"si\", \"sk\", \"sl\", \"sm\", \"sn\", \"so\", \"sq\", \"sr\", \"ss\", \"st\", \"su\", \"sv\", \"sw\", \"ta\", \"te\", \"tg\", \"th\", \"ti\", \"tk\", \"tl\", \"tn\", \"to\", \"tr\", \"ts\", \"tt\", \"tw\", \"uk\", \"ur\", \"uz\", \"vi\", \"vo\", \"wo\", \"xh\", \"yo\", \"zh\", \"zu\"]\n    },\n    \"lengthAdjust\": {\n        \"attribOptions\": [\"spacing\", \"spacingAndGlyphs\"]\n    },\n    \"letter-spacing\": {\n        \"attribOptions\": [\"inherit\", \"normal\"]\n    },\n    \"lighting-color\": {\n        \"type\": \"color\"\n    },\n    \"marker-end\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"marker-mid\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"marker-start\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"markerUnits\": {\n        \"attribOptions\": [\"strokeWidth\", \"userSpaceOnUse\"]\n    },\n    \"mask\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"maskContentUnits\": {\n        \"attribOptions\": [\"userSpaceOnUse\", \"objectBoundingBox\"]\n    },\n    \"maskUnits\": {\n        \"attribOptions\": [\"userSpaceOnUse\", \"objectBoundingBox\"]\n    },\n    \"max\": {\n        \"attribOptions\": [\"media\"]\n    },\n    \"method\": {\n        \"attribOptions\": [\"align\", \"stretch\"]\n    },\n    \"min\": {\n        \"attribOptions\": [\"media\"]\n    },\n    \"mode\": {\n        \"attribOptions\": [\"darken\", \"lighten\", \"multiply\", \"normal\", \"screen\"]\n    },\n    \"opacity\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"orient\": {\n        \"attribOptions\": [\"auto\"]\n    },\n    \"orientation\": {\n        \"attribOptions\": [\"h\", \"v\"]\n    },\n    \"origin\": {\n        \"attribOptions\": [\"default\"]\n    },\n    \"overflow\": {\n        \"attribOptions\": [\"auto\", \"hidden\", \"inherit\", \"scroll\", \"visible\"]\n    },\n    \"patternContentUnits\": {\n        \"attribOptions\": [\"objectBoundingBox\", \"userSpaceOnUse\"]\n    },\n    \"patternTransform\": {\n        \"attribOptions\": [\"matrix()\", \"rotate()\", \"scale()\", \"skewX()\", \"skewY()\", \"translate()\"],\n        \"multiple\": true\n    },\n    \"patternUnits\": {\n        \"attribOptions\": [\"objectBoundingBox\", \"userSpaceOnUse\"]\n    },\n    \"pointer-events\": {\n        \"attribOptions\": [\"all\", \"fill\", \"inherit\", \"none\", \"painted\", \"stroke\", \"visible\", \"visibleFill\", \"visiblePainted\", \"visibleStroke\"]\n    },\n    \"preserveAlpha\": {\n        \"attribOptions\": [\"false\", \"true\"]\n    },\n    \"preserveAspectRatio\": {\n        \"attribOptions\": [\"meet\", \"none\", \"slice\", \"xMaxYMax\", \"xMaxYMid\", \"xMaxYMin\", \"xMidYMax\", \"xMidYMid\", \"xMidYMin\", \"xMinYMax\", \"xMinYMid\", \"xMinYMin\"],\n        \"multiple\": true\n    },\n    \"primitiveUnits\": {\n        \"attribOptions\": [\"objectBoundingBox\", \"userSpaceOnUse\"]\n    },\n    \"rendering-intent\": {\n        \"attribOptions\": [\"absolute-colorimetric\", \"auto\", \"perceptual\", \"relative-colorimetric\", \"saturation\"]\n    },\n    \"repeatCount\": {\n        \"attribOptions\": [\"indefinite\"]\n    },\n    \"repeatDur\": {\n        \"attribOptions\": [\"indefinite\"]\n    },\n    \"requiredFeatures\": {\n        \"attribOptions\": [\"http://www.w3.org/TR/SVG11/feature#AnimationEventsAttribute\", \"http://www.w3.org/TR/SVG11/feature#BasicClip\", \"http://www.w3.org/TR/SVG11/feature#BasicFilter\", \"http://www.w3.org/TR/SVG11/feature#BasicFont\", \"http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute\", \"http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute\", \"http://www.w3.org/TR/SVG11/feature#BasicStructure\", \"http://www.w3.org/TR/SVG11/feature#BasicText\", \"http://www.w3.org/TR/SVG11/feature#Clip\", \"http://www.w3.org/TR/SVG11/feature#ColorProfile\", \"http://www.w3.org/TR/SVG11/feature#ConditionalProcessing\", \"http://www.w3.org/TR/SVG11/feature#ContainerAttribute\", \"http://www.w3.org/TR/SVG11/feature#CoreAttribute\", \"http://www.w3.org/TR/SVG11/feature#Cursor\", \"http://www.w3.org/TR/SVG11/feature#DocumentEventsAttribute\", \"http://www.w3.org/TR/SVG11/feature#Extensibility\", \"http://www.w3.org/TR/SVG11/feature#ExternalResourcesRequired\", \"http://www.w3.org/TR/SVG11/feature#Filter\", \"http://www.w3.org/TR/SVG11/feature#Font\", \"http://www.w3.org/TR/SVG11/feature#Gradient\", \"http://www.w3.org/TR/SVG11/feature#GraphicalEventsAttribute\", \"http://www.w3.org/TR/SVG11/feature#GraphicsAttribute\", \"http://www.w3.org/TR/SVG11/feature#Hyperlinking\", \"http://www.w3.org/TR/SVG11/feature#Image\", \"http://www.w3.org/TR/SVG11/feature#Marker\", \"http://www.w3.org/TR/SVG11/feature#Mask\", \"http://www.w3.org/TR/SVG11/feature#OpacityAttribute\", \"http://www.w3.org/TR/SVG11/feature#PaintAttribute\", \"http://www.w3.org/TR/SVG11/feature#Pattern\", \"http://www.w3.org/TR/SVG11/feature#SVG-animation\", \"http://www.w3.org/TR/SVG11/feature#SVG-dynamic\", \"http://www.w3.org/TR/SVG11/feature#SVG-static\", \"http://www.w3.org/TR/SVG11/feature#SVGDOM-animation\", \"http://www.w3.org/TR/SVG11/feature#SVGDOM-dynamic\", \"http://www.w3.org/TR/SVG11/feature#SVGDOM-static\", \"http://www.w3.org/TR/SVG11/feature#Scripting\", \"http://www.w3.org/TR/SVG11/feature#Shape\", \"http://www.w3.org/TR/SVG11/feature#Structure\", \"http://www.w3.org/TR/SVG11/feature#Style\", \"http://www.w3.org/TR/SVG11/feature#Text\", \"http://www.w3.org/TR/SVG11/feature#ViewportAttribute\", \"http://www.w3.org/TR/SVG11/feature#XlinkAttribute\"]\n    },\n    \"restart\": {\n        \"attribOptions\": [\"always\", \"never\", \"whenNotActive\"]\n    },\n    \"script/type\": {\n        \"attribOptions\": [\"application/ecmascript\", \"application/javascript\", \"application/x-ecmascript\", \"application/x-javascript\", \"text/ecmascript\", \"text/javascript\", \"text/jscript\", \"text/livescript\", \"text/tcl\", \"text/x-ecmascript\", \"text/x-javascript\", \"text/babel\", \"text/jsx\"]\n    },\n    \"set/fill\": {\n        \"attribOptions\": [\"freeze\", \"remove\"]\n    },\n    \"shape-rendering\": {\n        \"attribOptions\": [\"auto\", \"crispEdges\", \"geometricPrecision\", \"inherit\", \"optimizeSpeed\"]\n    },\n    \"spacing\": {\n        \"attribOptions\": [\"auto\", \"exact\"]\n    },\n    \"spreadMethod\": {\n        \"attribOptions\": [\"pad\", \"reflect\", \"repeat\"]\n    },\n    \"stitchTiles\": {\n        \"attribOptions\": [\"noStitch\", \"stitch\"]\n    },\n    \"stop-color\": {\n        \"type\": \"color\"\n    },\n    \"stop-opacity\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"stroke\": {\n        \"type\": \"color\"\n    },\n    \"stroke-dasharray\": {\n        \"attribOptions\": [\"inherit\", \"none\"]\n    },\n    \"stroke-dashoffset\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"stroke-linecap\": {\n        \"attribOptions\": [\"butt\", \"inherit\", \"round\", \"square\"]\n    },\n    \"stroke-linejoin\": {\n        \"attribOptions\": [\"bevel\", \"inherit\", \"miter\", \"round\"]\n    },\n    \"stroke-miterlimit\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"stroke-opacity\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"stroke-width\": {\n        \"attribOptions\": [\"inherit\"]\n    },\n    \"style/type\": {\n        \"attribOptions\": [\"text/css\"]\n    },\n    \"svg/xmlns\": {\n        \"attribOptions\": [\"http://www.w3.org/2000/svg\"]\n    },\n    \"svg/xmlns:xlink\": {\n        \"attribOptions\": [\"http://www.w3.org/1999/xlink\"]\n    },\n    \"systemLanguage\": {\n        \"attribOptions\": [\"aa\", \"ab\", \"af\", \"am\", \"ar\", \"as\", \"ay\", \"az\", \"ba\", \"be\", \"bg\", \"bh\", \"bi\", \"bn\", \"bo\", \"br\", \"ca\", \"co\", \"cs\", \"cy\", \"da\", \"de\", \"dz\", \"el\", \"en\", \"eo\", \"es\", \"et\", \"eu\", \"fa\", \"fi\", \"fj\", \"fo\", \"fr\", \"fy\", \"ga\", \"gd\", \"gl\", \"gn\", \"gu\", \"ha\", \"hi\", \"hr\", \"hu\", \"hy\", \"ia\", \"ie\", \"ik\", \"in\", \"is\", \"it\", \"iw\", \"ja\", \"ji\", \"jw\", \"ka\", \"kk\", \"kl\", \"km\", \"kn\", \"ko\", \"ks\", \"ku\", \"ky\", \"la\", \"ln\", \"lo\", \"lt\", \"lv\", \"mg\", \"mi\", \"mk\", \"ml\", \"mn\", \"mo\", \"mr\", \"ms\", \"mt\", \"my\", \"na\", \"ne\", \"nl\", \"no\", \"oc\", \"om\", \"or\", \"pa\", \"pl\", \"ps\", \"pt\", \"qu\", \"rm\", \"rn\", \"ro\", \"ru\", \"rw\", \"sa\", \"sd\", \"sg\", \"sh\", \"si\", \"sk\", \"sl\", \"sm\", \"sn\", \"so\", \"sq\", \"sr\", \"ss\", \"st\", \"su\", \"sv\", \"sw\", \"ta\", \"te\", \"tg\", \"th\", \"ti\", \"tk\", \"tl\", \"tn\", \"to\", \"tr\", \"ts\", \"tt\", \"tw\", \"uk\", \"ur\", \"uz\", \"vi\", \"vo\", \"wo\", \"xh\", \"yo\", \"zh\", \"zu\"],\n        \"multiple\": true\n    },\n    \"target\": {\n        \"attribOptions\": [\"_blank\", \"_parent\", \"_replace\", \"_self\", \"_top\"]\n    },\n    \"text-anchor\": {\n        \"attribOptions\": [\"end\", \"inherit\", \"middle\", \"start\"]\n    },\n    \"text-decoration\": {\n        \"attribOptions\": [\"blink\", \"inherit\", \"line-through\", \"none\", \"overline\", \"underline\"]\n    },\n    \"text-rendering\": {\n        \"attribOptions\": [\"auto\", \"geometricPrecision\", \"inherit\", \"optimizeLegibility\", \"optimizeSpeed\"]\n    },\n    \"transform\": {\n        \"attribOptions\": [\"matrix()\", \"rotate()\", \"scale()\", \"skewX()\", \"skewY()\", \"translate()\"],\n        \"multiple\": true\n    },\n    \"unicode-bidi\": {\n        \"attribOptions\": [\"bidi-override\", \"embed\", \"inherit\", \"normal\"]\n    },\n    \"version\": {\n        \"attribOptions\": [\"1.0\", \"1.1\"]\n    },\n    \"visibility\": {\n        \"attribOptions\": [\"collapse\", \"hidden\", \"inherit\", \"visible\"]\n    },\n    \"word-spacing\": {\n        \"attribOptions\": [\"inherit\", \"normal\"]\n    },\n    \"writing-mode\": {\n        \"attribOptions\": [\"inherit\", \"lr\", \"lr-tb\", \"rl\", \"rl-tb\", \"tb\", \"tb-rl\"]\n    },\n    \"xChannelSelector\": {\n        \"attribOptions\": [\"R\", \"G\", \"B\", \"A\"]\n    },\n    \"xlink:actuate\": {\n        \"attribOptions\": [\"onLoad\", \"onRequest\"]\n    },\n    \"xlink:show\": {\n        \"attribOptions\": [\"embed\", \"new\", \"none\", \"other\", \"replace\"]\n    },\n    \"xlink:type\": {\n        \"attribOptions\": [\"simple\"]\n    },\n    \"xml:lang\": {\n        \"attribOptions\": [\"aa\", \"ab\", \"af\", \"am\", \"ar\", \"as\", \"ay\", \"az\", \"ba\", \"be\", \"bg\", \"bh\", \"bi\", \"bn\", \"bo\", \"br\", \"ca\", \"co\", \"cs\", \"cy\", \"da\", \"de\", \"dz\", \"el\", \"en\", \"eo\", \"es\", \"et\", \"eu\", \"fa\", \"fi\", \"fj\", \"fo\", \"fr\", \"fy\", \"ga\", \"gd\", \"gl\", \"gn\", \"gu\", \"ha\", \"hi\", \"hr\", \"hu\", \"hy\", \"ia\", \"ie\", \"ik\", \"in\", \"is\", \"it\", \"iw\", \"ja\", \"ji\", \"jw\", \"ka\", \"kk\", \"kl\", \"km\", \"kn\", \"ko\", \"ks\", \"ku\", \"ky\", \"la\", \"ln\", \"lo\", \"lt\", \"lv\", \"mg\", \"mi\", \"mk\", \"ml\", \"mn\", \"mo\", \"mr\", \"ms\", \"mt\", \"my\", \"na\", \"ne\", \"nl\", \"no\", \"oc\", \"om\", \"or\", \"pa\", \"pl\", \"ps\", \"pt\", \"qu\", \"rm\", \"rn\", \"ro\", \"ru\", \"rw\", \"sa\", \"sd\", \"sg\", \"sh\", \"si\", \"sk\", \"sl\", \"sm\", \"sn\", \"so\", \"sq\", \"sr\", \"ss\", \"st\", \"su\", \"sv\", \"sw\", \"ta\", \"te\", \"tg\", \"th\", \"ti\", \"tk\", \"tl\", \"tn\", \"to\", \"tr\", \"ts\", \"tt\", \"tw\", \"uk\", \"ur\", \"uz\", \"vi\", \"vo\", \"wo\", \"xh\", \"yo\", \"zh\", \"zu\"]\n    },\n    \"xml:space\": {\n        \"attribOptions\": [\"default\", \"preserve\"]\n    },\n    \"yChannelSelector\": {\n        \"attribOptions\": [\"R\", \"G\", \"B\", \"A\"]\n    },\n    \"zoomAndPan\": {\n        \"attribOptions\": [\"disable\", \"magnify\"]\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/SVGCodeHints/SVGTags.json",
    "content": "{\n    \"attributeGroups\": {\n        \"animationAddition\":        [\"accumulate\", \"additive\"],\n        \"animationAttributeTarget\": [\"attributeName\", \"attributeType\"],\n        \"animationEvent\":           [\"onbegin\", \"onend\", \"onload\", \"onrepeat\"],\n        \"animationTiming\":          [\"begin\", \"dur\", \"end\", \"fill\", \"max\", \"min\", \"repeatCount\", \"repeatDur\", \"restart\"],\n        \"animationValue\":           [\"by\", \"calcMode\", \"from\", \"keySplines\", \"keyTimes\", \"to\", \"values\"],\n        \"conditionalProcessing\":    [\"requiredExtensions\", \"requiredFeatures\", \"systemLanguage\"],\n        \"core\":                     [\"id\", \"xml:base\", \"xml:lang\", \"xml:space\"],\n        \"documentEvent\":            [\"onabort\", \"onerror\", \"onresize\", \"onscroll\", \"onunload\", \"onzoom\"],\n        \"filterPrimitive\":          [\"height\", \"result\", \"width\", \"x\", \"y\"],\n        \"graphicalEvent\":           [\"onactivate\", \"onclick\", \"onfocusin\", \"onfocusout\", \"onload\", \"onmousedown\", \"onmousemove\", \"onmouseout\", \"onmouseover\", \"onmouseup\"],\n        \"presentation\":             [\"alignment-baseline\", \"baseline-shift\", \"clip\", \"clip-path\", \"clip-rule\", \"color\", \"color-interpolation\", \"color-interpolation-filters\", \"color-profile\", \"color-rendering\", \"cursor\", \"direction\", \"display\", \"dominant-baseline\", \"enable-background\", \"fill\", \"fill-opacity\", \"fill-rule\", \"filter\", \"flood-color\", \"flood-opacity\", \"font-family\", \"font-size\", \"font-size-adjust\", \"font-stretch\", \"font-style\", \"font-variant\", \"font-weight\", \"glyph-orientation-horizontal\", \"glyph-orientation-vertical\", \"image-rendering\", \"kerning\", \"letter-spacing\", \"lighting-color\", \"marker-end\", \"marker-mid\", \"marker-start\", \"mask\", \"opacity\", \"overflow\", \"pointer-events\", \"shape-rendering\", \"stop-color\", \"stop-opacity\", \"stroke\", \"stroke-dasharray\", \"stroke-dashoffset\", \"stroke-linecap\", \"stroke-linejoin\", \"stroke-miterlimit\", \"stroke-opacity\", \"stroke-width\", \"text-anchor\", \"text-decoration\", \"text-rendering\", \"unicode-bidi\", \"visibility\", \"word-spacing\", \"writing-mode\"],\n        \"transferFunctionElement\":  [\"amplitude\", \"exponent\", \"intercept\", \"offset\", \"slope\", \"tableValues\", \"type\"],\n        \"xlink\":                    [\"xlink:actuate\", \"xlink:arcrole\", \"xlink:href\", \"xlink:role\", \"xlink:show\", \"xlink:title\", \"xlink:type\"]\n    },\n    \"tags\": {\n        \"a\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"style\", \"target\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\", \"xlink\"]\n        },\n        \"altGlyph\": {\n            \"attributes\": [\"class\", \"dx\", \"dy\", \"externalResourcesRequired\", \"format\", \"glyphRef\", \"rotate\", \"style\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\", \"xlink\"]\n        },\n        \"altGlyphDef\": {\n            \"attributeGroups\": [\"core\"]\n        },\n        \"altGlyphItem\": {\n            \"attributeGroups\": [\"core\"]\n        },\n        \"animate\": {\n            \"attributes\": [\"externalResourcesRequired\"],\n            \"attributeGroups\": [\"animationAddition\", \"animationAttributeTarget\", \"animationEvent\", \"animationTiming\", \"animationValue\", \"conditionalProcessing\", \"core\", \"presentation\", \"xlink\"]\n        },\n        \"animateColor\": {\n            \"attributes\": [\"externalResourcesRequired\"],\n            \"attributeGroups\": [\"animationAddition\", \"animationAttributeTarget\", \"animationEvent\", \"animationTiming\", \"animationValue\", \"conditionalProcessing\", \"core\", \"presentation\", \"xlink\"]\n        },\n        \"animateMotion\": {\n            \"attributes\": [\"externalResourcesRequired\", \"keyPoints\", \"origin\", \"path\", \"rotate\"],\n            \"attributeGroups\": [\"animationAddition\", \"animationEvent\", \"animationTiming\", \"animationValue\", \"conditionalProcessing\", \"core\", \"xlink\"]\n        },\n        \"animateTransform\": {\n            \"attributes\": [\"externalResourcesRequired\", \"type\"],\n            \"attributeGroups\": [\"animationAddition\", \"animationAttributeTarget\", \"animationEvent\", \"animationTiming\", \"animationValue\", \"conditionalProcessing\", \"core\", \"xlink\"]\n        },\n        \"circle\": {\n            \"attributes\": [\"class\", \"cx\", \"cy\", \"externalResourcesRequired\", \"r\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"clipPath\": {\n            \"attributes\": [\"class\", \"clipPathUnits\", \"externalResourcesRequired\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"presentation\"]\n        },\n        \"color-profile\": {\n            \"attributes\": [\"local\", \"name\", \"rendering-intent\"],\n            \"attributeGroups\": [\"core\", \"xlink\"]\n        },\n        \"cursor\": {\n            \"attributes\": [\"externalResourcesRequired\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"xlink\"]\n        },\n        \"defs\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"desc\": {\n            \"attributes\": [\"class\", \"style\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"ellipse\": {\n            \"attributes\": [\"class\", \"cx\", \"cy\", \"externalResourcesRequired\", \"rx\", \"ry\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"feBlend\": {\n            \"attributes\": [\"class\", \"in2\", \"in\", \"mode\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feColorMatrix\": {\n            \"attibutes\": [\"class\", \"in\", \"style\", \"type\", \"values\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feComponentTransfer\": {\n            \"attributes\": [\"class\", \"in\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feComposite\": {\n            \"attributes\": [\"class\", \"in2\", \"in\", \"k1\", \"k2\", \"k3\", \"k4\", \"operator\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feConvolveMatrix\": {\n            \"attributes\": [\"bias\", \"class\", \"divisor\", \"edgeMode\", \"in\", \"kernelMatrix\", \"kernelUnitLength\", \"order\", \"preserveAlpha\", \"style\", \"targetX\", \"targetY\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feDiffuseLighting\": {\n            \"attributes\": [\"class\", \"diffuseConstant\", \"in\", \"kernelUnitLength\", \"style\", \"surfaceScale\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feDisplacementMap\": {\n            \"attributes\": [\"class\", \"in2\", \"in\", \"scale\", \"style\", \"xChannelSelector\", \"yChannelSelector\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feDistantLight\": {\n            \"attributes\": [\"azimuth\", \"elevation\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"feFlood\": {\n            \"attributes\": [\"class\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feFuncA\": {\n        \t\"attributeGroups\": [\"core\", \"transferFunctionElement\"]\n        },\n        \"feFuncB\": {\n        \t\"attributeGroups\": [\"core\", \"transferFunctionElement\"]\n        },\n        \"feFuncG\": {\n        \t\"attributeGroups\": [\"core\", \"transferFunctionElement\"]\n        },\n        \"feFuncR\": {\n        \t\"attributeGroups\": [\"core\", \"transferFunctionElement\"]\n        },\n        \"feGaussianBlur\": {\n            \"attributes\": [\"class\", \"in\", \"stdDeviation\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feImage\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"preserveAspectRatio\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\", \"xlink\"]\n        },\n        \"feMerge\": {\n            \"attributes\": [\"class\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feMergeNode\": {\n            \"attributes\": [\"in\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"feMorphology\": {\n            \"attributes\": [\"class\", \"in\", \"operator\", \"radius\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feOffset\": {\n            \"attributes\": [\"class\", \"dx\", \"dy\", \"in\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"fePointLight\": {\n            \"attributes\": [\"x\", \"y\", \"z\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"feSpecularLighting\": {\n            \"attributes\": [\"class\", \"in\", \"kernelUnitLength\", \"specularConstant\", \"specularExponent\", \"style\", \"surfaceScale\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feSpotLight\": {\n            \"attributes\": [\"limitingConeAngle\", \"pointsAtX\", \"pointsAtY\", \"pointsAtZ\", \"specularExponent\", \"x\", \"y\", \"z\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"feTile\": {\n            \"attributes\": [\"class\", \"in\", \"style\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"feTurbulence\": {\n            \"attributes\": [\"baseFrequency\", \"class\", \"numOctaves\", \"seed\", \"stitchTiles\", \"style\", \"type\"],\n            \"attributeGroups\": [\"core\", \"filterPrimitive\", \"presentation\"]\n        },\n        \"filter\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"filterRes\", \"filterUnits\", \"height\", \"primitiveUnits\", \"style\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"core\", \"presentation\", \"xlink\"]\n        },\n        \"font\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"horiz-adv-x\", \"horiz-origin-x\", \"horiz-origin-y\", \"style\", \"vert-adv-y\", \"vert-origin-x\", \"vert-origin-y\"],\n            \"attributeGroups\": [\"core\", \"presentation\"]\n        },\n        \"font-face\": {\n            \"attributes\": [\"accent-height\", \"alphabetic\", \"ascent\", \"bbox\", \"cap-height\", \"descent\", \"font-family\", \"font-size\", \"font-stretch\", \"font-style\", \"font-variant\", \"font-weight\", \"hanging\", \"ideographic\", \"mathematical\", \"overline-position\", \"overline-thickness\", \"panose-1\", \"slope\", \"stemh\", \"stemv\", \"strikethrough-position\", \"strikethrough-thickness\", \"underline-position\", \"underline-thickness\", \"unicode-range\", \"units-per-em\", \"v-alphabetic\", \"v-hanging\", \"v-ideographic\", \"v-mathematical\", \"widths\", \"x-height\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"font-face-format\": {\n            \"attributes\": [\"string\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"font-face-name\": {\n            \"attributes\": [\"name\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"font-face-src\": {\n        \t\"attributeGroups\": [\"core\"]\n        },\n        \"font-face-uri\": {\n        \t\"attributeGroups\": [\"core\", \"xlink\"]\n        },\n        \"foreignObject\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"height\", \"style\", \"transform\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"g\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"glyph\": {\n            \"attributes\": [\"arabic-form\", \"class\", \"d\", \"glyph-name\", \"horiz-adv-x\", \"lang\", \"orientation\", \"style\", \"unicode\", \"vert-adv-y\", \"vert-origin-x\", \"vert-origin-y\"],\n            \"attributeGroups\": [\"core\", \"presentation\"]\n        },\n        \"glyphRef\": {\n            \"attributes\": [\"class\", \"dx\", \"dy\", \"format\", \"glyphRef\", \"style\", \"x\", \"y\"],\n            \"attributeGroups\": [\"core\", \"presentation\", \"xlink\"]\n        },\n        \"hkern\": {\n            \"attributes\": [\"g1\", \"g2\", \"k\", \"u1\", \"u2\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"image\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"height\", \"preserveAspectRatio\", \"style\", \"transform\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\", \"xlink\"]\n        },\n        \"line\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"style\", \"transform\", \"x1\", \"x2\", \"y1\", \"y2\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"linearGradient\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"gradientTransform\", \"gradientUnits\", \"spreadMethod\", \"style\", \"x1\", \"x2\", \"y1\", \"y2\"],\n            \"attributeGroups\": [\"core\", \"presentation\", \"xlink\"]\n        },\n        \"marker\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"markerHeight\", \"markerUnits\", \"markerWidth\", \"orient\", \"preserveAspectRatio\", \"refX\", \"refY\", \"style\", \"viewBox\"],\n            \"attributeGroups\": [\"core\", \"presentation\"]\n        },\n        \"mask\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"height\", \"maskContentUnits\", \"maskUnits\", \"style\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"presentation\"]\n        },\n        \"metadata\": {\n        \t\"attributeGroups\": [\"core\"]\n        },\n        \"missing-glyph\": {\n            \"attributes\": [\"class\", \"d\", \"horiz-adv-x\", \"style\", \"vert-adv-y\", \"vert-origin-x\", \"vert-origin-y\"],\n            \"attributeGroups\": [\"core\", \"presentation\"]\n        },\n        \"mpath\": {\n            \"attributes\": [\"externalResourcesRequired\"],\n            \"attributeGroups\": [\"core\", \"xlink\"]\n        },\n        \"path\": {\n            \"attributes\": [\"class\", \"d\", \"externalResourcesRequired\", \"pathLength\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"pattern\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"height\", \"patternContentUnits\", \"patternTransform\", \"patternUnits\", \"preserveAspectRatio\", \"style\", \"viewBox\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"presentation\", \"xlink\"]\n        },\n        \"polygon\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"points\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"polyline\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"points\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"radialGradient\": {\n            \"attributes\": [\"class\", \"cx\", \"cy\", \"externalResourcesRequired\", \"fx\", \"fy\", \"gradientTransform\", \"gradientUnits\", \"r\", \"spreadMethod\", \"style\"],\n            \"attributeGroups\": [\"core\", \"presentation\", \"xlink\"]\n        },\n        \"rect\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"height\", \"rx\", \"ry\", \"style\", \"transform\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"script\": {\n            \"attributes\": [\"externalResourcesRequired\", \"type\"],\n            \"attributeGroups\": [\"core\", \"xlink\"]\n        },\n        \"set\": {\n            \"attributes\": [\"externalResourcesRequired\", \"to\"],\n            \"attributeGroups\": [\"animationAttributeTarget\", \"animationEvent\", \"animationTiming\", \"conditionalProcessing\", \"core\", \"xlink\"]\n        },\n        \"stop\": {\n            \"attributes\": [\"class\", \"offset\", \"style\"],\n            \"attributeGroups\": [\"core\", \"presentation\"]\n        },\n        \"style\": {\n            \"attributes\": [\"media\", \"title\", \"type\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"svg\": {\n            \"attributes\": [\"baseProfile\", \"class\", \"contentScriptType\", \"contentStyleType\", \"externalResourcesRequired\", \"height\", \"preserveAspectRatio\", \"style\", \"version\", \"viewBox\", \"width\", \"x\", \"xmlns\", \"xmlns:xlink\", \"y\", \"zoomAndPan\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"documentEvent\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"switch\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"style\", \"transform\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"symbol\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"preserveAspectRatio\", \"style\", \"viewBox\"],\n            \"attributeGroups\": [\"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"text\": {\n            \"attributes\": [\"class\", \"dx\", \"dy\", \"externalResourcesRequired\", \"lengthAdjust\", \"rotate\", \"style\", \"textLength\", \"transform\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"textPath\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"method\", \"spacing\", \"startOffset\", \"style\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"title\": {\n            \"attributes\": [\"class\", \"style\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"tref\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"style\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\", \"xlink\"]\n        },\n        \"tspan\": {\n            \"attributes\": [\"class\", \"dx\", \"dy\", \"externalResourcesRequired\", \"lengthAdjust\", \"rotate\", \"style\", \"textLength\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\"]\n        },\n        \"use\": {\n            \"attributes\": [\"class\", \"externalResourcesRequired\", \"height\", \"style\", \"transform\", \"width\", \"x\", \"y\"],\n            \"attributeGroups\": [\"conditionalProcessing\", \"core\", \"graphicalEvent\", \"presentation\", \"xlink\"]\n        },\n        \"view\": {\n            \"attributes\": [\"externalResourcesRequired\", \"preserveAspectRatio\", \"viewBox\", \"viewTarget\", \"zoomAndPan\"],\n            \"attributeGroups\": [\"core\"]\n        },\n        \"vkern\": {\n            \"attributes\": [\"g1\", \"g2\", \"k\", \"u1\", \"u2\"],\n            \"attributeGroups\": [\"core\"]\n        }\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/SVGCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependencies.\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        XMLUtils            = brackets.getModule(\"language/XMLUtils\"),\n        StringMatch         = brackets.getModule(\"utils/StringMatch\"),\n        ExtensionUtils      = brackets.getModule(\"utils/ExtensionUtils\"),\n        ColorUtils          = brackets.getModule(\"utils/ColorUtils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        _                   = brackets.getModule(\"thirdparty/lodash\"),\n        SVGTags             = require(\"text!SVGTags.json\"),\n        SVGAttributes       = require(\"text!SVGAttributes.json\"),\n        cachedAttributes    = {},\n        tagData,\n        attributeData,\n        isSVGEnabled;\n\n    var stringMatcherOptions = {\n        preferPrefixMatches: true\n    };\n\n    // Define our own pref for hinting.\n    PreferencesManager.definePreference(\"codehint.SVGHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_SVG_HINTS\n    });\n\n    // Preferences to control hint.\n    function _isSVGHintsEnabled() {\n        return (PreferencesManager.get(\"codehint.SVGHints\") !== false &&\n                PreferencesManager.get(\"showCodeHints\") !== false);\n    }\n\n    PreferencesManager.on(\"change\", \"codehint.SVGHints\", function () {\n        isSVGEnabled = _isSVGHintsEnabled();\n    });\n\n    PreferencesManager.on(\"change\", \"showCodeHints\", function () {\n        isSVGEnabled = _isSVGHintsEnabled();\n    });\n\n    // Check if SVG Hints are available.\n    isSVGEnabled = _isSVGHintsEnabled();\n\n    /**\n     * Returns a list of attributes used by a tag.\n     *\n     * @param {string} tagName name of the SVG tag.\n     * @return {Array.<string>} list of attributes.\n     */\n    function getTagAttributes(tagName) {\n        var tag;\n\n        if (!cachedAttributes.hasOwnProperty(tagName)) {\n            tag = tagData.tags[tagName];\n            cachedAttributes[tagName] = [];\n            if (tag.attributes) {\n                cachedAttributes[tagName] =  cachedAttributes[tagName].concat(tag.attributes);\n            }\n            tag.attributeGroups.forEach(function (group) {\n                if (tagData.attributeGroups.hasOwnProperty(group)) {\n                    cachedAttributes[tagName] = cachedAttributes[tagName].concat(tagData.attributeGroups[group]);\n                }\n            });\n            cachedAttributes[tagName] = _.uniq(cachedAttributes[tagName].sort(), true);\n        }\n        return cachedAttributes[tagName];\n    }\n\n    /*\n     * Returns a sorted and formatted list of hints with the query substring\n     * highlighted.\n     *\n     * @param {Array.<Object>} hints - the list of hints to format\n     * @param {string} query - querystring used for highlighting matched\n     *      portions of each hint\n     * @return {Array.jQuery} sorted Array of jQuery DOM elements to insert\n     */\n    function formatHints(hints, query) {\n        var hasColorSwatch = hints.some(function (token) {\n            return token.color;\n        });\n\n        StringMatch.basicMatchSort(hints);\n        return hints.map(function (token) {\n            var $hintObj = $(\"<span>\").addClass(\"brackets-svg-hints\");\n\n            // highlight the matched portion of each hint\n            if (token.stringRanges) {\n                token.stringRanges.forEach(function (item) {\n                    if (item.matched) {\n                        $hintObj.append($(\"<span>\")\n                            .text(item.text)\n                            .addClass(\"matched-hint\"));\n                    } else {\n                        $hintObj.append(item.text);\n                    }\n                });\n            } else {\n                $hintObj.text(token.value);\n            }\n\n            if (hasColorSwatch) {\n                $hintObj = ColorUtils.formatColorHint($hintObj, token.color);\n            }\n\n            return $hintObj;\n        });\n    }\n\n    /**\n     * @constructor\n     */\n    function SVGCodeHints() {\n        this.tagInfo = null;\n    }\n\n    /**\n     * Determines whether SVG code hints are available in the current editor.\n     *\n     * @param {!Editor} editor An instance of Editor\n     * @param {string} implicitChar A single character that was inserted by the\n     * user or null if the request was explicitly made to start hinting session.\n     *\n     * @return {boolean} Determines whether or not hints are available in the current context.\n     */\n    SVGCodeHints.prototype.hasHints = function (editor, implicitChar) {\n        if (isSVGEnabled && editor.getModeForSelection() === \"image/svg+xml\") {\n            this.editor = editor;\n            this.tagInfo = XMLUtils.getTagInfo(this.editor, this.editor.getCursorPos());\n\n            if (this.tagInfo && this.tagInfo.tokenType) {\n                return true;\n            }\n        }\n        return false;\n    };\n\n    /**\n     * Returns a list of hints that are available in the current context,\n     * or null if there are no hints available.\n     *\n     * @param {string} implicitChar A character that the user typed in the hinting session.\n     * @return {!{hints: Array.<jQueryObject>, match: string, selectInitial: boolean, handleWideResults: boolean}}\n     */\n    SVGCodeHints.prototype.getHints = function (implicitChar) {\n        var hints = [], query, tagInfo, attributes = [], options = [], index, isMultiple, tagSpecificOptions;\n\n        tagInfo  = XMLUtils.getTagInfo(this.editor, this.editor.getCursorPos());\n        this.tagInfo = tagInfo;\n\n        if (tagInfo && tagInfo.tokenType) {\n            query = tagInfo.token.string.substr(0, tagInfo.offset).trim();\n\n            if (tagInfo.tokenType === XMLUtils.TOKEN_TAG) {\n                hints = $.map(Object.keys(tagData.tags), function (tag) {\n                    var match = StringMatch.stringMatch(tag, query, stringMatcherOptions);\n                    if (match) {\n                        return match;\n                    }\n                });\n            } else if (tagInfo.tokenType === XMLUtils.TOKEN_ATTR) {\n                if (!tagData.tags[tagInfo.tagName]) {\n                    return null;\n                }\n                // Get attributes.\n                attributes = getTagAttributes(tagInfo.tagName);\n                hints = $.map(attributes, function (attribute) {\n                    if (tagInfo.exclusionList.indexOf(attribute) === -1) {\n                        var match = StringMatch.stringMatch(attribute, query, stringMatcherOptions);\n                        if (match) {\n                            return match;\n                        }\n                    }\n                });\n            } else if (tagInfo.tokenType === XMLUtils.TOKEN_VALUE) {\n                index = tagInfo.tagName + \"/\" + tagInfo.attrName;\n                tagSpecificOptions = attributeData[index];\n\n                if (!tagData.tags[tagInfo.tagName] && !(attributeData[tagInfo.attrName] || tagSpecificOptions)) {\n                    return null;\n                }\n\n                // Get attribute options.\n                // Prefer tag/attribute for specific tags, else use general options for attributes.\n                if (tagSpecificOptions) {\n                    options = tagSpecificOptions.attribOptions;\n                    isMultiple = tagSpecificOptions.multiple;\n                } else if (attributeData[tagInfo.attrName]) {\n                    options = attributeData[tagInfo.attrName].attribOptions;\n                    isMultiple = attributeData[tagInfo.attrName].multiple;\n\n                    if (attributeData[tagInfo.attrName].type === \"color\") {\n                        options = ColorUtils.COLOR_NAMES.map(function (color) {\n                            return { text: color, color: color };\n                        });\n                        options = options.concat([\"currentColor\", \"transparent\"]);\n                    }\n                }\n\n                // Stop if the attribute doesn't support multiple options.\n                if (!isMultiple && /\\s+/.test(tagInfo.token.string)) {\n                    return null;\n                }\n\n                query = XMLUtils.getValueQuery(tagInfo);\n                hints = $.map(options, function (option) {\n                    if (tagInfo.exclusionList.indexOf(option) === -1) {\n                        var match = StringMatch.stringMatch(option.text || option, query, stringMatcherOptions);\n                        if (match) {\n                            if (option.color) {\n                                match.color = option.color;\n                            }\n\n                            return match;\n                        }\n                    }\n                });\n            }\n            return {\n                hints: formatHints(hints, query),\n                match: null,\n                selectInitial: true,\n                handleWideResults: false\n            };\n        }\n        return null;\n    };\n\n    /**\n     * Insert the selected hint into the editor\n     *\n     * @param {string} completion The string that user selected from the list\n     * @return {boolean} Determines whether or not to continue the hinting session\n     */\n    SVGCodeHints.prototype.insertHint = function (completion) {\n        var tagInfo = this.tagInfo,\n            pos     = this.editor.getCursorPos(),\n            start   = {line: -1, ch: -1},\n            end     = {line: -1, ch: -1},\n            query,\n            startChar,\n            endChar,\n            quoteChar;\n\n        if (completion.jquery) {\n            completion = completion.text();\n        }\n        start.line = end.line = pos.line;\n\n        if (tagInfo.tokenType === XMLUtils.TOKEN_TAG) {\n            start.ch = pos.ch - tagInfo.offset;\n            end.ch = tagInfo.token.end;\n            this.editor.document.replaceRange(completion, start, end);\n            return false;\n        } else if (tagInfo.tokenType === XMLUtils.TOKEN_ATTR) {\n            if (!tagInfo.shouldReplace) {\n                completion += \"=\\\"\\\"\";\n\n                // In case the current token is whitespace, start and end will be same.\n                if (XMLUtils.regexWhitespace.test(tagInfo.token.string)) {\n                    start.ch = end.ch = pos.ch;\n                } else {\n                    start.ch = pos.ch - tagInfo.offset;\n                    end.ch = pos.ch;\n                }\n                this.editor.document.replaceRange(completion, start, end);\n                this.editor.setCursorPos(start.line, start.ch + completion.length - 1);\n                return true;\n            } else {\n                // We don't append =\"\" again, just replace the attribute token.\n                start.ch = tagInfo.token.start;\n                end.ch = tagInfo.token.end;\n                this.editor.document.replaceRange(completion, start, end);\n                this.editor.setCursorPos(start.line, start.ch + completion.length);\n                return false;\n            }\n        } else if (tagInfo.tokenType === XMLUtils.TOKEN_VALUE) {\n            startChar = tagInfo.token.string.charAt(0);\n            endChar = tagInfo.token.string.substr(-1, 1);\n\n            // Get the quote character.\n            if (/^['\"]$/.test(startChar)) {\n                quoteChar = startChar;\n            } else {\n                quoteChar = \"\\\"\";\n            }\n\n            // Append quotes to attribute value if not already.\n            if (!/^['\"]$/.test(startChar)) {\n                completion = quoteChar + completion;\n            }\n            if (!/^['\"]$/.test(endChar) || tagInfo.token.string.length === 1) {\n                completion = completion + quoteChar;\n            }\n\n            query = XMLUtils.getValueQuery(tagInfo);\n            start.ch = pos.ch - query.length;\n            end.ch = pos.ch;\n            this.editor.document.replaceRange(completion, start, end);\n\n            // Place cursor outside the quote if the next char is quote.\n            if (/^['\"]$/.test(tagInfo.token.string.substr(tagInfo.offset, 1))) {\n                this.editor.setCursorPos(pos.line, start.ch + completion.length + 1);\n            }\n            return false;\n        }\n    };\n\n    AppInit.appReady(function () {\n        tagData = JSON.parse(SVGTags);\n        attributeData = JSON.parse(SVGAttributes);\n\n        var hintProvider = new SVGCodeHints();\n        CodeHintManager.registerHintProvider(hintProvider, [\"svg\"], 0);\n\n        ExtensionUtils.loadStyleSheet(module, \"styles/brackets-svg-hints.css\");\n        exports.hintProvider = hintProvider;\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/SVGCodeHints/styles/brackets-svg-hints.css",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n.brackets-svg-hints .matched-hint {\n    font-weight: 500;\n}\n.dark .brackets-svg-hints .matched-hint {\n    color: #ccc;\n}\n"
  },
  {
    "path": "src/extensions/default/SVGCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, beforeEach, afterEach, it, expect */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules.\n    var SpecRunnerUtils     = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        SVGCodeHints        = require(\"./main\");\n\n    describe(\"SVG Code Hints\", function () {\n        var testContent, testDocument, testEditor;\n\n        // SVG Content that we will be using to run tests against.\n        testContent =   \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" ?>\\n\" +\n                        \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\" +\n                        \"     width=\\\"200\\\" height=\\\"200\\\" preserveAspectRatio=\\\"xMinYMin meet\\\">\\n\" +\n                        \"    <title>Brackets SVG Code Hints</title>\\n\" +\n                        \"    <rect width=\\\"200\\\" height=\\\"200\\\" baseline-shift=\\\"baseline\\\" alignment-baseline=\\\"alphabetic\\\" stroke-width=\\\"1\\\" color=\\\"\\\"></rect>\\n\" +\n                        \"    <rect width='160' height='160' x='20' y='20' baseline-shift='super' alignment-baseline='baseline' color='rent' fill='transparent' />\\n\" +\n                        \"    <g>\\n\" +\n                        \"        \\n\" +\n                        \"    </g>\\n\" +\n                        \"</svg>\\n\";\n\n        beforeEach(function () {\n            // Create a mock svg document to run tests against.\n            var mockEditor = SpecRunnerUtils.createMockEditor(testContent, \"svg\", {\n                startLine: 0,\n                endLine: 10\n            });\n            testEditor = mockEditor.editor;\n            testDocument = mockEditor.doc;\n        });\n\n        afterEach(function () {\n            testEditor.destroy();\n            testEditor = null;\n        });\n\n        // Returns a list of hints.\n        function extractHintList(hints) {\n            return $.map(hints, function ($node) {\n                return $node.text();\n            });\n        }\n\n        // Verifies the availability of hints.\n        function expectHints(provider) {\n            expect(provider.hasHints(testEditor, null)).toBe(true);\n            var hintObj = provider.getHints();\n            expect(hintObj).toBeTruthy();\n            return hintObj.hints;\n        }\n\n        // Verifies the non-availability of hints.\n        function expectNoHints(provider) {\n            expect(provider.hasHints(testEditor, null)).toBe(false);\n        }\n\n        // Verifies the presence of a hint.\n        function verifyHints(hintList, expectedHint) {\n            var hints = extractHintList(hintList);\n            expect(hints[0]).toBe(expectedHint);\n        }\n\n        // Verifies the exclusion of an unexpected hint.\n        function verifyHintsExcluded(hintList, unexpectedHint) {\n            var hints = extractHintList(hintList);\n            expect(hints.indexOf(unexpectedHint)).toBe(-1);\n        }\n\n        // Inserts the hint in document.\n        function selectHint(provider, expectedHint) {\n            var hintList = expectHints(provider),\n                hints = extractHintList(hintList);\n            expect(hints.indexOf(expectedHint)).not.toBe(-1);\n            return provider.insertHint(expectedHint);\n        }\n\n        // Used to test token at given positions.\n        function expectTokenAt(pos, string, type) {\n            var token = testEditor._codeMirror.getTokenAt(pos);\n            expect(token.string).toBe(string);\n            expect(token.type).toBe(type);\n        }\n\n        // Helper functions for testing cursor position / selection range\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n\n        // Used to test cursor position.\n        function expectCursorAt(pos) {\n            var selection = testEditor.getSelection();\n            expect(fixPos(selection.start)).toEqual(fixPos(selection.end));\n            expect(fixPos(selection.start)).toEqual(fixPos(pos));\n        }\n\n        describe(\"Tag Hinting\", function () {\n            it(\"should hint at < before tag name\", function () {\n                // After < in <svg\n                testEditor.setCursorPos({line: 1, ch: 1});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"a\");\n            });\n\n            it(\"should hint inside the tag name\", function () {\n                // After <sv in <svg\n                testEditor.setCursorPos({line: 1, ch: 3});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"svg\");\n            });\n\n            it(\"should hint at the end of the tag\", function () {\n                // After <svg in <svg\n                testEditor.setCursorPos({line: 1, ch: 4});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"svg\");\n            });\n\n            it(\"should NOT hint in closing tag between < and /\", function () {\n                // Between < and / in </title>\n                testEditor.setCursorPos({line: 3, ch: 35});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // In case we have space between < and /\n                testDocument.replaceRange(\" \", {line: 3, ch: 35});\n                testEditor.setCursorPos({line: 3, ch: 36});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint in closing tag after </\", function () {\n                // After </ in </title>\n                testEditor.setCursorPos({line: 3, ch: 36});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint in the middle of closing tag\", function () {\n                // After </tit in </title>\n                testEditor.setCursorPos({line: 3, ch: 39});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint at the end of closing tag\", function () {\n                // Before > in </title>\n                testEditor.setCursorPos({line: 3, ch: 41});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint after the first space in closing tag\", function () {\n                // Before > in </title >\n                testDocument.replaceRange(\" \", {line: 3, ch: 41});\n                testEditor.setCursorPos({line: 3, ch: 42});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            // A whitespace between < and tag name makes xml invalid.\n            it(\"should NOT hint in case there is a whitespace between < and tag name\", function () {\n                // After < in first < rect\n                testDocument.replaceRange(\" \", {line: 4, ch: 5});\n                testEditor.setCursorPos({line: 4, ch: 6});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint after first character in an invalid tag\", function () {\n                // After < r in first < rect\n                testDocument.replaceRange(\" \", {line: 4, ch: 5});\n                testEditor.setCursorPos({line: 4, ch: 7});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint in the middle of invalid tag\", function () {\n                // After < rec in < rect\n                testDocument.replaceRange(\" \", {line: 4, ch: 5});\n                testEditor.setCursorPos({line: 4, ch: 9});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint inside the content of a tag\", function () {\n                // After > in <title>\n                testEditor.setCursorPos({line: 3, ch: 11});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After Brackets in <title>Brackets\n                testEditor.setCursorPos({line: 3, ch: 20});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // Between <rect></rect>\n                testEditor.setCursorPos({line: 4, ch: 119});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After <title>+space in <title> Brackets\n                testDocument.replaceRange(\" \", {line: 3, ch: 11});\n                testEditor.setCursorPos({line: 3, ch: 12});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should not hint after the closed tag\", function () {\n                // After </rect>\n                testEditor.setCursorPos({line: 4, ch: 126});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After space at </rect>+space\n                testDocument.replaceRange(\" \", {line: 4, ch: 126});\n                testEditor.setCursorPos({line: 4, ch: 127});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After />\n                testEditor.setCursorPos({line: 5, ch: 136});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After space in />+space\n                testDocument.replaceRange(\" \", {line: 5, ch: 136});\n                testEditor.setCursorPos({line: 5, ch: 137});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After </g>\n                testEditor.setCursorPos({line: 8, ch: 8});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After space in </g>+space\n                testDocument.replaceRange(\" \", {line: 8, ch: 8});\n                testEditor.setCursorPos({line: 8, ch: 9});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should hint inside XML declaration\", function () {\n                // After < in <?xml\n                testEditor.setCursorPos({line: 0, ch: 1});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After <?xm\n                testEditor.setCursorPos({line: 0, ch: 4});\n                expectNoHints(SVGCodeHints.hintProvider);\n\n                // After <?xml+space\n                testEditor.setCursorPos({line: 0, ch: 6});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n        });\n\n        describe(\"Attribute Hinting\", function () {\n\n            it(\"should hint after first space after tag\", function () {\n                // After <rect\n                testEditor.setCursorPos({line: 4, ch: 10});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"class\");\n            });\n\n            it(\"should hint after first character of the attribute\", function () {\n                // After <rect w\n                testEditor.setCursorPos({line: 4, ch: 11});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"width\");\n            });\n\n            it(\"should hint in the middle of the attribute\", function () {\n                // After <rect wid\n                testEditor.setCursorPos({line: 4, ch: 13});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"width\");\n            });\n\n            it(\"should hint at the end of the attribute\", function () {\n                // After <rect width\n                testEditor.setCursorPos({line: 4, ch: 15});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"width\");\n            });\n\n            it(\"should NOT hint if we have whitespace between attribute and =\", function () {\n                // Before = in <rect width =\n                testDocument.replaceRange(\"  \", {line: 4, ch: 15});\n                testEditor.setCursorPos({line: 4, ch: 16});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint in case there is a space between < and tag name\", function () {\n                // After space in < rect\n                testDocument.replaceRange(\" \", {line: 4, ch: 5});\n                testEditor.setCursorPos({line: 4, ch: 11});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should exclude hints if they have already been used\", function () {\n                // In first <rect, after <rect+space\n                testEditor.setCursorPos({line: 4, ch: 10});\n                var hintLint = expectHints(SVGCodeHints.hintProvider);\n                verifyHintsExcluded(hintLint, \"width\");\n                verifyHintsExcluded(hintLint, \"height\");\n                verifyHintsExcluded(hintLint, \"baseline-shift\");\n                verifyHintsExcluded(hintLint, \"alignment-baseline\");\n                verifyHintsExcluded(hintLint, \"stroke-width\");\n\n                // In the second <rect, after <rect+space\n                testEditor.setCursorPos({line: 5, ch: 10});\n                hintLint = expectHints(SVGCodeHints.hintProvider);\n                verifyHintsExcluded(hintLint, \"width\");\n                verifyHintsExcluded(hintLint, \"height\");\n                verifyHintsExcluded(hintLint, \"x\");\n                verifyHintsExcluded(hintLint, \"y\");\n                verifyHintsExcluded(hintLint, \"baseline-shift\");\n                verifyHintsExcluded(hintLint, \"alignment-baseline\");\n            });\n\n            it(\"should NOT exclude current token from hints\", function () {\n                var hintList, hints;\n\n                // After <rect w\n                testEditor.setCursorPos({line: 4, ch: 11});\n                hintList = expectHints(SVGCodeHints.hintProvider);\n                hints    = extractHintList(hintList);\n                expect(hints.indexOf(\"width\")).not.toBe(-1);\n\n                // After <rect widt\n                testEditor.setCursorPos({line: 4, ch: 14});\n                hintList = expectHints(SVGCodeHints.hintProvider);\n                hints = extractHintList(hintList);\n                expect(hints.indexOf(\"width\")).not.toBe(-1);\n\n                // After <rect width\n                testEditor.setCursorPos({line: 5, ch: 15});\n                hintList = expectHints(SVGCodeHints.hintProvider);\n                hints = extractHintList(hintList);\n                expect(hints.indexOf(\"width\")).not.toBe(-1);\n            });\n        });\n\n        describe(\"Value Hinting\", function () {\n            it(\"should hint after =\", function () {\n                // After baseline-shift= in second rect.\n                testEditor.setCursorPos({line: 5, ch: 64});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"baseline\");\n            });\n\n            it(\"should hint after ='\", function () {\n                // After baseline-shift='\n                testEditor.setCursorPos({line: 5, ch: 65});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"baseline\");\n            });\n\n            it(\"should hint after =\\\"\", function () {\n                // After baseline-shift=\"\n                testEditor.setCursorPos({line: 4, ch: 51});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"baseline\");\n            });\n\n            it(\"should hint after first character\", function () {\n                // After baseline-shift=\"b\n                testEditor.setCursorPos({line: 4, ch: 52});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"baseline\");\n            });\n\n            it(\"should hint in the middle of value\", function () {\n                // After baseline-shift=\"base\n                testEditor.setCursorPos({line: 4, ch: 55});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"baseline\");\n            });\n\n            it(\"should hint at the end of the value\", function () {\n                // After baseline-shift=\"baseline\n                testEditor.setCursorPos({line: 4, ch: 59});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"baseline\");\n            });\n\n            it(\"should hint for first attribute in multiple options\", function () {\n                // After preserveAspectRatio=\"x\n                testEditor.setCursorPos({line: 2, ch: 52});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"xMaxYMax\");\n            });\n\n            it(\"should hint for second value in multiple options\", function () {\n                // After m in meet\n                testEditor.setCursorPos({line: 2, ch: 61});\n                var hintList = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintList, \"meet\");\n            });\n\n            it(\"should hint in middle of value in muliple options with empty query\", function () {\n                // Between xMinYMid and meet\n                testDocument.replaceRange(\" \", {line: 2, ch: 59});\n                testEditor.setCursorPos({ line: 2, ch: 60});\n                var hintLint = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintLint, \"none\");\n            });\n\n            it(\"should hint in middle of value in multiple options with a query\", function () {\n                // Between xMinYMid and meet\n                testDocument.replaceRange(\" sli\", {line: 2, ch: 59});\n                testEditor.setCursorPos({line: 2, ch: 63});\n                var hintLint = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hintLint, \"slice\");\n            });\n\n            it(\"should NOT hint in case cursor is out of right quote\", function () {\n                // After meet\"\n                testEditor.setCursorPos({line: 2, ch: 65});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should NOT hint in an invalid tag\", function () {\n                // After fill=\" in < rect\n                testDocument.replaceRange(\" \", {line: 4, ch: 5});\n                testEditor.setCursorPos({line: 4, ch: 42});\n                expectNoHints(SVGCodeHints.hintProvider);\n            });\n\n            it(\"should exclude a value if it is already been used\", function () {\n                // Between xMinYMid and meet\n                testDocument.replaceRange(\" \", {line: 2, ch: 59});\n                testEditor.setCursorPos({ line: 2, ch: 60});\n                var hintLint = expectHints(SVGCodeHints.hintProvider);\n                verifyHintsExcluded(hintLint, \"xMinYMin\");\n                verifyHintsExcluded(hintLint, \"meet\");\n            });\n\n            it(\"should NOT exclude current query from hints\", function () {\n                var hintList, hints;\n\n                // After xMinYMid\n                testDocument.replaceRange(\" xMax\", {line: 2, ch: 59});\n                testEditor.setCursorPos({line: 2, ch: 64});\n                hintList = expectHints(SVGCodeHints.hintProvider);\n                hints = extractHintList(hintList);\n                expect(hints.indexOf(\"xMaxYMax\")).not.toBe(-1);\n            });\n        });\n\n        describe(\"Color names and swatches\", function () {\n            it(\"should show color swatches\", function () {\n                // After color=\"\n                testEditor.setCursorPos({line: 4, ch: 117});\n                var hints = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hints, \"aliceblue\"); // first hint should be aliceblue\n                expect(hints[0].find(\".color-swatch\").length).toBe(1);\n                // CEF 2623 will output \"aliceblue\" whereas earlier versions give \"rgb(240, 248, 255)\",\n                // so we need this ugly hack to make sure this test passes on both\n                expect(hints[0].find(\".color-swatch\").css(\"backgroundColor\")).toMatch(/^rgb\\(240, 248, 255\\)$|aliceblue/);\n            });\n\n            it(\"should always include transparent and currentColor and they should not have a swatch, but class no-swatch-margin\", function () {\n                // After color='rent\n                testEditor.setCursorPos({line: 5, ch: 113});\n                var hints = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hints, \"currentColor\"); // first hint should be currentColor\n                expect(hints[0].find(\".color-swatch\").length).toBe(0); // no swatch for currentColor\n                expect(hints[2].find(\".color-swatch\").length).toBe(0); // no swatch for transparent\n                expect(hints[0].hasClass(\"no-swatch-margin\")).toBeTruthy(); // no-swatch-margin applied to currentColor\n                expect(hints[2].hasClass(\"no-swatch-margin\")).toBeTruthy(); // no-swatch-margin applied to transparent\n            });\n\n            it(\"should remove class no-swatch-margin from transparent if it's the only one in the list\", function () {\n                // After fill='transparent\n                testEditor.setCursorPos({line: 5, ch: 132});\n                var hints = expectHints(SVGCodeHints.hintProvider);\n                verifyHints(hints, \"transparent\");\n                expect(hints.length).toBe(1); // transparent should be the only hint\n                expect(hints[0].find(\".color-swatch\").length).toBe(0); // no swatch for transparent\n                expect(hints[0].hasClass(\"no-swatch-margin\")).toBeFalsy(); // no-swatch-margin not applied to transparent\n            });\n        });\n\n        describe(\"Tag Insertion\", function () {\n            it(\"should insert if query is empty\", function () {\n                // After < inside <g>\n                testDocument.replaceRange(\"<\", { line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 9});\n                selectHint(SVGCodeHints.hintProvider, \"a\");\n                expectTokenAt({line: 7, ch: 10}, \"a\", \"tag\");\n                expectCursorAt({line: 7, ch: 10});\n            });\n\n            it(\"should insert if query is one character long\", function () {\n                // After <d inside <g>\n                testDocument.replaceRange(\"<d\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 10});\n                selectHint(SVGCodeHints.hintProvider, \"defs\");\n                expectTokenAt({line: 7, ch: 11}, \"defs\", \"tag\");\n                expectCursorAt({line: 7, ch: 13});\n            });\n\n            it(\"should insert if query is complete\", function () {\n                // After <defs inside <g>\n                testDocument.replaceRange(\"<defs\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 13});\n                selectHint(SVGCodeHints.hintProvider, \"defs\");\n                expectTokenAt({line: 7, ch: 13}, \"defs\", \"tag\");\n                expectCursorAt({line: 7, ch: 13});\n            });\n        });\n\n        describe(\"Attribute Insertion\", function () {\n            it(\"should insert if query is empty\", function () {\n                // After <defs+space inside <g>\n                testDocument.replaceRange(\"<defs \", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 14});\n                selectHint(SVGCodeHints.hintProvider, \"alignment-baseline\");\n                expectTokenAt({line: 7, ch: 32}, \"alignment-baseline\", \"attribute\");\n                expectTokenAt({line: 7, ch: 33}, \"=\", null);\n                expectTokenAt({line: 7, ch: 35}, \"\\\"\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 34});\n            });\n\n            it(\"should insert if query is one character long\", function () {\n                // After <defs b inside <g>\n                testDocument.replaceRange(\"<defs b\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 15});\n                selectHint(SVGCodeHints.hintProvider, \"baseline-shift\");\n                expectTokenAt({line: 7, ch: 28}, \"baseline-shift\", \"attribute\");\n                expectTokenAt({line: 7, ch: 29}, \"=\", null);\n                expectTokenAt({line: 7, ch: 31}, \"\\\"\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 30});\n            });\n\n            it(\"should insert if query is complete\", function () {\n                // After <defs clip-path inside <g>\n                testDocument.replaceRange(\"<defs clip-path\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 23});\n                selectHint(SVGCodeHints.hintProvider, \"clip-path\");\n                expectTokenAt({line: 7, ch: 23}, \"clip-path\", \"attribute\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 26}, \"\\\"\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 25});\n            });\n\n            it(\"should NOT overide =\", function () {\n                // Between clip-path and \"inherit\" in <g>\n                testDocument.replaceRange(\"<defs clip-path=\\\"inherit\\\"\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 18});\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                selectHint(SVGCodeHints.hintProvider, \"clip-rule\");\n                expectTokenAt({line: 7, ch: 23}, \"clip-rule\", \"attribute\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectCursorAt({line: 7, ch: 23});\n            });\n        });\n\n        describe(\"Value Insertion\", function () {\n            it(\"should insert if = is typed after an attribute\", function () {\n                // after clip-path= inside <g>\n                testDocument.replaceRange(\"<defs clip-path=\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 24});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"\\\"inherit\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if =\\\" is typed after an attribute\", function () {\n                // After clip-path=\" inside <g>\n                testDocument.replaceRange(\"<defs clip-path=\\\"\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 25});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"\\\"inherit\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if =' is typed after an attribute\", function () {\n                // After =' inside <g>\n                testDocument.replaceRange(\"<defs clip-path='\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 25});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"'inherit'\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if first character is typed after =\\\"\", function () {\n                // After clip-path=\"i inside <g>\n                testDocument.replaceRange(\"<defs clip-path=\\\"i\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 26});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"\\\"inherit\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if first character is typed after ='\", function () {\n                // After clip-path='i inside <g>\n                testDocument.replaceRange(\"<defs clip-path='i\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 26});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"'inherit'\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if we are in middle of query after =\\\"\", function () {\n                // After clip-path=\"inhe inside <g>\n                testDocument.replaceRange(\"<defs clip-path=\\\"inhe\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 29});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"\\\"inherit\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if we are in middle of query after ='\", function () {\n                // After clip-path='inhe inside <g>\n                testDocument.replaceRange(\"<defs clip-path='inhe\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 29});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"'inherit'\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if we are in the end of value after ='\", function () {\n                // Before last ' in clip-path='inherit' inside <g>\n                testDocument.replaceRange(\"<defs clip-path='inherit'\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 32});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"'inherit'\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert if we are in the end of value after =\\\"\", function () {\n                // Before last \" in clip-path=\"inherit\" inside <g>\n                testDocument.replaceRange(\"<defs clip-path=\\\"inherit\\\"\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 32});\n                selectHint(SVGCodeHints.hintProvider, \"inherit\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 33}, \"\\\"inherit\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 33});\n            });\n\n            it(\"should insert value to left in a multiple options attribute\", function () {\n                // Between \"\" in transform=\"\" inside <g>\n                testDocument.replaceRange(\"<rect transform=\\\"\\\"\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 25});\n                selectHint(SVGCodeHints.hintProvider, \"matrix()\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 34}, \"\\\"matrix()\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 34});\n            });\n\n            it(\"should insert value to the right in a multiple options attribute\", function () {\n                // After \"matrix() \" inside <g>\n                testDocument.replaceRange(\"<rect transform=\\\"matrix() \\\"\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 34});\n                selectHint(SVGCodeHints.hintProvider, \"rotate()\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 34}, \"\\\"matrix() rotate()\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 43});\n            });\n\n            it(\"should insert value in the middle in a multiple options attribute\", function () {\n                // Between matrix() and rotate() in \"matrix()  rotate()\"\n                testDocument.replaceRange(\"<rect transform=\\\"matrix()  rotate()\\\"\", {line: 7, ch: 8});\n                testEditor.setCursorPos({line: 7, ch: 34});\n                selectHint(SVGCodeHints.hintProvider, \"scale()\");\n                expectTokenAt({line: 7, ch: 24}, \"=\", null);\n                expectTokenAt({line: 7, ch: 34}, \"\\\"matrix() scale() rotate()\\\"\", \"string\");\n                expectCursorAt({line: 7, ch: 41});\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/StaticServer/StaticServer.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var BaseServer           = brackets.getModule(\"LiveDevelopment/Servers/BaseServer\").BaseServer,\n        LiveDevelopmentUtils = brackets.getModule(\"LiveDevelopment/LiveDevelopmentUtils\"),\n        PreferencesManager   = brackets.getModule(\"preferences/PreferencesManager\"),\n        Strings              = brackets.getModule(\"strings\");\n\n\n    /**\n     * @private\n     *\n     * Preferences manager for this extension\n     */\n    var _prefs = PreferencesManager.getExtensionPrefs(\"staticserver\");\n\n    _prefs.definePreference(\"port\", \"number\", 0, {\n        description: Strings.DESCRIPTION_STATIC_SERVER_PORT\n    });\n\n    /**\n     * @constructor\n     * @extends {BaseServer}\n     * Live preview server that uses a built-in HTTP server to serve static\n     * and instrumented files.\n     *\n     * @param {!{baseUrl: string, root: string, pathResolver: function(string), nodeDomain: NodeDomain}} config\n     *    Configuration parameters for this server:\n     *        baseUrl        - Optional base URL (populated by the current project)\n     *        pathResolver   - Function to covert absolute native paths to project relative paths\n     *        root           - Native path to the project root (and base URL)\n     *        nodeDomain     - An initialized NodeDomain\n     */\n    function StaticServer(config) {\n        this._nodeDomain = config.nodeDomain;\n        this._onRequestFilter = this._onRequestFilter.bind(this);\n\n        BaseServer.call(this, config);\n    }\n\n    StaticServer.prototype = Object.create(BaseServer.prototype);\n    StaticServer.prototype.constructor = StaticServer;\n\n    /**\n     * Determines whether we can serve local file.\n     * @param {string} localPath A local path to file being served.\n     * @return {boolean} true for yes, otherwise false.\n     */\n    StaticServer.prototype.canServe = function (localPath) {\n        if (!this._nodeDomain.ready()) {\n            return false;\n        }\n\n        // If we can't transform the local path to a project relative path,\n        // the path cannot be served\n        if (localPath === this._pathResolver(localPath)) {\n            return false;\n        }\n\n        // Url ending in \"/\" implies default file, which is usually index.html.\n        // Return true to indicate that we can serve it.\n        if (localPath.match(/\\/$/)) {\n            return true;\n        }\n\n        // FUTURE: do a MIME Type lookup on file extension\n        return LiveDevelopmentUtils.isStaticHtmlFileExt(localPath);\n    };\n\n    /**\n     * @private\n     * Update the list of paths that fire \"request\" events\n     * @return {jQuery.Promise} Resolved by the StaticServer domain when the message is acknowledged.\n     */\n    StaticServer.prototype._updateRequestFilterPaths = function () {\n        var paths = Object.keys(this._liveDocuments);\n\n        return this._nodeDomain.exec(\"setRequestFilterPaths\", this._root, paths);\n    };\n\n    /**\n     * Gets the server details from the StaticServerDomain in node.\n     * The domain itself handles starting a server if necessary (when\n     * the staticServer.getServer command is called).\n     *\n     * @return {jQuery.Promise} A promise that resolves/rejects when\n     *     the server is ready/failed.\n     */\n    StaticServer.prototype.readyToServe = function () {\n        var self = this;\n        var deferred = new $.Deferred();\n\n        function sanitizePort(port) {\n            port = parseInt(port, 10);\n            port = (port && !isNaN(port) && port > 0 && port < 65536) ? port : 0;\n            return port;\n        }\n\n        function onSuccess(address) {\n            self._baseUrl = \"http://\" + address.address + \":\" + address.port + \"/\";\n            deferred.resolve();\n        }\n\n        function onFailure() {\n            self._baseUrl = \"\";\n            deferred.resolve();\n        }\n\n        var port = sanitizePort(_prefs.get(\"port\"));\n\n        this._nodeDomain.exec(\"getServer\", self._root, port)\n            .done(function (address) {\n\n                // If the port returned wasn't what was requested, then the preference has\n                // changed. Close the current server, and open a new one with the new port.\n                if (address.port !== port && port > 0) {\n                    return self._nodeDomain.exec(\"closeServer\", self._root)\n                        .done(function () {\n                            return self._nodeDomain.exec(\"getServer\", self._root, port)\n                                .done(onSuccess)\n                                .fail(onFailure);\n                        })\n                        .fail(onFailure);\n                }\n\n                onSuccess(address);\n            })\n            .fail(onFailure);\n\n        return deferred.promise();\n    };\n\n    /**\n     * See BaseServer#add. StaticServer ignores documents that do not have\n     * a setInstrumentationEnabled method. Updates request filters.\n     */\n    StaticServer.prototype.add = function (liveDocument) {\n        if (liveDocument.setInstrumentationEnabled) {\n            // enable instrumentation\n            liveDocument.setInstrumentationEnabled(true);\n        }\n\n        BaseServer.prototype.add.call(this, liveDocument);\n\n        // update the paths to watch\n        this._updateRequestFilterPaths();\n    };\n\n    /**\n     * See BaseServer#remove. Updates request filters.\n     */\n    StaticServer.prototype.remove = function (liveDocument) {\n        BaseServer.prototype.remove.call(this, liveDocument);\n\n        this._updateRequestFilterPaths();\n    };\n\n    /**\n     * See BaseServer#clear. Updates request filters.\n     */\n    StaticServer.prototype.clear = function () {\n        BaseServer.prototype.clear.call(this);\n\n        this._updateRequestFilterPaths();\n    };\n\n    /**\n     * @private\n     * Send HTTP response data back to the StaticServerSomain\n     */\n    StaticServer.prototype._send = function (location, response) {\n        this._nodeDomain.exec(\"writeFilteredResponse\", location.root, location.pathname, response);\n    };\n\n    /**\n     * @private\n     * Event handler for StaticServerDomain requestFilter event\n     * @param {jQuery.Event} event\n     * @param {{hostname: string, pathname: string, port: number, root: string, id: number}} request\n     */\n    StaticServer.prototype._onRequestFilter = function (event, request) {\n        var key             = request.location.pathname,\n            liveDocument    = this._liveDocuments[key],\n            response;\n\n        // send instrumented response or null to fallback to static file\n        if (liveDocument && liveDocument.getResponseData) {\n            response = liveDocument.getResponseData();\n        } else {\n            response = {};  // let server fall back on loading file off disk\n        }\n        response.id = request.id;\n\n        this._send(request.location, response);\n    };\n\n    /**\n     * See BaseServer#start. Starts listenting to StaticServerDomain events.\n     */\n    StaticServer.prototype.start = function () {\n        this._nodeDomain.on(\"requestFilter\", this._onRequestFilter);\n    };\n\n    /**\n     * See BaseServer#stop. Remove event handlers from StaticServerDomain.\n     */\n    StaticServer.prototype.stop = function () {\n        this._nodeDomain.off(\"requestFilter\", this._onRequestFilter);\n    };\n\n    module.exports = StaticServer;\n});\n"
  },
  {
    "path": "src/extensions/default/StaticServer/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit              = brackets.getModule(\"utils/AppInit\"),\n        ExtensionUtils       = brackets.getModule(\"utils/ExtensionUtils\"),\n        LiveDevServerManager = brackets.getModule(\"LiveDevelopment/LiveDevServerManager\"),\n        NodeDomain           = brackets.getModule(\"utils/NodeDomain\"),\n        ProjectManager       = brackets.getModule(\"project/ProjectManager\"),\n        StaticServer         = require(\"StaticServer\");\n\n    /**\n     * @private\n     * @type {string} fullPath of the StaticServerDomain implementation\n     */\n    var _domainPath = ExtensionUtils.getModulePath(module, \"node/StaticServerDomain\");\n\n    /**\n     * @private\n     * @type {NodeDomain}\n     */\n    var _nodeDomain = new NodeDomain(\"staticServer\", _domainPath);\n\n    /**\n     * @private\n     * @return {StaticServerProvider} The singleton StaticServerProvider initialized\n     * on app ready.\n     */\n    function _createStaticServer() {\n        var config = {\n            nodeDomain      : _nodeDomain,\n            pathResolver    : ProjectManager.makeProjectRelativeIfPossible,\n            root            : ProjectManager.getProjectRoot().fullPath\n        };\n\n        return new StaticServer(config);\n    }\n\n    AppInit.appReady(function () {\n        LiveDevServerManager.registerServer({ create: _createStaticServer }, 5);\n    });\n\n    // For unit tests only\n    exports._getStaticServerProvider = _createStaticServer;\n    exports._nodeDomain = _nodeDomain;\n});\n"
  },
  {
    "path": "src/extensions/default/StaticServer/node/StaticServerDomain.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nvar http     = require(\"http\"),\n    pathJoin = require(\"path\").join,\n    connect  = require(\"connect\"),\n    utils    = require(\"connect/lib/utils\"),\n    mime     = require(\"connect/node_modules/send/node_modules/mime\"),\n    parse    = utils.parseUrl;\n\nvar _domainManager;\n\nvar FILTER_REQUEST_TIMEOUT = 5000;\n\n/**\n * @private\n * @type {number}\n * Used to assign unique identifiers to each filter request\n */\nvar _filterRequestCounter = 0;\n\n/**\n * @private\n * @type {number}\n * Duration to wait before passing a filtered request to the static file server.\n */\nvar _filterRequestTimeout = FILTER_REQUEST_TIMEOUT;\n\n/**\n * When Chrome has a css stylesheet replaced over live development,\n * it re-checks any image urls in the new css stylesheet. If it has\n * to hit the server to check them, this is asynchronous, so it causes\n * two re-layouts of the webpage, which causes flickering. By setting\n * a max age of five seconds, Chrome won't bother to hit the server\n * on each keystroke. So, flickers will happen at most once every five\n * seconds.\n *\n * @const\n * @type {number}\n */\nvar STATIC_CACHE_MAX_AGE = 5000; // 5 seconds\n\n/**\n * @private\n * @type {Object.<string, http.Server>}\n * A map from root paths to server instances.\n */\nvar _servers = {};\n\n/**\n * @private\n * @type {Object.<string, {Object.<number, http.ServerResponse>}}\n * A map from a request identifier to its request/response mapping.\n */\nvar _requests = {};\n\n/**\n * @private\n * @type {Object.<string, {Object.<string>}}\n * A map from root paths to relative paths to rewrite\n */\nvar _rewritePaths = {};\n\nvar PATH_KEY_PREFIX = \"LiveDev_\";\n\n/**\n * @private\n * Removes trailing forward slash for the project root absolute path\n * @param {string} path Absolute path for a server\n * @returns {string}\n */\nfunction normalizeRootPath(path) {\n    return (path && path[path.length - 1] === \"/\") ? path.slice(0, -1) : path;\n}\n\n/**\n * @private\n * Generates a key based on a server's absolute path\n * @param {string} path Absolute path for a server\n * @returns {string}\n */\nfunction getPathKey(path) {\n    return PATH_KEY_PREFIX + normalizeRootPath(path);\n}\n\n/**\n * @private\n * Helper function to create a new server.\n * @param {string} path The absolute path that should be the document root\n * @param {function(?string, ?httpServer)} cb Callback function that receives\n *    an error (or null if there was no error) and the server (or null if there\n *    was an error).\n */\nfunction _createServer(path, port, createCompleteCallback) {\n    var server,\n        app,\n        address,\n        pathKey = getPathKey(path);\n\n    // create a new map for this server's requests\n    _requests[pathKey] = {};\n\n    function requestRoot(server, cb) {\n        address = server.address();\n\n        // Request the root file from the project in order to ensure that the\n        // server is actually initialized. If we don't do this, it seems like\n        // connect takes time to warm up the server.\n        var req = http.get(\n            {host: address.address, port: address.port},\n            function (res) {\n                cb(null, res);\n            }\n        );\n        req.on(\"error\", function (err) {\n            cb(err, null);\n        });\n    }\n\n    function rewrite(req, res, next) {\n        var location = {pathname: parse(req).pathname},\n            hasListener = _rewritePaths[pathKey] && _rewritePaths[pathKey][location.pathname],\n            requestId = _filterRequestCounter++,\n            timeoutId;\n\n        // ignore most HTTP methods and files that we're not watching\n        if ((\"GET\" !== req.method && \"HEAD\" !== req.method) || !hasListener) {\n            next();\n            return;\n        }\n\n        // pause the request and wait for listeners to possibly respond\n        var pause = utils.pause(req);\n\n        function resume(doNext) {\n            // delete the callback after it's used or we hit the timeout.\n            // if this path is requested again, a new callback is generated.\n            delete _requests[pathKey][requestId];\n\n            // pass request to next middleware\n            if (doNext) {\n                next();\n            }\n\n            pause.resume();\n        }\n\n        // map request pathname to response callback\n        _requests[pathKey][requestId] = function (resData) {\n            // clear timeout immediately when this callback is called\n            clearTimeout(timeoutId);\n\n            // response data is optional\n            if (resData.body) {\n                // HTTP headers\n                var type    = mime.lookup(location.pathname),\n                    charset = mime.charsets.lookup(type);\n\n                res.setHeader(\"Content-Type\", type + (charset ? \"; charset=\" + charset : \"\"));\n\n                // TODO (jasonsanjose): off-by-1 error here, why?\n                // Chrome seems to handle the request without issues when Content-Length is not specified\n                //res.setHeader(\"Content-Length\", Buffer.byteLength(resData.body /* TODO encoding? */));\n\n                // response body\n                res.end(resData.body);\n            }\n\n            // resume the HTTP ServerResponse, pass to next middleware if\n            // no response data was passed\n            resume(!resData.body);\n        };\n\n        location.hostname = address.address;\n        location.port = address.port;\n        location.root = path;\n\n        var request = {\n            headers:    req.headers,\n            location:   location,\n            id:         requestId\n        };\n\n        // dispatch request event\n        _domainManager.emitEvent(\"staticServer\", \"requestFilter\", [request]);\n\n        // set a timeout if custom responses are not returned\n        timeoutId = setTimeout(function () { resume(true); }, _filterRequestTimeout);\n    }\n\n    app = connect();\n    app.use(rewrite);\n    // JSLint complains if we use `connect.static` because static is a\n    // reserved word.\n    app.use(connect[\"static\"](path, { maxAge: STATIC_CACHE_MAX_AGE }));\n    app.use(connect.directory(path));\n\n    server = http.createServer(app);\n\n    // Once the server is listening then verify we can handle requests\n    // before calling the callback\n    server.on(\"listening\", function () {\n        requestRoot(\n            server,\n            function (err, res) {\n                if (err) {\n                    createCompleteCallback(\"Could not GET root after launching server\", null);\n                } else {\n                    createCompleteCallback(null, server);\n                }\n            }\n        );\n    });\n\n    // If the given port/address is in use then use a random port\n    server.on(\"error\", function (e) {\n        if (e.code === \"EADDRINUSE\") {\n            server.listen(0, \"127.0.0.1\");\n        } else {\n            throw e;\n        }\n    });\n\n    server.listen(port, \"127.0.0.1\");\n}\n\n/**\n * @private\n * Handler function for the staticServer.getServer command. If a server\n * already exists for the given path, returns that, otherwise starts a new\n * one.\n * @param {string} path The absolute path that should be the document root\n * @param {function(?string, ?{address: string, family: string,\n *    port: number})} cb Callback that should receive the address information\n *    for the server. First argument is the error string (or null if no error),\n *    second argument is the address object (or null if there was an error).\n *    The \"family\" property of the address indicates whether the address is,\n *    for example, IPv4, IPv6, or a UNIX socket.\n */\nfunction _cmdGetServer(path, port, cb) {\n    // Make sure the key doesn't conflict with some built-in property of Object.\n    var pathKey = getPathKey(path);\n    if (_servers[pathKey]) {\n        cb(null, _servers[pathKey].address());\n    } else {\n        _createServer(path, port, function (err, server) {\n            if (err) {\n                cb(err, null);\n            } else {\n                _servers[pathKey] = server;\n                _rewritePaths[pathKey] = {};\n                cb(null, server.address());\n            }\n        });\n    }\n}\n\n/**\n * @private\n * Handler function for the staticServer.closeServer command. If a server\n * exists for the given path, closes it, otherwise does nothing. Note that\n * this function doesn't wait for the actual socket to close, since the\n * server will actually wait for all client connections to close (which can\n * be awhile); but once it returns, you're guaranteed to get a different\n * server the next time you call getServer() on the same path.\n *\n * @param {string} path The absolute path whose server we should close.\n * @return {boolean} true if there was a server for that path, false otherwise\n */\nfunction _cmdCloseServer(path, cba) {\n    var pathKey = getPathKey(path);\n    if (_servers[pathKey]) {\n        var serverToClose = _servers[pathKey];\n        delete _servers[pathKey];\n        serverToClose.close();\n        return true;\n    }\n    return false;\n}\n\n/**\n * @private\n * Defines a set of paths from a server's root path to watch and fire \"request\" events for.\n *\n * @param {string} path The absolute path whose server we should watch\n * @param {Array.<string>} paths An array of root-relative paths to watch.\n *     Each path should begin with a forward slash \"/\".\n */\nfunction _cmdSetRequestFilterPaths(root, paths) {\n    var pathKey = getPathKey(root),\n        rewritePaths = {};\n\n    // reset list of filtered paths for each call to setRequestFilterPaths\n    _rewritePaths[pathKey] = rewritePaths;\n\n    paths.forEach(function (path) {\n        rewritePaths[path] = pathJoin(root, path);\n    });\n}\n\n/**\n * @private\n * Overrides the server response from static middleware with the provided\n * response data. This should be called only in response to a filtered request.\n *\n * @param {string} path The absolute path of the server\n * @param {string} root The relative path of the file beginning with a forward slash \"/\"\n * @param {!Object} resData Response data to use\n */\nfunction _cmdWriteFilteredResponse(root, path, resData) {\n    var pathKey  = getPathKey(root),\n        callback = _requests[pathKey][resData.id];\n\n    if (callback) {\n        callback(resData);\n    } else {\n        console.warn(\"writeFilteredResponse: Missing callback for %s. This command must only be called after a requestFilter event has fired for a path.\", pathJoin(root, path));\n    }\n}\n\n/**\n * @private\n * Unit tests only. Set, or reset, timeout value for filtered requests.\n *\n * @param {number=} timeout Duration to wait before passing a filtered request to the static file server.\n *     If omitted, timeout is reset to FILTER_REQUEST_TIMEOUT (5s).\n */\nfunction _cmdSetRequestFilterTimeout(timeout) {\n    timeout = (timeout === undefined) ? FILTER_REQUEST_TIMEOUT : timeout;\n    _filterRequestTimeout = timeout;\n}\n\n/**\n * Initializes the StaticServer domain with its commands.\n * @param {DomainManager} domainManager The DomainManager for the server\n */\nfunction init(domainManager) {\n    _domainManager = domainManager;\n\n    if (!domainManager.hasDomain(\"staticServer\")) {\n        domainManager.registerDomain(\"staticServer\", {major: 0, minor: 1});\n    }\n    _domainManager.registerCommand(\n        \"staticServer\",\n        \"_setRequestFilterTimeout\",\n        _cmdSetRequestFilterTimeout,\n        false,\n        \"Unit tests only. Set timeout value for filtered requests.\",\n        [{\n            name: \"timeout\",\n            type: \"number\",\n            description: \"Duration to wait before passing a filtered request to the static file server.\"\n        }],\n        []\n    );\n    _domainManager.registerCommand(\n        \"staticServer\",\n        \"getServer\",\n        _cmdGetServer,\n        true,\n        \"Starts or returns an existing server for the given path.\",\n        [\n            {\n                name: \"path\",\n                type: \"string\",\n                description: \"Absolute filesystem path for root of server.\"\n            },\n            {\n                name: \"port\",\n                type: \"number\",\n                description: \"Port number to use for HTTP server.  Pass zero to assign a random port.\"\n            }\n        ],\n        [{\n            name: \"address\",\n            type: \"{address: string, family: string, port: number}\",\n            description: \"hostname (stored in 'address' parameter), port, and socket type (stored in 'family' parameter) for the server. Currently, 'family' will always be 'IPv4'.\"\n        }]\n    );\n    _domainManager.registerCommand(\n        \"staticServer\",\n        \"closeServer\",\n        _cmdCloseServer,\n        false,\n        \"Closes the server for the given path.\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path for root of server\"\n        }],\n        [{\n            name: \"result\",\n            type: \"boolean\",\n            description: \"indicates whether a server was found for the specific path then closed\"\n        }]\n    );\n    _domainManager.registerCommand(\n        \"staticServer\",\n        \"setRequestFilterPaths\",\n        _cmdSetRequestFilterPaths,\n        false,\n        \"Defines a set of paths from a server's root path to watch and fire 'requestFilter' events for.\",\n        [\n            {\n                name: \"root\",\n                type: \"string\",\n                description: \"absolute filesystem path for root of server\"\n            },\n            {\n                name: \"paths\",\n                type: \"Array\",\n                description: \"path to notify\"\n            }\n        ],\n        []\n    );\n    _domainManager.registerCommand(\n        \"staticServer\",\n        \"writeFilteredResponse\",\n        _cmdWriteFilteredResponse,\n        false,\n        \"Overrides the server response from static middleware with the provided response data. This should be called only in response to a filtered request.\",\n        [\n            {\n                name: \"root\",\n                type: \"string\",\n                description: \"absolute filesystem path for root of server\"\n            },\n            {\n                name: \"path\",\n                type: \"string\",\n                description: \"path to rewrite\"\n            },\n            {\n                name: \"resData\",\n                type: \"{body: string, headers: Array}\",\n                description: \"TODO\"\n            }\n        ],\n        []\n    );\n    _domainManager.registerEvent(\n        \"staticServer\",\n        \"requestFilter\",\n        [{\n            name: \"location\",\n            type: \"{hostname: string, pathname: string, port: number, root: string: id: number}\",\n            description: \"request path\"\n        }]\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/extensions/default/StaticServer/unittest-files/folder1/index.txt",
    "content": "This is a file in folder 1."
  },
  {
    "path": "src/extensions/default/StaticServer/unittest-files/folder2/index.txt",
    "content": "This is a file in folder 2."
  },
  {
    "path": "src/extensions/default/StaticServer/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, waits, waitsFor, waitsForDone, runs, waitsForDone, spyOn */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var main            = require(\"main\"),\n        FileUtils       = brackets.getModule(\"file/FileUtils\"),\n        StaticServer    = require(\"StaticServer\");\n\n    var testFolder = FileUtils.getNativeModuleDirectoryPath(module) + \"/unittest-files\";\n\n    var CONNECT_TIMEOUT = 20000;\n\n    function makeBaseUrl(serverInfo) {\n        return \"http://\" + serverInfo.address + \":\" + serverInfo.port;\n    }\n\n    function getUrl(serverInfo, path) {\n        return $.get(makeBaseUrl(serverInfo) + path);\n    }\n\n    describe(\"StaticServer\", function () {\n\n        // Unit tests for the underlying node server.\n        describe(\"StaticServerDomain\", function () {\n            var nodeConnection,\n                nodeDomain,\n                logs;\n\n            beforeEach(function () {\n                logs = [];\n\n                if (!nodeConnection) {\n                    runs(function () {\n                        // wait for StaticServer/main to connect and load the StaticServerDomain\n                        nodeDomain = main._nodeDomain;\n                        nodeConnection = nodeDomain.connection;\n\n                        waitsFor(function () { return nodeDomain.ready(); }, \"NodeDomain connected\", CONNECT_TIMEOUT);\n                    });\n\n                    runs(function () {\n                        nodeConnection.on(\"base:log\", function (event, level, timestamp, message) {\n                            logs.push({level: level, message: message});\n                        });\n                    });\n                }\n            });\n\n            afterEach(function () {\n                runs(function () {\n                    // reset StaticServerDomain\n                    waitsForDone(nodeConnection.domains.staticServer._setRequestFilterTimeout(), \"restore request filter timeout\");\n                });\n            });\n\n            function onRequestFilter(callback) {\n                // only handle the first event\n                nodeConnection.one(\"staticServer:requestFilter\", function cb(event, request) {\n                    callback(request);\n                });\n            }\n\n            it(\"should start a static server on the given folder\", function () {\n                var serverInfo, path = testFolder + \"/folder1\";\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    expect(serverInfo.address).toBe(\"127.0.0.1\");\n                    expect(Number(serverInfo.port)).toBeGreaterThan(0);\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should start the server on the given port\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\";\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 54321)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n                runs(function () {\n                    expect(serverInfo.port).toBe(54321);\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should start a static server using a random port when the given port is already in use\", function () {\n                var serverInfo1, serverInfo2,\n                    path1 = testFolder + \"/folder1\", path2 = testFolder + \"/folder2\";\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path1, 54321)\n                        .done(function (info) {\n                            serverInfo1 = info;\n                        });\n                    nodeConnection.domains.staticServer.getServer(path2, 54321)\n                        .done(function (info) {\n                            serverInfo2 = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo1 && serverInfo2; }, \"waiting for static servers to start\");\n\n                runs(function () {\n                    expect(serverInfo1.port).toBe(54321);\n                    expect(serverInfo2.port).not.toBe(54321);\n                    expect(serverInfo2.port).toBeGreaterThan(0);\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path1),\n                                 \"waiting for static server 1 to close\");\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path2),\n                                 \"waiting for static server 2 to close\");\n                });\n            });\n\n            it(\"should serve the text of a file in the given folder\", function () {\n                var serverInfo, text, path = testFolder + \"/folder1\";\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        text = data;\n                    });\n                });\n\n                waitsFor(function () { return text; }, \"waiting for text from server\");\n\n                runs(function () {\n                    expect(text).toBe(\"This is a file in folder 1.\");\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should create separate servers for different folders\", function () {\n                var serverInfo1, serverInfo2,\n                    path1 = testFolder + \"/folder1\", path2 = testFolder + \"/folder2\";\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path1, 0)\n                        .done(function (info) {\n                            serverInfo1 = info;\n                        });\n                    nodeConnection.domains.staticServer.getServer(path2, 0)\n                        .done(function (info) {\n                            serverInfo2 = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo1 && serverInfo2; }, \"waiting for static servers to start\");\n\n                runs(function () {\n                    expect(serverInfo1.port).not.toBe(serverInfo2.port);\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path1),\n                                 \"waiting for static server 1 to close\");\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path2),\n                                 \"waiting for static server 2 to close\");\n                });\n            });\n\n            it(\"should keep a previous server alive after creating a new server\", function () {\n                var serverInfo1, serverInfo2,\n                    path1 = testFolder + \"/folder1\", path2 = testFolder + \"/folder2\",\n                    text1, text2;\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path1, 0)\n                        .done(function (info) {\n                            serverInfo1 = info;\n                        });\n                    nodeConnection.domains.staticServer.getServer(path2, 0)\n                        .done(function (info) {\n                            serverInfo2 = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo1 && serverInfo2; }, \"waiting for static servers to start\");\n\n                runs(function () {\n                    getUrl(serverInfo1, \"/index.txt\").done(function (data) {\n                        text1 = data;\n                    });\n                    getUrl(serverInfo2, \"/index.txt\").done(function (data) {\n                        text2 = data;\n                    });\n                });\n\n                waitsFor(function () { return text1 && text2; }, \"waiting for text from servers\");\n\n                runs(function () {\n                    expect(text1).toBe(\"This is a file in folder 1.\");\n                    expect(text2).toBe(\"This is a file in folder 2.\");\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path1),\n                                 \"waiting for static server 1 to close\");\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path2),\n                                 \"waiting for static server 2 to close\");\n                });\n            });\n\n            it(\"should trigger an event when a file path is requested\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\",\n                    text,\n                    location,\n                    elapsed,\n                    requestId,\n                    timeout = 500;\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    onRequestFilter(function (request) {\n                        location = request.location;\n                        requestId = request.id;\n                        // Do not call writeFilteredResponse in order to hit timeout\n                    });\n\n                    // listen for /index.txt requests\n                    waitsForDone(nodeConnection.domains.staticServer.setRequestFilterPaths(path, [\"/index.txt\"]));\n\n                    // set a custom timeout\n                    waitsForDone(nodeConnection.domains.staticServer._setRequestFilterTimeout(timeout));\n                });\n\n                runs(function () {\n                    // it should take longer than the StaticServerDomain timeout to get a response\n                    elapsed = new Date();\n\n                    // request /index.txt\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        elapsed = new Date() - elapsed;\n                        text = data;\n                    });\n                });\n\n                waitsFor(function () { return location && text; }, \"waiting for request event to fire\");\n\n                runs(function () {\n                    expect(requestId).toBeGreaterThan(-1);\n                    expect(location.pathname).toBe(\"/index.txt\");\n                    expect(text).toBe(\"This is a file in folder 1.\");\n\n                    // we should hit the timeout since we filtered this path and did not respond\n                    expect(elapsed).toBeGreaterThan(timeout);\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should send static file contents after canceling a filter request\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\",\n                    text,\n                    location,\n                    requestId;\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    // listen for request event\n                    onRequestFilter(function (request) {\n                        location = request.location;\n                        requestId = request.id;\n                        nodeConnection.domains.staticServer.writeFilteredResponse(request.root, request.pathname, {id: requestId});\n\n                        // a second call to send does nothing\n                        nodeConnection.domains.staticServer.writeFilteredResponse(request.root, request.pathname, {id : requestId, body: \"custom response\"});\n                    });\n\n                    // listen for /index.txt requests\n                    waitsForDone(nodeConnection.domains.staticServer.setRequestFilterPaths(path, [\"/index.txt\"]));\n                });\n\n                runs(function () {\n                    // request /index.txt\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        text = data;\n                    });\n                });\n\n                waitsFor(function () { return location && text; }, \"waiting for request event to fire\");\n\n                runs(function () {\n                    expect(requestId).toBeGreaterThan(-1);\n                    expect(location.pathname).toBe(\"/index.txt\");\n                    expect(text).toBe(\"This is a file in folder 1.\");\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should override the static file server response with a new response body\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\",\n                    text,\n                    location,\n                    requestId;\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    // listen for request event\n                    onRequestFilter(function (request) {\n                        location = request.location;\n                        requestId = request.id;\n                        nodeConnection.domains.staticServer.writeFilteredResponse(location.root, location.pathname, {id: requestId, body: \"custom response\"});\n                    });\n\n                    // listen for /index.txt requests\n                    waitsForDone(nodeConnection.domains.staticServer.setRequestFilterPaths(path, [\"/index.txt\"]));\n                });\n\n                runs(function () {\n                    // request /index.txt\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        text = data;\n                    });\n                });\n\n                waitsFor(function () { return location && text; }, \"waiting for text from server\");\n\n                runs(function () {\n                    expect(requestId).toBeGreaterThan(-1);\n                    expect(location.pathname).toBe(\"/index.txt\");\n                    expect(text).toBe(\"custom response\");\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should ignore multiple responses for the same request\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\",\n                    text,\n                    location,\n                    requestId;\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    // listen for request event\n                    onRequestFilter(function (request) {\n                        location = request.location;\n                        requestId = request.id;\n\n                        nodeConnection.domains.staticServer.writeFilteredResponse(location.root, location.pathname, {id: requestId, body: \"good response\"});\n                        nodeConnection.domains.staticServer.writeFilteredResponse(location.root, location.pathname, {id: requestId, body: \"bad response\"});\n                    });\n\n                    // listen for /index.txt requests\n                    waitsForDone(nodeConnection.domains.staticServer.setRequestFilterPaths(path, [\"/index.txt\"]));\n                });\n\n                runs(function () {\n                    // request /index.txt\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        text = data;\n                    });\n                });\n\n                waitsFor(\n                    function () { return location && text && (logs.length > 0); },\n                    \"waiting for text from server and warning in log\"\n                );\n\n                runs(function () {\n                    expect(logs.length).toBe(1);\n                    expect(logs[0].level).toBe(\"warn\");\n                    expect(logs[0].message.indexOf(\"writeFilteredResponse\")).toBe(0);\n\n                    expect(requestId).toBeGreaterThan(-1);\n                    expect(location.pathname).toBe(\"/index.txt\");\n                    expect(text).toBe(\"good response\");\n\n                    // cleanup\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should log a warning when writing to a non-existant request\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\",\n                    text,\n                    requestId = -1;\n\n                spyOn(console, \"warn\").andCallThrough();\n\n                onRequestFilter(function (request) {\n                    requestId = request.id;\n                });\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    // write response before the request\n                    waitsForDone(nodeConnection.domains.staticServer.writeFilteredResponse(path, \"/index.txt\", {id: requestId, body: \"custom response\"}));\n                });\n\n                runs(function () {\n                    // request /index.txt\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        text = data;\n                    });\n                });\n\n                runs(function () {\n                    // write response after the request\n                    waitsForDone(nodeConnection.domains.staticServer.writeFilteredResponse(path, \"/index.txt\", {id: requestId, body: \"custom response\"}));\n                });\n\n                waitsFor(function () { return text; }, \"waiting for text from server\");\n\n                runs(function () {\n                    // verify console warning\n                    expect(logs.length).toBe(2);\n\n                    logs.forEach(function (log) {\n                        expect(log.level).toBe(\"warn\");\n                        expect(log.message.indexOf(\"writeFilteredResponse\")).toBe(0);\n                    });\n\n                    // verify original file content\n                    expect(text).toBe(\"This is a file in folder 1.\");\n                    expect(requestId).toBe(-1);\n\n                    // cleanup\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n\n            it(\"should should require paths to be filtered for events to fire\", function () {\n                var serverInfo,\n                    path = testFolder + \"/folder1\",\n                    text = null,\n                    location = null,\n                    requestId = -1,\n                    elapsed,\n                    timeout = 500;\n\n                runs(function () {\n                    nodeConnection.domains.staticServer.getServer(path, 0)\n                        .done(function (info) {\n                            serverInfo = info;\n                        });\n                });\n\n                waitsFor(function () { return serverInfo; }, \"waiting for static server to start\");\n\n                runs(function () {\n                    onRequestFilter(function (request) {\n                        location = request.location;\n                        requestId = request.id;\n                    });\n\n                    // set a custom timeout\n                    waitsForDone(nodeConnection.domains.staticServer._setRequestFilterTimeout(timeout));\n                });\n\n                runs(function () {\n                    // it should take less than the 500ms timeout to get a response\n                    elapsed = new Date();\n\n                    // request /index.txt\n                    getUrl(serverInfo, \"/index.txt\").done(function (data) {\n                        elapsed = new Date() - elapsed;\n                        text = data;\n                    });\n                });\n\n                waits(timeout);\n\n                runs(function () {\n                    // requestFilter should never fire, location is never returned\n                    expect(location).toBeNull();\n\n                    // original content\n                    expect(text).toBe(\"This is a file in folder 1.\");\n\n                    // server should respond with original content before the timeout lapses\n                    expect(elapsed).toBeLessThan(timeout);\n                    expect(requestId).toBe(-1);\n\n                    waitsForDone(nodeConnection.domains.staticServer.closeServer(path),\n                                 \"waiting for static server to close\");\n                });\n            });\n        });\n\n        // Unit tests for the StaticServerProvider that wraps the underlying node server.\n        describe(\"StaticServer\", function () {\n            var projectPath         = testFolder + \"/\",\n                mockNodeDomain      = { ready: function () { return true; } },\n                pathResolver        = function (path) {\n                    if (path.indexOf(projectPath) === 0) {\n                        return path.slice(projectPath.length);\n                    }\n\n                    return path;\n                },\n                config              = {\n                    baseUrl: \"http://localhost/\",\n                    nodeDomain: mockNodeDomain,\n                    pathResolver: pathResolver,\n                    root: projectPath,\n                    port: 0\n                };\n\n            it(\"should translate local paths to server paths\", function () {\n                var outsidePath     = testFolder.substr(0, testFolder.lastIndexOf(\"/\") + 1),\n                    fileProtocol    = (brackets.platform === \"win\") ? \"file:///\" : \"file://\",\n                    fileRelPath     = \"subdir/index.html\",\n                    file1Path       = projectPath + fileRelPath,\n                    file2Path       = outsidePath + fileRelPath,\n                    file2FileUrl    = encodeURI(fileProtocol + outsidePath + fileRelPath),\n                    file1ServerUrl  = config.baseUrl + encodeURI(fileRelPath),\n                    server          = new StaticServer(config);\n\n                // Should use server url with base url\n                expect(server.pathToUrl(file1Path)).toBe(file1ServerUrl);\n                expect(server.urlToPath(file1ServerUrl)).toBe(file1Path);\n\n                // File outside project should still use file url\n                expect(server.pathToUrl(file2Path)).toBe(null);\n                expect(server.urlToPath(file2FileUrl)).toBe(null);\n            });\n\n            it(\"should only serve html files that are in the project file hierarchy\", function () {\n                var server = new StaticServer(config);\n\n                // should not serve files outside project hierarchy\n                expect(server.canServe(\"/foo.html\")).toBe(false);\n\n                // should not serve non-HTML files inside hierarchy\n                expect(server.canServe(testFolder + \"/foo.jpg\")).toBe(false);\n\n                // should serve .htm files inside hierarchy\n                expect(server.canServe(testFolder + \"/foo.htm\")).toBe(true);\n\n                // should serve .html files inside hierarchy\n                expect(server.canServe(testFolder + \"/foo.html\")).toBe(true);\n\n                // should serve .HTML files inside hierarchy\n                expect(server.canServe(testFolder + \"/foo.HTML\")).toBe(true);\n\n                // should serve root of hierarchy\n                expect(server.canServe(testFolder + \"/\")).toBe(true);\n            });\n\n            it(\"should decline serving if not connected to node\", function () {\n                // mock NodeDomain state to be disconnected\n                config.nodeDomain = { ready: function () { return false; } };\n\n                var server = new StaticServer(config);\n\n                expect(server.canServe(testFolder + \"foo.html\")).toBe(false);\n            });\n\n        });\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/data.json",
    "content": "{\n    \"htmlAttrs\": {\n        \"href\":         { \"attribOption\": [] },\n        \"poster\":       { \"attribOption\": [] },\n        \"src\":          { \"attribOption\": [] }\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var AppInit             = brackets.getModule(\"utils/AppInit\"),\n        CodeHintManager     = brackets.getModule(\"editor/CodeHintManager\"),\n        CSSUtils            = brackets.getModule(\"language/CSSUtils\"),\n        FileSystem          = brackets.getModule(\"filesystem/FileSystem\"),\n        FileUtils           = brackets.getModule(\"file/FileUtils\"),\n        HTMLUtils           = brackets.getModule(\"language/HTMLUtils\"),\n        PreferencesManager  = brackets.getModule(\"preferences/PreferencesManager\"),\n        ProjectManager      = brackets.getModule(\"project/ProjectManager\"),\n        StringUtils         = brackets.getModule(\"utils/StringUtils\"),\n        PathUtils           = brackets.getModule(\"thirdparty/path-utils/path-utils\"),\n        Strings             = brackets.getModule(\"strings\"),\n        Data                = require(\"text!data.json\"),\n\n        urlHints,\n        data,\n        htmlAttrs,\n        styleModes      = [\"css\", \"text/x-less\", \"text/x-scss\"];\n\n\n    PreferencesManager.definePreference(\"codehint.UrlCodeHints\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_URL_CODE_HINTS\n    });\n\n    /**\n     * @constructor\n     */\n    function UrlCodeHints() {}\n\n    /**\n     * Helper function to create a list of urls to existing files based on the query.\n     * @param {{queryStr: string}} query -- a query object, used to filter the code hints\n     *\n     * @return {Array.<string>|$.Deferred} The (possibly deferred) hints.\n     */\n    UrlCodeHints.prototype._getUrlList = function (query) {\n        var directory,\n            doc,\n            docDir,\n            queryDir = \"\",\n            queryUrl,\n            result = [],\n            self,\n            targetDir,\n            unfiltered = [];\n\n        doc = this.editor && this.editor.document;\n        if (!doc || !doc.file) {\n            return result;\n        }\n\n        docDir = FileUtils.getDirectoryPath(doc.file.fullPath);\n\n        // get relative path from query string\n        queryUrl = PathUtils.parseUrl(query.queryStr);\n        if (queryUrl) {\n            queryDir = queryUrl.directory;\n        }\n\n        // build target folder path\n        if (queryDir.length > 0 && queryDir[0] === \"/\") {\n            // site-root relative path\n            targetDir = ProjectManager.getProjectRoot().fullPath +\n                        decodeURI(queryDir).substring(1);\n        } else {\n            // page relative path\n            targetDir = docDir + decodeURI(queryDir);\n        }\n\n        // Get list of files from target folder. Getting the file/folder info is an\n        // asynch operation, so it works like this:\n        //\n        // The initial pass initiates the asynchronous retrieval of data and returns an\n        // empty list, so no code hints are displayed. In the async callback, the code\n        // hints and the original query are stored in a cache, and then the process to\n        // show code hints is re-initiated.\n        //\n        // During the next pass, there should now be code hints cached from the initial\n        // pass, but user may have typed while file/folder info was being retrieved from\n        // disk, so we need to make sure code hints still apply to current query. If so,\n        // display them, otherwise, clear cache and start over.\n        //\n        // As user types within a folder, the same unfiltered file/folder list is still\n        // valid and re-used from cache. Filtering based on user input is done outside\n        // of this method. When user moves to a new folder, then the cache is deleted,\n        // and file/folder info for new folder is then retrieved.\n\n        if (this.cachedHints) {\n            // url hints have been cached, so determine if they're stale\n            if (!this.cachedHints.query ||\n                    this.cachedHints.query.tag !== query.tag ||\n                    this.cachedHints.query.attrName !== query.attrName ||\n                    this.cachedHints.queryDir !== queryDir ||\n                    this.cachedHints.docDir !== docDir) {\n\n                // delete stale cache\n                this.cachedHints = null;\n            }\n        }\n\n        if (this.cachedHints) {\n            // use cached hints\n            unfiltered = this.cachedHints.unfiltered;\n\n        } else {\n            directory = FileSystem.getDirectoryForPath(targetDir);\n            self = this;\n\n            if (self.cachedHints && self.cachedHints.deferred) {\n                self.cachedHints.deferred.reject();\n            }\n            // create empty object so we can detect \"waiting\" state\n            self.cachedHints = {};\n            self.cachedHints.deferred = $.Deferred();\n            self.cachedHints.unfiltered = [];\n\n            directory.getContents(function (err, contents) {\n                var currentDeferred, entryStr, syncResults;\n\n                if (!err) {\n                    contents.forEach(function (entry) {\n                        if (ProjectManager.shouldShow(entry)) {\n                            // convert to doc relative path\n                            entryStr = queryDir + entry._name;\n                            if (entry._isDirectory) {\n                                entryStr += \"/\";\n                            }\n\n                            // code hints show the unencoded string so the\n                            // choices are easier to read.  The encoded string\n                            // will still be inserted into the editor.\n                            unfiltered.push(entryStr);\n                        }\n                    });\n\n                    self.cachedHints.unfiltered = unfiltered;\n                    self.cachedHints.query      = query;\n                    self.cachedHints.queryDir   = queryDir;\n                    self.cachedHints.docDir     = docDir;\n\n                    if (self.cachedHints.deferred.state() !== \"rejected\") {\n                        currentDeferred = self.cachedHints.deferred;\n\n                        // Since we've cached the results, the next call to _getUrlList should be synchronous.\n                        // If it isn't, we've got a problem and should reject both the current deferred\n                        // and any new deferred that got created on the call.\n                        syncResults = self._getUrlList(query);\n                        if (syncResults instanceof Array) {\n                            currentDeferred.resolveWith(self, [syncResults]);\n                        } else {\n                            if (currentDeferred && currentDeferred.state() === \"pending\") {\n                                currentDeferred.reject();\n                            }\n\n                            if (self.cachedHints.deferred &&\n                                    self.cachedHints.deferred.state() === \"pending\") {\n                                self.cachedHints.deferred.reject();\n                                self.cachedHints.deferred = null;\n                            }\n                        }\n                    }\n                }\n            });\n\n            return self.cachedHints.deferred;\n        }\n\n        // build list\n\n        // without these entries, typing \"../\" will not display entries for containing folder\n        if (queryUrl.filename === \".\") {\n            result.push(queryDir + \".\");\n        } else if (queryUrl.filename === \"..\") {\n            result.push(queryDir + \"..\");\n        }\n\n        // add file/folder entries\n        unfiltered.forEach(function (item) {\n            result.push(item);\n        });\n\n        // TODO: filter by desired file type based on tag, type attr, etc.\n\n        // TODO: add list item to top of list to popup modal File Finder dialog\n        // New string: \"Browse...\" or \"Choose a File...\"\n        // Command: Commands.FILE_OPEN\n\n        return result;\n    };\n\n    /**\n     * Helper function that determines the possible value hints for a given html tag/attribute name pair\n     *\n     * @param {{queryStr: string}} query\n     * The current query\n     *\n     * @return {{hints: (Array.<string>|$.Deferred), sortFunc: ?function(string, string): number}}\n     * The (possibly deferred) hints and the sort function to use on thise hints.\n     */\n    UrlCodeHints.prototype._getUrlHints = function (query) {\n        var hints = [],\n            sortFunc;\n\n        // Do not show hints after \"?\" in url\n        if (query.queryStr.indexOf(\"?\") === -1) {\n\n            // Default behavior for url hints is do not close on select.\n            this.closeOnSelect = false;\n            hints = this._getUrlList(query);\n            sortFunc = StringUtils.urlSort;\n        }\n\n        return { hints: hints, sortFunc: sortFunc };\n    };\n\n    /**\n     * Determines whether url hints are available in the current editor\n     * context.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non-null,\n     * whether it is appropriate to do so.\n     */\n    UrlCodeHints.prototype.hasHints = function (editor, implicitChar) {\n        var mode = editor.getModeForSelection();\n        if (mode === \"html\") {\n            return this.hasHtmlHints(editor, implicitChar);\n        } else if (styleModes.indexOf(mode) > -1) {\n            return this.hasCssHints(editor, implicitChar);\n        }\n\n        return false;\n    };\n\n    /**\n     * Helper function for hasHints() for CSS.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non-null,\n     * whether it is appropriate to do so.\n     */\n    UrlCodeHints.prototype.hasCssHints = function (editor, implicitChar) {\n        this.editor = editor;\n        var cursor = this.editor.getCursorPos();\n\n        this.info = CSSUtils.getInfoAtPos(editor, cursor);\n\n        if (this.info.context !== CSSUtils.PROP_VALUE && this.info.context !== CSSUtils.IMPORT_URL) {\n            return false;\n        }\n\n        // collect existing value\n        var i,\n            val = \"\";\n\n        for (i = 0; i <= this.info.index && i < this.info.values.length; i++) {\n            if (i < this.info.index) {\n                val += this.info.values[i];\n            } else {\n                val += this.info.values[i].substring(0, this.info.offset);\n            }\n        }\n\n        // starts with \"url(\" ?\n        if (val.match(/^\\s*url\\(/i)) {\n            return true;\n        }\n\n        return false;\n    };\n\n    /**\n     * Helper function for hasHints() for HTML.\n     *\n     * @param {Editor} editor\n     * A non-null editor object for the active window.\n     *\n     * @param {string} implicitChar\n     * Either null, if the hinting request was explicit, or a single character\n     * that represents the last insertion and that indicates an implicit\n     * hinting request.\n     *\n     * @return {boolean}\n     * Determines whether the current provider is able to provide hints for\n     * the given editor context and, in case implicitChar is non-null,\n     * whether it is appropriate to do so.\n     */\n    UrlCodeHints.prototype.hasHtmlHints = function (editor, implicitChar) {\n        var tagInfo,\n            query,\n            tokenType;\n\n        this.editor = editor;\n\n        tagInfo = HTMLUtils.getTagInfo(editor, editor.getCursorPos());\n        query = null;\n        tokenType = tagInfo.position.tokenType;\n\n        if (tokenType === HTMLUtils.ATTR_VALUE) {\n\n            // Verify that attribute name has hintable values\n            if (htmlAttrs[tagInfo.attr.name]) {\n\n                if (tagInfo.position.offset >= 0) {\n                    query = tagInfo.attr.value.slice(0, tagInfo.position.offset);\n                } else {\n                    // We get negative offset for a quoted attribute value with some leading whitespaces\n                    // as in <a rel= \"rtl\" where the cursor is just to the right of the \"=\".\n                    // So just set the queryStr to an empty string.\n                    query = \"\";\n                }\n\n                var hintsAndSortFunc = this._getUrlHints({queryStr: query}),\n                    hints = hintsAndSortFunc.hints;\n\n                if (hints instanceof Array) {\n                    // If we got synchronous hints, check if we have something we'll actually use\n                    var i, foundPrefix = false;\n                    query = query.toLowerCase();\n                    for (i = 0; i < hints.length; i++) {\n                        if (hints[i].toLowerCase().indexOf(query) === 0) {\n                            foundPrefix = true;\n                            break;\n                        }\n                    }\n\n                    if (!foundPrefix) {\n                        query = null;\n                    }\n                }\n            }\n        }\n\n        return (query !== null);\n    };\n\n    /**\n     * Returns a list of available url hints, if possible, for the current\n     * editor context.\n     *\n     * @return {jQuery.Deferred|{\n     *              hints: Array.<string|jQueryObject>,\n     *              match: string,\n     *              selectInitial: boolean,\n     *              handleWideResults: boolean}}\n     * Null if the provider wishes to end the hinting session. Otherwise, a\n     * response object that provides\n     * 1. a sorted array hints that consists of strings\n     * 2. a string match that is used by the manager to emphasize matching\n     *    substrings when rendering the hint list\n     * 3. a boolean that indicates whether the first result, if one exists, should be\n     *    selected by default in the hint list window.\n     * 4. handleWideResults, a boolean (or undefined) that indicates whether\n     *    to allow result string to stretch width of display.\n     */\n    UrlCodeHints.prototype.getHints = function (key) {\n        var mode = this.editor.getModeForSelection(),\n            cursor = this.editor.getCursorPos(),\n            filter = \"\",\n            hints = [],\n            sortFunc,\n            query = { queryStr: \"\" },\n            result = [];\n\n        if (mode === \"html\") {\n            var tagInfo = HTMLUtils.getTagInfo(this.editor, cursor),\n                tokenType = tagInfo.position.tokenType;\n\n            if (tokenType !== HTMLUtils.ATTR_VALUE || !htmlAttrs[tagInfo.attr.name]) {\n                return null;\n            }\n\n            if (tagInfo.position.offset >= 0) {\n                query.queryStr = tagInfo.attr.value.slice(0, tagInfo.position.offset);\n            }\n            this.info = tagInfo;\n\n        } else if (styleModes.indexOf(mode) > -1) {\n            this.info = CSSUtils.getInfoAtPos(this.editor, cursor);\n\n            var context = this.info.context;\n            if (context !== CSSUtils.PROP_VALUE && context !== CSSUtils.IMPORT_URL) {\n                return null;\n            }\n\n            // Cursor is in an existing property value or partially typed value\n            if (this.info.index !== -1) {\n\n                // Collect value up to (item) index/(char) offset\n                var i, val = \"\";\n                for (i = 0; i < this.info.index; i++) {\n                    val += this.info.values[i];\n                }\n                // index may exceed length of array for multiple-value case\n                if (this.info.index < this.info.values.length) {\n                    val += this.info.values[this.info.index].substr(0, this.info.offset);\n                }\n\n                // Strip \"url(\"\n                val = val.replace(/^\\s*url\\(/i, \"\");\n\n                // Keep track of leading whitespace and strip it\n                var matchWhitespace = val.match(/^\\s*/);\n                if (matchWhitespace) {\n                    this.info.leadingWhitespace = matchWhitespace[0];\n                    val = val.substring(matchWhitespace[0].length);\n                } else {\n                    this.info.leadingWhitespace = null;\n                }\n\n                // Keep track of opening quote and strip it\n                if (val.match(/^[\"']/)) {\n                    this.info.openingQuote = val[0];\n                    val = val.substring(1);\n                } else {\n                    this.info.openingQuote = null;\n                }\n\n                query.queryStr = val;\n            }\n\n        } else {\n            return null;\n        }\n\n        if (query.queryStr !== null) {\n            filter = query.queryStr;\n            var hintsAndSortFunc = this._getUrlHints(query);\n            hints = hintsAndSortFunc.hints;\n            sortFunc = hintsAndSortFunc.sortFunc;\n        }\n        this.info.filter = filter;\n\n        if (hints instanceof Array && hints.length) {\n            // Array was returned\n            var lowerCaseFilter = filter.toLowerCase();\n            console.assert(!result.length);\n            result = $.map(hints, function (item) {\n                if (item.toLowerCase().indexOf(lowerCaseFilter) === 0) {\n                    return item;\n                }\n            }).sort(sortFunc);\n\n            return {\n                hints: result,\n                match: query.queryStr,\n                selectInitial: true,\n                handleWideResults: false\n            };\n\n        } else if (hints instanceof Object && hints.hasOwnProperty(\"done\")) {\n            // Deferred hints were returned\n            var deferred = $.Deferred();\n            hints.done(function (asyncHints) {\n                var lowerCaseFilter = filter.toLowerCase();\n                result = $.map(asyncHints, function (item) {\n                    if (item.toLowerCase().indexOf(lowerCaseFilter) === 0) {\n                        return item;\n                    }\n                }).sort(sortFunc);\n\n                deferred.resolveWith(this, [{\n                    hints: result,\n                    match: query.queryStr,\n                    selectInitial: true,\n                    handleWideResults: false\n                }]);\n            });\n\n            return deferred;\n        }\n\n        return null;\n    };\n\n    /**\n     * Inserts a given url hint into the current editor context.\n     *\n     * @param {jQuery.Object} completion\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    UrlCodeHints.prototype.insertHint = function (completion) {\n        var mode = this.editor.getModeForSelection();\n\n        // Encode the string just prior to inserting the hint into the editor\n        completion = encodeURI(completion);\n\n        if (mode === \"html\") {\n            return this.insertHtmlHint(completion);\n        } else if (styleModes.indexOf(mode) > -1) {\n            return this.insertCssHint(completion);\n        }\n\n        return false;\n    };\n\n    /**\n     * Get distance between 2 positions.\n     *\n     * Assumption: pos2 >= pos1\n     *\n     * Note that this function is designed to work on CSSUtils info.values array,\n     * so this could be made a method if that is converted to an object.\n     *\n     * @param {Array.<string>}  array  - strings to be searched\n     * @param {{index: number, offset: number}} pos1 - starting index/offset in index string\n     * @param {{index: number, offset: number}} pos2 - ending index/offset in index string\n     *\n     * @return {number}\n     * Number of characters between 2 positions\n     */\n    UrlCodeHints.prototype.getCharOffset = function (array, pos1, pos2) {\n        var i, count = 0;\n\n        if (pos1.index === pos2.index) {\n            return (pos2.offset >= pos1.offset) ? (pos2.offset - pos1.offset) : 0;\n        } else if (pos1.index < pos2.index) {\n            if (pos1.index < 0 || pos1.index >= array.length || pos2.index < 0 || pos2.index >= array.length) {\n                return 0;\n            }\n\n            for (i = pos1.index; i <= pos2.index; i++) {\n                if (i === pos1.index) {\n                    count += (array[i].length - pos1.offset);\n                } else if (i === pos2.index) {\n                    count += pos2.offset;\n                } else {\n                    count += array[i].length;\n                }\n            }\n        }\n\n        return count;\n    };\n\n    /**\n     * Finds next position in array of specified char.\n     *\n     * Note that this function is designed to work on CSSUtils info.values array,\n     * so this could be made a method if that is converted to an object.\n     *\n     * @param {Array}  array - strings to be searched\n     * @param {string} ch    - char to search for\n     * @param {{index: number, offset: number}} pos - starting index/offset in index string\n     *\n     * @return {{index: number, offset: number}}\n     * Index of array, and offset in string where char found.\n     */\n    UrlCodeHints.prototype.findNextPosInArray = function (array, ch, pos) {\n        var i, o, searchOffset;\n        for (i = pos.index; i < array.length; i++) {\n            // Only use offset on index, then offset of 0 after that\n            searchOffset = (i === pos.index) ? pos.offset : 0;\n            o = array[i].indexOf(ch, searchOffset);\n\n            if (o !== -1) {\n                return { index: i, offset: o };\n            }\n        }\n        return { index: -1, offset: -1 };\n    };\n\n    /**\n     * Inserts a given css url hint into the current editor context.\n     *\n     * @param {jQuery.Object} completion\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    UrlCodeHints.prototype.insertCssHint = function (completion) {\n        var cursor = this.editor.getCursorPos(),\n            start  = { line: cursor.line, ch: cursor.ch },\n            end    = { line: cursor.line, ch: cursor.ch };\n\n        var hasClosingQuote = false,\n            hasClosingParen = false,\n            insertText      = completion,\n            moveLen         = 0,\n            closingPos      = { index: -1, offset: -1 },\n            searchResult    = { index: -1, offset: -1 };\n\n        if (this.info.context !== CSSUtils.PROP_VALUE && this.info.context !== CSSUtils.IMPORT_URL) {\n            return false;\n        }\n\n        // Special handling for URL hinting -- if the completion is a file name\n        // and not a folder, then close the code hint list.\n        if (!this.closeOnSelect && completion.match(/\\/$/) === null) {\n            this.closeOnSelect = true;\n        }\n\n        // Look for optional closing quote\n        if (this.info.openingQuote) {\n            closingPos = this.findNextPosInArray(this.info.values, this.info.openingQuote, this.info);\n            hasClosingQuote = (closingPos.index !== -1);\n        }\n\n        // Look for closing paren\n        if (hasClosingQuote) {\n            searchResult = this.findNextPosInArray(this.info.values, \")\", closingPos);\n            hasClosingParen = (searchResult.index !== -1);\n        } else {\n            // index may exceed length of array for multiple-value case\n            closingPos = this.findNextPosInArray(this.info.values, \")\", this.info);\n            hasClosingParen = (closingPos.index !== -1);\n        }\n\n        // Insert folder names, but replace file names, so if a file is selected\n        // (i.e. closeOnSelect === true), then adjust insert char positions to\n        // replace existing value, if there is a closing paren\n        if (this.closeOnSelect) {\n            if (closingPos.index !== -1) {\n                end.ch += this.getCharOffset(this.info.values, this.info, closingPos);\n            }\n        } else {\n            // If next char is \"/\", then overwrite it since we're inserting a \"/\"\n            var nextSlash = this.findNextPosInArray(this.info.values, \"/\", this.info);\n            if (nextSlash.index === this.info.index && nextSlash.offset === this.info.offset) {\n                end.ch += 1;\n            }\n        }\n        if (this.info.filter.length > 0) {\n            start.ch -= this.info.filter.length;\n        }\n\n        // Append matching quote, whitespace, paren\n        if (this.info.openingQuote && !hasClosingQuote) {\n            insertText += this.info.openingQuote;\n        }\n        if (!hasClosingParen) {\n            // Add trailing whitespace to match leading whitespace\n            if (this.info.leadingWhitespace) {\n                insertText += this.info.leadingWhitespace;\n            }\n            insertText += \")\";\n        }\n\n        // HACK (tracking adobe/brackets#1688): We talk to the private CodeMirror instance\n        // directly to replace the range instead of using the Document, as we should. The\n        // reason is due to a flaw in our current document synchronization architecture when\n        // inline editors are open.\n        this.editor._codeMirror.replaceRange(insertText, start, end);\n\n        // Adjust cursor position\n        if (this.closeOnSelect) {\n            // If there is existing closing quote and/or paren, move the cursor past them\n            moveLen = (hasClosingQuote ? 1 : 0) + (hasClosingParen ? 1 : 0);\n            if (moveLen > 0) {\n                this.editor.setCursorPos(start.line, start.ch + completion.length + moveLen);\n            }\n            return false;\n\n        } else {\n            // If closing quote and/or paren are added, move the cursor to where it would have been\n            moveLen = ((this.info.openingQuote && !hasClosingQuote) ? 1 : 0) + (!hasClosingParen ? 1 : 0);\n            if (moveLen > 0) {\n                this.editor.setCursorPos(start.line, start.ch + completion.length);\n            }\n        }\n\n        return true;\n    };\n\n    /**\n     * Inserts a given html url hint into the current editor context.\n     *\n     * @param {jQuery.Object} completion\n     * The hint to be inserted into the editor context.\n     *\n     * @return {boolean}\n     * Indicates whether the manager should follow hint insertion with an\n     * additional explicit hint request.\n     */\n    UrlCodeHints.prototype.insertHtmlHint = function (completion) {\n        var cursor = this.editor.getCursorPos(),\n            start = {line: -1, ch: -1},\n            end = {line: -1, ch: -1},\n            tagInfo = HTMLUtils.getTagInfo(this.editor, cursor),\n            tokenType = tagInfo.position.tokenType,\n            charCount = 0,\n            endQuote = \"\",\n            shouldReplace = false;\n\n        if (tokenType === HTMLUtils.ATTR_VALUE) {\n            // Special handling for URL hinting -- if the completion is a file name\n            // and not a folder, then close the code hint list.\n            if (!this.closeOnSelect && completion.match(/\\/$/) === null) {\n                this.closeOnSelect = true;\n\n                // Insert folder names, but replace file names\n                shouldReplace = true;\n            }\n\n            if (!tagInfo.attr.hasEndQuote) {\n                endQuote = tagInfo.attr.quoteChar;\n                if (endQuote) {\n                    completion += endQuote;\n                } else if (tagInfo.position.offset === 0) {\n                    completion = \"\\\"\" + completion + \"\\\"\";\n                }\n            }\n\n            if (shouldReplace) {\n                // Replace entire value\n                charCount = tagInfo.attr.value.length;\n            } else {\n                // Replace filter (to insert new selection)\n                charCount = this.info.filter.length;\n\n                // If next char is \"/\", then overwrite it since we're inserting a \"/\"\n                if (this.info.attr.value.length > charCount && this.info.attr.value[charCount] === \"/\") {\n                    charCount += 1;\n                }\n            }\n        }\n\n        end.line = start.line = cursor.line;\n        start.ch = cursor.ch - tagInfo.position.offset;\n        end.ch = start.ch + charCount;\n\n        this.editor.document.replaceRange(completion, start, end);\n\n        if (!this.closeOnSelect) {\n            // If we append the missing quote, then we need to adjust the cursor postion\n            // to keep the code hint list open.\n            if (tokenType === HTMLUtils.ATTR_VALUE && !tagInfo.attr.hasEndQuote) {\n                this.editor.setCursorPos(start.line, start.ch + completion.length - 1);\n            }\n            return true;\n        }\n\n        if (tokenType === HTMLUtils.ATTR_VALUE && tagInfo.attr.hasEndQuote) {\n            // Move the cursor to the right of the existing end quote after value insertion.\n            this.editor.setCursorPos(start.line, start.ch + completion.length + 1);\n        }\n\n        return false;\n    };\n\n    function _clearCachedHints() {\n        // Verify cache exists and is not deferred\n        if (urlHints && urlHints.cachedHints && urlHints.cachedHints.deferred &&\n                urlHints.cachedHints.deferred.state() !== \"pending\") {\n\n            // Cache may or may not be stale. Main benefit of cache is to limit async lookups\n            // during typing. File tree updates cannot happen during typing, so it's probably\n            // not worth determining whether cache may still be valid. Just delete it.\n            urlHints.cachedHints = null;\n        }\n    }\n\n    AppInit.appReady(function () {\n        data            = JSON.parse(Data);\n        htmlAttrs       = data.htmlAttrs;\n\n        urlHints        = new UrlCodeHints();\n        CodeHintManager.registerHintProvider(urlHints, [\"css\", \"html\", \"less\", \"scss\"], 5);\n\n        FileSystem.on(\"change\", _clearCachedHints);\n        FileSystem.on(\"rename\", _clearCachedHints);\n\n        // For unit testing\n        exports.hintProvider = urlHints;\n    });\n});\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/testfiles/subfolder/test.css",
    "content": "/* test.css */\nbody {\n    margin: 0;\n    background-image: url();\n}\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/testfiles/subfolder/test.js",
    "content": "/* test.js */\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/testfiles/subfolder/test.scss",
    "content": "/* test.scss */\nbody {\n    .test {\n        &.brackets {\n            background-image: url();\n        }\n    }\n}\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/testfiles/test.html",
    "content": "<!doctype html>\n<html>\n<head>\n<style type='text/css'>\n@import url() screen;\nbody {\n  background-image: url();\n  border-image: url('');\n  list-style-image: url(\"\");\n  filter: url(\"/\");\n  background-image: url(dummy.jpg);\n  background-image: \n}\n</style>\n<link href=\"\" rel=\"stylesheet\">\n<script src='' type=''></script>\n</head>\n<body>\n  <img src=''>\n  <img src='subfolder/'>\n  <a href='results.html?id=1003'>Results</a>\n  <a href='../'>Page relative: up 1 folder</a>\n  <a href='/'>Site-root relative: root folder</a>\n  <a href='test2.html'>Results</a>\n  <video poster=''>Results</video>\n  <img src='subfolder/chevron.png'>\n</body>\n</html>\n"
  },
  {
    "path": "src/extensions/default/UrlCodeHints/unittests.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, it, expect, beforeEach, afterEach, beforeFirst, afterLast, waitsFor, runs, waitsForDone */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Modules from the SpecRunner window\n    var MasterDocumentManager     = brackets.getModule(\"document/DocumentManager\"),\n        MasterMainViewManager     = brackets.getModule(\"view/MainViewManager\"),\n        FileUtils                 = brackets.getModule(\"file/FileUtils\"),\n        SpecRunnerUtils           = brackets.getModule(\"spec/SpecRunnerUtils\"),\n        UrlCodeHints              = require(\"main\");\n\n\n    describe(\"Url Code Hinting\", function () {\n\n        var extensionPath   = FileUtils.getNativeModuleDirectoryPath(module),\n            testHtmlPath    = extensionPath + \"/testfiles/test.html\",\n            testCssPath     = extensionPath + \"/testfiles/subfolder/test.css\",\n            testScssPath    = extensionPath + \"/testfiles/subfolder/test.scss\",\n            testDocument,\n            testEditor,\n            hintsObj;\n\n        // IMPORTANT: By default, Mac sorts folder contents differently from other OS's,\n        // so the files and folders in the \"testfiles\" and \"subfolder\" folder are named\n        // strategically so that they sort the same on all OS's (i.e. folders are listed\n        // first, and then files), but this is not true for UrlCodeHints folder.\n        var testfilesDirHints       = [ \"subfolder/\", \"test.html\"],\n            subfolderDirHints       = [ \"chevron.png\", \"test.css\", \"test.js\", \"test.scss\"],\n            UrlCodeHintsDirHintsMac = [ \"../data.json\", \"../main.js\", \"../testfiles/\", \"../unittests.js\"],\n            UrlCodeHintsDirHints    = [ \"../testfiles/\", \"../data.json\", \"../main.js\", \"../unittests.js\"];\n\n        /**\n         * Returns an Editor suitable for use in isolation, given a Document.\n         *\n         * @param {Document} doc - the document to be contained by the new Editor\n         * @return {Editor} - the mock editor object\n         */\n        function createMockEditor(doc) {\n            return SpecRunnerUtils.createMockEditorForDocument(doc);\n        }\n\n        function setupTests(testFilePath) {\n            runs(function () {\n                MasterDocumentManager.getDocumentForPath(testFilePath).done(function (doc) {\n                    testDocument = doc;\n                });\n            });\n\n            waitsFor(function () {\n                return (testDocument);\n            }, \"Unable to open test document\", 2000);\n\n            // create Editor instance (containing a CodeMirror instance)\n            runs(function () {\n                testEditor = createMockEditor(testDocument);\n                MasterMainViewManager._edit(MasterMainViewManager.ACTIVE_PANE, testDocument);\n            });\n        }\n\n        function tearDownTests() {\n            runs(function () {\n                // The following call ensures that the document is reloaded\n                // from disk before each test\n                MasterMainViewManager._closeAll(MasterMainViewManager.ALL_PANES);\n                SpecRunnerUtils.destroyMockEditor(testDocument);\n                testEditor = null;\n                testDocument = null;\n                hintsObj = null;\n            });\n        }\n\n        // Helper method to ask provider for hints at current cursor position.\n        // Provider returns either an array of hints, or a deferred promise.\n        // If a promise is returned, wait for it to resolve.\n        //\n        // Since this may be async, it cannot return the hints list, so it depends\n        // on the hintsObj variable (with module scope) to exist.\n        function expectAsyncHints(provider) {\n            runs(function () {\n                expect(provider.hasHints(testEditor, null)).toBe(true);\n                hintsObj = provider.getHints();\n                expect(hintsObj).toBeTruthy();\n            });\n\n            runs(function () {\n                if (hintsObj instanceof Object && hintsObj.hasOwnProperty(\"done\")) {\n                    hintsObj.done(function (resolvedHintsObj) {\n                        hintsObj = resolvedHintsObj;\n                    });\n                }\n            });\n\n            waitsFor(function () {\n                return (!hintsObj || hintsObj.hints);\n            }, \"Unable to resolve hints\", 2000);\n        }\n\n        // Ask provider for hints at current cursor position; expect it NOT to return any\n        function expectNoHints(provider) {\n            expect(provider.hasHints(testEditor, null)).toBeFalsy();\n        }\n\n        // Expect hintList to contain folder and file names.\n        function verifyUrlHints(hintList, expectedHints) {\n            expect(hintList).toEqual(expectedHints);\n        }\n\n        // Helper functions for testing cursor position / selection range\n        function fixPos(pos) {\n            if (!(\"sticky\" in pos)) {\n                pos.sticky = null;\n            }\n            return pos;\n        }\n\n        describe(\"HTML Url Code Hints\", function () {\n\n            beforeFirst(function () {\n                setupTests(testHtmlPath);\n            });\n\n            afterLast(function () {\n                tearDownTests();\n            });\n\n            it(\"should hint for href attribute\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 14, ch: 12 });\n\n                    // Must reset hintsObj before every call to expectAsyncHints()\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should hint for src attribute\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 15, ch: 13 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should hint for poster attribute\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 24, ch: 17 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should not hint for type attribute\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 15, ch: 21 });\n                    expectNoHints(UrlCodeHints.hintProvider);\n                });\n            });\n\n            it(\"should not hint in query part of url\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 20, ch: 31 });\n                    expectNoHints(UrlCodeHints.hintProvider);\n                });\n            });\n\n            it(\"should hint up 1 folder for '../'\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 21, ch: 14 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    var expectedHints = (brackets.platform !== \"win\") ? UrlCodeHintsDirHintsMac : UrlCodeHintsDirHints;\n                    verifyUrlHints(hintsObj.hints, expectedHints);\n                });\n            });\n        });\n\n        describe(\"CSS Url Code Hints\", function () {\n\n            beforeFirst(function () {\n                setupTests(testHtmlPath);\n            });\n\n            afterLast(function () {\n                tearDownTests();\n            });\n\n            it(\"should hint for @import url()\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 4, ch: 12 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should hint for background-image: url()\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 6, ch: 24 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should hint for border-image: url('')\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 7, ch: 21 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should hint for list-style-image: url(\\\"\\\")\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 8, ch: 25 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, testfilesDirHints);\n                });\n            });\n\n            it(\"should not hint for @import outside of url()\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 4, ch: 15 });\n                    expectNoHints(UrlCodeHints.hintProvider);\n                });\n            });\n\n            it(\"should not hint for background-image outside of url()\", function () {\n                runs(function () {\n                    testEditor.setCursorPos({ line: 11, ch: 20 });\n                    expectNoHints(UrlCodeHints.hintProvider);\n                });\n            });\n        });\n\n        describe(\"Url Code Hints in a subfolder\", function () {\n\n            afterEach(function () {\n                tearDownTests();\n            });\n\n            it(\"should hint for background-image: url() in CSS\", function () {\n                runs(function () {\n                    setupTests(testCssPath);\n                });\n\n                runs(function () {\n                    testEditor.setCursorPos({ line: 3, ch: 26 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, subfolderDirHints);\n                });\n            });\n\n            it(\"should hint for background-image: url() in SCSS\", function () {\n                runs(function () {\n                    setupTests(testScssPath);\n                });\n\n                runs(function () {\n                    testEditor.setCursorPos({ line: 4, ch: 34 });\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    verifyUrlHints(hintsObj.hints, subfolderDirHints);\n                });\n            });\n        });\n\n        describe(\"Project root relative Url Code Hints\", function () {\n\n            var testWindow,\n                brackets,\n                workingSet = [],\n                CodeHintManager,\n                CommandManager,\n                Commands,\n                DocumentManager,\n                MainViewManager,\n                EditorManager;\n\n            it(\"should hint site root '/'\", function () {\n                runs(function () {\n                    SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                        testWindow      = w;\n                        brackets        = testWindow.brackets;\n                        CodeHintManager = brackets.test.CodeHintManager;\n                        CommandManager  = brackets.test.CommandManager;\n                        Commands        = brackets.test.Commands;\n                        DocumentManager = brackets.test.DocumentManager;\n                        EditorManager   = brackets.test.EditorManager;\n                        MainViewManager = brackets.test.MainViewManager;\n                    });\n                });\n\n                runs(function () {\n                    SpecRunnerUtils.loadProjectInTestWindow(extensionPath);\n                });\n\n                runs(function () {\n                    workingSet.push(testHtmlPath);\n                    waitsForDone(SpecRunnerUtils.openProjectFiles(workingSet), \"openProjectFiles\");\n                });\n\n                runs(function () {\n                    DocumentManager.getDocumentForPath(testHtmlPath).done(function (doc) {\n                        testDocument = doc;\n                    });\n                });\n\n                waitsFor(function () {\n                    return (testDocument);\n                }, \"Unable to open test document\", 2000);\n\n                runs(function () {\n                    MainViewManager._edit(MainViewManager.ACTIVE_PANE, testDocument);\n                    testEditor = EditorManager.getCurrentFullEditor();\n                    testEditor.setCursorPos({ line: 22, ch: 12 });\n                    CommandManager.execute(Commands.SHOW_CODE_HINTS);\n                });\n\n                runs(function () {\n                    var hintList = CodeHintManager._getCodeHintList();\n                    expect(hintList).toBeTruthy();\n                    expect(hintList.hints).toBeTruthy();\n                    expect(hintList.hints).toContain(\"/testfiles/\");\n                });\n\n                // cleanup\n                runs(function () {\n                    testEditor       = null;\n                    testDocument     = null;\n                    testWindow       = null;\n                    brackets         = null;\n                    CodeHintManager  = null;\n                    CommandManager   = null;\n                    Commands         = null;\n                    DocumentManager  = null;\n                    EditorManager    = null;\n                    MainViewManager  = null;\n                    SpecRunnerUtils.closeTestWindow();\n                });\n            });\n        });\n\n        describe(\"Url Insertion\", function () {\n\n            // These tests edit doc, so we need to setup/tear-down for each test\n            beforeEach(function () {\n                setupTests(testHtmlPath);\n            });\n\n            afterEach(function () {\n                tearDownTests();\n            });\n\n            it(\"should handle unclosed url(\", function () {\n                var pos1    = { line: 11, ch: 20 },\n                    pos2    = { line: 11, ch: 24 },\n                    pos3    = { line: 11, ch: 34 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    testDocument.replaceRange(\"url(\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[1]).toBe(\"test.html\");\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[1])).toBe(false);\n\n                    // hint was added with closing paren\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"url(test.html)\");\n\n                    // Cursor was moved past closing paren\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos3));\n                });\n            });\n\n            it(\"should handle unclosed url( with unclosed single-quote\", function () {\n                var pos1    = { line: 11, ch: 20 },\n                    pos2    = { line: 11, ch: 25 },\n                    pos3    = { line: 11, ch: 36 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    testDocument.replaceRange(\"url('\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[1]).toBe(\"test.html\");\n\n                    // False indicates hints were closed after insertion\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[1])).toBe(false);\n\n                    // Hint was added with closing single-quote and closing paren\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"url('test.html')\");\n\n                    // Cursor was moved past closing single-quote and closing paren\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos3));\n                });\n            });\n\n            it(\"should keep hints open after inserting folder in HTML\", function () {\n                var pos1    = { line: 18, ch: 12 },\n                    pos2    = { line: 18, ch: 22 },\n                    pos3    = { line: 18, ch: 33 },\n                    pos4    = { line: 18, ch: 34 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // True indicates hints were remain open after insertion of folder\n                    // (i.e. showing contents of inserted folder)\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(true);\n\n                    // Hint was added with closing double-quote and closing paren\n                    expect(testDocument.getRange(pos1, pos2)).toEqual(\"subfolder/\");\n\n                    // Cursor remains inside quote\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos2));\n\n                    // Get hints of inserted folder\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(subfolderDirHints.length);\n\n                    // Complete path is displayed\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/chevron.png\");\n\n                    // False indicates hints were closed after insertion\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(false);\n\n                    // Hint was added\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"subfolder/chevron.png\");\n\n                    // Cursor was moved past closing double-quote and closing paren\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos4));\n                });\n            });\n\n            it(\"should keep hints open after inserting folder in CSS\", function () {\n                var pos1    = { line: 11, ch: 20 },\n                    pos2    = { line: 11, ch: 25 },\n                    pos3    = { line: 11, ch: 35 },\n                    pos4    = { line: 11, ch: 37 },\n                    pos5    = { line: 11, ch: 48 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    testDocument.replaceRange('url(\"', pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // True indicates hints were remain open after insertion of folder\n                    // (i.e. showing contents of inserted folder)\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(true);\n\n                    // Hint was added with closing double-quote and closing paren\n                    expect(testDocument.getRange(pos1, pos4)).toEqual('url(\"subfolder/\")');\n\n                    // Cursor remains inside double-quote and closing paren\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos3));\n\n                    // Get hints of inserted folder\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(subfolderDirHints.length);\n\n                    // Complete path is displayed\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/chevron.png\");\n\n                    // False indicates hints were closed after insertion\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(false);\n\n                    // Hint was added\n                    expect(testDocument.getRange(pos1, pos5)).toEqual('url(\"subfolder/chevron.png\")');\n\n                    // Cursor was moved past closing double-quote and closing paren\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos5));\n                });\n            });\n\n            it(\"should insert folder and replace file in HTML\", function () {\n                var pos1    = { line: 23, ch: 11 },\n                    pos2    = { line: 23, ch: 21 },\n                    pos3    = { line: 23, ch: 31 },\n                    pos4    = { line: 23, ch: 32 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // True indicates hints were remain open after insertion of folder\n                    // (i.e. showing contents of inserted folder)\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(true);\n\n                    // Folder was inserted (i.e. filename was not removed)\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"subfolder/test2.html\");\n\n                    // Cursor is at end of inserted folder\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos2));\n\n                    // Get hints of inserted folder\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(subfolderDirHints.length);\n\n                    // Complete path is displayed\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/chevron.png\");\n\n                    // False indicates hints were closed after insertion\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(false);\n\n                    // Filename was replaced\n                    expect(testDocument.getRange(pos1, pos4)).toEqual(\"subfolder/chevron.png\");\n                });\n            });\n\n            it(\"should completely replace file in HTML\", function () {\n                var pos1    = { line: 25, ch: 11 },\n                    pos2    = { line: 25, ch: 27 },\n                    pos3    = { line: 25, ch: 34 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/chevron.png\");\n\n                    // False indicates hints were closed after insertion\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(false);\n\n                    // File name was completely replaced, not just appended to\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"'subfolder/chevron.png'\");\n\n                    // Cursor was moved past closing single-quote\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos3));\n                });\n            });\n\n            it(\"should insert filtered folder in HTML\", function () {\n                var pos1    = { line: 23, ch: 11 },\n                    pos2    = { line: 23, ch: 14 },\n                    pos3    = { line: 23, ch: 31 };\n\n                runs(function () {\n                    testDocument.replaceRange(\"sub\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // Partially existing folder was inserted correctly\n                    UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0]);\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"subfolder/test2.html\");\n                });\n            });\n\n            it(\"should replace filtered file in HTML\", function () {\n                var pos1    = { line: 23, ch: 11 },\n                    pos2    = { line: 23, ch: 14 },\n                    pos3    = { line: 23, ch: 21 };\n\n                runs(function () {\n                    testDocument.replaceRange(\"tes\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"test.html\");\n\n                    // Partially existing file was replaced correctly\n                    UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0]);\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"test.html'\");\n                });\n            });\n\n            it(\"should insert folder and replace file in CSS\", function () {\n                var pos1    = { line: 10, ch: 24 },\n                    pos2    = { line: 10, ch: 34 },\n                    pos3    = { line: 10, ch: 43 },\n                    pos4    = { line: 10, ch: 45 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // True indicates hints were remain open after insertion of folder\n                    // (i.e. showing contents of inserted folder)\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(true);\n\n                    // Folder was inserted (i.e. filename was not removed)\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"subfolder/dummy.jpg\");\n\n                    // Cursor is at end of inserted folder\n                    expect(fixPos(testEditor.getCursorPos())).toEqual(fixPos(pos2));\n\n                    // Get hints of inserted folder\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(subfolderDirHints.length);\n\n                    // Complete path is displayed\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/chevron.png\");\n\n                    // False indicates hints were closed after insertion\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(false);\n\n                    // Filename was replaced\n                    expect(testDocument.getRange(pos1, pos4)).toEqual(\"subfolder/chevron.png\");\n                });\n            });\n\n            it(\"should insert filtered folder in CSS\", function () {\n                var pos1    = { line: 10, ch: 24 },\n                    pos2    = { line: 10, ch: 27 },\n                    pos3    = { line: 10, ch: 43 };\n\n                runs(function () {\n                    testDocument.replaceRange(\"sub\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // Partially existing folder was inserted correctly\n                    UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0]);\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"subfolder/dummy.jpg\");\n                });\n            });\n\n            it(\"should replace filtered file in CSS\", function () {\n                var pos1    = { line: 10, ch: 24 },\n                    pos2    = { line: 10, ch: 27 },\n                    pos3    = { line: 10, ch: 34 };\n\n                runs(function () {\n                    testDocument.replaceRange(\"tes\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"test.html\");\n\n                    // Partially existing file was replaced correctly\n                    UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0]);\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"test.html)\");\n                });\n            });\n\n            it(\"should collapse consecutive path separators when inserting folder in HTML\", function () {\n                var pos1    = { line: 22, ch: 11 },\n                    pos2    = { line: 22, ch: 22 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // True indicates hints were remain open after insertion of folder\n                    // (i.e. showing contents of inserted folder)\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(true);\n\n                    // Folder was inserted and there's only 1 slash afterwards\n                    expect(testDocument.getRange(pos1, pos2)).toEqual(\"subfolder/'\");\n                });\n            });\n\n            it(\"should collapse consecutive path separators when inserting folder in CSS\", function () {\n                var pos1    = { line: 9, ch: 15 },\n                    pos2    = { line: 9, ch: 26 };\n\n                runs(function () {\n                    testEditor.setCursorPos(pos1);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(2);\n                    expect(hintsObj.hints[0]).toBe(\"subfolder/\");\n\n                    // True indicates hints were remain open after insertion of folder\n                    // (i.e. showing contents of inserted folder)\n                    expect(UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0])).toBe(true);\n\n                    // Folder was inserted and there's only 1 slash afterwards\n                    expect(testDocument.getRange(pos1, pos2)).toEqual(\"subfolder/\\\"\");\n                });\n            });\n\n            it(\"should show & insert case insensitive hints in HTML\", function () {\n                var pos1    = { line: 18, ch: 12 },\n                    pos2    = { line: 18, ch: 13 },\n                    pos3    = { line: 18, ch: 21 };\n\n                runs(function () {\n                    // Insert letter that matches filename, but with different case\n                    testDocument.replaceRange(\"T\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"test.html\");\n\n                    UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0]);\n\n                    // Filename case from list was inserted (overriding case inserted in page)\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"test.html\");\n                });\n            });\n\n            it(\"should show & insert case insensitive hints in CSS\", function () {\n                var pos1    = { line: 6, ch: 24 },\n                    pos2    = { line: 6, ch: 25 },\n                    pos3    = { line: 6, ch: 33 };\n\n                runs(function () {\n                    // Insert letter that matches filename, but with different case\n                    testDocument.replaceRange(\"T\", pos1, pos1);\n                    testEditor.setCursorPos(pos2);\n                    hintsObj = null;\n                    expectAsyncHints(UrlCodeHints.hintProvider);\n                });\n\n                runs(function () {\n                    expect(hintsObj).toBeTruthy();\n                    expect(hintsObj.hints).toBeTruthy();\n                    expect(hintsObj.hints.length).toBe(1);\n                    expect(hintsObj.hints[0]).toBe(\"test.html\");\n\n                    UrlCodeHints.hintProvider.insertHint(hintsObj.hints[0]);\n\n                    // Filename case from list was inserted (overriding case inserted in page)\n                    expect(testDocument.getRange(pos1, pos3)).toEqual(\"test.html\");\n                });\n            });\n        });\n\n    }); // describe(\"Url Code Hinting\"\n});\n"
  },
  {
    "path": "src/extensions/dev/README.md",
    "content": "# Brackets Dev Extensions\n\nThis directory contains extensions that are being developed. User-installed\nextensions are placed in the \"user\" extensions directory, which can be accessed\nby running the <code>Help > Show Extensions Folder</code> menu command. The contents of\nthis directory (except the <code>README.md</code> file) are ignored by git.\n\n(<code>README.md</code> also serves as a dummy file so this directory can be added to git.)\n"
  },
  {
    "path": "src/extensions/samples/BracketsConfigCentral/htmlContent/Config.html",
    "content": "<div class=\"brackets-config-central\">\n    <div class=\"config-options\">\n        <label>\n            <p>Default file Extension When Creating New Files:</p>\n            <input type=\"text\" value=\"{{defaultExtension}}\">\n        </label>\n        <label>\n            <p>Number of space units for tabs</p>\n            <input type=\"text\" value=\"{{spaceUnits}}\">\n        </label>\n    </div>\n</div>"
  },
  {
    "path": "src/extensions/samples/BracketsConfigCentral/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var FileUtils                   = brackets.getModule(\"file/FileUtils\"),\n        ExtensionUtils              = brackets.getModule(\"utils/ExtensionUtils\"),\n        DocumentManager             = brackets.getModule(\"document/DocumentManager\"),\n        MainViewFactory             = brackets.getModule(\"view/MainViewFactory\"),\n        Mustache                    = brackets.getModule(\"thirdparty/mustache/mustache\"),\n        ConfigViewContent           = require(\"text!htmlContent/Config.html\");\n\n    /* our module object */\n    var _module = module;\n\n    /* @type {Object.<string, ConfigView>} List of open views */\n    function ConfigView(doc, $container) {\n        this.$container = $container;\n        this.doc = doc;\n        this.json = JSON.parse(this.doc.getText());\n        this.$view = $(Mustache.render(ConfigViewContent, this.json));\n        this.$view.css({\n            \"background-image\": \"url(file://\" + FileUtils.getNativeModuleDirectoryPath(_module) + \"/htmlContent/logo-sm.png)\",\n            \"background-position\": \"bottom right\",\n            \"background-repeat\": \"no-repeat\"\n        });\n        $container.append(this.$view);\n    }\n\n    /*\n     * Retrieves the file object for this view\n     * return {!File} the file object for this view\n     */\n    ConfigView.prototype.getFile = function () {\n        return this.doc.file;\n    };\n\n    /*\n     * Updates the layout of the view\n     */\n    ConfigView.prototype.updateLayout = function () {\n    };\n\n    /*\n     * Destroys the view\n     */\n    ConfigView.prototype.destroy = function () {\n        this.$view.remove();\n    };\n\n    /*\n     * Creates a view of a file (.brackets.json)\n     * @param {!File} file - the file to create a view for\n     * @param {!Pane} pane - the pane where to create the view\n     * @private\n     */\n    function _createConfigViewOf(file, pane) {\n        var result = new $.Deferred(),\n            view = pane.findViewOfFile(file.fullPath);\n\n        if (view) {\n            // existing view, then just show it\n            pane.showView(view);\n            result.resolve(view.getFile());\n        } else {\n            DocumentManager.getDocumentForPath(file.fullPath)\n                .done(function (doc) {\n                    var view = new ConfigView(doc, pane.$el);\n                    pane.addView(view, true);\n                    result.resolve(doc.file);\n                })\n                .fail(function (fileError) {\n                    result.reject(fileError);\n                });\n        }\n        return result.promise();\n    }\n\n    /*\n     *  Create a view factory that can create views for the file\n     *  `.brackets.json` in a project's root folder.\n     */\n    var configViewFactory = {\n        canOpenFile: function (fullPath) {\n            var filename = fullPath.substr(fullPath.lastIndexOf(\"/\") + 1);\n            return (filename.toLowerCase() === \".brackets.json\");\n        },\n        openFile: function (file, pane) {\n            return _createConfigViewOf(file, pane);\n        }\n    };\n\n    /* load styles used by our template */\n    ExtensionUtils.loadStyleSheet(module, \"styles/styles.css\");\n    MainViewFactory.registerViewFactory(configViewFactory);\n});\n"
  },
  {
    "path": "src/extensions/samples/BracketsConfigCentral/package.json",
    "content": "{\n    \"name\": \"JeffryBooher.BracketsConfigCentral\",\n    \"title\": \"Brackets Config Central\",\n    \"description\": \"A simple view factory provider\",\n    \"homepage\": \"https://github.com/JeffryBooher\",\n    \"version\": \"0.0.1\",\n    \"author\": \"@JeffryBooher\",\n    \"license\": \"MIT\",\n    \"engines\": {\n        \"brackets\": \">=0.44.0\"\n    }\n}\n"
  },
  {
    "path": "src/extensions/samples/BracketsConfigCentral/styles/styles.css",
    "content": ".brackets-config-central \n{\n    background-color: bisque;\n}\n\n.brackets-config-central input[type=\"text\"]\n{\n    width: 1em;\n}\n\n.brackets-config-central .config-options \n{\n    margin: 2em;\n}\n\n"
  },
  {
    "path": "src/extensions/samples/ContextMenuTest/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var CommandManager  = brackets.getModule(\"command/CommandManager\"),\n        EditorManager   = brackets.getModule(\"editor/EditorManager\"),\n        Menus           = brackets.getModule(\"command/Menus\");\n\n    // Define the functions that Commands will execute\n    function TestCommand1() {\n        var command1 = CommandManager.get(\"extensionTest.command1\");\n        if (!command1) {\n            return;\n        }\n        var command2 = CommandManager.get(\"extensionTest.command2\");\n        if (!command2) {\n            return;\n        }\n\n        var checked = command1.getChecked();\n        if (checked) {\n            window.alert(\"Unchecking self. Disabling next.\");\n            command2.setEnabled(false);\n        } else {\n            window.alert(\"Checking self. Enabling next.\");\n            command2.setEnabled(true);\n        }\n        command1.setChecked(!checked);\n    }\n\n    function TestCommand2() {\n        window.alert(\"Executing command 2\");\n    }\n\n    function TestCommand3() {\n        window.alert(\"Executing command 3\");\n    }\n\n    // Register the functions as commands\n    var command1 = CommandManager.register(\"Toggle Checkmark\", \"extensionTest.command1\", TestCommand1);\n    var command2 = CommandManager.register(\"Enabled when previous is Checked\", \"extensionTest.command2\", TestCommand2);\n    var command3 = CommandManager.register(\"Enabled when text selected\", \"extensionTest.command3\", TestCommand3);\n\n    // Set the Command initial state\n    command1.setChecked(true);\n    command2.setEnabled(true);\n    command3.setEnabled(false);\n\n    // Update the MenuItem by changing the underlying command\n    var updateEnabledState = function () {\n        var editor = EditorManager.getFocusedEditor();\n        command3.setEnabled(editor && editor.getSelectedText() !== \"\");\n    };\n    var editor_cmenu = Menus.getContextMenu(Menus.ContextMenuIds.EDITOR_MENU);\n    editor_cmenu.on(\"beforeContextMenuOpen\", updateEnabledState);\n\n\n    // Add the Commands as MenuItems of the Editor context menu\n    if (editor_cmenu) {\n        editor_cmenu.addMenuDivider();\n        editor_cmenu.addMenuItem(\"extensionTest.command1\");\n        editor_cmenu.addMenuItem(\"extensionTest.command2\");\n        editor_cmenu.addMenuItem(\"extensionTest.command3\");\n    }\n});\n"
  },
  {
    "path": "src/extensions/samples/InlineImageViewer/InlineImageViewer.html",
    "content": "<div class=\"inline-image-viewer\">\n    <div class=\"filename\"><span /></div>\n    <img class=\"image\" />\n</div>\n"
  },
  {
    "path": "src/extensions/samples/InlineImageViewer/InlineImageViewer.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    'use strict';\n\n    // Load Brackets modules\n    var InlineWidget        = brackets.getModule(\"editor/InlineWidget\").InlineWidget;\n\n    // Load tempalte\n    var inlineEditorTemplate = require(\"text!InlineImageViewer.html\");\n\n    function InlineImageViewer(fileName, fullPath) {\n        this.fileName = fileName;\n        this.fullPath = fullPath;\n        InlineWidget.call(this);\n    }\n    InlineImageViewer.prototype = Object.create(InlineWidget.prototype);\n    InlineImageViewer.prototype.constructor = InlineImageViewer;\n    InlineImageViewer.prototype.parentClass = InlineWidget.prototype;\n\n    InlineImageViewer.prototype.fileName = null;\n    InlineImageViewer.prototype.fullPath = null;\n    InlineImageViewer.prototype.$wrapperDiv = null;\n    InlineImageViewer.prototype.$image = null;\n\n    InlineImageViewer.prototype.load = function (hostEditor) {\n        InlineImageViewer.prototype.parentClass.load.apply(this, arguments);\n\n        this.$wrapperDiv = $(inlineEditorTemplate);\n\n        // TODO (jason-sanjose): Use handlebars.js and update template to\n        // use expressions instead e.g. {{filename}}\n        // Header\n        $(this.$wrapperDiv.find(\"span\")).text(this.fileName);\n\n        // Image\n        this.$image = $(this.$wrapperDiv.find(\"img\")).attr(\"src\", this.fullPath);\n\n        this.$htmlContent.append(this.$wrapperDiv);\n        this.$htmlContent.click(this.close.bind(this));\n    };\n\n    InlineImageViewer.prototype.onAdded = function () {\n        InlineImageViewer.prototype.parentClass.onAdded.apply(this, arguments);\n        window.setTimeout(this._sizeEditorToContent.bind(this));\n    };\n\n    InlineImageViewer.prototype._sizeEditorToContent = function () {\n        // TODO: image might not be loaded yet--need to listen for load event and update then.\n        this.hostEditor.setInlineWidgetHeight(this, this.$wrapperDiv.height() + 20, true);\n        this.$image.css(\"opacity\", 1);\n    };\n\n    module.exports = InlineImageViewer;\n});\n"
  },
  {
    "path": "src/extensions/samples/InlineImageViewer/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var EditorManager           = brackets.getModule(\"editor/EditorManager\"),\n        ExtensionUtils          = brackets.getModule(\"utils/ExtensionUtils\"),\n        ProjectManager          = brackets.getModule(\"project/ProjectManager\");\n\n    // Local modules\n    var InlineImageViewer       = require(\"InlineImageViewer\");\n\n    /**\n     * Return the token string that is at the specified position.\n     *\n     * @param hostEditor {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {String} token string at the specified position\n     */\n    function _getStringAtPos(hostEditor, pos) {\n        var token = hostEditor._codeMirror.getTokenAt(pos, true);\n\n        // If the pos is at the beginning of a name, token will be the\n        // preceding whitespace or dot. In that case, try the next pos.\n        if (!/\\S/.test(token.string) || token.string === \".\") {\n            token = hostEditor._codeMirror.getTokenAt({line: pos.line, ch: pos.ch + 1}, true);\n        }\n\n        if (token.type === \"string\") {\n            var string = token.string;\n\n            // Strip quotes\n            var ch = string[0];\n            if (ch === \"\\\"\" || ch === \"'\") {\n                string = string.substr(1);\n            }\n            ch = string[string.length - 1];\n            if (ch === \"\\\"\" || ch === \"'\") {\n                string = string.substr(0, string.length - 1);\n            }\n\n            return string;\n        } else {\n\n            // Check for url(...);\n            var line = hostEditor._codeMirror.getLine(pos.line);\n            var match = /url\\s*\\(([^)]*)\\)/.exec(line);\n\n            if (match && match[1]) {\n                // URLs are relative to the doc\n                var docPath = hostEditor.document.file.fullPath;\n\n                docPath = docPath.substr(0, docPath.lastIndexOf(\"/\"));\n\n                return docPath + \"/\" + match[1];\n            }\n        }\n\n        return \"\";\n    }\n\n    /**\n     * This function is registered with EditManager as an inline editor provider. It creates an inline editor\n     * when cursor is on a JavaScript function name, find all functions that match the name\n     * and show (one/all of them) in an inline editor.\n     *\n     * @param {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {$.Promise} a promise that will be resolved with an InlineWidget\n     *      or null if we're not going to provide anything.\n     */\n    function inlineImageViewerProvider(hostEditor, pos) {\n\n        // Only provide image viewer if the selection is within a single line\n        var sel = hostEditor.getSelection(false);\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n\n        // Always use the selection start for determining the image file name. The pos\n        // parameter is usually the selection end.\n        var fileName = _getStringAtPos(hostEditor, hostEditor.getSelection(false).start);\n        if (fileName === \"\") {\n            return null;\n        }\n\n        // Check for valid file extensions\n        if (!/(\\.png|\\.jpg|\\.jpeg|\\.gif|\\.webp|\\.svg)$/i.test(fileName)) {\n            return null;\n        }\n\n        // TODO: Check for relative path\n        var projectPath = ProjectManager.getProjectRoot().fullPath;\n\n        if (fileName.indexOf(projectPath) !== 0) {\n            fileName = projectPath + fileName;\n        }\n        var result = new $.Deferred();\n\n        var imageViewer = new InlineImageViewer(fileName.substr(fileName.lastIndexOf(\"/\")), fileName);\n        imageViewer.load(hostEditor);\n\n        result.resolve(imageViewer);\n\n        return result.promise();\n    }\n\n    ExtensionUtils.loadStyleSheet(module, \"style.css\");\n    EditorManager.registerInlineEditProvider(inlineImageViewerProvider);\n});\n"
  },
  {
    "path": "src/extensions/samples/InlineImageViewer/style.css",
    "content": ".inline-image-viewer .filename {\n    text-align: right;\n    padding-right: 1.5em;\n    line-height: 32px;\n}\n\n.inline-image-viewer .image {\n    display: block;\n    margin: 0 auto;\n    opacity: 0;\n}"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/README.md",
    "content": "\n\n## Localization in Brackets\nBrackets has basic support for displaying user visible text in other languages. The document describes how localized text can be added to core Brackets code and Brackets Plugins \n\nJavascript and HTML that displays user visible strings in Brackets should not use static English strings directly in code. Instead,  strings should be stored in a the file brackets \\src\\nls\\root\\strings.js. Code that wishes to display strings should import the String module from src\\string.js. This module dynamically loads a strings.js file in the nls folder for the current local. JavaScript can then directly reference properties of the String module to access strings, and HTML can use the String module in combination with Mustache.js templating to display localized strings. Brackets uses the i18n RequireJS plugin for to load localized strings. The plugin loads the strings.js file according to the user’s locale and also provides a fallback to English for missing translations. \n\n## Adding new localized strings to Brackets\nAdd new English strings to the file brackets\\src\\nls\\root\\strings.js. Translations in other languages should be added to the strings.js file in each of the locale folders inside the “nls” folder. For example, modify brackets\\src\\nls\\fr\\strings.js for French\n\n## Using Localized strings in Brackets modules\n\n## Strings JavaScript\n1. Load the Strings module in the file where the string is to be used\n`Strings = require(\"strings\");`\n\n2. Reference a string by selecting a property from the String module. For example, `Strings.NOT_FOUND_ERR` yields the string “The file could not be found.\" for an English locale.\n\n## Strings HTML\nLocalizing HTML in Brackets requires use of the templating framework mustache.js since HTML cannot directly reference properties in strings.js. Strings for both JavaScript and HTML are stored \\src\\nls\\root\\strings.js, but in HTML they are referenced using the template syntax `{{stringKeyName}}`. \n\nFor example,\n\n`<h1 class=\"dialog-title\">{{SAVE_CHANGES}}</h1>`\n\nyields \n\n`<h1 class=\"dialog-title\">Save Changes</h1>`\n\nMustache recognizes this syntax and can substite the appropriate string. Mustache is run when Brackets launches during module load. Code in brackets.js loads the appropriate strings.js file using i18n, loads html content from a file as a text, runs Mustache on the text using strings.js for the data lookup, and then inserts the result into the DOM. Core brackets code that depends on the DOM should listen for the “htmlContentLoadComplete” before inspecting or manipulating the dome\n\n## Localization Guidelines\nMultiple strings keys in strings.js should not be concatenated together since word order often varies between languages\n\n## Limitations\nBrackets does not support localizing keyboard shortcuts yet\n\n\n## Localization Support for Brackets Plugins\n\nLocalization in plugins works very similarly to how localization works for core Brackets module. The i18n RequireJS plugin is used to dynamically load a string.js file for the appropriate locale. JavaString can then reference strings via property name from the loaded string module and mustache can be used on on html fragments to insert localized text.\n\nFor an example of a simple localized plugin see: brackets\\src\\extensions\\disabled\\LocalizationExample\n\nMove this plugin to the extensions\\user\\ folder to run the plugin. It will add a \"My New Command\" menu item to the end of the Edit menu. This command shows an alert with localized text and then a modal dialog with localized HTML content.\n\n#### Below is the folder structure and comments on the role of each file\n\n* main.js – loads the Strings module for the plugin and uses mustache to localize html content\n\n* package.json - add the translation languages as in the example: `\"i18n\": [\"en\", \"fr\" ]`.  Also, add any localized metadata for displayed metadata in the Extension Manager, as in the example: `\"fr\": { \"title\": \"localized title\" }`.\n\n* strings.js – uses i18n to load a strings.js file in the nls folder\n\n* htmlContent\n    * htmlfragment.html – html template to be localized by mustache\n* nls\n    * strings.js – configures i18n by specifying the  root folder and listing the locales supported by the plugin\n    * root\n        * strings.js – contains the English strings\n    * fr\n        * strings.js – contains the French strings\n    * etc. for each locale\n\n#### Strings for plugins vs Brackets\nNote that there is a distinction between loading strings for a plugin vs. strings in the Brackets core. To access strings local to your plugin use `var strings = require(\"strings\")`. To load the core Brackets strings use `var bracketsStrings = brackets.getModule(\"strings\")`\n\n"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/htmlContent/sampleHTMLFragment.html",
    "content": "<div class=\"sample-localized-dialog modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{DIALOG_TITLE}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        {{DIALOG_TEXT}}\n    </div>\n    <div class=\"modal-footer\">\n        <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{DIALOG_OK}}</a>\n    </div>\n</div>"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\nrequire.config({\n    paths: {\n        \"text\" : \"lib/text\",\n        \"i18n\" : \"lib/i18n\"\n    },\n    locale: brackets.getLocale()\n});\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Brackets modules\n    var CommandManager      = brackets.getModule(\"command/CommandManager\"),\n        Menus               = brackets.getModule(\"command/Menus\"),\n        Dialogs             = brackets.getModule(\"widgets/Dialogs\"),\n        Mustache            = brackets.getModule(\"thirdparty/mustache/mustache\");\n\n    // Load an html fragment using the require text plugin. Mustache will later\n    // be used to localize some of the text\n    var browserWrapperHtml  = require(\"text!htmlContent/sampleHTMLFragment.html\");\n\n    // Load the string module for this plugin. Not this references to the strings.js\n    // file next to the main.js fiel for this plugin. To access core brackets strings\n    // you would call brackets.getModule(\"strings\") instead of require(\"strings\")\n    var Strings             = require(\"strings\");\n\n\n    // This sample command first shows an alert passing in a localized\n    // string in JavaScript then it shows a localized HTML dialog.\n    function testCommand() {\n        window.alert(Strings.ALERT_MESSAGE);\n\n        // Localize the dialog using Strings as the datasource and use it as the dialog template\n        var localizedTemplate = Mustache.render(browserWrapperHtml, Strings);\n        Dialogs.showModalDialogUsingTemplate(localizedTemplate);\n    }\n\n\n    // Register the command\n    // A localized command name is used by passing in Strings.COMMAND_NAME\n    var myCommandID = \"localizationExample.command\";\n    CommandManager.register(Strings.COMMAND_NAME, myCommandID, testCommand);\n\n    var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);\n    menu.addMenuItem(myCommandID, null, Menus.AFTER, myCommandID);\n});\n"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/nls/fr/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n// French Translation\n\ndefine({\n    \"COMMAND_NAME\"      : \"Ma nouvelle commande\",\n    \"ALERT_MESSAGE\"     : \"Ceci est un exemple d'alerte\",\n    \"DIALOG_TITLE\"      : \"Exemple de boite de dialogue traduite\",\n    \"DIALOG_TEXT\"       : \"Ceci est un exemple de texte traduit dans Brackets\",\n    \"DIALOG_OK\"         : \"OK\"\n});\n"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/nls/root/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n// English - root strings\n\ndefine({\n    \"COMMAND_NAME\"      : \"My New Command\",\n    \"ALERT_MESSAGE\"     : \"This is a sample alert message\",\n    \"DIALOG_TITLE\"      : \"Localized Dialog Example\",\n    \"DIALOG_TEXT\"       : \"This is an example of localized text in Brackets\",\n    \"DIALOG_OK\"         : \"OK\"\n});\n"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/nls/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n\n    'use strict';\n\n    // Code that needs to display user strings should call require(\"strings\") to load\n    // strings.js. This file will dynamically load strings.js for the specified by bracketes.locale.\n    //\n    // Translations for other locales should be placed in nls/<locale<optional country code>>/strings.js\n    // Localization is provided via the i18n plugin.\n    // All other bundles for languages need to add a prefix to the exports below so i18n can find them.\n    // TODO: dynamically populate the local prefix list below?\n    module.exports = {\n        root: true,\n        \"fr\": true\n    };\n});\n"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/package.json",
    "content": "{\n    \"name\": \"localization-example\",\n    \"title\": \"Localization Example\",\n    \"description\": \"A guide on how to localize your extension.\",\n    \"homepage\": \"https://github.com/adobe/brackets/tree/master/src/extensions/samples/LocalizationExample\",\n    \"version\": \"1.0.0\",\n    \"author\": \"The Brackets team\",\n    \"license\": \"MIT\",\n    \"engines\": {\n        \"brackets\": \">=0.42.0\"\n    },\n    \"i18n\": [\n        \"en\", \n        \"fr\" \n    ],\n    \"package-i18n\": {\n        \"fr\": {\n            \"title\": \"Localisation Exemple\",\n            \"description\": \"Un guide sur la façon de localiser votre poste.\"\n        }\n    }\n}\n"
  },
  {
    "path": "src/extensions/samples/LocalizationExample/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * This file provides the interface to user visible strings in Brackets. Code that needs\n * to display strings should should load this module by calling var Strings = require(\"strings\").\n * The i18n plugin will dynamically load the strings for the right locale and populate\n * the exports variable. See src\\nls\\strings.js for the master file of English strings.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    module.exports = require(\"i18n!nls/strings\");\n\n});\n"
  },
  {
    "path": "src/extensions/samples/README.md",
    "content": "# Brackets Example Extensions\n\nThis directory contains extensions that should be disabled by default, but\nthat we want to add to the repo. This might include things like examples and\ntest cases.\n\n(<code>README.md</code> also serves as a dummy file so this directory can be added to git.)\n"
  },
  {
    "path": "src/extensions/samples/TypingSpeedLogger/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EditorManager   = brackets.getModule(\"editor/EditorManager\"),\n        PerfUtils       = brackets.getModule(\"utils/PerfUtils\");\n\n    // https://paulirish.com/2011/requestanimationframe-for-smart-animating/\n    // shim layer with setTimeout fallback\n    var requestAnimFrame = (function () {\n        return window.requestAnimationFrame    ||\n            window.webkitRequestAnimationFrame ||\n            window.mozRequestAnimationFrame    ||\n            window.oRequestAnimationFrame      ||\n            window.msRequestAnimationFrame     ||\n            function (callback) {\n                window.setTimeout(callback, 1000 / 60);\n            };\n    }());\n\n    var STRING_FIRSTPAINT        = \"Typing Speed: First repaint\",\n        STRING_PAINTBEFORECHANGE = \"Typing Speed: Paint before DOM update\",\n        STRING_ONCHANGE          = \"Typing Speed: DOM update complete\",\n        STRING_PAINTAFTERCHANGE  = \"Typing Speed: Paint after DOM update\";\n\n    function _getInputField(editor) {\n        return editor._codeMirror.getInputField();\n    }\n\n    /**\n     * Installs input event handler on the current editor (full or inline).\n     */\n    function initTypingSpeedLogging() {\n        var editor = null,\n            inputField = null,\n            inProgress = false;\n\n        var inputChangedHandler = function () {\n            // CodeMirror's fastPoll will batch up input events into a consolidated change\n            if (inProgress) {\n                return;\n            }\n\n            inProgress = true;\n\n            // use a single markStart call so all start times are the same\n            PerfUtils.markStart([\n                STRING_FIRSTPAINT,\n                STRING_PAINTBEFORECHANGE,\n                STRING_ONCHANGE,\n                STRING_PAINTAFTERCHANGE\n            ]);\n\n            var repaintBeforeChangeHandler = function () {\n                if (PerfUtils.isActive(STRING_FIRSTPAINT)) {\n                    PerfUtils.addMeasurement(STRING_FIRSTPAINT);\n                }\n\n                if (PerfUtils.isActive(STRING_ONCHANGE)) {\n                    // don't know which paint event will be the last one,\n                    // so keep updating measurement until we hit onChange\n                    PerfUtils.updateMeasurement(STRING_PAINTBEFORECHANGE);\n                    requestAnimFrame(repaintBeforeChangeHandler);\n                }\n            };\n\n            var repaintAfterChangeHandler = function () {\n                PerfUtils.addMeasurement(STRING_PAINTAFTERCHANGE);\n\n                // need to tell PerfUtils that we are done updating this measurement\n                PerfUtils.finalizeMeasurement(STRING_PAINTBEFORECHANGE);\n\n                inProgress = false;\n            };\n\n            var onChangeHandler = function (event, editor, change) {\n                PerfUtils.addMeasurement(STRING_ONCHANGE);\n                editor.off(\"change.typingSpeedLogger\", onChangeHandler);\n\n                requestAnimFrame(repaintAfterChangeHandler);\n            };\n\n            requestAnimFrame(repaintBeforeChangeHandler);\n            editor.on(\"change.typingSpeedLogger\", onChangeHandler);\n        };\n\n        var updateFocusedEditor = function (focusedEditor) {\n            if (editor) {\n                inputField.removeEventListener(\"input\", inputChangedHandler, true);\n            }\n\n            if (focusedEditor) {\n                editor = focusedEditor;\n                inputField = _getInputField(focusedEditor);\n\n                // Listen for input changes in the capture phase, before\n                // CodeMirror's event handling.\n                inputField.addEventListener(\"input\", inputChangedHandler, true);\n            }\n        };\n\n        EditorManager.on(\"activeEditorChange\", function (event, focusedEditor) {\n            updateFocusedEditor(focusedEditor);\n        });\n        updateFocusedEditor(EditorManager.getFocusedEditor());\n    }\n\n    (function () {\n        initTypingSpeedLogging();\n    }());\n});\n"
  },
  {
    "path": "src/extensions/samples/circular_dependency_test/main.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    console.log(\"loading foo!\");\n\n    require(\"secondary\").bar();\n\n    exports.bar = function bar() {\n        console.log(\"in bar in foo!\");\n    };\n\n});\n"
  },
  {
    "path": "src/extensions/samples/circular_dependency_test/secondary.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    console.log(\"and a file that foo depends on!\");\n\n    exports.bar = function bar() {\n        console.log(\"in bar in secondary!\");\n        window.setTimeout(function () { require(\"main\").bar(); }, 300);\n    };\n\n});\n"
  },
  {
    "path": "src/features/FindReferencesManager.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit                     = require(\"utils/AppInit\"),\n        CommandManager              = require(\"command/CommandManager\"),\n        MainViewManager             = require(\"view/MainViewManager\"),\n        LanguageManager             = require(\"language/LanguageManager\"),\n        DocumentManager             = require(\"document/DocumentManager\"),\n        Commands                    = require(\"command/Commands\"),\n        EditorManager               = require(\"editor/EditorManager\"),\n        ProjectManager              = require(\"project/ProjectManager\"),\n        ProviderRegistrationHandler = require(\"features/PriorityBasedRegistration\").RegistrationHandler,\n        SearchResultsView           = require(\"search/SearchResultsView\").SearchResultsView,\n        SearchModel                 = require(\"search/SearchModel\").SearchModel,\n        Strings                     = require(\"strings\");\n\n    var _providerRegistrationHandler = new ProviderRegistrationHandler(),\n        registerFindReferencesProvider = _providerRegistrationHandler.registerProvider.bind(\n            _providerRegistrationHandler\n        ),\n        removeFindReferencesProvider = _providerRegistrationHandler.removeProvider.bind(_providerRegistrationHandler);\n\n    var searchModel = new SearchModel(),\n        _resultsView;\n\n    function _getReferences(provider, hostEditor, pos) {\n        var result = new $.Deferred();\n\n        if(!provider) {\n            return result.reject();\n        }\n\n        provider.getReferences(hostEditor, pos)\n            .done(function (rcvdObj) {\n\n                searchModel.results = rcvdObj.results;\n                searchModel.numFiles = rcvdObj.numFiles;\n                searchModel.numMatches = rcvdObj.numMatches;\n                searchModel.allResultsAvailable = true;\n                searchModel.setQueryInfo({query: rcvdObj.queryInfo, caseSensitive: true, isRegExp: false});\n                result.resolve();\n            }).fail(function (){\n                result.reject();\n            });\n        return result.promise();\n\n    }\n\n    function _openReferencesPanel() {\n        var editor = EditorManager.getActiveEditor(),\n            pos = editor ? editor.getCursorPos() : null,\n            referencesPromise,\n            result = new $.Deferred(),\n            errorMsg = Strings.REFERENCES_NO_RESULTS,\n            referencesProvider;\n\n        var language = editor.getLanguageForSelection(),\n            enabledProviders = _providerRegistrationHandler.getProvidersForLanguageId(language.getId());\n\n        enabledProviders.some(function (item, index) {\n            if (item.provider.hasReferences(editor)) {\n                referencesProvider = item.provider;\n                return true;\n            }\n        });\n\n        referencesPromise = _getReferences(referencesProvider, editor, pos);\n\n        // If one of them will provide a widget, show it inline once ready\n        if (referencesPromise) {\n            referencesPromise.done(function () {\n                if(_resultsView) {\n                    _resultsView.open();\n                }\n            }).fail(function () {\n                if(_resultsView) {\n                    _resultsView.close();\n                }\n                editor.displayErrorMessageAtCursor(errorMsg);\n                result.reject();\n            });\n        } else {\n            if(_resultsView) {\n                _resultsView.close();\n            }\n            editor.displayErrorMessageAtCursor(errorMsg);\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Clears any previous search information, removing update listeners and clearing the model.\n     */\n    function _clearSearch() {\n        searchModel.clear();\n    }\n\n    /**\n     * @public\n     * Closes the references panel\n     */\n    function closeReferencesPanel() {\n        if (_resultsView) {\n            _resultsView.close();\n        }\n    }\n    \n    function setMenuItemStateForLanguage(languageId) {\n        CommandManager.get(Commands.CMD_FIND_ALL_REFERENCES).setEnabled(false);\n        if (!languageId) {\n            var editor = EditorManager.getActiveEditor();\n            if (editor) {\n                languageId = LanguageManager.getLanguageForPath(editor.document.file._path).getId();\n            }\n        }\n        var enabledProviders = _providerRegistrationHandler.getProvidersForLanguageId(languageId),\n            referencesProvider;\n\n        enabledProviders.some(function (item, index) {\n            if (item.provider.hasReferences()) {\n                referencesProvider = item.provider;\n                return true;\n            }\n        });\n        if (referencesProvider) {\n            CommandManager.get(Commands.CMD_FIND_ALL_REFERENCES).setEnabled(true);\n        }\n\n    }\n\n    MainViewManager.on(\"currentFileChange\", function (event, newFile, newPaneId, oldFile, oldPaneId) {\n        if (!newFile) {\n            CommandManager.get(Commands.CMD_FIND_ALL_REFERENCES).setEnabled(false);\n            return;\n        }\n\n        var newFilePath = newFile.fullPath,\n            newLanguageId = LanguageManager.getLanguageForPath(newFilePath).getId();\n        setMenuItemStateForLanguage(newLanguageId);\n\n        DocumentManager.getDocumentForPath(newFilePath)\n            .done(function (newDoc) {\n                newDoc.on(\"languageChanged.reference-in-files\", function () {\n                    var changedLanguageId = LanguageManager.getLanguageForPath(newDoc.file.fullPath).getId();\n                    setMenuItemStateForLanguage(changedLanguageId);\n                });\n            });\n\n        if (!oldFile) {\n            return;\n        }\n\n        var oldFilePath = oldFile.fullPath;\n        DocumentManager.getDocumentForPath(oldFilePath)\n            .done(function (oldDoc) {\n                oldDoc.off(\"languageChanged.reference-in-files\");\n            });\n    });\n\n    AppInit.htmlReady(function () {\n        _resultsView = new SearchResultsView(\n            searchModel,\n            \"reference-in-files-results\",\n            \"reference-in-files.results\",\n            \"reference\"\n        );\n        if(_resultsView) {\n            _resultsView\n                .on(\"close\", function () {\n                    _clearSearch();\n                })\n                .on(\"getNextPage\", function () {\n                    if (searchModel.hasResults()) {\n                        _resultsView.showNextPage();\n                    }\n                })\n                .on(\"getLastPage\", function () {\n                    if (searchModel.hasResults()) {\n                        _resultsView.showLastPage();\n                    }\n                });\n        }\n    });\n\n    // Initialize: register listeners\n    ProjectManager.on(\"beforeProjectClose\", function () { if (_resultsView) { _resultsView.close(); } });\n\n    CommandManager.register(Strings.FIND_ALL_REFERENCES, Commands.CMD_FIND_ALL_REFERENCES, _openReferencesPanel);\n    CommandManager.get(Commands.CMD_FIND_ALL_REFERENCES).setEnabled(false);\n\n    exports.registerFindReferencesProvider    = registerFindReferencesProvider;\n    exports.removeFindReferencesProvider      = removeFindReferencesProvider;\n    exports.setMenuItemStateForLanguage       = setMenuItemStateForLanguage;\n    exports.closeReferencesPanel              = closeReferencesPanel;\n});\n"
  },
  {
    "path": "src/features/JumpToDefManager.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Commands = require(\"command/Commands\"),\n        Strings = require(\"strings\"),\n        AppInit = require(\"utils/AppInit\"),\n        CommandManager = require(\"command/CommandManager\"),\n        EditorManager = require(\"editor/EditorManager\"),\n        ProviderRegistrationHandler = require(\"features/PriorityBasedRegistration\").RegistrationHandler;\n\n    var _providerRegistrationHandler = new ProviderRegistrationHandler(),\n        registerJumpToDefProvider = _providerRegistrationHandler.registerProvider.bind(_providerRegistrationHandler),\n        removeJumpToDefProvider = _providerRegistrationHandler.removeProvider.bind(_providerRegistrationHandler);\n\n\n    /**\n     * Asynchronously asks providers to handle jump-to-definition.\n     * @return {!Promise} Resolved when the provider signals that it's done; rejected if no\n     * provider responded or the provider that responded failed.\n     */\n    function _doJumpToDef() {\n        var request = null,\n            result = new $.Deferred(),\n            jumpToDefProvider = null,\n            editor = EditorManager.getActiveEditor();\n\n        if (editor) {\n            // Find a suitable provider, if any\n            var language = editor.getLanguageForSelection(),\n                enabledProviders = _providerRegistrationHandler.getProvidersForLanguageId(language.getId());\n\n\n            enabledProviders.some(function (item, index) {\n                if (item.provider.canJumpToDef(editor)) {\n                    jumpToDefProvider = item.provider;\n                    return true;\n                }\n            });\n\n            if (jumpToDefProvider) {\n                request = jumpToDefProvider.doJumpToDef(editor);\n\n                if (request) {\n                    request.done(function () {\n                        result.resolve();\n                    }).fail(function () {\n                        result.reject();\n                    });\n                } else {\n                    result.reject();\n                }\n            } else {\n                result.reject();\n            }\n        } else {\n            result.reject();\n        }\n\n        return result.promise();\n    }\n\n    CommandManager.register(Strings.CMD_JUMPTO_DEFINITION, Commands.NAVIGATE_JUMPTO_DEFINITION, _doJumpToDef);\n\n    exports.registerJumpToDefProvider = registerJumpToDefProvider;\n    exports.removeJumpToDefProvider = removeJumpToDefProvider;\n});\n"
  },
  {
    "path": "src/features/ParameterHintsManager.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* eslint max-len: [\"error\", { \"code\": 200 }]*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var Commands = require(\"command/Commands\"),\n        AppInit = require(\"utils/AppInit\"),\n        CommandManager = require(\"command/CommandManager\"),\n        EditorManager = require(\"editor/EditorManager\"),\n        Menus = require(\"command/Menus\"),\n        KeyEvent = require(\"utils/KeyEvent\"),\n        Strings = require(\"strings\"),\n        ProviderRegistrationHandler = require(\"features/PriorityBasedRegistration\").RegistrationHandler;\n\n\n    /** @const {string} Show Function Hint command ID */\n    var SHOW_PARAMETER_HINT_CMD_ID = \"showParameterHint\", // string must MATCH string in native code (brackets_extensions)\n        hintContainerHTML = require(\"text!htmlContent/parameter-hint-template.html\"),\n        KeyboardPrefs = {\n            \"showParameterHint\": [\n                {\n                    \"key\": \"Ctrl-Shift-Space\"\n                },\n                {\n                    \"key\": \"Ctrl-Shift-Space\",\n                    \"platform\": \"mac\"\n                }\n            ]\n        };\n\n    var $hintContainer, // function hint container\n        $hintContent, // function hint content holder\n        hintState = {},\n        lastChar = null,\n        sessionEditor = null,\n        keyDownEditor = null;\n\n    // Constants\n    var POINTER_TOP_OFFSET = 4, // Size of margin + border of hint.\n        POSITION_BELOW_OFFSET = 4; // Amount to adjust to top position when the preview bubble is below the text\n\n    // keep jslint from complaining about handleCursorActivity being used before\n    // it was defined.\n    var handleCursorActivity;\n\n    var _providerRegistrationHandler = new ProviderRegistrationHandler(),\n        registerHintProvider = _providerRegistrationHandler.registerProvider.bind(_providerRegistrationHandler),\n        removeHintProvider = _providerRegistrationHandler.removeProvider.bind(_providerRegistrationHandler);\n\n    /**\n     * Position a function hint.\n     *\n     * @param {number} xpos\n     * @param {number} ypos\n     * @param {number} ybot\n     */\n    function positionHint(xpos, ypos, ybot) {\n        var hintWidth = $hintContainer.width(),\n            hintHeight = $hintContainer.height(),\n            top = ypos - hintHeight - POINTER_TOP_OFFSET,\n            left = xpos,\n            $editorHolder = $(\"#editor-holder\"),\n            editorLeft;\n\n        if ($editorHolder.offset() === undefined) {\n            // this happens in jasmine tests that run\n            // without a windowed document.\n            return;\n        }\n\n        editorLeft = $editorHolder.offset().left;\n        left = Math.max(left, editorLeft);\n        left = Math.min(left, editorLeft + $editorHolder.width() - hintWidth);\n\n        if (top < 0) {\n            $hintContainer.removeClass(\"preview-bubble-above\");\n            $hintContainer.addClass(\"preview-bubble-below\");\n            top = ybot + POSITION_BELOW_OFFSET;\n            $hintContainer.offset({\n                left: left,\n                top: top\n            });\n        } else {\n            $hintContainer.removeClass(\"preview-bubble-below\");\n            $hintContainer.addClass(\"preview-bubble-above\");\n            $hintContainer.offset({\n                left: left,\n                top: top - POINTER_TOP_OFFSET\n            });\n        }\n    }\n\n    /**\n     * Format the given parameter array. Handles separators between\n     * parameters, syntax for optional parameters, and the order of the\n     * parameter type and parameter name.\n     *\n     * @param {!Array.<{name: string, type: string, isOptional: boolean}>} params -\n     * array of parameter descriptors\n     * @param {function(string)=} appendSeparators - callback function to append separators.\n     * The separator is passed to the callback.\n     * @param {function(string, number)=} appendParameter - callback function to append parameter.\n     * The formatted parameter type and name is passed to the callback along with the\n     * current index of the parameter.\n     * @param {boolean=} typesOnly - only show parameter types. The\n     * default behavior is to include both parameter names and types.\n     * @return {string} - formatted parameter hint\n     */\n    function _formatParameterHint(params, appendSeparators, appendParameter, typesOnly) {\n        var result = \"\",\n            pendingOptional = false;\n\n        appendParameter(\"(\", \"\", -1);\n        params.forEach(function (value, i) {\n            var param = value.label || value.type,\n                documentation = value.documentation,\n                separators = \"\";\n\n            if (value.isOptional) {\n                // if an optional param is following by an optional parameter, then\n                // terminate the bracket. Otherwise enclose a required parameter\n                // in the same bracket.\n                if (pendingOptional) {\n                    separators += \"]\";\n                }\n\n                pendingOptional = true;\n            }\n\n            if (i > 0) {\n                separators += \", \";\n            }\n\n            if (value.isOptional) {\n                separators += \"[\";\n            }\n\n            if (appendSeparators) {\n                appendSeparators(separators);\n            }\n\n            result += separators;\n\n            if (!typesOnly && value.name) {\n                param += \" \" + value.name;\n            }\n\n            if (appendParameter) {\n                appendParameter(param, documentation, i);\n            }\n\n            result += param;\n\n        });\n\n        if (pendingOptional) {\n            if (appendSeparators) {\n                appendSeparators(\"]\");\n            }\n\n            result += \"]\";\n        }\n        appendParameter(\")\", \"\", -1);\n\n        return result;\n    }\n\n    /**\n     *  Bold the parameter at the caret.\n     *\n     *  @param {{inFunctionCall: boolean, functionCallPos: {line: number, ch: number}}} functionInfo -\n     *  tells if the caret is in a function call and the position\n     *  of the function call.\n     */\n    function formatHint(hints) {\n        $hintContent.empty();\n        $hintContent.addClass(\"brackets-hints\");\n\n        function appendSeparators(separators) {\n            $hintContent.append(separators);\n        }\n\n        function appendParameter(param, documentation, index) {\n            if (hints.currentIndex === index) {\n                $hintContent.append($(\"<span>\")\n                    .append(_.escape(param))\n                    .addClass(\"current-parameter\"));\n            } else {\n                $hintContent.append($(\"<span>\")\n                    .append(_.escape(param))\n                    .addClass(\"parameter\"));\n            }\n        }\n\n        if (hints.parameters.length > 0) {\n            _formatParameterHint(hints.parameters, appendSeparators, appendParameter);\n        } else {\n            $hintContent.append(_.escape(Strings.NO_ARGUMENTS));\n        }\n    }\n\n    /**\n     * Dismiss the function hint.\n     *\n     */\n    function dismissHint(editor) {\n        if (hintState.visible) {\n            $hintContainer.hide();\n            $hintContent.empty();\n            hintState = {};\n\n            if (editor) {\n                editor.off(\"cursorActivity.ParameterHinting\", handleCursorActivity);\n                sessionEditor = null;\n            } else if (sessionEditor) {\n                sessionEditor.off(\"cursorActivity.ParameterHinting\", handleCursorActivity);\n                sessionEditor = null;\n            }\n        }\n    }\n\n    /**\n     * Pop up a function hint on the line above the caret position.\n     *\n     * @param {object=} editor - current Active Editor\n     * @param {boolean} True if hints are invoked through cursor activity.\n     * @return {jQuery.Promise} - The promise will not complete until the\n     *      hint has completed. Returns null, if the function hint is already\n     *      displayed or there is no function hint at the cursor.\n     *\n     */\n    function popUpHint(editor, explicit, onCursorActivity) {\n        var request = null;\n        var $deferredPopUp = $.Deferred();\n        var sessionProvider = null;\n\n        dismissHint(editor);\n        // Find a suitable provider, if any\n        var language = editor.getLanguageForSelection(),\n            enabledProviders = _providerRegistrationHandler.getProvidersForLanguageId(language.getId());\n\n        enabledProviders.some(function (item, index) {\n            if (item.provider.hasParameterHints(editor, lastChar)) {\n                sessionProvider = item.provider;\n                return true;\n            }\n        });\n\n        if (sessionProvider) {\n            request = sessionProvider.getParameterHints(explicit, onCursorActivity);\n        }\n\n        if (request) {\n            request.done(function (parameterHint) {\n                var cm = editor._codeMirror,\n                    pos = parameterHint.functionCallPos || editor.getCursorPos();\n\n                pos = cm.charCoords(pos);\n                formatHint(parameterHint);\n\n                $hintContainer.show();\n                positionHint(pos.left, pos.top, pos.bottom);\n                hintState.visible = true;\n\n                sessionEditor = editor;\n                editor.on(\"cursorActivity.ParameterHinting\", handleCursorActivity);\n                $deferredPopUp.resolveWith(null);\n            }).fail(function () {\n                hintState = {};\n            });\n        }\n\n        return $deferredPopUp;\n    }\n\n    /**\n     *  Show the parameter the cursor is on in bold when the cursor moves.\n     *  Dismiss the pop up when the cursor moves off the function.\n     */\n    handleCursorActivity = function (event, editor) {\n        if (editor) {\n            popUpHint(editor, false, true);\n        } else {\n            dismissHint();\n        }\n    };\n\n    /**\n     * Install function hint listeners.\n     *\n     * @param {Editor} editor - editor context on which to listen for\n     *      changes\n     */\n    function installListeners(editor) {\n        editor.on(\"keydown.ParameterHinting\", function (event, editor, domEvent) {\n                if (domEvent.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                    dismissHint(editor);\n                }\n            }).on(\"scroll.ParameterHinting\", function () {\n                dismissHint(editor);\n            })\n            .on(\"editorChange.ParameterHinting\", _handleChange)\n            .on(\"keypress.ParameterHinting\", _handleKeypressEvent);\n    }\n\n    /**\n     * Clean up after installListeners()\n     * @param {!Editor} editor\n     */\n    function uninstallListeners(editor) {\n        editor.off(\".ParameterHinting\");\n    }\n\n    function _handleKeypressEvent(jqEvent, editor, event) {\n        keyDownEditor = editor;\n        // Last inserted character, used later by handleChange\n        lastChar = String.fromCharCode(event.charCode);\n    }\n\n    /**\n     * Start a new implicit hinting session, or update the existing hint list.\n     * Called by the editor after handleKeyEvent, which is responsible for setting\n     * the lastChar.\n     *\n     * @param {Event} event\n     * @param {Editor} editor\n     * @param {{from: Pos, to: Pos, text: Array, origin: string}} changeList\n     */\n    function _handleChange(event, editor, changeList) {\n        if (lastChar && (lastChar === '(' || lastChar === ',') && editor === keyDownEditor) {\n            keyDownEditor = null;\n            popUpHint(editor);\n        }\n    }\n\n    function activeEditorChangeHandler(event, current, previous) {\n\n        if (previous) {\n            //Removing all old Handlers\n            previous.document\n                .off(\"languageChanged.ParameterHinting\");\n            uninstallListeners(previous);\n        }\n\n        if (current) {\n            current.document\n                .on(\"languageChanged.ParameterHinting\", function () {\n                    // If current doc's language changed, reset our state by treating it as if the user switched to a\n                    // different document altogether\n                    uninstallListeners(current);\n                    installListeners(current);\n                });\n            installListeners(current);\n        }\n    }\n\n    /**\n     * Show a parameter hint in its own pop-up.\n     *\n     */\n    function handleShowParameterHint() {\n        var editor = EditorManager.getActiveEditor();\n        // Pop up function hint\n        popUpHint(editor, true, false);\n    }\n\n    AppInit.appReady(function () {\n        CommandManager.register(Strings.CMD_SHOW_PARAMETER_HINT, SHOW_PARAMETER_HINT_CMD_ID, handleShowParameterHint);\n\n        // Add the menu items\n        var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);\n        if (menu) {\n            menu.addMenuItem(SHOW_PARAMETER_HINT_CMD_ID, KeyboardPrefs.showParameterHint, Menus.AFTER, Commands.SHOW_CODE_HINTS);\n        }\n        // Create the function hint container\n        $hintContainer = $(hintContainerHTML).appendTo($(\"body\"));\n        $hintContent = $hintContainer.find(\".function-hint-content-new\");\n        activeEditorChangeHandler(null, EditorManager.getActiveEditor(), null);\n\n        EditorManager.on(\"activeEditorChange\", activeEditorChangeHandler);\n\n        CommandManager.on(\"beforeExecuteCommand\", function (event, commandId) {\n            if (commandId !== SHOW_PARAMETER_HINT_CMD_ID &&\n                commandId !== Commands.SHOW_CODE_HINTS) {\n                dismissHint();\n            }\n        });\n    });\n\n    exports.registerHintProvider = registerHintProvider;\n    exports.removeHintProvider = removeHintProvider;\n});\n"
  },
  {
    "path": "src/features/PriorityBasedRegistration.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* eslint-disable indent */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var PreferencesManager = require(\"preferences/PreferencesManager\");\n\n    /**\n     * Comparator to sort providers from high to low priority\n     */\n    function _providerSort(a, b) {\n        return b.priority - a.priority;\n    }\n\n\n    function RegistrationHandler() {\n        this._providers = {\n            \"all\": []\n        };\n    }\n\n    /**\n     * The method by which a Provider registers its willingness to\n     * providing tooling feature for editors in a given language.\n     *\n     * @param {!Provider} provider\n     * The provider to be registered, described below.\n     *\n     * @param {!Array.<string>} languageIds\n     * The set of language ids for which the provider is capable of\n     * providing tooling feature. If the special language id name \"all\" is included then\n     * the provider may be called for any language.\n     *\n     * @param {?number} priority\n     * Used to break ties among providers for a particular language.\n     * Providers with a higher number will be asked for tooling before those\n     * with a lower priority value. Defaults to zero.\n     */\n    RegistrationHandler.prototype.registerProvider = function (providerInfo, languageIds, priority) {\n        var providerObj = {\n                provider: providerInfo,\n                priority: priority || 0\n            },\n            self = this;\n\n        if (languageIds.indexOf(\"all\") !== -1) {\n            // Ignore anything else in languageIds and just register for every language. This includes\n            // the special \"all\" language since its key is in the hintProviders map from the beginning.\n            var languageId;\n            for (languageId in self._providers) {\n                if (self._providers.hasOwnProperty(languageId)) {\n                    self._providers[languageId].push(providerObj);\n                    self._providers[languageId].sort(_providerSort);\n                }\n            }\n        } else {\n            languageIds.forEach(function (languageId) {\n                if (!self._providers[languageId]) {\n                    // Initialize provider list with any existing all-language providers\n                    self._providers[languageId] = Array.prototype.concat(self._providers.all);\n                }\n                self._providers[languageId].push(providerObj);\n                self._providers[languageId].sort(_providerSort);\n            });\n        }\n    };\n\n    /**\n     * Remove a code hint provider\n     * @param {!CodeHintProvider} provider Code hint provider to remove\n     * @param {(string|Array.<string>)=} targetLanguageId Optional set of\n     *     language IDs for languages to remove the provider for. Defaults\n     *     to all languages.\n     */\n    RegistrationHandler.prototype.removeProvider = function (provider, targetLanguageId) {\n        var index,\n            providers,\n            targetLanguageIdArr,\n            self = this;\n\n        if (Array.isArray(targetLanguageId)) {\n            targetLanguageIdArr = targetLanguageId;\n        } else if (targetLanguageId) {\n            targetLanguageIdArr = [targetLanguageId];\n        } else {\n            targetLanguageIdArr = Object.keys(self._providers);\n        }\n\n        targetLanguageIdArr.forEach(function (languageId) {\n            providers = self._providers[languageId];\n\n            for (index = 0; index < providers.length; index++) {\n                if (providers[index].provider === provider) {\n                    providers.splice(index, 1);\n                    break;\n                }\n            }\n        });\n    };\n\n\n    RegistrationHandler.prototype.getProvidersForLanguageId = function (languageId) {\n        var providers = this._providers[languageId] || this._providers.all;\n\n        // Exclude providers that are explicitly disabled in the preferences.\n        // All providers that do not have their constructor\n        // names listed in the preferences are enabled by default.\n        return providers.filter(function (provider) {\n            var prefKey = \"tooling.\" + provider.provider.constructor.name;\n            return PreferencesManager.get(prefKey) !== false;\n        });\n    };\n\n\n    exports.RegistrationHandler = RegistrationHandler;\n});\n"
  },
  {
    "path": "src/file/FileUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*global unescape */\n\n/**\n * Set of utilities for working with files and text content.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var FileSystemError     = require(\"filesystem/FileSystemError\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\");\n\n    // These will be loaded asynchronously\n    var DocumentCommandHandlers, LiveDevelopmentUtils;\n\n    /**\n     * @const {Number} Maximium file size (in megabytes)\n     *   (for display strings)\n     *   This must be a hard-coded value since this value\n     *   tells how low-level APIs should behave which cannot\n     *   have a load order dependency on preferences manager\n     */\n    var MAX_FILE_SIZE_MB = 16;\n\n    /**\n     * @const {Number} Maximium file size (in bytes)\n     *   This must be a hard-coded value since this value\n     *   tells how low-level APIs should behave which cannot\n     *   have a load order dependency on preferences manager\n     */\n    var MAX_FILE_SIZE = MAX_FILE_SIZE_MB * 1024 * 1024;\n\n    /**\n     * @const {List} list of File Extensions which will be opened in external Application\n     */\n    var extListToBeOpenedInExtApp = [];\n\n\n    /**\n     * Asynchronously reads a file as UTF-8 encoded text.\n     * @param {!File} file File to read\n     * @return {$.Promise} a jQuery promise that will be resolved with the\n     *  file's text content plus its timestamp, or rejected with a FileSystemError string\n     *  constant if the file can not be read.\n     */\n    function readAsText(file) {\n        var result = new $.Deferred();\n\n        // Measure performance\n        var perfTimerName = PerfUtils.markStart(\"readAsText:\\t\" + file.fullPath);\n        result.always(function () {\n            PerfUtils.addMeasurement(perfTimerName);\n        });\n\n        // Read file\n        file.read(function (err, data, encoding, stat) {\n            if (!err) {\n                result.resolve(data, stat.mtime);\n            } else {\n                result.reject(err);\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Asynchronously writes a file as UTF-8 encoded text.\n     * @param {!File} file File to write\n     * @param {!string} text\n     * @param {boolean=} allowBlindWrite Indicates whether or not CONTENTS_MODIFIED\n     *      errors---which can be triggered if the actual file contents differ from\n     *      the FileSystem's last-known contents---should be ignored.\n     * @return {$.Promise} a jQuery promise that will be resolved when\n     * file writing completes, or rejected with a FileSystemError string constant.\n     */\n    function writeText(file, text, allowBlindWrite) {\n        var result = new $.Deferred(),\n            options = {};\n\n        if (allowBlindWrite) {\n            options.blind = true;\n        }\n\n        file.write(text, options, function (err) {\n            if (!err) {\n                result.resolve();\n            } else {\n                result.reject(err);\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Line endings\n     * @enum {string}\n     */\n    var LINE_ENDINGS_CRLF = \"CRLF\",\n        LINE_ENDINGS_LF   = \"LF\";\n\n    /**\n     * Returns the standard line endings for the current platform\n     * @return {LINE_ENDINGS_CRLF|LINE_ENDINGS_LF}\n     */\n    function getPlatformLineEndings() {\n        return brackets.platform === \"win\" ? LINE_ENDINGS_CRLF : LINE_ENDINGS_LF;\n    }\n\n    /**\n     * Scans the first 1000 chars of the text to determine how it encodes line endings. Returns\n     * null if usage is mixed or if no line endings found.\n     * @param {!string} text\n     * @return {null|LINE_ENDINGS_CRLF|LINE_ENDINGS_LF}\n     */\n    function sniffLineEndings(text) {\n        var subset = text.substr(0, 1000);  // (length is clipped to text.length)\n        var hasCRLF = /\\r\\n/.test(subset);\n        var hasLF = /[^\\r]\\n/.test(subset);\n\n        if ((hasCRLF && hasLF) || (!hasCRLF && !hasLF)) {\n            return null;\n        } else {\n            return hasCRLF ? LINE_ENDINGS_CRLF : LINE_ENDINGS_LF;\n        }\n    }\n\n    /**\n     * Translates any line ending types in the given text to the be the single form specified\n     * @param {!string} text\n     * @param {null|LINE_ENDINGS_CRLF|LINE_ENDINGS_LF} lineEndings\n     * @return {string}\n     */\n    function translateLineEndings(text, lineEndings) {\n        if (lineEndings !== LINE_ENDINGS_CRLF && lineEndings !== LINE_ENDINGS_LF) {\n            lineEndings = getPlatformLineEndings();\n        }\n\n        var eolStr = (lineEndings === LINE_ENDINGS_CRLF ? \"\\r\\n\" : \"\\n\");\n        var findAnyEol = /\\r\\n|\\r|\\n/g;\n\n        return text.replace(findAnyEol, eolStr);\n    }\n\n    /**\n     * @param {!FileSystemError} name\n     * @return {!string} User-friendly, localized error message\n     */\n    function getFileErrorString(name) {\n        // There are a few error codes that we have specific error messages for. The rest are\n        // displayed with a generic \"(error N)\" message.\n        var result;\n\n        if (name === FileSystemError.NOT_FOUND) {\n            result = Strings.NOT_FOUND_ERR;\n        } else if (name === FileSystemError.NOT_READABLE) {\n            result = Strings.NOT_READABLE_ERR;\n        } else if (name === FileSystemError.NOT_WRITABLE) {\n            result = Strings.NO_MODIFICATION_ALLOWED_ERR_FILE;\n        } else if (name === FileSystemError.CONTENTS_MODIFIED) {\n            result = Strings.CONTENTS_MODIFIED_ERR;\n        } else if (name === FileSystemError.UNSUPPORTED_ENCODING) {\n            result = Strings.UNSUPPORTED_ENCODING_ERR;\n        } else if (name === FileSystemError.EXCEEDS_MAX_FILE_SIZE) {\n            result = StringUtils.format(Strings.EXCEEDS_MAX_FILE_SIZE, MAX_FILE_SIZE_MB);\n        } else if (name === FileSystemError.ENCODE_FILE_FAILED) {\n            result = Strings.ENCODE_FILE_FAILED_ERR;\n        } else if (name === FileSystemError.DECODE_FILE_FAILED) {\n            result = Strings.DECODE_FILE_FAILED_ERR;\n        } else if (name === FileSystemError.UNSUPPORTED_UTF16_ENCODING) {\n            result = Strings.UNSUPPORTED_UTF16_ENCODING_ERR;\n        } else {\n            result = StringUtils.format(Strings.GENERIC_ERROR, name);\n        }\n\n        return result;\n    }\n\n    /**\n     * Shows an error dialog indicating that the given file could not be opened due to the given error\n     * @deprecated Use DocumentCommandHandlers.showFileOpenError() instead\n     *\n     * @param {!FileSystemError} name\n     * @return {!Dialog}\n     */\n    function showFileOpenError(name, path) {\n        DeprecationWarning.deprecationWarning(\"FileUtils.showFileOpenError() has been deprecated. \" +\n                                              \"Please use DocumentCommandHandlers.showFileOpenError() instead.\");\n        return DocumentCommandHandlers.showFileOpenError(name, path);\n    }\n\n    /**\n     * Creates an HTML string for a list of files to be reported on, suitable for use in a dialog.\n     * @param {Array.<string>} Array of filenames or paths to display.\n     */\n    function makeDialogFileList(paths) {\n        var result = \"<ul class='dialog-list'>\";\n        paths.forEach(function (path) {\n            result += \"<li><span class='dialog-filename'>\";\n            result += StringUtils.breakableUrl(path);\n            result += \"</span></li>\";\n        });\n        result += \"</ul>\";\n        return result;\n    }\n\n    /**\n     * Convert a URI path to a native path.\n     * On both platforms, this unescapes the URI\n     * On windows, URI paths start with a \"/\", but have a drive letter (\"C:\"). In this\n     * case, remove the initial \"/\".\n     * @param {!string} path\n     * @return {string}\n     */\n    function convertToNativePath(path) {\n        path = unescape(path);\n        if (path.indexOf(\":\") !== -1 && path[0] === \"/\") {\n            return path.substr(1);\n        }\n\n        return path;\n    }\n\n    /**\n     * Convert a Windows-native path to use Unix style slashes.\n     * On Windows, this converts \"C:\\foo\\bar\\baz.txt\" to \"C:/foo/bar/baz.txt\".\n     * On Mac, this does nothing, since Mac paths are already in Unix syntax.\n     * (Note that this does not add an initial forward-slash. Internally, our\n     * APIs generally use the \"C:/foo/bar/baz.txt\" style for \"native\" paths.)\n     * @param {string} path A native-style path.\n     * @return {string} A Unix-style path.\n     */\n    function convertWindowsPathToUnixPath(path) {\n        if (brackets.platform === \"win\") {\n            path = path.replace(/\\\\/g, \"/\");\n        }\n        return path;\n    }\n\n    /**\n     * Removes the trailing slash from a path, if it has one.\n     * Warning: this differs from the format of most paths used in Brackets! Use paths ending in \"/\"\n     * normally, as this is the format used by Directory.fullPath.\n     *\n     * @param {string} path\n     * @return {string}\n     */\n    function stripTrailingSlash(path) {\n        if (path && path[path.length - 1] === \"/\") {\n            return path.slice(0, -1);\n        } else {\n            return path;\n        }\n    }\n\n    /**\n     * Get the name of a file or a directory, removing any preceding path.\n     * @param {string} fullPath full path to a file or directory\n     * @return {string} Returns the base name of a file or the name of a\n     * directory\n     */\n    function getBaseName(fullPath) {\n        var lastSlash = fullPath.lastIndexOf(\"/\");\n        if (lastSlash === fullPath.length - 1) {  // directory: exclude trailing \"/\" too\n            return fullPath.slice(fullPath.lastIndexOf(\"/\", fullPath.length - 2) + 1, -1);\n        } else {\n            return fullPath.slice(lastSlash + 1);\n        }\n    }\n\n    /**\n     * Returns a native absolute path to the 'brackets' source directory.\n     * Note that this only works when run in brackets/src/index.html, so it does\n     * not work for unit tests (which is run from brackets/test/SpecRunner.html)\n     *\n     * WARNING: unlike most paths in Brackets, this path EXCLUDES the trailing \"/\".\n     * @return {string}\n     */\n    function getNativeBracketsDirectoryPath() {\n        var pathname = decodeURI(window.location.pathname);\n        var directory = pathname.substr(0, pathname.lastIndexOf(\"/\"));\n        return convertToNativePath(directory);\n    }\n\n    /**\n     * Given the module object passed to JS module define function,\n     * convert the path to a native absolute path.\n     * Returns a native absolute path to the module folder.\n     *\n     * WARNING: unlike most paths in Brackets, this path EXCLUDES the trailing \"/\".\n     * @return {string}\n     */\n    function getNativeModuleDirectoryPath(module) {\n        var path;\n\n        if (module && module.uri) {\n            path = decodeURI(module.uri);\n\n            // Remove module name and trailing slash from path.\n            path = path.substr(0, path.lastIndexOf(\"/\"));\n        }\n        return path;\n    }\n\n    /**\n     * Get the file extension (excluding \".\") given a path OR a bare filename.\n     * Returns \"\" for names with no extension. If the name starts with \".\", the\n     * full remaining text is considered the extension.\n     *\n     * @param {string} fullPath full path to a file or directory\n     * @return {string} Returns the extension of a filename or empty string if\n     * the argument is a directory or a filename with no extension\n     */\n    function getFileExtension(fullPath) {\n        var baseName = getBaseName(fullPath),\n            idx      = baseName.lastIndexOf(\".\");\n\n        if (idx === -1) {\n            return \"\";\n        }\n\n        return baseName.substr(idx + 1);\n    }\n\n    /**\n     * Get the file extension (excluding \".\") given a path OR a bare filename.\n     * Returns \"\" for names with no extension.\n     * If the only `.` in the file is the first character,\n     * returns \"\" as this is not considered an extension.\n     * This method considers known extensions which include `.` in them.\n     * @deprecated Use LanguageManager.getCompoundFileExtension() instead\n     *\n     * @param {string} fullPath full path to a file or directory\n     * @return {string} Returns the extension of a filename or empty string if\n     * the argument is a directory or a filename with no extension\n     */\n    function getSmartFileExtension(fullPath) {\n        DeprecationWarning.deprecationWarning(\"FileUtils.getSmartFileExtension() has been deprecated. \" +\n                                              \"Please use LanguageManager.getCompoundFileExtension() instead.\");\n        return LanguageManager.getCompoundFileExtension(fullPath);\n    }\n\n    /**\n     * Computes filename as relative to the basePath. For example:\n     * basePath: /foo/bar/, filename: /foo/bar/baz.txt\n     * returns: baz.txt\n     *\n     * The net effect is that the common prefix is stripped away. If basePath is not\n     * a prefix of filename, then undefined is returned.\n     *\n     * @param {string} basePath Path against which we're computing the relative path\n     * @param {string} filename Full path to the file for which we are computing a relative path\n     * @return {string} relative path\n     */\n    function getRelativeFilename(basePath, filename) {\n        if (!filename || filename.substr(0, basePath.length) !== basePath) {\n            return;\n        }\n\n        return filename.substr(basePath.length);\n    }\n\n    /**\n     * Determine if file extension is a static html file extension.\n     * @param {string} filePath could be a path, a file name or just a file extension\n     * @return {boolean} Returns true if fileExt is in the list\n     */\n    function isStaticHtmlFileExt(filePath) {\n        DeprecationWarning.deprecationWarning(\"FileUtils.isStaticHtmlFileExt() has been deprecated. \" +\n                                              \"Please use LiveDevelopmentUtils.isStaticHtmlFileExt() instead.\");\n        return LiveDevelopmentUtils.isStaticHtmlFileExt(filePath);\n    }\n\n    /**\n     * Get the parent directory of a file. If a directory is passed, the SAME directory is returned.\n     * @param {string} fullPath full path to a file or directory\n     * @return {string} Returns the path to the parent directory of a file or the path of a directory,\n     *                  including trailing \"/\"\n     */\n    function getDirectoryPath(fullPath) {\n        return fullPath.substr(0, fullPath.lastIndexOf(\"/\") + 1);\n    }\n\n    /**\n     * Get the parent folder of the given file/folder path. Differs from getDirectoryPath() when 'fullPath'\n     * is a directory itself: returns its parent instead of the original path. (Note: if you already have a\n     * FileSystemEntry, it's faster to use entry.parentPath instead).\n     * @param {string} fullPath full path to a file or directory\n     * @return {string} Path of containing folder (including trailing \"/\"); or \"\" if path was the root\n     */\n    function getParentPath(fullPath) {\n        if (fullPath === \"/\") {\n            return \"\";\n        }\n        return fullPath.substring(0, fullPath.lastIndexOf(\"/\", fullPath.length - 2) + 1);\n    }\n\n    /**\n     * Get the file name without the extension. Returns \"\" if name starts with \".\"\n     * @param {string} filename File name of a file or directory, without preceding path\n     * @return {string} Returns the file name without the extension\n     */\n    function getFilenameWithoutExtension(filename) {\n        var index = filename.lastIndexOf(\".\");\n        return index === -1 ? filename : filename.slice(0, index);\n    }\n\n    /**\n     * @private\n     * OS-specific helper for `compareFilenames()`\n     * @return {Function} The OS-specific compare function\n     */\n    var _cmpNames = (function () {\n        if (brackets.platform === \"win\") {\n            // Use this function on Windows\n            return function (filename1, filename2, lang) {\n                var f1 = getFilenameWithoutExtension(filename1),\n                    f2 = getFilenameWithoutExtension(filename2);\n                return f1.localeCompare(f2, lang, {numeric: true});\n            };\n        }\n\n        // Use this function other OSes\n        return function (filename1, filename2, lang) {\n            return filename1.localeCompare(filename2, lang, {numeric: true});\n        };\n    }());\n\n    /**\n     * Compares 2 filenames in lowercases. In Windows it compares the names without the\n     * extension first and then the extensions to fix issue #4409\n     * @param {string} filename1\n     * @param {string} filename2\n     * @param {boolean} extFirst If true it compares the extensions first and then the file names.\n     * @return {number} The result of the compare function\n     */\n    function compareFilenames(filename1, filename2, extFirst) {\n        var lang = brackets.getLocale();\n\n        filename1 = filename1.toLocaleLowerCase();\n        filename2 = filename2.toLocaleLowerCase();\n\n        function cmpExt() {\n            var ext1 = getFileExtension(filename1),\n                ext2 = getFileExtension(filename2);\n            return ext1.localeCompare(ext2, lang, {numeric: true});\n        }\n\n        function cmpNames() {\n            return _cmpNames(filename1, filename2, lang);\n        }\n\n        return extFirst ? (cmpExt() || cmpNames()) : (cmpNames() || cmpExt());\n    }\n\n    /**\n     * Compares two paths segment-by-segment, used for sorting. When two files share a path prefix,\n     * the less deeply nested one is sorted earlier in the list. Sorts files within the same parent\n     * folder based on `compareFilenames()`.\n     * @param {string} path1\n     * @param {string} path2\n     * @return {number} -1, 0, or 1 depending on whether path1 is less than, equal to, or greater than\n     *     path2 according to this ordering.\n     */\n    function comparePaths(path1, path2) {\n        var entryName1, entryName2,\n            pathParts1 = path1.split(\"/\"),\n            pathParts2 = path2.split(\"/\"),\n            length     = Math.min(pathParts1.length, pathParts2.length),\n            folders1   = pathParts1.length - 1,\n            folders2   = pathParts2.length - 1,\n            index      = 0;\n\n        while (index < length) {\n            entryName1 = pathParts1[index];\n            entryName2 = pathParts2[index];\n\n            if (entryName1 !== entryName2) {\n                if (index < folders1 && index < folders2) {\n                    return entryName1.toLocaleLowerCase().localeCompare(entryName2.toLocaleLowerCase());\n                } else if (index >= folders1 && index >= folders2) {\n                    return compareFilenames(entryName1, entryName2);\n                }\n                return (index >= folders1 && index < folders2) ? -1 : 1;\n            }\n            index++;\n        }\n        return 0;\n    }\n\n    /**\n     * @param {string} path Native path in the format used by FileSystemEntry.fullPath\n     * @return {string} URI-encoded version suitable for appending to 'file:///`. It's not safe to use encodeURI()\n     *     directly since it doesn't escape chars like \"#\".\n     */\n    function encodeFilePath(path) {\n        var pathArray = path.split(\"/\");\n        pathArray = pathArray.map(function (subPath) {\n            return encodeURIComponent(subPath);\n        });\n        return pathArray.join(\"/\");\n    }\n\n    /**\n     * @param {string} ext extension string a file\n     * @return {string} returns true If file to be opened in External Application.\n     *\n     */\n    function shouldOpenInExternalApplication(ext) {\n        return extListToBeOpenedInExtApp.includes(ext);\n    }\n\n    /**\n     * @param {string} ext File Extensions to be added in External App List\n     *\n     */\n    function addExtensionToExternalAppList(ext) {\n\n        if(Array.isArray(ext)) {\n            extListToBeOpenedInExtApp = ext;\n        } else if (typeof ext === 'string'){\n            extListToBeOpenedInExtApp.push(ext);\n        }\n    }\n\n    // Asynchronously load DocumentCommandHandlers\n    // This avoids a temporary circular dependency created\n    // by relocating showFileOpenError() until deprecation is over\n    require([\"document/DocumentCommandHandlers\"], function (dchModule) {\n        DocumentCommandHandlers = dchModule;\n    });\n\n    // Asynchronously load LiveDevelopmentUtils\n    // This avoids a temporary circular dependency created\n    // by relocating isStaticHtmlFileExt() until deprecation is over\n    require([\"LiveDevelopment/LiveDevelopmentUtils\"], function (lduModule) {\n        LiveDevelopmentUtils = lduModule;\n    });\n\n    // Define public API\n    exports.LINE_ENDINGS_CRLF              = LINE_ENDINGS_CRLF;\n    exports.LINE_ENDINGS_LF                = LINE_ENDINGS_LF;\n    exports.getPlatformLineEndings         = getPlatformLineEndings;\n    exports.sniffLineEndings               = sniffLineEndings;\n    exports.translateLineEndings           = translateLineEndings;\n    exports.showFileOpenError              = showFileOpenError;\n    exports.getFileErrorString             = getFileErrorString;\n    exports.makeDialogFileList             = makeDialogFileList;\n    exports.readAsText                     = readAsText;\n    exports.writeText                      = writeText;\n    exports.convertToNativePath            = convertToNativePath;\n    exports.convertWindowsPathToUnixPath   = convertWindowsPathToUnixPath;\n    exports.getNativeBracketsDirectoryPath = getNativeBracketsDirectoryPath;\n    exports.getNativeModuleDirectoryPath   = getNativeModuleDirectoryPath;\n    exports.stripTrailingSlash             = stripTrailingSlash;\n    exports.isStaticHtmlFileExt            = isStaticHtmlFileExt;\n    exports.getDirectoryPath               = getDirectoryPath;\n    exports.getParentPath                  = getParentPath;\n    exports.getBaseName                    = getBaseName;\n    exports.getRelativeFilename            = getRelativeFilename;\n    exports.getFilenameWithoutExtension    = getFilenameWithoutExtension;\n    exports.getFileExtension               = getFileExtension;\n    exports.getSmartFileExtension          = getSmartFileExtension;\n    exports.compareFilenames               = compareFilenames;\n    exports.comparePaths                   = comparePaths;\n    exports.MAX_FILE_SIZE                  = MAX_FILE_SIZE;\n    exports.encodeFilePath                 = encodeFilePath;\n    exports.shouldOpenInExternalApplication = shouldOpenInExternalApplication;\n    exports.addExtensionToExternalAppList = addExtensionToExternalAppList;\n});\n"
  },
  {
    "path": "src/filesystem/Directory.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileSystemEntry = require(\"filesystem/FileSystemEntry\");\n\n    /*\n     * Model for a file system Directory.\n     *\n     * This class should *not* be instantiated directly. Use FileSystem.getDirectoryForPath,\n     * FileSystem.resolve, or Directory.getContents to create an instance of this class.\n     *\n     * Note: Directory.fullPath always has a trailing slash.\n     *\n     * See the FileSystem class for more details.\n     *\n     * @constructor\n     * @param {!string} fullPath The full path for this Directory.\n     * @param {!FileSystem} fileSystem The file system associated with this Directory.\n     */\n    function Directory(fullPath, fileSystem) {\n        this._isDirectory = true;\n        FileSystemEntry.call(this, fullPath, fileSystem);\n    }\n\n    Directory.prototype = Object.create(FileSystemEntry.prototype);\n    Directory.prototype.constructor = Directory;\n    Directory.prototype.parentClass = FileSystemEntry.prototype;\n\n    /**\n     * The contents of this directory. This \"private\" property is used by FileSystem.\n     * @type {Array<FileSystemEntry>}\n     */\n    Directory.prototype._contents = null;\n\n    /**\n     * The stats for the contents of this directory, such that this._contentsStats[i]\n     * corresponds to this._contents[i].\n     * @type {Array.<FileSystemStats>}\n     */\n    Directory.prototype._contentsStats = null;\n\n    /**\n     * The stats errors for the contents of this directory.\n     * @type {object.<string: string>} fullPaths are mapped to FileSystemError strings\n     */\n    Directory.prototype._contentsStatsErrors = null;\n\n    /**\n     * Clear any cached data for this directory. By default, we clear the contents\n     * of immediate children as well, because in some cases file watchers fail\n     * provide precise change notifications. (Sometimes, like after a \"git\n     * checkout\", they just report that some directory has changed when in fact\n     * many of the file within the directory have changed.\n     *\n     * @private\n     * @param {boolean=} preserveImmediateChildren\n     */\n    Directory.prototype._clearCachedData = function (preserveImmediateChildren) {\n        FileSystemEntry.prototype._clearCachedData.apply(this);\n\n        if (!preserveImmediateChildren) {\n            if (this._contents) {\n                this._contents.forEach(function (child) {\n                    child._clearCachedData(true);\n                });\n            } else {\n                // No cached _contents, but child entries may still exist.\n                // Scan the full index to catch all of them.\n                var dirPath = this.fullPath;\n                this._fileSystem._index.visitAll(function (entry) {\n                    if (entry.parentPath === dirPath) {\n                        entry._clearCachedData(true);\n                    }\n                });\n            }\n        }\n\n        this._contents = undefined;\n        this._contentsStats = undefined;\n        this._contentsStatsErrors = undefined;\n    };\n\n    /**\n     * Apply each callback in a list to the provided arguments. Callbacks\n     * can throw without preventing other callbacks from being applied.\n     *\n     * @private\n     * @param {Array.<function>} callbacks The callbacks to apply\n     * @param {Array} args The arguments to which each callback is applied\n     */\n    function _applyAllCallbacks(callbacks, args) {\n        if (callbacks.length > 0) {\n            var callback = callbacks.pop();\n            try {\n                callback.apply(undefined, args);\n            } finally {\n                _applyAllCallbacks(callbacks, args);\n            }\n        }\n    }\n\n    /**\n     * Read the contents of a Directory. If this Directory is under a watch root,\n     * the listing will exclude any items filtered out by the watch root's filter\n     * function.\n     *\n     * @param {Directory} directory Directory whose contents you want to get\n     * @param {function (?string, Array.<FileSystemEntry>=, Array.<FileSystemStats>=, Object.<string, string>=)} callback\n     *          Callback that is passed an error code or the stat-able contents\n     *          of the directory along with the stats for these entries and a\n     *          fullPath-to-FileSystemError string map of unstat-able entries\n     *          and their stat errors. If there are no stat errors then the last\n     *          parameter shall remain undefined.\n     */\n    Directory.prototype.getContents = function (callback) {\n        if (this._contentsCallbacks) {\n            // There is already a pending call for this directory's contents.\n            // Push the new callback onto the stack and return.\n            this._contentsCallbacks.push(callback);\n            return;\n        }\n\n        // Return cached contents if the directory is watched\n        if (this._contents) {\n            callback(null, this._contents, this._contentsStats, this._contentsStatsErrors);\n            return;\n        }\n\n        this._contentsCallbacks = [callback];\n\n        this._impl.readdir(this.fullPath, function (err, names, stats) {\n            var contents = [],\n                contentsStats = [],\n                contentsStatsErrors;\n\n            if (err) {\n                this._clearCachedData();\n            } else {\n                // Use the \"relaxed\" parameter to _isWatched because it's OK to\n                // cache data even while watchers are still starting up\n                var watched = this._isWatched(true);\n\n                names.forEach(function (name, index) {\n                    var entryPath = this.fullPath + name;\n\n                    var entryStats = stats[index];\n                    if (this._fileSystem._indexFilter(entryPath, name, entryStats)) {\n                        var entry;\n\n                        // Note: not all entries necessarily have associated stats.\n                        if (typeof entryStats === \"string\") {\n                            // entryStats is an error string\n                            if (contentsStatsErrors === undefined) {\n                                contentsStatsErrors = {};\n                            }\n                            contentsStatsErrors[entryPath] = entryStats;\n                        } else {\n                            // entryStats is a FileSystemStats object\n                            if (entryStats.isFile) {\n                                entry = this._fileSystem.getFileForPath(entryPath);\n                            } else {\n                                entry = this._fileSystem.getDirectoryForPath(entryPath);\n                            }\n\n                            if (watched) {\n                                entry._stat = entryStats;\n                            }\n\n                            contents.push(entry);\n                            contentsStats.push(entryStats);\n                        }\n                    }\n                }, this);\n\n                if (watched) {\n                    this._contents = contents;\n                    this._contentsStats = contentsStats;\n                    this._contentsStatsErrors = contentsStatsErrors;\n                }\n            }\n\n            // Reset the callback list before we begin calling back so that\n            // synchronous reentrant calls are handled correctly.\n            var currentCallbacks = this._contentsCallbacks;\n\n            this._contentsCallbacks = null;\n\n            // Invoke all saved callbacks\n            var callbackArgs = [err, contents, contentsStats, contentsStatsErrors];\n            _applyAllCallbacks(currentCallbacks, callbackArgs);\n        }.bind(this));\n    };\n\n    /**\n     * Create a directory\n     *\n     * @param {function (?string, FileSystemStats=)=} callback Callback resolved with a\n     *      FileSystemError string or the stat object for the created directory.\n     */\n    Directory.prototype.create = function (callback) {\n        callback = callback || function () {};\n\n        // Block external change events until after the write has finished\n        this._fileSystem._beginChange();\n\n        this._impl.mkdir(this._path, function (err, stat) {\n            if (err) {\n                this._clearCachedData();\n                try {\n                    callback(err);\n                    return;\n                } finally {\n                    // Unblock external change events\n                    this._fileSystem._endChange();\n                }\n            }\n\n            var parent = this._fileSystem.getDirectoryForPath(this.parentPath);\n\n            // Update internal filesystem state\n            if (this._isWatched()) {\n                this._stat = stat;\n            }\n\n            this._fileSystem._handleDirectoryChange(parent, function (added, removed) {\n                try {\n                    callback(null, stat);\n                } finally {\n                    if (parent._isWatched()) {\n                        this._fileSystem._fireChangeEvent(parent, added, removed);\n                    }\n                    // Unblock external change events\n                    this._fileSystem._endChange();\n                }\n            }.bind(this));\n        }.bind(this));\n    };\n\n    // Export this class\n    module.exports = Directory;\n});\n"
  },
  {
    "path": "src/filesystem/File.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileSystemEntry = require(\"filesystem/FileSystemEntry\");\n\n\n    /*\n     * Model for a File.\n     *\n     * This class should *not* be instantiated directly. Use FileSystem.getFileForPath,\n     * FileSystem.resolve, or Directory.getContents to create an instance of this class.\n     *\n     * See the FileSystem class for more details.\n     *\n     * @constructor\n     * @param {!string} fullPath The full path for this File.\n     * @param {!FileSystem} fileSystem The file system associated with this File.\n     */\n    function File(fullPath, fileSystem) {\n        this._isFile = true;\n        FileSystemEntry.call(this, fullPath, fileSystem);\n    }\n\n    File.prototype = Object.create(FileSystemEntry.prototype);\n    File.prototype.constructor = File;\n    File.prototype.parentClass = FileSystemEntry.prototype;\n\n    /**\n     * Cached contents of this file. This value is nullable but should NOT be undefined.\n     * @private\n     * @type {?string}\n     */\n    File.prototype._contents = null;\n    \n    \n    /**\n     * Encoding detected by brackets-shell\n     * @private\n     * @type {?string}\n     */\n    File.prototype._encoding = null;\n\n    /**\n     * BOM detected by brackets-shell\n     * @private\n     * @type {?bool}\n     */\n    File.prototype._preserveBOM = false;\n\n    /**\n     * Consistency hash for this file. Reads and writes update this value, and\n     * writes confirm the hash before overwriting existing files. The type of\n     * this object is dependent on the FileSystemImpl; the only constraint is\n     * that === can be used as an equality relation on hashes.\n     * @private\n     * @type {?object}\n     */\n    File.prototype._hash = null;\n\n    /**\n     * Clear any cached data for this file. Note that this explicitly does NOT\n     * clear the file's hash.\n     * @private\n     */\n    File.prototype._clearCachedData = function () {\n        FileSystemEntry.prototype._clearCachedData.apply(this);\n        this._contents = null;\n    };\n\n    /**\n     * Read a file.\n     *\n     * @param {Object=} options Currently unused.\n     * @param {function (?string, string=, FileSystemStats=)} callback Callback that is passed the\n     *              FileSystemError string or the file's contents and its stats.\n     */\n    File.prototype.read = function (options, callback) {\n        if (typeof (options) === \"function\") {\n            callback = options;\n            options = {};\n            options.encoding = this._encoding;\n        }\n        options.encoding = this._encoding || \"utf8\";\n\n        // We don't need to check isWatched() here because contents are only saved\n        // for watched files. Note that we need to explicitly test this._contents\n        // for a default value; otherwise it could be the empty string, which is\n        // falsey.\n        if (this._contents !== null && this._stat) {\n            callback(null, this._contents, this._encoding, this._stat);\n            return;\n        }\n\n        var watched = this._isWatched();\n        if (watched) {\n            options.stat = this._stat;\n        }\n\n        this._impl.readFile(this._path, options, function (err, data, encoding, preserveBOM, stat) {\n            if (err) {\n                this._clearCachedData();\n                callback(err);\n                return;\n            }\n\n            // Always store the hash\n            this._hash = stat._hash;\n            this._encoding = encoding;\n            this._preserveBOM = preserveBOM;\n\n            // Only cache data for watched files\n            if (watched) {\n                this._stat = stat;\n                this._contents = data;\n            }\n\n            callback(err, data, encoding, stat);\n        }.bind(this));\n    };\n\n    /**\n     * Write a file.\n     *\n     * @param {string} data Data to write.\n     * @param {object=} options Currently unused.\n     * @param {function (?string, FileSystemStats=)=} callback Callback that is passed the\n     *              FileSystemError string or the file's new stats.\n     */\n    File.prototype.write = function (data, options, callback) {\n        if (typeof options === \"function\") {\n            callback = options;\n            options = {};\n        } else {\n            if (options === undefined) {\n                options = {};\n            }\n\n            callback = callback || function () {};\n        }\n\n        // Request a consistency check if the write is not blind\n        if (!options.blind) {\n            options.expectedHash = this._hash;\n            options.expectedContents = this._contents;\n        }\n        if (!options.encoding) {\n            options.encoding = this._encoding || \"utf8\";\n        }\n        options.preserveBOM = this._preserveBOM;\n\n        // Block external change events until after the write has finished\n        this._fileSystem._beginChange();\n\n        this._impl.writeFile(this._path, data, options, function (err, stat, created) {\n            if (err) {\n                this._clearCachedData();\n                try {\n                    callback(err);\n                    return;\n                } finally {\n                    // Always unblock external change events\n                    this._fileSystem._endChange();\n                }\n            }\n\n            // Always store the hash\n            this._hash = stat._hash;\n\n            // Only cache data for watched files\n            if (this._isWatched()) {\n                this._stat = stat;\n                this._contents = data;\n            }\n\n            if (created) {\n                var parent = this._fileSystem.getDirectoryForPath(this.parentPath);\n                this._fileSystem._handleDirectoryChange(parent, function (added, removed) {\n                    try {\n                        // Notify the caller\n                        callback(null, stat);\n                    } finally {\n                        if (parent._isWatched()) {\n                            // If the write succeeded and the parent directory is watched,\n                            // fire a synthetic change event\n                            this._fileSystem._fireChangeEvent(parent, added, removed);\n\n                        }\n                        // Always unblock external change events\n                        this._fileSystem._endChange();\n                    }\n                }.bind(this));\n            } else {\n                try {\n                    // Notify the caller\n                    callback(null, stat);\n                } finally {\n                    // existing file modified\n                    this._fileSystem._fireChangeEvent(this);\n\n                    // Always unblock external change events\n                    this._fileSystem._endChange();\n                }\n            }\n        }.bind(this));\n    };\n\n    // Export this class\n    module.exports = File;\n});\n"
  },
  {
    "path": "src/filesystem/FileIndex.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * FileIndex is an internal module used by FileSystem to maintain an index of all files and directories.\n *\n * This module is *only* used by FileSystem, and should not be called directly.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils = require(\"file/FileUtils\");\n\n    /**\n     * @constructor\n     */\n    function FileIndex() {\n        this._index = {};\n    }\n\n    /**\n     * Master index\n     *\n     * @type {Object.<string, File|Directory>} Maps a fullPath to a File or Directory object\n     */\n    FileIndex.prototype._index = null;\n\n    /**\n     * Clear the file index cache.\n     */\n    FileIndex.prototype.clear = function () {\n        this._index = {};\n    };\n\n    /**\n     * Visits every entry in the entire index; no stopping condition.\n     * @param {!function(FileSystemEntry, string):void} Called with an entry and its fullPath\n     */\n    FileIndex.prototype.visitAll = function (visitor) {\n        var path;\n        for (path in this._index) {\n            if (this._index.hasOwnProperty(path)) {\n                visitor(this._index[path], path);\n            }\n        }\n    };\n\n    /**\n     * Add an entry.\n     *\n     * @param {FileSystemEntry} entry The entry to add.\n     */\n    FileIndex.prototype.addEntry = function (entry) {\n        this._index[entry.fullPath] = entry;\n    };\n\n    /**\n     * Remove an entry.\n     *\n     * @param {FileSystemEntry} entry The entry to remove.\n     */\n    FileIndex.prototype.removeEntry = function (entry) {\n        var path = entry.fullPath,\n            property;\n\n        function replaceMember(property) {\n            var member = entry[property];\n            if (typeof member === \"function\") {\n                entry[property] = function () {\n                    console.warn(\"FileSystemEntry used after being removed from index: \", path);\n                    return member.apply(entry, arguments);\n                };\n            }\n        }\n\n        delete this._index[path];\n\n        for (property in entry) {\n            if (entry.hasOwnProperty(property)) {\n                replaceMember(property);\n            }\n        }\n    };\n\n    /**\n     * Notify the index that an entry has been renamed. This updates\n     * all affected entries in the index.\n     *\n     * @param {string} oldPath\n     * @param {string} newPath\n     * @param {boolean} isDirectory\n     */\n    FileIndex.prototype.entryRenamed = function (oldPath, newPath, isDirectory) {\n        var path,\n            renameMap = {},\n            oldParentPath = FileUtils.getParentPath(oldPath),\n            newParentPath = FileUtils.getParentPath(newPath);\n\n        // Find all entries affected by the rename and put into a separate map.\n        for (path in this._index) {\n            if (this._index.hasOwnProperty(path)) {\n                // See if we have a match. For directories, see if the path\n                // starts with the old name. This is safe since paths always end\n                // with '/'. For files, see if there is an exact match between\n                // the path and the old name.\n                if (isDirectory ? path.indexOf(oldPath) === 0 : path === oldPath) {\n                    renameMap[path] = newPath + path.substr(oldPath.length);\n                }\n            }\n        }\n\n        // Do the rename.\n        for (path in renameMap) {\n            if (renameMap.hasOwnProperty(path)) {\n                var item = this._index[path];\n\n                // Sanity check to make sure the item and path still match\n                console.assert(item.fullPath === path);\n\n                delete this._index[path];\n                this._index[renameMap[path]] = item;\n                item._setPath(renameMap[path]);\n            }\n        }\n\n\n        // If file path is changed, i.e the file is moved\n        // Remove the moved entry from old Directory and add it to new Directory\n        if (oldParentPath !== newParentPath) {\n            var oldDirectory = this._index[oldParentPath],\n                newDirectory = this._index[newParentPath],\n                renamedEntry;\n\n            if (oldDirectory && oldDirectory._contents) {\n                oldDirectory._contents = oldDirectory._contents.filter(function(entry) {\n                    if (entry.fullPath === newPath) {\n                        renamedEntry = entry;\n                        return false;\n                    }\n                    return true;\n                });\n            }\n\n            if (newDirectory && newDirectory._contents && renamedEntry) {\n                renamedEntry._setPath(newPath);\n                newDirectory._contents.push(renamedEntry);\n            }\n        }\n    };\n\n    /**\n     * Returns the cached entry for the specified path, or undefined\n     * if the path has not been cached.\n     *\n     * @param {string} path The path of the entry to return.\n     * @return {File|Directory} The entry for the path, or undefined if it hasn't\n     *              been cached yet.\n     */\n    FileIndex.prototype.getEntry = function (path) {\n        return this._index[path];\n    };\n\n    // Export public API\n    module.exports = FileIndex;\n});\n"
  },
  {
    "path": "src/filesystem/FileSystem.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * FileSystem is a model object representing a complete file system. This object creates\n * and manages File and Directory instances, dispatches events when the file system changes,\n * and provides methods for showing 'open' and 'save' dialogs.\n *\n * FileSystem automatically initializes when loaded. It depends on a pluggable \"impl\" layer, which\n * it loads itself but must be designated in the require.config() that loads FileSystem. For details\n * see: https://github.com/adobe/brackets/wiki/File-System-Implementations\n *\n * There are three ways to get File or Directory instances:\n *    * Use FileSystem.resolve() to convert a path to a File/Directory object. This will only\n *      succeed if the file/directory already exists.\n *    * Use FileSystem.getFileForPath()/FileSystem.getDirectoryForPath() if you know the\n *      file/directory already exists, or if you want to create a new entry.\n *    * Use Directory.getContents() to return all entries for the specified Directory.\n *\n * All paths passed *to* FileSystem APIs must be in the following format:\n *    * The path separator is \"/\" regardless of platform\n *    * Paths begin with \"/\" on Mac/Linux and \"c:/\" (or some other drive letter) on Windows\n *\n * All paths returned *from* FileSystem APIs additionally meet the following guarantees:\n *    * No \"..\" segments\n *    * No consecutive \"/\"s\n *    * Paths to a directory always end with a trailing \"/\"\n * (Because FileSystem normalizes paths automatically, paths passed *to* FileSystem do not need\n * to meet these requirements)\n *\n * FileSystem dispatches the following events:\n * (NOTE: attach to these events via `FileSystem.on()` - not `$(FileSystem).on()`)\n *\n * __change__ - Sent whenever there is a change in the file system. The handler\n *   is passed up to three arguments: the changed entry and, if that changed entry\n *   is a Directory, a list of entries added to the directory and a list of entries\n *   removed from the Directory. The entry argument can be:\n *   *  a File - the contents of the file have changed, and should be reloaded.\n *   *  a Directory - an immediate child of the directory has been added, removed,\n *      or renamed/moved. Not triggered for \"grandchildren\".\n *      - If the added & removed arguments are null, we don't know what was added/removed:\n *        clients should assume the whole subtree may have changed.\n *      - If the added & removed arguments are 0-length, there's no net change in the set\n *        of files but a file may have been replaced: clients should assume the contents\n *        of any immediate child file may have changed.\n *   *  null - a 'wholesale' change happened, and you should assume everything may\n *      have changed.\n *   For changes made externally, there may be a significant delay before a \"change\" event\n *   is dispatched.\n *\n * __rename__ - Sent whenever a File or Directory is renamed. All affected File and Directory\n *   objects have been updated to reflect the new path by the time this event is dispatched.\n *   This event should be used to trigger any UI updates that may need to occur when a path\n *   has changed. Note that these events will only be sent for rename operations that happen\n *   within the filesystem. If a file is renamed externally, a change event on the parent\n *   directory will be sent instead.\n *\n * FileSystem may perform caching. But it guarantees:\n *    * File contents & metadata - reads are guaranteed to be up to date (cached data is not used\n *      without first veryifying it is up to date).\n *    * Directory structure / file listing - reads may return cached data immediately, which may not\n *      reflect external changes made recently. (However, changes made via FileSystem itself are always\n *      reflected immediately, as soon as the change operation's callback signals success).\n *\n * The FileSystem doesn't directly read or write contents--this work is done by a low-level\n * implementation object. This allows client code to use the FileSystem API without having to\n * worry about the underlying storage, which could be a local filesystem or a remote server.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Directory       = require(\"filesystem/Directory\"),\n        File            = require(\"filesystem/File\"),\n        FileIndex       = require(\"filesystem/FileIndex\"),\n        FileSystemError = require(\"filesystem/FileSystemError\"),\n        WatchedRoot     = require(\"filesystem/WatchedRoot\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        PathUtils       = require(\"thirdparty/path-utils/path-utils\"),\n        _               = require(\"thirdparty/lodash\");\n\n\n    // Collection of registered protocol adapters\n    var _fileProtocolPlugins = {};\n\n    /**\n     * Typical signature of a file protocol adapter.\n     * @typedef {Object} FileProtocol~Adapter\n     * @property {Number} priority - Indicates the priority.\n     * @property {Object} fileImpl - Handle for the custom file implementation prototype.\n     * @property {function} canRead - To check if this impl can read a file for a given path.\n     */\n\n    /**\n     * FileSystem hook to register file protocol adapter\n     * @param {string} protocol ex: \"https:\"|\"http:\"|\"ftp:\"|\"file:\"\n     * @param {...FileProtocol~Adapter} adapter wrapper over file implementation\n     */\n    function registerProtocolAdapter(protocol, adapter) {\n        var adapters;\n        if (protocol) {\n            adapters = _fileProtocolPlugins[protocol] || [];\n            adapters.push(adapter);\n\n            // We will keep a sorted adapter list on 'priority'\n            // If priority is not provided a default of '0' is assumed\n            adapters.sort(function (a, b) {\n                return (b.priority || 0) - (a.priority || 0);\n            });\n\n            _fileProtocolPlugins[protocol] = adapters;\n        }\n    }\n\n    /**\n     * @param {string} protocol ex: \"https:\"|\"http:\"|\"ftp:\"|\"file:\"\n     * @param {string} filePath fullPath of the file\n     * @return adapter adapter wrapper over file implementation\n     */\n    function _getProtocolAdapter(protocol, filePath) {\n        var protocolAdapters = _fileProtocolPlugins[protocol] || [],\n            selectedAdapter;\n\n        // Find the fisrt compatible adapter having highest priority\n        _.forEach(protocolAdapters, function (adapter) {\n            if (adapter.canRead && adapter.canRead(filePath)) {\n                selectedAdapter = adapter;\n                // Break at first compatible adapter\n                return false;\n            }\n        });\n\n        return selectedAdapter;\n    }\n\n    /**\n     * The FileSystem is not usable until init() signals its callback.\n     * @constructor\n     */\n    function FileSystem() {\n        // Create a file index\n        this._index = new FileIndex();\n\n        // Initialize the set of watched roots\n        this._watchedRoots = {};\n\n        // Initialize the watch/unwatch request queue\n        this._watchRequests = [];\n\n        // Initialize the queue of pending external changes\n        this._externalChanges = [];\n    }\n    EventDispatcher.makeEventDispatcher(FileSystem.prototype);\n\n    /**\n     * The low-level file system implementation used by this object.\n     * This is set in the init() function and cannot be changed.\n     */\n    FileSystem.prototype._impl = null;\n\n    /**\n     * The FileIndex used by this object. This is initialized in the constructor.\n     */\n    FileSystem.prototype._index = null;\n\n    /**\n     * Refcount of any pending filesystem mutation operations (e.g., writes,\n     * unlinks, etc.). Used to ensure that external change events aren't processed\n     * until after index fixups, operation-specific callbacks, and internal change\n     * events are complete. (This is important for distinguishing rename from\n     * an unrelated delete-add pair).\n     * @type {number}\n     */\n    FileSystem.prototype._activeChangeCount = 0;\n\n    // For unit testing only\n    FileSystem.prototype._getActiveChangeCount = function () {\n        return this._activeChangeCount;\n    };\n\n    /**\n     * Queue of arguments with which to invoke _handleExternalChanges(); triggered\n     * once _activeChangeCount drops to zero.\n     * @type {!Array.<{path:?string, stat:FileSystemStats=}>}\n     */\n    FileSystem.prototype._externalChanges = null;\n\n    /** Process all queued watcher results, by calling _handleExternalChange() on each */\n    FileSystem.prototype._triggerExternalChangesNow = function () {\n        this._externalChanges.forEach(function (info) {\n            this._handleExternalChange(info.path, info.stat);\n        }, this);\n        this._externalChanges.length = 0;\n    };\n\n    /**\n     * Receives a result from the impl's watcher callback, and either processes it\n     * immediately (if _activeChangeCount is 0) or otherwise stores it for later\n     * processing.\n     * @param {?string} path The fullPath of the changed entry\n     * @param {FileSystemStats=} stat An optional stat object for the changed entry\n     */\n    FileSystem.prototype._enqueueExternalChange = function (path, stat) {\n        this._externalChanges.push({path: path, stat: stat});\n        if (!this._activeChangeCount) {\n            this._triggerExternalChangesNow();\n        }\n    };\n\n\n    /**\n     * The queue of pending watch/unwatch requests.\n     * @type {Array.<{fn: function(), cb: function()}>}\n     */\n    FileSystem.prototype._watchRequests = null;\n\n    /**\n     * Dequeue and process all pending watch/unwatch requests\n     */\n    FileSystem.prototype._dequeueWatchRequest = function () {\n        if (this._watchRequests.length > 0) {\n            var request = this._watchRequests[0];\n\n            request.fn.call(null, function () {\n                // Apply the given callback\n                var callbackArgs = arguments;\n                try {\n                    request.cb.apply(null, callbackArgs);\n                } finally {\n                    // Process the remaining watch/unwatch requests\n                    this._watchRequests.shift();\n                    this._dequeueWatchRequest();\n                }\n            }.bind(this));\n        }\n    };\n\n    /**\n     * Enqueue a new watch/unwatch request.\n     *\n     * @param {function()} fn - The watch/unwatch request function.\n     * @param {callback()} cb - The callback for the provided watch/unwatch\n     *      request function.\n     */\n    FileSystem.prototype._enqueueWatchRequest = function (fn, cb) {\n        // Enqueue the given watch/unwatch request\n        this._watchRequests.push({fn: fn, cb: cb});\n\n        // Begin processing the queue if it is not already being processed\n        if (this._watchRequests.length === 1) {\n            this._dequeueWatchRequest();\n        }\n    };\n\n    /**\n     * The set of watched roots, encoded as a mapping from full paths to WatchedRoot\n     * objects which contain a file entry, filter function, and an indication of\n     * whether the watched root is inactive, starting up or fully active.\n     *\n     * @type {Object.<string, WatchedRoot>}\n     */\n    FileSystem.prototype._watchedRoots = null;\n\n    /**\n     * Finds a parent watched root for a given path, or returns null if a parent\n     * watched root does not exist.\n     *\n     * @param {string} fullPath The child path for which a parent watched root is to be found\n     * @return {?{entry: FileSystemEntry, filter: function(string) boolean}} The parent\n     *      watched root, if it exists, or null.\n     */\n    FileSystem.prototype._findWatchedRootForPath = function (fullPath) {\n        var watchedRoot = null;\n\n        Object.keys(this._watchedRoots).some(function (watchedPath) {\n            if (fullPath.indexOf(watchedPath) === 0) {\n                watchedRoot = this._watchedRoots[watchedPath];\n                return true;\n            }\n        }, this);\n\n        return watchedRoot;\n    };\n\n    /**\n     * Helper function to watch or unwatch a filesystem entry beneath a given\n     * watchedRoot.\n     *\n     * @private\n     * @param {FileSystemEntry} entry - The FileSystemEntry to watch. Must be a\n     *      non-strict descendent of watchedRoot.entry.\n     * @param {WatchedRoot} watchedRoot - See FileSystem._watchedRoots.\n     * @param {function(?string)} callback - A function that is called once the\n     *      watch is complete, possibly with a FileSystemError string.\n     * @param {boolean} shouldWatch - Whether the entry should be watched (true)\n     *      or unwatched (false).\n     */\n    FileSystem.prototype._watchOrUnwatchEntry = function (entry, watchedRoot, callback, shouldWatch) {\n        var impl = this._impl,\n            recursiveWatch = impl.recursiveWatch,\n            commandName = shouldWatch ? \"watchPath\" : \"unwatchPath\",\n            filterGlobs = watchedRoot.filterGlobs;\n\n        if (recursiveWatch) {\n            // The impl can watch the entire subtree with one call on the root (we also fall into this case for\n            // unwatch, although that never requires us to do the recursion - see similar final case below)\n            if (entry !== watchedRoot.entry) {\n                // Watch and unwatch calls to children of the watched root are\n                // no-ops if the impl supports recursiveWatch\n                callback(null);\n            } else {\n                // The impl will handle finding all subdirectories to watch.\n                this._enqueueWatchRequest(function (requestCb) {\n                    impl[commandName].call(impl, entry.fullPath, filterGlobs, requestCb);\n                }.bind(this), callback);\n            }\n        } else if (shouldWatch) {\n            // The impl can't handle recursive watch requests, so it's up to the\n            // filesystem to recursively watch all subdirectories.\n            this._enqueueWatchRequest(function (requestCb) {\n                // First construct a list of entries to watch or unwatch\n                var entriesToWatch = [];\n\n                var visitor = function (child) {\n                    if (watchedRoot.filter(child.name, child.parentPath)) {\n                        if (child.isDirectory || child === watchedRoot.entry) {\n                            entriesToWatch.push(child);\n                        }\n                        return true;\n                    }\n                    return false;\n                };\n\n                entry.visit(visitor, function (err) {\n                    if (err) {\n                        // Unexpected error\n                        requestCb(err);\n                        return;\n                    }\n\n                    // Then watch or unwatched all these entries\n                    var count = entriesToWatch.length;\n                    if (count === 0) {\n                        requestCb(null);\n                        return;\n                    }\n\n                    var watchCallback = function () {\n                        if (--count === 0) {\n                            requestCb(null);\n                        }\n                    };\n\n                    entriesToWatch.forEach(function (entry) {\n                        impl.watchPath(entry.fullPath, filterGlobs, watchCallback);\n                    });\n                });\n            }, callback);\n        } else {\n            // Unwatching never requires enumerating the subfolders (which is good, since after a\n            // delete/rename we may be unable to do so anyway)\n            this._enqueueWatchRequest(function (requestCb) {\n                impl.unwatchPath(entry.fullPath, requestCb);\n            }, callback);\n        }\n    };\n\n    /**\n     * Watch a filesystem entry beneath a given watchedRoot.\n     *\n     * @private\n     * @param {FileSystemEntry} entry - The FileSystemEntry to watch. Must be a\n     *      non-strict descendent of watchedRoot.entry.\n     * @param {WatchedRoot} watchedRoot - See FileSystem._watchedRoots.\n     * @param {function(?string)} callback - A function that is called once the\n     *      watch is complete, possibly with a FileSystemError string.\n     */\n    FileSystem.prototype._watchEntry = function (entry, watchedRoot, callback) {\n        this._watchOrUnwatchEntry(entry, watchedRoot, callback, true);\n    };\n\n    /**\n     * Unwatch a filesystem entry beneath a given watchedRoot.\n     *\n     * @private\n     * @param {FileSystemEntry} entry - The FileSystemEntry to watch. Must be a\n     *      non-strict descendent of watchedRoot.entry.\n     * @param {WatchedRoot} watchedRoot - See FileSystem._watchedRoots.\n     * @param {function(?string)} callback - A function that is called once the\n     *      watch is complete, possibly with a FileSystemError string.\n     */\n    FileSystem.prototype._unwatchEntry = function (entry, watchedRoot, callback) {\n        this._watchOrUnwatchEntry(entry, watchedRoot, function (err) {\n            // Make sure to clear cached data for all unwatched entries because\n            // entries always return cached data if it exists!\n            this._index.visitAll(function (child) {\n                if (child.fullPath.indexOf(entry.fullPath) === 0) {\n                    // 'true' so entry doesn't try to clear its immediate childrens' caches too. That would be redundant\n                    // with the visitAll() here, and could be slow if we've already cleared its parent (#7150).\n                    child._clearCachedData(true);\n                }\n            }.bind(this));\n\n            callback(err);\n        }.bind(this), false);\n    };\n\n    /**\n     * Initialize this FileSystem instance.\n     *\n     * @param {FileSystemImpl} impl The back-end implementation for this\n     *      FileSystem instance.\n     */\n    FileSystem.prototype.init = function (impl) {\n        console.assert(!this._impl, \"This FileSystem has already been initialized!\");\n\n        var changeCallback = this._enqueueExternalChange.bind(this),\n            offlineCallback = this._unwatchAll.bind(this);\n\n        this._impl = impl;\n        this._impl.initWatchers(changeCallback, offlineCallback);\n    };\n\n    /**\n     * Close a file system. Clear all caches, indexes, and file watchers.\n     */\n    FileSystem.prototype.close = function () {\n        this._impl.unwatchAll();\n        this._index.clear();\n    };\n\n    /**\n     * Returns true if the given path should be automatically added to the index & watch list when one of its ancestors\n     * is a watch-root. (Files are added automatically when the watch-root is first established, or later when a new\n     * directory is created and its children enumerated).\n     *\n     * Entries explicitly created via FileSystem.getFile/DirectoryForPath() are *always* added to the index regardless\n     * of this filtering - but they will not be watched if the watch-root's filter excludes them.\n     *\n     * @param {string} path Full path\n     * @param {string} name Name portion of the path\n     */\n    FileSystem.prototype._indexFilter = function (path, name) {\n        var parentRoot = this._findWatchedRootForPath(path);\n\n        if (parentRoot) {\n            return parentRoot.filter(name, path);\n        }\n\n        // It might seem more sensible to return false (exclude) for files outside the watch roots, but\n        // that would break usage of appFileSystem for 'system'-level things like enumerating extensions.\n        // (Or in general, Directory.getContents() for any Directory outside the watch roots).\n        return true;\n    };\n\n    /**\n     * Indicates that a filesystem-mutating operation has begun. As long as there\n     * are changes taking place, change events from the external watchers are\n     * blocked and queued, to be handled once changes have finished. This is done\n     * because for mutating operations that originate from within the filesystem,\n     * synthetic change events are fired that do not depend on external file\n     * watchers, and we prefer the former over the latter for the following\n     * reasons: 1) there is no delay; and 2) they may have higher fidelity ---\n     * e.g., a rename operation can be detected as such, instead of as a nearly\n     * simultaneous addition and deletion.\n     *\n     * All operations that mutate the file system MUST begin with a call to\n     * _beginChange and must end with a call to _endChange.\n     */\n    FileSystem.prototype._beginChange = function () {\n        this._activeChangeCount++;\n        //console.log(\"> beginChange  -> \" + this._activeChangeCount);\n    };\n\n    /**\n     * Indicates that a filesystem-mutating operation has completed. See\n     * FileSystem._beginChange above.\n     */\n    FileSystem.prototype._endChange = function () {\n        this._activeChangeCount--;\n        //console.log(\"< endChange    -> \" + this._activeChangeCount);\n\n        if (this._activeChangeCount < 0) {\n            console.error(\"FileSystem _activeChangeCount has fallen below zero!\");\n        }\n\n        if (!this._activeChangeCount) {\n            this._triggerExternalChangesNow();\n        }\n    };\n\n    /**\n     * Determines whether or not the supplied path is absolute, as opposed to relative.\n     *\n     * @param {!string} fullPath\n     * @return {boolean} True if the fullPath is absolute and false otherwise.\n     */\n    FileSystem.isAbsolutePath = function (fullPath) {\n        return (fullPath[0] === \"/\" || (fullPath[1] === \":\" && fullPath[2] === \"/\"));\n    };\n\n    function _ensureTrailingSlash(path) {\n        if (path[path.length - 1] !== \"/\") {\n            path += \"/\";\n        }\n\n        return path;\n    }\n\n    /*\n     * Matches continguous groups of forward slashes\n     * @const\n     */\n    var _DUPLICATED_SLASH_RE = /\\/{2,}/g;\n\n    /**\n     * Returns a canonical version of the path: no duplicated \"/\"es, no \"..\"s,\n     * and directories guaranteed to end in a trailing \"/\"\n     * @param {!string} path  Absolute path, using \"/\" as path separator\n     * @param {boolean=} isDirectory\n     * @return {!string}\n     */\n    FileSystem.prototype._normalizePath = function (path, isDirectory) {\n\n        if (!FileSystem.isAbsolutePath(path)) {\n            throw new Error(\"Paths must be absolute: '\" + path + \"'\");  // expect only absolute paths\n        }\n\n        var isUNCPath = this._impl.normalizeUNCPaths && path.search(_DUPLICATED_SLASH_RE) === 0;\n\n        // Remove duplicated \"/\"es\n        path = path.replace(_DUPLICATED_SLASH_RE, \"/\");\n\n        // Remove \"..\" segments\n        if (path.indexOf(\"..\") !== -1) {\n            var segments = path.split(\"/\"),\n                i;\n            for (i = 1; i < segments.length; i++) {\n                if (segments[i] === \"..\") {\n                    if (i < 2) {\n                        throw new Error(\"Invalid absolute path: '\" + path + \"'\");\n                    }\n                    segments.splice(i - 1, 2);\n                    i -= 2; // compensate so we start on the right index next iteration\n                }\n            }\n            path = segments.join(\"/\");\n        }\n\n        if (isDirectory) {\n            // Make sure path DOES include trailing slash\n            path = _ensureTrailingSlash(path);\n        }\n\n        if (isUNCPath) {\n            // Restore the leading double slash that was removed previously\n            path = \"/\" + path;\n        }\n\n        return path;\n    };\n\n    /**\n     * This method adds an entry for a file in the file Index. Files on disk are added\n     * to the file index either on load or on open. This method is primarily needed to add\n     * in memory files to the index\n     *\n     * @param {File} The fileEntry which needs to be added\n     * @param {String} The full path to the file\n     */\n    FileSystem.prototype.addEntryForPathIfRequired = function (fileEntry, path) {\n        var entry = this._index.getEntry(path);\n\n        if (!entry) {\n            this._index.addEntry(fileEntry);\n        }\n    };\n\n    /**\n     * Return a (strict subclass of a) FileSystemEntry object for the specified\n     * path using the provided constuctor. For now, the provided constructor\n     * should be either File or Directory.\n     *\n     * @private\n     * @param {function(string, FileSystem)} EntryConstructor Constructor with\n     *      which to initialize new FileSystemEntry objects.\n     * @param {string} path Absolute path of file.\n     * @return {File|Directory} The File or Directory object. This file may not\n     *      yet exist on disk.\n     */\n    FileSystem.prototype._getEntryForPath = function (EntryConstructor, path) {\n        var isDirectory = EntryConstructor === Directory;\n        path = this._normalizePath(path, isDirectory);\n        var entry = this._index.getEntry(path);\n\n        if (!entry) {\n            entry = new EntryConstructor(path, this);\n            this._index.addEntry(entry);\n        }\n\n        return entry;\n    };\n\n    /**\n     * Return a File object for the specified path.\n     *\n     * @param {string} path Absolute path of file.\n     *\n     * @return {File} The File object. This file may not yet exist on disk.\n     */\n    FileSystem.prototype.getFileForPath = function (path) {\n        var protocol = PathUtils.parseUrl(path).protocol,\n            protocolAdapter = _getProtocolAdapter(protocol);\n\n        if (protocolAdapter && protocolAdapter.fileImpl) {\n            return new protocolAdapter.fileImpl(protocol, path, this);\n        } else {\n            return this._getEntryForPath(File, path);\n        }\n    };\n\n    /**\n     * Return a Directory object for the specified path.\n     *\n     * @param {string} path Absolute path of directory.\n     *\n     * @return {Directory} The Directory object. This directory may not yet exist on disk.\n     */\n    FileSystem.prototype.getDirectoryForPath = function (path) {\n        return this._getEntryForPath(Directory, path);\n    };\n\n    /**\n     * Resolve a path.\n     *\n     * @param {string} path The path to resolve\n     * @param {function (?string, FileSystemEntry=, FileSystemStats=)} callback Callback resolved\n     *      with a FileSystemError string or with the entry for the provided path.\n     */\n    FileSystem.prototype.resolve = function (path, callback) {\n        var normalizedPath = this._normalizePath(path, false),\n            item = this._index.getEntry(normalizedPath);\n\n        if (!item) {\n            normalizedPath = _ensureTrailingSlash(normalizedPath);\n            item = this._index.getEntry(normalizedPath);\n        }\n\n        if (item) {\n            item.stat(function (err, stat) {\n                if (err) {\n                    callback(err);\n                    return;\n                }\n\n                callback(null, item, stat);\n            });\n        } else {\n            this._impl.stat(path, function (err, stat) {\n                if (err) {\n                    callback(err);\n                    return;\n                }\n\n                if (stat.isFile) {\n                    item = this.getFileForPath(path);\n                } else {\n                    item = this.getDirectoryForPath(path);\n                }\n\n                if (item._isWatched()) {\n                    item._stat = stat;\n                }\n\n                callback(null, item, stat);\n            }.bind(this));\n        }\n    };\n\n    /**\n     * Show an \"Open\" dialog and return the file(s)/directories selected by the user.\n     *\n     * @param {boolean} allowMultipleSelection Allows selecting more than one file at a time\n     * @param {boolean} chooseDirectories Allows directories to be opened\n     * @param {string} title The title of the dialog\n     * @param {string} initialPath The folder opened inside the window initially. If initialPath\n     *                          is not set, or it doesn't exist, the window would show the last\n     *                          browsed folder depending on the OS preferences\n     * @param {?Array.<string>} fileTypes (Currently *ignored* except on Mac - https://trello.com/c/430aXkpq)\n     *                          List of extensions that are allowed to be opened, without leading \".\".\n     *                          Null or empty array allows all files to be selected. Not applicable\n     *                          when chooseDirectories = true.\n     * @param {function (?string, Array.<string>=)} callback Callback resolved with a FileSystemError\n     *                          string or the selected file(s)/directories. If the user cancels the\n     *                          open dialog, the error will be falsy and the file/directory array will\n     *                          be empty.\n     */\n    FileSystem.prototype.showOpenDialog = function (allowMultipleSelection,\n                            chooseDirectories,\n                            title,\n                            initialPath,\n                            fileTypes,\n                            callback) {\n\n        this._impl.showOpenDialog(allowMultipleSelection, chooseDirectories, title, initialPath, fileTypes, callback);\n    };\n\n    /**\n     * Show a \"Save\" dialog and return the path of the file to save.\n     *\n     * @param {string} title The title of the dialog.\n     * @param {string} initialPath The folder opened inside the window initially. If initialPath\n     *                          is not set, or it doesn't exist, the window would show the last\n     *                          browsed folder depending on the OS preferences.\n     * @param {string} proposedNewFilename Provide a new file name for the user. This could be based on\n     *                          on the current file name plus an additional suffix\n     * @param {function (?string, string=)} callback Callback that is resolved with a FileSystemError\n     *                          string or the name of the file to save. If the user cancels the save,\n     *                          the error will be falsy and the name will be empty.\n     */\n    FileSystem.prototype.showSaveDialog = function (title, initialPath, proposedNewFilename, callback) {\n        this._impl.showSaveDialog(title, initialPath, proposedNewFilename, callback);\n    };\n\n    /**\n     * Fire a rename event. Clients listen for these events using FileSystem.on.\n     *\n     * @param {string} oldPath The entry's previous fullPath\n     * @param {string} newPath The entry's current fullPath\n     */\n    FileSystem.prototype._fireRenameEvent = function (oldPath, newPath) {\n        this.trigger(\"rename\", oldPath, newPath);\n    };\n\n    /**\n     * Fire a change event. Clients listen for these events using FileSystem.on.\n     *\n     * @param {File|Directory} entry The entry that has changed\n     * @param {Array<File|Directory>=} added If the entry is a directory, this\n     *      is a set of new entries in the directory.\n     * @param {Array<File|Directory>=} removed If the entry is a directory, this\n     *      is a set of removed entries from the directory.\n     */\n    FileSystem.prototype._fireChangeEvent = function (entry, added, removed) {\n        this.trigger(\"change\", entry, added, removed);\n    };\n\n    /**\n     * @private\n     * Notify the system when an entry name has changed.\n     *\n     * @param {string} oldFullPath\n     * @param {string} newFullPath\n     * @param {boolean} isDirectory\n     */\n    FileSystem.prototype._handleRename = function (oldFullPath, newFullPath, isDirectory) {\n        // Update all affected entries in the index\n        this._index.entryRenamed(oldFullPath, newFullPath, isDirectory);\n    };\n\n    /**\n     * Notify the filesystem that the given directory has changed. Updates the filesystem's\n     * internal state as a result of the change, and calls back with the set of added and\n     * removed entries. Mutating FileSystemEntry operations should call this method before\n     * applying the operation's callback, and pass along the resulting change sets in the\n     * internal change event.\n     *\n     * @param {Directory} directory The directory that has changed.\n     * @param {function(Array<File|Directory>=, Array<File|Directory>=)} callback\n     *      The callback that will be applied to a set of added and a set of removed\n     *      FileSystemEntry objects.\n     */\n    FileSystem.prototype._handleDirectoryChange = function (directory, callback) {\n        var oldContents = directory._contents;\n\n        directory._clearCachedData();\n        directory.getContents(function (err, contents) {\n            var addedEntries = oldContents && contents.filter(function (entry) {\n                return oldContents.indexOf(entry) === -1;\n            });\n\n            var removedEntries = oldContents && oldContents.filter(function (entry) {\n                return contents.indexOf(entry) === -1;\n            });\n\n            // If directory is not watched, clear children's caches manually.\n            var watchedRoot = this._findWatchedRootForPath(directory.fullPath);\n            if (!watchedRoot || !watchedRoot.filter(directory.name, directory.parentPath)) {\n                this._index.visitAll(function (entry) {\n                    if (entry.fullPath.indexOf(directory.fullPath) === 0) {\n                        // Passing 'true' for a similar reason as in _unwatchEntry() - see #7150\n                        entry._clearCachedData(true);\n                    }\n                }.bind(this));\n\n                callback(addedEntries, removedEntries);\n                return;\n            }\n\n            var addedCounter = addedEntries ? addedEntries.length : 0,\n                removedCounter = removedEntries ? removedEntries.length : 0,\n                counter = addedCounter + removedCounter;\n\n            if (counter === 0) {\n                callback(addedEntries, removedEntries);\n                return;\n            }\n\n            var watchOrUnwatchCallback = function (err) {\n                if (err) {\n                    console.error(\"FileSystem error in _handleDirectoryChange after watch/unwatch entries: \" + err);\n                }\n\n                if (--counter === 0) {\n                    callback(addedEntries, removedEntries);\n                }\n            };\n\n            if (addedEntries) {\n                addedEntries.forEach(function (entry) {\n                    this._watchEntry(entry, watchedRoot, watchOrUnwatchCallback);\n                }, this);\n            }\n\n            if (removedEntries) {\n                removedEntries.forEach(function (entry) {\n                    this._unwatchEntry(entry, watchedRoot, watchOrUnwatchCallback);\n                }, this);\n            }\n        }.bind(this));\n    };\n\n    /**\n     * @private\n     * Processes a result from the file/directory watchers. Watch results are sent from the low-level implementation\n     * whenever a directory or file is changed.\n     *\n     * @param {string} path The path that changed. This could be a file or a directory.\n     * @param {FileSystemStats=} stat Optional stat for the item that changed. This param is not always\n     *         passed.\n     */\n    FileSystem.prototype._handleExternalChange = function (path, stat) {\n\n        if (!path) {\n            // This is a \"wholesale\" change event; clear all caches\n            this._index.visitAll(function (entry) {\n                // Passing 'true' for a similar reason as in _unwatchEntry() - see #7150\n                entry._clearCachedData(true);\n            });\n\n            this._fireChangeEvent(null);\n            return;\n        }\n\n        path = this._normalizePath(path, false);\n\n        var entry = this._index.getEntry(path);\n        if (entry) {\n            var oldStat = entry._stat;\n            if (entry.isFile) {\n                // Update stat and clear contents, but only if out of date\n                if (!(stat && oldStat && stat.mtime.getTime() <= oldStat.mtime.getTime())) {\n                    entry._clearCachedData();\n                    entry._stat = stat;\n                    this._fireChangeEvent(entry);\n                }\n            } else {\n                this._handleDirectoryChange(entry, function (added, removed) {\n                    entry._stat = stat;\n\n                    if (entry._isWatched()) {\n                        // We send a change even if added & removed are both zero-length. Something may still have changed,\n                        // e.g. a file may have been quickly removed & re-added before we got a chance to reread the directory\n                        // listing.\n                        this._fireChangeEvent(entry, added, removed);\n                    }\n                }.bind(this));\n            }\n        }\n    };\n\n    /**\n     * Clears all cached content. Because of the performance implications of this, this should only be used if\n     * there is a suspicion that the file system has not been updated through the normal file watchers\n     * mechanism.\n     */\n    FileSystem.prototype.clearAllCaches = function () {\n        this._handleExternalChange(null);\n    };\n\n    /**\n     * Start watching a filesystem root entry.\n     *\n     * @param {FileSystemEntry} entry - The root entry to watch. If entry is a directory,\n     *      all subdirectories that aren't explicitly filtered will also be watched.\n     * @param {function(string): boolean} filter - Returns true if a particular item should\n     *      be watched, given its name (not full path). Items that are ignored are also\n     *      filtered from Directory.getContents() results within this subtree.\n     * @param {Array<string>} filterGlobs - glob compatible string definitions for\n     *      filtering out events on the node side.\n     * @param {function(?string)=} callback - A function that is called when the watch has\n     *      completed. If the watch fails, the function will have a non-null FileSystemError\n     *      string parametr.\n     */\n    FileSystem.prototype.watch = function (entry, filter, filterGlobs, callback) {\n        // make filterGlobs an optional argument to stay backwards compatible\n        if (typeof callback === \"undefined\" && typeof filterGlobs === \"function\") {\n            callback = filterGlobs;\n            filterGlobs = null;\n        }\n\n        var fullPath = entry.fullPath;\n\n        callback = callback || function () {};\n\n        var watchingParentRoot = this._findWatchedRootForPath(fullPath);\n        if (watchingParentRoot &&\n                (watchingParentRoot.status === WatchedRoot.STARTING ||\n                 watchingParentRoot.status === WatchedRoot.ACTIVE)) {\n            callback(\"A parent of this root is already watched\");\n            return;\n        }\n\n        var watchingChildRoot = Object.keys(this._watchedRoots).some(function (path) {\n            var watchedRoot = this._watchedRoots[path],\n                watchedPath = watchedRoot.entry.fullPath;\n\n            return watchedPath.indexOf(fullPath) === 0;\n        }, this);\n\n        if (watchingChildRoot &&\n                (watchingChildRoot.status === WatchedRoot.STARTING ||\n                 watchingChildRoot.status === WatchedRoot.ACTIVE)) {\n            callback(\"A child of this root is already watched\");\n            return;\n        }\n\n        var watchedRoot = new WatchedRoot(entry, filter, filterGlobs);\n\n        this._watchedRoots[fullPath] = watchedRoot;\n\n        // Enter the STARTING state early to indiate that watched Directory\n        // objects may cache their contents. See FileSystemEntry._isWatched.\n        watchedRoot.status = WatchedRoot.STARTING;\n\n        this._watchEntry(entry, watchedRoot, function (err) {\n            if (err) {\n                console.warn(\"Failed to watch root: \", entry.fullPath, err);\n                delete this._watchedRoots[fullPath];\n                callback(err);\n                return;\n            }\n\n            watchedRoot.status = WatchedRoot.ACTIVE;\n\n            callback(null);\n        }.bind(this));\n    };\n\n    /**\n     * Stop watching a filesystem root entry.\n     *\n     * @param {FileSystemEntry} entry - The root entry to stop watching. The unwatch will\n     *      if the entry is not currently being watched.\n     * @param {function(?string)=} callback - A function that is called when the unwatch has\n     *      completed. If the unwatch fails, the function will have a non-null FileSystemError\n     *      string parameter.\n     */\n    FileSystem.prototype.unwatch = function (entry, callback) {\n        var fullPath = entry.fullPath,\n            watchedRoot = this._watchedRoots[fullPath];\n\n        callback = callback || function () {};\n\n        if (!watchedRoot) {\n            callback(FileSystemError.ROOT_NOT_WATCHED);\n            return;\n        }\n\n        // Mark this as inactive, but don't delete the entry until the unwatch is complete.\n        // This is useful for making sure we don't try to concurrently watch overlapping roots.\n        watchedRoot.status = WatchedRoot.INACTIVE;\n\n        this._unwatchEntry(entry, watchedRoot, function (err) {\n            delete this._watchedRoots[fullPath];\n\n            this._index.visitAll(function (child) {\n                if (child.fullPath.indexOf(entry.fullPath) === 0) {\n                    this._index.removeEntry(child);\n                }\n            }.bind(this));\n\n            if (err) {\n                console.warn(\"Failed to unwatch root: \", entry.fullPath, err);\n                callback(err);\n                return;\n            }\n\n            callback(null);\n        }.bind(this));\n    };\n\n    /**\n     * Unwatch all watched roots. Calls unwatch on the underlying impl for each\n     * watched root and ignores errors.\n     * @private\n     */\n    FileSystem.prototype._unwatchAll = function () {\n        console.warn(\"File watchers went offline!\");\n\n        Object.keys(this._watchedRoots).forEach(function (path) {\n            var watchedRoot = this._watchedRoots[path];\n\n            watchedRoot.status = WatchedRoot.INACTIVE;\n            delete this._watchedRoots[path];\n            this._unwatchEntry(watchedRoot.entry, watchedRoot, function () {\n                console.warn(\"Watching disabled for\", watchedRoot.entry.fullPath);\n            });\n        }, this);\n\n        // Fire a wholesale change event, clearing all caches and request that\n        // clients manually update their state.\n        this._handleExternalChange(null);\n    };\n\n\n    // The singleton instance\n    var _instance;\n\n    function _wrap(func) {\n        return function () {\n            return func.apply(_instance, arguments);\n        };\n    }\n\n    // Export public methods as proxies to the singleton instance\n    exports.init = _wrap(FileSystem.prototype.init);\n    exports.close = _wrap(FileSystem.prototype.close);\n    exports.shouldShow = _wrap(FileSystem.prototype.shouldShow);\n    exports.getFileForPath = _wrap(FileSystem.prototype.getFileForPath);\n    exports.addEntryForPathIfRequired = _wrap(FileSystem.prototype.addEntryForPathIfRequired);\n    exports.getDirectoryForPath = _wrap(FileSystem.prototype.getDirectoryForPath);\n    exports.resolve = _wrap(FileSystem.prototype.resolve);\n    exports.showOpenDialog = _wrap(FileSystem.prototype.showOpenDialog);\n    exports.showSaveDialog = _wrap(FileSystem.prototype.showSaveDialog);\n    exports.watch = _wrap(FileSystem.prototype.watch);\n    exports.unwatch = _wrap(FileSystem.prototype.unwatch);\n    exports.clearAllCaches = _wrap(FileSystem.prototype.clearAllCaches);\n\n    // Static public utility methods\n    exports.isAbsolutePath = FileSystem.isAbsolutePath;\n    exports.registerProtocolAdapter = registerProtocolAdapter;\n\n    // For testing only\n    exports._getActiveChangeCount = _wrap(FileSystem.prototype._getActiveChangeCount);\n\n    /**\n     * Add an event listener for a FileSystem event.\n     *\n     * @param {string} event The name of the event\n     * @param {function} handler The handler for the event\n     */\n    exports.on = function (event, handler) {\n        _instance.on(event, handler);\n    };\n\n    /**\n     * Remove an event listener for a FileSystem event.\n     *\n     * @param {string} event The name of the event\n     * @param {function} handler The handler for the event\n     */\n    exports.off = function (event, handler) {\n        _instance.off(event, handler);\n    };\n\n    // Export the FileSystem class as \"private\" for unit testing only.\n    exports._FileSystem = FileSystem;\n\n    // Create the singleton instance\n    _instance = new FileSystem();\n\n    // Initialize the singleton instance\n    _instance.init(require(\"fileSystemImpl\"));\n});\n"
  },
  {
    "path": "src/filesystem/FileSystemEntry.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * To ensure cache coherence, current and future asynchronous state-changing\n * operations of FileSystemEntry and its subclasses should implement the\n * following high-level sequence of steps:\n *\n * 1. Block external filesystem change events;\n * 2. Execute the low-level state-changing operation;\n * 3. Update the internal filesystem state, including caches;\n * 4. Apply the callback;\n * 5. Fire an appropriate internal change notification; and\n * 6. Unblock external change events.\n *\n * Note that because internal filesystem state is updated first, both the original\n * caller and the change notification listeners observe filesystem state that is\n * current w.r.t. the operation. Furthermore, because external change events are\n * blocked before the operation begins, listeners will only receive the internal\n * change event for the operation and not additional (or possibly inconsistent)\n * external change events.\n *\n * State-changing operations that block external filesystem change events must\n * take care to always subsequently unblock the external change events in all\n * control paths. It is safe to assume, however, that the underlying impl will\n * always apply the callback with some value.\n\n * Caches should be conservative. Consequently, the entry's cached data should\n * always be cleared if the underlying impl's operation fails. This is the case\n * event for read-only operations because an unexpected failure implies that the\n * system is in an unknown state. The entry should communicate this by failing\n * where appropriate, and should not use the cache to hide failure.\n *\n * Only watched entries should make use of cached data because change events are\n * only expected for such entries, and change events are used to granularly\n * invalidate out-of-date caches.\n *\n * By convention, callbacks are optional for asynchronous, state-changing\n * operations, but required for read-only operations. The first argument to the\n * callback should always be a nullable error string from FileSystemError.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileSystemError = require(\"filesystem/FileSystemError\"),\n        WatchedRoot     = require(\"filesystem/WatchedRoot\");\n\n    var VISIT_DEFAULT_MAX_DEPTH = 100,\n        VISIT_DEFAULT_MAX_ENTRIES = 30000;\n\n    /* Counter to give every entry a unique id */\n    var nextId = 0;\n\n    /**\n     * Model for a file system entry. This is the base class for File and Directory,\n     * and is never used directly.\n     *\n     * See the File, Directory, and FileSystem classes for more details.\n     *\n     * @constructor\n     * @param {string} path The path for this entry.\n     * @param {FileSystem} fileSystem The file system associated with this entry.\n     */\n    function FileSystemEntry(path, fileSystem) {\n        this._setPath(path);\n        this._fileSystem = fileSystem;\n        this._id = nextId++;\n    }\n\n    // Add \"fullPath\", \"name\", \"parent\", \"id\", \"isFile\" and \"isDirectory\" getters\n    Object.defineProperties(FileSystemEntry.prototype, {\n        \"fullPath\": {\n            get: function () { return this._path; },\n            set: function () { throw new Error(\"Cannot set fullPath\"); }\n        },\n        \"name\": {\n            get: function () { return this._name; },\n            set: function () { throw new Error(\"Cannot set name\"); }\n        },\n        \"parentPath\": {\n            get: function () { return this._parentPath; },\n            set: function () { throw new Error(\"Cannot set parentPath\"); }\n        },\n        \"id\": {\n            get: function () { return this._id; },\n            set: function () { throw new Error(\"Cannot set id\"); }\n        },\n        \"isFile\": {\n            get: function () { return this._isFile; },\n            set: function () { throw new Error(\"Cannot set isFile\"); }\n        },\n        \"isDirectory\": {\n            get: function () { return this._isDirectory; },\n            set: function () { throw new Error(\"Cannot set isDirectory\"); }\n        },\n        \"_impl\": {\n            get: function () { return this._fileSystem._impl; },\n            set: function () { throw new Error(\"Cannot set _impl\"); }\n        }\n    });\n\n    /**\n     * Cached stat object for this file.\n     * @type {?FileSystemStats}\n     */\n    FileSystemEntry.prototype._stat = null;\n\n    /**\n     * Parent file system.\n     * @type {!FileSystem}\n     */\n    FileSystemEntry.prototype._fileSystem = null;\n\n    /**\n     * The path of this entry.\n     * @type {string}\n     */\n    FileSystemEntry.prototype._path = null;\n\n    /**\n     * The name of this entry.\n     * @type {string}\n     */\n    FileSystemEntry.prototype._name = null;\n\n    /**\n     * The parent of this entry.\n     * @type {string}\n     */\n    FileSystemEntry.prototype._parentPath = null;\n\n    /**\n     * Whether or not the entry is a file\n     * @type {boolean}\n     */\n    FileSystemEntry.prototype._isFile = false;\n\n    /**\n     * Whether or not the entry is a directory\n     * @type {boolean}\n     */\n    FileSystemEntry.prototype._isDirectory = false;\n\n    /**\n     * Cached copy of this entry's watched root\n     * @type {entry: File|Directory, filter: function(FileSystemEntry):boolean, active: boolean}\n     */\n    FileSystemEntry.prototype._watchedRoot = undefined;\n\n    /**\n     * Cached result of _watchedRoot.filter(this.name, this.parentPath).\n     * @type {boolean}\n     */\n    FileSystemEntry.prototype._watchedRootFilterResult = undefined;\n\n    /**\n     * Determines whether or not the entry is watched.\n     * @param {boolean=} relaxed If falsey, the method will only return true if\n     *      the watched root is fully active. If true, the method will return\n     *      true if the watched root is either starting up or fully active.\n     * @return {boolean}\n     */\n    FileSystemEntry.prototype._isWatched = function (relaxed) {\n        var watchedRoot = this._watchedRoot,\n            filterResult = this._watchedRootFilterResult;\n\n        if (!watchedRoot) {\n            watchedRoot = this._fileSystem._findWatchedRootForPath(this._path);\n\n            if (watchedRoot) {\n                this._watchedRoot = watchedRoot;\n                if (watchedRoot.entry !== this) { // avoid creating entries for root's parent\n                    var parentEntry = this._fileSystem.getDirectoryForPath(this._parentPath);\n                    if (parentEntry._isWatched() === false) {\n                        filterResult = false;\n                    } else {\n                        filterResult = watchedRoot.filter(this._name, this._parentPath);\n                    }\n                } else { // root itself is watched\n                    filterResult = true;\n                }\n                this._watchedRootFilterResult = filterResult;\n            }\n        }\n\n        if (watchedRoot) {\n            if (watchedRoot.status === WatchedRoot.ACTIVE ||\n                    (relaxed && watchedRoot.status === WatchedRoot.STARTING)) {\n                return filterResult;\n            } else {\n                // We had a watched root, but it's no longer active, so it must now be invalid.\n                this._watchedRoot = undefined;\n                this._watchedRootFilterResult = false;\n                this._clearCachedData();\n            }\n        }\n        return false;\n    };\n\n    /**\n     * Update the path for this entry\n     * @private\n     * @param {String} newPath\n     */\n    FileSystemEntry.prototype._setPath = function (newPath) {\n        var parts = newPath.split(\"/\");\n        if (this.isDirectory) {\n            parts.pop(); // Remove the empty string after last trailing \"/\"\n        }\n        this._name = parts[parts.length - 1];\n        parts.pop(); // Remove name\n\n        if (parts.length > 0) {\n            this._parentPath = parts.join(\"/\") + \"/\";\n        } else {\n            // root directories have no parent path\n            this._parentPath = null;\n        }\n\n        this._path = newPath;\n\n        var watchedRoot = this._watchedRoot;\n        if (watchedRoot) {\n            if (newPath.indexOf(watchedRoot.entry.fullPath) === 0) {\n                // Update watchedRootFilterResult\n                this._watchedRootFilterResult = watchedRoot.filter(this._name, this._parentPath);\n            } else {\n                // The entry was moved outside of the watched root\n                this._watchedRoot = null;\n                this._watchedRootFilterResult = false;\n            }\n        }\n    };\n\n    /**\n     * Clear any cached data for this entry\n     * @private\n     */\n    FileSystemEntry.prototype._clearCachedData = function () {\n        this._stat = undefined;\n    };\n\n    /**\n     * Helpful toString for debugging purposes\n     */\n    FileSystemEntry.prototype.toString = function () {\n        return \"[\" + (this.isDirectory ? \"Directory \" : \"File \") + this._path + \"]\";\n    };\n\n    /**\n     * Check to see if the entry exists on disk. Note that there will NOT be an\n     * error returned if the file does not exist on the disk; in that case the\n     * error parameter will be null and the boolean will be false. The error\n     * parameter will only be truthy when an unexpected error was encountered\n     * during the test, in which case the state of the entry should be considered\n     * unknown.\n     *\n     * @param {function (?string, boolean)} callback Callback with a FileSystemError\n     *      string or a boolean indicating whether or not the file exists.\n     */\n    FileSystemEntry.prototype.exists = function (callback) {\n        if (this._stat) {\n            callback(null, true);\n            return;\n        }\n\n        this._impl.exists(this._path, function (err, exists) {\n            if (err) {\n                this._clearCachedData();\n                callback(err);\n                return;\n            }\n\n            if (!exists) {\n                this._clearCachedData();\n            }\n\n            callback(null, exists);\n        }.bind(this));\n    };\n\n    /**\n     * Returns the stats for the entry.\n     *\n     * @param {function (?string, FileSystemStats=)} callback Callback with a\n     *      FileSystemError string or FileSystemStats object.\n     */\n    FileSystemEntry.prototype.stat = function (callback) {\n        if (this._stat) {\n            callback(null, this._stat);\n            return;\n        }\n\n        this._impl.stat(this._path, function (err, stat) {\n            if (err) {\n                this._clearCachedData();\n                callback(err);\n                return;\n            }\n\n            if (this._isWatched()) {\n                this._stat = stat;\n            }\n\n            callback(null, stat);\n        }.bind(this));\n    };\n\n    /**\n     * Rename this entry.\n     *\n     * @param {string} newFullPath New path & name for this entry.\n     * @param {function (?string)=} callback Callback with a single FileSystemError\n     *      string parameter.\n     */\n    FileSystemEntry.prototype.rename = function (newFullPath, callback) {\n        callback = callback || function () {};\n\n        // Block external change events until after the write has finished\n        this._fileSystem._beginChange();\n\n        this._impl.rename(this._path, newFullPath, function (err) {\n            var oldFullPath = this._path;\n\n            try {\n                if (err) {\n                    this._clearCachedData();\n                    callback(err);\n                    return;\n                }\n\n                // Update internal filesystem state\n                this._fileSystem._handleRename(this._path, newFullPath, this.isDirectory);\n\n                try {\n                    // Notify the caller\n                    callback(null);\n                } finally {\n                    // Notify rename listeners\n                    this._fileSystem._fireRenameEvent(oldFullPath, newFullPath);\n                }\n            } finally {\n                // Unblock external change events\n                this._fileSystem._endChange();\n            }\n        }.bind(this));\n    };\n\n    /**\n     * Permanently delete this entry. For Directories, this will delete the directory\n     * and all of its contents. For reversible delete, see moveToTrash().\n     *\n     * @param {function (?string)=} callback Callback with a single FileSystemError\n     *      string parameter.\n     */\n    FileSystemEntry.prototype.unlink = function (callback) {\n        callback = callback || function () {};\n\n        // Block external change events until after the write has finished\n        this._fileSystem._beginChange();\n\n        this._clearCachedData();\n        this._impl.unlink(this._path, function (err) {\n            var parent = this._fileSystem.getDirectoryForPath(this.parentPath);\n\n            // Update internal filesystem state\n            this._fileSystem._handleDirectoryChange(parent, function (added, removed) {\n                try {\n                    // Notify the caller\n                    callback(err);\n                } finally {\n                    if (parent._isWatched()) {\n                        // Notify change listeners\n                        this._fileSystem._fireChangeEvent(parent, added, removed);\n                    }\n\n                    // Unblock external change events\n                    this._fileSystem._endChange();\n                }\n            }.bind(this));\n        }.bind(this));\n    };\n\n    /**\n     * Move this entry to the trash. If the underlying file system doesn't support move\n     * to trash, the item is permanently deleted.\n     *\n     * @param {function (?string)=} callback Callback with a single FileSystemError\n     *      string parameter.\n     */\n    FileSystemEntry.prototype.moveToTrash = function (callback) {\n        if (!this._impl.moveToTrash) {\n            this.unlink(callback);\n            return;\n        }\n\n        callback = callback || function () {};\n\n        // Block external change events until after the write has finished\n        this._fileSystem._beginChange();\n\n        this._clearCachedData();\n        this._impl.moveToTrash(this._path, function (err) {\n            var parent = this._fileSystem.getDirectoryForPath(this.parentPath);\n\n            // Update internal filesystem state\n            this._fileSystem._handleDirectoryChange(parent, function (added, removed) {\n                try {\n                    // Notify the caller\n                    callback(err);\n                } finally {\n                    if (parent._isWatched()) {\n                        // Notify change listeners\n                        this._fileSystem._fireChangeEvent(parent, added, removed);\n                    }\n\n                    // Unblock external change events\n                    this._fileSystem._endChange();\n                }\n            }.bind(this));\n        }.bind(this));\n    };\n\n    /**\n     * Private helper function for FileSystemEntry.visit that requires sanitized options.\n     *\n     * @private\n     * @param {FileSystemStats} stats - the stats for this entry\n     * @param {{string: boolean}} visitedPaths - the set of fullPaths that have already been visited\n     * @param {function(FileSystemEntry): boolean} visitor - A visitor function, which is\n     *      applied to descendent FileSystemEntry objects. If the function returns false for\n     *      a particular Directory entry, that directory's descendents will not be visited.\n     * @param {{maxDepth: number, maxEntriesCounter: {value: number}, sortList: boolean}} options\n     * @param {function(?string)=} callback Callback with single FileSystemError string parameter.\n     */\n    FileSystemEntry.prototype._visitHelper = function (stats, visitedPaths, visitor, options, callback) {\n        var maxDepth = options.maxDepth,\n            maxEntriesCounter = options.maxEntriesCounter,\n            sortList = options.sortList;\n\n        if (maxEntriesCounter.value-- <= 0 || maxDepth-- < 0) {\n            // The outer FileSystemEntry.visit call is responsible for applying\n            // the main callback to FileSystemError.TOO_MANY_FILES in this case\n            callback(null);\n            return;\n        }\n\n        if (this.isDirectory) {\n            var visitedPath = stats.realPath || this.fullPath;\n\n            if (visitedPaths.hasOwnProperty(visitedPath)) {\n                // Link cycle detected\n                callback(null);\n                return;\n            }\n\n            visitedPaths[visitedPath] = true;\n        }\n\n        if (!visitor(this) || this.isFile) {\n            callback(null);\n            return;\n        }\n\n        this.getContents(function (err, entries, entriesStats) {\n            if (err) {\n                callback(err);\n                return;\n            }\n\n            var counter = entries.length;\n            if (counter === 0) {\n                callback(null);\n                return;\n            }\n\n            function helperCallback(err) {\n                if (--counter === 0) {\n                    callback(null);\n                }\n            }\n\n            var nextOptions = {\n                maxDepth: maxDepth,\n                maxEntriesCounter: maxEntriesCounter,\n                sortList : sortList\n            };\n\n            //sort entries if required\n            function compareFilesWithIndices(index1, index2) {\n                return entries[index1]._name.toLocaleLowerCase().localeCompare(entries[index2]._name.toLocaleLowerCase());\n            }\n            if (sortList) {\n                var fileIndexes = [], i = 0;\n                for (i = 0; i < entries.length; i++) {\n                    fileIndexes[i] = i;\n                }\n                fileIndexes.sort(compareFilesWithIndices);\n                fileIndexes.forEach(function (fileIndex) {\n                    var stats = entriesStats[fileIndexes[fileIndex]];\n                    entries[fileIndexes[fileIndex]]._visitHelper(stats, visitedPaths, visitor, nextOptions, helperCallback);\n                });\n            } else {\n                entries.forEach(function (entry, index) {\n                    var stats = entriesStats[index];\n                    entry._visitHelper(stats, visitedPaths, visitor, nextOptions, helperCallback);\n                });\n            }\n        }.bind(this));\n    };\n\n    /**\n     * Visit this entry and its descendents with the supplied visitor function.\n     * Correctly handles symbolic link cycles and options can be provided to limit\n     * search depth and total number of entries visited. No particular traversal\n     * order is guaranteed; instead of relying on such an order, it is preferable\n     * to use the visit function to build a list of visited entries, sort those\n     * entries as desired, and then process them. Whenever possible, deep\n     * filesystem traversals should use this method.\n     *\n     * @param {function(FileSystemEntry): boolean} visitor - A visitor function, which is\n     *      applied to this entry and all descendent FileSystemEntry objects. If the function returns\n     *      false for a particular Directory entry, that directory's descendents will not be visited.\n     * @param {{maxDepth: number=, maxEntries: number=}=} options\n     * @param {function(?string)=} callback Callback with single FileSystemError string parameter.\n     */\n    FileSystemEntry.prototype.visit = function (visitor, options, callback) {\n        if (typeof options === \"function\") {\n            callback = options;\n            options = {};\n        } else {\n            if (options === undefined) {\n                options = {};\n            }\n\n            callback = callback || function () {};\n        }\n\n        if (options.maxDepth === undefined) {\n            options.maxDepth = VISIT_DEFAULT_MAX_DEPTH;\n        }\n\n        if (options.maxEntries === undefined) {\n            options.maxEntries = VISIT_DEFAULT_MAX_ENTRIES;\n        }\n\n        options.maxEntriesCounter = { value: options.maxEntries };\n\n        this.stat(function (err, stats) {\n            if (err) {\n                callback(err);\n                return;\n            }\n\n            this._visitHelper(stats, {}, visitor, options, function (err) {\n                if (callback) {\n                    if (err) {\n                        callback(err);\n                        return;\n                    }\n\n                    if (options.maxEntriesCounter.value < 0) {\n                        callback(FileSystemError.TOO_MANY_ENTRIES);\n                        return;\n                    }\n\n                    callback(null);\n                }\n            }.bind(this));\n        }.bind(this));\n    };\n\n    // Export this class\n    module.exports = FileSystemEntry;\n});\n"
  },
  {
    "path": "src/filesystem/FileSystemError.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * FileSystemError describes the errors that can occur when using the FileSystem, File,\n * and Directory modules.\n *\n * Error values are strings. Any \"falsy\" value: null, undefined or \"\" means \"no error\".\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * Enumerated File System Errors\n     * @enum {string}\n     */\n    module.exports = {\n        UNKNOWN                     : \"Unknown\",\n        INVALID_PARAMS              : \"InvalidParams\",\n        NOT_FOUND                   : \"NotFound\",\n        NOT_READABLE                : \"NotReadable\",\n        UNSUPPORTED_ENCODING        : \"UnsupportedEncoding\",\n        NOT_SUPPORTED               : \"NotSupported\",\n        NOT_WRITABLE                : \"NotWritable\",\n        OUT_OF_SPACE                : \"OutOfSpace\",\n        TOO_MANY_ENTRIES            : \"TooManyEntries\",\n        ALREADY_EXISTS              : \"AlreadyExists\",\n        CONTENTS_MODIFIED           : \"ContentsModified\",\n        ROOT_NOT_WATCHED            : \"RootNotBeingWatched\",\n        EXCEEDS_MAX_FILE_SIZE       : \"ExceedsMaxFileSize\",\n        NETWORK_DRIVE_NOT_SUPPORTED : \"NetworkDriveNotSupported\",\n        ENCODE_FILE_FAILED          : \"EncodeFileFailed\",\n        DECODE_FILE_FAILED          : \"DecodeFileFailed\",\n        UNSUPPORTED_UTF16_ENCODING  : \"UnsupportedUTF16Encoding\"\n\n        // FUTURE: Add remote connection errors: timeout, not logged in, connection err, etc.\n    };\n});\n"
  },
  {
    "path": "src/filesystem/FileSystemStats.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * The FileSystemStats represents a particular FileSystemEntry's stats.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * @constructor\n     * @param {{isFile: boolean, mtime: Date, size: Number, realPath: ?string, hash: object}} options\n     */\n    function FileSystemStats(options) {\n        var isFile = options.isFile;\n\n        this._isFile = isFile;\n        this._isDirectory = !isFile;\n        // in case of stats transferred over a node-domain,\n        // mtime will have JSON-ified value which needs to be restored\n        this._mtime = options.mtime instanceof Date ? options.mtime : new Date(options.mtime);\n        this._size = options.size;\n        // hash is a property introduced by brackets and it's calculated\n        // as a valueOf modification time -> calculate here if it's not present\n        this._hash = options.hash || this._mtime.valueOf();\n\n        var realPath = options.realPath;\n        if (realPath) {\n            if (!isFile && realPath[realPath.length - 1] !== \"/\") {\n                realPath += \"/\";\n            }\n\n            this._realPath = realPath;\n        }\n    }\n\n    // Add \"isFile\", \"isDirectory\", \"mtime\" and \"size\" getters\n    Object.defineProperties(FileSystemStats.prototype, {\n        \"isFile\": {\n            get: function () { return this._isFile; },\n            set: function () { throw new Error(\"Cannot set isFile\"); }\n        },\n        \"isDirectory\": {\n            get: function () { return this._isDirectory; },\n            set: function () { throw new Error(\"Cannot set isDirectory\"); }\n        },\n        \"mtime\": {\n            get: function () { return this._mtime; },\n            set: function () { throw new Error(\"Cannot set mtime\"); }\n        },\n        \"size\": {\n            get: function () { return this._size; },\n            set: function () { throw new Error(\"Cannot set size\"); }\n        },\n        \"realPath\": {\n            get: function () { return this._realPath; },\n            set: function () { throw new Error(\"Cannot set realPath\"); }\n        }\n    });\n\n    /**\n     * Whether or not this is a stats object for a file\n     * @type {boolean}\n     */\n    FileSystemStats.prototype._isFile = false;\n\n    /**\n     * Whether or not this is a stats object for a directory\n     * @type {boolean}\n     */\n    FileSystemStats.prototype._isDirectory = false;\n\n    /**\n     * Modification time for a file\n     * @type {Date}\n     */\n    FileSystemStats.prototype._mtime = null;\n\n    /**\n     * Size in bytes of a file\n     * @type {Number}\n     */\n    FileSystemStats.prototype._size = null;\n\n    /**\n     * Consistency hash for a file\n     * @type {object}\n     */\n    FileSystemStats.prototype._hash = null;\n\n    /**\n     * The canonical path of this file or directory ONLY if it is a symbolic link,\n     * and null otherwise.\n     *\n     * @type {?string}\n     */\n    FileSystemStats.prototype._realPath = null;\n\n    module.exports = FileSystemStats;\n});\n"
  },
  {
    "path": "src/filesystem/WatchedRoot.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /*\n     * Represents file or directory structure watched by the FileSystem. If the\n     * entry is a directory, all children (that pass the supplied filter function)\n     * are also watched. A WatchedRoot object begins and ends its life in the\n     * INACTIVE state. While in the process of starting up watchers, the WatchedRoot\n     * is in the STARTING state. When watchers are ready, the WatchedRoot enters\n     * the ACTIVE state.\n     *\n     * See the FileSystem class for more details.\n     *\n     * @constructor\n     * @param {File|Directory} entry\n     * @param {function(string, string):boolean} filter\n     * @param {Array<string>} filterGlobs\n     */\n    function WatchedRoot(entry, filter, filterGlobs) {\n        this.entry = entry;\n        this.filter = filter;\n        this.filterGlobs = filterGlobs;\n    }\n\n    // Status constants\n    WatchedRoot.INACTIVE = 0;\n    WatchedRoot.STARTING = 1;\n    WatchedRoot.ACTIVE = 2;\n\n    /**\n     * @type {File|Directory}\n     */\n    WatchedRoot.prototype.entry = null;\n\n    /**\n     * @type {function(string, string):boolean}\n     */\n    WatchedRoot.prototype.filter = null;\n\n    /**\n     * @type {Array<string>}\n     */\n    WatchedRoot.prototype.filterGlobs = null;\n\n    /**\n     * @type {number}\n     */\n    WatchedRoot.prototype.status = WatchedRoot.INACTIVE;\n\n\n    // Export this class\n    module.exports = WatchedRoot;\n});\n"
  },
  {
    "path": "src/filesystem/impls/appshell/AppshellFileSystem.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global appshell */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils           = require(\"file/FileUtils\"),\n        FileSystemStats     = require(\"filesystem/FileSystemStats\"),\n        FileSystemError     = require(\"filesystem/FileSystemError\"),\n        NodeDomain          = require(\"utils/NodeDomain\");\n\n    /**\n     * @const\n     */\n    var FILE_WATCHER_BATCH_TIMEOUT = 200;   // 200ms - granularity of file watcher changes\n\n    /**\n     * Callback to notify FileSystem of watcher changes\n     * @type {?function(string, FileSystemStats=)}\n     */\n    var _changeCallback;\n\n    /**\n     * Callback to notify FileSystem if watchers stop working entirely\n     * @type {?function()}\n     */\n    var _offlineCallback;\n\n    /** Timeout used to batch up file watcher changes (setTimeout() return value) */\n    var _changeTimeout;\n\n    /**\n     * Pending file watcher changes - map from fullPath to flag indicating whether we need to pass stats\n     * to _changeCallback() for this path.\n     * @type {!Object.<string, boolean>}\n     */\n    var _pendingChanges = {};\n\n    var _bracketsPath   = FileUtils.getNativeBracketsDirectoryPath(),\n        _modulePath     = FileUtils.getNativeModuleDirectoryPath(module),\n        _nodePath       = \"node/FileWatcherDomain\",\n        _domainPath     = [_bracketsPath, _modulePath, _nodePath].join(\"/\"),\n        _nodeDomain     = new NodeDomain(\"fileWatcher\", _domainPath);\n\n    var _isRunningOnWindowsXP = window.navigator.userAgent.indexOf(\"Windows NT 5.\") >= 0;\n\n\n    // If the connection closes, notify the FileSystem that watchers have gone offline.\n    _nodeDomain.connection.on(\"close\", function (event, promise) {\n        if (_offlineCallback) {\n            _offlineCallback();\n        }\n    });\n\n    /**\n     * Enqueue a file change event for eventual reporting back to the FileSystem.\n     *\n     * @param {string} changedPath The path that was changed\n     * @param {object} stats Stats coming from the underlying watcher, if available\n     * @private\n     */\n    function _enqueueChange(changedPath, stats) {\n        _pendingChanges[changedPath] = stats;\n        if (!_changeTimeout) {\n            _changeTimeout = window.setTimeout(function () {\n                if (_changeCallback) {\n                    Object.keys(_pendingChanges).forEach(function (path) {\n                        _changeCallback(path, _pendingChanges[path]);\n                    });\n                }\n\n                _changeTimeout = null;\n                _pendingChanges = {};\n            }, FILE_WATCHER_BATCH_TIMEOUT);\n        }\n    }\n\n    /**\n     * Event handler for the Node fileWatcher domain's change event.\n     *\n     * @param {jQuery.Event} The underlying change event\n     * @param {string} event The type of the event: \"changed\", \"created\" or \"deleted\"\n     * @param {string} parentDirPath The path to the directory holding entry that has changed\n     * @param {string=} entryName The name of the file/directory that has changed\n     * @param {object} statsObj Object that can be used to construct FileSystemStats\n     * @private\n     */\n    function _fileWatcherChange(evt, event, parentDirPath, entryName, statsObj) {\n        var change;\n        switch (event) {\n        case \"changed\":\n            // an existing file/directory was modified; stats are passed if available\n            var fsStats;\n            if (statsObj) {\n                fsStats = new FileSystemStats(statsObj);\n            } else {\n                console.warn(\"FileWatcherDomain was expected to deliver stats for changed event!\");\n            }\n            _enqueueChange(parentDirPath + entryName, fsStats);\n            break;\n        case \"created\":\n        case \"deleted\":\n            // file/directory was created/deleted; fire change on parent to reload contents\n            _enqueueChange(parentDirPath, null);\n            break;\n        default:\n            console.error(\"Unexpected 'change' event:\", event);\n        }\n    }\n\n    // Setup the change handler. This only needs to happen once.\n    _nodeDomain.on(\"change\", _fileWatcherChange);\n\n    /**\n     * Convert appshell error codes to FileSystemError values.\n     *\n     * @param {?number} err An appshell error code\n     * @return {?string} A FileSystemError string, or null if there was no error code.\n     * @private\n     */\n    function _mapError(err) {\n        if (!err) {\n            return null;\n        }\n\n        switch (err) {\n        case appshell.fs.ERR_INVALID_PARAMS:\n            return FileSystemError.INVALID_PARAMS;\n        case appshell.fs.ERR_NOT_FOUND:\n            return FileSystemError.NOT_FOUND;\n        case appshell.fs.ERR_CANT_READ:\n            return FileSystemError.NOT_READABLE;\n        case appshell.fs.ERR_CANT_WRITE:\n            return FileSystemError.NOT_WRITABLE;\n        case appshell.fs.ERR_UNSUPPORTED_ENCODING:\n            return FileSystemError.UNSUPPORTED_ENCODING;\n        case appshell.fs.ERR_OUT_OF_SPACE:\n            return FileSystemError.OUT_OF_SPACE;\n        case appshell.fs.ERR_FILE_EXISTS:\n            return FileSystemError.ALREADY_EXISTS;\n        case appshell.fs.ERR_ENCODE_FILE_FAILED:\n            return FileSystemError.ENCODE_FILE_FAILED;\n        case appshell.fs.ERR_DECODE_FILE_FAILED:\n            return FileSystemError.DECODE_FILE_FAILED;\n        case appshell.fs.ERR_UNSUPPORTED_UTF16_ENCODING:\n            return FileSystemError.UNSUPPORTED_UTF16_ENCODING;\n        }\n        return FileSystemError.UNKNOWN;\n    }\n\n    /**\n     * Convert a callback to one that transforms its first parameter from an\n     * appshell error code to a FileSystemError string.\n     *\n     * @param {function(?number)} cb A callback that expects an appshell error code\n     * @return {function(?string)} A callback that expects a FileSystemError string\n     * @private\n     */\n    function _wrap(cb) {\n        return function (err) {\n            var args = Array.prototype.slice.call(arguments);\n            args[0] = _mapError(args[0]);\n            cb.apply(null, args);\n        };\n    }\n\n    /**\n     * Display an open-files dialog to the user and call back asynchronously with\n     * either a FileSystmError string or an array of path strings, which indicate\n     * the entry or entries selected.\n     *\n     * @param {boolean} allowMultipleSelection\n     * @param {boolean} chooseDirectories\n     * @param {string} title\n     * @param {string} initialPath\n     * @param {Array.<string>=} fileTypes\n     * @param {function(?string, Array.<string>=)} callback\n     */\n    function showOpenDialog(allowMultipleSelection, chooseDirectories, title, initialPath, fileTypes, callback) {\n        appshell.fs.showOpenDialog(allowMultipleSelection, chooseDirectories, title, initialPath, fileTypes, _wrap(callback));\n    }\n\n    /**\n     * Display a save-file dialog and call back asynchronously with either a\n     * FileSystemError string or the path to which the user has chosen to save\n     * the file. If the dialog is cancelled, the path string will be empty.\n     *\n     * @param {string} title\n     * @param {string} initialPath\n     * @param {string} proposedNewFilename\n     * @param {function(?string, string=)} callback\n     */\n    function showSaveDialog(title, initialPath, proposedNewFilename, callback) {\n        appshell.fs.showSaveDialog(title, initialPath, proposedNewFilename, _wrap(callback));\n    }\n\n    /**\n     * Stat the file or directory at the given path, calling back\n     * asynchronously with either a FileSystemError string or the entry's\n     * associated FileSystemStats object.\n     *\n     * @param {string} path\n     * @param {function(?string, FileSystemStats=)} callback\n     */\n    function stat(path, callback) {\n        appshell.fs.stat(path, function (err, stats) {\n            if (err) {\n                callback(_mapError(err));\n            } else {\n                var options = {\n                    isFile: stats.isFile(),\n                    mtime: stats.mtime,\n                    size: stats.size,\n                    realPath: stats.realPath,\n                    hash: stats.mtime.getTime()\n                };\n\n                var fsStats = new FileSystemStats(options);\n\n                callback(null, fsStats);\n            }\n        });\n    }\n\n    /**\n     * Determine whether a file or directory exists at the given path by calling\n     * back asynchronously with either a FileSystemError string or a boolean,\n     * which is true if the file exists and false otherwise. The error will never\n     * be FileSystemError.NOT_FOUND; in that case, there will be no error and the\n     * boolean parameter will be false.\n     *\n     * @param {string} path\n     * @param {function(?string, boolean)} callback\n     */\n    function exists(path, callback) {\n        stat(path, function (err) {\n            if (err) {\n                if (err === FileSystemError.NOT_FOUND) {\n                    callback(null, false);\n                } else {\n                    callback(err);\n                }\n                return;\n            }\n\n            callback(null, true);\n        });\n    }\n\n    /**\n     * Read the contents of the directory at the given path, calling back\n     * asynchronously either with a FileSystemError string or an array of\n     * FileSystemEntry objects along with another consistent array, each index\n     * of which either contains a FileSystemStats object for the corresponding\n     * FileSystemEntry object in the second parameter or a FileSystemError\n     * string describing a stat error.\n     *\n     * @param {string} path\n     * @param {function(?string, Array.<FileSystemEntry>=, Array.<string|FileSystemStats>=)} callback\n     */\n    function readdir(path, callback) {\n        appshell.fs.readdir(path, function (err, contents) {\n            if (err) {\n                callback(_mapError(err));\n                return;\n            }\n\n            var count = contents.length;\n            if (!count) {\n                callback(null, [], []);\n                return;\n            }\n\n            var stats = [];\n            contents.forEach(function (val, idx) {\n                stat(path + \"/\" + val, function (err, stat) {\n                    stats[idx] = err || stat;\n                    count--;\n                    if (count <= 0) {\n                        callback(null, contents, stats);\n                    }\n                });\n            });\n        });\n    }\n\n    /**\n     * Create a directory at the given path, and call back asynchronously with\n     * either a FileSystemError string or a stats object for the newly created\n     * directory. The octal mode parameter is optional; if unspecified, the mode\n     * of the created directory is implementation dependent.\n     *\n     * @param {string} path\n     * @param {number=} mode The base-eight mode of the newly created directory.\n     * @param {function(?string, FileSystemStats=)=} callback\n     */\n    function mkdir(path, mode, callback) {\n        if (typeof mode === \"function\") {\n            callback = mode;\n            mode = parseInt(\"0755\", 8);\n        }\n        appshell.fs.makedir(path, mode, function (err) {\n            if (err) {\n                callback(_mapError(err));\n            } else {\n                stat(path, function (err, stat) {\n                    callback(err, stat);\n                });\n            }\n        });\n    }\n\n    /**\n     * Rename the file or directory at oldPath to newPath, and call back\n     * asynchronously with a possibly null FileSystemError string.\n     *\n     * @param {string} oldPath\n     * @param {string} newPath\n     * @param {function(?string)=} callback\n     */\n    function rename(oldPath, newPath, callback) {\n        appshell.fs.rename(oldPath, newPath, _wrap(callback));\n    }\n\n    /**\n     * Read the contents of the file at the given path, calling back\n     * asynchronously with either a FileSystemError string, or with the data and\n     * the FileSystemStats object associated with the read file. The options\n     * parameter can be used to specify an encoding (default \"utf8\"), and also\n     * a cached stats object that the implementation is free to use in order\n     * to avoid an additional stat call.\n     *\n     * Note: if either the read or the stat call fails then neither the read data\n     * nor stat will be passed back, and the call should be considered to have failed.\n     * If both calls fail, the error from the read call is passed back.\n     *\n     * @param {string} path\n     * @param {{encoding: string=, stat: FileSystemStats=}} options\n     * @param {function(?string, string=, FileSystemStats=)} callback\n     */\n    function readFile(path, options, callback) {\n        var encoding = options.encoding || \"utf8\";\n\n        // callback to be executed when the call to stat completes\n        //  or immediately if a stat object was passed as an argument\n        function doReadFile(stat) {\n            if (stat.size > (FileUtils.MAX_FILE_SIZE)) {\n                callback(FileSystemError.EXCEEDS_MAX_FILE_SIZE);\n            } else {\n                appshell.fs.readFile(path, encoding, function (_err, _data, encoding, preserveBOM) {\n                    if (_err) {\n                        callback(_mapError(_err));\n                    } else {\n                        callback(null, _data, encoding, preserveBOM, stat);\n                    }\n                });\n            }\n        }\n\n        if (options.stat) {\n            doReadFile(options.stat);\n        } else {\n            exports.stat(path, function (_err, _stat) {\n                if (_err) {\n                    callback(_err);\n                } else {\n                    doReadFile(_stat);\n                }\n            });\n        }\n    }\n    /**\n     * Write data to the file at the given path, calling back asynchronously with\n     * either a FileSystemError string or the FileSystemStats object associated\n     * with the written file and a boolean that indicates whether the file was\n     * created by the write (true) or not (false). If no file exists at the\n     * given path, a new file will be created. The options parameter can be used\n     * to specify an encoding (default \"utf8\"), an octal mode (default\n     * unspecified and implementation dependent), and a consistency hash, which\n     * is used to the current state of the file before overwriting it. If a\n     * consistency hash is provided but does not match the hash of the file on\n     * disk, a FileSystemError.CONTENTS_MODIFIED error is passed to the callback.\n     *\n     * @param {string} path\n     * @param {string} data\n     * @param {{encoding : string=, mode : number=, expectedHash : object=, expectedContents : string=}} options\n     * @param {function(?string, FileSystemStats=, boolean)} callback\n     */\n    function writeFile(path, data, options, callback) {\n        var encoding = options.encoding || \"utf8\",\n            preserveBOM = options.preserveBOM;\n\n        function _finishWrite(created) {\n            appshell.fs.writeFile(path, data, encoding, preserveBOM, function (err) {\n                if (err) {\n                    callback(_mapError(err));\n                } else {\n                    stat(path, function (err, stat) {\n                        callback(err, stat, created);\n                    });\n                }\n            });\n        }\n\n        stat(path, function (err, stats) {\n            if (err) {\n                switch (err) {\n                case FileSystemError.NOT_FOUND:\n                    _finishWrite(true);\n                    break;\n                default:\n                    callback(err);\n                }\n                return;\n            }\n\n            if (options.hasOwnProperty(\"expectedHash\") && options.expectedHash !== stats._hash) {\n                console.error(\"Blind write attempted: \", path, stats._hash, options.expectedHash);\n\n                if (options.hasOwnProperty(\"expectedContents\")) {\n                    appshell.fs.readFile(path, encoding, function (_err, _data) {\n                        if (_err || _data !== options.expectedContents) {\n                            callback(FileSystemError.CONTENTS_MODIFIED);\n                            return;\n                        }\n\n                        _finishWrite(false);\n                    });\n                    return;\n                } else {\n                    callback(FileSystemError.CONTENTS_MODIFIED);\n                    return;\n                }\n            }\n\n            _finishWrite(false);\n        });\n    }\n\n    /**\n     * Unlink (i.e., permanently delete) the file or directory at the given path,\n     * calling back asynchronously with a possibly null FileSystemError string.\n     * Directories will be unlinked even when non-empty.\n     *\n     * @param {string} path\n     * @param {function(string)=} callback\n     */\n    function unlink(path, callback) {\n        appshell.fs.unlink(path, function (err) {\n            callback(_mapError(err));\n        });\n    }\n\n    /**\n     * Move the file or directory at the given path to a system dependent trash\n     * location, calling back asynchronously with a possibly null FileSystemError\n     * string. Directories will be moved even when non-empty.\n     *\n     * @param {string} path\n     * @param {function(string)=} callback\n     */\n    function moveToTrash(path, callback) {\n        appshell.fs.moveToTrash(path, function (err) {\n            callback(_mapError(err));\n        });\n    }\n\n    /**\n     * Initialize file watching for this filesystem, using the supplied\n     * changeCallback to provide change notifications. The first parameter of\n     * changeCallback specifies the changed path (either a file or a directory);\n     * if this parameter is null, it indicates that the implementation cannot\n     * specify a particular changed path, and so the callers should consider all\n     * paths to have changed and to update their state accordingly. The second\n     * parameter to changeCallback is an optional FileSystemStats object that\n     * may be provided in case the changed path already exists and stats are\n     * readily available. The offlineCallback will be called in case watchers\n     * are no longer expected to function properly. All watched paths are\n     * cleared when the offlineCallback is called.\n     *\n     * @param {function(?string, FileSystemStats=)} changeCallback\n     * @param {function()=} offlineCallback\n     */\n    function initWatchers(changeCallback, offlineCallback) {\n        _changeCallback = changeCallback;\n        _offlineCallback = offlineCallback;\n\n        if (_isRunningOnWindowsXP && _offlineCallback) {\n            _offlineCallback();\n        }\n    }\n\n    /**\n     * Start providing change notifications for the file or directory at the\n     * given path, calling back asynchronously with a possibly null FileSystemError\n     * string when the initialization is complete. Notifications are provided\n     * using the changeCallback function provided by the initWatchers method.\n     * Note that change notifications are only provided recursively for directories\n     * when the recursiveWatch property of this module is true.\n     *\n     * @param {string} path\n     * @param {Array<string>} ignored\n     * @param {function(?string)=} callback\n     */\n    function watchPath(path, ignored, callback) {\n        if (_isRunningOnWindowsXP) {\n            callback(FileSystemError.NOT_SUPPORTED);\n            return;\n        }\n        appshell.fs.isNetworkDrive(path, function (err, isNetworkDrive) {\n            if (err || isNetworkDrive) {\n                if (isNetworkDrive) {\n                    callback(FileSystemError.NETWORK_DRIVE_NOT_SUPPORTED);\n                } else {\n                    callback(FileSystemError.UNKNOWN);\n                }\n                return;\n            }\n            _nodeDomain.exec(\"watchPath\", path, ignored)\n                .then(callback, callback);\n        });\n    }\n    /**\n     * Stop providing change notifications for the file or directory at the\n     * given path, calling back asynchronously with a possibly null FileSystemError\n     * string when the operation is complete.\n     * This function needs to mirror the signature of watchPath\n     * because of FileSystem.prototype._watchOrUnwatchEntry implementation.\n     *\n     * @param {string} path\n     * @param {Array<string>} ignored\n     * @param {function(?string)=} callback\n     */\n    function unwatchPath(path, ignored, callback) {\n        _nodeDomain.exec(\"unwatchPath\", path)\n            .then(callback, callback);\n    }\n\n    /**\n     * Stop providing change notifications for all previously watched files and\n     * directories, optionally calling back asynchronously with a possibly null\n     * FileSystemError string when the operation is complete.\n     *\n     * @param {function(?string)=} callback\n     */\n    function unwatchAll(callback) {\n        _nodeDomain.exec(\"unwatchAll\")\n            .then(callback, callback);\n    }\n\n\n    // Export public API\n    exports.showOpenDialog  = showOpenDialog;\n    exports.showSaveDialog  = showSaveDialog;\n    exports.exists          = exists;\n    exports.readdir         = readdir;\n    exports.mkdir           = mkdir;\n    exports.rename          = rename;\n    exports.stat            = stat;\n    exports.readFile        = readFile;\n    exports.writeFile       = writeFile;\n    exports.unlink          = unlink;\n    exports.moveToTrash     = moveToTrash;\n    exports.initWatchers    = initWatchers;\n    exports.watchPath       = watchPath;\n    exports.unwatchPath     = unwatchPath;\n    exports.unwatchAll      = unwatchAll;\n\n    /**\n     * Indicates whether or not recursive watching notifications are supported\n     * by the watchPath call.\n     *\n     * @type {boolean}\n     */\n    exports.recursiveWatch = true;\n\n    /**\n     * Indicates whether or not the filesystem should expect and normalize UNC\n     * paths. If set, then //server/directory/ is a normalized path; otherwise the\n     * filesystem will normalize it to /server/directory. Currently, UNC path\n     * normalization only occurs on Windows.\n     *\n     * @type {boolean}\n     */\n    exports.normalizeUNCPaths = appshell.platform === \"win\";\n});\n"
  },
  {
    "path": "src/filesystem/impls/appshell/node/CSharpWatcher.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * Code for working with CodeHelper.exe was inspired by:\n * https://github.com/Microsoft/vscode/blob/314e122b16c5c1ca0288c8006e9c9c3039a51cd7/src/vs/workbench/services/files/node/watcher/win32/csharpWatcherService.ts\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar fs = require(\"fs\");\nvar fspath = require(\"path\");\nvar cp = require(\"child_process\");\nvar anymatch = require('anymatch');\nvar FileWatcherManager = require(\"./FileWatcherManager\");\n\nfunction buildMatcher(ignored) {\n    // in case of a glob like **/.git we want also to ignore its contents **/.git/**\n    return anymatch(ignored.concat(ignored.map(function (glob) {\n        return glob + \"/**\";\n    })));\n}\n\nfunction watchPath(path, ignored, _watcherMap) {\n\n    var ignoreMatcher = buildMatcher(ignored);\n    var closing = false;\n\n    function processLine(line) {\n        if (line === \"\") {\n            return;\n        }\n\n        var parts = line.split(\"|\");\n        if (parts.length !== 2) {\n            console.warn(\"CSharpWatcher unexpected line: '\" + line + \"'\");\n            return;\n        }\n\n        var type = parseInt(parts[0], 10);\n        // convert it back to unix path and clear trailing whitespace\n        var absolutePath = parts[1].replace(/\\\\/g, \"/\").replace(/\\s+$/g, \"\");\n\n        // convert type to an event\n        var event;\n        switch (type) {\n        case 0:\n            event = \"changed\";\n            break;\n        case 1:\n            event = \"created\";\n            break;\n        case 2:\n            event = \"deleted\";\n            break;\n        default:\n            console.warn(\"CSharpWatcher event type: \" + type);\n            return;\n        }\n\n        // make sure ignored events are not emitted\n        if (ignoreMatcher(absolutePath)) {\n            return;\n        }\n\n        var parentDirPath = fspath.dirname(absolutePath) + \"/\";\n        var entryName = fspath.basename(absolutePath);\n\n        // we need stats object for changed event\n        if (event === \"changed\") {\n            fs.stat(absolutePath, function (err, nodeFsStats) {\n                if (err) {\n                    console.warn(\"CSharpWatcher err getting stats: \" + err.toString());\n                }\n                FileWatcherManager.emitChange(event, parentDirPath, entryName, nodeFsStats);\n            });\n        } else {\n            FileWatcherManager.emitChange(event, parentDirPath, entryName, null);\n        }\n    }\n\n    function onError(err) {\n        console.warn(\"CSharpWatcher process error: \" + err.toString());\n        FileWatcherManager.unwatchPath(path);\n    }\n\n    function onExit(code, signal) {\n        if (!closing || signal !== \"SIGTERM\") {\n            console.warn(\"CSharpWatcher terminated unexpectedly with code: \" + code + \", signal: \" + signal);\n        }\n        FileWatcherManager.unwatchPath(path);\n    }\n\n    try {\n\n        var args = [\n            // fspath.resolve will normalize slashes to windows format\n            fspath.resolve(path)\n        ];\n        var handle = cp.spawn(fspath.resolve(__dirname, \"win32\", \"CodeHelper.exe\"), args);\n\n        // Events over stdout\n        handle.stdout.on(\"data\", function (buffer) {\n            var lines = buffer.toString(\"utf8\").split(\"\\n\");\n            while (lines.length > 0) {\n                processLine(lines.shift());\n            }\n        });\n\n        // Errors\n        handle.on(\"error\", onError);\n        handle.stderr.on(\"data\", onError);\n\n        // Exit\n        handle.on(\"exit\", onExit);\n\n        // Add handler for closing to the _watcherMap\n        _watcherMap[path] = {\n            close: function () {\n                closing = true;\n                handle.kill();\n            }\n        };\n\n    } catch (err) {\n        console.warn(\"Failed to watch file \" + path + \": \" + (err && err.message));\n    }\n}\n\nexports.watchPath = watchPath;\n"
  },
  {
    "path": "src/filesystem/impls/appshell/node/ChokidarWatcher.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar fspath = require(\"path\");\nvar chokidar = require(\"chokidar\");\nvar FileWatcherManager = require(\"./FileWatcherManager\");\n\nfunction watchPath(path, ignored, _watcherMap) {\n    try {\n        var watcher = chokidar.watch(path, {\n            persistent: true,\n            ignoreInitial: true,\n            ignorePermissionErrors: true,\n            followSymlinks: true,\n            ignored: ignored,\n            interval: 1000, // while not used in normal cases, if any error causes chokidar to fallback to polling, increase its intervals\n            binaryInterval: 1000\n        });\n\n        watcher.on(\"all\", function (type, filename, nodeFsStats) {\n            var event;\n            switch (type) {\n            case \"change\":\n                event = \"changed\";\n                break;\n            case \"add\":\n            case \"addDir\":\n                event = \"created\";\n                break;\n            case \"unlink\":\n            case \"unlinkDir\":\n                event = \"deleted\";\n                break;\n            default:\n                event = null;\n            }\n            if (!event || !filename) {\n                return;\n            }\n            // make sure it's normalized\n            filename = filename.replace(/\\\\/g, \"/\");\n            var parentDirPath = fspath.dirname(filename) + \"/\";\n            var entryName = fspath.basename(filename);\n            FileWatcherManager.emitChange(event, parentDirPath, entryName, nodeFsStats);\n        });\n\n        _watcherMap[path] = watcher;\n\n        watcher.on(\"error\", function (err) {\n            console.error(\"Error watching file \" + path + \": \" + (err && err.message));\n            FileWatcherManager.unwatchPath(path);\n        });\n    } catch (err) {\n        console.warn(\"Failed to watch file \" + path + \": \" + (err && err.message));\n    }\n}\n\nexports.watchPath = watchPath;\n"
  },
  {
    "path": "src/filesystem/impls/appshell/node/FileWatcherDomain.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar os = require(\"os\");\nvar watcherManager = require(\"./FileWatcherManager\");\nvar watcherImpl;\nif (process.platform === \"win32\") {\n    watcherImpl = require(\"./CSharpWatcher\");\n} else {\n    watcherImpl = require(\"./ChokidarWatcher\");\n}\n\n/**\n * Initialize the \"fileWatcher\" domain.\n * The fileWatcher domain handles watching and un-watching directories.\n */\nfunction init(domainManager) {\n    if (!domainManager.hasDomain(\"fileWatcher\")) {\n        domainManager.registerDomain(\"fileWatcher\", {major: 0, minor: 1});\n    }\n\n    domainManager.registerCommand(\n        \"fileWatcher\",\n        \"watchPath\",\n        watcherManager.watchPath,\n        false,\n        \"Start watching a file or directory\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path of the file or directory to watch\"\n        }, {\n            name: \"ignored\",\n            type: \"array\",\n            description: \"list of path to ignore\"\n        }]\n    );\n    domainManager.registerCommand(\n        \"fileWatcher\",\n        \"unwatchPath\",\n        watcherManager.unwatchPath,\n        false,\n        \"Stop watching a single file or a directory and it's descendants\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"absolute filesystem path of the file or directory to unwatch\"\n        }]\n    );\n    domainManager.registerCommand(\n        \"fileWatcher\",\n        \"unwatchAll\",\n        watcherManager.unwatchAll,\n        false,\n        \"Stop watching all files and directories\"\n    );\n    domainManager.registerEvent(\n        \"fileWatcher\",\n        \"change\",\n        [\n            {name: \"event\", type: \"string\"},\n            {name: \"parentDirPath\", type: \"string\"},\n            {name: \"entryName\", type: \"string\"},\n            {name: \"statsObj\", type: \"object\"}\n        ]\n    );\n\n    watcherManager.setDomainManager(domainManager);\n    watcherManager.setWatcherImpl(watcherImpl);\n\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/filesystem/impls/appshell/node/FileWatcherManager.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar _watcherMap = {};\nvar _domainManager = null;\nvar _watcherImpl = null;\n\nfunction setDomainManager(dm) {\n    _domainManager = dm;\n}\n\nfunction setWatcherImpl(impl) {\n    _watcherImpl = impl;\n}\n\n/**\n * Transform Node's native fs.stats to a format that can be sent through domain\n * @param {stats} nodeFsStats Node's fs.stats result\n * @return {object} Can be consumed by new FileSystemStats(object); in Brackets\n */\nfunction normalizeStats(nodeFsStats) {\n    // current shell's stat method floors the mtime to the nearest thousand\n    // which causes problems when comparing timestamps\n    // so we have to round mtime to the nearest thousand too\n    var mtime = Math.floor(nodeFsStats.mtime.getTime() / 1000) * 1000;\n\n    // from shell: If \"filename\" is a symlink,\n    // realPath should be the actual path to the linked object\n    // not implemented in shell yet\n    return {\n        isFile: nodeFsStats.isFile(),\n        isDirectory: nodeFsStats.isDirectory(),\n        mtime: mtime,\n        size: nodeFsStats.size,\n        realPath: null,\n        hash: mtime\n    };\n}\n\n/**\n * Un-watch a file or directory.\n * @private\n * @param {string} path File or directory to unwatch.\n */\nfunction _unwatchPath(path) {\n    var watcher = _watcherMap[path];\n\n    if (watcher) {\n        try {\n            watcher.close();\n        } catch (err) {\n            console.warn(\"Failed to unwatch file \" + path + \": \" + (err && err.message));\n        } finally {\n            delete _watcherMap[path];\n        }\n    }\n}\n\n/**\n * Un-watch a file or directory. For directories, unwatch all descendants.\n * @param {string} path File or directory to unwatch.\n */\nfunction unwatchPath(path) {\n    Object.keys(_watcherMap).forEach(function (keyPath) {\n        if (keyPath.indexOf(path) === 0) {\n            _unwatchPath(keyPath);\n        }\n    });\n}\n\n/**\n * Watch a file or directory.\n * @param {string} path File or directory to watch.\n * @param {Array<string>} ignored List of entries to ignore during watching.\n */\nfunction watchPath(path, ignored) {\n    if (_watcherMap.hasOwnProperty(path)) {\n        return;\n    }\n    return _watcherImpl.watchPath(path, ignored, _watcherMap, _domainManager);\n}\n\n/**\n * Un-watch all files and directories.\n */\nfunction unwatchAll() {\n    var path;\n\n    for (path in _watcherMap) {\n        if (_watcherMap.hasOwnProperty(path)) {\n            unwatchPath(path);\n        }\n    }\n}\n\nfunction emitChange(event, parentDirPath, entryName, nodeFsStats) {\n    // make sure stats are normalized for domain transfer\n    var statsObj = nodeFsStats ? normalizeStats(nodeFsStats) : null;\n    _domainManager.emitEvent(\"fileWatcher\", \"change\", [event, parentDirPath, entryName, statsObj]);\n}\n\nexports.setDomainManager = setDomainManager;\nexports.setWatcherImpl = setWatcherImpl;\nexports.unwatchPath = unwatchPath;\nexports.watchPath = watchPath;\nexports.unwatchAll = unwatchAll;\nexports.emitChange = emitChange;\n"
  },
  {
    "path": "src/filesystem/impls/appshell/node/win32/CodeHelper.md",
    "content": "# Native File Watching for Windows using C# FileSystemWatcher\n\n- Repository: https://github.com/Microsoft/vscode-filewatcher-windows\n\n# Build\n\n- Build in \"Release\" config\n- Copy CodeHelper.exe over into this folder"
  },
  {
    "path": "src/filesystem/impls/appshell/node/win32/LICENSE",
    "content": "\nCopyright (c) Microsoft Corporation\n\nAll rights reserved. \n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation \nfiles (the \"\"Software\"\"), to deal in the Software without restriction, including without limitation the rights to use, copy, \nmodify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software \nis furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS \nBE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT \nOF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "src/help/HelpCommandHandlers.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit                 = require(\"utils/AppInit\"),\n        BuildInfoUtils          = require(\"utils/BuildInfoUtils\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Commands                = require(\"command/Commands\"),\n        Dialogs                 = require(\"widgets/Dialogs\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        NativeApp               = require(\"utils/NativeApp\"),\n        Strings                 = require(\"strings\"),\n        StringUtils             = require(\"utils/StringUtils\"),\n        UpdateNotification      = require(\"utils/UpdateNotification\"),\n        AboutDialogTemplate     = require(\"text!htmlContent/about-dialog.html\"),\n        ContributorsTemplate    = require(\"text!htmlContent/contributors-list.html\"),\n        Mustache                = require(\"thirdparty/mustache/mustache\");\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    /**\n     * This is the thirdparty API's (GitHub) maximum contributors per page limit\n     * @const {number}\n     */\n    var CONTRIBUTORS_PER_PAGE   = 100;\n\n    var buildInfo;\n\n\n    function _handleCheckForUpdates() {\n        UpdateNotification.checkForUpdate(true);\n    }\n\n    function _handleLinkMenuItem(url) {\n        return function () {\n            if (!url) {\n                return;\n            }\n            NativeApp.openURLInDefaultBrowser(url);\n        };\n    }\n\n    function _handleShowExtensionsFolder() {\n        brackets.app.showExtensionsFolder(\n            FileUtils.convertToNativePath(decodeURI(window.location.href)),\n            function (err) {} /* Ignore errors */\n        );\n    }\n\n    function _handleAboutDialog() {\n        var templateVars = {\n            ABOUT_ICON          : brackets.config.about_icon,\n            APP_NAME_ABOUT_BOX  : brackets.config.app_name_about,\n            BUILD_TIMESTAMP     : brackets.config.build_timestamp,\n            BUILD_INFO          : buildInfo || \"\",\n            Strings             : Strings\n        };\n\n        Dialogs.showModalDialogUsingTemplate(Mustache.render(AboutDialogTemplate, templateVars));\n\n        // Get containers\n        var $dlg            = $(\".about-dialog.instance\"),\n            $contributors   = $dlg.find(\".about-contributors\"),\n            $spinner        = $dlg.find(\".spinner\"),\n            contributorsUrl = brackets.config.contributors_url,\n            page;\n\n        if (contributorsUrl.indexOf(\"{1}\") !== -1) { // pagination enabled\n            page = 1;\n        }\n\n        $spinner.addClass(\"spin\");\n\n        function loadContributors(rawUrl, page, contributors, deferred) {\n            deferred = deferred || new $.Deferred();\n            contributors = contributors || [];\n            var url = StringUtils.format(rawUrl, CONTRIBUTORS_PER_PAGE, page);\n\n            $.ajax({\n                url: url,\n                dataType: \"json\",\n                cache: false\n            })\n                .done(function (response) {\n                    contributors = contributors.concat(response || []);\n                    if (page && response.length === CONTRIBUTORS_PER_PAGE) {\n                        loadContributors(rawUrl, page + 1, contributors, deferred);\n                    } else {\n                        deferred.resolve(contributors);\n                    }\n                })\n                .fail(function () {\n                    if (contributors.length) { // we weren't able to fetch this page, but previous fetches were successful\n                        deferred.resolve(contributors);\n                    } else {\n                        deferred.reject();\n                    }\n                });\n            return deferred.promise();\n        }\n\n        loadContributors(contributorsUrl, page) // Load the contributors\n            .done(function (allContributors) {\n                // Populate the contributors data\n                var totalContributors = allContributors.length,\n                    contributorsCount = 0;\n\n                allContributors.forEach(function (contributor) {\n                    // remove any UrlParams delivered via the GitHub API\n                    contributor.avatar_url = contributor.avatar_url.split(\"?\")[0];\n                });\n\n                $contributors.html(Mustache.render(ContributorsTemplate, allContributors));\n\n                // This is used to create an opacity transition when each image is loaded\n                $contributors.find(\"img\").one(\"load\", function () {\n                    $(this).css(\"opacity\", 1);\n\n                    // Count the contributors loaded and hide the spinner once all are loaded\n                    contributorsCount++;\n                    if (contributorsCount >= totalContributors) {\n                        $spinner.removeClass(\"spin\");\n                    }\n                }).each(function () {\n                    if (this.complete) {\n                        $(this).trigger(\"load\");\n                    }\n                });\n            })\n            .fail(function () {\n                $spinner.removeClass(\"spin\");\n                $contributors.html(Mustache.render(\"<p class='dialog-message'>{{ABOUT_TEXT_LINE6}}</p>\", Strings));\n            });\n    }\n\n    // Read \"build number\" SHAs off disk immediately at APP_READY, instead\n    // of later, when they may have been updated to a different version\n    AppInit.appReady(function () {\n        BuildInfoUtils.getBracketsSHA().done(function (branch, sha, isRepo) {\n            // If we've successfully determined a \"build number\" via .git metadata, add it to dialog\n            sha = sha ? sha.substr(0, 9) : \"\";\n            if (branch || sha) {\n                buildInfo = StringUtils.format(\"({0} {1})\", branch, sha).trim();\n            }\n        });\n    });\n\n    CommandManager.register(Strings.CMD_CHECK_FOR_UPDATE,       Commands.HELP_CHECK_FOR_UPDATE,     _handleCheckForUpdates);\n    CommandManager.register(Strings.CMD_HOW_TO_USE_BRACKETS,    Commands.HELP_HOW_TO_USE_BRACKETS,  _handleLinkMenuItem(brackets.config.how_to_use_url));\n    CommandManager.register(Strings.CMD_SUPPORT,                Commands.HELP_SUPPORT,              _handleLinkMenuItem(brackets.config.support_url));\n    CommandManager.register(Strings.CMD_SUGGEST,                Commands.HELP_SUGGEST,              _handleLinkMenuItem(brackets.config.suggest_feature_url));\n    CommandManager.register(Strings.CMD_RELEASE_NOTES,          Commands.HELP_RELEASE_NOTES,        _handleLinkMenuItem(brackets.config.release_notes_url));\n    CommandManager.register(Strings.CMD_GET_INVOLVED,           Commands.HELP_GET_INVOLVED,         _handleLinkMenuItem(brackets.config.get_involved_url));\n    CommandManager.register(Strings.CMD_SHOW_EXTENSIONS_FOLDER, Commands.HELP_SHOW_EXT_FOLDER,      _handleShowExtensionsFolder);\n    CommandManager.register(Strings.CMD_HOMEPAGE,               Commands.HELP_HOMEPAGE,             _handleLinkMenuItem(brackets.config.homepage_url));\n    CommandManager.register(Strings.CMD_TWITTER,                Commands.HELP_TWITTER,              _handleLinkMenuItem(brackets.config.twitter_url));\n    CommandManager.register(Strings.CMD_ABOUT,                  Commands.HELP_ABOUT,                _handleAboutDialog);\n});\n"
  },
  {
    "path": "src/htmlContent/about-dialog.html",
    "content": "<div class=\"about-dialog modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{Strings.ABOUT}}</h1>\n    </div>\n    <div class=\"modal-body no-padding\">\n        <img class=\"about-icon\" src=\"{{ABOUT_ICON}}\">\n        <div class=\"about-text\">\n            <h2>{{APP_NAME_ABOUT_BOX}}</h2>\n            <div class=\"about-info\">\n                <p class=\"dialog-message\">{{Strings.ABOUT_TEXT_LINE1}} <span id=\"about-build-number\">{{BUILD_INFO}}</span>\n                  {{#BUILD_TIMESTAMP}}\n                  <br><span class=\"dialog-message\">{{Strings.ABOUT_TEXT_BUILD_TIMESTAMP}}{{BUILD_TIMESTAMP}}</span>\n                  {{/BUILD_TIMESTAMP}}\n                </p>\n\n                <p class=\"dialog-message\"><!-- $NON-NLS$ -->Copyright 2012 - present Adobe Systems Incorporated and its licensors. All rights reserved.</p>\n                <p class=\"dialog-message\">{{{Strings.ABOUT_TEXT_MDN_DOCS}}}</p>\n                <p class=\"dialog-message\">{{{Strings.ABOUT_TEXT_LINE3}}}</p>\n                <p class=\"dialog-message\">{{{Strings.ABOUT_TEXT_LINE4}}}</p>\n                <p class=\"dialog-message\">\n                    {{Strings.ABOUT_TEXT_LINE5}}\n                    <span class=\"spinner inline\"></span>\n                </p>\n                <div class=\"about-contributors\">\n                </div>\n            </div>\n        </div>\n    </div>\n    <div class=\"modal-footer\">\n        <button class=\"dialog-button btn primary\" data-button-id=\"ok\">{{Strings.CLOSE}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/code-hint-list.html",
    "content": "{{#hints}}\n    <li>\n        <a href=\"#\">\n            <span class=\"codehint-item\">{{{formattedHint}}}</span>\n        </a>\n    </li>\n{{/hints}}"
  },
  {
    "path": "src/htmlContent/contributors-list.html",
    "content": "{{#.}}<a href=\"{{html_url}}\" title=\"{{login}} - {{html_url}}\"><img src=\"{{avatar_url}}?size=30\" alt=\"{{login}}\" width=\"30\" height=\"30\" /></a>{{/.}}\n"
  },
  {
    "path": "src/htmlContent/dialog-template.html",
    "content": "<div class=\"{{dlgClass}} template modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{{title}}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        <div class=\"dialog-message\">{{{message}}}</div>\n    </div>\n    <div class=\"modal-footer\">\n        {{#buttons}}\n        <button class=\"dialog-button btn {{className}}\" data-button-id=\"{{id}}\">{{{text}}}</button>\n        {{/buttons}}\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/edit-filter-dialog.html",
    "content": "<div class=\"file-filter-dialog modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{Strings.FILE_FILTER_DIALOG}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        <div class=\"dialog-message\">\n            {{{instruction}}}\n            <textarea class=\"exclusions-editor\"></textarea>\n            <input type=\"text\" class=\"exclusions-name\" placeholder=\"{{Strings.FILTER_NAME_PLACEHOLDER}}\">\n            <div class=\"exclusions-name-characters-remaining\"></div>\n            <div class=\"exclusions-filecount\">{{Strings.FILTER_COUNTING_FILES}}</div>\n        </div>\n    </div>\n    <div class=\"modal-footer\">\n        <button class=\"dialog-button btn\" data-button-id=\"cancel\">{{Strings.CANCEL}}</button>\n        <button class=\"dialog-button btn primary\" data-button-id=\"ok\">{{Strings.OK}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/extension-manager-dialog.html",
    "content": "<div class=\"extension-manager-dialog modal\">\n    <div class=\"modal-header\">\n        <ul class=\"nav nav-tabs no-focus\">\n            {{#showRegistry}}\n                <li><a href=\"#registry\" class=\"registry\" data-toggle=\"tab\"><img src=\"styles/images/extension-manager-registry.svg\"/><br/>{{Strings.EXTENSIONS_AVAILABLE_TITLE}}</a></li>\n                <li><a href=\"#themes\" class=\"themes\" data-toggle=\"tab\"><img src=\"styles/images/themes-icon.svg\"/><br/>{{Strings.EXTENSIONS_THEMES_TITLE}}</a></li>\n                <!--<li><a href=\"#updates\" class=\"updates\" data-toggle=\"tab\"><img src=\"styles/images/extension-manager-updates.svg\"/><br/>{{Strings.EXTENSIONS_UPDATES_TITLE}}</a></li>-->\n            {{/showRegistry}}\n            <li>\n                <a href=\"#installed\" class=\"installed\" data-toggle=\"tab\">\n                    <span class=\"notification\"></span>\n                    <img src=\"styles/images/extension-manager-installed.svg\"/>\n                    <br/>\n                    {{Strings.EXTENSIONS_INSTALLED_TITLE}}\n                </a>\n            </li>\n            <li>\n                <a href=\"#default\" class=\"default\" data-toggle=\"tab\">\n                    <img src=\"styles/images/extension-manager-installed.svg\"/>\n                    <br/>\n                    {{Strings.EXTENSIONS_DEFAULT_TITLE}}\n                </a>\n            </li>\n        </ul>\n        <div>\n            <div class=\"ext-sort-group\">\n               <div id=\"sort-attributes-icon\"></div>\n               <select class=\"sort-extensions\">\n                   <option value=\"publishedDate\">{{Strings.EXTENSIONS_LAST_UPDATED}}</option>\n                   <option value=\"downloadCount\">{{Strings.EXTENSIONS_DOWNLOADS}}</option>\n               </select>\n            </div>\n            <div class=\"search-container\">\n                <button class=\"search-clear\">&times;</button>\n                <input class=\"search\" type=\"text\" placeholder=\"{{Strings.EXTENSION_SEARCH_PLACEHOLDER}}\">\n            </div>\n        </div>\n    </div>\n    <div class=\"modal-body no-padding table-striped tab-content\">\n        <div class='spinner large spin'/>\n    </div>\n    <div class=\"modal-footer\">\n        <span id=\"install-drop-zone\" class=\"btn left drag\">\n            <span class=\"install-drag-message\">{{Strings.INSTALL_EXTENSION_DRAG}} <a class=\"install-from-url\">{{Strings.INSTALL_FROM_URL}}</a></span>\n            <span class=\"install-drop-message\">{{Strings.INSTALL_EXTENSION_DROP}}</span>\n            <span class=\"install-validating-message\">{{Strings.INSTALL_EXTENSION_VALIDATING}}</span>\n            <div id=\"install-drop-zone-mask\"></div>\n        </span>\n        <button class=\"dialog-button btn primary\" data-button-id=\"close\">{{Strings.CLOSE}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/extension-manager-view-item.html",
    "content": "<tr>\n    <td class=\"ext-info\">\n        <span class=\"ext-name\">{{#metadata.title}}{{metadata.title}}{{/metadata.title}}{{^metadata.title}}{{metadata.name}}{{/metadata.title}}</span>\n        {{#authorInfo}}\n            <span class=\"muted ext-author\">{{{authorInfo}}}</span>\n        {{/authorInfo}}\n        <span class=\"muted ext-version\">{{metadata.version}}</span>\n        {{#hasVersionInfo}}\n            <span class=\"muted ext-date\"> &mdash; {{lastVersionDate}}</span>\n        {{/hasVersionInfo}}\n        {{#downloadCount}}\n            <p title=\"{{downloadCount}} {{Strings.EXTENSIONS_DOWNLOADS}}\"><img src=\"styles/images/download-icon.svg\"/> {{downloadCount}}</p>\n        {{/downloadCount}}\n    </td>\n    <td class=\"ext-desc\">\n        {{#showInstallButton}}\n            <!-- Warnings when trying to install extension where latest/all versions not compatible -->\n            {{^isCompatible}}\n                <div class=\"alert warning\">\n                    {{#requiresNewer}}{{Strings.EXTENSION_INCOMPATIBLE_NEWER}}{{/requiresNewer}}\n                    {{^requiresNewer}}{{Strings.EXTENSION_INCOMPATIBLE_OLDER}}{{/requiresNewer}}\n                </div>\n            {{/isCompatible}}\n            {{#isCompatible}}\n                {{^isCompatibleLatest}}\n                    <div class=\"alert warning\">\n                        {{installWarning}}\n                    </div>\n                {{/isCompatibleLatest}}\n            {{/isCompatible}}\n        {{/showInstallButton}}\n        <span class=\"ext-full-description\">\n            {{#metadata.shortdescription}}\n                {{metadata.shortdescription}}\n            {{/metadata.shortdescription}}\n            {{^metadata.shortdescription}}\n                {{#metadata.description}}\n                    {{metadata.description}}\n                {{/metadata.description}}\n                {{^metadata.description}}\n                    <p class=\"muted\"><em>{{Strings.EXTENSION_NO_DESCRIPTION}}</em></p>\n                {{/metadata.description}}\n            {{/metadata.shortdescription}}\n        </span>\n        {{#metadata.shortdescription}}\n        <a data-extension-id=\"{{metadata.name}}\" data-toggle-desc=\"expand-desc\" title=\"{{Strings.VIEW_COMPLETE_DESCRIPTION}}\" href=\"#\">...</a>\n        {{/metadata.shortdescription}}\n        {{#metadata.homepage}}\n            <p><a title=\"{{metadata.homepage}}\" href=\"{{metadata.homepage}}\">{{Strings.EXTENSION_MORE_INFO}}</a></p>\n        {{/metadata.homepage}}\n        {{#translated}}\n            <br/>\n            <span class=\"ext-translated\" title=\"{{translatedLangs}}\">{{extensionTranslated}}</span>\n        {{/translated}}\n    </td>\n    <td class=\"ext-action\">\n        <div>\n        {{#showInstallButton}}\n            <button class=\"btn btn-mini install\" data-extension-id=\"{{metadata.name}}\" {{^allowInstall}}disabled{{/allowInstall}}>\n                {{^isInstalled}}{{Strings.INSTALL}}{{/isInstalled}}\n                {{#isInstalled}}{{Strings.EXTENSION_INSTALLED}}{{/isInstalled}}\n            </button>\n        {{/showInstallButton}}\n        {{#isInstalled}}\n            {{#showUpdateButton}}\n                <button class=\"btn btn-mini update\" data-extension-id=\"{{metadata.name}}\" {{^allowUpdate}}disabled title=\"{{updateNotAllowedReason}}\"{{/allowUpdate}}>\n                    {{Strings.UPDATE}}\n                </button>\n            {{/showUpdateButton}}\n            {{#disablingAllowed}}\n                {{#showUpdateButton}}\n                </div><div>\n                {{/showUpdateButton}}\n                <button class=\"btn btn-mini disable\" data-extension-id=\"{{metadata.name}}\">\n                    {{Strings.DISABLE}}\n                </button>\n            {{/disablingAllowed}}\n            {{#enablingAllowed}}\n                <button class=\"btn btn-mini enable\" data-extension-id=\"{{metadata.name}}\">\n                    {{Strings.ENABLE}}\n                </button>\n            {{/enablingAllowed}}\n            {{#removalAllowed}}\n                <button class=\"btn btn-mini remove\" data-extension-id=\"{{metadata.name}}\" {{^allowRemove}}disabled title=\"{{Strings.CANT_REMOVE_DEV}}\"{{/allowRemove}}>\n                    {{Strings.REMOVE}}\n                </button>\n            {{/removalAllowed}}\n            {{#failedToStart}}\n                {{^isMarkedForRemoval}}\n                    {{Strings.EXTENSION_ERROR}} {{#allowRemove}}(<a class=\"remove\" data-extension-id=\"{{metadata.name}}\">{{Strings.REMOVE}}</a>){{/allowRemove}}\n                {{/isMarkedForRemoval}}\n            {{/failedToStart}}\n            {{#isMarkedForRemoval}}\n                {{Strings.MARKED_FOR_REMOVAL}} (<a class=\"undo-remove\" data-extension-id=\"{{metadata.name}}\" href=\"#\">{{Strings.UNDO_REMOVE}}</a>)\n            {{/isMarkedForRemoval}}\n            {{#isMarkedForDisabling}}\n                {{Strings.MARKED_FOR_DISABLING}} (<a class=\"undo-disable\" data-extension-id=\"{{metadata.name}}\" href=\"#\">{{Strings.UNDO_DISABLE}}</a>)\n            {{/isMarkedForDisabling}}\n            {{#isMarkedForUpdate}}\n                {{Strings.MARKED_FOR_UPDATE}} (<a class=\"undo-update\" data-extension-id=\"{{metadata.name}}\" href=\"#\">{{Strings.UNDO_UPDATE}}</a>)\n            {{/isMarkedForUpdate}}\n        {{/isInstalled}}\n        </div>\n    </td>\n</tr>\n"
  },
  {
    "path": "src/htmlContent/filter-name.html",
    "content": "<div class='filter-trash-icon'>&times;</div><!-- \n--><span class='recent-filter-name'>{{{filter-name}}}</span><!-- \n--><span class='recent-filter-patterns'>{{{filter-patterns}}}</span><!-- \n--><span class='filter-edit-icon'></span>"
  },
  {
    "path": "src/htmlContent/findreplace-bar.html",
    "content": "<div class=\"find-input-group\">\n    <div id=\"find-group\"><!--\n        --><div class=\"search-input-container\"><input type=\"text\" id=\"find-what\" placeholder=\"{{queryPlaceholder}}\" value=\"{{initialQuery}}\" /><div class=\"dropdown-icon\"></div><div class=\"error\"></div><span id=\"find-counter\"></span></div><!--\n        --><button id=\"find-case-sensitive\" class=\"btn no-focus\" tabindex=\"-1\" title=\"{{Strings.BUTTON_CASESENSITIVE_HINT}}\"><div class=\"button-icon\"></div></button><!--\n        --><button id=\"find-regexp\" class=\"btn no-focus\" tabindex=\"-1\" title=\"{{Strings.BUTTON_REGEXP_HINT}}\"><div class=\"button-icon\"></div></button><!--\n        {{^multifile}}\n        --><div class=\"navigator\"><!--\n            --><button id=\"find-prev\" class=\"btn no-focus\" tabindex=\"-1\" title=\"{{Strings.BUTTON_PREV_HINT}}\">{{Strings.BUTTON_PREV}}</button><!--\n            --><button id=\"find-next\" class=\"btn no-focus\" tabindex=\"-1\" title=\"{{Strings.BUTTON_NEXT_HINT}}\">{{Strings.BUTTON_NEXT}}</button><!--\n        --></div><!--\n        {{/multifile}}\n    --></div>\n\n    {{#replace}}\n    <div id=\"replace-group\" {{#scope}}class=\"has-scope\"{{/scope}}><!--\n        --><input type=\"text\" id=\"replace-with\" placeholder=\"{{Strings.REPLACE_PLACEHOLDER}}\" value=\"{{initialReplaceText}}\" /><!--\n        {{^multifile}}\n        --><button id=\"replace-yes\" class=\"btn no-focus\" tabindex=\"-1\">{{Strings.BUTTON_REPLACE}}</button><!--\n        {{/multifile}}\n        --><button id=\"replace-batch\" class=\"btn no-focus {{#multifile}}solo{{/multifile}}\" tabindex=\"-1\">{{replaceBatchLabel}}</button><!--\n        {{^multifile}}\n        --><button id=\"replace-all\" class=\"btn no-focus\" tabindex=\"-1\">{{replaceAllLabel}}</button><!--\n        {{/multifile}}\n        --></div>\n    {{/replace}}\n</div>\n\n{{#multifile}}\n<div class=\"scope-group\">\n    <div class=\"no-results-message\">{{Strings.FIND_NO_RESULTS}}</div>\n    <div class=\"message\">\n        <span id=\"searchlabel\">{{{scopeLabel}}}</span>\n    </div>\n    <!-- For Find in Files, the filter picker will be added here programmatically. -->\n</div>\n<div id=\"indexing-spinner\" class=\"indexing-group forced-hidden\">\n    <div class=\"spinner inline spin\"></div>\n    <div class=\"indexing-message\">{{Strings.FIND_IN_FILES_INDEXING}}</div>\n</div>\n{{/multifile}}\n\n<a href=\"#\" class=\"close\">&times;</a>\n"
  },
  {
    "path": "src/htmlContent/image-view.html",
    "content": "<div class=\"image-view\">\n    <div class=\"image-centering\">\n        <div class=\"image-header\">\n            <div class=\"image-data\"></div>\n            <div class=\"image-path\"></div>\t\n        </div>\n        <div class=\"image\">\n            <div class=\"image-scale\"></div>\n            <img class=\"image-preview\" src=\"{{fullPath}}?ver={{now}}\">\n            <div class=\"image-tip\">\n                <table class=\"tip-container\">\n                    <tr>\n                        <td class=\"variable\">x: </td>\n                        <td class=\"x-value\"></td>\n                    </tr>\n                    <tr>\n                        <td class=\"variable\">y: </td>\n                        <td class=\"y-value\"></td>\n                    </tr>\n                </table>\n            </div>\n            <div class=\"horz-guide image-guide\"></div>\n            <div class=\"vert-guide image-guide\"></div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/infobar-template.html",
    "content": "<div id=\"info-bar-template\" {{#type}}class={{{type}}}{{/type}} tabindex=\"0\">\n    <div id=\"icon-container\">\n        <svg id=\"info-icon\"> </svg>\n    </div>\n    <div id=\"content-container\">\n        <p id=\"info-content\"><span id=\"heading\">{{title}}</span>&nbsp;&nbsp;<span id=\"description\">{{{description}}}</span></p>\n    </div>\n    {{^buttons}}\n    <div id=\"close-icon-container\">\n        <button type=\"button\" id=\"close-icon\" tabIndex=\"0\">&times;</button>\n    </div>\n    {{/buttons}}\n</div>"
  },
  {
    "path": "src/htmlContent/inline-menu.html",
    "content": "{{#items}}\n    <li class=\"inlinemenu-item\">\n        <a href=\"#\">\n            <span>{{{formattedItem}}}</span>\n        </a>\n    </li>\n{{/items}}\n"
  },
  {
    "path": "src/htmlContent/install-extension-dialog.html",
    "content": "<div class=\"install-extension-dialog modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">\n            {{#isUpdate}}{{Strings.UPDATE_EXTENSION_TITLE}}{{/isUpdate}}\n            {{^isUpdate}}{{Strings.INSTALL_EXTENSION_TITLE}}{{/isUpdate}}\n        </h1>\n    </div>\n    <div class=\"modal-body\">\n        <div class=\"field-container input-field\">\n            <input type=\"text\" placeholder=\"{{INSTALL_EXTENSION_HINT}}\" class=\"url\" />\n        </div>\n        <div class=\"field-container message-field\">\n            <div class=\"message\"></div>\n        </div>\n    </div>\n    <div class=\"modal-footer\">\n        {{#includeBrowseExtensions}}<button class=\"btn left browse-extensions\">{{Strings.BROWSE_EXTENSIONS}}</button>{{/includeBrowseExtensions}}\n        <button class=\"dialog-button btn\" data-button-id=\"cancel\">{{Strings.CANCEL}}</button>\n        <button class=\"dialog-button btn primary\" data-button-id=\"ok\" disabled>{{Strings.INSTALL}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/main-view.html",
    "content": "<!-- \n  Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n   \n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the \"Software\"), \n  to deal in the Software without restriction, including without limitation \n  the rights to use, copy, modify, merge, publish, distribute, sublicense, \n  and/or sell copies of the Software, and to permit persons to whom the \n  Software is furnished to do so, subject to the following conditions:\n   \n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n   \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n  DEALINGS IN THE SOFTWARE.\n-->\n\n\n<!--\n    HTML template for the body tag of index.html. It is rendered dynamically in\n    brackets.js with Mustache and localized with the i18n RequireJS plugin.\n\n    LOCALIZATION NOTE:\n    All display text for this file must use templating so the text can be localized.\n    \n    English text goes in src/nls/root/strings.js. All other translations go in the strings.js file for\n    the specific local in the nls folder. If a translation is missing for a specific key English\n    is used as a fallback\n\n    Strings should be referenced using the double brackets syntax.\n    Example: {{keyname}}. Note, all strings are HTML escaped unless the form \n    {{&keyname}} is used.\n\n-->\n\n    <!-- Main UI: horizontal set of sidebar, main content vertical stack, and vertical toolbar -->\n    <div class=\"main-view\">\n        <div id=\"sidebar\" class=\"sidebar panel quiet-scrollbars horz-resizable right-resizer collapsible\" data-minsize=\"0\" data-maxsize=\"80%\" data-forceleft=\".content\">\n            <div class=\"working-set-splitview-btn btn-alt-quiet\"></div>\n            <div class=\"working-set-option-btn btn-alt-quiet\"></div>\n            \n            <div id=\"working-set-list-container\">\n                \n            </div>\n            <div id=\"project-files-header\">\n                <span id=\"project-title\" class=\"title\"></span>\n            </div>\n            <div id=\"project-files-container\">\n                <!-- This will contain a dynamically generated <ul> hierarchy at runtime -->\n            </div>\n        </div>\n        \n        <!--\n            Vertical stack of titlebar (in-browser), editor, bottom panels, status bar\n                (status bar is injected later - see StatusBar.init()).\n            Note: all children must be in a vertical stack with heights explicitly set in a fixed\n                unit such as px (not percent/em/auto). If you change the height later, you must\n                call WorkspaceManager.recomputeLayout() each time. Otherwise the layout will\n                not get set correctly. Use WorkspaceManager to have this managed for you automatically.\n         -->\n        <div class=\"content\">\n            <!-- Horizontal titlebar containing menus & filename when inBrowser -->\n            <div id=\"titlebar\" class=\"toolbar no-focus\">\n                <!-- Menu bar -->\n                <ul class=\"nav\" data-dropdown=\"dropdown\">\n                </ul>\n                \n                <!-- Filename label -->\n                <div class=\"title-wrapper\">\n                    <span class=\"title\"></span>&nbsp;<span class='dirty-dot' style=\"visibility:hidden;\">•</span>\n                </div>\n            </div>\n            \n            <div id=\"editor-holder\" {{#shouldAddAA}}class=\"subpixel-aa\"{{/shouldAddAA}}>\n                <!-- View Panes are programatically created here -->\n            </div>\n            \n            <!-- Bottom panels and status bar are programmatically created here -->\n            \n        </div>\n\n        <!-- Vertical toolbar docked to right -->\n        <div id=\"main-toolbar\" class=\"toolbar no-focus collapsible\">\n            <!-- Top-aligned buttons -->\n            <div class=\"buttons\">\n                <a id=\"toolbar-go-live\" href=\"#\"></a> <!-- tooltip for this is set in JS -->\n                <a id=\"toolbar-extension-manager\" title=\"{{Strings.EXTENSION_MANAGER_TITLE}}\" href=\"#\"></a>\n                <a id=\"update-notification\" title=\"{{Strings.UPDATE_NOTIFICATION_TOOLTIP}}\" href=\"#\" style=\"display: none\"></a>\n            </div>\n            <div class=\"bottom-buttons\"></div>\n        </div>\n        \n        <!-- Hack to ensure that the code editor's web font is loaded early. -->\n        <!-- For more info, see note in brackets.less for class .dummy-text, or issue 76 -->\n        <div class=\"dummy-text\">x</div>\n    </div>\n\n    <!-- Modal Windows -->\n    <div id=\"context-menu-bar\">\n        <ul data-dropdown=\"dropdown\"></ul>\n    </div>\n    <div id=\"codehint-menu-bar\">\n        <ul data-dropdown=\"dropdown\"></ul>\n    </div>\n    <div id=\"inlinemenu-menu-bar\">\n        <ul data-dropdown=\"dropdown\"></ul>\n    </div>\n    <div id=\"hidden-editors\"></div>\n"
  },
  {
    "path": "src/htmlContent/pane.html",
    "content": "<div id=\"{{id}}\" class=\"view-pane\">\n    <div class=\"pane-header\">\n        <div class=\"pane-header-text\"></div>\n        <div class=\"pane-header-flipview-btn flipview-icon-none\"></div>\n        <div class=\"pane-header-close-btn file-status-icon can-close\"></div>\n    </div>\n    <div class=\"pane-content\">\n        <div class=\"not-editor\"></div>\n    </div>\n</div>"
  },
  {
    "path": "src/htmlContent/parameter-hint-template.html",
    "content": "<div id=\"function-hint-container-new\">\n    <div class=\"function-hint-content-new\">\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/problems-panel-table.html",
    "content": "<table class=\"bottom-panel-table table table-striped table-condensed row-highlight\">\n    <tbody>\n        {{#reportList}}\n        <tr class=\"inspector-section\">\n            <td colspan=\"4\">\n                <span class=\"disclosure-triangle {{#isExpanded}}expanded{{/isExpanded}}\"></span>\n                <input type=\"hidden\" value=\"{{providerName}}\" />\n                {{providerName}} ({{results.length}})\n            </td>\n        </tr>\n        {{#results}}\n        <tr class=\"{{display}}\">\n            <td class=\"line-number\" data-character=\"{{pos.ch}}\">{{friendlyLine}}</td>\n            <td class=\"line-icon\">\n                <div class=\"line-icon-default line-icon-{{type}}\"></div>\n            </td>\n            <td class=\"line-text\">{{message}}</td>\n            <td class=\"line-snippet\">{{codeSnippet}}</td>\n        </tr>\n        {{/results}}\n        {{/reportList}}\n    </tbody>\n</table>\n"
  },
  {
    "path": "src/htmlContent/problems-panel.html",
    "content": "<div id=\"problems-panel\" class=\"bottom-panel vert-resizable top-resizer\">\n    <div class=\"toolbar simple-toolbar-layout\">\n        <div class=\"title\"><!-- filled in programmatically --></div>\n        <a href=\"#\" class=\"close\">&times;</a>\n    </div>\n    <div class=\"table-container resizable-content\"></div>\n</div>"
  },
  {
    "path": "src/htmlContent/project-settings-dialog.html",
    "content": "<div class=\"project-settings-dialog modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{title}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        <div class=\"field-container\">\n            <label>\n                {{Strings.PROJECT_SETTING_BASE_URL}}: <input type=\"text\" placeholder=\"{{Strings.PROJECT_SETTING_BASE_URL_HINT}}\" value=\"{{baseUrl}}\" class=\"url\" />\n            </label>\n            {{#errorMessage}}<div class=\"alert\" style=\"margin-bottom: 0\">{{{errorMessage}}}</div>{{/errorMessage}}\n         </div>\n    </div>\n    <div class=\"modal-footer\">\n        <button class=\"dialog-button btn\" data-button-id=\"cancel\">{{Strings.CANCEL}}</button>\n        <button class=\"dialog-button btn primary\" data-button-id=\"ok\">{{Strings.DONE}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/search-panel.html",
    "content": "<div id=\"{{panelID}}\" class=\"search-results bottom-panel vert-resizable top-resizer no-focus\">\n    <div class=\"toolbar simple-toolbar-layout\">\n        <div class=\"title\"></div>\n        <a href=\"#\" class=\"close\">&times;</a>\n    </div>\n    <div class=\"table-container resizable-content\"></div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/search-results.html",
    "content": "<table class=\"bottom-panel-table table table-striped table-condensed row-highlight\">\n    <tbody>\n        {{#searchList}}\n        <tr class=\"file-section\" data-file-index=\"{{fileIndex}}\">\n            {{#replace}}<td class=\"checkbox-column\"><input type=\"checkbox\" class=\"check-one-file\" {{#isChecked}}checked=\"true\"{{/isChecked}} /></td>{{/replace}}\n            <td colspan=\"2\">\n                <span class=\"disclosure-triangle {{^isCollapsed}}expanded{{/isCollapsed}}\" title=\"{{Strings.FIND_IN_FILES_EXPAND_COLLAPSE}}\"></span>\n                {{{filename}}}\n            </td>\n        </tr>\n        {{#items}}\n        <tr data-file-index=\"{{fileIndex}}\" data-item-index=\"{{itemIndex}}\" data-match-index=\"{{matchIndex}}\" {{#isCollapsed}}style=\"display:none;\"{{/isCollapsed}}>\n            {{#replace}}<td class=\"checkbox-column\"><input type=\"checkbox\" class=\"check-one\" {{#isChecked}}checked=\"true\"{{/isChecked}} /></td>{{/replace}}\n            <td class=\"line-number\">{{line}}</td>\n            <td class=\"line-text\">{{pre}}<span class=\"highlight\">{{highlight}}</span>{{post}}</td>\n        </tr>\n        {{/items}}\n        {{/searchList}}\n    </tbody>\n</table>\n"
  },
  {
    "path": "src/htmlContent/search-summary.html",
    "content": "{{#replace}}\n<div class=\"fixed-col\"><input type=\"checkbox\" class=\"check-all\" {{#allChecked}}checked=\"checked\"{{/allChecked}} /></div>\n{{/replace}}\n<div class=\"fixed-col\">{{titleLabel}} &quot;</div>\n<div class=\"contracting-col\">{{query}}</div>\n<div class=\"fixed-col\">&quot;</div>\n{{#replace}}\n<div class=\"fixed-col\">&nbsp;{{Strings.FIND_REPLACE_TITLE_WITH}} &quot;</div>\n<div class=\"contracting-col\">{{replaceWith}}</div>\n<div class=\"fixed-col\">&quot;</div>\n{{/replace}}\n{{#scope}}\n<div class=\"contracting-col\">{{{scope}}}</div>\n{{/scope}}\n<div class=\"fixed-col\">&nbsp;{{{summary}}}</div>\n{{#hasPages}}\n<div class=\"pagination-col\">\n    <span class=\"first-page {{^hasPrev}}disabled{{/hasPrev}}\"></span>\n    <span class=\"prev-page {{^hasPrev}}disabled{{/hasPrev}}\"></span>\n    {{{results}}}\n    <span class=\"next-page {{^hasNext}}disabled{{/hasNext}}\"></span>\n    <span class=\"last-page {{^hasNext}}disabled{{/hasNext}}\"></span>\n</div>\n{{/hasPages}}\n{{#replace}}\n<div class=\"replace-col\">\n    <button class=\"btn small replace-checked\">{{Strings.BUTTON_REPLACE}}</button>\n</div>\n{{/replace}}"
  },
  {
    "path": "src/htmlContent/themes-settings.html",
    "content": "<div class=\"theme-settings modal\">\n    <div class=\"modal-header\">\n        <h1 class=\"dialog-title\">{{Strings.THEMES_SETTINGS}}</h1>\n    </div>\n    <div class=\"modal-body\">\n        <form class=\"form-horizontal\">\n            <div class=\"control-group\">\n                <label class=\"control-label\">{{Strings.CURRENT_THEME}}:</label>\n                <div class=\"controls\">\n                    <select>\n                        {{#themes}}\n                        <option style=\"text-align:left;\" value=\"{{name}}\" data-target=\"theme\">{{displayName}}</option>\n                        {{/themes}}\n                    </select>\n                </div>\n            </div>\n\n            <div class=\"control-group\">\n                <label class=\"control-label\">{{Strings.USE_THEME_SCROLLBARS}}:</label>\n                <div class=\"controls\">\n                    {{#settings.themeScrollbars}}\n                        <input type=\"checkbox\" data-target=\"themeScrollbars\" checked>\n                    {{/settings.themeScrollbars}}\n                    {{^settings.themeScrollbars}}\n                        <input type=\"checkbox\" data-target=\"themeScrollbars\">\n                    {{/settings.themeScrollbars}}\n                </div>\n            </div>\n\n            <div class=\"control-group\">\n                <label class=\"control-label\">{{Strings.FONT_SIZE}}:</label>\n                <div class=\"controls\">\n                    <input type=\"text\" pattern=\"{{settings.validFontSizeRegExp}}\" data-target=\"fontSize\" value=\"{{settings.fontSize}}\">\n                </div>\n            </div>\n\n            <div class=\"control-group\">\n                <label class=\"control-label\">{{Strings.FONT_FAMILY}}:</label>\n                <div class=\"controls\">\n                    <input type=\"text\" data-target=\"fontFamily\" value=\"{{settings.fontFamily}}\">\n                </div>\n            </div>\n        </form>\n    </div>\n    <div class=\"modal-footer\">\n        <button class=\"dialog-button btn\" data-button-id=\"cancel\">{{Strings.CANCEL}}</button>\n        <button class=\"dialog-button btn primary\" id=\"theme-settings-done-btn\" data-button-id=\"save\">{{Strings.DONE}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/update-dialog.html",
    "content": "<div class=\"update-dialog modal\">\n    <div class=\"modal-header\">\n        <img class=\"update-icon\" src=\"styles/images/update_large_icon.svg\">\n        <h1 class=\"dialog-title\">{{UPDATE_AVAILABLE_TITLE}}</h1>\n    </div>\n    <div class=\"modal-body no-padding\">\n        <div class=\"update-text\">\n            <p class=\"dialog-message\">{{UPDATE_MESSAGE}}</p>\n            <div class=\"update-info\">\n            </div>\n        </div>\n    </div>\n    <div class=\"modal-footer\">\n        <button class=\"dialog-button btn primary\" data-button-id=\"download\">{{GET_IT_NOW}}</button>\n        <button class=\"dialog-button btn\" data-button-id=\"cancel\">{{CANCEL}}</button>\n    </div>\n</div>\n"
  },
  {
    "path": "src/htmlContent/update-list.html",
    "content": "{{#.}}\n<div>\n    <h3>{{versionString}} - {{dateString}} | <a href=\"{{releaseNotesURL}}\" title=\"{{releaseNotesURL}}\">{{Strings.RELEASE_NOTES}}</a></h3>\n    <ul>\n        {{#newFeatures}}\n        <li><b>{{name}}</b> <br> {{description}}</li>\n        {{/newFeatures}}\n    </ul>\n</div>\n{{/.}}"
  },
  {
    "path": "src/htmlContent/working-set.html",
    "content": "<div class=\"working-set-view\" id=\"{{id}}\">\n    <div class=\"working-set-header\"><span class=\"working-set-header-title\">{{WORKING_FILES}}</span></div>\n    <div class=\"open-files-container\">\n        <!-- This will contain runtime-generated <li>'s for each file in the working set -->\n        <ul>\n        </ul>\n    </div>\n<div>"
  },
  {
    "path": "src/index.html",
    "content": "<!doctype html>\n\n<!--\n  Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n   \n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the \"Software\"),\n  to deal in the Software without restriction, including without limitation\n  the rights to use, copy, modify, merge, publish, distribute, sublicense,\n  and/or sell copies of the Software, and to permit persons to whom the\n  Software is furnished to do so, subject to the following conditions:\n   \n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n   \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n  DEALINGS IN THE SOFTWARE.\n-->\n\n<html spellcheck=\"false\">\n<head>\n    <meta charset=\"utf-8\">\n    <title></title>\n\n    <!-- CSS/LESS -->\n\n    <!-- NOTE: All scripts must be external for Chrome App support: http://developer.chrome.com/apps/app_csp.html -->\n\n    <!-- Warn about failed cross origin requests in Chrome -->\n    <script type=\"application/javascript\" src=\"xorigin.js\"></script>\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"thirdparty/CodeMirror/lib/codemirror.css\">\n    <!--(if target dev)><!-->\n    <link rel=\"stylesheet/less\" type=\"text/css\" href=\"styles/brackets.less\">\n    <!--<!(endif)-->\n    <!--(if target dist)>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/brackets.min.css\">\n    <!--<!(endif)-->\n    \n    <!-- JavaScript -->\n\n    <!-- Pre-load third party scripts that cannot be async loaded. -->\n    <!-- build:js thirdparty/thirdparty.min.js -->\n    <script src=\"thirdparty/less.min.js\"></script>\n    <script src=\"thirdparty/jquery-2.1.3.min.js\"></script>\n    <!-- endbuild -->\n</head>\n<body>\n\n    <!-- HTML content is dynamically loaded and rendered by brackets.js.\n         Any modules that depend on or modify HTML during load should\n         require the \"utils/AppInit\" module and install a callback for\n         \"htmlReady\" (e.g. AppInit.htmlReady(handler)) before touching the DOM.\n    -->\n    \n    <!-- All other scripts are loaded through require. -->\n    <!-- build:js main.js -->\n    <script src=\"thirdparty/requirejs/require.js\" data-main=\"main\"></script>\n    <!-- endbuild -->\n\n    <!-- Verify that all dependencies are loaded. -->\n    <script src=\"dependencies.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/language/CSSUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\n/**\n * Set of utilities for simple parsing of CSS text.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CodeMirror          = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        Async               = require(\"utils/Async\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        HTMLUtils           = require(\"language/HTMLUtils\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        TokenUtils          = require(\"utils/TokenUtils\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    // Constants\n    var SELECTOR   = \"selector\",\n        PROP_NAME  = \"prop.name\",\n        PROP_VALUE = \"prop.value\",\n        IMPORT_URL = \"import.url\";\n\n    var RESERVED_FLOW_NAMES = [\"content\", \"element\"],\n        INVALID_FLOW_NAMES = [\"none\", \"inherit\", \"default\", \"auto\", \"initial\"],\n        IGNORED_FLOW_NAMES = RESERVED_FLOW_NAMES.concat(INVALID_FLOW_NAMES);\n\n    /**\n     * List of all bracket pairs that is keyed by opening brackets, and the inverted list\n     * that is keyed by closing brackets.\n     * @type {{string: string}}\n     */\n    var _bracketPairs = { \"{\": \"}\",\n                          \"[\": \"]\",\n                          \"(\": \")\" },\n        _invertedBracketPairs = _.invert(_bracketPairs);\n\n    /**\n     * Determines if the given path is a CSS preprocessor file that CSSUtils supports.\n     * @param {string} filePath Absolute path to the file.\n     * @return {boolean} true if LanguageManager identifies filePath as less or scss language.\n     */\n    function isCSSPreprocessorFile(filePath) {\n        var languageId = LanguageManager.getLanguageForPath(filePath).getId();\n        return (languageId === \"less\" || languageId === \"scss\");\n    }\n\n    /**\n     * @private\n     * Helper function to check whether the given text string has any non whitespace character.\n     * @param {!string} text\n     * @return {boolean} true if text has any non whitespace character\n     */\n    function _hasNonWhitespace(text) {\n        return (/\\S/.test(text));\n    }\n\n    /**\n     * @private\n     * Returns state of a context\n     * @param {{editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}} ctx\n     * @return {{tokenize:function, state:string, stateArg:string, context:Object}}\n     */\n    function _getContextState(ctx) {\n        if (!ctx || !ctx.token) {\n            return null;\n        }\n        var state = ctx.token.state.localState || ctx.token.state;\n        // if state contains a valid html inner state use that first\n        if (state.htmlState) {\n            state = ctx.token.state.htmlState;\n        } else {\n            if (!state.context && ctx.token.state.html && ctx.token.state.html.localState) {\n                state = ctx.token.state.html.localState;\n            }\n        }\n        return state;\n    }\n\n    /**\n     * @private\n     * Checks if the current cursor position is inside the property name context\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {boolean} true if the context is in property name\n     */\n    function _isInPropName(ctx) {\n        var state = _getContextState(ctx),\n            lastToken;\n        if (!state || !state.context || ctx.token.type === \"comment\") {\n            return false;\n        }\n\n        lastToken = state.context.type;\n        return (lastToken === \"{\" || lastToken === \"rule\" || lastToken === \"block\");\n    }\n\n    /**\n     * @private\n     * Checks if the current cursor position is inside the property value context\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {boolean} true if the context is in property value\n     */\n    function _isInPropValue(ctx) {\n\n        function isInsideParens(context) {\n            if (context.type !== \"parens\" || !context.prev) {\n                return false;\n            }\n\n            if (context.prev.type === \"prop\") {\n                return true;\n            }\n\n            return isInsideParens(context.prev);\n        }\n\n        var state = _getContextState(ctx);\n        if (!state || !state.context || !state.context.prev || ctx.token.type === \"comment\") {\n            return false;\n        }\n\n        return ((state.context.type === \"prop\" &&\n                    (state.context.prev.type === \"rule\" || state.context.prev.type === \"block\")) ||\n                    isInsideParens(state.context));\n    }\n\n    /**\n     * @private\n     * Checks if the current cursor position is inside an at-rule\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {boolean} true if the context is in property value\n     */\n    function _isInAtRule(ctx) {\n        var state = _getContextState(ctx);\n        if (!state || !state.context) {\n            return false;\n        }\n        return (state.context.type === \"atBlock_parens\");\n    }\n\n    /**\n     * @private\n     * Creates a context info object\n     * @param {string=} context A constant string\n     * @param {number=} offset The offset of the token for a given cursor position\n     * @param {string=} name Property name of the context\n     * @param {number=} index The index of the property value for a given cursor position\n     * @param {Array.<string>=} values An array of property values\n     * @param {boolean=} isNewItem If this is true, then the value in index refers to the index at which a new item\n     *     is going to be inserted and should not be used for accessing an existing value in values array.\n     * @param {{start: {line: number, ch: number},\n     *          end: {line: number, ch: number}}=} range A range object with a start position and an end position\n     * @return {{context: string,\n     *           offset: number,\n     *           name: string,\n     *           index: number,\n     *           values: Array.<string>,\n     *           isNewItem: boolean,\n     *           range: {start: {line: number, ch: number},\n     *                   end: {line: number, ch: number}}}} A CSS context info object.\n     */\n    function createInfo(context, offset, name, index, values, isNewItem, range) {\n        var ruleInfo = { context: context || \"\",\n                         offset: offset || 0,\n                         name: name || \"\",\n                         index: -1,\n                         values: [],\n                         isNewItem: (isNewItem === true),\n                         range: range };\n\n        if (context === PROP_VALUE || context === SELECTOR || context === IMPORT_URL) {\n            ruleInfo.index = index;\n            ruleInfo.values = values;\n        }\n\n        return ruleInfo;\n    }\n\n    /**\n     * @private\n     * Scan backwards to check for any prefix if the current context is property name.\n     * If the current context is in a prefix (either 'meta' or '-'), then scan forwards\n     * to collect the entire property name. Return the name of the property in the CSS\n     * context info object if there is one that seems to be valid. Return an empty context\n     * info when we find an invalid one.\n     *\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx  context\n     * @return {{context: string,\n     *           offset: number,\n     *           name: string,\n     *           index: number,\n     *           values: Array.<string>,\n     *           isNewItem: boolean,\n     *           range: {start: {line: number, ch: number},\n     *                   end: {line: number, ch: number}}}} A CSS context info object.\n     */\n    function _getPropNameInfo(ctx) {\n        var propName = \"\",\n            offset = TokenUtils.offsetInToken(ctx),\n            tokenString = ctx.token.string,\n            excludedCharacters = [\";\", \"{\", \"}\"];\n\n        if (ctx.token.type === \"property\" || ctx.token.type === \"property error\" ||\n                ctx.token.type === \"tag\") {\n            propName = tokenString;\n            if (TokenUtils.movePrevToken(ctx) && _hasNonWhitespace(ctx.token.string) &&\n                    excludedCharacters.indexOf(ctx.token.string) === -1) {\n                propName = ctx.token.string + tokenString;\n                offset += ctx.token.string.length;\n            }\n        } else if (ctx.token.type === \"meta\" || tokenString === \"-\") {\n            propName = tokenString;\n            if (TokenUtils.moveNextToken(ctx) &&\n                    (ctx.token.type === \"property\" || ctx.token.type === \"property error\" ||\n                    ctx.token.type === \"tag\")) {\n                propName += ctx.token.string;\n            }\n        } else if (_hasNonWhitespace(tokenString) && excludedCharacters.indexOf(tokenString) === -1) {\n            // We're not inside the property name context.\n            return createInfo();\n        } else {\n            var testPos = {ch: ctx.pos.ch + 1, line: ctx.pos.line},\n                testToken = ctx.editor.getTokenAt(testPos, true);\n\n            if (testToken.type === \"property\" || testToken.type === \"property error\" ||\n                    testToken.type === \"tag\") {\n                propName = testToken.string;\n                offset = 0;\n            } else if (testToken.type === \"meta\" || testToken.string === \"-\") {\n                ctx.pos = testPos;\n                ctx.token = testToken;\n                return _getPropNameInfo(ctx);\n            }\n        }\n\n        // If we're in the property name context but not in an existing property name,\n        // then reset offset to zero.\n        if (propName === \"\") {\n            offset = 0;\n        }\n\n        return createInfo(PROP_NAME, offset, propName);\n    }\n\n    /**\n     * @private\n     * Scans backwards from the current context and returns the name of the property if there is\n     * a valid one.\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string} the property name of the current rule.\n     */\n    function _getPropNameStartingFromPropValue(ctx) {\n        var ctxClone = $.extend({}, ctx),\n            propName = \"\";\n        do {\n            // If we're no longer in the property value before seeing a colon, then we don't\n            // have a valid property name. Just return an empty string.\n            if (ctxClone.token.string !== \":\" && !_isInPropValue(ctxClone)) {\n                return \"\";\n            }\n        } while (ctxClone.token.string !== \":\" && TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctxClone));\n\n        if (ctxClone.token.string === \":\" && TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctxClone) &&\n                (ctxClone.token.type === \"property\" || ctxClone.token.type === \"property error\")) {\n            propName = ctxClone.token.string;\n            if (TokenUtils.movePrevToken(ctxClone) && ctxClone.token.type === \"meta\") {\n                propName = ctxClone.token.string + propName;\n            }\n        }\n\n        return propName;\n    }\n\n    /**\n     * @private\n     * Gets all of the space/comma seperated tokens before the the current cursor position.\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {?Array.<string>} An array of all the space/comma seperated tokens before the\n     *    current cursor position\n     */\n    function _getPrecedingPropValues(ctx) {\n        var lastValue = \"\",\n            curValue,\n            propValues = [];\n        while (ctx.token.string !== \":\" && TokenUtils.movePrevToken(ctx)) {\n            if (ctx.token.string === \":\" || !_isInPropValue(ctx)) {\n                break;\n            }\n\n            curValue = ctx.token.string;\n            if (lastValue !== \"\") {\n                curValue += lastValue;\n            }\n\n            if ((ctx.token.string.length > 0 && !ctx.token.string.match(/\\S/)) ||\n                    ctx.token.string === \",\") {\n                lastValue = curValue;\n            } else {\n                lastValue = \"\";\n                if (propValues.length === 0 || curValue.match(/,\\s*$/)) {\n                    // stack is empty, or current value ends with a comma\n                    // (and optional whitespace), so push it on the stack\n                    propValues.push(curValue);\n                } else {\n                    // current value does not end with a comma (and optional ws) so prepend\n                    // to last stack item (e.g. \"rgba(50\" get broken into 2 tokens)\n                    propValues[propValues.length - 1] = curValue + propValues[propValues.length - 1];\n                }\n            }\n        }\n        if (propValues.length > 0) {\n            propValues.reverse();\n        }\n\n        return propValues;\n    }\n\n    /**\n     * @private\n     * Gets all of the space/comma seperated tokens after the the current cursor position.\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @param {string} currentValue The token string at the current cursor position\n     * @return {?Array.<string>} An array of all the space/comma seperated tokens after the\n     *    current cursor position\n     */\n    function _getSucceedingPropValues(ctx, currentValue) {\n        var lastValue = currentValue,\n            propValues = [];\n\n        while (ctx.token.string !== \";\" && ctx.token.string !== \"}\" && TokenUtils.moveNextToken(ctx)) {\n            if (ctx.token.string === \";\" || ctx.token.string === \"}\") {\n                break;\n            }\n            if (!_isInPropValue(ctx)) {\n                lastValue = \"\";\n                break;\n            }\n\n            if (lastValue === \"\") {\n                lastValue = ctx.token.string.trim();\n            } else if (lastValue.length > 0) {\n                if (ctx.token.string.length > 0 && !ctx.token.string.match(/\\S/)) {\n                    lastValue += ctx.token.string;\n                    propValues.push(lastValue);\n                    lastValue = \"\";\n                } else if (ctx.token.string === \",\") {\n                    lastValue += ctx.token.string;\n                } else if (lastValue && lastValue.match(/,$/)) {\n                    propValues.push(lastValue);\n                    if (ctx.token.string.length > 0) {\n                        lastValue = ctx.token.string;\n                    } else {\n                        lastValue = \"\";\n                    }\n                } else {\n                    // e.g. \"rgba(50\" gets broken into 2 tokens\n                    lastValue += ctx.token.string;\n                }\n            }\n        }\n        if (lastValue.length > 0) {\n            propValues.push(lastValue);\n        }\n\n        return propValues;\n    }\n\n    /**\n     * @private\n     * Return a range object with a start position and an end position after\n     * skipping any whitespaces and all separators used before and after a\n     * valid property value.\n     *\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} startCtx context\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} endCtx context\n     * @return {{start: {line: number, ch: number},\n     *           end: {line: number, ch: number}}} A range object.\n     */\n    function _getRangeForPropValue(startCtx, endCtx) {\n        var range = { \"start\": {},\n                      \"end\": {} };\n\n        // Skip the \":\" and any leading whitespace\n        while (TokenUtils.moveNextToken(startCtx)) {\n            if (_hasNonWhitespace(startCtx.token.string)) {\n                break;\n            }\n        }\n\n        // Skip the trailing whitespace and property separators.\n        while (endCtx.token.string === \";\" || endCtx.token.string === \"}\" ||\n                !_hasNonWhitespace(endCtx.token.string)) {\n            TokenUtils.movePrevToken(endCtx);\n        }\n\n        range.start = _.clone(startCtx.pos);\n        range.start.ch = startCtx.token.start;\n\n        range.end = _.clone(endCtx.pos);\n        range.end.ch = endCtx.token.end;\n\n        return range;\n    }\n\n    /**\n     * @private\n     * Returns a context info object for the current CSS style rule\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @param {!Editor} editor\n     * @return {{context: string,\n     *           offset: number,\n     *           name: string,\n     *           index: number,\n     *           values: Array.<string>,\n     *           isNewItem: boolean,\n     *           range: {start: {line: number, ch: number},\n     *                   end: {line: number, ch: number}}}} A CSS context info object.\n     */\n    function _getRuleInfoStartingFromPropValue(ctx, editorParam) {\n        var editor      = editorParam._codeMirror || editorParam,\n            contextDoc  = editor.document || editor.doc,\n            propNamePos = $.extend({}, ctx.pos),\n            backwardPos = $.extend({}, ctx.pos),\n            forwardPos  = $.extend({}, ctx.pos),\n            propNameCtx = TokenUtils.getInitialContext(editor, propNamePos),\n            backwardCtx,\n            forwardCtx,\n            lastValue = \"\",\n            propValues = [],\n            index = -1,\n            offset = TokenUtils.offsetInToken(ctx),\n            canAddNewOne = false,\n            testPos = {ch: ctx.pos.ch + 1, line: ctx.pos.line},\n            testToken = editor.getTokenAt(testPos, true),\n            propName,\n            range;\n\n        // Get property name first. If we don't have a valid property name, then\n        // return a default rule info.\n        propName = _getPropNameStartingFromPropValue(propNameCtx);\n        if (!propName) {\n            return createInfo();\n        }\n\n        // Scan backward to collect all preceding property values\n        backwardCtx = TokenUtils.getInitialContext(editor, backwardPos);\n        propValues = _getPrecedingPropValues(backwardCtx);\n\n        lastValue = \"\";\n        if (ctx.token.string === \":\") {\n            index = 0;\n            canAddNewOne = true;\n        } else {\n            index = propValues.length - 1;\n            if (ctx.token.string === \",\") {\n                propValues[index] += ctx.token.string;\n                index++;\n                canAddNewOne = true;\n            } else {\n                index = (index < 0) ? 0 : index + 1;\n                if (ctx.token.string.match(/\\S/)) {\n                    lastValue = ctx.token.string;\n                } else {\n                    // Last token is all whitespace\n                    canAddNewOne = true;\n                    if (index > 0) {\n                        // Append all spaces before the cursor to the previous value in values array\n                        propValues[index - 1] += ctx.token.string.substr(0, offset);\n                    }\n                }\n            }\n        }\n\n        if (canAddNewOne) {\n            offset = 0;\n\n            // If pos is at EOL, then there's implied whitespace (newline).\n            if (contextDoc.getLine(ctx.pos.line).length > ctx.pos.ch  &&\n                    (testToken.string.length === 0 || testToken.string.match(/\\S/))) {\n                canAddNewOne = false;\n            }\n        }\n\n        // Scan forward to collect all succeeding property values and append to all propValues.\n        forwardCtx = TokenUtils.getInitialContext(editor, forwardPos);\n        propValues = propValues.concat(_getSucceedingPropValues(forwardCtx, lastValue));\n\n        if (propValues.length) {\n            range = _getRangeForPropValue(backwardCtx, forwardCtx);\n        } else {\n            // No property value, so just return the cursor pos as range\n            range = { \"start\": _.clone(ctx.pos),\n                      \"end\": _.clone(ctx.pos) };\n        }\n\n        // If current index is more than the propValues size, then the cursor is\n        // at the end of the existing property values and is ready for adding another one.\n        if (index === propValues.length) {\n            canAddNewOne = true;\n        }\n\n        return createInfo(PROP_VALUE, offset, propName, index, propValues, canAddNewOne, range);\n    }\n\n    /**\n     * @private\n     * Returns a context info object for the current CSS import rule\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @param {!Editor} editor\n     * @return {{context: string,\n     *           offset: number,\n     *           name: string,\n     *           index: number,\n     *           values: Array.<string>,\n     *           isNewItem: boolean,\n     *           range: {start: {line: number, ch: number},\n     *                   end: {line: number, ch: number}}}} A CSS context info object.\n     */\n    function _getImportUrlInfo(ctx, editor) {\n        var backwardPos = $.extend({}, ctx.pos),\n            forwardPos  = $.extend({}, ctx.pos),\n            backwardCtx,\n            forwardCtx,\n            index = 0,\n            propValues = [],\n            offset = TokenUtils.offsetInToken(ctx);\n\n        // Currently only support url. May be null if starting to type\n        if (ctx.token.type && ctx.token.type !== \"string\") {\n            return createInfo();\n        }\n\n        // Move backward to @import and collect data as we go. We return propValues\n        // array, but we can only have 1 value, so put all data in first item\n        backwardCtx = TokenUtils.getInitialContext(editor._codeMirror, backwardPos);\n        propValues[0] = backwardCtx.token.string;\n\n        while (TokenUtils.movePrevToken(backwardCtx)) {\n            if (backwardCtx.token.type === \"def\" && backwardCtx.token.string === \"@import\") {\n                break;\n            }\n\n            if (backwardCtx.token.type && backwardCtx.token.type !== \"atom\" && backwardCtx.token.string !== \"url\") {\n                // Previous token may be white-space\n                // Otherwise, previous token may only be \"url(\"\n                break;\n            }\n\n            propValues[0] = backwardCtx.token.string + propValues[0];\n            offset += backwardCtx.token.string.length;\n        }\n\n        if (backwardCtx.token.type !== \"def\" || backwardCtx.token.string !== \"@import\") {\n            // Not in url\n            return createInfo();\n        }\n\n        // Get value after cursor up until closing paren or newline\n        forwardCtx = TokenUtils.getInitialContext(editor._codeMirror, forwardPos);\n        do {\n            if (!TokenUtils.moveNextToken(forwardCtx)) {\n                if (forwardCtx.token.string === \"(\") {\n                    break;\n                } else {\n                    return createInfo();\n                }\n            }\n            propValues[0] += forwardCtx.token.string;\n        } while (forwardCtx.token.string !== \")\" && forwardCtx.token.string !== \"\");\n\n        return createInfo(IMPORT_URL, offset, \"\", index, propValues, false);\n    }\n\n    /**\n     * Returns a context info object for the given cursor position\n     * @param {!Editor} editor\n     * @param {{ch: number, line: number}} constPos  A CM pos (likely from editor.getCursorPos())\n     * @return {{context: string,\n     *           offset: number,\n     *           name: string,\n     *           index: number,\n     *           values: Array.<string>,\n     *           isNewItem: boolean,\n     *           range: {start: {line: number, ch: number},\n     *                   end: {line: number, ch: number}}}} A CSS context info object.\n     */\n    function getInfoAtPos(editor, constPos) {\n        // We're going to be changing pos a lot, but we don't want to mess up\n        // the pos the caller passed in so we use extend to make a safe copy of it.\n        var pos = $.extend({}, constPos),\n            ctx = TokenUtils.getInitialContext(editor._codeMirror, pos),\n            mode = editor.getModeForSelection();\n\n        // Check if this is inside a style block or in a css/less document.\n        if (mode !== \"css\" && mode !== \"text/x-scss\" && mode !== \"text/x-less\") {\n            return createInfo();\n        }\n\n        // Context from the current editor will have htmlState if we are in css mode\n        // and in attribute value state of a tag with attribute name style\n        if (ctx.token.state.htmlState && (!ctx.token.state.localMode || ctx.token.state.localMode.name !== \"css\")) {\n\n            // tagInfo is required to aquire the style attr value\n            var tagInfo = HTMLUtils.getTagInfo(editor, pos, true),\n                // To be used as relative character position\n                offset = tagInfo.position.offset;\n\n            /**\n             * We will use this CM to cook css context in case of style attribute value\n             * as CM in htmlmixed mode doesn't yet identify this as css context. We provide\n             * a no-op display function to run CM without a DOM head.\n             */\n            var _contextCM = new CodeMirror(function () {}, {\n                value: \"{\" + tagInfo.attr.value.replace(/(^\")|(\"$)/g, \"\"),\n                mode:  \"css\"\n            });\n\n            ctx = TokenUtils.getInitialContext(_contextCM, {line: 0, ch: offset + 1});\n        }\n        \n        if (_isInPropName(ctx)) {\n            return _getPropNameInfo(ctx);\n        }\n        \n        if (_isInPropValue(ctx)) {\n            return _getRuleInfoStartingFromPropValue(ctx, ctx.editor);\n        }\n        \n        if (_isInAtRule(ctx)) {\n            return _getImportUrlInfo(ctx, editor);\n        }\n\n        return createInfo();\n    }\n\n    /**\n     * Return a string that shows the literal parent hierarchy of the selector\n     * in info.\n     *\n     * @param {!SelectorInfo} info\n     * @param {boolean=} useGroup true to append selectorGroup instead of selector\n     * @return {string} the literal parent hierarchy of the selector\n     */\n    function getCompleteSelectors(info, useGroup) {\n        if (info.parentSelectors) {\n            // Show parents with / separators.\n            var completeSelectors = info.parentSelectors + \" / \";\n            if (useGroup && info.selectorGroup) {\n                completeSelectors += info.selectorGroup;\n            } else {\n                completeSelectors += info.selector;\n            }\n            return completeSelectors;\n        } else if (useGroup && info.selectorGroup) {\n            return info.selectorGroup;\n        }\n\n        return info.selector;\n    }\n\n    /**\n     * @typedef {{selector: !string,\n     *            ruleStartLine: number,\n     *            ruleStartChar: number,\n     *            selectorStartLine: number,\n     *            selectorStartChar: number,\n     *            selectorEndLine: number,\n     *            selectorEndChar: number,\n     *            selectorGroupStartLine: number,\n     *            selectorGroupStartChar: number,\n     *            selectorGroup: ?string,\n     *            declListStartLine: number,\n     *            declListStartChar: number,\n     *            declListEndLine: number,\n     *            declListEndChar: number,\n     *            level: number,\n     *            parentSelectors: ?string}} SelectorInfo\n     */\n\n    /**\n     * Extracts all CSS selectors from the given text\n     * Returns an array of SelectorInfo. Each SelectorInfo is an object with the following properties:\n         selector:                 the text of the selector (note: comma separated selector groups like\n                                   \"h1, h2\" are broken into separate selectors)\n         ruleStartLine:            line in the text where the rule (including preceding comment) appears\n         ruleStartChar:            column in the line where the rule (including preceding comment) starts\n         selectorStartLine:        line in the text where the selector appears\n         selectorStartChar:        column in the line where the selector starts\n         selectorEndLine:          line where the selector ends\n         selectorEndChar:          column where the selector ends\n         selectorGroupStartLine:   line where the comma-separated selector group (e.g. .foo, .bar, .baz)\n                                   starts that this selector (e.g. .baz) is part of. Particularly relevant for\n                                   groups that are on multiple lines.\n         selectorGroupStartChar:   column in line where the selector group starts.\n         selectorGroup:            the entire selector group containing this selector, or undefined if there\n                                   is only one selector in the rule.\n         declListStartLine:        line where the declaration list for the rule starts\n         declListStartChar:        column in line where the declaration list for the rule starts\n         declListEndLine:          line where the declaration list for the rule ends\n         declListEndChar:          column in the line where the declaration list for the rule ends\n         level:                    the level of the current selector including any containing @media block in the\n                                   nesting level count. Use this property with caution since it is primarily for internal\n                                   parsing use. For example, two sibling selectors may have different levels if one\n                                   of them is nested inside an @media block and it should not be used for sibling info.\n         parentSelectors:          all ancestor selectors separated with '/' if the current selector is a nested one\n     * @param {!string} text CSS text to extract from\n     * @param {?string} documentMode language mode of the document that text belongs to, default to css if undefined.\n     * @return {Array.<SelectorInfo>} Array with objects specifying selectors.\n     */\n    function extractAllSelectors(text, documentMode) {\n        var state, lines, lineCount,\n            token, style, stream, line,\n            selectors              = [],\n            mode                   = CodeMirror.getMode({indentUnit: 2}, documentMode || \"css\"),\n            currentSelector        = \"\",\n            currentLevel           = 0,\n            ruleStartChar          = -1,\n            ruleStartLine          = -1,\n            selectorStartChar      = -1,\n            selectorStartLine      = -1,\n            selectorGroupStartLine = -1,\n            selectorGroupStartChar = -1,\n            declListStartLine      = -1,\n            declListStartChar      = -1,\n            escapePattern          = new RegExp(\"\\\\\\\\[^\\\\\\\\]+\", \"g\"),\n            validationPattern      = new RegExp(\"\\\\\\\\([a-f0-9]{6}|[a-f0-9]{4}(\\\\s|\\\\\\\\|$)|[a-f0-9]{2}(\\\\s|\\\\\\\\|$)|.)\", \"i\"),\n            _parseRuleList;\n\n        // implement _firstToken()/_nextToken() methods to\n        // provide a single stream of tokens\n\n        function _hasStream() {\n            while (stream.eol()) {\n                line++;\n                if (line >= lineCount) {\n                    return false;\n                }\n                if (_hasNonWhitespace(currentSelector)) {\n                    // If we are in a current selector and starting a newline,\n                    // make sure there is whitespace in the selector\n                    currentSelector += \" \";\n                }\n                stream = new CodeMirror.StringStream(lines[line]);\n            }\n            return true;\n        }\n\n        function _firstToken() {\n            state = CodeMirror.startState(mode);\n            lines = CodeMirror.splitLines(text);\n            lineCount = lines.length;\n            if (lineCount === 0) {\n                return false;\n            }\n            line = 0;\n            stream = new CodeMirror.StringStream(lines[line]);\n            if (!_hasStream()) {\n                return false;\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            return true;\n        }\n\n        function _nextToken() {\n            // advance the stream past this token\n            stream.start = stream.pos;\n            if (!_hasStream()) {\n                return false;\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            return true;\n        }\n\n        function _firstTokenSkippingWhitespace() {\n            if (!_firstToken()) {\n                return false;\n            }\n            while (!_hasNonWhitespace(token)) {\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _nextTokenSkippingWhitespace() {\n            if (!_nextToken()) {\n                return false;\n            }\n            while (!_hasNonWhitespace(token)) {\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _isStartComment() {\n            // Also check for line comments used in LESS and SASS.\n            return (/^\\/[\\/\\*]/.test(token));\n        }\n\n        function _parseComment() {\n            // If it is a line comment, then do nothing and just return. Unlike block\n            // comment, a line comment is just one single token and the caller always\n            // has to find the next token by skipping the current token. So leaving\n            // it for the caller to skip the current token.\n            if (/^\\/\\//.test(token)) {\n                return;\n            }\n            while (!/\\*\\/$/.test(token)) {\n                if (!_nextToken()) {\n                    break;\n                }\n            }\n        }\n\n        function _nextTokenSkippingComments() {\n            if (!_nextToken()) {\n                return false;\n            }\n            while (_isStartComment()) {\n                _parseComment();\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _skipToClosingBracket(startChar) {\n            var skippedText = \"\",\n                unmatchedBraces = 0;\n            if (!startChar) {\n                startChar = \"{\";\n            }\n            while (true) {\n                if (token.indexOf(startChar) !== -1 && token.indexOf(_bracketPairs[startChar]) === -1) {\n                    // Found an opening bracket but not the matching closing bracket in the same token\n                    unmatchedBraces++;\n                } else if (token === _bracketPairs[startChar]) {\n                    unmatchedBraces--;\n                    if (unmatchedBraces <= 0) {\n                        skippedText += token;\n                        return skippedText;\n                    }\n                }\n                skippedText += token;\n\n                if (!_nextTokenSkippingComments()) {\n                    return skippedText; // eof\n                }\n            }\n        }\n\n        function _maybeProperty() {\n            return (/^-(moz|ms|o|webkit)-$/.test(token) ||\n                    (state.state !== \"top\" && state.state !== \"block\" && state.state !== \"pseudo\" &&\n                    // Has a semicolon as in \"rgb(0,0,0);\", but not one of those after a LESS\n                    // mixin parameter variable as in \".size(@width; @height)\"\n                    stream.string.indexOf(\";\") !== -1 && !/\\([^)]+;/.test(stream.string)));\n        }\n\n        function _skipProperty() {\n            var prevToken = \"\";\n            while (token !== \";\") {\n                // Skip tokens until the closing brace if we find an interpolated variable.\n                if (/[#@]\\{$/.test(token) || (token === \"{\" && /[#@]$/.test(prevToken))) {\n                    _skipToClosingBracket(\"{\");\n                    if (token === \"}\") {\n                        _nextToken();   // Skip the closing brace\n                    }\n                    if (token === \";\") {\n                        break;\n                    }\n                }\n                // If there is a '{' or '}' before the ';',\n                // then stop skipping.\n                if (token === \"{\" || token === \"}\") {\n                    return false;   // can't tell if the entire property is skipped\n                }\n                prevToken = token;\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n            }\n            return true;    // skip the entire property\n        }\n\n        function _getParentSelectors() {\n            var j;\n            for (j = selectors.length - 1; j >= 0; j--) {\n                if (selectors[j].declListEndLine === -1 && selectors[j].level < currentLevel) {\n                    return getCompleteSelectors(selectors[j], true);\n                }\n            }\n            return \"\";\n        }\n\n        function _parseSelector(start, level) {\n\n            currentSelector = \"\";\n            selectorStartChar = start;\n            selectorStartLine = line;\n\n            // Everything until the next ',' or '{' is part of the current selector\n            while ((token !== \",\" && token !== \"{\") ||\n                    (token === \"{\" && /[#@]$/.test(currentSelector)) ||\n                    (token === \",\" && !_hasNonWhitespace(currentSelector))) {\n                if (token === \"{\") {\n                    // Append the interpolated variable to selector\n                    currentSelector += _skipToClosingBracket(\"{\");\n                    _nextToken();  // skip the closing brace\n                } else if (token === \"}\" &&\n                        (!currentSelector || /:\\s*\\S/.test(currentSelector) || !/[#@]\\{.+/.test(currentSelector))) {\n                    // Either empty currentSelector or currentSelector is a CSS property\n                    // but not a selector that is in the form of #{$class} or @{class}\n                    return false;\n                }\n                // Clear currentSelector if we're in a property, but make sure we don't treat\n                // the semicolors inside a parameter as a property separators.\n                if ((token === \";\" && state.state !== \"parens\") ||\n                        // Make sure that something like `> li > a {` is not identified as a property\n                        (state.state === \"prop\" && !/\\{/.test(stream.string))) {\n                    currentSelector = \"\";\n                } else if (token === \"(\") {\n                    // Collect everything inside the parentheses as a whole chunk so that\n                    // commas inside the parentheses won't be identified as selector separators\n                    // by while loop.\n                    if (_hasNonWhitespace(currentSelector)) {\n                        currentSelector += _skipToClosingBracket(\"(\");\n                    } else {\n                        // Nothing in currentSelector yet. Skip to the closing parenthesis\n                        // without collecting the selector since a selector cannot start with\n                        // an opening parenthesis.\n                        _skipToClosingBracket(\"(\");\n                    }\n                } else if (_hasNonWhitespace(token) || _hasNonWhitespace(currentSelector)) {\n                    currentSelector += token;\n                }\n                if (!_nextTokenSkippingComments()) {\n                    return false; // eof\n                }\n            }\n\n            if (!currentSelector) {\n                return false;\n            }\n\n            // Unicode character replacement as defined in http://www.w3.org/TR/CSS21/syndata.html#characters\n            if (/\\\\/.test(currentSelector)) {\n                // Double replace in case of pattern overlapping (regex improvement?)\n                currentSelector = currentSelector.replace(escapePattern, function (escapedToken) {\n                    return escapedToken.replace(validationPattern, function (unicodeChar) {\n                        unicodeChar = unicodeChar.substr(1);\n                        if (unicodeChar.length === 1) {\n                            return unicodeChar;\n                        } else {\n                            if (parseInt(unicodeChar, 16) < 0x10FFFF) {\n                                return String.fromCharCode(parseInt(unicodeChar, 16));\n                            } else { return String.fromCharCode(0xFFFD); }\n                        }\n                    });\n                });\n            }\n\n            currentSelector = currentSelector.trim();\n            var startChar = (selectorGroupStartLine === -1) ? selectorStartChar : selectorStartChar + 1;\n            var selectorStart = (stream.string.indexOf(currentSelector, selectorStartChar) !== -1) ? stream.string.indexOf(currentSelector, selectorStartChar - currentSelector.length) : startChar;\n\n            if (currentSelector !== \"\") {\n                if (currentLevel < level) {\n                    currentLevel++;\n                }\n                if (ruleStartLine === -1) {\n                    ruleStartLine = line;\n                    ruleStartChar = stream.start - currentSelector.length;\n                }\n                var parentSelectors = _getParentSelectors();\n                selectors.push({selector: currentSelector,\n                                ruleStartLine: ruleStartLine,\n                                ruleStartChar: ruleStartChar,\n                                selectorStartLine: selectorStartLine,\n                                selectorStartChar: selectorStart,\n                                declListEndLine: -1,\n                                selectorEndLine: line,\n                                selectorEndChar: selectorStart + currentSelector.length,\n                                selectorGroupStartLine: selectorGroupStartLine,\n                                selectorGroupStartChar: selectorGroupStartChar,\n                                level: currentLevel,\n                                parentSelectors: parentSelectors\n                               });\n                currentSelector = \"\";\n            }\n            selectorStartChar = -1;\n\n            return true;\n        }\n\n        function _parseSelectorList(level) {\n            selectorGroupStartLine = (stream.string.indexOf(\",\") !== -1) ? line : -1;\n            selectorGroupStartChar = stream.start;\n\n            if (!_parseSelector(stream.start, level)) {\n                return false;\n            }\n\n            while (token === \",\") {\n                if (!_nextTokenSkippingComments()) {\n                    return false; // eof\n                }\n                if (!_parseSelector(stream.start, level)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        function _parseDeclarationList(level) {\n\n            var j;\n            declListStartLine = Math.min(line, lineCount - 1);\n            declListStartChar = stream.start;\n\n            // Extract the entire selector group we just saw.\n            var selectorGroup, sgLine;\n            if (selectorGroupStartLine !== -1) {\n                selectorGroup = \"\";\n                for (sgLine = selectorGroupStartLine; sgLine <= declListStartLine; sgLine++) {\n                    var startChar = 0, endChar = lines[sgLine].length;\n                    if (sgLine === selectorGroupStartLine) {\n                        startChar = selectorGroupStartChar;\n                    } else {\n                        selectorGroup += \" \"; // replace the newline with a single space\n                    }\n                    if (sgLine === declListStartLine) {\n                        endChar = declListStartChar;\n                    }\n                    selectorGroup += lines[sgLine].substring(startChar, endChar).trim();\n                }\n                selectorGroup = selectorGroup.trim();\n            }\n\n            // assign this declaration list position and selector group to every selector on the stack\n            // that doesn't have a declaration list start and end line\n            for (j = selectors.length - 1; j >= 0; j--) {\n                if (selectors[j].level === level) {\n                    if (selectors[j].declListEndLine !== -1) {\n                        break;\n                    } else {\n                        selectors[j].declListStartLine = declListStartLine;\n                        selectors[j].declListStartChar = declListStartChar;\n                        if (selectorGroup) {\n                            selectors[j].selectorGroup = selectorGroup;\n                        }\n                    }\n                }\n            }\n\n            var nested = true;\n            do {\n                // Since we're now in a declaration list, that means we also finished\n                // parsing the whole selector group. Therefore, reset selectorGroupStartLine\n                // so that next time we parse a selector we know it's a new group\n                selectorGroupStartLine = -1;\n                selectorGroupStartChar = -1;\n                ruleStartLine = -1;\n                ruleStartChar = -1;\n\n                if (!nested) {\n                    if (currentLevel > 0 && currentLevel === level) {\n                        currentLevel--;\n                        // Skip past '}'\n                        if (token === \"}\") {\n                            _nextTokenSkippingWhitespace();\n                        }\n                    }\n                }\n                // Skip past '{' before parsing nested rule list.\n                if (token === \"{\") {\n                    _nextTokenSkippingWhitespace();\n                }\n                nested = _parseRuleList(undefined, currentLevel + 1);\n\n                // assign this declaration list position to every selector on the stack\n                // that doesn't have a declaration list end line\n                for (j = selectors.length - 1; j >= 0; j--) {\n                    if (selectors[j].level < currentLevel) {\n                        break;\n                    }\n                    if (selectors[j].declListEndLine === -1) {\n                        selectors[j].declListEndLine = line;\n                        selectors[j].declListEndChar = stream.pos - 1; // stream.pos actually points to the char after the }\n                    }\n                }\n            } while (currentLevel > 0 && currentLevel === level);\n        }\n\n        function includeCommentInNextRule() {\n            if (ruleStartChar !== -1) {\n                return false;       // already included\n            }\n            if (stream.start > 0 && lines[line].substr(0, stream.start).indexOf(\"}\") !== -1) {\n                return false;       // on same line as '}', so it's for previous rule\n            }\n            return true;\n        }\n\n        function _isStartAtRule() {\n            // Exclude @mixin from at-rule so that we can parse it like a normal rule list\n            return (/^@/.test(token) && !/^@mixin/i.test(token) && token !== \"@\");\n        }\n\n        function _followedByPseudoSelector() {\n            return (/\\}:(enabled|disabled|checked|indeterminate|link|visited|hover|active|focus|target|lang|root|nth-|first-|last-|only-|empty|not)/.test(stream.string));\n        }\n\n        function _isVariableInterpolatedProperty() {\n            return (/[@#]\\{\\S+\\}(\\s*:|.*;)/.test(stream.string) && !_followedByPseudoSelector());\n        }\n\n        function _parseAtRule(level) {\n\n            // reset these fields to ignore comments preceding @rules\n            ruleStartLine = -1;\n            ruleStartChar = -1;\n            selectorStartLine = -1;\n            selectorStartChar = -1;\n            selectorGroupStartLine = -1;\n            selectorGroupStartChar = -1;\n\n            if (/@media/i.test(token)) {\n                // @media rule holds a rule list\n\n                // Skip everything until the opening '{'\n                while (token !== \"{\") {\n                    if (!_nextTokenSkippingComments()) {\n                        return; // eof\n                    }\n                }\n\n                // skip past '{', to next non-ws token\n                if (!_nextTokenSkippingWhitespace()) {\n                    return; // eof\n                }\n\n                if (currentLevel <= level) {\n                    currentLevel++;\n                }\n\n                // Parse rules until we see '}'\n                // Treat media rule as one nested level by\n                // calling _parseRuleList with next level.\n                _parseRuleList(\"}\", currentLevel + 1);\n\n                if (currentLevel > 0) {\n                    currentLevel--;\n                }\n\n            } else {\n                // This code handles @rules in this format:\n                //   @rule ... ;\n                // Or any less variable that starts with @var ... ;\n                // Skip everything until the next ';'\n                while (token !== \";\") {\n                    // This code handle @rules that use this format:\n                    //    @rule ... { ... }\n                    // such as @page, @keyframes (also -webkit-keyframes, etc.), and @font-face.\n                    // Skip everything including nested braces until the next matching '}'\n                    if (token === \"{\") {\n                        _skipToClosingBracket(\"{\");\n                        return;\n                    }\n                    if (!_nextTokenSkippingComments()) {\n                        return; // eof\n                    }\n                }\n            }\n        }\n\n        // parse a style rule\n        function _parseRule(level) {\n            if (!_parseSelectorList(level)) {\n                return false;\n            }\n\n            _parseDeclarationList(level);\n            return true;\n        }\n\n        _parseRuleList = function (escapeToken, level) {\n            while ((!escapeToken) || token !== escapeToken) {\n                if (_isVariableInterpolatedProperty()) {\n                    if (!_skipProperty()) {\n                        // We found a \"{\" or \"}\" while skipping a property. Return false to handle the\n                        // opening or closing of a block properly.\n                        return false;\n                    }\n                } else if (_isStartAtRule()) {\n                    // @rule\n                    _parseAtRule(level);\n                } else if (_isStartComment()) {\n                    // comment - make this part of style rule\n                    if (includeCommentInNextRule()) {\n                        ruleStartChar = stream.start;\n                        ruleStartLine = line;\n                    }\n                    _parseComment();\n                } else if (_maybeProperty()) {\n                    // Skip the property.\n                    if (!_skipProperty()) {\n                        // We found a \"{\" or \"}\" while skipping a property. Return false to handle the\n                        // opening or closing of a block properly.\n                        return false;\n                    }\n                } else {\n                    // Otherwise, it's style rule\n                    if (!_parseRule(level === undefined ? 0 : level) && level > 0) {\n                        return false;\n                    }\n                    if (level > 0) {\n                        return true;\n                    }\n                    // Clear ruleStartChar and ruleStartLine in case we have a comment\n                    // at the end of previous rule in level 0.\n                    ruleStartChar = -1;\n                    ruleStartLine = -1;\n                }\n\n                if (!_nextTokenSkippingWhitespace()) {\n                    break;\n                }\n            }\n\n            return true;\n        };\n\n        // Do parsing\n\n        if (_firstTokenSkippingWhitespace()) {\n\n            // Style sheet is a rule list\n            _parseRuleList();\n        }\n\n        return selectors;\n    }\n\n    /*\n     * This code can be used to create an \"independent\" HTML document that can be passed to jQuery\n     * calls. Allows using jQuery's CSS selector engine without actually putting anything in the browser's DOM\n     *\n    var _htmlDoctype = document.implementation.createDocumentType('html',\n        '-//W3C//DTD XHTML 1.0 Strict//EN',\n        'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'\n    );\n    var _htmlDocument = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', _htmlDoctype);\n\n    function checkIfSelectorSelectsHTML(selector, theHTML) {\n        $('html', _htmlDocument).html(theHTML);\n        return ($(selector, _htmlDocument).length > 0);\n    }\n    */\n\n    /**\n     * Helper function to remove whitespaces before and after a selector\n     * Returns trimmed selector if it is not an at-rule, or null if it starts with @.\n     *\n     * @param {string} selector\n     * @return {string}\n     */\n    function _stripAtRules(selector) {\n        selector = selector.trim();\n        if (selector.indexOf(\"@\") === 0) {\n            return \"\";\n        }\n        return selector;\n    }\n\n    /**\n     * Converts the given selector array into the actual CSS selectors similar to\n     * those generated by a CSS preprocessor.\n     *\n     * @param {Array.<string>} selectorArray\n     * @return {string}\n     */\n    function _getSelectorInFinalCSSForm(selectorArray) {\n        var finalSelectorArray = [\"\"],\n            parentSelectorArray = [],\n            group = [];\n        _.forEach(selectorArray, function (selector) {\n            selector = _stripAtRules(selector);\n            group = selector.split(\",\");\n            parentSelectorArray = [];\n            _.forEach(group, function (cs) {\n                var ampersandIndex = cs.indexOf(\"&\");\n                _.forEach(finalSelectorArray, function (ps) {\n                    if (ampersandIndex === -1) {\n                        cs = _stripAtRules(cs);\n                        if (ps.length && cs.length) {\n                            ps += \" \";\n                        }\n                        ps += cs;\n                    } else {\n                        // Replace all instances of & with regexp\n                        ps = _stripAtRules(cs.replace(/&/g, ps));\n                    }\n                    parentSelectorArray.push(ps);\n                });\n            });\n            finalSelectorArray = parentSelectorArray;\n        });\n        return finalSelectorArray.join(\", \");\n    }\n\n    /**\n     * Finds all instances of the specified selector in \"text\".\n     * Returns an Array of Objects with start and end properties.\n     *\n     * For now, we only support simple selectors. This function will need to change\n     * dramatically to support full selectors.\n     *\n     * FUTURE: (JRB) It would be nice to eventually use the browser/jquery to do the selector evaluation.\n     * One way to do this would be to take the user's HTML, add a special attribute to every tag with a UID,\n     * and then construct a DOM (using the commented out code above). Then, give this DOM and the selector to\n     * jquery and ask what matches. If the node that the user's cursor is in comes back from jquery, then\n     * we know the selector applies.\n     *\n     * @param {!string} text CSS text to search\n     * @param {!string} selector selector to search for\n     * @param {!string} mode language mode of the document that text belongs to\n     * @return {Array.<{selectorGroupStartLine:number, declListEndLine:number, selector:string}>}\n     *      Array of objects containing the start and end line numbers (0-based, inclusive range) for each\n     *      matched selector.\n     */\n    function _findAllMatchingSelectorsInText(text, selector, mode) {\n        var allSelectors = extractAllSelectors(text, mode);\n        var result = [];\n\n        // For now, we only match the rightmost simple selector, and ignore\n        // attribute selectors and pseudo selectors\n        var classOrIdSelector = selector[0] === \".\" || selector[0] === \"#\";\n\n        // Escape initial \".\" in selector, if present.\n        if (selector[0] === \".\") {\n            selector = \"\\\\\" + selector;\n        }\n\n        if (!classOrIdSelector) {\n            // Tag selectors must have nothing, whitespace, or a combinator before it.\n            selector = \"(^|[\\\\s>+~])\" + selector;\n        }\n\n        var re = new RegExp(selector + \"(\\\\[[^\\\\]]*\\\\]|:{1,2}[\\\\w-()]+|\\\\.[\\\\w-]+|#[\\\\w-]+)*\\\\s*$\", classOrIdSelector ? \"\" : \"i\");\n        allSelectors.forEach(function (entry) {\n            var actualSelector = entry.selector;\n            if (entry.selector.indexOf(\"&\") !== -1 && entry.parentSelectors) {\n                var selectorArray = entry.parentSelectors.split(\" / \");\n                selectorArray.push(entry.selector);\n                actualSelector = _getSelectorInFinalCSSForm(selectorArray);\n            }\n            if (actualSelector.search(re) !== -1) {\n                result.push(entry);\n            } else if (!classOrIdSelector) {\n                // Special case for tag selectors - match \"*\" as the rightmost character\n                if (/\\*\\s*$/.test(actualSelector)) {\n                    result.push(entry);\n                }\n            }\n        });\n\n        return result;\n    }\n\n    /**\n     * Converts the results of _findAllMatchingSelectorsInText() into a simpler bag of data and\n     * appends those new objects to the given 'resultSelectors' Array.\n     * @param {Array.<{document:Document, lineStart:number, lineEnd:number}>} resultSelectors\n     * @param {Array.<SelectorInfo>} selectorsToAdd\n     * @param {!Document} sourceDoc\n     * @param {!number} lineOffset Amount to offset all line number info by. Used if the first line\n     *          of the parsed CSS text is not the first line of the sourceDoc.\n     */\n    function _addSelectorsToResults(resultSelectors, selectorsToAdd, sourceDoc, lineOffset) {\n        selectorsToAdd.forEach(function (selectorInfo) {\n            resultSelectors.push({\n                name: getCompleteSelectors(selectorInfo),\n                document: sourceDoc,\n                lineStart: selectorInfo.ruleStartLine + lineOffset,\n                lineEnd: selectorInfo.declListEndLine + lineOffset,\n                selectorGroup: selectorInfo.selectorGroup\n            });\n        });\n    }\n\n    /** Finds matching selectors in CSS files; adds them to 'resultSelectors' */\n    function _findMatchingRulesInCSSFiles(selector, resultSelectors) {\n        var result          = new $.Deferred();\n\n        // Load one CSS file and search its contents\n        function _loadFileAndScan(fullPath, selector) {\n            var oneFileResult = new $.Deferred();\n\n            DocumentManager.getDocumentForPath(fullPath)\n                .done(function (doc) {\n                    // Find all matching rules for the given CSS file's content, and add them to the\n                    // overall search result\n                    var oneCSSFileMatches = _findAllMatchingSelectorsInText(doc.getText(), selector, doc.getLanguage().getMode());\n                    _addSelectorsToResults(resultSelectors, oneCSSFileMatches, doc, 0);\n\n                    oneFileResult.resolve();\n                })\n                .fail(function (error) {\n                    console.warn(\"Unable to read \" + fullPath + \" during CSS rule search:\", error);\n                    oneFileResult.resolve();  // still resolve, so the overall result doesn't reject\n                });\n\n            return oneFileResult.promise();\n        }\n\n        ProjectManager.getAllFiles(ProjectManager.getLanguageFilter([\"css\", \"less\", \"scss\"]))\n            .done(function (cssFiles) {\n                // Load index of all CSS files; then process each CSS file in turn (see above)\n                Async.doInParallel(cssFiles, function (fileInfo, number) {\n                    return _loadFileAndScan(fileInfo.fullPath, selector);\n                })\n                    .then(result.resolve, result.reject);\n            });\n\n        return result.promise();\n    }\n\n    /** Finds matching selectors in the <style> block of a single HTML file; adds them to 'resultSelectors' */\n    function _findMatchingRulesInStyleBlocks(htmlDocument, selector, resultSelectors) {\n        // HTMLUtils requires a real CodeMirror instance; make sure we can give it the right Editor\n        var htmlEditor = EditorManager.getCurrentFullEditor();\n        if (htmlEditor.document !== htmlDocument) {\n            console.error(\"Cannot search for <style> blocks in HTML file other than current editor\");\n            return;\n        }\n\n        // Find all <style> blocks in the HTML file\n        var styleBlocks = HTMLUtils.findStyleBlocks(htmlEditor);\n\n        styleBlocks.forEach(function (styleBlockInfo) {\n            // Search this one <style> block's content, appending results to 'resultSelectors'\n            var oneStyleBlockMatches = _findAllMatchingSelectorsInText(styleBlockInfo.text, selector);\n            _addSelectorsToResults(resultSelectors, oneStyleBlockMatches, htmlDocument, styleBlockInfo.start.line);\n        });\n    }\n\n    /**\n     * Return all rules matching the specified selector.\n     * For now, we only look at the rightmost simple selector. For example, searching for \".foo\" will\n     * match these rules:\n     *  .foo {}\n     *  div .foo {}\n     *  div.foo {}\n     *  div .foo[bar=\"42\"] {}\n     *  div .foo:hovered {}\n     *  div .foo::first-child\n     * but will *not* match these rules:\n     *  .foobar {}\n     *  .foo .bar {}\n     *  div .foo .bar {}\n     *  .foo.bar {}\n     *\n     * @param {!string} selector The selector to match. This can be a tag selector, class selector or id selector\n     * @param {?Document} htmlDocument An HTML file for context (so we can search <style> blocks)\n     * @return {$.Promise} that will be resolved with an Array of objects containing the\n     *      source document, start line, and end line (0-based, inclusive range) for each matching declaration list.\n     *      Does not addRef() the documents returned in the array.\n     */\n    function findMatchingRules(selector, htmlDocument) {\n        var result          = new $.Deferred(),\n            resultSelectors = [];\n\n        // Synchronously search for matches in <style> blocks\n        if (htmlDocument) {\n            _findMatchingRulesInStyleBlocks(htmlDocument, selector, resultSelectors);\n        }\n\n        // Asynchronously search for matches in all the project's CSS files\n        // (results are appended together in same 'resultSelectors' array)\n        _findMatchingRulesInCSSFiles(selector, resultSelectors)\n            .done(function () {\n                result.resolve(resultSelectors);\n            })\n            .fail(function (error) {\n                result.reject(error);\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * Returns the selector(s) of the rule at the specified document pos, or \"\" if the position is\n     * is not within a style rule.\n     *\n     * @param {!Editor} editor Editor to search\n     * @param {!{line: number, ch: number}} pos Position to search\n     * @return {string} Selector(s) for the rule at the specified position, or \"\" if the position\n     *          is not within a style rule. If the rule has multiple selectors, a comma-separated\n     *          selector string is returned.\n     */\n    function findSelectorAtDocumentPos(editor, pos) {\n        var cm = editor._codeMirror;\n        var ctx = TokenUtils.getInitialContext(cm, $.extend({}, pos));\n        var selector = \"\", foundChars = false;\n        var isPreprocessorDoc = isCSSPreprocessorFile(editor.document.file.fullPath);\n        var selectorArray = [];\n\n        function _skipToOpeningBracket(ctx, startChar) {\n            var unmatchedBraces = 0;\n            if (!startChar) {\n                startChar = \"}\";\n            }\n            while (true) {\n                if (startChar === ctx.token.string) {\n                    unmatchedBraces++;\n                } else if (ctx.token.string.match(_invertedBracketPairs[startChar])) {\n                    unmatchedBraces--;\n                    if (unmatchedBraces <= 0) {\n                        return;\n                    }\n                }\n\n                if (!TokenUtils.movePrevToken(ctx)) {\n                    return;\n                }\n            }\n        }\n\n        // Parse a selector. Assumes ctx is pointing at the opening\n        // { that is after the selector name.\n        function _parseSelector(ctx) {\n            var selector = \"\";\n\n            // Skip over {\n            TokenUtils.movePrevToken(ctx);\n\n            while (true) {\n                if (ctx.token.type !== \"comment\") {\n                    // Stop once we've reached a {, }, or ;\n                    if (/[\\{\\}\\;]/.test(ctx.token.string)) {\n                        break;\n                    }\n\n                    // Stop once we've reached a <style ...> tag\n                    if (ctx.token.string === \"style\" && ctx.token.type === \"tag\") {\n                        // Remove everything up to end-of-tag from selector\n                        var eotIndex = selector.indexOf(\">\");\n                        if (eotIndex !== -1) {\n                            selector = selector.substring(eotIndex + 1);\n                        }\n                        break;\n                    }\n\n                    selector = ctx.token.string + selector;\n                }\n                if (!TokenUtils.movePrevToken(ctx)) {\n                    break;\n                }\n            }\n\n            return selector;\n        }\n\n        var skipPrevSibling = false,\n            state           = _getContextState(ctx);\n\n        // If the cursor is inside a non-whitespace token with \"block\" or \"top\" state, then it is inside a\n        // selector. The only exception is when it is immediately after the '{'.\n        if (isPreprocessorDoc && _hasNonWhitespace(ctx.token.string) && ctx.token.string !== \"{\" &&\n                (state.state === \"block\" || state.state === \"top\")) {\n            foundChars = true;\n        }\n\n        // scan backwards to see if the cursor is in a rule\n        do {\n            if (ctx.token.type !== \"comment\") {\n                if (ctx.token.string === \"}\") {\n                    if (isPreprocessorDoc) {\n                        if (state.state === \"top\") {\n                            break;\n                        }\n                        skipPrevSibling = true;\n                        // Skip past the entire preceding block until the matching \"{\"\n                        _skipToOpeningBracket(ctx, \"}\");\n                    } else {\n                        break;\n                    }\n                } else if (ctx.token.string === \"{\") {\n                    selector = _parseSelector(ctx);\n                    if (isPreprocessorDoc) {\n                        if (!skipPrevSibling && !/^\\s*@/.test(selector)) {\n                            selectorArray.unshift(selector);\n                        }\n                        if (skipPrevSibling) {\n                            skipPrevSibling = false;\n                        }\n                    } else {\n                        break;\n                    }\n                } else {\n                    if (!isPreprocessorDoc && _hasNonWhitespace(ctx.token.string)) {\n                        foundChars = true;\n                    }\n                    TokenUtils.movePrevToken(ctx);\n                }\n            } else {\n                TokenUtils.movePrevToken(ctx);\n            }\n        } while (!TokenUtils.isAtStart(ctx));\n\n        selector = _stripAtRules(selector);\n\n        // Reset the context to original scan position\n        ctx = TokenUtils.getInitialContext(cm, $.extend({}, pos));\n\n        // special case - we aren't in a selector and haven't found any chars,\n        // look at the next immediate token to see if it is non-whitespace.\n        // For preprocessor documents we need to move the cursor to next non-whitespace\n        // token so that we can collect the current selector if the cursor is inside it.\n        if ((!selector && !foundChars && !isPreprocessorDoc) ||\n                (isPreprocessorDoc && (ctx.token.string === \"\" || /\\s+/.test(ctx.token.string)))) {\n            if (TokenUtils.moveNextToken(ctx) && ctx.token.type !== \"comment\" && _hasNonWhitespace(ctx.token.string)) {\n                foundChars = true;\n                ctx = TokenUtils.getInitialContext(cm, $.extend({}, pos));\n            }\n        }\n\n        // At this point if we haven't found a selector, but have seen chars when\n        // scanning, assume we are in the middle of a selector. For a preprocessor\n        // document we also need to collect the current selector if the cursor is\n        // within the selector or whitespaces immediately before or after it.\n        if ((!selector || isPreprocessorDoc) && foundChars) {\n            // scan forward to see if the cursor is in a selector\n            while (true) {\n                if (ctx.token.type !== \"comment\") {\n                    if (ctx.token.string === \"{\") {\n                        selector = _parseSelector(ctx);\n                        if (isPreprocessorDoc && !/^\\s*@/.test(selector)) {\n                            selectorArray.push(selector);\n                        }\n                        break;\n                    } else if (ctx.token.string === \"}\" || ctx.token.string === \";\") {\n                        break;\n                    }\n                }\n                if (!TokenUtils.moveNextToken(ctx)) {\n                    break;\n                }\n            }\n        }\n\n        if (isPreprocessorDoc) {\n            return _getSelectorInFinalCSSForm(selectorArray);\n        }\n\n        return _stripAtRules(selector);\n    }\n\n    /**\n     * removes CSS comments from the content\n     * @param {!string} content to reduce\n     * @return {string} reduced content\n     */\n    function _removeComments(content) {\n        return content.replace(/\\/\\*(?:(?!\\*\\/)[\\s\\S])*\\*\\//g, \"\");\n    }\n\n    /**\n     * removes strings from the content\n     * @param {!string} content to reduce\n     * @return {string} reduced content\n     */\n    function _removeStrings(content) {\n        // First remove escaped quotes so we can balance unescaped quotes\n        // since JavaScript doesn't support negative lookbehind\n        var s = content.replace(/\\\\\\\"|\\\\\\'/g, \"\");\n\n        // Now remove strings\n        return s.replace(/\\\"(.*?)\\\"|\\'(.*?)\\'/g, \"\");\n    }\n\n    /**\n     * Reduces the style sheet by removing comments and strings\n     * so that the content can be parsed using a regular expression\n     * @param {!string} content to reduce\n     * @return {string} reduced content\n     */\n    function reduceStyleSheetForRegExParsing(content) {\n        return _removeStrings(_removeComments(content));\n    }\n\n    /**\n     * Extracts all named flow instances\n     * @param {!string} text to extract from\n     * @return {Array.<string>} array of unique flow names found in the content (empty if none)\n     */\n    function extractAllNamedFlows(text) {\n        var namedFlowRegEx = /(?:flow\\-(into|from)\\:\\s*)([\\w\\-]+)(?:\\s*;)/gi,\n            result = [],\n            names = {},\n            thisMatch;\n\n        // Reduce the content so that matches\n        // inside strings and comments are ignored\n        text = reduceStyleSheetForRegExParsing(text);\n\n        // Find the first match\n        thisMatch = namedFlowRegEx.exec(text);\n\n        // Iterate over the matches and add them to result\n        while (thisMatch) {\n            var thisName = thisMatch[2];\n\n            if (IGNORED_FLOW_NAMES.indexOf(thisName) === -1 && !names.hasOwnProperty(thisName)) {\n                names[thisName] = result.push(thisName);\n            }\n            thisMatch = namedFlowRegEx.exec(text);\n        }\n\n        return result;\n    }\n\n    /**\n     * Adds a new rule to the end of the given document, and returns the range of the added rule\n     * and the position of the cursor on the indented blank line within it. Note that the range will\n     * not include all the inserted text (we insert extra newlines before and after the rule).\n     * @param {Document} doc The document to insert the rule into.\n     * @param {string} selector The selector to use for the given rule.\n     * @param {boolean} useTabChar Whether to indent with a tab.\n     * @param {number} indentUnit If useTabChar is false, how many spaces to indent with.\n     * @return {{range: {from: {line: number, ch: number}, to: {line: number, ch: number}}, pos: {line: number, ch: number}}}\n     *     The range of the inserted rule and the location where the cursor should be placed.\n     */\n    function addRuleToDocument(doc, selector, useTabChar, indentUnit) {\n        var newRule = \"\\n\" + selector + \" {\\n\",\n            blankLineOffset;\n        if (useTabChar) {\n            newRule += \"\\t\";\n            blankLineOffset = 1;\n        } else {\n            var i;\n            for (i = 0; i < indentUnit; i++) {\n                newRule += \" \";\n            }\n            blankLineOffset = indentUnit;\n        }\n        newRule += \"\\n}\\n\";\n\n        var docLines = doc.getText().split(\"\\n\"),\n            lastDocLine = docLines.length - 1,\n            lastDocChar = docLines[docLines.length - 1].length;\n        doc.replaceRange(newRule, {line: lastDocLine, ch: lastDocChar});\n        return {\n            range: {\n                from: {line: lastDocLine + 1, ch: 0},\n                to: {line: lastDocLine + 3, ch: 1}\n            },\n            pos: {line: lastDocLine + 2, ch: blankLineOffset}\n        };\n    }\n\n    /**\n     *\n     * In the given rule array (as returned by `findMatchingRules()`), if multiple rules in a row\n     * refer to the same rule (because there were multiple matching selectors), eliminate the redundant\n     * rules. Also, always use the selector group if available instead of the original matching selector.\n     */\n    function consolidateRules(rules) {\n        var newRules = [], lastRule;\n        rules.forEach(function (rule) {\n            if (rule.selectorGroup) {\n                rule.name = rule.selectorGroup;\n            }\n            // Push the entry unless it refers to the same rule as the previous entry.\n            if (!(lastRule &&\n                     rule.document === lastRule.document &&\n                     rule.lineStart === lastRule.lineStart &&\n                     rule.lineEnd === lastRule.lineEnd &&\n                     rule.selectorGroup === lastRule.selectorGroup)) {\n                newRules.push(rule);\n            }\n            lastRule = rule;\n        });\n        return newRules;\n    }\n\n    /**\n     * Given a TextRange, extracts the selector(s) for the rule in the range and returns it.\n     * Assumes the range only contains one rule; if there's more than one, it will return the\n     * selector(s) for the first rule.\n     * @param {TextRange} range The range to extract the selector(s) from.\n     * @return {string} The selector(s) for the rule in the range.\n     */\n    function getRangeSelectors(range) {\n        // There's currently no immediate way to access a given line in a Document, because it's just\n        // stored as a string. Eventually, we should have Documents cache the lines in the document\n        // as well, or make them use CodeMirror documents which do the same thing.\n        var i, startIndex = 0, endIndex, text = range.document.getText();\n        for (i = 0; i < range.startLine; i++) {\n            startIndex = text.indexOf(\"\\n\", startIndex) + 1;\n        }\n        endIndex = startIndex;\n        // Go one line past the end line. We'll extract text up to but not including the last newline.\n        for (i = range.startLine + 1; i <= range.endLine + 1; i++) {\n            endIndex = text.indexOf(\"\\n\", endIndex) + 1;\n        }\n        var allSelectors = extractAllSelectors(text.substring(startIndex, endIndex));\n\n        // There should only be one rule in the range, and if there are multiple selectors for\n        // the first rule, they'll all be recorded in the \"selectorGroup\" for the first selector,\n        // so we only need to look at the first one.\n        return (allSelectors.length ? allSelectors[0].selectorGroup || allSelectors[0].selector : \"\");\n    }\n\n    exports._findAllMatchingSelectorsInText = _findAllMatchingSelectorsInText; // For testing only\n    exports.findMatchingRules = findMatchingRules;\n    exports.extractAllSelectors = extractAllSelectors;\n    exports.extractAllNamedFlows = extractAllNamedFlows;\n    exports.findSelectorAtDocumentPos = findSelectorAtDocumentPos;\n    exports.reduceStyleSheetForRegExParsing = reduceStyleSheetForRegExParsing;\n    exports.addRuleToDocument = addRuleToDocument;\n    exports.consolidateRules = consolidateRules;\n    exports.getRangeSelectors = getRangeSelectors;\n    exports.getCompleteSelectors = getCompleteSelectors;\n    exports.isCSSPreprocessorFile = isCSSPreprocessorFile;\n\n    exports.SELECTOR = SELECTOR;\n    exports.PROP_NAME = PROP_NAME;\n    exports.PROP_VALUE = PROP_VALUE;\n    exports.IMPORT_URL = IMPORT_URL;\n\n    exports.getInfoAtPos = getInfoAtPos;\n\n    // The createInfo is really only for the unit tests so they can make the same\n    // structure to compare results with.\n    exports.createInfo = createInfo;\n});\n"
  },
  {
    "path": "src/language/CodeInspection.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Manages linters and other code inspections on a per-language basis. Provides a UI and status indicator for\n * the resulting errors/warnings.\n *\n * Currently, inspection providers are only invoked on the current file and only when it is opened, switched to,\n * or saved. But in the future, inspectors may be invoked as part of a global scan, at intervals while typing, etc.\n * Currently, results are only displayed in a bottom panel list and in a status bar icon. But in the future,\n * results may also be displayed inline in the editor (as gutter markers, squiggly underlines, etc.).\n * In the future, support may also be added for error/warning providers that cannot process a single file at a time\n * (e.g. a full-project compiler).\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    // Load dependent modules\n    var Commands                = require(\"command/Commands\"),\n        WorkspaceManager        = require(\"view/WorkspaceManager\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        MainViewManager         = require(\"view/MainViewManager\"),\n        LanguageManager         = require(\"language/LanguageManager\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        Strings                 = require(\"strings\"),\n        StringUtils             = require(\"utils/StringUtils\"),\n        AppInit                 = require(\"utils/AppInit\"),\n        Resizer                 = require(\"utils/Resizer\"),\n        StatusBar               = require(\"widgets/StatusBar\"),\n        Async                   = require(\"utils/Async\"),\n        PanelTemplate           = require(\"text!htmlContent/problems-panel.html\"),\n        ResultsTemplate         = require(\"text!htmlContent/problems-panel-table.html\"),\n        Mustache                = require(\"thirdparty/mustache/mustache\");\n\n    var INDICATOR_ID = \"status-inspection\";\n\n    /** Values for problem's 'type' property */\n    var Type = {\n        /** Unambiguous error, such as a syntax error */\n        ERROR: \"problem_type_error\",\n        /** Maintainability issue, probable error / bad smell, etc. */\n        WARNING: \"problem_type_warning\",\n        /** Inspector unable to continue, code too complex for static analysis, etc. Not counted in error/warning tally. */\n        META: \"problem_type_meta\"\n    };\n\n    /**\n     * Constants for the preferences defined in this file.\n     */\n    var PREF_ENABLED            = \"enabled\",\n        PREF_COLLAPSED          = \"collapsed\",\n        PREF_ASYNC_TIMEOUT      = \"asyncTimeout\",\n        PREF_PREFER_PROVIDERS   = \"prefer\",\n        PREF_PREFERRED_ONLY     = \"usePreferredOnly\";\n\n    var prefs = PreferencesManager.getExtensionPrefs(\"linting\");\n\n    /**\n     * When disabled, the errors panel is closed and the status bar icon is grayed out.\n     * Takes precedence over _collapsed.\n     * @private\n     * @type {boolean}\n     */\n    var _enabled = false;\n\n    /**\n     * When collapsed, the errors panel is closed but the status bar icon is kept up to date.\n     * @private\n     * @type {boolean}\n     */\n    var _collapsed = false;\n\n    /**\n     * @private\n     * @type {$.Element}\n     */\n    var $problemsPanel;\n\n    /**\n     * @private\n     * @type {$.Element}\n     */\n    var $problemsPanelTable;\n\n    /**\n     * @private\n     * @type {boolean}\n     */\n    var _gotoEnabled = false;\n\n    /**\n     * @private\n     * @type {{languageId:string, Array.<{name:string, scanFileAsync:?function(string, string):!{$.Promise}, scanFile:?function(string, string):Object}>}}\n     */\n    var _providers = {};\n\n    /**\n     * @private\n     * @type {boolean}\n     */\n    var _hasErrors;\n\n    /**\n     * Promise of the returned by the last call to inspectFile or null if linting is disabled. Used to prevent any stale promises\n     * to cause updates of the UI.\n     *\n     * @private\n     * @type {$.Promise}\n     */\n    var _currentPromise = null;\n\n    /**\n     * Enable or disable the \"Go to First Error\" command\n     * @param {boolean} gotoEnabled Whether it is enabled.\n     */\n    function setGotoEnabled(gotoEnabled) {\n        CommandManager.get(Commands.NAVIGATE_GOTO_FIRST_PROBLEM).setEnabled(gotoEnabled);\n        _gotoEnabled = gotoEnabled;\n    }\n\n    function _unregisterAll() {\n        _providers = {};\n    }\n\n    /**\n     * Returns a list of provider for given file path, if available.\n     * Decision is made depending on the file extension.\n     *\n     * @param {!string} filePath\n     * @return {Array.<{name:string, scanFileAsync:?function(string, string):!{$.Promise}, scanFile:?function(string, string):?{errors:!Array, aborted:boolean}}>}\n     */\n    function getProvidersForPath(filePath) {\n        var language            = LanguageManager.getLanguageForPath(filePath).getId(),\n            context             = PreferencesManager._buildContext(filePath, language),\n            installedProviders  = getProvidersForLanguageId(language),\n            preferredProviders,\n\n            prefPreferredProviderNames  = prefs.get(PREF_PREFER_PROVIDERS, context),\n            prefPreferredOnly           = prefs.get(PREF_PREFERRED_ONLY, context),\n\n            providers;\n\n        if (prefPreferredProviderNames && prefPreferredProviderNames.length) {\n            if (typeof prefPreferredProviderNames === \"string\") {\n                prefPreferredProviderNames = [prefPreferredProviderNames];\n            }\n            preferredProviders = prefPreferredProviderNames.reduce(function (result, key) {\n                var provider = _.find(installedProviders, {name: key});\n                if (provider) {\n                    result.push(provider);\n                }\n                return result;\n            }, []);\n            if (prefPreferredOnly) {\n                providers = preferredProviders;\n            } else {\n                providers = _.union(preferredProviders, installedProviders);\n            }\n        } else {\n            providers = installedProviders;\n        }\n        return providers;\n    }\n\n    /**\n     * Returns an array of the IDs of providers registered for a specific language\n     *\n     * @param {!string} languageId\n     * @return {Array.<string>} Names of registered providers.\n     */\n    function getProviderIDsForLanguage(languageId) {\n        if (!_providers[languageId]) {\n            return [];\n        }\n        return _providers[languageId].map(function (provider) {\n            return provider.name;\n        });\n    }\n\n    /**\n     * Runs a file inspection over passed file. Uses the given list of providers if specified, otherwise uses\n     * the set of providers that are registered for the file's language.\n     * This method doesn't update the Brackets UI, just provides inspection results.\n     * These results will reflect any unsaved changes present in the file if currently open.\n     *\n     * The Promise yields an array of provider-result pair objects (the result is the return value of the\n     * provider's scanFile() - see register() for details). The result object may be null if there were no\n     * errors from that provider.\n     * If there are no providers registered for this file, the Promise yields null instead.\n     *\n     * @param {!File} file File that will be inspected for errors.\n     * @param {?Array.<{name:string, scanFileAsync:?function(string, string):!{$.Promise}, scanFile:?function(string, string):?{errors:!Array, aborted:boolean}}>} providerList\n     * @return {$.Promise} a jQuery promise that will be resolved with ?Array.<{provider:Object, result: ?{errors:!Array, aborted:boolean}}>\n     */\n    function inspectFile(file, providerList) {\n        var response = new $.Deferred(),\n            results = [];\n\n        providerList = providerList || getProvidersForPath(file.fullPath);\n\n        if (!providerList.length) {\n            response.resolve(null);\n            return response.promise();\n        }\n\n        DocumentManager.getDocumentText(file)\n            .done(function (fileText) {\n                var perfTimerInspector = PerfUtils.markStart(\"CodeInspection:\\t\" + file.fullPath),\n                    masterPromise;\n\n                masterPromise = Async.doInParallel(providerList, function (provider) {\n                    var perfTimerProvider = PerfUtils.markStart(\"CodeInspection '\" + provider.name + \"':\\t\" + file.fullPath),\n                        runPromise = new $.Deferred();\n\n                    runPromise.done(function (scanResult) {\n                        results.push({provider: provider, result: scanResult});\n                    });\n\n                    if (provider.scanFileAsync) {\n                        window.setTimeout(function () {\n                            // timeout error\n                            var errTimeout = {\n                                pos: { line: -1, col: 0},\n                                message: StringUtils.format(Strings.LINTER_TIMED_OUT, provider.name, prefs.get(PREF_ASYNC_TIMEOUT)),\n                                type: Type.ERROR\n                            };\n                            runPromise.resolve({errors: [errTimeout]});\n                        }, prefs.get(PREF_ASYNC_TIMEOUT));\n                        provider.scanFileAsync(fileText, file.fullPath)\n                            .done(function (scanResult) {\n                                PerfUtils.addMeasurement(perfTimerProvider);\n                                runPromise.resolve(scanResult);\n                            })\n                            .fail(function (err) {\n                                PerfUtils.finalizeMeasurement(perfTimerProvider);\n                                var errError = {\n                                    pos: {line: -1, col: 0},\n                                    message: StringUtils.format(Strings.LINTER_FAILED, provider.name, err),\n                                    type: Type.ERROR\n                                };\n                                console.error(\"[CodeInspection] Provider \" + provider.name + \" (async) failed: \" + err);\n                                runPromise.resolve({errors: [errError]});\n                            });\n                    } else {\n                        try {\n                            var scanResult = provider.scanFile(fileText, file.fullPath);\n                            PerfUtils.addMeasurement(perfTimerProvider);\n                            runPromise.resolve(scanResult);\n                        } catch (err) {\n                            PerfUtils.finalizeMeasurement(perfTimerProvider);\n                            var errError = {\n                                pos: {line: -1, col: 0},\n                                message: StringUtils.format(Strings.LINTER_FAILED, provider.name, err),\n                                type: Type.ERROR\n                            };\n                            console.error(\"[CodeInspection] Provider \" + provider.name + \" (sync) threw an error: \" + err);\n                            runPromise.resolve({errors: [errError]});\n                        }\n                    }\n                    return runPromise.promise();\n\n                }, false);\n\n                masterPromise.then(function () {\n                    // sync async may have pushed results in different order, restore the original order\n                    results.sort(function (a, b) {\n                        return providerList.indexOf(a.provider) - providerList.indexOf(b.provider);\n                    });\n                    PerfUtils.addMeasurement(perfTimerInspector);\n                    response.resolve(results);\n                });\n\n            })\n            .fail(function (err) {\n                console.error(\"[CodeInspection] Could not read file for inspection: \" + file.fullPath);\n                response.reject(err);\n            });\n\n        return response.promise();\n    }\n\n    /**\n     * Update the title of the problem panel and the tooltip of the status bar icon. The title and the tooltip will\n     * change based on the number of problems reported and how many provider reported problems.\n     *\n     * @param {Number} numProblems - total number of problems across all providers\n     * @param {Array.<{name:string, scanFileAsync:?function(string, string):!{$.Promise}, scanFile:?function(string, string):Object}>} providersReportingProblems - providers that reported problems\n     * @param {boolean} aborted - true if any provider returned a result with the 'aborted' flag set\n     */\n    function updatePanelTitleAndStatusBar(numProblems, providersReportingProblems, aborted) {\n        var message, tooltip;\n\n        if (providersReportingProblems.length === 1) {\n            // don't show a header if there is only one provider available for this file type\n            $problemsPanelTable.find(\".inspector-section\").hide();\n            $problemsPanelTable.find(\"tr\").removeClass(\"forced-hidden\");\n\n            if (numProblems === 1 && !aborted) {\n                message = StringUtils.format(Strings.SINGLE_ERROR, providersReportingProblems[0].name);\n            } else {\n                if (aborted) {\n                    numProblems += \"+\";\n                }\n\n                message = StringUtils.format(Strings.MULTIPLE_ERRORS, providersReportingProblems[0].name, numProblems);\n            }\n        } else if (providersReportingProblems.length > 1) {\n            $problemsPanelTable.find(\".inspector-section\").show();\n\n            if (aborted) {\n                numProblems += \"+\";\n            }\n\n            message = StringUtils.format(Strings.ERRORS_PANEL_TITLE_MULTIPLE, numProblems);\n        } else {\n            return;\n        }\n\n        $problemsPanel.find(\".title\").text(message);\n        tooltip = StringUtils.format(Strings.STATUSBAR_CODE_INSPECTION_TOOLTIP, message);\n        StatusBar.updateIndicator(INDICATOR_ID, true, \"inspection-errors\", tooltip);\n    }\n\n    /**\n     * Run inspector applicable to current document. Updates status bar indicator and refreshes error list in\n     * bottom panel. Does not run if inspection is disabled or if a providerName is given and does not\n     * match the current doc's provider name.\n     *\n     * @param {?string} providerName name of the provider that is requesting a run\n     */\n    function run() {\n        if (!_enabled) {\n            _hasErrors = false;\n            _currentPromise = null;\n            Resizer.hide($problemsPanel);\n            StatusBar.updateIndicator(INDICATOR_ID, true, \"inspection-disabled\", Strings.LINT_DISABLED);\n            setGotoEnabled(false);\n            return;\n        }\n\n        var currentDoc = DocumentManager.getCurrentDocument(),\n            providerList = currentDoc && getProvidersForPath(currentDoc.file.fullPath);\n\n        if (providerList && providerList.length) {\n            var numProblems = 0;\n            var aborted = false;\n            var allErrors = [];\n            var html;\n            var providersReportingProblems = [];\n\n            // run all the providers registered for this file type\n            (_currentPromise = inspectFile(currentDoc.file, providerList)).then(function (results) {\n                // check if promise has not changed while inspectFile was running\n                if (this !== _currentPromise) {\n                    return;\n                }\n\n                // how many errors in total?\n                var errors = results.reduce(function (a, item) { return a + (item.result ? item.result.errors.length : 0); }, 0);\n\n                _hasErrors = Boolean(errors);\n\n                if (!errors) {\n                    Resizer.hide($problemsPanel);\n\n                    var message = Strings.NO_ERRORS_MULTIPLE_PROVIDER;\n                    if (providerList.length === 1) {\n                        message = StringUtils.format(Strings.NO_ERRORS, providerList[0].name);\n                    }\n\n                    StatusBar.updateIndicator(INDICATOR_ID, true, \"inspection-valid\", message);\n\n                    setGotoEnabled(false);\n                    return;\n                }\n\n                var perfTimerDOM = PerfUtils.markStart(\"ProblemsPanel render:\\t\" + currentDoc.file.fullPath);\n\n                // Augment error objects with additional fields needed by Mustache template\n                results.forEach(function (inspectionResult) {\n                    var provider = inspectionResult.provider;\n                    var isExpanded = prefs.get(provider.name + \".collapsed\") !== false;\n\n                    if (inspectionResult.result) {\n                        inspectionResult.result.errors.forEach(function (error) {\n                            // some inspectors don't always provide a line number or report a negative line number\n                            if (!isNaN(error.pos.line) &&\n                                    (error.pos.line + 1) > 0 &&\n                                    (error.codeSnippet = currentDoc.getLine(error.pos.line)) !== undefined) {\n                                error.friendlyLine = error.pos.line + 1;\n                                error.codeSnippet = error.codeSnippet.substr(0, 175);  // limit snippet width\n                            }\n\n                            if (error.type !== Type.META) {\n                                numProblems++;\n                            }\n\n                            // Hide the errors when the provider is collapsed.\n                            error.display = isExpanded ? \"\" : \"forced-hidden\";\n                        });\n\n                        // if the code inspector was unable to process the whole file, we keep track to show a different status\n                        if (inspectionResult.result.aborted) {\n                            aborted = true;\n                        }\n\n                        if (inspectionResult.result.errors.length) {\n                            allErrors.push({\n                                isExpanded:   isExpanded,\n                                providerName: provider.name,\n                                results:      inspectionResult.result.errors\n                            });\n\n                            providersReportingProblems.push(provider);\n                        }\n                    }\n                });\n\n                // Update results table\n                html = Mustache.render(ResultsTemplate, {reportList: allErrors});\n\n                $problemsPanelTable\n                    .empty()\n                    .append(html)\n                    .scrollTop(0);  // otherwise scroll pos from previous contents is remembered\n\n                if (!_collapsed) {\n                    Resizer.show($problemsPanel);\n                }\n\n                updatePanelTitleAndStatusBar(numProblems, providersReportingProblems, aborted);\n                setGotoEnabled(true);\n\n                PerfUtils.addMeasurement(perfTimerDOM);\n            });\n\n        } else {\n            // No provider for current file\n            _hasErrors = false;\n            _currentPromise = null;\n            Resizer.hide($problemsPanel);\n            var language = currentDoc && LanguageManager.getLanguageForPath(currentDoc.file.fullPath);\n            if (language) {\n                StatusBar.updateIndicator(INDICATOR_ID, true, \"inspection-disabled\", StringUtils.format(Strings.NO_LINT_AVAILABLE, language.getName()));\n            } else {\n                StatusBar.updateIndicator(INDICATOR_ID, true, \"inspection-disabled\", Strings.NOTHING_TO_LINT);\n            }\n            setGotoEnabled(false);\n        }\n    }\n\n    /**\n     * The provider is passed the text of the file and its fullPath. Providers should not assume\n     * that the file is open (i.e. DocumentManager.getOpenDocumentForPath() may return null) or\n     * that the file on disk matches the text given (file may have unsaved changes).\n     *\n     * Registering any provider for the \"javascript\" language automatically unregisters the built-in\n     * Brackets JSLint provider. This is a temporary convenience until UI exists for disabling\n     * registered providers.\n     *\n     * Providers implement scanFile() if results are available synchronously, or scanFileAsync() if results\n     * may require an async wait (if both are implemented, scanFile() is ignored). scanFileAsync() returns\n     * a {$.Promise} object resolved with the same type of value as scanFile() is expected to return.\n     * Rejecting the promise is treated as an internal error in the provider.\n     *\n     * @param {string} languageId\n     * @param {{name:string, scanFileAsync:?function(string, string):!{$.Promise},\n     *         scanFile:?function(string, string):?{errors:!Array, aborted:boolean}}} provider\n     *\n     * Each error is: { pos:{line,ch}, endPos:?{line,ch}, message:string, type:?Type }\n     * If type is unspecified, Type.WARNING is assumed.\n     * If no errors found, return either null or an object with a zero-length `errors` array.\n     */\n    function register(languageId, provider) {\n        if (!_providers[languageId]) {\n            _providers[languageId] = [];\n        } else {\n            // Check if provider with same name exists for the given language\n            // If yes, remove the provider before inserting the most recently loaded one\n            var indexOfProvider = _.findIndex(_providers[languageId], function(entry) { return entry.name === provider.name; });\n            if (indexOfProvider !== -1) {\n                _providers[languageId].splice(indexOfProvider, 1);\n            }\n        }\n\n        _providers[languageId].push(provider);\n\n        run();  // in case a file of this type is open currently\n    }\n\n    /**\n     * Returns a list of providers registered for given languageId through register function\n     */\n    function getProvidersForLanguageId(languageId) {\n        var result = [];\n        if (_providers[languageId]) {\n            result = result.concat(_providers[languageId]);\n        }\n        if (_providers['*']) {\n            result = result.concat(_providers['*']);\n        }\n        return result;\n    }\n\n    /**\n     * Update DocumentManager listeners.\n     */\n    function updateListeners() {\n        if (_enabled) {\n            // register our event listeners\n            MainViewManager\n                .on(\"currentFileChange.codeInspection\", function () {\n                    run();\n                });\n            DocumentManager\n                .on(\"currentDocumentLanguageChanged.codeInspection\", function () {\n                    run();\n                })\n                .on(\"documentSaved.codeInspection documentRefreshed.codeInspection\", function (event, document) {\n                    if (document === DocumentManager.getCurrentDocument()) {\n                        run();\n                    }\n                });\n        } else {\n            DocumentManager.off(\".codeInspection\");\n            MainViewManager.off(\".codeInspection\");\n        }\n    }\n\n    /**\n     * Enable or disable all inspection.\n     * @param {?boolean} enabled Enabled state. If omitted, the state is toggled.\n     * @param {?boolean} doNotSave true if the preference should not be saved to user settings. This is generally for events triggered by project-level settings.\n     */\n    function toggleEnabled(enabled, doNotSave) {\n        if (enabled === undefined) {\n            enabled = !_enabled;\n        }\n\n        // Take no action when there is no change.\n        if (enabled === _enabled) {\n            return;\n        }\n\n        _enabled = enabled;\n\n        CommandManager.get(Commands.VIEW_TOGGLE_INSPECTION).setChecked(_enabled);\n        updateListeners();\n        if (!doNotSave) {\n            prefs.set(PREF_ENABLED, _enabled);\n            prefs.save();\n        }\n\n        // run immediately\n        run();\n    }\n\n    /**\n     * Toggle the collapsed state for the panel. This explicitly collapses the panel (as opposed to\n     * the auto collapse due to files with no errors & filetypes with no provider). When explicitly\n     * collapsed, the panel will not reopen automatically on switch files or save.\n     *\n     * @param {?boolean} collapsed Collapsed state. If omitted, the state is toggled.\n     * @param {?boolean} doNotSave true if the preference should not be saved to user settings. This is generally for events triggered by project-level settings.\n     */\n    function toggleCollapsed(collapsed, doNotSave) {\n        if (collapsed === undefined) {\n            collapsed = !_collapsed;\n        }\n\n        if (collapsed === _collapsed) {\n            return;\n        }\n\n        _collapsed = collapsed;\n        if (!doNotSave) {\n            prefs.set(PREF_COLLAPSED, _collapsed);\n            prefs.save();\n        }\n\n        if (_collapsed) {\n            Resizer.hide($problemsPanel);\n        } else {\n            if (_hasErrors) {\n                Resizer.show($problemsPanel);\n            }\n        }\n    }\n\n    /** Command to go to the first Problem */\n    function handleGotoFirstProblem() {\n        run();\n        if (_gotoEnabled) {\n            $problemsPanel.find(\"tr:not(.inspector-section)\").first().trigger(\"click\");\n        }\n    }\n\n    // Register command handlers\n    CommandManager.register(Strings.CMD_VIEW_TOGGLE_INSPECTION, Commands.VIEW_TOGGLE_INSPECTION,        toggleEnabled);\n    CommandManager.register(Strings.CMD_GOTO_FIRST_PROBLEM,     Commands.NAVIGATE_GOTO_FIRST_PROBLEM,   handleGotoFirstProblem);\n\n    // Register preferences\n    prefs.definePreference(PREF_ENABLED, \"boolean\", brackets.config[\"linting.enabled_by_default\"], {\n        description: Strings.DESCRIPTION_LINTING_ENABLED\n    })\n        .on(\"change\", function (e, data) {\n            toggleEnabled(prefs.get(PREF_ENABLED), true);\n        });\n\n    prefs.definePreference(PREF_COLLAPSED, \"boolean\", false, {\n        description: Strings.DESCRIPTION_LINTING_COLLAPSED\n    })\n        .on(\"change\", function (e, data) {\n            toggleCollapsed(prefs.get(PREF_COLLAPSED), true);\n        });\n\n    prefs.definePreference(PREF_ASYNC_TIMEOUT, \"number\", 10000, {\n        description: Strings.DESCRIPTION_ASYNC_TIMEOUT\n    });\n\n    prefs.definePreference(PREF_PREFER_PROVIDERS, \"array\", [], {\n        description: Strings.DESCRIPTION_LINTING_PREFER,\n        valueType: \"string\"\n    });\n\n    prefs.definePreference(PREF_PREFERRED_ONLY, \"boolean\", false, {\n        description: Strings.DESCRIPTION_USE_PREFERED_ONLY\n    });\n\n    // Initialize items dependent on HTML DOM\n    AppInit.htmlReady(function () {\n        // Create bottom panel to list error details\n        var panelHtml = Mustache.render(PanelTemplate, Strings);\n        WorkspaceManager.createBottomPanel(\"errors\", $(panelHtml), 100);\n        $problemsPanel = $(\"#problems-panel\");\n\n        var $selectedRow;\n        $problemsPanelTable = $problemsPanel.find(\".table-container\")\n            .on(\"click\", \"tr\", function (e) {\n                if ($selectedRow) {\n                    $selectedRow.removeClass(\"selected\");\n                }\n\n                $selectedRow  = $(e.currentTarget);\n                $selectedRow.addClass(\"selected\");\n\n                // This is a inspector title row, expand/collapse on click\n                if ($selectedRow.hasClass(\"inspector-section\")) {\n                    var $triangle = $(\".disclosure-triangle\", $selectedRow);\n                    var isExpanded = $triangle.hasClass(\"expanded\");\n\n                    // Clicking the inspector title section header collapses/expands result rows\n                    if (isExpanded) {\n                        $selectedRow.nextUntil(\".inspector-section\").addClass(\"forced-hidden\");\n                    } else {\n                        $selectedRow.nextUntil(\".inspector-section\").removeClass(\"forced-hidden\");\n                    }\n                    $triangle.toggleClass(\"expanded\");\n\n                    var providerName = $selectedRow.find(\"input[type='hidden']\").val();\n                    prefs.set(providerName + \".collapsed\", !isExpanded);\n                    prefs.save();\n                } else {\n                    // This is a problem marker row, show the result on click\n                    // Grab the required position data\n                    var lineTd    = $selectedRow.find(\".line-number\");\n                    var line      = parseInt(lineTd.text(), 10) - 1;  // convert friendlyLine back to pos.line\n                    // if there is no line number available, don't do anything\n                    if (!isNaN(line)) {\n                        var character = lineTd.data(\"character\");\n\n                        var editor = EditorManager.getCurrentFullEditor();\n                        editor.setCursorPos(line, character, true);\n                        MainViewManager.focusActivePane();\n                    }\n                }\n            });\n\n        $(\"#problems-panel .close\").click(function () {\n            toggleCollapsed(true);\n        });\n\n        // Status bar indicator - icon & tooltip updated by run()\n        var statusIconHtml = Mustache.render(\"<div id=\\\"status-inspection\\\">&nbsp;</div>\", Strings);\n        StatusBar.addIndicator(INDICATOR_ID, $(statusIconHtml), true, \"\", \"\", \"status-indent\");\n\n        $(\"#status-inspection\").click(function () {\n            // Clicking indicator toggles error panel, if any errors in current file\n            if (_hasErrors) {\n                toggleCollapsed();\n            }\n        });\n\n        // Set initial UI state\n        toggleEnabled(prefs.get(PREF_ENABLED), true);\n        toggleCollapsed(prefs.get(PREF_COLLAPSED), true);\n    });\n\n    // Testing\n    exports._unregisterAll          = _unregisterAll;\n    exports._PREF_ASYNC_TIMEOUT     = PREF_ASYNC_TIMEOUT;\n    exports._PREF_PREFER_PROVIDERS  = PREF_PREFER_PROVIDERS;\n    exports._PREF_PREFERRED_ONLY    = PREF_PREFERRED_ONLY;\n\n    // Public API\n    exports.register                    = register;\n    exports.Type                        = Type;\n    exports.toggleEnabled               = toggleEnabled;\n    exports.inspectFile                 = inspectFile;\n    exports.requestRun                  = run;\n    exports.getProvidersForPath         = getProvidersForPath;\n    exports.getProviderIDsForLanguage   = getProviderIDsForLanguage;\n});\n"
  },
  {
    "path": "src/language/HTMLDOMDiff.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: HTML Instrumentation*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * @private\n     *\n     * Determines the changes made to attributes and generates edits for those changes.\n     *\n     * @param {SimpleNode} oldNode node from old tree\n     * @param {SimpleNode} newNode node from new tree\n     * @return {Array.<Object>} list of edits to mutate attributes from the old node to the new\n     */\n    function generateAttributeEdits(oldNode, newNode) {\n        // shallow copy the old attributes object so that we can modify it\n        var oldAttributes = $.extend({}, oldNode.attributes),\n            newAttributes = newNode.attributes,\n            edits = [];\n\n        Object.keys(newAttributes).forEach(function (attributeName) {\n            if (oldAttributes[attributeName] !== newAttributes[attributeName]) {\n                var type = oldAttributes.hasOwnProperty(attributeName) ? \"attrChange\" : \"attrAdd\";\n                edits.push({\n                    type: type,\n                    tagID: oldNode.tagID,\n                    attribute: attributeName,\n                    value: newAttributes[attributeName]\n                });\n            }\n            delete oldAttributes[attributeName];\n        });\n\n        Object.keys(oldAttributes).forEach(function (attributeName) {\n            edits.push({\n                type: \"attrDelete\",\n                tagID: oldNode.tagID,\n                attribute: attributeName\n            });\n        });\n\n        return edits;\n    }\n\n    /**\n     * @private\n     *\n     * Retrieve the parent tag ID of a SimpleDOM node.\n     *\n     * @param {Object} node SimpleDOM node for which to look up parent ID\n     * @return {int?} ID or null if there is no parent\n     */\n    function getParentID(node) {\n        return node.parent && node.parent.tagID;\n    }\n\n    /**\n     * @private\n     *\n     * When the main loop (see below) determines that something has changed with\n     * an element's immediate children, it calls this function to create edit\n     * operations for those changes.\n     *\n     * This adds to the edit list in place and does not return anything.\n     *\n     * @param {?Object} oldParent SimpleDOM node for the previous state of this element, null/undefined if the element is new\n     * @param {Object} newParent SimpleDOM node for the current state of the element\n     */\n    var generateChildEdits = function (oldParent, oldNodeMap, newParent, newNodeMap) {\n        /*jslint continue: true */\n\n        var newIndex = 0,\n            oldIndex = 0,\n            newChildren = newParent.children,\n            oldChildren = oldParent ? oldParent.children : [],\n            newChild,\n            oldChild,\n            newEdits = [],\n            newEdit,\n            textAfterID,\n            edits = [],\n            moves = [],\n            newElements = [];\n\n        /**\n         * We initially put new edit objects into the `newEdits` array so that we\n         * can fix them up with proper positioning information. This function is\n         * responsible for doing that fixup.\n         *\n         * The `beforeID` that appears in many edits tells the browser to make the\n         * change before the element with the given ID. In other words, an\n         * elementInsert with a `beforeID` of 32 would result in something like\n         * `parentElement.insertBefore(newChildElement, _queryBracketsID(32))`\n         *\n         * Many new edits are captured in the `newEdits` array so that a suitable\n         * `beforeID` can be added to them before they are added to the main edits\n         * list. This function sets the `beforeID` on any pending edits and adds\n         * them to the main list.\n         *\n         * If this item is not being deleted, then it will be used as the `afterID`\n         * for text edits that follow.\n         *\n         * @param {int} beforeID ID to set on the pending edits\n         * @param {boolean} isBeingDeleted true if the given item is being deleted. If so,\n         *     we can't use it as the `afterID` for future edits--whatever previous item\n         *     was set as the `textAfterID` is still okay.\n         */\n        var finalizeNewEdits = function (beforeID, isBeingDeleted) {\n            newEdits.forEach(function (edit) {\n                // elementDeletes don't need any positioning information\n                if (edit.type !== \"elementDelete\") {\n                    edit.beforeID = beforeID;\n                }\n            });\n            edits.push.apply(edits, newEdits);\n            newEdits = [];\n\n            // If the item we made this set of edits relative to\n            // is being deleted, we can't use it as the afterID for future\n            // edits. It's okay to just keep the previous afterID, since\n            // this node will no longer be in the tree by the time we get\n            // to any future edit that needs an afterID.\n            if (!isBeingDeleted) {\n                textAfterID = beforeID;\n            }\n        };\n\n        /**\n         * If the current element was not in the old DOM, then we will create\n         * an elementInsert edit for it.\n         *\n         * If the element was in the old DOM, this will return false and the\n         * main loop will either spot this element later in the child list\n         * or the element has been moved.\n         *\n         * @return {boolean} true if an elementInsert was created\n         */\n        var addElementInsert = function () {\n            if (!oldNodeMap[newChild.tagID]) {\n                newEdit = {\n                    type: \"elementInsert\",\n                    tag: newChild.tag,\n                    tagID: newChild.tagID,\n                    parentID: newChild.parent.tagID,\n                    attributes: newChild.attributes\n                };\n\n                newEdits.push(newEdit);\n\n                // This newly inserted node needs to have edits generated for its\n                // children, so we add it to the queue.\n                newElements.push(newChild);\n\n                // A textInsert edit that follows this elementInsert should use\n                // this element's ID.\n                textAfterID = newChild.tagID;\n\n                // new element means we need to move on to compare the next\n                // of the current tree with the one from the old tree that we\n                // just compared\n                newIndex++;\n                return true;\n            }\n            return false;\n        };\n\n        /**\n         * If the old element that we're looking at does not appear in the new\n         * DOM, that means it was deleted and we'll create an elementDelete edit.\n         *\n         * If the element is in the new DOM, then this will return false and\n         * the main loop with either spot this node later on or the element\n         * has been moved.\n         *\n         * @return {boolean} true if elementDelete was generated\n         */\n        var addElementDelete = function () {\n            if (!newNodeMap[oldChild.tagID]) {\n                // We can finalize existing edits relative to this node *before* it's\n                // deleted.\n                finalizeNewEdits(oldChild.tagID, true);\n\n                newEdit = {\n                    type: \"elementDelete\",\n                    tagID: oldChild.tagID\n                };\n                newEdits.push(newEdit);\n\n                // deleted element means we need to move on to compare the next\n                // of the old tree with the one from the current tree that we\n                // just compared\n                oldIndex++;\n                return true;\n            }\n            return false;\n        };\n\n        /**\n         * Adds a textInsert edit for a newly created text node.\n         */\n        var addTextInsert = function () {\n            newEdit = {\n                type: \"textInsert\",\n                content: newChild.content,\n                parentID: newChild.parent.tagID\n            };\n\n            // text changes will generally have afterID and beforeID, but we make\n            // special note if it's the first child.\n            if (textAfterID) {\n                newEdit.afterID = textAfterID;\n            } else {\n                newEdit.firstChild = true;\n            }\n            newEdits.push(newEdit);\n\n            // The text node is in the new tree, so we move to the next new tree item\n            newIndex++;\n        };\n\n        /**\n         * Finds the previous child of the new tree.\n         *\n         * @return {?Object} previous child or null if there wasn't one\n         */\n        var prevNode = function () {\n            if (newIndex > 0) {\n                return newParent.children[newIndex - 1];\n            }\n            return null;\n        };\n\n        /**\n         * Adds a textDelete edit for text node that is not in the new tree.\n         * Note that we actually create a textReplace rather than a textDelete\n         * if the previous node in current tree was a text node. We do this because\n         * text nodes are not individually addressable and a delete event would\n         * end up clearing out both that previous text node that we want to keep\n         * and this text node that we want to eliminate. Instead, we just log\n         * a textReplace which will result in the deletion of this node and\n         * the maintaining of the old content.\n         */\n        var addTextDelete = function () {\n            var prev = prevNode();\n            if (prev && !prev.children) {\n                newEdit = {\n                    type: \"textReplace\",\n                    content: prev.content\n                };\n            } else {\n                newEdit = {\n                    type: \"textDelete\"\n                };\n            }\n\n            // When elements are deleted or moved from the old set of children, you\n            // can end up with multiple text nodes in a row. A single textReplace edit\n            // will take care of those (and will contain all of the right content since\n            // the text nodes between elements in the new DOM are merged together).\n            // The check below looks to see if we're already in the process of adding\n            // a textReplace edit following the same element.\n            var previousEdit = newEdits.length > 0 && newEdits[newEdits.length - 1];\n            if (previousEdit && previousEdit.type === \"textReplace\" &&\n                    previousEdit.afterID === textAfterID) {\n                oldIndex++;\n                return;\n            }\n\n            newEdit.parentID = oldChild.parent.tagID;\n\n            // If there was only one child previously, we just pass along\n            // textDelete/textReplace with the parentID and the browser will\n            // clear all of the children\n            if (oldChild.parent.children.length === 1) {\n                newEdits.push(newEdit);\n            } else {\n                if (textAfterID) {\n                    newEdit.afterID = textAfterID;\n                }\n                newEdits.push(newEdit);\n            }\n\n            // This text appeared in the old tree but not the new one, so we\n            // increment the old children counter.\n            oldIndex++;\n        };\n\n        /**\n         * Adds an elementMove edit if the parent has changed between the old and new trees.\n         * These are fairly infrequent and generally occur if you make a change across\n         * tag boundaries.\n         *\n         * @return {boolean} true if an elementMove was generated\n         */\n        var addElementMove = function () {\n\n            // This check looks a little strange, but it suits what we're trying\n            // to do: as we're walking through the children, a child node that has moved\n            // from one parent to another will be found but would look like some kind\n            // of insert. The check that we're doing here is looking up the current\n            // child's ID in the *old* map and seeing if this child used to have a\n            // different parent.\n            var possiblyMovedElement = oldNodeMap[newChild.tagID];\n            if (possiblyMovedElement &&\n                    newParent.tagID !== getParentID(possiblyMovedElement)) {\n                newEdit = {\n                    type: \"elementMove\",\n                    tagID: newChild.tagID,\n                    parentID: newChild.parent.tagID\n                };\n                moves.push(newEdit.tagID);\n                newEdits.push(newEdit);\n\n                // this element in the new tree was a move to this spot, so we can move\n                // on to the next child in the new tree.\n                newIndex++;\n                return true;\n            }\n            return false;\n        };\n\n        /**\n         * Looks to see if the element in the old tree has moved by checking its\n         * current and former parents.\n         *\n         * @return {boolean} true if the element has moved\n         */\n        var hasMoved = function (oldChild) {\n            var oldChildInNewTree = newNodeMap[oldChild.tagID];\n\n            return oldChild.children && oldChildInNewTree && getParentID(oldChild) !== getParentID(oldChildInNewTree);\n        };\n\n        // Loop through the current and old children, comparing them one by one.\n        while (newIndex < newChildren.length && oldIndex < oldChildren.length) {\n            newChild = newChildren[newIndex];\n\n            // Check to see if the currentChild has been reparented from somewhere\n            // else in the old tree\n            if (newChild.children && addElementMove()) {\n                continue;\n            }\n\n            oldChild = oldChildren[oldIndex];\n\n            // Check to see if the oldChild has been moved to another parent.\n            // If it has, we deal with it on the other side (see above)\n            if (hasMoved(oldChild)) {\n                oldIndex++;\n                continue;\n            }\n\n            if (newChild.isElement() || oldChild.isElement()) {\n\n                if (newChild.isElement() && oldChild.isText()) {\n                    addTextDelete();\n\n                    // If this element is new, add it and move to the next child\n                    // in the current tree. Otherwise, we'll compare this same\n                    // current element with the next old element on the next pass\n                    // through the loop.\n                    addElementInsert();\n\n                } else if (oldChild.isElement() && newChild.isText()) {\n                    // If the old child has *not* been deleted, we assume that we've\n                    // inserted some text and will still encounter the old node\n                    if (!addElementDelete()) {\n                        addTextInsert();\n                    }\n\n                // both children are elements\n                } else {\n                    if (newChild.tagID !== oldChild.tagID) {\n\n                        // First, check to see if we're deleting an element.\n                        // If we are, get rid of that element and restart our comparison\n                        // logic with the same element from the new tree and the next one\n                        // from the old tree.\n                        if (!addElementDelete()) {\n                            // Since we're not deleting and these elements don't match up, we\n                            // must have a new element. Add an elementInsert (and log a problem\n                            // if no insert works.)\n                            if (!addElementInsert()) {\n                                console.error(\"HTML Instrumentation: This should not happen. Two elements have different tag IDs and there was no insert/delete. This generally means there was a reordering of elements.\");\n                                newIndex++;\n                                oldIndex++;\n                            }\n                        }\n\n                    // There has been no change in the tag we're looking at.\n                    } else {\n                        // Since this element hasn't moved, it is a suitable \"beforeID\"\n                        // for the edits we've logged.\n                        finalizeNewEdits(oldChild.tagID, false);\n                        newIndex++;\n                        oldIndex++;\n                    }\n                }\n\n            // We know we're comparing two texts. Just match up their signatures.\n            } else {\n                if (newChild.textSignature !== oldChild.textSignature) {\n                    newEdit = {\n                        type: \"textReplace\",\n                        content: newChild.content,\n                        parentID: newChild.parent.tagID\n                    };\n                    if (textAfterID) {\n                        newEdit.afterID = textAfterID;\n                    }\n                    newEdits.push(newEdit);\n                }\n\n                // Either we've done a text replace or both sides matched. In either\n                // case we're ready to move forward among both the old and new children.\n                newIndex++;\n                oldIndex++;\n            }\n        }\n\n        // At this point, we've used up all of the children in at least one of the\n        // two sets of children.\n\n        /**\n         * Take care of any remaining children in the old tree.\n         */\n        while (oldIndex < oldChildren.length) {\n            oldChild = oldChildren[oldIndex];\n\n            // Check for an element that has moved\n            if (hasMoved(oldChild)) {\n                // This element has moved, so we skip it on this side (the move\n                // is handled on the new tree side).\n                oldIndex++;\n\n            // is this an element? if so, delete it\n            } else if (oldChild.isElement()) {\n                if (!addElementDelete()) {\n                    console.error(\"HTML Instrumentation: failed to add elementDelete for remaining element in the original DOM. This should not happen.\", oldChild);\n                    oldIndex++;\n                }\n\n            // must be text. delete that.\n            } else {\n                addTextDelete();\n            }\n        }\n\n        /**\n         * Take care of the remaining children in the new tree.\n         */\n        while (newIndex < newChildren.length) {\n            newChild = newChildren[newIndex];\n\n            // Is this an element?\n            if (newChild.isElement()) {\n\n                // Look to see if the element has moved here.\n                if (!addElementMove()) {\n                    // Not a move, so we insert this element.\n                    if (!addElementInsert()) {\n                        console.error(\"HTML Instrumentation: failed to add elementInsert for remaining element in the updated DOM. This should not happen.\");\n                        newIndex++;\n                    }\n                }\n\n            // not a new element, so it must be new text.\n            } else {\n                addTextInsert();\n            }\n        }\n\n        /**\n         * Finalize remaining edits. For inserts and moves, we can set the `lastChild`\n         * flag and the browser can simply use `appendChild` to add these items.\n         */\n        newEdits.forEach(function (edit) {\n            if (edit.type === \"textInsert\" || edit.type === \"elementInsert\" || edit.type === \"elementMove\") {\n                edit.lastChild = true;\n                delete edit.firstChild;\n                delete edit.afterID;\n            }\n        });\n        edits.push.apply(edits, newEdits);\n\n        return {\n            edits: edits,\n            moves: moves,\n            newElements: newElements\n        };\n    };\n\n    /**\n     * Generate a list of edits that will mutate oldNode to look like newNode.\n     * Currently, there are the following possible edit operations:\n     *\n     * * elementInsert\n     * * elementDelete\n     * * elementMove\n     * * textInsert\n     * * textDelete\n     * * textReplace\n     * * attrDelete\n     * * attrChange\n     * * attrAdd\n     * * rememberNodes (a special instruction that reflects the need to hang on to moved nodes)\n     *\n     * @param {Object} oldNode SimpleDOM node with the original content\n     * @param {Object} newNode SimpleDOM node with the new content\n     * @return {Array.{Object}} list of edit operations\n     */\n    function domdiff(oldNode, newNode) {\n        var queue = [],\n            edits = [],\n            moves = [],\n            newElement,\n            oldElement,\n            oldNodeMap = oldNode ? oldNode.nodeMap : {},\n            newNodeMap = newNode.nodeMap;\n\n        /**\n         * Adds elements to the queue for generateChildEdits.\n         * Only elements (and not text nodes) are added. New nodes (ones that aren't in the\n         * old nodeMap), are not added here because they will be added when generateChildEdits\n         * creates the elementInsert edit.\n         */\n        var queuePush = function (node) {\n            if (node.children && oldNodeMap[node.tagID]) {\n                queue.push(node);\n            }\n        };\n\n        /**\n         * Aggregates the child edits in the proper data structures.\n         *\n         * @param {Object} delta edits, moves and newElements to add\n         */\n        var addEdits = function (delta) {\n            edits.push.apply(edits, delta.edits);\n            moves.push.apply(moves, delta.moves);\n            queue.push.apply(queue, delta.newElements);\n        };\n\n        // Start at the root of the current tree.\n        queue.push(newNode);\n\n        do {\n            newElement = queue.pop();\n            oldElement = oldNodeMap[newElement.tagID];\n\n            // Do we need to compare elements?\n            if (oldElement) {\n\n                // Are attributes different?\n                if (newElement.attributeSignature !== oldElement.attributeSignature) {\n                    // generate attribute edits\n                    edits.push.apply(edits, generateAttributeEdits(oldElement, newElement));\n                }\n\n                // Has there been a change to this node's immediate children?\n                if (newElement.childSignature !== oldElement.childSignature) {\n                    addEdits(generateChildEdits(oldElement, oldNodeMap, newElement, newNodeMap));\n                }\n\n                // If there's a change farther down in the tree, add the children to the queue.\n                // If not, we can skip that whole subtree.\n                if (newElement.subtreeSignature !== oldElement.subtreeSignature) {\n                    newElement.children.forEach(queuePush);\n                }\n\n            // This is a new element, so go straight to generating child edits (which will\n            // create the appropriate Insert edits).\n            } else {\n                // If this is the root (html) tag, we need to manufacture an insert for it here,\n                // because it isn't the child of any other node. The browser-side code doesn't\n                // care about parentage/positioning in this case, and will handle just setting the\n                // ID on the existing implied HTML tag in the browser without actually creating it.\n                if (!newElement.parent) {\n                    edits.push({\n                        type: \"elementInsert\",\n                        tag: newElement.tag,\n                        tagID: newElement.tagID,\n                        parentID: null,\n                        attributes: newElement.attributes\n                    });\n                }\n\n                addEdits(generateChildEdits(null, oldNodeMap, newElement, newNodeMap));\n            }\n        } while (queue.length);\n\n        // Special handling for moves: add edits to the beginning of the list so that\n        // moved nodes are set aside to ensure that they remain available at the time of their\n        // move.\n        if (moves.length > 0) {\n            edits.unshift({\n                type: \"rememberNodes\",\n                tagIDs: moves\n            });\n        }\n\n        return edits;\n    }\n\n    // Public API\n    exports.domdiff = domdiff;\n});\n"
  },
  {
    "path": "src/language/HTMLInstrumentation.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: HTML Instrumentation*/\n\n/**\n * HTMLInstrumentation\n *\n * This module contains functions for \"instrumenting\" html code so that we can track\n * the relationship of source code to DOM nodes in the browser. This functionality is\n * used by both live highlighting and live HTML editing.\n *\n * During live HTML development, the HTML source code is parsed to identify tag boundaries.\n * Each tag is assigned an ID which is stored in markers that are inserted into the editor.\n * These IDs are also included in \"data-brackets-id\" attributes that are inserted in the\n * HTML code that's served to the browser via the Live Development server.\n *\n * The primary function for that functionality is generateInstrumentedHTML(). This does just\n * what it says - it will read the HTML content in the doc and generate instrumented code by\n * injecting \"data-brackets-id\" attributes. Additionally, it caches the parsed DOM for use\n * by future updates.\n *\n * As the user makes edits in the editor, we determine how the DOM structure should change\n * based on the edits to the source code; those edits are generated by getUnappliedEditList().\n * HTMLDocument (in LiveDevelopment) takes those edits and sends them to the browser (via\n * RemoteFunctions) so that the DOM structure in the live preview can be updated accordingly.\n *\n * There are also helper functions for returning the tagID associated with a specified\n * position in the document--this is used in live highlighting.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DocumentManager = require(\"document/DocumentManager\"),\n        HTMLSimpleDOM   = require(\"./HTMLSimpleDOM\"),\n        HTMLDOMDiff     = require(\"./HTMLDOMDiff\"),\n        _               = require(\"thirdparty/lodash\");\n\n    var allowIncremental = true;\n\n    // Hash of scanned documents. Key is the full path of the doc. Value is an object\n    // with two properties: timestamp and dom. Timestamp is the document timestamp,\n    // dom is the root node of a simple DOM tree.\n    var _cachedValues = {};\n\n    /**\n     * @private\n     * Removes the cached information (DOM, timestamp, etc.) used by HTMLInstrumentation\n     * for the given document.\n     * @param {$.Event} event (unused)\n     * @param {Document} document The document to clear from the cache.\n     */\n    function _removeDocFromCache(evt, document) {\n        if (_cachedValues.hasOwnProperty(document.file.fullPath)) {\n            delete _cachedValues[document.file.fullPath];\n            document.off(\".htmlInstrumentation\");\n        }\n    }\n\n    /**\n     * @private\n     * Checks if two CodeMirror-style {line, ch} positions are equal.\n     * @param {{line: number, ch: number}} pos1\n     * @param {{line: number, ch: number}} pos2\n     * @return {boolean} true if pos1 and pos2 are equal. Fails if either of them is falsy.\n     */\n    function _posEq(pos1, pos2) {\n        return pos1 && pos2 && pos1.line === pos2.line && pos1.ch === pos2.ch;\n    }\n\n    function getPositionFromTagId(editor, tagId) {\n        var marks = editor._codeMirror.getAllMarks(),\n            i,\n            markFound;\n        \n        markFound = _.find(marks, function (mark) {\n            return (mark.tagID === tagId);\n        });\n        if (markFound) {\n            return markFound.find().from;\n        } else {\n            return null;\n        }\n    }\n\n    /**\n     * @private\n     * Filters the given marks to find the ones that correspond to instrumented tags,\n     * sorts them by their starting position, and looks up and/or stores their ranges\n     * in the given markCache.\n     * @param {Array} marks An array of mark objects returned by CodeMirror.\n     * @param {Object} markCache An object that maps tag IDs to {mark, range} objects.\n     *     If a mark in the marks array is already in the cache, we use the cached range info,\n     *     otherwise we look up its range in CodeMirror and store it in the cache.\n     * @return {Array.<{mark: Object, range: {line: number, ch: number}}>} The filtered and\n     *     sorted array of mark info objects (each of which contains the mark and its range,\n     *     so the range doesn't need to be looked up again).\n     */\n    function _getSortedTagMarks(marks, markCache) {\n        marks = marks.filter(function (mark) {\n            return !!mark.tagID;\n        }).map(function (mark) {\n            // All marks should exist since we just got them from CodeMirror.\n            if (!markCache[mark.tagID]) {\n                markCache[mark.tagID] = {mark: mark, range: mark.find()};\n            }\n            return markCache[mark.tagID];\n        });\n        marks.sort(function (mark1, mark2) {\n            return (mark1.range.from.line === mark2.range.from.line ?\n                    mark1.range.from.ch - mark2.range.from.ch :\n                    mark1.range.from.line - mark2.range.from.line);\n        });\n\n        return marks;\n    }\n\n    /**\n     * @private\n     * Finds the mark for the DOM node at the given position in the editor.\n     * @param {Editor} editor The editor containing the instrumented document.\n     * @param {{line: number, ch: number}} pos The position to find the DOM marker for.\n     * @param {boolean} preferParent If true, and the pos is at one or the other edge of the\n     *     innermost marked range, return the immediately enclosing mark instead.\n     * @param {Object=} markCache An optional cache to look up positions of existing\n     *     markers. (This avoids calling the find() operation on marks multiple times,\n     *     which is expensive.)\n     * @return {Object} The CodeMirror mark object that represents the DOM node at the\n     *     given position.\n     */\n    function _getMarkerAtDocumentPos(editor, pos, preferParent, markCache) {\n        var marks, match;\n\n        markCache = markCache || {};\n        marks = _getSortedTagMarks(editor._codeMirror.findMarksAt(pos), markCache);\n        if (!marks.length) {\n            return null;\n        }\n\n        // The mark with the latest start is the innermost one.\n        match = marks.pop();\n        if (preferParent) {\n            // If the match is exactly at the edge of the range and preferParent is set,\n            // we want to pop upwards. If pos is exactly between two marks, we need to pop upwards twice.\n            while (match && (_posEq(match.range.from, pos) || _posEq(match.range.to, pos))) {\n                match = marks.pop();\n            }\n        }\n\n        return match && match.mark;\n    }\n\n    /**\n     * @private\n     * Dumps the current list of mark ranges for instrumented tags to the console. Used for debugging.\n     * @param {Editor} editor The editor to find the mark ranges for.\n     * @param {Object=} nodeMap If specified, a map of tag IDs to DOM nodes, used so we can indicate which tag name\n     *     the DOM thinks corresponds to the given mark.\n     */\n    function _dumpMarks(editor, nodeMap) {\n        var markCache = {},\n            marks = _getSortedTagMarks(editor._codeMirror.getAllMarks(), markCache);\n        marks.forEach(function (markInfo) {\n            var mark = markInfo.mark,\n                range = markInfo.range;\n            console.log(\"<\" + nodeMap[mark.tagID].tag + \"> (\" + mark.tagID + \") \" +\n                        range.from.line + \":\" + range.from.ch + \" - \" + range.to.line + \":\" + range.to.ch);\n        });\n    }\n    // Workaround for JSHint to not complain about the unused function\n    void(_dumpMarks);\n\n    /**\n     * Get the instrumented tagID at the specified position. Returns -1 if\n     * there are no instrumented tags at the location.\n     * The _markText() function must be called before calling this function.\n     *\n     * NOTE: This function is \"private\" for now (has a leading underscore), since\n     * the API is likely to change in the future.\n     *\n     * @param {Editor} editor The editor to scan.\n     * @param {{line: number, ch: number}} pos The position to find the DOM marker for.\n     * @param {Object=} markCache An optional cache to look up positions of existing\n     *     markers. (This avoids calling the find() operation on marks multiple times,\n     *     which is expensive.)\n     * @return {number} tagID at the specified position, or -1 if there is no tag\n     */\n    function _getTagIDAtDocumentPos(editor, pos, markCache) {\n        var match = _getMarkerAtDocumentPos(editor, pos, false, markCache);\n\n        return (match) ? match.tagID : -1;\n    }\n\n    /**\n     * Recursively walks the SimpleDOM starting at node and marking\n     * all tags in the CodeMirror instance. The more useful interface\n     * is the _markTextFromDOM function which clears existing marks\n     * before calling this function to create new ones.\n     *\n     * @param {CodeMirror} cm CodeMirror instance in which to mark tags\n     * @param {Object} node SimpleDOM node to use as the root for marking\n     */\n    function _markTags(cm, node) {\n        node.children.forEach(function (childNode) {\n            if (childNode.isElement()) {\n                _markTags(cm, childNode);\n            }\n        });\n        var mark = cm.markText(node.startPos, node.endPos);\n        mark.tagID = node.tagID;\n    }\n\n    /**\n     * Clears the marks from the document and creates new ones.\n     *\n     * @param {Editor} editor Editor object holding this document\n     * @param {Object} dom SimpleDOM root object that contains the parsed structure\n     */\n    function _markTextFromDOM(editor, dom) {\n        var cm = editor._codeMirror;\n\n        // Remove existing marks\n        var marks = cm.getAllMarks();\n        cm.operation(function () {\n            marks.forEach(function (mark) {\n                if (mark.hasOwnProperty(\"tagID\")) {\n                    mark.clear();\n                }\n            });\n        });\n\n        // Mark\n        _markTags(cm, dom);\n    }\n\n    /**\n     * Subclass of HTMLSimpleDOM.Builder that builds an updated DOM after changes have been made,\n     * and maps nodes from the new DOM to the old DOM by tag ID. For non-structural edits, avoids reparsing\n     * the whole editor. Also updates marks in the editor based on the new DOM state.\n     *\n     * @constructor\n     * @param {Object} previousDOM The root of the HTMLSimpleDOM tree representing a previous state of the DOM.\n     * @param {Editor} editor The editor containing the instrumented HTML.\n     * @param {Array=} changeList An optional array of CodeMirror change records representing the\n     *     edits the user made in the editor since previousDOM was built. If provided, and the\n     *     edits are not structural, DOMUpdater will do a fast incremental reparse. If not provided,\n     *     or if one of the edits changes the DOM structure, DOMUpdater will reparse the whole DOM.\n     */\n    function DOMUpdater(previousDOM, editor, changeList) {\n        var text, startOffset = 0, startOffsetPos;\n\n        this.isIncremental = false;\n\n        function isDangerousEdit(text) {\n            // We don't consider & dangerous since entities only affect text content, not\n            // overall DOM structure.\n            return (/[<>\\/=\\\"\\']/).test(text);\n        }\n\n        // If there's more than one change, be conservative and assume we have to do a full reparse.\n        if (changeList && changeList.length === 1) {\n            // If the inserted or removed text doesn't have any characters that could change the\n            // structure of the DOM (e.g. by adding or removing a tag boundary), then we can do\n            // an incremental reparse of just the parent tag containing the edit. This should just\n            // be the marked range that contains the beginning of the edit range, since that position\n            // isn't changed by the edit.\n            var change = changeList[0];\n            if (!isDangerousEdit(change.text) && !isDangerousEdit(change.removed)) {\n                // If the edit is right at the beginning or end of a tag, we want to be conservative\n                // and use the parent as the edit range.\n                var startMark = _getMarkerAtDocumentPos(editor, change.from, true);\n                if (startMark) {\n                    var range = startMark.find();\n                    if (range) {\n                        text = editor._codeMirror.getRange(range.from, range.to);\n                        this.changedTagID = startMark.tagID;\n                        startOffsetPos = range.from;\n                        startOffset = editor._codeMirror.indexFromPos(startOffsetPos);\n                        this.isIncremental = true;\n                    }\n                }\n            }\n        }\n\n        if (!this.changedTagID) {\n            // We weren't able to incrementally update, so just rebuild and diff everything.\n            text = editor.document.getText();\n        }\n\n        HTMLSimpleDOM.Builder.call(this, text, startOffset, startOffsetPos);\n        this.editor = editor;\n        this.cm = editor._codeMirror;\n        this.previousDOM = previousDOM;\n    }\n\n    DOMUpdater.prototype = Object.create(HTMLSimpleDOM.Builder.prototype);\n\n    /**\n     * @private\n     * Returns true if the given node has an ancestor whose tagID is the given ID.\n     * @param {Object} node A node from an HTMLSimpleDOM structure.\n     * @param {number} id The ID of the tag to check for.\n     * @return {boolean} true if the node has an ancestor with that ID.\n     */\n    function _hasAncestorWithID(node, id) {\n        var ancestor = node.parent;\n        while (ancestor && ancestor.tagID !== id) {\n            ancestor = ancestor.parent;\n        }\n        return !!ancestor;\n    }\n\n    /**\n     * Overrides the `getID` method to return the tag ID from the document. If a viable tag\n     * ID cannot be found in the document marks, then a new ID is returned. This will also\n     * assign a new ID if the tag changed between the previous and current versions of this\n     * node.\n     *\n     * @param {Object} newTag tag object for the current element\n     * @return {int} best ID\n     */\n    DOMUpdater.prototype.getID = function (newTag, markCache) {\n        // Get the mark at the start of the tagname (not before the beginning of the tag, because that's\n        // actually inside the parent).\n        var currentTagID = _getTagIDAtDocumentPos(this.editor, HTMLSimpleDOM._offsetPos(newTag.startPos, 1), markCache);\n\n        // If the new tag is in an unmarked range, or the marked range actually corresponds to an\n        // ancestor tag, then this must be a newly inserted tag, so give it a new tag ID.\n        if (currentTagID === -1 || _hasAncestorWithID(newTag, currentTagID)) {\n            currentTagID = this.getNewID();\n        } else {\n            // If the tag has changed between the previous DOM and the new one, we assign a new ID\n            // so that the old tag will be deleted and the new one inserted.\n            var oldNode = this.previousDOM.nodeMap[currentTagID];\n            if (!oldNode || oldNode.tag !== newTag.tag) {\n                currentTagID = this.getNewID();\n            }\n        }\n        return currentTagID;\n    };\n\n    /**\n     * Updates the CodeMirror marks in the editor to reflect the new bounds of nodes in\n     * the given nodeMap.\n     * @param {Object} nodeMap The node map from the new DOM.\n     * @param {Object} markCache The cache of existing mark ranges built during the latest parse.\n     */\n    DOMUpdater.prototype._updateMarkedRanges = function (nodeMap, markCache) {\n        // FUTURE: this is somewhat inefficient (getting all the marks involves passing linearly through\n        // the document once), but it doesn't seem to be a hotspot right now.\n        var updateIDs = Object.keys(nodeMap),\n            cm = this.cm,\n            marks = cm.getAllMarks();\n\n        cm.operation(function () {\n            marks.forEach(function (mark) {\n                if (mark.hasOwnProperty(\"tagID\") && nodeMap[mark.tagID]) {\n                    var node = nodeMap[mark.tagID],\n                        markInfo = markCache[mark.tagID];\n                    // If the mark's bounds already match, avoid destroying and recreating the mark,\n                    // since that incurs some overhead.\n                    if (!(markInfo && _posEq(markInfo.range.from, node.startPos) && _posEq(markInfo.range.to, node.endPos))) {\n                        mark.clear();\n                        mark = cm.markText(node.startPos, node.endPos);\n                        mark.tagID = node.tagID;\n                    }\n                    updateIDs.splice(updateIDs.indexOf(String(node.tagID)), 1);\n                }\n            });\n\n            // Any remaining updateIDs are new.\n            updateIDs.forEach(function (id) {\n                var node = nodeMap[id], mark;\n                if (node.isElement()) {\n                    mark = cm.markText(node.startPos, node.endPos);\n                    mark.tagID = Number(id);\n                }\n            });\n        });\n    };\n\n    /**\n     * @private\n     * Creates a map from tagIDs to nodes in the given HTMLSimpleDOM subtree and\n     * stores it on the root.\n     * @param {Object} root The root of an HTMLSimpleDOM tree.\n     */\n    DOMUpdater.prototype._buildNodeMap = function (root) {\n        var nodeMap = {};\n\n        function walk(node) {\n            if (node.tagID) {\n                nodeMap[node.tagID] = node;\n            }\n            if (node.isElement()) {\n                node.children.forEach(walk);\n            }\n        }\n\n        walk(root);\n        root.nodeMap = nodeMap;\n    };\n\n    /**\n     * @private\n     * Removes all nodes deleted between the oldSubtree and the newSubtree from the given nodeMap,\n     * and clears marks associated with those nodes.\n     * @param {Object} nodeMap The nodeMap to update to remove deleted items.\n     * @param {Object} oldSubtreeMap The nodeMap for the original subtree (which should be a subset of the\n     *     first nodeMap).\n     * @param {Object} newSubtreeMap The nodeMap for the new subtree.\n     */\n    DOMUpdater.prototype._handleDeletions = function (nodeMap, oldSubtreeMap, newSubtreeMap) {\n        var deletedIDs = [];\n        Object.keys(oldSubtreeMap).forEach(function (key) {\n            if (!newSubtreeMap.hasOwnProperty(key)) {\n                deletedIDs.push(key);\n                delete nodeMap[key];\n            }\n        });\n\n        if (deletedIDs.length) {\n            // FUTURE: would be better to cache the mark for each node. Also, could\n            // conceivably combine this with _updateMarkedRanges().\n            var marks = this.cm.getAllMarks();\n            marks.forEach(function (mark) {\n                if (mark.hasOwnProperty(\"tagID\") && deletedIDs.indexOf(mark.tagID) !== -1) {\n                    mark.clear();\n                }\n            });\n        }\n    };\n\n    /**\n     * Reparses the document (or a portion of it if we can do it incrementally).\n     * Note that in an incremental update, the old DOM is actually mutated (the new\n     * subtree is swapped in for the old subtree).\n     * @return {?{newDOM: Object, oldSubtree: Object, newSubtree: Object}} newDOM is\n     *      the full new DOM. For a full update, oldSubtree is the full old DOM\n     *      and newSubtree is the same as newDOM; for an incremental update,\n     *      oldSubtree is the portion of the old tree that was reparsed,\n     *      newSubtree is the updated version, and newDOM is actually the same\n     *      as the original DOM (with newSubtree swapped in for oldSubtree).\n     *      If the document can't be parsed due to invalid HTML, returns null.\n     */\n    DOMUpdater.prototype.update = function () {\n        var markCache = {},\n            newSubtree = this.build(true, markCache),\n            result = {\n                // default result if we didn't identify a changed portion\n                newDOM: newSubtree,\n                oldSubtree: this.previousDOM,\n                newSubtree: newSubtree\n            };\n\n        if (!newSubtree) {\n            return null;\n        }\n\n        if (this.changedTagID) {\n            // Find the old subtree that's going to get swapped out.\n            var oldSubtree = this.previousDOM.nodeMap[this.changedTagID],\n                parent = oldSubtree.parent;\n\n            // If we didn't have a parent, then the whole tree changed anyway, so\n            // we'll just return the default result.\n            if (parent) {\n                var childIndex = parent.children.indexOf(oldSubtree);\n                if (childIndex === -1) {\n                    // This should never happen...\n                    console.error(\"DOMUpdater.update(): couldn't locate old subtree in tree\");\n                } else {\n                    // Swap the new subtree in place of the old subtree.\n                    oldSubtree.parent = null;\n                    newSubtree.parent = parent;\n                    parent.children[childIndex] = newSubtree;\n\n                    // Overwrite any node mappings in the parent DOM with the\n                    // mappings for the new subtree. We keep the nodeMap around\n                    // on the new subtree so that the differ can use it later.\n                    $.extend(this.previousDOM.nodeMap, newSubtree.nodeMap);\n\n                    // Update marked ranges for all items in the new subtree.\n                    this._updateMarkedRanges(newSubtree.nodeMap, markCache);\n\n                    // Build a local nodeMap for the old subtree so the differ can\n                    // use it.\n                    this._buildNodeMap(oldSubtree);\n\n                    // Clean up the info for any deleted nodes that are no longer in\n                    // the new tree.\n                    this._handleDeletions(this.previousDOM.nodeMap, oldSubtree.nodeMap, newSubtree.nodeMap);\n\n                    // Update the signatures for all parents of the new subtree.\n                    var curParent = parent;\n                    while (curParent) {\n                        curParent.update();\n                        curParent = curParent.parent;\n                    }\n\n                    result.newDOM = this.previousDOM;\n                    result.oldSubtree = oldSubtree;\n                }\n            }\n        } else {\n            _markTextFromDOM(this.editor, result.newDOM);\n        }\n\n        return result;\n    };\n\n    /**\n     * @private\n     * Builds a new DOM for the current state of the editor, diffs it against the\n     * previous DOM, and generates a DOM edit list that can be used to replay the\n     * diffs in the browser.\n     * @param {Object} previousDOM The HTMLSimpleDOM corresponding to the previous state of the editor.\n     *     Note that in the case of an incremental edit, this will be mutated to create the new DOM\n     *     (by swapping out the subtree corresponding to the changed portion).\n     * @param {Editor} editor The editor containing the instrumented HTML.\n     * @param {Array=} changeList If specified, a CodeMirror changelist reflecting all the\n     *     text changes in the editor since previousDOM was built. If specified, we will\n     *     attempt to do an incremental update (although we might fall back to a full update\n     *     in various cases). If not specified, we will always do a full update.\n     * @return {{dom: Object, edits: Array}} The new DOM representing the current state of the\n     *     editor, and an array of edits that can be applied to update the browser (see\n     *     HTMLDOMDiff for more information on the edit format).\n     */\n    function _updateDOM(previousDOM, editor, changeList) {\n        if (!allowIncremental) {\n            changeList = undefined;\n        }\n        var updater = new DOMUpdater(previousDOM, editor, changeList);\n        var result = updater.update();\n        if (!result) {\n            return { errors: updater.errors };\n        }\n\n        var edits = HTMLDOMDiff.domdiff(result.oldSubtree, result.newSubtree);\n\n        // We're done with the nodeMap that was added to the subtree by the updater.\n        if (result.newSubtree !== result.newDOM) {\n            delete result.newSubtree.nodeMap;\n        }\n\n        return {\n            dom: result.newDOM,\n            edits: edits,\n            _wasIncremental: updater.isIncremental // for unit tests only\n        };\n    }\n\n    /**\n     * Calculates the DOM edits that are needed to update the browser from the state the\n     * editor was in the last time that scanDocument(), getInstrumentedHTML(), or\n     * getUnappliedEditList() was called (whichever is most recent). Caches this state so\n     * it can be used as the base state for the next getUnappliedEditList().\n     *\n     * For simple text edits, this update is done quickly and incrementally. For structural\n     * edits (edits that change the DOM structure or add/remove attributes), the update\n     * requires a full reparse.\n     *\n     * If the document currently contains invalid HTML, no edits will be generated until\n     * getUnappliedEditList() is called when the document is valid, at which point the edits\n     * will reflect all the changes needed to catch the browser up with all the edits\n     * made while the document was invalid.\n     *\n     * @param {Editor} editor The editor containing the instrumented HTML\n     * @param {Array} changeList A CodeMirror change list describing the text changes made\n     *     in the editor since the last update. If specified, we will attempt to do an\n     *     incremental update.\n     * @return {Array} edits A list of edits to apply in the browser. See HTMLDOMDiff for\n     *     more information on the format of these edits.\n     */\n    function getUnappliedEditList(editor, changeList) {\n        var cachedValue = _cachedValues[editor.document.file.fullPath];\n\n        // We might not have a previous DOM if the document was empty before this edit.\n        if (!cachedValue || !cachedValue.dom || _cachedValues[editor.document.file.fullPath].invalid) {\n            // We were in an invalid state, so do a full rebuild.\n            changeList = null;\n        }\n\n        var result = _updateDOM(cachedValue && cachedValue.dom, editor, changeList);\n\n        if (!result.errors) {\n            _cachedValues[editor.document.file.fullPath] = {\n                timestamp: editor.document.diskTimestamp,\n                dom: result.dom,\n                dirty: false\n            };\n            return { edits: result.edits };\n        } else {\n            if (cachedValue) {\n                cachedValue.invalid = true;\n            }\n            return { errors: result.errors };\n        }\n    }\n\n    /**\n     * @private\n     * Add SimpleDOMBuilder metadata to browser DOM tree JSON representation\n     * @param {Object} root\n     */\n    function _processBrowserSimpleDOM(browserRoot, editorRootTagID) {\n        var nodeMap         = {},\n            root;\n\n        function _processElement(elem) {\n            elem.tagID = elem.attributes[\"data-brackets-id\"];\n\n            // remove data-brackets-id attribute for diff\n            delete elem.attributes[\"data-brackets-id\"];\n\n            elem.children.forEach(function (child) {\n                // set parent\n                child.parent = elem;\n\n                if (child.isElement()) {\n                    _processElement(child);\n                } else if (child.isText()) {\n                    child.update();\n                    child.tagID = HTMLSimpleDOM.getTextNodeID(child);\n\n                    nodeMap[child.tagID] = child;\n                }\n            });\n\n            elem.update();\n\n            nodeMap[elem.tagID] = elem;\n\n            // Choose the root element based on the root tag in the editor.\n            // The browser may insert html, head and body elements if missing.\n            if (elem.tagID === editorRootTagID) {\n                root = elem;\n            }\n        }\n\n        _processElement(browserRoot);\n\n        root = root || browserRoot;\n        root.nodeMap = nodeMap;\n\n        return root;\n    }\n\n    /**\n     * @private\n     * Diff the browser DOM with the in-editor DOM\n     * @param {Editor} editor\n     * @param {Object} browserSimpleDOM\n     */\n    function _getBrowserDiff(editor, browserSimpleDOM) {\n        var cachedValue = _cachedValues[editor.document.file.fullPath],\n            editorRoot  = cachedValue.dom,\n            browserRoot;\n\n        browserRoot = _processBrowserSimpleDOM(browserSimpleDOM, editorRoot.tagID);\n\n        return {\n            diff    : HTMLDOMDiff.domdiff(editorRoot, browserRoot),\n            browser : browserRoot,\n            editor  : editorRoot\n        };\n    }\n\n    DocumentManager.on(\"beforeDocumentDelete\", _removeDocFromCache);\n\n    /**\n     * Parses the document, returning an HTMLSimpleDOM structure and caching it as the\n     * initial state of the document. Will return a cached copy of the DOM if the\n     * document hasn't changed since the last time scanDocument was called.\n     *\n     * This is called by generateInstrumentedHTML(), but it can be useful to call it\n     * ahead of time so the DOM is cached and doesn't need to be rescanned when the\n     * instrumented HTML is requested by the browser.\n     *\n     * @param {Document} doc The doc to scan.\n     * @return {Object} Root DOM node of the document.\n     */\n    function scanDocument(doc) {\n        if (!_cachedValues.hasOwnProperty(doc.file.fullPath)) {\n            doc.on(\"change.htmlInstrumentation\", function () {\n                if (_cachedValues[doc.file.fullPath]) {\n                    _cachedValues[doc.file.fullPath].dirty = true;\n                }\n            });\n\n            // Assign to cache, but don't set a value yet\n            _cachedValues[doc.file.fullPath] = null;\n        }\n\n        var cachedValue = _cachedValues[doc.file.fullPath];\n        if (!doc.isDirty && cachedValue && !cachedValue.dirty && cachedValue.timestamp === doc.diskTimestamp) {\n            return cachedValue.dom;\n        }\n\n        var text = doc.getText(),\n            dom = HTMLSimpleDOM.build(text);\n\n        if (dom) {\n            // Cache results\n            _cachedValues[doc.file.fullPath] = {\n                timestamp: doc.diskTimestamp,\n                dom: dom,\n                dirty: false\n            };\n        }\n\n        return dom;\n    }\n\n    /**\n     * Generate instrumented HTML for the specified editor's document, and mark the associated tag\n     * ranges in the editor. Each tag has a \"data-brackets-id\" attribute with a unique ID for its\n     * value. For example, \"<div>\" becomes something like \"<div data-brackets-id='45'>\". The attribute\n     * value is just a number that is guaranteed to be unique.\n     *\n     * Also stores marks in the given editor that correspond to the tag ranges. These marks are used\n     * to track the DOM structure for in-browser highlighting and live HTML updating.\n     *\n     * This only needs to be done once on load of a document. As the document is edited in memory,\n     * the instrumentation is kept up to date via the diffs and edits that are generated on change\n     * events. Call this again only if you want to do a full re-sync of the editor's DOM state.\n     *\n     * @param {Editor} editor The editor whose document we're instrumenting, and which we should\n     *     mark ranges in.\n     * @return {string} instrumented html content\n     */\n    function generateInstrumentedHTML(editor) {\n        var doc = editor.document,\n            dom = scanDocument(doc),\n            orig = doc.getText(),\n            gen = \"\",\n            lastIndex = 0;\n\n        if (!dom) {\n            return null;\n        }\n\n        // Ensure that the marks in the editor are up to date with respect to the given DOM.\n        _markTextFromDOM(editor, dom);\n\n        // Walk through the dom nodes and insert the 'data-brackets-id' attribute at the\n        // end of the open tag\n        function walk(node) {\n            if (node.tag) {\n                var attrText = \" data-brackets-id='\" + node.tagID + \"'\";\n\n                // Insert the attribute as the first attribute in the tag.\n                var insertIndex = node.start + node.tag.length + 1;\n                gen += orig.substr(lastIndex, insertIndex - lastIndex) + attrText;\n                lastIndex = insertIndex;\n            }\n\n            if (node.isElement()) {\n                node.children.forEach(walk);\n            }\n        }\n\n        walk(dom);\n        gen += orig.substr(lastIndex);\n\n        return gen;\n    }\n\n    /**\n     * Mark the text for the specified editor. Either scanDocument() or\n     * generateInstrumentedHTML() must be called before this function\n     * is called.\n     *\n     * NOTE: This function is \"private\" for now (has a leading underscore), since\n     * the API is likely to change in the future.\n     *\n     * @param {Editor} editor The editor whose text should be marked.\n     * @return none\n     */\n    function _markText(editor) {\n        var cache = _cachedValues[editor.document.file.fullPath],\n            dom = cache && cache.dom;\n\n        if (!dom) {\n            console.error(\"Couldn't find the dom for \" + editor.document.file.fullPath);\n            return;\n        }\n\n        _markTextFromDOM(editor, dom);\n    }\n\n    /**\n     * @private\n     * Clear the DOM cache. For unit testing only.\n     */\n    function _resetCache() {\n        _cachedValues = {};\n    }\n\n    // private methods\n    exports._markText                   = _markText;\n    exports._getMarkerAtDocumentPos     = _getMarkerAtDocumentPos;\n    exports._getTagIDAtDocumentPos      = _getTagIDAtDocumentPos;\n    exports.getPositionFromTagId        = getPositionFromTagId;\n    exports._markTextFromDOM            = _markTextFromDOM;\n    exports._updateDOM                  = _updateDOM;\n    exports._allowIncremental           = allowIncremental;\n    exports._getBrowserDiff             = _getBrowserDiff;\n    exports._resetCache                 = _resetCache;\n\n    // public API\n    exports.scanDocument                = scanDocument;\n    exports.generateInstrumentedHTML    = generateInstrumentedHTML;\n    exports.getUnappliedEditList        = getUnappliedEditList;\n});\n"
  },
  {
    "path": "src/language/HTMLSimpleDOM.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: HTML Instrumentation*/\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Tokenizer   = require(\"language/HTMLTokenizer\").Tokenizer,\n        MurmurHash3 = require(\"thirdparty/murmurhash3_gc\"),\n        PerfUtils   = require(\"utils/PerfUtils\");\n\n    var seed = Math.floor(Math.random() * 65535);\n\n    var tagID = 1;\n\n    /**\n     * A list of tags whose start causes any of a given set of immediate parent\n     * tags to close. This mostly comes from the HTML5 spec section on omitted close tags:\n     * http://www.w3.org/html/wg/drafts/html/master/syntax.html#optional-tags\n     * This doesn't handle general content model violations.\n     */\n    var openImpliesClose = {\n        li      : { li: true },\n        dt      : { dd: true, dt: true },\n        dd      : { dd: true, dt: true },\n        address : { p: true },\n        article : { p: true },\n        aside   : { p: true },\n        blockquote : { p: true },\n        colgroup: { caption: true },\n        details : { p: true },\n        dir     : { p: true },\n        div     : { p: true },\n        dl      : { p: true },\n        fieldset: { p: true },\n        figcaption: { p: true },\n        figure  : { p: true },\n        footer  : { p: true },\n        form    : { p: true },\n        h1      : { p: true },\n        h2      : { p: true },\n        h3      : { p: true },\n        h4      : { p: true },\n        h5      : { p: true },\n        h6      : { p: true },\n        header  : { p: true },\n        hgroup  : { p: true },\n        hr      : { p: true },\n        main    : { p: true },\n        menu    : { p: true },\n        nav     : { p: true },\n        ol      : { p: true },\n        p       : { p: true },\n        pre     : { p: true },\n        section : { p: true },\n        table   : { p: true },\n        ul      : { p: true },\n        rb      : { rb: true, rt: true, rtc: true, rp: true },\n        rp      : { rb: true, rt: true, rp: true },\n        rt      : { rb: true, rt: true, rp: true },\n        rtc     : { rb: true, rt: true, rtc: true, rp: true },\n        optgroup: { optgroup: true, option: true },\n        option  : { option: true },\n        tbody   : { caption: true, colgroup: true, thead: true, tbody: true, tfoot: true },\n        tfoot   : { caption: true, colgroup: true, thead: true, tbody: true },\n        thead   : { caption: true, colgroup: true },\n        tr      : { tr: true, th: true, td: true, caption: true },\n        th      : { th: true, td: true },\n        td      : { th: true, td: true },\n        body    : { head: true }\n    };\n\n    /**\n     * A list of elements which are automatically closed when their parent is closed:\n     * http://www.w3.org/html/wg/drafts/html/master/syntax.html#optional-tags\n     */\n    var optionalClose = {\n      html: true,\n      body: true,\n      li: true,\n      dd: true,\n      dt: true, // This is not actually correct, but showing a syntax error is not helpful\n      p: true,\n      rb: true,\n      rt: true,\n      rtc: true,\n      rp: true,\n      optgroup: true,\n      option: true,\n      colgroup: true,\n      caption: true,\n      tbody: true,\n      tfoot: true,\n      tr: true,\n      td: true,\n      th: true\n    };\n\n    // TODO: handle optional start tags\n\n    /**\n     * A list of tags that are self-closing (do not contain other elements).\n     * Mostly taken from http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements\n     */\n    var voidElements = {\n        area: true,\n        base: true,\n        basefont: true,\n        br: true,\n        col: true,\n        command: true,\n        embed: true,\n        frame: true,\n        hr: true,\n        img: true,\n        input: true,\n        isindex: true,\n        keygen: true,\n        link: true,\n        menuitem: true,\n        meta: true,\n        param: true,\n        source: true,\n        track: true,\n        wbr: true\n    };\n\n    /**\n     * A SimpleNode represents one node in a SimpleDOM tree. Each node can have\n     * any set of properties on it, though there are a couple of assumptions made.\n     * Elements will have `children` and `attributes` properties. Text nodes will have a `content`\n     * property. All Elements will have a `tagID` and text nodes *can* have one.\n     *\n     * @constructor\n     *\n     * @param {Object} properties the properties provided will be set on the new object.\n     */\n    function SimpleNode(properties) {\n        $.extend(this, properties);\n    }\n\n    SimpleNode.prototype = {\n\n        /**\n         * Updates signatures used to optimize the number of comparisons done during\n         * diffing. This is important to call if you change:\n         *\n         * * children\n         * * child node attributes\n         * * text content of a text node\n         * * child node text\n         */\n        update: function () {\n            if (this.isElement()) {\n                var i,\n                    subtreeHashes = \"\",\n                    childHashes = \"\",\n                    child;\n                for (i = 0; i < this.children.length; i++) {\n                    child = this.children[i];\n                    if (child.isElement()) {\n                        childHashes += String(child.tagID);\n                        subtreeHashes += String(child.tagID) + child.attributeSignature + child.subtreeSignature;\n                    } else {\n                        childHashes += child.textSignature;\n                        subtreeHashes += child.textSignature;\n                    }\n                }\n                this.childSignature = MurmurHash3.hashString(childHashes, childHashes.length, seed);\n                this.subtreeSignature = MurmurHash3.hashString(subtreeHashes, subtreeHashes.length, seed);\n            } else {\n                this.textSignature = MurmurHash3.hashString(this.content, this.content.length, seed);\n            }\n        },\n\n        /**\n         * Updates the signature of this node's attributes. Call this after making attribute changes.\n         */\n        updateAttributeSignature: function () {\n            var attributeString = JSON.stringify(this.attributes);\n            this.attributeSignature = MurmurHash3.hashString(attributeString, attributeString.length, seed);\n        },\n\n        /**\n         * Is this node an element node?\n         *\n         * @return {bool} true if it is an element\n         */\n        isElement: function () {\n            return !!this.children;\n        },\n\n        /**\n         * Is this node a text node?\n         *\n         * @return {bool} true if it is text\n         */\n        isText: function () {\n            return !this.children;\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Generates a synthetic ID for text nodes. These IDs are only used\n     * for convenience when reading a SimpleDOM that is dumped to the console.\n     *\n     * @param {Object} textNode new node for which we are generating an ID\n     * @return {string} ID for the node\n     */\n    function getTextNodeID(textNode) {\n        var childIndex = textNode.parent.children.indexOf(textNode);\n        if (childIndex === 0) {\n            return textNode.parent.tagID + \".0\";\n        }\n        return textNode.parent.children[childIndex - 1].tagID + \"t\";\n    }\n\n    /**\n     * @private\n     *\n     * Adds two {line, ch}-style positions, returning a new pos.\n     */\n    function _addPos(pos1, pos2) {\n        return {line: pos1.line + pos2.line, ch: (pos2.line === 0 ? pos1.ch + pos2.ch : pos2.ch)};\n    }\n\n    /**\n     * @private\n     *\n     * Offsets the character offset of the given {line, ch} pos by the given amount and returns a new\n     * pos. Not for general purpose use as it does not account for line boundaries.\n     */\n    function _offsetPos(pos, offset) {\n        return {line: pos.line, ch: pos.ch + offset};\n    }\n\n    /**\n     * A Builder creates a SimpleDOM tree of SimpleNode objects representing the\n     * \"important\" contents of an HTML document. It does not include things like comments.\n     * The nodes include information about their position in the text provided.\n     *\n     * @constructor\n     *\n     * @param {string} text The text to parse\n     * @param {?int} startOffset starting offset in the text\n     * @param {?{line: int, ch: int}} startOffsetPos line/ch position in the text\n     */\n    function Builder(text, startOffset, startOffsetPos) {\n        this.stack = [];\n        this.text = text;\n        this.t = new Tokenizer(text);\n        this.currentTag = null;\n        this.startOffset = startOffset || 0;\n        this.startOffsetPos = startOffsetPos || {line: 0, ch: 0};\n    }\n\n    Builder.prototype._logError = function (token) {\n        var error       = { token: token },\n            startPos    = token ? (token.startPos || token.endPos) : this.startOffsetPos,\n            endPos      = token ? token.endPos : this.startOffsetPos;\n\n        error.startPos = _addPos(this.startOffsetPos, startPos);\n        error.endPos = _addPos(this.startOffsetPos, endPos);\n\n        if (!this.errors) {\n            this.errors = [];\n        }\n\n        this.errors.push(error);\n    };\n\n    /**\n     * Builds the SimpleDOM.\n     *\n     * @param {?bool} strict if errors are detected, halt and return null\n     * @param {?Object} markCache a cache that can be used in ID generation (is passed to `getID`)\n     * @return {SimpleNode} root of tree or null if parsing failed\n     */\n    Builder.prototype.build = function (strict, markCache) {\n        var self = this;\n        var token, lastClosedTag, lastTextNode;\n        var stack = this.stack;\n        var attributeName = null;\n        var nodeMap = {};\n\n        markCache = markCache || {};\n\n        // Start timers for building full and partial DOMs.\n        // Appropriate timer is used, and the other is discarded.\n        var timerBuildFull = \"HTMLInstr. Build DOM Full\";\n        var timerBuildPart = \"HTMLInstr. Build DOM Partial\";\n        var timers; // timer handles\n        timers = PerfUtils.markStart([timerBuildFull, timerBuildPart]);\n        timerBuildFull = timers[0];\n        timerBuildPart = timers[1];\n\n        function closeTag(endIndex, endPos) {\n            lastClosedTag = stack[stack.length - 1];\n            stack.pop();\n            lastClosedTag.update();\n\n            lastClosedTag.end = self.startOffset + endIndex;\n            lastClosedTag.endPos = _addPos(self.startOffsetPos, endPos);\n        }\n\n        while ((token = this.t.nextToken()) !== null) {\n            // lastTextNode is used to glue text nodes together\n            // If the last node we saw was text but this one is not, then we're done gluing.\n            // If this node is a comment, we might still encounter more text.\n            if (token.type !== \"text\" && token.type !== \"comment\" && lastTextNode) {\n                lastTextNode = null;\n            }\n\n            if (token.type === \"error\") {\n                PerfUtils.finalizeMeasurement(timerBuildFull);  // discard\n                PerfUtils.addMeasurement(timerBuildPart);       // use\n                this._logError(token);\n                return null;\n            } else if (token.type === \"opentagname\") {\n                var newTagName = token.contents.toLowerCase(),\n                    newTag;\n\n                if (openImpliesClose.hasOwnProperty(newTagName)) {\n                    var closable = openImpliesClose[newTagName];\n                    while (stack.length > 0 && closable.hasOwnProperty(stack[stack.length - 1].tag)) {\n                        // Close the previous tag at the start of this tag.\n                        // Adjust backwards for the < before the tag name.\n                        closeTag(token.start - 1, _offsetPos(token.startPos, -1));\n                    }\n                }\n\n                newTag = new SimpleNode({\n                    tag: token.contents.toLowerCase(),\n                    children: [],\n                    attributes: {},\n                    parent: (stack.length ? stack[stack.length - 1] : null),\n                    start: this.startOffset + token.start - 1,\n                    startPos: _addPos(this.startOffsetPos, _offsetPos(token.startPos, -1)) // ok because we know the previous char was a \"<\"\n                });\n                newTag.tagID = this.getID(newTag, markCache);\n\n                // During undo in particular, it's possible that tag IDs may be reused and\n                // the marks in the document may be misleading. If a tag ID has been reused,\n                // we apply a new tag ID to ensure that our edits come out correctly.\n                if (nodeMap[newTag.tagID]) {\n                    newTag.tagID = this.getNewID();\n                }\n\n                nodeMap[newTag.tagID] = newTag;\n                if (newTag.parent) {\n                    newTag.parent.children.push(newTag);\n                }\n                this.currentTag = newTag;\n\n                if (voidElements.hasOwnProperty(newTag.tag)) {\n                    // This is a self-closing element.\n                    newTag.update();\n                } else {\n                    stack.push(newTag);\n                }\n            } else if (token.type === \"opentagend\" || token.type === \"selfclosingtag\") {\n                // TODO: disallow <p/>?\n                if (this.currentTag) {\n                    if (token.type === \"selfclosingtag\" && stack.length && stack[stack.length - 1] === this.currentTag) {\n                        // This must have been a self-closing tag that we didn't identify as a void element\n                        // (e.g. an SVG tag). Pop it off the stack as if we had encountered its close tag.\n                        closeTag(token.end, token.endPos);\n                    } else {\n                        // We're ending an open tag. Record the end of the open tag as the end of the\n                        // range. (If we later find a close tag for this tag, the end will get overwritten\n                        // with the end of the close tag. In the case of a self-closing tag, we should never\n                        // encounter that.)\n                        // Note that we don't need to update the signature here because the signature only\n                        // relies on the tag name and ID, and isn't affected by the tag's attributes, so\n                        // the signature we calculated when creating the tag is still the same. If we later\n                        // find a close tag for this tag, we'll update the signature to account for its\n                        // children at that point (in the next \"else\" case).\n                        this.currentTag.end = this.startOffset + token.end;\n                        this.currentTag.endPos = _addPos(this.startOffsetPos, token.endPos);\n                        lastClosedTag = this.currentTag;\n                        this.currentTag.updateAttributeSignature();\n                        this.currentTag = null;\n                    }\n                }\n            } else if (token.type === \"closetag\") {\n                // If this is a self-closing element, ignore the close tag.\n                var closeTagName = token.contents.toLowerCase();\n                if (!voidElements.hasOwnProperty(closeTagName)) {\n                    // Find the topmost item on the stack that matches. If we can't find one, assume\n                    // this is just a dangling closing tag and ignore it.\n                    var i;\n                    for (i = stack.length - 1; i >= 0; i--) {\n                        if (stack[i].tag === closeTagName) {\n                            break;\n                        }\n                    }\n                    if (i >= 0) {\n                        do {\n                            // For all tags we're implicitly closing (before we hit the matching tag), we want the\n                            // implied end to be the beginning of the close tag (which is two characters, \"</\", before\n                            // the start of the tagname). For the actual tag we're explicitly closing, we want the\n                            // implied end to be the end of the close tag (which is one character, \">\", after the end of\n                            // the tagname).\n                            if (stack.length === i + 1) {\n                                closeTag(token.end + 1, _offsetPos(token.endPos, 1));\n                            } else {\n                                if (strict && !optionalClose.hasOwnProperty(stack[stack.length - 1].tag)) {\n                                    // If we're in strict mode, treat unbalanced tags as invalid.\n                                    PerfUtils.finalizeMeasurement(timerBuildFull);\n                                    PerfUtils.addMeasurement(timerBuildPart);\n                                    this._logError(token);\n                                    return null;\n                                }\n                                closeTag(token.start - 2, _offsetPos(token.startPos, -2));\n                            }\n                        } while (stack.length > i);\n                    } else {\n                        // If we're in strict mode, treat unmatched close tags as invalid. Otherwise\n                        // we just silently ignore them.\n                        if (strict) {\n                            PerfUtils.finalizeMeasurement(timerBuildFull);\n                            PerfUtils.addMeasurement(timerBuildPart);\n                            this._logError(token);\n                            return null;\n                        }\n                    }\n                }\n            } else if (token.type === \"attribname\") {\n                attributeName = token.contents.toLowerCase();\n                // Set the value to the empty string in case this is an empty attribute. If it's not,\n                // it will get overwritten by the attribvalue later.\n                this.currentTag.attributes[attributeName] = \"\";\n            } else if (token.type === \"attribvalue\" && attributeName !== null) {\n                this.currentTag.attributes[attributeName] = token.contents;\n                attributeName = null;\n            } else if (token.type === \"text\") {\n                if (stack.length) {\n                    var parent = stack[stack.length - 1];\n                    var newNode;\n\n                    // Check to see if we're continuing a previous text.\n                    if (lastTextNode) {\n                        newNode = lastTextNode;\n                        newNode.content += token.contents;\n                    } else {\n                        newNode = new SimpleNode({\n                            parent: stack[stack.length - 1],\n                            content: token.contents\n                        });\n                        parent.children.push(newNode);\n                        newNode.tagID = getTextNodeID(newNode);\n                        nodeMap[newNode.tagID] = newNode;\n                        lastTextNode = newNode;\n                    }\n\n                    newNode.update();\n                }\n            }\n        }\n\n        // If we have any tags hanging open, fail the parse if we're in strict mode,\n        // otherwise close them at the end of the document.\n        while (stack.length) {\n            if (strict && !optionalClose.hasOwnProperty(stack[stack.length - 1].tag)) {\n                PerfUtils.finalizeMeasurement(timerBuildFull);\n                PerfUtils.addMeasurement(timerBuildPart);\n                this._logError(token);\n                return null;\n            }\n            closeTag(this.text.length, this.t._indexPos);\n        }\n\n        var dom = lastClosedTag;\n        if (!dom) {\n            // This can happen if the document has no nontrivial content, or if the user tries to\n            // have something at the root other than the HTML tag. In all such cases, we treat the\n            // document as invalid.\n            this._logError(token);\n            return null;\n        }\n\n        dom.nodeMap = nodeMap;\n        PerfUtils.addMeasurement(timerBuildFull);       // use\n        PerfUtils.finalizeMeasurement(timerBuildPart);  // discard\n\n        return dom;\n    };\n\n    /**\n     * Returns a new tag ID.\n     *\n     * @return {int} unique tag ID\n     */\n    Builder.prototype.getNewID = function () {\n        return tagID++;\n    };\n\n    /**\n     * Returns the best tag ID for the new tag object given.\n     * The default implementation just calls `getNewID`\n     * and returns a unique ID.\n     *\n     * @param {Object} newTag tag object to potentially inspect to choose an ID\n     * @return {int} unique tag ID\n     */\n    Builder.prototype.getID = Builder.prototype.getNewID;\n\n    /**\n     * Builds a SimpleDOM from the text provided. If `strict` mode is true, parsing\n     * will halt as soon as any error is seen and null will be returned.\n     *\n     * @param {string} text Text of document to parse\n     * @param {bool} strict True for strict parsing\n     * @return {SimpleNode} root of tree or null if strict failed\n     */\n    function build(text, strict) {\n        var builder = new Builder(text);\n        return builder.build(strict);\n    }\n\n    /**\n     * @private\n     *\n     * Generates a string version of a SimpleDOM for debugging purposes.\n     *\n     * @param {SimpleNode} root root of the tree\n     * @return {string} Text version of the tree.\n     */\n    function _dumpDOM(root) {\n        var result = \"\",\n            indent = \"\";\n\n        function walk(node) {\n            if (node.tag) {\n                result += indent + \"TAG \" + node.tagID + \" \" + node.tag + \" \" + JSON.stringify(node.attributes) + \"\\n\";\n            } else {\n                result += indent + \"TEXT \" + (node.tagID || \"- \") + node.content + \"\\n\";\n            }\n            if (node.isElement()) {\n                indent += \"  \";\n                node.children.forEach(walk);\n                indent = indent.slice(2);\n            }\n        }\n        walk(root);\n\n        return result;\n    }\n\n    // Public API\n    exports.build                       = build;\n    exports.Builder                     = Builder;\n    exports.SimpleNode                  = SimpleNode;\n\n    // Private API\n    exports._dumpDOM                    = _dumpDOM;\n    exports._offsetPos                  = _offsetPos;\n    exports._getTextNodeID              = getTextNodeID;\n    exports._seed                       = seed;\n});\n"
  },
  {
    "path": "src/language/HTMLTokenizer.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n// A simple HTML tokenizer, originally adapted from https://github.com/fb55/htmlparser2\n// (MIT-licensed), but with significant customizations for use in HTML live development.\n\n/*jslint continue: true */\n\n/*unittests: HTML Tokenizer*/\n\ndefine(function (require, exports, module) {\n\n    \"use strict\";\n    var i = 0,\n\n        TEXT = i++,\n        BEFORE_TAG_NAME = i++, //after <\n        IN_TAG_NAME = i++,\n        BEFORE_CLOSING_TAG_NAME = i++,\n        IN_CLOSING_TAG_NAME = i++,\n        AFTER_CLOSING_TAG_NAME = i++,\n        AFTER_SELFCLOSE_SLASH = i++,\n\n        //attributes\n        BEFORE_ATTRIBUTE_NAME = i++,\n        AFTER_QUOTED_ATTRIBUTE_VALUE = i++,\n        IN_ATTRIBUTE_NAME = i++,\n        AFTER_ATTRIBUTE_NAME = i++,\n        BEFORE_ATTRIBUTE_VALUE = i++,\n        IN_ATTRIBUTE_VALUE_DOUBLE_QUOTES = i++, // \"\n        IN_ATTRIBUTE_VALUE_SINGLE_QUOTES = i++, // '\n        IN_ATTRIBUTE_VALUE_NO_QUOTES = i++,\n\n        //declarations\n        BEFORE_DECLARATION = i++, // !\n        IN_DECLARATION = i++,\n\n        //processing instructions\n        IN_PROCESSING_INSTRUCTION = i++, // ?\n\n        //comments\n        BEFORE_COMMENT = i++,\n        IN_COMMENT = i++,\n        AFTER_COMMENT_1 = i++,\n        AFTER_COMMENT_2 = i++,\n\n        //cdata\n        BEFORE_CDATA_1 = i++, // [\n        BEFORE_CDATA_2 = i++, // C\n        BEFORE_CDATA_3 = i++, // D\n        BEFORE_CDATA_4 = i++, // A\n        BEFORE_CDATA_5 = i++, // T\n        BEFORE_CDATA_6 = i++, // A\n        IN_CDATA = i++,// [\n        AFTER_CDATA_1 = i++, // ]\n        AFTER_CDATA_2 = i++, // ]\n\n        //special tags\n        BEFORE_SPECIAL = i++, //S\n        BEFORE_SPECIAL_END = i++,   //S\n\n        BEFORE_SCRIPT_1 = i++, //C\n        BEFORE_SCRIPT_2 = i++, //R\n        BEFORE_SCRIPT_3 = i++, //I\n        BEFORE_SCRIPT_4 = i++, //P\n        BEFORE_SCRIPT_5 = i++, //T\n        AFTER_SCRIPT_1 = i++, //C\n        AFTER_SCRIPT_2 = i++, //R\n        AFTER_SCRIPT_3 = i++, //I\n        AFTER_SCRIPT_4 = i++, //P\n        AFTER_SCRIPT_5 = i++, //T\n\n        BEFORE_STYLE_1 = i++, //T\n        BEFORE_STYLE_2 = i++, //Y\n        BEFORE_STYLE_3 = i++, //L\n        BEFORE_STYLE_4 = i++, //E\n        AFTER_STYLE_1 = i++, //T\n        AFTER_STYLE_2 = i++, //Y\n        AFTER_STYLE_3 = i++, //L\n        AFTER_STYLE_4 = i++; //E\n\n    /**\n     * @private\n     * @param {string} c the character to test\n     * @return {boolean} true if c is whitespace\n     */\n    function isWhitespace(c) {\n        return c === \" \" || c === \"\\t\" || c === \"\\r\" || c === \"\\n\";\n    }\n\n    /**\n     * @private\n     * @param {string} c the character to test\n     * @return {boolean} true if c is legal in an HTML tag name\n     */\n    function isLegalInTagName(c) {\n        // We allow \"-\" in tag names since they're popular in Angular custom tag names\n        // and will be legal in the web components spec.\n        return (/[A-Za-z0-9\\-]/).test(c);\n    }\n\n    /**\n     * @private\n     * @param {string} c the character to test\n     * @return {boolean} true if c is legal in an HTML attribute name\n     */\n    function isLegalInAttributeName(c) {\n        return c !== '\"' && c !== \"'\" && c !== \"<\" && c !== \"=\";\n    }\n\n    /**\n     * @private\n     * @param {string} c the character to test\n     * @return {boolean} true if c is legal in an unquoted attribute value\n     */\n    function isLegalInUnquotedAttributeValue(c) {\n        return c !== \"<\" && c !== \"=\";\n    }\n\n    function _clonePos(pos, offset) {\n        return pos ? { line: pos.line, ch: pos.ch + (offset || 0)} : null;\n    }\n\n    /**\n     * A simple HTML tokenizer. See the description of nextToken() for usage details.\n     * @constructor\n     * @param {string} text The HTML document to tokenize.\n     */\n    function Tokenizer(text) {\n        this._state = TEXT;\n        this._buffer = text;\n        this._sectionStart = 0;\n        this._sectionStartPos = {line: 0, ch: 0};\n        this._index = 0;\n        this._indexPos = {line: 0, ch: 0};\n        this._special = 0; // 1 for script, 2 for style\n        this._token = null;\n        this._nextToken = null;\n    }\n\n    /**\n     * Returns the next token in the HTML document, or null if we're at the end of the document.\n     * @return {?{type: string, contents: string, start: number, end: number}} token The next token, with the following fields:\n     *    type: The type of token, one of:\n     *          \"error\" - invalid syntax was found, tokenization aborted. Calling nextToken() again will produce undefined results.\n     *          \"text\" - contents contains the text\n     *          \"opentagname\" - an open tag was started; contents contains the tag name\n     *          \"attribname\" - an attribute was encountered; contents contains the attribute name\n     *          \"attribvalue\" - the value for the previous attribname was encountered; contents contains the (unquoted) value\n     *              (Note that attributes like checked and disabled might not have values.)\n     *          \"opentagend\" - the end of an open tag was encountered; contents is unspecified\n     *          \"selfclosingtag\" - a \"/>\" was encountered indicating that a void element was self-closed; contents is unspecified\n     *              (Note that this is optional in HTML; void elements like <img> will end with \"opentagend\", not \"selfclosingtag\")\n     *          \"closetag\" - a close tag was encountered; contents contains the tag name\n     *          \"comment\" - a comment was encountered; contents contains the body of the comment\n     *          \"cdata\" - a CDATA block was encountered; contents contains the text inside the block\n     *    contents: the contents of the token, as specified above. Note that \"opentagend\" and \"selfclosingtag\" really specify positions,\n     *          not tokens, and so have no contents.\n     *    start: the start index of the token contents within the text, or -1 for \"opentagend\" and \"selfclosingtag\"\n     *    end: the end index of the token contents within the text, or the position of the boundary for \"opentagend\" and \"selfclosingtag\"\n     */\n    Tokenizer.prototype.nextToken = function () {\n        this._token = null;\n\n        if (this._nextToken) {\n            var result = this._nextToken;\n            this._nextToken = null;\n            return result;\n        }\n\n        while (this._index < this._buffer.length && !this._token) {\n            var c = this._buffer.charAt(this._index);\n            if (this._state === TEXT) {\n                if (c === \"<\") {\n                    this._emitTokenIfNonempty(\"text\");\n                    this._state = BEFORE_TAG_NAME;\n                    this._startSection();\n                }\n            } else if (this._state === BEFORE_TAG_NAME) {\n                if (c === \"/\") {\n                    this._state = BEFORE_CLOSING_TAG_NAME;\n                } else if (c === \">\" || this._special > 0) {\n                    this._state = TEXT;\n                } else {\n                    if (c === \"!\") {\n                        this._state = BEFORE_DECLARATION;\n                        this._startSection(1);\n                    } else if (c === \"?\") {\n                        this._state = IN_PROCESSING_INSTRUCTION;\n                        this._startSection(1);\n                    } else if (c === \"s\" || c === \"S\") {\n                        this._state = BEFORE_SPECIAL;\n                        this._startSection();\n                    } else if (!isLegalInTagName(c)) {\n                        this._emitSpecialToken(\"error\");\n                        break;\n                    } else if (!isWhitespace(c)) {\n                        this._state = IN_TAG_NAME;\n                        this._startSection();\n                    }\n                }\n            } else if (this._state === IN_TAG_NAME) {\n                if (c === \"/\") {\n                    this._emitToken(\"opentagname\");\n                    this._emitSpecialToken(\"selfclosingtag\", this._index + 2, _clonePos(this._indexPos, 2));\n                    this._state = AFTER_SELFCLOSE_SLASH;\n                } else if (c === \">\") {\n                    this._emitToken(\"opentagname\");\n                    this._emitSpecialToken(\"opentagend\", this._index + 1, _clonePos(this._indexPos, 1));\n                    this._state = TEXT;\n                    this._startSection(1);\n                } else if (isWhitespace(c)) {\n                    this._emitToken(\"opentagname\");\n                    this._state = BEFORE_ATTRIBUTE_NAME;\n                } else if (!isLegalInTagName(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n            } else if (this._state === BEFORE_CLOSING_TAG_NAME) {\n                if (c === \">\") {\n                    this._state = TEXT;\n                } else if (this._special > 0) {\n                    if (c === \"s\" || c === \"S\") {\n                        this._state = BEFORE_SPECIAL_END;\n                    } else {\n                        this._state = TEXT;\n                        continue;\n                    }\n                } else if (!isLegalInTagName(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                } else if (!isWhitespace(c)) {\n                    this._state = IN_CLOSING_TAG_NAME;\n                    this._startSection();\n                }\n            } else if (this._state === IN_CLOSING_TAG_NAME) {\n                if (c === \">\") {\n                    this._emitToken(\"closetag\");\n                    this._state = TEXT;\n                    this._startSection(1);\n                    this._special = 0;\n                } else if (isWhitespace(c)) {\n                    this._emitToken(\"closetag\");\n                    this._state = AFTER_CLOSING_TAG_NAME;\n                    this._special = 0;\n                } else if (!isLegalInTagName(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n            } else if (this._state === AFTER_CLOSING_TAG_NAME) {\n                if (c === \">\") {\n                    this._state = TEXT;\n                    this._startSection(1);\n                } else if (!isWhitespace(c)) {\n                    // There must be only whitespace in the closing tag after the name until the \">\".\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n            } else if (this._state === AFTER_SELFCLOSE_SLASH) {\n                // Nothing (even whitespace) can come between the / and > of a self-close.\n                if (c === \">\") {\n                    this._state = TEXT;\n                    this._startSection(1);\n                } else {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n\n            /*\n            *\tattributes\n            */\n            } else if (this._state === BEFORE_ATTRIBUTE_NAME) {\n                if (c === \">\") {\n                    this._state = TEXT;\n                    this._emitSpecialToken(\"opentagend\", this._index + 1, _clonePos(this._indexPos, 1));\n                    this._startSection(1);\n                } else if (c === \"/\") {\n                    this._emitSpecialToken(\"selfclosingtag\", this._index + 2, _clonePos(this._indexPos, 2));\n                    this._state = AFTER_SELFCLOSE_SLASH;\n                } else if (!isLegalInAttributeName(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                } else if (!isWhitespace(c)) {\n                    this._state = IN_ATTRIBUTE_NAME;\n                    this._startSection();\n                }\n            } else if (this._state === IN_ATTRIBUTE_NAME) {\n                if (c === \"=\") {\n                    this._emitTokenIfNonempty(\"attribname\");\n                    this._state = BEFORE_ATTRIBUTE_VALUE;\n                } else if (isWhitespace(c)) {\n                    this._emitTokenIfNonempty(\"attribname\");\n                    this._state = AFTER_ATTRIBUTE_NAME;\n                } else if (c === \"/\" || c === \">\") {\n                    this._emitTokenIfNonempty(\"attribname\");\n                    this._state = BEFORE_ATTRIBUTE_NAME;\n                    continue;\n                } else if (!isLegalInAttributeName(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n            } else if (this._state === AFTER_ATTRIBUTE_NAME) {\n                if (c === \"=\") {\n                    this._state = BEFORE_ATTRIBUTE_VALUE;\n                } else if (c === \"/\" || c === \">\") {\n                    this._state = BEFORE_ATTRIBUTE_NAME;\n                    continue;\n                } else if (!isLegalInAttributeName(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                } else if (!isWhitespace(c)) {\n                    this._state = IN_ATTRIBUTE_NAME;\n                    this._startSection();\n                }\n            } else if (this._state === BEFORE_ATTRIBUTE_VALUE) {\n                if (c === \"\\\"\") {\n                    this._state = IN_ATTRIBUTE_VALUE_DOUBLE_QUOTES;\n                    this._startSection(1);\n                } else if (c === \"'\") {\n                    this._state = IN_ATTRIBUTE_VALUE_SINGLE_QUOTES;\n                    this._startSection(1);\n                } else if (!isLegalInUnquotedAttributeValue(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                } else if (!isWhitespace(c)) {\n                    this._state = IN_ATTRIBUTE_VALUE_NO_QUOTES;\n                    this._startSection();\n                }\n            } else if (this._state === IN_ATTRIBUTE_VALUE_DOUBLE_QUOTES) {\n                if (c === \"\\\"\") {\n                    this._emitToken(\"attribvalue\");\n                    this._state = AFTER_QUOTED_ATTRIBUTE_VALUE;\n                }\n            } else if (this._state === IN_ATTRIBUTE_VALUE_SINGLE_QUOTES) {\n                if (c === \"'\") {\n                    this._state = AFTER_QUOTED_ATTRIBUTE_VALUE;\n                    this._emitToken(\"attribvalue\");\n                }\n            } else if (this._state === IN_ATTRIBUTE_VALUE_NO_QUOTES) {\n                if (c === \">\") {\n                    this._emitToken(\"attribvalue\");\n                    this._emitSpecialToken(\"opentagend\", this._index + 1, _clonePos(this._indexPos, 1));\n                    this._state = TEXT;\n                    this._startSection(1);\n                } else if (isWhitespace(c)) {\n                    this._emitToken(\"attribvalue\");\n                    this._state = BEFORE_ATTRIBUTE_NAME;\n                } else if (!isLegalInUnquotedAttributeValue(c)) {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n            } else if (this._state === AFTER_QUOTED_ATTRIBUTE_VALUE) {\n                // There must be at least one whitespace between the end of a quoted\n                // attribute value and the next attribute, if any.\n                if (c === \">\") {\n                    this._state = TEXT;\n                    this._emitSpecialToken(\"opentagend\", this._index + 1, _clonePos(this._indexPos, 1));\n                    this._startSection(1);\n                } else if (c === \"/\") {\n                    this._emitSpecialToken(\"selfclosingtag\", this._index + 2, _clonePos(this._indexPos, 2));\n                    this._state = AFTER_SELFCLOSE_SLASH;\n                } else if (isWhitespace(c)) {\n                    this._state = BEFORE_ATTRIBUTE_NAME;\n                } else {\n                    this._emitSpecialToken(\"error\");\n                    break;\n                }\n\n            /*\n            *\tdeclarations\n            */\n            } else if (this._state === BEFORE_DECLARATION) {\n                if (c === \"[\") {\n                    this._state = BEFORE_CDATA_1;\n                } else if (c === \"-\") {\n                    this._state = BEFORE_COMMENT;\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === IN_DECLARATION) {\n                if (c === \">\") {\n                    this._emitToken(\"declaration\");\n                    this._state = TEXT;\n                    this._startSection(1);\n                }\n\n\n            /*\n            *\tprocessing instructions\n            */\n            } else if (this._state === IN_PROCESSING_INSTRUCTION) {\n                if (c === \">\") {\n                    this._emitToken(\"processinginstruction\");\n                    this._state = TEXT;\n                    this._startSection(1);\n                }\n\n\n            /*\n            *\tcomments\n            */\n            } else if (this._state === BEFORE_COMMENT) {\n                if (c === \"-\") {\n                    this._state = IN_COMMENT;\n                    this._startSection(1);\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === IN_COMMENT) {\n                if (c === \"-\") {\n                    this._state = AFTER_COMMENT_1;\n                }\n            } else if (this._state === AFTER_COMMENT_1) {\n                if (c === \"-\") {\n                    this._state = AFTER_COMMENT_2;\n                } else {\n                    this._state = IN_COMMENT;\n                }\n            } else if (this._state === AFTER_COMMENT_2) {\n                if (c === \">\") {\n                    //remove 2 trailing chars\n                    // It should be okay to just decrement the char position by 2 because we know neither of the previous\n                    // characters is a newline.\n                    this._emitToken(\"comment\", this._index - 2, _clonePos(this._indexPos, -2));\n                    this._state = TEXT;\n                    this._startSection(1);\n                } else if (c !== \"-\") {\n                    this._state = IN_COMMENT;\n                }\n                // else: stay in AFTER_COMMENT_2 (`--->`)\n\n\n            /*\n            *\tcdata\n            */\n            } else if (this._state === BEFORE_CDATA_1) {\n                if (c === \"C\") {\n                    this._state = BEFORE_CDATA_2;\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === BEFORE_CDATA_2) {\n                if (c === \"D\") {\n                    this._state = BEFORE_CDATA_3;\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === BEFORE_CDATA_3) {\n                if (c === \"A\") {\n                    this._state = BEFORE_CDATA_4;\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === BEFORE_CDATA_4) {\n                if (c === \"T\") {\n                    this._state = BEFORE_CDATA_5;\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === BEFORE_CDATA_5) {\n                if (c === \"A\") {\n                    this._state = BEFORE_CDATA_6;\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === BEFORE_CDATA_6) {\n                if (c === \"[\") {\n                    this._state = IN_CDATA;\n                    this._startSection(1);\n                } else {\n                    this._state = IN_DECLARATION;\n                }\n            } else if (this._state === IN_CDATA) {\n                if (c === \"]\") {\n                    this._state = AFTER_CDATA_1;\n                }\n            } else if (this._state === AFTER_CDATA_1) {\n                if (c === \"]\") {\n                    this._state = AFTER_CDATA_2;\n                } else {\n                    this._state = IN_CDATA;\n                }\n            } else if (this._state === AFTER_CDATA_2) {\n                if (c === \">\") {\n                    //remove 2 trailing chars\n                    // It should be okay to just decrement the char position by 2 because we know neither of the previous\n                    // characters is a newline.\n                    this._emitToken(\"cdata\", this._index - 2, _clonePos(this._indexPos, -2));\n                    this._state = TEXT;\n                    this._startSection(1);\n                } else if (c !== \"]\") {\n                    this._state = IN_CDATA;\n                }\n                //else: stay in AFTER_CDATA_2 (`]]]>`)\n\n\n            /*\n            * special tags\n            */\n            } else if (this._state === BEFORE_SPECIAL) {\n                if (c === \"c\" || c === \"C\") {\n                    this._state = BEFORE_SCRIPT_1;\n                } else if (c === \"t\" || c === \"T\") {\n                    this._state = BEFORE_STYLE_1;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_SPECIAL_END) {\n                if (this._special === 1 && (c === \"c\" || c === \"C\")) {\n                    this._state = AFTER_SCRIPT_1;\n                } else if (this._special === 2 && (c === \"t\" || c === \"T\")) {\n                    this._state = AFTER_STYLE_1;\n                } else {\n                    this._state = TEXT;\n                }\n\n\n            /*\n            * script\n            */\n            } else if (this._state === BEFORE_SCRIPT_1) {\n                if (c === \"r\" || c === \"R\") {\n                    this._state = BEFORE_SCRIPT_2;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_SCRIPT_2) {\n                if (c === \"i\" || c === \"I\") {\n                    this._state = BEFORE_SCRIPT_3;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_SCRIPT_3) {\n                if (c === \"p\" || c === \"P\") {\n                    this._state = BEFORE_SCRIPT_4;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_SCRIPT_4) {\n                if (c === \"t\" || c === \"T\") {\n                    this._state = BEFORE_SCRIPT_5;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_SCRIPT_5) {\n                if (c === \"/\" || c === \">\" || isWhitespace(c)) {\n                    this._special = 1;\n                }\n                this._state = IN_TAG_NAME;\n                continue; //consume the token again\n            } else if (this._state === AFTER_SCRIPT_1) {\n                if (c === \"r\" || c === \"R\") {\n                    this._state = AFTER_SCRIPT_2;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_SCRIPT_2) {\n                if (c === \"i\" || c === \"I\") {\n                    this._state = AFTER_SCRIPT_3;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_SCRIPT_3) {\n                if (c === \"p\" || c === \"P\") {\n                    this._state = AFTER_SCRIPT_4;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_SCRIPT_4) {\n                if (c === \"t\" || c === \"T\") {\n                    this._state = AFTER_SCRIPT_5;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_SCRIPT_5) {\n                if (c === \">\" || isWhitespace(c)) {\n                    this._state = IN_CLOSING_TAG_NAME;\n                    this._startSection(-6);\n                    continue; //reconsume the token\n                } else {\n                    this._state = TEXT;\n                }\n\n\n            /*\n            * style\n            */\n            } else if (this._state === BEFORE_STYLE_1) {\n                if (c === \"y\" || c === \"Y\") {\n                    this._state = BEFORE_STYLE_2;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_STYLE_2) {\n                if (c === \"l\" || c === \"L\") {\n                    this._state = BEFORE_STYLE_3;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_STYLE_3) {\n                if (c === \"e\" || c === \"E\") {\n                    this._state = BEFORE_STYLE_4;\n                } else {\n                    this._state = IN_TAG_NAME;\n                    continue; //consume the token again\n                }\n            } else if (this._state === BEFORE_STYLE_4) {\n                if (c === \"/\" || c === \">\" || isWhitespace(c)) {\n                    this._special = 2;\n                }\n                this._state = IN_TAG_NAME;\n                continue; //consume the token again\n            } else if (this._state === AFTER_STYLE_1) {\n                if (c === \"y\" || c === \"Y\") {\n                    this._state = AFTER_STYLE_2;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_STYLE_2) {\n                if (c === \"l\" || c === \"L\") {\n                    this._state = AFTER_STYLE_3;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_STYLE_3) {\n                if (c === \"e\" || c === \"E\") {\n                    this._state = AFTER_STYLE_4;\n                } else {\n                    this._state = TEXT;\n                }\n            } else if (this._state === AFTER_STYLE_4) {\n                if (c === \">\" || isWhitespace(c)) {\n                    this._state = IN_CLOSING_TAG_NAME;\n                    this._startSection(-5);\n                    continue; //reconsume the token\n                } else {\n                    this._state = TEXT;\n                }\n            } else {\n                console.error(\"HTMLTokenizer: Encountered unknown state\");\n                this._emitSpecialToken(\"error\");\n                break;\n            }\n\n            if (c === \"\\n\") {\n                this._indexPos.line++;\n                this._indexPos.ch = 0;\n            } else {\n                this._indexPos.ch++;\n            }\n            this._index++;\n        }\n\n        if (!this._token) {\n            if (this._state !== TEXT) {\n                // We hit EOF in the middle of processing something else.\n                this._emitSpecialToken(\"error\");\n            } else {\n                this._emitTokenIfNonempty(\"text\");\n                this._startSection();\n            }\n        }\n        return this._token;\n    };\n\n    Tokenizer.prototype._startSection = function (offset) {\n        offset = offset || 0;\n        this._sectionStart = this._index + offset;\n\n        // Normally it wouldn't be safe to assume that we can just add the offset to the\n        // character position, because there might be a newline, which would require us to\n        // move to the next line. However, in all the cases where this is called, we are\n        // adjusting for characters that we know are not newlines.\n        this._sectionStartPos = _clonePos(this._indexPos, offset);\n    };\n\n    /**\n     * @private\n     * Extract the portion of the buffer since _sectionStart and set it to be the next token we return\n     * from `nextToken()`. If there's already a _token, we stuff it in _nextToken instead.\n     * @param {string} type The token's type (see documentation for `nextToken()`)\n     * @param {number} index If specified, the index to use as the end of the token; uses this._index if not specified\n     */\n    Tokenizer.prototype._setToken = function (type, index, indexPos) {\n        if (index === undefined) {\n            index = this._index;\n        }\n        if (indexPos === undefined) {\n            indexPos = this._indexPos;\n        }\n        var token = {\n            type: type,\n            contents: this._sectionStart === -1 ? \"\" : this._buffer.substring(this._sectionStart, index),\n            start: this._sectionStart,\n            end: index,\n            startPos: _clonePos(this._sectionStartPos),\n            endPos: _clonePos(indexPos)\n        };\n        if (this._token) {\n            // Queue this token to be emitted next. In theory it would be more general to have\n            // an arbitrary-length queue, but currently we only ever emit at most two tokens in a\n            // single pass through the tokenization loop.\n            if (this._nextToken) {\n                console.error(\"HTMLTokenizer: Tried to emit more than two tokens in a single call\");\n            }\n            this._nextToken = token;\n        } else {\n            this._token = token;\n        }\n    };\n\n    /**\n     * @private\n     * Sets the token to be returned from `nextToken()` and resets the section start to an invalid value.\n     * this._sectionStart should be set to a valid value before the next call to one of the `_emit` methods.\n     * @param {string} type The token's type (see documentation for `nextToken()`)\n     * @param {number} index If specified, the index to use as the end of the token; uses this._index if not specified\n     */\n    Tokenizer.prototype._emitToken = function (type, index, indexPos) {\n        this._setToken(type, index, indexPos);\n        this._sectionStart = -1;\n        this._sectionStartPos = null;\n    };\n\n    /**\n     * @private\n     * Like `_emitToken()`, but used for special tokens that don't have real content (like opentagend and selfclosingtag).\n     * @param {string} type The token's type (see documentation for `nextToken()`)\n     * @param {number} index If specified, the index to use as the end of the token; uses this._index if not specified\n     */\n    Tokenizer.prototype._emitSpecialToken = function (type, index, indexPos) {\n        // Force the section start to be -1, since these tokens don't have meaningful content--they're\n        // just marking particular boundaries we care about (end of an open tag or a self-closing tag).\n        this._sectionStart = -1;\n        this._sectionStartPos = null;\n        this._emitToken(type, index, indexPos);\n    };\n\n    /**\n     * @private\n     * Like `_emitToken()`, but only emits a token if there is actually content in it. Note that this still\n     * resets this._sectionStart to an invalid value even if there is no content, so a new section must be\n     * started before the next `_emit`.\n     * @param {string} type The token's type (see documentation for `nextToken()`)\n     */\n    Tokenizer.prototype._emitTokenIfNonempty = function (type) {\n        if (this._index > this._sectionStart) {\n            this._setToken(type);\n        }\n        this._sectionStart = -1;\n        this._sectionStartPos = null;\n    };\n\n    exports.Tokenizer = Tokenizer;\n});\n"
  },
  {
    "path": "src/language/HTMLUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CodeMirror = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        TokenUtils = require(\"utils/TokenUtils\");\n\n    // Constants\n    var TAG_NAME = \"tagName\",\n        CLOSING_TAG = \"closingTag\",\n        ATTR_NAME = \"attr.name\",\n        ATTR_VALUE = \"attr.value\";\n\n    // Regular expression for token types with \"tag\" prefixed\n    var tagPrefixedRegExp = /^tag/;\n\n   /**\n     * @private\n     * Sometimes as attr values are getting typed, if the quotes aren't balanced yet\n     * some extra 'non attribute value' text gets included in the token. This attempts\n     * to assure the attribute value we grab is always good\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return { val:{string}, offset:{number}}\n     */\n    function _extractAttrVal(ctx) {\n        var attrValue = ctx.token.string,\n            startChar = attrValue.charAt(0),\n            endChar = attrValue.charAt(attrValue.length - 1),\n            offset = TokenUtils.offsetInToken(ctx),\n            foundEqualSign = false;\n\n        //If this is a fully quoted value, return the whole\n        //thing regardless of position\n        if (attrValue.length > 1 &&\n                (startChar === \"'\" || startChar === '\"') &&\n                endChar === startChar) {\n\n            // Find an equal sign before the end quote. If found,\n            // then the user may be entering an attribute value right before\n            // another attribute and we're getting a false balanced string.\n            // An example of this case is <link rel\" href=\"foo\"> where the\n            // cursor is right after the first double quote.\n            foundEqualSign = (attrValue.match(/\\=\\s*['\"]$/) !== null);\n\n            if (!foundEqualSign) {\n                //strip the quotes and return;\n                attrValue = attrValue.substring(1, attrValue.length - 1);\n                offset = offset - 1 > attrValue.length ? attrValue.length : offset - 1;\n                return {val: attrValue, offset: offset, quoteChar: startChar, hasEndQuote: true};\n            }\n        }\n\n        if (foundEqualSign) {\n            var spaceIndex = attrValue.indexOf(\" \"),\n                bracketIndex = attrValue.indexOf(\">\"),\n                upToIndex = (spaceIndex !== -1 && spaceIndex < bracketIndex) ? spaceIndex : bracketIndex;\n            attrValue = attrValue.substring(0, (upToIndex > offset) ? upToIndex : offset);\n        } else if (offset > 0 && (startChar === \"'\" || startChar === '\"')) {\n            //The att value is getting edit in progress. There is possible extra\n            //stuff in this token state since the quote isn't closed, so we assume\n            //the stuff from the quote to the current pos is definitely in the attribute\n            //value.\n            attrValue = attrValue.substring(0, offset);\n        }\n\n        //If the attrValue start with a quote, trim that now\n        startChar = attrValue.charAt(0);\n        if (startChar === \"'\" || startChar === '\"') {\n            attrValue = attrValue.substring(1);\n            offset--;\n        } else {\n            startChar = \"\";\n            // Make attr value empty and set offset to zero if it has the \">\"\n            // which is the closing of the tag.\n            if (endChar === \">\") {\n                attrValue = \"\";\n                offset = 0;\n            }\n        }\n\n        return {val: attrValue, offset: offset, quoteChar: startChar, hasEndQuote: false};\n    }\n\n    /**\n     * @private\n     * Gets the tagname from where ever you are in the currect state\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string}\n     */\n    function _extractTagName(ctx) {\n        var mode = ctx.editor.getMode(),\n            innerModeData = CodeMirror.innerMode(mode, ctx.token.state);\n\n        if (ctx.token.type === \"tag bracket\") {\n            return innerModeData.state.tagName;\n        }\n\n        // If the ctx is inside the tag name of an end tag, innerModeData.state.tagName is\n        // undefined. So return token string as the tag name.\n        return innerModeData.state.tagName || ctx.token.string;\n    }\n\n    /**\n     * Compiles a list of used attributes for a given tag\n     * @param {CodeMirror} editor An instance of a CodeMirror editor\n     * @param {ch:{string}, line:{number}} pos A CodeMirror position\n     * @return {Array.<string>} A list of the used attributes inside the current tag\n     */\n    function getTagAttributes(editor, pos) {\n        var attrs       = [],\n            backwardCtx = TokenUtils.getInitialContext(editor._codeMirror, pos),\n            forwardCtx  = $.extend({}, backwardCtx);\n\n        if (editor.getModeForSelection() === \"html\") {\n            if (backwardCtx.token && !tagPrefixedRegExp.test(backwardCtx.token.type)) {\n                while (TokenUtils.movePrevToken(backwardCtx) && !tagPrefixedRegExp.test(backwardCtx.token.type)) {\n                    if (backwardCtx.token.type === \"error\" && backwardCtx.token.string.indexOf(\"<\") === 0) {\n                        break;\n                    }\n                    if (backwardCtx.token.type === \"attribute\") {\n                        attrs.push(backwardCtx.token.string);\n                    }\n                }\n\n                while (TokenUtils.moveNextToken(forwardCtx) && !tagPrefixedRegExp.test(forwardCtx.token.type)) {\n                    if (forwardCtx.token.type === \"attribute\") {\n                        // If the current tag is not closed, codemirror may return the next opening\n                        // tag as an attribute. Stop the search loop in that case.\n                        if (forwardCtx.token.string.indexOf(\"<\") === 0) {\n                            break;\n                        }\n                        attrs.push(forwardCtx.token.string);\n                    } else if (forwardCtx.token.type === \"error\") {\n                        if (forwardCtx.token.string.indexOf(\"<\") === 0 || forwardCtx.token.string.indexOf(\">\") === 0) {\n                            break;\n                        }\n                        // If we type the first letter of the next attribute, it comes as an error\n                        // token. We need to double check for possible invalidated attributes.\n                        if (/\\S/.test(forwardCtx.token.string) &&\n                                forwardCtx.token.string.indexOf(\"\\\"\") === -1 &&\n                                forwardCtx.token.string.indexOf(\"'\") === -1 &&\n                                forwardCtx.token.string.indexOf(\"=\") === -1) {\n                            attrs.push(forwardCtx.token.string);\n                        }\n                    }\n                }\n            }\n        }\n\n        return attrs;\n    }\n\n    /**\n     * Creates a tagInfo object and assures all the values are entered or are empty strings\n     * @param {string=} tokenType what is getting edited and should be hinted\n     * @param {number=} offset where the cursor is for the part getting hinted\n     * @param {string=} tagName The name of the tag\n     * @param {string=} attrName The name of the attribute\n     * @param {string=} attrValue The value of the attribute\n     * @return {{tagName:string,\n     *           attr:{name:string, value:string, valueAssigned:boolean, quoteChar:string, hasEndQuote:boolean},\n     *           position:{tokenType:string, offset:number}\n     *         }}\n     *         A tagInfo object with some context about the current tag hint.\n     */\n    function createTagInfo(tokenType, offset, tagName, attrName, attrValue, valueAssigned, quoteChar, hasEndQuote) {\n        return { tagName: tagName || \"\",\n                 attr:\n                    { name: attrName || \"\",\n                      value: attrValue || \"\",\n                      valueAssigned: valueAssigned || false,\n                      quoteChar: quoteChar || \"\",\n                      hasEndQuote: hasEndQuote || false },\n                 position:\n                    { tokenType: tokenType || \"\",\n                      offset: offset || 0 } };\n    }\n\n    /**\n     * @private\n     * Gets the taginfo starting from the attribute value and moving backwards\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string}\n     */\n    function _getTagInfoStartingFromAttrValue(ctx) {\n        // Assume we in the attr value\n        // and validate that by going backwards\n        var attrInfo = _extractAttrVal(ctx),\n            attrVal = attrInfo.val,\n            offset = attrInfo.offset,\n            quoteChar = attrInfo.quoteChar,\n            hasEndQuote = attrInfo.hasEndQuote,\n            strLength = ctx.token.string.length;\n\n        if ((ctx.token.type === \"string\" || ctx.token.type === \"error\") &&\n                ctx.pos.ch === ctx.token.end && strLength > 1) {\n            var firstChar = ctx.token.string[0],\n                lastChar = ctx.token.string[strLength - 1];\n\n            // We get here only when the cursor is immediately on the right of the end quote\n            // of an attribute value. So we want to return an empty tag info so that the caller\n            // can dismiss the code hint popup if it is still open.\n            if (firstChar === lastChar && (firstChar === \"'\" || firstChar === \"\\\"\")) {\n                return createTagInfo();\n            }\n        }\n        \n        //Skip all the 'string' tokens backwards. Required to reach to the first line \n        //of multiline HTML attribute value.\n        while (TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx)) {\n            if (ctx.token.type !== \"string\") {\n                break;\n            }\n        }\n\n        //As we have skipped all the string tokens, make a forward navigation to move to the\n        //first 'string token so that in next backward navigation we can find '='.\n        TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx);\n\n        //Move to the prev token, and check if it's \"=\"\n        if (!TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx) || ctx.token.string !== \"=\") {\n            return createTagInfo();\n        }\n\n        //Move to the prev token, and check if it's an attribute\n        if (!TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx) || ctx.token.type !== \"attribute\") {\n            return createTagInfo();\n        }\n\n        var attrName = ctx.token.string;\n        var tagName = _extractTagName(ctx);\n\n        //We're good.\n        return createTagInfo(ATTR_VALUE, offset, tagName, attrName, attrVal, true, quoteChar, hasEndQuote);\n    }\n\n    /**\n     * @private\n     * Gets the taginfo starting from the attribute name and moving forwards\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @param {boolean} isPriorAttr indicates whether we're getting info for a prior attribute\n     * @return {string}\n     */\n    function _getTagInfoStartingFromAttrName(ctx, isPriorAttr) {\n        //Verify We're in the attribute name, move forward and try to extract the rest of\n        //the info. If the user it typing the attr the rest might not be here\n        if (isPriorAttr === false && ctx.token.type !== \"attribute\") {\n            return createTagInfo();\n        }\n\n        var tagName = _extractTagName(ctx);\n        var attrName = ctx.token.string;\n        var offset = TokenUtils.offsetInToken(ctx);\n\n        if (!TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) || ctx.token.string !== \"=\") {\n            // If we're checking for a prior attribute and the next token we get is a tag or an html comment or\n            // an undefined token class, then we've already scanned past our original cursor location.\n            // So just return an empty tag info.\n            if (isPriorAttr &&\n                    (!ctx.token.type ||\n                    (ctx.token.type && ctx.token.type !== \"attribute\" &&\n                        ctx.token.type.indexOf(\"error\") === -1 &&\n                        ctx.token.string.indexOf(\"<\") !== -1))) {\n                return createTagInfo();\n            }\n            return createTagInfo(ATTR_NAME, offset, tagName, attrName);\n        }\n\n        if (!TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx)) {\n            return createTagInfo(ATTR_NAME, offset, tagName, attrName);\n        }\n        //this should be the attrvalue\n        var attrInfo = _extractAttrVal(ctx),\n            attrVal = attrInfo.val,\n            quoteChar = attrInfo.quoteChar,\n            hasEndQuote = attrInfo.hasEndQuote;\n\n        return createTagInfo(ATTR_NAME, offset, tagName, attrName, attrVal, true, quoteChar, hasEndQuote);\n    }\n\n    /**\n     * Figure out if we're in a tag, and if we are return info about it\n     * An example token stream for this tag is <span id=\"open-files-disclosure-arrow\"></span> :\n     *      className:tag       string:\"<span\"\n     *      className:          string:\" \"\n     *      className:attribute string:\"id\"\n     *      className:          string:\"=\"\n     *      className:string    string:\"\"open-files-disclosure-arrow\"\"\n     *      className:tag       string:\"></span>\"\n     * @param {Editor} editor An instance of a Brackets editor\n     * @param {{ch: number, line: number}} constPos  A CM pos (likely from editor.getCursorPos())\n     * @param {isHtmlMode:boolean} let the module know we are in html mode\n     * @return {{tagName:string,\n     *           attr:{name:string, value:string, valueAssigned:boolean, quoteChar:string, hasEndQuote:boolean},\n     *           position:{tokenType:string, offset:number}\n     *         }}\n     *         A tagInfo object with some context about the current tag hint.\n     */\n    function getTagInfo(editor, constPos, isHtmlMode) {\n        // We're going to be changing pos a lot, but we don't want to mess up\n        // the pos the caller passed in so we use extend to make a safe copy of it.\n        var pos = $.extend({}, constPos),\n            ctx = TokenUtils.getInitialContext(editor._codeMirror, pos),\n            offset = TokenUtils.offsetInToken(ctx),\n            tagInfo,\n            tokenType;\n\n        // Check if this is not known to be in html mode and inside a style block.\n        if (!isHtmlMode && editor.getModeForSelection() !== \"html\") {\n            return createTagInfo();\n        }\n\n        // Check and see where we are in the tag\n        if (ctx.token.string.length > 0 && !/\\S/.test(ctx.token.string)) {\n\n            // token at (i.e. before) pos is whitespace, so test token at next pos\n            //\n            // note: getTokenAt() does range checking for ch. If it detects that ch is past\n            // EOL, it uses EOL, same token is returned, and the following condition fails,\n            // so we don't need to worry about testPos being valid.\n            var testPos = {ch: ctx.pos.ch + 1, line: ctx.pos.line},\n                testToken = editor._codeMirror.getTokenAt(testPos, true);\n\n            if (testToken.string.length > 0 && /\\S/.test(testToken.string) &&\n                    testToken.string.charAt(0) !== \">\") {\n                // pos has whitespace before it and non-whitespace after it, so use token after\n                ctx.token = testToken;\n\n                // Check whether the token type is one of the types prefixed with \"tag\"\n                // (e.g. \"tag\", \"tag error\", \"tag brackets\")\n                if (tagPrefixedRegExp.test(ctx.token.type)) {\n                    // Check to see if the cursor is just before a \"<\" but not in any tag.\n                    if (ctx.token.string.charAt(0) === \"<\") {\n                        return createTagInfo();\n                    }\n                } else if (ctx.token.type === \"attribute\") {\n                    // Check to see if the user is going to add a new attr before an existing one\n                    return _getTagInfoStartingFromAttrName(ctx, false);\n                } else if (ctx.token.string === \"=\") {\n                    // We're between a whitespace and  \"=\", so return an empty tag info.\n                    return createTagInfo();\n                }\n            } else {\n                // We get here if \">\" or white spaces after testPos.\n                // Check if there is an equal sign after testPos by creating a new ctx\n                // with the original pos. We can't use the current ctx since we need to\n                // use it to scan backwards if we don't find an equal sign here.\n                // Comment out this block to fix issue #1510.\n//                if (testToken.string.length > 0 && testToken.string.charAt(0) !== \">\") {\n//                    tempCtx = TokenUtils.getInitialContext(editor._codeMirror, pos);\n//                    if (TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, tempCtx) && tempCtx.token.string === \"=\") {\n//                        // Return an empty tag info since we're between an atribute name and the equal sign.\n//                        return createTagInfo();\n//                    }\n//                }\n\n                // next, see what's before pos\n                if (!TokenUtils.movePrevToken(ctx)) {\n                    return createTagInfo();\n                }\n\n                if (ctx.token.type === \"comment\") {\n                    return createTagInfo();\n                } else if (!tagPrefixedRegExp.test(ctx.token.type) && ctx.token.string !== \"=\") {\n                    // If it wasn't the tag name, assume it was an attr value\n                    // Also we don't handle the \"=\" here.\n                    tagInfo = _getTagInfoStartingFromAttrValue(ctx);\n\n                    // Check to see if this is the closing of a tag (either the start or end)\n                    // or a comment tag.\n                    if (ctx.token.type === \"comment\" ||\n                            (tagPrefixedRegExp.test(ctx.token.type) &&\n                            (ctx.token.string === \">\" || ctx.token.string === \"/>\" ||\n                                ctx.token.string === \"</\"))) {\n                        return createTagInfo();\n                    }\n\n                    // If it wasn't an attr value, assume it was an empty attr (ie. attr with no value)\n                    if (!tagInfo.tagName) {\n                        tagInfo = _getTagInfoStartingFromAttrName(ctx, true);\n                    }\n\n                    // We don't want to give context for the previous attr\n                    // and we want it to look like the user is going to add a new attr\n                    if (tagInfo.tagName) {\n                        return createTagInfo(ATTR_NAME, 0, tagInfo.tagName);\n                    }\n                    return createTagInfo();\n                }\n\n                // We know the tag was here, so the user is adding an attr name\n                tokenType = ATTR_NAME;\n                offset = 0;\n            }\n        }\n\n        if (tagPrefixedRegExp.test(ctx.token.type)) {\n            if (ctx.token.type !== \"tag bracket\") {\n                // Check if the user just typed a white space after \"<\" that made an existing tag invalid.\n                if (TokenUtils.movePrevToken(ctx) && !/\\S/.test(ctx.token.string)) {\n                    return createTagInfo();\n                }\n\n                // Check to see if this is a closing tag\n                if (ctx.token.type === \"tag bracket\" && ctx.token.string === \"</\") {\n                    tokenType = CLOSING_TAG;\n                }\n\n                // Restore the original ctx by moving back to next context since we call\n                // movePrevToken above to detect \"<\" or \"</\".\n                TokenUtils.moveNextToken(ctx);\n            }\n\n            // Check to see if this is the closing of a start tag or a self closing tag\n            if (ctx.token.string === \">\" || ctx.token.string === \"/>\") {\n                return createTagInfo();\n            }\n\n            // Make sure the cursor is not after an equal sign or a quote before we report the context as a tag.\n            if (ctx.token.string !== \"=\" && ctx.token.string.match(/^[\"']/) === null) {\n                if (!tokenType) {\n                    tokenType = TAG_NAME;\n                    if (ctx.token.type === \"tag bracket\") {\n                        // Check to see if this is a closing tag\n                        if (ctx.token.string === \"</\") {\n                            tokenType = CLOSING_TAG;\n                            offset -= 2;\n                        } else {\n                            offset = 0;\n                        }\n                        // If the cursor is right after the \"<\" or \"</\", then\n                        // move context to next one so that _extractTagName\n                        // call below can get the tag name if there is one.\n                        if (offset === 0) {\n                            TokenUtils.moveNextToken(ctx);\n                        }\n                    }\n                }\n\n                // We're actually in the tag, just return that as we have no relevant\n                // info about what attr is selected\n                return createTagInfo(tokenType, offset, _extractTagName(ctx));\n            }\n        }\n\n        if (ctx.token.string === \"=\") {\n            // We could be between the attr and the value\n            // Step back and check\n            if (!TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx) || ctx.token.type !== \"attribute\") {\n                return createTagInfo();\n            }\n\n            // The \"=\" is added, time to hint for values\n            tokenType = ATTR_VALUE;\n            offset = 0;\n        }\n\n        if (ctx.token.type === \"attribute\") {\n            tagInfo = _getTagInfoStartingFromAttrName(ctx, false);\n\n            // If we're in attr value, then we may need to calculate the correct offset\n            // from the beginning of the attribute value. If the cursor position is to\n            // the left of attr value, then the offset is negative.\n            // e.g. if the cursor is just to the right of the \"=\" in <a rel= \"rtl\", then\n            // the offset will be -2.\n            if (tagInfo.attr.quoteChar) {\n                offset = constPos.ch - ctx.pos.ch;\n            } else if (tokenType === ATTR_VALUE && (constPos.ch + 1) < ctx.pos.ch) {\n                // The cursor may be right before an unquoted attribute or another attribute name.\n                // Since we can't distinguish between them, we will empty the value so that the\n                // caller can just insert a new attribute value.\n                tagInfo.attr.value = \"\";\n            }\n        } else {\n            // if we're not at a tag, \"=\", or attribute name, assume we're in the value\n            tagInfo = _getTagInfoStartingFromAttrValue(ctx);\n        }\n\n        if (tokenType && tagInfo.tagName) {\n            tagInfo.position.tokenType = tokenType;\n            tagInfo.position.offset = offset;\n        }\n\n        return tagInfo;\n    }\n\n\n\n    /**\n     * Returns an Array of info about all blocks whose token mode name matches that passed in,\n     * in the given Editor's HTML document (assumes the Editor contains HTML text).\n     * @param {!Editor} editor - the editor containing the HTML text\n     * @param {string} modeName - the mode name of the tokens to look for\n     * @return {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, text:string}>}\n     */\n    function findBlocks(editor, modeName) {\n        // Start scanning from beginning of file\n        var ctx = TokenUtils.getInitialContext(editor._codeMirror, {line: 0, ch: 0}),\n            blocks = [],\n            currentBlock = null,\n            inBlock = false,\n            outerMode = editor._codeMirror.getMode(),\n            tokenModeName,\n            previousMode;\n\n        while (TokenUtils.moveNextToken(ctx, false)) {\n            tokenModeName = CodeMirror.innerMode(outerMode, ctx.token.state).mode.name;\n            if (inBlock) {\n                if (!currentBlock.end) {\n                    // Handle empty blocks\n                    currentBlock.end = currentBlock.start;\n                }\n                // Check for end of this block\n                if (tokenModeName === previousMode) {\n                    // currentBlock.end is already set to pos of the last token by now\n                    currentBlock.text = editor.document.getRange(currentBlock.start, currentBlock.end);\n                    inBlock = false;\n                } else {\n                    currentBlock.end = { line: ctx.pos.line, ch: ctx.pos.ch };\n                }\n            } else {\n                // Check for start of a block\n                if (tokenModeName === modeName) {\n                    currentBlock = {\n                        start: { line: ctx.pos.line, ch: ctx.pos.ch }\n                    };\n                    blocks.push(currentBlock);\n                    inBlock = true;\n                } else {\n                    previousMode = tokenModeName;\n                }\n                // else, random token: ignore\n            }\n        }\n\n        return blocks;\n    }\n\n    /**\n     * Returns an Array of info about all <style> blocks in the given Editor's HTML document (assumes\n     * the Editor contains HTML text).\n     * @param {!Editor} editor\n     * @return {Array.<{start:{line:number, ch:number}, end:{line:number, ch:number}, text:string}>}\n     */\n    function findStyleBlocks(editor) {\n        return findBlocks(editor, \"css\");\n    }\n\n\n    // Define public API\n    exports.TAG_NAME         = TAG_NAME;\n    exports.CLOSING_TAG      = CLOSING_TAG;\n    exports.ATTR_NAME        = ATTR_NAME;\n    exports.ATTR_VALUE       = ATTR_VALUE;\n\n    exports.getTagInfo       = getTagInfo;\n    exports.getTagAttributes = getTagAttributes;\n    //The createTagInfo is really only for the unit tests so they can make the same structure to\n    //compare results with\n    exports.createTagInfo   = createTagInfo;\n    exports.findStyleBlocks = findStyleBlocks;\n    exports.findBlocks      = findBlocks;\n});\n"
  },
  {
    "path": "src/language/JSONUtils.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var TokenUtils      = require(\"utils/TokenUtils\");\n\n    // Enumerations for token types.\n    var TOKEN_KEY   = 1,\n        TOKEN_VALUE = 2;\n\n    // Whitelist for allowed value types.\n    var valueTokenTypes = [\"atom\", \"string\", \"number\", \"variable\"];\n\n    // Reg-ex to match colon, comma, opening bracket of an array and white-space.\n    var regexAllowedChars = /(?:^[:,\\[]$)|(?:^\\s+$)/;\n\n    /**\n     * @private\n     *\n     * Returns an object that represents all its parameters\n     *\n     * @param {!Object} token CodeMirror token\n     * @param {!number} tokenType Type of current token\n     * @param {!number} offset Offset in current token\n     * @param {!String} keyName Name of corresponding key\n     * @param {String} valueName Name of current value\n     * @param {String} parentKeyName Name of parent key name\n     * @param {Boolean} isArray Whether or not we are inside an array\n     * @param {Array.<String>} exclusionList An array of keys that have already been used in the context of an object\n     * @param {Boolean} shouldReplace Should we just replace the current token or also add colons/braces/brackets to it\n     * @return {!{token: Object, tokenType: number, offset: number, keyName: String, valueName: String, parentKeyName: String, isArray: Boolean, exclusionList: Array.<String>, shouldReplace: Boolean}}\n     */\n    function _createContextInfo(token, tokenType, offset, keyName, valueName, parentKeyName, isArray, exclusionList, shouldReplace) {\n        return {\n            token: token || null,\n            tokenType: tokenType || null,\n            offset: offset || 0,\n            keyName: keyName || null,\n            valueName: valueName || null,\n            parentKeyName: parentKeyName || null,\n            isArray: isArray || false,\n            exclusionList: exclusionList || [],\n            shouldReplace: shouldReplace || false\n        };\n    }\n\n    /**\n     * Removes the quotes around a string\n     *\n     * @param {!String} string\n     * @return {String}\n     */\n    function stripQuotes(string) {\n        if (string) {\n            if (/^['\"]$/.test(string.charAt(0))) {\n                string = string.substr(1);\n            }\n            if (/^['\"]$/.test(string.substr(-1, 1))) {\n                string = string.substr(0, string.length - 1);\n            }\n        }\n        return string;\n    }\n\n    /**\n     * @private\n     *\n     * Returns the name of parent object\n     *\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} ctx\n     * @return {String}\n     */\n    function _getParentKeyName(ctx) {\n        var parentKeyName, braceParity = 1, hasColon;\n\n        // Move the context back to find the parent key.\n        while (TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx)) {\n            if (ctx.token.type === null) {\n                if (ctx.token.string === \"}\") {\n                    braceParity++;\n                } else if (ctx.token.string === \"{\") {\n                    braceParity--;\n                }\n            }\n\n            if (braceParity === 0) {\n                while (TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx)) {\n                    if (ctx.token.type === null && ctx.token.string === \":\") {\n                        hasColon = true;\n                    } else if (ctx.token.type === \"string property\") {\n                        parentKeyName = stripQuotes(ctx.token.string);\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n\n        if (parentKeyName && hasColon) {\n            return parentKeyName;\n        }\n        return null;\n    }\n\n    /**\n     * @private\n     *\n     * Returns a list of properties that are already used by an object\n     *\n     * @param {!Editor} editor\n     * @param {!{line: number, ch: number}} constPos\n     * @return {Array.<String>}\n     */\n    function _getExclusionList(editor, constPos) {\n        var ctxPrev, ctxNext, exclusionList = [], pos, braceParity;\n\n        // Move back to find exclusions.\n        pos = $.extend({}, constPos);\n        braceParity = 1;\n        ctxPrev = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        while (TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctxPrev)) {\n            if (ctxPrev.token.type === null) {\n                if (ctxPrev.token.string === \"}\") {\n                    braceParity++;\n                } else if (ctxPrev.token.string === \"{\") {\n                    braceParity--;\n                }\n            }\n\n            if (braceParity === 1 && ctxPrev.token.type === \"string property\") {\n                exclusionList.push(stripQuotes(ctxPrev.token.string));\n            } else if (braceParity === 0) {\n                break;\n            }\n        }\n\n        // Move forward and find exclusions.\n        pos = $.extend({}, constPos);\n        braceParity = 1;\n        ctxNext = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        while (TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctxNext)) {\n            if (ctxNext.token.type === null) {\n                if (ctxNext.token.string === \"{\") {\n                    braceParity++;\n                } else if (ctxNext.token.string === \"}\") {\n                    braceParity--;\n                }\n            }\n\n            if (braceParity === 1 && ctxNext.token.type === \"string property\") {\n                exclusionList.push(stripQuotes(ctxNext.token.string));\n            } else if (braceParity === 0) {\n                break;\n            }\n        }\n\n        return exclusionList;\n    }\n\n    /**\n     * Returns context info at a given position in editor\n     *\n     * @param {!Editor} editor\n     * @param {!{line: number, ch: number}} constPos Position of cursor in the editor\n     * @param {Boolean} requireParent If true will look for parent key name\n     * @param {Boolean} requireNextToken if true we can replace the next token of a value.\n     * @return {!{token: Object, tokenType: number, offset: number, keyName: String, valueName: String, parentKeyName: String, isArray: Boolean, exclusionList: Array.<String>, shouldReplace: Boolean}}\n     */\n    function getContextInfo(editor, constPos, requireParent, requireNextToken) {\n        var pos, ctx, ctxPrev, ctxNext, offset, keyName, valueName, parentKeyName,\n            isArray, exclusionList, hasColon, hasComma, hasBracket, shouldReplace;\n\n        pos = $.extend({}, constPos);\n        ctx = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        offset = TokenUtils.offsetInToken(ctx);\n\n        if (ctx.token && ctx.token.type === \"string property\") {\n            // String literals used as keys.\n\n            // Disallow hints if cursor is out of the string.\n            if (/^['\"]$/.test(ctx.token.string.substr(-1, 1)) &&\n                    ctx.token.string.length !== 1 && ctx.token.end === pos.ch) {\n                return null;\n            }\n            keyName = stripQuotes(ctx.token.string);\n\n            // Get parent key name.\n            if (requireParent) {\n                ctxPrev = $.extend(true, {}, ctx);\n                parentKeyName = stripQuotes(_getParentKeyName(ctxPrev));\n            }\n\n            // Check if the key is followed by a colon, so we should not append colon again.\n            ctxNext = $.extend(true, {}, ctx);\n            TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctxNext);\n            if (ctxNext.token.type === null && ctxNext.token.string === \":\") {\n                shouldReplace = true;\n            }\n\n            // Get an exclusion list of properties.\n            pos = $.extend({}, constPos);\n            exclusionList = _getExclusionList(editor, pos);\n\n            return _createContextInfo(ctx.token, TOKEN_KEY, offset, keyName, valueName, parentKeyName, null, exclusionList, shouldReplace);\n        } else if (ctx.token && (valueTokenTypes.indexOf(ctx.token.type) !== -1 ||\n                                (ctx.token.type === null && regexAllowedChars.test(ctx.token.string)))) {\n            // Boolean, String, Number and variable literal values.\n\n            // Disallow hints if cursor is out of the string.\n            if (ctx.token.type === \"string\" && /^['\"]$/.test(ctx.token.string.substr(-1, 1)) &&\n                    ctx.token.string.length !== 1 && ctx.token.end === pos.ch) {\n                return null;\n            }\n            valueName = ctx.token.string;\n\n            // Check the current token\n            if (ctx.token.type === null) {\n                if (ctx.token.string === \":\") {\n                    hasColon = true;\n                } else if (ctx.token.string === \",\") {\n                    hasComma = true;\n                } else if (ctx.token.string === \"[\") {\n                    hasBracket = true;\n                }\n            }\n\n            // move context back and find corresponding key name.\n            ctxPrev = $.extend(true, {}, ctx);\n            while (TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctxPrev)) {\n                if (ctxPrev.token.type === \"string property\") {\n                    keyName = stripQuotes(ctxPrev.token.string);\n                    break;\n                } else if (ctxPrev.token.type === null) {\n                    if (ctxPrev.token.string === \":\") {\n                        hasColon = true;\n                    } else if (ctxPrev.token.string === \",\") {\n                        hasComma = true;\n                    } else if (ctxPrev.token.string === \"[\") {\n                        hasBracket = true;\n                    } else {\n                        return null;\n                    }\n                } else if (!hasComma) {\n                    return null;\n                }\n            }\n\n            // If no key name or colon found OR\n            // If we have a comma but no opening bracket, return null.\n            if ((!keyName || !hasColon) || (hasComma && !hasBracket)) {\n                return null;\n            } else {\n                isArray = hasBracket;\n            }\n\n            // Get parent key name.\n            if (requireParent) {\n                ctxPrev = $.extend(true, {}, ctx);\n                parentKeyName = stripQuotes(_getParentKeyName(ctxPrev));\n            }\n\n            // Check if we can replace the next token of a value.\n            ctxNext = $.extend(true, {}, ctx);\n            TokenUtils.moveNextToken(ctxNext);\n            if (requireNextToken && valueTokenTypes.indexOf(ctxNext.token.type) !== -1) {\n                shouldReplace = true;\n            }\n\n            return _createContextInfo((shouldReplace) ? ctxNext.token : ctx.token, TOKEN_VALUE, offset, keyName, valueName, parentKeyName, isArray, null, shouldReplace);\n        }\n\n        return null;\n    }\n\n    // Expose public API.\n    exports.TOKEN_KEY           = TOKEN_KEY;\n    exports.TOKEN_VALUE         = TOKEN_VALUE;\n    exports.regexAllowedChars   = regexAllowedChars;\n    exports.getContextInfo      = getContextInfo;\n    exports.stripQuotes         = stripQuotes;\n});\n"
  },
  {
    "path": "src/language/JSUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Set of utilities for simple parsing of JS text.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _          = require(\"thirdparty/lodash\"),\n        Acorn      = require(\"thirdparty/acorn/dist/acorn\"),\n        AcornLoose = require(\"thirdparty/acorn/dist/acorn_loose\"),\n        ASTWalker  = require(\"thirdparty/acorn/dist/walk\");\n\n    // Load brackets modules\n    var CodeMirror              = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        Async                   = require(\"utils/Async\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        ChangedDocumentTracker  = require(\"document/ChangedDocumentTracker\"),\n        FileSystem              = require(\"filesystem/FileSystem\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        StringUtils             = require(\"utils/StringUtils\");\n\n    /**\n     * Tracks dirty documents between invocations of findMatchingFunctions.\n     * @type {ChangedDocumentTracker}\n     */\n    var _changedDocumentTracker = new ChangedDocumentTracker();\n\n    /**\n     * @private\n     * Return an object mapping function name to offset info for all functions in the specified text.\n     * Offset info is an array, since multiple functions of the same name can exist.\n     * @param {!string} text Document text\n     * @return {Object.<string, Array.<{offsetStart: number, offsetEnd: number}>}\n     */\n    function _findAllFunctionsInText(text) {\n        var AST,\n            results = {},\n            functionName,\n            resultNode,\n            memberPrefix,\n            match;\n   \n        PerfUtils.markStart(PerfUtils.JSUTILS_REGEXP);\n        \n        try {\n            AST = Acorn.parse(text, {locations: true});\n        } catch (e) {\n            AST = AcornLoose.parse_dammit(text, {locations: true});\n        }\n        \n        function _addResult(node, offset, prefix) {\n            memberPrefix = prefix ? prefix + \" - \" : \"\";\n            resultNode = node.id || node.key || node;\n            functionName = resultNode.name;\n            if (!Array.isArray(results[functionName])) {\n                results[functionName] = [];\n            }\n\n            results[functionName].push(\n                {\n                    offsetStart: offset || node.start,\n                    label: memberPrefix ? memberPrefix + functionName : null,\n                    location: resultNode.loc\n                }\n            );\n        }\n        \n        ASTWalker.simple(AST, {\n            /*\n                function <functionName> () {}\n            */\n            FunctionDeclaration: function (node) {\n                // As acorn_loose marks identifier names with '✖' under erroneous declarations\n                // we should have a check to discard such 'FunctionDeclaration' nodes\n                if (node.id.name !== '✖') {\n                    _addResult(node);\n                }\n            },\n            /*\n                class <className> () {}\n            */\n            ClassDeclaration: function (node) {\n                _addResult(node);\n                ASTWalker.simple(node, {\n                    /*\n                        class <className> () {\n                            <methodName> () {\n                            \n                            }\n                        }\n                    */\n                    MethodDefinition: function (methodNode) {\n                        _addResult(methodNode, methodNode.key.start, node.id.name);\n                    }\n                });\n            },\n            /*\n                var <functionName> = function () {} \n                \n                or \n                \n                var <functionName> = () => {}\n            */\n            VariableDeclarator: function (node) {\n                if (node.init && (node.init.type === \"FunctionExpression\" || node.init.type === \"ArrowFunctionExpression\")) {\n                    _addResult(node);\n                }\n            },\n            /*\n                SomeFunction.prototype.<functionName> = function () {}\n            */\n            AssignmentExpression: function (node) {\n                if (node.right && node.right.type === \"FunctionExpression\") {\n                    if (node.left && node.left.type === \"MemberExpression\" && node.left.property) {\n                        _addResult(node.left.property);\n                    }\n                }\n            },\n            /*\n                {\n                    <functionName>: function() {}\n                }\n            */\n            Property: function (node) {\n                if (node.value && node.value.type === \"FunctionExpression\") {\n                    if (node.key && node.key.type === \"Identifier\") {\n                        _addResult(node.key);\n                    }\n                }\n            },\n            /*\n                <functionName>: function() {}\n            */\n            LabeledStatement: function (node) {\n                if (node.body && node.body.type === \"FunctionDeclaration\") {\n                    if (node.label) {\n                        _addResult(node.label);\n                    }\n                }\n            }\n        });\n\n        PerfUtils.addMeasurement(PerfUtils.JSUTILS_REGEXP);\n\n        return results;\n    }\n\n    // Given the start offset of a function definition (before the opening brace), find\n    // the end offset for the function (the closing \"}\"). Returns the position one past the\n    // close brace. Properly ignores braces inside comments, strings, and regexp literals.\n    function _getFunctionEndOffset(text, offsetStart) {\n        var mode = CodeMirror.getMode({}, \"javascript\");\n        var state = CodeMirror.startState(mode), stream, style, token;\n        var curOffset = offsetStart, length = text.length, blockCount = 0, lineStart;\n        var foundStartBrace = false;\n\n        // Get a stream for the next line, and update curOffset and lineStart to point to the\n        // beginning of that next line. Returns false if we're at the end of the text.\n        function nextLine() {\n            if (stream) {\n                curOffset++; // account for \\n\n                if (curOffset >= length) {\n                    return false;\n                }\n            }\n            lineStart = curOffset;\n            var lineEnd = text.indexOf(\"\\n\", lineStart);\n            if (lineEnd === -1) {\n                lineEnd = length;\n            }\n            stream = new CodeMirror.StringStream(text.slice(curOffset, lineEnd));\n            return true;\n        }\n\n        // Get the next token, updating the style and token to refer to the current\n        // token, and updating the curOffset to point to the end of the token (relative\n        // to the start of the original text).\n        function nextToken() {\n            if (curOffset >= length) {\n                return false;\n            }\n            if (stream) {\n                // Set the start of the next token to the current stream position.\n                stream.start = stream.pos;\n            }\n            while (!stream || stream.eol()) {\n                if (!nextLine()) {\n                    return false;\n                }\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            curOffset = lineStart + stream.pos;\n            return true;\n        }\n\n        while (nextToken()) {\n            if (style !== \"comment\" && style !== \"regexp\" && style !== \"string\" && style !== \"string-2\") {\n                if (token === \"{\") {\n                    foundStartBrace = true;\n                    blockCount++;\n                } else if (token === \"}\") {\n                    blockCount--;\n                }\n            }\n\n            // blockCount starts at 0, so we don't want to check if it hits 0\n            // again until we've actually gone past the start of the function body.\n            if (foundStartBrace && blockCount <= 0) {\n                return curOffset;\n            }\n        }\n\n        // Shouldn't get here, but if we do, return the end of the text as the offset.\n        return length;\n    }\n\n    /**\n     * @private\n     * Computes function offsetEnd, lineStart and lineEnd. Appends a result record to rangeResults.\n     * @param {!Document} doc\n     * @param {!string} functionName\n     * @param {!Array.<{offsetStart: number, offsetEnd: number}>} functions\n     * @param {!Array.<{document: Document, name: string, lineStart: number, lineEnd: number}>} rangeResults\n     */\n    function _computeOffsets(doc, functionName, functions, rangeResults) {\n        var text    = doc.getText(),\n            lines   = StringUtils.getLines(text);\n\n        functions.forEach(function (funcEntry) {\n            if (!funcEntry.offsetEnd) {\n                PerfUtils.markStart(PerfUtils.JSUTILS_END_OFFSET);\n\n                funcEntry.offsetEnd = _getFunctionEndOffset(text, funcEntry.offsetStart);\n                funcEntry.lineStart = StringUtils.offsetToLineNum(lines, funcEntry.offsetStart);\n                funcEntry.lineEnd   = StringUtils.offsetToLineNum(lines, funcEntry.offsetEnd);\n\n                PerfUtils.addMeasurement(PerfUtils.JSUTILS_END_OFFSET);\n            }\n\n            rangeResults.push({\n                document:   doc,\n                name:       functionName,\n                lineStart:  funcEntry.lineStart,\n                lineEnd:    funcEntry.lineEnd\n            });\n        });\n    }\n\n    /**\n     * @private\n     * Read a file and build a function list. Result is cached in fileInfo.\n     * @param {!FileInfo} fileInfo File to parse\n     * @param {!$.Deferred} result Deferred to resolve with all functions found and the document\n     */\n    function _readFile(fileInfo, result) {\n        DocumentManager.getDocumentForPath(fileInfo.fullPath)\n            .done(function (doc) {\n                var allFunctions = _findAllFunctionsInText(doc.getText());\n\n                // Cache the result in the fileInfo object\n                fileInfo.JSUtils = {};\n                fileInfo.JSUtils.functions = allFunctions;\n                fileInfo.JSUtils.timestamp = doc.diskTimestamp;\n\n                result.resolve({doc: doc, functions: allFunctions});\n            })\n            .fail(function (error) {\n                result.reject(error);\n            });\n    }\n\n    /**\n     * Determines if the document function cache is up to date.\n     * @param {FileInfo} fileInfo\n     * @return {$.Promise} A promise resolved with true with true when a function cache is available for the document. Resolves\n     *   with false when there is no cache or the cache is stale.\n     */\n    function _shouldGetFromCache(fileInfo) {\n        var result = new $.Deferred(),\n            isChanged = _changedDocumentTracker.isPathChanged(fileInfo.fullPath);\n\n        if (isChanged && fileInfo.JSUtils) {\n            // See if it's dirty and in the working set first\n            var doc = DocumentManager.getOpenDocumentForPath(fileInfo.fullPath);\n\n            if (doc && doc.isDirty) {\n                result.resolve(false);\n            } else {\n                // If a cache exists, check the timestamp on disk\n                var file = FileSystem.getFileForPath(fileInfo.fullPath);\n\n                file.stat(function (err, stat) {\n                    if (!err) {\n                        result.resolve(fileInfo.JSUtils.timestamp.getTime() === stat.mtime.getTime());\n                    } else {\n                        result.reject(err);\n                    }\n                });\n            }\n        } else {\n            // Use the cache if the file did not change and the cache exists\n            result.resolve(!isChanged && fileInfo.JSUtils);\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Compute lineStart and lineEnd for each matched function\n     * @param {!Array.<{doc: Document, fileInfo: FileInfo, functions: Array.<offsetStart: number, offsetEnd: number>}>} docEntries\n     * @param {!string} functionName\n     * @param {!Array.<document: Document, name: string, lineStart: number, lineEnd: number>} rangeResults\n     * @return {$.Promise} A promise resolved with an array of document ranges to populate a MultiRangeInlineEditor.\n     */\n    function _getOffsetsForFunction(docEntries, functionName) {\n        // Filter for documents that contain the named function\n        var result              = new $.Deferred(),\n            matchedDocuments    = [],\n            rangeResults        = [];\n\n        docEntries.forEach(function (docEntry) {\n            // Need to call _.has here since docEntry.functions could have an\n            // entry for \"hasOwnProperty\", which results in an error if trying\n            // to invoke docEntry.functions.hasOwnProperty().\n            if (_.has(docEntry.functions, functionName)) {\n                var functionsInDocument = docEntry.functions[functionName];\n                matchedDocuments.push({doc: docEntry.doc, fileInfo: docEntry.fileInfo, functions: functionsInDocument});\n            }\n        });\n\n        Async.doInParallel(matchedDocuments, function (docEntry) {\n            var doc         = docEntry.doc,\n                oneResult   = new $.Deferred();\n\n            // doc will be undefined if we hit the cache\n            if (!doc) {\n                DocumentManager.getDocumentForPath(docEntry.fileInfo.fullPath)\n                    .done(function (fetchedDoc) {\n                        _computeOffsets(fetchedDoc, functionName, docEntry.functions, rangeResults);\n                    })\n                    .always(function () {\n                        oneResult.resolve();\n                    });\n            } else {\n                _computeOffsets(doc, functionName, docEntry.functions, rangeResults);\n                oneResult.resolve();\n            }\n\n            return oneResult.promise();\n        }).done(function () {\n            result.resolve(rangeResults);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Resolves with a record containing the Document or FileInfo and an Array of all\n     * function names with offsets for the specified file. Results may be cached.\n     * @param {FileInfo} fileInfo\n     * @return {$.Promise} A promise resolved with a document info object that\n     *   contains a map of all function names from the document and each function's start offset.\n     */\n    function _getFunctionsForFile(fileInfo) {\n        var result = new $.Deferred();\n\n        _shouldGetFromCache(fileInfo)\n            .done(function (useCache) {\n                if (useCache) {\n                    // Return cached data. doc property is undefined since we hit the cache.\n                    // _getOffsets() will fetch the Document if necessary.\n                    result.resolve({/*doc: undefined,*/fileInfo: fileInfo, functions: fileInfo.JSUtils.functions});\n                } else {\n                    _readFile(fileInfo, result);\n                }\n            }).fail(function (err) {\n                result.reject(err);\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Get all functions for each FileInfo.\n     * @param {Array.<FileInfo>} fileInfos\n     * @return {$.Promise} A promise resolved with an array of document info objects that each\n     *   contain a map of all function names from the document and each function's start offset.\n     */\n    function _getFunctionsInFiles(fileInfos) {\n        var result      = new $.Deferred(),\n            docEntries  = [];\n\n        PerfUtils.markStart(PerfUtils.JSUTILS_GET_ALL_FUNCTIONS);\n\n        Async.doInParallel(fileInfos, function (fileInfo) {\n            var oneResult = new $.Deferred();\n\n            _getFunctionsForFile(fileInfo)\n                .done(function (docInfo) {\n                    docEntries.push(docInfo);\n                })\n                .always(function (error) {\n                    // If one file fails, continue to search\n                    oneResult.resolve();\n                });\n\n            return oneResult.promise();\n        }).always(function () {\n            // Reset ChangedDocumentTracker now that the cache is up to date.\n            _changedDocumentTracker.reset();\n\n            PerfUtils.addMeasurement(PerfUtils.JSUTILS_GET_ALL_FUNCTIONS);\n            result.resolve(docEntries);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Return all functions that have the specified name, searching across all the given files.\n     *\n     * @param {!String} functionName The name to match.\n     * @param {!Array.<File>} fileInfos The array of files to search.\n     * @param {boolean=} keepAllFiles If true, don't ignore non-javascript files.\n     * @return {$.Promise} that will be resolved with an Array of objects containing the\n     *      source document, start line, and end line (0-based, inclusive range) for each matching function list.\n     *      Does not addRef() the documents returned in the array.\n     */\n    function findMatchingFunctions(functionName, fileInfos, keepAllFiles) {\n        var result  = new $.Deferred(),\n            jsFiles = [];\n\n        if (!keepAllFiles) {\n            // Filter fileInfos for .js files\n            jsFiles = fileInfos.filter(function (fileInfo) {\n                return FileUtils.getFileExtension(fileInfo.fullPath).toLowerCase() === \"js\";\n            });\n        } else {\n            jsFiles = fileInfos;\n        }\n\n        // RegExp search (or cache lookup) for all functions in the project\n        _getFunctionsInFiles(jsFiles).done(function (docEntries) {\n            // Compute offsets for all matched functions\n            _getOffsetsForFunction(docEntries, functionName).done(function (rangeResults) {\n                result.resolve(rangeResults);\n            });\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Finds all instances of the specified searchName in \"text\".\n     * Returns an Array of Objects with start and end properties.\n     *\n     * @param text {!String} JS text to search\n     * @param searchName {!String} function name to search for\n     * @return {Array.<{offset:number, functionName:string}>}\n     *      Array of objects containing the start offset for each matched function name.\n     */\n    function findAllMatchingFunctionsInText(text, searchName) {\n        var allFunctions = _findAllFunctionsInText(text);\n        var result = [];\n        var lines = text.split(\"\\n\");\n\n        _.forEach(allFunctions, function (functions, functionName) {\n            if (functionName === searchName || searchName === \"*\") {\n                functions.forEach(function (funcEntry) {\n                    var endOffset = _getFunctionEndOffset(text, funcEntry.offsetStart);\n                    result.push({\n                        name: functionName,\n                        label: funcEntry.label,\n                        lineStart: StringUtils.offsetToLineNum(lines, funcEntry.offsetStart),\n                        lineEnd: StringUtils.offsetToLineNum(lines, endOffset),\n                        nameLineStart: funcEntry.location.start.line - 1,\n                        nameLineEnd: funcEntry.location.end.line - 1,\n                        columnStart: funcEntry.location.start.column,\n                        columnEnd: funcEntry.location.end.column\n                    });\n                });\n            }\n        });\n\n        return result;\n    }\n\n    PerfUtils.createPerfMeasurement(\"JSUTILS_GET_ALL_FUNCTIONS\", \"Parallel file search across project\");\n    PerfUtils.createPerfMeasurement(\"JSUTILS_REGEXP\", \"RegExp search for all functions\");\n    PerfUtils.createPerfMeasurement(\"JSUTILS_END_OFFSET\", \"Find end offset for a single matched function\");\n\n    exports.findAllMatchingFunctionsInText = findAllMatchingFunctionsInText;\n    exports._getFunctionEndOffset = _getFunctionEndOffset; // For testing only\n    exports.findMatchingFunctions = findMatchingFunctions;\n});\n"
  },
  {
    "path": "src/language/LanguageManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: LanguageManager*/\n\n/**\n * LanguageManager provides access to the languages supported by Brackets\n *\n * To find out which languages we support by default, have a look at languages.json.\n *\n * To get access to an existing language, call getLanguage():\n *\n *     var language = LanguageManager.getLanguage(\"<id>\");\n *\n * To define your own languages, call defineLanguage():\n *\n *     LanguageManager.defineLanguage(\"haskell\", {\n *         name: \"Haskell\",\n *         mode: \"haskell\",\n *         fileExtensions: [\"hs\"],\n *         blockComment: [\"{-\", \"-}\"],\n *         lineComment: [\"--\"]\n *     });\n *\n * To use that language and its related mode, wait for the returned promise to be resolved:\n *\n *     LanguageManager.defineLanguage(\"haskell\", definition).done(function (language) {\n *         console.log(\"Language \" + language.getName() + \" is now available!\");\n *     });\n *\n * The extension can also contain dots:\n *\n *     LanguageManager.defineLanguage(\"literatecoffeescript\", {\n *         name: \"Literate CoffeeScript\",\n *         mode: \"coffeescript\",\n *         fileExtensions: [\"litcoffee\", \"coffee.md\"]\n *     });\n *\n * You can also specify file names:\n *\n *     LanguageManager.defineLanguage(\"makefile\", {\n *         name: \"Make\",\n *         mode: [\"null\", \"text/plain\"],\n *         fileNames: [\"Makefile\"]\n *     });\n *\n * You can combine file names and extensions, or not define them at all.\n *\n * You can also refine an existing language:\n *\n *     var language = LanguageManager.getLanguage(\"haskell\");\n *     language.setLineCommentSyntax([\"--\"]);\n *     language.setBlockCommentSyntax(\"{-\", \"-}\");\n *     language.addFileExtension(\"lhs\");\n *\n * Some CodeMirror modes define variations of themselves. They are called MIME modes.\n * To find existing MIME modes, search for \"CodeMirror.defineMIME\" in thirdparty/CodeMirror/mode\n * For instance, C++, C# and Java all use the clike (C-like) mode with different settings and a different MIME name.\n * You can refine the mode definition by specifying the MIME mode as well:\n *\n *     LanguageManager.defineLanguage(\"csharp\", {\n *         name: \"C#\",\n *         mode: [\"clike\", \"text/x-csharp\"],\n *         ...\n *     });\n *\n * Defining the base mode is still necessary to know which file to load.\n * However, language.getMode() will return just the MIME mode if one was\n * specified.\n *\n * If you need to configure a mode, you can just create a new MIME mode and use that:\n *\n *     CodeMirror.defineMIME(\"text/x-brackets-html\", {\n *         \"name\": \"htmlmixed\",\n *         \"scriptTypes\": [{\"matches\": /\\/x-handlebars-template|\\/x-mustache/i,\n *                        \"mode\": null}]\n *     });\n *\n *     LanguageManager.defineLanguage(\"html\", {\n *         name: \"HTML\",\n *         mode: [\"htmlmixed\", \"text/x-brackets-html\"],\n *         ...\n *     });\n *\n * If a mode is not shipped with our CodeMirror distribution, you need to first load it yourself.\n * If the mode is part of our CodeMirror distribution, it gets loaded automatically.\n *\n * You can also defines binary file types, i.e. Brackets supports image files by default,\n * such as *.jpg, *.png etc.\n * Binary files do not require mode because modes are specific to CodeMirror, which\n * only handles text based file types.\n * To register a binary language the isBinary flag must be set, i.e.\n *\n *     LanguageManager.defineLanguage(\"audio\", {\n *         name: \"Audio\",\n *         fileExtensions: [\"mp3\", \"wav\", \"aif\", \"aiff\", \"ogg\"],\n *         isBinary: true\n *     });\n *\n *\n * LanguageManager dispatches two events:\n *\n *  - languageAdded -- When any new Language is added. 2nd arg is the new Language.\n *  - languageModified -- When the attributes of a Language change, or when the Language gains or loses\n *          file extension / filename mappings. 2nd arg is the modified Language.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n\n    // Dependencies\n    var CodeMirror            = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        EventDispatcher       = require(\"utils/EventDispatcher\"),\n        Async                 = require(\"utils/Async\"),\n        FileUtils             = require(\"file/FileUtils\"),\n        Strings               = require(\"strings\"),\n        _defaultLanguagesJSON = require(\"text!language/languages.json\"),\n        _                     = require(\"thirdparty/lodash\"),\n\n        // PreferencesManager is loaded near the end of the file\n        PreferencesManager;\n\n    // State\n    var _fallbackLanguage               = null,\n        _pendingLanguages               = {},\n        _languages                      = {},\n        _baseFileExtensionToLanguageMap = {},\n        _fileExtensionToLanguageMap     = Object.create(_baseFileExtensionToLanguageMap),\n        _fileNameToLanguageMap          = {},\n        _filePathToLanguageMap          = {},\n        _modeToLanguageMap              = {},\n        _ready;\n\n    // Constants\n\n    var _EXTENSION_MAP_PREF = \"language.fileExtensions\",\n        _NAME_MAP_PREF      = \"language.fileNames\";\n\n    // Tracking for changes to mappings made by preferences\n    var _prefState = {};\n\n    _prefState[_EXTENSION_MAP_PREF] = {\n        last: {},\n        overridden: {},\n        add: \"addFileExtension\",\n        remove: \"removeFileExtension\",\n        get: \"getLanguageForExtension\"\n    };\n\n    _prefState[_NAME_MAP_PREF] = {\n        last: {},\n        overridden: {},\n        add: \"addFileName\",\n        remove: \"removeFileName\",\n        get: \"getLanguageForPath\"\n    };\n\n    // Helper functions\n\n    /**\n     * Checks whether value is a non-empty string. Reports an error otherwise.\n     * If no deferred is passed, console.error is called.\n     * Otherwise the deferred is rejected with the error message.\n     * @param {*}                value         The value to validate\n     * @param {!string}          description   A helpful identifier for value\n     * @param {?jQuery.Deferred} deferred      A deferred to reject with the error message in case of an error\n     * @return {boolean} True if the value is a non-empty string, false otherwise\n     */\n    function _validateNonEmptyString(value, description, deferred) {\n        var reportError = deferred ? deferred.reject : console.error;\n\n        // http://stackoverflow.com/questions/1303646/check-whether-variable-is-number-or-string-in-javascript\n        if (Object.prototype.toString.call(value) !== \"[object String]\") {\n            reportError(description + \" must be a string\");\n            return false;\n        }\n        if (value === \"\") {\n            reportError(description + \" must not be empty\");\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * Monkey-patch CodeMirror to prevent modes from being overwritten by extensions.\n     * We may rely on the tokens provided by some of these modes.\n     */\n    function _patchCodeMirror() {\n        var _original_CodeMirror_defineMode = CodeMirror.defineMode;\n        function _wrapped_CodeMirror_defineMode(name) {\n            if (CodeMirror.modes[name]) {\n                console.error(\"There already is a CodeMirror mode with the name \\\"\" + name + \"\\\"\");\n                return;\n            }\n            _original_CodeMirror_defineMode.apply(CodeMirror, arguments);\n        }\n        CodeMirror.defineMode = _wrapped_CodeMirror_defineMode;\n    }\n\n    /**\n     * Adds a global mode-to-language association.\n     * @param {!string} mode The mode to associate the language with\n     * @param {!Language} language The language to associate with the mode\n     */\n    function _setLanguageForMode(mode, language) {\n        if (_modeToLanguageMap[mode]) {\n            console.warn(\"CodeMirror mode \\\"\" + mode + \"\\\" is already used by language \" + _modeToLanguageMap[mode]._name + \" - cannot fully register language \" + language._name +\n                         \" using the same mode. Some features will treat all content with this mode as language \" + _modeToLanguageMap[mode]._name);\n            return;\n        }\n\n        _modeToLanguageMap[mode] = language;\n    }\n\n    /**\n     * Resolves a language ID to a Language object.\n     * File names have a higher priority than file extensions.\n     * @param {!string} id Identifier for this language: lowercase letters, digits, and _ separators (e.g. \"cpp\", \"foo_bar\", \"c99\")\n     * @return {Language} The language with the provided identifier or undefined\n     */\n    function getLanguage(id) {\n        return _languages[id];\n    }\n\n    /**\n     * Resolves a file extension to a Language object.\n     * *Warning:* it is almost always better to use getLanguageForPath(), since Language can depend\n     * on file name and even full path. Use this API only if no relevant file/path exists.\n     * @param {!string} extension Extension that language should be resolved for\n     * @return {?Language} The language for the provided extension or null if none exists\n     */\n    function getLanguageForExtension(extension) {\n        return _fileExtensionToLanguageMap[extension.toLowerCase()];\n    }\n\n    /**\n     * Resolves a file path to a Language object.\n     * @param {!string} path Path to the file to find a language for\n     * @param {?boolean} ignoreOverride If set to true will cause the lookup to ignore any\n     *      overrides and return default binding. By default override is not ignored.\n     *\n     * @return {Language} The language for the provided file type or the fallback language\n     */\n    function getLanguageForPath(path, ignoreOverride) {\n        var fileName,\n            language = _filePathToLanguageMap[path],\n            extension,\n            parts;\n\n        // if there's an override, return it\n        if (!ignoreOverride && language) {\n            return language;\n        }\n\n        fileName = FileUtils.getBaseName(path).toLowerCase();\n        language = _fileNameToLanguageMap[fileName];\n\n        // If no language was found for the file name, use the file extension instead\n        if (!language) {\n            // Split the file name into parts:\n            //   \"foo.coffee.md\"   => [\"foo\", \"coffee\", \"md\"]\n            //   \".profile.bak\"    => [\"\", \"profile\", \"bak\"]\n            //   \"1. Vacation.txt\" => [\"1\", \" Vacation\", \"txt\"]\n            parts = fileName.split(\".\");\n\n            // A leading dot does not indicate a file extension, but marks the file as hidden => remove it\n            if (parts[0] === \"\") {\n                // [\"\", \"profile\", \"bak\"] => [\"profile\", \"bak\"]\n                parts.shift();\n            }\n\n            // The first part is assumed to be the title, not the extension => remove it\n            //   [\"foo\", \"coffee\", \"md\"]   => [\"coffee\", \"md\"]\n            //   [\"profile\", \"bak\"]        => [\"bak\"]\n            //   [\"1\", \" Vacation\", \"txt\"] => [\" Vacation\", \"txt\"]\n            parts.shift();\n\n            // Join the remaining parts into a file extension until none are left or a language was found\n            while (!language && parts.length) {\n                // First iteration:\n                //   [\"coffee\", \"md\"]     => \"coffee.md\"\n                //   [\"bak\"]              => \"bak\"\n                //   [\" Vacation\", \"txt\"] => \" Vacation.txt\"\n                // Second iteration (assuming no language was found for \"coffee.md\"):\n                //   [\"md\"]  => \"md\"\n                //   [\"txt\"] => \"txt\"\n                extension = parts.join(\".\");\n                language  = _fileExtensionToLanguageMap[extension];\n                // Remove the first part\n                // First iteration:\n                //   [\"coffee\", \"md\"]     => [\"md\"]\n                //   [\"bak\"]              => []\n                //   [\" Vacation\", \"txt\"] => [\"txt\"]\n                // Second iteration:\n                //   [\"md\"]  => []\n                //   [\"txt\"] => []\n                parts.shift();\n            }\n        }\n\n        return language || _fallbackLanguage;\n    }\n\n    /**\n     * Returns a map of all the languages currently defined in the LanguageManager. The key to\n     * the map is the language id and the value is the language object.\n     *\n     * @return {Object.<string, Language>} A map containing all of the\n     *      languages currently defined.\n     */\n    function getLanguages() {\n        return $.extend({}, _languages); // copy to prevent modification\n    }\n\n    /**\n     * Resolves a CodeMirror mode to a Language object.\n     * @param {!string} mode CodeMirror mode\n     * @return {Language} The language for the provided mode or the fallback language\n     */\n    function _getLanguageForMode(mode) {\n        var language = _modeToLanguageMap[mode];\n        if (language) {\n            return language;\n        }\n\n        // In case of unsupported languages\n        console.log(\"Called LanguageManager._getLanguageForMode with a mode for which no language has been registered:\", mode);\n        return _fallbackLanguage;\n    }\n\n    /**\n     * @private\n     * Notify listeners when a language is added\n     * @param {!Language} language The new language\n     */\n    function _triggerLanguageAdded(language) {\n        // finally, store language to _language map\n        _languages[language.getId()] = language;\n        exports.trigger(\"languageAdded\", language);\n    }\n\n    /**\n     * @private\n     * Notify listeners when a language is modified\n     * @param {!Language} language The modified language\n     */\n    function _triggerLanguageModified(language) {\n        exports.trigger(\"languageModified\", language);\n    }\n\n    /**\n     * Adds a language mapping for the specified fullPath. If language is falsy (null or undefined), the mapping\n     * is removed. The override is NOT persisted across Brackets sessions.\n     *\n     * @param {!fullPath} fullPath absolute path of the file\n     * @param {?object} language language to associate the file with or falsy value to remove any existing override\n     */\n    function setLanguageOverrideForPath(fullPath, language) {\n        var oldLang = getLanguageForPath(fullPath);\n        if (!language) {\n            delete _filePathToLanguageMap[fullPath];\n        } else {\n            _filePathToLanguageMap[fullPath] = language;\n        }\n        var newLang = getLanguageForPath(fullPath);\n\n        // Old language changed since this path is no longer mapped to it\n        _triggerLanguageModified(oldLang);\n        // New language changed since a path is now mapped to it that wasn't before\n        _triggerLanguageModified(newLang);\n    }\n\n    /**\n     * Resets all the language overrides for file paths. Used by unit tests only.\n     */\n    function _resetPathLanguageOverrides() {\n        _filePathToLanguageMap = {};\n    }\n\n    /**\n     * Get the file extension (excluding \".\") given a path OR a bare filename.\n     * Returns \"\" for names with no extension.\n     * If the only `.` in the file is the first character,\n     * returns \"\" as this is not considered an extension.\n     * This method considers known extensions which include `.` in them.\n     *\n     * @param {string} fullPath full path to a file or directory\n     * @return {string} Returns the extension of a filename or empty string if\n     * the argument is a directory or a filename with no extension\n     */\n    function getCompoundFileExtension(fullPath) {\n        var baseName = FileUtils.getBaseName(fullPath),\n            parts = baseName.split(\".\");\n\n        // get rid of file name\n        parts.shift();\n        if (baseName[0] === \".\") {\n            // if starts with a `.`, then still consider it as file name\n            parts.shift();\n        }\n\n        var extension = [parts.pop()], // last part is always an extension\n            i = parts.length;\n        while (i--) {\n            if (getLanguageForExtension(parts[i])) {\n                extension.unshift(parts[i]);\n            } else {\n                break;\n            }\n        }\n        return extension.join(\".\");\n    }\n\n\n\n    /**\n     * Model for a language.\n     * @constructor\n     */\n    function Language() {\n        this._fileExtensions    = [];\n        this._fileNames         = [];\n        this._modeToLanguageMap = {};\n        this._lineCommentSyntax = [];\n    }\n\n\n    /**\n     * Identifier for this language\n     * @type {string}\n     */\n    Language.prototype._id = null;\n\n    /**\n     * Human-readable name of this language\n     * @type {string}\n     */\n    Language.prototype._name = null;\n\n    /**\n     * CodeMirror mode for this language\n     * @type {string}\n     */\n    Language.prototype._mode = null;\n\n    /**\n     * File extensions that use this language\n     * @type {Array.<string>}\n     */\n    Language.prototype._fileExtensions = null;\n\n    /**\n     * File names for extensionless files that use this language\n     * @type {Array.<string>}\n     */\n    Language.prototype._fileNames = null;\n\n    /**\n     * Line comment syntax\n     * @type {Array.<string>}\n     */\n    Language.prototype._lineCommentSyntax = null;\n\n    /**\n     * Which language to use for what CodeMirror mode\n     * @type {Object.<string,Language>}\n     */\n    Language.prototype._modeToLanguageMap = null;\n\n    /**\n     * Block comment syntax\n     * @type {{ prefix: string, suffix: string }}\n     */\n    Language.prototype._blockCommentSyntax = null;\n\n    /**\n     * Whether or not the language is binary\n     * @type {boolean}\n     */\n    Language.prototype._isBinary = false;\n\n    /**\n     * Returns the identifier for this language.\n     * @return {string} The identifier\n     */\n    Language.prototype.getId = function () {\n        return this._id;\n    };\n\n    /**\n     * Sets the identifier for this language or prints an error to the console.\n     * @param {!string} id Identifier for this language: lowercase letters, digits, and _ separators (e.g. \"cpp\", \"foo_bar\", \"c99\")\n     * @return {boolean} Whether the ID was valid and set or not\n     */\n    Language.prototype._setId = function (id) {\n        if (!_validateNonEmptyString(id, \"Language ID\")) {\n            return false;\n        }\n        // Make sure the ID is a string that can safely be used universally by the computer - as a file name, as an object key, as part of a URL, etc.\n        // Hence we use \"_\" instead of \".\" since the latter often has special meaning\n        if (!id.match(/^[a-z0-9]+(_[a-z0-9]+)*$/)) {\n            console.error(\"Invalid language ID \\\"\" + id + \"\\\": Only groups of lower case letters and numbers are allowed, separated by underscores.\");\n            return false;\n        }\n\n        this._id = id;\n        return true;\n    };\n\n    /**\n     * Returns the human-readable name of this language.\n     * @return {string} The name\n     */\n    Language.prototype.getName = function () {\n        return this._name;\n    };\n\n    /**\n     * Sets the human-readable name of this language or prints an error to the console.\n     * @param {!string} name Human-readable name of the language, as it's commonly referred to (e.g. \"C++\")\n     * @return {boolean} Whether the name was valid and set or not\n     */\n    Language.prototype._setName = function (name) {\n        if (!_validateNonEmptyString(name, \"name\")) {\n            return false;\n        }\n\n        this._name = name;\n        return true;\n    };\n\n    /**\n     * Returns the CodeMirror mode for this language.\n     * @return {string} The mode\n     */\n    Language.prototype.getMode = function () {\n        return this._mode;\n    };\n\n    /**\n     * Loads a mode and sets it for this language.\n     *\n     * @param {(string|Array.<string>)} mode  CodeMirror mode (e.g. \"htmlmixed\"), optionally paired with a MIME mode defined by\n     *      that mode (e.g. [\"clike\", \"text/x-c++src\"]). Unless the mode is located in thirdparty/CodeMirror/mode/<name>/<name>.js,\n     *      you need to first load it yourself.\n     * @return {$.Promise} A promise object that will be resolved when the mode is loaded and set\n     */\n    Language.prototype._loadAndSetMode = function (mode) {\n        var result      = new $.Deferred(),\n            self        = this,\n            mimeMode; // Mode can be an array specifying a mode plus a MIME mode defined by that mode [\"clike\", \"text/x-c++src\"]\n\n        if (Array.isArray(mode)) {\n            if (mode.length !== 2) {\n                result.reject(\"Mode must either be a string or an array containing two strings\");\n                return result.promise();\n            }\n            mimeMode = mode[1];\n            mode = mode[0];\n        }\n\n        // mode must not be empty. Use \"null\" (the string \"null\") mode for plain text\n        if (!_validateNonEmptyString(mode, \"mode\", result)) {\n            result.reject();\n            return result.promise();\n        }\n\n        var finish = function () {\n            if (!CodeMirror.modes[mode]) {\n                result.reject(\"CodeMirror mode \\\"\" + mode + \"\\\" is not loaded\");\n                return;\n            }\n\n            if (mimeMode) {\n                var modeConfig = CodeMirror.mimeModes[mimeMode];\n\n                if (!modeConfig) {\n                    result.reject(\"CodeMirror MIME mode \\\"\" + mimeMode + \"\\\" not found\");\n                    return;\n                }\n            }\n\n            // This mode is now only about what to tell CodeMirror\n            // The base mode was only necessary to load the proper mode file\n            self._mode = mimeMode || mode;\n            self._wasModified();\n\n            result.resolve(self);\n        };\n\n        if (CodeMirror.modes[mode]) {\n            finish();\n        } else {\n            require([\"thirdparty/CodeMirror/mode/\" + mode + \"/\" + mode], finish);\n        }\n\n        return result.promise();\n    };\n\n    /**\n     * Returns an array of file extensions for this language.\n     * @return {Array.<string>} File extensions used by this language\n     */\n    Language.prototype.getFileExtensions = function () {\n        // Use concat to create a copy of this array, preventing external modification\n        return this._fileExtensions.concat();\n    };\n\n    /**\n     * Returns an array of file names for extensionless files that use this language.\n     * @return {Array.<string>} Extensionless file names used by this language\n     */\n    Language.prototype.getFileNames = function () {\n        // Use concat to create a copy of this array, preventing external modification\n        return this._fileNames.concat();\n    };\n\n    /**\n     * Adds one or more file extensions to this language.\n     * @param {!string|Array.<string>} extension A file extension (or array thereof) used by this language\n     */\n    Language.prototype.addFileExtension = function (extension) {\n        if (Array.isArray(extension)) {\n            extension.forEach(this._addFileExtension.bind(this));\n        } else {\n            this._addFileExtension(extension);\n        }\n    };\n    Language.prototype._addFileExtension = function (extension) {\n        // Remove a leading dot if present\n        if (extension.charAt(0) === \".\") {\n            extension = extension.substr(1);\n        }\n\n        // Make checks below case-INsensitive\n        extension = extension.toLowerCase();\n\n        if (this._fileExtensions.indexOf(extension) === -1) {\n            this._fileExtensions.push(extension);\n\n            var language = _fileExtensionToLanguageMap[extension];\n            if (language) {\n                console.warn(\"Cannot register file extension \\\"\" + extension + \"\\\" for \" + this._name + \", it already belongs to \" + language._name);\n            } else {\n                _fileExtensionToLanguageMap[extension] = this;\n            }\n\n            this._wasModified();\n        } else if(!_fileExtensionToLanguageMap[extension]) {\n            \n            // Language should be in the extension map but isn't\n            _fileExtensionToLanguageMap[extension] = this;\n            this._wasModified();\n        }\n    };\n\n    /**\n     * Unregisters one or more file extensions from this language.\n     * @param {!string|Array.<string>} extension File extension (or array thereof) to stop using for this language\n     */\n    Language.prototype.removeFileExtension = function (extension) {\n        if (Array.isArray(extension)) {\n            extension.forEach(this._removeFileExtension.bind(this));\n        } else {\n            this._removeFileExtension(extension);\n        }\n    };\n    Language.prototype._removeFileExtension = function (extension) {\n        // Remove a leading dot if present\n        if (extension.charAt(0) === \".\") {\n            extension = extension.substr(1);\n        }\n\n        // Make checks below case-INsensitive\n        extension = extension.toLowerCase();\n\n        var index = this._fileExtensions.indexOf(extension);\n        if (index !== -1) {\n            this._fileExtensions.splice(index, 1);\n\n            delete _fileExtensionToLanguageMap[extension];\n\n            this._wasModified();\n        }\n    };\n\n    /**\n     * Adds one or more file names to the language which is used to match files that don't have extensions like \"Makefile\" for example.\n     * @param {!string|Array.<string>} extension An extensionless file name (or array thereof) used by this language\n     */\n    Language.prototype.addFileName = function (name) {\n        if (Array.isArray(name)) {\n            name.forEach(this._addFileName.bind(this));\n        } else {\n            this._addFileName(name);\n        }\n    };\n    Language.prototype._addFileName = function (name) {\n        // Make checks below case-INsensitive\n        name = name.toLowerCase();\n\n        if (this._fileNames.indexOf(name) === -1) {\n            this._fileNames.push(name);\n\n            var language = _fileNameToLanguageMap[name];\n            if (language) {\n                console.warn(\"Cannot register file name \\\"\" + name + \"\\\" for \" + this._name + \", it already belongs to \" + language._name);\n            } else {\n                _fileNameToLanguageMap[name] = this;\n            }\n\n            this._wasModified();\n        }\n    };\n\n    /**\n     * Unregisters one or more file names from this language.\n     * @param {!string|Array.<string>} extension An extensionless file name (or array thereof) used by this language\n     */\n    Language.prototype.removeFileName = function (name) {\n        if (Array.isArray(name)) {\n            name.forEach(this._removeFileName.bind(this));\n        } else {\n            this._removeFileName(name);\n        }\n    };\n    Language.prototype._removeFileName = function (name) {\n        // Make checks below case-INsensitive\n        name = name.toLowerCase();\n\n        var index = this._fileNames.indexOf(name);\n        if (index !== -1) {\n            this._fileNames.splice(index, 1);\n\n            delete _fileNameToLanguageMap[name];\n\n            this._wasModified();\n        }\n    };\n\n    /**\n     * Returns whether the line comment syntax is defined for this language.\n     * @return {boolean} Whether line comments are supported\n     */\n    Language.prototype.hasLineCommentSyntax = function () {\n        return this._lineCommentSyntax.length > 0;\n    };\n\n    /**\n     * Returns an array of prefixes to use for line comments.\n     * @return {Array.<string>} The prefixes\n     */\n    Language.prototype.getLineCommentPrefixes = function () {\n        return this._lineCommentSyntax;\n    };\n\n    /**\n     * Sets the prefixes to use for line comments in this language or prints an error to the console.\n     * @param {!(string|Array.<string>)} prefix Prefix string or an array of prefix strings\n     *   to use for line comments (e.g. \"//\" or [\"//\", \"#\"])\n     * @return {boolean} Whether the syntax was valid and set or not\n     */\n    Language.prototype.setLineCommentSyntax = function (prefix) {\n        var prefixes = Array.isArray(prefix) ? prefix : [prefix];\n        var i;\n\n        if (prefixes.length) {\n            this._lineCommentSyntax = [];\n            for (i = 0; i < prefixes.length; i++) {\n                _validateNonEmptyString(String(prefixes[i]), Array.isArray(prefix) ? \"prefix[\" + i + \"]\" : \"prefix\");\n\n                this._lineCommentSyntax.push(prefixes[i]);\n            }\n            this._wasModified();\n        } else {\n            console.error(\"The prefix array should not be empty\");\n        }\n\n        return true;\n    };\n\n    /**\n     * Returns whether the block comment syntax is defined for this language.\n     * @return {boolean} Whether block comments are supported\n     */\n    Language.prototype.hasBlockCommentSyntax = function () {\n        return Boolean(this._blockCommentSyntax);\n    };\n\n    /**\n     * Returns the prefix to use for block comments.\n     * @return {string} The prefix\n     */\n    Language.prototype.getBlockCommentPrefix = function () {\n        return this._blockCommentSyntax && this._blockCommentSyntax.prefix;\n    };\n\n    /**\n     * Returns the suffix to use for block comments.\n     * @return {string} The suffix\n     */\n    Language.prototype.getBlockCommentSuffix = function () {\n        return this._blockCommentSyntax && this._blockCommentSyntax.suffix;\n    };\n\n    /**\n     * Sets the prefix and suffix to use for blocks comments in this language or prints an error to the console.\n     * @param {!string} prefix Prefix string to use for block comments (e.g. \"<!--\")\n     * @param {!string} suffix Suffix string to use for block comments (e.g. \"-->\")\n     * @return {boolean} Whether the syntax was valid and set or not\n     */\n    Language.prototype.setBlockCommentSyntax = function (prefix, suffix) {\n        if (!_validateNonEmptyString(prefix, \"prefix\") || !_validateNonEmptyString(suffix, \"suffix\")) {\n            return false;\n        }\n\n        this._blockCommentSyntax = { prefix: prefix, suffix: suffix };\n        this._wasModified();\n\n        return true;\n    };\n\n    /**\n     * Returns either a language associated with the mode or the fallback language.\n     * Used to disambiguate modes used by multiple languages.\n     * @param {!string} mode The mode to associate the language with\n     * @return {Language} This language if it uses the mode, or whatever {@link #_getLanguageForMode} returns\n     */\n    Language.prototype.getLanguageForMode = function (mode) {\n        if (mode === this._mode) {\n            return this;\n        }\n        return this._modeToLanguageMap[mode] || _getLanguageForMode(mode);\n    };\n\n    /**\n     * Overrides a mode-to-language association for this particular language only or prints an error to the console.\n     * Used to disambiguate modes used by multiple languages.\n     * @param {!string} mode The mode to associate the language with\n     * @param {!Language} language The language to associate with the mode\n     * @return {boolean} Whether the mode-to-language association was valid and set or not\n     * @private\n     */\n    Language.prototype._setLanguageForMode = function (mode, language) {\n        if (mode === this._mode && language !== this) {\n            console.error(\"A language must always map its mode to itself\");\n            return false;\n        }\n\n        this._modeToLanguageMap[mode] = language;\n        this._wasModified();\n\n        return true;\n    };\n\n    /**\n     * Determines whether this is the fallback language or not\n     * @return {boolean} True if this is the fallback language, false otherwise\n     */\n    Language.prototype.isFallbackLanguage = function () {\n        return this === _fallbackLanguage;\n    };\n\n    /**\n     * Trigger the \"languageModified\" event if this language is registered already\n     * @see #_triggerLanguageModified\n     * @private\n     */\n    Language.prototype._wasModified = function () {\n        if (_languages[this._id]) {\n            _triggerLanguageModified(this);\n        }\n    };\n\n    /**\n     * Indicates whether or not the language is binary (e.g., image or audio).\n     * @return {boolean}\n     */\n    Language.prototype.isBinary = function () {\n        return this._isBinary;\n    };\n\n    /**\n     * Sets whether or not the language is binary\n     * @param {!boolean} isBinary\n     */\n    Language.prototype._setBinary = function (isBinary) {\n        this._isBinary = isBinary;\n    };\n\n    /**\n     * Defines a language.\n     *\n     * @param {!string}               id                        Unique identifier for this language: lowercase letters, digits, and _ separators (e.g. \"cpp\", \"foo_bar\", \"c99\")\n     * @param {!Object}               definition                An object describing the language\n     * @param {!string}               definition.name           Human-readable name of the language, as it's commonly referred to (e.g. \"C++\")\n     * @param {Array.<string>}        definition.fileExtensions List of file extensions used by this language (e.g. [\"php\", \"php3\"] or [\"coffee.md\"] - may contain dots)\n     * @param {Array.<string>}        definition.fileNames      List of exact file names (e.g. [\"Makefile\"] or [\"package.json]). Higher precedence than file extension.\n     * @param {Array.<string>}        definition.blockComment   Array with two entries defining the block comment prefix and suffix (e.g. [\"<!--\", \"-->\"])\n     * @param {(string|Array.<string>)} definition.lineComment  Line comment prefixes (e.g. \"//\" or [\"//\", \"#\"])\n     * @param {(string|Array.<string>)} definition.mode         CodeMirror mode (e.g. \"htmlmixed\"), optionally with a MIME mode defined by that mode [\"clike\", \"text/x-c++src\"]\n     *                                                          Unless the mode is located in thirdparty/CodeMirror/mode/<name>/<name>.js, you need to first load it yourself.\n     *\n     * @return {$.Promise} A promise object that will be resolved with a Language object\n     **/\n    function defineLanguage(id, definition) {\n        var result = new $.Deferred();\n\n        if (_pendingLanguages[id]) {\n            result.reject(\"Language \\\"\" + id + \"\\\" is waiting to be resolved.\");\n            return result.promise();\n        }\n        if (_languages[id]) {\n            result.reject(\"Language \\\"\" + id + \"\\\" is already defined\");\n            return result.promise();\n        }\n\n        var language       = new Language(),\n            name           = definition.name,\n            fileExtensions = definition.fileExtensions,\n            fileNames      = definition.fileNames,\n            blockComment   = definition.blockComment,\n            lineComment    = definition.lineComment,\n            i,\n            l;\n\n        function _finishRegisteringLanguage() {\n            if (fileExtensions) {\n                for (i = 0, l = fileExtensions.length; i < l; i++) {\n                    language.addFileExtension(fileExtensions[i]);\n                }\n            }\n            // register language file names after mode has loaded\n            if (fileNames) {\n                for (i = 0, l = fileNames.length; i < l; i++) {\n                    language.addFileName(fileNames[i]);\n                }\n            }\n\n            language._setBinary(!!definition.isBinary);\n\n            // store language to language map\n            _languages[language.getId()] = language;\n\n            // restore any preferences for non-default languages\n            if(PreferencesManager) {\n                _updateFromPrefs(_EXTENSION_MAP_PREF);\n                _updateFromPrefs(_NAME_MAP_PREF);\n            }\n        }\n\n        if (!language._setId(id) || !language._setName(name) ||\n                (blockComment && !language.setBlockCommentSyntax(blockComment[0], blockComment[1])) ||\n                (lineComment && !language.setLineCommentSyntax(lineComment))) {\n            result.reject();\n            return result.promise();\n        }\n\n\n        if (definition.isBinary) {\n            // add file extensions and store language to language map\n            _finishRegisteringLanguage();\n\n            result.resolve(language);\n            // Not notifying DocumentManager via event LanguageAdded, because DocumentManager\n            // does not care about binary files.\n        } else {\n            // track languages that are currently loading\n            _pendingLanguages[id] = language;\n\n            language._loadAndSetMode(definition.mode).done(function () {\n\n                // globally associate mode to language\n                _setLanguageForMode(language.getMode(), language);\n\n                // add file extensions and store language to language map\n                _finishRegisteringLanguage();\n\n                // fire an event to notify DocumentManager of the new language\n                _triggerLanguageAdded(language);\n\n                result.resolve(language);\n            }).fail(function (error) {\n                console.error(error);\n                result.reject(error);\n            }).always(function () {\n                // delete from pending languages after success and failure\n                delete _pendingLanguages[id];\n            });\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     *\n     * If a default file extension or name was overridden by a pref, restore it.\n     *\n     * @param {string} name Extension or filename that should be restored\n     * @param {{overridden: string, add: string}} prefState object for the pref that is currently being updated\n     */\n    function _restoreOverriddenDefault(name, state) {\n        if (state.overridden[name]) {\n            var language = getLanguage(state.overridden[name]);\n            language[state.add](name);\n            delete state.overridden[name];\n        }\n    }\n\n    /**\n     * @private\n     *\n     * Updates extension and filename mappings from languages based on the current preferences values.\n     *\n     * The preferences look like this in a prefs file:\n     *\n     * Map *.foo to javascript, *.vm to html\n     *\n     *     \"language.fileExtensions\": {\n     *         \"foo\": \"javascript\",\n     *         \"vm\": \"html\"\n     *     }\n     *\n     * Map \"Gemfile\" to ruby:\n     *\n     *     \"language.fileNames\": {\n     *         \"Gemfile\": \"ruby\"\n     *     }\n     */\n    function _updateFromPrefs(pref) {\n        var newMapping = PreferencesManager.get(pref),\n            newNames = Object.keys(newMapping),\n            state = _prefState[pref],\n            last = state.last,\n            overridden = state.overridden;\n\n        // Look for added and changed names (extensions or filenames)\n        newNames.forEach(function (name) {\n            var language;\n            if (newMapping[name] !== last[name]) {\n                if (last[name]) {\n                    language = getLanguage(last[name]);\n                    if (language) {\n                        language[state.remove](name);\n\n                        // If this name that was previously mapped was overriding a default\n                        // restore it now.\n                        _restoreOverriddenDefault(name, state);\n                    }\n                }\n\n                language = exports[state.get](name);\n                if (language) {\n                    language[state.remove](name);\n\n                    // We're removing a name that was defined in Brackets or an extension,\n                    // so keep track of how it used to be mapped.\n                    if (!overridden[name]) {\n                        overridden[name] = language.getId();\n                    }\n                }\n                language = getLanguage(newMapping[name]);\n                if (language) {\n                    language[state.add](name);\n                }\n            }\n            if(!getLanguage(newMapping[name])) {\n                \n                // If the language doesn't exist, restore any overrides and remove it\n                // from the state.\n                if(overridden[name]) {\n                    _restoreOverriddenDefault(name, state);\n                }\n                delete newMapping[name];\n            }\n        });\n\n        // Look for removed names (extensions or filenames)\n        _.difference(Object.keys(last), newNames).forEach(function (name) {\n            var language = getLanguage(last[name]);\n            if (language) {\n                language[state.remove](name);\n                _restoreOverriddenDefault(name, state);\n            }\n        });\n        state.last = newMapping;\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Prevent modes from being overwritten by extensions\n    _patchCodeMirror();\n\n    // Define a custom MIME mode here instead of putting it directly into languages.json\n    // because JSON files can't contain regular expressions. Also, all other modes so\n    // far were strings, so we spare us the trouble of allowing more complex mode values.\n    CodeMirror.defineMIME(\"text/x-brackets-html\", {\n        \"name\": \"htmlmixed\",\n        \"scriptTypes\": [\n            {\n                \"matches\": /\\/x-handlebars|\\/x-mustache|\\/ng-template$|^text\\/html$/i,\n                \"mode\": \"htmlmixed\"\n            },\n            {\n                \"matches\": /^text\\/(babel|jsx)$/i,\n                \"mode\": \"jsx\"\n            }\n        ]\n    });\n\n    // Define SVG MIME type so an SVG language can be defined for SVG-specific code hints.\n    // Currently, SVG uses XML mode so it has generic XML syntax highlighting. This can\n    // be removed when SVG gets its own CodeMirror mode with SVG syntax highlighting.\n    CodeMirror.defineMIME(\"image/svg+xml\", \"xml\");\n\n    // Load the default languages\n    _defaultLanguagesJSON = JSON.parse(_defaultLanguagesJSON);\n    _ready = Async.doInParallel(Object.keys(_defaultLanguagesJSON), function (key) {\n        return defineLanguage(key, _defaultLanguagesJSON[key]);\n    }, false);\n\n    // Get the object for HTML\n    _ready.always(function () {\n        var html = getLanguage(\"html\");\n\n        // The htmlmixed mode uses the xml mode internally for the HTML parts, so we map it to HTML\n        html._setLanguageForMode(\"xml\", html);\n\n        // Currently we override the above mentioned \"xml\" in TokenUtils.getModeAt, instead returning \"html\".\n        // When the CSSInlineEditor and the hint providers are no longer based on modes, this can be changed.\n        // But for now, we need to associate this madeup \"html\" mode with our HTML language object.\n        _setLanguageForMode(\"html\", html);\n\n        // Similarly, the php mode uses clike internally for the PHP parts\n        var php = getLanguage(\"php\");\n        php._setLanguageForMode(\"clike\", php);\n\n        // Similar hack to the above for dealing with SCSS/CSS.\n        var scss = getLanguage(\"scss\");\n        scss._setLanguageForMode(\"css\", scss);\n\n        // Map stylus mode to the stylus Brackets language, fixes #13378\n        var stylus = getLanguage(\"stylus\");\n        _setLanguageForMode(\"stylus\", stylus);\n\n        // The fallback language for unknown modes and file extensions\n        _fallbackLanguage = getLanguage(\"unknown\");\n\n        // There is a circular dependency between FileUtils and LanguageManager which\n        // was introduced in 254b01e2f2eebea4416026d0f40d017b8ca6dbc9\n        // and may be preventing us from importing PreferencesManager (which also\n        // depends on FileUtils) here. Using the async form of require fixes this.\n        require([\"preferences/PreferencesManager\"], function (pm) {\n            PreferencesManager = pm;\n            pm.definePreference(_EXTENSION_MAP_PREF, \"object\", {}, {\n                description: Strings.DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\n            }).on(\"change\", function () {\n                _updateFromPrefs(_EXTENSION_MAP_PREF);\n            });\n            pm.definePreference(_NAME_MAP_PREF, \"object\", {}, {\n                description: Strings.DESCRIPTION_LANGUAGE_FILE_NAMES\n            }).on(\"change\", function () {\n                _updateFromPrefs(_NAME_MAP_PREF);\n            });\n            _updateFromPrefs(_EXTENSION_MAP_PREF);\n            _updateFromPrefs(_NAME_MAP_PREF);\n        });\n    });\n\n    // Private for unit tests\n    exports._EXTENSION_MAP_PREF         = _EXTENSION_MAP_PREF;\n    exports._NAME_MAP_PREF              = _NAME_MAP_PREF;\n    exports._resetPathLanguageOverrides = _resetPathLanguageOverrides;\n\n    // Public methods\n    exports.ready                       = _ready;\n    exports.defineLanguage              = defineLanguage;\n    exports.getLanguage                 = getLanguage;\n    exports.getLanguageForExtension     = getLanguageForExtension;\n    exports.getLanguageForPath          = getLanguageForPath;\n    exports.getLanguages                = getLanguages;\n    exports.setLanguageOverrideForPath  = setLanguageOverrideForPath;\n    exports.getCompoundFileExtension    = getCompoundFileExtension;\n});\n"
  },
  {
    "path": "src/language/XMLUtils.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependencies.\n    var TokenUtils  = require(\"utils/TokenUtils\");\n\n    // Enums of token types.\n    var TOKEN_TAG    = 1,\n        TOKEN_ATTR   = 2,\n        TOKEN_VALUE  = 3;\n\n    // Regex to find whitespace.\n    var regexWhitespace = /^\\s+$/;\n\n    /**\n     * Returns an object that represents all its params.\n     *\n     * @param {!Token} token CodeMirror token at the current pos\n     * @param {number} tokenType Type of current token\n     * @param {number} offset Offset in current token\n     * @param {Array.<string>} exclusionList List of attributes of a tag or attribute options used by an attribute\n     * @param {string} tagName Name of the current tag\n     * @param {string} attrName Name of the current attribute\n     * @param {boolean} shouldReplace true if we don't want to append =\"\" to an attribute\n     * @return {!{token: Token, tokenType: int, offset: int, exclusionList: Array.<string>, tagName: string, attrName: string, shouldReplace: boolean}}\n     */\n    function _createTagInfo(token, tokenType, offset, exclusionList, tagName, attrName, shouldReplace) {\n        return {\n            token: token || null,\n            tokenType: tokenType || null,\n            offset: offset || 0,\n            exclusionList: exclusionList || [],\n            tagName: tagName || \"\",\n            attrName: attrName || \"\",\n            shouldReplace: shouldReplace || false\n        };\n    }\n\n    /**\n     * Return the tagName and a list of attributes used by the tag.\n     *\n     * @param {!Editor} editor An instance of active editor\n     * @param {!{line: number, ch: number}} constPos The position of cursor in the active editor\n     * @return {!{tagName: string, exclusionList: Array.<string>, shouldReplace: boolean}}\n     */\n    function _getTagAttributes(editor, constPos) {\n        var pos, ctx, ctxPrev, ctxNext, ctxTemp, tagName, exclusionList = [], shouldReplace;\n\n        pos = $.extend({}, constPos);\n        ctx = TokenUtils.getInitialContext(editor._codeMirror, pos);\n\n        // Stop if the cursor is before = or an attribute value.\n        ctxTemp = $.extend(true, {}, ctx);\n        if (ctxTemp.token.type === null && regexWhitespace.test(ctxTemp.token.string)) {\n            if (TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctxTemp)) {\n                if ((ctxTemp.token.type === null && ctxTemp.token.string === \"=\") ||\n                        ctxTemp.token.type === \"string\") {\n                    return null;\n                }\n                TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctxTemp);\n            }\n        }\n\n        // Incase an attribute is followed by an equal sign, shouldReplace will be used\n        // to prevent from appending =\"\" again.\n        if (ctxTemp.token.type === \"attribute\") {\n            if (TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctxTemp)) {\n                if (ctxTemp.token.type === null && ctxTemp.token.string === \"=\") {\n                    shouldReplace = true;\n                }\n            }\n        }\n\n        // Look-Back and get the attributes and tag name.\n        pos = $.extend({}, constPos);\n        ctxPrev = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        while (TokenUtils.movePrevToken(ctxPrev)) {\n            if (ctxPrev.token.type && ctxPrev.token.type.indexOf(\"tag bracket\") >= 0) {\n                // Disallow hints in closed tag and inside tag content\n                if (ctxPrev.token.string === \"</\" || ctxPrev.token.string.indexOf(\">\") !== -1) {\n                    return null;\n                }\n            }\n\n            // Get attributes.\n            if (ctxPrev.token.type === \"attribute\") {\n                exclusionList.push(ctxPrev.token.string);\n            }\n\n            // Get tag.\n            if (ctxPrev.token.type === \"tag\") {\n                tagName = ctxPrev.token.string;\n                if (TokenUtils.movePrevToken(ctxPrev)) {\n                    if (ctxPrev.token.type === \"tag bracket\" && ctxPrev.token.string === \"<\") {\n                        break;\n                    }\n                    return null;\n                }\n            }\n        }\n\n        // Look-Ahead and find rest of the attributes.\n        pos = $.extend({}, constPos);\n        ctxNext = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        while (TokenUtils.moveNextToken(ctxNext)) {\n            if (ctxNext.token.type === \"string\" && ctxNext.token.string === \"\\\"\") {\n                return null;\n            }\n\n            // Stop on closing bracket of its own tag or opening bracket of next tag.\n            if (ctxNext.token.type === \"tag bracket\" &&\n                    (ctxNext.token.string.indexOf(\">\") >= 0 || ctxNext.token.string === \"<\")) {\n                break;\n            }\n            if (ctxNext.token.type === \"attribute\" && exclusionList.indexOf(ctxNext.token.string) === -1) {\n                exclusionList.push(ctxNext.token.string);\n            }\n        }\n        return {\n            tagName: tagName,\n            exclusionList: exclusionList,\n            shouldReplace: shouldReplace\n        };\n    }\n\n    /**\n     * Return the tag name, attribute name and a list of options used by the attribute\n     *\n     * @param {!Editor} editor An instance of active editor\n     * @param {!{line: number, ch: number}} pos Position of cursor in the editor\n     * @return {!{tagName: string, attrName: string, exclusionList: Array.<string>}}\n     */\n    function _getTagAttributeValue(editor, pos) {\n        var ctx, tagName, attrName, exclusionList = [], offset, textBefore, textAfter;\n\n        ctx = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        offset = TokenUtils.offsetInToken(ctx);\n\n        // To support multiple options on the same attribute, we have\n        // to break the value, these values will not be available then.\n        if (ctx.token.type === \"string\" && /\\s+/.test(ctx.token.string)) {\n            textBefore = ctx.token.string.substr(1, offset);\n            textAfter = ctx.token.string.substr(offset);\n\n            // Remove quote from end of the string.\n            if (/^['\"]$/.test(ctx.token.string.substr(-1, 1))) {\n                textAfter = textAfter.substr(0, textAfter.length - 1);\n            }\n\n            // Split the text before and after the offset, skipping the current query.\n            exclusionList = exclusionList.concat(textBefore.split(/\\s+/).slice(0, -1));\n            exclusionList = exclusionList.concat(textAfter.split(/\\s+/));\n\n            // Filter through the list removing empty strings.\n            exclusionList = exclusionList.filter(function (value) {\n                if (value.length > 0) {\n                    return true;\n                }\n            });\n        }\n\n        // Look-back and find tag and attributes.\n        while (TokenUtils.movePrevToken(ctx)) {\n            if (ctx.token.type === \"tag bracket\") {\n                // Disallow hints in closing tags.\n                if (ctx.token.string === \"</\") {\n                    return null;\n                }\n                // Stop when closing bracket of another tag or opening bracket of its own in encountered.\n                if (ctx.token.string.indexOf(\">\") >= 0 || ctx.token.string === \"<\") {\n                    break;\n                }\n            }\n\n            // Get the first previous attribute.\n            if (ctx.token.type === \"attribute\" && !attrName) {\n                attrName = ctx.token.string;\n            }\n\n            // Stop if we get a bracket after tag.\n            if (ctx.token.type === \"tag\") {\n                tagName = ctx.token.string;\n                if (TokenUtils.movePrevToken(ctx)) {\n                    if (ctx.token.type === \"tag bracket\" && ctx.token.string === \"<\") {\n                        break;\n                    }\n                    return null;\n                }\n            }\n        }\n\n        return {\n            tagName: tagName,\n            attrName: attrName,\n            exclusionList: exclusionList\n        };\n    }\n\n    /**\n     * Return the tag info at a given position in the active editor\n     *\n     * @param {!Editor} editor Instance of active editor\n     * @param {!{line: number, ch: number}} pos Position of cursor in the editor\n     * @return {!{token: Object, tokenType: number, offset: number, exclusionList: Array.<string>, tagName: string, attrName: string, shouldReplace: boolean}}\n     */\n    function getTagInfo(editor, pos) {\n        var ctx, offset, tagAttrs, tagAttrValue;\n\n        ctx = TokenUtils.getInitialContext(editor._codeMirror, pos);\n        offset = TokenUtils.offsetInToken(ctx);\n\n        if (ctx.token && ctx.token.type === \"tag bracket\" && ctx.token.string === \"<\") {\n            // Returns tagInfo when an angle bracket is created.\n            return _createTagInfo(ctx.token, TOKEN_TAG);\n        } else if (ctx.token && ctx.token.type === \"tag\") {\n            // Return tagInfo when a tag is created.\n            if (TokenUtils.movePrevToken(ctx)) {\n                if (ctx.token.type === \"tag bracket\" && ctx.token.string === \"<\") {\n                    TokenUtils.moveNextToken(ctx);\n                    return _createTagInfo(ctx.token, TOKEN_TAG, offset);\n                }\n            }\n        } else if (ctx.token && (ctx.token.type === \"attribute\" ||\n                                 (ctx.token.type === null && regexWhitespace.test(ctx.token.string)))) {\n            // Return tagInfo when an attribute is created.\n            tagAttrs = _getTagAttributes(editor, pos);\n            if (tagAttrs && tagAttrs.tagName) {\n                return _createTagInfo(ctx.token, TOKEN_ATTR, offset, tagAttrs.exclusionList, tagAttrs.tagName, null, tagAttrs.shouldReplace);\n            }\n        } else if (ctx.token && ((ctx.token.type === null && ctx.token.string === \"=\") ||\n                                 (ctx.token.type === \"string\" && /^['\"]$/.test(ctx.token.string.charAt(0))))) {\n            // Return tag info when an attribute value is created.\n            // Allow no hints if the cursor is outside the value.\n            if (ctx.token.type === \"string\" &&\n                    /^['\"]$/.test(ctx.token.string.substr(-1, 1)) &&\n                    ctx.token.string.length !== 1 &&\n                    ctx.token.end === pos.ch) {\n                return _createTagInfo();\n            }\n\n            tagAttrValue = _getTagAttributeValue(editor, pos);\n            if (tagAttrValue && tagAttrValue.tagName && tagAttrValue.attrName) {\n                return _createTagInfo(ctx.token, TOKEN_VALUE, offset, tagAttrValue.exclusionList, tagAttrValue.tagName, tagAttrValue.attrName);\n            }\n        }\n        return _createTagInfo();\n    }\n\n    /**\n     * Return the query text of a value.\n     *\n     * @param {!{token: Object, tokenType: number, offset: number, exclusionList: Array.<string>, tagName: string, attrName: string, shouldReplace: boolean}}\n     * @return {string}  The query to use to matching hints.\n     */\n    function getValueQuery(tagInfo) {\n        var query;\n        if (tagInfo.token.string === \"=\") {\n            return \"\";\n        }\n        // Remove quotation marks in query.\n        query = tagInfo.token.string.substr(1, tagInfo.offset - 1);\n\n        // Get the last option to use as a query to support multiple options.\n        return query.split(/\\s+/).slice(-1)[0];\n    }\n\n    // Expose public API.\n    exports.getTagInfo      = getTagInfo;\n    exports.getValueQuery   = getValueQuery;\n    exports.regexWhitespace = regexWhitespace;\n    exports.TOKEN_TAG       = TOKEN_TAG;\n    exports.TOKEN_ATTR      = TOKEN_ATTR;\n    exports.TOKEN_VALUE     = TOKEN_VALUE;\n});\n"
  },
  {
    "path": "src/language/languages.json",
    "content": "{\n    \"unknown\": {\n        \"name\": \"Text\",\n        \"mode\": [\"null\", \"text/plain\"]\n    },\n    \n    \"groovy\": {\n        \"name\": \"Groovy\",\n        \"mode\": \"groovy\",\n        \"fileExtensions\": [\"groovy\", \"gradle\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n   \n    \"properties\": {\n        \"name\": \"Properties\",\n        \"mode\": [\"properties\", \"text/x-properties\"],\n        \"fileExtensions\": [\"ini\", \"properties\"]\n    },\n\n    \"css\": {\n        \"name\": \"CSS\",\n        \"mode\": \"css\",\n        \"fileExtensions\": [\"css\", \"css.erb\"],\n        \"blockComment\": [\"/*\", \"*/\"]\n    },\n\n    \"scss\": {\n        \"name\": \"SCSS\",\n        \"mode\": [\"css\", \"text/x-scss\"],\n        \"fileExtensions\": [\"scss\", \"scss.erb\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"stylus\": {\n        \"name\": \"Stylus\",\n        \"mode\": [\"stylus\", \"text/x-styl\"],\n        \"fileExtensions\": [\"styl\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"html\": {\n        \"name\": \"HTML\",\n        \"mode\": [\"htmlmixed\", \"text/x-brackets-html\"],\n        \"fileExtensions\": [\"html\", \"htm\", \"shtm\", \"shtml\", \"xhtml\", \"cfm\", \"cfml\", \"cfc\", \"dhtml\", \"xht\", \"tpl\", \"twig\", \"kit\", \"jsp\", \"aspx\", \"ascx\", \"asp\", \"master\", \"cshtml\", \"vbhtml\"],\n        \"blockComment\": [\"<!--\", \"-->\"]\n    },\n    \n    \"ejs\": {\n        \"name\": \"EJS\",\n        \"mode\": [\"htmlembedded\", \"application/x-ejs\"],\n        \"fileExtensions\": [\"ejs\", \"dust\"],\n        \"blockComment\": [\"<!--\", \"-->\"]\n    },\n    \n    \"erb_html\": {\n        \"name\": \"Embedded Ruby\",\n        \"mode\": [\"htmlembedded\", \"application/x-erb\"],\n        \"fileExtensions\": [\"erb\", \"html.erb\", \"htm.erb\"],\n        \"blockComment\": [\"<!--\", \"-->\"]\n    },\n\n    \"javascript\": {\n        \"name\": \"JavaScript\",\n        \"mode\": \"javascript\",\n        \"fileExtensions\": [\"js\", \"js.erb\", \"jsm\", \"_js\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"jsx\": {\n        \"name\": \"JSX\",\n        \"mode\": \"jsx\",\n        \"fileExtensions\": [\"jsx\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"dart\": {\n        \"name\": \"Dart\",\n        \"mode\": [\"dart\", \"application/dart\"],\n        \"fileExtensions\": [\"dart\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"vbscript\": {\n        \"name\": \"VBScript\",\n        \"mode\": \"vbscript\",\n        \"fileExtensions\": [\"vbs\"],\n        \"lineComment\": [\"'\", \"REM\"]\n    },\n\n    \"vb\": {\n        \"name\": \"VB\",\n        \"mode\": [\"vb\", \"text/x-vb\"],\n        \"fileExtensions\": [\"vb\"],\n        \"lineComment\": [\"'\"]\n    },\n\n    \"json\": {\n        \"name\": \"JSON\",\n        \"mode\": [\"javascript\", \"application/json\"],\n        \"fileExtensions\": [\"json\"],\n        \"fileNames\": [\".jshintrc\", \".bowerrc\"]\n    },\n\n    \"xml\": {\n        \"name\": \"XML\",\n        \"mode\": \"xml\",\n        \"fileExtensions\": [\"xml\", \"wxs\", \"wxl\", \"wsdl\", \"rss\", \"atom\", \"rdf\", \"xslt\", \"xsl\", \"xul\", \"xsd\", \"xbl\", \"mathml\", \"config\", \"plist\", \"xaml\"],\n        \"blockComment\": [\"<!--\", \"-->\"]\n    },\n\n    \"svg\": {\n        \"name\": \"SVG\",\n        \"mode\": [\"xml\", \"image/svg+xml\"],\n        \"fileExtensions\": [\"svg\"],\n        \"blockComment\": [\"<!--\", \"-->\"]\n    },\n\n    \"php\": {\n        \"name\": \"PHP\",\n        \"mode\": \"php\",\n        \"fileExtensions\": [\"php\", \"php3\", \"php4\", \"php5\", \"phtm\", \"phtml\", \"ctp\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\", \"#\"]\n    },\n\n    \"c\": {\n        \"name\": \"C\",\n        \"mode\": [\"clike\", \"text/x-csrc\"],\n        \"fileExtensions\": [\"c\", \"h\", \"i\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"cpp\": {\n        \"name\": \"C++\",\n        \"mode\": [\"clike\", \"text/x-c++src\"],\n        \"fileExtensions\": [\"cc\", \"cp\", \"cpp\", \"c++\", \"cxx\", \"hh\", \"hpp\", \"hxx\", \"h++\", \"ii\", \"ino\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"csharp\": {\n        \"name\": \"C#\",\n        \"mode\": [\"clike\", \"text/x-csharp\"],\n        \"fileExtensions\": [\"cs\", \"asax\", \"ashx\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"java\": {\n        \"name\": \"Java\",\n        \"mode\": [\"clike\", \"text/x-java\"],\n        \"fileExtensions\": [\"java\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"scala\": {\n        \"name\": \"Scala\",\n        \"mode\": [\"clike\", \"text/x-scala\"],\n        \"fileExtensions\": [\"scala\", \"sbt\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"coffeescript\": {\n        \"name\": \"CoffeeScript\",\n        \"mode\": \"coffeescript\",\n        \"fileExtensions\": [\"coffee\", \"cf\", \"cson\", \"_coffee\"],\n        \"fileNames\": [\"Cakefile\"],\n        \"blockComment\": [\"###\", \"###\"],\n        \"lineComment\": [\"#\"]\n    },\n\n    \"clojure\": {\n        \"name\": \"Clojure\",\n        \"mode\": \"clojure\",\n        \"fileExtensions\": [\"clj\", \"cljs\", \"cljx\"],\n        \"lineComment\": [\";\", \";;\"]\n    },\n\n    \"perl\": {\n        \"name\": \"Perl\",\n        \"mode\": \"perl\",\n        \"fileExtensions\": [\"pl\", \"pm\", \"t\"],\n        \"lineComment\": [\"#\"]\n    },\n\n    \"ruby\": {\n        \"name\": \"Ruby\",\n        \"mode\": \"ruby\",\n        \"fileExtensions\": [\"rb\", \"ru\", \"gemspec\", \"rake\"],\n        \"fileNames\": [\"Gemfile\", \"Rakefile\", \"Guardfile\", \"Vagrantfile\"],\n        \"lineComment\": [\"#\"]\n    },\n\n    \"python\": {\n        \"name\": \"Python\",\n        \"mode\": \"python\",\n        \"fileExtensions\": [\"py\", \"pyw\", \"wsgi\", \"gyp\", \"gypi\"],\n        \"lineComment\": [\"#\"]\n    },\n\n    \"sass\": {\n        \"name\": \"SASS\",\n        \"mode\": \"sass\",\n        \"fileExtensions\": [\"sass\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"lua\": {\n        \"name\": \"Lua\",\n        \"mode\": \"lua\",\n        \"fileExtensions\": [\"lua\"],\n        \"blockComment\": [\"--[[\", \"]]\"],\n        \"lineComment\": [\"--\"]\n    },\n\n    \"sql\": {\n        \"name\": \"SQL\",\n        \"mode\": [\"sql\", \"text/x-mysql\"],\n        \"fileExtensions\": [\"sql\"]\n    },\n\n    \"diff\": {\n        \"name\": \"Diff\",\n        \"mode\": \"diff\",\n        \"fileExtensions\": [\"diff\", \"patch\"]\n    },\n\n    \"markdown\": {\n        \"name\": \"Markdown\",\n        \"mode\": \"markdown\",\n        \"fileExtensions\": [\"md\", \"markdown\", \"mdown\", \"mkdn\"],\n        \"blockComment\": [\"<!--\", \"-->\"]\n    },\n\n    \"gfm\": {\n        \"name\": \"Markdown (GitHub)\",\n        \"mode\": \"gfm\"\n    },\n\n    \"yaml\": {\n        \"name\": \"YAML\",\n        \"mode\": \"yaml\",\n        \"fileExtensions\": [\"yaml\", \"yml\"],\n        \"lineComment\": [\"#\"]\n    },\n\n    \"hx\": {\n        \"name\": \"Haxe\",\n        \"mode\": \"haxe\",\n        \"fileExtensions\": [\"hx\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"bash\": {\n        \"name\": \"Bash\",\n        \"mode\": [\"shell\", \"text/x-sh\"],\n        \"fileExtensions\": [\"sh\", \"command\", \"bash\"],\n        \"fileNames\": [\".bash_login\", \".bash_logout\", \".bash_profile\", \".bashrc\", \".profile\"],\n        \"lineComment\": [\"#\"]\n    },\n  \n    \"image\": {\n        \"name\": \"Image\",\n        \"fileExtensions\": [\"gif\", \"png\", \"jpe\", \"jpeg\", \"jpg\", \"ico\", \"bmp\", \"webp\"],\n        \"isBinary\": true\n    },\n    \n    \"audio\": {\n        \"name\": \"Audio\",\n        \"fileExtensions\": [\"mp3\", \"wav\", \"aif\", \"aiff\", \"ogg\"],\n        \"isBinary\": true\n    },\n    \n    \"binary\": {\n        \"name\": \"Other Binary\",\n        \"fileExtensions\": [\n            \"a\", \"ai\", \"avi\", \"bin\", \"cab\", \"com\", \"db\", \"dll\", \"dmg\",\n            \"doc\", \"docx\", \"dot\", \"dotx\", \"dsym\", \"dylib\", \"egg\", \"epub\", \"eot\",\n            \"exe\", \"flv\", \"gz\", \"gzip\", \"htmz\", \"htmlz\", \"ipch\", \"iso\", \"jar\",\n            \"jsz\", \"lib\", \"mpeg\", \"mpg\", \"mp4\", \"msi\", \"node\", \"o\", \"obj\", \"odc\",\n            \"odb\", \"odf\", \"odg\", \"odp\", \"ods\", \"odt\", \"otf\", \"pak\", \"pdb\", \"pdf\",\n            \"pdi\", \"ppt\", \"pptx\", \"psd\", \"rar\", \"sdf\", \"so\", \"sqlite\", \"suo\", \"svgz\",\n            \"swf\", \"tar\", \"tif\", \"tiff\", \"ttf\", \"woff\", \"xls\", \"xlsx\", \"zip\", \"xd\"\n        ],\n        \"isBinary\": true\n    },\n\n    \"haskell\": {\n        \"name\": \"Haskell\",\n        \"mode\": \"haskell\",\n        \"fileExtensions\": [\"hs\"],\n        \"blockComment\": [\"{-\", \"-}\"],\n        \"lineComment\": [\"--\"]\n    },\n    \n    \"turtle\": {\n        \"name\": \"RDF Turtle\",\n        \"mode\": \"turtle\",\n        \"fileExtensions\": [\"ttl\"],\n        \"lineComment\": [\"#\"]\n    },\n    \n    \"go\": {\n        \"name\": \"Go\",\n        \"mode\": \"go\",\n        \"fileExtensions\": [\"go\"],\n        \"blockComment\": [\"/*\", \"*/\"],\n        \"lineComment\": [\"//\"]\n    },\n\n    \"pug\": {\n        \"name\": \"Pug\",\n        \"mode\": \"pug\",\n        \"fileExtensions\": [\"pug\", \"jade\"],\n        \"lineComment\": [\"//\"]\n    }\n\n}\n"
  },
  {
    "path": "src/languageTools/BracketsToNodeInterface.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint no-invalid-this: 0*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    function BracketsToNodeInterface(domain) {\n        this.domain = domain;\n        this.bracketsFn = {};\n\n        this._registerDataEvent();\n    }\n\n    BracketsToNodeInterface.prototype._messageHandler = function (evt, params) {\n        var methodName = params.method,\n            self = this;\n\n        function _getErrorString(err) {\n            if (typeof err === \"string\") {\n                return err;\n            } else if (err && err.name && err.name === \"Error\") {\n                return err.message;\n            }\n            return \"Error in executing \" + methodName;\n\n        }\n\n        function _sendResponse(response) {\n            var responseParams = {\n                requestId: params.requestId,\n                params: response\n            };\n            self.domain.exec(\"response\", responseParams);\n        }\n\n        function _sendError(err) {\n            var responseParams = {\n                requestId: params.requestId,\n                error: _getErrorString(err)\n            };\n            self.domain.exec(\"response\", responseParams);\n        }\n\n        if (self.bracketsFn[methodName]) {\n            var method = self.bracketsFn[methodName];\n            try {\n                var response = method.call(null, params.params);\n                if (params.respond && params.requestId) {\n                    if (response.promise) {\n                        response.done(function (result) {\n                            _sendResponse(result);\n                        }).fail(function (err) {\n                            _sendError(err);\n                        });\n                    } else {\n                        _sendResponse(response);\n                    }\n                }\n            } catch (err) {\n                if (params.respond && params.requestId) {\n                    _sendError(err);\n                }\n            }\n        }\n\n    };\n\n\n    BracketsToNodeInterface.prototype._registerDataEvent = function () {\n        this.domain.on(\"data\", this._messageHandler.bind(this));\n    };\n\n    BracketsToNodeInterface.prototype.createInterface = function (methodName, isAsync) {\n        var self = this;\n        return function (params) {\n            var execEvent = isAsync ? \"asyncData\" : \"data\";\n            var callObject = {\n                method: methodName,\n                params: params\n            };\n            return self.domain.exec(execEvent, callObject);\n        };\n    };\n\n    BracketsToNodeInterface.prototype.registerMethod = function (methodName, methodHandle) {\n        if (methodName && methodHandle &&\n            typeof methodName === \"string\" && typeof methodHandle === \"function\") {\n            this.bracketsFn[methodName] = methodHandle;\n        }\n    };\n\n    BracketsToNodeInterface.prototype.registerMethods = function (methodList) {\n        var self = this;\n        methodList.forEach(function (methodObj) {\n            self.registerMethod(methodObj.methodName, methodObj.methodHandle);\n        });\n    };\n\n    exports.BracketsToNodeInterface = BracketsToNodeInterface;\n});\n"
  },
  {
    "path": "src/languageTools/ClientLoader.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint no-console: 0*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var ToolingInfo = JSON.parse(require(\"text!languageTools/ToolingInfo.json\")),\n        NodeDomain = require(\"utils/NodeDomain\"),\n        FileUtils = require(\"file/FileUtils\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        BracketsToNodeInterface = require(\"languageTools/BracketsToNodeInterface\").BracketsToNodeInterface;\n\n    EventDispatcher.makeEventDispatcher(exports);\n    //Register paths required for Language Client and also register default brackets capabilities.\n    var _bracketsPath = FileUtils.getNativeBracketsDirectoryPath();\n    // The native directory path ends with either \"test\" or \"src\".\n    _bracketsPath = _bracketsPath.replace(/\\/test$/, \"/src\"); // convert from \"test\" to \"src\"\n\n    var _modulePath = FileUtils.getNativeModuleDirectoryPath(module),\n        _nodePath = \"node/RegisterLanguageClientInfo\",\n        _domainPath = [_bracketsPath, _modulePath, _nodePath].join(\"/\"),\n        clientInfoDomain = null,\n        clientInfoLoadedPromise = null,\n        //Clients that have to be loaded once the LanguageClient info is successfully loaded on the\n        //node side.\n        pendingClientsToBeLoaded = [];\n\n    function syncPrefsWithDomain(languageToolsPrefs) {\n        if (clientInfoDomain) {\n            clientInfoDomain.exec(\"syncPreferences\", languageToolsPrefs);\n        }\n    }\n\n    function _createNodeDomain(domainName, domainPath) {\n        return new NodeDomain(domainName, domainPath);\n    }\n\n    function loadLanguageClientDomain(clientName, domainPath) {\n        //generate a random hash name for the domain, this is the client id\n        var domainName = clientName,\n            result = $.Deferred(),\n            languageClientDomain = _createNodeDomain(domainName, domainPath);\n\n        if (languageClientDomain) {\n            languageClientDomain.promise()\n                .done(function () {\n                    console.log(domainPath + \" domain successfully created\");\n                    result.resolve(languageClientDomain);\n                })\n                .fail(function (err) {\n                    console.error(domainPath + \" domain could not be created.\");\n                    result.reject();\n                });\n        } else {\n            console.error(domainPath + \" domain could not be created.\");\n            result.reject();\n        }\n\n        return result;\n    }\n\n    function createNodeInterfaceForDomain(languageClientDomain) {\n        var nodeInterface = new BracketsToNodeInterface(languageClientDomain);\n\n        return nodeInterface;\n    }\n\n    function _clientLoader(clientName, clientFilePath, clientPromise) {\n        loadLanguageClientDomain(clientName, clientFilePath)\n            .then(function (languageClientDomain) {\n                var languageClientInterface = createNodeInterfaceForDomain(languageClientDomain);\n\n                clientPromise.resolve({\n                    name: clientName,\n                    interface: languageClientInterface\n                });\n            }, clientPromise.reject);\n    }\n\n    function initiateLanguageClient(clientName, clientFilePath) {\n        var result = $.Deferred();\n\n        //Only load clients after the LanguageClient Info has been initialized\n        if (!clientInfoLoadedPromise || clientInfoLoadedPromise.state() === \"pending\") {\n            var pendingClient = {\n                load: _clientLoader.bind(null, clientName, clientFilePath, result)\n            };\n            pendingClientsToBeLoaded.push(pendingClient);\n        } else {\n            _clientLoader(clientName, clientFilePath, result);\n        }\n\n        return result;\n    }\n\n    /**\n     * This function passes Brackets's native directory path as well as the tooling commands\n     * required by the LanguageClient node module. This information is then maintained in memory\n     * in the node process server for succesfully loading and functioning of all language clients\n     * since it is a direct dependency.\n     */\n    function sendLanguageClientInfo() {\n        //Init node with Information required by Language Client\n        clientInfoLoadedPromise = clientInfoDomain.exec(\"initialize\", _bracketsPath, ToolingInfo);\n\n        function logInitializationError() {\n            console.error(\"Failed to Initialize LanguageClient Module Information.\");\n        }\n\n        //Attach success and failure function for the clientInfoLoadedPromise\n        clientInfoLoadedPromise.then(function (success) {\n            if (!success) {\n                logInitializationError();\n                return;\n            }\n\n            if (Array.isArray(pendingClientsToBeLoaded)) {\n                pendingClientsToBeLoaded.forEach(function (pendingClient) {\n                    pendingClient.load();\n                });\n            } else {\n                exports.trigger(\"languageClientModuleInitialized\");\n            }\n            pendingClientsToBeLoaded = null;\n        }, function () {\n            logInitializationError();\n        });\n    }\n\n    /**\n     * This function starts a domain which initializes the LanguageClient node module\n     * required by the Language Server Protocol framework in Brackets. All the LSP clients\n     * can only be successfully initiated once this domain has been successfully loaded and\n     * the LanguageClient info initialized. Refer to sendLanguageClientInfo for more.\n     */\n    function initDomainAndHandleNodeCrash() {\n        clientInfoDomain = new NodeDomain(\"LanguageClientInfo\", _domainPath);\n        //Initialize LanguageClientInfo once the domain has successfully loaded.\n        clientInfoDomain.promise().done(function () {\n            sendLanguageClientInfo();\n            //This is to handle the node failure. If the node process dies, we get an on close\n            //event on the websocket connection object. Brackets then spawns another process and\n            //restablishes the connection. Once the connection is restablished we send reinitialize\n            //the LanguageClient info.\n            clientInfoDomain.connection.on(\"close\", function (event, reconnectedPromise) {\n                reconnectedPromise.done(sendLanguageClientInfo);\n            });\n        }).fail(function (err) {\n            console.error(\"ClientInfo domain could not be loaded: \", err);\n        });\n    }\n    initDomainAndHandleNodeCrash();\n\n\n    exports.initiateLanguageClient = initiateLanguageClient;\n    exports.syncPrefsWithDomain = syncPrefsWithDomain;\n});\n"
  },
  {
    "path": "src/languageTools/DefaultEventHandlers.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* eslint-disable indent */\n/* eslint no-console: 0*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var LanguageManager = require(\"language/LanguageManager\"),\n        ProjectManager = require(\"project/ProjectManager\"),\n        PathConverters = require(\"languageTools/PathConverters\");\n\n    function EventPropagationProvider(client) {\n        this.client = client;\n        this.previousProject = \"\";\n        this.currentProject = ProjectManager.getProjectRoot();\n    }\n\n    EventPropagationProvider.prototype._sendDocumentOpenNotification = function (languageId, doc) {\n        if (!this.client) {\n            return;\n        }\n\n        if (this.client._languages.includes(languageId)) {\n            this.client.notifyTextDocumentOpened({\n                languageId: languageId,\n                filePath: (doc.file._path || doc.file.fullPath),\n                fileContent: doc.getText()\n            });\n        }\n    };\n\n    EventPropagationProvider.prototype.handleActiveEditorChange = function (event, current, previous) {\n        var self = this;\n\n        if (!this.client) {\n            return;\n        }\n\n        if (previous) {\n            previous.document\n                .off(\"languageChanged.language-tools\");\n            var previousLanguageId = LanguageManager.getLanguageForPath(previous.document.file.fullPath).getId();\n            if (this.client._languages.includes(previousLanguageId)) {\n                this.client.notifyTextDocumentClosed({\n                    filePath: (previous.document.file._path || previous.document.file.fullPath)\n                });\n            }\n        }\n        if (current) {\n            var currentLanguageId = LanguageManager.getLanguageForPath(current.document.file.fullPath).getId();\n            current.document\n                .on(\"languageChanged.language-tools\", function () {\n                    var languageId = LanguageManager.getLanguageForPath(current.document.file.fullPath).getId();\n                    self._sendDocumentOpenNotification(languageId, current.document);\n                });\n            self._sendDocumentOpenNotification(currentLanguageId, current.document);\n        }\n    };\n\n    EventPropagationProvider.prototype.handleProjectOpen = function (event, directory) {\n        if (!this.client) {\n            return;\n        }\n\n        this.currentProject = directory.fullPath;\n\n        this.client.notifyProjectRootsChanged({\n            foldersAdded: [this.currentProject],\n            foldersRemoved: [this.previousProject]\n        });\n    };\n\n    EventPropagationProvider.prototype.handleProjectClose = function (event, directory) {\n        if (!this.client) {\n            return;\n        }\n\n        this.previousProject = directory.fullPath;\n    };\n\n    EventPropagationProvider.prototype.handleDocumentDirty = function (event, doc) {\n        if (!this.client) {\n            return;\n        }\n\n        if (!doc.isDirty) {\n            var docLanguageId = LanguageManager.getLanguageForPath(doc.file.fullPath).getId();\n            if (this.client._languages.includes(docLanguageId)) {\n                this.client.notifyTextDocumentSave({\n                    filePath: (doc.file._path || doc.file.fullPath)\n                });\n            }\n        }\n    };\n\n    EventPropagationProvider.prototype.handleDocumentChange = function (event, doc, changeList) {\n        if (!this.client) {\n            return;\n        }\n\n        var docLanguageId = LanguageManager.getLanguageForPath(doc.file.fullPath).getId();\n        if (this.client._languages.includes(docLanguageId)) {\n            this.client.notifyTextDocumentChanged({\n                filePath: (doc.file._path || doc.file.fullPath),\n                fileContent: doc.getText()\n            });\n        }\n    };\n\n    EventPropagationProvider.prototype.handleDocumentRename = function (event, oldName, newName) {\n        if (!this.client) {\n            return;\n        }\n\n        var oldDocLanguageId = LanguageManager.getLanguageForPath(oldName).getId();\n        if (this.client._languages.includes(oldDocLanguageId)) {\n            this.client.notifyTextDocumentClosed({\n                filePath: oldName\n            });\n        }\n\n        var newDocLanguageId = LanguageManager.getLanguageForPath(newName).getId();\n        if (this.client._languages.includes(newDocLanguageId)) {\n            this.client.notifyTextDocumentOpened({\n                filePath: newName\n            });\n        }\n    };\n\n    EventPropagationProvider.prototype.handleAppClose = function (event) {\n        //Also handles Reload with Extensions\n        if (!this.client) {\n            return;\n        }\n\n        this.client.stop();\n    };\n\n    function handleProjectFoldersRequest(event) {\n        var projectRoot = ProjectManager.getProjectRoot(),\n            workspaceFolders = [projectRoot];\n\n        workspaceFolders = PathConverters.convertToWorkspaceFolders(workspaceFolders);\n\n        return $.Deferred().resolve(workspaceFolders);\n    };\n\n    EventPropagationProvider.prototype.registerClientForEditorEvent = function () {\n        if (this.client) {\n            var handleActiveEditorChange = this.handleActiveEditorChange.bind(this),\n                handleProjectOpen = this.handleProjectOpen.bind(this),\n                handleProjectClose = this.handleProjectClose.bind(this),\n                handleDocumentDirty = this.handleDocumentDirty.bind(this),\n                handleDocumentChange = this.handleDocumentChange.bind(this),\n                handleDocumentRename = this.handleDocumentRename.bind(this),\n                handleAppClose = this.handleAppClose.bind(this);\n\n            this.client.addOnEditorChangeHandler(handleActiveEditorChange);\n            this.client.addOnProjectOpenHandler(handleProjectOpen);\n            this.client.addBeforeProjectCloseHandler(handleProjectClose);\n            this.client.addOnDocumentDirtyFlagChangeHandler(handleDocumentDirty);\n            this.client.addOnDocumentChangeHandler(handleDocumentChange);\n            this.client.addOnFileRenameHandler(handleDocumentRename);\n            this.client.addBeforeAppClose(handleAppClose);\n            this.client.onProjectFoldersRequest(handleProjectFoldersRequest);\n        } else {\n            console.log(\"No client provided for event propagation\");\n        }\n    };\n\n    exports.EventPropagationProvider = EventPropagationProvider;\n});\n"
  },
  {
    "path": "src/languageTools/DefaultProviders.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global Map*/\n/* eslint-disable indent */\n/* eslint max-len: [\"error\", { \"code\": 200 }], no-invalid-this: 0*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = brackets.getModule(\"thirdparty/lodash\");\n\n    var EditorManager = require('editor/EditorManager'),\n        DocumentManager = require('document/DocumentManager'),\n        ExtensionUtils = require(\"utils/ExtensionUtils\"),\n        CommandManager = require(\"command/CommandManager\"),\n        Commands = require(\"command/Commands\"),\n        TokenUtils = require(\"utils/TokenUtils\"),\n        StringMatch = require(\"utils/StringMatch\"),\n        CodeInspection = require(\"language/CodeInspection\"),\n        PathConverters = require(\"languageTools/PathConverters\"),\n        matcher = new StringMatch.StringMatcher({\n            preferPrefixMatches: true\n        });\n\n    ExtensionUtils.loadStyleSheet(module, \"styles/default_provider_style.css\");\n\n    function setClient(client) {\n        if (client) {\n            this.client = client;\n        }\n    }\n\n    function CodeHintsProvider(client) {\n        this.client = client;\n        this.query = \"\";\n        this.ignoreQuery = [\"-\", \"->\", \">\", \":\", \"::\", \"(\", \"()\", \")\", \"[\", \"[]\", \"]\", \"{\", \"{}\", \"}\"];\n    }\n\n    CodeHintsProvider.prototype.setClient = setClient;\n\n    function formatTypeDataForToken($hintObj, token) {\n        $hintObj.addClass('brackets-hints-with-type-details');\n        if (token.detail) {\n            if (token.detail.trim() !== '?') {\n                if (token.detail.length < 30) {\n                    $('<span>' + token.detail.split('->').join(':').toString().trim() + '</span>').appendTo($hintObj).addClass(\"brackets-hints-type-details\");\n                }\n                $('<span>' + token.detail.split('->').join(':').toString().trim() + '</span>').appendTo($hintObj).addClass(\"hint-description\");\n            }\n        } else {\n            if (token.keyword) {\n                $('<span>keyword</span>').appendTo($hintObj).addClass(\"brackets-hints-keyword\");\n            }\n        }\n        if (token.documentation) {\n            $hintObj.attr('title', token.documentation);\n            $('<span></span>').text(token.documentation.trim()).appendTo($hintObj).addClass(\"hint-doc\");\n        }\n    }\n\n    function filterWithQueryAndMatcher(hints, query) {\n        var matchResults = $.map(hints, function (hint) {\n            var searchResult = matcher.match(hint.label, query);\n            if (searchResult) {\n                for (var key in hint) {\n                    searchResult[key] = hint[key];\n                }\n            }\n\n            return searchResult;\n        });\n\n        return matchResults;\n    }\n\n    CodeHintsProvider.prototype.hasHints = function (editor, implicitChar) {\n        if (!this.client) {\n            return false;\n        }\n\n        var serverCapabilities = this.client.getServerCapabilities();\n        if (!serverCapabilities || !serverCapabilities.completionProvider) {\n            return false;\n        }\n\n        return true;\n    };\n\n    CodeHintsProvider.prototype.getHints = function (implicitChar) {\n        if (!this.client) {\n            return null;\n        }\n\n        var editor = EditorManager.getActiveEditor(),\n            pos = editor.getCursorPos(),\n            docPath = editor.document.file._path,\n            $deferredHints = $.Deferred(),\n            self = this;\n\n        this.client.requestHints({\n            filePath: docPath,\n            cursorPos: pos\n        }).done(function (msgObj) {\n            var context = TokenUtils.getInitialContext(editor._codeMirror, pos),\n                hints = [];\n\n            self.query = context.token.string.slice(0, context.pos.ch - context.token.start);\n            if (msgObj) {\n                var res = msgObj.items,\n                    filteredHints = filterWithQueryAndMatcher(res, self.query);\n\n                StringMatch.basicMatchSort(filteredHints);\n                filteredHints.forEach(function (element) {\n                    var $fHint = $(\"<span>\")\n                        .addClass(\"brackets-hints\");\n\n                    if (element.stringRanges) {\n                        element.stringRanges.forEach(function (item) {\n                            if (item.matched) {\n                                $fHint.append($(\"<span>\")\n                                    .append(_.escape(item.text))\n                                    .addClass(\"matched-hint\"));\n                            } else {\n                                $fHint.append(_.escape(item.text));\n                            }\n                        });\n                    } else {\n                        $fHint.text(element.label);\n                    }\n\n                    $fHint.data(\"token\", element);\n                    formatTypeDataForToken($fHint, element);\n                    hints.push($fHint);\n                });\n            }\n\n            $deferredHints.resolve({\n                \"hints\": hints\n            });\n        }).fail(function () {\n            $deferredHints.reject();\n        });\n\n        return $deferredHints;\n    };\n\n    CodeHintsProvider.prototype.insertHint = function ($hint) {\n        var editor = EditorManager.getActiveEditor(),\n            cursor = editor.getCursorPos(),\n            token = $hint.data(\"token\"),\n            txt = null,\n            query = this.query,\n            shouldIgnoreQuery = this.ignoreQuery.includes(query),\n            inclusion = shouldIgnoreQuery ? \"\" : query,\n            start = {\n                line: cursor.line,\n                ch: cursor.ch - inclusion.length\n            },\n            end = {\n                line: cursor.line,\n                ch: cursor.ch\n            };\n\n        txt = token.label;\n        if (token.textEdit && token.textEdit.newText) {\n            txt = token.textEdit.newText;\n            start = {\n                line: token.textEdit.range.start.line,\n                ch: token.textEdit.range.start.character\n            };\n            end = {\n                line: token.textEdit.range.end.line,\n                ch: token.textEdit.range.end.character\n            };\n        }\n\n        if (editor) {\n            editor.document.replaceRange(txt, start, end);\n        }\n        // Return false to indicate that another hinting session is not needed\n        return false;\n    };\n\n    function ParameterHintsProvider(client) {\n        this.client = client;\n    }\n\n    ParameterHintsProvider.prototype.setClient = setClient;\n\n    ParameterHintsProvider.prototype.hasParameterHints = function (editor, implicitChar) {\n        if (!this.client) {\n            return false;\n        }\n\n        var serverCapabilities = this.client.getServerCapabilities();\n        if (!serverCapabilities || !serverCapabilities.signatureHelpProvider) {\n            return false;\n        }\n\n        return true;\n    };\n\n    ParameterHintsProvider.prototype.getParameterHints = function () {\n        if (!this.client) {\n            return null;\n        }\n\n        var editor = EditorManager.getActiveEditor(),\n            pos = editor.getCursorPos(),\n            docPath = editor.document.file._path,\n            $deferredHints = $.Deferred();\n\n        this.client.requestParameterHints({\n            filePath: docPath,\n            cursorPos: pos\n        }).done(function (msgObj) {\n            let paramList = [];\n            let label;\n            let activeParameter;\n            if (msgObj) {\n                let res;\n                res = msgObj.signatures;\n                activeParameter = msgObj.activeParameter;\n                if (res && res.length) {\n                    res.forEach(function (element) {\n                        label = element.documentation;\n                        let param = element.parameters;\n                        param.forEach(ele => {\n                            paramList.push({\n                                label: ele.label,\n                                documentation: ele.documentation\n                            });\n                        });\n                    });\n\n                    $deferredHints.resolve({\n                        parameters: paramList,\n                        currentIndex: activeParameter,\n                        functionDocumentation: label\n                    });\n                } else {\n                    $deferredHints.reject();\n                }\n            } else {\n                $deferredHints.reject();\n            }\n        }).fail(function () {\n            $deferredHints.reject();\n        });\n\n        return $deferredHints;\n    };\n\n    /**\n     * Utility function to make the jump\n     * @param   {Object} curPos - target postion for the cursor after the jump\n     */\n    function setJumpPosition(curPos) {\n        EditorManager.getCurrentFullEditor().setCursorPos(curPos.line, curPos.ch, true);\n    }\n\n    function JumpToDefProvider(client) {\n        this.client = client;\n    }\n\n    JumpToDefProvider.prototype.setClient = setClient;\n\n    JumpToDefProvider.prototype.canJumpToDef = function (editor, implicitChar) {\n        if (!this.client) {\n            return false;\n        }\n\n        var serverCapabilities = this.client.getServerCapabilities();\n        if (!serverCapabilities || !serverCapabilities.definitionProvider) {\n            return false;\n        }\n\n        return true;\n    };\n\n    /**\n     * Method to handle jump to definition feature.\n     */\n    JumpToDefProvider.prototype.doJumpToDef = function () {\n        if (!this.client) {\n            return null;\n        }\n\n        var editor = EditorManager.getFocusedEditor(),\n            pos = editor.getCursorPos(),\n            docPath = editor.document.file._path,\n            docPathUri = PathConverters.pathToUri(docPath),\n            $deferredHints = $.Deferred();\n\n        this.client.gotoDefinition({\n            filePath: docPath,\n            cursorPos: pos\n        }).done(function (msgObj) {\n            //For Older servers\n            if (Array.isArray(msgObj)) {\n                msgObj = msgObj[msgObj.length - 1];\n            }\n\n            if (msgObj && msgObj.range) {\n                var docUri = msgObj.uri,\n                    startCurPos = {};\n                startCurPos.line = msgObj.range.start.line;\n                startCurPos.ch = msgObj.range.start.character;\n\n                if (docUri !== docPathUri) {\n                    let documentPath = PathConverters.uriToPath(docUri);\n                    CommandManager.execute(Commands.FILE_OPEN, {\n                            fullPath: documentPath\n                        })\n                        .done(function () {\n                            setJumpPosition(startCurPos);\n                            $deferredHints.resolve();\n                        });\n                } else { //definition is in current document\n                    setJumpPosition(startCurPos);\n                    $deferredHints.resolve();\n                }\n            }\n        }).fail(function () {\n            $deferredHints.reject();\n        });\n\n        return $deferredHints;\n    };\n\n    function LintingProvider() {\n        this._results = new Map();\n        this._promiseMap = new Map();\n        this._validateOnType = false;\n    }\n\n    LintingProvider.prototype.setClient = setClient;\n\n    LintingProvider.prototype.clearExistingResults = function (filePath) {\n        var filePathProvided = !!filePath;\n\n        if (filePathProvided) {\n            this._results.delete(filePath);\n            this._promiseMap.delete(filePath);\n        } else {\n            //clear all results\n            this._results.clear();\n            this._promiseMap.clear();\n        }\n    };\n\n    /**\n     * Publish the diagnostics information related to current document\n     * @param   {Object} msgObj - json object containing information associated with 'textDocument/publishDiagnostics' notification from server\n     */\n    LintingProvider.prototype.setInspectionResults = function (msgObj) {\n        let diagnostics = msgObj.diagnostics,\n            filePath = PathConverters.uriToPath(msgObj.uri),\n            errors = [];\n\n        errors = diagnostics.map(function (obj) {\n            return {\n                pos: {\n                    line: obj.range.start.line,\n                    ch: obj.range.start.character\n                },\n                message: obj.message,\n                type: (obj.severity === 1 ? CodeInspection.Type.ERROR : (obj.severity === 2 ? CodeInspection.Type.WARNING : CodeInspection.Type.META))\n            };\n        });\n\n        this._results.set(filePath, {\n            errors: errors\n        });\n        if(this._promiseMap.get(filePath)) {\n           this._promiseMap.get(filePath).resolve(this._results.get(filePath));\n           this._promiseMap.delete(filePath);\n        }\n        if (this._validateOnType) {\n            var editor = EditorManager.getActiveEditor(),\n                docPath = editor ? editor.document.file._path : \"\";\n            if (filePath === docPath) {\n                CodeInspection.requestRun();\n            }\n        }\n    };\n\n    LintingProvider.prototype.getInspectionResultsAsync = function (fileText, filePath) {\n        var result = $.Deferred();\n\n        if (this._results.get(filePath)) {\n            return result.resolve(this._results.get(filePath));\n        }\n        this._promiseMap.set(filePath, result);\n        return result;\n    };\n\n    LintingProvider.prototype.getInspectionResults = function (fileText, filePath) {\n        return this._results.get(filePath);\n    };\n\n    function serverRespToSearchModelFormat(msgObj) {\n        var referenceModel = {},\n            result = $.Deferred();\n\n        if(!(msgObj && msgObj.length && msgObj.cursorPos)) {\n            return result.reject();\n        }\n        referenceModel.results = {};\n        referenceModel.numFiles = 0;\n        var fulfilled = 0;\n        msgObj.forEach((element, i) => {\n            var filePath = PathConverters.uriToPath(element.uri);\n            DocumentManager.getDocumentForPath(filePath)\n                .done(function(doc) {\n                    var startRange = {line: element.range.start.line, ch: element.range.start.character};\n                    var endRange = {line: element.range.end.line, ch: element.range.end.character};\n                    var match = {\n                        start: startRange,\n                        end: endRange,\n                        highlightOffset: 0,\n                        line: doc.getLine(element.range.start.line)\n                    };\n                    if(!referenceModel.results[filePath]) {\n                        referenceModel.numFiles = referenceModel.numFiles + 1;\n                        referenceModel.results[filePath] = {\"matches\": []};\n                    }\n                    if(!referenceModel.queryInfo || msgObj.cursorPos.line === startRange.line) {\n                        referenceModel.queryInfo = doc.getRange(startRange, endRange);\n                    }\n                    referenceModel.results[filePath][\"matches\"].push(match);\n                }).always(function() {\n                    fulfilled++;\n                    if(fulfilled === msgObj.length) {\n                        referenceModel.numMatches = msgObj.length;\n                        referenceModel.allResultsAvailable = true;\n                        result.resolve(referenceModel);\n                    }\n                });\n        });\n        return result.promise();\n    }\n\n    function ReferencesProvider(client) {\n        this.client = client;\n    }\n\n    ReferencesProvider.prototype.setClient = setClient;\n\n    ReferencesProvider.prototype.hasReferences = function() {\n        if (!this.client) {\n            return false;\n        }\n\n        var serverCapabilities = this.client.getServerCapabilities();\n        if (!serverCapabilities || !serverCapabilities.referencesProvider) {\n            return false;\n        }\n\n        return true;\n    };\n\n    ReferencesProvider.prototype.getReferences = function(hostEditor, curPos) {\n        var editor = hostEditor || EditorManager.getActiveEditor(),\n            pos = curPos || editor ? editor.getCursorPos() : null,\n            docPath = editor.document.file._path,\n            result = $.Deferred();\n\n        if (this.client) {\n            this.client.findReferences({\n                filePath: docPath,\n                cursorPos: pos\n            }).done(function(msgObj){\n                    if(msgObj && msgObj.length) {\n                        msgObj.cursorPos = pos;\n                        serverRespToSearchModelFormat(msgObj)\n                            .done(result.resolve)\n                            .fail(result.reject);\n                    } else {\n                        result.reject();\n                    }\n                }).fail(function(){\n                    result.reject();\n                });\n            return result.promise();\n        }\n        return result.reject();\n    };\n\n    exports.CodeHintsProvider = CodeHintsProvider;\n    exports.ParameterHintsProvider = ParameterHintsProvider;\n    exports.JumpToDefProvider = JumpToDefProvider;\n    exports.LintingProvider = LintingProvider;\n    exports.ReferencesProvider = ReferencesProvider;\n    exports.serverRespToSearchModelFormat = serverRespToSearchModelFormat;\n});\n"
  },
  {
    "path": "src/languageTools/LanguageClient/Connection.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global exports */\n/*eslint no-console: 0*/\n/* eslint no-empty: [\"error\", { \"allowEmptyCatch\": true }] */\n(function () {\n    \"use strict\";\n\n    var protocol = require(\"vscode-languageserver-protocol\");\n\n    var Actions = {\n        OnClose: {\n            Stop: 0,\n            Restart: 1\n        },\n        OnError: {\n            Ignore: 0,\n            Stop: 1\n        }\n    };\n\n    function ActionController() {\n        this.restartsTimes = [];\n    }\n\n    ActionController.prototype.getOnErrorAction = function (errorData) {\n        var errorCount = errorData[2];\n\n        if (errorCount <= 3) {\n            return Actions.OnError.Ignore;\n        }\n\n        return Actions.OnError.Restart;\n    };\n\n    ActionController.prototype.getOnCloseAction = function () {\n        var currentTime = Date.now();\n        this.restartsTimes.push(currentTime);\n\n        var numRestarts = this.restartsTimes.length;\n        if (numRestarts < 5) {\n            return Actions.OnClose.Restart;\n        }\n\n        var timeBetweenFiveRestarts = this.restartsTimes[numRestarts - 1] - this.restartsTimes[0];\n        if (timeBetweenFiveRestarts <= 3 * 60 * 1000) { //3 minutes\n            return Actions.OnClose.Stop;\n        }\n\n        this.restartsTimes.shift();\n        return Actions.OnClose.Restart;\n    };\n\n    function _getOnCloseHandler(connection, actionController, restartLanguageClient) {\n        return function () {\n            try {\n                if (connection) {\n                    connection.dispose();\n                }\n            } catch (error) {}\n\n            var action = Actions.OnClose.Stop;\n            try {\n                action = actionController.getOnCloseAction();\n            } catch (error) {}\n\n\n            if (action === Actions.OnClose.Restart) {\n                restartLanguageClient();\n            }\n        };\n    }\n\n    function _getOnErrorHandler(actionController, stopLanguageClient) {\n        return function (errorData) {\n            var action = actionController.getOnErrorAction(errorData);\n\n            if (action === Actions.OnError.Stop) {\n                stopLanguageClient();\n            }\n        };\n    }\n\n    function Logger() {}\n\n    Logger.prototype.error = function (message) {\n        console.error(message);\n    };\n    Logger.prototype.warn = function (message) {\n        console.warn(message);\n    };\n    Logger.prototype.info = function (message) {\n        console.info(message);\n    };\n    Logger.prototype.log = function (message) {\n        console.log(message);\n    };\n\n    function createConnection(reader, writer, restartLanguageClient, stopLanguageClient) {\n        var logger = new Logger(),\n            actionController = new ActionController(),\n            connection = protocol.createProtocolConnection(reader, writer, logger),\n            errorHandler = _getOnErrorHandler(actionController, stopLanguageClient),\n            closeHandler = _getOnCloseHandler(connection, actionController, restartLanguageClient);\n\n        connection.onError(errorHandler);\n        connection.onClose(closeHandler);\n\n        return connection;\n    }\n\n    exports.createConnection = createConnection;\n}());\n"
  },
  {
    "path": "src/languageTools/LanguageClient/LanguageClient.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global exports, Promise, LanguageClientInfo */\n/*eslint no-console: 0*/\n/*eslint strict: [\"error\", \"global\"]*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\n\"use strict\";\n\nvar ProtocolAdapter = require(\"./ProtocolAdapter\"),\n    ServerUtils = require(\"./ServerUtils\"),\n    Connection = require(\"./Connection\"),\n    NodeToBracketsInterface = require(\"./NodeToBracketsInterface\").NodeToBracketsInterface,\n    ToolingInfo = LanguageClientInfo.toolingInfo,\n    MESSAGE_TYPE = {\n        BRACKETS: \"brackets\",\n        SERVER: \"server\"\n    };\n\nfunction validateHandler(handler) {\n    var retval = false;\n\n    if (handler && typeof handler === \"function\") {\n        retval = true;\n    } else {\n        console.warn(\"Handler validation failed. Handler should be of type 'function'. Provided handler is of type :\", typeof handler);\n    }\n\n    return retval;\n}\n\nfunction LanguageClient(clientName, domainManager, options) {\n    this._clientName = clientName;\n    this._bracketsInterface = null;\n    this._notifyBrackets = null;\n    this._requestBrackets = null;\n    this._connection = null,\n    this._startUpParams = null, //_projectRoot, capabilties, workspaceFolders etc.\n    this._initialized = false,\n    this._onRequestHandler = {};\n    this._onNotificationHandlers = {};\n    this._options = options || null;\n\n\n    this._init(domainManager);\n}\n\n\nLanguageClient.prototype._createConnection = function () {\n    if (!this._options || !this._options.serverOptions) {\n        return Promise.reject(\"No valid options provided for client :\", this._clientName);\n    }\n\n    var restartLanguageClient = this.start.bind(this),\n        stopLanguageClient = this.stop.bind(this);\n\n    var serverOptions = this._options.serverOptions;\n    return ServerUtils.startServerAndGetConnectionArgs(serverOptions)\n        .then(function (connectionArgs) {\n            return Connection.createConnection(connectionArgs.reader, connectionArgs.writer, restartLanguageClient, stopLanguageClient);\n        }).catch(function (err) {\n            console.error(\"Couldn't establish connection\", err);\n        });\n};\n\nLanguageClient.prototype.setOptions = function (options) {\n    if (options && typeof options === \"object\") {\n        this._options = options;\n    } else {\n        console.error(\"Invalid options provided for client :\", this._clientName);\n    }\n};\n\nLanguageClient.prototype.start = function (params) {\n    var self = this;\n\n    //Check to see if a connection to a language server already exists.\n    if (self._connection) {\n        return Promise.resolve(true);\n    }\n\n    self._connection = null;\n    self._startUpParams = params || self._startUpParams;\n\n    //We default to standard capabilties\n    if (!self._startUpParams.capabilities) {\n        self._startUpParams.capabilities = LanguageClientInfo.defaultBracketsCapabilities;\n    }\n\n    return self._createConnection()\n        .then(function (connection) {\n            connection.listen();\n            self._connection = connection;\n\n            return ProtocolAdapter.initialize(connection, self._startUpParams);\n        }).then(function (result) {\n            self._initialized = result;\n            ProtocolAdapter.attachOnNotificationHandlers(self._connection, self._notifyBrackets);\n            ProtocolAdapter.attachOnRequestHandlers(self._connection, self._requestBrackets);\n            ProtocolAdapter.initialized(self._connection);\n            return result;\n        }).catch(function (error) {\n            console.error('Starting client failed because :', error);\n            console.error('Couldn\\'t start client :', self._clientName);\n\n            return error;\n        });\n};\n\nLanguageClient.prototype.stop = function () {\n    var self = this;\n\n    self._initialized = false;\n    if (!self._connection) {\n        return Promise.resolve(true);\n    }\n\n\n    return ProtocolAdapter.shutdown(self._connection).then(function () {\n        ProtocolAdapter.exit(self._connection);\n        self._connection.dispose();\n        self._connection = null;\n    });\n};\n\nLanguageClient.prototype.request = function (params) {\n    var messageParams = params.params;\n    if (messageParams && messageParams.messageType === MESSAGE_TYPE.BRACKETS) {\n        if (!messageParams.type) {\n            console.log(\"Invalid brackets request\");\n            return Promise.reject();\n        }\n\n        var requestHandler = this._onRequestHandler[messageParams.type];\n        if(validateHandler(requestHandler)) {\n            return requestHandler.call(null, messageParams.params);\n        }\n        console.log(\"No handler provided for brackets request type : \", messageParams.type);\n        return Promise.reject();\n    }\n    return ProtocolAdapter.processRequest(this._connection, params);\n\n};\n\nLanguageClient.prototype.notify = function (params) {\n    var messageParams = params.params;\n    if (messageParams && messageParams.messageType === MESSAGE_TYPE.BRACKETS) {\n        if (!messageParams.type) {\n            console.log(\"Invalid brackets notification\");\n            return;\n        }\n\n        var notificationHandlers = this._onNotificationHandlers[messageParams.type];\n        if(notificationHandlers && Array.isArray(notificationHandlers) && notificationHandlers.length) {\n            notificationHandlers.forEach(function (handler) {\n                if(validateHandler(handler)) {\n                    handler.call(null, messageParams.params);\n                }\n            });\n        } else {\n            console.log(\"No handlers provided for brackets notification type : \", messageParams.type);\n        }\n    } else {\n        ProtocolAdapter.processNotification(this._connection, params);\n    }\n};\n\nLanguageClient.prototype.addOnRequestHandler = function (type, handler) {\n    if (validateHandler(handler)) {\n        this._onRequestHandler[type] = handler;\n    }\n};\n\nLanguageClient.prototype.addOnNotificationHandler = function (type, handler) {\n    if (validateHandler(handler)) {\n        if (!this._onNotificationHandlers[type]) {\n            this._onNotificationHandlers[type] = [];\n        }\n\n        this._onNotificationHandlers[type].push(handler);\n    }\n};\n\nLanguageClient.prototype._init = function (domainManager) {\n    this._bracketsInterface = new NodeToBracketsInterface(domainManager, this._clientName);\n\n    //Expose own methods for interfaceing. All these are async except notify.\n    this._bracketsInterface.registerMethods([\n        {\n            methodName: ToolingInfo.LANGUAGE_SERVICE.START,\n            methodHandle: this.start.bind(this)\n        },\n        {\n            methodName: ToolingInfo.LANGUAGE_SERVICE.STOP,\n            methodHandle: this.stop.bind(this)\n        },\n        {\n            methodName: ToolingInfo.LANGUAGE_SERVICE.REQUEST,\n            methodHandle: this.request.bind(this)\n        },\n        {\n            methodName: ToolingInfo.LANGUAGE_SERVICE.NOTIFY,\n            methodHandle: this.notify.bind(this)\n        }\n    ]);\n\n    //create function interfaces for Brackets\n    this._notifyBrackets = this._bracketsInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.NOTIFY);\n    this._requestBrackets = this._bracketsInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.REQUEST, true);\n};\n\nexports.LanguageClient = LanguageClient;\n"
  },
  {
    "path": "src/languageTools/LanguageClient/NodeToBracketsInterface.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global require, Promise, exports*/\n/*eslint no-invalid-this: 0*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\n(function () {\n\n    \"use strict\";\n\n    var EventEmitter = require(\"events\"),\n        bracketsEventHandler = new EventEmitter();\n\n    /** https://gist.github.com/LeverOne/1308368 */\n    /*eslint-disable */\n    function _generateUUID() {\n        var result,\n            numericSeed;\n        for (\n            result = numericSeed = '';\n            numericSeed++ < 36;\n            result += numericSeed * 51 & 52 ? (numericSeed ^ 15 ? 8 ^ Math.random() * (numericSeed ^ 20 ? 16 : 4) : 4).toString(16) : '-'\n        );\n\n        return result;\n    }\n    /*eslint-enable */\n\n    function NodeToBracketsInterface(domainManager, domainName) {\n        this.domainManager = domainManager;\n        this.domainName = domainName;\n        this.nodeFn = {};\n\n        this._registerDataEvents(domainManager, domainName);\n    }\n\n    NodeToBracketsInterface.prototype.processRequest = function (params) {\n        var methodName = params.method;\n        if (this.nodeFn[methodName]) {\n            var method = this.nodeFn[methodName];\n            return method.call(null, params.params);\n        }\n    };\n\n    NodeToBracketsInterface.prototype.processAsyncRequest = function (params, resolver) {\n        var methodName = params.method;\n        if (this.nodeFn[methodName]) {\n            var method = this.nodeFn[methodName];\n            method.call(null, params.params) //The Async function should return a promise\n                .then(function (result) {\n                    resolver(null, result);\n                }).catch(function (err) {\n                    resolver(err, null);\n                });\n        }\n    };\n\n    NodeToBracketsInterface.prototype.processResponse = function (params) {\n        if (params.requestId) {\n            if (params.error) {\n                bracketsEventHandler.emit(params.requestId, params.error);\n            } else {\n                bracketsEventHandler.emit(params.requestId, false, params.params);\n            }\n        } else {\n            bracketsEventHandler.emit(params.requestId, \"error\");\n        }\n    };\n\n    NodeToBracketsInterface.prototype.createInterface = function (methodName, respond) {\n        var self = this;\n        return function (params) {\n            var callObject = {\n                method: methodName,\n                params: params\n            };\n\n            var retval = undefined;\n            if (respond) {\n                var requestId = _generateUUID();\n\n                callObject[\"respond\"] = true;\n                callObject[\"requestId\"] = requestId;\n\n                self.domainManager.emitEvent(self.domainName, \"data\", callObject);\n\n                retval = new Promise(function (resolve, reject) {\n                    bracketsEventHandler.once(requestId, function (err, response) {\n                        if (err) {\n                            reject(err);\n                        } else {\n                            resolve(response);\n                        }\n                    });\n                });\n            } else {\n                self.domainManager.emitEvent(self.domainName, \"data\", callObject);\n            }\n            return retval;\n        };\n    };\n\n    NodeToBracketsInterface.prototype.registerMethod = function (methodName, methodHandle) {\n        var self = this;\n        if (methodName && methodHandle &&\n            typeof methodName === \"string\" && typeof methodHandle === \"function\") {\n            self.nodeFn[methodName] = methodHandle;\n        }\n    };\n\n    NodeToBracketsInterface.prototype.registerMethods = function (methodList) {\n        var self = this;\n        methodList.forEach(function (methodObj) {\n            self.registerMethod(methodObj.methodName, methodObj.methodHandle);\n        });\n    };\n\n    NodeToBracketsInterface.prototype._registerDataEvents = function (domainManager, domainName) {\n        if (!domainManager.hasDomain(domainName)) {\n            domainManager.registerDomain(domainName, {\n                major: 0,\n                minor: 1\n            });\n        }\n\n        domainManager.registerCommand(\n            domainName,\n            \"data\",\n            this.processRequest.bind(this),\n            false,\n            \"Receives sync request from brackets\",\n            [\n                {\n                    name: \"params\",\n                    type: \"object\",\n                    description: \"json object containing message info\"\n                }\n            ],\n            []\n        );\n\n        domainManager.registerCommand(\n            domainName,\n            \"response\",\n            this.processResponse.bind(this),\n            false,\n            \"Receives response from brackets for an earlier request\",\n            [\n                {\n                    name: \"params\",\n                    type: \"object\",\n                    description: \"json object containing message info\"\n                }\n            ],\n            []\n        );\n\n        domainManager.registerCommand(\n            domainName,\n            \"asyncData\",\n            this.processAsyncRequest.bind(this),\n            true,\n            \"Receives async call request from brackets\",\n            [\n                {\n                    name: \"params\",\n                    type: \"object\",\n                    description: \"json object containing message info\"\n                },\n                {\n                    name: \"resolver\",\n                    type: \"function\",\n                    description: \"callback required to resolve the async request\"\n                }\n            ],\n            []\n        );\n\n        domainManager.registerEvent(\n            domainName,\n            \"data\",\n            [\n                {\n                    name: \"params\",\n                    type: \"object\",\n                    description: \"json object containing message info to pass to brackets\"\n                }\n            ]\n        );\n    };\n\n    exports.NodeToBracketsInterface = NodeToBracketsInterface;\n}());\n"
  },
  {
    "path": "src/languageTools/LanguageClient/ProtocolAdapter.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global LanguageClientInfo*/\n/*eslint-env es6, node*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\n/*eslint no-fallthrough: 0*/\n\"use strict\";\n\nvar protocol = require(\"vscode-languageserver-protocol\"),\n    Utils = require(\"./Utils\"),\n    ToolingInfo = LanguageClientInfo.toolingInfo,\n    MESSAGE_FORMAT = {\n        BRACKETS: \"brackets\",\n        LSP: \"lsp\"\n    };\n\nfunction _constructParamsAndRelay(relay, type, params) {\n    var _params = null,\n        handler = null;\n\n    //Check for param object format. We won't change anything if the object is preformatted.\n    if (params.format === MESSAGE_FORMAT.LSP) {\n        params.format = undefined;\n        _params = JSON.parse(JSON.stringify(params));\n    }\n\n    switch (type) {\n    case ToolingInfo.LANGUAGE_SERVICE.CUSTOM_REQUEST:\n        return sendCustomRequest(relay, params.type, params.params);\n    case ToolingInfo.LANGUAGE_SERVICE.CUSTOM_NOTIFICATION:\n        {\n            sendCustomNotification(relay, params.type, params.params);\n            break;\n        }\n    case ToolingInfo.SERVICE_REQUESTS.SHOW_SELECT_MESSAGE:\n    case ToolingInfo.SERVICE_REQUESTS.REGISTRATION_REQUEST:\n    case ToolingInfo.SERVICE_REQUESTS.UNREGISTRATION_REQUEST:\n    case ToolingInfo.SERVICE_REQUESTS.PROJECT_FOLDERS_REQUEST:\n        {\n            _params = {\n                type: type,\n                params: params\n            };\n            return relay(_params);\n        }\n    case ToolingInfo.SERVICE_NOTIFICATIONS.SHOW_MESSAGE:\n    case ToolingInfo.SERVICE_NOTIFICATIONS.LOG_MESSAGE:\n    case ToolingInfo.SERVICE_NOTIFICATIONS.TELEMETRY:\n    case ToolingInfo.SERVICE_NOTIFICATIONS.DIAGNOSTICS:\n        {\n            _params = {\n                type: type,\n                params: params\n            };\n            relay(_params);\n            break;\n        }\n    case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_OPENED:\n        {\n            _params = _params || {\n                textDocument: {\n                    uri: Utils.pathToUri(params.filePath),\n                    languageId: params.languageId,\n                    version: 1,\n                    text: params.fileContent\n                }\n            };\n            didOpenTextDocument(relay, _params);\n            break;\n        }\n    case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_CHANGED:\n        {\n            _params = _params || {\n                textDocument: {\n                    uri: Utils.pathToUri(params.filePath),\n                    version: 1\n                },\n                contentChanges: [{\n                    text: params.fileContent\n                }]\n            };\n            didChangeTextDocument(relay, _params);\n            break;\n        }\n    case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_SAVED:\n        {\n            if (!_params) {\n                _params = {\n                    textDocument: {\n                        uri: Utils.pathToUri(params.filePath)\n                    }\n                };\n\n                if (params.fileContent) {\n                    _params['text'] = params.fileContent;\n                }\n            }\n            didSaveTextDocument(relay, _params);\n            break;\n        }\n    case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_CLOSED:\n        {\n            _params = _params || {\n                textDocument: {\n                    uri: Utils.pathToUri(params.filePath)\n                }\n            };\n\n            didCloseTextDocument(relay, _params);\n            break;\n        }\n    case ToolingInfo.SYNCHRONIZE_EVENTS.PROJECT_FOLDERS_CHANGED:\n        {\n            var foldersAdded = params.foldersAdded || [],\n                foldersRemoved = params.foldersRemoved || [];\n\n            foldersAdded = Utils.convertToWorkspaceFolders(foldersAdded);\n            foldersRemoved = Utils.convertToWorkspaceFolders(foldersRemoved);\n\n            _params = _params || {\n                event: {\n                    added: foldersAdded,\n                    removed: foldersRemoved\n                }\n            };\n            didChangeWorkspaceFolders(relay, _params);\n            break;\n        }\n    case ToolingInfo.FEATURES.CODE_HINTS:\n        handler = completion;\n    case ToolingInfo.FEATURES.PARAMETER_HINTS:\n        handler = handler || signatureHelp;\n    case ToolingInfo.FEATURES.JUMP_TO_DECLARATION:\n        handler = handler || gotoDeclaration;\n    case ToolingInfo.FEATURES.JUMP_TO_DEFINITION:\n        handler = handler || gotoDefinition;\n    case ToolingInfo.FEATURES.JUMP_TO_IMPL:\n        {\n            handler = handler || gotoImplementation;\n            _params = _params || {\n                textDocument: {\n                    uri: Utils.pathToUri(params.filePath)\n                },\n                position: Utils.convertToLSPPosition(params.cursorPos)\n            };\n\n            return handler(relay, _params);\n        }\n    case ToolingInfo.FEATURES.CODE_HINT_INFO:\n        {\n            return completionItemResolve(relay, params);\n        }\n    case ToolingInfo.FEATURES.FIND_REFERENCES:\n        {\n            _params = _params || {\n                textDocument: {\n                    uri: Utils.pathToUri(params.filePath)\n                },\n                position: Utils.convertToLSPPosition(params.cursorPos),\n                context: {\n                    includeDeclaration: params.includeDeclaration\n                }\n            };\n\n            return findReferences(relay, _params);\n        }\n    case ToolingInfo.FEATURES.DOCUMENT_SYMBOLS:\n        {\n            _params = _params || {\n                textDocument: {\n                    uri: Utils.pathToUri(params.filePath)\n                }\n            };\n\n            return documentSymbol(relay, _params);\n        }\n    case ToolingInfo.FEATURES.PROJECT_SYMBOLS:\n        {\n            _params = _params || {\n                query: params.query\n            };\n\n            return workspaceSymbol(relay, _params);\n        }\n    }\n}\n\n/** For custom messages */\nfunction onCustom(connection, type, handler) {\n    connection.onNotification(type, handler);\n}\n\nfunction sendCustomRequest(connection, type, params) {\n    return connection.sendRequest(type, params);\n}\n\nfunction sendCustomNotification(connection, type, params) {\n    connection.sendNotification(type, params);\n}\n\n/** For Notification messages */\nfunction didOpenTextDocument(connection, params) {\n    connection.sendNotification(protocol.DidOpenTextDocumentNotification.type, params);\n}\n\nfunction didChangeTextDocument(connection, params) {\n    connection.sendNotification(protocol.DidChangeTextDocumentNotification.type, params);\n}\n\nfunction didCloseTextDocument(connection, params) {\n    connection.sendNotification(protocol.DidCloseTextDocumentNotification.type, params);\n}\n\nfunction didSaveTextDocument(connection, params) {\n    connection.sendNotification(protocol.DidSaveTextDocumentNotification.type, params);\n}\n\nfunction didChangeWorkspaceFolders(connection, params) {\n    connection.sendNotification(protocol.DidChangeWorkspaceFoldersNotification.type, params);\n}\n\n/** For Request messages */\nfunction completion(connection, params) {\n    return connection.sendRequest(protocol.CompletionRequest.type, params);\n}\n\nfunction completionItemResolve(connection, params) {\n    return connection.sendRequest(protocol.CompletionResolveRequest.type, params);\n}\n\nfunction signatureHelp(connection, params) {\n    return connection.sendRequest(protocol.SignatureHelpRequest.type, params);\n}\n\nfunction gotoDefinition(connection, params) {\n    return connection.sendRequest(protocol.DefinitionRequest.type, params);\n}\n\nfunction gotoDeclaration(connection, params) {\n    return connection.sendRequest(protocol.DeclarationRequest.type, params);\n}\n\nfunction gotoImplementation(connection, params) {\n    return connection.sendRequest(protocol.ImplementationRequest.type, params);\n}\n\nfunction findReferences(connection, params) {\n    return connection.sendRequest(protocol.ReferencesRequest.type, params);\n}\n\nfunction documentSymbol(connection, params) {\n    return connection.sendRequest(protocol.DocumentSymbolRequest.type, params);\n}\n\nfunction workspaceSymbol(connection, params) {\n    return connection.sendRequest(protocol.WorkspaceSymbolRequest.type, params);\n}\n\n/**\n * Server commands\n */\nfunction initialize(connection, params) {\n    var rootPath = params.rootPath,\n        workspaceFolders = params.rootPaths;\n\n    if(!rootPath && workspaceFolders && Array.isArray(workspaceFolders)) {\n        rootPath = workspaceFolders[0];\n    }\n\n    if (!workspaceFolders) {\n        workspaceFolders = [rootPath];\n    }\n\n    if (workspaceFolders.length) {\n        workspaceFolders = Utils.convertToWorkspaceFolders(workspaceFolders);\n    }\n\n    var _params = {\n        rootPath: rootPath,\n        rootUri: Utils.pathToUri(rootPath),\n        processId: process.pid,\n        capabilities: params.capabilities,\n        workspaceFolders: workspaceFolders\n    };\n\n    return connection.sendRequest(protocol.InitializeRequest.type, _params);\n}\n\nfunction initialized(connection) {\n    connection.sendNotification(protocol.InitializedNotification.type);\n}\n\nfunction shutdown(connection) {\n    return connection.sendRequest(protocol.ShutdownRequest.type);\n}\n\nfunction exit(connection) {\n    connection.sendNotification(protocol.ExitNotification.type);\n}\n\nfunction processRequest(connection, message) {\n    return _constructParamsAndRelay(connection, message.type, message.params);\n}\n\nfunction processNotification(connection, message) {\n    _constructParamsAndRelay(connection, message.type, message.params);\n}\n\nfunction attachOnNotificationHandlers(connection, handler) {\n    function _callbackFactory(type) {\n        switch (type) {\n        case protocol.ShowMessageNotification.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_NOTIFICATIONS.SHOW_MESSAGE);\n        case protocol.LogMessageNotification.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_NOTIFICATIONS.LOG_MESSAGE);\n        case protocol.TelemetryEventNotification.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_NOTIFICATIONS.TELEMETRY);\n        case protocol.PublishDiagnosticsNotification.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_NOTIFICATIONS.DIAGNOSTICS);\n        }\n    }\n\n    connection.onNotification(protocol.ShowMessageNotification.type, _callbackFactory(protocol.ShowMessageNotification.type));\n    connection.onNotification(protocol.LogMessageNotification.type, _callbackFactory(protocol.LogMessageNotification.type));\n    connection.onNotification(protocol.TelemetryEventNotification.type, _callbackFactory(protocol.TelemetryEventNotification.type));\n    connection.onNotification(protocol.PublishDiagnosticsNotification.type, _callbackFactory(protocol.PublishDiagnosticsNotification.type));\n    connection.onNotification(function (type, params) {\n        var _params = {\n            type: type,\n            params: params\n        };\n        handler(_params);\n    });\n}\n\nfunction attachOnRequestHandlers(connection, handler) {\n    function _callbackFactory(type) {\n        switch (type) {\n        case protocol.ShowMessageRequest.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_REQUESTS.SHOW_SELECT_MESSAGE);\n        case protocol.RegistrationRequest.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_REQUESTS.REGISTRATION_REQUEST);\n        case protocol.UnregistrationRequest.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_REQUESTS.UNREGISTRATION_REQUEST);\n        case protocol.WorkspaceFoldersRequest.type:\n            return _constructParamsAndRelay.bind(null, handler, ToolingInfo.SERVICE_REQUESTS.PROJECT_FOLDERS_REQUEST);\n        }\n    }\n\n    connection.onRequest(protocol.ShowMessageRequest.type, _callbackFactory(protocol.ShowMessageRequest.type));\n    connection.onRequest(protocol.RegistrationRequest.type, _callbackFactory(protocol.RegistrationRequest.type));\n    // See https://github.com/Microsoft/vscode-languageserver-node/issues/199\n    connection.onRequest(\"client/registerFeature\", _callbackFactory(protocol.RegistrationRequest.type));\n    connection.onRequest(protocol.UnregistrationRequest.type, _callbackFactory(protocol.UnregistrationRequest.type));\n    // See https://github.com/Microsoft/vscode-languageserver-node/issues/199\n    connection.onRequest(\"client/unregisterFeature\", _callbackFactory(protocol.UnregistrationRequest.type));\n    connection.onRequest(protocol.WorkspaceFoldersRequest.type, _callbackFactory(protocol.WorkspaceFoldersRequest.type));\n    connection.onRequest(function (type, params) {\n        var _params = {\n            type: type,\n            params: params\n        };\n        return handler(_params);\n    });\n}\n\nexports.initialize = initialize;\nexports.initialized = initialized;\nexports.shutdown = shutdown;\nexports.exit = exit;\nexports.onCustom = onCustom;\nexports.sendCustomRequest = sendCustomRequest;\nexports.sendCustomNotification = sendCustomNotification;\nexports.processRequest = processRequest;\nexports.processNotification = processNotification;\nexports.attachOnNotificationHandlers = attachOnNotificationHandlers;\nexports.attachOnRequestHandlers = attachOnRequestHandlers;\n"
  },
  {
    "path": "src/languageTools/LanguageClient/ServerUtils.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global exports, process, Promise, __dirname, global*/\n/*eslint no-console: 0*/\n/*eslint no-fallthrough: 0*/\n/* eslint no-empty: [\"error\", { \"allowEmptyCatch\": true }] */\n(function () {\n    \"use strict\";\n\n    var protocol = require(\"vscode-languageserver-protocol\"),\n        cp = require(\"child_process\"),\n        fs = require(\"fs\");\n\n    var CommunicationTypes = {\n            NodeIPC: {\n                type: \"ipc\",\n                flag: \"--node-ipc\"\n            },\n            StandardIO: {\n                type: \"stdio\",\n                flag: \"--stdio\"\n            },\n            Pipe: {\n                type: \"pipe\",\n                flag: \"--pipe\"\n            },\n            Socket: {\n                type: \"socket\",\n                flag: \"--socket\"\n            }\n        },\n        CLIENT_PROCESS_ID_FLAG = \"--clientProcessId\";\n\n    function addCommunicationArgs(communication, processArgs, isRuntime) {\n        switch (communication) {\n            case CommunicationTypes.NodeIPC.type:\n                {\n                    if (isRuntime) {\n                        processArgs.options.stdio = [null, null, null, 'ipc'];\n                        processArgs.args.push(CommunicationTypes.NodeIPC.flag);\n                    } else {\n                        processArgs.args.push(CommunicationTypes.NodeIPC.flag);\n                    }\n                    break;\n                }\n            case CommunicationTypes.StandardIO.type:\n                {\n                    processArgs.args.push(CommunicationTypes.StandardIO.flag);\n                    break;\n                }\n            case CommunicationTypes.Pipe.type:\n                {\n                    var pipeName = protocol.generateRandomPipeName(),\n                        pipeflag = CommunicationTypes.Pipe.flag + \"=\" + pipeName.toString();\n\n                    processArgs.args.push(pipeflag);\n                    processArgs.pipeName = pipeName;\n                    break;\n                }\n            default:\n                {\n                    if (communication && communication.type === CommunicationTypes.Socket.type) {\n                        var socketFlag = CommunicationTypes.Socket.flag + \"=\" + communication.port.toString();\n                        processArgs.args.push(socketFlag);\n                    }\n                }\n        }\n\n        var clientProcessIdFlag = CLIENT_PROCESS_ID_FLAG + \"=\" + process.pid.toString();\n        processArgs.args.push(clientProcessIdFlag);\n    }\n\n    function _getEnvironment(env) {\n        if (!env) {\n            return process.env;\n        }\n\n        //Combine env vars\n        var result = Object.assign({}, process.env, env);\n        return result;\n    }\n\n    function _createReaderAndWriteByCommunicationType(resp, type) {\n        var retval = null;\n\n        switch (type) {\n            case CommunicationTypes.NodeIPC.type:\n                {\n                    if (resp.process) {\n                        resp.process.stderr.on('data', function (data) {\n                            if (global.LanguageClientInfo.preferences.showServerLogsInConsole) {\n                                console.error('[Server logs @ stderr] \"%s\"', String(data));\n                            }\n                        });\n\n                        resp.process.stdout.on('data', function (data) {\n                            if (global.LanguageClientInfo.preferences.showServerLogsInConsole) {\n                                console.info('[Server logs @ stdout] \"%s\"', String(data));\n                            }\n                        });\n\n                        retval = {\n                            reader: new protocol.IPCMessageReader(resp.process),\n                            writer: new protocol.IPCMessageWriter(resp.process)\n                        };\n                    }\n                    break;\n                }\n            case CommunicationTypes.StandardIO.type:\n                {\n                    if (resp.process) {\n                        resp.process.stderr.on('data', function (data) {\n                            if (global.LanguageClientInfo.preferences.showServerLogsInConsole) {\n                                console.error('[Server logs @ stderr] \"%s\"', String(data));\n                            }\n                        });\n\n                        retval = {\n                            reader: new protocol.StreamMessageReader(resp.process.stdout),\n                            writer: new protocol.StreamMessageWriter(resp.process.stdin)\n                        };\n                    }\n                    break;\n                }\n            case CommunicationTypes.Pipe.type:\n            case CommunicationTypes.Socket.type:\n                {\n                    if (resp.reader && resp.writer && resp.process) {\n                        resp.process.stderr.on('data', function (data) {\n                            if (global.LanguageClientInfo.preferences.showServerLogsInConsole) {\n                                console.error('[Server logs @ stderr] \"%s\"', String(data));\n                            }\n                        });\n\n                        resp.process.stdout.on('data', function (data) {\n                            if (global.LanguageClientInfo.preferences.showServerLogsInConsole) {\n                                console.info('[Server logs @ stdout] \"%s\"', String(data));\n                            }\n                        });\n\n                        retval = {\n                            reader: resp.reader,\n                            writer: resp.writer\n                        };\n                    }\n                }\n        }\n\n        return retval;\n    }\n\n    function _createReaderAndWriter(resp) {\n        var retval = null;\n\n        if (!resp) {\n            return retval;\n        }\n\n        if (resp.reader && resp.writer) {\n            retval = {\n                reader: resp.reader,\n                writer: resp.writer\n            };\n        } else if (resp.process) {\n            retval = {\n                reader: new protocol.StreamMessageReader(resp.process.stdout),\n                writer: new protocol.StreamMessageWriter(resp.process.stdin)\n            };\n\n            resp.process.stderr.on('data', function (data) {\n                if (global.LanguageClientInfo.preferences.showServerLogsInConsole) {\n                    console.error('[Server logs @ stderr] \"%s\"', String(data));\n                }\n            });\n        }\n\n        return retval;\n    }\n\n    function _isServerProcessValid(serverProcess) {\n        if (!serverProcess || !serverProcess.pid) {\n            return false;\n        }\n\n        return true;\n    }\n\n    function _startServerAndGetTransports(communication, processArgs, isRuntime) {\n        return new Promise(function (resolve, reject) {\n            var serverProcess = null,\n                result = null,\n                protocolTransport = null,\n                type = typeof communication === \"object\" ? communication.type : communication;\n\n            var processFunc = isRuntime ? cp.spawn : cp.fork;\n\n            switch (type) {\n                case CommunicationTypes.NodeIPC.type:\n                case CommunicationTypes.StandardIO.type:\n                    {\n                        serverProcess = processFunc(processArgs.primaryArg, processArgs.args, processArgs.options);\n                        if (_isServerProcessValid(serverProcess)) {\n                            result = _createReaderAndWriteByCommunicationType({\n                                process: serverProcess\n                            }, type);\n\n                            resolve(result);\n                        } else {\n                            reject(null);\n                        }\n                        break;\n                    }\n                case CommunicationTypes.Pipe.type:\n                    {\n                        protocolTransport = protocol.createClientPipeTransport(processArgs.pipeName);\n                    }\n                case CommunicationTypes.Socket.type:\n                    {\n                        if (communication && communication.type === CommunicationTypes.Socket.type) {\n                            protocolTransport = protocol.createClientSocketTransport(communication.port);\n                        }\n                        \n                        if (!protocolTransport) {\n                            reject(\"Invalid Communications Object. Can't create connection with server\");\n                            return;\n                        }\n\n                        protocolTransport.then(function (transportObj) {\n                            serverProcess = processFunc(processArgs.primaryArg, processArgs.args, processArgs.options);\n                            if (_isServerProcessValid(serverProcess)) {\n                                transportObj.onConnected().then(function (protocolObj) {\n                                    result = _createReaderAndWriteByCommunicationType({\n                                        process: serverProcess,\n                                        reader: protocolObj[0],\n                                        writer: protocolObj[1]\n                                    }, type);\n\n                                    resolve(result);\n                                }).catch(reject);\n                            }\n                        }).catch(reject);\n                    }\n            }\n        });\n    }\n\n    function _handleOtherRuntime(serverOptions) {\n        function _getArguments(sOptions) {\n            var args = [];\n\n            if (sOptions.options && sOptions.options.execArgv) {\n                args = args.concat(sOptions.options.execArgv);\n            }\n\n            args.push(sOptions.module);\n            if (sOptions.args) {\n                args = args.concat(sOptions.args);\n            }\n\n            return args;\n        }\n\n        function _getOptions(sOptions) {\n            var cwd = undefined,\n                env = undefined;\n\n            if (sOptions.options) {\n                if (sOptions.options.cwd) {\n                    try {\n                        if (fs.lstatSync(sOptions.options.cwd).isDirectory(sOptions.options.cwd)) {\n                            cwd = sOptions.options.cwd;\n                        }\n                    } catch (e) {}\n                }\n\n                cwd = cwd || __dirname;\n                if (sOptions.options.env) {\n                    env = sOptions.options.env;\n                }\n            }\n\n            var options = {\n                cwd: cwd,\n                env: _getEnvironment(env)\n            };\n\n            return options;\n        }\n\n        var communication = serverOptions.communication || CommunicationTypes.StandardIO.type,\n            args = _getArguments(serverOptions),\n            options = _getOptions(serverOptions),\n            processArgs = {\n                args: args,\n                options: options,\n                primaryArg: serverOptions.runtime\n            };\n\n        addCommunicationArgs(communication, processArgs, true);\n        return _startServerAndGetTransports(communication, processArgs, true);\n    }\n\n    function _handleNodeRuntime(serverOptions) {\n        function _getArguments(sOptions) {\n            var args = [];\n\n            if (sOptions.args) {\n                args = args.concat(sOptions.args);\n            }\n\n            return args;\n        }\n\n        function _getOptions(sOptions) {\n            var cwd = undefined;\n\n            if (sOptions.options) {\n                if (sOptions.options.cwd) {\n                    try {\n                        if (fs.lstatSync(sOptions.options.cwd).isDirectory(sOptions.options.cwd)) {\n                            cwd = sOptions.options.cwd;\n                        }\n                    } catch (e) {}\n                }\n                cwd = cwd || __dirname;\n            }\n\n            var options = Object.assign({}, sOptions.options);\n            options.cwd = cwd,\n                options.execArgv = options.execArgv || [];\n            options.silent = true;\n\n            return options;\n        }\n\n        var communication = serverOptions.communication || CommunicationTypes.StandardIO.type,\n            args = _getArguments(serverOptions),\n            options = _getOptions(serverOptions),\n            processArgs = {\n                args: args,\n                options: options,\n                primaryArg: serverOptions.module\n            };\n\n        addCommunicationArgs(communication, processArgs, false);\n        return _startServerAndGetTransports(communication, processArgs, false);\n    }\n\n\n    function _handleServerFunction(func) {\n        return func().then(function (resp) {\n            var result = _createReaderAndWriter(resp);\n\n            return result;\n        });\n    }\n\n    function _handleModules(serverOptions) {\n        if (serverOptions.runtime) {\n            return _handleOtherRuntime(serverOptions);\n        }\n        return _handleNodeRuntime(serverOptions);\n\n    }\n\n    function _handleExecutable(serverOptions) {\n        return new Promise(function (resolve, reject) {\n            var command = serverOptions.command,\n                args = serverOptions.args,\n                options = Object.assign({}, serverOptions.options);\n\n            var serverProcess = cp.spawn(command, args, options);\n            if (!serverProcess || !serverProcess.pid) {\n                reject(\"Failed to launch server using command :\", command);\n            }\n\n            var result = _createReaderAndWriter({\n                process: serverProcess,\n                detached: !!options.detached\n            });\n\n            if (result) {\n                resolve(result);\n            } else {\n                reject(result);\n            }\n        });\n    }\n\n    function startServerAndGetConnectionArgs(serverOptions) {\n        if (typeof serverOptions === \"function\") {\n            return _handleServerFunction(serverOptions);\n        } else if (typeof serverOptions === \"object\") {\n            if (serverOptions.module) {\n                return _handleModules(serverOptions);\n            } else if (serverOptions.command) {\n                return _handleExecutable(serverOptions);\n            }\n        }\n\n        return Promise.reject(null);\n    }\n\n\n    exports.startServerAndGetConnectionArgs = startServerAndGetConnectionArgs;\n}());\n"
  },
  {
    "path": "src/languageTools/LanguageClient/Utils.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env es6, node*/\n\"use strict\";\n\nvar nodeURL = require(\"url\"),\n    path = require(\"path\");\n\nfunction pathToUri(filePath) {\n    var newPath = convertWinToPosixPath(filePath);\n    if (newPath[0] !== '/') {\n        newPath = `/${newPath}`;\n    }\n    return encodeURI(`file://${newPath}`).replace(/[?#]/g, encodeURIComponent);\n}\n\nfunction uriToPath(uri) {\n    var url = nodeURL.URL.parse(uri);\n    if (url.protocol !== 'file:' || url.path === undefined) {\n        return uri;\n    }\n\n    let filePath = decodeURIComponent(url.path);\n    if (process.platform === 'win32') {\n        if (filePath[0] === '/') {\n            filePath = filePath.substr(1);\n        }\n        return filePath;\n    }\n    return filePath;\n}\n\nfunction convertPosixToWinPath(filePath) {\n    return filePath.replace(/\\//g, '\\\\');\n}\n\nfunction convertWinToPosixPath(filePath) {\n    return filePath.replace(/\\\\/g, '/');\n}\n\nfunction convertToLSPPosition(pos) {\n    return {\n        line: pos.line,\n        character: pos.ch\n    };\n}\n\nfunction convertToWorkspaceFolders(paths) {\n    var workspaceFolders = paths.map(function (folderPath) {\n        var uri = pathToUri(folderPath),\n            name = path.basename(folderPath);\n\n        return {\n            uri: uri,\n            name: name\n        };\n    });\n\n    return workspaceFolders;\n}\n\nexports.uriToPath = uriToPath;\nexports.pathToUri = pathToUri;\nexports.convertPosixToWinPath = convertPosixToWinPath;\nexports.convertWinToPosixPath = convertWinToPosixPath;\nexports.convertToLSPPosition = convertToLSPPosition;\nexports.convertToWorkspaceFolders = convertToWorkspaceFolders;\n"
  },
  {
    "path": "src/languageTools/LanguageClient/package.json",
    "content": "{\n  \"name\": \"brackets-language-client\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Brackets language client interface for Language Server Protocol\",\n  \"main\": \"LanguageClient.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [\n    \"LSP\",\n    \"LanguageClient\",\n    \"Brackets\"\n  ],\n  \"author\": \"Adobe\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"vscode-languageserver-protocol\": \"^3.14.1\"\n  }\n}\n"
  },
  {
    "path": "src/languageTools/LanguageClientWrapper.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint no-console: 0*/\n/*eslint indent: 0*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var ToolingInfo = JSON.parse(require(\"text!languageTools/ToolingInfo.json\")),\n        MESSAGE_FORMAT = {\n            BRACKETS: \"brackets\",\n            LSP: \"lsp\"\n        };\n\n    function _addTypeInformation(type, params) {\n        return {\n            type: type,\n            params: params\n        };\n    }\n\n    function hasValidProp(obj, prop) {\n        return (obj && obj[prop] !== undefined && obj[prop] !== null);\n    }\n\n    function hasValidProps(obj, props) {\n        var retval = !!obj,\n            len = props.length,\n            i;\n\n        for (i = 0; retval && (i < len); i++) {\n            retval = (retval && obj[props[i]] !== undefined && obj[props[i]] !== null);\n        }\n\n        return retval;\n    }\n    /*\n        RequestParams creator - sendNotifications/request\n    */\n    function validateRequestParams(type, params) {\n        var validatedParams = null;\n\n        params = params || {};\n\n        //Don't validate if the formatting is done by the caller\n        if (params.format === MESSAGE_FORMAT.LSP) {\n            return params;\n        }\n\n        switch (type) {\n            case ToolingInfo.LANGUAGE_SERVICE.START:\n                {\n                    if (hasValidProp(params, \"rootPaths\") || hasValidProp(params, \"rootPath\")) {\n                        validatedParams = params;\n                        validatedParams.capabilities = validatedParams.capabilities || false;\n                    }\n                    break;\n                }\n            case ToolingInfo.FEATURES.CODE_HINTS:\n            case ToolingInfo.FEATURES.PARAMETER_HINTS:\n            case ToolingInfo.FEATURES.JUMP_TO_DECLARATION:\n            case ToolingInfo.FEATURES.JUMP_TO_DEFINITION:\n            case ToolingInfo.FEATURES.JUMP_TO_IMPL:\n                {\n                    if (hasValidProps(params, [\"filePath\", \"cursorPos\"])) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.FEATURES.CODE_HINT_INFO:\n                {\n                    validatedParams = params;\n                    break;\n                }\n            case ToolingInfo.FEATURES.FIND_REFERENCES:\n                {\n                    if (hasValidProps(params, [\"filePath\", \"cursorPos\"])) {\n                        validatedParams = params;\n                        validatedParams.includeDeclaration = validatedParams.includeDeclaration || false;\n                    }\n                    break;\n                }\n            case ToolingInfo.FEATURES.DOCUMENT_SYMBOLS:\n                {\n                    if (hasValidProp(params, \"filePath\")) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.FEATURES.PROJECT_SYMBOLS:\n                {\n                    if (hasValidProp(params, \"query\") && typeof params.query === \"string\") {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.LANGUAGE_SERVICE.CUSTOM_REQUEST:\n                {\n                    validatedParams = params;\n                }\n        }\n\n        return validatedParams;\n    }\n\n    /*\n        ReponseParams transformer - used by OnNotifications\n    */\n    function validateNotificationParams(type, params) {\n        var validatedParams = null;\n\n        params = params || {};\n\n        //Don't validate if the formatting is done by the caller\n        if (params.format === MESSAGE_FORMAT.LSP) {\n            return params;\n        }\n\n        switch (type) {\n            case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_OPENED:\n                {\n                    if (hasValidProps(params, [\"filePath\", \"fileContent\", \"languageId\"])) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_CHANGED:\n                {\n                    if (hasValidProps(params, [\"filePath\", \"fileContent\"])) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_SAVED:\n                {\n                    if (hasValidProp(params, \"filePath\")) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_CLOSED:\n                {\n                    if (hasValidProp(params, \"filePath\")) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.SYNCHRONIZE_EVENTS.PROJECT_FOLDERS_CHANGED:\n                {\n                    if (hasValidProps(params, [\"foldersAdded\", \"foldersRemoved\"])) {\n                        validatedParams = params;\n                    }\n                    break;\n                }\n            case ToolingInfo.LANGUAGE_SERVICE.CUSTOM_NOTIFICATION:\n                {\n                    validatedParams = params;\n                }\n        }\n\n        return validatedParams;\n    }\n\n    function validateHandler(handler) {\n        var retval = false;\n\n        if (handler && typeof handler === \"function\") {\n            retval = true;\n        } else {\n            console.warn(\"Handler validation failed. Handler should be of type 'function'. Provided handler is of type :\", typeof handler);\n        }\n\n        return retval;\n    }\n\n    function LanguageClientWrapper(name, path, domainInterface, languages) {\n        this._name = name;\n        this._path = path;\n        this._domainInterface = domainInterface;\n        this._languages = languages || [];\n        this._startClient = null;\n        this._stopClient = null;\n        this._notifyClient = null;\n        this._requestClient = null;\n        this._onRequestHandler = {};\n        this._onNotificationHandlers = {};\n        this._dynamicCapabilities = {};\n        this._serverCapabilities = {};\n\n        //Initialize with keys for brackets events we want to tap into.\n        this._onEventHandlers = {\n            \"activeEditorChange\": [],\n            \"projectOpen\": [],\n            \"beforeProjectClose\": [],\n            \"dirtyFlagChange\": [],\n            \"documentChange\": [],\n            \"fileNameChange\": [],\n            \"beforeAppClose\": []\n        };\n\n        this._init();\n    }\n\n    LanguageClientWrapper.prototype._init = function () {\n        this._domainInterface.registerMethods([\n            {\n                methodName: ToolingInfo.LANGUAGE_SERVICE.REQUEST,\n                methodHandle: this._onRequestDelegator.bind(this)\n            },\n            {\n                methodName: ToolingInfo.LANGUAGE_SERVICE.NOTIFY,\n                methodHandle: this._onNotificationDelegator.bind(this)\n            }\n        ]);\n\n        //create function interfaces\n        this._startClient = this._domainInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.START, true);\n        this._stopClient = this._domainInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.STOP, true);\n        this._notifyClient = this._domainInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.NOTIFY);\n        this._requestClient = this._domainInterface.createInterface(ToolingInfo.LANGUAGE_SERVICE.REQUEST, true);\n    };\n\n    LanguageClientWrapper.prototype._onRequestDelegator = function (params) {\n        if (!params || !params.type) {\n            console.log(\"Invalid server request\");\n            return $.Deferred().reject();\n        }\n\n        var requestHandler = this._onRequestHandler[params.type];\n        if (params.type === ToolingInfo.SERVICE_REQUESTS.REGISTRATION_REQUEST) {\n            return this._registrationShim(params.params, requestHandler);\n        }\n\n        if (params.type === ToolingInfo.SERVICE_REQUESTS.UNREGISTRATION_REQUEST) {\n            return this._unregistrationShim(params.params, requestHandler);\n        }\n\n        if (validateHandler(requestHandler)) {\n            return requestHandler.call(null, params.params);\n        }\n        console.log(\"No handler provided for server request type : \", params.type);\n        return $.Deferred().reject();\n\n    };\n\n    LanguageClientWrapper.prototype._onNotificationDelegator = function (params) {\n        if (!params || !params.type) {\n            console.log(\"Invalid server notification\");\n            return;\n        }\n\n        var notificationHandlers = this._onNotificationHandlers[params.type];\n        if (notificationHandlers && Array.isArray(notificationHandlers) && notificationHandlers.length) {\n            notificationHandlers.forEach(function (handler) {\n                if (validateHandler(handler)) {\n                    handler.call(null, params.params);\n                }\n            });\n        } else {\n            console.log(\"No handlers provided for server notification type : \", params.type);\n        }\n    };\n\n    LanguageClientWrapper.prototype._request = function (type, params) {\n        params = validateRequestParams(type, params);\n        if (params) {\n            params = _addTypeInformation(type, params);\n            return this._requestClient(params);\n        }\n\n        console.log(\"Invalid Parameters provided for request type : \", type);\n        return $.Deferred().reject();\n    };\n\n    LanguageClientWrapper.prototype._notify = function (type, params) {\n        params = validateNotificationParams(type, params);\n        if (params) {\n            params = _addTypeInformation(type, params);\n            this._notifyClient(params);\n        } else {\n            console.log(\"Invalid Parameters provided for notification type : \", type);\n        }\n    };\n\n    LanguageClientWrapper.prototype._addOnRequestHandler = function (type, handler) {\n        if (validateHandler(handler)) {\n            this._onRequestHandler[type] = handler;\n        }\n    };\n\n    LanguageClientWrapper.prototype._addOnNotificationHandler = function (type, handler) {\n        if (validateHandler(handler)) {\n            if (!this._onNotificationHandlers[type]) {\n                this._onNotificationHandlers[type] = [];\n            }\n\n            this._onNotificationHandlers[type].push(handler);\n        }\n    };\n\n    /**\n        Requests\n    */\n    //start\n    LanguageClientWrapper.prototype.start = function (params) {\n        params = validateRequestParams(ToolingInfo.LANGUAGE_SERVICE.START, params);\n        if (params) {\n            var self = this;\n            return this._startClient(params)\n                    .then(function (result) {\n                        self.setServerCapabilities(result.capabilities);\n                        return $.Deferred().resolve(result);\n                    }, function (err) {\n                        return $.Deferred().reject(err);\n                    });\n        }\n\n        console.log(\"Invalid Parameters provided for request type : start\");\n        return $.Deferred().reject();\n    };\n\n    //shutdown\n    LanguageClientWrapper.prototype.stop = function () {\n        return this._stopClient();\n    };\n\n    //restart\n    LanguageClientWrapper.prototype.restart = function (params) {\n        var self = this;\n        return this.stop().then(function () {\n            return self.start(params);\n        });\n    };\n\n    /**\n        textDocument requests\n    */\n    //completion\n    LanguageClientWrapper.prototype.requestHints = function (params) {\n        return this._request(ToolingInfo.FEATURES.CODE_HINTS, params)\n            .then(function(response) {\n                if(response && response.items && response.items.length) {\n                    logAnalyticsData(\"CODE_HINTS\");\n                }\n                return $.Deferred().resolve(response);\n            }, function(err) {\n                return $.Deferred().reject(err);\n            });\n    };\n\n    //completionItemResolve\n    LanguageClientWrapper.prototype.getAdditionalInfoForHint = function (params) {\n        return this._request(ToolingInfo.FEATURES.CODE_HINT_INFO, params);\n    };\n\n    //signatureHelp\n    LanguageClientWrapper.prototype.requestParameterHints = function (params) {\n        return this._request(ToolingInfo.FEATURES.PARAMETER_HINTS, params)\n            .then(function(response) {\n                if (response && response.signatures && response.signatures.length) {\n                    logAnalyticsData(\"PARAM_HINTS\");\n                }\n                return $.Deferred().resolve(response);\n            }, function(err) {\n                return $.Deferred().reject(err);\n            });\n    };\n\n    //gotoDefinition\n    LanguageClientWrapper.prototype.gotoDefinition = function (params) {\n        return this._request(ToolingInfo.FEATURES.JUMP_TO_DEFINITION, params)\n            .then(function(response) {\n                if(response && response.range) {\n                    logAnalyticsData(\"JUMP_TO_DEF\");\n                }\n                return $.Deferred().resolve(response);\n            }, function(err) {\n                return $.Deferred().reject(err);\n            });\n    };\n\n    //gotoDeclaration\n    LanguageClientWrapper.prototype.gotoDeclaration = function (params) {\n        return this._request(ToolingInfo.FEATURES.JUMP_TO_DECLARATION, params);\n    };\n\n    //gotoImplementation\n    LanguageClientWrapper.prototype.gotoImplementation = function (params) {\n        return this._request(ToolingInfo.FEATURES.JUMP_TO_IMPL, params);\n    };\n\n    //findReferences\n    LanguageClientWrapper.prototype.findReferences = function (params) {\n        return this._request(ToolingInfo.FEATURES.FIND_REFERENCES, params);\n    };\n\n    //documentSymbol\n    LanguageClientWrapper.prototype.requestSymbolsForDocument = function (params) {\n        return this._request(ToolingInfo.FEATURES.DOCUMENT_SYMBOLS, params);\n    };\n\n    /**\n        workspace requests\n    */\n    //workspaceSymbol\n    LanguageClientWrapper.prototype.requestSymbolsForWorkspace = function (params) {\n        return this._request(ToolingInfo.FEATURES.PROJECT_SYMBOLS, params);\n    };\n\n    //These will mostly be callbacks/[done-fail](promises)\n    /**\n        Window OnNotifications\n    */\n    //showMessage\n    LanguageClientWrapper.prototype.addOnShowMessage = function (handler) {\n        this._addOnNotificationHandler(ToolingInfo.SERVICE_NOTIFICATIONS.SHOW_MESSAGE, handler);\n    };\n\n    //logMessage\n    LanguageClientWrapper.prototype.addOnLogMessage = function (handler) {\n        this._addOnNotificationHandler(ToolingInfo.SERVICE_NOTIFICATIONS.LOG_MESSAGE, handler);\n    };\n\n    /**\n        healthData/logging OnNotifications\n    */\n    //telemetry\n    LanguageClientWrapper.prototype.addOnTelemetryEvent = function (handler) {\n        this._addOnNotificationHandler(ToolingInfo.SERVICE_NOTIFICATIONS.TELEMETRY, handler);\n    };\n\n    /**\n        textDocument OnNotifications\n    */\n    //onPublishDiagnostics\n    LanguageClientWrapper.prototype.addOnCodeInspection = function (handler) {\n        this._addOnNotificationHandler(ToolingInfo.SERVICE_NOTIFICATIONS.DIAGNOSTICS, handler);\n    };\n\n    /**\n        Window OnRequest\n    */\n\n    //showMessageRequest - handler must return promise\n    LanguageClientWrapper.prototype.onShowMessageWithRequest = function (handler) {\n        this._addOnRequestHandler(ToolingInfo.SERVICE_REQUESTS.SHOW_SELECT_MESSAGE, handler);\n    };\n\n    LanguageClientWrapper.prototype.onProjectFoldersRequest = function (handler) {\n        this._addOnRequestHandler(ToolingInfo.SERVICE_REQUESTS.PROJECT_FOLDERS_REQUEST, handler);\n    };\n\n    LanguageClientWrapper.prototype._registrationShim = function (params, handler) {\n        var self = this;\n\n        var registrations = params.registrations;\n        registrations.forEach(function (registration) {\n            var id = registration.id;\n            self._dynamicCapabilities[id] = registration;\n        });\n        return validateHandler(handler) ? handler(params) : $.Deferred().resolve();\n    };\n\n    LanguageClientWrapper.prototype.onDynamicCapabilityRegistration = function (handler) {\n        this._addOnRequestHandler(ToolingInfo.SERVICE_REQUESTS.REGISTRATION_REQUEST, handler);\n    };\n\n    LanguageClientWrapper.prototype._unregistrationShim = function (params, handler) {\n        var self = this;\n\n        var unregistrations = params.unregistrations;\n        unregistrations.forEach(function (unregistration) {\n            var id = unregistration.id;\n            delete self._dynamicCapabilities[id];\n        });\n        return validateHandler(handler) ? handler(params) : $.Deferred().resolve();\n    };\n\n    LanguageClientWrapper.prototype.onDynamicCapabilityUnregistration = function (handler) {\n        this._addOnRequestHandler(ToolingInfo.SERVICE_REQUESTS.UNREGISTRATION_REQUEST, handler);\n    };\n\n    /*\n        Unimplemented OnNotifications\n            workspace\n                applyEdit (codeAction, codeLens)\n    */\n\n    /**\n        SendNotifications\n    */\n\n    /**\n        workspace SendNotifications\n    */\n    //didChangeProjectRoots\n    LanguageClientWrapper.prototype.notifyProjectRootsChanged = function (params) {\n        this._notify(ToolingInfo.SYNCHRONIZE_EVENTS.PROJECT_FOLDERS_CHANGED, params);\n    };\n\n    /**\n        textDocument SendNotifications\n    */\n    //didOpenTextDocument\n    LanguageClientWrapper.prototype.notifyTextDocumentOpened = function (params) {\n        this._notify(ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_OPENED, params);\n    };\n\n    //didCloseTextDocument\n    LanguageClientWrapper.prototype.notifyTextDocumentClosed = function (params) {\n        this._notify(ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_CLOSED, params);\n    };\n\n    //didChangeTextDocument\n    LanguageClientWrapper.prototype.notifyTextDocumentChanged = function (params) {\n        this._notify(ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_CHANGED, params);\n    };\n\n    //didSaveTextDocument\n    LanguageClientWrapper.prototype.notifyTextDocumentSave = function (params) {\n        this._notify(ToolingInfo.SYNCHRONIZE_EVENTS.DOCUMENT_SAVED, params);\n    };\n\n    /**\n        Custom messages\n     */\n\n    //customNotification\n    LanguageClientWrapper.prototype.sendCustomNotification = function (params) {\n        this._notify(ToolingInfo.LANGUAGE_SERVICE.CUSTOM_NOTIFICATION, params);\n    };\n\n    LanguageClientWrapper.prototype.onCustomNotification = function (type, handler) {\n        this._addOnNotificationHandler(type, handler);\n    };\n\n    //customRequest\n    LanguageClientWrapper.prototype.sendCustomRequest = function (params) {\n        return this._request(ToolingInfo.LANGUAGE_SERVICE.CUSTOM_REQUEST, params);\n    };\n\n    LanguageClientWrapper.prototype.onCustomRequest = function (type, handler) {\n        this._addOnRequestHandler(type, handler);\n    };\n\n    //Handling Brackets Events\n    LanguageClientWrapper.prototype.addOnEditorChangeHandler = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"activeEditorChange\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addOnProjectOpenHandler = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"projectOpen\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addBeforeProjectCloseHandler = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"beforeProjectClose\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addOnDocumentDirtyFlagChangeHandler = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"dirtyFlagChange\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addOnDocumentChangeHandler = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"documentChange\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addOnFileRenameHandler = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"fileNameChange\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addBeforeAppClose = function (handler) {\n        if (validateHandler(handler)) {\n            this._onEventHandlers[\"beforeAppClose\"].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.addOnCustomEventHandler = function (eventName, handler) {\n        if (validateHandler(handler)) {\n            if (!this._onEventHandlers[eventName]) {\n                this._onEventHandlers[eventName] = [];\n            }\n            this._onEventHandlers[eventName].push(handler);\n        }\n    };\n\n    LanguageClientWrapper.prototype.triggerEvent = function (event) {\n        var eventName = event.type,\n            eventArgs = arguments;\n\n        if (this._onEventHandlers[eventName] && Array.isArray(this._onEventHandlers[eventName])) {\n            var handlers = this._onEventHandlers[eventName];\n\n            handlers.forEach(function (handler) {\n                if (validateHandler(handler)) {\n                    handler.apply(null, eventArgs);\n                }\n            });\n        }\n    };\n\n    LanguageClientWrapper.prototype.getDynamicCapabilities = function () {\n        return this._dynamicCapabilities;\n    };\n\n    LanguageClientWrapper.prototype.getServerCapabilities = function () {\n        return this._serverCapabilities;\n    };\n\n    LanguageClientWrapper.prototype.setServerCapabilities = function (serverCapabilities) {\n        this._serverCapabilities = serverCapabilities;\n    };\n\n    exports.LanguageClientWrapper = LanguageClientWrapper;\n\n    function logAnalyticsData(typeStrKey) {\n        var editor =  require(\"editor/EditorManager\").getActiveEditor(),\n            document = editor ? editor.document : null,\n            language = document ? document.language : null,\n            languageName = language ? language._name : \"\",\n            HealthLogger = require(\"utils/HealthLogger\"),\n            typeStr = HealthLogger.commonStrings[typeStrKey] || \"\";\n\n         HealthLogger.sendAnalyticsData(\n            HealthLogger.commonStrings.USAGE + HealthLogger.commonStrings.LANGUAGE_SERVER_PROTOCOL + typeStr + languageName,\n            HealthLogger.commonStrings.USAGE,\n            HealthLogger.commonStrings.LANGUAGE_SERVER_PROTOCOL,\n            typeStr,\n            languageName.toLowerCase()\n          );\n    }\n\n    //For unit testting\n    exports.validateRequestParams = validateRequestParams;\n    exports.validateNotificationParams = validateNotificationParams;\n});\n"
  },
  {
    "path": "src/languageTools/LanguageTools.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint no-console: 0*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\n/*eslint-env es6*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var ClientLoader = require(\"languageTools/ClientLoader\"),\n        EditorManager = require(\"editor/EditorManager\"),\n        ProjectManager = require(\"project/ProjectManager\"),\n        DocumentManager = require(\"document/DocumentManager\"),\n        DocumentModule = require(\"document/Document\"),\n        PreferencesManager = require(\"preferences/PreferencesManager\"),\n        Strings = require(\"strings\"),\n        LanguageClientWrapper = require(\"languageTools/LanguageClientWrapper\").LanguageClientWrapper;\n\n    var languageClients = new Map(),\n        languageToolsPrefs = {\n            showServerLogsInConsole: false\n        },\n        BRACKETS_EVENTS_NAMES = {\n            EDITOR_CHANGE_EVENT: \"activeEditorChange\",\n            PROJECT_OPEN_EVENT: \"projectOpen\",\n            PROJECT_CLOSE_EVENT: \"beforeProjectClose\",\n            DOCUMENT_DIRTY_EVENT: \"dirtyFlagChange\",\n            DOCUMENT_CHANGE_EVENT: \"documentChange\",\n            FILE_RENAME_EVENT: \"fileNameChange\",\n            BEFORE_APP_CLOSE: \"beforeAppClose\"\n        };\n\n    PreferencesManager.definePreference(\"languageTools\", \"object\", languageToolsPrefs, {\n        description: Strings.LANGUAGE_TOOLS_PREFERENCES\n    });\n\n    PreferencesManager.on(\"change\", \"languageTools\", function () {\n        languageToolsPrefs = PreferencesManager.get(\"languageTools\");\n\n        ClientLoader.syncPrefsWithDomain(languageToolsPrefs);\n    });\n\n    function registerLanguageClient(clientName, languageClient) {\n        languageClients.set(clientName, languageClient);\n    }\n\n    function _withNamespace(event) {\n        return event.split(\" \")\n            .filter((value) => !!value)\n            .map((value) => value + \".language-tools\")\n            .join(\" \");\n    }\n\n    function _eventHandler() {\n        var eventArgs = arguments;\n        //Broadcast event to all clients\n        languageClients.forEach(function (client) {\n            client.triggerEvent.apply(client, eventArgs);\n        });\n    }\n\n    function _attachEventHandlers() {\n        //Attach standard listeners\n        EditorManager.on(_withNamespace(BRACKETS_EVENTS_NAMES.EDITOR_CHANGE_EVENT), _eventHandler); //(event, current, previous)\n        ProjectManager.on(_withNamespace(BRACKETS_EVENTS_NAMES.PROJECT_OPEN_EVENT), _eventHandler); //(event, directory)\n        ProjectManager.on(_withNamespace(BRACKETS_EVENTS_NAMES.PROJECT_CLOSE_EVENT), _eventHandler); //(event, directory)\n        DocumentManager.on(_withNamespace(BRACKETS_EVENTS_NAMES.DOCUMENT_DIRTY_EVENT), _eventHandler); //(event, document)\n        DocumentModule.on(_withNamespace(BRACKETS_EVENTS_NAMES.DOCUMENT_CHANGE_EVENT), _eventHandler); //(event, document, changeList)\n        DocumentManager.on(_withNamespace(BRACKETS_EVENTS_NAMES.FILE_RENAME_EVENT), _eventHandler); //(event, oldName, newName)\n        ProjectManager.on(_withNamespace(BRACKETS_EVENTS_NAMES.BEFORE_APP_CLOSE), _eventHandler); //(event, oldName, newName)\n    }\n\n    _attachEventHandlers();\n\n    function listenToCustomEvent(eventModule, eventName) {\n        eventModule.on(_withNamespace(eventName), _eventHandler);\n    }\n\n    function initiateToolingService(clientName, clientFilePath, languages) {\n        var result = $.Deferred();\n\n        ClientLoader.initiateLanguageClient(clientName, clientFilePath)\n            .done(function (languageClientInfo) {\n                var languageClientName = languageClientInfo.name,\n                    languageClientInterface = languageClientInfo.interface,\n                    languageClient = new LanguageClientWrapper(languageClientName, clientFilePath, languageClientInterface, languages);\n\n                registerLanguageClient(languageClientName, languageClient);\n\n                result.resolve(languageClient);\n            })\n            .fail(result.reject);\n\n        return result;\n    }\n\n    exports.initiateToolingService = initiateToolingService;\n    exports.listenToCustomEvent = listenToCustomEvent;\n});\n"
  },
  {
    "path": "src/languageTools/PathConverters.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* eslint-disable indent */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var PathUtils = require(\"thirdparty/path-utils/path-utils\"),\n        FileUtils = require(\"file/FileUtils\");\n\n    function uriToPath(uri) {\n        var url = PathUtils.parseUrl(uri);\n        if (url.protocol !== 'file:' || url.pathname === undefined) {\n            return uri;\n        }\n\n        let filePath = decodeURIComponent(url.pathname);\n        if (brackets.platform === 'win') {\n            if (filePath && filePath.includes(\":/\") && filePath[0] === '/') {\n                filePath = filePath.substr(1);\n            }\n            return filePath;\n        }\n        return filePath;\n    }\n\n    function pathToUri(filePath) {\n        var newPath = convertWinToPosixPath(filePath);\n        if (newPath[0] !== '/') {\n            newPath = `/${newPath}`;\n        }\n        return encodeURI(`file://${newPath}`).replace(/[?#]/g, encodeURIComponent);\n    }\n\n    function convertToWorkspaceFolders(paths) {\n        var workspaceFolders = paths.map(function (folderPath) {\n            var uri = pathToUri(folderPath),\n                name = FileUtils.getBasename(folderPath);\n\n            return {\n                uri: uri,\n                name: name\n            };\n        });\n\n        return workspaceFolders;\n    }\n\n    function convertPosixToWinPath(path) {\n        return path.replace(/\\//g, '\\\\');\n    }\n\n    function convertWinToPosixPath(path) {\n        return path.replace(/\\\\/g, '/');\n    }\n\n    exports.uriToPath = uriToPath;\n    exports.pathToUri = pathToUri;\n    exports.convertPosixToWinPath = convertPosixToWinPath;\n    exports.convertPosixToWinPath = convertPosixToWinPath;\n    exports.convertToWorkspaceFolders = convertToWorkspaceFolders;\n});\n"
  },
  {
    "path": "src/languageTools/ToolingInfo.json",
    "content": "{\n    \"LANGUAGE_SERVICE\": {\n        \"START\": \"start\",\n        \"STOP\": \"stop\",\n        \"REQUEST\": \"request\",\n        \"NOTIFY\": \"notify\",\n        \"CANCEL_REQUEST\": \"cancelRequest\",\n        \"CUSTOM_REQUEST\": \"customRequest\",\n        \"CUSTOM_NOTIFICATION\": \"customNotification\"\n    },\n    \"SERVICE_NOTIFICATIONS\": {\n        \"SHOW_MESSAGE\": \"showMessage\",\n        \"LOG_MESSAGE\": \"logMessage\",\n        \"TELEMETRY\": \"telemetry\",\n        \"DIAGNOSTICS\": \"diagnostics\"\n    },\n    \"SERVICE_REQUESTS\": {\n        \"SHOW_SELECT_MESSAGE\": \"showSelectMessage\",\n        \"REGISTRATION_REQUEST\": \"registerDynamicCapability\",\n        \"UNREGISTRATION_REQUEST\": \"unregisterDynamicCapability\",\n        \"PROJECT_FOLDERS_REQUEST\": \"projectFoldersRequest\"\n    },\n    \"SYNCHRONIZE_EVENTS\": {\n        \"DOCUMENT_OPENED\": \"didOpen\",\n        \"DOCUMENT_CHANGED\": \"didChange\",\n        \"DOCUMENT_SAVED\": \"didSave\",\n        \"DOCUMENT_CLOSED\": \"didClose\",\n        \"PROJECT_FOLDERS_CHANGED\": \"projectRootsChanged\"\n    },\n    \"FEATURES\": {\n        \"CODE_HINTS\": \"codehints\",\n        \"CODE_HINT_INFO\": \"hintInfo\",\n        \"PARAMETER_HINTS\": \"parameterHints\",\n        \"JUMP_TO_DECLARATION\": \"declaration\",\n        \"JUMP_TO_DEFINITION\": \"definition\",\n        \"JUMP_TO_IMPL\": \"implementation\",\n        \"FIND_REFERENCES\": \"references\",\n        \"DOCUMENT_SYMBOLS\": \"documentSymbols\",\n        \"PROJECT_SYMBOLS\": \"projectSymbols\"\n    }\n}\n"
  },
  {
    "path": "src/languageTools/node/RegisterLanguageClientInfo.js",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global exports*/\n/*eslint-env es6, node*/\n/*eslint max-len: [\"error\", { \"code\": 200 }]*/\n\"use strict\";\n\nvar domainName = \"LanguageClientInfo\",\n    LANGUAGE_CLIENT_RELATIVE_PATH_ARRAY = [\"languageTools\", \"LanguageClient\", \"LanguageClient\"],\n    FORWARD_SLASH = \"/\",\n    BACKWARD_SLASH = \"\\\\\",\n    CompletionItemKind = {\n        Text: 1,\n        Method: 2,\n        Function: 3,\n        Constructor: 4,\n        Field: 5,\n        Variable: 6,\n        Class: 7,\n        Interface: 8,\n        Module: 9,\n        Property: 10,\n        Unit: 11,\n        Value: 12,\n        Enum: 13,\n        Keyword: 14,\n        Snippet: 15,\n        Color: 16,\n        File: 17,\n        Reference: 18,\n        Folder: 19,\n        EnumMember: 20,\n        Constant: 21,\n        Struct: 22,\n        Event: 23,\n        Operator: 24,\n        TypeParameter: 25\n    },\n    SymbolKind = {\n        File: 1,\n        Module: 2,\n        Namespace: 3,\n        Package: 4,\n        Class: 5,\n        Method: 6,\n        Property: 7,\n        Field: 8,\n        Constructor: 9,\n        Enum: 10,\n        Interface: 11,\n        Function: 12,\n        Variable: 13,\n        Constant: 14,\n        String: 15,\n        Number: 16,\n        Boolean: 17,\n        Array: 18,\n        Object: 19,\n        Key: 20,\n        Null: 21,\n        EnumMember: 22,\n        Struct: 23,\n        Event: 24,\n        Operator: 25,\n        TypeParameter: 26\n    },\n    defaultBracketsCapabilities = {\n        //brackets default capabilties\n        \"workspace\": {\n            \"workspaceFolders\": true,\n            \"symbol\": {\n                \"dynamicRegistration\": false,\n                \"symbolKind\": [\n                    SymbolKind.File,\n                    SymbolKind.Module,\n                    SymbolKind.Namespace,\n                    SymbolKind.Package,\n                    SymbolKind.Class,\n                    SymbolKind.Method,\n                    SymbolKind.Property,\n                    SymbolKind.Field,\n                    SymbolKind.Constructor,\n                    SymbolKind.Enum,\n                    SymbolKind.Interface,\n                    SymbolKind.Function,\n                    SymbolKind.Variable,\n                    SymbolKind.Constant,\n                    SymbolKind.String,\n                    SymbolKind.Number,\n                    SymbolKind.Boolean,\n                    SymbolKind.Array,\n                    SymbolKind.Object,\n                    SymbolKind.Key,\n                    SymbolKind.Null,\n                    SymbolKind.EnumMember,\n                    SymbolKind.Struct,\n                    SymbolKind.Event,\n                    SymbolKind.Operator,\n                    SymbolKind.TypeParameter\n                ]\n            }\n        },\n        \"textDocument\": {\n            \"synchronization\": {\n                \"didSave\": true\n            },\n            \"completion\": {\n                \"dynamicRegistration\": false,\n                \"completionItem\": {\n                    \"deprecatedSupport\": true,\n                    \"documentationFormat\": [\"plaintext\"],\n                    \"preselectSupport\": true\n                },\n                \"completionItemKind\": {\n                    \"valueSet\": [\n                        CompletionItemKind.Text,\n                        CompletionItemKind.Method,\n                        CompletionItemKind.Function,\n                        CompletionItemKind.Constructor,\n                        CompletionItemKind.Field,\n                        CompletionItemKind.Variable,\n                        CompletionItemKind.Class,\n                        CompletionItemKind.Interface,\n                        CompletionItemKind.Module,\n                        CompletionItemKind.Property,\n                        CompletionItemKind.Unit,\n                        CompletionItemKind.Value,\n                        CompletionItemKind.Enum,\n                        CompletionItemKind.Keyword,\n                        CompletionItemKind.Snippet,\n                        CompletionItemKind.Color,\n                        CompletionItemKind.File,\n                        CompletionItemKind.Reference,\n                        CompletionItemKind.Folder,\n                        CompletionItemKind.EnumMember,\n                        CompletionItemKind.Constant,\n                        CompletionItemKind.Struct,\n                        CompletionItemKind.Event,\n                        CompletionItemKind.Operator,\n                        CompletionItemKind.TypeParameter\n                    ]\n                },\n                \"contextSupport\": true\n            },\n            \"signatureHelp\": {\n                \"dynamicRegistration\": false,\n                \"signatureInformation\": {\n                    \"documentationFormat\": [\"plaintext\"]\n                }\n            },\n            \"references\": {\n                \"dynamicRegistration\": false\n            },\n            \"documentSymbol\": {\n                \"dynamicRegistration\": false,\n                \"symbolKind\": {\n                    \"valueSet\": [\n                        SymbolKind.File,\n                        SymbolKind.Module,\n                        SymbolKind.Namespace,\n                        SymbolKind.Package,\n                        SymbolKind.Class,\n                        SymbolKind.Method,\n                        SymbolKind.Property,\n                        SymbolKind.Field,\n                        SymbolKind.Constructor,\n                        SymbolKind.Enum,\n                        SymbolKind.Interface,\n                        SymbolKind.Function,\n                        SymbolKind.Variable,\n                        SymbolKind.Constant,\n                        SymbolKind.String,\n                        SymbolKind.Number,\n                        SymbolKind.Boolean,\n                        SymbolKind.Array,\n                        SymbolKind.Object,\n                        SymbolKind.Key,\n                        SymbolKind.Null,\n                        SymbolKind.EnumMember,\n                        SymbolKind.Struct,\n                        SymbolKind.Event,\n                        SymbolKind.Operator,\n                        SymbolKind.TypeParameter\n                    ]\n                },\n                \"hierarchicalDocumentSymbolSupport\": false\n            },\n            \"definition\": {\n                \"dynamicRegistration\": false\n            },\n            \"declaration\": {\n                \"dynamicRegistration\": false\n            },\n            \"typeDefinition\": {\n                \"dynamicRegistration\": false\n            },\n            \"implementation\": {\n                \"dynamicRegistration\": false\n            },\n            \"publishDiagnostics\": {\n                \"relatedInformation\": true\n            }\n        }\n    };\n\nfunction syncPreferences(prefs) {\n    global.LanguageClientInfo = global.LanguageClientInfo || {};\n    global.LanguageClientInfo.preferences = prefs || global.LanguageClientInfo.preferences || {};\n}\n\nfunction initialize(bracketsSourcePath, toolingInfo, resolve) {\n    if (!bracketsSourcePath || !toolingInfo) {\n        resolve(true, null); //resolve with err param\n    }\n    \n    var normalizedBracketsSourcePath = bracketsSourcePath.split(BACKWARD_SLASH).join(FORWARD_SLASH),\n        bracketsSourcePathArray = normalizedBracketsSourcePath.split(FORWARD_SLASH),\n        languageClientAbsolutePath = bracketsSourcePathArray.concat(LANGUAGE_CLIENT_RELATIVE_PATH_ARRAY).join(FORWARD_SLASH);\n\n    global.LanguageClientInfo = global.LanguageClientInfo || {};\n    global.LanguageClientInfo.languageClientPath = languageClientAbsolutePath;\n    global.LanguageClientInfo.defaultBracketsCapabilities = defaultBracketsCapabilities;\n    global.LanguageClientInfo.toolingInfo = toolingInfo;\n    global.LanguageClientInfo.preferences = {};\n    \n    resolve(null, true); //resolve with boolean denoting success\n}\n\nfunction init(domainManager) {\n    if (!domainManager.hasDomain(domainName)) {\n        domainManager.registerDomain(domainName, {\n            major: 0,\n            minor: 1\n        });\n    }\n\n    domainManager.registerCommand(\n        domainName,\n        \"initialize\",\n        initialize,\n        true,\n        \"Initialize node environment for Language Client Module\",\n        [\n            {\n                name: \"bracketsSourcePath\",\n                type: \"string\",\n                description: \"Absolute path to the brackets source\"\n            },\n            {\n                name: \"toolingInfo\",\n                type: \"object\",\n                description: \"Tooling Info json to be used by Language Client\"\n            }\n        ],\n        []\n    );\n\n    domainManager.registerCommand(\n        domainName,\n        \"syncPreferences\",\n        syncPreferences,\n        false,\n        \"Sync language tools preferences for Language Client Module\",\n        [\n            {\n                name: \"prefs\",\n                type: \"object\",\n                description: \"Language tools preferences\"\n            }\n        ],\n        []\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/languageTools/styles/default_provider_style.css",
    "content": "/*\n * Copyright (c) 2019 - present Adobe. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n\nspan.brackets-hints-with-type-details {\n    width: 300px;\n    display: inline-block;\n}\n\n.brackets-hints-type-details {\n    color: #a3a3a3 !important;\n    font-weight: 100;\n    font-style: italic !important;\n    margin-right: 5px;\n    float: right;\n}\n\n.hint-description {\n    display: none;\n    color: #d4d4d4;\n    word-wrap: break-word;\n    white-space: normal;\n    box-sizing: border-box;\n}\n\n.hint-doc {\n    display: none;\n    padding-right: 10px !important;\n    color: grey;\n    word-wrap: break-word;\n    white-space: normal;\n    box-sizing: border-box;\n    float: left;\n    clear: left;\n    max-height: 2em;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    line-height: 1em;\n    -webkit-line-clamp: 2;\n    -webkit-box-orient: vertical;\n}\n\n.highlight .hint-description {\n    display: block;\n    color: #6495ed !important;\n}\n\n.highlight .hint-doc {\n    display: -webkit-box;\n}\n\n.dark .brackets-hints-type-details {\n    color: #696969 !important;\n}\n\n.highlight .brackets-hints-type-details {\n    display: none;\n}\n\n.brackets-hints-keyword {\n    font-weight: 100;\n    font-style: italic !important;\n    margin-right: 5px;\n    float: right;\n    color: #6495ed !important;\n}\n\n.brackets-hints .matched-hint {\n    font-weight: 500;\n}\n\n#function-hint-container-new {\n    display: none;\n\n    background: #fff;\n    position: absolute;\n    z-index: 15;\n    left: 400px;\n    top: 40px;\n    height: auto;\n    width: auto;\n    overflow: scroll;\n\n    padding: 1px 6px;\n    text-align: center;\n\n    border-radius: 3px;\n    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.24);\n}\n\n#function-hint-container-new .function-hint-content-new {\n    text-align: left;\n}\n\n.brackets-hints .current-parameter {\n    font-weight: 500;\n}\n\n/* Dark Styles */\n\n.dark #function-hint-container-new {\n    background: #000;\n    border: 1px solid rgba(255, 255, 255, 0.15);\n    color: #fff;\n    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.24);\n}\n\n.dark .hint-doc {\n    color: #ccc;\n}\n\n.dark .hint-description {\n    color: #ccc;\n}\n"
  },
  {
    "path": "src/main.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * The bootstrapping module for brackets. This module sets up the require\n * configuration and loads the brackets module.\n */\nrequire.config({\n    paths: {\n        \"text\"              : \"thirdparty/text/text\",\n        \"i18n\"              : \"thirdparty/i18n/i18n\",\n\n        // The file system implementation. Change this value to use different\n        // implementations (e.g. cloud-based storage).\n        \"fileSystemImpl\"    : \"filesystem/impls/appshell/AppshellFileSystem\",\n        \"preact-compat\"     : \"thirdparty/preact-compat/preact-compat.min\",\n        \"preact\"            : \"thirdparty/preact/preact\"\n    },\n    map: {\n        \"*\": {\n            \"thirdparty/CodeMirror2\": \"thirdparty/CodeMirror\",\n            \"thirdparty/preact\"     : \"preact-compat\"\n        }\n    }\n});\n\nif (window.location.search.indexOf(\"testEnvironment\") > -1) {\n    require.config({\n        paths: {\n            \"preferences/PreferencesImpl\": \"../test/TestPreferencesImpl\"\n        },\n        locale: \"en\" // force English (US)\n    });\n} else {\n    /**\n     * hack for r.js optimization, move locale to another config call\n     *\n     * Use custom brackets property until CEF sets the correct navigator.language\n     * NOTE: When we change to navigator.language here, we also should change to\n     * navigator.language in ExtensionLoader (when making require contexts for each\n     * extension).\n     */\n    require.config({\n        locale: window.localStorage.getItem(\"locale\") || (typeof (brackets) !== \"undefined\" ? brackets.app.language : window.navigator.language)\n    });\n}\n\ndefine(function (require) {\n    \"use strict\";\n\n    // Load compatibility shims--these need to load early, be careful moving this\n    require([\"utils/Compatibility\"], function () {\n        // Load the brackets module. This is a self-running module that loads and runs the entire application.\n        require([\"brackets\"]);\n    });\n});\n"
  },
  {
    "path": "src/nls/README.md",
    "content": "# How to add translations for a *new* locale\n\n1. Create a subfolder of the `nls` folder whose name is the language or locale you want to\n   create a translation for.\n    * If you're creating a general translation for a language, just use its two-letter code\n      (e.g. `en`, `de`).\n    * If you're creating a locale-specific translation for a particular country, add a hyphen\n      and the country code in lowercase (e.g. `en-ca`, `en-gb`).\n2. Add an entry for your translation to the `module.exports` object in `nls/strings.js`.\n3. Edit the root `strings-app.js` file and add a new `LOCALE_`* entry for your language, as seen in\n   the Debug > Switch Language UI.\n4. Copy the root `strings.js` file into your subfolder and start translating!\n5. Use the [UI walkthrough steps](https://github.com/adobe/brackets/wiki/Localization-Tests) to\n   see strings in context.\n6. Add this comment ``/* Last translated for commit_SHA_of_root_strings.js */`` at the end \n   of your `strings.js` and replace `commit_SHA_of_root_strings.js` with the actual SHA.\n   You can copy the actual SHA in this [history page](https://github.com/adobe/brackets/commits/master/src/nls/root/strings.js)\n   by hovering on the one you used for this translation and click on Copy SHA button.\n7. Edit this file and update the list of languages below!\n\nStrings not specified in a given locale will fall back to the general language (without hyphen)\nfirst, and then will fall back to the English string from `nls/root/strings.js`.\n\nLocalization is provided via the [require.js i18n plugin](http://requirejs.org/docs/api.html#i18n).\n\n### Translating the Getting Started project\n\nWhen first installed, Brackets will open a Getting Started project that serves\nas an introduction to Brackets features. This project can be translated by\nproviding a ``urls.js`` file that points to a localized directory under the\n``samples`` folder at the root of the Brackets repository. See the French\nlocalization (`src/nls/fr/urls.js`) for an example.\n\nIt is also recommended to add this comment ``<!-- Last translated for commit_SHA_of_root_index.html -->``\nat the end of your `index.html` and replace `commit_SHA_of_root_index.html` with the actual SHA.\n\n\n# How to modify *existing* translations\n\n### Adobe-maintained translations\n\nAdobe provides translations for the following languages:\n\n* French (fr)\n* Japanese (ja)\n\nThese translations cannot be modified through our normal pull request\nprocess. Please contribute changes by filing an issue in our GitHub repository https://github.com/adobe/brackets/issues\n\n### Community-maintained translations\n\nThe following languages have been contributed by the Brackets community:\n\n* Bulgarian (bg)\n* Czech (cs)\n* Danish (da)\n* German (de)\n* Greek (el)\n* Spanish (es)\n* Persian-Farsi (fa-ir)\n* Finnish (fi)\n* Galician (gl)\n* Croatian (hr)\n* Hungarian (hu)\n* Indonesia (id)\n* Italian (it)\n* Korean (ko)\n* Latvian (lv)\n* Norwegian (nb)\n* Dutch (nl)\n* Polish (pl)\n* Brazilian Portuguese (pt-br)\n* Portuguese (pt-pt)\n* Romanian (ro)\n* Russian (ru)\n* Slovak (sk)\n* Serbian (sr)\n* Swedish (sv)\n* Turkish (tr)\n* Ukrainian (uk)\n* Simplified Chinese (zh-cn)\n* Traditional Chinese (zh-tw)\n\nThese translations _can be directly modified_ through our normal pull request\nprocess. Make sure that you also update the comment on the last line with the \ncorrect SHA of `strings.js` from root directory, which you used for your translation.\nIf the SHA comment is missing, then add one with the correct SHA. See step 6 in \n__How to add translations for a *new* locale__ section for adding a new one.\n\nIn the future, Adobe may begin maintaining some of these languages too, at which\npoint the process will switch to the one above. But until then, please _do not\nuse_ http://translate.adobe.com for these languages.\n\n\n## Contributing Translations directly from github.com\n\nYou must be logged in to your github.com id (e.g. `user1`).\n\n### Adding a New Translation\nTo add a new translation, you need to start with a copy of the\nroot `strings.js` file which is located at\n[https://github.com/adobe/brackets/blob/master/src/nls/root/strings.js](https://github.com/adobe/brackets/blob/master/src/nls/root/strings.js).\nNew translations can be added by navigating to the\n[nls folder on github](https://github.com/adobe/brackets/tree/master/src/nls)\nand then clicking on the [+] button to add a new file.\nYou will be taken to a New File page where you:\n\n1. Specify the file name as *language-id*/strings.js\n2. Paste in the contents of root/strings.js and edit strings for new language\n3. Add this comment `/* Last translated for commit_SHA_of_root_strings.js */`\nat the end of your strings.js and replace `commit_SHA_of_root_strings.js` with the\nactual SHA.\nYou can copy the actual SHA in this\n[history page](https://github.com/adobe/brackets/commits/master/src/nls/root/strings.js)\nby hovering on the one you used for this translation and click on Copy SHA button.\n4. Add short and (optional) long description of new file\n5. Click \"Propose New File\" button\n\n### Editing an Existing Translation\nExisting files can be edited directly in\n[brackets repo on github](https://github.com/adobe/brackets).\n\nNavigate to the file to edit and click \"Edit\" button above file.\nYou will be taken to an Edit File page where you:\n\n1. Make desired edits to file\n2. Make sure that you also update the comment on the last line with the correct SHA of\nstrings.js from root directory, which you used for your translation. If the SHA comment\nis missing, then add one with the correct SHA. See step 6 in How to add translations\nfor a new locale section for adding a new one.\n3. Add short and (optional) long description of Commit changes\n4. Click \"Commit changes\" button\n\n### Branch and Pull Request\nFor either case, if you have not yet forked the brackets repository in your\ngithub account (`https://github.com/user1/brackets`), it's done automatically.\nA new branch will be created in your Brackets fork with a unique name\nwhich is something like `patch-1` that contains your changes.\n\nYou are then taken to the New Pull Request dialog which is filled in\nwith all of the information from previous dialog.\nIt also shows contents of new file or a \"diff\" of changes to existing file.\nYou can make any changes if desired, then click \"Send Pull Request\" when done\n(or close page to Cancel).\nA pull request for your branch is created and submitted to the Brackets \"repo\".\n\n### Code Review\nSomeone on the Brackets team will review the pull request. If it's ok, it will\nbe merged. If changes need to be made, the reviewer will post comments in the\npull request which will send you an e-mail notification.\n\n### Updating Existing Branch and Pull Request\n\nIf you need to make changes to an existing branch, \nyou should make updates in the `patch-1` branch in your Github fork of Brackets\nso all of your changes for this update are in a single branch.\nCreating a new branch for every update makes it difficult for core team\nto see all changes at once, and can even create conflicts that are\nvery difficult to resolve. For example:\n\n1. After submitting your pull request, look at the top where it says something like:\n\n    `user1` wants to merge 1 commit into `adobe:master` from `user1:patch-1`\n    \n2. Go to your github fork of brackets page: `github.com/user1/brackets`\n3. Click on the Branches Tab: `github.com/user1/brackets/branches`\n4. Click on the link to the branch: `github.com/user1/brackets/tree/patch-1`\n5. This is where you make changes to your `patch-1` branch.\n\nSaved edits show up as a new commit, so they automatically show up in the original\npull request. After making an update, add a comment to the pull request such as\n\"Changes made -- ready for another review\" to notify reviewer\nthat it's time to review the changes again.\n\n\n# Translation limitations\n\nSome strings cannot be localized yet:\n\n* [Keyboard shortcuts](https://trello.com/c/4k2yalBd)\n* [Some native menus on Mac](https://trello.com/c/0IsE7q02) (hardcoded support only for English, French, Japanese)\n* Windows installer UI (hardcoded support only for English, Japanese - with some limitations)\n* Localized folder name of \"Getting Started\" has to be made of up basic English characters only, as described\n[here](https://github.com/adobe/brackets/pull/8332#issuecomment-48767847).\n"
  },
  {
    "path": "src/nls/bg/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(грешка {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Файлът/папката не може да бъде открит.\",\n    \"NOT_READABLE_ERR\"                  : \"Файлът/папката не може да бъде прочетен.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Файлове с размер по-голям от {0} МБ не могат да бъдат прочетени от {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Целевата папка не може да бъде променяна.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Правата не Ви позволяват да правите промени.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Файлът е бил променен извън {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} в момента поддържа само текстови файлове с кодировка UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Файлът или папката вече съществува.\",\n    \"FILE\"                              : \"файл\",\n    \"FILE_TITLE\"                        : \"Файл\",\n    \"DIRECTORY\"                         : \"папка\",\n    \"DIRECTORY_TITLE\"                   : \"Папка\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Имена на папки\",\n    \"FILENAMES_LEDE\"                    : \"Имена на файлове\",\n    \"FILENAME\"                          : \"Име на файл\",\n    \"DIRECTORY_NAME\"                    : \"Име на папка\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Грешка при зареждане на проекта\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Възникна грешка при показването на прозореца за отваряне на файл. (грешка {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Възникна грешка при опита за зареждане на папката <span class='dialog-filename'>{0}</span>. (грешка {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Възникна грешка при прочитането на съдържанието на папката <span class='dialog-filename'>{0}</span>. (грешка {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Грешка при отваряне на файла\",\n    \"ERROR_OPENING_FILE\"                : \"Възникна грешка при опита за отваряне на файла <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Възникна грешка при опита за отваряне на следните файлове:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Грешка при прочитането на промените от диска\",\n    \"ERROR_RELOADING_FILE\"              : \"Възникна грешка при опита за презареждане на файла <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Грешка при запазването на файла\",\n    \"ERROR_SAVING_FILE\"                 : \"Възникна грешка при опита за запазване на файла <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Грешка при преименуването на {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Възникна грешка при опита за преименуване на {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Файлът или папката не е част от текущо отворения проект. За съжаление, само файловете в проекта могат да бъдат преименувани засега.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Грешка при изтриването на {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Възникна грешка при опита за изтриване на {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Грешно {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} не може да използва запазени думи, да завършва с точки (.) или да използва никой от следните знаци: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Вече съществува файл или папка с името <span class='dialog-filename'>{0}</span>.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Грешка при създаването на {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Възникна грешка при опита за създаване на {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Папка и файлове не могат да се отварят едновременно.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Грешка при прочитането на потребителските клавишни настройки\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Файлът с Вашите клавишни настройки не е правилно форматиран според формата JSON. Файлът ще бъде отворен, за да го поправите.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Файлът с Вашите клавишни настройки не е кодиран в правилната кодировка UTF-8 и не може да бъде зареден.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Не можете да настройвате други клавиши и комбинации за следните команди: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Не можете да пренастройвате следните клавиши и комбинации: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Настройвате твърде много клавишни комбинации за следните команди: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Имате твърде много настроени команди за следните клавишни комбинации: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Следните клавишни комбинации са грешни: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Задавате клавишни комбинации на несъществуващи команди: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Грешка при прочитането на настройките\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Файлът с настройките не е правилно форматиран според формата JSON. Файлът ще бъде отворен, за да го поправите. След това ще трябва да затворите и пуснете отново {APP_NAME}, за да влязат в сила промените.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Файлът с настройките на проекта не е правилно форматиран според формата JSON. Файлът ще бъде отворен, за да го поправите. След това ще трябва да презаредите проекта, за да влязат в сила промените.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Опа! {APP_NAME} все още не може да работи в браузър.\",\n    \"ERROR_IN_BROWSER\"                  : \"Приложението {APP_NAME} е изградено чрез HTML, но в момента работи като настолно приложение, така че да може да го използвате за редактиране на местни файлове. Моля, използвайте приложната обвивка от хранилището <b>github.com/adobe/brackets-shell</b>, за да пуснете {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Грешка при обработката на файловете\",\n    \"ERROR_MAX_FILES\"                   : \"Този проект има над 30 000 файла. Функционалностите, които работят с множество файлове може да бъдат изключени или да работят така, сякаш проектът е празен. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Прочете повече относно работата с големи проекти</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Грешка при пускането на браузъра\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Браузърът „Google Chrome“ не може да бъде открит. Моля, уверете се, че той е инсталиран.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Възникна грешка при пускането на браузъра. (грешка {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Грешка при прегледа на живо\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Свързване с браузъра\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"За да може да се свърже прегледът на живо, Chrome трябва да бъде пуснат отново с включена възможност за отдалечено отстраняване на грешки.<br /><br />Искате ли да пуснете отново Chrome и да включите тази възможност?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Неуспешно зареждане на страницата в прегледа на живо.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Отворете файл с HTML или се уверете, че има файл с името „index.html“ в проекта Ви, за да можете да пуснете прегледа на живо.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"За да пуснете прегледа на живо с файл от сървър, трябва да посочите базов адрес за този проект.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Грешка при пускането на HTTP сървъра за преглед на файлове на живо. Моля, опитайте отново.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Добре дошли в прегледа на живо!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Прегледът на живо свързва {APP_NAME} към браузъра Ви. Той Ви дава възможност да видите своя HTML файл в браузъра си, а след това го обновява постоянно, докато редактирате кода си.<br /><br />В тази ранна версия на {APP_NAME}, прегледът на живо може да работи единствено с <strong>Google Chrome</strong> и се обновява, докато редактирате файлове от типовете <strong>CSS и HTML</strong>. Промените във файловете с код на JavaScript се презареждат автоматично, когато ги запазите.<br /><br />(Това съобщение се появява само веднъж.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"За повече информация, вижте <a href='{0}' title='{0}'>Отстраняване на проблеми с връзката на прегледа на живо</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Преглед на живо\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Преглед на живо: свързване\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Преглед на живо: установка\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Разкачане на прегледа на живо\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Преглед на живо (запазете файла, за да опресните)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Преглед на живо (без обновяване, поради синтактична грешка)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Прегледът на живо беше прекъснат, тъй като бяха отворени инструментите за разработчици на браузъра.\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Прегледът на живо беше прекъснат, тъй като страницата в браузъра беше затворена.\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Прегледът на живо беше прекъснат, тъй като бръузърът премина към страница, която не е част от текущия проект.\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Прегледът на живо беше прекъснат поради неизвестна причина ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Запазване на промените\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Искате ли да запазите промените, които направихте в документа <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Искате ли да запазите промените си в следните файлове?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Външни промени\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Потвърждаване на изтриването\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Наистина ли искате да изтриете папката <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Изтрит файл\",\n    \"EXT_MODIFIED_WARNING\"              : \"Файлът <span class='dialog-filename'>{0}</span> беше променен извън {APP_NAME}.<br /><br />Искате ли да запазите файла и да презапишете промените му?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"Файлът <span class='dialog-filename'>{0}</span> беше променен извън {APP_NAME}, но също така има незапазени промени в {APP_NAME}.<br /><br />Кой вариант искате да запазите?\",\n    \"EXT_DELETED_MESSAGE\"               : \"Файлът <span class='dialog-filename'>{0}</span> беше изтрит извън {APP_NAME}, но има незапазени промени в {APP_NAME}.<br /><br />Искате ли да запазите промените си?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Готово\",\n    \"OK\"                                : \"Добре\",\n    \"CANCEL\"                            : \"Отказ\",\n    \"DONT_SAVE\"                         : \"Без запазване\",\n    \"SAVE\"                              : \"Запазване\",\n    \"SAVE_AS\"                           : \"Запазване като\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Презаписване\",\n    \"DELETE\"                            : \"Изтриване\",\n    \"BUTTON_YES\"                        : \"Да\",\n    \"BUTTON_NO\"                         : \"Не\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} от {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Няма резултати\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Търсене\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Замяна с\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Група\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Замяна\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Замяна\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Следващо съвпадение\",\n    \"BUTTON_PREV_HINT\"                  : \"Предишно съвпадение\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Съвпадение на малки/големи букви\",\n    \"BUTTON_REGEXP_HINT\"                : \"Регулярен израз\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Замяна без възможност връщане\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Тъй като трябва да бъдат променени повече от {0} файла, {APP_NAME} ще промени и неотворените файлове направо в диска.<br />Няма да можете да отмените замените в тези файлове.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Замяна без връщане\",\n\n    \"OPEN_FILE\"                         : \"Отваряне на файл\",\n    \"SAVE_FILE_AS\"                      : \"Запазване на файл\",\n    \"CHOOSE_FOLDER\"                     : \"Изберете папка\",\n\n    \"RELEASE_NOTES\"                     : \"Бележки за изданието\",\n    \"NO_UPDATE_TITLE\"                   : \"Актулно издание!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Вие използвате най-новото издание на {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Замяна на\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"с\",\n    \"FIND_TITLE_LABEL\"                  : \"Открито:\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} в {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"в <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"в проекта\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Филтърът изключва всички файлове {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"файл\",\n    \"FIND_IN_FILES_FILES\"               : \"файла\",\n    \"FIND_IN_FILES_MATCH\"               : \"съвпадение\",\n    \"FIND_IN_FILES_MATCHES\"             : \"съвпадения\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Над \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd + щракване за показване/скриване на всички\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Обработване за мигновено търсене\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Грешки при замяната\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Следните файлове не бяха променени, тъй като те самите са били променени след търсенето, или не могат да бъдат записани.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Грешка при получаване на информацията за обновлението\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Възникна грешка при получаването на информацията за най-новото обновление от сървъра. Моля, уверете се, че имате връзка с Интернет, и опитайте отново.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Нов множество за изключване\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Да не се изключват файлове\",\n    \"NO_FILE_FILTER\"                    : \"Няма изключени файлове\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Изключване на {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Редактиране\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Редактиране на множество за изключване\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Изключете файловете и папките, отговарящи на следните низове/поднизове или <a href='{0}' title='{0}'>маски</a>. Въвеждайте всеки низ на нов ред.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Въведете име за това множество (незадължително)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"и още {0}\",\n    \"FILTER_COUNTING_FILES\"             : \"Броене на файловете\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Позволени са {0} от {1} файл(а) {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Позволени са всички {0} файл(а) {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Няма приложимо бързо редактиране за текущото местоположение на курсора.\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Бързо редактиране на CSS: поставете курсора върху едно име на клас.\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Бързо редактиране на CSS: непълен атрибут на клас.\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Бързо редактиране на CSS: непълен атрибут на идентификатор.\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Бързо редактиране на CSS: поставете кърсора върху елемент, клас или идентификатор.\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Бързо редактиране на времева функция в CSS: грешен синтаксис.\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Бързо редактиране на JS: поставете курсора върху име на функция.\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Няма бързи документи за текущото местоположение на курсора.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Зареждане\\u2026\",\n    \"UNTITLED\"          : \"Неозаглавен\",\n    \"WORKING_FILES\"     : \"Работни файлове\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Горе\",\n    \"BOTTOM\"            : \"Долу\",\n    \"LEFT\"              : \"Ляво\",\n    \"RIGHT\"             : \"Дясно\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Без разделяне\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Вертикално разделяне\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Хоризонтално разделяне\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Вертикално или хоризонтално разделяне на редактора\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Настройки за работните файлове\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Вече е отворен\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Файлът вече е отворен в друг раздел. {APP_NAME} скоро ще поддържа отварянето на един и същ файл в повече от един раздел. Дотогава файлът ще бъде показван само в раздела, в който вече е отворен.<br /><br />(Това съобщение се появява само веднъж.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"Space\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Ред {0}, колона {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Избрана е {0} колона\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Избрани са {0} колони\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Избран е {0} ред\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Избрани са {0} реда\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} избора\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Щракнете, за да превърнете отстъпите в интервали\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Щракнете, за да превърнете отстъпите в табулации\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Щракнете, за да промените броя интервали, използвани при отстъпите\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Щракнете, за да промените ширината на табулатора в брой знаци\",\n    \"STATUSBAR_SPACES\"                      : \"Интервали:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Табулация с размер:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} ред\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} реда\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Разширенията са изключени\",\n    \"STATUSBAR_INSERT\"                      : \"ВМК\",\n    \"STATUSBAR_OVERWRITE\"                   : \"ЗАМ\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Щракнете, за да превключите поведените на курсора между вмъкване (ВМК) и заместване (ЗАМ)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Щракнете, за да промените типа на файла\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Щракнете, за да превключите панела да доклади.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(по подразбиране)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Задаване по подразбиране за файлове с разширение .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"Проблеми от {0}\",\n    \"SINGLE_ERROR\"                          : \"1 проблем от {0} \",\n    \"MULTIPLE_ERRORS\"                       : \"{1} проблема от {0}\",\n    \"NO_ERRORS\"                             : \"Не са открити проблеми от {0} — добра работа!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Не са открити проблеми — добра работа!\",\n    \"LINT_DISABLED\"                         : \"Проверката е изключена\",\n    \"NO_LINT_AVAILABLE\"                     : \"Няма налични системи за проверка на {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Няма нищо за проверка\",\n    \"LINTER_TIMED_OUT\"                      : \"Времето на {0} изтече след като чака {1} милисекунди\",\n    \"LINTER_FAILED\"                         : \"{0} приключи с грешка: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Файл\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Нов\",\n    \"CMD_FILE_NEW\"                        : \"Нов файл\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Нова папка\",\n    \"CMD_FILE_OPEN\"                       : \"Отваряне\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Отваряне в работните файлове\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Отваряне на пуснати файлове\",\n    \"CMD_OPEN_FOLDER\"                     : \"Отваряне на папка\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Затваряне\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Затваряне на всички\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Затваряне на списък\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Затваряне на останалите\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Затваряне на всички отгоре\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Затваряне на всички отдолу\",\n    \"CMD_FILE_SAVE\"                       : \"Запазване\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Запазване на всички\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Запазване като\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Преглед на живо\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Включване на експерименталния преглед на живо\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Презареждане на прегледа на живо насила\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Настройки на проекта\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Преименуване\",\n    \"CMD_FILE_DELETE\"                     : \"Изтриване\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Инсталиране на разширение\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Управител на разширения\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Опресняване на дървото от файлове\",\n    \"CMD_QUIT\"                            : \"Изход\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Изход\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Редактиране\",\n    \"CMD_UNDO\"                            : \"Отмяна\",\n    \"CMD_REDO\"                            : \"Повторение\",\n    \"CMD_CUT\"                             : \"Отрязване\",\n    \"CMD_COPY\"                            : \"Копиране\",\n    \"CMD_PASTE\"                           : \"Поставяне\",\n    \"CMD_SELECT_ALL\"                      : \"Избиране на всичко\",\n    \"CMD_SELECT_LINE\"                     : \"Избиране на ред\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Разделяне на избраното на редове\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Добавяне на курсор на следващия ред\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Добавяне на курсор на предишния ред\",\n    \"CMD_INDENT\"                          : \"Увеличаване на отстъпа\",\n    \"CMD_UNINDENT\"                        : \"Намаляване на отстъпа\",\n    \"CMD_DUPLICATE\"                       : \"Копие на реда\",\n    \"CMD_DELETE_LINES\"                    : \"Изтриване на реда\",\n    \"CMD_COMMENT\"                         : \"Превключване на коментар на реда\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Превключване на коментар на блок\",\n    \"CMD_LINE_UP\"                         : \"Преместване на реда нагоре\",\n    \"CMD_LINE_DOWN\"                       : \"Преместване на реда надолу\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Нов ред отгоре\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Нов ред отдолу\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Автоматично затваряне на скобите\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Показване на подсказки за кода\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Търсене\",\n    \"CMD_FIND\"                            : \"Търсене\",\n    \"CMD_FIND_NEXT\"                       : \"Търсене на следващото\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Търсене на предишното\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Търсене на всичко и избиране\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Добавяне на следващото съвпадение към избора\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Пропускане и добавяне на следващото съвпадение\",\n    \"CMD_FIND_IN_FILES\"                   : \"Търсене във файлове\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Търсене в\\u2026\",\n    \"CMD_REPLACE\"                         : \"Замяна\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Замяна във файлове\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Замяна в\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Преглед\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Скриване на страничната лента\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Показване на страничната лента\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Превключване на страничната лента\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Превключване на панелите\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Без разсейвания\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Увеличаване на размера на шрифта\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Намаляване на размера на шрифта\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Възстановяване на размера на шрифта\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Превъртане един ред нагоре\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Превъртане един ред надолу\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Номера на редове\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Осветяване на текущия ред\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Пренасяне\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Осветяване на прегледа на живо\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Проверка на файловете при запазване\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Подреждане по ред на добавяне\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Подреждане по име\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Подреждане по тип\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Автоматично подреждане\",\n    \"CMD_THEMES\"                          : \"Теми\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Придвижване\",\n    \"CMD_QUICK_OPEN\"                      : \"Бързо отваряне\",\n    \"CMD_GOTO_LINE\"                       : \"Отиване на ред\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Бързо търсене на определение\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Преминаване към първия проблем\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Бързо редактиране\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Бърза документация\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Предишно съвпадение\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Следващо съвпадение\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Ново правило\",\n    \"CMD_NEXT_DOC\"                        : \"Следващ документ\",\n    \"CMD_PREV_DOC\"                        : \"Предишен документ\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Следващ документ в списъка\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Предишен документ в списъка\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Показване в дървото на файловете\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Показване в Explorer\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Показване във Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Показване в ОС\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Помощ\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Проверка за обновления\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Как се използва {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Поддръжка на {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Предложете функционалност\",\n    \"CMD_RELEASE_NOTES\"                   : \"Бележки за изданието\",\n    \"CMD_GET_INVOLVED\"                    : \"Включете се\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Показване на папката с разширенията\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Здравен доклад\",\n    \"CMD_HOMEPAGE\"                        : \"Начална страница на {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} в Тиутър\",\n    \"CMD_ABOUT\"                           : \"Относно {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Отваряне на файла с настройките\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Отваряне на файла с потребителските клавишни настройки\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"експериментална компилация\",\n    \"RELEASE_BUILD\"                        : \"компилация\",\n    \"DEVELOPMENT_BUILD\"                    : \"компилация за разработчици\",\n    \"RELOAD_FROM_DISK\"                     : \"Презареждане от диска\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Използване на промените в редактора\",\n    \"CLOSE_DONT_SAVE\"                      : \"Затваряне (без запазване)\",\n    \"RELAUNCH_CHROME\"                      : \"Повторно пускане на Chrome\",\n    \"ABOUT\"                                : \"Относно\",\n    \"CLOSE\"                                : \"Затваряне\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Издание {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"дата на компилиране: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Бележките, правата и условията, свързани с използването на софтуер от трети страни, могат да бъдат открити на <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> и смятани за включени тук.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Документацията и изходният код могат да бъдат открити тук: <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Създадено с \\u2764 и JavaScript от:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Много хора (но в момента не може да заредим данните за тях).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"Документацията и логото на MDN са лицензирани под лиценз за признание от вида „Криейтив Комънс“: <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Нелокализиран</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Има ново издание на {APP_NAME}! Щракнете тук за подробности.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Има ново обновление\",\n    \"UPDATE_MESSAGE\"                       : \"Хей, има ново издание на {APP_NAME}. Ето някои от новите функционалности:\",\n    \"GET_IT_NOW\"                           : \"Вземете го сега!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Настройки на проекта за: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Базов адрес за преглед на живо\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"За да използвате местен сървър, въведете адрес като: http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Протоколът {0} не се поддържа от прегледа на живо &mdash; моля, използвайте „http:“ или „https:“.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Базовият адрес не може да съдържа параметри за търсене като „{0}“.\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Базовият адрес не може да съдържа диези като „{0}“.\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Специалните знаци като „{0}“ трябва да бъдат кодирани с „%“.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Възникна неизвестна грешка при обработката на базовия адрес.\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Отворете файл, докато този раздел е на фокус</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Прехвърляне на този изглед към раздела „{0}“.\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Текуща тема\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Използване на лентите за превъртане от темата\",\n    \"FONT_SIZE\"                            : \"Размер на шрифта\",\n    \"FONT_FAMILY\"                          : \"Семейство на шрифта\",\n    \"THEMES_SETTINGS\"                      : \"Настройки на темите\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Ново правило\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Инсталиране\",\n    \"UPDATE\"                               : \"Обновяване\",\n    \"REMOVE\"                               : \"Премахване\",\n    \"DISABLE\"                              : \"Изключване\",\n    \"ENABLE\"                               : \"Включване\",\n    \"OVERWRITE\"                            : \"Презаписване\",\n    \"CANT_REMOVE_DEV\"                      : \"Разширенията в папката „dev“ трябва да бъдат изтрити ръчно.\",\n    \"CANT_UPDATE\"                          : \"Обновлението не е съвместимо с това издание на {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Разширенията в папката „dev“ не могат да бъдат обновени автоматично.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Инсталиране на разширение\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Обновяване на разширение\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Адрес на разширението\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Адресът на архивния файл на разширението или хранилището му в GitHub\",\n    \"INSTALLING_FROM\"                      : \"Инсталиране на разширение от {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Инсталирането беше успешно!\",\n    \"INSTALL_FAILED\"                       : \"Инсталирането се провали.\",\n    \"CANCELING_INSTALL\"                    : \"Отказване\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Отказването на инсталирането отнема много време. Може да е възникнала вътрешна грешка.\",\n    \"INSTALL_CANCELED\"                     : \"Инсталирането беше отказано.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Преглед на пълното описание\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Преглед на съкратеното описание\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Сваленото съдържание не е правилен архивен файл във формата „zip“.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Файлът „package.json“ не е правилно форматиран (грешката е: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Файлът „package.json“ не указва името на пакета.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} не е правилно име на пакет.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Файлът „package.json“ не указва версията на пакета.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Версията на пакета ({0}) е грешна.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Низът за съвместимост ({0}) с {APP_NAME} е грешен.\",\n    \"DISALLOWED_WORDS\"                     : \"Думите ({1}) не са позволени в полето {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Разширението не е съвместимо с това издание на {APP_NAME}. То е инсталирано във Вашата папка с изключени разширения.\",\n    \"MISSING_MAIN\"                         : \"В пакета няма файл „main.js“.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Инсталирането на този пакет ще презапише друго, вече инсталирано разширение. Искате ли да презапишете старото разширение?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Този пакет има същата версия като вече инсталирания. Искате ли да презапишете текущата инсталация?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Този пакет има версия {0}, която е по-стара от текущо инсталираната ({1}). Искате ли да презапишете текущата инсталация?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Вътрешна грешка: идентификатора на свалянето вече е зает.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Неуспешна връзка със сървъра.\",\n    \"BAD_HTTP_STATUS\"                      : \"Файлът не е открит на сървъра (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Неуспешно запазване на свалянето като временен файл.\",\n    \"ERROR_LOADING\"                        : \"Това разширение имаше грешка при стартирането си.\",\n    \"MALFORMED_URL\"                        : \"Адресът е грешен. Моля, проверете дали сте го въвели правилно.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"Адресът трябва да бъде от вида „http“ или „https“.\",\n    \"UNKNOWN_ERROR\"                        : \"Неизвестна вътрешна грешка.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Управител на разширенията\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Неуспешен достъп до регистъра на разширенията. Моля, опитайте отново по-късно.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Завлачете .zip тук или\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Пуснете .zip за инсталиране\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Инсталирането/обновяването беше прекъснато поради следните грешки:\",\n    \"INSTALL_FROM_URL\"                     : \"Инсталирайте от адрес\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Проверка\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Автор\",\n    \"EXTENSION_DATE\"                       : \"Дата\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Това разширение изисква по-ново издание на {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Това разширение в момента работи само с по-стари издания на {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Версия {0} на това разширение изисква по-ново издание на {APP_NAME}. Но можете да инсталирате по-старата версия {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Версия {0} на това разширение работи само с по-стари издания на {APP_NAME}. Но можете да инсталирате по-старата версия {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Няма описание\",\n    \"EXTENSION_MORE_INFO\"                  : \"Още\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Грешка на разширението\",\n    \"EXTENSION_KEYWORDS\"                   : \"Ключови думи\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Разширението е преведено на {0} езика, включително Вашия.\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Разширението е преведено на {0} езика\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Това разширение е преведено на следните езици: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Инсталирано\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Обновлението за това разширение е било свалено и ще бъде инсталирано след като {APP_NAME} се презареди.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Търсене\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Още\",\n    \"BROWSE_EXTENSIONS\"                    : \"Преглед на разширенията\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Премахване на разширението\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Неуспешно премахване на едно или повече разширения: {0}. {APP_NAME} все пак ще се презареди.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Обновяване на разширението\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Неуспешно обновяване на едно или повече разширения: {0}. {APP_NAME} все пак ще се презареди.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Изключване на разширението\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Неуспешно изключване на едно или повече разширения: {0}. {APP_NAME} все пак ще се презареди.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Отбелязано за премахване\",\n    \"UNDO_REMOVE\"                          : \"Отмяна\",\n    \"MARKED_FOR_UPDATE\"                    : \"Отбелязано за обновяване\",\n    \"UNDO_UPDATE\"                          : \"Отмяна\",\n    \"MARKED_FOR_DISABLING\"                 : \"Отбелязано за изключване\",\n    \"UNDO_DISABLE\"                         : \"Отмяна\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Промяна на разширенията\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"За да обновите, премахнете или изключите отбелязаните разширения, {APP_NAME} ще трябва да се презареди. Ако имате незапазени промени, ще Ви бъде предложено да ги запазите.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Премахване на разширенията и презареждане\",\n    \"CHANGE_AND_RELOAD\"                    : \"Промяна на разширенията и презареждане\",\n    \"UPDATE_AND_RELOAD\"                    : \"Обновяване на разширенията и презареждане\",\n    \"DISABLE_AND_RELOAD\"                   : \"Изключване на разширенията и презареждане\",\n    \"PROCESSING_EXTENSIONS\"                : \"Обработване на промените по разширенията\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Разширението {0} не може да бъде премахнато, тъй като не е инсталирано.\",\n    \"NO_EXTENSIONS\"                        : \"Все още няма инсталирани разширения.<br>Изберете раздела с наличните разширения отгоре, за да започнете.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Няма разширения, отговарящи на търсенето Ви.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"ЗАБЕЛЕЖКА: Тези разширения може да са предоставени от различни автори, които не са свързани с {APP_NAME}. Разширенията не преминават никакви проверки и имат пълен достъп до местните Ви файлове. Внимавайте, когато инсталирате разширения от неизвестни източници.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Инсталирани\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Налични\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Теми\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Обновления\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Няма съвпадения.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Всички съвпадения бяха свити. Разширете файловете, изредени вдясно, за да видите съвпаденията.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Няма съществуващи правила за CSS, които да отговарят на избора Ви.<br> Натиснете „Ново правило“, за да създадете такова.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"В проекта Ви няма стилови файлове.<br>Създайте поне един, за да добавите правила за CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"най-голямо\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"пиксели\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Разработка\",\n    \"ERRORS\"                                    : \"Грешки\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Показване на инструментите за разработчици\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Презареждане с разширения\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Презареждане без разширения\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Нов прозорец на {APP_NAME}\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Инсталиране на пряк път за командния ред\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Смяна на езика\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Пускане на тестовете\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Показване на данните за производителността\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Включване на отстраняването на грешки за Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Извеждане на състоянието на Node в конзолата\",\n    \"CMD_RESTART_NODE\"                          : \"Рестартиране на Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Показване на грешките в лентата на състоянието\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Отваряне на изходния код на {APP_NAME}\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"Пряк път към {APP_NAME} за командния ред\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Възникна грешка при инсталирането на прекия път за командния ред. Моля, прегледайте <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>тези съвети за отстраняване на проблемите</a>.<br/><br/>Причина: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Неуспешно премахване на съществуващата символна връзка <code>/usr/local/bin/brackets</code> .\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Неуспешно създаване на папката <code>/usr/local/bin</code> .\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Неуспешно създаване на символната връзка <code>/usr/local/bin/brackets</code> .\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Вътрешна грешка.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Тази ОС не поддържа преки пътища за команден ред.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Готово! Вече можете да пускате {APP_NAME} лесно от командния ред чрез: <code>brackets файл.txt</code> за отваряне на файл или <code>brackets папка</code> за промяна на проекта. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Научете повече</a> относно използването на {APP_NAME} от командния ред.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Смяна на езика\",\n    \"LANGUAGE_MESSAGE\"                          : \"Език:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Презареждане на {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Отказ\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"По подразбиране\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Предпочитания за здравния доклад\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"Здравен доклад на {APP_NAME}\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Искам да споделям информация за това как използвам {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"С цел подобряване на {APP_NAME}, ни периодично изпращаме ограничено количество, <strong>анонимни</strong> данни до Adobe относно това как използвате {APP_NAME}. Тази информация ни помога да преценим кои функционалности са най-важни, да откриваме проблеми и забелязваме неудобства при ползването.<br><br>Можете да видите своите данни или да изберете да не ги споделяте с нас, като изберете <strong>Помощ > Здравен доклад</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Нучете повече относно здравния доклад на {APP_NAME}</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"Здравен доклад на {APP_NAME}\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>С цел подобряване на {APP_NAME}, ни периодично изпращаме ограничено количество, <strong>анонимни</strong> данни до Adobe относно това как използвате {APP_NAME}. Тази информация ни помога да преценим кои функционалности са най-важни, да откриваме проблеми и забелязваме неудобства при ползването. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Нучете повече относно здравния доклад на {APP_NAME}</a> и как той е в полза на общността на {APP_NAME}, както и защитава личните Ви данни.</p><p>По-долу виждате преглед на данните, които ще бъдат изпратени в следващия Ви здравен доклад, <em>ако</em> той е включен.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Време\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Напредък\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Преместване на избраната точка<br><kbd class='text'>Shift</kbd> Преместване с десет единици<br><kbd class='text'>Tab</kbd> Превключване на точката\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Увеличаване или намаляване на стъпките<br><kbd>←</kbd><kbd>→</kbd> „Начало“ или „Край“\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Старата стойност <code>{0}</code> не е правилна, така че показаната функция беше променена на <code>{1}</code>. Документът ще бъде обновен при първата редакция.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Текущ цвят\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Оригинален цвят\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Формат ЧЗСа\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Шестнадесетичен формат\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Формат тон-насищане-осветеност\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (използван {1} път)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (използван {1} пъти)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Към определението\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Показване на подсказката за параметрите\",\n    \"NO_ARGUMENTS\"                              : \"<няма параметри>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Проблем с файл с код на JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} имаше проблем при обработката на <span class='dialog-filename'>{0}</span>.<br><br>Този файл няма повече да бъде проучван за подсказки за кода, преминаване към определения или бързо редактиране. За да включите този файл отново, отворете файла <code>.brackets.json</code> в проекта си и редактирайте секцията <code>jscodehints.detectedExclusions</code>.<br><br>Най-вероятно проблемът е в {APP_NAME}. Ако можете да изпратите този файл, моля <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>докладвайте проблема</a> с връзка към файла.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Бърз преглед при посочване\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Скорошни проекти\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Прочетете повече\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Сгъване на всичко\",\n    \"EXPAND_ALL\"                    : \"Разгъване на всичко\",\n    \"COLLAPSE_CURRENT\"              : \"Сгъване на текущото\",\n    \"EXPAND_CURRENT\"                : \"Разгъване на текущото\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"Задайте true за автоматично затваряне на всички видове скоби\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"Задайте false за премахване на възможността за „Затваряне на всички отгоре“ от контекстното меню на работните файлове\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"Задайте false за премахване на възможността за „Затваряне на всички отдолу“ от контекстното меню на работните файлове\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"Задайте false за премахване на възможността за „Затваряне на останалите“ от контекстното меню на работните файлове\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Настройки за автоматично затваряне на елементи\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Списък от елементи, които не трябва да бъдат затваряни автоматично\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Затваряне при въвеждане на „>“ от отварящия елемент\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Затваряне при въвеждане на „/“ от затварящия елемент\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Списък от елементи, които трябва да имат празен ред след отваряне\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"Задайте true за автоматично създаване на позиции за сгъване при промяна не нивото на отстъпа\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"Задайте true за включване на сгъването на кода\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"Задайте true за показване на триъгълничетата за сгъване само когато поставите курсора над лентата им\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Ограничение за това върху колко нива се прилага операцията „Сгъване на всичко“\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Минимален брой редове, преди да се появи иконка за сгъване\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"Задайте true за запомняне на сгънатите части при затваряне и повторно отваряне на файлове и проекти\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"Задайте true за включване на сгъването на избрания текст в редактора\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Включване/изключване на подсказките за атрибути в HTML\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Включване/изключване на подсказките за атрибути в CSS/LESS/SCSS\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Включване/изключване на подсказките за код на JavaScript\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Включване/изключване на подсказките за подробности относно типовете данни в код на JavaScript\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Включване/изключване на подсказките за предпочитанията\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Включване/изключване на подсказките за специални знаци в HTML\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Включване/изключване на подсказките за код на векторни изображения (SVG)\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Включване/изключване на подсказките за елементи в HTML\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Включване/изключване на подсказките за адреси в HTML и CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Включване/изключване на фукционалността за влачене и пускане\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Включване на следенето на здравните данни\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Включване на автоматичното осветяване на съвпадащите текстове в документа\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Осветяване на всички текстове, отговарящи на елемента/символа, който в момента се намира под курсора (без нужда от избиране)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Осветяване само когато избраното е завършен елемент/символ\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"Задайте true за използване на текущо избраната подсказка при натискане на клавиша Tab\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"Задайте true за изключване на автоматичните подсказки в код на JavaScript при въвеждане на точка (.)\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Обект с настройките по подразбиране за JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"Задайте true за разрешаване на изразите за присвояване\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"Задайте true за разрешаване на побитовите оператори\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"Задайте true , ако глобалните променливи на стандартния браузър трябва да бъдат преопределени\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"Задайте true за разрешаване на диалектите на „Google Closure“\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"Задайте true за разрешаване на ключовата дума „continue“\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"Задайте true , ако глобалните променливи на CouchDB трябва да бъдат преопределени\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"Задайте true за разрешаване на изразите, свързани с отстраняването на грешки\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"Задайте true , ако глобалните променливи на браузъра, полезни за отстраняването на грешки, трябва да бъдат преопределени\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"Задайте true за разрешаване на == и !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"Задайте true , ако глобалните променливи на ES6 трябва да бъдат преопределени\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"Задайте true за разрешаване на „eval“\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"Задайте true за разрешаване на нефилтриране изрази от вида „for ... in“\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Задаване на конкретна ширина на табулатора\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Максимален брой докладвани грешки\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Максимален брой знаци на ред\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"Задайте true за разрешаване на конструктори, които започват с малка буква\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"Задайте true , ако голбалните променливи на Node.js трябва да бъдат преопределени\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"Задайте true за разрешаване на висяща долна черта в идентификаторите\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"Задайте true за спиране при първа грешка\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"Задайте true за разрешаване на ++ и --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"Задайте true за разрешаване на . и [^...]. в регулярни изрази\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"Задайте true , ако глобалните променливи на Rhino трябва да бъдат преопределени\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"Задайте true за разрешаване на липсващи изявления „use strict“\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"Задайте true за разрешаване на използването на блокиращи методи („...Sync“).\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"Задайте true за разрешаване на неефективното извикване на методи/данни\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"Задайте true за разрешаване на коментарите „TODO“\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"Задайте true за разрешаване на неизползваните параметри\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"Задайте true за разрешаване на повече от 1 използване на „var“ във функция\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"Задайте true за пренебрегване на правилата за празните места\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Настройки според езика\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Допълнителни съответствия между файлово разширение и име на език\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Допълнителни съответствия между файлово име и име на език\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"Задайте true за включване на проучването на кода\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Време в милисекунди, след което асинхронните системи за проверка ще бъдат спирани\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Списък от системи за проверка, които да бъдат изпълнявани първо\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"Задайте true за включване на експерименталния преглед на живо\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"Задайте true за изпълнение само на доставчиците, определени в linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Максимален брой подсказки за кода, които могат да бъдат показани наведнъж\",\n    \"DESCRIPTION_PATH\"                               : \"Настройки за пътищата\",\n    \"DESCRIPTION_PROXY\"                              : \"Адресът на прокси сървъра, използван за инсталиране на разширения\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"Задайте true за включване на превъртането след края на документа\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"Задайте false за изключване на всички подсказки\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Курсорът продължава да мига дори и когато има избран текст\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"Задайте true за показване на номерата на редовете в ивица отляво на кода\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Автоматичен отстъп при създаване на нов блок\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"Задайте false за изключване на леките табулатори\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"Задайте true за показване на папките най-отгоре в дървото на файловете\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Брой интервали, използвани при остъп чрез интервали\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Номер на порт, който вграденият сървър да използва при преглед на живо\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"Задайте true за осветяване на цвета на фона на ред, на който се намира курсорът в момента\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Ширина на табулатора в брой интервали\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"Задайте true за използване на табулатори, вместо интервали\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"Задайте true за използване на главни букви в шестнадесетичните цветове, създадени от редактора за цветове в текста\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Привидно пресяне на редовете, чиято дължина излиза извън видимата област на редактора\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Списък от файлове, за които се е установило, че създават проблеми на Tern\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Време, след което Tern ще спре да опитва да проучва файловете\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"Задайте true за показване на грешки в лентата на състоянието\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"Задайте true за включване на бързия преглед\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"Задайте true за показване на изображения за адресите с лепсващи разширения\",\n    \"DESCRIPTION_THEME\"                              : \"Изберете тема за {APP_NAME}\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"Задайте true за позволяване на персонализирани ленти за превъртане\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"Задайте true за скриване на панела за проверки\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Промяна на семейството на шрифта\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Промяна на размера на шрифта, например 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"Задайте true за включване на търсенето по възли\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"Задайте true за включване на моменталното търсене\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Само за Мак: използвайте „subpixel-antialiased“, за да включите подпикселното заглаждане или „antialiased“ за черно-бяло заглаждане\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"Задайте false за изключване на отварянето на файла с настройките в разделен режим\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"Задайте false за отваряне на файла с потребителските настройки в левия/горния раздел\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"Задайте true за скриване на разделите след като последният файл от раздела бъде затворен чрез бутона за затваряне в заглавната лента на раздела\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Превключване на това кога да бъдат показвани бутоните за затваряне и прехвърляне в друг раздел в заглавната лента на раздела\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Този файл е само за четене и съдържа настройките,\\n * поддържани от {APP_NAME}.\\n * Използвайте го за справка, когато променяте своите настройки в\\n * файла „brackets.json“, отворен в другия рездел.\\n * За повече информация относно използването на настройките в\\n * {APP_NAME}, прегледайте страницата https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"По подразбиране\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"Задайте true за включване на режима, в който се вижда само кода, а всички останали части на потребителския интерфейс на {APP_NAME} са скрити\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"Задайте true за включване на отстъпа на коментарите за ред\"\n});\n\n/* Last translated for a505026d40a4eb0bffc196eda30557c0e6b021bc */"
  },
  {
    "path": "src/nls/bg/urls.js",
    "content": "/*\n * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"bg/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.bg\"\n});\n"
  },
  {
    "path": "src/nls/cs/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Chyby\n     */\n\n    // Řetězce obecných chyb souboru\n    \"GENERIC_ERROR\"                     : \"(chyba {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Soubor nenalezen.\",\n    \"NOT_READABLE_ERR\"                  : \"Soubor nelze číst.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Soubor větší než {0} MB nemůže být otevřen v aplikaci {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Cílová složka nemůže být změněna.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Oprávnění neumožní provádět změny.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Soubor byl změněn mimo aplikaci {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} v této chvíli podporuje pouze UTF-8 textové soubory.\",\n    \"FILE_EXISTS_ERR\"                   : \"Soubor již existuje.\",\n    \"FILE\"                              : \"souboru\",\n    \"FILE_TITLE\"                        : \"Soubor\",\n    \"DIRECTORY\"                         : \"složky\",\n    \"DIRECTORY_TITLE\"                   : \"Složka\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Názvy složek\",\n    \"FILENAMES_LEDE\"                    : \"Názvy souborů\",\n    \"FILENAME\"                          : \"název souboru\",\n    \"DIRECTORY_NAME\"                    : \"název složky\",\n\n    // Řetězce chyb projektu\n    \"ERROR_LOADING_PROJECT\"             : \"Chyba při otevírání projektu\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Došlo k chybě při zobrazování dialogu Otevřít soubor. (chyba {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Došlo k chybě při načítání adresáře <span class='dialog-filename'>{0}</span>. (chyba {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Došlo k chybě při načítání obsahu složky <span class='dialog-filename'>{0}</span>. (chyba {1})\",\n\n    // Řetězce chyb otevírání/ukládání souboru\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Chyba při otevírání souboru\",\n    \"ERROR_OPENING_FILE\"                : \"Došlo k chybě při otevírání souboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Došlo k chybě při otevírání následujících souborů:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Chyba při načítání změn z disku\",\n    \"ERROR_RELOADING_FILE\"              : \"Došlo k chybě při načítání souboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Chyba při ukládání souboru\",\n    \"ERROR_SAVING_FILE\"                 : \"Došlo k chybě při ukládání souboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Chyba při přejmenování {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Došlo k chybě při přejmenování {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Chyba při mazání {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Došlo k chybě při mazání {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Špatný {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} nemohou obsahovat rezervovaná slova, končit tečkami (.) nebo obsahovat znaky: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Soubor nebo složka se jménem <span class='dialog-filename'>{0}</span> již existuje.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Chyba při vytváření {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Došlo k chybě při vytváření {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Nelze otevřít složku ve chvíli, kdy se otevírají jiné soubory.\",\n\n    // Řetězce chyb nastavení klávesových zkratek\n    \"ERROR_KEYMAP_TITLE\"                : \"Chyba při čtení uživatelských klávesových zkratek\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Soubor s nastavením klávesových zkratek není platný soubor typu JSON. Soubor bude otevřen, abyste mohli opravit formát.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Váš soubor s klávesovými zkratkami není platný UTF-8 soubor a nemůže být otevřen\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Nemůžete změnit klávesové zkratky následujícím příkazům: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Nemůžete změnit tyto klávesové zkratky: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Vytváříte více klávesových zkratek pro tyto příkazy: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Tyto příkazy mají stejnou klávesovou zkratku: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Tyto klávesové zkratky jsou neplatné: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Vytváříte klávesovou zkratku pro neexistující příkaz: {0}\",\n\n    // Řetězce chyb nastavení aplikace\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Chyba při čtení nastavení\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Soubor s nastavením není platný soubor typu JSON. Soubor bude otevřen, abyste mohli opravit formát. Pro uložení změn budete muset restartovat aplikaci {APP_NAME}.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Soubor s preferencemi vašeho projektu neodpovídá validnímu JSON formátu. Tento soubor bude otevřen, abyste mohl formát opravit. K provedení změn bude nutné znovu načíst projekt.\",\n\n    // Řetězce chyb aplikace\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ouha! {APP_NAME} ještě neběží v prohlížeči.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} je vytvořen v HTML, ale nyní pracuje jako desktopová aplikace, takže ji můžete použít pro úpravu lokálních souborů. Prosím, použijte shell aplikace v repozitáři <b>github.com/adobe/brackets-shell</b> pro spuštění {APP_NAME}.\",\n\n    // Řetězce chyb indexování souboru\n    \"ERROR_MAX_FILES_TITLE\"             : \"Chyba při indexování souborů\",\n    \"ERROR_MAX_FILES\"                   : \"Tento projekt obsahuje více než 30.000 souborů. Funkce zpracovávající více souborů mohou být zablokované nebo se mohou chovat jako kdyby byl projekt prázdný. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Čtěte více o práci s obřími projekty</a>.\",\n\n    // Řetězce chyb živého náhledu\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Chyba při spouštění prohlížeče\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Prohlížeč Google Chrome nebyl nalezen. Přesvědčte se, že je nainstalován\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Došlo k chybě při spouštění prohlížeče. (chyba {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Živý náhled - chyba\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Připojování k prohlížeči\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Aby se mohl živý náhled připojit, je třeba restartovat Chrome s povolenou možností vzdálené ladění.<br /><br />Chcete restartovat Chrome a povolit vzdálené ladění?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Nelze načíst stránku s živým náhledem\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Otevřete HTML soubor pro zobrazení v živém náhledu.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Pro spuštění živého náhledu se vzdáleným souborem, musíte specifikovat URL pro tento projekt.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Chyba při spouštění HTTP serveru pro soubory živého náhledu. Prosím, zkuste to znovu.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Vítejte v živém náhledu!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Živý náhled připojí {APP_NAME} k vašemu prohlížeči. Spustí náhled HTML souboru, který se aktualizuje pokaždé, kdy editujete svůj kód.<br /><br />V této verzi {APP_NAME}, živý náhled funguje pouze v <strong>Google Chrome</strong> a aktualizuje změny v <strong>CSS souborech</strong>. Změny v HTML nebo JavaScript souborech jsou automaticky načteny, když soubor uložíte.<br /><br />(Tato zpráva se zobrazí pouze jednou.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Pro více informací navštivte stránku <a href='{0}' title='{0}'>řešení problémů s připojením v Živém náhledu</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Živý náhled\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Živý náhled: Připojování\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Živý náhled: Spouštění\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Zrušit živý náhled\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Živý náhled (uložte soubor k obnovení)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Živý náhled (neaktualizováno kvůli chybě v syntaxi)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Živý náhled byl zrušen, protože byly otevřeny vývojářské nástroje prohlížeče\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Živý náhled byl zrušen, protože dokument byl zavřen v prohlížeči\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Živý náhled byl zrušen, protože prohlížeč přešel na stránku, která není součástí projektu\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Živý náhled byl zrušen z neznámého důvodu ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Uložit změny\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Chcete uložit změny v souboru <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Chcete uložit změny v následujících souborech?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Externí změny\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Potvrdit smazání\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Opravdu chcete smazat složku <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Soubor smazán\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> byl změněn mimo {APP_NAME}.<br /><br />Chcete uložit soubor a přepsat tyto změny?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> byl změněn mimo {APP_NAME}, ale existují také neuložené změny v {APP_NAME}.<br /><br />Kterou verzi chcete zachovat?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> byl smazán mimo {APP_NAME}, ale existují neuložené změny v {APP_NAME}.<br /><br />Chcete vaše změny zachovat?\",\n\n    // Obecná označení dialogů/tlačítek\n    \"DONE\"                              : \"Hotovo\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Zrušit\",\n    \"DONT_SAVE\"                         : \"Neukládat\",\n    \"SAVE\"                              : \"Uložit\",\n    \"SAVE_AS\"                           : \"Uložit jako\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Přepsat\",\n    \"DELETE\"                            : \"Smazat\",\n    \"BUTTON_YES\"                        : \"Ano\",\n    \"BUTTON_NO\"                         : \"Ne\",\n\n    // Najít, Nahradit, Najít v souborech\n    \"FIND_MATCH_INDEX\"                  : \"{0} z {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Žádné výsledky\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Najít\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Nahradit s\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Vše\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Nahradit\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Nahradit\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Další shoda\",\n    \"BUTTON_PREV_HINT\"                  : \"Předchozí shoda\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Rozlišovat velká a malá písmena\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regulární výraz\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Nahradit bez možnosti vrátit změny\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Protože musí být změněno více než {0} souborů, {APP_NAME} změní neotevřené soubory na disku.<br />Nebude možné vrátit změny v těchto souborech.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Nahradit bez možnosti vrátit změny\",\n\n    \"OPEN_FILE\"                         : \"Otevřít soubor\",\n    \"SAVE_FILE_AS\"                      : \"Uložit soubor\",\n    \"CHOOSE_FOLDER\"                     : \"Vybrat složku\",\n\n    \"RELEASE_NOTES\"                     : \"Poznámky k verzi\",\n    \"NO_UPDATE_TITLE\"                   : \"Vše je aktuální!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Verze {APP_NAME} je aktuální.\",\n\n    // Najít a nahradit\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Nahradit\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"s\",\n    \"FIND_TITLE_LABEL\"                  : \"Nalezeno\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} v {3}\",\n\n    // Najít v souborech\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"v <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"v projektu\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtr vyloučil všechny soubory {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"souboru\",\n    \"FIND_IN_FILES_FILES\"               : \"souborech\",\n    \"FIND_IN_FILES_MATCH\"               : \"výsledek\",\n    \"FIND_IN_FILES_MATCHES\"             : \"výsledků\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"více než \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"Soubor <span class='dialog-filename'>{0}</span> ve složce <span class='dialog-path'>{1}</span>\",\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd klik pro rozbalení/sbalení všeho\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indexování pro okamžité vyhledávání\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Nahradit chyby\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Následující soubory nebyly změněny, protože se změnily po hledání nebo do nich nelze zapisovat.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Chyba při získávání informací o aktualizaci\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Nelze získat aktualizace. Ujistěte se, že máte připojení k internetu a zkuste to znovu.\",\n\n    // Filtry vyloučení souborů\n    \"NEW_FILE_FILTER\"                   : \"Nová řada vyloučených souborů\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Nevylučovat soubory\",\n    \"NO_FILE_FILTER\"                    : \"Vyloučit soubory\\u2026\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Vyloučit {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Upravit\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Upravit filtr\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Vyloučit soubory a složky, které obsahují jakýkoliv z následujících řetězců / podřetězců nebo <a href='{0}' title='{0}'>vzorků</a>. Vložte každý řetězec na nový řádek.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Pojmenujte řadu vyloučených souborů (nepovinné)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"a {0} více\",\n    \"FILTER_COUNTING_FILES\"             : \"Počítání souborů\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Povolit {0} z {1} souborů {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Povolit všechny {0} soubory {1}\",\n\n    // Rychlá úprava\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Rychlá úprava není dostupná pro aktuální pozici kurzoru\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Rychlá úprava CSS: umístěte kurzor do jména třídy\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Rychlá úprava CSS: nekompletní class atribut\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Rychlá úprava CSS: nekompletní id atribut\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Rychlá úprava CSS: umístěte kurzor do elementu, třídy nebo id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Rychlá úprava CSS časování: neplatná syntaxe\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Rychlá úprava JS: umístěte kurzor do jména funkce\",\n\n    // Rychlá dokumentace\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Rychlá dokumentace není dostupná pro aktuální pozici kurzoru\",\n\n    /**\n     * Správce projektu\n     */\n    \"PROJECT_LOADING\"   : \"Načítání\\u2026\",\n    \"UNTITLED\"          : \"Nový\",\n    \"WORKING_FILES\"     : \"Pracovní soubory\",\n\n    /**\n     * Správce rozložení\n     */\n    \"TOP\"               : \"Nahoře\",\n    \"BOTTOM\"            : \"Dole\",\n    \"LEFT\"              : \"Vlevo\",\n    \"RIGHT\"             : \"Vpravo\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Bez rozdělení\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Vertikální rozdělení\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Horizontální rozdělení\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Rozdělit editor horizontálně nebo vertikálně\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Nastavit pracovní plochu\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Již otevřen\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Soubor je již otevřen v jiném okně. {APP_NAME} bude brzy podporovat otevírání stejného souboru ve více oknech. Do té doby bude soubor zobrazen v již otevřeném okně.<br /><br />(Tuto zprávu uvidíte pouze jednou.)\",\n\n    /**\n     * Názvy kláves\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"Mezerník\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * Řetězce stavového řádku\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Řádek {0}, Sloupec {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Vybrán {0} sloupec\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Vybrány {0} sloupce\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Vybrán {0} řádek\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Vybrány {0} řádky\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} Vybráno\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Přepnout odsazení na mezery\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Přepnout odsazení na tabulátory\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Změnit počet mezer použitých pro odsazení\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Změnit šířku tabulátoru\",\n    \"STATUSBAR_SPACES\"                      : \"Mezery:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Velikost tabulátoru:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"Řádek: {0}\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"Řádky: {0}\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Doplňky zakázány\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Klikněte pro přepnutí kurzoru mezi módem Insert (INS) a Overwrite (OVR)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Klikněte pro změnu typu souboru\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Klikněte pro zapnutí panelu zpráv.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(výchozí)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Nastavit jako výchozí pro .{0} soubory\",\n\n    // CodeInspection: chyby/varování\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} chyb\",\n    \"SINGLE_ERROR\"                          : \"1 {0} chyba\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} chyby\",\n    \"NO_ERRORS\"                             : \"Žádné {0} chyby - dobrá práce!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Žádné chyby nenalezeny - dobrá práce!\",\n    \"LINT_DISABLED\"                         : \"Lintování je vypnuto\",\n    \"NO_LINT_AVAILABLE\"                     : \"Žádný linter není dostupný pro {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Nic k lintování\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} - vypršel časový limit po uplynutí {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} byl(a) ukončen(a) s chybou: {1}\",\n\n    /**\n     * Názvy příkazů\n     */\n\n    // Příkazy menu Soubor\n    \"FILE_MENU\"                           : \"Soubor\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nový\",\n    \"CMD_FILE_NEW\"                        : \"Nový soubor\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nová složka\",\n    \"CMD_FILE_OPEN\"                       : \"Otevřít\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Přidat k pracovní sadě\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Otevřít opuštěné soubory\",\n    \"CMD_OPEN_FOLDER\"                     : \"Otevřít složku\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Zavřít\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Zavřít vše\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Zavřít seznam\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Zavřít ostatní\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Zavřít ostatní výše\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Zavřít ostatní níže\",\n    \"CMD_FILE_SAVE\"                       : \"Uložit\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Uložit vše\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Uložit jako\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Živý náhled\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Experimentální živý náhled\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Vynutit obnovení živého náhledu\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Nastavení projektu\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Přejmenovat\",\n    \"CMD_FILE_DELETE\"                     : \"Smazat\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instalovat doplňky\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Správce doplňků\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Obnovit\",\n    \"CMD_QUIT\"                            : \"Konec\",\n    // Použito v souborovém menu Windows\n    \"CMD_EXIT\"                            : \"Konec\",\n\n    // Příkazy menu Úpravy\n    \"EDIT_MENU\"                           : \"Úpravy\",\n    \"CMD_UNDO\"                            : \"Zpět\",\n    \"CMD_REDO\"                            : \"Znovu\",\n    \"CMD_CUT\"                             : \"Vyjmout\",\n    \"CMD_COPY\"                            : \"Kopírovat\",\n    \"CMD_PASTE\"                           : \"Vložit\",\n    \"CMD_SELECT_ALL\"                      : \"Vybrat vše\",\n    \"CMD_SELECT_LINE\"                     : \"Vybrat řádek\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Rozdělit výběr na řádky\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Přidat kurzor na další řádek\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Přidat kurzor na předcházející řádek\",\n    \"CMD_INDENT\"                          : \"Odsadit\",\n    \"CMD_UNINDENT\"                        : \"Vrátit odsazení\",\n    \"CMD_DUPLICATE\"                       : \"Duplikovat\",\n    \"CMD_DELETE_LINES\"                    : \"Smazat řádek\",\n    \"CMD_COMMENT\"                         : \"Řádkový komentář\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Blokový komentář\",\n    \"CMD_LINE_UP\"                         : \"Posunout řádek nahoru\",\n    \"CMD_LINE_DOWN\"                       : \"Posunout řádek dolů\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"O řádek výše\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"O řádek níže\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Uzavírat závorky\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Zobrazit nápovědy kódu\",\n\n    // Příkazy menu Najít\n    \"FIND_MENU\"                           : \"Najít\",\n    \"CMD_FIND\"                            : \"Najít\",\n    \"CMD_FIND_NEXT\"                       : \"Najít další\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Najít předchozí\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Najít vše a vybrat\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Přidat další shodu do výběru\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Přeskočit a přidat další shodu do výběru\",\n    \"CMD_FIND_IN_FILES\"                   : \"Najít v souborech\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Najít v\\u2026\",\n    \"CMD_REPLACE\"                         : \"Nahradit\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Nahradit v souborech\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Nahradit v\\u2026\",\n\n    // Příkazy menu Zobrazit\n    \"VIEW_MENU\"                           : \"Zobrazit\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Skrýt boční menu\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Zobrazit boční menu\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Zobrazit/skrýt boční menu\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Zobrazit/skrýt panely\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Žádné rozptylování\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Zvětšit velikost písma\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Zmenšit velikost písma\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Obnovit velikost písma\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Posunout o řádek nahoru\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Posunout o řádek dolů\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Čísla řádků\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Zvýraznit aktivní řádek\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Zalomit řádky\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Živé zvýraznění\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Lintovat soubory při uložení\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Řadit podle data přidání\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Řadit podle jména\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Řadit podle typu\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatické řazení\",\n    \"CMD_THEMES\"                          : \"Motivy\\u2026\",\n\n    // Příkazy menu Navigace\n    \"NAVIGATE_MENU\"                       : \"Navigace\",\n    \"CMD_QUICK_OPEN\"                      : \"Rychle otevřít\",\n    \"CMD_GOTO_LINE\"                       : \"Přejít na řádek\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Přejít na definici\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Přejít na první chybu/varování\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Rychlá úprava\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Rychlá dokumentace\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Předchozí shoda\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Další shoda\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Nový předpis\",\n    \"CMD_NEXT_DOC\"                        : \"Další dokument\",\n    \"CMD_PREV_DOC\"                        : \"Předchozí dokument\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Další dokument v seznamu\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Předchozí dokument v seznamu\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Zobrazit stromovou strukturu\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Zobrazit v průzkumníkovi\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Zobrazit ve vyhledávači\",\n    \"CMD_SHOW_IN_OS\"                      : \"Zobrazit v OS\",\n\n    // Příkazy menu Nápověda\n    \"HELP_MENU\"                           : \"Nápověda\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Zkontrolovat aktualizace\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Jak používat {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} Podpora\",\n    \"CMD_SUGGEST\"                         : \"Navrhněte funkci\",\n    \"CMD_RELEASE_NOTES\"                   : \"Poznámky k verzi\",\n    \"CMD_GET_INVOLVED\"                    : \"Zapojte se\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Zobrazit složku s doplňky\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Hlášení o zdraví\",\n    \"CMD_HOMEPAGE\"                        : \"Domovská stránka {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} na Twitteru\",\n    \"CMD_ABOUT\"                           : \"O aplikaci {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Otevřít soubor s preferencemi\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Otevřít uživatelské klávesové zkratky\",\n\n    // Řetězce pro main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimentální sestavení\",\n    \"RELEASE_BUILD\"                        : \"sestavení\",\n    \"DEVELOPMENT_BUILD\"                    : \"vývojové sestavení\",\n    \"RELOAD_FROM_DISK\"                     : \"Načíst z disku\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Ponechat změny v editoru\",\n    \"CLOSE_DONT_SAVE\"                      : \"Zavřít (neukládat)\",\n    \"RELAUNCH_CHROME\"                      : \"Restartovat Chrome\",\n    \"ABOUT\"                                : \"O aplikaci\",\n    \"CLOSE\"                                : \"Zavřít\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Vydání {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"vytvořeno: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Oznámení, podmínky týkající se software třetích stran jsou umístěny na stránce <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> a začleněny prostřednictvím odkazu zde.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentace a zdrojový kód na stránce <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>.\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Vytvořeno s \\u2764 a pomocí JavaScriptu těmito lidmi:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Mnoho lidí (ale momentálně máme problém s načítáním dat).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs a MDN logo využívají licenci Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Je dostupná nová verze {APP_NAME}! Klikněte zde pro více informací.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Dostupná aktualizace\",\n    \"UPDATE_MESSAGE\"                       : \"Nová verze {APP_NAME} je dostupná. Seznam některých vylepšení:\",\n    \"GET_IT_NOW\"                           : \"Stáhnout!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Nastavení projektu: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL Živého náhledu\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"(nechte prázdné pro URL souboru)\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"{0} protokol není podporován živým náhledem &mdash; prosím, použijte http: nebo https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL nemůže obsahovat výrazy pro hledání jako \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL nemůže obsahovat znaky jako \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Zvláštní znaky jako '{0}' musí být zakódovány %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Neznámá chyba při zpracování URL\",\n\n    // Řetězce pro Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Otevřete soubor, zatímco tento panel je aktivní</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Přepnout toto zobrazení na panel {0}\",\n\n    // Řetězce pro themes-settings.html a themes-general.html\n    \"CURRENT_THEME\"                        : \"Aktuální motiv\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Použít posuvníky motivu\",\n    \"FONT_SIZE\"                            : \"Velikost písma\",\n    \"FONT_FAMILY\"                          : \"Rodina písma\",\n    \"THEMES_SETTINGS\"                      : \"Nastavení motivů\",\n\n    // Rychlá úprava CSS\n    \"BUTTON_NEW_RULE\"                      : \"Nový předpis\",\n\n    // Řetězce pro správce doplňků\n    \"INSTALL\"                              : \"Instalovat\",\n    \"UPDATE\"                               : \"Aktualizovat\",\n    \"REMOVE\"                               : \"Odstranit\",\n    \"DISABLE\"                              : \"Deaktivovat\",\n    \"ENABLE\"                               : \"Aktivovat\",\n    \"OVERWRITE\"                            : \"Přepsat\",\n    \"CANT_REMOVE_DEV\"                      : \"Doplněk ve složce \\\"dev\\\" musí být smazán manuálně.\",\n    \"CANT_UPDATE\"                          : \"Aktualizace není kompatibilní s touto verzí {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Doplňky ve složce \\\"dev\\\" nemohou být aktualizovány automaticky.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instalovat doplněk\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Aktualizovat doplněk\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL adresa doplňku\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL adresa zip archivu nebo GitHub repozitáře\",\n    \"INSTALLING_FROM\"                      : \"Instalace doplňku z {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalace byla úspěšná!\",\n    \"INSTALL_FAILED\"                       : \"Instalace se nezdařila.\",\n    \"CANCELING_INSTALL\"                    : \"Rušení instalace\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Rušení instalace trvá dlouho. Mohlo dojít k interní chybě.\",\n    \"INSTALL_CANCELED\"                     : \"Instalace zrušena.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Zobrazit úplný popis\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Zobrazit zkrácený popis\",\n    // Tyto musí odpovídat chybovým hlášením v ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Stažený soubor není platný zip soubor.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Package.json balíček není platný (chyba byla: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Package.json balíček nespecifikuje jméno souboru.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} je neplatné jméno balíčku.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Package.json balíček nespecifikuje verzi souboru.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Balíček verze ({0}) je neplatný.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Řetězec kompatibility {0} pro {APP_NAME} je neplatný.\",\n    \"DISALLOWED_WORDS\"                     : \"Slova {1} nejsou povolena v {0} poli.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Doplněk není kompatibilní s touto verzí {APP_NAME}. Naleznete jej ve složce disabled extensions.\",\n    \"MISSING_MAIN\"                         : \"Balíček neobsahuje soubor main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Instalace tohoto balíčku přepíše již nainstalovaný doplněk. Chcete přepsat starý doplněk?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Tento balíček je stejná verze jako ta, kterou již máte nainstalovanou. Chcete přepsat existující doplněk?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Tento balíček je verze {0}, která je starší než současně nainstalovaná verze ({1}). Chcete přepsat existující doplněk?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Interní chyba: ID stahování se již používá.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Nelze se připojit na server.\",\n    \"BAD_HTTP_STATUS\"                      : \"Soubor nebyl nalezen (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Nelze uložit do dočasných souborů.\",\n    \"ERROR_LOADING\"                        : \"Při spuštění doplňku došlo k chybě.\",\n    \"MALFORMED_URL\"                        : \"URL adresa je neplatná. Ujistěte se, že jste adresu zadali správně.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL adresa musí být http nebo https.\",\n    \"UNKNOWN_ERROR\"                        : \"Neznámá chyba.\",\n    // Pro NOT_FOUND_ERR, vyhledejte obecné řetězce výše\n    \"EXTENSION_MANAGER_TITLE\"              : \"Správce doplňků\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Nelze získat přístup k registru doplňků. Prosím, zkuste to znovu později.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Přetáhněte .zip zde nebo\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Pusťte .zip pro instalaci\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Instalace/aktualizace byla zrušena kvůli následujících chyb:\",\n    \"INSTALL_FROM_URL\"                     : \"Instalovat z URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Ověření\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Datum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Tento doplněk požaduje novější verzi {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Tento doplněk funguje pouze ve starší verzi {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Verze {0} tohoto doplňku vyžaduje novější verzi {APP_NAME}. Můžete si ale nainstalovat dřívější verzi {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Verze {0} tohoto doplňku funguje pouze se starší verzí {APP_NAME}. Můžete si ale nainstalovat dřívější verzi {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Bez popisu\",\n    \"EXTENSION_MORE_INFO\"                  : \"Více informací\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Chyba doplňku\",\n    \"EXTENSION_KEYWORDS\"                   : \"Klíčová slova\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Přeloženo do {0} jazyků, včetně vašeho\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Přeloženo do {0} jazyků\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Tento doplněk byl přeložen do těchto jazyků: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Nainstalováno\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Aktualizace doplňku byla stažena a bude nainstalována při ukončení aplikace {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Hledat\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Více\",\n    \"BROWSE_EXTENSIONS\"                    : \"Procházet doplňky\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Odstranit doplněk\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Nelze odstranit jeden nebo více doplňků: {0}. Aplikace {APP_NAME} se i přesto restartuje.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Aktualizovat doplněk\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Nelze aktualizovat jeden nebo více doplňků: {0}. Aplikace {APP_NAME} se i přesto restartuje.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Deaktivovat doplněk\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Nelze deaktivovat jeden nebo více doplňků: {0}. Aplikace {APP_NAME} se i přesto restartuje.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Označeno k odstranění\",\n    \"UNDO_REMOVE\"                          : \"Zpět\",\n    \"MARKED_FOR_UPDATE\"                    : \"Označeno k aktualizaci\",\n    \"UNDO_UPDATE\"                          : \"Zpět\",\n    \"MARKED_FOR_DISABLING\"                 : \"Označeno k deaktivaci\",\n    \"UNDO_DISABLE\"                         : \"Zpět\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Změnit doplňky\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"K aktualizaci, odstranění nebo deaktivaci označených doplňků je třeba restartovat aplikaci {APP_NAME}. Budete vyzváni k uložení změn.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Odstranit doplňky a restartovat\",\n    \"CHANGE_AND_RELOAD\"                    : \"Změnit doplňky a restartovat\",\n    \"UPDATE_AND_RELOAD\"                    : \"Aktualizovat doplňky a restartovat\",\n    \"DISABLE_AND_RELOAD\"                   : \"Deaktivovat doplňky a restartovat\",\n    \"PROCESSING_EXTENSIONS\"                : \"Zpracování změn doplňku\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Doplněk {0} nemohl být odstraněn, protože nebyl nainstalován.\",\n    \"NO_EXTENSIONS\"                        : \"Žádný doplněk ještě nebyl nainstalován.<br>Klikněte na tlačítko Instalovat z URL pro zahájení instalace.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Žádný doplněk neodpovídá hledání.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"POZNÁMKA: Tyto doplňky mohou pocházet od jiných autorů než {APP_NAME}. Buďte opatrní při instalaci doplňků z neznámých zdrojů.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Nainstalované\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Dostupné\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Motivy\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Aktualizace\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Žádné dostupné shody.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Všechny shody jsou sbalené. Pro prohlédnutí shod rozbalte soubory zobrazené vpravo.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Neexistují žádné CSS předpisy odpovídající vašemu výběru.<br>Pro vytvoření předpisu klikněte na \\\"Nový předpis\\\".\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Neexistují žádné soubory s kaskádovými styly ve vašem projektu.<br>Vytvořte nový soubor pro přidání CSS předpisů.\",\n\n    // Prohlížeče obrázků\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"největší\",\n\n    /**\n     * Názvy jednotek\n     */\n    \"UNIT_PIXELS\"                          : \"pixely\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Nástroje\",\n    \"ERRORS\"                                    : \"Chyby\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Zobrazit nástroje pro vývojáře\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Restartovat {APP_NAME}\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Restartovat bez doplňků\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nové okno {APP_NAME}\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Nainstalovat zástupce do příkazové řádky\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Změnit jazyk\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Spustit testy\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Zobrazit údaje o výkonnosti\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Povolit Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Uložit stav Node do konzole\",\n    \"CMD_RESTART_NODE\"                          : \"Restartovat Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Zobrazit chyby ve stavovém řádku\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Otevřít zdroj {APP_NAME}\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"Zástupce {APP_NAME} v příkazové řádce\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Při instalaci zástupce do příkazové řádky se vyskytla chyba. Prosím vyzkoušejte řešení <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>na této stránce</a>.<br/><br/>Důvod: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Nelze odstranit existující symbolický odkaz na <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Nelze vytvořit složku <code>/usr/local/bin</code>.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Nelze vytvořit symbolický odkaz na <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Vnitřní chyba.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"V tomto operačním systému nelze vytvořit zástupce do příkazové řádky.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Hotovo! Nyní můžete jednoduše spustit {APP_NAME} z příkazové řádky: příkazem <code>brackets myFile.txt</code> otevřete soubor a příkazem <code>brackets myFolder</code> změníte projekt. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Na této stránce zjistíte více</a> o používání {APP_NAME} z příkazové řádky.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Změnit jazyk\",\n    \"LANGUAGE_MESSAGE\"                          : \"Prosím, vyberte jazyk ze seznamu:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Restartovat {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Zrušit\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Výchozí\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Nastavení hlášení o zdraví\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"Hlášení o zdraví {APP_NAME}\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Sdílejte anonymní informace o používání {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Kvůli vylepšování {APP_NAME} odesíláme společnosti Adobe pravidelně omezené <strong>anonymní</strong> statistiky o používání {APP_NAME}. Tyto informace pomáhají upřednostnit některé funkce, předcházet chybám a všimnout si nedostatků v použitelnosti.<br><br>Vaše data si můžete prohlédnout nebo zakázat jejich sdílení výběrem <strong>Nápověda > Hlášení o zdraví</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Zjistěte více ke hlášení o zdraví {APP_NAME}</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"Hlášení o zdraví {APP_NAME}\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Kvůli vylepšování {APP_NAME} odesíláme společnosti Adobe pravidelně omezené <strong>anonymní</strong> statistiky o používání {APP_NAME}. Tyto informace pomáhají upřednostnit některé funkce, předcházet chybám a všimnout si nedostatků v použitelnosti. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Zjistěte více ke hlášení o zdraví {APP_NAME}</a> a jak je pro komunitu {APP_NAME} prospěšné, zatímco je chráněno vaše soukromí.</p><p>Níže je náhled dat, která budou odeslána v příštím hlášení o zdraví, <em>pokud</em> je odesílání povoleno.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Doba\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Postup\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Posunout vybraný bod<br><kbd class='text'>Shift</kbd> Posunout o deset jednotek<br><kbd class='text'>Tab</kbd> Vyměnit body\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Zvýšení nebo snížení kroků<br><kbd>←</kbd><kbd>→</kbd> 'Start' nebo 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Stará hodnota <code>{0}</code> není platná, proto zobrazená funkce byla změněna na <code>{1}</code>. Dokument bude aktualizován při první úpravě.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Současná barva\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Původní barva\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa formát\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex formát\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa formát\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (použito {1} krát)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (použito {1} krát)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Přejít na definici\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Zobrazit nápovědu parametru\",\n    \"NO_ARGUMENTS\"                              : \"<žádné parametry>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Inferenční problém JavaScript souboru\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} narazil na problémy při zpracování <span class='dialog-filename'>{0}</span>.<br><br>Tento soubor nebude nadále používat nápovědy kódu, přechod na definici nebo rychlou úpravu. Pro opětovné zapnutí těchto funkcí, otevřete <code>.brackets.json</code> ve vašem projektu a upravte <code>jscodehints.detectedExclusions</code>.<br><br>Pravděpodobně je to chyba {APP_NAME}. Pokud můžete poskytnout kopii tohoto souboru, prosíme <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>nahlaste tuto chybu</a> s odkazem na daný soubor.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Rychlý náhled\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Nedávné projekty\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Více\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Skrýt vše\",\n    \"EXPAND_ALL\"                    : \"Zobrazit vše\",\n    \"COLLAPSE_CURRENT\"              : \"Skrýt aktuální\",\n    \"EXPAND_CURRENT\"                : \"Zobrazit aktuální\",\n\n    // Popis základních preferencí\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true k automatickému uzavírání závorek\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false k odebrání \\\"Zavřít ostatní výše\\\" z kontextového menu pracovních souborů\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false k odebrání \\\"Zavřít ostatní níže\\\" z kontextového menu pracovních souborů\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false k odebrání \\\"Zavřít ostatní\\\" z kontextového menu pracovních souborů\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Nastavit možnosti uzavírání značek\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Pole značek, které by neměly být automaticky uzavírány\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Zavřít, pokud je napsán > otevírací značky\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Zavřít, pokud je napsán / uzavírací značky\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Pole značek, do kterých je po jejich otevření vložen prázdný řádek\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true k vygenerování záložek skrývajících kód vždy, když se změní úroveň odsazení\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true k povolení skrývání kódu\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true k zobrazení záložek skrývajících kód pouze pokud přejedete myší nad okrajem\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limity, kolik úrovní do hloubky platí Skrýt vše\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Nejmenší počet řádků, pro které se objeví ikona pro skrytí kódu\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true k zapamatování skrytých částí pokud zavřete a znovu otevřete soubor nebo projekt\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"true k povolení skrývání kódu při výběru textu v editoru\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Povolit/zakázat nápovědy HTML vlastností\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Povolit/zakázat nápovědy CSS/LESS/SCSS hodnot\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Povolit/zakázat nápovědy v JavaScriptu\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Povolit/zakázat detaily o datových typech v nápovědách kódu u JavaScriptu\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Povolit/zakázat nápovědy v preferencích\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Povolit/zakázat nápovědy HTML entit\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Povolit/zakázat nápovědy v SVG\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Povolit/zakázat nápovědy HTML značek\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Povolit/zakázat nápovědy adres URL v HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Povolit/zakázat funkci Drag & Drop\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Povolit sledování hlášení o zdraví\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Povolit automatické zvýrazňování shodujících se výrazů v celém dokumentu\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Zvýraznit všechny výrazy shodující se s výrazem, na kterém je aktuálně kurzor (není nutný výběr výrazu)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Zvýraznit pouze pokud je výběr kompletním výrazem\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true k vložení aktuálně vybrané nápovědy při tabulátoru\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true k zamezení automatického zobrazení nápověd JS kódu, jestliže je napsaná .\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Objekt s výchozími možnostmi pro JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true k povolení přiřazených výrazů\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true k povolení bitových operátorů\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true pokud by globální proměnné standardního prohlížeče měly být předdefinované\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true k povolení idiomů Google Closure\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true k povolení příkazu \\\"continue\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true pokud by globální proměnné CouchDB měly být předdefinované\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true k povolení příkazů debuggeru\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true pokud by globální proměnné prohlížeče užitečné při vývoji měly být předdefinované\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true k povolení == a !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true pokud by globální proměnné ES6 měly být předdefinované\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true k povolení eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true k povolení nefiltrovaných \\\"for ... in\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Nastavit vlastní šířku tabulátoru\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Maximální počet hlášených varování\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Maximální počet znaků na řádku\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true k povolení nevyužitých konstruktorů\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true pokud by globální proměnné Node.js měly být předdefinované\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true k povolení přebývajících podtržítek v identifikátorech\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true k zastavení na první chybě\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true k povolení ++ a --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true k povolení . a [^...]. v RegExpu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true pokud by globální proměnné Rhino měly být předdefinované\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true k povolení chybějících `use strict`\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true pokud může být použito blokování ('...Sync') metod.\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true k povolení neefektivního indexování\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true k povolení TODO komentářů\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true k povolení nepoužitých parametrů\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true k povolení více než 1 proměnné ve funkci\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true k ignorování pravidel ohledně prázdných znaků\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Vlastní nastavení jazyků\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Dodatečná mapování z přípony souboru na jméno jazyka\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Dodatečná mapování z názvu souboru na jméno jazyka\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true k povolení panelu zpráv\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Čas v milisekundách, po kterém vyprší asynchronní lintery\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Pole linterů spouštěných nejdříve\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true k povolení experimentálního živého náhledu\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true ke spuštění poskytovatelů určených pouze v linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Maximální počet současně zobrazených nápověd kódu\",\n    \"DESCRIPTION_PATH\"                               : \"Vlastní nastavení cest\",\n    \"DESCRIPTION_PROXY\"                              : \"URL proxy serveru použitého k instalaci doplňků\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true k povolení rolování za konec dokumentu\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false k zakázání všech nápověd kódu\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Při výběru textu nechat zobrazený blikající kurzor\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true ke zobrazení čísel řádků na okraji vlevo od kódu\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Automaticky odsadit při vytvoření nového bloku\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false k zamezení nahrazování tabulátorů mezerami\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true k řazení složek nahoru ve stromu souborů projektu\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Počet mezer použitých v odsazení mezerami\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Síťový port, který by zabudovaný server měl použít pro živý náhled\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true ke zvýraznění řádku, na kterém se nachází kurzor, barvou na pozadí\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Počet zobrazených mezer místo tabulátoru\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true k používání tabulátorů místo mezer\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true k vygenerování hex barev velkými písmeny v Inline Color Editor\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Zalomit řádky přesahující šířku viewportu\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Seznam souborů, u kterých bylo zjištěno, že způsobují, že se Tern vymkne kontrole\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Doba, po jejímž uplynutí Tern při snaze porozumět souborům vyprší\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true ke zobrazení chyb ve stavovém řádku\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true k povolení rychlého náhledu\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true ke zobrazení náhledů obrázků pro chybějící přípony URL\",\n    \"DESCRIPTION_THEME\"                              : \"Vybrat motiv {APP_NAME}\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true k povolení vlastních posuvníků\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true ke skrytí panelu linteru\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Změnit písmo\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Změnit velikost písma, např. 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"true k povolení vyhledávání založeného na Node\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"true k povolení okamžitého vyhledávání\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Pouze pro Mac: \\\"subpixel-antialiased\\\" k povolení sub-pixel vyhlazování nebo \\\"antialiased\\\" k vyhlazování v odstínech šedi\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false k zamezení otevírání souboru s preferencemi v rozděleném editoru\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false k otevření souboru s preferencemi v levém/horním panelu\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"true ke skrytí panelů po zavření posledního souboru z panelu pomocí tlačítka na hlavičce panelu\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Změňte ke zobrazení tlačítek zavřít a rozdělit ve hlavičce.\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Toto je soubor pouze ke čtení s preferencemi podporovanými\\n * v {APP_NAME}.\\n * Použijte tento soubor jako doporučení pro úpravu vašeho souboru s preferencemi\\n * \\\"brackets.json\\\" otevřeném ve druhém panelu.\\n * Pro více informací o úpravě preferencí\\n * v {APP_NAME} se podívejte na webovou stránku https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Výchozí\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"true k povolení módu pouze s kódem a ke skrytí Všech dalších UI prvků v {APP_NAME}\"\n});\n\n/* Last translated for fcd2e98ef35c110e00aebfbb6d3c3816e5156552 */\n"
  },
  {
    "path": "src/nls/cs/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"cs/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_cz/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.cs\"\n});\n"
  },
  {
    "path": "src/nls/da/strings.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(fejl {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Filen kunne ikke findes.\",\n    \"NOT_READABLE_ERR\"                  : \"Filen kunne ikke læses.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Den pågældende mappe kan ikke ændres.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Du har ikke tilladelse til at lave ændringer.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Filen er blevet ændret udenfor {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} understøtter i øjeblikket kun tekstfiler kodet i UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Filen eller mappen eksisterer allerede.\",\n    \"FILE\"                              : \"filen\",\n    \"DIRECTORY\"                         : \"mappen\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Mappe navne\",\n    \"FILENAMES_LEDE\"                    : \"Filnavne\",\n    \"FILENAME\"                          : \"filnavn\",\n    \"DIRECTORY_NAME\"                    : \"mappenavn\",\n\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Fejl ved indlæsning af projekt\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Der skete en fejl ved visning af \\\"Åbn fil\\\"-dialogboksen. (fejl {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Der skete en fejl i forsøget på at læse mappen <span class='dialog-filename'>{0}</span>. (fejl {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Der skete en fejl ved læsning af indholdet i mappen <span class='dialog-filename'>{0}</span>. (fejl {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Fejl ved åbning af fil\",\n    \"ERROR_OPENING_FILE\"                : \"Der skete en fejl i forsøget på at åbne filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Der skete en fejl i forsøget på at åbne følgende filer:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Fejl ved genindlæsning af ændringer fra disk\",\n    \"ERROR_RELOADING_FILE\"              : \"Der skete en fejl i forsøget på at genindlæse filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Fejl ved gemning af fil\",\n    \"ERROR_SAVING_FILE\"                 : \"Der skete en fejl i forsøget på at gemme filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Fejl ved omdøbning af fil\",\n    \"ERROR_RENAMING_FILE\"               : \"Der skete en fejl i forsøget på at omdøbe filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Fejl ved sletning af fil\",\n    \"ERROR_DELETING_FILE\"               : \"Der skete en fejl i forsøget på at slette filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Ugyldigt {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} må ikke gøre brug af system-reserverede ord, ende med punktum (.) eller indeholde nogen af følgende tegn: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"En fil eller mappe med navnet <span class='dialog-filename'>{0}</span> eksisterer allerede.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Fejl ved oprettelse af {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Der skete en fejl i forsøget på at oprette {0} <span class='dialog-filename'>{1}</span>. {2}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Fejl ved indlæsning af indstillinger\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Din konfigurationsfil er ikke gyldig JSON. Filen vil blive åbnet, så du kan rette formateringen. Du bliver nødt til at genindlæse {APP_NAME} for at anvende ændringerne.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ups! {APP_NAME} virker ikke i browsere endnu.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} er lavet i HTML, men lige nu fungerer det som et almindeligt computerprogram, så du kan bruge det til at redigere lokale filer. Brug venligst programskallen fra <b>github.com/adobe/brackets-shell</b> til at køre {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Fejl ved indeksering af filer\",\n    \"ERROR_MAX_FILES\"                   : \"Det maksimale antal filer er blevet indekseret. Handlinger som tilgår filindekset fungerer måske ikke korrekt.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Fejl ved start af browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Google Chrome browseren kunne ikke findes. Undersøg venligst om det er installeret korrekt.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Der skete en fejl ved start af browseren. (fejl {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Fejl ved Live-Forhåndsvisning\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Forbinder til browser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"For at Live-Forhåndsvisning kan forbinde, bliver Chrome nødt til at blive genstartet med fjern-fejlsøgning slået til.<br /><br />Ønsker du at genstarte Chrome med fjern-fejlsøgning slået til?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Kan ikke indlæse siden for Live-Forhåndsvisning\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Åbn en HTML-fil, eller sørg for at der er en fil ved navn <span class='dialog-filename'>index.html</span> i dit projekt, før du starter Live-Forhåndsvisning.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"For at bruge Live-Forhåndsvisning på en server-side fil, bliver du nødt til at angive en basis-URL for dette projekt.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Fejl ved opstart af HTTP-serveren for Live-Forhåndsvisning. Prøv igen.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Velkommen til Live-Forhåndsvisning!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live-Forhåndsvisning forbinder {APP_NAME} til din browser. Der åbnes en forhåndsvisning af din HTML-fil i browseren, som opdateres samtidig med at du redigerer i koden.<br /><br />I denne tidlige version af {APP_NAME}, virker Live-Forhåndsvisning kun med <strong>Google Chrome</strong> og opdaterer direkte imens du redigerer i <strong>CSS- eller HTML-filer</strong>. Ændringer i JavaScript-filer bliver automatisk genindlæst når du gemmer.<br /><br />(Denne besked bliver ikke vist igen.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"For yderligere information, se <a href='{0}' title='{0}'>Løsningsforslag til forbindelsesfejl vedrørende Live-Forhåndsvisning</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live-Forhåndsvisning\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live-Forhåndsvisning: Forbinder\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live-Forhåndsvisning: Starter op\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Afbryd Live-Forhåndsvisning\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live-Forhåndsvisning (gem fil for at genindlæse)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live-Forhåndsvisning (opdatering standset grundet syntaksfejl)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Live-Forhåndsvisning blev afbrudt fordi udviklerværktøjer blev åbnet i browseren\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Live-Forhåndsvisning blev afbrudt fordi siden blev lukket i browseren\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Live-Forhåndsvisning blev afbrudt fordi browseren navigerede til en side udenfor projektet\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Live-Forhåndsvisning blev afbrudt af ukendte årsager ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Gem ændringer\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Ønsker du at gemme ændringerne i dokumentet <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Ønsker du at gemme ændringerne i følgende filer?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Eksterne ændringer\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Bekræft sletning\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Er du sikker på at du vil slette mappen <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Fil slettet\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> er blevet ændret på disken.<br /><br />Ønsker du at gemme filen og overskrive disse ændringer?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> er blevet ændret på disken, men har også ikke-gemte ændringer i {APP_NAME}.<br /><br />Hvilken version ønsker du at beholde?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> er blevet slettet på disken, men har ikke-gemte ændringer i {APP_NAME}.<br /><br />Ønsker du at beholde disse ændringer?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Færdig\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Annuller\",\n    \"DONT_SAVE\"                         : \"Gem ikke\",\n    \"SAVE\"                              : \"Gem\",\n    \"SAVE_AS\"                           : \"Gem som\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Overskriv\",\n    \"DELETE\"                            : \"Slet\",\n    \"BUTTON_YES\"                        : \"Ja\",\n    \"BUTTON_NO\"                         : \"Nej\",\n\n    // Find, Replace, Find in Files\n    \"FIND_NO_RESULTS\"                   : \"Ingen resultater\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Søg\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Erstat med\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Alle\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Erstat\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Erstat\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Næste forekomst\",\n    \"BUTTON_PREV_HINT\"                  : \"Forrige forekomst\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Match store og små bogstaver\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regulært udtryk\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Erstat uden fortrydelse\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Da mere end {0} filer skal ændres, vil {APP_NAME} ændre uåbnede filer på disk.<br />Du vil ikke kunne fortryde ændringerne i disse filer.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Erstat uden fortrydelse\",\n\n    \"OPEN_FILE\"                         : \"Åbn fil\",\n    \"SAVE_FILE_AS\"                      : \"Gem fil\",\n    \"CHOOSE_FOLDER\"                     : \"Vælg en mappe\",\n\n    \"RELEASE_NOTES\"                     : \"Udgivelsesnoter\",\n    \"NO_UPDATE_TITLE\"                   : \"Du er fuldt opdateret!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Du bruger den seneste version af {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Erstat\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"med\",\n    \"FIND_TITLE_LABEL\"                  : \"Fundet\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} i {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"i <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"i projektet\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtret udelukker alle filer {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"fil\",\n    \"FIND_IN_FILES_FILES\"               : \"filer\",\n    \"FIND_IN_FILES_MATCH\"               : \"forekomst\",\n    \"FIND_IN_FILES_MATCHES\"             : \"forekomster\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Mere end \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl-/Cmd-klik for at udfolde/sammenfolde alt\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Fejl ved erstatning\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Følgende filer blev ikke behandlet, da de har ændret sig siden søgningen eller ikke kunne gemmes.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Fejl ved hentning af opdateringsinformation\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Der opstod en fejl ved hentning af seneste opdateringsinformationer fra serveren. Sørg venligst for at du er forbundet til internettet og prøv igen.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Nyt udelukkelsessæt\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Udeluk ingen filer\",\n    \"NO_FILE_FILTER\"                    : \"Ingen filer udelukket\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Udeluk {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Redigér\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Redigér udelukkelsessæt\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Udeluk filer og mapper der matcher en eller flere af følgende (del)strenge eller <a href='{0}' title='{0}'>jokertegn</a>. Indtast hver streng på hver sin linje.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Navngiv dette udelukkelsessæt (valgfrit)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"og {0} flere\",\n    \"FILTER_COUNTING_FILES\"             : \"Tæller filer\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Tillader {0} af {1} filer {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Tillader alle {0} filer {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Ingen Lyn-Redigering tilgængelig for denne markørposition\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS-Lyn-Redigering: placér markøren på et enkelt klassenavn\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS-Lyn-Redigering: ukomplet klasse-attribut\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS-Lyn-Redigering: ukomplet id-attribut\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS-Lyn-Redigering: placér markøren i et tag, en klasse eller et id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS-Timing-Funktion Lyn-Redigering: ugyldig syntaks\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS-Lyn-Redigering: placér markøren i et funktionsnavn\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Ingen Lyn-Dokumentation tilgængelig for denne markørposition\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Indlæser\\u2026\",\n    \"UNTITLED\"          : \"Unavngivet\",\n    \"WORKING_FILES\"     : \"Arbejdsfiler\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Skift\",\n    \"KEYBOARD_SPACE\"  : \"Mellemrum\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Linje {0}, kolonne {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} kolonne markeret\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} kolonner markeret\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} linje markeret\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} linjer markeret\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} markeringer\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klik for at skifte indrykning til mellemrum\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klik for at skifte indrykning til tabulatorstop\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klik for at ændre antallet af mellemrum ved indrykning\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klik for at ændre bredde af tabulatorstop\",\n    \"STATUSBAR_SPACES\"                      : \"Mellemrum:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tabulatorbredde:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} linje\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} linjer\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Udvidelser slået fra\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} problemer\",\n    \"SINGLE_ERROR\"                          : \"1 {0}-problem\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0}-problemer\",\n    \"NO_ERRORS\"                             : \"Ingen {0}-problemer fundet - godt gået!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Ingen problemer fundet - godt gået!\",\n    \"LINT_DISABLED\"                         : \"Lintning er slået fra\",\n    \"NO_LINT_AVAILABLE\"                     : \"Ingen linter tilgængelig for {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Intet at linte\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} har opgivet at vente efter {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} afsluttede med fejl: {1}\",\n\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Filer\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Ny\",\n    \"CMD_FILE_NEW\"                        : \"Ny fil\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Ny mappe\",\n    \"CMD_FILE_OPEN\"                       : \"Åbn\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Tilføj til arbejdsfiler\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Åbn droppede filer\",\n    \"CMD_OPEN_FOLDER\"                     : \"Åbn mappe\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Luk\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Luk alle\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Luk liste\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Luk øvrige\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Luk ovenstående\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Luk nedenstående\",\n    \"CMD_FILE_SAVE\"                       : \"Gem\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Gem alle\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Gem som\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live-Forhåndsvisning\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projektindstillinger\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Omdøb\",\n    \"CMD_FILE_DELETE\"                     : \"Slet\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Installér udvidelse\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Udvidelseshåndtering\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Genindlæs filtræ\",\n    \"CMD_QUIT\"                            : \"Afslut\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Afslut\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Redigér\",\n    \"CMD_UNDO\"                            : \"Fortryd\",\n    \"CMD_REDO\"                            : \"Gentag\",\n    \"CMD_CUT\"                             : \"Klip\",\n    \"CMD_COPY\"                            : \"Kopiér\",\n    \"CMD_PASTE\"                           : \"Sæt ind\",\n    \"CMD_SELECT_ALL\"                      : \"Markér alt\",\n    \"CMD_SELECT_LINE\"                     : \"Markér linje\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Opdel markering i linjer\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Tilføj markør til næste linje\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Tilføj markør til forrige linje\",\n    \"CMD_INDENT\"                          : \"Indryk\",\n    \"CMD_UNINDENT\"                        : \"Udryk\",\n    \"CMD_DUPLICATE\"                       : \"Duplikér\",\n    \"CMD_DELETE_LINES\"                    : \"Slet linje\",\n    \"CMD_COMMENT\"                         : \"Slå linje-kommentar til/fra\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Slå blok-kommentar til/fra\",\n    \"CMD_LINE_UP\"                         : \"Flyt linje op\",\n    \"CMD_LINE_DOWN\"                       : \"Flyt linje ned\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Åbn linjen ovenover\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Åbn linjen nedenunder\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Luk parenteser automatisk\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Vis kodehjælp\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Søg\",\n    \"CMD_FIND\"                            : \"Søg\",\n    \"CMD_FIND_NEXT\"                       : \"Find næste\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Find forrige\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Find alle og markér\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Tilføj næste forekomst til markeringer\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Spring over og tilføj næste forekomst\",\n    \"CMD_FIND_IN_FILES\"                   : \"Søg i filer\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Søg i\\u2026\",\n    \"CMD_REPLACE\"                         : \"Erstat\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Erstat i filer\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Erstat i\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Vis\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Skjul sidepanel\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Vis sidepanel\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Forøg skriftstørrelse\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Formindsk skriftstørrelse\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Nulstil skriftstørrelse\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Rul en linje op\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Rul en linje ned\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Linjenumre\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Fremhæv aktiv linje\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Tekstombrydning\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Fremhæv i Live-Forhåndsvisning\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Lint filer når de gemmes\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sortér efter tilføjelse\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sortér efter navn\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sortér efter type\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatisk sortering\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigér\",\n    \"CMD_QUICK_OPEN\"                      : \"Lyn-åbn\",\n    \"CMD_GOTO_LINE\"                       : \"Gå til linje\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Lyn-søg efter definition\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Gå til første fejl/advarsel\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Lyn-Redigering\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Lyn-Dokumentation\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Forrige forekomst\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Næste forekomst\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Ny regel\",\n    \"CMD_NEXT_DOC\"                        : \"Næste dokument\",\n    \"CMD_PREV_DOC\"                        : \"Forrige dokument\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Vis i filtræ\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Vis i Stifinder\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Vis i Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Vis i OS\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Hjælp\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Kontrollér for opdateringer\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Sådan bruger du {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} support\",\n    \"CMD_SUGGEST\"                         : \"Foreslå en funktion\",\n    \"CMD_RELEASE_NOTES\"                   : \"Udgivelsesnoter\",\n    \"CMD_GET_INVOLVED\"                    : \"Bliv involveret\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Vis udvidelsesmappe\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} hjemmeside\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} på Twitter\",\n    \"CMD_ABOUT\"                           : \"Om {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Åbn konfigurationsfil\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"eksperimentiel version\",\n    \"DEVELOPMENT_BUILD\"                    : \"udviklerversion\",\n    \"RELOAD_FROM_DISK\"                     : \"Genindlæs fra disk\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Behold ændringer i editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Luk (uden at gemme)\",\n    \"RELAUNCH_CHROME\"                      : \"Genstart Chrome\",\n    \"ABOUT\"                                : \"Om\",\n    \"CLOSE\"                                : \"Luk\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"fabrikationstidspunkt: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Bemærkninger om og/eller yderligere betingelser og vilkår for tredjeparts software kan findes på <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> og medtaget heri som reference.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentation og kildekode på <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Skabt med \\u2764 og JavaScript af:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"En masse mennesker (men vi har problemer med at hente det data i øjeblikket).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"Dokumentationen og det grafiske logo fra MDN er udgivet under en Creative Commons Attribution licens, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Der ligger en ny version af {APP_NAME} klar! Klik her for at læse mere.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Opdatering klar\",\n    \"UPDATE_MESSAGE\"                       : \"Hey! Der er en ny version af {APP_NAME} tilgængelig. Her er nogen af de nye funktioner:\",\n    \"GET_IT_NOW\"                           : \"Hent den nu!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projektindstillinger for: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Basis-URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"For at bruge en lokal server, indtast en URL såsom http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"{0}-protokollen er ikke understøttet af Live-Forhåndsvisning&mdash;Brug venligst http: eller https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Basis-URL'en kan ikke indeholde søgeparametre såsom \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Basis-URL'en kan ikke indeholde interne henvisninger såsom \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Specielle tegn såsom '{0}' skal kodes med %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Ukendt fejl ved tolkning af Basis-URL\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Ny regel\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Installér\",\n    \"UPDATE\"                               : \"Opdatér\",\n    \"REMOVE\"                               : \"Fjern\",\n    \"OVERWRITE\"                            : \"Overskriv\",\n    \"CANT_REMOVE_DEV\"                      : \"Udvidelser i \\\"dev\\\"-mappen skal slettes manuelt.\",\n    \"CANT_UPDATE\"                          : \"Opdateringen er ikke kompatibel med denne version af {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Udvidelser i \\\"dev\\\"-mappen kan ikke opdateres automatisk.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Installér udvidelse\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Opdatér udvidelse\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Udvidelses-URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL til udvidelsens zip-fil eller GitHub-repo\",\n    \"INSTALLING_FROM\"                      : \"Installerer udvidelse fra {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installation lykkedes!\",\n    \"INSTALL_FAILED\"                       : \"Installation mislykkedes.\",\n    \"CANCELING_INSTALL\"                    : \"Afbryder\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Afbrydelsen af installationen tager lang tid. En intern fejl er måske opstået.\",\n    \"INSTALL_CANCELED\"                     : \"Installation afbrudt.\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Det modtagede indhold er ikke en gyldig zip-fil.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Filen <span class='dialog-filename'>package.json</span> er ugyldig (fejl: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Filen <span class='dialog-filename'>package.json</span> angiver ikke et pakkenavn.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} er et ugyldigt pakkenavn.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Filen <span class='dialog-filename'>package.json</span> angiver ikke en pakkeversion.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Pakkeversionsnummeret ({0}) er ugyldigt.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Kompatibilitets-strengen for {APP_NAME} ({0}) er ugyldig.\",\n    \"DISALLOWED_WORDS\"                     : \"Ordene ({1}) er ikke tilladt i {0}-feltet.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Udvidelsen er ikke kompatibel med denne version af {APP_NAME}. Den er installeret i mappen for deaktiverede udvidelser.\",\n    \"MISSING_MAIN\"                         : \"Pakken har ingen fil ved navn <span class='dialog-filename'>main.js</span>.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Denne pakke vil overskrive en tidligere installation. Overskriv den gamle udvidelse?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Denne pakke er samme version som den installerede. Overskriv den eksisterende installation?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Denne pakke er version {0}, som er ældre end den nuværende installation ({1}). Overskriv den eksisterende installation?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Intern fejl: download-ID er allerede i brug.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Kan ikke forbinde til server.\",\n    \"BAD_HTTP_STATUS\"                      : \"Filen kunne ikke findes på serveren (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Ikke i stand til at gemme nedhentede data til en midlertidig fil.\",\n    \"ERROR_LOADING\"                        : \"Udvidelsen stødte på en fejl imens den startede op.\",\n    \"MALFORMED_URL\"                        : \"URL'en er ugyldig. Sørg for at du har indtastet den korrekt.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL'en skal være en http- eller https-URL.\",\n    \"UNKNOWN_ERROR\"                        : \"Ukendt intern fejl.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Udvidelseshåndtering\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Ikke i stand til at tilgå udvidelsesregistret. Prøv igen senere.\",\n    \"INSTALL_FROM_URL\"                     : \"Installér fra URL\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Forfatter\",\n    \"EXTENSION_DATE\"                       : \"Dato\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Denne udvidelse kræver en nyere version af {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Denne udvidelse virker i øjeblikket kun med ældre versioner af {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Version {0} af denne udvidelse kræver en nyere version af {APP_NAME}. Men du kan installere den tidligere version {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Version {0} af denne udvidelse virker kun med en ældre version af {APP_NAME}. Men du kan installere den tidligere version {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Ingen beskrivelse\",\n    \"EXTENSION_MORE_INFO\"                  : \"Mere information...\",\n    \"EXTENSION_ERROR\"                      : \"Udvidelsesfejl\",\n    \"EXTENSION_KEYWORDS\"                   : \"Nøgleord\",\n    \"EXTENSION_INSTALLED\"                  : \"Installeret\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Opdatering til denne udvidelse er blevet hentet og vil blive installeret efter at {APP_NAME} er genindlæst.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Søg\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Mere\",\n    \"BROWSE_EXTENSIONS\"                    : \"Gennemse udvidelser\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Fjern udvidelse\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Ikke i stand til at fjerne en eller flere udvidelser: {0}. {APP_NAME} vil stadig blive genindlæst.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Opdatér udvidelse\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Ikke i stand til at opdatere en eller flere udvidelser: {0}. {APP_NAME} vil stadig blive genindlæst.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Markeret til fjernelse\",\n    \"UNDO_REMOVE\"                          : \"Fortryd\",\n    \"MARKED_FOR_UPDATE\"                    : \"Markeret til opdatering\",\n    \"UNDO_UPDATE\"                          : \"Fortryd\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Gennemfør ændringer på udvidelser\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"For at opdatere eller fjerne de valgte udvidelser bliver {APP_NAME} nødt til at blive genindlæst. Du vil blive bedt om at gemme ikke-gemte ændringer.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Fjern udvidelser og genindlæs\",\n    \"CHANGE_AND_RELOAD\"                    : \"Gennemfør ændringer og genindlæs\",\n    \"UPDATE_AND_RELOAD\"                    : \"Opdatér udvidelser og genindlæs\",\n    \"PROCESSING_EXTENSIONS\"                : \"Behandler udvidelsesændringer\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Kunne ikke fjerne udvidelsen {0} da den ikke er installeret.\",\n    \"NO_EXTENSIONS\"                        : \"Ingen udvidelser er installeret endnu.<br>Klik på \\\"Udvalg\\\" foroven for at komme i gang.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Ingen udvidelser matcher din søgning.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Vær forsigtig med at installere udvidelser fra en ukendt kilde.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Installeret\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Udvalg\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Opdateringer\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Ingen forekomster.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Der eksisterer ingen CSS-regler, som matcher det markerede element.<br> Klik \\\"Ny regel\\\" for at oprette en.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Der er ingen stylesheets i dit projekt.<br>Opret et for at tilføje CSS-regler.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"største\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"pixler\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Fejlsøgning\",\n    \"ERRORS\"                                    : \"Fejl\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Vis udviklerværktøjer\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Genindlæs med udvidelser\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Genindlæs uden udvidelser\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nyt {APP_NAME} vindue\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Skift sprog\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Kør enhedstest\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Vis ydelsesdata\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Slå Node-debugger til\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Log Node tilstand til konsol\",\n    \"CMD_RESTART_NODE\"                          : \"Genstart Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Vis fejl i statuslinjen\",\n\n    \"LANGUAGE_TITLE\"                            : \"Skift sprog\",\n    \"LANGUAGE_MESSAGE\"                          : \"Sprog:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Genindlæs {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Annuller\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Systemets sprog\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tid\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Forløb\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Flyt valgte punkt<br><kbd class='text'>Skift</kbd> Flyt ti enheder af gangen<br><kbd class='text'>Tab</kbd> Skift punkter\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Forøg eller formindsk antal trin<br><kbd>←</kbd><kbd>→</kbd> 'Start' eller 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Den gamle værdi <code>{0}</code> er ikke gyldig, så den viste funktion blev ændret til <code>{1}</code>. Dokumentet vil blive opdateret ved første redigering.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Nuværende farve\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Oprindelig farve\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa-format\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex-format\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa-format\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Brugt {1} gang)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Brugt {1} gange)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Hop til definition\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Vis parameterhjælp\",\n    \"NO_ARGUMENTS\"                              : \"<ingen parametre>\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Lyn-visning af det du peger på\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Seneste projekter\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Læs mere\"\n});\n\n/* Last translated for 3a762c3cf91d6f65a5bb19aeb2056afacd777c71 */\n"
  },
  {
    "path": "src/nls/da/urls.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"da/Kom godt i gang\"\n});\n"
  },
  {
    "path": "src/nls/de/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(Fehler {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Die Datei/der Ordner konnte nicht gefunden werden.\",\n    \"NOT_READABLE_ERR\"                  : \"Die Datei/der Ordner konnte nicht gelesen werden.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"{APP_NAME} kann keine Dateien öffnen, die größer als {0} MB sind.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Der Ziel-Ordner kann nicht verändert werden.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Die Berechtigungen erlauben Ihnen nicht, Veränderungen vorzunehmen.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Die Datei wurde außerhalb von {APP_NAME} verändert.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} unterstützt derzeit nur UTF-8-kodierte Textdateien.\",\n    \"FILE_EXISTS_ERR\"                   : \"Die Datei existiert bereits.\",\n    \"FILE\"                              : \"Datei\",\n    \"FILE_TITLE\"                        : \"Datei\",\n    \"DIRECTORY\"                         : \"Ordner\",\n    \"DIRECTORY_TITLE\"                   : \"Ordner\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Ordnernamen\",\n    \"FILENAMES_LEDE\"                    : \"Dateinamen\",\n    \"FILENAME\"                          : \"Dateiname\",\n    \"DIRECTORY_NAME\"                    : \"Ordnername\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Fehler beim Laden des Projekts\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Fehler beim Erstellen des Datei-Öffnen-Dialogs. (Fehler {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Fehler beim Lesen des Ordners <span class='dialog-filename'>{0}</span>. (Fehler {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Fehler beim Lesen der Ordnerinhalte von <span class='dialog-filename'>{0}</span>. (Fehler {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Fehler beim Öffnen der Datei\",\n    \"ERROR_OPENING_FILE\"                : \"Beim Öffnen der Datei <span class='dialog-filename'>{0}</span> ist ein Fehler aufgetreten: {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Beim Öffnen folgender Dateien ist ein Fehler aufgetreten:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Fehler beim Laden der Änderungen\",\n    \"ERROR_RELOADING_FILE\"              : \"Beim Laden der Änderungen der Datei <span class='dialog-filename'>{0}</span> ist ein Fehler aufgetreten: {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Fehler beim Speichern der Datei\",\n    \"ERROR_SAVING_FILE\"                 : \"Beim Speichern der Datei <span class='dialog-filename'>{0}</span> ist ein Fehler aufgetreten: {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Fehler beim Umbenennen von {0}\", // TODO: depends on {0} gender\n    \"ERROR_RENAMING_FILE\"               : \"Beim Umbenennen von {2} <span class='dialog-filename'>{0}</span> ist ein Fehler aufgetreten: {1}\", // TODO: depends on {2} gender\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Die Datei oder der Ordner ist nicht Teil des geöffneten Projekts. Leider können derzeit nur Dateien im Projekt umbenannt werden.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Fehler beim Löschen von {0}\", // TODO: depends on {0} gender\n    \"ERROR_DELETING_FILE\"               : \"Beim Löschen von {2} <span class='dialog-filename'>{0}</span> ist ein Fehler aufgetreten. {1}\", // TODO: depends on {2} gender\n    \"INVALID_FILENAME_TITLE\"            : \"Ungültiger {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} dürfen keine dem System vorbehaltenen Namen gebrauchen und nicht mit Punkten (.) enden oder die folgenden Zeichen enthalten: <span class='emphasized'>{1}</span>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Eine Datei oder ein Ordner mit dem Namen <span class='dialog-filename'>{0}</span> existiert bereits.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Fehler beim Erstellen von {0}\", // TODO: depends on {0} gender\n    \"ERROR_CREATING_FILE\"               : \"Beim Erstellen von {0} <span class='dialog-filename'>{1}</span> ist ein Fehler aufgetreten: {2}\", // TODO: depends on {0} gender\n    \"ERROR_MIXED_DRAGDROP\"              : \"Ein Ordner kann nicht zeitgleich mit anderen Dateien geöffnet werden.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Fehler beim Einlesen der benutzerdefinierten Tastenbelegung\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Ihre Tastenbelegungs-Datei enthält kein gültiges JSON. Die Datei wird geöffnet, damit sie das Format korrigieren können.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Ihre Tastenbelegungs-Datei ist keine gültige UTF-8-kodierte Textdatei und kann daher nicht geladen werden.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Sie können die Tastenkürzel der folgenden Befehle nicht ändern: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Sie können die folgenden Tastenkürzel nicht ändern: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Sie ordnen diesen Befehlen mehrere Tastenkürzel zu: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Sie belegen diese Tastenkürzel mehrfach: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Diese Tastenkürzel sind ungültig: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Sie ordnen nicht existierenden Befehlen Tastenkürzel zu: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Fehler beim Lesen der Einstellungen\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Ihre Einstellungsdatei enthält kein gültiges JSON. Die Datei wird geöffnet, damit Sie das Format korrigieren können. Sie müssen {APP_NAME} neu starten, damit die Änderungen wirksam werden.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Ihre projektspezifische Einstellungsdatei enthält kein gültiges JSON. Die Datei wird geöffnet, damit Sie das Format korrigieren können. Sie müssen das Projekt neu öffnen, damit die Änderungen wirksam werden.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ups! {APP_NAME} kann derzeit leider noch nicht im Browser ausgeführt werden.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} wurde in HTML programmiert, ist derzeit jedoch lediglich als Desktop-Anwendung verfügbar, um damit lokale Dateien zu bearbeiten. Bitte verwenden Sie die Anwendungs-Shell im Repo <b>github.com/adobe/brackets-shell</b>, um {APP_NAME} auszuführen.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Fehler beim Indizieren der Dateien\",\n    \"ERROR_MAX_FILES\"                   : \"Dieses Projekt besteht aus über 30.000 Dateien. Funktionen, die mit mehreren Dateien interagieren, wurden eventuell deaktiviert oder verhalten sich so, als ob das Projekt keine Dateien hätte. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Lies mehr über das Arbeiten mit großen Projekten</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Fehler beim Starten des Browsers\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Der Browser Google Chrome konnte nicht gefunden werden. Bitte stellen Sie sicher, dass er installiert ist.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Beim Starten des Browsers ist ein Fehler aufgetreten. (Fehler {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Fehler bei der Live-Vorschau\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Verbinden zum Browser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Um die Live-Vorschau zu verwenden, muss Chrome mit aktiviertem Remote-Debugging neu gestartet werden.<br /><br />Soll Chrome neu gestartet werden, um das Remote Debugger Protokoll zu aktivieren?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Laden der Live-Vorschau nicht möglich.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Öffnen Sie eine HTML-Datei oder stellen Sie sicher, dass sich eine index.html-Datei im Projekt befindet, um die Live-Vorschau zu starten.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Zum Starten der Live-Vorschau mit einer serverseitigen Datei müssen Sie eine Basis-URL für dieses Projekt angeben.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Ein Fehler ist beim Starten des HTTP-Servers oder der Live-Vorschau-Dateien aufgetreten. Bitte versuchen Sie es später erneut.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Willkommen bei der Live-Vorschau!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Die Live-Vorschau verbindet {APP_NAME} mit Ihrem Browser. Sie startet eine Vorschau Ihrer HTML-Datei im Browser und aktualisiert die Vorschau, sobald Sie Ihren Code bearbeiten.<br /><br />In dieser frühen Version von {APP_NAME} funktioniert die Live-Vorschau nur mit <strong>Google Chrome</strong> und aktualisiert sich live, wenn Sie <strong>CSS- oder HTML-Dateien</strong> bearbeiten. Änderungen an JavaScript-Dateien werden beim Speichern automatisch neu geladen.<br /><br />(Sie sehen diese Meldung nur einmal.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Weitere Informationen finden Sie unter dem Thema <a href='{0}' title='{0}'>Fehlerbehebung bei Verbindungs-Fehlern der Live-Entwicklung</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live-Vorschau\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live-Vorschau: Verbinden\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live-Vorschau: Initialisieren\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Live-Vorschau trennen\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live-Vorschau (Datei speichern zum Aktualisieren)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live-Vorschau (Es wird aufgrund eines Syntax-Fehlers nicht aktualisiert)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Die Live-Vorschau wurde abgebrochen, weil die Entwickler-Tools des Browsers geöffnet wurden\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Die Live-Vorschau wurde abgebrochen, weil die Seite im Browser geschlossen wurde\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Die Live-Vorschau wurde abgebrochen, weil der Browser eine Seite geladen hat, die nicht Teil des aktuellen Projekts ist\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Die Live-Vorschau wurde aus einem unbekannten Grund abgebrochen ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Änderungen speichern\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Wollen Sie die Änderungen in dem Dokument <span class='dialog-filename'>{0}</span> speichern?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Wollen Sie Ihre Änderungen in den folgenden Dateien speichern?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Externe Änderungen\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Löschen bestätigen\",\n    \"CONFIRM_FILE_DELETE\"               : \"Sind Sie sich sicher, dass Sie die Datei <span class='dialog-filename'>{0}</span> löschen wollen?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Sind Sie sich sicher, dass Sie den Ordner <span class='dialog-filename'>{0}</span> löschen wollen?\",\n    \"FILE_DELETED_TITLE\"                : \"Datei gelöscht\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> wurde außerhalb von {APP_NAME} geändert.<br /><br />Wollen Sie die Datei speichern und die externen Änderungen ersetzen?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> wurde außerhalb von {APP_NAME} geändert und hat ungespeicherte Änderungen in {APP_NAME}.<br /><br />Welche Version wollen Sie weiterverwenden?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> wurde außerhalb von {APP_NAME} gelöscht und hat ungespeicherte Änderungen in {APP_NAME}.<br /><br />Wollen Sie die Änderungen beibehalten?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Fertig\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Abbrechen\",\n    \"DONT_SAVE\"                         : \"Nicht speichern\",\n    \"SAVE\"                              : \"Speichern\",\n    \"SAVE_AS\"                           : \"Speichern unter\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Ersetzen\",\n    \"DELETE\"                            : \"Löschen\",\n    \"BUTTON_YES\"                        : \"Ja\",\n    \"BUTTON_NO\"                         : \"Nein\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} von {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Keine Ergebnisse\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Suchen\\u2026\",\n    \"FIND_HISTORY_MAX_COUNT\"            : \"Höchstzahl an Ergebnissen im Suchverlauf\",\n    \"REPLACE_PLACEHOLDER\"               : \"Ersetzen mit\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Alle ersetzen\",\n    \"BUTTON_REPLACE_BATCH\"              : \"Mehrere\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Ersetzen\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Ersetzen\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Nächster Treffer\",\n    \"BUTTON_PREV_HINT\"                  : \"Vorheriger Treffer\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Groß-/Kleinschreibung beachten\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regulärer Ausdruck\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Endgültiges Ersetzen\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Da mehr als {0} Dateien geändert werden, wird {APP_NAME} ungeöffnete Dateien auf der Festplatte verändern.<br />Das Ersetzen kann in diesen Dateien nicht mehr rückgängig gemacht werden.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Endgültig ersetzen\",\n\n    \"OPEN_FILE\"                         : \"Datei öffnen\",\n    \"SAVE_FILE_AS\"                      : \"Datei speichern\",\n    \"CHOOSE_FOLDER\"                     : \"Ordner wählen\",\n\n    \"RELEASE_NOTES\"                     : \"Versionshinweise\",\n    \"NO_UPDATE_TITLE\"                   : \"Sie sind auf dem Laufenden!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Sie führen die neuste Version von {APP_NAME} aus.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Ersetze\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"mit\",\n    \"FIND_TITLE_LABEL\"                  : \"Gefunden:\",\n    \"FIND_TITLE_SUMMARY\"                : \"&ndash; {0} {1} {2} in {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"in <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"im Projekt\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Der Filter schließt alle Dateien {0} aus\",\n    \"FIND_IN_FILES_FILE\"                : \"Datei\",\n    \"FIND_IN_FILES_FILES\"               : \"Dateien\",\n    \"FIND_IN_FILES_MATCH\"               : \"Treffer\",\n    \"FIND_IN_FILES_MATCHES\"             : \"Treffer\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Über \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&ndash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Strg/Cmd + Klick, um alle aus-/einzuklappen\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Index für Sofortsuche wird erstellt\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Fehler beim Ersetzen\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Die folgenden Dateien wurden nicht verändert, weil sie nach der Suche geändert wurden oder nicht geschrieben werden konnten.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Fehler beim Abrufen der Update-Info\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Beim Abrufen der neusten Update-Informationen vom Server ist ein Problem aufgetreten. Bitte stellen Sie sicher, dass Sie mit dem Internet verbunden sind, und probieren Sie es erneut.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Neuer Filter\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Keine Dateien ausschließen\",\n    \"NO_FILE_FILTER\"                    : \"Keine Dateien werden ausgeschlossen\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Schließe {0} aus\",\n    \"EDIT_FILE_FILTER\"                  : \"Bearbeiten\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Filter bearbeiten\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Schließe Dateien und Ordner aus, auf die einer der folgenden Pfade / Teilpfade oder <a href='{0}' title='{0}'>Platzhalter</a> zutrifft. Nutze für jeden Pfad eine neue Zeile.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Benenne diesen Filter (optional)\",\n    \"FILTER_NAME_REMAINING\"             : \"Noch {0} Zeichen\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"und {0} weitere\",\n    \"FILTER_COUNTING_FILES\"             : \"Dateien werden gezählt\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Lässt {0} von {1} Dateien {2} zu\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Lässt alle {0} Dateien {1} zu\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Es wurde kein Editor für Schnelles Bearbeiten für die aktuelle Cursorposition gefunden\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Quick Edit: Setzen Sie den Cursor auf einen einzigen Klassennamen\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Quick Edit: Unvollständiges Klassenattribut\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Quick Edit: Unvollständiges ID-Attribut\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Quick Edit: Setzen Sie den Cursor auf einen Tag, eine Klasse oder eine ID\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS Timing Function Quick Edit: Syntax nicht korrekt\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Quick Edit: Setzen Sie den Cursor auf einen Funktionsnamen\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Die Schnell-Dokumentation ist für die aktuelle Cursorposition nicht verfügbar\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"  : \"Lädt\\u2026\",\n    \"UNTITLED\"         : \"Unbenannt\",\n    \"WORKING_FILES\"    : \"Offene Dateien\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Oben\",\n    \"BOTTOM\"            : \"Unten\",\n    \"LEFT\"              : \"Links\",\n    \"RIGHT\"             : \"Rechts\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Nicht geteilt\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Vertikal geteilt\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Horizontal geteilt\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Teilen Sie den Editor vertikal oder horizontal\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Projektdateien konfigurieren\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Bereits geöffnet\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Diese Datei ist bereits in einer anderen Ansicht geöffnet. Das Öffnen einer Datei in mehreren Ansichten wird {APP_NAME} bald unterstützen. Bis dahin wird die Datei in der Ansicht angezeigt, in der sie bereits geöffnet ist.<br /><br />(Sie sehen diese Nachricht nur einmal.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Strg\",\n    \"KEYBOARD_SHIFT\"        : \"Umschalt\",\n    \"KEYBOARD_SPACE\"        : \"Leer\",\n    \"KEYBOARD_PAGE_UP\"      : \"Bild\\u2191\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Bild\\u2193\",\n    \"KEYBOARD_HOME\"         : \"Pos 1\",\n    \"KEYBOARD_END\"          : \"Ende\",\n    \"KEYBOARD_INSERT\"       : \"Einfg\",\n    \"KEYBOARD_DELETE\"       : \"Entf\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Zeile {0}, Spalte {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} Spalte ausgewählt\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} Spalten ausgewählt\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} Zeile ausgewählt\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} Zeilen ausgewählt\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} Auswahlen\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klicken, um Einrückung auf Leerzeichen umzuschalten\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klicken, um Einrückung auf Tabs umzuschalten\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klicken, um die Anzahl Leerzeichen beim Einrücken zu ändern\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klicken, um die Schrittweite von Tabs zu ändern\",\n    \"STATUSBAR_SPACES\"                      : \"Leerzeichen:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab-Schrittweite:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Zeile\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Zeilen\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Erweiterungen deaktiviert\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Klicken, um zwischen den Cursor-Modi Einfügen (INS) und Überschreiben (OVR) umzuschalten\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Klicken, um den Dateityp zu ändern\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Klicken, um Übersicht anzuzeigen/auszublenden.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(Standard)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Als Standard für .{0}-Dateien festlegen\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} Probleme\",\n    \"SINGLE_ERROR\"                          : \"1 {0} Fehler\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} Fehler\",\n    \"NO_ERRORS\"                             : \"Keine {0} Fehler - gute Arbeit!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Keine Fehler - gute Arbeit!\",\n    \"LINT_DISABLED\"                         : \"Das Linten ist nicht aktiviert\",\n    \"NO_LINT_AVAILABLE\"                     : \"Es ist kein Linter für {0} verfügbar\",\n    \"NOTHING_TO_LINT\"                       : \"Es gibt nichts zum Linten\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} hat die Zeitbegrenzung von {1} ms überschritten\",\n    \"LINTER_FAILED\"                         : \"{0} hat mit einer Fehlermeldung abgebrochen: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Datei\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Neu\",\n    \"CMD_FILE_NEW\"                        : \"Neue Datei\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Neuer Ordner\",\n    \"CMD_FILE_OPEN\"                       : \"Öffnen\\u2026\",\n    \"CMD_RECENT_FILES_OPEN\"               : \"Zuletzt verwendete Dateien öffnen\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Im Projekt öffnen\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Abgelegte Dateien öffnen\",\n    \"CMD_OPEN_FOLDER\"                     : \"Ordner öffnen\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Schließen\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Alles schließen\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Liste schließen\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Alle anderen schließen\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Alle darüber schließen\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Alle darunter schließen\",\n    \"CMD_FILE_SAVE\"                       : \"Speichern\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Alles speichern\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Speichern unter\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live-Vorschau\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Experimentelle Live-Vorschau aktivieren\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Live-Vorschau neu laden\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projekt-Einstellungen\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Umbenennen\\u2026\",\n    \"CMD_FILE_DELETE\"                     : \"Löschen\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Erweiterung installieren\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Erweiterungs-Verwaltung\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Dateibaum neu laden\",\n    \"CMD_QUIT\"                            : \"Beenden\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Beenden\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Bearbeiten\",\n    \"CMD_UNDO\"                            : \"Rückgängig\",\n    \"CMD_REDO\"                            : \"Wiederholen\",\n    \"CMD_CUT\"                             : \"Ausschneiden\",\n    \"CMD_COPY\"                            : \"Kopieren\",\n    \"CMD_PASTE\"                           : \"Einfügen\",\n    \"CMD_SELECT_ALL\"                      : \"Alles auswählen\",\n    \"CMD_SELECT_LINE\"                     : \"Zeile auswählen\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Auswahl in Zeilen aufteilen\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Cursor zur nächsten Zeile hinzufügen\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Cursor zur vorherigen Zeile hinzufügen\",\n    \"CMD_INDENT\"                          : \"Einrücken\",\n    \"CMD_UNINDENT\"                        : \"Ausrücken\",\n    \"CMD_DUPLICATE\"                       : \"Duplizieren\",\n    \"CMD_DELETE_LINES\"                    : \"Zeile löschen\",\n    \"CMD_COMMENT\"                         : \"Zeile (aus-)kommentieren\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Block (aus-)kommentieren\",\n    \"CMD_LINE_UP\"                         : \"Zeile nach oben verschieben\",\n    \"CMD_LINE_DOWN\"                       : \"Zeile nach unten verschieben\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Zeile darüber öffnen\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Zeile darunter öffnen\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Klammern automatisch schließen\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Code Hints anzeigen\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Suchen\",\n    \"CMD_FIND\"                            : \"Suchen\",\n    \"CMD_FIND_NEXT\"                       : \"Weitersuchen (vorwärts)\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Weitersuchen (rückwärts)\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Alle suchen und auswählen\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Nächsten Treffer zur Auswahl hinzufügen\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Überspringen und nächsten Treffer hinzufügen\",\n    \"CMD_FIND_IN_FILES\"                   : \"Im Projekt suchen\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Suchen in\\u2026\",\n    \"CMD_REPLACE\"                         : \"Ersetzen\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Im Projekt ersetzen\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Ersetzen in\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Ansicht\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Seitenleiste verbergen\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Seitenleiste zeigen\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Seitenleiste anzeigen/verbergen\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Panels anzeigen/verbergen\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Ablenkungsfreier Modus\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Schrift vergrößern\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Schrift verkleinern\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Schriftgröße zurücksetzen\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Zeile hoch scrollen\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Zeile runter scrollen\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Zeilennummern anzeigen\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Aktive Zeile hervorheben\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Zeilenumbruch aktivieren\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Live-Vorschau Highlight\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Beim Speichern linten\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Nach Hinzufügen-Datum sortieren\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Nach Name sortieren\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Nach Typ sortieren\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatisch sortieren\",\n    \"CMD_THEMES\"                          : \"Designs\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Navigation\",\n    \"CMD_QUICK_OPEN\"                      : \"Schnell öffnen\",\n    \"CMD_GOTO_LINE\"                       : \"Gehe zur Zeile\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Definition schnell finden\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Zum ersten Problem gehen\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Schnell bearbeiten\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Schnell-Dokumentation\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Voriger Treffer\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Nächster Treffer\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Neue Regel\",\n    \"CMD_NEXT_DOC\"                        : \"Nächstes Dokument\",\n    \"CMD_PREV_DOC\"                        : \"Voriges Dokument\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Nächstes Dokument in der Liste\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Vorheriges Dokument in der Liste\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Im Dateibaum anzeigen\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Im Explorer anzeigen\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Im Finder anzeigen\",\n    \"CMD_SHOW_IN_OS\"                      : \"Im Dateisystem anzeigen\",\n    \"CMD_SWITCH_PANE_FOCUS\"               : \"In andere Ansicht wechseln\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Hilfe\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Nach Updates suchen\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"So verwendet man {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME}-Support\",\n    \"CMD_SUGGEST\"                         : \"Ein Feature vorschlagen\",\n    \"CMD_RELEASE_NOTES\"                   : \"Versionshinweise\",\n    \"CMD_GET_INVOLVED\"                    : \"Mach mit\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Erweiterungen-Ordner anzeigen\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Statusbericht\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_NAME}-Homepage\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} auf Twitter\",\n    \"CMD_ABOUT\"                           : \"Über {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Einstellungsdatei öffnen\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Benutzerdefinierte Tastenbelegung öffnen\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"Experimenteller Build\",\n    \"RELEASE_BUILD\"                        : \"Build\",\n    \"DEVELOPMENT_BUILD\"                    : \"Entwicklungs-Build\",\n    \"RELOAD_FROM_DISK\"                     : \"Von der Festplatte neu laden\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Änderungen im Editor behalten\",\n    \"CLOSE_DONT_SAVE\"                      : \"Schließen (nicht speichern)\",\n    \"RELAUNCH_CHROME\"                      : \"Chrome neu starten\",\n    \"ABOUT\"                                : \"Über\",\n    \"CLOSE\"                                : \"Schließen\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Release {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"Zeitpunkt des Builds: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Hinweise, Bestimmungen und Bedingungen, die sich auf Drittanbieter-Software beziehen, finden sich unter <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> und sind hier durch Bezugnahme eingeschlossen.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentation und Quellcode unter <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Gemacht mit \\u2764 und JavaScript von:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"…vielen Leuten (…leider haben wir aber gerade Probleme, diese Daten zu laden).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN-Dokumente und das grafische Logo von MDN sind unter einer Creative-Commons-Namensnennungs-Lizenz lizenziert, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Eine neue Version von {APP_NAME} ist verfügbar! Für Details hier klicken.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Update verfügbar\",\n    \"UPDATE_MESSAGE\"                       : \"Hallo! Eine neue Version von {APP_NAME} ist verfügbar. Hier sind einige der neuen Funktionen:\",\n    \"GET_IT_NOW\"                           : \"Jetzt aktualisieren!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projekt-Einstellungen\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Basis-URL für Live-Vorschau\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"(URL angeben, um einen lokalen Server zu verwenden)\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Das Protokoll {0} wird von der Live-Vorschau nicht unterstützt &ndash; bitte http: oder https: verwenden.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Die Basis-URL kann keine Such-Parameter wie \\\"{0}\\\" enthalten.\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Die Basis-URL kann keine Hashes wie \\\"{0}\\\" enthalten.\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Sonderzeichen wie \\\"{0}\\\" müssen %-kodiert werden.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Unbekannter Fehler beim Verarbeiten der Basis-URL\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Öffnen Sie eine Datei, während diese Ansicht fokussiert ist</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Diese Ansicht nach {0} verschieben\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Aktuelles Design\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Scrollbars vom Design verwenden\",\n    \"FONT_SIZE\"                            : \"Schriftgröße\",\n    \"FONT_FAMILY\"                          : \"Schriftart\",\n    \"THEMES_SETTINGS\"                      : \"Design-Einstellungen\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Neue Regel\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Installieren\",\n    \"UPDATE\"                               : \"Aktualisieren\",\n    \"REMOVE\"                               : \"Entfernen\",\n    \"DISABLE\"                              : \"Deaktivieren\",\n    \"ENABLE\"                               : \"Aktivieren\",\n    \"OVERWRITE\"                            : \"Überschreiben\",\n    \"CANT_REMOVE_DEV\"                      : \"Erweiterungen im \\\"dev\\\"-Ordner müssen manuell gelöscht werden.\",\n    \"CANT_UPDATE\"                          : \"Das Update ist nicht kompatibel mit dieser Version von {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Erweiterungen im \\\"dev\\\"-Ordner können nicht automatisch aktualisiert werden.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Erweiterung installieren\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Erweiterung aktualisieren\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Erweiterungs-URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL der Erweiterungs-ZIP-Datei oder GitHub-Repo\",\n    \"INSTALLING_FROM\"                      : \"Erweiterung installieren von {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installation abgeschlossen!\",\n    \"INSTALL_FAILED\"                       : \"Installation fehlgeschlagen.\",\n    \"CANCELING_INSTALL\"                    : \"Abgebrochen\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Das Abbrechen der Installation nimmt bereits einige Minuten in Anspruch. Ein interner Fehler könnte aufgetreten sein.\",\n    \"INSTALL_CANCELED\"                     : \"Installation abgebrochen.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Komplette Beschreibung anzeigen\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Gekürzte Beschreibung anzeigen\",\n    \"SORT_EXTENSION_METHOD\"                : \"Erweiterungen nach Downloadzahl oder Veröffentlichungsdatum sortieren\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Der heruntergeladene Inhalt ist keine gültige ZIP-Datei.\",\n    \"MISSING_PACKAGE_JSON\"                 : \"Die package.json-Datei ist nicht vorhanden.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Die package.json-Datei ist ungültig (Fehler: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Die package.json-Datei hat keinen definierten Paketnamen.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} ist ein ungültiger Paketname.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Die package.json-Datein hat keine definierte Paketversion.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Die Paket-Versionsnummer ({0}) ist ungültig.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Die {APP_NAME}-Kompatibilitäts-Zeichenkette ({0}) ist ungültig.\",\n    \"DISALLOWED_WORDS\"                     : \"Die Wörter ({1}) sind im Feld {0} nicht erlaubt.\",\n    \"NPM_INSTALL_FAILED\"                   : \"Der Befehl 'npm install' ist fehlgeschlagen: {0}\",\n    \"API_NOT_COMPATIBLE\"                   : \"Die Erweiterung ist nicht mit der aktuellen Version von {APP_NAME} kompatibel. Die Erweiterung wurde in den Ordner für die deaktivierten Erweiterungen installiert.\",\n    \"MISSING_MAIN\"                         : \"Das Paket hat keine main.js-Datei.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Durch die Installation dieses Pakets wird eine zuvor installierte Erweiterung überschrieben. Alte Erweiterung überschreiben?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Dieses Paket ist die gleiche Version wie die bereits installierte. Bestehende Installation überschreiben?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Dieses Paket ist die Version {0}, die älter ist als die aktuell installierte ({1}). Bestehende Installation überschreiben?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Interner Fehler: Download-ID wird schon verwendet.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Verbindung konnte nicht hergestellt werden.\",\n    \"BAD_HTTP_STATUS\"                      : \"Die Datei wurde auf dem Server nicht gefunden (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Konnte den Download nicht in einer temporären Datei speichern.\",\n    \"ERROR_LOADING\"                        : \"Beim Starten der Erweiterung ist ein Fehler aufgetreten.\",\n    \"MALFORMED_URL\"                        : \"Die URL ist ungültig. Bitte prüfen Sie, ob es sich um eine gültige URL handelt.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"Bitte geben Sie eine http- oder https-URL an.\",\n    \"UNKNOWN_ERROR\"                        : \"Unbekannter (interner) Fehler.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Erweiterungs-Verwaltung\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Fehler beim Zugriff auf das Verzeichnis der Erweiterungen. Bitte später erneut versuchen.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \".zip hierhin ziehen oder\",\n    \"INSTALL_EXTENSION_DROP\"               : \".zip zum Installieren ablegen\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Das Installieren/Aktualisieren schlug fehl, da die folgenden Fehler aufgetreten sind:\",\n    \"INSTALL_FROM_URL\"                     : \"von URL installieren\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Überprüfen\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Datum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Diese Erweiterung benötigt eine neuere Version von {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Diese Erweiterung funktioniert momentan nur mit älteren Versionen von {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Die Version {0} dieser Erweiterung benötigt eine neuere Version von {APP_NAME}. Sie können jedoch die ältere Version {1} installieren.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Die Version {0} dieser Erweiterung funktioniert nur mit älteren Versionen von {APP_NAME}. Sie können jedoch die ältere Version {1} installieren.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Keine Beschreibung\",\n    \"EXTENSION_MORE_INFO\"                  : \"Mehr Informationen\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Erweiterungs-Fehler\",\n    \"EXTENSION_KEYWORDS\"                   : \"Schlüsselwörter\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"In {0} Sprachen, inklusive Ihrer, übersetzt\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"In {0} Sprachen übersetzt\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Die Erweiterung wurde in diese Sprachen übersetzt: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Installiert\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Dieses Erweiterungs-Update wurde heruntergeladen und wird installiert, wenn {APP_NAME} neu geladen wird.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Suchen\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Mehr\",\n    \"BROWSE_EXTENSIONS\"                    : \"Erweiterungen durchsuchen\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Erweiterung entfernen\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Fehler beim Entfernen der Erweiterung: {0}. {APP_NAME} wird trotzdem neu geladen.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Erweiterung aktualisieren\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Fehler beim Update einer oder mehrerer Erweiterung(en): {0}. {APP_NAME} wird trotzdem neu geladen.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Erweiterung deaktivieren\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Fehler beim Deaktivieren einer oder mehrerer Erweiterung(en): {0}. {APP_NAME} wird trotzdem neu geladen.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Zur Entfernung markiert\",\n    \"UNDO_REMOVE\"                          : \"Rückgängig\",\n    \"MARKED_FOR_UPDATE\"                    : \"Zum Update markiert\",\n    \"UNDO_UPDATE\"                          : \"Rückgängig\",\n    \"MARKED_FOR_DISABLING\"                 : \"Zum Deaktivieren markiert\",\n    \"UNDO_DISABLE\"                         : \"Rückgängig\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Erweiterungen ändern\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Um die markierten Erweiterungen zu aktualisieren, entfernen oder deaktivieren, muss {APP_NAME} neu geladen werden. Sie werden gefragt, ob ungespeicherte Änderungen gespeichert werden sollen.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Erweiterungen entfernen und neu laden\",\n    \"CHANGE_AND_RELOAD\"                    : \"Erweiterungen ändern und neu laden\",\n    \"UPDATE_AND_RELOAD\"                    : \"Erweiterungen aktualisieren und neu laden\",\n    \"DISABLE_AND_RELOAD\"                   : \"Erweiterungen deaktivieren und neu laden\",\n    \"PROCESSING_EXTENSIONS\"                : \"Erweiterungs-Änderungen werden verarbeitet\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Die Erweiterung {0} konnte nicht entfernt werden, weil sie nicht installiert ist.\",\n    \"NO_EXTENSIONS\"                        : \"Momentan sind keine Erweiterungen installiert.<br>Klicken Sie oben auf den Tab \\\"Verfügbar\\\", um zu beginnen.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Keine Erweiterungen passen auf Ihre Suchanfrage.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"ACHTUNG: Diese Erweiterungen stammen nicht unbedingt von den Machern von {APP_NAME}. Erweiterungen werden nicht überprüft und haben uneingeschränkte lokale Rechte. Seien Sie vorsichtig, wenn Sie Erweiterungen aus unbekannter Quelle installieren.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Installiert\",\n    \"EXTENSIONS_DEFAULT_TITLE\"             : \"Standard\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Verfügbar\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Designs\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Updates\",\n    \"EXTENSIONS_LAST_UPDATED\"              : \"Zuletzt aktualisiert\",\n    \"EXTENSIONS_DOWNLOADS\"                 : \"Downloads\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Keine Ergebnisse verfügbar.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Alle Ergebnisse sind ausglendet. Klicken Sie auf die rechts gelisteten Dateien, um die dazugehörigen Ergebnisse anzuzeigen.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Es gibt keine CSS-Regeln, die zu Ihrer Auswahl passen.<br> Klicken Sie auf \\\"Neue Regel\\\", um eine neue Regel zu erstellen.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Es gibt keine Stylesheets in Ihrem Projekt.<br>Erstellen Sie eines, um CSS-Regeln hinzuzufügen.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"größtes\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"Pixel\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"Fehler\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Entwicklungswerkzeuge zeigen\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Mit Erweiterungen neu laden\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Ohne Erweiterungen neu laden\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Neues {APP_NAME}-Fenster\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Kommandozeilenverknüpfung einrichten\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Sprache wechseln\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Tests durchführen\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Performance-Analyse\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Node-Debugger aktivieren\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Node-Status in Konsole anzeigen\",\n    \"CMD_RESTART_NODE\"                          : \"Node neu starten\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Zeige Fehler in der Statusleiste\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"{APP_NAME}-Quellcode anzeigen\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME}-Befehlszeilenverknüpfung\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Beim Einrichten der Befehlszeilenverknüpfung ist ein Fehler aufgetreten. Bitte probieren Sie <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>diese Schritte zur Fehlerbehebung</a>.<br/><br/>Fehler: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Die aktuelle symbolische Verknüpfung <code>/usr/local/bin/brackets</code> konnte nicht entfernt werden.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Das Verzeichnis <code>/usr/local/bin</code> konnte nicht erstellt werden.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Die symbolische Verknüpfung <code>/usr/local/bin/brackets</code> konnte nicht erstellt werden.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Interner Fehler.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Eine Befehlszeilenverknüpfung wird unter diesem Betriebssystem nicht unterstützt.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Einrichtung erfolgreich! Sie können {APP_NAME} nun ganz einfach von der Befehlszeile aus starten: <code<brackets myFile.txt</code>, um eine Datei zu öffnen oder <code>brackets myFolder</code>, um das geöffnete Projekt zu ändern.<br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Erfahre mehr</a> über das Nutzen von {APP_NAME} über die Befehlszeile.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Sprache wechseln\",\n    \"LANGUAGE_MESSAGE\"                          : \"Sprache:\",\n    \"LANGUAGE_SUBMIT\"                           : \"{APP_NAME} neu starten\",\n    \"LANGUAGE_CANCEL\"                           : \"Abbrechen\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Systemstandard\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Statusbericht-Einstellungen\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME}-Statusbericht\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Anonyme Informationen über meine {APP_NAME}-Nutzung teilen\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Um {APP_NAME} zu verbessern, werden in regelmäßigen Zeitabständen <strong>anonyme</strong> Statistiken über Ihre {APP_NAME}-Nutzung an Adobe gesendet. Diese Informationen helfen dabei, Funktionen zu priorisieren sowie Bugs und Bedienungsprobleme aufzuspüren.<br><br>Sie können die Daten, die gesendet werden, jederzeit einsehen und das Teilen von Daten abstellen, indem Sie <strong>Hilfe > Statusbericht</strong> aufrufen.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Mehr über den {APP_NAME}-Statusbericht erfahren</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME}-Statusbericht\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Um {APP_NAME} zu verbessern, werden in regelmäßigen Zeitabständen beschränkte, <strong>anonyme</strong> Statistiken über Ihre {APP_NAME}-Nutzung an Adobe gesendet. Diese Informationen helfen dabei, Funktionen zu priorisieren sowie Bugs und Bedienungsprobleme aufzuspüren. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Erfahre mehr über den {APP_NAME}-Statusbericht</a> und darüber, wie dieser der {APP_NAME}-Community hilft, während er gleichzeitig Privatsphäre gewährt.</p><p>Unten sehen Sie die Daten, die mit dem nächsten Statusbericht gesendet werden, <em>wenn</em> dieser aktiviert ist.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Zeit\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Verlauf\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Ausgewählten Punkt bewegen<br><kbd class='text'>Umschalt</kbd> Um 10 Einheiten bewegen<br><kbd class='text'>Tab</kbd> Zwischen Punkten wechseln\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Stufenzahl vergrößern oder verkleinern<br><kbd>←</kbd><kbd>→</kbd> 'Start' oder 'Ende'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Der Code im Dokument <code>{0}</code> ist nicht korrekt, daher wird die Funktion <code>{1}</code> angezeigt. Die Änderungen werden bei der ersten Bearbeitung ins Dokument übernommen.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Aktuelle Farbe\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Original-Farbe\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa-Format\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex-Format\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa-Format\",\n    \"COLOR_EDITOR_0X_BUTTON_TIP\"                : \"Hex-Format (0x)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} ({1} Mal verwendet)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} ({1} Mal verwendet)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Springe zur Definition\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Parameter-Hinweis anzeigen\",\n    \"NO_ARGUMENTS\"                              : \"<keine Parameter>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problem mit einer JavaScript-Datei\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} hat Probleme damit, <span class='dialog-filename'>{0}</span> zu verarbeiten.<br><br>Code Hints, Springen zur Definition und Schnelles Bearbeiten werden für die Datei nicht mehr bereitgestellt. Öffnen Sie <code>.brackets.json</code> in diesem Projekt und entfernen Sie den Dateipfad von <code>jscodehints.detectedExclusions</code>, um diese Datei wieder einzuschließen.<br><br>Das ist wahrscheinlich ein Bug in {APP_NAME}. <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>Melden Sie den Fehler</a> bitte, falls Sie eine Kopie dieser Datei bereitstellen können. Verlinken Sie in diesem Fall die oben genannte Datei.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Schnelle Farbansicht\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Zuletzt verwendete Projekte\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Weiterlesen\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Alle einklappen\",\n    \"EXPAND_ALL\"                    : \"Alle ausklappen\",\n    \"COLLAPSE_CURRENT\"              : \"Aktuelle einklappen\",\n    \"EXPAND_CURRENT\"                : \"Aktuelle ausklappen\",\n    \n    // extensions/default/NavigationAndHistory\n    \"RECENT_FILES_DLG_HEADER\"                    : \"Kürzlich verwendete Dateien\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\"        : \"Leeren\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\"        : \"Entferne alle Dateien aus der Liste, die nicht im Projekt geöffnet sind\",\n    \n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"Aktiviert das automatische Schließen von runden, eckigen und geschweiften Klammern\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"Aktiviert den Eintrag \\\"Alle darüber schließen\\\" im Kontextmenü der Offenen Dateien\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"Aktiviert den Eintrag \\\"Alle darunter schließen\\\" im Kontextmenü der Offenen Dateien\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"Aktiviert den Eintrag \\\"Alle anderen schließen\\\" im Kontextmenü der Offenen Dateien\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Optionen für die \\\"Tags automatisch schließen\\\"-Funktion\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Ein Array von Tags, die nicht automatisch geschlossen werden sollen\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Tag beim Eingeben von > vom öffnenden Tag schließen\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Tag beim Eingeben von / vom schließenden Tag schließen\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Ein Array von Tags, die einen Zeilenumbruch auslösen\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"Immer einklappbare Folding-Markierungen anzeigen, wenn sich der Zeileneinzug ändert\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"Aktiviert Code Folding\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"Einklappbare Folding-Markierungen nur anzeigen, wenn sich die Maus über dem linken Zeilenrand befindet\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limitiert die maximale Anzahl von \\\"Alle Einklappen\\\"-Markierungen\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Mindestzahl an Zeilen, bevor eine einklappbare Folding-Markierung erscheint\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"Aktiviert das Speichern der eingeklappten Abschnitte\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"Aktiviert das Einklappen von ausgewähltem Text\",\n    \"DESCRIPTION_DISABLED_DEFAULT_EXTENSIONS\"        : \"Standardmäßig installierte Erweiterungen, die deaktiviert sind\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Aktiviert Code Hints für HTML-Attribute\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Aktiviert Code Hints für CSS/LESS/SCSS\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Aktiviert Code Hints für JavaScript\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Zeigt Details zum Datentyp in den Code Hints für JavaScript\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Aktiviert Code Hints für Einstellungen\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Aktiviert Code Hints für HTML Entities\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Aktiviert Code Hints für SVG\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Aktiviert Code Hints für HTML-Tags\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Aktiviert Code Hints für URLs in HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Aktiviert Drag & Drop\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Aktiviert das Übermitteln des {APP_NAME}-Statusberichts\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Aktiviert die Hervorhebung von Vorkommnissen des markierten Worts im Dokument\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Hervorheben aller Vorkommnisse des Wortes, auf dem sich der Cursor befindet (keine Auswahl benötigt)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Nur hervorheben, wenn die Auswahl ein komplettes Wort umfasst\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"Aktiviert das Akzeptieren eines Code Hints mithilfe der Tab-Taste\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"Deaktiviert das automatische Anzeigen der JavaScript Code Hints, sobald . eingegeben wird\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Ein Objekt, das die Standardeinstellungen für JSLint festlegt\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"Ausdrücke mit Zuweisungen erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"Bitweise Operatoren erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"Die Verwendung von globalen Variablen, die im Browser standardmäßig verfügbar sind, erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"Google Closure-Anmerkungen erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"\\\"continue\\\"-Anweisungen erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"Die Verwendung von globalen Variablen, die in Verbindung mit CouchDB verfügbar sind, erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"\\\"debugger\\\"-Anweisungen erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"Die Verwendung von globalen Variablen, die bei der Entwicklung hilfreich sind, erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"== und != erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"Die Verwendung von globalen Variablen, die Bestandteil von ES6 sind, erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"eval erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"\\\"for ... in\\\" ohne weitere Prüfung erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Festlegen einer bestimmten Tab-Schrittweite bzw. Anzahl an Leerzeichen\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Maximale Anzahl an Warnungen\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Maximale Anzahl an Zeichen in einer Zeile\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"Kleingeschriebene Konstruktoren erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"Die Verwendung von globalen Variablen, die in Node.js standardmäßig verfügbar sind, erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"Unterstrich am Beginn oder Ende eines Bezeichners erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"Beim ersten Fehler stoppen\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"++ und -- erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \". und [^...] in regulären Ausdrücken erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"Die Verwendung von globalen Variablen, die in Rhino standardmäßig verfügbar sind, erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"Fehlen von `use strict` erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"Die Nutzung blockierender Funktionen ('...Sync') erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"Ineffizientes Subscripting erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"TODO-Kommentare erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"Unbenutzte Funktionsparameter erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"Mehr als 1 Variable in Funktionen erlauben\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"Regeln für Whitespace ignorieren\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Sprachspezifische Einstellungen\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Zusätzliche Zuordnungen von Dateierweiterung zu Programmiersprache\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Zusätzliche Zuordnungen von Dateiname zu Programmiersprache\",\n    \"DESCRIPTION_LINEWISE_COPY_CUT\"                  : \"Kopieren und Ausschneiden ohne Auswahl kopiert alle Zeilen mit Cursor bzw. schneidet diese aus\",\n    \"DESCRIPTION_INPUT_STYLE\"                        : \"Die Art, wie CodeMirror mit Eingaben und Auswahlen umgeht. Kann 'textarea' (Standard) oder 'contenteditable' sein, wobei letzteres besser für Screenreader geeignet ist\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"Aktiviert Linten beim Speichern\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Die Zeitbegrenzung in Millisekunden, nach der asynchrone Linter gestoppt werden\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Array der Linter, die als erstes ausgeführt werden\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"Aktiviert die experimentelle Live-Vorschau\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"Nur die in linting.prefer angegebenen Linter ausführen\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Maximale Anzahl an Code Hints, die gleichzeitig angezeigt werden\",\n    \"DESCRIPTION_PATH\"                               : \"Pfadspezifische Einstellungen\",\n    \"DESCRIPTION_PROXY\"                              : \"URL des Proxyservers, der bei der Installation von Erweiterungen verwendet wird\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"Aktiviert Scrollen über das Ende des Dokuments hinaus\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"Aktiviert Code Hints\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Der Cursor wird auch angezeigt, wenn eine Auswahl besteht\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"Zeigt Zeilennummern am linken Zeilenrand an\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Aktiviert das automatische Einrücken von neuen Blocks\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"Aktiviert die \\\"Soft Tabs\\\"-Navigation\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"Aktiviert, dass Ordner im Dateibaum vor Dateien aufgelistet werden\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Anzahl der Leerzeichen beim Einrücken, wenn Leerzeichen verwendet werden\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Port, der vom internen Server für die Live-Vorschau verwendet wird\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"Aktiviert das Hervorheben der aktiven Zeile\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Anzahl der Leerzeichen, die für Tabs angezeigt werden\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"Tabs anstelle von Leerzeichen verwenden\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"Erzeugt großgeschriebene Hex-Werte im Farbeditor\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Aktiviert Zeilenumbruch für lange Zeilen\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Ein Array von Dateien, für die erkannt wurde, dass Tern durch sie außer Kontrolle gerät\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Das Zeitlimit, nach dem Tern stoppt zu versuchen, Dateien zu verstehen\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"Aktiviert die Anzeige von Fehlern in der Statusleiste\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"Aktiviert die Schnelle Farbansicht\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"Aktiviert die Bildvorschau auch bei URLs, die keine Dateierweiterung haben\",\n    \"DESCRIPTION_THEME\"                              : \"Wählen eines {APP_NAME}-Designs\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"Erlaubt die Verwendung der Scrollbars vom Design\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"Das Linter-Panel einklappen\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Schriftart ändern\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Schriftgröße ändern; z. B. 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"Aktiviert die Node-basierte Suche\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"Aktiviert die Sofortsuche\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Nur Mac: \\\"subpixel-antialiased\\\", um Subpixel-Antialiasing zu aktivieren, oder \\\"antialiased\\\" für Graustufen-Antialiasing\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"Aktiviert das Öffnen der Einstellungsdatei in einer geteilten Ansicht\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"Öffnet die Einstellungsdatei in der rechten bzw. unteren Ansicht\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"Eine Ansicht einer geteilten Ansicht wird automatisch geschlossen, wenn ihre letzte Datei mit dem Schließen-Button oben rechts geschlossen wird\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Zeigt bei der geteilten Ansicht die Schließen- und Umschalten-Buttons in der Kopfzeile\",\n\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Dies ist ein schreibgeschütztes Dokument, das alle von\\n * {APP_NAME} unterstützten Einstellungen auflistet.\\n * Nutzen Sie dieses Dokument als Referenz, um die\\n * Einstellungsdatei \\\"brackets.json\\\", die in der anderen\\n * Ansicht geöffnet ist, anzupassen.\\n * Besuchen Sie auch https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences,\\n * um mehr über den Umgang mit Einstellungen in {APP_NAME}\\n * zu erfahren.\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Standard\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"Aktiviert den Ablenkungsfreien Modus, bei dem alle UI-Elemente außer dem Code ausgeblendet werden\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"Aktiviert das Einrücken von Zeilenkommentaren\",\n    \"DESCRIPTION_RECENT_FILES_NAV\"                   : \"Aktiviert das Navigieren durch kürzlich verwendete Dateien\",\n    \"DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\"             : \"Der Port, der für den WebSocket-Server der Live-Vorschau genutzt wird\",\n    \"DESCRIPTION_LIVE_DEV_HIGHLIGHT_SETTINGS\"        : \"Live-Vorschau Highlight-Einstellungen\"\n});\n\n/* Last translated for ae015b5be491e1d97d86b1f7f4fd352157063110 */\n"
  },
  {
    "path": "src/nls/de/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"de/Erste Schritte\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_de/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.de\"\n});\n"
  },
  {
    "path": "src/nls/el/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(error {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Το αρχείο δεν βρέθηκε.\",\n    \"NOT_READABLE_ERR\"                  : \"Το αρχείο δεν μπορεί να διαβαστεί.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Αρχεία που ξεπερνούν τα {0} MB δεν μπορούν να ανοίξουν στο {APP_NAME}.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Το αρχείο έχει τροποποιηθεί εκτός του {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Ο φάκελος δεν μπορεί να τροποποιηθεί.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Δεν επιτρέπεται να κάνεις τροποποιήσεις.\",\n    \"FILE_EXISTS_ERR\"                   : \"Αυτό το αρχείο ή ο φάκελος υπάρχουν ήδη.\",\n    \"FILE\"                              : \"αρχείο\",\n    \"FILE_TITLE\"                        : \"Αρχείο\",\n    \"DIRECTORY\"                         : \"φάκελος\",\n    \"DIRECTORY_TITLE\"                   : \"Φάκελος\",\n    \"FILENAMES_LEDE\"                    : \"Ονόματα αρχείων\",\n    \"FILENAME\"                          : \"Όνομα αρχείου\",\n    \"DIRECTORY_NAME\"                    : \"Όνομα φακέλου\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Σφάλμα φόρτωσης project\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Σφάλμα προέκυψε κατά τη διαδικασία εμφάνισης του παραθύρου ανοίγματος αρχείου. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Σφάλμα προέκυψε κατά τη διαδικασία φόρτωσης του φακέλου <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Σφάλμα προέκυψε κατά τη διαδικασία διαβάσματος των περιεχομένων του φακέλου <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Σφάλμα ανοίγματος αρχείου\",\n    \"ERROR_OPENING_FILE\"                : \"Σφάλμα προέκυψε κατά τη διαδικασία ανοίγματος του αρχείου <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Σφάλμα προέκυψε κατά τη διαδικασία ανοίγματος των παρακάτω αρχείων:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Σφάλμα επαναφόρτωσης αλλαγών από το δίσκο\",\n    \"ERROR_RELOADING_FILE\"              : \"Σφάλμα προέκυψε κατά τη διαδικασία επαναφόρτωσης του αρχείου <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Σφάλμα αποθήκευσης αρχείου\",\n    \"ERROR_SAVING_FILE\"                 : \"Σφάλμα προέκυψε κατά τη διαδικασία αποθήκευσης του αρχείου <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Σφάλμα μετονομασίας αρχείου\",\n    \"ERROR_RENAMING_FILE\"               : \"Σφάλμα προέκυψε κατά τη διαδικασία μετονομασίας αρχείου <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Σφάλμα διαγραφής αρχείου\",\n    \"ERROR_DELETING_FILE\"               : \"Σφάλμα προέκυψε κατά τη διαδικασία διαγραφής του αρχείου <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Μη έγκυρο {0} όνομα\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Τα όνομα αρχείων δεν μπορούν να περιέχουν τους ακόλουθους χαρακτήρες: {0} ή οποιεσδήποτε system reserved λέξεις.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Σφάλμα δημιουργίας {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Σφάλμα προέκυψε κατά τη διαδικασία δημιουργίας του {0} <span class='dialog-filename'>{1}</span>. {2}\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ουπς! Το {APP_NAME} δεν τρέχει ακόμα σε browsers.\",\n    \"ERROR_IN_BROWSER\"                  : \"To {APP_NAME} είναι γραμμένο σε HTML, αλλά αυτή τη στιγμή τρέχει σαν native εφαρμογή έτσι ώστε να μπορείτε να επεξεργαστείτε τοπικά αρχεία. Παρακαλούμε να χρησιμοποιήσετε το application shell στο <b>github.com/adobe/brackets-shell</b> repo για να τρέξετε το {APP_NAME}.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Σφάλμα κατά τη διαδικασία indexing των αρχείων\",\n    \"ERROR_MAX_FILES\"                   : \"Ο μέγιστος αριθμός αρχείων έχει καταχωρηθεί index. Λειτουργίες που ψάχνουν αρχεία στο index μπορεί να μην δουλεύουν σωστά.\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Σφάλμα ανοίγματος browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Ο Google Chrome browser δεν βρέθηκε. Παρακαλούμε σιγουρευτείτε ότι είναι εγκατεστημένος.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Σφάλμα προέκυψε κατά τη διαδικασία ανοίγματος του browser. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Σφάλμα Live Preview\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Σύνδεση στον Browser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Για να συνδεθεί το Live Preview, ο Chrome πρέπει να επανεκκινηθεί με το remote debugging (απομακρυσμένη αποσφαλμάτωση) ενεργοποιημένο.<br /><br />Θέλετε να επανεκκινήσετε τον Chrome και να ενεργοποιήσετε το remote debugging;\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Αδυναμία φόρτωσης της σελίδας Live Development\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Ανοίξτε ένα αρχείο HTML έτσι ώστε να ξεκινήσει η άμεση προεπισκόπηση (Live Preview).\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Για να ανοίξετε το Live Preview με ένα αρχείο από κάποιον server, πρέπει να προσδιορίσετε μια διεύθυνση (Base URL) για αυτό το project.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Σφάλμα κατά τη διαδικασία εκκίνησης του HTTP server για την άμεση επεξεργασία αρχείων. Παρακαλούμε προσπαθήστε ξανά.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Καλώς ήρθατε στο Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Το Live Preview συνδέει το {APP_NAME} με τον browser σας. Ανοίγει μια προεπισκόπηση του HTML αρχείου σας στον browser, και την ανανεώνει στιγμιαία ενώ επεξεργάζεστε τον κώδικα.<br /><br />Σε τούτη την πρώιμη έκδοση του {APP_NAME}, το Live Preview δουλεύει μόνο με <strong>Google Chrome</strong> και ανανεώνει άμεσα την σελίδα ενώ επεξεργάζεστε <strong>αρχεία CSS ή HTML</strong>. Αλλαγές σε αρχεία JavaScript ανανεώνονται αυτόματα όταν κάνετε αποθήκευση.<br /><br />(Το μήνυμα αυτό θα αυτοκαταστραφεί μετά την πρώτη εμφάνιση του.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Για περισσότερες πληροφορίες δείτε εδώ: <a href='{0}' title='{0}'>Troubleshooting Live Development connection errors</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: Σύνδεση\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: Εκκίνηση\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Αποσύνδεση Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview (κάντε αποθήκευση για να ανανεωθεί)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Preview (αδυναμία ανανέωσης λόγο συντακτικού λάθους)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Το Live Preview ακυρώθηκε επειδή τα developer tools του browser ανοίχτηκαν\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Το Live Preview ακυρώθηκε επειδή η σελίδα στον browser έκλεισε\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Το Live Preview ακυρώθηκε επειδή ο browser πήγε σε μια σελίδα που δεν είναι μέρος του τρέχων project\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Το Live Preview ακυρώθηκε. Δεν ξέρουμε γιατί. ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Αποθήκευση Αλλαγών\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Θέλετε να αποθηκεύσετε τις αλλαγές που κάνατε στο έγγραφο <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Θέλετε να αποθηκεύσετε τις αλλαγές σας στα παρακάτω αρχεία;\",\n    \"EXT_MODIFIED_TITLE\"                : \"Εξωτερικές Αλλαγές\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Επιβεβαίωση Διαγραφής\",\n    \"CONFIRM_FILE_DELETE\"               : \"Είστε σίγουρος ότι θέλετε να διαγράψε το αρχείο <span class='dialog-filename'>{0}</span>?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Είστε σίγουρος ότι θέλετε να διαγράψετε τον φάκελο <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Το Αρχείο Διαγράφηκε\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"Το <span class='dialog-filename'>{0}</span> έχει τροποποιηθεί στο δίσκο, αλλά υπάρχουν και μη αποθηκευμένες αλλαγές στο {APP_NAME}.<br /><br />Ποια έκδοση θέλετε να κρατήσετε;\",\n    \"EXT_DELETED_MESSAGE\"               : \"Το <span class='dialog-filename'>{0}</span> έχει διαγραφεί στον δίσκο, αλλά έχει μη αποθηκευμένες αλλαγές στο {APP_NAME}.<br /><br />Θέλετε να κρατήσετε τις αλλαγές σας;\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} από {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Δεν βρέθηκαν αποτελέσματα\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Εύρεση\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Αντικατάσταση με\\u2026\",\n    \"BUTTON_YES\"                        : \"Ναι\",\n    \"BUTTON_NO\"                         : \"Όχι\",\n    \"BUTTON_REPLACE_ALL\"                : \"Όλα\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Αντικατάσταση\",\n    \"BUTTON_REGEXP_HINT\"                : \"Κανονική έκφραση\",\n\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Επόμενη Αντιστοιχία\",\n    \"BUTTON_PREV_HINT\"                  : \"Προηγούμενη Αντιστοιχία\",\n\n    \"OPEN_FILE\"                         : \"Άνοιγμα Αρχείου\",\n    \"SAVE_FILE_AS\"                      : \"Αποθήκευση Αρχείου\",\n    \"CHOOSE_FOLDER\"                     : \"Επίλεξε ένα φάκελο\",\n\n    \"RELEASE_NOTES\"                     : \"Release Notes\",\n    \"NO_UPDATE_TITLE\"                   : \"Έχετε την τελευταία έκδοση!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Τρέχετε την τελευταία έκδοση του {APP_NAME}.\",\n    \n    //Find and replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Αντικατάσταση\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"με\",\n\n    \"FIND_IN_FILES_SCOPED\"              : \"στο <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"στο project\",\n    \"FIND_IN_FILES_FILE\"                : \"αρχείο\",\n    \"FIND_IN_FILES_FILES\"               : \"αρχεία\",\n    \"FIND_IN_FILES_MATCH\"               : \"αντιστοιχία\",\n    \"FIND_IN_FILES_MATCHES\"             : \"αντιστοιχίες\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Πάνω από \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We shoudl use normal dashes on Windows instead of em dash eventually\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Αντικατάσταση λαθών\",\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Σφάλμα λήψης πληροφοριών αναβάθμισης\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Προέκυψε σφάλμα κατά τη διαδικασία λήψης πληροφοριών της τελευταίας αναβάθμισης από τον server. Παρακαλούμε βεβαιωθείτε ότι είστε συνδεδεμένος στο internet και προσπαθήστε ξανά.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Φόρτωση\\u2026\",\n    \"UNTITLED\"          : \"Άτιτλο\",\n    \"WORKING_FILES\"     : \"Αρχεία Εργασίας\",\n\n   \n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Σειρά {0}, Στήλη {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 επιλεγμένη {0} στήλη\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 επιλεγμένες {0} στήλες\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 επιλεγμένη {0} γραμμή\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 επιλεγμένες {0} γραμμές\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} επιλογές\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Κάντε κλικ για να αλλάξετε τις εσοχές (indentation) σε κενά\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Κάντε κλικ για να αλλάξετε τις εσοχές (indentation) σε tabs\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Κάντε κλικ για να αλλάξετε τον αριθμό των κενών στις εσοχές\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Κάντε κλικ για να αλλάξετε το πλάτος του tab\",\n    \"STATUSBAR_SPACES\"                      : \"Κενά:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Μέγεθος Tab:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Γραμμή\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Γραμμές\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Οι επεκτάσεις απενεργοποιήθηκαν\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Κάνε κλικ για να αλλάξεις τον τύπο του αρχείου\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Ορισμός ως προεπιλογή για .{0} αρχεία\",\n\n    // CodeInspection: errors/warnings\n    \"SINGLE_ERROR\"                          : \"1 {0} Σφάλμα\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} Σφάλματα\",\n    \"NO_ERRORS\"                             : \"Καθόλου {0} σφάλματα - καλή δουλειά!\",\n    \"LINT_DISABLED\"                         : \"Το Linting είναι απενεργοποιημένο\",\n    \"NO_LINT_AVAILABLE\"                     : \"Δεν υπάρχει linter διαθέσιμος για {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Δεν υπάρχει κάτι για να γίνει lint\",\n    \"LINTER_FAILED\"                         : \"{0} τερμάτισε με σφάλμα: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Αρχείο\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Νέο\",\n    \"CMD_FILE_NEW\"                        : \"Νέο Αρχείο\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Νέος Φάκελος\",\n    \"CMD_FILE_OPEN\"                       : \"Άνοιγμα\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Προσθήκη στα Αρχεία Εργασίας\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Άνοιγμα Αρχείων που ρίχτηκαν\",\n    \"CMD_OPEN_FOLDER\"                     : \"Άνοιγμα Φακέλου\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Κλείσιμο\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Κλείσιμο Όλων\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Κλείσιμο Λίστας\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Κλείσιμο Άλλων\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Κλείσιμο Άλλων απο πάνω\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Κλείσιμο Άλλων από κάτων\",\n    \"CMD_FILE_SAVE\"                       : \"Αποθήκευση\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Αποθήκευση Όλων\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Αποθήκευση Ως\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Ρυθμίσεις Project\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Μετονομασία\",\n    \"CMD_FILE_DELETE\"                     : \"Διαγραφή\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Εγκατάσταση Επέκτασης (Extension)\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Διαχείρηση Επεκτάσεων\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Ανανέωση Δέντρου Αρχείων\",\n    \"CMD_QUIT\"                            : \"Κλείσιμο\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"΄Εξοδος\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Επεξεργασία\",\n    \"CMD_UNDO\"                            : \"Αναίρεση\",\n    \"CMD_REDO\"                            : \"Επανάληψη\",\n    \"CMD_CUT\"                             : \"Αποκοπή\",\n    \"CMD_COPY\"                            : \"Αντιγραφή\",\n    \"CMD_PASTE\"                           : \"Επικόλληση\",\n    \"CMD_SELECT_ALL\"                      : \"Επιλογή Όλων\",\n    \"CMD_SELECT_LINE\"                     : \"Επιλογή Γραμμής\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Προσθήκη κέρσοσα στην επόμενη γραμμή\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Προσθήκη κέρσοσα στην προηγούμενη γραμμή\",\n    \"CMD_FIND\"                            : \"Εύρεση\",\n    \"CMD_FIND_IN_FILES\"                   : \"Εύρεση σε Αρχεία\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Εύρεση σε\\u2026\",\n    \"CMD_FIND_NEXT\"                       : \"Εύρεση Επόμενου\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Εύρεση Προηγούμενου\",\n    \"CMD_REPLACE\"                         : \"Αντικατάσταση\",\n    \"CMD_INDENT\"                          : \"Εσοχή\",\n    \"CMD_UNINDENT\"                        : \"Αφαίρεση Εσοχής\",\n    \"CMD_DUPLICATE\"                       : \"Δημιουργία Αντιγράφου\",\n    \"CMD_DELETE_LINES\"                    : \"Διαγραφή Γραμμής\",\n    \"CMD_COMMENT\"                         : \"Εναλλαγή Σχολίου Γραμμής\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Εναλλαγή Σχολίου Block\",\n    \"CMD_LINE_UP\"                         : \"Μετακίνηση Γραμμής Πάνω\",\n    \"CMD_LINE_DOWN\"                       : \"Μετακίνηση Γραμμής Κάτω\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Δημιουργία Γραμμής από πάνω\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Δημιουργία Γραμμής από κάτω\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Αυτόματο Κλείσιμο Αγκίστρων\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Προβολή Υποδείξεων Κώδικα\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Προβολή\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Απόκρυψη Πλευρικής Εργαλειοθήκης\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Προβολή Πλευρικής Εργαλειοθήκης\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Αύξηση Μεγέθους Γραμματοσειράς\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Μείωση Μεγέθους Γραμματοσειράς\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Επαναφορά Μεγέθους Γραμματοσειράς\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Κύλιση Γραμμής Πάνω\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Κύλιση Γραμμής Κάτω\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Αριθμοί Γραμμών\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Επισήμανση Ενεργής Γραμμής\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Αναδίπλωση Λέξης\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Επισήμανση Live Preview\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Lint Αρχείων κατά την Αποθήκευση\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Ταξινόμηση κατά Σειρά Προσθήκης\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Ταξινόμηση κατά Όνομα\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Ταξινόμηση κατά Τύπο\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Αυτόματη Ταξινόμηση\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Πλοήγηση\",\n    \"CMD_QUICK_OPEN\"                      : \"Γρήγορο Άνοιγμα\",\n    \"CMD_GOTO_LINE\"                       : \"Πήγαινε στη γραμμή\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Γρήγορη Αναζήτηση Ορισμού\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Πήγαινε στο Πρώτο Σφάλμα/Προειδοποίηση\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Γρήγορη Επεξεργασία\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Γρήγορα Έγγραφα\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Προηγούμενη Αντιστοιχία\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Επόμενη Αντιστοιχία\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Νέος Κανόνας\",\n    \"CMD_NEXT_DOC\"                        : \"Επόμενο Έγγραφο\",\n    \"CMD_PREV_DOC\"                        : \"Προηγούμενο Έγγραφο\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Επόμενο έγγραφο στην λίστα\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Προηγούμενο έγγραφο στην λίστα\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Προβολή στο Δέντρο Αρχείων\",\n    \"CMD_SHOW_IN_OS\"                      : \"Προβολή στο Λειτουργικό Σύστημα\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Βοήθεια\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Έλεγχος για Αναβαθμίσεις\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Πώς να Χρησιμοποιήσετε το {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Υποστήριξη {APP_NAME}\",\n    \"CMD_RELEASE_NOTES\"                   : \"Release Notes\",\n    \"CMD_SUGGEST\"                         : \"Πρότεινε Feature\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} Αρχική σελίδα\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Προβολή Φακέλου Επεκτάσεων\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} στο Twitter\",\n    \"CMD_ABOUT\"                           : \"Σχετικά με το {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Άνοιξε το αρχείο προτιμήσεων\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimental build\",\n    \"DEVELOPMENT_BUILD\"                    : \"development build\",\n    \"OK\"                                   : \"OK\",\n    \"DONT_SAVE\"                            : \"Να Μην Αποθηκευτεί\",\n    \"SAVE\"                                 : \"Αποθήκευση\",\n    \"CANCEL\"                               : \"Ακύρωση\",\n    \"DELETE\"                               : \"Διαγραφή\",\n    \"RELOAD_FROM_DISK\"                     : \"Επαναφόρτωση από τον Δίσκο\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Διατήρηση Αλλαγών στον Επεξεργαστή\",\n    \"CLOSE_DONT_SAVE\"                      : \"Κλείσιμο (Να Μην Αποθηκευτεί)\",\n    \"RELAUNCH_CHROME\"                      : \"Επανεκκίνηση Chrome\",\n    \"ABOUT\"                                : \"Σχετικά\",\n    \"CLOSE\"                                : \"Κλείσιμο\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Πληροφορίες, όροι και οι προϋποθέσεις που αφορούν λογισμικό τρίτων κατασκευαστών βρίσκονται στο <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> και ενσωματώνονται εδώ με αναφορά.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentation και πηγαίος κώδικας στο <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Φτιαγμένο με \\u2764 και JavaScript από:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Πολλούς ανθρώπους (απλά αντιμετωπίζουμε ένα πρόβλημα με την φόρτωση των δεδομένων αυτήν την στιγμή).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"Τα MDN Docs και το MDN γραφικό logo είναι αδειοδοτημένα κάτω από την άδεια Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Υπάρχει ένα νέο build του {APP_NAME} διαθέσιμο! Πατήστε εδώ για λεπτομέρειες.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Διαθέσιμη Αναβάθμιση\",\n    \"UPDATE_MESSAGE\"                       : \"Ψιτ, υπάρχει ένα νέο build του {APP_NAME} διαθέσιμο. Μερικές από τις καινούργιες λειτουργίες:\",\n    \"GET_IT_NOW\"                           : \"Κατέβασε το τώρα!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Ρυθμίσεις Project για: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Live Preview Base URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Για να χρησιμοποιήσετε τοπικό server, εισάγετε μια διεύθυνση σαν και αυτή http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Το πρωτόκολλο {0} δεν υποστηρίζεται από το Live Preview&mdash;παρακαλούμε χρησιμοποιήστε http: ή https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Η διεύθυνση URL δεν μπορεί να περιέχει παραμέτρους αναζήτησης όπως \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Η διεύθυνση URL δεν μπορεί να περιέχει hashes σαν και αυτά \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Οι ειδικοί χαρακτήρες όπως '{0}' πρέπει να είναι %-encoded.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Άγνωστο σφάλμα κατά την προσπέλαση της διεύθυνσης URL\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Νέος Κανόνας\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Εγκατάσταση\",\n    \"UPDATE\"                               : \"Αναβάθμιση\",\n    \"REMOVE\"                               : \"Κατάργηση\",\n    \"OVERWRITE\"                            : \"Αντικατάσταση\",\n    \"DISABLE\"                              : \"Απενεργοποίηση\",\n    \"CANT_REMOVE_DEV\"                      : \"Οι επεκτάσεις στο φάκελο \\\"dev\\\" πρέπει να διαγραφούν χειροκίνητα.\",\n    \"CANT_UPDATE\"                          : \"Η αναβάθμιση δεν είναι συμβατή με αυτήν την έκδοση του {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Οι επεκτάσεις στον φάκελο \\\"dev\\\" δεν μπορούν να αναβαθμιστούν αυτόματα.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Εγκατάσταση Επέκτασης\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Αναβάθμιση Επέκτασης\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL Επέκτασης\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL αρχείου zip ή GitHub repo της επέκτασης\",\n    \"INSTALLING_FROM\"                      : \"Εγκατάσταση επέκτασης από {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Επιτυχής Εγκατάσταση!\",\n    \"INSTALL_FAILED\"                       : \"Ανεπιτυχής Εγκατάσταση .\",\n    \"CANCELING_INSTALL\"                    : \"Ακύρωση\\u2026\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Προβολή αναλυτικής περιγραφής\",\n    \"CANCELING_HUNG\"                       : \"Η ακύρωση της εγκατάστασης παίρνει πολύ ώρα. Κάποιο εσωτερικό σφάλμα μπορεί να έχει προκληθεί.\",\n    \"INSTALL_CANCELED\"                     : \"Η εγκατάσταση ακυρώθηκε.\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Το περιεχόμενο που κατέβηκε δεν είναι έγκυρο αρχείο zip.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Το αρχείο package.json δεν είναι έγκυρο (error was: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Το αρχείο package.json δεν καθορίζει όνομα πακέτου.\",\n    \"BAD_PACKAGE_NAME\"                     : \"Το {0} δεν είναι έγκυρο όνομα αρχείου.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Το αρχείο package.json δεν καθορίζει έκδοση πακέτου.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Ο αριθμός έκδοσης του πακέτου ({0}) δεν είναι έγκυρος.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Η συμβολοσειρά συμβατότητας (compatibility string) ({0}) του {APP_NAME} δεν είναι έγκυρη.\",\n    \"DISALLOWED_WORDS\"                     : \"Οι λέξεις ({1}) δεν επιτρέπονται στο πεδίο {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Η επέκταση δεν είναι συμβατή με αυτήν την έκδοση του {APP_NAME}. Εγκαταστάθηκε στον φάκελο των απενεργοποιημένων επεκτάσεων.\",\n    \"MISSING_MAIN\"                         : \"Το πακέτο δεν έχει main.js αρχείο.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Η εγκατάσταση αυτού του πακέτου θα αντικαταστήσει μια προηγούμενη εγκατάσταση επέκτασης. Να αντικατασταθεί η παλιά επέκταση;\",\n    \"EXTENSION_SAME_VERSION\"               : \"Αυτό το πακέτο είναι η ίδια έκδοση με αυτό που είναι ήδη εγκατεστημένο. Να αντικατασταθεί η υπάρχουσα εγκατάσταση;\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Αυτό το πακέτο είναι στην έκδοση {0} η οποία είναι παλιότερη από την τρέχουσα εγκατάσταση ({1}). Να αντικατασταθεί η υπάρχουσα εγκατάσταση;\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Εσωτερικό σφάλμα: το ID που κατέβηκε χρησιμοποιείται ήδη.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Αδυναμία σύνδεσης στον server.\",\n    \"BAD_HTTP_STATUS\"                      : \"Το αρχείο δεν βρέθηκε στον server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Αδυναμία αποθήκευσης του ληφθέντος αρχείου στο temp.\",\n    \"ERROR_LOADING\"                        : \"Η επέκταση αντιμετώπισε ένα σφάλμα κατά την εκκίνηση.\",\n    \"MALFORMED_URL\"                        : \"Η διεύθυνση URL δεν είναι έγκυρη is invalid. Please check that you entered it correctly.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"Η διεύθυνση URL πρέπει να είναι http ή https.\",\n    \"UNKNOWN_ERROR\"                        : \"Άγνωστο εσωτερικό σφάλμα.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Διαχειριστής Επεκτάσεων\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Αδυναμία πρόσβασης στο μητρώο επεκτάσεων. Παρακαλώ προσπαθήστε αργότερα.\",\n    \"INSTALL_FROM_URL\"                     : \"Εγκατάσταση από διεύθυνση URL\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Δημιουργός\",\n    \"EXTENSION_DATE\"                       : \"Ημερομηνία\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Αυτή η επέκταση απαιτεί νεότερη έκδοση του {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Αυτή η επέκταση προς το παρόν δουλεύει μόνο με παλαιότερες εκδόσεις του {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Η έκδοση {0} αυτής της επέκτασης απαιτεί μια νεότερη έκδοση του {APP_NAME}. Αλλά μπορείτε να εγκαταστήσετε την προηγούμενη έκδοση {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Η έκδοση {0} αυτής της επέκτασης λειτουργεί μόνο με παλαιότερες εκδόσεις του {APP_NAME}. Αλλά μπορείτε να εγκαταστήσετε την προηγούμενη έκδοση {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Δεν υπάρχει περιγραφή\",\n    \"EXTENSION_MORE_INFO\"                  : \"Περισσότερες Πληροφορίες...\",\n    \"EXTENSION_ERROR\"                      : \"Σφάλμα επέκτασης\",\n    \"EXTENSION_KEYWORDS\"                   : \"Λέξεις κλειδιά\",\n    \"EXTENSION_INSTALLED\"                  : \"Εγκατεστημένο\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Αυτή η αναβάθμιση επέκτασης έχει κατέβει και θα εγκατασταθεί όταν κλείσει το {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Αναζήτηση\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Περισσότερα\",\n    \"BROWSE_EXTENSIONS\"                    : \"Περιήγηση Επεκτάσεων\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Κατάργηση Επέκτασης\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Αδυναμία κατάργησης μίας ή περισσότερων επεκτάσεων: {0}. Το {APP_NAME} θα κλείσει.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Αναβάθμιση Επέκτασης\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Αδυναμία αναβάθμισης μίας η περισσότερων επεκτάσεων: {0}. Το {APP_NAME} θα κλείσει.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Επιλεγμένο για κατάργηση\",\n    \"UNDO_REMOVE\"                          : \"Αναίρεση\",\n    \"MARKED_FOR_UPDATE\"                    : \"Επιλεγμένο για αναβάθμιση\",\n    \"UNDO_UPDATE\"                          : \"Αναίρεση\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Αδυναμία κατάργησης της επέκτασης {0} αφού δεν ήταν εγκατεστημένη.\",\n    \"NO_EXTENSIONS\"                        : \"Δεν υπάρχουν επεκτάσεις εγκατεστημένες ακόμα.<br>Κάντε κλικ στην καρτέλα Διαθέσιμα για να ξεκινήσετε.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Δεν βρέθηκαν επεκτάσεις που να ικανοποιούν τα κριτήρια αναζήτησης σας.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Να είστε προσεκτικοί όταν εγκαθιστάτε επεκτάσεις από άγνωστες πηγές.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Εγκατεστημένες\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Διαθέσιμες\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Αναβαθμίσεις\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Δεν υπάρχουν διαθέσιμες αντιστοιχίες.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Δεν υπάρχουν κανόνες CSS που να ταιριάζουν με την επιλογή σας.<br> Κάντε κλικ στο \\\"Νέος Κανόνας\\\" για να δημιουργήσετε ένα νέο.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Δεν υπάρχουν stylesheets στο project σας.<br>Δημιουργήστε ένα για να προσθέσετε κανόνες CSS.\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"pixels\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Προβολή Developer Tools\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Επαναφόρτωση {APP_NAME}\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Επαναφόρτωση χωρίς τις επεκτάσεις\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Νέο Παράθυρο {APP_NAME}\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Εγκατάσταση συντόμευσης για την γραμμή εντολών\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Αλλαγή Γλώσσας\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Τρέξε Tests\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Προβολή Δεδομένων Επίδοσης\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Ενεργοποίηση του Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Καταγραφή Node State στη Console\",\n    \"CMD_RESTART_NODE\"                          : \"Επανεκκίνηση του Node\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Άνοιξε τον κώδικα του {APP_NAME}\",\n    \n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} Συντόμευση γραμμής εντολών\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Ένα σφάλμα προέκυψε κατά την εγκατάσταση της συντόμευσης για την γραμμή εντολών. Παρακαλώ δοκίμασε <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>αυτές τις προτείνομενες λύσεις</a>.<br/><br/>Αιτιολογία: {0}\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Αποτυχία δημιουργίας φακέλου του <code>/usr/local/bin</code>.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Εσωτερικό σφάλμα.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Η συντόμευση για την γραμμή εντολών δεν υποστηρίζεται στο συγκεκριμένο λειτουργικό σύστημα.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Επιτυχία! Τώρα μπορείς εύκολα να τρέξεις το {APP_NAME} από την γραμμή εντολών: <code>brackets myFile.txt</code> για να ανοίξεις ένα αρχείο ή <code>brackets myFolder</code> για να αλλάξεις project. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Μάθε περισσότερα</a>για το πώς να χρησιμοποιήσεις το {APP_NAME} από την γραμμή εντολών.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Αλλαγή Γλώσσας\",\n    \"LANGUAGE_MESSAGE\"                          : \"Γλώσσες:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Επανεκκίνηση του {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Ακύρωση\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Προεπιλογή Συστήματος\",\n\n    \n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Προτιμήσεις Health Report\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} Health Report\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Κοινοποίηση ανώνυμων πληροφοριών σχετικά με το πώς χρησιμοποιώ το {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Προκειμένου να βελτιώσουμε το {APP_NAME}, στέλνουμε περιοδικά περιορισμένα, <strong>ανώνυμα</strong> στατιστικά στοιχεία στην Adobe σχετικά με το πώς χρησιμοποιείς το {APP_NAME}. Αυτές οι πληροφορίες βοηθάνε στην καταχώρηση προτεραιοτήτων στα χαρακτηριστικά,στην εύρεση σφαλμάτων και στον εντοπισμό προβλημάτων χρηστικότητας.<br><br>Μπορείς να δεις τα δεδομένα σου ή να επιλέξεις να μην μοιραστείς κάποια επιλέγοντας <strong>Help > Health Report</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Μάθε περισσότερα για το {APP_NAME} Health Report</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} Health Report\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Προκειμένου να βελτιώσουμε το {APP_NAME}, στέλνουμε περιοδικά περιορισμένα, <strong>ανώνυμα</strong> στατιστικά στοιχεία στην Adobe σχετικά με το πώς χρησιμοποιείς το {APP_NAME}. Αυτές οι πληροφορίες βοηθάνε στην καταχώρηση προτεραιοτήτων στα χαρακτηριστικά,στην εύρεση σφαλμάτων και στον εντοπισμό προβλημάτων χρηστικότητας. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Μάθε περισσότερα για το {APP_NAME} Health Report</a> και πόσο ωφελεί την κοινότητα του {APP_NAME} προστατεύοντας παράλληλα την ιδιωτικότητα σου..</p><p>Παρακάτω βλέπεις μια προεπισκόπηση των δεδομένων που θα σταλούν στο επόμενο Health Report <em>εφόσον</em> είναι ενεργοποιημένο.</p>\",\n    \n    \n     // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Χρόνος\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Πρόοδος\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Τρέχων Χρώμα\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Αρχικό Χρώμα\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Μορφή RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Μορφή Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Μορφή HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Χρησιμοποιήθηκε {1} φορά)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Χρησιμοποιήθηκε {1} φορές)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Πήγαινε στον Ορισμό\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Προβολή Υποδείξεων Παραμέτρων\",\n    \"NO_ARGUMENTS\"                              : \"<χωρίς παραμέτρους>\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Γρήγορη Προβολή στο Hover\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Πρόσφατα Project\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Διαβάστε Περισσότερα\"\n});\n\n/* Last translated for c16e34f867a027aa9b321f7ef1f4da106ce83edf */\n"
  },
  {
    "path": "src/nls/el/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"el/Ξεκινώντας\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.el\"\n});\n"
  },
  {
    "path": "src/nls/en-gb/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n});\n"
  },
  {
    "path": "src/nls/es/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(error {0})\",\n    \"NOT_FOUND_ERR\"                     : \"No se pudo encontrar el archivo/directorio.\",\n    \"NOT_READABLE_ERR\"                  : \"No se pudo leer el archivo/directorio.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Los archivos de más de {0} MB no se pueden abrir en {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"El directorio de destino no se puede modificar.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Los permisos no permiten hacer modificaciones.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"El archivo fue modificado fuera de {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} actualmente solo soporta archivos codificados como UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"El archivo ya existe.\",\n    \"FILE\"                              : \"archivo\",\n    \"FILE_TITLE\"                        : \"archivo\",\n    \"DIRECTORY\"                         : \"directorio\",\n    \"DIRECTORY_TITLE\"                   : \"directorio\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"nombres de directorios\",\n    \"FILENAMES_LEDE\"                    : \"nombres de archivos\",\n    \"FILENAME\"                          : \"nombre de archivo\",\n    \"DIRECTORY_NAME\"                    : \"nombre de directorio\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Error abriendo el proyecto\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Ha ocurrido un error al mostrar el aviso de apertura de archivo. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Ha ocurrido un error al intentar abrir el directorio <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Ha ocurrido un error al leer los contenidos del directorio <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Error abriendo el archivo\",\n    \"ERROR_OPENING_FILE\"                : \"Ha ocurrido un error al intentar abrir el archivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Ha ocurrido un error al intentar abrir los siguientes archivos:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Error recargando cambios desde disco\",\n    \"ERROR_RELOADING_FILE\"              : \"Ha ocurrido un error al intentar recargar el archivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Error guardando el archivo\",\n    \"ERROR_SAVING_FILE\"                 : \"Ha ocurrido un error al intentar guardar el archivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Error renombrando el {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Ha ocurrido un error al intentar renombrar el {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Error eliminando el {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Ha ocurrido un error al intentar eliminar el {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"{0} inválido\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Los {0} no pueden utilizar ninguna palabra reservada por el sistema, terminar con puntos (.) o utilizar cualquiera de los siguientes caracteres: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Ya existe un archivo o directorio con el nombre <span class='dialog-filename'>{0}</span>.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Error creando {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Ha ocurrido un error al intentar crear el {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"No es posible abrir una carpeta y otros archivos al mismo tiempo.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Ocurrió un error leyendo los atajos de teclado\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"El archivo de atajos de teclado no tiene un formato JSON válido. El archivo se abrirá para que puedas corregir el formato.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"El archivo de atajos de teclado no está codificado como UTF-8 y no puede ser cargado.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"No puedes reasignar atajos de teclado a los siguientes comandos: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"No puedes reasignar los siguientes atajos de teclado: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Estas reasignando múltiples atajos de teclado a los siguientes comandos: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Hay múltiples apariciones de los siguientes atajos de teclado: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Los siguientes atajos de teclado son inválidos: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Estas asignando atajos de teclado a commandos inexistentes: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Error leyendo las preferencias\",\n    \"ERROR_PREFS_CORRUPT\"               : \"El archivo de preferencias no tiene un formato JSON válido. El archivo se abrirá para que puedas corregir el formato. Luego deberás reiniciar {APP_NAME} para que los cambios surtan efecto.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"El archivo de preferencias para el proyecto no tiene un formato JSON válido. El archivo se abrirá para que puedas corregir el formato. Luego deberás recargar el proyecto para que los cambios surtan efecto.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Vaya... parece que {APP_NAME} todavía no funciona en navegadores.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} está desarrollado en HTML, pero por ahora funciona como una aplicación de escritorio para que puedas editar archivos localmente. Por favor, utiliza la aplicación del repositorio <b>github.com/adobe/brackets-shell</b> para ejecutar {APP_NAME}.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Error indexando archivos\",\n    \"ERROR_MAX_FILES\"                   : \"Este proyecto contiene más de 30.000 archivos. Funciones que operan sobre múltiples archivos pueden estar deshabilitadas o funcionar igual que si el proyecto estuviese vacío. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Leer más acerca de cómo trabajar con proyectos grandes</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Error iniciando el navegador\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"No se pudo encontrar el navegador Google Chrome. Por favor, asegúrate que esté instalado correctamente.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Ha ocurrido un error al iniciar el navegador. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Error en la Vista previa dinámica\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Conectando con el navegador\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Para poder iniciar el modo de Vista previa dinámica, Chrome debe ser iniciado habilitando la depuración remota.<br><br>¿Quieres reiniciar Chrome y habilitar la depuración remota?<br><br>\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"No se pudo cargar la página para la Vista previa dinámica.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Abra un archivo HTML o asegúrate de que haya un index.html en tu proyecto para poder iniciar el modo de Vista previa dinámica.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Necesitas especificar una URL base en este proyecto para poder iniciar la Vista previa dinámica con archivos de servidor.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Error iniciando el servidor HTTP para la Vista previa dinámica. Vuelve a intentarlo, por favor.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"¡Bienvenido a la Vista previa dinámica!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Vista previa dinámica conecta {APP_NAME} con tu navegador. Lanza una vista previa de tu archivo HTML en el navegador y la actualiza a medida que modificas tu código.<br><br>En esta versión preliminar de {APP_NAME}, el modo de Vista previa dinámica sólo funciona para cambios de <strong>archivos CSS o HTML</strong> y únicamente con <strong>Google Chrome</strong>. Los cambios en los archivos Javascript son recargados automáticamente cuando se guardan.<br><br>(No volverás a ver este mensaje.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Para más información, consulta <a href='{0}' title='{0}'>Resolución de Problemas de conexión en Vista previa dinámica</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Vista previa dinámica\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Vista previa dinámica: Conectando\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Vista previa dinámica: Inicializando\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Terminar la Vista previa dinámica\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Vista previa dinámica (guarda el archivo para actualizar)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Vista previa dinámica (no se está actualizando debido a un error de sintaxis)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Vista previa dinámica se ha detenido porque se han abierto las herramientas de desarrollo\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Vista previa dinámica se ha detenido porque se ha cerrado la página en el navegador\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Vista previa dinámica se ha detenido porque se ha accedido a una página que no es parte del proyecto actual\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Vista previa dinámica se ha detenido por motivos desconocidos ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Guardar cambios\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"¿Quieres guardar los cambios existentes en el documento <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"¿Quieres guardar tus cambios en los siguientes documentos?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Cambios externos\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Confirmar eliminación\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"¿Estás seguro que deseas eliminar el directorio <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Archivo eliminado\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> ha sido modificado en el disco fuera de {APP_NAME}.<br><br>¿Deseas guardar el archivo y sobrescribir esos cambios?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> ha sido modificado en el disco fuera de {APP_NAME}, pero también tiene cambios en {APP_NAME}.<br><br>¿Qué versión quieres conservar?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> ha sido eliminado en el disco fuera de {APP_NAME}, pero tiene cambios sin guardar en {APP_NAME}.<br><br>¿Quieres conservar tus cambios?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Aceptar\",\n    \"OK\"                                : \"Aceptar\",\n    \"CANCEL\"                            : \"Cancelar\",\n    \"DONT_SAVE\"                         : \"No guardar\",\n    \"SAVE\"                              : \"Guardar\",\n    \"DELETE\"                            : \"Eliminar\",\n    \"SAVE_AS\"                           : \"Guardar como\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Sobrescribir\",\n    \"BUTTON_YES\"                        : \"Sí\",\n    \"BUTTON_NO\"                         : \"No\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} de {1}\",\n    \"FIND_NO_RESULTS\"                   : \"No hay resultados\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Buscar\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Reemplazar con\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Todo\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Reemplazar\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Reemplazar\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Siguiente coincidencia\",\n    \"BUTTON_PREV_HINT\"                  : \"Anterior coincidencia\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Sensible a mayúsculas\",\n    \"BUTTON_REGEXP_HINT\"                : \"Expresión regular\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Reemplazar sin deshacer\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Dado que hay más de {0} archivos que necesitan ser modificados, {APP_NAME} modificará los archivos no abiertos en el disco.<br>Por lo tanto, no será posible deshacer los reemplazos en esos archivos.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Reemplazar sin deshacer\",\n\n    \"OPEN_FILE\"                         : \"Abrir archivo\",\n    \"SAVE_FILE_AS\"                      : \"Guardar archivo\",\n    \"CHOOSE_FOLDER\"                     : \"Elige una carpeta\",\n\n    \"RELEASE_NOTES\"                     : \"Notas sobre la versión\",\n    \"NO_UPDATE_TITLE\"                   : \"¡Estás actualizado!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Estás utilizando la última versión de {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Reemplazar\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"con\",\n    \"FIND_TITLE_LABEL\"                  : \"Se encontró\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} en {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"en <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"en el proyecto\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"El filtro excluye todos los archivos {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"archivo\",\n    \"FIND_IN_FILES_FILES\"               : \"archivos\",\n    \"FIND_IN_FILES_MATCH\"               : \"coincidencia\",\n    \"FIND_IN_FILES_MATCHES\"             : \"coincidencias\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Más de \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indexando archivos para la Búsqueda instantánea\\u2026\",\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd clic para expandir/colapsar todo\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Errores al reemplazar\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Los siguientes archivos no fueron modificados porque cambiaron después de realizar la búsqueda o no pueden ser escritos.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Error obteniendo información sobre actualizaciones\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Ocurrió un problema al obtener la información sobre las últimas actualizaciones desde el servidor. Por favor, asegúrate de estar conectado a Internet y vuelve a intentarlo.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Nuevo conjunto de filtros\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"No excluir archivos\",\n    \"NO_FILE_FILTER\"                    : \"No hay archivos excluidos\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Excluir {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Editar\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Editar conjunto de filtros\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Excluir archivos y carpetas que coincidan con alguna de las siguientes cadenas / subcadenas o <a href='{0}' title='{0}'>comodines</a>. Ingrese una cadena por línea.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nombrar este conjunto de filtros (opcional)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"y {0} más\",\n    \"FILTER_COUNTING_FILES\"             : \"Contando archivos\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Permite {0} de {1} archivos {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Permite todos los {0} archivos {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"La Edición Rápida no está disponible para la posición actual del cursor\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Edición Rápida para CSS: ubique el cursor sobre el nombre de una clase\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Edición Rápida para CSS: atributo de clase incompleto\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Edición Rápida para CSS: atributo de identificación incompleto\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Edición Rápida para CSS: ubique el cursor sobre una etiqueta, clase o id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Edición Rápida para Funciones de Temporización de CSS: sintaxis inválida\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Edición Rápida para JS: ubique el cursor sobre el nombre de una función\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"La Documentación Rápida no está disponible para la posición actual del cursor\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Cargando\\u2026\",\n    \"UNTITLED\"          : \"Sin título\",\n    \"WORKING_FILES\"     : \"Área de trabajo\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Arriba\",\n    \"BOTTOM\"            : \"Abajo\",\n    \"LEFT\"              : \"Izquierda\",\n    \"RIGHT\"             : \"Derecha\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"No dividido\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"División vertical\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"División horizontal\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Dividir el editor vertical u horizontalmente\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configurar el área de trabajo\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Ya está abierto\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"El archivo ya está abierto en otro panel. Próximamente {APP_NAME} soportará abrir el mismo archivo en más de un panel. Hasta entonces, el archivo se mostrará en el panel en el cual ya está abierto.<br><br>(Sólo verá este mensaje una vez.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"May\",\n    \"KEYBOARD_SPACE\"  : \"Espacio\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Línea {0}, Columna {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} columna seleccionada\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} columnas seleccionadas\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} línea seleccionada\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} líneas seleccionadas\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} selecciones\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Haz clic para usar espacios en la sangría\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Haz clic para usar tabulaciones en la sangría\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Haz clic para cambiar el número de espacios usados en la sangría\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Haz clic para cambiar el ancho de las tabulaciones\",\n    \"STATUSBAR_SPACES\"                      : \"Espacios:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tamaño del tabulador:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} línea\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} líneas\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extensiones deshabilitadas\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"SOB\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Haz clic para intercambiar entre el modo insertar (INS) y el modo sobrescribir (SOB)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Haz clic para cambiar el tipo de archivo\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Haz clic para mostrar/ocultar el panel de reportes.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(por defecto)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Marcar como predeterminado para los archivos .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"Problemas de {0}\",\n    \"SINGLE_ERROR\"                          : \"1 problema de {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} problemas de {0}\",\n    \"NO_ERRORS\"                             : \"No se encontraron problemas de {0} - ¡Buen trabajo!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"No se encontraron problemas - ¡Buen trabajo!\",\n    \"LINT_DISABLED\"                         : \"La inspección de código está deshabilitada\",\n    \"NO_LINT_AVAILABLE\"                     : \"No hay inspección de código disponible para {0}\",\n    \"NOTHING_TO_LINT\"                       : \"No hay nada para inspeccionar\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} ha agotado el tiempo después de esperar {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} terminó con error: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Archivo\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nuevo\",\n    \"CMD_FILE_NEW\"                        : \"Nuevo archivo\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nueva carpeta\",\n    \"CMD_FILE_OPEN\"                       : \"Abrir\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Abrir en el área de trabajo\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Abrir archivos soltados\",\n    \"CMD_OPEN_FOLDER\"                     : \"Abrir carpeta\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Cerrar\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Cerrar todo\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Cerrar lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Cerrar otros\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Cerrar otros por encima\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Cerrar otros por debajo\",\n    \"CMD_FILE_SAVE\"                       : \"Guardar\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Guardar todo\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Guardar como\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Vista previa dinámica\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Habilitar la Vista previa dinámica experimental\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Recargar la Vista previa dinámica\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Configuración del proyecto\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Renombrar\",\n    \"CMD_FILE_DELETE\"                     : \"Eliminar\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instalar extensión\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Gestionar extensiones\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Actualizar árbol de archivos\",\n    \"CMD_QUIT\"                            : \"Salir\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Salir\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edición\",\n    \"CMD_UNDO\"                            : \"Deshacer\",\n    \"CMD_REDO\"                            : \"Rehacer\",\n    \"CMD_CUT\"                             : \"Cortar\",\n    \"CMD_COPY\"                            : \"Copiar\",\n    \"CMD_PASTE\"                           : \"Pegar\",\n    \"CMD_SELECT_ALL\"                      : \"Seleccionar todo\",\n    \"CMD_SELECT_LINE\"                     : \"Seleccionar línea\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Dividir selección en líneas\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Agregar cursor a la siguiente línea\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Agregar cursor a la línea anterior\",\n    \"CMD_INDENT\"                          : \"Aumentar sangría\",\n    \"CMD_UNINDENT\"                        : \"Disminuir sangría\",\n    \"CMD_DUPLICATE\"                       : \"Duplicar\",\n    \"CMD_DELETE_LINES\"                    : \"Eliminar línea\",\n    \"CMD_COMMENT\"                         : \"Comentar/Descomentar línea\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Comentar/Descomentar bloque\",\n    \"CMD_LINE_UP\"                         : \"Subir línea\",\n    \"CMD_LINE_DOWN\"                       : \"Bajar línea\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Crear línea arriba\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Crear línea abajo\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Completar paréntesis automáticamente\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Mostrar sugerencias de código\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Buscar\",\n    \"CMD_FIND\"                            : \"Buscar\",\n    \"CMD_FIND_NEXT\"                       : \"Buscar siguiente\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Buscar anterior\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Buscar todo y seleccionar\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Agregar la siguiente coincidencia a la selección\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Omitir y agregar la siguiente coincidencia\",\n    \"CMD_FIND_IN_FILES\"                   : \"Buscar en archivos\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Buscar en\\u2026\",\n    \"CMD_REPLACE\"                         : \"Reemplazar\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Reemplazar en archivos\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Reemplazar en\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Ver\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Ocultar menú lateral\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Mostrar menú lateral\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Aumentar tamaño de fuente\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Disminuir tamaño de fuente\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restablecer tamaño de fuente\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Desplazar hacia arriba\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Desplazar hacia abajo\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Mostrar números de línea\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Resaltar línea actual\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Habilitar ajuste de línea\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Resaltado en Vista previa dinámica\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Inspeccionar el código al guardar\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Ordenar por Añadido\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Ordenar por Nombre\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Ordenar por Tipo\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Ordenación automática\",\n    \"CMD_THEMES\"                          : \"Temas\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Navegación\",\n    \"CMD_QUICK_OPEN\"                      : \"Apertura rápida\",\n    \"CMD_GOTO_LINE\"                       : \"Ir a la línea\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Búsqueda rápida de definición\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Ir al primer problema\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Edición rápida\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Documentación rápida\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Coincidencia anterior\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Coincidencia siguiente\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Nueva regla\",\n    \"CMD_NEXT_DOC\"                        : \"Documento siguiente\",\n    \"CMD_PREV_DOC\"                        : \"Documento anterior\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Documento siguiente en la lista\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Documento anterior en la lista\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Mostrar en el árbol de directorios\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Mostrar en el Explorador\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Mostrar en Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Mostrar en el Sistema Operativo\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Ayuda\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Buscar actualizaciones\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Cómo utilizar {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Soporte de {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Sugerir una mejora\",\n    \"CMD_RELEASE_NOTES\"                   : \"Notas de la versión\",\n    \"CMD_GET_INVOLVED\"                    : \"Involúcrese\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Abrir carpeta de extensiones\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Reporte de estadísticas\",\n    \"CMD_HOMEPAGE\"                        : \"Página principal de {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} en Twitter\",\n    \"CMD_ABOUT\"                           : \"Acerca de {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Abrir archivo de preferencias\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Abrir archivo de atajos de teclado\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"versión experimental\",\n    \"RELEASE_BUILD\"                        : \"versión\",\n    \"DEVELOPMENT_BUILD\"                    : \"versión de desarrollo\",\n    \"RELOAD_FROM_DISK\"                     : \"Volver a cargar desde disco\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Conservar los cambios del editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Cerrar (No guardar)\",\n    \"RELAUNCH_CHROME\"                      : \"Reiniciar Chrome\",\n    \"ABOUT\"                                : \"Acerca de\\u2026\",\n    \"CLOSE\"                                : \"Cerrar\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Release {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"construido el: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Los avisos, términos y condiciones pertenecientes a software de terceros se encuentran en <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> y se incluyen aquí como referencia.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Puedes encontrar la documentación y código fuente en <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Hecho con \\u2764 y JavaScript por:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Mucha gente (pero ahora mismo estamos teniendo problemas para cargar esos datos).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"El contenido de MDN Docs y el logo de MDN están disponibles bajo Licencia de Reconocimiento de Creative Commons, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"¡Hay una nueva versión de {APP_NAME} disponible! Haz clic aquí para ver más detalles.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Actualización disponible\",\n    \"UPDATE_MESSAGE\"                       : \"¡Hay una nueva versión de {APP_NAME} disponible! Éstas son algunas de las nuevas características:\",\n    \"GET_IT_NOW\"                           : \"¡Consíguelo ahora!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Configuración del proyecto para: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL base para Vista previa dinámica\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Para usar un servidor local, ingresa una URL como http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"El protocolo {0} no está soportado por la Vista previa dinámica. Por favor, utiliza http: o https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"La URL base no puede contener parámetros de búsqueda como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"La URL base no puede contener hashes como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Los caracteres especiales como '{0}' deben codificarse en formato %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Error desconocido analizando la URL base\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Abra un archivo mientras este panel está enfocado</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Tema actual\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Usar las barras de desplazamiento del tema\",\n    \"FONT_SIZE\"                            : \"Tamaño de letra\",\n    \"FONT_FAMILY\"                          : \"Tipo de letra\",\n    \"THEMES_SETTINGS\"                      : \"Preferencias de temas\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Nueva regla\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instalar\",\n    \"UPDATE\"                               : \"Actualizar\",\n    \"REMOVE\"                               : \"Eliminar\",\n    \"DISABLE\"                              : \"Deshabilitar\",\n    \"ENABLE\"                               : \"Habilitar\",\n    \"OVERWRITE\"                            : \"Sobrescribir\",\n    \"CANT_REMOVE_DEV\"                      : \"Las extensiones en la carpeta \\\"dev\\\" se deben eliminar manualmente.\",\n    \"CANT_UPDATE\"                          : \"La actualización no es compatible con esta versión de {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Las extensiones en la carpeta \\\"dev\\\" no se pueden actualizar automáticamente.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instalar extensión\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Actualizar extensión\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL de la extensión\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL del archivo zip de la extensión o del repositorio de Github\",\n    \"INSTALLING_FROM\"                      : \"Instalando extensión desde {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"¡Instalación completada!\",\n    \"INSTALL_FAILED\"                       : \"Error en la instalación.\",\n    \"CANCELING_INSTALL\"                    : \"Cancelando\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Cancelando la instalación porque está tardando demasiado tiempo. Puede que se haya producido un error interno.\",\n    \"INSTALL_CANCELED\"                     : \"Instalación cancelada.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Ver descripción completa\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Ver descripción corta\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"El contenido descargado no es un archivo zip válido.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"El archivo package.json no es válido (error: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"El archivo package.json no especifica un nombre de paquete.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} no es un nombre de paquete válido.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"El archivo package.json no especifica la versión del paquete.\",\n    \"INVALID_VERSION_NUMBER\"               : \"El número de paquete de la versión ({0}) no es válido.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"El código de compatibilidad de {APP_NAME} ({0}) no es válido.\",\n    \"DISALLOWED_WORDS\"                     : \"Las palabras ({1}) no están permitidas en el campo {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"La extensión no es compatible con esta versión de {APP_NAME}. Está en la carpeta de extensiones deshabilitadas.\",\n    \"MISSING_MAIN\"                         : \"El paquete no contiene el archivo main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Instalar este paquete sobrescribirá una extensión instalada previamente. ¿Deseas sobrescribir la antigua extensión?\",\n    \"EXTENSION_SAME_VERSION\"               : \"La versión de este paquete es la misma que la instalada actualmente. ¿Deseas sobrescribir la instalación actual?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"La versión {0} de este paquete es más antigua que la instalada actualmente ({1}). ¿Deseas sobrescribir la instalación actual?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Error interno: el ID de descarga ya está siendo utilizado.\",\n    \"NO_SERVER_RESPONSE\"                   : \"No se puede conectar con el servidor.\",\n    \"BAD_HTTP_STATUS\"                      : \"Archivo no encontrado en el servidor (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"No se pudo guardar la descarga en un archivo temporal.\",\n    \"ERROR_LOADING\"                        : \"La extensión ha encontrado un error al arrancar.\",\n    \"MALFORMED_URL\"                        : \"La URL no es válida. Por favor, comprueba que esté escrita correctamente.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"La URL debe ser una dirección http o https.\",\n    \"UNKNOWN_ERROR\"                        : \"Error interno desconocido.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Gestor de extensiones\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"No se pudo acceder al registro de extensiones. Vuelve a intentarlo más tarde, por favor.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Arrastrar el .zip aquí ó\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Soltar el .zip para instalarlo\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"La instalación/actualización fue abortada por los siguientes errores:\",\n    \"INSTALL_FROM_URL\"                     : \"Instalar desde URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validando\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Fecha\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Esta extensión necesita una versión más actualizada de {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"En estos momentos esta extensión sólo funciona con versiones anteriores de {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"La versión {0} de esta extensión necesita una versión superior de {APP_NAME}. Puedes instalar la versión anterior {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"La versión {0} de esta extensión sólo funciona con versiones anteriores de {APP_NAME}. Puedes instalar la versión anterior {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Sin descripción\",\n    \"EXTENSION_MORE_INFO\"                  : \"Más información\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Error en la extensión\",\n    \"EXTENSION_KEYWORDS\"                   : \"Palabras clave\",\n    \"EXTENSION_INSTALLED\"                  : \"Instalada\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Traducida a {0} idiomas, incluyendo el tuyo\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Traducida a {0} idiomas\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Esta extension fue traducida a los siguientes idiomas: {0}\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"La actualización de esta extensión se ha descargado y se instalará luego de recargar {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Buscar\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Más\",\n    \"BROWSE_EXTENSIONS\"                    : \"Explorar extensiones\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Eliminar extensión\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"No se pudo eliminar una o más extensiones: {0}. {APP_NAME} se recargará igualmente.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Actualizar extensión\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"No se pudo actualizar una o más extensiones: {0}. {APP_NAME} se recargará igualmente.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Deshabilitar extensiones\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"No se pudo deshabilitar una o más extensiones: {0}. {APP_NAME} se recargará igualmente.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Marcada para eliminar\",\n    \"UNDO_REMOVE\"                          : \"Deshacer\",\n    \"MARKED_FOR_UPDATE\"                    : \"Marcada para actualizar\",\n    \"UNDO_UPDATE\"                          : \"Deshacer\",\n    \"MARKED_FOR_DISABLING\"                 : \"Marcada para deshabilitar\",\n    \"UNDO_DISABLE\"                         : \"Deshacer\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Cambiar extensiones\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Para actualizar o eliminar las extensiones marcadas, necesitas recargar {APP_NAME}. Se solicitará confirmación para guardar los cambios pendientes.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Eliminar extensiones y recargar\",\n    \"CHANGE_AND_RELOAD\"                    : \"Cambiar extensiones y recargar\",\n    \"UPDATE_AND_RELOAD\"                    : \"Actualizar extensiones y recargar\",\n    \"DISABLE_AND_RELOAD\"                   : \"Deshabilitar extensiones y recargar\",\n    \"PROCESSING_EXTENSIONS\"                : \"Procesando los cambios en las extensiones\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"No se pudo eliminar la extensión {0} porque no se encuentra instalada.\",\n    \"NO_EXTENSIONS\"                        : \"Todavía no hay ninguna extensión instalada.<br>Haz clic en la pestaña Disponibles para empezar.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"No hay extensiones que coincidan con tu búsqueda.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"NOTA: estas extensiones pueden provenir de autores diferentes a {APP_NAME}. Las extensiones no son revisadas y tiene todos los privilegios locales. Tenga cuidado cuando instala extensiones de una fuente desconocida.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Instaladas\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Disponibles\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Temas\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Actualizaciones\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"No hay coincidencias disponibles.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Todas las coincidencias están colapsadas. Expanda los archivos listados a la derecha para ver coincidencias.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"No hay reglas de CSS existentes que coincidan con tu selección.<br> Haz clic en \\\"Nueva regla\\\" para crear una.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"No hay hojas de estilos en tu proyecto.<br>Crea una para añadir reglas de CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"más grande\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"píxeles\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Desarrollo\",\n    \"ERRORS\"                                    : \"Errores\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Mostrar herramientas para desarrolladores\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Recargar con extensiones\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Recargar sin extensiones\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nueva ventana de {APP_NAME}\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Instalar acceso directo por línea de comandos\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Cambiar idioma\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Ejecutar tests\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Mostrar información de rendimiento\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Habilitar depuración de Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Mostrar estado de Node en Consola\",\n    \"CMD_RESTART_NODE\"                          : \"Reiniciar Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Mostrar errores en la barra de estado\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Abrir el código fuente de {APP_NAME}\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"Acceso directo a {APP_NAME} por línea de comandos\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Ocurrió un error al instalar el acceso directo por línea de comandos. Por favor probá <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>estas sugerencias de solución de problemas</a>.<br><br>Razón: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"No se pudó eliminar el enlace simbólico existente <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"No se pudó crear el directorio <code>/usr/local/bin</code>.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"No se pudó crear elenlace simbólico <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Error interno.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"El acceso directo por línea de comandos no es compatible con este sistema operativo.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"¡Éxito! Ahora puedes abrir fácilmente {APP_NAME} desde la línea de comandos: <code>brackets myFile.txt</code> para abrir un archivo o <code>brackets myFolder</code> para cambiar de proyecto.<br><br><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Aprende más</a> acerca de como usar {APP_NAME} desde la línea de comandos.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Cambiar idioma\",\n    \"LANGUAGE_MESSAGE\"                          : \"Idioma:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Reiniciar {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Cancelar\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Idioma predeterminado\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Preferencias del reporte de estadísticas\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"Reporte de estadísticas de {APP_NAME}\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Compartir información anónima sobre cómo utilizo {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Para poder mejorar {APP_NAME}, enviamos periódicamente limitadas estadísticas <strong>anónimas</strong> a Adobe acerca de cómo se utiliza {APP_NAME}. Esta información ayuda a priorizar características a desarrollar, encontrar errores y problemas de usabilidad.<br><br>Puedes ver tus datos o elegir no compartir datos seleccionando <strong>Ayuda > Reporte de estadísticas</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Aprende más sobre el reporte de estadísticas de {APP_NAME}</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"Reporte de estadísticas de {APP_NAME}\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Para poder mejorar {APP_NAME}, enviamos periódicamente limitadas estadísticas <strong>anónimas</strong> a Adobe acerca de cómo se utiliza {APP_NAME}. Esta información ayuda a priorizar características a desarrollar, encontrar errores y problemas de usabilidad. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Aprende más sobre el Reporte de estadísticas de {APP_NAME}</a> y cómo beneficia a la comunidad de {APP_NAME} mientras protege tu privacidad.</p><p>A continuación hay una vista previa de la información que será enviada en el siguiente Reporte de estadísticas <em>si</em> está habilitado.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tiempo\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progresión\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Mueven el punto seleccionado<br><kbd class='text'>Shift</kbd> Mueve de a diez unidades<br><kbd class='text'>Tab</kbd> Cambia el punto seleccionado\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Incrementa o disminuya los pasos<br><kbd>←</kbd><kbd>→</kbd> 'Start' o 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"El valor viejo <code>{0}</code> no es válido, por lo tanto, fue modificado a <code>{1}</code>. El documento será actualizado luego de la primer edición.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Color actual\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Color original\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Formato RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Formato Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Formato HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Utilizado {1} vez)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Utilizado {1} veces)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Saltar a la definición\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Mostrar sugerencias de parámetros\",\n    \"NO_ARGUMENTS\"                              : \"<no hay parámetros>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problema de inferencia con un archivo JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} se encontró con problemas procesando: <span class='dialog-filename'>{0}</span>.<br><br>Este archivo no volverá a ser procesado para las sugerencias de código, saltar a la definición o para la edición rápida. Para reactivar este archivo, abra el archivo <code>.brackets.json</code> en su proyecto y edite <code>jscodehints.detectedExclusions</code><br><br>Esto es probablemente un error en {APP_NAME}. Si puede proporcionar una copia de este archivo, por favor <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>envíe un informe</a> con un vínculo a dicho archivo.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Vista rápida con cursor\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Proyectos recientes\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Más\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Colapsar todo\",\n    \"EXPAND_ALL\"                    : \"Expandir todo\",\n    \"COLLAPSE_CURRENT\"              : \"Colapsar actual\",\n    \"EXPAND_CURRENT\"                : \"Expandir actual\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true para cerrar automáticamente las llaves, los corchetes y los paréntesis\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false para eliminar \\\"Cerrar otros por encima\\\" del menú contextual del Área de trabajo\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false para eliminar \\\"Cerrar otros por debajo\\\" del menú contextual del Área de trabajo\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false para eliminar \\\"Cerrar otros\\\" del menú contextual del Área de trabajo\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Configura las opciones de cierre de etiquetas automático\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Un vector de etiquetas que no deben cerrarse automáticamente\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Cerrar cuando \\\">\\\" de la etiqueta de apertura es tipeado\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Cerrar cuando \\\"/\\\" de la etiqueta de clausura es tipeado\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Un vector de etiquetas que cuando se cierran generan una linea en blanco entre las etiquetas\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true para siempre generar marcadores plegables cuando cambia el nivel de indentación\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true para habilitar el colapsado del código\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true para hacer marcadores de sección plegables visible sólo cuando se mueve el cursor sobre el espacio a la izquierda del código\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limita a cuántos niveles de profundidad Colapsar todo aplica\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Mínima cantidad de líneas antes de que aparezca un icono de sección plegable\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true para recordar la secciones colapsadas luego de cerrar y abrir un archivo o proyecto\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Activar/desactivar las sugerencias de código para los atributos en HTML\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Activar/desactivar las sugerencias de código para las propiedades en CSS/LESS/SCSS\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Activar/desactivar las sugerencias de código en JavaScript\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Activar/desactivar las sugerencias de código para las Preferences\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Activar/desactivar las sugerencias de código para las entidades en HTML\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Activar/desactivar las sugerencias de código en SVG\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Activar/desactivar las sugerencias de código para las etiquetas en HTML\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Activar/desactivar las sugerencias de código para las URLs en HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Activar/desactivar la funcionalidad de arrastrar y soltar\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Habilitar el seguimiento de los Reportes de estadísticas\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Habilita el resaltado automático de cadenas que coinciden en el documento\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Resaltar todas las cadenas que coincidan con la cadena donde el cursor se encuentra (ninguna selección es necesaria)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Resaltar sólo cuando la selección es una cadena completa\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true para insertar la sugerencia de código al presionar tab\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true para no mostrar sugerencias de código automáticamente en JS cuando \\\".\\\" es tipeado\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Un objeto con las opciones por defecto de JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true para permitir expresiones de asignación\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true para permitir los operadores bit a bit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true si las variables/funciones globales del navegador deben estar predefinidas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true para permitir modismos de Google Closure\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true para permitir la declaración \\\"continue\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true si las variables/funciones globales de CouchDB deben estar predefinidas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true para permitir declaraciones del depurador\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true si las variables/funciones globales del navegador para el desarrollo deben estar predefinidas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true para permitir == y !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true si las variables/funciones globales de ES6 deben estar predefinidas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true para permitir eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true para permitir \\\"for ... in\\\" sin filtrar\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Establece un ancho para el tab\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"La cantidad máxima de advertencias reportadas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"La cantidad máxima de caracters por línea\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true para permitir constructores sin mayúsculas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true si las variables/funciones globales de Node.js deben estar predefinidas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true para permitir el guión bajo delante de los identificadores\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true para parar en el primer error\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true para permitir ++ y --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true para permitir . y [^...]. en RegExp\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true si las variables/funciones globales de Rhino deben estar predefinidas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true para permitir que falte el pragma `use strict`\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true si los métodos bloqueantes ('...Sync') se pueden usar\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true para permitir subíndices ineficiente\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true para permitir comentarios TODO\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true para permitir parámetros no usados\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true para permitir más de 1 var en una función\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true para ignorar las reglas espaciado\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Preferencias específicas de un lenguaje\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Asignaciones adicionales de extensión de archivo a nombre del lenguaje\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Asignaciones adicionales de nombre de archivo a nombre del lenguaje\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true para habilitar la inspección del código\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"El tiempo en milisegundos para esperar a los inspectores de código asincrónicos\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Vector de inspectores de código para ejecutar primero\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true para habilitar la Vista previa dinámica experimental\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true para ejecutar solo los proveedores especificados en linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Máxima cantidad de sugerencias de código mostradas\",\n    \"DESCRIPTION_PATH\"                               : \"Preferencias especificas para una ruta de archivo\",\n    \"DESCRIPTION_PROXY\"                              : \"La URL del servidor proxy utilizada para la instalación de extensiones\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true permitir el desplazamiento más allá del final del documento\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false para deshabilitar todas las sugerencias de código\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Mantiene el cursor intermitente visible cuando se tiene una selección de texto\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true para mostrar los números de líne a la izquierda del código\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Indentar automáticamente cuando se crea un nuevo bloque\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false para deshabilitar el comportamiento de \\\"soft tabs\\\"\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true para ordenar los directorios primero en el árbol del proyecto\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Cantidad de espacios para utilizar en la indentación basada en espacios\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Número de puerto que el servidor utilizará para la Vista previa dinámica\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true para resaltar la línea en la que se encuentra el cursor\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Cantidad de espacios utilizados para el tab\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true para usar tabs en vez de espacios\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true para generar color en mayúsculas en el editor de colores\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Ajustar líneas que sobrepasen el ancho de la ventana\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Una lista de los archivos que se ha detectado que causan que Tern no funcione correctamente\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"La cantidad de veces después de la cual Tern dejara de intentar entender los archivos\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true para mostrar errores en la barra de estado\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true para habilitar la Vista rápida\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true para mostrar vistas previas de imágenes para URLs sin extensión\",\n    \"DESCRIPTION_THEME\"                              : \"Seleccionar un tema para {APP_NAME}\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true para habilitar la barra de desplazamiento customizada\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true para colapsar el panel de inspección de código\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Cambiar la fuente\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Cambiar el tamaño de la fuente; ej., 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"True to para habilitar búsquedas basadas en node\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"True to para habilitar la búsqueda instantánea\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Sólo para Mac: \\\"subpixel-antialiased\\\" para habilitar sub-pixel antialiasing o \\\"antialiased\\\" para antialiasing en escala de grises\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false para deshabilitar la apertura del archivo de preferencias en la vista dividida\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false para abrir el archivo de preferencias en el panel de la izquierda/arriba\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Éste es un archivo únicamente de lectura con las preferencias soportadas\\n * por {APP_NAME}.\\n * Podes usar este archivo como referencia para modificar tu archivo de\\n * preferencias \\\"brackets.json\\\" abierto en el otro panel.\\n * Para más información sobre como usar las preferencias dentro de\\n * {APP_NAME}, podes consultar la página web https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Por defecto\"\n});\n\n/* Last translated for 1e5ba8f612dcf983d3cbffbbf1bfe455a90788c8 */\n"
  },
  {
    "path": "src/nls/es/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"es/Primeros Pasos\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_es/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.es\"\n\n});\n"
  },
  {
    "path": "src/nls/fa-ir/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(خطا {0})\",\n    \"NOT_FOUND_ERR\"                     : \"پرونده پیدا نشد.\",\n    \"NOT_READABLE_ERR\"                  : \"پرونده قابل خواندن نیست.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"فایل های بزرگتر از {0} MB قابل ویرایش در {APP_NAME} نیست.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"دایرکتوری هدف قابل ویرایش نیست.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"دسترسی های تعریف شده برای شما اجازه تغییرات را نمی دهند.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"فایل خارج از محیط {APP_NAME} تغییر یافته است.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} فعلا تنها از پرونده ها با ساختار یونیکدی UTF-8 پشتیبانی می کند.\",\n    \"FILE_EXISTS_ERR\"                   : \"پرونده یا پوشه مد نظر موجود می باشد.\",\n    \"FILE\"                              : \"پرونده\",\n    \"FILE_TITLE\"                        : \"پرونده\",\n    \"DIRECTORY\"                         : \"پوشه\",\n    \"DIRECTORY_TITLE\"                   : \"پوشه\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"نام های پوشه\",\n    \"FILENAMES_LEDE\"                    : \"نام های پرونده\",\n    \"FILENAME\"                          : \"نام پرونده\",\n    \"DIRECTORY_NAME\"                    : \"نام پوشه\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"خطا در بارگذاری پروژه\",\n    \"OPEN_DIALOG_ERROR\"                 : \"خطا در باز کردن پرونده خوان. (خطا {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"خطا بهنگام بارگذاری پوشه <span class='dialog-filename'>{0}</span>. (خطا {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"بروز خطا در خواندن اطلاعات پوشه <span class='dialog-filename'>{0}</span>. (خطا {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"خطا در باز کردن پرونده\",\n    \"ERROR_OPENING_FILE\"                : \"خطا بهنگام تلاش برای باز کردن پرونده <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"خطا بهنگام بارگذاری پرونده های زیر:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"خطا در بارگذاری تغییرات از حافظه\",\n    \"ERROR_RELOADING_FILE\"              : \"بروز خطا بهنگام تلاش برای بارگذاری پرونده <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"خطا در ذخیره سازی پرونده\",\n    \"ERROR_SAVING_FILE\"                 : \"بروز خطا بهنگام تلاش جهت ذخیره پرونده <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"خطا در تغییر نام پرونده {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"بروز خطا بهنگام تلاش برای تغییر نام پرونده {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"خطا در حذف پرونده {0}\",\n    \"ERROR_DELETING_FILE\"               : \"بروز خطا بهنگام تلاش برای تغییر نام پرونده {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"غیر مجاز {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} نمیتوانید از عبارات مورد استفاده نرم افزار, نقطه ها پایانی (.) یا کاراکترهای شامل موارد زیر استفاده کنید: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"پوشه یا پرونده ی با نام  <span class='dialog-filename'>{0}</span> هم اکنون موجود است.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"خطا در ایجاد {0}\",\n    \"ERROR_CREATING_FILE\"               : \"خطا بهنگام ایجاد {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"نمی توان یک پوشه را همزمان به عنوان سایر فایل ها باز شده در نظر گرفت\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"خطا در خواندن نقشه ی کلید مورد استفاده\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"فایل نقشه کلید شما در  JSON نامعتبر میباشد. زمانی فایل باز خواهد شده که شما آن را به شکل صحیح بنویسید.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"فایل نقشه کلید شما هست یک فایل متنی غیر معتبر با کدگذاری UTF-8 .و نمی توان بارگذاری شود\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"شما نمی توان با این دستور کلیدهای میانبر را اختصاص دهید: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"شما این میانبرها را نمیتوانید اختصاص دهید: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"شما با این دستور کلید میانبر چندگانه ایجاد کرده اید: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"شما مقادیر متعددی برای این میانبر دارید: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"این میانبر نامعتبر میباشد: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"شما در حال اختصاص کلید میانبر برای دستوراتی که وجود ندارند هستید: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"خطا در خواندن تنظیمات\",\n    \"ERROR_PREFS_CORRUPT\"               :   \"پرونده تنظیمات شما از نوع پرونده JSON معتبر نیست. از آنجایی که پرونده قابل دسترسی و خواندن است، میتواند بصورت دستی توسط شما تصحیح گردد. البته جهت اعمال تغییرات می بایست {APP_NAME} بارگذاری مجدد گردد.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \" متاسفم! {APP_NAME}اکنون در این مرورگر اجرا نمیشود .\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} در اچ تی ام ال ساخته شده است, اما در حال حاضر آن به عنوان یک نرم افزار در دسکتاپ اجرا میشود بنابراین شما میتوانید جهت ویرایش فایل ها از آن استفاده کنید. لطفا از اپلیکیشن shell در <b>github.com/adobe/brackets-shell</b> جهت اجرای مخازن  {APP_NAME} استفاده کنید.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"خطا در فهرست بندی پرونده ها\",\n    \"ERROR_MAX_FILES\"                   : \"این پروژه شامل بیش از 30000 فایل است. امکانات که در فایل های چندگانه کار می کنند ممکن است غیرفعال و یا به عنوان پروژه خالی در نظر گرفته شوند. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>اطلاعات بیشتر در مورد کار با پروژه های بزرگ</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"خطا در اجرای مرورگر\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"مرورگر گوگل کروم پیدا نشد. لطفا از نصب بودن آن اطمینان حاصل کنید.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"بروز خطا بهنگام اجرای مرورگر. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"خطا در پیش نمایش زنده\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"در حال اتصال به مرورگر\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"به هر صورت بهنگام اتصال به حالت پیش نمایش, مرورگر کروم احتیاج دارد به فعال بودن اشکال زدای راه دور (خطایابی راه دور).<br /><br />آیا تمایل دارید به اجرای دوباره کروم و فعال سازی اشکال زدای راه دور(اشکال زدایی از راه دور)?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"ناتوان در بارگذاری صفحه توسعه زنده.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"باز کنید یک فایل اچ تی ام ال و یا مطمئن شوید که یک فایل index.html در پروژه شما جهت راه اندازی پیش نمایش زنده وجود دارد.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"جهت اجرای پیش نمایش زنده بصورت پرونده در سمت سرور(server-side), می بایست یک URL پایه برای پروژه تعریف نمایید.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"خطا در اجرای سرویس دهنده HTTP برای توسعه زنده پرونده ها. لطفا دوباره تلاش کنید\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"به پیش نمایش زنده خوش آمدید!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     :  \"پیش نمایش زنده براکتس به مرورگر متصل شده و یک پیش نمایش از پرونده اچ تی ام ال شما در مرورگرتان نشان خواهد داد, و هرگونه تغییری در کدهایتان را فورا در پیش نمایش اعمال خواهد نمود.<br /><br />در این نسخه موجود براکتس, پیش نمایش تنها با مرورگر <strong>گوگل کروم</strong> برای اعمال فوری مقادیر <strong>فایل های سی اس اس </strong> برای حالت پیش نمایش کار خواهد کرد. هرگونه تغییری در پرونده های اچ تی ام ال یا جاوا اسکریپت بصورت خودکار بعد از ذخیر بارگذاری خواهد شد.<br /><br />(شما این پیغام را برای بار دیگر مشاهده نخواهید کرد.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"برای اطلاعات بیشتر, ببینید <a href='{0}' title='{0}'>عیب یابی خطاهای اتصال پیش نمایش زنده</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"پیش نمایش زنده\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"پیش نمایش زنده: درحال اتصال\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"پیش نمایش زنده: درحال مقداردهی اولیه\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"قطع اتصال از پیش نمایش زنده\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"پیش نمایش زنده (ذخیره فایل ها جهت نوسازی)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"پیش نمایش زنده (به دلیل خطا در سینتکس، بروزرسانی نشده است)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" :  \"پیش نمایش زنده لغو شد زیرا از برخی از ابزارهای توسعه مختص مرورگرتان استفاده کرده اید.\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"پیش نمایش زنده لغو شد زیرا پنجره یا زبانه مربوط به صفحه در مرورگر بسته شده.\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"پیش نمایش زنده لغو شد زیرا پنجره یا زبانه موجود در مرورگر آدرس دیگری را پیمایش کرده است.\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"پیش نمایش زنده به دلیل نامشخصی لغو شد ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                      : \"ذخیره تغییرات\",\n    \"SAVE_CLOSE_MESSAGE\"                    : \"آیا مایلید تغییرات داده شده در سند ذخیره گردند <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"              : \"آیا مایلید تغییرات داده شده در پرونده های زیر، ذخیره گردند?    \",\n    \"EXT_MODIFIED_TITLE\"                    : \"تغییرات خارجی\",\n    \"CONFIRM_DELETE_TITLE\"                  : \"تایید حذف\",\n    \"CONFIRM_FOLDER_DELETE\"                 : \"آیا مطمئنید می خواهید این پوشه حذف گردد <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                    : \"پرونده حذف گردید\",\n    \"EXT_MODIFIED_WARNING\"                  : \"<span class='dialog-filename'>{0}</span> خارج از براکتس ویرایش شده.<br /><br />آیا می خواهید پرونده را ذخیره و تغییراتی را که داده اید دوباره بر روی پرونده ویرایش شده اعمال نمایید؟\",\n    \"EXT_MODIFIED_MESSAGE\"                  :   \"<span class='dialog-filename'>{0}</span> تغییراتی بر روی دیسک انجام شده, ولی تغییرات بر روی براکتس ذخیره نگردیده.<br /><br />کدام نسخه را می خواهید نگه دارید?\",\n    \"EXT_DELETED_MESSAGE\"                   : \"<span class='dialog-filename'>{0}</span> برخی مقادیر از دیسک حذف شده, ولی تغییرات بر روی براکتس اعمال/ذخیره نشده.<br /><br />آیا می خواهید تغییرات را حفظ کنید?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                                  : \"انجام\",\n    \"OK\"                                    : \"تائید\",\n    \"CANCEL\"                                : \"لغو\",\n    \"DONT_SAVE\"                             : \"ذخیره نکن\",\n    \"SAVE\"                                  : \"ذخیره\",\n    \"SAVE_AS\"                               : \"ذخیر با نام\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                    : \"بازنویسی\",\n    \"DELETE\"                                : \"حذف\",\n    \"BUTTON_YES\"                            : \"بله\",\n    \"BUTTON_NO\"                             : \"خیر\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                      : \"{0} از {1}\",\n    \"FIND_NO_RESULTS\"                       : \"بدون نتیجه\",\n    \"FIND_QUERY_PLACEHOLDER\"                : \"جستجو\\u2026\",\n    \"REPLACE_PLACEHOLDER\"                   : \"جایگزینی با\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                    : \"همه\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"           : \"جایگزینی\\u2026\",\n    \"BUTTON_REPLACE\"                        : \"جایگزینی\",\n    \"BUTTON_NEXT\"                           : \"\\u25B6\",\n    \"BUTTON_PREV\"                           : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                      : \"مورد بعدی\",\n    \"BUTTON_PREV_HINT\"                      : \"مورد قبلی\",\n    \"BUTTON_CASESENSITIVE_HINT\"             : \"مورد تطبیق یافته\",\n    \"BUTTON_REGEXP_HINT\"                    : \"عبارت منظم\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\"    : \"جایگزینی بدون امکان بازگشت به قبل\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"          : \"بدلیل اعمال تغییر در تعداد {0} پرونده, {APP_NAME} پرونده های باز نشده را نیز ویرایش و تغییر خواهد داد. به همین جهت مقادیر تغییر یافته (جایگزین شده) غیر قابل بازگشت خواهند بود.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"           : \"جایگزینی بدون بازگشت\",\n\n    \"OPEN_FILE\"                             : \"باز کردن پرونده\",\n    \"SAVE_FILE_AS\"                          : \"ذخیره پرونده\",\n    \"CHOOSE_FOLDER\"                         : \"انتخاب یک پوشه\",\n\n    \"RELEASE_NOTES\"                         : \"نکات و یادداشت های انتشار\",\n    \"NO_UPDATE_TITLE\"                       : \"شما بروز هستید!!\",\n    \"NO_UPDATE_MESSAGE\"                     : \"شما درحال استفاده از آخرین نسخه  {APP_NAME} هستید.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"              : \"جایگزینی\",\n    \"FIND_REPLACE_TITLE_WITH\"               : \"با\",\n    \"FIND_TITLE_LABEL\"                      : \"جستجو\",\n    \"FIND_TITLE_SUMMARY\"                    : \"&mdash; {0} {1} {2} با {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                        : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"                  : \"در <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"                : \"در پروژه\",\n    \"FIND_IN_FILES_ZERO_FILES\"              : \"فیلترسازی تمامی پرونده های منع شده {0}\",\n    \"FIND_IN_FILES_FILE\"                    : \"پرونده\",\n    \"FIND_IN_FILES_FILES\"                   : \"پرونده ها\",\n    \"FIND_IN_FILES_MATCH\"                   : \"تطبیق\",\n    \"FIND_IN_FILES_MATCHES\"                 : \"تطبیق ها\",\n    \"FIND_IN_FILES_MORE_THAN\"               : \"بیش تر از \",\n    \"FIND_IN_FILES_PAGING\"                  : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"               : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"         : \"جهت بازکردن/بستن منوها کلید Ctrl/Cmd را گرفته و کلیک کنید.\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"         : \"خطاهای جایگزینی مقادیر\",\n    \"REPLACE_IN_FILES_ERRORS\"               : \"پرونده های زیر قابل ویرایش نبودن. علت می تواند از قابل نوشتن نبودن پرونده های و یا تغییر آن های بعد از جستجو باشد.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"      : \"درحال بروزرسانی اطلاعات خطا\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"        :  \"بروز خطا در هنگام دستیابی به آخرین اطلاعات بروزرسانی از سرویس دهنده. اطمینان حاصل کنید که به اینترنت متصل بوده و دوباره تلاش نمایید.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                       : \"اعمال یک تصویه(فیلتر) جدید\\u2026\",\n    \"CLEAR_FILE_FILTER\"                     : \"رفع نادیده گیری پرونده ها\",\n    \"NO_FILE_FILTER\"                        : \"این پرونده ها از پرونده های نادیده گرفته شده نیستند\",\n    \"EXCLUDE_FILE_FILTER\"                   : \"نادیده گیری {0}\",\n    \"EDIT_FILE_FILTER\"                      : \"ویرایش\\u2026\",\n    \"FILE_FILTER_DIALOG\"                    : \"ویرایش نادیده گرفته شده ها\",\n    \"FILE_FILTER_INSTRUCTIONS\"              : \"نادیده گیری پرونده ها و پوشه های منطبق با عبارات زیر یا برخی / substrings or <a href='{0}' title='{0}'>نویسه های عام</a>. هر عبارت را در یک سطر جدید وارد کنید.\",\n    \"FILTER_NAME_PLACEHOLDER\"               : \"منع نام (اختیاری)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"            : \"و {0} بیشتر\",\n    \"FILTER_COUNTING_FILES\"                 : \"شمارش پرونده ها\\u2026\",\n    \"FILTER_FILE_COUNT\"                     : \"همیشه {0} از {1} پرونده {2}\",\n    \"FILTER_FILE_COUNT_ALL\"                 : \"تایید {0} پرونده {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"امکان ویرایش سریع برای مکان فعلی نشانگر موجود نمی باشد\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"ویرایشگر سریع CSS: نشانگر را روی یک کلاس قرار دهید\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"ویرایشگر سریع CSS: صفات/خصوصیات این کلاس کامل نیست\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"ویرایشگر سریع CSS: صفات/خصوصیات این id کامل نیست\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"ویرایشگر سریع CSS: نشانگر را بر روی یک تگ، کلاس یا id قرار دهید\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"تابع زمانبندی ویرایشگر سریع CSS: خطا در نحو\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"ویرایشگر سریع JS: نشانگر را روی نام تابع قرار دهید\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"سند سریع برای مکان فعلی نمایشگر مکان موجود نمی باشد\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"                       : \"درحال بارگذاری\\u2026\",\n    \"UNTITLED\"                              : \"عنوان گذاری نشده\",\n    \"WORKING_FILES\"                         : \"پرونده های کاری\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"                                   : \"بالا\",\n    \"BOTTOM\"                                : \"پایین\",\n    \"LEFT\"                                  : \"چپ\",\n    \"RIGHT\"                                 : \"راست\",\n\n    \"CMD_SPLITVIEW_NONE\"                    : \"بدون دو بخشی کردن\",\n    \"CMD_SPLITVIEW_VERTICAL\"                : \"دو بخشی کردن عمودی\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"              : \"دو بخشی کردن افقی\",\n    \"SPLITVIEW_MENU_TOOLTIP\"                : \"دو بخشی کردن ویرایشگر به صورت عمودی یا افقی\",\n    \"GEAR_MENU_TOOLTIP\"                     : \"پیکربندی پرونده های کاری\",\n\n    \"SPLITVIEW_INFO_TITLE\"                  : \"هم اکنون باز است\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"           :  \"این پرونده هم اکنون در پنجره ای دیگر باز شده است. {APP_NAME} بزودی باز کردن همان پرونده در سایر پنجره ها را پشتیبانی خواهد نمود. تا آن زمان پرونده ها تنها در پنجره ای که باز شده اند نمایش داده خواند شد.<br /><br />(این پیغام تنها یک بار مشاهده خواهد شد.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"                         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"                        : \"Shift\",\n    \"KEYBOARD_SPACE\"                        : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"خط {0}, ستون {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} ستون انتخاب شده\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} ستون های انتخاب شده\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} خط انتخاب شده\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} خط های انتخاب شده\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} انتخاب شده ها\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"کلیک کنید تا به این فضاها منتقل شوید\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"کلیک کنید تا به این زبانه ها منتقل شوید\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"جهت تغییر تعداد فضاهای خالی استفاده شده در هنگام فاصله دهی خطوط از چپ، کلیک کنید\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"کلیک کنید تا طول زبانه کاراکتر ها تغییر کند\",\n    \"STATUSBAR_SPACES\"                      : \"فاصله ها:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"اندازه زبانه:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} خط\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} خط ها\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"غیرفعال سازی افزونه ها\",\n    \"STATUSBAR_INSERT\"                      : \"واردسازی\",\n    \"STATUSBAR_OVERWRITE\"                   : \"دوباره نویسی\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"جهت تغییر حالت از وارد سازی (INS) به بازنویسی (OVR) یا برعکس، کلیک کنید\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"جهت تغییر نوع پرونده، کلیک کنید.\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. باز و بسته کردن پنل گزارشات.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(پیش فرض)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \" اعمال بعنوان پیش فرض برای .{0} پرونده ها\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \" {0} خطا\",\n    \"SINGLE_ERROR\"                          : \" 1 {0} خطا\",\n    \"MULTIPLE_ERRORS\"                       : \" {1} {0} خطا\",\n    \"NO_ERRORS\"                             : \"هیچ خطایی یافت نشد {0} - کارت خوبه!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"خطایی پیدا نشد - کارت خوبه!\",\n    \"LINT_DISABLED\"                         : \"Linting غیرفعال شد\",\n    \"NO_LINT_AVAILABLE\"                     : \"linter برای {0} دردسترس نیست\",\n    \"NOTHING_TO_LINT\"                       : \"linter برای {0} دردسترس نیست\",\n    \"LINTER_TIMED_OUT\"                      : \"فعالیت{0} پس از انتظار بمدت{1} میلی ثانیه خاتمه یافت\",\n    \"LINTER_FAILED\"                         : \"{0} با خطای زیر پایان یافته: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"فایل\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"جدید\",\n    \"CMD_FILE_NEW\"                        : \"فایل جدید\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"پوشه جدید\",\n    \"CMD_FILE_OPEN\"                       : \"باز کردن\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"افزودن به محیط کاری و باز کردن آن\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"باز کردن پرونده های در نظر گرفته نشده\",\n    \"CMD_OPEN_FOLDER\"                     : \"باز کردن پوشه\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"بستن\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"بستن همه\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"بستن لیست\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"بستن سایر موارد\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"بستن موارد بالایی\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"بستن موارد پایینی\",\n    \"CMD_FILE_SAVE\"                       : \"ذخیره\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"ذخیره همه\",\n    \"CMD_FILE_SAVE_AS\"                    : \"ذخیره با نام\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"پیش نمایش زنده\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"فعال کردن پیش نمایش تجربی\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"بارگذاری مجدد پیش نمایش زنده (با فشار)\",\n    \"CMD_PROJECT_SETTINGS\"                : \"تنظیمات پروژه\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"تغییر نام\",\n    \"CMD_FILE_DELETE\"                     : \"حذف\",\n    \"CMD_INSTALL_EXTENSION\"               : \"نصب افزونه \\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"مدیریت افزونه\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"نوسازی درختی پرونده\",\n    \"CMD_QUIT\"                            : \"ترک کردن\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"خروج\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"ویرایش\",\n    \"CMD_UNDO\"                            : \"یک مرحله به قبل\",\n    \"CMD_REDO\"                            : \"یک مرحله به بعد\",\n    \"CMD_CUT\"                             : \"بریدن\",\n    \"CMD_COPY\"                            : \"رونوشت\",\n    \"CMD_PASTE\"                           : \"چسباندن رو نوشت\",\n    \"CMD_SELECT_ALL\"                      : \"انتخاب همه\",\n    \"CMD_SELECT_LINE\"                     : \"انتخاب خط\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"تقسیم انتخاب شده به چند سطر\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"افزودن نشانگر به سطر بعدی\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"افزودن نشانگر به سطر قبلی\",\n    \"CMD_INDENT\"                          : \"یک فاصله از چپ\",\n    \"CMD_UNINDENT\"                        : \"حذف یک فاصله از چپ\",\n    \"CMD_DUPLICATE\"                       : \"دو نسخه کردن خط\",\n    \"CMD_DELETE_LINES\"                    : \"حذف خط\",\n    \"CMD_COMMENT\"                         : \"تعویض خط به نظر\",\n    \"CMD_BLOCK_COMMENT\"                   : \"تعویض نظر به خط\",\n    \"CMD_LINE_UP\"                         : \"خط را یکی به بالا ببر\",\n    \"CMD_LINE_DOWN\"                       : \"خط را یکی به پایین ببر\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"باز کردن خط بالا\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"باز کردن خط زیرین\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"پرانتزها را خودکار ببند\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"نمایش نکات کد\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"جستجو\",\n    \"CMD_FIND\"                            : \"یافتن\",\n    \"CMD_FIND_NEXT\"                       : \"یافتن بعدی\",\n    \"CMD_FIND_PREVIOUS\"                   : \"یافتن قبلی\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"جستجو برای تمامی موارد و انتخاب آن ها\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"عبارت انطباق یافته بعدی را به انتخاب شده ها اضافه کن\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"پرش از این مورد و افزودن مورد انطباق یافته بعدی\",\n    \"CMD_FIND_IN_FILES\"                   : \"جستجو در پرونده ها\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"جستجو در\\u2026\",\n    \"CMD_REPLACE\"                         : \"جایگزینی\",\n    \"CMD_REPLACE_IN_FILES\"                : \"جایگزینی در پرونده ها\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"جایگزینی در\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"نمایش\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"پنهان کردن نوار کناری\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"نمایش نوار کناری\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"افزایش سایز نوشته ها\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"کاهش سایز نوشته ها\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"پیشفرض سایز نوشته ها\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"حرکت به بالا\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"حرکت به پایین\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"شماره گذاری خط ها\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"نشانه گذاری خط فعال\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"شکستن عبارات طولانی\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"نشانه گذاری پیش نمایش\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"نشانه گذاری پرونده های تغییر یافته برای ذخیره سازی\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"مرتب سازی بر اساس ترتیب اضافه شدن\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"مرتب سازی بر اساس نام\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"مرتب سازی بر اساس نوع\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"مرتب سازی خودکار\",\n    \"CMD_THEMES\"                          : \"پوسته ها\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"انتقال\",\n    \"CMD_QUICK_OPEN\"                      : \"باز کردن سریع\",\n    \"CMD_GOTO_LINE\"                       : \"برو به خط\",\n    \"CMD_GOTO_DEFINITION\"                 : \"تعریف جستجوی سریع\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"رجوع به اولین خطا/اخطار\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"ویرایش سریع\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"مستند گزاری سریع\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"تطبیق یافته قبلی\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"تطبیق یافته بعدی\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"قاعده جدید\",\n    \"CMD_NEXT_DOC\"                        : \"سند بعدی\",\n    \"CMD_PREV_DOC\"                        : \"سند قبلی\",\n    \"CMD_SHOW_IN_TREE\"                    : \"نمایش در پرونده ها به صورت درختی\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"نمایش در پیمایشگر\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"نمایش در جستجوگر\",\n    \"CMD_SHOW_IN_OS\"                      : \"نمایش در OS\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"راهنما\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"بررسی بروزرسانی ها\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"چگونگی استفاده از {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} پشتیبانی\",\n    \"CMD_SUGGEST\"                         : \"پیشنهاد یک امکان جدید\",\n    \"CMD_RELEASE_NOTES\"                   : \"نکات انتشار\",\n    \"CMD_GET_INVOLVED\"                    : \"درگیرش شوید\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"نمایش پوشه افزونه ها\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} صفحه اصلی سایت\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} در توییتر\",\n    \"CMD_ABOUT\"                           : \"درباره {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"تنظیمات باز کردن فایل\",\n    \"CMD_OPEN_KEYMAP\"                     : \"باز کردن نقشه کلیدهای کاربردی\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"ساخت آزمایشی\",\n    \"RELEASE_BUILD\"                        : \"ساختن و انتشار\",\n    \"DEVELOPMENT_BUILD\"                    : \"ایجاد توسعه\",\n    \"RELOAD_FROM_DISK\"                     : \"بارگذاری مجدد از دیسک\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"نگه داشتن تغییرات در ویرایشگر\",\n    \"CLOSE_DONT_SAVE\"                      : \"بستن (بدون ذخیره سازی)\",\n    \"RELAUNCH_CHROME\"                      : \"اجرای دوباره کروم\",\n    \"ABOUT\"                                : \"پیرامون\",\n    \"CLOSE\"                                : \"بستن\",\n    \"ABOUT_TEXT_LINE1\"                     : \"انتشار {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"ایجاد برچسب زمان: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"<div style='direction:rtl;margin-right:3px;'>یادداشت ها، شرایط و ضوابط مربوط به نرم افزار و حقوق شخص ثالث در آدرس<a href='#' class='clickable-link' data-href='http://www.adobe.com/go/thirdparty/'>http://www.adobe.com/go/thirdparty/</a> جهت تلفیق و بعنوان مرجع قرار داده شده.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"اسناد و منابع در <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"ساخته شده با \\u2764 و جاوا اسکریپت توسط:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"بسیاری از مردم (اما اکنون در بارگذاری داده ها ما مشکل داریم ).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"اسناد و مدارک صفحات وب و آرم اصلی گرافیکی تحت مجوز , <a href='#' class='clickable-link' data-href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 .پایه ریزی شده است</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"ساخته ی جدیدی از {APP_NAME} هم اکنون در دسترس است! جهت مشاهده جزئیات کلیک کنید.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"بروزرسانی جدید در دسترس است\",\n    \"UPDATE_MESSAGE\"                       : \"نسخه جدیدی از {APP_NAME} هم اکنون در دسترس است. برخی از مشخصه های آن:\",\n    \"GET_IT_NOW\"                           : \"اکنون برو به!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"تنظیمات پروژه برای: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"پیش نمایش URL اصلی/پایه\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"جهت استفاده از سرویس دهنده داخلی, از url بمانند http://localhost:8000/ استفاده کنید.\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"پروتکول {0} با پیش نمایش زنده پشتیبانی نمی شود&mdash;لطفا از http: یا https: استفاده نمایید.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL اصلی نمی تواند شامل پارامترهای جستجو بمانند \\\"{0}\\\" باشد.\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL اصلی نمی تواند hashes مشابه \\\"{0}\\\" داشته باشد.\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"برخی کاراکترهای خاص شبیه '{0}' می بایست %-encoded.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"خطای ناشناخته در URL اصلی/پایه\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>انتخاب کنید یک فایلی را در حالی که بر روی این قسمت تمرکز شده است</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"پوسته فعلی\",\n    \"USE_THEME_SCROLLBARS\"                 : \"استفاده از نوار شناور پوسته\",\n    \"FONT_SIZE\"                            : \"اندازه قلم\",\n    \"FONT_FAMILY\"                          : \"نوع قلم\",\n    \"THEMES_SETTINGS\"                      : \"تنظیمات پوسته ها\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"قائده جدید\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"نصب\",\n    \"UPDATE\"                               : \"بروزرسانی\",\n    \"REMOVE\"                               : \"حذف\",\n    \"OVERWRITE\"                            : \"دوباره نویسی\",\n    \"CANT_REMOVE_DEV\"                      : \"افزونه های موجود در پوشه \\\"dev\\\" می بایست بصورت دستی حذف گردند.\",\n    \"CANT_UPDATE\"                          : \"بروزرسانی سازگار با این نسخه از {APP_NAME} نیست.\",\n    \"CANT_UPDATE_DEV\"                      : \"افزونه موجود در پوشه \\\"dev\\\" قادر به بروزرسانی خودکار نیست\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"نصب افزونه\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"بروزرسانی افزونه\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL افزونه\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL افزونه های دارای پرونده zip یا مخازن Github\",\n    \"INSTALLING_FROM\"                      : \"نصب افزونه ها از {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"نصب با موفقیت به اتمام رسید!\",\n    \"INSTALL_FAILED\"                       : \"نصب ناموفق.\",\n    \"CANCELING_INSTALL\"                    : \"درحال لغو\\u2026\",\n    \"CANCELING_HUNG\"                       : \"عملیات لغو نصب زمان طولانی ای به طول خواهد کشید. خطا یا خطاهای داخلی ممکن است رخ دهد.\",\n    \"INSTALL_CANCELED\"                     : \"فرایند نصب لغو گردید.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"مشاهده توضیح کامل\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"مشاهده توضیح مختصر\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"محتوای دانلود شده دارای پرونده zip معتبر نمی باشد.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"پرونده package.json معتبر نمی باشد (error was: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"پرونده package.json دارای خطا در نام می باشد.\",\n    \"BAD_PACKAGE_NAME\"                     : \"نام بسته {0} نامعتبر می باشد.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"پرونده package.json دارای خطا در نسخه می باشد.\",\n    \"INVALID_VERSION_NUMBER\"               : \"عدد نسخه این بسته ({0}) نامعتبر می باشد.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"خطا در سازگاری {APP_NAME} با رشته نامعتبر({0}).\",\n    \"DISALLOWED_WORDS\"                     : \"عبارت ({1}) اجازه وارد سازی در این فیلد را ندارد {0}\",\n    \"API_NOT_COMPATIBLE\"                   : \"افزونه با این نسخه از برنامه {APP_NAME} سازگار نیست. در پوشه افزونه های قابل نمایش نصب نشد.\",\n    \"MISSING_MAIN\"                         : \"بسته حاوی پرونده main.js نیست.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"نصب این بسته سبب دوباره نویسی پرونده های افزونه قبلی می شود. دوباره نویسی صورت گیرد?\",\n    \"EXTENSION_SAME_VERSION\"               : \"نسخه این بسته با نسخه بسته ای که هم اکنون نصب می باشد برابر است. آیا افزونه دوباره نویسی گردد?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"این بسته نسخه {0} هست قبل تر نصب شده({1}). آیا این افزونه دوباره نویسی گردد?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"خطای داخلی: این ID دانلود هم اکنون درحال استفاده است.\",\n    \"NO_SERVER_RESPONSE\"                   : \"ناتوان در اتصال به سرویس دهنده.\",\n    \"BAD_HTTP_STATUS\"                      : \"پرونده در سرویس دهنده یافت نشد (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"ناتوان در ذخیره دانلود در یک پرونده خالی.\",\n    \"ERROR_LOADING\"                        : \"این افزونه بهنگام شروع با خطا مواجه می شود.\",\n    \"MALFORMED_URL\"                        : \"آدرس URL نامعتبر است. لطفا آن را بررسی کرده و آدرس معتبر وارد سازید.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"آدرس URL می بایست http یا https باشد.\",\n    \"UNKNOWN_ERROR\"                        : \"خطای داخلی نامشخص.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"مدیریت افزونه ها\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"ناتوان در دسترسی به افزونه های ثبت شده. لطفا بعدا تلاش کنید.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"پرونده زیپ را اینجا بکشید و یا\",\n    \"INSTALL_EXTENSION_DROP\"               : \"پرونده زیپ را رها کنید تا نصب شود\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"نصب/بروزرسانی لغو شد، لطفا خطاهای زیر را بررسی کنید:\",\n    \"INSTALL_FROM_URL\"                     : \"نصب کنید از آدرس اینترنتی\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"بررسی صحت پرونده\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"نویسنده\",\n    \"EXTENSION_DATE\"                       : \"تاریخ\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"این افزونه نیاز به نسخه جدیدی از {APP_NAME} دارد.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \" نسخه فعلی این افزونه فقط با نسخه های قبلی {APP_NAME} سازگار است.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"نسخه {0} از این افزونه نیازمند نسخه جدیدی از {APP_NAME} می باشد. ولی شما می توانید یک نسخه پایین تر از {1} را نصب کنید.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"نسخه {0} از این افزونه فقط با نسخه قدیمی از {APP_NAME} کار می کند. اما شما به راحتی می توانید نصب کنید نسخه {1} را \",\n\n\n    \"EXTENSION_NO_DESCRIPTION\"             : \"بدون شرح\",\n    \"EXTENSION_MORE_INFO\"                  : \"اطلاعات بیشتر...\",\n    \"EXTENSION_ERROR\"                      : \"خطای افزونه\",\n    \"EXTENSION_KEYWORDS\"                   : \"کلمات کلیدی\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"ترجمه شده به زبان های {0} که زبان شما را نیز در بر دارد\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"ترجمه شده به زبان های {0}\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \" این افزونه تنها برای زبان های زیر ترجمه شده است: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"نصب شده\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"بروزرسانی این افزونه دانلود و بعد از بارگذاری مجدد  {APP_NAME} نصب می شود.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"جستجو\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"بیشتر\",\n    \"BROWSE_EXTENSIONS\"                    : \"پیمایش افزونه ها\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"حذف براکتس\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"ناتوان در حذف یک یا بیشتر از یک افزونه : {0}. {APP_NAME} در حال بارگذاری مجدد.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"بروزرسانی افزونه\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"ناتوان در بروزرسانی یک افزونه یا بیشتر: {0}. {APP_NAME} در حال برگذاری مجدد.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"نشانه گذاری جهت حذف\",\n    \"UNDO_REMOVE\"                          : \"مرحله قبل\",\n    \"MARKED_FOR_UPDATE\"                    : \"انتخاب شده برای بروزرسانی\",\n    \"UNDO_UPDATE\"                          : \"مرحله قبل\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"تغییر افزونه ها و بارگذاری مجدد\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"جهت بروزرسانی یا حذف افزونه ها, {APP_NAME} براکتس احتیاج به بارگذاری مجدد دارد. تغییرات ذخیره نشده شما ذخیره خواهد شد.\",\n    \"REMOVE_AND_RELOAD\"                    : \"حذف افزونه ها و بارگذاری مجدد\",\n    \"CHANGE_AND_RELOAD\"                    : \"تغییر افزونه ها و بارگذاری مجدد\",\n    \"UPDATE_AND_RELOAD\"                    : \"بروزرسانی افزونه ها و بارگذاری مجدد\",\n    \"PROCESSING_EXTENSIONS\"                : \"درحال پردازش تغییرات\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"ناتوان در حذف افزونه {0} زیرا این افزونه به درستی نصب نشده.\",\n    \"NO_EXTENSIONS\"                        : \"هیچ افزونه ای نصب نشده.<br>جهت شروع بر روی زبانه در دسترس بالا کلیک کنید.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"هیچ افزونه ای منطبق با جستجوی شما پیدا نشد\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"نکته: این افزونه ها ممکن است از نویسندگان مختلفی که براکتس را خودشان توسعه داده اند و متعلق به خوشان است باشند. افزونه ها بررسی نشده اند و امتیازات کاملا محلی هستند. احتیاط کنید در هنگام نصب افزونه هایی که منبع مشخصی ندارند.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"نصب شده\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"در دسترس\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"پوسته ها\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"بروزرسانی ها\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"هیچ مورد سازگاری در دسترس نیست.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"تمام سازگاری ها فرو ریخته هستند. گسترش فایل های ذکر شده در سمت راست جهت نمایش سازگاری.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            :  \"هیچ قائده منطبقی برای CSSها نسبت به موردی که انتخاب کرده اید وجود ندارد.<br> از گزینه \\\"قائده جدید\\\" برای تعریف یک قائده جدید استفاده کنید.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"هیچ شیوه نامه ای-پرونده CSS- در پروژه شما وجود ندارد.<br>جهت تعریف قوائد CSS ابتدا یک پرونده شیوه نامه ایجاد کنید.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"بزرگتر\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"پیکسل\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"خطایابی\",\n    \"ERRORS\"                                    : \"خطاها\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"نمایش ابزار توسعه\",\n    \"CMD_REFRESH_WINDOW\"                        : \"بارگذاری مجدد با افزونه ها\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"بارگذاری مجدد بدون افزونه ها\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"پنجره جدید از {APP_NAME} باز کنید.\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"تغییر زبان\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"بررسی برای اجرا\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"نمایش داده های عملکردی\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"فعال سازی اشکال زدای گره ای\",\n    \"CMD_LOG_NODE_STATE\"                        : \"ورود گره به حالت کنسول\",\n    \"CMD_RESTART_NODE\"                          : \"شروع دوباره گره\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"نمایش خطاها در نوار وظیفه\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"باز کردن منبع براکتس\",\n\n    \"LANGUAGE_TITLE\"                            : \"تغییر زبان\",\n    \"LANGUAGE_MESSAGE\"                          : \"زبان:\",\n    \"LANGUAGE_SUBMIT\"                           : \"بارگذاری مجدد {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"لغو\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"پیشفرض سیستم\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"زمان\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"پیشرفت\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> انتخاب حرکت نشانگر<br><kbd class='text'>شیفت</kbd>حرکت با ده واحد<br><kbd class='text'>تب</kbd> نقاط تغییر\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd>افزایش و یا کاهش گام<br><kbd>←</kbd><kbd>→</kbd> 'شروع' or 'پایان'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"مقدار سابق <code>{0}</code> دیگر معتبر نمی باشد, زیرا تابع نمایش به مقدار <code>{1}</code> تغییر یافته. سند در اولین ویرایش بروزرسانی خواهد شد.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"رنگ فعلی\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"رنگ اصلی\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa قالب\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex قالب\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa قالب\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} ({1} بار استفاده شده)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} ({1} بار استفاده شده)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"پرش جهت تعریف\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"نمایش نکات پارامتر\",\n    \"NO_ARGUMENTS\"                              : \"<بدون پارامترها>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"خطای منطقی در پرونده جاوا اسکریپت\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"براکتس در حال انجام یک پردازش مشکل دار با پرونده <span class='dialog-filename'>{0}</span> است.<br><br>این پرونده اشاره گرهای کدها را بطور کامل نشان نخواهد داد, برای این منظور میتوانید از حالت تعریف یا ویرایش سریع استفاده نمایید. جهت فعال سازی دوباره این پرونده, <code>.brackets.json</code> را در پروژه خود باز کنید و <code>jscodehints.detectedExclusions</code> را ویرایش نمایید.<br><br>این مشکل میتواند یک Bug در براکتس باشد. اگر مشکلی در ارائه این پرونده به ما ندارید, لطفا گزارش <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>پرونده دارای اشکال</a> را با یک لینک به پرونده جهت بررسی ثبت نمایید.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"مشاهده سریع بهنگام اشاره با ماوس\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"پروژه های اخیر\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"بیشتر بخوانید\"\n});\n/* Last translated for eef9c68a1fdff372b9ea6352cacb5e2506e55be9 */\n"
  },
  {
    "path": "src/nls/fa-ir/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"fa-ir/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.fa\"\n});\n"
  },
  {
    "path": "src/nls/fi/strings.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(virhe {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Tiedostoa tai hakemistoa ei löytynyt.\",\n    \"NOT_READABLE_ERR\"                  : \"Tiedostoa tai hakemistoa ei voitu lukea.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Yli {0} Mt:n tiedostoja ei voi avata {APP_NAME}issa.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Kohdehakemistoa ei voi muuttaa.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Sinulla ei ole oikeuksia tehdä muutoksia.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Tiedostoa on muokattu {APP_NAME}in ulkopuolella.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"Tuntematon enkoodausmuoto\",\n    \"ENCODE_FILE_FAILED_ERR\"            : \"{APP_NAME} ei voinut enkoodata tämän tiedoston sisältöä.\",\n    \"DECODE_FILE_FAILED_ERR\"            : \"{APP_NAME} ei voinut dekoodata tämän tiedoston sisältöä.\",\n    \"UNSUPPORTED_UTF16_ENCODING_ERR\"    : \"{APP_NAME} ei tällä hetkellä tue UTF-16-koodattuja tiedostoja.\",\n    \"FILE_EXISTS_ERR\"                   : \"Tiedosto tai hakemisto on jo olemassa.\",\n    \"FILE\"                              : \"tiedosto\",\n    \"FILE_TITLE\"                        : \"tiedosto\",\n    \"DIRECTORY\"                         : \"hakemisto\",\n    \"DIRECTORY_TITLE\"                   : \"hakemisto\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Hakemistojen nimet\",\n    \"FILENAMES_LEDE\"                    : \"Tiedostonimet\",\n    \"FILENAME\"                          : \"tiedostonimi\",\n    \"DIRECTORY_NAME\"                    : \"hakemiston nimi\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Virhe projektia ladattaessa\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Tapahtui virhe avattaessa tiedostonvalintaikkunaa. (Virhe {0}.)\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Tapahtui virhe yritettäessä avata hakemistoa <span class='dialog-filename'>{0}</span>. (Virhe {1}.)\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Tapahtui virhe luettaessa hakemiston <span class='dialog-filename'>{0}</span> sisältöä. (Virhe {1}.)\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Virhe tiedostoa avattaessa\",\n    \"ERROR_OPENING_FILE\"                : \"Tapahtui virhe yritettäessä avata tiedostoa <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Tapahtui virhe yritettäessä avata seuraavia tiedostoja:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Virhe päivitettäessä muutoksia levyltä\",\n    \"ERROR_RELOADING_FILE\"              : \"Tapahtui virhe yritettäessä päivittää tiedostoa <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Virhe tallennettaessa tiedostoa\",\n    \"ERROR_SAVING_FILE\"                 : \"Tapahtui virhe yritettäessä tallentaa tiedostoa <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Virhe nimettäessä {0}a uudelleen\",\n    \"ERROR_RENAMING_FILE\"               : \"Tapahtui virhe yritettäessä nimetä uudelleen {2}a <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Tiedosto tai hakemisto ei kuulu avoinna olevaan projektiin. Valitettavasti vain projektin tiedostoja voi nimetä uudelleen tällä hetkellä.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Virhe poistettaessa {0}a\",\n    \"ERROR_DELETING_FILE\"               : \"Tapahtui virhe yritettäessä poistaa {2}a <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Virheellinen {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} ei voi käyttää mitään järjestelmän varaamia sanoja, päättyä pisteeseen (.) tai käyttää mitään seuraavista merkeistä: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Tiedosto tai hakemisto nimellä <span class='dialog-filename'>{0}</span> on jo olemassa.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Virhe luotaessa {0}a\",\n    \"ERROR_CREATING_FILE\"               : \"Virhe yritettäessä luoda {0}a <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Kansiota ei voi avata samaan aikaan muiden tiedostojen kanssa.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Virhe käyttäjän näppäinkarttaa luettaessa\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Näppäinkarttatiedostossasi on virheellistä JSON-koodia. Tiedosto aukeaa, niin voit korjata sen muodon.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Näppäinkarttatiedostosi ei ole UTF-8-koodattu tai tekstimuotoinen, joten sitä ei voi ladata.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Seuraavien komentojen näppäinyhdistelmiä ei voi määrittää uudelleen: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Seuraavia näppäinyhdistelmiä ei voi määrittää uudelleen: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Olet määrittämässä seuraaville komennoille useita näppäinyhdistelmiä: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Seuraaviin näppäinyhdistelmiin on useita liitoksia: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Seuraavat näppäinyhdistelmät ovat virheellisiä: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Olet määrittämässä näppäinyhdistelmiä olemattomille komennoille: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Virhe asetuksia luettaessa\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Asetustiedostossa on virheellistä JSON-koodia. Tiedosto avataan, niin voit korjata sen muodon. {APP_NAME} tulee käynnistää uudelleen, jotta muutokset tulevat voimaan.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Projektin asetustiedostossa on virheellistä JSON-koodia. Tiedosto avataan, niin voit korjata sen muodon. Projekti tulee ladata uudelleen, jotta muutokset tulevat voimaan.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Hups! {APP_NAME} ei toimi vielä selaimessa.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} on tehty HTML:llä, mutta juuri nyt se toimii työpöytäsovelluksena, joten voit muokata sillä paikallisia tiedostoja. Käytä ohjelmistolähteen <b>github.com/adobe/brackets-shell</b> sovellusliittymää, niin voit suorittaa {APP_NAME}in.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Virhe tiedostojen indeksoinnissa\",\n    \"ERROR_MAX_FILES\"                   : \"Tässä projektissa on yli 30&nbsp;000 tiedostoa. Useiden tiedostojen väliset ominaisuudet poistetaan käytöstä, tai ne toimivat niin kuin projekti olisi tyhjä. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Lue lisää suurten projektien parissa työskentelystä</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Virhe selaimen avaamisessa\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Google Chrome \\u2011selainta ei löytynyt. Varmista, että se on asennettu.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Selaimen avaaminen epäonnistui. (Virhe {0}.)\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Esikatselun virhe\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Yhdistetään selaimeen\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Jotta esikatselu voi muodostaa yhteyden, pitää Chromen käynnistyä uudelleen etävirheenjäljitys käytössä.<br /><br />Käynnistetäänkö Chrome uudelleen ja aktivoidaan etävirheenjäljitys?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Esikatselun sivua ei voitu ladata.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Avaa HTML-tiedosto tai varmista, että projektissa on tiedosto index.html, niin voit aloittaa esikatselun.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Jotta voit käynnistää esikatselun palvelimen tiedostolla, täytyy tämän projektin URL-osoite määrittää.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Virhe käynnistettäessä HTTP-palvelinta esikatselun tiedostoille. Yritä uudelleen.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Tervetuloa esikatseluun!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Esikatselu yhdistää {APP_NAME}in selaimeesi. Se avaa selaimessa HTML-tiedoston esikatselun, joka päivittyy välittömästi muokatessasi koodia.<br /><br />Tässä varhaisessa {APP_NAME}-versiossa esikatselu toimii vain <strong>Google Chromella</strong> ja päivittyy heti, kun muokkaat <strong>CSS- tai HTML-tiedostoja</strong>. JavaScript-tiedostojen muutokset päivittyvät, kun ne tallennetaan.<br /><br />(Tämä viesti näkyy vain kerran.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Saat lisätietoja tutustumalla ohjeeseen <a href='{0}' title='{0}'>Troubleshooting Live Preview connection errors</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Esikatselu\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Esikatselu: yhdistetään\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Esikatselu: alustetaan\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Lopeta esikatselu\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Esikatselu (päivitä tallentamalla tiedosto)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Esikatselu (ei päivity syntaksivirheen takia)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Esikatselu peruutettiin, koska selaimen kehitystyökalut avattiin\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Esikatselu peruutettiin, koska sivu suljettiin selaimessa\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Esikatselu peruutettiin, koska selain siirtyi sivulle, joka ei kuulu nykyiseen projektiin\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Esikatselu peruutettiin tuntemattomasta syystä ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Tallenna muutokset\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Haluatko tallentaa dokumenttiin <span class='dialog-filename'>{0}</span> tehdyt muutokset?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Haluatko tallentaa seuraavien tiedostojen muutokset?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Ulkoisia muutoksia\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Vahvista poisto\",\n    \"CONFIRM_FILE_DELETE\"               : \"Haluatko varmasti poistaa tiedoston <span class='dialog-filename'>{0}</span>?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Haluatko varmasti poistaa kansion <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Poistettu tiedosto\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> on muuttunut levyllä {APP_NAME}in ulkopuolella.<br /><br />Haluatko tallentaa tiedoston ja korvata kyseiset muutokset?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> on muuttunut levyllä {APP_NAME}in ulkopuolella, mutta sillä on tallentamattomia muutoksia myös {APP_NAME}issa.<br /><br />Kumman version haluat säilyttää?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> on poistettu levyltä {APP_NAME}in ulkopuolella, mutta sillä on tallentamattomia muutoksia {APP_NAME}issa.<br /><br />Haluatko säilyttää muutoksesi?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Valmis\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Peruuta\",\n    \"DONT_SAVE\"                         : \"Älä tallenna\",\n    \"SAVE\"                              : \"Tallenna\",\n    \"SAVE_AS\"                           : \"Tallenna nimellä\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Korvaa\",\n    \"DELETE\"                            : \"Poista\",\n    \"BUTTON_YES\"                        : \"Kyllä\",\n    \"BUTTON_NO\"                         : \"Ei\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} / {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Ei tuloksia\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Etsi\\u2026\",\n    \"FIND_HISTORY_MAX_COUNT\"            : \"Kohteiden enimmäismäärä hakuhistoriassa\",\n    \"REPLACE_PLACEHOLDER\"               : \"Korvaa merkkijonolla\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Korvaa kaikki\",\n    \"BUTTON_REPLACE_BATCH\"              : \"Korvaa erissä\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Korvaa\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Korvaa\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Seuraava vastine\",\n    \"BUTTON_PREV_HINT\"                  : \"Edellinen vastine\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Huomioi kirjainkoko\",\n    \"BUTTON_REGEXP_HINT\"                : \"Säännöllinen lauseke\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Korvaa kumoamatta\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Koska yli {0} tiedoston pitää muuttua, {APP_NAME} muokkaa avaamattomia tiedostoja levyllä.<br />Et voi perua korvauksia näissä tiedostoissa.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Korvaa kumoamatta\",\n\n    \"OPEN_FILE\"                         : \"Avaa tiedosto\",\n    \"SAVE_FILE_AS\"                      : \"Tallenna tiedosto\",\n    \"CHOOSE_FOLDER\"                     : \"Valitse kansio\",\n\n    \"RELEASE_NOTES\"                     : \"Julkaisutiedot\",\n    \"NO_UPDATE_TITLE\"                   : \"Olet ajan tasalla!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Käytät uusinta {APP_NAME}-versiota.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Korvaa\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"merkkijonolla\",\n    \"FIND_TITLE_LABEL\"                  : \"Löytyi\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"kohteesta <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"projektissa\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Suodatin ohittaa kaikki tiedostot {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"tiedostossa\",\n    \"FIND_IN_FILES_FILES\"               : \"tiedostossa\",\n    \"FIND_IN_FILES_MATCH\"               : \"vastine\",\n    \"FIND_IN_FILES_MATCHES\"             : \"vastinetta\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Yli \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&ndash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Laajenna tai pienennä kaikki painamalla Ctrl/Cmd\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indeksoidaan pikahakua varten\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Korvausvirheitä\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Seuraavia tiedostoja ei muokattu, koska ne olivat muuttuneet haun jälkeen tai niihin ei voitu kirjoittaa.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Virhe päivitystietojen haussa\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Uusimpien päivitystietojen haussa palvelimelta oli ongelmia. Varmista, että olet yhteydessä verkkoon, ja yritä uudelleen.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Uusi ohitusjoukko\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Älä ohita tiedostoja\",\n    \"NO_FILE_FILTER\"                    : \"Tiedostoja ei ohitettu\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Ohita {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Muokkaa\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Muokkaa ohitusjoukkoa\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Ohita tiedostoja ja kansioita, jotka sopivat mihin tahansa seuraavista merkkijonoista tai alimerkkijonoista. Voit käyttää myös <a href='{0}' title='{0}'>jokerimerkkiä</a>. Kirjoita kukin merkkijono uudelle riville.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nimeä tämä ohitusjoukko (valinnainen)\",\n    \"FILTER_NAME_REMAINING\"             : \"{0} merkkiä jäljellä\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"ja {0} lisää\",\n    \"FILTER_COUNTING_FILES\"             : \"Lasketaan tiedostoja\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Sallii {0} yhteensä {1} tiedostosta {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Sallii kaikki {0} tiedostoa {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Pikamuokkaus ei ole saatavilla kohdistimen nykyiselle sijainnille\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS-pikamuokkaus: sijoita kohdistin yksittäiseen luokan nimeen\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS-pikamuokkaus: puutteellinen class-määrite\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS-pikamuokkaus: puutteellinen id-määrite\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS-pikamuokkaus: sijoita kohdistin tägiin taikka class- tai id-attribuuttiin\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS:n aikafunktion pikamuokkaus: virheellinen syntaksi\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS-pikamuokkaus: sijoita kohdistin funktion nimeen\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Pikadokumentaatio ei ole saatavilla kohdistimen nykyiselle sijainnille\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Ladataan\\u2026\",\n    \"UNTITLED\"          : \"Nimetön\",\n    \"WORKING_FILES\"     : \"Työtiedostot\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"ylä\",\n    \"BOTTOM\"            : \"ala\",\n    \"LEFT\"              : \"vasempaan \",\n    \"RIGHT\"             : \"oikeaan \",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Ei jakoa\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Pystyjako\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Vaakajako\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Jaa editori pysty- tai vaakasuunnassa\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Määritä työlista\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Jo avoinna\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Tiedosto on jo auki toisessa ruudussa. {APP_NAME} tukee pian saman tiedoston avaamista useammassa ruudussa. Siihen asti tiedosto näytetään ruudussa, jossa se on jo auki.<br /><br />(Tämä viesti näkyy vain kerran.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Vaihto\",\n    \"KEYBOARD_SPACE\"        : \"Välilyönti\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Rivi {0}, sarake {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 valittu {0} sarake\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 valittu {0} saraketta\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 valittu {0} rivi\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 valittu {0} riviä\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} valintaa\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Muuta sisennys välilyönneiksi napsauttamalla\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Muuta sisennys sarkainmerkeiksi napsauttamalla\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Muuta sisennyksenä käytettävien välilyöntien määrää napsauttamalla\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Muuta sarkainmerkin leveyttä napsauttamalla\",\n    \"STATUSBAR_SPACES\"                      : \"Välilyöntejä:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Sarkaimen koko:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} rivi\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} riviä\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Laajennukset poistettu käytöstä\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Vaihda kohdistimen sijoitus (INS)- ja korvaus (OVR) \\u2011tilojen välillä napsauttamalla\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Vaihda tiedostotyyppiä napsauttamalla\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Näytä tai piilota raporttipaneeli napsauttamalla.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(oletus)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Aseta oletukseksi .{0}-tiedostoille\",\n    \"STATUSBAR_ENCODING_TOOLTIP\"            : \"Valitse enkoodaus\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} ongelmaa\",\n    \"SINGLE_ERROR\"                          : \"1 {0}-ongelma\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0}-ongelmaa\",\n    \"NO_ERRORS\"                             : \"{0}-ongelmia ei löytynyt \\u2013 hyvää työtä!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Ongelmia ei löytynyt \\u2013 hyvää työtä!\",\n    \"LINT_DISABLED\"                         : \"Tarkistus on pois käytöstä\",\n    \"NO_LINT_AVAILABLE\"                     : \"Tarkistinta ei saatavilla kohteelle {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Ei tarkistettavaa\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} on aikakatkaistu {1} ms:n odotuksen jälkeen\",\n    \"LINTER_FAILED\"                         : \"{0} keskeytyi virheeseen: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Tiedosto\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Uusi\",\n    \"CMD_FILE_NEW\"                        : \"Uusi tiedosto\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Uusi kansio\",\n    \"CMD_FILE_OPEN\"                       : \"Avaa\\u2026\",\n    \"CMD_RECENT_FILES_OPEN\"               : \"Avaa viimeaikainen\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Avaa työlistaan\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Avaa pudotetut tiedostot\",\n    \"CMD_OPEN_FOLDER\"                     : \"Avaa kansio\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Sulje\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Sulje kaikki\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Sulje lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Sulje muut\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Sulje muut yläpuolelta\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Sulje muut alapuolelta\",\n    \"CMD_FILE_SAVE\"                       : \"Tallenna\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Tallenna kaikki\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Tallenna nimellä\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Esikatselu\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Ota kokeellinen esikatselu käyttöön\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Pakota esikatselu päivittymään\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projektin asetukset\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Nimeä uudelleen\",\n    \"CMD_FILE_DELETE\"                     : \"Poista\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Asenna laajennus\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Laajennusten hallinta\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Päivitä tiedostopuu\",\n    \"CMD_QUIT\"                            : \"Lopeta\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Lopeta\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Muokkaa\",\n    \"CMD_UNDO\"                            : \"Kumoa\",\n    \"CMD_REDO\"                            : \"Tee uudelleen\",\n    \"CMD_CUT\"                             : \"Leikkaa\",\n    \"CMD_COPY\"                            : \"Kopioi\",\n    \"CMD_PASTE\"                           : \"Liitä\",\n    \"CMD_SELECT_ALL\"                      : \"Valitse kaikki\",\n    \"CMD_SELECT_LINE\"                     : \"Valitse rivi\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Jaa valinta riveille\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Lisää kohdistin seuraavalle riville\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Lisää kohdistin edelliselle riville\",\n    \"CMD_INDENT\"                          : \"Sisennä\",\n    \"CMD_UNINDENT\"                        : \"Poista sisennys\",\n    \"CMD_DUPLICATE\"                       : \"Monista\",\n    \"CMD_DELETE_LINES\"                    : \"Poista rivi\",\n    \"CMD_COMMENT\"                         : \"Muuta kommenttiriviksi\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Muuta kommenttilohkoksi\",\n    \"CMD_LINE_UP\"                         : \"Siirrä riviä ylös\",\n    \"CMD_LINE_DOWN\"                       : \"Siirrä riviä alas\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Avaa rivi yllä\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Avaa rivi alla\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Sulje sulkeet automaattisesti\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Näytä koodivihjeet\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Etsi\",\n    \"CMD_FIND\"                            : \"Etsi\",\n    \"CMD_FIND_NEXT\"                       : \"Etsi seuraava\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Etsi edellinen\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Etsi ja valitse kaikki\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Lisää seuraava vastine valintaan\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Ohita ja lisää seuraava vastine\",\n    \"CMD_FIND_IN_FILES\"                   : \"Etsi tiedostoista\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Etsi kohteesta\\u2026\",\n    \"CMD_REPLACE\"                         : \"Korvaa\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Korvaa tiedostoissa\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Korvaa kohteessa\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Näytä\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Piilota sivupalkki\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Näytä sivupalkki\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Näytä tai piilota sivupalkki\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Näytä tai piilota paneelit\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Ei häiriötekijöitä\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Suurenna fonttikokoa\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Pienennä fonttikokoa\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Palauta fonttikoko\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Vieritä rivi ylös\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Vieritä rivi alas\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Rivinumerot\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Korosta valittu rivi\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Automaattinen rivitys\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Esikatselun korostus\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Tarkista tiedostot tallennettaessa\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Järjestä lisäysajan mukaan\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Järjestä nimen mukaan\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Järjestä tyypin mukaan\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automaattinen järjestys\",\n    \"CMD_THEMES\"                          : \"Teemat\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Siirry\",\n    \"CMD_QUICK_OPEN\"                      : \"Pika-avaus\",\n    \"CMD_GOTO_LINE\"                       : \"Siirry riville\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Etsi määrittely nopeasti\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Siirry ensimmäiseen ongelmaan\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Pikamuokkaus\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Pikadokumentaatio\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Edellinen vastine\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Seuraava vastine\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Uusi sääntö\",\n    \"CMD_NEXT_DOC\"                        : \"Seuraava dokumentti\",\n    \"CMD_PREV_DOC\"                        : \"Edellinen dokumentti\",\n    \"CMD_NAVIGATE_BACKWARD\"               : \"Siirry taaksepäin\",\n    \"CMD_NAVIGATE_FORWARD\"                : \"Siirry eteenpäin\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Seuraava dokumentti listassa\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Edellinen dokumentti listassa\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Näytä tiedostopuussa\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Näytä Resurssienhallinnassa\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Näytä Finderissä\",\n    \"CMD_SHOW_IN_OS\"                      : \"Näytä käyttöjärjestelmässä\",\n    \"CMD_SWITCH_PANE_FOCUS\"               : \"Vaihda ruudun valinta\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Ohje\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Tarkista päivitykset\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Kuinka käyttää {APP_NAME}iä\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME}-tuki\",\n    \"CMD_SUGGEST\"                         : \"Ehdota ominaisuutta\",\n    \"CMD_RELEASE_NOTES\"                   : \"Julkaisutiedot\",\n    \"CMD_GET_INVOLVED\"                    : \"Lähde mukaan\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Näytä laajennuskansio\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Terveydentilaraportti\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE}in kotisivut\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} Twitterissä\",\n    \"CMD_ABOUT\"                           : \"Tietoja {APP_TITLE}istä\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Avaa asetustiedosto\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Avaa käyttäjän näppäinkartta\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"kokeellinen koontiversio\",\n    \"RELEASE_BUILD\"                        : \"koontiversio\",\n    \"DEVELOPMENT_BUILD\"                    : \"kehityskoontiversio\",\n    \"RELOAD_FROM_DISK\"                     : \"Lataa uudelleen levyltä\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Pidä muutokset editorissa\",\n    \"CLOSE_DONT_SAVE\"                      : \"Sulje (Älä tallenna)\",\n    \"RELAUNCH_CHROME\"                      : \"Käynnistä Chrome uudelleen\",\n    \"ABOUT\"                                : \"Tietoja\",\n    \"CLOSE\"                                : \"Sulje\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Julkaisu {VERSION_MAJOR}.{VERSION_MINOR}, {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"koontiversion aikaleima: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Kolmannen osapuolen ohjelmistoja koskevat ilmoitukset ja ehdot sijaitsevat osoitteessa <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a>, ja tässä ne esitetään viittauksena.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentaatio ja lähdekoodi osoitteessa <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"He tekivät tämän \\u2764:lla ja JavaScriptillä:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Monet ihmiset (mutta meillä on juuri nyt vaikeuksia ladata näitä tietoja).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN-dokumentit ja graafinen MDN-logo on lisensoitu Creative Commons Attribution \\u2011lisenssillä, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Uusi {APP_NAME}-versio on saatavilla! Saat lisätietoja napsauttamalla tästä.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Päivitys saatavilla\",\n    \"UPDATE_MESSAGE\"                       : \"Hei, uusi {APP_NAME}-versio on saatavilla. Tässä on joitakin uusista ominaisuuksista:\",\n    \"GET_IT_NOW\"                           : \"Hae nyt!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projektin asetukset kohteelle: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Esikatselun perus-URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Käytä paikall. palvelinta antamalla URL, kuten http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Esikatselu ei tue {0}-protokollaa. Käytä joko http: tai https: \\u2011muotoa.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL-osoite ei voi sisältää hakuparametreja, kuten ”{0}”.\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL-osoite ei voi sisältää ristikkomerkkejä, kuten ”{0}”.\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Erikoismerkit, kuten ”{0}”, täytyy %-koodata.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Tuntematon virhe URL-osoitteen jäsentämisessä\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Avaa tiedosto tämän ruudun ollessa valittuna</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Heitä tämä näkymä {0}paneeliin\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Nykyinen teema\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Käytä teeman vierityspalkkeja\",\n    \"FONT_SIZE\"                            : \"Fonttikoko\",\n    \"FONT_FAMILY\"                          : \"Fonttiperhe\",\n    \"THEMES_SETTINGS\"                      : \"Teema-asetukset\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Uusi sääntö\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Asenna\",\n    \"UPDATE\"                               : \"Päivitä\",\n    \"REMOVE\"                               : \"Poista\",\n    \"DISABLE\"                              : \"Poista käytöstä\",\n    \"ENABLE\"                               : \"Ota käyttöön\",\n    \"OVERWRITE\"                            : \"Korvaa\",\n    \"CANT_REMOVE_DEV\"                      : \"Kansion ”dev” laajennukset on poistettava käsin.\",\n    \"CANT_UPDATE\"                          : \"Laajennus ei ole yhteensopiva tämän {APP_NAME}-version kanssa.\",\n    \"CANT_UPDATE_DEV\"                      : \"Kansion ”dev” laajennuksia ei voi päivittää automaattisesti.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Asenna laajennus\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Päivitä laajennus\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Laajennuksen URL-osoite\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Laajennuksen zip-tiedoston URL-osoite tai GitHub-varasto\",\n    \"INSTALLING_FROM\"                      : \"Asennetaan laajennus kohteesta {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Asennus on valmis!\",\n    \"INSTALL_FAILED\"                       : \"Asennus epäonnistui.\",\n    \"CANCELING_INSTALL\"                    : \"Peruutetaan\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Asennuksen peruuttaminen kestää pitkään. On saattanut tapahtua sisäinen virhe.\",\n    \"INSTALL_CANCELED\"                     : \"Asennus on peruutettu.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Näytä täysi kuvaus\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Näytä katkaistu kuvaus\",\n    \"SORT_EXTENSION_METHOD\"                : \"Järjestele laajennukset latausmäärän tai päivitysajankohdan mukaan\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Ladattu sisältö ei ole kelvollinen zip-tiedosto.\",\n    \"MISSING_PACKAGE_JSON\"                 : \"Paketissa ei ole tiedostoa package.json.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Tiedosto package.json on virheellinen. (Virhe {0}.)\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Tiedostoon package.json ei ole merkitty paketin nimeä.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} on virheellinen paketin nimi.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Tiedostoon package.json ei ole merkitty paketin versiota.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Paketin versionumero ({0}) on virheellinen.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"{APP_NAME}in yhteensopivuuden merkkijono ({0}) on virheellinen.\",\n    \"DISALLOWED_WORDS\"                     : \"Sanat ({1}) eivät ole sallittuja kentässä {0}.\",\n    \"NPM_INSTALL_FAILED\"                   : \"npm install \\u2011komento epäonnistui: {0}\",\n    \"API_NOT_COMPATIBLE\"                   : \"Laajennus ei ole yhteensopiva tämän {APP_NAME}-version kanssa. Se asennettiin käytöstä poistettujen laajennusten kansioon.\",\n    \"MISSING_MAIN\"                         : \"Paketissa ei ole tiedostoa main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Tämän paketin asennus korvaa aiemmin asennetun laajennuksen. Korvataanko vanha laajennus?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Tämän paketin versio on sama kuin jo asennetun. Korvataanko nykyinen asennus?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Tämän paketin versio on {0}, joka on vanhempi kuin jo asennetun ({1}). Korvataanko nykyinen asennus?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Sisäinen virhe: lataustunnus on jo käytössä.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Palvelimeen ei voida yhdistää.\",\n    \"BAD_HTTP_STATUS\"                      : \"Tiedostoa ei löydy palvelimelta (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Latausta ei kyetty tallentamaan tilapäistiedostoon.\",\n    \"ERROR_LOADING\"                        : \"Laajennuksen käynnistyksessä tapahtui virhe.\",\n    \"MALFORMED_URL\"                        : \"URL-osoite on virheellinen. Tarkista, että kirjoitit sen oikein.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL-osoitteen on oltava http- tai https-muotoinen.\",\n    \"UNKNOWN_ERROR\"                        : \"Tuntematon sisäinen virhe.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Laajennusten hallinta\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Virhe käytettäessä laajennusten rekisteriä. Yritä myöhemmin uudelleen.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Vedä .zip-paketti tähän tai\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Asenna pudottamalla .zip-paketti\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Asennus tai päivitys keskeytyi seuraaviin virheisiin:\",\n    \"INSTALL_FROM_URL\"                     : \"asenna URL-osoitteesta\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Vahvistetaan\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Tekijä\",\n    \"EXTENSION_DATE\"                       : \"Päivämäärä\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Tämä laajennus vaatii uudemman {APP_NAME}-version.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Tämä laajennus toimii tällä hetkellä vain vanhemmilla {APP_NAME}-versioilla.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Tämän laajennuksen versio {0} vaatii uudemman {APP_NAME}-version, mutta voit asentaa aikaisemman version {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Tämän laajennuksen versio {0} toimii vain vanhemmilla {APP_NAME}-versioilla, mutta voit asentaa aikaisemman version {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Ei kuvausta\",\n    \"EXTENSION_MORE_INFO\"                  : \"Lisätietoja\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Laajennusvirhe\",\n    \"EXTENSION_KEYWORDS\"                   : \"Avainsanat\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Käännetty {0} kielelle, myös sinun\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Käännetty {0} kielelle\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Tämä laajennus on käännetty näille kielille: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Asennettu\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Tämä laajennuspäivitys on ladattu ja asennetaan {APP_NAME}in latauduttua uudelleen.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Hae\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Lisää\",\n    \"BROWSE_EXTENSIONS\"                    : \"Selaa laajennuksia\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Poista laajennus\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Ainakaan yhtä laajennusta ei voitu poistaa: {0}. {APP_NAME} latautuu silti uudelleen.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Päivitä laajennus\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Ainakaan yhtä laajennusta ei voitu päivittää: {0}. {APP_NAME} latautuu silti uudelleen.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Poista laajennus käytöstä\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Ainakaan yhtä laajennusta ei voitu poistaa käytöstä: {0}. {APP_NAME} latautuu silti uudelleen.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Merkitty poistettavaksi\",\n    \"UNDO_REMOVE\"                          : \"Kumoa\",\n    \"MARKED_FOR_UPDATE\"                    : \"Merkitty päivitettäväksi\",\n    \"UNDO_UPDATE\"                          : \"Kumoa\",\n    \"MARKED_FOR_DISABLING\"                 : \"Merkitty käytöstä poistettavaksi\",\n    \"UNDO_DISABLE\"                         : \"Kumoa\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Muuta laajennuksia\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Jotta voit päivittää, poistaa tai poistaa käytöstä merkityt laajennukset, pitää {APP_NAME}in latautua uudelleen. Sinua muistutetaan tallentamattomien muutosten tallentamisesta.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Poista laajennukset ja lataa uudelleen\",\n    \"CHANGE_AND_RELOAD\"                    : \"Muuta laajennuksia ja lataa uudelleen\",\n    \"UPDATE_AND_RELOAD\"                    : \"Päivitä laajennukset ja lataa uudelleen\",\n    \"DISABLE_AND_RELOAD\"                   : \"Poista laajennukset käytöstä ja lataa uudelleen\",\n    \"PROCESSING_EXTENSIONS\"                : \"Käsitellään laajennusten muutoksia\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Laajennusta {0} ei voida poistaa, koska sitä ei ole asennettu.\",\n    \"NO_EXTENSIONS\"                        : \"Laajennuksia ei ole vielä asennettu.<br>Aloita napsauttamalla Saatavilla-välilehteä yltä.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Ei hakuasi vastaavia laajennuksia.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"HUOMAA: Nämä laajennukset voivat olla peräisin eri lähteistä kuin {APP_NAME} itse. Laajennuksia ei ole tarkastettu, ja niillä on täydet paikalliset oikeudet. Ole varovainen asentaessasi laajennuksia tuntemattomasta lähteestä.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Asennettu\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Saatavilla\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Teemat\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Päivitykset\",\n    \"EXTENSIONS_LAST_UPDATED\"              : \"Päivitetty\",\n    \"EXTENSIONS_DOWNLOADS\"                 : \"Lataukset\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Vastineita ei saatavilla.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Kaikki vastineet on pienennetty. Laajenna oikealla listatut tiedostot, niin näet vastineet.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Valintaasi vastaavia CSS-sääntöjä ei ole.<br> Luo sellainen napsauttamalla ”Uusi sääntö”.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Projektissa ei ole tyylitiedostoja.<br>Lisää CSS-sääntöjä luomalla sellainen.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"suurin\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pikseliä\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Kehitys\",\n    \"ERRORS\"                                    : \"Virheet\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Näytä kehitystyökalut\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Lataa uudelleen laajennuksineen\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Lataa uudelleen laajennuksitta\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Uusi {APP_NAME}-ikkuna\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Asenna komentorivin oikotie\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Vaihda kieltä\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Suorita testejä\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Näytä suorituskykytiedot\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Ota Noden virheenjäljitin käyttöön\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Kirjaa Noden tila konsoliin\",\n    \"CMD_RESTART_NODE\"                          : \"Käynnistä Node uudelleen\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Näytä virheet tilapalkissa\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Avaa {APP_NAME}in lähdekoodi\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME}in komentorivin oikotie\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Tapahtui virhe asennettaessa komentorivin oikotietä. Kokeile <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>näitä vianmääritysohjeita</a>.<br/><br/>Syy: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Olemassa olevaa symbolista linkkiä <code>/usr/local/bin/brackets</code> ei voitu poistaa.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Hakemistoa <code>/usr/local/bin</code> ei voitu luoda.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Symbolista linkkiä <code>/usr/local/bin/brackets</code> ei voitu luoda.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Sisäinen virhe.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Komentorivin oikotie ei ole tuettu tässä käyttöjärjestelmässä.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Onnistui! Voit nyt avata {APP_NAME}in helposti komentoriviltä: avaa tiedosto komennolla <code>brackets tiedosto.txt</code> tai vaihda projektia komennolla <code>brackets kansio</code>. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Lue lisää</a> {APP_NAME}in käyttämisestä komentoriviltä.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Vaihda kieltä\",\n    \"LANGUAGE_MESSAGE\"                          : \"Kieli:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Päivitä {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Peruuta\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Järjestelmän oletus\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Terveydentilaraportin asetukset\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME}in terveydentilaraportti\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Jaa nimettömiä tietoja {APP_NAME}in käytöstäni\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Jotta voit parantaa {APP_NAME}ia, lähetämme säännöllisesti Adobelle rajattuja, <strong>nimettömiä</strong> tilastotietoja siitä, kuinka käytät tuotetta. Nämä tiedot auttavat priorisoimaan ominaisuuksia, löytämään bugeja ja huomaamaan käytettävyysongelmia.<br><br>Voit nähdä tietosi tai valita, ettei tietoja jaeta, valitsemalla <strong>Ohje > Terveydentilaraportti</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Lue lisää {APP_NAME}in terveydentilaraportista</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME}in terveydentilaraportti\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Jotta voimme parantaa {APP_NAME}ia, lähetämme säännöllisesti Adobelle rajattuja, <strong>nimettömiä</strong> tilastotietoja siitä, kuinka käytät tuotetta. Nämä tiedot auttavat priorisoimaan ominaisuuksia, löytämään bugeja ja huomaamaan käytettävyysongelmia. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Lue lisää {APP_NAME}in terveydentilaraportista</a> ja siitä, kuinka se hyödyttää {APP_NAME}-yhteisöä samalla, kun suojelemme yksityisyyttäsi.</p><p>Alla on esikatselu tiedoista, jotka lähetetään seuraavassa terveydentilaraportissasi <em>jos</em> se on otettu käyttöön.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Aika\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Edistyminen\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Siirrä valittua pistettä<br><kbd class='text'>Vaihto</kbd> Siirrä kymmenen yksikköä<br><kbd class='text'>Tab</kbd> Vaihda pisteitä\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Lisää tai vähennä askelmia<br><kbd>←</kbd><kbd>→</kbd> ”Start” tai ”end”\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Vanha arvo <code>{0}</code> on virheellinen, joten näytetty funktio muutettiin muotoon <code>{1}</code>. Dokumentti päivitetään ensimmäisellä muokkauksella.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Nykyinen väri\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Alkuperäinen väri\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa-muoto\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex-muoto\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa-muoto\",\n    \"COLOR_EDITOR_0X_BUTTON_TIP\"                : \"Hex (0x) \\u2011muoto\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (käytetty {1} kerran)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (käytetty {1} kertaa)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Siirry määrittelyyn\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Näytä parametrivihje\",\n    \"NO_ARGUMENTS\"                              : \"<ei parametreja>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"JavaScript-tiedoston päättelyongelma\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} kohtasi vaikeuksia tiedoston <span class='dialog-filename'>{0}</span> käsittelyssä.<br><br>Tätä tiedostoa ei enää käsitellä koodivihjeitä, määrittelyyn siirtymistä tai pikamuokkausta varten. Avaa projektin tiedosto <code>.brackets.json</code> ja muokkaa kohtaa <code>jscodehints.detectedExclusions</code>, niin saat tiedoston takaisin käyttöön.<br><br>Tämä on todennäköisesti {APP_NAME}in bugi. Jos voit luovuttaa kopion tästä tiedostosta, <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>ilmoita virheestä</a> ja laita mukaan linkki kyseiseen tiedostoon, kiitos!\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Pikanäkymä osoitettaessa\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Viimeaikaiset projektit\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Lue lisää\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Pienennä kaikki\",\n    \"EXPAND_ALL\"                    : \"Laajenna kaikki\",\n    \"COLLAPSE_CURRENT\"              : \"Pienennä nykyinen\",\n    \"EXPAND_CURRENT\"                : \"Laajenna nykyinen\",\n\n    // extensions/default/NavigationAndHistory\n    \"RECENT_FILES_DLG_HEADER\"                    : \"Viimeaikaiset tiedostot\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\"        : \"Tyhjennä\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\"        : \"Tyhjennä työlistassa olemattomat tiedostot\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true: sulje aalto-, haka- ja kaarisulkeet automaattisesti\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false: poista Sulje muut yläpuolelta -valinta työtiedostojen kontekstivalikosta\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false: poista Sulje muut alapuolelta -valinta työtiedostojen kontekstivalikosta\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false: poista Sulje muut -valinta työtiedostojen kontekstivalikosta\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Asettaa tägien sulkemisvalinnat\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Taulukko tägeistä, joita ei pidä sulkea automaattisesti\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Sulje, kun avaustägin > kirjoitetaan\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Sulje, kun sulkutägin / kirjoitetaan\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Taulukko tägeistä, jotka avattaessa sisältävät tyhjän rivin\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true: luo aina pienennettävän osion merkit, kun sisennyksen taso muuttuu\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true: ota koodin laskostus käyttöön\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true: näytä osion pienennyksen merkit vain, kun osoitin siirretään vasemman marginaalin päälle\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Rajoittaa sitä, kuinka monta tasoa syvälle Pienennä kaikki -valinta vaikuttaa\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Rivejä vähintään ennen kuin pienennettävän osion kuvake tulee esiin\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true: muista pienennetyt osiot, jos tiedosto tai projekti suljetaan ja avataan sitten uudelleen\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"true: ota valitun tekstin koodin laskostus käyttöön editorissa\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Näytä tai piilota HTML-attribuuttien vihjeet\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Näytä tai piilota CSS/LESS/SCSS-ominaisuuksien vihjeet\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Näytä tai piilota JavaScript-koodin vihjeet\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Näytä tai piilota datatyyppien yksityiskohdat JavaScript-koodin vihjeissä\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Näytä tai piilota asetusten koodin vihjeet\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Näytä tai piilota HTML-entiteettien vihjeet\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Näytä tai piilota SVG-koodin vihjeet\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Näytä tai piilota HTML-tägien vihjeet\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Näytä tai piilota URL-vihjeet HTML- ja CSS/LESS/SCSS-tiedostoissa\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Ota vedä ja pudota -toiminto käyttöön tai poista se käytöstä\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Ota terveydentilan seuranta käyttöön\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Ottaa käyttöön vastaavien merkkijonojen automaattisen korostuksen koko dokumentissa\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Korosta kaikki merkkijonot, jotka vastaavat ilmausta, jossa kohdistin parhaillaan on (valintaa ei tarvita)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Korosta vain, kun valinta on kokonainen ilmaus\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true: lisää parhaillaan valittu koodivihje, kun painetaan sarkainnäppäintä\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true: älä näytä JS-koodivihjeitä automaattisesti, kun . kirjoitetaan\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Objekti, joka sisältää JSLintin oletusasetukset\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true: salli sijoituslausekkeet\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true: salli bittioperaattorit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true, jos tavalliset selaimen globaalit pitää määritellä ennalta\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true: salli Google Closure -idiomit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true: salli continue-komento\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true, jos CouchDB:n globaalit pitää määritellä ennalta\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true: salli debugger-komennot\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true, jos kehityksessä hyödylliset selaimen globaalit pitää määritellä ennalta\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true: salli == ja !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true, jos ES6:n globaalit pitää määritellä ennalta\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true: salli eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true: salli suodattamaton ”for ... in”\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Aseta tietty sarkainmerkin leveys\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Raportoitavien varoitusten enimmäismäärä\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Merkkien enimmäismäärä rivillä\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true: salli pienaakkosin alkavat konstruktorit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true, jos Node.js:n globaalit pitää määritellä ennalta\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true: salli tunnisteiden alkaa alaviivalla\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true: pysähdy ensimmäiseen virheeseen\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true: salli ++ ja --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true: salli . ja [^...]. säännöllisissä lausekkeissa\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true, jos Rhinon globaalit pitää määritellä ennalta\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true: salli puuttuva `use strict` -toimintaohje\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true, jos blokkaavia (”...Sync”) metodeja voi käyttää\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true: salli tehoton hakasuljemerkintä\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true: salli TODO-kommentit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true: salli käyttämättömät parametrit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true: salli funktiossa useampi var-muuttuja\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true: jätä tyhjän tilan säännöt huomiotta\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Kielikohtaiset asetukset\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Ylimääräiset liitokset tiedostopäätteestä kielen nimeen\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Ylimääräiset liitokset tiedostonimestä kielen nimeen\",\n    \"DESCRIPTION_LINEWISE_COPY_CUT\"                  : \"Kopiointi ja leikkaaminen ilman valintaa kopioi tai leikkaa kokonaan rivit, joilla on kohdistin\",\n    \"DESCRIPTION_INPUT_STYLE\"                        : \"Valitsee, miten CodeMirror käsittelee syötteen ja kohdistuksen. Se voi olla textarea, joka on oletus, tai contenteditable, joka on parempi näytönlukijoille (mutta epävakaa)\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true: ota koodin tarkistus käyttööön\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Aika, jonka jälkeen asynkroniset tarkistimet aikakatkaistaan, millisekunteina\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Taulukko tarkistimista, jotka suoritetaan ensin\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true: ota kokeellinen esikatselu käyttöön\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true: suorita vain kohdassa linting.prefer eritellyt tarkistimet\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Kerralla näytettävien koodivihjeiden enimmäismäärä\",\n    \"DESCRIPTION_PATH\"                               : \"Polkukohtaiset asetukset\",\n    \"DESCRIPTION_PROXY\"                              : \"URL välityspalvelimelle, jota käytetään laajennusten asentamiseen\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true: ota käyttöön vierittäminen pidemmälle kuin dokumentin loppuun\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false: poista kaikki koodivihjeet käytöstä\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Pitää vilkkuvan kohdistimen esillä, kun tekstiä on valittu\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true: näytä rivinumerot vasemman reunan marginaalissa\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Sisennä automaattisesti, kun luodaan uusi lohko\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false: poista pehmeät sarkaimet -toiminto käytöstä\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true: järjestä hakemistot ensin projektipuussa\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Väleihin perustuvassa sisennyksessä käytettävien välilyöntien määrä\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Portin numero, jota sisäänrakennetun palvelimen pitäisi käyttää esikatselussa\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true: korosta taustavärillä rivi, jossa kohdistin on\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Näytettävien välilyöntien määrä sarkainmerkeissä\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true: käytä sarkainmerkkejä välilyöntien sijaan\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true: luo suuraakkosin kirjoitettuja hex-värejä sisäisessä värieditorissa\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Katkaise rivit, jotka ylittävät näyttöalueen leveyden\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Luettelo tiedostoista, joiden on havaittu aiheuttavan sen, että Tern ajautuu pois hallinnasta\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Aika, jonka jälkeen Tern aikakatkaistaan, sen yrittäessä ymmärtää tiedostoja\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true: näytä virheet tilapalkissa\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true: ota pikanäkymä käyttöön\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true: näytä kuvien esikatselut päätteettömille URL-osoitteille\",\n    \"DESCRIPTION_THEME\"                              : \"Valitse {APP_NAME}in teema\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true: salli mukautetut vierityspalkit\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true: pienennä tarkistuksen paneeli\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Vaihda fonttiperhettä\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Vaihda fonttikokoa, esim. 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"true: ota Node-pohjainen haku käyttöön\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"true: ota pikahaku käyttöön\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Vain Mac: ota käyttöön alipikselien reunapehmennys valinnalla ”subpixel-antialiased” tai harmaansävyinen reunapehmennys valinnalla ”antialiased”\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false: poista asetustiedoston avaaminen käytöstä jaetussa näkymässä\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false: avaa käyttäjän asetustiedosto vasemmassa tai ylemmässä ruudussa\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"true: yhdistä ruudut sen jälkeen, kun ruudun viimeinen tiedosto on suljettu ruudun yläosassa olevalla sulkupaikkeella\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Valitse, milloin sulku- ja flip view -painikkeet näkyvät ruudun yläosassa\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Tämä on vain luku -tiedosto {APP_NAME}in tukemista\\n * asetuksista.\\n * Käytä tätä apuna, kun muutat asetustiedostoasi\\n * ”brackets.json”, joka on avattu toiseen ruutuun.\\n * Lisätietoa siitä, kuinka käyttää asetuksia {APP_NAME}issa,\\n * löydät verkkosivulta osoitteessa https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Oletus\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"true: ota vain koodi -näkymä käyttöön ja piilota muut {APP_NAME}in käyttöliittymäelementit\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"true: ota rivikommenttien sisennys käyttöön\",\n    \"DESCRIPTION_RECENT_FILES_NAV\"                   : \"Ota viimeaikaisiin tiedostoihin siirtyminen käyttöön tai poista se käytöstä\",\n    \"DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\"             : \"WebSocket-palvelimen käyttämä portti esikatselua varten\",\n    \"DESCRIPTION_LIVE_DEV_HIGHLIGHT_SETTINGS\"        : \"Esikatselun korostuksen asetukset\"\n});\n\n/* Last translated for 6ac21ffbe51dde2256fe6c44be007f3cd1390e7a */"
  },
  {
    "path": "src/nls/fi/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"fi/Aloitus\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_fi/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.fi\"\n});\n"
  },
  {
    "path": "src/nls/fr/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n\t\"GENERIC_ERROR\": \"(Erreur {0})\",\n\t\"NOT_FOUND_ERR\": \"Fichier/répertoire introuvable.\",\n\t\"NOT_READABLE_ERR\": \"Impossible de lire le fichier/répertoire.\",\n\t\"EXCEEDS_MAX_FILE_SIZE\": \"Les fichiers dont la taille excède {0} Mo ne peuvent pas être ouverts dans {APP_NAME}.\",\n\t\"NO_MODIFICATION_ALLOWED_ERR\": \"Le répertoire cible ne peut pas être modifié.\",\n\t\"NO_MODIFICATION_ALLOWED_ERR_FILE\": \"Vous n’êtes pas autorisé à effectuer des modifications.\",\n\t\"CONTENTS_MODIFIED_ERR\": \"Le fichier a été modifié dans une application autre que {APP_NAME}.\",\n\t\"UNSUPPORTED_ENCODING_ERR\": \"Format de codage inconnu\",\n\t\"ENCODE_FILE_FAILED_ERR\": \"{APP_NAME} n’a pas pu coder le contenu du fichier.\",\n\t\"DECODE_FILE_FAILED_ERR\": \"{APP_NAME} n’a pas pu décoder le contenu du fichier.\",\n\t\"UNSUPPORTED_UTF16_ENCODING_ERR\": \"Actuellement, {APP_NAME} ne prend pas en charge les fichiers texte codés UTF-16.\",\n\t\"FILE_EXISTS_ERR\": \"Le fichier ou le répertoire existe déjà.\",\n\t\"FILE\": \"fichier\",\n\t\"FILE_TITLE\": \"Fichier\",\n\t\"DIRECTORY\": \"répertoire\",\n\t\"DIRECTORY_TITLE\": \"Répertoire\",\n\t\"DIRECTORY_NAMES_LEDE\": \"noms de répertoires\",\n\t\"FILENAMES_LEDE\": \"noms de fichiers\",\n\t\"FILENAME\": \"Nom de fichier\",\n\t\"DIRECTORY_NAME\": \"Nom du répertoire\",\n\n    // Project error strings\n\t\"ERROR_LOADING_PROJECT\": \"Erreur lors du chargement du projet\",\n\t\"OPEN_DIALOG_ERROR\": \"Une erreur s’est produite lors de l’affichage de la boîte de dialogue Ouvrir. (Erreur {0})\",\n\t\"REQUEST_NATIVE_FILE_SYSTEM_ERROR\": \"Une erreur s’est produite lors de la tentative de chargement du répertoire <span class='dialog-filename'>{0}</span>. (Erreur {1})\",\n\t\"READ_DIRECTORY_ENTRIES_ERROR\": \"Une erreur s’est produite lors de la lecture du contenu du répertoire <span class='dialog-filename'>{0}</span>. (Erreur {1})\",\n\n    // File open/save error string\n\t\"ERROR_OPENING_FILE_TITLE\": \"Erreur lors de l’ouverture du fichier\",\n\t\"ERROR_OPENING_FILE\": \"Une erreur s’est produite lors de la tentative d’ouverture du fichier <span class='dialog-filename'>{0}</span>. {1}\",\n\t\"ERROR_OPENING_FILES\": \"Une erreur s’est produite en tentant d’ouvrir les fichiers suivants :\",\n\t\"ERROR_RELOADING_FILE_TITLE\": \"Erreur lors du rechargement des modifications à partir du disque\",\n\t\"ERROR_RELOADING_FILE\": \"Une erreur s’est produite lors de la tentative de rechargement du fichier <span class='dialog-filename'>{0}</span>. {1}\",\n\t\"ERROR_SAVING_FILE_TITLE\": \"Erreur lors de l’enregistrement du fichier\",\n\t\"ERROR_SAVING_FILE\": \"Une erreur s’est produite lors de la tentative d’enregistrement du fichier <span class='dialog-filename'>{0}</span>. {1}\",\n\t\"ERROR_RENAMING_FILE_TITLE\": \"Erreur lors du changement de nom du {0}\",\n\t\"ERROR_RENAMING_FILE\": \"Une erreur s’est produite lors de la tentative de changement de nom du {2} <span class='dialog-filename'>{0}</span>. {1}\",\n\t\"ERROR_RENAMING_NOT_IN_PROJECT\": \"Le fichier ou le répertoire ne fait pas partie du projet actuellement ouvert. Or, seuls les fichiers appartenant au projet peuvent être renommés à ce stade.\",\n\t\"ERROR_MOVING_FILE_TITLE\": \"Erreur lors du déplacement de l’élément {0}\",\n\t\"ERROR_MOVING_FILE\": \"Une erreur s’est produite lors du déplacement de l’élément {2} <span class='dialog-filename'>{0}</span>. {1}\",\n\t\"ERROR_MOVING_NOT_IN_PROJECT\": \"Impossible de déplacer le fichier/dossier, car ils ne font pas partie du projet en cours.\",\n\t\"ERROR_DELETING_FILE_TITLE\": \"Erreur lors de la suppression du {0}\",\n\t\"ERROR_DELETING_FILE\": \"Une erreur s’est produite lors de la tentative de suppression du {2} <span class='dialog-filename'>{0}</span>. {1}\",\n\t\"INVALID_FILENAME_TITLE\": \"{0} non valide\",\n\t\"INVALID_FILENAME_MESSAGE\": \"Les {0} ne peuvent pas utiliser de termes réservés au système, finir par un point (.) ou contenir l’un des caractères suivants : <code class='emphasized'>{1}</code>\",\n\t\"ENTRY_WITH_SAME_NAME_EXISTS\": \"Il existe déjà un fichier ou un répertoire portant le nom <span class='dialog-filename'>{0}</span>.\",\n\t\"ERROR_CREATING_FILE_TITLE\": \"Erreur lors de la création de l’élément {0}\",\n\t\"ERROR_CREATING_FILE\": \"Une erreur s’est produite lors de la tentative de création du {0} <span class='dialog-filename'>{1}</span>. {2}\",\n\t\"ERROR_MIXED_DRAGDROP\": \"Impossible d’ouvrir un dossier en même temps que d’autres fichiers.\",\n\n    // User key map error strings\n\t\"ERROR_KEYMAP_TITLE\": \"Erreur lors de la lecture du mappage de touches utilisateur\",\n\t\"ERROR_KEYMAP_CORRUPT\": \"Votre fichier de mappage de touches n’est pas un fichier JSON valide. Il va s’ouvrir afin que vous puissiez corriger le format.\",\n\t\"ERROR_LOADING_KEYMAP\": \"Votre fichier de mappage de touches n’étant pas un fichier texte codé en UTF-8 valide, il ne peut pas être chargé.\",\n\t\"ERROR_RESTRICTED_COMMANDS\": \"Vous ne pouvez pas réaffecter de raccourcis à ces commandes : {0}\",\n\t\"ERROR_RESTRICTED_SHORTCUTS\": \"Vous ne pouvez pas réaffecter ces raccourcis : {0}\",\n\t\"ERROR_MULTIPLE_SHORTCUTS\": \"Vous réaffectez plusieurs raccourcis à ces commandes : {0}\",\n\t\"ERROR_DUPLICATE_SHORTCUTS\": \"Plusieurs liaisons ont été définies pour les raccourcis suivants : {0}\",\n\t\"ERROR_INVALID_SHORTCUTS\": \"Ces raccourcis ne sont pas valides : {0}\",\n\t\"ERROR_NONEXISTENT_COMMANDS\": \"Vous affectez des raccourcis à des commandes qui n'existent pas : {0}\",\n\n    // Application preferences corrupt error strings\n\t\"ERROR_PREFS_CORRUPT_TITLE\": \"Erreur lors de la lecture des préférences\",\n\t\"ERROR_PREFS_CORRUPT\": \"Votre fichier de préférences n’est pas un fichier JSON valide, il va donc être ouvert afin que vous puissiez corriger le format. Vous devrez ensuite redémarrer {APP_NAME} pour que les modifications prennent effet.\",\n\t\"ERROR_PROJ_PREFS_CORRUPT\": \"Votre fichier de préférences de projet n’est pas un fichier JSON valide, il va donc être ouvert afin que vous puissiez corriger le format. Vous devrez ensuite recharger le projet pour que les modifications prennent effet.\",\n\n    // Application error strings\n\t\"ERROR_IN_BROWSER_TITLE\": \"Malheureusement, {APP_NAME} n’est pas encore compatible avec les navigateurs.\",\n\t\"ERROR_IN_BROWSER\": \"{APP_NAME} est défini en HTML, mais il s’exécute actuellement en tant qu’application de bureau, vous pouvez donc l’utiliser afin de modifier des fichiers locaux. Utilisez l’interpréteur de commandes d’application situé dans le référentiel <b>github.com/adobe/brackets-shell</b> afin d’exécuter {APP_NAME}.\",\n\n    // ProjectManager max files error string\n\t\"ERROR_MAX_FILES_TITLE\": \"Erreur lors de l’indexation des fichiers\",\n\t\"ERROR_MAX_FILES\": \"Ce projet contient plus de 30 000 fichiers. Les fonctionnalités qui s’appliquent de manière globale à plusieurs fichiers peuvent être désactivées ou se comporter comme si le projet était vide. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>En savoir plus sur l’utilisation de projets volumineux</a>.\",\n\n    // Live Preview error strings\n\t\"ERROR_LAUNCHING_BROWSER_TITLE\": \"Erreur lors du lancement du navigateur\",\n\t\"ERROR_CANT_FIND_CHROME\": \"Le navigateur Google Chrome est introuvable. Assurez-vous qu’il est installé.\",\n\t\"ERROR_LAUNCHING_BROWSER\": \"Une erreur s’est produite lors du lancement du navigateur. (Erreur {0})\",\n\n\t\"LIVE_DEVELOPMENT_ERROR_TITLE\": \"Erreur du module Aperçu en direct\",\n\t\"LIVE_DEVELOPMENT_RELAUNCH_TITLE\": \"Connexion au navigateur\",\n\t\"LIVE_DEVELOPMENT_ERROR_MESSAGE\": \"Pour que le module Aperçu en direct puisse se connecter, vous devez relancer Chrome en activant la fonction de débogage à distance.<br /><br />Voulez-vous relancer Chrome et activer le débogage à distance ?<br /><br />\",\n\t\"LIVE_DEV_LOADING_ERROR_MESSAGE\": \"Impossible de charger la page Aperçu en direct.\",\n\t\"LIVE_DEV_NEED_HTML_MESSAGE\": \"Ouvrez un fichier HTML ou vérifiez qu’il y a un fichier index.html dans votre projet pour pouvoir lancer l’aperçu en direct.\",\n\t\"LIVE_DEV_NEED_BASEURL_MESSAGE\": \"Pour lancer l’Aperçu en direct avec un fichier de serveur, vous devez indiquer une URL de base pour ce projet.\",\n\t\"LIVE_DEV_SERVER_NOT_READY_MESSAGE\": \"Une erreur s’est produite au démarrage du serveur HTTP pour les fichiers d’aperçu en direct. Veuillez réessayer.\",\n\t\"LIVE_DEVELOPMENT_INFO_TITLE\": \"Bienvenue dans le module Aperçu en direct !\",\n\t\"LIVE_DEVELOPMENT_INFO_MESSAGE\": \"Le module Aperçu en direct connecte {APP_NAME} à votre navigateur. Il ouvre un aperçu de votre fichier HTML dans le navigateur, puis le met à jour instantanément dès que vous modifiez le code.<br /><br />Dans cette première version du logiciel {APP_NAME}, le module Aperçu en direct ne fonctionne qu’avec <strong>Google Chrome</strong> et affiche les mises à jour en direct, dès que vous modifiez des <strong>fichiers CSS ou HTML</strong>. Les modifications apportées aux fichiers JavaScript sont automatiquement rechargées lorsque vous enregistrez.<br /><br />(Ce message ne s’affichera qu’une seule fois.)\",\n\t\"LIVE_DEVELOPMENT_TROUBLESHOOTING\": \"Pour plus d’informations, consultez la page <a href='{0}' title='{0}'>Résolution des erreurs de connexion à l’Aperçu en direct</a>.\",\n\n\t\"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\": \"Aperçu en direct\",\n\t\"LIVE_DEV_STATUS_TIP_PROGRESS1\": \"Aperçu en direct : Connexion\\u2026\",\n\t\"LIVE_DEV_STATUS_TIP_PROGRESS2\": \"Aperçu en direct : Initialisation\\u2026\",\n\t\"LIVE_DEV_STATUS_TIP_CONNECTED\": \"Déconnecter le module Aperçu en direct\",\n\t\"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\": \"Aperçu en direct (enregistrez le fichier pour actualiser)\",\n\t\"LIVE_DEV_STATUS_TIP_SYNC_ERROR\": \"Aperçu en direct (échec de la mise à jour en raison d’une erreur de syntaxe)\",\n\n\t\"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\": \"Aperçu en direct annulé car les outils de développement du navigateur étaient ouverts\",\n\t\"LIVE_DEV_DETACHED_TARGET_CLOSED\": \"Aperçu en direct annulé car la page a été fermée dans le navigateur\",\n\t\"LIVE_DEV_NAVIGATED_AWAY\": \"Aperçu en direct annulé car le navigateur a accédé à une page qui ne fait pas partie du projet actuel\",\n\t\"LIVE_DEV_CLOSED_UNKNOWN_REASON\": \"Aperçu en direct annulé pour une raison inconnue ({0})\",\n\n\t\"SAVE_CLOSE_TITLE\": \"Enregistrer les modifications\",\n\t\"SAVE_CLOSE_MESSAGE\": \"Souhaitez-vous enregistrer les modifications apportées au document <span class='dialog-filename'>{0}</span> ?\",\n\t\"SAVE_CLOSE_MULTI_MESSAGE\": \"Souhaitez-vous enregistrer les modifications apportées aux fichiers suivants ?\",\n\t\"EXT_MODIFIED_TITLE\": \"Modifications externes\",\n\t\"CONFIRM_DELETE_TITLE\": \"Confirmer la suppression\",\n\t\"CONFIRM_FILE_DELETE\": \"Souhaitez-vous vraiment supprimer le fichier <span class='dialog-filename'>{0}</span> ?\",\n\t\"CONFIRM_FOLDER_DELETE\": \"Voulez-vous vraiment supprimer le dossier <span class='dialog-filename'>{0}</span> ?\",\n\t\"FILE_DELETED_TITLE\": \"Fichier supprimé\",\n\t\"EXT_MODIFIED_WARNING\": \"<span class='dialog-filename'>{0}</span> a été modifié sur le disque, dans une application autre que {APP_NAME}.<br /><br />Voulez-vous enregistrer le fichier et remplacer ces modifications ?\",\n\t\"EXT_MODIFIED_MESSAGE\": \"Le fichier <span class='dialog-filename'>{0}</span> a été modifié sur le disque dans une autre application que {APP_NAME} mais présente également des modifications non enregistrées dans {APP_NAME}.<br /><br />Quelle version souhaitez-vous conserver ?\",\n\t\"EXT_DELETED_MESSAGE\": \"Le fichier <span class='dialog-filename'>{0}</span> a été supprimé du disque dans une autre application que {APP_NAME} mais présente également des modifications non enregistrées dans {APP_NAME}.<br /><br />Souhaitez-vous conserver vos modifications ?\",\n    \n    // Window unload warning messages\n\t\"WINDOW_UNLOAD_WARNING\": \"Are you sure you want to navigate to a different URL and leave Brackets?\",\n\t\"WINDOW_UNLOAD_WARNING_WITH_UNSAVED_CHANGES\": \"You have unsaved changes! Are you sure you want to navigate to a different URL and leave Brackets?\",\n\n    // Generic dialog/button labels\n\t\"DONE\": \"Terminé\",\n\t\"OK\": \"OK\",\n\t\"CANCEL\": \"Annuler\",\n\t\"DONT_SAVE\": \"Ne pas enregistrer\",\n\t\"SAVE\": \"Enregistrer\",\n\t\"SAVE_AS\": \"Enregistrer sous\\u2026\",\n\t\"SAVE_AND_OVERWRITE\": \"Remplacer\",\n\t\"DELETE\": \"Supprimer\",\n\t\"BUTTON_YES\": \"Oui\",\n\t\"BUTTON_NO\": \"Non\",\n\n    // Find, Replace, Find in Files\n\t\"FIND_MATCH_INDEX\": \"{0} sur {1}\",\n\t\"FIND_NO_RESULTS\": \"Aucun résultat\",\n\t\"FIND_QUERY_PLACEHOLDER\": \"Rechercher\\u2026\",\n\t\"FIND_HISTORY_MAX_COUNT\": \"Nombre maximal d'éléments de recherche dans l'historique des recherches\",\n\t\"REPLACE_PLACEHOLDER\": \"Remplacer par\\u2026\",\n\t\"BUTTON_REPLACE_ALL\": \"Tout remplacer\",\n\t\"BUTTON_REPLACE_BATCH\": \"Traiter par lots\\u2026\",\n\t\"BUTTON_REPLACE_ALL_IN_FILES\": \"Remplacer\\u2026\",\n\t\"BUTTON_REPLACE\": \"Remplacer\",\n\t\"BUTTON_NEXT\": \"\\u25B6\",\n\t\"BUTTON_PREV\": \"\\u25C0\",\n\t\"BUTTON_NEXT_HINT\": \"Résultat suivant\",\n\t\"BUTTON_PREV_HINT\": \"Résultat précédent\",\n\t\"BUTTON_CASESENSITIVE_HINT\": \"Respecter la casse\",\n\t\"BUTTON_REGEXP_HINT\": \"Expression régulière\",\n\t\"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Remplacer sans possibilité d’annuler\",\n\t\"REPLACE_WITHOUT_UNDO_WARNING\": \"Dans la mesure où le nombre de fichiers à modifier excède {0}, {APP_NAME} va modifier des fichiers non ouverts sur le disque.<br />Vous ne pourrez pas annuler les remplacements effectués dans ces fichiers.\",\n\t\"BUTTON_REPLACE_WITHOUT_UNDO\": \"Remplacer sans possibilité d’annuler\",\n\n\t\"OPEN_FILE\": \"Ouvrir le fichier\",\n\t\"SAVE_FILE_AS\": \"Enregistrer le fichier\",\n\t\"CHOOSE_FOLDER\": \"Choisir un dossier\",\n\n\t\"RELEASE_NOTES\": \"Notes de mise à jour\",\n\t\"NO_UPDATE_TITLE\": \"Vos logiciels sont à jour !\",\n\t\"NO_UPDATE_MESSAGE\": \"Vous utilisez la dernière version de {APP_NAME}.\",\n\n    // Find and Replace\n\t\"FIND_REPLACE_TITLE_LABEL\": \"Remplacer\",\n\t\"FIND_REPLACE_TITLE_WITH\": \"par\",\n\t\"FIND_TITLE_LABEL\": \"Occurrences trouvées pour\",\n\t\"FIND_TITLE_SUMMARY\": \"&mdash; {0} {1} {2} dans {3}\",\n\n    // Find in Files\n\t\"FIND_NUM_FILES\": \"{0} {1}\",\n\t\"FIND_IN_FILES_SCOPED\": \"dans <span class='dialog-filename'>{0}</span>\",\n\t\"FIND_IN_FILES_NO_SCOPE\": \"dans le projet\",\n\t\"FIND_IN_FILES_ZERO_FILES\": \"Le filtre exclut tous les fichiers {0}\",\n\t\"FIND_IN_FILES_FILE\": \"fichier\",\n\t\"FIND_IN_FILES_FILES\": \"fichiers\",\n\t\"FIND_IN_FILES_MATCH\": \"résultat\",\n\t\"FIND_IN_FILES_MATCHES\": \"résultats\",\n\t\"FIND_IN_FILES_MORE_THAN\": \"Plus de \",\n\t\"FIND_IN_FILES_PAGING\": \"{0}&mdash;{1}\",\n\t\"FIND_IN_FILES_FILE_PATH\": \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n\t\"FIND_IN_FILES_EXPAND_COLLAPSE\": \"Cliquer tout en appuyant sur Ctrl/Cmd pour tout développer/tout réduire\",\n\t\"FIND_IN_FILES_INDEXING\": \"Indexation pour la recherche instantanée\\u2026\",\n\t\"REPLACE_IN_FILES_ERRORS_TITLE\": \"Erreurs de remplacement\",\n\t\"REPLACE_IN_FILES_ERRORS\": \"Les fichiers suivants n’ont pas été traités car ils ont été modifiés après l’opération de recherche ou ne sont pas accessibles en écriture.\",\n\n\t\"ERROR_FETCHING_UPDATE_INFO_TITLE\": \"Erreur de récupération des informations de mise à jour\",\n\t\"ERROR_FETCHING_UPDATE_INFO_MSG\": \"Un problème est survenu lors de la récupération des dernières informations de mise à jour sur le serveur. Vérifiez que vous êtes connecté à Internet et réessayez.\",\n\n    // File exclusion filters\n\t\"NEW_FILE_FILTER\": \"Nouveau jeu d’exclusion\\u2026\",\n\t\"CLEAR_FILE_FILTER\": \"Ne pas exclure les fichiers\",\n\t\"NO_FILE_FILTER\": \"Aucun fichier exclu\",\n\t\"EXCLUDE_FILE_FILTER\": \"Exclure {0}\",\n\t\"EDIT_FILE_FILTER\": \"Modifier\\u2026\",\n\t\"FILE_FILTER_DIALOG\": \"Modifier le jeu d’exclusion\",\n\t\"FILE_FILTER_INSTRUCTIONS\": \"Exclure les fichiers et dossiers correspondant à l’une des chaînes/sous-chaînes ou aux <a href='{0}' title='{0}'>caractères génériques</a> suivants. Entrez chaque chaîne sur une ligne différente.\",\n\t\"FILTER_NAME_PLACEHOLDER\": \"Nommer ce jeu d’exclusion (facultatif)\",\n\t\"FILTER_NAME_REMAINING\": \"{0} caractères restants\",\n\t\"FILE_FILTER_CLIPPED_SUFFIX\": \"et {0} autre(s)\",\n\t\"FILTER_COUNTING_FILES\": \"Comptage des fichiers\\u2026\",\n\t\"FILTER_FILE_COUNT\": \"Autorise {0} fichier(s) sur les {1} {2}\",\n\t\"FILTER_FILE_COUNT_ALL\": \"Autorise les {0} fichiers {1}\",\n\n    // Quick Edit\n\t\"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\": \"Fonction Édition rapide non disponible pour la position actuelle du curseur\",\n\t\"ERROR_CSSQUICKEDIT_BETWEENCLASSES\": \"Édition rapide CSS : placez le curseur sur un seul nom de classe\",\n\t\"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\": \"Édition rapide CSS : attribut de classe incomplet\",\n\t\"ERROR_CSSQUICKEDIT_IDNOTFOUND\": \"Édition rapide CSS : attribut d’ID incomplet\",\n\t\"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\": \"Édition rapide CSS : placez le curseur dans la balise, la classe ou l’ID\",\n\t\"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\": \"Édition rapide des fonctions de temporisation CSS : syntaxe incorrecte\",\n\t\"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\": \"Édition rapide JS : placez le curseur dans le nom de fonction\",\n\n    // Quick Docs\n\t\"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\": \"Fonction Documentation rapide non disponible pour la position actuelle du curseur\",\n\n    /**\n     * ProjectManager\n     */\n\t\"PROJECT_LOADING\": \"Chargement\\u2026\",\n\t\"UNTITLED\": \"Sans titre\",\n\t\"WORKING_FILES\": \"Fichiers de travail\",\n\n    /**\n     * MainViewManager\n     */\n\t\"TOP\": \"Haut\",\n\t\"BOTTOM\": \"Bas\",\n\t\"LEFT\": \"Gauche\",\n\t\"RIGHT\": \"Droite\",\n\n\t\"CMD_SPLITVIEW_NONE\": \"Pas de fractionnement\",\n\t\"CMD_SPLITVIEW_VERTICAL\": \"Fractionnement vertical\",\n\t\"CMD_SPLITVIEW_HORIZONTAL\": \"Fractionnement horizontal\",\n\t\"SPLITVIEW_MENU_TOOLTIP\": \"Fractionner l’éditeur horizontalement ou verticalement\",\n\t\"GEAR_MENU_TOOLTIP\": \"Configurer l’ensemble de travail\",\n\n\t\"SPLITVIEW_INFO_TITLE\": \"Déjà ouvert\",\n\t\"SPLITVIEW_MULTIPANE_WARNING\": \"Ce fichier est déjà ouvert dans un autre volet. Il sera bientôt possible d’ouvrir un même fichier dans plusieurs volets de l’application {APP_NAME}, mais en attendant, vous ne pouvez consulter le fichier que dans le volet dans lequel il est déjà ouvert.<br /><br />(Ce message ne s’affichera qu’une fois.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n\t\"KEYBOARD_CTRL\": \"Ctrl\",\n\t\"KEYBOARD_SHIFT\": \"Maj\",\n\t\"KEYBOARD_SPACE\": \"Espace\",\n\t\"KEYBOARD_PAGE_UP\": \"Page précédente\",\n\t\"KEYBOARD_PAGE_DOWN\": \"Page suivante\",\n\t\"KEYBOARD_HOME\": \"Accueil\",\n\t\"KEYBOARD_END\": \"Fin\",\n\t\"KEYBOARD_INSERT\": \"Insérer\",\n\t\"KEYBOARD_DELETE\": \"Supprimer\",\n\n    /**\n     * StatusBar strings\n     */\n\t\"STATUSBAR_CURSOR_POSITION\": \"Ligne {0}, colonne {1}\",\n\t\"STATUSBAR_SELECTION_CH_SINGULAR\": \" \\u2014 {0} colonne sélectionnée\",\n\t\"STATUSBAR_SELECTION_CH_PLURAL\": \" \\u2014 {0} colonnes sélectionnées\",\n\t\"STATUSBAR_SELECTION_LINE_SINGULAR\": \" \\u2014 {0} ligne sélectionnée\",\n\t\"STATUSBAR_SELECTION_LINE_PLURAL\": \" \\u2014 {0} lignes sélectionnées\",\n\t\"STATUSBAR_SELECTION_MULTIPLE\": \" \\u2014 {0} sélections\",\n\t\"STATUSBAR_INDENT_TOOLTIP_SPACES\": \"Cliquez ici pour remplacer la mise en retrait par des espaces.\",\n\t\"STATUSBAR_INDENT_TOOLTIP_TABS\": \"Cliquez ici pour remplacer la mise en retrait par des tabulations.\",\n\t\"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\": \"Cliquez ici pour changer le nombre d’espaces utilisés lors de la mise en retrait.\",\n\t\"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\": \"Cliquez ici pour modifier la largeur du caractère de tabulation.\",\n\t\"STATUSBAR_SPACES\": \"Espaces :\",\n\t\"STATUSBAR_TAB_SIZE\": \"Taille de tabulation :\",\n\t\"STATUSBAR_LINE_COUNT_SINGULAR\": \"\\u2014 {0} ligne\",\n\t\"STATUSBAR_LINE_COUNT_PLURAL\": \"\\u2014 {0} lignes\",\n\t\"STATUSBAR_USER_EXTENSIONS_DISABLED\": \"Extensions désactivées\",\n\t\"STATUSBAR_INSERT\": \"INS\",\n\t\"STATUSBAR_OVERWRITE\": \"RFP\",\n\t\"STATUSBAR_INSOVR_TOOLTIP\": \"Cliquez pour faire passer le curseur du mode Insertion (INS) au mode Remplacement (RFP) ou inversement\",\n\t\"STATUSBAR_LANG_TOOLTIP\": \"Cliquez pour modifier le type de fichier\",\n\t\"STATUSBAR_CODE_INSPECTION_TOOLTIP\": \"{0}. Cliquez pour afficher/masquer le panneau des rapports.\",\n\t\"STATUSBAR_DEFAULT_LANG\": \"(par défaut)\",\n\t\"STATUSBAR_SET_DEFAULT_LANG\": \"Utiliser par défaut pour les fichiers .{0}\",\n\t\"STATUSBAR_ENCODING_TOOLTIP\": \"Sélectionner le codage\",\n\n    // CodeInspection: errors/warnings\n\t\"ERRORS_PANEL_TITLE_MULTIPLE\": \"{0} problèmes\",\n\t\"SINGLE_ERROR\": \"1 problème {0}\",\n\t\"MULTIPLE_ERRORS\": \"{1} problèmes {0}\",\n\t\"NO_ERRORS\": \"Aucun problème {0} détecté, félicitations !\",\n\t\"NO_ERRORS_MULTIPLE_PROVIDER\": \"Aucun problème détecté, félicitations !\",\n\t\"LINT_DISABLED\": \"L’analyse lint est désactivée\",\n\t\"NO_LINT_AVAILABLE\": \"Aucun programme lint disponible pour {0}\",\n\t\"NOTHING_TO_LINT\": \"Rien à analyser\",\n\t\"LINTER_TIMED_OUT\": \"Délai dépassé pour {0} après une attente de {1} ms\",\n\t\"LINTER_FAILED\": \"{0} arrêté avec l’erreur suivante : {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n\t\"FILE_MENU\": \"Fichier\",\n\t\"CMD_FILE_NEW_UNTITLED\": \"Nouveau\",\n\t\"CMD_FILE_NEW\": \"Nouveau fichier\",\n\t\"CMD_FILE_NEW_FOLDER\": \"Nouveau dossier\",\n\t\"CMD_FILE_OPEN\": \"Ouvrir\\u2026\",\n\t\"CMD_RECENT_FILES_OPEN\": \"Ouvrir les fichiers récents\\u2026\",\n\t\"CMD_ADD_TO_WORKING_SET\": \"Ouvrir dans l’ensemble de travail\",\n\t\"CMD_OPEN_DROPPED_FILES\": \"Ouvrir les fichiers déposés\",\n\t\"CMD_OPEN_FOLDER\": \"Ouvrir un dossier\\u2026\",\n\t\"CMD_FILE_CLOSE\": \"Fermer\",\n\t\"CMD_FILE_CLOSE_ALL\": \"Tout fermer\",\n\t\"CMD_FILE_CLOSE_LIST\": \"Fermer la liste\",\n\t\"CMD_FILE_CLOSE_OTHERS\": \"Fermer tous les autres\",\n\t\"CMD_FILE_CLOSE_ABOVE\": \"Fermer les autres au-dessus\",\n\t\"CMD_FILE_CLOSE_BELOW\": \"Fermer les autres en dessous\",\n\t\"CMD_FILE_SAVE\": \"Enregistrer\",\n\t\"CMD_FILE_SAVE_ALL\": \"Enregistrer tout\",\n\t\"CMD_FILE_SAVE_AS\": \"Enregistrer sous\\u2026\",\n\t\"CMD_LIVE_FILE_PREVIEW\": \"Aperçu en direct\",\n\t\"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\": \"Activer la version expérimentale de l’Aperçu en direct\",\n\t\"CMD_RELOAD_LIVE_PREVIEW\": \"Forcer le rechargement de l’aperçu en direct\",\n\t\"CMD_PROJECT_SETTINGS\": \"Paramètres du projet\\u2026\",\n\t\"CMD_FILE_RENAME\": \"Renommer\",\n\t\"CMD_FILE_DELETE\": \"Supprimer\",\n\t\"CMD_INSTALL_EXTENSION\": \"Installer une extension\\u2026\",\n\t\"CMD_EXTENSION_MANAGER\": \"Gestionnaire d'extensions\\u2026\",\n\t\"CMD_FILE_REFRESH\": \"Actualiser l’arborescence de fichiers\",\n\t\"CMD_QUIT\": \"Quitter\",\n    // Used in native File menu on Windows\n\t\"CMD_EXIT\": \"Quitter\",\n\n    // Edit menu commands\n\t\"EDIT_MENU\": \"Modifier\",\n\t\"CMD_UNDO\": \"Annuler\",\n\t\"CMD_REDO\": \"Répéter\",\n\t\"CMD_CUT\": \"Couper\",\n\t\"CMD_COPY\": \"Copier\",\n\t\"CMD_PASTE\": \"Coller\",\n\t\"CMD_SELECT_ALL\": \"Sélectionner tout\",\n\t\"CMD_SELECT_LINE\": \"Sélectionner la ligne\",\n\t\"CMD_SPLIT_SEL_INTO_LINES\": \"Scinder la sélection en lignes\",\n\t\"CMD_ADD_CUR_TO_NEXT_LINE\": \"Ajouter un curseur à la ligne suivante\",\n\t\"CMD_ADD_CUR_TO_PREV_LINE\": \"Ajouter un curseur à la ligne précédente\",\n\t\"CMD_INDENT\": \"Retrait\",\n\t\"CMD_UNINDENT\": \"Annuler le retrait\",\n\t\"CMD_DUPLICATE\": \"Dupliquer\",\n\t\"CMD_DELETE_LINES\": \"Supprimer la ligne\",\n\t\"CMD_COMMENT\": \"Activer/Désactiver le commentaire de ligne\",\n\t\"CMD_BLOCK_COMMENT\": \"Commenter les blocs/Annuler les commentaires\",\n\t\"CMD_LINE_UP\": \"Déplacer la ligne vers le haut\",\n\t\"CMD_LINE_DOWN\": \"Déplacer la ligne vers le bas\",\n\t\"CMD_OPEN_LINE_ABOVE\": \"Ouvrir une ligne au-dessus\",\n\t\"CMD_OPEN_LINE_BELOW\": \"Ouvrir une ligne en dessous\",\n\t\"CMD_TOGGLE_CLOSE_BRACKETS\": \"Fermeture automatique des accolades\",\n\t\"CMD_SHOW_CODE_HINTS\": \"Afficher les indicateurs de code\",\n\n    // Search menu commands\n\t\"FIND_MENU\": \"Rechercher\",\n\t\"CMD_FIND\": \"Rechercher\",\n\t\"CMD_FIND_NEXT\": \"Rechercher suivant\",\n\t\"CMD_FIND_PREVIOUS\": \"Rechercher précédent\",\n\t\"CMD_FIND_ALL_AND_SELECT\": \"Rechercher et sélectionner tout\",\n\t\"CMD_ADD_NEXT_MATCH\": \"Ajouter l’occurrence suivante à la sélection\",\n\t\"CMD_SKIP_CURRENT_MATCH\": \"Ignorer et ajouter l’occurrence suivante\",\n\t\"CMD_FIND_IN_FILES\": \"Rechercher dans les fichiers\",\n\t\"CMD_FIND_IN_SUBTREE\": \"Rechercher dans\\u2026\",\n\t\"CMD_REPLACE\": \"Remplacer\",\n\t\"CMD_REPLACE_IN_FILES\": \"Remplacer dans les fichiers\",\n\t\"CMD_REPLACE_IN_SUBTREE\": \"Remplacer dans\\u2026\",\n\n    // View menu commands\n\t\"VIEW_MENU\": \"Affichage\",\n\t\"CMD_HIDE_SIDEBAR\": \"Masquer la barre latérale\",\n\t\"CMD_SHOW_SIDEBAR\": \"Afficher la barre latérale\",\n\t\"CMD_TOGGLE_SIDEBAR\": \"Afficher/Masquer la barre latérale\",\n\t\"CMD_TOGGLE_PANELS\": \"Afficher/Masquer les panneaux\",\n\t\"CMD_TOGGLE_PURE_CODE\": \"Pas de distraction\",\n\t\"CMD_INCREASE_FONT_SIZE\": \"Augmenter la taille de la police\",\n\t\"CMD_DECREASE_FONT_SIZE\": \"Diminuer la taille de la police\",\n\t\"CMD_RESTORE_FONT_SIZE\": \"Restaurer la taille de la police\",\n\t\"CMD_SCROLL_LINE_UP\": \"Faire défiler d’une ligne vers le haut\",\n\t\"CMD_SCROLL_LINE_DOWN\": \"Faire défiler d’une ligne vers le bas\",\n\t\"CMD_TOGGLE_LINE_NUMBERS\": \"Numéros de ligne\",\n\t\"CMD_TOGGLE_ACTIVE_LINE\": \"Surligner la ligne active\",\n\t\"CMD_TOGGLE_WORD_WRAP\": \"Renvoi à la ligne\",\n\t\"CMD_LIVE_HIGHLIGHT\": \"Surlignement dans l’Aperçu en direct\",\n\t\"CMD_VIEW_TOGGLE_INSPECTION\": \"Effectuer une analyse lint des fichiers à l’enregistrement\",\n\t\"CMD_WORKINGSET_SORT_BY_ADDED\": \"Trier par date d’ajout\",\n\t\"CMD_WORKINGSET_SORT_BY_NAME\": \"Trier par nom\",\n\t\"CMD_WORKINGSET_SORT_BY_TYPE\": \"Trier par type\",\n\t\"CMD_WORKING_SORT_TOGGLE_AUTO\": \"Tri automatique\",\n\t\"CMD_THEMES\": \"Thèmes\\u2026\",\n\t\"CMD_TOGGLE_SEARCH_AUTOHIDE\": \"Fermer automatiquement la recherche\",\n\n    // Navigate menu commands\n\t\"NAVIGATE_MENU\": \"Naviguer\",\n\t\"CMD_QUICK_OPEN\": \"Ouverture rapide\",\n\t\"CMD_GOTO_LINE\": \"Atteindre la ligne\",\n\t\"CMD_GOTO_DEFINITION\": \"Accès rapide à la définition\",\n\t\"CMD_GOTO_DEFINITION_PROJECT\": \"Accès rapide à la définition dans le projet\",\n\t\"CMD_GOTO_FIRST_PROBLEM\": \"Accéder au premier problème\",\n\t\"CMD_TOGGLE_QUICK_EDIT\": \"Édition rapide\",\n\t\"CMD_TOGGLE_QUICK_DOCS\": \"Documentation rapide\",\n\t\"CMD_QUICK_EDIT_PREV_MATCH\": \"Correspondance précédente\",\n\t\"CMD_QUICK_EDIT_NEXT_MATCH\": \"Correspondance suivante\",\n\t\"CMD_CSS_QUICK_EDIT_NEW_RULE\": \"Nouvelle règle\",\n\t\"CMD_NEXT_DOC\": \"Document suivant\",\n\t\"CMD_PREV_DOC\": \"Document précédent\",\n\t\"CMD_NAVIGATE_BACKWARD\": \"Naviguer vers l’arrière\",\n\t\"CMD_NAVIGATE_FORWARD\": \"Naviguer vers l’avant\",\n\t\"CMD_NEXT_DOC_LIST_ORDER\": \"Document suivant de la liste\",\n\t\"CMD_PREV_DOC_LIST_ORDER\": \"Document précédent de la liste\",\n\t\"CMD_SHOW_IN_TREE\": \"Afficher dans l’arborescence de fichiers\",\n\t\"CMD_SHOW_IN_EXPLORER\": \"Afficher dans l’Explorateur\",\n\t\"CMD_SHOW_IN_FINDER\": \"Afficher dans le Finder\",\n\t\"CMD_SHOW_IN_OS\": \"Afficher dans le SE\",\n\t\"CMD_SWITCH_PANE_FOCUS\": \"Changer de volet actif\",\n\n    // Help menu commands\n\t\"HELP_MENU\": \"Aide\",\n\t\"CMD_CHECK_FOR_UPDATE\": \"Rechercher les mises à jour\",\n\t\"CMD_HOW_TO_USE_BRACKETS\": \"Comment utiliser {APP_NAME}\",\n\t\"CMD_SUPPORT\": \"Assistance {APP_NAME}\",\n\t\"CMD_SUGGEST\": \"Suggérer une fonctionnalité\",\n\t\"CMD_RELEASE_NOTES\": \"Notes de mise à jour\",\n\t\"CMD_GET_INVOLVED\": \"Participer\",\n\t\"CMD_SHOW_EXTENSIONS_FOLDER\": \"Afficher le dossier d’extensions\",\n\t\"CMD_HEALTH_DATA_STATISTICS\": \"Rapport d’intégrité\",\n\t\"CMD_HOMEPAGE\": \"Page d’accueil de {APP_TITLE}\",\n\t\"CMD_TWITTER\": \"{TWITTER_NAME} sur Twitter\",\n\t\"CMD_ABOUT\": \"À propos de {APP_TITLE}\",\n\t\"CMD_OPEN_PREFERENCES\": \"Ouvrir le fichier de préférences\",\n\t\"CMD_OPEN_KEYMAP\": \"Ouvrir le mappage de touches utilisateur\",\n\n    // Strings for main-view.html\n\t\"EXPERIMENTAL_BUILD\": \"version expérimentale\",\n\t\"RELEASE_BUILD\": \"édition\",\n\t\"DEVELOPMENT_BUILD\": \"version de développement\",\n\t\"PRERELEASE_BUILD\": \"version préliminaire\",\n\t\"RELOAD_FROM_DISK\": \"Recharger à partir du disque\",\n\t\"KEEP_CHANGES_IN_EDITOR\": \"Conserver les modifications dans l’éditeur\",\n\t\"CLOSE_DONT_SAVE\": \"Fermer (sans enregistrer)\",\n\t\"RELAUNCH_CHROME\": \"Relancer Chrome\",\n\t\"ABOUT\": \"À propos\",\n\t\"CLOSE\": \"Fermer\",\n\t\"ABOUT_TEXT_LINE1\": \"Version {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n\t\"ABOUT_TEXT_BUILD_TIMESTAMP\": \"Horodatage de la version : \",\n\t\"ABOUT_TEXT_LINE3\": \"Les mentions légales et conditions générales relatives aux logiciels tiers sont disponibles à l’adresse <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> et sont incluses dans le présent document à titre de référence.\",\n\t\"ABOUT_TEXT_LINE4\": \"La documentation et le code source sont disponibles à l’adresse <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n\t\"ABOUT_TEXT_LINE5\": \"Développé avec \\u2764 et JavaScript par :\",\n\t\"ABOUT_TEXT_LINE6\": \"De nombreux contributeurs (information indisponible pour le moment).\",\n\t\"ABOUT_TEXT_MDN_DOCS\": \"MDN Docs et le logo graphique MDN sont sous licence Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n\t\"UPDATE_NOTIFICATION_TOOLTIP\": \"Une nouvelle version de {APP_NAME} est disponible. Cliquez ici pour plus de détails.\",\n\t\"UPDATE_AVAILABLE_TITLE\": \"Mise à jour disponible\",\n\t\"UPDATE_MESSAGE\": \"Une nouvelle version de {APP_NAME} est disponible. Voici quelques-unes des nouvelles fonctionnalités proposées :\",\n\t\"GET_IT_NOW\": \"Télécharger\",\n\t\"PROJECT_SETTINGS_TITLE\": \"Paramètres de projet pour : {0}\",\n\t\"PROJECT_SETTING_BASE_URL\": \"URL de base de l’Aperçu en direct \",\n\t\"PROJECT_SETTING_BASE_URL_HINT\": \"Pour utiliser un serveur local, entrez une URL telle que http://localhost:8000/\",\n\t\"BASEURL_ERROR_INVALID_PROTOCOL\": \"Le protocole {0} n’est pas pris en charge par l’Aperçu en direct. Veuillez utiliser une adresse de type http: ou https: .\",\n\t\"BASEURL_ERROR_SEARCH_DISALLOWED\": \"L’URL de base ne peut pas contenir de paramètres de recherche tels que \\\"{0}\\\".\",\n\t\"BASEURL_ERROR_HASH_DISALLOWED\": \"L’URL de base ne peut pas contenir de signe dièse (\\\"{0}\\\").\",\n\t\"BASEURL_ERROR_INVALID_CHAR\": \"Les caractères spéciaux tels que '{0}' doivent être codés en %.\",\n\t\"BASEURL_ERROR_UNKNOWN_ERROR\": \"Erreur inconnue lors de l’analyse de l’URL de base\",\n\n    // Strings for Pane.js\n\t\"EMPTY_VIEW_HEADER\": \"<em>Ouvrir un fichier quand ce panneau est actif</em>\",\n\t\"FLIPVIEW_BTN_TOOLTIP\": \"Transférer cette vue dans le volet de {0}\",\n\n    // Strings for themes-settings.html and themes-general.html\n\t\"CURRENT_THEME\": \"Thème actuel \",\n\t\"USE_THEME_SCROLLBARS\": \"Utiliser les barres de défilement du thème \",\n\t\"FONT_SIZE\": \"Taille de la police \",\n\t\"FONT_FAMILY\": \"Famille de polices \",\n\t\"THEMES_SETTINGS\": \"Paramètres des thèmes\",\n\n    // CSS Quick Edit\n\t\"BUTTON_NEW_RULE\": \"Nouvelle règle\",\n\n    // Extension Management strings\n\t\"INSTALL\": \"Installer\",\n\t\"UPDATE\": \"Mettre à jour\",\n\t\"REMOVE\": \"Supprimer\",\n\t\"DISABLE\": \"Désactiver\",\n\t\"ENABLE\": \"Activer\",\n\t\"OVERWRITE\": \"Remplacer\",\n\t\"CANT_REMOVE_DEV\": \"Les extensions du dossier \\\"dev\\\" doivent être supprimées manuellement.\",\n\t\"CANT_UPDATE\": \"La mise à jour n’est pas disponible avec cette version de l’application {APP_NAME}.\",\n\t\"CANT_UPDATE_DEV\": \"Les extensions du dossier « dev » ne peuvent pas être mises à jour automatiquement.\",\n\t\"INSTALL_EXTENSION_TITLE\": \"Installer l’extension\",\n\t\"UPDATE_EXTENSION_TITLE\": \"Mettre à jour l’extension\",\n\t\"INSTALL_EXTENSION_LABEL\": \"URL de l’extension \",\n\t\"INSTALL_EXTENSION_HINT\": \"URL du fichier zip de l’extension ou du référentiel GitHub\",\n\t\"INSTALLING_FROM\": \"Installation de l’extension depuis·{0}\\u2026\",\n\t\"INSTALL_SUCCEEDED\": \"Installation réussie !\",\n\t\"INSTALL_FAILED\": \"Échec de l’installation.\",\n\t\"CANCELING_INSTALL\": \"Annulation en cours\\u2026\",\n\t\"CANCELING_HUNG\": \"L’annulation de l’installation prend beaucoup de temps. Il est possible qu’une erreur interne se soit produite.\",\n\t\"INSTALL_CANCELED\": \"Installation annulée.\",\n\t\"VIEW_COMPLETE_DESCRIPTION\": \"Voir la description complète\",\n\t\"VIEW_TRUNCATED_DESCRIPTION\": \"Voir la description tronquée\",\n\t\"SORT_EXTENSION_METHOD\": \"Trier les extensions suivant downloadCount ou publishedDate\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n\t\"INVALID_ZIP_FILE\": \"Le contenu téléchargé n’est pas un fichier zip valide.\",\n\t\"MISSING_PACKAGE_JSON\": \"Le pack ne contient pas de fichier package.json.\",\n\t\"INVALID_PACKAGE_JSON\": \"Le fichier package.json n’est pas valide (erreur : {0}).\",\n\t\"MISSING_PACKAGE_NAME\": \"Le fichier package.json n’indique pas le nom du pack.\",\n\t\"BAD_PACKAGE_NAME\": \"{0} n’est pas un nom de pack valide.\",\n\t\"MISSING_PACKAGE_VERSION\": \"Le fichier package.json n’indique pas la version du pack.\",\n\t\"INVALID_VERSION_NUMBER\": \"Le numéro de version du pack ({0}) n’est pas valide.\",\n\t\"INVALID_BRACKETS_VERSION\": \"La chaîne de compatibilité {APP_NAME} ({0}) n’est pas valide.\",\n\t\"DISALLOWED_WORDS\": \"Le champ {0} ne peut pas contenir les mots ({1}).\",\n\t\"NPM_INSTALL_FAILED\": \"Échec de la commande npm install : {0}\",\n\t\"API_NOT_COMPATIBLE\": \"L’extension n’est pas compatible avec cette version de l’application {APP_NAME}. Elle a été installée dans le dossier contenant les extensions désactivées.\",\n\t\"MISSING_MAIN\": \"Le pack ne contient pas de fichier main.js.\",\n\t\"EXTENSION_ALREADY_INSTALLED\": \"L’installation de ce pack remplacera une extension installée précédemment. Voulez-vous remplacer l’extension installée ?\",\n\t\"EXTENSION_SAME_VERSION\": \"Ce pack correspond à la même version que celle installée actuellement. Voulez-vous remplacer l’installation actuelle ?\",\n\t\"EXTENSION_OLDER_VERSION\": \"Ce pack correspond à la version {0}, qui est antérieure à la version actuellement installée ({1}). Voulez-vous remplacer l’installation actuelle ?\",\n\t\"DOWNLOAD_ID_IN_USE\": \"Erreur interne : l’ID de téléchargement est déjà utilisé.\",\n\t\"NO_SERVER_RESPONSE\": \"Impossible de se connecter au serveur.\",\n\t\"BAD_HTTP_STATUS\": \"Fichier introuvable sur le serveur (HTTP {0}).\",\n\t\"CANNOT_WRITE_TEMP\": \"Impossible d’enregistrer le téléchargement vers le fichier temporaire.\",\n\t\"ERROR_LOADING\": \"Une erreur s’est produite au démarrage de l’extension.\",\n\t\"MALFORMED_URL\": \"URL non valide. Veuillez vérifier l’URL saisie.\",\n\t\"UNSUPPORTED_PROTOCOL\": \"L’URL doit commencer par http ou https.\",\n\t\"UNKNOWN_ERROR\": \"Erreur interne inconnue.\",\n    // For NOT_FOUND_ERR, see generic strings above\n\t\"EXTENSION_MANAGER_TITLE\": \"Gestionnaire d’extensions\",\n\t\"EXTENSION_MANAGER_ERROR_LOAD\": \"Impossible d’accéder au registre de l’extension. Réessayez ultérieurement.\",\n\t\"INSTALL_EXTENSION_DRAG\": \"Faire glisser le fichier .zip ici ou\",\n\t\"INSTALL_EXTENSION_DROP\": \"Déposer le fichier .zip pour lancer l’installation\",\n\t\"INSTALL_EXTENSION_DROP_ERROR\": \"Installation/Mise à jour interrompue en raison des erreurs suivantes :\",\n\t\"INSTALL_FROM_URL\": \"Installer à partir de l’URL\\u2026\",\n\t\"INSTALL_EXTENSION_VALIDATING\": \"Validation en cours\\u2026\",\n\t\"EXTENSION_AUTHOR\": \"Auteur\",\n\t\"EXTENSION_DATE\": \"Date\",\n\t\"EXTENSION_INCOMPATIBLE_NEWER\": \"Cette extension nécessite une version plus récente de l’application {APP_NAME}.\",\n\t\"EXTENSION_INCOMPATIBLE_OLDER\": \"Cette extension n’est actuellement compatible qu’avec les versions antérieures de l’application {APP_NAME}.\",\n\t\"EXTENSION_LATEST_INCOMPATIBLE_NEWER\": \"La version {0} de cette extension nécessite une version plus récente de {APP_NAME}. Mais vous pouvez installer la version antérieure {1}.\",\n\t\"EXTENSION_LATEST_INCOMPATIBLE_OLDER\": \"La version {0} de cette extension n’est compatible qu’avec les anciennes versions de {APP_NAME}. Mais vous pouvez installer la version antérieure {1}.\",\n\t\"EXTENSION_NO_DESCRIPTION\": \"Aucune description\",\n\t\"EXTENSION_MORE_INFO\": \"Plus d’infos\\u2026\",\n\t\"EXTENSION_ERROR\": \"Erreur d’extension\",\n\t\"EXTENSION_KEYWORDS\": \"Mots-clés\",\n\t\"EXTENSION_TRANSLATED_USER_LANG\": \"Traduit en {0} langues, y compris la vôtre\",\n\t\"EXTENSION_TRANSLATED_GENERAL\": \"Traduit en {0} langues\",\n\t\"EXTENSION_TRANSLATED_LANGS\": \"Cette extension a été traduite dans les langues suivantes : {0}\",\n\t\"EXTENSION_INSTALLED\": \"Installée\",\n\t\"EXTENSION_UPDATE_INSTALLED\": \"Cette mise à jour d’extension a été téléchargée et va être installée une fois le rechargement de {APP_NAME} effectué.\",\n\t\"EXTENSION_SEARCH_PLACEHOLDER\": \"Rechercher\",\n\t\"EXTENSION_MORE_INFO_LINK\": \"Plus\",\n\t\"BROWSE_EXTENSIONS\": \"Parcourir les extensions\",\n\t\"EXTENSION_MANAGER_REMOVE\": \"Supprimer l’extension\",\n\t\"EXTENSION_MANAGER_REMOVE_ERROR\": \"Impossible de supprimer une ou plusieurs extensions : {0}. {APP_NAME} va être rechargé malgré tout.\",\n\t\"EXTENSION_MANAGER_UPDATE\": \"Mettre à jour l’extension\",\n\t\"EXTENSION_MANAGER_UPDATE_ERROR\": \"Impossible de mettre à jour une ou plusieurs extensions : {0}. {APP_NAME} va être rechargé malgré tout.\",\n\t\"EXTENSION_MANAGER_DISABLE\": \"Désactiver l’extension\",\n\t\"EXTENSION_MANAGER_DISABLE_ERROR\": \"Impossible de désactiver une ou plusieurs extensions : {0}. {APP_NAME} va être rechargé malgré tout.\",\n\t\"MARKED_FOR_REMOVAL\": \"Marquée pour suppression\",\n\t\"UNDO_REMOVE\": \"Annuler\",\n\t\"MARKED_FOR_UPDATE\": \"Marquée pour mise à jour\",\n\t\"UNDO_UPDATE\": \"Annuler\",\n\t\"MARKED_FOR_DISABLING\": \"Marqué pour désactivation\",\n\t\"UNDO_DISABLE\": \"Annuler\",\n\t\"CHANGE_AND_RELOAD_TITLE\": \"Modifier les extensions\",\n\t\"CHANGE_AND_RELOAD_MESSAGE\": \"Pour mettre à jour, supprimer ou désactiver les extensions marquées, {APP_NAME} va devoir être rechargé. Vous serez invité à enregistrer vos modifications.\",\n\t\"REMOVE_AND_RELOAD\": \"Supprimer les extensions et recharger\",\n\t\"CHANGE_AND_RELOAD\": \"Modifier les extensions et recharger\",\n\t\"UPDATE_AND_RELOAD\": \"Mettre à jour les extensions et recharger\",\n\t\"DISABLE_AND_RELOAD\": \"Désactiver les extensions et recharger\",\n\t\"PROCESSING_EXTENSIONS\": \"Traitement des changements d’extension\\u2026\",\n\t\"EXTENSION_NOT_INSTALLED\": \"Impossible de supprimer l’extension {0} car elle n’est pas installée.\",\n\t\"NO_EXTENSIONS\": \"Aucune extension installée pour le moment.<br>Cliquez sur l’onglet Disponibles ci-dessus pour vous lancer.\",\n\t\"NO_EXTENSION_MATCHES\": \"Aucune extension ne correspond à votre recherche.\",\n\t\"REGISTRY_SANITY_CHECK_WARNING\": \"REMARQUE : ces extensions peuvent provenir d’autres sources que l’application {APP_NAME} elle-même. Les extensions ne sont pas contrôlées et disposent de privilèges locaux complets. Soyez prudents lorsque vous installez des extensions provenant d’une source inconnue.\",\n\t\"EXTENSIONS_INSTALLED_TITLE\": \"Installées\",\n\t\"EXTENSIONS_DEFAULT_TITLE\": \"Par défaut\",\n\t\"EXTENSIONS_AVAILABLE_TITLE\": \"Disponibles\",\n\t\"EXTENSIONS_THEMES_TITLE\": \"Thèmes\",\n\t\"EXTENSIONS_UPDATES_TITLE\": \"Mises à jour\",\n\t\"EXTENSIONS_LAST_UPDATED\": \"Dernière mise à jour\",\n\t\"EXTENSIONS_DOWNLOADS\": \"Téléchargements\",\n\n\t\"INLINE_EDITOR_NO_MATCHES\": \"Aucun résultat.\",\n\t\"INLINE_EDITOR_HIDDEN_MATCHES\": \"Tous les résultats sont réduits. Développez les fichiers dans la liste de droite pour voir le détail.\",\n\t\"CSS_QUICK_EDIT_NO_MATCHES\": \"Aucune règle CSS existante ne correspond à votre sélection.<br> Cliquez sur « Nouvelle règle » pour en créer une.\",\n\t\"CSS_QUICK_EDIT_NO_STYLESHEETS\": \"Votre projet ne contient aucune feuille de style.<br>Créez-en une pour pouvoir ajouter des règles CSS.\",\n\n    // Custom Viewers\n\t\"IMAGE_VIEWER_LARGEST_ICON\": \"maximum\",\n\n    /**\n     * Unit names\n     */\n\t\"UNIT_PIXELS\": \"pixels\",\n\n    // extensions/default/DebugCommands\n\t\"DEBUG_MENU\": \"Déboguer\",\n\t\"ERRORS\": \"Erreurs \",\n\t\"CMD_SHOW_DEV_TOOLS\": \"Afficher les outils de développement\",\n\t\"CMD_REFRESH_WINDOW\": \"Recharger avec les extensions\",\n\t\"CMD_RELOAD_WITHOUT_USER_EXTS\": \"Recharger sans les extensions\",\n\t\"CMD_NEW_BRACKETS_WINDOW\": \"Nouvelle fenêtre {APP_NAME}\",\n\t\"CMD_LAUNCH_SCRIPT_MAC\": \"Installer le raccourci de ligne de commande\",\n\t\"CMD_SWITCH_LANGUAGE\": \"Changer de langue\",\n\t\"CMD_RUN_UNIT_TESTS\": \"Exécuter des tests\",\n\t\"CMD_SHOW_PERF_DATA\": \"Afficher les données de performances\",\n\t\"CMD_ENABLE_NODE_DEBUGGER\": \"Activer le débogage de nœud\",\n\t\"CMD_LOG_NODE_STATE\": \"Noter l’état du nœud dans la console\",\n\t\"CMD_RESTART_NODE\": \"Redémarrer le nœud\",\n\t\"CMD_SHOW_ERRORS_IN_STATUS_BAR\": \"Afficher les erreurs dans la barre d’état\",\n\t\"CMD_OPEN_BRACKETS_SOURCE\": \"Ouvrir la source de {APP_NAME}\",\n\n\t\"CREATING_LAUNCH_SCRIPT_TITLE\": \"Raccourci de ligne de commande {APP_NAME}\",\n\t\"ERROR_CREATING_LAUNCH_SCRIPT\": \"Une erreur est survenue lors de l’installation du raccourci de ligne de commande. Essayez d’appliquer <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>ces suggestions pour résoudre le problème</a>.<br/><br/>Motif : {0}\",\n\t\"ERROR_CLTOOLS_RMFAILED\": \"Impossible de supprimer le lien symbolique existant <code>/usr/local/bin/brackets</code>.\",\n\t\"ERROR_CLTOOLS_MKDIRFAILED\": \"Impossible de créer le répertoire <code>/usr/local/bin</code>.\",\n\t\"ERROR_CLTOOLS_LNFAILED\": \"Impossible de créer le lien symbolique <code>/usr/local/bin/brackets</code>.\",\n\t\"ERROR_CLTOOLS_SERVFAILED\": \"Erreur interne.\",\n\t\"ERROR_CLTOOLS_NOTSUPPORTED\": \"Le raccourci de ligne de commande n’est pas pris en charge par ce système d’exploitation.\",\n\t\"LAUNCH_SCRIPT_CREATE_SUCCESS\": \"Opération réussie ! À présent, vous pouvez facilement lancer {APP_NAME} depuis la ligne de commande : utilisez <code>brackets myFile.txt</code> pour ouvrir un fichier ou <code>brackets myFolder</code> pour changer de projet. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>En savoir plus</a> sur l’utilisation de {APP_NAME} depuis la ligne de commande.\",\n\n\t\"LANGUAGE_TITLE\": \"Changer de langue\",\n\t\"LANGUAGE_MESSAGE\": \"Langue :\",\n\t\"LANGUAGE_SUBMIT\": \"Recharger {APP_NAME}\",\n\t\"LANGUAGE_CANCEL\": \"Annuler\",\n\t\"LANGUAGE_SYSTEM_DEFAULT\": \"Langue par défaut du système\",\n\n    // extensions/default/HealthData\n\t\"HEALTH_DATA_NOTIFICATION\": \"Health Report Preferences\",\n\t\"HEALTH_FIRST_POPUP_TITLE\": \"Rapport d’intégrité de {APP_NAME}\",\n\t\"HEALTH_DATA_DO_TRACK\": \"Partager des informations pseudonymes sur la façon dont j’utilise {APP_NAME}\",\n\t\"HEALTH_DATA_NOTIFICATION_MESSAGE\": \"Afin d’améliorer {APP_NAME}, nous transmettons régulièrement des statistiques limitées et <strong>pseudonymes</strong> à Adobe sur la manière dont vous utilisez {APP_NAME}. Ces données permettent de hiérarchiser les fonctionnalités à traiter, de détecter les bugs éventuels et d’identifier les problèmes d’utilisation.<br><br>Pour voir les renseignements collectés et choisir ceux que vous ne souhaitez pas partager, cliquez sur <strong>Aide > Rapport d’intégrité</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Project-Health-Data'>Lisez cet article pour en savoir plus concernant le rapport d’intégrité de {APP_NAME}</a>\",\n\t\"HEALTH_DATA_PREVIEW\": \"Rapport d’intégrité de {APP_NAME}\",\n\t\"HEALTH_DATA_PREVIEW_INTRO\": \"<p>Afin d’améliorer {APP_NAME}, nous transmettons régulièrement des statistiques limitées et <strong>pseudonymes</strong> à Adobe sur la manière dont vous utilisez {APP_NAME}. Ces données permettent de hiérarchiser les fonctionnalités à traiter, de détecter les bugs éventuels et d’identifier les problèmes d’utilisation. <a href='https://github.com/adobe/brackets/wiki/Project-Health-Data'>Lisez cet article concernant le rapport d’intégrité de {APP_NAME}</a> et découvrez en quoi il est utile à la communauté {APP_NAME} tout en préservant votre confidentialité.</p><p>Vous trouverez ci-dessous un résumé des données qui seront envoyées dans le cadre de votre prochain rapport d’intégrité <em>si</em> vous décidez d’activer cette option.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n\t\"INLINE_TIMING_EDITOR_TIME\": \"Temps\",\n\t\"INLINE_TIMING_EDITOR_PROGRESSION\": \"Progression\",\n\t\"BEZIER_EDITOR_INFO\": \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Déplacer le point sélectionné<br><kbd class='text'>Maj</kbd> Déplacer de dix unités<br><kbd class='text'>Tabulation</kbd> Permuter les points\",\n\t\"STEPS_EDITOR_INFO\": \"<kbd>↑</kbd><kbd>↓</kbd> Augmenter ou réduire les pas<br><kbd>←</kbd><kbd>→</kbd> 'Démarrer' ou 'Arrêter'\",\n\t\"INLINE_TIMING_EDITOR_INVALID\": \"L’ancienne valeur <code>{0}</code> n’est pas valide et a donc été remplacée par <code>{1}</code> pour la fonction affichée. Le document sera mis à jour à la première modification.\",\n\n    // extensions/default/InlineColorEditor\n\t\"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\": \"Couleur actuelle\",\n\t\"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\": \"Couleur d’origine\",\n\t\"COLOR_EDITOR_RGBA_BUTTON_TIP\": \"Format RGBa\",\n\t\"COLOR_EDITOR_HEX_BUTTON_TIP\": \"Format Hex\",\n\t\"COLOR_EDITOR_HSLA_BUTTON_TIP\": \"Format HSLa\",\n\t\"COLOR_EDITOR_0X_BUTTON_TIP\": \"Format hexadécimal (0x)\",\n\t\"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\": \"{0} (utilisé {1} fois)\",\n\t\"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\": \"{0} (utilisé {1} fois)\",\n\n    // extensions/default/JavaScriptCodeHints\n\t\"CMD_JUMPTO_DEFINITION\": \"Accéder à la définition\",\n\t\"CMD_SHOW_PARAMETER_HINT\": \"Afficher l’indicateur de paramètre\",\n\t\"NO_ARGUMENTS\": \"<aucun paramètre>\",\n\t\"DETECTED_EXCLUSION_TITLE\": \"Problème d’inférence de fichier Javascript\",\n\t\"DETECTED_EXCLUSION_INFO\": \"{APP_NAME} a rencontré des problèmes lors du traitement du fichier <span class='dialog-filename'>{0}</span>.<br><br>La fonction d’accès aux définitions, les indicateurs de code et la fonction Edition rapide de ce fichier ne seront plus traités. Pour réactiver ce fichier, ouvrez <code>.brackets.json</code> dans votre projet et éditez la section <code>jscodehints.detectedExclusions</code>.<br><br>Il s’agit vraisemblablement d’un bug au niveau de l’application {APP_NAME}. Si vous pouvez nous transmettre une copie de ce fichier, merci de <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>consigner un bug</a> en fournissant un lien vers le fichier en question.\",\n\n    // extensions/default/JavascriptRefactoring\n\t\"CMD_REFACTOR\": \"Remanier\",\n\t\"CMD_EXTRACTTO_VARIABLE\": \"Extraire vers variable\",\n\t\"CMD_EXTRACTTO_FUNCTION\": \"Extraire vers fonction\",\n\t\"ERROR_TERN_FAILED\": \"Impossible d’obtenir des données depuis Tern\",\n\t\"ERROR_EXTRACTTO_VARIABLE_NOT_VALID\": \"La sélection ne forme pas une expression\",\n\t\"ERROR_EXTRACTTO_FUNCTION_NOT_VALID\": \"Le bloc sélectionné doit représenter un ensemble d’instructions ou une expression\",\n\t\"ERROR_EXTRACTTO_VARIABLE_MULTICURSORS\": \"L’option Extraire vers variable ne fonctionne pas en cas de curseurs multiples\",\n\t\"ERROR_EXTRACTTO_FUNCTION_MULTICURSORS\": \"L’option Extraire vers fonction ne fonctionne pas en cas de curseurs multiples\",\n\t\"EXTRACTTO_FUNCTION_SELECT_SCOPE\": \"Choisir la portée cible\",\n\t\"EXTRACTTO_VARIABLE_SELECT_EXPRESSION\": \"Sélectionner une expression\",\n\t\"CMD_REFACTORING_RENAME\": \"Renommer\",\n\t\"CMD_REFACTORING_TRY_CATCH\": \"Encapsuler dans Try/Catch\",\n\t\"CMD_REFACTORING_CONDITION\": \"Encapsuler dans Condition\",\n\t\"CMD_REFACTORING_GETTERS_SETTERS\": \"Créer des getters/setters\",\n\t\"CMD_REFACTORING_ARROW_FUNCTION\": \"Convertir en fonction de flèche\",\n\t\"DESCRIPTION_CODE_REFACTORING\": \"Activer/désactiver le remaniement de code JavaScript\",\n\t\"ERROR_TRY_CATCH\": \"Sélectionner un code valide à encapsuler dans un bloc Try/Catch\",\n\t\"ERROR_WRAP_IN_CONDITION\": \"Sélectionner un code valide à encapsuler dans un bloc Condition\",\n\t\"ERROR_ARROW_FUNCTION\": \"Placer le curseur à l’intérieur d’une expression de fonction\",\n\t\"ERROR_GETTERS_SETTERS\": \"Placer le curseur au niveau d’un membre d’une expression d’objet\",\n\t\"ERROR_RENAME_MULTICURSOR\": \"Impossible de renommer en cas d’utilisation de plusieurs curseurs\",\n\t\"ERROR_RENAME_QUICKEDIT\": \"Impossible de renommer cet identifiant, car il est référencé ailleurs en dehors de cette fonction.\",\n\t\"ERROR_RENAME_GENERAL\": \"Impossible de renommer le texte sélectionné\",\n\n    // extensions/default/JSLint\n\t\"JSLINT_NAME\": \"JSLint\",\n\n    // extensions/default/QuickView\n\t\"CMD_ENABLE_QUICK_VIEW\": \"Affichage rapide au survol\",\n\n    // extensions/default/RecentProjects\n\t\"CMD_TOGGLE_RECENT_PROJECTS\": \"Projets récents\",\n\n    // extensions/default/MDNDocs\n\t\"DOCS_MORE_LINK\": \"En savoir plus\",\n\n    // extensions/default/CodeFolding\n\t\"COLLAPSE_ALL\": \"Réduire tout\",\n\t\"EXPAND_ALL\": \"Développer tout\",\n\t\"COLLAPSE_CURRENT\": \"Réduire l’élément actif\",\n\t\"EXPAND_CURRENT\": \"Développer l’élément actif\",\n\n    // extensions/default/NavigationAndHistory\n\t\"RECENT_FILES_DLG_HEADER\": \"Fichiers récents\",\n\t\"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\": \"Effacer\",\n\t\"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\": \"Effacer les fichiers non présents dans l’ensemble de travail\",\n\n    // Descriptions of core preferences\n\t\"DESCRIPTION_CLOSE_BRACKETS\": \"vrai pour fermer automatiquement les accolades, les crochets et les parenthèses\",\n\t\"DESCRIPTION_CLOSE_OTHERS_ABOVE\": \"faux pour supprimer l’option « Fermer les autres au-dessus » du menu contextuel Fichiers de travail\",\n\t\"DESCRIPTION_CLOSE_OTHERS_BELOW\": \"faux pour supprimer l’option « Fermer les autres en dessous » du menu contextuel Fichiers de travail\",\n\t\"DESCRIPTION_CLOSE_OTHERS\": \"faux pour supprimer l’option « Fermer tous les autres » du menu contextuel Fichiers de travail\",\n\t\"DESCRIPTION_CLOSE_TAGS\": \"Définit les options de fermeture des balises\",\n\t\"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\": \"Ensemble de balises qui ne doivent pas se fermer automatiquement\",\n\t\"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\": \"Fermer quand l’utilisateur tape le caractère > de la balise d’ouverture\",\n\t\"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\": \"Fermer quand l’utilisateur tape le caractère / de la balise de fermeture\",\n\t\"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\": \"Ensemble de balises qui, quand elles sont ouvertes, disposent d’une ligne vierge\",\n\t\"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\": \"vrai pour toujours générer des marqueurs de sections réductibles quand le niveau de retrait change\",\n\t\"DESCRIPTION_CODE_FOLDING_ENABLED\": \"vrai pour activer le pliage de code\",\n\t\"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\": \"vrai pour rendre les marqueurs de réduction de section visibles uniquement quand l’utilisateur passe la souris sur la gouttière\",\n\t\"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\": \"Limite le nombre de niveaux auquel s’applique l’option Réduire tout\",\n\t\"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\": \"Nombre minimum de lignes pour qu’une icône de section réductible apparaisse\",\n\t\"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\": \"vrai pour mémoriser les sections réduites si vous fermez et rouvrez un fichier ou un projet\",\n\t\"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"vrai pour activer le pliage de code sur le texte sélectionné dans l’éditeur\",\n\t\"DESCRIPTION_DISABLED_DEFAULT_EXTENSIONS\": \"Extensions par défaut qui sont désactivées\",\n\t\"DESCRIPTION_ATTR_HINTS\": \"Activer/désactiver les indicateurs d’attribut HTML\",\n\t\"DESCRIPTION_CSS_PROP_HINTS\": \"Activer/désactiver les indicateurs de propriété CSS/LESS/SCSS\",\n\t\"DESCRIPTION_JS_HINTS\": \"Activer/désactiver les indicateurs de code JavaScript\",\n\t\"DESCRIPTION_JS_HINTS_TYPE_DETAILS\": \"Activer/désactiver les détails de type de données dans les indicateurs de code JavaScript\",\n\t\"DESCRIPTION_PREF_HINTS\": \"Activer/désactiver les indicateurs de code Préférences\",\n\t\"DESCRIPTION_SPECIAL_CHAR_HINTS\": \"Activer/désactiver les indicateurs d’entité HTML\",\n\t\"DESCRIPTION_SVG_HINTS\": \"Activer/désactiver les indicateurs de code SVG\",\n\t\"DESCRIPTION_HTML_TAG_HINTS\": \"Activer/désactiver les indicateurs de balise HTML\",\n\t\"DESCRIPTION_URL_CODE_HINTS\": \"Activer/désactiver les indicateurs d’URL dans le code HTML et CSS/LESS/SCSS\",\n\t\"DESCRIPTION_DRAG_DROP_TEXT\": \"Activer/désactiver la fonctionnalité de glisser-déposer\",\n\t\"DESCRIPTION_HEALTH_DATA_TRACKING\": \"Activer le suivi des données d’intégrité\",\n\t\"DESCRIPTION_HIGHLIGHT_MATCHES\": \"Active le surlignage automatique des chaînes correspondantes dans tout le document\",\n\t\"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\": \"Surligner toutes les chaînes qui correspondent au paramètre dans lequel se trouve le curseur actuellement (sélection non nécessaire)\",\n\t\"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\": \"Surligner uniquement quand la sélection est un paramètre complet\",\n\t\"DESCRIPTION_INSERT_HINT_ON_TAB\": \"vrai pour insérer l’indicateur de code sélectionné avec la touche Tabulation\",\n\t\"DESCRIPTION_NO_HINTS_ON_DOT\": \"vrai pour que les indicateurs de code JS ne s’affichent pas automatiquement quand l’utilisateur tape un point (.)\",\n\t\"DESCRIPTION_JSLINT_OPTIONS\": \"Objet doté des options par défaut pour JSLint\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_ASS\": \"vrai pour autoriser les expressions d’affectation\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_BITWISE\": \"vrai pour autoriser les opérateurs bitwise\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_BROWSER\": \"vrai si les paramètres globaux de navigateur standard doivent être prédéfinis\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\": \"vrai pour autoriser les idiomes Google Closure\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\": \"vrai pour autoriser les instructions « continue »\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_COUCH\": \"vrai si les paramètres globaux CouchDB doivent être prédéfinis\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_DEBUG\": \"vrai pour autoriser les instructions Debugger\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_DEVEL\": \"vrai si les paramètres globaux du navigateur utiles au développement doivent être prédéfinis\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_EQEQ\": \"vrai pour autoriser == et !=\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_ES6\": \"vrai si les paramètres globaux ES6 doivent être prédéfinis\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_EVIL\": \"vrai pour autoriser eval\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_FORIN\": \"vrai pour autoriser la suppression du filtre « pour ... dans »\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_INDENT\": \"Définir une largeur de tabulation spécifique\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_MAXERR\": \"Nombre maximum d’avertissements signalés\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\": \"Nombre maximum de caractères sur une ligne\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\": \"vrai pour autoriser les constructeurs non indiqués en capitales\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_NODE\": \"vrai si les paramètres globaux Node.js doivent être prédéfinis\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_NOMEN\": \"vrai pour autoriser le trait de soulignement libre (dangling) dans les identificateurs\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\": \"vrai pour arrêter à la première erreur\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\": \"vrai pour autoriser ++ et --\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_REGEXP\": \"vrai pour autoriser . et [^...]. dans RegExp\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_RHINO\": \"vrai si les paramètres globaux Rhino doivent être prédéfinis\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\": \"vrai pour autoriser l’absence de balise Pragma « use strict »\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_STUPID\": \"vrai si des méthodes de blocage (« ...Sync ») peuvent être utilisées\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_SUB\": \"vrai pour autoriser les indices inefficaces\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_TODO\": \"vrai pour autoriser les commentaires TODO\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\": \"vrai pour autoriser les paramètres inutilisés\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_VARS\": \"vrai pour autoriser plusieurs variables dans une fonction\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_WHITE\": \"vrai pour ignorer les règles d’espaces blancs\",\n\t\"DESCRIPTION_LANGUAGE\": \"Paramètres spécifiques à la langue\",\n\t\"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\": \"Mappages supplémentaires entre extension de fichier et nom de langue\",\n\t\"DESCRIPTION_LANGUAGE_FILE_NAMES\": \"Mappages supplémentaires entre nom de fichier et nom de langue\",\n\t\"DESCRIPTION_LINEWISE_COPY_CUT\": \"En cas d’absence de sélection, un couper-copier coupe ou copie les lignes entières comportant des curseurs.\",\n\t\"DESCRIPTION_INPUT_STYLE\": \"Sélectionne la manière dont CodeMirror gère l'entrée et la mise au point. Il peut s'agir de zone de texte, qui est la sélection par défaut, ou de contenu modifiable, qui est la meilleure méthode pour les lecteurs d'écran (instable)\",\n\t\"DESCRIPTION_LINTING_ENABLED\": \"vrai pour activer l’inspection de code\",\n\t\"DESCRIPTION_ASYNC_TIMEOUT\": \"Durée, en millisecondes, après laquelle les utilitaires lint asynchrones échouent\",\n\t\"DESCRIPTION_LINTING_PREFER\": \"Ensemble d’utilitaires lint à exécuter en premier\",\n\t\"DESCRIPTION_LIVE_DEV_MULTIBROWSER\": \"vrai pour activer la version expérimentale de l’Aperçu en direct\",\n\t\"DESCRIPTION_USE_PREFERED_ONLY\": \"vrai pour exécuter uniquement les fournisseurs spécifiés dans linting.prefer\",\n\t\"DESCRIPTION_MAX_CODE_HINTS\": \"Nombre maximum d’indicateurs de code affichés à la fois\",\n\t\"DESCRIPTION_PATH\": \"Paramètres spécifiques au chemin d’accès\",\n\t\"DESCRIPTION_PROXY\": \"URL du serveur proxy utilisé pour l’installation des extensions\",\n\t\"DESCRIPTION_SCROLL_PAST_END\": \"vrai pour autoriser le défilement au-delà de la fin du document\",\n\t\"DESCRIPTION_SHOW_CODE_HINTS\": \"faux pour désactiver tous les indicateurs de code\",\n\t\"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\": \"Laisse le curseur clignotant visible en cas de sélection de texte\",\n\t\"DESCRIPTION_SHOW_LINE_NUMBERS\": \"vrai pour afficher les numéros de ligne dans une « gouttière » à gauche du code\",\n\t\"DESCRIPTION_SMART_INDENT\": \"Mettre en retrait automatiquement lors de la création d’un nouveau bloc\",\n\t\"DESCRIPTION_SOFT_TABS\": \"faux pour désactiver le comportement des tabulations flexibles\",\n\t\"DESCRIPTION_SORT_DIRECTORIES_FIRST\": \"vrai pour trier les répertoires en premier dans l’arborescence de projets\",\n\t\"DESCRIPTION_SPACE_UNITS\": \"Nombre d’espaces à utiliser pour la mise en retrait\",\n\t\"DESCRIPTION_STATIC_SERVER_PORT\": \"Numéro de port que le serveur intégré doit utiliser pour l’Aperçu en direct\",\n\t\"DESCRIPTION_STYLE_ACTIVE_LINE\": \"vrai pour surligner la couleur d’arrière-plan de la ligne sur laquelle se trouve le curseur\",\n\t\"DESCRIPTION_TAB_SIZE\": \"Nombre d’espaces à afficher pour les tabulations\",\n\t\"DESCRIPTION_USE_TAB_CHAR\": \"vrai pour utiliser des tabulations au lieu d’espaces\",\n\t\"DESCRIPTION_UPPERCASE_COLORS\": \"vrai pour générer des couleurs hexadécimales en majuscules dans l’éditeur de couleur intégré\",\n\t\"DESCRIPTION_WORD_WRAP\": \"Renvoyer à la ligne automatiquement en cas de dépassement de la largeur de la fenêtre\",\n\t\"DESCRIPTION_SEARCH_AUTOHIDE\": \"Fermer la recherche dès que l’éditeur redevient actif\",\n\t\"DESCRIPTION_DETECTED_EXCLUSIONS\": \"Liste de fichiers qui ont été identifiés comme provoquant une perte de contrôle de Tern\",\n\t\"DESCRIPTION_INFERENCE_TIMEOUT\": \"Laps de temps au bout duquel le processus Tern expire quand il tente d’interpréter des fichiers\",\n\t\"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\": \"vrai pour afficher les erreurs dans la barre d’état\",\n\t\"DESCRIPTION_QUICK_VIEW_ENABLED\": \"vrai pour activer l’affichage rapide\",\n\t\"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\": \"vrai pour afficher les aperçus d’images pour les extensions sans URL\",\n\t\"DESCRIPTION_THEME\": \"Sélectionner un thème {APP_NAME}\",\n\t\"DESCRIPTION_USE_THEME_SCROLLBARS\": \"vrai pour autoriser les barres de défilement personnalisées\",\n\t\"DESCRIPTION_LINTING_COLLAPSED\": \"vrai pour réduire le panneau d’analyse lint\",\n\t\"DESCRIPTION_FONT_FAMILY\": \"Changer de famille de polices\",\n\t\"DESCRIPTION_FONT_SIZE\": \"Modifier la taille de police, par ex. 13px\",\n\t\"DESCRIPTION_FIND_IN_FILES_NODE\": \"vrai pour activer la recherche basée sur des nœuds\",\n\t\"DESCRIPTION_FIND_IN_FILES_INSTANT\": \"vrai pour activer la recherche instantanée\",\n\t\"DESCRIPTION_FONT_SMOOTHING\": \"Mac uniquement : « subpixel-antialiased » pour activer l’anticrénelage (lissage) des sous-pixels ou « antialiased » pour l’anticrénelage des niveaux de gris\",\n\t\"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\": \"faux pour désactiver l’ouverture du fichier de préférences en mode fractionné\",\n\t\"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\": \"faux pour ouvrir le fichier de préférences de l’utilisateur dans le volet gauche/supérieur\",\n\t\"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\": \"vrai pour réduire les volets une fois que le dernier fichier du volet est fermé à l’aide du bouton situé dans l’en-tête\",\n\t\"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\": \"Permet de choisir quand afficher les boutons Fermer et Transférer la vue dans l’en-tête.\",\n\t\"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\": \"/*\\n * Fichier en lecture seule contenant les préférences prises\\n * en charge par {APP_NAME}.\\n * Utilisez ce fichier en référence pour modifier\\n * votre fichier de préférences « brackets.json » ouvert dans l’autre volet.\\n * Pour savoir comment utiliser les préférences dans\\n * {APP_NAME}, reportez-vous à la page https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences.\\n */\",\n\t\"DEFAULT_PREFERENCES_JSON_DEFAULT\": \"Par défaut\",\n\t\"DESCRIPTION_PURE_CODING_SURFACE\": \"vrai pour activer le mode code seul et masquer tous les autres éléments de l’interface utilisateur dans {APP_NAME}\",\n\t\"DESCRIPTION_INDENT_LINE_COMMENT\": \"vrai pour activer la mise en retrait des commentaires sur une ligne\",\n\t\"DESCRIPTION_RECENT_FILES_NAV\": \"Activer/désactiver la navigation dans les fichiers récents\",\n\t\"DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\": \"Port sur lequel s’exécute le serveur WebSocket pour le mode Aperçu en direct\",\n\t\"DESCRIPTION_LIVE_DEV_HIGHLIGHT_SETTINGS\": \"Paramètres de surbrillance de l'Aperçu en direct\",\n\t\"DESCRIPTION_LIVEDEV_ENABLE_REVERSE_INSPECT\": \"faux pour désactiver l’inspection inverse de l’Aperçu en direct\",\n    \n    // Strings for Auto Update\n\t\"DOWNLOAD_FAILED\": \"Échec du téléchargement.\",\n\t\"DOWNLOAD_COMPLETE\": \"Téléchargement terminé.\",\n\t\"UPDATE_SUCCESSFUL\": \"Mise à jour effectuée.\",\n\t\"UPDATE_FAILED\": \"Échec de la mise à jour.\",\n\t\"VALIDATION_FAILED\": \"Échec de la validation.\",\n\t\"INITIALISATION_FAILED\": \"Échec de l’initialisation.\",\n\t\"CLEANUP_FAILED\": \"Échec du nettoyage.\",\n\t\"WARNING_TYPE\": \"Avertissement !\",\n\t\"CLICK_RESTART_TO_UPDATE\": \"Cliquez sur Redémarrer pour mettre à jour Brackets.\",\n\t\"UPDATE_ON_NEXT_LAUNCH\": \"La mise à jour sera appliquée au prochain lancement de l’application.\",\n\t\"GO_TO_SITE\": \"Rendez-vous sur <a href=\\\"http://brackets.io/\\\"> brackets.io </a> pour réessayer.\",\n\t\"INTERNET_UNAVAILABLE\": \"Aucune connexion Internet disponible.\",\n\t\"UPDATEDIR_READ_FAILED\": \"Impossible de lire le répertoire de mise à jour.\",\n\t\"UPDATEDIR_CLEAN_FAILED\": \"Impossible de nettoyer le répertoire de mise à jour.\",\n\t\"INITIAL_DOWNLOAD\": \"Téléchargement de la mise à jour...\",\n\t\"RETRY_DOWNLOAD\": \"Échec du téléchargement. Nouvelle tentative... \",\n\t\"VALIDATING_INSTALLER\": \"Téléchargement terminé. Validation du programme d’installation...\",\n\t\"CHECKSUM_DID_NOT_MATCH\": \"La somme de contrôle ne correspond pas.\",\n\t\"INSTALLER_NOT_FOUND\": \"Programme d’installation non trouvé.\",\n\t\"DOWNLOAD_ERROR\": \"Erreur lors du téléchargement.\",\n\t\"NETWORK_SLOW_OR_DISCONNECTED\": \"Le réseau est déconnecté ou trop lent.\",\n\t\"RESTART_BUTTON\": \"Recommencer\",\n\t\"LATER_BUTTON\": \"Plus tard\",\n\t\"DESCRIPTION_AUTO_UPDATE\": \"Activer/désactiver la mise à jour automatique de Brackets\",\n\t\"AUTOUPDATE_ERROR\": \"Erreur !\",\n\t\"AUTOUPDATE_IN_PROGRESS\": \"Une mise à jour est déjà en cours.\",\n\n\t\"NUMBER_WITH_PERCENTAGE\": \"{0} %\",\n    // Strings for Related Files\n\t\"CMD_FIND_RELATED_FILES\": \"Trouver les fichiers associés\",\n\n    ///String for Php Tooling Extensions\n\t\"PHP_VERSION_INVALID\": \"Erreur lors de l’analyse de la version de PHP. Veuillez vérifier la sortie de la commande « php –version ».\",\n\t\"PHP_UNSUPPORTED_VERSION\": \"Installez le moteur d’exécution de PHP 7 pour activer les outils correspondants comme Conseils de code, Conseils de paramètres, Accéder à la définition, etc. Version trouvée : {0}\",\n\t\"PHP_EXECUTABLE_NOT_FOUND\": \"Moteur d’exécution PHP introuvable. Installez le moteur d’exécution de PHP 7 et mettez à jour « executablePath » dans les préférences PHP. Cela permettra l’activation des outils liés à PHP comme Conseils de code, Conseils de paramètres ou encore Accéder à la définition.\",\n\t\"PHP_PROCESS_SPAWN_ERROR\": \"Code d’erreur {0} rencontré lors du démarrage du processus PHP.\",\n\t\"PHP_SERVER_ERROR_TITLE\": \"Erreur\",\n\t\"PHP_SERVER_MEMORY_LIMIT_INVALID\": \"La limite de mémoire que vous avez fournie n’est pas valide. Veuillez corriger la valeur indiquée dans les préférences PHP.\",\n\t\"DESCRIPTION_PHP_TOOLING_CONFIGURATION\": \"Paramètres de configuration par défaut des outils PHP\",\n\t\"OPEN_PREFERENNCES\": \"Ouvrir les préférences\",\n\n    //Strings for LanguageTools Preferences\n\t\"LANGUAGE_TOOLS_PREFERENCES\": \"Préférences pour les outils linguistiques\",\n\n\t\"FIND_ALL_REFERENCES\": \"Rechercher toutes les références\",\n\t\"REFERENCES_IN_FILES\": \"références\",\n\t\"REFERENCE_IN_FILES\": \"référence\",\n\t\"REFERENCES_NO_RESULTS\": \"Références non disponibles pour la position actuelle du curseur\",\n\n\t\"CMD_FIND_DOCUMENT_SYMBOLS\": \"Rechercher des symboles de document\",\n\t\"CMD_FIND_PROJECT_SYMBOLS\": \"Rechercher des symboles de projet\",\n\n   // Remote debugging enabled\n\t\"REMOTE_DEBUGGING_ENABLED\": \"Débogage à distance activé sur localhost:\",\n\n   // Remote debugging port argument is invalid\n\t\"REMOTE_DEBUGGING_PORT_INVALID\": \"Impossible d’activer le débogage à distance sur le port {0}. Les numéros de port doivent être compris entre {1} et {2}.\",\n    \n    //Associate File Type to External App\n\t\"DESCRIPTION_EXTERNAL_APPLICATION_ASSOCIATE\": \"Mappages d’extension de fichier avec des applications externes. Syntaxe : \\\"<type_fichier>\\\": \\\"<default|NomApplication|CheminApplication>\\\", Utiliser « default » pour ouvrir les fichiers dans l’application par défaut du système pour le type de fichier.\",\n\n\t\"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_TITLE\": \"Ouvrez les fichiers graphiques dans des éditeurs externes.\",\n\t\"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_MSG\": \"Votre dossier actuel comporte des types de fichier graphique non pris en charge par {APP_NAME}.<br/>Vous pouvez à présent associer des types de fichiers spécifiques avec des éditeurs externes. Une fois l’association établie, vous pouvez ouvrir des fichiers graphiques tels que .xd, .psd, .jpg, .png, .ai et .svg, dans leur application par défaut en double-cliquant sur ces fichiers dans l’arborescence de fichiers.<br/><br/>Cliquez sur le bouton OK pour associer les types de fichier graphique avec leur application par défaut respective.\",\n\t\"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_CNF_MSG\": \"Les types de fichiers suivants ont été associés à des applications par défaut.<br/>{0} Vous pouvez modifier votre préférence concernant l’éventuel(le) suppression/ajout d’associations de type de fichier dans brackets.json via le menu Déboguer->Ouvrir le fichier des préférences.\"\n\n\n});\n"
  },
  {
    "path": "src/nls/fr/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"fr/Premiers pas\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_fr/\",\n    \"MDN_DOCS_LICENSE\" : \"http://creativecommons.org/licenses/by-sa/2.5/deed.fr\"\n});\n"
  },
  {
    "path": "src/nls/gl/strings.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(erro {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Non se puido atopar o arquivo.\",\n    \"NOT_READABLE_ERR\"                  : \"Non se puido ler o arquivo.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"O directorio de destino non se pode modificar.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Os permisos non permiten facer modificacións.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"O arquivo foi modificado fóra de {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} actualmente só soporta arquivos codificados como UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"O arquivo xa existe.\",\n    \"FILE\"                              : \"arquivo\",\n    \"FILE_TITLE\"                        : \"Arquivo\",\n    \"DIRECTORY\"                         : \"directorio\",\n    \"DIRECTORY_TITLE\"                   : \"Directorio\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"nomes de directorios\",\n    \"FILENAMES_LEDE\"                    : \"nomes de arquivos\",\n    \"FILENAME\"                          : \"Nome de arquivo\",\n    \"DIRECTORY_NAME\"                    : \"Nome de directorio\",\n\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Erro abrindo o proxecto\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Houbo un erro ó amosar o aviso de apertura de arquivo. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Houbo un erro ó intentar abrir o directorio <span class='dialog-filename'>{0}</span>. (erro {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Houbo un erro ó ler os contidos do directorio <span class='dialog-filename'>{0}</span>. (erro {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Erro abrindo arquivo\",\n    \"ERROR_OPENING_FILE\"                : \"Houbo un erro ó intentar abrir o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Houbo un erro ó intentar abrir os seguintes arquivos:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Erro recargando cambios dende disco\",\n    \"ERROR_RELOADING_FILE\"              : \"Houbo un erro ó intentar recargar o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Erro gardando arquivo\",\n    \"ERROR_SAVING_FILE\"                 : \"Houbo un erro ó intentar gardar o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Erro renomeando arquivo\",\n    \"ERROR_RENAMING_FILE\"               : \"Houbo un erro ó intentar renomear o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Erro eliminando arquivo\",\n    \"ERROR_DELETING_FILE\"               : \"Houbo un erro ó intentar eliminar o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"{0} inválido\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Os {0} non poden utilizar ningunha palabra reservada polo sistema, rematar con puntos (.) ou utilizar calquera dos seguintes caracteres: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Xa existe un arquivo ou directorio co nome <span class='dialog-filename'>{0}</span>.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Erro creando {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Houbo un erro ó intentar crear o {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Non se pode abrir o cartafol ó mesmo tempo que hai abertos outros arquivos.\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Erro lendo os axustes\",\n    \"ERROR_PREFS_CORRUPT\"               : \"O arquivo de axustes non ten o formato JSON válido. O arquivo abrirase para que poida correxir o formato. Despois deberá reiniciar {APP_NAME} para que os cambios surtan efecto.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Vaia... parece que {APP_NAME} aínda non funciona en navegadores.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} está desenvolvido en HTML, pero por agora funciona como unha aplicación de escritorio para que poidas editar arquivos en local. Por favor, utiliza a aplicación do repositorio <b>github.com/adobe/brackets-shell</b> para executar {APP_NAME}.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Erro indexando arquivos\",\n    \"ERROR_MAX_FILES\"                   : \"Este proxecto contén máis de 30.000 arquivos. Funcións que operan sobre múltiples arquivos poden estar deshabilitadas ou funcionar igual que si o proxecto estivese baleiro. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Ler máis acerca de cómo traballar con proxectos grandes</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Erro iniciando navegador\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"No se puido atopar o navegador Google Chrome. Por favor, asegúrate de que está instalado correctamente.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Houbo un erro ó iniciar o navegador. (erro {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Erro na Vista Previa en Vivo\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Conectando co navegador\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Para poder iniciar o modo de Vista Previa en Vivo, Chrome debe ser iniciado habilitando a depuración remota.<br /><br />¿Queres reiniciar Chrome e habilitar a depuración remota?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Non se puido cargar a páxina para Vista Previa en Vivo\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Abre un arquivo HTML ou asegúrate de que hai un index.html no teu proxecto para poder iniciar o modo de Vista Previa en Vivo.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Necesitas especificar unha URL base neste proxecto para poder iniciar Vista Previa en Vivo con arquivos de servidor.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Erro iniciando o servidor HTTP para Vista Previa en Vivo. Volve a intentalo, por favor.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"¡Benvido á Vista Previa en Vivo!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Vista Previa en Vivo conecta {APP_NAME} co teu navegador. Lanza unha vista previa do teu arquivo HTML no navegador e actualízaa a medida que modificas o teu código.<br /><br />Nesta versión preliminar de {APP_NAME}, Desenvolvemento en Vivo só funciona para cambios de <strong>arquivos CSS ou HTML</strong> e únicamente con <strong>Google Chrome</strong>. Os cambios nos arquivos Javascript son recargados automáticamente cando se gardan.<br /><br />(Non volverás a ver ésta mensaxe.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Para máis información, consulta <a href='{0}' title='{0}'>Resolución de Problemas de conexión en Vista Previa en Vivo</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Vista Previa en Vivo\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Vista Previa en Vivo: Conectando\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Vista Previa en Vivo: Inicializando\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Rematar Vista Previa en Vivo\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Vista Previa en Vivo (garda o arquivo para actualizar)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Vista Previa en Vivo (non se está actualizando debido a un erro de sintaxis)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Vista Previa en Vivo detiuse porque abríronse as ferramentas de desenvolvemento\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Vista Previa en Vivo detiuse porque cerrouse a páxina no navegador\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Vista Previa en Vivo detiuse porque accediuse a unha páxina que non é parte do proxecto actual\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Vista Previa en Vivo detiuse por motivos descoñecidos ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Gardar cambios\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"¿Queres gardar os cambios existentes no documento <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"¿Queres gardar os teus cambios nos seguintes documentos?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Cambios externos\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Confirmar eliminación\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"¿Está seguro de que desexa eliminar o directorio <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Arquivo eliminado\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> foi modificado no disco.<br /><br />¿Desexa gardar o arquivo e sobrescribir eses cambios?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> foi modificado, pero tamén ten cambios en {APP_NAME}.<br /><br />¿Qué versión queres conservar?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> foi eliminado, pero ten cambios sen gardar en {APP_NAME}.<br /><br />¿Qieres conservar os teus cambios?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Aceptar\",\n    \"OK\"                                : \"Aceptar\",\n    \"CANCEL\"                            : \"Cancelar\",\n    \"DONT_SAVE\"                         : \"Non gardar\",\n    \"SAVE\"                              : \"Gardar\",\n    \"DELETE\"                            : \"Eliminar\",\n    \"SAVE_AS\"                           : \"Gardar como\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Sobrescribir\",\n    \"BUTTON_YES\"                        : \"Sí\",\n    \"BUTTON_NO\"                         : \"Non\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} de {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Non hai resultados\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Atopado\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Reemplazar con\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Todo\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Reemplazar\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Reemplazar\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Seguinte coincidencia\",\n    \"BUTTON_PREV_HINT\"                  : \"Anterior coincidencia\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Sensible a maiúsculas\",\n    \"BUTTON_REGEXP_HINT\"                : \"Expresión regular\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Reemplazar sen volta atrás\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Debido a que máis de {0} arquivos precisan ser cambiados, {APP_NAME} modificará arquivos non abertos.<br />Non poderás desfacer estes cambios.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Reemplazar sen volta atrás\",\n\n    \"OPEN_FILE\"                         : \"Abrir arquivo\",\n    \"SAVE_FILE_AS\"                      : \"Gardar arquivo\",\n    \"CHOOSE_FOLDER\"                     : \"Elixe unha carpeta\",\n\n    \"RELEASE_NOTES\"                     : \"Notas sobre a versión\",\n    \"NO_UPDATE_TITLE\"                   : \"¡Estás actualizado!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Estás utilizando a última versión de {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Reemprazar\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"con\",\n    \"FIND_TITLE_LABEL\"                  : \"Atopado\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} en {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"en <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"no proxecto\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"O filtro exclúe tódolos arquivos {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"arquivo\",\n    \"FIND_IN_FILES_FILES\"               : \"arquivos\",\n    \"FIND_IN_FILES_MATCH\"               : \"coincidencia\",\n    \"FIND_IN_FILES_MATCHES\"             : \"coincidencias\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Máis de \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",  // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd click para expandir/colapsar todo\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Reemprazar Erros\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Os seguintes arquivos non se modificaron porque se cambiaron despois da búsqueda ou non poden ser modificados.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Erro obtendo información sobre actualizacións\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Houbo un problema ó obter a información sobre as últimas actualizacións dende o servidor. Por favor, asegúrate de estar conectado a internet e volve a intentalo.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Novo conxunto de filtros\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Non excluir arquivos\",\n    \"NO_FILE_FILTER\"                    : \"Non hai arquivos excluidos\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Excluir {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Editar\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Editar conxunto de filtros\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Excluir arquivos e carpetas que coincidan con algunha das seguintes cadeas / subcadeas ou <a href='{0}' title='{0}'>comodines</a>. Ingrese unha cadea por liña.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nomear este conxunto de filtros (opcional)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"e {0} máis\",\n    \"FILTER_COUNTING_FILES\"             : \"Contando arquivos\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Permite {0} de {1} arquivos {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Permite tódolos {0} arquivos {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"A Edición Rápida non está dispoñible para a posición actual do cursor\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Edición Rápida para CSS: ubique o cursor sobre o nome de unha clase\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Edición Rápida para CSS: atributo de clase incompleto\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Edición Rápida para CSS: atributo de identificación incompleto\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Edición Rápida para CSS: ubique o cursor sobre unha etiqueta, clase ou id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Edición Rápida para Funcións de Temporización de CSS: sintaxis inválida\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Edición Rápida para JS: ubique o cursor sobre o nome de unha función\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"A Documentación Rápida non está dispoñible para a posición actual do cursor\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Cargando\\u2026\",\n    \"UNTITLED\"          : \"Sen título\",\n    \"WORKING_FILES\"     : \"Área de traballo\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Arriba\",\n    \"BOTTOM\"            : \"Abaixo\",\n    \"LEFT\"              : \"Esquerda\",\n    \"RIGHT\"             : \"Dereita\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Non Dividir\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"División Vertical\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"División Horizontal\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Dividir o editor vertical ou horizontalmente\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configurar espacio de traballo\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Xa está aberto\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"O arquivo xa está aberto noutro panel. {APP_NAME} pronto soportará abrir o mesmo arquivo noutro panel. Ata entón, o arquivo amosarase no panel que xa está aberto en.<br /><br />(Só verás esta mensaxe unha vez.)\",\n\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"May\",\n    \"KEYBOARD_SPACE\"  : \"Espacio\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Liña {0}, Columna {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} columna seleccionada\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} columnas seleccionadas\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} liña seleccionada\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} liñas seleccionadas\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} seleccións\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Fai click para usar espacios na sangría\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Fai click para usar tabulacións na sangría\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Fai click para cambiar o número de espacios usados na sangría\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Fai click para cambiar o ancho das tabulacións\",\n    \"STATUSBAR_SPACES\"                      : \"Espacios:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tamaño de tabulador:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} liña\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} liñas\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extensións deshabilitadas\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"SOB\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Fai click para intercambiar entre o modo insertar (INS) e o modo sobrescribir (SOB)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Fai click para cambiar o tipo de arquivo\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Fai click para amosar/ocultar o panel de reportes.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(por defecto)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Marcar como predeterminado para os arquivos .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"Problemas de {0}\",\n    \"SINGLE_ERROR\"                          : \"1 problema de {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} problemas de {0}\",\n    \"NO_ERRORS\"                             : \"Non se atoparon problemas de {0} - ¡Bo traballo!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Non se atoparon problemas - ¡Bo traballo!\",\n    \"LINT_DISABLED\"                         : \"A inspección de código está deshabilitada\",\n    \"NO_LINT_AVAILABLE\"                     : \"Non hai inspección de código dispoñible para {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Non hai nada para inspeccionar\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} esgotou o tempo despois de esperar {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} rematou con erro: {1}\",\n\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Arquivo\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Novo\",\n    \"CMD_FILE_NEW\"                        : \"Novo arquivo\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Novo cartafol\",\n    \"CMD_FILE_OPEN\"                       : \"Abrir\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Añadir ó espacio de traballo\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Abrir arquivos caídos\",\n    \"CMD_OPEN_FOLDER\"                     : \"Abrir cartafol\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Pechar\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Pechar todo\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Pechar lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Pechar outros\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Pechar outros por encima\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Pechar outros por debaixo\",\n    \"CMD_FILE_SAVE\"                       : \"Gardar\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Gardar todo\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Gardar como\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Vista Previa en Vivo\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Forzar Recargar a Vista Previa en Vivo\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Configuración do proxecto\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Renomear\",\n    \"CMD_FILE_DELETE\"                     : \"Eliminar\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instalar extensión\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Xestionar extensións\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Actualizar árbol de arquivos\",\n    \"CMD_QUIT\"                            : \"Saír\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Saír\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edición\",\n    \"CMD_UNDO\"                            : \"Desfacer\",\n    \"CMD_REDO\"                            : \"Refacer\",\n    \"CMD_CUT\"                             : \"Cortar\",\n    \"CMD_COPY\"                            : \"Copiar\",\n    \"CMD_PASTE\"                           : \"Pegar\",\n    \"CMD_SELECT_ALL\"                      : \"Seleccionar todo\",\n    \"CMD_SELECT_LINE\"                     : \"Seleccionar liña\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Dividir selección en liñas\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Engadir cursor á seguinte líña\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Engadir cursor á liña anterior\",\n    \"CMD_INDENT\"                          : \"Aumentar sangría\",\n    \"CMD_UNINDENT\"                        : \"Diminuír sangría\",\n    \"CMD_DUPLICATE\"                       : \"Duplicar\",\n    \"CMD_DELETE_LINES\"                    : \"Eliminar liña\",\n    \"CMD_COMMENT\"                         : \"Comentar/Descomentar liña\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Comentar/Descomentar bloque\",\n    \"CMD_LINE_UP\"                         : \"Subir liña\",\n    \"CMD_LINE_DOWN\"                       : \"Baixar liña\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Crear liña arriba\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Crear liña abaixo\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Completar paréntesis automáticamente\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Amosar suxerencias de código\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Buscar\",\n    \"CMD_FIND\"                            : \"Buscar\",\n    \"CMD_FIND_NEXT\"                       : \"Buscar seguinte\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Buscar anterior\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Buscar todo e seleccionar\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Agregar a seguinte coincidencia á selección\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Omitir e agregar a seguinte coincidencia\",\n    \"CMD_FIND_IN_FILES\"                   : \"Buscar en arquivos\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Buscar en\\u2026\",\n    \"CMD_REPLACE\"                         : \"Reemplazar\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Reemplazar en Arquivos\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Reemplazar en\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Ver\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Ocultar menú lateral\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Amosar menú lateral\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Aumentar tamaño de fuente\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Diminuír tamaño de fuente\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restablecer tamaño de fuente\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Desplazar cara arriba\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Desplazar cara abaixo\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Amosar números de liña\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Resaltar liña actual\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Habilitar axuste de liña\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Resaltado en Vista Previa en Vivo\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Inspeccionar o código ó gardar\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Ordenar por Añadido\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Ordenar por Nome\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Ordenar por Tipo\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Ordenación automática\",\n    \"CMD_THEMES\"                          : \"Temas\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navegación\",\n    \"CMD_QUICK_OPEN\"                      : \"Apertura rápida\",\n    \"CMD_GOTO_LINE\"                       : \"Ir á liña\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Búsqueda rápida de definición\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Ir ó primeiro Erro/Advertencia\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Edición rápida\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Documentación rápida\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Coincidencia anterior\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Coincidencia seguinte\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Nova norma\",\n    \"CMD_NEXT_DOC\"                        : \"Documento seguinte\",\n    \"CMD_PREV_DOC\"                        : \"Documento anterior\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Amosar na árbore de directorios\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Amosar no Explorador\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Amosar en Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Amosar no Sistema Operativo\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Axuda\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Buscar actualizacións\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Cómo utilizar {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Soporte de {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Suxerir unha mellora\",\n    \"CMD_RELEASE_NOTES\"                   : \"Notas da versión\",\n    \"CMD_GET_INVOLVED\"                    : \"Involúcrate\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Abrir cartafol de extensións\",\n    \"CMD_HOMEPAGE\"                        : \"Páxina principal de {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} en Twitter\",\n    \"CMD_ABOUT\"                           : \"Acerca de {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Abrir arquivo de axustes\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"versión experimental\",\n    \"DEVELOPMENT_BUILD\"                    : \"versión de desenvolvemento\",\n    \"RELOAD_FROM_DISK\"                     : \"Volver a cargar dende disco\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Conservar os cambios do editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Pechar (Non gardar)\",\n    \"RELAUNCH_CHROME\"                      : \"Reiniciar Chrome\",\n    \"ABOUT\"                                : \"Acerca de\\u2026\",\n    \"CLOSE\"                                : \"Pechar\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Versión {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"construír marca de tempo: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Os avisos, termos e condicións pertencentes a software de terceiros atópanse en <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> e inclúense aquí como referencia.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Podes atopar a documentación e código fonte en <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Feito con \\u2764 e JavaScript por:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Moita xente (pero agora mesmo estamos tendo problemas para cargar eses datos).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"O contido de MDN Docs e o logo de MDN están dispoñibles baixo unha Licencia de Recoñecemento de Creative Commons, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"¡Hai unha nova versión de {APP_NAME} dispoñible! Fai click aquí para máis detalles.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Actualización dispoñible\",\n    \"UPDATE_MESSAGE\"                       : \"¡Hai unha nova versión de {APP_NAME} dispoñible! Éstas son algunas das novas características:\",\n    \"GET_IT_NOW\"                           : \"¡Conségueo agora!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Configuración do proxecto para: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL base para Vista Previa en Vivo\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"(deixa en branco para urls de tipo \\\"file\\\")\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Vista Previa en Vivo non soporta o protocolo {0}. Por favor, utiliza http: ou https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"A URL base non pode conter parámetros de búsqueda como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"A URL base non pode conter hashes como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Os caracteres especiais como '{0}' deben codificarse en formato %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Erro descoñecido analizando a URL base\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Selecciona un arquivo mentres esta vista está activa</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Tema actual\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Usar scrollbars do tema\",\n    \"FONT_SIZE\"                            : \"Tamaño de letra\",\n    \"FONT_FAMILY\"                          : \"Tipo de letra\",\n    \"THEMES_SETTINGS\"                      : \"Preferencias dos temas\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Nova regra\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instalar\",\n    \"UPDATE\"                               : \"Actualizar\",\n    \"REMOVE\"                               : \"Eliminar\",\n    \"OVERWRITE\"                            : \"Sobrescribir\",\n    \"CANT_REMOVE_DEV\"                      : \"As extensións na carpeta \\\"dev\\\" débense eliminar manualmente.\",\n    \"CANT_UPDATE\"                          : \"A actualización non é compatible con ésta versión de {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"As extensións na carpeta \\\"dev\\\" non se poden actualizar automáticamente.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instalar extensión\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Actualizar extensión\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL da extensión\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL do arquivo zip da extensión ou do repositorio de Github\",\n    \"INSTALLING_FROM\"                      : \"Instalando extensión dende {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"¡Instalación completada!\",\n    \"INSTALL_FAILED\"                       : \"Erro na instalación.\",\n    \"CANCELING_INSTALL\"                    : \"Cancelando\\u2026\",\n    \"CANCELING_HUNG\"                       : \"A instalación está tardando demasiado; cancelando. Pode que se producira un erro interno.\",\n    \"INSTALL_CANCELED\"                     : \"Instalación cancelada.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Ver descripción completa\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Ver descripción corta\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"O contido descargado non é un arquivo zip válido.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"O arquivo package.json non é válido (error: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"O arquivo package.json non especifica un nome de paquete.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} non é un nome de paquete válido.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"O arquivo package.json non especifica a versión do paquete.\",\n    \"INVALID_VERSION_NUMBER\"               : \"O número de paquete da versión ({0}) non é válido.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"O código de compatibilidade de {APP_NAME} {{0}} non é válido.\",\n    \"DISALLOWED_WORDS\"                     : \"As palabras {{1}} non están permitidas no campo {{0}}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"A extensión non é compatible con esta versión de {APP_NAME}. Está no cartafol de extensións deshabilitadas.\",\n    \"MISSING_MAIN\"                         : \"O paquete non contén o arquivo main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Instalar este paquete sobrescribirá unha extensión instalada previamente. ¿Deseas sobrescribir a antiga extensión?\",\n    \"EXTENSION_SAME_VERSION\"               : \"A versión de este paquete é a misma que a instalada actualmente. ¿Desexas sobrescribir a instalación actual?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"A versión {0} de este paquete é máis antiga que a instalada actualmente ({1}). ¿Desexas sobrescribir a instalación actual?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Erro interno: o ID de descarga xa está sendo utilizado.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Non se pode conectar co servidor.\",\n    \"BAD_HTTP_STATUS\"                      : \"Arquivo non atopado no servidor (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Non se puido gardar a descarga en un arquivo temporal.\",\n    \"ERROR_LOADING\"                        : \"A extensión atopou un erro ó arrancar.\",\n    \"MALFORMED_URL\"                        : \"A URL non é válida. Por favor, comproba que as escribiches correctamente.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"A URL ten que ser unha dirección http ou https.\",\n    \"UNKNOWN_ERROR\"                        : \"Erro interno descoñecido.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Xestor de extensións\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Non se puido acceder o rexistro de extensións. Volve a intentalo máis tarde, por favor.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Arrastra .zip aquí ou\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Solta .zip para instalar\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"A Instalación/Actualizacións foi abortada polos seguintes erros:\",\n    \"INSTALL_FROM_URL\"                     : \"Instalar dende URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validando\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Data\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Esta extensión necesita unha versión máis actualizada de {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Nestes momentos esta extensión só funciona con versións anteriores de {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"A versión {0} de esta extensión precisa unha versión superior de {APP_NAME}. Podes instalar a versión anterior {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"A versión {0} de esta extensión só funciona con versións anteriores de {APP_NAME}. Podes instalar a versión anterior {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Sen descripción\",\n    \"EXTENSION_MORE_INFO\"                  : \"Máis información...\",\n    \"EXTENSION_ERROR\"                      : \"Erro na extensión\",\n    \"EXTENSION_KEYWORDS\"                   : \"Palabras clave\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Traducido a {0} linguas, incluída a túa\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Traducido a {0} linguas\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Esta extensión foi traducida ás seguintes linguas: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Instalada\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"A actualización de esta extensión descargouse e instalarase despois de recargar {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Buscar\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Máis\",\n    \"BROWSE_EXTENSIONS\"                    : \"Explorar extensións\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Eliminar extensión\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Non se puido eliminar unha ou máis extensións: {{0}}. {APP_NAME} recargarase igualmente.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Actualizar extensión\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Non se puido actualizar unha ou máis extensións: {{0}}. {APP_NAME} recargarase igualmente.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Marcada para eliminar\",\n    \"UNDO_REMOVE\"                          : \"Desfacer\",\n    \"MARKED_FOR_UPDATE\"                    : \"Marcada para actualizar\",\n    \"UNDO_UPDATE\"                          : \"Desfacer\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Cambiar extensións\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Para actualizar ou eliminar as extensións marcadas, precisas recargar {APP_NAME}. Solicitarase confirmación para gardar os cambios pendentes.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Eliminar extensións e recargar\",\n    \"CHANGE_AND_RELOAD\"                    : \"Cambiar extensións e recargar\",\n    \"UPDATE_AND_RELOAD\"                    : \"Actualizar extensións e recargar\",\n    \"PROCESSING_EXTENSIONS\"                : \"Procesando os cambios nas extensións\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Non se puido eliminar a extensión {{0}} porque no se atopa instalada.\",\n    \"NO_EXTENSIONS\"                        : \"Aínda non hai ningunha extensión instalada.<br />Fai click na pestana Dispoñibles para comenzar.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Non hai extensións que coincidan coa túa busca.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"NOTA: Estas extensións poden provir de diferentes autores a {APP_NAME}. As extensións non son revisadas e teñen todos os privilexios locais. Ten coidado cando instales extensións de unha fonte descoñecida.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Instaladas\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Dispoñibles\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Temas\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Actualizacións\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Non hai coincidencias dispoñibles.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Non hai reglas CSS existentes que coincidan cua túa selección.<br> Fai click en \\\"Nova regra\\\" para crear unha.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Non hai follas de estilos no teu proxecto.<br>Crea unha para añadir regras CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"máis grande\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"píxeles\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Desenvolvemento\",\n    \"ERRORS\"                                    : \"Erros\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Amosar ferramentas para desenvolvedores\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Recargar con extensións\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Recargar sin extensións\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nova ventá de {APP_NAME}\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Cambiar idioma\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Executar tests\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Amosar información de rendemento\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Habilitar depuración de Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Amosar estado de Node en Consola\",\n    \"CMD_RESTART_NODE\"                          : \"Reiniciar Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Amosar erros na barra de estado\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Abrir código de Brackets\",\n\n    \"LANGUAGE_TITLE\"                            : \"Cambiar idioma\",\n    \"LANGUAGE_MESSAGE\"                          : \"Idioma:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Reiniciar {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Cancelar\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Idioma predeterminado\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tempo\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progresión\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Moven o punto seleccionado<br><kbd class='text'>Shift</kbd> Move de a dez unidades<br><kbd class='text'>Tab</kbd> Cambia o punto seleccionado\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Incrementa ou decrementa os pasos<br><kbd>←</kbd><kbd>→</kbd> 'Start' ou 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"O valor vello <code>{0}</code> non é válido, polo tanto, foi modificado a <code>{1}</code>. O documento será actualizado despois da primeira edición.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Color actual\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Color orixinal\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Formato RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Formato Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Formato HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Utilizado {1} vez)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Utilizado {1} veces)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Saltar á definición\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Amosar suxerencias de parámetros\",\n    \"NO_ARGUMENTS\"                              : \"<non hay parámetros>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problema de inferencia con un arquivo JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets atopouse con problemas procesando:<br><br>{0}<br><br>Este arquivo non volverá a ser procesado para as suxerencias de código e saltar á definición. Para reactivarlo, abre <code>.brackets.json</code> no seu proxecto e elimina o arquivo de jscodehints.detectedExclusions.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Vista rápida co cursor\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Proxectos recentes\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Máis\"\n});\n\n/* Last translated for a4e9a06605cfca5dff5ab5dbacfb1d97c604b6f0 */\n"
  },
  {
    "path": "src/nls/hr/strings.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(greška {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Nepostojeća datoteka.\",\n    \"NOT_READABLE_ERR\"                  : \"Datoteka ne može biti učitana.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Ciljana mapa ne može biti izmijenjena.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Trenutne ovlasti vam ne dozvoljavaju kreiranje izmjena.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Datoteka je bila izmjenjena izvan {APP_NAME}.\",\n    \"FILE_EXISTS_ERR\"                   : \"Datoteka ili mapa već postoji.\",\n    \"FILE\"                              : \"Datoteka\",\n    \"DIRECTORY\"                         : \"Direktorij\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Greška pri učitavanju projekta\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Došlo je do greške prilikom prikazivanja dijaloga za otvaranje datoteke. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Došlo je do greške prilikom pokušaja da se učita direktorij <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Došlo je do greške prilikom iščitavanja sadržaja direktorija <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Greška pri otvaranju datoteke\",\n    \"ERROR_OPENING_FILE\"                : \"Došlo je do greške prilikom pokušaja da se otvori datoteka <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Došlo je do greške prilikom pokušaja da se otvore sljedeće datoteke:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Greška pri ponovom učitavanju izmjena sa diska\",\n    \"ERROR_RELOADING_FILE\"              : \"Došlo je do greške prilikom pokušaja da se ponovo učita datoteka <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Greška pri spremanju datoteke\",\n    \"ERROR_SAVING_FILE\"                 : \"Došlo je do greške prilikom pokušaja da se sačuva datoteka <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Greška pri preimenovanju datoteke\",\n    \"ERROR_RENAMING_FILE\"               : \"Došlo je do greške prilikom pokušaja da se preimenuje datoteka <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Greška pri brisanju datoteke\",\n    \"ERROR_DELETING_FILE\"               : \"Došlo je do greške prilikom pokušaja da se obriše datoteka <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Ime {0} nije valjano\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Imena datoteka ne smiju sadržavati sljedeće znakove: {0} ili riječi rezervirane za sistem.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Greška pri kreiranju {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Došlo je do greške prilikom pokušaja da se kreira {0} <span class='dialog-filename'>{1}</span>. {2}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Greška prilikom učitavanja preferencija\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Vaša datoteka preferencije nije valjana u JSON. Datoteka će biti otvorena tako da možete ispraviti format. Da biste vidjeli promjene, ponovo pokrenite {APP_NAME}.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ups! {APP_NAME} još uvijek ne radi u pregledniku.\",\n    \"ERROR_IN_BROWSER\"                  : \"Aplikacija \\\"{APP_NAME}\\\" je napravljena pomoću HTML-a, ali trenutno radi kao \\\"desktop\\\" aplikacija pa je možete koristiti za izmjenu lokalnih datoteka. Molimo Vas koristite \\\"application shell\\\" na <b>github.com/adobe/brackets-shell</b> repozitorij za pokretanje \\\"{APP_NAME}\\\" aplikacije.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Greška prilikom indeksiranja datoteka\",\n    \"ERROR_MAX_FILES\"                   : \"Indeksiran je maksimalni broj datoteka. Akcije koje pretražuju datoteke u indeksu mogu pogrešno funkcionirati.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Greška prilikom pokretanja web preglednika\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Google Chrome preglednik nije pronađen. Molimo potvrdite da je instaliran.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Greška prilikom pokretanja web preglednika. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Greška u živom prikazivanju\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Povezivanje sa preglednikom\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Da bi se Prikaz Uživo povezao, potrebno je ponovo pokrenuti Chrome sa uključenim podešavanjima za remote debugging.<br /><br />Da li želite ponovo pokrenuti Chrome i omogućiti remote debugging?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Nije moguće učitati živi prikaz stranice\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Otvorite HTML datoteku ili budite sigurni da postoji index.html datoteka u vašem projektu kako bi se pokrenuo živi prikaz.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Za pokretanje prikaza uživo sa datotekom koja je na serveru, morate navesti osnovnu URL adresu za ovaj projekt.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Greška prilikom pokretanja HTTP servera za prikaz datoteka uživo. Pokušajte ponovo.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Dobro došli u Prikaz Uživo!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Prikaz uživo spaja {APP_NAME} sa vašim preglednikom. On pokreće prikaz vaše HTML datoteke u pregledniku, te potom trenutno ažurira prikaz, kako Vi mijenjate vaš kôd.<br /><br />U ovoj ranoj verziji aplikacije {APP_NAME}, Prikaz uživo radi samo sa <strong>Google Chrome</strong> preglednikom i ažurira prikaz dok mijenjate <strong>CSS ili HTML datoteke</strong>. Izmjene načinjene u JavaScript datotekama su automatski ponovo učitane kada ih spremite.<br /><br />(Ova poruka će biti prikazana samo jednom.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Za više informacija, pogledajte <a href='{0}' title='{0}'>Rješavanje grešaka u povezivanju prilikom Prikaza uživo.</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Prikaz uživo\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Prikaz uživo: Povezivanje\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Prikaz uživo: Inicijalizacija\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Napusti prikaz uživo\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Prikaz uživo (sačuvaj datoteku za osvježavanje)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Prikaz uživo (ne osvježava se zbog greške u sintaksi)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Prikaz uživo je otkazan jer su u pregledniku bili otvoreni razvojni alati\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Prikaz uživo je otkazan jer je stranica zatvorena u pregledniku\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Prikaz uživo je otkazan jer je preglednik otišao na stranicu koja nije dio trenutnog projekta.\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Prikaz uživo je otkazan iz nepoznatog razloga ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Sačuvaj promjene\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Želite li sačuvati izmjene koje ste napravili u dokumentu <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Želite li sačuvati izmjene sljedećih datoteka?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Vanjske izmjene\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Potvrdi brisanje\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Da li ste sigurni da želite obrisati mapu <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Datoteka obrisana\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> je bio izmjenjen na disku.<br /><br />Da li želite sačuvati datoteku i spremiti preko tih izmjena?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> je bila izmjenjena na disku, ali isto tako sadrži nesačuvane promjene u {APP_NAME}.<br /><br />Koju verziju želite sačuvati?\",\n    \"EXT_DELETED_MESSAGE\"               : \"Datoteka <span class='dialog-filename'>{0}</span> je izbrisana na disku, ali postoje njene nesačuvane promjene u {APP_NAME}.<br /><br />Želite li sačuvati te promjene?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Može\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Otkaži\",\n    \"DONT_SAVE\"                         : \"Nemoj sačuvati\",\n    \"SAVE\"                              : \"Sačuvaj\",\n    \"SAVE_AS\"                           : \"Sačuvaj kao\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Piši preko\",\n    \"DELETE\"                            : \"Izbriši\",\n    \"BUTTON_YES\"                        : \"Da\",\n    \"BUTTON_NO\"                         : \"Ne\",\n\n    // Find, Replace, Find in Files\n    \"FIND_NO_RESULTS\"                   : \"Nema rezultata\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Nađi\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Zamijeni sa\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Sve\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Zamijeni\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Sljedeće poklapanje\",\n    \"BUTTON_PREV_HINT\"                  : \"Prethodno poklapanje\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Poklapanje samo sa specificiranim/određenim velikim ili malim slovom\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regularni izraz\",\n\n    \"OPEN_FILE\"                         : \"Otvori datoteku\",\n    \"SAVE_FILE_AS\"                      : \"Sačuvaj datoteku\",\n    \"CHOOSE_FOLDER\"                     : \"Izaberi mapu\",\n\n    \"RELEASE_NOTES\"                     : \"Obavijesti o izmjenama\",\n    \"NO_UPDATE_TITLE\"                   : \"Imate aktualnu verziju!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Trenutno koristite aktualnu verziju aplikacije {APP_NAME}.\",\n\n    // Find in Files\n    \"FIND_IN_FILES_SCOPED\"              : \"u <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"u projektu\",\n    \"FIND_IN_FILES_FILE\"                : \"datoteci\",\n    \"FIND_IN_FILES_FILES\"               : \"datoteka\",\n    \"FIND_IN_FILES_MATCH\"               : \"poklapanje\",\n    \"FIND_IN_FILES_MATCHES\"             : \"poklapanja\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Preko \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n    // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd klikni da proširiš/skupiš sve\",\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Greška prilikom učitavanja informacija o novoj verziji\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Došlo je do problema prilikom preuzimanja posljednjih informacija o novoj verziji sa servera. Molimo provjerite da li ste povezani na internet i pokušajte ponovo\",\n\n    // File exclusion filters\n    \"NO_FILE_FILTER\"                    : \"Isključi datoteke\\u2026\",\n    \"EDIT_FILE_FILTER\"                  : \"Uredi\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Uređivački filter\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Isključi datoteke i direktorije koji se slažu sa ijednom od sljedećih nizova / podnizova riječi ili <a href='{0}' title='{0}'>globs</a>. Unesi svaki niz u novi red.\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"i {0} više\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Brzo uređivanje nije dostupno za trenutnu poziciju kursora\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Brzo CSS uređivanje: postavi kursor na pojedinačno ime klase\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Brzo CSS uređivanje: nepotpuno svojstvo klase\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Brzo CSS uređivanje: nepotpuno id svojstvo\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Brzo CSS uređivanje: postavi kursor na tag, klasu(class), ili id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Brzo CSS uređivanje vremenskog raspoređivanja: nevažeća sintaksa\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Brzo JS uređivanje: postavi kursor na ime funkcije\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Nema dostupnih brzih dokumenata za trenutnu poziciju kursora\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Učitavanje\\u2026\",\n    \"UNTITLED\"          : \"Neimenovan\",\n    \"WORKING_FILES\"     : \"Radne datoteke\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Vrh\",\n    \"BOTTOM\"            : \"Dno\",\n    \"LEFT\"              : \"Lijevo\",\n    \"RIGHT\"             : \"Desno\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Bez prepolavljanja\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Prepolovi okomito\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Prepolovi vodoravno\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Prepolovi editor okomito ili vodoravno\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Definiraj radni skup\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Već otvoreno\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Datoteka je već otvorena u drugom panelu. {APP_NAME} će uskoro podržavati otvaranje iste datoteke u više od jednog panela. Do tada, datoteka će biti prikazana u panelu u kojem je već otvorena.<br /><br />(Ovu ćeš poruku vidjeti samo jednom.)\",\n\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Red {0}, Stupac {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 izabran {0} stupac\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 izabrano {0} stupaca\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 izabrano {0} redova\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 izabrano {0} redova\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klikni za korištenje razmaka prilikom uvlačenja kôda\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klikni za korištenje tabova prilikom uvlačenja kôda*\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klikni da promjeniš broj razmaka prilikom uvlačenja kôda\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klikni da promjeniš širinu karaktera na kartici\",\n    \"STATUSBAR_SPACES\"                      : \"Razmaci:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Veličina kartice:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} red\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} redova\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extenzije onemogućene\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} grešaka\",\n    \"SINGLE_ERROR\"                          : \"1 {0} greška\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} grešaka\",\n    \"NO_ERRORS\"                             : \"Nema {0} nađenih grešaka - svaka čast!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Nema nađenih grešaka - bravo!\",\n    \"LINT_DISABLED\"                         : \"Detektiranje sumnjivog kôda isključeno\",\n    \"NO_LINT_AVAILABLE\"                     : \"Nijedan detektor sumnjivog kôda nije dostupan za {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Nije pronađen sumnjivi kôd\",\n\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Datoteka\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nova\",\n    \"CMD_FILE_NEW\"                        : \"Nova datoteka\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nova mapa\",\n    \"CMD_FILE_OPEN\"                       : \"Otvori\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Dodaj u radni set\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Otvori umetnune datoteke\",\n    \"CMD_OPEN_FOLDER\"                     : \"Otvori mapu\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Zatvori\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Zatvori sve\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Zatvori listu\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Zatvori druge\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Zatvori druge iznad\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Zatvori druge ispod\",\n    \"CMD_FILE_SAVE\"                       : \"Sačuvaj\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Sačuvaj sve\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Sačuvaj kao\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Prikaz uživo\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Omogući Experimentalni Prikaz Uživo\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Postavke projekta\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Preimenuj\",\n    \"CMD_FILE_DELETE\"                     : \"Obriši\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instaliraj ekstenziju\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Manager ekstenzija\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Osvježi stablo datoteka\",\n    \"CMD_QUIT\"                            : \"Prekini\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\" : \"Izađi\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Uredi\",\n    \"CMD_UNDO\"                            : \"Poništi\",\n    \"CMD_REDO\"                            : \"Ponovi\",\n    \"CMD_CUT\"                             : \"Izreži\",\n    \"CMD_COPY\"                            : \"Kopiraj\",\n    \"CMD_PASTE\"                           : \"Zalijepi\",\n    \"CMD_SELECT_ALL\"                      : \"Odaberi sve\",\n    \"CMD_SELECT_LINE\"                     : \"Odaberi red\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Razdvoji odabrano u redove\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Dodaj kursor u sljedeći red\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Dodaj kursor u prošli red\",\n    \"CMD_INDENT\"                          : \"Pomakni udesno\",\n    \"CMD_UNINDENT\"                        : \"Pomakni ulijevo\",\n    \"CMD_DUPLICATE\"                       : \"Udvostruči\",\n    \"CMD_DELETE_LINES\"                    : \"Obriši red\",\n    \"CMD_COMMENT\"                         : \"// Komentar reda\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Blok komentar /*..*/\",\n    \"CMD_LINE_UP\"                         : \"Pomakni red gore\",\n    \"CMD_LINE_DOWN\"                       : \"Pomakni red dolje\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Otvori red iznad\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Otvori red ispod\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Automatski zatvori zagrade\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Prikaži naznake (hintove) kôda\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Pronađi\",\n    \"CMD_FIND\"                            : \"Pronađi\",\n    \"CMD_FIND_IN_FILES\"                   : \"Pronađi u datotekama\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Pronađi u\\u2026\",\n    \"CMD_FIND_NEXT\"                       : \"Pronađi sljedeće\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Pronađi prethodno\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Pronađi sve i odaberi\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Dodaj sljedeće slaganje u odabir\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Preskoči i dodaj sljedeće slaganje\",\n    \"CMD_REPLACE\"                         : \"Zamijeni\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Zamijeni u datotekama\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Zamijeni u\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Prikaz\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Sakrij bočnu traku\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Prikaži bočnu traku\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Toggle bočnu traku\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Toggle panele\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Bez odvraćanja pažnje\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Povećaj veličinu fonta\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Smanji veličinu fonta\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Vrati veličinu fonta\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Pomakni red gore\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Pomakni red dolje\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Brojevi redova\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Označi aktivni red\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Prijelom teksta\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Obilježi prikaz uživo\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Prekontroliraj datoteke prilikom spremanja\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sortiraj po datumu\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sortiraj po imenu\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sortiraj po tipu\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatsko sortiranje\",\n    \"CMD_THEMES\"                          : \"Teme\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigacija\",\n    \"CMD_QUICK_OPEN\"                      : \"Brzo otvori\",\n    \"CMD_GOTO_LINE\"                       : \"Idi na red\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Brzo nađi definiciju\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Idi na prvu grešku/upozorenje\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Brzo izmjeni\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Brzi dokumenti\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Prethodno poklapanje\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Sljedeće poklapanje\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Novo pravilo\",\n    \"CMD_NEXT_DOC\"                        : \"Sljedeći dokument\",\n    \"CMD_PREV_DOC\"                        : \"Prethodni dokument\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Sljedeći dokument u listi\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Prethodni dokument u listi\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Prikaži u stablu datoteka\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Prikaži u pregledniku\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Prikaži u pretraživaču\",\n    \"CMD_SHOW_IN_OS\"                      : \"Prikaži u OS-u\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Pomoć\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Provjeri postoji li novija verzija\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Kako koristiti {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} Podrška (na engleskom)\",\n    \"CMD_SUGGEST\"                         : \"Predloži mogućnost / značajku\",\n    \"CMD_RELEASE_NOTES\"                   : \"Bilješke o trenutnoj verziji\",\n    \"CMD_GET_INVOLVED\"                    : \"Uključi se\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Prikaži direktorij sa ekstenzijama\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} na Twitteru\",\n    \"CMD_ABOUT\"                           : \"O programu {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Otvori preferencije\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Otvori svoje postavke tipki*\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimentalna verzija\",\n    \"DEVELOPMENT_BUILD\"                    : \"razvojna verzija\",\n    \"RELOAD_FROM_DISK\"                     : \"Ponovo učitaj sa diska\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Sačuvaj izmjene u Editoru\",\n    \"CLOSE_DONT_SAVE\"                      : \"Zatvori (Nemoj sačuvati)\",\n    \"RELAUNCH_CHROME\"                      : \"Ponovo pokreni Chrome\",\n    \"ABOUT\"                                : \"O aplikaciji\",\n    \"CLOSE\"                                : \"Zatvori\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Obavijesti, obaveze i uvjeti korištenja koji se odnose na third party softver su locirani na <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> i uključeni su ovdje putem linka.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentacija i izvorni kôd na <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Napravili sa \\u2764 i JavaScriptom:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Mnogo ljudi (ali trenutno imamo poteškoća sa učitavanjem tih podataka).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs i MDN graphical logo su zaštićeni pod Creative Commons Attribution licencom, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Dostupna je nova verzija aplikacije {APP_NAME}! Kliknite ovdje za detalje.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Novija verzija je dostupna\",\n    \"UPDATE_MESSAGE\"                       : \"Nova verzija aplikacije {APP_NAME} je dostupna. Ovo su neke od najnovijih izmjena:\",\n    \"GET_IT_NOW\"                           : \"Preuzmi sada!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Postavke projekta za: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Osnovna URL adresa za prikaz uživo\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Da biste koristili lokalni server unesite adresu (url) kao http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Prikaz uživo ne podržava protokol {0} &mdash; koristite http: or https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Osnovna URL adresa ne smije sadržavati parametre za traženje poput \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Osnovna URL adresa ne smije sadržavati hasheve (hashes) poput \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Posebni znakovi kao '{0}' moraju biti %-enkodirani.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Nepoznata greška prilikom parsiranja osnovne URL adrese\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Otvori datoteku dok je ovaj panel u fokusu</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Trenutna tema\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Koristi scrollbarove teme\",\n    \"FONT_SIZE\"                            : \"Veličina fonta\",\n    \"FONT_FAMILY\"                          : \"Obitelj fonta\",\n    \"THEMES_SETTINGS\"                      : \"Postavke teme\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Novo pravilo\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instaliraj\",\n    \"UPDATE\"                               : \"Ažuriraj\",\n    \"REMOVE\"                               : \"Ukloni\",\n    \"DISABLE\"                              : \"Onemogući\",\n    \"ENABLE\"                               : \"Omogući\",\n    \"OVERWRITE\"                            : \"Piši preko\",\n    \"CANT_REMOVE_DEV\"                      : \"Extenzije u \\\"dev\\\" mapi moraju biti ručno obrisane.\",\n    \"CANT_UPDATE\"                          : \"Novija verzija nije kompatibilna sa trenutnom verzijom aplikacije {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Extenzije u \\\"dev\\\" mapi ne mogu biti automatski ažurirane.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instaliraj ekstenziju\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Ažuriraj ekstenziju\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Link ekstenzije\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Link zip arhive ekstenzije ili GitHub repozitorija\",\n    \"INSTALLING_FROM\"                      : \"Instaliranje ekstenzije sa {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalacija je uspjela!\",\n    \"INSTALL_FAILED\"                       : \"Instalacija nije uspjela.\",\n    \"CANCELING_INSTALL\"                    : \"Otkazivanje\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Otkazivanje instalacije traje predugo. Vjerojatno je došlo do unutarnje greške.\",\n    \"INSTALL_CANCELED\"                     : \"Instalacija je otkazana.\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Preuzeti sadržaj nije valjana zip arhiva.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"package.json datoteka nije valjana (greška je bila: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"package.json datoteka nije navela ime paketa.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} nije valjano ime za paket.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"package.json datoteka nije navela verziju paketa.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Verzija paketa broj ({0}) nije valjana.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Niz o kompatibilnosti ({0}) aplikacije {APP_NAME} nije valjan.\",\n    \"DISALLOWED_WORDS\"                     : \"Riječi ({1}) nisu dozvoljene u polju {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Ova ekstenzija nije kompatibilna sa ovom verzijom aplikacije {APP_NAME}. Instalirana je u vašu mapu onemogućenih extenzija.\",\n    \"MISSING_MAIN\"                         : \"Paket nema main.js datoteku.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Instaliranjem ovog paketa ćete presnimiti prethodno instaliranu verziju. Da li želite presnimiti staru ekstenziju?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Verzija ovog paketa je ista kao verzija koja je trenutno instalirana. Da li želite presnimiti postojeću instalaciju?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Ovaj paket je verzija {0} što je starije od trenutno instalirane verzije ({1}). Želite li presnimiti postojeću instalaciju?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Unutarnja greška: ID preuzimanja je već u upotrebi.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Povezivanje sa serverom nije moguće.\",\n    \"BAD_HTTP_STATUS\"                      : \"Datoteka nije pronađena na serveru (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Nije moguće sačuvati preuzete podatke u privremenu datoteku.\",\n    \"ERROR_LOADING\"                        : \"Extenzija je naišla na grešku prilikom pokretanja.\",\n    \"MALFORMED_URL\"                        : \"URL nije valjan. Molimo provjerite da li ste ga unjeli točno.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL mora biti http ili https URL.\",\n    \"UNKNOWN_ERROR\"                        : \"Nepoznata unutarnja greška.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Manager ekstenzija\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Pristupanje registru ekstenzije nije moguće. Pokušajte kasnije.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Dovuci .zip ovdje ili\",\n    \"INSTALL_EXTENSION_DROP\"               : \"ispusti .zip da instaliraš\",\n    \"INSTALL_FROM_URL\"                     : \"Instaliraj sa URL linka\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Datum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Ova extenzija zahtjeva noviju verziju aplikacije {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Ova extenzija trenutno radi samo sa starijom verzijom aplikacije {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Verzija {0} ove ekstenzije traži noviju verziju aplikacije {APP_NAME}. Ali možete instalirati raniju verziju {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Verzija {0} ove ekstenzije radi samo sa starijim verzijama aplikacije {APP_NAME}. Ali možete instalirati raniju verziju {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Nema opisa\",\n    \"EXTENSION_MORE_INFO\"                  : \"Više informacija...\",\n    \"EXTENSION_ERROR\"                      : \"Greška u ekstenziji\",\n    \"EXTENSION_KEYWORDS\"                   : \"Ključne riječi\",\n    \"EXTENSION_INSTALLED\"                  : \"Instalirano\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Ova verzija ekstenzije već je preuzeta i bit će instalirana nakon što se {APP_NAME} ponovo učita.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Traži\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Više\",\n    \"BROWSE_EXTENSIONS\"                    : \"Pretraži ekstenzije\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Ukloni ekstenziju\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Nemoguće je ukloniti jednu ili više ekstenzija: {0}. {APP_NAME} će se svejedno ponovo učitati.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Obnovi ekstenziju\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Nije moguće obnoviti jednu ili više ekstenzija: {0}. {APP_NAME} će se svejedno ponovno učitati.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Označeno za uklanjanje\",\n    \"UNDO_REMOVE\"                          : \"Poništi\",\n    \"MARKED_FOR_UPDATE\"                    : \"Označeno za ažuriranje\",\n    \"UNDO_UPDATE\"                          : \"Poništi\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Promjeni ekstenzije\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Da biste obnovili ili uklonili označene ekstenzije, {APP_NAME} se treba ponovo učitati. Bit ćete zatraženi da sačuvate nesačuvane promjene.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Ukloni ekstenzije i ponovno učitaj\",\n    \"CHANGE_AND_RELOAD\"                    : \"Promjeni ekstenzije i ponovo učitaj\",\n    \"UPDATE_AND_RELOAD\"                    : \"Obnovi ekstenzije i ponovo učitaj\",\n    \"PROCESSING_EXTENSIONS\"                : \"Obrađivanje promjene ekstenzije\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Nemoguće je ukloniti ekstenziju {0} jer nije bila instalirana.\",\n    \"NO_EXTENSIONS\"                        : \"Trenutno nema instaliranih ekstenzija.<br>Kliknite iznad na karticu Dostupno da dodate extenziju.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nijedna ekstenzija se ne poklapa sa unesenim parametrima pretrage.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Budite oprezni prilikom instalacije ekstenzija koje potječu iz nepoznatih izvora.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Instalirano\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Dostupno\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Teme\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Obnovljene verzije\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Poklapanja nisu nađena.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Nema postojećih CSS pravila koji odgovaraju vašem odabiru.<br> Kliknite \\\"New Rule\\\" da biste ih stvorili.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Ne postoje stilovi u vašem projektu.<br>Stvorite jedan da dodate CSS pravila.\",\n\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\" : \"najveća\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"piksela\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Otklanjanje grešaka\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Prikaži razvojne alate\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Ponovo učitaj sa ekstenzijama\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Ponovo učitaj bez ekstenzija\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Novi {APP_NAME} Prozor\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Promjeni jezik\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Testiraj\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Prikaži podatke o performansama\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Uključi Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Zapiši u konzolu stanje Node-a\",\n    \"CMD_RESTART_NODE\"                          : \"Ponovo pokreni Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Prikaži greške u statusnoj traci\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Otvori Brackets izvor\",\n\n    \"LANGUAGE_TITLE\"                            : \"Promjeni Jezik\",\n    \"LANGUAGE_MESSAGE\"                          : \"Jezik:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Ponovo učitaj {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Otkaži\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Zadani jezik\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Vrijeme\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Napredak\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Pomakni odabranu točku<br><kbd class='text'>Shift</kbd> Pomakni za 10 jedinica<br><kbd class='text'>Tab</kbd> Zamijeni točke.\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Povećaj ili smanji korake<br><kbd>←</kbd><kbd>→</kbd> 'Početak' ili 'Kraj'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Stara vrijednost <code>{0}</code> nije valjana, tako da je prikazana funkcija promjenjena u <code>{1}</code>. Dokument će biti ažuriran kod prvog uređivanja.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Trenutna boja\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Originalna boja\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa format\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex format\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa format\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Korištena {1} put)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Korištena {1} puta)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Skoči na definiciju\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Pokaži naznake (hintove) parametara\",\n    \"NO_ARGUMENTS\"                              : \"<bez parametara>\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Brzi 'lebdeći' (hover) prikaz\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Nedavni projekti\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Pročitaj više\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Skupi sve\",\n    \"EXPAND_ALL\"                    : \"Proširi sve\",\n    \"COLLAPSE_CURRENT\"              : \"Skupi trenutno\",\n    \"EXPAND_CURRENT\"                : \"Proširi trenutno\"\n});\n\n/* Last translated for a57bd8888da0b44f382e591c64b394b065178277 */\n"
  },
  {
    "path": "src/nls/hr/urls.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"ADOBE_THIRD_PARTY\" : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\" : \"http://creativecommons.org/licenses/by-sa/2.5/deed.hr\"\n});\n"
  },
  {
    "path": "src/nls/hu/strings.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(hiba {0})\",\n    \"NOT_FOUND_ERR\"                     : \"A fájl nem található.\",\n    \"NOT_READABLE_ERR\"                  : \"A fájl nem olvasható.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"A célkönyvtárat nem lehet módosítani.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Nincs engedélyed a módosításhoz.\",\n    \"FILE_EXISTS_ERR\"                   : \"A fájl vagy a könyvtár már létezik.\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Hiba a projekt betöltése közben\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Hiba történt a \\\"fájl megnyitása\\\" ablak megjelenítésekor. (hiba {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Hiba történt a <span class='dialog-filename'>{0}</span> könyvtár megnyitása közben. (hiba {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Hiba történt a könyvtár tartalmának beolvasása közben. <span class='dialog-filename'>{0}</span>. (hiba {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Hiba történt a fájl megnyitása közben.\",\n    \"ERROR_OPENING_FILE\"                : \"Hiba történt a fájl megnyitása közben: <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Hiba történt a változások merevlemezről való újratöltése közben.\",\n    \"ERROR_RELOADING_FILE\"              : \"Hiba történt a fájl újratöltése közben: <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Hiba történt a fájl mentése közben\",\n    \"ERROR_SAVING_FILE\"                 : \"Hiba történt a fájl mentése közben: <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Hiba történt a fájl átnevezése közben\",\n    \"ERROR_RENAMING_FILE\"               : \"Hiba történt a fájl átnevezése közben: <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Hiba történt a fájl törlése közben\",\n    \"ERROR_DELETING_FILE\"               : \"Hiba történt a fájl törlése közben: <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Helytelen fájlnév\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"A fájl neve nem tartalmazhatja a következő karaktereket: {0} és foglalt rendszer neveket.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Hiba történt a fájl létrehozása közben.\",\n    \"ERROR_CREATING_FILE\"               : \"Hiba történt a fájl létrehozása közben: <span class='dialog-filename'>{0}</span>. {1}\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! A {APP_NAME} még nem fut böngészőben.\",\n    \"ERROR_IN_BROWSER\"                  : \"A {APP_NAME} HTML-ben épült, de jelenleg asztali alkalmazásként fut, ezért helyi fájlokat is tudsz vele szerkeszteni. Kérlek használd az alkalmazás \\\"burkot\\\" a {APP_NAME} futtatásához: <b>github.com/adobe/brackets-shell</b>.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Hiba a fájlok Indexszelése közben\",\n    \"ERROR_MAX_FILES\"                   : \"A maximális fájlszám indexelésre került. Folyamatok amelyek a fájlokat az indexben keresik esélyes hogy nem fognak rendesen működni.\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Hiba a böngésző megnyitása közben\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"A Google Chrome böngésző nem található. Bizonyosodj meg hogy telepítve van.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Hiba a böngésző megnyitása közben: (hiba {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Élő Előnézet hiba\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Csatlakozás a Böngészőhöz\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Az Élő Előnézet használatához muszály újraindítani a Chrome-ot a megfelelő beállításokkal.<br /><br />Szeretnéd most újraindítani a Chrome-ot ezekkel a beállításokkal?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Nem lehet betölteni az Élő Fejlesztő oldalt\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Nyiss meg egy HTML fájlt az Élő Előnézet indításához.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Az Élő Előnézet használatához szerver-oldali fájlokkal meg kell adni az alap URL-t a projekthez.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Hiba a HTTP szerver indításakor az Élő Fejlesztéshez. Kérlek próbáld újra később.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Üdv az Élő Előnézetben!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Az Élő Előnézet összeköti a {APP_NAME}-et a böngésződdel. Megnyitja a HTML fájl előnézetét a Böngészőben, majd rögtön frissül amikor szerkeszted a kódodat.<br /><br />Ebben a kezdetleges {APP_NAME} verzióban, az Élő Előnézet csak a <strong>Google Chrome</strong>-ban működik és élőben változik<strong>CSS fájlok</strong> szerkesztésekor. A HTML vagy JavaScript változások automatikusan frissülnek mentéskor.<br /><br />(Ezt az üzenetet csak egyszer fogod látni.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"További információért lásd: <a href='{0}' title='{0}'>Élő Előnézet csatlakozási hibák kiküszöbölése</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Élő Előnézet\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Élő Előnézet: Csatlakozás\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Élő Előnézet: Inicializálás\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Élő Előnézet lecsatlakozása\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Élő Előnézet: Kattints a lecsatlakozáshoz (Mentsd el a fájlt a frissítéshez)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Az Élő Előnézet lecsatlakozott mert a bongésző fejlesztő eszközei meg lettek nyitva\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Az Élő Előnézet lecsatlakozott mert az oldal be lett zárva a böngészőben\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Az Élő Előnézet lecsatlakozott mert a böngésző olyan oldalra lépett amely nem része a jelenlegi projektnek\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Az Élő Előnézet lecsatlakozott ismeretlen ok miatt ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Változtatások mentése\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"El szeretnéd menteni a változtatásokat itt: <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"El szeretnéd menteni a változtatásokat a következő fájlokban?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Külső Változtatások\",\n    \"FILE_DELETED_TITLE\"                : \"Fájl törölve\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"A/az <span class='dialog-filename'>{0}</span> meg lett változtatva a lemezen, de tartalmaz nem mentet változtatásokat is a {APP_NAME}-ben.<br /><br />Melyik verziót szeretnéd megtartani?\",\n    \"EXT_DELETED_MESSAGE\"               : \"A/az <span class='dialog-filename'>{0}</span> törölve lett a lemezen, de tartalmaz nem mentet változtatásokat is a {APP_NAME}-ben.<br /><br />Meg szeretnéd tartani a változtatásokat?\",\n\n    // Find, Replace, Find in Files\n    \"BUTTON_YES\"                        : \"Igen\",\n    \"BUTTON_NO\"                         : \"Nem\",\n\n    \"OPEN_FILE\"                         : \"Fájl megnyitása\",\n    \"SAVE_FILE_AS\"                      : \"Fájl mentése\",\n    \"CHOOSE_FOLDER\"                     : \"Válassz mappát\",\n\n    \"RELEASE_NOTES\"                     : \"Kiadási megjegyzések\",\n    \"NO_UPDATE_TITLE\"                   : \"A legfrissebb verziót használod!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"A legfrissebb {APP_NAME} fut.\",\n\n    \"FIND_IN_FILES_SCOPED\"              : \"a <span class='dialog-filename'>{0}</span>-ban\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"a projektben\",\n    \"FIND_IN_FILES_FILE\"                : \"fájl\",\n    \"FIND_IN_FILES_FILES\"               : \"fájlok\",\n    \"FIND_IN_FILES_MATCH\"               : \"találat\",\n    \"FIND_IN_FILES_MATCHES\"             : \"találatok\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Több mint \",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"Fájl: <span class='dialog-filename'>{0}</span>\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Hiba a frissítési infó lekérdezése közben\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Hiba történt a legfrissebb frissítési infó lekérdezése közben. Győződj meg arról hogy van internet kapcsolatod, majd próbáld meg újra.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Betöltés\\u2026\",\n    \"UNTITLED\"          : \"Névtelen\",\n    \"WORKING_FILES\"     : \"Munka fájlok\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Szóköz\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Sor {0}, Oszlop {1}\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Kattints hogy átváltsd a behúzást space-re\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Kattints hogy átváltsd a behúzást tabokra\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Kattints hogy átváltsd a behúzás space-ek számát\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Kattints hogy átváltsd a tab szélességét\",\n    \"STATUSBAR_SPACES\"                      : \"Szóközök\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab Mérete\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Sor\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Sor\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Fájl\",\n    \"CMD_FILE_NEW\"                        : \"Új Fájl\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Új Mappa\",\n    \"CMD_FILE_OPEN\"                       : \"Megnyitás\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Hozzáadás a Munkakészlethez\",\n    \"CMD_OPEN_FOLDER\"                     : \"Mappa Megnyitása\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Bezárás\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Összes Bezárása\",\n    \"CMD_FILE_SAVE\"                       : \"Mentés\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Összes Mentése\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Mentés másként\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Élő Előnézet\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Élő Kijelölés\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projekt Beállítások\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Átnevez\",\n    \"CMD_FILE_DELETE\"                     : \"Töröl\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Bővítmény Telepítése\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Bővítménykezelő\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Újratöltés\",\n    \"CMD_QUIT\"                            : \"Bezár\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Kilépés\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Szerkesztés\",\n    \"CMD_UNDO\"                            : \"Visszavonás\",\n    \"CMD_REDO\"                            : \"Újra\",\n    \"CMD_CUT\"                             : \"Kivágás\",\n    \"CMD_COPY\"                            : \"Másolás\",\n    \"CMD_PASTE\"                           : \"Beillesztés\",\n    \"CMD_SELECT_ALL\"                      : \"Összes kijelölése\",\n    \"CMD_SELECT_LINE\"                     : \"Sor kijelölése\",\n    \"CMD_FIND\"                            : \"Keres\",\n    \"CMD_FIND_IN_FILES\"                   : \"Keresés a Fájlokban\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Keresés a\\u2026\",\n    \"CMD_FIND_NEXT\"                       : \"Következő találat\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Előző találat\",\n    \"CMD_REPLACE\"                         : \"Csere\",\n    \"CMD_INDENT\"                          : \"Behúzás\",\n    \"CMD_UNINDENT\"                        : \"Behúzás visszavonása\",\n    \"CMD_DUPLICATE\"                       : \"Duplikálás\",\n    \"CMD_DELETE_LINES\"                    : \"Sor törlése\",\n    \"CMD_COMMENT\"                         : \"Sor komment bekapcsolása\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Blokk komment bekapcsolása\",\n    \"CMD_LINE_UP\"                         : \"Sor Mozgatása Fel\",\n    \"CMD_LINE_DOWN\"                       : \"Sor Mozgatása le\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Sor Nyitása Felül\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Sor Nyitása Alul\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Zárójelek Automatikus Bezárása\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Kód Súgó megjelenítése\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Nézet\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Oldalsáv Elrejtése\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Oldalsáv Mutatása\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Font Méretének Nagyítása\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Font Méretének Kicsinyítése\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Font Méretének Visszaállítása\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Sor Lapozása Felfele\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Sor Lapozása Lefele\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Sorok száma\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Aktív sor megjelölése\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Sortörés\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Rendezés Hozzáadás Szerint\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Rendezés Név Szerint\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Rendezés Típus Szerint\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatikus Rendezés\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigálás\",\n    \"CMD_QUICK_OPEN\"                      : \"Gyors megnyitás\",\n    \"CMD_GOTO_LINE\"                       : \"Ugrás Sorhoz\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Gyors Definíció keresés\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Gyors Szerkesztés\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Gyors Dokumentáció\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Előző Találat\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Következő Találat\",\n    \"CMD_NEXT_DOC\"                        : \"Következő Dokumentum\",\n    \"CMD_PREV_DOC\"                        : \"Előző Dokumentum\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Megjelenítés a Fastruktúrában\",\n    \"CMD_SHOW_IN_OS\"                      : \"Megjelenítés Intézőben\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Súgó\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Frissítések keresése\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"{APP_NAME} használata\",\n    \"CMD_RELEASE_NOTES\"                   : \"Kiadási megjegyzések\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Bővítmények mappa megjelenítése\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} a Twitter-en\",\n    \"CMD_ABOUT\"                           : \"A {APP_TITLE}-ről\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"kísérleti verzió\",\n    \"DEVELOPMENT_BUILD\"                    : \"fejlesztési verzió\",\n    \"OK\"                                   : \"OK\",\n    \"DONT_SAVE\"                            : \"Ne Mentse\",\n    \"SAVE\"                                 : \"Mentés\",\n    \"CANCEL\"                               : \"Mégse\",\n    \"RELOAD_FROM_DISK\"                     : \"Újratöltés a lemezről\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Változtatások megtartása a szerkesztőben\",\n    \"CLOSE_DONT_SAVE\"                      : \"Bezárás (Ne Mentse)\",\n    \"RELAUNCH_CHROME\"                      : \"Chrome Újraindítása\",\n    \"ABOUT\"                                : \"Rólunk\",\n    \"CLOSE\"                                : \"Bezárás\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Harmadik féltől származó szoftverekre vonatkozó közlemények, felhasználási feltételek megtalálhatók a következő linken <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a>.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentation and source at <a 'https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Készítve \\u2764 és JavaScript-el a következők által:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Sok ember (de ezt az adatot nem tudjuk megjeleníteni jelenleg).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"A MDN Dokumentáció és a  MDN grafikai logó a Creative Commons Attribution license alatt vannak licencelve, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Új {APP_NAME} verzió elérhető! Kattints ide a részletekért.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Új verzió elérhető\",\n    \"UPDATE_MESSAGE\"                       : \"Hé, új {APP_NAME} verzió elérhető. Íme néhány kulcsfontosságú frissítés:\",\n    \"GET_IT_NOW\"                           : \"Szerezd meg most!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projekt Beállítások a következőhöz: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Élő Előnézet alap URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Helyi szerver használatához, írd be a címet pl.: http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"A {0} protokol nem támogatott az Élő Előnézetben&mdash;kérlek használj http:-t vagy https:-t.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Az alap URL nem tartalmazhat paramétereket mint: \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Az alap URL nem tartalmazhat hash-okat mint: \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Speciális karakterek mint: '{0}' muszáj enkódolni %-be.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Ismeretlen hiba az alap URL beolvasásakor\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Telepítés\",\n    \"REMOVE\"                               : \"Eltávolítás\",\n    \"OVERWRITE\"                            : \"Felülírás\",\n    \"CANT_REMOVE_DEV\"                      : \"Bővítmények a \\\"dev\\\" mappában csak manuálisan távolíthatóak el.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Bővítmény telepítése\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Bővítmény URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"A Bővítmény GitHub repo-jának ZIP URL-je\",\n    \"INSTALLING_FROM\"                      : \"Bővítmény telepítése: {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Sikeres telepítés!\",\n    \"INSTALL_FAILED\"                       : \"Sikertelen telepítés.\",\n    \"CANCELING_INSTALL\"                    : \"Telepítés lemondása\\u2026\",\n    \"CANCELING_HUNG\"                       : \"A Telepítés lemondása sokáig tart. Lehetséges hogy belső hiba történt.\",\n    \"INSTALL_CANCELED\"                     : \"Telepítés lemondva.\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"A letöltött tartalom nem érvényes ZIP fájl.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"A package.json fájl nem érvényes (hiba: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"A package.json fájl nem határoz meg csomagnevet.\",\n    \"BAD_PACKAGE_NAME\"                     : \"A {0} nem érvényes csomagnév.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"A package.json fájl nem határoz meg csomagverziót.\",\n    \"INVALID_VERSION_NUMBER\"               : \"A csomagverzió ({0}) nem érvényes.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"A {APP_NAME} kompatibilitási sor ({0}) nem érvényes.\",\n    \"DISALLOWED_WORDS\"                     : \"A ({1}) szavak nem engedélyezettek a {0} mezőben.\",\n    \"API_NOT_COMPATIBLE\"                   : \"A Bővítmény nem kompatibilis a jelenlegi {APP_NAME} verzióval. A letiltott bővítmények közé lett telepítve.\",\n    \"MISSING_MAIN\"                         : \"A csomag nem tartalmaz main.js fájlt.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"A csomag telepítésével felülíródik egy előzőleg telepített bővítmény. Folytatod?\",\n    \"EXTENSION_SAME_VERSION\"               : \"A csomag verziója megegyezik a jelenleg telepítettével. Felülírod?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"A csomag verziója {0} ami régebbi mint a jelenlegi ({1}). Felülírod a jelenlegit?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Belső hiba: letöltő ID már használatban van.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Nem lehet csatlakozni a szerverhez.\",\n    \"BAD_HTTP_STATUS\"                      : \"A fájl nem található a szerveren (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Nem lehet ideiglenes fájlba menteni a letöltést.\",\n    \"ERROR_LOADING\"                        : \"A bővítmény hibába ütközött indításkor.\",\n    \"MALFORMED_URL\"                        : \"Az URL helytelen. Nézd meg hogy jól írtad be.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"Az URL muszáj http vagy https URL legyen.\",\n    \"UNKNOWN_ERROR\"                        : \"Ismeretlen belső hiba.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Bővítménykezelő\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Nem lehet elérni a bővítmény adatbázist. Kérlek próbáld meg később.\",\n    \"INSTALL_FROM_URL\"                     : \"Telepítés URL-ről\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Szerző\",\n    \"EXTENSION_DATE\"                       : \"Dátum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Ez a bővítmény csak a {APP_NAME} újabb verziójához jó.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Ez a bővítmény csak a {APP_NAME} régebbi verziójához jó\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Nincs leírás\",\n    \"EXTENSION_MORE_INFO\"                  : \"További infó...\",\n    \"EXTENSION_ERROR\"                      : \"Bővítmény hiba\",\n    \"EXTENSION_KEYWORDS\"                   : \"Kulcsszavak\",\n    \"EXTENSION_INSTALLED\"                  : \"Telepítve\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"A bővítményfrissítés letöltve és telepítve lessz amikor kilépsz a {APP_NAME}-ből.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Keresés\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Több\",\n    \"BROWSE_EXTENSIONS\"                    : \"Bővítmények tallózása\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Bővítmény Eltávolítása\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Nem lehet eltávolítani egy vagy több bővítményt: {0}. A {APP_NAME} ki fog lépni.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Bővítmény frissítése\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Nem lehet frissíteni egy vagy több bővítményt: {0}. A {APP_NAME} ki fog lépni.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Eltávolításhoz megjelölve\",\n    \"UNDO_REMOVE\"                          : \"Mégsem\",\n    \"MARKED_FOR_UPDATE\"                    : \"Frissítéshez megjelölve\",\n    \"UNDO_UPDATE\"                          : \"Mégsem\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"A {0} bővítményt nem lehet eltávolítani, mert nincs telepítve.\",\n    \"NO_EXTENSIONS\"                        : \"Nincs még telepített bővítmény.<br>Kattints a Telepítés URL-ről gombra a kezdéshez.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nincs bővítmény a keresett szavakra.\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"pixelek\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Hibakeresés\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Fejlesztői Eszközök megjelenítése\",\n    \"CMD_REFRESH_WINDOW\"                        : \"A {APP_NAME} újratöltése\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Új {APP_NAME} Ablak\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Nyelv változtatása\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Tesztek Futtatása\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Teljesítmény adatok megjelenítése\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Node Hibakereső engedélyezése\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Node naplózása a konzolban\",\n    \"CMD_RESTART_NODE\"                          : \"Node újraindítása\",\n\n    \"LANGUAGE_TITLE\"                            : \"Nyelv változtatása\",\n    \"LANGUAGE_MESSAGE\"                          : \"Nyelv:\",\n    \"LANGUAGE_SUBMIT\"                           : \"{APP_NAME} újratöltése\",\n    \"LANGUAGE_CANCEL\"                           : \"Mégsem\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Rendszer Alapértelmezett\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Jelenlegi szín\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Eredeti szín\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa Formátum\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex Formátum\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa Formátum\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} ({1}-szer használva)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} ({1}-szer használva)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Ugrás a Definícióhoz\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Gyors Nézet rámutatáskor\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Olvasd tovább\"\n});\n"
  },
  {
    "path": "src/nls/id/strings.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(kesalahan {0})\",\n    \"NOT_FOUND_ERR\"                     : \"File/direktori tidak dapat ditemukan.\",\n    \"NOT_READABLE_ERR\"                  : \"File/direktori tidak dapat dibaca.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"File lebih besar dari {0} MB tidak dapat dibuka di {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Direktori tujuan tidak dapat dimodifikasi.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Anda tidak memiliki izin untuk melakukan perubahan.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"File telah dimodifikasi di luar {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} saat ini hanya mendukung file teks yang di-encode dengan UTF-8.\",\n    \"ENCODE_FILE_FAILED_ERR\"            : \"{APP_NAME} tidak dapat mengenkoding konten pada berkas.\",\n    \"DECODE_FILE_FAILED_ERR\"            : \"{APP_NAME} tidak dapat mendekoding konten pada berkas.\",\n    \"UNSUPPORTED_UTF16_ENCODING_ERR\"    : \"{APP_NAME} saat ini tidak mendukung berkas teks dengan enkoding UTF-16.\",\n    \"FILE_EXISTS_ERR\"                   : \"File atau direktori sudah ada.\",\n    \"FILE\"                              : \"file\",\n    \"FILE_TITLE\"                        : \"File\",\n    \"DIRECTORY\"                         : \"direktori\",\n    \"DIRECTORY_TITLE\"                   : \"Direktori\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Nama direktori\",\n    \"FILENAMES_LEDE\"                    : \"Nama file\",\n    \"FILENAME\"                          : \"Nama file\",\n    \"DIRECTORY_NAME\"                    : \"Nama Direktori\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Gagal Memuat Proyek\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Terjadi kesalahan saat menampilkan dialog buka file. (kesalahan {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Terjadi kesalahan saat mencoba memuat direktori <span class='dialog-filename'>{0}</span>. (kesalahan {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Terjadi kesalahan saat membaca konten direktori <span class='dialog-filename'>{0}</span>. (kesalahan {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Gagal Membuka File\",\n    \"ERROR_OPENING_FILE\"                : \"Terjadi kesalahan saat mencoba membuka file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Terjadi kesalahan saat mencoba membuka file berikut:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Gagal Memuat Ulang Perubahan dari Disk\",\n    \"ERROR_RELOADING_FILE\"              : \"Terjadi kesalahan saat mencoba memuat ulang file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Gagal Menyimpan File\",\n    \"ERROR_SAVING_FILE\"                 : \"Terjadi kesalahan saat mencoba menyimpan file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Gagal Mengubah Nama {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Terjadi kesalahan saat mencoba mengubah nama {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Berkas atau direktori ini tidak termasuk dalam proyek yang dibuka saat ini. Sayangnya, hanya berkas dalam proyek yang dapat diganti namanya saat ini.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Gagal Menghapus {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Terjadi kesalahan saat mencoba menghapus {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"{0} Tidak Valid\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} tidak boleh menggunakan istilah cadangan milik sistem, akhiri dengan titik (.) atau gunakan karakter berikut: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"File atau direktori dengan nama <span class='dialog-filename'>{0}</span> sudah ada.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Gagal Membuat {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Terjadi kesalahan saat mencoba membuat {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Tidak dapat membuka folder di saat yang sama sedang membuka file lain.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Gagal Membaca Peta Kunci Pengguna\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"File kunci peta Anda bukan JSON yang valid. File akan dibuka agar Anda dapat memperbaikinya.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"File kunci peta Anda tidak ter-encode dengan UTF-8 secara valid dan tidak dapat dimuat\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Anda tidak dapat menetapkan ulang pintasan untuk perintah ini: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Anda tidak dapat menetapkan ulang pintasan ini: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Anda sedang menetapkan ulang banyak pintasan untuk perintah ini: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Anda mempunyai banyak kaitan untuk pintasan ini: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Pintasan ini tidak valid: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Anda sedang menetapkan pintasan untuk perintah yang tidak ada: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Gagal Membaca Preferensi\",\n    \"ERROR_PREFS_CORRUPT\"               : \"File preferensi Anda bukan merupakan JSON yang valid. File akan dibuka agar Anda dapat memperbaikinya. Anda perlu memulai ulang {APP_NAME} untuk memberlakukan perubahan.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ups! {APP_NAME} Belum Dapat Dijalankan di Peramban.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} dibuat menggunakan HTML, tetapi saat ini berjalan sebagai aplikasi desktop agar Anda dapat mengedit file lokal. Gunakan shell aplikasi di repositori <b>github.com/adobe/brackets-shell</b> untuk menjalankan {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Gagal Mengindeks File\",\n    \"ERROR_MAX_FILES\"                   : \"Proyek ini mempunyai lebih dari 30,000 file. Fitur yang beroperasi di beberapa file mungkin dinonaktifkan atau bersikap seolah-olah proyek kosong. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Baca selengkapnya tentang bekerja dengan proyek besar</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Gagal Menjalankan Peramban\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Peramban Google Chrome tidak dapat ditemukan. Pastikan Anda telah menginstalnya.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Terjadi kesalahan saat menjalankan peramban. (kesalahan {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Tinjauan Langsung Gagal\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Menyambung ke Peramban\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Agar Tinjauan Langsung dapat tersambung, Chrome harus dijalankan ulang dengan mode Remote Debugging.<br /><br />Apakah Anda ingin menjalankan ulang Chrome dan mengaktifkan Remote Debugging?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Tidak dapat memuat halaman Tinjauan Langsung\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Buka file HTML atau pastikan di dalam proyek Anda ada file index.html agar bisa menjalankan tinjauan langsung.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Untuk menjalankan tinjauan langsung dengan file sisi-server, Anda perlu mengatur URL Dasar untuk proyek ini.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Gagal menjalankan server HTTP untuk meninjau langsung file. Coba lagi.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Selamat Datang di Tinjauan Langsung!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Tinjauan Langsung menghubungkan {APP_NAME} ke peramban Anda, menjalankan file HTML Anda di peramban dan memperbarui tampilannya selagi Anda mengedit kode.<br /><br />Di versi awal {APP_NAME} ini, Tinjauan Langsung hanya bekerja pada <strong>Google Chrome</strong> dan memperbarui langsung selagi Anda mengedit <strong>file CSS atau HTML</strong>. Perubahan pada file JavaScript secara otomatis dimuat ulang saat Anda menyimpannya.<br /><br />(Anda hanya melihat pesan ini sekali.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Untuk informasi selengkapnya, lihat <a href='{0}' title='{0}'>Mengatasi masalah sambungan Tinjauan Langsung</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Tinjauan Langsung\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Tinjauan Langsung: Menyambung\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Tinjauan Langsung: Menginisialisasi\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Putuskan sambungan Tinjauan Langsung\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Tinjauan Langsung (simpan file untuk muat ulang)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Tinjauan Langsung (gagal memperbarui karena kesalahan sintaks)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Tinjauan Langsung dibatalkan karena Alat Pengembang pada peramban sedang dibuka\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Tinjauan Langsung dibatalkan karena halaman telah ditutup pada peramban\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Tinjauan Langsung dibatalkan karena peramban berpindah ke halaman yang bukan dari proyek\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Tinjauan Langsung dibatalkan karena alasan yang tidak diketahui ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Simpan Perubahan\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Apakah Anda ingin menyimpan perubahan yang Anda buat di dokumen <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Apakah Anda ingin menyimpan perubahan pada file berikut?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Perubahan Eksternal\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Konfirmasi Hapus\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Apakah Anda yakin ingin menghapus folder <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"File Dihapus\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> telah dimodifikasi di disk.<br /><br />Apakah Anda ingin menyimpan file dan menimpa perubahan tersebut?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> telah dimodifikasi, tetapi juga ada perubahan yang belum disimpan di {APP_NAME}.<br /><br />Versi mana yang ingin Anda simpan?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> telah dihapus di disk, tetapi ada perubahan yang belum disimpan di {APP_NAME}.<br /><br />Apakah Anda ingin menyimpan perubahan?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Selesai\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Batal\",\n    \"DONT_SAVE\"                         : \"Jangan Disimpan\",\n    \"SAVE\"                              : \"Simpan\",\n    \"SAVE_AS\"                           : \"Simpan Sebagai\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Timpa\",\n    \"DELETE\"                            : \"Hapus\",\n    \"BUTTON_YES\"                        : \"Ya\",\n    \"BUTTON_NO\"                         : \"Tidak\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} dari {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Tidak ada hasil\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Temukan\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Ganti dengan\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Batch\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Ganti\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Ganti\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Kecocokan Berikutnya\",\n    \"BUTTON_PREV_HINT\"                  : \"Kecocokan Sebelumnya\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Cocokkan Huruf Besar/Kecil\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regular Expression\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Ganti Tanpa Urung\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Karena lebih dari {0} file perlu diubah, {APP_NAME} akan memodifikasi file yang tidak dibuka di disk.<br />Anda tidak akan bisa membatalkan perubahan pada file tersebut.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Ganti Tanpa Urung\",\n\n    \"OPEN_FILE\"                         : \"Buka File\",\n    \"SAVE_FILE_AS\"                      : \"Simpan File\",\n    \"CHOOSE_FOLDER\"                     : \"Pilih folder\",\n\n    \"RELEASE_NOTES\"                     : \"Catatan Rilis\",\n    \"NO_UPDATE_TITLE\"                   : \"Versi terbaru!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Anda sedang menjalankan versi terbaru dari {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Ganti\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"dengan\",\n    \"FIND_TITLE_LABEL\"                  : \"Ditemukan\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} di {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"di <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"pada proyek\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filter mengecualikan semua file {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"file\",\n    \"FIND_IN_FILES_FILES\"               : \"file\",\n    \"FIND_IN_FILES_MATCH\"               : \"hasil\",\n    \"FIND_IN_FILES_MATCHES\"             : \"hasil\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Lebih dari \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd klik untuk melebarkan/melipat semua\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Gagal Mengganti\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"File berikut tidak termodifikasi karena berubah setelah pencarian atau tidak dapat ditulisi.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Gagal Mendapat Informasi Pembaruan\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Ada masalah saat mengambil data pembaruan dari server. Pastikan Anda terhubung ke internet dan coba lagi.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Daftar Pengecualian Baru\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Jangan Kecualikan File\",\n    \"NO_FILE_FILTER\"                    : \"Tidak Ada File yang Dikecualikan\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Kecualikan {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Edit\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Edit Daftar Pengecualian\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Kecualikan file dan folder yang cocok dengan kata atau <a href='{0}' title='{0}'>wildcard</a> berikut. Tulis tiap kata ke baris baru.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Beri nama daftar pengecualian ini (opsional)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"dan {0} lagi\",\n    \"FILTER_COUNTING_FILES\"             : \"Menghitung file\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Izinkan {0} dari {1} file {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Izinkan semua {0} file {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Edit Cepat tidak tersedia untuk posisi kursor saat ini\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Edit Cepat CSS: letakkan kursor pada satu nama class\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Edit Cepat CSS: atribut class tidak lengkap\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Edit Cepat CSS: atribut id tidak lengkap\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Edit Cepat CSS: letakkan kursor pada tag, class, atau id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Edit Cepat Fungsi Waktu CSS: sintaks tidak valid\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Edit Cepat JS: letakkan kursor pada nama fungsi\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Dokumentasi Cepat tidak tersedia untuk posisi kursor saat ini\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Memuat\\u2026\",\n    \"UNTITLED\"          : \"Tanpa Judul\",\n    \"WORKING_FILES\"     : \"File Kerja\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Atas\",\n    \"BOTTOM\"            : \"Bawah\",\n    \"LEFT\"              : \"Kiri\",\n    \"RIGHT\"             : \"Kanan\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Tanpa Sekat\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Sekat Vertikal\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Sekat Horisontal\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Beri sekat pada editor secara horisontal atau vertikal\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Atur Daftar Kerja\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Sudah Terbuka\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"File telah terbuka di panel lain. {APP_NAME} akan segera mendukung pembukaan file yang sama pada lebih dari satu panel. Sementara itu, file akan ditampilkan di panel yang telah membukanya.<br /><br />(Anda hanya melihat pesan ini sekali.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Spasi\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Baris {0}, Kolom {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} kolom dipilih\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} kolom dipilih\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} baris dipilih\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} baris dipilih\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} pilihan\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klik untuk mengganti inden menjadi spasi\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klik untuk mengganti inden menjadi tab\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klik untuk mengubah jumlah spasi yang digunakan untuk indentasi\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klik untuk mengubah ukuran karakter tab\",\n    \"STATUSBAR_SPACES\"                      : \"Spasi:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Ukuran Tab:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Baris\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Baris\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Ekstensi Tidak Aktif\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Klik untuk beralih antara mode Sisipan (INS) dan Timpa (OVR)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Klik untuk mengubah tipe file\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Klik untuk menampilkan/menyembunyikan panel laporan.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(default)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Simpan sebagai Default untuk File .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} Masalah\",\n    \"SINGLE_ERROR\"                          : \"1 Masalah {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} Masalah {0}\",\n    \"NO_ERRORS\"                             : \"Tidak ditemukan masalah {0} - kerja bagus!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Tidak ditemukan masalah - kerja bagus!\",\n    \"LINT_DISABLED\"                         : \"Analisa lint tidak aktif\",\n    \"NO_LINT_AVAILABLE\"                     : \"Tidak ada program lint yang tersedia untuk {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Tidak ada yang dapat dianalisis\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} telah habis waktunya setelah menunggu selama {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} dihentikan dengan kesalahan: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"File\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Baru\",\n    \"CMD_FILE_NEW\"                        : \"File Baru\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Folder Baru\",\n    \"CMD_FILE_OPEN\"                       : \"Buka\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Buka di Daftar Kerja\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Buka File yang Didrop\",\n    \"CMD_OPEN_FOLDER\"                     : \"Buka Folder\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Tutup\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Tutup Semua\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Tutup Daftar\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Tutup Lainnya\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Tutup yang di Atas\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Tutup yang di Bawah\",\n    \"CMD_FILE_SAVE\"                       : \"Simpan\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Simpan Semua\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Simpan Sebagai\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Tinjauan Langsung\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Aktifkan Tinjauan Langsung Eksperimental\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Memaksa Muat Ulang Tinjauan Langsung\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Pengaturan Proyek\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Ubah Nama\",\n    \"CMD_FILE_DELETE\"                     : \"Hapus\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instal Ekstensi\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Pengelola Ekstensi\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Muat Ulang Daftar File\",\n    \"CMD_QUIT\"                            : \"Keluar\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Keluar\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edit\",\n    \"CMD_UNDO\"                            : \"Urung\",\n    \"CMD_REDO\"                            : \"Ulangi\",\n    \"CMD_CUT\"                             : \"Potong\",\n    \"CMD_COPY\"                            : \"Salin\",\n    \"CMD_PASTE\"                           : \"Tempel\",\n    \"CMD_SELECT_ALL\"                      : \"Pilih Semua\",\n    \"CMD_SELECT_LINE\"                     : \"Pilih Baris\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Pisahkan Pilihan menjadi Baris\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Tambahkan Kursor ke Baris Selanjutnya\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Tambahkan Kursor ke Baris Sebelumnya\",\n    \"CMD_INDENT\"                          : \"Inden\",\n    \"CMD_UNINDENT\"                        : \"Batalkan Inden\",\n    \"CMD_DUPLICATE\"                       : \"Gandakan\",\n    \"CMD_DELETE_LINES\"                    : \"Hapus Baris\",\n    \"CMD_COMMENT\"                         : \"Aktifkan/Nonaktifkan Komentar Baris\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Aktifkan/Nonaktifkan Komentar Blok\",\n    \"CMD_LINE_UP\"                         : \"Pindahkan Baris ke Atas\",\n    \"CMD_LINE_DOWN\"                       : \"Pindahkan Baris ke Bawah\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Buka Baris di Atas\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Buka Baris di Bawah\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Tutup Kurung Otomatis\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Tampilkan Petunjuk Kode\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Temukan\",\n    \"CMD_FIND\"                            : \"Temukan\",\n    \"CMD_FIND_NEXT\"                       : \"Temukan Berikutnya\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Temukan Sebelumnya\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Temukan Semuanya dan Pilih\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Tambahkan Hasil Berikutnya ke Pilihan\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Lewati dan Tambahkan Hasil Berikutnya\",\n    \"CMD_FIND_IN_FILES\"                   : \"Temukan di File\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Temukan\\u2026\",\n    \"CMD_REPLACE\"                         : \"Ganti\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Ganti di File\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Ganti di\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Tampilan\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Sembunyikan Sidebar\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Tampilkan Sidebar\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Perbesar Ukuran Huruf\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Perkecil Ukuran Huruf\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Kembalikan Huruf ke Ukuran Awal\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Scroll Baris ke Atas\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Scroll Baris ke Bawah\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Nomor Baris\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Sorot Baris yang Aktif\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Word Wrap\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Sorotan Tinjauan Langsung\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Analisa File saat Menyimpan\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Urutkan Berdasarkan Waktu\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Urutkan Berdasarkan Nama\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Urutkan Berdasarkan Jenis\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Urutkan Secara Otomatis\",\n    \"CMD_THEMES\"                          : \"Tema\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigasi\",\n    \"CMD_QUICK_OPEN\"                      : \"Buka Cepat\",\n    \"CMD_GOTO_LINE\"                       : \"Pergi ke Baris\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Cari Cepat Definisi\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Pergi ke Masalah Pertama\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Edit Cepat\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Dokumentasi Cepat\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Hasil Sebelumnya\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Hasil Berikutnya\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Aturan Baru\",\n    \"CMD_NEXT_DOC\"                        : \"Dokumen Berikutnya\",\n    \"CMD_PREV_DOC\"                        : \"Dokumen Sebelumnya\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Tampilkan di Daftar File\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Tampilkan di Penelusur\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Tampilkan di Pencari\",\n    \"CMD_SHOW_IN_OS\"                      : \"Tampilkan di OS\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Bantuan\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Periksa Pembaruan\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Bagaimana Menggunakan {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Bantuan {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Sarankan Fitur\",\n    \"CMD_RELEASE_NOTES\"                   : \"Catatan Rilis\",\n    \"CMD_GET_INVOLVED\"                    : \"Ikut Terlibat\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Tampilkan Folder Ekstensi\",\n    \"CMD_HOMEPAGE\"                        : \"Beranda {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} di Twitter\",\n    \"CMD_ABOUT\"                           : \"Tentang {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Buka File Preferensi\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Buka Peta Kunci Pengguna\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"versi eksperimental\",\n    \"RELEASE_BUILD\"                        : \"versi\",\n    \"DEVELOPMENT_BUILD\"                    : \"versi pengembangan\",\n    \"RELOAD_FROM_DISK\"                     : \"Muat Ulang dari Disk\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Simpan Perubahan di Editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Tutup (Jangan Simpan)\",\n    \"RELAUNCH_CHROME\"                      : \"Jalankan Ulang Chrome\",\n    \"ABOUT\"                                : \"Tentang\",\n    \"CLOSE\"                                : \"Tutup\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Rilis {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"timestamp versi: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Catatan, syarat dan ketentuan mengenai perangkat lunak pihak ketiga ada di <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> dan digunakan di sini sebagai acuan.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentasi dan kode sumber di <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Dibuat dengan \\u2764 dan JavaScript oleh:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Banyak sekali orang (tetapi kami tidak dapat menampilkan daftarnya saat ini).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"Dokumentasi dan logo grafis MDN berlisensi Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Versi terbaru dari {APP_NAME} telah tersedia! Klik disini untuk lebih detail.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Pembaruan Tersedia\",\n    \"UPDATE_MESSAGE\"                       : \"Hai, versi terbaru {APP_NAME} sudah ada. Ini fitur terbarunya:\",\n    \"GET_IT_NOW\"                           : \"Dapatkan sekarang!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Pengaturan Proyek untuk: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL Dasar untuk Tinjauan Langsung\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Untuk menggunakan server lokal, masukkan url seperti http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Protokol {0} tidak didukung oleh Tinjauan Langsung&mdash;gunakan http: atau https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL dasar tidak boleh mengandung parameter pencarian seperti \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL dasar tidak boleh mengandung tanda hash seperti \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Karakter spesial seperti '{0}' harus ter-encode dalam format %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Gagal membuka URL Dasar\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Buka file ketika panel ini mendapat fokus</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Tema Saat Ini\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Gunakan Scrollbar Tema\",\n    \"FONT_SIZE\"                            : \"Ukuran Huruf\",\n    \"FONT_FAMILY\"                          : \"Famili Huruf\",\n    \"THEMES_SETTINGS\"                      : \"Pengaturan Tema\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Aturan Baru\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instal\",\n    \"UPDATE\"                               : \"Perbarui\",\n    \"REMOVE\"                               : \"Buang\",\n    \"OVERWRITE\"                            : \"Timpa\",\n    \"CANT_REMOVE_DEV\"                      : \"Ekstensi pada folder \\\"dev\\\" harus dihapus secara manual.\",\n    \"CANT_UPDATE\"                          : \"Pembaruan tidak kompatibel dengan {APP_NAME} versi ini.\",\n    \"CANT_UPDATE_DEV\"                      : \"Ekstensi pada folder \\\"dev\\\" tidak dapat diperbarui secara otomatis.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instal Ekstensi\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Perbarui Ekstensi\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL Ekstensi\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL file zip atau repositori GitHub dari ekstensi\",\n    \"INSTALLING_FROM\"                      : \"Menginstal ekstensi dari {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalasi sukses!\",\n    \"INSTALL_FAILED\"                       : \"Instalasi gagal.\",\n    \"CANCELING_INSTALL\"                    : \"Membatalkan\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Pembatalan memakan waktu terlalu lama. Mungkin telah terjadi kesalahan internal.\",\n    \"INSTALL_CANCELED\"                     : \"Instalasi dibatalkan.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Tampilkan deskripsi lengkap\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Tampilkan deskripsi singkat\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Konten yang diunduh bukan file zip yang valid.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"File package.json tidak valid (kesalahan: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"File package.json tidak menyebutkan nama paket.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} adalah nama paket yang tidak valid.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"File package.json tidak menyebutkan versi paket.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Nomor versi paket ({0}) tidak valid.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"String kompatibilitas {APP_NAME} ({0}) tidak valid.\",\n    \"DISALLOWED_WORDS\"                     : \"Kata ({1}) tidak diizinkan di kolom {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Ekstensi tidak cocok dengan versi {APP_NAME} ini. Ekstensi diinstal pada folder ekstensi nonaktif.\",\n    \"MISSING_MAIN\"                         : \"Paket ini tidak mempunyai file main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Menginstal paket ini akan menimpa ekstensi yang lama. Timpa ekstensi?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Versi paket ini sama dengan yang terinstal saat ini. Timpa ekstensi yang ada?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Paket ini adalah versi {0} yang lebih lama dari versi yang terinstal saat ini ({1}). Timpa instalasi yang ada?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Kesalahan internal: ID unduh sedang digunakan.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Tidak dapat tersambung ke server.\",\n    \"BAD_HTTP_STATUS\"                      : \"File tidak ditemukan pada server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Gagal menyimpan unduhan ke file sementara.\",\n    \"ERROR_LOADING\"                        : \"Ada masalah saat menjalankan ekstensi.\",\n    \"MALFORMED_URL\"                        : \"URL tidak valid. Periksa kembali.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL harus HTTP atau HTTPS.\",\n    \"UNKNOWN_ERROR\"                        : \"Kesalahan internal yang tidak diketahui.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Pengelola Ekstensi\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Gagal membuka daftar ekstensi. Coba lagi nanti.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Tarik .zip ke sini atau\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Jatuhkan .zip untuk menginstal\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Instal/Pembaruan dibatalkan karena kesalahan berikut:\",\n    \"INSTALL_FROM_URL\"                     : \"Instal dari URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Memvalidasi\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Pembuat\",\n    \"EXTENSION_DATE\"                       : \"Tanggal\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Ekstensi ini membutuhkan versi {APP_NAME} yang lebih baru.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Ekstensi ini hanya  kompatibel dengan versi {APP_NAME} yang lama.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Versi {0} dari ekstensi ini membutuhkan versi terbaru dari {APP_NAME}. Tapi Anda dapat menginstal versi sebelumnya {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Versi {0} hanya kompatibel dengan versi {APP_NAME} yang lama. Tapi Anda dapat menginstal versi sebelumnya {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Tanpa keterangan\",\n    \"EXTENSION_MORE_INFO\"                  : \"Info selengkapnya\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Kesalahan Ekstensi\",\n    \"EXTENSION_KEYWORDS\"                   : \"Kata Kunci\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Diterjemahkan ke {0} bahasa, termasuk bahasa Anda\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Diterjemahkan ke {0} bahasa\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Ekstensi ini telah diterjemahkan ke bahasa berikut: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Terinstal\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Pembaruan untuk ekstensi ini telah terunduh dan akan diinstal setelah {APP_NAME} dimuat ulang.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Cari\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Selengkapnya\",\n    \"BROWSE_EXTENSIONS\"                    : \"Telusuri Ekstensi\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Buang Ekstensi\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Gagal membuang extensi: {0}. {APP_NAME} akan tetap dimuat ulang.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Perbarui Ekstensi\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Gagal memperbarui ekstensi: {0}. {APP_NAME} akan tetap dimuat ulang.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Ditandai untuk dibuang\",\n    \"UNDO_REMOVE\"                          : \"Urungkan\",\n    \"MARKED_FOR_UPDATE\"                    : \"Ditandai untuk diperbarui\",\n    \"UNDO_UPDATE\"                          : \"Urungkan\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Ganti Ekstensi\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Untuk memperbarui atau membuang ekstensi yang ditandai, {APP_NAME} perlu dimuat ulang. Anda akan diminta untuk menyimpan perubahan.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Buang Ekstensi dan Muat Ulang\",\n    \"CHANGE_AND_RELOAD\"                    : \"Ganti Ekstensi dan Muat Ulang\",\n    \"UPDATE_AND_RELOAD\"                    : \"Perbarui Ekstensi dan Muat Ulang\",\n    \"PROCESSING_EXTENSIONS\"                : \"Memproses perubahan ekstensi\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Tidak dapat membuang extensi {0} karena tidak terinstal.\",\n    \"NO_EXTENSIONS\"                        : \"Belum ada ekstensi yang terinstal.<br />Klik pada tab Tersedia di atas untuk memulai.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Tidak ditemukan ekstensi yang sesuai dengan kriteria pencarian.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"CATATAN: Ekstensi ini bisa berasal dari pembuat yang berbeda dari {APP_NAME}. Ekstensi tidak ditinjau dan mempunyai akses lokal secara penuh. Hati-hati ketika menginstal ekstensi dari sumber yang tidak diketahui.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Terinstal\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Tersedia\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Tema\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Pembaruan\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Tidak ada hasil.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Semua hasil disembunyikan. Perbesar file yang ditampilkan di sebelah kanan untuk menampilkannya.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Tidak ada aturan CSS yang cocok dengan kriteria Anda.<br> Klik \\\"Aturan Baru\\\" untuk membuat baru.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Proyek Anda tidak mempunyai stylesheet.<br>Buat baru untuk menambahkan aturan CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"paling besar\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"piksel\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"Kesalahan\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Tampilkan Alat Pengembang\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Muat Ulang Dengan Ekstensi\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Muat Ulang Tanpa Ekstensi\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Jendela {APP_NAME} Baru\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Ganti Bahasa\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Jalankan Tes\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Tampilkan Data Performa\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Aktifkan Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Log Status Node di konsol\",\n    \"CMD_RESTART_NODE\"                          : \"Jalankan Ulang Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Tampilkan Kesalahan di Status Bar\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Buka Kode Sumber Brackets\",\n\n    \"LANGUAGE_TITLE\"                            : \"Ganti Bahasa\",\n    \"LANGUAGE_MESSAGE\"                          : \"Bahasa:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Muat ulang {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Batal\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Default Sistem\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Waktu\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progres\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Pindahkan titik yang dipilih<br><kbd class='text'>Shift</kbd> Pindahkan 10 unit<br><kbd class='text'>Tab</kbd> Tukar titik\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Tambah atau kurangi langkah<br><kbd>←</kbd><kbd>→</kbd> 'Awal' atau 'Akhir'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Nilai <code>{0}</code> yang lama tidak valid, sehingga fungsi yang ditampilkan diubah ke <code>{1}</code>. Dokumen akan diperbarui menggunakan editan pertama.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Warna Saat ini\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Warna Awal\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Format RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Format Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Format HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Digunakan {1} kali)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Digunakan {1} kali)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Lompat ke Definisi\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Tampilkan Petunjuk Parameter\",\n    \"NO_ARGUMENTS\"                              : \"<tidak ada parameter>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Masalah Inferensi File JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets mengalami masalah dalam memproses <span class='dialog-filename'>{0}</span>.<br><br>File ini tidak akan lagi diproses untuk Petunjuk Kode, Lompat ke Definisi atau Edit Cepat. Untuk mengaktifkan kembali file ini, buka <code>.brackets.json</code> pada proyek Anda dan ubah <code>jscodehints.detectedExclusions</code>.<br><br>Kemungkinan ini adalah bug pada Brackets. Jika Anda dapat memberikan salinan file ini, <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>laporkan bug/a> dengan tautan ke file yang disebutkan di sini.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Tampilkan Cepat Saat Hover\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Proyek Terkini\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Baca selengkapnya\"\n});\n/* Last translated for c96c8bc3b55f518a91ebb6625e24347812fe9a1b */\n"
  },
  {
    "path": "src/nls/id/urls.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"id/Memulai\",\n    \"MDN_DOCS_LICENSE\" : \"http://creativecommons.org/licenses/by-sa/2.5/deed.id\"\n});\n"
  },
  {
    "path": "src/nls/it/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n    * Errors\n    */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(errore {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Impossibile trovare il file o la cartella.\",\n    \"NOT_READABLE_ERR\"                  : \"Impossibile leggere il file o la cartella.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"File oltre {0} MB non possono essere aperti con {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"La cartella selezionata non può essere modificata.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Non hai i permessi necessari per effettuare la modifica.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Il file è stato modificato fuori {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"Attualmente {APP_NAME} supporta solo testo codificato in UTF-8\",\n    \"FILE_EXISTS_ERR\"                   : \"Il file o la cartella è già presente.\",\n    \"FILE\"                              : \"file\",\n    \"FILE_TITLE\"                        : \"File\",\n    \"DIRECTORY\"                         : \"cartella\",\n    \"DIRECTORY_TITLE\"                   : \"Cartella\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"nomi delle cartelle\",\n    \"FILENAMES_LEDE\"                    : \"nomi dei file\",\n    \"FILENAME\"                          : \"nome del file\",\n    \"DIRECTORY_NAME\"                    : \"nome della cartella\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Errore durante il caricamento del progetto\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Errore durante il caricamento della finestra di dialogo per l’apertura del file. (errore {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Errore durante il tentativo di caricare la cartella <span class='dialog-filename'>{0}</span>. (errore {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Errore durante la lettura del contenuto della cartella <span class='dialog-filename'>{0}</span>. (errore {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Errore durante l’apertura del file\",\n    \"ERROR_OPENING_FILE\"                : \"Errore durante il tentativo di apertura del file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Errore durante il tentativo di apertura dei seguenti file:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Errore durante il caricamento delle modifiche dal disco\",\n    \"ERROR_RELOADING_FILE\"              : \"Errore durante il tentativo di ricaricare il file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Errore durante il salvataggio del file\",\n    \"ERROR_SAVING_FILE\"                 : \"Errore durante il tentativo di salvare il file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Errore durante il tentativo di rinominare il file\",\n    \"ERROR_RENAMING_FILE\"               : \"Errore durante il tentativo di rinominare il file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Errore durante il tentativo di eliminazione del file\",\n    \"ERROR_DELETING_FILE\"               : \"Errore durante il tentativo di eliminazione del file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Il {0} non è valido\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"I {0} non possono usare caratteri di sistema riservati, finire con un punto (.) o contenere i seguenti caratteri: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Il file o la cartella <span class='dialog-filename'>{0}</span> esiste già.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Errore durante la creazione del file\",\n    \"ERROR_CREATING_FILE\"               : \"Errore durante il tentativo di creare il file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Impossibile aprire una cartella contemporaneamente all'apertura di altri file.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Errore nella lettura del Key Map\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Il tuo file non è in formato JSON valido. Il file sarà riaperto per poter correggere il formato.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"La tua Key Map non è un file UTF-8 valido e non può essere caricato\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Non puoi riassegnare queste scorciatoie: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Non puoi riassegnare delle scorciatoie a questi comandi: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Stai riassegnando più di una scorciatoia a questi comandi:: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Possiedi più possibilità in queste scorciatoie: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Queste scorciatoie non sono valide: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Stai assegnando scorciatoie a comandi inesistenti: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Errore nella lettura delle preferenze\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Le tue preferenze non sono in un file JSON valido. Il file verrà aperto in modo da poter correggere il formato. Dovrai riavviare {APP_NAME} affinché le modifiche abbiano effetto.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Le preferenze del progetto non sono in un file JSON valido. Il file verrà aperto in modo da poter correggere il formato. Dovrai riavviare {APP_NAME} affinché le modifiche abbiano effetto.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! {APP_NAME} non può essere ancora eseguita nel browser.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} è scritta in HTML, ma al momento viene eseguita come applicazione desktop per avere la possibilità di modificare file locali. Puoi usare la shell dal repository <b>github.com/adobe/brackets-shell</b> per eseguire {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Errore durante l’indicizzazione dei file\",\n    \"ERROR_MAX_FILES\"                   : \"È stato raggiunto il massimo numero di file indicizzati. Le azioni che controllano file presenti nell’indice posso funzionare in modo non corretto.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Errore durante l’avvio del browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Non è stato possibile trovare il browser Google Chrome. Assicurarsi che sia correttamente installato.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Errore durante l’avvio del browser. (errore {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Errore durante l’Anteprima Live\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Connessione al Browser in corso\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Per effettuare una connessione con Anteprima Live, Chrome deve essere rilanciato con il debugging remoto abilitato.<br /><br />Vuoi rilanciare Chrome e abilitare il debugging remoto?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Impossibile caricare l'Anteprima Live\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Apri un file HTML per lanciare l’Anteprima Live.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Per avviare l'Anteprima Live con un file server-side, è necessario specificare un URL di base per questo progetto.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Errore durante l’avvio del server HTTP server per i file di sviluppo in tempo reale. Riprova ancora.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Benvenuto nell’Anteprima Live!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Anteprima Live connette {APP_NAME} al tuo browser. Lancia una anteprima del tuo file HTML nel browser e dopo ogni tua modifica l’anteprima verrà aggiornata istantaneamente per riflettere le modifiche del tuo codice.<br /><br />In questa versione preliminare di {APP_NAME}, Anteprima Live funziona solo per le modifiche su <strong>file CSS</strong> e solo con <strong>Google Chrome</strong>. Verrà implementata presto anche per HTML e JavaScript!<br /><br />(Vedrai questo messaggio una sola volta.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Per maggiori informazioni leggi <a href='{0}' title='{0}'>Risoluzione dei problemi di connessione a Anteprima Live</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Anteprima Live\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Anteprima Live: Connessione\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Anteprima Live: Inizializzazione\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Disconnetti Anteprima Live\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Anteprima Live: clicca per disconnettere (Salva il file per aggiornare)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Anteprima Live (non aggiorna a causa di un errore di sintassi)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"L’Anteprima Live è stata cancellata perché uno strumento di sviluppo è stato aperto nel browser\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"L’Anteprima Live è stata cancellata perché è stato chiuso il browser\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"L’Anteprima Live è stata cancellata perché il browser ha caricato una pagina che non fa parte del progetto corrente\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"L’Anteprima Live è stata cancellata a causa di un errore sconosciuto ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Salva le modifiche\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Vuoi cambiare le modifiche apportate al file <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Vuoi cambiare le modifiche apportate ai seguenti file?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Modifiche esterne\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Confermi l'eliminazione?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Sei sicuro di eliminare la cartella <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"File Eliminato\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> è stato modificato sul disco.<br /><br />Vuoi salvare il file e sovrascrivere le modifiche?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> è stato modificato sul disco ma ha delle modifiche non ancora salvate in {APP_NAME}.<br /><br />Quale versione vuoi tenere?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> è stato eliminato sul disco ma ha delle modifiche non ancora salvate in {APP_NAME}.<br /><br />Vuoi mantenere le tue modifiche?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Fatto\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Annulla\",\n    \"DONT_SAVE\"                         : \"Non salvare\",\n    \"SAVE\"                              : \"Salva\",\n    \"SAVE_AS\"                           : \"Salva come\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Sovrascrivi\",\n    \"DELETE\"                            : \"Cancella\",\n    \"BUTTON_YES\"                        : \"Si\",\n    \"BUTTON_NO\"                         : \"No\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} di {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Nessun risultato\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Trova\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Sostituisci con\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Tutti\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Sostituire\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Sostituisci\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Corrispondenza successiva\",\n    \"BUTTON_PREV_HINT\"                  : \"Corrispondenza precedente\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Rispetta maiuscole/minuscole\",\n    \"BUTTON_REGEXP_HINT\"                : \"Espressione regolare\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Sostituire senza Annullare\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Poichè più di {0} file deve essere modificato, {APP_NAME} modificherà i file aperti sul disco.<br />Non sarai in grado di annullare le modifiche in quei file.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Sostituire senza Annullare\",\n\n    \"OPEN_FILE\"                         : \"Apri File\",\n    \"SAVE_FILE_AS\"                      : \"Salva File\",\n    \"CHOOSE_FOLDER\"                     : \"Scegli una cartella\",\n\n    \"RELEASE_NOTES\"                     : \"Note di rilascio\",\n    \"NO_UPDATE_TITLE\"                   : \"Sei aggiornato!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Stai utilizzando l’ultima versione di {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Sostituire\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"con\",\n    \"FIND_TITLE_LABEL\"                  : \"Trovato\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} in {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"in <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"nel progetto\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtra esclude tutti i file {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"file\",\n    \"FIND_IN_FILES_FILES\"               : \"file\",\n    \"FIND_IN_FILES_MATCH\"               : \"corrispondenza\",\n    \"FIND_IN_FILES_MATCHES\"             : \"corrispondenze\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Oltre \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We shoudl use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd click per Espandere/Comprimi tutto\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indicizzazione per ricerca immediata\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Sostituire errori\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"I seguenti file non sono stati modificati perché hanno cambiato dopo la ricerca o non potevano essere scritti.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Si è verificato un errore nel recuperare le informazioni aggiornate\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Si è verificato un errore nel recuperare le informazioni aggiornate dal server. Assicurati di essere connesso a internet e riprova.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Nuova regola di esclusione\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Non escludere file\",\n    \"NO_FILE_FILTER\"                    : \"Nessun file escluso\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Escludere {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Modifica\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Modifica regole di esclusione\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Esclusione di file e cartelle corrispondenti delle seguenti stringhe o sottostringhe <a href='{0}' title='{0}'>caratteri jolly</a>. Immettere ogni stringa su una nuova linea.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nome delle regole di esclusione (facoltativo)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"e {0} più\",\n    \"FILTER_COUNTING_FILES\"             : \"Contando i file\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Consentire {0} di {1} file {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Consentire tutti {0} file {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Quick Edit non disponibile per posizione attuale del cursore\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Quick Edit: posiziona il cursore sul nome di una classe singola.\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Quick Edit: attributo classe incompleto\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Quick Edit: attributo id incompleto\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Quick Edit: posiziona il cursore su etichetta, classe, oppure id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Funzione CSS Timing Quick Edit: sintassi invalida\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Quick Edit: posiziona il cursore su nome della Funzione\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Quick Docs non disponibile per posizione attuale del cursore\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Caricamento\\u2026\",\n    \"UNTITLED\"          : \"Senza titolo\",\n    \"WORKING_FILES\"     : \"File attivi\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Superiore\",\n    \"BOTTOM\"            : \"Inferiore\",\n    \"LEFT\"              : \"Sinistra\",\n    \"RIGHT\"             : \"Destra\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Nessuna Divisione\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Dividere Verticalmente\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Dividere Orizzontalmente\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Dividere l'editor verticalmente oppure orizzontalmente\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configura le impostazioni di lavoro\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Già aperto\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Il file è già aperto in un altro riquadro. {APP_NAME} sarà presto possibile aprire lo stesso file in più di un riquadro. Fino ad allora, il file verrà mostrato nel riquadro che è già aperto.<br /><br />(Tu vedrai questo messaggio solo una volta.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Maiusc\",\n    \"KEYBOARD_SPACE\"  : \"Spazio\",\n    \"KEYBOARD_PAGE_UP\"      : \"Pagina Su\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Pagina Giù\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"Fine\",\n    \"KEYBOARD_INSERT\"       : \"Ins\",\n    \"KEYBOARD_DELETE\"       : \"Canc\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Linea {0}, Colonna {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Selezionata {0} colonna\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Selezionate {0} colonne\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Selezionata {0} linea\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Selezionate {0} linee\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} selezioni\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Clicca per passare alla indentazione a spazi\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Clicca per passare alla indentazione a tabulazione\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Clicca per cambiare il numero di spazi usati per l’indentazione\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Clicca per cambiare la ampiezza della tabulazione\",\n    \"STATUSBAR_SPACES\"                      : \"Spazi\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Ampiezza tabulazione:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Linea\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Linee\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Estensioni disabilitate\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Fare clic per cambiare il cursore tra la modalità Inserisci (INS) e Sovrascrivi (OVR)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Clicca per cambiare il tipo di file\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Clicca per attivare pannello dei report.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(default)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Imposta come predefinito per .{0} File\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} Problemi\",\n    \"SINGLE_ERROR\"                          : \"1 {0} Problema\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} Problemi\",\n    \"NO_ERRORS\"                             : \"Nessun {0} problema trovato - ottimo lavoro!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Nessun problema trovato - ottimo lavoro!\",\n    \"LINT_DISABLED\"                         : \"Lint disabilitato\",\n    \"NO_LINT_AVAILABLE\"                     : \"Lint disponibile {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Niente dal Lint\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} è scaduto dopo aver atteso per {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} terminato con errore: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"File\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nuovo\",\n    \"CMD_FILE_NEW\"                        : \"Nuovo File\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nuova cartella\",\n    \"CMD_FILE_OPEN\"                       : \"Apri\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Aggiungi all'area di lavoro\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Apri un file abbandonato\",\n    \"CMD_OPEN_FOLDER\"                     : \"Apri cartella\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Chiudi\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Chiudi tutto\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Chiudi lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Chiudi tutto il resto\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Chiudi tutto al di sopra\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Chiudi tutto al di sotto\",\n    \"CMD_FILE_SAVE\"                       : \"Salva\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Salva tutto\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Salva come\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Anteprima Live\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Abilita l'Anteprima Live nel tuo browser preferito (sperimentale)\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Forza ricarica Anteprima Live\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Impostazioni del progetto\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Rinomina\",\n    \"CMD_FILE_DELETE\"                     : \"Elimina\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Installa Estensioni\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Manager delle Estensioni\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Ricarica il percorso file\",\n    \"CMD_QUIT\"                            : \"Abbandona\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                          : \"Esci\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                         : \"Modifica\",\n    \"CMD_UNDO\"                          : \"Annulla\",\n    \"CMD_REDO\"                          : \"Ripristina\",\n    \"CMD_CUT\"                           : \"Taglia\",\n    \"CMD_COPY\"                          : \"Copia\",\n    \"CMD_PASTE\"                         : \"Incolla\",\n    \"CMD_SELECT_ALL\"                    : \"Seleziona tutto\",\n    \"CMD_SELECT_LINE\"                   : \"Seleziona riga\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"          : \"Dividi selezione dentro alle righe\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"          : \"Aggiungi cursore alla riga successiva\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"          : \"Aggiungi il cursore sulla riga precedente\",\n    \"CMD_INDENT\"                        : \"Aumenta indentazione\",\n    \"CMD_UNINDENT\"                      : \"Riduci indentazione\",\n    \"CMD_DUPLICATE\"                     : \"Duplica\",\n    \"CMD_DELETE_LINES\"                  : \"Elimina linea\",\n    \"CMD_COMMENT\"                       : \"Commenta/De-commenta linee\",\n    \"CMD_BLOCK_COMMENT\"                 : \"Commenta/De-commenta blocco\",\n    \"CMD_LINE_UP\"                       : \"Sposta la riga in alto\",\n    \"CMD_LINE_DOWN\"                     : \"Sposta la riga in basso\",\n    \"CMD_OPEN_LINE_ABOVE\"               : \"Apri linea sopra\",\n    \"CMD_OPEN_LINE_BELOW\"               : \"Apri linea sotto\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"         : \"Chiudi le parentesi automaticamente\",\n    \"CMD_SHOW_CODE_HINTS\"               : \"Mostra suggerimenti\",\n\n     // Search menu commands\n    \"FIND_MENU\"                           : \"Cerca\",\n    \"CMD_FIND\"                            : \"Cerca\",\n    \"CMD_FIND_NEXT\"                       : \"Cerca il successivo\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Cerca il precedente\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Trova tutto e seleziona\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Aggiungi la prossima corrispondenza alla selezione\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Salta e aggiungi prossima correspondenza\",\n    \"CMD_FIND_IN_FILES\"                   : \"Cerca nei file\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Cerca in\\u2026\",\n    \"CMD_REPLACE\"                         : \"Sostituisci\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Sostituisci nei file\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Sostituisci in\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                         : \"Vista\",\n    \"CMD_HIDE_SIDEBAR\"                  : \"Nascondi barra laterale\",\n    \"CMD_SHOW_SIDEBAR\"                  : \"Mostra barra laterale\",\n    \"CMD_TOGGLE_SIDEBAR\"                : \"Apri/Chiudi la barra laterale\",\n    \"CMD_TOGGLE_PANELS\"                 : \"Apri/Chiudi i pannelli\",\n    \"CMD_TOGGLE_PURE_CODE\"              : \"Nessuna distrazione\",\n    \"CMD_INCREASE_FONT_SIZE\"            : \"Aumenta la dimensione del testo\",\n    \"CMD_DECREASE_FONT_SIZE\"            : \"Diminuisci la dimensione del testo\",\n    \"CMD_RESTORE_FONT_SIZE\"             : \"Ripristina la dimensione del testo\",\n    \"CMD_SCROLL_LINE_UP\"                : \"Scorri verso l’alto\",\n    \"CMD_SCROLL_LINE_DOWN\"              : \"Scorri verso il basso\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"           : \"Numeri linea\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"            : \"Evidenzia linea attiva\",\n    \"CMD_TOGGLE_WORD_WRAP\"              : \"A capo automaticamente\",\n    \"CMD_LIVE_HIGHLIGHT\"                : \"Ispezione Anteprima Live\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"        : \"Lint Files al salvataggio\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"      : \"Ordina per Aggiunta\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"       : \"Ordina per Nome\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"       : \"Ordina per Tipo\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"      : \"Ordina Automaticamente\",\n    \"CMD_THEMES\"                        : \"Temi\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                     : \"Naviga\",\n    \"CMD_QUICK_OPEN\"                    : \"Apri velocemente\",\n    \"CMD_GOTO_LINE\"                     : \"Vai alla linea\",\n    \"CMD_GOTO_DEFINITION\"               : \"Vai alla definizione\",\n    \"CMD_GOTO_FIRST_PROBLEM\"            : \"Vai al primo Errore/Avviso\",\n    \"CMD_TOGGLE_QUICK_EDIT\"             : \"Modifica veloce\",\n    \"CMD_TOGGLE_QUICK_DOCS\"             : \"Documentazione veloce\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"         : \"Corrispondenza precedente\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"         : \"Corrispondenza successiva\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"       : \"Nuova regola\",\n    \"CMD_NEXT_DOC\"                      : \"Documento successivo\",\n    \"CMD_PREV_DOC\"                      : \"Documento precedente\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"           : \"Documento successivo nella lista\",\n    \"CMD_PREV_DOC_LIST_ORDER\"           : \"Documento precedente nella lista\",\n    \"CMD_SHOW_IN_TREE\"                  : \"Mostra nell’albero dei file\",\n    \"CMD_SHOW_IN_EXPLORER\"              : \"Mostra in Explorer\",\n    \"CMD_SHOW_IN_FINDER\"                : \"Mostra in Finder\",\n    \"CMD_SHOW_IN_OS\"                    : \"Mostra in SO\",\n\n    // Help menu commands\n    \"HELP_MENU\"                         : \"Aiuto\",\n    \"CMD_CHECK_FOR_UPDATE\"              : \"Controlla aggiornamenti\",\n    \"CMD_HOW_TO_USE_BRACKETS\"           : \"Come usare {APP_NAME}\",\n    \"CMD_SUPPORT\"                       : \"Supporto per {APP_NAME}\",\n    \"CMD_SUGGEST\"                       : \"Suggerisci una funzionalità\",\n    \"CMD_RELEASE_NOTES\"                 : \"Note di rilascio\",\n    \"CMD_GET_INVOLVED\"                  : \"Far parte\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"        : \"Mostra cartella estensioni\",\n    \"CMD_HEALTH_DATA_STATISTICS\"        : \"Health Data Report\",\n    \"CMD_HOMEPAGE\"                      : \"Sito WEB di {APP_TITLE}\",\n    \"CMD_TWITTER\"                       : \"{TWITTER_NAME} su Twitter\",\n    \"CMD_ABOUT\"                         : \"Informazioni su {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"              : \"Apri il file delle preferenze\",\n    \"CMD_OPEN_KEYMAP\"                   : \"Apri la Key Map del utente\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                : \"build sperimentale\",\n    \"DEVELOPMENT_BUILD\"                 : \"build di sviluppo\",\n    \"RELEASE_BUILD\"                     : \"build di rilascio\",\n    \"RELOAD_FROM_DISK\"                  : \"Ricarica dal disco\",\n    \"KEEP_CHANGES_IN_EDITOR\"            : \"Conserva le modifiche nell’editor\",\n    \"CLOSE_DONT_SAVE\"                   : \"Chiudi (non salvare)\",\n    \"RELAUNCH_CHROME\"                   : \"Riavvia Google Chrome\",\n    \"ABOUT\"                             : \"Informazioni\",\n    \"CLOSE\"                             : \"Chiudi\",\n    \"ABOUT_TEXT_LINE1\"                  : \"Release {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"        : \"build timestamp: \",\n    \"ABOUT_TEXT_LINE3\"                  : \"Avvisi, termini e condizioni circa i software di terze parti raggiungibili all’indirizzo <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> incorporati come riferimento.\",\n    \"ABOUT_TEXT_LINE4\"                  : \"Documentazione e codice sorgente sono disponibili all’indirizzo <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Fatto con \\u2764 e JavaScript da:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Molte persone (abbiamo qualche difficoltà a caricare questi dati ora).\",\n    \"ABOUT_TEXT_MDN_DOCS\"               : \"I loghi di 'MDN Docs'e 'MDN' sono sotto licenza Creative Common Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"       : \"È disponibile una nuova versione di {APP_NAME}! Clicca qui per i dettagli.\",\n    \"UPDATE_AVAILABLE_TITLE\"            : \"Aggiornamento Disponibile\",\n    \"UPDATE_MESSAGE\"                    : \"Hey, è disponibile una nuova versione di {APP_NAME}. Nuove caratteristiche:\",\n    \"GET_IT_NOW\"                        : \"Installalo ora!\",\n    \"PROJECT_SETTINGS_TITLE\"            : \"Impostazioni del progetto per: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"          : \"URL di base per Anteprima Live\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"     : \"Per utilizzare un server locale, immettere un URL come http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"    : \"Il protocollo {0} non è supportato da Anteprima Live&mdash;utilizzare http:// o https:// .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"   : \"L’URL di base non può contenere parametri di ricerca come \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"     : \"L’URL di base non può contenere hash come \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"        : \"I caratteri speciali come '{0}' devono essere %-encodate.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"       : \"Trovato un carattere sconosciuto durante l'analisi del URL di base\",\n    \n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                 : \"<em>Aprire un file mentre questo riquadro è attivo</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"              : \"Spostare questa vista nel riquadro {0}\",\n   \n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Tema attuale\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Utilizzare le barre di scorrimento a tema\",\n    \"FONT_SIZE\"                            : \"Dimensioni carattere\",\n    \"FONT_FAMILY\"                          : \"Tipo di carattere\",\n    \"THEMES_SETTINGS\"                      : \"Impostazioni Temi\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Nuova regola\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Installa\",\n    \"UPDATE\"                               : \"Aggiorna\",\n    \"REMOVE\"                               : \"Rimuovi\",\n    \"OVERWRITE\"                            : \"Sovrascrivi\",\n    \"DISABLE\"                              : \"Disabilita\",\n    \"ENABLE\"                               : \"Abilita\",\n    \"CANT_REMOVE_DEV\"                      : \"Le estensioni nella cartella \\\"dev\\\" devono essere eliminate manualmente.\",\n    \"CANT_UPDATE\"                          : \"L’aggiornamento non è compatibile con questa versione di {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Le estensioni nella cartella \\\"dev\\\" non possono essere aggiornate automaticamente.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Installa Estensione\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Aggiorna Estensione\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Indirizzo URL dell’estensione\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Indirizzo URL dell’archivio contenente l’estensione o del repo GitHub\",\n    \"INSTALLING_FROM\"                      : \"Installazione dell’estensione da {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installazione andata a buon fine!\",\n    \"INSTALL_FAILED\"                       : \"Installazione fallita.\",\n    \"CANCELING_INSTALL\"                    : \"Cancellazione\\u2026\",\n    \"CANCELING_HUNG\"                       : \"L’arresto dell’installazione sta prendendo molto tempo. Potrebbe essersi verificato un errore interno.\",\n    \"INSTALL_CANCELED\"                     : \"Installazione cancellata.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Visualizza descrizione completa\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Visualizza descrizione ridotta\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Il contenuto scaricato non è un file zip valido.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Il file package.json non è valido (errore: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Il file package.json non specifica un nome per il pacchetto.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} è un nome non valido per il pacchetto.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Il file package.json non specifica una versione.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Il numero di versione ({0}) del pacchetto non è valida.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"La compatibilità di {APP_NAME} string ({0}) è invalida.\",\n    \"DISALLOWED_WORDS\"                     : \"Le parole ({1}) non sono ammesse nel campo {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"L’estensione non è compatibile con questa versione di {APP_NAME}. Verrà installata nella cartella delle estensioni disabilitate.\",\n    \"MISSING_MAIN\"                         : \"Il pacchetto non contiene il file main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"L’installazione di questo pacchetto sovrascriverà una versione installata in precedenza. Sovrascrivere la vecchia versione?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Questo pacchetto è la stessa versione di quello già installato. Sovrascrivere l’installazione esistente?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Questo pacchetto è alla versione {0}, che è più vecchia di quella installata ({1}). Sovrascrivere l’installazione esistente?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Errore interno: ID di download già in uso.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Impossibile connettersi al server.\",\n    \"BAD_HTTP_STATUS\"                      : \"File non trovato sul server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Impossibile salvare il file scaricato nei file temporanei.\",\n    \"ERROR_LOADING\"                        : \"Questa estensione ha incontrato un errore durante l’avvio.\",\n    \"MALFORMED_URL\"                        : \"L’indirizzo URL non è valido. Controlla di averlo inserito correttamente.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"L’indirizzo URL dev’essere di tipo http o https.\",\n    \"UNKNOWN_ERROR\"                        : \"Errore interno sconosciuto.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Manager delle Estensioni\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Impossibile accedere al registro delle estensioni. Riprova più tardi.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Trascina il file .zip qui o\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Rilascia il file .zip per l'installazione\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Installazione/Aggiornamento interrotto a causa dei seguenti errori:\",\n    \"INSTALL_FROM_URL\"                     : \"Installa dall’indirizzo URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Convalida\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autore\",\n    \"EXTENSION_DATE\"                       : \"Data\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Questa estensione richiede una versione di {APP_NAME} più recente.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Questa estensione al momento può funzionare solo con versioni di {APP_NAME} più vecchie.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"La versione {0} di questa estensione richiede una versione di {APP_NAME} più recente.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"La versione {0} di questa estensione richiede una versione di {APP_NAME} più vecchia. Ma puoi comunque installare una versione più recente {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Nessuna descrizione\",\n    \"EXTENSION_MORE_INFO\"                  : \"Più info...\",\n    \"EXTENSION_ERROR\"                      : \"Errore di estensione\",\n    \"EXTENSION_KEYWORDS\"                   : \"Parole chiave\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Tradotto in {0} lingue, inclusa la tua\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Tradotto in {0} lingue\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Questa estensione è stata tradotta in queste lingue: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Installata\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Questo aggiornamento dell’estensione è stato scaricato e sarà installato dopo il riavvio di {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Cerca\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Altro\",\n    \"BROWSE_EXTENSIONS\"                    : \"Naviga le Estensioni\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Rimuovi Estensione\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Impossibile rimuovere una o più estensioni: {0}. {APP_NAME} si riavvierà comunque.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Aggiorna Estensioni\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Impossibile aggiornare una o più estensioni: {0}. {APP_NAME} si riavvierà comunque.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Disabilita estensione\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Impossibile disattivare una o più estensioni: {0}. {APP_NAME} si riavvierà comunque.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Marcato per la rimozione\",\n    \"UNDO_REMOVE\"                          : \"Annulla\",\n    \"MARKED_FOR_UPDATE\"                    : \"Marcato per l’aggiornamento\",\n    \"UNDO_UPDATE\"                          : \"Annulla\",\n    \"MARKED_FOR_DISABLING\"                 : \"Marcato per la disabilitazione\",\n    \"UNDO_DISABLE\"                         : \"Annulla\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Cambia Estensioni\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Per aggiornare o rimuovere le estensioni marcate, {APP_NAME} dovrà riavviarsi. Ti verrà chiesto di salvare le modifiche apportate.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Rimuovi le estensioni e riavvia\",\n    \"CHANGE_AND_RELOAD\"                    : \"Modifica le estensioni e riavvia\",\n    \"UPDATE_AND_RELOAD\"                    : \"Aggiorna Rimuovi le estensioni e riavvia\",\n    \"DISABLE_AND_RELOAD\"                   : \"Disabilita le estensioni e riavvia\",\n    \"PROCESSING_EXTENSIONS\"                : \"Processo le modifiche alle estensioni\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Impossibile rimuovere l’estensione {0}. Non era installata.\",\n    \"NO_EXTENSIONS\"                        : \"Nessuna estensione ancora installata.<br />Clicca nel tab delle Disponibili per iniziare.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nessuna estensione soddisfa la tua ricerca.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"NOTA: Queste estensioni possono provenire da autori diversi da {APP_NAME}. Le estensioni non vengono riviste e dispongono di privilegi locali completi. Fai attenzione quando installi le estensioni da sorgenti sconosciute.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Installate\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Disponibili\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Temi\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Aggiornamenti\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Nessuna corrispondenza disponibile.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Tutte le corrispondenze sono crollate. Espandere i file elencati a destra per vedere le corrispondenze\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Non ci sono regole CSS esistenti che corrispondano alla tua selezione.<br />Clicca \\\"Nuova Regola\\\" per crearne una.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Non ci sono fogli di stile nel tuo progetto.<br />Creane uno per aggiungere regole CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"il più grande\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pixel\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"Errori\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Mostra strumenti per gli sviluppatori\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Riavvia con le Estensioni\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Riavvia senza Estensioni\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nuova finestra di {APP_NAME}\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Aggiungi linea di comando di Brackets\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Cambia la lingua\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Esegui i test\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Mostra dati sulla performance\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Abilita Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Registra i Log Node State nella Console\",\n    \"CMD_RESTART_NODE\"                          : \"Riavvia Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Mostra errori nella barra di stato\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Apri {APP_NAME} sorgente\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"Scorciatoia da riga di comando di {APP_NAME}\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Si è verificato un errore durante la creazione della scorciatoia da riga di comando. Per favore, leggi la <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>guida della linea di comando</a> per la risoluzione dei problemi.<br/><br/>Motivo: \",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Impossibile rimuovere collegamento simbolico esistente {APP_NAME} a <code>/usr/local/bin.</code>\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Impossibile creare la cartella <code>/usr/local/bin</code>.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Impossibile creare il collegamento simbolico <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Errore interno.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"La scorciatoia da riga di comando non è supportato su questo OS.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Successo! Ora si può facilmente avviare {APP_NAME} dalla riga di comando eseguendo: <code>brackets myFile.txt</code> per aprire un file o <code>brackets myFolder</code> per aprire un progetto.<br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Altre informazioni sulla riga di comando di {APP_NAME}</a>.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Cambia la lingua\",\n    \"LANGUAGE_MESSAGE\"                          : \"Lingua:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Riavvia {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Annulla\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Preferita dal sistema\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Preferenze Health Data\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"Brackets Health Report\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Sì, mi piacerebbe condividere informazioni su come uso Brackets.\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Al fine di migliorare Brackets stiamo implementando un nuovo Health Report che invia <strong>anonimo</strong> dati a Adobe su come usi Brackets. Questo rapporto aiuterà il gruppo di sviluppo e gli sviluppatori di estensioni sulle caratteristiche prioritarie, bug, problemi di usabilità e reperibilità.<br><br>È possibile visualizzare i dati inviati così come cambiare la vostra preferenza in qualsiasi momento visitando <strong>Help->Health Data Report</strong>. Ulteriori informazioni su Brackets Health Report e sullo stato <a href='https://github.com/adobe/brackets/wiki/Health-Data'>nella pagina wiki</a>.\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"Anteprima Health Data\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Al fine di migliorare {APP_NAME}, periodicamente invieremo limitate statistiche <strong>anonime</strong> a Adobe su come usi {APP_NAME}. Queste informazioni aiutano ad assegnare una priorità ad alcune caratteristiche, a trovare i bug e a individuare problemi di usabilità. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Clicca qui per saperne di più su {APP_NAME} Health Report</a> e su come si avvantaggia la comunità di {APP_NAME} mantenendo la tua privacy protetta.</p><p>Ecco un'anteprima dei dati che saranno inviati nella tua prossima Health Report (<em>se</em> abilitato):</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tempo\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progresso\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Sposta punto selezionato<br><kbd class='text'>Maiuscola</kbd> Muovi di dieci unità\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Aumenta o diminuisci<br><kbd>←</kbd><kbd>→</kbd> 'Inizio' o 'Fine'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Il vecchio valore <code>{0}</code> non è valido, per cui la funzione visualizzata è stato cambiato in <code>{1}</code>. Il documento sarà aggiornato con la prima modifica.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Colore corrente\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Colore originale\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Formato RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Formato Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Formato HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Usato {1} volta)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Usato {1} volte)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Passa alla definizione\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Mostra suggerimenti sul parametro\",\n    \"NO_ARGUMENTS\"                              : \"<nessun parametro>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problema Conseguente File JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets ha dei problemi nel elaborare il processo <span class='dialog-filename'>{0}</span>.<br><br> Questo file non sarà più elaborato per i Suggerimenti sul codice, Vai a definizione o Modifica rapida. Per riattivare questo file , aprire <code>.brackets.json</code> nel progetto e modificare <code>jscodehints.detectedExclusions</code>.<br><br>Questo è probabilmente un bug di Brackets. Se è possibile fornire una copia di questo file, <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>un bug</a> con un collegamento al file denominato qui.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Quick Edit al passaggio del mouse\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Progetti recenti\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Leggi tutto\",\n\n     // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Comprimi tutto\",\n    \"EXPAND_ALL\"                    : \"Espandi tutto\",\n    \"COLLAPSE_CURRENT\"              : \"Comprimi attuale\",\n    \"EXPAND_CURRENT\"                : \"Espandi attuale\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true per chiudere automaticamente le parentesi tonde, quadre e graffe\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false per rimuovere le 'Chiudi tutto al di sopra' dal menu dello spazio di lavoro\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false per rimuovere le 'Chiudi tutto al di sotto' dal menu dello spazio di lavoro\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false per rimuovere le 'Chiudi tutto il resto' dal menu dello spazio di lavoro\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Imposta le opzioni dei tag di chiusura\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Una serie di tag che non dovrebbe essere chiusa automaticamente\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Chiudi quando viene digitato > nei tag di apertura\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Chiudi quando viene digitato / nei tag di chiusura\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Una serie di tag nei quali inserire una riga vuota quando aperti\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true per mostrare le icone per comprimere il codice anche a livello di indentazione\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true per consentire il raggruppamento del codice\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true per mostrare le icone per comprimere il codice solo quando si sposta il mouse sulla barra di sinistra\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limita il numero di livelli da comprimere quando si usa il comando Comprimi tutto\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Il minimo numero di righe necessario affinché appaia l'icona per comprimere il codice\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true per ricordare quali parti di codice sono compresse quando chiudi o riapri un file od un progetto\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"true per attivare il raggruppamento del codice sul testo selezionato nell'editor\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Abilita/Disabilita i suggerimenti per gli attributi HTML\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Abilita/Disabilita i suggerimenti delle proprietà CSS/LESS/SCSS\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Abilita/Disabilita i suggerimenti del codice JavaScript\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Abilita/Disabilita i dettagli sul tipo delle variabili nei suggerimenti del codice JavaScript\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Abilita/Disabilita i suggerimenti del codice delle Preferenze\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Abilita/Disabilita i suggerimenti delle entità HTML\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Abilita/Disabilita i suggerimenti del codice SVG\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Abilita/Disabilita i suggerimenti dei tag HTML\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Abilita/Disabilita i suggerimenti degli URL in HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Abilita/Disabilita la funzionalità Drag & Drop\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Abilita il tracciamento di Health Data\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Abilita l'evidenziazione automatica delle stringhe corrispondenti in tutto il documento\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Evidenziare tutte le stringhe che corrispondono al token sul quale si trova il cursore (non è necessaria nessuna selezione)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Evidenziare solo quando la selezione è un token completo\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true per inserire il codice suggerimento suggerito alla pressione del tasto TAB\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true per non mostrare automaticamente i suggerimenti del codice JavaScript quando viene digitato '.'\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Un oggetto con le opzioni predefinite per JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true per consentire espressioni di assegnamento al di fuori delle dichiarazioni\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true per consentire gli operatori bit a bit\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true se le variabili globali dei browser devono essere abilitate\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true per consentire gli idiomi di Google Closure\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true per consentire l'istruzione continue\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true se le variabili globali di CouchDB devono essere abilitate\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true per consentire l'istruzione debugger\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true se le variabili globali dei browser utili in fase di sviluppo devono essere abilitate\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true per consentire == e !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true se le variabili globali di EcmaScript 6 devono essere abilitate\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true per consentire eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true per consentire i cicli for...in non filtrati\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Il numero di spazi usati per l'indentazione\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Il massimo numero di avvertimenti\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Il massimo numero di caratteri in una linea\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true per consentire costruttori in minuscolo\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true se le variabili globali di Node.js devono essere abilitate\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true per consentire gli underscore all'inizio e alla fine dei nomi\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true per fermarsi al primo errore\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true per consentire ++ e --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true per consentire . e [^...] nelle espressioni regolari\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true se le variabili globali di Rhino devono essere abilitate\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true per consentire di omettere `use strict`\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true per consentire pratiche stupide\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true per consentire il riferimento agli elementi degli oggetti utilizzando le parentesi quadre\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true per consentire commenti TODO\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true per consentire parametri non utilizzati\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true per consentire più di un'espressione var per funzione\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true per non controllare l'indentazione\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Impostazioni specifiche dei linguaggi\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Ulteriori mappature dei linguaggi corrispondenti alle estensioni\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Ulteriori mappature dei linguaggi corrispondenti ai nomi dei file\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true per abilitare il controllo del codice\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Il tempo in millisecondi dopo il quale il controllo del codice viene interrotto\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Un array di linter da eseguire per primi\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true per abilitare l'Anteprima Live nel tuo browser preferito (sperimentale)\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true per abilitare soltanto i linter specificati in linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Massimo numero di suggerimenti visualizzati alla volta\",\n    \"DESCRIPTION_PATH\"                               : \"Impostazioni specifiche per un percorso\",\n    \"DESCRIPTION_PROXY\"                              : \"L'URL del server proxy utilizzato per installare le estensioni\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true per attivare lo scorrimento oltre la fine del documento\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false per disattivare tutti i suggerimenti sul codice\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Mantiene il cursore lampeggiante quando del testo è selezionato\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true per mostrare i numeri delle righe a sinistra del codice\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Indenta automaticamente il codice quando si crea un nuovo blocco\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false per disattivare il comportamento soft tab\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true per mostrare prima le cartelle nell'albero dei file\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Numero di spazi da utilizzare per l'indentazione\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Numero della porta da usare per l'Anteprima Live\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true per evidenziare la linea dove si trova il cursore\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Numero di spazi da visualizzare per le tabulazioni\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true utilizzare le tabulazioni al posto degli spazi\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true per generare caratteri maiuscoli nei colori esadecimali nell'editor dei colori inline\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Mostra su più linee le righe più larghe dell'editor\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Un elenco dei file che causano problemi a Tern\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Il tempo in millisecondi dopo il quale Tern viene interrotto mentre cerca di leggere un file\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true per mostrare gli errori nella barra di stato\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true per abilitare Quick View\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true per visualizzare le anteprime delle immagini anche se non hanno un'estensione\",\n    \"DESCRIPTION_THEME\"                              : \"Seleziona un tema di {APP_NAME}\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true per consentire le barre di scorrimento su misura\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true per non mostrare il pannello del controllo del codice\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Modifica il font usato in {APP_NAME}\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Modifica le dimensioni dei caratteri; ad esempio 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"true per attivare la ricerca basata su Node\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"true per attivare la ricerca immediata\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Solo per Mac: \\\"subpixel-antialias\\\" per consentire sub-pixel antialiasing o \\\"antialias\\\" per la scala dei grigi antialiasing\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false per disabilitare l'apertura delle preferenze in Split View\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false per aprire le preferenze nel pannello di sinistra / superiore\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"true per chiudere la finestra quando l'ultimo file che contiene viene chiuso tramite il pulsante di chiusura\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Alterna i pulsanti chiudi e flip-view nell'header\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Questo è un file non modificabile che contiene le preferenze supportate da\\n * {APP_NAME}.\\n * Basati su questo file per modificare le preferenze del file\\n * \\\"brackets.json\\\" aperto nell'altra scheda.\\n * Per ulteriori informazioni sull'utilizzo delle preferenze vedere\\n * https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Default\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"true per abilitare il codice in modalità senza distrazioni e nascondere tutti gli altri elementi dell'interfaccia utente di {APP_NAME}\"\n});\n\n/* Last translation of: fcd2e98ef35c110e00aebfbb6d3c3816e5156552*/\n\n"
  },
  {
    "path": "src/nls/it/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"it/Primi passi\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_it/\",\n    \"MDN_DOCS_LICENSE\" : \"http://creativecommons.org/licenses/by-sa/2.5/deed.it\"\n});\n"
  },
  {
    "path": "src/nls/ja/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n\t\"GENERIC_ERROR\": \"(エラー {0})\",\n\t\"NOT_FOUND_ERR\": \"ファイルまたはディレクトリが見つかりません。\",\n\t\"NOT_READABLE_ERR\": \"ファイルまたはディレクトリを読み込めませんでした。\",\n\t\"EXCEEDS_MAX_FILE_SIZE\": \"{0} MB を超えるサイズのファイルは {APP_NAME} で開くことはできません。\",\n\t\"NO_MODIFICATION_ALLOWED_ERR\": \"対象ディレクトリは変更できません。\",\n\t\"NO_MODIFICATION_ALLOWED_ERR_FILE\": \"ファイルを変更する権限がありません。\",\n\t\"CONTENTS_MODIFIED_ERR\": \"このファイルは {APP_NAME} 以外で変更されています。\",\n\t\"UNSUPPORTED_ENCODING_ERR\": \"不明なエンコード形式\",\n\t\"ENCODE_FILE_FAILED_ERR\": \"{APP_NAME} でファイルの内容をエンコードすることができませんでした。\",\n\t\"DECODE_FILE_FAILED_ERR\": \"{APP_NAME} でファイルの内容をデコードすることができませんでした。\",\n\t\"UNSUPPORTED_UTF16_ENCODING_ERR\": \"{APP_NAME} は現在 UTF-16 でエンコードされたテキストファイルに対応していません。\",\n\t\"FILE_EXISTS_ERR\": \"ファイルまたはディレクトリは既に存在しています。\",\n\t\"FILE\": \"ファイル\",\n\t\"FILE_TITLE\": \"ファイル\",\n\t\"DIRECTORY\": \"ディレクトリ\",\n\t\"DIRECTORY_TITLE\": \"ディレクトリ\",\n\t\"DIRECTORY_NAMES_LEDE\": \"ディレクトリ名\",\n\t\"FILENAMES_LEDE\": \"ファイル名\",\n\t\"FILENAME\": \"ファイル名\",\n\t\"DIRECTORY_NAME\": \"ディレクトリ名\",\n\n    // Project error strings\n\t\"ERROR_LOADING_PROJECT\": \"プロジェクトを読み込む際にエラーが発生しました。\",\n\t\"OPEN_DIALOG_ERROR\": \"「ファイルを開く」ダイアログを表示する際にエラーが発生しました。(エラー {0})\",\n\t\"REQUEST_NATIVE_FILE_SYSTEM_ERROR\": \"ディレクトリ <span class='dialog-filename'>{0}</span> を読み込む際にエラーが発生しました。(エラー {1})\",\n\t\"READ_DIRECTORY_ENTRIES_ERROR\": \"ディレクトリ <span class='dialog-filename'>{0}</span> の内容を読み込む際にエラーが発生しました。(エラー {1})\",\n\n    // File open/save error string\n\t\"ERROR_OPENING_FILE_TITLE\": \"ファイルを開く際にエラーが発生しました。\",\n\t\"ERROR_OPENING_FILE\": \"ファイル <span class='dialog-filename'>{0}</span> を開く際にエラーが発生しました。{1}\",\n\t\"ERROR_OPENING_FILES\": \"次のファイルを開くときにエラーが発生しました :\",\n\t\"ERROR_RELOADING_FILE_TITLE\": \"ディスクから変更を再読み込みする際にエラーが発生しました。\",\n\t\"ERROR_RELOADING_FILE\": \"ファイル <span class='dialog-filename'>{0}</span> を再読込する際にエラーが発生しました。{1}\",\n\t\"ERROR_SAVING_FILE_TITLE\": \"ファイルを保存する際にエラーが発生しました。\",\n\t\"ERROR_SAVING_FILE\": \"ファイル <span class='dialog-filename'>{0}</span> を保存する際にエラーが発生しました。{1}\",\n\t\"ERROR_RENAMING_FILE_TITLE\": \"{0} の名前を変更する際にエラーが発生しました。\",\n\t\"ERROR_RENAMING_FILE\": \"{2} <span class='dialog-filename'>{0}</span> の名前を変更する際にエラーが発生しました。{1}\",\n\t\"ERROR_RENAMING_NOT_IN_PROJECT\": \"ファイルまたはディレクトリが、現在開いているプロジェクトの一部ではありません。現時点で、プロジェクトファイルの名前のみを変更できます。\",\n\t\"ERROR_MOVING_FILE_TITLE\": \"{0}の移動エラー\",\n\t\"ERROR_MOVING_FILE\": \"{2} <span class='dialog-filename'>{0}</span> を移動する際にエラーが発生しました。{1}\",\n\t\"ERROR_MOVING_NOT_IN_PROJECT\": \"現在のプロジェクトに含まれないため、ファイル/フォルダーを移動することはできません。\",\n\t\"ERROR_DELETING_FILE_TITLE\": \"{0} を削除する際にエラーが発生しました。\",\n\t\"ERROR_DELETING_FILE\": \"{2} <span class='dialog-filename'>{0}</span> を削除する際にエラーが発生しました。{1}\",\n\t\"INVALID_FILENAME_TITLE\": \"無効な{0}\",\n\t\"INVALID_FILENAME_MESSAGE\": \"{0}にはシステムのすべての予約語、末尾のピリオド (.)、および次の文字を含めることはできません : <code class='emphasized'>{1}</code>\",\n\t\"ENTRY_WITH_SAME_NAME_EXISTS\": \"<span class='dialog-filename'>{0}</span> という名前のファイルまたはディレクトリは既に存在します。\",\n\t\"ERROR_CREATING_FILE_TITLE\": \"{0} を作成する際にエラーが発生しました。\",\n\t\"ERROR_CREATING_FILE\": \"{0} <span class='dialog-filename'>{1}</span> を作成する際にエラーが発生しました。{2}\",\n\t\"ERROR_MIXED_DRAGDROP\": \"他のファイルを開いている間はフォルダーを開くことはできません。\",\n\n    // User key map error strings\n\t\"ERROR_KEYMAP_TITLE\": \"ユーザーキーマップを読み込む際にエラーが発生しました\",\n\t\"ERROR_KEYMAP_CORRUPT\": \"キーマップファイルが有効な JSON ではありません。ファイルが開かれます。フォーマットを修正してください。\",\n\t\"ERROR_LOADING_KEYMAP\": \"キーマップファイルが UTF-8 でエンコードされた有効なテキストファイルではないため、読み込めません\",\n\t\"ERROR_RESTRICTED_COMMANDS\": \"次のコマンドにショートカットを割り当て直すことはできません : {0}\",\n\t\"ERROR_RESTRICTED_SHORTCUTS\": \"次のショートカットを割り当て直すことはできません : {0}\",\n\t\"ERROR_MULTIPLE_SHORTCUTS\": \"次のコマンドに複数のショートカットを割り当て直しています : {0}\",\n\t\"ERROR_DUPLICATE_SHORTCUTS\": \"次のショートカットの複数のバインディングがあります : {0}\",\n\t\"ERROR_INVALID_SHORTCUTS\": \"次のショートカットは無効です : {0}\",\n\t\"ERROR_NONEXISTENT_COMMANDS\": \"存在しないコマンドにショートカットを割り当てています : {0}\",\n\n    // Application preferences corrupt error strings\n\t\"ERROR_PREFS_CORRUPT_TITLE\": \"環境設定を読み込む際にエラーが発生しました。\",\n\t\"ERROR_PREFS_CORRUPT\": \"環境設定ファイルが有効な JSON ではありません。ファイルが開かれます。フォーマットを修正してください。変更を反映するには、{APP_NAME} を再起動する必要があります。\",\n\t\"ERROR_PROJ_PREFS_CORRUPT\": \"プロジェクトの環境設定ファイルが有効な JSON ではありません。ファイルが開かれます。フォーマットを修正してください。変更を反映するには、プロジェクトを再読み込みする必要があります。\",\n\n    // Application error strings\n\t\"ERROR_IN_BROWSER_TITLE\": \"{APP_NAME} は、まだブラウザー上で実行されていません。\",\n\t\"ERROR_IN_BROWSER\": \"{APP_NAME} は HTML で構築されていますが、デスクトップアプリとして実行することで、ローカルファイルを編集することができます。{APP_NAME} を実行するために、<b>github.com/adobe/brackets-shell</b> リポジトリのアプリケーションシェルを使用してください。\",\n\n    // ProjectManager max files error string\n\t\"ERROR_MAX_FILES_TITLE\": \"ファイルのインデックス時にエラーが発生しました。\",\n\t\"ERROR_MAX_FILES\": \"このプロジェクトには 30,000 個以上のファイルが含まれています。複数のファイルを操作する機能が無効になるか、プロジェクトが空であるかのように動作します。<a href='https://github.com/adobe/brackets/wiki/Large-Projects'>大きいプロジェクトの操作方法の詳細を表示</a>。\",\n\n    // Live Preview error strings\n\t\"ERROR_LAUNCHING_BROWSER_TITLE\": \"ブラウザーの起動時にエラーが発生しました。\",\n\t\"ERROR_CANT_FIND_CHROME\": \"Google Chrome ブラウザーが見つかりません。インストールされていることを確認してください。\",\n\t\"ERROR_LAUNCHING_BROWSER\": \"ブラウザーの起動時にエラーが発生しました。(エラー {0})\",\n\n\t\"LIVE_DEVELOPMENT_ERROR_TITLE\": \"ライブプレビューのエラーが発生しました。\",\n\t\"LIVE_DEVELOPMENT_RELAUNCH_TITLE\": \"ブラウザーに接続しています\",\n\t\"LIVE_DEVELOPMENT_ERROR_MESSAGE\": \"ライブプレビューに接続するには、リモートデバッグを有効にして Chrome を再起動する必要があります。<br /><br />Chrome を再起動してリモートデバッグを有効にしますか？<br /><br />\",\n\t\"LIVE_DEV_LOADING_ERROR_MESSAGE\": \"ライブプレビューページを読み込めません。\",\n\t\"LIVE_DEV_NEED_HTML_MESSAGE\": \"ライブプレビューを起動するには、HTML ファイルを開くか、index.html ファイルがプロジェクトに含まれていることを確認してください。\",\n\t\"LIVE_DEV_NEED_BASEURL_MESSAGE\": \"サーバー側ファイルでライブプレビューを起動するには、このプロジェクトのベース URL を指定する必要があります。\",\n\t\"LIVE_DEV_SERVER_NOT_READY_MESSAGE\": \"ファイルのライブプレビューで使用する HTTP サーバーの起動時にエラーが発生しました。もう一度実行してください。\",\n\t\"LIVE_DEVELOPMENT_INFO_TITLE\": \"ライブプレビューへようこそ\",\n\t\"LIVE_DEVELOPMENT_INFO_MESSAGE\": \"ライブプレビューにより {APP_NAME} がブラウザーに接続しました。ブラウザーで HTML ファイルのプレビューが起動し、コードを編集すると直ちにプレビューが更新されます。<br /><br />この初期バージョンの {APP_NAME} では、<strong>Google Chrome</strong> でのみライブプレビューが機能し、<strong>CSS または HTML ファイル</strong>の編集時にのみライブ更新が行われます。 JavaScript ファイルへの変更は、保存時に自動的にリロードされます。<br /><br />(このメッセージは一度しか表示されません。)\",\n\t\"LIVE_DEVELOPMENT_TROUBLESHOOTING\": \"詳しくは、<a href='{0}' title='{0}'>ライブプレビューの接続エラーに関するトラブルシューティング</a>を参照してください。\",\n\n\t\"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\": \"ライブプレビュー\",\n\t\"LIVE_DEV_STATUS_TIP_PROGRESS1\": \"ライブプレビュー : 接続中\\u2026\",\n\t\"LIVE_DEV_STATUS_TIP_PROGRESS2\": \"ライブプレビュー : 初期化中\\u2026\",\n\t\"LIVE_DEV_STATUS_TIP_CONNECTED\": \"ライブプレビューの接続を切断します\",\n\t\"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\": \"ライブプレビュー (ファイルを保存して更新)\",\n\t\"LIVE_DEV_STATUS_TIP_SYNC_ERROR\": \"ライブプレビュー (シンタックスエラーのため更新されません)\",\n\n\t\"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\": \"ブラウザーの開発ツールが開いているため、ライブプレビューはキャンセルされました\",\n\t\"LIVE_DEV_DETACHED_TARGET_CLOSED\": \"ブラウザーでページが閉じられたため、ライブプレビューはキャンセルされました\",\n\t\"LIVE_DEV_NAVIGATED_AWAY\": \"ブラウザーで現在のプロジェクトに含まれないページに移動したため、ライブプレビューはキャンセルされました\",\n\t\"LIVE_DEV_CLOSED_UNKNOWN_REASON\": \"不明な原因 ({0}) によってライブプレビューはキャンセルされました\",\n\n\t\"SAVE_CLOSE_TITLE\": \"変更を保存\",\n\t\"SAVE_CLOSE_MESSAGE\": \"文書 <span class='dialog-filename'>{0}</span> に加えた変更を保存しますか？\",\n\t\"SAVE_CLOSE_MULTI_MESSAGE\": \"以下のファイルに対する変更を保存しますか？\",\n\t\"EXT_MODIFIED_TITLE\": \"外部で変更されました。\",\n\t\"CONFIRM_DELETE_TITLE\": \"削除を確認\",\n\t\"CONFIRM_FILE_DELETE\": \"ファイル <span class='dialog-filename'>{0}</span> を削除してもよろしいですか？\",\n\t\"CONFIRM_FOLDER_DELETE\": \"<span class='dialog-filename'>{0}</span> フォルダーを削除してもよろしいですか？\",\n\t\"FILE_DELETED_TITLE\": \"ファイルは削除されました\",\n\t\"EXT_MODIFIED_WARNING\": \"<span class='dialog-filename'>{0}</span> は {APP_NAME} 外のディスク上で変更されています。<br /><br />ファイルを保存し、これらの変更を上書きしますか？\",\n\t\"EXT_MODIFIED_MESSAGE\": \"<span class='dialog-filename'>{0}</span> は {APP_NAME} 外のディスク上で変更されていますが、{APP_NAME} 内にも保存されていない変更があります。<br /><br />どちらのバージョンを保持しますか？\",\n\t\"EXT_DELETED_MESSAGE\": \"<span class='dialog-filename'>{0}</span> は {APP_NAME} 外のディスク上で削除されていますが、{APP_NAME} 内に保存されていない変更があります。<br /><br />変更を保持しますか？\",\n    \n    // Window unload warning messages\n\t\"WINDOW_UNLOAD_WARNING\": \"Are you sure you want to navigate to a different URL and leave Brackets?\",\n\t\"WINDOW_UNLOAD_WARNING_WITH_UNSAVED_CHANGES\": \"You have unsaved changes! Are you sure you want to navigate to a different URL and leave Brackets?\",\n\n    // Generic dialog/button labels\n\t\"DONE\": \"完了\",\n\t\"OK\": \"OK\",\n\t\"CANCEL\": \"キャンセル\",\n\t\"DONT_SAVE\": \"保存しない\",\n\t\"SAVE\": \"保存\",\n\t\"SAVE_AS\": \"名前を付けて保存\\u2026\",\n\t\"SAVE_AND_OVERWRITE\": \"上書き\",\n\t\"DELETE\": \"削除\",\n\t\"BUTTON_YES\": \"はい\",\n\t\"BUTTON_NO\": \"いいえ\",\n\n    // Find, Replace, Find in Files\n\t\"FIND_MATCH_INDEX\": \"{0} / {1}\",\n\t\"FIND_NO_RESULTS\": \"該当なし\",\n\t\"FIND_QUERY_PLACEHOLDER\": \"検索\\u2026\",\n\t\"FIND_HISTORY_MAX_COUNT\": \"検索履歴内の検索項目の最大数\",\n\t\"REPLACE_PLACEHOLDER\": \" に置換\\u2026\",\n\t\"BUTTON_REPLACE_ALL\": \"すべて置換\",\n\t\"BUTTON_REPLACE_BATCH\": \"バッチ\\u2026\",\n\t\"BUTTON_REPLACE_ALL_IN_FILES\": \"置換\\u2026\",\n\t\"BUTTON_REPLACE\": \"置換\",\n\t\"BUTTON_NEXT\": \"\\u25B6\",\n\t\"BUTTON_PREV\": \"\\u25C0\",\n\t\"BUTTON_NEXT_HINT\": \"次の候補に移動\",\n\t\"BUTTON_PREV_HINT\": \"前の候補に移動\",\n\t\"BUTTON_CASESENSITIVE_HINT\": \"大文字と小文字を区別\",\n\t\"BUTTON_REGEXP_HINT\": \"正規表現\",\n\t\"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"取り消し情報を保存せずに置換\",\n\t\"REPLACE_WITHOUT_UNDO_WARNING\": \"{0} 個を超えるファイルを変更する必要があるため、{APP_NAME} によってディスク上の開かれていないファイルが変更されます。<br />これらのファイルで行った置換は取り消しできません。\",\n\t\"BUTTON_REPLACE_WITHOUT_UNDO\": \"取り消し情報を保存せずに置換\",\n\n\t\"OPEN_FILE\": \"ファイルを開く\",\n\t\"SAVE_FILE_AS\": \"ファイルを保存\",\n\t\"CHOOSE_FOLDER\": \"フォルダーを選択\",\n\n\t\"RELEASE_NOTES\": \"リリースノート\",\n\t\"NO_UPDATE_TITLE\": \"最新バージョンです。\",\n\t\"NO_UPDATE_MESSAGE\": \"{APP_NAME} の最新バージョンを実行中です。\",\n\n    // Find and Replace\n\t\"FIND_REPLACE_TITLE_LABEL\": \"置換対象\",\n\t\"FIND_REPLACE_TITLE_WITH\": \"置換後の文字列\",\n\t\"FIND_TITLE_LABEL\": \"検索結果\",\n\t\"FIND_TITLE_SUMMARY\": \"&mdash; {0} {1} {2} ({3})\",\n\n    // Find in Files\n\t\"FIND_NUM_FILES\": \"{0} {1}\",\n\t\"FIND_IN_FILES_SCOPED\": \"<span class='dialog-filename'>{0}</span> 内\",\n\t\"FIND_IN_FILES_NO_SCOPE\": \"プロジェクト内\",\n\t\"FIND_IN_FILES_ZERO_FILES\": \"フィルターは {0}の全ファイルを除外します\",\n\t\"FIND_IN_FILES_FILE\": \"ファイル\",\n\t\"FIND_IN_FILES_FILES\": \"ファイル\",\n\t\"FIND_IN_FILES_MATCH\": \"が見つかりました\",\n\t\"FIND_IN_FILES_MATCHES\": \"件見つかりました\",\n\t\"FIND_IN_FILES_MORE_THAN\": \"以上\",\n\t\"FIND_IN_FILES_PAGING\": \"{0}&mdash;{1}\",\n\t\"FIND_IN_FILES_FILE_PATH\": \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n\t\"FIND_IN_FILES_EXPAND_COLLAPSE\": \"Ctrl / Command キーをクリックしてすべて展開 / 折りたたみ\",\n\t\"FIND_IN_FILES_INDEXING\": \"クイック検索のインデックスを作成中\\u2026\",\n\t\"REPLACE_IN_FILES_ERRORS_TITLE\": \"置換エラー\",\n\t\"REPLACE_IN_FILES_ERRORS\": \"次のファイルは検索の後で変更されているか、書き込むことができないため、変更されていません。\",\n\n\t\"ERROR_FETCHING_UPDATE_INFO_TITLE\": \"更新情報を取得する際にエラーが発生しました。\",\n\t\"ERROR_FETCHING_UPDATE_INFO_MSG\": \"サーバーから最新の更新情報を取得する際にエラーが発生しました。インターネット接続を確認してリトライしてください。\",\n\n    // File exclusion filters\n\t\"NEW_FILE_FILTER\": \"新規除外セット\\u2026\",\n\t\"CLEAR_FILE_FILTER\": \"ファイルを除外しない\",\n\t\"NO_FILE_FILTER\": \"除外されたファイルはありません\",\n\t\"EXCLUDE_FILE_FILTER\": \"{0} を除外\",\n\t\"EDIT_FILE_FILTER\": \"編集\\u2026\",\n\t\"FILE_FILTER_DIALOG\": \"除外セットを編集\",\n\t\"FILE_FILTER_INSTRUCTIONS\": \"次の文字列やサブストリング、または<a href='{0}' title='{0}'>ワイルドカード</a>のいずれかに一致するファイルおよびフォルダーを除外します。各文字列を新しい行に入力してください。\",\n\t\"FILTER_NAME_PLACEHOLDER\": \"この除外セットに名前を付ける (オプション)\",\n\t\"FILTER_NAME_REMAINING\": \"残り {0} 文字\",\n\t\"FILE_FILTER_CLIPPED_SUFFIX\": \"さらに {0} 件\",\n\t\"FILTER_COUNTING_FILES\": \"ファイル数を確認中\\u2026\",\n\t\"FILTER_FILE_COUNT\": \"{2}の {1} ファイル中 {0} ファイルを許可\",\n\t\"FILTER_FILE_COUNT_ALL\": \"{1}の全 {0} ファイルを許可\",\n\n    // Quick Edit\n\t\"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\": \"現在のカーソル位置で行えるクイック編集はありません\",\n\t\"ERROR_CSSQUICKEDIT_BETWEENCLASSES\": \"CSS クイック編集 : カーソルを単一のクラス名に置いてください\",\n\t\"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\": \"CSS クイック編集 : 不完全なクラス属性\",\n\t\"ERROR_CSSQUICKEDIT_IDNOTFOUND\": \"CSS クイック編集 : 不完全な ID 属性\",\n\t\"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\": \"CSS クイック編集 : カーソルをタグ、クラスまたは ID に置いてください\",\n\t\"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\": \"CSS タイミング機能のクイック編集 : 無効なシンタックス\",\n\t\"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\": \"JS クイック編集 : カーソルを関数名に置いてください\",\n\n    // Quick Docs\n\t\"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\": \"現在のカーソル位置で使用できるクイックドキュメントはありません\",\n\n    /**\n     * ProjectManager\n     */\n\t\"PROJECT_LOADING\": \"読み込んでいます\\u2026\",\n\t\"UNTITLED\": \"名称未設定\",\n\t\"WORKING_FILES\": \"作業中ファイル\",\n\n    /**\n     * MainViewManager\n     */\n\t\"TOP\": \"上\",\n\t\"BOTTOM\": \"下\",\n\t\"LEFT\": \"左\",\n\t\"RIGHT\": \"右\",\n\n\t\"CMD_SPLITVIEW_NONE\": \"分割なし\",\n\t\"CMD_SPLITVIEW_VERTICAL\": \"左右分割\",\n\t\"CMD_SPLITVIEW_HORIZONTAL\": \"上下分割\",\n\t\"SPLITVIEW_MENU_TOOLTIP\": \"エディターを垂直方向 / 水平方向に分割\",\n\t\"GEAR_MENU_TOOLTIP\": \"ワーキングセットを構成\",\n\n\t\"SPLITVIEW_INFO_TITLE\": \"既に開かれています\",\n\t\"SPLITVIEW_MULTIPANE_WARNING\": \"ファイルは他のペインで既に開かれています。{APP_NAME} ではまもなく複数のペインで同じファイルを開くことが可能になる予定です。それまでは、ファイルは既に開かれているペインで表示されます。<br /><br />(このメッセージは一度しか表示されません。)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n\t\"KEYBOARD_CTRL\": \"Ctrl\",\n\t\"KEYBOARD_SHIFT\": \"Shift\",\n\t\"KEYBOARD_SPACE\": \"Space\",\n\t\"KEYBOARD_PAGE_UP\": \"上に移動\",\n\t\"KEYBOARD_PAGE_DOWN\": \"下に移動\",\n\t\"KEYBOARD_HOME\": \"ホーム\",\n\t\"KEYBOARD_END\": \"終了\",\n\t\"KEYBOARD_INSERT\": \"挿入\",\n\t\"KEYBOARD_DELETE\": \"削除\",\n\n    /**\n     * StatusBar strings\n     */\n\t\"STATUSBAR_CURSOR_POSITION\": \"行 {0}, 列 {1}\",\n\t\"STATUSBAR_SELECTION_CH_SINGULAR\": \" \\u2014 {0} 列を選択\",\n\t\"STATUSBAR_SELECTION_CH_PLURAL\": \" \\u2014 {0} 列を選択\",\n\t\"STATUSBAR_SELECTION_LINE_SINGULAR\": \" \\u2014 {0} 行を選択\",\n\t\"STATUSBAR_SELECTION_LINE_PLURAL\": \" \\u2014 {0} 行を選択\",\n\t\"STATUSBAR_SELECTION_MULTIPLE\": \" \\u2014 選択範囲 {0}\",\n\t\"STATUSBAR_INDENT_TOOLTIP_SPACES\": \"インデントをスペースに変換する\",\n\t\"STATUSBAR_INDENT_TOOLTIP_TABS\": \"インデントをタブに変換する\",\n\t\"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\": \"インデントに用いるスペースの数を変更\",\n\t\"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\": \"タブ幅を変更\",\n\t\"STATUSBAR_SPACES\": \"スペース :\",\n\t\"STATUSBAR_TAB_SIZE\": \"タブ幅 :\",\n\t\"STATUSBAR_LINE_COUNT_SINGULAR\": \"\\u2014 {0} 行\",\n\t\"STATUSBAR_LINE_COUNT_PLURAL\": \"\\u2014 {0} 行\",\n\t\"STATUSBAR_USER_EXTENSIONS_DISABLED\": \"拡張機能無効\",\n\t\"STATUSBAR_INSERT\": \"INS\",\n\t\"STATUSBAR_OVERWRITE\": \"OVR\",\n\t\"STATUSBAR_INSOVR_TOOLTIP\": \"クリックして挿入 (INS) モードと上書き (OVR) モード間のカーソルを切り替え\",\n\t\"STATUSBAR_LANG_TOOLTIP\": \"クリックしてファイルタイプを変更\",\n\t\"STATUSBAR_CODE_INSPECTION_TOOLTIP\": \"{0}。クリックしてレポートパネルを切り替えます。\",\n\t\"STATUSBAR_DEFAULT_LANG\": \"(指定なし)\",\n\t\"STATUSBAR_SET_DEFAULT_LANG\": \".{0} ファイルのデフォルトとして設定\",\n\t\"STATUSBAR_ENCODING_TOOLTIP\": \"エンコードを選択\",\n\n    // CodeInspection: errors/warnings\n\t\"ERRORS_PANEL_TITLE_MULTIPLE\": \"{0} 個の問題\",\n\t\"SINGLE_ERROR\": \"1 個の {0} の問題\",\n\t\"MULTIPLE_ERRORS\": \"{1} 個の {0} の問題\",\n\t\"NO_ERRORS\": \"{0} の問題は検出されませんでした - Good job!\",\n\t\"NO_ERRORS_MULTIPLE_PROVIDER\": \"問題は検出されませんでした - Good job!\",\n\t\"LINT_DISABLED\": \"Lint チェックは使用できません\",\n\t\"NO_LINT_AVAILABLE\": \"{0} に使用できる Lint チェッカーがありません\",\n\t\"NOTHING_TO_LINT\": \"Lint チェックするファイルがありません\",\n\t\"LINTER_TIMED_OUT\": \"{0} は {1} ミリ秒待機した後でタイムアウトしました\",\n\t\"LINTER_FAILED\": \"{0} は次のエラーにより終了しました : {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n\t\"FILE_MENU\": \"ファイル\",\n\t\"CMD_FILE_NEW_UNTITLED\": \"新規作成\",\n\t\"CMD_FILE_NEW\": \"新しいファイル\",\n\t\"CMD_FILE_NEW_FOLDER\": \"新しいフォルダー\",\n\t\"CMD_FILE_OPEN\": \"開く\\u2026\",\n\t\"CMD_RECENT_FILES_OPEN\": \"最近使用したファイルを開く\\u2026\",\n\t\"CMD_ADD_TO_WORKING_SET\": \"ワーキングセットに開く\",\n\t\"CMD_OPEN_DROPPED_FILES\": \"ドロップしたファイルを開く\",\n\t\"CMD_OPEN_FOLDER\": \"フォルダーを開く\\u2026\",\n\t\"CMD_FILE_CLOSE\": \"閉じる\",\n\t\"CMD_FILE_CLOSE_ALL\": \"すべて閉じる\",\n\t\"CMD_FILE_CLOSE_LIST\": \"リストを閉じる\",\n\t\"CMD_FILE_CLOSE_OTHERS\": \"他をすべて閉じる\",\n\t\"CMD_FILE_CLOSE_ABOVE\": \"上をすべて閉じる\",\n\t\"CMD_FILE_CLOSE_BELOW\": \"下をすべて閉じる\",\n\t\"CMD_FILE_SAVE\": \"保存\",\n\t\"CMD_FILE_SAVE_ALL\": \"すべて保存\",\n\t\"CMD_FILE_SAVE_AS\": \"名前を付けて保存\\u2026\",\n\t\"CMD_LIVE_FILE_PREVIEW\": \"ライブプレビュー\",\n\t\"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\": \"試験ライブプレビューを有効にする\",\n\t\"CMD_RELOAD_LIVE_PREVIEW\": \"ライブプレビューを強制的に再読込み\",\n\t\"CMD_PROJECT_SETTINGS\": \"プロジェクト設定\\u2026\",\n\t\"CMD_FILE_RENAME\": \"ファイル名変更\",\n\t\"CMD_FILE_DELETE\": \"削除\",\n\t\"CMD_INSTALL_EXTENSION\": \"拡張機能をインストール\\u2026\",\n\t\"CMD_EXTENSION_MANAGER\": \"拡張機能マネージャー\\u2026\",\n\t\"CMD_FILE_REFRESH\": \"ファイルツリーを更新\",\n\t\"CMD_QUIT\": \"終了する\",\n    // Used in native File menu on Windows\n\t\"CMD_EXIT\": \"終了\",\n\n    // Edit menu commands\n\t\"EDIT_MENU\": \"編集\",\n\t\"CMD_UNDO\": \"取り消し\",\n\t\"CMD_REDO\": \"やり直し\",\n\t\"CMD_CUT\": \"カット\",\n\t\"CMD_COPY\": \"コピー\",\n\t\"CMD_PASTE\": \"ペースト\",\n\t\"CMD_SELECT_ALL\": \"すべて選択\",\n\t\"CMD_SELECT_LINE\": \"行の選択\",\n\t\"CMD_SPLIT_SEL_INTO_LINES\": \"選択範囲を行に分ける\",\n\t\"CMD_ADD_CUR_TO_NEXT_LINE\": \"次の行にカーソルを追加\",\n\t\"CMD_ADD_CUR_TO_PREV_LINE\": \"前の行にカーソルを追加\",\n\t\"CMD_INDENT\": \"インデント\",\n\t\"CMD_UNINDENT\": \"インデント解除\",\n\t\"CMD_DUPLICATE\": \"行を複製\",\n\t\"CMD_DELETE_LINES\": \"行を削除\",\n\t\"CMD_COMMENT\": \"行コメントの切り替え\",\n\t\"CMD_BLOCK_COMMENT\": \"ブロックコメントの切り替え\",\n\t\"CMD_LINE_UP\": \"行を上に移動\",\n\t\"CMD_LINE_DOWN\": \"行を下に移動\",\n\t\"CMD_OPEN_LINE_ABOVE\": \"上の行を開く\",\n\t\"CMD_OPEN_LINE_BELOW\": \"下の行を開く\",\n\t\"CMD_TOGGLE_CLOSE_BRACKETS\": \"自動閉じカッコ\",\n\t\"CMD_SHOW_CODE_HINTS\": \"コードヒントを表示\",\n\n    // Search menu commands\n\t\"FIND_MENU\": \"検索\",\n\t\"CMD_FIND\": \"検索\",\n\t\"CMD_FIND_NEXT\": \"次を検索\",\n\t\"CMD_FIND_PREVIOUS\": \"前を検索\",\n\t\"CMD_FIND_ALL_AND_SELECT\": \"すべて検索して選択\",\n\t\"CMD_ADD_NEXT_MATCH\": \"選択範囲に次の候補を追加\",\n\t\"CMD_SKIP_CURRENT_MATCH\": \"スキップして次の候補を追加\",\n\t\"CMD_FIND_IN_FILES\": \"ファイルを横断して検索\",\n\t\"CMD_FIND_IN_SUBTREE\": \"検索先\\u2026\",\n\t\"CMD_REPLACE\": \"置換\",\n\t\"CMD_REPLACE_IN_FILES\": \"ファイルを横断して置換\",\n\t\"CMD_REPLACE_IN_SUBTREE\": \"置換対象\\u2026\",\n\n    // View menu commands\n\t\"VIEW_MENU\": \"表示\",\n\t\"CMD_HIDE_SIDEBAR\": \"サイドバーを隠す\",\n\t\"CMD_SHOW_SIDEBAR\": \"サイドバーを表示する\",\n\t\"CMD_TOGGLE_SIDEBAR\": \"サイドバーの切り替え\",\n\t\"CMD_TOGGLE_PANELS\": \"パネルの表示切り替え\",\n\t\"CMD_TOGGLE_PURE_CODE\": \"簡易表示\",\n\t\"CMD_INCREASE_FONT_SIZE\": \"フォントサイズを大きく\",\n\t\"CMD_DECREASE_FONT_SIZE\": \"フォントサイズを小さく\",\n\t\"CMD_RESTORE_FONT_SIZE\": \"フォントサイズを元に戻す\",\n\t\"CMD_SCROLL_LINE_UP\": \"1 行上にスクロール\",\n\t\"CMD_SCROLL_LINE_DOWN\": \"1 行下にスクロール\",\n\t\"CMD_TOGGLE_LINE_NUMBERS\": \"行番号\",\n\t\"CMD_TOGGLE_ACTIVE_LINE\": \"アクティブな行をハイライト\",\n\t\"CMD_TOGGLE_WORD_WRAP\": \"折り返し\",\n\t\"CMD_LIVE_HIGHLIGHT\": \"ライブプレビューハイライト\",\n\t\"CMD_VIEW_TOGGLE_INSPECTION\": \"保存時にファイルを Lint チェック\",\n\t\"CMD_WORKINGSET_SORT_BY_ADDED\": \"追加日時順\",\n\t\"CMD_WORKINGSET_SORT_BY_NAME\": \"名前順\",\n\t\"CMD_WORKINGSET_SORT_BY_TYPE\": \"種類順\",\n\t\"CMD_WORKING_SORT_TOGGLE_AUTO\": \"自動ソート\",\n\t\"CMD_THEMES\": \"テーマ\\u2026\",\n\t\"CMD_TOGGLE_SEARCH_AUTOHIDE\": \"検索を自動的に閉じる\",\n\n    // Navigate menu commands\n\t\"NAVIGATE_MENU\": \"ナビゲート\",\n\t\"CMD_QUICK_OPEN\": \"クイックオープン\",\n\t\"CMD_GOTO_LINE\": \"行に移動\",\n\t\"CMD_GOTO_DEFINITION\": \"定義をクイック検索\",\n\t\"CMD_GOTO_DEFINITION_PROJECT\": \"プロジェクトで定義をクイック検索\",\n\t\"CMD_GOTO_FIRST_PROBLEM\": \"最初の問題に移動\",\n\t\"CMD_TOGGLE_QUICK_EDIT\": \"クイック編集\",\n\t\"CMD_TOGGLE_QUICK_DOCS\": \"クイックドキュメント\",\n\t\"CMD_QUICK_EDIT_PREV_MATCH\": \"前の候補に移動\",\n\t\"CMD_QUICK_EDIT_NEXT_MATCH\": \"次の候補に移動\",\n\t\"CMD_CSS_QUICK_EDIT_NEW_RULE\": \"新規ルール\",\n\t\"CMD_NEXT_DOC\": \"次の文書\",\n\t\"CMD_PREV_DOC\": \"前の文書\",\n\t\"CMD_NAVIGATE_BACKWARD\": \"前に戻る\",\n\t\"CMD_NAVIGATE_FORWARD\": \"次に進む\",\n\t\"CMD_NEXT_DOC_LIST_ORDER\": \"リストの次の文書\",\n\t\"CMD_PREV_DOC_LIST_ORDER\": \"リストの前の文書\",\n\t\"CMD_SHOW_IN_TREE\": \"ファイルツリー内で表示\",\n\t\"CMD_SHOW_IN_EXPLORER\": \"エクスプローラーで表示\",\n\t\"CMD_SHOW_IN_FINDER\": \"Finder で表示\",\n\t\"CMD_SHOW_IN_OS\": \"OS で表示\",\n\t\"CMD_SWITCH_PANE_FOCUS\": \"ペインフォーカスの切り替え\",\n\n    // Help menu commands\n\t\"HELP_MENU\": \"ヘルプ\",\n\t\"CMD_CHECK_FOR_UPDATE\": \"更新をチェックする\",\n\t\"CMD_HOW_TO_USE_BRACKETS\": \"{APP_NAME} の使用方法\",\n\t\"CMD_SUPPORT\": \"{APP_NAME} サポート\",\n\t\"CMD_SUGGEST\": \"機能改善の提案\",\n\t\"CMD_RELEASE_NOTES\": \"リリースノート\",\n\t\"CMD_GET_INVOLVED\": \"コミュニティに参加\",\n\t\"CMD_SHOW_EXTENSIONS_FOLDER\": \"拡張機能のフォルダーを開く\",\n\t\"CMD_HEALTH_DATA_STATISTICS\": \"正常性レポート\",\n\t\"CMD_HOMEPAGE\": \"{APP_TITLE} ホームページ\",\n\t\"CMD_TWITTER\": \"Twitter で {TWITTER_NAME} をフォロー\",\n\t\"CMD_ABOUT\": \"{APP_TITLE} について\",\n\t\"CMD_OPEN_PREFERENCES\": \"環境設定ファイルを開く\",\n\t\"CMD_OPEN_KEYMAP\": \"ユーザーキーマップを開く\",\n\n    // Strings for main-view.html\n\t\"EXPERIMENTAL_BUILD\": \"試験ビルド\",\n\t\"RELEASE_BUILD\": \"ビルド\",\n\t\"DEVELOPMENT_BUILD\": \"開発ビルド\",\n\t\"PRERELEASE_BUILD\": \"プレリリースビルド\",\n\t\"RELOAD_FROM_DISK\": \"ディスクから再読み込み\",\n\t\"KEEP_CHANGES_IN_EDITOR\": \"エディター内の変更を保持する\",\n\t\"CLOSE_DONT_SAVE\": \"保存せずに閉じる\",\n\t\"RELAUNCH_CHROME\": \"Chrome を再起動\",\n\t\"ABOUT\": \"このソフトウェアについて\",\n\t\"CLOSE\": \"閉じる\",\n\t\"ABOUT_TEXT_LINE1\": \"リリース {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n\t\"ABOUT_TEXT_BUILD_TIMESTAMP\": \"ビルドのタイムスタンプ : \",\n\t\"ABOUT_TEXT_LINE3\": \"Notices, terms and conditions pertaining to third party software are located at <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> and incorporated by reference herein.\",\n\t\"ABOUT_TEXT_LINE4\": \"ドキュメントとソースコードは <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a> から入手できます。\",\n\t\"ABOUT_TEXT_LINE5\": \"\\u2764 および JavaScript を使用して次の人によって作成されました :\",\n\t\"ABOUT_TEXT_LINE6\": \"多くの人々 (ただし、人物データの読み込みに問題が発生しています)。\",\n\t\"ABOUT_TEXT_MDN_DOCS\": \"MDN Docs および MDN グラフィックロゴは Creative Commons の帰属ライセンス、<a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a> によってライセンス付与されています。\",\n\t\"UPDATE_NOTIFICATION_TOOLTIP\": \"{APP_NAME} の新しいビルドを利用できます。詳細はここをクリックしてください。\",\n\t\"UPDATE_AVAILABLE_TITLE\": \"利用可能なアップデートがあります\",\n\t\"UPDATE_MESSAGE\": \"{APP_NAME} の新しいビルドが利用できます。新機能の一部を以下にご紹介します :\",\n\t\"GET_IT_NOW\": \"すぐに入手する\",\n\t\"PROJECT_SETTINGS_TITLE\": \"プロジェクト設定 : {0}\",\n\t\"PROJECT_SETTING_BASE_URL\": \"ライブプレビューのベース URL\",\n\t\"PROJECT_SETTING_BASE_URL_HINT\": \"ローカルサーバーを使用するには、http://localhost:8000/ などの URL を入力してください\",\n\t\"BASEURL_ERROR_INVALID_PROTOCOL\": \"{0} プロトコルはライブプレビューではサポートされていません。http: または https: を使用してください。\",\n\t\"BASEURL_ERROR_SEARCH_DISALLOWED\": \"ベース URL には、「{0}」のような検索パラメーターは使用できません。\",\n\t\"BASEURL_ERROR_HASH_DISALLOWED\": \"ベース URL には、「{0}」のようなハッシュ記号は使用できません。\",\n\t\"BASEURL_ERROR_INVALID_CHAR\": \"「{0}」のような特殊文字は、パーセントエンコーディングする必要があります。\",\n\t\"BASEURL_ERROR_UNKNOWN_ERROR\": \"ベース URL の解析中に不明なエラーが発生しました\",\n\n    // Strings for Pane.js\n\t\"EMPTY_VIEW_HEADER\": \"<em>このペインにフォーカスがあるときにファイルを開く</em>\",\n\t\"FLIPVIEW_BTN_TOOLTIP\": \"このビューを {0} ペインにめくる\",\n\n    // Strings for themes-settings.html and themes-general.html\n\t\"CURRENT_THEME\": \"現在のテーマ \",\n\t\"USE_THEME_SCROLLBARS\": \"テーマスクロールバーを使用 \",\n\t\"FONT_SIZE\": \"フォントサイズ \",\n\t\"FONT_FAMILY\": \"フォントファミリー \",\n\t\"THEMES_SETTINGS\": \"テーマ設定\",\n\n    // CSS Quick Edit\n\t\"BUTTON_NEW_RULE\": \"新規ルール\",\n\n    // Extension Management strings\n\t\"INSTALL\": \"インストール\",\n\t\"UPDATE\": \"更新\",\n\t\"REMOVE\": \"削除\",\n\t\"DISABLE\": \"無効\",\n\t\"ENABLE\": \"有効\",\n\t\"OVERWRITE\": \"上書き\",\n\t\"CANT_REMOVE_DEV\": \"dev フォルダーの拡張機能は手動で削除する必要があります。\",\n\t\"CANT_UPDATE\": \"アップデートはこのバージョンの {APP_NAME} と互換性がありません。\",\n\t\"CANT_UPDATE_DEV\": \"dev フォルダーの拡張機能は自動的に更新されません。\",\n\t\"INSTALL_EXTENSION_TITLE\": \"拡張機能をインストール\",\n\t\"UPDATE_EXTENSION_TITLE\": \"拡張機能を更新\",\n\t\"INSTALL_EXTENSION_LABEL\": \"拡張機能の URL\",\n\t\"INSTALL_EXTENSION_HINT\": \"拡張機能 zip ファイルまたは GitHub レポジトリの URL\",\n\t\"INSTALLING_FROM\": \"{0} から拡張機能をインストールしています\\u2026\",\n\t\"INSTALL_SUCCEEDED\": \"インストールは成功しました。\",\n\t\"INSTALL_FAILED\": \"インストールは失敗しました。\",\n\t\"CANCELING_INSTALL\": \"キャンセルしています\\u2026\",\n\t\"CANCELING_HUNG\": \"インストールのキャンセルに時間がかかっています。内部エラーが発生した可能性があります。\",\n\t\"INSTALL_CANCELED\": \"インストールはキャンセルされました。\",\n\t\"VIEW_COMPLETE_DESCRIPTION\": \"詳細な説明を表示\",\n\t\"VIEW_TRUNCATED_DESCRIPTION\": \"省略された説明を表示\",\n\t\"SORT_EXTENSION_METHOD\": \"downloadCount または publishedDate を使用してエクステンションをソート\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n\t\"INVALID_ZIP_FILE\": \"ダウンロードされたコンテンツは有効な zip ファイルではありません。\",\n\t\"MISSING_PACKAGE_JSON\": \"パッケージに package.json ファイルがありません。\",\n\t\"INVALID_PACKAGE_JSON\": \"package.json ファイルは有効ではありません (エラーは {0} です)。\",\n\t\"MISSING_PACKAGE_NAME\": \"package.json ファイルはパッケージ名を指定していません。\",\n\t\"BAD_PACKAGE_NAME\": \"{0} は無効なパッケージ名です。\",\n\t\"MISSING_PACKAGE_VERSION\": \"package.json ファイルはパッケージバージョンを指定していません。\",\n\t\"INVALID_VERSION_NUMBER\": \"パッケージバージョン番号 ({0}) は無効です。\",\n\t\"INVALID_BRACKETS_VERSION\": \"{APP_NAME} 互換文字列 {0} は無効です。\",\n\t\"DISALLOWED_WORDS\": \"{1} は {0} フィールドでは使用できません。\",\n\t\"NPM_INSTALL_FAILED\": \"npm install コマンドに失敗しました : {0}\",\n\t\"API_NOT_COMPATIBLE\": \"拡張機能はこのバージョンの {APP_NAME} と互換性がありません。無効な拡張機能フォルダーにインストールされます。\",\n\t\"MISSING_MAIN\": \"パッケージに main.js ファイルが含まれていません。\",\n\t\"EXTENSION_ALREADY_INSTALLED\": \"このパッケージをインストールすると以前にインストールした拡張機能が上書きされます。古い拡張機能を上書きしますか？\",\n\t\"EXTENSION_SAME_VERSION\": \"このパッケージのバージョンは現在インストールされているバージョンと同じです。既存のインストールを上書きしますか？\",\n\t\"EXTENSION_OLDER_VERSION\": \"このパッケージのバージョン ({0}) は、現在インストールされているバージョン ({1}) よりも古いバージョンです。既存のインストールを上書きしますか？\",\n\t\"DOWNLOAD_ID_IN_USE\": \"内部エラー : ダウンロード ID は既に使用されています。\",\n\t\"NO_SERVER_RESPONSE\": \"サーバーに接続できません。\",\n\t\"BAD_HTTP_STATUS\": \"ファイルがサーバー (HTTP {0}) に見つかりません。\",\n\t\"CANNOT_WRITE_TEMP\": \"一時ダウンロードファイルを保存できません。\",\n\t\"ERROR_LOADING\": \"拡張機能の起動時にエラーが発生しました。\",\n\t\"MALFORMED_URL\": \"URL が無効です。正しく入力されているか確認してください。\",\n\t\"UNSUPPORTED_PROTOCOL\": \"URL は http または https URL である必要があります。\",\n\t\"UNKNOWN_ERROR\": \"不明な内部エラー。\",\n    // For NOT_FOUND_ERR, see generic strings above\n\t\"EXTENSION_MANAGER_TITLE\": \"拡張機能マネージャー\",\n\t\"EXTENSION_MANAGER_ERROR_LOAD\": \"拡張機能レジストリにアクセスできません。後でもう一度試してください。\",\n\t\"INSTALL_EXTENSION_DRAG\": \".zip をここにドラッグするか、\",\n\t\"INSTALL_EXTENSION_DROP\": \".zip をドロップしてインストール\",\n\t\"INSTALL_EXTENSION_DROP_ERROR\": \"次のエラーのため、インストール / アンインストールが中止されました :\",\n\t\"INSTALL_FROM_URL\": \"URL からインストール\\u2026\",\n\t\"INSTALL_EXTENSION_VALIDATING\": \"検証中\\u2026\",\n\t\"EXTENSION_AUTHOR\": \"作成者\",\n\t\"EXTENSION_DATE\": \"日付\",\n\t\"EXTENSION_INCOMPATIBLE_NEWER\": \"この拡張機能には新しいバージョンの {APP_NAME} が必要です。\",\n\t\"EXTENSION_INCOMPATIBLE_OLDER\": \"この拡張機能は現在、古いバージョンの {APP_NAME} でしか動作しません。\",\n\t\"EXTENSION_LATEST_INCOMPATIBLE_NEWER\": \"この拡張機能のバージョン {0} には {APP_NAME} の新しいバージョンが必要です。ただし、以前のバージョン {1} をインストールすることができます。\",\n\t\"EXTENSION_LATEST_INCOMPATIBLE_OLDER\": \"この拡張機能のバージョン {0} は {APP_NAME} の古いバージョンでのみ動作します。ただし、以前のバージョン {1} をインストールすることができます。\",\n\t\"EXTENSION_NO_DESCRIPTION\": \"説明なし\",\n\t\"EXTENSION_MORE_INFO\": \"詳細情報\\u2026\",\n\t\"EXTENSION_ERROR\": \"拡張機能のエラー\",\n\t\"EXTENSION_KEYWORDS\": \"キーワード\",\n\t\"EXTENSION_TRANSLATED_USER_LANG\": \"ご使用の言語を含む {0} 言語に翻訳されました\",\n\t\"EXTENSION_TRANSLATED_GENERAL\": \"{0} 言語に翻訳されました\",\n\t\"EXTENSION_TRANSLATED_LANGS\": \"この拡張機能はこれらの言語に翻訳されています : {0}\",\n\t\"EXTENSION_INSTALLED\": \"インストール完了\",\n\t\"EXTENSION_UPDATE_INSTALLED\": \"この拡張機能のアップデートがダウンロードされました。{APP_NAME} のリロード後にインストールされます。\",\n\t\"EXTENSION_SEARCH_PLACEHOLDER\": \"検索\",\n\t\"EXTENSION_MORE_INFO_LINK\": \"詳細\",\n\t\"BROWSE_EXTENSIONS\": \"拡張機能を探す\",\n\t\"EXTENSION_MANAGER_REMOVE\": \"拡張機能を削除\",\n\t\"EXTENSION_MANAGER_REMOVE_ERROR\": \"1 つ以上の拡張機能 ({0}) を削除できません。{APP_NAME} がリロード中です。\",\n\t\"EXTENSION_MANAGER_UPDATE\": \"拡張機能を更新\",\n\t\"EXTENSION_MANAGER_UPDATE_ERROR\": \"1 つ以上の拡張機能 ({0}) を更新できません。{APP_NAME} がリロード中です。\",\n\t\"EXTENSION_MANAGER_DISABLE\": \"拡張機能を無効化\",\n\t\"EXTENSION_MANAGER_DISABLE_ERROR\": \"1 つ以上の拡張機能 ({0}) を無効化できません。{APP_NAME} がリロード中です。\",\n\t\"MARKED_FOR_REMOVAL\": \"削除予定\",\n\t\"UNDO_REMOVE\": \"取り消し\",\n\t\"MARKED_FOR_UPDATE\": \"更新予定\",\n\t\"UNDO_UPDATE\": \"取り消し\",\n\t\"MARKED_FOR_DISABLING\": \"無効化予定\",\n\t\"UNDO_DISABLE\": \"取り消し\",\n\t\"CHANGE_AND_RELOAD_TITLE\": \"拡張機能を変更\",\n\t\"CHANGE_AND_RELOAD_MESSAGE\": \"予定された拡張機能を更新、削除、無効にするには、{APP_NAME} をリロードする必要があります。未保存の変更を保存するかどうか確認されます。\",\n\t\"REMOVE_AND_RELOAD\": \"拡張機能を削除してリロード\",\n\t\"CHANGE_AND_RELOAD\": \"拡張機能を変更してリロード\",\n\t\"UPDATE_AND_RELOAD\": \"拡張機能を更新してリロード\",\n\t\"DISABLE_AND_RELOAD\": \"拡張機能を無効化してリロード\",\n\t\"PROCESSING_EXTENSIONS\": \"拡張機能の変更を処理中\\u2026\",\n\t\"EXTENSION_NOT_INSTALLED\": \"インストールされていなかったため、拡張機能 {0} を削除できませんでした。\",\n\t\"NO_EXTENSIONS\": \"インストールされている拡張機能はまだありません。<br>上の「入手可能」タブをクリックしてインストールしてください。\",\n\t\"NO_EXTENSION_MATCHES\": \"検索条件に一致する拡張機能がありません。\",\n\t\"REGISTRY_SANITY_CHECK_WARNING\": \"注意 : これらの拡張機能の作成元が {APP_NAME} 以外である可能性があります。拡張機能はレビューされず、ローカルアクセス権が一杯です。不明なソースから拡張機能をインストールするときは十分に注意してください。\",\n\t\"EXTENSIONS_INSTALLED_TITLE\": \"インストール済み\",\n\t\"EXTENSIONS_DEFAULT_TITLE\": \"初期設定\",\n\t\"EXTENSIONS_AVAILABLE_TITLE\": \"入手可能\",\n\t\"EXTENSIONS_THEMES_TITLE\": \"テーマ\",\n\t\"EXTENSIONS_UPDATES_TITLE\": \"アップデート\",\n\t\"EXTENSIONS_LAST_UPDATED\": \"最終更新日\",\n\t\"EXTENSIONS_DOWNLOADS\": \"ダウンロード\",\n\n\t\"INLINE_EDITOR_NO_MATCHES\": \"一致するものがありません。\",\n\t\"INLINE_EDITOR_HIDDEN_MATCHES\": \"一致項目はすべて縮小されています。一致項目を表示するには、右側にリストされているファイルを展開してください。\",\n\t\"CSS_QUICK_EDIT_NO_MATCHES\": \"選択に一致する既存の CSS ルールがありません。<br>「新規ルール」をクリックしてルールを作成してください。\",\n\t\"CSS_QUICK_EDIT_NO_STYLESHEETS\": \"プロジェクトにはスタイルシートがありません。<br>スタイルシートを作成して CSS ルールに追加してください。\",\n\n    // Custom Viewers\n\t\"IMAGE_VIEWER_LARGEST_ICON\": \"最大\",\n\n    /**\n     * Unit names\n     */\n\t\"UNIT_PIXELS\": \"ピクセル\",\n\n    // extensions/default/DebugCommands\n\t\"DEBUG_MENU\": \"デバッグ\",\n\t\"ERRORS\": \"エラー \",\n\t\"CMD_SHOW_DEV_TOOLS\": \"開発者ツールを表示\",\n\t\"CMD_REFRESH_WINDOW\": \"拡張機能付きでリロード\",\n\t\"CMD_RELOAD_WITHOUT_USER_EXTS\": \"拡張機能なしでリロード\",\n\t\"CMD_NEW_BRACKETS_WINDOW\": \"新しい {APP_NAME} ウィンドウ\",\n\t\"CMD_LAUNCH_SCRIPT_MAC\": \"コマンドラインショートカットをインストール\",\n\t\"CMD_SWITCH_LANGUAGE\": \"言語を切り替える\",\n\t\"CMD_RUN_UNIT_TESTS\": \"テストを実行\",\n\t\"CMD_SHOW_PERF_DATA\": \"パフォーマンスデータを表示\",\n\t\"CMD_ENABLE_NODE_DEBUGGER\": \"Node Debugger を有効にする\",\n\t\"CMD_LOG_NODE_STATE\": \"Node の状態をコンソールに記録\",\n\t\"CMD_RESTART_NODE\": \"Node を再起動\",\n\t\"CMD_SHOW_ERRORS_IN_STATUS_BAR\": \"ステータスバーにエラーを表示\",\n\t\"CMD_OPEN_BRACKETS_SOURCE\": \"{APP_NAME} ソースを開く\",\n\n\t\"CREATING_LAUNCH_SCRIPT_TITLE\": \"{APP_NAME} コマンドラインショートカット\",\n\t\"ERROR_CREATING_LAUNCH_SCRIPT\": \"コマンドラインショートカットのインストール中にエラーが発生しました。<a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>これらのトラブルシューティングの提案</a>をお試しください。<br/><br/>理由 : {0}\",\n\t\"ERROR_CLTOOLS_RMFAILED\": \"既存の <code>/usr/local/bin/brackets</code> シンボリックリンクを削除できません。\",\n\t\"ERROR_CLTOOLS_MKDIRFAILED\": \"<code>/usr/local/bin</code> ディレクトリを作成できません。\",\n\t\"ERROR_CLTOOLS_LNFAILED\": \"<code>/usr/local/bin/brackets</code> シンボリックリンクを作成できません。\",\n\t\"ERROR_CLTOOLS_SERVFAILED\": \"内部エラーです。\",\n\t\"ERROR_CLTOOLS_NOTSUPPORTED\": \"この OS ではコマンドラインショートカットがサポートされていません。\",\n\t\"LAUNCH_SCRIPT_CREATE_SUCCESS\": \"成功しました。{APP_NAME} をコマンドラインから簡単に起動できるようになりました (<code>brackets myFile.txt</code> でファイルを開く、<code>brackets myFolder</code> でプロジェクトを切り替えるなど)。<br/><br/>コマンドラインから {APP_NAME} を使用する方法について<a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>詳細</a>をご確認ください。\",\n\n\t\"LANGUAGE_TITLE\": \"言語を切り替える\",\n\t\"LANGUAGE_MESSAGE\": \"言語 :\",\n\t\"LANGUAGE_SUBMIT\": \"{APP_NAME} をリロード\",\n\t\"LANGUAGE_CANCEL\": \"キャンセル\",\n\t\"LANGUAGE_SYSTEM_DEFAULT\": \"システムのデフォルト\",\n\n    // extensions/default/HealthData\n\t\"HEALTH_DATA_NOTIFICATION\": \"Health Report Preferences\",\n\t\"HEALTH_FIRST_POPUP_TITLE\": \"{APP_NAME} の正常性レポート\",\n\t\"HEALTH_DATA_DO_TRACK\": \"{APP_NAME} の使用方法に関する偽名情報を共有します\",\n\t\"HEALTH_DATA_NOTIFICATION_MESSAGE\": \"{APP_NAME} 品質向上のため、アドビでは、お客様の {APP_NAME} の使用方法に関する限られた<strong>偽名</strong>の統計をアドビに定期的に送信しています。この情報は、機能を優先順位付けし、バグを発見し、操作性の問題を検出する際に役立ちます。<br><br><strong>ヘルプ／正常性レポート</strong>から、お客様のデータの確認またはデータの非共有の選択をすることができます。<br><br><a href='https://github.com/adobe/brackets/wiki/Project-Health-Data'>{APP_NAME} の正常性レポートに関する詳細情報</a>\",\n\t\"HEALTH_DATA_PREVIEW\": \"{APP_NAME} の正常性レポート\",\n\t\"HEALTH_DATA_PREVIEW_INTRO\": \"<p>{APP_NAME} 品質向上のため、アドビでは、お客様の {APP_NAME} の使用方法に関する限られた<strong>偽名</strong>の統計をアドビに定期的に送信しています。この情報は、機能を優先順位付けし、バグを発見し、操作性の問題を検出する際に役立ちます。<a href='https://github.com/adobe/brackets/wiki/Project-Health-Data'>{APP_NAME} の正常性レポート</a>についての詳細およびレポートがお客様のプライバシーを保護した上でどのように {APP_NAME} コミュニティに役立つかをご確認ください。</p><p>有効にした場合に、次回のお客様の正常性レポートで送信されるデータのプレビューを以下に示します。<em></em> </p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n\t\"INLINE_TIMING_EDITOR_TIME\": \"時間\",\n\t\"INLINE_TIMING_EDITOR_PROGRESSION\": \"進行\",\n\t\"BEZIER_EDITOR_INFO\": \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> 選択したポイントを移動<br><kbd class='text'>Shift</kbd> 10 単位ずつ移動<br><kbd class='text'>Tab</kbd> ポイントを切り替え\",\n\t\"STEPS_EDITOR_INFO\": \"<kbd>↑</kbd><kbd>↓</kbd> 手順を増減<br><kbd>←</kbd><kbd>→</kbd> 「開始」または「終了」\",\n\t\"INLINE_TIMING_EDITOR_INVALID\": \"古い値 <code>{0}</code> が無効なため、表示されている関数は <code>{1}</code> に変更されました。ドキュメントは最初の編集内容で更新されます。\",\n\n    // extensions/default/InlineColorEditor\n\t\"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\": \"現在の色\",\n\t\"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\": \"元の色\",\n\t\"COLOR_EDITOR_RGBA_BUTTON_TIP\": \"RGBa 形式\",\n\t\"COLOR_EDITOR_HEX_BUTTON_TIP\": \"16 進形式\",\n\t\"COLOR_EDITOR_HSLA_BUTTON_TIP\": \"HSLa 形式\",\n\t\"COLOR_EDITOR_0X_BUTTON_TIP\": \"16 進数 (0x) 形式\",\n\t\"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\": \"{0} ({1} 回使用)\",\n\t\"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\": \"{0} ({1} 回使用)\",\n\n    // extensions/default/JavaScriptCodeHints\n\t\"CMD_JUMPTO_DEFINITION\": \"定義にジャンプ\",\n\t\"CMD_SHOW_PARAMETER_HINT\": \"パラメーターヒントを表示\",\n\t\"NO_ARGUMENTS\": \"<パラメーターがありません>\",\n\t\"DETECTED_EXCLUSION_TITLE\": \"JavaScript ファイルの推論問題\",\n\t\"DETECTED_EXCLUSION_INFO\": \"{APP_NAME} で <span class='dialog-filename'>{0}</span> の処理中に問題が発生しました。<br><br>このファイルはコードヒント、定義にジャンプ、またはクイック編集では処理されません。このファイルを再度有効にするには、プロジェクトで <code>.brackets.json</code> を開いて <code>jscodehints.detectedExclusions</code> を編集してください。<br><br>これは、{APP_NAME} のバグである可能性があります。このファイルのコピーをご提供いただける場合は、ここで名付けたファイルへのリンクを記載して<a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>バグを登録</a>してください。\",\n\n    // extensions/default/JavascriptRefactoring\n\t\"CMD_REFACTOR\": \"リファクタリング\",\n\t\"CMD_EXTRACTTO_VARIABLE\": \"変数に抽出\",\n\t\"CMD_EXTRACTTO_FUNCTION\": \"関数に抽出\",\n\t\"ERROR_TERN_FAILED\": \"Tern からデータを取得できません\",\n\t\"ERROR_EXTRACTTO_VARIABLE_NOT_VALID\": \"選択内容は式になっていません\",\n\t\"ERROR_EXTRACTTO_FUNCTION_NOT_VALID\": \"選択したブロックは、ステートメントセットまたは式を表す必要があります\",\n\t\"ERROR_EXTRACTTO_VARIABLE_MULTICURSORS\": \"変数に抽出は複数カーソルでは機能しません\",\n\t\"ERROR_EXTRACTTO_FUNCTION_MULTICURSORS\": \"関数に抽出は複数カーソルでは機能しません\",\n\t\"EXTRACTTO_FUNCTION_SELECT_SCOPE\": \"対象範囲を選択\",\n\t\"EXTRACTTO_VARIABLE_SELECT_EXPRESSION\": \"式を選択\",\n\t\"CMD_REFACTORING_RENAME\": \"ファイル名変更\",\n\t\"CMD_REFACTORING_TRY_CATCH\": \"Try Catch で囲む\",\n\t\"CMD_REFACTORING_CONDITION\": \"Condition で囲む\",\n\t\"CMD_REFACTORING_GETTERS_SETTERS\": \"Getters Setters を作成\",\n\t\"CMD_REFACTORING_ARROW_FUNCTION\": \"Arrow Function へ変換\",\n\t\"DESCRIPTION_CODE_REFACTORING\": \"JavaScript のコードリファクタリングを有効化または無効化します\",\n\t\"ERROR_TRY_CATCH\": \"有効なコードを選択して、Try-catch ブロックで囲みます\",\n\t\"ERROR_WRAP_IN_CONDITION\": \"有効なコードを選択して、Condition ブロックで囲みます\",\n\t\"ERROR_ARROW_FUNCTION\": \"関数式の中にカーソルを置きます\",\n\t\"ERROR_GETTERS_SETTERS\": \"オブジェクト式のメンバーにカーソルを置きます\",\n\t\"ERROR_RENAME_MULTICURSOR\": \"複数のカーソルを使用して名前を変更することはできません\",\n\t\"ERROR_RENAME_QUICKEDIT\": \"この識別子は、この関数以外の場所で参照されているため名前変更できません\",\n\t\"ERROR_RENAME_GENERAL\": \"選択したテキストの名前を変更できません\",\n\n    // extensions/default/JSLint\n\t\"JSLINT_NAME\": \"JSLint\",\n\n    // extensions/default/QuickView\n\t\"CMD_ENABLE_QUICK_VIEW\": \"ホバー・クイックビュー\",\n\n    // extensions/default/RecentProjects\n\t\"CMD_TOGGLE_RECENT_PROJECTS\": \"最近使用したプロジェクト\",\n\n    // extensions/default/MDNDocs\n\t\"DOCS_MORE_LINK\": \"詳細\",\n\n    // extensions/default/CodeFolding\n\t\"COLLAPSE_ALL\": \"すべて折りたたむ\",\n\t\"EXPAND_ALL\": \"すべて展開\",\n\t\"COLLAPSE_CURRENT\": \"現在のコードをたたむ\",\n\t\"EXPAND_CURRENT\": \"現在のコードを展開\",\n\n    // extensions/default/NavigationAndHistory\n\t\"RECENT_FILES_DLG_HEADER\": \"最近使用したファイル\",\n\t\"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\": \"消去\",\n\t\"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\": \"ワーキングセットにないファイルをクリア\",\n\n    // Descriptions of core preferences\n\t\"DESCRIPTION_CLOSE_BRACKETS\": \"中括弧、角括弧、丸括弧を自動的に閉じるには true\",\n\t\"DESCRIPTION_CLOSE_OTHERS_ABOVE\": \"「作業中ファイル」コンテキストメニューから「上をすべて閉じる」を削除するには false\",\n\t\"DESCRIPTION_CLOSE_OTHERS_BELOW\": \"「作業中ファイル」コンテキストメニューから「下をすべて閉じる」を削除するには false\",\n\t\"DESCRIPTION_CLOSE_OTHERS\": \"「作業中ファイル」コンテキストメニューから「他をすべて閉じる」を削除するには false\",\n\t\"DESCRIPTION_CLOSE_TAGS\": \"タグ終了オプションを設定します\",\n\t\"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\": \"自動終了させないタグの配列\",\n\t\"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\": \"開始タグの > の入力時に閉じる\",\n\t\"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\": \"終了タグの / の入力時に閉じる\",\n\t\"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\": \"表示時に空白行があるタグの配列\",\n\t\"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\": \"インデントレベルの変更時に、折りたたみ可能なセクションマーカーを常に生成するには true\",\n\t\"DESCRIPTION_CODE_FOLDING_ENABLED\": \"コード折りたたみを有効にするには true\",\n\t\"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\": \"余白の上にマウスのポインターを置いたときにのみセクション折りたたみマーカーを表示させるには true\",\n\t\"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\": \"「すべて折りたたむ」を適用するレベル数を制限します\",\n\t\"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\": \"次の行数に達したら折りたたみ可能なセクションのアイコンを表示する\",\n\t\"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\": \"ファイルまたはプロジェクトを閉じて再度開く場合に折りたたまれたセクションを記憶するには true\",\n\t\"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"エディター内の選択したテキストでコード折りたたみを有効にするには true\",\n\t\"DESCRIPTION_DISABLED_DEFAULT_EXTENSIONS\": \"無効化された初期設定のエクステンション\",\n\t\"DESCRIPTION_ATTR_HINTS\": \"HTML 属性ヒントを有効化/無効化\",\n\t\"DESCRIPTION_CSS_PROP_HINTS\": \"CSS/LESS/SCSS プロパティヒントを有効化/無効化\",\n\t\"DESCRIPTION_JS_HINTS\": \"JavaScript のコードヒントを有効化/無効化\",\n\t\"DESCRIPTION_JS_HINTS_TYPE_DETAILS\": \"JavaScript コードヒントのデータタイプの詳細を有効化/無効化\",\n\t\"DESCRIPTION_PREF_HINTS\": \"環境設定のコードヒントを有効化/無効化\",\n\t\"DESCRIPTION_SPECIAL_CHAR_HINTS\": \"HTML エンティティヒントを有効化/無効化\",\n\t\"DESCRIPTION_SVG_HINTS\": \"SVG のコードヒントを有効化/無効化\",\n\t\"DESCRIPTION_HTML_TAG_HINTS\": \"HTML タグヒントを有効化/無効化\",\n\t\"DESCRIPTION_URL_CODE_HINTS\": \"HTML や CSS/LESS/SCSS の URL ヒントを有効化/無効化\",\n\t\"DESCRIPTION_DRAG_DROP_TEXT\": \"ドラッグ＆ドロップ機能を有効化/無効化\",\n\t\"DESCRIPTION_HEALTH_DATA_TRACKING\": \"正常性データのトラッキングを有効にする\",\n\t\"DESCRIPTION_HIGHLIGHT_MATCHES\": \"ドキュメント全体の一致する文字列の自動ハイライト表示を有効にします\",\n\t\"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\": \"現在カーソルがあるトークンと一致するすべての文字列をハイライト表示 (選択不要)\",\n\t\"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\": \"選択内容が完全なトークンの場合のみハイライト表示\",\n\t\"DESCRIPTION_INSERT_HINT_ON_TAB\": \"タブで現在選択しているコードヒントを挿入するには true\",\n\t\"DESCRIPTION_NO_HINTS_ON_DOT\": \". の入力時に JS コードヒントを自動表示しない場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS\": \"初期設定で JS 構文チェックのオプションが付いたオブジェクト\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_ASS\": \"代入式を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_BITWISE\": \"ビット演算子を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_BROWSER\": \"標準ブラウザーのグローバルを事前定義する必要がある場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\": \"Google Closure の慣用句を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\": \"continue ステートメントを許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_COUCH\": \"CouchDB グローバルを事前定義する必要がある場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_DEBUG\": \"デバッガーステートメントを許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_DEVEL\": \"開発に役立つブラウザーグローバルを事前定義する必要がある場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_EQEQ\": \"== と != を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_ES6\": \"ES6 グローバルを事前定義する必要がある場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_EVIL\": \"eval を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_FORIN\": \"フィルターされていない「for ... in」を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_INDENT\": \"タブ幅を指定\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_MAXERR\": \"報告する最大警告数\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\": \"1 行内の最大文字数\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\": \"小文字のコンストラクターを許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_NODE\": \"Node.js グローバルを事前定義する必要がある場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_NOMEN\": \"識別子での先頭のアンダースコアを許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\": \"最初のエラー発生時に停止するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\": \"++ と -- を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_REGEXP\": \"正規表現の . と [^...]. を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_RHINO\": \"Rhino グローバルを事前定義する必要がある場合は true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\": \"use strict プラグマの不足を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_STUPID\": \"ブロック ('...Sync') メソッドを使用できる場合は true。\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_SUB\": \"不完全な登録を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_TODO\": \"TODO コメントを許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\": \"未使用のパラメーターを許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_VARS\": \"関数で 2 つ以上の変数を許可するには true\",\n\t\"DESCRIPTION_JSLINT_OPTIONS_WHITE\": \"ホワイトスペースのルールを無視するには true\",\n\t\"DESCRIPTION_LANGUAGE\": \"言語固有の設定\",\n\t\"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\": \"ファイル拡張子から言語名への追加のマッピング\",\n\t\"DESCRIPTION_LANGUAGE_FILE_NAMES\": \"ファイル名から言語名への追加のマッピング\",\n\t\"DESCRIPTION_LINEWISE_COPY_CUT\": \"何も選択せずにコピーやカットを行うと、カーソルのあるすべての行がコピーまたはカットされます。\",\n\t\"DESCRIPTION_INPUT_STYLE\": \"CodeMirror による入力とフォーカスの処理方法を選択します。Textarea (初期設定) や counterditable (スクリーンリーダー向け)(不安定) などを選択できます\",\n\t\"DESCRIPTION_LINTING_ENABLED\": \"コード検証を有効にするには true\",\n\t\"DESCRIPTION_ASYNC_TIMEOUT\": \"非同期の構文チェックがタイムアウトするまでの時間 (ミリ秒)\",\n\t\"DESCRIPTION_LINTING_PREFER\": \"最初に実行する構文チェックの配列\",\n\t\"DESCRIPTION_LIVE_DEV_MULTIBROWSER\": \"試験ライブプレビューを有効にするには true\",\n\t\"DESCRIPTION_USE_PREFERED_ONLY\": \"linting.prefer のみで指定されたプロバイダーを実行するには true\",\n\t\"DESCRIPTION_MAX_CODE_HINTS\": \"一度に表示される最大コードヒント\",\n\t\"DESCRIPTION_PATH\": \"パス固有の設定\",\n\t\"DESCRIPTION_PROXY\": \"拡張機能のインストールに使用するプロキシサーバーの URL\",\n\t\"DESCRIPTION_SCROLL_PAST_END\": \"ドキュメントの終端を超えたスクロールを有効にするには true\",\n\t\"DESCRIPTION_SHOW_CODE_HINTS\": \"すべてのコードヒントを無効にするには false\",\n\t\"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\": \"文字が選択されているときに点滅カーソルを表示したままにします\",\n\t\"DESCRIPTION_SHOW_LINE_NUMBERS\": \"コードの左の「余白」に行番号を表示するには true\",\n\t\"DESCRIPTION_SMART_INDENT\": \"新規ブロックの作成時に自動的にインデントを設定\",\n\t\"DESCRIPTION_SOFT_TABS\": \"ソフトタブの動作を無効にするには false\",\n\t\"DESCRIPTION_SORT_DIRECTORIES_FIRST\": \"プロジェクトツリーでディレクトリが先に来るように並べ替えるには true\",\n\t\"DESCRIPTION_SPACE_UNITS\": \"スペースベースのインデントに用いるスペースの数\",\n\t\"DESCRIPTION_STATIC_SERVER_PORT\": \"組み込みのサーバーがライブプレビューで使用するポートの番号\",\n\t\"DESCRIPTION_STYLE_ACTIVE_LINE\": \"カーソルが置かれた線の背景色をハイライト表示するには true\",\n\t\"DESCRIPTION_TAB_SIZE\": \"タブに表示するスペースの数\",\n\t\"DESCRIPTION_USE_TAB_CHAR\": \"スペースの代わりにタブを使用するには true\",\n\t\"DESCRIPTION_UPPERCASE_COLORS\": \"Inline Color Editor で大文字の 16 進カラーを生成するには true\",\n\t\"DESCRIPTION_WORD_WRAP\": \"ビューポートの幅を超える行を折り返す\",\n\t\"DESCRIPTION_SEARCH_AUTOHIDE\": \"エディターがフォーカスされるとすぐに検索を閉じる\",\n\t\"DESCRIPTION_DETECTED_EXCLUSIONS\": \"Tern が制御不能になる原因として検出されたファイルの一覧\",\n\t\"DESCRIPTION_INFERENCE_TIMEOUT\": \"ファイルの認識時に Tern がタイムアウトするまでの時間\",\n\t\"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\": \"ステータスバーにエラーを表示するには true\",\n\t\"DESCRIPTION_QUICK_VIEW_ENABLED\": \"クイックビューを有効にするには true\",\n\t\"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\": \"URL のない拡張機能の画像プレビューを表示するには true\",\n\t\"DESCRIPTION_THEME\": \"{APP_NAME} のテーマを選択\",\n\t\"DESCRIPTION_USE_THEME_SCROLLBARS\": \"カスタムスクロールバーを許可するには true\",\n\t\"DESCRIPTION_LINTING_COLLAPSED\": \"構文チェックパネルを閉じるには true\",\n\t\"DESCRIPTION_FONT_FAMILY\": \"フォントファミリーを変更\",\n\t\"DESCRIPTION_FONT_SIZE\": \"フォントサイズを変更 (例 : 13 px)\",\n\t\"DESCRIPTION_FIND_IN_FILES_NODE\": \"ノードベースの検索を有効にするには true\",\n\t\"DESCRIPTION_FIND_IN_FILES_INSTANT\": \"クイック検索を有効にするには true\",\n\t\"DESCRIPTION_FONT_SMOOTHING\": \"Mac のみ : サブピクセルアンチエイリアスを有効にするには subpixel-antialiased、グレースケールアンチエイリアスの場合は antialiased\",\n\t\"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\": \"分割ビューで環境設定ファイルを開けないようにするには false\",\n\t\"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\": \"左側/上部のペインでユーザーの環境設定ファイルを開くには false\",\n\t\"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\": \"ペインからの最後のファイルがペインのヘッダーの閉じるボタンにより閉じられた後、ペインを折りたたむには true\",\n\t\"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\": \"ヘッダーの閉じるボタンと反転表示ボタンを表示するタイミングを切り替えます。\",\n\t\"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\": \"/*\\n * これは、{APP_NAME} がサポートしている環境設定が 記録された読み取り\\n * 専用ファイルです。\\n * もう片方のペインで開かれた環境設定ファイル brackets.json を変更\\n * する際の参考としてお使いください。\\n * {APP_NAME} 内で環境設定を使用する方法について は、Web ページ\\n * https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n * を参照してください。\\n*/\",\n\t\"DEFAULT_PREFERENCES_JSON_DEFAULT\": \"デフォルト\",\n\t\"DESCRIPTION_PURE_CODING_SURFACE\": \"{APP_NAME} でコードのみモードを有効にし、その他すべての UI エレメントを非表示にするには true\",\n\t\"DESCRIPTION_INDENT_LINE_COMMENT\": \"行コメントのインデントを有効にするには true\",\n\t\"DESCRIPTION_RECENT_FILES_NAV\": \"最近使用したファイルのナビゲーションを有効化/無効化\",\n\t\"DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\": \"ライブプレビューで WebSocket サーバーが実行されるポート\",\n\t\"DESCRIPTION_LIVE_DEV_HIGHLIGHT_SETTINGS\": \"ライブプレビューハイライト設定\",\n\t\"DESCRIPTION_LIVEDEV_ENABLE_REVERSE_INSPECT\": \"false にすると、ライブプレビューでのリバースインスペクトが無効になります\",\n    \n    // Strings for Auto Update\n\t\"DOWNLOAD_FAILED\": \"ダウンロードに失敗しました。\",\n\t\"DOWNLOAD_COMPLETE\": \"ダウンロードが完了しました。\",\n\t\"UPDATE_SUCCESSFUL\": \"アップデートが正常に完了しました。\",\n\t\"UPDATE_FAILED\": \"アップデートに失敗しました。\",\n\t\"VALIDATION_FAILED\": \"検証に失敗しました。\",\n\t\"INITIALISATION_FAILED\": \"初期化に失敗しました。\",\n\t\"CLEANUP_FAILED\": \"クリーンアップに失敗しました。\",\n\t\"WARNING_TYPE\": \"警告\",\n\t\"CLICK_RESTART_TO_UPDATE\": \"Brackets をアップデートするには、「再起動」をクリックしてください。\",\n\t\"UPDATE_ON_NEXT_LAUNCH\": \"アップデートは再起動時に適用されます。\",\n\t\"GO_TO_SITE\": \"<a href=\\\"http://brackets.io/\\\">brackets.io</a> に移動して、再試行します。\",\n\t\"INTERNET_UNAVAILABLE\": \"インターネットに接続されていません.\",\n\t\"UPDATEDIR_READ_FAILED\": \"アップデートディレクトリを読み込めませんでした。\",\n\t\"UPDATEDIR_CLEAN_FAILED\": \"アップデートディレクトリを空にできませんでした。\",\n\t\"INITIAL_DOWNLOAD\": \"アップデートをダウンロード中...\",\n\t\"RETRY_DOWNLOAD\": \"ダウンロードに失敗しました。再試行...試行\",\n\t\"VALIDATING_INSTALLER\": \"ダウンロードが完了しました。インストーラーを検証中...\",\n\t\"CHECKSUM_DID_NOT_MATCH\": \"チェックサムが一致しませんでした。\",\n\t\"INSTALLER_NOT_FOUND\": \"インストーラーが見つかりません。\",\n\t\"DOWNLOAD_ERROR\": \"ダウンロード中にエラーが発生しました。\",\n\t\"NETWORK_SLOW_OR_DISCONNECTED\": \"ネットワーク接続がないか速度が遅すぎます。\",\n\t\"RESTART_BUTTON\": \"再起動\",\n\t\"LATER_BUTTON\": \"後で再起動\",\n\t\"DESCRIPTION_AUTO_UPDATE\": \"Brackets の自動更新を有効化/無効化\",\n\t\"AUTOUPDATE_ERROR\": \"エラー!\",\n\t\"AUTOUPDATE_IN_PROGRESS\": \"更新は既に進行中です。\",\n\n\t\"NUMBER_WITH_PERCENTAGE\": \"{0}%\",\n    // Strings for Related Files\n\t\"CMD_FIND_RELATED_FILES\": \"関連するファイルを検索\",\n\n    ///String for Php Tooling Extensions\n\t\"PHP_VERSION_INVALID\": \"PHP バージョンを解析する際のエラーです。“php –version” コマンドの出力を確認してください。\",\n\t\"PHP_UNSUPPORTED_VERSION\": \"コードヒント、パラメーターヒント、定義にジャンプなどの PHP 関連のツールを有効化するために、PHP7 ランタイムをインストールしてください。検出されたバージョン: {0}\",\n\t\"PHP_EXECUTABLE_NOT_FOUND\": \"PHP ランタイムが見つかりません。PHP7 ランタイムをインストールして、PHP の環境設定で適切に “executablePath” を更新してください。これにより、コードヒント、パラメーターヒント、定義にジャンプなどの PHP 関連のツールが有効になります。\",\n\t\"PHP_PROCESS_SPAWN_ERROR\": \"PHP プロセスを起動中に、エラーコード {0} が発生しました。\",\n\t\"PHP_SERVER_ERROR_TITLE\": \"エラー\",\n\t\"PHP_SERVER_MEMORY_LIMIT_INVALID\": \"指定したメモリ制限は無効です。正しい値を設定するために、PHP の環境設定を確認してください。\",\n\t\"DESCRIPTION_PHP_TOOLING_CONFIGURATION\": \"PHP ツールのデフォルト設定\",\n\t\"OPEN_PREFERENNCES\": \"環境設定を開く\",\n\n    //Strings for LanguageTools Preferences\n\t\"LANGUAGE_TOOLS_PREFERENCES\": \"言語ツールの設定\",\n\n\t\"FIND_ALL_REFERENCES\": \"すべての参照を検索\",\n\t\"REFERENCES_IN_FILES\": \"参照\",\n\t\"REFERENCE_IN_FILES\": \"参照\",\n\t\"REFERENCES_NO_RESULTS\": \"現在のカーソル位置で利用可能な参照はありません\",\n\n\t\"CMD_FIND_DOCUMENT_SYMBOLS\": \"ドキュメント記号を検索\",\n\t\"CMD_FIND_PROJECT_SYMBOLS\": \"プロジェクト記号を検索\",\n\n   // Remote debugging enabled\n\t\"REMOTE_DEBUGGING_ENABLED\": \"次のローカルホストでリモートデバッグが有効になりました。localhost:\",\n\n   // Remote debugging port argument is invalid\n\t\"REMOTE_DEBUGGING_PORT_INVALID\": \"ポート {0} でリモートデバッグを有効にできません。ポート番号は、{1} から {2} の間で指定してください。\",\n    \n    //Associate File Type to External App\n\t\"DESCRIPTION_EXTERNAL_APPLICATION_ASSOCIATE\": \"ファイル拡張子の外部アプリケーションへのマッピング。構文: \\\"<file_type>\\\": \\\"<default|applicationName|ApplicationPath>\\\"。「default」を指定すると、そのファイルタイプに対してシステムでデフォルトに設定されているアプリケーションを使用してファイルが開きます。\",\n\n\t\"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_TITLE\": \"外部エディターでグラフィックファイルを開きます。\",\n\t\"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_MSG\": \"現在のフォルダーには、{APP_NAME}でサポートされていないタイプのグラフィックファイルがあります。<br/>ここで、特定のファイルタイプを外部エディターに関連付けることができます。関連付けが完了すると、xd、.psd、.jpg、.png、.ai、.svgなどのグラフィックファイルをファイルツリーでダブルクリックすることで、デフォルトのアプリケーションで開くことができます。<br/><br/>「OK」ボタンをクリックして、グラフィックファイルタイプをそれぞれのデフォルトアプリケーションに関連付けてください。\",\n\t\"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_CNF_MSG\": \"次のファイルタイプが、デフォルトのアプリケーションに関連付けられました。<br/>{0} この設定は、brackets.json でファイルタイプの関連付けを削除し、新しい関連付けを追加するか、デバッグ／環境設定ファイルを開くメニューにアクセスして変更できます。\"\n\n\n});\n"
  },
  {
    "path": "src/nls/ja/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"ja/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_jp/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.ja\"\n});\n"
  },
  {
    "path": "src/nls/ko/strings.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\": \"(에러 {0})\",\n    \"NOT_FOUND_ERR\": \"파일을 찾을 수 없습니다.\",\n    \"NOT_READABLE_ERR\": \"파일을 읽을 수 없습니다.\",\n    \"EXCEEDS_MAX_FILE_SIZE\": \"{0} MB보다 큰 파일은 {APP_NAME}에서 열 수 없습니다.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\": \"대상 디렉토리를 변경할 수 없습니다.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\": \"파일을 수정할 수 있는 권한이 없습니다.\",\n    \"CONTENTS_MODIFIED_ERR\": \"{APP_NAME} 외부에서 파일이 변경되었습니다.\",\n    \"UNSUPPORTED_ENCODING_ERR\": \"{APP_NAME}는 현재 UTF-8 인코딩된 파일만 지원합니다.\",\n    \"FILE_EXISTS_ERR\": \"파일 또는 디렉토리가 이미 있습니다.\",\n    \"FILE\": \"파일\",\n    \"FILE_TITLE\": \"파일\",\n    \"DIRECTORY\": \"디렉토리\",\n    \"DIRECTORY_TITLE\": \"디렉토리\",\n    \"DIRECTORY_NAMES_LEDE\": \"디렉토리 이름\",\n    \"FILENAMES_LEDE\": \"파일 이름\",\n    \"FILENAME\": \"파일 이름\",\n    \"DIRECTORY_NAME\": \"디렉토리 이름\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\": \"프로젝트 로드에 실패했습니다\",\n    \"OPEN_DIALOG_ERROR\": \"'파일 열기' 대화 상자를 표시 하는 중 에러가 발생했습니다. (에러 {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\": \"디렉토리 <span class='dialog-filename'>{0}</span>을 읽는 중 에러가 발생했습니다. (에러 {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\": \"디렉토리 <span class='dialog-filename'>{0}</span>의 내용을 읽는 중에 에러가 발생했습니다. (에러 {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\": \"파일을 열던 중에 에러가 발생했습니다.\",\n    \"ERROR_OPENING_FILE\": \"파일 <span class='dialog-filename'>{0}</span>을 열던 중에 에러가 발생했습니다. {1}\",\n    \"ERROR_OPENING_FILES\": \"다음의 파일을 열던 중에 에러가 발생했습니다 :\",\n    \"ERROR_RELOADING_FILE_TITLE\": \"디스크에서 변경 내용을 다시 로드 하던 중에 에러가 발생했습니다.\",\n    \"ERROR_RELOADING_FILE\": \"파일 <span class='dialog-filename'>{0}</span>을 다시 읽어 오던 중에 에러가 발생했습니다. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\": \"파일을 저장하는 동안 에러가 발생했습니다.\",\n    \"ERROR_SAVING_FILE\": \"파일 <span class='dialog-filename'>{0}</span>을 저장하던 중에 에러가 발생했습니다. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\": \"파일의 이름을 변경하던 중에 에러가 발생했습니다.\",\n    \"ERROR_RENAMING_FILE\": \"파일 <span class='dialog-filename'>{0}</span>의 이름을 변경하던 중에 에러가 발생했습니다. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\": \"파일 삭제 에러\",\n    \"ERROR_DELETING_FILE\": \"파일을 삭제할 때 에러가 발생했습니다 <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\": \"잘못된 {0}이름\",\n    \"INVALID_FILENAME_MESSAGE\": \"파일 이름에는 다음 문자를 포함 할 수 없습니다: {0} 또는 시스템의 모든 예약어\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\": \"<span class='dialog-filename'>{0}</span> 이름을 가진 파일 또는 디렉토리가 이미 존재합니다.\",\n    \"ERROR_CREATING_FILE_TITLE\": \"{0}를 만들던 중에 에러가 발생했습니다\",\n    \"ERROR_CREATING_FILE\": \"{0} <span class='dialog-filename'>{1}</span>를 만들던 중에 에러가 발생했습니다.{2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"다른 파일을 여는 도중에는 폴더를 열 수 없습니다.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"사용자 키맵 파일을 읽는 중 에러가 발생했습니다\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"키맵 파일의 JSON 형식이 올바르지 않습니다. 형식을 올바르게 수정할 수 있도록 파일이 열릴 것입니다\",\n    \"ERROR_LOADING_KEYMAP\"              : \"키맵 파일이 올바르지 않은 UTF-8로 인코딩되어 있어 읽을 수 없습니다\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"다음 명령에 대한 단축키를 다시 설정할 수 없습니다: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"다음 단축키를 다시 설정할 수 없습니다: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"다음 명령에 대해 단축키를 여러 개 할당하려 했습니다: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"다음 단축키에 대해 여러 개의 명령어가 설정되어 있습니다: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"다음 단축키는 올바르지 않습니다: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"존재하지 안는 명령어애 단축키를 설정했습니다: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"환경설정을 읽는 중 에러가 발생했습니다\",\n    \"ERROR_PREFS_CORRUPT\"               : \"환경설정 파일의 JSON 형식이 올바르지 않습니다. 형식을 올바르게 수정할 수 있도록 파일이 열릴 것입니다. 수정한 내용을 반영하려면 {APP_NAME}를 재시작해야 합니다.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"프로젝트 환경설정 파일의 JSON 형식이 올바르지 않습니다. 형식을 올바르게 수정할 수 있도록 파일이 열릴 것입니다. 변경 사항을 적용하려면 프로젝트를 다시 로드해야 합니다.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\": \"{APP_NAME}는 아직 브라우저에서 실행되지 않습니다.\",\n    \"ERROR_IN_BROWSER\": \"{APP_NAME}는 HTML로 구축되어 있지만 데스크톱 응용 프로그램으로 실행하여 로컬 파일을 편집 할 수 있습니다. {APP_NAME}를 실행하기 위해 <b>github.com / adobe / brackets-shell</b> 저장소 응용 프로그램 셸을 사용하십시오.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\": \"파일을 인덱스 하던 중에 에러가 발생했습니다.\",\n    \"ERROR_MAX_FILES\": \"인덱싱 할 수 있는 파일의 최대 수에 도달했습니다. 인덱스에서 파일 검색 기능이 제대로 작동하지 않을 수 있습니다.\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\": \"브라우저 시작 에러\",\n    \"ERROR_CANT_FIND_CHROME\": \"Google Chrome 브라우저를 찾을 수 없습니다. 설치되어 있는지 확인하십시오.\",\n    \"ERROR_LAUNCHING_BROWSER\": \"브라우저를 시작하던 중에 에러가 발생했습니다. (에러 {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\": \"실시간 미리보기 에러\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\": \"브라우저에 연결합니다\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\": \"실시간 미리보기에 연결하려면 원격 디버깅을 사용하여 Chrome을 다시 시작해야 합니다. <br /> Chrome을 다시 시작하고 원격 디버깅을 사용하시겠습니까?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\": \"실시간 미리보기 페이지를 읽을 수 없습니다.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\": \"실시간 미리보기를 시작하려면 HTML 파일을 열거나 index.html 파일이 프로젝트에 포함되어 있는지 확인하십시오.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\": \"서버 측 파일 실시간 미리보기를 시작하려면 이 프로젝트의 기본 URL을 지정해야 합니다.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\": \"실시간 미리보기에 사용되는 HTTP 서버를 시작할 때 에러가 발생했습니다. 잠시 후에 다시 시도하세요.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\": \"실시간 미리보기에 오신 것을 환영합니다\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\": \"{APP_NAME}가 실시간 미리보기를 통해 브라우저에 연결됐습니다. HTML 파일이 수정되면 브라우저에서 미리보기가 즉시 업데이트됩니다. <br />현재 사용 중인 {APP_NAME}의 초기 버전에서는 <strong>Google Chrome</strong> 에서만 실시간 미리보기를 지원하며, <strong>CSS 또는 HTML 파일</strong>을 편집할 때만 실시간으로 업데이트됩니다. 자바스크립트 파일에 대한 변경 사항은 저장할 때 자동으로 다시 로드됩니다. (이 메시지는 한 번만 표시됩니다)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\": \"자세한 내용은 <a href='{0}' title='{0}'> Live Development 연결 오류 문제 해결 </a>를 참조하세요.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\": \"실시간 미리보기\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\": \"실시간 미리보기: 연결 중 \\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\": \"실시간 미리보기: 초기화 중\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\": \"실시간 미리보기가 연결되었습니다.\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\": \"실시간 미리보기 (파일을 저장하고 업데이트)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\": \"실시간 프리 (구문 오류로 인해 업데이트되지 않습니다)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\": \"브라우저의 개발 도구가 열려 있기 때문에 실시간 미리보기가 취소되었습니다뷰.\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\": \"브라우저에서 페이지가 닫혀 있으므로 실시간 미리보기가 취소되었습니다.\",\n    \"LIVE_DEV_NAVIGATED_AWAY\": \"브라우저에서 현재 프로젝트에 포함되지 않은 페이지로 이동했기 때문에 실시간 미리보기가 취소되었습니다.\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\": \"알 수없는 원인 ({0})에 의해 실시간 미리보기가 취소되었습니다.\",\n\n    \"SAVE_CLOSE_TITLE\": \"변경 사항 저장\",\n    \"SAVE_CLOSE_MESSAGE\": \"문서 <span class='dialog-filename'>{0}</span> 변경 내용을 저장 하시겠습니까?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\": \"다음 파일에 대한 변경 사항을 저장 하시겠습니까?\",\n    \"EXT_MODIFIED_TITLE\": \"외부 변경 감지\",\n    \"CONFIRM_DELETE_TITLE\": \"삭제 확인\",\n    \"CONFIRM_FOLDER_DELETE\": \"<span class='dialog-filename'>{0}</span> 폴더를 삭제 하시겠습니까?\",\n    \"FILE_DELETED_TITLE\": \"파일이 삭제되었습니다\",\n    \"EXT_MODIFIED_WARNING\": \"<span class='dialog-filename'>{0}</span>파일이 변경되었습니다.<br /><br />파일을 저장하여 이 변경 사항을 덮어씌우겠습니까?\",\n    \"EXT_MODIFIED_MESSAGE\": \"<span class='dialog-filename'>{0}</span>파일에 저장되지 않은 변경 사항이 있습니다. <br /> 두 버전을 유지 하시겠습니까?\",\n    \"EXT_DELETED_MESSAGE\": \"<span class='dialog-filename'>{0}</span>파일은 삭제되었지만 저장되지 않은 변경 사항이 있습니다. <br /> 변경을 유지 하시겠습니까?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"완료\",\n    \"OK\": \"확인\",\n    \"CANCEL\": \"취소\",\n    \"DONT_SAVE\": \"저장하지 않음\",\n    \"SAVE\": \"저장\",\n    \"SAVE_AS\": \"다른 이름으로 저장\\u2026\",\n    \"SAVE_AND_OVERWRITE\": \"덮어쓰기\",\n    \"DELETE\": \"삭제\",\n    \"BUTTON_YES\": \"예\",\n    \"BUTTON_NO\": \"아니오\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\": \"{1}개 중 {0}번째\",\n    \"FIND_NO_RESULTS\": \"결과 없음\",\n    \"FIND_QUERY_PLACEHOLDER\": \"검색할 내용\\u2026\",\n    \"REPLACE_PLACEHOLDER\": \"바꿀 내용\\u2026\",\n    \"BUTTON_REPLACE_ALL\": \"일괄 변경\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\": \"바꾸기\\u2026\",\n    \"BUTTON_REPLACE\": \"바꾸기\",\n    \"BUTTON_NEXT\": \"\\u25B6\",\n    \"BUTTON_PREV\": \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\": \"다음 항목으로 이동\",\n    \"BUTTON_PREV_HINT\": \"이전 항목으로 이동\",\n    \"BUTTON_CASESENSITIVE_HINT\": \"대소문자 구별\",\n    \"BUTTON_REGEXP_HINT\": \"정규식\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"복원할 수 없는 바꾸기\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"{0}개 이상의 파일을 수정해야 하므로, {APP_NAME}는 열지 않은 파일도 수정할 것입니다.<br />열지 않은 파일에서 바꾼 내용은 복원할 수 없습니다.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"바꾸기\",\n\n    \"OPEN_FILE\": \"파일 열기\",\n    \"SAVE_FILE_AS\": \"다른 이름으로 저장\",\n    \"CHOOSE_FOLDER\": \"폴더 선택\",\n\n    \"RELEASE_NOTES\": \"릴리즈 노트\",\n    \"NO_UPDATE_TITLE\": \"최신 버전입니다.\",\n    \"NO_UPDATE_MESSAGE\": \"{APP_NAME} 최신 버전을 사용중입니다.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"바꾸기:\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"\\u2192\",\n    \"FIND_TITLE_LABEL\"                  : \"찾기:\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {3}에서 {1}개를 찾았습니다\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0}개 {1}\",\n    \"FIND_IN_FILES_SCOPED\": \"<span class='dialog-filename'>{0}</span>의\",\n    \"FIND_IN_FILES_NO_SCOPE\": \"프로젝트\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"검색 규칙이 {0}의 파일을 모두 대상에서 제외시켰습니다.\",\n    \"FIND_IN_FILES_FILE\": \"파일\",\n    \"FIND_IN_FILES_FILES\": \"파일\",\n    \"FIND_IN_FILES_MATCH\": \"을 찾았습니다\",\n    \"FIND_IN_FILES_MATCHES\": \"을 찾았습니다\",\n    \"FIND_IN_FILES_MORE_THAN\": \"이상\",\n    \"FIND_IN_FILES_PAGING\": \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\": \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd를 클릭하면 전부 펼치거나 접습니다\",\n    \"FIND_IN_FILES_INDEXING\"            : \"빠른 검색을 위한 색인 중\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"바꾸기 에러\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"다음 파일은 검색 후에 변경되었거나 저장할 수 없는 파일이므로 수정할 수 없습니다.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\": \"업데이트 정보를 검색하는 중 오류가 발생했습니다.\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\": \"서버에서 최신 업데이트를 검색하는 중 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도하세요.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"검색 제외 규칙\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"제외할 파일 없음\",\n    \"NO_FILE_FILTER\"                    : \"제외할 파일 없음\",\n    \"EXCLUDE_FILE_FILTER\"               : \"{0} 제외\",\n    \"EDIT_FILE_FILTER\"                  : \"수정\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"검색 제외 규칙 편집\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"다음에 입력한 문자열에 전체나 일부 혹은 <a href='{0}' title='{0}'>와일드 카드</a>에 일치하는 파일과 폴더를 검색에서 제외합니다. 각 문자열은 한 줄에 하나씩 입력하세요.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"이 제외 규칙의 이름 (생략가능)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"and {0} more\",\n    \"FILTER_COUNTING_FILES\"             : \"파일 계산 중\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"{2}의 전체 {1}개 파일/폴더 중 {0}개 제외\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"전체 {1}개 파일/폴더 중 {0}개 제외\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"현재 커서 위치에서는 빠른 편집을 사용할 수 없습니다\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS 빠른 편집: 커서를 클래스 이름 위에 두세요\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS 빠른 편집: 완료되지 않은 class 속성입니다\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS 빠른 편집: 완료되지 않은 id 속성입니다\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS 빠른 편집: 커서를 태그, 클래스 또는 아이디에 두세요\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS 타이밍 함수 빠른 편집:  문법이 올바르지 않습니다\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS 빠른 편집: 커서를 함수 이름에 두세요\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"현재 커서 위치에서는 빠른 문서보기를 사용할 수 없습니다\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\": \"프로젝트 여는 중\\u2026\",\n    \"UNTITLED\": \"제목 없음\",\n    \"WORKING_FILES\": \"현재 파일\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"위\",\n    \"BOTTOM\"            : \"아래\",\n    \"LEFT\"              : \"왼쪽\",\n    \"RIGHT\"             : \"오른쪽\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"나누지 않음\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"왼쪽/오른쪽으로 분할\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"위/아래로 분할\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"에디터를 왼쪽/오른쪽 또는 위/아래로 분할합니다\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configure Working Set\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"이미 열려있는 파일\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"이 파일은 이미 다른 패널에서 열려있습니다. 이름이 같은 파일을 여러 패널에서 여는 기능은 곧 지원될 예정입니다. 그 전에는 이미 열려있던 파일은 해당 패널에서 보게될 것입니다.<br /><br />(이 메시지는 한 번만 나타납니다.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\": \"Ctrl\",\n    \"KEYBOARD_SHIFT\": \"Shift\",\n    \"KEYBOARD_SPACE\": \"Space\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\": \"행 {0}, 열 {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\": \" \\u2014 {0} 열을 선택\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\": \" \\u2014 {0} 열을 선택\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\": \" \\u2014 {0} 행을 선택\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\": \" \\u2014 {0} 행을 선택\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0}개 선택영역\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\": \"들여쓰기를 공백으로 변환\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\": \"들여쓰기를 탭으로 변환\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\": \"들여쓰기에 사용할 공백 갯수 변경\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\": \"탭 너비 변경\",\n    \"STATUSBAR_SPACES\": \"스페이스:\",\n    \"STATUSBAR_TAB_SIZE\": \"탭 폭:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\": \"\\u2014 {0} 행\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\": \"\\u2014 {0} 행\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"확장 기능 사용 불가\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"클릭하면 커서를 삽입(INS)또는 덮어쓰기(OVR) 모드로 전환합니다\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"파일 종류를 변경하려면 클릭하세요\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. 클릭하면 기록 패널을 토글합니다.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(기본값)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \".{0} 파일에 대한 기본값으로 설정\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0}개의 에러\",\n    \"SINGLE_ERROR\": \"1개의 {0} 에러\",\n    \"MULTIPLE_ERRORS\": \"{1}개의 {0} 에러\",\n    \"NO_ERRORS\": \"{0} 에러가 없습니다 - 훌륭합니다!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"에러가 없습니다 - 훌륭합니다!\",\n    \"LINT_DISABLED\": \"Lint 검사를 사용할 수 없습니다.\",\n    \"NO_LINT_AVAILABLE\": \"{0} 사용할 수 있는 Lint 검사기가 없습니다.\",\n    \"NOTHING_TO_LINT\": \"Lint 검사기로 확인할 파일이 없습니다.\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} 검사기가 {1}ms 대기 후 타임아웃 되었습니다\",\n    \"LINTER_FAILED\"                         : \"{0} 검사기가 에러때문에 종료되었습니다: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\": \"파일\",\n    \"CMD_FILE_NEW_UNTITLED\": \"새 파일\",\n    \"CMD_FILE_NEW\": \"파일 만들기\",\n    \"CMD_FILE_NEW_FOLDER\": \"폴더 만들기\",\n    \"CMD_FILE_OPEN\": \"파일 열기\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\": \"작업세트에 추가\",\n    \"CMD_OPEN_DROPPED_FILES\": \"드롭한 파일 열기\",\n    \"CMD_OPEN_FOLDER\": \"폴더 열기\\u2026\",\n    \"CMD_FILE_CLOSE\": \"닫기\",\n    \"CMD_FILE_CLOSE_ALL\": \"모두 닫기\",\n    \"CMD_FILE_CLOSE_LIST\": \"목록 닫기\",\n    \"CMD_FILE_CLOSE_OTHERS\": \"다른 파일 닫기\",\n    \"CMD_FILE_CLOSE_ABOVE\": \"위의 목록 닫기\",\n    \"CMD_FILE_CLOSE_BELOW\": \"아래 목록 닫기\",\n    \"CMD_FILE_SAVE\": \"저장\",\n    \"CMD_FILE_SAVE_ALL\": \"모두 저장\",\n    \"CMD_FILE_SAVE_AS\": \"다른 이름으로 저장\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\": \"실시간 미리보기\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"실험적 실시간 미리보기 활성화\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"실시간 미리보기 다시 읽기\",\n    \"CMD_PROJECT_SETTINGS\": \"프로젝트 설정\\u2026\",\n    \"CMD_FILE_RENAME\": \"파일명 변경\",\n    \"CMD_FILE_DELETE\": \"삭제\",\n    \"CMD_INSTALL_EXTENSION\": \"확장 기능 설치\\u2026\",\n    \"CMD_EXTENSION_MANAGER\": \"확장 기능 관리자\\u2026\",\n    \"CMD_FILE_REFRESH\": \"파일 트리 업데이트\",\n    \"CMD_QUIT\": \"종료\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\": \"종료\",\n\n    // Edit menu commands\n    \"EDIT_MENU\": \"편집\",\n    \"CMD_UNDO\": \"되돌리기\",\n    \"CMD_REDO\": \"재실행\",\n    \"CMD_CUT\": \"오려두기\",\n    \"CMD_COPY\": \"복사하기\",\n    \"CMD_PASTE\": \"붙여넣기\",\n    \"CMD_SELECT_ALL\": \"전체 선택\",\n    \"CMD_SELECT_LINE\": \"행 선택\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"선택영역을 여러 줄로 나누기\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"아랫줄에 커서 추가\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"윗줄에 커서 추가\",\n    \"CMD_INDENT\": \"들여쓰기\",\n    \"CMD_UNINDENT\": \"내어쓰기\",\n    \"CMD_DUPLICATE\": \"행 복사\",\n    \"CMD_DELETE_LINES\": \"행 삭제\",\n    \"CMD_COMMENT\": \"행 주석처리\",\n    \"CMD_BLOCK_COMMENT\": \"블록 주석처리\",\n    \"CMD_LINE_UP\": \"행을 위로 이동\",\n    \"CMD_LINE_DOWN\": \"행을 아래로 이동\",\n    \"CMD_OPEN_LINE_ABOVE\": \"상단에 라인 열기\",\n    \"CMD_OPEN_LINE_BELOW\": \"하단에 라인 열기\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\": \"자동 괄호\",\n    \"CMD_SHOW_CODE_HINTS\": \"코드 힌트 표시\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"검색\",\n    \"CMD_FIND\"                            : \"찾기\",\n    \"CMD_FIND_NEXT\"                       : \"다음 찾기\",\n    \"CMD_FIND_PREVIOUS\"                   : \"이전 찾기\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"전부 찾은 후 선택\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"다음 일치하는 단어 찾은 후 선택영역에 추가\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"현재 영역 건너뛰고 다음 찾기\",\n    \"CMD_FIND_IN_FILES\"                   : \"파일에서 찾기\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"다음에서 찾기\\u2026\",\n    \"CMD_REPLACE\"                         : \"바꾸기\",\n    \"CMD_REPLACE_IN_FILES\"                : \"파일에서 바꾸기\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"다음에서 바꾸기\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\": \"보기\",\n    \"CMD_HIDE_SIDEBAR\": \"사이드 바 숨기기\",\n    \"CMD_SHOW_SIDEBAR\": \"사이드 바 표시\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"사이드바 표시 전환\",\n    \"CMD_TOGGLE_PANELS\"                   : \"패널 표시 전환\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"코드만 보기\",\n    \"CMD_INCREASE_FONT_SIZE\": \"폰트 크기 키우기\",\n    \"CMD_DECREASE_FONT_SIZE\": \"폰트 크기 줄이기\",\n    \"CMD_RESTORE_FONT_SIZE\": \"폰트 크기 초기화\",\n    \"CMD_SCROLL_LINE_UP\": \"한줄 위로 스크롤\",\n    \"CMD_SCROLL_LINE_DOWN\": \"한줄 아래로 스크롤\",\n    \"CMD_TOGGLE_LINE_NUMBERS\": \"행 번호 보이기\",\n    \"CMD_TOGGLE_ACTIVE_LINE\": \"활성 행 하이라이트\",\n    \"CMD_TOGGLE_WORD_WRAP\": \"자동 줄바꿈\",\n    \"CMD_LIVE_HIGHLIGHT\": \"실시간 미리보기 하이라이트\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\": \"저장시 파일 Lint표시\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\": \"추가순으로 작업세트 정렬\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\": \"이름순으로 작업세트 정렬\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\": \"타입별로 작업세트 정렬\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\": \"자동으로 작업세트 정렬\",\n    \"CMD_THEMES\"                          : \"테마\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\": \"탐색\",\n    \"CMD_QUICK_OPEN\": \"빠른 열기\",\n    \"CMD_GOTO_LINE\": \"행으로 이동\",\n    \"CMD_GOTO_DEFINITION\": \"빠른 정의 검색\",\n    \"CMD_GOTO_FIRST_PROBLEM\": \"최초의 에러 또는 경고로 이동\",\n    \"CMD_TOGGLE_QUICK_EDIT\": \"빠른 편집\",\n    \"CMD_TOGGLE_QUICK_DOCS\": \"빠른 문서보기\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\": \"이전 결과로 이동\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\": \"다음 결과로 이동\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\": \"새 규칙\",\n    \"CMD_NEXT_DOC\": \"다음 문서\",\n    \"CMD_PREV_DOC\": \"이전 문서\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"목록의 다음 문서\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"목록의 이전 문서\",\n    \"CMD_SHOW_IN_TREE\": \"파일트리에서 보기\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"탐색기에서 보기\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"파인더에서 보기\",\n    \"CMD_SHOW_IN_OS\": \"파일 위치 열기\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"도움말\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"업데이트 확인\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"{APP_NAME} 사용법\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} 지원\",\n    \"CMD_SUGGEST\"                         : \"기능 제안\",\n    \"CMD_RELEASE_NOTES\"                   : \"릴리즈 노트\",\n    \"CMD_GET_INVOLVED\"                    : \"프로젝트 참여\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"확장 기능 폴더 열기\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"상태 보고서\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} 홈페이지\",\n    \"CMD_TWITTER\"                         : \"Twitter에서 {TWITTER_NAME} 팔로우하기\",\n    \"CMD_ABOUT\"                           : \"{APP_TITLE} 정보\",\n    \"CMD_OPEN_PREFERENCES\"                : \"환경설정 파일 열기\",\n    \"CMD_OPEN_KEYMAP\"                     : \"사용자 키맵 파일 열기\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\": \"시험 빌드\",\n    \"RELEASE_BUILD\"                        : \"빌드\",\n    \"DEVELOPMENT_BUILD\": \"개발 빌드\",\n    \"RELOAD_FROM_DISK\": \"디스크에서 다시 읽기\",\n    \"KEEP_CHANGES_IN_EDITOR\": \"편집기에서 변경 내용을 유지\",\n    \"CLOSE_DONT_SAVE\": \"저장하지 않고 닫기\",\n    \"RELAUNCH_CHROME\": \"Chrome 재시작\",\n    \"ABOUT\": \"이 소프트웨어에 대하여\",\n    \"CLOSE\": \"닫기\",\n    \"ABOUT_TEXT_LINE1\": \"스프린트 {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"빌드 시각: \",\n    \"ABOUT_TEXT_LINE3\": \"제3자 소프트웨어의 사용에 관한 공지, 이용 약관은 <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a>에 있으며 기록으로써 이곳에 존재합니다.\",\n    \"ABOUT_TEXT_LINE4\": \"문서와 소스 코드는 <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>에서 구할 수 있습니다.\",\n    \"ABOUT_TEXT_LINE5\": \"\\u2764 및 JavaScript를 사용하여 다음의 사람에 의해 작성되었습니다 :\",\n    \"ABOUT_TEXT_LINE6\": \"많은 사람들 (단, 인물 데이터 로딩에 문제가 발생하고 있습니다).\",\n    \"ABOUT_TEXT_MDN_DOCS\": \"MDN 문서와 MDN 로고는 크리에이티브 커먼즈 저작자표시 라이선스, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a> 로 배포됩니다.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\": \"{APP_NAME}의 새로운 빌드를 사용할 수 있습니다. 자세한 내용은 여기를 클릭하세요.\",\n    \"UPDATE_AVAILABLE_TITLE\": \"사용 가능한 업데이트가 있습니다\",\n    \"UPDATE_MESSAGE\": \"{APP_NAME}의 새로운 빌드를 사용할 수 있습니다. 새로운 기능의 일부를 다음에 소개합니다 :\",\n    \"GET_IT_NOW\": \"지금 다운로드\",\n    \"PROJECT_SETTINGS_TITLE\": \"프로젝트 설정 : {0}\",\n    \"PROJECT_SETTING_BASE_URL\": \"실시간 미리보기에 대한 기본 URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\": \"http://localhost:8000/ 등의 URL을 입력하여 로컬 서버를 사용\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\": \"{0} 프로토콜이 실시간 미리보기가 지원되지 않습니다. http: 또는 https:를 사용하세요.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\": \"기본 URL에는 「{0}」과(와) 같은 검색어를 사용할 수 없습니다.\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\": \"기본 URL에는 「{0}」과(와) 같은 해시 기호는 사용할 수 없습니다.\",\n    \"BASEURL_ERROR_INVALID_CHAR\": \"「{0}」과(와) 같은 특수 문자는 퍼센트로 인코딩해야합니다.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\": \"기본 URL의 구문을 분석하는 동안 알 수 없는 오류가 발생했습니다\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>이 창에 포커스가 있을 때 파일 열기</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"{0} 창에 이 보기를 반전\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"현재 테마\",\n    \"USE_THEME_SCROLLBARS\"                 : \"테마에서 정의한 스크롤바 적용\",\n    \"FONT_SIZE\"                            : \"글자 크기\",\n    \"FONT_FAMILY\"                          : \"글꼴\",\n    \"THEMES_SETTINGS\"                      : \"테마 설정\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\": \"새 규칙\",\n\n    // Extension Management strings\n    \"INSTALL\": \"설치\",\n    \"UPDATE\": \"업데이트\",\n    \"REMOVE\": \"삭제\",\n    \"DISABLE\"                              : \"비활성\",\n    \"ENABLE\"                               : \"활성\",\n    \"OVERWRITE\": \"덮어쓰기\",\n    \"CANT_REMOVE_DEV\": \"\\\"dev\\\" 폴더의 확장 기능은 수동으로 제거해야 합니다.\",\n    \"CANT_UPDATE\": \"업데이트가 이 버전의 {APP_NAME}와 호환되지 않습니다.\",\n    \"CANT_UPDATE_DEV\"                      : \"\\\"dev\\\" 폴더의 확장 기능은 자동으로 업데이트 할 수 없습니다.\",\n    \"INSTALL_EXTENSION_TITLE\": \"확장 기능 설치\",\n    \"UPDATE_EXTENSION_TITLE\": \"확장 기능 업데이트\",\n    \"INSTALL_EXTENSION_LABEL\": \"확장 기능 URL\",\n    \"INSTALL_EXTENSION_HINT\": \"확장 기능 zip 파일 또는 GitHub 저장소의 URL\",\n    \"INSTALLING_FROM\": \"{0}에서 확장 기능을 설치합니다\",\n    \"INSTALL_SUCCEEDED\": \"설치에 성공했습니다.\",\n    \"INSTALL_FAILED\": \"설치에 실패했습니다.\",\n    \"CANCELING_INSTALL\": \"설치 취소중\\u2026\",\n    \"CANCELING_HUNG\": \"설치 취소에 시간이 지연되고 있습니다. 내부 에러가 발생했을 수 있습니다.\",\n    \"INSTALL_CANCELED\": \"설치가 취소되었습니다.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"전체 설명 보기\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"설명 일부 숨기기\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\": \"다운로드 한 콘텐츠가 유효한 zip 파일이 아닙니다.\",\n    \"INVALID_PACKAGE_JSON\": \"package.json 파일이 유효하지 않습니다 (에러: {0})\",\n    \"MISSING_PACKAGE_NAME\": \"package.json 파일에 패키지 이름을 지정하지 않았습니다.\",\n    \"BAD_PACKAGE_NAME\": \"{0} 잘못된 패키지 이름입니다.\",\n    \"MISSING_PACKAGE_VERSION\": \"package.json 파일에 패키지 버전을 지정하지 않습니다.\",\n    \"INVALID_VERSION_NUMBER\": \"패키지 버전 번호 ({0})가 잘못되었습니다.\",\n    \"INVALID_BRACKETS_VERSION\": \"{APP_NAME} 호환 문자열 {0}이 잘못되었습니다.\",\n    \"DISALLOWED_WORDS\": \"{1} {0} 필드에서는 사용할 수 없습니다.\",\n    \"API_NOT_COMPATIBLE\": \"확장 기능은 이 버전의 {APP_NAME}와 호환되지 않습니다. 잘못된 확장 기능 폴더에 설치됩니다.\",\n    \"MISSING_MAIN\": \"패키지에 main.js 파일이 포함되어 있지 않습니다.\",\n    \"EXTENSION_ALREADY_INSTALLED\": \"이 패키지를 설치하면 이전에 설치한 확장 기능이 무시됩니다. 이전 확장을 덮어 쓰시겠습니까?\",\n    \"EXTENSION_SAME_VERSION\": \"이 패키지 버전은 현재 설치되어있는 버전과 동일합니다. 기존 설치를 겹쳐 쓰시겠습니까?\",\n    \"EXTENSION_OLDER_VERSION\": \"이 패키지 버전 ({0})은 현재 설치되어있는 버전 ({1})보다 이전 버전입니다. 기존 설치를 겹쳐 쓰시겠습니까?\",\n    \"DOWNLOAD_ID_IN_USE\": \"내부 에러: 이미 사용 중인 다운로드 ID 입니다.\",\n    \"NO_SERVER_RESPONSE\": \"서버에 연결할 수 없습니다.\",\n    \"BAD_HTTP_STATUS\": \"파일 서버 (HTTP {0})에 찾을 수 없습니다.\",\n    \"CANNOT_WRITE_TEMP\": \"임시 다운로드 파일을 저장할 수 없습니다.\",\n    \"ERROR_LOADING\": \"확장 기능 시작 중 오류가 발생했습니다\",\n    \"MALFORMED_URL\": \"URL이 잘못되었습니다. 제대로 입력되어 있는지 확인하세요.\",\n    \"UNSUPPORTED_PROTOCOL\": \"URL은 http 또는 https URL이어야합니다.\",\n    \"UNKNOWN_ERROR\": \"알 수 없는 내부 에러.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\": \"확장 기능 관리자\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\": \"확장 기능 레지스트리에 액세스 할 수 없습니다. 나중에 다시 시도하십시오.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"여기에 .zip 파일을 드래그하거나\",\n    \"INSTALL_EXTENSION_DROP\"               : \"파일을 드롭하면 설치를 시작합니다.\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"에러가 발생하여 설치/업데이트가 종료되었습니다:\",\n    \"INSTALL_FROM_URL\": \"URL에서 설치하세요\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"유효성 검사중\\u2026\",\n    \"EXTENSION_AUTHOR\": \"제작자\",\n    \"EXTENSION_DATE\": \"제작일\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\": \"이 확장 기능은 새 버전의 {APP_NAME}가 필요합니다.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\": \"이 확장 기능은 현재 이전 버전의 {APP_NAME}에서 작동하지 않습니다.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\": \"이 확장 기능 버전 {0}에는 {APP_NAME}의 새 버전이 필요합니다. 그러나 이전 버전 {1}을 설치할 수 있습니다.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\": \"이 확장 기능 버전 {0} {APP_NAME}의 이전 버전에서만 작동합니다. 그러나 이전 버전 {1}을 설치할 수 있습니다.\",\n    \"EXTENSION_NO_DESCRIPTION\": \"설명 없음\",\n    \"EXTENSION_MORE_INFO\": \"추가 정보...\",\n    \"EXTENSION_ERROR\": \"확장 기능 에러\",\n    \"EXTENSION_KEYWORDS\": \"키워드\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"{0}개 언어 지원. 한국어 포함\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"{0}개 언어 지원\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"이 확장 기능은 다음 언어를 지원합니다: {0}\",\n    \"EXTENSION_INSTALLED\": \"설치 완료\",\n    \"EXTENSION_UPDATE_INSTALLED\": \"이 확장 기능의 업데이트가 다운로드되었습니다. {APP_NAME}를 종료할 때 설치합니다.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\": \"검색\",\n    \"EXTENSION_MORE_INFO_LINK\": \"상세 정보\",\n    \"BROWSE_EXTENSIONS\": \"확장 기능 찾기\",\n    \"EXTENSION_MANAGER_REMOVE\": \"확장 기능 제거\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\": \"하나 이상의 확장 기능을 ({0}) 제거할 수 없습니다. {APP_NAME}가 종료 중입니다.\",\n    \"EXTENSION_MANAGER_UPDATE\": \"확장 기능 업데이트\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\": \"하나 이상의 확장 기능을 ({0}) 업데이트 할 수 없습니다. {APP_NAME}가 종료 중입니다.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"확장 기능 비활성\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"하나 이상의 확장 기능을 ({0}) 비활성화 할 수 없습니다. {APP_NAME}가 종료 중입니다.\",\n    \"MARKED_FOR_REMOVAL\": \"삭제 예정\",\n    \"UNDO_REMOVE\": \"삭제 취소\",\n    \"MARKED_FOR_UPDATE\": \"업데이트 예정\",\n    \"UNDO_UPDATE\": \"업데이트 취소\",\n    \"MARKED_FOR_DISABLING\"                 : \"비활성화 예정\",\n    \"UNDO_DISABLE\"                         : \"비활성화 취소\",\n    \"CHANGE_AND_RELOAD_TITLE\": \"확장 기능 변경\",\n    \"CHANGE_AND_RELOAD_MESSAGE\": \"업데이트 예정 또는 삭제 예정 확장 기능을 업데이트하거나 삭제하려면 {APP_NAME}를 재시작해야 합니다. 저장되지 않은 변경 내용은 저장여부를 확인합니다.\",\n    \"REMOVE_AND_RELOAD\": \"확장 기능을 제거하고 재시작\",\n    \"CHANGE_AND_RELOAD\": \"확장 기능을 변경하고 재시작\",\n    \"UPDATE_AND_RELOAD\": \"확장 기능을 업데이트하고 재시작\",\n    \"DISABLE_AND_RELOAD\"                   : \"확장 기능을 비활성화하고 재시작\",\n    \"PROCESSING_EXTENSIONS\"                : \"확장 기능 변경사항 처리 중\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\": \"설치되지 않았기 때문에 확장 기능 {0}을 삭제할 수 없습니다.\",\n    \"NO_EXTENSIONS\": \"설치되어있는 확장 기능이 아직 없습니다. <br>에서 「설치 가능」탭을 클릭하여 설치하세요.\",\n    \"NO_EXTENSION_MATCHES\": \"검색 조건에 일치하는 확장 기능이 없습니다.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\": \"알 수 없는 소스에서 확장 기능을 설치할 때 주의하세요.\",\n    \"EXTENSIONS_INSTALLED_TITLE\": \"설치됨\",\n    \"EXTENSIONS_AVAILABLE_TITLE\": \"설치 가능\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"테마\",\n    \"EXTENSIONS_UPDATES_TITLE\": \"업데이트\",\n\n    \"INLINE_EDITOR_NO_MATCHES\": \"일치하는 항목이 없습니다.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"All matches are collapsed. Expand the files listed at right to view matches.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\": \"선택 일치하는 기존 CSS 규칙이 없습니다. <br> 「새 규칙」을 클릭하여 규칙을 작성하세요.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\": \"프로젝트에는 스타일 시트가 없습니다. <br> 스타일 시트를 작성하여 CSS 규칙에 추가하세요.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"최대\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\": \"픽셀\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\": \"디버그\",\n    \"ERRORS\"                                    : \"에러\",\n    \"CMD_SHOW_DEV_TOOLS\": \"개발자 도구 보기\",\n    \"CMD_REFRESH_WINDOW\": \"{APP_NAME} 재시작\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"확장 기능 없이 재시작\",\n    \"CMD_NEW_BRACKETS_WINDOW\": \"새로운 {APP_NAME} 창\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"명령 줄 바로가기 설치\",\n    \"CMD_SWITCH_LANGUAGE\": \"언어 변경\",\n    \"CMD_RUN_UNIT_TESTS\": \"테스트 실행\",\n    \"CMD_SHOW_PERF_DATA\": \"성능 데이터를 표시\",\n    \"CMD_ENABLE_NODE_DEBUGGER\": \"Node Debugger 사용\",\n    \"CMD_LOG_NODE_STATE\": \"Node 상태를 콘솔에 기록\",\n    \"CMD_RESTART_NODE\": \"Node를 다시 시작\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"에러를 상태표시줄에 표시\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"{APP_NAME} 소스 열기\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} 명령 줄 바로가기\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"명령 줄 바로가기를 설치하는 동안 오류가 발생했습니다. <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>이런 문제를 해결하기 위한 제안</a>을 시도해 보세요.<br/><br/>원인: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"기존의 <code>/usr/local/bin/brackets</code> 심볼릭 링크를 제거할 수 없습니다.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"<code>/usr/local/bin</code> 디렉토리를 만들 수 없습니다.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"<code>/usr/local/bin/brackets</code> 심볼릭 링크를 만들 수 없습니다.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"내부 오류입니다.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"현재 운영체제(OS)가 명령줄 바로가기를 지원하지 않습니다.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"성공! 이제부터 명령 줄에서 쉽게 {APP_NAME}를 시작할 수 있습니다: 파일을 열기 위해 <code>brackets myFile.txt</code> 또는 프로젝트를 전환하기 위해 <code>brackets myFolder</code>. <br/><br/>명령 줄에서 {APP_NAME}를 사용하기 위한 <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>더 자세한 정보</a>.\",\n\n    \"LANGUAGE_TITLE\": \"언어 변경\",\n    \"LANGUAGE_MESSAGE\": \"언어:\",\n    \"LANGUAGE_SUBMIT\": \"{APP_NAME} 재시작\",\n    \"LANGUAGE_CANCEL\": \"취소\",\n    \"LANGUAGE_SYSTEM_DEFAULT\": \"시스템 언어\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"상태 보고서 환경설정\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} 상태 보고서\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"{APP_NAME} 사용 행태 정보를 익명으로 공유\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"{APP_NAME} 개선을 위해 고객이 {APP_NAME}를 어떻게 사용하는지에 관한 제한된 <strong>익명</strong> 통계를 Adobe에 주기적으로 전송합니다. 이 정보는 기능의 우선 순위를 정하고, 버그를 찾고, 사용성 문제를 해결하는데 도움을 줍니다.<br><br>고객의 데이터를 보거나 또는 데이터를 공유하지 않도록 하려면 <strong>도움말 > 상태 보고서</strong>를 선택하세요. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>{APP_NAME} 상태 보고서에 관한 자세한 정보.</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} 상태 보고서\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>{APP_NAME} 개선을 위해 고객이 {APP_NAME}를 어떻게 사용하는지에 관한 제한된 <strong>익명</strong> 통계를 Adobe에 주기적으로 전송하고 있습니다. 이 정보는 기능의 우선 순위를 정하고, 버그를 찾고, 사용성 문제를 해결하는데 도움을 줍니다. 고객의 개인정보를 보호하면서 {APP_NAME} 커뮤니티에 어떤 이득을 주는지 <a href='https://github.com/adobe/brackets/wiki/Health-Data'>{APP_NAME} 상태 보고서에 관해 자세히 알아보세요</a>.</p><p><em>만약</em> 상태 보고서 전송이 가능한 상태라면 아래 미리보기 데이터는 고객의 다음 번 상태 보고서로 전송할 것입니다.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\": \"시간\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\": \"진행\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Move selected point<br><kbd class='text'>Shift</kbd> Move by ten units<br><kbd class='text'>Tab</kbd> Switch points\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> 단계를 증가 또는 감소 <br><kbd>←</kbd><kbd>→</kbd> '시작' 또는 '끝내기'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"이전의 값 <code>{0}</code>이 유효하지 않으므로 표시된 기능이 <code>{1}</code>로 변경되었습니다. 문서가 첫 번째 수정으로 업데이트됩니다.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\": \"현재색\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\": \"원본색\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\": \"RGBa 형식\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\": \"16 진수\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\": \"HSLa 형식\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\": \"{0} ({1}시간 사용)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\": \"{0} ({1}시간 사용)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\": \"정의로 이동\",\n    \"CMD_SHOW_PARAMETER_HINT\": \"파라메터 정보를 표시\",\n    \"NO_ARGUMENTS\": \"<매개변수가 없습니다>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"자바스크립트 파일 추론 문제\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets에서 <span class='dialog-filename'>{0}</span> 파일을 처리하던 중 문제가 발생했습니다.<br><br>이 파일은 코드 힌트, 정의 이동, 빠른 편집 등에서 사용되지 않을 것입니다. 이 파일을 다시 사용하려면 프로젝트 폴더에 있는 <code>.brackets.json</code> 파일을 열고 <code>jscodehints.detectedExclusions</code> 항목을 수정하세요.<br><br>Backets의 버그일 수 있습니다. 이 파일의 사본을 제출할 수 있다면 여기서 말한 파일과 함께<a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>버그 보고</a>에 등록해주세요.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\": \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\": \"QuickView 사용\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\": \"최근에 사용한 프로젝트\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\": \"상세 정보\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"모두 접기\",\n    \"EXPAND_ALL\"                    : \"모두 펼치기\",\n    \"COLLAPSE_CURRENT\"              : \"현재 코드 접기\",\n    \"EXPAND_CURRENT\"                : \"현재 코드 펼치기\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"괄호(), 중괄호{}, 대괄호[]를 자동으로 닫으려면 true\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"작업중인 파일 콘텍스트 메뉴에서 \\\"위의 목록 닫기\\\"를 제거하려면 false\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"작업중인 파일 콘텍스트 메뉴에서 \\\"아래 목록 닫기\\\"를 제거하려면 false\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"작업중인 파일 콘텍스트 메뉴에서 \\\"다른 파일 닫기\\\"를 제거하려면 false\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"태그 종료 옵션 설정\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"자동으로 닫지 말아야 할 태그 목록\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"시작 태그 > 입력 시 닫기\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"종료 태그 / 입력 시 닫기\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"열릴 때 빈 줄 하나를 포함해야 하는 태그 목록\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"들여쓰기 수준을 변경할 때 접을 수 있는 섹션 마커를 항상 생성하려면 true\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"코드 접기를 활성화 하려면 true\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"빈 공간에 마우스 포인터를 두는 경우에만 섹션 접기 마커를 표시하려면 true\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"모두 접기를 얼마나 깊게 적용할 것인지 수준을 제한합니다\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"섹션 접기 아이콘을 표시하기 위한 최소 라인 수\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"파일 또는 프로젝트를 닫거나 다시 열 때 접은 섹션을 기억해야 한다면 true\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"편집기 안에서 선택한 텍스트에 대한 코드 접기 기능을 활성화 하려면 true\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"HTML 속성 힌트 활성/비활성\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"CSS/LESS/SCSS 속성 힌트 활성/비활성\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"JavaScript 코드 힌트 활성/비활성\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"JavaScript 코드 힌트에 데이터 타입 상세 활성/비활성\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"환경설정 코드 힌트 활성/비활성\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"HTML 엔터티 힌트 활성/비활성\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"SVG 코드 힌트 활성/비활성\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"HTML 태그 힌트 활성/비활성\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"HTML & CSS/LESS/SCSS의 URL 힌트 활성/비활성\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"드래그 앤 드롭 기능 활성/비활성\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"상태 데이터 추적 활성화\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"문서 내에서 일치하는 문자열 자동 강조 활성화\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"현재 커서가 있는 토큰과 일치하는 모든 문자열 강조(선택 불필요)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"선택 항목이 완전한 토큰인 경우에만 강조\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"탭에서 현재 선택한 코드 힌트를 삽입하려면 true\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \". 입력 시 JS 코드 힌트를 자동으로 표시하지 않으려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"JSLint 기본 옵션 적용 객체\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"할당 표현식을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"비트 연산자를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"표준 브라우저의 전역 변수를 미리 정의하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"구글 클로저 관용구를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"\\\"continue\\\" 문을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"CouchDB 전역 변수를 미리 정의해야 하는 경우 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"디버거 문을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"개발 편의를 위해 브라우저 전역 변수를 미리 정의하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"==과 !=를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"ES6 전역 변수를 미리 정의하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"eval을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"필터링하지 않은 \\\"for ... in\\\"을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"탭 폭 설정\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"최대 경고 수\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"한개 행 최대 문자 수\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"알파벳 대문자로 시작하지 않는 생성자를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"Node.js 전역 변수를 미리 정의하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"언더스코어(_)로 시작하는 식별자를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"첫 오류 발생 시 중지하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"++와 --를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"정규 표현식에서 .과 [^...].을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"Rhino 전역 변수를 미리 정의하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"`use strict` 지시어 생략을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"블록 ('...Sync') 메서드를 사용할 수 있는 경우 true.\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"비효율적인 첨자 지정을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"TODO 주석을 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"사용하지 않는 매개 변수를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"함수 안에서 하나 이상의 변수를 허용하려면 true\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"공백 규칙을 무시하려면 true\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"언어 별 설정\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"파일 확장자를 통해 언어 이름 매핑\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"파일 이름을 통해 언어 이름 매핑\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"코드 검사를 활성화 하려면 true\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"비동기 구문 검사 초과 시간을 밀리세컨드로 표기\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"최초 실행 구문 검사 배열\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"실험적 실시간 미리보기를 활성화 하려면 true\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"제공자에 의해 기술된 linting.prefer 만으로 실행하려면 true\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"한 번에 표시되는 최대 코드 힌트\",\n    \"DESCRIPTION_PATH\"                               : \"경로 별 설정\",\n    \"DESCRIPTION_PROXY\"                              : \"확장기능 설치를 위해 사용된 프록시 서버 URL\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"문서 끝을 넘어선 스크롤을 활성화 하려면 true\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"모든 코드 힌트를 비활성화 하려면 false\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"문자를 선택한 경우 깜빡이는 커서 표시\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"코드 왼쪽의 “여백”에 행 번호를 표시하려면 true\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"새 블록을 만들 때 자동 들여쓰기\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"소프트 탭 작동을 끄려면 false\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"프로젝트 트리에서 디렉토리 우선 정렬하려면 true\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"공백 기반의 들여쓰기를 위한 공백 수\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"실시간 미리보기를 위한 빌트인 서버 포트 번호\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"커서가 있는 행의 배경 색을 강조하려면 true\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"탭 표시를 위한 공백 수\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"공백 대신 탭을 사용하려면 true\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"인라인 색상 편집기에서 대문자 16진수 색을 생성하려면 true\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"뷰포트 폭을 초과하는 행 감싸기\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"통제 불가능한 실행 Tern을 유발하도록 감지된 파일 목록\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"파일 인식 시 Tern이 초과될 때 까지의 시간\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"상태 표시 줄에 오류를 표시하려면 true\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"빠른 보기를 활성화 하려면 true\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"URL 없는 확장 기능의 이미지 미리보기를 표시하려면 true\",\n    \"DESCRIPTION_THEME\"                              : \"{APP_NAME} 테마 선택\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"사용자 정의 스크롤 바를 허용하려면 true\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"구문 검사 패널을 접어 두려면 true\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"글꼴 변경\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"글꼴 크기 변경(예: 13px)\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"노드 기반 검색을 활성화 하려면 true\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"빠른 검색을 활성화 하려면 true\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"맥 전용: 서브픽셀 안티 에일리어싱을 활성화 하려면 \\\"subpixel-antialiased\\\" 회색조 안티 에일리어싱을 활성화 하려면 \\\"antialiased\\\"\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"분할 보기에서 파일 환경 설정 열기를 비 활성화 하려면 false\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"사용자 환경 설정 파일을 좌측/상단 창에서 열려면 false\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"창 헤더의 닫기 버튼을 통해 마지막으로 닫힌 창을 접으려면 true\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"헤더에 닫기 버튼과 반전 보기 버튼 표시 전환.\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * 이것은 {APP_NAME}에 의해 환경 설정이 지원된 읽기 전용 파일입니다.\\n * 이 파일은 다른 창에서 열린 \\\"brackets.json\\\" 환경 설정 파일을 수정하기 위한 참조로 사용합니다.\\n * {APP_NAME} 환경 설정을 어떻게 하는지에 관한 더 많은 정보는 웹 페이지를 참고하세요.\\n * https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"기본\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"{APP_NAME}에서 코드 전용 모드를 실행하고 다른 모든 UI 요소 숨기기를 활성화 하려면 true\"\n});\n\n/* Last translated for fcd2e98ef35c110e00aebfbb6d3c3816e5156552 */\n"
  },
  {
    "path": "src/nls/ko/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"ko/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_kr/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.ko\"\n});\n"
  },
  {
    "path": "src/nls/lv/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(kļūda {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Datne/katalogs netika atrasts.\",\n    \"NOT_READABLE_ERR\"                  : \"Nevar nolasīt datni/katalogu.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"{APP_NAME} nevar atvērt datnes, lielākas par {0} MB.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Izvēlētais katalogs nevar tikt pārveidots.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Jums nav atļaujas veikt izmaiņas.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Šī datne ir pārveidota ārpus {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} šobrīd atbalsta tikai UTF-8 kodējuma teksta datnes.\",\n    \"FILE_EXISTS_ERR\"                   : \"Datne vai katalogs jau eksistē.\",\n    \"FILE\"                              : \"datne\",\n    \"FILE_TITLE\"                        : \"Datne\",\n    \"DIRECTORY\"                         : \"katalogs\",\n    \"DIRECTORY_TITLE\"                   : \"Katalogs\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Katalogu nosaukumi\",\n    \"FILENAMES_LEDE\"                    : \"Datņu nosaukumi\",\n    \"FILENAME\"                          : \"Datnes nosaukums\",\n    \"DIRECTORY_NAME\"                    : \"Kataloga nosaukums\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Kļūda, ielādējot projektu\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Radās kļūda, rādot datņu atvēršanas dialogu. (kļūda {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Radās kļūda, ielādējot katalogu <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Radās kļūda, nolasot kataloga saturu <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Kļūda, verot datni\",\n    \"ERROR_OPENING_FILE\"                : \"Radās kļūda, verot datni <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Radās kļūda, verot šīs datnes:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Kļūda, pārlādējot izmaiņas no diska\",\n    \"ERROR_RELOADING_FILE\"              : \"Radās kļūda, pārlādējot datni <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Kļūda, saglabājot datni\",\n    \"ERROR_SAVING_FILE\"                 : \"Radās kļūda, saglabājot datni <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Kļūda, pārdēvējot {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Radās kļūda, pārdēvējot {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Datne vai katalogs nav daļa no pašlaik atvērtā projekta. Diemžēl šobrīd var pārdēvēt tikai projekta datnes.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Kļūda, dzēšot {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Radās kļūda, dzēšot {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Nederīgs {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} nevar izmantot sistēmas rezervētos vārdus, kas beidzas ar punktu (.) vai izmantot šādus simbolus: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Jau eksistē datne vai katalogs ar nosaukumu <span class='dialog-filename'>{0}</span> .\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Kļūda, veidojot {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Radās kļūda, veidojot {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Nevar atvērt mapi, kamēr tiek atvērtas citas datnes.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Kļūda, lasot lietotāja atslēgu karti\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Atslēgu kartes datne nav derīga JSON datne. Datne tiks atvērta, lai Jūs varētu izlabot formātu.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Atslēgu karte nav derīga UTF-8 kodējuma teksta datne un nevar tikt ielādēta\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Nevar piešķirt saīsnes šīm komandām: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Nevar piešķirt šīs saīsnes: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Tiek piešķirtas vairākas saīsnes šīm komandām: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Šīm saīsnēm ir vairākas piesaistes: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Šīs saīsnes nav derīgas: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Tiek piešķirtas saīsnes neeksistējošām komandām: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Kļūda, lasot iestatījumus\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Iestatījumu datne nav derīga JSON datne. Datne tiks atvērta, lai Jūs varētu izlabot formātu. Nepieciešams restartēt {APP_NAME}, lai izmaiņas stāstos spēkā.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Iestatījumu datne nav derīga JSON datne. Datne tiks atvērta, lai Jūs varētu izlabot formātu. Nepieciešams pārlādēt projektu, lai izmaiņas stāstos spēkā.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ups! {APP_NAME} vēl nedarbojas pārlūkā.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} ir būvēta HTML, bet šobrīd strādā kā darbvirsmas lietotne, tāpēc to var izmantot, lai rediģētu lokālās datnes. Lūdzu, izmantojiet lietotnes čaulu <b>github.com/adobe/brackets-shell</b> repozitorijā, lai palaistu {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Kļūda, indeksējot datnes\",\n    \"ERROR_MAX_FILES\"                   : \"Šis projekts ietver vairāk nekā 30000 datņu. Funkcijas, kas darbojas vairākās datnēs, var tikt atspējotas vai darboties tā, it kā projekts būtu tukšs. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'> Lasīt vairāk par strādāšanu ar lieliem projektiem</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Kļūda, palaižot pārlūku\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Pārlūks Google Chrome netika atrasts. Pārliecinieties, ka tas ir instalēts.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Radās kļūda, palaižot pārlūku. (kļūda {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Tiešā priekšskatījuma kļūda\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Savienojas ar pārlūku\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Lai savienotos ar tiešo priekšskatījumu, nepieciešams pārlādēt Chrome ar iespējotu attālo atkļūdošanu.<br /><br />Vai vēlaties pārlādēt Chrome un iespējot attālo atkļūdošanu?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Neizdevās ielādēt tiešā priekšskatījuma lapu.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Atveriet HTML datni vai pārliecinieties, ka jūsu projektā ir datne index.html, lai palaistu tiešo priekšskatījumu.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Lai palaistu tiešo priekšskatījumu ar serverī importētu datni, nepieciešams norādīt šī projekta bāzes URL.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Kļūda, startējot HTTP serveri tiešā priekšskatījuma datnēm. Lūdzu, mēģiniet vēlreiz. \",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Laipni lūgts tiešajā priekšskatījumā!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Tiešais priekšskatījums savieno {APP_NAME} ar pārlūku. Tas palaiž HTML datnes priekšskatījumu pārlūkā, tad atjaunina priekšskatījumu, kad tiek rediģēts kods.<br /><br />Šajā agrīnajā {APP_NAME} versijā tiešais priekšskatījums darbojas tikai ar <strong>Google Chrome</strong> un atjauninās, kad tiek rediģētas <strong>CSS vai HTML datnes</strong>. Izmaiņas JavaScript datnēs tiek automātiski pārlādētas saglabājot.<br /><br />(Šis paziņojums paradīsies tikai vienreiz.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Sīkākai informācijai skatiet <a href='{0}' title='{0}'>Tiešā priekšskatījuma savienojuma kļūdu novēršana</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Tiešais priekšskatījums\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Tiešais priekšskatījums: savienojas\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Tiešais priekšskatījums: inicializē\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Izslēgt tiešo priekšskatījumu\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Tiešais priekšskatījums (saglabājiet datni, lai atsvaidzinātu)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Tiešais priekšskatījums (netiek atjaunināts sintakses kļūdas dēļ)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Tiešais priekšskatījums tika atcelts, jo bija atvērti pārlūka izstrādātāja rīki\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Tiešais priekšskatījums tika atcelts, jo lapa tika aizvērta pārlūkā\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Tiešais priekšskatījums tika atcelts, jo pārlūks pārvietojās uz lapu, kas nav daļa no šī projekta\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Tiešais priekšskatījums tika atcelts nezināma iemesla dēļ ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Saglabāt izmaiņas\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Vai vēlaties saglabāt veiktās izmaiņas dokumentā <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Vai vēlaties saglabāt izmaiņas šajās datnēs?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Ārējas izmaiņas\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Apstiprināt dzēšanu\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Vai tiešām vēlaties izdzēst mapi <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Datne izdzēsta\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> ir pārveidots diskā ārpus {APP_NAME}.<br /><br />Vai vēlaties saglabāt datni un pārrakstīt šīs izmaiņas?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> ir pārveidots diskā ārpus {APP_NAME}, bet tam ir arī nesaglabātas izmaiņas {APP_NAME}.<br /><br />Kuru versiju vēlaties paturēt?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> ir pārveidots diskā ārpus {APP_NAME}, bet tam ir nesaglabātas izmaiņas {APP_NAME}.<br /><br />Vai vēlaties paturēt izmaiņas?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Darīts\",\n    \"OK\"                                : \"Labi\",\n    \"CANCEL\"                            : \"Atcelt\",\n    \"DONT_SAVE\"                         : \"Nesaglabāt\",\n    \"SAVE\"                              : \"Saglabāt\",\n    \"SAVE_AS\"                           : \"Saglabāt kā\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Pārrakstīt\",\n    \"DELETE\"                            : \"Dzēst\",\n    \"BUTTON_YES\"                        : \"Jā\",\n    \"BUTTON_NO\"                         : \"Nē\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} no {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Nav rezultātu\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Meklēt\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Aizstāt ar\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Grupēt\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Aizstāt\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Aizstāt\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Nākamā sakritība\",\n    \"BUTTON_PREV_HINT\"                  : \"Iepriekšējā sakritība\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Jāsakrīt reģistriem\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regulārā izteiksme\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Aizstāt bez atcelšanas\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Tā kā jāizmaina vairāk nekā {0} datnes, {APP_NAME} pārveidos neatvērtas datnes uz diska.<br />Jūs nevarēsiet atcelt šajās datnēs veiktos aizvietojumus.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Aizstāt bez atcelšanas\",\n\n    \"OPEN_FILE\"                         : \"Atvērt datni\",\n    \"SAVE_FILE_AS\"                      : \"Saglabāt datni\",\n    \"CHOOSE_FOLDER\"                     : \"Izvēlēties mapi\",\n\n    \"RELEASE_NOTES\"                     : \"Informācija par laidienu\",\n    \"NO_UPDATE_TITLE\"                   : \"Jums ir jaunākā versija!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Jums ir jaunākā {APP_NAME} versija.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Aizstāt\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"ar\",\n    \"FIND_TITLE_LABEL\"                  : \"Atrasts\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} iekš {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"iekš <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"projektā\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtrs izslēdz visas datnes {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"datne\",\n    \"FIND_IN_FILES_FILES\"               : \"datnes\",\n    \"FIND_IN_FILES_MATCH\"               : \"sakritība\",\n    \"FIND_IN_FILES_MATCHES\"             : \"sakritības\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Pāri \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\",\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Spiediet Ctrl/Cmd, lai izvērstu/sakļautu visu\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indeksēšana tūlītējai meklēšanai\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Aizstāt kļūdas\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Šīs datnes netika pārveidotas, jo tās mainījās pēc meklēšanas vai nevar tikt rakstītas.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Kļūda, saņemot informāciju par atjauninājumiem\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Neizdevās iegūt informāciju no servera par jaunākajiem atjauninājumiem. Pārliecinieties, vai esat pieslēdzies internetam, un mēģiniet vēlreiz.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Jauna izslēgšanas kopa\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Neizslēgt datnes\",\n    \"NO_FILE_FILTER\"                    : \"Netika izslēgtas datnes\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Izslēgt {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Rediģēt\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Rediģēt izslēgšanas kopu\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Izslēgt datnes un mapes, kas sakrīt ar šīm virknēm / apakšvirknēm vai <a href='{0}' title='{0}'>aizstājējzīmēm</a>. Ievadiet katru virkni jaunā rindā.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nosaukt šo izslēgšanas kopu (nav obligāti)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"un {0} vairāk\",\n    \"FILTER_COUNTING_FILES\"             : \"Skaita datnes\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Pieļauj {0} no {1} datnēm {2} \",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Pieļauj visas {0} datnes {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Pašreizējai kursora pozīcijai nav pieejama ātrā rediģēšana\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS ātrā rediģēšana: novietojiet kursoru uz vienas klases nosaukuma\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS ātrā rediģēšana: nepilnīgs klases atribūts\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS ātrā rediģēšana: nepilnīgs id atribūts\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS ātrā rediģēšana: novietojiet kursuru tagā, klasē vai id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS laika funkcijas ātrā rediģēšana: nederīga sintakse\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS ātrā rediģēšana: novietojiet kursoru funkcijas nosaukumā\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Pašreizējai kursora pozīcijai nav pieejams neviens ātrais dokuments\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Ielādē\\u2026\",\n    \"UNTITLED\"          : \"Nenosaukts\",\n    \"WORKING_FILES\"     : \"Darba datnes\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Augša\",\n    \"BOTTOM\"            : \"Apakša\",\n    \"LEFT\"              : \"Pa kreisi\",\n    \"RIGHT\"             : \"Pa labi\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Netiek sadalīts\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Vertikālā sadalīšana\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Horizontālā sadalīšana\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Sadalīt redaktoru vertikāli vai horizontāli\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Konfigurēt darba kopu\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Jau atvērts\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Datne jau ir atvērta citā rūtī. {APP_NAME} drīz atbalstīs datnes atvēršanu vairāk nekā vienā rūtī. Līdz tam datne tiks rādīta rūtī, kurā tā jau ir atvērta.<br /<br />(Šis paziņojums paradīsies tikai vienreiz.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Vadības taustiņš \\\"Ctrl\\\"\",\n    \"KEYBOARD_SHIFT\"        : \"Pārslēgšanas taustiņš \\\"Shift\\\"\",\n    \"KEYBOARD_SPACE\"        : \"Atstarpēšanas taustiņš \\\"Space\\\"\",\n    \"KEYBOARD_PAGE_UP\"      : \"Augšupšķiršanas taustiņš \\\"Page Up\\\"\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Lejupšķiršanas taustiņš \\\"Page Down\\\"\",\n    \"KEYBOARD_HOME\"         : \"Sākumvietas taustiņš \\\"Home\\\"\",\n    \"KEYBOARD_END\"          : \"Beigvietas taustiņš \\\"End\\\"\",\n    \"KEYBOARD_INSERT\"       : \"Iespraušanas taustiņš \\\"Insert\\\"\",\n    \"KEYBOARD_DELETE\"       : \"Dzēšanas taustiņš \\\"Delete\\\"\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Rinda {0} kolonna {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 izvēlēta {0} kolonna\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 izvēlētas {0} kolonnas\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 izvēlēta {0} rinda\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 izvēlētas {0} rindas\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} izvēles\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Nospiediet, lai pārslēgtu atkāpes uz atstarpēm\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Nospiediet, lai pārslēgtu atkāpes uz tabulāciju\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Nospiediet, lai mainītu atstarpju skaitu, izmantojot atkāpes\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Nospiediet, lai mainītu tabulācijas simbolu platumu\",\n    \"STATUSBAR_SPACES\"                      : \"Atstarpes:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tabulācijas izmērs:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} rinda\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} rindas\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Paplašinājumi atspējoti\",\n    \"STATUSBAR_INSERT\"                      : \"Iespraušana (INS)\",\n    \"STATUSBAR_OVERWRITE\"                   : \"Pārraksts (OVR)\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Nospiediet, lai pārslēgtu kursoru starp iespraušanas (INS) un pārraksta (OVR) režīmu\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Nospiediet, lai mainītu datnes tipu\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Nospiediet, lai rādītu/slēptu atskaites paneli.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(noklusējums)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Iestatīt kā noklusējumu .{0} datnēm\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} problēmas\",\n    \"SINGLE_ERROR\"                          : \"1 {0} problēma\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} problēmas\",\n    \"NO_ERRORS\"                             : \"Netika atrasta neviena {0} problēma - labi pastrādāts!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Netika atrasta neviena problēma - labi pastrādāts!\",\n    \"LINT_DISABLED\"                         : \"Sintakses pārbaudīšana ir atspējota\",\n    \"NO_LINT_AVAILABLE\"                     : \"Nav pieejama sintakses pārbaudīšana priekš {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Nav ko pārbaudīt\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} iestājās taimauts pēc {1} ms ilgas gaidīšanas\",\n    \"LINTER_FAILED\"                         : \"{0} beidzās ar kļūdu: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Datne\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Jauna\",\n    \"CMD_FILE_NEW\"                        : \"Jauna datne\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Jauna mape\",\n    \"CMD_FILE_OPEN\"                       : \"Atvērt\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Atvērt darba kopā\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Atvērt nomestās datnes\",\n    \"CMD_OPEN_FOLDER\"                     : \"Atvērt mapi\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Aizvērt\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Aizvērt visas\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Aizvērt sarakstu\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Aizvērt citas\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Aizvērt visas augstāk\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Aizvērt visas zemāk\",\n    \"CMD_FILE_SAVE\"                       : \"Saglabāt\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Saglabāt visas\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Saglabāt kā\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Tiešais priekšskatījums\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Iespējot eksperimentālo tiešo priekšskatījumu\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Piespiedu tiešā priekšskatījuma pārlādēšana\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projekta iestatījumi\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Pārdēvēt\",\n    \"CMD_FILE_DELETE\"                     : \"Dzēst\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instalēt paplašinājumu\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Paplašinājumu pārvaldnieks\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Atsvaidzināt datņu koku\",\n    \"CMD_QUIT\"                            : \"Beigt\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Iziet\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Rediģēt\",\n    \"CMD_UNDO\"                            : \"Atsaukt\",\n    \"CMD_REDO\"                            : \"Atcelt atsaukšanu\",\n    \"CMD_CUT\"                             : \"Izgriezt\",\n    \"CMD_COPY\"                            : \"Kopēt\",\n    \"CMD_PASTE\"                           : \"Ielīmēt\",\n    \"CMD_SELECT_ALL\"                      : \"Izvēlēties visu\",\n    \"CMD_SELECT_LINE\"                     : \"Izvēlēties rindu\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Sadalīt izvēlēto rindās\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Pievienot kursoru nākamajai rindai\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Pievienot kursoru iepriekšējai rindai\",\n    \"CMD_INDENT\"                          : \"Atkāpe\",\n    \"CMD_UNINDENT\"                        : \"Nav atkāpes\",\n    \"CMD_DUPLICATE\"                       : \"Dublēt\",\n    \"CMD_DELETE_LINES\"                    : \"Dzēst rindu\",\n    \"CMD_COMMENT\"                         : \"Rādīt/slēpt rindas komentāru\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Rādīt/slēpt bloka komentāru\",\n    \"CMD_LINE_UP\"                         : \"Pārvietot rindu uz augšu\",\n    \"CMD_LINE_DOWN\"                       : \"Pārvietot rindu uz leju\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Atvērt augšējo rindu\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Atvērt apakšējo rindu\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Automātiski aizvērt figūriekavas\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Rādīt koda ieteikumus\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Meklēt\",\n    \"CMD_FIND\"                            : \"Meklēt\",\n    \"CMD_FIND_NEXT\"                       : \"Meklēt nākamo\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Meklēt iepriekšējo\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Meklēt visu un izvēlēties\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Pievienot nākamo sakritību izvēlētajam\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Izlaist un pievienot nākamo sakritību\",\n    \"CMD_FIND_IN_FILES\"                   : \"Meklēt datnēs\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Meklēt\\u2026 \",\n    \"CMD_REPLACE\"                         : \"Aizstāt\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Aizstāt datnēs\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Aizstāt\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Skats\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Slēpt sānjoslu\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Rādīt sānjoslu\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Rādīt/slēpt sānjoslu\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Rādīt/slēpt paneļus\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Rādīt/slēpt palīgjoslas\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Palielināt fonta lielumu\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Samazināt fonta lielumu\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Atjaunot fonta lielumu\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Ritināt rindu augstāk\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Ritināt rindu zemāk\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Rindu numuri\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Izcelt aktīvo rindu\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Aplaušana\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Tiešā priekšskatījuma izcelšana\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Pārbaudīt sintaksi datnēs, tās saglabājot\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Kārtot pēc pievienošanas datuma\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Kārtot pēc nosaukuma\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Kārtot pēc tipa\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automātiskā kārtošana\",\n    \"CMD_THEMES\"                          : \"Dizains\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Pārvietoties\",\n    \"CMD_QUICK_OPEN\"                      : \"Ātrā atvēršana\",\n    \"CMD_GOTO_LINE\"                       : \"Iet uz rindu\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Ātrā definīcijas meklēšana\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Iet uz pirmo problēmu\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Ātrā rediģēšana\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Ātrie dokumenti\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Iepriekšējā sakritība\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Nākamā sakritība\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Jauna kārtula\",\n    \"CMD_NEXT_DOC\"                        : \"Nākamais dokuments\",\n    \"CMD_PREV_DOC\"                        : \"Iepriekšējais dokuments\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Nākamais dokuments sarakstā\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Iepriekšējais dokuments sarakstā\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Parādīt datņu kokā\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Parādīt pārlūkā\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Parādīt meklētājā\",\n    \"CMD_SHOW_IN_OS\"                      : \"Parādīt operētājsistēmā\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Palīdzība\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Pārbaudīt atjauninājumus\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Kā lietot {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} palīdzība\",\n    \"CMD_SUGGEST\"                         : \"Ieteikt funkciju\",\n    \"CMD_RELEASE_NOTES\"                   : \"Informācija par laidienu\",\n    \"CMD_GET_INVOLVED\"                    : \"Iesaistīties\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Parādīt paplašinājumu mapi\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Veselības atskaite\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} mājas lapa\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} tīmekļa vietnē \\\"Twitter\\\"\",\n    \"CMD_ABOUT\"                           : \"Par {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Atvērt iestatījumu datni\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Atvērt lietotāja atslēgu karti\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"eksperimentāls būvējums\",\n    \"RELEASE_BUILD\"                        : \"būvējums\",\n    \"DEVELOPMENT_BUILD\"                    : \"izstrādes būvējums\",\n    \"RELOAD_FROM_DISK\"                     : \"Pārlādēt no diska\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Saglabāt izmaiņas redaktorā\",\n    \"CLOSE_DONT_SAVE\"                      : \"Aizvērt (nesaglabāt)\",\n    \"RELAUNCH_CHROME\"                      : \"Restartēt Chrome\",\n    \"ABOUT\"                                : \"Par\",\n    \"CLOSE\"                                : \"Aizvērt\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Laidiena versija {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"būvējuma laikspiedols:\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Paziņojumi, noteikumi un nosacījumi, kas attiecas uz trešo pušu programmatūru, atrodas <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> un šeit iekļauti ar atsauci.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentācija un avots <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Izveidots ar \\u2764 un JavaScript, autors:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Daudz cilvēku (bet mums šobrīd ir grūtības ielādēt šos datus).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN dokumenti un MDN grafiskais logo ir licencēti saskaņā ar \\\"Creative Commons\\\" licenci <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"{APP_NAME} ir pieejams jauns būvējums! Spiediet šeit, lai saņemtu sīkāku informāciju.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Pieejams atjauninājums\",\n    \"UPDATE_MESSAGE\"                       : \"{APP_NAME} ir pieejams jauns būvējums. Dažas no jaunajām funkcijām:\",\n    \"GET_IT_NOW\"                           : \"Iegūt to tagad!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projekta iestatījumi priekš: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Tiešā priekšskatījuma bāzes URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Lai izmantotu lokālo serveri, ievadiet URL, kā, piemēram, http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Tiešais priekšskatījums neatbalsta protokolu {0} &mdash;lūdzu, izmantojiet http: vai https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Bāzes URL nevar ietvert tādus meklēšanas parametrus kā \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Bāzes URL nevar ietver jaucējkodu kā \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Speciālajiem simboliem kā '{0}' jābūt %-kodētiem.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Nezināma kļūda, parsējot bāzes URL\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Atvērt datni, kamēr fokuss ir uz šo rūti</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Pārnest šo skatu uz rūti {0}\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Pašreizējais dizains\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Lietot dizaina ritjoslas\",\n    \"FONT_SIZE\"                            : \"Fonta lielums\",\n    \"FONT_FAMILY\"                          : \"Fontu saime\",\n    \"THEMES_SETTINGS\"                      : \"Dizaina iestatījumi\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Jauna kārtula\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instalēt\",\n    \"UPDATE\"                               : \"Atjaunināt\",\n    \"REMOVE\"                               : \"Noņemt\",\n    \"DISABLE\"                              : \"Atspējot\",\n    \"ENABLE\"                               : \"Iespējot\",\n    \"OVERWRITE\"                            : \"Pārrakstīt\",\n    \"CANT_REMOVE_DEV\"                      : \"Paplašinājumi mapē \\\"dev\\\" ir jādzēš manuāli.\",\n    \"CANT_UPDATE\"                          : \"Atjauninājums nesader ar šo {APP_NAME} versiju.\",\n    \"CANT_UPDATE_DEV\"                      : \"Paplašinājumi mapē \\\"dev\\\" nevar tikt atjaunoti automātiski.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instalēt paplašinājumu\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Atjaunināt paplašinājumu\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Paplašinājuma URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Paplašinājuma zip datnes URL vai GitHub repozitorijs\",\n    \"INSTALLING_FROM\"                      : \"Instalē paplašinājumu no {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalēšana veiksmīga!\",\n    \"INSTALL_FAILED\"                       : \"Instalēšana neveiksmīga.\",\n    \"CANCELING_INSTALL\"                    : \"Atceļ \\u2026\",\n    \"CANCELING_HUNG\"                       : \"Instalēšanas atcelšana aizņem daudz laika. Var būt radusies iekšēja kļūda.\",\n    \"INSTALL_CANCELED\"                     : \"Instalēšana atcelta.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Skatīt pilnīgu aprakstu\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Skatīt saīsinātu aprakstu\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Lejupielādētais saturs nav derīga zip datne.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Datne package.json nav derīga (kļūda: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Datnē package.json nav norādīts pakotnes nosaukums.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} ir nederīgs pakotnes nosaukums.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Datnē package.json nav norādīta pakotnes versija.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Pakotnes versijas numurs ({0}) ir nederīgs.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"{APP_NAME} saderības virkne ({0}) ir nederīga.\",\n    \"DISALLOWED_WORDS\"                     : \"Laukā {0} nav atļauti vārdi ({1}).\",\n    \"API_NOT_COMPATIBLE\"                   : \"Paplašinājums nav saderīgs ar šo {APP_NAME} versiju. Tas ir instalēts atspējoto paplašinājumu mapē.\",\n    \"MISSING_MAIN\"                         : \"Pakotnē nav datnes main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Šīs pakotnes instalēšana pārrakstīs iepriekš instalētu paplašinājumu. Pārrakstīt veco paplašinājumu?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Šai pakotnei ir tāda pati versija kā jau pašreiz instalētajai. Pārrakstīt esošo instalāciju?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Pakotnes versija ir {0}, kas ir vecāka par pašreiz instalēto ({1}). Pārrakstīt esošo instalāciju?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Iekšēja kļūda: lejupielādes ID jau tiek lietots.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Nevar savienoties ar serveri.\",\n    \"BAD_HTTP_STATUS\"                      : \"Datne netika atrasta serverī (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Neizdevās saglabāt lejupielādi pagaidu datnē.\",\n    \"ERROR_LOADING\"                        : \"Uzsākot darbību, paplašinājums sadūrās ar kļūdu.\",\n    \"MALFORMED_URL\"                        : \"URL nav derīgs. Pārliecinieties, vai ievadījāt to pareizi.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL jābūt http vai https formātā.\",\n    \"UNKNOWN_ERROR\"                        : \"Nezināma iekšējā kļūda.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Paplašinājumu pārvaldnieks\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Neizdevās piekļūt paplašinājumu reģistram. Lūdzu, mēģiniet vēlreiz.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Ievelciet šeit .zip vai\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Nometiet .zip, lai instalētu\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Instalēšana/atjaunināšana pārtraukta šādu kļūdu dēļ:\",\n    \"INSTALL_FROM_URL\"                     : \"Instalēt no URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validē\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autors\",\n    \"EXTENSION_DATE\"                       : \"Datums\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Šim paplašinājumam nepieciešama jaunāka {APP_NAME} versija.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Pašlaik šis paplašinājums darbojas tikai ar vecākām {APP_NAME} versijām.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Šai paplašinājuma versijai {0} nepieciešama jaunāka {APP_NAME} versija. Bet jūs varat instalēt agrāko versiju {1}. \",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Šī paplašinājuma versija {0} darbojas tikai ar vecākām {APP_NAME} versijām. Bet jūs varat instalēt agrāko versiju {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Nav apraksta\",\n    \"EXTENSION_MORE_INFO\"                  : \"Vairāk informācijas\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Paplašinājuma kļūda\",\n    \"EXTENSION_KEYWORDS\"                   : \"Atslēgas vārdi\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Tulkots {0} valodās, ieskaitot Jūsu\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Tulkots {0} valodās\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Paplašinājums tulkots šādās valodās: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Instalēts\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Paplašinājuma atjauninājums tika lejupielādēts, un tas tiks instalēts pēc {APP_NAME} pārlādēšanas.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Meklēt\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Vairāk\",\n    \"BROWSE_EXTENSIONS\"                    : \"Pārlūkot paplašinājumus\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Noņemt paplašinājumu\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Neizdevās noņemt vienu vai vairākus paplašinājumus: {0}. {APP_NAME} tik un tā pārlādēsies.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Atjaunināt paplašinājumu\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Neizdevās atjaunināt vienu vai vairākus paplašinājumus: {0}. {APP_NAME} tik un tā pārlādēsies.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Atspējot paplašinājumu\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Neizdevās atspējot vienu vai vairākus paplašinājumus: {0}. {APP_NAME} tik un tā pārlādēsies.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Atzīmēts noņemšanai\",\n    \"UNDO_REMOVE\"                          : \"Atsaukt\",\n    \"MARKED_FOR_UPDATE\"                    : \"Atzīmēts atjaunināšanai\",\n    \"UNDO_UPDATE\"                          : \"Atsaukt\",\n    \"MARKED_FOR_DISABLING\"                 : \"Atzīmēts atspējošanai\",\n    \"UNDO_DISABLE\"                         : \"Atsaukt\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Mainīt paplašinājumus\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Lai atjauninātu, noņemtu vai atspējotu atzīmētos paplašinājumus, ir jāpārlādē {APP_NAME}. Jums būs jāsaglabā nesaglabātās izmaiņas.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Noņemt paplašinājumus un pārlādēt\",\n    \"CHANGE_AND_RELOAD\"                    : \"Mainīt paplašinājumus un pārlādēt\",\n    \"UPDATE_AND_RELOAD\"                    : \"Atjaunināt paplašinājumus un pārlādēt\",\n    \"DISABLE_AND_RELOAD\"                   : \"Atspējot paplašinājumus un pārlādēt\",\n    \"PROCESSING_EXTENSIONS\"                : \"Apstrādā paplašinājumu izmaiņas\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Nevarēja noņemt paplašinājumu {0}, jo tas nebija instalēts.\",\n    \"NO_EXTENSIONS\"                        : \"Vēl nav instalēti paplašinājumi.<br>Spiediet uz cilnes \\\"Pieejamie\\\", lai sāktu darbu.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Neviens paplašinājums neatbilst meklētajam.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"PIEZĪME: Šo paplašinājumu autori var nebūt {APP_NAME} autori. Paplašinājumi nav pārskatīti, un tiem ir pilnas lokālās privilēģijas. Uzmanieties, instalējot paplašinājumus no nezināma avota.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Instalētie\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Pieejamie\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Dizaini\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Atjauninājumi\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Nav sakritību.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Visas sakritības ir sakļautas. Izvērsiet labajā pusē uzskaitītās datnes, lai apskatītu sakritības.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Neeksistē tādas CSS kārtulas, kas atbilstu izvēlētajam.<br> Nospiediet \\\"Jauna kārtula\\\", lai to izveidotu.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Jūsu projektā nav stila lapu.<br>Izveidojiet to, lai pievienotu CSS kārtulas.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"lielākais\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pikseļi\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Atkļūdot\",\n    \"ERRORS\"                                    : \"Kļūdas\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Rādīt izstrādātāja rīkus\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Pārlādēt ar paplašinājumiem\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Pārlādēt bez paplašinājumiem\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Jauns {APP_NAME} logs\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Instalēt komandrindas saīsni\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Pārslēgt valodu\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Palaist testus\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Rādīt veiktspējas informāciju\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Iespējot mezgla atkļūdošanu\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Ierakstīt mezgla stāvokli konsolē\",\n    \"CMD_RESTART_NODE\"                          : \"Restartēt mezglu\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Rādīt kļūdas statusa joslā\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Atvērt {APP_NAME} avotu\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} komandrindas saīsne\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Radās kļūda, instalējot komandrindas saīsni. Lūdzu, mēģiniet <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>šīs problēmu noteikšanas ieteikumi</a>.<br/><br/>Iemesls: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Neizdevās noņemt esošo <code>/usr/local/bin/brackets</code> simbolisko saiti.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Neizdevās izveidot <code>/usr/local/bin</code> katalogu.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Neizdevās izveidot <code>/usr/local/bin/brackets</code> simbolisko saiti.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Iekšēja kļūda.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Šī operētājsistēma neatbalsta komandrindas saīsni.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Veiksmīgi! Nu varat vienkārši palaist {APP_NAME} no komandrindas: <code>brackets myFile.txt</code>, lai atvērtu datni vai <code>brackets myFolder</code>, lai pārslēgtu projektus. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Uzzināt vairāk</a>  par {APP_NAME} komandrindas izmantošanu.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Pārslēgt valodu\",\n    \"LANGUAGE_MESSAGE\"                          : \"Valoda:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Pārlādēt {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Atcelt\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Sistēmas noklusējums\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Veselības atskaites iestatījumi\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} veselības atskaite\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Dalīties ar anonīmu informāciju, kā es izmantoju {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Lai uzlabotu {APP_NAME}, mēs periodiski nosūtām ierobežotu, <strong>anonīmu</strong> statistiku uzņēmumam Adobe, kā Jūs izmantojat {APP_NAME}. Šī informācija palīdz noteikt funkciju prioritāti, atrast kļūdas un noteikt lietojamības problēmas.<br><br>Jūs varat redzēt savus datus vai izvēlēties nedalīties ar informāciju, izvēloties <strong>Palīdzība > Veselības atskaite</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Uzzināt vairāk par {APP_NAME} veselības atskaiti</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} veselības atskaite\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p> Lai uzlabotu {APP_NAME}, mēs periodiski nosūtām ierobežotu, <strong>anonīmu</strong> statistiku uzņēmumam Adobe, kā Jūs izmantojat {APP_NAME}. Šī informācija palīdz noteikt funkciju prioritāti, atrast kļūdas un noteikt lietojamības problēmas. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Uzzināt vairāk par {APP_NAME} veselības atskaiti</a> un kādu labumu tā dod {APP_NAME} kopienai, pasargājot jūsu privātumu.</p><p>Zemāk varat redzēt datu priekšskatījumu, kas tiks nosūtīti nākamajā veselības atskaitē<em>ja</em> tā ir iespējota.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Laiks\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progress\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd>Pārvietot izvēlēto punktu<br><kbd class='text'>Shift</kbd> Pārvietot par desmit vienībām<br><kbd class='text'>Tabulācija</kbd> Pārslēgšanās punkti\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Palielināt vai samazināt soļus<br><kbd>←</kbd><kbd>→</kbd> 'Sākt' vai 'Beigt'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Vecā vērtība <code>{0}</code> nav derīga, tāpēc parādītā funkcija tika mainīta uz <code>{1}</code>. Dokuments tiks atjaunināts līdz ar pirmo rediģēšanu.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Pašreizējā krāsa\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Oriģinālā krāsa\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa formāts\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex formāts\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa formāts\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (lietots {1} reizi)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (lietots {1} reizes)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Pārlēkt uz definīciju\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Rādīt parametru ieteikumus\",\n    \"NO_ARGUMENTS\"                              : \"<nav argumentu>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"JavaScript datnes izveduma problēma\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} saskārās ar grūtībām apstrādāt <span class='dialog-filename'>{0}</span>.<br><br> Šo datni vairs nevarēs apstrādāt ar funkcijām: koda ieteikumi, pārlēkt uz definīciju un ātrā rediģēšana. Lai no jauna iespējotu šo datni, atveriet <code>.brackets.json</code> projektā un rediģējiet <code>jscodehints.detectedExclusions</code>.<br><br> Šī ir iespējama {APP_NAME} kļūda. Ja varat nodrošināt šīs datnes kopiju, <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>reģistrējiet kļūdu</a> ar saiti uz šeit norādīto datni.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Ātrais skats uz norādēm\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Nesenie projekti\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Lasīt vairāk\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Sakļaut visu\",\n    \"EXPAND_ALL\"                    : \"Izvērst visu\",\n    \"COLLAPSE_CURRENT\"              : \"Sakļaut pašreizējo\",\n    \"EXPAND_CURRENT\"                : \"Izvērst pašreizējo\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"vērtība true, lai automātiski aizvērtu figūriekavas, iekavas un apaļās iekavas\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"vērtība false, lai noņemtu \\\"Aizvērt visus augstāk\\\" no darba datņu kontekstizvēlnes\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"vērtība false, lai noņemtu \\\"Aizvērt visus zemāk\\\" no darba datņu kontekstizvēlnes\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"vērtība false, lai noņemtu \\\"Aizvērt citus\\\" no darba datņu kontekstizvēlnes\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Nosaka tagu aizvēršanas iespējas\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Tagu masīvs, kas nav automātiski jāaizver\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Aizvērt, kad tiek ierakstīts atverošā taga > \",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Aizvērt, kad tiek ierakstīts aizverošā taga / \",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Tagu masīvs, kuru atverot ir tukša rinda\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"vērtība true, lai vienmēr ģenerētu sakļaušanas atzīmes, kad mainās atkāpes līmenis\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"vērtība true, lai iespējotu koda locīšanu\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"vērtība true, lai sadaļu sakļaušanas atzīmes būtu redzamas, kustinot peli pāri koda kreisajai malai\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limitēt, uz cik līmeņiem attiecas Sakļaut visu\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Minimālais rindu skaits, pirms parādās sakļaušanas sadaļas ikona\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"vērtība true, lai atcerētos sakļautās sadaļas, aizverot un no jauna atverot datni vai projektu\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"vērtība true, lai iespējotu koda locīšanu izvēlētajam tekstam redaktorā\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Iespējot/atspējot HTML atribūtu ieteikumus\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Iespējot/atspējot CSS/LESS/SCSS rekvizītu ieteikumus\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Iespējot/atspējot JavaScript koda ieteikumus\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Iespējot/atspējot datu tipa informāciju JavaScript koda ieteikumos\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Iespējot/atspējot iestatījumu koda ieteikumus\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Iespējot/atspējot HTML elementu ieteikumus\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Iespējot/atspējot SVG koda ieteikumus\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Iespējot/atspējot HTML tagu ieteikumus\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Iespējot/atspējot URL ieteikumus HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Iespējot/atspējot ievilkšanas & nomešanas funkcionalitāti\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Iespējot sekošanu veselības datiem\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Iespējot automātisko saskanīgo virkņu izcelšanu visā dokumentā\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Izcelt visas virknes, kuras sakrīt ar tekstvienībām, kurās šobrīd ir kursors (nav nepieciešams izvēlēties)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Izcelt tikai tad, kad izvēlētais ir pilna tekstvienība\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"vērtība true, lai ievietotu pašlaik izvēlēto koda ieteikumu cilnē\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"vērtība true, lai automātiski nerādītu JS koda ieteikumus, ierakstot .\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Objekts ar JSLint noklusējuma iespējām\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"vērtība true, lai atļautu piešķiršanas izteiksmes\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"vērtība true, lai atļautu bitu operācijas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"vērtība true, ja pārlūka globālie mainīgie ir jānosaka iepriekš\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"vērtība true, lai atļautu Google Closure idiomas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"vērtība true, lai atļautu \\\"turpināt\\\" priekšrakstu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"vērtība true, ja CouchDB globālie mainīgie ir jānosaka iepriekš\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"vērtība true, lai atļautu atkļūdotāja priekšrakstu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"vērtība true, ja iepriekš jānosaka pārlūka globālie mainīgie, kas var noderēt izstrādē\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"vērtība true, lai atļautu  == un !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"vērtība true, ja ES6 globālie mainīgie ir jānosaka iepriekš\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"vērtība true, lai atļautu novērtēšanu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"vērtība true, lai atļautu nefiltrētu \\\"priekš … iekš\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Noteikt specifisku tabulācijas platumu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Maksimālais aprakstīto brīdinājumu skaits\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Maksimālais simbolu skaits rindā\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"vērtība true, lai atļautu konstruktorus ar mazo burtu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"vērtība true, ja Node.js globālie mainīgie ir jānosaka iepriekš\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"vērtība true, lai atļautu apakšsvītru identifikatorus sākumā vai beigās\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"vērtība true, lai apstātos pie pirmās kļūdas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"vērtība true, lai atļautu  ++ un --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"vērtība true, lai atļautu . un [^...]. regulārajā izteiksmē\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"vērtība true, ja Rhino globālie mainīgie ir jānosaka iepriekš\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"vērtība true, lai atļautu neizdevušos 'striktas pragmatikas izmantošanu'\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"vērtība true, ja bloķēšanas ('…Sinhronizācija') metodes var tikt izmantotas.\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"vērtība true, lai atļautu neefektīvu masīva indeksēšanu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"vērtība true, lai atļautu TODO komentārus\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"vērtība true, lai atļautu neizmantotus parametrus\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"vērtība true, lai atļautu funkcijā vairāk nekā 1 mainīgo\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"vērtība true, lai ignorētu baltstarpas rakstzīmju noteikumus\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Specifiski valodas iestatījumi\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Papildu kartēšana no datnes paplašinājuma uz valodas nosaukumu\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Papildu kartēšana no datnes nosaukuma uz valodas nosaukumu\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"vērtība true, lai iespējotu koda pārbaudi\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Laiks milisekundēs pēc asinhronās sintakses pārbaudes taimauta\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Sintakses pārbaužu kārtība\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"vērtība true, lai iespējotu eksperimentālo tiešo priekšskatījumu\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"vērtība true, lai palaistu sniedzējus, kas norādīti tikai linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Sasniegts maksimālais vienlaicīgi parādīto kodu ieteikumu skaits\",\n    \"DESCRIPTION_PATH\"                               : \"Specifiski ceļu iestatījumi\",\n    \"DESCRIPTION_PROXY\"                              : \"Paplašinājuma instalēšanai izmantotais starpniekservera URL\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"vērtība true, lai iespējotu ritināšanu pēc dokumenta beigām\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"vērtība false, lai atspējotu koda ieteikumus\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Atstāj mirgojošo kursoru redzamu, kad izvēlēts teksts\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"vērtība true, lai rādītu rindu numuru koda kreisajā malā\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Automātiskā atkāpe, veidojot jaunu bloku\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"vērtība false, lai izslēgtu mīkstās tabulācijas uzvedību\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"vērtība true, lai projektu kokā pirmos sakārtotu katalogus\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Atstarpju skaits, lai izmantotu uz atstarpēm balstītas atkāpes\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Porta numurs, kas iebūvētajam serverim jāizmanto tiešajam priekšskatījumam\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"vērtība true, lai izceltu fona krāsu rindai, kurā atrodas kursors\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Atstarpju skaits, lai parādītu tabulāciju\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"vērtība true, lai atstarpju vietā izmantotu tabulāciju\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"vērtība true, lai iekšrindas krāsu redaktorā ģenerētu  heksadecimālos krāsu kodus ar lielajiem burtiem\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Rindu aplaušana, lai pārsniegtu skatlauka platumu\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Noteikto datņu saraksts, kas izraisīja Tern nekontrolējamību\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Laiks, pēc kura Tern iestāsies taimauts, cenšoties saprast datnes\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"vērtība true, lai rādītu kļūdas statusa joslā\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"vērtība true, lai iespējotu ātro skatu\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"vērtība true, lai rādītu attēlu priekšskatījumus URL bez paplašinājumiem\",\n    \"DESCRIPTION_THEME\"                              : \"Izvēlēties {APP_NAME} dizainu\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"vērtība true, lai atļautu pielāgotas ritjoslas\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"vērtība true, lai sakļautu sintakses pārbaudes paneli\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Mainīt fontu saimi\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Mainīt fonta lielumu; piemēram, 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"vērtība true, lai iespējotu uz mezgliem balstītu meklēšanu\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"vērtība true, lai iespējotu tūlītēju meklēšanu\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Tikai Mac: \\\"subpikseļi-gludināšana\\\", lai iespējotu subpikseļu gludināšanu vai \\\"gludināšana\\\", lai iespējotu pelēko toņu gludināšanu\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"vērtība false, lai atspējotu iestatījumu datni sadalītajā skatā\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"vērtība false, lai atvērtu iestatījumu datni kreisajā/augšējā rūtī\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"vērtība true, lai sakļautu rūtis, kad tiek aizvērta pēdējā rūts ar aizvēršanas pogu rūts galvenē\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Rādīt/nerādīt aizvēršanas un pārnešanas pogas galvenē.\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Šī datne ir tikai lasāma, iestatījumus atbalsta\\n * {APP_NAME}.\\n * Izmantojiet šo datni kā norādījumus, lai mainītu iestatījumus \\n * datnē \\\"brackets.json\\\", kas ir atvērta citā rūtī.\\n * Sīkākai informācija par iestatījumu izmantošanu\\n * {APP_NAME} apmeklējiet tīmekļa vietni https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Noklusējums\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"vērtība true, lai iespējotu tikai koda režīmu un paslēptu visus citus UI elementus {APP_NAME}\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"vērtība true, lai iespējotu rindas komentāru atkāpi\"\n});\n\n/* Last translated for a505026d40a4eb0bffc196eda30557c0e6b021bc */"
  },
  {
    "path": "src/nls/nb/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(feil {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Kunne ikke finne filen.\",\n    \"NOT_READABLE_ERR\"                  : \"Filen kunne ikke bli lest.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Målkatalogen kunnet ikke bli modifisert.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Rettighetene tillater ikke modifikasjoner.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Filen har blitt modifisert utenfor  {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"Filen er ikke UTF-8 kodet tekst.\",\n    \"FILE_EXISTS_ERR\"                   : \"Filen eller katalogen eksisterer allerede.\",\n    \"FILE\"                              : \"fil\",\n    \"DIRECTORY\"                         : \"katalog\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Katalognavn\",\n    \"FILENAMES_LEDE\"                    : \"Filnavn\",\n    \"FILENAME\"                          : \"filnavn\",\n    \"DIRECTORY_NAME\"                    : \"katalognavn\",\n\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Feil ved lasting av prosjektet\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Det oppstod en feil ved forsøk på å åpne fildialog. (feil {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Det oppstod en feil ved forsøk på å laste katalogen <span class='dialog-filename'>{0}</span>. (feil {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Det oppstod en feil ved lesing av innholdet i katalogen <span class='dialog-filename'>{0}</span>. (feil {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Feil ved åpning av filen\",\n    \"ERROR_OPENING_FILE\"                : \"Det oppstod en feil ved forsøk på å åpne filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Det oppstod en feil ved forsøk på å åpne følgende filer:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Feil ved oppfriskning av endringer fra disk\",\n    \"ERROR_RELOADING_FILE\"              : \"Det oppstod en feil ved forsøk på å oppfriske filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Feil ved lagring av fil\",\n    \"ERROR_SAVING_FILE\"                 : \"Det oppstod en feil ved forsøk på å lagre filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Det oppstod en feil ved forsøk på å gi nytt navn til filen\",\n    \"ERROR_RENAMING_FILE\"               : \"Det oppstod en feil ved forsøk på å gi nytt navn til filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Det oppstod en feil ved forsøk på å slette filen\",\n    \"ERROR_DELETING_FILE\"               : \"Det oppstod en feil ved forsøk på å slette filen <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Ugyldig filnavn {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Filnavn kan ikke inneholde følgende tegn: {0}\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"En fil eller katalog med navnet <span class='dialog-filename'>{0}</span> eksisterer allerede.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Feil ved oppretting av fil {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Det oppstod en feil ved forsøk på å opprette filen  {0} <span class='dialog-filename'>{1}</span>. {2}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Feil ved lesing av preferanser\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Din preferansefil er ikke gyldig JSON. Filen vil bli åpnet slik at du kan korrigere formatet. Du trenger å starte {APP_NAME} på nytt for at endringene skal ha effekt.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! {APP_NAME} kjører ikke i nettlesere ennå.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} er bygd med HTML, men akkurat nå kjører den som en skrivebords-app slik at du kan bruke den til å redigere lokale filer. Vennligst bruk applikasjonsskallet <b>github.com/adobe/brackets-app</b> repo'et for å kjøre {APP_NAME}\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Feil ved indeksering av filer\",\n    \"ERROR_MAX_FILES\"                   : \"Maksimalt antall filer har blitt indeksert. Handlinger som slår opp filer i indeksen kan feile.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Feil ved åpning av nettleser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Nettleseren Google Chrome ble ikke funnet. Vennligst sørg for at den er installert.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"En feil skjedde ved åpning av nettleseren. (feil {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Live Preview feil\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Kobler til nettleser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"En Live Preview kobling til Chrome kunne ikke bli etablert. For at Live Preview skal fungere må Chrome startes med remote debugging på.<br /><br />Ønsker du å start Chrome på nytt med remote debugging slått på?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Kan ikke laste Live Preview siden\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Åpne en HTML-fil for å åpne live Preview.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"For å starte Live Preview med en server-side fil må du spesifisere en base-url for dette prosjektet.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Feil ved starting av HTTP serveren for Live Preview filer. Vennligst prøv igjen.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Velkommen til Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live Preview kobler {APP_NAME} til din nettleser. Den åpner en forhåndsvisning av HTML-filen i nettleseren. Forhåndsvisningen oppdateres umiddelbart når du redigerer koden.<br /><br />I denne tidlige versjonen av {APP_NAME} fungerer Live Preview bare for endringer av <strong>CSS-filer</strong> og bare med <strong>Google Chrome</strong>. Vi ønsker å implementere det for HTML og JavaScript også snart!<br /><br /> (Du ser bare denne meldingen en gang).\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"For mer informasjon, se <a href='{0}' title='{0}'>Troubleshooting Live Preview connection errors</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: Kobler til\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: Initaliserer\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Koble fra Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview (lagre fil for oppfriskning)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Preview (kan ikke oppdatere p.g.a. syntax error)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Live Preview ble kansellert fordi nettleserens utviklerverktøy ble åpnet\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Live Preview ble kansellert fordi siden ble stengt i nettleseren\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Live Preview ble kansellert fordi nettleseren navigerte til en side som ikke er en del av prosjektet\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Live Preview ble kansellert for en ukjent årsak ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Lagre endringer\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Ønsker du å lagre enderinger i dokumentet <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Ønsker du å lagre enderinger i følgende filer?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Eksterne endringer\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Bekreft sletting\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Er du sikker på at du vil slette katalogen <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Fil slettet\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> har blitt modifisert på disk.<br /><br />Vil du lagre filen og overskrive de endringene?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> er blitt endret på disk, men har samtidig ulagrede endringer i {APP_NAME}.<br /><br />Hvilken versjon ønsker du å beholde?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> er blitt slettet på disken, men har ulagrede endringer i {APP_NAME}.<br /><br />Ønsker du å beholde endringene?\",\n\n    // Generic dialog/button labels\n    \"OK\"                                : \"Ok\",\n    \"CANCEL\"                            : \"Avbryt\",\n    \"DONT_SAVE\"                         : \"Ikke lagre\",\n    \"SAVE\"                              : \"Lagre\",\n    \"SAVE_AS\"                           : \"Lagre som\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Overskriv\",\n    \"DELETE\"                            : \"Slett\",\n    \"BUTTON_YES\"                        : \"Ja\",\n    \"BUTTON_NO\"                         : \"Nei\",\n\n    // Find, Replace, Find in Files\n    \"FIND_NO_RESULTS\"                   : \"Ingen resultater\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Finn\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Erstatt med\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Alle\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Erstatt\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Neste treff\",\n    \"BUTTON_PREV_HINT\"                  : \"Forrige treff\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Skill mellom store og små (bokstaver)\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regulært uttrykk\",\n\n    \"OPEN_FILE\"                         : \"Åpne fil\",\n    \"SAVE_FILE_AS\"                      : \"Lagre fil\",\n    \"CHOOSE_FOLDER\"                     : \"Velg katalog\",\n\n    \"RELEASE_NOTES\"                     : \"Versjonsmerknader\",\n    \"NO_UPDATE_TITLE\"                   : \"Du er oppdatert!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Du kjører den nyeste versjonen av {APP_NAME}.\",\n\n    // Find in Files\n    \"FIND_IN_FILES_SCOPED\"              : \"i <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"i prosjekt\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filter ekskluderer alle filer {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"fil\",\n    \"FIND_IN_FILES_FILES\"               : \"filer\",\n    \"FIND_IN_FILES_MATCH\"               : \"treff\",\n    \"FIND_IN_FILES_MATCHES\"             : \"treff\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Over \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd klikk for å ekspandere/kollapse alle\",\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Feil ved henting av oppdateringinfo\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Det var et problem å hente siste oppdateringsinformasjon fra serveren. Vennligst kontroller at du er tilkoblet internett og prøv på nytt.\",\n\n    // File exclusion filters\n    \"NO_FILE_FILTER\"                    : \"Ekskluder filer\\u2026\",\n    \"EDIT_FILE_FILTER\"                  : \"Rediger\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Rediger filter\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Ekskluder filer og kataloger som er lik følgende strenger / understrenger eller <a href='{0}' title='{0}'>jokertegn</a>. Skriv inn hver streng på egen linje.\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"og {0} mere\",\n    \"FILTER_COUNTING_FILES\"             : \"Teller filer\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Tillater {0} av {1} filer {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Tillater alle {0} filer {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Ingen Quick Edit tilgjengelig for denne markørposisjonen.\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Quick Edit: plassér markøren på et enkelt klassenavn\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Quick Edit: ufullstendig klasse attributt\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Quick Edit: ufullstendig id attributt\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Quick Edit: plassér markøren i tag, class eller id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS Timing Function Quick Edit: ugyldig syntax\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Quick Edit: plassér markøren i funksjonsnavnet\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Ingen Quick Docs tilgjengelig for denne markørposisjonen\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Laster\\u2026\",\n    \"UNTITLED\"          : \"Uten tittel\",\n    \"WORKING_FILES\"     : \"Arbeidsfiler\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Linje {0}, Kolonne {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Valgt {0} kolonne\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Valgt {0} kolonner\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Valgt {0} linje\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Valgt {0} linjer\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} valg\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klikk for å bytte indentering til mellomrom\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klikk for å bytte indentering til tabulator\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klikk for å bytte antall mellomrom som brukes til indentering\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klikk for å bytte antall tabulatorer som brukes til indentering\",\n    \"STATUSBAR_SPACES\"                      : \"Mellomrom:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tabulatorbredde:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Linje\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Linjer\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Utvidelser deaktivert\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} Problemer\",\n    \"SINGLE_ERROR\"                          : \"1 {0} Problem\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} Problemer\",\n    \"NO_ERRORS\"                             : \"Ingen {0} problemer funnet - godt jobbet!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Ingen problemer funnet - godt jobbet!\",\n    \"LINT_DISABLED\"                         : \"Linting er deaktivert\",\n    \"NO_LINT_AVAILABLE\"                     : \"Ingen linter tilgjengelig for {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Ingenting å linte\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} tidsavbrudd etter å ha ventet i {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} terminerte med feil: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Fil\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Ny\",\n    \"CMD_FILE_NEW\"                        : \"Ny\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Ny katalog\",\n    \"CMD_FILE_OPEN\"                       : \"Åpne\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Tilføye til arbeidsset\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Åpne droppete filer\",\n    \"CMD_OPEN_FOLDER\"                     : \"Åpne katalogen\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Lukk\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Lukk alle\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Lukk liste\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Lukk andre\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Lukke andre over\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Lukk andre under\",\n    \"CMD_FILE_SAVE\"                       : \"Lagre\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Lagre alle\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Lagre som\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Prosjektinstillinger\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Gi nytt navn\",\n    \"CMD_FILE_DELETE\"                     : \"Slett\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Installer utvidelser\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Utvidelsebehandleren\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Oppdater filtre\",\n    \"CMD_QUIT\"                            : \"Avslutt\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Avslutt\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Rediger\",\n    \"CMD_UNDO\"                            : \"Angre\",\n    \"CMD_REDO\"                            : \"Gjenta\",\n    \"CMD_CUT\"                             : \"Klipp\",\n    \"CMD_COPY\"                            : \"Kopier\",\n    \"CMD_PASTE\"                           : \"Lim inn\",\n    \"CMD_SELECT_ALL\"                      : \"Velg alt\",\n    \"CMD_SELECT_LINE\"                     : \"Velg linje\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Splitt utvalg til linjer\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Legg til markør på neste linje\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Legg til markør på forrige linje\",\n    \"CMD_INDENT\"                          : \"Øk innrykk\",\n    \"CMD_UNINDENT\"                        : \"Reduser innrykk\",\n    \"CMD_DUPLICATE\"                       : \"Dupliser\",\n    \"CMD_DELETE_LINES\"                    : \"Slett linje\",\n    \"CMD_COMMENT\"                         : \"Kommenter/utkommenter linjer\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Veksle blokkommentar\",\n    \"CMD_LINE_UP\"                         : \"Flytt linje(r) opp\",\n    \"CMD_LINE_DOWN\"                       : \"Flytt linje(r) ned\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Åpne linje over\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Åpne linje under\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Automatisk avslutt krøllparenteser\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Vis kodehint\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Finn\",\n    \"CMD_FIND\"                            : \"Finn\",\n    \"CMD_FIND_NEXT\"                       : \"Finn neste\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Finn forrige\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Finn alle og velg\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Legg til neste treff til utvalg\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Hopp over og legg til neste treff\",\n    \"CMD_FIND_IN_FILES\"                   : \"Finn i filer\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Finn i\\u2026\",\n    \"CMD_REPLACE\"                         : \"Erstatt\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Vis\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Gjem sidestolpe\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Vis sidestolpe\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Større skrift\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Mindre skrift\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Tilbakestill skriftstørrelse\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Rull linje opp\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Rull linje ned\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Linjenummer\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Uthev aktiv linje\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Tekstbryting\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Live Preview Highlight\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Lint filer ved lagring\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sorter på tilføyd\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sorter på navn\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sorter på type\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatisk sortering\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Naviger\",\n    \"CMD_QUICK_OPEN\"                      : \"Hurtigåpne\",\n    \"CMD_GOTO_LINE\"                       : \"Gå til linje\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Gå til definisjon\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Gå til første feil/advarsel\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Hurtigrediger\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Quick Docs\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Forrige treff\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Neste treff\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Ny regel\",\n    \"CMD_NEXT_DOC\"                        : \"Neste dokument\",\n    \"CMD_PREV_DOC\"                        : \"Forrige dokument\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Vis i filtre\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Vis i utforsker\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Show in Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Vis i OS\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Hjelp\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Se etter oppdateringer\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Hvordan bruke {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} support\",\n    \"CMD_SUGGEST\"                         : \"Foreslå en funksjonalitet\",\n    \"CMD_RELEASE_NOTES\"                   : \"Utgivelsesnotat\",\n    \"CMD_GET_INVOLVED\"                    : \"Bli involvert\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Vis utvidelser\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} hjemmeside\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} på Twitter\",\n    \"CMD_ABOUT\"                           : \"Om {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Åpne preferansefilen\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"eksperimentell bygg\",\n    \"DEVELOPMENT_BUILD\"                    : \"utvikler bygg\",\n    \"RELOAD_FROM_DISK\"                     : \"Oppdater fra disk\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Behold endringer i editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Lukk (ikke lagre)\",\n    \"RELAUNCH_CHROME\"                      : \"Start Chrome på nytt\",\n    \"ABOUT\"                                : \"Om\",\n    \"CLOSE\"                                : \"Lukk\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Notices, terms and conditions pertaining to third party software are located at <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> and incorporated by reference herein.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentation and source at <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Made with \\u2764 and JavaScript by:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Lots of people (but we're having trouble loading that data right now).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs and the MDN graphical logo are licensed under a Creative Commons Attribution license, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"En ny for {APP_NAME} er tilgjengelig! Klikk her for mer informasjon.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Oppdatering er tilgjengelig\",\n    \"UPDATE_MESSAGE\"                       : \"Hei, en ny bygg for {APP_NAME} er tilgjengelig. Her er noen av de nye funksjonene:\",\n    \"GET_IT_NOW\"                           : \"Hent den nå!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Prosjektinstillinger for: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Live Preview base URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"For å bruke en lokal server, skriv inn en url lingnende http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Protokollen {0} er ikke støttet av Live Preview&mdash;vennligst bruk http: eller https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Base URL kan ikke inneholde søkeparametere som \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Base URL kan ikke inneholde hashes som \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Spesialtegn som '{0}' må bli %-kodet.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Ukjent feil ved tolking av base URL\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Ny regel\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Installer\",\n    \"UPDATE\"                               : \"Oppdater\",\n    \"REMOVE\"                               : \"Slett\",\n    \"OVERWRITE\"                            : \"Overskriv\",\n    \"CANT_REMOVE_DEV\"                      : \"Utvidelser i \\\"dev\\\" katalogen må slettes manuelt.\",\n    \"CANT_UPDATE\"                          : \"Oppdatering er ikke kompatibel med denne versjonen av {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Utvidelser i \\\"dev\\\" katalogen kan ikke oppdateres automatisk.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Installer utvidelse\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Oppdater utvidelse\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Utvidelse URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL for utvidelsens zipfil eller GitHub repo\",\n    \"INSTALLING_FROM\"                      : \"Installerer utvidelse fra {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installasjon var suksessfull!\",\n    \"INSTALL_FAILED\"                       : \"Installasjonen feilet.\",\n    \"CANCELING_INSTALL\"                    : \"Kansellerer\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Kansellering av installasjonen tar lang tid. En intern feil kan ha oppstått.\",\n    \"INSTALL_CANCELED\"                     : \"Installasjonen kansellert.\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Nedlastet innhold er ikke en gyldig zipfil\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Filen package.json er ikke gyldig (error: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Filen package.json spesifiserer ikke pakkenavn.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} er et ugyldig pakkenavn.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Filen package.json spesifiserer ikke en pakkeversjon.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Pakkens versjonsnummer {0} er ugyldig.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"{APP_NAME} kompatiblitetstreng ({0}) er ugyldig.\",\n    \"DISALLOWED_WORDS\"                     : \"Ordene ({1}) er ikke tillatt i {0} feltet.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Utvidelsen er ikke kompatibel med denne versjonen av {APP_NAME}. Den er installert i katalogen for deaktiverte utvidelser.\",\n    \"MISSING_MAIN\"                         : \"Pakken har ingen main.js fil.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Installasjon av denne pakken vil overskrive en tidligere installert utvidelse. Overskrive den gamle utvidelsen?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Denne pakken er den samme versjonen som er allerede installert. Overskrive den eksisterende utvidelsen?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Denne pakken er versjon {0} som er eldre enn den installerte versjonen ({1}). Overskrive den eksisterende installasjonen?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Intern feil: nedlastingsid er allerede i bruk.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Kan ikke koble til server.\",\n    \"BAD_HTTP_STATUS\"                      : \"Fil ikke funnet på server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Kan ikke lagre nedlastingen til temporær fil.\",\n    \"ERROR_LOADING\"                        : \"Det oppstod en feil ved oppstart av utvidelsen.\",\n    \"MALFORMED_URL\"                        : \"URL er ugyldig. Vennligst kontroller at du tastet inn korrekt.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL må være en http eller https URL.\",\n    \"UNKNOWN_ERROR\"                        : \"Ukjent intern feil.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Utvidelsesbehandler\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Kan ikke aksessere utvidelsesregisteret. Vennligst prøv igjen senere.\",\n    \"INSTALL_FROM_URL\"                     : \"Installerer fra URL\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Forfatter\",\n    \"EXTENSION_DATE\"                       : \"Dato\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Denne utvidelsen krever en nyere versjon av {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Denne utvidelsen virker bare med en eldre versjon av {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Versjon {0} av denne utvidelsen krever en nyere versjon av {APP_NAME}. Men du kan installere tidligere versjon {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Versjon {0} av denne utvidelsen krever en eldre versjon av {APP_NAME}. Men du kan installere tidligere versjon {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Ingen beskrivelse\",\n    \"EXTENSION_MORE_INFO\"                  : \"Mer info...\",\n    \"EXTENSION_ERROR\"                      : \"Utvidelsesfeil\",\n    \"EXTENSION_KEYWORDS\"                   : \"Nøkkelord\",\n    \"EXTENSION_INSTALLED\"                  : \"Installert\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Denne utvidelsen har blitt lastet ned og vil bli installert etter omstart av {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Søk\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Mer\",\n    \"BROWSE_EXTENSIONS\"                    : \"Bla gjennom utvidelser\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Slett utvidelse\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Klarte ikkke å fjerne en eller flere utvidelser: {0}. {APP_NAME} vil uansett starte på nytt.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Oppdater utvidelse\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Klarte ikke å oppdatere en eller flere utvidelser: {0}. {APP_NAME} will uansett starte på nytt.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Markert for sletting\",\n    \"UNDO_REMOVE\"                          : \"Angre\",\n    \"MARKED_FOR_UPDATE\"                    : \"Markert for oppdatering\",\n    \"UNDO_UPDATE\"                          : \"Angre\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Endre utvidelser\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"For å oppdatere eller slette markerte utvidelser, må {APP_NAME} starte på nytt. Du vil bli spurt om å lagre You'll be prompted to save unsaved changes.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Fjern utvidelse og start på nytt\",\n    \"CHANGE_AND_RELOAD\"                    : \"Endre utvidelse og start på nytt\",\n    \"UPDATE_AND_RELOAD\"                    : \"Oppdater utvidelse og start på nytt\",\n    \"PROCESSING_EXTENSIONS\"                : \"Prosesserer utvidelseendringer\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Kunne ikke fjerne utvidelsen {0} ettersom den ikke var installert.\",\n    \"NO_EXTENSIONS\"                        : \"Ingen utvidelser installert ennå.<br>Klikk på Tilgjengelig-fanen over for å komme i gang.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Fant ingen utvidelser for ditt søk.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Vær forsiktig når du installerer utvidelser fra ukjent kilde.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Installert\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Tilgjengelig\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Oppdateringer\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Ingen treff.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Ingen eksisterende CSS regler passer ditt utvalg.<br> Klikk \\\"Ny regel\\\" for å lage en.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Det er ingen stilark i prosjektet ditt.<br>Lag ett for å legge til CSS regler.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"største\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"piksler\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"Feil\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Vis utviklerverktøy\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Gjenåpne med utvidelser\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Gjenåpne uten utvidelser\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nytt {APP_NAME} vindu\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Bytt språk\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Kjør tester\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Vis ytelsesdata\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Aktiver Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Logg Nodestatus til konsoll\",\n    \"CMD_RESTART_NODE\"                          : \"Omstart Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Vis feil i statuslinjen\",\n\n    \"LANGUAGE_TITLE\"                            : \"Bytt språk\",\n    \"LANGUAGE_MESSAGE\"                          : \"Velg ønsket språk fra listen under:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Gjenåpne {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Avbryt\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Sett systemforvalg\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tid\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progresjon\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Flytt valgt punkt<br><kbd class='text'>Shift</kbd> Flytt med ti enheter<br><kbd class='text'>Tab</kbd> Bytt punkter\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Øk eller mink trinn<br><kbd>←</kbd><kbd>→</kbd> 'Start' eller 'Slutt'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Den gamle verdien <code>{0}</code> er ikke gyldig, den viste funksjonen ble endret til <code>{1}</code>. Dokumentet vil bli oppdatert ved første redigering.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Gjeldende farge\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Original farge\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa Format\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex Format\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa Format\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Brukt {1} gang)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Brukt {1} ganger)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Hopp til definisjonen\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Vis parameter hint\",\n    \"NO_ARGUMENTS\"                              : \"<ingen parametere>\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Quick View ved hovring\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Siste prosjekter\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Les mer\"\n});\n\n/* Last translated for 36fd23e311b2bb7f64c37e56c00006d8795050da */\n"
  },
  {
    "path": "src/nls/nb/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.nb\"\n});\n"
  },
  {
    "path": "src/nls/nl/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(fout {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Het bestand kan niet worden gevonden.\",\n    \"NOT_READABLE_ERR\"                  : \"Het bestand kan niet worden ingelezen.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Bestanden groter dan {0} MB kunnen niet worden geopend in {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"De doelmap kan niet gewijzigd worden.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"De bevoegdheden laten u niet toe enige wijzigingen aan te brengen.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Het bestand is bijgewerkt buiten {APP_NAME} om.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} ondersteunt momenteel alleen bestanden in UTF-8 tekstcodering.\",\n    \"FILE_EXISTS_ERR\"                   : \"Het bestand of map bestaat al.\",\n    \"FILE\"                              : \"bestand\",\n    \"FILE_TITLE\"                        : \"Bestand\",\n    \"DIRECTORY\"                         : \"map\",\n    \"DIRECTORY_TITLE\"                   : \"Map\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Mapnamen\",\n    \"FILENAMES_LEDE\"                    : \"Bestandsnamen\",\n    \"FILENAME\"                          : \"Bestandsnaam\",\n    \"DIRECTORY_NAME\"                    : \"Mapnaam\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Probleem tijdens het laden van het project\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Er is een fout opgetreden bij het tonen van het dialoogvenster om een bestand te openen. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Er is een fout opgetreden bij het laden van map <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Er is een fout opgetreden bij het lezen van de inhoud van map <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Probleem bij het openen van een bestand\",\n    \"ERROR_OPENING_FILE\"                : \"Er is een fout opgetreden bij het openen van het bestand <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Er is een fout opgetreden bij het openen van de volgende bestanden:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Probleem bij het herladen van wijzigingen op de schijf\",\n    \"ERROR_RELOADING_FILE\"              : \"Er is een fout opgetreden bij het herladen van het bestand <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Probleem bij het opslaan van een bestand\",\n    \"ERROR_SAVING_FILE\"                 : \"Er is een fout opgetreden bij het opslaan van het bestand <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Probleem bij het hernoemen van een bestand\",\n    \"ERROR_RENAMING_FILE\"               : \"Er is een fout opgetreden bij het hernoemen van het bestand <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Probleem bij het verwijderen van een bestand\",\n    \"ERROR_DELETING_FILE\"               : \"Er is een fout opgetreden bij het verwijderen van het bestand <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Ongeldige {0} naam\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Bestandsnamen kunnen de volgende karakters niet bevatten: {0} of gebruik maken van woorden die door het systeem zijn gereserveerd.\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Een bestand of map met de naam <span class='dialog-filename'>{0}</span> bestaat al.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Probleem bij het aanmaken van een {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Er is een fout opgetreden bij het aanmaken van het {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Het is niet mogelijk een map te openen en tegelijkertijd andere bestanden.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Fout tijdens lezen van het configuratiebestand \\u0028keymap.json\\u0029.\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"De JSON-code in het configuratiebestand \\u0028keymap.json\\u0029 is niet correct. Het bestand wordt geopend zodat je het kan corrigeren.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Het configuratiebestand \\u0028keymap.json\\u0029 is niet opgeslagen in UTF-8 tekstcodering en kan zodoende niet worden geopend.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Je kan deze sneltoetsen niet toewijzen aan deze commando\\u0027s: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Je kan deze sneltoetsen niet opnieuw toewijzen: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Je wijst meerdere sneltoetsen toe aan deze commando\\u0027s: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Je hebt meerdere acties aan dezelfde sneltoetsen toegewezen: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Deze sneltoetsen zijn niet toegestaan: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Je wijst sneltoetsen toe aan niet-bestaande commando\\u0027s: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Fout tijdens lezen instellingen\",\n    \"ERROR_PREFS_CORRUPT\"               : \"De JSON-code van het configuratiebestand is niet correct. Het bestand wordt geopend zodat je het kan corrigeren. {APP_NAME} moet hierna herstart worden om de wijzigingen toe te passen.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"De JSON-code van het project-configuratiebestand is niet correct. Het bestand wordt geopend zodat je het kan corrigeren. Je moet het project opnieuw laden om de wijzigingen toe te passen.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oeps! {APP_NAME} werkt nog niet in browsers.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} is gebouwd in HTML, maar op dit moment werkt het als desktop applicatie zodat je het kan gebruiken om lokale bestanden te bewerken. Gebruik graag de applicatie-omgeving op <b>github.com/adobe/brackets-shell</b> om {APP_NAME} te starten.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Probleem bij het indexeren van bestanden\",\n    \"ERROR_MAX_FILES\"                   : \"Het maximum aantal bestanden is geïndexeerd. Het kan zijn dat acties om bestanden op te zoeken in de index niet correct verlopen.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Probleem bij het starten in de browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"De Google Chrome browser kon niet gevonden worden. Zorg ervoor dat deze geïnstalleerd is.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Er is een fout opgetreden bij het starten van de browser. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Probleem met Live Voorbeeld\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Bezig met verbinden met de browser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Om met Live Voorbeeld te verbinden, moet Chrome opnieuw gestart worden met debugging op afstand ingeschakeld.<br /><br />Wil je Chrome herstarten en debugging op afstand inschakelen?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Onmogelijk om de Live Ontwikkeling pagina te laden\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Open een HTML bestand om Live Voorbeeld te starten.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Om live voorbeeld te starten met een server-side bestand, moet je een Start URL voor dit project definiëren.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Er is een fout opgetreden bij het opstarten van de HTTP server voor live ontwikkeling bestanden. Probeer alsjeblieft opnieuw.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Welkom bij Live Voorbeeld!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live Voorbeeld verbindt {APP_NAME} met je browser. Het toont een voorbeeld van je HTML bestand in de browser, vervolgens updatet het voorbeeld onmiddelijk bij het wijzigen van je code.<br /><br />In deze vroege versie van {APP_NAME}, werkt Live Voorbeeld enkel met <strong>Google Chrome</strong> en updatet live bij het wijzigen van <strong>CSS of HTML bestanden</strong>. Wijzigingen aan JavaScript bestanden worden automatisch herladen wanneer je bewaart.<br /><br />(Je zal dit bericht slechts eenmaal zien.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Voor meer informatie, zie <a href='{0}' title='{0}'>oplossen van Live Voorbeeld verbindingsproblemen</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Voorbeeld\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Voorbeeld: Bezig met verbinden\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Voorbeeld: Initialiseren\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Verbreek verbinding met Live Voorbeeld\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Voorbeeld (sla bestand op om te verversen)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Voorbeeld (niet bezig met updaten door een verkeerde syntax)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Live Voorbeeld is geannuleerd omdat de developer tools in de browser zijn geopend\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Live Voorbeeld is geannuleerd omdat de pagina gesloten werd in de browser\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Live Voorbeeld is geannuleerd omdat de browser navigeerde naar een pagina die geen deel uit maakt van het huidige project\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Live Voorbeeld is geannuleerd om een onbekende reden ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Opslaan van wijzigingen\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Wil je de wijzigingen opslaan die je maakte in het document <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Wil je je wijzigingen van de volgende bestanden opslaan?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Externe wijzigingen\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Bevestig verwijderen\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Ben je zeker dat je de map <span class='dialog-filename'>{0}</span> wil verwijderen?\",\n    \"FILE_DELETED_TITLE\"                : \"Bestand verwijderd\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> is gewijzigd op de schijf buiten {APP_NAME}.<br /><br />Wil je het bestand overschrijven evenals de wijzigingen buiten {APP_NAME} om?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> is gewijzigd op de schijf, maar heeft ook onbewaarde wijzigingen in {APP_NAME}.<br /><br />Welke versie wil je behouden?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> is verwijderd op de schijf, maar heeft onbewaarde wijzigingen in {APP_NAME}.<br /><br />Wil je je wijzigingen behouden?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Gedaan\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Annuleer\",\n    \"DONT_SAVE\"                         : \"Niet opslaan\",\n    \"SAVE\"                              : \"Opslaan\",\n    \"SAVE_AS\"                           : \"Opslaan als\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Overschrijven\",\n    \"DELETE\"                            : \"Verwijder\",\n    \"BUTTON_YES\"                        : \"Ja\",\n    \"BUTTON_NO\"                         : \"Nee\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} van {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Geen resultaten\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Zoek\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Vervang met\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Alle\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Vervang\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Vervang\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Volgende overeenkomst\",\n    \"BUTTON_PREV_HINT\"                  : \"Vorige overeenkomst\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Hoofdlettergevoelig\",\n    \"BUTTON_REGEXP_HINT\"                : \"Reguliere expressie\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Vervang zonder herstellen\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Omdat meer dan {0} bestanden moeten worden veranderd, {APP_NAME} zal ongeopende bestanden op de schijf aanpassen.<br /> Wijzigingen kunnen niet meer ongedaan worden gemaakt in die bestanden.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Vervang zonder herstellen\",\n\n    \"OPEN_FILE\"                         : \"Bestand openen\",\n    \"SAVE_FILE_AS\"                      : \"Bestand opslaan\",\n    \"CHOOSE_FOLDER\"                     : \"Kies een map\",\n\n    \"RELEASE_NOTES\"                     : \"Nieuw in deze versie\",\n    \"NO_UPDATE_TITLE\"                   : \"Je bent up to date!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Je werkt met de laatste versie van {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Vervang\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"met\",\n    \"FIND_TITLE_LABEL\"                  : \"Gevonden\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} in {3}\",\n\n    //Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"in <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"in project\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filter sluit alle bestanden uit {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"bestand\",\n    \"FIND_IN_FILES_FILES\"               : \"bestanden\",\n    \"FIND_IN_FILES_MATCH\"               : \"overeenkomst\",\n    \"FIND_IN_FILES_MATCHES\"             : \"overeenkomsten\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Meer dan \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Klik Ctrl/Cmd om alles in/uit te vouwen\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Vervang fouten\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"De volgende bestanden zijn niet aangepast omdat deze na het zoeken zijn aangepast of niet bewerkt kunnen worden.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Probleem bij het ophalen van update-informatie\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Er is een fout opgetreden bij het ophalen van de laatste update-informatie van de server. Zorg ervoor dat je verbonden bent met het internet en probeer opnieuw.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Nieuwe set uitgesloten bestanden\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Sluit geen bestanden uit\",\n    \"NO_FILE_FILTER\"                    : \"Geen uitgesloten bestanden\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Sluit {0} uit\",\n    \"EDIT_FILE_FILTER\"                  : \"Bewerk\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Bewerk set uitgesloten bestanden\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Sluit bestanden en mappen uit met de volgende teksten/deelteksten of <a href='{0}' title='{0}'>wildcards</a>. Plaats elke tekst op een nieuwe regel.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Geef deze set een naam (optioneel)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"en {0} meer\",\n    \"FILTER_COUNTING_FILES\"             : \"Bestanden tellen\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Sta {0} toe van {1} bestanden {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Sta alle {0} bestanden toe {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Quick Edit is niet beschikbaar voor huidige cursorpositie.\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Quick Edit: plaats cursor op een enkele class naam.\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Quick Edit: class attribuut is incompleet.\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Quick Edit: id attribuut is incompleet.\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Quick Edit: plaats cursor in tag, class of id.\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS Timing Function Quick Edit: syntax onjuist\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Quick Edit: plaats cursor in functienaam.\",\n\n     // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Geen snelle documentatie beschikbaar voor huidige cursorpositie.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Laden\\u2026\",\n    \"UNTITLED\"          : \"Naamloos\",\n    \"WORKING_FILES\"     : \"Geopend\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Boven\",\n    \"BOTTOM\"            : \"Beneden\",\n    \"LEFT\"              : \"Links\",\n    \"RIGHT\"             : \"Rechts\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Niet splitsen\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Verticaal splitsen\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Horizontaal splitsen\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Splits de editor verticaal of horizontaal\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configureer bestanden\",\n\n    \"SPLITVIEW_INFO_TITLE\"             : \"Al geopend\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"      : \"Dit bestand is al geopend in een ander paneel. {APP_NAME} zal spoedig ondersteuning bieden aan het openen van hetzelfde bestand in meerdere panelen. Voor nu wordt het bestand weergegeven in het paneel waarin het al geopend is.<br /><br />(Dit is een eenmalige melding.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Regel {0}, Kolom {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} kolom geselecteerd\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} kolommen geselecteerd\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} regel geselecteerd\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} regels geselecteerd\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} selecties\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klik om de indentatie te veranderen naar spaties\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klik om de indentatie te veranderen naar tabs\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klik om het aantal spaties bij indentatie te veranderen\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klik om de breedte van het tab karakter te veranderen\",\n    \"STATUSBAR_SPACES\"                      : \"Spaties:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab Grootte:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Regel\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Regels\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extensies uitgeschakeld\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Klik om de cursor te wisselen tussen Insert (INS) en Overwrite (OVR) mode.\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Klik om bestandstype te veranderen.\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Klik om foutenpaneel te openen.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(default)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Standaard voor .{0} bestanden\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} Fouten\",\n    \"SINGLE_ERROR\"                          : \"1 {0} Fout\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} Fouten\",\n    \"NO_ERRORS\"                             : \"Geen {0} fouten - goed zo!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Geen fouten gevonden - goed zo!\",\n    \"LINT_DISABLED\"                         : \"Linting is uitgeschakeld\",\n    \"NO_LINT_AVAILABLE\"                     : \"Er is geen linter beschikbaar voor {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Niets om te linten\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} is gestopt na wachten voor {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} is gestopt met fout: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Bestand\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nieuw\",\n    \"CMD_FILE_NEW\"                        : \"Nieuw bestand\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nieuwe map\",\n    \"CMD_FILE_OPEN\"                       : \"Bestand openen\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Voeg toe aan werkset\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Open gesloten bestanden\",\n    \"CMD_OPEN_FOLDER\"                     : \"Open map\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Sluit\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Alles sluiten\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Sluit lijsten\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Sluit anderen\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Sluit bestanden boven\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Sluit bestanden onder\",\n    \"CMD_FILE_SAVE\"                       : \"Opslaan\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Alles opslaan\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Opslaan als\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Voorbeeld\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Experimentele versie Live Voorbeeld\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Forceer herladen Live Voorbeeld\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projectinstellingen\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Bestand hernoemen\",\n    \"CMD_FILE_DELETE\"                     : \"Verwijder\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Installeer extensie\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Extensiebeheer\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Ververs bestandsboom\",\n    \"CMD_QUIT\"                            : \"Stoppen\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Afsluiten\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Bewerken\",\n    \"CMD_UNDO\"                            : \"Herstel\",\n    \"CMD_REDO\"                            : \"Opnieuw\",\n    \"CMD_CUT\"                             : \"Knippen\",\n    \"CMD_COPY\"                            : \"Kopierën\",\n    \"CMD_PASTE\"                           : \"Plakken\",\n    \"CMD_SELECT_ALL\"                      : \"Alles selecteren\",\n    \"CMD_SELECT_LINE\"                     : \"Regel selecteren\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Splits selectie in regels\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Voeg cursor toe aan volgende regel\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Voeg cursor toe aan vorige regel\",\n    \"CMD_INDENT\"                          : \"Inspringen\",\n    \"CMD_UNINDENT\"                        : \"Inspringen verwijderen\",\n    \"CMD_DUPLICATE\"                       : \"Dupliceer\",\n    \"CMD_DELETE_LINES\"                    : \"Verwijder regel\",\n    \"CMD_COMMENT\"                         : \"Zet regel commentaar aan/uit\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Zet blok commentaar aan/uit\",\n    \"CMD_LINE_UP\"                         : \"Verplaats regel naar boven\",\n    \"CMD_LINE_DOWN\"                       : \"Verplaats regel naar beneden\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Open regel boven\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Open regel beneden\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Automatisch accolades sluiten\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Toon code hints\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Zoek\",\n    \"CMD_FIND\"                            : \"Zoek\",\n    \"CMD_FIND_NEXT\"                       : \"Zoek volgende\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Zoek vorige\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Zoek alles en selecteer\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Voeg eerstvolgende overeenkomst toe aan selectie\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Sla-over en selecteer volgende overeenkomst\",\n    \"CMD_FIND_IN_FILES\"                   : \"Zoek in bestanden\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Zoek in\\u2026\",\n    \"CMD_REPLACE\"                         : \"Vervang\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Vervang in bestanden\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Vervang in\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Beeld\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Verberg zijbalk\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Toon zijbalk\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Vergroot lettertype\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Verklein lettertype\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Herstel lettertype\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Scroll regel naar Boven\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Scroll regel naar Beneden\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Regelnummers\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Markeer actieve regel\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Word wrap\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Live voorbeeld markeren\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Lint bestanden bij opslaan\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sorteren op toegevoegd\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sorteren op naam\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sorteren op type\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatisch sorteren\",\n    \"CMD_THEMES\"                          : \"Thema\\u0027s\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigeer\",\n    \"CMD_QUICK_OPEN\"                      : \"Snel openen\",\n    \"CMD_GOTO_LINE\"                       : \"Ga naar regel\\u2026\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Definitie snel zoeken\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Ga naar de eerstvolgende fout/waarschuwing\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Snel wijzigen\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Snel naar documentatie\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Vorige overeenkomst\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Volgende overeenkomst\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Nieuwe regel\",\n    \"CMD_NEXT_DOC\"                        : \"Volgend document\",\n    \"CMD_PREV_DOC\"                        : \"Vorig document\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Toon in bestandsboom\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Toon in Verkenner\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Toon in Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Toon in besturingssysteem\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Help\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Controleer op updates\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Hoe gebruik je {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} ondersteuning\",\n    \"CMD_SUGGEST\"                         : \"Stel een nieuwe functie voor\",\n    \"CMD_RELEASE_NOTES\"                   : \"Nieuw in deze versie\",\n    \"CMD_GET_INVOLVED\"                    : \"Doe mee\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Toon de map met extensies\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Statusrapport\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} homepage\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} op Twitter\",\n    \"CMD_ABOUT\"                           : \"Over {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Open configuratiebestand\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Open gebruiker toetsenbordinstellingen\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimentele build\",\n    \"RELEASE_BUILD\"                        : \"build\",\n    \"DEVELOPMENT_BUILD\"                    : \"development build\",\n    \"RELOAD_FROM_DISK\"                     : \"Opnieuw laden van schijf\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Behoud veranderingen in editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Sluit (niet bewaren)\",\n    \"RELAUNCH_CHROME\"                      : \"Herstart Chrome\",\n    \"ABOUT\"                                : \"Over\",\n    \"CLOSE\"                                : \"Sluiten\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"build timestamp: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Kennisgevingen, voorwaarden en bepalingen met betrekking tot software van derden bevinden zich op <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> en op de pagina's, hierin door verwijzing opgenomen.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentatie en broncode op <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Gemaakt met \\u2764 en JavaScript door:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Veel mensen (maar we hebben problemen met het laden van die data op dit moment).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs en het MDN logo zijn gelicentieerd onder een Creative Commons Attribution licentie, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Er is een nieuwe versie van {APP_NAME} beschikbaar! Klik hier voor details.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Update beschikbaar\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, er is een nieuwe versie van {APP_NAME} beschikbaar. Hier zijn een aantal van de nieuwe functies:\",\n    \"GET_IT_NOW\"                           : \"Download het nu!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projectinstellingen voor: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Live voorbeeld begin URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Gebruik url als http://localhost:8000/ om als lokale server te gebruiken.\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Het {0} protocol wordt niet ondersteund door Live Voorbeeld&mdash;gebruik http: of https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"De start URL kan geen zoekparameters bevatten zoals \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"De start URL kan geen hashes bevatten zoals \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Speciale karakters zoals '{0}' moeten %-geëncodeerd zijn.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Onbekende fout bij het parsen van de begin URL\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Open een bestand wanneer dit paneel actief is</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Huidig thema\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Scrollbalken van thema\",\n    \"FONT_SIZE\"                            : \"Lettergrootte\",\n    \"FONT_FAMILY\"                          : \"Lettertype\\u0028s\\u0029\",\n    \"THEMES_SETTINGS\"                      : \"Thema-instellingen\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Nieuwe regel\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Installeren\",\n    \"UPDATE\"                               : \"Update\",\n    \"REMOVE\"                               : \"Verwijder\",\n    \"OVERWRITE\"                            : \"Overschrijf\",\n    \"CANT_REMOVE_DEV\"                      : \"Extensies in de \\\"dev\\\" map moeten met de hand verwijderd worden.\",\n    \"CANT_UPDATE\"                          : \"De update is niet compatibel met deze versie van {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Extensies in de \\\"dev\\\" map kunnen niet automatisch geupdate worden.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Installeer extensie\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Update extensie\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Extensie URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL van het zip bestand of de GitHub repo van de extensie\",\n    \"INSTALLING_FROM\"                      : \"Bezig met installeren van {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installatie succesvol!\",\n    \"INSTALL_FAILED\"                       : \"Installatie mislukt.\",\n    \"CANCELING_INSTALL\"                    : \"Bezig met annuleren\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Het annuleren van de installatie duurt lang. Een intern probleem kan zijn opgetreden.\",\n    \"INSTALL_CANCELED\"                     : \"Installatie geannuleerd.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Laat volledige beschrijving zien\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Laat afgekorte beschrijving zien\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"De gedownloade inhoud is geen geldig zip bestand.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Het package.json bestand is niet geldig (Fout: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Het package.json specifieert geen pakket naam.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} is een ongeldige pakket naam.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Het package.json bestand specifieert geen geldige pakket versie.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Het pakket versienummer ({0}) is ongeldig.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"De {APP_NAME} compatibiliteit string ({0}) is ongeldig.\",\n    \"DISALLOWED_WORDS\"                     : \"De woorden ({1}) zijn niet toegelaten in het {0} veld.\",\n    \"API_NOT_COMPATIBLE\"                   : \"De extensie is niet compatibel met deze versie van {APP_NAME}. Het werd geïnstalleerd in de map met uitgeschakelde extensies.\",\n    \"MISSING_MAIN\"                         : \"Het pakket heeft geen main.js bestand.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Het installeren van dit pakket zal een vroeger geïnstalleerde extensie overschrijven. Overschrijf de oudere extensie?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Dit pakket is dezelfde versie als degene die op dit moment is geïnstalleerd. Overschrijf de bestaande installatie?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Dit pakket is versie {0} welke ouder is dan de op dit moment geïnstalleerde ({1}). Overschrijf de bestaande installatie?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Interne fout: download ID is reeds in gebruik.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Kan niet verbinden met de server.\",\n    \"BAD_HTTP_STATUS\"                      : \"Bestand niet worden gevonden op server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Onmogelijk om het gedownloade bestand op te slaan naar een tijdelijk bestand.\",\n    \"ERROR_LOADING\"                        : \"De extensie ondervond een probleem bij het opstarten.\",\n    \"MALFORMED_URL\"                        : \"De URL is ongeldig. Controleer of deze correct is ingevoerd.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"De URL moet een http of https URL zijn.\",\n    \"UNKNOWN_ERROR\"                        : \"Onbekende interne fout.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Extensiebeheer\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Er is momenteel geen toegang mogelijk tot het extensieregister. Probeer later opnieuw.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Sleep .zip hier of\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Sleep .zip hier voor installatie\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Installatie/update afgebroken vanwege de volgende fouten:\",\n    \"INSTALL_FROM_URL\"                     : \"installeer van URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validating\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Auteur\",\n    \"EXTENSION_DATE\"                       : \"Datum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Deze extensie vereist een nieuwere versie van {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Deze extensie werkt momenteel enkel met oudere versies van {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Versie {0} van deze extensie vereist een nieuwere versie van {APP_NAME}. Je kan wel de oudere versie {1} installeren.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Versie {0} van deze extensie werkt alleen met oudere versies van {APP_NAME}. Je kan wel de oudere versie {1} installeren.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Geen beschrijving\",\n    \"EXTENSION_MORE_INFO\"                  : \"Meer info...\",\n    \"EXTENSION_ERROR\"                      : \"Extensie fout\",\n    \"EXTENSION_KEYWORDS\"                   : \"Sleutelwoorden\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Vertaalt in {0} talen, inclusief de jouwe\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Vertaalt in {0} talen\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Deze extensie is vertaald in de volgende talen: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Geïnstalleerd\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Deze extensie is gedownload en zal geïnstalleerd worden wanneer je {APP_NAME} stopt.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Zoek\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Meer\",\n    \"BROWSE_EXTENSIONS\"                    : \"Blader door extensies\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Verwijder extensie\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Onmogelijk om een of meerdere extensies te verwijderen: {0}. {APP_NAME} zal nog steeds stoppen.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Update extensie\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Onmogelijk om een of meerdere extensies te updaten: {0}. {APP_NAME} zal nog steeds stoppen.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Aangeduid voor verwijder\",\n    \"UNDO_REMOVE\"                          : \"Herstel\",\n    \"MARKED_FOR_UPDATE\"                    : \"Aangeduid voor update\",\n    \"UNDO_UPDATE\"                          : \"Herstel\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Wijzig extensies\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Om de aangeduidde extensie te updaten of te verwijderen, moet je {APP_NAME} stoppen en herstarten. Er zal gevraagd worden alle onbewaarde wijzigingen op te slaan.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Verwijder extensies en herladen\",\n    \"CHANGE_AND_RELOAD\"                    : \"Wijzig extensies en herladen\",\n    \"UPDATE_AND_RELOAD\"                    : \"Update extensies en herladen\",\n    \"PROCESSING_EXTENSIONS\"                : \"Verwerken van wijzigingen aan extensie\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Kon de extensie {0} niet verwijderen omdat deze niet is geïnstalleerd\",\n    \"NO_EXTENSIONS\"                        : \"Geen extensies geïnstalleerd.<br>Klik op de Beschikbaar tab hierboven om te starten.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Geen extensies komen overeen met je zoekopdracht.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Wees voorzichtig bij het installeren van extensies van een onbekende bron.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Geïnstalleerd\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Beschikbaar\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Thema\\u0027s\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Updates\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Geen overeenkomsten beschikbaar.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Alle overeenkomsten zijn samengevouwen. Vouw alle bestanden uit in het overzicht rechts om overeenkomsten te zien.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Er zijn geen bestaande CSS regels die overeenkomsten met jouw selectie.<br> Klik \\\"Nieuwe regel\\\" om te maken.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Er zijn geen stylesheets in je project.<br>Maak er een om CSS regels toe te voegen.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"meest grote\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pixels\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"fouten\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Tools voor ontwikkelaars weergeven\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Laad {APP_NAME} opnieuw\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Laad opnieuw zonder extensies\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nieuw {APP_NAME} venster\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Installeer {APP_NAME} in de opdrachtprompt\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Wijzig taal \\u0028change language\\u0029\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Start testen\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Toon prestatiedata\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Schakel Node Debugger in\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Log Node status naar console\",\n    \"CMD_RESTART_NODE\"                          : \"Herstart Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Laad fouten zien in statusbalk\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Open broncode van {APP_NAME}\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} Command Line Shortcut\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Er is een fout opgetreden bij het installeren van de opdrachtprompt snelkoppeling. Kijk op <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>deze pagina</a> voor mogelijke foutoplossing.<br/><br/>Reden: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Niet mogelijk om bestaande symlink <code>/usr/local/bin/brackets</code> te verwijderen.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Niet mogelijk om map <code>/usr/local/bin</code> te maken.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Niet mogelijk om symlink <code>/usr/local/bin/brackets</code> te maken.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Interne fout.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Koppeling met opdrachtprompt is niet beschikbaar op dit OS.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Gelukt! Je kunt {APP_NAME} nu makkelijk starten vanaf de opdrachtprompt. Type <code>brackets myFile.txt</code> om een bestand te openen of <code>brackets myFolder</code> om van project te wisselen. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Klik hier</a> voor meer informatie over het gebruik van {APP_NAME} via de opdrachtprompt \\u0028in het Engels\\u0029.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Wijzig taal\",\n    \"LANGUAGE_MESSAGE\"                          : \"Taal:\",\n    \"LANGUAGE_SUBMIT\"                           : \"{APP_NAME} opnieuw laden\",\n    \"LANGUAGE_CANCEL\"                           : \"Annuleren\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Systeemvoorkeuren\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Statusrapport instellingen\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} statusrapport\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Deel anoniem informatie over hoe je {APP_NAME} gebruikt.\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Om {APP_NAME} te verbeteren, wordt er periodiek <strong>(anoniem)</strong> beperkt aantal statistieken verzonden naar Adobe over hoe je {APP_NAME} gebruikt. Deze informatie helpt ons prioriteit te geven aan bepaalde functies, het vinden van fouten in de software en problemen in het gebruik zichtbaar te maken.<br><br>Je kan de data bekijken of ervoor kiezen om geen data te delen via <strong>Help > Statusrapport</strong>. <br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Lees meer over het {APP_NAME} statusrapport (Engels)</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} statusrapport\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Om {APP_NAME} te verbeteren, wordt er periodiek <strong>(anoniem)</strong> beperkt aantal statistieken verzonden naar Adobe over hoe je {APP_NAME} gebruikt. Deze informatie helpt ons prioriteit te geven aan bepaalde functies, het vinden van fouten in de software en problemen in het gebruik zichtbaar te maken. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Lees meer over het {APP_NAME} statusrapport (Engels)</a> en hoe het bijdraagt aan de {APP_NAME} gemeenschap terwijl je privacy beschermd blijft.</p><p>Onder zie je een voorbeeld van de data die wordt verzonden bij het volgende statusrapport, <em>als</em> het is ingeschakeld.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tijd\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Voortgang\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Verplaats geselecteerde punt<br><kbd class='text'>Shift</kbd> Verplaats met 10 units<br><kbd class='text'>Tab</kbd> Verwissel punten\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Vergroot of verklein stappen<br><kbd>←</kbd><kbd>→</kbd> 'Start' of 'Einde'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"De oude waarde <code>{0}</code> is niet geldig, de weergegeven functie is veranderd naar <code>{1}</code>. Het bestand wordt bijgewerkt met de eerste aanpassing.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Huidige kleur\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Originele kleur\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa formaat\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex formaat\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa formaat\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} ({1} keer gebruikt)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} ({1} keer gebruikt)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Ga naar definitie\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Toon parameter hint\",\n    \"NO_ARGUMENTS\"                              : \"<geen parameters>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"JavaScript File Inference Problem\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} kwam in de problemen met het verwerken van <span class='dialog-filename'>{0}</span>.<br><br>Dit bestand wordt niet verder verwerkt voor \\\"code hints\\\", \\\"Jump to Definition\\\" of \\\"Quick Edit\\\". Om het bestand weer te activeren, open <code>brackets.json</code> in je project en bewerkt <code>jscodehints.detectedExclusions</code>.<br><br>Dit is vermoedelijk een bug in {APP_NAME}. Indien mogelijk kun je een kopie van het bestand sturen naar <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>\\\"rapporteer een bug\\\"</a> met een link naar het bestand.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Snel bekijken bij muis over\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Recente projecten\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Lees meer\",\n\n    //extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Alles inklappen\",\n    \"EXPAND_ALL\"                    : \"Alles uitklappen\",\n    \"COLLAPSE_CURRENT\"              : \"Huidige inklappen\",\n    \"EXPAND_CURRENT\"                : \"Huidige uitklappen\"\n});\n/* Last translated for 50cbe1b8848786c6be27d4788e4b6a367244abc2 */\n"
  },
  {
    "path": "src/nls/nl/urls.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"nl/Aan-de-slag\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_nl/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.nl\"\n});\n"
  },
  {
    "path": "src/nls/pl/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(błąd {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Nie znaleziono pliku/folderu.\",\n    \"NOT_READABLE_ERR\"                  : \"Nie można odczytać pliku/folderu.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Pliki większe niż {0} MB nie mogą być otwarte w {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Nie można zmodyfikować folderu docelowego.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Nie masz uprawnień by modyfikować ten plik.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Plik został zmodyfikowany poza {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} aktualnie wspiera tylko pliki tekstowe z kodowaniem UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Plik lub folder już istnieje.\",\n    \"FILE\"                              : \"plik\",\n    \"FILE_TITLE\"                        : \"Plik\",\n    \"DIRECTORY\"                         : \"folder\",\n    \"DIRECTORY_TITLE\"                   : \"Folder\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Nazwy folderów\",\n    \"FILENAMES_LEDE\"                    : \"Nazwy plików\",\n    \"FILENAME\"                          : \"Nazwa pliku\",\n    \"DIRECTORY_NAME\"                    : \"Nazwa folderu\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Błąd podczas ładowania projektu\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Wystąpił błąd podczas wyświetlania okna otwierania pliku. (błąd {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Wystąpił błąd przy próbie otwarcia folderu <span class='dialog-filename'>{0}</span>. (błąd {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Wystąpił błąd podczas odczytu zawartości folderu <span class='dialog-filename'>{0}</span>. (błąd {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Błąd podczas otwarcia pliku\",\n    \"ERROR_OPENING_FILE\"                : \"Wystąpił błąd podczas próby otwarcia pliku <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Wystąpił błąd podczas otwierania plików:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Błąd podczas przeładowania zmian z dysku\",\n    \"ERROR_RELOADING_FILE\"              : \"Błąd podczas przeładowania pliku <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Problem z zapisaniem pliku\",\n    \"ERROR_SAVING_FILE\"                 : \"Błąd podczas próby zapisu pliku <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Błąd podczas zmiany nazwy pliku {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Błąd podczas próby zmiany nazwy pliku {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Plik lub folder nie jest częścią aktualnie otwartego projektu. Niestety, w tym momencie możesz zmienić nazwę tylko dla plików projektu.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Błąd podczas usuwania pliku {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Błąd podczas próby usunięcia {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Nieprawidłowa nazwa pliku {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} nie może kończyć się kropką (.), zawierać żadnych zarezerwowanych słów ani żadnych z tych znaków: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Plik lub folder o nazwie <span class='dialog-filename'>{0}</span> już istnieje.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Nie można utworzyć pliku {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Błąd podczas próby stworzenia pliku {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Nie można otworzyć folderu podczas otwierana innych plików.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Błąd podczas odczytywania konfiguracji klawiszy\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Twój plik z konfiguracją klawiszy nie jest poprawnie zakodowanym plikiem JSON. Zostanie on otwarty abyś mógł go poprawić.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Twój plik z konfiguracją klawiszy nie jest poprawnie zakodowanym plikiem UTF-8 i nie może zostać załadowany.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Nie możesz nadpisać skrótów do tych komend: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Nie możesz nadpisać tych skrótów: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Próbujesz przypisać kilka skrótów do następujących komend: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Upewnij się, że następujące skróty są unikalne (nie nadpisują się): {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Podane skróty są nieprawidłowe: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Próbujesz przypisać skróty do niestniejących komend: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Błąd podczas wczytywania ustawień\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Twój plik ustawień nie jest poprawnie zakodowanym plikiem JSON. Zostanie on otwarty abyś mógł go poprawić. Aby zastosować zmiany, uruchom ponownie {APP_NAME}.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Twój plik ustawień projektu nie jest poprawnie zakodowanym plikiem JSON. Zostanie on otwarty abyś mógł go poprawić. Aby zastosować zmiany, musisz przeładować projekt.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! {APP_NAME} nie działa jeszcze w przeglądarkach.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} został zbudowany w HTML, jednak na razie działa jako samodzielna aplikacja. Możesz użyć jej do edycji plików na dysku. Aby uruchomić {APP_NAME} użyj aplikacji dostępnej pod adresem <b>github.com/adobe/brackets-shell</b>.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Błąd podczas indeksowania plików\",\n    \"ERROR_MAX_FILES\"                   : \"Ten projekt zawiera więcej niż 30.000 plików. Funkcje, które pracują na wielu plikach mogą być wyłączone lub zachowywać się tak, jakby projekt był pusty. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Przeczytaj więcej nt. pracy z dużymi projektami</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Błąd podczas uruchamiania przeglądarki\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Nie znaleziono przeglądarki Google Chrome. Upewnij się, że jest zainstalowana.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Błąd podczas uruchamiania przeglądarki. (błąd {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Błąd podglądu na żywo\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Łączenie z przeglądarką\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Aby podgląd na żywo mógł się połączyć, Chrome musi zostać zrestartowany z włączonym zdalnym debugowaniem.<br /><br />Czy chcesz zrestartować Chrome i uaktywnić zdalne debugowanie?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Nie można wczytać strony podglądu na żywo.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Aby uruchomić podgląd na żywo, otwórz plik HTML lub upewnij się, że w Twoim projekcie jest plik index.html.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Aby uruchomić podgląd na żywo na plikach serwerowych, musisz podać główny adres dla tego projektu (Base URL).\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Błąd przy próbie uruchomienia serwera HTTP dla podglądu na żywo. Spróbuj ponownie.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Witaj w podglądzie na żywo (Live Preview)!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Podgląd na żywo został podłączony do twojej przeglądarki. Umożliwia on podgląd twojego pliku HTML w przeglądarce oraz aktualizuje go za każdym razem, gdy edytujesz swój kod.<br /><br />W aktualnej wersji {APP_NAME}, podgląd na żywo działa tylko w <strong>Google Chrome</strong> i aktualizuje w czasie rzeczywistym <strong>pliki CSS lub HTML</strong>. Zmiany w JavaScript są automatycznie odświeżane po zapisie pliku.<br /><br />(Zobaczysz tę wiadomość tylko raz.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Więcej informacji znajdziesz na stronie <a href='{0}' title='{0}'>Troubleshooting Live Preview connection errors</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Podgląd na żywo\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Podgląd na żywo: łączenie\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Podgląd na żywo: inicjalizacja\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Rozłącz podgląd na żywo\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Podgląd na żywo (zapisz plik by odświeżyć)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Podgląd na żywo (bez odświeżania - wystąpiły błędy składniowe)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Podgląd na żywo został wyłączony, ponieważ uruchomiono narzędzia dla programistów w przeglądarce\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Podgląd na żywo został wyłączony, ponieważ strona została zamknięta w przeglądarce\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Podgląd na żywo został wyłączony, ponieważ została załadowana strona nie należąca do aktualnego projektu\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Podgląd na żywo został wyłączony z nieznanego powodu ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Zapisz zmiany\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Czy chcesz zapisać zmiany w dokumencie <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Czy chcesz zapisać zmiany w następujących plikach?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Zmiany zewnętrzne\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Potwierdź usunięcie\",\n    \"CONFIRM_FILE_DELETE\"               : \"Czy na pewno chcesz usunąć plik <span class='dialog-filename'>{0}</span>?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Czy na pewno chcesz usunąć folder <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Plik został usunięty\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> został zmodyfikowany na dysku, poza {APP_NAME}.<br /><br />Czy chcesz zapisać plik i nadpisać te zmiany?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> został zmodyfikowany na dysku, poza {APP_NAME}, ale zawiera też niezapisane zmiany w {APP_NAME}.<br /><br />Którą wersję chcesz zachować?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> został usunięty z dysku, ale zawiera niezapisane zmiany w {APP_NAME}.<br /><br />Czy chcesz zachować te zmiany?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Gotowe\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Anuluj\",\n    \"DONT_SAVE\"                         : \"Nie zapisuj\",\n    \"SAVE\"                              : \"Zapisz\",\n    \"SAVE_AS\"                           : \"Zapisz jako\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Nadpisz\",\n    \"DELETE\"                            : \"Usuń\",\n    \"BUTTON_YES\"                        : \"Tak\",\n    \"BUTTON_NO\"                         : \"Nie\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} z {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Brak wyników\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Szukaj\\u2026\",\n    \"FIND_HISTORY_MAX_COUNT\"            : \"Maksymalna liczba pozycji w historii wyszukiwania\",\n    \"REPLACE_PLACEHOLDER\"               : \"Zamień na\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Zamień wiele\\u2026\",\n    \"BUTTON_REPLACE_BATCH\"              : \"Przetwarzaj\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Zamień w wielu plikach\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Zamień\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Następna reguła\",\n    \"BUTTON_PREV_HINT\"                  : \"Poprzednia reguła\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Weź pod uwagę wielkie i małe litery\",\n    \"BUTTON_REGEXP_HINT\"                : \"Wyrażenie regularne\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Zamień bez cofania\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Ponieważ więcej niż {0} plików wymaga zmiany, {APP_NAME} zmodyfikuje pliki na dysku, które nie są otwarte.<br />Nie będziesz możlwiości cofnięcia nadpisanych zmian w tych plikach.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Zamień bez cofania\",\n\n    \"OPEN_FILE\"                         : \"Otwórz plik\",\n    \"SAVE_FILE_AS\"                      : \"Zapisz plik\",\n    \"CHOOSE_FOLDER\"                     : \"Wybierz folder\",\n\n    \"RELEASE_NOTES\"                     : \"Informacje o wydaniu\",\n    \"NO_UPDATE_TITLE\"                   : \"{APP_NAME} jest aktualny!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Aktualnie używasz najnowszej wersji {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Zamień\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"z\",\n    \"FIND_TITLE_LABEL\"                  : \"Znaleziono\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} w {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"w <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"w projekcie\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtr wyklucza wszystkie pliki {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"plik\",\n    \"FIND_IN_FILES_FILES\"               : \"pliki\",\n    \"FIND_IN_FILES_MATCH\"               : \"dopasowanie\",\n    \"FIND_IN_FILES_MATCHES\"             : \"dopasowania\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Więcej niż \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Naciśnij Ctrl/Cmd by rozwinąć/zwinąć wszystkie\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indeksowanie do natychmiastowego wyszukiwania\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Zamień błędy\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Poniższe pliki nie zostały zmienione, ponieważ ich treść zmieniła się po zakończeniu wyszukiwania lub nie mogły być zapisane.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Błąd podczas pobierania informacji o aktualizacjach\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Wystąpił problem podczas pobierania informacji o najnowszej wersji aplikacji. Upewnij się, że masz połączenie z internetem i spróbuj ponownie\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Nowy filtr\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Nie wykluczaj plików\",\n    \"NO_FILE_FILTER\"                    : \"Brak wykluczonych plików\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Wyklucz {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Edytuj\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Edytuj wykluczenia\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Wyklucz pliki/foldery pasujące do następujących nazw, wzorów lub <a href='{0}' title='{0}'>masek</a>. Każdą regułę umieść w osobnej linii.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nazwa wykluczenia (opcjonalnie)\",\n    \"FILTER_NAME_REMAINING\"             : \"pozostało {0} znaków\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"i {0} więcej\",\n    \"FILTER_COUNTING_FILES\"             : \"Liczenie plików\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Przeszukane zostanie {0} z {1} plików {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Przeszukane zostanie wszystkie {0} plików {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Nie można użyć szybkiej edycji w tym miejscu\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Szybka edycja CSS: zaznacz kursorem pojedynczą nazwę klasy\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Szybka edycja CSS: niekompletny atrybut class\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Szybka edycja CSS: niekompletny atrybut id\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Szybka edycja CSS: zaznacz kursorem tag, klasę lub id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Szybka edycja funkcji czasowych CSS: nieprawidłowa składnia\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Szybka edycja JS: zaznacz kursorem nazwę funkcji\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Nie znaleziono dokumentacji dla tego elementu.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Ładowanie\\u2026\",\n    \"UNTITLED\"          : \"Bez tytułu\",\n    \"WORKING_FILES\"     : \"Otwarte pliki\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Panel górny\",\n    \"BOTTOM\"            : \"Panel dolny\",\n    \"LEFT\"              : \"Panel lewy\",\n    \"RIGHT\"             : \"Panel prawy\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Bez podziału\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Podziel pionowo\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Podziel poziomo\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Podziel edytor pionowo lub poziomo\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Uporządkuj pliki\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Plik jest już otwarty\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Plik jest już otwarty w innym panelu. {APP_NAME} niedługo będzie pozwalał otwierać ten sam plik w wielu panelach. Do tego czasu plik będzie widoczny w panelu, w którym już jest otwarty.<br /><br />(Tę wiadomość zobaczysz tylko raz)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"Space\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"linia {0}, kolumna {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Zaznaczono {0} kolumnę\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Zaznaczono {0} kolumn\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Zaznaczono {0} linię\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Zaznaczono {0} linii\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} zaznaczeń\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Kliknij, by zamienić wcięcia na spacje\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Kliknij, by zamienić wcięcia na tabulacje\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Kliknij, by zmienić ilość spacji we wcięciu\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Kliknij, by zmienić wielkość tabulacji\",\n    \"STATUSBAR_SPACES\"                      : \"Spacje:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tabulacje:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} linia\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} linii\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Rozszerzenia wyłączone\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Kliknij aby zmienić tryb wprowadzania: wstaw (INS) lub zastąp (OVR)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Kliknij aby zmienić rodzaj pliku (podświetlanie składni)\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Naciśnij aby włączyć/wyłączyć panel raportów.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(domyślny)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Ustaw domyślny dla plików .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} problemów\",\n    \"SINGLE_ERROR\"                          : \"1 błąd {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} błędów {0} \",\n    \"NO_ERRORS\"                             : \"Brak błędów {0} – dobra robota!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Brak błędów - dobra robota!\",\n    \"LINT_DISABLED\"                         : \"Linting jest wyłączony.\",\n    \"NO_LINT_AVAILABLE\"                     : \"Żaden linter nie jest dostępny dla {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Brak plików do sprawdzenia.\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} przekroczył limit czasu, czekał {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} zakończył z błędem: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Plik\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nowy\",\n    \"CMD_FILE_NEW\"                        : \"Nowy plik\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nowy folder\",\n    \"CMD_FILE_OPEN\"                       : \"Otwórz\\u2026\",\n    \"CMD_RECENT_FILES_OPEN\"               : \"Ostatnio otwierane\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Dodaj do folderu roboczego\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Otwórz przeciągnięte pliki\",\n    \"CMD_OPEN_FOLDER\"                     : \"Otwórz folder\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Zamknij\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Zamknij wszystko\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Zamknij listę\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Zamknij inne\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Zamknij pliki powyżej\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Zamknij pliki poniżej\",\n    \"CMD_FILE_SAVE\"                       : \"Zapisz\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Zapisz wszystko\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Zapisz jako\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Podgląd na żywo\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Podgląd na żywo (eksperymentalny)\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Wymuś przeładowanie podglądu na żywo\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Ustawienia projektu\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Zmień nazwę\",\n    \"CMD_FILE_DELETE\"                     : \"Usuń\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Zainstaluj rozszerzenie\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Menedżer rozszerzeń\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Odśwież\",\n    \"CMD_QUIT\"                            : \"Wyjdź\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Wyjdź\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edytuj\",\n    \"CMD_UNDO\"                            : \"Cofnij\",\n    \"CMD_REDO\"                            : \"Ponów\",\n    \"CMD_CUT\"                             : \"Wytnij\",\n    \"CMD_COPY\"                            : \"Kopiuj\",\n    \"CMD_PASTE\"                           : \"Wklej\",\n    \"CMD_SELECT_ALL\"                      : \"Zaznacz wszystko\",\n    \"CMD_SELECT_LINE\"                     : \"Zaznacz linię\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Podziel zaznaczenie na linie\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Dodaj kursor do następnej linii\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Dodaj kursor do poprzedniej linii\",\n    \"CMD_INDENT\"                          : \"Dodaj wcięcie\",\n    \"CMD_UNINDENT\"                        : \"Cofnij wcięcie\",\n    \"CMD_DUPLICATE\"                       : \"Duplikuj\",\n    \"CMD_DELETE_LINES\"                    : \"Usuń linię\",\n    \"CMD_COMMENT\"                         : \"Komentarz liniowy\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Komentarz blokowy\",\n    \"CMD_LINE_UP\"                         : \"Przenieś linię wyżej\",\n    \"CMD_LINE_DOWN\"                       : \"Przenieś linię niżej\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Otwórz linię wyżej\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Otwórz linię niżej\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Automatycznie zamykaj nawiasy\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Pokaż podpowiedź\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Szukaj\",\n    \"CMD_FIND\"                            : \"Znajdź\",\n    \"CMD_FIND_NEXT\"                       : \"Znajdź następny\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Znajdź poprzedni\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Znajdź wszystkie i zaznacz\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Dodaj następny wynik do zaznaczenia\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Pomiń i dodaj następny wynik\",\n    \"CMD_FIND_IN_FILES\"                   : \"Szukaj w plikach\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Szukaj w\\u2026\",\n    \"CMD_REPLACE\"                         : \"Zamień\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Zamień w plikach\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Zamień w\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Widok\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Ukryj pasek boczny\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Pokaż pasek boczny\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Przełącz pasek boczny\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Przełącz panele\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Tryb bez przeszkadzania\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Zwiększ czcionkę\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Zmniejsz czcionkę\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Przywróć domyślny rozmiar czcionki\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Przewiń linię wyżej\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Przewiń linię niżej\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Numery linii\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Podświetl aktualną linię\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Zawijaj wiersze\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Podświetlaj w podglądzie na żywo\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Sprawdzaj poprawność plików przy zapisie\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sortuj według dodanych\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sortuj według nazwy\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sortuj według typu\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatyczne sortowanie\",\n    \"CMD_THEMES\"                          : \"Motywy\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Nawigacja\",\n    \"CMD_QUICK_OPEN\"                      : \"Otwórz szybko\",\n    \"CMD_GOTO_LINE\"                       : \"Przejdź do linii\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Znajdź szybko definicję\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Przejdź do pierwszego błędu\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Szybka edycja\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Szybka dokumentacja\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Poprzedni wynik\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Następny wynik\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Nowa reguła\",\n    \"CMD_NEXT_DOC\"                        : \"Następny dokument\",\n    \"CMD_PREV_DOC\"                        : \"Poprzedni dokument\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Następny dokument z listy\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Poprzedni dokument z listy\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Pokaż w drzewie katalogów\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Pokaż w eksploratorze\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Pokaż w Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Pokaż w systemie plików\",\n    \"CMD_SWITCH_PANE_FOCUS\"               : \"Zmień aktywny panel\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Pomoc\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Sprawdź aktualizacje\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Jak używać {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Wsparcie {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Zaproponuj swój pomysł\",\n    \"CMD_RELEASE_NOTES\"                   : \"Informacje o wydaniu\",\n    \"CMD_GET_INVOLVED\"                    : \"Daj coś od siebie\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Otwórz folder z rozszerzeniami\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Raportowanie\",\n    \"CMD_HOMEPAGE\"                        : \"Strona główna {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} na Twitterze\",\n    \"CMD_ABOUT\"                           : \"O programie\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Otwórz plik z ustawieniami\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Otwórz plik z konfiguracją klawiszy\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"kompilacja eksperymentalna\",\n    \"RELEASE_BUILD\"                        : \"kompilacja\",\n    \"DEVELOPMENT_BUILD\"                    : \"kompilacja rozwojowa\",\n    \"RELOAD_FROM_DISK\"                     : \"Załaduj z dysku\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Zachowaj zmiany w edytorze\",\n    \"CLOSE_DONT_SAVE\"                      : \"Zamknij (nie zapisuj)\",\n    \"RELAUNCH_CHROME\"                      : \"Zrestartuj Chrome\",\n    \"ABOUT\"                                : \"O programie\",\n    \"CLOSE\"                                : \"Zamknij\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Wydanie {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"Czas kompilacji: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Uwagi i warunki odnoszące się do oprogramowania firm trzecich znajdują się na: <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> i zostały dołączone jako odnośnik.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentacja i pliki źródłowe dostępne są pod adresem <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Stworzony z \\u2764 oraz w JavaScript przez:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Mnóstwo ludzi (mamy problemy, by załadować teraz te wszystkie dane).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"Dokumentacja MDN oraz logo MDN są objęte licencją Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Dostępna jest nowa wersja {APP_NAME}! Kliknij tutaj i dowiedz się więcej.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Dostępna nowa aktualizacja\",\n    \"UPDATE_MESSAGE\"                       : \"Hej, dostępna jest już nowa wersja {APP_NAME}. Oto kilka nowych funkcjonalności:\",\n    \"GET_IT_NOW\"                           : \"Pobierz teraz!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Ustawienia projektu dla: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Adres podglądu na żywo\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Aby użyć lokalnego serwera, wpisz odpowiedni adres, np. http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Protokół {0} nie jest wspierany przez podgląd na żywo&mdash;Użyj http lub https.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Adres URL nie może zawierać parametrów wyszukiwania takich, jak \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Adres URL nie może zawierać znaku hash: \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Znaki specjalne takie, jak '{0}' muszą być zakodowane.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Nieznany błąd podczas parsowania adresu URL\",\n    \n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Kliknij w to okno, a następnie otwórz plik</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Przenieś ten widok do: {0}\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Aktualny motyw\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Użyj pasków przewijania z motywu\",\n    \"FONT_SIZE\"                            : \"Rozmiar czcionki\",\n    \"FONT_FAMILY\"                          : \"Rodzina czcionek\",\n    \"THEMES_SETTINGS\"                      : \"Ustawienia motywów\",\n    \n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Nowa reguła\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Zainstaluj\",\n    \"UPDATE\"                               : \"Aktualizuj\",\n    \"REMOVE\"                               : \"Usuń\",\n    \"DISABLE\"                              : \"Wyłącz\",\n    \"ENABLE\"                               : \"Włącz\",\n    \"OVERWRITE\"                            : \"Nadpisz\",\n    \"CANT_REMOVE_DEV\"                      : \"Rozszerzenia w folderze \\\"dev\\\" muszą być usunięte ręcznie.\",\n    \"CANT_UPDATE\"                          : \"Aktualizacja nie jest kompatybilna z tą wersją {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Rozszerzenia w folderze \\\"dev\\\" nie mogą być automatycznie zaktualizowane.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Zainstaluj rozszerzenie\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Aktualizuj rozszerzenie\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Adres URL rozszerzenia\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Adres URL pliku zip z rozszerzeniem lub adres repozytorium na GitHub\",\n    \"INSTALLING_FROM\"                      : \"Instaluję rozszerzenie z {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalacja zakończona!\",\n    \"INSTALL_FAILED\"                       : \"Instalacja nie powiodła się.\",\n    \"CANCELING_INSTALL\"                    : \"Anulowanie\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Anulowanie instalacji trwa zbyt długo. Możliwe, że wystąpił błąd wewnętrzny.\",\n    \"INSTALL_CANCELED\"                     : \"Instalacja anulowana.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Pokaż cały opis\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Pokaż skrócony opis\",\n    \"SORT_EXTENSION_METHOD\"                : \"Sortuj rozszerzenia według liczby pobrań lub daty publikacji\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Pobrany plik nie jest poprawnym plikiem zip.\",\n    \"MISSING_PACKAGE_JSON\"                 : \"Pakiet nie zawiera pliku package.json.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Plik package.json nie jest poprawny (wystąpił błąd: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Plik package.json nie zawiera nazwy pakietu.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} jest niepoprawną nazwą pakietu.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Plik package.json nie zawiera wersji pakietu.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Numer wersji pakietu ({0}) jest niepoprawny.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Ciąg kompatybilności z {APP_NAME} ({0}) jest nieprawidłowy.\",\n    \"DISALLOWED_WORDS\"                     : \"Słowa ({1}) są niedozwolone w polu {0}.\",\n    \"NPM_INSTALL_FAILED\"                   : \"Nie udało się wykonać polecenia npm install: {0}\",\n    \"API_NOT_COMPATIBLE\"                   : \"Rozszerzenie nie jest kompatybilne z tą wersją {APP_NAME}. Jest zainstalowane w folderze z nieaktywnymi rozszerzeniami.\",\n    \"MISSING_MAIN\"                         : \"Pakiet nie zawiera pliku main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Zainstalowanie tego rozszerzenia nadpisze to, które zainstalowano poprzednio. Czy nadpisać starsze rozszerzenie?\",\n    \"EXTENSION_SAME_VERSION\"               : \"To rozszerzenie jest w tej samej wersji, co obecnie zainstalowane. Czy nadpisać zainstalowane rozszerzenie?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"To rozszerzenie jest w wersji {0}, czyli jest starsze niż obecnie zainstalowane ({1}). Czy nadpisać zainstalowane rozszerzenie?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Błąd wewnętrzny: taki plik już istnieje.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Nie można połączyć z serwerem.\",\n    \"BAD_HTTP_STATUS\"                      : \"Nie znaleziono pliku na serwerze (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Nie można zapisać pobranego pliku w folderze tymczasowym.\",\n    \"ERROR_LOADING\"                        : \"Rozszerzenie napotkało błąd podczas uruchamiania.\",\n    \"MALFORMED_URL\"                        : \"Niepoprawny adres URL. Sprawdź czy został wpisany prawidłowo.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"Adres URL musi zaczynać się od http lub https.\",\n    \"UNKNOWN_ERROR\"                        : \"Nieznany błąd wewnętrzny.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Menedżer rozszerzeń\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Nie udało się dostać do rejestru rozszerzeń. Spróbuj ponownie później.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Przenieś plik .zip lub\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Przenieś plik .zip aby zainstalować\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Instalacja/aktualizacja przerwana z powodu błędów:\",\n    \"INSTALL_FROM_URL\"                     : \"zainstaluj z adresu URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Sprawdzanie\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Data\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"To rozszerzenie wymaga nowszej wersji {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"To rozszerzenie działa tylko ze starszymi wersjami {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Wersja {0} tego rozszerzenia wymaga nowszej wersji {APP_NAME}, ale możesz zainstalować starszą wersję {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Wersja {0} tego rozszerzenia wymaga starszej wersji {APP_NAME}, ale możesz zainstalować starszą wersję {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Brak opisu\",\n    \"EXTENSION_MORE_INFO\"                  : \"Więcej informacji\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Błąd rozszerzenia\",\n    \"EXTENSION_KEYWORDS\"                   : \"Słowa kluczowe\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Przetłumaczono na {0} języków, w tym twój\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Przetłumaczono na {0} języków\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"To rozszerzenie zostało przetłumaczone na języki: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Zainstalowane\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Aktualizacja rozszerzenia została pobrana i będzie zainstalowana po przeładowaniu {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Szukaj\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Więcej\",\n    \"BROWSE_EXTENSIONS\"                    : \"Przeglądaj rozszerzenia\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Usuń rozszerzenie\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Nie udało się usunąć rozszerzeń: {0}. {APP_NAME} zostanie zrestartowany.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Zaktualizuj rozszerzenie\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Nie udało się zaktualizować rozszerzeń: {0}. {APP_NAME} zostanie zrestartowany.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Wyłącz rozszerzenie\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Nie udało się wyłączyć rozszerzeń: {0}. {APP_NAME} zostanie zrestartowany.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Zaznaczono do usunięcia\",\n    \"UNDO_REMOVE\"                          : \"Cofnij\",\n    \"MARKED_FOR_UPDATE\"                    : \"Zaznaczono do aktualizacji\",\n    \"UNDO_UPDATE\"                          : \"Cofnij\",\n    \"MARKED_FOR_DISABLING\"                 : \"Zaznaczono do wyłączenia\",\n    \"UNDO_DISABLE\"                         : \"Cofnij\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Zmień rozszerzenia\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Aby zaktualizować, usunąć lub wyłączyć zaznaczone rozszerzenia, {APP_NAME} musi zostać zrestartowany. Zostaniesz poproszony o zapisanie zmian.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Usuń rozszerzenia i zrestartuj\",\n    \"CHANGE_AND_RELOAD\"                    : \"Zmień rozszerzenia i zrestartuj\",\n    \"UPDATE_AND_RELOAD\"                    : \"Zaktualizuj rozszerzenia i zrestartuj\",\n    \"DISABLE_AND_RELOAD\"                   : \"Wyłącz rozszerzenia i zrestartuj\",\n    \"PROCESSING_EXTENSIONS\"                : \"Przetwarzanie\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Nie można usunąć rozszerzenia {0}, ponieważ nie zostało zainstalowane.\",\n    \"NO_EXTENSIONS\"                        : \"Nie masz jeszcze żadnych rozszerzeń.<br>Użyj zakładki Dostępne (powyżej), aby zobaczyć listę.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nie znaleziono pasujących rozszerzeń.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Uwaga: te rozszerzenia mogą pochodzić od innych autorów i mają pełne uprawnienia. Uważaj gdy instalujesz rozszerzenia z nieznanych źródeł.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Zainstalowane\",\n    \"EXTENSIONS_DEFAULT_TITLE\"             : \"Domyślne\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Dostępne\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Motywy\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Aktualizacje\",\n    \"EXTENSIONS_LAST_UPDATED\"              : \"Ostatnia aktualizacja\",\n    \"EXTENSIONS_DOWNLOADS\"                 : \"Ilość pobrań\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Brak wyników.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Wszystkie wyniki zostały zwinięte. Rozwiń listę plików po prawej, by pokazać wyniki.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Brak reguł.<br> Kliknij \\\"Nowa reguła\\\", aby ją utworzyć.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"W twoim projekcie brakuje stylów CSS.<br>Stwórz je, by móc dodawać reguły CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"największy\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pikseli\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debuguj\",\n    \"ERRORS\"                                    : \"Błędy\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Pokaż narzędzia deweloperskie\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Uruchom ponownie z rozszerzeniami\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Uruchom ponownie bez rozszerzeń\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nowe okno\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Zainstaluj skrót do wiersza poleceń\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Zmień język\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Uruchom testy\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Pokaż informacje o wydajności\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Włącz debugger Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Zapisz stan Node w konsoli\",\n    \"CMD_RESTART_NODE\"                          : \"Zrestartuj Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Pokazuj błędy na pasku statusu\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Otwórz kod źródłowy {APP_NAME}\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"Skrót do wiersza poleceń {APP_NAME}\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Błąd podczas instalacji skrótu wiersza poleceń. Przeczytaj artykuł <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>z propozycjami rozwiązania tego problemu.</a>.<br/><br/>Powód: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Nie można usunąć istniejącego dowiązania <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Nie można utworzyć katalogu <code>/usr/local/bin</code>.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Nie można utworzyć dowiązania <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Błąd wewnętrzny.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Skrót do wiersza poleceń nie jest dostępny w tym systemie.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Udało się! Teraz możesz uruchamiać {APP_NAME} z wiersza poleceń: <code>brackets plik.txt</code> aby otworzyć plik lub <code>brackets folder</code> aby zmienić projekt. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Przeczytaj więcej</a> na temat używania {APP_NAME} w wierszu poleceń.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Zmień język\",\n    \"LANGUAGE_MESSAGE\"                          : \"Język:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Zrestartuj {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Anuluj\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Domyślny systemu\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Ustawienia raportowania\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"Raporty {APP_NAME}\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Wysyłaj anonimowe informacje o tym, jak używam {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Aby ciągle udoskonalać {APP_NAME}, co pewien czas wysyłamy <strong>anonimowe</strong> statystyki do Adobe na temat tego, jak korzystasz z edytora. Informacje te pomagają nam tworzyć lepsze funkcjonalności, wyszukiwać problemy czy poprawiać wygodę w korzystaniu z programu. <br><br>Możesz zobaczyć co przesyłamy lub wyłączyć przesyłanie danych w menu <strong>Pomoc > Raportowanie</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Przeczytaj więcej o raportach w {APP_NAME}</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"Raporty {APP_NAME}\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Aby ciągle udoskonalać {APP_NAME}, co pewien czas wysyłamy <strong>anonimowe</strong> statystyki do Adobe na temat tego, jak wykorzystujesz {APP_NAME}. Informacje te pomagają nam tworzyć lepsze funkcjonalności, znajdować problemy czy poprawiać wygodę w korzystaniu z programu. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Przeczytaj więcej o raportach w {APP_NAME}</a> oraz w jaki sposób pomaga to całej społeczności {APP_NAME}, jednocześnie dbając o twoją prywatność.</p><p>Poniżej możesz podejrzeć jakie dane zostaną przesłane w twoim następnym raporcie <em>jeżeli</em> jest u uaktywniony.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Czas\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Postęp\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Przenieś zaznaczony punkt<br><kbd class='text'>Shift</kbd> Przenieś o 10 jednostek<br><kbd class='text'>Tab</kbd> Zmień punkt\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Zwiększ lub zmniejsz kroki<br><kbd>←</kbd><kbd>→</kbd> 'Start' lub 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Poprzednia wartość <code>{0}</code> jest niepoprawna, więc została zamieniona na <code>{1}</code>. Dokument zostanie uaktualniony podczas pierwszej edycji.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Aktualny kolor\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Orginalny kolor\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Format RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Format Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Format HSLa\",\n    \"COLOR_EDITOR_0X_BUTTON_TIP\"                : \"Format Hex (0x)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (użyto {1} raz)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (użyto {1} razy)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Przejdź do definicji\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Pokaż podpowiedź (parametr)\",\n    \"NO_ARGUMENTS\"                              : \"<brak parametrów>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Błąd podczas sprawdzania poprawności kodu JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} napotkał problemy podczas przetwarzania pliku <span class='dialog-filename'>{0}</span>.<br><br>Plik nie będzie już przetwarzany w celu pokazywania podpowiedzi w kodzie, wykorzystywaniu Przejdź do definicji lub do Szybkiej Edycji. Aby przywrócić dla pliku te funkcjonalności, otwórz <code>.brackets.json</code> w swoim projekcie i edytuj plik <code>jscodehints.detectedExclusions</code>.<br><br>Jest to prawdopodobnie błąd {APP_NAME}. Jeżeli chcesz dostarczyć kopię tego pliku, prosimy <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>prześlij plik z błędem</a>.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Szybki Podgląd po najechaniu na element\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Ostatnie projekty\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Czytaj więcej\",\n    \n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Zwiń wszystko\",\n    \"EXPAND_ALL\"                    : \"Rozwiń wszystko\",\n    \"COLLAPSE_CURRENT\"              : \"Zwiń element\",\n    \"EXPAND_CURRENT\"                : \"Rozwiń element\",\n\n    // extensions/default/NavigationAndHistory\n    \"RECENT_FILES_DLG_HEADER\"                    : \"Ostatnio otwierane pliki\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\"        : \"Wyczyść\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\"        : \"Wyczyść pliki (oprócz aktualnie otwartych)\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true, by automatycznie zamykać nawiasy okrągłe, kwadratowe i klamrowe\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false, by usunąć pozycję \\\"Zamknij pliki powyżej\\\" z menu kontekstowego plików w obszarze roboczym\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false, by usunąć pozycję \\\"Zamknij pliki poniżej\\\" z menu kontekstowego plików w obszarze roboczym\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false, by usunąć pozycję \\\"Zamknij inne\\\" z menu kontekstowego plików w obszarze roboczym\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Opcje automatycznego zamykania tagów\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"lista tagów, które nie powinny być automatycznie zamykane\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"zamykaj znaczniki po wpisaniu \\\">\\\" otwierającego tagu\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"zamykaj znaczniki po wpisaniu \\\"/\\\" zamykającego tagu\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"lista tagów, które wstawiają pustą linie (po wpisaniu otwierającego znacznika)\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true, by generować znaczniki zwijania kodu na podstawie poziomów wcięć\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true, by włączyć zwijanie kodu\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true, by wyświetlać znaczniki zwijania kodu po najechaniu kursora myszy na boczny panel\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Określa do ilu poziomów głębokości zostanie zastosowana funkcja \\\"Zwiń wszystko\\\"\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Minimalna liczba linii wymagana do pojawienia się znacznika zwijania kodu\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true, by zapamiętać zwinięte fragmenty kodu, gdy plik lub projekt zostanie zamknięty bądź ponownie otwarty\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"true, by zezwolić na zwijanie zaznaczonego fragmentu kodu\",\n    \"DESCRIPTION_DISABLED_DEFAULT_EXTENSIONS\"        : \"Lista rozszerzeń, które są domyślnie wyłączone\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Włącz/wyłącz podpowiedzi do atrybutów HTML\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Włącz/wyłącz podpowiedzi do właściwości CSS/LESS/SCSS\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Włącz/wyłącz podpowiedzi do kodu JavaScript\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Włącz/wyłącz wyświetlanie typów danych w podpowiedziach do kodu JavaScript\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Włącz/wyłącz podpowiedzi w pliku z ustawieniami\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Włącz/wyłącz podpowiedzi dla encji HTML\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Włącz/wyłącz podpowiedzi do kodu SVG\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Włącz/wyłącz podpowiedzi do tagów HTML\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Włącz/wyłącz podpowiedzi URL w kodzie HTML i CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Włącz/wyłącz funkcjonalność przeciągnij i upuść\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Włącz raportowanie o stanie programu\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Zezwól na automatyczne podświetlanie dopasowanych wyrazów w dokumencie\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Podświetl wszystkie wyrazy dopasowane według słowa z aktualnej pozycji kursora (bez zaznaczania)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Podświetl, tylko gdy zaznaczony jest cały wyraz\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true, by wstawić podpowiedź do kodu po naciśnięciu klawisza tab\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true, by nie pokazywać automatycznie podpowiedzi do kodu JS po wpisaniu znaku \\\".\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Obiekt z domyślnymi ustawieniami JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true, by zezwolić na wyrażenia przypisania\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true, by zezwolić na używanie operatorów bitowych\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true, jeśli standardowe zmienne (globalne) przeglądarki powinny być predefiniowane\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true, by zezwolić na Google Closure idioms\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true, by zezwolić na używanie instrukcji \\\"continue\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true, jeśli zmienne globalne dla CouchDB powinny być predefiniowane\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true, by zezwolić na instrukcje debugera\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true, jeśli zmienne globalne przeglądarki (użyteczne podczas projektowania) powinny być predefiniowane\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true, by zezwolić na użycie == i !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true, jeśli zmienne globalne standardu ES6 powinny być predefiniowane\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true, by zezwolić na używanie wyrażenia eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true, by zezwolić na niefiltrowaną instrukcje \\\"for ... in\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"określa szerokość wcięcia\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"maksymalna liczba raportowanych ostrzeżeń\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"maksymalna liczba znaków w jednej linii\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true, by zezwolić na definiowanie konstruktora nierozpoczynającego się od wielkiej litery\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true, jeśli zmienne globalne dla Node.js powinny być predefiniowane\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true, by zezwolić na użycie znaku \\\"_\\\" w zmiennych\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true, by zatrzymać analizę po wystąpieniu pierwszego błędu\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true, by zezwolić na ++ i --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true, by zezwolić na . i [^...]. w wyrażeniach regularnych\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true, jeśli zmienne globalne dla Rhino powinny być predefiniowane\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true, by zezwolić na ominięcie definicji `use strict`\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true, by zezwolić na używanie blokowanych metod ('...Sync')\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true, by zezwolić na dostęp do właściwości obiektu za pomocą nawiasów kwadratowych (subscript notation)\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true, by zezwolić na komentarze typu TODO\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true, by zezwolić na pozostawienie nieużywanych parametrów funkcji\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true, by zezwolić na użycie więcej niż jednej deklaracji var w funkcji\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true, by ignorować zasady białych znaków\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Ustawienia języka\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Dodatkowe mapowanie nazwy rozszerzenia z nazwą języka\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Dodatkowe mapowanie nazwy pliku z nazwą języka\",\n    \"DESCRIPTION_LINEWISE_COPY_CUT\"                  : \"Kopiuj lub wytnij całą linie, gdy nie został zaznaczony żaden fragment tekstu\",\n    \"DESCRIPTION_INPUT_STYLE\"                        : \"Wybiera sposób, w jaki CodeMirror obsługuje wejście oraz aktywność. Wartością może być textarea (domyślnie) lub contenteditable, która jest lepsza dla czytników ekranu (niestabilne)\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true, by włączyć inspekcje kodu (Code Inspection)\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Limit czasu (w milisekundach), którego nie mogą przekroczyć asynchroniczne lintery\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Lista linterów do uruchomienia w pierwszej kolejności\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true, by włączyć eksperymentalny podgląd na żywo\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true, by uruchomić tylko te moduły, które zostały określone w linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Maksymalna liczba pozycji w liście podpowiedzi do kodu\",\n    \"DESCRIPTION_PATH\"                               : \"Ścieżka do ustawień\",\n    \"DESCRIPTION_PROXY\"                              : \"Adres URL serwera proxy używanego do instalacji rozszerzeń\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true, by włączyć możliwość przewijania poza koniec dokumentu\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false, by wyłączyć wszystkie podpowiedzi do kodu\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Wyświetlaj migający kursor podczas zaznaczenia tekstu\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true, by wyświetlać numery linii obok kodu\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Automatycznie dodaj wcięcie, gdy zostanie utworzona nowa linia\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false, by wyłączyć soft tabs\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true, by sortować foldery w drzewie projektu\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Liczba spacji lub tabulatorów do sformatowania wcięcia w kodzie\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Numer portu, który powinien być używany przez wbudowany serwer podczas podglądu na żywo\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true, by podświetlać tło dla aktualnie edytowanej linii\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Określ rozmiar tabulatora (według liczby spacji)\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true, by używać tabulatorów zamiast spacji\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true, by generować kolory w formacie szesnastkowym (hex) używając wielkich liter w liniowym edytorze kolorów\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Zawijaj wiersze\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Lista plików, które zostały wykryte jako problematyczne dla modułu Tern\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Limit czasu, którego moduł Tern nie może przekroczyć podczas analizy plików\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true, by wyświetlać błędy aplikacji w pasku stanu\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true, by włączyć Quick View\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true, by wyświetlać podgląd dla grafiki, która nie posiada rozszerzenia w adresie URL\",\n    \"DESCRIPTION_THEME\"                              : \"Wybierz motyw dla {APP_NAME}\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true, by zezwolić na modyfikacje pasków przewijania przez motyw\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true, by zwijać (ukrywać) panel inspekcji kodu\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Rodzaj czcionki\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Rozmiar czcionki, np. 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"true, by włączyć wyszukiwanie oparte na NodeJS\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"true, by zezwolić na natychmiastowe wyszukiwanie\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Tylko dla MacOS: \\\"subpixel-antialiased\\\" włącz sub-pixel antialiasing lub \\\"antialiased\\\" dla antyaliasingu skali szarości\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false, by wyłączyć otwieranie pliku z ustawieniami w podzielonym widoku\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false, by wyłączyć otwieranie pliku z ustawieniami użytkownika w lewym/górnym panelu\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"true, by automatycznie włączyć tryb \\\"bez podziału\\\", gdy ostatni plik w panelu zostanie zamknięty (za pomocą przyciku w nagłówku panelu)\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Określ, kiedy powinny być wyświetlane przyciski zamknięcia i odwrócenia widoku w nagłówku panelu\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * This is a read-only file with the preferences supported\\n * by {APP_NAME}.\\n * Use this file as a reference to modify your preferences\\n * file \\\"brackets.json\\\" opened in the other pane.\\n * For more information on how to use preferences inside\\n * {APP_NAME}, refer to the web page at https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Domyślnie\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"true, by włączyć tryb \\\"bez przeszkadzania\\\" i ukryć wszystkie inne elementy UI w {APP_NAME}\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"true, by włączyć wcięcia w komentarzach\",\n    \"DESCRIPTION_RECENT_FILES_NAV\"                   : \"Włącz/wyłącz nawigację w ostatnich plikach\",\n    \"DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\"             : \"Port, na którym będzie uruchomiony serwer WebSocket podczas podglądu na żywo\"\n});\n\n/* Last translated for a01159ac2518fe1f27dfafb62d95a28c2958831f */"
  },
  {
    "path": "src/nls/pl/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"pl/Szybki Start\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_pl/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.pl\"\n});\n"
  },
  {
    "path": "src/nls/pt-br/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(erro {0})\",\n    \"NOT_FOUND_ERR\"                     : \"O arquivo não pôde ser encontrado.\",\n    \"NOT_READABLE_ERR\"                  : \"O arquivo não pôde ser lido.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Arquivos maiores que {0} MB não podem ser abertos no {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"O diretório de destino não pode ser modificado.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"As permissões não permitem que você faça modificações.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"O arquivo foi modificado fora do {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} atualmente suporta apenas arquivos de texto codificados em UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Arquivo ou pasta já existe.\",\n    \"FILE\"                              : \"arquivo\",\n    \"FILE_TITLE\"                        : \"Arquivo\",\n    \"DIRECTORY\"                         : \"diretório\",\n    \"DIRECTORY_TITLE\"                   : \"Diretório\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Nomes de diretórios\",\n    \"FILENAMES_LEDE\"                    : \"Nomes de arquivos\",\n    \"FILENAME\"                          : \"Nome de arquivo\",\n    \"DIRECTORY_NAME\"                    : \"Nome de diretório\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Erro ao carregar o projeto\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Ocorreu um erro ao mostrar o diálogo de abertura de arquivo. (erro {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Ocorreu um erro ao tentar carregar a pasta <span class='dialog-filename'>{0}</span>. (erro {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Ocorreu um erro ao ler o conteúdo da pasta <span class='dialog-filename'>{0}</span>. (erro {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Erro ao abrir arquivo\",\n    \"ERROR_OPENING_FILE\"                : \"Ocorreu um erro ao tentar abrir o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Ocorreu um erro ao tentar abrir os seguintes arquivos:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Erro ao recarregar as mudanças a partir do disco\",\n    \"ERROR_RELOADING_FILE\"              : \"Ocorreu um erro ao tentar recarregar o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Erro ao salvar arquivo\",\n    \"ERROR_SAVING_FILE\"                 : \"Ocorreu um erro ao tentar salvar o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Erro ao renomear arquivo\",\n    \"ERROR_RENAMING_FILE\"               : \"Ocorreu um erro ao tentar renomear o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Erro ao excluir arquivo\",\n    \"ERROR_DELETING_FILE\"               : \"Ocorreu um erro ao tentar excluir o arquivo <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"{0} inválido\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} não podem usar palavras reservadas do sistema, terminar com pontos (.) ou conter qualquer um dos seguintes caracteres: <code class='emphasized'>{1}</code>.\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Já existe um arquivo ou diretório como o nome <span class='dialog-filename'>{0}</span>.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Erro ao criar {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Ocorreu um erro ao tentar criar o {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Não é possível abrir uma pasta e outros arquivos ao mesmo tempo.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Erro ao ler mapa de teclas do usuário\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Seu arquivo de mapa de teclas não é um JSON válido. O arquivo será aberto para que você possa corrigir o formato.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Seu arquivo de mapa de teclas não é um arquivo de texto com codificação UTF-8 válida e não pode ser carregado\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Você não pode reatribuir atalhos para estes comandos: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Você não pode reatribuir estes atalhos: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Você está reatribuindo múltiplos atalhos para estes comandos: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Você tem múltiplos vínculos para estes atalhos: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Estes atalhos são inválidos: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Você está atribuindo atalhos para comandos não existentes: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Erro ao ler as preferências\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Seu arquivo de preferências não é um JSON válido. O arquivo será aberto para que você possa corrigir o formato. Você deverá reiniciar o {APP_NAME} para as alterações terem efeito.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"O arquivo de preferências de seu projeto não é um arquivo JSON válido. O arquivo será aberto para que você corrija sua formatação. Você precisará recarregar o projeto, para que as mudanças façam efeito.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Opa! O {APP_NAME} não funciona em navegadores ainda.\",\n    \"ERROR_IN_BROWSER\"                  : \"O {APP_NAME} é criado em HTML, mas no momento ele é executado como um aplicativo de desktop para que você possa usá-lo para editar arquivos locais. Por favor, use o shell da aplicação do repositório <b>github.com/adobe/brackets-shell</b> para executar {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Erro ao indexar arquivos\",\n    \"ERROR_MAX_FILES\"                   : \"Este projeto contém mais de 30.000 arquivos. Funcionalidades que operam em múltiplos arquivos podem ser desabilitadas ou se comportarem como se o projeto estivesse vazio. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Leia mais sobre como trabalhar com grandes projetos</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Erro ao abrir o navegador\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"O navegador Google Chrome não pôde ser encontrado. Por favor, verifique se ele está instalado.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Ocorreu um erro ao iniciar o navegador. (erro {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Erro no Live Preview\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Conectando-se ao navegador\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Para que o Live Preview conecte-se, o Chrome deve ser reiniciado com a opção de depuração remota ativada.<br /><br />Gostaria de abrir o Chrome novamente e permitir a depuração remota?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Não foi possível carregar a página de Live Preview\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Abra um arquivo HTML para iniciar Live Preview.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Para iniciar um live preview com um arquivo server-side, é preciso especificar uma URL Base para este projeto.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Erro ao iniciar o servidor HTTP para os arquivos do desenvolvimento em tempo real. Por favor, tente novamente.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Bem-vindo à Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"O Live Preview conecta o {APP_NAME} ao seu navegador. Ele abre uma prévia do seu arquivo HTML no navegador e atualiza a visualização em tempo real, enquanto você edita o código.<br /><br />Nesta versão inicial do {APP_NAME}, o Live Preview só funciona com o <strong>Google Chrome</strong> e atualiza em tempo real enquanto você edita <strong>arquivos CSS</strong>. Alterações em arquivos HTML ou JavaScript são automaticamente recarregados ao salvar.<br /><br />(Você só verá esta mensagem uma vez.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Para mais informações, veja <a href='{0}' title='{0}'>Solucionando erros de conexão com Live Development</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: Conectando\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: Inicializando\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Desconectar Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview (salve o arquivo para recarregar)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Preview (atualização interrompida devido a erro de sintaxe)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"O Live Preview foi cancelado pois as ferramentas de desenvolvedor do navegador foram abertas\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"O Live Preview foi cancelado pois a página foi fechada no navegador\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"O Live Preview foi cancelado pois o navegador foi para uma página que não pertence a este projeto atual\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"O Live Preview foi cancelado por uma razão desconhecida ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Salvar alterações\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Você quer salvar as alterações feitas no documento <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Você quer salvar as alterações feitas aos seguintes arquivos?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Alterações externas\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Confirmar exclusão\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Tem certeza que deseja excluir a pasta <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Arquivo excluído\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> foi modificado no disco.<br /><br />Deseja salvar o arquivo e sobrescrever essas alterações?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> foi modificado no disco, mas também tem alterações não salvas em {APP_NAME}.<br /><br />Qual versão você quer manter?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> foi excluído no disco, mas tem alterações não salvas em {APP_NAME}.<br /><br />Deseja manter suas alterações?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Concluído\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Cancelar\",\n    \"DONT_SAVE\"                         : \"Não salvar\",\n    \"SAVE\"                              : \"Salvar\",\n    \"SAVE_AS\"                           : \"Salvar como\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Sobrescrever\",\n    \"DELETE\"                            : \"Excluir\",\n    \"BUTTON_YES\"                        : \"Sim\",\n    \"BUTTON_NO\"                         : \"Não\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} de {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Nenhum resultado\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Localizar\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Substituir por\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Tudo\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Substituir\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Substituir\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Resultado seguinte\",\n    \"BUTTON_PREV_HINT\"                  : \"Resultado anterior\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Diferenciar maiúsculas/minúsculas\",\n    \"BUTTON_REGEXP_HINT\"                : \"Expressão regular\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Substituir sem desfazer\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Porque mais de {0} arquivos precisam ser alterados, {APP_NAME} irá modificar arquivos não abertos no disco.<br />Não será possível desfazer as modificações nestes arquivos.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Substituir sem desfazer\",\n\n    \"OPEN_FILE\"                         : \"Abrir arquivo\",\n    \"SAVE_FILE_AS\"                      : \"Salvar arquivo\",\n    \"CHOOSE_FOLDER\"                     : \"Escolha uma pasta\",\n\n    \"RELEASE_NOTES\"                     : \"Notas da versão\",\n    \"NO_UPDATE_TITLE\"                   : \"Você está atualizado!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Você está executando a versão mais recente do {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Substituir\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"por\",\n    \"FIND_TITLE_LABEL\"                  : \"Encontrados\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} em {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"em <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"no projeto\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtro exclui todos os arquivos {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"arquivo\",\n    \"FIND_IN_FILES_FILES\"               : \"arquivos\",\n    \"FIND_IN_FILES_MATCH\"               : \"resultado\",\n    \"FIND_IN_FILES_MATCHES\"             : \"resultados\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Mais de \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd + clique para expandir/comprimir tudo\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indexação de pesquisa instantânea\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Erro na substituição\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Os seguintes arquivos não foram modificados porque eles foram alterados antes da busca ou não puderam ser escritos.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Erro ao receber informações de atualização\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Houve um problema ao obter informações sobre a última atualização do servidor. Por favor, certifique-se de estar conectado à Internet e tente novamente.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Adicionar filtro\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Limpar filtro de arquivos\",\n    \"NO_FILE_FILTER\"                    : \"Nenhum filtro de arquivos\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Excetua {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Editar\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Editar filtro\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Exclui dos resultados os arquivos e pastas que correspondam a qualquer das strings, substrings ou <a href='{0}' title='{0}'>wildcards</a> abaixo. Insira cada string em uma linha separada.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Nome desta configuração de filtro (opcional)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"e outros {0}\",\n    \"FILTER_COUNTING_FILES\"             : \"Contando arquivos\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Permite {0} de {1} arquivos {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Permite todos os {0} arquivos {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Quick Edit não disponível para posição atual do cursor\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Quick Edit CSS: posicione o cursor no nome de uma única classe\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Quick Edit CSS: atributo class incompleto\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Quick Edit CSS: atributo id incompleto\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Quick Edit CSS: posicione cursor em tag, class ou id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Quick Edit Função Timing de CSS: sintaxe inválida\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Quick Edit JS: posicione cursor no nome de uma função\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Quick Docs não disponível para a posição atual do cursor\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Carregando\\u2026\",\n    \"UNTITLED\"          : \"Sem título\",\n    \"WORKING_FILES\"     : \"Arquivos abertos\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Início\",\n    \"BOTTOM\"            : \"Fim\",\n    \"LEFT\"              : \"Esquerda\",\n    \"RIGHT\"             : \"Direita\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Sem divisão\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Divisão vertical\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Divisão horizontal\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Divida o editor verticalmente ou horizontalmente\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configurar conjunto de trabalho\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Já está aberto\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"O arquivo já está aberto em outro painel. {APP_NAME} em breve irá suportar a abertura de um mesmo arquivo em mais de um painel. Até lá, o arquivo será mostrado no painel onde já está aberto.<br /><br />(Você irá ver esta mensagem apenas uma vez.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"Espaço\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Linha {0}, Coluna {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} coluna selecionada\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} colunas selecionadas\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} linha selecionada\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} linhas selecionadas\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} seleções\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Clique para alterar a indentação para espaços\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Clique para alterar a indentação para tabulação\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Clique para alterar o número de espaços usados ao indentar\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Clique para alterar a largura do caractere de tabulação\",\n    \"STATUSBAR_SPACES\"                      : \"Espaços:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tamanho da tabulação:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} linha\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} linhas\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extensões desativadas\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Clique para alternar o cursor entre os modos Insert (INS) e Overwrite (OVR)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Clique para alterar o tipo de arquivo\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Clique para abrir/fechar o painel de relatórios.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(padrão)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Definir como padrão para arquivos .{0}.\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"Problemas de {0}\",\n    \"SINGLE_ERROR\"                          : \"Um problema de {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} problemas de {0}\",\n    \"NO_ERRORS\"                             : \"Nenhum problema de {0} encontrado - bom trabalho!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Nenhum problema encontrado - bom trabalho!\",\n    \"LINT_DISABLED\"                         : \"A análise de código está desativada\",\n    \"NO_LINT_AVAILABLE\"                     : \"Nenhum analisador de código disponível para {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Nada para analisar\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} expirou após esperar durante {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} terminou com o erro: {1}\",\n\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Arquivo\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Novo\",\n    \"CMD_FILE_NEW\"                        : \"Novo arquivo\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nova pasta\",\n    \"CMD_FILE_OPEN\"                       : \"Abrir\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Adicionar ao conjunto de trabalho\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Abrir arquivos largados\",\n    \"CMD_OPEN_FOLDER\"                     : \"Abrir pasta\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Fechar\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Fechar todos\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Fechar lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Fechar outros\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Fechar outros acima\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Fechar outros abaixo\",\n    \"CMD_FILE_SAVE\"                       : \"Salvar\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Salvar todos\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Salvar como\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Preview\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Habilitar Live Preview experimental\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Forçar recarregamento do Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Configurações do projeto\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Renomear\",\n    \"CMD_FILE_DELETE\"                     : \"Excluir\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instalar extensão\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Gerenciador de extensões\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Atualizar árvore de arquivos\",\n    \"CMD_QUIT\"                            : \"Fechar\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Sair\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Editar\",\n    \"CMD_UNDO\"                            : \"Desfazer\",\n    \"CMD_REDO\"                            : \"Refazer\",\n    \"CMD_CUT\"                             : \"Recortar\",\n    \"CMD_COPY\"                            : \"Copiar\",\n    \"CMD_PASTE\"                           : \"Colar\",\n    \"CMD_SELECT_ALL\"                      : \"Selecionar tudo\",\n    \"CMD_SELECT_LINE\"                     : \"Selecionar linha\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Dividir seleção em linhas\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Adicionar cursor à linha seguinte\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Adicionar cursor à linha anterior\",\n    \"CMD_INDENT\"                          : \"Indentar\",\n    \"CMD_UNINDENT\"                        : \"Diminuir indentação\",\n    \"CMD_DUPLICATE\"                       : \"Duplicar\",\n    \"CMD_DELETE_LINES\"                    : \"Excluir linha\",\n    \"CMD_COMMENT\"                         : \"Alternar comentário de linha\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Alternar comentário de bloco\",\n    \"CMD_LINE_UP\"                         : \"Mover linha para cima\",\n    \"CMD_LINE_DOWN\"                       : \"Mover linha para baixo\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Abrir linha acima\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Abrir linha abaixo\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Fechar chaves automaticamente\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Mostrar dicas de código\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Localizar\",\n    \"CMD_FIND\"                            : \"Localizar\",\n    \"CMD_FIND_NEXT\"                       : \"Localizar próximo\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Localizar anterior\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Localizar tudo e selecionar\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Adicionar próximo resultado à seleção\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Pular e adicionar próximo resultado\",\n    \"CMD_FIND_IN_FILES\"                   : \"Localizar em arquivos\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Localizar em\\u2026\",\n    \"CMD_REPLACE\"                         : \"Substituir\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Substituir em arquivos\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Substituir em\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Visualizar\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Esconder barra lateral\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Mostrar barra lateral\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Aumentar tamanho da fonte\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Diminuir tamanho da fonte\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restaurar tamanho da fonte\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Rolar linha para cima\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Rolar linha para baixo\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Números de linha\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Destacar linha ativa\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Quebra automática de linha\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Destacar Live Preview\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Analisar arquivos ao salvar\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Ordenar por Data de Adição\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Ordenar por Nome\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Ordenar por Tipo\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Ordenação automática\",\n    \"CMD_THEMES\"                          : \"Temas\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navegar\",\n    \"CMD_QUICK_OPEN\"                      : \"Abertura rápida\",\n    \"CMD_GOTO_LINE\"                       : \"Ir para linha\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Encontrar definição\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Ir ao primeiro erro/aviso\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Edição rápida\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Documentação rápida\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Resultado anterior\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Resultado seguinte\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Nova regra\",\n    \"CMD_NEXT_DOC\"                        : \"Documento seguinte\",\n    \"CMD_PREV_DOC\"                        : \"Documento anterior\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Documento seguinte na lista\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Documento anterior na lista\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Mostrar na árvore de arquivos\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Mostrar no Explorer\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Mostrar no Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Mostrar no sistema operacional\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Ajuda\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Verificar atualizações\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Como usar o {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Ajuda do {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Sugira um recurso\",\n    \"CMD_RELEASE_NOTES\"                   : \"Notas da versão\",\n    \"CMD_GET_INVOLVED\"                    : \"Envolva-se\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Mostrar pasta de extensões\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Relatório de saúde do Brackets\",\n    \"CMD_HOMEPAGE\"                        : \"Página do {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} no Twitter\",\n    \"CMD_ABOUT\"                           : \"Sobre o {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Abrir arquivo de configurações\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Abrir mapa de teclas do usuário\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"versão experimental\",\n    \"RELEASE_BUILD\"                        : \"versão\",\n    \"DEVELOPMENT_BUILD\"                    : \"versão de desenvolvimento\",\n    \"RELOAD_FROM_DISK\"                     : \"Recarregar do disco\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Manter alterações no editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Fechar (não salvar)\",\n    \"RELAUNCH_CHROME\"                      : \"Abrir Chrome novamente\",\n    \"ABOUT\"                                : \"Sobre\",\n    \"CLOSE\"                                : \"Fechar\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"timestamp da versão: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Avisos, termos e condições de softwares de terceiros estão localizados em <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> e aqui incorporados por referência.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentação e código-fonte em <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Feito com \\u2764 e JavaScript por:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Várias pessoas (mas não estamos conseguindo carregar estes dados no momento).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs e logo gráfico MDN são licenciados sob a licença Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Há uma nova versão do {APP_NAME} disponível! Clique aqui para mais detalhes.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Atualização Disponível\",\n    \"UPDATE_MESSAGE\"                       : \"Ei, há uma nova versão do {APP_NAME} disponível. Aqui estão alguns dos novos recursos:\",\n    \"GET_IT_NOW\"                           : \"Obtenha agora!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Configurações do projeto para: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL base do Live Preview\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Para usar um servidor local, insira uma URL como http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"O protocolo {0} não é suportado pelo Live Preview&mdash;por favor, use http: ou https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"A URL base não pode conter parâmetros de busca como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"A URL base não pode conter hashes como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Caracteres especiais como '{0}' devem ser codificados para URL encoding.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Erro desconhecido ao parsear URL base\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Abra um arquivo enquanto este painel possui o foco</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Tema atual\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Usar barra de rolagens do tema\",\n    \"FONT_SIZE\"                            : \"Tamanho da fonte\",\n    \"FONT_FAMILY\"                          : \"Família da fonte\",\n    \"THEMES_SETTINGS\"                      : \"Configurações de temas\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Nova regra\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instalar\",\n    \"UPDATE\"                               : \"Atualizar\",\n    \"REMOVE\"                               : \"Remover\",\n    \"DISABLE\"                              : \"Desabilitar\",\n    \"ENABLE\"                               : \"Habilitar\",\n    \"OVERWRITE\"                            : \"Sobrescrever\",\n    \"CANT_REMOVE_DEV\"                      : \"Extensões na pasta \\\"dev\\\" devem ser excluídas manualmente.\",\n    \"CANT_UPDATE\"                          : \"A atualização não é compatível com esta versão do {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Extensões na pasta \\\"dev\\\" não podem ser atualizadas automaticamente.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instalar extensão\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Atualizar extensão\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL da extensão\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL do zip ou repositório GitHub da extensão\",\n    \"INSTALLING_FROM\"                      : \"Instalando extensão de {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalada com sucesso!\",\n    \"INSTALL_FAILED\"                       : \"Falha na instalação.\",\n    \"CANCELING_INSTALL\"                    : \"Cancelando\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Cancelar a instalação está demorando muito. Um erro interno deve ter ocorrido.\",\n    \"INSTALL_CANCELED\"                     : \"Instalação cancelada.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Ver descrição completa\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Ver descrição reduzida\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"O conteúdo baixado não é um arquivo zip válido.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"O arquivo package.json não é válido (o erro foi: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"O arquivo package.json não especifica um nome de pacote.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} é um nome de pacote inválido.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"O arquivo package.json não especifica uma versão de pacote.\",\n    \"INVALID_VERSION_NUMBER\"               : \"O número da versão do pacote ({0}) é inválido.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"A string de compatibilidade com o {APP_NAME} ({0}) é inválida.\",\n    \"DISALLOWED_WORDS\"                     : \"As palavras ({1}) não são permitidas no campo {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"A extensão não é compatível com esta versão do {APP_NAME}. Está instalada na sua pasta de extensões desativadas.\",\n    \"MISSING_MAIN\"                         : \"O pacote não tem um arquivo main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Instalar este pacote irá substituir uma extensão instalada anteriormente. Sobrescrever a exensão antiga?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Este pacote está na mesma versão que o instalado atualmente. Sobrescrever a instalação existente?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Este pacote está na versão {0}, que é mais antiga que a instalada atualmente ({1}). Sobrescrever a instalação existente?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Erro interno: ID de download já em uso.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Não foi possível conectar-se ao servidor.\",\n    \"BAD_HTTP_STATUS\"                      : \"Aquivo não encontrado no servidor (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Não foi possível salvar o download em um arquivo temporário.\",\n    \"ERROR_LOADING\"                        : \"A extensão encontrou um erro ao inicializar.\",\n    \"MALFORMED_URL\"                        : \"A URL é inválida. Por favor, verifique se você a inseriu corretamente.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"A URL precisa ser um endereço http ou https.\",\n    \"UNKNOWN_ERROR\"                        : \"Erro interno desconhecido.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Gerenciador de Extensões\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Não foi possível acessar o registro de extensões. Por favor,tente novamente mais tarde.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Arraste o .zip aqui ou\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Solte o .zip aqui ou\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Instalação/atualização cancelada devido aos seguintes erros:\",\n    \"INSTALL_FROM_URL\"                     : \"Instalar a partir de URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validando\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Data\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Esta extensão requer uma versão mais recente do {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Esta extensão atualmente só funciona com versões mais antigas do {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"A versão {0} desta extensão exige uma versão mais recente do {APP_NAME}. Mas você pode instalar a versão {1} mais antiga.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"A versão {0} desta extensão funciona apenas com versões mais antigas do {APP_NAME}. Mas você pode instalar a versão {1} mais recente.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Sem descrição\",\n    \"EXTENSION_MORE_INFO\"                  : \"Mais informações...\",\n    \"EXTENSION_ERROR\"                      : \"Erro na extensão\",\n    \"EXTENSION_KEYWORDS\"                   : \"Palavras-chave\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Traduzido para {0} idiomas, incluindo o seu\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Traduzido para {0} idiomas\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Essa extensão foi traduzida para os seguintes idiomas: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Instalada\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Esta atualização foi baixada e será instalada quando você sair do {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Pesquisar\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Mais\",\n    \"BROWSE_EXTENSIONS\"                    : \"Procurar extensões\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Remover extensão\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Não foi possível remover uma ou mais extensões: {0}. O {APP_NAME} será encerrado mesmo assim.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Atualizar extensão\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Não foi possível atualizar uma ou mais extensões: {0}. O {APP_NAME} será encerrado mesmo assim.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Desabilitar extensão\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Não é possível desabilitar uma ou mais extensões: {0}. {APP_NAME} será encerrado mesmo assim.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Marcada para remoção\",\n    \"UNDO_REMOVE\"                          : \"Desfazer\",\n    \"MARKED_FOR_UPDATE\"                    : \"Marcada para atualização\",\n    \"UNDO_UPDATE\"                          : \"Desfazer\",\n    \"MARKED_FOR_DISABLING\"                 : \"Marcada para desabilitação\",\n    \"UNDO_DISABLE\"                         : \"Desfazer\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Alterar extensões\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Para atualizar ou remover as extensões marcadas, o {APP_NAME} precisa ser recarregado. Você será solicitado a salvar suas alterações.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Remover extensões e recarregar\",\n    \"CHANGE_AND_RELOAD\"                    : \"Alterar extensões e recarregar\",\n    \"UPDATE_AND_RELOAD\"                    : \"Atualizar extensões e recarregar\",\n    \"DISABLE_AND_RELOAD\"                   : \"Desabilitar extensões e recarregar\",\n    \"PROCESSING_EXTENSIONS\"                : \"Processando alterações nas extensões\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Não foi possível remover a extensão {0} porque ela não estava instalada.\",\n    \"NO_EXTENSIONS\"                        : \"Nenhuma extensão instalada ainda.<br>Clique na aba Disponíveis acima para começar.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nenhuma extensão corresponde à sua pesquisa.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"NOTA: Estas extensões podem vir de diferentes autores e não do próprio {APP_NAME}. Extensões não são revisadas e tem prilégios locais totais. Tenha cuidado ao instalar extensões de fontes desconhecidas.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Instaladas\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Disponíveis\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Temas\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Atualizações\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Nenhum resultado.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Todas as correspondências foram ocultadas. Expanda os arquivos listados na direita para ver os resultados.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Nenhuma regra CSS corresponde à sua seleção.<br> Clique em \\\"Nova regra\\\" para criar uma.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Seu projeto não tem uma folha de estilos.<br>Crie uma para adicionar regras CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"maior\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pixels\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Depurar\",\n    \"ERRORS\"                                    : \"Erros\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Mostrar ferramentas do desenvolvedor\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Recarregar com extensões\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Recarregar sem extensões\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nova janela do {APP_NAME}\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Instalar atalhos da linha de comando\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Alterar idioma\\u2026\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Executar testes\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Mostrar dados de desempenho\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Habilitar depurador do Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Registrar estado do Node no console\",\n    \"CMD_RESTART_NODE\"                          : \"Reiniciar Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Mostrar erros na barra de status\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Abrir local do Brackets\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"Atalho de {APP_NAME} na linha de comando\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Um erro ocorreu enquanto um atalho de linha de comando estava sendo instalado. Por favor, tente <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>estas sugestões de resolução</a>.<br/><br/>Razão: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Não foi possível remover o link simbólico existente <code>/usr/local/bin/brackets</code> .\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Não foi possível criar o diretório <code>/usr/local/bin</code> .\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Não foi possível criar o link simbólico <code>/usr/local/bin/brackets</code> .\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Erro interno.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Atalhos de linha de comando não são suportados por este Sistema Operacional.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Sucesso! Agora você poderá usar de maneira confortável a linha de comando para o {APP_NAME} !! <code>brackets myFile.txt</code> para abrir um arquivo ou <code>brackets myFolder</code> para alternar em projetos. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Aprenda mais</a> como usar {APP_NAME} pela linha de comando.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Alterar idioma\",\n    \"LANGUAGE_MESSAGE\"                          : \"Idioma:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Reiniciar {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Cancelar\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Padrão do sistema\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Preferências do relatório de saúde\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"Relatório de saúde do {APP_NAME}\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Compartilhe informações anônimas sobre como eu uso o {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"Com a intenção de melhorar a sua experiência com {APP_NAME}, nós enviamos periodicamente alguns poucos dados estatísticos de forma <strong>anônima</strong> para a Adobe, sobre como você utiliza o {APP_NAME}. Essas informações nos ajudam a priorizar novas funcionalidades, encontrar bugs, e encontrar problemas de usabilidade.<br><br>Você pode ver e/ou escolher o que deseja compartilhar em <strong>Ajuda > Relatório de saúde Brackets</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Aprenda mais sobre a saúde de seu {APP_NAME}</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"Relatório de saúde do {APP_NAME}\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>Com a intenção de melhorar a sua experiência com {APP_NAME}, nós enviamos periodicamente alguns poucos dados estatísticos de forma <strong>anônima</strong> para a Adobe, sobre como você utiliza o {APP_NAME}. Essas informações nos ajudam a priorizar novas funcionalidades, encontrar bugs, e encontrar problemas de usabilidade. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Aprenda mais sobre a saúde de seu {APP_NAME}</a> e veja como isso beneficiará a comunidade {APP_NAME}, e isso tudo mantendo sua privacidade.</p><p>Abaixo está uma prévia de como será modelo de dados enviados em seu próximo relatório de saúde <em>se</em> ele for habilitado por você.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tempo\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progresso\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Move o ponto selecionado<br><kbd class='text'>Shift</kbd> Move dez unidades<br><kbd class='text'>Tab</kbd> Troca pontos\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Aumenta ou diminui passos<br><kbd>←</kbd><kbd>→</kbd> 'Start' ou 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"O valor antigo <code>{0}</code> não é válido, então a função exibida foi alterada para <code>{1}</code>. O documento será atualizado com a primeira edição.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Cor atual\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Cor original\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Formato RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Formato Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Formato HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (usada {1} vez)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (usada {1} vezes)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Pular para definição\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Mostrar dicas de parâmetro\",\n    \"NO_ARGUMENTS\"                              : \"<nenhum parâmetro>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problema de inferência de arquivo JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets enfrentou um problema ao processar: <span class='dialog-filename'>{0}</span>.<br><br>Este arquivo não será mais processado para dicas de código, definições ou edição rápida. Para reverter, abra <code>.brackets.json</code> em seu projeto e edite <code>jscodehints.detectedExclusions</code>.<br><br>Este provavelmente é um bug do Brackets. Se você pode fornecer uma cópia deste arquivo, por favor <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>registre um bug</a> com um link para o arquivo mencionado aqui.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Quick View ao passar o mouse\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Projetos Recentes\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Leia mais\",\n\n    //extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Dobrar Tudo\",\n    \"EXPAND_ALL\"                    : \"Expandir Tudo\",\n    \"COLLAPSE_CURRENT\"              : \"Dobrar Posição Atual\",\n    \"EXPAND_CURRENT\"                : \"Expandir Posição Atual\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"verdadeiro (true) para fechar chaves, colchetes e parênteses automaticamente\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"falso (false) para remover  \\\"Fechar outros acima\\\" do menu de contexto Arquivos abertos\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"falso (false) para remover \\\"Fechar outros abaixo\\\" do menu de contexto Arquivos abertos\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"falso (false) para remover \\\"Fechar outros\\\" do menu de contexto Arquivos abertos\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Definir opções de fechamento de tags\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"Uma matriz de tags não deve ser automaticamente fechada\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Fechar > quando a abertura da tag for digitada\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Fechar / quando o fechamento da tag for digitada\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"Um vetor de tags terá uma linha em branco entre as tags quando for aberta\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"verdadeiro (true) para sempre gerar marcadores de agrupamento quando o nível de identação mudar\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"verdadeiro (true) para habilitar o agrupamento de código\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"verdadeiro (true) para fazer que os marcadores de agrupamento de seção visíveis somente quando o cursor sai da área de edição pelo painel da esquerda\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limite de quantos níveis de Agrupar Todos pode agrupar\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Mínimo de linhas antes de um ícone agrupamento de seção surgir\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"verdadeiro (true) para lembrar o estado de uma seção agrupada caso você feche e reabra um arquivo ou projeto\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Habilitar/Desabilitar as sugestões de atributos HTML\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Habilitar/Desabilitar as sugestões de atributos CSS/LESS/SCSS\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Habilitar/Desabilitar as sugestões de atributos JavaScript\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Habilitar/Desabilitar as sugestões de preferências de código\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Habilitar/Desabilitar as sugestões de entidades HTML\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Habilitar/Desabilitar as sugestões de código SVG\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Habilitar/Desabilitar as sugestões de tags HTML\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Habilitar/Desabilitar as sugestões URL dentro de HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Habilitar/Desabilitar funcionalidade Drag & Drop/Arrastar & Soltar\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Habilitar rastreamento de dados de saúde\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Habilitar highlighting automático de palavras ao longo do documento\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Destaque todas strings correspondentes ao símbolo em que o cursor se encontra (não é necessária uma seleção)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Destaque somente quando um símbolo selecionado estiver completo\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"verdadeiro (true) para inserir a sugestão de código ao pressionar tab\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"verdadeiro (true) para não mostrar automaticamente dicas para JS quando  . for digitado\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"Um objeto com valores padrões para JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"verdadeiro (true) para permitir expressões de atribuição\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"verdadeiro (true) para permitir operadores bitwise\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"verdadeiro (true) se as funções variáveis globais do navegador devem ser predefinidos\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"verdadeiro (true) para permitir expressões idiomáticas do Google Closure\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"verdadeiro (true) para permitir a declaração  \\\"continue\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"verdadeiro (true) se as funções/variáveis globais do CouchDB devem ser predefinidos\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"verdadeiro (true) para permitir as declarações do debugger\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"verdadeiro (true) se as funções/variáveis globais de desenvolvimento no navegador devem ser predefinidos\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"verdadeiro (true) para permitir == e !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"verdadeiro (true) se as funções/variáveis globais ES6 devem ser predefinidos\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"verdadeiro (true) para permitir eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"verdadeiro (true) para permitir \\\"for ... in\\\" não filtrados\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Designar uma largura identação específica para o tab\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"Número máximo de advertências reportadas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"Número máximo de caracteres por linha\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"verdadeiro (true) para permitir construtores não capitalizados/sem maiúsculas\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"verdadeiro (true) se as funções/variáveis globais do NodeJS devem ser predefinidos\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"verdadeiro (true) para permitir sublinhados a frente dos identificadores\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"verdadeiro (true) para para no primeiro erro\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"verdadeiro (true) para permitir ++ e --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"verdadeiro (true) para permitir . e [^...]. em RegExp\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"verdadeiro (true) se as funções/variáveis globais Rhino devem ser predefinidos\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"verdadeiro (true) para permitir que não haja `use strict` pragma\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"verdadeiro (true) se os métodos de bloqueio ('...Sync') podem ser usados.\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"verdadeiro (true) para permitir subíndices ineficientes\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"verdadeiro (true) para permitir comentários TODO\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"verdadeiro (true) para permitir parâmetros nunca usados\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"verdadeiro (true) para permitir mais de 1 variável em uma função\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"verdadeiro (true) para ignorar as regras de espaçamento\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Configurações específicas de linguagem\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Mapeamentos adicionais de uma extensão arquivo ao nome da linguagem\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Mapeamentos adicionais de um nome de arquivo ao nome da linguagem\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"verdadeiro (true) para habilitar a inspeção do código\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"Tempo em milisegundos para a espera dos inspetores de código assíncronos\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Vetores de inspetores de código que executam primeiro\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"verdadeiro (true) para habilitar o Live Preview experimental\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"verdadeiro (true) para executar somente os provedores especificados pelo linting.prefer\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Máximo de sugestões de códigos exibidos ao mesmo tempo\",\n    \"DESCRIPTION_PATH\"                               : \"Configurações específicas para uma rota de arquivo\",\n    \"DESCRIPTION_PROXY\"                              : \"A URL do proxy utilizado para a instalação das extensões\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"verdadeiro (true) para habilitar o scrolling após o fim do arquivo\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"falso (false) para desabilitar todos as sugestões de código\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Mantenha o cursor visível quando houver uma seleção de texto\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"verdadeiro (true) para mostrar o número das linhas na borda \\\"gutter\\\" à esquerda do editor\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Identar automaticamente quando se criar um novo bloco\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"falso (false) para desabilitar o comportamento de \\\"soft tabs\\\"\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"verdadeiro (true) para ordenar os diretórios no topo da árvore de projetos\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Quantidade de espaços utilizados na identações baseada em espaços\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Número da porta do servidor que será utilizada para o Live Preview\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"verdadeiro (true) para ressaltar a linha atual que o cursor se encontra\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Quantidade de espaços utilizados pelo tab\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"verdadeiro (true) para usar tabs ao invés de espaços\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"verdadeiro (true) para gerar cores utilizando hexadecimais maiúsculas no editor de cores\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Ajustar linhas que ultrapassam a largura do editor\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"Uma lista de arquivos que foram detectados problemas fazem o Tern não funcionar corretamente\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Quantidade de vezes que o Tern deixará de tentar de compreender os arquivos\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"verdadeiro (true) para mostrar os erros na barra de status\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"verdadeiro (true) pra habilitar Visualização Rápida/Quick View\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"verdadeiro (true) para mostrar uma prévia de imagem para URLs sem extensões\",\n    \"DESCRIPTION_THEME\"                              : \"Selecionar um tema para {APP_NAME}\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"verdadeiro (true) para permitir barras de rolagem customizadas\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"verdadeiro (true) para agrupar painel de sugestões\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Alterar fonte\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Alterar o tamanho da fonte; e.g. 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"verdadeiro (true) para habilitar a busca baseada em nós/node\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"verdadeiro (true) para habilitar busca instantânea\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Somente para Mac: \\\"subpixel-antialiased\\\" para habilitar sub-pixel antialiasing ou \\\"antialiased\\\" para gray scale antialiasing / antialiasing com escala de cinza\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"falso (false) para desabilitar a abertura do arquivo de preferências em tela dividida\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"falso (false) para desabilitar a abertura do arquivo de preferências no topo do painel lateral esquerdo\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * Isso é um arquivo de somente leitura contendo as preferências suportadas\\n * pelo {APP_NAME}.\\n * Utilize este arquivo como referência para ajustar e modificar suas preferências no\\n * arquivo \\\"brackets.json\\\" aberto em outro painel.\\n * Para saber mais sobre como usar as preferências do\\n * {APP_NAME}, pode consultar a página web https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Padrão\"\n});\n/* Last translated for 0b949dd02b87866d54f38631715a4353a8f927e5 */\n"
  },
  {
    "path": "src/nls/pt-br/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"   : \"pt-br/Primeiros Passos\"\n});\n"
  },
  {
    "path": "src/nls/pt-pt/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(erro {0})\",\n    \"NOT_FOUND_ERR\"                     : \"O ficheiro não foi encontrado.\",\n    \"NOT_READABLE_ERR\"                  : \"O ficheiro não pode ser lido.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"A pasta de destino não pode ser modificado.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"As permissões não permitem modificações.\",\n    \"FILE_EXISTS_ERR\"                   : \"O ficheiro já existe.\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Erro ao carregar o projeto\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Ocorreu um erro na abertura do ficheiro. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Ocorreu um erro ao tentar carregar a pasta <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Ocorreu um erro ao ler o conteúdo da pasta <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Erro ao abrir ficheiro\",\n    \"ERROR_OPENING_FILE\"                : \"Ocorreu um erro ao tentar abrir o ficheiro <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Ocorreu um erro ao recarregar as mudanças a partir do disco\",\n    \"ERROR_RELOADING_FILE\"              : \"Ocorreu um erro ao tentar recarregar o ficheiro <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Erro ao guardar ficheiro\",\n    \"ERROR_SAVING_FILE\"                 : \"Ocorreu um erro ao tentar guardar o ficheiro <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Erro ao renomear ficheiro\",\n    \"ERROR_RENAMING_FILE\"               : \"Ocorreu um erro ao tentar renomear o ficheiro <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Nome do ficheiro inválido\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"O nome do ficheiro não pode conter os seguintes caracteres: {0}\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Erro ao criar ficheiro.\",\n    \"ERROR_CREATING_FILE\"               : \"Ocorreu um erro ao tentar criar o ficheiro <span class='dialog-filename'>{0}</span>. {1}\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! {APP_NAME} não funciona em navegadores ainda.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} é feito em HTML, e é executado como uma aplicação de desktop para que possa usá-lo para editar ficheiros locais. Por favor, use o shell da aplicação no <b>github.com/adobe/brackets-shell</b> repo para executar {APP_NAME}.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Erro a indexar Ficheiros\",\n    \"ERROR_MAX_FILES\"                   : \"O número máximo de ficheiros foi indexado. Acções que procurem ficheiros no index podem não funcionar corretamente.\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Erro ao abrir o navegador\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"O navegador Google Chrome não foi encontrado. Por favor, verifique se está instalado.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Ocorreu um erro ao iniciar o navegador. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Erro no Live Preview\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"A conectar ao navegador\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Para que a Live Preview funcione, o Google Chrome deve ser aberto com a opção de depuração(debug) remota ativada.<br /><br />Gostaria de reabrir Goggle Chrome e permitir a depuração remota?\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Abra um ficheiro HTML de modo a executar o Live Preview.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Bem-vindo ao Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live Preview liga o {APP_NAME} ao seu navegador. Ele faz uma pré-vizualização do seu ficheiro HTML no navegador, e cada vez que editar o código a pré-vizualização é automáticamente actualizada.<br /><br />Nesta versão inicial do {APP_NAME}, o Live Preview só funciona com a edição de <strong>ficheiros CSS</strong> e apenas com <strong>Google Chrome</strong>. Iremos implementá-lo para HTML e JavaScript em breve!<br /><br />(Só vai ver esta mensagem uma vez.)\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: A ligar\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: A iniciar\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Live Preview: Desligar\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview: Clique para desligar (Guarde o ficheiro para atualizar)\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Guardar alterações\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Você quer guardar as alterações feitas no ficheiro <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Você quer guardar as alterações para os seguintes ficheiros?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Mudanças externas\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> foi modificado no disco, mas também tem alterações não guardadas em {APP_NAME}.<br /><br />Que versão quer manter?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> foi apagado do disco, mas tem alterações não guardadas em {APP_NAME}.<br /><br />Quer manter as suas alterações?\",\n\n    // Find, Replace, Find in Files\n    \"BUTTON_YES\"                        : \"Sim\",\n    \"BUTTON_NO\"                         : \"Não\",\n\n    \"OPEN_FILE\"                         : \"Abrir ficheiro\",\n    \"CHOOSE_FOLDER\"                     : \"Escolha uma pasta\",\n\n    \"RELEASE_NOTES\"                     : \"Notas de lançamento\",\n    \"NO_UPDATE_TITLE\"                   : \"Está atualizado!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Está a executar a versão mais recente de {APP_NAME}.\",\n\n    \"FIND_IN_FILES_SCOPED\"              : \"em <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"no projeto\",\n    \"FIND_IN_FILES_FILE\"                : \"ficheiro\",\n    \"FIND_IN_FILES_FILES\"               : \"ficheiros\",\n    \"FIND_IN_FILES_MATCH\"               : \"resultado\",\n    \"FIND_IN_FILES_MATCHES\"             : \"resultado\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Mais que \",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"Ficheiro: <span class='dialog-filename'>{0}</span>\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Erro ao receber as atualizações\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Houve um problema a receber a atualização mais recente a partir do servidor. Por favor, verifique se você está conectado à Internet e tente novamente.\",\n\n    /**\n     * ProjectManager\n     */\n\n    \"UNTITLED\" : \"Sem título\",\n\n    /**\n     * Keyboard modifier names\n     */\n\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Linha {0}, Coluna {1}\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Mudar a indentação para espaços\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Mudar a indentação para tabulação\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Mudar o número de espaços usados ao indentar\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Mudar a largura do caractere de tabulação\",\n    \"STATUSBAR_SPACES\"                      : \"Espaços\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tamanho da tabulação\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Ficheiro\",\n    \"CMD_FILE_NEW\"                        : \"Novo\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nova pasta\",\n    \"CMD_FILE_OPEN\"                       : \"Abrir\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Adicionar ao conjunto de trabalho\",\n    \"CMD_OPEN_FOLDER\"                     : \"Abrir pasta\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Fechar\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Fechar tudo\",\n    \"CMD_FILE_SAVE\"                       : \"Guardar\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Guardar tudo\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Definições do projeto\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Renomear\",\n    \"CMD_QUIT\"                            : \"Sair\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Editar\",\n    \"CMD_SELECT_ALL\"                      : \"Selecionar tudo\",\n    \"CMD_SELECT_LINE\"                     : \"Selecionar linha\",\n    \"CMD_FIND\"                            : \"Encontrar\",\n    \"CMD_FIND_IN_FILES\"                   : \"Encontrar nos ficheiros\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Encontrar em\\u2026\",\n    \"CMD_FIND_NEXT\"                       : \"Encontrar próximo\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Encontrar anterior\",\n    \"CMD_REPLACE\"                         : \"Substituir\",\n    \"CMD_INDENT\"                          : \"Indentar\",\n    \"CMD_UNINDENT\"                        : \"Recuar indentação\",\n    \"CMD_DUPLICATE\"                       : \"Duplicar\",\n    \"CMD_DELETE_LINES\"                    : \"Apagar linha(s) selecionadas\",\n    \"CMD_COMMENT\"                         : \"Alternar comentário linhas\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Alternar comentário bloco\",\n    \"CMD_LINE_UP\"                         : \"Mover linha(s) para cima\",\n    \"CMD_LINE_DOWN\"                       : \"Mover linha(s) para baixo\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Ver\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Esconder barra lateral\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Mostrar barra lateral\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Aumentar tamanho da fonte\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Diminuir tamanho da fonte\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restaurar tamanho da fonte\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Ordenar por data adicionado\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Ordenar por nome\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Ordenar por tipo\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Ordenação automática\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navegar\",\n    \"CMD_QUICK_OPEN\"                      : \"Abertura rápida\",\n    \"CMD_GOTO_LINE\"                       : \"Ir para a linha\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Ir para definição\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Edição rápida\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Resultado anterior\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Resultado seguinte\",\n    \"CMD_NEXT_DOC\"                        : \"Ficheiro seguinte\",\n    \"CMD_PREV_DOC\"                        : \"Ficheiro anterior\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Mostrar na lista de pastas\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Ajuda\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Mostrar pasta de extensões\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Verificar atualizações\",\n    \"CMD_ABOUT\"                           : \"Sobre\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"Versão Experimental\",\n    \"OK\"                                   : \"OK\",\n    \"DONT_SAVE\"                            : \"Não guardar\",\n    \"SAVE\"                                 : \"Guardar\",\n    \"CANCEL\"                               : \"Cancelar\",\n    \"RELOAD_FROM_DISK\"                     : \"Atualizar a partir do disco\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Manter mudanças no editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Fechar (Não guardar)\",\n    \"RELAUNCH_CHROME\"                      : \"Re-abrir Chrome\",\n    \"ABOUT\"                                : \"Sobre\",\n    \"CLOSE\"                                : \"Fechar\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} versão experimental {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Avisos, termos e condições de softwares de terceiros estão localizados em <span class=\\\"non-clickble-link\\\">http://www.adobe.com/go/thirdparty/</span> e aqui incorporados por referência.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentação e fontes <span class=\\\"non-clickble-link\\\">https://github.com/adobe/brackets/</span>\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Nova versão de {APP_NAME} disponível! Clique aqui para mais detalhes.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Atualização disponível\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, {APP_NAME} {VERSION} disponível. Aqui estão alguns dos novos recursos:\",\n    \"GET_IT_NOW\"                           : \"Obter agora!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Definições do projeto para: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Live Preview URL base\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"(deixe em branco para url do ficheiro)\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"O {0} protocolo não é suportado pelo Live Preview&mdash;por favor usar http: or https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"O URL base não pode conter parametros de pesquisa como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"O URL base não pode conter cardinal como \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Caracteres especiais como '{0}' têm que ser %-codificados.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Erro desconhecido na análise do URL base\",\n\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                           : \"Debug\",\n    \"CMD_SHOW_DEV_TOOLS\"                   : \"Mostrar ferramentas de desenvolvimento\",\n    \"CMD_REFRESH_WINDOW\"                   : \"Recarregar o {APP_NAME}\",\n    \"CMD_NEW_BRACKETS_WINDOW\"              : \"Nova janela do {APP_NAME}\",\n    \"CMD_SWITCH_LANGUAGE\"                  : \"Mudar linguagem\",\n    \"CMD_RUN_UNIT_TESTS\"                   : \"Executar testes\",\n    \"CMD_SHOW_PERF_DATA\"                   : \"Mostrar dados de desempenho\",\n\n    \"LANGUAGE_TITLE\"                       : \"Mudar idioma\",\n    \"LANGUAGE_MESSAGE\"                     : \"Por favor, selecione o idioma desejado na lista abaixo:\",\n    \"LANGUAGE_SUBMIT\"                      : \"Recarregar {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                      : \"Cancelar\"\n});\n"
  },
  {
    "path": "src/nls/pt-pt/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"   : \"pt-pt/Primeiros Passos\"\n});\n"
  },
  {
    "path": "src/nls/ro/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(eroare {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Fișierul nu a fost găsit.\",\n    \"NOT_READABLE_ERR\"                  : \"Fișierul nu poate fi citit.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Fișierele mai mari de {0} MO nu pot fi deschise în {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Nu sunt permise modificări în directoriul curent.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Nu aveți destule drepturi pentru a face modificări.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Fișierul a fost modificat din afara la {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} suportă, pentru moment, doar fișierele textuale codificate cu UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Fișierul sau directoriul există deja.\",\n    \"FILE\"                              : \"fișier\",\n    \"FILE_TITLE\"                        : \"Fișier\",\n    \"DIRECTORY\"                         : \"directoriu\",\n    \"DIRECTORY_TITLE\"                   : \"Directoriu\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Denumirile directoriilor\",\n    \"FILENAMES_LEDE\"                    : \"Denumirile fișierelor\",\n    \"FILENAME\"                          : \"nume fișier\",\n    \"DIRECTORY_NAME\"                    : \"nume directoriu\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Eroare la încărcarea proiectului\",\n    \"OPEN_DIALOG_ERROR\"                 : \"S-a produs o eroare la afișarea dialogului de deschidere a fișierelor. (eroare {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"S-a produs o eroare la încărcarea directoriului <span class='dialog-filename'>{0}</span>. (eroare {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"S-a produs o eroare la citirea conținutului directoriului <span class='dialog-filename'>{0}</span>. (eroare {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Eroare la deschiderea fișierului\",\n    \"ERROR_OPENING_FILE\"                : \"S-a produs o eroare la încercarea de a deschide fișierul <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"S-a produs o eroare la încercarea de a deschide următoarele fișiere:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Eroare la reîncărcarea schimbărilor de pe disc\",\n    \"ERROR_RELOADING_FILE\"              : \"S-a produs o eroare la încercarea reîncărcării fișierului <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Eroare la salvarea fișierului\",\n    \"ERROR_SAVING_FILE\"                 : \"S-a produs o eroare la încercarea de a salva fișierul <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Eroare la redenumirea fișierului\",\n    \"ERROR_RENAMING_FILE\"               : \"S-a produs o eroare la încercarea de a redenumi fișierul <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Eroare la ștergerea fișierului\",\n    \"ERROR_DELETING_FILE\"               : \"S-a produs o eroare la încercarea de a șterge fișierul <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Numele {0} e invalid\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Numele fișierului nu poate conține următoarele caractere: {0} sau să fie un cuvânt rezervat de sistemul de operare.\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Un fișier sau un directoriu cu numele <span class='dialog-filename'>{0}</span> există deja.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Eroare la crearea fișierului {0}\",\n    \"ERROR_CREATING_FILE\"               : \"S-a produs o eroare la încercarea de a crea fișierul {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Imposibil de a deschide un directoriu dacă sunt fișiere deschise.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Eroare la citirea tastelor definite de utilizator\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Conținutul fișierului pentru maparea tastelor nu e un JSON valid. Fișierul va fi deschis pentru a corecta conținutul lui.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Fișierul pentru maparea tastelor nu poate fi încărcat deoarece nu este codificat în formatul UTF-8.\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Tastele rapide pentru următoarele comenzi nu pot fi realocate: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Imposibil de realocat următoarele taste rapide: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Au fost realocate prea multe taste rapide pentru următoarele comenzi: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Au fost realocate mai multe taste rapide pentru următoarele comenzi: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Următoarele taste rapide nu sunt valide: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Au fost alocate taste rapide pentru comenzi inexistente: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Eroare la citirea preferințelor\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Fișierul cu preferințe nu e un JSON valid. Fișierul va fi deschis pentru a corecta formatul. Pentru ca schimbările să aibă loc {APP_NAME} va trebui relansat.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! {APP_NAME} nu a fost lansat pentru browser încă.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} e construit în HTML, dar acum rulează ca o aplicație desktop și poate fi folosit pentru a edita fișierele locale. Lansați interpretatorul de comenzi al aplicației din repozitoriul <b>github.com/adobe/brackets-shell</b> pentru a rula {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Eroare la indexarea fișierelor\",\n    \"ERROR_MAX_FILES\"                   : \"Ați atins numărul maxim de fișiere indexate. Acțiunile pentru căutarea fișierelor în index ar putea lucra incorect.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Eroare la lansarea browser-ului\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Browser-ul Google Chrome nu a putut fi găsit. Asigurați-vă că el este instalat.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"S-a produs o eroare la lansarea browser-ului. (eroare {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Eroare la lansarea Live Preview\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Conectare la browser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Pentru a lansa Live Preview Google Chrome trebuie să fie relansat cu opțiunea de depanarea la distanță activată.<br /><br />Doriți ca Google Chrome să fie relansat cu opțiunea de depanare la distanță activată?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Imposibil de a încărca pagina Live Development\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Deschideți un fișier HTML sau asigurați-vă că există un fișier index.html în proiect pentru a lansa Live Preview.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Pentru a lansa Live Preview cu un fișier server-side, e necesar de a specifica un URL de bază pentru acest proiect.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Eroare la lansarea serverului HTTP pentru editarea în direct a fișierelor. Mai încercați o dată.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Bun venit la Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live Preview conectează {APP_NAME} la browser-ul tău. El lansează o previzualizare a fișierului HTML, apoi, imediat, la editare codului actualizează previzualizarea.<br /><br />În această versiune timpurie {APP_NAME}, Live Preview funcționează doar cu <strong>Google Chrome</strong> și actualizează imediat <strong>fișierele CSS sau HTML</strong>. Schimbările în fișierele JavaScript sunt reîncărcate automat la salvare.<br /><br />(Veți vedea acest mesaj o singură dată.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Pentru mai multe informații, vezi <a href='{0}' title='{0}'>Depanarea erorilor de conexiune în Live Development</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: Conectare\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: Inițializare\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Deconectare Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview (salvează fișierul pentru actualizare)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Preview (nu poate fi reînnoit din cauza unei erori de sintaxă)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Live Preview a fost revocat din cauza că în browser au fost deschise uneltele pentru dezvoltatori\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Live Preview a fost revocat din cauza că pagina a fost închisă în browser\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Live Preview a fost revocat din cauza că browser-ul a navigat spre o pagină care nu face parte din proiectul curent\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Live Preview a fost revocat dintr-un motiv necunoscut ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Salvare modificări\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Doriți să salvați modificările făcute în documentul <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Doriți să salvați modificările din următoarele fișiere?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Modificări externe\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Confirmare ștergere dosar\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Sunteți sigur că doriți să ștergeți dosarul <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Fișier șters\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> a fost modificat pe disc.<br /><br />Doriți să salvați fișierul și să suprascrieți aceste modificări?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> a fost modificat pe disc, dar, deasemenea, are modificări nesalvate în {APP_NAME}.<br /><br />Care versiune doriți să o păstrați?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> a fost șters de pe disc, dar are modificări nesalvate în {APP_NAME}.<br /><br />Doriți să păstrați modificările?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Terminat\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Revocare\",\n    \"DONT_SAVE\"                         : \"Nu salva\",\n    \"SAVE\"                              : \"Salvează\",\n    \"SAVE_AS\"                           : \"Salvează ca\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Suprascrie\",\n    \"DELETE\"                            : \"Șterge\",\n    \"BUTTON_YES\"                        : \"Da\",\n    \"BUTTON_NO\"                         : \"Nu\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} din {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Niciun rezultat\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Găsește\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Înlocuiește cu\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Tot\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Înlocuiește\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Înlocuiește\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Potrivirea următoare\",\n    \"BUTTON_PREV_HINT\"                  : \"Potrivirea precedentă\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Potrivire litere\",\n    \"BUTTON_REGEXP_HINT\"                : \"Expresie regulată\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Înlocuiește fără întoarcere\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Dat fiind faptul că mai mult de {0} fișiere trebuie să fie modificate, {APP_NAME} va modifica fișierele non deschise pe disc.<br />Înlocuirile în aceste fișiere nu vor putea fi anulate.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Înlocuiește fără întoarcere\",\n\n    \"OPEN_FILE\"                         : \"Deschide un fișier\",\n    \"SAVE_FILE_AS\"                      : \"Salvează fișierul\",\n    \"CHOOSE_FOLDER\"                     : \"Alege un dosar\",\n\n    \"RELEASE_NOTES\"                     : \"Notele ediției\",\n    \"NO_UPDATE_TITLE\"                   : \"Aplicația e la zi!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Utilizați ultima versiune {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Înlocuiește\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"cu\",\n    \"FIND_TITLE_LABEL\"                  : \"S-a găsit\",\n    \"FIND_TITLE_SUMMARY\"                : \": {0} {1} {2} în {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"în <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"în proiect\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filtrul exclude toate {0} fișiere\",\n    \"FIND_IN_FILES_FILE\"                : \"fișier\",\n    \"FIND_IN_FILES_FILES\"               : \"fișiere\",\n    \"FIND_IN_FILES_MATCH\"               : \"potrivire\",\n    \"FIND_IN_FILES_MATCHES\"             : \"potriviri\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Peste \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We shoudl use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd clic pentru a extinde/restrânge toate\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Erori la înlocuire\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Următoarele fișiere nu au fost modificate pentru că acestea au fost modificate după căutare sau nu pot fi rescrise.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Eroare la primirea informațiilor despre actualizare\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"S-a produs o eroare la primirea informațiilor despre actualizare de la server. Asigurați-vă că sunteți conectat la internet și să mai încercați o dată.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Set nou de excludere\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Nu exclude fișierele\",\n    \"NO_FILE_FILTER\"                    : \"Niciun fișier exclus\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Exclude {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Editează\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Editare set de excludere\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Exclude fișierele și directoriile care se potrivesc șirurilor / subșirurilor sau <a href='{0}' title='{0}'>metacaracterelor</a> următoare. Introduceți fiecare șir într-o linie nouă.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Denumește acest set de excludere (opțional)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"și {0} încă\",\n    \"FILTER_COUNTING_FILES\"             : \"Numărul fișierelor\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Permite {0} din {1} fișiere {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Permite toate {0} fișiere {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Funcția de editare rapidă nu e disponibilă pe poziția curentă a cursorului\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Editare rapidă CSS: plasează cursorul pe un singur nume de clasă\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Editare rapidă CSS: atributul \\\"class\\\" e incomplet\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Editare rapidă CSS: atributul \\\"id\\\" e incomplet\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Editare rapidă CSS: plasează cursorul în tag, class, sau id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Funcția de ediare rapidă a întîrzierii CSS: sintaxă invalidă\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Editare rapidă JS: plasează cursorul în numele funcției\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Funcția de documentare rapidă nu e disponibilă pe poziția curentă a cursorului\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Încărcare\\u2026\",\n    \"UNTITLED\"          : \"Neintitulat\",\n    \"WORKING_FILES\"     : \"Fișierele active\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Sus\",\n    \"BOTTOM\"            : \"Jos\",\n    \"LEFT\"              : \"Stânga\",\n    \"RIGHT\"             : \"Dreapta\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Fără divizare\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Divizare verticală\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Divizare orizontală\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Divizare verticală și orizontală\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configurează setul de lucru\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Deja deschis\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Fișierul este deja deschis în alt panou. {APP_NAME} va suporta în curând dechiderea unui fișier în mai multe panouri. Până atunci, fișierul va fi arătat doar în panoul în care a fost deschis.<br /><br />(Acest mesaj va fi afișat o singură dată.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Spațiu\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Rândul {0}, Coloana {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 {0} coloană selectată\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 {0} coloane selectate\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 {0} rând selectat\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 {0} rânduri selectate\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} selecții\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Comută la indentarea prin spații\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Comută la indentarea prin tab-uri\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Modifica numărul de spații folosit pentru indentare\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Modifica lățimea caracterului tab\",\n    \"STATUSBAR_SPACES\"                      : \"Spații:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab-uri:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} rând\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} rânduri\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extensii dezactivate\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"RSC\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Clic pentru a modifica cursorul între modul de Inserare(INS) și modul de Rescriere(RSC)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Clic pentru a modifica tipul fișierului\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Clic pentru a arăta / ascunde panoul de rapoarte.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(implicit)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Setează ca implicit pentru fișierele .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} probleme\",\n    \"SINGLE_ERROR\"                          : \"1 eroare {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} erori {0}\",\n    \"NO_ERRORS\"                             : \"Nicio eroare {0} - bine lucrat!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Nicio eroare găsită - bine lucrat!\",\n    \"LINT_DISABLED\"                         : \"Verificarea codului e dezactivată\",\n    \"NO_LINT_AVAILABLE\"                     : \"Verificarea codului e indisponibilă pentru {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Nimic de verificat\",\n    \"LINTER_TIMED_OUT\"                      : \"Timp de așteptare depășit pentru {0} după o întârziere de {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} finisat cu eroarea: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Fișier\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nou\",\n    \"CMD_FILE_NEW\"                        : \"Fișier nou\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Dosar nou\",\n    \"CMD_FILE_OPEN\"                       : \"Deschide\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Adaugă la setul de lucru și deschide\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Deschide fișierele depuse\",\n    \"CMD_OPEN_FOLDER\"                     : \"Deshide un dosar\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Închide\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Închide tot\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Închide lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Închide celelalte\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Închide cele de mai sus\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Închide cele de mai jos\",\n    \"CMD_FILE_SAVE\"                       : \"Salvează\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Salvează tot\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Salvează ca\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Previzualizare interactivă\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Forțează relansarea previzualizării interactive\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Setările proiectului\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Redenumește\",\n    \"CMD_FILE_DELETE\"                     : \"Șterge\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Instalează extensia\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Managerul de extensii\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Actualizează arborele de fișiere\",\n    \"CMD_QUIT\"                            : \"Ieșire\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Ieșire\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Editare\",\n    \"CMD_UNDO\"                            : \"Anulează\",\n    \"CMD_REDO\"                            : \"Refă\",\n    \"CMD_CUT\"                             : \"Taie\",\n    \"CMD_COPY\"                            : \"Copiază\",\n    \"CMD_PASTE\"                           : \"Lipește\",\n    \"CMD_SELECT_ALL\"                      : \"Selectează tot\",\n    \"CMD_SELECT_LINE\"                     : \"Selectează rând\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Împarte selecția în linii\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Adaugă cursor la linia următoare\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Adaugă cursor la linia precedentă\",\n    \"CMD_INDENT\"                          : \"Indentează\",\n    \"CMD_UNINDENT\"                        : \"Deindentează\",\n    \"CMD_DUPLICATE\"                       : \"Dublează\",\n    \"CMD_DELETE_LINES\"                    : \"Șterge rândurile\",\n    \"CMD_COMMENT\"                         : \"Comută comentariul pentru rând\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Comută comentariul pentru bloc\",\n    \"CMD_LINE_UP\"                         : \"Mută pe rândul de mai sus\",\n    \"CMD_LINE_DOWN\"                       : \"Mută pe rândul de mai jos\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Deschide rândul de mai sus\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Deschide rândul de mai jos\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Închide automat perechile de caractere\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Arată sugestiile de cod\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Căutare\",\n    \"CMD_FIND\"                            : \"Caută\",\n    \"CMD_FIND_NEXT\"                       : \"Caută următorul\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Caută precedentul\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Caută tot și selectează\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Adaugă următoarea potrivire la selecție\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Omite și adaugă următoarea potrivire\",\n    \"CMD_FIND_IN_FILES\"                   : \"Caută în fișiere\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Caută în\\u2026\",\n    \"CMD_REPLACE\"                         : \"Înlocuiește\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Înlocuiește în fișiere\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Înlocuiește în\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Vizualizare\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Ascunde bara laterală\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Arată bara laterală\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Mărește dimensiunea font-ului\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Micșorează dimensiunea font-ului\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Resetează dimensiunea font-ului\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Rulează o linie în sus\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Rulează o linie în jos\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Numerotează rândurile\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Evidențiază rândul activ\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Potrivește cuvintele în rând\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Evidențiere Live Preview\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Verifică codul din fișiere la salvare\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sortare după adăugare\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sortare după nume\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sortare după tip\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Sortare automată\",\n    \"CMD_THEMES\"                          : \"Teme\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigare\",\n    \"CMD_QUICK_OPEN\"                      : \"Deshidere rapidă\",\n    \"CMD_GOTO_LINE\"                       : \"Mergi la rândul\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Acces rapid la definiție\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Mergi la prima eroare/primul avertisment\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Editare rapidă\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Documentație rapidă\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Potrivirea precedentă\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Potrivirea următoare\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Regulă nouă\",\n    \"CMD_NEXT_DOC\"                        : \"Documentul următor\",\n    \"CMD_PREV_DOC\"                        : \"Documentul precedent\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Arată în arborele de fișiere\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Arată în Explorer\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Arată în Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Arată în sistemul de operare\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Ajutor\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Verifică pentru actualizări\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Cum să folosești {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Suport {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Sugerează o funcționalitate\",\n    \"CMD_RELEASE_NOTES\"                   : \"Notele ediției\",\n    \"CMD_GET_INVOLVED\"                    : \"Participă la proiect\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Deschide dosarul cu extensii\",\n    \"CMD_HOMEPAGE\"                        : \"Pagina de start {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} în Twitter\",\n    \"CMD_ABOUT\"                           : \"Despre {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Deschide fișierul cu preferințe\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Deschide maparea tastelor\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"versiune experimentală\",\n    \"RELEASE_BUILD\"                        : \"versiune\",\n    \"DEVELOPMENT_BUILD\"                    : \"versiune în dezvoltare\",\n    \"RELOAD_FROM_DISK\"                     : \"Reîncarcă de pe disc\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Păstrează modificările în editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Închide (Nu salva)\",\n    \"RELAUNCH_CHROME\"                      : \"Relansează Google Chrome\",\n    \"ABOUT\"                                : \"Despre\",\n    \"CLOSE\"                                : \"Închide\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"amprenta de timp a versiunii: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Notițele, termenii și condițiile ce țin de părțile software terțe sunt localizate la <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> și sunt adăugate aici ca referință.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentația și sursa se găsesc la <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Creat cu \\u2764 și JavaScript de:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"O mulțime de oameni (dar avem dificultăți la încărcarea datelor despre ei acum).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs și logotipul MDN sunt licențiați sub licența Creative Commons Attribution, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Există o versiune nouă {APP_NAME} disponibilă! Clic aici pentru detalii.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Înnoire disponibilă\",\n    \"UPDATE_MESSAGE\"                       : \"Hei, o nouă versiune {APP_NAME} disponibilă. Aici sunt o parte din noile posibilități:\",\n    \"GET_IT_NOW\"                           : \"Descarcă acum!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Setările pentru proiectul \\\"{0}\\\"\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL-ul de bază pentru Live Preview\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Server local, exemplu: \\\"http://localhost:8000/\\\"\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Protocolul {0} nu e suportat de Live Preview &mdash; folosiți HTTP sau HTTPS.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL-ul de bază nu poate conține parametri pentru căutare ca \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL-ul de bază nu poate conține caracterul diez ca \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Caracterele speciale ca '{0}' trebuie să fie codificate cu %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Eroare necunoscută la analiza URL-ului de bază\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Selectați un fișier cât această vedere e activă</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Tema curentă\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Folosește barele de derulare ale temei\",\n    \"FONT_SIZE\"                            : \"Mărimea fontului\",\n    \"FONT_FAMILY\"                          : \"Familia fontului\",\n    \"THEMES_SETTINGS\"                      : \"Setările temei\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Regulă nouă\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Instalare\",\n    \"UPDATE\"                               : \"Actualizare\",\n    \"REMOVE\"                               : \"Dezinstalare\",\n    \"OVERWRITE\"                            : \"Rescriere\",\n    \"CANT_REMOVE_DEV\"                      : \"Extensiile din dosarul \\\"dev\\\" trebuie să fie șterse manual.\",\n    \"CANT_UPDATE\"                          : \"Înnoirea nu e compatibilă cu versiunea curentă {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Extensiile din mapa \\\"dev\\\" nu pot fi înnoite automat.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Instalare extensie\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Actualizare extensie\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL-ul extensiei\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL-ul arhivei zip a extensiei sau a repozitoriului GitHub\",\n    \"INSTALLING_FROM\"                      : \"Instalarea extensiei din {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Instalare cu succes!\",\n    \"INSTALL_FAILED\"                       : \"Instalarea a eșuat.\",\n    \"CANCELING_INSTALL\"                    : \"În curs de revocare\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Revocarea instalării durează prea mult. E posibil ca o eroare internă să fi avut loc.\",\n    \"INSTALL_CANCELED\"                     : \"Instalarea a fost revocată.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Afișare descriere completă\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Afișare descriere parțială\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Conținutul descărcat nu e un fișier zip valid.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Fișierul \\\"package.json\\\" nu e valid (eroarea e: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Fișierul \\\"package.json\\\" nu specifică un nume pentru pachet.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} e un nume invalid pentru pachet.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Fișierul \\\"package.json\\\" nu specifică o versiune pentru pachet.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Versiunea pachetului ({0}) e invalidă.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Valoarea parametrului de compatibilitate {APP_NAME} ({0}) e invalid.\",\n    \"DISALLOWED_WORDS\"                     : \"Cuvintele ({1}) nu sunt permise în câmpul {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Extensia nu e compatibilă cu versiuea curentă {APP_NAME}. E instalată în dosarul cu extensii dezactivate.\",\n    \"MISSING_MAIN\"                         : \"Pachetul nu are fișierul \\\"main.js.\\\"\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Instalând acest pachet veți rescrie o extensie instalată anterior. Doriți să rescrieți extensia?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Acest pachet are aceeași versiune ca și extensia instalată curent. Doriți să rescrieți extensia?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Acest pachet are versiunea {0} care e mai veche decât vesiunea instalată curent ({1}). Doriți să rescrieți extensia?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Eroare internă: identificatorul descărcării e utilizat deja.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Imposibil de conectat la server.\",\n    \"BAD_HTTP_STATUS\"                      : \"Fișierul nu a fost găsit pe server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Imposibil de salvat descărcarea într-un fișier temporar.\",\n    \"ERROR_LOADING\"                        : \"Extensia a întîlnit o eroare la lansare.\",\n    \"MALFORMED_URL\"                        : \"URL-ul e invalid. Verificați corectitudinea URL-ului introdus.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL-ul trebuie să fie un URL HTTP sau HTTPS.\",\n    \"UNKNOWN_ERROR\"                        : \"Eroare internă necunoscută.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Manager de extensii\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"La moment este imposibil de accesat registrul extensiilor. Încercați mai târziu.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Glisați .zip aici sau\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Plasați .zip pentru a instala\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Instalare/Actualizare întreruptă din cauza următoarelor erori:\",\n    \"INSTALL_FROM_URL\"                     : \"Instalare din URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"În curs de validare\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Dată\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Această extensie necesită o vesiune mai nouă {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Această extensie funcționează doar cu versiunile mai vechi {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Versiunea {0} a acestei extensii necesită o vesiune mai nouă {APP_NAME}. Dar puteți instala versiunea {1} a extensiei.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Versiunea {0} a acestei extensii funcționează doar cu versiunile vechi {APP_NAME}. Dar puteți instala versiunea {1} a extensiei.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Nicio descriere\",\n    \"EXTENSION_MORE_INFO\"                  : \"Mai multe informații...\",\n    \"EXTENSION_ERROR\"                      : \"Eroare de extensie\",\n    \"EXTENSION_KEYWORDS\"                   : \"Cuvinte cheie\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Tradus în {0} limbi, incluzând Româna\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Tradus în {0} limbi\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Această extensie a fost tradusă în următoarele limbi: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Instalat\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Actualizarea extensiei curente a fost descărcată și va fi instalată când veți ieși din {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Caută\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Mai mult\",\n    \"BROWSE_EXTENSIONS\"                    : \"Parcurge extensiile\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Șterge extensia\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Imposibil de șters una sau mai multe extensii: {0}. {APP_NAME} va fi închis oricum.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Actualizează extensia\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Imposibil de actualizat una sau mai multe extensii: {0}. {APP_NAME} va fi închis oricum.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Marcată pentru ștergere\",\n    \"UNDO_REMOVE\"                          : \"Anulează\",\n    \"MARKED_FOR_UPDATE\"                    : \"Marcată pentru actualizare\",\n    \"UNDO_UPDATE\"                          : \"Refă\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Modificare extensii\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Pentru a actualiza sau șterge extensiile marcate {APP_NAME} trebuie relansat. Veți fi solicitat pentru a salva schimbările.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Șterge extensiile și repornește\",\n    \"CHANGE_AND_RELOAD\"                    : \"Modifică extensiile și repornește\",\n    \"UPDATE_AND_RELOAD\"                    : \"Actualizează extensiile și repornește\",\n    \"PROCESSING_EXTENSIONS\"                : \"Procesează modificările extensiilor\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Extensia {0} nu a putut fi ștearsă pentru că nu e instalată.\",\n    \"NO_EXTENSIONS\"                        : \"Nicio extensie instalată.<br>Clic pe fila extensiilor disponibile pentru a instala una.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nicio extensie nu se potrivește căutării.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Fiți precaut la instalarea extensiilor din surse necunoscute.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Instalate\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Disponibile\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Teme\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Actualizări\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Nicio potrivire disponibilă.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Toate potrivirile sunt reduse. Extinde fișierele afișate pe dreapta pentru a vedea potrivirile.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Nu există nicio regulă CSS care să se potrivească selecției.<br>Clic pe \\\"Regulă nouă\\\" pentru a crea una.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Proiectul nu conține nicio foaie de stiluri.<br>Creați una pentru a adăuga reguli CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"maxim\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"pixeli\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Depanare\",\n    \"ERRORS\"                                    : \"Erori\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Arată uneltele pentru dezvoltatori\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Reîncarcă {APP_NAME}\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Reîncarcă fără extensii\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Deschide o fereastră nouă {APP_NAME}\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Modifică limba\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Rulează testele\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Arată datele despre performanță\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Activează opțiunea de depanare pentru Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Înregistrează statutul Node în consolă\",\n    \"CMD_RESTART_NODE\"                          : \"Repornește Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Arată erorile în bara de stare\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Deschide sursa Brackets\",\n\n    \"LANGUAGE_TITLE\"                            : \"Modificare Limbă\",\n    \"LANGUAGE_MESSAGE\"                          : \"Limba:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Reîncarcă {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Revocare\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Limba implicită a sistemului\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Timp\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progres\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Mută punctul selectat<br><kbd class='text'>Shift</kbd> Mută cu zece unități<br><kbd class='text'>Tab</kbd> Comută punctele\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Incrementează sau decrementează pașii<br><kbd>←</kbd><kbd>→</kbd> 'Început' or 'Sfâșit'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Valoarea veche <code>{0}</code> nu e validă, astfel funcția afișată a fost modificată în <code>{1}</code>. Documentul va fi actualizat cu prima editare.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Culoarea curentă\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Culoarea originală\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Format RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Format Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Format HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (folosită {1} dată)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (folosită {1} ori)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Sari la definiție\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Arată sugestia parametrului\",\n    \"NO_ARGUMENTS\"                              : \"<niciun parametru>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problemă de inferență a fișierelu JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets a întâlnit probleme la procesarea:<br><br>{0}<br><br>Acest fișier nu va mai fi procesat pentru indicii de cod și definiții. Pentru a reactiva acest funcțional, deschideți <code>.brackets.json</code> din proiect și eliminați fișierul din jscodehints.detectedExclusions.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Activare Quick View\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Proiecte recente\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Vezi mai mult\"\n});\n\n/* Last translated for 2caf4f2e5745a87d482246b2aa57cdd5aab1e13d */\n"
  },
  {
    "path": "src/nls/root/strings-app.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // product-specific strings\n    \"APP_NAME\"                             : \"Brackets\",\n\n    // Self locales (used by Debug > Switch Language)\n    \"LOCALE_BG\"                                 : \"български\",\n    \"LOCALE_CS\"                                 : \"čeština\",\n    \"LOCALE_DA\"                                 : \"Dansk\",\n    \"LOCALE_DE\"                                 : \"Deutsch\",\n    \"LOCALE_EL\"                                 : \"Ελληνικά\",\n    \"LOCALE_EN\"                                 : \"English (US)\",\n    \"LOCALE_EN_GB\"                              : \"English (UK)\",\n    \"LOCALE_ES\"                                 : \"español\",\n    \"LOCALE_FA_IR\"                              : \"فارسی\",\n    \"LOCALE_FI\"                                 : \"suomi\",\n    \"LOCALE_FR\"                                 : \"français\",\n    \"LOCALE_GL\"                                 : \"galego\",\n    \"LOCALE_HR\"                                 : \"hrvatski\",\n    \"LOCALE_HU\"                                 : \"magyar\",\n    \"LOCALE_ID\"                                 : \"Bahasa Indonesia\",\n    \"LOCALE_IT\"                                 : \"italiano\",\n    \"LOCALE_JA\"                                 : \"日本語\",\n    \"LOCALE_KO\"                                 : \"한국어\",\n    \"LOCALE_LV\"                                 : \"latviešu\",\n    \"LOCALE_NB\"                                 : \"norsk\",\n    \"LOCALE_NL\"                                 : \"Nederlands\",\n    \"LOCALE_PL\"                                 : \"polski\",\n    \"LOCALE_PT_BR\"                              : \"português (BR)\",\n    \"LOCALE_PT_PT\"                              : \"português (PT)\",\n    \"LOCALE_RO\"                                 : \"română\",\n    \"LOCALE_RU\"                                 : \"русский\",\n    \"LOCALE_SK\"                                 : \"slovenčina\",\n    \"LOCALE_SR\"                                 : \"Српски\",\n    \"LOCALE_SV\"                                 : \"svenska\",\n    \"LOCALE_TR\"                                 : \"Türkçe\",\n    \"LOCALE_UK\"                                 : \"Українська\",\n    \"LOCALE_ZH_CN\"                              : \"简体中文\",\n    \"LOCALE_ZH_TW\"                              : \"繁體中文\"\n});\n"
  },
  {
    "path": "src/nls/root/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(error {0})\",\n    \"NOT_FOUND_ERR\"                     : \"The file/directory could not be found.\",\n    \"NOT_READABLE_ERR\"                  : \"The file/directory could not be read.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Files larger than {0} MB cannot be opened in {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"The target directory cannot be modified.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"The permissions do not allow you to make modifications.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"The file has been modified outside of {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"Unknown encoding format\",\n    \"ENCODE_FILE_FAILED_ERR\"            : \"{APP_NAME} was not able to encode the contents of file.\",\n    \"DECODE_FILE_FAILED_ERR\"            : \"{APP_NAME} was not able to decode the contents of file.\",\n    \"UNSUPPORTED_UTF16_ENCODING_ERR\"    : \"{APP_NAME} currently doesn't support UTF-16 encoded text files.\",\n    \"FILE_EXISTS_ERR\"                   : \"The file or directory already exists.\",\n    \"FILE\"                              : \"file\",\n    \"FILE_TITLE\"                        : \"File\",\n    \"DIRECTORY\"                         : \"directory\",\n    \"DIRECTORY_TITLE\"                   : \"Directory\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Directory names\",\n    \"FILENAMES_LEDE\"                    : \"Filenames\",\n    \"FILENAME\"                          : \"Filename\",\n    \"DIRECTORY_NAME\"                    : \"Directory Name\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Error Loading Project\",\n    \"OPEN_DIALOG_ERROR\"                 : \"An error occurred when showing the open file dialog. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"An error occurred when trying to load the directory <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"An error occurred when reading the contents of the directory <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Error Opening File\",\n    \"ERROR_OPENING_FILE\"                : \"An error occurred when trying to open the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"An error occurred when trying to open the following files:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Error Reloading Changes From Disk\",\n    \"ERROR_RELOADING_FILE\"              : \"An error occurred when trying to reload the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Error Saving File\",\n    \"ERROR_SAVING_FILE\"                 : \"An error occurred when trying to save the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Error Renaming {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"An error occurred when trying to rename the {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"The file or directory is not part of the currently opened project. Unfortunately, only project files can be renamed at this point.\",\n    \"ERROR_MOVING_FILE_TITLE\"           : \"Error Moving {0}\",\n    \"ERROR_MOVING_FILE\"                 : \"An error occurred when trying to move the {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_MOVING_NOT_IN_PROJECT\"       : \"Cannot move the file/folder, as they are not part of the current project.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Error Deleting {0}\",\n    \"ERROR_DELETING_FILE\"               : \"An error occurred when trying to delete the {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Invalid {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} cannot use any system reserved words, end with dots (.) or use any of the following characters: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"A file or directory with the name <span class='dialog-filename'>{0}</span> already exists.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Error Creating {0}\",\n    \"ERROR_CREATING_FILE\"               : \"An error occurred when trying to create the {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Cannot open a folder at the same time as opening other files.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Error Reading User Key Map\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Your key map file is not valid JSON. The file will be opened so that you can correct the format.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Your key map file is not a valid UTF-8 encoded text file and cannot be loaded\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"You cannot reassign shortcuts to these commands: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"You cannot reassign these shortcuts: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"You are reassigning multiple shortcuts to these commands: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"You have multiple bindings of these shortcuts: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"These shortcuts are invalid: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"You are assigning shortcuts to nonexistent commands: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Error Reading Preferences\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Your preferences file is not valid JSON. The file will be opened so that you can correct the format. You will need to restart {APP_NAME} for the changes to take effect.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Your project preferences file is not valid JSON. The file will be opened so that you can correct the format. You will need to reload the project for the changes to take effect.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Oops! {APP_NAME} Doesn't Run in Browsers Yet.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} is built in HTML, but right now it runs as a desktop app so you can use it to edit local files. Please use the application shell in the <b>github.com/adobe/brackets-shell</b> repo to run {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Error Indexing Files\",\n    \"ERROR_MAX_FILES\"                   : \"This project contains more than 30,000 files. Features that operate across multiple files may be disabled or behave as if the project is empty. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Read more about working with large projects</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Error Launching Browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"The Google Chrome browser could not be found. Please make sure it is installed.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"An error occurred when launching the browser. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Live Preview Error\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Connecting to Browser\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"In order for Live Preview to connect, Chrome needs to be relaunched with remote debugging enabled.<br /><br />Would you like to relaunch Chrome and enable remote debugging?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Unable to load Live Preview page.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Open an HTML file or make sure there is an index.html file in your project in order to launch live preview.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"To launch live preview with a server-side file, you need to specify a Base URL for this project.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Error starting up the HTTP server for live preview files. Please try again.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Welcome to Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live Preview connects {APP_NAME} to your browser. It launches a preview of your HTML file in the browser, then updates the preview instantly as you edit your code.<br /><br />In this early version of {APP_NAME}, Live Preview only works with <strong>Google Chrome</strong> and updates live as you edit <strong>CSS or HTML files</strong>. Changes to JavaScript files are automatically reloaded when you save.<br /><br />(You'll only see this message once.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"For more information, see <a href='{0}' title='{0}'>Troubleshooting Live Preview connection errors</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: Connecting\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: Initializing\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Disconnect Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview (save file to refresh)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Preview (not updating due to syntax error)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Live Preview was canceled because the browser's developer tools were opened\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Live Preview was canceled because the page was closed in the browser\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Live Preview was canceled because the browser navigated to a page that is not part of the current project\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Live Preview was canceled for an unknown reason ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Save Changes\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Do you want to save the changes you made in the document <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Do you want to save your changes to the following files?\",\n    \"EXT_MODIFIED_TITLE\"                : \"External Changes\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Confirm Delete\",\n    \"CONFIRM_FILE_DELETE\"               : \"Are you sure you want to delete the file <span class='dialog-filename'>{0}</span>?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Are you sure you want to delete the folder <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"File Deleted\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> has been modified on disk outside of {APP_NAME}.<br /><br />Do you want to save the file and overwrite those changes?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> has been modified on disk outside of {APP_NAME}, but also has unsaved changes in {APP_NAME}.<br /><br />Which version do you want to keep?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> has been deleted on disk outside of {APP_NAME}, but has unsaved changes in {APP_NAME}.<br /><br />Do you want to keep your changes?\",\n    \n    // Window unload warning messages\n    \"WINDOW_UNLOAD_WARNING\"                      : \"Are you sure you want to navigate to a different URL and leave Brackets?\",\n    \"WINDOW_UNLOAD_WARNING_WITH_UNSAVED_CHANGES\" : \"You have unsaved changes! Are you sure you want to navigate to a different URL and leave Brackets?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Done\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Cancel\",\n    \"DONT_SAVE\"                         : \"Don't Save\",\n    \"SAVE\"                              : \"Save\",\n    \"SAVE_AS\"                           : \"Save As\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Overwrite\",\n    \"DELETE\"                            : \"Delete\",\n    \"BUTTON_YES\"                        : \"Yes\",\n    \"BUTTON_NO\"                         : \"No\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} of {1}\",\n    \"FIND_NO_RESULTS\"                   : \"No results\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Find\\u2026\",\n    \"FIND_HISTORY_MAX_COUNT\"            : \"Maximum Number of Search Items in Search History\",\n    \"REPLACE_PLACEHOLDER\"               : \"Replace with\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Replace All\",\n    \"BUTTON_REPLACE_BATCH\"              : \"Batch\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Replace\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Replace\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Next Match\",\n    \"BUTTON_PREV_HINT\"                  : \"Previous Match\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Match Case\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regular Expression\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Replace Without Undo\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Because more than {0} files need to be changed, {APP_NAME} will modify unopened files on disk.<br />You won't be able to undo replacements in those files.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Replace Without Undo\",\n\n    \"OPEN_FILE\"                         : \"Open File\",\n    \"SAVE_FILE_AS\"                      : \"Save File\",\n    \"CHOOSE_FOLDER\"                     : \"Choose a folder\",\n\n    \"RELEASE_NOTES\"                     : \"Release Notes\",\n    \"NO_UPDATE_TITLE\"                   : \"You're Up to Date!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"You are running the latest version of {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Replace\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"with\",\n    \"FIND_TITLE_LABEL\"                  : \"Found\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} in {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"in <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"in project\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filter excludes all files {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"file\",\n    \"FIND_IN_FILES_FILES\"               : \"files\",\n    \"FIND_IN_FILES_MATCH\"               : \"match\",\n    \"FIND_IN_FILES_MATCHES\"             : \"matches\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Over \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd click to expand/collapse all\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indexing for Instant Search\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Replace Errors\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"The following files weren't modified because they changed after the search or couldn't be written.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Error Getting Update Info\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"There was a problem getting the latest update information from the server. Please make sure you are connected to the Internet and try again.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"New Exclusion Set\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Don't Exclude Files\",\n    \"NO_FILE_FILTER\"                    : \"No Files Excluded\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Exclude {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Edit\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Edit Exclusion Set\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Exclude files and folders matching any of the following strings / substrings or <a href='{0}' title='{0}'>wildcards</a>. Enter each string on a new line.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Name this exclusion set (optional)\",\n    \"FILTER_NAME_REMAINING\"             : \"{0} characters remaining\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"and {0} more\",\n    \"FILTER_COUNTING_FILES\"             : \"Counting files\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Allows {0} of {1} files {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Allows all {0} files {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"No Quick Edit available for current cursor position\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Quick Edit: place cursor on a single class name\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Quick Edit: incomplete class attribute\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Quick Edit: incomplete id attribute\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Quick Edit: place cursor in tag, class, or id\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS Timing Function Quick Edit: invalid syntax\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Quick Edit: place cursor in function name\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"No Quick Docs available for current cursor position\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Loading\\u2026\",\n    \"UNTITLED\"          : \"Untitled\",\n    \"WORKING_FILES\"     : \"Working Files\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Top\",\n    \"BOTTOM\"            : \"Bottom\",\n    \"LEFT\"              : \"Left\",\n    \"RIGHT\"             : \"Right\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"No Split\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Vertical Split\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Horizontal Split\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Split the editor vertically or horizontally\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Configure Working Set\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Already Open\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"The file is already open in another pane. {APP_NAME} will soon support opening the same file in more than one pane. Until then, the file will be shown in the pane it's already open in.<br /><br />(You'll only see this message once.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"Space\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Line {0}, Column {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Selected {0} column\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Selected {0} columns\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Selected {0} line\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Selected {0} lines\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} selections\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Click to switch indentation to spaces\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Click to switch indentation to tabs\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Click to change number of spaces used when indenting\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Click to change tab character width\",\n    \"STATUSBAR_SPACES\"                      : \"Spaces:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab Size:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} Line\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} Lines\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Extensions Disabled\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Click to toggle cursor between Insert (INS) and Overwrite (OVR) modes\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Click to change file type\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Click to toggle report panel.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(default)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Set as Default for .{0} Files\",\n    \"STATUSBAR_ENCODING_TOOLTIP\"            : \"Select the encoding\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} Problems\",\n    \"SINGLE_ERROR\"                          : \"1 {0} Problem\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} Problems\",\n    \"NO_ERRORS\"                             : \"No {0} problems found - good job!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"No problems found - good job!\",\n    \"LINT_DISABLED\"                         : \"Linting is disabled\",\n    \"NO_LINT_AVAILABLE\"                     : \"No linter available for {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Nothing to lint\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} has timed out after waiting for {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} terminated with error: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"File\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"New\",\n    \"CMD_FILE_NEW\"                        : \"New File\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"New Folder\",\n    \"CMD_FILE_OPEN\"                       : \"Open\\u2026\",\n    \"CMD_RECENT_FILES_OPEN\"               : \"Open Recent\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Open To Working Set\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Open Dropped Files\",\n    \"CMD_OPEN_FOLDER\"                     : \"Open Folder\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Close\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Close All\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Close List\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Close Others\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Close Others Above\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Close Others Below\",\n    \"CMD_FILE_SAVE\"                       : \"Save\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Save All\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Save As\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Preview\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"Enable Experimental Live Preview\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Force Reload Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Project Settings\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Rename\",\n    \"CMD_FILE_DELETE\"                     : \"Delete\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Install Extension\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Extension Manager\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Refresh File Tree\",\n    \"CMD_QUIT\"                            : \"Quit\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Exit\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edit\",\n    \"CMD_UNDO\"                            : \"Undo\",\n    \"CMD_REDO\"                            : \"Redo\",\n    \"CMD_CUT\"                             : \"Cut\",\n    \"CMD_COPY\"                            : \"Copy\",\n    \"CMD_PASTE\"                           : \"Paste\",\n    \"CMD_SELECT_ALL\"                      : \"Select All\",\n    \"CMD_SELECT_LINE\"                     : \"Select Line\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Split Selection into Lines\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Add Cursor to Next Line\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Add Cursor to Previous Line\",\n    \"CMD_INDENT\"                          : \"Indent\",\n    \"CMD_UNINDENT\"                        : \"Unindent\",\n    \"CMD_DUPLICATE\"                       : \"Duplicate\",\n    \"CMD_DELETE_LINES\"                    : \"Delete Line\",\n    \"CMD_COMMENT\"                         : \"Toggle Line Comment\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Toggle Block Comment\",\n    \"CMD_LINE_UP\"                         : \"Move Line Up\",\n    \"CMD_LINE_DOWN\"                       : \"Move Line Down\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Open Line Above\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Open Line Below\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Auto Close Braces\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Show Code Hints\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Find\",\n    \"CMD_FIND\"                            : \"Find\",\n    \"CMD_FIND_NEXT\"                       : \"Find Next\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Find Previous\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Find All and Select\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Add Next Match to Selection\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Skip and Add Next Match\",\n    \"CMD_FIND_IN_FILES\"                   : \"Find in Files\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Find in\\u2026\",\n    \"CMD_REPLACE\"                         : \"Replace\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Replace in Files\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Replace in\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"View\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Hide Sidebar\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Show Sidebar\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Toggle Sidebar\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Toggle Panels\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"No Distractions\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Increase Font Size\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Decrease Font Size\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restore Font Size\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Scroll Line Up\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Scroll Line Down\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Line Numbers\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Highlight Active Line\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Word Wrap\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Live Preview Highlight\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Lint Files on Save\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sort by Added\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sort by Name\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sort by Type\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatic Sort\",\n    \"CMD_THEMES\"                          : \"Themes\\u2026\",\n    \"CMD_TOGGLE_SEARCH_AUTOHIDE\"          : \"Automatically close search\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Navigate\",\n    \"CMD_QUICK_OPEN\"                      : \"Quick Open\",\n    \"CMD_GOTO_LINE\"                       : \"Go to Line\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Quick Find Definition\",\n    \"CMD_GOTO_DEFINITION_PROJECT\"         : \"Quick Find Definition in Project\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Go to First Problem\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Quick Edit\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Quick Docs\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Previous Match\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Next Match\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"New Rule\",\n    \"CMD_NEXT_DOC\"                        : \"Next Document\",\n    \"CMD_PREV_DOC\"                        : \"Previous Document\",\n    \"CMD_NAVIGATE_BACKWARD\"               : \"Navigate Backward\",\n    \"CMD_NAVIGATE_FORWARD\"                : \"Navigate Forward\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Next Document in List\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Previous Document in List\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Show in File Tree\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Show in Explorer\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Show in Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Show in OS\",\n    \"CMD_SWITCH_PANE_FOCUS\"               : \"Switch Pane Focus\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Help\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Check for Updates\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"How to Use {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} Support\",\n    \"CMD_SUGGEST\"                         : \"Suggest a Feature\",\n    \"CMD_RELEASE_NOTES\"                   : \"Release Notes\",\n    \"CMD_GET_INVOLVED\"                    : \"Get Involved\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Show Extensions Folder\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Health Report\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} Homepage\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} on Twitter\",\n    \"CMD_ABOUT\"                           : \"About {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Open Preferences File\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Open User Key Map\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimental build\",\n    \"RELEASE_BUILD\"                        : \"build\",\n    \"DEVELOPMENT_BUILD\"                    : \"development build\",\n    \"PRERELEASE_BUILD\"                     : \"prerelease build\",\n    \"RELOAD_FROM_DISK\"                     : \"Reload from Disk\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Keep Changes in Editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Close (Don't Save)\",\n    \"RELAUNCH_CHROME\"                      : \"Relaunch Chrome\",\n    \"ABOUT\"                                : \"About\",\n    \"CLOSE\"                                : \"Close\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Release {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"build timestamp: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Notices, terms and conditions pertaining to third party software are located at <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> and incorporated by reference herein.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Documentation and source at <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Made with \\u2764 and JavaScript by:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Lots of people (but we're having trouble loading that data right now).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs and the MDN graphical logo are licensed under a Creative Commons Attribution license, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"There's a new build of {APP_NAME} available! Click here for details.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Update Available\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, there's a new build of {APP_NAME} available. Here are some of the new features:\",\n    \"GET_IT_NOW\"                           : \"Get it now!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Project Settings for: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Live Preview Base URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"To use a local server, enter a URL like http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"The {0} protocol isn't supported by Live Preview&mdash;please use http: or https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"The base URL can't contain search parameters like \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"The base URL can't contain hashes like \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Special characters like '{0}' must be %-encoded.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Unknown error parsing Base URL\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Open a file while this pane has focus</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Flip this view to {0} pane\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Current Theme\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Use Theme Scrollbars\",\n    \"FONT_SIZE\"                            : \"Font Size\",\n    \"FONT_FAMILY\"                          : \"Font Family\",\n    \"THEMES_SETTINGS\"                      : \"Themes Settings\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"New Rule\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Install\",\n    \"UPDATE\"                               : \"Update\",\n    \"REMOVE\"                               : \"Remove\",\n    \"DISABLE\"                              : \"Disable\",\n    \"ENABLE\"                               : \"Enable\",\n    \"OVERWRITE\"                            : \"Overwrite\",\n    \"CANT_REMOVE_DEV\"                      : \"Extensions in the \\\"dev\\\" folder must be manually deleted.\",\n    \"CANT_UPDATE\"                          : \"The update isn't compatible with this version of {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Extensions in the \\\"dev\\\" folder can't be updated automatically.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Install Extension\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Update Extension\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Extension URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL of the extension's zip file or GitHub repo\",\n    \"INSTALLING_FROM\"                      : \"Installing extension from {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installation successful!\",\n    \"INSTALL_FAILED\"                       : \"Installation failed.\",\n    \"CANCELING_INSTALL\"                    : \"Canceling\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Canceling the install is taking a long time. An internal error may have occurred.\",\n    \"INSTALL_CANCELED\"                     : \"Installation canceled.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"View complete description\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"View truncated description\",\n    \"SORT_EXTENSION_METHOD\"                : \"Sort Extensions using downloadCount or publishedDate\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"The downloaded content is not a valid zip file.\",\n    \"MISSING_PACKAGE_JSON\"                 : \"The package has no package.json file.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"The package.json file is not valid (error was: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"The package.json file doesn't specify a package name.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} is an invalid package name.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"The package.json file doesn't specify a package version.\",\n    \"INVALID_VERSION_NUMBER\"               : \"The package version number ({0}) is invalid.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"The {APP_NAME} compatibility string ({0}) is invalid.\",\n    \"DISALLOWED_WORDS\"                     : \"The words ({1}) are not allowed in the {0} field.\",\n    \"NPM_INSTALL_FAILED\"                   : \"npm install command failed: {0}\",\n    \"API_NOT_COMPATIBLE\"                   : \"The extension isn't compatible with this version of {APP_NAME}. It's installed in your disabled extensions folder.\",\n    \"MISSING_MAIN\"                         : \"The package has no main.js file.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Installing this package will overwrite a previously installed extension. Overwrite the old extension?\",\n    \"EXTENSION_SAME_VERSION\"               : \"This package is the same version as the one that is currently installed. Overwrite the existing installation?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"This package is version {0} which is older than the currently installed ({1}). Overwrite the existing installation?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Internal error: download ID already in use.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Cannot connect to server.\",\n    \"BAD_HTTP_STATUS\"                      : \"File not found on server (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Unable to save download to temp file.\",\n    \"ERROR_LOADING\"                        : \"The extension encountered an error while starting up.\",\n    \"MALFORMED_URL\"                        : \"The URL is invalid. Please check that you entered it correctly.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"The URL must be an http or https URL.\",\n    \"UNKNOWN_ERROR\"                        : \"Unknown internal error.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Extension Manager\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Unable to access the extension registry. Please try again later.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Drag .zip here or\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Drop .zip to install\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Install/Update aborted due to the following errors:\",\n    \"INSTALL_FROM_URL\"                     : \"Install from URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validating\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Author\",\n    \"EXTENSION_DATE\"                       : \"Date\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"This extension requires a newer version of {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"This extension currently only works with older versions of {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Version {0} of this extension requires a newer version of {APP_NAME}. But you can install the earlier version {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Version {0} of this extension only works with older versions of {APP_NAME}. But you can install the earlier version {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"No description\",\n    \"EXTENSION_MORE_INFO\"                  : \"More info\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Extension error\",\n    \"EXTENSION_KEYWORDS\"                   : \"Keywords\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Translated into {0} languages, including yours\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Translated into {0} languages\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"This extension has been translated into these languages: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Installed\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"This extension update has been downloaded and will be installed after {APP_NAME} reloads.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Search\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"More\",\n    \"BROWSE_EXTENSIONS\"                    : \"Browse Extensions\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Remove Extension\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Unable to remove one or more extensions: {0}. {APP_NAME} will still reload.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Update Extension\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Unable to update one or more extensions: {0}. {APP_NAME} will still reload.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Disable Extension\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Unable to disable one or more extensions: {0}. {APP_NAME} will still reload.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Marked for removal\",\n    \"UNDO_REMOVE\"                          : \"Undo\",\n    \"MARKED_FOR_UPDATE\"                    : \"Marked for update\",\n    \"UNDO_UPDATE\"                          : \"Undo\",\n    \"MARKED_FOR_DISABLING\"                 : \"Marked for disabling\",\n    \"UNDO_DISABLE\"                         : \"Undo\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Change Extensions\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"To update, remove or disable the marked extensions, {APP_NAME} will need to reload. You'll be prompted to save unsaved changes.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Remove Extensions and Reload\",\n    \"CHANGE_AND_RELOAD\"                    : \"Change Extensions and Reload\",\n    \"UPDATE_AND_RELOAD\"                    : \"Update Extensions and Reload\",\n    \"DISABLE_AND_RELOAD\"                   : \"Disable Extensions and Reload\",\n    \"PROCESSING_EXTENSIONS\"                : \"Processing extension changes\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Couldn't remove extension {0} because it wasn't installed.\",\n    \"NO_EXTENSIONS\"                        : \"No extensions installed yet.<br>Click on the Available tab above to get started.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"No extensions match your search.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"NOTE: These extensions may come from different authors than {APP_NAME} itself. Extensions are not reviewed and have full local privileges. Be cautious when installing extensions from an unknown source.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Installed\",\n    \"EXTENSIONS_DEFAULT_TITLE\"             : \"Default\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Available\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Themes\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Updates\",\n    \"EXTENSIONS_LAST_UPDATED\"              : \"Last Updated\",\n    \"EXTENSIONS_DOWNLOADS\"                 : \"Downloads\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"No matches available.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"All matches are collapsed. Expand the files listed at right to view matches.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"There are no existing CSS rules that match your selection.<br> Click \\\"New Rule\\\" to create one.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"There are no stylesheets in your project.<br>Create one to add CSS rules.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"largest\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pixels\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"Errors\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Show Developer Tools\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Reload With Extensions\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Reload Without Extensions\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"New {APP_NAME} Window\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Install Command Line Shortcut\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Switch Language\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Run Tests\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Show Performance Data\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Enable Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Log Node State to Console\",\n    \"CMD_RESTART_NODE\"                          : \"Restart Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Show Errors in Status Bar\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Open {APP_NAME} Source\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} Command Line Shortcut\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"An error occurred while installing the command line shortcut. Please try <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>these troubleshooting suggestions</a>.<br/><br/>Reason: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Unable to remove existing <code>/usr/local/bin/brackets</code> symlink.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Unable to create <code>/usr/local/bin</code> directory.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Unable to create <code>/usr/local/bin/brackets</code> symlink.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Internal error.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Command line shortcut is not supported on this OS.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Success! Now you can easily launch {APP_NAME} from the command line: <code>brackets myFile.txt</code> to open a file or <code>brackets myFolder</code> to switch projects. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Learn more</a> about using {APP_NAME} from the command line.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Switch Language\",\n    \"LANGUAGE_MESSAGE\"                          : \"Language:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Reload {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Cancel\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"System Default\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Health Report Preferences\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} Health Report\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Share pseudonymous information on how I use {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"In order to improve {APP_NAME}, we periodically send limited, <strong>pseudonymous</strong> statistics to Adobe about how you use {APP_NAME}. This information helps prioritize features, find bugs, and spot usability issues.<br><br>You can see your data or choose not to share data by selecting <strong>Help > Health Report</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Project-Health-Data'>Learn more about {APP_NAME} Health Report</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} Health Report\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>In order to improve {APP_NAME}, we periodically send limited, <strong>pseudonymous</strong> statistics to Adobe about how you use {APP_NAME}. This information helps prioritize features, find bugs, and spot usability issues. <a href='https://github.com/adobe/brackets/wiki/Project-Health-Data'>Learn more about {APP_NAME} Health Report</a> and how it benefits the {APP_NAME} community while protecting your privacy.</p><p>Below is a preview of the data that will be sent in your next Health Report <em>if</em> it is enabled.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Time\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progression\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Move selected point<br><kbd class='text'>Shift</kbd> Move by ten units<br><kbd class='text'>Tab</kbd> Switch points\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Increase or decrease steps<br><kbd>←</kbd><kbd>→</kbd> 'Start' or 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"The old value <code>{0}</code> is not valid, so the displayed function was changed to <code>{1}</code>. The document will be updated with the first edit.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Current Color\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Original Color\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa Format\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex Format\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa Format\",\n    \"COLOR_EDITOR_0X_BUTTON_TIP\"                : \"Hex (0x) Format\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Used {1} time)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Used {1} times)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Jump to Definition\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Show Parameter Hint\",\n    \"NO_ARGUMENTS\"                              : \"<no parameters>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"JavaScript File Inference Problem\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} ran into trouble processing <span class='dialog-filename'>{0}</span>.<br><br>This file will no longer be processed for code hints, Jump to Definition or Quick Edit. To re-enable this file, open <code>.brackets.json</code> in your project and edit <code>jscodehints.detectedExclusions</code>.<br><br>This is likely a {APP_NAME} bug. If you can provide a copy of this file, please <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>file a bug</a> with a link to the file named here.\",\n\n    // extensions/default/JavascriptRefactoring\n    \"CMD_REFACTOR\"                              : \"Refactor\",\n    \"CMD_EXTRACTTO_VARIABLE\"                    : \"Extract to Variable\",\n    \"CMD_EXTRACTTO_FUNCTION\"                    : \"Extract to Function\",\n    \"ERROR_TERN_FAILED\"                         : \"Unable to get data from Tern\",\n    \"ERROR_EXTRACTTO_VARIABLE_NOT_VALID\"        : \"Selection does not form an expression\",\n    \"ERROR_EXTRACTTO_FUNCTION_NOT_VALID\"        : \"Selected block should represent set of statements or an expression\",\n    \"ERROR_EXTRACTTO_VARIABLE_MULTICURSORS\"     : \"Extract to Variable does not work in multicursors\",\n    \"ERROR_EXTRACTTO_FUNCTION_MULTICURSORS\"     : \"Extract to Function does not work in multicursors\",\n    \"EXTRACTTO_FUNCTION_SELECT_SCOPE\"           : \"Choose destination scope\",\n    \"EXTRACTTO_VARIABLE_SELECT_EXPRESSION\"      : \"Select an expression\",\n    \"CMD_REFACTORING_RENAME\"                    : \"Rename\",\n    \"CMD_REFACTORING_TRY_CATCH\"                 : \"Wrap in Try Catch\",\n    \"CMD_REFACTORING_CONDITION\"                 : \"Wrap in Condition\",\n    \"CMD_REFACTORING_GETTERS_SETTERS\"           : \"Create Getters/Setters\",\n    \"CMD_REFACTORING_ARROW_FUNCTION\"            : \"Convert to Arrow Function\",\n    \"DESCRIPTION_CODE_REFACTORING\"              : \"Enable/disable JavaScript Code Refactoring\",\n    \"ERROR_TRY_CATCH\"                           : \"Select valid code to wrap in a Try-catch block\",\n    \"ERROR_WRAP_IN_CONDITION\"                   : \"Select valid code to wrap in a Condition block\",\n    \"ERROR_ARROW_FUNCTION\"                      : \"Place the cursor inside a function expression\",\n    \"ERROR_GETTERS_SETTERS\"                     : \"Place the cursor at a member of an object expression\",\n    \"ERROR_RENAME_MULTICURSOR\"                  : \"Cannot rename when using multi-cursors\",\n    \"ERROR_RENAME_QUICKEDIT\"                    : \"Cannot rename this identifier, as it is referenced elsewhere outside this function\",\n    \"ERROR_RENAME_GENERAL\"                      : \"Cannot rename selected text\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Quick View on Hover\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Recent Projects\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Read more\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Collapse All\",\n    \"EXPAND_ALL\"                    : \"Expand All\",\n    \"COLLAPSE_CURRENT\"              : \"Collapse Current\",\n    \"EXPAND_CURRENT\"                : \"Expand Current\",\n\n    // extensions/default/NavigationAndHistory\n    \"RECENT_FILES_DLG_HEADER\"                    : \"Recent Files\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\"        : \"Clear\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\"        : \"Clear files not in Working Set\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true to automatically close braces, brackets and parentheses\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false to remove the \\\"Close Others Above\\\" from the Working Files context menu\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false to remove the \\\"Close Others Below\\\" from the Working Files context menu\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false to remove the \\\"Close Others\\\" from the Working Files context menu\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"Sets the tag closing options\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"An array of tags that should not be auto-closed\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"Close when > of opening tag is typed\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"Close when / of closing tag is typed\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"An array of tags that when opened has a blank line\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true to always generate collapsible section markers when indent level changes\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true to enable code folding\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true to make Section-collapsing markers visible only when you move the mouse over the gutter\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"Limits how many levels deep Collapse All applies\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"Minimum lines before a collapsible section icon appears\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true to remember collapsed sections if you close and reopen a file or project\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"true to enable code folding on selected text in the editor\",\n    \"DESCRIPTION_DISABLED_DEFAULT_EXTENSIONS\"        : \"Default extensions that are disabled\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"Enable/disable HTML attribute hints\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"Enable/disable CSS/LESS/SCSS property hints\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"Enable/disable JavaScript code hints\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"Enable/disable datatype details in JavaScript code hints\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"Enable/disable Preferences code hints\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"Enable/disable HTML entity hints\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"Enable/disable SVG code hints\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"Enable/disable HTML tag hints\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"Enable/disable URL hints in HTML & CSS/LESS/SCSS\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"Enable/disable Drag & Drop functionality\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"Enable the Health Data Tracking\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"Enables automatic highlighting of matching strings throughout the document\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"Highlight all strings that match the token the cursor is currently in (no selection needed)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"Highlight only when selection is a complete token\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true to insert the currently selected code hint on tab\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true to not automatically show JS code hints when . is typed\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"An object with the default options for JSLint\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true to allow assignment expressions\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true to allow bitwise operators\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true if standard browser globals should be predefined\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true to allow Google Closure idioms\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true to allow \\\"continue\\\" statement\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true if CouchDB globals should be predefined\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true to allow debugger statements\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true if browser globals useful in development should be predefined\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true to allow == and !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true if ES6 globals should be predefined\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true to allow eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true to allow unfiltered \\\"for ... in\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"Set a specific tab width\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"The maximum number of warnings reported\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"The maximum number of characters in a line\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true to allow uncapitalized constructors\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true if Node.js globals should be predefined\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true to allow dangling underscore in identifiers\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true to stop on first error\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true to allow ++ and --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true to allow . and [^...]. in RegExp\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true if Rhino globals should be predefined\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true to allow missing `use strict` pragma\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true if blocking ('...Sync') methods can be used.\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true to allow inefficient subscripting\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true to allow TODO comments\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true to allow unused parameters\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true to allow more than 1 vars in a function\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true to ignore white-space rules\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"Language specific settings\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"Additional mappings from file extension to language name\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"Additional mappings from file name to language name\",\n    \"DESCRIPTION_LINEWISE_COPY_CUT\"                  : \"Doing copy and cut when there's no selection will copy or cut the whole lines that have cursors in them\",\n    \"DESCRIPTION_INPUT_STYLE\"                        : \"Selects the way CodeMirror handles input and focus. It can be textarea, which is the default, or contenteditable which is better for screen readers (unstable)\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true to enable Code Inspection\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"The time in milliseconds after which asynchronous linters time out\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"Array of linters to run first\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true to enable experimental Live Preview\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true to run providers specified in linting.prefer only\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"Maximum code hints displayed at once\",\n    \"DESCRIPTION_PATH\"                               : \"Path specific settings\",\n    \"DESCRIPTION_PROXY\"                              : \"The URL of the proxy server used for extension installation\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true to enable scrolling beyond the end of the document\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false to disable all code hints\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"Keeps the blinking cursor visible when you have a text selection\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true to show line numbers in a “gutter” to the left of the code\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"Automatically indent when creating a new block\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false to turn off soft tabs behavior\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true to sort the directories first in the project tree\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"Number of spaces to use for space-based indentation\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"Port number that the built-in server should use for Live Preview\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true to highlight background color of the line the cursor is on\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"Number of spaces to display for tabs\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true to use tabs instead of spaces\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true to generate uppercase hex colors in Inline Color Editor\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"Wrap lines that exceed the viewport width\",\n    \"DESCRIPTION_SEARCH_AUTOHIDE\"                    : \"Close the search as soon as the editor is focused\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"A list of files that have been detected to cause Tern to run out of control\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"The amount of time after which Tern will time out when trying to understand files\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true to show errors in status bar\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true to enable Quick View\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true to show image previews for URLs missing extensions\",\n    \"DESCRIPTION_THEME\"                              : \"Select a {APP_NAME} theme\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true to allow custom scroll bars\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true to collapse linting panel\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"Change font family\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"Change font size; e.g. 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"true to enable node based search\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"true to enable instant search\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"Mac-only: \\\"subpixel-antialiased\\\" to enable sub-pixel antialiasing or \\\"antialiased\\\" for gray scale antialiasing\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false to disable opening preferences file in split view\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false to open user preferences file in left/top pane\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"true to collapse panes after the last file from the pane is closed via pane header close button\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"Toggle when to show the close and flip-view buttons on the header.\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * This is a read-only file with the preferences supported\\n * by {APP_NAME}.\\n * Use this file as a reference to modify your preferences\\n * file \\\"brackets.json\\\" opened in the other pane.\\n * For more information on how to use preferences inside\\n * {APP_NAME}, refer to the web page at https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"Default\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"true to enable code only mode and hide all other UI elements in {APP_NAME}\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"true to enable indenting of line comments\",\n    \"DESCRIPTION_RECENT_FILES_NAV\"                   : \"Enable/disable navigation in recent files\",\n    \"DESCRIPTION_LIVEDEV_WEBSOCKET_PORT\"             : \"Port on which WebSocket Server runs for Live Preview\",\n    \"DESCRIPTION_LIVE_DEV_HIGHLIGHT_SETTINGS\"        : \"Live Preview Highlight settings\",\n    \"DESCRIPTION_LIVEDEV_ENABLE_REVERSE_INSPECT\"     : \"false to disable live preview reverse inspect\",\n    \n    // Strings for Auto Update\n    \"DOWNLOAD_FAILED\"                                : \"Download failed.\",\n    \"DOWNLOAD_COMPLETE\"                              : \"Download complete!\",\n    \"UPDATE_SUCCESSFUL\"                              : \"Update successful!\",\n    \"UPDATE_FAILED\"                                  : \"Update failed!\",\n    \"VALIDATION_FAILED\"                              : \"Validation failed!\",\n    \"INITIALISATION_FAILED\"                          : \"Initialization failed!\",\n    \"CLEANUP_FAILED\"                                 : \"Clean-up failed!\",\n    \"WARNING_TYPE\"                                   : \"Warning!\",\n    \"CLICK_RESTART_TO_UPDATE\"                        : \"Click Restart to update Brackets.\",\n    \"UPDATE_ON_NEXT_LAUNCH\"                          : \"The update will be applied on relaunch.\",\n    \"GO_TO_SITE\"                                     : \"Go to <a href = \\\"http://brackets.io/\\\"> brackets.io </a> to retry.\",\n    \"INTERNET_UNAVAILABLE\"                           : \"No Internet connection available.\",\n    \"UPDATEDIR_READ_FAILED\"                          : \"Update directory could not be read.\",\n    \"UPDATEDIR_CLEAN_FAILED\"                         : \"Update directory could not be cleaned.\",\n    \"INITIAL_DOWNLOAD\"                               : \"Downloading Update...\",\n    \"RETRY_DOWNLOAD\"                                 : \"Download failed. Retrying...Attempt \",\n    \"VALIDATING_INSTALLER\"                           : \"Download complete! Validating Installer...\",\n    \"CHECKSUM_DID_NOT_MATCH\"                         : \"Checksum didn't match.\",\n    \"INSTALLER_NOT_FOUND\"                            : \"Installer not found.\",\n    \"DOWNLOAD_ERROR\"                                 : \"Error occurred while downloading.\",\n    \"NETWORK_SLOW_OR_DISCONNECTED\"                   : \"Network is disconnected or too slow.\",\n    \"RESTART_BUTTON\"                                 : \"Restart\",\n    \"LATER_BUTTON\"                                   : \"Later\",\n    \"DESCRIPTION_AUTO_UPDATE\"                        : \"Enable/disable Brackets Auto-update\",\n    \"AUTOUPDATE_ERROR\"                               : \"Error!\",\n    \"AUTOUPDATE_IN_PROGRESS\"                         : \"An update is already in progress.\",\n\n    \"NUMBER_WITH_PERCENTAGE\"                         : \"{0}%\",\n    // Strings for Related Files\n    \"CMD_FIND_RELATED_FILES\"                         : \"Find Related Files\",\n\n    ///String for Php Tooling Extensions\n    \"PHP_VERSION_INVALID\"                            : \"Error parsing PHP version. Please check the output of the “php –version” command.\",\n    \"PHP_UNSUPPORTED_VERSION\"                        : \"Install PHP7 runtime for enabling PHP-related tooling such as Code Hints, Parameter Hints, Jump To Definition and more. Version found: {0}\",\n    \"PHP_EXECUTABLE_NOT_FOUND\"                       : \"PHP runtime not found. Install the PHP7 runtime and update “executablePath” in PHP Preferences appropriately. This enables PHP-related tooling such as Code Hints, Parameter Hints, Jump To Definition and more.\",\n    \"PHP_PROCESS_SPAWN_ERROR\"                        : \"Error code {0} encountered while starting the PHP process.\",\n    \"PHP_SERVER_ERROR_TITLE\"                         : \"Error\",\n    \"PHP_SERVER_MEMORY_LIMIT_INVALID\"                : \"The memory limit you provided is invalid. Review the PHP preferences to set the correct value.\",\n    \"DESCRIPTION_PHP_TOOLING_CONFIGURATION\"          : \"PHP Tooling default configuration settings\",\n    \"OPEN_PREFERENNCES\"                              : \"Open Preferences\",\n\n    //Strings for LanguageTools Preferences\n    \"LANGUAGE_TOOLS_PREFERENCES\"                     : \"Preferences for Language Tools\",\n\n    \"FIND_ALL_REFERENCES\"                            : \"Find All References\",\n    \"REFERENCES_IN_FILES\"                            : \"references\",\n    \"REFERENCE_IN_FILES\"                             : \"reference\",\n    \"REFERENCES_NO_RESULTS\"                          : \"No References available for current cursor position\",\n\n    \"CMD_FIND_DOCUMENT_SYMBOLS\"                      : \"Find Document Symbols\",\n    \"CMD_FIND_PROJECT_SYMBOLS\"                       : \"Find Project Symbols\",\n\n   // Remote debugging enabled\n    \"REMOTE_DEBUGGING_ENABLED\"                       : \"Remote debugging enabled on localhost:\",\n\n   // Remote debugging port argument is invalid\n    \"REMOTE_DEBUGGING_PORT_INVALID\"                  : \"Cannot enable remote debugging on port {0}. Port numbers should be between {1} and {2}.\",\n    \n    //Associate File Type to External App\n    \"DESCRIPTION_EXTERNAL_APPLICATION_ASSOCIATE\"     : \"Mappings for file extension to external applications. Syntax: \\\"<file_type>\\\": \\\"<default|applicationName|ApplicationPath>\\\", Use \\\"default\\\" to open files in system default application for the file type.\",\n\n    \"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_TITLE\"   : \"Open Graphic Files in External Editors.\",\n    \"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_MSG\"     : \"Your current folder has graphic file types which are not supported by {APP_NAME}.<br/>You can now associate specific file types with external editors. Once associated, you can open graphic files like .xd, .psd, .jpg, .png, .ai, .svg in their default applications by double clicking on the files in File Tree.<br/><br/>Please click on ‘Ok’ button to associate the graphic file types with their respective default applications.\",\n    \"ASSOCIATE_GRAPHICS_FILE_TO_DEFAULT_APP_CNF_MSG\" : \"Following file types have been successfully associated with default applications.<br/>{0} You have the option to change your preference on whether you delete/add new file type associations in brackets.json by going to “Debug->Open Preferences File” menu.\"\n\n\n});\n"
  },
  {
    "path": "src/nls/root/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"root/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/\"\n});\n"
  },
  {
    "path": "src/nls/ru/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(ошибка {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Файл не найден\",\n    \"NOT_READABLE_ERR\"                  : \"Файл не может быть прочитан\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Целевая директория не может быть изменена.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Ограничение прав не позволяет сделать изменения.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Файл был изменен вне {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} пока поддерживает только текстовые файлы в кодировке UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Файл уже существует.\",\n    \"FILE\"                              : \"файл\",\n    \"DIRECTORY\"                         : \"директория\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Имена директорий\",\n    \"FILENAMES_LEDE\"                    : \"Имена файлов\",\n    \"FILENAME\"                          : \"имя файла\",\n    \"DIRECTORY_NAME\"                    : \"имя директории\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Ошибка при загрузке проекта\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Произошла ошибка при показе диалога открытия файлов. (ошибка {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Произошла ошибка при попытке загрузить директорию <span class='dialog-filename'>{0}</span>. (ошибка {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Произошла ошибка при чтении содержимого директории <span class='dialog-filename'>{0}</span>. (ошибка {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Ошибка открытия файла\",\n    \"ERROR_OPENING_FILE\"                : \"Произошла ошибка при попытке открыть файл <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Произошла ошибка при попытке открыть файлы: \",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Ошибка перезагрузки изменений с диска\",\n    \"ERROR_RELOADING_FILE\"              : \"Произошла ошибка при попытке перезагрузить файл <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Ошибка сохранения файла\",\n    \"ERROR_SAVING_FILE\"                 : \"Произошла ошибка при попытке сохранить файл <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Ошибка переименования файла\",\n    \"ERROR_RENAMING_FILE\"               : \"Произошла ошибка при попытке переименовать файл <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Ошибка удаления файла\",\n    \"ERROR_DELETING_FILE\"               : \"Произошла ошибка при попытке удалить файл <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Неверное имя файла {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} не может содержать зарезервированные слова, заканчиваться точкой (.) или содержать следующие символы: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Файл или директория с именем <span class='dialog-filename'>{0}</span> уже существует.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Ошибка создания файла\",\n    \"ERROR_CREATING_FILE\"               : \"Произошла ошибка при попытке создать файл <span class='dialog-filename'>{0}</span>. {1}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Ошибка чтения настроек\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Обнаружена ошибка формата JSON в файле настроек. Он будет открыт для того, чтобы исправить ошибку вручную. Вам будет необходимо перезагрузить {APP_NAME}, чтобы исправления вступили в силу.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"К сожалению, запуск {APP_NAME} в браузере пока что не поддерживается.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} разработан на HTML, но пока что может работать только как настольное приложение, чтобы вы могли редактировать локальные файлы. Пожалуйста, используйте специальную оболочку (проект <b>github.com/adobe/brackets-shell</b>) для запуска {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Ошибка индексирования файлов\",\n    \"ERROR_MAX_FILES\"                   : \"Количество файлов превышает предельно допустимое. Команды использующие индекс файлов могут работать некорректно.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Ошибка запуска браузера.\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Браузер Google Chrome не найден. Пожалуйста, убедитесь, что он установлен.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Произошла ошибка при запуске браузера. (ошибка {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Ошибка функции Live Preview\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Соединение с браузером\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Функция Live Preview требует перезапуска Chrome с включенной функцией удаленной отладки. <br /><br />Перезапустить Chrome с удаленной отладкой?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Невозможно загрузить страницу Live Preview\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Откройте HTML файл или убедитесь в наличии index.html в проекте для того чтобы запустить интерактивную разработку.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Для запуска Live Preview с серверным файлом, вы должны указать базовый URL проекта.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Ошибка запуска HTTP сервера для Live Preview. Попытайтесь снова.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Добро пожаловать в Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Live Preview, функция синхронного предпросмотра, подключает браузер к среде разработки {APP_NAME}. Эта функция загружает HTML файл для предварительного просмотра в браузере и мгновенно отображает все изменения при редактировании кода.<br /><br />В данной версии {APP_NAME}, функция Live Preview пока что работает только с <strong>Google Chrome</strong> и обновления в реальном времени отображаются только при редактировании <strong>CSS или HTML файлов</strong>. Изменения в JavaScript файлах автоматически перезагружают страницу при сохранении.<br /><br />(Это сообщение будет показано только один раз.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Для дополнительной информации, смотрите <a href='{0}' title='{0}'>Поиск и устранение неисправностей ошибок подключения Live Preview</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live Preview: Подключение\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live Preview: Инициализация\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Отсоединить Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Live Preview (Для отображения изменений сохраните их)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Live Preview (Не обновляется из-за синтаксической ошибки)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Функция Live Preview была отключена при открытии инструментов разработки в браузере\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Функция Live Preview была отключена при закрытии страницы в браузере\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Функция Live Preview была отключена при переходе на страницу не принадлежащую проекту\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Функция Live Preview была отменена по неизвестной причине ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Сохранить изменения\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Вы хотите сохранить изменения, которые вы сделали в документе <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Вы хотите сохранить изменения для следующих файлов?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Внешние изменения\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Подтвердить удаление\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Вы уверены, что хотите удалить директорию <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Файл удален\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> был изменен на диске.<br /><br />Вы хотите сохранить ваши изменения и перезаписать внешние?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> был изменен на диске, но также имеются несохраненные изменения в {APP_NAME}.<br /><br />Какую версию вы хотите оставить?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> был удален на диске, но имеются несохраненные изменения в {APP_NAME}.<br /><br />Вы хотите оставить ваши изменения?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Готово\",\n    \"OK\"                                : \"ОК\",\n    \"CANCEL\"                            : \"Отменить\",\n    \"DONT_SAVE\"                         : \"Не сохранять\",\n    \"SAVE\"                              : \"Сохранить\",\n    \"SAVE_AS\"                           : \"Сохранить как\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Перезаписать\",\n    \"DELETE\"                            : \"Удалить\",\n    \"BUTTON_YES\"                        : \"Да\",\n    \"BUTTON_NO\"                         : \"Нет\",\n\n    // Find, Replace, Find in Files\n    \"FIND_NO_RESULTS\"                   : \"Не найдено\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Найти\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Заменить на\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Все\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Заменить\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Следующее совпадение\",\n    \"BUTTON_PREV_HINT\"                  : \"Предыдущее совпадение\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"С учетом регистра\",\n    \"BUTTON_REGEXP_HINT\"                : \"Регулярное выражение\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Заменить без отмены\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Т.к. необходимо изменить более чем {0} файла(ов), {APP_NAME} выполнит замену непосредственно на диске.<br />Вы не сможете отменить изменения в этих файлах.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Заменить без отмены\",\n\n    \"OPEN_FILE\"                         : \"Открыть файл\",\n    \"SAVE_FILE_AS\"                      : \"Сохранить файл\",\n    \"CHOOSE_FOLDER\"                     : \"Выбрать директорию\",\n\n    \"RELEASE_NOTES\"                     : \"Примечания к выпуску\",\n    \"NO_UPDATE_TITLE\"                   : \"Обновления отсутствуют\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Вы используете последнюю версию {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Заменить\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"на\",\n    \"FIND_TITLE_LABEL\"                  : \"Найдено\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} в {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"в <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"в проекте\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Фильтр исключает все файлы {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"файле\",\n    \"FIND_IN_FILES_FILES\"               : \"файлах\",\n    \"FIND_IN_FILES_MATCH\"               : \"совпадение\",\n    \"FIND_IN_FILES_MATCHES\"             : \"совпадений\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Более \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We shoudl use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd-клик чтобы развернуть/свернуть все\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Ошибка замены\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Данные файлы не были изменены, т.к. они изменились после поиска или не могут быть записаны.\",\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Ошибка при получении информации об обновлениях\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Ошибка при получении информации о последних обновлениях с сервера. Пожалуйста, убедитесь, что вы подключены к интернету и попробуйте снова. \",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Новый фильтр\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Не исключать файлы\",\n    \"NO_FILE_FILTER\"                    : \"Нет исключенных файлов\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Исключить {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Редактировать\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Редактировать фильтр\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Исключить файлы и директории содержащие любую из перечисленных строк, возможно использование <a href='{0}' title='{0}'>групповых символов</a>. Указывайте по одной строке на линию.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Назвать этот фильтр (опционально)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"и еще {0}\",\n\n    \"FILTER_COUNTING_FILES\"             : \"Подсчет количества файлов\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Фильтр оставляет {0} из {1} файлов/а {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Фильтр оставляет все {0} файлов/а {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Быстрое редактирование недоступно для данной позиции курсора\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"Быстрое редактирование CSS: установите курсор на одном из имен класса\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"Быстрое редактирование CSS: отсутствует имя класса\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"Быстрое редактирование CSS: отсутствует имя идентификатора\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"Быстрое редактирование CSS: установите курсор на теге, классе или идентификаторе\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"Быстрое редактирование временной функции CSS: некорректный синтаксис\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"Быстрое редактирование JS: установите курсор на имени функции\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Быстрая документация для текущей позиции курсора отсутствет\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Загрузка\\u2026\",\n    \"UNTITLED\"          : \"Без названия\",\n    \"WORKING_FILES\"     : \"Рабочие файлы\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Строка {0}, Столбец {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Выделен {0} столбец\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Выделено {0} столбцов\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Выделена {0} строка\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Выделено {0} строк\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} выбранных элементов\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Нажмите чтобы использовать пробелы для отступа\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Нажмите чтобы использовать табуляцию для отступа\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Нажмите чтобы изменить количества пробелов для отступа\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Нажмите чтобы изменить ширину табуляции в столбцах\",\n    \"STATUSBAR_SPACES\"                      : \"Пробелы:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Табуляция:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} строка\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} строк\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Расширения отключены\",\n    \"STATUSBAR_INSERT\"                      : \"ВСТ\",\n    \"STATUSBAR_OVERWRITE\"                   : \"ЗАМ\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} ошибок\",\n    \"SINGLE_ERROR\"                          : \"1 ошибка {0}\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} ошибок {0}\",\n    \"NO_ERRORS\"                             : \"{0} не нашел ошибок &mdash; отлично!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Ошибок не найдено &mdash; отлично!\",\n    \"LINT_DISABLED\"                         : \"Статический анализ отключен\",\n    \"NO_LINT_AVAILABLE\"                     : \"Нет статического анализатора для {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Не подлежит статическому анализу\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} превысил время ожидания {1} мс\",\n    \"LINTER_FAILED\"                         : \"{0} завершил исполнение с ошибкой: {1}\",\n\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Файл\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Новый\",\n    \"CMD_FILE_NEW\"                        : \"Новый файл\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Новая директория\",\n    \"CMD_FILE_OPEN\"                       : \"Открыть\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Добавить в рабочий набор\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Открыть перетащенные файлы\",\n    \"CMD_OPEN_FOLDER\"                     : \"Открыть директорию\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Закрыть\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Закрыть все\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Закрыть список\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Закрыть остальные\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Закрыть остальные сверху\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Закрыть остальные снизу\",\n    \"CMD_FILE_SAVE\"                       : \"Сохранить\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Сохранить все\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Сохранить как\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Настройки проекта\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Переименовать\",\n    \"CMD_FILE_DELETE\"                     : \"Удалить\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Установить расширение\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Менеджер расширений\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Обновить дерево проекта\",\n    \"CMD_QUIT\"                            : \"Выход\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Выход\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Правка\",\n    \"CMD_UNDO\"                            : \"Отменить\",\n    \"CMD_REDO\"                            : \"Повторить\",\n    \"CMD_CUT\"                             : \"Вырезать\",\n    \"CMD_COPY\"                            : \"Копировать\",\n    \"CMD_PASTE\"                           : \"Вставить\",\n    \"CMD_SELECT_ALL\"                      : \"Выделить все\",\n    \"CMD_SELECT_LINE\"                     : \"Выделить строку\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Разбить выделенное на линии\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Добавить курсор к следующей линии\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Добавить курсор к предыдущей линии\",\n    \"CMD_INDENT\"                          : \"Сделать отступ\",\n    \"CMD_UNINDENT\"                        : \"Убрать отступ\",\n    \"CMD_DUPLICATE\"                       : \"Дублировать\",\n    \"CMD_DELETE_LINES\"                    : \"Удалить строку\",\n    \"CMD_COMMENT\"                         : \"Вкл./выкл. строчный комментарий\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Вкл./выкл. блочный комментарий\",\n    \"CMD_LINE_UP\"                         : \"Переместить строку вверх\",\n    \"CMD_LINE_DOWN\"                       : \"Переместить строку вниз\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Открыть строку сверху\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Открыть строку снизу\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Автоматически закрывать скобки\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Показывать подсказки в коде\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Поиск\",\n    \"CMD_FIND\"                            : \"Найти\",\n    \"CMD_FIND_NEXT\"                       : \"Найти след.\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Найти пред.\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Найти все и выделить\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Добавить следущее найденное к выделению\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Пропустить и добавить следующее найденное\",\n    \"CMD_FIND_IN_FILES\"                   : \"Найти в файлах\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Найти в\\u2026\",\n    \"CMD_REPLACE\"                         : \"Заменить\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Заменить в файлах\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Заменить в\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Вид\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Скрыть боковую панель\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Показать боковую панель\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Увеличить размер шрифта\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Уменьшить размер шрифта\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Восстановить размер шрифта\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Прокрутить на строку вверх\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Прокрутить на строку вниз\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Номера строк\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Подсвечивать активную строку\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Заворачивать строки\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Подсвечивать в Live Preview\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Анализировать при сохранении\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Сортировать по порядку добавления\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Сортировать по имени\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Сортировать по типу\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Автоматическая сортировка\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Навигация\",\n    \"CMD_QUICK_OPEN\"                      : \"Быстрое открытие\",\n    \"CMD_GOTO_LINE\"                       : \"Перейти к строке\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Быстрый поиск определения\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Перейти к первой ошибке/предупреждению\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Быстрое редактирование\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Быстрая документация\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Предыдущее совпадение\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Следующее совпадение\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Новое правило\",\n    \"CMD_NEXT_DOC\"                        : \"Следующий документ\",\n    \"CMD_PREV_DOC\"                        : \"Предыдущий документ\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Показать в дереве проекта\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Показать в Проводнике\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Показать в Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Показать в операционной системе\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Помощь\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Проверить наличие обновлений\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Как использовать {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"Поддержка {APP_NAME}\",\n    \"CMD_SUGGEST\"                         : \"Предложить улучшение\",\n    \"CMD_RELEASE_NOTES\"                   : \"Примечания к выпуску\",\n    \"CMD_GET_INVOLVED\"                    : \"Принять участие в проекте\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Показать директорию расширений\",\n    \"CMD_HOMEPAGE\"                        : \"Домашняя страница {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} в Twitter\",\n    \"CMD_ABOUT\"                           : \"О {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Открыть файл настроек\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"Экспериментальная сборка\",\n    \"DEVELOPMENT_BUILD\"                    : \"Сборка для разработчиков\",\n    \"RELOAD_FROM_DISK\"                     : \"Перезагрузить с диска\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Оставить изменения в редакторе\",\n    \"CLOSE_DONT_SAVE\"                      : \"Закрыть (Не сохранять)\",\n    \"RELAUNCH_CHROME\"                      : \"Перезапустить Chrome\",\n    \"ABOUT\"                                : \"О программе\",\n    \"CLOSE\"                                : \"Закрыть\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Внимание, правила и условия, относящиеся к стороннему программному обеспечению находятся на <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> и включены здесь в качестве ссылки.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Документация и исходный код находятся на <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Сделано с \\u2764 и на JavaScript:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Длинный список инженеров, но, к сожалению, в данный момент мы не можем его показать.\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs and the MDN graphical logo are licensed under a Creative Commons Attribution license, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Новая сборка {APP_NAME} доступна! Нажмите здесь для подробностей.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Доступно обновление\",\n    \"UPDATE_MESSAGE\"                       : \"Эй, новая версия {APP_NAME} доступна. Вот некоторые из новых функций:\",\n    \"GET_IT_NOW\"                           : \"Установить немедленно!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Настройки проекта для: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Базовый URL для Live Preview\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"(оставьте пустым для просмотра локальных файлов)\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Протокол {0} не поддерживается Live Preview &mdash; пожалуйста, используйте http: или https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Базовый URL не может содержать такие параметры поиска как \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Базовый URL не может содержать такие хеши как \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Специальные символы как '{0}' должны быть %-экранированы.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Неизвестная ошибка при синтаксическом разборе основного URL\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Новое правило\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Установить\",\n    \"UPDATE\"                               : \"Обновить\",\n    \"REMOVE\"                               : \"Удалить\",\n    \"OVERWRITE\"                            : \"Переустановить\",\n    \"CANT_REMOVE_DEV\"                      : \"Расширения, установленные в директории \\\"dev\\\", должны удаляться вручную.\",\n    \"CANT_UPDATE\"                          : \"Это обновление не совместимо с данной версией {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Расширения, установленные в директории \\\"dev\\\", не могут быть автоматически обновлены.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Установка расширения\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Обновление расширения\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL расширения\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL zip-файла расширения или репозитория GitHub\",\n    \"INSTALLING_FROM\"                      : \"Установка расширения с {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Установка завершена успешно!\",\n    \"INSTALL_FAILED\"                       : \"Не удалось установить.\",\n    \"CANCELING_INSTALL\"                    : \"Отмена\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Отмена установки занимает продолжительное время. Возможно по причине внутренней ошибки.\",\n    \"INSTALL_CANCELED\"                     : \"Установка отменена.\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Скачанный файл не является zip-файлом.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Файл package.json некорректен (ошибка: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Файл package.json не содержит имени пакета.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} не является корректным именем пакета.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Файл package.json не содержит версии пакета.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Версия пакета ({0}) некорректна.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Строка совместимости с {APP_NAME} ({0}) некорректна.\",\n    \"DISALLOWED_WORDS\"                     : \"Слова ({1}) недопустимы в поле {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Расширение несовместимо с данной версией {APP_NAME}. Расширение установлено в директории disabled.\",\n    \"MISSING_MAIN\"                         : \"Пакет не содержит файл main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Установка данного пакета перезапишет установленное расширение. Перезаписать существующее расширение?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Версия данного пакета совпадает с версией установленного расширения. Перезаписать существующее расширение?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Версия данного пакета ({0}) старее версии уставновленного расширения ({1}). Перезаписать существующее расширение?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Внутренняя ошибка: идентификатор закачки уже используется.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Невозможно присоединиться к серверу.\",\n    \"BAD_HTTP_STATUS\"                      : \"Файл не найден на сервере (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Невозможно сохранить закачку во временный файл.\",\n    \"ERROR_LOADING\"                        : \"Ошибка при запуске расширения.\",\n    \"MALFORMED_URL\"                        : \"Некорректный URL. Пожалуйста, убедитесь в его правильности.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL должен использовать протокол http or https.\",\n    \"UNKNOWN_ERROR\"                        : \"Неизвестная внутренняя ошибка.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Менеджер расширений\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Невозможно подсоединиться к каталогу расширений. Пожалуйста, попытайтесь еще раз.\",\n    \"INSTALL_FROM_URL\"                     : \"Установить с URL\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Автор\",\n    \"EXTENSION_DATE\"                       : \"Дата\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Это расширение требует новой версии {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Это расширение работает только с предыдущими версиями {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Версия {0} данного расширения требует новой версии {APP_NAME}. Вы можете установить предыдущую версию расширения{1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Версия {0} данного расширения требует предыдущей версии {APP_NAME}. Вы можете установить предыдущую версию {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Описание отсутвует\",\n    \"EXTENSION_MORE_INFO\"                  : \"Подробнее\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"Ошибка расширения\",\n    \"EXTENSION_KEYWORDS\"                   : \"Ключевые слова\",\n    \"EXTENSION_INSTALLED\"                  : \"Установлено\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Данное расширение было скачано и будет установлено после перегрузки {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Поиск\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Подробнее\",\n    \"BROWSE_EXTENSIONS\"                    : \"Просмотреть расширения\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Удалить расширение\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Невозможно удалить одно или более расширений: {0}. {APP_NAME} продолжит перезагрузку.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Обновить расширение\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Невозможно обновить одно или более расширений: {0}. {APP_NAME} продолжит перезагрузку.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Отмечено для удаления\",\n    \"UNDO_REMOVE\"                          : \"Не удалять\",\n    \"MARKED_FOR_UPDATE\"                    : \"Отмечено для обновления\",\n    \"UNDO_UPDATE\"                          : \"Не обновлять\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Изменить расширения\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Для обновления или удаления расширений, {APP_NAME} будет перезагружен. Вам будет предложено сохранить несохраненные изменения.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Удалить расширения и перегрузиться\",\n    \"CHANGE_AND_RELOAD\"                    : \"Изменить расширения и перегрузиться\",\n    \"UPDATE_AND_RELOAD\"                    : \"Обновить расширения и перегрузиться\",\n    \"PROCESSING_EXTENSIONS\"                : \"Обработка изменений в расширениях\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Невозможно удалить расширение {0}, оно не было установлено.\",\n    \"NO_EXTENSIONS\"                        : \"Нет установленных расширений.<br>Перейдите на закладку Доступные чтобы начать работу с расширениями.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Не найдено расширений по критерию поиска.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Будьте осторожны при установке расширений из неизвестных источников.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Установленные\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Доступные\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Обновления\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Совпадений не найдено.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Существующих правил CSS соответвующих выделенному тексту не определено. <br> Выберите \\\"Новое правило\\\" чтобы создать новое.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Ваш проект не содержит таблиц стилей (stylesheets).<br>Создайте его чтобы добавить правила CSS.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"наибольший размер\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"пикселей\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Отладка\",\n    \"ERRORS\"                                    : \"Ошибки\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Показать инструменты разработчика\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Перезагрузить с расширениями\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Перезагрузить без расширений\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Новое окно {APP_NAME}\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Переключить язык\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Запустить тесты\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Показать данные о производительности\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Включить отладчик node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Отображать состояние node в консоли\",\n    \"CMD_RESTART_NODE\"                          : \"Перезапустить node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Показывать ошибки в строке состояния\",\n\n    \"LANGUAGE_TITLE\"                            : \"Изменить язык\",\n    \"LANGUAGE_MESSAGE\"                          : \"Пожалуйста, выберите желаемый язык из списка ниже:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Перезагрузить {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Отмена\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"По умолчанию\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Время\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Прогресс\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Передвинуть выделенную точку<br><kbd class='text'>Shift</kbd> Передвинуться на десять единиц<br><kbd class='text'>Tab</kbd> Переключиться между точками\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Увеличить или уменьшить шаги<br><kbd>←</kbd><kbd>→</kbd> 'Начало' или 'Конец'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Старое значение <code>{0}</code> некорректно, отображаемая функция была заменена на <code>{1}</code>. Документ будет обновлен с первой правкой.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Текущий цвет\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Оригинальный цвет\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa формат\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex формат\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa формат\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Использовано {1} раз)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Использовано {1} раза)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Перейти к определению\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Показывать подсказки по аргументам функции\",\n    \"NO_ARGUMENTS\"                              : \"<нет аргументов>\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Быстрый просмотр при наведении\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Предыдущие проекты\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Подробнее\\u2026\",\n\n    //extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Свернуть все\",\n    \"EXPAND_ALL\"                    : \"Развернуть все\",\n    \"COLLAPSE_CURRENT\"              : \"Свернуть текущий\",\n    \"EXPAND_CURRENT\"                : \"Развернуть текущий\"\n});\n"
  },
  {
    "path": "src/nls/ru/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"ru/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_ru/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.ru\"\n});\n"
  },
  {
    "path": "src/nls/sk/strings.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Chyby\n     */\n\n    // Všeobecné chyby súboru\n    \"GENERIC_ERROR\"                     : \"(chyba {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Súbor nenájdený.\",\n    \"NOT_READABLE_ERR\"                  : \"Súbor sa nedá čítať.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Cieľový adresár nemôže byť zmenený.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Práva vám neumožňujú robiť zmeny.\",\n    \"FILE_EXISTS_ERR\"                   : \"Súbor alebo adresár už existuje.\",\n    \"FILE\"                              : \"súbor\",\n    \"DIRECTORY\"                         : \"adresár\",\n\n    // Reťazce chyby projektu\n    \"ERROR_LOADING_PROJECT\"             : \"Chyba pri otváraní projektu\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Nastala chyba pri zobrazení dialógu otvorenia súboru. (chyba {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Nastala chyba pri načítaní adresára <span class='dialog-filename'>{0}</span>. (chyba {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Nastala chyba pri načítaní obsahu adresára <span class='dialog-filename'>{0}</span>. (chyba {1})\",\n\n    // Reťazce chýb pri otváraní/ukladaní súboru\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Chyba pri otváraní súboru\",\n    \"ERROR_OPENING_FILE\"                : \"Nastala chyba pri otváraní súboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Nastala chyba pri otváraní nasledujúcich súborov:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Chyba pri načítaní zmien z disku\",\n    \"ERROR_RELOADING_FILE\"              : \"Nastala chyba pri načítaní súboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Chyba pri ukladaní súboru\",\n    \"ERROR_SAVING_FILE\"                 : \"Nastala chyba pri ukladaní súboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Chyba pri premenovaní súboru\",\n    \"ERROR_RENAMING_FILE\"               : \"Nastala chyba pri premenovaní súboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Chyba pri zmazaní súboru\",\n    \"ERROR_DELETING_FILE\"               : \"Nastala chyba pri zmazaní súboru <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Neplatný {0} názov\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Názvy súboru nesmú obsahovať nasledujúce znaky: {0} alebo používať rezervované systémové slová.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Chyba pri vytváraní súboru {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Nastala chyba pri vytváraní súboru {0} <span class='dialog-filename'>{1}</span>. {2}\",\n\n    // Reťazce chýb aplikácie\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Hopa! {APP_NAME} zatiaľ nejde spustiť v prehliadači.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} je vytvorený HTML, ale teraz pracuje ako desktopová aplikácia, takže ho môžete využiť na úpravu lokálnych súborov. Prosím, používajte shell aplikácie v <b>github.com/adobe/brackets-shell</b> repozitári pre spustenie {APP_NAME}.\",\n\n    // Reťazce chýb indexovaní súboru\n    \"ERROR_MAX_FILES_TITLE\"             : \"Chyba pri indexovaní súborov\",\n    \"ERROR_MAX_FILES\"                   : \"Bol indexovaný maximálny počet súborov. Akcie pre vyhľadávanie súborov podľa indexu nemusia fungovať správne.\",\n\n    // Reťazce chýb pri živom náhlade\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Chyba pri spúšťaní prehliadača\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Prehliadač Google Chrome nebol nájdený. Prosím uistite sa, že je nainštalovaný.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Nastala chyba pri spúšťaní prehliadača. (chyba {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Chyba pri živom náhľade\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Pripojovanie k prehliadaču\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"V prípade využitia živého náhľadu je treba reštarovať Chrome zo zapnutým vzdialeným ladením.<br /><br />Chceli by ste reštartovať Chrome a zapnúť vzdialené ladenie?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Nie je možné načítať stránku zo živým náhľadom\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Otvorte HTML súbor pre spustenie živého náhľadu.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Pre spustenie živého náhľadu zo súborom na serveri, musíte špecifikovať URL pre tento projekt.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Chyba pri spúšťaní HTTP severa pre súbory živého náhľadu. Prosím, skúste to znovu.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Vitajte v živom náhľade!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Živý náhľad pripája {APP_NAME} k vášmu prehliadaču. Spustí náhľad vášho HTML súboru v prehliadači, potom aktualizuje náhľad okamžite, vždy keď upravíte svoj kód.<br /><br />V tejto verzii {APP_NAME}, živý náhľad funguje iba s <strong>Google Chrome</strong> a aktualizuje keď upravíte <strong>CSS súbory</strong>. Zmeny pre HTML alebo JavaScript súbory sú automaticky načítané, keď súbor uložíte.<br /><br />(Túto správu uvidíte iba jeden krát.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Pre viac informácií pozrite <a class=\\\"clickable-link\\\" data-href=\\\"{0}\\\">Riešenie chýb pri pripojení do živého náhľadu</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Živý náhľad\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Živý náhľad: Pripájanie\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Živý náhľad: Inicializácia\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Odpojenie živého náhľadu\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Živý náhľad: Kliknite pre odpojenie (Uložte súbor)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Živý náhľad bol zrušený kvôli tomu, že boli otvorené vývojárske nástroje v prehliadači\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Živý náhľad bol zrušený kvôli tomu, že stránka bola zatvorená v prehliadači\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Živý náhľad bol zrušený kvôli tomu, že prehliadač odkazoval na stránku, ktorá nie je súčasťou aktuálneho projektu\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Živý náhľad bol zrušený pre neznámy dôvod ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Uložiť zmeny\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Chcete uložiť zmeny, ktoré ste spravili v dokumente <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Chcete uložiť zmeny v následujúcich súboroch?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Externé zmeny\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Potvrdte odstránenie\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Ste si istý zmazaním priečinku <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Súbor odstránený\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> bol upravený na disku, ale tiež ma neuložené zmeny in {APP_NAME}.<br /><br />Ktorú verziu chcete ponechať?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> bol zmazaný z disku, ale zmeny sa neuložili v {APP_NAME}.<br /><br />Chcete uložiť zmeny?\",\n\n    // Find, Replace, Find in Files\n    \"BUTTON_YES\"                        : \"Áno\",\n    \"BUTTON_NO\"                         : \"Nie\",\n    \"BUTTON_REPLACE\"                    : \"Nahradiť\",\n\n    \"OPEN_FILE\"                         : \"Otvoriť súbor\",\n    \"SAVE_FILE_AS\"                      : \"Uložiť súbor\",\n    \"CHOOSE_FOLDER\"                     : \"Vybrať adresár\",\n\n    \"RELEASE_NOTES\"                     : \"Poznámky k verzii\",\n    \"NO_UPDATE_TITLE\"                   : \"Všetko je aktuálne!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Máte najnovšiu verziu {APP_NAME}.\",\n\n    \"FIND_IN_FILES_SCOPED\"              : \"v <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"v projekte\",\n    \"FIND_IN_FILES_FILE\"                : \"súbor\",\n    \"FIND_IN_FILES_FILES\"               : \"súbory\",\n    \"FIND_IN_FILES_MATCH\"               : \"zhoda\",\n    \"FIND_IN_FILES_MATCHES\"             : \"zhody\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Cez \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"Súbor: <span class='dialog-filename'>{0}</span>\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Problém pri získavaní informácií o aktualizácii\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Nastal problém pri získavaní aktuálnych informácií zo servera. Prosím uistite sa, že ste pripojený do internetu a skúste znovu.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Načítavanie\\u2026\",\n    \"UNTITLED\"          : \"bez názvu\",\n    \"WORKING_FILES\"     : \"Otvorené súbory\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Medzerník\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Riadok {0}, Stĺpec {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Vybraný {0} stĺpec\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Vybraných {0} stĺpcov\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Vybraný {0} riadok\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Vybraných {0} riadkov\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Kliknite pre zmenu osadenia na medzery\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Kliknite pre zmenu odsadenia na tabulátory\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Kliknite pre zmenu počet medzier použitých pre odsadenie\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Kliknite pre zmenu šírky tabulátora\",\n    \"STATUSBAR_SPACES\"                      : \"Medzery\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Velkosť tabulátora\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"Riadok: \\u2014 {0}\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"Riadky: \\u2014 {0}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // Príkazy v menu Súbor\n    \"FILE_MENU\"                           : \"Súbor\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Nový\",\n    \"CMD_FILE_NEW\"                        : \"Nový súbor\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Nový adresár\",\n    \"CMD_FILE_OPEN\"                       : \"Otvoriť\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Pridať do pracovnej sady\",\n    \"CMD_OPEN_FOLDER\"                     : \"Otvoriť adresár\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Zatvoriť\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Zatvoriť všetko\",\n    \"CMD_FILE_SAVE\"                       : \"Uložiť\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Uložiť všetko\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Uložiť ako\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Živý náhľad\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Zvýraznenie živého náhľadu\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Nastavenia projektu\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Premenovať\",\n    \"CMD_FILE_DELETE\"                     : \"Zmazať\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Inštalovať rozšírenia\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Správca rozšírení\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Obnoviť strom súborov\",\n    \"CMD_QUIT\"                            : \"Koniec\",\n    // Použité v natívnom menu Súborov na Windows\n    \"CMD_EXIT\"                            : \"Koniec\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Upraviť\",\n    \"CMD_UNDO\"                            : \"Späť\",\n    \"CMD_REDO\"                            : \"Znovu\",\n    \"CMD_CUT\"                             : \"Vystrihnúť\",\n    \"CMD_COPY\"                            : \"Kopírovať\",\n    \"CMD_PASTE\"                           : \"Vložiť\",\n    \"CMD_SELECT_ALL\"                      : \"Vybrať všetko\",\n    \"CMD_SELECT_LINE\"                     : \"Vybrať riadok\",\n    \"CMD_FIND\"                            : \"Vyhľadať\",\n    \"CMD_FIND_IN_FILES\"                   : \"Vyhľadať v súboroch\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Vyhľadať v\\u2026\",\n    \"CMD_FIND_NEXT\"                       : \"Vyhľadať nasledujúci\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Vyhľadať predchádzajúci\",\n    \"CMD_REPLACE\"                         : \"Nahradiť\",\n    \"CMD_INDENT\"                          : \"Odsadiť\",\n    \"CMD_UNINDENT\"                        : \"Vrátiť odsadenie\",\n    \"CMD_DUPLICATE\"                       : \"Duplikovať\",\n    \"CMD_DELETE_LINES\"                    : \"Zmazať riadok\",\n    \"CMD_COMMENT\"                         : \"Riadkový komentár\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Blokový komentár\",\n    \"CMD_LINE_UP\"                         : \"Posunúť riadok hore\",\n    \"CMD_LINE_DOWN\"                       : \"Posunúť riadok dole\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"O riadok vyššie\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"O riadok nižšie\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Uzatvárať zátvorky\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Zobraziť tipy\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Zobraziť\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Skryť bočný panel\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Zobraziť bočný panel\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Zväčšiť veľkosť písma\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Zmenšiť veľkosť písma\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Obnoviť veľkosť písma\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Posunúť o riadok hore\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Posunúť o riadok dole\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Čísla riadkov\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Zvýrazniť aktívny riadok\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Zalomenie riadkov\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Usporiadať podľa dátumu\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Usporiadať podľa mena\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Usporiadať podľa typu\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatické usporiadanie\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigácia\",\n    \"CMD_QUICK_OPEN\"                      : \"Rýchle otvorenie\",\n    \"CMD_GOTO_LINE\"                       : \"Prejsť na riadok\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Prejsť na definíciu\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Rýchla úprava\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Rýchla dokumentácia\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Predchádzajúca zhoda\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Ďalšia zhoda\",\n    \"CMD_NEXT_DOC\"                        : \"Následujúci dokument\",\n    \"CMD_PREV_DOC\"                        : \"Predchádzajúci dokument\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Zobraziť stromovú štruktúru\",\n    \"CMD_SHOW_IN_OS\"                      : \"Zobraziť v OS\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Nápoveda\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Skontrolovať aktualizácie\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Ako používať {APP_NAME}\",\n    \"CMD_RELEASE_NOTES\"                   : \"Poznámky o verzii\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Zobraziť priečinok s doplnkami\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} na Twitteri\",\n    \"CMD_ABOUT\"                           : \"O {APP_TITLE}\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimentálna verzia\",\n    \"DEVELOPMENT_BUILD\"                    : \"vývojová verzia\",\n    \"OK\"                                   : \"OK\",\n    \"DONT_SAVE\"                            : \"Neukladať\",\n    \"SAVE\"                                 : \"Uložiť\",\n    \"CANCEL\"                               : \"Zrusiť\",\n    \"DELETE\"                               : \"Odstrániť\",\n    \"RELOAD_FROM_DISK\"                     : \"Načítať z disku\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Ponechať zmeny v editore\",\n    \"CLOSE_DONT_SAVE\"                      : \"Zatvoriť (neukladať)\",\n    \"RELAUNCH_CHROME\"                      : \"Reštartovať Chrome\",\n    \"ABOUT\"                                : \"O aplikácii\",\n    \"CLOSE\"                                : \"Zatvoriť\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Oznámenia, podmienky týkajúce sa software tretích strán sú umiestnené na <a class=\\\"clickable-link\\\" data-href=\\\"{ADOBE_THIRD_PARTY}\\\">{ADOBE_THIRD_PARTY}</a> za začlenené prostredníctvom odkazu tu.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentácia a zdrojový kód na <a class=\\\"clickable-link\\\" data-href=\\\"https://github.com/adobe/brackets/\\\">https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Vytvorené s \\u2764 a JavaScript týmito ľuďmi:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Veľa ľudí (ale práve máme problém s načítaním údajov).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs a the MDN grafické logo sú licencované pod Creative Commons Attribution license, <a class=\\\"clickable-link\\\" data-href=\\\"{MDN_DOCS_LICENSE}\\\">CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Je dostupná nová verzia {APP_NAME}! Kliknite sem pre viac detailov.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Dostupná aktualizácia\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, je dostupná nová verzia {APP_NAME}. Zoznam niektorých nových vylepšení:\",\n    \"GET_IT_NOW\"                           : \"Stiahnuť!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Nastavenia projketu pre: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Živý náhľad URL\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Pre použitie lokálneho servera, vložte URL v tvare http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Protokol {0} nie je podporovaný Živým náhľadom&mdash;prosím použite http: alebo https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL adresa nemôže obsahovať výrazy pre hľadanie ako \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL adresa nemôže obsahovať znaky ako \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Zvláštné znaky ako '{0}' musia byť %-enkódované.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Neznáma chyba pri spracovávaní URL\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Inštalovať\",\n    \"UPDATE\"                               : \"Aktualizovať\",\n    \"REMOVE\"                               : \"Odstrániť\",\n    \"OVERWRITE\"                            : \"Prepísať\",\n    \"CANT_REMOVE_DEV\"                      : \"Doplnky v \\\"dev\\\" priečinku musia byť manuálne odstránené.\",\n    \"CANT_UPDATE\"                          : \"Aktualizácia nie je kompatibilná s touto verziou {APP_NAME}.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Inštalovať doplnok\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Aktualizovať doplnok\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL adresa doplnku\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL adresa zip súboru doplnku alebo Git repozitár\",\n    \"INSTALLING_FROM\"                      : \"Inštalovanie doplnku z {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Inštalácia bola úspešná!\",\n    \"INSTALL_FAILED\"                       : \"Inštalácia sa nepodarila.\",\n    \"CANCELING_INSTALL\"                    : \"Rušenie\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Zrušenie inštalácie trvá dlho. Mohlo prísť k internej chybe.\",\n    \"INSTALL_CANCELED\"                     : \"Inštalácia zrušená.\",\n    // Tieto musia odpovedať chybovým hláseniam v ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Stiahnutý obsah nie je platný zip súbor.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Súbor package.json nie je platný (chyba bola: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Súbor package.json nešpecifikuje názov balíku.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} je neplatný názov balíka.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Súbor package.json nešpecifikuje verziu súboru.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Balík verzie ({0}) je neplatný.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Reťazec kompatibility ({0}) pre {APP_NAME} je neplatný.\",\n    \"DISALLOWED_WORDS\"                     : \"Slová ({1}) nie sú povolené v {0} poli.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Balík nie je kompatibilný s verziou {APP_NAME}. Nájdete ho v zložke vypnuté doplnky.\",\n    \"MISSING_MAIN\"                         : \"Balík nemá žiadny súbor main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Inštalácia tohto balíku prepíše nainštalovaný doplnok. Prepísať starý doplnok?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Tento balík je rovnakej verzie ako aktuálne nainštalovaný. Prepísať existujúci doplnok?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Tento balík je verzie {0}, ktorá je staršia ako aktuálne nainštalovaná ({1}). Prepísať existujúci doplnok?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Interná chyba: ID sťahovania sa už používa.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Nie je možné pripojiť sa k serveru.\",\n    \"BAD_HTTP_STATUS\"                      : \"Súbor nebol nájdený na serveri (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Nie je možné uložiť do dočasného súboru.\",\n    \"ERROR_LOADING\"                        : \"Pri spúšťaní doplnku prišlo k chybe.\",\n    \"MALFORMED_URL\"                        : \"URL adresa je chybná. Prosím skontrolujte ju, či je zadaná správne.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL adresa musí byť http alebo https.\",\n    \"UNKNOWN_ERROR\"                        : \"Neznáma chyba\",\n    // Pre NOT_FOUND_ERR, pozri všeobecné reťazce vyššie\n    \"EXTENSION_MANAGER_TITLE\"              : \"Správca doplnkov\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Nie je možné získať prístup k registrom doplnkov. Prosím, skúste to znovu neskôr.\",\n    \"INSTALL_FROM_URL\"                     : \"Inštalovať z URL\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Autor\",\n    \"EXTENSION_DATE\"                       : \"Dátum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Tento doplnok vyžaduje novšiu verziu {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Tento doplnok momentálne funguje iba zo staršími verziami {APP_NAME}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Bez popisu\",\n    \"EXTENSION_MORE_INFO\"                  : \"Viac informácií...\",\n    \"EXTENSION_ERROR\"                      : \"Chyba doplnku\",\n    \"EXTENSION_KEYWORDS\"                   : \"Kľúčové slová\",\n    \"EXTENSION_INSTALLED\"                  : \"Nainštalované\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Aktualizácia tohto doplnku bola stiahnutá a bude nainštalovaná keď ukončíte {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Hľadať\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Viac\",\n    \"BROWSE_EXTENSIONS\"                    : \"Prechádzať doplnky\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Odstrániť doplnok\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Nie je možné odstrániť jeden alebo viac doplnkov: {0}. {APP_NAME} bude ukončená.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Aktualizovať doplnok\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Nie je možné aktualizovať jeden alebo viac doplnkov: {0}. {APP_NAME} bude ukončená.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Označené pre odstránenie\",\n    \"UNDO_REMOVE\"                          : \"Späť\",\n    \"MARKED_FOR_UPDATE\"                    : \"Označené pre aktualizáciu\",\n    \"UNDO_UPDATE\"                          : \"Späť\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Nie je možné odstrániť doplnok {0}, pretože nebol nainštalovaný\",\n    \"NO_EXTENSIONS\"                        : \"Nie sú nainštalované žiadne doplnky.<br>Click on the Available tab above to get started.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Nenašiel sa žiadny doplnok.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Buďte opatrní pri inštalácií doplnkov z neznámeho zdroja.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Nainštalované\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Dostupné\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Aktualizácie\",\n\n    /**\n     * Mená jednotiek\n     */\n\n    \"UNIT_PIXELS\"                          : \"pixely\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Ladenie\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Zobraziť vývojárske nástroje\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Reštartovať {APP_NAME}\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nové {APP_NAME} okno\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Zmeniť jazyk\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Spustiť testy\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Zobraziť údaje o výkone\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Zapnúť Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Uložiť stav Node do konzole\",\n    \"CMD_RESTART_NODE\"                          : \"Reštartovať Node\",\n\n    \"LANGUAGE_TITLE\"                            : \"Zmeniť jazyk\",\n    \"LANGUAGE_MESSAGE\"                          : \"Jazyk:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Reštartovať {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Zrušiť\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Predvolený v systéme\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Aktuálna farba\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Pôvodná farba\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa formát\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex formát\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa formát\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Použité {1} krát)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Použité {1} krát)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Prejsť na definíciu\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Ukázať pomôcku parametra\",\n    \"NO_ARGUMENTS\"                              : \"<žiadne parametre>\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Rýchly náhľad\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Viac\"\n});\n"
  },
  {
    "path": "src/nls/sr/strings-app.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // product-specific strings\n    \"APP_NAME\"                             : \"Заграде\"\n});\n"
  },
  {
    "path": "src/nls/sr/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(грешка {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Непостојећа датотека.\",\n    \"NOT_READABLE_ERR\"                  : \"Датотека не може бити учитана.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Датотеке веће од {0} MB се не могу отворити у {APP_NAME}-у.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Циљани директоријум не може бити измењен.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Тренутна овлашћења Вам не дозвољавају да правите измене.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Ова датотека је била измењена ван {APP_NAME}-а.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} тренутно подржава искључиво текстуалне датотеке које су енкодиране у UTF-8 формату.\",\n    \"FILE_EXISTS_ERR\"                   : \"Датотека или директоријум већ постоји.\",\n    \"FILE\"                              : \"датотека\",\n    \"FILE_TITLE\"                        : \"Датотека\",\n    \"DIRECTORY\"                         : \"директоријум\",\n    \"DIRECTORY_TITLE\"                   : \"Директоријум\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Имена директоријума\",\n    \"FILENAMES_LEDE\"                    : \"Имена датотека\",\n    \"FILENAME\"                          : \"Име датотеке\",\n    \"DIRECTORY_NAME\"                    : \"Име директоријума\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Грешка приликом учитавања пројекта\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Дошло је до грешке приликом приказивања дијалога за отварање датотеке. (грешка {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Дошло је до грешке приликом покушаја да се учита директоријум <span class='dialog-filename'>{0}</span>. (грешка {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Дошло је до грешке приликом ишчитавања садржаја директоријума <span class='dialog-filename'>{0}</span>. (грешка {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Грешка при отварању датотеке\",\n    \"ERROR_OPENING_FILE\"                : \"Дошло је до грешке приликом покушаја да се отвори датотека <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Дошло је до грешке приликом покушаја да се отворе следеће датотеке:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Грешка при поновном учитавању измена са диска\",\n    \"ERROR_RELOADING_FILE\"              : \"Дошло је до грешке приликом покушаја да се поново учита датотека <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Грешка при чувању датотеке\",\n    \"ERROR_SAVING_FILE\"                 : \"Дошло је до грешке приликом покушаја да се сачува датотека <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Грешка приликом преименовања датотеке {0}\",\n    \"ERROR_RENAMING_FILE\"               : \"Дошло је до грешке приликом покушаја да се преименује датотека {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Грешка при брисању датотеке {0}\",\n    \"ERROR_DELETING_FILE\"               : \"Дошло је до грешке приликом покушаја да се обрише датотека {2} <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Име {0} није валидно\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Име {0} не сме садржати системски резервисане речи, не сме се завршити тачком (.) или користити неки од следећих карактера: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"Датотека или директоријум са именом <span class='dialog-filename'>{0}</span> већ постоји.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Грешка при креирању {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Дошло је до грешке приликом покушаја да се креира {0} <span class='dialog-filename'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Директоријум се не може учитавати у исто време када и остале датотеке.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Грешка приликом ишчитавања корисничке мапе пречица на тастатури\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Ваша мапа пречица на тастатури није валидан JSON. Датотека ће бити отворена како бисте исправили формат.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Ваша мапа пречица на тастатури није валидна UTF-8 енкодирана текстуална датотека и не може се учитати\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Не можете поново доделити пречице овим командама: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Не можете доделити ове пречице: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Додајете више пречица на тастатури за ове команде: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Имате више комбинација за ове пречице: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Ове пречице нису валидне: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Додајете пречице на тастатури непостојећим командама: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Грешка приликом ишчитавања подешавања\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Ваша датотека са подешавањима није валидан JSON. Датотека ће бити отворена како бисте исправили формат. Биће неопходно да поново покренете {APP_NAME} како би измене биле примењене.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Упс! {APP_NAME} још увек не ради у веб претраживачу.\",\n    \"ERROR_IN_BROWSER\"                  : \"Апликација {APP_NAME} је направљена помоћу HTML-а, али тренутно ради као \\\"desktop\\\" апликација па је можете користити за измену локалних датотека. Молимо Вас користите \\\"application shell\\\" на <b>github.com/adobe/brackets-shell</b> репозиторијуму за покретање {APP_NAME}-а.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Грешка приликом индексирања датотека\",\n    \"ERROR_MAX_FILES\"                   : \"Пројекат садржи више од 30.000 датотека. Делови апликације који врше обраду над више датотека могу постати неактивни или се понашати као да је пројекат празан. <a href='https://github.com/adobe/brackets/wiki/Large-Projects'>Прочитајте више о раду са великим пројектима</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Грешка при покретању претраживача\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Google Chrome претраживач није пронађен. Молимо потврдите да је инсталиран.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Грешка приликом покретања претраживача. (error {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Грешка у живом приказу\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Повезивање са веб претраживачем\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Да би се живи приказ повезао, потребно је да поново покренете Chrome са укљученим подешавањима за \\\"remote debugging\\\".<br /><br />Да ли желите поново да покренете Chrome са укљученим подешавањима за \\\"remote debugging\\\"?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Није могуће учитати страницу са живим приказом.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Отворите HTML датотеку како бисте били сигурни да постоји index.html датотека у Вашем пројекту како бисте покренули живи приказ.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"За покретање живог приказа са датотеком која је \\\"server-side\\\", морате навести основну URL адресу за овај пројекат.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Грешка приликом покретања HTTP сервера за \\\"живе\\\" развојне датотеке. Молимо покушајте поново.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Добро дошли у живи приказ!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Живи приказ повезује {APP_NAME} са Вашим веб претраживачем. Он покреће Вашу HTML датотеку у претраживачу, а потом ажурира приказ тренутно док Ви мењате Ваш кôд.<br /><br />У овој раној верзији {APP_NAME}-a, живи приказ ради једино у <strong>Google Chrome</strong> претраживачу и ажурира приказ док мењате <strong>CSS или HTML датотеке</strong>. За освежавање приказа приликом измена у JavaScript датотекама потребно је да сачувате Ваше измене.<br /><br />(Ова порука ће се приказати само једном.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"За више информација, погледајте <a href='{0}' title='{0}'>Отклањање грешака у конекцији приликом развоја уживо</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Живи приказ\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Живи приказ: Успостављање конекције\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Живи приказ: Иницијализација\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Прекини конекцију са живим приказом\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Живи приказ (сачувај датотеку за освежавање)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Живи приказ (не освежава се због грешке у синтакси)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Живи приказ је отказан јер су развојни алати били отворени у претраживачу\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Живи приказ је отказан јер је страница затворена у претраживачу\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Живи приказ је отказан јер је претраживач отишао на страницу која није део тренутног пројекта\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Живи приказ је отказан из непознатог разлога ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Сачувај измене\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Да ли желите да сачувате измене које сте направили у документу <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Да ли желите да сачувате Ваше измене над следећим датотекама?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Екстерне измене\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Потврди брисање\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Да ли сте сигурни да желите обрисати директоријум <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Датотека обрисана\",\n    \"EXT_MODIFIED_WARNING\"              : \"Датотека <span class='dialog-filename'>{0}</span> је измењена на диску.<br /><br />Да ли желите да сачувате датотеку и преснимите те измене?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"Датотека <span class='dialog-filename'>{0}</span> је измењена на диску, али садржи и измене начињене у {APP_NAME}-у.<br /><br />Коју верзију желите да сачувате?\",\n    \"EXT_DELETED_MESSAGE\"               : \"Датотека <span class='dialog-filename'>{0}</span> је обрисана са диска, али садржи несачуване измене начињене у {APP_NAME}-у.<br /><br />Да ли желите да сачувате Ваше измене?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Завршено\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Откажи\",\n    \"DONT_SAVE\"                         : \"Немој сачувати\",\n    \"SAVE\"                              : \"Сачувај\",\n    \"SAVE_AS\"                           : \"Сачувај као\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Сачувај и препиши\",\n    \"DELETE\"                            : \"Обриши\",\n    \"BUTTON_YES\"                        : \"Да\",\n    \"BUTTON_NO\"                         : \"Не\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} од {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Нема резултата\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Пронађи\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"Замени са\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Комплет\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Замени\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Замени\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Следеће поклапање\",\n    \"BUTTON_PREV_HINT\"                  : \"Претходно поклапање\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Иста величина\",\n    \"BUTTON_REGEXP_HINT\"                : \"Регуларни израз\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Замени без опозива\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Зато што је потребно променити више од {0} датотека, {APP_NAME} ће изменити неотворене датотеке на диску.<br />Нећете бити у могућности да опозовете измене у овим датотекама.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Замени без опозива\",\n\n    \"OPEN_FILE\"                         : \"Отвори датотеку\",\n    \"SAVE_FILE_AS\"                      : \"Сачувај датотеку\",\n    \"CHOOSE_FOLDER\"                     : \"Изабери директоријум\",\n\n    \"RELEASE_NOTES\"                     : \"Обавештење о изменама\",\n    \"NO_UPDATE_TITLE\"                   : \"Имате актуелну верзију!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Тренутно поседујете актуелну верзију апликације {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Замени\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"са\",\n    \"FIND_TITLE_LABEL\"                  : \"Пронађено\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} у {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"у <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"у пројекту\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Филтер искључује све датотеке {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"датотеци\",\n    \"FIND_IN_FILES_FILES\"               : \"датотека\",\n    \"FIND_IN_FILES_MATCH\"               : \"поклапање\",\n    \"FIND_IN_FILES_MATCHES\"             : \"поклапања\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Преко \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Притисните Ctrl/Cmd и кликните како бисте раширили/скупили све\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Замени грешке\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Следеће датотеке нису модификоване зато што су измењене након претраге или у њих није било могуће уписивати.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Грешка приликом учитавања информација о новој верзији\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Дошло је до проблема приликом преузимања последњих информација о новој верзији са сервера. Молимо проверите да ли сте повезани на интернет и покушајте поново.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Нови сет искључења\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Немој исључити датотеке\",\n    \"NO_FILE_FILTER\"                    : \"Ниједна датотека није искључена\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Искључи {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Измени\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Измени сет искључења\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Искључи све датотеке и директоријуме који се поклапају са било којим од следећих низова / поднизова или <a href='{0}' title='{0}'>џокер знакова</a>. Enter each string on a new line.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Дај име овом сету искључења (опционо)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"и још {0}\",\n    \"FILTER_COUNTING_FILES\"             : \"Пребројавам датотеке\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Дозвољава {0} од {1} датотека {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Дозвољава свих {0} датотека {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Брза измена није доступна на тренутној позицији курсора\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Брза измена: позиционирајте курсор на једно име класе\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Брза измена: непотпун атрибут класе\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Брза измена: непотпун атрибут идентификатора\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Брза измена: позиционирајте курсор на таг, класу, или идентификатор\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS Времендска функција Брза измена: синтакса није валидна\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Брза измена: позиционирајте курсор на име функције\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Брзи документи нису доступни за тренутну позицију курсора\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Учитавам\\u2026\",\n    \"UNTITLED\"          : \"Неименовано\",\n    \"WORKING_FILES\"     : \"Радне датотеке\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Горе\",\n    \"BOTTOM\"            : \"Доле\",\n    \"LEFT\"              : \"Лево\",\n    \"RIGHT\"             : \"Десно\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Без поделе\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Вертикална подела\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Хоризонтална подела\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Подели едитор вертикално или хоризонтално\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Конфигуриши радни сет\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Већ отворена\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Датотека је већ отворена у другом панелу. {APP_NAME} ће ускоро подржавати отварање исте датотеке у више панела. До тада, датотека ће бити приказана у панелу у коме је већ отворена.<br /><br />(Ова порука ће се приказати само једном.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Линија {0}, колона {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Изабрана {0} колона\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Изабрано {0} колона\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Изабрана {0} линија\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Изабрано {0} линија\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} селекција\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Кликни за коришћење размака приликом увлачења кôда\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Кликни за коришћење таб-ова приликом увлачења кôда\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Кликни за промену броја размака приликом увлачења кôда\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Кликни за промену величине таб-а приликом увлачења кôда\",\n    \"STATUSBAR_SPACES\"                      : \"Размаци:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Величина таб-а:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} линија\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} линија\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Екстензије деактивиране\",\n    \"STATUSBAR_INSERT\"                      : \"УБ\",\n    \"STATUSBAR_OVERWRITE\"                   : \"ПРЕ\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Кликни да промениш мôд курсора из Убаци (УБ) у Препиши (ПРЕ) и обрнуто\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Кликни за измену типа датотеке\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Кликни за приказ/скривање панела са извештајима.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(подразумевано)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Подеси као \\\"подразумевано\\\" за .{0} датотеке\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} грешака\",\n    \"SINGLE_ERROR\"                          : \"1 {0} грешка\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} грешака\",\n    \"NO_ERRORS\"                             : \"Нема {0} грешака - свака част!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Нема пронађених грешака - свака част!\",\n    \"LINT_DISABLED\"                         : \"Детектовање сумњивог кôда искључено\",\n    \"NO_LINT_AVAILABLE\"                     : \"Ниједан детектор сумњивог кôда није доступан за {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Није пронађен сумњив кôд\",\n    \"LINTER_TIMED_OUT\"                      : \"Прекинуто је извршавање {0} након чекања од {1} ms\",\n    \"LINTER_FAILED\"                         : \"Прекинуто је извршавање {0} уз грешку: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Датотека\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Нова\",\n    \"CMD_FILE_NEW\"                        : \"Нова датотека\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Нови директоријум\",\n    \"CMD_FILE_OPEN\"                       : \"Отвори\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Додај у радни сет\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Open Dropped Files\",\n    \"CMD_OPEN_FOLDER\"                     : \"Отвори директоријум\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Затвори\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Затвори све\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Затвори листу\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Затвори остале\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Затвори остале изнад\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Затвори остале испод\",\n    \"CMD_FILE_SAVE\"                       : \"Сачувај\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Сачувај све\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Сачувај као\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Живи приказ\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"На силу обнови Живи приказ\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Подешавање пројекта\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Преименуј\",\n    \"CMD_FILE_DELETE\"                     : \"Обриши\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Инсталирај екстензију\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Менаџер екстензија\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Освежи стабло датотека\",\n    \"CMD_QUIT\"                            : \"Прекини\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Излаз\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Уреди\",\n    \"CMD_UNDO\"                            : \"Опозови\",\n    \"CMD_REDO\"                            : \"Понови\",\n    \"CMD_CUT\"                             : \"Исеци\",\n    \"CMD_COPY\"                            : \"Копирај\",\n    \"CMD_PASTE\"                           : \"Налепи\",\n    \"CMD_SELECT_ALL\"                      : \"Изабери све\",\n    \"CMD_SELECT_LINE\"                     : \"Изабери линију\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Подели селекцију на линије\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Додај курсор следећој линији\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Додај курсор претходној линији\",\n    \"CMD_INDENT\"                          : \"Помери удесно\",\n    \"CMD_UNINDENT\"                        : \"Помери улево\",\n    \"CMD_DUPLICATE\"                       : \"Удвостручи\",\n    \"CMD_DELETE_LINES\"                    : \"Обриши линију\",\n    \"CMD_COMMENT\"                         : \"Додај/уклони линијски коментар\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Додај/уклони блок коментар\",\n    \"CMD_LINE_UP\"                         : \"Помери линију горе\",\n    \"CMD_LINE_DOWN\"                       : \"Помери линију доле\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Отвори линију изнад\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Отвори линију испод\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Аутоматски затвори заграде\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Пружи малу помоћ око кôда\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Пронађи\",\n    \"CMD_FIND\"                            : \"Пронађи\",\n    \"CMD_FIND_NEXT\"                       : \"Пронађи следеће\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Пронађи претходно\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Пронађи све и изабери\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Додај следеће поклапање у селекцију\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Прескочи и додај следеће поклапање\",\n    \"CMD_FIND_IN_FILES\"                   : \"Пронађи међу датотекама\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Пронађи у\\u2026\",\n    \"CMD_REPLACE\"                         : \"Замени\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Замени у датотекама\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Замени у\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Приказ\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Сакриј споредну траку\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Прикажи споредну траку\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Повећај величину фонта\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Смањи величину фонта\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Поврати величину фонта\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Помакни једну линију горе\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Помакни једну линију доле\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Бројеви редова\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Означи активну линију\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Прелом текста\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Обележи живи приказ\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Преконтролиши датотеке приликом чувања\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Сортирај по датуму додавања\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Сортирај по имену\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Сортирај по типу\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Аутоматско сортирање\",\n    \"CMD_THEMES\"                          : \"Теме\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Навигација\",\n    \"CMD_QUICK_OPEN\"                      : \"Отвори на брзину\",\n    \"CMD_GOTO_LINE\"                       : \"Иди на линију\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Брзо пронађи дефиницију\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Иди на први проблем\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Измени на брзину\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Брзи документи\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Претходно поклапање\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Следеће поклапање\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Ново правило\",\n    \"CMD_NEXT_DOC\"                        : \"Следећи документ\",\n    \"CMD_PREV_DOC\"                        : \"Претходни документ\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Прикажи у стаблу датотека\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Прикажи у Explorer-у\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Прикажи у Проналазачу\",\n    \"CMD_SHOW_IN_OS\"                      : \"Прикажи у оперативном систему\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Помоћ\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Провери да ли постоји новијa верзија\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Корисничко упутство за {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} подршка\",\n    \"CMD_SUGGEST\"                         : \"Предложи нову функционалност\",\n    \"CMD_RELEASE_NOTES\"                   : \"Белешке о тренутној верзији\",\n    \"CMD_GET_INVOLVED\"                    : \"Прикључи се развоју апликације\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Прикажи директоријум са екстензијама\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} веб страница\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} на Твитеру\",\n    \"CMD_ABOUT\"                           : \"О апликацији {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Отвори датотеку са подешавањима\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Отвори мапу корисничких пречица на тастатури\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"експериментална верзија\",\n    \"RELEASE_BUILD\"                        : \"билд\",\n    \"DEVELOPMENT_BUILD\"                    : \"развојна верзија\",\n    \"RELOAD_FROM_DISK\"                     : \"Поново учитај са диска\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Сачувај измене у едитору\",\n    \"CLOSE_DONT_SAVE\"                      : \"Затвори (без чувања измена)\",\n    \"RELAUNCH_CHROME\"                      : \"Поново покрени Chrome\",\n    \"ABOUT\"                                : \"О апликацији\",\n    \"CLOSE\"                                : \"Затвори\",\n    \"ABOUT_TEXT_LINE1\"                     : \"Итерација {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"временска ознака билда: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Обавештења, обавезе и услови коришћења који се односе на \\\"third party\\\" софтвер су лоцирани на <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> и укључени су овде путем референце.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Документација и изворни кôд на <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Направили са \\u2764 и JavaScript-ом:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Много људи (али тренутно имамо потешкоћа да учитамо те податке).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"\\\"MDN Docs\\\" и \\\"MDN\\\" логотип су заштићени \\\"Creative Commons Attribution\\\" лиценцом, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"Објављена је нова верзија {APP_NAME}-а! Кликните овде за више информација.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Нова верзија доступна\",\n    \"UPDATE_MESSAGE\"                       : \"Хеј, нова верзија {APP_NAME}-а је доступна. Ово су нека од најновијих унапређења:\",\n    \"GET_IT_NOW\"                           : \"Преузми сада!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Подешавања пројекта за: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Основна URL адреса за живи приказ\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"Да бисте користили локални сервер, унесите адресу (url) попут http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"Живи приказ не подржава протокол {0}&mdash;Молимо Вас користите http: или https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Основна URL адреса не сме садржати параметре попут \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Основна URL адреса не сме садржати хешеве (hashes) попут \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Специјални карактери попут '{0}' морају бити %-енкодирани.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Непозната грешка приликом парсирања основне URL адресе\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Отвори датотеку док је овај панел у фокусу</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Тренутна тема\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Користи клизаче из теме\",\n    \"FONT_SIZE\"                            : \"Величина фонта\",\n    \"FONT_FAMILY\"                          : \"Породица фонта\",\n    \"THEMES_SETTINGS\"                      : \"Подешавања теме\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Ново правило\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Инсталирај\",\n    \"UPDATE\"                               : \"Ажурирај\",\n    \"REMOVE\"                               : \"Уклони\",\n    \"OVERWRITE\"                            : \"Пресними\",\n    \"CANT_REMOVE_DEV\"                      : \"Екстензије у \\\"dev\\\" директоријуму морају бити ручно обрисане.\",\n    \"CANT_UPDATE\"                          : \"Нова верзија није компатибилна са тренутном верзијом {APP_NAME}-а.\",\n    \"CANT_UPDATE_DEV\"                      : \"Extensions in the \\\"dev\\\" folder can't be updated automatically.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Инсталирај екстензију\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Ажурирај екстензију\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"URL екстензије\",\n    \"INSTALL_EXTENSION_HINT\"               : \"Интернет адреса (URL) zip архиве екстензије или GitHub репозиторијума\",\n    \"INSTALLING_FROM\"                      : \"Инсталирам екстензију са {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Инсталација успешна!\",\n    \"INSTALL_FAILED\"                       : \"Инсталација неуспешна.\",\n    \"CANCELING_INSTALL\"                    : \"Отказујем\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Отказивање инсталације траје предуго. Могуће да је дошло до интерне грешке.\",\n    \"INSTALL_CANCELED\"                     : \"Инсталација отказана.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Прикажи комплетан опис\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Прикажи сажет опис\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Преузети садржај није валидна zip архива.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Датотека \\\"package.json\\\" није валидна (грешка: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"У датотеци \\\"package.json\\\" није наведено име пакета.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} није валидно име за пакет.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"У датотеци \\\"package.json\\\" није наведена верзија пакета.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Верзија пакета број ({0}) није валидна.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"{APP_NAME}-ов низ о компатибилности ({0}) није валидан.\",\n    \"DISALLOWED_WORDS\"                     : \"Речи ({1}) нису дозвољене у пољу {0}.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Ова екстензија није компатибилна са тренутном верзијом апликације \\\"{APP_NAME}\\\". Инсталирана је у Ваш директоријум са неактивним екстензијама.\",\n    \"MISSING_MAIN\"                         : \"Овај пакет нема \\\"main.js\\\" датотеку.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Инсталирањем овог пакета ћете преснимити претходно инсталирану екстензију. Да ли желите да преснимите стару инсталацију?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Верзија овог пакета је иста као верзија која је тренутно инсталирана. Да ли желите да преснимите постојећу инсталацију?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Овај пакет је у верзији {0} што је старије од тренутно инсталиране верзије ({1}). Да ли желите да преснимите постојећу инсталацију?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Интерна грешка: ID преузимања је већ у употреби.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Повезивање са сервером није могуће.\",\n    \"BAD_HTTP_STATUS\"                      : \"Датотека није пронађена на серверу (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Није могуће сачувати преузете податке у привремену датотеку.\",\n    \"ERROR_LOADING\"                        : \"Дошло је до грешке у екстензији приликом њеног покретања.\",\n    \"MALFORMED_URL\"                        : \"URL није валидан. Молимо проверите да ли је Ваш унос тачан.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"URL мора бити http или https.\",\n    \"UNKNOWN_ERROR\"                        : \"Непозната интерна грешка.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Менаџер екстензија\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Приступање регистру екстензије није могуће. Молимо покушајте касније.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Превуци .zip овде или\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Пусти .zip за инсталирање\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Инсталирање/Ажурирање прекинуто услед следећих грешака:\",\n    \"INSTALL_FROM_URL\"                     : \"Инсталирај са URL адресе\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Валидирам\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Аутор\",\n    \"EXTENSION_DATE\"                       : \"Датум\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Ова екстензија захтева новиу верзију {APP_NAME}-а.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Ова екстензија тренутно ради само у старијим верзијама {APP_NAME}-а.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Верзија {0} ове екстензије захтева новију верзију апликације {APP_NAME}. Али можете инсталирати ранију верзију {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Верзија {0} ове екстензије ради искључиво са старијим верзијама апликације {APP_NAME}. Али можете инсталирати ранију верзију {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Не постоји опис\",\n    \"EXTENSION_MORE_INFO\"                  : \"Више информација...\",\n    \"EXTENSION_ERROR\"                      : \"Грешка у екстензији\",\n    \"EXTENSION_KEYWORDS\"                   : \"Кључне речи\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Преведено на {0} језика, укључујући Ваш\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Преведено на {0} језика\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Ова екстензија је преведена на ове језике: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Инсталирано\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Ова верзија екстензије је већ преузета и биће инсталирана приликом поновног покретања {APP_NAME}-а.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Пронађи\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Још\",\n    \"BROWSE_EXTENSIONS\"                    : \"Претражи екстензије\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Уклони екстензију\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Није могуће уклонити једну или више екстензија: {0}. {APP_NAME} ће се ипак поново покренути.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Ажурирај екстензију\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Није могуће ажурирати једну или више екстензија: {0}. {APP_NAME} ће се ипак поново покренути.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Означено за уклањање\",\n    \"UNDO_REMOVE\"                          : \"Опозови\",\n    \"MARKED_FOR_UPDATE\"                    : \"Означено за ажурирање\",\n    \"UNDO_UPDATE\"                          : \"Опозови\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Промени екстензије\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"Да би се означене екстензије ажурирале или уклониле \\\"{APP_NAME}\\\" ће морати поново да се покрене. Од Вас ће бити затражено да сачувате измене.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Уклони екстензије и изађи\",\n    \"CHANGE_AND_RELOAD\"                    : \"Промени екстензије и изађи\",\n    \"UPDATE_AND_RELOAD\"                    : \"Ажурирај екстензије и изађи\",\n    \"PROCESSING_EXTENSIONS\"                : \"Процесуирам измене у екстензијама\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Екстензија {0} није могла бити уклоњена јер није била инсталирана.\",\n    \"NO_EXTENSIONS\"                        : \"Тренутно нема инсталираних екстензија.<br>Кликните изнад на картицу Доступно да додате екстензију.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Ниједна екстензија се не поклапа са унетим параметрима претраге.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"ОПРЕЗ: Ове екстензије можда потичу од непознатих извора. Екстензије нису проверене и поседују пуне локалне привилегије. Будите обазриви приликом инсталације екстензија које потичу од непознатих извора.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Инсталирано\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Доступно\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Теме\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Ажурирања\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Нема поклапања.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Сва поклапања су скривена. Раширите датотеке излистане на десној страни како бисте видели поклапања.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Не постоје CSS правила која се поклапају са Вашом селекцијом.<br> Кликните \\\"Ново правило\\\" како бисте креирали ново.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Не постоје стилови у вашем пројекту.<br>Креирајте један или додајте CSS правила.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"највећа\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                          : \"пиксели\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Отклањање грешака\",\n    \"ERRORS\"                                    : \"Грешке\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Прикажи развојне алате\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Поново учитај са екстензијама\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Поново учитај без екстензија\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Нови {APP_NAME} прозор\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Промени језик\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Изврши тестове\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Прикажи податке о перформансама\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Укључи Node Debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Прикажи стање Node-а у конзоли\",\n    \"CMD_RESTART_NODE\"                          : \"Поново покрени Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Прикажи грешке у статусној линији\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Отвори изворни кôд Brackets-а\",\n\n    \"LANGUAGE_TITLE\"                            : \"Промени језик\",\n    \"LANGUAGE_MESSAGE\"                          : \"Језик:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Поново учитај {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Откажи\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"језик система\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Време\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Напредак\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Помери изабрану тачку<br><kbd class='text'>Shift</kbd> Помери за десет јединица<br><kbd class='text'>Tab</kbd> Замени тачке\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Повећај или смањи кораке<br><kbd>←</kbd><kbd>→</kbd> 'Почни' или 'Заврши'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Стара вредност <code>{0}</code> није валидна, па је приказана функција промењена у <code>{1}</code>. Овај документ ће се ажурирати приликом прве измене.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Тренутна боја\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Оригинална боја\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa формат\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex формат\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa формат\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (Коришћена {1} пут)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (Коришћена {1} пута)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Скочи на дефиницију\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Пружи малу помоћ око параметра\",\n    \"NO_ARGUMENTS\"                              : \"<без параметара>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Проблем у обради JavaScript датотеке\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets није успео да процесуира <span class='dialog-filename'>{0}</span>.<br><br>Ова датотека више неће бити процесуирана за приказивање малих помоћи у кôду, Скочи на дефиницију или Брза измена. Како бисте активирали ову датотеку, отворите <code>.brackets.json</code> у Вашем пројекту и измените <code>jscodehints.detectedExclusions</code>.<br><br>Ово је вероватно баг у апликацији Brackets. Ако можете приложити копију ове датотеке, молимо Вас <a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>пријавите баг</a> који садржи линк до овде наведене датотеке.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Брзи приказ приликом задржавања миша\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Недавни пројекти\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Прочитај више\"\n});\n\n/* Last translated for c292e896761bc7d451a9e3b95bedd20d6b355d77 */\n"
  },
  {
    "path": "src/nls/strings-app.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n\n    \"use strict\";\n\n    // Code that needs to display user strings should call require(\"strings\") to load\n    // src/strings.js. This file will dynamically load strings.js for the specified brackets.locale.\n    //\n    // See the README.md file in this folder for information on how to add a new translation for\n    // another language or locale.\n    //\n    // TODO: dynamically populate the local prefix list below?\n    module.exports = {\n        root: true\n    };\n});\n"
  },
  {
    "path": "src/nls/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n\n    \"use strict\";\n\n    // Code that needs to display user strings should call require(\"strings\") to load\n    // src/strings.js. This file will dynamically load strings.js for the specified brackets.locale.\n    //\n    // See the README.md file in this folder for information on how to add a new translation for\n    // another language or locale.\n    //\n    // TODO: dynamically populate the local prefix list below?\n    module.exports = {\n        root: true,\n        \"bg\": true,\n        \"cs\": true,\n        \"da\": true,\n        \"de\": true,\n        \"el\": true,\n        \"en-gb\": true,\n        \"es\": true,\n        \"fa-ir\": true,\n        \"fi\": true,\n        \"fr\": true,\n        \"gl\": true,\n        \"hr\": true,\n        \"hu\": true,\n        \"id\": true,\n        \"it\": true,\n        \"ja\": true,\n        \"ko\": true,\n        \"lv\": true,\n        \"nb\": true,\n        \"nl\": true,\n        \"pl\": true,\n        \"pt-br\": true,\n        \"pt-pt\": true,\n        \"ro\": true,\n        \"ru\": true,\n        \"sk\": true,\n        \"sr\": true,\n        \"sv\": true,\n        \"tr\": true,\n        \"uk\": true,\n        \"zh-cn\": true,\n        \"zh-tw\": true\n    };\n});\n"
  },
  {
    "path": "src/nls/sv/strings.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(fel {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Filen/mappen kunde inte hittas.\",\n    \"NOT_READABLE_ERR\"                  : \"Filen/mappen kunde inte läsas.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"Filer större än {0} MB kan inte öppnas i {APP_NAME}.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Målmappen kunde inte ändras.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Du har inte behörighet att modifiera filen.\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"Filen har ändrats utanför {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} stöder just nu bara textfiler kodade i UTF-8.\",\n    \"FILE_EXISTS_ERR\"                   : \"Filen eller mappen existerar redan.\",\n    \"FILE\"                              : \"fil\",\n    \"FILE_TITLE\"                        : \"Fil\",\n    \"DIRECTORY\"                         : \"mapp\",\n    \"DIRECTORY_TITLE\"                   : \"Mapp\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"Mappnamn\",\n    \"FILENAMES_LEDE\"                    : \"Filnamn\",\n    \"FILENAME\"                          : \"filnamn\",\n    \"DIRECTORY_NAME\"                    : \"mappnamn\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Projektet kunde inte öppnas\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Ett fel inträffade när öppningsdialogen skulle visas. (fel {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"Ett fel inträffade när mappen skulle öppnas <span class='dialog-filename'>{0}</span>. (fel {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"Ett fel inträffade när mappens innehåll skulle läsas <span class='dialog-filename'>{0}</span>. (fel {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Filen kunde inte öppnas\",\n    \"ERROR_OPENING_FILE\"                : \"Ett fel inträffade när filen <span class='dialog-filename'>{0}</span> skulle öppnas. {1}\",\n    \"ERROR_OPENING_FILES\"               : \"Ett fel inträffade när följande filer skulle öppnas:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Filen kunde inte laddas om\",\n    \"ERROR_RELOADING_FILE\"              : \"Ett fel inträffade när filen <span class='dialog-filename'>{0}</span> skulle läsas om. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Filen kunde inte sparas\",\n    \"ERROR_SAVING_FILE\"                 : \"Ett fel inträffade när filen <span class='dialog-filename'>{0}</span> skulle sparas. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Filen kunde inte döpas om\",\n    \"ERROR_RENAMING_FILE\"               : \"Ett fel uppstod när {2}-filen <span class='dialog-filename'>{0}</span> skulle döpas om. {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"Filen eller mappen är inte del av det öppna projektet. Tyvärr kan bara projektfiler döpas om för närvarande.\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"Filen kunde inte raderas\",\n    \"ERROR_DELETING_FILE\"               : \"Ett fel uppstod när {2}-filen <span class='dialog-filename'>{0}</span> skulle tas bort. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Ogiltigt {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} får inte innehålla ord som reserverats av systemet, sluta med punkt (.) eller använda något av följande tecken: <code class='emphasized'>{1}</code>.\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"En fil eller mapp med namnet <span class='dialog-filename'>{0}</span> existerar redan.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Kunde inte skapa {0}\",\n    \"ERROR_CREATING_FILE\"               : \"Ett fel uppstod när en {0} med namnet <span class='dialog-filename'>{1}</span> skulle skapas. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"Kan inte öppna en mapp samtidigt som andra filer öppnas.\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"Fel uppstod när användarens tangentuppsättning lästes in\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"Din tangentuppsättningsfil är inte korrekt formaterad JSON. Filen kommer att öppnas så att du kan åtgärda formateringsfelet.\",\n    \"ERROR_LOADING_KEYMAP\"              : \"Din tangentuppsättningsfil är inte en UTF-8-kodad textfil och kan inte läsas\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"Du kan inte ändra kortkommandot för följande kommandon: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"Du kan inte ändra följande kortkommandon: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"Du håller på att koppla flera kortkommandon till följande kommandon: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"Du har flera kopplingar till följande kommandon: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"Följande kortkommandon är felaktiga: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"Du håller på att skapa kortkommandon till följande icke-existerande kommandon: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"Kunde inte läsa inställningar\",\n    \"ERROR_PREFS_CORRUPT\"               : \"Din inställningsfil är inte korrekt formaterad JSON. Filen kommer att öppnas så att du kan korrigera felet. Du kommer att behöva starta om {APP_NAME} för att ändringarna ska träda i kraft.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"Dina projektinställningar är inte giltig JSON. Filen kommer att öppnas så att du kan rätta till formatet. Du behöver ladda om projektet för att ändringarna ska träda i kraft.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ajdå! {APP_NAME} körs inte i webbläsaren ännu.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} är byggd i HTML, men körs just nu som en skrivbordsapplikation så att du kan använda den för att redigera lokala filer. Vänligen använd skalapplikationen <b>github.com/adobe/brackets-shell</b> för att köra {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Fel vid indexering av filer\",\n    \"ERROR_MAX_FILES\"                   : \"Det maximala antalet filer har indexerats. Funktioner som använder sig av indexet kanske inte kommer att fungera som förväntat.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Webbläsaren kunde inte öppnas.\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Google Chrome kunde inte hittas. Kontrollera att den är installerad.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Ett fel inträffade då webbläsaren skulle startas. (fel {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Förhandsvisning misslyckades\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Ansluter till webbläsaren\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"För att förhandsvisningen ska lyckas måste Chrome startas om med fjärrfelsökning aktiverad.<br /><br />Vill du starta om Chrome och aktivera fjärrfelsökning?\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"Lyckades inte ladda förhandsvisningssidan.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Öppna en HTML-fil eller kontrollera att det finns en fil med namnet index.html i din projektmapp för att kunna starta förhandsvisningen.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"För att starta förhandsvisningen med en fil innehållande serverkod måste du ange en bas-URL för detta projekt.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"Ett fel uppstod när webbsevern för förhandsvisningen skulle startas. Vänligen försök igen.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Välkommen till förhandsvisningen!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Förhandsvisningen ansluter {APP_NAME} till din webbläsare. Den öppnar en förhandsvisning av din HTML-fil i webbläsaren och uppdaterar förhandsvisningen så fort ändringar skett i koden.<br /><br />I denna tidiga version av {APP_NAME} fungerar förhandsvisningen endast för redigering av <strong>CSS- och HTML-filer</strong> och endast med <strong>Google Chrome</strong>. Vid ändringar i JavaScript-kod laddas webbläsaren om när du sparar filen.<br /><br />(Du kommer bara se detta meddelande en gång.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"För mer information se <a href='{0}' title='{0}'>Troubleshooting Live Development connection errors</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Förhandsvisning\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Förhandsvisning: Ansluter\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Förhandsvisning: Initierar\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Koppla från förhandsvisningen\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Förhandsvisning (spara filen för att uppdatera)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"Förhandsvisning (uppdateras inte på grund av syntaxfel)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"Förhandsvisningen avbröts eftersom webbläsarens utvecklarverktyg öppnades.\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"Förhandsvisningen avbröts eftersom sidan stängdes i webbläsaren.\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"Förhandsvisningen avbröts eftersom webbläsaren navigerades till en sida som inte är del av det nuvarande projektet.\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"Förhandsvisningen avbröts på grund av ett okänt fel. ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Spara ändringar?\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Vill du spara de ändringar i dokumentet <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Vill du spara ändringarna du gjort följande filer?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Externa ändringar\",\n    \"CONFIRM_DELETE_TITLE\"              : \"Bekräfta borttagning\",\n    \"CONFIRM_FILE_DELETE\"               : \"Är du säker att du vill radera filen <span class='dialog-filename'>{0}</span>?\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"Är du säker att du vill radera mappen <span class='dialog-filename'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                : \"Filen raderades\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> har ändrats.<br /><br />Vill du spara filen och skriva över dessa ändringar?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> har ändrats men har också osparade ändringar i {APP_NAME}.<br /><br />Vilken version vill du behålla?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> har raderats man har också osparade ändringar i {APP_NAME}.<br /><br />Vill du behålla dina ändringar?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"Klar\",\n    \"OK\"                                : \"OK\",\n    \"CANCEL\"                            : \"Avbryt\",\n    \"DONT_SAVE\"                         : \"Spara inte\",\n    \"SAVE\"                              : \"Spara\",\n    \"SAVE_AS\"                           : \"Spara som\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"Spara och skriv över\",\n    \"DELETE\"                            : \"Radera\",\n    \"BUTTON_YES\"                        : \"Ja\",\n    \"BUTTON_NO\"                         : \"Nej\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} av {1}\",\n    \"FIND_NO_RESULTS\"                   : \"Inga träffar\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"Sök\\u2026\",\n    \"FIND_HISTORY_MAX_COUNT\"            : \"Maximalt antal poster i sökhistoriken\",\n    \"REPLACE_PLACEHOLDER\"               : \"Ersätt med\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"Alla\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"Ersätt\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"Ersätt\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"Nästa träff\",\n    \"BUTTON_PREV_HINT\"                  : \"Föregående träff\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"Skiftlägeskänslig\",\n    \"BUTTON_REGEXP_HINT\"                : \"Regular Expression\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"Ersätt utan att ångra\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"Eftersom mer än {0} filer ändras kommer {APP_NAME} ändra dessa utan att de öppnas.<br />Du kommer inte att kunna ånga ändringarna i dessa filer.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"Ersätt utan att ångra\",\n\n    \"OPEN_FILE\"                         : \"Öppna fil\",\n    \"SAVE_FILE_AS\"                      : \"Spara fil som\",\n    \"CHOOSE_FOLDER\"                     : \"Välj mapp\",\n\n    \"RELEASE_NOTES\"                     : \"Versionsinformation\",\n    \"NO_UPDATE_TITLE\"                   : \"Du är uppdaterad!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"Du använder den senaste versionen av {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"Ersätt\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"med\",\n    \"FIND_TITLE_LABEL\"                  : \"Hittades\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} i {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"i <span class='dialog-filename'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"i projekt\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"Filter exkluderar alla filer {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"fil\",\n    \"FIND_IN_FILES_FILES\"               : \"filer\",\n    \"FIND_IN_FILES_MATCH\"               : \"träff\",\n    \"FIND_IN_FILES_MATCHES\"             : \"träffar\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Mer än \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"Ctrl/Cmd-klicka för att expandera/minimera alla\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"Ersättningsfel\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"Följande filer ändrades inte eftersom de förändrats efter sökningen eller inte kunde skrivas till.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Fel vid hämtning av versioninformation\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Det gick inte att hämta versionsinformation från servern. Kontrollera din internetuppkoppling och försök igen.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"Nytt exkluderingsset\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"Exkludera inte filer\",\n    \"NO_FILE_FILTER\"                    : \"Exkludera filer\\u2026\",\n    \"EXCLUDE_FILE_FILTER\"               : \"Exkludera {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"Redigera\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"Redigera filter\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"Exkludera filer och mappar som matchar någon av följande strängar, substrängar eller <a href='{0}' title='{0}'>wildcards</a>. Ange varje sträng på en ny rad.\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"Namnge detta exkluderingsset (frivilligt)\",\n    \"FILTER_NAME_REMAINING\"             : \"{0} tecken kvar\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"och {0} till\",\n    \"FILTER_COUNTING_FILES\"             : \"Räknar filer\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Tillåter {0} av {1} filer {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Tillåter alla {0} filer {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"Ingen Quick Edit är tillgänglig vid markörens nuvarande position\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS Quick Edit: placera markören på ett klassnamn\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS Quick Edit: ofullständigt klassattribut\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS Quick Edit: ofullständigt ID-attribut\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS Quick Edit: placera markören inom en tagg, klass eller ID\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS tidsfunktion Quick Edit: felaktigt syntax\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS Quick Edit: placera markören på ett funktionsnamn\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"Inga Quick Docs är tillgängliga vid markörens nuvarande position\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Öppnar\\u2026\",\n    \"UNTITLED\"          : \"Namnlös\",\n    \"WORKING_FILES\"     : \"Öppna filer\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"Övre\",\n    \"BOTTOM\"            : \"Undre\",\n    \"LEFT\"              : \"Vänster\",\n    \"RIGHT\"             : \"Höger\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"Ingen delning\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"Vertikal delning\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"Horisontell delning\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"Dela editorn vertikalt eller horisontellt\",\n    \"GEAR_MENU_TOOLTIP\"         : \"Konfigurera arbetsyta\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"Redan öppen\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"Filen är redan öppen i en annan panel. {APP_NAME} kommer inom kort att stödja möjligheten att öppna samma fil i flera paneler. Filen kommer att visas i nuvarande panel tills dess.<br /><br />(Detta meddelande kommer bara att visas en gång.)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Space\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Rad {0}, kolumn {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 Markerade {0} kolumn\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 Markerade {0} kolumner\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 Markerade {0} rad\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 Markerade {0} rader\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} markeringar\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Klicka för att använda mellanslag för indrag\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Klicka för att använda tabbar för indrag\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Klicka för att ändra antalet mellanslag som används för indrag\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Klicka för att ändra bredden på tabbtecken\",\n    \"STATUSBAR_SPACES\"                      : \"Mellanslag:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tabbstorlek:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} rad\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} rader\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"Tillägg har avaktiverats\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"ÖVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"Klicka för att växla mellan Insert (INS)- och Overwrite (ÖVR)-läge.\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"Klicka för att byta filtyp\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}. Klicka för att visa rapportpanel.\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(standard)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"Ställ in som standard för .{0}-filer\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} fel\",\n    \"SINGLE_ERROR\"                          : \"1 {0} fel\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} {0} fel\",\n    \"NO_ERRORS\"                             : \"Inga {0} fel funna - bra jobbat!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"Inga fel funna - bra jobbat!\",\n    \"LINT_DISABLED\"                         : \"Linting är avaktiverat.\",\n    \"NO_LINT_AVAILABLE\"                     : \"Ingen linter är tillgänglig för {0}\",\n    \"NOTHING_TO_LINT\"                       : \"Ingenting att linta\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} har avbrutits efter att ha väntat {1} ms\",\n    \"LINTER_FAILED\"                         : \"{0} avbröts efter ett fel: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Arkiv\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Ny\",\n    \"CMD_FILE_NEW\"                        : \"Ny fil\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Ny mapp\",\n    \"CMD_FILE_OPEN\"                       : \"Öppna\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Lägg till i arbetsyta\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"Öppna släppta filer\",\n    \"CMD_OPEN_FOLDER\"                     : \"Öppna mapp\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Stäng\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Stäng alla\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"Stäng lista\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"Stäng andra\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"Stäng andra ovanför\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"Stäng andra nedanför\",\n    \"CMD_FILE_SAVE\"                       : \"Spara\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Spara alla\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Spara som\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Förhandsvisning\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"Tvinga uppdatering av förhandsvisningen\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Projektinställningar\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Byt namn\",\n    \"CMD_FILE_DELETE\"                     : \"Radera\",\n    \"CMD_INSTALL_EXTENSION\"               : \"Installera tillägg\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Tilläggshanteraren\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"Uppdatera filträd\",\n    \"CMD_QUIT\"                            : \"Avsluta\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Avsluta\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Redigera\",\n    \"CMD_UNDO\"                            : \"Ångra\",\n    \"CMD_REDO\"                            : \"Gör om\",\n    \"CMD_CUT\"                             : \"Klipp ut\",\n    \"CMD_COPY\"                            : \"Kopiera\",\n    \"CMD_PASTE\"                           : \"Klistra in\",\n    \"CMD_SELECT_ALL\"                      : \"Markera alla\",\n    \"CMD_SELECT_LINE\"                     : \"Markera rad\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Dela markering i rader\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Lägg till markör på nästa rad\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Lägg till markör på föregående rad\",\n    \"CMD_INDENT\"                          : \"Öka indrag\",\n    \"CMD_UNINDENT\"                        : \"Minska indrag\",\n    \"CMD_DUPLICATE\"                       : \"Duplicera\",\n    \"CMD_DELETE_LINES\"                    : \"Radera rad\",\n    \"CMD_COMMENT\"                         : \"Växla kommentarsrad\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Växla blockkommentar\",\n    \"CMD_LINE_UP\"                         : \"Flytta rad uppåt\",\n    \"CMD_LINE_DOWN\"                       : \"Flytta rad nedåt\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"Öppna rad ovanför\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"Öppna rad nedanför\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Stäng parenteser automatiskt\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Visa kodförslag\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Sök\",\n    \"CMD_FIND\"                            : \"Sök\",\n    \"CMD_FIND_NEXT\"                       : \"Sök nästa\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Sök föregående\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Sök och markera alla\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Lägg nästa träff till markering\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Hoppa över och lägg till nästa träff\",\n    \"CMD_FIND_IN_FILES\"                   : \"Sök i filer\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"Sök i\\u2026\",\n    \"CMD_REPLACE\"                         : \"Ersätt\",\n    \"CMD_REPLACE_IN_FILES\"                : \"Ersätt i filer\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"Ersätt i\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Visa\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Dölj sidomeny\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Visa sidomeny\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"Växla på/av sidomeny\",\n    \"CMD_TOGGLE_PANELS\"                   : \"Växla på/av paneler\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"Inga distraktioner\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Öka textstorlek\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Minska teckenstorlek\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Återställ teckenstorlek\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"Rulla rad uppåt\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"Rulla rad nedåt\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"Radnummer\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"Markera aktiv rad\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"Automatisk radbrytning\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"Markera förhandsvisning\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"Linta filer vid spara\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Sortera efter senast tillagd\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"Sortera efter namn\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Sortera efter typ\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Automatisk sortering\",\n    \"CMD_THEMES\"                          : \"Teman\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"Navigera\",\n    \"CMD_QUICK_OPEN\"                      : \"Snabböppna\",\n    \"CMD_GOTO_LINE\"                       : \"Gå till rad\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Gå till definition\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"Gå till första fel/varning\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Snabbredigering\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Quick Docs\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Föregående träff\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Nästa träff\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Ny regel\",\n    \"CMD_NEXT_DOC\"                        : \"Nästa dokument\",\n    \"CMD_PREV_DOC\"                        : \"Föregående dokument\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"Nästa dokument i lista\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"Föregående dokument i lista\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Visa i filträdet\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"Visa i Utforskaren\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"Visa i Finder\",\n    \"CMD_SHOW_IN_OS\"                      : \"Visa i operativsystemet\",\n    \"CMD_SWITCH_PANE_FOCUS\"               : \"Växla panelfokus\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Hjälp\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Sök efter uppdateringar\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"Hur du använder {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME}-forum\",\n    \"CMD_SUGGEST\"                         : \"Föreslå en funktion\",\n    \"CMD_RELEASE_NOTES\"                   : \"Versionsinformation\",\n    \"CMD_GET_INVOLVED\"                    : \"Engagera dig\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Visa tilläggsmapp\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"Hälsorapport\",\n    \"CMD_HOMEPAGE\"                        : \"Webbplats för {APP_TITLE}\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} på Twitter\",\n    \"CMD_ABOUT\"                           : \"Om {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Öppna inställningsfil\",\n    \"CMD_OPEN_KEYMAP\"                     : \"Öppna användarens tangentuppsättning\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"experimental build\",\n    \"RELEASE_BUILD\"                        : \"build\",\n    \"DEVELOPMENT_BUILD\"                    : \"development build\",\n    \"RELOAD_FROM_DISK\"                     : \"Ladda om\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Behåll ändringar i editorn\",\n    \"CLOSE_DONT_SAVE\"                      : \"Stäng (spara inte)\",\n    \"RELAUNCH_CHROME\"                      : \"Starta om Chrome\",\n    \"ABOUT\"                                : \"Om\",\n    \"CLOSE\"                                : \"Stäng\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"tidsstämpel för build: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"Meddelanden och villkor gällande program från tredje part finns på <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> och inkluderas här som referens.\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Dokumentation och källkod återfinns på <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Skapat med \\u2764 och JavaScript av:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"Massor av människor (men vi har lite problem att visa dessa data just nu).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN Docs och dess logotyp är licenserad under en Creative Commons Attribution-licens, <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"En ny version av {APP_NAME} är tillgänglig! Klicka här för fler detaljer.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Uppdatering tillgänglig!\",\n    \"UPDATE_MESSAGE\"                       : \"Hallå! En ny version av {APP_NAME} är tillgänglig. Här är några av de nya funktionerna:\",\n    \"GET_IT_NOW\"                           : \"Installera nu!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"Projektinställningar för: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"URL till förhandsvisning\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"För att använda en lokal server anger du en adress liknande: http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"{0}-protokollet stöder inte förhandsvisning &mdash; vänligen använd http: eller https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Adressen kan inte innehålla sökparametrar som \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Adressen kan inte innehålla hashar som \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"Specialtecken som '{0}' måste vara %-kodade.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Okänt fel när adressen skulle läsas!\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>Öppna en fil medan denna panel är i fokus</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"Flippa denna vy till panel {0}\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"Nuvarande tema\",\n    \"USE_THEME_SCROLLBARS\"                 : \"Använd temats rullningslister\",\n    \"FONT_SIZE\"                            : \"Teckenstorlek\",\n    \"FONT_FAMILY\"                          : \"Typsnitt\",\n    \"THEMES_SETTINGS\"                      : \"Temainställningar\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"Ny regel\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"Installera\",\n    \"UPDATE\"                               : \"Uppdatera\",\n    \"REMOVE\"                               : \"Radera\",\n    \"DISABLE\"                              : \"Avaktivera\",\n    \"ENABLE\"                               : \"Aktivera\",\n    \"OVERWRITE\"                            : \"Skriv över\",\n    \"CANT_REMOVE_DEV\"                      : \"Tillägg i mappen \\\"dev\\\" måste raderas manuellt.\",\n    \"CANT_UPDATE\"                          : \"Uppdateringen är inte kompatibel med denna version av {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                      : \"Tilläggen i mappen \\\"dev\\\" kan inte uppdateras automatiskt.\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"Installera tillägg\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"Uppdatera tillägg\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"Tilläggets URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"URL till tilläggets zip-fil eller GitHub-repository\",\n    \"INSTALLING_FROM\"                      : \"Installerar tillägg från {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"Installationen lyckades!\",\n    \"INSTALL_FAILED\"                       : \"Installationen misslyckades.\",\n    \"CANCELING_INSTALL\"                    : \"Avbryter\\u2026\",\n    \"CANCELING_HUNG\"                       : \"Installationen avbröts då den tog för lång tid. Ett internt fel kan ha inträffat.\",\n    \"INSTALL_CANCELED\"                     : \"Installationen avbröts.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"Visa hela beskrivningen\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"Visa förkortad beskrivning\",\n    \"SORT_EXTENSION_METHOD\"                : \"Sortera tillägg på downloadCount eller publishedDate\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"Det nedladdade innehållet är inte en fungerande zip-fil.\",\n    \"MISSING_PACKAGE_JSON\"                 : \"Paketet saknar filen package.json.\",\n    \"INVALID_PACKAGE_JSON\"                 : \"Filen package.json är inte korrekt (felet var: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"Filen package.json innehåller inte tilläggets namn.\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} är inte ett godkänt namn.\",\n    \"MISSING_PACKAGE_VERSION\"              : \"Filen package.json innehåller inte tilläggets versionsnummer.\",\n    \"INVALID_VERSION_NUMBER\"               : \"Tilläggets versionsnummer ({0}) är felaktigt.\",\n    \"INVALID_BRACKETS_VERSION\"             : \"Kompatibilitetssträngen ({0}) för {APP_NAME} är felaktig.\",\n    \"DISALLOWED_WORDS\"                     : \"Orden ({1}) är inte tillåtna i {0}-fältet.\",\n    \"API_NOT_COMPATIBLE\"                   : \"Tillägget är inte kompatibelt med denna version av {APP_NAME}. Det har installerats i din mapp med inaktiverade tillägg.\",\n    \"MISSING_MAIN\"                         : \"Tillägget har ingen fil med namnet main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"Installationen av detta tillägg kommer att skriva över ett tidigare installerat tillägg. Vill du skriva över det befintliga tillägget?\",\n    \"EXTENSION_SAME_VERSION\"               : \"Tillägget har samma versionsnummer som ett redan installerat tillägg. Vill du skriva över den befintliga installationen?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"Detta tillägg har versionsnummer {0} och är äldre än den nuvarade versionen ({1}). Vill du skriva över den befintliga installationen?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"Internt fel: nedladdnings-ID används redan.\",\n    \"NO_SERVER_RESPONSE\"                   : \"Kunde inte ansluta till servern.\",\n    \"BAD_HTTP_STATUS\"                      : \"Filen kunde inte hittas på servern (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                    : \"Kunde inte spara filen temporärt.\",\n    \"ERROR_LOADING\"                        : \"Tillägget stötte på ett fel under uppstart.\",\n    \"MALFORMED_URL\"                        : \"Adressen är felaktig. Vänligen kontrollera att du angett den korrekt.\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"Adressen måste använda http eller https.\",\n    \"UNKNOWN_ERROR\"                        : \"Okänt internt fel.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Tilläggshanteraren\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"Kunde inte nå tilläggsregistret. Vänligen försök igen senare.\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"Dra .zip hit eller\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Släpp .zip här för att installera\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"Installation/Uppdatering avbröts på grund av följande fel:\",\n    \"INSTALL_FROM_URL\"                     : \"Installera från URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validerar\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"Författare\",\n    \"EXTENSION_DATE\"                       : \"Datum\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"Detta tillägg kräver en nyare version av {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"Detta tillägg fungerar för närvarande bara med äldre versioner av {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"Version {0} av detta tillägg kräver en nyare version av {APP_NAME} men du kan installera den äldre versionen {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"Version {0} av detta tillägg fungerar endast med äldre versioner av {APP_NAME} men du kan installera den äldre versionen {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"Ingen beskrivning\",\n    \"EXTENSION_MORE_INFO\"                  : \"Mer information...\",\n    \"EXTENSION_ERROR\"                      : \"Tilläggsfel\",\n    \"EXTENSION_KEYWORDS\"                   : \"Nyckelord\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"Översatt till {0} språk, inklusive ditt\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"Översatt till {0} språk\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"Detta tillägg har översatts till dessa språk: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"Installerade\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"Uppdateringen av detta tillägg har laddats ner och kommer att installeras när {APP_NAME} startas om.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"Sök\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"Mer\",\n    \"BROWSE_EXTENSIONS\"                    : \"Bläddra bland tillägg\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"Ta bort tillägg\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"Kunde inte ta bort ett eller flera tillägg: {0}. {APP_NAME} kommer fortfarande att startas om.\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"Uppdatera tillägg\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"Kunde inte uppdatera ett eller flera tillägg: {0}. {APP_NAME} kommer fortfarande att startas om.\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"Avaktivera tillägg\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"Kan inte avaktivera ett eller flera tillägg: {0}. {APP_NAME} kommer fortfarande att startas om.\",\n    \"MARKED_FOR_REMOVAL\"                   : \"Markerad för borttagning\",\n    \"UNDO_REMOVE\"                          : \"Ångra\",\n    \"MARKED_FOR_UPDATE\"                    : \"Markerad för uppdatering\",\n    \"UNDO_UPDATE\"                          : \"Ångra\",\n    \"MARKED_FOR_DISABLING\"                 : \"Markerad för avaktivering\",\n    \"UNDO_DISABLE\"                         : \"Ångra\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"Ändra tillägg\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"{APP_NAME} måste startas om för att uppdatera eller ta bort markerade tillägg. Du kommer att få en fråga om att spara eventuella osparade ändringar.\",\n    \"REMOVE_AND_RELOAD\"                    : \"Ta bort tillägg och starta om\",\n    \"CHANGE_AND_RELOAD\"                    : \"Ta bort tillägg och starta om\",\n    \"UPDATE_AND_RELOAD\"                    : \"Ändra tillägg och starta om\",\n    \"PROCESSING_EXTENSIONS\"                : \"Genomför förändringar av tillägg\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"Kunde inte radera tillägget {0} då det inte är installerat.\",\n    \"NO_EXTENSIONS\"                        : \"Inga tillägg har installerats ännu.<br>Klicka på fliken Tillgängliga för att komma igång.\",\n    \"NO_EXTENSION_MATCHES\"                 : \"Inga tillägg matchade din sökning.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"Var försiktig när du installerar tillägg från okända källor.\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"Installerade\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"Tillgängliga\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"Teman\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"Uppdateringar\",\n    \"EXTENSIONS_LAST_UPDATED\"              : \"Senast uppdaterad\",\n    \"EXTENSIONS_DOWNLOADS\"                 : \"Nedladdningar\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"Inga träffar tillgängliga.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"Alla träffar är minimerade. Expandera filerna listade till höger för att visa träffar.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"Det finns inga CSS-regler som matchar din markering.<br> Klicka på \\\"Ny regel\\\" för att skapa en.\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"Det finns inga stilmallar i ditt projekt.<br>Skapa en flr att lägga till CSS-regler.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"största\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"pixlar\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Debug\",\n    \"ERRORS\"                                    : \"Fel\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Visa utvecklarverktyg\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Starta om med tillägg\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Starta om utan tillägg\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Nytt {APP_NAME}-fönster\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"Installera genväg i kommandotolk\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Byt språk\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Kör tester\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Visa prestandadata\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Aktivera Node-debugger\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Skriv ut Node-status till konsollen\",\n    \"CMD_RESTART_NODE\"                          : \"Starta om Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Visa fel i statusraden\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Öppna Brackets källkod\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} kommandotolk-genväg\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"Ett fel inträffade under installationen av kommandotolk-genvägen. Vänligen prova <a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>dessa felsökningsförslag</a>.<br/><br/>Anledning: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"Kunde inte ta bort existerande symlink <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"Kunde inte skapa mappen <code>/usr/local/bin</code>.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"Kunde inte skapa symlink <code>/usr/local/bin/brackets</code>.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"Internt fel.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"Kommandotolk-genväg stöds inte för det här operativsystemet.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"Lyckades! Nu kan du lätt starta {APP_NAME} från kommandotolken: <code>brackets myFile.txt</code> för att öppna en fil eller <code>brackets myFolder</code> för att växla projekt. <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>Läs mer</a> om att använda {APP_NAME} från kommandotolken.\",\n\n    \"LANGUAGE_TITLE\"                            : \"Byt språk\",\n    \"LANGUAGE_MESSAGE\"                          : \"Språk:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Uppdatera {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Avbryt\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Systemstandard\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"Hälsorapport inställningar\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} Hälsorapport\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"Dela anonym information om hur jag använder {APP_NAME}\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"För att förbättra {APP_NAME} skickar vi regelbundet begränsad, <strong>anonym</strong> statistik till Adobe om hur du använder {APP_NAME}. Denna information hjälper att prioritera funktioner, hitta buggar och upptäcka användbarhetsproblem.<br><br>Du kan se din data eller välja att inte dela din data genom <strong>Hjälp > Hälsorapport</strong>.<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>Läs mer om {APP_NAME} Hälsorapport</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} Hälsorapport\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>För att förbättra {APP_NAME} skickar vi regelbundet begränsad, <strong>anonym</strong> statistik till Adobe om hur du använder {APP_NAME}. Denna information hjälper att prioritera funktioner, hitta buggar och upptäcka användbarhetsproblem. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>Läs mer om {APP_NAME} Hälsorapport</a> och hur det gagnar {APP_NAME}-gemenskapen samtidigt som din integritet skyddas.</p><p>Nedan är en förhandsvisning av datan som skickas i nästa Hälsorapport <em>om</em> det är aktiverat.</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Tid\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Progression\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Flytta markerad punkt<br><kbd class='text'>Shift</kbd> Flytta tio enheter\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Öka eller minska antal steg<br><kbd>←</kbd><kbd>→</kbd> 'Start' eller 'Slut'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Det tidigare värdet <code>{0}</code> är inte korrekt så den visade funktionen har ändrats till <code>{1}</code>. Dokumentet kommer att uppdateras med det första värdet.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Nuvarande färg\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Originalfärg\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa-format\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Hex-format\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa-format\",\n    \"COLOR_EDITOR_0X_BUTTON_TIP\"                : \"Hex (0x)-format\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (använd {1} gång)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (använd {1} gånger)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Gå till definition\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Visa parameterförslag\",\n    \"NO_ARGUMENTS\"                              : \"<inga parametrar>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Problem att slutleda JavaScript-fil\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets stötte på processeringsfel:<br><br>{0}<br><br>Denna fil kommer inte längre genomsökas efter kodförslag eller definitioner. Öppna <code>.brackets.json</code> och ta bort filen från jscodehints.detectedExclusions för att återställa detta.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Quick View vid hover\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Senaste projekt\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Läs mer\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"Kollapsa alla\",\n    \"EXPAND_ALL\"                    : \"Expandera alla\",\n    \"COLLAPSE_CURRENT\"              : \"Kollapsa nuvarande\",\n    \"EXPAND_CURRENT\"                : \"Expandera nuvarande\",\n\n    // extensions/default/NavigationAndHistory\n    \"RECENT_FILES_DLG_HEADER\"                    : \"Senaste filer\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\"        : \"Rensa\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\"        : \"Rensa filer ej i arbetsyta\"\n});\n\n/* Last translated for a01159ac2518fe1f27dfafb62d95a28c2958831f */\n"
  },
  {
    "path": "src/nls/sv/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"sv/Kom igang\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_sv/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.sv\"\n});\n"
  },
  {
    "path": "src/nls/tr/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(hata {0})\",\n    \"NOT_FOUND_ERR\"                     : \"Dosya bulunamadı.\",\n    \"NOT_READABLE_ERR\"                  : \"Dosya okunamadı.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"Klasörde değişiklik yapılamıyor.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"Dosya değişikliği için izniniz yok.\",\n    \"FILE_EXISTS_ERR\"                   : \"Dosya bulunmaktadır.\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Proje yüklenirken hata\",\n    \"OPEN_DIALOG_ERROR\"                 : \"Dosya dialogu gösterilirken hata meydana geldi. (hata {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"<span class='dialog-filename'>{0}</span> klasörü yüklenirken hata meydana geldi. (hata {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"<span class='dialog-filename'>{0}</span> klasörü okunurken hata meydana geldi. (hata {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Dosya açılırken hata\",\n    \"ERROR_OPENING_FILE\"                : \"<span class='dialog-filename'>{0}</span> dosyası açılırken hata meydana geldi. {1}\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Değişiklikler hafızadan okunurken hata oluştu.\",\n    \"ERROR_RELOADING_FILE\"              : \"<span class='dialog-filename'>{0}</span> dosyası yenilenirken hata meydana geldi. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Dosya kaydedilirken hata\",\n    \"ERROR_SAVING_FILE\"                 : \"<span class='dialog-filename'>{0}</span> dosyası kaydedilirken hata meydana geldi. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"Dosya ismi değiştirilirken hata\",\n    \"ERROR_RENAMING_FILE\"               : \"<span class='dialog-filename'>{0}</span> dosyasının ismi değiştirilirken hata meydana geldi. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Hatalı dosya ismi\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Dosya isimleri yandaki karakterleri bulunduramaz: {0}\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Dosya yaratılırken hata\",\n    \"ERROR_CREATING_FILE\"               : \"<span class='dialog-filename'>{0}</span> dosyası yaratılırken hata meydana geldi. {1}\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"Ups! {APP_NAME} programı şuan tarayıcıda açılmadı.\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} HTML olarak hazırlandı, ancak şuan için masaüstünde çalışabilmekte. Bu nedenle makinanızda bulunan dosyalarda değişiklik için kullanabilirsiniz. {APP_NAME} programını çalıştırabilmek için lütfen <b>github.com/adobe/brackets-shell</b> adresindeki 'application shell'i kullanınız.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Dosyalar indekslenirken hata\",\n    \"ERROR_MAX_FILES\"                   : \"Maksimum sayıda dosya indekslendi. Indekslenen dosyalardaki işlemler düzgün çalışmayabilir.\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Tarayıcı çalıştırılırken hata\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"Google Chrome tarayıcısı bulunamadı. Lütfen kurulu olduğundan emin olun.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"Tarayıcı açılırken hata meydana geldi. (hata {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Canlı Önizleme Hatası\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"Tarayıcıya bağlanılıyor\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"Canlı önizleme özelliğini kullanabilmek için uzaktan hata ayıklayıcı ile Chrome'un tekrardan açılması gerekiyor.<br /><br />Chrome'u uzaktan hata ayıklayıcı ile tekrardan açılmasını ister misiniz?\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Canlı önizlemeyi çalıştırabilmeniz için html dosyası açmanız gerekiyor\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"Canlı Önizlemeyi server-side dosyalarınız ile açmak istiyorsanız, lütfen bu proje için kullanılabilir bir link belirtiniz.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"Canlı Önizlemeye Hoşgeldiniz!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"Canlı önizleme için {APP_NAME} programı tarayıcınıza bağlanıyor ve sizin HTML dosyanızın örnek görüntüsünü tarayıcınızda açıyor. Sonrasında ise değişiklik yaptığınız sayfayı anında tarayıcıda yenileyerek gösteriyor.<br /><br />{APP_NAME} programının bu versiyonunda, Canlı önizleme özelliği sadece <strong>CSS dosyaları</strong> değişikliğine izin veriyor ve sadece <strong>Google Chrome</strong> üzerinde çalışıyor. Yakında HTML ve Javascript değişikliğini de ekleyeceğiz!<br /><br />(Bu mesaj sadece tek sefer gösterilecektir.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"Detaylı bilgi için lütfen <a href='{0}' title='{0}'>Troubleshooting Live Development connection errors</a> sayfasına bakınız.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Canlı Önizleme\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Canlı Önizleme: Bağlanılıyor\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Canlı Önizleme: Başlıyor\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Canlı Önizleme'den Çık\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"Canlı Önizleme: Kapatmak için tıklayın (Yenilemek için dosyayı kaydedin)\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"Değişiklikleri kaydet\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"<span class='dialog-filename'>{0}</span> dosyasında yaptığınız değişiklikleri kaydetmek istiyor musunuz?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Dosyalardaki değişiklikleri kaydetmek istiyor musunuz?\",\n    \"EXT_MODIFIED_TITLE\"                : \"Harici değişiklikler\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> dosyası dışarıdan değiştirildi ama {APP_NAME} programında kaydetmediğiniz değişiklikler bulunmakta.<br /><br />Hangi versiyonun kalmasını istiyorsunuz?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> dosyası hafızadan silind ama {APP_NAME} programında kaydetmediğiniz değişiklikler bulunmakta.<br /><br />Değişikliklerin kalmasını istiyor musunuz?\",\n\n    // Find, Replace, Find in Files\n    \"BUTTON_YES\"                        : \"Evet\",\n    \"BUTTON_NO\"                         : \"Hayır\",\n\n    \"OPEN_FILE\"                         : \"Dosya Aç\",\n    \"CHOOSE_FOLDER\"                     : \"Klasör Seç\",\n\n    \"RELEASE_NOTES\"                     : \"Yeni Versiyon Bilgileri\",\n    \"NO_UPDATE_TITLE\"                   : \"En son versiyon!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"{APP_NAME} programının en son versiyonunu kullanıyorsunuz.\",\n\n    \"FIND_IN_FILES_SCOPED\"              : \"<span class='dialog-filename'>{0}</span> dosyası içinde\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"proje içinde\",\n    \"FIND_IN_FILES_FILE\"                : \"dosya\",\n    \"FIND_IN_FILES_FILES\"               : \"dosyalar\",\n    \"FIND_IN_FILES_MATCH\"               : \"eşleşen\",\n    \"FIND_IN_FILES_MATCHES\"             : \"eşleşenler\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"Daha fazla \",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"Dosya: <b>{0}</b>\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"Versiyon bilgisi alınırken hata\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"Sunucudan yeni versiyon bilgisi alınırken hata oluştu. Lütfen internete bağlı olduğunuzdan emin olun ve tekrar deneyin.\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"Proje Yükleniyor\\u2026\",\n    \"UNTITLED\" : \"Adsız\",\n    \"WORKING_FILES\"     : \"Çalışılan Dosyalar\",\n\n    /**\n     * Keyboard modifier names\n     */\n\n    \"KEYBOARD_CTRL\"   : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"  : \"Shift\",\n    \"KEYBOARD_SPACE\"  : \"Boşluk\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"Satır {0}, Kolon {1}\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"Girintiyi boşluk karakterleriyle değiştirmek için tıklayın\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"Girintiyi tab karakterleriyle değiştirmek için tıklayın\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"Girintide kullanılacak boşluk sayısını değiştirmek için tıklayın\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"Tab karakter genişliğini değiştirmek için tıklayın\",\n    \"STATUSBAR_SPACES\"                      : \"Boşluk:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab Boyutu:\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"Dosya\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"Yeni\",\n    \"CMD_FILE_NEW\"                        : \"Yeni Dosya\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"Yeni Klasör\",\n    \"CMD_FILE_OPEN\"                       : \"Aç\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Çalışma Ekranına Ekle\",\n    \"CMD_OPEN_FOLDER\"                     : \"Klasörü Aç\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Kapat\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Hepsini Kapat\",\n    \"CMD_FILE_SAVE\"                       : \"Kaydet\",\n    \"CMD_FILE_SAVE_AS\"                    : \"Farklı Kaydet\\u2026\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Hepsini Kaydet\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Canlı Önizleme\",\n    \"CMD_PROJECT_SETTINGS\"                : \"Proje Ayarları\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"Yeniden Adlandır\",\n    \"CMD_EXTENSION_MANAGER\"               : \"Eklenti Yöneticisi\\u2026\",\n    \"CMD_FILE_DELETE\"                     : \"Sil\",\n    \"CMD_QUIT\"                            : \"Çık\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"Çıkış\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Düzenle\",\n    \"CMD_UNDO\"                            : \"Geri Al\",\n    \"CMD_REDO\"                            : \"Yinele\",\n    \"CMD_CUT\"                             : \"Kes\",\n    \"CMD_COPY\"                            : \"Kopyala\",\n    \"CMD_PASTE\"                           : \"Yapıştır\",\n    \"CMD_SELECT_ALL\"                      : \"Hepsini Seç\",\n    \"CMD_SELECT_LINE\"                     : \"Satırı Seç\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"Seçileni Satırlara Böl\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"Sonraki Satıra İmleç Ekle\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"Önceki Satıra İmleç Ekle\",\n    \"CMD_INDENT\"                          : \"Girinti Ekle\",\n    \"CMD_UNINDENT\"                        : \"Girintiyi Geri Al\",\n    \"CMD_DUPLICATE\"                       : \"Çoğalt\",\n    \"CMD_DELETE_LINES\"                    : \"Satırı Sil\",\n    \"CMD_COMMENT\"                         : \"Yorum Satırını Aç / Kapat\",\n    \"CMD_BLOCK_COMMENT\"                   : \"Yorum Bloğunu Aç / Kapat\",\n    \"CMD_LINE_UP\"                         : \"Satırı Yukarı Taşı\",\n    \"CMD_LINE_DOWN\"                       : \"Satırı Aşağıya Taşı\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"Parantezleri Otomatik Tamamla\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"Kod İpuçlarını Göster\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"Bul\",\n    \"CMD_FIND\"                            : \"Bul\",\n    \"CMD_FIND_NEXT\"                       : \"Sonrakini Bul\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Öncekini Bul\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"Hepsini Bul ve Seç\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"Sonraki Eşleşmeyi Seçime Ekle\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"Atla ve Sonraki Eşleşmeyi Ekle\",\n    \"CMD_FIND_IN_FILES\"                   : \"Dosyalarda Bul\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"\\u2026içinde bul\",\n    \"CMD_REPLACE\"                         : \"Değiştir\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"Göster\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Kenar Çubuğunu Gizle\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Kenar Çubuğunu Göster\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Font Boyutunu Büyült\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Font Boyutunu Küçült\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Font Boyutunu Sıfırla\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"Eklenmeye Göre Sırala\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"İsme Göre Sırala\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"Türüne Göre Sırala\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"Otomatik Sırala\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Git\",\n    \"CMD_QUICK_OPEN\"                      : \"Hızlı Aç\",\n    \"CMD_GOTO_LINE\"                       : \"Satıra Git\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Tanıma Git\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Hızlı Düzenle\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Önceki Eşleşme\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"İlk Hata veya Uyarıya Git\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Sonraki Eşleşme\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"Hızlı Erişim Dökümanları\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"Yeni Kural\",\n    \"CMD_NEXT_DOC\"                        : \"Sonraki Dosya\",\n    \"CMD_PREV_DOC\"                        : \"Önceki Dosya\",\n    \"CMD_SHOW_IN_TREE\"                    : \"Dosya Listesinde Göster\",\n    \"CMD_SHOW_IN_OS\"                      : \"Bulunduğu Konumu Aç\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"Yardım\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"{APP_NAME} Nasıl Kullanılır\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} Desteği\",\n    \"CMD_SUGGEST\"                         : \"Yeni Özellik Öner\",\n    \"CMD_RELEASE_NOTES\"                   : \"Sürüm Notları\",\n    \"CMD_GET_INVOLVED\"                    : \"Projeye Dahil Ol\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Eklentiler Klasörünü Göster\",\n    \"CMD_TWITTER\"                         : \"{TWITTER_NAME} Twitter'da...\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Yeni Versiyon Kontrol Et\",\n    \"CMD_ABOUT\"                           : \"{APP_TITLE} Hakkında\",\n    \"CMD_OPEN_PREFERENCES\"                : \"Ayarlar Dosyasını Aç\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"Deneysel Sürüm\",\n    \"OK\"                                   : \"Tamam\",\n    \"DONT_SAVE\"                            : \"Kaydetme\",\n    \"SAVE\"                                 : \"Kaydet\",\n    \"CANCEL\"                               : \"İptal\",\n    \"RELOAD_FROM_DISK\"                     : \"Hafızadan Yenile\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Değişiklikleri Editörde Tut\",\n    \"CLOSE_DONT_SAVE\"                      : \"Kapat (Kaydetme)\",\n    \"RELAUNCH_CHROME\"                      : \"Chrome'u Tekrar Aç\",\n    \"ABOUT\"                                : \"Hakkında\",\n    \"CLOSE\"                                : \"Kapat\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint 14 test sürümü\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Üçüncü parti yazılımlara ilişkin bildirimler, şartlar ve koşullar <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> adresinde bulunmaktadır ve bu adreste referans olarak dahil edilmiştir\",\n    \"ABOUT_TEXT_LINE4\"                     : \"Döküman ve kodlar için <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a> adresine bakabilirsiniz.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"{APP_NAME} programının yeni versiyonu bulunmakta! Detaylar için tıklayın.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Yeni versiyon hazır\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, {APP_NAME} programının yeni versiyonu hazır. İşte bazı yeni özellikler:\",\n    \"GET_IT_NOW\"                           : \"Şimdi Yükle!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"{0} için Proje Ayarları\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"Ana URL'den Canlı Önizleme\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"(dosya urlsi için boş bırakın)\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"{0} protokolü canlı önizlemeyi desteklemiyor.&mdash;lütfen http: or https: kullanın.\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"Ana URL \\\"{0}\\\" gibi arama karakterleri bulunduramaz.\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"Ana URL \\\"{0}\\\" gibi karakterler bulunduramaz.\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"'{0}' gibi özel karakterler %-kodlanması gerekiyor.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"Ana URL'yi işlerken bilinmeyen hata\",\n\n    // Extension Management strings\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"Eklenti Yöneticisi\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                           : \"Ayıkla\",\n    \"CMD_SHOW_DEV_TOOLS\"                   : \"Geliştirici Araçlarını Göster\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"         : \"Eklentiler Olmadan Yeniden Yükle\",\n    \"CMD_REFRESH_WINDOW\"                   : \"{APP_NAME} Ekranını Yenile\",\n    \"CMD_NEW_BRACKETS_WINDOW\"              : \"Yeni {APP_NAME} Ekranı\",\n    \"CMD_SWITCH_LANGUAGE\"                  : \"Dili Değiştir\",\n    \"CMD_RUN_UNIT_TESTS\"                   : \"Testleri Çalıştır\",\n    \"CMD_SHOW_PERF_DATA\"                   : \"Performans Bilgisini Göster\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"             : \"Node Hata Ayıklayıcısını Etkinleştir\",\n    \"CMD_LOG_NODE_STATE\"                   : \"Node Durumunu Konsola Yaz\",\n    \"CMD_RESTART_NODE\"                     : \"Node'u Yeniden Başlat\",\n\n    \"LANGUAGE_TITLE\"                       : \"Dili değiştir\",\n    \"LANGUAGE_MESSAGE\"                     : \"Lütfen aşağıdaki dillerden istediğiniz dili seçin:\",\n    \"LANGUAGE_SUBMIT\"                      : \"{APP_NAME} Yenile\",\n    \"LANGUAGE_CANCEL\"                      : \"İptal\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Tanıma Atla\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Parametre İpuçlarını Göster\",\n    \"NO_ARGUMENTS\"                              : \"<parametre yok>\"\n\n});\n"
  },
  {
    "path": "src/nls/tr/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_tr/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.tr\"\n});\n"
  },
  {
    "path": "src/nls/uk/strings.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                             : \"(помилка {0})\",\n    \"NOT_FOUND_ERR\"                             : \"Файл не знайдено.\",\n    \"NOT_READABLE_ERR\"                          : \"Не вдається прочитати файл.\",\n    \"EXCEEDS_MAX_FILE_SIZE\"                     : \"{APP_NAME} не працює з файлами, що перевищують {0} Мб.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"               : \"Не вдається внести зміни до цільової теки.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"          : \"Ваших повноважень недостатньо, аби вносити змінити.\",\n    \"CONTENTS_MODIFIED_ERR\"                     : \"Файл змінено за межами {APP_NAME}.\",\n    \"UNSUPPORTED_ENCODING_ERR\"                  : \"{APP_NAME} наразі підтримує тільки текстові файли у кодуванні UTF-8.\",\n    \"FILE_EXISTS_ERR\"                           : \"Файл або така уже існує.\",\n    \"FILE\"                                      : \"файл\",\n    \"FILE_TITLE\"                                : \"Файл\",\n    \"DIRECTORY\"                                 : \"тека\",\n    \"DIRECTORY_TITLE\"                           : \"Тека\",\n    \"DIRECTORY_NAMES_LEDE\"                      : \"Назви тек\",\n    \"FILENAMES_LEDE\"                            : \"Назви файлів\",\n    \"FILENAME\"                                  : \"Назва файлу\",\n    \"DIRECTORY_NAME\"                            : \"Назва теки\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"                     : \"Помилка завантаження проекту\",\n    \"OPEN_DIALOG_ERROR\"                         : \"Під час показу діалогу відкриття файлу виникла помилка. (помилка {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"          : \"Виникла помилка під час спроби відкрити теку <span class=\\'dialog-filename\\'>{0}</span>. (помилка {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"              : \"Виникла помилка під час спроби прочитати вміст теки <span class=\\'dialog-filename\\'>{0}</span>. (помилка {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"                  : \"Помилка відкриття файлу\",\n    \"ERROR_OPENING_FILE\"                        : \"Виникла помилка під час спроби відкрити файл <span class=\\'dialog-filename\\'>{0}</span>. {1}\",\n    \"ERROR_OPENING_FILES\"                       : \"Під час відкриття наступних файлів виникли помилки:\",\n    \"ERROR_RELOADING_FILE_TITLE\"                : \"Помилка перевантаження змін з диску\",\n    \"ERROR_RELOADING_FILE\"                      : \"Сталась помилка під час спроби перевантаження файлу <span class=\\'dialog-filename\\'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"                   : \"Помилка збереження файлу\",\n    \"ERROR_SAVING_FILE\"                         : \"Сталась помилка під час спроби збереження файлу <span class=\\'dialog-filename\\'>{0}</span>. {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"                 : \"Помилка під час перейменування {0}\",\n    \"ERROR_RENAMING_FILE\"                       : \"Сталась помилка під час спроби перейменувати файл {2} <span class=\\'dialog-filename\\'>{0}</span>. {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"                 : \"Помилка видалення {0}\",\n    \"ERROR_DELETING_FILE\"                       : \"Сталась помилка під час проби видалити {2} <span class=\\'dialog-filename\\'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"                    : \"Невірна {0}\",\n    \"INVALID_FILENAME_MESSAGE\"                  : \"{0} не може містити зарезервованих слів, закінчуватись крапками (.) та використовувати наступні симовли: <code class=\\'emphasized\\'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"               : \"Файл або тека з назвою <span class=\\'dialog-filename\\'>{0}</span> уже існує.\",\n    \"ERROR_CREATING_FILE_TITLE\"                 : \"Помилка створення {0}\",\n    \"ERROR_CREATING_FILE\"                       : \"Сталась помилка під час спроби створити файл {0} <span class=\\'dialog-filename\\'>{1}</span>. {2}\",\n    \"ERROR_MIXED_DRAGDROP\"                      : \"Не можна відкривати теку одночасно відкриваючи інші файли\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                        : \"Не вдалось прочитати карту прив’язок клавіш\",\n    \"ERROR_KEYMAP_CORRUPT\"                      : \"У вашому файлі помилкова структура JSON. Файли буде відкрито, аби ви могли її виправити.\",\n    \"ERROR_LOADING_KEYMAP\"                      : \"Ваш файл не у кодуванні UTF-8 і не може бути завантаженим\",\n    \"ERROR_RESTRICTED_COMMANDS\"                 : \"Ви не можете переприв’язати клавіатурні скорочення для команд: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"                : \"Ви не можете переприв’язати ці клавіатурні скорочення: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"                  : \"Ви переприв’язуєте кілька клавіатурних скорочень для команд: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"                 : \"У вас кілька прив’язок до цих комбінацій: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"                   : \"Це клавіатурне скорочення помилкове: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"                : \"Ви назначили клавіатурне скорочення для неіснуючій команді: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"                 : \"Помилка читання налаштувань\",\n    \"ERROR_PREFS_CORRUPT\"                       : \"Ваш файл налаштувань не відповідає правилам формату JSON. Файл буде відкрито для виправлення. Після цього потрібно буде перезапустити {APP_NAME}, аби зміни набули чинності.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"                    : \"Ой! {APP_NAME} ще не працює у браузерах.\",\n    \"ERROR_IN_BROWSER\"                          : \"{APP_NAME} створено на базі веб-технологій, але наразі працює як звичайна програма аби мати змогу редагувати локальні файли. Будь ласка, скористайтесь спеціальною оболонкою на <b>github.com/adobe/brackets-shell</b> для запуску {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"                     : \"Помилка індексації файлів\",\n    \"ERROR_MAX_FILES\"                           : \"Цей проект містить більше 30 000 файлів. Функції, що оперують кількома файлам можуть не працювати правильно або вимкнутись. <a href=\\'https://github.com/adobe/brackets/wiki/Large-Projects\\'>Дізнайтесь більше про роботу програми під час відкриття великих проектів</a>.\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"             : \"Помилка запуску браузера\",\n    \"ERROR_CANT_FIND_CHROME\"                    : \"Не знайдено браузер Google Chrome. Переконайтесь, будь ласка, що він встановлений.\",\n    \"ERROR_LAUNCHING_BROWSER\"                   : \"Під час запуску браузера сталася помилка. (помилка {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"              : \"Помилка Live Preview\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"           : \"Підключення до броузера\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"            : \"Live Preview потребує перезапустити Chrome з увімкненням віддаленого відлагодження.<br /><br />Бажаєте виконати це?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"            : \"Помилка завантаження сторінки Live Preview.\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"                : \"Відкрийте файл HTML або ж переконайтесь, що для запуску live preview у вашому проекті існує файл index.html.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"             : \"Аби запустити live preview з серверним файлом, вам варто вказати базову адресу для цього проекту.\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\"         : \"Помилка запуску HTTP-сервера для live preview. Будь ласка, спробуйте пізніше.\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"               : \"Вітаємо у Live Preview!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"             : \"Live Preview підключає {APP_NAME} до вашого браузера та забезпечує попередній перегляд файлів HTML. Функція оновлює попередній перегляд одразу, як ви вносите зміни в код.<br /><br />У цій ранній збірці {APP_NAME}, Live Preview працює тільки з <strong>Google Chrome</strong> і оновлення в реальному часі відображається тільки для <strong>файлів CSS та HTML</strong>. Зміни до файлів JavaScript вносяться автоматично під час збереження.<br /><br />(Це повідомлення більше не турбуватиме вас.)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"          : \"Для докладнішої інформації погляньте на <a href=\\'{0}\\' title=\\'{0}\\'>пошук та усунення помилок підключення Live Preview</a>.\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\"         : \"Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"             : \"Live Preview: Підключення\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"             : \"Live Preview: Ініціалізація\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"             : \"Відключити Live Preview\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"           : \"Live Preview (збережіть файл для оновлення)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"            : \"Live Preview (не оновлюється, якщо є помилки)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\"  : \"Live Preview зупинено, оскільки в браузері відкрито панель інструментів розробника\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"           : \"Live Preview зупинено, оскільки сторінку закрито в браузері\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                   : \"Live Preview зупинено, оскільки браузер перенаправлено на сторінку, що не є частиною поточного проекту\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"            : \"Live Preview скасовано з невідомих причин ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                          : \"Зберегти зміни\",\n    \"SAVE_CLOSE_MESSAGE\"                        : \"Чи бажаєте ви зберегти зміни внесені у файл <span class=\\'dialog-filename\\'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"                  : \"Чи бажаєте ви зберегти зміни до наступних файлів?\",\n    \"EXT_MODIFIED_TITLE\"                        : \"Зовнішні зміни\",\n    \"CONFIRM_DELETE_TITLE\"                      : \"Підтвердження видалення\",\n    \"CONFIRM_FOLDER_DELETE\"                     : \"Ви дійсно хочете видалити теку <span class=\\'dialog-filename\\'>{0}</span>?\",\n    \"FILE_DELETED_TITLE\"                        : \"Файл видалено\",\n    \"EXT_MODIFIED_WARNING\"                      : \"<span class=\\'dialog-filename\\'>{0}</span> змінено на диску.<br /><br />Чи ви хочете зберегти файл і перезаписати ці зміни?\",\n    \"EXT_MODIFIED_MESSAGE\"                      : \"<span class=\\'dialog-filename\\'>{0}</span> змінено на диску, проте існують також не збережені зміни у {APP_NAME}.<br /><br />Яку версію ви бажаєте лишити?\",\n    \"EXT_DELETED_MESSAGE\"                       : \"<span class=\\'dialog-filename\\'>{0}</span> видалено з диску, але {APP_NAME} містить не збережені в нього зміни.<br /><br />Чи бажаєте ви залишити їх?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                                      : \"Готово\",\n    \"OK\"                                        : \"OK\",\n    \"CANCEL\"                                    : \"Скасувати\",\n    \"DONT_SAVE\"                                 : \"Не зберігати зміни\",\n    \"SAVE\"                                      : \"Зберегти\",\n    \"SAVE_AS\"                                   : \"Зберегти як\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                        : \"Перезаписати\",\n    \"DELETE\"                                    : \"Видалити\",\n    \"BUTTON_YES\"                                : \"Так\",\n    \"BUTTON_NO\"                                 : \"Ні\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                          : \"{0} з {1}\",\n    \"FIND_NO_RESULTS\"                           : \"Жодних результатів\",\n    \"FIND_QUERY_PLACEHOLDER\"                    : \"Хочу знайти\\u2026\",\n    \"REPLACE_PLACEHOLDER\"                       : \"Замінити на\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                        : \"Усе\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"               : \"Замінити\\u2026\",\n    \"BUTTON_REPLACE\"                            : \"Замінити\",\n    \"BUTTON_NEXT\"                               : \"\\u25B6\",\n    \"BUTTON_PREV\"                               : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                          : \"Наступний збіг\",\n    \"BUTTON_PREV_HINT\"                          : \"Попередній збіг\",\n    \"BUTTON_CASESENSITIVE_HINT\"                 : \"Враховувати регістр\",\n    \"BUTTON_REGEXP_HINT\"                        : \"Регулярний вираз\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\"        : \"Замінити без можливості скасування\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"              : \"Оскільки більше {0} файлів потрібно змінити, {APP_NAME} виконає заміну невідкритих файлів безпосередньо на диску.<br />Ви не зможете скасувати цю дію.\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"               : \"Замінити без можливості скасування\",\n\n    \"OPEN_FILE\"                                 : \"Відкрити файл\",\n    \"SAVE_FILE_AS\"                              : \"Зберегти файл\",\n    \"CHOOSE_FOLDER\"                             : \"Оберіть теку\",\n\n    \"RELEASE_NOTES\"                             : \"Примітки до випуску\",\n    \"NO_UPDATE_TITLE\"                           : \"У вас найновіша версія!\",\n    \"NO_UPDATE_MESSAGE\"                         : \"Ви користуєтесь останньою версією {APP_NAME}.\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"                  : \"Заміна\",\n    \"FIND_REPLACE_TITLE_WITH\"                   : \"на\",\n    \"FIND_TITLE_LABEL\"                          : \"Знайдене\",\n    \"FIND_TITLE_SUMMARY\"                        : \"&mdash; {0} {1} {2} у {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                            : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"                      : \"у <span class=\\'dialog-filename\\'>{0}</span>\",\n    \"FIND_IN_FILES_NO_SCOPE\"                    : \"у проекті\",\n    \"FIND_IN_FILES_ZERO_FILES\"                  : \"Фільтр не включає всі файли {0}\",\n    \"FIND_IN_FILES_FILE\"                        : \"файл\",\n    \"FIND_IN_FILES_FILES\"                       : \"файлів\",\n    \"FIND_IN_FILES_MATCH\"                       : \"збіг\",\n    \"FIND_IN_FILES_MATCHES\"                     : \"збігів\",\n    \"FIND_IN_FILES_MORE_THAN\"                   : \"Більше \",\n    \"FIND_IN_FILES_PAGING\"                      : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"                   : \"<span class=\\'dialog-filename\\'>{0}</span> {2} <span class=\\'dialog-path\\'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"             : \"Ctrl/Cmd+клік згорнути/розгорнути все\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"             : \"Помилки під час заміни\",\n    \"REPLACE_IN_FILES_ERRORS\"                   : \"Наступні файли не змінено, оскільки вони змінились після пошуку аби недоступні для запису.\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"          : \"Сталась помилка під час отримання даних про оновлення\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"            : \"Помилка отримання з сервера інформації про оновлення. Переконайтесь, що маєте доступ до інтернету та спробуйте знову.\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                           : \"Новий набір виключень\\u2026\",\n    \"CLEAR_FILE_FILTER\"                         : \"Не виключати файли\",\n    \"NO_FILE_FILTER\"                            : \"Жодного файлу не виключено\",\n    \"EXCLUDE_FILE_FILTER\"                       : \"Не включати {0}\",\n    \"EDIT_FILE_FILTER\"                          : \"Змінити\\u2026\",\n    \"FILE_FILTER_DIALOG\"                        : \"Змінити набір виключень\",\n    \"FILE_FILTER_INSTRUCTIONS\"                  : \"Всі файли та таки, що підпадають під ці рядки, підрядки або <a href=\\'{0}\\' title=\\'{0}\\'>шаблони</a> будуть виключені. Вказуйте кожне правило з нового рядка.\",\n    \"FILTER_NAME_PLACEHOLDER\"                   : \"Назва набору виключень (не обов’язково)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"                : \"і ще {0}\",\n    \"FILTER_COUNTING_FILES\"                     : \"Підрахунок файлів\\u2026\",\n    \"FILTER_FILE_COUNT\"                         : \"Відбирає {0} з {1} файлів {2}\",\n    \"FILTER_FILE_COUNT_ALL\"                     : \"Відбирає всі {0} файлів {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"       : \"Швидке редагування не доступне для поточного розміщення курсора\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"         : \"Швидке редагування CSS: помістіть курсор на один клас\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"          : \"Швидке редагування CSS: атрибут класу незавершено\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"             : \"Швидке редагування CSS: атрибут ID незавершено\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"        : \"Швидке редагування CSS: помістіть курсор на мітку, клас або ID\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"       : \"Швидке редагування часової функції CSS: невірний синтаксис\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"        : \"Швидке редагування JS: помістіть курсор на назву функції\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"       : \"Для поточного розміщення курсора швидка документація відсутня\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"                           : \"Завантаження\\u2026\",\n    \"UNTITLED\"                                  : \"Без-назви\",\n    \"WORKING_FILES\"                             : \"Робочі файли\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"                                       : \"Верхня\",\n    \"BOTTOM\"                                    : \"Нижня\",\n    \"LEFT\"                                      : \"Ліва\",\n    \"RIGHT\"                                     : \"Права\",\n\n    \"CMD_SPLITVIEW_NONE\"                        : \"Не розділяти\",\n    \"CMD_SPLITVIEW_VERTICAL\"                    : \"Вертикальне розділення\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"                  : \"Горизонтальне розділення\",\n    \"SPLITVIEW_MENU_TOOLTIP\"                    : \"Розділити редактор горизонтально або вертикально\",\n    \"GEAR_MENU_TOOLTIP\"                         : \"Налаштувати робочий набір\",\n\n    \"SPLITVIEW_INFO_TITLE\"                      : \"Уже відкрито\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"               : \"Цей файл відкрито в іншій панелі. {APP_NAME} незабаром підтримуватиме відкриття файлу в кількох панелях одночасно. А до того часу, файл буде показуватись у тій панелі, у якій уже відкритий.<br /><br />(Ви більше не бачитимете цього повідомлення.)\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"                             : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"                            : \"Shift\",\n    \"KEYBOARD_SPACE\"                            : \"Пробіл\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"                 : \"Рядок {0}, Стовпець {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"           : \"\\u2014 Обрано {0} стовпець\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"             : \"\\u2014 Обрано {0} стовпців\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"         : \"\\u2014 Обрано {0} рядок\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"           : \"\\u2014 Обрано {0} рядків\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"              : \"\\u2014 обрано {0}\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"           : \"Натисніть, аби перемкнути відступи а пробіли\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"             : \"Натисніть, аби перемкнути відступи а ьаби\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"      : \"Натисніть, аби змінити кількість пробілів для відступів\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"        : \"Натисніть, аби змінити ширину символа вкладки\",\n    \"STATUSBAR_SPACES\"                          : \"Пробіли:\",\n    \"STATUSBAR_TAB_SIZE\"                        : \"Розмір вкладки:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"             : \"\\u2014 {0} Рядок\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"               : \"\\u2014 {0} Рядків\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"        : \"Розширення вимкнено\",\n    \"STATUSBAR_INSERT\"                          : \"ВСТ\",\n    \"STATUSBAR_OVERWRITE\"                       : \"ПРЗ\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"                  : \"Натисніть, аби перемкнути режим курсору між вставкою (ВСТ) та перезаписом (ПРЗ)\",\n    \"STATUSBAR_LANG_TOOLTIP\"                    : \"Натисніть, аби змінити тип файлу\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"         : \"{0}. Натисніть, аби перемкнути панель повідомлень.\",\n    \"STATUSBAR_DEFAULT_LANG\"                    : \"(типово)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"                : \"Встановити типовим для файлів .{0}\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"               : \"{0} Помилок\",\n    \"SINGLE_ERROR\"                              : \"1 помилка {0}\",\n    \"MULTIPLE_ERRORS\"                           : \"{0} помилок {1}\",\n    \"NO_ERRORS\"                                 : \"Не знайдено жодної помилки {0} – гарна робота!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"               : \"Не знайдено жодної помилки – гарна робота!\",\n    \"LINT_DISABLED\"                             : \"Аналіз вимкнено\",\n    \"NO_LINT_AVAILABLE\"                         : \"Для {0} відсутній аналізатор\",\n    \"NOTHING_TO_LINT\"                           : \"Нічого аналізувати\",\n    \"LINTER_TIMED_OUT\"                          : \"Аналізатором {0} перевищено час очікування у {1} мс\",\n    \"LINTER_FAILED\"                             : \"Аналізатор {0} завершився з помилкою: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                                 : \"Файл\",\n    \"CMD_FILE_NEW_UNTITLED\"                     : \"Новий\",\n    \"CMD_FILE_NEW\"                              : \"Новий файл\",\n    \"CMD_FILE_NEW_FOLDER\"                       : \"Нова тека\",\n    \"CMD_FILE_OPEN\"                             : \"Відкрити\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"                    : \"Відкрити у робочому наборі\",\n    \"CMD_OPEN_DROPPED_FILES\"                    : \"Відкрити вкинуті файли\",\n    \"CMD_OPEN_FOLDER\"                           : \"Відкрити теку\\u2026\",\n    \"CMD_FILE_CLOSE\"                            : \"Закрити\",\n    \"CMD_FILE_CLOSE_ALL\"                        : \"Закрити все\",\n    \"CMD_FILE_CLOSE_LIST\"                       : \"Закрити список\",\n    \"CMD_FILE_CLOSE_OTHERS\"                     : \"Закрити інші\",\n    \"CMD_FILE_CLOSE_ABOVE\"                      : \"Закрити інші ті що вище\",\n    \"CMD_FILE_CLOSE_BELOW\"                      : \"Закрити інші ті що нижче\",\n    \"CMD_FILE_SAVE\"                             : \"Зберегти\",\n    \"CMD_FILE_SAVE_ALL\"                         : \"Зберегти все\",\n    \"CMD_FILE_SAVE_AS\"                          : \"Зберегти як\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"                     : \"Live Preview\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"                   : \"Примусово перезапустити Live Preview\",\n    \"CMD_PROJECT_SETTINGS\"                      : \"Налаштування проекту\\u2026\",\n    \"CMD_FILE_RENAME\"                           : \"Перейменувати\",\n    \"CMD_FILE_DELETE\"                           : \"Видалити\",\n    \"CMD_INSTALL_EXTENSION\"                     : \"Встановити розширення\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"                     : \"Менеджер розширень\\u2026\",\n    \"CMD_FILE_REFRESH\"                          : \"Оновити дерево файлів\",\n    \"CMD_QUIT\"                                  : \"Покинути програму\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                                  : \"Вийти\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                                 : \"Змінити\",\n    \"CMD_UNDO\"                                  : \"Відмінити\",\n    \"CMD_REDO\"                                  : \"Повторити\",\n    \"CMD_CUT\"                                   : \"Вирізати\",\n    \"CMD_COPY\"                                  : \"Копіювати\",\n    \"CMD_PASTE\"                                 : \"Вставити\",\n    \"CMD_SELECT_ALL\"                            : \"Обрати все\",\n    \"CMD_SELECT_LINE\"                           : \"Обрати рядок\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"                  : \"Розбити виділене на рядки\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"                  : \"Додати курсор на наступний рядок\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"                  : \"Додати курсор на попередній рядок рядок\",\n    \"CMD_INDENT\"                                : \"Зробити відступ\",\n    \"CMD_UNINDENT\"                              : \"Забрати відступ\",\n    \"CMD_DUPLICATE\"                             : \"Дублювати\",\n    \"CMD_DELETE_LINES\"                          : \"Вилучити рядок\",\n    \"CMD_COMMENT\"                               : \"Перемкнути рядковий коментар\",\n    \"CMD_BLOCK_COMMENT\"                         : \"Перемкнути блочний коментар\",\n    \"CMD_LINE_UP\"                               : \"Перемістити рядок угору\",\n    \"CMD_LINE_DOWN\"                             : \"Перемісти рядок униз\",\n    \"CMD_OPEN_LINE_ABOVE\"                       : \"Відкрити рядок вище\",\n    \"CMD_OPEN_LINE_BELOW\"                       : \"Відкрити рядок нижче\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"                 : \"Автозакривання дужок\",\n    \"CMD_SHOW_CODE_HINTS\"                       : \"Показувати поради до коду\",\n\n    // Search menu commands\n    \"FIND_MENU\"                                 : \"Пошук\",\n    \"CMD_FIND\"                                  : \"Знайти\",\n    \"CMD_FIND_NEXT\"                             : \"Знайти наступний\",\n    \"CMD_FIND_PREVIOUS\"                         : \"Знайти попередній\",\n    \"CMD_FIND_ALL_AND_SELECT\"                   : \"Знайти все та виділити\",\n    \"CMD_ADD_NEXT_MATCH\"                        : \"Додати наступний збіг до виділення\",\n    \"CMD_SKIP_CURRENT_MATCH\"                    : \"Пропустити поточний збіг\",\n    \"CMD_FIND_IN_FILES\"                         : \"Знайти у файлах\",\n    \"CMD_FIND_IN_SUBTREE\"                       : \"Знайти у\\u2026\",\n    \"CMD_REPLACE\"                               : \"Замінити\",\n    \"CMD_REPLACE_IN_FILES\"                      : \"Замінити у файлах\",\n    \"CMD_REPLACE_IN_SUBTREE\"                    : \"Замінити\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                                 : \"Вигляд\",\n    \"CMD_HIDE_SIDEBAR\"                          : \"Приховати бокову панель\",\n    \"CMD_SHOW_SIDEBAR\"                          : \"Показати бокову панель\",\n    \"CMD_INCREASE_FONT_SIZE\"                    : \"Збільшити розмір шрифту\",\n    \"CMD_DECREASE_FONT_SIZE\"                    : \"Зменшити розмір шрифту\",\n    \"CMD_RESTORE_FONT_SIZE\"                     : \"Відновити типовий шрифт\",\n    \"CMD_SCROLL_LINE_UP\"                        : \"Прокрутити на рядок вгору\",\n    \"CMD_SCROLL_LINE_DOWN\"                      : \"Прокрутити на рядок вниз\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"                   : \"Номери рядків\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"                    : \"Підсвічувати активний рядок\",\n    \"CMD_TOGGLE_WORD_WRAP\"                      : \"Перенесення слів\",\n    \"CMD_LIVE_HIGHLIGHT\"                        : \"Виділяти у Live Preview\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"                : \"Аналізувати файли під час збереження\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"              : \"Впорядкувати за додаванням\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"               : \"Впорядкувати за назвою\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"               : \"Впорядкувати за типом\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"              : \"Автоматичне впорядкування\",\n    \"CMD_THEMES\"                                : \"Теми\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                             : \"Навігація\",\n    \"CMD_QUICK_OPEN\"                            : \"Швидке відкриття\",\n    \"CMD_GOTO_LINE\"                             : \"Перейти до рядка\",\n    \"CMD_GOTO_DEFINITION\"                       : \"Швидкий пошук оголошення\",\n    \"CMD_GOTO_FIRST_PROBLEM\"                    : \"Перейти до найближчої помилки\",\n    \"CMD_TOGGLE_QUICK_EDIT\"                     : \"Швидке редагування\",\n    \"CMD_TOGGLE_QUICK_DOCS\"                     : \"Швидка документація\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"                 : \"Попередній збіг\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"                 : \"Наступний збіг\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"               : \"Нове правило\",\n    \"CMD_NEXT_DOC\"                              : \"Наступний документ\",\n    \"CMD_PREV_DOC\"                              : \"Попередній документ\",\n    \"CMD_SHOW_IN_TREE\"                          : \"Показати у дереві файлів\",\n    \"CMD_SHOW_IN_EXPLORER\"                      : \"Показати у провіднику\",\n    \"CMD_SHOW_IN_FINDER\"                        : \"Показати у Finder\",\n    \"CMD_SHOW_IN_OS\"                            : \"Показати у ОС\",\n\n    // Help menu commands\n    \"HELP_MENU\"                                 : \"Допомога\",\n    \"CMD_CHECK_FOR_UPDATE\"                      : \"Перевірити наявність оновлень\",\n    \"CMD_HOW_TO_USE_BRACKETS\"                   : \"Як використовувати {APP_NAME}\",\n    \"CMD_SUPPORT\"                               : \"Підтримка {APP_NAME}\",\n    \"CMD_SUGGEST\"                               : \"Запропонувати ідею\",\n    \"CMD_RELEASE_NOTES\"                         : \"Примітки до випуску\",\n    \"CMD_GET_INVOLVED\"                          : \"Прийняти участь в розробці\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"                : \"Показати теку розширень\",\n    \"CMD_HOMEPAGE\"                              : \"Домівка {APP_TITLE}\",\n    \"CMD_TWITTER\"                               : \"{TWITTER_NAME} у Twitter\",\n    \"CMD_ABOUT\"                                 : \"Про {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                      : \"Відкрити файл налаштувань\",\n    \"CMD_OPEN_KEYMAP\"                           : \"Відкрити карту клавіатурних скорочень\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                        : \"експериментальна збірка\",\n    \"RELEASE_BUILD\"                             : \"збірка\",\n    \"DEVELOPMENT_BUILD\"                         : \"тестова збірка\",\n    \"RELOAD_FROM_DISK\"                          : \"Завантажити з диска\",\n    \"KEEP_CHANGES_IN_EDITOR\"                    : \"Залишити зміни в редакторі\",\n    \"CLOSE_DONT_SAVE\"                           : \"Закрити (без збереження)\",\n    \"RELAUNCH_CHROME\"                           : \"Перезапустити Chrome\",\n    \"ABOUT\"                                     : \"Про програму\",\n    \"CLOSE\"                                     : \"Закрити\",\n    \"ABOUT_TEXT_LINE1\"                          : \"Версія {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"                : \"часова мітка збирання:\",\n    \"ABOUT_TEXT_LINE3\"                          : \"Зауважте, що правила та умови використання комерційного програмного забезпечення розміщенні на <a href=\\'{ADOBE_THIRD_PARTY}\\'>{ADOBE_THIRD_PARTY}</a> і наводяться тут в якості посилання.\",\n    \"ABOUT_TEXT_LINE4\"                          : \"Документація та сирці доступні на <a href=\\'https://github.com/adobe/brackets/\\'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                          : \"Створено з \\u2764 та JavaScript авторами:\",\n    \"ABOUT_TEXT_LINE6\"                          : \"Значна кількість людей (але наразі існують проблеми із завантаженням даних про них).\",\n    \"ABOUT_TEXT_MDN_DOCS\"                       : \"Документація та логотип MDN Docs поширюється на умовах ліцензії Creative Commons Attribution, <a href=\\'{MDN_DOCS_LICENSE}\\'>CC-BY-SA 2.5 Unported</a>.\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"               : \"Доступна нова збірка {APP_NAME}! Натисніть тут аби дізнатись деталі.\",\n    \"UPDATE_AVAILABLE_TITLE\"                    : \"Доступне оновлення\",\n    \"UPDATE_MESSAGE\"                            : \"Агов! Доступна нова збірка {APP_NAME}. Ось кілька функцій, що з’явилися:\",\n    \"GET_IT_NOW\"                                : \"Забрати негайно!\",\n    \"PROJECT_SETTINGS_TITLE\"                    : \"Налаштування проекту для: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"                  : \"Базова адреса Live Preview\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"             : \"Уведіть URL кшталту http://localhost:8000/, аби користуватись локальним сервером\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"            : \"Протокол {0} не підтримується Preview&mdash;будь ласка, використовуйте http: або https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"           : \"Базова адреса не може містити параметри пошуку, кшталту \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"             : \"Базова адреса не може містити хеші кшталту \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"                : \"Спеціальні символи, кшталту \\'{0}\\', мають бути з обох боків заключені у %.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"               : \"Неочікувана помилка розбору базової адреси\",\n    \"EMPTY_VIEW_HEADER\"                         : \"<em>Відкрийте файл, поки ця панель у фокусі</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                             : \"Поточна тема\",\n    \"USE_THEME_SCROLLBARS\"                      : \"Брати панель прокрутки з теми\",\n    \"FONT_SIZE\"                                 : \"Розмір шрифту\",\n    \"FONT_FAMILY\"                               : \"Сімейство шрифтів\",\n    \"THEMES_SETTINGS\"                           : \"Налаштування тем\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                           : \"Нове правило\",\n\n    // Extension Management strings\n    \"INSTALL\"                                   : \"Встановити\",\n    \"UPDATE\"                                    : \"Оновити\",\n    \"REMOVE\"                                    : \"Вилучити\",\n    \"OVERWRITE\"                                 : \"Перезаписати\",\n    \"CANT_REMOVE_DEV\"                           : \"Розширення у теці \\\"dev\\\" потрібно видалити власноруч.\",\n    \"CANT_UPDATE\"                               : \"Оновлення не сумісне з цією версією {APP_NAME}.\",\n    \"CANT_UPDATE_DEV\"                           : \"Розширення у теці \\\"dev\\\" не можуть автоматично оновлюватись.\",\n    \"INSTALL_EXTENSION_TITLE\"                   : \"Встановлення розширень\",\n    \"UPDATE_EXTENSION_TITLE\"                    : \"Оновити розширення\",\n    \"INSTALL_EXTENSION_LABEL\"                   : \"URL розширення\",\n    \"INSTALL_EXTENSION_HINT\"                    : \"Посилання на zip-файл розширення або репозитарій GitHub\",\n    \"INSTALLING_FROM\"                           : \"Встановлення розширення з {0}\\u2026\",\n    \"INSTALL_SUCCEEDED\"                         : \"Встановлення вдалося!\",\n    \"INSTALL_FAILED\"                            : \"Встановлення не вдалося.\",\n    \"CANCELING_INSTALL\"                         : \"Скасування\\u2026\",\n    \"CANCELING_HUNG\"                            : \"Скасування встановлення займає багато часу. Схоже, на виникнення внутрішньої помилки.\",\n    \"INSTALL_CANCELED\"                          : \"Встановлення скасовано.\",\n    \"VIEW_COMPLETE_DESCRIPTION\"                 : \"Переглянути весь опис\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"                : \"Переглянути короткий опис\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                          : \"Завантажені дані не є zip-архівом.\",\n    \"INVALID_PACKAGE_JSON\"                      : \"Файл package.json – помилковий (помилка: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                      : \"Файл package.json не містить назви пакунку.\",\n    \"BAD_PACKAGE_NAME\"                          : \"{0} – помилкова назва пакунку.\",\n    \"MISSING_PACKAGE_VERSION\"                   : \"Файл package.json не містить версії пакунку.\",\n    \"INVALID_VERSION_NUMBER\"                    : \"Номер версії пакунку ({0}) – помилковий.\",\n    \"INVALID_BRACKETS_VERSION\"                  : \"У {APP_NAME} рядок сумісності ({0}) – помилковий.\",\n    \"DISALLOWED_WORDS\"                          : \"Слова ({1}) недозволені у полі {0}.\",\n    \"API_NOT_COMPATIBLE\"                        : \"Розширення не сумісне з цією версією {APP_NAME}. Його встановлено до теки disabled.\",\n    \"MISSING_MAIN\"                              : \"Пакунок не містить файлу main.js.\",\n    \"EXTENSION_ALREADY_INSTALLED\"               : \"Встановлення цього пакунка перезапише попередньо встановлене розширення. Ви впевнені?\",\n    \"EXTENSION_SAME_VERSION\"                    : \"Пакунок має ту ж версію що й наразі встановлена. Перезаписати?\",\n    \"EXTENSION_OLDER_VERSION\"                   : \"Версія пакунка {0} старіша ніж наразі встановлена ({1}). Перезаписати?\",\n    \"DOWNLOAD_ID_IN_USE\"                        : \"Внутрішня помилка: ID завантаження уже використовується.\",\n    \"NO_SERVER_RESPONSE\"                        : \"Не вдалось приєднатися до сервера.\",\n    \"BAD_HTTP_STATUS\"                           : \"Файл відсутній на сервері (HTTP {0}).\",\n    \"CANNOT_WRITE_TEMP\"                         : \"Помилка запису тимчасового файлу.\",\n    \"ERROR_LOADING\"                             : \"Розширення несподівано викликало помилку під час запуску.\",\n    \"MALFORMED_URL\"                             : \"Адреса недійсна. Перевірте, будь ласка, чи ви все вказали вірно.\",\n    \"UNSUPPORTED_PROTOCOL\"                      : \"Адреса має бути на протоколі http або https.\",\n    \"UNKNOWN_ERROR\"                             : \"Невідома внутрішня помилка.\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"                   : \"Менеджер розширень\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"              : \"Помилка отримання доступу до реєстру розширення. Будь ласка, спробуйте пізніше.\",\n    \"INSTALL_EXTENSION_DRAG\"                    : \"Перетягніть сюди .zip або\",\n    \"INSTALL_EXTENSION_DROP\"                    : \"Перетягніть .zip для встановлення\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"              : \"Встановлення/оновлення скасовано через наступні помилки:\",\n    \"INSTALL_FROM_URL\"                          : \"встановіть з URL\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"              : \"Перевірка\\u2026\",\n    \"EXTENSION_AUTHOR\"                          : \"Автор\",\n    \"EXTENSION_DATE\"                            : \"Дата\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"              : \"Це розширення потребує новішої версії {APP_NAME}.\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"              : \"Наразі це розширення працює зі старішими версіями {APP_NAME}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"       : \"Версія {0} цього розширення потребує новішої версії {APP_NAME}. Як варіант, ви можете встановити новішу версію {1}.\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"       : \"Версія {0} цього розширення працює тільки зі старішими версіями {APP_NAME}. Як варіант, ви можете встановити новішу версію {1}.\",\n    \"EXTENSION_NO_DESCRIPTION\"                  : \"Опис відсутній\",\n    \"EXTENSION_MORE_INFO\"                       : \"Докладніше...\",\n    \"EXTENSION_ERROR\"                           : \"Помилка розширення\",\n    \"EXTENSION_KEYWORDS\"                        : \"Ключові слова\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"            : \"Перекладено {0} мовами, включаючи вашу\",\n    \"EXTENSION_TRANSLATED_GENERAL\"              : \"Перекладено {0} мовами\",\n    \"EXTENSION_TRANSLATED_LANGS\"                : \"Це розширення перекладено наступними мовами: {0}\",\n    \"EXTENSION_INSTALLED\"                       : \"Встановлено\",\n    \"EXTENSION_UPDATE_INSTALLED\"                : \"Оновлення розширення завантажено і буде встановлено після перевантаження {APP_NAME}.\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"              : \"Пошук\",\n    \"EXTENSION_MORE_INFO_LINK\"                  : \"Більше\",\n    \"BROWSE_EXTENSIONS\"                         : \"Переглянути розширення\",\n    \"EXTENSION_MANAGER_REMOVE\"                  : \"Вилучити розшмрення\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"            : \"Не вдалось вилучити одне або кілька розширень: {0}. {APP_NAME} продовжить перезапуск.\",\n    \"EXTENSION_MANAGER_UPDATE\"                  : \"Оновити розширення\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"            : \"Не вдалось оновити одне або кілька розширень: {0}. {APP_NAME} продовжить перезапуск.\",\n    \"MARKED_FOR_REMOVAL\"                        : \"Помічено для вилучення\",\n    \"UNDO_REMOVE\"                               : \"Відмінити\",\n    \"MARKED_FOR_UPDATE\"                         : \"Помічено для оновлення\",\n    \"UNDO_UPDATE\"                               : \"Відмінити\",\n    \"CHANGE_AND_RELOAD_TITLE\"                   : \"Змінити розширення\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"                 : \"Аби оновити або вилучити помічені розширення, потрібно перезапустити {APP_NAME}. Вам буде запропоновано зберегти незбережені зміни.\",\n    \"REMOVE_AND_RELOAD\"                         : \"Вилучити розширення і перезапустити\",\n    \"CHANGE_AND_RELOAD\"                         : \"Змінити розширення і перезапустити\",\n    \"UPDATE_AND_RELOAD\"                         : \"Оновити розширення і перезапустити\",\n    \"PROCESSING_EXTENSIONS\"                     : \"Обробка змін розширення\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"                   : \"Не вдалось вилучити розширення {0} оскільки воно не встановлене.\",\n    \"NO_EXTENSIONS\"                             : \"Ви ще не маєте жодного розширення.<br>Натисніть на вкладку Доступні вище, аби щось встановити.\",\n    \"NO_EXTENSION_MATCHES\"                      : \"Жодне розширення не відповідає вашому запиту.\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"             : \"ЗАУВАЖТЕ: Ці розширення поширюються різними авторами і не тільки від {APP_NAME}. Вони не перевіряються і мають повні локальні права. Будьте обережні під час встановлення розширень з невідомих джерел\",\n    \"EXTENSIONS_INSTALLED_TITLE\"                : \"Встановлені\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"                : \"Доступні\",\n    \"EXTENSIONS_THEMES_TITLE\"                   : \"Теми\",\n    \"EXTENSIONS_UPDATES_TITLE\"                  : \"Оновлення\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"                  : \"Нічого не знайдено.\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"              : \"Всі збіги згорнуто. Розгортайте файли наведені справа, аби переглянути збіги.\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"                 : \"Жодне правило CSS, що відповідає виділенню.<br> Натисніть \\'Нове правило\\' для створення. \",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"             : \"У вашому проекті відсутні таблиці стилів.<br>Створіть хоча б одну аби мати можливість додавати CSS-правила.\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"                 : \"найбільша\",\n\n    /**\n     * Unit names\n     */\n\n    \"UNIT_PIXELS\"                               : \"пікселі\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"Відлагодження\",\n    \"ERRORS\"                                    : \"Помилки\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"Показати інструменти розробника\",\n    \"CMD_REFRESH_WINDOW\"                        : \"Перезапустити з розширеннями\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"Перезапустити без розширень\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"Нове вікно {APP_NAME}\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"Змінити мову\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"Запустити тестування\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"Показати дані продуктивності\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"Увімкнути відлагоджувач Node\",\n    \"CMD_LOG_NODE_STATE\"                        : \"Логувати статус Node до консолі\",\n    \"CMD_RESTART_NODE\"                          : \"Перезапустити Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"Показати помилки у рядку стану\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"Відкрити код Brackets\",\n\n    \"LANGUAGE_TITLE\"                            : \"Змінити мову\",\n    \"LANGUAGE_MESSAGE\"                          : \"Мова:\",\n    \"LANGUAGE_SUBMIT\"                           : \"Перезапустити {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"Скасувати\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"Типова в системі\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"Час\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"Просування\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> Переміщення обраної точки<br><kbd class=\\'text\\'>Shift</kbd> Переміщення на 10 одиниць<br><kbd class=\\'text\\'>Tab</kbd> Навігація точками\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> Збільшення та зменшення кроку<br><kbd>←</kbd><kbd>→</kbd> \\'Початок\\' та \\'кінець\\'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"Старе значення <code>{0}</code> – невірне, тому функцію змінено на <code>{1}</code>. Документ буде оновлено після першого редагування.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"Поточний колір\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"Початковий колір\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"Формат RGBa\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"Формат Hex\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"Формат HSLa\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (використано {1} раз)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (використано {1} разів)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"Перейти до оголошення\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"Показувати підсвічування параметрів функції\",\n    \"NO_ARGUMENTS\"                              : \"<параметри відсутні>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"Помилка виведення файлу JavaScript\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets зіткнувся з проблемою під час обробки <span class=\\'dialog-filename\\'>{0}</span>.<br><br>Для цього файлу більше не працюватиме аналіз, перехід до оголошень та швидке редагування. Аби повернути їх, відкрийте <code>.brackets.json</code> у теці свого проекту та відредагуйте параметр <code>jscodehints.detectedExclusions</code>. <br><br> Це схоже на ваду у Brackets. Якщо ви можете надати копію цього файлу, будь ласка, <a href=\\'https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue\\'>сповістіть про ваду</a> та вкажіть посилання на нього.\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"Швидкий перегляд під час наведення\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"Останні проекти\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"Докладніше\"\n});\n/* Last translated for ed1b597f2c0e72fc11c9ec42d88d35f57cd6798b */\n"
  },
  {
    "path": "src/nls/uk/urls.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"uk/Pochynayemo\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_uk/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.uk\"\n});"
  },
  {
    "path": "src/nls/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n\n    \"use strict\";\n\n    // Registry for languages that have specific per-language URLs or file paths that we use\n    // elsewhere in Brackets.\n    //\n    // TODO: dynamically populate the local prefix list below?\n    module.exports = {\n        root: true,\n        \"bg\": true,\n        \"cs\": true,\n        \"da\": true,\n        \"de\": true,\n        \"es\": true,\n        \"fa-ir\": true,\n        \"fi\": true,\n        \"fr\": true,\n        \"hr\": true,\n        \"id\": true,\n        \"it\": true,\n        \"ja\": true,\n        \"ko\": true,\n        \"nb\": true,\n        \"pl\": true,\n        \"pt-br\": true,\n        \"pt-pt\": true,\n        \"ru\": true,\n        \"sv\": true,\n        \"zh-cn\": true,\n        \"zh-tw\": true,\n        \"tr\": true,\n        \"uk\": true\n    };\n});\n"
  },
  {
    "path": "src/nls/zh-cn/strings.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(错误 {0})\",\n    \"NOT_FOUND_ERR\"                     : \"未能发现该文件\",\n    \"NOT_READABLE_ERR\"                  : \"无法读取该文件。\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"{APP_NAME} 不能打开大于 {0} MB 的文件。\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"无法修改此目录。\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"你没有权限做此次修改。\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"该文件已经在 {APP_NAME} 之外被修改。\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} 暂时仅支持UTF-8编码的文本文档。\",\n    \"FILE_EXISTS_ERR\"                   : \"该文件已存在。\",\n    \"FILE\"                              : \"文件\",\n    \"FILE_TITLE\"                        : \"文件\",\n    \"DIRECTORY\"                         : \"目录\",\n    \"DIRECTORY_TITLE\"                   : \"目录\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"目录名\",\n    \"FILENAMES_LEDE\"                    : \"文件名\",\n    \"FILENAME\"                          : \"文件名\",\n    \"DIRECTORY_NAME\"                    : \"目录名\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"无法加载此项目。\",\n    \"OPEN_DIALOG_ERROR\"                 : \"显示[打开文件]对话框发生错误。 (错误 {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"打开目录 <span class='dialog-filename'>{0}</span> 发生错误。 (错误 {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"读取目录 <span class='dialog-filename'>{0}</span> 发生错误。 (错误 {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"打开文件时发生错误\",\n    \"ERROR_OPENING_FILE\"                : \"尝试打开文件 <span class='dialog-filename'>{0}</span> 时发生错误。 {1}\",\n    \"ERROR_OPENING_FILES\"               : \"尝试打开以下文件发生现错误:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"重新加载文件时发生错误\",\n    \"ERROR_RELOADING_FILE\"              : \"尝试重新加载文件 <span class='dialog-filename'>{0}</span> 时发生错误。 {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"保存文件时发生错误\",\n    \"ERROR_SAVING_FILE\"                 : \"尝试保存文件 <span class='dialog-filename'>{0}</span> 时发生错误。 {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"重命名文件 {0} 失败\",\n    \"ERROR_RENAMING_FILE\"               : \"尝试重命名文件 {2} <span class='dialog-filename'>{0}</span> 时发生错误。 {1}\",\n    \"ERROR_RENAMING_NOT_IN_PROJECT\"     : \"文件或目录不是已打开项目的一部分。当前只允许重命名项目中的文件。\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"删除文件 {0} 失败\",\n    \"ERROR_DELETING_FILE\"               : \"尝试删除文件 {2} <span class='dialog-filename'>{0}</span> 时发生错误。 {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"无效文件名: {0}\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0} 不能以(.)结尾或者包含系统保留字及以下字符：<code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"名为 <span class='dialog-filename'>{0}</span> 的文件/文件夹已经存在。\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"创建文件 {0} 出现错误\",\n    \"ERROR_CREATING_FILE\"               : \"尝试创建 {0} <span class='dialog-filename'>{1}</span> 时发生错误。 {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"无法在打开文件夹的同时打开其他文件\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"读取用户键映射错误\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"键映射文件不是有效的 JSON 格式。即将打开配置文件以便您修正。\",\n    \"ERROR_LOADING_KEYMAP\"              : \"不能打开你的键映射文件，因为它不是 UTF-8 编码的文本文件。\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"不能将快捷键重新分配给这些命令： {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"不能重新分配这些快捷键： {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"这些命令定义了多个快捷键： {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"这些快捷键上指定了多个命令： {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"这些快捷键是无效的： {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"快捷键指向了并不存在的命令： {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"读取配置错误\",\n    \"ERROR_PREFS_CORRUPT\"               : \"您的配置文件不是有效的 JSON 格式. 即将打开配置文件以便您修正. 为使更改生效, 您需要重启 {APP_NAME}.\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"您的项目配置文件不是有效的 JSON 格式. 即将打开配置文件以便您修正. 为使更改生效, 您需要重新载入项目.\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"囧! {APP_NAME} 暂无法在浏览器中运行。\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} 是建立在 HTML 上的一个桌面程序, 你可以用它修改本地文件. 可以前往此处下载系统对应的版本<b>github.com/adobe/brackets-shell</b>, 然后重新运行 {APP_NAME}.\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"索引文件错误\",\n    \"ERROR_MAX_FILES\"                   : \"索引文件过多, 可能无法通过索引查找文件。\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"启动浏览器失败\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"没有找到 Google Chrome 浏览器, 请确定您已安装了 Chrome 浏览器。\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"启动浏览器时发生错误。 (错误 {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"实时预览错误\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"正在连接浏览器\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"要使用实时预览, 需要重启 Chrome 并打开远程调试功能。<br /><br />你确定重新启动 Chrome 浏览器, 并且打开远程调试功能吗？\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"无法加载实时预览页面\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"打开一个 HTML 文件或确认项目中包含 index.html 文件以启动实时预览.\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"实时预览需要一个服务端, 您需要为这个项目指定一个基本 URL 地址。 (如http://127.0.0.1/)\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"试图启动实时预览 HTTP 服务器时出现错误, 请再试一次。\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"欢迎使用实时预览！\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"{APP_NAME} 将通过实时预览连接至你的浏览器. 你的 HTML 文件将在浏览器中预览, 修改你的代码将会即时更新你浏览器中的预览。<br /><br />目前版本的 {APP_NAME} 实时预览只能运行于 <strong>Google Chrome</strong> 浏览器更新实时编辑时的 <strong>CSS 和 HTML 文件</strong>，当你保存了 JavaScript 文件, 实时预览将在浏览器中重新加载它们。<br /><br />(此消息仅会出现一次)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"更多信息, 请参考<a href='{0}' title='{0}'>实时预览连接错误信息</a>。\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"实时预览\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"实时预览: 连接中\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"实时预览: 初始化\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"断开实时预览\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"实时预览 (保存文件并刷新)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"实时预览 (由于语法错误没有更新)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"由于浏览器开发人员工具已打开, 实时预览已关闭。\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"由于浏览器中页面已关闭, 实时预览已关闭\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"由于浏览器打开一个不属于本项目的页面, 实时预览已关闭\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"未知原因 ({0}) 导致实时预览关闭\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"保存更新\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"保存 <span class='dialog-filename'>{0}</span> 文件中所做的修改？\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"是否保存以下文件的修改？\",\n    \"EXT_MODIFIED_TITLE\"                : \"外部文件发生变化\",\n    \"CONFIRM_DELETE_TITLE\"              : \"删除确认\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"确认要删除目录 <span class='dialog-filename'>{0}</span>？\",\n    \"FILE_DELETED_TITLE\"                : \"文件已删除\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> 已产生了外部修改，<br /><br />是否保存并覆盖外部修改？\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> 已产生了外部修改, 但是 {APP_NAME} 中有你未保存的内容，<br /><br />需要保留哪个版本？\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> 已被删除, 但是 {APP_NAME} 有你未保存的内容，<br /><br />是否保存你的修改？\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"完成\",\n    \"OK\"                                : \"确认\",\n    \"CANCEL\"                            : \"取消\",\n    \"DONT_SAVE\"                         : \"不要保存\",\n    \"SAVE\"                              : \"保存\",\n    \"SAVE_AS\"                           : \"另存为\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"覆盖原文件\",\n    \"DELETE\"                            : \"删除\",\n    \"BUTTON_YES\"                        : \"是\",\n    \"BUTTON_NO\"                         : \"否\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{1} 条中的 {0} 条\",\n    \"FIND_NO_RESULTS\"                   : \"未找到匹配项\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"查找\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"替换为\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"全部\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"替换\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"替换\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"下一个匹配项\",\n    \"BUTTON_PREV_HINT\"                  : \"上一个匹配项\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"区分大小写\",\n    \"BUTTON_REGEXP_HINT\"                : \"正则表达式\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"替换(无法撤销)\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"由于有 {0} 个文件需要修改, {APP_NAME} 将修改磁盘中未打开的文件，<br />这些修改无法撤销。\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"替换(无法撤销)\",\n\n    \"OPEN_FILE\"                         : \"打开文件\",\n    \"SAVE_FILE_AS\"                      : \"保存文件\",\n    \"CHOOSE_FOLDER\"                     : \"请选择一个目录\",\n\n    \"RELEASE_NOTES\"                     : \"发行说明\",\n    \"NO_UPDATE_TITLE\"                   : \"已更新!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"正在使用最新版本的 {APP_NAME}。\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"替换\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"为\",\n    \"FIND_TITLE_LABEL\"                  : \"已找到\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {0} {1} {2} 于 {3}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} {1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"在 <span class='dialog-filename'>{0}</span> 中\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"在项目中\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"筛选条件排除了所有文件 {0}\",\n    \"FIND_IN_FILES_FILE\"                : \"个文件\",\n    \"FIND_IN_FILES_FILES\"               : \"个文件\",\n    \"FIND_IN_FILES_MATCH\"               : \"个匹配\",\n    \"FIND_IN_FILES_MATCHES\"             : \"个匹配\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"超过 \",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We shoudl use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"按住 Ctrl/Cmd 键以便展开/折叠全部结果\",\n    \"FIND_IN_FILES_INDEXING\"            : \"Indexing for Instant Search\\u2026\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"替换出现错误\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"以下文件未被修改，可能是搜索后发生变更或无法写入。\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"获取更新信息失败\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"无法从服务器获取最新的更新信息. 请确认你的电脑已经连接互联网, 然后再次尝试重新获取！\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"新建排除规则\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"不排除文件\",\n    \"NO_FILE_FILTER\"                    : \"没有文件被排除\",\n    \"EXCLUDE_FILE_FILTER\"               : \"排除 {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"编辑\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"编辑过滤规则\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"根据下列匹配规则排除文件或文件夹, 匹配规则可以是文件名或其子串, 或使用 <a href='{0}' title='{0}'>globs</a>，每行输入一条规则。\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"命名过滤规则 (可选)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"及另外 {0} 类\",\n    \"FILTER_COUNTING_FILES\"             : \"统计文件数目\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"Allows {0} of {1} files {2}\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"Allows all {0} files {1}\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"当前光标位置没有可用的快速编辑\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS 快速编辑: 将光标放在单一class名称上\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS 快速编辑: class属性不完整\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS 快速编辑: id属性不完整\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS 快速编辑: 将光标放在标签,、class 或 id上\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS 计时函数快速编辑: 语法无效\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS 快速编辑: 将光标放在函数名称上\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"当前光标位置没有可用的快速文件\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"载入中\\u2026\",\n    \"UNTITLED\"          : \"无标题\",\n    \"WORKING_FILES\"     : \"工作区\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"上\",\n    \"BOTTOM\"            : \"下\",\n    \"LEFT\"              : \"左\",\n    \"RIGHT\"             : \"右\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"单窗口\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"垂直分割\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"水平分割\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"垂直/水平分割编辑器窗口\",\n    \"GEAR_MENU_TOOLTIP\"         : \"配置工作区\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"已经打开\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"该文件已经在编辑器的另一个窗格中打开。{APP_NAME} 后续会加上同文件多窗格打开的支持。在此之前，文件只会显示在已打开的窗格中。<br /><br />（本信息只显示一次。）\",\n\n    /**\n     * Keyboard modifier names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"空格\",\n    \"KEYBOARD_PAGE_UP\"      : \"向上翻页\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"向下翻页\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"插入\",\n    \"KEYBOARD_DELETE\"       : \"删除\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"行 {0}, 列 {1}\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 已选中 {0} 列\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 已选中 {0} 列\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 已选中 {0} 行\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 已选中 {0} 行\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 {0} 处选择\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"点击切换缩进为空格\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"点击切换缩进为Tab\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"点击修改缩进的空格长度\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"点击修改缩进的Tab长度\",\n    \"STATUSBAR_SPACES\"                      : \"空格长度:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab 长度:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} 行\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} 行\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"扩展已禁用\",\n    \"STATUSBAR_INSERT\"                      : \"插入\",\n    \"STATUSBAR_OVERWRITE\"                   : \"改写\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"点击切换光标的插入 (INS) 和改写 (OVR) 模式\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"点击更改文件类型\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}。点击打开关闭报告面板\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(默认)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"设置为 .{0} 的缺省\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} 问题\",\n    \"SINGLE_ERROR\"                          : \"1个 {0} 问题\",\n    \"MULTIPLE_ERRORS\"                       : \"{1}个 {0} 问题\",\n    \"NO_ERRORS\"                             : \"未发现 {0} 问题 - 加油！\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"未发现问题 - 加油！\",\n    \"LINT_DISABLED\"                         : \"JSLint 已被禁用或者无法在此文件工作。\",\n    \"NO_LINT_AVAILABLE\"                     : \"{0} 没有可用检查器\",\n    \"NOTHING_TO_LINT\"                       : \"没有可检查文件\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} 等待 {1} ms 后超时\",\n    \"LINTER_FAILED\"                         : \"{0} 已终止，错误：{1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"文件\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"新建\",\n    \"CMD_FILE_NEW\"                        : \"新建文件\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"新建目录\",\n    \"CMD_FILE_OPEN\"                       : \"打开\\u2026\",\n    \"CMD_RECENT_FILES_OPEN\"               : \"打开最近\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"添加至工作集合\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"打开拖放的文件\",\n    \"CMD_OPEN_FOLDER\"                     : \"打开目录\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"关闭\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"全部关闭\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"关闭列表中的文件\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"关闭其他文件\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"关闭上面的其他文件\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"关闭下面的其他文件\",\n    \"CMD_FILE_SAVE\"                       : \"保存\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"全部保存\",\n    \"CMD_FILE_SAVE_AS\"                    : \"另存为\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"实时预览\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"开启实验性实时预览\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"强制实时预览重新加载\",\n    \"CMD_PROJECT_SETTINGS\"                : \"项目设置\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"重命名\",\n    \"CMD_FILE_DELETE\"                     : \"删除\",\n    \"CMD_INSTALL_EXTENSION\"               : \"安装扩展\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"扩展管理器\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"刷新文件列表\",\n    \"CMD_QUIT\"                            : \"退出\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"退出\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"编辑\",\n    \"CMD_UNDO\"                            : \"撤销\",\n    \"CMD_REDO\"                            : \"重做\",\n    \"CMD_CUT\"                             : \"剪切\",\n    \"CMD_COPY\"                            : \"复制\",\n    \"CMD_PASTE\"                           : \"粘贴\",\n    \"CMD_SELECT_ALL\"                      : \"全选\",\n    \"CMD_SELECT_LINE\"                     : \"选中当前行\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"将选中内容拆分至多行\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"将下一行添加至选中内容\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"将上一行添加至选中内容\",\n    \"CMD_INDENT\"                          : \"增加行缩进\",\n    \"CMD_UNINDENT\"                        : \"减少行缩进\",\n    \"CMD_DUPLICATE\"                       : \"创建副本\",\n    \"CMD_DELETE_LINES\"                    : \"删除当前行\",\n    \"CMD_COMMENT\"                         : \"注释当前行\",\n    \"CMD_BLOCK_COMMENT\"                   : \"注释选中内容\",\n    \"CMD_LINE_UP\"                         : \"移到下一行\",\n    \"CMD_LINE_DOWN\"                       : \"移到上一行\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"在上方插入新行\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"在下方插入新行\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"括号自动补全\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"显示代码提示\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"查找\",\n    \"CMD_FIND\"                            : \"查找\",\n    \"CMD_FIND_NEXT\"                       : \"查找下一个\",\n    \"CMD_FIND_PREVIOUS\"                   : \"查找上一个\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"查找全部并选中\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"将下一项匹配添加至选中内容\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"跳过并添加下一项匹配\",\n    \"CMD_FIND_IN_FILES\"                   : \"在文件中查找\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"在该位置查找\\u2026\",\n    \"CMD_REPLACE\"                         : \"替换\",\n    \"CMD_REPLACE_IN_FILES\"                : \"在文件中替换\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"在该位置替换\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"视图\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"隐藏边栏\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"显示边栏\",\n    \"CMD_TOGGLE_SIDEBAR\"                  : \"显示/隐藏边栏\",\n    \"CMD_TOGGLE_PANELS\"                   : \"显示/隐藏面板\",\n    \"CMD_TOGGLE_PURE_CODE\"                : \"无干扰模式\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"放大编辑器字体\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"缩小编辑器字体\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"恢复编辑器默认字体\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"向上滚动\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"向下滚动\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"显示行号\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"高亮当前行\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"自动换行\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"实时预览高亮\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"保存时检查文件\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"根据添加时间排序\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"根据名称排序\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"根据类型排序\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"自动排序\",\n    \"CMD_THEMES\"                          : \"主题\\u2026\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"导航\",\n    \"CMD_QUICK_OPEN\"                      : \"打开快速导航\",\n    \"CMD_GOTO_LINE\"                       : \"转到某行\",\n    \"CMD_GOTO_DEFINITION\"                 : \"转到定义\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"转到第一个错误/警告\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"快速编辑\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"快速文档\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"上一个匹配项\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"下一个匹配项\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"新 CSS 规则\",\n    \"CMD_NEXT_DOC\"                        : \"下一个文件\",\n    \"CMD_PREV_DOC\"                        : \"上一个文件\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"列表中下一个文件\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"列表中上一个文件\",\n    \"CMD_SHOW_IN_TREE\"                    : \"在侧边栏显示\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"在资源管理器中显示\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"在 Finder 中显示\",\n    \"CMD_SHOW_IN_OS\"                      : \"打开文件所在目录\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"帮助\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"检查更新\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"如何使用 {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} 支持\",\n    \"CMD_SUGGEST\"                         : \"推荐功能\",\n    \"CMD_RELEASE_NOTES\"                   : \"发行说明\",\n    \"CMD_GET_INVOLVED\"                    : \"参与\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"显示扩展目录\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"健康报告\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} 主页\",\n    \"CMD_TWITTER\"                         : \"在 Twitter 上 {TWITTER_NAME}\",\n    \"CMD_ABOUT\"                           : \"关于 {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"打开配置文件\",\n    \"CMD_OPEN_KEYMAP\"                     : \"打开用户键映射\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"体验版\",\n    \"RELEASE_BUILD\"                        : \"发布版\",\n    \"DEVELOPMENT_BUILD\"                    : \"开发版\",\n    \"RELOAD_FROM_DISK\"                     : \"重新从硬盘中加载\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"保留编辑器中的修改\",\n    \"CLOSE_DONT_SAVE\"                      : \"放弃保存并关闭\",\n    \"RELAUNCH_CHROME\"                      : \"重新运行 Chrome\",\n    \"ABOUT\"                                : \"关于\",\n    \"CLOSE\"                                : \"关闭\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"构建时间：\",\n    \"ABOUT_TEXT_LINE3\"                     : \"关于第三方软件的条款、条例和声明 <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a> 以此作为参考。\",\n    \"ABOUT_TEXT_LINE4\"                     : \"文档与源码在 <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a>\",\n    \"ABOUT_TEXT_LINE5\"                     : \"基于 \\u2764 和 JavaScript 由以下用户参与贡献设计:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"有相当多的人参与其中, 但现在有一些问题导致加载不出, 你可以到GitHub上去看。\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN 文档和图形 logo 遵循<a href='{MDN_DOCS_LICENSE}'>署名-相同方式共享 3.0 未本地化</a>协议。\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"有一个新版本的 {APP_NAME}! 点此查看详情。\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"可用的更新\",\n    \"UPDATE_MESSAGE\"                       : \"有一个新版本的 {APP_NAME}，增加了一些功能：\",\n    \"GET_IT_NOW\"                           : \"马上获取！\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"项目设置: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"实时预览的根目录地址\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"使用本地服务器, 并指定一个URL。 例如: http://localhost:8000/\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"实时预览不支持此协议 {0} &mdash;请使用 http: 或 https: .\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"地址不能包含搜索参数如 \\\"{0}\\\".\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"地址不能包含哈希如 \\\"{0}\\\".\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"特殊字符 '{0}' 必须 %-encoded.\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"地址解析错误, 请确认地址格式\",\n\n    // Strings for Pane.js\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>保持此窗格的焦点，打开文件</em>\",\n    \"FLIPVIEW_BTN_TOOLTIP\"                 : \"将此视图翻转到 {0} 面板\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"当前主题\",\n    \"USE_THEME_SCROLLBARS\"                 : \"使用主题自带滚动条\",\n    \"FONT_SIZE\"                            : \"字号\",\n    \"FONT_FAMILY\"                          : \"字体\",\n    \"THEMES_SETTINGS\"                      : \"主题设置\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"新 CSS 规则\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"安装\",\n    \"UPDATE\"                               : \"升级\",\n    \"REMOVE\"                               : \"移除\",\n    \"DISABLE\"                              : \"禁用\",\n    \"ENABLE\"                               : \"启用\",\n    \"OVERWRITE\"                            : \"覆盖\",\n    \"CANT_REMOVE_DEV\"                      : \"\\\"dev\\\" 文件夹中扩展必须手动删除。\",\n    \"CANT_UPDATE\"                          : \"升级与当前版本的 {APP_NAME} 不兼容。\",\n    \"CANT_UPDATE_DEV\"                      : \"\\\"dev\\\" 文件夹中的扩展无法自动升级。\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"安装扩展\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"升级扩展\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"扩展包地址\",\n    \"INSTALL_EXTENSION_HINT\"               : \"填写扩展包的 zip 文件或 GitHub repo 的链接地址\",\n    \"INSTALLING_FROM\"                      : \"正在从 {0} 安装扩展\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"安装成功！\",\n    \"INSTALL_FAILED\"                       : \"安装失败.\",\n    \"CANCELING_INSTALL\"                    : \"正在取消\\u2026\",\n    \"CANCELING_HUNG\"                       : \"取消安装需要很长时间. 可能出现了内部错误。\",\n    \"INSTALL_CANCELED\"                     : \"安装已取消。\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"查看完整说明\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"查看简短说明\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"下载的内容不是一个有效的 ZIP 文件。\",\n    \"INVALID_PACKAGE_JSON\"                 : \"扩展包中的 Package.json 不存在。(错误: {0})\",\n    \"MISSING_PACKAGE_NAME\"                 : \"扩展包中的 Package.json 未指定扩展包名称。\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} 是一个无效扩展包名。\",\n    \"MISSING_PACKAGE_VERSION\"              : \"扩展包中的 Package.json 未指定扩展包版本。\",\n    \"INVALID_VERSION_NUMBER\"               : \"扩展包版本号 ({0}) 无效。\",\n    \"INVALID_BRACKETS_VERSION\"             : \"{APP_NAME} 兼容性字串 ({0}) 无效。\",\n    \"DISALLOWED_WORDS\"                     : \"({1}) 不允许在 {0} 中出现。\",\n    \"API_NOT_COMPATIBLE\"                   : \"这个扩展包不兼容当前版本的 {APP_NAME}. 将安装至 Disabled 扩展文件夹中。\",\n    \"MISSING_MAIN\"                         : \"扩展包遗失 main.js 文件.\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"安装这个扩展将会覆盖先前的版本, 覆盖旧版本吗？\",\n    \"EXTENSION_SAME_VERSION\"               : \"已安装相同版本的扩展. 覆盖已存在的安装吗？\",\n    \"EXTENSION_OLDER_VERSION\"              : \"扩展包版本 {0} 低于已安装版本 ({1})， 覆盖已存在的安装吗？\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"内部错误: 该下载ID已被使用。\",\n    \"NO_SERVER_RESPONSE\"                   : \"无法连接到服务器。\",\n    \"BAD_HTTP_STATUS\"                      : \"未在服务器上发现该文件 (HTTP {0})。\",\n    \"CANNOT_WRITE_TEMP\"                    : \"无法保存下载文件到临时文件。\",\n    \"ERROR_LOADING\"                        : \"扩展程序启动时遇到一个错误。\",\n    \"MALFORMED_URL\"                        : \"无效的链接地址，请检查输入是否有误。\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"需要一个 http 或 https 协议的地址。\",\n    \"UNKNOWN_ERROR\"                        : \"未知内部错误。\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"扩展管理器\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"无法连接到扩展仓库。请稍后重试。\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"拖拽 .zip 到此处或者\",\n    \"INSTALL_EXTENSION_DROP\"               : \"Drop .zip to install\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"安装/更新由于以下错误终止:\",\n    \"INSTALL_FROM_URL\"                     : \"从 URL 安装\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"验证中...\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"作者\",\n    \"EXTENSION_DATE\"                       : \"日期\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"这个扩展需要更新版本的 {APP_NAME}。\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"这个扩展目前只能在旧版本的 {APP_NAME} 上运行。\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"扩展版本为 {0} 需要一个更新版本的 {APP_NAME}，但你可以安装旧版本的扩展 {1}。\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"扩展版本为 {0} 需要一个更旧版本的 {APP_NAME}，但你可以安装旧版本的扩展 {1}。\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"没有描述\",\n    \"EXTENSION_MORE_INFO\"                  : \"更多信息...\",\n    \"EXTENSION_ERROR\"                      : \"扩展错误\",\n    \"EXTENSION_KEYWORDS\"                   : \"关键词\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"翻译为{0} , 包括你所使用的语言\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"翻译为 {0} \",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"该扩展已被翻译为以下语言: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"已安装\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"此扩展的更新已下载, 将在重启 {APP_NAME} 后安装。\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"搜索\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"更多\",\n    \"BROWSE_EXTENSIONS\"                    : \"浏览扩展\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"移除扩展\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"无法移除一个或多个扩展: {0}. {APP_NAME} 仍会重新加载。\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"升级扩展\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"无法升级一个或多个扩展: {0}. {APP_NAME} 仍会重新加载。\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"禁用扩展\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"无法禁用一个或多个扩展: {0}. {APP_NAME} 仍会重新加载。\",\n    \"MARKED_FOR_REMOVAL\"                   : \"标记为删除\",\n    \"UNDO_REMOVE\"                          : \"撤销\",\n    \"MARKED_FOR_UPDATE\"                    : \"标记为升级\",\n    \"UNDO_UPDATE\"                          : \"撤销\",\n    \"MARKED_FOR_DISABLING\"                 : \"标记为禁用\",\n    \"UNDO_DISABLE\"                         : \"撤销\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"扩展更改\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"安装或移除已标记的扩展, 需要退出并重启 {APP_NAME}， 请保存未保存的更改。\",\n    \"REMOVE_AND_RELOAD\"                    : \"移除扩展并退出重启\",\n    \"CHANGE_AND_RELOAD\"                    : \"更改扩展并退出重启\",\n    \"UPDATE_AND_RELOAD\"                    : \"升级扩展并退出重启\",\n    \"DISABLE_AND_RELOAD\"                   : \"禁用扩展并退出重启\",\n    \"PROCESSING_EXTENSIONS\"                : \"正在处理扩展的变更\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"无法移除扩展 {0} 其并未被安装.\",\n    \"NO_EXTENSIONS\"                        : \"还没有安装扩展。<br>点击上方可用的标签开始安装。\",\n    \"NO_EXTENSION_MATCHES\"                 : \"没有找到相符的扩展。\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"小心来自未知源的扩展。\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"已安装\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"可获取\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"主题\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"升级\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"未找到匹配项。\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"所有匹配项已折叠。展开右侧列出的文件以查看匹配项。\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"符合选择的 CSS 规则不存在。<br> 点击 \\\"新 CSS 规则\\\" 来创建。\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"您的项目中没有样式表。<br>建立一个来添加 CSS 规则。\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"最大化\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"像素\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"调试\",\n    \"ERRORS\"                                    : \"错误\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"显示开发者工具\",\n    \"CMD_REFRESH_WINDOW\"                        : \"以带扩展模式重启\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"以无扩展模式重启\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"新建一个 {APP_NAME} 窗口\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"安装命令行快捷方式\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"切换语言\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"运行测试\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"显示性能数据\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"启用 Node.js 调试\",\n    \"CMD_LOG_NODE_STATE\"                        : \"将 Node.js 日志显示在控制台中\",\n    \"CMD_RESTART_NODE\"                          : \"重启 Node.js\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"状态栏显示错误信息\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"打开 Brackets 源码\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} 命令行快捷方式\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"安装命令行快捷方式时发生错误。 请尝试<a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>这些故障排除建议</a>.<br/><br/>原因: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"无法移除已存在的 <code>/usr/local/bin/brackets</code> 符号链接.\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"无法创建 <code>/usr/local/bin</code> 目录.\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"无法创建 <code>/usr/local/bin/brackets</code> 符号链接.\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"内部错误.\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"该系统不支持命令行快捷方式.\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"成功! 现在你可以通过这样的命令简单地启动 {APP_NAME} 了: <code>brackets myFile.txt</code> 打开文件, <code>brackets myFolder</code> 切换项目, <br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>点击此处</a>了解更多 {APP_NAME} 命令行的使用方法.\",\n\n    \"LANGUAGE_TITLE\"                            : \"切换语言\",\n    \"LANGUAGE_MESSAGE\"                          : \"请从列表中选择所需的语言:\",\n    \"LANGUAGE_SUBMIT\"                           : \"重新加载 {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"取消\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"系统默认\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"健康报告首选项\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} 健康报告\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"共享关于我如何使用 {APP_NAME} 的匿名信息\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"为了改进 {APP_NAME}, 我们会周期性地向 Adobe 发送有限的 <strong>匿名的</strong> 关于你如何使用 {APP_NAME} 的统计信息. 这些信息有助于调整特性的优先顺序, 寻找错误和定位可用性问题. <br><br>你可以通过 <strong>帮助 > 健康报告</strong> 查看你的数据或者选择不共享数据. <br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>了解 {APP_NAME} 健康报告详情</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} 健康报告\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>为了改进 {APP_NAME}, 我们会周期性地向 Adobe 发送有限的 <strong>匿名的</strong> 关于你如何使用 {APP_NAME} 的统计信息. 这些信息有助于调整特性的优先顺序, 寻找错误和定位可用性问题. <a href='https://github.com/adobe/brackets/wiki/Health-Data'>了解更多 {APP_NAME} 健康报告</a>, 以及它是怎样在保护你的隐私的情况下帮助 {APP_NAME} 社区. </p><p><em>如果</em>你打开它, 下面的数据将被用于下次健康报告的发送. </p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"时间\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"进程\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> 移动选中点<br><kbd class='text'>Shift</kbd> 10倍移动<br><kbd class='text'>Tab</kbd> 切换点\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> 增减步进<br><kbd>←</kbd><kbd>→</kbd> 切换 'Start' 或 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"原值 <code>{0}</code> 无效, 函数值已变为 <code>{1}</code>. 文档将在首次编辑时更新.\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"当前的颜色\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"原来的颜色\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa 格式\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"十六进制格式\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa 格式\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (使用 {1} 次)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (使用 {1} 次)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"跳转到源代码定义处\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"显示参数提示\",\n    \"NO_ARGUMENTS\"                              : \"<无相应参数>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"JavaScript 文件引用问题\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"Brackets 处理文件遇到问题： <br><br>{0}<br><br> 该文件不再用于处理代码提示，并会跳转到源码定义处。 为避免这个问题, 请打开项目中的 <code>.brackets.json</code> ,从 jscodehints.detectedExclusions 删除该文件\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"鼠标悬停时启用快速查看\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"最近的项目\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"更多信息\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"收起所有\",\n    \"EXPAND_ALL\"                    : \"展开所有\",\n    \"COLLAPSE_CURRENT\"              : \"收起当前\",\n    \"EXPAND_CURRENT\"                : \"展开当前\",\n\n    // extensions/default/NavigationAndHistory\n    \"RECENT_FILES_DLG_HEADER\"                    : \"最近打开的文件\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_LABEL\"        : \"清除\",\n    \"RECENT_FILES_DLG_CLEAR_BUTTON_TITLE\"        : \"清除不在工作区的文件\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"值为真时，自动闭合括号\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"值为假时，从工作区右键菜单中移除 \\\"关闭上面的其他文件\\\" 项\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"值为假时，从工作区右键菜单中移除 \\\"关闭下面的其他文件\\\" 项\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"值为假时，从工作区右键菜单中移除 \\\"关闭其他文件\\\" 项\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"设置标签自动闭合选项\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"不应自动闭合的一组标签\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"键入起始标签的 > 字符时闭合\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"键入结束标签的 / 字符时闭合\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"标签内容另起一行的一组标签\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"值为真时，总是在缩进级别改变后可折叠区域标记\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"值为真时，开启代码折叠\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"值为真时，区域折叠标记只会在鼠标移动到折叠处显示\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"限制展开全部所限制的最大层级数\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"显示可折叠区域图标的最小行数\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"值为真时，关闭或打开文件/项目也会记住所折叠的区域\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"值为真时，在编辑器中开启选定文本的代码折叠功能\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"开启/关闭 HTML 属性提示\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"开启/关闭 CSS/LESS/SCSS 属性名提示\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"开启/关闭 JavaScript 代码提示\",\n    \"DESCRIPTION_JS_HINTS_TYPE_DETAILS\"              : \"开启/关闭 JavaScript 代码的数据类型提示\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"开启/关闭配置文件选项提示\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"开启/关闭 HTML 实体提示\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"开启/关闭 SVG 代码提示\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"开启/关闭 HTML 标签提示\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"开启/关闭 HTML & CSS/LESS/SCSS 中的 URL 提示\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"开启/关闭拖曳功能\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"开启健康数据跟踪\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"开启文档中匹配字符串的自动高亮\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"高亮匹配光标处符号的所有字符串(无需选区)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"仅在选区为完整符号时高亮\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"值为真时，插入在标签页上选择的代码\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"值为真时，不再在输入 . 符号后自动显示 JS 代码提示\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"用于 JSLint 默认选项的Object对象\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"值为真时，允许使用赋值表达式\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"值为真时，允许使用位运算符\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"值为真时，应事先定义标准浏览器全局变量\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"值为真时，允许使用 Google Closure 语法\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"值为真时，允许使用 \\\"continue\\\" 语句\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"值为真时，应事先定义 CouchDB 全局变量\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"值为真时，允许使用调试器语句\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"值为真时，应事先定义浏览器开发的全局变量\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"值为真时，允许使用 == 及 !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"值为真时，应事先定义 ES6 全局变量\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"值为真时，允许使用 eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"值为真时，允许使用不经过筛选的 \\\"for ... in\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"设置特定 Tab 键大小\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"报告警告信息的最大值\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"每行字符数的最大值\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"值为真时，允许使用非首字母大写的构造器函数\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"值为真时，应事先定义 Node.js 全局变量\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"值为真时，允许使用带前下划线的标识符\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"值为真时，在第一处错误处停止执行\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"值为真时，允许使用 ++ 及 --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"值为真时，允许在正则表达式中使用 . 及 [^...].\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"值为真时，应事先定义 Rhino 全局变量\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"值为真时，允许不声明 `use strict` 语句\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"值为真时，允许使用阻塞性 ('...Sync') 方法\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"值为真时，允许使用不方便的括号语法\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"值为真时，允许使用 TODO 语句\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"值为真时，允许含有未使用的参数\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"值为真时，允许在函数中使用多个 var 语句\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"值为真时，忽略空格规则\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"语言特定设置\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"扩展名到语言名的附加映射\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"文件名到语言名的附加映射\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"值为真时，开启代码检查器\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"异步检查器的超时时间\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"首先运行的代码检查器列表\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"值为真时，开启实验性的实时预览\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"值为真时，只使用 linting.prefer 指定的提供商\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"一次显示最多的提示数\",\n    \"DESCRIPTION_PATH\"                               : \"路径特定设置\",\n    \"DESCRIPTION_PROXY\"                              : \"扩展安装所用的代理服务器 URL\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"值为真时，允许滚动超出文档末尾\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"值为假时，关闭所有代码提示\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"有文字选区时保持光标闪烁\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"值为真时，在代码左侧显示行号\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"生成新区域时自动缩进\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"值为假时，关闭软 tab 功能\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"值为真时，给项目数中的文件夹排序\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"空格缩进所使用的空格数\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"内置服务器开启实时预览所使用的端口号\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"值为真时，高亮显示光标所在行的背景颜色\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"一个 Tab 键所代表的空格数\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"值为真时，使用 tab 字符而不用空格\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"值为真时，在内联的色彩编辑器中生成大写的16进制色彩值\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"超过可视区域时换行\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"检测会导致 Tern 失效的文件列表\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Tern 尝试解析文件所需要的超时时长\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"值为真时，在状态栏显示错误\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"值为真时，开启快速查看\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"值为真时，为缺少 URL 的扩展程序显示图像预览\",\n    \"DESCRIPTION_THEME\"                              : \"选择一个 {APP_NAME} 主题\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"值为真时，允许自定义滚动条\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"值为真时，折叠提示面板\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"改变字体\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"改变字号，例如 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"值为真时，开启基于 node 的搜索\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"值为真时，开启实时搜索\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"仅Mac: \\\"subpixel-antialiased\\\" 开启次像素防锯齿或者 \\\"antialiased\\\" 开启灰阶防锯齿\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"值为假时，不再划分一个窗口打开用户配置\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"值为假时，在左边/顶部窗格中打开用户设置\",\n    \"DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\"  : \"值为真时，折叠面板头部关闭后最后一个文件之后的面板\",\n    \"DESCRIPTION_SHOW_PANE_HEADER_BUTTONS\"           : \"切换头部显示关闭或者翻转视图的按钮。\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * This is a read-only file with the preferences supported\\n * by {APP_NAME}.\\n * Use this file as a reference to modify your preferences\\n * file \\\"brackets.json\\\" opened in the other pane.\\n * For more information on how to use preferences inside\\n * {APP_NAME}, refer to the web page at https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"默认\",\n    \"DESCRIPTION_PURE_CODING_SURFACE\"                : \"值为真时，开启纯代码模式，隐藏 {APP_NAME} 的其他 UI 元素\",\n    \"DESCRIPTION_INDENT_LINE_COMMENT\"                : \"值为真时，开启行注释缩进\",\n    \"DESCRIPTION_RECENT_FILES_NAV\"                   : \"开启/关闭最近文件导航\"\n});\n\n/* Last translated for ae015b5be491e1d97d86b1f7f4fd352157063110 */\n"
  },
  {
    "path": "src/nls/zh-cn/urls.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"zh-cn/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.zh\"\n});\n"
  },
  {
    "path": "src/nls/zh-tw/strings.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(錯誤 {0})\",\n    \"NOT_FOUND_ERR\"                     : \"找不到檔案或目錄。\",\n    \"NOT_READABLE_ERR\"                  : \"無法讀取檔案或目錄。\",\n    \"EXCEEDS_MAX_FILE_SIZE\"             : \"{APP_NAME} 無法開啟大於 {0} MB 的檔案。\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"無法異動目標目錄。\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"您的權限不足，無法修改。\",\n    \"CONTENTS_MODIFIED_ERR\"             : \"檔案已被 {APP_NAME} 以外的程式修改。\",\n    \"UNSUPPORTED_ENCODING_ERR\"          : \"{APP_NAME} 目前只支援 UTF-8 編碼的文字檔。\",\n    \"FILE_EXISTS_ERR\"                   : \"檔案或目錄已經存在。\",\n    \"FILE\"                              : \"檔案\",\n    \"FILE_TITLE\"                        : \"檔案\",\n    \"DIRECTORY\"                         : \"目錄\",\n    \"DIRECTORY_TITLE\"                   : \"目錄\",\n    \"DIRECTORY_NAMES_LEDE\"              : \"目錄名稱\",\n    \"FILENAMES_LEDE\"                    : \"檔案名稱\",\n    \"FILENAME\"                          : \"檔案名稱\",\n    \"DIRECTORY_NAME\"                    : \"目錄名稱\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"無法載入專案\",\n    \"OPEN_DIALOG_ERROR\"                 : \"顯示開啟檔案對話框時發生錯誤。 (錯誤 {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"載入 <span class='dialog-filename'>{0}</span> 目錄時發生錯誤。 (錯誤 {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"讀取 <span class='dialog-filename'>{0}</span> 目錄中的內容時發生錯誤。 (錯誤 {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"無法開啟檔案\",\n    \"ERROR_OPENING_FILE\"                : \"開啟 <span class='dialog-filename'>{0}</span> 檔案時發生錯誤。 {1}\",\n    \"ERROR_OPENING_FILES\"               : \"開啟下列檔案時發生錯誤:\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"無法從磁碟重新載入變更\",\n    \"ERROR_RELOADING_FILE\"              : \"重新載入 <span class='dialog-filename'>{0}</span> 檔案時發生錯誤。 {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"無法儲存檔案\",\n    \"ERROR_SAVING_FILE\"                 : \"儲存 <span class='dialog-filename'>{0}</span> 檔案時發生錯誤。 {1}\",\n    \"ERROR_RENAMING_FILE_TITLE\"         : \"無法將{0}重新命名\",\n    \"ERROR_RENAMING_FILE\"               : \"重新命名{2} <span class='dialog-filename'>{0}</span> 時發生錯誤。 {1}\",\n    \"ERROR_DELETING_FILE_TITLE\"         : \"無法刪除{0}\",\n    \"ERROR_DELETING_FILE\"               : \"刪除{2} <span class='dialog-filename'>{0}</span> 時發生錯誤。 {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"{0}無效\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"{0}當中不能包含任何的系統保留字、結尾不能是半型句點 (.)，也不能使用下列字元: <code class='emphasized'>{1}</code>\",\n    \"ENTRY_WITH_SAME_NAME_EXISTS\"       : \"已經有叫做 <span class='dialog-filename'>{0}</span> 的檔案或目錄了。\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"無法建立{0}\",\n    \"ERROR_CREATING_FILE\"               : \"建立{0} <span class='dialog-filename'>{1}</span> 時發生錯誤。 {2}\",\n    \"ERROR_MIXED_DRAGDROP\"              : \"開啟其他檔案的同時不能開啟資料夾。\",\n\n    // User key map error strings\n    \"ERROR_KEYMAP_TITLE\"                : \"無法讀取使用者按鍵對應資料\",\n    \"ERROR_KEYMAP_CORRUPT\"              : \"您的按鍵對應檔內容不是正確的 JSON 格式。將開啟該檔以便您修正格式問題。\",\n    \"ERROR_LOADING_KEYMAP\"              : \"您的按鍵對應檔不是正確的 UTF-8 編碼文字檔，無法載入\",\n    \"ERROR_RESTRICTED_COMMANDS\"         : \"您無法重新定義下列指令的快捷鍵: {0}\",\n    \"ERROR_RESTRICTED_SHORTCUTS\"        : \"您無法重新定義快捷鍵: {0}\",\n    \"ERROR_MULTIPLE_SHORTCUTS\"          : \"您定義了超過一組快捷鍵給下列指令: {0}\",\n    \"ERROR_DUPLICATE_SHORTCUTS\"         : \"您定義了超過一種按鍵組合給下列快捷鍵: {0}\",\n    \"ERROR_INVALID_SHORTCUTS\"           : \"下列快捷鍵無效: {0}\",\n    \"ERROR_NONEXISTENT_COMMANDS\"        : \"您定義了快捷鍵給不存在的指令: {0}\",\n\n    // Application preferences corrupt error strings\n    \"ERROR_PREFS_CORRUPT_TITLE\"         : \"讀取喜好設定時發生錯誤\",\n    \"ERROR_PREFS_CORRUPT\"               : \"您的喜好設定檔內容不是正確的 JSON 格式。將開啟該檔以便您修正格式問題。 重新啟動 {APP_NAME} 後異動才會生效。\",\n    \"ERROR_PROJ_PREFS_CORRUPT\"          : \"您的專案喜好設定檔內容不是正確的 JSON 格式。將開啟該檔以便您修正格式問題。 重新啟動 {APP_NAME} 後異動才會生效。\",\n\n    // Application error strings\n    \"ERROR_IN_BROWSER_TITLE\"            : \"不妙! {APP_NAME} 還不能在瀏覽器裡跑。\",\n    \"ERROR_IN_BROWSER\"                  : \"{APP_NAME} 是以 HTML 打造，不過要以應用程式的方式執行才能編輯電腦上的檔案。請透過 <b>github.com/adobe/brackets-shell</b> 儲存庫中的應用程式介面來執行 {APP_NAME}。\",\n\n    // ProjectManager max files error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"無法建立檔案索引\",\n    \"ERROR_MAX_FILES\"                   : \"專案超過 30,000 個檔案。需要跨檔案執行的功能可能會被關閉或是變成跟專案內沒有任何檔案一樣。<a href='https://github.com/adobe/brackets/wiki/Large-Projects'>了解怎麼處理大型專案</a>。\",\n\n    // Live Preview error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"無法啟動瀏覽器\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"找不到 Google Chrome 瀏覽器。請確定您有安裝。\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"啟動瀏覽器時發生錯誤。 (錯誤 {0})\",\n\n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"即時預覽錯誤\",\n    \"LIVE_DEVELOPMENT_RELAUNCH_TITLE\"   : \"正在連到瀏覽器\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"為了讓即時預覽功能順利連線，需要重新啟動 Chrome 並開啟遠端除錯功能。<br /><br />您是否要重新啟動 Chrome 並啟用遠端除錯功能?<br /><br />\",\n    \"LIVE_DEV_LOADING_ERROR_MESSAGE\"    : \"無法載入即時預覽頁。\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"請開啟 HTML 檔，或是確定專案中有 index.html 檔才能啟動即時預覽功能。\",\n    \"LIVE_DEV_NEED_BASEURL_MESSAGE\"     : \"您需要指定專案的 URL 根位址，才能啟動包含伺服器端資源的即時預覽功能。\",\n    \"LIVE_DEV_SERVER_NOT_READY_MESSAGE\" : \"無法啟動即時預覽用的 HTTP 伺服器。請再試一次。\",\n    \"LIVE_DEVELOPMENT_INFO_TITLE\"       : \"歡迎使用即時預覽!\",\n    \"LIVE_DEVELOPMENT_INFO_MESSAGE\"     : \"即時預覽將 {APP_NAME} 與您的瀏覽器連線。讓您在瀏覽器中預覽 HTML 檔案，編輯的內容也會即時反應在預覽畫面上。<br /><br />因為 {APP_NAME} 才剛起步，即時預覽目前只能在 <strong>Google Chrome</strong> 上面執行，<strong>CSS 或 HTML 檔案</strong>的異動會即時反應。修改 JavaScript 檔案並儲存後會重新載入頁面。<br /><br />(您只會看到一次這段訊息。)\",\n    \"LIVE_DEVELOPMENT_TROUBLESHOOTING\"  : \"想了解更多，請參考<a href='{0}' title='{0}'>即時預覽連結錯誤排解</a>。\",\n\n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"即時預覽\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"即時預覽: 連線中\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"即時預覽: 初始化中\\u2026\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"關閉即時預覽\",\n    \"LIVE_DEV_STATUS_TIP_OUT_OF_SYNC\"   : \"即時預覽 (檔案儲存後重新載入)\",\n    \"LIVE_DEV_STATUS_TIP_SYNC_ERROR\"    : \"即時預覽 (語法錯誤，不更新)\",\n\n    \"LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS\" : \"已取消即時預覽，因為開發者工具被打開了\",\n    \"LIVE_DEV_DETACHED_TARGET_CLOSED\"          : \"已取消即時預覽，因為頁面被關掉了\",\n    \"LIVE_DEV_NAVIGATED_AWAY\"                  : \"已取消即時預覽，因為您連到專案外的頁面了\",\n    \"LIVE_DEV_CLOSED_UNKNOWN_REASON\"           : \"即時預覽因為不明的錯誤而取消 ({0})\",\n\n    \"SAVE_CLOSE_TITLE\"                  : \"儲存變更\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"您想要儲存 <span class='dialog-filename'>{0}</span> 檔案的變更嗎?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"您想要儲存下列檔案的變更嗎?\",\n    \"EXT_MODIFIED_TITLE\"                : \"外部變更\",\n    \"CONFIRM_DELETE_TITLE\"              : \"確定刪除\",\n    \"CONFIRM_FOLDER_DELETE\"             : \"您確定要刪除 <span class='dialog-filename'>{0}</span> 資料夾嗎?\",\n    \"FILE_DELETED_TITLE\"                : \"檔案已刪除\",\n    \"EXT_MODIFIED_WARNING\"              : \"<span class='dialog-filename'>{0}</span> 在 {APP_NAME} 外被修改過了。<br /><br />您想要儲存檔案並覆寫蓋掉外部的變更嗎?\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> 在 {APP_NAME} 外被修改過了，但在 {APP_NAME} 中也有還沒儲存的變更。<br /><br />您想保留哪個版本呢?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> 在 {APP_NAME} 外被刪除了，但在 {APP_NAME} 中還有沒儲存的變更。<br /><br />想要保留您變更的內容嗎?\",\n\n    // Generic dialog/button labels\n    \"DONE\"                              : \"完成\",\n    \"OK\"                                : \"確定\",\n    \"CANCEL\"                            : \"取消\",\n    \"DONT_SAVE\"                         : \"不要儲存\",\n    \"SAVE\"                              : \"儲存\",\n    \"SAVE_AS\"                           : \"另存新檔\\u2026\",\n    \"SAVE_AND_OVERWRITE\"                : \"覆寫\",\n    \"DELETE\"                            : \"刪除\",\n    \"BUTTON_YES\"                        : \"是\",\n    \"BUTTON_NO\"                         : \"否\",\n\n    // Find, Replace, Find in Files\n    \"FIND_MATCH_INDEX\"                  : \"{0} / {1}\",\n    \"FIND_NO_RESULTS\"                   : \"沒有結果\",\n    \"FIND_QUERY_PLACEHOLDER\"            : \"尋找\\u2026\",\n    \"REPLACE_PLACEHOLDER\"               : \"取代成\\u2026\",\n    \"BUTTON_REPLACE_ALL\"                : \"批次\\u2026\",\n    \"BUTTON_REPLACE_ALL_IN_FILES\"       : \"取代\\u2026\",\n    \"BUTTON_REPLACE\"                    : \"取代\",\n    \"BUTTON_NEXT\"                       : \"\\u25B6\",\n    \"BUTTON_PREV\"                       : \"\\u25C0\",\n    \"BUTTON_NEXT_HINT\"                  : \"下一筆符合的\",\n    \"BUTTON_PREV_HINT\"                  : \"上一筆符合的\",\n    \"BUTTON_CASESENSITIVE_HINT\"         : \"大小寫須相符\",\n    \"BUTTON_REGEXP_HINT\"                : \"正規表示式\",\n    \"REPLACE_WITHOUT_UNDO_WARNING_TITLE\": \"取代後無法復原\",\n    \"REPLACE_WITHOUT_UNDO_WARNING\"      : \"有超過 {0} 個檔案會被變更，{APP_NAME} 會修改到磁碟上沒被開啟的檔案。<br />這些檔案內容取代後無法再復原。\",\n    \"BUTTON_REPLACE_WITHOUT_UNDO\"       : \"直接取代，不用復原\",\n\n    \"OPEN_FILE\"                         : \"開啟檔案\",\n    \"SAVE_FILE_AS\"                      : \"儲存檔案\",\n    \"CHOOSE_FOLDER\"                     : \"選取資料夾\",\n\n    \"RELEASE_NOTES\"                     : \"版本資訊\",\n    \"NO_UPDATE_TITLE\"                   : \"已經是最新版!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"您的 {APP_NAME} 已經是最新版。\",\n\n    // Find and Replace\n    \"FIND_REPLACE_TITLE_LABEL\"          : \"將\",\n    \"FIND_REPLACE_TITLE_WITH\"           : \"取代成\",\n    \"FIND_TITLE_LABEL\"                  : \"找到\",\n    \"FIND_TITLE_SUMMARY\"                : \"&mdash; {3}中共有{0} {1} 筆{2}\",\n\n    // Find in Files\n    \"FIND_NUM_FILES\"                    : \"{0} 個{1}\",\n    \"FIND_IN_FILES_SCOPED\"              : \"在 <span class='dialog-filename'>{0}</span> 中\",\n    \"FIND_IN_FILES_NO_SCOPE\"            : \"在專案中\",\n    \"FIND_IN_FILES_ZERO_FILES\"          : \"篩選條件排除了{0}的所有檔案\",\n    \"FIND_IN_FILES_FILE\"                : \"檔案\",\n    \"FIND_IN_FILES_FILES\"               : \"檔案\",\n    \"FIND_IN_FILES_MATCH\"               : \"符合\",\n    \"FIND_IN_FILES_MATCHES\"             : \"符合\",\n    \"FIND_IN_FILES_MORE_THAN\"           : \"超過\",\n    \"FIND_IN_FILES_PAGING\"              : \"{0}&mdash;{1}\",\n    \"FIND_IN_FILES_FILE_PATH\"           : \"<span class='dialog-filename'>{0}</span> {2} <span class='dialog-path'>{1}</span>\", // We should use normal dashes on Windows instead of em dash eventually\n    \"FIND_IN_FILES_EXPAND_COLLAPSE\"     : \"按住 Ctrl/Cmd 再用滑鼠點一下可以全部展開/收合\",\n    \"REPLACE_IN_FILES_ERRORS_TITLE\"     : \"取代錯誤\",\n    \"REPLACE_IN_FILES_ERRORS\"           : \"下列檔案沒有被修改，可能是搜尋後又被變更或是無法寫入。\",\n\n    \"ERROR_FETCHING_UPDATE_INFO_TITLE\"  : \"無法取得更新資訊\",\n    \"ERROR_FETCHING_UPDATE_INFO_MSG\"    : \"由伺服器取得更新資訊時發生錯誤。請確定您已連線到 Internet 後再重試一次。\",\n\n    // File exclusion filters\n    \"NEW_FILE_FILTER\"                   : \"新增排除集\\u2026\",\n    \"CLEAR_FILE_FILTER\"                 : \"不要排除檔案\",\n    \"NO_FILE_FILTER\"                    : \"沒有檔案被排除\",\n    \"EXCLUDE_FILE_FILTER\"               : \"排除 {0}\",\n    \"EDIT_FILE_FILTER\"                  : \"編輯\\u2026\",\n    \"FILE_FILTER_DIALOG\"                : \"編輯排除集\",\n    \"FILE_FILTER_INSTRUCTIONS\"          : \"排除名稱完全或部分符合下列字串的檔案及資料夾，也可以使用<a href='{0}' title='{0}'>萬用字元</a>。 多組條件請分行輸入，一行一個。\",\n    \"FILTER_NAME_PLACEHOLDER\"           : \"排除集名稱 (選填)\",\n    \"FILE_FILTER_CLIPPED_SUFFIX\"        : \"及其他 {0} 個\",\n    \"FILTER_COUNTING_FILES\"             : \"計算檔案數目中\\u2026\",\n    \"FILTER_FILE_COUNT\"                 : \"包含{2}全部 {1} 個檔案中的 {0} 個\",\n    \"FILTER_FILE_COUNT_ALL\"             : \"包含{1}的全部 {0} 個檔案\",\n\n    // Quick Edit\n    \"ERROR_QUICK_EDIT_PROVIDER_NOT_FOUND\"   : \"游標所在位置沒有相關的快速編輯功能\",\n    \"ERROR_CSSQUICKEDIT_BETWEENCLASSES\"     : \"CSS 快速編輯: 將游標放在單一 class 名稱上\",\n    \"ERROR_CSSQUICKEDIT_CLASSNOTFOUND\"      : \"CSS 快速編輯: class 屬性不完整\",\n    \"ERROR_CSSQUICKEDIT_IDNOTFOUND\"         : \"CSS 快速編輯: id 屬性不完整\",\n    \"ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR\"    : \"CSS 快速編輯: 將游標放在標籤名稱、class 或 id 上\",\n    \"ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX\"   : \"CSS 計時函式快速編輯: 語法無效\",\n    \"ERROR_JSQUICKEDIT_FUNCTIONNOTFOUND\"    : \"JS 快速編輯: 將游標放在函式名稱上\",\n\n    // Quick Docs\n    \"ERROR_QUICK_DOCS_PROVIDER_NOT_FOUND\"   : \"游標所在位置沒有相關的快速文件\",\n\n    /**\n     * ProjectManager\n     */\n    \"PROJECT_LOADING\"   : \"載入中\\u2026\",\n    \"UNTITLED\"          : \"未命名\",\n    \"WORKING_FILES\"     : \"工作檔案\",\n\n    /**\n     * MainViewManager\n     */\n    \"TOP\"               : \"上方\",\n    \"BOTTOM\"            : \"下方\",\n    \"LEFT\"              : \"左側\",\n    \"RIGHT\"             : \"右側\",\n\n    \"CMD_SPLITVIEW_NONE\"        : \"不分割\",\n    \"CMD_SPLITVIEW_VERTICAL\"    : \"左右分割\",\n    \"CMD_SPLITVIEW_HORIZONTAL\"  : \"上下分割\",\n    \"SPLITVIEW_MENU_TOOLTIP\"    : \"將編輯器分割成上下或左右兩塊\",\n    \"GEAR_MENU_TOOLTIP\"         : \"設定工作集\",\n\n    \"SPLITVIEW_INFO_TITLE\"              : \"已經開啟\",\n    \"SPLITVIEW_MULTIPANE_WARNING\"       : \"檔案已經在另一個窗格中開啟。{APP_NAME} 很快就會支援在多個窗格中開啟相同的檔案。在那之前，檔案還是會在原本已開啟的窗格中顯示。<br /><br />(您只會看到一次這個訊息。)\",\n\n    /**\n     * Keyboard modifiers and special key names\n     */\n    \"KEYBOARD_CTRL\"         : \"Ctrl\",\n    \"KEYBOARD_SHIFT\"        : \"Shift\",\n    \"KEYBOARD_SPACE\"        : \"空白鍵\",\n    \"KEYBOARD_PAGE_UP\"      : \"Page Up\",\n    \"KEYBOARD_PAGE_DOWN\"    : \"Page Down\",\n    \"KEYBOARD_HOME\"         : \"Home\",\n    \"KEYBOARD_END\"          : \"End\",\n    \"KEYBOARD_INSERT\"       : \"Insert\",\n    \"KEYBOARD_DELETE\"       : \"Delete\",\n\n    /**\n     * StatusBar strings\n     */\n    \"STATUSBAR_CURSOR_POSITION\"             : \"第 {0} 行，第 {1} 個字元\",\n    \"STATUSBAR_SELECTION_CH_SINGULAR\"       : \" \\u2014 選了 {0} 個字元\",\n    \"STATUSBAR_SELECTION_CH_PLURAL\"         : \" \\u2014 選了 {0} 個字元\",\n    \"STATUSBAR_SELECTION_LINE_SINGULAR\"     : \" \\u2014 選了 {0} 行\",\n    \"STATUSBAR_SELECTION_LINE_PLURAL\"       : \" \\u2014 選了 {0} 行\",\n    \"STATUSBAR_SELECTION_MULTIPLE\"          : \" \\u2014 選了 {0} 段\",\n    \"STATUSBAR_INDENT_TOOLTIP_SPACES\"       : \"點一下切換成使用空白字元縮排\",\n    \"STATUSBAR_INDENT_TOOLTIP_TABS\"         : \"點一下切換成使用 Tab 縮排\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_SPACES\"  : \"點一下變更縮排用的空白字元數\",\n    \"STATUSBAR_INDENT_SIZE_TOOLTIP_TABS\"    : \"點一下變更 Tab 字元所代表的長度\",\n    \"STATUSBAR_SPACES\"                      : \"空白字元:\",\n    \"STATUSBAR_TAB_SIZE\"                    : \"Tab 長度:\",\n    \"STATUSBAR_LINE_COUNT_SINGULAR\"         : \"\\u2014 {0} 行\",\n    \"STATUSBAR_LINE_COUNT_PLURAL\"           : \"\\u2014 {0} 行\",\n    \"STATUSBAR_USER_EXTENSIONS_DISABLED\"    : \"已停用擴充功能\",\n    \"STATUSBAR_INSERT\"                      : \"INS\",\n    \"STATUSBAR_OVERWRITE\"                   : \"OVR\",\n    \"STATUSBAR_INSOVR_TOOLTIP\"              : \"按一下可以在插入 (INS) 與覆寫 (OVR) 模式中切換\",\n    \"STATUSBAR_LANG_TOOLTIP\"                : \"按一下可以變更檔案類型\",\n    \"STATUSBAR_CODE_INSPECTION_TOOLTIP\"     : \"{0}。按一下可以開啟或關閉報告面板。\",\n    \"STATUSBAR_DEFAULT_LANG\"                : \"(預設)\",\n    \"STATUSBAR_SET_DEFAULT_LANG\"            : \"設定成 .{0} 檔的預設值\",\n\n    // CodeInspection: errors/warnings\n    \"ERRORS_PANEL_TITLE_MULTIPLE\"           : \"{0} 項問題\",\n    \"SINGLE_ERROR\"                          : \"1 項 {0} 問題\",\n    \"MULTIPLE_ERRORS\"                       : \"{1} 項 {0} 問題\",\n    \"NO_ERRORS\"                             : \"沒發現任何 {0} 問題，幹得好!\",\n    \"NO_ERRORS_MULTIPLE_PROVIDER\"           : \"沒發現任何問題，幹得好!\",\n    \"LINT_DISABLED\"                         : \"已停用 Lint 功能\",\n    \"NO_LINT_AVAILABLE\"                     : \"沒有 {0} 適用的 Linter\",\n    \"NOTHING_TO_LINT\"                       : \"沒有東西好 Lint\",\n    \"LINTER_TIMED_OUT\"                      : \"{0} 等了 {1} 毫秒後逾時\",\n    \"LINTER_FAILED\"                         : \"{0} 已終止，錯誤: {1}\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"檔案\",\n    \"CMD_FILE_NEW_UNTITLED\"               : \"新增\",\n    \"CMD_FILE_NEW\"                        : \"新增檔案\",\n    \"CMD_FILE_NEW_FOLDER\"                 : \"新增資料夾\",\n    \"CMD_FILE_OPEN\"                       : \"開啟\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"開啟進工作集\",\n    \"CMD_OPEN_DROPPED_FILES\"              : \"開啟拖放的檔案\",\n    \"CMD_OPEN_FOLDER\"                     : \"開啟資料夾\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"關閉\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"全部關閉\",\n    \"CMD_FILE_CLOSE_LIST\"                 : \"關閉清單\",\n    \"CMD_FILE_CLOSE_OTHERS\"               : \"關閉其他檔案\",\n    \"CMD_FILE_CLOSE_ABOVE\"                : \"關閉上列檔案\",\n    \"CMD_FILE_CLOSE_BELOW\"                : \"關閉下列檔案\",\n    \"CMD_FILE_SAVE\"                       : \"儲存\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"全部儲存\",\n    \"CMD_FILE_SAVE_AS\"                    : \"另存新檔\\u2026\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"即時預覽\",\n    \"CMD_TOGGLE_LIVE_PREVIEW_MB_MODE\"     : \"啟用實驗版即時預覽\",\n    \"CMD_RELOAD_LIVE_PREVIEW\"             : \"強制重新載入即時預覽\",\n    \"CMD_PROJECT_SETTINGS\"                : \"專案設定\\u2026\",\n    \"CMD_FILE_RENAME\"                     : \"重新命名\",\n    \"CMD_FILE_DELETE\"                     : \"刪除\",\n    \"CMD_INSTALL_EXTENSION\"               : \"安裝擴充功能\\u2026\",\n    \"CMD_EXTENSION_MANAGER\"               : \"擴充功能管理員\\u2026\",\n    \"CMD_FILE_REFRESH\"                    : \"重新整理檔案樹\",\n    \"CMD_QUIT\"                            : \"結束\",\n    // Used in native File menu on Windows\n    \"CMD_EXIT\"                            : \"結束\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"編輯\",\n    \"CMD_UNDO\"                            : \"復原\",\n    \"CMD_REDO\"                            : \"取消復原\",\n    \"CMD_CUT\"                             : \"剪下\",\n    \"CMD_COPY\"                            : \"複製\",\n    \"CMD_PASTE\"                           : \"貼上\",\n    \"CMD_SELECT_ALL\"                      : \"全部選取\",\n    \"CMD_SELECT_LINE\"                     : \"整行選取\",\n    \"CMD_SPLIT_SEL_INTO_LINES\"            : \"逐行切成多段選取區塊\",\n    \"CMD_ADD_CUR_TO_NEXT_LINE\"            : \"在下一行加入游標\",\n    \"CMD_ADD_CUR_TO_PREV_LINE\"            : \"在上一行加入游標\",\n    \"CMD_INDENT\"                          : \"縮排\",\n    \"CMD_UNINDENT\"                        : \"取消縮排\",\n    \"CMD_DUPLICATE\"                       : \"整行複製\",\n    \"CMD_DELETE_LINES\"                    : \"整行刪除\",\n    \"CMD_COMMENT\"                         : \"加入或取消行註解\",\n    \"CMD_BLOCK_COMMENT\"                   : \"加入或取消區塊註解\",\n    \"CMD_LINE_UP\"                         : \"整行上移\",\n    \"CMD_LINE_DOWN\"                       : \"整行下移\",\n    \"CMD_OPEN_LINE_ABOVE\"                 : \"往上新增一行\",\n    \"CMD_OPEN_LINE_BELOW\"                 : \"往下新增一行\",\n    \"CMD_TOGGLE_CLOSE_BRACKETS\"           : \"自動插入右括號\",\n    \"CMD_SHOW_CODE_HINTS\"                 : \"顯示程式提示\",\n\n    // Search menu commands\n    \"FIND_MENU\"                           : \"尋找\",\n    \"CMD_FIND\"                            : \"尋找\",\n    \"CMD_FIND_NEXT\"                       : \"找下一個\",\n    \"CMD_FIND_PREVIOUS\"                   : \"找上一個\",\n    \"CMD_FIND_ALL_AND_SELECT\"             : \"找出並全部選取\",\n    \"CMD_ADD_NEXT_MATCH\"                  : \"一併選取下一筆符合的\",\n    \"CMD_SKIP_CURRENT_MATCH\"              : \"跳過並選取下一筆符合的\",\n    \"CMD_FIND_IN_FILES\"                   : \"在檔案中尋找\",\n    \"CMD_FIND_IN_SUBTREE\"                 : \"尋找\\u2026\",\n    \"CMD_REPLACE\"                         : \"取代\",\n    \"CMD_REPLACE_IN_FILES\"                : \"在檔案中取代\",\n    \"CMD_REPLACE_IN_SUBTREE\"              : \"取代\\u2026\",\n\n    // View menu commands\n    \"VIEW_MENU\"                           : \"檢視\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"隱藏側欄\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"顯示側欄\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"放大字體\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"縮小字體\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"還原字體大小\",\n    \"CMD_SCROLL_LINE_UP\"                  : \"向上捲動一行\",\n    \"CMD_SCROLL_LINE_DOWN\"                : \"向下捲動一行\",\n    \"CMD_TOGGLE_LINE_NUMBERS\"             : \"行號\",\n    \"CMD_TOGGLE_ACTIVE_LINE\"              : \"強調游標所在行\",\n    \"CMD_TOGGLE_WORD_WRAP\"                : \"自動換行\",\n    \"CMD_LIVE_HIGHLIGHT\"                  : \"即時預覽強調顯示\",\n    \"CMD_VIEW_TOGGLE_INSPECTION\"          : \"存檔時執行 Lint\",\n    \"CMD_WORKINGSET_SORT_BY_ADDED\"        : \"依加入先後排序\",\n    \"CMD_WORKINGSET_SORT_BY_NAME\"         : \"依檔名排序\",\n    \"CMD_WORKINGSET_SORT_BY_TYPE\"         : \"依類型排序\",\n    \"CMD_WORKING_SORT_TOGGLE_AUTO\"        : \"自動排序\",\n    \"CMD_THEMES\"                          : \"佈景主題\\u2026\",\n\n    // Navigate menu commands\n    \"NAVIGATE_MENU\"                       : \"瀏覽\",\n    \"CMD_QUICK_OPEN\"                      : \"快速開啟\",\n    \"CMD_GOTO_LINE\"                       : \"到指定行\",\n    \"CMD_GOTO_DEFINITION\"                 : \"快速尋找定義\",\n    \"CMD_GOTO_FIRST_PROBLEM\"              : \"到第一筆問題\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"快速編輯\",\n    \"CMD_TOGGLE_QUICK_DOCS\"               : \"快速文件\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"上一筆符合\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"下一筆符合\",\n    \"CMD_CSS_QUICK_EDIT_NEW_RULE\"         : \"新增規則\",\n    \"CMD_NEXT_DOC\"                        : \"下一個檔案\",\n    \"CMD_PREV_DOC\"                        : \"上一個檔案\",\n    \"CMD_NEXT_DOC_LIST_ORDER\"             : \"清單中的下一個檔案\",\n    \"CMD_PREV_DOC_LIST_ORDER\"             : \"清單中的上一個檔案\",\n    \"CMD_SHOW_IN_TREE\"                    : \"在檔案樹中顯示\",\n    \"CMD_SHOW_IN_EXPLORER\"                : \"在檔案總管中顯示\",\n    \"CMD_SHOW_IN_FINDER\"                  : \"在 Finder 中顯示\",\n    \"CMD_SHOW_IN_OS\"                      : \"在作業系統中顯示\",\n\n    // Help menu commands\n    \"HELP_MENU\"                           : \"說明\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"檢查是否有更新\",\n    \"CMD_HOW_TO_USE_BRACKETS\"             : \"如何使用 {APP_NAME}\",\n    \"CMD_SUPPORT\"                         : \"{APP_NAME} 支援\",\n    \"CMD_SUGGEST\"                         : \"功能建議\",\n    \"CMD_RELEASE_NOTES\"                   : \"版本資訊\",\n    \"CMD_GET_INVOLVED\"                    : \"參與\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"顯示擴充功能資料夾\",\n    \"CMD_HEALTH_DATA_STATISTICS\"          : \"狀況報告\",\n    \"CMD_HOMEPAGE\"                        : \"{APP_TITLE} 首頁\",\n    \"CMD_TWITTER\"                         : \"Twitter {TWITTER_NAME} 專頁\",\n    \"CMD_ABOUT\"                           : \"關於 {APP_TITLE}\",\n    \"CMD_OPEN_PREFERENCES\"                : \"開啟喜好設定檔\",\n    \"CMD_OPEN_KEYMAP\"                     : \"開啟使用者按鍵對應檔\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"實驗建置\",\n    \"RELEASE_BUILD\"                        : \"建置\",\n    \"DEVELOPMENT_BUILD\"                    : \"開發建置\",\n    \"RELOAD_FROM_DISK\"                     : \"從磁碟重新載入\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"在編輯器中保留變更\",\n    \"CLOSE_DONT_SAVE\"                      : \"關閉 (不要儲存)\",\n    \"RELAUNCH_CHROME\"                      : \"重新啟動 Chrome\",\n    \"ABOUT\"                                : \"關於\",\n    \"CLOSE\"                                : \"關閉\",\n    \"ABOUT_TEXT_LINE1\"                     : \"發行 {VERSION_MAJOR}.{VERSION_MINOR} {BUILD_TYPE} {VERSION}\",\n    \"ABOUT_TEXT_BUILD_TIMESTAMP\"           : \"建置時間: \",\n    \"ABOUT_TEXT_LINE3\"                     : \"第三方軟體的注意事項、使用條款及條件公佈在 <a href='{ADOBE_THIRD_PARTY}'>{ADOBE_THIRD_PARTY}</a>，於此引用納入。\",\n    \"ABOUT_TEXT_LINE4\"                     : \"說明文件及原始碼都在 <a href='https://github.com/adobe/brackets/'>https://github.com/adobe/brackets/</a> 上。\",\n    \"ABOUT_TEXT_LINE5\"                     : \"用 \\u2764 跟 JavaScript 打造。工匠名錄:\",\n    \"ABOUT_TEXT_LINE6\"                     : \"一大票人馬 (只可惜我們現在沒辦法正常載入名單)。\",\n    \"ABOUT_TEXT_MDN_DOCS\"                  : \"MDN 文件及 MDN 圖示皆以 Creative Commons Attribution 授權條款 <a href='{MDN_DOCS_LICENSE}'>CC-BY-SA 2.5 Unported</a> 授權。\",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"有新版的 {APP_NAME}! 點這裡了解詳情。\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"有新版\",\n    \"UPDATE_MESSAGE\"                       : \"嗨! 新版的 {APP_NAME} 已經可以下載。新功能有:\",\n    \"GET_IT_NOW\"                           : \"馬上取得!\",\n    \"PROJECT_SETTINGS_TITLE\"               : \"專案設定: {0}\",\n    \"PROJECT_SETTING_BASE_URL\"             : \"即時預覽 URL 根位址\",\n    \"PROJECT_SETTING_BASE_URL_HINT\"        : \"如果要用本機伺服器，可以輸入 http://localhost:8000/ 這類 URL\",\n    \"BASEURL_ERROR_INVALID_PROTOCOL\"       : \"即時預覽功能不支援 {0} 協定&mdash;請使用 http: 或 https: 。\",\n    \"BASEURL_ERROR_SEARCH_DISALLOWED\"      : \"URL 根位址不能有 \\\"{0}\\\" 這類搜尋參數。\",\n    \"BASEURL_ERROR_HASH_DISALLOWED\"        : \"URL 根位址不能有半型井號 (#)，例如 \\\"{0}\\\"。\",\n    \"BASEURL_ERROR_INVALID_CHAR\"           : \"'{0}' 這類特殊字元一定要用 % 格式編碼過。\",\n    \"BASEURL_ERROR_UNKNOWN_ERROR\"          : \"解析 URL 根位址時發生不明錯誤\",\n    \"EMPTY_VIEW_HEADER\"                    : \"<em>選到本窗格後再開啟檔案</em>\",\n\n    // Strings for themes-settings.html and themes-general.html\n    \"CURRENT_THEME\"                        : \"目前的佈景主題\",\n    \"USE_THEME_SCROLLBARS\"                 : \"使用佈景主題的捲軸\",\n    \"FONT_SIZE\"                            : \"字體大小\",\n    \"FONT_FAMILY\"                          : \"字體\",\n    \"THEMES_SETTINGS\"                      : \"佈景主題設定\",\n\n    // CSS Quick Edit\n    \"BUTTON_NEW_RULE\"                      : \"新增規則\",\n\n    // Extension Management strings\n    \"INSTALL\"                              : \"安裝\",\n    \"UPDATE\"                               : \"更新\",\n    \"REMOVE\"                               : \"移除\",\n    \"DISABLE\"                              : \"停用\",\n    \"ENABLE\"                               : \"啟用\",\n    \"OVERWRITE\"                            : \"覆寫\",\n    \"CANT_REMOVE_DEV\"                      : \"在 \\\"dev\\\" 資料夾中的擴充功能必需手動刪除。\",\n    \"CANT_UPDATE\"                          : \"這項更新不相容於這一版的 {APP_NAME}。\",\n    \"CANT_UPDATE_DEV\"                      : \"在 \\\"dev\\\" 資料夾中的擴充功能無法自動更新。\",\n    \"INSTALL_EXTENSION_TITLE\"              : \"安裝擴充功能\",\n    \"UPDATE_EXTENSION_TITLE\"               : \"更新擴充功能\",\n    \"INSTALL_EXTENSION_LABEL\"              : \"擴充功能 URL\",\n    \"INSTALL_EXTENSION_HINT\"               : \"擴充功能 zip 壓縮檔或是 GitHub 儲存庫的 URL\",\n    \"INSTALLING_FROM\"                      : \"由 {0} 安裝擴充功能中\\u2026\",\n    \"INSTALL_SUCCEEDED\"                    : \"安裝成功!\",\n    \"INSTALL_FAILED\"                       : \"安裝失敗。\",\n    \"CANCELING_INSTALL\"                    : \"取消中\\u2026\",\n    \"CANCELING_HUNG\"                       : \"取消安裝花太多時間。可能發生了內部錯誤。\",\n    \"INSTALL_CANCELED\"                     : \"安裝已取消。\",\n    \"VIEW_COMPLETE_DESCRIPTION\"            : \"顯示完整描述資訊\",\n    \"VIEW_TRUNCATED_DESCRIPTION\"           : \"只顯示部分描述資訊\",\n    // These must match the error codes in ExtensionsDomain.Errors.* :\n    \"INVALID_ZIP_FILE\"                     : \"下載的內容不是正確的 zip 壓縮檔。\",\n    \"INVALID_PACKAGE_JSON\"                 : \"package.json 檔案無效 (錯誤: {0}).\",\n    \"MISSING_PACKAGE_NAME\"                 : \"package.json 檔案中沒有指定套件名稱。\",\n    \"BAD_PACKAGE_NAME\"                     : \"{0} 不是正確的套件名稱。\",\n    \"MISSING_PACKAGE_VERSION\"              : \"package.json 檔案中沒有指定套件版本。\",\n    \"INVALID_VERSION_NUMBER\"               : \"套件版號 ({0}) 無效。\",\n    \"INVALID_BRACKETS_VERSION\"             : \"{APP_NAME} 相容性字串 ({0}) 無效。\",\n    \"DISALLOWED_WORDS\"                     : \"{0} 欄位中不能有 ({1}) 這些字。\",\n    \"API_NOT_COMPATIBLE\"                   : \"這個擴充功能不相容於本版 {APP_NAME}。已將其安裝在 \\\"disabled\\\" 已停用擴充功能資料夾中。\",\n    \"MISSING_MAIN\"                         : \"套件中沒有 main.js 檔案。\",\n    \"EXTENSION_ALREADY_INSTALLED\"          : \"安裝這個套件將會蓋掉先前安裝的擴充功能。 是否要覆寫?\",\n    \"EXTENSION_SAME_VERSION\"               : \"已經安裝過這個版本的套件了。 是否要覆寫已安裝的版本?\",\n    \"EXTENSION_OLDER_VERSION\"              : \"{0} 版的套件比已安裝的版本 ({1}) 還要舊。 是否要覆寫已經安裝的版本?\",\n    \"DOWNLOAD_ID_IN_USE\"                   : \"內部錯誤: 下載識別碼正在使用中。\",\n    \"NO_SERVER_RESPONSE\"                   : \"無法連到伺服器。\",\n    \"BAD_HTTP_STATUS\"                      : \"伺服器 (HTTP {0}) 回應找不到檔案。\",\n    \"CANNOT_WRITE_TEMP\"                    : \"無法下載存成暫存檔。\",\n    \"ERROR_LOADING\"                        : \"擴充功能啟動時發生錯誤。\",\n    \"MALFORMED_URL\"                        : \"URL 無效。請檢查您是否輸入正確。\",\n    \"UNSUPPORTED_PROTOCOL\"                 : \"只支援 http 或 https 協定的 URL。\",\n    \"UNKNOWN_ERROR\"                        : \"不明的內部錯誤。\",\n    // For NOT_FOUND_ERR, see generic strings above\n    \"EXTENSION_MANAGER_TITLE\"              : \"擴充功能管理員\",\n    \"EXTENSION_MANAGER_ERROR_LOAD\"         : \"無法存取擴充功能登錄庫。請稍後再試。\",\n    \"INSTALL_EXTENSION_DRAG\"               : \"將 .zip 拖過來，或\",\n    \"INSTALL_EXTENSION_DROP\"               : \"放開 .zip 開始安裝\",\n    \"INSTALL_EXTENSION_DROP_ERROR\"         : \"下列原因造成安裝或是更新失敗:\",\n    \"INSTALL_FROM_URL\"                     : \"由 URL 安裝\\u2026\",\n    \"INSTALL_EXTENSION_VALIDATING\"         : \"Validating\\u2026\",\n    \"EXTENSION_AUTHOR\"                     : \"作者\",\n    \"EXTENSION_DATE\"                       : \"日期\",\n    \"EXTENSION_INCOMPATIBLE_NEWER\"         : \"這個擴充功能需要較新版的 {APP_NAME} 才能使用。\",\n    \"EXTENSION_INCOMPATIBLE_OLDER\"         : \"這個擴充功能目前只能在舊版 {APP_NAME} 中使用。\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_NEWER\"  : \"這個擴充功能 {0} 版只能在新版 {APP_NAME} 中使用。不過您可以選擇安裝較舊的 {1} 版。\",\n    \"EXTENSION_LATEST_INCOMPATIBLE_OLDER\"  : \"這個擴充功能 {0} 版只能在舊版 {APP_NAME} 中使用。不過您可以選擇安裝較舊的 {1} 版。\",\n    \"EXTENSION_NO_DESCRIPTION\"             : \"沒有描述資訊\",\n    \"EXTENSION_MORE_INFO\"                  : \"更多資訊\\u2026\",\n    \"EXTENSION_ERROR\"                      : \"擴充功能錯誤\",\n    \"EXTENSION_KEYWORDS\"                   : \"關鍵字\",\n    \"EXTENSION_TRANSLATED_USER_LANG\"       : \"包含您使用的語言在內，總共支援 {0} 種語言\",\n    \"EXTENSION_TRANSLATED_GENERAL\"         : \"支援 {0} 種語言\",\n    \"EXTENSION_TRANSLATED_LANGS\"           : \"這個擴充功能已經被翻譯成下列語言: {0}\",\n    \"EXTENSION_INSTALLED\"                  : \"已安裝\",\n    \"EXTENSION_UPDATE_INSTALLED\"           : \"這個擴充功能的更新已經下載完成，會在重新載入 {APP_NAME} 時安裝。\",\n    \"EXTENSION_SEARCH_PLACEHOLDER\"         : \"搜尋\",\n    \"EXTENSION_MORE_INFO_LINK\"             : \"更多\",\n    \"BROWSE_EXTENSIONS\"                    : \"瀏覽擴充功能\",\n    \"EXTENSION_MANAGER_REMOVE\"             : \"移除擴充功能\",\n    \"EXTENSION_MANAGER_REMOVE_ERROR\"       : \"無法移除擴充功能: {0}。 {APP_NAME} 還是會重新載入。\",\n    \"EXTENSION_MANAGER_UPDATE\"             : \"更新擴充功能\",\n    \"EXTENSION_MANAGER_UPDATE_ERROR\"       : \"無法更新擴充功能: {0}。 {APP_NAME} 還是會重新載入。\",\n    \"EXTENSION_MANAGER_DISABLE\"            : \"停用擴充功能\",\n    \"EXTENSION_MANAGER_DISABLE_ERROR\"      : \"無法停用擴充功能: {0}。 {APP_NAME} 還是會重新載入。\",\n    \"MARKED_FOR_REMOVAL\"                   : \"標為待移除\",\n    \"UNDO_REMOVE\"                          : \"復原\",\n    \"MARKED_FOR_UPDATE\"                    : \"標為待更新\",\n    \"UNDO_UPDATE\"                          : \"復原\",\n    \"MARKED_FOR_DISABLING\"                 : \"標為待停用\",\n    \"UNDO_DISABLE\"                         : \"復原\",\n    \"CHANGE_AND_RELOAD_TITLE\"              : \"變更擴充功能\",\n    \"CHANGE_AND_RELOAD_MESSAGE\"            : \"要更新、移除或停用標記的擴充功能，需要重新載入 {APP_NAME}。 會再提示您儲存所做的變更。\",\n    \"REMOVE_AND_RELOAD\"                    : \"移除擴充功能並重新載入\",\n    \"CHANGE_AND_RELOAD\"                    : \"變更擴充功能並重新載入\",\n    \"UPDATE_AND_RELOAD\"                    : \"更新擴充功能並重新載入\",\n    \"DISABLE_AND_RELOAD\"                   : \"停用擴充功能並重新載入\",\n    \"PROCESSING_EXTENSIONS\"                : \"正在變更擴充功能\\u2026\",\n    \"EXTENSION_NOT_INSTALLED\"              : \"無法移除還沒安裝的擴充功能 {0}。\",\n    \"NO_EXTENSIONS\"                        : \"還沒安裝任何擴充功能。<br>請點一下上方的「可使用」頁籤開始。\",\n    \"NO_EXTENSION_MATCHES\"                 : \"找不到符合您搜尋條件的擴充功能。\",\n    \"REGISTRY_SANITY_CHECK_WARNING\"        : \"注意: 擴充功能可能是 {APP_NAME} 以外的作者提供，內容沒有經過檢閱，並且有完整的本地權限。由不明來源安裝時請小心警覺!\",\n    \"EXTENSIONS_INSTALLED_TITLE\"           : \"已安裝\",\n    \"EXTENSIONS_AVAILABLE_TITLE\"           : \"可使用\",\n    \"EXTENSIONS_THEMES_TITLE\"              : \"佈景主題\",\n    \"EXTENSIONS_UPDATES_TITLE\"             : \"更新\",\n\n    \"INLINE_EDITOR_NO_MATCHES\"             : \"找不到符合的。\",\n    \"INLINE_EDITOR_HIDDEN_MATCHES\"         : \"所有符合項目都被收合起來了。展開右側清單中的檔案檢視符合項目。\",\n    \"CSS_QUICK_EDIT_NO_MATCHES\"            : \"既有 CSS 中沒有符合您選取內容的規則。<br> 按一下「新增規則」 建立一組。\",\n    \"CSS_QUICK_EDIT_NO_STYLESHEETS\"        : \"您的專案中沒有 Stylesheet 樣式表檔案。<br>建立一個來新增 CSS 規則。\",\n\n    // Custom Viewers\n    \"IMAGE_VIEWER_LARGEST_ICON\"            : \"最大\",\n\n    /**\n     * Unit names\n     */\n    \"UNIT_PIXELS\"                          : \"像素\",\n\n    // extensions/default/DebugCommands\n    \"DEBUG_MENU\"                                : \"除錯\",\n    \"ERRORS\"                                    : \"錯誤\",\n    \"CMD_SHOW_DEV_TOOLS\"                        : \"顯示開發者工具\",\n    \"CMD_REFRESH_WINDOW\"                        : \"重新載入並啟用擴充功能\",\n    \"CMD_RELOAD_WITHOUT_USER_EXTS\"              : \"重新載入並停用擴充功能\",\n    \"CMD_NEW_BRACKETS_WINDOW\"                   : \"開新 {APP_NAME} 視窗\",\n    \"CMD_LAUNCH_SCRIPT_MAC\"                     : \"安裝命令列捷徑\",\n    \"CMD_SWITCH_LANGUAGE\"                       : \"切換語言\",\n    \"CMD_RUN_UNIT_TESTS\"                        : \"執行測試\",\n    \"CMD_SHOW_PERF_DATA\"                        : \"顯示效能資料\",\n    \"CMD_ENABLE_NODE_DEBUGGER\"                  : \"啟用 Node 除錯工具\",\n    \"CMD_LOG_NODE_STATE\"                        : \"將 Node 狀態寫到 Console\",\n    \"CMD_RESTART_NODE\"                          : \"重新啟動 Node\",\n    \"CMD_SHOW_ERRORS_IN_STATUS_BAR\"             : \"在狀態列顯示錯誤訊息\",\n    \"CMD_OPEN_BRACKETS_SOURCE\"                  : \"開啟 {APP_NAME} 原始碼\",\n\n    \"CREATING_LAUNCH_SCRIPT_TITLE\"              : \"{APP_NAME} 命令列捷徑\",\n    \"ERROR_CREATING_LAUNCH_SCRIPT\"              : \"安裝命令列捷徑時發生錯誤。請嘗試<a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments#troubleshooting'>這些疑難排解建議</a>。<br/><br/>原因: {0}\",\n    \"ERROR_CLTOOLS_RMFAILED\"                    : \"無法移除現有的 <code>/usr/local/bin/brackets</code> 符號連結。\",\n    \"ERROR_CLTOOLS_MKDIRFAILED\"                 : \"無法建立 <code>/usr/local/bin</code> 目錄。\",\n    \"ERROR_CLTOOLS_LNFAILED\"                    : \"無法建立 <code>/usr/local/bin/brackets</code> 符號連結。\",\n    \"ERROR_CLTOOLS_SERVFAILED\"                  : \"內部錯誤。\",\n    \"ERROR_CLTOOLS_NOTSUPPORTED\"                : \"在這個作業系統中無法使用命令列捷徑功能。\",\n    \"LAUNCH_SCRIPT_CREATE_SUCCESS\"              : \"成功! 現在開始您可以經由下列指令啟動 {APP_NAME}: <code>brackets myFile.txt</code> 開啟檔案，或 <code>brackets myFolder</code> 切換專案。<br/><br/><a href='https://github.com/adobe/brackets/wiki/Command-Line-Arguments'>了解更多</a> {APP_NAME} 命令列的使用方法。\",\n\n    \"LANGUAGE_TITLE\"                            : \"切換語言\",\n    \"LANGUAGE_MESSAGE\"                          : \"語言:\",\n    \"LANGUAGE_SUBMIT\"                           : \"重新載入 {APP_NAME}\",\n    \"LANGUAGE_CANCEL\"                           : \"取消\",\n    \"LANGUAGE_SYSTEM_DEFAULT\"                   : \"系統預設\",\n\n    // extensions/default/HealthData\n    \"HEALTH_DATA_NOTIFICATION\"                  : \"狀況報告喜好設定\",\n    \"HEALTH_FIRST_POPUP_TITLE\"                  : \"{APP_NAME} 狀況報告\",\n    \"HEALTH_DATA_DO_TRACK\"                      : \"匿名分享我如何使用 {APP_NAME} 的資訊\",\n    \"HEALTH_DATA_NOTIFICATION_MESSAGE\"          : \"為了讓 {APP_NAME} 更好，我們會定期將您使用 {APP_NAME} 的統計資料傳送給 Adobe，資料內容是有限且<strong>匿名</strong>的。這些資訊能幫忙區別出各項功能的重要程度、找出程式錯誤及突顯出可用性問題。<br><br>您可以在 <strong>說明 > 狀況報告</strong> 裡看到資料內容，或是設成不回報。<br><br><a href='https://github.com/adobe/brackets/wiki/Health-Data'>更進一步了解 {APP_NAME} 狀況報告</a>\",\n    \"HEALTH_DATA_PREVIEW\"                       : \"{APP_NAME} 狀況報告\",\n    \"HEALTH_DATA_PREVIEW_INTRO\"                 : \"<p>為了讓 {APP_NAME} 更好，我們會定期將您使用 {APP_NAME} 的統計資料傳送給 Adobe，資料內容是有限且<strong>匿名</strong>的。這些資訊能幫忙區別出各項功能的重要程度、找出程式錯誤及突顯出可用性問題。<a href='https://github.com/adobe/brackets/wiki/Health-Data'>更進一步了解 {APP_NAME} 狀況報告</a>以及如何在不洩露您隱私的情況下幫助 {APP_NAME} 開發社群。</p><p><strong>在您同意的前提下</strong>，下次會送出的「狀況報告」資料內容預覽如下。</p>\",\n\n    // extensions/default/InlineTimingFunctionEditor\n    \"INLINE_TIMING_EDITOR_TIME\"                 : \"時間\",\n    \"INLINE_TIMING_EDITOR_PROGRESSION\"          : \"進度\",\n    \"BEZIER_EDITOR_INFO\"                        : \"<kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> 移動選取的控制點<br><kbd class='text'>Shift</kbd> 移動 10 個單位<br><kbd class='text'>Tab</kbd> 切換控制點\",\n    \"STEPS_EDITOR_INFO\"                         : \"<kbd>↑</kbd><kbd>↓</kbd> 增加或減少 Step 數<br><kbd>←</kbd><kbd>→</kbd> 'Start' 或 'End'\",\n    \"INLINE_TIMING_EDITOR_INVALID\"              : \"原始值 <code>{0}</code> 無效，因此改以 <code>{1}</code> 函式顯示。 檔案在第一次編輯後將被更新。\",\n\n    // extensions/default/InlineColorEditor\n    \"COLOR_EDITOR_CURRENT_COLOR_SWATCH_TIP\"     : \"目前的色彩\",\n    \"COLOR_EDITOR_ORIGINAL_COLOR_SWATCH_TIP\"    : \"原來的色彩\",\n    \"COLOR_EDITOR_RGBA_BUTTON_TIP\"              : \"RGBa 格式\",\n    \"COLOR_EDITOR_HEX_BUTTON_TIP\"               : \"16 進位格式\",\n    \"COLOR_EDITOR_HSLA_BUTTON_TIP\"              : \"HSLa 格式\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_SINGULAR\"      : \"{0} (用了 {1} 次)\",\n    \"COLOR_EDITOR_USED_COLOR_TIP_PLURAL\"        : \"{0} (用了 {1} 次)\",\n\n    // extensions/default/JavaScriptCodeHints\n    \"CMD_JUMPTO_DEFINITION\"                     : \"跳到定義位置\",\n    \"CMD_SHOW_PARAMETER_HINT\"                   : \"顯示參數提示\",\n    \"NO_ARGUMENTS\"                              : \"<沒有參數>\",\n    \"DETECTED_EXCLUSION_TITLE\"                  : \"JavaScript 檔案推斷問題\",\n    \"DETECTED_EXCLUSION_INFO\"                   : \"{APP_NAME} 處理 <span class='dialog-filename'>{0}</span> 時發生問題。<br><br>這個檔案在「程式提示」、「跳到定義位置」或「快速編輯」時都不會再被處理。如果想要繼續處理這個檔案，請開啟專案中的 <code>.brackets.json</code> 檔編輯 <code>jscodehints.detectedExclusions</code> 屬性。<br><br>也有可能是 {APP_NAME} 本身的 Bug 引起的。如果可以，請您將這個檔案複製一份，並<a href='https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue'>開一張問題單</a>連結過去。\",\n\n    // extensions/default/JSLint\n    \"JSLINT_NAME\"                               : \"JSLint\",\n\n    // extensions/default/QuickView\n    \"CMD_ENABLE_QUICK_VIEW\"                     : \"游標停留時快速檢視\",\n\n    // extensions/default/RecentProjects\n    \"CMD_TOGGLE_RECENT_PROJECTS\"                : \"最近開啟的專案\",\n\n    // extensions/default/MDNDocs\n    \"DOCS_MORE_LINK\"                            : \"更多資訊\",\n\n    // extensions/default/CodeFolding\n    \"COLLAPSE_ALL\"                  : \"全部收合\",\n    \"EXPAND_ALL\"                    : \"全部展開\",\n    \"COLLAPSE_CURRENT\"              : \"收合目前區塊\",\n    \"EXPAND_CURRENT\"                : \"展開目前區塊\",\n\n    // Descriptions of core preferences\n    \"DESCRIPTION_CLOSE_BRACKETS\"                     : \"true 代表自動插入右括號\",\n    \"DESCRIPTION_CLOSE_OTHERS_ABOVE\"                 : \"false 代表由「工作檔案」內容功能表中移除「關閉上列檔案」\",\n    \"DESCRIPTION_CLOSE_OTHERS_BELOW\"                 : \"false 代表由「工作檔案」內容功能表中移除「關閉下列檔案」\",\n    \"DESCRIPTION_CLOSE_OTHERS\"                       : \"false 代表由「工作檔案」內容功能表中移除「關閉其他檔案」\",\n    \"DESCRIPTION_CLOSE_TAGS\"                         : \"設定結尾標籤自動插入選項\",\n    \"DESCRIPTION_CLOSE_TAGS_DONT_CLOSE_TAGS\"         : \"不需要自動結尾的標籤陣列\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_OPENING\"            : \"輸入啟始標籤的 > 時自動結尾\",\n    \"DESCRIPTION_CLOSE_TAGS_WHEN_CLOSING\"            : \"輸入結尾標籤的 / 時自動完成結尾\",\n    \"DESCRIPTION_CLOSE_TAGS_INDENT_TAGS\"             : \"啟始時需要空一行的標籤陣列\",\n    \"DESCRIPTION_CODE_FOLDING_ALWAY_USE_INDENT_FOLD\" : \"true 代表縮排階層變更時立即產生區塊收合標記\",\n    \"DESCRIPTION_CODE_FOLDING_ENABLED\"               : \"true 代表啟用程式區塊收合功能\",\n    \"DESCRIPTION_CODE_FOLDING_HIDE_UNTIL_MOUSEOVER\"  : \"true 代表只在滑鼠游標移動到邊欄時才顯示區塊收合標記\",\n    \"DESCRIPTION_CODE_FOLDING_MAX_FOLD_LEVEL\"        : \"「全部收合」時實際收合的階層上限\",\n    \"DESCRIPTION_CODE_FOLDING_MIN_FOLD_SIZE\"         : \"顯示區塊收合標記的最小行數\",\n    \"DESCRIPTION_CODE_FOLDING_SAVE_FOLD_STATES\"      : \"true 代表關閉再重開檔案或專案後還要記住收合狀態\",\n    \"DESCRIPTION_CODE_FOLDING_MAKE_SELECTIONS_FOLDABLE\": \"true 代表在編輯器中啟用選取區塊收合功能\",\n    \"DESCRIPTION_ATTR_HINTS\"                         : \"啟用或停用 HTML 屬性提示\",\n    \"DESCRIPTION_CSS_PROP_HINTS\"                     : \"啟用或停用 CSS/LESS/SCSS 屬性提示\",\n    \"DESCRIPTION_JS_HINTS\"                           : \"啟用或停用 JavaScript 程式碼提示\",\n    \"DESCRIPTION_PREF_HINTS\"                         : \"啟用或停用「喜好設定」程式碼提示\",\n    \"DESCRIPTION_SPECIAL_CHAR_HINTS\"                 : \"啟用或停用 HTML 實體 (Entity) 提示\",\n    \"DESCRIPTION_SVG_HINTS\"                          : \"啟用或停用 SVG 程式碼提示\",\n    \"DESCRIPTION_HTML_TAG_HINTS\"                     : \"啟用或停用 HTML 標籤提示\",\n    \"DESCRIPTION_URL_CODE_HINTS\"                     : \"啟用或停用 HTML 與 CSS/LESS/SCSS 中的 URL 提示\",\n    \"DESCRIPTION_DRAG_DROP_TEXT\"                     : \"啟用或停用「拖放功能」\",\n    \"DESCRIPTION_HEALTH_DATA_TRACKING\"               : \"啟用「狀況資料追蹤」\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES\"                  : \"啟用檔案中的其他符合字串突顯功能\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_SHOW_TOKEN\"       : \"突顯游標所在字符的所有符合字串 (不用選取)\",\n    \"DESCRIPTION_HIGHLIGHT_MATCHES_WORDS_ONLY\"       : \"只在選到完整字符時才突顯其他符合字串\",\n    \"DESCRIPTION_INSERT_HINT_ON_TAB\"                 : \"true 代表按 Tab 鍵也能插入選取的程式碼提示\",\n    \"DESCRIPTION_NO_HINTS_ON_DOT\"                    : \"true 代表輸入 . 時不要自動顯示 JS 程式碼提示\",\n    \"DESCRIPTION_JSLINT_OPTIONS\"                     : \"JSLint 預設選項值物件\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ASS\"                 : \"true 代表允許使用指派運算式\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BITWISE\"             : \"true 代表允許使用位元運算子\",\n    \"DESCRIPTION_JSLINT_OPTIONS_BROWSER\"             : \"true 代表標準瀏覽器全域變數應該事先定義\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CLOSURE\"             : \"true 代表允許使用 Google Closure 慣用語\",\n    \"DESCRIPTION_JSLINT_OPTIONS_CONTINUE\"            : \"true 代表允許使用 \\\"continue\\\" 陳述式\",\n    \"DESCRIPTION_JSLINT_OPTIONS_COUCH\"               : \"true 代表 CouchDB 全域變數應該事先定義\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEBUG\"               : \"true 代表允許使用 debugger 陳述式\",\n    \"DESCRIPTION_JSLINT_OPTIONS_DEVEL\"               : \"true 代表瀏覽器開發輔助全域應該事先定義\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EQEQ\"                : \"true 代表允許使用 == 及 !=\",\n    \"DESCRIPTION_JSLINT_OPTIONS_ES6\"                 : \"true 代表 ES6 全域變數應該事先定義\",\n    \"DESCRIPTION_JSLINT_OPTIONS_EVIL\"                : \"true 代表允許 eval\",\n    \"DESCRIPTION_JSLINT_OPTIONS_FORIN\"               : \"true 代表允許使用不過濾的 \\\"for in\\\"\",\n    \"DESCRIPTION_JSLINT_OPTIONS_INDENT\"              : \"指定 Tab 寬度\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXERR\"              : \"警告回報上限\",\n    \"DESCRIPTION_JSLINT_OPTIONS_MAXLEN\"              : \"每一行字元數上限\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NEWCAP\"              : \"true 代表允許建構式首字不用大寫\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NODE\"                : \"true 代表 Node.js 全域變數應該事先定義\",\n    \"DESCRIPTION_JSLINT_OPTIONS_NOMEN\"               : \"true 代表允許在識別名稱中使用底線 (_) 開頭或結尾\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PASSFAIL\"            : \"true 代表停在第一筆錯誤\",\n    \"DESCRIPTION_JSLINT_OPTIONS_PLUSPLUS\"            : \"true 代表允許使用 ++ 及 --\",\n    \"DESCRIPTION_JSLINT_OPTIONS_REGEXP\"              : \"true 代表允許在 RegExp 中使用 . 及 [^...].\",\n    \"DESCRIPTION_JSLINT_OPTIONS_RHINO\"               : \"true 代表 Rhino 全域變數應該事先定義\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SLOPPY\"              : \"true 代表允許不用 `use strict` 指示詞 (Pragma)\",\n    \"DESCRIPTION_JSLINT_OPTIONS_STUPID\"              : \"true 代表允許使用阻斷式 ('...Sync') 方法\",\n    \"DESCRIPTION_JSLINT_OPTIONS_SUB\"                 : \"true 代表允許使用效率較差的方括號方式存取屬性值\",\n    \"DESCRIPTION_JSLINT_OPTIONS_TODO\"                : \"true 代表允許使用 TODO 註解\",\n    \"DESCRIPTION_JSLINT_OPTIONS_UNPARAM\"             : \"true 代表允許出現沒有使用到的參數\",\n    \"DESCRIPTION_JSLINT_OPTIONS_VARS\"                : \"true 代表允許函式中出現兩個以上的 var\",\n    \"DESCRIPTION_JSLINT_OPTIONS_WHITE\"               : \"true 代表要忽略空格規則\",\n    \"DESCRIPTION_LANGUAGE\"                           : \"語言相關設定\",\n    \"DESCRIPTION_LANGUAGE_FILE_EXTENSIONS\"           : \"副檔與程式語言名稱的額外對應\",\n    \"DESCRIPTION_LANGUAGE_FILE_NAMES\"                : \"檔名與程式語言名稱的額外對應\",\n    \"DESCRIPTION_LINTING_ENABLED\"                    : \"true 代表啟用「程式碼檢查」\",\n    \"DESCRIPTION_ASYNC_TIMEOUT\"                      : \"非同步檢查程式的執行時間上限亳秒數\",\n    \"DESCRIPTION_LINTING_PREFER\"                     : \"優先執行的檢查程式陣列\",\n    \"DESCRIPTION_LIVE_DEV_MULTIBROWSER\"              : \"true 代表啟用實驗版「即時預覽」\",\n    \"DESCRIPTION_USE_PREFERED_ONLY\"                  : \"true 代表只執行 linting.prefer 中指定的提供者\",\n    \"DESCRIPTION_MAX_CODE_HINTS\"                     : \"同時顯示的程式碼提示數目上限\",\n    \"DESCRIPTION_PATH\"                               : \"路徑相關設定\",\n    \"DESCRIPTION_PROXY\"                              : \"用來安裝擴充功能的 Proxy 伺服器 URL\",\n    \"DESCRIPTION_SCROLL_PAST_END\"                    : \"true 代表允許捲動到檔案結尾之後\",\n    \"DESCRIPTION_SHOW_CODE_HINTS\"                    : \"false 代表停用所有的程式碼提示\",\n    \"DESCRIPTION_SHOW_CURSOR_WHEN_SELECTING\"         : \"選取文字時還是要顯示閃動的游標\",\n    \"DESCRIPTION_SHOW_LINE_NUMBERS\"                  : \"true 代表在程式碼左方「邊欄」中顯示行號\",\n    \"DESCRIPTION_SMART_INDENT\"                       : \"建立新區塊時自動縮排\",\n    \"DESCRIPTION_SOFT_TABS\"                          : \"false 代表停用軟體 Tab 功能\",\n    \"DESCRIPTION_SORT_DIRECTORIES_FIRST\"             : \"true 代表在專案樹中將目錄排在上面\",\n    \"DESCRIPTION_SPACE_UNITS\"                        : \"以空格縮排時一階的空格數\",\n    \"DESCRIPTION_STATIC_SERVER_PORT\"                 : \"供「即時預覽」內建伺服器使用的通訊埠號\",\n    \"DESCRIPTION_STYLE_ACTIVE_LINE\"                  : \"true 代表使用背景色突顯出游標所在行\",\n    \"DESCRIPTION_TAB_SIZE\"                           : \"顯示一個 Tab 所需的空格數\",\n    \"DESCRIPTION_USE_TAB_CHAR\"                       : \"true 代表使用 Tab 取代空格\",\n    \"DESCRIPTION_UPPERCASE_COLORS\"                   : \"true 代表在「就地色彩編輯器」中產出 16 進位色彩值時使用大寫\",\n    \"DESCRIPTION_WORD_WRAP\"                          : \"超過檢視區寛度時自動換行\",\n    \"DESCRIPTION_DETECTED_EXCLUSIONS\"                : \"偵測出會讓 Tern 失控的檔案清單\",\n    \"DESCRIPTION_INFERENCE_TIMEOUT\"                  : \"Tern 檔案內容分析時間上限毫秒數\",\n    \"DESCRIPTION_SHOW_ERRORS_IN_STATUS_BAR\"          : \"true 代表在狀態列顯示錯誤\",\n    \"DESCRIPTION_QUICK_VIEW_ENABLED\"                 : \"true 代表啟用「快速檢視」\",\n    \"DESCRIPTION_EXTENSION_LESS_IMAGE_PREVIEW\"       : \"true 代表對沒有副檔名的 URL 顯示圖片預覽\",\n    \"DESCRIPTION_THEME\"                              : \"選用 {APP_NAME} 佈景主題\",\n    \"DESCRIPTION_USE_THEME_SCROLLBARS\"               : \"true 代表允許自訂捲軸\",\n    \"DESCRIPTION_LINTING_COLLAPSED\"                  : \"true 代表收合檢查面板\",\n    \"DESCRIPTION_FONT_FAMILY\"                        : \"變更字族 (Font Family)\",\n    \"DESCRIPTION_FONT_SIZE\"                          : \"變更字體大小，例如: 13px\",\n    \"DESCRIPTION_FIND_IN_FILES_NODE\"                 : \"true 代表啟用節點搜尋\",\n    \"DESCRIPTION_FIND_IN_FILES_INSTANT\"              : \"true 代表啟用立即搜尋\",\n    \"DESCRIPTION_FONT_SMOOTHING\"                     : \"只適用 Mac: \\\"subpixel-antialiased\\\" 代表啟用子像素鋸齒消除模式，或是設成 \\\"antialiased\\\" 使用灰階鋸齒消除模式。\",\n    \"DESCRIPTION_OPEN_PREFS_IN_SPLIT_VIEW\"           : \"false 代表不要使用分割窗格開啟喜好設定檔\",\n    \"DESCRIPTION_OPEN_USER_PREFS_IN_SECOND_PANE\"     : \"false 代表在左窗格或上窗格開啟使用者喜好設定檔\",\n    \"DEFAULT_PREFERENCES_JSON_HEADER_COMMENT\"        : \"/*\\n * 這是 {APP_NAME} 支援的喜好設定值，內容是唯讀的，請勿直接修改。\\n * 供您參考並請修改開在另一個窗格的 \\\"brackets.json\\\" 個人喜好設定檔。\\n * 如果想更了解 {APP_NAME} 喜好設定，請參考網頁 https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#preferences\\n */\",\n    \"DEFAULT_PREFERENCES_JSON_DEFAULT\"               : \"預設\"\n});\n\n/* Last translated for 1eba0ae1cb21e73752c8359132b972ec7e5997ab */\n"
  },
  {
    "path": "src/nls/zh-tw/urls.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine({\n    // Relative to the samples folder\n    \"GETTING_STARTED\"           : \"zh-tw/Getting Started\",\n    \"ADOBE_THIRD_PARTY\"         : \"http://www.adobe.com/go/thirdparty_tw/\",\n    \"MDN_DOCS_LICENSE\"          : \"http://creativecommons.org/licenses/by-sa/2.5/deed.zh_TW\"\n});\n"
  },
  {
    "path": "src/npm-shrinkwrap.json",
    "content": "{\n  \"name\": \"brackets-src\",\n  \"dependencies\": {\n    \"acorn\": {\n      \"version\": \"5.1.1\",\n      \"from\": \"acorn@5.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz\"\n    },\n    \"ajv\": {\n      \"version\": \"4.11.8\",\n      \"from\": \"ajv@>=4.9.1 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz\",\n      \"optional\": true\n    },\n    \"asap\": {\n      \"version\": \"2.0.6\",\n      \"from\": \"asap@>=2.0.3 <2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/asap/-/asap-2.0.6.tgz\",\n      \"optional\": true\n    },\n    \"asn1\": {\n      \"version\": \"0.2.3\",\n      \"from\": \"asn1@>=0.2.3 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz\",\n      \"optional\": true\n    },\n    \"assert-plus\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"assert-plus@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz\",\n      \"optional\": true\n    },\n    \"asynckit\": {\n      \"version\": \"0.4.0\",\n      \"from\": \"asynckit@>=0.4.0 <0.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\",\n      \"optional\": true\n    },\n    \"aws-sign2\": {\n      \"version\": \"0.6.0\",\n      \"from\": \"aws-sign2@>=0.6.0 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz\",\n      \"optional\": true\n    },\n    \"aws4\": {\n      \"version\": \"1.6.0\",\n      \"from\": \"aws4@>=1.2.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz\",\n      \"optional\": true\n    },\n    \"bcrypt-pbkdf\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"bcrypt-pbkdf@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz\",\n      \"optional\": true\n    },\n    \"boom\": {\n      \"version\": \"2.10.1\",\n      \"from\": \"boom@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/boom/-/boom-2.10.1.tgz\"\n    },\n    \"caseless\": {\n      \"version\": \"0.12.0\",\n      \"from\": \"caseless@>=0.12.0 <0.13.0\",\n      \"resolved\": \"https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz\",\n      \"optional\": true\n    },\n    \"co\": {\n      \"version\": \"4.6.0\",\n      \"from\": \"co@>=4.6.0 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/co/-/co-4.6.0.tgz\",\n      \"optional\": true\n    },\n    \"codemirror\": {\n      \"version\": \"5.30.0\",\n      \"from\": \"codemirror@5.30.0\",\n      \"resolved\": \"https://registry.npmjs.org/codemirror/-/codemirror-5.30.0.tgz\"\n    },\n    \"combined-stream\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"combined-stream@>=1.0.5 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz\"\n    },\n    \"core-util-is\": {\n      \"version\": \"1.0.2\",\n      \"from\": \"core-util-is@1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz\",\n      \"optional\": true\n    },\n    \"cryptiles\": {\n      \"version\": \"2.0.5\",\n      \"from\": \"cryptiles@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz\",\n      \"optional\": true\n    },\n    \"dashdash\": {\n      \"version\": \"1.14.1\",\n      \"from\": \"dashdash@>=1.12.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"optional\": true\n        }\n      }\n    },\n    \"delayed-stream\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"delayed-stream@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\"\n    },\n    \"ecc-jsbn\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"ecc-jsbn@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz\",\n      \"optional\": true\n    },\n    \"errno\": {\n      \"version\": \"0.1.4\",\n      \"from\": \"errno@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/errno/-/errno-0.1.4.tgz\",\n      \"optional\": true\n    },\n    \"extend\": {\n      \"version\": \"3.0.1\",\n      \"from\": \"extend@>=3.0.0 <3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/extend/-/extend-3.0.1.tgz\",\n      \"optional\": true\n    },\n    \"extsprintf\": {\n      \"version\": \"1.3.0\",\n      \"from\": \"extsprintf@1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz\"\n    },\n    \"forever-agent\": {\n      \"version\": \"0.6.1\",\n      \"from\": \"forever-agent@>=0.6.1 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz\",\n      \"optional\": true\n    },\n    \"form-data\": {\n      \"version\": \"2.1.4\",\n      \"from\": \"form-data@>=2.1.1 <2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz\",\n      \"optional\": true\n    },\n    \"getpass\": {\n      \"version\": \"0.1.7\",\n      \"from\": \"getpass@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"optional\": true\n        }\n      }\n    },\n    \"graceful-fs\": {\n      \"version\": \"4.1.11\",\n      \"from\": \"graceful-fs@>=4.1.2 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz\",\n      \"optional\": true\n    },\n    \"har-schema\": {\n      \"version\": \"1.0.5\",\n      \"from\": \"har-schema@>=1.0.5 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz\",\n      \"optional\": true\n    },\n    \"har-validator\": {\n      \"version\": \"4.2.1\",\n      \"from\": \"har-validator@>=4.2.1 <4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz\",\n      \"optional\": true\n    },\n    \"hawk\": {\n      \"version\": \"3.1.3\",\n      \"from\": \"hawk@>=3.1.3 <3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz\",\n      \"optional\": true\n    },\n    \"hoek\": {\n      \"version\": \"2.16.3\",\n      \"from\": \"hoek@>=2.0.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz\"\n    },\n    \"http-signature\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"http-signature@>=1.1.0 <1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz\",\n      \"optional\": true\n    },\n    \"image-size\": {\n      \"version\": \"0.5.5\",\n      \"from\": \"image-size@>=0.5.0 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz\",\n      \"optional\": true\n    },\n    \"immutability-helper\": {\n      \"version\": \"2.3.1\",\n      \"from\": \"immutability-helper@>=2.1.2 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.3.1.tgz\"\n    },\n    \"invariant\": {\n      \"version\": \"2.2.2\",\n      \"from\": \"invariant@>=2.2.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz\"\n    },\n    \"is-typedarray\": {\n      \"version\": \"1.0.0\",\n      \"from\": \"is-typedarray@>=1.0.0 <1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz\",\n      \"optional\": true\n    },\n    \"isstream\": {\n      \"version\": \"0.1.2\",\n      \"from\": \"isstream@>=0.1.2 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz\",\n      \"optional\": true\n    },\n    \"js-tokens\": {\n      \"version\": \"3.0.2\",\n      \"from\": \"js-tokens@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz\"\n    },\n    \"jsbn\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"jsbn@>=0.1.0 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz\",\n      \"optional\": true\n    },\n    \"json-schema\": {\n      \"version\": \"0.2.3\",\n      \"from\": \"json-schema@0.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz\",\n      \"optional\": true\n    },\n    \"json-stable-stringify\": {\n      \"version\": \"1.0.1\",\n      \"from\": \"json-stable-stringify@>=1.0.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz\",\n      \"optional\": true\n    },\n    \"json-stringify-safe\": {\n      \"version\": \"5.0.1\",\n      \"from\": \"json-stringify-safe@>=5.0.1 <5.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz\",\n      \"optional\": true\n    },\n    \"jsonify\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"jsonify@>=0.0.0 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz\",\n      \"optional\": true\n    },\n    \"jsprim\": {\n      \"version\": \"1.4.1\",\n      \"from\": \"jsprim@>=1.2.2 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@1.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"optional\": true\n        }\n      }\n    },\n    \"less\": {\n      \"version\": \"2.7.2\",\n      \"from\": \"less@2.7.2\",\n      \"resolved\": \"https://registry.npmjs.org/less/-/less-2.7.2.tgz\"\n    },\n    \"loose-envify\": {\n      \"version\": \"1.3.1\",\n      \"from\": \"loose-envify@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz\"\n    },\n    \"mime\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"mime@>=1.2.11 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime/-/mime-1.4.0.tgz\",\n      \"optional\": true\n    },\n    \"mime-db\": {\n      \"version\": \"1.29.0\",\n      \"from\": \"mime-db@>=1.29.0 <1.30.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz\"\n    },\n    \"mime-types\": {\n      \"version\": \"2.1.16\",\n      \"from\": \"mime-types@>=2.1.7 <2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz\"\n    },\n    \"minimist\": {\n      \"version\": \"0.0.8\",\n      \"from\": \"minimist@0.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\",\n      \"optional\": true\n    },\n    \"mkdirp\": {\n      \"version\": \"0.5.1\",\n      \"from\": \"mkdirp@>=0.5.0 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n      \"optional\": true\n    },\n    \"oauth-sign\": {\n      \"version\": \"0.8.2\",\n      \"from\": \"oauth-sign@>=0.8.1 <0.9.0\",\n      \"resolved\": \"https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz\",\n      \"optional\": true\n    },\n    \"performance-now\": {\n      \"version\": \"0.2.0\",\n      \"from\": \"performance-now@>=0.2.0 <0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz\",\n      \"optional\": true\n    },\n    \"preact\": {\n      \"version\": \"8.2.1\",\n      \"from\": \"preact@8.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/preact/-/preact-8.2.1.tgz\"\n    },\n    \"preact-compat\": {\n      \"version\": \"3.17.0\",\n      \"from\": \"adobe/preact-compat\",\n      \"resolved\": \"git+https://github.com/adobe/preact-compat.git#a2a7274e9655535c967429af9de825e6978f3290\"\n    },\n    \"preact-render-to-string\": {\n      \"version\": \"3.6.3\",\n      \"from\": \"preact-render-to-string@>=3.6.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-3.6.3.tgz\"\n    },\n    \"preact-test-utils\": {\n      \"version\": \"0.1.3\",\n      \"from\": \"preact-test-utils@0.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/preact-test-utils/-/preact-test-utils-0.1.3.tgz\"\n    },\n    \"preact-transition-group\": {\n      \"version\": \"1.1.1\",\n      \"from\": \"preact-transition-group@>=1.1.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/preact-transition-group/-/preact-transition-group-1.1.1.tgz\"\n    },\n    \"pretty-format\": {\n      \"version\": \"3.8.0\",\n      \"from\": \"pretty-format@>=3.5.1 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz\"\n    },\n    \"promise\": {\n      \"version\": \"7.3.1\",\n      \"from\": \"promise@>=7.1.1 <8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/promise/-/promise-7.3.1.tgz\",\n      \"optional\": true\n    },\n    \"prr\": {\n      \"version\": \"0.0.0\",\n      \"from\": \"prr@>=0.0.0 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/prr/-/prr-0.0.0.tgz\",\n      \"optional\": true\n    },\n    \"punycode\": {\n      \"version\": \"1.4.1\",\n      \"from\": \"punycode@>=1.4.1 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz\",\n      \"optional\": true\n    },\n    \"qs\": {\n      \"version\": \"6.4.0\",\n      \"from\": \"qs@>=6.4.0 <6.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/qs/-/qs-6.4.0.tgz\",\n      \"optional\": true\n    },\n    \"request\": {\n      \"version\": \"2.81.0\",\n      \"from\": \"request@>=2.72.0 <3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/request/-/request-2.81.0.tgz\",\n      \"optional\": true\n    },\n    \"safe-buffer\": {\n      \"version\": \"5.1.1\",\n      \"from\": \"safe-buffer@>=5.0.1 <6.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz\"\n    },\n    \"simulate-event\": {\n      \"version\": \"1.4.0\",\n      \"from\": \"simulate-event@>=1.4.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/simulate-event/-/simulate-event-1.4.0.tgz\"\n    },\n    \"sntp\": {\n      \"version\": \"1.0.9\",\n      \"from\": \"sntp@>=1.0.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz\",\n      \"optional\": true\n    },\n    \"source-map\": {\n      \"version\": \"0.5.7\",\n      \"from\": \"source-map@>=0.5.3 <0.6.0\",\n      \"resolved\": \"https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz\",\n      \"optional\": true\n    },\n    \"sshpk\": {\n      \"version\": \"1.13.1\",\n      \"from\": \"sshpk@>=1.7.0 <2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"optional\": true\n        }\n      }\n    },\n    \"standalone-react-addons-pure-render-mixin\": {\n      \"version\": \"0.1.1\",\n      \"from\": \"standalone-react-addons-pure-render-mixin@>=0.1.1 <0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/standalone-react-addons-pure-render-mixin/-/standalone-react-addons-pure-render-mixin-0.1.1.tgz\"\n    },\n    \"stringstream\": {\n      \"version\": \"0.0.5\",\n      \"from\": \"stringstream@>=0.0.4 <0.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz\",\n      \"optional\": true\n    },\n    \"tough-cookie\": {\n      \"version\": \"2.3.2\",\n      \"from\": \"tough-cookie@>=2.3.0 <2.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz\",\n      \"optional\": true\n    },\n    \"tunnel-agent\": {\n      \"version\": \"0.6.0\",\n      \"from\": \"tunnel-agent@>=0.6.0 <0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz\",\n      \"optional\": true\n    },\n    \"tweetnacl\": {\n      \"version\": \"0.14.5\",\n      \"from\": \"tweetnacl@>=0.14.0 <0.15.0\",\n      \"resolved\": \"https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz\",\n      \"optional\": true\n    },\n    \"uuid\": {\n      \"version\": \"3.1.0\",\n      \"from\": \"uuid@>=3.0.0 <4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz\",\n      \"optional\": true\n    },\n    \"verror\": {\n      \"version\": \"1.10.0\",\n      \"from\": \"verror@1.10.0\",\n      \"resolved\": \"https://registry.npmjs.org/verror/-/verror-1.10.0.tgz\",\n      \"optional\": true,\n      \"dependencies\": {\n        \"assert-plus\": {\n          \"version\": \"1.0.0\",\n          \"from\": \"assert-plus@>=1.0.0 <2.0.0\",\n          \"resolved\": \"https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz\",\n          \"optional\": true\n        }\n      }\n    },\n    \"xtend\": {\n      \"version\": \"4.0.1\",\n      \"from\": \"xtend@>=4.0.1 <5.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/package.json",
    "content": "{\n  \"name\": \"brackets-src\",\n  \"dependencies\": {\n    \"acorn\": \"5.1.1\",\n    \"codemirror\": \"5.30.0\",\n    \"less\": \"2.7.2\",\n    \"preact\": \"8.2.1\",\n    \"preact-test-utils\": \"0.1.3\",\n    \"preact-compat\": \"adobe/preact-compat\"\n  }\n}\n"
  },
  {
    "path": "src/preferences/PreferencesBase.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global appshell */\n/*unittests: Preferences Base */\n\n/**\n * Infrastructure for the preferences system.\n *\n * At the top, the level at which most people will interact, is the `PreferencesSystem` object.\n * The most common operation is `get(id)`, which simply retrieves the value of a given preference.\n *\n * The PreferencesSystem has a collection of Scopes, which it traverses in a specified order.\n * Each Scope holds one level of settings.\n *\n * PreferencesManager.js sets up a singleton PreferencesSystem that has the following Scopes:\n *\n * * default (the default values for any settings that are explicitly registered)\n * * user (the user's customized settings – the equivalent of Brackets' old\n *   localStorage-based system. This is the settings file that lives in AppData)\n * * Additional scopes for each .brackets.json file going upward in the file tree from the\n *   current file\n *\n * For example, if spaceUnits has a value set in a .brackets.json file near the open file,\n * then a call to get(\"spaceUnits\") would return the value from that file. File values come\n * first, user values next, default values last. If the setting is not known\n * at all, undefined is returned.\n *\n * Each Scope has an associated Storage object that knows how to load and\n * save the preferences value for that Scope. There are two implementations:\n * MemoryStorage and FileStorage.\n *\n * The final concept used is that of Layers, which can be added to Scopes. Generally, a Layer looks\n * for a collection of preferences that are nested in some fashion in the Scope's\n * data. Under certain circumstances (decided upon by the Layer object),\n * those nested preferences will take precedence over the main preferences in the Scope.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils       = require(\"file/FileUtils\"),\n        FileSystem      = require(\"filesystem/FileSystem\"),\n        FileSystemError = require(\"filesystem/FileSystemError\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        _               = require(\"thirdparty/lodash\"),\n        Async           = require(\"utils/Async\"),\n        globmatch       = require(\"thirdparty/globmatch\");\n\n    // CONSTANTS\n    var PREFERENCE_CHANGE = \"change\",\n        SCOPEORDER_CHANGE = \"scopeOrderChange\";\n\n    /*\n     * Storages manage the loading and saving of preference data.\n     */\n\n    /**\n     * MemoryStorage, as the name implies, stores the preferences in memory.\n     * This is suitable for single session data or testing.\n     *\n     * @constructor\n     * @param {?Object} data Initial data for the storage.\n     */\n    function MemoryStorage(data) {\n        this.data = data || {};\n    }\n\n    MemoryStorage.prototype = {\n\n        /**\n         * *Synchronously* returns the data stored in this storage.\n         * The original object (not a clone) is returned.\n         *\n         * @return {Promise} promise that is already resolved\n         */\n        load: function () {\n            var result = new $.Deferred();\n            result.resolve(this.data);\n            return result.promise();\n        },\n\n        /**\n         * *Synchronously* saves the data to this storage. This saves\n         * the `newData` object reference without cloning it.\n         *\n         * @param {Object} newData The data to store.\n         * @return {Promise} promise that is already resolved\n         */\n        save: function (newData) {\n            var result = new $.Deferred();\n            this.data = newData;\n            result.resolve();\n            return result.promise();\n        },\n\n        /**\n         * MemoryStorage is not stored in a file, so fileChanged is ignored.\n         *\n         * @param {string} filePath File that has changed\n         */\n        fileChanged: function (filePath) {\n        }\n    };\n\n    // MemoryStorage never actually dispatches change events, but Storage interface requires implementing on()/off()\n    EventDispatcher.makeEventDispatcher(MemoryStorage.prototype);\n\n\n    /**\n     * Error type for problems parsing preference files.\n     *\n     * @constructor\n     * @param {string} message Error message\n     */\n    function ParsingError(message) {\n        this.name = \"ParsingError\";\n        this.message = message || \"\";\n    }\n\n    ParsingError.prototype = new Error();\n\n\n    /**\n     * Loads/saves preferences from a JSON file on disk.\n     *\n     * @constructor\n     * @param {string}  path        Path to the preferences file\n     * @param {boolean} createIfMissing True if the file should be created if it doesn't exist.\n     *                              If this is not true, an exception will be thrown if the\n     *                              file does not exist.\n     * @param {boolean} recreateIfInvalid True if the file needs to be recreated if it is invalid.\n     *                              Invalid- Either unreadable or unparseable.\n     *                              The invalid copy will be sent to trash in case the user wants to refer to it.\n     */\n    function FileStorage(path, createIfMissing, recreateIfInvalid) {\n        this.path = path;\n        this.createIfMissing = createIfMissing;\n        this.recreateIfInvalid = recreateIfInvalid;\n        this._lineEndings = FileUtils.getPlatformLineEndings();\n    }\n\n    FileStorage.prototype = {\n\n        /**\n         * Loads the preferences from disk. Can throw an exception if the file is not\n         * readable or parseable.\n         *\n         * @return {Promise} Resolved with the data once it has been parsed.\n         */\n        load: function () {\n            var result = new $.Deferred();\n            var path = this.path;\n            var createIfMissing = this.createIfMissing;\n            var recreateIfInvalid = this.recreateIfInvalid;\n            var self = this;\n\n            if (path) {\n                var prefFile = FileSystem.getFileForPath(path);\n                prefFile.read({}, function (err, text) {\n                    if (err) {\n                        if (createIfMissing) {\n                            // Unreadable file is also unwritable -- delete so get recreated\n                            if (recreateIfInvalid && (err === FileSystemError.NOT_READABLE || err === FileSystemError.UNSUPPORTED_ENCODING)) {\n                                appshell.fs.moveToTrash(path, function (err) {\n                                    if (err) {\n                                        console.log(\"Cannot move unreadable preferences file \" + path + \" to trash!!\");\n                                    } else {\n                                        console.log(\"Brackets has recreated the unreadable preferences file \" + path + \". You may refer to the deleted file in trash in case you need it!!\");\n                                    }\n                                }.bind(this));\n                            }\n                            result.resolve({});\n                        } else {\n                            result.reject(new Error(\"Unable to load preferences at \" + path + \" \" + err));\n                        }\n                        return;\n                    }\n\n                    self._lineEndings = FileUtils.sniffLineEndings(text);\n\n                    // If the file is empty, turn it into an empty object\n                    if (/^\\s*$/.test(text)) {\n                        result.resolve({});\n                    } else {\n                        try {\n                            result.resolve(JSON.parse(text));\n                        } catch (e) {\n                            if (recreateIfInvalid) {\n                                // JSON parsing error -- recreate the preferences file\n                                appshell.fs.moveToTrash(path, function (err) {\n                                    if (err) {\n                                        console.log(\"Cannot move unparseable preferences file \" + path + \" to trash!!\");\n                                    } else {\n                                        console.log(\"Brackets has recreated the Invalid JSON preferences file \" + path + \". You may refer to the deleted file in trash in case you need it!!\");\n                                    }\n                                }.bind(this));\n                                result.resolve({});\n                            } else {\n                                result.reject(new ParsingError(\"Invalid JSON settings at \" + path + \"(\" + e.toString() + \")\"));\n                            }\n                        }\n                    }\n                });\n            } else {\n                result.resolve({});\n            }\n\n            return result.promise();\n        },\n\n        /**\n         * Saves the new data to disk.\n         *\n         * @param {Object} newData data to save\n         * @return {Promise} Promise resolved (with no arguments) once the data has been saved\n         */\n        save: function (newData) {\n            var result = new $.Deferred();\n            var path = this.path;\n            var prefFile = FileSystem.getFileForPath(path);\n\n            if (path) {\n                try {\n                    var text = JSON.stringify(newData, null, 4);\n\n                    // maintain the original line endings\n                    text = FileUtils.translateLineEndings(text, this._lineEndings);\n                    prefFile.write(text, {}, function (err) {\n                        if (err) {\n                            result.reject(\"Unable to save prefs at \" + path + \" \" + err);\n                        } else {\n                            result.resolve();\n                        }\n                    });\n                } catch (e) {\n                    result.reject(\"Unable to convert prefs to JSON\" + e.toString());\n                }\n            } else {\n                result.resolve();\n            }\n            return result.promise();\n        },\n\n        /**\n         * Changes the path to the preferences file.\n         * This sends a \"changed\" event to listeners, regardless of whether\n         * the path has changed.\n         *\n         * @param {string} newPath location of this settings file\n         */\n        setPath: function (newPath) {\n            this.path = newPath;\n            this.trigger(\"changed\");\n        },\n\n        /**\n         * If the filename matches this Storage's path, a changed message is triggered.\n         *\n         * @param {string} filePath File that has changed\n         */\n        fileChanged: function (filePath) {\n            if (filePath === this.path) {\n                this.trigger(\"changed\");\n            }\n        }\n    };\n\n    EventDispatcher.makeEventDispatcher(FileStorage.prototype);\n\n\n    /**\n     * A `Scope` is a data container that is tied to a `Storage`.\n     *\n     * Additionally, `Scope`s support \"layers\" which are additional levels of preferences\n     * that are stored within a single preferences file.\n     *\n     * @constructor\n     * @param {Storage} storage Storage object from which prefs are loaded/saved\n     */\n    function Scope(storage) {\n        this.storage = storage;\n        storage.on(\"changed\", this.load.bind(this));\n        this.data = {};\n        this._dirty = false;\n        this._layers = [];\n        this._layerMap = {};\n        this._exclusions = [];\n    }\n\n    _.extend(Scope.prototype, {\n        /**\n         * Loads the prefs for this `Scope` from the `Storage`.\n         *\n         * @return {Promise} Promise that is resolved once loading is complete\n         */\n        load: function () {\n            var result = new $.Deferred();\n            this.storage.load()\n                .then(function (data) {\n                    var oldKeys = this.getKeys();\n                    this.data = data;\n                    result.resolve();\n                    this.trigger(PREFERENCE_CHANGE, {\n                        ids: _.union(this.getKeys(), oldKeys)\n                    });\n                }.bind(this))\n                .fail(function (error) {\n                    result.reject(error);\n                });\n            return result.promise();\n        },\n\n        /**\n         * Saves the prefs for this `Scope`.\n         *\n         * @return {Promise} promise resolved once the data is saved.\n         */\n        save: function () {\n            var self = this;\n            if (this._dirty) {\n                self._dirty = false;\n                return this.storage.save(this.data);\n            } else {\n                return (new $.Deferred()).resolve().promise();\n            }\n        },\n\n        /**\n         * Sets the value for `id`. The value is set at the location given, or at the current\n         * location for the preference if no location is specified. If an invalid location is\n         * given, nothing will be set and no exception is thrown.\n         *\n         * @param {string} id Key to set\n         * @param {*} value Value for this key\n         * @param {Object=} context Optional additional information about the request (typically used for layers)\n         * @param {{layer: ?string, layerID: ?Object}=} location Optional location in which to set the value.\n         *                                                      If the object is empty, the value will be\n         *                                                      set at the Scope's base level.\n         * @return {boolean} true if the value was set\n         */\n        set: function (id, value, context, location) {\n            if (!location) {\n                location = this.getPreferenceLocation(id, context);\n            }\n            if (location && location.layer) {\n                var layer = this._layerMap[location.layer];\n                if (layer) {\n                    if (this.data[layer.key] === undefined) {\n                        this.data[layer.key] = {};\n                    }\n\n                    var wasSet = layer.set(this.data[layer.key], id, value, context, location.layerID);\n                    this._dirty = this._dirty || wasSet;\n                    return wasSet;\n                } else {\n                    return false;\n                }\n            } else {\n                return this._performSet(id, value);\n            }\n        },\n\n        /**\n         * @private\n         *\n         * Performs the set operation on this Scope's data, deleting the given ID if\n         * the new value is undefined. The dirty flag will be set as well.\n         *\n         * @param {string} id key to set or delete\n         * @param {*} value value for this key (undefined to delete)\n         * @return {boolean} true if the value was set.\n         */\n        _performSet: function (id, value) {\n            if (!_.isEqual(this.data[id], value)) {\n                this._dirty = true;\n                if (value === undefined) {\n                    delete this.data[id];\n                } else {\n                    this.data[id] = _.cloneDeep(value);\n                }\n                return true;\n            }\n            return false;\n        },\n\n        /**\n         * Get the value for id, given the context. The context is provided to layers\n         * which may override the value from the main data of the Scope. Note that\n         * layers will often exclude values from consideration.\n         *\n         * @param {string} id Preference to retrieve\n         * @param {?Object} context Optional additional information about the request\n         * @return {*} Current value of the Preference\n         */\n        get: function (id, context) {\n            var layerCounter,\n                layers = this._layers,\n                layer,\n                data = this.data,\n                result;\n\n            context = context || {};\n\n            for (layerCounter = 0; layerCounter < layers.length; layerCounter++) {\n                layer = layers[layerCounter];\n                result = layer.get(data[layer.key], id, context);\n                if (result !== undefined) {\n                    return result;\n                }\n            }\n\n            if (this._exclusions.indexOf(id) === -1) {\n                return data[id];\n            }\n        },\n\n        /**\n         * Get the location in this Scope (if any) where the given preference is set.\n         *\n         * @param {string} id Name of the preference for which the value should be retrieved\n         * @param {Object=} context Optional context object to change the preference lookup\n         * @return {{layer: ?string, layerID: ?object}|undefined} Object describing where the preferences came from.\n         *                                              An empty object means that it was defined in the Scope's\n         *                                              base data. Undefined means the pref is not\n         *                                              defined in this Scope.\n         */\n        getPreferenceLocation: function (id, context) {\n            var layerCounter,\n                layers = this._layers,\n                layer,\n                data = this.data,\n                result;\n\n            context = context || {};\n\n            for (layerCounter = 0; layerCounter < layers.length; layerCounter++) {\n                layer = layers[layerCounter];\n                result = layer.getPreferenceLocation(data[layer.key], id, context);\n                if (result !== undefined) {\n                    return {\n                        layer: layer.key,\n                        layerID: result\n                    };\n                }\n            }\n\n            if (this._exclusions.indexOf(id) === -1 && data[id] !== undefined) {\n                // The value is defined in this Scope, which means we need to return an\n                // empty object as a signal to the PreferencesSystem that this pref\n                // is defined in this Scope (in the base data)\n                return {};\n            }\n\n            // return undefined when this Scope does not have the requested pref\n            return undefined;\n        },\n\n        /**\n         * Get the preference IDs that are set in this Scope. All layers are added\n         * in. If context is not provided, the set of all keys in the Scope including\n         * all keys in each layer will be returned.\n         *\n         * @param {?Object} context Optional additional information for looking up the keys\n         * @return {Array.<string>} Set of preferences set by this Scope\n         */\n        getKeys: function (context) {\n            context = context || {};\n\n            var layerCounter,\n                layers = this._layers,\n                layer,\n                data = this.data;\n\n            var keySets = [_.difference(_.keys(data), this._exclusions)];\n            for (layerCounter = 0; layerCounter < layers.length; layerCounter++) {\n                layer = layers[layerCounter];\n                keySets.push(layer.getKeys(data[layer.key], context));\n            }\n\n            return _.union.apply(null, keySets);\n        },\n\n        /**\n         * Adds a Layer to this Scope. The Layer object should define a `key`, which\n         * represents the subset of the preference data that the Layer works with.\n         * Layers should also define `get` and `getKeys` operations that are like their\n         * counterparts in Scope but take \"data\" as the first argument.\n         *\n         * Listeners are notified of potential changes in preferences with the addition of\n         * this layer.\n         *\n         * @param {Layer} layer Layer object to add to this Scope\n         */\n        addLayer: function (layer) {\n            this._layers.push(layer);\n            this._layerMap[layer.key] = layer;\n            this._exclusions.push(layer.key);\n            this.trigger(PREFERENCE_CHANGE, {\n                ids: layer.getKeys(this.data[layer.key], {})\n            });\n        },\n\n        /**\n         * Tells the Scope that the given file has been changed so that the\n         * Storage can be reloaded if needed.\n         *\n         * @param {string} filePath File that has changed\n         */\n        fileChanged: function (filePath) {\n            this.storage.fileChanged(filePath);\n        },\n\n        /**\n         * Determines if there are likely to be any changes based on the change\n         * of context.\n         *\n         * @param {{path: string, language: string}} oldContext Old context\n         * @param {{path: string, language: string}} newContext New context\n         * @return {Array.<string>} List of changed IDs\n         */\n        contextChanged: function (oldContext, newContext) {\n            var changes = [],\n                data    = this.data;\n\n            _.each(this._layers, function (layer) {\n                if (data[layer.key] && oldContext[layer.key] !== newContext[layer.key]) {\n                    var changesInLayer = layer.contextChanged(data[layer.key],\n                                                              oldContext,\n                                                              newContext);\n                    if (changesInLayer) {\n                        changes.push(changesInLayer);\n                    }\n                }\n            });\n            return _.union.apply(null, changes);\n        }\n    });\n\n    EventDispatcher.makeEventDispatcher(Scope.prototype);\n\n\n    // Utility functions for the PathLayer\n\n    /**\n     * @private\n     *\n     * Look for a matching file glob among the collection of paths.\n     *\n     * @param {Object} pathData The keys are globs and the values are the preferences for that glob\n     * @param {string} filename relative filename to match against the globs\n     * @return {?string} glob pattern that matched, if any\n     */\n    function _findMatchingGlob(pathData, filename) {\n        var globs = Object.keys(pathData),\n            globCounter;\n\n        if (!filename) {\n            return;\n        }\n\n        for (globCounter = 0; globCounter < globs.length; globCounter++) {\n            var glob = globs[globCounter];\n\n            if (globmatch(filename, glob)) {\n                return glob;\n            }\n        }\n    }\n\n    /**\n     * Create a default project layer object that has a single property \"key\"\n     * with \"project\" as its value.\n     *\n     * @constructor\n     */\n    function ProjectLayer() {\n        this.projectPath = null;\n    }\n\n    ProjectLayer.prototype = {\n        key: \"project\",\n\n        /**\n         * Retrieve the current value based on the current project path\n         * in the layer.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         */\n        get: function (data, id) {\n            if (!data || !this.projectPath) {\n                return;\n            }\n\n            if (data[this.projectPath] && (data[this.projectPath][id] !== undefined)) {\n                return data[this.projectPath][id];\n            }\n            return;\n        },\n\n        /**\n         * Gets the location in which the given pref was set, if it was set within\n         * this project layer for the current project path.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @return {string} the Layer ID, in this case the current project path.\n         */\n        getPreferenceLocation: function (data, id) {\n            if (!data || !this.projectPath) {\n                return;\n            }\n\n            if (data[this.projectPath] && (data[this.projectPath][id] !== undefined)) {\n                return this.projectPath;\n            }\n\n            return;\n        },\n\n        /**\n         * Sets the preference value in the given data structure for the layerID provided. If no\n         * layerID is provided, then the current project path is used. If a layerID is provided\n         * and it does not exist, it will be created.\n         *\n         * This function returns whether or not a value was set.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @param {Object} value new value to assign to the preference\n         * @param {Object} context Object with scope and layer key-value pairs (not yet used in project layer)\n         * @param {string=} layerID Optional: project path to be used for setting value\n         * @return {boolean} true if the value was set\n         */\n        set: function (data, id, value, context, layerID) {\n            if (!layerID) {\n                layerID = this.getPreferenceLocation(data, id);\n            }\n\n            if (!layerID) {\n                return false;\n            }\n\n            var section = data[layerID];\n            if (!section) {\n                data[layerID] = section = {};\n            }\n            if (!_.isEqual(section[id], value)) {\n                if (value === undefined) {\n                    delete section[id];\n                } else {\n                    section[id] = _.cloneDeep(value);\n                }\n                return true;\n            }\n            return false;\n        },\n\n        /**\n         * Retrieves the keys provided by this layer object.\n         *\n         * @param {Object} data the preference data from the Scope\n         */\n        getKeys: function (data) {\n            if (!data) {\n                return;\n            }\n\n            return _.union.apply(null, _.map(_.values(data), _.keys));\n        },\n\n        /**\n         * Set the project path to be used as the layer ID of this layer object.\n         *\n         * @param {string} projectPath Path of the project root\n         */\n        setProjectPath: function (projectPath) {\n            this.projectPath = projectPath;\n        }\n    };\n\n\n    /**\n     * @constructor\n     *\n     * Create a language layer object. Language Layer is completely stateless, it\n     * only knows how look up and process prefs set in the language layer. Desired\n     * language id should be specified in the \"language\" field of the context.\n     */\n    function LanguageLayer() {\n    }\n\n    LanguageLayer.prototype = {\n        key: \"language\",\n\n        /**\n         * Retrieve the current value based on the specified context. If the context\n         * does contain language field, undefined is returned.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @param {{language: string}} context Context to operate with\n         * @return {*|undefined} property value\n         */\n        get: function (data, id, context) {\n            if (!data || !context.language) {\n                return;\n            }\n\n            if (data[context.language] && (data[context.language][id] !== undefined)) {\n                return data[context.language][id];\n            }\n            return;\n        },\n\n        /**\n         * Gets the location in which the given pref was set, if it was set within\n         * this language layer for the current language.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @param {{language: string}} context Context to operate with\n         * @return {string|undefined} the Layer ID, in this case the current language\n         */\n        getPreferenceLocation: function (data, id, context) {\n            if (!data || !context.language) {\n                return;\n            }\n\n            if (data[context.language] && (data[context.language][id] !== undefined)) {\n                return context.language;\n            }\n\n            return;\n        },\n        /**\n         * Retrieves the keys provided by this layer object. If the context is\n         * empty, it will return all the keys provided in all the layerIDs\n         * (languages).\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {{language: string}} context Context to operate with\n         * @return {Array<{string}>|undefined} An array of pref ids\n         */\n        getKeys: function (data, context) {\n            if (!data) {\n                return;\n            }\n\n            // do not upset other layers if context for the this one is not specified\n            if (!_.isEmpty(context)) {\n                if (data[context.language]) {\n                    return _.keys(data[context.language]);\n                } else {\n                    return [];\n                }\n            } else {\n                return _.union.apply(null, _.map(_.values(data), _.keys));\n            }\n        },\n\n        /**\n         * Sets the preference value in the given data structure for the layerID\n         * provided. If no layerID is provided, then it will be determined using\n         * getPreferenceLocation. If a layerID is located, but it does not\n         * exist, it will be created.\n         *\n         * This function returns whether or not a value was set.\n         *\n         * @param {Object} data The preference data from the Scope\n         * @param {string} id Preference ID to look up\n         * @param {Object} value New value to assign to the preference\n         * @param {{language: string}} context Context to operate with\n         * @param {string=} layerID Language to be used for setting value\n         * @return {boolean} True if the value was set\n         */\n        set: function (data, id, value, context, layerID) {\n            if (!layerID) {\n                layerID = this.getPreferenceLocation(data, id, context);\n            }\n\n            if (!layerID) {\n                return false;\n            }\n\n            var section = data[layerID];\n            if (!section) {\n                data[layerID] = section = {};\n            }\n            if (!_.isEqual(section[id], value)) {\n                if (value === undefined) {\n                    delete section[id];\n                    if (_.isEmpty(section)) {\n                        delete data[layerID];\n                    }\n                } else {\n                    section[id] = _.cloneDeep(value);\n                }\n                return true;\n            }\n            return false;\n        },\n\n        /**\n         * Determines if there are preference IDs that could change as a result\n         * of the context change. This implementation considers only changes in\n         * language.\n         *\n         * @param {Object} data Data in the Scope\n         * @param {{language: string}} oldContext Old context\n         * @param {{language: string}} newContext New context\n         * @return {Array.<string>|undefined} list of preference IDs that could have changed\n         */\n        contextChanged: function (data, oldContext, newContext) {\n            // this function is called only if the language has changed\n            if (newContext.language === undefined) {\n                return _.keys(data[oldContext.language]);\n            }\n            if (oldContext.language === undefined) {\n                return _.keys(data[newContext.language]);\n            }\n\n            return _.union(_.keys(data[newContext.language]), _.keys(data[oldContext.language]));\n        }\n    };\n\n    /**\n     * Provides layered preferences based on file globs, generally following the model provided\n     * by [EditorConfig](http://editorconfig.org/). In usage, it looks something like this\n     * (switching to single line comments because the glob interferes with the multiline comment):\n     */\n//    \"path\": {\n//        \"src/thirdparty/CodeMirror/**/*.js\": {\n//            \"spaceUnits\": 2,\n//            \"linting.enabled\": false\n//        }\n//    }\n\n    /**\n     * There can be multiple paths and they are each checked in turn. The first that matches the\n     * currently edited file wins.\n     *\n     * @constructor\n     * @param {string} prefFilePath path to the preference file\n     */\n    function PathLayer(prefFilePath) {\n        this.setPrefFilePath(prefFilePath);\n    }\n\n    PathLayer.prototype = {\n        key: \"path\",\n\n        /**\n         * Retrieve the current value based on the filename in the context\n         * object, comparing globs relative to the prefFilePath that this\n         * PathLayer was set up with.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @param {Object} context Object with filename that will be compared to the globs\n         */\n        get: function (data, id, context) {\n            var glob = this.getPreferenceLocation(data, id, context);\n\n            if (!glob) {\n                return;\n            }\n\n            return data[glob][id];\n        },\n\n        /**\n         * Gets the location in which the given pref was set, if it was set within\n         * this path layer for the current path.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @param {Object} context Object with filename that will be compared to the globs\n         * @return {string} the Layer ID, in this case the glob that matched\n         */\n        getPreferenceLocation: function (data, id, context) {\n            if (!data) {\n                return;\n            }\n\n            var relativeFilename = FileUtils.getRelativeFilename(this.prefFilePath, context[this.key]);\n            if (!relativeFilename) {\n                return;\n            }\n\n            return _findMatchingGlob(data, relativeFilename);\n        },\n\n        /**\n         * Sets the preference value in the given data structure for the layerID provided. If no\n         * layerID is provided, then the current layer is used. If a layerID is provided and it\n         * does not exist, it will be created.\n         *\n         * This function returns whether or not a value was set.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {string} id preference ID to look up\n         * @param {Object} value new value to assign to the preference\n         * @param {Object} context Object with filename that will be compared to the globs\n         * @param {string=} layerID Optional: glob pattern for a specific section to set the value in\n         * @return {boolean} true if the value was set\n         */\n        set: function (data, id, value, context, layerID) {\n            if (!layerID) {\n                layerID = this.getPreferenceLocation(data, id, context);\n            }\n\n            if (!layerID) {\n                return false;\n            }\n\n            var section = data[layerID];\n            if (!section) {\n                data[layerID] = section = {};\n            }\n            if (!_.isEqual(section[id], value)) {\n                if (value === undefined) {\n                    delete section[id];\n                } else {\n                    section[id] = _.cloneDeep(value);\n                }\n                return true;\n            }\n            return false;\n        },\n\n        /**\n         * Retrieves the keys provided by this layer object. If context with a filename is provided,\n         * only the keys for the matching file glob are given. Otherwise, all keys for all globs\n         * are provided.\n         *\n         * @param {Object} data the preference data from the Scope\n         * @param {?Object} context Additional context data (filename in particular is important)\n         */\n        getKeys: function (data, context) {\n            if (!data) {\n                return;\n            }\n\n            var relativeFilename = FileUtils.getRelativeFilename(this.prefFilePath, context[this.key]);\n\n            if (relativeFilename) {\n                var glob = _findMatchingGlob(data, relativeFilename);\n                if (glob) {\n                    return _.keys(data[glob]);\n                } else {\n                    return [];\n                }\n            }\n            return _.union.apply(null, _.map(_.values(data), _.keys));\n        },\n\n        /**\n         * Changes the preference file path.\n         *\n         * @param {string} prefFilePath New path to the preferences file\n         */\n        setPrefFilePath: function (prefFilePath) {\n            if (!prefFilePath) {\n                this.prefFilePath = \"/\";\n            } else {\n                this.prefFilePath = FileUtils.getDirectoryPath(prefFilePath);\n            }\n        },\n\n        /**\n         * Determines if there are preference IDs that could change as a result of\n         * a change in the context. This implementation considers only the path portion\n         * of the context and looks up matching globes if any.\n         *\n         * @param {Object} data Data in the Scope\n         * @param {{path: string}} oldContext Old context\n         * @param {{path: string}} newContext New context\n         * @return {Array.<string>} list of preference IDs that could have changed\n         */\n        contextChanged: function (data, oldContext, newContext) {\n            var newGlob = _findMatchingGlob(data,\n                              FileUtils.getRelativeFilename(this.prefFilePath, newContext[this.key])),\n                oldGlob = _findMatchingGlob(data,\n                              FileUtils.getRelativeFilename(this.prefFilePath, oldContext[this.key]));\n\n            if (newGlob === oldGlob) {\n                return;\n            }\n            if (newGlob === undefined) {\n                return _.keys(data[oldGlob]);\n            }\n            if (oldGlob === undefined) {\n                return _.keys(data[newGlob]);\n            }\n\n            return _.union(_.keys(data[oldGlob]), _.keys(data[newGlob]));\n        }\n    };\n\n\n    /**\n     * Represents a single, known Preference.\n     *\n     * @constructor\n     * @param {Object} properties Information about the Preference that is stored on this object\n     */\n    function Preference(properties) {\n        _.extend(this, properties);\n    }\n\n    EventDispatcher.makeEventDispatcher(Preference.prototype);\n\n\n    /**\n     * Utility for PreferencesSystem & PrefixedPreferencesSystem -- attach EventDispatcher's on()/off()\n     * implementation as private _on_internal()/_off_internal() methods, so the custom on()/off() APIs\n     * these classes use can leverage EventDispatcher code internally. Also attach the regular public trigger().\n     */\n    function _addEventDispatcherImpl(proto) {\n        var temp = {};\n        EventDispatcher.makeEventDispatcher(temp);\n        proto._on_internal  = temp.on;\n        proto._off_internal = temp.off;\n        proto.trigger       = temp.trigger;\n    }\n\n    /**\n     * Provides a subset of the PreferencesSystem functionality with preference\n     * access always occurring with the given prefix.\n     *\n     * @constructor\n     * @param {PreferencesSystem} base The real PreferencesSystem that is backing this one\n     * @param {string} prefix Prefix that is used for preferences lookup. Any separator characters should already be added.\n     */\n    function PrefixedPreferencesSystem(base, prefix) {\n        this.base = base;\n        this.prefix = prefix;\n        this._listenerInstalled = false;\n    }\n\n    PrefixedPreferencesSystem.prototype = {\n        /**\n         * Defines a new (prefixed) preference.\n         *\n         * @param {string} id unprefixed identifier of the preference. Generally a dotted name.\n         * @param {string} type Data type for the preference (generally, string, boolean, number)\n         * @param {Object} initial Default value for the preference\n         * @param {?{name: string=, description: string=, validator: function=, excludeFromHints: boolean=, keys: object=, values: array=, valueType: string=}} options\n         *      Additional options for the pref.\n         *      - `options.name`               Name of the preference that can be used in the UI.\n         *      - `options.description`        A description of the preference.\n         *      - `options.validator`          A function to validate the value of a preference.\n         *      - `options.excludeFromHints`   True if you want to exclude a preference from code hints.\n         *      - `options.keys`               An object that will hold the child preferences in case the preference type is `object`\n         *      - `options.values`             An array of possible values of a preference. It will show up in code hints.\n         *      - `options.valueType`          In case the preference type is `array`, `valueType` should hold data type of its elements.\n         * @return {Object} The preference object.\n         */\n        definePreference: function (id, type, initial, options) {\n            return this.base.definePreference(this.prefix + id, type, initial, options);\n        },\n\n        /**\n         * Get the prefixed preference object\n         *\n         * @param {string} id ID of the pref to retrieve.\n         */\n        getPreference: function (id) {\n            return this.base.getPreference(this.prefix + id);\n        },\n\n        /**\n         * Gets the prefixed preference\n         *\n         * @param {string} id Name of the preference for which the value should be retrieved\n         * @param {Object=} context Optional context object to change the preference lookup\n         */\n        get: function (id, context) {\n            context = context || {};\n            return this.base.get(this.prefix + id, this.base._getContext(context));\n        },\n\n        /**\n         * Gets the location in which the value of a prefixed preference has been set.\n         *\n         * @param {string} id Name of the preference for which the value should be retrieved\n         * @param {Object=} context Optional context object to change the preference lookup\n         * @return {{scope: string, layer: ?string, layerID: ?object}} Object describing where the preferences came from\n         */\n        getPreferenceLocation: function (id, context) {\n            return this.base.getPreferenceLocation(this.prefix + id, context);\n        },\n\n        /**\n         * Sets the prefixed preference\n         *\n         * @param {string} id Identifier of the preference to set\n         * @param {Object} value New value for the preference\n         * @param {{location: ?Object, context: ?Object}=} options Specific location in which to set the value or the context to use when setting the value\n         * @param {boolean=} doNotSave True if the preference change should not be saved automatically.\n         * @return {valid:  {boolean}, true if no validator specified or if value is valid\n         *          stored: {boolean}} true if a value was stored\n         */\n        set: function (id, value, options, doNotSave) {\n            return this.base.set(this.prefix + id, value, options, doNotSave);\n        },\n\n        /**\n         * @private\n         *\n         * Listens for events on the base PreferencesSystem to filter down to the\n         * events that consumers of this PreferencesSystem would be interested in.\n         */\n        _installListener: function () {\n            if (this._listenerInstalled) {\n                return;\n            }\n            var self = this,\n                prefix = this.prefix;\n\n            var onlyWithPrefix = function (id) {\n                if (_.startsWith(id, prefix)) {\n                    return true;\n                }\n                return false;\n            };\n\n            var withoutPrefix = function (id) {\n                return id.substr(prefix.length);\n            };\n\n            this.base.on(PREFERENCE_CHANGE, function (e, data) {\n                var prefixedIds = data.ids.filter(onlyWithPrefix);\n\n                if (prefixedIds.length > 0) {\n                    self.trigger(PREFERENCE_CHANGE, {\n                        ids: prefixedIds.map(withoutPrefix)\n                    });\n                }\n            });\n\n            this._listenerInstalled = true;\n        },\n\n        /**\n         * Sets up a listener for events for this PrefixedPreferencesSystem. Only prefixed events\n         * will notify. Optionally, you can set up a listener for a specific preference.\n         *\n         * @param {string} event Name of the event to listen for\n         * @param {string|Function} preferenceID Name of a specific preference or the handler function\n         * @param {?Function} handler Handler for the event\n         */\n        on: function (event, preferenceID, handler) {\n            if (typeof preferenceID === \"function\") {\n                handler = preferenceID;\n                preferenceID = null;\n            }\n\n            if (preferenceID) {\n                var pref = this.getPreference(preferenceID);\n                pref.on(event, handler);\n            } else {\n                this._installListener();\n                this._on_internal(event, handler);\n            }\n        },\n\n        /**\n         * Turns off the event handlers for a given event, optionally for a specific preference\n         * or a specific handler function.\n         *\n         * @param {string} event Name of the event for which to turn off listening\n         * @param {string|Function} preferenceID Name of a specific preference or the handler function\n         * @param {?Function} handler Specific handler which should stop being notified\n         */\n        off: function (event, preferenceID, handler) {\n            if (typeof preferenceID === \"function\") {\n                handler = preferenceID;\n                preferenceID = null;\n            }\n\n            if (preferenceID) {\n                var pref = this.getPreference(preferenceID);\n                pref.off(event, handler);\n            } else {\n                this._off_internal(event, handler);\n            }\n        },\n\n        /**\n         * Saves the preferences. If a save is already in progress, a Promise is returned for\n         * that save operation.\n         *\n         * @return {Promise} Resolved when the preferences are done saving.\n         */\n        save: function () {\n            return this.base.save();\n        }\n    };\n\n    _addEventDispatcherImpl(PrefixedPreferencesSystem.prototype);\n\n\n    /**\n     * PreferencesSystem ties everything together to provide a simple interface for\n     * managing the whole prefs system.\n     *\n     * It keeps track of multiple Scope levels and also manages path-based Scopes.\n     *\n     * It also provides the ability to register preferences, which gives a fine-grained\n     * means for listening for changes and will ultimately allow for automatic UI generation.\n     *\n     * The contextBuilder is used to construct get/set contexts based on the needs of individual\n     * context systems. It can be passed in at construction time or set later.\n     *\n     * @constructor\n     * @param {function=} contextNormalizer function that is passed the context used for get or set to adjust for specific PreferencesSystem behavior\n     */\n    function PreferencesSystem(contextBuilder) {\n        this.contextBuilder = contextBuilder;\n\n        this._knownPrefs = {};\n        this._scopes = {\n            \"default\": new Scope(new MemoryStorage())\n        };\n\n        this._scopes[\"default\"].load();\n\n        this._defaults = {\n            scopeOrder: [\"default\"],\n            _shadowScopeOrder: [{\n                id: \"default\",\n                scope: this._scopes[\"default\"],\n                promise: (new $.Deferred()).resolve().promise()\n            }]\n        };\n\n        this._pendingScopes = {};\n\n        this._saveInProgress = false;\n        this._nextSaveDeferred = null;\n\n        // The objects that define the different kinds of path-based Scope handlers.\n        // Examples could include the handler for .brackets.json files or an .editorconfig\n        // handler.\n        this._pathScopeDefinitions = {};\n\n        // Names of the files that contain path scopes\n        this._pathScopeFilenames = [];\n\n        // Keeps track of cached path scope objects.\n        this._pathScopes = {};\n\n        // Keeps track of change events that need to be sent when change events are resumed\n        this._changeEventQueue = null;\n\n        var notifyPrefChange = function (id) {\n            var pref = this._knownPrefs[id];\n            if (pref) {\n                pref.trigger(PREFERENCE_CHANGE);\n            }\n        }.bind(this);\n\n        // When we signal a general change message on this manager, we also signal a change\n        // on the individual preference object.\n        this.on(PREFERENCE_CHANGE, function (e, data) {\n            data.ids.forEach(notifyPrefChange);\n        }.bind(this));\n    }\n\n    _.extend(PreferencesSystem.prototype, {\n\n        /**\n         * Defines a new preference.\n         *\n         * @param {string} id identifier of the preference. Generally a dotted name.\n         * @param {string} type Data type for the preference (generally, string, boolean, number)\n         * @param {Object} initial Default value for the preference\n         * @param {?{name: string=, description: string=, validator: function=, excludeFromHints: boolean=, keys: object=, values: array=, valueType: string=}} options\n         *      Additional options for the pref.\n         *      - `options.name`               Name of the preference that can be used in the UI.\n         *      - `options.description`        A description of the preference.\n         *      - `options.validator`          A function to validate the value of a preference.\n         *      - `options.excludeFromHints`   True if you want to exclude a preference from code hints.\n         *      - `options.keys`               An object that will hold the child preferences in case the preference type is `object`\n         *      - `options.values`             An array of possible values of a preference. It will show up in code hints.\n         *      - `options.valueType`          In case the preference type is `array`, `valueType` should hold data type of its elements.\n         * @return {Object} The preference object.\n         */\n        definePreference: function (id, type, initial, options) {\n            options = options || {};\n            if (this._knownPrefs.hasOwnProperty(id)) {\n                throw new Error(\"Preference \" + id + \" was redefined\");\n            }\n            var pref = this._knownPrefs[id] = new Preference({\n                type: type,\n                initial: initial,\n                name: options.name,\n                description: options.description,\n                validator: options.validator,\n                excludeFromHints: options.excludeFromHints,\n                keys: options.keys,\n                values: options.values,\n                valueType: options.valueType\n            });\n            this.set(id, initial, {\n                location: {\n                    scope: \"default\"\n                }\n            });\n            return pref;\n        },\n\n        /**\n         * Get the preference object for the given ID.\n         *\n         * @param {string} id ID of the pref to retrieve.\n         */\n        getPreference: function (id) {\n            return this._knownPrefs[id];\n        },\n\n        /**\n         * Returns a clone of all preferences defined.\n         *\n         * @return {Object}\n         */\n        getAllPreferences: function () {\n            return _.cloneDeep(this._knownPrefs);\n        },\n\n        /**\n         * @private\n         *\n         * Adds the scope before the scope specified by before argument.  This\n         * function must never be called directly. Use addScope to add scopes to\n         * PreferencesSystem, including from within its implementation.\n         *\n         * @param {string} id Id of the scope to add\n         * @param {string} before Id of the scope to add it before\n         */\n        _pushToScopeOrder: function (id, before) {\n            var defaultScopeOrder = this._defaults.scopeOrder,\n                index = _.findIndex(defaultScopeOrder, function (id) {\n                    return id === before;\n                });\n            if (index > -1) {\n                defaultScopeOrder.splice(index, 0, id);\n            } else {\n                // error\n                throw new Error(\"Internal error: scope \" + before + \" should be in the scope order\");\n            }\n\n        },\n\n        /**\n         * @private\n         *\n         * Tries to add scope to the scopeOrder once it's resolved. It looks up\n         * context's _shadowScopeOrder to find an appropriate context to add it\n         * before.\n         *\n         * @param {Object} shadowEntry Shadow entry of the resolved scope\n         */\n        _tryAddToScopeOrder: function (shadowEntry) {\n            var shadowScopeOrder = this._defaults._shadowScopeOrder,\n                index = _.findIndex(shadowScopeOrder, function (entry) {\n                    return entry === shadowEntry;\n                }),\n                i = index + 1;\n\n            // Find an appropriate scope of lower priority to add it before\n            while (i < shadowScopeOrder.length) {\n                if (shadowScopeOrder[i].promise.state() === \"pending\" ||\n                        shadowScopeOrder[i].promise.state() === \"resolved\") {\n                    break;\n                }\n                i++;\n            }\n            switch (shadowScopeOrder[i].promise.state()) {\n            case \"pending\":\n                // cannot decide now, lookup once pending promise is settled\n                shadowScopeOrder[i].promise.always(function () {\n                    this._tryAddToScopeOrder(shadowEntry);\n                }.bind(this));\n                break;\n            case \"resolved\":\n                this._pushToScopeOrder(shadowEntry.id, shadowScopeOrder[i].id);\n                this.trigger(SCOPEORDER_CHANGE, {\n                    id: shadowEntry.id,\n                    action: \"added\"\n                });\n                this._triggerChange({\n                    ids: shadowEntry.scope.getKeys()\n                });\n                break;\n            default:\n                throw new Error(\"Internal error: no scope found to add before. \\\"default\\\" is missing?..\");\n            }\n\n        },\n\n        /**\n         * @private\n         *\n         * Schedules the new Scope to be added the scope order in the specified\n         * location once the promise is resolved. Context's _shadowScopeOrder is\n         * used to keep track of the order in which the scope should appear. If\n         * the scope which should precede this scope fails to load, then\n         * _shadowScopeOrder will be searched for the next appropriate context\n         * (the first one which is pending or loaded that is before the failed\n         * scope). There's always the lowest-priority \"default\" scope which is\n         * loaded and added, it guarantees that a successfully loaded scope will\n         * always be added.\n         *\n         * Adding a Scope \"before\" another Scope means that the new Scope's\n         * preferences will take priority over the \"before\" Scope's preferences.\n         *\n         * @param {string} id Name of the new Scope\n         * @param {Scope} scope The scope object to add\n         * @param {$.Promise} promise Scope's load promise\n         * @param {?string} addBefore Name of the Scope before which this new one is added\n         */\n        _addToScopeOrder: function (id, scope, promise, addBefore) {\n            var shadowScopeOrder = this._defaults._shadowScopeOrder,\n                shadowEntry,\n                index,\n                isPending = false,\n                self = this;\n\n            scope.on(PREFERENCE_CHANGE + \".prefsys\", function (e, data) {\n                self._triggerChange(data);\n            }.bind(this));\n\n            index = _.findIndex(shadowScopeOrder, function (entry) {\n                return entry.id === id;\n            });\n\n            if (index > -1) {\n                shadowEntry = shadowScopeOrder[index];\n            } else {\n                /* new scope is being added. */\n                shadowEntry = {\n                    id: id,\n                    promise: promise,\n                    scope: scope\n                };\n                if (!addBefore) {\n                    shadowScopeOrder.unshift(shadowEntry);\n                } else {\n                    index = _.findIndex(shadowScopeOrder, function (entry) {\n                        return entry.id === addBefore;\n                    });\n                    if (index > -1) {\n                        shadowScopeOrder.splice(index, 0, shadowEntry);\n                    } else {\n                        var queue = this._pendingScopes[addBefore];\n                        if (!queue) {\n                            queue = [];\n                            this._pendingScopes[addBefore] = queue;\n                        }\n                        queue.unshift(shadowEntry);\n                        isPending = true;\n                    }\n                }\n            }\n\n            if (!isPending) {\n                promise\n                    .then(function () {\n                        this._scopes[id] = scope;\n                        this._tryAddToScopeOrder(shadowEntry);\n                    }.bind(this))\n                    .fail(function (err) {\n                        // clean up all what's been done up to this point\n                        _.pull(shadowScopeOrder, shadowEntry);\n                    }.bind(this));\n                if (this._pendingScopes[id]) {\n                    var pending = this._pendingScopes[id];\n                    delete this._pendingScopes[id];\n                    pending.forEach(function (entry) {\n                        this._addToScopeOrder(entry.id, entry.scope, entry.promise, id);\n                    }.bind(this));\n                }\n            }\n        },\n\n        /**\n         * Adds scope to the scope order by its id. The scope should be previously added to the preference system.\n         *\n         * @param {string} id the scope id\n         * @param {string} before the id of the scope to add before\n         *\n         */\n        addToScopeOrder: function (id, addBefore) {\n            var shadowScopeOrder = this._defaults._shadowScopeOrder,\n                index = _.findIndex(shadowScopeOrder, function (entry) {\n                    return entry.id === id;\n                }),\n                entry;\n            if (index > -1) {\n                entry = shadowScopeOrder[index];\n                this._addToScopeOrder(entry.id, entry.scope, entry.promise, addBefore);\n            }\n        },\n\n        /**\n         * Removes a scope from the default scope order.\n         *\n         * @param {string} id Name of the Scope to remove from the default scope order.\n         */\n        removeFromScopeOrder: function (id) {\n            var scope = this._scopes[id];\n            if (scope) {\n                _.pull(this._defaults.scopeOrder, id);\n                scope.off(\".prefsys\");\n                this.trigger(SCOPEORDER_CHANGE, {\n                    id: id,\n                    action: \"removed\"\n                });\n                this._triggerChange({\n                    ids: scope.getKeys()\n                });\n            }\n        },\n\n        /**\n         * @private\n         *\n         * Normalizes the context to be one of:\n         *\n         * 1. a context object that was passed in\n         * 2. the default context\n         *\n         * @param {Object} context Context that was passed in\n         * @return {{scopeOrder: string, filename: ?string}} context object\n         */\n        _getContext: function (context) {\n            if (context) {\n                if (this.contextBuilder) {\n                    context = this.contextBuilder(context);\n                }\n                if (!context.scopeOrder) {\n                    context.scopeOrder = this._defaults.scopeOrder;\n                }\n                return context;\n            }\n            return { scopeOrder: this._defaults.scopeOrder };\n        },\n\n        /**\n         * Adds a new Scope. New Scopes are added at the highest precedence, unless the \"before\" option\n         * is given. The new Scope is automatically loaded.\n         *\n         * @param {string} id Name of the Scope\n         * @param {Scope|Storage} scope the Scope object itself. Optionally, can be given a Storage directly for convenience.\n         * @param {{before: string}} options optional behavior when adding (e.g. setting which scope this comes before)\n         * @return {Promise} Promise that is resolved when the Scope is loaded. It is resolved\n         *                   with id and scope.\n         */\n        addScope: function (id, scope, options) {\n            var promise;\n            options = options || {};\n\n            if (this._scopes[id]) {\n                throw new Error(\"Attempt to redefine preferences scope: \" + id);\n            }\n\n            // Check to see if scope is a Storage that needs to be wrapped\n            if (!scope.get) {\n                scope = new Scope(scope);\n            }\n\n            promise = scope.load();\n\n            this._addToScopeOrder(id, scope, promise, options.before);\n\n            promise\n                .fail(function (err) {\n                    // With preferences, it is valid for there to be no file.\n                    // It is not valid to have an unparseable file.\n                    if (err instanceof ParsingError) {\n                        console.error(err);\n                    }\n                });\n\n            return promise;\n        },\n\n        /**\n         * Removes a Scope from this PreferencesSystem. Returns without doing anything\n         * if the Scope does not exist. Notifies listeners of preferences that may have\n         * changed.\n         *\n         * @param {string} id Name of the Scope to remove\n         */\n        removeScope: function (id) {\n            var scope = this._scopes[id],\n                shadowIndex;\n            if (!scope) {\n                return;\n            }\n\n            this.removeFromScopeOrder(id);\n            shadowIndex = _.findIndex(this._defaults._shadowScopeOrder, function (entry) {\n                return entry.id === id;\n            });\n            this._defaults._shadowScopeOrder.splice(shadowIndex, 1);\n            delete this._scopes[id];\n        },\n\n        /**\n         * @private\n         *\n         * Retrieves the appropriate scopeOrder based on the given context.\n         * If the context contains a scopeOrder, that will be used. If not,\n         * the default scopeOrder is used.\n         *\n         * @param {{scopeOrder: ?Array.<string>} context\n         * @return {Array.<string>} list of scopes in the correct order for traversal\n         */\n        _getScopeOrder: function (context) {\n            return context.scopeOrder || this._defaults.scopeOrder;\n        },\n\n        /**\n         * Get the current value of a preference. The optional context provides a way to\n         * change scope ordering or the reference filename for path-based scopes.\n         *\n         * @param {string} id Name of the preference for which the value should be retrieved\n         * @param {Object|string=} context Optional context object or name of context to change the preference lookup\n         */\n        get: function (id, context) {\n            var scopeCounter;\n\n            context = this._getContext(context);\n\n            var scopeOrder = this._getScopeOrder(context);\n\n            for (scopeCounter = 0; scopeCounter < scopeOrder.length; scopeCounter++) {\n                var scope = this._scopes[scopeOrder[scopeCounter]];\n                if (scope) {\n                    var result = scope.get(id, context);\n                    if (result !== undefined) {\n                        var pref      = this.getPreference(id),\n                            validator = pref && pref.validator;\n                        if (!validator || validator(result)) {\n                            if (pref && pref.type === \"object\") {\n                                result = _.extend({}, pref.initial, result);\n                            }\n                            return _.cloneDeep(result);\n                        }\n                    }\n                }\n            }\n        },\n\n        /**\n         * Gets the location in which the value of a preference has been set.\n         *\n         * @param {string} id Name of the preference for which the value should be retrieved\n         * @param {Object=} context Optional context object to change the preference lookup\n         * @return {{scope: string, layer: ?string, layerID: ?object}} Object describing where the preferences came from\n         */\n        getPreferenceLocation: function (id, context) {\n            var scopeCounter,\n                scopeName;\n\n            context = this._getContext(context);\n\n            var scopeOrder = this._getScopeOrder(context);\n\n            for (scopeCounter = 0; scopeCounter < scopeOrder.length; scopeCounter++) {\n                scopeName = scopeOrder[scopeCounter];\n                var scope = this._scopes[scopeName];\n                if (scope) {\n                    var result = scope.getPreferenceLocation(id, context);\n                    if (result !== undefined) {\n                        result.scope = scopeName;\n                        return result;\n                    }\n                }\n            }\n        },\n\n        /**\n         * Sets a preference and notifies listeners that there may\n         * have been a change. By default, the preference is set in the same location in which\n         * it was defined except for the \"default\" scope. If the current value of the preference\n         * comes from the \"default\" scope, the new value will be set at the level just above\n         * default.\n         *\n         * @param {string} id Identifier of the preference to set\n         * @param {Object} value New value for the preference\n         * @param {{location: ?Object, context: ?Object}=} options Specific location in which to set the value or the context to use when setting the value\n         * @param {boolean=} doNotSave True if the preference change should not be saved automatically.\n         * @return {valid:  {boolean}, true if no validator specified or if value is valid\n         *          stored: {boolean}} true if a value was stored\n         */\n        set: function (id, value, options, doNotSave) {\n            options = options || {};\n            var context = this._getContext(options.context),\n\n                // The case where the \"default\" scope was chosen specifically is special.\n                // Usually \"default\" would come up only when a preference did not have any\n                // user-set value, in which case we'd want to set the value in a different scope.\n                forceDefault = options.location && options.location.scope === \"default\" ? true : false,\n                location = options.location || this.getPreferenceLocation(id, context);\n\n            if (!location || (location.scope === \"default\" && !forceDefault)) {\n                var scopeOrder = this._getScopeOrder(context);\n\n                // The default scope for setting a preference is the lowest priority\n                // scope after \"default\".\n                if (scopeOrder.length > 1) {\n                    location = {\n                        scope: scopeOrder[scopeOrder.length - 2]\n                    };\n                } else {\n                    return { valid: true, stored: false };\n                }\n            }\n\n            var scope = this._scopes[location.scope];\n            if (!scope) {\n                return { valid: true, stored: false };\n            }\n\n            var pref      = this.getPreference(id),\n                validator = pref && pref.validator;\n            if (validator && !validator(value)) {\n                return { valid: false, stored: false };\n            }\n\n            var wasSet = scope.set(id, value, context, location);\n            if (wasSet) {\n                if (!doNotSave) {\n                    this.save();\n                }\n                this._triggerChange({\n                    ids: [id]\n                });\n            }\n            return { valid: true, stored: wasSet };\n        },\n\n        /**\n         * Saves the preferences. If a save is already in progress, a Promise is returned for\n         * that save operation.\n         *\n         * @return {Promise} Resolved when the preferences are done saving.\n         */\n        save: function () {\n            if (this._saveInProgress) {\n                if (!this._nextSaveDeferred) {\n                    this._nextSaveDeferred = new $.Deferred();\n                }\n                return this._nextSaveDeferred.promise();\n            }\n\n            var deferred = this._nextSaveDeferred || (new $.Deferred());\n            this._saveInProgress = true;\n            this._nextSaveDeferred = null;\n\n            Async.doInParallel(_.values(this._scopes), function (scope) {\n                if (scope) {\n                    return scope.save();\n                } else {\n                    return (new $.Deferred()).resolve().promise();\n                }\n            }.bind(this))\n                .then(function () {\n                    this._saveInProgress = false;\n                    if (this._nextSaveDeferred) {\n                        this.save();\n                    }\n                    deferred.resolve();\n                }.bind(this))\n                .fail(function (err) {\n                    deferred.reject(err);\n                });\n\n            return deferred.promise();\n        },\n\n        /**\n         * Signals the context change to all the scopes within the preferences\n         * layer.  PreferencesManager is in charge of computing the context and\n         * signaling the changes to PreferencesSystem.\n         *\n         * @param {{path: string, language: string}} oldContext Old context\n         * @param {{path: string, language: string}} newContext New context\n         */\n        signalContextChanged: function (oldContext, newContext) {\n            var changes = [];\n\n            _.each(this._scopes, function (scope) {\n                var changedInScope = scope.contextChanged(oldContext, newContext);\n                if (changedInScope) {\n                    changes.push(changedInScope);\n                }\n            });\n\n            changes = _.union.apply(null, changes);\n            if (changes.length > 0) {\n                this._triggerChange({\n                    ids: changes\n                });\n            }\n        },\n\n        /**\n         * Sets up a listener for events. Optionally, you can set up a listener for a\n         * specific preference.\n         *\n         * @param {string} event Name of the event to listen for\n         * @param {string|Function} preferenceID Name of a specific preference or the handler function\n         * @param {?Function} handler Handler for the event\n         */\n        on: function (event, preferenceID, handler) {\n            if (typeof preferenceID === \"function\") {\n                handler = preferenceID;\n                preferenceID = null;\n            }\n\n            if (preferenceID) {\n                var pref = this.getPreference(preferenceID);\n                pref.on(event, handler);\n            } else {\n                this._on_internal(event, handler);\n            }\n        },\n\n        /**\n         * Turns off the event handlers for a given event, optionally for a specific preference\n         * or a specific handler function.\n         *\n         * @param {string} event Name of the event for which to turn off listening\n         * @param {string|Function} preferenceID Name of a specific preference or the handler function\n         * @param {?Function} handler Specific handler which should stop being notified\n         */\n        off: function (event, preferenceID, handler) {\n            if (typeof preferenceID === \"function\") {\n                handler = preferenceID;\n                preferenceID = null;\n            }\n\n            if (preferenceID) {\n                var pref = this.getPreference(preferenceID);\n                pref.off(event, handler);\n            } else {\n                this._off_internal(event, handler);\n            }\n        },\n\n        /**\n         * @private\n         *\n         * Sends a change event to listeners. If change events have been paused (see\n         * pauseChangeEvents) then the IDs are queued up.\n         *\n         * @param {{ids: Array.<string>}} data Message to send\n         */\n        _triggerChange: function (data) {\n            if (this._changeEventQueue) {\n                this._changeEventQueue = _.union(this._changeEventQueue, data.ids);\n            } else {\n                this.trigger(PREFERENCE_CHANGE, data);\n            }\n        },\n\n        /**\n         * Turns off sending of change events, queueing them up for sending once sending is resumed.\n         * The events are compacted so that each preference that will be notified is only\n         * notified once. (For example, if `spaceUnits` is changed 5 times, only one change\n         * event will be sent upon resuming events.)\n         */\n        pauseChangeEvents: function () {\n            if (!this._changeEventQueue) {\n                this._changeEventQueue = [];\n            }\n        },\n\n        /**\n         * Turns sending of events back on, sending any events that were queued while the\n         * events were paused.\n         */\n        resumeChangeEvents: function () {\n            if (this._changeEventQueue) {\n                this.trigger(PREFERENCE_CHANGE, {\n                    ids: this._changeEventQueue\n                });\n                this._changeEventQueue = null;\n            }\n        },\n\n        /**\n         * Tells the PreferencesSystem that the given file has been changed so that any\n         * related Scopes can be reloaded.\n         *\n         * @param {string} filePath File that has changed\n         */\n        fileChanged: function (filePath) {\n            _.forEach(this._scopes, function (scope) {\n                scope.fileChanged(filePath);\n            });\n        },\n\n        /**\n         * Retrieves a PreferencesSystem in which all preference access is prefixed.\n         * This helps provide namespacing so that different preferences consumers do\n         * not interfere with one another.\n         *\n         * The prefix provided has a `.` character appended when preference lookups are\n         * done.\n         */\n        getPrefixedSystem: function (prefix) {\n            return new PrefixedPreferencesSystem(this, prefix + \".\");\n        }\n\n    });\n\n    _addEventDispatcherImpl(PreferencesSystem.prototype);\n\n\n    // Public interface\n    exports.PreferencesSystem   = PreferencesSystem;\n    exports.Scope               = Scope;\n    exports.MemoryStorage       = MemoryStorage;\n    exports.PathLayer           = PathLayer;\n    exports.ProjectLayer        = ProjectLayer;\n    exports.LanguageLayer       = LanguageLayer;\n    exports.FileStorage         = FileStorage;\n});\n"
  },
  {
    "path": "src/preferences/PreferencesDialogs.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * PreferencesDialogs\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Dialogs                = require(\"widgets/Dialogs\"),\n        ProjectManager         = require(\"project/ProjectManager\"),\n        StringUtils            = require(\"utils/StringUtils\"),\n        Strings                = require(\"strings\"),\n        SettingsDialogTemplate = require(\"text!htmlContent/project-settings-dialog.html\"),\n        Mustache               = require(\"thirdparty/mustache/mustache\"),\n        PathUtils              = require(\"thirdparty/path-utils/path-utils\"),\n        HealthLogger           = require(\"utils/HealthLogger\");\n\n    /**\n     * Validate that text string is a valid base url which should map to a server folder\n     * @param {string} url\n     * @return {string} Empty string if valid, otherwise error string\n     */\n    function _validateBaseUrl(url) {\n        var result = \"\";\n        // Empty url means \"no server mapping; use file directly\"\n        if (url === \"\") {\n            return result;\n        }\n\n        var obj = PathUtils.parseUrl(url);\n        if (!obj) {\n            result = Strings.BASEURL_ERROR_UNKNOWN_ERROR;\n        } else if (obj.href.search(/^(http|https):\\/\\//i) !== 0) {\n            result = StringUtils.format(Strings.BASEURL_ERROR_INVALID_PROTOCOL, obj.href.substring(0, obj.href.indexOf(\"//\")));\n        } else if (obj.search !== \"\") {\n            result = StringUtils.format(Strings.BASEURL_ERROR_SEARCH_DISALLOWED, obj.search);\n        } else if (obj.hash !== \"\") {\n            result = StringUtils.format(Strings.BASEURL_ERROR_HASH_DISALLOWED, obj.hash);\n        } else {\n            var index = url.search(/[ \\^\\[\\]\\{\\}<>\\\\\"\\?]+/);\n            if (index !== -1) {\n                result = StringUtils.format(Strings.BASEURL_ERROR_INVALID_CHAR, url[index]);\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * Show a dialog that shows the project preferences\n     * @param {string} baseUrl Initial value\n     * @param {string} errorMessage Error to display\n     * @return {Dialog} A Dialog object with an internal promise that will be resolved with the ID\n     *      of the clicked button when the dialog is dismissed. Never rejected.\n     */\n    function showProjectPreferencesDialog(baseUrl, errorMessage) {\n        var $baseUrlControl,\n            dialog;\n\n        // Title\n        var projectName = \"\",\n            projectRoot = ProjectManager.getProjectRoot(),\n            title;\n        if (projectRoot) {\n            projectName = projectRoot.name;\n        }\n        title = StringUtils.format(Strings.PROJECT_SETTINGS_TITLE, projectName);\n\n        var templateVars = {\n            title        : title,\n            baseUrl      : baseUrl,\n            errorMessage : errorMessage,\n            Strings      : Strings\n        };\n\n        dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(SettingsDialogTemplate, templateVars));\n\n        dialog.done(function (id) {\n            if (id === Dialogs.DIALOG_BTN_OK) {\n                var baseUrlValue = $baseUrlControl.val();\n                var result = _validateBaseUrl(baseUrlValue);\n                if (result === \"\") {\n                    // Send analytics data when url is set in project settings\n                    HealthLogger.sendAnalyticsData(\n                        \"projectSettingsLivepreview\",\n                        \"usage\",\n                        \"projectSettings\",\n                        \"use\"\n                    );\n                    ProjectManager.setBaseUrl(baseUrlValue);\n                } else {\n                    // Re-invoke dialog with result (error message)\n                    showProjectPreferencesDialog(baseUrlValue, result);\n                }\n            }\n        });\n\n        // Give focus to first control\n        $baseUrlControl = dialog.getElement().find(\".url\");\n        $baseUrlControl.focus();\n\n        return dialog;\n    }\n\n    // For unit testing\n    exports._validateBaseUrl                = _validateBaseUrl;\n\n    exports.showProjectPreferencesDialog    = showProjectPreferencesDialog;\n});\n"
  },
  {
    "path": "src/preferences/PreferencesImpl.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Generates the fully configured preferences systems used throughout Brackets. This is intended\n * to be essentially private implementation that can be overridden for tests.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var PreferencesBase = require(\"./PreferencesBase\"),\n        Async           = require(\"utils/Async\"),\n\n        // The SETTINGS_FILENAME is used with a preceding \".\" within user projects\n        SETTINGS_FILENAME = \"brackets.json\",\n        STATE_FILENAME    = \"state.json\",\n\n        // User-level preferences\n        userPrefFile = brackets.app.getApplicationSupportDirectory() + \"/\" + SETTINGS_FILENAME;\n\n    /**\n     * A deferred object which is used to indicate PreferenceManager readiness during the start-up.\n     * @private\n     * @type {$.Deferred}\n     */\n    var _prefManagerReadyDeferred = new $.Deferred();\n\n    /**\n     * A boolean property indicating if the user scope configuration file is malformed.\n     */\n    var userScopeCorrupt = false;\n\n    function isUserScopeCorrupt() {\n        return userScopeCorrupt;\n    }\n\n    /**\n     * Promises to add scopes. Used at init time only.\n     * @private\n     * @type {Array.<$.Promise>}\n     */\n    var _addScopePromises = [];\n\n    var manager = new PreferencesBase.PreferencesSystem();\n    manager.pauseChangeEvents();\n\n    // Create a Project scope\n    var projectStorage          = new PreferencesBase.FileStorage(undefined, true),\n        projectScope            = new PreferencesBase.Scope(projectStorage),\n        projectPathLayer        = new PreferencesBase.PathLayer(),\n        projectLanguageLayer    = new PreferencesBase.LanguageLayer();\n\n    projectScope.addLayer(projectPathLayer);\n    projectScope.addLayer(projectLanguageLayer);\n\n    // Create a User scope\n    var userStorage             = new PreferencesBase.FileStorage(userPrefFile, true),\n        userScope               = new PreferencesBase.Scope(userStorage),\n        userLanguageLayer       = new PreferencesBase.LanguageLayer();\n\n    userScope.addLayer(userLanguageLayer);\n\n    var userScopeLoading = manager.addScope(\"user\", userScope);\n\n    _addScopePromises.push(userScopeLoading);\n\n    // Set up the .brackets.json file handling\n    userScopeLoading\n        .fail(function (err) {\n            _addScopePromises.push(manager.addScope(\"user\", new PreferencesBase.MemoryStorage(), {\n                before: \"default\"\n            }));\n\n            if (err.name && err.name === \"ParsingError\") {\n                userScopeCorrupt = true;\n            }\n        })\n        .always(function () {\n            _addScopePromises.push(manager.addScope(\"project\", projectScope, {\n                before: \"user\"\n            }));\n\n            // Session Scope is for storing prefs in memory only but with the highest precedence.\n            _addScopePromises.push(manager.addScope(\"session\", new PreferencesBase.MemoryStorage()));\n\n            Async.waitForAll(_addScopePromises)\n                .always(function () {\n                    _prefManagerReadyDeferred.resolve();\n                });\n        });\n\n\n    // \"State\" is stored like preferences but it is not generally intended to be user-editable.\n    // It's for more internal, implicit things like window size, working set, etc.\n    var stateManager = new PreferencesBase.PreferencesSystem();\n    var userStateFile = brackets.app.getApplicationSupportDirectory() + \"/\" + STATE_FILENAME;\n    var smUserScope = new PreferencesBase.Scope(new PreferencesBase.FileStorage(userStateFile, true, true));\n    var stateProjectLayer = new PreferencesBase.ProjectLayer();\n    smUserScope.addLayer(stateProjectLayer);\n    var smUserScopeLoading = stateManager.addScope(\"user\", smUserScope);\n\n\n    // Listen for times where we might be unwatching a root that contains one of the user-level prefs files,\n    // and force a re-read of the file in order to ensure we can write to it later (see #7300).\n    function _reloadUserPrefs(rootDir) {\n        var prefsDir = brackets.app.getApplicationSupportDirectory() + \"/\";\n        if (prefsDir.indexOf(rootDir.fullPath) === 0) {\n            manager.fileChanged(userPrefFile);\n            stateManager.fileChanged(userStateFile);\n        }\n    }\n\n    // Semi-Public API. Use this at your own risk. The public API is in PreferencesManager.\n    exports.manager             = manager;\n    exports.projectStorage      = projectStorage;\n    exports.projectPathLayer    = projectPathLayer;\n    exports.userScopeLoading    = userScopeLoading;\n    exports.stateManager        = stateManager;\n    exports.stateProjectLayer   = stateProjectLayer;\n    exports.smUserScopeLoading  = smUserScopeLoading;\n    exports.userPrefFile        = userPrefFile;\n    exports.isUserScopeCorrupt  = isUserScopeCorrupt;\n    exports.managerReady        = _prefManagerReadyDeferred.promise();\n    exports.reloadUserPrefs     = _reloadUserPrefs;\n    exports.STATE_FILENAME      = STATE_FILENAME;\n    exports.SETTINGS_FILENAME   = SETTINGS_FILENAME;\n});\n"
  },
  {
    "path": "src/preferences/PreferencesManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global define, console */\n/*unittests: Preferences Manager */\n\n/**\n * PreferencesManager\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit                 = require(\"utils/AppInit\"),\n        Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        PreferencesBase         = require(\"preferences/PreferencesBase\"),\n        FileSystem              = require(\"filesystem/FileSystem\"),\n        Strings                 = require(\"strings\"),\n        PreferencesImpl         = require(\"preferences/PreferencesImpl\"),\n        _                       = require(\"thirdparty/lodash\");\n\n    var currentFilename         = null, // the filename currently being edited\n        currentLanguageId       = null, // the language id of the file currently being edited\n        projectDirectory        = null,\n        projectScopeIsIncluded  = true;\n\n    /**\n     * @private\n     *\n     * Determines whether the project Scope should be included based on whether\n     * the currently edited file is within the project.\n     *\n     * @param {string=} filename Full path to edited file\n     * @return {boolean} true if the project Scope should be included.\n     */\n    function _includeProjectScope(filename) {\n        filename = filename || currentFilename;\n        if (!filename || !projectDirectory) {\n            return false;\n        }\n        return FileUtils.getRelativeFilename(projectDirectory, filename) !== undefined;\n    }\n\n    /**\n     * Get the full path to the user-level preferences file.\n     *\n     * @return {string} Path to the preferences file\n     */\n    function getUserPrefFile() {\n        return PreferencesImpl.userPrefFile;\n    }\n\n    /**\n     * @private\n     *\n     * Adds or removes the project Scope as needed based on whether the currently\n     * edited file is within the project.\n     */\n    function _toggleProjectScope() {\n        if (_includeProjectScope() === projectScopeIsIncluded) {\n            return;\n        }\n        if (projectScopeIsIncluded) {\n            PreferencesImpl.manager.removeFromScopeOrder(\"project\");\n        } else {\n            PreferencesImpl.manager.addToScopeOrder(\"project\", \"user\");\n        }\n        projectScopeIsIncluded = !projectScopeIsIncluded;\n    }\n\n    /**\n     * @private\n     *\n     * This is used internally within Brackets for the ProjectManager to signal\n     * which file contains the project-level preferences.\n     *\n     * @param {string} settingsFile Full path to the project's settings file\n     */\n    function _setProjectSettingsFile(settingsFile) {\n        projectDirectory = FileUtils.getDirectoryPath(settingsFile);\n        _toggleProjectScope();\n        PreferencesImpl.projectPathLayer.setPrefFilePath(settingsFile);\n        PreferencesImpl.projectStorage.setPath(settingsFile);\n    }\n\n    /**\n     * Creates an extension-specific preferences manager using the prefix given.\n     * A `.` character will be appended to the prefix. So, a preference named `foo`\n     * with a prefix of `myExtension` will be stored as `myExtension.foo` in the\n     * preferences files.\n     *\n     * @param {string} prefix Prefix to be applied\n     */\n    function getExtensionPrefs(prefix) {\n        return PreferencesImpl.manager.getPrefixedSystem(prefix);\n    }\n\n    // Constants for preference lookup contexts.\n\n    /**\n     * Context to look up preferences in the current project.\n     * @type {Object}\n     */\n    var CURRENT_PROJECT = {};\n\n    /**\n     * Context to look up preferences for the currently edited file.\n     * This is undefined because this is the default behavior of PreferencesSystem.get.\n     *\n     * @type {Object}\n     */\n    var CURRENT_FILE;\n\n    /**\n     * Cached copy of the scopeOrder with the project Scope\n     */\n    var scopeOrderWithProject = null;\n\n    /**\n     * Cached copy of the scopeOrder without the project Scope\n     */\n    var scopeOrderWithoutProject = null;\n\n    /**\n     * @private\n     *\n     * Adjusts scopeOrder to have the project Scope if necessary.\n     * Returns a new array if changes are needed, otherwise returns\n     * the original array.\n     *\n     * @param {Array.<string>} scopeOrder initial scopeOrder\n     * @param {boolean} includeProject Whether the project Scope should be included\n     * @return {Array.<string>} array with or without project Scope as needed.\n     */\n    function _adjustScopeOrderForProject(scopeOrder, includeProject) {\n        var hasProject = scopeOrder.indexOf(\"project\") > -1;\n\n        if (hasProject === includeProject) {\n            return scopeOrder;\n        }\n\n        var newScopeOrder;\n\n        if (includeProject) {\n            var before = scopeOrder.indexOf(\"user\");\n            if (before === -1) {\n                before = scopeOrder.length - 2;\n            }\n            newScopeOrder = _.take(scopeOrder, before);\n            newScopeOrder.push(\"project\");\n            newScopeOrder.push.apply(newScopeOrder, _.drop(scopeOrder, before));\n        } else {\n            newScopeOrder = _.without(scopeOrder, \"project\");\n        }\n        return newScopeOrder;\n    }\n\n    /**\n     * @private\n     *\n     * Creates a context based on the specified filename and language.\n     *\n     * @param {string=} filename Filename to create the context with.\n     * @param {string=} languageId Language ID to create the context with.\n     */\n    function _buildContext(filename, languageId) {\n        var ctx = {};\n        if (filename) {\n            ctx.path = filename;\n        } else {\n            ctx.path = currentFilename;\n        }\n        if (languageId) {\n            ctx.language = languageId;\n        } else {\n            ctx.language = currentLanguageId;\n        }\n        ctx.scopeOrder = _includeProjectScope(ctx.path) ?\n                        scopeOrderWithProject :\n                        scopeOrderWithoutProject;\n        return ctx;\n    }\n\n    function _getContext(context) {\n        context = context || {};\n        return _buildContext(context.path, context.language);\n    }\n\n    /**\n     * @private\n     *\n     * This is used internally within Brackets for the EditorManager to signal\n     * to the preferences what the currently edited file is.\n     *\n     * @param {string} newFilename Full path to currently edited file\n     */\n    function _setCurrentFile(newFilename) {\n        var oldFilename = currentFilename;\n        if (oldFilename === newFilename) {\n            return;\n        }\n        currentFilename = newFilename;\n        _toggleProjectScope();\n        PreferencesImpl.manager.signalContextChanged(_buildContext(oldFilename, currentLanguageId),\n                                                     _buildContext(newFilename, currentLanguageId));\n    }\n\n    /**\n     * @private\n     * This function is used internally to set the current language of the document.\n     * Both at the moment of opening the file and when the language is manually\n     * overriden.\n     *\n     * @param {string} newLanguageId The id of the language of the current editor.\n     */\n    function _setCurrentLanguage(newLanguageId) {\n        var oldLanguageId = currentLanguageId;\n        if (oldLanguageId === newLanguageId) {\n            return;\n        }\n        currentLanguageId = newLanguageId;\n        PreferencesImpl.manager.signalContextChanged(_buildContext(currentFilename, oldLanguageId),\n                                                     _buildContext(currentFilename, newLanguageId));\n    }\n\n\n    PreferencesImpl.manager.contextBuilder = _getContext;\n\n    /**\n     * @private\n     *\n     * Updates the CURRENT_PROJECT context to have the correct scopes.\n     */\n    function _updateCurrentProjectContext() {\n        var defaultScopeOrder = PreferencesImpl.manager._getScopeOrder({});\n        scopeOrderWithProject = _adjustScopeOrderForProject(defaultScopeOrder, true);\n        scopeOrderWithoutProject = _adjustScopeOrderForProject(defaultScopeOrder, false);\n        CURRENT_PROJECT.scopeOrder = scopeOrderWithProject;\n    }\n\n    _updateCurrentProjectContext();\n\n    PreferencesImpl.manager.on(\"scopeOrderChange\", _updateCurrentProjectContext);\n\n    /**\n     * @private\n     */\n    function _handleOpenPreferences() {\n        var fullPath = getUserPrefFile(),\n            file = FileSystem.getFileForPath(fullPath);\n        file.exists(function (err, doesExist) {\n            if (doesExist) {\n                CommandManager.execute(Commands.FILE_OPEN, { fullPath: fullPath });\n            } else {\n                FileUtils.writeText(file, \"\", true)\n                    .done(function () {\n                        CommandManager.execute(Commands.FILE_OPEN, { fullPath: fullPath });\n                    });\n            }\n        });\n\n    }\n\n    CommandManager.register(Strings.CMD_OPEN_PREFERENCES, Commands.FILE_OPEN_PREFERENCES, _handleOpenPreferences);\n\n    /**\n     * Convenience function that gets a view state\n     *\n     * @param {string} id preference to get\n     * @param {?Object} context Optional additional information about the request\n     */\n    function getViewState(id, context) {\n        return PreferencesImpl.stateManager.get(id, context);\n    }\n\n    /**\n     * Convenience function that sets a view state and then saves the file\n     *\n     * @param {string} id preference to set\n     * @param {*} value new value for the preference\n     * @param {?Object} context Optional additional information about the request\n     * @param {boolean=} doNotSave If it is undefined or false, then save the\n     *      view state immediately.\n     */\n    function setViewState(id, value, context, doNotSave) {\n\n        PreferencesImpl.stateManager.set(id, value, context);\n\n        if (!doNotSave) {\n            PreferencesImpl.stateManager.save();\n        }\n    }\n\n    AppInit.appReady(function () {\n        PreferencesImpl.manager.resumeChangeEvents();\n    });\n\n    // Private API for unit testing and use elsewhere in Brackets core\n    exports._isUserScopeCorrupt     = PreferencesImpl.isUserScopeCorrupt;\n    exports._setCurrentFile         = _setCurrentFile;\n    exports._setCurrentLanguage     = _setCurrentLanguage;\n    exports._setProjectSettingsFile = _setProjectSettingsFile;\n    exports._smUserScopeLoading     = PreferencesImpl.smUserScopeLoading;\n    exports._stateProjectLayer      = PreferencesImpl.stateProjectLayer;\n    exports._reloadUserPrefs        = PreferencesImpl.reloadUserPrefs;\n    exports._buildContext           = _buildContext;\n\n    // Public API\n\n    // Context names for preference lookups\n    exports.CURRENT_FILE        = CURRENT_FILE;\n    exports.CURRENT_PROJECT     = CURRENT_PROJECT;\n\n    exports.ready               = PreferencesImpl.managerReady;\n    exports.getUserPrefFile     = getUserPrefFile;\n    exports.get                 = PreferencesImpl.manager.get.bind(PreferencesImpl.manager);\n    exports.set                 = PreferencesImpl.manager.set.bind(PreferencesImpl.manager);\n    exports.save                = PreferencesImpl.manager.save.bind(PreferencesImpl.manager);\n    exports.on                  = PreferencesImpl.manager.on.bind(PreferencesImpl.manager);\n    exports.off                 = PreferencesImpl.manager.off.bind(PreferencesImpl.manager);\n    exports.getPreference       = PreferencesImpl.manager.getPreference.bind(PreferencesImpl.manager);\n    exports.getAllPreferences   = PreferencesImpl.manager.getAllPreferences.bind(PreferencesImpl.manager);\n    exports.getExtensionPrefs   = getExtensionPrefs;\n    exports.getViewState        = getViewState;\n    exports.setViewState        = setViewState;\n    exports.addScope            = PreferencesImpl.manager.addScope.bind(PreferencesImpl.manager);\n    exports.stateManager        = PreferencesImpl.stateManager;\n    exports.FileStorage         = PreferencesBase.FileStorage;\n    exports.SETTINGS_FILENAME   = PreferencesImpl.SETTINGS_FILENAME;\n    exports.definePreference    = PreferencesImpl.manager.definePreference.bind(PreferencesImpl.manager);\n    exports.fileChanged         = PreferencesImpl.manager.fileChanged.bind(PreferencesImpl.manager);\n});\n"
  },
  {
    "path": "src/project/FileSyncManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * FileSyncManager is a set of utilities to help track external modifications to the files and folders\n * in the currently open project.\n *\n * Currently, we detect external changes purely by checking file timestamps against the last-sync\n * timestamp recorded on Document. Brackets triggers this check whenever an external change was detected\n * by our native file watchers, and on window focus. We recheck all open Documents, but with file caching\n * the timestamp check is a fast no-op for everything other than files where a watcher change was just\n * notified. If watchers/caching are disabled, we'll essentially check only on window focus, and we'll hit\n * the disk to check every open Document's timestamp every time.\n *\n * FUTURE: Whenever we have a 'project file tree model,' we should manipulate that instead of notifying\n * DocumentManager directly. DocumentManager, the tree UI, etc. then all listen to that model for changes.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var ProjectManager  = require(\"project/ProjectManager\"),\n        DocumentManager = require(\"document/DocumentManager\"),\n        MainViewManager = require(\"view/MainViewManager\"),\n        Async           = require(\"utils/Async\"),\n        Dialogs         = require(\"widgets/Dialogs\"),\n        DefaultDialogs  = require(\"widgets/DefaultDialogs\"),\n        Strings         = require(\"strings\"),\n        StringUtils     = require(\"utils/StringUtils\"),\n        FileUtils       = require(\"file/FileUtils\"),\n        FileSystemError = require(\"filesystem/FileSystemError\");\n\n\n    /**\n     * Guard to spot re-entrancy while syncOpenDocuments() is still in progress\n     * @type {boolean}\n     */\n    var _alreadyChecking = false;\n\n    /**\n     * If true, we should bail from the syncOpenDocuments() process and then re-run it. See\n     * comments in syncOpenDocuments() for how this works.\n     * @type {boolean}\n     */\n    var _restartPending = false;\n\n    /**\n     * @type {Array.<Document>}\n     */\n    var toReload;\n\n    /**\n     * @type {Array.<Document>}\n     */\n    var toClose;\n\n    /**\n     * @type {Array.<{doc: Document, fileTime: number}>}\n     */\n    var editConflicts;\n\n    /**\n     * @type {Array.<{doc: Document, fileTime: number}>}\n     */\n    var deleteConflicts;\n\n\n    /**\n     * Scans all the given Documents for changes on disk, and sorts them into four buckets,\n     * populating the corresponding arrays:\n     *  toReload        - changed on disk; unchanged within Brackets\n     *  toClose         - deleted on disk; unchanged within Brackets\n     *  editConflicts   - changed on disk; also dirty in Brackets\n     *  deleteConflicts - deleted on disk; also dirty in Brackets\n     *\n     * @param {!Array.<Document>} docs\n     * @return {$.Promise}  Resolved when all scanning done, or rejected immediately if there's any\n     *      error while reading file timestamps. Errors are logged but no UI is shown.\n     */\n    function findExternalChanges(docs) {\n\n        toReload = [];\n        toClose = [];\n        editConflicts = [];\n        deleteConflicts = [];\n\n        function checkDoc(doc) {\n            var result = new $.Deferred();\n\n            // Check file timestamp / existence\n\n            if (doc.isUntitled()) {\n                result.resolve();\n            } else if (doc.file.donotWatch) { // Some file might not like to be watched!\n                result.resolve();\n            } else {\n                doc.file.stat(function (err, stat) {\n                    if (!err) {\n                        // Does file's timestamp differ from last sync time on the Document?\n                        var fileTime = stat.mtime.getTime();\n                        if (fileTime !== doc.diskTimestamp.getTime()) {\n                            // If the user has chosen to keep changes that conflict with the\n                            // current state of the file on disk, then do nothing. This means\n                            // that even if the user later undoes back to clean, we won't\n                            // automatically reload the file on window reactivation. We could\n                            // make it do that, but it seems better to be consistent with the\n                            // deletion case below, where it seems clear that you don't want\n                            // to auto-delete the file on window reactivation just because you\n                            // undid back to clean.\n                            if (doc.keepChangesTime !== fileTime) {\n                                if (doc.isDirty) {\n                                    editConflicts.push({doc: doc, fileTime: fileTime});\n                                } else {\n                                    toReload.push(doc);\n                                }\n                            }\n                        }\n                        result.resolve();\n                    } else {\n                        // File has been deleted externally\n                        if (err === FileSystemError.NOT_FOUND) {\n                            // If the user has chosen to keep changes previously, and the file\n                            // has been deleted, then do nothing. Like the case above, this\n                            // means that even if the user later undoes back to clean, we won't\n                            // then automatically delete the file on window reactivation.\n                            // (We use -1 as the \"mod time\" to indicate that the file didn't\n                            // exist, since there's no actual modification time to keep track of\n                            // and -1 isn't a valid mod time for a real file.)\n                            if (doc.keepChangesTime !== -1) {\n                                if (doc.isDirty) {\n                                    deleteConflicts.push({doc: doc, fileTime: -1});\n                                } else {\n                                    toClose.push(doc);\n                                }\n                            }\n                            result.resolve();\n                        } else {\n                            // Some other error fetching metadata: treat as a real error\n                            console.log(\"Error checking modification status of \" + doc.file.fullPath, err);\n                            result.reject();\n                        }\n                    }\n                });\n            }\n\n            return result.promise();\n        }\n\n        // Check all docs in parallel\n        // (fail fast b/c we won't continue syncing if there was any error fetching timestamps)\n        return Async.doInParallel(docs, checkDoc, true);\n    }\n\n    /**\n     * Scans all the files in the working set that do not have Documents (and thus were not scanned\n     * by findExternalChanges()). If any were deleted on disk, removes them from the working set.\n     */\n    function syncUnopenWorkingSet() {\n        // We only care about working set entries that have never been open (have no Document).\n        var unopenWorkingSetFiles = MainViewManager.getWorkingSet(MainViewManager.ALL_PANES).filter(function (wsFile) {\n            return !DocumentManager.getOpenDocumentForPath(wsFile.fullPath);\n        });\n\n        function checkWorkingSetFile(file) {\n            var result = new $.Deferred();\n\n            file.stat(function (err, stat) {\n                if (!err) {\n                    // File still exists\n                    result.resolve();\n                } else {\n                    // File has been deleted externally\n                    if (err === FileSystemError.NOT_FOUND) {\n                        DocumentManager.notifyFileDeleted(file);\n                        result.resolve();\n                    } else {\n                        // Some other error fetching metadata: treat as a real error\n                        console.log(\"Error checking for deletion of \" + file.fullPath, err);\n                        result.reject();\n                    }\n                }\n            });\n            return result.promise();\n        }\n\n        // Check all these files in parallel\n        return Async.doInParallel(unopenWorkingSetFiles, checkWorkingSetFile, false);\n    }\n\n\n    /**\n     * Reloads the Document's contents from disk, discarding any unsaved changes in the editor.\n     *\n     * @param {!Document} doc\n     * @return {$.Promise} Resolved after editor has been refreshed; rejected if unable to load the\n     *      file's new content. Errors are logged but no UI is shown.\n     */\n    function reloadDoc(doc) {\n\n        var promise = FileUtils.readAsText(doc.file);\n\n        promise.done(function (text, readTimestamp) {\n            doc.refreshText(text, readTimestamp);\n        });\n        promise.fail(function (error) {\n            console.log(\"Error reloading contents of \" + doc.file.fullPath, error);\n        });\n        return promise;\n    }\n\n    /**\n     * Reloads all the documents in \"toReload\" silently (no prompts). The operations are all run\n     * in parallel.\n     * @return {$.Promise} Resolved/rejected after all reloads done; will be rejected if any one\n     *      file's reload failed. Errors are logged (by reloadDoc()) but no UI is shown.\n     */\n    function reloadChangedDocs() {\n        // Reload each doc in turn, and once all are (async) done, signal that we're done\n        return Async.doInParallel(toReload, reloadDoc, false);\n    }\n\n    /**\n     * @param {FileError} error\n     * @param {!Document} doc\n     * @return {Dialog}\n     */\n    function showReloadError(error, doc) {\n        return Dialogs.showModalDialog(\n            DefaultDialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_RELOADING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_RELOADING_FILE,\n                StringUtils.breakableUrl(doc.file.fullPath),\n                FileUtils.getFileErrorString(error)\n            )\n        );\n    }\n\n\n    /**\n     * Closes all the documents in \"toClose\" silently (no prompts). Completes synchronously.\n     */\n    function closeDeletedDocs() {\n        toClose.forEach(function (doc) {\n            DocumentManager.notifyFileDeleted(doc.file);\n        });\n    }\n\n\n    /**\n     * Walks through all the documents in \"editConflicts\" & \"deleteConflicts\" and prompts the user\n     * about each one. Processing is sequential: if the user chooses to reload a document, the next\n     * prompt is not shown until after the reload has completed.\n     *\n     * @param {string} title Title of the dialog.\n     * @return {$.Promise} Resolved/rejected after all documents have been prompted and (if\n     *      applicable) reloaded (and any resulting error UI has been dismissed). Rejected if any\n     *      one reload failed.\n     */\n    function presentConflicts(title) {\n\n        var allConflicts = editConflicts.concat(deleteConflicts);\n\n        function presentConflict(docInfo, i) {\n            var result = new $.Deferred(),\n                promise = result.promise(),\n                doc = docInfo.doc,\n                fileTime = docInfo.fileTime;\n\n            // If window has been re-focused, skip all remaining conflicts so the sync can bail & restart\n            if (_restartPending) {\n                result.resolve();\n                return promise;\n            }\n\n            var toClose;\n            var dialogId;\n            var message;\n            var buttons;\n\n            // Prompt UI varies depending on whether the file on disk was modified vs. deleted\n            if (i < editConflicts.length) {\n                toClose = false;\n                dialogId = DefaultDialogs.DIALOG_ID_EXT_CHANGED;\n                message = StringUtils.format(\n                    Strings.EXT_MODIFIED_MESSAGE,\n                    StringUtils.breakableUrl(\n                        ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath)\n                    )\n                );\n                buttons = [\n                    {\n                        className: Dialogs.DIALOG_BTN_CLASS_LEFT,\n                        id:        Dialogs.DIALOG_BTN_DONTSAVE,\n                        text:      Strings.RELOAD_FROM_DISK\n                    },\n                    {\n                        className: Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                        id:        Dialogs.DIALOG_BTN_CANCEL,\n                        text:      Strings.KEEP_CHANGES_IN_EDITOR\n                    }\n                ];\n\n            } else {\n                toClose = true;\n                dialogId = DefaultDialogs.DIALOG_ID_EXT_DELETED;\n                message = StringUtils.format(\n                    Strings.EXT_DELETED_MESSAGE,\n                    StringUtils.breakableUrl(\n                        ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath)\n                    )\n                );\n                buttons = [\n                    {\n                        className: Dialogs.DIALOG_BTN_CLASS_LEFT,\n                        id:        Dialogs.DIALOG_BTN_DONTSAVE,\n                        text:      Strings.CLOSE_DONT_SAVE\n                    },\n                    {\n                        className: Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                        id:        Dialogs.DIALOG_BTN_CANCEL,\n                        text:      Strings.KEEP_CHANGES_IN_EDITOR\n                    }\n                ];\n            }\n\n            Dialogs.showModalDialog(dialogId, title, message, buttons)\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_DONTSAVE) {\n                        if (toClose) {\n                            // Discard - close all editors\n                            DocumentManager.notifyFileDeleted(doc.file);\n                            result.resolve();\n                        } else {\n                            // Discard - load changes from disk\n                            reloadDoc(doc)\n                                .done(function () {\n                                    result.resolve();\n                                })\n                                .fail(function (error) {\n                                    // Unable to load changed version from disk - show error UI\n                                    showReloadError(error, doc)\n                                        .done(function () {\n                                            // After user dismisses, move on to next conflict prompt\n                                            result.reject();\n                                        });\n                                });\n                        }\n\n                    } else {\n                        // Cancel - if user doesn't manually save or close, remember that they\n                        // chose to keep the changes in the editor and don't prompt again unless the\n                        // file changes again\n                        // OR programmatically canceled due to _resetPending - we'll skip all\n                        // remaining files in the conflicts list (see above)\n\n                        // If this wasn't programmatically cancelled, remember that the user\n                        // has accepted conflicting changes as of this file version.\n                        if (!_restartPending) {\n                            doc.keepChangesTime = fileTime;\n                        }\n\n                        result.resolve();\n                    }\n                });\n\n            return promise;\n        }\n\n        // Begin walking through the conflicts, one at a time\n        return Async.doSequentially(allConflicts, presentConflict, false);\n    }\n\n\n\n    /**\n     * Check to see whether any open files have been modified by an external app since the last time\n     * Brackets synced up with the copy on disk (either by loading or saving the file). For clean\n     * files, we silently upate the editor automatically. For files with unsaved changes, we prompt\n     * the user.\n     *\n     * @param {string} title Title to use for document. Default is \"External Changes\".\n     */\n    function syncOpenDocuments(title) {\n\n        title = title || Strings.EXT_MODIFIED_TITLE;\n\n        // We can become \"re-entrant\" if the user leaves & then returns to Brackets before we're\n        // done -- easy if a prompt dialog is left open. Since the user may have left Brackets to\n        // revert some of the disk changes, etc. we want to cancel the current sync and immediately\n        // begin a new one. We let the orig sync run until the user-visible dialog phase, then\n        // bail; if we're already there we programmatically close the dialog to bail right away.\n        if (_alreadyChecking) {\n            _restartPending = true;\n\n            // Close dialog if it was open. This will 'unblock' presentConflict(), which bails back\n            // to us immediately upon seeing _restartPending. We then restart the sync - see below\n            Dialogs.cancelModalDialogIfOpen(DefaultDialogs.DIALOG_ID_EXT_CHANGED);\n            Dialogs.cancelModalDialogIfOpen(DefaultDialogs.DIALOG_ID_EXT_DELETED);\n\n            return;\n        }\n\n        _alreadyChecking = true;\n\n\n        // Syncing proceeds in four phases:\n        //  1) Check all open files for external modifications\n        //  2) Check any other working set entries (that are not open) for deletion, and remove\n        //     from working set if deleted\n        //  3) Refresh all Documents that are clean (if file changed on disk)\n        //  4) Close all Documents that are clean (if file deleted on disk)\n        //  5) Prompt about any Documents that are dirty (if file changed/deleted on disk)\n        // Each phase fully completes (asynchronously) before the next one begins.\n\n\n        // 1) Check for external modifications\n        var allDocs = DocumentManager.getAllOpenDocuments();\n\n        findExternalChanges(allDocs)\n            .done(function () {\n                // 2) Check un-open working set entries for deletion (& \"close\" if needed)\n                syncUnopenWorkingSet()\n                    .always(function () {\n                        // If we were unable to check any un-open files for deletion, silently ignore\n                        // (after logging to console). This doesn't have any bearing on syncing truly\n                        // open Documents (which we've already successfully checked).\n\n                        // 3) Reload clean docs as needed\n                        reloadChangedDocs()\n                            .always(function () {\n                                // 4) Close clean docs as needed\n                                // This phase completes synchronously\n                                closeDeletedDocs();\n\n                                // 5) Prompt for dirty editors (conflicts)\n                                presentConflicts(title)\n                                    .always(function () {\n                                        if (_restartPending) {\n                                            // Restart the sync if needed\n                                            _restartPending = false;\n                                            _alreadyChecking = false;\n                                            syncOpenDocuments();\n                                        } else {\n                                            // We're really done!\n                                            _alreadyChecking = false;\n\n                                            // If we showed a dialog, restore focus to editor\n                                            if (editConflicts.length > 0 || deleteConflicts.length > 0) {\n                                                MainViewManager.focusActivePane();\n                                            }\n\n                                            // (Any errors that ocurred during presentConflicts() have already\n                                            // shown UI & been dismissed, so there's no fail() handler here)\n                                        }\n                                    });\n                            });\n                            // Note: if any auto-reloads failed, we silently ignore (after logging to console)\n                            // and we still continue onto phase 4 and try to process those files anyway.\n                            // (We'll retry the auto-reloads next time window is activated... and evenually\n                            // we'll also be double checking before each Save).\n                    });\n            }).fail(function () {\n                // Unable to fetch timestamps for some reason - silently ignore (after logging to console)\n                // (We'll retry next time window is activated... and evenually we'll also be double\n                // checking before each Save).\n\n                // We can't go on without knowing which files are dirty, so bail now\n                _alreadyChecking = false;\n            });\n\n    }\n\n\n    // Define public API\n    exports.syncOpenDocuments = syncOpenDocuments;\n});\n"
  },
  {
    "path": "src/project/FileTreeView.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: FileTreeView*/\n\n/**\n * This is the view layer (template) for the file tree in the sidebar. It takes a FileTreeViewModel\n * and renders it to the given element using Preact. User actions are signaled via an ActionCreator\n * (in the Flux sense).\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Preact            = require(\"thirdparty/preact\"),\n        Classnames        = require(\"thirdparty/classnames\"),\n        Immutable         = require(\"thirdparty/immutable\"),\n        _                 = require(\"thirdparty/lodash\"),\n        FileUtils         = require(\"file/FileUtils\"),\n        LanguageManager   = require(\"language/LanguageManager\"),\n        FileTreeViewModel = require(\"project/FileTreeViewModel\"),\n        ViewUtils         = require(\"utils/ViewUtils\"),\n        KeyEvent          = require(\"utils/KeyEvent\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\");\n\n    var DOM = Preact.DOM;\n\n    /**\n     * @private\n     * @type {Immutable.Map}\n     *\n     * Stores the file tree extensions for adding classes and icons. The keys of the map\n     * are the \"categories\" of the extensions and values are vectors of the callback functions.\n     */\n    var _extensions = Immutable.Map();\n\n     /**\n     * @private\n     * @type {string}\n     *\n     * Stores the path of the currently dragged item in the filetree.\n     */\n    var _draggedItemPath;\n\n\n    // Constants\n\n    // Time range from first click to second click to invoke renaming.\n    var CLICK_RENAME_MINIMUM  = 500,\n        RIGHT_MOUSE_BUTTON    = 2,\n        LEFT_MOUSE_BUTTON     = 0;\n\n    var INDENTATION_WIDTH     = 10;\n\n    /**\n     * @private\n     *\n     * Returns the name of a file without its extension.\n     *\n     * @param {string} fullname The complete name of the file (not including the rest of the path)\n     * @param {string} extension The file extension\n     * @return {string} The fullname without the extension\n     */\n    function _getName(fullname, extension) {\n        return extension !== \"\" ? fullname.substring(0, fullname.length - extension.length - 1) : fullname;\n    }\n\n    /**\n     * Mixin that allows a component to compute the full path to its directory entry.\n     */\n    var pathComputer = {\n        /**\n         * Computes the full path of the file represented by this input.\n         */\n        myPath: function () {\n            var result = this.props.parentPath + this.props.name;\n\n            // Add trailing slash for directories\n            if (!FileTreeViewModel.isFile(this.props.entry) && _.last(result) !== \"/\") {\n                result += \"/\";\n            }\n\n            return result;\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Gets an appropriate width given the text provided.\n     *\n     * @param {string} text Text to measure\n     * @return {int} Width to use\n     */\n    function _measureText(text) {\n        var measuringElement = $(\"<span />\", { css : { \"position\" : \"absolute\", \"top\" : \"-200px\", \"left\" : \"-1000px\", \"visibility\" : \"hidden\", \"white-space\": \"pre\" } }).appendTo(\"body\");\n        measuringElement.text(\"pW\" + text);\n        var width = measuringElement.width();\n        measuringElement.remove();\n        return width;\n    }\n\n    /**\n     * @private\n     *\n     * Create an appropriate div based \"thickness\" to indent the tree correctly.\n     *\n     * @param {int} depth The depth of the current node.\n     * @return {PreactComponent} The resulting div.\n     */\n    function _createThickness(depth) {\n        return DOM.div({\n            style: {\n                display: \"inline-block\",\n                width: INDENTATION_WIDTH * depth\n            }\n        });\n    }\n\n    /**\n     * @private\n     *\n     * Create, and indent correctly, the arrow icons used for the folders.\n     *\n     * @param {int} depth The depth of the current node.\n     * @return {PreactComponent} The resulting ins.\n     */\n    function _createAlignedIns(depth) {\n        return DOM.ins({\n            className: \"jstree-icon\",\n            style: {\n                marginLeft: INDENTATION_WIDTH * depth\n            }\n        });\n    }\n\n    /**\n     * This is a mixin that provides rename input behavior. It is responsible for taking keyboard input\n     * and invoking the correct action based on that input.\n     */\n    var renameBehavior = {\n        /**\n         * Stop clicks from propagating so that clicking on the rename input doesn't\n         * cause directories to collapse.\n         */\n        handleClick: function (e) {\n            e.stopPropagation();\n            if (e.button !== LEFT_MOUSE_BUTTON) {\n                e.preventDefault();\n            }\n        },\n\n        /**\n         * If the user presses enter or escape, we either successfully complete or cancel, respectively,\n         * the rename or create operation that is underway.\n         */\n        handleKeyDown: function (e) {\n            if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                this.props.actions.cancelRename();\n            } else if (e.keyCode === KeyEvent.DOM_VK_RETURN) {\n                this.props.actions.performRename();\n            }\n        },\n\n        /**\n         * The rename or create operation can be completed or canceled by actions outside of\n         * this component, so we keep the model up to date by sending every update via an action.\n         */\n        handleInput: function (e) {\n            this.props.actions.setRenameValue(this.props.parentPath + this.refs.name.value.trim());\n\n            if (e.keyCode !== KeyEvent.DOM_VK_LEFT &&\n                    e.keyCode !== KeyEvent.DOM_VK_RIGHT) {\n                // update the width of the input field\n                var node = this.refs.name,\n                    newWidth = _measureText(node.value);\n                $(node).width(newWidth);\n            }\n        },\n\n        /**\n         * If we leave the field for any reason, complete the rename.\n         */\n        handleBlur: function () {\n            this.props.actions.performRename();\n        }\n    };\n\n    /**\n     * This is a mixin that provides drag and drop move function.\n     */\n    var dragAndDrop = {\n        handleDrag: function(e) {\n            // Disable drag when renaming\n            if (this.props.entry.get(\"rename\")) {\n                e.preventDefault();\n                e.stopPropagation();\n                return false;\n            }\n\n            // In newer CEF versions, the drag and drop data from the event\n            // (i.e. e.dataTransfer.getData) cannot be used to read data in dragOver event,\n            // so store the drag and drop data in a global variable to read it in the dragOver\n            // event.\n            _draggedItemPath = this.myPath();\n\n            // Pass the dragged item path.\n            e.dataTransfer.setData(\"text\", JSON.stringify({\n                path: _draggedItemPath\n            }));\n\n            this.props.actions.dragItem(this.myPath());\n\n            this.setDragImage(e);\n            e.stopPropagation();\n        },\n        handleDrop: function(e) {\n            var data = JSON.parse(e.dataTransfer.getData(\"text\"));\n\n            this.props.actions.moveItem(data.path, this.myPath());\n            this.setDraggedOver(false);\n\n            this.clearDragTimeout();\n            e.stopPropagation();\n        },\n\n        handleDragEnd: function(e) {\n            this.clearDragTimeout();\n        },\n\n        handleDragOver: function(e) {\n            var data = e.dataTransfer.getData(\"text\"),\n                path;\n\n            if (data) {\n                path = JSON.parse(data).path;\n            } else {\n                path = _draggedItemPath;\n            }\n\n            if (path === this.myPath() || FileUtils.getParentPath(path) === this.myPath()) {\n                e.preventDefault();\n                e.stopPropagation();\n                return;\n            }\n            var self = this;\n            this.setDraggedOver(true);\n\n            // Open the directory tree when item is dragged over a directory\n            if (!this.dragOverTimeout) {\n                this.dragOverTimeout = window.setTimeout(function() {\n                    self.props.actions.setDirectoryOpen(self.myPath(), true);\n                    self.dragOverTimeout = null;\n                }, 800);\n            }\n\n            e.preventDefault(); // Allow the drop\n            e.stopPropagation();\n        },\n\n        handleDragLeave: function(e) {\n            this.setDraggedOver(false);\n            this.clearDragTimeout();\n        },\n\n        clearDragTimeout: function() {\n            if (this.dragOverTimeout) {\n                clearTimeout(this.dragOverTimeout);\n                this.dragOverTimeout = null;\n            }\n        },\n        setDraggedOver: function(draggedOver) {\n            if (this.state.draggedOver !== draggedOver) {\n                this.setState({\n                    draggedOver: draggedOver\n                });\n            }\n        },\n\n        setDragImage: function(e) {\n            var div = window.document.createElement('div');\n            div.textContent = this.props.name;\n            div.classList.add('jstree-dragImage');\n            window.document.body.appendChild(div);\n            e.dataTransfer.setDragImage(div, -10, -10);\n            setTimeout(function() {\n                window.document.body.removeChild(div);\n            }, 0);\n        }\n    };\n\n    /**\n     * @private\n     *\n     * This component presents an input field to the user for renaming a file.\n     *\n     * Props:\n     * * parentPath: the full path of the directory containing this file\n     * * name: the name of the file, including the extension\n     * * actions: the action creator responsible for communicating actions the user has taken\n     */\n    var fileRenameInput = Preact.createFactory(Preact.createClass({\n        mixins: [renameBehavior],\n\n        /**\n         * When this component is displayed, we scroll it into view and select the portion\n         * of the filename that excludes the extension.\n         */\n        componentDidMount: function () {\n            var fullname = this.props.name,\n                extension = LanguageManager.getCompoundFileExtension(fullname);\n\n            var node = this.refs.name;\n            node.setSelectionRange(0, _getName(fullname, extension).length);\n            node.focus(); // set focus on the rename input\n            ViewUtils.scrollElementIntoView($(\"#project-files-container\"), $(node), true);\n        },\n\n        render: function () {\n            var width = _measureText(this.props.name);\n\n            return DOM.input({\n                className: \"jstree-rename-input\",\n                type: \"text\",\n                defaultValue: this.props.name,\n                autoFocus: true,\n                onKeyDown: this.handleKeyDown,\n                onInput: this.handleInput,\n                onClick: this.handleClick,\n                onBlur: this.handleBlur,\n                style: {\n                    width: width\n                },\n                ref: \"name\"\n            });\n        }\n    }));\n\n    /**\n     * @private\n     *\n     * This mixin handles right click (or control click on Mac) action to make a file\n     * the \"context\" object for performing operations like rename.\n     */\n    var contextSettable = {\n\n        /**\n         * Send matching mouseDown events to the action creator as a setContext action.\n         */\n        handleMouseDown: function (e) {\n            e.stopPropagation();\n            if (e.button === RIGHT_MOUSE_BUTTON ||\n                    (this.props.platform === \"mac\" && e.button === LEFT_MOUSE_BUTTON && e.ctrlKey)) {\n                this.props.actions.setContext(this.myPath());\n                e.preventDefault();\n                return;\n            }\n            // Return true only for mouse down in rename mode.\n            if (this.props.entry.get(\"rename\")) {\n                return;\n            }\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Returns true if the value is defined (used in `.filter`)\n     *\n     * @param {Object} value value to test\n     * @return {boolean} true if value is defined\n     */\n    function isDefined(value) {\n        return value !== undefined;\n    }\n\n    /**\n     * Mixin for components that support the \"icons\" and \"addClass\" extension points.\n     * `fileNode` and `directoryNode` support this.\n     */\n    var extendable = {\n\n        /**\n         * Calls the icon providers to get the collection of icons (most likely just one) for\n         * the current file or directory.\n         *\n         * @return {Array.<PreactComponent>} icon components to render\n         */\n        getIcons: function () {\n            var result,\n                extensions = this.props.extensions;\n\n            if (extensions && extensions.get(\"icons\")) {\n                var data = this.getDataForExtension();\n                result = extensions.get(\"icons\").map(function (callback) {\n                    try {\n                        var result = callback(data);\n                        if (result && !Preact.isValidElement(result)) {\n                            result = Preact.DOM.span({\n                                dangerouslySetInnerHTML: {\n                                    __html: $(result)[0].outerHTML\n                                }\n                            });\n                        }\n                        return result;  // by this point, returns either undefined or a Preact object\n                    } catch (e) {\n                        console.error(\"Exception thrown in FileTreeView icon provider: \" + e, e.stack);\n                    }\n                }).filter(isDefined).toArray();\n            }\n\n            if (!result || result.length === 0) {\n                result = [DOM.ins({\n                    className: \"jstree-icon\"\n                }, \" \")];\n            }\n            return result;\n        },\n\n        /**\n         * Calls the addClass providers to get the classes (in string form) to add for the current\n         * file or directory.\n         *\n         * @param {string} classes Initial classes for this node\n         * @return {string} classes for the current node\n         */\n        getClasses: function (classes) {\n            var extensions = this.props.extensions;\n\n            if (extensions && extensions.get(\"addClass\")) {\n                var data = this.getDataForExtension();\n                classes = classes + \" \" + extensions.get(\"addClass\").map(function (callback) {\n                    try {\n                        return callback(data);\n                    } catch (e) {\n                        console.error(\"Exception thrown in FileTreeView addClass provider: \" + e, e.stack);\n                    }\n                }).filter(isDefined).toArray().join(\" \");\n            }\n\n            return classes;\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Component to display a file in the tree.\n     *\n     * Props:\n     * * parentPath: the full path of the directory containing this file\n     * * name: the name of the file, including the extension\n     * * entry: the object with the relevant metadata for the file (whether it's selected or is the context file)\n     * * actions: the action creator responsible for communicating actions the user has taken\n     * * extensions: registered extensions for the file tree\n     * * forceRender: causes the component to run render\n     */\n    var fileNode = Preact.createFactory(Preact.createClass({\n        mixins: [contextSettable, pathComputer, extendable, dragAndDrop],\n\n        /**\n         * Ensures that we always have a state object.\n         */\n        getInitialState: function () {\n            return {\n                clickTimer: null\n            };\n        },\n\n        /**\n         * Thanks to immutable objects, we can just do a start object identity check to know\n         * whether or not we need to re-render.\n         */\n        shouldComponentUpdate: function (nextProps, nextState) {\n            return nextProps.forceRender ||\n                this.props.entry !== nextProps.entry ||\n                this.props.extensions !== nextProps.extensions;\n        },\n\n        /**\n         * If this node is newly selected, scroll it into view. Also, move the selection or\n         * context boxes as appropriate.\n         */\n        componentDidUpdate: function (prevProps, prevState) {\n            var wasSelected = prevProps.entry.get(\"selected\"),\n                isSelected  = this.props.entry.get(\"selected\");\n\n            if (isSelected && !wasSelected) {\n                // TODO: This shouldn't really know about project-files-container\n                // directly. It is probably the case that our Preact tree should actually\n                // start with project-files-container instead of just the interior of\n                // project-files-container and then the file tree will be one self-contained\n                // functional unit.\n                ViewUtils.scrollElementIntoView($(\"#project-files-container\"), $(Preact.findDOMNode(this)), true);\n            } else if (!isSelected && wasSelected && this.state.clickTimer !== null) {\n                this.clearTimer();\n            }\n        },\n\n        clearTimer: function () {\n            if (this.state.clickTimer !== null) {\n                window.clearTimeout(this.state.clickTimer);\n                this.setState({\n                    clickTimer: null\n                });\n            }\n        },\n\n        startRename: function () {\n            if (!this.props.entry.get(\"rename\")) {\n                this.props.actions.startRename(this.myPath());\n            }\n            this.clearTimer();\n        },\n\n        /**\n         * When the user clicks on the node, we'll either select it or, if they've clicked twice\n         * with a bit of delay in between, we'll invoke the `startRename` action.\n         */\n        handleClick: function (e) {\n            // If we're renaming, allow the click to go through to the rename input.\n            if (this.props.entry.get(\"rename\")) {\n                e.stopPropagation();\n                return;\n            }\n\n            if (e.button !== LEFT_MOUSE_BUTTON) {\n                return;\n            }\n\n            if (this.props.entry.get(\"selected\") && !e.ctrlKey) {\n                if (this.state.clickTimer === null && !this.props.entry.get(\"rename\")) {\n                    var timer = window.setTimeout(this.startRename, CLICK_RENAME_MINIMUM);\n                    this.setState({\n                        clickTimer: timer\n                    });\n                }\n            } else {\n                var language = LanguageManager.getLanguageForPath(this.myPath()),\n                    doNotOpen = false;\n                if (language && language.isBinary() && \"image\" !== language.getId() &&\n                        FileUtils.shouldOpenInExternalApplication(\n                            FileUtils.getFileExtension(this.myPath()).toLowerCase()\n                        )\n                    ) {\n                    doNotOpen = true;\n                }\n                this.props.actions.setSelected(this.myPath(), doNotOpen);\n            }\n            e.stopPropagation();\n            e.preventDefault();\n        },\n\n        /**\n         * When the user double clicks, we will select this file and add it to the working\n         * set (via the `selectInWorkingSet` action.)\n         */\n        handleDoubleClick: function () {\n            if (!this.props.entry.get(\"rename\")) {\n                if (this.state.clickTimer !== null) {\n                    this.clearTimer();\n                }\n                if (FileUtils.shouldOpenInExternalApplication(\n                        FileUtils.getFileExtension(this.myPath()).toLowerCase()\n                      )) {\n                    this.props.actions.openWithExternalApplication(this.myPath());\n                    return;\n                }\n                this.props.actions.selectInWorkingSet(this.myPath());\n            }\n        },\n\n        /**\n         * Create the data object to pass to extensions.\n         *\n         * @return {!{name:string, isFile:boolean, fullPath:string}} Data for extensions\n         */\n        getDataForExtension: function () {\n            return {\n                name: this.props.name,\n                isFile: true,\n                fullPath: this.myPath()\n            };\n        },\n\n        render: function () {\n            var fullname = this.props.name,\n                extension = LanguageManager.getCompoundFileExtension(fullname),\n                name = _getName(fullname, extension);\n\n            // React automatically wraps content in a span element whereas preact doesn't, so do it manually\n            if (name) {\n                name = DOM.span({}, name);\n            }\n\n            if (extension) {\n                extension = DOM.span({\n                    className: \"extension\"\n                }, \".\" + extension);\n            }\n\n            var nameDisplay,\n                cx = Classnames;\n\n            var fileClasses = cx({\n                'jstree-clicked selected-node': this.props.entry.get(\"selected\"),\n                'context-node': this.props.entry.get(\"context\")\n            });\n\n            var liArgs = [\n                {\n                    className: this.getClasses(\"jstree-leaf\"),\n                    onClick: this.handleClick,\n                    onMouseDown: this.handleMouseDown,\n                    onDoubleClick: this.handleDoubleClick,\n                    draggable: true,\n                    onDragStart: this.handleDrag\n                },\n                DOM.ins({\n                    className: \"jstree-icon\"\n                })\n            ];\n\n            var thickness = _createThickness(this.props.depth);\n\n            if (this.props.entry.get(\"rename\")) {\n                liArgs.push(thickness);\n                nameDisplay = fileRenameInput({\n                    actions: this.props.actions,\n                    entry: this.props.entry,\n                    name: this.props.name,\n                    parentPath: this.props.parentPath\n                });\n            } else {\n                // Need to flatten the argument list because getIcons returns an array\n                var aArgs = _.flatten([{\n                    href: \"#\",\n                    className: fileClasses\n                }, thickness, this.getIcons(), name, extension]);\n                nameDisplay = DOM.a.apply(DOM.a, aArgs);\n            }\n\n            liArgs.push(nameDisplay);\n\n            return DOM.li.apply(DOM.li, liArgs);\n        }\n    }));\n\n    /**\n     * @private\n     *\n     * Creates a comparison function for sorting a directory's contents with directories\n     * appearing before files.\n     *\n     * We're sorting the keys of the directory (the names) based partly on the values,\n     * so we use a closure to capture the map itself so that we can look up the\n     * values as needed.\n     *\n     * @param {Immutable.Map} contents The directory's contents\n     * @return {function(string,string)} Comparator that sorts directories first.\n     */\n    function _buildDirsFirstComparator(contents) {\n        function _dirsFirstCompare(a, b) {\n            var aIsFile = FileTreeViewModel.isFile(contents.get(a)),\n                bIsFile = FileTreeViewModel.isFile(contents.get(b));\n\n            if (!aIsFile && bIsFile) {\n                return -1;\n            } else if (aIsFile && !bIsFile) {\n                return 1;\n            } else {\n                return FileUtils.compareFilenames(a, b);\n            }\n        }\n        return _dirsFirstCompare;\n    }\n\n    /**\n     * @private\n     *\n     * Sort a directory either alphabetically or with subdirectories listed first.\n     *\n     * @param {Immutable.Map} contents the directory's contents\n     * @param {boolean} dirsFirst true to sort subdirectories first\n     * @return {Immutable.Map} sorted mapping\n     */\n    function _sortDirectoryContents(contents, dirsFirst) {\n        if (dirsFirst) {\n            return contents.keySeq().sort(_buildDirsFirstComparator(contents));\n        } else {\n            return contents.keySeq().sort(FileUtils.compareFilenames);\n        }\n    }\n\n    // Forward references to keep JSLint happy.\n    var directoryNode, directoryContents;\n\n    /**\n     * @private\n     *\n     * Component that provides the input for renaming a directory.\n     *\n     * Props:\n     * * parentPath: the full path of the directory containing this file\n     * * name: the name of the file, including the extension\n     * * actions: the action creator responsible for communicating actions the user has taken\n     */\n    var directoryRenameInput = Preact.createFactory(Preact.createClass({\n        mixins: [renameBehavior],\n\n        /**\n         * When this component is displayed, we scroll it into view and select the folder name.\n         */\n        componentDidMount: function () {\n            var fullname = this.props.name;\n\n            var node = this.refs.name;\n            node.setSelectionRange(0, fullname.length);\n            node.focus(); // set focus on the rename input\n            ViewUtils.scrollElementIntoView($(\"#project-files-container\"), $(node), true);\n        },\n\n        render: function () {\n            var width = _measureText(this.props.name);\n\n            return DOM.input({\n                className: \"jstree-rename-input\",\n                type: \"text\",\n                defaultValue: this.props.name,\n                autoFocus: true,\n                onKeyDown: this.handleKeyDown,\n                onInput: this.handleInput,\n                onBlur: this.handleBlur,\n                style: {\n                    width: width\n                },\n                onClick: this.handleClick,\n                ref: \"name\"\n            });\n        }\n    }));\n\n    /**\n     * @private\n     *\n     * Displays a directory (but not its contents) in the tree.\n     *\n     * Props:\n     * * parentPath: the full path of the directory containing this file\n     * * name: the name of the directory\n     * * entry: the object with the relevant metadata for the file (whether it's selected or is the context file)\n     * * actions: the action creator responsible for communicating actions the user has taken\n     * * sortDirectoriesFirst: whether the directories should be displayed first when listing the contents of a directory\n     * * extensions: registered extensions for the file tree\n     * * forceRender: causes the component to run render\n     */\n    directoryNode = Preact.createFactory(Preact.createClass({\n        mixins: [contextSettable, pathComputer, extendable, dragAndDrop],\n\n        getInitialState: function() {\n            return {\n                draggedOver: false\n            };\n        },\n\n        /**\n         * We need to update this component if the sort order changes or our entry object\n         * changes. Thanks to immutability, if any of the directory contents change, our\n         * entry object will change.\n         */\n        shouldComponentUpdate: function (nextProps, nextState) {\n            return nextProps.forceRender ||\n                this.props.entry !== nextProps.entry ||\n                this.props.sortDirectoriesFirst !== nextProps.sortDirectoriesFirst ||\n                this.props.extensions !== nextProps.extensions ||\n                (nextState !== undefined && this.state.draggedOver !== nextState.draggedOver);\n        },\n\n        /**\n         * If you click on a directory, it will toggle between open and closed.\n         */\n        handleClick: function (event) {\n            if (this.props.entry.get(\"rename\")) {\n                event.stopPropagation();\n                return;\n            }\n\n            if (event.button !== LEFT_MOUSE_BUTTON) {\n                return;\n            }\n\n            var isOpen = this.props.entry.get(\"open\"),\n                setOpen = isOpen ? false : true;\n\n            if (event.metaKey || event.ctrlKey) {\n                // ctrl-alt-click toggles this directory and its children\n                if (event.altKey) {\n                    if (setOpen) {\n                        // when opening, we only open the immediate children because\n                        // opening a whole subtree could be really slow (consider\n                        // a `node_modules` directory, for example).\n                        this.props.actions.toggleSubdirectories(this.myPath(), setOpen);\n                        this.props.actions.setDirectoryOpen(this.myPath(), setOpen);\n                    } else {\n                        // When closing, we recursively close the whole subtree.\n                        this.props.actions.closeSubtree(this.myPath());\n                    }\n                } else {\n                    // ctrl-click toggles the sibling directories\n                    this.props.actions.toggleSubdirectories(this.props.parentPath, setOpen);\n                }\n            } else {\n                // directory toggle with no modifier\n                this.props.actions.setDirectoryOpen(this.myPath(), setOpen);\n            }\n            event.stopPropagation();\n            event.preventDefault();\n        },\n\n        /**\n         * Create the data object to pass to extensions.\n         *\n         * @return {{name: {string}, isFile: {boolean}, fullPath: {string}}} Data for extensions\n         */\n        getDataForExtension: function () {\n            return {\n                name: this.props.name,\n                isFile: false,\n                fullPath: this.myPath()\n            };\n        },\n\n        render: function () {\n            var entry = this.props.entry,\n                nodeClass,\n                childNodes,\n                children = entry.get(\"children\"),\n                isOpen = entry.get(\"open\");\n\n            if (isOpen && children) {\n                nodeClass = \"open\";\n                childNodes = directoryContents({\n                    depth: this.props.depth + 1,\n                    parentPath: this.myPath(),\n                    contents: children,\n                    extensions: this.props.extensions,\n                    actions: this.props.actions,\n                    forceRender: this.props.forceRender,\n                    platform: this.props.platform,\n                    sortDirectoriesFirst: this.props.sortDirectoriesFirst\n                });\n            } else {\n                nodeClass = \"closed\";\n            }\n\n            var nameDisplay,\n                cx = Classnames;\n\n            var directoryClasses = cx({\n                'jstree-clicked sidebar-selection': entry.get(\"selected\"),\n                'context-node': entry.get(\"context\")\n            });\n\n            var nodeClasses = \"jstree-\" + nodeClass;\n            if (this.state.draggedOver) {\n                nodeClasses += \" jstree-draggedOver\";\n            }\n\n            var liArgs = [\n                {\n                    className: this.getClasses(nodeClasses),\n                    onClick: this.handleClick,\n                    onMouseDown: this.handleMouseDown,\n                    draggable: true,\n                    onDragStart: this.handleDrag,\n                    onDrop: this.handleDrop,\n                    onDragEnd: this.handleDragEnd,\n                    onDragOver: this.handleDragOver,\n                    onDragLeave: this.handleDragLeave\n                },\n                _createAlignedIns(this.props.depth)\n            ];\n\n            var thickness = _createThickness(this.props.depth);\n\n            if (entry.get(\"rename\")) {\n                liArgs.push(thickness);\n                nameDisplay = directoryRenameInput({\n                    actions: this.props.actions,\n                    entry: entry,\n                    name: this.props.name,\n                    parentPath: this.props.parentPath\n                });\n            } else {\n                // React automatically wraps content in a span element whereas preact doesn't, so do it manually\n                if (this.props.name) {\n                    var name = DOM.span({}, this.props.name);\n                }\n\n                // Need to flatten the arguments because getIcons returns an array\n                var aArgs = _.flatten([{\n                    href: \"#\",\n                    className: directoryClasses\n                }, thickness, this.getIcons(), name]);\n                nameDisplay = DOM.a.apply(DOM.a, aArgs);\n            }\n\n            liArgs.push(nameDisplay);\n            liArgs.push(childNodes);\n\n            return DOM.li.apply(DOM.li, liArgs);\n        }\n    }));\n\n    /**\n     * @private\n     *\n     * Displays the contents of a directory.\n     *\n     * Props:\n     * * isRoot: whether this directory is the root of the tree\n     * * parentPath: the full path of the directory containing this file\n     * * contents: the map of name/child entry pairs for this directory\n     * * actions: the action creator responsible for communicating actions the user has taken\n     * * sortDirectoriesFirst: whether the directories should be displayed first when listing the contents of a directory\n     * * extensions: registered extensions for the file tree\n     * * forceRender: causes the component to run render\n     */\n    directoryContents = Preact.createFactory(Preact.createClass({\n\n        /**\n         * Need to re-render if the sort order or the contents change.\n         */\n        shouldComponentUpdate: function (nextProps, nextState) {\n            return nextProps.forceRender ||\n                this.props.contents !== nextProps.contents ||\n                this.props.sortDirectoriesFirst !== nextProps.sortDirectoriesFirst ||\n                this.props.extensions !== nextProps.extensions;\n        },\n\n        render: function () {\n            var extensions = this.props.extensions,\n                iconClass = extensions && extensions.get(\"icons\") ? \"jstree-icons\" : \"jstree-no-icons\",\n                ulProps = this.props.isRoot ? {\n                    className: \"jstree-brackets jstree-no-dots \" + iconClass\n                } : null;\n\n            var contents = this.props.contents,\n                namesInOrder = _sortDirectoryContents(contents, this.props.sortDirectoriesFirst);\n\n            return DOM.ul(ulProps, namesInOrder.map(function (name) {\n                var entry = contents.get(name);\n\n                if (FileTreeViewModel.isFile(entry)) {\n                    return fileNode({\n                        depth: this.props.depth,\n                        parentPath: this.props.parentPath,\n                        name: name,\n                        entry: entry,\n                        actions: this.props.actions,\n                        extensions: this.props.extensions,\n                        forceRender: this.props.forceRender,\n                        platform: this.props.platform,\n                        key: name\n                    });\n                } else {\n                    return directoryNode({\n                        depth: this.props.depth,\n                        parentPath: this.props.parentPath,\n                        name: name,\n                        entry: entry,\n                        actions: this.props.actions,\n                        extensions: this.props.extensions,\n                        sortDirectoriesFirst: this.props.sortDirectoriesFirst,\n                        forceRender: this.props.forceRender,\n                        platform: this.props.platform,\n                        key: name\n                    });\n                }\n            }.bind(this)).toArray());\n        }\n    }));\n\n    /**\n     * Displays the absolutely positioned box for the selection or context in the\n     * file tree. Its position is determined by passed-in info about the scroller in which\n     * the tree resides and the top of the selected node (as reported by the node itself).\n     *\n     * Props:\n     * * selectionViewInfo: Immutable.Map with width, scrollTop, scrollLeft and offsetTop for the tree container\n     * * visible: should this be visible now\n     * * selectedClassName: class name applied to the element that is selected\n     */\n    var fileSelectionBox = Preact.createFactory(Preact.createClass({\n        /**\n         * When the component has updated in the DOM, reposition it to where the currently\n         * selected node is located now.\n         */\n        componentDidUpdate: function () {\n            if (!this.props.visible) {\n                return;\n            }\n\n            var node = Preact.findDOMNode(this),\n                selectedNode = $(node.parentNode).find(this.props.selectedClassName),\n                selectionViewInfo = this.props.selectionViewInfo;\n\n            if (selectedNode.length === 0) {\n                return;\n            }\n\n            node.style.top = selectedNode.offset().top - selectionViewInfo.get(\"offsetTop\") + selectionViewInfo.get(\"scrollTop\") - selectedNode.position().top + \"px\";\n        },\n\n        render: function () {\n            var selectionViewInfo = this.props.selectionViewInfo,\n                left = selectionViewInfo.get(\"scrollLeft\"),\n                width = selectionViewInfo.get(\"width\"),\n                scrollWidth = selectionViewInfo.get(\"scrollWidth\");\n\n            return DOM.div({\n                style: {\n                    overflow: \"auto\",\n                    left: left,\n                    display: this.props.visible ? \"block\" : \"none\"\n                },\n                className: this.props.className\n            });\n        }\n    }));\n\n    /**\n     * On Windows and Linux, the selection bar in the tree does not extend over the scroll bar.\n     * The selectionExtension sits on top of the scroll bar to make the selection bar appear to span the\n     * whole width of the sidebar.\n     *\n     * Props:\n     * * selectionViewInfo: Immutable.Map with width, scrollTop, scrollLeft and offsetTop for the tree container\n     * * visible: should this be visible now\n     * * selectedClassName: class name applied to the element that is selected\n     * * className: class to be applied to the extension element\n     */\n    var selectionExtension = Preact.createFactory(Preact.createClass({\n        /**\n         * When the component has updated in the DOM, reposition it to where the currently\n         * selected node is located now.\n         */\n        componentDidUpdate: function () {\n            if (!this.props.visible) {\n                return;\n            }\n\n            var node = Preact.findDOMNode(this),\n                selectedNode = $(node.parentNode).find(this.props.selectedClassName).closest(\"li\"),\n                selectionViewInfo = this.props.selectionViewInfo;\n\n            if (selectedNode.length === 0) {\n                return;\n            }\n\n            var top = selectedNode.offset().top,\n                baselineHeight = node.dataset.initialHeight,\n                height = baselineHeight,\n                scrollerTop = selectionViewInfo.get(\"offsetTop\");\n\n            if (!baselineHeight) {\n                baselineHeight = $(node).outerHeight();\n                node.dataset.initialHeight = baselineHeight;\n                height = baselineHeight;\n            }\n\n            // Check to see if the selection is completely scrolled out of view\n            // to prevent the extension from appearing in the working set area.\n            if (top < scrollerTop - baselineHeight) {\n                node.style.display = \"none\";\n                return;\n            }\n\n            node.style.display = \"block\";\n\n            // The selectionExtension sits on top of the other nodes\n            // so we need to shrink it if only part of the selection node is visible\n            if (top < scrollerTop) {\n                var difference = scrollerTop - top;\n                top += difference;\n                height = parseInt(height, 10);\n                height -= difference;\n            }\n\n            node.style.top = top + \"px\";\n            node.style.height = height + \"px\";\n            node.style.left = selectionViewInfo.get(\"width\") - $(node).outerWidth() + \"px\";\n        },\n\n        render: function () {\n            return DOM.div({\n                style: {\n                    display: this.props.visible ? \"block\" : \"none\"\n                },\n                className: this.props.className\n            });\n        }\n    }));\n\n    /**\n     * @private\n     *\n     * This is the root component of the file tree.\n     *\n     * Props:\n     * * treeData: the root of the tree (an Immutable.Map with the contents of the project root)\n     * * sortDirectoriesFirst: whether the directories should be displayed first when listing the contents of a directory\n     * * parentPath: the full path of the directory containing this file\n     * * actions: the action creator responsible for communicating actions the user has taken\n     * * extensions: registered extensions for the file tree\n     * * forceRender: causes the component to run render\n     * * platform: platform that Brackets is running on\n     */\n    var fileTreeView = Preact.createFactory(Preact.createClass({\n\n        /**\n         * Update for any change in the tree data or directory sorting preference.\n         */\n        shouldComponentUpdate: function (nextProps, nextState) {\n            return nextProps.forceRender ||\n                this.props.treeData !== nextProps.treeData ||\n                this.props.sortDirectoriesFirst !== nextProps.sortDirectoriesFirst ||\n                this.props.extensions !== nextProps.extensions ||\n                this.props.selectionViewInfo !== nextProps.selectionViewInfo;\n        },\n\n        handleDrop: function(e) {\n            var data = JSON.parse(e.dataTransfer.getData(\"text\"));\n            this.props.actions.moveItem(data.path, this.props.parentPath);\n            e.stopPropagation();\n        },\n\n        /**\n         * Allow the Drop\n         */\n        handleDragOver: function(e) {\n            e.preventDefault();\n        },\n\n        render: function () {\n            var selectionBackground = fileSelectionBox({\n                ref: \"selectionBackground\",\n                selectionViewInfo: this.props.selectionViewInfo,\n                className: \"filetree-selection\",\n                visible: this.props.selectionViewInfo.get(\"hasSelection\"),\n                selectedClassName: \".selected-node\",\n                forceUpdate: true\n            }),\n                contextBackground = fileSelectionBox({\n                    ref: \"contextBackground\",\n                    selectionViewInfo: this.props.selectionViewInfo,\n                    className: \"filetree-context\",\n                    visible: this.props.selectionViewInfo.get(\"hasContext\"),\n                    selectedClassName: \".context-node\",\n                    forceUpdate: true\n                }),\n                extensionForSelection = selectionExtension({\n                    selectionViewInfo: this.props.selectionViewInfo,\n                    selectedClassName: \".selected-node\",\n                    visible: this.props.selectionViewInfo.get(\"hasSelection\"),\n                    forceUpdate: true,\n                    className: \"filetree-selection-extension\"\n                }),\n                extensionForContext = selectionExtension({\n                    selectionViewInfo: this.props.selectionViewInfo,\n                    selectedClassName: \".context-node\",\n                    visible: this.props.selectionViewInfo.get(\"hasContext\"),\n                    forceUpdate: true,\n                    className: \"filetree-context-extension\"\n                }),\n                contents = directoryContents({\n                    isRoot: true,\n                    depth: 1,\n                    parentPath: this.props.parentPath,\n                    sortDirectoriesFirst: this.props.sortDirectoriesFirst,\n                    contents: this.props.treeData,\n                    extensions: this.props.extensions,\n                    actions: this.props.actions,\n                    forceRender: this.props.forceRender,\n                    platform: this.props.platform\n                }),\n                args = {\n                    onDrop: this.handleDrop,\n                    onDragOver: this.handleDragOver\n                };\n\n\n            return DOM.div(\n                args,\n                contents,\n                selectionBackground,\n                contextBackground,\n                extensionForSelection,\n                extensionForContext\n            );\n        }\n    }));\n\n    /**\n     * Renders the file tree to the given element.\n     *\n     * @param {DOMNode|jQuery} element Element in which to render this file tree\n     * @param {FileTreeViewModel} viewModel the data container\n     * @param {Directory} projectRoot Directory object from which the fullPath of the project root is extracted\n     * @param {ActionCreator} actions object with methods used to communicate events that originate from the user\n     * @param {boolean} forceRender Run render on the entire tree (useful if an extension has new data that it needs rendered)\n     * @param {string} platform mac, win, linux\n     */\n    function render(element, viewModel, projectRoot, actions, forceRender, platform) {\n        if (!projectRoot) {\n            return;\n        }\n\n        Preact.render(fileTreeView({\n            treeData: viewModel.treeData,\n            selectionViewInfo: viewModel.selectionViewInfo,\n            sortDirectoriesFirst: viewModel.sortDirectoriesFirst,\n            parentPath: projectRoot.fullPath,\n            actions: actions,\n            extensions: _extensions,\n            platform: platform,\n            forceRender: forceRender\n        }),\n              element);\n    }\n\n    /**\n     * @private\n     *\n     * Add an extension for the given category (icons, addClass).\n     *\n     * @param {string} category Category to which the extension is being added\n     * @param {function} callback The extension function itself\n     */\n    function _addExtension(category, callback) {\n        if (!callback || typeof callback !== \"function\") {\n            console.error(\"Attempt to add FileTreeView\", category, \"extension without a callback function\");\n            return;\n        }\n        var callbackList = _extensions.get(category);\n        if (!callbackList) {\n            callbackList = Immutable.List();\n        }\n        callbackList = callbackList.push(callback);\n        _extensions = _extensions.set(category, callbackList);\n    }\n\n    /**\n     * @see {@link ProjectManager::#addIconProvider}\n     */\n    function addIconProvider(callback) {\n        _addExtension(\"icons\", callback);\n    }\n\n    /**\n     * @see {@link ProjectManager::#addClassesProvider}\n     */\n    function addClassesProvider(callback) {\n        _addExtension(\"addClass\", callback);\n    }\n\n    // Private API for testing\n    exports._sortFormattedDirectory = _sortDirectoryContents;\n    exports._fileNode = fileNode;\n    exports._directoryNode = directoryNode;\n    exports._directoryContents = directoryContents;\n    exports._fileTreeView = fileTreeView;\n\n    // Public API\n    exports.addIconProvider = addIconProvider;\n    exports.addClassesProvider = addClassesProvider;\n    exports.render = render;\n});\n"
  },
  {
    "path": "src/project/FileTreeViewModel.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: FileTreeViewModel*/\n\n/**\n * The view model (or a Store in the Flux terminology) used by the file tree.\n *\n * Many of the view model's methods are implemented by pure functions, which can be\n * helpful for composability. Many of the methods commit the new treeData and send a\n * change event when they're done whereas the functions do not do this.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Immutable           = require(\"thirdparty/immutable\"),\n        _                   = require(\"thirdparty/lodash\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        FileUtils           = require(\"file/FileUtils\");\n\n    // Constants\n    var EVENT_CHANGE = \"change\";\n\n    /**\n     * Determine if an entry from the treeData map is a file.\n     *\n     * @param {Immutable.Map} entry entry to test\n     * @return {boolean} true if this is a file and not a directory\n     */\n    function isFile(entry) {\n        return entry.get(\"children\") === undefined;\n    }\n\n    /**\n     * @constructor\n     *\n     * Contains the treeData used to generate the file tree and methods used to update that\n     * treeData.\n     *\n     * Instances dispatch the following events:\n     * - \"change\" (FileTreeViewModel.EVENT_CHANGE constant): Fired any time there's a change that should be reflected in the view.\n     */\n    function FileTreeViewModel() {\n        // For convenience in callbacks, make a bound version of this method so that we can\n        // just refer to it as this._commit when passing in a callback.\n        this._commit = this._commit.bind(this);\n    }\n    EventDispatcher.makeEventDispatcher(FileTreeViewModel.prototype);\n\n    /**\n     * @type {boolean}\n     *\n     * Preference for whether directories should all be sorted to the top of listings\n     */\n    FileTreeViewModel.prototype.sortDirectoriesFirst = false;\n\n    /**\n     * @type {Immutable.Map}\n     * @private\n     *\n     * The data for the tree. Some notes about its structure:\n     *\n     * * It starts with a Map for the project root's contents.\n     * * Each directory entry has a `children` key.\n     *     * `children` will be null if the directory has not been loaded\n     *     * An `open` key denotes whether the directory is open\n     * * Most file entries are just empty maps\n     *     * They can have flags like selected, context, rename, create with state information for the tree\n     */\n    FileTreeViewModel.prototype._treeData = Immutable.Map();\n\n    Object.defineProperty(FileTreeViewModel.prototype, \"treeData\", {\n        get: function () {\n            return this._treeData;\n        }\n    });\n\n    /**\n     * @private\n     * @type {Immutable.Map}\n     * Selection view information determines how the selection bar appears.\n     *\n     * * width: visible width of the selection area\n     * * scrollTop: current scroll position.\n     * * scrollLeft: current horizontal scroll position\n     * * offsetTop: top of the scroller element\n     * * hasSelection: is the selection bar visible?\n     * * hasContext: is the context bar visible?\n     */\n    FileTreeViewModel.prototype._selectionViewInfo = Immutable.Map({\n        width: 0,\n        scrollTop: 0,\n        scrollLeft: 0,\n        offsetTop: 0,\n        hasContext: false,\n        hasSelection: false\n    });\n\n    Object.defineProperty(FileTreeViewModel.prototype, \"selectionViewInfo\", {\n        get: function () {\n            return this._selectionViewInfo;\n        }\n    });\n\n    /**\n     * @private\n     *\n     * If the project root changes, we reset the tree data so that everything will be re-read.\n     */\n    FileTreeViewModel.prototype._rootChanged = function () {\n        this._treeData = Immutable.Map();\n    };\n\n    /**\n     * @private\n     *\n     * The FileTreeViewModel is like a database for storing the directory contents and its\n     * state moves atomically from one value to the next. This method stores the next version\n     * of the state, if it has changed, and triggers a change event so that the UI can update.\n     *\n     * @param {?Immutable.Map} treeData new treeData state\n     * @param {?Immutable.Map} selectionViewInfo updated information for the selection/context bars\n     */\n    FileTreeViewModel.prototype._commit = function (treeData, selectionViewInfo) {\n        var changed = false;\n        if (treeData && treeData !== this._treeData) {\n            this._treeData = treeData;\n            changed = true;\n        }\n\n        if (selectionViewInfo && selectionViewInfo !== this._selectionViewInfo) {\n            this._selectionViewInfo = selectionViewInfo;\n            changed = true;\n        }\n        if (changed) {\n            this.trigger(EVENT_CHANGE);\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Converts a project-relative file path into an object path array suitable for\n     * `Immutable.Map.getIn` and `Immutable.Map.updateIn`.\n     *\n     * The root path is \"\".\n     *\n     * @param {Immutable.Map} treeData\n     * @param {string} path project relative path to the file or directory. Can include trailing slash.\n     * @return {Array.<string>|null} Returns null if the path can't be found in the tree, otherwise an array of strings representing the path through the object.\n     */\n    function _filePathToObjectPath(treeData, path) {\n        if (path === null) {\n            return null;\n        } else if (path === \"\") {\n            return [];\n        }\n\n        var parts = path.split(\"/\"),\n            part = parts.shift(),\n            result = [],\n            node;\n\n        // Step through the parts of the path and the treeData object simultaneously\n        while (part) {\n            // We hit the end of the tree without finding our object, so return null\n            if (!treeData) {\n                return null;\n            }\n\n            node = treeData.get(part);\n\n            // The name represented by `part` isn't in the tree, so return null.\n            if (node === undefined) {\n                return null;\n            }\n\n            // We've verified this part, so store it.\n            result.push(part);\n\n            // Pull the next part of the path\n            part = parts.shift();\n\n            // If we haven't passed the end of the path string, then the object we've got in hand\n            // *should* be a directory. Confirm that and add `children` to the path to move down\n            // to the next directory level.\n            if (part) {\n                treeData = node.get(\"children\");\n                if (treeData) {\n                    result.push(\"children\");\n                }\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * @private\n     *\n     * See `FileTreeViewModel.isFilePathVisible`\n     */\n    function _isFilePathVisible(treeData, path) {\n        if (path === null) {\n            return null;\n        } else if (path === \"\") {\n            return true;\n        }\n\n        var parts = path.split(\"/\"),\n            part = parts.shift(),\n            result = [],\n            node;\n\n        while (part) {\n            if (treeData === null) {\n                return false;\n            }\n            node = treeData.get(part);\n            if (node === undefined) {\n                return null;\n            }\n            result.push(part);\n            part = parts.shift();\n            if (part) {\n                if (!node.get(\"open\")) {\n                    return false;\n                }\n                treeData = node.get(\"children\");\n                if (treeData) {\n                    result.push(\"children\");\n                }\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Determines if a given file path is visible within the tree.\n     *\n     * For detailed documentation on how the loop works, see `_filePathToObjectPath` which\n     * follows the same pattern. This differs from that function in that this one checks for\n     * the open state of directories and has a different return value.\n     *\n     * @param {string} path project relative file path\n     * @return {boolean|null} true if the given path is currently visible in the tree, null if the given path is not present in the tree.\n     */\n    FileTreeViewModel.prototype.isFilePathVisible = function (path) {\n        return _isFilePathVisible(this._treeData, path);\n    };\n\n    /**\n     * Determines if a given path has been loaded.\n     *\n     * @param {string} path project relative file or directory path\n     * @return {boolean} true if the path has been loaded\n     */\n    FileTreeViewModel.prototype.isPathLoaded = function (path) {\n        var objectPath = _filePathToObjectPath(this._treeData, path);\n\n        if (!objectPath) {\n            return false;\n        }\n\n        // If it's a directory, make sure that its children are loaded\n        if (_.last(path) === \"/\") {\n            var directory = this._treeData.getIn(objectPath);\n            if (!directory.get(\"children\") || directory.get(\"notFullyLoaded\")) {\n                return false;\n            }\n        }\n\n        return true;\n    };\n\n    /**\n     * @private\n     *\n     * See `FileTreeViewModel.getOpenNodes`.\n     */\n    function _getOpenNodes(treeData, projectRootPath) {\n        var openNodes = [];\n\n        function addNodesAtDepth(treeData, parent, depth) {\n            if (!treeData) {\n                return;\n            }\n\n            treeData.forEach(function (value, key) {\n                if (isFile(value)) {\n                    return;\n                }\n\n                var directoryPath = parent + key + \"/\";\n\n                if (value.get(\"open\")) {\n                    var nodeList = openNodes[depth];\n                    if (!nodeList) {\n                        nodeList = openNodes[depth] = [];\n                    }\n                    nodeList.push(directoryPath);\n                    addNodesAtDepth(value.get(\"children\"), directoryPath, depth + 1);\n                }\n            });\n        }\n\n        // start at the top of the tree and the first array element\n        addNodesAtDepth(treeData, projectRootPath, 0);\n        return openNodes;\n    }\n\n    /**\n     * @private\n     * TODO: merge with _getOpenNodes?!\n     * See `FileTreeViewModel.getChildNodes`.\n     */\n    function _getChildDirectories(treeData, projectRootPath) {\n        var childDirectories = [];\n\n        function addNodesAtDepth(treeData, parent, depth) {\n            if (!treeData) {\n                return;\n            }\n\n            treeData.forEach(function (value, key) {\n                if (!isFile(value)) {\n                    var directoryPath = key + \"/\";\n\n                    childDirectories.push(directoryPath);\n                }\n            });\n        }\n\n        // start at the top of the tree and the first array element\n        addNodesAtDepth(treeData, projectRootPath, 0);\n        return childDirectories;\n    }\n\n    /**\n     * Creates an array of arrays where each entry of the top-level array has an array\n     * of paths that are at the same depth in the tree. All of the paths are full paths.\n     *\n     * This is used for saving the current set of open nodes to the preferences system\n     * for restoring on project open.\n     *\n     * @param {string} projectRootPath Full path to the project root\n     * @return {Array.<Array.<string>>} Array of array of full paths, organized by depth in the tree.\n     */\n    FileTreeViewModel.prototype.getOpenNodes = function (projectRootPath) {\n        return _getOpenNodes(this._treeData, projectRootPath);\n    };\n\n    FileTreeViewModel.prototype.getChildDirectories = function (parent) {\n        var treeData = this._treeData,\n            objectPath = _filePathToObjectPath(treeData, parent);\n\n        if (!objectPath) {\n            return;\n        }\n\n        var children;\n        if (objectPath.length === 0) {\n            // this is the root of the tree\n            children = this._treeData;\n        } else {\n            objectPath.push(\"children\");\n            children = this._treeData.getIn(objectPath);\n        }\n\n        return _getChildDirectories(children, parent);\n    };\n\n    /**\n     * @private\n     *\n     * The Immutable package does not have a `setIn` method, which is what this effectively\n     * provides. This is a simple function that does an `updateIn` on treeData, replacing\n     * the current value with the new one.\n     *\n     * @param {Immutable.Map} treeData\n     * @param {Array.<string>} objectPath path to object that should be replaced\n     * @param {Immutable.Map} newValue new value to provide at that path\n     * @return {Immutable.Map} updated treeData\n     */\n    function _setIn(treeData, objectPath, newValue) {\n        return treeData.updateIn(objectPath, function (oldValue) {\n            return newValue;\n        });\n    }\n\n    /**\n     * @private\n     *\n     * See `FileTreeViewModel.moveMarker`\n     */\n    function _moveMarker(treeData, markerName, oldPath, newPath) {\n        var objectPath;\n\n        if (newPath) {\n            objectPath = _filePathToObjectPath(treeData, newPath);\n        }\n\n        var newTreeData = treeData;\n\n        if (oldPath && oldPath !== newPath) {\n            var lastObjectPath = _filePathToObjectPath(treeData, oldPath);\n            if (lastObjectPath) {\n                newTreeData = newTreeData.updateIn(lastObjectPath, function (entry) {\n                    return entry.delete(markerName);\n                });\n            }\n        }\n\n        if (newPath && objectPath && objectPath.length !== 0) {\n            newTreeData = newTreeData.updateIn(objectPath, function (entry) {\n                return entry.set(markerName, true);\n            });\n        }\n\n        return newTreeData;\n    }\n\n    /**\n     * Moves a boolean marker flag from one file path to another.\n     *\n     * @param {string} markerName Name of the flag to set (for example, \"selected\")\n     * @param {string|null} oldPath Project relative file path with the location of the marker to move, or null if it's not being moved from elsewhere in the tree\n     * @param {string|null} newPath Project relative file path with where to place the marker, or null if the marker is being removed from the tree\n     */\n    FileTreeViewModel.prototype.moveMarker = function (markerName, oldPath, newPath) {\n        var newTreeData = _moveMarker(this._treeData, markerName, oldPath, newPath),\n            selectionViewInfo = this._selectionViewInfo;\n\n        if (markerName === \"selected\") {\n            selectionViewInfo = selectionViewInfo.set(\"hasSelection\", !!newPath);\n        } else if (markerName === \"context\") {\n            selectionViewInfo = selectionViewInfo.set(\"hasContext\", !!newPath);\n        }\n        this._commit(newTreeData, selectionViewInfo);\n    };\n\n    /**\n     * Changes the path of the item at the `currentPath` to `newPath`.\n     *\n     * @param {string} currentPath project relative file path to the current item\n     * @param {string} newPath project relative new path to give the item\n     */\n    FileTreeViewModel.prototype.renameItem = function (oldPath, newPath) {\n        var treeData = this._treeData,\n            oldObjectPath = _filePathToObjectPath(treeData, oldPath),\n            newDirectoryPath = FileUtils.getParentPath(newPath),\n            newObjectPath = _filePathToObjectPath(treeData, newDirectoryPath);\n\n        if (!oldObjectPath || !newObjectPath) {\n            return;\n        }\n\n        var originalName = _.last(oldObjectPath),\n            newName = FileUtils.getBaseName(newPath),\n            currentObject;\n\n        // Back up to the parent directory\n        oldObjectPath.pop();\n\n        // Remove the oldPath\n        treeData = treeData.updateIn(oldObjectPath, function (directory) {\n            currentObject = directory.get(originalName);\n            directory = directory.delete(originalName);\n            return directory;\n        });\n\n        // Add the newPath\n\n        // If the new directory is not loaded, create a not fully loaded directory there,\n        // so that we can add the new item as a child of new directory\n        if (!this.isPathLoaded(newDirectoryPath)) {\n            treeData = treeData.updateIn(newObjectPath, _createNotFullyLoadedDirectory);\n        }\n\n        // If item moved to root directory, objectPath should not have \"children\",\n        // otherwise the objectPath should have \"children\"\n        if (newObjectPath.length > 0) {\n            newObjectPath.push(\"children\");\n        }\n\n        treeData = treeData.updateIn(newObjectPath, function (children) {\n            return children.set(newName, currentObject);\n        });\n\n        this._commit(treeData);\n    };\n\n\n    /**\n     * @private\n     *\n     * See `FileTreeViewModel.setDirectoryOpen`\n     */\n    function _setDirectoryOpen(treeData, path, open) {\n        var objectPath = _filePathToObjectPath(treeData, path),\n            directory = treeData.getIn(objectPath);\n\n        if (!objectPath) {\n            return {\n                needsLoading: true,\n                treeData: treeData\n            };\n        }\n\n        if (isFile(directory)) {\n            return;\n        }\n\n        var alreadyOpen = directory.get(\"open\") === true;\n\n        if ((alreadyOpen && open) || (!alreadyOpen && !open)) {\n            return;\n        }\n\n        treeData = treeData.updateIn(objectPath, function (directory) {\n            if (open) {\n                return directory.set(\"open\", true);\n            } else {\n                return directory.delete(\"open\");\n            }\n        });\n\n        if (open && (directory.get(\"children\") === null || directory.get(\"notFullyLoaded\"))) {\n            return {\n                needsLoading: true,\n                treeData: treeData\n            };\n        }\n        return {\n            needsLoading: false,\n            treeData: treeData\n        };\n    }\n\n    /**\n     * Sets the directory at the given path to open or closed. Returns true if the directory\n     * contents need to be loaded.\n     *\n     * @param {string} path Project relative file path to the directory\n     * @param {boolean} open True to open the directory\n     * @return {boolean} true if the directory contents need to be loaded.\n     */\n    FileTreeViewModel.prototype.setDirectoryOpen = function (path, open) {\n        var result = _setDirectoryOpen(this._treeData, path, open);\n        if (result && result.treeData) {\n            this._commit(result.treeData);\n        }\n        return result ? result.needsLoading : false;\n    };\n\n    /**\n     * Returns the object at the given file path.\n     *\n     * @param {string} path Path to the object\n     * @return {Immutable.Map=} directory or file object from the tree. Null if it's not found.\n     */\n    FileTreeViewModel.prototype._getObject = function (path) {\n        var objectPath = _filePathToObjectPath(this._treeData, path);\n        if (!objectPath) {\n            return null;\n        }\n        return this._treeData.getIn(objectPath);\n    };\n\n    /**\n     * Closes a subtree path, given by an object path.\n     *\n     * @param {Immutable.Map} directory Current directory\n     * @return {Immutable.Map} new directory\n     */\n    function _closeSubtree(directory) {\n        directory = directory.delete(\"open\");\n\n        var children = directory.get(\"children\");\n        if (children) {\n            children.keySeq().forEach(function (name) {\n                var subdir = children.get(name);\n                if (!isFile(subdir)) {\n                    subdir = _closeSubtree(subdir);\n                    children = children.set(name, subdir);\n                }\n            });\n        }\n\n        directory = directory.set(\"children\", children);\n        return directory;\n    }\n\n    /**\n     * Closes the directory at path and recursively closes all of its children.\n     *\n     * @param {string} path Path of subtree to close\n     */\n    FileTreeViewModel.prototype.closeSubtree = function (path) {\n        var treeData = this._treeData,\n            subtreePath = _filePathToObjectPath(treeData, path);\n\n        if (!subtreePath) {\n            return;\n        }\n\n        var directory = treeData.getIn(subtreePath);\n\n        directory = _closeSubtree(directory);\n        treeData = _setIn(treeData, subtreePath, directory);\n        this._commit(treeData);\n    };\n\n    /**\n     * @private\n     *\n     * Takes an array of file system entries and merges them into the children map\n     * of a directory in the view model treeData.\n     *\n     * @param {Immutable.Map} children current children in the directory\n     * @param {Array.<FileSystemEntry>} contents FileSystemEntry objects currently in the directory\n     * @return {Immutable.Map} updated children\n     */\n    function _mergeContentsIntoChildren(children, contents) {\n\n        // We keep track of the names we've seen among the current directory entries to make\n        // it easy to spot the names that we *haven't* seen (in other words, files that have\n        // been deleted).\n        var keysSeen = [];\n\n        children = children.withMutations(function (children) {\n\n            // Loop through the directory entries\n            contents.forEach(function (entry) {\n                keysSeen.push(entry.name);\n\n                var match = children.get(entry.name);\n                if (match) {\n                    // Confirm that a name that used to represent a file and now represents a\n                    // directory (or vice versa) isn't what we've encountered here. If we have\n                    // hit this situation, pretend the current child of treeData doesn't exist\n                    // so we can replace it.\n                    var matchIsFile = isFile(match);\n                    if (matchIsFile !== entry.isFile) {\n                        match = undefined;\n                    }\n                }\n\n                // We've got a new entry that we need to add.\n                if (!match) {\n                    if (entry.isFile) {\n                        children.set(entry.name, Immutable.Map());\n                    } else {\n                        children.set(entry.name, Immutable.Map({\n                            children: null\n                        }));\n                    }\n                }\n            });\n\n            // Look at the list of names that we currently have in the treeData that no longer\n            // appear in the directory and delete those.\n            var currentEntries = children.keySeq().toJS(),\n                deletedEntries = _.difference(currentEntries, keysSeen);\n\n            deletedEntries.forEach(function (name) {\n                children.delete(name);\n            });\n        });\n        return children;\n    }\n\n    /**\n     * @private\n     *\n     * Creates a directory object (or updates an existing directory object) to look like one\n     * that has not yet been loaded, but in which we want to start displaying entries.\n     * @param {Immutable.Map=} directory Directory entry to update\n     * @return {Immutable.Map} New or updated directory object\n     */\n    function _createNotFullyLoadedDirectory(directory) {\n        if (!directory) {\n            return Immutable.Map({\n                notFullyLoaded: true,\n                children: Immutable.Map()\n            });\n        }\n        return directory.merge({\n            notFullyLoaded: true,\n            children: Immutable.Map()\n        });\n    }\n\n    /**\n     * @private\n     *\n     * Creates the directories necessary to display the given path, even if those directories\n     * do not yet exist in the tree and have not been loaded.\n     *\n     * @param {Immutable.Map} treeData\n     * @param {string} path Path to the final directory to be added in the tree\n     * @return {{treeData: Immutable.Map, objectPath: Array.<string>}} updated treeData and object path to the created object\n     */\n    function _createIntermediateDirectories(treeData, path) {\n        var objectPath = [],\n            result = {\n                objectPath: objectPath,\n                treeData: treeData\n            },\n            treePointer = treeData;\n\n        if (path === \"\") {\n            return result;\n        }\n\n        var parts = path.split(\"/\"),\n            part = parts.shift(),\n            node;\n\n        while (part) {\n            if (treePointer === null) {\n                return null;\n            }\n            node = treePointer.get(part);\n            objectPath.push(part);\n\n            // This directory is missing, so create it.\n            if (node === undefined) {\n                treeData = treeData.updateIn(objectPath, _createNotFullyLoadedDirectory);\n                node = treeData.getIn(objectPath);\n            }\n\n            part = parts.shift();\n            if (part) {\n                treePointer = node.get(\"children\");\n\n                if (treePointer) {\n                    objectPath.push(\"children\");\n                } else {\n\n                    // The directory is there, but the directory hasn't been loaded.\n                    // Update the directory to be a `notFullyLoaded` directory.\n                    treeData = treeData.updateIn(objectPath, _createNotFullyLoadedDirectory);\n                    objectPath.push(\"children\");\n                    treePointer = treeData.getIn(objectPath);\n                }\n            }\n        }\n\n        result.treeData = treeData;\n        return result;\n    }\n\n    /**\n     * Updates the directory at the given path with the new contents. If the parent directories\n     * of this directory have not been loaded yet, they will be created. This allows directories\n     * to be loaded in any order.\n     *\n     * @param {string} Project relative path to the directory that is being updated.\n     * @param {Array.<FileSystemEntry>} Current contents of the directory\n     */\n    FileTreeViewModel.prototype.setDirectoryContents = function (path, contents) {\n        path = FileUtils.stripTrailingSlash(path);\n\n        var intermediate = _createIntermediateDirectories(this._treeData, path),\n            objectPath = intermediate.objectPath,\n            treeData = intermediate.treeData;\n\n        if (objectPath === null) {\n            return;\n        }\n\n        var directory = treeData.getIn(objectPath),\n            children = directory;\n\n        // The root directory doesn't need this special handling.\n        if (path !== \"\") {\n\n            // The user of this API passed in a path to a file rather than a directory.\n            // Perhaps this should be an exception?\n            if (isFile(directory)) {\n                return;\n            }\n\n            // If the directory had been created previously as `notFullyLoaded`, we can\n            // remove that flag now because this is the step that is loading the directory.\n            if (directory.get(\"notFullyLoaded\")) {\n                directory = directory.delete(\"notFullyLoaded\");\n            }\n\n            if (!directory.get(\"children\")) {\n                directory = directory.set(\"children\", Immutable.Map());\n            }\n\n            treeData = _setIn(treeData, objectPath, directory);\n\n            objectPath.push(\"children\");\n            children = directory.get(\"children\");\n        }\n\n        children = _mergeContentsIntoChildren(children, contents);\n        treeData = _setIn(treeData, objectPath, children);\n        this._commit(treeData);\n    };\n\n    /**\n     * @private\n     *\n     * Opens the directories along the provided path.\n     *\n     * @param {Immutable.Map} treeData\n     * @param {string} path Path to open\n     */\n    function _openPath(treeData, path) {\n        var objectPath = _filePathToObjectPath(treeData, path);\n\n        function setOpen(node) {\n            return node.set(\"open\", true);\n        }\n\n        while (objectPath && objectPath.length) {\n            var node = treeData.getIn(objectPath);\n            if (isFile(node)) {\n                objectPath.pop();\n            } else {\n                if (!node.get(\"open\")) {\n                    treeData = treeData.updateIn(objectPath, setOpen);\n                }\n                objectPath.pop();\n                if (objectPath.length) {\n                    objectPath.pop();\n                }\n            }\n        }\n\n        return treeData;\n    }\n\n    /**\n     * Opens the directories along the given path.\n     *\n     * @param {string} path Project-relative path\n     */\n    FileTreeViewModel.prototype.openPath = function (path) {\n        this._commit(_openPath(this._treeData, path));\n    };\n\n    /**\n     * @private\n     *\n     * See FileTreeViewModel.createPlaceholder\n     */\n    function _createPlaceholder(treeData, basedir, name, isFolder, options) {\n        options = options || {};\n        var parentPath = _filePathToObjectPath(treeData, basedir);\n\n        if (!parentPath) {\n            return;\n        }\n\n        var newObject = {\n        };\n\n        if (!options.notInCreateMode) {\n            newObject.creating = true;\n        }\n\n        if (isFolder) {\n            // If we're creating a folder, then we know it's empty.\n            // But if we're not in create mode, (we're adding a folder based on an\n            // FS event), we don't know anything about the new directory's children.\n            if (options.notInCreateMode) {\n                newObject.children = null;\n            } else {\n                newObject.children = Immutable.Map();\n            }\n        }\n\n        var newFile = Immutable.Map(newObject);\n\n        if (!options.doNotOpen) {\n            treeData = _openPath(treeData, basedir);\n        }\n        if (parentPath.length > 0) {\n            var childrenPath = _.clone(parentPath);\n            childrenPath.push(\"children\");\n\n            treeData = treeData.updateIn(childrenPath, function (children) {\n                return children.set(name, newFile);\n            });\n        } else {\n            treeData = treeData.set(name, newFile);\n        }\n        return treeData;\n    }\n\n    /**\n     * Creates a placeholder file or directory that appears in the tree so that the user\n     * can provide a name for the new entry.\n     *\n     * @param {string} basedir Directory that contains the new file or folder\n     * @param {string} name Initial name to give the new entry\n     * @param {boolean} isFolder true if the entry being created is a folder\n     */\n    FileTreeViewModel.prototype.createPlaceholder = function (basedir, name, isFolder) {\n        var treeData = _createPlaceholder(this._treeData, basedir, name, isFolder);\n        this._commit(treeData);\n    };\n\n    /**\n     * @private\n     *\n     * See FileTreeViewModel.deleteAtPath\n     */\n    function _deleteAtPath(treeData, path) {\n        var objectPath = _filePathToObjectPath(treeData, path);\n\n        if (!objectPath) {\n            return;\n        }\n\n        var originalName = _.last(objectPath);\n\n        // Back up to the parent directory\n        objectPath.pop();\n\n        treeData = treeData.updateIn(objectPath, function (directory) {\n            directory = directory.delete(originalName);\n            return directory;\n        });\n\n        return treeData;\n    }\n\n    /**\n     * Deletes the entry at the given path.\n     *\n     * @param {string} path Project-relative path to delete\n     */\n    FileTreeViewModel.prototype.deleteAtPath = function (path) {\n        var treeData = _deleteAtPath(this._treeData, path);\n        if (treeData) {\n            this._commit(treeData);\n        }\n    };\n\n    /**\n     * @private\n     *\n     * Adds a timestamp to an entry (much like the \"touch\" command) to force a given entry\n     * to rerender.\n     */\n    function _addTimestamp(item) {\n        return item.set(\"_timestamp\", new Date().getTime());\n    }\n\n    /**\n     * @private\n     *\n     * Sets/updates the timestamp on the file paths listed in the `changed` array.\n     *\n     * @param {Immutable.Map} treeData\n     * @param {Array.<string>} changed list of changed project-relative file paths\n     * @return {Immutable.Map} revised treeData\n     */\n    function _markAsChanged(treeData, changed) {\n        changed.forEach(function (filePath) {\n            var objectPath = _filePathToObjectPath(treeData, filePath);\n            if (objectPath) {\n                treeData = treeData.updateIn(objectPath, _addTimestamp);\n            }\n        });\n        return treeData;\n    }\n\n    /**\n     * @private\n     *\n     * Adds entries at the paths listed in the `added` array. Directories should have a trailing slash.\n     *\n     * @param {Immutable.Map} treeData\n     * @param {Array.<string>} added list of new project-relative file paths\n     * @return {Immutable.Map} revised treeData\n     */\n    function _addNewEntries(treeData, added) {\n        added.forEach(function (filePath) {\n            var isFolder = _.last(filePath) === \"/\";\n\n            filePath = isFolder ? filePath.substr(0, filePath.length - 1) : filePath;\n\n            var parentPath = FileUtils.getDirectoryPath(filePath),\n                parentObjectPath = _filePathToObjectPath(treeData, parentPath),\n                basename = FileUtils.getBaseName(filePath);\n\n            if (parentObjectPath) {\n                // Verify that the children are loaded\n                var childrenPath = _.clone(parentObjectPath);\n                childrenPath.push(\"children\");\n                if (treeData.getIn(childrenPath) === null) {\n                    return;\n                }\n\n                treeData = _createPlaceholder(treeData, parentPath, basename, isFolder, {\n                    notInCreateMode: true,\n                    doNotOpen: true\n                });\n            }\n        });\n\n        return treeData;\n    }\n\n    /**\n     * Applies changes to the tree. The `changes` object can have one or more of the following keys which all\n     * have arrays of project-relative paths as their values:\n     *\n     * * `changed`: entries that have changed in some way that should be re-rendered\n     * * `added`: new entries that need to appear in the tree\n     * * `removed`: entries that have been deleted from the tree\n     *\n     * @param {{changed: Array.<string>=, added: Array.<string>=, removed: Array.<string>=}}\n     */\n    FileTreeViewModel.prototype.processChanges = function (changes) {\n        var treeData = this._treeData;\n\n        if (changes.changed) {\n            treeData = _markAsChanged(treeData, changes.changed);\n        }\n\n        if (changes.added) {\n            treeData = _addNewEntries(treeData, changes.added);\n        }\n\n        if (changes.removed) {\n            changes.removed.forEach(function (path) {\n                treeData = _deleteAtPath(treeData, path);\n            });\n        }\n\n        this._commit(treeData);\n    };\n\n    /**\n     * Makes sure that the directory exists. This will create a directory object (unloaded)\n     * if the directory does not already exist. A change message is also fired in that case.\n     *\n     * This is useful for file system events which can refer to a directory that we don't\n     * know about already.\n     *\n     * @param {string} path Project-relative path to the directory\n     */\n    FileTreeViewModel.prototype.ensureDirectoryExists = function (path) {\n        var treeData          = this._treeData,\n            pathWithoutSlash  = FileUtils.stripTrailingSlash(path),\n            parentPath        = FileUtils.getDirectoryPath(pathWithoutSlash),\n            name              = pathWithoutSlash.substr(parentPath.length),\n            targetPath        = [];\n\n        if (parentPath) {\n            targetPath = _filePathToObjectPath(treeData, parentPath);\n            if (!targetPath) {\n                return;\n            }\n            targetPath.push(\"children\");\n            if (!treeData.getIn(targetPath)) {\n                return;\n            }\n        }\n\n        targetPath.push(name);\n\n        if (treeData.getIn(targetPath)) {\n            return;\n        }\n\n        treeData = _setIn(treeData, targetPath, Immutable.Map({\n            children: null\n        }));\n\n        this._commit(treeData);\n    };\n\n    /**\n     * Sets the value of the `sortDirectoriesFirst` flag which tells to view that directories\n     * should be listed before the alphabetical listing of files.\n     *\n     * @param {boolean} sortDirectoriesFirst True if directories should be displayed first\n     */\n    FileTreeViewModel.prototype.setSortDirectoriesFirst = function (sortDirectoriesFirst) {\n        if (sortDirectoriesFirst !== this.sortDirectoriesFirst) {\n            this.sortDirectoriesFirst = sortDirectoriesFirst;\n            this.trigger(EVENT_CHANGE);\n        }\n    };\n\n    /**\n     * Sets the width of the selection bar.\n     *\n     * @param {int} width New width\n     */\n    FileTreeViewModel.prototype.setSelectionWidth = function (width) {\n        var selectionViewInfo = this._selectionViewInfo;\n        selectionViewInfo = selectionViewInfo.set(\"width\", width);\n        this._commit(null, selectionViewInfo);\n    };\n\n    /**\n     * Sets the scroll position of the file tree to help position the selection bar.\n     * SPECIAL CASE NOTE: this does not trigger a change event because this data is\n     * explicitly set in the rendering process (see ProjectManager._renderTree).\n     *\n     * @param {int} scrollWidth width of the tree content\n     * @param {int} scrollTop Scroll position\n     * @param {int=} scrollLeft Horizontal scroll position\n     * @param {int=} offsetTop top of the scroller\n     */\n    FileTreeViewModel.prototype.setSelectionScrollerInfo = function (scrollWidth, scrollTop, scrollLeft, offsetTop) {\n        this._selectionViewInfo = this._selectionViewInfo.set(\"scrollWidth\", scrollWidth);\n        this._selectionViewInfo = this._selectionViewInfo.set(\"scrollTop\", scrollTop);\n\n        if (scrollLeft !== undefined) {\n            this._selectionViewInfo = this._selectionViewInfo.set(\"scrollLeft\", scrollLeft);\n        }\n\n        if (offsetTop !== undefined) {\n            this._selectionViewInfo = this._selectionViewInfo.set(\"offsetTop\", offsetTop);\n        }\n        // Does not emit change event. See SPECIAL CASE NOTE in docstring above.\n    };\n\n    // Private API\n    exports.EVENT_CHANGE          = EVENT_CHANGE;\n    exports._filePathToObjectPath = _filePathToObjectPath;\n    exports._isFilePathVisible    = _isFilePathVisible;\n    exports._createPlaceholder    = _createPlaceholder;\n\n    // Public API\n    exports.isFile            = isFile;\n    exports.FileTreeViewModel = FileTreeViewModel;\n});\n"
  },
  {
    "path": "src/project/FileViewController.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Responsible for coordinating file selection between views by permitting only one view\n * to show the current file selection at a time. Currently, only WorkingSetView and\n * ProjectManager can show file selection. In general the WorkingSetView takes higher\n * priority until the user selects a file in the ProjectManager.\n *\n * Events dispatched:\n * - documentSelectionFocusChange - indicates a document change has caused the focus to\n *   change between the working set and file tree.\n *\n * - fileViewFocusChange - indicates the selection focus has changed between the working\n *   set and the project tree, but the document selection has NOT changed\n *\n * Current file selection rules in views:\n * - select a file in WorkingSetView > select in WorkingSetView\n * - add a file to the WorkingSetView > select in WorkingSetView\n * - select a file in ProjectManager > select in ProjectManager\n * - open a file from places other than the WorkingSetView or ProjectManager >\n *       select file in WorkignSetView if its in the working set, otherwise select in ProjectManager\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Commands            = require(\"command/Commands\"),\n        DeprecationWarning  = require(\"utils/DeprecationWarning\");\n\n    /**\n     * Tracks whether a \"currentFileChange\" notification occured due to a call to\n     * openAndSelectDocument.\n     * @see #openAndSelectDocument\n     * @private\n     */\n    var _curDocChangedDueToMe = false;\n    var WORKING_SET_VIEW = \"WorkingSetView\";\n    var PROJECT_MANAGER = \"ProjectManager\";\n\n    /**\n     * @private\n     * @see #getFileSelectionFocus\n     */\n    var _fileSelectionFocus = PROJECT_MANAGER;\n\n    // Due to circular dependencies, not safe to call on() directly\n    /**\n     * Change the doc selection to the working set when ever a new file is added to the working set\n     */\n    EventDispatcher.on_duringInit(MainViewManager, \"workingSetAdd\", function (event, addedFile) {\n        _fileSelectionFocus = WORKING_SET_VIEW;\n        exports.trigger(\"documentSelectionFocusChange\");\n    });\n\n    /**\n     * Update the file selection focus whenever the contents of the editor area change\n     */\n    EventDispatcher.on_duringInit(MainViewManager, \"currentFileChange\", function (event, file, paneId) {\n        var perfTimerName;\n        if (!_curDocChangedDueToMe) {\n            // The the cause of the doc change was not openAndSelectDocument, so pick the best fileSelectionFocus\n            perfTimerName = PerfUtils.markStart(\"FileViewController._oncurrentFileChange():\\t\" + (file ? (file.fullPath) : \"(no open file)\"));\n            if (file && MainViewManager.findInWorkingSet(paneId,  file.fullPath) !== -1) {\n                _fileSelectionFocus = WORKING_SET_VIEW;\n            } else {\n                _fileSelectionFocus = PROJECT_MANAGER;\n            }\n        }\n\n        exports.trigger(\"documentSelectionFocusChange\");\n\n        if (!_curDocChangedDueToMe) {\n            PerfUtils.addMeasurement(perfTimerName);\n        }\n    });\n\n    /**\n     * @private\n     * @param {string=} paneId - the Pane to activate\n     */\n    function _activatePane(paneId) {\n        if (paneId) {\n            MainViewManager.setActivePaneId(paneId);\n        } else {\n            MainViewManager.focusActivePane();\n        }\n        // If fullPath corresonds to the current doc being viewed then opening the file won't\n        // trigger a currentFileChange event, so we need to trigger a documentSelectionFocusChange\n        // in this case to signify the selection focus has changed even though the current document has not.\n        exports.trigger(\"documentSelectionFocusChange\");\n    }\n\n    /**\n     * Modifies the selection focus in the project side bar. A file can either be selected\n     * in the working set (the open files) or in the file tree, but not both.\n     * @param {String} fileSelectionFocus - either PROJECT_MANAGER or WORKING_SET_VIEW\n     */\n    function setFileViewFocus(fileSelectionFocus) {\n        if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {\n            console.error(\"Bad parameter passed to FileViewController.setFileViewFocus\");\n            return;\n        }\n\n        if (_fileSelectionFocus !== fileSelectionFocus) {\n            _fileSelectionFocus = fileSelectionFocus;\n            exports.trigger(\"fileViewFocusChange\");\n        }\n    }\n\n    /**\n     * Opens a document if it's not open and selects the file in the UI corresponding to\n     * fileSelectionFocus\n     * @param {!fullPath} fullPath - full path of the document to open\n     * @param {string} fileSelectionFocus - (WORKING_SET_VIEW || PROJECT_MANAGER)\n     * @param {string} paneId - pane in which to open the document\n     * @return {$.Promise}\n     */\n    function openAndSelectDocument(fullPath, fileSelectionFocus, paneId) {\n        var result,\n            curDocChangedDueToMe = _curDocChangedDueToMe;\n\n        function _getDerivedPaneContext() {\n\n            function _secondPaneContext() {\n                return (window.event.ctrlKey || window.event.metaKey) && window.event.altKey ? MainViewManager.SECOND_PANE : null;\n            }\n\n            function _firstPaneContext() {\n                return (window.event.ctrlKey || window.event.metaKey) ? MainViewManager.FIRST_PANE : null;\n            }\n\n            return window.event && (_secondPaneContext() || _firstPaneContext());\n        }\n\n        if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {\n            console.error(\"Bad parameter passed to FileViewController.openAndSelectDocument\");\n            return;\n        }\n\n        // Opening files are asynchronous and we want to know when this function caused a file\n        // to open so that _fileSelectionFocus is set appropriatly. _curDocChangedDueToMe is set here\n        // and checked in the currentFileChange handler\n        _curDocChangedDueToMe = true;\n\n        _fileSelectionFocus = fileSelectionFocus;\n\n\n        paneId = (paneId || _getDerivedPaneContext() || MainViewManager.ACTIVE_PANE);\n\n        // If fullPath corresonds to the current doc being viewed then opening the file won't\n        // trigger a currentFileChange event, so we need to trigger a documentSelectionFocusChange\n        // in this case to signify the selection focus has changed even though the current document has not.\n        var currentPath = MainViewManager.getCurrentlyViewedPath(paneId);\n        if (currentPath === fullPath) {\n            _activatePane(paneId);\n            result = (new $.Deferred()).resolve().promise();\n        } else {\n            result = CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath,\n                                                                 paneId: paneId});\n        }\n\n        // clear after notification is done\n        result.always(function () {\n            _curDocChangedDueToMe = curDocChangedDueToMe;\n        });\n\n        return result;\n    }\n\n    /**\n     * Opens the specified document if it's not already open, adds it to the working set,\n     * and selects it in the WorkingSetView\n     * @param {!fullPath}\n     * @param {string=} paneId - Pane in which to add the view.  If omitted, the command default is to use the ACTIVE_PANE\n     * @return {!$.Promise}\n     */\n    function openFileAndAddToWorkingSet(fullPath, paneId) {\n        var result = new $.Deferred(),\n            promise = CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {fullPath: fullPath,\n                                                                                  paneId: paneId});\n\n        // This properly handles sending the right nofications in cases where the document\n        // is already the current one. In that case we will want to notify with\n        // documentSelectionFocusChange so the views change their selection\n        promise.done(function (file) {\n            // CMD_ADD_TO_WORKINGSET_AND_OPEN command sets the current document. Update the\n            // selection focus only if doc is not null. When double-clicking on an\n            // image file, we get a null doc here but we still want to keep _fileSelectionFocus\n            // as PROJECT_MANAGER. Regardless of doc is null or not, call _activatePane\n            // to trigger documentSelectionFocusChange event.\n            _fileSelectionFocus = WORKING_SET_VIEW;\n            _activatePane(paneId);\n\n            result.resolve(file);\n        }).fail(function (err) {\n            result.reject(err);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Opens the specified document with its associated external editor,\n     */\n    function openWithExternalApplication(fullPath) {\n        exports.trigger(\"openWithExternalApplication\", fullPath);\n    }\n\n    /**\n     * Opens the specified document if it's not already open, adds it to the working set,\n     * and selects it in the WorkingSetView\n     * @deprecated use FileViewController.openFileAndAddToWorkingSet() instead\n     * @param {!fullPath}\n     * @return {!$.Promise}\n     */\n    function addToWorkingSetAndSelect(fullPath) {\n        DeprecationWarning.deprecationWarning(\"Use FileViewController.openFileAndAddToWorkingSet() instead of FileViewController.addToWorkingSetAndSelect().\", true);\n        var result = new $.Deferred();\n        openFileAndAddToWorkingSet(fullPath)\n            .done(function (file) {\n                var doc;\n\n                if (file) {\n                    doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n                }\n\n                result.resolve(doc);\n            })\n            .fail(function (err) {\n                result.reject(err);\n            });\n        return result.promise();\n    }\n\n\n\n    /**\n     * returns either WORKING_SET_VIEW or PROJECT_MANAGER\n     * @return {!String}\n     */\n    function getFileSelectionFocus() {\n        return _fileSelectionFocus;\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Deprecated\n    exports.addToWorkingSetAndSelect = addToWorkingSetAndSelect;\n\n    // Define public API\n    exports.getFileSelectionFocus = getFileSelectionFocus;\n    exports.openAndSelectDocument = openAndSelectDocument;\n    exports.openFileAndAddToWorkingSet = openFileAndAddToWorkingSet;\n    exports.setFileViewFocus = setFileViewFocus;\n    exports.WORKING_SET_VIEW = WORKING_SET_VIEW;\n    exports.PROJECT_MANAGER = PROJECT_MANAGER;\n    exports.openWithExternalApplication = openWithExternalApplication;\n});\n"
  },
  {
    "path": "src/project/ProjectManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * ProjectManager glues together the project model and file tree view and integrates as needed with other parts\n * of Brackets. It is responsible for creating and updating the project tree when projects are opened\n * and when changes occur to the file tree.\n *\n * This module dispatches these events:\n *    - beforeProjectClose -- before `_projectRoot` changes, but working set files still open\n *    - projectClose       -- *just* before `_projectRoot` changes; working set already cleared\n *      & project root unwatched\n *    - beforeAppClose     -- before Brackets quits entirely\n *    - projectOpen        -- after `_projectRoot` changes and the tree is re-rendered\n *    - projectRefresh     -- when project tree is re-rendered for a reason other than\n *      a project being opened (e.g. from the Refresh command)\n *\n * To listen for events, do something like this: (see EventDispatcher for details on this pattern)\n *    ProjectManager.on(\"eventname\", handler);\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var _ = require(\"thirdparty/lodash\");\n\n    // Load dependent modules\n    var AppInit             = require(\"utils/AppInit\"),\n        Async               = require(\"utils/Async\"),\n        PreferencesDialogs  = require(\"preferences/PreferencesDialogs\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        DefaultDialogs      = require(\"widgets/DefaultDialogs\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        Menus               = require(\"command/Menus\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Strings             = require(\"strings\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        FileSystemError     = require(\"filesystem/FileSystemError\"),\n        Urls                = require(\"i18n!nls/urls\"),\n        FileSyncManager     = require(\"project/FileSyncManager\"),\n        ProjectModel        = require(\"project/ProjectModel\"),\n        FileTreeView        = require(\"project/FileTreeView\"),\n        ViewUtils           = require(\"utils/ViewUtils\");\n\n    // Needed to ensure that menus are set up when we need them.\n    // See #10115\n    require(\"command/DefaultMenus\");\n\n    /**\n     * @private\n     * Filename to use for project settings files.\n     * @type {string}\n     */\n    var SETTINGS_FILENAME = \".\" + PreferencesManager.SETTINGS_FILENAME;\n\n    /**\n     * Name of the preferences for sorting directories first\n     *\n     * @type {string}\n     */\n    var SORT_DIRECTORIES_FIRST = \"sortDirectoriesFirst\";\n\n    /**\n     * @private\n     * Forward declarations to make JSLint happy.\n     */\n    var _fileSystemChange,\n        _fileSystemRename,\n        _showErrorDialog,\n        _saveTreeState,\n        renameItemInline,\n        _renderTreeSync,\n        _renderTree;\n\n    /**\n     * @const\n     * @private\n     * Error context to show the correct error message\n     * @type {int}\n     */\n    var ERR_TYPE_CREATE                 = 1,\n        ERR_TYPE_CREATE_EXISTS          = 2,\n        ERR_TYPE_RENAME                 = 3,\n        ERR_TYPE_DELETE                 = 4,\n        ERR_TYPE_LOADING_PROJECT        = 5,\n        ERR_TYPE_LOADING_PROJECT_NATIVE = 6,\n        ERR_TYPE_MAX_FILES              = 7,\n        ERR_TYPE_OPEN_DIALOG            = 8,\n        ERR_TYPE_INVALID_FILENAME       = 9,\n        ERR_TYPE_MOVE                   = 10;\n\n    /**\n     * @private\n     * Reference to the tree control container div. Initialized by\n     * htmlReady handler\n     * @type {jQueryObject}\n     */\n    var $projectTreeContainer;\n\n    /**\n     * @private\n     *\n     * Reference to the container of the Preact component. Everything in this\n     * node is managed by Preact.\n     * @type {Element}\n     */\n    var fileTreeViewContainer;\n\n    /**\n     * @private\n     *\n     * Does the file tree currently have the focus?\n     *\n     * @return {boolean} `true` if the file tree has the focus\n     */\n    function _hasFileSelectionFocus() {\n        return FileViewController.getFileSelectionFocus() === FileViewController.PROJECT_MANAGER;\n    }\n\n    /**\n     * @private\n     * Singleton ProjectModel object.\n     * @type {ProjectModel.ProjectModel}\n     */\n    var model = new ProjectModel.ProjectModel({\n        focused: _hasFileSelectionFocus()\n    });\n\n    /**\n     * @private\n     * @type {boolean}\n     * A flag to remember when user has been warned about too many files, so they\n     * are only warned once per project/session.\n     */\n    var _projectWarnedForTooManyFiles = false;\n\n    /**\n     * @private\n     *\n     * Event handler which displays an error based on a problem creating a file.\n     *\n     * @param {$.Event} e jQuery event object\n     * @param {{type:any,isFolder:boolean}} errorInfo Information passed in the error events\n     */\n    function _displayCreationError(e, errorInfo) {\n        window.setTimeout(function () {\n            var error = errorInfo.type,\n                isFolder = errorInfo.isFolder,\n                name = errorInfo.name;\n\n            if (error === FileSystemError.ALREADY_EXISTS) {\n                _showErrorDialog(ERR_TYPE_CREATE_EXISTS, isFolder, null, name);\n            } else if (error === ProjectModel.ERROR_INVALID_FILENAME) {\n                _showErrorDialog(ERR_TYPE_INVALID_FILENAME, isFolder, ProjectModel._invalidChars);\n            } else {\n                var errString = error === FileSystemError.NOT_WRITABLE ?\n                        Strings.NO_MODIFICATION_ALLOWED_ERR :\n                        StringUtils.format(Strings.GENERIC_ERROR, error);\n\n                _showErrorDialog(ERR_TYPE_CREATE, isFolder, errString, name).getPromise();\n            }\n        }, 10);\n    }\n\n    /**\n     * @private\n     *\n     * Reverts to the previous selection (useful if there's an error).\n     *\n     * @param {string|File} previousPath The previously selected path.\n     * @param {boolean} switchToWorkingSet True if we need to switch focus to the Working Set\n     */\n    function _revertSelection(previousPath, switchToWorkingSet) {\n        model.setSelected(previousPath);\n        if (switchToWorkingSet) {\n            FileViewController.setFileViewFocus(FileViewController.WORKING_SET_VIEW);\n        }\n    }\n\n    /**\n     * @constructor\n     * @private\n     *\n     * Manages the interaction between the view and the model. This is loosely structured in\n     * the style of [Flux](https://github.com/facebook/flux), but the initial implementation did\n     * not need all of the parts of Flux yet. This ActionCreator could be replaced later with\n     * a real ActionCreator that talks to a Dispatcher.\n     *\n     * Most of the methods just delegate to the ProjectModel. Some are responsible for integration\n     * with other parts of Brackets.\n     *\n     * @param {ProjectModel} model store (in Flux terminology) with the project data\n     */\n    function ActionCreator(model) {\n        this.model = model;\n        this._bindEvents();\n    }\n\n    /**\n     * @private\n     *\n     * Listen to events on the ProjectModel and cause the appropriate behavior within the rest of the system.\n     */\n    ActionCreator.prototype._bindEvents = function () {\n\n        // Change events are the standard Flux signal to rerender the view. Note that\n        // current Flux style is to have the view itself listen to the Store for change events\n        // and re-render itself.\n        this.model.on(ProjectModel.EVENT_CHANGE, function () {\n            _renderTree();\n        });\n\n        // The \"should select\" event signals that we need to open the document based on file tree\n        // activity.\n        this.model.on(ProjectModel.EVENT_SHOULD_SELECT, function (e, data) {\n            if (data.add) {\n                FileViewController.openFileAndAddToWorkingSet(data.path).fail(_.partial(_revertSelection, data.previousPath, !data.hadFocus));\n            } else {\n                FileViewController.openAndSelectDocument(data.path, FileViewController.PROJECT_MANAGER).fail(_.partial(_revertSelection, data.previousPath, !data.hadFocus));\n            }\n        });\n\n        this.model.on(ProjectModel.EVENT_SHOULD_FOCUS, function () {\n            FileViewController.setFileViewFocus(FileViewController.PROJECT_MANAGER);\n        });\n\n        this.model.on(ProjectModel.ERROR_CREATION, _displayCreationError);\n    };\n\n    /**\n     * Sets the directory at the given path to open in the tree and saves the open nodes to view state.\n     *\n     * See `ProjectModel.setDirectoryOpen`\n     */\n    ActionCreator.prototype.setDirectoryOpen = function (path, open) {\n        this.model.setDirectoryOpen(path, open).then(_saveTreeState);\n    };\n\n    /**\n     * See `ProjectModel.setSelected`\n     */\n    ActionCreator.prototype.setSelected = function (path, doNotOpen) {\n        this.model.setSelected(path, doNotOpen);\n    };\n\n    /**\n     * See `ProjectModel.selectInWorkingSet`\n     */\n    ActionCreator.prototype.selectInWorkingSet = function (path) {\n        this.model.selectInWorkingSet(path);\n    };\n\n    /**\n     * See `FileViewController.openWithExternalApplication`\n     */\n    ActionCreator.prototype.openWithExternalApplication = function (path) {\n        FileViewController.openWithExternalApplication(path);\n    };\n\n\n    /**\n     * See `ProjectModel.setContext`\n     */\n    ActionCreator.prototype.setContext = function (path) {\n        this.model.setContext(path);\n    };\n\n    /**\n     * See `ProjectModel.restoreContext`\n     */\n    ActionCreator.prototype.restoreContext = function () {\n        this.model.restoreContext();\n    };\n\n    /**\n     * See `ProjectModel.startRename`\n     */\n    ActionCreator.prototype.startRename = function (path, isMoved) {\n        // This is very not Flux-like, which is a sign that Flux may not be the\n        // right choice here *or* that this architecture needs to evolve subtly\n        // in how errors are reported (more like the create case).\n        // See #9284.\n        renameItemInline(path, isMoved);\n    };\n\n    /**\n     * See `ProjectModel.setRenameValue`\n     */\n    ActionCreator.prototype.setRenameValue = function (path) {\n        this.model.setRenameValue(path);\n    };\n\n    /**\n     * See `ProjectModel.cancelRename`\n     */\n    ActionCreator.prototype.cancelRename = function () {\n        this.model.cancelRename();\n    };\n\n    /**\n     * See `ProjectModel.performRename`\n     */\n    ActionCreator.prototype.performRename = function () {\n        return this.model.performRename();\n    };\n\n    /**\n     * See `ProjectModel.startCreating`\n     */\n    ActionCreator.prototype.startCreating = function (basedir, newName, isFolder) {\n        return this.model.startCreating(basedir, newName, isFolder);\n    };\n\n    /**\n     * See `ProjectModel.setSortDirectoriesFirst`\n     */\n    ActionCreator.prototype.setSortDirectoriesFirst = function (sortDirectoriesFirst) {\n        this.model.setSortDirectoriesFirst(sortDirectoriesFirst);\n    };\n\n    /**\n     * See `ProjectModel.setFocused`\n     */\n    ActionCreator.prototype.setFocused = function (focused) {\n        this.model.setFocused(focused);\n    };\n\n    /**\n     * See `ProjectModel.setCurrentFile`\n     */\n    ActionCreator.prototype.setCurrentFile = function (curFile) {\n        this.model.setCurrentFile(curFile);\n    };\n\n    /**\n     * See `ProjectModel.toggleSubdirectories`\n     */\n    ActionCreator.prototype.toggleSubdirectories = function (path, openOrClose) {\n        this.model.toggleSubdirectories(path, openOrClose).then(_saveTreeState);\n    };\n\n    /**\n     * See `ProjectModel.closeSubtree`\n     */\n    ActionCreator.prototype.closeSubtree = function (path) {\n        this.model.closeSubtree(path);\n        _saveTreeState();\n    };\n\n    ActionCreator.prototype.dragItem = function (path) {\n        // Close open menus on drag and clear the context, but only if there's a menu open.\n        if ($(\".dropdown.open\").length > 0) {\n            Menus.closeAll();\n            this.setContext(null);\n        }\n\n        // Close directory, if dragged item is directory\n        if (_.last(path) === '/') {\n            this.setDirectoryOpen(path, false);\n        }\n    };\n\n    /**\n     * Moves the item in the oldPath to the newDirectory directory\n     */\n    ActionCreator.prototype.moveItem = function (oldPath, newDirectory) {\n        var fileName = FileUtils.getBaseName(oldPath),\n            newPath = newDirectory + fileName,\n            self = this;\n\n        // If item dropped onto itself or onto its parent directory, return\n        if (oldPath === newDirectory || FileUtils.getParentPath(oldPath) === newDirectory) {\n            return;\n        }\n\n        // Add trailing slash if directory is moved\n        if (_.last(oldPath) === '/') {\n            newPath = ProjectModel._ensureTrailingSlash(newPath);\n        }\n\n        this.startRename(oldPath, true);\n        this.setRenameValue(newPath);\n\n        this.performRename();\n        this.setDirectoryOpen(newDirectory, true);\n    };\n\n    /**\n     * See `ProjectModel.refresh`\n     */\n    ActionCreator.prototype.refresh = function () {\n        this.model.refresh();\n    };\n\n    /**\n     * @private\n     * @type {ActionCreator}\n     *\n     * Singleton actionCreator that is used for dispatching changes to the ProjectModel.\n     */\n    var actionCreator = new ActionCreator(model);\n    \n    /**\n     * Returns the File or Directory corresponding to the item that was right-clicked on in the file tree menu.\n     * @return {?(File|Directory)}\n     */\n    function getFileTreeContext() {\n        var selectedEntry = model.getContext();\n        return selectedEntry;\n    }\n\n    /**\n     * Returns the File or Directory corresponding to the item selected in the sidebar panel, whether in\n     * the file tree OR in the working set; or null if no item is selected anywhere in the sidebar.\n     * May NOT be identical to the current Document - a folder may be selected in the sidebar, or the sidebar may not\n     * have the current document visible in the tree & working set.\n     * @return {?(File|Directory)}\n     */\n    function getSelectedItem() {\n        // Prefer file tree context, then file tree selection, else use working set\n        var selectedEntry = getFileTreeContext();\n        if (!selectedEntry) {\n            selectedEntry = model.getSelected();\n        }\n        if (!selectedEntry) {\n            selectedEntry = MainViewManager.getCurrentlyViewedFile();\n        }\n        return selectedEntry;\n    }\n\n    /**\n     * @private\n     *\n     * Handler for changes in the focus between working set and file tree view.\n     */\n    function _fileViewControllerChange() {\n        actionCreator.setFocused(_hasFileSelectionFocus());\n        _renderTree();\n    }\n\n    /**\n     * @private\n     *\n     * Handler for changes in document selection.\n     */\n    function _documentSelectionFocusChange() {\n        var curFullPath = MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE);\n        if (curFullPath && _hasFileSelectionFocus()) {\n            actionCreator.setSelected(curFullPath, true);\n        } else {\n            actionCreator.setSelected(null);\n        }\n        _fileViewControllerChange();\n    }\n\n    /**\n     * @private\n     *\n     * Handler for changes to which file is currently viewed.\n     *\n     * @param {Object} e jQuery event object\n     * @param {File} curFile Currently viewed file.\n     */\n    function _currentFileChange(e, curFile) {\n        actionCreator.setCurrentFile(curFile);\n    }\n\n    /**\n     * @private\n     *\n     * Creates a context object for doing project view state lookups.\n     */\n    function _getProjectViewStateContext() {\n        return { location : { scope: \"user\",\n                             layer: \"project\",\n                             layerID: model.projectRoot.fullPath } };\n    }\n\n    /**\n     * Returns the encoded Base URL of the currently loaded project, or empty string if no project\n     * is open (during startup, or running outside of app shell).\n     * @return {String}\n     */\n    function getBaseUrl() {\n        return model.getBaseUrl();\n    }\n\n    /**\n     * Sets the encoded Base URL of the currently loaded project.\n     * @param {String}\n     */\n    function setBaseUrl(projectBaseUrl) {\n        var context = _getProjectViewStateContext();\n\n        projectBaseUrl = model.setBaseUrl(projectBaseUrl);\n\n        PreferencesManager.setViewState(\"project.baseUrl\", projectBaseUrl, context);\n    }\n\n    /**\n     * Returns true if absPath lies within the project, false otherwise.\n     * Does not support paths containing \"..\"\n     * @param {string|FileSystemEntry} absPathOrEntry\n     * @return {boolean}\n     */\n    function isWithinProject(absPathOrEntry) {\n        return model.isWithinProject(absPathOrEntry);\n    }\n\n    /**\n     * If absPath lies within the project, returns a project-relative path. Else returns absPath\n     * unmodified.\n     * Does not support paths containing \"..\"\n     * @param {!string} absPath\n     * @return {!string}\n     */\n    function makeProjectRelativeIfPossible(absPath) {\n        return model.makeProjectRelativeIfPossible(absPath);\n    }\n\n    /**\n     * Returns the root folder of the currently loaded project, or null if no project is open (during\n     * startup, or running outside of app shell).\n     * @return {Directory}\n     */\n    function getProjectRoot() {\n        return model.projectRoot;\n    }\n\n    /**\n     * @private\n     *\n     * Sets the project root to the given directory, resetting the ProjectModel and file tree in the process.\n     *\n     * @param {Directory} rootEntry directory object for the project root\n     * @return {$.Promise} resolved when the project is done setting up\n     */\n    function _setProjectRoot(rootEntry) {\n        var d = new $.Deferred();\n        model.setProjectRoot(rootEntry).then(function () {\n            d.resolve();\n            model.reopenNodes(PreferencesManager.getViewState(\"project.treeState\", _getProjectViewStateContext()));\n        });\n        return d.promise();\n    }\n\n    /**\n     * @private\n     *\n     * Saves the project path.\n     */\n    var _saveProjectPath = function () {\n        // save the current project\n        PreferencesManager.setViewState(\"projectPath\", model.projectRoot.fullPath);\n    };\n\n    /**\n     * @private\n     * Save tree state.\n     */\n    _saveTreeState = function () {\n        var context = _getProjectViewStateContext(),\n            openNodes = model.getOpenNodes();\n\n        // Store the open nodes by their full path and persist to storage\n        PreferencesManager.setViewState(\"project.treeState\", openNodes, context);\n    };\n\n    /**\n     * @private\n     *\n     * Displays an error dialog for problems when working with files in the file tree.\n     *\n     * @param {number} errType type of error that occurred\n     * @param {boolean} isFolder did the error occur because of a folder operation?\n     * @param {string} error message with detail about the error\n     * @param {string} path path to file or folder that had the error\n     * @return {Dialog|null} Dialog if the error message was created\n     */\n    _showErrorDialog = function (errType, isFolder, error, path) {\n        var titleType = isFolder ? Strings.DIRECTORY_TITLE : Strings.FILE_TITLE,\n            entryType = isFolder ? Strings.DIRECTORY : Strings.FILE,\n            title,\n            message;\n        path = StringUtils.breakableUrl(path);\n\n        switch (errType) {\n        case ERR_TYPE_CREATE:\n            title = StringUtils.format(Strings.ERROR_CREATING_FILE_TITLE, titleType);\n            message = StringUtils.format(Strings.ERROR_CREATING_FILE, entryType, path, error);\n            break;\n        case ERR_TYPE_CREATE_EXISTS:\n            title = StringUtils.format(Strings.INVALID_FILENAME_TITLE, titleType);\n            message = StringUtils.format(Strings.ENTRY_WITH_SAME_NAME_EXISTS, path);\n            break;\n        case ERR_TYPE_RENAME:\n            title = StringUtils.format(Strings.ERROR_RENAMING_FILE_TITLE, titleType);\n            message = StringUtils.format(Strings.ERROR_RENAMING_FILE, path, error, entryType);\n            break;\n        case ERR_TYPE_MOVE:\n            title = StringUtils.format(Strings.ERROR_MOVING_FILE_TITLE, titleType);\n            message = StringUtils.format(Strings.ERROR_MOVING_FILE, path, error, entryType);\n            break;\n        case ERR_TYPE_DELETE:\n            title = StringUtils.format(Strings.ERROR_DELETING_FILE_TITLE, titleType);\n            message = StringUtils.format(Strings.ERROR_DELETING_FILE, path, error, entryType);\n            break;\n        case ERR_TYPE_LOADING_PROJECT:\n            title = Strings.ERROR_LOADING_PROJECT;\n            message = StringUtils.format(Strings.READ_DIRECTORY_ENTRIES_ERROR, path, error);\n            break;\n        case ERR_TYPE_LOADING_PROJECT_NATIVE:\n            title = Strings.ERROR_LOADING_PROJECT;\n            message = StringUtils.format(Strings.REQUEST_NATIVE_FILE_SYSTEM_ERROR, path, error);\n            break;\n        case ERR_TYPE_MAX_FILES:\n            title = Strings.ERROR_MAX_FILES_TITLE;\n            message = Strings.ERROR_MAX_FILES;\n            break;\n        case ERR_TYPE_OPEN_DIALOG:\n            title = Strings.ERROR_LOADING_PROJECT;\n            message = StringUtils.format(Strings.OPEN_DIALOG_ERROR, error);\n            break;\n        case ERR_TYPE_INVALID_FILENAME:\n            title = StringUtils.format(Strings.INVALID_FILENAME_TITLE, isFolder ? Strings.DIRECTORY_NAME : Strings.FILENAME);\n            message = StringUtils.format(Strings.INVALID_FILENAME_MESSAGE, isFolder ? Strings.DIRECTORY_NAMES_LEDE : Strings.FILENAMES_LEDE, error);\n            break;\n        }\n\n        if (title && message) {\n            return Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_ERROR,\n                title,\n                message\n            );\n        }\n        return null;\n    };\n\n    var _RENDER_DEBOUNCE_TIME = 100;\n\n    /**\n     * @private\n     *\n     * Rerender the file tree view.\n     *\n     * @param {boolean} forceRender Force the tree to rerender. Should only be needed by extensions that call rerenderTree.\n     */\n    _renderTreeSync = function (forceRender) {\n        var projectRoot = getProjectRoot();\n        if (!projectRoot) {\n            return;\n        }\n        model.setScrollerInfo($projectTreeContainer[0].scrollWidth, $projectTreeContainer.scrollTop(), $projectTreeContainer.scrollLeft(), $projectTreeContainer.offset().top);\n        FileTreeView.render(fileTreeViewContainer, model._viewModel, projectRoot, actionCreator, forceRender, brackets.platform);\n    };\n\n    _renderTree = _.debounce(_renderTreeSync, _RENDER_DEBOUNCE_TIME);\n\n    /**\n     * @private\n     *\n     * Returns the full path to the welcome project, which we open on first launch.\n     *\n     * @param {string} sampleUrl URL for getting started project\n     * @param {string} initialPath Path to Brackets directory (see FileUtils.getNativeBracketsDirectoryPath())\n     * @return {!string} fullPath reference\n     */\n    function _getWelcomeProjectPath() {\n        return ProjectModel._getWelcomeProjectPath(Urls.GETTING_STARTED, FileUtils.getNativeBracketsDirectoryPath());\n    }\n\n    /**\n     * Adds the path to the list of welcome projects we've ever seen, if not on the list already.\n     *\n     * @param {string} path Path to possibly add\n     */\n    function addWelcomeProjectPath(path) {\n        var welcomeProjects = ProjectModel._addWelcomeProjectPath(path,\n                                                                 PreferencesManager.getViewState(\"welcomeProjects\"));\n        PreferencesManager.setViewState(\"welcomeProjects\", welcomeProjects);\n    }\n\n\n    /**\n     * Returns true if the given path is the same as one of the welcome projects we've previously opened,\n     * or the one for the current build.\n     *\n     * @param {string} path Path to check to see if it's a welcome project path\n     * @return {boolean} true if this is a welcome project path\n     */\n    function isWelcomeProjectPath(path) {\n        return ProjectModel._isWelcomeProjectPath(path, _getWelcomeProjectPath(), PreferencesManager.getViewState(\"welcomeProjects\"));\n    }\n\n    /**\n     * If the provided path is to an old welcome project, returns the current one instead.\n     */\n    function updateWelcomeProjectPath(path) {\n        if (isWelcomeProjectPath(path)) {\n            return _getWelcomeProjectPath();\n        } else {\n            return path;\n        }\n    }\n\n    /**\n     * After failing to load a project, this function determines which project path to fallback to.\n     * @return {$.Promise} Promise that resolves to a project path {string}\n     */\n    function _getFallbackProjectPath() {\n        var fallbackPaths = [],\n            recentProjects = PreferencesManager.getViewState(\"recentProjects\") || [],\n            deferred = new $.Deferred();\n\n        // Build ordered fallback path array\n        if (recentProjects.length > 1) {\n            // *Most* recent project is the one that just failed to load, so use second most recent\n            fallbackPaths.push(recentProjects[1]);\n        }\n\n        // Next is Getting Started project\n        fallbackPaths.push(_getWelcomeProjectPath());\n\n        // Helper func for Async.firstSequentially()\n        function processItem(path) {\n            var deferred = new $.Deferred(),\n                fileEntry = FileSystem.getDirectoryForPath(path);\n\n            fileEntry.exists(function (err, exists) {\n                if (!err && exists) {\n                    deferred.resolve();\n                } else {\n                    deferred.reject();\n                }\n            });\n\n            return deferred.promise();\n        }\n\n        // Find first path that exists\n        Async.firstSequentially(fallbackPaths, processItem)\n            .done(function (fallbackPath) {\n                deferred.resolve(fallbackPath);\n            })\n            .fail(function () {\n                // Last resort is Brackets source folder which is guaranteed to exist\n                deferred.resolve(FileUtils.getNativeBracketsDirectoryPath());\n            });\n\n        return deferred.promise();\n    }\n\n    /**\n     * Initial project path is stored in prefs, which defaults to the welcome project on\n     * first launch.\n     */\n    function getInitialProjectPath() {\n        return updateWelcomeProjectPath(PreferencesManager.getViewState(\"projectPath\"));\n    }\n\n    /**\n     * @private\n     *\n     * Watches the project for filesystem changes so that the tree can be updated.\n     */\n    function _watchProjectRoot(rootPath) {\n        FileSystem.on(\"change\", _fileSystemChange);\n        FileSystem.on(\"rename\", _fileSystemRename);\n\n        FileSystem.watch(FileSystem.getDirectoryForPath(rootPath), ProjectModel._shouldShowName, ProjectModel.defaultIgnoreGlobs, function (err) {\n            if (err === FileSystemError.TOO_MANY_ENTRIES) {\n                if (!_projectWarnedForTooManyFiles) {\n                    _showErrorDialog(ERR_TYPE_MAX_FILES);\n                    _projectWarnedForTooManyFiles = true;\n                }\n            } else if (err) {\n                console.error(\"Error watching project root: \", rootPath, err);\n            }\n        });\n\n        // Reset allFiles cache\n        model._resetCache();\n    }\n\n\n    /**\n     * @private\n     * Close the file system and remove listeners.\n     * @return {$.Promise} A promise that's resolved when the root is unwatched. Rejected if\n     *     there is no project root or if the unwatch fails.\n     */\n    function _unwatchProjectRoot() {\n        var result = new $.Deferred();\n        if (!model.projectRoot) {\n            result.reject();\n        } else {\n            FileSystem.off(\"change\", _fileSystemChange);\n            FileSystem.off(\"rename\", _fileSystemRename);\n\n            FileSystem.unwatch(model.projectRoot, function (err) {\n                if (err) {\n                    console.error(\"Error unwatching project root: \", model.projectRoot.fullPath, err);\n                    result.reject(err);\n                } else {\n                    result.resolve();\n                }\n            });\n\n            // Reset allFiles cache\n            model._resetCache();\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Reloads the project preferences.\n     */\n    function _reloadProjectPreferencesScope() {\n        var root = getProjectRoot();\n        if (root) {\n            // Alias the \"project\" Scope to the path Scope for the project-level settings file\n            PreferencesManager._setProjectSettingsFile(root.fullPath + SETTINGS_FILENAME);\n        } else {\n            PreferencesManager._setProjectSettingsFile();\n        }\n    }\n\n    /**\n     * Loads the given folder as a project. Does NOT prompt about any unsaved changes - use openProject()\n     * instead to check for unsaved changes and (optionally) let the user choose the folder to open.\n     *\n     * @param {!string} rootPath  Absolute path to the root folder of the project.\n     *  A trailing \"/\" on the path is optional (unlike many Brackets APIs that assume a trailing \"/\").\n     * @param {boolean=} isUpdating  If true, indicates we're just updating the tree;\n     *  if false, a different project is being loaded.\n     * @return {$.Promise} A promise object that will be resolved when the\n     *  project is loaded and tree is rendered, or rejected if the project path\n     *  fails to load.\n     */\n    function _loadProject(rootPath, isUpdating) {\n        var result = new $.Deferred(),\n            startLoad = new $.Deferred();\n\n        // Some legacy code calls this API with a non-canonical path\n        rootPath = ProjectModel._ensureTrailingSlash(rootPath);\n\n        var projectPrefFullPath = (rootPath + SETTINGS_FILENAME),\n            file   = FileSystem.getFileForPath(projectPrefFullPath);\n\n        //Verify that the project preferences file (.brackets.json) is NOT corrupted.\n        //If corrupted, display the error message and open the file in editor for the user to edit.\n        FileUtils.readAsText(file)\n            .done(function (text) {\n                try {\n                    if (text) {\n                        JSON.parse(text);\n                    }\n                } catch (err) {\n                    // Cannot parse the text read from the project preferences file.\n                    var info = MainViewManager.findInAllWorkingSets(projectPrefFullPath);\n                    var paneId;\n                    if (info.length) {\n                        paneId = info[0].paneId;\n                    }\n                    FileViewController.openFileAndAddToWorkingSet(projectPrefFullPath, paneId)\n                        .done(function () {\n                            Dialogs.showModalDialog(\n                                DefaultDialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_PREFS_CORRUPT_TITLE,\n                                Strings.ERROR_PROJ_PREFS_CORRUPT\n                            ).done(function () {\n                                // give the focus back to the editor with the pref file\n                                MainViewManager.focusActivePane();\n                            });\n                        });\n                }\n            });\n\n        if (isUpdating) {\n            // We're just refreshing. Don't need to unwatch the project root, so we can start loading immediately.\n            startLoad.resolve();\n        } else {\n            if (model.projectRoot && model.projectRoot.fullPath === rootPath) {\n                return (new $.Deferred()).resolve().promise();\n            }\n\n            // About to close current project (if any)\n            if (model.projectRoot) {\n                exports.trigger(\"beforeProjectClose\", model.projectRoot);\n            }\n\n            // close all the old files\n            MainViewManager._closeAll(MainViewManager.ALL_PANES);\n\n            _unwatchProjectRoot().always(function () {\n                // Done closing old project (if any)\n                if (model.projectRoot) {\n                    LanguageManager._resetPathLanguageOverrides();\n                    PreferencesManager._reloadUserPrefs(model.projectRoot);\n                    exports.trigger(\"projectClose\", model.projectRoot);\n                }\n\n                startLoad.resolve();\n            });\n        }\n\n        startLoad.done(function () {\n            var context = { location : { scope: \"user\",\n                                         layer: \"project\" } };\n\n            // Clear project path map\n            if (!isUpdating) {\n                PreferencesManager._stateProjectLayer.setProjectPath(rootPath);\n            }\n\n            // Populate file tree as long as we aren't running in the browser\n            if (!brackets.inBrowser) {\n                if (!isUpdating) {\n                    _watchProjectRoot(rootPath);\n                }\n                // Point at a real folder structure on local disk\n                var rootEntry = FileSystem.getDirectoryForPath(rootPath);\n                rootEntry.exists(function (err, exists) {\n                    if (exists) {\n                        var projectRootChanged = (!model.projectRoot || !rootEntry) ||\n                            model.projectRoot.fullPath !== rootEntry.fullPath;\n\n                        // Success!\n                        var perfTimerName = PerfUtils.markStart(\"Load Project: \" + rootPath);\n\n                        _projectWarnedForTooManyFiles = false;\n\n                        _setProjectRoot(rootEntry).always(function () {\n                            model.setBaseUrl(PreferencesManager.getViewState(\"project.baseUrl\", context) || \"\");\n\n                            if (projectRootChanged) {\n                                _reloadProjectPreferencesScope();\n                                PreferencesManager._setCurrentFile(rootPath);\n                            }\n\n                            // If this is the most current welcome project, record it. In future launches, we want\n                            // to substitute the latest welcome project from the current build instead of using an\n                            // outdated one (when loading recent projects or the last opened project).\n                            if (rootPath === _getWelcomeProjectPath()) {\n                                addWelcomeProjectPath(rootPath);\n                            }\n\n                            if (projectRootChanged) {\n                                // Allow asynchronous event handlers to finish before resolving result by collecting promises from them\n                                exports.trigger(\"projectOpen\", model.projectRoot);\n                                result.resolve();\n                            } else {\n                                exports.trigger(\"projectRefresh\", model.projectRoot);\n                                result.resolve();\n                            }\n                            PerfUtils.addMeasurement(perfTimerName);\n                        });\n                    } else {\n                        console.log(\"error loading project\");\n                        _showErrorDialog(ERR_TYPE_LOADING_PROJECT_NATIVE, true, err || FileSystemError.NOT_FOUND, rootPath)\n                            .done(function () {\n                                // Reset _projectRoot to null so that the following _loadProject call won't\n                                // run the 'beforeProjectClose' event a second time on the original project,\n                                // which is now partially torn down (see #6574).\n                                model.projectRoot = null;\n\n                                // The project folder stored in preference doesn't exist, so load the default\n                                // project directory.\n                                // TODO (issue #267): When Brackets supports having no project directory\n                                // defined this code will need to change\n                                _getFallbackProjectPath().done(function (path) {\n                                    _loadProject(path).always(function () {\n                                        // Make sure not to reject the original deferred until the fallback\n                                        // project is loaded, so we don't violate expectations that there is always\n                                        // a current project before continuing after _loadProject().\n                                        result.reject();\n                                    });\n                                });\n                            });\n                    }\n                });\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * @const\n     * @private\n     * @type {number} Minimum delay in milliseconds between calls to refreshFileTree\n     */\n    var _refreshDelay = 1000;\n\n    /**\n     * Refresh the project's file tree, maintaining the current selection.\n     *\n     * Note that the original implementation of this returned a promise to be resolved when the refresh is complete.\n     * That use is deprecated and `refreshFileTree` is now a \"fire and forget\" kind of function.\n     */\n    var refreshFileTree = function refreshFileTree() {\n        FileSystem.clearAllCaches();\n        return new $.Deferred().resolve().promise();\n    };\n\n    refreshFileTree = _.debounce(refreshFileTree, _refreshDelay);\n\n    /**\n     * Expands tree nodes to show the given file or folder and selects it. Silently no-ops if the\n     * path lies outside the project, or if it doesn't exist.\n     *\n     * @param {!(File|Directory)} entry File or Directory to show\n     * @return {$.Promise} Resolved when done; or rejected if not found\n     */\n    function showInTree(entry) {\n        return model.showInTree(entry).then(_saveTreeState);\n    }\n\n\n    /**\n     * Open a new project. Currently, Brackets must always have a project open, so\n     * this method handles both closing the current project and opening a new project.\n     *\n     * @param {string=} path Optional absolute path to the root folder of the project.\n     *  If path is undefined or null, displays a dialog where the user can choose a\n     *  folder to load. If the user cancels the dialog, nothing more happens.\n     * @return {$.Promise} A promise object that will be resolved when the\n     *  project is loaded and tree is rendered, or rejected if the project path\n     *  fails to load.\n     */\n    function openProject(path) {\n\n        var result = new $.Deferred();\n\n        // Confirm any unsaved changes first. We run the command in \"prompt-only\" mode, meaning it won't\n        // actually close any documents even on success; we'll do that manually after the user also oks\n        // the folder-browse dialog.\n        CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })\n            .done(function () {\n                if (path) {\n                    // use specified path\n                    _loadProject(path, false).then(result.resolve, result.reject);\n                } else {\n                    // Pop up a folder browse dialog\n                    FileSystem.showOpenDialog(false, true, Strings.CHOOSE_FOLDER, model.projectRoot.fullPath, null, function (err, files) {\n                        if (!err) {\n                            // If length == 0, user canceled the dialog; length should never be > 1\n                            if (files.length > 0) {\n                                // Load the new project into the folder tree\n                                _loadProject(files[0]).then(result.resolve, result.reject);\n                            } else {\n                                result.reject();\n                            }\n                        } else {\n                            _showErrorDialog(ERR_TYPE_OPEN_DIALOG, null, err);\n                            result.reject();\n                        }\n                    });\n                }\n            })\n            .fail(function () {\n                result.reject();\n            });\n\n        // if fail, don't open new project: user canceled (or we failed to save its unsaved changes)\n        return result.promise();\n    }\n\n    /**\n     * Invoke project settings dialog.\n     * @return {$.Promise}\n     */\n    function _projectSettings() {\n        return PreferencesDialogs.showProjectPreferencesDialog(getBaseUrl()).getPromise();\n    }\n\n    /**\n     * Create a new item in the current project.\n     *\n     * @param baseDir {string|Directory} Full path of the directory where the item should go.\n     *   Defaults to the project root if the entry is not valid or not within the project.\n     * @param initialName {string} Initial name for the item\n     * @param skipRename {boolean} If true, don't allow the user to rename the item\n     * @param isFolder {boolean} If true, create a folder instead of a file\n     * @return {$.Promise} A promise object that will be resolved with the File\n     *  of the created object, or rejected if the user cancelled or entered an illegal\n     *  filename.\n     */\n    function createNewItem(baseDir, initialName, skipRename, isFolder) {\n        baseDir = model.getDirectoryInProject(baseDir);\n\n        if (skipRename) {\n            if(isFolder) {\n                return model.createAtPath(baseDir + initialName + \"/\");\n            }\n            return model.createAtPath(baseDir + initialName);\n        }\n        return actionCreator.startCreating(baseDir, initialName, isFolder);\n    }\n\n    /**\n     * Delete file or directore from project\n     * @param {!(File|Directory)} entry File or Directory to delete\n     */\n    function deleteItem(entry) {\n        var result = new $.Deferred();\n\n        entry.moveToTrash(function (err) {\n            if (!err) {\n                DocumentManager.notifyPathDeleted(entry.fullPath);\n                result.resolve();\n            } else {\n                _showErrorDialog(ERR_TYPE_DELETE, entry.isDirectory, FileUtils.getFileErrorString(err), entry.fullPath);\n\n                result.reject(err);\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Returns a filter for use with getAllFiles() that filters files based on LanguageManager language id\n     * @param {!(string|Array.<string>)} languageId a single string of a language id or an array of language ids\n     * @return {!function(File):boolean}\n     */\n    function getLanguageFilter(languageId) {\n        return function languageFilter(file) {\n            var id = LanguageManager.getLanguageForPath(file.fullPath).getId();\n            if (typeof languageId === \"string\") {\n                return (id === languageId);\n            } else {\n                return (languageId.indexOf(id) !== -1);\n            }\n        };\n    }\n\n    /**\n     * @private\n     *\n     * Respond to a FileSystem change event. Note that if renames are initiated\n     * externally, they may be reported as a separate removal and addition. In\n     * this case, the editor state isn't currently preserved.\n     *\n     * @param {$.Event} event\n     * @param {?(File|Directory)} entry File or Directory changed\n     * @param {Array.<FileSystemEntry>=} added If entry is a Directory, contains zero or more added children\n     * @param {Array.<FileSystemEntry>=} removed If entry is a Directory, contains zero or more removed children\n     */\n    _fileSystemChange = function (event, entry, added, removed) {\n        FileSyncManager.syncOpenDocuments();\n\n        model.handleFSEvent(entry, added, removed);\n\n        // @TODO: DocumentManager should implement its own fsChange  handler\n        //          we can clean up the calls to DocumentManager.notifyPathDeleted\n        //          and privatize DocumentManager.notifyPathDeleted as well\n        //        We can also remove the _fileSystemRename handler below and move\n        //          it to DocumentManager\n        if (removed) {\n            removed.forEach(function (file) {\n                // The call to syncOpenDocuemnts above will not nofify\n                //  document manager about deleted images that are\n                //  not in the working set -- try to clean that up here\n                DocumentManager.notifyPathDeleted(file.fullPath);\n            });\n        }\n    };\n\n    /**\n     * @private\n     * Respond to a FileSystem rename event.\n     */\n    _fileSystemRename = function (event, oldName, newName) {\n        // Tell the document manager about the name change. This will update\n        // all of the model information and send notification to all views\n        DocumentManager.notifyPathNameChanged(oldName, newName);\n    };\n\n    /**\n     * Causes the rename operation that's in progress to complete.\n     */\n    function forceFinishRename() {\n        actionCreator.performRename();\n    }\n\n    /**\n     * @private\n     *\n     * Sets the width of the selection bar in the file tree.\n     *\n     * @param {int} width New width value\n     */\n    function _setFileTreeSelectionWidth(width) {\n        model.setSelectionWidth(width);\n        _renderTreeSync();\n    }\n\n    // Initialize variables and listeners that depend on the HTML DOM\n    AppInit.htmlReady(function () {\n        $projectTreeContainer = $(\"#project-files-container\");\n        $projectTreeContainer.addClass(\"jstree jstree-brackets\");\n        $projectTreeContainer.css(\"overflow\", \"auto\");\n        $projectTreeContainer.css(\"position\", \"relative\");\n\n        fileTreeViewContainer = $(\"<div>\").appendTo($projectTreeContainer)[0];\n\n        model.setSelectionWidth($projectTreeContainer.width());\n\n        $(\".main-view\").click(function (jqEvent) {\n            if (!jqEvent.target.classList.contains(\"jstree-rename-input\")) {\n                forceFinishRename();\n                actionCreator.setContext(null);\n            }\n        });\n\n        $(\"#working-set-list-container\").on(\"contentChanged\", function () {\n            $projectTreeContainer.trigger(\"contentChanged\");\n        });\n\n        Menus.getContextMenu(Menus.ContextMenuIds.PROJECT_MENU).on(\"beforeContextMenuOpen\", function () {\n            actionCreator.restoreContext();\n        });\n\n        Menus.getContextMenu(Menus.ContextMenuIds.PROJECT_MENU).on(\"beforeContextMenuClose\", function () {\n            model.setContext(null, false, true);\n        });\n\n        $projectTreeContainer.on(\"contextmenu\", function () {\n            forceFinishRename();\n        });\n\n        $projectTreeContainer.on(\"dragover\", function(e) {\n            e.preventDefault();\n        });\n\n        // Add support for moving items to root directory\n        $projectTreeContainer.on(\"drop\", function(e) {\n            var data = JSON.parse(e.originalEvent.dataTransfer.getData(\"text\"));\n            actionCreator.moveItem(data.path, getProjectRoot().fullPath);\n            e.stopPropagation();\n        });\n\n        // When a context menu item is selected, we need to clear the context\n        // because we don't get a beforeContextMenuClose event since Bootstrap\n        // handles this directly.\n        $(\"#project-context-menu\").on(\"click.dropdown-menu\", function () {\n            model.setContext(null, true);\n        });\n\n        $projectTreeContainer.on(\"scroll\", function () {\n            // Close open menus on scroll and clear the context, but only if there's a menu open.\n            if ($(\".dropdown.open\").length > 0) {\n                Menus.closeAll();\n                actionCreator.setContext(null);\n            }\n            // we need to render the tree without a delay to not cause selection extension issues (#10573)\n            _renderTreeSync();\n        });\n\n        _renderTree();\n\n        ViewUtils.addScrollerShadow($projectTreeContainer[0]);\n    });\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Init default project path to welcome project\n    PreferencesManager.stateManager.definePreference(\"projectPath\", \"string\", _getWelcomeProjectPath());\n\n    exports.on(\"projectOpen\", _reloadProjectPreferencesScope);\n    exports.on(\"projectOpen\", _saveProjectPath);\n    exports.on(\"beforeAppClose\", _unwatchProjectRoot);\n\n    // Due to circular dependencies, not safe to call on() directly for other modules' events\n    EventDispatcher.on_duringInit(FileViewController, \"documentSelectionFocusChange\", _documentSelectionFocusChange);\n    EventDispatcher.on_duringInit(FileViewController, \"fileViewFocusChange\", _fileViewControllerChange);\n    EventDispatcher.on_duringInit(MainViewManager, \"currentFileChange\", _currentFileChange);\n\n    // Commands\n    CommandManager.register(Strings.CMD_OPEN_FOLDER,      Commands.FILE_OPEN_FOLDER,      openProject);\n    CommandManager.register(Strings.CMD_PROJECT_SETTINGS, Commands.FILE_PROJECT_SETTINGS, _projectSettings);\n    CommandManager.register(Strings.CMD_FILE_REFRESH,     Commands.FILE_REFRESH,          refreshFileTree);\n\n    // Define the preference to decide how to sort the Project Tree files\n    PreferencesManager.definePreference(SORT_DIRECTORIES_FIRST, \"boolean\", brackets.platform !== \"mac\", {\n        description: Strings.DESCRIPTION_SORT_DIRECTORIES_FIRST\n    })\n        .on(\"change\", function () {\n            actionCreator.setSortDirectoriesFirst(PreferencesManager.get(SORT_DIRECTORIES_FIRST));\n        });\n\n    actionCreator.setSortDirectoriesFirst(PreferencesManager.get(SORT_DIRECTORIES_FIRST));\n\n    /**\n     * Gets the filesystem object for the current context in the file tree.\n     */\n    function getContext() {\n        return model.getContext();\n    }\n\n    /**\n     * Starts a rename operation, completing the current operation if there is one.\n     *\n     * The Promise returned is resolved with an object with a `newPath` property with the renamed path. If the user cancels the operation, the promise is resolved with the value RENAME_CANCELLED.\n     *\n     * @param {FileSystemEntry} entry file or directory filesystem object to rename\n     * @param {boolean=} isMoved optional flag which indicates whether the entry is being moved instead of renamed\n     * @return {$.Promise} a promise resolved when the rename is done.\n     */\n    renameItemInline = function (entry, isMoved) {\n        var d = new $.Deferred();\n\n        model.startRename(entry, isMoved)\n            .done(function () {\n                d.resolve();\n            })\n            .fail(function (errorInfo) {\n                // Need to do display the error message on the next event loop turn\n                // because some errors can come up synchronously and then the dialog\n                // is not displayed.\n                window.setTimeout(function () {\n                    if (isMoved) {\n                        switch (errorInfo.type) {\n                            case FileSystemError.ALREADY_EXISTS:\n                                _showErrorDialog(ERR_TYPE_MOVE, errorInfo.isFolder, Strings.FILE_EXISTS_ERR, errorInfo.fullPath);\n                                break;\n                            case ProjectModel.ERROR_NOT_IN_PROJECT:\n                                _showErrorDialog(ERR_TYPE_MOVE, errorInfo.isFolder, Strings.ERROR_MOVING_NOT_IN_PROJECT, errorInfo.fullPath);\n                                break;\n                            default:\n                                _showErrorDialog(ERR_TYPE_MOVE, errorInfo.isFolder, FileUtils.getFileErrorString(errorInfo.type), errorInfo.fullPath);\n                        }\n                    } else {\n                        switch (errorInfo.type) {\n                            case ProjectModel.ERROR_INVALID_FILENAME:\n                                _showErrorDialog(ERR_TYPE_INVALID_FILENAME, errorInfo.isFolder, ProjectModel._invalidChars);\n                                break;\n                            case FileSystemError.ALREADY_EXISTS:\n                                _showErrorDialog(ERR_TYPE_RENAME, errorInfo.isFolder, Strings.FILE_EXISTS_ERR, errorInfo.fullPath);\n                                break;\n                            case ProjectModel.ERROR_NOT_IN_PROJECT:\n                                _showErrorDialog(ERR_TYPE_RENAME, errorInfo.isFolder, Strings.ERROR_RENAMING_NOT_IN_PROJECT, errorInfo.fullPath);\n                                break;\n                            default:\n                                _showErrorDialog(ERR_TYPE_RENAME, errorInfo.isFolder, FileUtils.getFileErrorString(errorInfo.type), errorInfo.fullPath);\n                        }\n                    }\n                }, 10);\n                d.reject(errorInfo);\n            });\n        return d.promise();\n    };\n\n    /**\n     * Returns an Array of all files for this project, optionally including\n     * files in the working set that are *not* under the project root. Files are\n     * filtered first by ProjectModel.shouldShow(), then by the custom filter\n     * argument (if one was provided).\n     *\n     * @param {function (File, number):boolean=} filter Optional function to filter\n     *          the file list (does not filter directory traversal). API matches Array.filter().\n     * @param {boolean=} includeWorkingSet If true, include files in the working set\n     *          that are not under the project root (*except* for untitled documents).\n     * @param {boolean=} sort If true, The files will be sorted by their paths\n     *\n     * @return {$.Promise} Promise that is resolved with an Array of File objects.\n     */\n    function getAllFiles(filter, includeWorkingSet, sort) {\n        var viewFiles, deferred;\n\n        // The filter and includeWorkingSet params are both optional.\n        // Handle the case where filter is omitted but includeWorkingSet is\n        // specified.\n        if (includeWorkingSet === undefined && typeof (filter) !== \"function\") {\n            includeWorkingSet = filter;\n            filter = null;\n        }\n\n        if (includeWorkingSet) {\n            viewFiles = MainViewManager.getWorkingSet(MainViewManager.ALL_PANES);\n        }\n\n        deferred = new $.Deferred();\n        model.getAllFiles(filter, viewFiles, sort)\n            .done(function (fileList) {\n                deferred.resolve(fileList);\n            })\n            .fail(function (err) {\n                if (err === FileSystemError.TOO_MANY_ENTRIES && !_projectWarnedForTooManyFiles) {\n                    _showErrorDialog(ERR_TYPE_MAX_FILES);\n                    _projectWarnedForTooManyFiles = true;\n                }\n                // resolve with empty list\n                deferred.resolve([]);\n            });\n        return deferred.promise();\n    }\n\n    /**\n     * Adds an icon provider. The callback is invoked before each tree item is rendered, and can\n     * return content to prepend to the item.\n     *\n     * @param {!function(!{name:string, fullPath:string, isFile:boolean}):?string|jQuery|DOMNode|Preact.DOM.ins} callback\n     * * `name`: the file or directory name\n     * * `fullPath`: full path to the file or directory\n     * * `isFile`: true if it's a file, false if it's a directory\n     * Return a string of HTML text, a Preact.DOM.ins instance, a jQuery object, or a DOM node; or undefined\n     * to prepend nothing.\n     */\n    function addIconProvider(callback) {\n        return FileTreeView.addIconProvider(callback);\n    }\n\n    /**\n     * Adds a CSS class provider, invoked before each tree item is rendered.\n     *\n     * @param {!function(!{name:string, fullPath:string, isFile:boolean}):?string} callback\n     * * `name`: the file or directory name\n     * * `fullPath`: full path to the file or directory\n     * * `isFile`: true if it's a file, false if it's a directory\n     * Return a string containing space-separated CSS class(es) to add, or undefined to leave CSS unchanged.\n     */\n    function addClassesProvider(callback) {\n        return FileTreeView.addClassesProvider(callback);\n    }\n\n    /**\n     * Forces the file tree to rerender. Typically, the tree only rerenders the portions of the\n     * tree that have changed data. If an extension that augments the tree has changes that it\n     * needs to display, calling rerenderTree will cause the components for the whole tree to\n     * be rerendered.\n     */\n    function rerenderTree() {\n        _renderTree(true);\n    }\n\n\n    // Private API helpful in testing\n    exports._actionCreator                = actionCreator;\n    exports._RENDER_DEBOUNCE_TIME         = _RENDER_DEBOUNCE_TIME;\n\n    // Private API for use with SidebarView\n    exports._setFileTreeSelectionWidth    = _setFileTreeSelectionWidth;\n\n    // Define public API\n    exports.getProjectRoot                = getProjectRoot;\n    exports.getBaseUrl                    = getBaseUrl;\n    exports.setBaseUrl                    = setBaseUrl;\n    exports.isWithinProject               = isWithinProject;\n    exports.makeProjectRelativeIfPossible = makeProjectRelativeIfPossible;\n    exports.shouldShow                    = ProjectModel.shouldShow;\n    exports.openProject                   = openProject;\n    exports.getFileTreeContext            = getFileTreeContext;\n    exports.getSelectedItem               = getSelectedItem;\n    exports.getContext                    = getContext;\n    exports.getInitialProjectPath         = getInitialProjectPath;\n    exports.isWelcomeProjectPath          = isWelcomeProjectPath;\n    exports.updateWelcomeProjectPath      = updateWelcomeProjectPath;\n    exports.createNewItem                 = createNewItem;\n    exports.renameItemInline              = renameItemInline;\n    exports.deleteItem                    = deleteItem;\n    exports.forceFinishRename             = forceFinishRename;\n    exports.showInTree                    = showInTree;\n    exports.refreshFileTree               = refreshFileTree;\n    exports.getAllFiles                   = getAllFiles;\n    exports.getLanguageFilter             = getLanguageFilter;\n    exports.addIconProvider               = addIconProvider;\n    exports.addClassesProvider            = addClassesProvider;\n    exports.rerenderTree                  = rerenderTree;\n});\n"
  },
  {
    "path": "src/project/ProjectModel.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* unittests: ProjectModel */\n\n/**\n * Provides the data source for a project and manages the view model for the FileTreeView.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var InMemoryFile        = require(\"document/InMemoryFile\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        _                   = require(\"thirdparty/lodash\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileSystemError     = require(\"filesystem/FileSystemError\"),\n        FileTreeViewModel   = require(\"project/FileTreeViewModel\"),\n        Async               = require(\"utils/Async\"),\n        PerfUtils           = require(\"utils/PerfUtils\");\n\n    // Constants\n    var EVENT_CHANGE            = \"change\",\n        EVENT_SHOULD_SELECT     = \"select\",\n        EVENT_SHOULD_FOCUS      = \"focus\",\n        ERROR_CREATION          = \"creationError\",\n        ERROR_INVALID_FILENAME  = \"invalidFilename\",\n        ERROR_NOT_IN_PROJECT    = \"notInProject\";\n\n    /**\n     * @private\n     * File and folder names which are not displayed or searched\n     * TODO: We should add the rest of the file names that TAR excludes:\n     *    http://www.gnu.org/software/tar/manual/html_section/exclude.html\n     * TODO: This should be user configurable\n     *    https://github.com/adobe/brackets/issues/6781\n     * @type {RegExp}\n     */\n    var _exclusionListRegEx = /\\.pyc$|^\\.git$|^\\.gitmodules$|^\\.svn$|^\\.DS_Store$|^Icon\\r|^Thumbs\\.db$|^\\.hg$|^CVS$|^\\.hgtags$|^\\.idea$|^\\.c9revisions$|^\\.SyncArchive$|^\\.SyncID$|^\\.SyncIgnore$|\\~$/;\n\n    /**\n     * Glob definition of files and folders that should be excluded directly\n     * inside node domain watching with chokidar\n     */\n    var defaultIgnoreGlobs = [\n        \"**/(.pyc|.git|.gitmodules|.svn|.DS_Store|Thumbs.db|.hg|CVS|.hgtags|.idea|.c9revisions|.SyncArchive|.SyncID|.SyncIgnore)\",\n        \"**/bower_components\",\n        \"**/node_modules\"\n    ];\n\n    /**\n     * @private\n     * RegEx to validate a file path.\n     */\n    var _invalidChars = /([?\\*\\|\\<\\>\"]+|\\/{2,}|\\.{2,}|\\.$)/i;\n\n    /**\n     * @private\n     * RegEx to validate if a filename is not allowed even if the system allows it.\n     * This is done to prevent cross-platform issues.\n     */\n    var _illegalFilenamesRegEx = /((\\b(com[0-9]+|lpt[0-9]+|nul|con|prn|aux)\\b)|\\.+$|\\/+|\\\\+|\\:)/i;\n\n    /**\n     * Returns true if this matches valid filename specifications.\n     * See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx\n     *\n     * TODO: This likely belongs in FileUtils.\n     *\n     * @param {string} filename to check\n     * @return {boolean} true if the filename is valid\n     */\n    function isValidFilename(filename) {\n        // Fix issue adobe#13099\n        // See https://github.com/adobe/brackets/issues/13099\n        return !(\n            filename.match(_invalidChars)|| filename.match(_illegalFilenamesRegEx)\n        );\n    }\n\n    /**\n     * Returns true if given path is valid.\n     *\n     * @param {string} path to check\n     * @return {boolean} true if the filename is valid\n     */\n    function isValidPath(path) {\n        // Fix issue adobe#13099\n        // See https://github.com/adobe/brackets/issues/13099\n        return !(path.match(_invalidChars));\n    }\n\n    /**\n     * @private\n     * @see #shouldShow\n     */\n    function _shouldShowName(name) {\n        return !_exclusionListRegEx.test(name);\n    }\n\n    /**\n     * Returns false for files and directories that are not commonly useful to display.\n     *\n     * @param {!FileSystemEntry} entry File or directory to filter\n     * @return {boolean} true if the file should be displayed\n     */\n    function shouldShow(entry) {\n        return _shouldShowName(entry.name);\n    }\n\n    // Constants used by the ProjectModel\n\n    var FILE_RENAMING     = 0,\n        FILE_CREATING     = 1,\n        RENAME_CANCELLED  = 2;\n\n\n    /**\n     * @private\n     *\n     * Determines if a path string is pointing to a directory (does it have a trailing slash?)\n     *\n     * @param {string} path Path to test.\n     */\n    function _pathIsFile(path) {\n        return _.last(path) !== \"/\";\n    }\n\n    /**\n     * @private\n     *\n     * Gets the FileSystem object (either a File or Directory) based on the path provided.\n     *\n     * @param {string} path Path to retrieve\n     */\n    function _getFSObject(path) {\n        if (!path) {\n            return path;\n        } else if (_pathIsFile(path)) {\n            return FileSystem.getFileForPath(path);\n        }\n        return FileSystem.getDirectoryForPath(path);\n    }\n\n    /**\n     * @private\n     *\n     * Given what is possible a FileSystem object, return its path (if a string path is passed in,\n     * it will be returned as-is).\n     *\n     * @param {FileSystemEntry} fsobj Object from which the path should be extracted\n     */\n    function _getPathFromFSObject(fsobj) {\n        if (fsobj && fsobj.fullPath) {\n            return fsobj.fullPath;\n        }\n        return fsobj;\n    }\n\n    /**\n     * Creates a new file or folder at the given path. The returned promise is rejected if the filename\n     * is invalid, the new path already exists or some other filesystem error comes up.\n     *\n     * @param {string} path path to create\n     * @param {boolean} isFolder true if the new entry is a folder\n     * @return {$.Promise} resolved when the file or directory has been created.\n     */\n    function doCreate(path, isFolder) {\n        var d = new $.Deferred();\n        var filename = FileUtils.getBaseName(path);\n\n        // Check if filename\n        if (!isValidFilename(filename)){\n            return d.reject(ERROR_INVALID_FILENAME).promise();\n        }\n\n        // Check if fullpath with filename is valid\n        // This check is used to circumvent directory jumps (Like ../..)\n        if (!isValidPath(path)) {\n            return d.reject(ERROR_INVALID_FILENAME).promise();\n        }\n\n        FileSystem.resolve(path, function (err) {\n            if (!err) {\n                // Item already exists, fail with error\n                d.reject(FileSystemError.ALREADY_EXISTS);\n            } else {\n                if (isFolder) {\n                    var directory = FileSystem.getDirectoryForPath(path);\n\n                    directory.create(function (err) {\n                        if (err) {\n                            d.reject(err);\n                        } else {\n                            d.resolve(directory);\n                        }\n                    });\n                } else {\n                    // Create an empty file\n                    var file = FileSystem.getFileForPath(path);\n\n                    FileUtils.writeText(file, \"\").then(function () {\n                        d.resolve(file);\n                    }, d.reject);\n                }\n            }\n        });\n\n        return d.promise();\n    }\n\n    /**\n     * @constructor\n     *\n     * The ProjectModel provides methods for accessing information about the current open project.\n     * It also manages the view model to display a FileTreeView of the project.\n     *\n     * Events:\n     * - EVENT_CHANGE (`change`) - Fired when there's a change that should refresh the UI\n     * - EVENT_SHOULD_SELECT (`select`) - Fired when a selection has been made in the file tree and the file tree should be selected\n     * - EVENT_SHOULD_FOCUS (`focus`)\n     * - ERROR_CREATION (`creationError`) - Triggered when there's a problem creating a file\n     */\n    function ProjectModel(initial) {\n        initial = initial || {};\n        if (initial.projectRoot) {\n            this.projectRoot = initial.projectRoot;\n        }\n\n        if (initial.focused !== undefined) {\n            this._focused = initial.focused;\n        }\n        this._viewModel = new FileTreeViewModel.FileTreeViewModel();\n        this._viewModel.on(FileTreeViewModel.EVENT_CHANGE, function () {\n            this.trigger(EVENT_CHANGE);\n        }.bind(this));\n        this._selections = {};\n    }\n    EventDispatcher.makeEventDispatcher(ProjectModel.prototype);\n\n    /**\n     * @type {Directory}\n     *\n     * The root Directory object for the project.\n     */\n    ProjectModel.prototype.projectRoot = null;\n\n    /**\n     * @private\n     * @type {FileTreeViewModel}\n     *\n     * The view model for this project.\n     */\n    ProjectModel.prototype._viewModel = null;\n\n    /**\n     * @private\n     * @type {string}\n     *\n     * Encoded URL\n     * @see {@link ProjectModel#getBaseUrl}, {@link ProjectModel#setBaseUrl}\n     */\n    ProjectModel.prototype._projectBaseUrl = \"\";\n\n    /**\n     * @private\n     * @type {{selected: ?string, context: ?string, previousContext: ?string, rename: ?Object}}\n     *\n     * Keeps track of selected files, context, previous context and files\n     * that are being renamed or created.\n     */\n    ProjectModel.prototype._selections = null;\n\n    /**\n     * @private\n     * @type {boolean}\n     *\n     * Flag to store whether the file tree has focus.\n     */\n    ProjectModel.prototype._focused = true;\n\n    /**\n     * @private\n     * @type {string}\n     *\n     * Current file path being viewed.\n     */\n    ProjectModel.prototype._currentPath = null;\n\n    /**\n     * @private\n     * @type {?$.Promise.<Array<File>>}\n     *\n     * A promise that is resolved with an array of all project files. Used by\n     * ProjectManager.getAllFiles().\n     */\n    ProjectModel.prototype._allFilesCachePromise = null;\n\n    /**\n     * Sets whether the file tree is focused or not.\n     *\n     * @param {boolean} focused True if the file tree has the focus.\n     */\n    ProjectModel.prototype.setFocused = function (focused) {\n        this._focused = focused;\n        if (!focused) {\n            this.setSelected(null);\n        }\n    };\n\n    /**\n     * Sets the width of the selection bar.\n     *\n     * @param {int} width New width\n     */\n    ProjectModel.prototype.setSelectionWidth = function (width) {\n        this._viewModel.setSelectionWidth(width);\n    };\n\n    /**\n     * Tracks the scroller position.\n     *\n     * @param {int} scrollWidth Width of the tree container\n     * @param {int} scrollTop Top of scroll position\n     * @param {int} scrollLeft Left of scroll position\n     * @param {int} offsetTop Top of scroller element\n     */\n    ProjectModel.prototype.setScrollerInfo = function (scrollWidth, scrollTop, scrollLeft, offsetTop) {\n        this._viewModel.setSelectionScrollerInfo(scrollWidth, scrollTop, scrollLeft, offsetTop);\n    };\n\n    /**\n     * Returns the encoded Base URL of the currently loaded project, or empty string if no project\n     * is open (during startup, or running outside of app shell).\n     * @return {String}\n     */\n    ProjectModel.prototype.getBaseUrl = function getBaseUrl() {\n        return this._projectBaseUrl;\n    };\n\n    /**\n     * Sets the encoded Base URL of the currently loaded project.\n     * @param {String}\n     */\n    ProjectModel.prototype.setBaseUrl = function setBaseUrl(projectBaseUrl) {\n        // Ensure trailing slash to be consistent with projectRoot.fullPath\n        // so they're interchangable (i.e. easy to convert back and forth)\n        if (projectBaseUrl.length > 0 && projectBaseUrl[projectBaseUrl.length - 1] !== \"/\") {\n            projectBaseUrl += \"/\";\n        }\n\n        this._projectBaseUrl = projectBaseUrl;\n        return projectBaseUrl;\n    };\n\n    /**\n     * Returns true if absPath lies within the project, false otherwise.\n     * Does not support paths containing \"..\"\n     *\n     * @param {string|FileSystemEntry} absPathOrEntry\n     * @return {boolean}\n     */\n    ProjectModel.prototype.isWithinProject = function isWithinProject(absPathOrEntry) {\n        var absPath = absPathOrEntry.fullPath || absPathOrEntry;\n        return (this.projectRoot && absPath.indexOf(this.projectRoot.fullPath) === 0);\n    };\n\n    /**\n     * If absPath lies within the project, returns a project-relative path. Else returns absPath\n     * unmodified.\n     * Does not support paths containing \"..\"\n     *\n     * @param {!string} absPath\n     * @return {!string}\n     */\n    ProjectModel.prototype.makeProjectRelativeIfPossible = function makeProjectRelativeIfPossible(absPath) {\n        if (absPath && this.isWithinProject(absPath)) {\n            return absPath.slice(this.projectRoot.fullPath.length);\n        }\n        return absPath;\n    };\n\n    /**\n     * Returns a valid directory within the project, either the path (or Directory object)\n     * provided or the project root.\n     *\n     * @param {string|Directory} path Directory path to verify against the project\n     * @return {string} A directory path within the project.\n     */\n    ProjectModel.prototype.getDirectoryInProject = function (path) {\n        if (path && typeof path === \"string\") {\n            if (_.last(path) !== \"/\") {\n                path += \"/\";\n            }\n        } else if (path && path.isDirectory) {\n            path = path.fullPath;\n        } else {\n            path = null;\n        }\n\n        if (!path || (typeof path !== \"string\") || !this.isWithinProject(path)) {\n            path = this.projectRoot.fullPath;\n        }\n        return path;\n    };\n\n    /**\n     * @private\n     *\n     * Returns a promise that resolves with a cached copy of all project files.\n     * Used by ProjectManager.getAllFiles(). Ensures that at most one un-cached\n     * directory traversal is active at a time, which is useful at project load\n     * time when watchers (and hence filesystem-level caching) has not finished\n     * starting up. The cache is cleared on every filesystem change event, and\n     * also on project load and unload.\n     *\n     * @param {boolean} true to sort files by their paths\n     * @return {$.Promise.<Array.<File>>}\n     */\n    ProjectModel.prototype._getAllFilesCache = function _getAllFilesCache(sort) {\n        if (!this._allFilesCachePromise) {\n            var deferred = new $.Deferred(),\n                allFiles = [],\n                allFilesVisitor = function (entry) {\n                    if (shouldShow(entry)) {\n                        if (entry.isFile) {\n                            allFiles.push(entry);\n                        }\n                        return true;\n                    }\n                    return false;\n                };\n\n            this._allFilesCachePromise = deferred.promise();\n\n            var projectIndexTimer = PerfUtils.markStart(\"Creating project files cache: \" +\n                                                        this.projectRoot.fullPath),\n                options = {\n                    sortList : sort\n                };\n\n            this.projectRoot.visit(allFilesVisitor, options, function (err) {\n                if (err) {\n                    PerfUtils.finalizeMeasurement(projectIndexTimer);\n                    deferred.reject(err);\n                } else {\n                    PerfUtils.addMeasurement(projectIndexTimer);\n                    deferred.resolve(allFiles);\n                }\n            }.bind(this));\n        }\n\n        return this._allFilesCachePromise;\n    };\n\n    /**\n     * Returns an Array of all files for this project, optionally including\n     * files additional files provided. Files are filtered out by shouldShow().\n     *\n     * @param {function (File, number):boolean=} filter Optional function to filter\n     *          the file list (does not filter directory traversal). API matches Array.filter().\n     * @param {Array.<File>=} additionalFiles Additional files to include (for example, the WorkingSet)\n     *          Only adds files that are *not* under the project root or untitled documents.\n     * @param {boolean} true to sort files by their paths\n     *\n     * @return {$.Promise} Promise that is resolved with an Array of File objects.\n     */\n    ProjectModel.prototype.getAllFiles = function getAllFiles(filter, additionalFiles, sort) {\n        // The filter and includeWorkingSet params are both optional.\n        // Handle the case where filter is omitted but includeWorkingSet is\n        // specified.\n        if (additionalFiles === undefined && typeof (filter) !== \"function\") {\n            additionalFiles = filter;\n            filter = null;\n        }\n\n        var filteredFilesDeferred = new $.Deferred();\n\n        // First gather all files in project proper\n        // Note that with proper promises we may be able to fix this so that we're not doing this\n        // anti-pattern of creating a separate deferred rather than just chaining off of the promise\n        // from _getAllFilesCache\n        this._getAllFilesCache(sort).done(function (result) {\n            // Add working set entries, if requested\n            if (additionalFiles) {\n                additionalFiles.forEach(function (file) {\n                    if (result.indexOf(file) === -1 && !(file instanceof InMemoryFile)) {\n                        result.push(file);\n                    }\n                });\n            }\n\n            // Filter list, if requested\n            if (filter) {\n                result = result.filter(filter);\n            }\n\n            // If a done handler attached to the returned filtered files promise\n            // throws an exception that isn't handled here then it will leave\n            // _allFilesCachePromise in an inconsistent state such that no\n            // additional done handlers will ever be called!\n            try {\n                filteredFilesDeferred.resolve(result);\n            } catch (e) {\n                console.error(\"Unhandled exception in getAllFiles handler: \" + e, e.stack);\n            }\n        }).fail(function (err) {\n            try {\n                filteredFilesDeferred.reject(err);\n            } catch (e) {\n                console.error(\"Unhandled exception in getAllFiles handler: \" + e, e.stack);\n            }\n        });\n\n        return filteredFilesDeferred.promise();\n    };\n\n    /**\n     * @private\n     *\n     * Resets the all files cache.\n     */\n    ProjectModel.prototype._resetCache = function _resetCache() {\n        this._allFilesCachePromise = null;\n    };\n\n    /**\n     * Sets the project root (effectively resetting this ProjectModel).\n     *\n     * @param {Directory} projectRoot new project root\n     * @return {$.Promise} resolved when the project root has been updated\n     */\n    ProjectModel.prototype.setProjectRoot = function (projectRoot) {\n        this.projectRoot = projectRoot;\n        this._resetCache();\n        this._viewModel._rootChanged();\n\n        var d = new $.Deferred(),\n            self = this;\n\n        projectRoot.getContents(function (err, contents) {\n            if (err) {\n                d.reject(err);\n            } else {\n                self._viewModel.setDirectoryContents(\"\", contents);\n                d.resolve();\n            }\n        });\n        return d.promise();\n    };\n\n    /**\n     * @private\n     *\n     * Gets the contents of a directory at the given path.\n     *\n     * @param {string} path path to retrieve\n     * @return {$.Promise} Resolved with the directory contents.\n     */\n    ProjectModel.prototype._getDirectoryContents = function (path) {\n        var d = new $.Deferred();\n        FileSystem.getDirectoryForPath(path).getContents(function (err, contents) {\n            if (err) {\n                d.reject(err);\n            } else {\n                d.resolve(contents);\n            }\n        });\n        return d.promise();\n    };\n\n    /**\n     * Opens or closes the given directory in the file tree.\n     *\n     * @param {string} path Path to open\n     * @param {boolean} open `true` to open the path\n     * @return {$.Promise} resolved when the path has been opened.\n     */\n    ProjectModel.prototype.setDirectoryOpen = function (path, open) {\n        var projectRelative = this.makeProjectRelativeIfPossible(path),\n            needsLoading    = !this._viewModel.isPathLoaded(projectRelative),\n            d               = new $.Deferred(),\n            self            = this;\n\n        function onSuccess(contents) {\n            // Update the view model\n            if (contents) {\n                self._viewModel.setDirectoryContents(projectRelative, contents);\n            }\n\n            if (open) {\n                self._viewModel.openPath(projectRelative);\n                if (self._focused) {\n                    var currentPathInProject = self.makeProjectRelativeIfPossible(self._currentPath);\n                    if (self._viewModel.isFilePathVisible(currentPathInProject)) {\n                        self.setSelected(self._currentPath, true);\n                    } else {\n                        self.setSelected(null);\n                    }\n                }\n            } else {\n                self._viewModel.setDirectoryOpen(projectRelative, false);\n                var selected = self._selections.selected;\n                if (selected) {\n                    var relativeSelected = self.makeProjectRelativeIfPossible(selected);\n                    if (!self._viewModel.isFilePathVisible(relativeSelected)) {\n                        self.setSelected(null);\n                    }\n                }\n            }\n\n            d.resolve();\n        }\n\n        // If the view model doesn't have the data it needs, we load it now, otherwise we can just\n        // manage the selection and resovle the promise.\n        if (open && needsLoading) {\n            var parentDirectory = FileUtils.getDirectoryPath(FileUtils.stripTrailingSlash(path));\n            this.setDirectoryOpen(parentDirectory, true).then(function () {\n                self._getDirectoryContents(path).then(onSuccess).fail(function (err) {\n                    d.reject(err);\n                });\n            }, function (err) {\n                d.reject(err);\n            });\n        } else {\n            onSuccess();\n        }\n\n        return d.promise();\n    };\n\n    /**\n     * Shows the given path in the tree and selects it if it's a file. Any intermediate directories\n     * will be opened and a promise is returned to show when the entire operation is complete.\n     *\n     * @param {string|File|Directory} path full path to the file or directory\n     * @return {$.Promise} promise resolved when the path is shown\n     */\n    ProjectModel.prototype.showInTree = function (path) {\n        var d = new $.Deferred();\n        path = _getPathFromFSObject(path);\n\n        if (!this.isWithinProject(path)) {\n            return d.resolve().promise();\n        }\n\n        var parentDirectory = FileUtils.getDirectoryPath(path),\n            self = this;\n        this.setDirectoryOpen(parentDirectory, true).then(function () {\n            if (_pathIsFile(path)) {\n                self.setSelected(path);\n            }\n            d.resolve();\n        }, function (err) {\n            d.reject(err);\n        });\n        return d.promise();\n    };\n\n    /**\n     * Selects the given path in the file tree and opens the file (unless doNotOpen is specified).\n     * Directories will not be selected.\n     *\n     * When the selection changes, any rename operation that is currently underway will be completed.\n     *\n     * @param {string} path full path to the file being selected\n     * @param {boolean} doNotOpen `true` if the file should not be opened.\n     */\n    ProjectModel.prototype.setSelected = function (path, doNotOpen) {\n        path = _getPathFromFSObject(path);\n\n        // Directories are not selectable\n        if (!_pathIsFile(path)) {\n            return;\n        }\n\n        var oldProjectPath = this.makeProjectRelativeIfPossible(this._selections.selected),\n            pathInProject = this.makeProjectRelativeIfPossible(path);\n\n        if (path && !this._viewModel.isFilePathVisible(pathInProject)) {\n            path = null;\n            pathInProject = null;\n        }\n\n        this.performRename();\n\n        this._viewModel.moveMarker(\"selected\", oldProjectPath, pathInProject);\n        if (this._selections.context) {\n            this._viewModel.moveMarker(\"context\", this.makeProjectRelativeIfPossible(this._selections.context), null);\n            delete this._selections.context;\n        }\n\n        var previousSelection = this._selections.selected;\n        this._selections.selected = path;\n\n        if (path) {\n            if (!doNotOpen) {\n                this.trigger(EVENT_SHOULD_SELECT, {\n                    path: path,\n                    previousPath: previousSelection,\n                    hadFocus: this._focused\n                });\n            }\n\n            this.trigger(EVENT_SHOULD_FOCUS);\n        }\n    };\n\n    /**\n     * Gets the currently selected file or directory.\n     *\n     * @return {FileSystemEntry} the filesystem object for the currently selected file\n     */\n    ProjectModel.prototype.getSelected = function () {\n        return _getFSObject(this._selections.selected);\n    };\n\n    /**\n     * Keeps track of which file is currently being edited.\n     *\n     * @param {File|string} curFile Currently edited file.\n     */\n    ProjectModel.prototype.setCurrentFile = function (curFile) {\n        this._currentPath = _getPathFromFSObject(curFile);\n    };\n\n    /**\n     * Adds the file at the given path to the Working Set and selects it there.\n     *\n     * @param {string} path full path of file to open in Working Set\n     */\n    ProjectModel.prototype.selectInWorkingSet = function (path) {\n        this.performRename();\n        this.trigger(EVENT_SHOULD_SELECT, {\n            path: path,\n            add: true\n        });\n    };\n\n    /**\n     * Sets the context (for context menu operations) to the given path. This is independent from the\n     * open/selected file.\n     *\n     * @param {string} path full path of file or directory to which the context should be setBaseUrl\n     * @param {boolean} _doNotRename True if this context change should not cause a rename operation to finish. This is a special case that goes with context menu handling.\n     * @param {boolean} _saveContext True if the current context should be saved (see comment below)\n     */\n    ProjectModel.prototype.setContext = function (path, _doNotRename, _saveContext) {\n        // This bit is not ideal: when the user right-clicks on an item in the file tree\n        // and there is already a context menu up, the FileTreeView sends a signal to set the\n        // context to the new element but the PopupManager follows that with a message that it's\n        // closing the context menu (because it closes the previous one and then opens the new\n        // one.) This timing means that we need to provide some special case handling here.\n        if (_saveContext) {\n            if (!path) {\n                this._selections.previousContext = this._selections.context;\n            } else {\n                this._selections.previousContext = path;\n            }\n        } else {\n            delete this._selections.previousContext;\n        }\n\n        path = _getPathFromFSObject(path);\n\n        if (!_doNotRename) {\n            this.performRename();\n        }\n        var currentContext = this._selections.context;\n        this._selections.context = path;\n        this._viewModel.moveMarker(\"context\", this.makeProjectRelativeIfPossible(currentContext),\n                                   this.makeProjectRelativeIfPossible(path));\n    };\n\n    /**\n     * Restores the context to the last non-null context. This is specifically here to handle\n     * the sequence of messages that we get from the project context menu.\n     */\n    ProjectModel.prototype.restoreContext = function () {\n        if (this._selections.previousContext) {\n            this.setContext(this._selections.previousContext);\n        }\n    };\n\n    /**\n     * Gets the currently selected context.\n     *\n     * @return {FileSystemEntry} filesystem object for the context file or directory\n     */\n    ProjectModel.prototype.getContext = function () {\n        return _getFSObject(this._selections.context);\n    };\n\n    /**\n     * Starts a rename operation for the file or directory at the given path. If the path is\n     * not provided, the current context is used.\n     *\n     * If a rename operation is underway, it will be completed automatically.\n     *\n     * The Promise returned is resolved with an object with a `newPath` property with the renamed path. If the user cancels the operation, the promise is resolved with the value RENAME_CANCELLED.\n     *\n     * @param {string=} path optional path to start renaming\n     * @param {boolean=} isMoved optional flag which indicates whether the entry is being moved instead of renamed\n     * @return {$.Promise} resolved when the operation is complete.\n     */\n    ProjectModel.prototype.startRename = function (path, isMoved) {\n        var d = new $.Deferred();\n        path = _getPathFromFSObject(path);\n        if (!path) {\n            path = this._selections.context;\n            if (!path) {\n                return d.resolve().promise();\n            }\n        }\n\n        if (this._selections.rename && this._selections.rename.path === path) {\n            return d.resolve().promise();\n        }\n\n        if (!this.isWithinProject(path)) {\n            return d.reject({\n                type: ERROR_NOT_IN_PROJECT,\n                isFolder: !_pathIsFile(path),\n                fullPath: path\n            }).promise();\n        }\n\n        var projectRelativePath = this.makeProjectRelativeIfPossible(path);\n\n        if (!this._viewModel.isFilePathVisible(projectRelativePath)) {\n            this.showInTree(path);\n        }\n\n        if (!isMoved) {\n            if (path !== this._selections.context) {\n                this.setContext(path);\n            } else {\n                this.performRename();\n            }\n\n            this._viewModel.moveMarker(\"rename\", null,\n                projectRelativePath);\n        }\n        this._selections.rename = {\n            deferred: d,\n            type: FILE_RENAMING,\n            path: path,\n            newPath: path\n        };\n        return d.promise();\n    };\n\n    /**\n     * Sets the new value for the rename operation that is in progress (started previously with a call\n     * to `startRename`).\n     *\n     * @param {string} newPath new path for the file or directory being renamed\n     */\n    ProjectModel.prototype.setRenameValue = function (newPath) {\n        if (!this._selections.rename) {\n            return;\n        }\n        this._selections.rename.newPath = newPath;\n    };\n\n    /**\n     * Cancels the rename operation that is in progress. This resolves the original promise with\n     * a RENAME_CANCELLED value.\n     */\n    ProjectModel.prototype.cancelRename = function () {\n        var renameInfo = this._selections.rename;\n        if (!renameInfo) {\n            return;\n        }\n\n        // File creation is a special case.\n        if (renameInfo.type === FILE_CREATING) {\n            this._cancelCreating();\n            return;\n        }\n\n        this._viewModel.moveMarker(\"rename\", this.makeProjectRelativeIfPossible(renameInfo.path), null);\n        renameInfo.deferred.resolve(RENAME_CANCELLED);\n        delete this._selections.rename;\n        this.setContext(null);\n    };\n\n    /**\n     * Rename a file/folder. This will update the project tree data structures\n     * and send notifications about the rename.\n     *\n     * @param {string} oldPath Old name of the item with the path\n     * @param {string} newPath New name of the item with the path\n     * @param {string} newName New name of the item\n     * @param {boolean} isFolder True if item is a folder; False if it is a file.\n     * @return {$.Promise} A promise object that will be resolved or rejected when\n     *   the rename is finished.\n     */\n    function _renameItem(oldPath, newPath, newName, isFolder) {\n        var result = new $.Deferred();\n\n        if (oldPath === newPath) {\n            result.resolve();\n        } else if (!isValidFilename(newName)) {\n            result.reject(ERROR_INVALID_FILENAME);\n        } else {\n            var entry = isFolder ? FileSystem.getDirectoryForPath(oldPath) : FileSystem.getFileForPath(oldPath);\n            entry.rename(newPath, function (err) {\n                if (err) {\n                    result.reject(err);\n                } else {\n                    result.resolve();\n                }\n            });\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     *\n     * Renames the item at the old path to the new name provided.\n     *\n     * @param {string} oldPath full path to the current location of file or directory (should include trailing slash for directory)\n     * @param {string} newPath full path to the new location of the file or directory\n     * @param {string} newName new name for the file or directory\n     */\n    ProjectModel.prototype._renameItem = function (oldPath, newPath, newName) {\n        return _renameItem(oldPath, newPath, newName, !_pathIsFile(oldPath));\n    };\n\n    /**\n     * Completes the rename operation that is in progress.\n     */\n    ProjectModel.prototype.performRename = function () {\n        var renameInfo = this._selections.rename;\n        if (!renameInfo) {\n            return;\n        }\n        var oldPath         = renameInfo.path,\n            isFolder        = renameInfo.isFolder || !_pathIsFile(oldPath),\n            oldProjectPath  = this.makeProjectRelativeIfPossible(oldPath),\n\n            // To get the parent directory, we need to strip off the trailing slash on a directory name\n            parentDirectory = FileUtils.getDirectoryPath(isFolder ? FileUtils.stripTrailingSlash(oldPath) : oldPath),\n            oldName         = FileUtils.getBaseName(oldPath),\n            newPath         = renameInfo.newPath,\n            newName         = FileUtils.getBaseName(newPath),\n            viewModel       = this._viewModel,\n            self            = this;\n\n        if (renameInfo.type !== FILE_CREATING && oldPath === newPath) {\n            this.cancelRename();\n            return;\n        }\n\n        if (isFolder && _.last(newPath) !== \"/\") {\n            newPath += \"/\";\n        }\n\n        delete this._selections.rename;\n        delete this._selections.context;\n\n        viewModel.moveMarker(\"rename\", oldProjectPath, null);\n        viewModel.moveMarker(\"context\", oldProjectPath, null);\n        viewModel.moveMarker(\"creating\", oldProjectPath, null);\n\n        function finalizeRename() {\n            viewModel.renameItem(oldProjectPath, self.makeProjectRelativeIfPossible(newPath));\n            if (self._selections.selected && self._selections.selected.indexOf(oldPath) === 0) {\n                self._selections.selected = newPath + self._selections.selected.slice(oldPath.length);\n                self.setCurrentFile(newPath);\n            }\n        }\n\n        if (renameInfo.type === FILE_CREATING) {\n            this.createAtPath(newPath).done(function (entry) {\n                finalizeRename();\n                renameInfo.deferred.resolve(entry);\n            }).fail(function (error) {\n                self._viewModel.deleteAtPath(self.makeProjectRelativeIfPossible(renameInfo.path));\n                renameInfo.deferred.reject(error);\n            });\n        } else {\n            this._renameItem(oldPath, newPath, newName).then(function () {\n                finalizeRename();\n                renameInfo.deferred.resolve({\n                    newPath: newPath\n                });\n            }).fail(function (errorType) {\n                var errorInfo = {\n                    type: errorType,\n                    isFolder: isFolder,\n                    fullPath: oldPath\n                };\n                renameInfo.deferred.reject(errorInfo);\n            });\n        }\n    };\n\n    /**\n     * Creates a file or folder at the given path. Folder paths should have a trailing slash.\n     *\n     * If an error comes up during creation, the ERROR_CREATION event is triggered.\n     *\n     * @param {string} path full path to file or folder to create\n     * @return {$.Promise} resolved when creation is complete\n     */\n    ProjectModel.prototype.createAtPath = function (path) {\n        var isFolder  = !_pathIsFile(path),\n            name      = FileUtils.getBaseName(path),\n            self      = this;\n\n        return doCreate(path, isFolder).done(function (entry) {\n            if (!isFolder) {\n                self.selectInWorkingSet(entry.fullPath);\n            }\n        }).fail(function (error) {\n            self.trigger(ERROR_CREATION, {\n                type: error,\n                name: name,\n                isFolder: isFolder\n            });\n        });\n    };\n\n    /**\n     * Starts creating a file or folder with the given name in the given directory.\n     *\n     * The Promise returned is resolved with an object with a `newPath` property with the renamed path. If the user cancels the operation, the promise is resolved with the value RENAME_CANCELLED.\n     *\n     * @param {string} basedir directory that should contain the new entry\n     * @param {string} newName initial name for the new entry (the user can rename it)\n     * @param {boolean} isFolder `true` if the entry being created is a folder\n     * @return {$.Promise} resolved when the user is done creating the entry.\n     */\n    ProjectModel.prototype.startCreating = function (basedir, newName, isFolder) {\n        this.performRename();\n        var d = new $.Deferred(),\n            self = this;\n\n        this.setDirectoryOpen(basedir, true).then(function () {\n            self._viewModel.createPlaceholder(self.makeProjectRelativeIfPossible(basedir), newName, isFolder);\n            var promise = self.startRename(basedir + newName);\n            self._selections.rename.type = FILE_CREATING;\n            if (isFolder) {\n                self._selections.rename.isFolder = isFolder;\n            }\n            promise.then(d.resolve).fail(d.reject);\n        }).fail(function (err) {\n            d.reject(err);\n        });\n        return d.promise();\n    };\n\n    /**\n     * Cancels the creation process that is underway. The original promise returned will be resolved with the\n     * RENAME_CANCELLED value. The temporary entry added to the file tree will be deleted.\n     */\n    ProjectModel.prototype._cancelCreating = function () {\n        var renameInfo = this._selections.rename;\n        if (!renameInfo || renameInfo.type !== FILE_CREATING) {\n            return;\n        }\n        this._viewModel.deleteAtPath(this.makeProjectRelativeIfPossible(renameInfo.path));\n        renameInfo.deferred.resolve(RENAME_CANCELLED);\n        delete this._selections.rename;\n        this.setContext(null);\n    };\n\n    /**\n     * Sets the `sortDirectoriesFirst` option for the file tree view.\n     *\n     * @param {boolean} True if directories should appear first\n     */\n    ProjectModel.prototype.setSortDirectoriesFirst = function (sortDirectoriesFirst) {\n        this._viewModel.setSortDirectoriesFirst(sortDirectoriesFirst);\n    };\n\n    /**\n     * Gets an array of arrays where each entry of the top-level array has an array\n     * of paths that are at the same depth in the tree. All of the paths are full paths.\n     *\n     * @return {Array.<Array.<string>>} Array of array of full paths, organized by depth in the tree.\n     */\n    ProjectModel.prototype.getOpenNodes = function () {\n        return this._viewModel.getOpenNodes(this.projectRoot.fullPath);\n    };\n\n    /**\n     * Reopens a set of nodes in the tree by full path.\n     * @param {Array.<Array.<string>>} nodesByDepth An array of arrays of node ids to reopen. The ids within\n     *     each sub-array are reopened in parallel, and the sub-arrays are reopened in order, so they should\n     *     be sorted by depth within the tree.\n     * @return {$.Deferred} A promise that will be resolved when all nodes have been fully\n     *     reopened.\n     */\n    ProjectModel.prototype.reopenNodes = function (nodesByDepth) {\n        var deferred = new $.Deferred();\n\n        if (!nodesByDepth || nodesByDepth.length === 0) {\n            // All paths are opened and fully rendered.\n            return deferred.resolve().promise();\n        } else {\n            var self = this;\n            return Async.doSequentially(nodesByDepth, function (toOpenPaths) {\n                return Async.doInParallel(\n                    toOpenPaths,\n                    function (path) {\n                        return self._getDirectoryContents(path).then(function (contents) {\n                            var relative = self.makeProjectRelativeIfPossible(path);\n                            self._viewModel.setDirectoryContents(relative, contents);\n                            self._viewModel.setDirectoryOpen(relative, true);\n                        });\n                    },\n                    false\n                );\n            });\n        }\n    };\n\n    /**\n     * Clears caches and refreshes the contents of the tree.\n     *\n     * @return {$.Promise} resolved when the tree has been refreshed\n     */\n    ProjectModel.prototype.refresh = function () {\n        var projectRoot = this.projectRoot,\n            openNodes   = this.getOpenNodes(),\n            self        = this,\n            selections  = this._selections,\n            viewModel   = this._viewModel,\n            deferred    = new $.Deferred();\n\n        this.setProjectRoot(projectRoot).then(function () {\n            self.reopenNodes(openNodes).then(function () {\n                if (selections.selected) {\n                    viewModel.moveMarker(\"selected\", null, self.makeProjectRelativeIfPossible(selections.selected));\n                }\n\n                if (selections.context) {\n                    viewModel.moveMarker(\"context\", null, self.makeProjectRelativeIfPossible(selections.context));\n                }\n\n                if (selections.rename) {\n                    viewModel.moveMarker(\"rename\", null, self.makeProjectRelativeIfPossible(selections.rename));\n                }\n\n                deferred.resolve();\n            });\n        });\n\n        return deferred.promise();\n    };\n\n    /**\n     * Handles filesystem change events and prepares the update for the view model.\n     *\n     * @param {?(File|Directory)} entry File or Directory changed\n     * @param {Array.<FileSystemEntry>=} added If entry is a Directory, contains zero or more added children\n     * @param {Array.<FileSystemEntry>=} removed If entry is a Directory, contains zero or more removed\n     */\n    ProjectModel.prototype.handleFSEvent = function (entry, added, removed) {\n        this._resetCache();\n\n        if (!entry) {\n            this.refresh();\n            return;\n        }\n\n        if (!this.isWithinProject(entry)) {\n            return;\n        }\n\n        var changes = {},\n            self = this;\n\n        if (entry.isFile) {\n            changes.changed = [\n                this.makeProjectRelativeIfPossible(entry.fullPath)\n            ];\n        } else {\n            // Special case: a directory passed in without added and removed values\n            // needs to be updated.\n            if (!added && !removed) {\n                entry.getContents(function (err, contents) {\n                    if (err) {\n                        console.error(\"Unexpected error refreshing file tree for directory \" + entry.fullPath + \": \" + err, err.stack);\n                        return;\n                    }\n                    self._viewModel.setDirectoryContents(self.makeProjectRelativeIfPossible(entry.fullPath), contents);\n                });\n\n                // Exit early because we can't update the viewModel until we get the directory contents.\n                return;\n            }\n        }\n\n        if (added) {\n            changes.added = added.map(function (entry) {\n                return self.makeProjectRelativeIfPossible(entry.fullPath);\n            });\n        }\n\n        if (removed) {\n            if (this._selections.selected &&\n                    _.find(removed, { fullPath: this._selections.selected })) {\n                this.setSelected(null);\n            }\n\n            if (this._selections.rename &&\n                    _.find(removed, { fullPath: this._selections.rename.path })) {\n                this.cancelRename();\n            }\n\n            if (this._selections.context &&\n                    _.find(removed, { fullPath: this._selections.context })) {\n                this.setContext(null);\n            }\n            changes.removed = removed.map(function (entry) {\n                return self.makeProjectRelativeIfPossible(entry.fullPath);\n            });\n        }\n\n        this._viewModel.processChanges(changes);\n    };\n\n    /**\n     * Closes the directory at path and recursively closes all of its children.\n     *\n     * @param {string} path Path of subtree to close\n     */\n    ProjectModel.prototype.closeSubtree = function (path) {\n        this._viewModel.closeSubtree(this.makeProjectRelativeIfPossible(path));\n    };\n\n    /**\n     * Toggle the open state of subdirectories.\n     * @param {!string}  path        parent directory\n     * @param {boolean} openOrClose  true to open directory, false to close\n     * @return {$.Promise} promise resolved when the directories are open\n     */\n    ProjectModel.prototype.toggleSubdirectories = function (path, openOrClose) {\n        var self = this,\n            d = new $.Deferred();\n\n        this.setDirectoryOpen(path, true).then(function () {\n            var projectRelativePath = self.makeProjectRelativeIfPossible(path),\n                childNodes = self._viewModel.getChildDirectories(projectRelativePath);\n\n            Async.doInParallel(childNodes, function (node) {\n                return self.setDirectoryOpen(path + node, openOrClose);\n            }, true).then(function () {\n                d.resolve();\n            }, function (err) {\n                d.reject(err);\n            });\n        });\n\n        return d.promise();\n    };\n\n    /**\n     * Although Brackets is generally standardized on folder paths with a trailing \"/\", some APIs here\n     * receive project paths without \"/\" due to legacy preference storage formats, etc.\n     * @param {!string} fullPath  Path that may or may not end in \"/\"\n     * @return {!string} Path that ends in \"/\"\n     */\n    function _ensureTrailingSlash(fullPath) {\n        if (_pathIsFile(fullPath)) {\n            return fullPath + \"/\";\n        }\n        return fullPath;\n    }\n\n    /**\n     * @private\n     *\n     * Returns the full path to the welcome project, which we open on first launch.\n     *\n     * @param {string} sampleUrl URL for getting started project\n     * @param {string} initialPath Path to Brackets directory (see {@link FileUtils::#getNativeBracketsDirectoryPath})\n     * @return {!string} fullPath reference\n     */\n    function _getWelcomeProjectPath(sampleUrl, initialPath) {\n        if (sampleUrl) {\n            // Back up one more folder. The samples folder is assumed to be at the same level as\n            // the src folder, and the sampleUrl is relative to the samples folder.\n            initialPath = initialPath.substr(0, initialPath.lastIndexOf(\"/\")) + \"/samples/\" + sampleUrl;\n        }\n\n        return _ensureTrailingSlash(initialPath); // paths above weren't canonical\n    }\n\n    /**\n     * @private\n     *\n     * Adds the path to the list of welcome projects we've ever seen, if not on the list already.\n     *\n     * @param {string} path Path to possibly add\n     * @param {Array.<string>=} currentProjects Array of current welcome projects\n     * @return {Array.<string>} New array of welcome projects with the additional project added\n     */\n    function _addWelcomeProjectPath(path, currentProjects) {\n        var pathNoSlash = FileUtils.stripTrailingSlash(path);  // \"welcomeProjects\" pref has standardized on no trailing \"/\"\n\n        var newProjects;\n\n        if (currentProjects) {\n            newProjects = _.clone(currentProjects);\n        } else {\n            newProjects = [];\n        }\n\n        if (newProjects.indexOf(pathNoSlash) === -1) {\n            newProjects.push(pathNoSlash);\n        }\n        return newProjects;\n    }\n\n    /**\n     * Returns true if the given path is the same as one of the welcome projects we've previously opened,\n     * or the one for the current build.\n     *\n     * @param {string} path Path to check to see if it's a welcome project\n     * @param {string} welcomeProjectPath Current welcome project path\n     * @param {Array.<string>=} welcomeProjects All known welcome projects\n     */\n    function _isWelcomeProjectPath(path, welcomeProjectPath, welcomeProjects) {\n        if (path === welcomeProjectPath) {\n            return true;\n        }\n\n        // No match on the current path, and it's not a match if there are no previously known projects\n        if (!welcomeProjects) {\n            return false;\n        }\n\n        var pathNoSlash = FileUtils.stripTrailingSlash(path);  // \"welcomeProjects\" pref has standardized on no trailing \"/\"\n        return welcomeProjects.indexOf(pathNoSlash) !== -1;\n    }\n\n    exports._getWelcomeProjectPath  = _getWelcomeProjectPath;\n    exports._addWelcomeProjectPath  = _addWelcomeProjectPath;\n    exports._isWelcomeProjectPath   = _isWelcomeProjectPath;\n    exports._ensureTrailingSlash    = _ensureTrailingSlash;\n    exports._shouldShowName         = _shouldShowName;\n    exports._invalidChars           = \"? * | : / < > \\\\ | \\\" ..\";\n\n    exports.shouldShow              = shouldShow;\n    exports.defaultIgnoreGlobs      = defaultIgnoreGlobs;\n    exports.isValidFilename         = isValidFilename;\n    exports.isValidPath             = isValidPath;\n    exports.EVENT_CHANGE            = EVENT_CHANGE;\n    exports.EVENT_SHOULD_SELECT     = EVENT_SHOULD_SELECT;\n    exports.EVENT_SHOULD_FOCUS      = EVENT_SHOULD_FOCUS;\n    exports.ERROR_CREATION          = ERROR_CREATION;\n    exports.ERROR_INVALID_FILENAME  = ERROR_INVALID_FILENAME;\n    exports.ERROR_NOT_IN_PROJECT    = ERROR_NOT_IN_PROJECT;\n    exports.FILE_RENAMING           = FILE_RENAMING;\n    exports.FILE_CREATING           = FILE_CREATING;\n    exports.RENAME_CANCELLED        = RENAME_CANCELLED;\n    exports.doCreate                = doCreate;\n    exports.ProjectModel            = ProjectModel;\n});\n"
  },
  {
    "path": "src/project/SidebarView.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * The view that controls the showing and hiding of the sidebar.\n *\n * Although the sidebar view doesn't dispatch any events directly, it is a\n * resizable element (../utils/Resizer.js), which means it can dispatch Resizer\n * events.  For example, if you want to listen for the sidebar showing\n * or hiding itself, set up listeners for the corresponding Resizer events,\n * panelCollapsed and panelExpanded:\n *\n *      $(\"#sidebar\").on(\"panelCollapsed\", ...);\n *      $(\"#sidebar\").on(\"panelExpanded\", ...);\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit         = require(\"utils/AppInit\"),\n        ProjectManager  = require(\"project/ProjectManager\"),\n        WorkingSetView  = require(\"project/WorkingSetView\"),\n        MainViewManager = require(\"view/MainViewManager\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        Commands        = require(\"command/Commands\"),\n        Strings         = require(\"strings\"),\n        Resizer         = require(\"utils/Resizer\"),\n        _               = require(\"thirdparty/lodash\");\n\n    // These vars are initialized by the htmlReady handler\n    // below since they refer to DOM elements\n    var $sidebar,\n        $gearMenu,\n        $splitViewMenu,\n        $projectTitle,\n        $projectFilesContainer,\n        $workingSetViewsContainer;\n\n    var _cmdSplitNone,\n        _cmdSplitVertical,\n        _cmdSplitHorizontal;\n\n    /**\n     * @private\n     * Update project title when the project root changes\n     */\n    function _updateProjectTitle() {\n        var displayName = ProjectManager.getProjectRoot().name;\n        var fullPath = ProjectManager.getProjectRoot().fullPath;\n\n        if (displayName === \"\" && fullPath === \"/\") {\n            displayName = \"/\";\n        }\n\n        $projectTitle.html(_.escape(displayName));\n        $projectTitle.attr(\"title\", fullPath);\n\n        // Trigger a scroll on the project files container to\n        // reposition the scroller shadows and avoid issue #2255\n        $projectFilesContainer.trigger(\"scroll\");\n    }\n\n    /**\n     * Toggle sidebar visibility.\n     */\n    function toggle() {\n        Resizer.toggle($sidebar);\n    }\n\n    /**\n     * Show the sidebar.\n     */\n    function show() {\n        Resizer.show($sidebar);\n    }\n\n    /**\n     * Hide the sidebar.\n     */\n    function hide() {\n        Resizer.hide($sidebar);\n    }\n\n    /**\n     * Returns the visibility state of the sidebar.\n     * @return {boolean} true if element is visible, false if it is not visible\n     */\n    function isVisible() {\n        return Resizer.isVisible($sidebar);\n    }\n\n    /**\n     * Update state of working set\n     * @private\n     */\n    function _updateWorkingSetState() {\n        if (MainViewManager.getPaneCount() === 1 &&\n                MainViewManager.getWorkingSetSize(MainViewManager.ACTIVE_PANE) === 0) {\n            $workingSetViewsContainer.hide();\n            $gearMenu.hide();\n        } else {\n            $workingSetViewsContainer.show();\n            $gearMenu.show();\n        }\n    }\n\n    /**\n     * Update state of splitview and option elements\n     * @private\n     */\n    function _updateUIStates() {\n        var spriteIndex,\n            ICON_CLASSES = [\"splitview-icon-none\", \"splitview-icon-vertical\", \"splitview-icon-horizontal\"],\n            layoutScheme = MainViewManager.getLayoutScheme();\n\n        if (layoutScheme.columns > 1) {\n            spriteIndex = 1;\n        } else if (layoutScheme.rows > 1) {\n            spriteIndex = 2;\n        } else {\n            spriteIndex = 0;\n        }\n\n        // SplitView Icon\n        $splitViewMenu.removeClass(ICON_CLASSES.join(\" \"))\n                      .addClass(ICON_CLASSES[spriteIndex]);\n\n        // SplitView Menu\n        _cmdSplitNone.setChecked(spriteIndex === 0);\n        _cmdSplitVertical.setChecked(spriteIndex === 1);\n        _cmdSplitHorizontal.setChecked(spriteIndex === 2);\n\n        // Options icon\n        _updateWorkingSetState();\n    }\n\n    /**\n     * Handle No Split Command\n     * @private\n     */\n    function _handleSplitViewNone() {\n        MainViewManager.setLayoutScheme(1, 1);\n    }\n\n    /**\n     * Handle Vertical Split Command\n     * @private\n     */\n    function _handleSplitViewVertical() {\n        MainViewManager.setLayoutScheme(1, 2);\n    }\n\n    /**\n     * Handle Horizontal Split Command\n     * @private\n     */\n    function _handleSplitViewHorizontal() {\n        MainViewManager.setLayoutScheme(2, 1);\n    }\n\n    // Initialize items dependent on HTML DOM\n    AppInit.htmlReady(function () {\n        $sidebar                  = $(\"#sidebar\");\n        $gearMenu                 = $sidebar.find(\".working-set-option-btn\");\n        $splitViewMenu            = $sidebar.find(\".working-set-splitview-btn\");\n        $projectTitle             = $sidebar.find(\"#project-title\");\n        $projectFilesContainer    = $sidebar.find(\"#project-files-container\");\n        $workingSetViewsContainer = $sidebar.find(\"#working-set-list-container\");\n\n        // init\n        $sidebar.on(\"panelResizeStart\", function (evt, width) {\n            $sidebar.find(\".sidebar-selection-extension\").css(\"display\", \"none\");\n            $sidebar.find(\".scroller-shadow\").css(\"display\", \"none\");\n        });\n\n        $sidebar.on(\"panelResizeUpdate\", function (evt, width) {\n            ProjectManager._setFileTreeSelectionWidth(width);\n        });\n\n        $sidebar.on(\"panelResizeEnd\", function (evt, width) {\n            $sidebar.find(\".sidebar-selection-extension\").css(\"display\", \"block\").css(\"left\", width);\n            $sidebar.find(\".scroller-shadow\").css(\"display\", \"block\");\n            $projectFilesContainer.triggerHandler(\"scroll\");\n            WorkingSetView.syncSelectionIndicator();\n        });\n\n        $sidebar.on(\"panelCollapsed\", function (evt, width) {\n            CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(Strings.CMD_SHOW_SIDEBAR);\n        });\n\n        $sidebar.on(\"panelExpanded\", function (evt, width) {\n            WorkingSetView.refresh();\n            $sidebar.find(\".scroller-shadow\").css(\"display\", \"block\");\n            $sidebar.find(\".sidebar-selection-extension\").css(\"left\", width);\n            $projectFilesContainer.triggerHandler(\"scroll\");\n            WorkingSetView.syncSelectionIndicator();\n            CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(Strings.CMD_HIDE_SIDEBAR);\n        });\n\n        // AppInit.htmlReady in utils/Resizer executes before, so it's possible that the sidebar\n        // is collapsed before we add the event. Check here initially\n        if (!$sidebar.is(\":visible\")) {\n            $sidebar.trigger(\"panelCollapsed\");\n        }\n\n        // wire up an event handler to monitor when panes are created\n        MainViewManager.on(\"paneCreate\", function (evt, paneId) {\n            WorkingSetView.createWorkingSetViewForPane($workingSetViewsContainer, paneId);\n        });\n\n        MainViewManager.on(\"paneLayoutChange\", function () {\n            _updateUIStates();\n        });\n\n        MainViewManager.on(\"workingSetAdd workingSetAddList workingSetRemove workingSetRemoveList workingSetUpdate\", function () {\n            _updateWorkingSetState();\n        });\n\n        // create WorkingSetViews for each pane already created\n        _.forEach(MainViewManager.getPaneIdList(), function (paneId) {\n            WorkingSetView.createWorkingSetViewForPane($workingSetViewsContainer, paneId);\n        });\n\n        _updateUIStates();\n\n        // Tooltips\n        $gearMenu.attr(\"title\", Strings.GEAR_MENU_TOOLTIP);\n        $splitViewMenu.attr(\"title\", Strings.SPLITVIEW_MENU_TOOLTIP);\n    });\n\n    ProjectManager.on(\"projectOpen\", _updateProjectTitle);\n\n    /**\n     * Register Command Handlers\n     */\n    _cmdSplitNone       = CommandManager.register(Strings.CMD_SPLITVIEW_NONE,       Commands.CMD_SPLITVIEW_NONE,       _handleSplitViewNone);\n    _cmdSplitVertical   = CommandManager.register(Strings.CMD_SPLITVIEW_VERTICAL,   Commands.CMD_SPLITVIEW_VERTICAL,   _handleSplitViewVertical);\n    _cmdSplitHorizontal = CommandManager.register(Strings.CMD_SPLITVIEW_HORIZONTAL, Commands.CMD_SPLITVIEW_HORIZONTAL, _handleSplitViewHorizontal);\n\n    CommandManager.register(Strings.CMD_TOGGLE_SIDEBAR, Commands.VIEW_HIDE_SIDEBAR, toggle);\n    CommandManager.register(Strings.CMD_SHOW_SIDEBAR, Commands.SHOW_SIDEBAR, show);\n    CommandManager.register(Strings.CMD_HIDE_SIDEBAR, Commands.HIDE_SIDEBAR, hide);\n\n    // Define public API\n    exports.toggle      = toggle;\n    exports.show        = show;\n    exports.hide        = hide;\n    exports.isVisible   = isVisible;\n});\n"
  },
  {
    "path": "src/project/WorkingSetSort.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Manages the workingSetList sort methods.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        MainViewManager         = require(\"view/MainViewManager\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        AppInit                 = require(\"utils/AppInit\"),\n        Strings                 = require(\"strings\"),\n        _                       = require(\"thirdparty/lodash\");\n\n    /**\n     * List of sorting method objects\n     * @private\n     * @type {Array.<Sort>}\n     */\n    var _sorts = [];\n\n    /**\n     * Denotes the current sort method object\n     * @private\n     * @type {Sort}\n     */\n    var _currentSort = null;\n\n    /**\n     * Denotes if automatic sorting is enabled or not\n     * @private\n     * @type {boolean}\n     */\n    var _automaticSort = false;\n\n\n    /**\n     * Maps Legacy sort method names  to new sort method names\n     * @private\n     * @type {object.<string: string>} oldname: newname\n     */\n    var _sortPrefConversionMap = {\n        \"view.sortWorkingSetByAdded\" : \"cmd.sortWorkingSetByAdded\",\n        \"view.sortWorkingSetByName\"  : \"cmd.sortWorkingSetByName\",\n        \"view.sortWorkingSetByType\"  : \"cmd.sortWorkingSetByType\"\n    };\n\n    /**\n     * Events which the sort command will listen for to trigger a sort\n     * @constant {string}\n     * @private\n     */\n    var _SORT_EVENT_NAMES = \"workingSetAdd workingSetAddList\";\n\n    /**\n     * Preference name\n     * @constant {string}\n     * @private\n     */\n    var _WORKING_SET_SORT_PREF = \"workingSetSortMethod\";\n\n    /**\n     * Legacy preference name\n     * @constant {string}\n     * @private\n     */\n    var _LEGACY_SORT_PREF = \"currentSort\";\n\n    /**\n     * Retrieves a Sort object by id\n     * @param {(string|Command)} command A command ID or a command object.\n     * @return {?Sort}\n     */\n    function get(command) {\n        var commandID;\n        if (!command) {\n            console.error(\"Attempting to get a Sort method with a missing required parameter: command\");\n            return;\n        }\n\n        if (typeof command === \"string\") {\n            commandID = command;\n        } else {\n            commandID = command.getID();\n        }\n        return _sorts[commandID];\n    }\n\n    /**\n     * Converts the old brackets working set sort preference into the modern paneview sort preference\n     * @private\n     * @param {!string} sortMethod - sort preference to convert\n     * @return {?string} new sort preference string or undefined if an sortMethod is not found\n     */\n    function _convertSortPref(sortMethod) {\n        if (!sortMethod) {\n            return null;\n        }\n\n        if (_sortPrefConversionMap.hasOwnProperty(sortMethod)) {\n            sortMethod = _sortPrefConversionMap[sortMethod];\n            PreferencesManager.setViewState(_WORKING_SET_SORT_PREF, sortMethod);\n        } else {\n            sortMethod = null;\n        }\n\n        return sortMethod;\n    }\n\n    /**\n     * @return {boolean} Enabled state of Automatic Sort.\n     */\n    function getAutomatic() {\n        return _automaticSort;\n    }\n\n    /**\n     * Removes the sort listeners.\n     * @private\n     */\n    function _removeListeners() {\n        MainViewManager.off(\".sort\");\n    }\n\n    /**\n     * Enables/Disables Automatic Sort depending on the value.\n     * @param {boolean} enable True to enable, false to disable.\n     */\n    function setAutomatic(enable) {\n        _automaticSort = enable;\n        PreferencesManager.setViewState(\"automaticSort\", _automaticSort);\n        CommandManager.get(Commands.CMD_WORKING_SORT_TOGGLE_AUTO).setChecked(_automaticSort);\n        _currentSort.setChecked(_automaticSort);\n\n        if (_automaticSort) {\n            _currentSort.sort();\n        } else {\n            _removeListeners();\n        }\n    }\n\n    /**\n     * Adds the current sort MainViewManager listeners.\n     * @private\n     */\n    function _addListeners() {\n        if (_automaticSort && _currentSort && _currentSort.getEvents()) {\n            MainViewManager\n                .on(_currentSort.getEvents(), function () {\n                    _currentSort.sort();\n                })\n                .on(\"_workingSetDisableAutoSort.sort\", function () {\n                    setAutomatic(false);\n                });\n        }\n    }\n\n\n    /**\n     * Sets the current sort method and checks it on the context menu.\n     * @private\n     * @param {Sort} newSort\n     */\n    function _setCurrentSort(newSort) {\n        if (_currentSort !== newSort) {\n            if (_currentSort !== null) {\n                _currentSort.setChecked(false);\n            }\n            if (_automaticSort) {\n                newSort.setChecked(true);\n            }\n\n            CommandManager.get(Commands.CMD_WORKING_SORT_TOGGLE_AUTO).setEnabled(!!newSort.getEvents());\n            PreferencesManager.setViewState(_WORKING_SET_SORT_PREF, newSort.getCommandID());\n            _currentSort = newSort;\n        }\n    }\n\n\n    /**\n     * @constructor\n     * @param {string} commandID A valid command identifier.\n     * @param {function(File, File): number} compareFn A valid sort\n     *      function (see register for a longer explanation).\n     * @param {string} events Space-separated WorkingSetSort possible events\n     *      ending with \".sort\".\n     */\n    function Sort(commandID, compareFn, events, automaticFn) {\n        this._commandID = commandID;\n        this._compareFn = compareFn;\n        this._events    = events;\n    }\n\n    /**\n     * The Command ID\n     * @return {string}\n     */\n    Sort.prototype.getCommandID = function () {\n        return this._commandID;\n    };\n\n    /**\n     * The compare function\n     * @return {function(File, File): number}\n     */\n    Sort.prototype.getCompareFn = function () {\n        return this._compareFn;\n    };\n\n    /**\n     * Gets the event that this sort object is listening to\n     * @return {string}\n     */\n    Sort.prototype.getEvents = function () {\n        return this._events;\n    };\n\n    /**\n     * Checks/Unchecks the command which will show a check in the menu\n     * @param {boolean} value\n     */\n    Sort.prototype.setChecked = function (value) {\n        var command = CommandManager.get(this._commandID);\n        if (command) {\n            command.setChecked(value);\n        }\n    };\n\n    /**\n     * Performs the sort and makes it the current sort method.\n     */\n    Sort.prototype.execute = function () {\n        _setCurrentSort(this);\n        this.sort();\n    };\n\n    /**\n     * Only performs the working set sort if this is the current sort.\n     */\n    Sort.prototype.sort = function () {\n        if (_currentSort === this) {\n            _removeListeners();\n            MainViewManager._sortWorkingSet(MainViewManager.ALL_PANES, this._compareFn);\n            _addListeners();\n        }\n    };\n\n\n    /**\n     * Registers a working set sort method.\n     * @param {(string|Command)} command A command ID or a command object\n     * @param {function(File, File): number} compareFn The function that\n     *      will be used inside JavaScript's sort function. The return a value\n     *      should be >0 (sort a to a lower index than b), =0 (leaves a and b\n     *      unchanged with respect to each other) or <0 (sort b to a lower index\n     *      than a) and must always returns the same value when given a specific\n     *      pair of elements a and b as its two arguments. Documentation at:\n     *      https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort\n     * @param {?string} events One or more space-separated event types that\n     *      DocumentManger uses. Each event passed will trigger the automatic\n     *      sort. If no events are passed, the automatic sort will be disabled\n     *      for that sort method.\n     * @return {?Sort}\n     */\n    function register(command, compareFn, events) {\n        var commandID = \"\";\n\n        if (!command || !compareFn) {\n            console.log(\"Attempting to register a Sort method with a missing required parameter: command or compare function\");\n            return;\n        }\n        if (typeof command === \"string\") {\n            commandID = command;\n        } else {\n            commandID = command.getID();\n        }\n\n        if (_sorts[commandID]) {\n            console.log(\"Attempting to register an already-registered Sort method: \" + command);\n            return;\n        }\n\n        // Adds \".sort\" to the end of each event to make them specific for the automatic sort.\n        if (events) {\n            events = events.split(\" \");\n            events.forEach(function (event, index) {\n                events[index] = events[index].trim() + \".sort\";\n            });\n            events = events.join(\" \");\n        }\n\n        var sort = new Sort(commandID, compareFn, events);\n        _sorts[commandID] = sort;\n        return sort;\n    }\n\n\n    /**\n     * Command Handler for CMD_WORKING_SORT_TOGGLE_AUTO\n     * @private\n     */\n    function _handleToggleAutoSort() {\n        setAutomatic(!getAutomatic());\n    }\n\n    /**\n     * Command Handler for CMD_WORKINGSET_SORT_BY_*\n     * @private\n     * @param {!string} commandId identifies the sort method to use\n     */\n    function _handleSort(commandId) {\n        get(commandId).execute();\n    }\n\n    /**\n     * Register Sort Methods\n     */\n    register(\n        Commands.CMD_WORKINGSET_SORT_BY_ADDED,\n        function (paneId, file1, file2) {\n            var index1 = MainViewManager.findInWorkingSetByAddedOrder(paneId, file1.fullPath),\n                index2 = MainViewManager.findInWorkingSetByAddedOrder(paneId, file2.fullPath);\n\n            return index1 - index2;\n        },\n        _SORT_EVENT_NAMES\n    );\n    register(\n        Commands.CMD_WORKINGSET_SORT_BY_NAME,\n        function (paneId, file1, file2) {\n            return FileUtils.compareFilenames(file1.name, file2.name, false);\n        },\n        _SORT_EVENT_NAMES\n    );\n    register(\n        Commands.CMD_WORKINGSET_SORT_BY_TYPE,\n        function (paneId, file1, file2) {\n            return FileUtils.compareFilenames(file1.name, file2.name, true);\n        },\n        _SORT_EVENT_NAMES\n    );\n\n\n    /**\n     * Register Command Handlers\n     */\n    CommandManager.register(Strings.CMD_WORKINGSET_SORT_BY_ADDED, Commands.CMD_WORKINGSET_SORT_BY_ADDED, _.partial(_handleSort, Commands.CMD_WORKINGSET_SORT_BY_ADDED));\n    CommandManager.register(Strings.CMD_WORKINGSET_SORT_BY_NAME,  Commands.CMD_WORKINGSET_SORT_BY_NAME,  _.partial(_handleSort, Commands.CMD_WORKINGSET_SORT_BY_NAME));\n    CommandManager.register(Strings.CMD_WORKINGSET_SORT_BY_TYPE,  Commands.CMD_WORKINGSET_SORT_BY_TYPE,  _.partial(_handleSort, Commands.CMD_WORKINGSET_SORT_BY_TYPE));\n    CommandManager.register(Strings.CMD_WORKING_SORT_TOGGLE_AUTO,   Commands.CMD_WORKING_SORT_TOGGLE_AUTO,    _handleToggleAutoSort);\n\n\n    /**\n     * Initialize default values for sorting preferences\n     */\n    PreferencesManager.stateManager.definePreference(\"automaticSort\", \"boolean\", false);\n\n    /**\n     * Define a default sort method that's empty so that we\n     *   just convert and use the legacy sort method\n     */\n    PreferencesManager.stateManager.definePreference(_WORKING_SET_SORT_PREF, \"string\", \"\");\n\n    /*\n     * initializes global sort method from preference settings or the default\n     */\n    function initSortMethod() {\n        var sortMethod = PreferencesManager.getViewState(_WORKING_SET_SORT_PREF);\n\n        if (!sortMethod) {\n            sortMethod = _convertSortPref(PreferencesManager.getViewState(_LEGACY_SORT_PREF));\n        }\n\n        if (!sortMethod) {\n            sortMethod = Commands.CMD_WORKINGSET_SORT_BY_ADDED;\n        }\n        return sortMethod;\n    }\n\n    /**\n     * Initialize items dependent on extensions/workingSetList\n     */\n    AppInit.appReady(function () {\n        var sortMethod = initSortMethod(),\n            curSort    = get(sortMethod),\n            autoSort = PreferencesManager.getViewState(\"automaticSort\");\n\n        if (curSort) {\n            _setCurrentSort(curSort);\n        }\n        if (autoSort) {\n            setAutomatic(autoSort);\n        }\n        if (curSort && autoSort) {\n            curSort.sort();\n        }\n    });\n\n    // Public API\n    exports.register        = register;\n    exports.get             = get;\n    exports.getAutomatic    = getAutomatic;\n    exports.setAutomatic    = setAutomatic;\n});\n"
  },
  {
    "path": "src/project/WorkingSetView.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * WorkingSetView generates the UI for the list of the files user is editing based on the model provided by EditorManager.\n * The UI allows the user to see what files are open/dirty and allows them to close files and specify the current editor.\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit               = require(\"utils/AppInit\"),\n        DocumentManager       = require(\"document/DocumentManager\"),\n        MainViewManager       = require(\"view/MainViewManager\"),\n        CommandManager        = require(\"command/CommandManager\"),\n        Commands              = require(\"command/Commands\"),\n        Menus                 = require(\"command/Menus\"),\n        FileViewController    = require(\"project/FileViewController\"),\n        ViewUtils             = require(\"utils/ViewUtils\"),\n        KeyEvent              = require(\"utils/KeyEvent\"),\n        paneListTemplate      = require(\"text!htmlContent/working-set.html\"),\n        Strings               = require(\"strings\"),\n        _                     = require(\"thirdparty/lodash\"),\n        Mustache              = require(\"thirdparty/mustache/mustache\");\n\n    /**\n     * Open view dictionary\n     * Maps PaneId to WorkingSetView\n     * @private\n     * @type {Object.<string, WorkingSetView>}\n     */\n    var _views = {};\n\n    /**\n     * Icon Providers\n     * @see {@link #addIconProvider}\n     * @private\n     */\n    var _iconProviders = [];\n\n    /**\n     * The file/folder object of the current context\n     * @type {FileSystemEntry}\n     * @private\n     */\n    var _contextEntry;\n\n    /**\n     * Class Providers\n     * @see {@link #addClassProvider}\n     * @private\n     */\n    var _classProviders = [];\n\n\n    /**\n     * #working-set-list-container\n     * @type {jQuery}\n     */\n    var $workingFilesContainer;\n\n    /**\n     * Constants for event.which values\n     * @enum {number}\n     */\n    var LEFT_BUTTON = 1,\n        MIDDLE_BUTTON = 2;\n\n    /**\n     * Each list item in the working set stores a references to the related document in the list item's data.\n     *  Use `listItem.data(_FILE_KEY)` to get the document reference\n     * @type {string}\n     * @private\n     */\n    var _FILE_KEY = \"file\";\n\n    /**\n     * Constants for hitTest.where\n     * @enum {string}\n     */\n    var NOMANSLAND = \"nomansland\",\n        NOMOVEITEM = \"nomoveitem\",\n        ABOVEITEM  = \"aboveitem\",\n        BELOWITEM  = \"belowitem\",\n        TOPSCROLL  = \"topscroll\",\n        BOTSCROLL  = \"bottomscroll\",\n        BELOWVIEW  = \"belowview\",\n        ABOVEVIEW  = \"aboveview\";\n\n    /**\n     * Drag an item has to move 3px before dragging starts\n     * @constant\n     */\n    var _DRAG_MOVE_DETECTION_START = 3;\n\n    /**\n     * Refreshes all Pane View List Views\n     */\n    function refresh(rebuild) {\n        _.forEach(_views, function (view) {\n            var top = view.$openFilesContainer.scrollTop();\n            if (rebuild) {\n                view._rebuildViewList(true);\n            } else {\n                view._redraw();\n            }\n            view.$openFilesContainer.scrollTop(top);\n        });\n    }\n\n    /**\n     * Synchronizes the selection indicator for all views\n     */\n    function syncSelectionIndicator() {\n        _.forEach(_views, function (view) {\n            view.$openFilesContainer.triggerHandler(\"scroll\");\n        });\n    }\n\n    /**\n     * Updates the appearance of the list element based on the parameters provided.\n     * @private\n     * @param {!HTMLLIElement} listElement\n     * @param {?File} selectedFile\n     */\n    function _updateListItemSelection(listItem, selectedFile) {\n        var shouldBeSelected = (selectedFile && $(listItem).data(_FILE_KEY).fullPath === selectedFile.fullPath);\n        ViewUtils.toggleClass($(listItem), \"selected\", shouldBeSelected);\n    }\n\n    /**\n     * Determines if a file is dirty\n     * @private\n     * @param {!File} file - file to test\n     * @return {boolean} true if the file is dirty, false otherwise\n     */\n    function _isOpenAndDirty(file) {\n        // working set item might never have been opened; if so, then it's definitely not dirty\n        var docIfOpen = DocumentManager.getOpenDocumentForPath(file.fullPath);\n        return (docIfOpen && docIfOpen.isDirty);\n    }\n\n\n    function _hasSelectionFocus() {\n        return FileViewController.getFileSelectionFocus() === FileViewController.WORKING_SET_VIEW;\n    }\n\n    /**\n     * Turns on/off the flag which suppresses rebuilding of the working set\n     * when the \"workingSetSort\" event is dispatched from MainViewManager.\n     * Only used while dragging things around in the working set to disable\n     * rebuilding the list while dragging.\n     * @private\n     * @param {boolean} suppress - true suppress, false to allow sort redrawing\n     */\n    function _suppressSortRedrawForAllViews(suppress) {\n        _.forEach(_views, function (view) {\n            view.suppressSortRedraw = suppress;\n        });\n    }\n\n    /**\n     * turns off the scroll shadow on view containers so they don't interfere with dragging\n     * @private\n     * @param {Boolean} disable - true to disable, false to enable\n     */\n    function _suppressScrollShadowsOnAllViews(disable) {\n        _.forEach(_views, function (view) {\n            if (disable) {\n                ViewUtils.removeScrollerShadow(view.$openFilesContainer[0], null);\n            } else if (view.$openFilesContainer[0].scrollHeight > view.$openFilesContainer[0].clientHeight) {\n                ViewUtils.addScrollerShadow(view.$openFilesContainer[0], null, true);\n            }\n        });\n    }\n\n    /**\n     * Deactivates all views so the selection marker does not show\n     * @private\n     * @param {Boolean} deactivate - true to deactivate, false to reactivate\n     */\n    function _deactivateAllViews(deactivate) {\n        _.forEach(_views, function (view) {\n            if (deactivate) {\n                if (view.$el.hasClass(\"active\")) {\n                    view.$el.removeClass(\"active\").addClass(\"reactivate\");\n                    view.$openFilesList.trigger(\"selectionHide\");\n                }\n            } else {\n                if (view.$el.hasClass(\"reactivate\")) {\n                    view.$el.removeClass(\"reactivate\").addClass(\"active\");\n                }\n                // don't update the scroll pos\n                view._fireSelectionChanged(false);\n            }\n        });\n    }\n\n    /**\n     * Finds the WorkingSetView object for the specified element\n     * @private\n     * @param {jQuery} $el - the element to find the view for\n     * @return {View} view object\n     */\n    function _viewFromEl($el) {\n        if (!$el.hasClass(\"working-set-view\")) {\n            $el = $el.parents(\".working-set-view\");\n        }\n\n        var id = $el.attr(\"id\").match(/working\\-set\\-list\\-([\\w]+[\\w\\d\\-\\.\\:\\_]*)/).pop();\n        return _views[id];\n    }\n\n    /**\n     * Makes the specified element draggable\n     * @private\n     * @param {jQuery} $el - the element to make draggable\n     */\n    function _makeDraggable($el) {\n        var interval,\n            sourceFile = $el.data(_FILE_KEY);\n\n        // turn off the \"hover-scroll\"\n        function endScroll($el) {\n            if (interval) {\n                window.clearInterval(interval);\n                interval = undefined;\n            }\n        }\n\n        //  We scroll the list while hovering over the first or last visible list element\n        //  in the working set, so that positioning a working set item before or after one\n        //  that has been scrolled out of view can be performed.\n        //\n        //  This function will call the drag interface repeatedly on an interval to allow\n        //  the item to be dragged while scrolling the list until the mouse is moved off\n        //  the first or last item or endScroll is called\n        function scroll($container, $el, dir, callback) {\n            var container = $container[0],\n                maxScroll = container.scrollHeight - container.clientHeight;\n            if (maxScroll && dir && !interval) {\n                // Scroll view if the mouse is over the first or last pixels of the container\n                interval = window.setInterval(function () {\n                    var scrollTop = $container.scrollTop();\n                    if ((dir === -1 && scrollTop <= 0) || (dir === 1 && scrollTop >= maxScroll)) {\n                        endScroll($el);\n                    } else {\n                        $container.scrollTop(scrollTop + 7 * dir);\n                        callback($el);\n                    }\n                }, 50);\n            }\n        }\n\n        // The mouse down handler pretty much handles everything\n        $el.mousedown(function (e) {\n            var scrollDir = 0,\n                dragged = false,\n                startPageY = e.pageY,\n                lastPageY = startPageY,\n                lastHit = { where: NOMANSLAND },\n                tryClosing = $(e.target).hasClass(\"can-close\"),\n                currentFile = MainViewManager.getCurrentlyViewedFile(),\n                activePaneId = MainViewManager.getActivePaneId(),\n                activeView = _views[activePaneId],\n                sourceView = _viewFromEl($el),\n                currentView = sourceView,\n                startingIndex = $el.index(),\n                itemHeight,\n                offset,\n                $copy,\n                $ghost,\n                draggingCurrentFile;\n\n            function initDragging() {\n                itemHeight = $el.height();\n                offset = $el.offset();\n                $copy = $el.clone();\n                $ghost = $(\"<div class='open-files-container wsv-drag-ghost' style='overflow: hidden; display: inline-block;'>\").append($(\"<ul>\").append($copy).css(\"padding\", \"0\"));\n                draggingCurrentFile = ($el.hasClass(\"selected\") && sourceView.paneId === activePaneId);\n\n                // setup our ghost element as position absolute\n                //  so we can put it wherever we want to while dragging\n                if (draggingCurrentFile && _hasSelectionFocus()) {\n                    $ghost.addClass(\"dragging-current-file\");\n                }\n\n                $ghost.css({\n                    top: offset.top,\n                    left: offset.left,\n                    width: $el.width() + 8\n                });\n\n                // this will give the element the appearence that it's ghosted if the user\n                //  drags the element out of the view and goes off into no mans land\n                $ghost.appendTo($(\"body\"));\n            }\n\n            // Switches the view context to match the hit context\n            function updateContext(hit) {\n                // just set the container and update\n                currentView = _viewFromEl(hit.which);\n            }\n\n            // Determines where the mouse hit was\n            function hitTest(e) {\n                var pageY = $ghost.offset().top,\n                    direction =  e.pageY - lastPageY,\n                    result = {\n                        where: NOMANSLAND\n                    },\n                    lookCount = 0,\n                    hasScroller = false,\n                    onTopScroller = false,\n                    onBottomScroller = false,\n                    $container,\n                    $hit,\n                    $item,\n                    $view,\n                    gTop,\n                    gHeight,\n                    gBottom,\n                    containerOffset,\n                    scrollerTopArea,\n                    scrollerBottomArea;\n\n                // if the mouse is outside of the view then\n                //  return nomansland -- this prevents some UI glitches\n                //  that appear when dragging onto a second monitor\n                if (e.pageX < 0 || e.pageX > $workingFilesContainer.width()) {\n                    return result;\n                }\n\n                do {\n                    // Turn off the ghost so elementFromPoint ignores it\n                    $ghost.hide();\n\n                    $hit = $(window.document.elementFromPoint(e.pageX, pageY));\n                    $view = $hit.closest(\".working-set-view\");\n                    $item = $hit.closest(\"#working-set-list-container li\");\n\n                    // Show the ghost again\n                    $ghost.show();\n\n                    $container = $view.children(\".open-files-container\");\n\n                    if ($container.length) {\n                        containerOffset = $container.offset();\n\n                        // Compute \"scrollMe\" regions\n                        scrollerTopArea = { top: containerOffset.top - 14,\n                                            bottom: containerOffset.top + 7};\n\n                        scrollerBottomArea = { top: containerOffset.top + $container.height() - 7,\n                                               bottom: containerOffset.top + $container.height() + 14};\n                    }\n\n                    // If we hit ourself then look for another\n                    //  element to insert before/after\n                    if ($item[0] === $el[0]) {\n                        if (direction > 0) {\n                            $item = $item.next();\n                            if ($item.length) {\n                                pageY += itemHeight;\n                            }\n                        } else {\n                            $item = $item.prev();\n                            if ($item.length) {\n                                pageY -= itemHeight;\n                            }\n                        }\n                    }\n\n                    // If we didn't hit anything then\n                    //  back up and try again in the other direction\n                    if (!$item.length) {\n                        pageY += itemHeight;\n                    }\n\n                    // look one more time below the mouse\n                    //  if we didn't get a hit\n                } while (!$item.length && ++lookCount < 2);\n\n                // if we hit a span or an anchor tag and didn't\n                //  find an item then force the selection hit to\n                //  the item so we can bail out on the scrollMe\n                //  region at the top and bottom of the list\n                if ($item.length === 0 && ($hit.is(\"a\") || $hit.is(\"span\"))) {\n                    $item = $hit.parents(\"#working-set-list-container li\");\n                }\n\n                // compute ghost location, we compute the insertion point based\n                //  on where the ghost is, not where the  mouse is\n                gTop = $ghost.offset().top;\n                gHeight = $ghost.height();\n                gBottom = gTop + gHeight;\n\n                // data to help us determine if we have a scroller\n                hasScroller = $item.length && $container.length && $container[0].scrollHeight > $container[0].clientHeight;\n\n                // data to help determine if the ghost is in either of the scrollMe regions\n                onTopScroller = hasScroller && scrollerTopArea && ((gTop >= scrollerTopArea.top && gTop <= scrollerTopArea.bottom)  ||\n                                                    (gBottom >= scrollerTopArea.top && gBottom <= scrollerTopArea.bottom));\n                onBottomScroller = hasScroller && scrollerBottomArea && ((gTop >= scrollerBottomArea.top && gTop <= scrollerBottomArea.bottom) ||\n                                                         (gBottom >= scrollerBottomArea.top && gBottom <= scrollerBottomArea.bottom));\n\n\n                // helpers\n                function mouseIsInTopHalf($elem) {\n                    var top = $elem.offset().top,\n                        height = $elem.height();\n\n                    return (pageY < top + (height / 2));\n                }\n\n                function ghostIsAbove($elem) {\n                    var top = $elem.offset().top,\n                        checkVal = gTop;\n\n                    if (direction > 0) {\n                        checkVal += gHeight;\n                    }\n\n                    return (checkVal <=  (top + (itemHeight / 2)));\n                }\n\n                function ghostIsBelow($elem) {\n                    var top = $elem.offset().top,\n                        checkVal = gTop;\n\n                    if (direction > 0) {\n                        checkVal += gHeight;\n                    }\n\n                    return (checkVal >= (top + (itemHeight / 2)));\n                }\n\n                function elIsClearBelow($a, $b) {\n                    var aTop = $a.offset().top,\n                        bTop = $b.offset().top;\n\n                    return (aTop >= bTop + $b.height());\n                }\n\n                function draggingBelowWorkingSet() {\n                    return ($hit.length === 0 || elIsClearBelow($hit, $workingFilesContainer));\n                }\n\n                function targetIsContainer() {\n                    return ($hit.is(\".working-set-view\") ||\n                            $hit.is(\".open-files-container\") ||\n                            ($hit.is(\"ul\") && $hit.parent().is(\".open-files-container\")));\n                }\n\n                function targetIsNoDrop() {\n                    return $hit.is(\".working-set-header\") ||\n                           $hit.is(\".working-set-header-title\") ||\n                           $hit.is(\".scroller-shadow\") ||\n                           $hit.is(\".scroller-shadow\");\n                }\n\n                function findViewFor($elem) {\n                    if ($elem.is(\".working-set-view\")) {\n                        return $elem;\n                    }\n                    return $elem.parents(\".working-set-view\");\n                }\n\n                if ($item.length) {\n                    // We hit an item (li)\n                    if (onTopScroller && (direction <= 0 || lastHit.where === TOPSCROLL)) {\n                        result = {\n                            where: TOPSCROLL,\n                            which: $item\n                        };\n                    } else if (onBottomScroller && (direction >= 0 || lastHit.where === BOTSCROLL)) {\n                        result = {\n                            where: BOTSCROLL,\n                            which: $item\n                        };\n                    } else if (ghostIsAbove($item)) {\n                        result = {\n                            where: ABOVEITEM,\n                            which: $item\n                        };\n                    } else if (ghostIsBelow($item)) {\n                        result = {\n                            where: BELOWITEM,\n                            which: $item\n                        };\n                    }\n                } else if ($el.parent()[0] !== $hit[0]) {\n                    // Didn't hit an li, figure out\n                    //  where to go from here\n                    $view = $el.parents(\".working-set-view\");\n\n                    if (targetIsNoDrop()) {\n                        if (direction < 0) {\n                            if (ghostIsBelow($hit)) {\n                                return result;\n                            }\n                        } else {\n                            return result;\n                        }\n                    }\n\n                    if (draggingBelowWorkingSet()) {\n                        return result;\n                    }\n\n                    if (targetIsContainer()) {\n                        if (mouseIsInTopHalf($hit)) {\n                            result = {\n                                where: ABOVEVIEW,\n                                which: findViewFor($hit)\n                            };\n                        } else {\n                            result = {\n                                where: BELOWVIEW,\n                                which: findViewFor($hit)\n                            };\n                        }\n                        return result;\n                    }\n\n                    // Data to determine to help determine if we should\n                    //  append to the previous or prepend to the next\n                    var $prev = $view.prev(),\n                        $next = $view.next();\n\n                    if (direction < 0) {\n                        // moving up, if there is a view above\n                        //  then we want to append to the view above\n                        // otherwise we're in nomandsland\n                        if ($prev.length) {\n                            result = {\n                                where: BELOWVIEW,\n                                which: $prev\n                            };\n                        }\n                    } else if (direction > 0) {\n                        // moving down, if there is a view below\n                        // then we want to append to the view below\n                        //  otherwise we're in nomandsland\n                        if ($next.length) {\n                            result = {\n                                where: ABOVEVIEW,\n                                which: $next\n                            };\n                        }\n                    } else if (mouseIsInTopHalf($view)) {\n                        // we're inside the top half of\n                        //  a view so prepend to the view we hit\n                        result = {\n                            where: ABOVEVIEW,\n                            which: $view\n                        };\n                    } else {\n                        // we're inside the bottom half of\n                        //  a view so append to the view we hit\n                        result = {\n                            where: BELOWVIEW,\n                            which: $view\n                        };\n                    }\n                } else {\n                    // The item doesn't need updating\n                    result = {\n                        where: NOMOVEITEM,\n                        which: $hit\n                    };\n                }\n\n                return result;\n            }\n\n            // mouse move handler -- this pretty much does\n            //  the heavy lifting for dragging the item around\n            $(window).on(\"mousemove.wsvdragging\", function (e) {\n                // The drag function\n                function drag(e) {\n                    if (!dragged) {\n                        initDragging();\n                        // sort redraw and scroll shadows\n                        //  cause problems during drag so disable them\n                        _suppressSortRedrawForAllViews(true);\n                        _suppressScrollShadowsOnAllViews(true);\n\n                        // remove the \"active\" class to remove the\n                        //  selection indicator so we don't have to\n                        //  keep it in sync while we're dragging\n                        _deactivateAllViews(true);\n\n                        // add a \"dragging\" class to the outer container\n                        $workingFilesContainer.addClass(\"dragging\");\n\n                        // add a class to the element we're dragging if\n                        //  it's the currently selected file so that we\n                        //  can show it as selected while dragging\n                        if (!draggingCurrentFile && FileViewController.getFileSelectionFocus() === FileViewController.WORKING_SET_VIEW) {\n                            $(activeView._findListItemFromFile(currentFile)).addClass(\"drag-show-as-selected\");\n                        }\n\n                        // we've dragged the item so set\n                        //  dragged to true so we don't try and open it\n                        dragged = true;\n                    }\n\n                    // reset the scrolling direction to no-scroll\n                    scrollDir = 0;\n\n                    // Find out where to to drag it to\n                    lastHit = hitTest(e);\n\n                    // if the drag goes into nomansland then\n                    //  drop the opacity on the drag affordance\n                    //  and show the inserted item at reduced opacity\n                    switch (lastHit.where) {\n                    case NOMANSLAND:\n                    case BELOWVIEW:\n                    case ABOVEVIEW:\n                        $el.css({opacity: \".75\"});\n                        $ghost.css(\"opacity\", \".25\");\n                        break;\n                    default:\n                        $el.css({opacity: \".0001\"});\n                        $ghost.css(\"opacity\", \"\");\n                        break;\n                    }\n\n                    // now do the insertion\n                    switch (lastHit.where) {\n                    case TOPSCROLL:\n                    case ABOVEITEM:\n                        if (lastHit.where === TOPSCROLL) {\n                            scrollDir = -1;\n                        }\n                        $el.insertBefore(lastHit.which);\n                        updateContext(lastHit);\n                        break;\n                    case BOTSCROLL:\n                    case BELOWITEM:\n                        if (lastHit.where === BOTSCROLL) {\n                            scrollDir = 1;\n                        }\n                        $el.insertAfter(lastHit.which);\n                        updateContext(lastHit);\n                        break;\n                    case BELOWVIEW:\n                        $el.appendTo(lastHit.which.find(\"ul\"));\n                        updateContext(lastHit);\n                        break;\n                    case ABOVEVIEW:\n                        $el.prependTo(lastHit.which.find(\"ul\"));\n                        updateContext(lastHit);\n                        break;\n                    }\n\n                    // we need to scroll\n                    if (scrollDir) {\n                        // we're in range to scroll\n                        scroll(currentView.$openFilesContainer, $el, scrollDir, function () {\n                            // as we scroll, recompute the element and insert\n                            //  it before/after the item to drag it in to place\n                            drag(e);\n                        });\n                    } else {\n                        // we've moved away from the top/bottom \"scrolling\" region\n                        endScroll($el);\n                    }\n                }\n\n                // Reposition the drag affordance if we've started dragging\n                if ($ghost) {\n                    $ghost.css(\"top\", $ghost.offset().top + (e.pageY - lastPageY));\n                }\n\n                // if we have't started dragging yet then we wait until\n                //  the mouse has moved 3 pixels before we start dragging\n                //  to avoid the item moving when clicked or double clicked\n                if (dragged || Math.abs(e.pageY - startPageY) > _DRAG_MOVE_DETECTION_START) {\n                    drag(e);\n                }\n\n                lastPageY = e.pageY;\n                e.stopPropagation();\n            });\n\n\n            function scrollCurrentViewToBottom() {\n                var $container = currentView.$openFilesContainer,\n                    container = $container[0],\n                    maxScroll = container.scrollHeight - container.clientHeight;\n\n                if (maxScroll) {\n                    $container.scrollTop(maxScroll);\n                }\n            }\n\n            // Close down the drag operation\n            function preDropCleanup() {\n                window.onmousewheel = window.document.onmousewheel = null;\n                $(window).off(\".wsvdragging\");\n                if (dragged) {\n                    $workingFilesContainer.removeClass(\"dragging\");\n                    $workingFilesContainer.find(\".drag-show-as-selected\").removeClass(\"drag-show-as-selected\");\n                    endScroll($el);\n                    // re-activate the views (adds the \"active\" class to the view that was previously active)\n                    _deactivateAllViews(false);\n                    // turn scroll wheel back on\n                    $ghost.remove();\n                    $el.css(\"opacity\", \"\");\n\n                    if ($el.next().length === 0) {\n                        scrollCurrentViewToBottom();\n                    }\n                }\n            }\n\n            // Final Cleanup\n            function postDropCleanup(noRefresh) {\n                if (dragged) {\n                    // re-enable stuff we turned off\n                    _suppressSortRedrawForAllViews(false);\n                    _suppressScrollShadowsOnAllViews(false);\n                }\n\n                // we don't need to refresh if the item\n                //  was dragged but not enough to not change\n                //  its order in the working set\n                if (!noRefresh) {\n                    // rebuild the view\n                    refresh(true);\n                }\n                // focus the editor\n                MainViewManager.focusActivePane();\n            }\n\n            // Drop\n            function drop() {\n                preDropCleanup();\n                if (sourceView.paneId === currentView.paneId && startingIndex === $el.index()) {\n                    // if the item was dragged but not moved then don't open or close\n                    if (!dragged) {\n                        // Click on close icon, or middle click anywhere - close the item without selecting it first\n                        if (tryClosing || e.which === MIDDLE_BUTTON) {\n                            CommandManager\n                                .execute(Commands.FILE_CLOSE, {file: sourceFile,\n                                                           paneId: sourceView.paneId})\n                                .always(function () {\n                                    postDropCleanup();\n                                });\n                        } else {\n                            // Normal right and left click - select the item\n                            FileViewController.setFileViewFocus(FileViewController.WORKING_SET_VIEW);\n                            CommandManager\n                                .execute(Commands.FILE_OPEN, {fullPath: sourceFile.fullPath,\n                                                               paneId: currentView.paneId})\n                                .always(function () {\n                                    postDropCleanup();\n                                });\n                        }\n                    } else {\n                        // no need to refresh\n                        postDropCleanup(true);\n                    }\n                } else if (sourceView.paneId === currentView.paneId) {\n                    // item was reordered\n                    MainViewManager._moveWorkingSetItem(sourceView.paneId, startingIndex, $el.index());\n                    postDropCleanup();\n                } else {\n                    // If the same doc view is present in the destination pane prevent drop\n                    if (!MainViewManager._getPane(currentView.paneId).getViewForPath(sourceFile.fullPath)) {\n                        // item was dragged to another working set\n                        MainViewManager._moveView(sourceView.paneId, currentView.paneId, sourceFile, $el.index())\n                            .always(function () {\n                                // if the current document was dragged to another working set\n                                //  then reopen it to make it the currently selected file\n                                if (draggingCurrentFile) {\n                                    CommandManager\n                                        .execute(Commands.FILE_OPEN, {fullPath: sourceFile.fullPath,\n                                                                       paneId: currentView.paneId})\n                                        .always(function () {\n                                            postDropCleanup();\n                                        });\n                                } else {\n                                    postDropCleanup();\n                                }\n                            });\n                    } else {\n                        postDropCleanup();\n                    }\n                }\n            }\n\n            // prevent working set from grabbing focus no matter what type of click/drag occurs\n            e.preventDefault();\n\n            // initialization\n            $(window).on(\"mouseup.wsvdragging\", function () {\n                drop();\n            });\n\n            // let escape cancel the drag\n            $(window).on(\"keydown.wsvdragging\", function (e) {\n                if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                    preDropCleanup();\n                    postDropCleanup();\n                    e.stopPropagation();\n                }\n            });\n\n            // turn off scroll wheel\n            window.onmousewheel = window.document.onmousewheel = function (e) {\n                e.preventDefault();\n            };\n\n            // close all menus, and disable sorting\n            Menus.closeAll();\n\n            // Dragging only happens with the left mouse button\n            //  or (on the Mac) when the ctrl key isn't pressed\n            if (e.which !== LEFT_BUTTON || (e.ctrlKey && brackets.platform === \"mac\")) {\n                drop();\n                return;\n            }\n\n\n\n            e.stopPropagation();\n        });\n    }\n\n    /*\n     * WorkingSetView constructor\n     * @constructor\n     * @param {!jQuery} $container - owning container\n     * @param {!string} paneId - paneId of this view pertains to\n     */\n    function WorkingSetView($container, paneId) {\n        var id = \"working-set-list-\" + paneId;\n\n        this.$header = null;\n        this.$openFilesList = null;\n        this.$container = $container;\n        this.$el = $container.append(Mustache.render(paneListTemplate, _.extend({id: id}, Strings))).find(\"#\" + id);\n        this.suppressSortRedraw = false;\n        this.paneId = paneId;\n\n        this.init();\n    }\n\n    /*\n     * Hides or shows the WorkingSetView\n     */\n    WorkingSetView.prototype._updateVisibility = function () {\n        var fileList = MainViewManager.getWorkingSet(this.paneId);\n        if (MainViewManager.getPaneCount() === 1 && (!fileList || fileList.length === 0)) {\n            this.$openFilesContainer.hide();\n            this.$workingSetListViewHeader.hide();\n        } else {\n            this.$openFilesContainer.show();\n            this.$workingSetListViewHeader.show();\n            this._checkForDuplicatesInWorkingTree();\n        }\n    };\n\n    /*\n     * paneLayoutChange event listener\n     * @private\n     */\n    WorkingSetView.prototype._handlePaneLayoutChange = function () {\n        var $titleEl = this.$el.find(\".working-set-header-title\"),\n            title = Strings.WORKING_FILES;\n\n        this._updateVisibility();\n\n        if (MainViewManager.getPaneCount() > 1) {\n            title = MainViewManager.getPaneTitle(this.paneId);\n        }\n\n        $titleEl.text(title);\n    };\n\n    /**\n     * Finds the listItem item assocated with the file. Returns null if not found.\n     * @private\n     * @param {!File} file\n     * @return {HTMLLIItem} returns the DOM element of the item. null if one could not be found\n     */\n    WorkingSetView.prototype._findListItemFromFile = function (file) {\n        var result = null;\n\n        if (file) {\n            var items = this.$openFilesContainer.find(\"ul\").children();\n            items.each(function () {\n                var $listItem = $(this);\n                if ($listItem.data(_FILE_KEY).fullPath === file.fullPath) {\n                    result = $listItem;\n                    return false; // breaks each\n                }\n            });\n        }\n\n        return result;\n    };\n\n    /*\n     * creates a name that is namespaced to this pane\n     * @param {!string} name - name of the event to create.\n     * use an empty string to get just the event name to turn off all events in the namespace\n     * @private\n     */\n    WorkingSetView.prototype._makeEventName = function (name) {\n        return name + \".paneList\" + this.paneId;\n    };\n\n\n    /**\n     * Scrolls the selected file into view\n     * @private\n     */\n    WorkingSetView.prototype._scrollSelectedFileIntoView = function () {\n        if (!_hasSelectionFocus()) {\n            return;\n        }\n\n        var file = MainViewManager.getCurrentlyViewedFile(this.paneId);\n\n        var $selectedFile = this._findListItemFromFile(file);\n        if (!$selectedFile) {\n            return;\n        }\n\n        ViewUtils.scrollElementIntoView(this.$openFilesContainer, $selectedFile, false);\n    };\n\n    /**\n     * Redraw selection when list size changes or DocumentManager currentDocument changes.\n     * @param {boolean=} scrollIntoView = Scrolls the selected item into view (the default behavior)\n     * @private\n     */\n    WorkingSetView.prototype._fireSelectionChanged = function (scrollIntoView) {\n        var reveal = (scrollIntoView === undefined || scrollIntoView === true);\n\n        if (reveal) {\n            this._scrollSelectedFileIntoView();\n        }\n\n        if (_hasSelectionFocus() && this.$el.hasClass(\"active\")) {\n            this.$openFilesList.trigger(\"selectionChanged\", reveal);\n        } else {\n            this.$openFilesList.trigger(\"selectionHide\");\n        }\n        // in-lieu of resize events, manually trigger contentChanged to update scroll shadows\n        this.$openFilesContainer.trigger(\"contentChanged\");\n    };\n\n    /**\n     * adds the style 'vertical-scroll' if a vertical scroll bar is present\n     * @private\n     */\n    WorkingSetView.prototype._adjustForScrollbars = function () {\n        if (this.$openFilesContainer[0].scrollHeight > this.$openFilesContainer[0].clientHeight) {\n            if (!this.$openFilesContainer.hasClass(\"vertical-scroll\")) {\n                this.$openFilesContainer.addClass(\"vertical-scroll\");\n            }\n        } else {\n            this.$openFilesContainer.removeClass(\"vertical-scroll\");\n        }\n    };\n\n    /**\n     * Adds directory names to elements representing passed files in working tree\n     * @private\n     * @param {Array.<File>} filesList - list of Files with the same filename\n     */\n    WorkingSetView.prototype._addDirectoryNamesToWorkingTreeFiles = function (filesList) {\n        // filesList must have at least two files in it for this to make sense\n        if (filesList.length <= 1) {\n            return;\n        }\n\n        var displayPaths = ViewUtils.getDirNamesForDuplicateFiles(filesList);\n\n        // Go through open files and add directories to appropriate entries\n        this.$openFilesContainer.find(\"ul > li\").each(function () {\n            var $li = $(this);\n            var io = filesList.indexOf($li.data(_FILE_KEY));\n            if (io !== -1) {\n                var dirSplit = displayPaths[io].split(\"/\");\n                if (dirSplit.length > 3) {\n                    displayPaths[io] = dirSplit[0] + \"/\\u2026/\" + dirSplit[dirSplit.length - 1];\n                }\n\n                var $dir = $(\"<span class='directory'/>\").html(\" &mdash; \" + displayPaths[io]);\n                $li.children(\"a\").append($dir);\n            }\n        });\n    };\n\n    /**\n     * Looks for files with the same name in the working set\n     * and adds a parent directory name to them\n     * @private\n     */\n    WorkingSetView.prototype._checkForDuplicatesInWorkingTree = function () {\n        var self = this,\n            map = {},\n            fileList = MainViewManager.getWorkingSet(MainViewManager.ALL_PANES);\n\n        // We need to always clear current directories as files could be removed from working tree.\n        this.$openFilesContainer.find(\"ul > li > a > span.directory\").remove();\n\n        // Go through files and fill map with arrays of files.\n        fileList.forEach(function (file) {\n            // Use the same function that is used to create html for file.\n            var displayHtml = ViewUtils.getFileEntryDisplay(file);\n\n            if (!map[displayHtml]) {\n                map[displayHtml] = [];\n            }\n            map[displayHtml].push(file);\n        });\n\n        // Go through the map and solve the arrays with length over 1. Ignore the rest.\n        _.forEach(map, function (value) {\n            if (value.length > 1) {\n                self._addDirectoryNamesToWorkingTreeFiles(value);\n            }\n        });\n    };\n\n    /**\n     * Shows/Hides open files list based on working set content.\n     * @private\n     */\n    WorkingSetView.prototype._redraw = function () {\n        this._updateViewState();\n        this._updateVisibility();\n        this._updateItemClasses();\n        this._adjustForScrollbars();\n        this._fireSelectionChanged();\n    };\n\n    /**\n     * activePaneChange event handler\n     * @private\n     */\n    WorkingSetView.prototype._handleActivePaneChange = function () {\n        this._redraw();\n    };\n\n    /**\n     * Updates the appearance of the list element based on the parameters provided\n     * @private\n     * @param {!HTMLLIElement} listElement\n     * @param {bool} isDirty\n     * @param {bool} canClose\n     */\n    WorkingSetView.prototype._updateFileStatusIcon = function (listElement, isDirty, canClose) {\n        var $fileStatusIcon = listElement.find(\".file-status-icon\"),\n            showIcon = isDirty || canClose;\n\n        // remove icon if its not needed\n        if (!showIcon && $fileStatusIcon.length !== 0) {\n            $fileStatusIcon.remove();\n            $fileStatusIcon = null;\n\n        // create icon if its needed and doesn't exist\n        } else if (showIcon && $fileStatusIcon.length === 0) {\n\n            $fileStatusIcon = $(\"<div class='file-status-icon'></div>\")\n                .prependTo(listElement);\n        }\n\n        // Set icon's class\n        if ($fileStatusIcon) {\n            ViewUtils.toggleClass($fileStatusIcon, \"dirty\", isDirty);\n            ViewUtils.toggleClass($fileStatusIcon, \"can-close\", canClose);\n        }\n    };\n\n    /**\n     * Updates the working set item class list\n     * @private\n     */\n    WorkingSetView.prototype._updateItemClasses = function () {\n        if (_classProviders.length > 0) {\n            this.$openFilesContainer.find(\"ul > li\").each(function () {\n                var $li = $(this),\n                    file = $li.data(_FILE_KEY),\n                    data = {fullPath: file.fullPath,\n                            name: file.name,\n                            isFile: file.isFile};\n                _classProviders.forEach(function (provider) {\n                    $li.addClass(provider(data));\n                });\n            });\n        }\n    };\n\n    /**\n     * Builds the UI for a new list item and inserts in into the end of the list\n     * @private\n     * @param {File} file\n     * @return {HTMLLIElement} newListItem\n     */\n    WorkingSetView.prototype._createNewListItem = function (file) {\n        var self = this,\n            selectedFile = MainViewManager.getCurrentlyViewedFile(this.paneId),\n            data = {fullPath: file.fullPath,\n                    name: file.name,\n                    isFile: file.isFile};\n\n        // Create new list item with a link\n        var $link = $(\"<a href='#'></a>\").html(ViewUtils.getFileEntryDisplay(file));\n\n        _iconProviders.forEach(function (provider) {\n            var icon = provider(data);\n            if (icon) {\n                $link.prepend($(icon));\n            }\n        });\n\n        var $newItem = $(\"<li></li>\")\n            .append($link)\n            .data(_FILE_KEY, file);\n\n        this.$openFilesContainer.find(\"ul\").append($newItem);\n\n        _classProviders.forEach(function (provider) {\n            $newItem.addClass(provider(data));\n        });\n\n        // Update the listItem's apperance\n        this._updateFileStatusIcon($newItem, _isOpenAndDirty(file), false);\n        _updateListItemSelection($newItem, selectedFile);\n        _makeDraggable($newItem);\n\n        $newItem.hover(\n            function () {\n                self._updateFileStatusIcon($(this), _isOpenAndDirty(file), true);\n            },\n            function () {\n                self._updateFileStatusIcon($(this), _isOpenAndDirty(file), false);\n            }\n        );\n    };\n\n    /**\n     * Deletes all the list items in the view and rebuilds them from the working set model\n     * @private\n     */\n    WorkingSetView.prototype._rebuildViewList = function (forceRedraw) {\n        var self = this,\n            fileList = MainViewManager.getWorkingSet(this.paneId);\n\n        this.$openFilesContainer.find(\"ul\").empty();\n\n        fileList.forEach(function (file) {\n            self._createNewListItem(file);\n        });\n\n        if (forceRedraw) {\n            self._redraw();\n        }\n    };\n\n    /**\n     * Updates the pane view's selection state\n     * @private\n     */\n    WorkingSetView.prototype._updateViewState = function () {\n        var paneId = MainViewManager.getActivePaneId();\n        if (_hasSelectionFocus() && paneId === this.paneId) {\n            this.$el.addClass(\"active\");\n            this.$openFilesContainer.addClass(\"active\");\n        } else {\n            this.$el.removeClass(\"active\");\n            this.$openFilesContainer.removeClass(\"active\");\n        }\n    };\n\n    /**\n     * Updates the pane view's selection marker and scrolls the item into view\n     * @private\n     */\n    WorkingSetView.prototype._updateListSelection = function () {\n        var file = MainViewManager.getCurrentlyViewedFile(this.paneId);\n\n        this._updateViewState();\n\n        // Iterate through working set list and update the selection on each\n        this.$openFilesContainer.find(\"ul\").children().each(function () {\n            _updateListItemSelection(this, file);\n        });\n\n        // Make sure selection is in view\n        this._scrollSelectedFileIntoView();\n        this._fireSelectionChanged();\n    };\n\n    /**\n     * workingSetAdd event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {!File} fileAdded - the file that was added\n     * @param {!number} index - index where the file was added\n     * @param {!string} paneId - the id of the pane the item that was to\n     */\n    WorkingSetView.prototype._handleFileAdded = function (e, fileAdded, index, paneId) {\n        if (paneId === this.paneId) {\n            this._rebuildViewList(true);\n        } else {\n            this._checkForDuplicatesInWorkingTree();\n        }\n    };\n\n    /**\n     * workingSetAddList event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {!Array.<File>} files - the files that were added\n     * @param {!string} paneId - the id of the pane the item that was to\n     */\n    WorkingSetView.prototype._handleFileListAdded = function (e, files, paneId) {\n        if (paneId === this.paneId) {\n            this._rebuildViewList(true);\n        } else {\n            this._checkForDuplicatesInWorkingTree();\n        }\n    };\n\n    /**\n     * workingSetRemove event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {!File} file - the file that was removed\n     * @param {?boolean} suppressRedraw If true, suppress redraw\n     * @param {!string} paneId - the id of the pane the item that was to\n     */\n    WorkingSetView.prototype._handleFileRemoved = function (e, file, suppressRedraw, paneId) {\n        /*\n         * The suppressRedraw flag is used in cases when we are replacing the working\n         * set entry with another one. There are only 2 use cases for this:\n         *\n         *      1) When an untitled document is being saved.\n         *      2) When a file is saved with a new name.\n         */\n        if (paneId === this.paneId) {\n            if (!suppressRedraw) {\n                var $listItem = this._findListItemFromFile(file);\n                if ($listItem) {\n                    // Make the next file in the list show the close icon,\n                    // without having to move the mouse, if there is a next file.\n                    var $nextListItem = $listItem.next();\n                    if ($nextListItem && $nextListItem.length > 0) {\n                        var canClose = ($listItem.find(\".can-close\").length === 1);\n                        var isDirty = _isOpenAndDirty($nextListItem.data(_FILE_KEY));\n                        this._updateFileStatusIcon($nextListItem, isDirty, canClose);\n                    }\n                    $listItem.remove();\n                }\n                this._redraw();\n            }\n        } else {\n            /*\n             * When this event is handled by a pane that is not being updated then\n             * the suppressRedraw flag does not need to be respected.\n             * _checkForDuplicatesInWorkingTree() does not remove any entries so it's\n             * safe to call at any time.\n             */\n            this._checkForDuplicatesInWorkingTree();\n        }\n    };\n\n    /**\n     * workingSetRemoveList event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {!Array.<File>} files - the files that were removed\n     * @param {!string} paneId - the id of the pane the item that was to\n     */\n    WorkingSetView.prototype._handleRemoveList = function (e, files, paneId) {\n        var self = this;\n        if (paneId === this.paneId) {\n            files.forEach(function (file) {\n                var $listItem = self._findListItemFromFile(file);\n                if ($listItem) {\n                    $listItem.remove();\n                }\n            });\n\n            this._redraw();\n        } else {\n            this._checkForDuplicatesInWorkingTree();\n        }\n    };\n\n    /**\n     * workingSetSort event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {!string} paneId - the id of the pane to sort\n     */\n    WorkingSetView.prototype._handleWorkingSetSort = function (e, paneId) {\n        if (!this.suppressSortRedraw && paneId === this.paneId) {\n            this._rebuildViewList(true);\n        }\n    };\n\n    /**\n     * dirtyFlagChange event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {Document} doc - document whose dirty state has changed\n     */\n    WorkingSetView.prototype._handleDirtyFlagChanged = function (e, doc) {\n        var listItem = this._findListItemFromFile(doc.file);\n        if (listItem) {\n            var canClose = $(listItem).find(\".can-close\").length === 1;\n            this._updateFileStatusIcon(listItem, doc.isDirty, canClose);\n        }\n    };\n\n    /**\n     * workingSetUpdate event handler\n     * @private\n     * @param {jQuery.Event} e - event object\n     * @param {!string} paneId - the id of the pane to update\n     */\n    WorkingSetView.prototype._handleWorkingSetUpdate = function (e, paneId) {\n        if (this.paneId === paneId) {\n            this._rebuildViewList(true);\n        } else {\n            this._checkForDuplicatesInWorkingTree();\n        }\n    };\n\n\n    /**\n     * Initializes the WorkingSetView object\n     */\n    WorkingSetView.prototype.init = function () {\n        this.$openFilesContainer = this.$el.find(\".open-files-container\");\n        this.$workingSetListViewHeader = this.$el.find(\".working-set-header\");\n\n        this.$openFilesList = this.$el.find(\"ul\");\n\n        // Register listeners\n        MainViewManager.on(this._makeEventName(\"workingSetAdd\"), _.bind(this._handleFileAdded, this));\n        MainViewManager.on(this._makeEventName(\"workingSetAddList\"), _.bind(this._handleFileListAdded, this));\n        MainViewManager.on(this._makeEventName(\"workingSetRemove\"), _.bind(this._handleFileRemoved, this));\n        MainViewManager.on(this._makeEventName(\"workingSetRemoveList\"), _.bind(this._handleRemoveList, this));\n        MainViewManager.on(this._makeEventName(\"workingSetSort\"), _.bind(this._handleWorkingSetSort, this));\n        MainViewManager.on(this._makeEventName(\"activePaneChange\"), _.bind(this._handleActivePaneChange, this));\n        MainViewManager.on(this._makeEventName(\"paneLayoutChange\"), _.bind(this._handlePaneLayoutChange, this));\n        MainViewManager.on(this._makeEventName(\"workingSetUpdate\"), _.bind(this._handleWorkingSetUpdate, this));\n\n        DocumentManager.on(this._makeEventName(\"dirtyFlagChange\"), _.bind(this._handleDirtyFlagChanged, this));\n\n        FileViewController.on(this._makeEventName(\"documentSelectionFocusChange\") + \" \" + this._makeEventName(\"fileViewFocusChange\"), _.bind(this._updateListSelection, this));\n\n        // Show scroller shadows when open-files-container scrolls\n        ViewUtils.addScrollerShadow(this.$openFilesContainer[0], null, true);\n        ViewUtils.sidebarList(this.$openFilesContainer);\n\n        // Disable horizontal scrolling until WebKit bug #99379 is fixed\n        this.$openFilesContainer.css(\"overflow-x\", \"hidden\");\n\n        this.$openFilesContainer.on(\"contextmenu.workingSetView\", function (e) {\n            _contextEntry = $(e.target).closest(\"li\").data(_FILE_KEY);\n            Menus.getContextMenu(Menus.ContextMenuIds.WORKING_SET_CONTEXT_MENU).open(e);\n        });\n\n        this._redraw();\n    };\n\n    /**\n     * Destroys the WorkingSetView DOM element and removes all event handlers\n     */\n    WorkingSetView.prototype.destroy = function () {\n        ViewUtils.removeScrollerShadow(this.$openFilesContainer[0], null);\n        this.$openFilesContainer.off(\".workingSetView\");\n        this.$el.remove();\n        MainViewManager.off(this._makeEventName(\"\"));\n        DocumentManager.off(this._makeEventName(\"\"));\n        FileViewController.off(this._makeEventName(\"\"));\n    };\n\n    /**\n     * paneDestroy event handler\n     */\n    MainViewManager.on(\"paneDestroy\", function (e, paneId) {\n        var view = _views[paneId];\n        delete _views[view.paneId];\n        view.destroy();\n    });\n\n    /**\n     * Creates a new WorkingSetView object for the specified pane\n     * @param {!jQuery} $container - the WorkingSetView's DOM parent node\n     * @param {!string} paneId - the id of the pane the view is being created for\n     */\n    function createWorkingSetViewForPane($container, paneId) {\n        var view = _views[paneId];\n        if (!view) {\n            view = new WorkingSetView($container, paneId);\n            _views[view.paneId] = view;\n        }\n    }\n\n\n    /**\n     * Adds an icon provider. The callback is invoked before each working set item is created, and can\n     * return content to prepend to the item.\n     *\n     * @param {!function(!{name:string, fullPath:string, isFile:boolean}):?string|jQuery|DOMNode} callback\n     * Return a string representing the HTML, a jQuery object or DOM node, or undefined. If undefined,\n     * nothing is prepended to the list item.\n     */\n    function addIconProvider(callback) {\n        if (!callback) {\n            return;\n        }\n        _iconProviders.push(callback);\n        // build all views so the provider has a chance to add icons\n        //    to all items that have already been created\n        refresh(true);\n    }\n\n    /**\n     * Adds a CSS class provider, invoked before each working set item is created or updated. When called\n     * to update an existing item, all previously applied classes have been cleared.\n     *\n     * @param {!function(!{name:string, fullPath:string, isFile:boolean}):?string} callback\n     * Return a string containing space-separated CSS class(es) to add, or undefined to leave CSS unchanged.\n     */\n    function addClassProvider(callback) {\n        if (!callback) {\n            return;\n        }\n        _classProviders.push(callback);\n        // build all views so the provider has a chance to style\n        //    all items that have already been created\n        refresh(true);\n    }\n\n    AppInit.htmlReady(function () {\n        $workingFilesContainer =  $(\"#working-set-list-container\");\n    });\n    \n    /*\n     * To be used by other modules/default-extensions which needs to borrow working set entry icons\n     * @param {!object} data - contains file info {fullPath, name, isFile}\n     * @param {!jQuery} $element - jquery fn wrap for the list item\n     */\n    function useIconProviders(data, $element) {\n        _iconProviders.forEach(function (provider) {\n            var icon = provider(data);\n            if (icon) {\n                $element.prepend($(icon));\n            }\n        });\n    }\n\n    /*\n     * To be used by other modules/default-extensions which needs to borrow working set entry custom classes\n     * @param {!object} data - contains file info {fullPath, name, isFile}\n     * @param {!jQuery} $element - jquery fn wrap for the list item\n     */\n    function useClassProviders(data, $element) {\n        _classProviders.forEach(function (provider) {\n            $element.addClass(provider(data));\n        });\n    }\n\n    /**\n     * Gets the filesystem object for the current context in the working set.\n     */\n    function getContext() {\n        return _contextEntry;\n    }\n    \n    // Public API\n    exports.createWorkingSetViewForPane   = createWorkingSetViewForPane;\n    exports.refresh                       = refresh;\n    exports.addIconProvider               = addIconProvider;\n    exports.addClassProvider              = addClassProvider;\n    exports.syncSelectionIndicator        = syncSelectionIndicator;\n    exports.getContext                    = getContext;\n    \n    // API to be used only by default extensions\n    exports.useIconProviders              = useIconProviders;\n    exports.useClassProviders               = useClassProviders;\n});\n"
  },
  {
    "path": "src/search/FileFilters.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities for managing file-set filters, as used in Find in Files.\n * Includes both UI for selecting/editing filters, as well as the actual file-filtering implementation.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                  = require(\"thirdparty/lodash\"),\n        Mustache           = require(\"thirdparty/mustache/mustache\"),\n        Dialogs            = require(\"widgets/Dialogs\"),\n        DropdownButton     = require(\"widgets/DropdownButton\").DropdownButton,\n        StringUtils        = require(\"utils/StringUtils\"),\n        Strings            = require(\"strings\"),\n        PreferencesManager = require(\"preferences/PreferencesManager\"),\n        FindUtils          = require(\"search/FindUtils\"),\n        EditFilterTemplate = require(\"text!htmlContent/edit-filter-dialog.html\"),\n        FilterNameTemplate = require(\"text!htmlContent/filter-name.html\");\n\n    /**\n     * Constant: first filter index in the filter dropdown list\n     * @type {number}\n     */\n    var FIRST_FILTER_INDEX = 3;\n\n    /**\n     * Constant: max number of characters for the filter name\n     * @type {number}\n     */\n    var FILTER_NAME_CHARACTER_MAX = 20;\n\n    /**\n     * Context Info on which files the filter will be applied to.\n     * It will be initialized when createFilterPicker is called and if specified, editing UI will\n     * indicate how many files are excluded by the filter. Label should be of the form \"in ...\"\n     * @type {?{label:string, promise:$.Promise}}\n     */\n    var _context = null;\n\n    /**\n     * @type {DropdownButton}\n     */\n    var _picker  = null;\n\n    /**\n     * Get the condensed form of the filter set by joining the first two in the set with\n     * a comma separator and appending a short message with the number of filters being clipped.\n     * @param {Array.<string>} filter\n     * @return {string} Condensed form of filter set if `filter` is a valid array.\n     *                  Otherwise, return an empty string.\n     */\n    function _getCondensedForm(filter) {\n        if (!_.isArray(filter)) {\n            return \"\";\n        }\n\n        // Format filter in condensed form\n        if (filter.length > 2) {\n            return filter.slice(0, 2).join(\", \") + \" \" +\n                   StringUtils.format(Strings.FILE_FILTER_CLIPPED_SUFFIX, filter.length - 2);\n        }\n        return filter.join(\", \");\n    }\n\n    /**\n     * Populate the list of dropdown menu with two filter commands and\n     * the list of saved filter sets.\n     */\n    function _doPopulate() {\n        var dropdownItems = [Strings.NEW_FILE_FILTER, Strings.CLEAR_FILE_FILTER],\n            filterSets = PreferencesManager.get(\"fileFilters\") || [];\n\n        if (filterSets.length) {\n            dropdownItems.push(\"---\");\n\n            // Remove all the empty exclusion sets before concatenating to the dropdownItems.\n            filterSets = filterSets.filter(function (filter) {\n                return (_getCondensedForm(filter.patterns) !== \"\");\n            });\n\n            // FIRST_FILTER_INDEX needs to stay in sync with the number of static items (plus separator)\n            // ie. the number of items populated so far before we concatenate with the actual filter sets.\n            dropdownItems = dropdownItems.concat(filterSets);\n        }\n        _picker.items = dropdownItems;\n    }\n\n    /**\n     * Find the index of a filter set in the list of saved filter sets.\n     * @param {Array.<{name: string, patterns: Array.<string>}>} filterSets\n     * @return {{name: string, patterns: Array.<string>}} filter\n     */\n    function _getFilterIndex(filterSets, filter) {\n        var index = -1;\n\n        if (!filter || !filterSets.length) {\n            return index;\n        }\n\n        return _.findIndex(filterSets, _.partial(_.isEqual, filter));\n    }\n\n    /**\n     * A search filter is an array of one or more glob strings. The filter must be 'compiled' via compile()\n     * before passing to filterPath()/filterFileList().\n     * @return {?{name: string, patterns: Array.<string>}}\n     */\n    function getActiveFilter() {\n        var filterSets        = PreferencesManager.get(\"fileFilters\") || [],\n            activeFilterIndex = PreferencesManager.getViewState(\"activeFileFilter\"),\n            oldFilter         = PreferencesManager.getViewState(\"search.exclusions\") || [],\n            activeFilter      = null;\n\n        if (activeFilterIndex === undefined && oldFilter.length) {\n            activeFilter = { name: \"\", patterns: oldFilter };\n            activeFilterIndex = _getFilterIndex(filterSets, activeFilter);\n\n            // Migrate the old filter into the new filter storage\n            if (activeFilterIndex === -1) {\n                activeFilterIndex = filterSets.length;\n                filterSets.push(activeFilter);\n                PreferencesManager.set(\"fileFilters\", filterSets);\n            }\n            PreferencesManager.setViewState(\"activeFileFilter\", activeFilterIndex);\n        } else if (activeFilterIndex > -1 && activeFilterIndex < filterSets.length) {\n            activeFilter = filterSets[activeFilterIndex];\n        }\n\n        return activeFilter;\n    }\n\n    /**\n     * Update the picker button label with the name/patterns of the selected filter or\n     * No Files Excluded if no filter is selected.\n     */\n    function _updatePicker() {\n        var filter = getActiveFilter();\n        if (filter && filter.patterns.length) {\n            var label = filter.name || _getCondensedForm(filter.patterns);\n            _picker.setButtonLabel(StringUtils.format(Strings.EXCLUDE_FILE_FILTER, label));\n        } else {\n            _picker.setButtonLabel(Strings.NO_FILE_FILTER);\n        }\n    }\n\n    /**\n     * Sets and save the index of the active filter. Automatically set when editFilter() is completed.\n     * If no filter is passed in, then clear the last active filter index by setting it to -1.\n     *\n     * @param {{name: string, patterns: Array.<string>}=} filter\n     * @param {number=} index The index of the filter set in the list of saved filter sets or -1 if it is a new one\n     */\n    function setActiveFilter(filter, index) {\n        var filterSets = PreferencesManager.get(\"fileFilters\") || [];\n\n        if (filter) {\n            if (index === -1) {\n                // Add a new filter set\n                index = filterSets.length;\n                filterSets.push(filter);\n            } else if (index > -1 && index < filterSets.length) {\n                // Update an existing filter set only if the filter set has some changes\n                if (!_.isEqual(filterSets[index], filter)) {\n                    filterSets[index] = filter;\n                }\n            } else {\n                // Should not have been called with an invalid index to the available filter sets.\n                console.log(\"setActiveFilter is called with an invalid index: \" + index);\n                return;\n            }\n\n            PreferencesManager.set(\"fileFilters\", filterSets);\n            PreferencesManager.setViewState(\"activeFileFilter\", index);\n        } else {\n            // Explicitly set to -1 to remove the active file filter\n            PreferencesManager.setViewState(\"activeFileFilter\", -1);\n        }\n        FindUtils.notifyFileFiltersChanged();\n    }\n\n\n    /**\n     * Converts a user-specified filter object (as chosen in picker or retrieved from getFilters()) to a 'compiled' form\n     * that can be used with filterPath()/filterFileList().\n     * @param {!Array.<string>} userFilter\n     * @return {!string} 'compiled' filter that can be passed to filterPath()/filterFileList().\n     */\n    function compile(userFilter) {\n        // Automatically apply ** prefix/suffix to make writing simple substring-match filters more intuitive\n        var wrappedGlobs = userFilter.map(function (glob) {\n            // Automatic \"**\" prefix if not explicitly present\n            if (glob.substr(0, 2) !== \"**\") {\n                glob = \"**\" + glob;\n            }\n            // Automatic \"**\" suffix if not explicitly present and no \".\" in last path segment of filter string\n            if (glob.substr(-2, 2) !== \"**\") {\n                var lastSeg = glob.lastIndexOf(\"/\");\n                if (glob.indexOf(\".\", lastSeg + 1) === -1) {  // if no \"/\" present, this treats whole string as 'last segment'\n                    glob += \"**\";\n                }\n            }\n            return glob;\n        });\n\n        // Convert to regular expression for fast matching\n        var regexStrings = wrappedGlobs.map(function (glob) {\n            var reStr = \"\", i;\n            for (i = 0; i < glob.length; i++) {\n                var ch = glob[i];\n                if (ch === \"*\") {\n                    // Check for `**`\n                    if (glob[i + 1] === \"*\") {\n                        // Special case: `/**/` can collapse - that is, it shouldn't require matching both slashes\n                        if (glob[i + 2] === \"/\" && glob[i - 1] === \"/\") {\n                            reStr += \"(.*/)?\";\n                            i += 2; // skip 2nd * and / after it\n                        } else {\n                            reStr += \".*\";\n                            i++;    // skip 2nd *\n                        }\n                    } else {\n                        // Single `*`\n                        reStr += \"[^/]*\";\n                    }\n                } else if (ch === \"?\") {\n                    reStr += \"[^/]\";  // unlike '?' in regexp, in globs this requires exactly 1 char\n                } else {\n                    // Regular char with no special meaning\n                    reStr += StringUtils.regexEscape(ch);\n                }\n            }\n            return \"^\" + reStr + \"$\";\n        });\n        return regexStrings.join(\"|\");\n    }\n\n\n    /**\n     * Returns false if the given path matches any of the exclusion globs in the given filter. Returns true\n     * if the path does not match any of the globs. If filtering many paths at once, use filterFileList()\n     * for much better performance.\n     *\n     * @param {?string} compiledFilter  'Compiled' filter object as returned by compile(), or null to no-op\n     * @param {!string} fullPath\n     * @return {boolean}\n     */\n    function filterPath(compiledFilter, fullPath) {\n        if (!compiledFilter) {\n            return true;\n        }\n\n        var re = new RegExp(compiledFilter);\n        return !fullPath.match(re);\n    }\n\n    /**\n     * Returns a copy of 'files' filtered to just those that don't match any of the exclusion globs in the filter.\n     *\n     * @param {?string} compiledFilter  'Compiled' filter object as returned by compile(), or null to no-op\n     * @param {!Array.<File>} files\n     * @return {!Array.<File>}\n     */\n    function filterFileList(compiledFilter, files) {\n        if (!compiledFilter) {\n            return files;\n        }\n\n        var re = new RegExp(compiledFilter);\n        return files.filter(function (f) {\n            return !re.test(f.fullPath);\n        });\n    }\n\n    /**\n     * Returns a copy of 'file path' strings that match any of the exclusion globs in the filter.\n     *\n     * @param {?string} compiledFilter  'Compiled' filter object as returned by compile(), or null to no-op\n     * @param {!Array.<string>} An array with a list of full file paths that matches atleast one of the filter.\n     * @return {!Array.<string>}\n     */\n    function getPathsMatchingFilter(compiledFilter, filePaths) {\n        if (!compiledFilter) {\n            return filePaths;\n        }\n\n        var re = new RegExp(compiledFilter);\n        return filePaths.filter(function (f) {\n            return f.match(re);\n        });\n    }\n\n\n    /**\n     * Opens a dialog box to edit the given filter. When editing is finished, the value of getActiveFilter() changes to\n     * reflect the edits. If the dialog was canceled, the preference is left unchanged.\n     * @param {!{name: string, patterns: Array.<string>}} filter\n     * @param {number} index The index of the filter set to be edited or created. The value is -1 if it is for a new one\n     *          to be created.\n     * @return {!$.Promise} Dialog box promise\n     */\n    function editFilter(filter, index) {\n        var lastFocus = window.document.activeElement;\n\n        var templateVars = {\n                instruction: StringUtils.format(Strings.FILE_FILTER_INSTRUCTIONS, brackets.config.glob_help_url),\n                Strings: Strings\n            };\n        var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(EditFilterTemplate, templateVars)),\n            $nameField = dialog.getElement().find(\".exclusions-name\"),\n            $editField = dialog.getElement().find(\".exclusions-editor\"),\n            $remainingField = dialog.getElement().find(\".exclusions-name-characters-remaining\");\n\n        $nameField.val(filter.name);\n        $editField.val(filter.patterns.join(\"\\n\")).focus();\n\n        function getValue() {\n            var newFilter = $editField.val().split(\"\\n\");\n\n            // Remove blank lines\n            return newFilter.filter(function (glob) {\n                return glob.trim().length;\n            });\n        }\n\n        $nameField.bind('input', function () {\n            var remainingCharacters = FILTER_NAME_CHARACTER_MAX - $(this).val().length;\n            if (remainingCharacters < 0.25*FILTER_NAME_CHARACTER_MAX) {\n                $remainingField.show();\n\n                $remainingField.text(StringUtils.format(\n                    Strings.FILTER_NAME_REMAINING,\n                    remainingCharacters\n                ));\n\n                if (remainingCharacters < 0) {\n                    $remainingField.addClass(\"exclusions-name-characters-limit-reached\");\n                } else {\n                    $remainingField.removeClass(\"exclusions-name-characters-limit-reached\");\n                }\n            }\n            else {\n                $remainingField.hide();\n            }\n            updatePrimaryButton();\n        });\n\n        dialog.done(function (buttonId) {\n            if (buttonId === Dialogs.DIALOG_BTN_OK) {\n                // Update saved filter preference\n                setActiveFilter({ name: $nameField.val(), patterns: getValue() }, index);\n                _updatePicker();\n                _doPopulate();\n            }\n            lastFocus.focus();  // restore focus to old pos\n        });\n\n        // Code to update the file count readout at bottom of dialog (if context provided)\n        var $fileCount = dialog.getElement().find(\".exclusions-filecount\");\n\n        function updateFileCount() {\n            _context.promise.done(function (files) {\n                var filter = getValue();\n                if (filter.length) {\n                    var filtered = filterFileList(compile(filter), files);\n                    $fileCount.html(StringUtils.format(Strings.FILTER_FILE_COUNT, filtered.length, files.length, _context.label));\n                } else {\n                    $fileCount.html(StringUtils.format(Strings.FILTER_FILE_COUNT_ALL, files.length, _context.label));\n                }\n            });\n        }\n\n        // Code to enable/disable the OK button at the bottom of dialog (whether filter is empty or not)\n        var $primaryBtn = dialog.getElement().find(\".primary\");\n\n        function updatePrimaryButton() {\n            var trimmedValue = $editField.val().trim();\n            var exclusionNameLength = $nameField.val().length;\n\n            $primaryBtn.prop(\"disabled\", !trimmedValue.length || (exclusionNameLength > FILTER_NAME_CHARACTER_MAX));\n        }\n\n        $editField.on(\"input\", updatePrimaryButton);\n        updatePrimaryButton();\n\n        if (_context) {\n            $editField.on(\"input\", _.debounce(updateFileCount, 400));\n            updateFileCount();\n        } else {\n            $fileCount.hide();\n        }\n\n        return dialog.getPromise();\n    }\n\n\n    /**\n     * Marks the filter picker's currently selected item as most-recently used, and returns the corresponding\n     * 'compiled' filter object ready for use with filterPath().\n     * @param {!jQueryObject} picker UI returned from createFilterPicker()\n     * @return {!string} 'compiled' filter that can be passed to filterPath()/filterFileList().\n     */\n    function commitPicker(picker) {\n        var filter = getActiveFilter();\n        return (filter && filter.patterns.length) ? compile(filter.patterns) : \"\";\n    }\n\n    /**\n     * Remove the target item from the filter dropdown list and update dropdown button\n     * and dropdown list UI.\n     * @param {!Event} e Mouse events\n     */\n    function _handleDeleteFilter(e) {\n        // Remove the filter set from the preferences and\n        // clear the active filter set index from view state.\n        var filterSets        = PreferencesManager.get(\"fileFilters\") || [],\n            activeFilterIndex = PreferencesManager.getViewState(\"activeFileFilter\"),\n            filterIndex       = $(e.target).parent().data(\"index\") - FIRST_FILTER_INDEX;\n\n        // Don't let the click bubble upward.\n        e.stopPropagation();\n\n        filterSets.splice(filterIndex, 1);\n        PreferencesManager.set(\"fileFilters\", filterSets);\n\n        if (activeFilterIndex === filterIndex) {\n            // Removing the active filter, so clear the active filter\n            // both in the view state.\n            setActiveFilter(null);\n        } else if (activeFilterIndex > filterIndex) {\n            // Adjust the active filter index after the removal of a filter set before it.\n            --activeFilterIndex;\n            setActiveFilter(filterSets[activeFilterIndex], activeFilterIndex);\n        }\n\n        _updatePicker();\n        _doPopulate();\n        _picker.refresh();\n    }\n\n    /**\n     * Close filter dropdwon list and launch edit filter dialog.\n     * @param {!Event} e Mouse events\n     */\n    function _handleEditFilter(e) {\n        var filterSets  = PreferencesManager.get(\"fileFilters\") || [],\n            filterIndex = $(e.target).parent().data(\"index\") - FIRST_FILTER_INDEX;\n\n        // Don't let the click bubble upward.\n        e.stopPropagation();\n\n        // Close the dropdown first before opening the edit filter dialog\n        // so that it will restore focus to the DOM element that has focus\n        // prior to opening it.\n        _picker.closeDropdown();\n\n        editFilter(filterSets[filterIndex], filterIndex);\n    }\n\n    /**\n     * Set up mouse click event listeners for 'Delete' and 'Edit' buttons\n     * when the dropdown is open. Also set check mark on the active filter.\n     * @param {!Event>} event listRendered event triggered when the dropdown is open\n     * @param {!jQueryObject} $dropdown the jQuery DOM node of the dropdown list\n     */\n    function _handleListRendered(event, $dropdown) {\n        var activeFilterIndex = PreferencesManager.getViewState(\"activeFileFilter\"),\n            checkedItemIndex = (activeFilterIndex > -1) ? (activeFilterIndex + FIRST_FILTER_INDEX) : -1;\n        _picker.setChecked(checkedItemIndex, true);\n\n        $dropdown.find(\".filter-trash-icon\")\n            .on(\"click\", _handleDeleteFilter);\n\n        $dropdown.find(\".filter-edit-icon\")\n            .on(\"click\", _handleEditFilter);\n    }\n\n    /**\n     * Creates a UI element for selecting a filter, populated with a list of recently used filters, an option to\n     * edit the selected filter and another option to create a new filter. The client should call commitDropdown()\n     * when the UI containing the filter picker is confirmed (which updates the MRU order) and then use the\n     * returned filter object as needed.\n     *\n     * @param {?{label:string, promise:$.Promise}} context Info on files that filter will apply to.\n     *      This will be saved as _context for later use in creating a new filter or editing an\n     *      existing filter in Edit Filter dialog.\n     * @return {!jQueryObject} Picker UI. To retrieve the selected value, use commitPicker().\n     */\n    function createFilterPicker(context) {\n\n        function itemRenderer(item, index) {\n            if (index < FIRST_FILTER_INDEX) {\n                // Prefix the two filter commands with 'recent-filter-name' so that\n                // they also get the same margin-left as the actual filters.\n                return \"<span class='recent-filter-name'></span>\" + _.escape(item);\n            }\n\n            var condensedPatterns = _getCondensedForm(item.patterns),\n                templateVars = {\n                    \"filter-name\"    : _.escape(item.name || condensedPatterns),\n                    \"filter-patterns\": item.name ? \" - \" + _.escape(condensedPatterns) : \"\"\n                };\n\n            return Mustache.render(FilterNameTemplate, templateVars);\n        }\n\n        _context = context;\n        _picker = new DropdownButton(\"\", [], itemRenderer);\n\n        _updatePicker();\n        _doPopulate();\n\n        // Add 'file-filter-picker' to keep some margin space on the left of the button\n        _picker.$button.addClass(\"file-filter-picker no-focus\");\n\n        // Set up mouse click event listeners for 'Delete' and 'Edit' buttons\n        _picker.on(\"listRendered\", _handleListRendered);\n\n        _picker.on(\"select\", function (event, item, itemIndex) {\n            if (itemIndex === 0) {\n                // Close the dropdown first before opening the edit filter dialog\n                // so that it will restore focus to the DOM element that has focus\n                // prior to opening it.\n                _picker.closeDropdown();\n\n                // Create a new filter set\n                editFilter({ name: \"\", patterns: [] }, -1);\n            } else if (itemIndex === 1) {\n                // Uncheck the prior active filter in the dropdown list.\n                _picker.setChecked(itemIndex, false);\n\n                // Clear the active filter\n                setActiveFilter(null);\n                _updatePicker();\n            } else if (itemIndex >= FIRST_FILTER_INDEX && item) {\n                setActiveFilter(item, itemIndex - FIRST_FILTER_INDEX);\n                _picker.setChecked(itemIndex, true);\n                _updatePicker();\n            }\n        });\n\n        return _picker.$button;\n    }\n\n    /**\n     * Allows unit tests to open the file filter dropdown list.\n     */\n    function showDropdown() {\n        if (_picker) {\n            _picker.showDropdown();\n        }\n    }\n\n    /**\n     * Allows unit tests to close the file filter dropdown list.\n     */\n    function closeDropdown() {\n        if (_picker) {\n            _picker.closeDropdown();\n        }\n    }\n\n    // For unit tests only\n    exports.showDropdown       = showDropdown;\n    exports.closeDropdown      = closeDropdown;\n\n    exports.createFilterPicker     = createFilterPicker;\n    exports.commitPicker           = commitPicker;\n    exports.getActiveFilter        = getActiveFilter;\n    exports.setActiveFilter        = setActiveFilter;\n    exports.editFilter             = editFilter;\n    exports.compile                = compile;\n    exports.filterPath             = filterPath;\n    exports.filterFileList         = filterFileList;\n    exports.getPathsMatchingFilter = getPathsMatchingFilter;\n});\n"
  },
  {
    "path": "src/search/FindBar.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * UI for the Find/Replace and Find in Files modal bar.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                  = require(\"thirdparty/lodash\"),\n        Mustache           = require(\"thirdparty/mustache/mustache\"),\n        EventDispatcher    = require(\"utils/EventDispatcher\"),\n        Commands           = require(\"command/Commands\"),\n        KeyBindingManager  = require(\"command/KeyBindingManager\"),\n        KeyEvent           = require(\"utils/KeyEvent\"),\n        ModalBar           = require(\"widgets/ModalBar\").ModalBar,\n        PreferencesManager = require(\"preferences/PreferencesManager\"),\n        MainViewManager    = require(\"view/MainViewManager\"),\n        Strings            = require(\"strings\"),\n        ViewUtils          = require(\"utils/ViewUtils\"),\n        FindUtils          = require(\"search/FindUtils\"),\n        QuickSearchField   = require(\"search/QuickSearchField\").QuickSearchField,\n        HealthLogger       = require(\"utils/HealthLogger\");\n\n    /**\n     * @private\n     * The template we use for all Find bars.\n     * @type {string}\n     */\n    var _searchBarTemplate = require(\"text!htmlContent/findreplace-bar.html\");\n\n    var lastTypedTime = 0,\n        currentTime = 0,\n        intervalId = 0,\n        lastQueriedText = \"\",\n        lastTypedText = \"\",\n        lastTypedTextWasRegexp = false,\n        lastKeyCode;\n\n    /**\n     * @constructor\n     * Find Bar UI component, used for both single- and multi-file find/replace. This doesn't actually\n     * create and add the FindBar to the DOM - for that, call open().\n     *\n     * Dispatches these events:\n     *\n     * - queryChange - when the user types in the input field or sets a query option. Use getQueryInfo()\n     *      to get the current query state.\n     * - doFind - when the user chooses to do a Find Previous or Find Next.\n     *      Parameters are:\n     *          shiftKey - boolean, false for Find Next, true for Find Previous\n     * - doReplace - when the user chooses to do a single replace. Use getReplaceText() to get the current replacement text.\n     * - doReplaceBatch - when the user chooses to initiate a Replace All. Use getReplaceText() to get the current replacement text.\n     * - doReplaceAll - when the user chooses to perform a Replace All. Use getReplaceText() to get the current replacement text.\n     *-  close - when the find bar is closed\n     *\n     * @param {boolean=} options.multifile - true if this is a Find/Replace in Files (changes the behavior of Enter in\n     *      the fields, hides the navigator controls, shows the scope/filter controls, and if in replace mode, hides the\n     *      Replace button (so there's only Replace All)\n     * @param {boolean=} options.replace - true to show the Replace controls - default false\n     * @param {string=}  options.queryPlaceholder - label to show in the Find field - default empty string\n     * @param {string=}  options.initialQuery - query to populate in the Find field on open - default empty string\n     * @param {string=}  scopeLabel - HTML label to show for the scope of the search, expected to be already escaped - default empty string\n     */\n    function FindBar(options) {\n        var defaults = {\n            multifile: false,\n            replace: false,\n            queryPlaceholder: \"\",\n            initialQuery: \"\",\n            initialReplaceText: \"\",\n            scopeLabel: \"\"\n        };\n        this._options = _.extend(defaults, options);\n        this._closed = false;\n        this._enabled = true;\n        this.lastQueriedText = \"\";\n        this.lastTypedText = \"\";\n        this.lastTypedTextWasRegexp = false;\n    }\n    EventDispatcher.makeEventDispatcher(FindBar.prototype);\n\n    /*\n     * Global FindBar functions for making sure only one is open at a time.\n     */\n\n    // TODO: this is temporary - we should do this at the ModalBar level, but can't do that until\n    // we land the simplified Quick Open UI (#7227) that eliminates some asynchronicity in closing\n    // its ModalBar.\n\n    /**\n     * @private\n     * Register a find bar so we can close it later if another one tries to open.\n     * Note that this is a global function, not an instance function.\n     * @param {!FindBar} findBar The find bar to register.\n     */\n    FindBar._addFindBar = function (findBar) {\n        FindBar._bars = FindBar._bars || [];\n        FindBar._bars.push(findBar);\n    };\n\n    /**\n     * @private\n     * Remove a find bar from the list.\n     * Note that this is a global function, not an instance function.\n     * @param {FindBar} findBar The bar to remove.\n     */\n    FindBar._removeFindBar = function (findBar) {\n        if (FindBar._bars) {\n            _.pull(FindBar._bars, findBar);\n        }\n    };\n\n    /**\n     * @private\n     * Close all existing find bars. In theory there should be only one, but since there can be\n     * timing issues due to animation we maintain a list.\n     * Note that this is a global function, not an instance function.\n     */\n    FindBar._closeFindBars = function () {\n        var bars = FindBar._bars;\n        if (bars) {\n            bars.forEach(function (bar) {\n                bar.close(true, false);\n            });\n            bars = [];\n        }\n    };\n\n    /*\n     * Instance properties/functions\n     */\n\n    /**\n     * @private\n     * Options passed into the FindBar.\n     * @type {!{multifile: boolean, replace: boolean, queryPlaceholder: string, initialQuery: string, scopeLabel: string}}\n     */\n    FindBar.prototype._options = null;\n\n    /**\n     * @private\n     * Whether the FindBar has been closed.\n     * @type {boolean}\n     */\n    FindBar.prototype._closed = false;\n\n    /**\n     * @private\n     * Whether the FindBar is currently enabled.\n     * @type {boolean}\n     */\n    FindBar.prototype._enabled = true;\n\n    /**\n     * @private\n     * @type {?ModalBar} Modal bar containing this find bar's UI\n     */\n    FindBar.prototype._modalBar = null;\n\n    /**\n     * @private\n     * Returns the jQuery object for an element in this Find bar.\n     * @param {string} selector The selector for the element.\n     * @return {jQueryObject} The jQuery object for the element, or an empty object if the Find bar isn't yet\n     *      in the DOM or the element doesn't exist.\n     */\n    FindBar.prototype.$ = function (selector) {\n        if (this._modalBar) {\n            return $(selector, this._modalBar.getRoot());\n        } else {\n            return $();\n        }\n    };\n\n    // TODO: change IDs to classes\n\n    /**\n     * @private\n     * Set the state of the toggles in the Find bar to the saved prefs state.\n     */\n    FindBar.prototype._updateSearchBarFromPrefs = function () {\n        // Have to make sure we explicitly cast the second parameter to a boolean, because\n        // toggleClass expects literal true/false.\n        this.$(\"#find-case-sensitive\").toggleClass(\"active\", !!PreferencesManager.getViewState(\"caseSensitive\"));\n        this.$(\"#find-regexp\").toggleClass(\"active\", !!PreferencesManager.getViewState(\"regexp\"));\n    };\n\n    /**\n     * @private\n     * Save the prefs state based on the state of the toggles.\n     */\n    FindBar.prototype._updatePrefsFromSearchBar = function () {\n        var isRegexp = this.$(\"#find-regexp\").is(\".active\");\n        PreferencesManager.setViewState(\"caseSensitive\", this.$(\"#find-case-sensitive\").is(\".active\"));\n        PreferencesManager.setViewState(\"regexp\", isRegexp);\n        lastTypedTextWasRegexp = isRegexp;\n    };\n\n    /**\n     * @private\n     * Shows the keyboard shortcut for the given command in the element's tooltip.\n     * @param {jQueryObject} $elem The element to add the shortcut to.\n     * @param {string} commandId The ID for the command whose keyboard shortcut to show.\n     */\n    FindBar.prototype._addShortcutToTooltip = function ($elem, commandId) {\n        var replaceShortcut = KeyBindingManager.getKeyBindings(commandId)[0];\n        if (replaceShortcut) {\n            var oldTitle = $elem.attr(\"title\");\n            oldTitle = (oldTitle ? oldTitle + \" \" : \"\");\n            $elem.attr(\"title\", oldTitle + \"(\" + KeyBindingManager.formatKeyDescriptor(replaceShortcut.displayKey) + \")\");\n        }\n    };\n\n    /**\n     * @private\n     * Adds element to the search history queue.\n     * @param {string} search string that needs to be added to history.\n     */\n    FindBar.prototype._addElementToSearchHistory = function (searchVal) {\n        if (searchVal) {\n            var searchHistory = PreferencesManager.getViewState(\"searchHistory\");\n            var maxCount = PreferencesManager.get(\"maxSearchHistory\");\n            var searchQueryIndex = searchHistory.indexOf(searchVal);\n            if (searchQueryIndex !== -1) {\n                searchHistory.splice(searchQueryIndex, 1);\n            } else {\n                if (searchHistory.length === maxCount) {\n                    searchHistory.pop();\n                }\n            }\n            searchHistory.unshift(searchVal);\n            PreferencesManager.setViewState(\"searchHistory\", searchHistory);\n        }\n    };\n\n    /**\n     * Opens the Find bar, closing any other existing Find bars.\n     */\n    FindBar.prototype.open = function () {\n        var self = this;\n\n        // Normally, creating a new Find bar will simply cause the old one to close\n        // automatically. This can cause timing issues because the focus change might\n        // cause the new one to think it should close, too. So we simply explicitly\n        // close the old Find bar (with no animation) before creating a new one.\n        // TODO: see note above - this will move to ModalBar eventually.\n        FindBar._closeFindBars();\n        if (this._options.multifile) {\n            HealthLogger.searchDone(HealthLogger.SEARCH_NEW);\n        }\n\n        var templateVars = _.clone(this._options);\n        templateVars.Strings = Strings;\n        templateVars.replaceBatchLabel = (templateVars.multifile ? Strings.BUTTON_REPLACE_ALL_IN_FILES : Strings.BUTTON_REPLACE_BATCH);\n        templateVars.replaceAllLabel = Strings.BUTTON_REPLACE_ALL;\n\n        self._addElementToSearchHistory(this._options.initialQuery);\n\n        this._modalBar = new ModalBar(\n            Mustache.render(_searchBarTemplate, templateVars),\n            !!PreferencesManager.get('autoHideSearch')\t\t// 2nd arg = auto-close on Esc/blur\n        );\n        \n        // Done this way because ModalBar.js seems to react unreliably when\n        // modifying it to handle the escape key - the findbar wasn't getting\n        // closed as it should, instead persisting in the background\n        function _handleKeydown(e) {\n            if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                e.stopPropagation();\n                e.preventDefault();\n                self.close();\n            }\n        }\n        window.document.body.addEventListener(\"keydown\", _handleKeydown, true);\n        \n        // When the ModalBar closes, clean ourselves up.\n        this._modalBar.on(\"close\", function (event) {\n            window.document.body.removeEventListener(\"keydown\", _handleKeydown, true);\n\n            // Hide error popup, since it hangs down low enough to make the slide-out look awkward\n            self.showError(null);\n            self._modalBar = null;\n            self._closed = true;\n            window.clearInterval(intervalId);\n            intervalId = 0;\n            lastTypedTime = 0;\n            FindBar._removeFindBar(self);\n            MainViewManager.focusActivePane();\n            self.trigger(\"close\");\n            if (self.searchField) {\n                self.searchField.destroy();\n            }\n        });\n\n        FindBar._addFindBar(this);\n\n        var $root = this._modalBar.getRoot();\n        var historyIndex = 0;\n        $root\n            .on(\"input\", \"#find-what\", function () {\n                self.trigger(\"queryChange\");\n                var queryInfo = self.getQueryInfo();\n                lastTypedText = queryInfo.query;\n                lastTypedTextWasRegexp = queryInfo.isRegexp;\n            })\n            .on(\"click\", \"#find-case-sensitive, #find-regexp\", function (e) {\n                $(e.currentTarget).toggleClass(\"active\");\n                self._updatePrefsFromSearchBar();\n                self.trigger(\"queryChange\");\n                if (self._options.multifile) {  //instant search\n                    self.trigger(\"doFind\");\n                }\n            })\n            .on(\"click\", \".dropdown-icon\", function (e) {\n                var quickSearchContainer = $(\".quick-search-container\");\n                if (!self.searchField) {\n                    self.showSearchHints();\n                } else if (quickSearchContainer.is(':visible')) {\n                    quickSearchContainer.hide();\n                } else {\n                    self.searchField.setText(self.$(\"#find-what\").val());\n                    quickSearchContainer.show();\n                }\n                self.$(\"#find-what\").focus();\n            })\n            .on(\"keydown\", \"#find-what, #replace-with\", function (e) {\n                lastTypedTime = new Date().getTime();\n                lastKeyCode = e.keyCode;\n                var executeSearchIfNeeded = function () {\n                    // We only do instant search via node.\n                    if (FindUtils.isNodeSearchDisabled() || FindUtils.isInstantSearchDisabled()) {\n                        // we still keep the interval timer up as instant search could get enabled/disabled based on node busy state\n                        return;\n                    }\n                    if (self._closed) {\n                        return;\n                    }\n                    currentTime = new Date().getTime();\n\n                    if (lastTypedTime && (currentTime - lastTypedTime >= 100) &&\n                            self.getQueryInfo().query !== lastQueriedText &&\n                            !FindUtils.isNodeSearchInProgress()) {\n\n                        // init Search\n                        if (self._options.multifile) {\n                            if ($(e.target).is(\"#find-what\")) {\n                                if (!self._options.replace) {\n                                    HealthLogger.searchDone(HealthLogger.SEARCH_INSTANT);\n                                    self.trigger(\"doFind\");\n                                    lastQueriedText = self.getQueryInfo().query;\n                                }\n                            }\n                        }\n                    }\n                };\n                if (intervalId === 0) {\n                    intervalId = window.setInterval(executeSearchIfNeeded, 50);\n                }\n                if (e.keyCode === KeyEvent.DOM_VK_RETURN) {\n                    e.preventDefault();\n                    e.stopPropagation();\n                    self._addElementToSearchHistory(self.$(\"#find-what\").val());\n                    lastQueriedText = self.getQueryInfo().query;\n                    if (self._options.multifile) {\n                        if ($(e.target).is(\"#find-what\")) {\n                            if (self._options.replace) {\n                                // Just set focus to the Replace field.\n                                self.focusReplace();\n                            } else {\n                                HealthLogger.searchDone(HealthLogger.SEARCH_ON_RETURN_KEY);\n                                // Trigger a Find (which really means \"Find All\" in this context).\n                                self.trigger(\"doFind\");\n                            }\n                        } else {\n                            HealthLogger.searchDone(HealthLogger.SEARCH_REPLACE_ALL);\n                            self.trigger(\"doReplaceBatch\");\n                        }\n                    } else {\n                        // In the single file case, we just want to trigger a Find Next (or Find Previous\n                        // if Shift is held down).\n                        self.trigger(\"doFind\", e.shiftKey);\n                    }\n                    historyIndex = 0;\n                } else if (e.keyCode === KeyEvent.DOM_VK_DOWN || e.keyCode === KeyEvent.DOM_VK_UP) {\n                    var quickSearchContainer = $(\".quick-search-container\");\n                    if (!self.searchField) {\n                        self.showSearchHints();\n                    } else if (!quickSearchContainer.is(':visible')) {\n                        quickSearchContainer.show();\n                    }\n                }\n            })\n            .on(\"click\", \".close\", function () {\n                self.close();\n            });\n\n        if (!this._options.multifile) {\n            this._addShortcutToTooltip($(\"#find-next\"), Commands.CMD_FIND_NEXT);\n            this._addShortcutToTooltip($(\"#find-prev\"), Commands.CMD_FIND_PREVIOUS);\n            $root\n                .on(\"click\", \"#find-next\", function (e) {\n                    self.trigger(\"doFind\", false);\n                })\n                .on(\"click\", \"#find-prev\", function (e) {\n                    self.trigger(\"doFind\", true);\n                });\n        }\n\n        if (this._options.replace) {\n            this._addShortcutToTooltip($(\"#replace-yes\"), Commands.CMD_REPLACE);\n            $root\n                .on(\"click\", \"#replace-yes\", function (e) {\n                    self.trigger(\"doReplace\");\n                })\n                .on(\"click\", \"#replace-batch\", function (e) {\n                    self.trigger(\"doReplaceBatch\");\n                })\n                .on(\"click\", \"#replace-all\", function (e) {\n                    self.trigger(\"doReplaceAll\");\n                })\n                // One-off hack to make Find/Replace fields a self-contained tab cycle\n                // TODO: remove once https://trello.com/c/lTSJgOS2 implemented\n                .on(\"keydown\", function (e) {\n                    if (e.keyCode === KeyEvent.DOM_VK_TAB && !e.ctrlKey && !e.metaKey && !e.altKey) {\n                        if (e.target.id === \"replace-with\" && !e.shiftKey) {\n                            self.$(\"#find-what\").focus();\n                            e.preventDefault();\n                        } else if (e.target.id === \"find-what\" && e.shiftKey) {\n                            self.$(\"#replace-with\").focus();\n                            e.preventDefault();\n                        }\n                    }\n                });\n        }\n\n        if (this._options.multifile && FindUtils.isIndexingInProgress()) {\n            this.showIndexingSpinner();\n        }\n\n        // Set up the initial UI state.\n        this._updateSearchBarFromPrefs();\n        this.focusQuery();\n    };\n\n    /**\n     * @private\n     * Shows the search History in dropdown.\n     */\n    FindBar.prototype.showSearchHints = function () {\n        var self = this;\n        var searchFieldInput = self.$(\"#find-what\");\n        this.searchField = new QuickSearchField(searchFieldInput, {\n            verticalAdjust: searchFieldInput.offset().top > 0 ? 0 : this._modalBar.getRoot().outerHeight(),\n            maxResults: 20,\n            firstHighlightIndex: null,\n            resultProvider: function (query) {\n                var asyncResult = new $.Deferred();\n                asyncResult.resolve(PreferencesManager.getViewState(\"searchHistory\"));\n                return asyncResult.promise();\n            },\n            formatter: function (item, query) {\n                return \"<li>\" + item + \"</li>\";\n            },\n            onCommit: function (selectedItem, query) {\n                if (selectedItem) {\n                    self.$(\"#find-what\").val(selectedItem);\n                    self.trigger(\"queryChange\");\n                } else if (query.length) {\n                    self.searchField.setText(query);\n                }\n                self.$(\"#find-what\").focus();\n                $(\".quick-search-container\").hide();\n            },\n            onHighlight: function (selectedItem, query, explicit) {},\n            highlightZeroResults: false\n        });\n        this.searchField.setText(searchFieldInput.val());\n    };\n\n    /**\n     * Closes this Find bar. If already closed, does nothing.\n     * @param {boolean} suppressAnimation If true, don't do the standard closing animation. Default false.\n     */\n    FindBar.prototype.close = function (suppressAnimation) {\n        if (this._modalBar) {\n            // 1st arg = restore scroll pos; 2nd arg = no animation, since getting replaced immediately\n            this._modalBar.close(true, !suppressAnimation);\n        }\n    };\n\n    /**\n     * @return {boolean} true if this FindBar has been closed.\n     */\n    FindBar.prototype.isClosed = function () {\n        return this._closed;\n    };\n\n    /**\n     * @return {Object} The options passed into the FindBar.\n     */\n    FindBar.prototype.getOptions = function () {\n        return this._options;\n    };\n\n    /**\n     * Returns the current query and parameters.\n     * @return {{query: string, caseSensitive: boolean, isRegexp: boolean}}\n     */\n    FindBar.prototype.getQueryInfo = function () {\n        return {\n            query:           this.$(\"#find-what\").val() || \"\",\n            isCaseSensitive: this.$(\"#find-case-sensitive\").is(\".active\"),\n            isRegexp:        this.$(\"#find-regexp\").is(\".active\")\n        };\n    };\n\n    /**\n     * Show or clear an error message related to the query.\n     * @param {?string} error The error message to show, or null to hide the error display.\n     * @param {boolean=} isHTML Whether the error message is HTML that should remain unescaped.\n     */\n    FindBar.prototype.showError = function (error, isHTML) {\n        var $error = this.$(\".error\");\n        if (error) {\n            if (isHTML) {\n                $error.html(error);\n            } else {\n                $error.text(error);\n            }\n            $error.show();\n        } else {\n            $error.hide();\n        }\n    };\n\n    /**\n     * Set the find count.\n     * @param {string} count The find count message to show. Can be the empty string to hide it.\n     */\n    FindBar.prototype.showFindCount = function (count) {\n        this.$(\"#find-counter\").text(count);\n    };\n\n    /**\n     * Show or hide the no-results indicator and optional message. This is also used to\n     * indicate regular expression errors.\n     * @param {boolean} showIndicator\n     * @param {boolean} showMessage\n     */\n    FindBar.prototype.showNoResults = function (showIndicator, showMessage) {\n        ViewUtils.toggleClass(this.$(\"#find-what\"), \"no-results\", showIndicator);\n\n        var $msg = this.$(\".no-results-message\");\n        if (showMessage) {\n            $msg.show();\n        } else {\n            $msg.hide();\n        }\n    };\n\n    /**\n     * Returns the current replace text.\n     * @return {string}\n     */\n    FindBar.prototype.getReplaceText = function () {\n        return this.$(\"#replace-with\").val() || \"\";\n    };\n\n    /**\n     * Enables or disables the controls in the Find bar. Note that if enable is true, *all* controls will be\n     * re-enabled, even if some were previously disabled using enableNavigation() or enableReplace(), so you\n     * will need to refresh their enable state after calling this.\n     * @param {boolean} enable Whether to enable or disable the controls.\n     */\n    FindBar.prototype.enable = function (enable) {\n        this.$(\"#find-what, #replace-with, #find-prev, #find-next, #find-case-sensitive, #find-regexp\").prop(\"disabled\", !enable);\n        this._enabled = enable;\n    };\n\n    FindBar.prototype.focus = function (enable) {\n        this.$(\"#find-what\").focus();\n    };\n\n    /**\n     * @return {boolean} true if the FindBar is enabled.\n     */\n    FindBar.prototype.isEnabled = function () {\n        return this._enabled;\n    };\n\n    /**\n     * @return {boolean} true if the Replace button is enabled.\n     */\n    FindBar.prototype.isReplaceEnabled = function () {\n        return this.$(\"#replace-yes\").is(\":enabled\");\n    };\n\n    /**\n     * Enable or disable the navigation controls if present. Note that if the Find bar is currently disabled\n     * (i.e. isEnabled() returns false), this will have no effect.\n     * @param {boolean} enable Whether to enable the controls.\n     */\n    FindBar.prototype.enableNavigation = function (enable) {\n        if (this.isEnabled()) {\n            this.$(\"#find-prev, #find-next\").prop(\"disabled\", !enable);\n        }\n    };\n\n    /**\n     * Enable or disable the replace controls if present. Note that if the Find bar is currently disabled\n     * (i.e. isEnabled() returns false), this will have no effect.\n     * @param {boolean} enable Whether to enable the controls.\n     */\n    FindBar.prototype.enableReplace = function (enable) {\n        if (this.isEnabled) {\n            this.$(\"#replace-yes, #replace-batch, #replace-all\").prop(\"disabled\", !enable);\n        }\n    };\n\n    /**\n     * @private\n     * Focus and select the contents of the given field.\n     * @param {string} selector The selector for the field.\n     */\n    FindBar.prototype._focus = function (selector) {\n        this.$(selector)\n            .focus()\n            .get(0).select();\n    };\n\n    /**\n     * Sets focus to the query field and selects its text.\n     */\n    FindBar.prototype.focusQuery = function () {\n        this._focus(\"#find-what\");\n    };\n\n    /**\n     * Sets focus to the replace field and selects its text.\n     */\n    FindBar.prototype.focusReplace = function () {\n        this._focus(\"#replace-with\");\n    };\n\n    /**\n     * The indexing spinner is usually shown when node is indexing files\n     */\n    FindBar.prototype.showIndexingSpinner = function () {\n        this.$(\"#indexing-spinner\").removeClass(\"forced-hidden\");\n    };\n\n    FindBar.prototype.hideIndexingSpinner = function () {\n        this.$(\"#indexing-spinner\").addClass(\"forced-hidden\");\n    };\n\n    /**\n     * Force a search again\n     */\n    FindBar.prototype.redoInstantSearch = function () {\n        this.trigger(\"doFind\");\n    };\n\n    /*\n     * Returns the string used to prepopulate the find bar\n     * @param {!Editor} editor\n     * @return {string} first line of primary selection to populate the find bar\n     */\n    FindBar._getInitialQueryFromSelection = function(editor) {\n        var selectionText = editor.getSelectedText();\n        if (selectionText) {\n            return selectionText\n                .replace(/^\\n*/, \"\") // Trim possible newlines at the very beginning of the selection\n                .split(\"\\n\")[0];\n        }\n        return \"\";\n    };\n\n    /**\n     * Gets you the right query and replace text to prepopulate the Find Bar.\n     * @static\n     * @param {?FindBar} currentFindBar The currently open Find Bar, if any\n     * @param {?Editor} The active editor, if any\n     * @return {query: string, replaceText: string} Query and Replace text to prepopulate the Find Bar with\n     */\n    FindBar.getInitialQuery = function (currentFindBar, editor) {\n        var query,\n            selection = editor ? FindBar._getInitialQueryFromSelection(editor) : \"\",\n            replaceText = \"\";\n\n        if (currentFindBar && !currentFindBar.isClosed()) {\n            // The modalBar was already up. When creating the new modalBar, copy the\n            // current query instead of using the passed-in selected text.\n            var queryInfo = currentFindBar.getQueryInfo();\n            query = (!queryInfo.isRegexp && selection) || queryInfo.query;\n            replaceText = currentFindBar.getReplaceText();\n        } else {\n            var openedFindBar = FindBar._bars && _.find(FindBar._bars,\n                function (bar) {\n                    return !bar.isClosed();\n                }\n            );\n\n            if (openedFindBar) {\n                query = openedFindBar.getQueryInfo().query;\n                replaceText = openedFindBar.getReplaceText();\n            } else if (editor) {\n                query = (!lastTypedTextWasRegexp && selection) || lastQueriedText || lastTypedText;\n            }\n        }\n\n        return {query: query, replaceText: replaceText};\n    };\n\n    PreferencesManager.stateManager.definePreference(\"caseSensitive\", \"boolean\", false);\n    PreferencesManager.stateManager.definePreference(\"regexp\", \"boolean\", false);\n    PreferencesManager.stateManager.definePreference(\"searchHistory\", \"array\", []);\n    PreferencesManager.definePreference(\"maxSearchHistory\", \"number\", 10, {\n        description: Strings.FIND_HISTORY_MAX_COUNT\n    });\n\n    exports.FindBar = FindBar;\n});\n"
  },
  {
    "path": "src/search/FindInFiles.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * The core search functionality used by Find in Files and single-file Replace Batch.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                     = require(\"thirdparty/lodash\"),\n        FileFilters           = require(\"search/FileFilters\"),\n        Async                 = require(\"utils/Async\"),\n        StringUtils           = require(\"utils/StringUtils\"),\n        ProjectManager        = require(\"project/ProjectManager\"),\n        PreferencesManager    = require(\"preferences/PreferencesManager\"),\n        DocumentModule        = require(\"document/Document\"),\n        DocumentManager       = require(\"document/DocumentManager\"),\n        MainViewManager       = require(\"view/MainViewManager\"),\n        FileSystem            = require(\"filesystem/FileSystem\"),\n        LanguageManager       = require(\"language/LanguageManager\"),\n        SearchModel           = require(\"search/SearchModel\").SearchModel,\n        PerfUtils             = require(\"utils/PerfUtils\"),\n        NodeDomain            = require(\"utils/NodeDomain\"),\n        FileUtils             = require(\"file/FileUtils\"),\n        FindUtils             = require(\"search/FindUtils\"),\n        HealthLogger          = require(\"utils/HealthLogger\");\n\n    var _bracketsPath   = FileUtils.getNativeBracketsDirectoryPath(),\n        _modulePath     = FileUtils.getNativeModuleDirectoryPath(module),\n        _nodePath       = \"node/FindInFilesDomain\",\n        _domainPath     = [_bracketsPath, _modulePath, _nodePath].join(\"/\"),\n        searchDomain     = new NodeDomain(\"FindInFiles\", _domainPath),\n        searchScopeChanged = false,\n        findOrReplaceInProgress = false,\n        changedFileList = {};\n\n    /**\n     * Token used to indicate a specific reason for zero search results\n     * @const @type {!Object}\n     */\n    var ZERO_FILES_TO_SEARCH = {};\n\n    /**\n     * Maximum length of text displayed in search results panel\n     * @const\n     */\n    var MAX_DISPLAY_LENGTH = 200;\n\n    /**\n     * The search query and results model.\n     * @type {SearchModel}\n     */\n    var searchModel = new SearchModel();\n\n    /* Forward declarations */\n    var _documentChangeHandler,\n        _fileSystemChangeHandler,\n        _processCachedFileSystemEvents,\n        _debouncedFileSystemChangeHandler,\n        _fileNameChangeHandler,\n        clearSearch;\n    \n    /**\n     * Waits for FS changes to stack up until processing them\n     * (scripts like npm install can do a lot of movements on the disk)\n     * @const\n     */\n    var FILE_SYSTEM_EVENT_DEBOUNCE_TIME = 100;\n\n    /** Remove the listeners that were tracking potential search result changes */\n    function _removeListeners() {\n        DocumentModule.off(\"documentChange\", _documentChangeHandler);\n        FileSystem.off(\"change\", _debouncedFileSystemChangeHandler);\n        DocumentManager.off(\"fileNameChange\", _fileNameChangeHandler);\n    }\n\n    /** Add listeners to track events that might change the search result set */\n    function _addListeners() {\n        // Avoid adding duplicate listeners - e.g. if a 2nd search is run without closing the old results panel first\n        _removeListeners();\n\n        DocumentModule.on(\"documentChange\", _documentChangeHandler);\n        FileSystem.on(\"change\", _debouncedFileSystemChangeHandler);\n        DocumentManager.on(\"fileNameChange\",  _fileNameChangeHandler);\n    }\n\n    function nodeFileCacheComplete(event, numFiles, cacheSize) {\n        if (/\\/test\\/SpecRunner\\.html$/.test(window.location.pathname)) {\n            // Ignore the event in the SpecRunner window\n            return;\n        }\n\n        var projectRoot = ProjectManager.getProjectRoot(),\n            projectName = projectRoot ? projectRoot.name : null;\n\n        if (!projectName) {\n            console.error(\"'File cache complete' event received, but no project root found\");\n            projectName = \"noName00\";\n        }\n\n        FindUtils.setInstantSearchDisabled(false);\n        // Node search could be disabled if some error has happened in node. But upon\n        // project change, if we get this message, then it means that node search is working,\n        // we re-enable node search. If a search fails, node search will be switched off eventually.\n        FindUtils.setNodeSearchDisabled(false);\n        FindUtils.notifyIndexingFinished();\n        HealthLogger.setProjectDetail(projectName, numFiles, cacheSize);\n    }\n\n    /**\n     * @private\n     * Searches through the contents and returns an array of matches\n     * @param {string} contents\n     * @param {RegExp} queryExpr\n     * @return {!Array.<{start: {line:number,ch:number}, end: {line:number,ch:number}, line: string}>}\n     */\n    function _getSearchMatches(contents, queryExpr) {\n        // Quick exit if not found or if we hit the limit\n        if (searchModel.foundMaximum || contents.search(queryExpr) === -1) {\n            return [];\n        }\n\n        var match, lineNum, line, ch, totalMatchLength, matchedLines, numMatchedLines, lastLineLength, endCh,\n            padding, leftPadding, rightPadding, highlightOffset, highlightEndCh,\n            lines   = StringUtils.getLines(contents),\n            matches = [];\n\n        while ((match = queryExpr.exec(contents)) !== null) {\n            lineNum          = StringUtils.offsetToLineNum(lines, match.index);\n            line             = lines[lineNum];\n            ch               = match.index - contents.lastIndexOf(\"\\n\", match.index - 1) - 1;  // 0-based index\n            matchedLines     = match[0].split(\"\\n\");\n            numMatchedLines  = matchedLines.length;\n            totalMatchLength = match[0].length;\n            lastLineLength   = matchedLines[matchedLines.length - 1].length;\n            endCh            = (numMatchedLines === 1 ? ch + totalMatchLength : lastLineLength);\n            highlightEndCh   = (numMatchedLines === 1 ? endCh : line.length);\n            highlightOffset  = 0;\n\n            if (highlightEndCh <= MAX_DISPLAY_LENGTH) {\n                // Don't store more than 200 chars per line\n                line = line.substr(0, MAX_DISPLAY_LENGTH);\n            } else if (totalMatchLength > MAX_DISPLAY_LENGTH) {\n                // impossible to display the whole match\n                line = line.substr(ch, ch + MAX_DISPLAY_LENGTH);\n                highlightOffset = ch;\n            } else {\n                // Try to have both beginning and end of match displayed\n                padding = MAX_DISPLAY_LENGTH - totalMatchLength;\n                rightPadding = Math.floor(Math.min(padding / 2, line.length - highlightEndCh));\n                leftPadding = Math.ceil(padding - rightPadding);\n                highlightOffset = ch - leftPadding;\n                line = line.substring(highlightOffset, highlightEndCh + rightPadding);\n            }\n\n            matches.push({\n                start:       {line: lineNum, ch: ch},\n                end:         {line: lineNum + numMatchedLines - 1, ch: endCh},\n\n                highlightOffset: highlightOffset,\n\n                // Note that the following offsets from the beginning of the file are *not* updated if the search\n                // results change. These are currently only used for multi-file replacement, and we always\n                // abort the replace (by shutting the results panel) if we detect any result changes, so we don't\n                // need to keep them up to date. Eventually, we should either get rid of the need for these (by\n                // doing everything in terms of line/ch offsets, though that will require re-splitting files when\n                // doing a replace) or properly update them.\n                startOffset: match.index,\n                endOffset:   match.index + totalMatchLength,\n\n                line:        line,\n                result:      match,\n                isChecked:   true\n            });\n\n            // We have the max hits in just this 1 file. Stop searching this file.\n            // This fixed issue #1829 where code hangs on too many hits.\n            // Adds one over MAX_TOTAL_RESULTS in order to know if the search has exceeded\n            // or is equal to MAX_TOTAL_RESULTS. Additional result removed in SearchModel\n            if (matches.length > SearchModel.MAX_TOTAL_RESULTS) {\n                queryExpr.lastIndex = 0;\n                break;\n            }\n\n            // Pathological regexps like /^/ return 0-length matches. Ensure we make progress anyway\n            if (totalMatchLength === 0) {\n                queryExpr.lastIndex++;\n            }\n        }\n\n        return matches;\n    }\n\n    /**\n     * @private\n     * Update the search results using the given list of changes for the given document\n     * @param {Document} doc  The Document that changed, should be the current one\n     * @param {Array.<{from: {line:number,ch:number}, to: {line:number,ch:number}, text: !Array.<string>}>} changeList\n     *      An array of changes as described in the Document constructor\n     */\n    function _updateResults(doc, changeList) {\n        var i, diff, matches, lines, start, howMany,\n            resultsChanged = false,\n            fullPath       = doc.file.fullPath,\n            resultInfo     = searchModel.results[fullPath];\n\n        // Remove the results before we make any changes, so the SearchModel can accurately update its count.\n        searchModel.removeResults(fullPath);\n\n        changeList.forEach(function (change) {\n            lines = [];\n            start = 0;\n            howMany = 0;\n\n            // There is no from or to positions, so the entire file changed, we must search all over again\n            if (!change.from || !change.to) {\n                // TODO: add unit test exercising timestamp logic in this case\n                // We don't just call _updateSearchMatches() here because we want to continue iterating through changes in\n                // the list and update at the end.\n                resultInfo = {matches: _getSearchMatches(doc.getText(), searchModel.queryExpr), timestamp: doc.diskTimestamp};\n                resultsChanged = true;\n\n            } else {\n                // Get only the lines that changed\n                for (i = 0; i < change.text.length; i++) {\n                    lines.push(doc.getLine(change.from.line + i));\n                }\n\n                // We need to know how many newlines were inserted/deleted in order to update the rest of the line indices;\n                // this is the total number of newlines inserted (which is the length of the lines array minus\n                // 1, since the last line in the array is inserted without a newline after it) minus the\n                // number of original newlines being removed.\n                diff = lines.length - 1 - (change.to.line - change.from.line);\n\n                if (resultInfo) {\n                    // Search the last match before a replacement, the amount of matches deleted and update\n                    // the lines values for all the matches after the change\n                    resultInfo.matches.forEach(function (item) {\n                        if (item.end.line < change.from.line) {\n                            start++;\n                        } else if (item.end.line <= change.to.line) {\n                            howMany++;\n                        } else {\n                            item.start.line += diff;\n                            item.end.line   += diff;\n                        }\n                    });\n\n                    // Delete the lines that where deleted or replaced\n                    if (howMany > 0) {\n                        resultInfo.matches.splice(start, howMany);\n                    }\n                    resultsChanged = true;\n                }\n\n                // Searches only over the lines that changed\n                matches = _getSearchMatches(lines.join(\"\\r\\n\"), searchModel.queryExpr);\n                if (matches.length) {\n                    // Updates the line numbers, since we only searched part of the file\n                    matches.forEach(function (value, key) {\n                        matches[key].start.line += change.from.line;\n                        matches[key].end.line   += change.from.line;\n                    });\n\n                    // If the file index exists, add the new matches to the file at the start index found before\n                    if (resultInfo) {\n                        Array.prototype.splice.apply(resultInfo.matches, [start, 0].concat(matches));\n                    // If not, add the matches to a new file index\n                    } else {\n                        // TODO: add unit test exercising timestamp logic in self case\n                        resultInfo = {\n                            matches:   matches,\n                            collapsed: false,\n                            timestamp: doc.diskTimestamp\n                        };\n                    }\n                    resultsChanged = true;\n                }\n            }\n        });\n\n        // Always re-add the results, even if nothing changed.\n        if (resultInfo && resultInfo.matches.length) {\n            searchModel.setResults(fullPath, resultInfo);\n        }\n\n        if (resultsChanged) {\n            // Pass `true` for quickChange here. This will make listeners debounce the change event,\n            // avoiding lots of updates if the user types quickly.\n            searchModel.fireChanged(true);\n        }\n    }\n\n    /**\n     * Checks that the file matches the given subtree scope. To fully check whether the file\n     * should be in the search set, use _inSearchScope() instead - a supserset of this.\n     *\n     * @param {!File} file\n     * @param {?FileSystemEntry} scope Search scope, or null if whole project\n     * @return {boolean}\n     */\n    function _subtreeFilter(file, scope) {\n        if (scope) {\n            if (scope.isDirectory) {\n                // Dirs always have trailing slash, so we don't have to worry about being\n                // a substring of another dir name\n                return file.fullPath.indexOf(scope.fullPath) === 0;\n            } else {\n                return file.fullPath === scope.fullPath;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Filters out files that are known binary types.\n     * @param {string} fullPath\n     * @return {boolean} True if the file's contents can be read as text\n     */\n    function _isReadableText(fullPath) {\n        return !LanguageManager.getLanguageForPath(fullPath).isBinary();\n    }\n\n    /**\n     * Finds all candidate files to search in the given scope's subtree that are not binary content. Does NOT apply\n     * the current filter yet.\n     * @param {?FileSystemEntry} scope Search scope, or null if whole project\n     * @return {$.Promise} A promise that will be resolved with the list of files in the scope. Never rejected.\n     */\n    function getCandidateFiles(scope) {\n        function filter(file) {\n            return _subtreeFilter(file, scope) && _isReadableText(file.fullPath);\n        }\n\n        // If the scope is a single file, just check if the file passes the filter directly rather than\n        // trying to use ProjectManager.getAllFiles(), both for performance and because an individual\n        // in-memory file might be an untitled document that doesn't show up in getAllFiles().\n        if (scope && scope.isFile) {\n            return new $.Deferred().resolve(filter(scope) ? [scope] : []).promise();\n        } else {\n            return ProjectManager.getAllFiles(filter, true, true);\n        }\n    }\n\n    /**\n     * Checks that the file is eligible for inclusion in the search (matches the user's subtree scope and\n     * file exclusion filters, and isn't binary). Used when updating results incrementally - during the\n     * initial search, these checks are done in bulk via getCandidateFiles() and the filterFileList() call\n     * after it.\n     * @param {!File} file\n     * @return {boolean}\n     */\n    function _inSearchScope(file) {\n        // Replicate the checks getCandidateFiles() does\n        if (searchModel && searchModel.scope) {\n            if (!_subtreeFilter(file, searchModel.scope)) {\n                return false;\n            }\n        } else {\n            // Still need to make sure it's within project or working set\n            // In getCandidateFiles(), this is covered by the baseline getAllFiles() itself\n            if (file.fullPath.indexOf(ProjectManager.getProjectRoot().fullPath) !== 0) {\n                if (MainViewManager.findInWorkingSet(MainViewManager.ALL_PANES, file.fullPath) === -1) {\n                    return false;\n                }\n            }\n        }\n\n        if (!_isReadableText(file.fullPath)) {\n            return false;\n        }\n\n        // Replicate the filtering filterFileList() does\n        return FileFilters.filterPath(searchModel.filter, file.fullPath);\n    }\n\n\n    /**\n     * @private\n     * Tries to update the search result on document changes\n     * @param {$.Event} event\n     * @param {Document} document\n     * @param {<{from: {line:number,ch:number}, to: {line:number,ch:number}, text: !Array.<string>}>} change\n     *      A change list as described in the Document constructor\n     */\n    _documentChangeHandler = function (event, document, change) {\n        if (!findOrReplaceInProgress) {\n            changedFileList[document.file.fullPath] = true;\n        } else {\n            if (_inSearchScope(document.file)) {\n                _updateResults(document, change);\n            }\n        }\n    };\n\n    /**\n     * @private\n     * Finds search results in the given file and adds them to 'searchResults.' Resolves with\n     * true if any matches found, false if none found. Errors reading the file are treated the\n     * same as if no results found.\n     *\n     * Does not perform any filtering - assumes caller has already vetted this file as a search\n     * candidate.\n     *\n     * @param {!File} file\n     * @return {$.Promise}\n     */\n    function _doSearchInOneFile(file) {\n        var result = new $.Deferred();\n\n        DocumentManager.getDocumentText(file)\n            .done(function (text, timestamp) {\n                // Note that we don't fire a model change here, since this is always called by some outer batch\n                // operation that will fire it once it's done.\n                var matches = _getSearchMatches(text, searchModel.queryExpr);\n                searchModel.setResults(file.fullPath, {matches: matches, timestamp: timestamp});\n                result.resolve(!!matches.length);\n            })\n            .fail(function () {\n                // Always resolve. If there is an error, this file\n                // is skipped and we move on to the next file.\n                result.resolve(false);\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Inform node that the document has changed [along with its contents]\n     * @param {string} docPath the path of the changed document\n     */\n    function _updateDocumentInNode(docPath) {\n        DocumentManager.getDocumentForPath(docPath).done(function (doc) {\n            if (doc) {\n                var updateObject = {\n                    \"filePath\": docPath,\n                    \"docContents\": doc.getText()\n                };\n                searchDomain.exec(\"documentChanged\", updateObject);\n            }\n        });\n    }\n\n     /**\n     * @private\n     * sends all changed documents that we have tracked to node\n     */\n    function _updateChangedDocs() {\n        var key = null;\n        for (key in changedFileList) {\n            if (changedFileList.hasOwnProperty(key)) {\n                _updateDocumentInNode(key);\n            }\n        }\n    }\n\n    /**\n     * @private\n     * Executes the Find in Files search inside the current scope.\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo Query info object\n     * @param {!$.Promise} candidateFilesPromise Promise from getCandidateFiles(), which was called earlier\n     * @param {?string} filter A \"compiled\" filter as returned by FileFilters.compile(), or null for no filter\n     * @return {?$.Promise} A promise that's resolved with the search results (or ZERO_FILES_TO_SEARCH) or rejected when the find competes.\n     *      Will be null if the query is invalid.\n     */\n    function _doSearch(queryInfo, candidateFilesPromise, filter) {\n        searchModel.filter = filter;\n\n        var queryResult = searchModel.setQueryInfo(queryInfo);\n        if (!queryResult) {\n            return null;\n        }\n\n        var scopeName = searchModel.scope ? searchModel.scope.fullPath : ProjectManager.getProjectRoot().fullPath,\n            perfTimer = PerfUtils.markStart(\"FindIn: \" + scopeName + \" - \" + queryInfo.query);\n\n        findOrReplaceInProgress = true;\n\n        return candidateFilesPromise\n            .then(function (fileListResult) {\n                // Filter out files/folders that match user's current exclusion filter\n                fileListResult = FileFilters.filterFileList(filter, fileListResult);\n\n                if (searchModel.isReplace || FindUtils.isNodeSearchDisabled()) {\n                    if (fileListResult.length) {\n                        searchModel.allResultsAvailable = true;\n                        return Async.doInParallel(fileListResult, _doSearchInOneFile);\n                    } else {\n                        return ZERO_FILES_TO_SEARCH;\n                    }\n                }\n\n                var searchDeferred = new $.Deferred();\n\n                if (fileListResult.length) {\n                    var searchObject;\n                    if (searchScopeChanged) {\n                        var files = fileListResult\n                            .filter(function (entry) {\n                                return entry.isFile && _isReadableText(entry.fullPath);\n                            })\n                            .map(function (entry) {\n                                return entry.fullPath;\n                            });\n\n                        /* The following line prioritizes the open Document in editor and\n                         * pushes it to the top of the filelist. */\n                        files = FindUtils.prioritizeOpenFile(files, FindUtils.getOpenFilePath());\n\n                        searchObject = {\n                            \"files\": files,\n                            \"queryInfo\": queryInfo,\n                            \"queryExpr\": searchModel.queryExpr\n                        };\n                        searchScopeChanged = false;\n                    } else {\n                        searchObject = {\n                            \"queryInfo\": queryInfo,\n                            \"queryExpr\": searchModel.queryExpr\n                        };\n                    }\n\n                    if (searchModel.isReplace) {\n                        searchObject.getAllResults = true;\n                    }\n                    _updateChangedDocs();\n                    FindUtils.notifyNodeSearchStarted();\n                    searchDomain.exec(\"doSearch\", searchObject)\n                        .done(function (rcvd_object) {\n                            FindUtils.notifyNodeSearchFinished();\n                            if (!rcvd_object || !rcvd_object.results) {\n                                console.log('no node falling back to brackets search');\n                                FindUtils.setNodeSearchDisabled(true);\n                                searchDeferred.fail();\n                                clearSearch();\n                                return;\n                            }\n                            searchModel.results = rcvd_object.results;\n                            searchModel.numMatches = rcvd_object.numMatches;\n                            searchModel.numFiles = rcvd_object.numFiles;\n                            searchModel.exceedsMaximum = rcvd_object.exceedsMaximum;\n                            searchModel.allResultsAvailable = rcvd_object.allResultsAvailable;\n                            searchDeferred.resolve();\n                        })\n                        .fail(function () {\n                            FindUtils.notifyNodeSearchFinished();\n                            console.log('node fails');\n                            FindUtils.setNodeSearchDisabled(true);\n                            clearSearch();\n                            searchDeferred.reject();\n                        });\n                    return searchDeferred.promise();\n                } else {\n                    return ZERO_FILES_TO_SEARCH;\n                }\n            })\n            .then(function (zeroFilesToken) {\n                exports._searchDone = true; // for unit tests\n                PerfUtils.addMeasurement(perfTimer);\n\n                if (zeroFilesToken === ZERO_FILES_TO_SEARCH) {\n                    return zeroFilesToken;\n                } else {\n                    return searchModel.results;\n                }\n            }, function (err) {\n                console.log(\"find in files failed: \", err);\n                PerfUtils.finalizeMeasurement(perfTimer);\n\n                // In jQuery promises, returning the error here propagates the rejection,\n                // unlike in Promises/A, where we would need to re-throw it to do so.\n                return err;\n            });\n    }\n\n    /**\n     * @private\n     * Clears any previous search information, removing update listeners and clearing the model.\n     * @param {?Entry} scope Project file/subfolder to search within; else searches whole project.\n     */\n    clearSearch = function () {\n        findOrReplaceInProgress = false;\n        searchModel.clear();\n    };\n\n    /**\n     * Does a search in the given scope with the given filter. Used when you want to start a search\n     * programmatically.\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo Query info object\n     * @param {?Entry} scope Project file/subfolder to search within; else searches whole project.\n     * @param {?string} filter A \"compiled\" filter as returned by FileFilters.compile(), or null for no filter\n     * @param {?string} replaceText If this is a replacement, the text to replace matches with. This is just\n     *      stored in the model for later use - the replacement is not actually performed right now.\n     * @param {?$.Promise} candidateFilesPromise If specified, a promise that should resolve with the same set of files that\n     *      getCandidateFiles(scope) would return.\n     * @return {$.Promise} A promise that's resolved with the search results or rejected when the find competes.\n     */\n    function doSearchInScope(queryInfo, scope, filter, replaceText, candidateFilesPromise) {\n        clearSearch();\n        searchModel.scope = scope;\n        if (replaceText !== undefined) {\n            searchModel.isReplace = true;\n            searchModel.replaceText = replaceText;\n        }\n        candidateFilesPromise = candidateFilesPromise || getCandidateFiles(scope);\n        return _doSearch(queryInfo, candidateFilesPromise, filter);\n    }\n\n    /**\n     * Given a set of search results, replaces them with the given replaceText, either on disk or in memory.\n     * @param {Object.<fullPath: string, {matches: Array.<{start: {line:number,ch:number}, end: {line:number,ch:number}, startOffset: number, endOffset: number, line: string}>, collapsed: boolean}>} results\n     *      The list of results to replace, as returned from _doSearch..\n     * @param {string} replaceText The text to replace each result with.\n     * @param {?Object} options An options object:\n     *      forceFilesOpen: boolean - Whether to open all files in editors and do replacements there rather than doing the\n     *          replacements on disk. Note that even if this is false, files that are already open in editors will have replacements\n     *          done in memory.\n     *      isRegexp: boolean - Whether the original query was a regexp. If true, $-substitution is performed on the replaceText.\n     * @return {$.Promise} A promise that's resolved when the replacement is finished or rejected with an array of errors\n     *      if there were one or more errors. Each individual item in the array will be a {item: string, error: string} object,\n     *      where item is the full path to the file that could not be updated, and error is either a FileSystem error or one\n     *      of the `FindInFiles.ERROR_*` constants.\n     */\n    function doReplace(results, replaceText, options) {\n        return FindUtils.performReplacements(results, replaceText, options).always(function () {\n            // For UI integration testing only\n            exports._replaceDone = true;\n        });\n    }\n\n    /**\n     * @private\n     * Flags that the search scope has changed, so that the file list for the following search is recomputed\n     */\n    var _searchScopeChanged = function () {\n        searchScopeChanged = true;\n    };\n\n    /**\n     * Notify node that the results should be collapsed\n     */\n    function _searchcollapseResults() {\n        if (FindUtils.isNodeSearchDisabled()) {\n            return;\n        }\n        searchDomain.exec(\"collapseResults\", FindUtils.isCollapsedResults());\n    }\n\n    /**\n     * Inform node that the list of files has changed.\n     * @param {array} fileList The list of files that changed.\n     */\n    function filesChanged(fileList) {\n        if (FindUtils.isNodeSearchDisabled() || !fileList || fileList.length === 0) {\n            return;\n        }\n        var updateObject = {\n            \"fileList\": fileList\n        };\n        if (searchModel.filter) {\n            updateObject.filesInSearchScope = FileFilters.getPathsMatchingFilter(searchModel.filter, fileList);\n            _searchScopeChanged();\n        }\n        searchDomain.exec(\"filesChanged\", updateObject);\n    }\n\n    /**\n     * Inform node that the list of files have been removed.\n     * @param {array} fileList The list of files that was removed.\n     */\n    function filesRemoved(fileList) {\n        if (FindUtils.isNodeSearchDisabled() || !fileList || fileList.length === 0) {\n            return;\n        }\n        var updateObject = {\n            \"fileList\": fileList\n        };\n        if (searchModel.filter) {\n            updateObject.filesInSearchScope = FileFilters.getPathsMatchingFilter(searchModel.filter, fileList);\n            _searchScopeChanged();\n        }\n        searchDomain.exec(\"filesRemoved\", updateObject);\n    }\n\n    /**\n     * @private\n     * Moves the search results from the previous path to the new one and updates the results list, if required\n     * @param {$.Event} event\n     * @param {string} oldName\n     * @param {string} newName\n     */\n    _fileNameChangeHandler = function (event, oldName, newName) {\n        var resultsChanged = false;\n\n            // Update the search results\n        _.forEach(searchModel.results, function (item, fullPath) {\n            if (fullPath.indexOf(oldName) === 0) {\n                // node search : inform node about the rename\n                filesRemoved([fullPath]);\n                filesChanged([fullPath.replace(oldName, newName)]);\n\n                if (findOrReplaceInProgress) {\n                    searchModel.removeResults(fullPath);\n                    searchModel.setResults(fullPath.replace(oldName, newName), item);\n                    resultsChanged = true;\n                }\n            }\n        });\n\n        if (resultsChanged) {\n            searchModel.fireChanged();\n        }\n    };\n\n    /**\n     * @private\n     * Updates search results in response to FileSystem \"change\" event\n     * @param {$.Event} event\n     * @param {FileSystemEntry} entry\n     * @param {Array.<FileSystemEntry>=} added Added children\n     * @param {Array.<FileSystemEntry>=} removed Removed children\n     */\n    _fileSystemChangeHandler = function (event, entry, added, removed) {\n        var resultsChanged = false;\n\n        /*\n         * Remove existing search results that match the given entry's path\n         * @param {Array.<(File|Directory)>} entries\n         */\n        function _removeSearchResultsForEntries(entries) {\n            var fullPaths = [];\n            entries.forEach(function (entry) {\n                Object.keys(searchModel.results).forEach(function (fullPath) {\n                    if (fullPath === entry.fullPath ||\n                            (entry.isDirectory && fullPath.indexOf(entry.fullPath) === 0)) {\n                        // node search : inform node that the file is removed\n                        fullPaths.push(fullPath);\n                        if (findOrReplaceInProgress) {\n                            searchModel.removeResults(fullPath);\n                            resultsChanged = true;\n                        }\n                    }\n                });\n            });\n            // this should be called once with a large array instead of numerous calls with single items\n            filesRemoved(fullPaths);\n        }\n\n        /*\n         * Add new search results for these entries and all of its children\n         * @param {Array.<(File|Directory)>} entries\n         * @return {jQuery.Promise} Resolves when the results have been added\n         */\n        function _addSearchResultsForEntries(entries) {\n            var fullPaths = [];\n            return Async.doInParallel(entries, function (entry) {\n                var addedFiles = [],\n                    addedFilePaths = [],\n                    deferred = new $.Deferred();\n\n                // gather up added files\n                var visitor = function (child) {\n                    // Replicate filtering that getAllFiles() does\n                    if (ProjectManager.shouldShow(child)) {\n                        if (child.isFile && _isReadableText(child.name)) {\n                            // Re-check the filtering that the initial search applied\n                            if (_inSearchScope(child)) {\n                                addedFiles.push(child);\n                                addedFilePaths.push(child.fullPath);\n                            }\n                        }\n                        return true;\n                    }\n                    return false;\n                };\n\n                entry.visit(visitor, function (err) {\n                    if (err) {\n                        deferred.reject(err);\n                        return;\n                    }\n\n                    //node Search : inform node about the file changes\n                    //filesChanged(addedFilePaths);\n                    fullPaths = fullPaths.concat(addedFilePaths);\n\n                    if (findOrReplaceInProgress) {\n                        // find additional matches in all added files\n                        Async.doInParallel(addedFiles, function (file) {\n                            return _doSearchInOneFile(file)\n                                .done(function (foundMatches) {\n                                    resultsChanged = resultsChanged || foundMatches;\n                                });\n                        }).always(deferred.resolve);\n                    } else {\n                        deferred.resolve();\n                    }\n                });\n\n                return deferred.promise();\n            }).always(function () {\n                // this should be called once with a large array instead of numerous calls with single items\n                filesChanged(fullPaths);\n            });\n        }\n\n        if (!entry) {\n            // TODO: re-execute the search completely?\n            return;\n        }\n\n        var addPromise;\n        if (entry.isDirectory) {\n            if (added.length === 0 && removed.length === 0) {\n                // If the added or removed sets are null, must redo the search for the entire subtree - we\n                // don't know which child files/folders may have been added or removed.\n                _removeSearchResultsForEntries([ entry ]);\n\n                var deferred = $.Deferred();\n                addPromise = deferred.promise();\n                entry.getContents(function (err, entries) {\n                    _addSearchResultsForEntries(entries).always(deferred.resolve);\n                });\n            } else {\n                _removeSearchResultsForEntries(removed);\n                addPromise = _addSearchResultsForEntries(added);\n            }\n        } else { // entry.isFile\n            _removeSearchResultsForEntries([ entry ]);\n            addPromise = _addSearchResultsForEntries([ entry ]);\n        }\n\n        addPromise.always(function () {\n            // Restore the results if needed\n            if (resultsChanged) {\n                searchModel.fireChanged();\n            }\n        });\n    };\n    \n    /**\n     * This stores file system events emitted by watchers that were not yet processed\n     */\n    var _cachedFileSystemEvents = [];\n    \n    /**\n     * Debounced function to process emitted file system events\n     * for cases when there's a lot of fs events emitted in a very short period of time\n     */\n    _processCachedFileSystemEvents = _.debounce(function () {\n        // we need to reduce _cachedFileSystemEvents not to contain duplicates!\n        _cachedFileSystemEvents = _cachedFileSystemEvents.reduce(function (result, obj) {\n            var fullPath = obj.entry ? obj.entry.fullPath : null;\n            // merge added & removed\n            if (result[fullPath] && obj.isDirectory) {\n                obj.added = obj.added.concat(result[fullPath].added);\n                obj.removed = obj.removed.concat(result[fullPath].removed);\n            }\n            // use the latest event as base\n            result[fullPath] = obj;\n            return result;\n        }, {});\n        _.forEach(_cachedFileSystemEvents, function (obj) {\n            _fileSystemChangeHandler(obj.event, obj.entry, obj.added, obj.removed);\n        });\n        _cachedFileSystemEvents = [];\n    }, FILE_SYSTEM_EVENT_DEBOUNCE_TIME);\n    \n    /**\n     * Wrapper function for _fileSystemChangeHandler which handles all incoming fs events\n     * putting them to cache and executing a debounced function\n     */\n    _debouncedFileSystemChangeHandler = function (event, entry, added, removed) {\n        // normalize this here so we don't need to handle null later\n        var isDirectory = false;\n        if (entry && entry.isDirectory) {\n            isDirectory = true;\n            added = added || [];\n            removed = removed || [];\n        }\n        _cachedFileSystemEvents.push({\n            event: event,\n            entry: entry,\n            isDirectory: isDirectory,\n            added: added,\n            removed: removed\n        });\n        _processCachedFileSystemEvents();\n    };\n\n    /**\n     * On project change, inform node about the new list of files that needs to be crawled.\n     * Instant search is also disabled for the time being till the crawl is complete in node.\n     */\n    var _initCache = function () {\n        function filter(file) {\n            return _subtreeFilter(file, null) && _isReadableText(file.fullPath);\n        }\n        FindUtils.setInstantSearchDisabled(true);\n\n        //we always listen for filesytem changes.\n        _addListeners();\n\n        if (!PreferencesManager.get(\"findInFiles.nodeSearch\")) {\n            return;\n        }\n        ProjectManager.getAllFiles(filter, true, true)\n            .done(function (fileListResult) {\n                var files = fileListResult,\n                    filter = FileFilters.getActiveFilter();\n                if (filter && filter.patterns.length > 0) {\n                    files = FileFilters.filterFileList(FileFilters.compile(filter.patterns), files);\n                }\n                files = files.filter(function (entry) {\n                    return entry.isFile && _isReadableText(entry.fullPath);\n                }).map(function (entry) {\n                    return entry.fullPath;\n                });\n                FindUtils.notifyIndexingStarted();\n                searchDomain.exec(\"initCache\", files);\n            });\n        _searchScopeChanged();\n    };\n\n\n    /**\n     * Gets the next page of search results to append to the result set.\n     * @return {object} A promise that's resolved with the search results or rejected when the find competes.\n     */\n    function getNextPageofSearchResults() {\n        var searchDeferred = $.Deferred();\n        if (searchModel.allResultsAvailable) {\n            return searchDeferred.resolve().promise();\n        }\n        _updateChangedDocs();\n        FindUtils.notifyNodeSearchStarted();\n        searchDomain.exec(\"nextPage\")\n            .done(function (rcvd_object) {\n                FindUtils.notifyNodeSearchFinished();\n                if (searchModel.results) {\n                    var resultEntry;\n                    for (resultEntry in rcvd_object.results ) {\n                        if (rcvd_object.results.hasOwnProperty(resultEntry)) {\n                            searchModel.results[resultEntry.toString()] = rcvd_object.results[resultEntry];\n                        }\n                    }\n                } else {\n                    searchModel.results = rcvd_object.results;\n                }\n                searchModel.fireChanged();\n                searchDeferred.resolve();\n            })\n            .fail(function () {\n                FindUtils.notifyNodeSearchFinished();\n                console.log('node fails');\n                FindUtils.setNodeSearchDisabled(true);\n                searchDeferred.reject();\n            });\n        return searchDeferred.promise();\n    }\n\n    function getAllSearchResults() {\n        var searchDeferred = $.Deferred();\n        if (searchModel.allResultsAvailable) {\n            return searchDeferred.resolve().promise();\n        }\n        _updateChangedDocs();\n        FindUtils.notifyNodeSearchStarted();\n        searchDomain.exec(\"getAllResults\")\n            .done(function (rcvd_object) {\n                FindUtils.notifyNodeSearchFinished();\n                searchModel.results = rcvd_object.results;\n                searchModel.numMatches = rcvd_object.numMatches;\n                searchModel.numFiles = rcvd_object.numFiles;\n                searchModel.allResultsAvailable = true;\n                searchModel.fireChanged();\n                searchDeferred.resolve();\n            })\n            .fail(function () {\n                FindUtils.notifyNodeSearchFinished();\n                console.log('node fails');\n                FindUtils.setNodeSearchDisabled(true);\n                searchDeferred.reject();\n            });\n        return searchDeferred.promise();\n    }\n\n    ProjectManager.on(\"projectOpen\", _initCache);\n    FindUtils.on(FindUtils.SEARCH_FILE_FILTERS_CHANGED, _searchScopeChanged);\n    FindUtils.on(FindUtils.SEARCH_SCOPE_CHANGED, _searchScopeChanged);\n    FindUtils.on(FindUtils.SEARCH_COLLAPSE_RESULTS, _searchcollapseResults);\n    searchDomain.on(\"crawlComplete\", nodeFileCacheComplete);\n\n    // Public exports\n    exports.searchModel            = searchModel;\n    exports.doSearchInScope        = doSearchInScope;\n    exports.doReplace              = doReplace;\n    exports.getCandidateFiles      = getCandidateFiles;\n    exports.clearSearch            = clearSearch;\n    exports.ZERO_FILES_TO_SEARCH   = ZERO_FILES_TO_SEARCH;\n    exports.getNextPageofSearchResults          = getNextPageofSearchResults;\n    exports.getAllSearchResults    = getAllSearchResults;\n\n    // For unit tests only\n    exports._documentChangeHandler = _documentChangeHandler;\n    exports._fileNameChangeHandler = _fileNameChangeHandler;\n    exports._fileSystemChangeHandler = _fileSystemChangeHandler;\n});\n"
  },
  {
    "path": "src/search/FindInFilesUI.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * UI and controller logic for find/replace across multiple files within the project.\n *\n * FUTURE:\n *  - Handle matches that span multiple lines\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit           = require(\"utils/AppInit\"),\n        CommandManager    = require(\"command/CommandManager\"),\n        Commands          = require(\"command/Commands\"),\n        Dialogs           = require(\"widgets/Dialogs\"),\n        DefaultDialogs    = require(\"widgets/DefaultDialogs\"),\n        EditorManager     = require(\"editor/EditorManager\"),\n        WorkspaceManager  = require(\"view/WorkspaceManager\"),\n        FileFilters       = require(\"search/FileFilters\"),\n        FileUtils         = require(\"file/FileUtils\"),\n        FindBar           = require(\"search/FindBar\").FindBar,\n        FindInFiles       = require(\"search/FindInFiles\"),\n        FindUtils         = require(\"search/FindUtils\"),\n        InMemoryFile      = require(\"document/InMemoryFile\"),\n        ProjectManager    = require(\"project/ProjectManager\"),\n        SearchResultsView = require(\"search/SearchResultsView\").SearchResultsView,\n        StatusBar         = require(\"widgets/StatusBar\"),\n        Strings           = require(\"strings\"),\n        StringUtils       = require(\"utils/StringUtils\"),\n        HealthLogger      = require(\"utils/HealthLogger\"),\n        _                 = require(\"thirdparty/lodash\");\n\n\n    /** @const Maximum number of files to do replacements in-memory instead of on disk. */\n    var MAX_IN_MEMORY = 20;\n\n    /** @type {SearchResultsView} The results view. Initialized in htmlReady() */\n    var _resultsView = null;\n\n    /** @type {FindBar} Find bar containing the search UI. */\n    var _findBar = null;\n\n    /**\n     * @private\n     * Forward declaration for JSLint.\n     * @type {Function}\n     */\n    var _finishReplaceBatch;\n    \n    /**\n     * Does a search in the given scope with the given filter. Shows the result list once the search is complete.\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo Query info object\n     * @param {?Entry} scope Project file/subfolder to search within; else searches whole project.\n     * @param {?string} filter A \"compiled\" filter as returned by FileFilters.compile(), or null for no filter\n     * @param {?string} replaceText If this is a replacement, the text to replace matches with.\n     * @param {?$.Promise} candidateFilesPromise If specified, a promise that should resolve with the same set of files that\n     *      getCandidateFiles(scope) would return.\n     * @return {$.Promise} A promise that's resolved with the search results or rejected when the find competes.\n     */\n    function searchAndShowResults(queryInfo, scope, filter, replaceText, candidateFilesPromise) {\n        return FindInFiles.doSearchInScope(queryInfo, scope, filter, replaceText, candidateFilesPromise)\n            .done(function (zeroFilesToken) {\n                // Done searching all files: show results\n                if (FindInFiles.searchModel.hasResults()) {\n                    _resultsView.open();\n\n                    if (_findBar) {\n                        _findBar.enable(true);\n                        _findBar.focus();\n                    }\n\n                } else {\n                    _resultsView.close();\n\n                    if (_findBar) {\n                        var showMessage = false;\n                        _findBar.enable(true);\n                        if (zeroFilesToken === FindInFiles.ZERO_FILES_TO_SEARCH) {\n                            _findBar.showError(StringUtils.format(Strings.FIND_IN_FILES_ZERO_FILES,\n                                FindUtils.labelForScope(FindInFiles.searchModel.scope)), true);\n                        } else {\n                            showMessage = true;\n                        }\n                        _findBar.showNoResults(true, showMessage);\n                    }\n                }\n\n                StatusBar.hideBusyIndicator();\n            })\n            .fail(function (err) {\n                console.log(\"find in files failed: \", err);\n                StatusBar.hideBusyIndicator();\n            });\n    }\n\n    /**\n     * Does a search in the given scope with the given filter. Replace the result list once the search is complete.\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo Query info object\n     * @param {?Entry} scope Project file/subfolder to search within; else searches whole project.\n     * @param {?string} filter A \"compiled\" filter as returned by FileFilters.compile(), or null for no filter\n     * @param {?string} replaceText If this is a replacement, the text to replace matches with.\n     * @param {?$.Promise} candidateFilesPromise If specified, a promise that should resolve with the same set of files that\n     *      getCandidateFiles(scope) would return.\n     * @return {$.Promise} A promise that's resolved with the search results or rejected when the find competes.\n     */\n    function searchAndReplaceResults(queryInfo, scope, filter, replaceText, candidateFilesPromise) {\n        return FindInFiles.doSearchInScope(queryInfo, scope, filter, replaceText, candidateFilesPromise)\n            .done(function (zeroFilesToken) {\n                // Done searching all files: replace all\n                if (FindInFiles.searchModel.hasResults()) {\n                    _finishReplaceBatch(FindInFiles.searchModel);\n\n                    if (_findBar) {\n                        _findBar.enable(true);\n                        _findBar.focus();\n                    }\n\n                }\n                StatusBar.hideBusyIndicator();\n            })\n            .fail(function (err) {\n                console.log(\"replace all failed: \", err);\n                StatusBar.hideBusyIndicator();\n            });\n    }\n\n    /**\n     * @private\n     * Displays a non-modal embedded dialog above the code mirror editor that allows the user to do\n     * a find operation across all files in the project.\n     * @param {?Entry} scope  Project file/subfolder to search within; else searches whole project.\n     * @param {boolean=} showReplace If true, show the Replace controls.\n     */\n    function _showFindBar(scope, showReplace) {\n        FindUtils.notifySearchScopeChanged();\n        // If the scope is a file with a custom viewer, then we\n        // don't show find in files dialog.\n        if (scope && !EditorManager.canOpenPath(scope.fullPath)) {\n            return;\n        }\n\n        if (scope instanceof InMemoryFile) {\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: scope.fullPath }).done(function () {\n                CommandManager.execute(Commands.CMD_FIND);\n            });\n            return;\n        }\n\n        // Get initial query/replace text\n        var currentEditor = EditorManager.getActiveEditor(),\n            initialQuery = FindBar.getInitialQuery(_findBar, currentEditor);\n\n        // Close our previous find bar, if any. (The open() of the new _findBar will\n        // take care of closing any other find bar instances.)\n        if (_findBar) {\n            _findBar.close();\n        }\n\n        _findBar = new FindBar({\n            multifile: true,\n            replace: showReplace,\n            initialQuery: initialQuery.query,\n            initialReplaceText: initialQuery.replaceText,\n            queryPlaceholder: Strings.FIND_QUERY_PLACEHOLDER,\n            scopeLabel: FindUtils.labelForScope(scope)\n        });\n        _findBar.open();\n\n        // TODO Should push this state into ModalBar (via a FindBar API) instead of installing a callback like this.\n        // Custom closing behavior: if in the middle of executing search, blur shouldn't close ModalBar yet. And\n        // don't close bar when opening Edit Filter dialog either.\n        _findBar._modalBar.isLockedOpen = function () {\n            // TODO: should have state for whether the search is executing instead of looking at find bar state\n            // TODO: should have API on filterPicker to figure out if dialog is open\n            return !_findBar.isEnabled() || $(\".modal.instance .exclusions-editor\").length > 0;\n        };\n\n        var candidateFilesPromise = FindInFiles.getCandidateFiles(scope),  // used for eventual search, and in exclusions editor UI\n            filterPicker;\n\n        function handleQueryChange() {\n            // Check the query expression on every input event. This way the user is alerted\n            // to any RegEx syntax errors immediately.\n            var queryInfo = _findBar.getQueryInfo(),\n                queryResult = FindUtils.parseQueryInfo(queryInfo);\n\n            // Enable the replace button appropriately.\n            _findBar.enableReplace(queryResult.valid);\n\n            if (queryResult.valid || queryResult.empty) {\n                _findBar.showNoResults(false);\n                _findBar.showError(null);\n            } else {\n                _findBar.showNoResults(true, false);\n                _findBar.showError(queryResult.error);\n            }\n        }\n\n        function startSearch(replaceText) {\n            var queryInfo = _findBar.getQueryInfo(),\n                disableFindBar = FindUtils.isNodeSearchDisabled() || (replaceText ? true : false);\n            if (queryInfo && queryInfo.query) {\n                _findBar.enable(!disableFindBar);\n                StatusBar.showBusyIndicator(disableFindBar);\n                if (queryInfo.isRegexp) {\n                    HealthLogger.searchDone(HealthLogger.SEARCH_REGEXP);\n                }\n                if (queryInfo.isCaseSensitive) {\n                    HealthLogger.searchDone(HealthLogger.SEARCH_CASE_SENSITIVE);\n                }\n\n                var filter;\n                if (filterPicker) {\n                    filter = FileFilters.commitPicker(filterPicker);\n                } else {\n                    // Single-file scope: don't use any file filters\n                    filter = null;\n                }\n                searchAndShowResults(queryInfo, scope, filter, replaceText, candidateFilesPromise);\n            }\n            return null;\n        }\n\n        function startReplace() {\n            startSearch(_findBar.getReplaceText());\n        }\n\n        _findBar\n            .on(\"doFind.FindInFiles\", function () {\n                // Subtle issue: we can't just pass startSearch directly as the handler, because\n                // we don't want it to get the event object as an argument.\n                startSearch();\n            })\n            .on(\"queryChange.FindInFiles\", handleQueryChange)\n            .on(\"close.FindInFiles\", function (e) {\n                _findBar.off(\".FindInFiles\");\n                _findBar = null;\n            });\n\n        if (showReplace) {\n            // We shouldn't get a \"doReplace\" in this case, since the Replace button\n            // is hidden when we set options.multifile.\n            _findBar.on(\"doReplaceBatch.FindInFiles\", startReplace);\n        }\n\n        var oldModalBarHeight = _findBar._modalBar.height();\n\n        // Show file-exclusion UI *unless* search scope is just a single file\n        if (!scope || scope.isDirectory) {\n            var exclusionsContext = {\n                label: FindUtils.labelForScope(scope),\n                promise: candidateFilesPromise\n            };\n\n            filterPicker = FileFilters.createFilterPicker(exclusionsContext);\n            // TODO: include in FindBar? (and disable it when FindBar is disabled)\n            _findBar._modalBar.getRoot().find(\".scope-group\").append(filterPicker);\n        }\n\n        handleQueryChange();\n\n        // Appending FilterPicker and query text can change height of modal bar, so resize editor.\n        // Preserve scroll position of the current full editor across the editor refresh, adjusting\n        // for the height of the modal bar so the code doesn't appear to shift if possible.\n        var fullEditor = EditorManager.getCurrentFullEditor(),\n            scrollPos;\n        if (fullEditor) {\n            scrollPos = fullEditor.getScrollPos();\n            scrollPos.y -= oldModalBarHeight;   // modalbar already showing, adjust for old height\n        }\n        WorkspaceManager.recomputeLayout();\n        if (fullEditor) {\n            fullEditor._codeMirror.scrollTo(scrollPos.x, scrollPos.y + _findBar._modalBar.height());\n        }\n    }\n\n    /**\n     * @private\n     * Finish a replace across files operation when the user clicks \"Replace\" on the results panel.\n     * @param {SearchModel} model The model for the search associated with ths replace.\n     */\n    function _finishReplaceBatch(model) {\n        var replaceText = model.replaceText;\n        if (replaceText === null) {\n            return;\n        }\n\n        // Clone the search results so that they don't get updated in the middle of the replacement.\n        var resultsClone = _.cloneDeep(model.results),\n            replacedFiles = Object.keys(resultsClone).filter(function (path) {\n                return FindUtils.hasCheckedMatches(resultsClone[path]);\n            }),\n            isRegexp = model.queryInfo.isRegexp;\n\n        function processReplace(forceFilesOpen) {\n            StatusBar.showBusyIndicator(true);\n            FindInFiles.doReplace(resultsClone, replaceText, { forceFilesOpen: forceFilesOpen, isRegexp: isRegexp })\n                .fail(function (errors) {\n                    var message = Strings.REPLACE_IN_FILES_ERRORS + FileUtils.makeDialogFileList(\n                            errors.map(function (errorInfo) {\n                                return ProjectManager.makeProjectRelativeIfPossible(errorInfo.item);\n                            })\n                        );\n\n                    Dialogs.showModalDialog(\n                        DefaultDialogs.DIALOG_ID_ERROR,\n                        Strings.REPLACE_IN_FILES_ERRORS_TITLE,\n                        message,\n                        [\n                            {\n                                className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                                id        : Dialogs.DIALOG_BTN_OK,\n                                text      : Strings.BUTTON_REPLACE_WITHOUT_UNDO\n                            }\n                        ]\n                    );\n                })\n                .always(function () {\n                    StatusBar.hideBusyIndicator();\n                });\n        }\n\n        if (replacedFiles.length <= MAX_IN_MEMORY) {\n            // Just do the replacements in memory.\n            _resultsView.close();\n            processReplace(true);\n        } else {\n            Dialogs.showModalDialog(\n                DefaultDialogs.DIALOG_ID_INFO,\n                Strings.REPLACE_WITHOUT_UNDO_WARNING_TITLE,\n                StringUtils.format(Strings.REPLACE_WITHOUT_UNDO_WARNING, MAX_IN_MEMORY),\n                [\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,\n                        id        : Dialogs.DIALOG_BTN_CANCEL,\n                        text      : Strings.CANCEL\n                    },\n                    {\n                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,\n                        id        : Dialogs.DIALOG_BTN_OK,\n                        text      : Strings.BUTTON_REPLACE_WITHOUT_UNDO\n                    }\n                ]\n            )\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_OK) {\n                        _resultsView.close();\n                        processReplace(false);\n                    }\n                });\n        }\n    }\n\n    // Command handlers\n\n    /**\n     * @private\n     * Bring up the Find in Files UI with the replace options.\n     */\n    function _showReplaceBar() {\n        FindUtils.notifySearchScopeChanged();\n        _showFindBar(null, true);\n    }\n\n    /**\n     * @private\n     * Search within the file/subtree defined by the sidebar selection\n     */\n    function _showFindBarForSubtree() {\n        FindUtils.notifySearchScopeChanged();\n        var selectedEntry = ProjectManager.getSelectedItem();\n        _showFindBar(selectedEntry);\n    }\n\n    /**\n     * @private\n     * Search within the file/subtree defined by the sidebar selection\n     */\n    function _showReplaceBarForSubtree() {\n        FindUtils.notifySearchScopeChanged();\n        var selectedEntry = ProjectManager.getSelectedItem();\n        _showFindBar(selectedEntry, true);\n    }\n\n    /**\n     * @private\n     * Close the open search bar, if any. For unit tests.\n     */\n    function _closeFindBar() {\n        if (_findBar) {\n            _findBar.close();\n        }\n    }\n\n    /**\n     * When the search indexing is started, we need to show the indexing status on the find bar if present.\n     */\n    function _searchIndexingStarted() {\n        if (_findBar && _findBar._options.multifile && FindUtils.isIndexingInProgress()) {\n            _findBar.showIndexingSpinner();\n        }\n    }\n\n    /**\n     * Once the indexing has finished, clear the indexing spinner\n     */\n    function _searchIndexingFinished() {\n        if (_findBar) {\n            _findBar.hideIndexingSpinner();\n        }\n    }\n\n    /**\n     * Issues a search if find bar is visible and is multi file search and not instant search\n     */\n    function _defferedSearch() {\n        if (_findBar && _findBar._options.multifile && !_findBar._options.replace) {\n            _findBar.redoInstantSearch();\n        }\n    }\n\n    /**\n     * Schedules a search on search scope/filter changes. Have to schedule as when we listen to this event, the file filters\n     * might not have been updated yet.\n     */\n    function _searchIfRequired() {\n        if (!FindUtils.isInstantSearchDisabled() && _findBar && _findBar._options.multifile && !_findBar._options.replace) {\n            setTimeout(_defferedSearch, 100);\n        }\n    }\n\n    /**\n    * @public\n    * Closes the search results panel\n    */\n    function closeResultsPanel() {\n        _resultsView.close();\n        _closeFindBar();\n\t}\n\n    // Initialize items dependent on HTML DOM\n    AppInit.htmlReady(function () {\n        var model = FindInFiles.searchModel;\n        _resultsView = new SearchResultsView(model, \"find-in-files-results\", \"find-in-files.results\");\n        _resultsView\n            .on(\"replaceBatch\", function () {\n                _finishReplaceBatch(model);\n            })\n            .on(\"close\", function () {\n                FindInFiles.clearSearch();\n            })\n            .on(\"getNextPage\", function () {\n                FindInFiles.getNextPageofSearchResults().done(function () {\n                    if (FindInFiles.searchModel.hasResults()) {\n                        _resultsView.showNextPage();\n                    }\n                });\n            })\n            .on(\"getLastPage\", function () {\n                FindInFiles.getAllSearchResults().done(function () {\n                    if (FindInFiles.searchModel.hasResults()) {\n                        _resultsView.showLastPage();\n                    }\n                });\n            });\n    });\n\n    // Initialize: register listeners\n    ProjectManager.on(\"beforeProjectClose\", function () { _resultsView.close(); });\n\n    // Initialize: command handlers\n    CommandManager.register(Strings.CMD_FIND_IN_FILES,       Commands.CMD_FIND_IN_FILES,       _showFindBar);\n    CommandManager.register(Strings.CMD_FIND_IN_SUBTREE,     Commands.CMD_FIND_IN_SUBTREE,     _showFindBarForSubtree);\n\n    CommandManager.register(Strings.CMD_REPLACE_IN_FILES,    Commands.CMD_REPLACE_IN_FILES,    _showReplaceBar);\n    CommandManager.register(Strings.CMD_REPLACE_IN_SUBTREE,  Commands.CMD_REPLACE_IN_SUBTREE,  _showReplaceBarForSubtree);\n\n    FindUtils.on(FindUtils.SEARCH_INDEXING_STARTED, _searchIndexingStarted);\n    FindUtils.on(FindUtils.SEARCH_INDEXING_FINISHED, _searchIndexingFinished);\n    FindUtils.on(FindUtils.SEARCH_FILE_FILTERS_CHANGED, _searchIfRequired);\n    FindUtils.on(FindUtils.SEARCH_SCOPE_CHANGED, _searchIfRequired);\n\n    // Public exports\n    exports.searchAndShowResults = searchAndShowResults;\n    exports.searchAndReplaceResults = searchAndReplaceResults;\n    exports.closeResultsPanel = closeResultsPanel;\n\n    // For unit testing\n    exports._showFindBar  = _showFindBar;\n    exports._closeFindBar = _closeFindBar;\n});\n"
  },
  {
    "path": "src/search/FindReplace.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: FindReplace*/\n\n/**\n * Adds Find and Replace commands\n *\n * Originally based on the code in CodeMirror/lib/util/search.js.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Editor              = require(\"editor/Editor\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FindBar             = require(\"search/FindBar\").FindBar,\n        FindUtils           = require(\"search/FindUtils\"),\n        FindInFilesUI       = require(\"search/FindInFilesUI\"),\n        ScrollTrackMarkers  = require(\"search/ScrollTrackMarkers\"),\n        _                   = require(\"thirdparty/lodash\"),\n        CodeMirror          = require(\"thirdparty/CodeMirror/lib/codemirror\");\n\n    /**\n     * Maximum file size to search within (in chars)\n     * @const {number}\n     */\n    var FIND_MAX_FILE_SIZE  = 500000;\n\n    /**\n     * If the number of matches exceeds this limit, inline text highlighting and scroll-track tickmarks are disabled\n     * @const {number}\n     */\n    var FIND_HIGHLIGHT_MAX  = 2000;\n\n    /**\n     * Currently open Find or Find/Replace bar, if any\n     * @type {?FindBar}\n     */\n    var findBar;\n\n    function SearchState() {\n        this.searchStartPos = null;\n        this.parsedQuery = null;\n        this.queryInfo = null;\n        this.foundAny = false;\n        this.marked = [];\n        this.resultSet = [];\n        this.matchIndex = -1;\n        this.markedCurrent = null;\n    }\n\n    function getSearchState(cm) {\n        if (!cm._searchState) {\n            cm._searchState = new SearchState();\n        }\n        return cm._searchState;\n    }\n\n    function getSearchCursor(cm, state, pos) {\n        // Heuristic: if the query string is all lowercase, do a case insensitive search.\n        return cm.getSearchCursor(state.parsedQuery, pos, !state.queryInfo.isCaseSensitive);\n    }\n\n    function parseQuery(queryInfo) {\n        if (findBar) {\n            findBar.showError(null);\n        }\n\n        var parsed = FindUtils.parseQueryInfo(queryInfo);\n        if (parsed.empty === true) {\n            return \"\";\n        }\n\n        if (!parsed.valid) {\n            if (findBar) {\n                findBar.showError(parsed.error);\n            }\n            return \"\";\n        }\n\n        return parsed.queryExpr;\n    }\n\n    /**\n     * @private\n     * Determine the query from the given info and store it in the state.\n     * @param {SearchState} state The state to store the parsed query in\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo\n     *      The query info object as returned by FindBar.getQueryInfo()\n     */\n    function setQueryInfo(state, queryInfo) {\n        state.queryInfo = queryInfo;\n        if (!queryInfo) {\n            state.parsedQuery = null;\n        } else {\n            state.parsedQuery = parseQuery(queryInfo);\n        }\n    }\n\n    /**\n     * @private\n     * Show the current match index by finding matchRange in the resultSet stored\n     * in the search state if this is the first call for a new search query. For\n     * subsequent calls, just compare matchRange with the next match in the resultSet\n     * based on the search direction and show the next match if they are the same.\n     * If not, then find the match index by searching matchRange in the entire resultSet.\n     *\n     * @param {!SearchState} state The search state that has the array of search result\n     * @param {!{from: {line: number, ch: number}, to: {line: number, ch: number}}} matchRange - the range of current match\n     * @param {!boolean} searchBackwards true if searching backwards\n     */\n    function _updateFindBarWithMatchInfo(state, matchRange, searchBackwards) {\n        // Bail if there is no result set.\n        if (!state.foundAny) {\n            return;\n        }\n\n        if (findBar) {\n            if (state.matchIndex === -1) {\n                state.matchIndex = _.findIndex(state.resultSet, matchRange);\n            } else {\n                state.matchIndex = searchBackwards ? state.matchIndex - 1 : state.matchIndex + 1;\n                // Adjust matchIndex for modulo wraparound\n                state.matchIndex = (state.matchIndex + state.resultSet.length) % state.resultSet.length;\n\n                // Confirm that we find the right matchIndex. If not, then search\n                // matchRange in the entire resultSet.\n                if (!_.isEqual(state.resultSet[state.matchIndex], matchRange)) {\n                    state.matchIndex = _.findIndex(state.resultSet, matchRange);\n                }\n            }\n\n            console.assert(state.matchIndex !== -1);\n            if (state.matchIndex !== -1) {\n                // Convert to 1-based by adding one before showing the index.\n                findBar.showFindCount(StringUtils.format(Strings.FIND_MATCH_INDEX,\n                                                        state.matchIndex + 1, state.resultSet.length));\n            }\n        }\n    }\n\n    /**\n     * @private\n     * Returns the next match for the current query (from the search state) before/after the given position. Wraps around\n     * the end of the document if no match is found before the end.\n     *\n     * @param {!Editor} editor The editor to search in\n     * @param {boolean} searchBackwards true to search backwards\n     * @param {{line: number, ch: number}=} pos The position to start from. Defaults to the current primary selection's\n     *      head cursor position.\n     * @param {boolean=} wrap Whether to wrap the search around if we hit the end of the document. Default true.\n     * @return {?{start: {line: number, ch: number}, end: {line: number, ch: number}}} The range for the next match, or\n     *      null if there is no match.\n     */\n    function _getNextMatch(editor, searchBackwards, pos, wrap) {\n        var cm = editor._codeMirror;\n        var state = getSearchState(cm);\n        var cursor = getSearchCursor(cm, state, pos || editor.getCursorPos(false, searchBackwards ? \"start\" : \"end\"));\n\n        state.lastMatch = cursor.find(searchBackwards);\n        if (!state.lastMatch && wrap !== false) {\n            // If no result found before hitting edge of file, try wrapping around\n            cursor = getSearchCursor(cm, state, searchBackwards ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});\n            state.lastMatch = cursor.find(searchBackwards);\n        }\n        if (!state.lastMatch) {\n            // No result found, period: clear selection & bail\n            cm.setCursor(editor.getCursorPos());  // collapses selection, keeping cursor in place to avoid scrolling\n            return null;\n        }\n\n        return {start: cursor.from(), end: cursor.to()};\n    }\n\n    /**\n     * @private\n     * Sets the given selections in the editor and applies some heuristics to determine whether and how we should\n     * center the primary selection.\n     *\n     * @param {!Editor} editor The editor to search in\n     * @param {!Array<{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed: boolean}>} selections\n     *      The selections to set. Must not be empty.\n     * @param {boolean} center Whether to try to center the primary selection vertically on the screen. If false, the selection will still be scrolled\n     *      into view if it's offscreen, but will not be centered.\n     * @param {boolean=} preferNoScroll If center is true, whether to avoid scrolling if the hit is in the top half of the screen. Default false.\n     */\n    function _selectAndScrollTo(editor, selections, center, preferNoScroll) {\n        var primarySelection = _.find(selections, function (sel) { return sel.primary; }) || _.last(selections),\n            resultVisible = editor.isLineVisible(primarySelection.start.line),\n            centerOptions = Editor.BOUNDARY_CHECK_NORMAL;\n\n        if (preferNoScroll && resultVisible) {\n            // no need to scroll if the line with the match is in view\n            centerOptions = Editor.BOUNDARY_IGNORE_TOP;\n        }\n\n        // Make sure the primary selection is fully visible on screen.\n        var primary = _.find(selections, function (sel) {\n            return sel.primary;\n        });\n        if (!primary) {\n            primary = _.last(selections);\n        }\n\n        editor._codeMirror.scrollIntoView({from: primary.start, to: primary.end});\n        editor.setSelections(selections, center, centerOptions);\n    }\n\n    /**\n     * Returns the range of the word surrounding the given editor position. Similar to getWordAt() from CodeMirror.\n     *\n     * @param {!Editor} editor The editor to search in\n     * @param {!{line: number, ch: number}} pos The position to find a word at.\n     * @return {{start:{line: number, ch: number}, end:{line:number, ch:number}, text:string}} The range and content of the found word. If\n     *     there is no word, start will equal end and the text will be the empty string.\n     */\n    function _getWordAt(editor, pos) {\n        var cm = editor._codeMirror,\n            start = pos.ch,\n            end = start,\n            line = cm.getLine(pos.line);\n        while (start && CodeMirror.isWordChar(line.charAt(start - 1))) {\n            --start;\n        }\n        while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) {\n            ++end;\n        }\n        return {start: {line: pos.line, ch: start}, end: {line: pos.line, ch: end}, text: line.slice(start, end)};\n    }\n\n    /**\n     * @private\n     * Helper function. Returns true if two selections are equal.\n     * @param {!{start: {line: number, ch: number}, end: {line: number, ch: number}}} sel1 The first selection to compare\n     * @param {!{start: {line: number, ch: number}, end: {line: number, ch: number}}} sel2 The second selection to compare\n     * @return {boolean} true if the selections are equal\n     */\n    function _selEq(sel1, sel2) {\n        return (CodeMirror.cmpPos(sel1.start, sel2.start) === 0 && CodeMirror.cmpPos(sel1.end, sel2.end) === 0);\n    }\n\n    /**\n     * Expands each empty range in the selection to the nearest word boundaries. Then, if the primary selection\n     * was already a range (even a non-word range), adds the next instance of the contents of that range as a selection.\n     *\n     * @param {!Editor} editor The editor to search in\n     * @param {boolean=} removePrimary Whether to remove the current primary selection in addition to adding the\n     * next one. If true, we add the next match even if the current primary selection is a cursor (we expand it\n     * first to determine what to match).\n     */\n    function _expandWordAndAddNextToSelection(editor, removePrimary) {\n        editor = editor || EditorManager.getActiveEditor();\n        if (!editor) {\n            return;\n        }\n\n        var selections = editor.getSelections(),\n            primarySel,\n            primaryIndex,\n            searchText,\n            added = false;\n\n        _.each(selections, function (sel, index) {\n            var isEmpty = (CodeMirror.cmpPos(sel.start, sel.end) === 0);\n            if (sel.primary) {\n                primarySel = sel;\n                primaryIndex = index;\n                if (!isEmpty) {\n                    searchText = editor.document.getRange(primarySel.start, primarySel.end);\n                }\n            }\n            if (isEmpty) {\n                var wordInfo = _getWordAt(editor, sel.start);\n                sel.start = wordInfo.start;\n                sel.end = wordInfo.end;\n                if (sel.primary && removePrimary) {\n                    // Get the expanded text, even though we're going to remove this selection,\n                    // since in this case we still want to select the next match.\n                    searchText = wordInfo.text;\n                }\n            }\n        });\n\n        if (searchText && searchText.length) {\n            // We store this as a query in the state so that if the user next does a \"Find Next\",\n            // it will use the same query (but throw away the existing selection).\n            var state = getSearchState(editor._codeMirror);\n            setQueryInfo(state, { query: searchText, isCaseSensitive: false, isRegexp: false });\n\n            // Skip over matches that are already in the selection.\n            var searchStart = primarySel.end,\n                nextMatch,\n                isInSelection;\n            do {\n                nextMatch = _getNextMatch(editor, false, searchStart);\n                if (nextMatch) {\n                    // This is a little silly, but if we just stick the equivalence test function in here\n                    // JSLint complains about creating a function in a loop, even though it's safe in this case.\n                    isInSelection = _.find(selections, _.partial(_selEq, nextMatch));\n                    searchStart = nextMatch.end;\n\n                    // If we've gone all the way around, then all instances must have been selected already.\n                    if (CodeMirror.cmpPos(searchStart, primarySel.end) === 0) {\n                        nextMatch = null;\n                        break;\n                    }\n                }\n            } while (nextMatch && isInSelection);\n\n            if (nextMatch) {\n                nextMatch.primary = true;\n                selections.push(nextMatch);\n                added = true;\n            }\n        }\n\n        if (removePrimary) {\n            selections.splice(primaryIndex, 1);\n        }\n\n        if (added) {\n            // Center the new match, but avoid scrolling to matches that are already on screen.\n            _selectAndScrollTo(editor, selections, true, true);\n        } else {\n            // If all we did was expand some selections, don't center anything.\n            _selectAndScrollTo(editor, selections, false);\n        }\n    }\n\n    function _skipCurrentMatch(editor) {\n        return _expandWordAndAddNextToSelection(editor, true);\n    }\n\n    /**\n     * Takes the primary selection, expands it to a word range if necessary, then sets the selection to\n     * include all instances of that range. Removes all other selections. Does nothing if the selection\n     * is not a range after expansion.\n     */\n    function _findAllAndSelect(editor) {\n        editor = editor || EditorManager.getActiveEditor();\n        if (!editor) {\n            return;\n        }\n\n        var sel = editor.getSelection(),\n            newSelections = [];\n        if (CodeMirror.cmpPos(sel.start, sel.end) === 0) {\n            sel = _getWordAt(editor, sel.start);\n        }\n        if (CodeMirror.cmpPos(sel.start, sel.end) !== 0) {\n            var searchStart = {line: 0, ch: 0},\n                state = getSearchState(editor._codeMirror),\n                nextMatch;\n            setQueryInfo(state, { query: editor.document.getRange(sel.start, sel.end), isCaseSensitive: false, isRegexp: false });\n\n            while ((nextMatch = _getNextMatch(editor, false, searchStart, false)) !== null) {\n                if (_selEq(sel, nextMatch)) {\n                    nextMatch.primary = true;\n                }\n                newSelections.push(nextMatch);\n                searchStart = nextMatch.end;\n            }\n\n            // This should find at least the original selection, but just in case...\n            if (newSelections.length) {\n                // Don't change the scroll position.\n                editor.setSelections(newSelections, false);\n            }\n        }\n    }\n\n    /** Removes the current-match highlight, leaving all matches marked in the generic highlight style */\n    function clearCurrentMatchHighlight(cm, state) {\n        if (state.markedCurrent) {\n            state.markedCurrent.clear();\n            ScrollTrackMarkers.markCurrent(-1);\n        }\n    }\n\n    /**\n     * Selects the next match (or prev match, if searchBackwards==true) starting from either the current position\n     * (if pos unspecified) or the given position (if pos specified explicitly). The starting position\n     * need not be an existing match. If a new match is found, sets to state.lastMatch either the regex\n     * match result, or simply true for a plain-string match. If no match found, sets state.lastMatch\n     * to false.\n     * @param {!Editor} editor\n     * @param {?boolean} searchBackwards\n     * @param {?boolean} preferNoScroll\n     * @param {?Pos} pos\n     */\n    function findNext(editor, searchBackwards, preferNoScroll, pos) {\n        var cm = editor._codeMirror;\n        cm.operation(function () {\n            var state = getSearchState(cm);\n            clearCurrentMatchHighlight(cm, state);\n\n            var nextMatch = _getNextMatch(editor, searchBackwards, pos);\n            if (nextMatch) {\n                // Update match index indicators - only possible if we have resultSet saved (missing if FIND_MAX_FILE_SIZE threshold hit)\n                if (state.resultSet.length) {\n                    _updateFindBarWithMatchInfo(state,\n                                                {from: nextMatch.start, to: nextMatch.end}, searchBackwards);\n                    // Update current-tickmark indicator - only if highlighting enabled (disabled if FIND_HIGHLIGHT_MAX threshold hit)\n                    if (state.marked.length) {\n                        ScrollTrackMarkers.markCurrent(state.matchIndex);  // _updateFindBarWithMatchInfo() has updated this index\n                    }\n                }\n\n                _selectAndScrollTo(editor, [nextMatch], true, preferNoScroll);\n\n                // Only mark text with \"current match\" highlight if search bar still open\n                if (findBar && !findBar.isClosed()) {\n                    // If highlighting disabled, apply both match AND current-match styles for correct appearance\n                    var curentMatchClassName = state.marked.length ? \"searching-current-match\" : \"CodeMirror-searching searching-current-match\";\n                    state.markedCurrent = cm.markText(nextMatch.start, nextMatch.end,\n                         { className: curentMatchClassName, startStyle: \"searching-first\", endStyle: \"searching-last\" });\n                }\n            } else {\n                cm.setCursor(editor.getCursorPos());  // collapses selection, keeping cursor in place to avoid scrolling\n                // (nothing more to do: previous highlights already cleared above)\n            }\n        });\n    }\n\n    /** Clears all match highlights, including the current match */\n    function clearHighlights(cm, state) {\n        cm.operation(function () {\n            state.marked.forEach(function (markedRange) {\n                markedRange.clear();\n            });\n            clearCurrentMatchHighlight(cm, state);\n        });\n        state.marked.length = 0;\n        state.markedCurrent = null;\n\n        ScrollTrackMarkers.clear();\n\n        state.resultSet = [];\n        state.matchIndex = -1;\n    }\n\n    function clearSearch(cm) {\n        cm.operation(function () {\n            var state = getSearchState(cm);\n            if (!state.parsedQuery) {\n                return;\n            }\n            setQueryInfo(state, null);\n\n            clearHighlights(cm, state);\n        });\n    }\n\n    function toggleHighlighting(editor, enabled) {\n        // Temporarily change selection color to improve highlighting - see LESS code for details\n        if (enabled) {\n            $(editor.getRootElement()).addClass(\"find-highlighting\");\n        } else {\n            $(editor.getRootElement()).removeClass(\"find-highlighting\");\n        }\n\n        ScrollTrackMarkers.setVisible(editor, enabled);\n    }\n\n    /**\n     * Called each time the search query changes or document is modified (via Replace). Updates\n     * the match count, match highlights and scrollbar tickmarks. Does not change the cursor pos.\n     */\n    function updateResultSet(editor) {\n        var cm = editor._codeMirror,\n            state = getSearchState(cm);\n\n        function indicateHasMatches(numResults) {\n            // Make the field red if it's not blank and it has no matches (which also covers invalid regexes)\n            findBar.showNoResults(!state.foundAny && findBar.getQueryInfo().query);\n\n            // Navigation buttons enabled if we have a query and more than one match\n            findBar.enableNavigation(state.foundAny && numResults > 1);\n            findBar.enableReplace(state.foundAny);\n        }\n\n        cm.operation(function () {\n            // Clear old highlights\n            if (state.marked) {\n                clearHighlights(cm, state);\n            }\n\n            if (!state.parsedQuery) {\n                // Search field is empty - no results\n                findBar.showFindCount(\"\");\n                state.foundAny = false;\n                indicateHasMatches();\n                return;\n            }\n\n            // Find *all* matches, searching from start of document\n            // (Except on huge documents, where this is too expensive)\n            var cursor = getSearchCursor(cm, state);\n            if (cm.getValue().length <= FIND_MAX_FILE_SIZE) {\n                // FUTURE: if last query was prefix of this one, could optimize by filtering last result set\n                state.resultSet = [];\n                while (cursor.findNext()) {\n                    state.resultSet.push(cursor.pos);  // pos is unique obj per search result\n                }\n\n                // Highlight all matches if there aren't too many\n                if (state.resultSet.length <= FIND_HIGHLIGHT_MAX) {\n                    toggleHighlighting(editor, true);\n\n                    state.resultSet.forEach(function (result) {\n                        state.marked.push(cm.markText(result.from, result.to,\n                             { className: \"CodeMirror-searching\", startStyle: \"searching-first\", endStyle: \"searching-last\" }));\n                    });\n                    var scrollTrackPositions = state.resultSet.map(function (result) {\n                        return result.from;\n                    });\n\n                    ScrollTrackMarkers.addTickmarks(editor, scrollTrackPositions);\n                }\n\n                // Here we only update find bar with no result. In the case of a match\n                // a findNext() call is guaranteed to be followed by this function call,\n                // and findNext() in turn calls _updateFindBarWithMatchInfo() to show the\n                // match index.\n                if (state.resultSet.length === 0) {\n                    findBar.showFindCount(Strings.FIND_NO_RESULTS);\n                }\n\n                state.foundAny = (state.resultSet.length > 0);\n                indicateHasMatches(state.resultSet.length);\n\n            } else {\n                // On huge documents, just look for first match & then stop\n                findBar.showFindCount(\"\");\n                state.foundAny = cursor.findNext();\n                indicateHasMatches();\n            }\n        });\n    }\n\n    /**\n     * Called each time the search query field changes. Updates state.parsedQuery (parsedQuery will be falsy if the field\n     * was blank OR contained a regexp with invalid syntax). Then calls updateResultSet(), and then jumps to\n     * the first matching result, starting from the original cursor position.\n     * @param {!Editor} editor The editor we're searching in.\n     * @param {Object} state The current query state.\n     * @param {boolean} initial Whether this is the initial population of the query when the search bar opens.\n     *     In that case, we don't want to change the selection unnecessarily.\n     */\n    function handleQueryChange(editor, state, initial) {\n        setQueryInfo(state, findBar.getQueryInfo());\n        updateResultSet(editor);\n\n        if (state.parsedQuery) {\n            // 3rd arg: prefer to avoid scrolling if result is anywhere within view, since in this case user\n            // is in the middle of typing, not navigating explicitly; viewport jumping would be distracting.\n            findNext(editor, false, true, state.searchStartPos);\n        } else if (!initial) {\n            // Blank or invalid query: just jump back to initial pos\n            editor._codeMirror.setCursor(state.searchStartPos);\n        }\n\n        editor.lastParsedQuery = state.parsedQuery;\n    }\n\n\n    /**\n     * Creates a Find bar for the current search session.\n     * @param {!Editor} editor\n     * @param {boolean} replace Whether to show the Replace UI; default false\n     */\n    function openSearchBar(editor, replace) {\n        var cm = editor._codeMirror,\n            state = getSearchState(cm);\n\n        // Use the selection start as the searchStartPos. This way if you\n        // start with a pre-populated search and enter an additional character,\n        // it will extend the initial selection instead of jumping to the next\n        // occurrence.\n        state.searchStartPos = editor.getCursorPos(false, \"start\");\n\n        // Prepopulate the search field\n        var initialQuery = FindBar.getInitialQuery(findBar, editor);\n        if (initialQuery.query === \"\" && editor.lastParsedQuery !== \"\") {\n            initialQuery.query = editor.lastParsedQuery;\n        }\n\n        // Close our previous find bar, if any. (The open() of the new findBar will\n        // take care of closing any other find bar instances.)\n        if (findBar) {\n            findBar.close();\n        }\n\n        // Create the search bar UI (closing any previous find bar in the process)\n        findBar = new FindBar({\n            multifile: false,\n            replace: replace,\n            initialQuery: initialQuery.query,\n            initialReplaceText: initialQuery.replaceText,\n            queryPlaceholder: Strings.FIND_QUERY_PLACEHOLDER\n        });\n        findBar.open();\n\n        findBar\n            .on(\"queryChange.FindReplace\", function (e) {\n                handleQueryChange(editor, state);\n            })\n            .on(\"doFind.FindReplace\", function (e, searchBackwards) {\n                findNext(editor, searchBackwards);\n            })\n            .on(\"close.FindReplace\", function (e) {\n                editor.lastParsedQuery = state.parsedQuery;\n                // Clear highlights but leave search state in place so Find Next/Previous work after closing\n                clearHighlights(cm, state);\n\n                // Dispose highlighting UI (important to restore normal selection color as soon as focus goes back to the editor)\n                toggleHighlighting(editor, false);\n\n                findBar.off(\".FindReplace\");\n                findBar = null;\n            });\n\n        handleQueryChange(editor, state, true);\n    }\n\n    /**\n     * If no search pending, opens the Find dialog. If search bar already open, moves to\n     * next/prev result (depending on 'searchBackwards')\n     */\n    function doSearch(editor, searchBackwards) {\n        var state = getSearchState(editor._codeMirror);\n\n        if (state.parsedQuery) {\n            findNext(editor, searchBackwards);\n        } else {\n            openSearchBar(editor, false);\n        }\n    }\n\n\n    /**\n     * @private\n     * When the user switches documents (or closes the last document), ensure that the find bar\n     * closes, and also close the Replace All panel.\n     */\n    function _handleFileChanged() {\n        if (findBar) {\n            findBar.close();\n        }\n    }\n\n    function doReplace(editor, all) {\n        var cm = editor._codeMirror,\n            state = getSearchState(cm),\n            replaceText = findBar.getReplaceText();\n\n        // Do not replace if editor is set to read only\n        if (cm.options.readOnly) {\n            return;\n        }\n\n        if (all === null) {\n            findBar.close();\n            FindInFilesUI.searchAndReplaceResults(state.queryInfo, editor.document.file, null, replaceText);\n        } else if (all) {\n            findBar.close();\n            // Delegate to Replace in Files.\n            FindInFilesUI.searchAndShowResults(state.queryInfo, editor.document.file, null, replaceText);\n        } else {\n            cm.replaceSelection(state.queryInfo.isRegexp ? FindUtils.parseDollars(replaceText, state.lastMatch) : replaceText);\n\n            updateResultSet(editor);  // we updated the text, so result count & tickmarks must be refreshed\n\n            findNext(editor);\n            if (!state.lastMatch) {\n                // No more matches, so destroy find bar\n                findBar.close();\n            }\n        }\n    }\n\n    function replace(editor) {\n        // If Replace bar already open, treat the shortcut as a hotkey for the Replace button\n        if (findBar && findBar.getOptions().replace && findBar.isReplaceEnabled()) {\n            doReplace(editor, false);\n            return;\n        }\n\n        openSearchBar(editor, true);\n\n        findBar\n            .on(\"doReplace.FindReplace\", function (e) {\n                doReplace(editor, false);\n            })\n            .on(\"doReplaceBatch.FindReplace\", function (e) {\n                doReplace(editor, true);\n            })\n            .on(\"doReplaceAll.FindReplace\", function (e) {\n                doReplace(editor, null);\n            });\n    }\n\n    function _launchFind() {\n        var editor = EditorManager.getActiveEditor();\n\n        if (editor) {\n            // Create a new instance of the search bar UI\n            clearSearch(editor._codeMirror);\n            doSearch(editor, false);\n        }\n    }\n\n    function _findNext() {\n        var editor = EditorManager.getActiveEditor();\n        if (editor) {\n            doSearch(editor);\n        }\n    }\n\n    function _findPrevious() {\n        var editor = EditorManager.getActiveEditor();\n        if (editor) {\n            doSearch(editor, true);\n        }\n    }\n\n    function _replace() {\n        var editor = EditorManager.getActiveEditor();\n        if (editor) {\n            replace(editor);\n        }\n    }\n\n    MainViewManager.on(\"currentFileChange\", _handleFileChanged);\n\n    CommandManager.register(Strings.CMD_FIND,                   Commands.CMD_FIND,                  _launchFind);\n    CommandManager.register(Strings.CMD_FIND_NEXT,              Commands.CMD_FIND_NEXT,             _findNext);\n    CommandManager.register(Strings.CMD_REPLACE,                Commands.CMD_REPLACE,               _replace);\n    CommandManager.register(Strings.CMD_FIND_PREVIOUS,          Commands.CMD_FIND_PREVIOUS,         _findPrevious);\n    CommandManager.register(Strings.CMD_FIND_ALL_AND_SELECT,    Commands.CMD_FIND_ALL_AND_SELECT,   _findAllAndSelect);\n    CommandManager.register(Strings.CMD_ADD_NEXT_MATCH,         Commands.CMD_ADD_NEXT_MATCH,        _expandWordAndAddNextToSelection);\n    CommandManager.register(Strings.CMD_SKIP_CURRENT_MATCH,     Commands.CMD_SKIP_CURRENT_MATCH,    _skipCurrentMatch);\n\n    // For unit testing\n    exports._getWordAt                       = _getWordAt;\n    exports._expandWordAndAddNextToSelection = _expandWordAndAddNextToSelection;\n    exports._findAllAndSelect                = _findAllAndSelect;\n});\n"
  },
  {
    "path": "src/search/FindUtils.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Async               = require(\"utils/Async\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        _                   = require(\"thirdparty/lodash\");\n\n    var nodeSearchDisabled = false,\n        instantSearchDisabled = false,\n        indexingInProgress = false,\n        nodeSearchCount = 0,\n        collapseResults = false;\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // define preferences for find in files\n    PreferencesManager.definePreference(\"findInFiles.nodeSearch\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_FIND_IN_FILES_NODE\n    });\n    PreferencesManager.definePreference(\"findInFiles.instantSearch\", \"boolean\", true, {\n        description: Strings.DESCRIPTION_FIND_IN_FILES_INSTANT\n    });\n\n    /**\n     * returns true if the used disabled node based search in his preferences\n     * @return {boolean}\n     */\n    function _prefNodeSearchDisabled() {\n        return !PreferencesManager.get(\"findInFiles.nodeSearch\");\n    }\n\n    /**\n     * returns true if the used instant search in his preferences\n     * @return {boolean}\n     */\n    function _prefInstantSearchDisabled() {\n        return !PreferencesManager.get(\"findInFiles.instantSearch\");\n    }\n\n    /**\n     * Given a replace string that contains $-expressions, replace them with data from the given\n     * regexp match info.\n     * NOTE: we can't just use the ordinary replace() function here because the string has been\n     * extracted from the original text and so might be missing some context that the regexp matched.\n     * @param {string} replaceWith The string containing the $-expressions.\n     * @param {Object} match The match data from the regexp.\n     * @return {string} The replace text with the $-expressions substituted.\n     */\n    function parseDollars(replaceWith, match) {\n        replaceWith = replaceWith.replace(/(\\$+)(\\d{1,2}|&)/g, function (whole, dollars, index) {\n            if (dollars.length % 2 === 1) { // make sure dollar signs don't escape themselves (like $$1, $$$$&)\n                if (index === \"&\") { // handle $&\n                    // slice the first dollar (but leave any others to get unescaped below) and return the\n                    // whole match\n                    return dollars.substr(1) + (match[0] || \"\");\n                } else {\n                    // now we're sure index is an integer, so we can parse it\n                    var parsedIndex = parseInt(index, 10);\n                    if (parsedIndex !== 0) { // handle $n or $nn, but don't handle $0 or $00\n                        // slice the first dollar (but leave any others to get unescaped below) and return the\n                        // the corresponding match\n                        return dollars.substr(1) + (match[parsedIndex] || \"\");\n                    }\n                }\n            }\n            // this code gets called if the dollar signs escape themselves or if $0/$00 (not handled) was present\n            return whole; // return everything to get handled below\n        });\n        // replace escaped dollar signs (i.e. $$, $$$$, ...) with single ones (unescaping)\n        replaceWith = replaceWith.replace(/\\$\\$/g, \"$\");\n        return replaceWith;\n    }\n\n    /**\n     * Does a set of replacements in a single document in memory.\n     * @param {!Document} doc The document to do the replacements in.\n     * @param {Object} matchInfo The match info for this file, as returned by `_addSearchMatches()`. Might be mutated.\n     * @param {string} replaceText The text to replace each result with.\n     * @param {boolean=} isRegexp Whether the original query was a regexp.\n     * @return {$.Promise} A promise that's resolved when the replacement is finished or rejected with an error if there were one or more errors.\n     */\n    function _doReplaceInDocument(doc, matchInfo, replaceText, isRegexp) {\n        // Double-check that the open document's timestamp matches the one we recorded. This\n        // should normally never go out of sync, because if it did we wouldn't start the\n        // replace in the first place (due to the fact that we immediately close the search\n        // results panel whenever we detect a filesystem change that affects the results),\n        // but we want to double-check in case we don't happen to get the change in time.\n        // This will *not* handle cases where the document has been edited in memory since\n        // the matchInfo was generated.\n        if (doc.diskTimestamp.getTime() !== matchInfo.timestamp.getTime()) {\n            return new $.Deferred().reject(exports.ERROR_FILE_CHANGED).promise();\n        }\n\n        // Do the replacements in reverse document order so the offsets continue to be correct.\n        doc.batchOperation(function () {\n            matchInfo.matches.reverse().forEach(function (match) {\n                if (match.isChecked) {\n                    doc.replaceRange(isRegexp ? parseDollars(replaceText, match.result) : replaceText, match.start, match.end);\n                }\n            });\n        });\n\n        return new $.Deferred().resolve().promise();\n    }\n\n    /**\n     * Does a set of replacements in a single file on disk.\n     * @param {string} fullPath The full path to the file.\n     * @param {Object} matchInfo The match info for this file, as returned by `_addSearchMatches()`.\n     * @param {string} replaceText The text to replace each result with.\n     * @param {boolean=} isRegexp Whether the original query was a regexp.\n     * @return {$.Promise} A promise that's resolved when the replacement is finished or rejected with an error if there were one or more errors.\n     */\n    function _doReplaceOnDisk(fullPath, matchInfo, replaceText, isRegexp) {\n        var file = FileSystem.getFileForPath(fullPath);\n        return DocumentManager.getDocumentText(file, true).then(function (contents, timestamp, lineEndings) {\n            if (timestamp.getTime() !== matchInfo.timestamp.getTime()) {\n                // Return a promise that we'll reject immediately. (We can't just return the\n                // error since this is the success handler.)\n                return new $.Deferred().reject(exports.ERROR_FILE_CHANGED).promise();\n            }\n\n            // Note that this assumes that the matches are sorted.\n            // TODO: is there a more efficient way to do this in a large string?\n            var result = [],\n                lastIndex = 0;\n            matchInfo.matches.forEach(function (match) {\n                if (match.isChecked) {\n                    result.push(contents.slice(lastIndex, match.startOffset));\n                    result.push(isRegexp ? parseDollars(replaceText, match.result) : replaceText);\n                    lastIndex = match.endOffset;\n                }\n            });\n            result.push(contents.slice(lastIndex));\n\n            var newContents = result.join(\"\");\n            // TODO: duplicated logic from Document - should refactor this?\n            if (lineEndings === FileUtils.LINE_ENDINGS_CRLF) {\n                newContents = newContents.replace(/\\n/g, \"\\r\\n\");\n            }\n\n            return Async.promisify(file, \"write\", newContents);\n        });\n    }\n\n    /**\n     * Does a set of replacements in a single file. If the file is already open in a Document in memory,\n     * will do the replacement there, otherwise does it directly on disk.\n     * @param {string} fullPath The full path to the file.\n     * @param {Object} matchInfo The match info for this file, as returned by `_addSearchMatches()`.\n     * @param {string} replaceText The text to replace each result with.\n     * @param {Object=} options An options object:\n     *      forceFilesOpen: boolean - Whether to open the file in an editor and do replacements there rather than doing the\n     *          replacements on disk. Note that even if this is false, files that are already open in editors will have replacements\n     *          done in memory.\n     *      isRegexp: boolean - Whether the original query was a regexp. If true, $-substitution is performed on the replaceText.\n     * @return {$.Promise} A promise that's resolved when the replacement is finished or rejected with an error if there were one or more errors.\n     */\n    function _doReplaceInOneFile(fullPath, matchInfo, replaceText, options) {\n        var doc = DocumentManager.getOpenDocumentForPath(fullPath);\n        options = options || {};\n        // If we're forcing files open, or if the document is in the working set but not actually open\n        // yet, we want to open the file and do the replacement in memory.\n        if (!doc && (options.forceFilesOpen || MainViewManager.findInWorkingSet(MainViewManager.ALL_PANES, fullPath) !== -1)) {\n            return DocumentManager.getDocumentForPath(fullPath).then(function (newDoc) {\n                return _doReplaceInDocument(newDoc, matchInfo, replaceText, options.isRegexp);\n            });\n        } else if (doc) {\n            return _doReplaceInDocument(doc, matchInfo, replaceText, options.isRegexp);\n        } else {\n            return _doReplaceOnDisk(fullPath, matchInfo, replaceText, options.isRegexp);\n        }\n    }\n\n    /**\n     * @private\n     * Returns true if a search result has any checked matches.\n     */\n    function hasCheckedMatches(result) {\n        return result.matches.some(function (match) { return match.isChecked; });\n    }\n\n    /**\n     * Given a set of search results, replaces them with the given replaceText, either on disk or in memory.\n     * Checks timestamps to ensure replacements are not performed in files that have changed on disk since\n     * the original search results were generated. However, does *not* check whether edits have been performed\n     * in in-memory documents since the search; it's up to the caller to guarantee this hasn't happened.\n     * (When called from the standard Find in Files UI, SearchResultsView guarantees this. If called headlessly,\n     * the caller needs to track changes.)\n     *\n     * Replacements in documents that are already open in memory at the start of the replacement are guaranteed to\n     * happen synchronously; replacements in files on disk will return an error if the on-disk file changes between\n     * the time performReplacements() is called and the time the replacement actually happens.\n     *\n     * @param {Object.<fullPath: string, {matches: Array.<{start: {line:number,ch:number}, end: {line:number,ch:number}, startOffset: number, endOffset: number, line: string}>, collapsed: boolean}>} results\n     *      The list of results to replace, as returned from _doSearch..\n     * @param {string} replaceText The text to replace each result with.\n     * @param {?Object} options An options object:\n     *      forceFilesOpen: boolean - Whether to open all files in editors and do replacements there rather than doing the\n     *          replacements on disk. Note that even if this is false, files that are already open in editors will have replacements\n     *          done in memory.\n     *      isRegexp: boolean - Whether the original query was a regexp. If true, $-substitution is performed on the replaceText.\n     * @return {$.Promise} A promise that's resolved when the replacement is finished or rejected with an array of errors\n     *      if there were one or more errors. Each individual item in the array will be a {item: string, error: string} object,\n     *      where item is the full path to the file that could not be updated, and error is either a FileSystem error or one\n     *      of the `FindUtils.ERROR_*` constants.\n     */\n    function performReplacements(results, replaceText, options) {\n        return Async.doInParallel_aggregateErrors(Object.keys(results), function (fullPath) {\n            return _doReplaceInOneFile(fullPath, results[fullPath], replaceText, options);\n        }).done(function () {\n            if (options && options.forceFilesOpen) {\n                // If the currently selected document wasn't modified by the search, or there is no open document,\n                // then open the first modified document.\n                var doc = DocumentManager.getCurrentDocument();\n                if (!doc ||\n                        !results[doc.file.fullPath] ||\n                        !hasCheckedMatches(results[doc.file.fullPath])) {\n                    // Figure out the first modified document. This logic is slightly different from\n                    // SearchResultsView._getSortedFiles() because it doesn't sort the currently open file to\n                    // the top. But if the currently open file were in the search results, we wouldn't be\n                    // doing this anyway.\n                    var sortedPaths = Object.keys(results).sort(FileUtils.comparePaths),\n                        firstPath = _.find(sortedPaths, function (path) {\n                            return hasCheckedMatches(results[path]);\n                        });\n\n                    if (firstPath) {\n                        var newDoc = DocumentManager.getOpenDocumentForPath(firstPath);\n                        // newDoc might be null if the replacement failed.\n                        if (newDoc) {\n                            // @todo change the `_edit` call to this:\n                            //\n                            ///    CommandManager.execute(Commands.FILE_OPEN, {fullPath: firstPath});\n                            //\n                            // The problem with doing that is that the promise returned by this\n                            // function has already been resolved by `Async.doInParallel()` and\n                            // `CommandManager.execute` is an asynchronous operation.\n                            // An asynchronous open can't be waited on (since the promise has been\n                            //  resolved already) so use the synchronous version so that the next `done`\n                            //  handler is blocked until the open completes\n                            MainViewManager._edit(MainViewManager.ACTIVE_PANE, newDoc);\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n    /**\n     * Returns label text to indicate the search scope. Already HTML-escaped.\n     * @param {?Entry} scope\n     * @return {string}\n     */\n    function labelForScope(scope) {\n        if (scope) {\n            return StringUtils.format(\n                Strings.FIND_IN_FILES_SCOPED,\n                StringUtils.breakableUrl(\n                    ProjectManager.makeProjectRelativeIfPossible(scope.fullPath)\n                )\n            );\n        } else {\n            return Strings.FIND_IN_FILES_NO_SCOPE;\n        }\n    }\n\n    /**\n     * Parses the given query into a regexp, and returns whether it was valid or not.\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo\n     * @return {{queryExpr: RegExp, valid: boolean, empty: boolean, error: string}}\n     *      queryExpr - the regexp representing the query\n     *      valid - set to true if query is a nonempty string or a valid regexp.\n     *      empty - set to true if query was empty.\n     *      error - set to an error string if valid is false and query is nonempty.\n     */\n    function parseQueryInfo(queryInfo) {\n        var queryExpr;\n\n        if (!queryInfo || !queryInfo.query) {\n            return {empty: true};\n        }\n\n        // For now, treat all matches as multiline (i.e. ^/$ match on every line, not the whole\n        // document). This is consistent with how single-file find works. Eventually we should add\n        // an option for this.\n        var flags = \"gm\";\n        if (!queryInfo.isCaseSensitive) {\n            flags += \"i\";\n        }\n\n        // Is it a (non-blank) regex?\n        if (queryInfo.isRegexp) {\n            try {\n                queryExpr = new RegExp(queryInfo.query, flags);\n            } catch (e) {\n                return {valid: false, error: e.message};\n            }\n        } else {\n            // Query is a plain string. Turn it into a regexp\n            queryExpr = new RegExp(StringUtils.regexEscape(queryInfo.query), flags);\n        }\n        return {valid: true, queryExpr: queryExpr};\n    }\n\n     /**\n     * Prioritizes the open file and then the working set files to the starting of the list of files\n     * @param {Array.<*>} files An array of file paths or file objects to sort\n     * @param {?string} firstFile If specified, the path to the file that should be sorted to the top.\n     * @return {Array.<*>}\n     */\n    function prioritizeOpenFile(files, firstFile) {\n        var workingSetFiles = MainViewManager.getWorkingSet(MainViewManager.ALL_PANES),\n            workingSetFileFound = {},\n            fileSetWithoutWorkingSet = [],\n            startingWorkingFileSet = [],\n            propertyName = \"\",\n            i = 0;\n        firstFile = firstFile || \"\";\n\n        // Create a working set path map which indicates if a file in working set is found in file list\n        for (i = 0; i < workingSetFiles.length; i++) {\n            workingSetFileFound[workingSetFiles[i].fullPath] = false;\n        }\n\n        // Remove all the working set files from the filtration list\n        fileSetWithoutWorkingSet = files.filter(function (key) {\n            if (workingSetFileFound[key] !== undefined) {\n                workingSetFileFound[key] = true;\n                return false;\n            }\n            return true;\n        });\n\n        //push in the first file\n        if (workingSetFileFound[firstFile] === true) {\n            startingWorkingFileSet.push(firstFile);\n            workingSetFileFound[firstFile] = false;\n        }\n        //push in the rest of working set files already present in file list\n        for (propertyName in workingSetFileFound) {\n            if (workingSetFileFound.hasOwnProperty(propertyName) && workingSetFileFound[propertyName]) {\n                startingWorkingFileSet.push(propertyName);\n            }\n        }\n        return startingWorkingFileSet.concat(fileSetWithoutWorkingSet);\n    }\n\n\n    /**\n     * Returns the path of the currently open file or null if there isn't one open\n     * @return {?string}\n     */\n    function getOpenFilePath() {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        return currentDoc ? currentDoc.file.fullPath : null;\n    }\n\n    /**\n     * enable/disable instant search\n     * @param {boolean} disable true to disable node based search\n     */\n    function setInstantSearchDisabled(disable) {\n        instantSearchDisabled = disable;\n    }\n\n    /**\n     * if instant search is disabled, this will return true we can only do instant search through node\n     * @return {boolean}\n     */\n    function isInstantSearchDisabled() {\n        return _prefNodeSearchDisabled() || _prefInstantSearchDisabled() || nodeSearchDisabled || instantSearchDisabled;\n    }\n\n    /**\n     * enable/disable node based search\n     * @param {boolean} disable true to disable node based search\n     */\n    function setNodeSearchDisabled(disable) {\n        if (disable) {\n            // only set disable. Enabling node earch doesnt mean we have to enable instant search.\n            setInstantSearchDisabled(disable);\n        }\n        nodeSearchDisabled = disable;\n    }\n\n    /**\n     * if node search is disabled, this will return true\n     * @return {boolean}\n     */\n    function isNodeSearchDisabled() {\n        return _prefNodeSearchDisabled() || nodeSearchDisabled;\n    }\n\n    /**\n     * check if a search is progressing in node\n     * @return {Boolean} true if search is processing in node\n     */\n    function isNodeSearchInProgress() {\n        if (nodeSearchCount === 0) {\n            return false;\n        } else {\n            return true;\n        }\n    }\n\n\n    /**\n     * Raises an event when the file filters applied to a search changes\n     */\n    function notifyFileFiltersChanged() {\n        exports.trigger(exports.SEARCH_FILE_FILTERS_CHANGED);\n    }\n\n    /**\n     * Raises an event when the search scope changes[say search in a sub drictory in the project]\n     */\n    function notifySearchScopeChanged() {\n        exports.trigger(exports.SEARCH_SCOPE_CHANGED);\n    }\n\n    /**\n     * Notifies that a node search has started so that we FindUtils can figure out\n     * if any outstanding node search requests are pendind\n     */\n    function notifyNodeSearchStarted() {\n        nodeSearchCount++;\n    }\n\n    /**\n     * Notifies that a node search has finished so that we FindUtils can figure out\n     * if any outstanding node search requests are pendind\n     */\n    function notifyNodeSearchFinished() {\n        nodeSearchCount--;\n    }\n\n    /**\n     * Notifies that a node has started indexing the files\n     */\n    function notifyIndexingStarted() {\n        indexingInProgress = true;\n        exports.trigger(exports.SEARCH_INDEXING_STARTED);\n    }\n\n    /**\n     * Notifies that a node has finished indexing the files\n     */\n    function notifyIndexingFinished() {\n        indexingInProgress = false;\n        exports.trigger(exports.SEARCH_INDEXING_FINISHED);\n    }\n\n    /**\n     * Return true if indexing is in pregress in node\n     * @return {boolean} true if files are being indexed in node\n     */\n    function isIndexingInProgress() {\n        return indexingInProgress;\n    }\n\n    /**\n     * Set if we need to collapse all results in the results pane\n     * @param {boolean} collapse true to collapse\n     */\n    function setCollapseResults(collapse) {\n        collapseResults = collapse;\n        exports.trigger(exports.SEARCH_COLLAPSE_RESULTS);\n    }\n\n    /**\n     * check if results should be collapsed\n     * @return {boolean} true if results should be collapsed\n     */\n    function isCollapsedResults() {\n        return collapseResults;\n    }\n\n    /**\n     * Returns the health data pertaining to Find in files\n     */\n    function getHealthReport() {\n        return {\n            prefNodeSearchDisabled : _prefNodeSearchDisabled(),\n            prefInstantSearchDisabled : _prefInstantSearchDisabled()\n        };\n    }\n\n    exports.parseDollars                    = parseDollars;\n    exports.hasCheckedMatches               = hasCheckedMatches;\n    exports.performReplacements             = performReplacements;\n    exports.labelForScope                   = labelForScope;\n    exports.parseQueryInfo                  = parseQueryInfo;\n    exports.prioritizeOpenFile              = prioritizeOpenFile;\n    exports.getOpenFilePath                 = getOpenFilePath;\n    exports.setNodeSearchDisabled           = setNodeSearchDisabled;\n    exports.isNodeSearchDisabled            = isNodeSearchDisabled;\n    exports.setInstantSearchDisabled        = setInstantSearchDisabled;\n    exports.isInstantSearchDisabled         = isInstantSearchDisabled;\n    exports.isNodeSearchInProgress          = isNodeSearchInProgress;\n    exports.isIndexingInProgress            = isIndexingInProgress;\n    exports.setCollapseResults              = setCollapseResults;\n    exports.isCollapsedResults              = isCollapsedResults;\n    exports.getHealthReport                 = getHealthReport;\n    exports.ERROR_FILE_CHANGED              = \"fileChanged\";\n\n    // event notification functions\n    exports.notifyFileFiltersChanged        = notifyFileFiltersChanged;\n    exports.notifySearchScopeChanged        = notifySearchScopeChanged;\n    exports.notifyNodeSearchStarted         = notifyNodeSearchStarted;\n    exports.notifyNodeSearchFinished        = notifyNodeSearchFinished;\n    exports.notifyIndexingStarted           = notifyIndexingStarted;\n    exports.notifyIndexingFinished          = notifyIndexingFinished;\n\n    // events raised by FindUtils\n    exports.SEARCH_FILE_FILTERS_CHANGED              = \"fileFiltersChanged\";\n    exports.SEARCH_SCOPE_CHANGED                     = \"searchScopeChanged\";\n    exports.SEARCH_INDEXING_STARTED                  = \"searchIndexingStarted\";\n    exports.SEARCH_INDEXING_FINISHED                 = \"searchIndexingFinished\";\n    exports.SEARCH_COLLAPSE_RESULTS                  = \"searchCollapseResults\";\n});\n"
  },
  {
    "path": "src/search/QuickOpen.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: QuickOpen*/\n\n/*\n * Displays a search bar where the user can quickly navigate to a different file by searching file names in\n * the project, and/or jump to a line number. Providers can plug in to offer additional search modes.\n */\n\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        MainViewFactory     = require(\"view/MainViewFactory\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Commands            = require(\"command/Commands\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        LanguageManager     = require(\"language/LanguageManager\"),\n        ModalBar            = require(\"widgets/ModalBar\").ModalBar,\n        QuickSearchField    = require(\"search/QuickSearchField\").QuickSearchField,\n        StringMatch         = require(\"utils/StringMatch\"),\n        ProviderRegistrationHandler = require(\"features/PriorityBasedRegistration\").RegistrationHandler;\n\n    var _providerRegistrationHandler = new ProviderRegistrationHandler(),\n        _registerQuickOpenProvider = _providerRegistrationHandler.registerProvider.bind(_providerRegistrationHandler);\n\n    var SymbolKind = {\n        \"1\": \"File\",\n        \"2\": \"Module\",\n        \"3\": \"Namespace\",\n        \"4\": \"Package\",\n        \"5\": \"Class\",\n        \"6\": \"Method\",\n        \"7\": \"Property\",\n        \"8\": \"Field\",\n        \"9\": \"Constructor\",\n        \"10\": \"Enum\",\n        \"11\": \"Interface\",\n        \"12\": \"Function\",\n        \"13\": \"Variable\",\n        \"14\": \"Constant\",\n        \"15\": \"String\",\n        \"16\": \"Number\",\n        \"17\": \"Boolean\",\n        \"18\": \"Array\",\n        \"19\": \"Object\",\n        \"20\": \"Key\",\n        \"21\": \"Null\",\n        \"22\": \"EnumMember\",\n        \"23\": \"Struct\",\n        \"24\": \"Event\",\n        \"25\": \"Operator\",\n        \"26\": \"TypeParameter\"\n    };\n\n    /**\n     * The regular expression to check the cursor position\n     * @const {RegExp}\n     */\n    var CURSOR_POS_EXP = new RegExp(\":([^,]+)?(,(.+)?)?\");\n\n    /**\n     * Current plugin\n     * @type {QuickOpenPlugin}\n     */\n    var currentPlugin = null;\n\n    /** @type {Array.<File>} */\n    var fileList;\n\n    /** @type {$.Promise} */\n    var fileListPromise;\n\n    /**\n     * The currently open (or last open) QuickNavigateDialog\n     * @type {?QuickNavigateDialog}\n     */\n    var _curDialog;\n\n    /**\n     * Helper function to get the plugins based on the type of the current document.\n     * @private\n     * @returns {Array} Returns the plugings based on the languageId of the current document.\n     */\n    function _getPluginsForCurrentContext() {\n        var curDoc = DocumentManager.getCurrentDocument();\n\n        if (curDoc) {\n            var languageId = curDoc.getLanguage().getId();\n            return _providerRegistrationHandler.getProvidersForLanguageId(languageId);\n        }\n\n        return _providerRegistrationHandler.getProvidersForLanguageId(); //plugins registered for all\n    }\n\n    /**\n     * Defines API for new QuickOpen plug-ins\n     */\n    function QuickOpenPlugin(name, languageIds, done, search, match, itemFocus, itemSelect, resultsFormatter, matcherOptions, label) {\n        this.name = name;\n        this.languageIds = languageIds;\n        this.done = done;\n        this.search = search;\n        this.match = match;\n        this.itemFocus = itemFocus;\n        this.itemSelect = itemSelect;\n        this.resultsFormatter = resultsFormatter;\n        this.matcherOptions = matcherOptions;\n        this.label = label;\n    }\n\n    /**\n     * Creates and registers a new QuickOpenPlugin\n     *\n     * @param { name: string,\n     *          languageIds: !Array.<string>,\n     *          done: ?function(),\n     *          search: function(string, !StringMatch.StringMatcher):(!Array.<SearchResult|string>|$.Promise),\n     *          match: function(string):boolean,\n     *          itemFocus: ?function(?SearchResult|string, string, boolean),\n     *          itemSelect: function(?SearchResult|string, string),\n     *          resultsFormatter: ?function(SearchResult|string, string):string,\n     *          matcherOptions: ?Object,\n     *          label: ?string\n     *        } pluginDef\n     *\n     * Parameter Documentation:\n     *\n     * name - plug-in name, **must be unique**\n     * languageIds - language Ids array. Example: [\"javascript\", \"css\", \"html\"]. To allow any language, pass []. Required.\n     * done - called when quick open is complete. Plug-in should clear its internal state. Optional.\n     * search - takes a query string and a StringMatcher (the use of which is optional but can speed up your searches) and returns\n     *      an array of strings or result objects that match the query; or a Promise that resolves to such an array. Required.\n     * match - takes a query string and returns true if this plug-in wants to provide\n     *      results for this query. Required.\n     * itemFocus - performs an action when a result has been highlighted (via arrow keys, or by becoming top of the list).\n     *      Passed the highlighted search result item (as returned by search()), the current query string, and a flag that is true\n     *      if the item was highlighted explicitly (arrow keys), not implicitly (at top of list after last search()). Optional.\n     * itemSelect - performs an action when a result is chosen.\n     *      Passed the highlighted search result item (as returned by search()), and the current query string. Required.\n     * resultsFormatter - takes a query string and an item string and returns\n     *      a <LI> item to insert into the displayed search results. Optional.\n     * matcherOptions - options to pass along to the StringMatcher (see StringMatch.StringMatcher\n     *          for available options). Optional.\n     * label - if provided, the label to show before the query field. Optional.\n     *\n     * If itemFocus() makes changes to the current document or cursor/scroll position and then the user\n     * cancels Quick Open (via Esc), those changes are automatically reverted.\n     */\n    function addQuickOpenPlugin(pluginDef) {\n        var quickOpenProvider = new QuickOpenPlugin(\n                pluginDef.name,\n                pluginDef.languageIds,\n                pluginDef.done,\n                pluginDef.search,\n                pluginDef.match,\n                pluginDef.itemFocus,\n                pluginDef.itemSelect,\n                pluginDef.resultsFormatter,\n                pluginDef.matcherOptions,\n                pluginDef.label\n            ),\n            providerLanguageIds = pluginDef.languageIds.length ? pluginDef.languageIds : [\"all\"],\n            providerPriority = pluginDef.priority || 0;\n\n        _registerQuickOpenProvider(quickOpenProvider, providerLanguageIds, providerPriority);\n    }\n\n    /**\n     * QuickNavigateDialog class\n     * @constructor\n     */\n    function QuickNavigateDialog() {\n        this.$searchField = undefined; // defined when showDialog() is called\n\n        // ModalBar event handlers & callbacks\n        this._handleCloseBar           = this._handleCloseBar.bind(this);\n\n        // QuickSearchField callbacks\n        this._handleItemSelect         = this._handleItemSelect.bind(this);\n        this._handleItemHighlight      = this._handleItemHighlight.bind(this);\n        this._filterCallback           = this._filterCallback.bind(this);\n        this._resultsFormatterCallback = this._resultsFormatterCallback.bind(this);\n\n        // StringMatchers that cache in-progress query data.\n        this._filenameMatcher           = new StringMatch.StringMatcher({\n            segmentedSearch: true\n        });\n        this._matchers                  = {};\n    }\n\n    /**\n     * True if the search bar is currently open. Note that this is set to false immediately\n     * when the bar starts closing; it doesn't wait for the ModalBar animation to finish.\n     * @type {boolean}\n     */\n    QuickNavigateDialog.prototype.isOpen = false;\n\n    /**\n     * @private\n     * Handles caching of filename search information for the lifetime of a\n     * QuickNavigateDialog (a single search until the dialog is dismissed)\n     *\n     * @type {StringMatch.StringMatcher}\n     */\n    QuickNavigateDialog.prototype._filenameMatcher = null;\n\n    /**\n     * @private\n     * StringMatcher caches for each QuickOpen plugin that keep track of search\n     * information for the lifetime of a QuickNavigateDialog (a single search\n     * until the dialog is dismissed)\n     *\n     * @type {Object.<string, StringMatch.StringMatcher>}\n     */\n    QuickNavigateDialog.prototype._matchers = null;\n\n    /**\n     * @private\n     * If the dialog is closing, this will contain a deferred that is resolved\n     * when it's done closing.\n     * @type {$.Deferred}\n     */\n    QuickNavigateDialog.prototype._closeDeferred = null;\n\n\n    /**\n     * @private\n     * Remembers the current document that was displayed when showDialog() was called.\n     * @type {?string} full path\n     */\n    QuickNavigateDialog.prototype._origDocPath = null;\n\n    /**\n     * @private\n     * Remembers the selection state in origDocPath that was present when showDialog() was called. Focusing on an\n     * item can change the selection; we restore this original selection if the user presses Escape. Null if\n     * no document was open when Quick Open was invoked.\n     * @type {?Array.<{{start:{line:number, ch:number}, end:{line:number, ch:number}, primary:boolean, reversed:boolean}}>}\n     */\n    QuickNavigateDialog.prototype._origSelections = null;\n\n    /**\n     * @private\n     * Remembers the scroll position in origDocPath when showDialog() was called (see origSelection above).\n     * @type {?{x:number, y:number}}\n     */\n    QuickNavigateDialog.prototype._origScrollPos = null;\n\n    function _filenameFromPath(path, includeExtension) {\n        var end;\n        if (includeExtension) {\n            end = path.length;\n        } else {\n            end = path.lastIndexOf(\".\");\n            if (end === -1) {\n                end = path.length;\n            }\n        }\n        return path.slice(path.lastIndexOf(\"/\") + 1, end);\n    }\n\n    /**\n     * Attempts to extract a line number from the query where the line number\n     * is followed by a colon. Callers should explicitly test result with isNaN()\n     *\n     * @param {string} query string to extract line number from\n     * @return {{query: string, local: boolean, line: number, ch: number}} An object with\n     *      the extracted line and column numbers, and two additional fields: query with the original position\n     *      string and local indicating if the cursor position should be applied to the current file.\n     *      Or null if the query is invalid\n     */\n    function extractCursorPos(query) {\n        var regInfo = query.match(CURSOR_POS_EXP);\n\n        if (query.length <= 1 || !regInfo ||\n                (regInfo[1] && isNaN(regInfo[1])) ||\n                (regInfo[3] && isNaN(regInfo[3]))) {\n\n            return null;\n        }\n\n        return {\n            query:  regInfo[0],\n            local:  query[0] === \":\",\n            line:   regInfo[1] - 1 || 0,\n            ch:     regInfo[3] - 1 || 0\n        };\n    }\n\n    /**\n     * Navigates to the appropriate file and file location given the selected item\n     * and closes the dialog.\n     *\n     * Note, if selectedItem is null quick search should inspect $searchField for text\n     * that may have not matched anything in the list, but may have information\n     * for carrying out an action (e.g. go to line).\n     */\n    QuickNavigateDialog.prototype._handleItemSelect = function (selectedItem, query) {\n\n        var doClose = true,\n            self = this;\n\n        // Delegate to current plugin\n        if (currentPlugin) {\n            currentPlugin.itemSelect(selectedItem, query);\n        } else {\n            // Extract line/col number, if any\n            var cursorPos = extractCursorPos(query);\n\n            // Navigate to file and line number\n            var fullPath = selectedItem && selectedItem.fullPath;\n            if (fullPath) {\n                // We need to fix up the current editor's scroll pos before switching to the next one. But if\n                // we run the full close() now, ModalBar's animate-out won't be smooth (gets starved of cycles\n                // during creation of the new editor). So we call prepareClose() to do *only* the scroll pos\n                // fixup, and let the full close() be triggered later when the new editor takes focus.\n                doClose = false;\n                this.modalBar.prepareClose();\n                CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {fullPath: fullPath})\n                    .done(function () {\n                        if (cursorPos) {\n                            var editor = EditorManager.getCurrentFullEditor();\n                            editor.setCursorPos(cursorPos.line, cursorPos.ch, true);\n                        }\n                    })\n                    .always(function () {\n                        // Ensure we finish closing even if file failed to open, or file was already current (in\n                        // either case, we may not get a blur to trigger ModalBar to auto-close)\n                        self.close();\n                    });\n            } else if (cursorPos) {\n                EditorManager.getCurrentFullEditor().setCursorPos(cursorPos.line, cursorPos.ch, true);\n            }\n        }\n\n        if (doClose) {\n            this.close();\n            MainViewManager.focusActivePane();\n        }\n    };\n\n    /**\n     * Opens the file specified by selected item if there is no current plug-in, otherwise defers handling\n     * to the currentPlugin\n     */\n    QuickNavigateDialog.prototype._handleItemHighlight = function (selectedItem, query, explicit) {\n        if (currentPlugin && currentPlugin.itemFocus) {\n            currentPlugin.itemFocus(selectedItem, query, explicit);\n        }\n    };\n\n    /**\n     * Closes the search bar; if search bar is already closing, returns the Promise that is tracking the\n     * existing close activity.\n     * @return {$.Promise} Resolved when the search bar is entirely closed.\n     */\n    QuickNavigateDialog.prototype.close = function () {\n        if (!this.isOpen) {\n            return this.closePromise;\n        }\n\n        this.modalBar.close();  // triggers _handleCloseBar(), setting closePromise\n\n        return this.closePromise;\n    };\n\n    QuickNavigateDialog.prototype._handleCloseBar = function (event, reason, modalBarClosePromise) {\n        console.assert(!this.closePromise);\n        this.closePromise = modalBarClosePromise;\n        this.isOpen = false;\n\n        var i,\n            plugins = _getPluginsForCurrentContext();\n        for (i = 0; i < plugins.length; i++) {\n            var plugin = plugins[i].provider;\n            if (plugin.done) {\n                plugin.done();\n            }\n        }\n\n        // Close popup & ensure we ignore any still-pending result promises\n        this.searchField.destroy();\n\n        // Restore original selection / scroll pos if closed via Escape\n        if (reason === ModalBar.CLOSE_ESCAPE) {\n            // We can reset the scroll position synchronously on ModalBar's \"close\" event (before close animation\n            // completes) since ModalBar has already resized the editor and done its own scroll adjustment before\n            // this event fired - so anything we set here will override the pos that was (re)set by ModalBar.\n            var editor = EditorManager.getCurrentFullEditor();\n            if (editor && this._origSelections) {\n                editor.setSelections(this._origSelections);\n            }\n            if (editor && this._origScrollPos) {\n                editor.setScrollPos(this._origScrollPos.x, this._origScrollPos.y);\n            }\n        }\n    };\n\n\n    function _doSearchFileList(query, matcher) {\n        // Strip off line/col number suffix so it doesn't interfere with filename search\n        var cursorPos = extractCursorPos(query);\n        if (cursorPos && !cursorPos.local && cursorPos.query !== \"\") {\n            query = query.replace(cursorPos.query, \"\");\n        }\n\n        // First pass: filter based on search string; convert to SearchResults containing extra info\n        // for sorting & display\n        var filteredList = $.map(fileList, function (fileInfo) {\n            // Is it a match at all?\n            // match query against the full path (with gaps between query characters allowed)\n            var searchResult;\n\n            searchResult = matcher.match(ProjectManager.makeProjectRelativeIfPossible(fileInfo.fullPath), query);\n\n            if (searchResult) {\n                searchResult.label = fileInfo.name;\n                searchResult.fullPath = fileInfo.fullPath;\n                searchResult.filenameWithoutExtension = _filenameFromPath(fileInfo.name, false);\n            }\n            return searchResult;\n        });\n\n        // Sort by \"match goodness\" tier first, then within each tier sort alphabetically - first by filename\n        // sans extension, (so that \"abc.js\" comes before \"abc-d.js\"), then by filename, and finally (for\n        // identically-named files) by full path\n        StringMatch.multiFieldSort(filteredList, { matchGoodness: 0, filenameWithoutExtension: 1, label: 2, fullPath: 3 });\n\n        return filteredList;\n    }\n\n    function searchFileList(query, matcher) {\n        // The file index may still be loading asynchronously - if so, can't return a result yet\n        if (!fileList) {\n            var asyncResult = new $.Deferred();\n            fileListPromise.done(function () {\n                // Synchronously re-run the search call and resolve with its results\n                asyncResult.resolve(_doSearchFileList(query, matcher));\n            });\n            return asyncResult.promise();\n\n        } else {\n            return _doSearchFileList(query, matcher);\n        }\n    }\n\n    /**\n     * Handles changes to the current query in the search field.\n     * @param {string} query The new query.\n     * @return {$.Promise|Array.<*>|{error:?string}} The filtered list of results, an error object, or a Promise that\n     *                                               yields one of those\n     */\n    QuickNavigateDialog.prototype._filterCallback = function (query) {\n        // Re-evaluate which plugin is active each time query string changes\n        currentPlugin = null;\n\n        // \"Go to line\" mode is special-cased\n        var cursorPos = extractCursorPos(query);\n        if (cursorPos && cursorPos.local) {\n            // Bare Go to Line (no filename search) - can validate & jump to it now, without waiting for Enter/commit\n            var editor = EditorManager.getCurrentFullEditor();\n\n            // Validate (could just use 0 and lineCount() here, but in future might want this to work for inline editors too)\n            if (cursorPos && editor && cursorPos.line >= editor.getFirstVisibleLine() && cursorPos.line <= editor.getLastVisibleLine()) {\n                var from = {line: cursorPos.line, ch: cursorPos.ch},\n                    to   = {line: cursorPos.line};\n                EditorManager.getCurrentFullEditor().setSelection(from, to, true);\n\n                return { error: null };  // no error even though no results listed\n            } else {\n                return [];  // red error highlight: line number out of range, or no editor open\n            }\n        }\n        if (query === \":\") {  // treat blank \":\" query as valid, but no-op\n            return { error: null };\n        }\n\n        var i,\n            plugins = _getPluginsForCurrentContext();\n        for (i = 0; i < plugins.length; i++) {\n            var plugin = plugins[i].provider;\n            if(plugin.match(query)) {\n                currentPlugin = plugin;\n\n                // Look up the StringMatcher for this plugin.\n                var matcher = this._matchers[currentPlugin.name];\n                if (!matcher) {\n                    matcher = new StringMatch.StringMatcher(plugin.matcherOptions);\n                    this._matchers[currentPlugin.name] = matcher;\n                }\n                this._updateDialogLabel(plugin, query);\n                return plugin.search(query, matcher);\n            }\n        }\n\n        // Reflect current search mode in UI\n        this._updateDialogLabel(null, query);\n\n        // No matching plugin: use default file search mode\n        return searchFileList(query, this._filenameMatcher);\n    };\n\n    /**\n     * Formats item's label as properly escaped HTML text, highlighting sections that match 'query'.\n     * If item is a SearchResult generated by stringMatch(), uses its metadata about which string ranges\n     * matched; else formats the label with no highlighting.\n     * @param {!string|SearchResult} item\n     * @param {?string} matchClass CSS class for highlighting matched text\n     * @param {?function(boolean, string):string} rangeFilter\n     * @return {!string} bolded, HTML-escaped result\n     */\n    function highlightMatch(item, matchClass, rangeFilter) {\n        var label = item.label || item;\n        matchClass = matchClass || \"quicksearch-namematch\";\n\n        var stringRanges = item.stringRanges;\n        if (!stringRanges) {\n            // If result didn't come from stringMatch(), highlight nothing\n            stringRanges = [{\n                text: label,\n                matched: false,\n                includesLastSegment: true\n            }];\n        }\n\n        var displayName = \"\";\n        if (item.scoreDebug) {\n            var sd = item.scoreDebug;\n            displayName += '<span title=\"sp:' + sd.special + ', m:' + sd.match +\n                ', ls:' + sd.lastSegment + ', b:' + sd.beginning +\n                ', ld:' + sd.lengthDeduction + ', c:' + sd.consecutive + ', nsos: ' +\n                sd.notStartingOnSpecial + ', upper: ' + sd.upper + '\">(' + item.matchGoodness + ') </span>';\n        }\n\n        // Put the path pieces together, highlighting the matched parts\n        stringRanges.forEach(function (range) {\n            if (range.matched) {\n                displayName += \"<span class='\" + matchClass + \"'>\";\n            }\n\n            var rangeText = rangeFilter ? rangeFilter(range.includesLastSegment, range.text) : range.text;\n            displayName += StringUtils.breakableUrl(rangeText);\n\n            if (range.matched) {\n                displayName += \"</span>\";\n            }\n        });\n        return displayName;\n    }\n\n    function defaultResultsFormatter(item, query) {\n        query = query.slice(query.indexOf(\"@\") + 1, query.length);\n\n        var displayName = highlightMatch(item);\n        return \"<li>\" + displayName + \"</li>\";\n    }\n\n    function _filenameResultsFormatter(item, query) {\n        // For main label, we just want filename: drop most of the string\n        function fileNameFilter(includesLastSegment, rangeText) {\n            if (includesLastSegment) {\n                var rightmostSlash = rangeText.lastIndexOf('/');\n                return rangeText.substring(rightmostSlash + 1);  // safe even if rightmostSlash is -1\n            } else {\n                return \"\";\n            }\n        }\n        var displayName = highlightMatch(item, null, fileNameFilter);\n        var displayPath = highlightMatch(item, \"quicksearch-pathmatch\");\n\n        return \"<li>\" + displayName + \"<br /><span class='quick-open-path'>\" + displayPath + \"</span></li>\";\n    }\n\n    /**\n     * Formats the entry for the given item to be displayed in the dropdown.\n     * @param {Object} item The item to be displayed.\n     * @return {string} The HTML to be displayed.\n     */\n    QuickNavigateDialog.prototype._resultsFormatterCallback = function (item, query) {\n        var formatter;\n\n        if (currentPlugin) {\n            // Plugins use their own formatter or the default formatter\n            formatter = currentPlugin.resultsFormatter || defaultResultsFormatter;\n        } else {\n            // No plugin: default file search mode uses a special formatter\n            formatter = _filenameResultsFormatter;\n        }\n        return formatter(item, query);\n    };\n\n    /**\n     * Sets the value in the search field, updating the current mode and label based on the\n     * given prefix.\n     * @param {string} prefix The prefix that determines which mode we're in: must be empty (for file search),\n     *      \"@\" for go to definition, or \":\" for go to line.\n     * @param {string} initialString The query string to search for (without the prefix).\n     */\n    QuickNavigateDialog.prototype.setSearchFieldValue = function (prefix, initialString) {\n        prefix = prefix || \"\";\n        initialString = initialString || \"\";\n        initialString = prefix + initialString;\n\n        this.searchField.setText(initialString);\n\n        // Select just the text after the prefix\n        this.$searchField[0].setSelectionRange(prefix.length, initialString.length);\n    };\n\n    /**\n     * Sets the dialog label based on the current plugin (if any) and the current query.\n     * @param {Object} plugin The current Quick Open plugin, or none if there is none.\n     * @param {string} query The user's current query.\n     */\n    QuickNavigateDialog.prototype._updateDialogLabel = function (plugin, query) {\n        var dialogLabel = \"\";\n        if (plugin && plugin.label) {\n            dialogLabel = plugin.label;\n        } else {\n            var prefix = (query.length > 0 ? query.charAt(0) : \"\");\n\n            // Update the dialog label based on the current prefix.\n            switch (prefix) {\n            case \":\":\n                dialogLabel = Strings.CMD_GOTO_LINE + \"\\u2026\";\n                break;\n            case \"@\":\n                dialogLabel = Strings.CMD_GOTO_DEFINITION + \"\\u2026\";\n                break;\n            case \"#\":\n                dialogLabel = Strings.CMD_GOTO_DEFINITION_PROJECT + \"\\u2026\";\n                break;\n            default:\n                dialogLabel = \"\";\n                break;\n            }\n        }\n        $(\".find-dialog-label\", this.dialog).text(dialogLabel);\n    };\n\n    /**\n     * Shows the search dialog and initializes the auto suggestion list with filenames from the current project\n     */\n    QuickNavigateDialog.prototype.showDialog = function (prefix, initialString) {\n        if (this.isOpen) {\n            return;\n        }\n        this.isOpen = true;\n\n        // Record current document & cursor pos so we can restore it if search is canceled\n        // We record scroll pos *before* modal bar is opened since we're going to restore it *after* it's closed\n        var curDoc = DocumentManager.getCurrentDocument();\n        this._origDocPath = curDoc ? curDoc.file.fullPath : null;\n        if (curDoc) {\n            this._origSelections = EditorManager.getCurrentFullEditor().getSelections();\n            this._origScrollPos = EditorManager.getCurrentFullEditor().getScrollPos();\n        } else {\n            this._origSelections = null;\n            this._origScrollPos = null;\n        }\n\n        // Show the search bar\n        var searchBarHTML = \"<div align='right'><input type='text' autocomplete='off' id='quickOpenSearch' placeholder='\" + Strings.CMD_QUICK_OPEN + \"\\u2026' style='width: 30em'><span class='find-dialog-label'></span></div>\";\n        this.modalBar = new ModalBar(searchBarHTML, true);\n\n        this.modalBar.on(\"close\", this._handleCloseBar);\n\n        this.$searchField = $(\"input#quickOpenSearch\");\n\n        this.searchField = new QuickSearchField(this.$searchField, {\n            maxResults: 20,\n            firstHighlightIndex: 0,\n            verticalAdjust: this.modalBar.getRoot().outerHeight(),\n            resultProvider: this._filterCallback,\n            formatter: this._resultsFormatterCallback,\n            onCommit: this._handleItemSelect,\n            onHighlight: this._handleItemHighlight\n        });\n\n        // Return files that are non-binary, or binary files that have a custom viewer\n        function _filter(file) {\n            return !LanguageManager.getLanguageForPath(file.fullPath).isBinary() ||\n                MainViewFactory.findSuitableFactoryForPath(file.fullPath);\n        }\n\n        // Start prefetching the file list, which will be needed the first time the user enters an un-prefixed query. If file index\n        // caches are out of date, this list might take some time to asynchronously build, forcing searchFileList() to wait. In the\n        // meantime we show our old, stale fileList (unless the user has switched projects and we cleared it).\n        fileListPromise = ProjectManager.getAllFiles(_filter, true)\n            .done(function (files) {\n                fileList = files;\n                fileListPromise = null;\n                this._filenameMatcher.reset();\n            }.bind(this));\n\n        // Prepopulated query\n        this.$searchField.focus();\n        this.setSearchFieldValue(prefix, initialString);\n    };\n\n    function getCurrentEditorSelectedText() {\n        var currentEditor = EditorManager.getActiveEditor();\n        return (currentEditor && currentEditor.getSelectedText()) || \"\";\n    }\n\n    /**\n     * Opens the Quick Open bar prepopulated with the given prefix (to select a mode) and optionally\n     * with the given query text too. Updates text field contents if Quick Open already open.\n     * @param {?string} prefix\n     * @param {?string} initialString\n     */\n    function beginSearch(prefix, initialString) {\n        function createDialog() {\n            _curDialog = new QuickNavigateDialog();\n            _curDialog.showDialog(prefix, initialString);\n        }\n\n        if (_curDialog) {\n            if (_curDialog.isOpen) {\n                // Just start a search using the existing dialog.\n                _curDialog.setSearchFieldValue(prefix, initialString);\n            } else {\n                // The dialog is already closing. Wait till it's done closing,\n                // then open a new dialog. (Calling close() again returns the\n                // promise for the deferred that was already kicked off when it\n                // started closing.)\n                _curDialog.close().done(createDialog);\n            }\n        } else {\n            createDialog();\n        }\n    }\n\n    function doFileSearch() {\n        beginSearch(\"\", getCurrentEditorSelectedText());\n    }\n\n    function doGotoLine() {\n        // TODO: Brackets doesn't support disabled menu items right now, when it does goto line and\n        // goto definition should be disabled when there is not a current document\n        if (DocumentManager.getCurrentDocument()) {\n            beginSearch(\":\", \"\");\n        }\n    }\n\n    function doDefinitionSearch() {\n        if (DocumentManager.getCurrentDocument()) {\n            beginSearch(\"@\", getCurrentEditorSelectedText());\n        }\n    }\n\n    function doDefinitionSearchInProject() {\n        if (DocumentManager.getCurrentDocument()) {\n            beginSearch(\"#\", getCurrentEditorSelectedText());\n        }\n    }\n\n    function _canHandleTrigger(trigger, plugins) {\n        var retval = false;\n\n        plugins.some(function (plugin, index) {\n            var provider = plugin.provider;\n            if (provider.match(trigger)) {\n                retval = true;\n                return true;\n            }\n        });\n\n        return retval;\n    }\n\n    function _setMenuItemStateForLanguage(languageId) {\n        var plugins = _providerRegistrationHandler.getProvidersForLanguageId(languageId);\n        if (_canHandleTrigger(\"@\", plugins)) {\n            CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(true);\n        } else {\n            CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(false);\n        }\n\n        if (_canHandleTrigger(\"#\", plugins)) {\n            CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(true);\n        } else {\n            CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(false);\n        }\n    }\n\n    // Listen for a change of project to invalidate our file list\n    ProjectManager.on(\"projectOpen\", function () {\n        fileList = null;\n    });\n\n    MainViewManager.on(\"currentFileChange\", function (event, newFile, newPaneId, oldFile, oldPaneId) {\n        if (!newFile) {\n            CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION).setEnabled(false);\n            CommandManager.get(Commands.NAVIGATE_GOTO_DEFINITION_PROJECT).setEnabled(false);\n            return;\n        }\n\n        var newFilePath = newFile.fullPath,\n            newLanguageId = LanguageManager.getLanguageForPath(newFilePath).getId();\n        _setMenuItemStateForLanguage(newLanguageId);\n\n        DocumentManager.getDocumentForPath(newFilePath)\n            .done(function (newDoc) {\n                newDoc.on(\"languageChanged.quickFindDefinition\", function () {\n                    var changedLanguageId = LanguageManager.getLanguageForPath(newDoc.file.fullPath).getId();\n                    _setMenuItemStateForLanguage(changedLanguageId);\n                });\n            }).fail(function (err) {\n                console.error(err);\n            });\n\n        if (!oldFile) {\n            return;\n        }\n\n        var oldFilePath = oldFile.fullPath;\n        DocumentManager.getDocumentForPath(oldFilePath)\n            .done(function (oldDoc) {\n                oldDoc.off(\"languageChanged.quickFindDefinition\");\n            }).fail(function (err) {\n                console.error(err);\n            });\n    });\n\n    CommandManager.register(Strings.CMD_QUICK_OPEN,         Commands.NAVIGATE_QUICK_OPEN,       doFileSearch);\n    CommandManager.register(Strings.CMD_GOTO_DEFINITION,    Commands.NAVIGATE_GOTO_DEFINITION,  doDefinitionSearch);\n    CommandManager.register(Strings.CMD_GOTO_DEFINITION_PROJECT,    Commands.NAVIGATE_GOTO_DEFINITION_PROJECT,  doDefinitionSearchInProject);\n    CommandManager.register(Strings.CMD_GOTO_LINE,          Commands.NAVIGATE_GOTO_LINE,        doGotoLine);\n\n    exports.beginSearch             = beginSearch;\n    exports.addQuickOpenPlugin      = addQuickOpenPlugin;\n    exports.highlightMatch          = highlightMatch;\n    exports.SymbolKind              = SymbolKind;\n\n    // Convenience exports for functions that most QuickOpen plugins would need.\n    exports.stringMatch             = StringMatch.stringMatch;\n    exports.SearchResult            = StringMatch.SearchResult;\n    exports.basicMatchSort          = StringMatch.basicMatchSort;\n    exports.multiFieldSort          = StringMatch.multiFieldSort;\n});\n"
  },
  {
    "path": "src/search/QuickOpenHelper.js",
    "content": "/*\n * Copyright (c) 2016 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n    \n    var EditorManager       = require(\"editor/EditorManager\"),\n        QuickOpen           = require(\"search/QuickOpen\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        StringMatch         = require(\"utils/StringMatch\");\n    \n    /**\n     * @param {string} query what the user is searching for\n     * @param {boolean} returns true if this plug-in wants to provide results for this query\n     */\n    function match(query) {\n        return (query[0] === \"@\");\n    }\n\n    /**\n     * Scroll to the selected item in the current document (unless no query string entered yet,\n     * in which case the topmost list item is irrelevant)\n     * @param {?SearchResult} selectedItem\n     * @param {string} query\n     * @param {boolean} explicit False if this is only highlighted due to being at top of list after search()\n     */\n    function itemFocus(selectedItem, query, explicit) {\n        if (!selectedItem || (query.length < 2 && !explicit)) {\n            return;\n        }\n        var fileLocation = selectedItem.fileLocation;\n\n        var from = {line: fileLocation.line, ch: fileLocation.chFrom};\n        var to = {line: fileLocation.line, ch: fileLocation.chTo};\n        EditorManager.getCurrentFullEditor().setSelection(from, to, true);\n    }\n\n    /**\n     * Scroll to the selected item in the current document (unless no query string entered yet,\n     * in which case the topmost list item is irrelevant)\n     * @param {?SearchResult} selectedItem\n     * @param {string} query\n     */\n    function itemSelect(selectedItem, query) {\n        itemFocus(selectedItem, query, true);\n    }\n    \n    exports.match      = match;\n    exports.itemFocus  = itemFocus;\n    exports.itemSelect = itemSelect;\n});\n"
  },
  {
    "path": "src/search/QuickSearchField.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * Text field with attached dropdown list that is updated (based on a provider) whenever the text changes.\n *\n * For styling, the DOM structure of the popup is as follows:\n *  body\n *      ol.quick-search-container\n *          li\n *          li.highlight\n *          li\n * And the text field is:\n *      input\n *      input.no-results\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var KeyEvent = require(\"utils/KeyEvent\");\n\n\n    /**\n     * Attaches to an existing <input> tag\n     *\n     * @constructor\n     *\n     * @param {!jQueryObject} $input\n     * @param {!function(string):($.Promise|Array.<*>|{error:?string}} options.resultProvider\n     *          Given the current search text, returns an an array of result objects, an error object, or a\n     *          Promise that yields one of those. If the Promise is still outstanding when the query next\n     *          changes, resultProvider() will be called again (without waiting for the earlier Promise), and\n     *          the Promise's result will be ignored.\n     *          If the provider yields [], or a non-null error string, input is decorated with \".no-results\"; if\n     *          the provider yields a null error string, input is not decorated.\n     *\n     * @param {!function(*, string):string} options.formatter\n     *          Converts one result object to a string of HTML text. Passed the item and the current query. The\n     *          outermost element must be <li>. The \".highlight\" class can be ignored as it is applied automatically.\n     * @param {!function(?*, string):void} options.onCommit\n     *          Called when an item is selected by clicking or pressing Enter. Passed the item and the current\n     *          query. If the current result list is not up to date with the query text at the time Enter is\n     *          pressed, waits until it is before running this callback. If Enter pressed with no results, passed\n     *          null. The popup remains open after this event.\n     * @param {!function(*, string, boolean):void} options.onHighlight\n     *          Called when an item is highlighted in the list. Passed the item, the current query, and a flag that is\n     *          true if the item was highlighted explicitly (arrow keys), not simply due to a results list update. Since\n     *          the top item in the list is always initially highlighted, every time the list is updated onHighlight()\n     *          is called with the top item and with the explicit flag set to false.\n     * @param {?number} options.maxResults\n     *          Maximum number of items from resultProvider() to display in the popup.\n     * @param {?number} options.verticalAdjust\n     *          Number of pixels to position the popup below where $input is when constructor is called. Useful\n     *          if UI is going to animate position after construction, but QuickSearchField may receive input\n     *          before the animation is done.\n     * @param {?number} options.firstHighlightIndex\n     *          Index of the result that is highlighted by default. null to not highlight any result.\n     */\n    function QuickSearchField($input, options) {\n        this.$input = $input;\n        this.options = options;\n\n        options.maxResults = options.maxResults || 10;\n\n        this._handleInput   = this._handleInput.bind(this);\n        this._handleKeyDown = this._handleKeyDown.bind(this);\n\n        if (options.highlightZeroResults !== undefined) {\n            this._highlightZeroResults = options.highlightZeroResults;\n        } else {\n            this._highlightZeroResults = true;\n        }\n\n        $input.on(\"input\", this._handleInput);\n        $input.on(\"keydown\", this._handleKeyDown);\n        \n        // For search History this value is set to null\n        this._firstHighlightIndex = options.firstHighlightIndex;\n\n        this._dropdownTop = $input.offset().top + $input.height() + (options.verticalAdjust || 0);\n    }\n\n    /** @type {!Object} */\n    QuickSearchField.prototype.options = null;\n\n    /** @type {?$.Promise} Promise corresponding to latest resultProvider call. Any earlier promises ignored */\n    QuickSearchField.prototype._pending = null;\n\n    /** @type {boolean} True if Enter already pressed & just waiting for results to arrive before committing */\n    QuickSearchField.prototype._commitPending = false;\n\n    /** @type {?string} Value of $input corresponding to the _displayedResults list */\n    QuickSearchField.prototype._displayedQuery = null;\n\n    /** @type {?Array.<*>}  Latest resultProvider result */\n    QuickSearchField.prototype._displayedResults = null;\n\n    /** @type {?number} */\n    QuickSearchField.prototype._highlightIndex = null;\n\n    /** @type {?jQueryObject} Dropdown's <ol>, while open; null while closed */\n    QuickSearchField.prototype._$dropdown = null;\n\n    /** @type {!jQueryObject} */\n    QuickSearchField.prototype.$input = null;\n\n\n    /** When text field changes, update results list */\n    QuickSearchField.prototype._handleInput = function () {\n        this._pending = null;  // immediately invalidate any previous Promise\n\n        var valueAtEvent = this.$input.val();\n        var self = this;\n        // The timeout lets us skip over a backlog of multiple keyboard events when the provider is responding\n        // so slowly that JS execution can't keep up. All the remaining input events are serviced before the\n        // first timeout runs; then all the queued-up timeouts run in a row. All except the last one can no-op.\n        setTimeout(function () {\n            if (self.$input.val() === valueAtEvent) {\n                self.updateResults();\n            }\n        }, 0);\n    };\n\n    /** Handle special keys: Enter, Up/Down */\n    QuickSearchField.prototype._handleKeyDown = function (event) {\n        if (event.keyCode === KeyEvent.DOM_VK_RETURN) {\n            // Enter should always act on the latest results. If input has changed and we're still waiting for\n            // new results, just flag the 'commit' for later\n            if (this._displayedQuery === this.$input.val()) {\n                event.preventDefault();  // prevents keyup from going to someone else after we close\n                this._doCommit();\n            } else {\n                // Once the current wait resolves, _render() will run the commit\n                this._commitPending = true;\n            }\n        } else if (event.keyCode === KeyEvent.DOM_VK_DOWN) {\n            // Highlight changes are always done synchronously on the currently shown result list. If the list\n            // later changes, the highlight is reset to the top\n            if (this._displayedResults && this._displayedResults.length) {\n                if (this._highlightIndex === null || this._highlightIndex === this._displayedResults.length - 1) {\n                    this._highlightIndex = 0;\n                } else {\n                    this._highlightIndex++;\n                }\n                this._updateHighlight(true);\n            }\n            event.preventDefault(); // treated as Home key otherwise\n\n        } else if (event.keyCode === KeyEvent.DOM_VK_UP) {\n            if (this._displayedResults && this._displayedResults.length) {\n                if (this._highlightIndex === null || this._highlightIndex === 0) {\n                    this._highlightIndex = this._displayedResults.length - 1;\n                } else {\n                    this._highlightIndex--;\n                }\n                this._updateHighlight(true);\n            }\n            event.preventDefault(); // treated as End key otherwise\n        }\n    };\n\n    /** Call onCommit() immediately */\n    QuickSearchField.prototype._doCommit = function (index) {\n        var item;\n        if (this._displayedResults && this._displayedResults.length) {\n            if (index >= 0) {\n                item = this._displayedResults[index];\n            } else if (this._highlightIndex >= 0) {\n                item = this._displayedResults[this._highlightIndex];\n            }\n        }\n        this.options.onCommit(item, this._displayedQuery);\n    };\n\n    /** Update display to reflect value of _highlightIndex, & call onHighlight() */\n    QuickSearchField.prototype._updateHighlight = function (explicit) {\n        if (this._$dropdown) {\n            var $items = this._$dropdown.find(\"li\");\n            $items.removeClass(\"highlight\");\n            if (this._highlightIndex !== null) {\n                $items.eq(this._highlightIndex).addClass(\"highlight\");\n\n                this.options.onHighlight(this._displayedResults[this._highlightIndex], this.$input.val(), explicit);\n            }\n        }\n    };\n\n    /**\n     * Refresh the results dropdown, as if the user had changed the search text. Useful for providers that\n     * want to show cached data initially, then update the results with fresher data once available.\n     */\n    QuickSearchField.prototype.updateResults = function () {\n        this._pending = null;  // immediately invalidate any previous Promise\n\n        var query = this.$input.val();\n        var results = this.options.resultProvider(query);\n        if (results.done && results.fail) {\n            // Provider returned an async result - mark it as the latest Promise and if it's still latest when\n            // it resolves, render the results then\n            this._pending = results;\n            var self = this;\n            this._pending.done(function (realResults) {\n                if (self._pending === results) {\n                    self._render(realResults, query);\n                    this._pending = null;\n                }\n            });\n            if (this._pending) {\n                this._pending.fail(function () {\n                    if (self._pending === results) {\n                        self._render([], query);\n                        this._pending = null;\n                    }\n                });\n            }\n        } else {\n            // Synchronous result - render immediately\n            this._render(results, query);\n        }\n    };\n\n\n    /** Close dropdown result list if visible */\n    QuickSearchField.prototype._closeDropdown = function () {\n        if (this._$dropdown) {\n            this._$dropdown.remove();\n            this._$dropdown = null;\n        }\n    };\n\n    /**\n     * Open dropdown result list & populate with the given content\n     * @param {!string} htmlContent\n     */\n    QuickSearchField.prototype._openDropdown = function (htmlContent) {\n        if (!this._$dropdown) {\n            var self = this;\n            this._$dropdown = $(\"<ol class='quick-search-container'/>\").appendTo(\"body\")\n                .css({\n                    position: \"absolute\",\n                    top: this._dropdownTop,\n                    left: this.$input.offset().left,\n                    width: this.$input.outerWidth()\n                })\n                .click(function (event) {\n                    // Unlike the Enter key, where we wait to catch up with typing, clicking commits immediately\n                    var $item = $(event.target).closest(\"li\");\n                    if ($item.length) {\n                        self._doCommit($item.index());\n                    }\n                });\n        }\n        this._$dropdown.html(htmlContent);\n    };\n\n    /**\n     * Given finished provider result, format it into HTML and show in dropdown, and update \"no-results\" style.\n     * If an Enter key commit was pending from earlier, process it now.\n     * @param {!Array.<*>} results\n     * @param {!string} query\n     */\n    QuickSearchField.prototype._render = function (results, query) {\n        this._displayedQuery = query;\n        this._displayedResults = results;\n        if (this._firstHighlightIndex >= 0) {\n            this._highlightIndex = this._firstHighlightIndex;\n        } else {\n            this._highlightIndex = null;\n        }\n        // TODO: fixup to match prev value's item if possible?\n\n        if (results.error || results.length === 0) {\n            this._closeDropdown();\n            if (this._highlightZeroResults) {\n                this.$input.addClass(\"no-results\");\n            }\n        } else if (results.hasOwnProperty(\"error\")) {\n            // Error present but falsy - no results to show, but don't decorate with error style\n            this._closeDropdown();\n            if (this._highlightZeroResults) {\n                this.$input.removeClass(\"no-results\");\n            }\n        } else {\n            if (this._highlightZeroResults) {\n                this.$input.removeClass(\"no-results\");\n            }\n\n            var count = Math.min(results.length, this.options.maxResults),\n                html = \"\",\n                i;\n            for (i = 0; i < count; i++) {\n                html += this.options.formatter(results[i], query);\n            }\n            this._openDropdown(html);\n\n            // Highlight top item and trigger highlight callback\n            this._updateHighlight(false);\n        }\n\n        // If Enter key was pressed earlier, handle it now that we've gotten results back\n        if (this._commitPending) {\n            this._commitPending = false;\n            this._doCommit();\n        }\n    };\n\n\n    /**\n     * Programmatically changes the search text and updates the results.\n     * @param {!string} value\n     */\n    QuickSearchField.prototype.setText = function (value) {\n        this.$input.val(value);\n        this.updateResults();  // programmatic changes don't trigger \"input\" event\n    };\n\n    /**\n     * Closes the dropdown, and discards any pending Promises.\n     */\n    QuickSearchField.prototype.destroy = function () {\n        this._pending = null;  // immediately invalidate any pending Promise\n        this._closeDropdown();\n    };\n\n\n    exports.QuickSearchField = QuickSearchField;\n});\n"
  },
  {
    "path": "src/search/ScrollTrackMarkers.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Manages tickmarks shown along the scrollbar track.\n * NOT yet intended for use by anyone other than the FindReplace module.\n * It is assumed that markers are always clear()ed when switching editors.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var WorkspaceManager = require(\"view/WorkspaceManager\");\n\n\n    /**\n     * Editor the markers are currently shown for, or null if not shown\n     * @type {?Editor}\n     */\n    var editor;\n\n    /**\n     * Top of scrollbar track area, relative to top of scrollbar\n     * @type {number}\n     */\n    var trackOffset;\n\n    /**\n     * Height of scrollbar track area\n     * @type {number}\n     */\n    var trackHt;\n\n    /**\n     * Text positions of markers\n     * @type {!Array.<{line: number, ch: number}>}\n     */\n    var marks = [];\n\n    /**\n     * Tickmark markCurrent() last called on, or null if never called / called with -1.\n     * @type {?jQueryObject}\n     */\n    var $markedTickmark;\n    \n    /**\n     * Vertical space above and below the scrollbar\n     * @type {number}\n     */\n    var scrollbarTrackOffset;\n\n    switch (brackets.platform) {\n    case \"win\": // Custom scrollbar CSS has no gap around the track\n        scrollbarTrackOffset = 0;\n        break;\n    case \"mac\": // Native scrollbar has padding around the track\n        scrollbarTrackOffset = 4;\n        break;\n    case \"linux\": // Custom scrollbar CSS has assymmetrical gap; this approximates it\n        scrollbarTrackOffset = 2;\n        break;\n    }\n\n    /**\n     * Vertical space above and below the scrollbar.\n     * @return {number} amount Value in pixels\n     */\n    function getScrollbarTrackOffset() {\n        return scrollbarTrackOffset;\n    }\n\n    /**\n     * Sets how much vertical space there's above and below the scrollbar, which depends\n     * on the OS and may also be affected by extensions\n     * @param {number} offset Value in pixels\n     */\n    function setScrollbarTrackOffset(offset) {\n        scrollbarTrackOffset = offset;\n    }\n    \n    \n    function _getScrollbar(editor) {\n        // Be sure to select only the direct descendant, not also elements within nested inline editors\n        return $(editor.getRootElement()).children(\".CodeMirror-vscrollbar\");\n    }\n\n    /** Measure scrollbar track */\n    function _calcScaling() {\n        var $sb = _getScrollbar(editor);\n\n        trackHt = $sb[0].offsetHeight;\n\n        if (trackHt > 0) {\n            trackOffset = getScrollbarTrackOffset();\n            trackHt -= trackOffset * 2;\n        } else {\n            // No scrollbar: use the height of the entire code content\n            var codeContainer = $(editor.getRootElement()).find(\"> .CodeMirror-scroll > .CodeMirror-sizer > div > .CodeMirror-lines > div\")[0];\n            trackHt = codeContainer.offsetHeight;\n            trackOffset = codeContainer.offsetTop;\n        }\n    }\n\n    /** Add all the given tickmarks to the DOM in a batch */\n    function _renderMarks(posArray) {\n        var html = \"\",\n            cm = editor._codeMirror,\n            editorHt = cm.getScrollerElement().scrollHeight;\n\n        // We've pretty much taken these vars and the getY function from CodeMirror's annotatescrollbar addon\n        // https://github.com/codemirror/CodeMirror/blob/master/addon/scroll/annotatescrollbar.js\n        var wrapping = cm.getOption(\"lineWrapping\"),\n            singleLineH = wrapping && cm.defaultTextHeight() * 1.5,\n            curLine = null,\n            curLineObj = null;\n\n        function getY(cm, pos) {\n            if (curLine !== pos.line) {\n                curLine = pos.line;\n                curLineObj = cm.getLineHandle(curLine);\n            }\n            if (wrapping && curLineObj.height > singleLineH) {\n                return cm.charCoords(pos, \"local\").top;\n            }\n            return cm.heightAtLine(curLineObj, \"local\");\n        }\n\n        posArray.forEach(function (pos) {\n            var cursorTop = getY(cm, pos),\n                top = Math.round(cursorTop / editorHt * trackHt) + trackOffset;\n            top--;  // subtract ~1/2 the ht of a tickmark to center it on ideal pos\n\n            html += \"<div class='tickmark' style='top:\" + top + \"px'></div>\";\n        });\n        $(\".tickmark-track\", editor.getRootElement()).append($(html));\n    }\n\n\n    /**\n     * Clear any markers in the editor's tickmark track, but leave it visible. Safe to call when\n     * tickmark track is not visible also.\n     */\n    function clear() {\n        if (editor) {\n            $(\".tickmark-track\", editor.getRootElement()).empty();\n            marks = [];\n            $markedTickmark = null;\n        }\n    }\n\n    /** Add or remove the tickmark track from the editor's UI */\n    function setVisible(curEditor, visible) {\n        // short-circuit no-ops\n        if ((visible && curEditor === editor) || (!visible && !editor)) {\n            return;\n        }\n\n        if (visible) {\n            console.assert(!editor);\n            editor = curEditor;\n\n            // Don't support inline editors yet - search inside them is pretty screwy anyway (#2110)\n            if (editor.isTextSubset()) {\n                return;\n            }\n\n            var $sb = _getScrollbar(editor),\n                $overlay = $(\"<div class='tickmark-track'></div>\");\n            $sb.parent().append($overlay);\n\n            _calcScaling();\n\n            // Update tickmarks during editor resize (whenever resizing has paused/stopped for > 1/3 sec)\n            WorkspaceManager.on(\"workspaceUpdateLayout.ScrollTrackMarkers\", _.debounce(function () {\n                if (marks.length) {\n                    _calcScaling();\n                    $(\".tickmark-track\", editor.getRootElement()).empty();\n                    _renderMarks(marks);\n                }\n            }, 300));\n\n        } else {\n            console.assert(editor === curEditor);\n            $(\".tickmark-track\", curEditor.getRootElement()).remove();\n            editor = null;\n            marks = [];\n            WorkspaceManager.off(\"workspaceUpdateLayout.ScrollTrackMarkers\");\n        }\n    }\n\n    /**\n     * Add tickmarks to the editor's tickmark track, if it's visible\n     * @param curEditor {!Editor}\n     * @param posArray {!Array.<{line:Number, ch:Number}>}\n     */\n    function addTickmarks(curEditor, posArray) {\n        console.assert(editor === curEditor);\n\n        marks = marks.concat(posArray);\n        _renderMarks(posArray);\n    }\n\n    /** @param {number} index Either -1, or an index into the array passed to addTickmarks() */\n    function markCurrent(index) {\n        // Remove previous highlight first\n        if ($markedTickmark) {\n            $markedTickmark.removeClass(\"tickmark-current\");\n            $markedTickmark = null;\n        }\n        if (index !== -1) {\n            $markedTickmark = $(\".tickmark-track > .tickmark\", editor.getRootElement()).eq(index).addClass(\"tickmark-current\");\n        }\n    }\n\n    // Private helper for unit tests\n    function _getTickmarks() {\n        return marks;\n    }\n\n\n    // For unit tests\n    exports._getTickmarks   = _getTickmarks;\n\n    exports.clear           = clear;\n    exports.setVisible      = setVisible;\n    exports.addTickmarks    = addTickmarks;\n    exports.markCurrent     = markCurrent;\n    \n    exports.getScrollbarTrackOffset = getScrollbarTrackOffset;\n    exports.setScrollbarTrackOffset = setScrollbarTrackOffset;\n});\n"
  },
  {
    "path": "src/search/SearchModel.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileUtils       = require(\"file/FileUtils\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        FindUtils       = require(\"search/FindUtils\"),\n        MainViewManager = require(\"view/MainViewManager\");\n\n    /**\n     * @constructor\n     * Manages a set of search query and result data.\n     * Dispatches these events:\n     *      \"change\" - whenever the results have been updated. Note that it's up to people who\n     *      edit the model to call fireChange() when necessary - it doesn't automatically fire.\n     */\n    function SearchModel() {\n        this.clear();\n    }\n    EventDispatcher.makeEventDispatcher(SearchModel.prototype);\n\n    /** @const Constant used to define the maximum results found.\n     *  Note that this is a soft limit - we'll likely go slightly over it since\n     *  we always add all the searches in a given file.\n     */\n    SearchModel.MAX_TOTAL_RESULTS = 100000;\n\n    /**\n     * The current set of results.\n     * @type {Object.<fullPath: string, {matches: Array.<Object>, collapsed: boolean, timestamp: Date}>}\n     */\n    SearchModel.prototype.results = null;\n\n    /**\n     * The query that generated these results.\n     * @type {{query: string, caseSensitive: boolean, isRegexp: boolean}}\n     */\n    SearchModel.prototype.queryInfo = null;\n\n    /**\n     * The compiled query, expressed as a regexp.\n     * @type {RegExp}\n     */\n    SearchModel.prototype.queryExpr = null;\n\n    /**\n     * Whether this is a find/replace query.\n     * @type {boolean}\n     */\n    SearchModel.prototype.isReplace = false;\n\n    /**\n     * The replacement text specified for this query, if any.\n     * @type {string}\n     */\n    SearchModel.prototype.replaceText = null;\n\n    /**\n     * The file/folder path representing the scope that this query was performed in.\n     * @type {FileSystemEntry}\n     */\n    SearchModel.prototype.scope = null;\n\n    /**\n     * A file filter (as returned from FileFilters) to apply within the main scope.\n     * @type {string}\n     */\n    SearchModel.prototype.filter = null;\n\n    /**\n     * The total number of matches in the model.\n     * @type {number}\n     */\n    SearchModel.prototype.numMatches = 0;\n\n    /**\n     * Whether or not we hit the maximum number of results for the type of search we did.\n     * @type {boolean}\n     */\n    SearchModel.prototype.foundMaximum = false;\n\n    /**\n     * Whether or not we exceeded the maximum number of results in the search we did.\n     * @type {boolean}\n     */\n    SearchModel.prototype.exceedsMaximum = false;\n\n    /**\n     * Clears out the model to an empty state.\n     */\n    SearchModel.prototype.clear = function () {\n        var numMatchesBefore = this.numMatches;\n        this.results = {};\n        this.queryInfo = null;\n        this.queryExpr = null;\n        this.isReplace = false;\n        this.replaceText = null;\n        this.scope = null;\n        this.numMatches = 0;\n        this.foundMaximum = false;\n        this.exceedsMaximum = false;\n        if (numMatchesBefore !== 0) {\n            this.fireChanged();\n        }\n    };\n\n    /**\n     * Sets the given query info and stores a compiled RegExp query in this.queryExpr.\n     * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo\n     * @return {boolean} true if the query was valid and properly set, false if it was\n     *      invalid or empty.\n     */\n    SearchModel.prototype.setQueryInfo = function (queryInfo) {\n        var parsedQuery = FindUtils.parseQueryInfo(queryInfo);\n        if (parsedQuery.valid) {\n            this.queryInfo = queryInfo;\n            this.queryExpr = parsedQuery.queryExpr;\n            return true;\n        } else {\n            return false;\n        }\n    };\n\n    /**\n     * Sets the list of matches for the given path, removing the previous match info, if any, and updating\n     * the total match count. Note that for the count to remain accurate, the previous match info must not have\n     * been mutated since it was set.\n     * @param {string} fullpath Full path to the file containing the matches.\n     * @param {!{matches: Object, timestamp: Date, collapsed: boolean=}} resultInfo Info for the matches to set:\n     *      matches - Array of matches, in the format returned by FindInFiles._getSearchMatches()\n     *      timestamp - The timestamp of the document at the time we searched it.\n     *      collapsed - Optional: whether the results should be collapsed in the UI (default false).\n     */\n    SearchModel.prototype.setResults = function (fullpath, resultInfo) {\n        this.removeResults(fullpath);\n\n        if (this.foundMaximum || !resultInfo.matches.length) {\n            return;\n        }\n\n        // Make sure that the optional `collapsed` property is explicitly set to either true or false,\n        // to avoid logic issues later with comparing values.\n        resultInfo.collapsed = !!resultInfo.collapsed;\n\n        this.results[fullpath] = resultInfo;\n        this.numMatches += resultInfo.matches.length;\n        if (this.numMatches >= SearchModel.MAX_TOTAL_RESULTS) {\n            this.foundMaximum = true;\n\n            // Remove final result if there have been over MAX_TOTAL_RESULTS found\n            if (this.numMatches > SearchModel.MAX_TOTAL_RESULTS) {\n                this.results[fullpath].matches.pop();\n                this.numMatches--;\n                this.exceedsMaximum = true;\n            }\n        }\n    };\n\n    /**\n     * Removes the given result's matches from the search results and updates the total match count.\n     * @param {string} fullpath Full path to the file containing the matches.\n     */\n    SearchModel.prototype.removeResults = function (fullpath) {\n        if (this.results[fullpath]) {\n            this.numMatches -= this.results[fullpath].matches.length;\n            delete this.results[fullpath];\n        }\n    };\n\n    /**\n     * @return {boolean} true if there are any results in this model.\n     */\n    SearchModel.prototype.hasResults = function () {\n        return Object.keys(this.results).length > 0;\n    };\n\n    /**\n     * Counts the total number of matches and files\n     * @return {{files: number, matches: number}}\n     */\n    SearchModel.prototype.countFilesMatches = function () {\n        return {files: (this.numFiles || Object.keys(this.results).length), matches: this.numMatches};\n    };\n\n    /**\n     * Prioritizes the open file and then the working set files to the starting of the list of files\n     * If node search is disabled, we sort the files too- Sorting is computation intensive, and our\n     * ProjectManager.getAllFiles with the sort flag is not working properly : TODO TOFIX\n     * @param {?string} firstFile If specified, the path to the file that should be sorted to the top.\n     * @return {Array.<string>}\n     */\n    SearchModel.prototype.prioritizeOpenFile = function (firstFile) {\n        var workingSetFiles = MainViewManager.getWorkingSet(MainViewManager.ALL_PANES),\n            workingSetFileFound = {},\n            fileSetWithoutWorkingSet = [],\n            startingWorkingFileSet = [],\n            propertyName = \"\",\n            i = 0;\n\n        if (FindUtils.isNodeSearchDisabled()) {\n            return Object.keys(this.results).sort(function (key1, key2) {\n                if (firstFile === key1) {\n                    return -1;\n                } else if (firstFile === key2) {\n                    return 1;\n                }\n                return FileUtils.comparePaths(key1, key2);\n            });\n        }\n\n        firstFile = firstFile || \"\";\n\n        // Create a working set path map which indicates if a file in working set is found in file list\n        for (i = 0; i < workingSetFiles.length; i++) {\n            workingSetFileFound[workingSetFiles[i].fullPath] = false;\n        }\n\n        // Remove all the working set files from the filtration list\n        fileSetWithoutWorkingSet = Object.keys(this.results).filter(function (key) {\n            if (workingSetFileFound[key] !== undefined) {\n                workingSetFileFound[key] = true;\n                return false;\n            }\n            return true;\n        });\n\n        //push in the first file\n        if (workingSetFileFound[firstFile] === true) {\n            startingWorkingFileSet.push(firstFile);\n            workingSetFileFound[firstFile] = false;\n        }\n        //push in the rest of working set files already present in file list\n        for (propertyName in workingSetFileFound) {\n            if (workingSetFileFound.hasOwnProperty(propertyName) && workingSetFileFound[propertyName]) {\n                startingWorkingFileSet.push(propertyName);\n            }\n        }\n        return startingWorkingFileSet.concat(fileSetWithoutWorkingSet);\n    };\n\n    /**\n     * Notifies listeners that the set of results has changed. Must be called after the\n     * model is changed.\n     * @param {boolean} quickChange Whether this type of change is one that might occur\n     *      often, meaning that the view should buffer updates.\n     */\n    SearchModel.prototype.fireChanged = function (quickChange) {\n        this.trigger(\"change\", quickChange);\n    };\n\n    // Public API\n    exports.SearchModel = SearchModel;\n});\n"
  },
  {
    "path": "src/search/SearchResultsView.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * Panel showing search results for a Find/Replace in Files operation.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CommandManager        = require(\"command/CommandManager\"),\n        EventDispatcher       = require(\"utils/EventDispatcher\"),\n        Commands              = require(\"command/Commands\"),\n        DocumentManager       = require(\"document/DocumentManager\"),\n        EditorManager         = require(\"editor/EditorManager\"),\n        ProjectManager        = require(\"project/ProjectManager\"),\n        FileViewController    = require(\"project/FileViewController\"),\n        FileUtils             = require(\"file/FileUtils\"),\n        FindUtils             = require(\"search/FindUtils\"),\n        WorkspaceManager      = require(\"view/WorkspaceManager\"),\n        StringUtils           = require(\"utils/StringUtils\"),\n        Strings               = require(\"strings\"),\n        HealthLogger          = require(\"utils/HealthLogger\"),\n        _                     = require(\"thirdparty/lodash\"),\n        Mustache              = require(\"thirdparty/mustache/mustache\"),\n\n        searchPanelTemplate   = require(\"text!htmlContent/search-panel.html\"),\n        searchResultsTemplate = require(\"text!htmlContent/search-results.html\"),\n        searchSummaryTemplate = require(\"text!htmlContent/search-summary.html\");\n\n\n    /**\n     * @const\n     * The maximum results to show per page.\n     * @type {number}\n     */\n    var RESULTS_PER_PAGE = 100;\n\n    /**\n     * @const\n     * Debounce time for document changes updating the search results view.\n     * @type {number}\n     */\n    var UPDATE_TIMEOUT   = 400;\n\n    /**\n     * @constructor\n     * Handles the search results panel.\n     * Dispatches the following events:\n     *      replaceBatch - when the \"Replace\" button is clicked.\n     *      close - when the panel is closed.\n     *\n     * @param {SearchModel} model The model that this view is showing.\n     * @param {string} panelID The CSS ID to use for the panel.\n     * @param {string} panelName The name to use for the panel, as passed to WorkspaceManager.createBottomPanel().\n     * @param {string} type type to identify if it is reference search or string match serach\n     */\n    function SearchResultsView(model, panelID, panelName, type) {\n        var panelHtml  = Mustache.render(searchPanelTemplate, {panelID: panelID});\n\n        this._panel    = WorkspaceManager.createBottomPanel(panelName, $(panelHtml), 100);\n        this._$summary = this._panel.$panel.find(\".title\");\n        this._$table   = this._panel.$panel.find(\".table-container\");\n        this._model    = model;\n        this._searchResultsType = type;\n    }\n    EventDispatcher.makeEventDispatcher(SearchResultsView.prototype);\n\n    /** @type {SearchModel} The search results model we're viewing. */\n    SearchResultsView.prototype._model = null;\n\n    /**\n     * Array with content used in the Results Panel\n     * @type {Array.<{fileIndex: number, filename: string, fullPath: string, items: Array.<Object>}>}\n     */\n    SearchResultsView.prototype._searchList = [];\n\n    /** @type {Panel} Bottom panel holding the search results */\n    SearchResultsView.prototype._panel = null;\n\n    /** @type {?string} The full path of the file that was open in the main editor on the initial search */\n    SearchResultsView.prototype._initialFilePath = null;\n\n    /** @type {number} The index of the first result that is displayed */\n    SearchResultsView.prototype._currentStart = 0;\n\n    /** @type {boolean} Used to remake the replace all summary after it is changed */\n    SearchResultsView.prototype._allChecked = false;\n\n    /** @type {$.Element} The currently selected row */\n    SearchResultsView.prototype._$selectedRow = null;\n\n    /** @type {$.Element} The element where the title is placed */\n    SearchResultsView.prototype._$summary = null;\n\n    /** @type {$.Element} The table that holds the results */\n    SearchResultsView.prototype._$table = null;\n\n    /** @type {number} The ID we use for timeouts when handling model changes. */\n    SearchResultsView.prototype._timeoutID = null;\n\n    /** @type {string} The Id we use to check if it is reference search or match search */\n    SearchResultsView.prototype._searchResultsType = null;\n\n    /**\n     * @private\n     * Handles when model changes. Updates the view, buffering changes if necessary so as not to churn too much.\n     */\n    SearchResultsView.prototype._handleModelChange = function (quickChange) {\n        // If this is a replace, to avoid complications with updating, just close ourselves if we hear about\n        // a results model change after we've already shown the results initially.\n        // TODO: notify user, re-do search in file\n        if (this._model.isReplace) {\n            this.close();\n            return;\n        }\n\n        var self = this;\n        if (this._timeoutID) {\n            window.clearTimeout(this._timeoutID);\n        }\n        if (quickChange) {\n            this._timeoutID = window.setTimeout(function () {\n                self._updateResults();\n                self._timeoutID = null;\n            }, UPDATE_TIMEOUT);\n        } else {\n            this._updateResults();\n        }\n    };\n\n    /**\n     * @private\n     * Adds the listeners for close, prev, next, first, last and check all\n     */\n    SearchResultsView.prototype._addPanelListeners = function () {\n        var self = this;\n        this._panel.$panel\n            .off(\".searchResults\")  // Remove the old events\n            .on(\"dblclick.searchResults\", \".toolbar\", function() {\n                self.close();\n            })\n            .on(\"click.searchResults\", \".close\", function () {\n                self.close();\n            })\n            // The link to go the first page\n            .on(\"click.searchResults\", \".first-page:not(.disabled)\", function () {\n                self._currentStart = 0;\n                self._render();\n                HealthLogger.searchDone(HealthLogger.SEARCH_FIRST_PAGE);\n            })\n            // The link to go the previous page\n            .on(\"click.searchResults\", \".prev-page:not(.disabled)\", function () {\n                self._currentStart -= RESULTS_PER_PAGE;\n                self._render();\n                HealthLogger.searchDone(HealthLogger.SEARCH_PREV_PAGE);\n            })\n            // The link to go to the next page\n            .on(\"click.searchResults\", \".next-page:not(.disabled)\", function () {\n                self.trigger('getNextPage');\n                HealthLogger.searchDone(HealthLogger.SEARCH_NEXT_PAGE);\n            })\n            // The link to go to the last page\n            .on(\"click.searchResults\", \".last-page:not(.disabled)\", function () {\n                self.trigger('getLastPage');\n                HealthLogger.searchDone(HealthLogger.SEARCH_LAST_PAGE);\n            })\n\n            // Add the file to the working set on double click\n            .on(\"dblclick.searchResults\", \".table-container tr:not(.file-section)\", function (e) {\n                var item = self._searchList[$(this).data(\"file-index\")];\n                FileViewController.openFileAndAddToWorkingSet(item.fullPath);\n            })\n\n            // Add the click event listener directly on the table parent\n            .on(\"click.searchResults .table-container\", function (e) {\n                var $row = $(e.target).closest(\"tr\");\n\n                if ($row.length) {\n                    if (self._$selectedRow) {\n                        self._$selectedRow.removeClass(\"selected\");\n                    }\n                    $row.addClass(\"selected\");\n                    self._$selectedRow = $row;\n\n                    var searchItem = self._searchList[$row.data(\"file-index\")],\n                        fullPath   = searchItem.fullPath;\n\n                    // This is a file title row, expand/collapse on click\n                    if ($row.hasClass(\"file-section\")) {\n                        var $titleRows,\n                            collapsed = !self._model.results[fullPath].collapsed;\n\n                        if (e.metaKey || e.ctrlKey) { //Expand all / Collapse all\n                            $titleRows = $(e.target).closest(\"table\").find(\".file-section\");\n                        } else {\n                            // Clicking the file section header collapses/expands result rows for that file\n                            $titleRows = $row;\n                        }\n\n                        $titleRows.each(function () {\n                            fullPath   = self._searchList[$(this).data(\"file-index\")].fullPath;\n                            searchItem = self._model.results[fullPath];\n\n                            if (searchItem.collapsed !== collapsed) {\n                                searchItem.collapsed = collapsed;\n                                $(this).nextUntil(\".file-section\").toggle();\n                                $(this).find(\".disclosure-triangle\").toggleClass(\"expanded\");\n                            }\n                        });\n\n                        //In Expand/Collapse all, reset all search results 'collapsed' flag to same value(true/false).\n                        if (e.metaKey || e.ctrlKey) {\n                            FindUtils.setCollapseResults(collapsed);\n                            _.forEach(self._model.results, function (item) {\n                                item.collapsed = collapsed;\n                            });\n                        }\n\n                    // This is a file row, show the result on click\n                    } else {\n                        // Grab the required item data\n                        var item = searchItem.items[$row.data(\"item-index\")];\n\n                        CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath})\n                            .done(function (doc) {\n                                // Opened document is now the current main editor\n                                EditorManager.getCurrentFullEditor().setSelection(item.start, item.end, true);\n                            });\n                    }\n                }\n            });\n\n        function updateHeaderCheckbox($checkAll) {\n            var $allFileRows     = self._panel.$panel.find(\".file-section\"),\n                $checkedFileRows = $allFileRows.filter(function (index) {\n                    return $(this).find(\".check-one-file\").is(\":checked\");\n                });\n            if ($checkedFileRows.length === $allFileRows.length) {\n                $checkAll.prop(\"checked\", true);\n            }\n        }\n\n        function updateFileAndHeaderCheckboxes($clickedRow, isChecked) {\n            var $firstMatch = ($clickedRow.data(\"item-index\") === 0) ? $clickedRow :\n                    $clickedRow.prevUntil(\".file-section\").last(),\n                $fileRow = $firstMatch.prev(),\n                $siblingRows = $fileRow.nextUntil(\".file-section\"),\n                $fileCheckbox = $fileRow.find(\".check-one-file\"),\n                $checkAll = self._panel.$panel.find(\".check-all\");\n\n            if (isChecked) {\n                if (!$fileCheckbox.is(\":checked\")) {\n                    var $checkedSibilings = $siblingRows.filter(function (index) {\n                            return $(this).find(\".check-one\").is(\":checked\");\n                        });\n                    if ($checkedSibilings.length === $siblingRows.length) {\n                        $fileCheckbox.prop(\"checked\", true);\n                        if (!$checkAll.is(\":checked\")) {\n                            updateHeaderCheckbox($checkAll);\n                        }\n                    }\n                }\n            } else {\n                if ($checkAll.is(\":checked\")) {\n                    $checkAll.prop(\"checked\", false);\n                }\n                if ($fileCheckbox.is(\":checked\")) {\n                    $fileCheckbox.prop(\"checked\", false);\n                }\n            }\n        }\n\n        // Add the Click handlers for replace functionality if required\n        if (this._model.isReplace) {\n            this._panel.$panel\n                .on(\"click.searchResults\", \".check-all\", function (e) {\n                    var isChecked = $(this).is(\":checked\");\n                    _.forEach(self._model.results, function (results) {\n                        results.matches.forEach(function (match) {\n                            match.isChecked = isChecked;\n                        });\n                    });\n                    self._$table.find(\".check-one\").prop(\"checked\", isChecked);\n                    self._$table.find(\".check-one-file\").prop(\"checked\", isChecked);\n                    self._allChecked = isChecked;\n                })\n                .on(\"click.searchResults\", \".check-one-file\", function (e) {\n                    var isChecked = $(this).is(\":checked\"),\n                        $row = $(e.target).closest(\"tr\"),\n                        item = self._searchList[$row.data(\"file-index\")],\n                        $matchRows = $row.nextUntil(\".file-section\"),\n                        $checkAll = self._panel.$panel.find(\".check-all\");\n\n                    if (item) {\n                        self._model.results[item.fullPath].matches.forEach(function (match) {\n                            match.isChecked = isChecked;\n                        });\n                    }\n                    $matchRows.find(\".check-one\").prop(\"checked\", isChecked);\n                    if (!isChecked) {\n                        if ($checkAll.is(\":checked\")) {\n                            $checkAll.prop(\"checked\", false);\n                        }\n                    } else if (!$checkAll.is(\":checked\")) {\n                        updateHeaderCheckbox($checkAll);\n                    }\n                    e.stopPropagation();\n                })\n                .on(\"click.searchResults\", \".check-one\", function (e) {\n                    var $row = $(e.target).closest(\"tr\"),\n                        item = self._searchList[$row.data(\"file-index\")],\n                        match = self._model.results[item.fullPath].matches[$row.data(\"match-index\")];\n\n                    match.isChecked = $(this).is(\":checked\");\n                    updateFileAndHeaderCheckboxes($row, match.isChecked);\n                    e.stopPropagation();\n                })\n                .on(\"click.searchResults\", \".replace-checked\", function (e) {\n                    self.trigger(\"replaceBatch\");\n                });\n        }\n    };\n\n\n    /**\n     * @private\n     * Shows the Results Summary\n     */\n    SearchResultsView.prototype._showSummary = function () {\n        var count     = this._model.countFilesMatches(),\n            lastIndex = this._getLastIndex(count.matches),\n            typeStr = (count.matches > 1) ? Strings.FIND_IN_FILES_MATCHES : Strings.FIND_IN_FILES_MATCH,\n            filesStr,\n            summary;\n\n        if(this._searchResultsType === \"reference\") {\n            typeStr = (count.matches > 1) ? Strings.REFERENCES_IN_FILES : Strings.REFERENCE_IN_FILES;\n        }\n\n        filesStr = StringUtils.format(\n            Strings.FIND_NUM_FILES,\n            count.files,\n            (count.files > 1 ? Strings.FIND_IN_FILES_FILES : Strings.FIND_IN_FILES_FILE)\n        );\n\n        // This text contains some formatting, so all the strings are assumed to be already escaped\n        summary = StringUtils.format(\n            Strings.FIND_TITLE_SUMMARY,\n            this._model.exceedsMaximum ? Strings.FIND_IN_FILES_MORE_THAN : \"\",\n            String(count.matches),\n            typeStr,\n            filesStr\n        );\n\n        this._$summary.html(Mustache.render(searchSummaryTemplate, {\n            query:       (this._model.queryInfo && this._model.queryInfo.query && this._model.queryInfo.query.toString()) || \"\",\n            replaceWith: this._model.replaceText,\n            titleLabel:  this._model.isReplace ? Strings.FIND_REPLACE_TITLE_LABEL : Strings.FIND_TITLE_LABEL,\n            scope:       this._model.scope ? \"&nbsp;\" + FindUtils.labelForScope(this._model.scope) + \"&nbsp;\" : \"\",\n            summary:     summary,\n            allChecked:  this._allChecked,\n            hasPages:    count.matches > RESULTS_PER_PAGE,\n            results:     StringUtils.format(Strings.FIND_IN_FILES_PAGING, this._currentStart + 1, lastIndex),\n            hasPrev:     this._currentStart > 0,\n            hasNext:     lastIndex < count.matches,\n            replace:     this._model.isReplace,\n            Strings:     Strings\n        }));\n    };\n\n    /**\n     * @private\n     * Shows the current set of results.\n     */\n    SearchResultsView.prototype._render = function () {\n        var searchItems, match, i, item, multiLine,\n            count            = this._model.countFilesMatches(),\n            searchFiles      = this._model.prioritizeOpenFile(this._initialFilePath),\n            lastIndex        = this._getLastIndex(count.matches),\n            matchesCounter   = 0,\n            showMatches      = false,\n            allInFileChecked = true,\n            self             = this;\n\n        this._showSummary();\n        this._searchList = [];\n\n        // Iterates throuh the files to display the results sorted by filenamess. The loop ends as soon as\n        // we filled the results for one page\n        searchFiles.some(function (fullPath) {\n            showMatches = true;\n            item = self._model.results[fullPath];\n\n            // Since the amount of matches on this item plus the amount of matches we skipped until\n            // now is still smaller than the first match that we want to display, skip these.\n            if (matchesCounter + item.matches.length < self._currentStart) {\n                matchesCounter += item.matches.length;\n                showMatches = false;\n\n            // If we still haven't skipped enough items to get to the first match, but adding the\n            // item matches to the skipped ones is greater the the first match we want to display,\n            // then we can display the matches from this item skipping the first ones\n            } else if (matchesCounter < self._currentStart) {\n                i = self._currentStart - matchesCounter;\n                matchesCounter = self._currentStart;\n\n            // If we already skipped enough matches to get to the first match to display, we can start\n            // displaying from the first match of this item\n            } else if (matchesCounter < lastIndex) {\n                i = 0;\n\n            // We can't display more items by now. Break the loop\n            } else {\n                return true;\n            }\n\n            if (showMatches && i < item.matches.length) {\n                // Add a row for each match in the file\n                searchItems = [];\n\n                allInFileChecked = true;\n                // Add matches until we get to the last match of this item, or filling the page\n                while (i < item.matches.length && matchesCounter < lastIndex) {\n                    match     = item.matches[i];\n                    multiLine = match.start.line !== match.end.line;\n\n                    searchItems.push({\n                        fileIndex:   self._searchList.length,\n                        itemIndex:   searchItems.length,\n                        matchIndex:  i,\n                        line:        match.start.line + 1,\n                        pre:         match.line.substr(0, match.start.ch - match.highlightOffset),\n                        highlight:   match.line.substring(match.start.ch - match.highlightOffset, multiLine ? undefined : match.end.ch - match.highlightOffset),\n                        post:        multiLine ? \"\\u2026\" : match.line.substr(match.end.ch - match.highlightOffset),\n                        start:       match.start,\n                        end:         match.end,\n                        isChecked:   match.isChecked,\n                        isCollapsed: item.collapsed\n                    });\n                    if (!match.isChecked) {\n                        allInFileChecked = false;\n                    }\n                    matchesCounter++;\n                    i++;\n                }\n\n                // Add a row for each file\n                var relativePath    = FileUtils.getDirectoryPath(ProjectManager.makeProjectRelativeIfPossible(fullPath)),\n                    directoryPath   = FileUtils.getDirectoryPath(relativePath),\n                    displayFileName = StringUtils.format(\n                        Strings.FIND_IN_FILES_FILE_PATH,\n                        StringUtils.breakableUrl(FileUtils.getBaseName(fullPath)),\n                        StringUtils.breakableUrl(directoryPath),\n                        directoryPath ? \"&mdash;\" : \"\"\n                    );\n\n                self._searchList.push({\n                    fileIndex:   self._searchList.length,\n                    filename:    displayFileName,\n                    fullPath:    fullPath,\n                    isChecked:   allInFileChecked,\n                    items:       searchItems,\n                    isCollapsed: item.collapsed\n                });\n            }\n        });\n\n\n        // Insert the search results\n        this._$table\n            .empty()\n            .append(Mustache.render(searchResultsTemplate, {\n                replace:       this._model.isReplace,\n                searchList:    this._searchList,\n                Strings:       Strings\n            }));\n\n        if (this._$selectedRow) {\n            this._$selectedRow.removeClass(\"selected\");\n            this._$selectedRow = null;\n        }\n\n        this._panel.show();\n        this._$table.scrollTop(0); // Otherwise scroll pos from previous contents is remembered\n    };\n\n    /**\n     * Updates the results view after a model change, preserving scroll position and selection.\n     */\n    SearchResultsView.prototype._updateResults = function () {\n        // In general this shouldn't get called if the panel is closed, but in case some\n        // asynchronous process kicks this (e.g. a debounced model change), we double-check.\n        if (this._panel.isVisible()) {\n            var scrollTop  = this._$table.scrollTop(),\n                index      = this._$selectedRow ? this._$selectedRow.index() : null,\n                numMatches = this._model.countFilesMatches().matches;\n\n            if (this._currentStart > numMatches) {\n                this._currentStart = this._getLastCurrentStart(numMatches);\n            }\n\n            this._render();\n\n            this._$table.scrollTop(scrollTop);\n            if (index) {\n                this._$selectedRow = this._$table.find(\"tr:eq(\" + index + \")\");\n                this._$selectedRow.addClass(\"selected\");\n            }\n        }\n    };\n\n    /**\n     * @private\n     * Returns one past the last result index displayed for the current page.\n     * @param {number} numMatches\n     * @return {number}\n     */\n    SearchResultsView.prototype._getLastIndex = function (numMatches) {\n        return Math.min(this._currentStart + RESULTS_PER_PAGE, numMatches);\n    };\n\n    /**\n     * Shows the next page of the resultrs view if possible\n     */\n    SearchResultsView.prototype.showNextPage = function () {\n        this._currentStart += RESULTS_PER_PAGE;\n        this._render();\n    };\n\n    /**\n     * Shows the last page of the results view.\n     */\n    SearchResultsView.prototype.showLastPage = function () {\n        this._currentStart = this._getLastCurrentStart();\n        this._render();\n    };\n\n    /**\n     * @private\n     * Returns the last possible current start based on the given number of matches\n     * @param {number=} numMatches\n     * @return {number}\n     */\n    SearchResultsView.prototype._getLastCurrentStart = function (numMatches) {\n        numMatches = numMatches || this._model.countFilesMatches().matches;\n        return Math.floor((numMatches - 1) / RESULTS_PER_PAGE) * RESULTS_PER_PAGE;\n    };\n\n    /**\n     * Opens the results panel and displays the current set of results from the model.\n     */\n    SearchResultsView.prototype.open = function () {\n        // Clear out any paging/selection state.\n        this._currentStart  = 0;\n        this._$selectedRow  = null;\n        this._allChecked    = true;\n\n        // Save the currently open document's fullpath, if any, so we can sort it to the top of the result list.\n        var currentDoc = DocumentManager.getCurrentDocument();\n        this._initialFilePath = currentDoc ? currentDoc.file.fullPath : null;\n\n        this._render();\n\n        // Listen for user interaction events with the panel and change events from the model.\n        this._addPanelListeners();\n        this._model.on(\"change.SearchResultsView\", this._handleModelChange.bind(this));\n    };\n\n    /**\n     * Hides the Search Results Panel and unregisters listeners.\n     */\n    SearchResultsView.prototype.close = function () {\n        if (this._panel && this._panel.isVisible()) {\n            this._$table.empty();\n            this._panel.hide();\n            this._panel.$panel.off(\".searchResults\");\n            this._model.off(\"change.SearchResultsView\");\n            this.trigger(\"close\");\n        }\n    };\n\n    // Public API\n    exports.SearchResultsView = SearchResultsView;\n});\n"
  },
  {
    "path": "src/search/node/FindInFilesDomain.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n/*global setImmediate */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n    projectCache = [],\n    files,\n    _domainManager,\n    MAX_FILE_SIZE_TO_INDEX = 16777216, //16MB\n    MAX_DISPLAY_LENGTH = 200,\n    MAX_TOTAL_RESULTS = 100000, // only 100,000 search results are supported\n    MAX_RESULTS_IN_A_FILE = MAX_TOTAL_RESULTS,\n    MAX_RESULTS_TO_RETURN = 120;\n\nvar results = {},\n    numMatches = 0,\n    numFiles = 0,\n    evaluatedMatches,\n    foundMaximum = false,\n    exceedsMaximum = false,\n    currentCrawlIndex = 0,\n    savedSearchObject = null,\n    lastSearchedIndex = 0,\n    crawlComplete = false,\n    crawlEventSent = false,\n    collapseResults = false,\n    cacheSize = 0;\n\n/**\n * Copied from StringUtils.js\n * Returns a line number corresponding to an offset in some text. The text can\n * be specified as a single string or as an array of strings that correspond to\n * the lines of the string.\n *\n * Specify the text in lines when repeatedly calling the function on the same\n * text in a loop. Use getLines() to divide the text into lines, then repeatedly call\n * this function to compute a line number from the offset.\n *\n * @param {string | Array.<string>} textOrLines - string or array of lines from which\n *      to compute the line number from the offset\n * @param {number} offset\n * @return {number} line number\n */\nfunction offsetToLineNum(textOrLines, offset) {\n    if (Array.isArray(textOrLines)) {\n        var lines = textOrLines,\n            total = 0,\n            line;\n        for (line = 0; line < lines.length; line++) {\n            if (total < offset) {\n                // add 1 per line since /n were removed by splitting, but they needed to\n                // contribute to the total offset count\n                total += lines[line].length + 1;\n            } else if (total === offset) {\n                return line;\n            } else {\n                return line - 1;\n            }\n        }\n\n        // if offset is NOT over the total then offset is in the last line\n        if (offset <= total) {\n            return line - 1;\n        } else {\n            return undefined;\n        }\n    } else {\n        return textOrLines.substr(0, offset).split(\"\\n\").length - 1;\n    }\n}\n\n/**\n * Searches through the contents and returns an array of matches\n * @param {string} contents\n * @param {RegExp} queryExpr\n * @return {!Array.<{start: {line:number,ch:number}, end: {line:number,ch:number}, line: string}>}\n */\nfunction getSearchMatches(contents, queryExpr) {\n    if (!contents) {\n        return;\n    }\n    // Quick exit if not found or if we hit the limit\n    if (foundMaximum || contents.search(queryExpr) === -1) {\n        return [];\n    }\n\n    var match, lineNum, line, ch, totalMatchLength, matchedLines, numMatchedLines, lastLineLength, endCh,\n        padding, leftPadding, rightPadding, highlightOffset, highlightEndCh,\n        lines   = contents.split(\"\\n\"),\n        matches = [];\n\n    while ((match = queryExpr.exec(contents)) !== null) {\n        lineNum          = offsetToLineNum(lines, match.index);\n        line             = lines[lineNum];\n        ch               = match.index - contents.lastIndexOf(\"\\n\", match.index) - 1;  // 0-based index\n        matchedLines     = match[0].split(\"\\n\");\n        numMatchedLines  = matchedLines.length;\n        totalMatchLength = match[0].length;\n        lastLineLength   = matchedLines[matchedLines.length - 1].length;\n        endCh            = (numMatchedLines === 1 ? ch + totalMatchLength : lastLineLength);\n        highlightEndCh   = (numMatchedLines === 1 ? endCh : line.length);\n        highlightOffset  = 0;\n\n        if (highlightEndCh <= MAX_DISPLAY_LENGTH) {\n            // Don't store more than 200 chars per line\n            line = line.substr(0, Math.min(MAX_DISPLAY_LENGTH, line.length));\n        } else if (totalMatchLength > MAX_DISPLAY_LENGTH) {\n            // impossible to display the whole match\n            line = line.substr(ch, ch + MAX_DISPLAY_LENGTH);\n            highlightOffset = ch;\n        } else {\n            // Try to have both beginning and end of match displayed\n            padding = MAX_DISPLAY_LENGTH - totalMatchLength;\n            rightPadding = Math.floor(Math.min(padding / 2, line.length - highlightEndCh));\n            leftPadding = Math.ceil(padding - rightPadding);\n            highlightOffset = ch - leftPadding;\n            line = line.substring(highlightOffset, highlightEndCh + rightPadding);\n        }\n\n        matches.push({\n            start:       {line: lineNum, ch: ch},\n            end:         {line: lineNum + numMatchedLines - 1, ch: endCh},\n\n            highlightOffset: highlightOffset,\n\n            // Note that the following offsets from the beginning of the file are *not* updated if the search\n            // results change. These are currently only used for multi-file replacement, and we always\n            // abort the replace (by shutting the results panel) if we detect any result changes, so we don't\n            // need to keep them up to date. Eventually, we should either get rid of the need for these (by\n            // doing everything in terms of line/ch offsets, though that will require re-splitting files when\n            // doing a replace) or properly update them.\n            startOffset: match.index,\n            endOffset:   match.index + totalMatchLength,\n\n            line:        line,\n            result:      match,\n            isChecked:   true\n        });\n\n        // We have the max hits in just this 1 file. Stop searching this file.\n        // This fixed issue #1829 where code hangs on too many hits.\n        // Adds one over MAX_RESULTS_IN_A_FILE in order to know if the search has exceeded\n        // or is equal to MAX_RESULTS_IN_A_FILE. Additional result removed in SearchModel\n        if (matches.length > MAX_RESULTS_IN_A_FILE) {\n            queryExpr.lastIndex = 0;\n            break;\n        }\n\n        // Pathological regexps like /^/ return 0-length matches. Ensure we make progress anyway\n        if (totalMatchLength === 0) {\n            queryExpr.lastIndex++;\n        }\n    }\n\n    return matches;\n}\n\n/**\n * Clears the cached file contents of the project\n */\nfunction clearProjectCache() {\n    projectCache = [];\n}\n\n\n/**\n * Gets the file size in bytes.\n * @param   {string} fileName The name of the file to get the size\n * @returns {Number} the file size in bytes\n */\nfunction getFilesizeInBytes(fileName) {\n    try {\n        var stats = fs.statSync(fileName);\n        return stats.size || 0;\n    } catch (ex) {\n        console.log(ex);\n        return 0;\n    }\n}\n\n/**\n * Get the contents of a file from cache given the path. Also adds the file contents to cache from disk if not cached.\n * Will not read/cache files greater than MAX_FILE_SIZE_TO_INDEX in size.\n * @param   {string} filePath full file path\n * @return {string} contents or null if no contents\n */\nfunction getFileContentsForFile(filePath) {\n    if (projectCache[filePath] || projectCache[filePath] === \"\") {\n        return projectCache[filePath];\n    }\n    try {\n        if (getFilesizeInBytes(filePath) <= MAX_FILE_SIZE_TO_INDEX) {\n            projectCache[filePath] = fs.readFileSync(filePath, 'utf8');\n        } else {\n            projectCache[filePath] = \"\";\n        }\n    } catch (ex) {\n        console.log(ex);\n        projectCache[filePath] = null;\n    }\n    return projectCache[filePath];\n}\n\n/**\n * Sets the list of matches for the given path, removing the previous match info, if any, and updating\n * the total match count. Note that for the count to remain accurate, the previous match info must not have\n * been mutated since it was set.\n * @param {string} fullpath Full path to the file containing the matches.\n * @param {!{matches: Object, collapsed: boolean=}} resultInfo Info for the matches to set:\n *      matches - Array of matches, in the format returned by FindInFiles.getSearchMatches()\n *      collapsed - Optional: whether the results should be collapsed in the UI (default false).\n */\nfunction setResults(fullpath, resultInfo, maxResultsToReturn) {\n    if (results[fullpath]) {\n        numMatches -= results[fullpath].matches.length;\n        delete results[fullpath];\n    }\n\n    if (foundMaximum || !resultInfo || !resultInfo.matches || !resultInfo.matches.length) {\n        return;\n    }\n\n    // Make sure that the optional `collapsed` property is explicitly set to either true or false,\n    // to avoid logic issues later with comparing values.\n    resultInfo.collapsed = collapseResults;\n\n    results[fullpath] = resultInfo;\n    numMatches += resultInfo.matches.length;\n    evaluatedMatches += resultInfo.matches.length;\n    maxResultsToReturn = maxResultsToReturn || MAX_RESULTS_TO_RETURN;\n    if (numMatches >= maxResultsToReturn || evaluatedMatches > MAX_TOTAL_RESULTS) {\n        foundMaximum = true;\n    }\n}\n\n/**\n * Finds search results in the given file and adds them to 'results'\n * @param {string} filepath\n * @param {string} text   contents of the file\n * @param {Object} queryExpr\n * @param {number} maxResultsToReturn the maximum of results that should be returned in the current search.\n */\nfunction doSearchInOneFile(filepath, text, queryExpr, maxResultsToReturn) {\n    var matches = getSearchMatches(text, queryExpr);\n    setResults(filepath, {matches: matches}, maxResultsToReturn);\n}\n\n/**\n * Search in the list of files given and populate the results\n * @param {array} fileList           array of file paths\n * @param {Object} queryExpr\n * @param {number} startFileIndex    the start index of the array from which the search has to be done\n * @param {number} maxResultsToReturn  the maximum number of results to return in this search\n */\nfunction doSearchInFiles(fileList, queryExpr, startFileIndex, maxResultsToReturn) {\n    var i;\n    if (fileList.length === 0) {\n        console.log('no files found');\n        return;\n\n    } else {\n        startFileIndex = startFileIndex || 0;\n        for (i = startFileIndex; i < fileList.length && !foundMaximum; i++) {\n            doSearchInOneFile(fileList[i], getFileContentsForFile(fileList[i]), queryExpr, maxResultsToReturn);\n        }\n        lastSearchedIndex = i;\n    }\n}\n\n// Copied from StringUtils.js\nfunction regexEscape(str) {\n    return str.replace(/([.?*+\\^$\\[\\]\\\\(){}|\\-])/g, \"\\\\$1\");\n}\n\n/**\n * Parses the given query into a regexp, and returns whether it was valid or not.\n * @param {{query: string, caseSensitive: boolean, isRegexp: boolean}} queryInfo\n * @return {{queryExpr: RegExp, valid: boolean, empty: boolean, error: string}}\n *      queryExpr - the regexp representing the query\n *      valid - set to true if query is a nonempty string or a valid regexp.\n *      empty - set to true if query was empty.\n *      error - set to an error string if valid is false and query is nonempty.\n */\nfunction parseQueryInfo(queryInfo) {\n    var queryExpr;\n\n    // TODO: only major difference between this one and the one in FindReplace is that\n    // this always returns a regexp even for simple strings. Reconcile.\n    if (!queryInfo || !queryInfo.query) {\n        return {empty: true};\n    }\n\n    // For now, treat all matches as multiline (i.e. ^/$ match on every line, not the whole\n    // document). This is consistent with how single-file find works. Eventually we should add\n    // an option for this.\n    var flags = \"gm\";\n    if (!queryInfo.isCaseSensitive) {\n        flags += \"i\";\n    }\n\n    // Is it a (non-blank) regex?\n    if (queryInfo.isRegexp) {\n        try {\n            queryExpr = new RegExp(queryInfo.query, flags);\n        } catch (e) {\n            return {valid: false, error: e.message};\n        }\n    } else {\n        // Query is a plain string. Turn it into a regexp\n        queryExpr = new RegExp(regexEscape(queryInfo.query), flags);\n    }\n    return {valid: true, queryExpr: queryExpr};\n}\n\n/**\n * Crawls through the files in the project ans stores them in cache. Since that could take a while\n * we do it in batches so that node wont be blocked.\n */\nfunction fileCrawler() {\n    if (!files || (files && files.length === 0)) {\n        setTimeout(fileCrawler, 1000);\n        return;\n    }\n    var contents = \"\";\n    if (currentCrawlIndex < files.length) {\n        contents = getFileContentsForFile(files[currentCrawlIndex]);\n        if (contents) {\n            cacheSize += contents.length;\n        }\n        currentCrawlIndex++;\n    }\n    if (currentCrawlIndex < files.length) {\n        crawlComplete = false;\n        setImmediate(fileCrawler);\n    } else {\n        crawlComplete = true;\n        if (!crawlEventSent) {\n            crawlEventSent = true;\n            _domainManager.emitEvent(\"FindInFiles\", \"crawlComplete\", [files.length, cacheSize]);\n        }\n        setTimeout(fileCrawler, 1000);\n    }\n}\n\n/**\n * Init for project, resets the old project cache, and sets the crawler function to\n * restart the file crawl\n * @param   {array} fileList an array of files\n */\nfunction initCache(fileList) {\n    files = fileList;\n    currentCrawlIndex = 0;\n    cacheSize = 0;\n    clearProjectCache();\n    crawlEventSent = false;\n}\n\n/**\n * Counts the number of matches matching the queryExpr in the given contents\n * @param   {String} contents  The contents to search on\n * @param   {Object} queryExpr\n * @return {number} number of matches\n */\nfunction countNumMatches(contents, queryExpr) {\n    if (!contents) {\n        return 0;\n    }\n    var matches = contents.match(queryExpr);\n    return matches ? matches.length : 0;\n}\n\n/**\n * Get the total number of matches from all the files in fileList\n * @param   {array} fileList  file path array\n * @param   {Object} queryExpr\n * @return {Number} total number of matches\n */\nfunction getNumMatches(fileList, queryExpr) {\n    var i,\n        matches = 0;\n    for (i = 0; i < fileList.length; i++) {\n        var temp = countNumMatches(getFileContentsForFile(fileList[i]), queryExpr);\n        if (temp) {\n            numFiles++;\n            matches += temp;\n        }\n        if (matches > MAX_TOTAL_RESULTS) {\n            exceedsMaximum = true;\n            break;\n        }\n    }\n    return matches;\n}\n\n/**\n * Do a search with the searchObject context and return the results\n * @param   {Object}   searchObject\n * @param   {boolean} nextPages    set to true if to indicate that next page of an existing page is being fetched\n * @return {Object}   search results\n */\nfunction doSearch(searchObject, nextPages) {\n\n    savedSearchObject = searchObject;\n    if (!files) {\n        console.log(\"no file object found\");\n        return {};\n    }\n    results = {};\n    numMatches = 0;\n    numFiles = 0;\n    foundMaximum = false;\n    if (!nextPages) {\n        exceedsMaximum = false;\n        evaluatedMatches = 0;\n    }\n    var queryObject = parseQueryInfo(searchObject.queryInfo);\n    if (searchObject.files) {\n        files = searchObject.files;\n    }\n    if (searchObject.getAllResults) {\n        searchObject.maxResultsToReturn = MAX_TOTAL_RESULTS;\n    }\n    doSearchInFiles(files, queryObject.queryExpr, searchObject.startFileIndex, searchObject.maxResultsToReturn);\n    if (crawlComplete && !nextPages) {\n        numMatches = getNumMatches(files, queryObject.queryExpr);\n    }\n    var send_object = {\n        \"results\":  results,\n        \"foundMaximum\":  foundMaximum,\n        \"exceedsMaximum\":  exceedsMaximum\n    };\n\n    if (!nextPages) {\n        send_object.numMatches = numMatches;\n        send_object.numFiles = numFiles;\n    }\n\n    if (searchObject.getAllResults) {\n        send_object.allResultsAvailable = true;\n    }\n    return send_object;\n}\n\n/**\n * Remove the list of given files from the project cache\n * @param   {Object}   updateObject\n */\nfunction removeFilesFromCache(updateObject) {\n    var fileList = updateObject.fileList || [],\n        filesInSearchScope = updateObject.filesInSearchScope || [],\n        i = 0;\n    for (i = 0; i < fileList.length; i++) {\n        delete projectCache[fileList[i]];\n    }\n    function isNotInRemovedFilesList(path) {\n        return (filesInSearchScope.indexOf(path) === -1) ? true : false;\n    }\n    files = files ? files.filter(isNotInRemovedFilesList) : files;\n}\n\n/**\n * Adds the list of given files to the project cache. However the files will not be\n * read at this time. We just delete the project cache entry which will trigger a fetch on search.\n * @param   {Object}   updateObject\n */\nfunction addFilesToCache(updateObject) {\n    var fileList = updateObject.fileList || [],\n        filesInSearchScope = updateObject.filesInSearchScope || [],\n        i = 0,\n        changedFilesAlreadyInList = [],\n        newFiles = [];\n    for (i = 0; i < fileList.length; i++) {\n        // We just add a null entry indicating the precense of the file in the project list.\n        // The file will be later read when required.\n        projectCache[fileList[i]] = null;\n    }\n\n    //Now update the search scope\n    function isInChangedFileList(path) {\n        return (filesInSearchScope.indexOf(path) !== -1) ? true : false;\n    }\n    changedFilesAlreadyInList = files ? files.filter(isInChangedFileList) : [];\n    function isNotAlreadyInList(path) {\n        return (changedFilesAlreadyInList.indexOf(path) === -1) ? true : false;\n    }\n    newFiles = changedFilesAlreadyInList.filter(isNotAlreadyInList);\n    files.push.apply(files, newFiles);\n}\n\n/**\n * Notification function on document changed, we update the cache with the contents\n * @param {Object} updateObject\n */\nfunction documentChanged(updateObject) {\n    projectCache[updateObject.filePath] = updateObject.docContents;\n}\n\n/**\n * Gets the next page of results of the ongoing search\n * @return {Object} search results\n */\nfunction getNextPage() {\n    var send_object = {\n        \"results\":  {},\n        \"numMatches\": 0,\n        \"foundMaximum\":  foundMaximum,\n        \"exceedsMaximum\":  exceedsMaximum\n    };\n    if (!savedSearchObject) {\n        return send_object;\n    }\n    savedSearchObject.startFileIndex = lastSearchedIndex;\n    return doSearch(savedSearchObject, true);\n}\n\n/**\n * Gets all the results for the saved search query if present or empty search results\n * @return {Object} The results object\n */\nfunction getAllResults() {\n    var send_object = {\n        \"results\":  {},\n        \"numMatches\": 0,\n        \"foundMaximum\":  foundMaximum,\n        \"exceedsMaximum\":  exceedsMaximum\n    };\n    if (!savedSearchObject) {\n        return send_object;\n    }\n    savedSearchObject.startFileIndex = 0;\n    savedSearchObject.getAllResults = true;\n    return doSearch(savedSearchObject);\n}\n\n/**\n * Sets if the results should be collapsed\n * @param {boolean} collapse true to collapse\n */\nfunction setCollapseResults(collapse) {\n    collapseResults = collapse;\n}\n\n/**\n * Initialize the test domain with commands and events related to find in files.\n * @param {DomainManager} domainManager The DomainManager for the find in files domain \"FindInFiles\"\n */\nfunction init(domainManager) {\n    if (!domainManager.hasDomain(\"FindInFiles\")) {\n        domainManager.registerDomain(\"FindInFiles\", {major: 0, minor: 1});\n    }\n    _domainManager = domainManager;\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"doSearch\",    // command name\n        doSearch,   // command handler function\n        false,          // this command is synchronous in Node\n        \"Searches in project files and returns matches\",\n        [{name: \"searchObject\", // parameters\n            type: \"object\",\n            description: \"Object containing search data\"}],\n        [{name: \"searchResults\", // return values\n            type: \"object\",\n            description: \"Object containing results of the search\"}]\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"nextPage\",    // command name\n        getNextPage,   // command handler function\n        false,          // this command is synchronous in Node\n        \"get the next page of reults\",\n        [],\n        [{name: \"searchResults\", // return values\n            type: \"object\",\n            description: \"Object containing results of the search\"}]\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"getAllResults\",    // command name\n        getAllResults,   // command handler function\n        false,          // this command is synchronous in Node\n        \"get the next page of reults\",\n        [],\n        [{name: \"searchResults\", // return values\n            type: \"object\",\n            description: \"Object containing all results of the search\"}]\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"collapseResults\",    // command name\n        setCollapseResults,   // command handler function\n        false,          // this command is synchronous in Node\n        \"get the next page of reults\",\n        [{name: \"collapse\", // return values\n            type: \"boolean\",\n            description: \"true to collapse\"}],\n        []\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"filesChanged\",    // command name\n        addFilesToCache,   // command handler function\n        false,          // this command is synchronous in Node\n        \"files in the project has been changed, update cache\",\n        [{name: \"updateObject\", // parameters\n            type: \"object\",\n            description: \"Object containing list of changed files\"}],\n        []\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"documentChanged\",    // command name\n        documentChanged,   // command handler function\n        false,          // this command is synchronous in Node\n        \"informs that the document changed and updates the cache\",\n        [{name: \"updateObject\", // parameters\n            type: \"object\",\n            description: \"update with the contents of the object\"}],\n        []\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"filesRemoved\",    // command name\n        removeFilesFromCache,   // command handler function\n        false,          // this command is synchronous in Node\n        \"Searches in project files and returns matches\",\n        [{name: \"updateObject\", // parameters\n            type: \"object\",\n            description: \"Object containing list of removed files\"}],\n        []\n    );\n    domainManager.registerCommand(\n        \"FindInFiles\",       // domain name\n        \"initCache\",    // command name\n        initCache,   // command handler function\n        false,          // this command is synchronous in Node\n        \"Caches the project for find in files in node\",\n        [{name: \"fileList\", // parameters\n            type: \"Array\",\n            description: \"List of all project files - Path only\"}],\n        []\n    );\n    domainManager.registerEvent(\n        \"FindInFiles\",     // domain name\n        \"crawlComplete\",   // event name\n        [\n            {\n                name: \"numFiles\",\n                type: \"number\",\n                description: \"number of files cached\"\n            },\n            {\n                name: \"cacheSize\",\n                type: \"number\",\n                description: \"The size of the file cache epressesd as string length of files\"\n            }\n        ]\n    );\n    setTimeout(fileCrawler, 5000);\n}\n\nexports.init = init;\n"
  },
  {
    "path": "src/strings.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * This file provides the interface to user visible strings in Brackets. Code that needs\n * to display strings should should load this module by calling `var Strings = require(\"strings\")`.\n * The i18n plugin will dynamically load the strings for the right locale and populate\n * the exports variable. See src\\nls\\strings.js for the master file of English strings.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var strings     = require(\"i18n!nls/strings\"),\n        urls        = require(\"i18n!nls/urls\"),\n        stringsApp  = require(\"i18n!nls/strings-app\"),\n        StringUtils = require(\"utils/StringUtils\");\n\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    // Add URLs as additional globals\n    var additionalGlobals = $.extend({}, urls),\n        parsedVersion = /([0-9]+)\\.([0-9]+)\\.([0-9]+)/.exec(brackets.metadata.version);\n\n    additionalGlobals.APP_NAME      = brackets.metadata.name || strings.APP_NAME;\n    additionalGlobals.APP_TITLE     = brackets.config.app_title || strings.APP_NAME;\n    additionalGlobals.TWITTER_NAME  = brackets.config.twitter_name;\n    additionalGlobals.VERSION       = brackets.metadata.version;\n    additionalGlobals.VERSION_MAJOR = parsedVersion[1];\n    additionalGlobals.VERSION_MINOR = parsedVersion[2];\n    additionalGlobals.VERSION_PATCH = parsedVersion[3];\n\n    var isDevBuild = !StringUtils.endsWith(decodeURI(window.location.pathname), \"/www/index.html\");\n    if (isDevBuild) {\n        additionalGlobals.BUILD_TYPE = strings.DEVELOPMENT_BUILD;\n    } else {\n        if (brackets.config.buildtype === 'production') {\n            additionalGlobals.BUILD_TYPE = strings.RELEASE_BUILD;\n        } else {\n            additionalGlobals.BUILD_TYPE = strings.PRERELEASE_BUILD;\n        }\n    }\n\n    // Insert application strings\n    _.forEach(strings, function (value, key) {\n        _.forEach(additionalGlobals, function (item, name) {\n            strings[key] = strings[key].replace(new RegExp(\"{\" + name + \"}\", \"g\"), additionalGlobals[name]);\n        });\n    });\n\n    // Append or overlay additional, product-specific strings\n    _.forEach(stringsApp, function (value, key) {\n        _.forEach(additionalGlobals, function (item, name) {\n            stringsApp[key] = stringsApp[key].replace(new RegExp(\"{\" + name + \"}\", \"g\"), additionalGlobals[name]);\n        });\n        strings[key] = stringsApp[key];\n    });\n\n    module.exports = strings;\n\n});\n"
  },
  {
    "path": "src/styles/Makefile",
    "content": "#\n# Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n#  \n# Permission is hereby granted, free of charge, to any person obtaining a\n# copy of this software and associated documentation files (the \"Software\"), \n# to deal in the Software without restriction, including without limitation \n# the rights to use, copy, modify, merge, publish, distribute, sublicense, \n# and/or sell copies of the Software, and to permit persons to whom the \n# Software is furnished to do so, subject to the following conditions:\n#  \n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#  \n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n# DEALINGS IN THE SOFTWARE.\n# \n#\n\n\n# input filenames \nBRACKETS_LESS = ../brackets.less\n\n# output filenames\nBRACKETS_CSS = ../brackets.css\nBRACKETS_CSS_MIN = ../brackets.min.css\n\nDATE=$(shell DATE)\nLESS_COMPRESSOR ?= `which lessc`\nWATCHR ?= `which watchr`\n\nbuild:\n\t@@if test ! -z ${LESS_COMPRESSOR}; then \\\n\t\tsed -e 's/@DATE/'\"${DATE}\"'/' <${BRACKETS_LESS} >${BRACKETS_LESS}.tmp; \\\n\t\tlessc ${BRACKETS_LESS}.tmp > ${BRACKETS_CSS}; \\\n\t\tlessc ${BRACKETS_LESS}.tmp > ${BRACKETS_CSS_MIN} --compress; \\\n\t\trm -f ${BRACKETS_LESS}.tmp; \\\n\t\techo \"brackets-app css successfully built! - `date`\"; \\\n\telse \\\n\t\techo \"You must have the LESS compiler installed in order to build Bootstrap.\"; \\\n\t\techo \"You can install it by running: npm install less -g\"; \\\n\tfi\n\nwatch:\n\t@@if test ! -z ${WATCHR}; then \\\n\t  echo \"Watching less files...\"; \\\n\t  watchr -e \"watch('lib/.*\\.less') { system 'make' }\"; \\\n\telse \\\n\t\techo \"You must have the watchr installed in order to watch Bootstrap less files.\"; \\\n\t\techo \"You can install it by running: gem install watchr\"; \\\n\tfi\n\n.PHONY: build watch"
  },
  {
    "path": "src/styles/bootstrap/accordion.less",
    "content": "//\n// Accordion\n// --------------------------------------------------\n\n\n// Parent container\n.accordion {\n  margin-bottom: @baseLineHeight;\n}\n\n// Group == heading + body\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  .border-radius(@baseBorderRadius);\n}\n.accordion-heading {\n  border-bottom: 0;\n}\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n\n// General toggle styles\n.accordion-toggle {\n  cursor: pointer;\n}\n\n// Inner needs the styles because you can't animate properly with any styles on the element\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/alerts.less",
    "content": "//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: @baseLineHeight;\n  text-shadow: 0 1px 0 rgba(255,255,255,.5);\n  background-color: @warningBackground;\n  border: 1px solid @warningBorder;\n  .border-radius(@baseBorderRadius);\n}\n.alert,\n.alert h4 {\n  // Specified for the h4 to prevent conflicts of changing @headingsColor\n  color: @warningText;\n}\n.alert h4 {\n  margin: 0;\n}\n\n// Adjust close link position\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: @baseLineHeight;\n}\n\n\n// Alternate styles\n// -------------------------\n\n.alert-success {\n  background-color: @successBackground;\n  border-color: @successBorder;\n  color: @successText;\n}\n.alert-success h4 {\n  color: @successText;\n}\n.alert-danger,\n.alert-error {\n  background-color: @errorBackground;\n  border-color: @errorBorder;\n  color: @errorText;\n}\n.alert-danger h4,\n.alert-error h4 {\n  color: @errorText;\n}\n.alert-info {\n  background-color: @infoBackground;\n  border-color: @infoBorder;\n  color: @infoText;\n}\n.alert-info h4 {\n  color: @infoText;\n}\n\n\n// Block alerts\n// -------------------------\n\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n.alert-block p + p {\n  margin-top: 5px;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/bootstrap.less",
    "content": "/*!\n * Bootstrap v2.3.1\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\n// Core variables and mixins\n@import \"variables.less\"; // Modify this for custom colors, font-sizes, etc\n@import \"mixins.less\";\n\n// CSS Reset\n@import \"reset.less\";\n\n// Grid system and page structure\n@import \"scaffolding.less\";\n@import \"grid.less\";\n@import \"layouts.less\";\n\n// Base CSS\n@import \"type.less\";\n@import \"code.less\";\n@import \"forms.less\";\n@import \"tables.less\";\n\n// Components: common\n@import \"sprites.less\";\n@import \"dropdowns.less\";\n@import \"wells.less\";\n@import \"component-animations.less\";\n@import \"close.less\";\n\n// Components: Buttons & Alerts\n@import \"buttons.less\";\n@import \"button-groups.less\";\n@import \"alerts.less\"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less\n\n// Components: Nav\n@import \"navs.less\";\n@import \"navbar.less\";\n@import \"breadcrumbs.less\";\n@import \"pagination.less\";\n@import \"pager.less\";\n\n// Components: Popovers\n@import \"modals.less\";\n@import \"tooltip.less\";\n@import \"popovers.less\";\n\n// Components: Misc\n@import \"thumbnails.less\";\n@import \"media.less\";\n@import \"labels-badges.less\";\n@import \"progress-bars.less\";\n@import \"accordion.less\";\n@import \"carousel.less\";\n@import \"hero-unit.less\";\n\n// Utility classes\n@import \"utilities.less\"; // Has to be last to override when necessary\n"
  },
  {
    "path": "src/styles/bootstrap/breadcrumbs.less",
    "content": "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 @baseLineHeight;\n  list-style: none;\n  background-color: #f5f5f5;\n  .border-radius(@baseBorderRadius);\n  > li {\n    display: inline-block;\n    .ie7-inline-block();\n    text-shadow: 0 1px 0 @white;\n    > .divider {\n      padding: 0 5px;\n      color: #ccc;\n    }\n  }\n  > .active {\n    color: @grayLight;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/button-groups.less",
    "content": "//\n// Button groups\n// --------------------------------------------------\n\n\n// Make the div behave like a button\n.btn-group {\n  position: relative;\n  display: inline-block;\n  .ie7-inline-block();\n  font-size: 0; // remove as part 1 of font-size inline-block hack\n  vertical-align: middle; // match .btn alignment given font-size hack above\n  white-space: nowrap; // prevent buttons from wrapping when in tight spaces (e.g., the table on the tests page)\n  .ie7-restore-left-whitespace();\n}\n\n// Space out series of button groups\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n  font-size: 0; // Hack to remove whitespace that results from using inline-block\n  margin-top: @baseLineHeight / 2;\n  margin-bottom: @baseLineHeight / 2;\n  > .btn + .btn,\n  > .btn-group + .btn,\n  > .btn + .btn-group {\n    margin-left: 5px;\n  }\n}\n\n// Float them, remove border radius, then re-add to first and last elements\n.btn-group > .btn {\n  position: relative;\n  .border-radius(0);\n}\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n.btn-group > .btn,\n.btn-group > .dropdown-menu,\n.btn-group > .popover {\n  font-size: @baseFontSize; // redeclare as part 2 of font-size inline-block hack\n}\n\n// Reset fonts for other sizes\n.btn-group > .btn-mini {\n  font-size: @fontSizeMini;\n}\n.btn-group > .btn-small {\n  font-size: @fontSizeSmall;\n}\n.btn-group > .btn-large {\n  font-size: @fontSizeLarge;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  .border-top-left-radius(@baseBorderRadius);\n  .border-bottom-left-radius(@baseBorderRadius);\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  .border-top-right-radius(@baseBorderRadius);\n  .border-bottom-right-radius(@baseBorderRadius);\n}\n// Reset corners for large buttons\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  .border-top-left-radius(@borderRadiusLarge);\n  .border-bottom-left-radius(@borderRadiusLarge);\n}\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  .border-top-right-radius(@borderRadiusLarge);\n  .border-bottom-right-radius(@borderRadiusLarge);\n}\n\n// On hover/focus/active, bring the proper btn to front\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n  .box-shadow(~\"inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)\");\n  *padding-top: 5px;\n  *padding-bottom: 5px;\n}\n.btn-group > .btn-mini + .dropdown-toggle {\n  padding-left: 5px;\n  padding-right: 5px;\n  *padding-top: 2px;\n  *padding-bottom: 2px;\n}\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n.btn-group > .btn-large + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n\n.btn-group.open {\n\n  // The clickable button for toggling the menu\n  // Remove the gradient and set the same inset shadow as the :active state\n  .dropdown-toggle {\n    background-image: none;\n    .box-shadow(~\"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)\");\n  }\n\n  // Keep the hover's background when dropdown is open\n  .btn.dropdown-toggle {\n    background-color: @btnBackgroundHighlight;\n  }\n  .btn-primary.dropdown-toggle {\n    background-color: @btnPrimaryBackgroundHighlight;\n  }\n  .btn-warning.dropdown-toggle {\n    background-color: @btnWarningBackgroundHighlight;\n  }\n  .btn-danger.dropdown-toggle {\n    background-color: @btnDangerBackgroundHighlight;\n  }\n  .btn-success.dropdown-toggle {\n    background-color: @btnSuccessBackgroundHighlight;\n  }\n  .btn-info.dropdown-toggle {\n    background-color: @btnInfoBackgroundHighlight;\n  }\n  .btn-inverse.dropdown-toggle {\n    background-color: @btnInverseBackgroundHighlight;\n  }\n}\n\n\n// Reposition the caret\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n// Carets in other button sizes\n.btn-large .caret {\n  margin-top: 6px;\n}\n.btn-large .caret {\n  border-left-width:  5px;\n  border-right-width: 5px;\n  border-top-width:   5px;\n}\n.btn-mini .caret,\n.btn-small .caret {\n  margin-top: 8px;\n}\n// Upside down carets for .dropup\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n\n\n// Account for other colors\n.btn-primary,\n.btn-warning,\n.btn-danger,\n.btn-info,\n.btn-success,\n.btn-inverse {\n  .caret {\n    border-top-color: @white;\n    border-bottom-color: @white;\n  }\n}\n\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n  display: inline-block; // makes buttons only take up the width they need\n  .ie7-inline-block();\n}\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  max-width: 100%;\n  .border-radius(0);\n}\n.btn-group-vertical > .btn + .btn {\n  margin-left: 0;\n  margin-top: -1px;\n}\n.btn-group-vertical > .btn:first-child {\n  .border-radius(@baseBorderRadius @baseBorderRadius 0 0);\n}\n.btn-group-vertical > .btn:last-child {\n  .border-radius(0 0 @baseBorderRadius @baseBorderRadius);\n}\n.btn-group-vertical > .btn-large:first-child {\n  .border-radius(@borderRadiusLarge @borderRadiusLarge 0 0);\n}\n.btn-group-vertical > .btn-large:last-child {\n  .border-radius(0 0 @borderRadiusLarge @borderRadiusLarge);\n}\n"
  },
  {
    "path": "src/styles/bootstrap/buttons.less",
    "content": "//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n// Core\n.btn {\n  display: inline-block;\n  .ie7-inline-block();\n  padding: 4px 12px;\n  margin-bottom: 0; // For input.btn\n  font-size: @baseFontSize;\n  line-height: @baseLineHeight;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  .buttonBackground(@btnBackground, @btnBackgroundHighlight, @grayDark, 0 1px 1px rgba(255,255,255,.75));\n  border: 1px solid @btnBorder;\n  *border: 0; // Remove the border to prevent IE7's black border on input:focus\n  border-bottom-color: darken(@btnBorder, 10%);\n  .border-radius(@baseBorderRadius);\n  .ie7-restore-left-whitespace(); // Give IE7 some love\n  .box-shadow(~\"inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)\");\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    color: @grayDark;\n    text-decoration: none;\n    background-position: 0 -15px;\n\n    // transition is only when going to hover/focus, otherwise the background\n    // behind the gradient (there for IE<=9 fallback) gets mismatched\n    .transition(background-position .1s linear);\n  }\n\n  // Focus state for keyboard and accessibility\n  &:focus {\n    .tab-focus();\n  }\n\n  // Active state\n  &.active,\n  &:active {\n    background-image: none;\n    outline: 0;\n    .box-shadow(~\"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)\");\n  }\n\n  // Disabled state\n  &.disabled,\n  &[disabled] {\n    cursor: default;\n    background-image: none;\n    .opacity(65);\n    .box-shadow(none);\n  }\n\n}\n\n\n\n// Button Sizes\n// --------------------------------------------------\n\n// Large\n.btn-large {\n  padding: @paddingLarge;\n  font-size: @fontSizeLarge;\n  .border-radius(@borderRadiusLarge);\n}\n.btn-large [class^=\"icon-\"],\n.btn-large [class*=\" icon-\"] {\n  margin-top: 4px;\n}\n\n// Small\n.btn-small {\n  padding: @paddingSmall;\n  font-size: @fontSizeSmall;\n  .border-radius(@borderRadiusSmall);\n}\n.btn-small [class^=\"icon-\"],\n.btn-small [class*=\" icon-\"] {\n  margin-top: 0;\n}\n.btn-mini [class^=\"icon-\"],\n.btn-mini [class*=\" icon-\"] {\n  margin-top: -1px;\n}\n\n// Mini\n.btn-mini {\n  padding: @paddingMini;\n  font-size: @fontSizeMini;\n  .border-radius(@borderRadiusSmall);\n}\n\n\n// Block button\n// -------------------------\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n  .box-sizing(border-box);\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  &.btn-block {\n    width: 100%;\n  }\n}\n\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n// Provide *some* extra contrast for those who can get it\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255,255,255,.75);\n}\n\n// Set the backgrounds\n// -------------------------\n.btn-primary {\n  .buttonBackground(@btnPrimaryBackground, @btnPrimaryBackgroundHighlight);\n}\n// Warning appears are orange\n.btn-warning {\n  .buttonBackground(@btnWarningBackground, @btnWarningBackgroundHighlight);\n}\n// Danger and error appear as red\n.btn-danger {\n  .buttonBackground(@btnDangerBackground, @btnDangerBackgroundHighlight);\n}\n// Success appears as green\n.btn-success {\n  .buttonBackground(@btnSuccessBackground, @btnSuccessBackgroundHighlight);\n}\n// Info appears as a neutral blue\n.btn-info {\n  .buttonBackground(@btnInfoBackground, @btnInfoBackgroundHighlight);\n}\n// Inverse appears as dark gray\n.btn-inverse {\n  .buttonBackground(@btnInverseBackground, @btnInverseBackgroundHighlight);\n}\n\n\n// Cross-browser Jank\n// --------------------------------------------------\n\nbutton.btn,\ninput[type=\"submit\"].btn {\n\n  // Firefox 3.6 only I believe\n  &::-moz-focus-inner {\n    padding: 0;\n    border: 0;\n  }\n\n  // IE7 has some default padding on button controls\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n\n  &.btn-large {\n    *padding-top: 7px;\n    *padding-bottom: 7px;\n  }\n  &.btn-small {\n    *padding-top: 3px;\n    *padding-bottom: 3px;\n  }\n  &.btn-mini {\n    *padding-top: 1px;\n    *padding-bottom: 1px;\n  }\n}\n\n\n// Link buttons\n// --------------------------------------------------\n\n// Make a button look and behave like a link\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  .box-shadow(none);\n}\n.btn-link {\n  border-color: transparent;\n  cursor: pointer;\n  color: @linkColor;\n  .border-radius(0);\n}\n.btn-link:hover,\n.btn-link:focus {\n  color: @linkColorHover;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover,\n.btn-link[disabled]:focus {\n  color: @grayDark;\n  text-decoration: none;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/carousel.less",
    "content": "//\n// Carousel\n// --------------------------------------------------\n\n\n.carousel {\n  position: relative;\n  margin-bottom: @baseLineHeight;\n  line-height: 1;\n}\n\n.carousel-inner {\n  overflow: hidden;\n  width: 100%;\n  position: relative;\n}\n\n.carousel-inner {\n\n  > .item {\n    display: none;\n    position: relative;\n    .transition(.6s ease-in-out left);\n\n    // Account for jankitude on images\n    > img,\n    > a > img {\n      display: block;\n      line-height: 1;\n    }\n  }\n\n  > .active,\n  > .next,\n  > .prev { display: block; }\n\n  > .active {\n    left: 0;\n  }\n\n  > .next,\n  > .prev {\n    position: absolute;\n    top: 0;\n    width: 100%;\n  }\n\n  > .next {\n    left: 100%;\n  }\n  > .prev {\n    left: -100%;\n  }\n  > .next.left,\n  > .prev.right {\n    left: 0;\n  }\n\n  > .active.left {\n    left: -100%;\n  }\n  > .active.right {\n    left: 100%;\n  }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: @white;\n  text-align: center;\n  background: @grayDarker;\n  border: 3px solid @white;\n  .border-radius(23px);\n  .opacity(50);\n\n  // we can't have this transition here\n  // because webkit cancels the carousel\n  // animation if you trip this while\n  // in the middle of another animation\n  // ;_;\n  // .transition(opacity .2s linear);\n\n  // Reposition the right one\n  &.right {\n    left: auto;\n    right: 15px;\n  }\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    color: @white;\n    text-decoration: none;\n    .opacity(90);\n  }\n}\n\n// Carousel indicator pips\n// -----------------------------\n.carousel-indicators {\n  position: absolute;\n  top: 15px;\n  right: 15px;\n  z-index: 5;\n  margin: 0;\n  list-style: none;\n\n  li {\n    display: block;\n    float: left;\n    width: 10px;\n    height: 10px;\n    margin-left: 5px;\n    text-indent: -999px;\n    background-color: #ccc;\n    background-color: rgba(255,255,255,.25);\n    border-radius: 5px;\n  }\n  .active {\n    background-color: #fff;\n  }\n}\n\n// Caption for text below images\n// -----------------------------\n\n.carousel-caption {\n  position: absolute;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  padding: 15px;\n  background: @grayDark;\n  background: rgba(0,0,0,.75);\n}\n.carousel-caption h4,\n.carousel-caption p {\n  color: @white;\n  line-height: @baseLineHeight;\n}\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n.carousel-caption p {\n  margin-bottom: 0;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/close.less",
    "content": "//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: @baseLineHeight;\n  color: @black;\n  text-shadow: 0 1px 0 rgba(255,255,255,1);\n  .opacity(20);\n  &:hover,\n  &:focus {\n    color: @black;\n    text-decoration: none;\n    cursor: pointer;\n    .opacity(40);\n  }\n}\n\n// Additional properties for button version\n// iOS requires the button element instead of an anchor tag.\n// If you want the anchor version, it requires `href=\"#\"`.\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}"
  },
  {
    "path": "src/styles/bootstrap/code.less",
    "content": "//\n// Code (inline and blocK)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\npre {\n  padding: 0 3px 2px;\n  #font > #family > .monospace;\n  font-size: @baseFontSize - 2;\n  color: @grayDark;\n  .border-radius(3px);\n}\n\n// Inline code\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n  white-space: nowrap;\n}\n\n// Blocks of code\npre {\n  display: block;\n  padding: (@baseLineHeight - 1) / 2;\n  margin: 0 0 @baseLineHeight / 2;\n  font-size: @baseFontSize - 1; // 14px to 13px\n  line-height: @baseLineHeight;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc; // fallback for IE7-8\n  border: 1px solid rgba(0,0,0,.15);\n  .border-radius(@baseBorderRadius);\n\n  // Make prettyprint styles more spaced out for readability\n  &.prettyprint {\n    margin-bottom: @baseLineHeight;\n  }\n\n  // Account for some code outputs that place code tags in pre tags\n  code {\n    padding: 0;\n    color: inherit;\n    white-space: pre;\n    white-space: pre-wrap;\n    background-color: transparent;\n    border: 0;\n  }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}"
  },
  {
    "path": "src/styles/bootstrap/component-animations.less",
    "content": "//\n// Component animations\n// --------------------------------------------------\n\n\n.fade {\n  opacity: 0;\n  .transition(opacity .15s linear);\n  &.in {\n    opacity: 1;\n  }\n}\n\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  .transition(height .35s ease);\n  &.in {\n    height: auto;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/dropdowns.less",
    "content": "//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Use the .menu class on any <li> element within the topbar or ul.tabs and you'll get some superfancy dropdowns\n.dropup,\n.dropdown {\n  position: relative;\n}\n.dropdown-toggle {\n  // The caret makes the toggle a bit too tall in IE7\n  *margin-bottom: -3px;\n}\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n\n// Dropdown arrow/caret\n// --------------------\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top:   4px solid @black;\n  border-right: 4px solid transparent;\n  border-left:  4px solid transparent;\n  content: \"\";\n}\n\n// Place the caret\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n\n// The dropdown menu (ul)\n// ----------------------\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: @zindexDropdown;\n  display: none; // none by default, but block on \"open\" of the menu\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0; // override default ul\n  list-style: none;\n  background-color: @dropdownBackground;\n  border: 1px solid #ccc; // Fallback for IE7-8\n  border: 1px solid @dropdownBorder;\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  .border-radius(6px);\n  .box-shadow(0 5px 10px rgba(0,0,0,.2));\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n\n  // Aligns the dropdown menu to right\n  &.pull-right {\n    right: 0;\n    left: auto;\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .divider {\n    .nav-divider(@dropdownDividerTop, @dropdownDividerBottom);\n  }\n\n  // Links within the dropdown menu\n  > li > a {\n    display: block;\n    padding: 3px 20px;\n    clear: both;\n    font-weight: normal;\n    line-height: @baseLineHeight;\n    color: @dropdownLinkColor;\n    white-space: nowrap;\n  }\n}\n\n// Hover/Focus state\n// -----------\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus,\n.dropdown-submenu:hover > a,\n.dropdown-submenu:focus > a {\n  text-decoration: none;\n  color: @dropdownLinkColorHover;\n  #gradient > .vertical(@dropdownLinkBackgroundHover, darken(@dropdownLinkBackgroundHover, 5%));\n}\n\n// Active state\n// ------------\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: @dropdownLinkColorActive;\n  text-decoration: none;\n  outline: 0;\n  #gradient > .vertical(@dropdownLinkBackgroundActive, darken(@dropdownLinkBackgroundActive, 5%));\n}\n\n// Disabled state\n// --------------\n// Gray out text and ensure the hover/focus state remains gray\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: @grayLight;\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  text-decoration: none;\n  background-color: transparent;\n  background-image: none; // Remove CSS gradient\n  .reset-filter();\n  cursor: default;\n}\n\n// Open state for the dropdown\n// ---------------------------\n.open {\n  // IE7's z-index only goes to the nearest positioned ancestor, which would\n  // make the menu appear below buttons that appeared later on the page\n  *z-index: @zindexDropdown;\n\n  & > .dropdown-menu {\n    display: block;\n  }\n}\n\n// Right aligned dropdowns\n// ---------------------------\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n// ------------------------------------------------------\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n.dropup,\n.navbar-fixed-bottom .dropdown {\n  // Reverse the caret\n  .caret {\n    border-top: 0;\n    border-bottom: 4px solid @black;\n    content: \"\";\n  }\n  // Different positioning for bottom up menu\n  .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n    margin-bottom: 1px;\n  }\n}\n\n// Sub menus\n// ---------------------------\n.dropdown-submenu {\n  position: relative;\n}\n// Default dropdowns\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  .border-radius(0 6px 6px 6px);\n}\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n// Dropups\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n  .border-radius(5px 5px 5px 0);\n}\n\n// Caret to indicate there is a submenu\n.dropdown-submenu > a:after {\n  display: block;\n  content: \" \";\n  float: right;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  border-left-color: darken(@dropdownBackground, 20%);\n  margin-top: 5px;\n  margin-right: -10px;\n}\n.dropdown-submenu:hover > a:after {\n  border-left-color: @dropdownLinkColorHover;\n}\n\n// Left aligned submenus\n.dropdown-submenu.pull-left {\n  // Undo the float\n  // Yes, this is awkward since .pull-left adds a float, but it sticks to our conventions elsewhere.\n  float: none;\n\n  // Positioning the submenu\n  > .dropdown-menu {\n    left: -100%;\n    margin-left: 10px;\n    .border-radius(6px 0 6px 6px);\n  }\n}\n\n// Tweak nav headers\n// -----------------\n// Increase padding from 15px to 20px on sides\n.dropdown .dropdown-menu .nav-header {\n  padding-left: 20px;\n  padding-right: 20px;\n}\n\n// Typeahead\n// ---------\n.typeahead {\n  z-index: 1051;\n  margin-top: 2px; // give it some space to breathe\n  .border-radius(@baseBorderRadius);\n}\n"
  },
  {
    "path": "src/styles/bootstrap/forms.less",
    "content": "//\n// Forms\n// --------------------------------------------------\n\n\n// GENERAL STYLES\n// --------------\n\n// Make all forms have space below them\nform {\n  margin: 0 0 @baseLineHeight;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\n// Groups of fields with labels on top (legends)\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: @baseLineHeight;\n  font-size: @baseFontSize * 1.5;\n  line-height: @baseLineHeight * 2;\n  color: @grayDark;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n\n  // Small\n  small {\n    font-size: @baseLineHeight * .75;\n    color: @grayLight;\n  }\n}\n\n// Set font for forms\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  #font > .shorthand(@baseFontSize,normal,@baseLineHeight); // Set size, weight, line-height here\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: @baseFontFamily; // And only set font-family here for those that need it (note the missing label element)\n}\n\n// Identify controls by their labels\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\n\n// Form controls\n// -------------------------\n\n// Shared size and type resets\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: @baseLineHeight;\n  padding: 4px 6px;\n  margin-bottom: @baseLineHeight / 2;\n  font-size: @baseFontSize;\n  line-height: @baseLineHeight;\n  color: @gray;\n  .border-radius(@inputBorderRadius);\n  vertical-align: middle;\n}\n\n// Reset appearance properties for textual inputs and textarea\n// Declare width for legacy (can't be on input[type=*] selectors or it's too specific)\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px; // plus 12px padding and 2px border\n}\n// Reset height since textareas have rows\ntextarea {\n  height: auto;\n}\n// Everything else\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: @inputBackground;\n  border: 1px solid @inputBorder;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n  .transition(~\"border linear .2s, box-shadow linear .2s\");\n\n  // Focus state\n  &:focus {\n    border-color: rgba(82,168,236,.8);\n    outline: 0;\n    outline: thin dotted \\9; /* IE6-9 */\n    .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6)\");\n  }\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  *margin-top: 0; /* IE7 */\n  margin-top: 1px \\9; /* IE8-9 */\n  line-height: normal;\n}\n\n// Reset width of input images, buttons, radios, checkboxes\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto; // Override of generic input selector\n}\n\n// Set the height of select and file controls to match text inputs\nselect,\ninput[type=\"file\"] {\n  height: @inputHeight; /* In IE7, the height of the select element cannot be changed by height, only font-size */\n  *margin-top: 4px; /* For IE7, add top margin to align select with labels */\n  line-height: @inputHeight;\n}\n\n// Make select elements obey height by applying a border\nselect {\n  width: 220px; // default input width + 10px of padding that doesn't get applied\n  border: 1px solid @inputBorder;\n  background-color: @inputBackground; // Chrome on Linux and Mobile Safari need background-color\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\n// Focus for select, file, radio, and checkbox\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  .tab-focus();\n}\n\n\n// Uneditable inputs\n// -------------------------\n\n// Make uneditable inputs look inactive\n.uneditable-input,\n.uneditable-textarea {\n  color: @grayLight;\n  background-color: darken(@inputBackground, 1%);\n  border-color: @inputBorder;\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.025));\n  cursor: not-allowed;\n}\n\n// For text that needs to appear as an input but should not be an input\n.uneditable-input {\n  overflow: hidden; // prevent text from wrapping, but still cut it off like an input does\n  white-space: nowrap;\n}\n\n// Make uneditable textareas behave like a textarea\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\n\n\n// Placeholder\n// -------------------------\n\n// Placeholder text gets special styles because when browsers invalidate entire lines if it doesn't understand a selector\ninput,\ntextarea {\n  .placeholder();\n}\n\n\n// CHECKBOXES & RADIOS\n// -------------------\n\n// Indent the labels to position radios/checkboxes as hanging\n.radio,\n.checkbox {\n  min-height: @baseLineHeight; // clear the floating input if there is no label text\n  padding-left: 20px;\n}\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n// Move the options list down to align with labels\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px; // has to be padding because margin collaspes\n}\n\n// Radios and checkboxes on same line\n// TODO v3: Convert .inline to .control-inline\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px; // space out consecutive inline controls\n}\n\n\n\n// INPUT SIZES\n// -----------\n\n// General classes for quick sizes\n.input-mini       { width: 60px; }\n.input-small      { width: 90px; }\n.input-medium     { width: 150px; }\n.input-large      { width: 210px; }\n.input-xlarge     { width: 270px; }\n.input-xxlarge    { width: 530px; }\n\n// Grid style input sizes\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n// Redeclare since the fluid row class is more specific\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n// Ensure input-prepend/append never wraps\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\n\n\n\n// GRID SIZING FOR INPUTS\n// ----------------------\n\n// Grid sizes\n#grid > .input(@gridColumnWidth, @gridGutterWidth);\n\n// Control row for multiple inputs per line\n.controls-row {\n  .clearfix(); // Clear the float from controls\n}\n\n// Float to collapse white-space for proper grid alignment\n.controls-row [class*=\"span\"],\n// Redeclare the fluid grid collapse since we undo the float for inputs\n.row-fluid .controls-row [class*=\"span\"] {\n  float: left;\n}\n// Explicitly set top padding on all checkboxes/radios, not just first-child\n.controls-row .checkbox[class*=\"span\"],\n.controls-row .radio[class*=\"span\"] {\n  padding-top: 5px;\n}\n\n\n\n\n// DISABLED STATE\n// --------------\n\n// Disabled and read-only inputs\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: @inputDisabledBackground;\n}\n// Explicitly reset the colors here\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n\n\n\n\n// FORM FIELD FEEDBACK STATES\n// --------------------------\n\n// Warning\n.control-group.warning {\n  .formFieldState(@warningText, @warningText, @warningBackground);\n}\n// Error\n.control-group.error {\n  .formFieldState(@errorText, @errorText, @errorBackground);\n}\n// Success\n.control-group.success {\n  .formFieldState(@successText, @successText, @successBackground);\n}\n// Success\n.control-group.info {\n  .formFieldState(@infoText, @infoText, @infoBackground);\n}\n\n// HTML5 invalid states\n// Shares styles with the .control-group.error above\ninput:focus:invalid,\ntextarea:focus:invalid,\nselect:focus:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n  &:focus {\n    border-color: darken(#ee5f5b, 10%);\n    @shadow: 0 0 6px lighten(#ee5f5b, 20%);\n    .box-shadow(@shadow);\n  }\n}\n\n\n\n// FORM ACTIONS\n// ------------\n\n.form-actions {\n  padding: (@baseLineHeight - 1) 20px @baseLineHeight;\n  margin-top: @baseLineHeight;\n  margin-bottom: @baseLineHeight;\n  background-color: @formActionsBackground;\n  border-top: 1px solid #e5e5e5;\n  .clearfix(); // Adding clearfix to allow for .pull-right button containers\n}\n\n\n\n// HELP TEXT\n// ---------\n\n.help-block,\n.help-inline {\n  color: lighten(@textColor, 15%); // lighten the text some for contrast\n}\n\n.help-block {\n  display: block; // account for any element using help-block\n  margin-bottom: @baseLineHeight / 2;\n}\n\n.help-inline {\n  display: inline-block;\n  .ie7-inline-block();\n  vertical-align: middle;\n  padding-left: 5px;\n}\n\n\n\n// INPUT GROUPS\n// ------------\n\n// Allow us to put symbols and text within the input field for a cleaner look\n.input-append,\n.input-prepend {\n  display: inline-block;\n  margin-bottom: @baseLineHeight / 2;\n  vertical-align: middle;\n  font-size: 0; // white space collapse hack\n  white-space: nowrap; // Prevent span and input from separating\n\n  // Reset the white space collapse hack\n  input,\n  select,\n  .uneditable-input,\n  .dropdown-menu,\n  .popover {\n    font-size: @baseFontSize;\n  }\n\n  input,\n  select,\n  .uneditable-input {\n    position: relative; // placed here by default so that on :focus we can place the input above the .add-on for full border and box-shadow goodness\n    margin-bottom: 0; // prevent bottom margin from screwing up alignment in stacked forms\n    *margin-left: 0;\n    vertical-align: top;\n    .border-radius(0 @inputBorderRadius @inputBorderRadius 0);\n    // Make input on top when focused so blue border and shadow always show\n    &:focus {\n      z-index: 2;\n    }\n  }\n  .add-on {\n    display: inline-block;\n    width: auto;\n    height: @baseLineHeight;\n    min-width: 16px;\n    padding: 4px 5px;\n    font-size: @baseFontSize;\n    font-weight: normal;\n    line-height: @baseLineHeight;\n    text-align: center;\n    text-shadow: 0 1px 0 @white;\n    background-color: @grayLighter;\n    border: 1px solid #ccc;\n  }\n  .add-on,\n  .btn,\n  .btn-group > .dropdown-toggle {\n    vertical-align: top;\n    .border-radius(0);\n  }\n  .active {\n    background-color: lighten(@green, 30);\n    border-color: @green;\n  }\n}\n\n.input-prepend {\n  .add-on,\n  .btn {\n    margin-right: -1px;\n  }\n  .add-on:first-child,\n  .btn:first-child {\n    // FYI, `.btn:first-child` accounts for a button group that's prepended\n    .border-radius(@inputBorderRadius 0 0 @inputBorderRadius);\n  }\n}\n\n.input-append {\n  input,\n  select,\n  .uneditable-input {\n    .border-radius(@inputBorderRadius 0 0 @inputBorderRadius);\n    + .btn-group .btn:last-child {\n      .border-radius(0 @inputBorderRadius @inputBorderRadius 0);\n    }\n  }\n  .add-on,\n  .btn,\n  .btn-group {\n    margin-left: -1px;\n  }\n  .add-on:last-child,\n  .btn:last-child,\n  .btn-group:last-child > .dropdown-toggle {\n    .border-radius(0 @inputBorderRadius @inputBorderRadius 0);\n  }\n}\n\n// Remove all border-radius for inputs with both prepend and append\n.input-prepend.input-append {\n  input,\n  select,\n  .uneditable-input {\n    .border-radius(0);\n    + .btn-group .btn {\n      .border-radius(0 @inputBorderRadius @inputBorderRadius 0);\n    }\n  }\n  .add-on:first-child,\n  .btn:first-child {\n    margin-right: -1px;\n    .border-radius(@inputBorderRadius 0 0 @inputBorderRadius);\n  }\n  .add-on:last-child,\n  .btn:last-child {\n    margin-left: -1px;\n    .border-radius(0 @inputBorderRadius @inputBorderRadius 0);\n  }\n  .btn-group:first-child {\n    margin-left: 0;\n  }\n}\n\n\n\n\n// SEARCH FORM\n// -----------\n\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9; /* IE7-8 doesn't have border-radius, so don't indent the padding */\n  margin-bottom: 0; // Remove the default margin on all inputs\n  .border-radius(15px);\n}\n\n/* Allow for input prepend/append in search forms */\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  .border-radius(0); // Override due to specificity\n}\n.form-search .input-append .search-query {\n  .border-radius(14px 0 0 14px);\n}\n.form-search .input-append .btn {\n  .border-radius(0 14px 14px 0);\n}\n.form-search .input-prepend .search-query {\n  .border-radius(0 14px 14px 0);\n}\n.form-search .input-prepend .btn {\n  .border-radius(14px 0 0 14px);\n}\n\n\n\n\n// HORIZONTAL & VERTICAL FORMS\n// ---------------------------\n\n// Common properties\n// -----------------\n\n.form-search,\n.form-inline,\n.form-horizontal {\n  input,\n  textarea,\n  select,\n  .help-inline,\n  .uneditable-input,\n  .input-prepend,\n  .input-append {\n    display: inline-block;\n    .ie7-inline-block();\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  // Re-hide hidden elements due to specifity\n  .hide {\n    display: none;\n  }\n}\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n// Remove margin for input-prepend/-append\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n// Inline checkbox/radio labels (remove padding on left)\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n// Remove float and margin, set to inline-block\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n\n\n// Margin to space out fieldsets\n.control-group {\n  margin-bottom: @baseLineHeight / 2;\n}\n\n// Legend collapses margin, so next element is responsible for spacing\nlegend + .control-group {\n  margin-top: @baseLineHeight;\n  -webkit-margin-top-collapse: separate;\n}\n\n// Horizontal-specific styles\n// --------------------------\n\n.form-horizontal {\n  // Increase spacing between groups\n  .control-group {\n    margin-bottom: @baseLineHeight;\n    .clearfix();\n  }\n  // Float the labels left\n  .control-label {\n    float: left;\n    width: @horizontalComponentOffset - 20;\n    padding-top: 5px;\n    text-align: right;\n  }\n  // Move over all input controls and content\n  .controls {\n    // Super jank IE7 fix to ensure the inputs in .input-append and input-prepend\n    // don't inherit the margin of the parent, in this case .controls\n    *display: inline-block;\n    *padding-left: 20px;\n    margin-left: @horizontalComponentOffset;\n    *margin-left: 0;\n    &:first-child {\n      *padding-left: @horizontalComponentOffset;\n    }\n  }\n  // Remove bottom margin on block level help text since that's accounted for on .control-group\n  .help-block {\n    margin-bottom: 0;\n  }\n  // And apply it only to .help-block instances that follow a form control\n  input,\n  select,\n  textarea,\n  .uneditable-input,\n  .input-prepend,\n  .input-append {\n    + .help-block {\n      margin-top: @baseLineHeight / 2;\n    }\n  }\n  // Move over buttons in .form-actions to align with .controls\n  .form-actions {\n    padding-left: @horizontalComponentOffset;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/grid.less",
    "content": "//\n// Grid system\n// --------------------------------------------------\n\n\n// Fixed (940px)\n#grid > .core(@gridColumnWidth, @gridGutterWidth);\n\n// Fluid (940px)\n#grid > .fluid(@fluidGridColumnWidth, @fluidGridGutterWidth);\n\n// Reset utility classes due to specificity\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/hero-unit.less",
    "content": "//\n// Hero unit\n// --------------------------------------------------\n\n\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  font-size: 18px;\n  font-weight: 200;\n  line-height: @baseLineHeight * 1.5;\n  color: @heroUnitLeadColor;\n  background-color: @heroUnitBackground;\n  .border-radius(6px);\n  h1 {\n    margin-bottom: 0;\n    font-size: 60px;\n    line-height: 1;\n    color: @heroUnitHeadingColor;\n    letter-spacing: -1px;\n  }\n  li {\n    line-height: @baseLineHeight * 1.5; // Reset since we specify in type.less\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/labels-badges.less",
    "content": "//\n// Labels and badges\n// --------------------------------------------------\n\n\n// Base classes\n.label,\n.badge {\n  display: inline-block;\n  padding: 2px 4px;\n  font-size: @baseFontSize * .846;\n  font-weight: bold;\n  line-height: 14px; // ensure proper line-height if floated\n  color: @white;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n  background-color: @grayLight;\n}\n// Set unique padding and border-radii\n.label {\n  .border-radius(3px);\n}\n.badge {\n  padding-left: 9px;\n  padding-right: 9px;\n  .border-radius(9px);\n}\n\n// Empty labels/badges collapse\n.label,\n.badge {\n  &:empty {\n    display: none;\n  }\n}\n\n// Hover/focus state, but only for links\na {\n  &.label:hover,\n  &.label:focus,\n  &.badge:hover,\n  &.badge:focus {\n    color: @white;\n    text-decoration: none;\n    cursor: pointer;\n  }\n}\n\n// Colors\n// Only give background-color difference to links (and to simplify, we don't qualifty with `a` but [href] attribute)\n.label,\n.badge {\n  // Important (red)\n  &-important         { background-color: @errorText; }\n  &-important[href]   { background-color: darken(@errorText, 10%); }\n  // Warnings (orange)\n  &-warning           { background-color: @orange; }\n  &-warning[href]     { background-color: darken(@orange, 10%); }\n  // Success (green)\n  &-success           { background-color: @successText; }\n  &-success[href]     { background-color: darken(@successText, 10%); }\n  // Info (turquoise)\n  &-info              { background-color: @infoText; }\n  &-info[href]        { background-color: darken(@infoText, 10%); }\n  // Inverse (black)\n  &-inverse           { background-color: @grayDark; }\n  &-inverse[href]     { background-color: darken(@grayDark, 10%); }\n}\n\n// Quick fix for labels/badges in buttons\n.btn {\n  .label,\n  .badge {\n    position: relative;\n    top: -1px;\n  }\n}\n.btn-mini {\n  .label,\n  .badge {\n    top: 0;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/layouts.less",
    "content": "//\n// Layouts\n// --------------------------------------------------\n\n\n// Container (centered, fixed-width layouts)\n.container {\n  .container-fixed();\n}\n\n// Fluid layouts (left aligned, with sidebar, min- & max-width content)\n.container-fluid {\n  padding-right: @gridGutterWidth;\n  padding-left: @gridGutterWidth;\n  .clearfix();\n}"
  },
  {
    "path": "src/styles/bootstrap/media.less",
    "content": "// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n  overflow: hidden;\n  *overflow: visible;\n  zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n  display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n  margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n  margin-left: 0;\n  list-style: none;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/mixins.less",
    "content": "//\n// Mixins\n// --------------------------------------------------\n\n\n// UTILITY MIXINS\n// --------------------------------------------------\n\n// Clearfix\n// --------\n// For clearing floats like a boss h5bp.com/q\n.clearfix {\n  *zoom: 1;\n  &:before,\n  &:after {\n    display: table;\n    content: \"\";\n    // Fixes Opera/contenteditable bug:\n    // http://nicolasgallagher.com/micro-clearfix-hack/#comment-36952\n    line-height: 0;\n  }\n  &:after {\n    clear: both;\n  }\n}\n\n// Webkit-style focus\n// ------------------\n.tab-focus() {\n  // Default\n  outline: thin dotted #333;\n  // Webkit\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n// Center-align a block level element\n// ----------------------------------\n.center-block() {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n// IE7 inline-block\n// ----------------\n.ie7-inline-block() {\n  *display: inline; /* IE7 inline-block hack */\n  *zoom: 1;\n}\n\n// IE7 likes to collapse whitespace on either side of the inline-block elements.\n// Ems because we're attempting to match the width of a space character. Left\n// version is for form buttons, which typically come after other elements, and\n// right version is for icons, which come before. Applying both is ok, but it will\n// mean that space between those elements will be .6em (~2 space characters) in IE7,\n// instead of the 1 space in other browsers.\n.ie7-restore-left-whitespace() {\n  *margin-left: .3em;\n\n  &:first-child {\n    *margin-left: 0;\n  }\n}\n\n.ie7-restore-right-whitespace() {\n  *margin-right: .3em;\n}\n\n// Sizing shortcuts\n// -------------------------\n.size(@height, @width) {\n  width: @width;\n  height: @height;\n}\n.square(@size) {\n  .size(@size, @size);\n}\n\n// Placeholder text\n// -------------------------\n.placeholder(@color: @placeholderText) {\n  &:-moz-placeholder {\n    color: @color;\n  }\n  &:-ms-input-placeholder {\n    color: @color;\n  }\n  &::-webkit-input-placeholder {\n    color: @color;\n  }\n}\n\n// Text overflow\n// -------------------------\n// Requires inline-block or block for proper styling\n.text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n// CSS image replacement\n// -------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n\n// FONTS\n// --------------------------------------------------\n\n#font {\n  #family {\n    .serif() {\n      font-family: @serifFontFamily;\n    }\n    .sans-serif() {\n      font-family: @sansFontFamily;\n    }\n    .monospace() {\n      font-family: @monoFontFamily;\n    }\n  }\n  .shorthand(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {\n    font-size: @size;\n    font-weight: @weight;\n    line-height: @lineHeight;\n  }\n  .serif(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {\n    #font > #family > .serif;\n    #font > .shorthand(@size, @weight, @lineHeight);\n  }\n  .sans-serif(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {\n    #font > #family > .sans-serif;\n    #font > .shorthand(@size, @weight, @lineHeight);\n  }\n  .monospace(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {\n    #font > #family > .monospace;\n    #font > .shorthand(@size, @weight, @lineHeight);\n  }\n}\n\n\n// FORMS\n// --------------------------------------------------\n\n// Block level inputs\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: @inputHeight; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n  .box-sizing(border-box); // Makes inputs behave like true block-level elements\n}\n\n\n\n// Mixin for form field states\n.formFieldState(@textColor: #555, @borderColor: #ccc, @backgroundColor: #f5f5f5) {\n  // Set the text color\n  .control-label,\n  .help-block,\n  .help-inline {\n    color: @textColor;\n  }\n  // Style inputs accordingly\n  .checkbox,\n  .radio,\n  input,\n  select,\n  textarea {\n    color: @textColor;\n  }\n  input,\n  select,\n  textarea {\n    border-color: @borderColor;\n    .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n    &:focus {\n      border-color: darken(@borderColor, 10%);\n      @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@borderColor, 20%);\n      .box-shadow(@shadow);\n    }\n  }\n  // Give a small background color for input-prepend/-append\n  .input-prepend .add-on,\n  .input-append .add-on {\n    color: @textColor;\n    background-color: @backgroundColor;\n    border-color: @textColor;\n  }\n}\n\n\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Border Radius\n.border-radius(@radius) {\n  -webkit-border-radius: @radius;\n     -moz-border-radius: @radius;\n          border-radius: @radius;\n}\n\n// Single Corner Border Radius\n.border-top-left-radius(@radius) {\n  -webkit-border-top-left-radius: @radius;\n      -moz-border-radius-topleft: @radius;\n          border-top-left-radius: @radius;\n}\n.border-top-right-radius(@radius) {\n  -webkit-border-top-right-radius: @radius;\n      -moz-border-radius-topright: @radius;\n          border-top-right-radius: @radius;\n}\n.border-bottom-right-radius(@radius) {\n  -webkit-border-bottom-right-radius: @radius;\n      -moz-border-radius-bottomright: @radius;\n          border-bottom-right-radius: @radius;\n}\n.border-bottom-left-radius(@radius) {\n  -webkit-border-bottom-left-radius: @radius;\n      -moz-border-radius-bottomleft: @radius;\n          border-bottom-left-radius: @radius;\n}\n\n// Single Side Border Radius\n.border-top-radius(@radius) {\n  .border-top-right-radius(@radius);\n  .border-top-left-radius(@radius);\n}\n.border-right-radius(@radius) {\n  .border-top-right-radius(@radius);\n  .border-bottom-right-radius(@radius);\n}\n.border-bottom-radius(@radius) {\n  .border-bottom-right-radius(@radius);\n  .border-bottom-left-radius(@radius);\n}\n.border-left-radius(@radius) {\n  .border-top-left-radius(@radius);\n  .border-bottom-left-radius(@radius);\n}\n\n// Drop shadows\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow;\n     -moz-box-shadow: @shadow;\n          box-shadow: @shadow;\n}\n\n// Transitions\n.transition(@transition) {\n  -webkit-transition: @transition;\n     -moz-transition: @transition;\n       -o-transition: @transition;\n          transition: @transition;\n}\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n     -moz-transition-delay: @transition-delay;\n       -o-transition-delay: @transition-delay;\n          transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n     -moz-transition-duration: @transition-duration;\n       -o-transition-duration: @transition-duration;\n          transition-duration: @transition-duration;\n}\n\n// Transformations\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n     -moz-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees);\n       -o-transform: rotate(@degrees);\n          transform: rotate(@degrees);\n}\n.scale(@ratio) {\n  -webkit-transform: scale(@ratio);\n     -moz-transform: scale(@ratio);\n      -ms-transform: scale(@ratio);\n       -o-transform: scale(@ratio);\n          transform: scale(@ratio);\n}\n.translate(@x, @y) {\n  -webkit-transform: translate(@x, @y);\n     -moz-transform: translate(@x, @y);\n      -ms-transform: translate(@x, @y);\n       -o-transform: translate(@x, @y);\n          transform: translate(@x, @y);\n}\n.skew(@x, @y) {\n  -webkit-transform: skew(@x, @y);\n     -moz-transform: skew(@x, @y);\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twitter/bootstrap/issues/4885\n       -o-transform: skew(@x, @y);\n          transform: skew(@x, @y);\n  -webkit-backface-visibility: hidden; // See https://github.com/twitter/bootstrap/issues/5319\n}\n.translate3d(@x, @y, @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n     -moz-transform: translate3d(@x, @y, @z);\n       -o-transform: translate3d(@x, @y, @z);\n          transform: translate3d(@x, @y, @z);\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden\n// See git pull https://github.com/dannykeane/bootstrap.git backface-visibility for examples\n.backface-visibility(@visibility){\n\t-webkit-backface-visibility: @visibility;\n\t   -moz-backface-visibility: @visibility;\n\t        backface-visibility: @visibility;\n}\n\n// Background clipping\n// Heads up: FF 3.6 and under need \"padding\" instead of \"padding-box\"\n.background-clip(@clip) {\n  -webkit-background-clip: @clip;\n     -moz-background-clip: @clip;\n          background-clip: @clip;\n}\n\n// Background sizing\n.background-size(@size) {\n  -webkit-background-size: @size;\n     -moz-background-size: @size;\n       -o-background-size: @size;\n          background-size: @size;\n}\n\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n     -moz-box-sizing: @boxmodel;\n          box-sizing: @boxmodel;\n}\n\n// User select\n// For selecting text on the page\n.user-select(@select) {\n  -webkit-user-select: @select;\n     -moz-user-select: @select;\n      -ms-user-select: @select;\n       -o-user-select: @select;\n          user-select: @select;\n}\n\n// Resize anything\n.resizable(@direction) {\n  resize: @direction; // Options: horizontal, vertical, both\n  overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n.content-columns(@columnCount, @columnGap: @gridGutterWidth) {\n  -webkit-column-count: @columnCount;\n     -moz-column-count: @columnCount;\n          column-count: @columnCount;\n  -webkit-column-gap: @columnGap;\n     -moz-column-gap: @columnGap;\n          column-gap: @columnGap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n     -moz-hyphens: @mode;\n      -ms-hyphens: @mode;\n       -o-hyphens: @mode;\n          hyphens: @mode;\n}\n\n// Opacity\n.opacity(@opacity) {\n  opacity: (@opacity / 100);\n  filter: ~\"alpha(opacity=@{opacity})\";\n}\n\n\n\n// BACKGROUNDS\n// --------------------------------------------------\n\n// Add an alphatransparency value to any background or border color (via Elyse Holladay)\n#translucent {\n  .background(@color: @white, @alpha: 1) {\n    background-color: hsla(hue(@color), saturation(@color), lightness(@color), @alpha);\n  }\n  .border(@color: @white, @alpha: 1) {\n    border-color: hsla(hue(@color), saturation(@color), lightness(@color), @alpha);\n    .background-clip(padding-box);\n  }\n}\n\n// Gradient Bar Colors for buttons and alerts\n.gradientBar(@primaryColor, @secondaryColor, @textColor: #fff, @textShadow: 0 -1px 0 rgba(0,0,0,.25)) {\n  color: @textColor;\n  text-shadow: @textShadow;\n  #gradient > .vertical(@primaryColor, @secondaryColor);\n  border-color: @secondaryColor @secondaryColor darken(@secondaryColor, 15%);\n  border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) fadein(rgba(0,0,0,.1), 15%);\n}\n\n// Gradients\n#gradient {\n  .horizontal(@startColor: #555, @endColor: #333) {\n    background-color: @endColor;\n    background-image: -moz-linear-gradient(left, @startColor, @endColor); // FF 3.6+\n    background-image: -webkit-gradient(linear, 0 0, 100% 0, from(@startColor), to(@endColor)); // Safari 4+, Chrome 2+\n    background-image: -webkit-linear-gradient(left, @startColor, @endColor); // Safari 5.1+, Chrome 10+\n    background-image: -o-linear-gradient(left, @startColor, @endColor); // Opera 11.10\n    background-image: linear-gradient(to right, @startColor, @endColor); // Standard, IE10\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@startColor),argb(@endColor))); // IE9 and down\n  }\n  .vertical(@startColor: #555, @endColor: #333) {\n    background-color: mix(@startColor, @endColor, 60%);\n    background-image: -moz-linear-gradient(top, @startColor, @endColor); // FF 3.6+\n    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@startColor), to(@endColor)); // Safari 4+, Chrome 2+\n    background-image: -webkit-linear-gradient(top, @startColor, @endColor); // Safari 5.1+, Chrome 10+\n    background-image: -o-linear-gradient(top, @startColor, @endColor); // Opera 11.10\n    background-image: linear-gradient(to bottom, @startColor, @endColor); // Standard, IE10\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@startColor),argb(@endColor))); // IE9 and down\n  }\n  .directional(@startColor: #555, @endColor: #333, @deg: 45deg) {\n    background-color: @endColor;\n    background-repeat: repeat-x;\n    background-image: -moz-linear-gradient(@deg, @startColor, @endColor); // FF 3.6+\n    background-image: -webkit-linear-gradient(@deg, @startColor, @endColor); // Safari 5.1+, Chrome 10+\n    background-image: -o-linear-gradient(@deg, @startColor, @endColor); // Opera 11.10\n    background-image: linear-gradient(@deg, @startColor, @endColor); // Standard, IE10\n  }\n  .horizontal-three-colors(@startColor: #00b3ee, @midColor: #7a43b6, @colorStop: 50%, @endColor: #c3325f) {\n    background-color: mix(@midColor, @endColor, 80%);\n    background-image: -webkit-gradient(left, linear, 0 0, 0 100%, from(@startColor), color-stop(@colorStop, @midColor), to(@endColor));\n    background-image: -webkit-linear-gradient(left, @startColor, @midColor @colorStop, @endColor);\n    background-image: -moz-linear-gradient(left, @startColor, @midColor @colorStop, @endColor);\n    background-image: -o-linear-gradient(left, @startColor, @midColor @colorStop, @endColor);\n    background-image: linear-gradient(to right, @startColor, @midColor @colorStop, @endColor);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@startColor),argb(@endColor))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n\n  .vertical-three-colors(@startColor: #00b3ee, @midColor: #7a43b6, @colorStop: 50%, @endColor: #c3325f) {\n    background-color: mix(@midColor, @endColor, 80%);\n    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@startColor), color-stop(@colorStop, @midColor), to(@endColor));\n    background-image: -webkit-linear-gradient(@startColor, @midColor @colorStop, @endColor);\n    background-image: -moz-linear-gradient(top, @startColor, @midColor @colorStop, @endColor);\n    background-image: -o-linear-gradient(@startColor, @midColor @colorStop, @endColor);\n    background-image: linear-gradient(@startColor, @midColor @colorStop, @endColor);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@startColor),argb(@endColor))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@innerColor: #555, @outerColor: #333) {\n    background-color: @outerColor;\n    background-image: -webkit-gradient(radial, center center, 0, center center, 460, from(@innerColor), to(@outerColor));\n    background-image: -webkit-radial-gradient(circle, @innerColor, @outerColor);\n    background-image: -moz-radial-gradient(circle, @innerColor, @outerColor);\n    background-image: -o-radial-gradient(circle, @innerColor, @outerColor);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: #555, @angle: 45deg) {\n    background-color: @color;\n    background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,.15)), color-stop(.75, rgba(255,255,255,.15)), color-stop(.75, transparent), to(transparent));\n    background-image: -webkit-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);\n    background-image: -moz-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);\n    background-image: -o-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);\n    background-image: linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);\n  }\n}\n// Reset filters for IE\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n\n\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n.nav-divider(@top: #e5e5e5, @bottom: @white) {\n  // IE7 needs a set width since we gave a height. Restricting just\n  // to IE7 to keep the 1px left/right space in other browsers.\n  // It is unclear where IE is getting the extra space that we need\n  // to negative-margin away, but so it goes.\n  *width: 100%;\n  height: 1px;\n  margin: ((@baseLineHeight / 2) - 1) 1px; // 8px 1px\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: @top;\n  border-bottom: 1px solid @bottom;\n}\n\n// Button backgrounds\n// ------------------\n.buttonBackground(@startColor, @endColor, @textColor: #fff, @textShadow: 0 -1px 0 rgba(0,0,0,.25)) {\n  // gradientBar will set the background to a pleasing blend of these, to support IE<=9\n  .gradientBar(@startColor, @endColor, @textColor, @textShadow);\n  *background-color: @endColor; /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n  .reset-filter();\n\n  // in these cases the gradient won't cover the background, so we override\n  &:hover, &:focus, &:active, &.active, &.disabled, &[disabled] {\n    color: @textColor;\n    background-color: @endColor;\n    *background-color: darken(@endColor, 5%);\n  }\n\n  // IE 7 + 8 can't handle box-shadow to show active, so we darken a bit ourselves\n  &:active,\n  &.active {\n    background-color: darken(@endColor, 10%) e(\"\\9\");\n  }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbarVerticalAlign(30px);` to calculate the appropriate top margin.\n.navbarVerticalAlign(@elementHeight) {\n  margin-top: (@navbarHeight - @elementHeight) / 2;\n}\n\n\n\n// Grid System\n// -----------\n\n// Centered container element\n.container-fixed() {\n  margin-right: auto;\n  margin-left: auto;\n  .clearfix();\n}\n\n// Table columns\n.tableColumns(@columnSpan: 1) {\n  float: none; // undo default grid column styles\n  width: ((@gridColumnWidth) * @columnSpan) + (@gridGutterWidth * (@columnSpan - 1)) - 16; // 16 is total padding on left and right of table cells\n  margin-left: 0; // undo default grid column styles\n}\n\n// Make a Grid\n// Use .makeRow and .makeColumn to assign semantic layouts grid system behavior\n.makeRow() {\n  margin-left: @gridGutterWidth * -1;\n  .clearfix();\n}\n.makeColumn(@columns: 1, @offset: 0) {\n  float: left;\n  margin-left: (@gridColumnWidth * @offset) + (@gridGutterWidth * (@offset - 1)) + (@gridGutterWidth * 2);\n  width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));\n}\n\n// The Grid\n#grid {\n\n  .core (@gridColumnWidth, @gridGutterWidth) {\n\n    .spanX (@index) when (@index > 0) {\n      .span@{index} { .span(@index); }\n      .spanX(@index - 1);\n    }\n    .spanX (0) {}\n\n    .offsetX (@index) when (@index > 0) {\n      .offset@{index} { .offset(@index); }\n      .offsetX(@index - 1);\n    }\n    .offsetX (0) {}\n\n    .offset (@columns) {\n      margin-left: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns + 1));\n    }\n\n    .span (@columns) {\n      width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));\n    }\n\n    .row {\n      margin-left: @gridGutterWidth * -1;\n      .clearfix();\n    }\n\n    [class*=\"span\"] {\n      float: left;\n      min-height: 1px; // prevent collapsing columns\n      margin-left: @gridGutterWidth;\n    }\n\n    // Set the container width, and override it for fixed navbars in media queries\n    .container,\n    .navbar-static-top .container,\n    .navbar-fixed-top .container,\n    .navbar-fixed-bottom .container { .span(@gridColumns); }\n\n    // generate .spanX and .offsetX\n    .spanX (@gridColumns);\n    .offsetX (@gridColumns);\n\n  }\n\n  .fluid (@fluidGridColumnWidth, @fluidGridGutterWidth) {\n\n    .spanX (@index) when (@index > 0) {\n      .span@{index} { .span(@index); }\n      .spanX(@index - 1);\n    }\n    .spanX (0) {}\n\n    .offsetX (@index) when (@index > 0) {\n      .offset@{index} { .offset(@index); }\n      .offset@{index}:first-child { .offsetFirstChild(@index); }\n      .offsetX(@index - 1);\n    }\n    .offsetX (0) {}\n\n    .offset (@columns) {\n      margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) + (@fluidGridGutterWidth*2);\n  \t  *margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%) + (@fluidGridGutterWidth*2) - (.5 / @gridRowWidth * 100 * 1%);\n    }\n\n    .offsetFirstChild (@columns) {\n      margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) + (@fluidGridGutterWidth);\n      *margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%) + @fluidGridGutterWidth - (.5 / @gridRowWidth * 100 * 1%);\n    }\n\n    .span (@columns) {\n      width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1));\n      *width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%);\n    }\n\n    .row-fluid {\n      width: 100%;\n      .clearfix();\n      [class*=\"span\"] {\n        .input-block-level();\n        float: left;\n        margin-left: @fluidGridGutterWidth;\n        *margin-left: @fluidGridGutterWidth - (.5 / @gridRowWidth * 100 * 1%);\n      }\n      [class*=\"span\"]:first-child {\n        margin-left: 0;\n      }\n\n      // Space grid-sized controls properly if multiple per line\n      .controls-row [class*=\"span\"] + [class*=\"span\"] {\n        margin-left: @fluidGridGutterWidth;\n      }\n\n      // generate .spanX and .offsetX\n      .spanX (@gridColumns);\n      .offsetX (@gridColumns);\n    }\n\n  }\n\n  .input(@gridColumnWidth, @gridGutterWidth) {\n\n    .spanX (@index) when (@index > 0) {\n      input.span@{index}, textarea.span@{index}, .uneditable-input.span@{index} { .span(@index); }\n      .spanX(@index - 1);\n    }\n    .spanX (0) {}\n\n    .span(@columns) {\n      width: ((@gridColumnWidth) * @columns) + (@gridGutterWidth * (@columns - 1)) - 14;\n    }\n\n    input,\n    textarea,\n    .uneditable-input {\n      margin-left: 0; // override margin-left from core grid system\n    }\n\n    // Space grid-sized controls properly if multiple per line\n    .controls-row [class*=\"span\"] + [class*=\"span\"] {\n      margin-left: @gridGutterWidth;\n    }\n\n    // generate .spanX\n    .spanX (@gridColumns);\n\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/modals.less",
    "content": "//\n// Modals\n// --------------------------------------------------\n// Modified for Brackets:\n//  -changed modal-backdrop opacity to 50\n//  -changed modal position and margin\n\n// Background\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindexModalBackdrop;\n  background-color: @black;\n  // Fade for backdrop\n  &.fade { opacity: 0; }\n}\n\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  .opacity(50);\n}\n\n// Base modal\n.modal {\n  position: fixed;\n  top: 50%;//changed from 10%\n  z-index: @zindexModal;\n  width: 600px;\n  background-color: @white;\n  border: 1px solid #999;\n  border: 1px solid rgba(0,0,0,.3);\n  *border: 1px solid #999; /* IE6-7 */\n  .border-radius(6px);\n  .box-shadow(0 3px 7px rgba(0,0,0,0.3));\n  .background-clip(padding-box);\n  // Remove focus outline from opened modal\n  outline: none;\n\n  &.fade {\n    .transition(e('opacity .3s linear, top .3s ease-out'));\n    top: -25%;\n  }\n  &.fade.in { top: 50%; }\n}\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n  // Close icon\n  .close { margin-top: 2px; }\n  // Heading\n  h3 {\n    margin: 0;\n    line-height: 30px;\n  }\n}\n\n// Body (where all modal content resides)\n.modal-body {\n  position: relative;\n  overflow-y: auto;\n  max-height: 400px;\n  padding: 15px;\n}\n// Remove bottom margin if need be\n.modal-form {\n  margin-bottom: 0;\n}\n\n// Footer (for actions)\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right; // right align buttons\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  .border-radius(0 0 6px 6px);\n  .box-shadow(inset 0 1px 0 @white);\n  .clearfix(); // clear it in case folks use .pull-* classes on buttons\n\n  // Properly space out buttons\n  .btn + .btn {\n    margin-left: 5px;\n    margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n  }\n  // but override that for button groups\n  .btn-group .btn + .btn {\n    margin-left: -1px;\n  }\n  // and override it for block buttons as well\n  .btn-block + .btn-block {\n    margin-left: 0;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/navbar.less",
    "content": "//\n// Navbars (Redux)\n// --------------------------------------------------\n\n\n// COMMON STYLES\n// -------------\n\n// Base class and wrapper\n.navbar {\n  overflow: visible;\n  margin-bottom: @baseLineHeight;\n\n  // Fix for IE7's bad z-indexing so dropdowns don't appear below content that follows the navbar\n  *position: relative;\n  *z-index: 2;\n}\n\n// Inner for background effects\n// Gradient is applied to its own element because overflow visible is not honored by IE when filter is present\n.navbar-inner {\n  min-height: @navbarHeight;\n  padding-left:  20px;\n  padding-right: 20px;\n  #gradient > .vertical(@navbarBackgroundHighlight, @navbarBackground);\n  border: 1px solid @navbarBorder;\n  .border-radius(@baseBorderRadius);\n  .box-shadow(0 1px 4px rgba(0,0,0,.065));\n\n  // Prevent floats from breaking the navbar\n  .clearfix();\n}\n\n// Set width to auto for default container\n// We then reset it for fixed navbars in the #gridSystem mixin\n.navbar .container {\n  width: auto;\n}\n\n// Override the default collapsed state\n.nav-collapse.collapse {\n  height: auto;\n  overflow: visible;\n}\n\n\n// Brand: website or project name\n// -------------------------\n.navbar .brand {\n  float: left;\n  display: block;\n  // Vertically center the text given @navbarHeight\n  padding: ((@navbarHeight - @baseLineHeight) / 2) 20px ((@navbarHeight - @baseLineHeight) / 2);\n  margin-left: -20px; // negative indent to left-align the text down the page\n  font-size: 20px;\n  font-weight: 200;\n  color: @navbarBrandColor;\n  text-shadow: 0 1px 0 @navbarBackgroundHighlight;\n  &:hover,\n  &:focus {\n    text-decoration: none;\n  }\n}\n\n// Plain text in topbar\n// -------------------------\n.navbar-text {\n  margin-bottom: 0;\n  line-height: @navbarHeight;\n  color: @navbarText;\n}\n\n// Janky solution for now to account for links outside the .nav\n// -------------------------\n.navbar-link {\n  color: @navbarLinkColor;\n  &:hover,\n  &:focus {\n    color: @navbarLinkColorHover;\n  }\n}\n\n// Dividers in navbar\n// -------------------------\n.navbar .divider-vertical {\n  height: @navbarHeight;\n  margin: 0 9px;\n  border-left: 1px solid @navbarBackground;\n  border-right: 1px solid @navbarBackgroundHighlight;\n}\n\n// Buttons in navbar\n// -------------------------\n.navbar .btn,\n.navbar .btn-group {\n  .navbarVerticalAlign(30px); // Vertically center in navbar\n}\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn,\n.navbar .input-prepend .btn-group,\n.navbar .input-append .btn-group {\n  margin-top: 0; // then undo the margin here so we don't accidentally double it\n}\n\n// Navbar forms\n// -------------------------\n.navbar-form {\n  margin-bottom: 0; // remove default bottom margin\n  .clearfix();\n  input,\n  select,\n  .radio,\n  .checkbox {\n    .navbarVerticalAlign(30px); // Vertically center in navbar\n  }\n  input,\n  select,\n  .btn {\n    display: inline-block;\n    margin-bottom: 0;\n  }\n  input[type=\"image\"],\n  input[type=\"checkbox\"],\n  input[type=\"radio\"] {\n    margin-top: 3px;\n  }\n  .input-append,\n  .input-prepend {\n    margin-top: 5px;\n    white-space: nowrap; // preven two  items from separating within a .navbar-form that has .pull-left\n    input {\n      margin-top: 0; // remove the margin on top since it's on the parent\n    }\n  }\n}\n\n// Navbar search\n// -------------------------\n.navbar-search {\n  position: relative;\n  float: left;\n  .navbarVerticalAlign(30px); // Vertically center in navbar\n  margin-bottom: 0;\n  .search-query {\n    margin-bottom: 0;\n    padding: 4px 14px;\n    #font > .sans-serif(13px, normal, 1);\n    .border-radius(15px); // redeclare because of specificity of the type attribute\n  }\n}\n\n\n\n// Static navbar\n// -------------------------\n\n.navbar-static-top {\n  position: static;\n  margin-bottom: 0; // remove 18px margin for default navbar\n  .navbar-inner {\n    .border-radius(0);\n  }\n}\n\n\n\n// Fixed navbar\n// -------------------------\n\n// Shared (top/bottom) styles\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: @zindexFixedNavbar;\n  margin-bottom: 0; // remove 18px margin for default navbar\n}\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-left:  0;\n  padding-right: 0;\n  .border-radius(0);\n}\n\n// Reset container width\n// Required here as we reset the width earlier on and the grid mixins don't override early enough\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  .span(@gridColumns);\n}\n\n// Fixed to top\n.navbar-fixed-top {\n  top: 0;\n}\n.navbar-fixed-top,\n.navbar-static-top {\n  .navbar-inner {\n    .box-shadow(~\"0 1px 10px rgba(0,0,0,.1)\");\n  }\n}\n\n// Fixed to bottom\n.navbar-fixed-bottom {\n  bottom: 0;\n  .navbar-inner {\n    .box-shadow(~\"0 -1px 10px rgba(0,0,0,.1)\");\n  }\n}\n\n\n\n// NAVIGATION\n// ----------\n\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n.navbar .nav.pull-right {\n  float: right; // redeclare due to specificity\n  margin-right: 0; // remove margin on float right nav\n}\n.navbar .nav > li {\n  float: left;\n}\n\n// Links\n.navbar .nav > li > a {\n  float: none;\n  // Vertically center the text given @navbarHeight\n  padding: ((@navbarHeight - @baseLineHeight) / 2) 15px ((@navbarHeight - @baseLineHeight) / 2);\n  color: @navbarLinkColor;\n  text-decoration: none;\n  text-shadow: 0 1px 0 @navbarBackgroundHighlight;\n}\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n// Hover/focus\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  background-color: @navbarLinkBackgroundHover; // \"transparent\" is default to differentiate :hover/:focus from .active\n  color: @navbarLinkColorHover;\n  text-decoration: none;\n}\n\n// Active nav items\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: @navbarLinkColorActive;\n  text-decoration: none;\n  background-color: @navbarLinkBackgroundActive;\n  .box-shadow(inset 0 3px 8px rgba(0,0,0,.125));\n}\n\n// Navbar button for toggling navbar items in responsive layouts\n// These definitions need to come after '.navbar .btn'\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-left: 5px;\n  margin-right: 5px;\n  .buttonBackground(darken(@navbarBackgroundHighlight, 5%), darken(@navbarBackground, 5%));\n  .box-shadow(~\"inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075)\");\n}\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  .border-radius(1px);\n  .box-shadow(0 1px 0 rgba(0,0,0,.25));\n}\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n\n\n\n// Dropdown menus\n// --------------\n\n// Menu position and menu carets\n.navbar .nav > li > .dropdown-menu {\n  &:before {\n    content: '';\n    display: inline-block;\n    border-left:   7px solid transparent;\n    border-right:  7px solid transparent;\n    border-bottom: 7px solid #ccc;\n    border-bottom-color: @dropdownBorder;\n    position: absolute;\n    top: -7px;\n    left: 9px;\n  }\n  &:after {\n    content: '';\n    display: inline-block;\n    border-left:   6px solid transparent;\n    border-right:  6px solid transparent;\n    border-bottom: 6px solid @dropdownBackground;\n    position: absolute;\n    top: -6px;\n    left: 10px;\n  }\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .nav > li > .dropdown-menu {\n  &:before {\n    border-top: 7px solid #ccc;\n    border-top-color: @dropdownBorder;\n    border-bottom: 0;\n    bottom: -7px;\n    top: auto;\n  }\n  &:after {\n    border-top: 6px solid @dropdownBackground;\n    border-bottom: 0;\n    bottom: -6px;\n    top: auto;\n  }\n}\n\n// Caret should match text color on hover/focus\n.navbar .nav li.dropdown > a:hover .caret,\n.navbar .nav li.dropdown > a:focus .caret {\n  border-top-color: @navbarLinkColorHover;\n  border-bottom-color: @navbarLinkColorHover;\n}\n\n// Remove background color from open dropdown\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  background-color: @navbarLinkBackgroundActive;\n  color: @navbarLinkColorActive;\n}\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: @navbarLinkColor;\n  border-bottom-color: @navbarLinkColor;\n}\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: @navbarLinkColorActive;\n  border-bottom-color: @navbarLinkColorActive;\n}\n\n// Right aligned menus need alt position\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n  &:before {\n    left: auto;\n    right: 12px;\n  }\n  &:after {\n    left: auto;\n    right: 13px;\n  }\n  .dropdown-menu {\n    left: auto;\n    right: 100%;\n    margin-left: 0;\n    margin-right: -1px;\n    .border-radius(6px 0 6px 6px);\n  }\n}\n\n\n// Inverted navbar\n// -------------------------\n\n.navbar-inverse {\n\n  .navbar-inner {\n    #gradient > .vertical(@navbarInverseBackgroundHighlight, @navbarInverseBackground);\n    border-color: @navbarInverseBorder;\n  }\n\n  .brand,\n  .nav > li > a {\n    color: @navbarInverseLinkColor;\n    text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n    &:hover,\n    &:focus {\n      color: @navbarInverseLinkColorHover;\n    }\n  }\n\n  .brand {\n    color: @navbarInverseBrandColor;\n  }\n\n  .navbar-text {\n    color: @navbarInverseText;\n  }\n\n  .nav > li > a:focus,\n  .nav > li > a:hover {\n    background-color: @navbarInverseLinkBackgroundHover;\n    color: @navbarInverseLinkColorHover;\n  }\n\n  .nav .active > a,\n  .nav .active > a:hover,\n  .nav .active > a:focus {\n    color: @navbarInverseLinkColorActive;\n    background-color: @navbarInverseLinkBackgroundActive;\n  }\n\n  // Inline text links\n  .navbar-link {\n    color: @navbarInverseLinkColor;\n    &:hover,\n    &:focus {\n      color: @navbarInverseLinkColorHover;\n    }\n  }\n\n  // Dividers in navbar\n  .divider-vertical {\n    border-left-color: @navbarInverseBackground;\n    border-right-color: @navbarInverseBackgroundHighlight;\n  }\n\n  // Dropdowns\n  .nav li.dropdown.open > .dropdown-toggle,\n  .nav li.dropdown.active > .dropdown-toggle,\n  .nav li.dropdown.open.active > .dropdown-toggle {\n    background-color: @navbarInverseLinkBackgroundActive;\n    color: @navbarInverseLinkColorActive;\n  }\n  .nav li.dropdown > a:hover .caret,\n  .nav li.dropdown > a:focus .caret {\n    border-top-color: @navbarInverseLinkColorActive;\n    border-bottom-color: @navbarInverseLinkColorActive;\n  }\n  .nav li.dropdown > .dropdown-toggle .caret {\n    border-top-color: @navbarInverseLinkColor;\n    border-bottom-color: @navbarInverseLinkColor;\n  }\n  .nav li.dropdown.open > .dropdown-toggle .caret,\n  .nav li.dropdown.active > .dropdown-toggle .caret,\n  .nav li.dropdown.open.active > .dropdown-toggle .caret {\n    border-top-color: @navbarInverseLinkColorActive;\n    border-bottom-color: @navbarInverseLinkColorActive;\n  }\n\n  // Navbar search\n  .navbar-search {\n    .search-query {\n      color: @white;\n      background-color: @navbarInverseSearchBackground;\n      border-color: @navbarInverseSearchBorder;\n      .box-shadow(~\"inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15)\");\n      .transition(none);\n      .placeholder(@navbarInverseSearchPlaceholderColor);\n\n      // Focus states (we use .focused since IE7-8 and down doesn't support :focus)\n      &:focus,\n      &.focused {\n        padding: 5px 15px;\n        color: @grayDark;\n        text-shadow: 0 1px 0 @white;\n        background-color: @navbarInverseSearchBackgroundFocus;\n        border: 0;\n        .box-shadow(0 0 3px rgba(0,0,0,.15));\n        outline: 0;\n      }\n    }\n  }\n\n  // Navbar collapse button\n  .btn-navbar {\n    .buttonBackground(darken(@navbarInverseBackgroundHighlight, 5%), darken(@navbarInverseBackground, 5%));\n  }\n\n}\n"
  },
  {
    "path": "src/styles/bootstrap/navs.less",
    "content": "//\n// Navs\n// --------------------------------------------------\n\n\n// BASE CLASS\n// ----------\n\n.nav {\n  margin-left: 0;\n  margin-bottom: @baseLineHeight;\n  list-style: none;\n}\n\n// Make links block level\n.nav > li > a {\n  display: block;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: @grayLighter;\n}\n\n// Prevent IE8 from misplacing imgs\n// See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n.nav > li > a > img {\n  max-width: none;\n}\n\n// Redeclare pull classes because of specifity\n.nav > .pull-right {\n  float: right;\n}\n\n// Nav headers (for dropdowns and lists)\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: @baseLineHeight;\n  color: @grayLight;\n  text-shadow: 0 1px 0 rgba(255,255,255,.5);\n  text-transform: uppercase;\n}\n// Space them out when they follow another list item (link)\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n\n\n\n// NAV LIST\n// --------\n\n.nav-list {\n  padding-left: 15px;\n  padding-right: 15px;\n  margin-bottom: 0;\n}\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-left:  -15px;\n  margin-right: -15px;\n  text-shadow: 0 1px 0 rgba(255,255,255,.5);\n}\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n.nav-list > .active > a,\n.nav-list > .active > a:hover,\n.nav-list > .active > a:focus {\n  color: @white;\n  text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n  background-color: @linkColor;\n}\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  margin-right: 2px;\n}\n// Dividers (basically an hr) within the dropdown\n.nav-list .divider {\n  .nav-divider();\n}\n\n\n\n// TABS AND PILLS\n// -------------\n\n// Common styles\n.nav-tabs,\n.nav-pills {\n  .clearfix();\n}\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px; // keeps the overall height an even number\n}\n\n// TABS\n// ----\n\n// Give the tabs something to sit on\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n// Make the list-items overlay the bottom border\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n// Actual tabs (as links)\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: @baseLineHeight;\n  border: 1px solid transparent;\n  .border-radius(4px 4px 0 0);\n  &:hover,\n  &:focus {\n    border-color: @grayLighter @grayLighter #ddd;\n  }\n}\n// Active state, and it's :hover/:focus to override normal :hover/:focus\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover,\n.nav-tabs > .active > a:focus {\n  color: @gray;\n  background-color: @bodyBackground;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n\n\n// PILLS\n// -----\n\n// Links rendered as pills\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  .border-radius(5px);\n}\n\n// Active state\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover,\n.nav-pills > .active > a:focus {\n  color: @white;\n  background-color: @linkColor;\n}\n\n\n\n// STACKED NAV\n// -----------\n\n// Stacked tabs and pills\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li > a {\n  margin-right: 0; // no need for the gap between nav items\n}\n\n// Tabs\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  .border-radius(0);\n}\n.nav-tabs.nav-stacked > li:first-child > a {\n  .border-top-radius(4px);\n}\n.nav-tabs.nav-stacked > li:last-child > a {\n  .border-bottom-radius(4px);\n}\n.nav-tabs.nav-stacked > li > a:hover,\n.nav-tabs.nav-stacked > li > a:focus {\n  border-color: #ddd;\n  z-index: 2;\n}\n\n// Pills\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px; // decrease margin to match sizing of stacked tabs\n}\n\n\n\n// DROPDOWNS\n// ---------\n\n.nav-tabs .dropdown-menu {\n  .border-radius(0 0 6px 6px); // remove the top rounded corners here since there is a hard edge above the menu\n}\n.nav-pills .dropdown-menu {\n  .border-radius(6px); // make rounded corners match the pills\n}\n\n// Default dropdown links\n// -------------------------\n// Make carets use linkColor to start\n.nav .dropdown-toggle .caret {\n  border-top-color: @linkColor;\n  border-bottom-color: @linkColor;\n  margin-top: 6px;\n}\n.nav .dropdown-toggle:hover .caret,\n.nav .dropdown-toggle:focus .caret {\n  border-top-color: @linkColorHover;\n  border-bottom-color: @linkColorHover;\n}\n/* move down carets for tabs */\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n\n// Active dropdown links\n// -------------------------\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: @gray;\n  border-bottom-color: @gray;\n}\n\n// Active:hover/:focus dropdown links\n// -------------------------\n.nav > .dropdown.active > a:hover,\n.nav > .dropdown.active > a:focus {\n  cursor: pointer;\n}\n\n// Open dropdowns\n// -------------------------\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover,\n.nav > li.dropdown.open.active > a:focus {\n  color: @white;\n  background-color: @grayLight;\n  border-color: @grayLight;\n}\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret,\n.nav li.dropdown.open a:focus .caret {\n  border-top-color: @white;\n  border-bottom-color: @white;\n  .opacity(100);\n}\n\n// Dropdowns in stacked tabs\n.tabs-stacked .open > a:hover,\n.tabs-stacked .open > a:focus {\n  border-color: @grayLight;\n}\n\n\n\n// TABBABLE\n// --------\n\n\n// COMMON STYLES\n// -------------\n\n// Clear any floats\n.tabbable {\n  .clearfix();\n}\n.tab-content {\n  overflow: auto; // prevent content from running below tabs\n}\n\n// Remove border on bottom, left, right\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n// Show/hide tabbable areas\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n\n// BOTTOM\n// ------\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n.tabs-below > .nav-tabs > li > a {\n  .border-radius(0 0 4px 4px);\n  &:hover,\n  &:focus {\n    border-bottom-color: transparent;\n    border-top-color: #ddd;\n  }\n}\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover,\n.tabs-below > .nav-tabs > .active > a:focus {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n// LEFT & RIGHT\n// ------------\n\n// Common styles\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n// Tabs on the left\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  .border-radius(4px 0 0 4px);\n}\n.tabs-left > .nav-tabs > li > a:hover,\n.tabs-left > .nav-tabs > li > a:focus {\n  border-color: @grayLighter #ddd @grayLighter @grayLighter;\n}\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover,\n.tabs-left > .nav-tabs .active > a:focus {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: @white;\n}\n\n// Tabs on the right\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  .border-radius(0 4px 4px 0);\n}\n.tabs-right > .nav-tabs > li > a:hover,\n.tabs-right > .nav-tabs > li > a:focus {\n  border-color: @grayLighter @grayLighter @grayLighter #ddd;\n}\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover,\n.tabs-right > .nav-tabs .active > a:focus {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: @white;\n}\n\n\n\n// DISABLED STATES\n// ---------------\n\n// Gray out text\n.nav > .disabled > a {\n  color: @grayLight;\n}\n// Nuke hover/focus effects\n.nav > .disabled > a:hover,\n.nav > .disabled > a:focus {\n  text-decoration: none;\n  background-color: transparent;\n  cursor: default;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/pager.less",
    "content": "//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n  margin: @baseLineHeight 0;\n  list-style: none;\n  text-align: center;\n  .clearfix();\n}\n.pager li {\n  display: inline;\n}\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  .border-radius(15px);\n}\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: @grayLight;\n  background-color: #fff;\n  cursor: default;\n}"
  },
  {
    "path": "src/styles/bootstrap/pagination.less",
    "content": "//\n// Pagination (multiple pages)\n// --------------------------------------------------\n\n// Space out pagination from surrounding content\n.pagination {\n  margin: @baseLineHeight 0;\n}\n\n.pagination ul {\n  // Allow for text-based alignment\n  display: inline-block;\n  .ie7-inline-block();\n  // Reset default ul styles\n  margin-left: 0;\n  margin-bottom: 0;\n  // Visuals\n  .border-radius(@baseBorderRadius);\n  .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n.pagination ul > li {\n  display: inline; // Remove list-style and block-level defaults\n}\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left; // Collapse white-space\n  padding: 4px 12px;\n  line-height: @baseLineHeight;\n  text-decoration: none;\n  background-color: @paginationBackground;\n  border: 1px solid @paginationBorder;\n  border-left-width: 0;\n}\n.pagination ul > li > a:hover,\n.pagination ul > li > a:focus,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: @paginationActiveBackground;\n}\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: @grayLight;\n  cursor: default;\n}\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover,\n.pagination ul > .disabled > a:focus {\n  color: @grayLight;\n  background-color: transparent;\n  cursor: default;\n}\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  .border-left-radius(@baseBorderRadius);\n}\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  .border-right-radius(@baseBorderRadius);\n}\n\n\n// Alignment\n// --------------------------------------------------\n\n.pagination-centered {\n  text-align: center;\n}\n.pagination-right {\n  text-align: right;\n}\n\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-large {\n  ul > li > a,\n  ul > li > span {\n    padding: @paddingLarge;\n    font-size: @fontSizeLarge;\n  }\n  ul > li:first-child > a,\n  ul > li:first-child > span {\n    .border-left-radius(@borderRadiusLarge);\n  }\n  ul > li:last-child > a,\n  ul > li:last-child > span {\n    .border-right-radius(@borderRadiusLarge);\n  }\n}\n\n// Small and mini\n.pagination-mini,\n.pagination-small {\n  ul > li:first-child > a,\n  ul > li:first-child > span {\n    .border-left-radius(@borderRadiusSmall);\n  }\n  ul > li:last-child > a,\n  ul > li:last-child > span {\n    .border-right-radius(@borderRadiusSmall);\n  }\n}\n\n// Small\n.pagination-small {\n  ul > li > a,\n  ul > li > span {\n    padding: @paddingSmall;\n    font-size: @fontSizeSmall;\n  }\n}\n// Mini\n.pagination-mini {\n  ul > li > a,\n  ul > li > span {\n    padding: @paddingMini;\n    font-size: @fontSizeMini;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/popovers.less",
    "content": "//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: @zindexPopover;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  text-align: left; // Reset given new insertion method\n  background-color: @popoverBackground;\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0,0,0,.2);\n  .border-radius(6px);\n  .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n  // Overrides for proper insertion\n  white-space: normal;\n\n  // Offset the popover to account for the popover arrow\n  &.top     { margin-top: -10px; }\n  &.right   { margin-left: 10px; }\n  &.bottom  { margin-top: 10px; }\n  &.left    { margin-left: -10px; }\n}\n\n.popover-title {\n  margin: 0; // reset heading margin\n  padding: 8px 14px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: @popoverTitleBackground;\n  border-bottom: 1px solid darken(@popoverTitleBackground, 5%);\n  .border-radius(5px 5px 0 0);\n\n  &:empty {\n    display: none;\n  }\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.popover .arrow {\n  border-width: @popoverArrowOuterWidth;\n}\n.popover .arrow:after {\n  border-width: @popoverArrowWidth;\n  content: \"\";\n}\n\n.popover {\n  &.top .arrow {\n    left: 50%;\n    margin-left: -@popoverArrowOuterWidth;\n    border-bottom-width: 0;\n    border-top-color: #999; // IE8 fallback\n    border-top-color: @popoverArrowOuterColor;\n    bottom: -@popoverArrowOuterWidth;\n    &:after {\n      bottom: 1px;\n      margin-left: -@popoverArrowWidth;\n      border-bottom-width: 0;\n      border-top-color: @popoverArrowColor;\n    }\n  }\n  &.right .arrow {\n    top: 50%;\n    left: -@popoverArrowOuterWidth;\n    margin-top: -@popoverArrowOuterWidth;\n    border-left-width: 0;\n    border-right-color: #999; // IE8 fallback\n    border-right-color: @popoverArrowOuterColor;\n    &:after {\n      left: 1px;\n      bottom: -@popoverArrowWidth;\n      border-left-width: 0;\n      border-right-color: @popoverArrowColor;\n    }\n  }\n  &.bottom .arrow {\n    left: 50%;\n    margin-left: -@popoverArrowOuterWidth;\n    border-top-width: 0;\n    border-bottom-color: #999; // IE8 fallback\n    border-bottom-color: @popoverArrowOuterColor;\n    top: -@popoverArrowOuterWidth;\n    &:after {\n      top: 1px;\n      margin-left: -@popoverArrowWidth;\n      border-top-width: 0;\n      border-bottom-color: @popoverArrowColor;\n    }\n  }\n\n  &.left .arrow {\n    top: 50%;\n    right: -@popoverArrowOuterWidth;\n    margin-top: -@popoverArrowOuterWidth;\n    border-right-width: 0;\n    border-left-color: #999; // IE8 fallback\n    border-left-color: @popoverArrowOuterColor;\n    &:after {\n      right: 1px;\n      border-right-width: 0;\n      border-left-color: @popoverArrowColor;\n      bottom: -@popoverArrowWidth;\n    }\n  }\n\n}\n"
  },
  {
    "path": "src/styles/bootstrap/progress-bars.less",
    "content": "//\n// Progress bars\n// --------------------------------------------------\n\n\n// ANIMATIONS\n// ----------\n\n// Webkit\n@-webkit-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Firefox\n@-moz-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// IE9\n@-ms-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Opera\n@-o-keyframes progress-bar-stripes {\n  from  { background-position: 0 0; }\n  to    { background-position: 40px 0; }\n}\n\n// Spec\n@keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n\n\n// THE BARS\n// --------\n\n// Outer container\n.progress {\n  overflow: hidden;\n  height: @baseLineHeight;\n  margin-bottom: @baseLineHeight;\n  #gradient > .vertical(#f5f5f5, #f9f9f9);\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n  .border-radius(@baseBorderRadius);\n}\n\n// Bar of progress\n.progress .bar {\n  width: 0%;\n  height: 100%;\n  color: @white;\n  float: left;\n  font-size: 12px;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n  #gradient > .vertical(#149bdf, #0480be);\n  .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n  .box-sizing(border-box);\n  .transition(width .6s ease);\n}\n.progress .bar + .bar {\n  .box-shadow(~\"inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15)\");\n}\n\n// Striped bars\n.progress-striped .bar {\n  #gradient > .striped(#149bdf);\n  .background-size(40px 40px);\n}\n\n// Call animation for the active one\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n\n\n// COLORS\n// ------\n\n// Danger (red)\n.progress-danger .bar, .progress .bar-danger {\n  #gradient > .vertical(#ee5f5b, #c43c35);\n}\n.progress-danger.progress-striped .bar, .progress-striped .bar-danger {\n  #gradient > .striped(#ee5f5b);\n}\n\n// Success (green)\n.progress-success .bar, .progress .bar-success {\n  #gradient > .vertical(#62c462, #57a957);\n}\n.progress-success.progress-striped .bar, .progress-striped .bar-success {\n  #gradient > .striped(#62c462);\n}\n\n// Info (teal)\n.progress-info .bar, .progress .bar-info {\n  #gradient > .vertical(#5bc0de, #339bb9);\n}\n.progress-info.progress-striped .bar, .progress-striped .bar-info {\n  #gradient > .striped(#5bc0de);\n}\n\n// Warning (orange)\n.progress-warning .bar, .progress .bar-warning {\n  #gradient > .vertical(lighten(@orange, 15%), @orange);\n}\n.progress-warning.progress-striped .bar, .progress-striped .bar-warning {\n  #gradient > .striped(lighten(@orange, 15%));\n}\n"
  },
  {
    "path": "src/styles/bootstrap/reset.less",
    "content": "//\n// Reset CSS\n// Adapted from http://github.com/necolas/normalize.css\n// --------------------------------------------------\n\n\n// Display in IE6-9 and FF3\n// -------------------------\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\n\n// Display block in IE6-9 and FF3\n// -------------------------\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n\n// Prevents modern browsers from displaying 'audio' without controls\n// -------------------------\n\naudio:not([controls]) {\n    display: none;\n}\n\n// Base settings\n// -------------------------\n\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n// Focus states\na:focus {\n  .tab-focus();\n}\n// Hover & Active\na:hover,\na:active {\n  outline: 0;\n}\n\n// Prevents sub and sup affecting line-height in all browsers\n// -------------------------\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\n\n// Img border in a's and image quality\n// -------------------------\n\nimg {\n  /* Responsive images (ensure images don't scale beyond their parents) */\n  max-width: 100%; /* Part 1: Set a maxium relative to the parent */\n  width: auto\\9; /* IE7-8 need help adjusting responsive images */\n  height: auto; /* Part 2: Scale the height according to the width, otherwise you get stretching */\n\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n\n// Prevent max-width from affecting Google Maps\n#map_canvas img,\n.google-maps img {\n  max-width: none;\n}\n\n// Forms\n// -------------------------\n\n// Font size in all browsers, margin changes, misc consistency\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\nbutton,\ninput {\n  *overflow: visible; // Inner spacing ie IE6/7\n  line-height: normal; // FF3/4 have !important on line-height in UA stylesheet\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner { // Inner padding and border oddities in FF3/4\n  padding: 0;\n  border: 0;\n}\nbutton,\nhtml input[type=\"button\"], // Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls.\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n    -webkit-appearance: button; // Corrects inability to style clickable `input` types in iOS.\n    cursor: pointer; // Improves usability and consistency of cursor style between image-type `input` and others.\n}\nlabel,\nselect,\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n    cursor: pointer; // Improves usability and consistency of cursor style between image-type `input` and others.\n}\ninput[type=\"search\"] { // Appearance in Safari/Chrome\n  .box-sizing(content-box);\n  -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5\n}\ntextarea {\n  overflow: auto; // Remove vertical scrollbar in IE6-9\n  vertical-align: top; // Readability and alignment cross-browser\n}\n\n\n// Printing\n// -------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n  * {\n    text-shadow: none !important;\n    color: #000 !important; // Black prints faster: h5bp.com/s\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  // Don't show links for images, or javascript/internal links\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group; // h5bp.com/t\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  @page {\n    margin: 0.5cm;\n  }\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/scaffolding.less",
    "content": "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Body reset\n// -------------------------\n\nbody {\n  margin: 0;\n  font-family: @baseFontFamily;\n  font-size: @baseFontSize;\n  line-height: @baseLineHeight;\n  color: @textColor;\n  background-color: @bodyBackground;\n}\n\n\n// Links\n// -------------------------\n\na {\n  color: @linkColor;\n  text-decoration: none;\n}\na:hover,\na:focus {\n  color: @linkColorHover;\n  text-decoration: underline;\n}\n\n\n// Images\n// -------------------------\n\n// Rounded corners\n.img-rounded {\n  .border-radius(6px);\n}\n\n// Add polaroid-esque trim\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0,0,0,.2);\n  .box-shadow(0 1px 3px rgba(0,0,0,.1));\n}\n\n// Perfect circle\n.img-circle {\n  .border-radius(500px); // crank the border-radius so it works with most reasonably sized images\n}\n"
  },
  {
    "path": "src/styles/bootstrap/sprites.less",
    "content": "//\n// Sprites\n// --------------------------------------------------\n\n\n// ICONS\n// -----\n\n// All icons receive the styles of the <i> tag with a base class\n// of .i and are then given a unique class to add width, height,\n// and background-position. Your resulting HTML will look like\n// <i class=\"icon-inbox\"></i>.\n\n// For the white version of the icons, just add the .icon-white class:\n// <i class=\"icon-inbox icon-white\"></i>\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  .ie7-restore-right-whitespace();\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"@{iconSpritePath}\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n  margin-top: 1px;\n}\n\n/* White icons with optional class, or on hover/focus/active states of certain elements */\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:focus > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > li > a:focus > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:focus > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"],\n.dropdown-submenu:focus > a > [class*=\" icon-\"] {\n  background-image: url(\"@{iconWhiteSpritePath}\");\n}\n\n.icon-glass              { background-position: 0      0; }\n.icon-music              { background-position: -24px  0; }\n.icon-search             { background-position: -48px  0; }\n.icon-envelope           { background-position: -72px  0; }\n.icon-heart              { background-position: -96px  0; }\n.icon-star               { background-position: -120px 0; }\n.icon-star-empty         { background-position: -144px 0; }\n.icon-user               { background-position: -168px 0; }\n.icon-film               { background-position: -192px 0; }\n.icon-th-large           { background-position: -216px 0; }\n.icon-th                 { background-position: -240px 0; }\n.icon-th-list            { background-position: -264px 0; }\n.icon-ok                 { background-position: -288px 0; }\n.icon-remove             { background-position: -312px 0; }\n.icon-zoom-in            { background-position: -336px 0; }\n.icon-zoom-out           { background-position: -360px 0; }\n.icon-off                { background-position: -384px 0; }\n.icon-signal             { background-position: -408px 0; }\n.icon-cog                { background-position: -432px 0; }\n.icon-trash              { background-position: -456px 0; }\n\n.icon-home               { background-position: 0      -24px; }\n.icon-file               { background-position: -24px  -24px; }\n.icon-time               { background-position: -48px  -24px; }\n.icon-road               { background-position: -72px  -24px; }\n.icon-download-alt       { background-position: -96px  -24px; }\n.icon-download           { background-position: -120px -24px; }\n.icon-upload             { background-position: -144px -24px; }\n.icon-inbox              { background-position: -168px -24px; }\n.icon-play-circle        { background-position: -192px -24px; }\n.icon-repeat             { background-position: -216px -24px; }\n.icon-refresh            { background-position: -240px -24px; }\n.icon-list-alt           { background-position: -264px -24px; }\n.icon-lock               { background-position: -287px -24px; } // 1px off\n.icon-flag               { background-position: -312px -24px; }\n.icon-headphones         { background-position: -336px -24px; }\n.icon-volume-off         { background-position: -360px -24px; }\n.icon-volume-down        { background-position: -384px -24px; }\n.icon-volume-up          { background-position: -408px -24px; }\n.icon-qrcode             { background-position: -432px -24px; }\n.icon-barcode            { background-position: -456px -24px; }\n\n.icon-tag                { background-position: 0      -48px; }\n.icon-tags               { background-position: -25px  -48px; } // 1px off\n.icon-book               { background-position: -48px  -48px; }\n.icon-bookmark           { background-position: -72px  -48px; }\n.icon-print              { background-position: -96px  -48px; }\n.icon-camera             { background-position: -120px -48px; }\n.icon-font               { background-position: -144px -48px; }\n.icon-bold               { background-position: -167px -48px; } // 1px off\n.icon-italic             { background-position: -192px -48px; }\n.icon-text-height        { background-position: -216px -48px; }\n.icon-text-width         { background-position: -240px -48px; }\n.icon-align-left         { background-position: -264px -48px; }\n.icon-align-center       { background-position: -288px -48px; }\n.icon-align-right        { background-position: -312px -48px; }\n.icon-align-justify      { background-position: -336px -48px; }\n.icon-list               { background-position: -360px -48px; }\n.icon-indent-left        { background-position: -384px -48px; }\n.icon-indent-right       { background-position: -408px -48px; }\n.icon-facetime-video     { background-position: -432px -48px; }\n.icon-picture            { background-position: -456px -48px; }\n\n.icon-pencil             { background-position: 0      -72px; }\n.icon-map-marker         { background-position: -24px  -72px; }\n.icon-adjust             { background-position: -48px  -72px; }\n.icon-tint               { background-position: -72px  -72px; }\n.icon-edit               { background-position: -96px  -72px; }\n.icon-share              { background-position: -120px -72px; }\n.icon-check              { background-position: -144px -72px; }\n.icon-move               { background-position: -168px -72px; }\n.icon-step-backward      { background-position: -192px -72px; }\n.icon-fast-backward      { background-position: -216px -72px; }\n.icon-backward           { background-position: -240px -72px; }\n.icon-play               { background-position: -264px -72px; }\n.icon-pause              { background-position: -288px -72px; }\n.icon-stop               { background-position: -312px -72px; }\n.icon-forward            { background-position: -336px -72px; }\n.icon-fast-forward       { background-position: -360px -72px; }\n.icon-step-forward       { background-position: -384px -72px; }\n.icon-eject              { background-position: -408px -72px; }\n.icon-chevron-left       { background-position: -432px -72px; }\n.icon-chevron-right      { background-position: -456px -72px; }\n\n.icon-plus-sign          { background-position: 0      -96px; }\n.icon-minus-sign         { background-position: -24px  -96px; }\n.icon-remove-sign        { background-position: -48px  -96px; }\n.icon-ok-sign            { background-position: -72px  -96px; }\n.icon-question-sign      { background-position: -96px  -96px; }\n.icon-info-sign          { background-position: -120px -96px; }\n.icon-screenshot         { background-position: -144px -96px; }\n.icon-remove-circle      { background-position: -168px -96px; }\n.icon-ok-circle          { background-position: -192px -96px; }\n.icon-ban-circle         { background-position: -216px -96px; }\n.icon-arrow-left         { background-position: -240px -96px; }\n.icon-arrow-right        { background-position: -264px -96px; }\n.icon-arrow-up           { background-position: -289px -96px; } // 1px off\n.icon-arrow-down         { background-position: -312px -96px; }\n.icon-share-alt          { background-position: -336px -96px; }\n.icon-resize-full        { background-position: -360px -96px; }\n.icon-resize-small       { background-position: -384px -96px; }\n.icon-plus               { background-position: -408px -96px; }\n.icon-minus              { background-position: -433px -96px; }\n.icon-asterisk           { background-position: -456px -96px; }\n\n.icon-exclamation-sign   { background-position: 0      -120px; }\n.icon-gift               { background-position: -24px  -120px; }\n.icon-leaf               { background-position: -48px  -120px; }\n.icon-fire               { background-position: -72px  -120px; }\n.icon-eye-open           { background-position: -96px  -120px; }\n.icon-eye-close          { background-position: -120px -120px; }\n.icon-warning-sign       { background-position: -144px -120px; }\n.icon-plane              { background-position: -168px -120px; }\n.icon-calendar           { background-position: -192px -120px; }\n.icon-random             { background-position: -216px -120px; width: 16px; }\n.icon-comment            { background-position: -240px -120px; }\n.icon-magnet             { background-position: -264px -120px; }\n.icon-chevron-up         { background-position: -288px -120px; }\n.icon-chevron-down       { background-position: -313px -119px; } // 1px, 1px off\n.icon-retweet            { background-position: -336px -120px; }\n.icon-shopping-cart      { background-position: -360px -120px; }\n.icon-folder-close       { background-position: -384px -120px; width: 16px; }\n.icon-folder-open        { background-position: -408px -120px; width: 16px; }\n.icon-resize-vertical    { background-position: -432px -119px; } // 1px, 1px off\n.icon-resize-horizontal  { background-position: -456px -118px; } // 1px, 2px off\n\n.icon-hdd                     { background-position: 0      -144px; }\n.icon-bullhorn                { background-position: -24px  -144px; }\n.icon-bell                    { background-position: -48px  -144px; }\n.icon-certificate             { background-position: -72px  -144px; }\n.icon-thumbs-up               { background-position: -96px  -144px; }\n.icon-thumbs-down             { background-position: -120px -144px; }\n.icon-hand-right              { background-position: -144px -144px; }\n.icon-hand-left               { background-position: -168px -144px; }\n.icon-hand-up                 { background-position: -192px -144px; }\n.icon-hand-down               { background-position: -216px -144px; }\n.icon-circle-arrow-right      { background-position: -240px -144px; }\n.icon-circle-arrow-left       { background-position: -264px -144px; }\n.icon-circle-arrow-up         { background-position: -288px -144px; }\n.icon-circle-arrow-down       { background-position: -312px -144px; }\n.icon-globe                   { background-position: -336px -144px; }\n.icon-wrench                  { background-position: -360px -144px; }\n.icon-tasks                   { background-position: -384px -144px; }\n.icon-filter                  { background-position: -408px -144px; }\n.icon-briefcase               { background-position: -432px -144px; }\n.icon-fullscreen              { background-position: -456px -144px; }\n"
  },
  {
    "path": "src/styles/bootstrap/tables.less",
    "content": "//\n// Tables\n// --------------------------------------------------\n\n\n// BASE TABLES\n// -----------------\n\ntable {\n  max-width: 100%;\n  background-color: @tableBackground;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n// BASELINE STYLES\n// ---------------\n\n.table {\n  width: 100%;\n  margin-bottom: @baseLineHeight;\n  // Cells\n  th,\n  td {\n    padding: 8px;\n    line-height: @baseLineHeight;\n    text-align: left;\n    vertical-align: top;\n    border-top: 1px solid @tableBorder;\n  }\n  th {\n    font-weight: bold;\n  }\n  // Bottom align for column headings\n  thead th {\n    vertical-align: bottom;\n  }\n  // Remove top border from thead by default\n  caption + thead tr:first-child th,\n  caption + thead tr:first-child td,\n  colgroup + thead tr:first-child th,\n  colgroup + thead tr:first-child td,\n  thead:first-child tr:first-child th,\n  thead:first-child tr:first-child td {\n    border-top: 0;\n  }\n  // Account for multiple tbody instances\n  tbody + tbody {\n    border-top: 2px solid @tableBorder;\n  }\n\n  // Nesting\n  .table {\n    background-color: @bodyBackground;\n  }\n}\n\n\n\n// CONDENSED TABLE W/ HALF PADDING\n// -------------------------------\n\n.table-condensed {\n  th,\n  td {\n    padding: 4px 5px;\n  }\n}\n\n\n// BORDERED VERSION\n// ----------------\n\n.table-bordered {\n  border: 1px solid @tableBorder;\n  border-collapse: separate; // Done so we can round those corners!\n  *border-collapse: collapse; // IE7 can't round corners anyway\n  border-left: 0;\n  .border-radius(@baseBorderRadius);\n  th,\n  td {\n    border-left: 1px solid @tableBorder;\n  }\n  // Prevent a double border\n  caption + thead tr:first-child th,\n  caption + tbody tr:first-child th,\n  caption + tbody tr:first-child td,\n  colgroup + thead tr:first-child th,\n  colgroup + tbody tr:first-child th,\n  colgroup + tbody tr:first-child td,\n  thead:first-child tr:first-child th,\n  tbody:first-child tr:first-child th,\n  tbody:first-child tr:first-child td {\n    border-top: 0;\n  }\n  // For first th/td in the first row in the first thead or tbody\n  thead:first-child tr:first-child > th:first-child,\n  tbody:first-child tr:first-child > td:first-child,\n  tbody:first-child tr:first-child > th:first-child {\n    .border-top-left-radius(@baseBorderRadius);\n  }\n  // For last th/td in the first row in the first thead or tbody\n  thead:first-child tr:first-child > th:last-child,\n  tbody:first-child tr:first-child > td:last-child,\n  tbody:first-child tr:first-child > th:last-child {\n    .border-top-right-radius(@baseBorderRadius);\n  }\n  // For first th/td (can be either) in the last row in the last thead, tbody, and tfoot\n  thead:last-child tr:last-child > th:first-child,\n  tbody:last-child tr:last-child > td:first-child,\n  tbody:last-child tr:last-child > th:first-child,\n  tfoot:last-child tr:last-child > td:first-child,\n  tfoot:last-child tr:last-child > th:first-child {\n    .border-bottom-left-radius(@baseBorderRadius);\n  }\n  // For last th/td (can be either) in the last row in the last thead, tbody, and tfoot\n  thead:last-child tr:last-child > th:last-child,\n  tbody:last-child tr:last-child > td:last-child,\n  tbody:last-child tr:last-child > th:last-child,\n  tfoot:last-child tr:last-child > td:last-child,\n  tfoot:last-child tr:last-child > th:last-child {\n    .border-bottom-right-radius(@baseBorderRadius);\n  }\n\n  // Clear border-radius for first and last td in the last row in the last tbody for table with tfoot\n  tfoot + tbody:last-child tr:last-child td:first-child {\n    .border-bottom-left-radius(0);\n  }\n  tfoot + tbody:last-child tr:last-child td:last-child {\n    .border-bottom-right-radius(0);\n  }\n\n  // Special fixes to round the left border on the first td/th\n  caption + thead tr:first-child th:first-child,\n  caption + tbody tr:first-child td:first-child,\n  colgroup + thead tr:first-child th:first-child,\n  colgroup + tbody tr:first-child td:first-child {\n    .border-top-left-radius(@baseBorderRadius);\n  }\n  caption + thead tr:first-child th:last-child,\n  caption + tbody tr:first-child td:last-child,\n  colgroup + thead tr:first-child th:last-child,\n  colgroup + tbody tr:first-child td:last-child {\n    .border-top-right-radius(@baseBorderRadius);\n  }\n\n}\n\n\n\n\n// ZEBRA-STRIPING\n// --------------\n\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n.table-striped {\n  > tbody {\n    > tr:nth-child(odd) > td,\n    > tr:nth-child(odd) > th {\n      background-color: @tableBackgroundAccent;\n    }\n  }\n}\n\n\n// HOVER EFFECT\n// ------------\n// Placed here since it has to come after the potential zebra striping\n.table-hover {\n  > tbody {\n    tr:hover > td,\n    tr:hover > th {\n      background-color: @tableBackgroundHover;\n    }\n  }\n}\n\n\n// TABLE CELL SIZING\n// -----------------\n\n// Reset default grid behavior\ntable td[class*=\"span\"],\ntable th[class*=\"span\"],\n.row-fluid table td[class*=\"span\"],\n.row-fluid table th[class*=\"span\"] {\n  display: table-cell;\n  float: none; // undo default grid column styles\n  margin-left: 0; // undo default grid column styles\n}\n\n// Change the column widths to account for td/th padding\n.table td,\n.table th {\n  &.span1     { .tableColumns(1); }\n  &.span2     { .tableColumns(2); }\n  &.span3     { .tableColumns(3); }\n  &.span4     { .tableColumns(4); }\n  &.span5     { .tableColumns(5); }\n  &.span6     { .tableColumns(6); }\n  &.span7     { .tableColumns(7); }\n  &.span8     { .tableColumns(8); }\n  &.span9     { .tableColumns(9); }\n  &.span10    { .tableColumns(10); }\n  &.span11    { .tableColumns(11); }\n  &.span12    { .tableColumns(12); }\n}\n\n\n\n// TABLE BACKGROUNDS\n// -----------------\n// Exact selectors below required to override .table-striped\n\n.table tbody tr {\n  &.success > td {\n    background-color: @successBackground;\n  }\n  &.error > td {\n    background-color: @errorBackground;\n  }\n  &.warning > td {\n    background-color: @warningBackground;\n  }\n  &.info > td {\n    background-color: @infoBackground;\n  }\n}\n\n// Hover states for .table-hover\n.table-hover tbody tr {\n  &.success:hover > td {\n    background-color: darken(@successBackground, 5%);\n  }\n  &.error:hover > td {\n    background-color: darken(@errorBackground, 5%);\n  }\n  &.warning:hover > td {\n    background-color: darken(@warningBackground, 5%);\n  }\n  &.info:hover > td {\n    background-color: darken(@infoBackground, 5%);\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/thumbnails.less",
    "content": "//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Note: `.thumbnails` and `.thumbnails > li` are overriden in responsive files\n\n// Make wrapper ul behave like the grid\n.thumbnails {\n  margin-left: -@gridGutterWidth;\n  list-style: none;\n  .clearfix();\n}\n// Fluid rows have no left margin\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n\n// Float li to make thumbnails appear in a row\n.thumbnails > li {\n  float: left; // Explicity set the float since we don't require .span* classes\n  margin-bottom: @baseLineHeight;\n  margin-left: @gridGutterWidth;\n}\n\n// The actual thumbnail (can be `a` or `div`)\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: @baseLineHeight;\n  border: 1px solid #ddd;\n  .border-radius(@baseBorderRadius);\n  .box-shadow(0 1px 3px rgba(0,0,0,.055));\n  .transition(all .2s ease-in-out);\n}\n// Add a hover/focus state for linked versions only\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: @linkColor;\n  .box-shadow(0 1px 4px rgba(0,105,214,.25));\n}\n\n// Images and captions\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-left: auto;\n  margin-right: auto;\n}\n.thumbnail .caption {\n  padding: 9px;\n  color: @gray;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/tooltip.less",
    "content": "//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n  position: absolute;\n  z-index: @zindexTooltip;\n  display: block;\n  visibility: visible;\n  font-size: 11px;\n  line-height: 1.4;\n  .opacity(0);\n  &.in     { .opacity(80); }\n  &.top    { margin-top:  -3px; padding: 5px 0; }\n  &.right  { margin-left:  3px; padding: 0 5px; }\n  &.bottom { margin-top:   3px; padding: 5px 0; }\n  &.left   { margin-left: -3px; padding: 0 5px; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n  max-width: 200px;\n  padding: 8px;\n  color: @tooltipColor;\n  text-align: center;\n  text-decoration: none;\n  background-color: @tooltipBackground;\n  .border-radius(@baseBorderRadius);\n}\n\n// Arrows\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip {\n  &.top .tooltip-arrow {\n    bottom: 0;\n    left: 50%;\n    margin-left: -@tooltipArrowWidth;\n    border-width: @tooltipArrowWidth @tooltipArrowWidth 0;\n    border-top-color: @tooltipArrowColor;\n  }\n  &.right .tooltip-arrow {\n    top: 50%;\n    left: 0;\n    margin-top: -@tooltipArrowWidth;\n    border-width: @tooltipArrowWidth @tooltipArrowWidth @tooltipArrowWidth 0;\n    border-right-color: @tooltipArrowColor;\n  }\n  &.left .tooltip-arrow {\n    top: 50%;\n    right: 0;\n    margin-top: -@tooltipArrowWidth;\n    border-width: @tooltipArrowWidth 0 @tooltipArrowWidth @tooltipArrowWidth;\n    border-left-color: @tooltipArrowColor;\n  }\n  &.bottom .tooltip-arrow {\n    top: 0;\n    left: 50%;\n    margin-left: -@tooltipArrowWidth;\n    border-width: 0 @tooltipArrowWidth @tooltipArrowWidth;\n    border-bottom-color: @tooltipArrowColor;\n  }\n}\n"
  },
  {
    "path": "src/styles/bootstrap/type.less",
    "content": "//\n// Typography\n// --------------------------------------------------\n\n\n// Body text\n// -------------------------\n\np {\n  margin: 0 0 @baseLineHeight / 2;\n}\n.lead {\n  margin-bottom: @baseLineHeight;\n  font-size: @baseFontSize * 1.5;\n  font-weight: 200;\n  line-height: @baseLineHeight * 1.5;\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall   { font-size: 85%; }\n\nstrong  { font-weight: bold; }\nem      { font-style: italic; }\ncite    { font-style: normal; }\n\n// Utility classes\n.muted               { color: @grayLight; }\na.muted:hover,\na.muted:focus        { color: darken(@grayLight, 10%); }\n\n.text-warning        { color: @warningText; }\na.text-warning:hover,\na.text-warning:focus { color: darken(@warningText, 10%); }\n\n.text-error          { color: @errorText; }\na.text-error:hover,\na.text-error:focus   { color: darken(@errorText, 10%); }\n\n.text-info           { color: @infoText; }\na.text-info:hover,\na.text-info:focus    { color: darken(@infoText, 10%); }\n\n.text-success        { color: @successText; }\na.text-success:hover,\na.text-success:focus { color: darken(@successText, 10%); }\n\n.text-left           { text-align: left; }\n.text-right          { text-align: right; }\n.text-center         { text-align: center; }\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6 {\n  margin: (@baseLineHeight / 2) 0;\n  font-family: @headingsFontFamily;\n  font-weight: @headingsFontWeight;\n  line-height: @baseLineHeight;\n  color: @headingsColor;\n  text-rendering: optimizelegibility; // Fix the character spacing for headings\n  small {\n    font-weight: normal;\n    line-height: 1;\n    color: @grayLight;\n  }\n}\n\nh1,\nh2,\nh3 { line-height: @baseLineHeight * 2; }\n\nh1 { font-size: @baseFontSize * 2.75; } // ~38px\nh2 { font-size: @baseFontSize * 2.25; } // ~32px\nh3 { font-size: @baseFontSize * 1.75; } // ~24px\nh4 { font-size: @baseFontSize * 1.25; } // ~18px\nh5 { font-size: @baseFontSize; }\nh6 { font-size: @baseFontSize * 0.85; } // ~12px\n\nh1 small { font-size: @baseFontSize * 1.75; } // ~24px\nh2 small { font-size: @baseFontSize * 1.25; } // ~18px\nh3 small { font-size: @baseFontSize; }\nh4 small { font-size: @baseFontSize; }\n\n\n// Page header\n// -------------------------\n\n.page-header {\n  padding-bottom: (@baseLineHeight / 2) - 1;\n  margin: @baseLineHeight 0 (@baseLineHeight * 1.5);\n  border-bottom: 1px solid @grayLighter;\n}\n\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul, ol {\n  padding: 0;\n  margin: 0 0 @baseLineHeight / 2 25px;\n}\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\nli {\n  line-height: @baseLineHeight;\n}\n\n// Remove default list styles\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\n\n// Single-line list items\nul.inline,\nol.inline {\n  margin-left: 0;\n  list-style: none;\n  > li {\n    display: inline-block;\n    .ie7-inline-block();\n    padding-left: 5px;\n    padding-right: 5px;\n  }\n}\n\n// Description Lists\ndl {\n  margin-bottom: @baseLineHeight;\n}\ndt,\ndd {\n  line-height: @baseLineHeight;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: @baseLineHeight / 2;\n}\n// Horizontal layout (like forms)\n.dl-horizontal {\n  .clearfix(); // Ensure dl clears floats if empty dd elements present\n  dt {\n    float: left;\n    width: @horizontalComponentOffset - 20;\n    clear: left;\n    text-align: right;\n    .text-overflow();\n  }\n  dd {\n    margin-left: @horizontalComponentOffset;\n  }\n}\n\n// MISC\n// ----\n\n// Horizontal rules\nhr {\n  margin: @baseLineHeight 0;\n  border: 0;\n  border-top: 1px solid @hrBorder;\n  border-bottom: 1px solid @white;\n}\n\n// Abbreviations and acronyms\nabbr[title],\n// Added data-* attribute to help out our tooltip plugin, per https://github.com/twitter/bootstrap/issues/5257\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted @grayLight;\n}\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 @baseLineHeight;\n  border-left: 5px solid @grayLighter;\n  p {\n    margin-bottom: 0;\n    font-size: @baseFontSize * 1.25;\n    font-weight: 300;\n    line-height: 1.25;\n  }\n  small {\n    display: block;\n    line-height: @baseLineHeight;\n    color: @grayLight;\n    &:before {\n      content: '\\2014 \\00A0';\n    }\n  }\n\n  // Float right with text-align: right\n  &.pull-right {\n    float: right;\n    padding-right: 15px;\n    padding-left: 0;\n    border-right: 5px solid @grayLighter;\n    border-left: 0;\n    p,\n    small {\n      text-align: right;\n    }\n    small {\n      &:before {\n        content: '';\n      }\n      &:after {\n        content: '\\00A0 \\2014';\n      }\n    }\n  }\n}\n\n// Quotes\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\n// Addresses\naddress {\n  display: block;\n  margin-bottom: @baseLineHeight;\n  font-style: normal;\n  line-height: @baseLineHeight;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/utilities.less",
    "content": "//\n// Utility classes\n// --------------------------------------------------\n\n\n// Quick floats\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n\n// Toggling content\n.hide {\n  display: none;\n}\n.show {\n  display: block;\n}\n\n// Visibility\n.invisible {\n  visibility: hidden;\n}\n\n// For Affix plugin\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "src/styles/bootstrap/variables.less",
    "content": "//\n// Variables\n// --------------------------------------------------\n// Edited for Brackets:\n//  - chnaged @baseFontSize and @baseLineHeight\n\n// Global values\n// --------------------------------------------------\n\n\n// Grays\n// -------------------------\n@black:                 #000;\n@grayDarker:            #222;\n@grayDark:              #333;\n@gray:                  #555;\n@grayLight:             #999;\n@grayLighter:           #eee;\n@white:                 #fff;\n\n\n// Accent colors\n// -------------------------\n@blue:                  #049cdb;\n@blueDark:              #0064cd;\n@green:                 #46a546;\n@red:                   #9d261d;\n@yellow:                #ffc40d;\n@orange:                #f89406;\n@pink:                  #c3325f;\n@purple:                #7a43b6;\n\n\n// Scaffolding\n// -------------------------\n@bodyBackground:        @white;\n@textColor:             @grayDark;\n\n\n// Links\n// -------------------------\n@linkColor:             #08c;\n@linkColorHover:        darken(@linkColor, 15%);\n\n\n// Typography\n// -------------------------\n@sansFontFamily:        \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n@serifFontFamily:       Georgia, \"Times New Roman\", Times, serif;\n@monoFontFamily:        Monaco, Menlo, Consolas, \"Courier New\", monospace;\n\n@baseFontSize:          13px;\n@baseFontFamily:        @sansFontFamily;\n@baseLineHeight:        18px;\n@altFontFamily:         @serifFontFamily;\n\n@headingsFontFamily:    inherit; // empty to use BS default, @baseFontFamily\n@headingsFontWeight:    bold;    // instead of browser default, bold\n@headingsColor:         inherit; // empty to use BS default, @textColor\n\n\n// Component sizing\n// -------------------------\n// Based on 14px font-size and 20px line-height\n\n@fontSizeLarge:         @baseFontSize * 1.25; // ~18px\n@fontSizeSmall:         @baseFontSize * 0.85; // ~12px\n@fontSizeMini:          @baseFontSize * 0.75; // ~11px\n\n@paddingLarge:          11px 19px; // 44px\n@paddingSmall:          2px 10px;  // 26px\n@paddingMini:           0 6px;   // 22px\n\n@baseBorderRadius:      4px;\n@borderRadiusLarge:     6px;\n@borderRadiusSmall:     3px;\n\n\n// Tables\n// -------------------------\n@tableBackground:                   transparent; // overall background-color\n@tableBackgroundAccent:             #f9f9f9; // for striping\n@tableBackgroundHover:              #f5f5f5; // for hover\n@tableBorder:                       #ddd; // table and cell border\n\n// Buttons\n// -------------------------\n@btnBackground:                     @white;\n@btnBackgroundHighlight:            darken(@white, 10%);\n@btnBorder:                         #ccc;\n\n@btnPrimaryBackground:              @linkColor;\n@btnPrimaryBackgroundHighlight:     spin(@btnPrimaryBackground, 20%);\n\n@btnInfoBackground:                 #5bc0de;\n@btnInfoBackgroundHighlight:        #2f96b4;\n\n@btnSuccessBackground:              #62c462;\n@btnSuccessBackgroundHighlight:     #51a351;\n\n@btnWarningBackground:              lighten(@orange, 15%);\n@btnWarningBackgroundHighlight:     @orange;\n\n@btnDangerBackground:               #ee5f5b;\n@btnDangerBackgroundHighlight:      #bd362f;\n\n@btnInverseBackground:              #444;\n@btnInverseBackgroundHighlight:     @grayDarker;\n\n\n// Forms\n// -------------------------\n@inputBackground:               @white;\n@inputBorder:                   #ccc;\n@inputBorderRadius:             @baseBorderRadius;\n@inputDisabledBackground:       @grayLighter;\n@formActionsBackground:         #f5f5f5;\n@inputHeight:                   @baseLineHeight + 10px; // base line-height + 8px vertical padding + 2px top/bottom border\n\n\n// Dropdowns\n// -------------------------\n@dropdownBackground:            @white;\n@dropdownBorder:                rgba(0,0,0,.2);\n@dropdownDividerTop:            #e5e5e5;\n@dropdownDividerBottom:         @white;\n\n@dropdownLinkColor:             @grayDark;\n@dropdownLinkColorHover:        @white;\n@dropdownLinkColorActive:       @white;\n\n@dropdownLinkBackgroundActive:  @linkColor;\n@dropdownLinkBackgroundHover:   @dropdownLinkBackgroundActive;\n\n\n\n// COMPONENT VARIABLES\n// --------------------------------------------------\n\n\n// Z-index master list\n// -------------------------\n// Used for a bird's eye view of components dependent on the z-axis\n// Try to avoid customizing these :)\n@zindexDropdown:          1000;\n@zindexPopover:           1010;\n@zindexTooltip:           1030;\n@zindexFixedNavbar:       1030;\n@zindexModalBackdrop:     1040;\n@zindexModal:             1050;\n\n\n// Sprite icons path\n// -------------------------\n@iconSpritePath:          \"../img/glyphicons-halflings.png\";\n@iconWhiteSpritePath:     \"../img/glyphicons-halflings-white.png\";\n\n\n// Input placeholder text color\n// -------------------------\n@placeholderText:         @grayLight;\n\n\n// Hr border color\n// -------------------------\n@hrBorder:                @grayLighter;\n\n\n// Horizontal forms & lists\n// -------------------------\n@horizontalComponentOffset:       180px;\n\n\n// Wells\n// -------------------------\n@wellBackground:                  #f5f5f5;\n\n\n// Navbar\n// -------------------------\n@navbarCollapseWidth:             979px;\n@navbarCollapseDesktopWidth:      @navbarCollapseWidth + 1;\n\n@navbarHeight:                    40px;\n@navbarBackgroundHighlight:       #ffffff;\n@navbarBackground:                darken(@navbarBackgroundHighlight, 5%);\n@navbarBorder:                    darken(@navbarBackground, 12%);\n\n@navbarText:                      #777;\n@navbarLinkColor:                 #777;\n@navbarLinkColorHover:            @grayDark;\n@navbarLinkColorActive:           @gray;\n@navbarLinkBackgroundHover:       transparent;\n@navbarLinkBackgroundActive:      darken(@navbarBackground, 5%);\n\n@navbarBrandColor:                @navbarLinkColor;\n\n// Inverted navbar\n@navbarInverseBackground:                #111111;\n@navbarInverseBackgroundHighlight:       #222222;\n@navbarInverseBorder:                    #252525;\n\n@navbarInverseText:                      @grayLight;\n@navbarInverseLinkColor:                 @grayLight;\n@navbarInverseLinkColorHover:            @white;\n@navbarInverseLinkColorActive:           @navbarInverseLinkColorHover;\n@navbarInverseLinkBackgroundHover:       transparent;\n@navbarInverseLinkBackgroundActive:      @navbarInverseBackground;\n\n@navbarInverseSearchBackground:          lighten(@navbarInverseBackground, 25%);\n@navbarInverseSearchBackgroundFocus:     @white;\n@navbarInverseSearchBorder:              @navbarInverseBackground;\n@navbarInverseSearchPlaceholderColor:    #ccc;\n\n@navbarInverseBrandColor:                @navbarInverseLinkColor;\n\n\n// Pagination\n// -------------------------\n@paginationBackground:                #fff;\n@paginationBorder:                    #ddd;\n@paginationActiveBackground:          #f5f5f5;\n\n\n// Hero unit\n// -------------------------\n@heroUnitBackground:              @grayLighter;\n@heroUnitHeadingColor:            inherit;\n@heroUnitLeadColor:               inherit;\n\n\n// Form states and alerts\n// -------------------------\n@warningText:             #c09853;\n@warningBackground:       #fcf8e3;\n@warningBorder:           darken(spin(@warningBackground, -10), 3%);\n\n@errorText:               #b94a48;\n@errorBackground:         #f2dede;\n@errorBorder:             darken(spin(@errorBackground, -10), 3%);\n\n@successText:             #468847;\n@successBackground:       #dff0d8;\n@successBorder:           darken(spin(@successBackground, -10), 5%);\n\n@infoText:                #3a87ad;\n@infoBackground:          #d9edf7;\n@infoBorder:              darken(spin(@infoBackground, -10), 7%);\n\n\n// Tooltips and popovers\n// -------------------------\n@tooltipColor:            #fff;\n@tooltipBackground:       #000;\n@tooltipArrowWidth:       5px;\n@tooltipArrowColor:       @tooltipBackground;\n\n@popoverBackground:       #fff;\n@popoverArrowWidth:       10px;\n@popoverArrowColor:       #fff;\n@popoverTitleBackground:  darken(@popoverBackground, 3%);\n\n// Special enhancement for popovers\n@popoverArrowOuterWidth:  @popoverArrowWidth + 1;\n@popoverArrowOuterColor:  rgba(0,0,0,.25);\n\n\n\n// GRID\n// --------------------------------------------------\n\n\n// Default 940px grid\n// -------------------------\n@gridColumns:             12;\n@gridColumnWidth:         60px;\n@gridGutterWidth:         20px;\n@gridRowWidth:            (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));\n\n// 1200px min\n@gridColumnWidth1200:     70px;\n@gridGutterWidth1200:     30px;\n@gridRowWidth1200:        (@gridColumns * @gridColumnWidth1200) + (@gridGutterWidth1200 * (@gridColumns - 1));\n\n// 768px-979px\n@gridColumnWidth768:      42px;\n@gridGutterWidth768:      20px;\n@gridRowWidth768:         (@gridColumns * @gridColumnWidth768) + (@gridGutterWidth768 * (@gridColumns - 1));\n\n\n// Fluid grid\n// -------------------------\n@fluidGridColumnWidth:    percentage(@gridColumnWidth/@gridRowWidth);\n@fluidGridGutterWidth:    percentage(@gridGutterWidth/@gridRowWidth);\n\n// 1200px min\n@fluidGridColumnWidth1200:     percentage(@gridColumnWidth1200/@gridRowWidth1200);\n@fluidGridGutterWidth1200:     percentage(@gridGutterWidth1200/@gridRowWidth1200);\n\n// 768px-979px\n@fluidGridColumnWidth768:      percentage(@gridColumnWidth768/@gridRowWidth768);\n@fluidGridGutterWidth768:      percentage(@gridGutterWidth768/@gridRowWidth768);\n"
  },
  {
    "path": "src/styles/bootstrap/wells.less",
    "content": "//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: @wellBackground;\n  border: 1px solid darken(@wellBackground, 7%);\n  .border-radius(@baseBorderRadius);\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n  blockquote {\n    border-color: #ddd;\n    border-color: rgba(0,0,0,.15);\n  }\n}\n\n// Sizes\n.well-large {\n  padding: 24px;\n  .border-radius(@borderRadiusLarge);\n}\n.well-small {\n  padding: 9px;\n  .border-radius(@borderRadiusSmall);\n}\n"
  },
  {
    "path": "src/styles/brackets.less",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*\n * This file first imports all of the shared LESS/CSS, and then defines\n * version-specific layout (e.g. layout for the App shell, or layout for\n * the In-Browser version on Firefox).\n *\n * Going forward, we may have different versions of this file for different\n * Versions (e.g. App, In-Browser, etc.)\n *\n * Anything that is general/reusable should be pushed up into a LESS file\n * in the \"styles\" directory. See \"brackets_shared.less\" for the organization\n *\n * Date: @DATE\n */\n\n/* IMPORTANT: importing brackets_shared should be the first step in this file\n * This is so that imported CSS files (NOT LESS files) end up in the\n * right place\n */\n@import \"brackets_shared.less\";\n\n/* Overall layout */\n\nhtml, body {\n    color: @bc-text;\n    height: 100%;\n    overflow: hidden;\n\n    /* Turn off selection for UI elements */\n    .user-select(none);\n\n    /* And make sure we get a pointer cursor even over text */\n    cursor: default;\n\n    &.platform-mac {\n        // Use gray scale antialiasing for UI. Code view editor-holder\n        // overrides this to use subpixel antialiasing on Mac, which then\n        // can be overridden by setting \"fontSmoothing\" preference to\n        // \"antialiased\". Gray scale AA is used for UI parts which use\n        // SourceSansPro font, which does't look good with subpixel AA,\n        // especially on low resolution monitors.\n        -webkit-font-smoothing: antialiased;\n    }\n\n    .dark,\n    &.dark {\n         color: @dark-bc-text;\n    }\n}\n\n.subpixel-aa{\n    -webkit-font-smoothing: subpixel-antialiased;\n}\n\n.resizing-container {\n    position: absolute;\n    top: 0;\n    width: 100%;\n    height: 100%;\n    z-index: @z-index-brackets-panel-resizer;\n\n    &.horz-resizing {\n        cursor: col-resize;\n    }\n\n    &.vert-resizing {\n        cursor: row-resize;\n    }\n}\n\na, img {\n    -webkit-user-drag: none;\n}\n\n.main-view {\n    background: @bc-menu-bg; // to keep the theme background consistent\n    height: 100%;\n\n    .dark & {\n        background: @dark-bc-menu-bg;\n    }\n\n    .sidebar, .content {\n        height: 100%;\n        position: absolute;\n        top: 0;\n    }\n\n    .sidebar {\n        .vbox;\n        left: 0;\n        width: @sidebar-width;  // changed dynamically via Resizer\n        white-space: nowrap;\n    }\n\n    .content {\n        padding: 0;\n        left: @sidebar-width;  // changed dynamically via Resizer\n        right: @main-toolbar-width;\n    }\n\n    .force-right-zero {\n        right: 0;\n    }\n}\n\n#titlebar, .modal-bar {\n    border-bottom: 1px solid @bc-panel-border;\n    box-shadow: 0 1px 3px @bc-shadow-small;\n\n    // Make sure the bottom box-shadow goes above the editor (position: relative needed to start a new stacking group)\n    position: relative;\n    z-index: @z-index-brackets-toolbar;\n\n    .dark & {\n        border-bottom: 1px solid @dark-bc-shadow;\n        box-shadow: 0 1px 3px @dark-bc-shadow-small;\n    }\n}\n\n.forced-hidden {\n    display: none !important;\n}\n\n.busyCursor {\n    cursor: wait !important;\n}\n\n#status-bar {\n    position: relative;\n    background: @bc-bg-status-bar;\n    border-top: 1px solid @bc-panel-border;\n    box-sizing: border-box;\n    color: @bc-text;\n    font-family: @sansFontFamily;\n    font-size: 11px;\n    line-height: 25px;\n    height: 26px;\n    overflow: hidden;\n    .dark & {\n        background: @dark-bc-bg-status-bar;\n        border-top: 1px solid @dark-bc-panel-separator;\n        color: @dark-bc-text;\n    }\n}\n\n#status-info {\n    color: @bc-text;\n    left: 10px;\n    position: absolute;\n    white-space: nowrap;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n\n    div {\n        display: inline;\n    }\n}\n\n#status-file {\n    color: @bc-text-quiet;\n\n    .dark & {\n        color: @dark-bc-text-quiet;\n    }\n}\n\n#status-indicators {\n    background: @bc-bg-status-bar;\n    color: @bc-text;\n    position: absolute;\n    right: 0;\n    text-align: right;\n    white-space: nowrap;\n\n    .dark & {\n        background: @dark-bc-bg-status-bar;\n        color: @dark-bc-text;\n    }\n\n    > div {\n        &:not(.spinner) {\n            border-left: 1px solid @bc-panel-border;\n\n            .dark & {\n                border-left: 1px solid @dark-bc-panel-separator;\n            }\n        }\n        float: right;\n        padding: 0 10px;\n    }\n    .spinner {  // spinner is tiny & usually invisible; reduce margin so gap is less glaring\n        margin: 6px 10px;\n        padding: 0;\n    }\n\n    #status-language {\n        border-right: 1px solid @bc-panel-border;\n        padding: 0;\n        margin: 0;\n\n        .dark & {\n            border-right: 1px solid @dark-bc-panel-separator;\n        }\n    }\n\n    /* dropdown button styling */\n    .btn-status-bar {\n        border: 0;\n        background-color: inherit;\n        color: inherit;\n        font: inherit;\n        height: inherit;\n        line-height: inherit;\n        margin: 0;\n        padding: 0 21px 0 10px;\n        vertical-align: top;\n        width: auto;\n        cursor: pointer;\n        border-radius: 0;\n        box-shadow: none;\n        text-shadow: none;\n\n        &:focus {\n            outline: 0;\n        }\n        &[disabled] {\n            cursor: inherit;\n            background: none;\n            text-decoration: none;\n        }\n        &::after {\n            top: 10px;\n            right: 8px;\n        }\n    }\n\n}\n\n#status-indent > * {\n    display: inline-block;\n}\n\n#status-indent > *.hidden {\n    display: none;\n}\n\n#indent-type, #indent-width-label {\n    cursor: pointer;\n    margin-right: 3px;\n}\n\n#status-overwrite:hover, #indent-type:hover, #indent-width-label:hover {\n    text-decoration: underline;\n}\n\n#indent-width-input {\n    font-size: 11px;\n    font-weight: @font-weight-semibold;\n    height: 13px;\n    line-height: 1;\n    vertical-align: middle;\n    color: @bc-text;\n    margin: 0;\n    padding: 0 3px 2px;\n    position: relative;\n    left: 0;\n    top: -1px;\n    width: 6px;\n    transition: 0.1s linear all;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\n#indent-width-input:focus {\n\n}\n\n#indent-width-input::-webkit-inner-spin-button {\n    -webkit-appearance: none;\n    margin: 0;\n}\n\n#status-overwrite {\n    transition: background-color 3s;\n    background-color: rgba(255, 255, 255, 0);\n    color: @bc-text;\n    cursor: pointer;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\n#status-overwrite.flash {\n    transition: background-color 1s;\n    background-color: rgb(120, 178, 242);\n}\n\n\n#editor-holder {\n    position: relative;\n\n    /* Placeholder shown when there is no editor open */\n\n    .view-pane {\n        display: block !important;\n        margin: 0;\n        overflow: hidden;\n    }\n\n    .pane-content {\n        display: block;\n        margin: 0;\n        overflow: hidden;\n        height: 100%;\n        width: 100%;\n        box-sizing: border-box;\n\n        /* Image Preview */\n        .image-view {\n            overflow: hidden;\n            position: absolute;\n            top: 0;\n            right: 0;\n            bottom: 0;\n            left: 0;\n            text-align: center;\n            .image-centering {\n                display: inline-block;\n                vertical-align: middle;\n                width: 90%; //As long as the width isn't set on the image itself theres no need for max-width/height\n                height: 90%;\n            }\n            .image-data {\n                font-weight: @font-weight-semibold;\n            }\n        }\n\n        .image-view:before {\n            content: '';\n            display: inline-block;\n            height: 100%;\n            margin-right: -0.25em; /* Adjusts for spacing */\n            vertical-align: middle;\n        }\n\n        .image-preview {\n            background: url(images/preview-bg.svg);\n            box-shadow: 0 1px 3px @bc-shadow;\n            max-height: 100%;\n\n            .dark & {\n                background: url(images/preview-bg-dark.svg);\n                box-shadow: 0 1px 3px @dark-bc-shadow;\n            }\n        }\n\n        .image-header {\n            display: block;\n            width: 100%;\n            height: 38px;\n            margin-bottom: 15px;\n        }\n\n        .image-data,\n        .image-path {\n            text-align: left;\n            .user-select(text);\n            white-space: nowrap;\n            text-overflow: ellipsis;\n            overflow: hidden;\n        }\n\n        .image-data::selection,\n        .image-path::selection {\n            background: @selection-color-focused;\n        }\n\n        .image {\n            position: relative;\n            height: calc(~'100% - 53px');//.image-header height+margin\n        }\n\n        .image-guide,\n        .image-tip,\n        .image-scale {\n            pointer-events: none;\n        }\n\n        .image-scale {\n            display: block;\n            position: absolute;\n            top: 5px;\n            left: 5px;\n            width: 40px;\n            text-align: center;\n            background-color: rgba(0, 0, 0, 0.8);\n            color: @bc-text-alt;\n            border-radius: 3px;\n            box-shadow: 0 1px 3px @bc-shadow;\n\n            .dark & {\n                color: @dark-bc-text-alt;\n                box-shadow: 0 1px 3px @dark-bc-shadow;\n            }\n        }\n\n        .image-tip {\n            display: block;\n            position: absolute;\n            text-align: left;\n            white-space: nowrap;\n            padding: 6px 9px;\n            color: @bc-text-alt;\n            background-color: rgba(0, 0, 0, 0.8);\n            font-size: 11px;\n            font-family: @sourceFontFamily;\n            line-height: 13px;\n            border-radius: 3px;\n            box-shadow: 0 1px 3px @bc-shadow;\n\n            .dark & {\n                color: @dark-bc-text-alt;\n                box-shadow: 0 1px 3px @dark-bc-shadow;\n            }\n        }\n\n        .x-value,\n        .y-value {\n            text-align: right;\n        }\n\n        .tip-container {\n            border: 0;\n        }\n\n        .horz-guide {\n            background-image: url(\"images/horizontal-dash.svg\");\n            background-repeat: repeat-x;\n            width: 8px;\n            height: 1px;\n        }\n\n        .vert-guide {\n            background-image: url(\"images/vertical-dash.svg\");\n            background-repeat: repeat-y;\n            width: 1px;\n            height: 8px;\n        }\n\n        .horz-guide,\n        .vert-guide {\n            position: absolute;\n            display: block;\n        }\n    }\n    .pane-header {\n        opacity: 0.7; // quieten inactive pane header\n        box-sizing: border-box;\n        border-bottom:  1px solid rgba(0, 0, 0, 0.05);\n        padding: 5px 10px;\n        background-color: @background;\n        white-space: nowrap;\n        overflow: hidden;\n        text-overflow: ellipsis;\n\n        &-text {\n            display: inline;\n        }\n\n        .dark & {\n            background-color: #1d1f21; // not using a variable on purpose.\n            border-bottom-color: rgba(255, 255, 255, 0.05);\n        }\n\n        &-flipview-btn {\n            position: relative;\n            display: none;\n            top: 0;\n            padding-top: 2px;\n            padding-right: 4px;\n            padding-left: 4px;\n            margin-left: 0;\n            margin-bottom: 0;\n            .sprite-icon(0, 0, 13px, 13px, \"images/flip-view-icons.svg\");\n            background-origin: content-box;\n            -webkit-transform: translateZ(0); // forces GPU mode for better filter rendering on retina\n            transform: translateZ(0); // future proofing\n            z-index: 1;\n            vertical-align: middle;\n\n            &:hover {\n                background-image: url(\"images/flip-view-icons-hover.svg\")\n            }\n\n            &.flipview-icon-none {\n                display: none;\n            }\n\n            &.flipview-icon-top {\n                background-position: center 1px;\n            }\n\n            &.flipview-icon-right {\n                background-position: center -18px;\n            }\n\n            &.flipview-icon-bottom {\n                background-position: center -35px;\n            }\n\n            &.flipview-icon-left {\n                background-position: center -54px;\n            }\n        }\n\n        &-close-btn {\n            position: relative;\n            display: none;\n            height: 16px;\n            width: 16px;\n            float: right;\n            margin-top: -2px;\n\n            &:before {\n                color: rgba(0, 0, 0, 0.5);\n            }\n\n            &:hover:before {\n                color: rgba(0, 0, 0, 0.8);\n            }\n\n            .dark & {\n                &:before {\n                    color: rgba(255, 255, 255, 0.5);\n                }\n\n                &:hover:before {\n                    color: rgba(255, 255, 255, 0.8);\n                }\n            }\n        }\n\n        &:hover, &.always-show-header-buttons {\n            > .pane-header-flipview-btn:not(.flipview-icon-none) {\n                display: inline-block;\n            }\n\n            > .pane-header-close-btn {\n                display: inline;\n            }\n        }\n    }\n\n    .active-pane {\n\n        .pane-header {\n            opacity: 1;\n            color: @bc-menu-text;\n\n            .dark & {\n                color: @dark-bc-menu-text;\n            }\n        }\n    }\n}\n\n// moved this out of #editor-holder because we need to lower the specificity so theme authors can override the background color\n.not-editor {\n    height: 100%;\n    .vbox;\n    .box-pack(center);\n    .box-align(center);\n    background: #f8f8f8 url('images/no_content_bg.svg') no-repeat center 45%;\n\n    .dark & {\n        background: #1d1f21 url('images/no_content_bg_dark.svg') no-repeat center 45%;\n    }\n}\n\n// Split View Separator Styles\n.split-vertical #second-pane {\n    border-left: 1px solid rgba(0, 0, 0, 0.17);\n    .dark & {\n        border-left: 1px solid rgba(255, 255, 255, 0.3);\n    }\n}\n\n.split-horizontal #second-pane {\n    border-top: 1px solid rgba(0, 0, 0, 0.17);\n    .dark & {\n        border-top: 1px solid rgba(255, 255, 255, 0.3);\n    }\n}\n\n.vert-resizer {\n    position: absolute;\n    height: 6px;\n    width: 100%;\n    z-index: @z-index-brackets-panel-resizer;\n    opacity: 0;\n    cursor: row-resize;\n}\n\n.horz-resizer {\n    position: absolute;\n    height: 100%;\n    width: 6px;\n    z-index: @z-index-brackets-panel-resizer;\n    opacity: 0;\n    cursor: col-resize;\n}\n\n.bottom-panel {\n    background-color: @bc-panel-bg;\n    display: none;\n    height: 200px;\n    border-top: 1px solid @bc-panel-border;\n\n    .dark & {\n        background-color: @dark-bc-panel-bg;\n        border-top: 1px solid @dark-bc-panel-border;\n    }\n\n    .check-all {\n        margin: 7px 15px 7px 7px;\n    }\n\n    .toolbar {\n        background-color: @bc-panel-bg-promoted;\n        border-bottom: @bc-panel-separator;\n        height: auto;\n        padding-top: (@base-padding / 2);\n        padding-bottom: (@base-padding / 2);\n        z-index: @z-index-brackets-results-panel;\n        box-shadow: inset 0 1px 0 @bc-highlight-hard, 0 -1px 3px @bc-shadow-small;\n\n        .dark & {\n            background-color: @dark-bc-panel-bg-promoted;\n            border-bottom: @dark-bc-panel-separator;\n            box-shadow: inset 0 1px 0 @dark-bc-highlight, 0 -1px 3px @dark-bc-shadow-small;\n        }\n\n        .title {\n            color: @bc-text;\n            font-size: @label-font-size;\n            font-weight: @font-weight-semibold;\n\n            .dark & {\n                color: @dark-bc-text;\n            }\n        }\n        .close {\n            position: absolute;\n            right: 10px;\n            top: 50%;\n            margin-top: -10px;\n        }\n    }\n\n    .table-container {\n        height: 170px;\n        overflow: auto;\n\n        .highlight {\n            background: @bc-panel-bg-text-highlight;\n            border-radius: 2px;\n\n            .dark & {\n                background: @dark-bc-panel-bg-text-highlight;\n            }\n        }\n\n        tr.selected td {\n            background-color: @bc-panel-bg-selected;\n            color: @bc-text-thin;\n\n            .dark & {\n                background-color: @dark-bc-panel-bg-selected;\n                color: @dark-bc-text-thin;\n            }\n        }\n    }\n}\n\n.bottom-panel-table {\n    td {\n        font-size: 12px;\n        padding-left: 15px;\n        padding-right: 0;\n        vertical-align: baseline;\n    }\n\n    .file-section > .checkbox-column {\n        width: 15px;\n    }\n\n    .line-number {\n        color: @bc-text-thin-quiet;\n        font-family: @sourceFontFamily;\n        font-size: 11px;\n        padding: 4px 0 0 15px;\n        text-align: right;\n        white-space: nowrap;\n        width: 5px;\n\n        .dark & {\n            color: @dark-bc-text-thin-quiet;\n        }\n    }\n\n    .dialog-filename {\n        font-size: 13px;\n        font-weight: @font-weight-semibold;\n    }\n\n    .dialog-path {\n        font-size: 11px;\n        font-weight: normal;\n    }\n\n    .line-text {\n        width: 100%;\n    }\n}\n\n\n#update-notification {\n    .sprite-icon(0, 0, 24px, 24px, \"images/updateSprites.svg\");\n    &.update-in-progress {\n        .sprite-icon(0, 0, 24px, 24px, \"images/updateSpritesGrayed.svg\");\n    }\n}\n\n#toolbar-go-live {\n    // background-position is 0 0 for 24x24 icons\n    // Default icon is for the 'disconnected' state\n    // The 'connecting failed' (.warning) state also maps here\n    .sprite-icon(0, 0, 24px, 24px, \"images/live_development_sprites.svg\");\n    // 'Connected' state\n    &.success {\n        .sprite-swap(0, 24px);\n    }\n    // 'Connection in progress' state\n    &.info {\n        .sprite-swap(0, 48px);\n    }\n    // 'Out-of-sync' state\n    &.out-of-sync {\n        .sprite-swap(0, 72px);\n    }\n    // 'sync-error'\n    &.sync-error {\n        .sprite-swap(0, 96px);\n    }\n}\n\n#toolbar-extension-manager {\n    .sprite-icon(0, 0, 24px, 24px, \"images/extension-manager-sprite.svg\");\n    &.updatesAvailable {\n        .sprite-icon(0, 24px, 24px, 24px, \"images/extension-manager-sprite.svg\");\n    }\n}\n\n/* Project panel */\n\n#working-set-list-container {\n    background: @bc-sidebar-bg;\n\n    > div:last-child ul {\n        padding-bottom: 21px; // Adds working set bottom padding to the last UL.\n    }\n}\n\n.working-set-header {\n    position: relative;\n    height: 19px;\n    padding: 10px 0 9px 12px;\n    background: @bc-sidebar-bg;\n    color: @project-panel-text-2;\n    text-shadow: none;\n    overflow: hidden;\n\n    > span {\n        background: @bc-sidebar-bg;\n        position: relative;\n        z-index: 9;\n    }\n\n    > div {\n        background-color: @dark-bc-sidebar-bg;\n        opacity: 1;\n    }\n}\n\n.working-set-option-btn {\n    position: absolute;\n    right: 30px;\n    top: 7px;\n    padding: 4px 6px;\n    .sprite-icon(0, 0, 13px, 13px, \"images/topcoat-settings-13.svg\");\n    background-position: center;\n    opacity: 0.8;\n    z-index: 1;\n}\n\n.working-set-splitview-btn {\n    position: absolute;\n    right: 4px;\n    top: 7px;\n    padding: 4px 6px;\n    .sprite-icon(0, 0, 13px, 13px, \"images/split-view-icons.svg\");\n    background-origin: content-box;  // center image within the 13x13 area - ignore button's padding\n    -webkit-transform: translateZ(0); // forces GPU mode for better filter rendering on retina\n    transform: translateZ(0); // future proofing\n    -webkit-filter: drop-shadow(0 1px 0 rgba(0,0,0,0.36));\n    filter: drop-shadow(0 1px 0 rgba(0,0,0,0.36));\n    z-index: 1;\n}\n\n.splitview-icon-none {\n    background-position: center 1px;\n}\n.splitview-icon-vertical {\n    background-position: center -20px;\n}\n.splitview-icon-horizontal {\n    background-position: center -41px;\n}\n\n\n\n// Show splitview icons on the button's dropdown menu too\n#splitview-menu ul.dropdown-menu > li {\n    .menu-name::before {\n        display: inline-block;\n        .sprite-icon(0, 0, 13px, 13px, \"images/split-view-icons.svg\");\n        margin: 0 5px 0 -1px;\n        vertical-align: -2px;\n\n        .dark & {\n            .sprite-icon(0, 0, 13px, 13px, \"images/split-view-icons-dark.svg\");\n        }\n    }\n    &:nth-child(1) .menu-name::before {\n        .splitview-icon-none();\n    }\n    &:nth-child(2) .menu-name::before {\n        .splitview-icon-vertical();\n    }\n    &:nth-child(3) .menu-name::before {\n        .splitview-icon-horizontal();\n    }\n}\n\n#sidebar-resizer {\n    position: absolute;\n    width: 6px;\n    height: 100%;\n    z-index: @z-index-brackets-sidebar-resizer;\n    opacity: 0;\n    cursor: col-resize;\n}\n\n#project-files-header {\n    border-top: 1px solid rgba(255, 255, 255, 0.05);\n    padding: 8px 0 9px 12px;\n    font-size: 13px;\n    color: @project-panel-text-2;\n    overflow: hidden;\n\n    .btn-alt-quiet {\n        background-color: #47484b;\n\n        // relative positioning plus z-index make sure that the splitview button flows under the left aligned buttons in the project pane when there are no working set files\n        position: relative;\n        z-index: 9;\n    }\n}\n\n.open-files-container {\n    .box-flex(0);\n    padding: 0;\n    max-height: 200px; // TODO (Issue #276): it would be nicer to have this be 50%, but that doesn't seem to work\n\n\n    ul {\n        list-style-type: none;\n        margin: 0 0 2px; // 2px bottom margin required to stop scrollbar from appearing when the cursor is hovering over the last opened file.\n    }\n\n    li {\n        position: relative; // so that children can be positioned absolute\n        line-height: 18px;\n        padding: 0 0 0 8px;\n        min-height: 18px;\n        vertical-align: baseline;\n        white-space: nowrap;\n\n        &.selected a {\n            color: @open-working-file-name-highlight;\n        }\n\n        &.selected .extension {\n            color: @open-working-file-ext-highlight;\n        }\n    }\n\n    a {\n        color: @bc-text-alt;\n\n        font-size: 13px;\n        text-decoration: none;\n\n        display: block;\n        height: 16px;\n        line-height: 15px;\n        margin-left: 18px;\n        padding: 3px 0 3px 0;\n\n        cursor: default;\n\n        .dark & {\n            color: @dark-bc-text-alt;\n        }\n\n        .directory {\n            font-size: 11px;\n        }\n    }\n\n    .extension, .directory {\n        color: @project-panel-text-2;\n    }\n}\n\n\n\n.sidebar-selection, .filetree-selection {\n    background: @bc-sidebar-selection;\n    border-top: 1px solid @bc-shadow-small;\n    border-bottom: 1px solid @bc-highlight;\n    box-sizing: border-box;\n    height: 23px;\n    width: 100%;\n    position: absolute;\n}\n\n.sidebar-selection-extension, .filetree-selection-extension {\n    background: @bc-sidebar-selection;\n    border-top: 1px solid @bc-shadow-small;\n    border-bottom: 1px solid @bc-highlight;\n    box-sizing: border-box;\n    height: 23px;\n    width: 9px; /* quiet scrollbar width */\n    position: fixed;\n\n    z-index: @z-index-brackets-selection-extension; /* scroller-shadow appears above the extension */\n}\n\n.filetree-context-extension {\n    background: rgba(255, 255, 255, 0.06);\n    box-sizing: border-box;\n    height: 23px;\n    width: 9px; /* quiet scrollbar width */\n    position: fixed;\n\n    z-index: @z-index-brackets-selection-extension; /* scroller-shadow appears above the extension */\n}\n\n.filetree-context {\n    background: rgba(255, 255, 255, 0.06);\n    box-sizing: border-box;\n    position: absolute;\n    height: 23px;\n    width: 100%;\n}\n\n//Initially start with the open files hidden, they will get show as files are added\n.open-files-container {\n    display:none;\n}\n\n#project-files-container {\n    .box-flex(1);\n\n    div > ul {\n        padding-bottom: 24px;\n        padding-left: 8px;\n    }\n}\n\n.scroller-shadow {\n    background-size: 100%;\n    background-repeat: no-repeat;\n    height: 5px;\n    position: fixed;\n    z-index: @z-index-brackets-scroller-shadow;\n    pointer-events: none; // serves as a \"click through\", so clicks go to the file tree behind (see #12684)\n\n    &.top {\n        #gradient > .vertical(rgba(0,0,0,0.1), rgba(0,0,0,0));\n        background-position: 0 -5px;\n        background-color: transparent; /* override background-color: @endColor from #gradient.vertical */\n    }\n\n    &.bottom {\n        #gradient > .vertical(rgba(0,0,0,0), rgba(0,0,0,0.1));\n        background-position: 0 5px;\n        background-color: transparent; /* override background-color: @endColor from #gradient.vertical */\n    }\n}\n\n\n@jstree-sprite-size: 18px;  // this is hardcoded in jsTree's JS code\n\n/** Classes for icons from jsTreeSprites.svg\n*/\n.jstree-sprite {\n    background-image: @jstree-sprite;\n    background-repeat: no-repeat;\n    background-color: transparent;\n    vertical-align: middle;\n    width: @jstree-sprite-size;\n    height: @jstree-sprite-size;\n\n    .dark & {\n        background-image: @dark-jstree-sprite;\n    }\n}\n\n/** Overriding jsTreeTheme.less\n*/\n.jstree-brackets .jstree-no-dots .jstree-open > ins {\n    background-position: 7px -8px;\n    -webkit-transform: translateZ(0) rotate(90deg);\n    transform: translateZ(0) rotate(90deg);\n    transition: -webkit-transform 190ms cubic-bezier(.01, .91, 0, .99);\n    transition: transform 190ms cubic-bezier(.01, .91, 0, .99);\n    -webkit-filter: drop-shadow(1px 0 1px @bc-shadow);\n    filter: drop-shadow(1px 0 1px @bc-shadow);\n\n    .dark & {\n        -webkit-filter: drop-shadow(1px 0 1px @dark-bc-shadow);\n        filter: drop-shadow(1px 0 1px @dark-bc-shadow);\n    }\n}\n\n.jstree-brackets .jstree-no-dots .jstree-closed > ins {\n    background-position: 7px -8px;\n    -webkit-transform: translateZ(0); /* Need this to make sure that the svg isn't blurry on retina. */\n    transform: translateZ(0);\n    transition: -webkit-transform 90ms cubic-bezier(.01, .91, 0, .99);\n    transition: transform 90ms cubic-bezier(.01, .91, 0, .99);\n    -webkit-filter: drop-shadow(1px 0 1px @bc-shadow);\n    filter: drop-shadow(1px 0 1px @bc-shadow);\n\n    .dark & {\n        -webkit-filter: drop-shadow(1px 0 1px @dark-bc-shadow);\n        filter: drop-shadow(1px 0 1px @dark-bc-shadow);\n    }\n}\n\n/** Unicode Icon container\n*/\n.unicode-icon-container {\n    display: inline-block;\n    width: 16px;\n    height: 16px;\n    font-size: 20px;\n    line-height: 15px;\n    text-align: center;\n}\n\n.file-status-icon {\n    margin: 0 0 0 8px;\n    position: absolute;\n    left: 0;\n    top: 0;\n\n    &.dirty:before,\n    &.can-close:before {\n        .unicode-icon-container;\n        color: rgba(255, 255, 255, 0.5);\n    }\n\n    &.dirty:before {\n        content: \"\\2022\";\n        line-height: 1em;\n    }\n\n    &.can-close:before {\n        content: \"\\00D7\";\n        line-height: 1.1em;\n    }\n\n    &.can-close:hover:before {\n        color: rgba(255, 255, 255, 0.7);\n    }\n\n    &.can-close:active:before {\n        color: rgba(255, 255, 255, 0.3);\n    }\n}\n\n/* Styles for inline editors */\n\n.inline-text-editor {\n    line-height: 0;\n}\n\n.inline-widget {\n    position: relative;\n    overflow: hidden;\n    outline: none;\n\n    background-color: @bc-bg-inline-widget;\n    min-width: 250px;\n    cursor: default;\n\n    .dark & {\n        background-color: @dark-bc-bg-inline-widget;\n    }\n\n    &.animating {\n        // Make the animation use the GPU--especially important for retina.\n        -webkit-transform: translateZ(0);\n        transform: translateZ(0);\n\n        transition: height 250ms cubic-bezier(0, 1.02, 0.6, 1);\n    }\n\n    .CodeMirror {\n        /* remove CodeMirror default height: 300px */\n        height: auto;\n    }\n\n    .inline-text-editor {\n        white-space: nowrap;\n    }\n\n    .inline-editor-header {\n        display: inline-block;\n        padding: 8px 10px 2px 40px;\n\n        .filename {\n            vertical-align: middle;\n            font-family: @sansFontFamily;\n            font-size: 13px;\n            color: @bc-text-thin;\n\n            // Filename header is clickable (it's an <a> tag, so we get underscore on hover by\n            // default; but the hand cursor is shut off by Bootstrap's reset stylesheet)\n            cursor: pointer;\n\n            .dark & {\n                color: @dark-bc-text-thin;\n            }\n\n            .dirty-indicator {\n                .unicode-icon-container;\n                color: @bc-text-quiet;\n                overflow: hidden;\n                position: relative;\n                top: 1px;\n\n                .dark & {\n                    color: @dark-bc-text-quiet;\n                }\n            }\n\n            .line-number {\n                color: @accent-comment;\n            }\n        }\n    }\n\n    .shadow {\n        display: block;\n        height: 4px;\n        width: 100%;\n        position: absolute;\n        content: \" \";\n        left: 0;\n        z-index: @z-index-brackets-inline-editor-shadow;\n    }\n\n    .shadow.top {\n        top: 0;\n        background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));\n    }\n\n    .shadow.bottom {\n        bottom: 0;\n        background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1));\n    }\n\n    .CodeMirror-scroll {\n        background-color: transparent !important;\n\n        .CodeMirror-linenumbers {\n            background-color: @bc-bg-inline-widget;\n\n            .dark & {\n                background-color: @dark-bc-bg-inline-widget;\n            }\n        }\n    }\n\n    .close {\n        position: absolute;\n        left: 15px;\n        top: 10px;\n        margin-right: 30px;\n    }\n\n}\n\n/* CSSInlineEditor rule list */\n.related-container {\n    @top-margin: 12px;\n\n    float: right;\n    position: relative;\n    min-height: 100%;\n    font-family: @sansFontFamily;\n    width: 250px;\n    max-width: 50%;\n    overflow: hidden;\n    background: @bc-panel-bg;\n\n    // Without this, the \"New Rule\" button shows on top of the rule list if you resize\n    // the window narrow enough. No idea why, since there's no z-index on the button, and\n    // the other items in the header go behind the rule list.\n    z-index: 1;\n\n    .dark & {\n        background: @dark-bc-panel-bg;\n    }\n\n    .selection {\n        width: 100%;\n        background: @bc-panel-bg-selected;\n        position: absolute;\n        border-top: none;\n        border-bottom: none;\n        top: @top-margin;\n\n        .dark & {\n            background: @dark-bc-panel-bg-selected;\n        }\n\n        &.animate {\n            transition: top 0.1s ease-out;\n        }\n    }\n\n    /*\n     * CSS triangle hack with anti-alias workarounds:\n     * (a) Use selection-background-color instead of transparent.\n     * (b) Use transform scaleX and origin to adjust width.\n     */\n    .selection:before {\n        content: \" \";\n        position: absolute;\n        width: 0;\n        height: 0;\n        border-top: @inline-triangle-size solid transparent;\n        border-bottom: @inline-triangle-size solid transparent;\n        border-left: @inline-triangle-size solid @bc-bg-inline-widget;\n        margin-top: -@inline-triangle-size;\n        top: 50%;\n        .scale-x(0.9, left, top);\n\n        .dark & {\n            border-left: @inline-triangle-size solid @dark-bc-bg-inline-widget;\n        }\n    }\n\n    .related {\n        font-size: 12px;\n        position: absolute;\n        top: 0;\n        left: 1px;\n        width: 100%;\n\n        ul {\n            margin: 0;\n            padding: 10px 0 10px 5px;\n            list-style: none;\n        }\n\n        li {\n            color: @bc-text-emphasized;\n            margin: 0;\n            overflow: hidden;\n            padding: 2px 0 2px 15px;\n            text-overflow: ellipsis;\n            white-space: nowrap;\n\n            .dark & {\n                color: @dark-bc-text-emphasized;\n            }\n\n            &.section-header {\n                padding-left: 0;\n                padding-bottom: 0;\n                .disclosure-triangle {\n                    .expand-collapse-triangle();\n                }\n                .filename {\n                    font-weight: @font-weight-semibold;\n                }\n            }\n\n            .related-file {\n                color: @bc-text-thin-quiet;\n                padding-left: 3px;\n\n                .dark & {\n                    color: @dark-bc-text-thin-quiet;\n                }\n            }\n        }\n\n        .selected {\n            color: @bc-text-thin;\n            transition: color 0.1s ease-out .15s;\n\n            .dark & {\n                color: @dark-bc-text-thin;\n            }\n        }\n    }\n}\n\n.inline-editor-message {\n    color: @bc-text-thin-quiet;\n    font-family: @sansFontFamily;\n    font-size: 12px;\n    line-height: 17px;\n    height: 20px;\n    padding: 10px 0 40px 50px;\n\n    .dark & {\n        color: @dark-bc-text-thin-quiet;\n    }\n}\n\n/* This text is used to force the code editor's font to be loaded early on if it's a\n   web font. This is necessary in order for the editor's horizontal measurement of text\n   to work properly.\n\n   In the future, when we allow the user to switch fonts, we'll need to make sure to\n   update the font for this text item whenever the user switches. We'll also need to\n   wait to initiate a re-measure in CodeMirror until the new font is loaded (if they\n   choose a web font). This library allows for checking if a web font is loaded:\n\n     http://code.google.com/apis/webfonts/docs/webfont_loader.html\n*/\n.dummy-text {\n    position: fixed;\n    top: -10000px;\n    .code-font();\n}\n\n.platform-mac .dummy-text {\n    .code-font-mac();\n}\n\n/* Find in Files results panel - temporary UI, to be replaced with a richer search feature later */\n\n.search-results .title {\n    .sane-box-model;\n    padding-right: 20px;\n    width: 100%;\n    line-height: 25px;\n\n    .flex-box;\n    .contracting-col {\n        .flex-item(0);\n        min-width: 1px;\n        overflow: hidden;\n        text-overflow: ellipsis;\n    }\n    .fixed-col {\n        .flex-item(0, 0);\n    }\n    .pagination-col {\n        .flex-item(0, 0);\n        min-width: 100px;\n        word-spacing: 0;\n    }\n    .pagination-col > span:hover {\n        background-color: rgba(255, 255, 255, 0.3);\n    }\n    .pagination-col > span:active {\n        background-color: @bc-shadow;\n\n        .dark & {\n            background-color: @dark-bc-shadow;\n        }\n    }\n    .replace-col {\n        .flex-item(1, 0);\n        min-width: 120px;\n        padding: 0 15px;\n    }\n    .first-page,\n    .prev-page,\n    .next-page,\n    .last-page {\n        .jstree-sprite;\n        width: 18px;\n        display: inline-block;\n        margin: 0;\n        background-position: 7px 6px;\n        vertical-align: text-top;\n        border-radius: 3px;\n    }\n    .first-page {\n        background-position: 6px -78px;\n        margin-left: 10px;\n    }\n    .prev-page {\n        background-position: 6px -22px;\n        margin-right: 5px;\n    }\n    .next-page {\n        margin-left: 5px;\n    }\n    .last-page {\n        background-position: 6px -50px;\n    }\n    .disabled,\n    .disabled:hover,\n    .disabled:active {\n        background-color: transparent;\n        opacity: 0.3;\n    }\n}\n\n.search-results .disclosure-triangle,\n#problems-panel .disclosure-triangle {\n    .expand-collapse-triangle();\n}\n.expand-collapse-triangle() {\n    .jstree-sprite;\n    display: inline-block;\n    background-position: 7px 5px;\n    &.expanded {\n        // Unfortunately, the way jsTree sprites are aligned within their 18px boxes doesn't look good in\n        // other contexts, so we need some tweaks here instead of straight multiples of @jstree-sprite-size\n        -webkit-transform: translateZ(0) rotate(90deg);\n        transform: translateZ(0) rotate(90deg);\n    }\n}\n\n/* Modal bar for Find/Quick Open */\n\n.modal-bar {\n    display: block;\n    text-align: left;\n\n    font-family: @sansFontFamily;\n    font-size: 14px;\n    color: @bc-text;\n    background: @bc-panel-bg;\n    overflow: visible;  // needed for .error popup\n    padding: 5px 4px 4px 14px;\n\n    -webkit-transform: translate(0, 0); // Prefix still required.\n    transform: translate(0, 0);\n    transition: -webkit-transform 66ms cubic-bezier(0, 0.62, 0.04, 0.99);\n    transition: transform 66ms cubic-bezier(0, 0.62, 0.04, 0.99);\n    z-index: @z-index-brackets-modalbar;\n\n    .dark & {\n        color: @dark-bc-text;\n        background: @dark-bc-panel-bg;\n    }\n\n    body.in-browser &,\n    body:not(.has-appshell-menus) & {\n        // Separator line between us and the HTML menu/titlebar above\n        border-top: 1px solid @bc-panel-border;\n\n        .dark & {\n            border-top: 1px solid @dark-bc-panel-border;\n        }\n    }\n\n    &.popout {\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n    }\n\n    &.offscreen {\n        -webkit-transform: translate(0, -100%);\n        transform: translate(0, -100%);\n        transition: -webkit-transform 266ms cubic-bezier(0, 0.56, 0, 1);\n        transition: transform 266ms cubic-bezier(0, 0.56, 0, 1);\n    }\n\n    input {\n        font-family: @sansFontFamily;\n        outline: none;\n        width: 20em;\n        margin: 5px 5px 0;\n        position: relative;\n        top: -3px;\n        &.no-results {\n            border: 1px solid  @bc-btn-border-error;\n            box-shadow: inset 0 1px 0 @bc-shadow-small, 0 0 0 1px @bc-btn-border-error-glow;\n\n            .dark & {\n                border: 1px solid  @dark-bc-btn-border-error;\n                box-shadow: inset 0 1px 0 @dark-bc-shadow-small, 0 0 0 1px @dark-bc-btn-border-error-glow;\n            }\n        }\n    }\n\n    #find-what, #replace-with {\n        width: 295px;\n    }\n\n    .search-input-container {\n        position: relative;\n        display: inline;\n\n        .error {  // \"popup\" that hangs below search field\n            position: absolute;\n            left: 5px;\n            top: 24px;\n            min-width: 291px + 2px;  // to align with search field above it\n            z-index: 1; // to appear above any controls that wrap below\n\n            background-color: @bc-error;\n            color: @bc-text-alt;\n            font-size: 12px;\n            padding: 3px 8px;\n            border-radius: 0 0 3px 3px;\n            box-shadow: 0 1px 3px @bc-shadow-small;\n\n            .dark & {\n                background-color: @dark-bc-error;\n                color: @dark-bc-text-alt;\n                box-shadow: 0 1px 3px @dark-bc-shadow-small;\n            }\n        }\n\n        #find-what {\n            padding-right: 78px;  // room for #find-counter overlay\n            width: 295px - (62px - 6px);  // maintain width, accounting for differing padding\n        }\n\n        .dropdown-icon {\n            background: url(images/dropdown-icon.svg) no-repeat scroll 15px 15px;\n            background-position: center right;\n            width: 20px;\n            height: 20px;\n        }\n\n        #find-counter, .dropdown-icon {\n            position: absolute;\n            color: @bc-text-thin-quiet;\n            top: 1px;\n            right: 2px;\n            font-size: 12px;\n\n            .dark & {\n                color: @dark-bc-text-thin-quiet;\n            }\n        }\n    }\n\n    .find-input-group {\n        display: inline-block;\n    }\n    #find-group, #replace-group {\n        display: inline-block;\n        white-space: nowrap;\n    }\n    #replace-group.has-scope {\n        // If scope controls are showing, force the replace controls to a second line.\n        display: block;\n    }\n\n    .scope-group {\n        display: inline-block;\n        margin-left: 10px;\n    }\n\n    .indexing-group {\n        display: inline-block;\n        margin-left: 10px;\n    }\n\n    .indexing-message {\n        display: inline-block;\n        font-style: italic;\n        margin-left: 5px;\n    }\n\n    .message, .no-results-message {\n        display: inline-block;\n    }\n\n    #find-case-sensitive, #find-regexp {\n        padding: 1px 5px;\n    }\n    .button-icon {  // icons must be nested inside button so we can apply padding w/o tiling icon\n        .sprite-icon(0, 0, 24px, 24px, @button-icon);\n        background-repeat: no-repeat;\n\n        .dark & {\n            .sprite-icon(0, 0, 24px, 24px, @dark-button-icon);\n        }\n    }\n    #find-regexp.active .button-icon {\n        .sprite-swap(0, 24px);\n    }\n    #find-case-sensitive .button-icon {\n        .sprite-swap(0, 48px);\n    }\n    #find-case-sensitive.active .button-icon {\n        .sprite-swap(0, 72px);\n    }\n    #find-regexp.active,\n    #find-regexp:active,\n    #find-case-sensitive.active,\n    #find-case-sensitive:active { // Make the toggle buttons' down states the same color as 'on' state to prevent a flash of different color.\n        background-color: @bc-bg-highlight;\n\n        .dark & {\n            background-color: @dark-bc-bg-highlight;\n        }\n    }\n\n    .navigator {  // next/prev buttons\n        display: inline-block;\n    }\n    button {\n        margin: 2px 1px 3px;\n    }\n    #find-prev {\n        border-top-right-radius: 0;\n        border-bottom-right-radius: 0;\n        margin-left: 5px;\n    }\n\n    // Make button pairs snug\n    #find-prev, #replace-yes, #replace-batch, #find-case-sensitive {\n        border-right: none;\n        margin-right: 0;\n    }\n    #find-next, #replace-all, #find-regexp {\n        border-top-left-radius: 0;\n        border-bottom-left-radius: 0;\n        margin-left: 0;\n    }\n    #replace-batch {\n        border-radius: 0;\n        margin-left: 0;\n    }\n    #replace-batch.solo {\n        border-top-right-radius: 3px;\n        border-bottom-right-radius: 3px;\n        border-left: none;\n        border-right: 1px solid @bc-btn-border;\n        \n        .dark & {\n            border-right-color: @dark-bc-btn-border;\n        }\n    }\n\n    // Make find field snug with options buttons\n    //    & replace snug with replace commands\n    #find-what, #replace-with {\n        margin-right: 0;\n        border-top-right-radius: 0;\n        border-bottom-right-radius: 0;\n    }\n    #find-case-sensitive, #replace-yes {\n        border-left: none;\n        margin-left: 0;\n        border-radius: 0;\n    }\n\n    .close {\n        position: absolute;\n        right: 10px;\n        top: 50%;\n        margin-top: -8px;\n    }\n}\n\n// File exclusion filter (used only in Find in Files search bar, for now)\n.filter-trash-icon {\n    position: absolute;\n    left: 7px;\n    width: 16px;\n    height: 16px;\n    font-size: 20px;\n    color: rgba(0, 0, 0, 0.5);\n    line-height: 15px;\n    text-align: center;\n    visibility: hidden;\n}\n\n.filter-trash-icon:hover {\n    color: rgba(0, 0, 0, 1);\n}\n\n.filter-edit-icon {\n    float: right;\n    width: 13px;\n    height: 13px;\n    background-image: url(\"images/edit-icon.svg\");\n    background-repeat: no-repeat;\n    opacity: 0.5;\n    visibility: hidden;\n    position: relative;\n    top: 2px;\n    right: -4px;\n}\n\n.filter-edit-icon:hover {\n    opacity: 1;\n}\n\nli:hover .filter-trash-icon,\nli:hover .filter-edit-icon {\n    visibility: visible;\n}\n\n.recent-filter-name {\n    margin-left: 12px;\n}\n\n.recent-filter-patterns {\n    color: @bc-text-thin-quiet;\n    padding-right: 52px;\n\n    .dark & {\n        color: @dark-bc-text-thin-quiet;\n    }\n}\n\nbutton.file-filter-picker {\n    margin-left: 10px;\n}\n\n// File exclusion filter editor dialog\ninput.exclusions-name {\n    display: block;\n    width: 100%;\n    height: 30px;\n    box-sizing: border-box; // needed for width: 100% since it has padding\n    margin-top: 12px;\n    margin-bottom: 0;\n}\ntextarea.exclusions-editor {\n    display: block;\n    width: 100%;\n    height: 120px;\n    box-sizing: border-box; // needed for width: 100% since it has padding\n    margin-top: 5px;\n    margin-bottom: 0;\n    .code-font();\n}\n.exclusions-name-characters-remaining {\n    text-align: right;\n    padding-top: 4px;\n}\n.exclusions-name-characters-limit-reached {\n    color: red;\n}\n.exclusions-filecount {\n    margin: 12px 0 -14px 0;\n    padding: 4px 8px;\n    background-color: @bc-bg-highlight;\n    border-radius: @bc-border-radius;\n\n    .dark & {\n        background-color: @dark-bc-bg-highlight;\n    }\n}\n\n\n// Find/Replace result highlighting\n.CodeMirror-searching {\n    background-color: @cm-match-highlight;\n    box-shadow: 0 1px 3px @bc-shadow-small;\n    color: @match-text !important;\n\n    .dark & {\n        box-shadow: 0 1px 3px @dark-bc-shadow-small;\n    }\n\n    &.searching-current-match {\n        background-color: @cm-current-match-highlight;\n    }\n    &.searching-first {  // first in a contiguous run of highlights\n        border-top-left-radius: @bc-border-radius-small;\n        border-bottom-left-radius: @bc-border-radius-small;\n    }\n    &.searching-last {  // last in a contiguous run of highlights\n        border-top-right-radius: @bc-border-radius-small;\n        border-bottom-right-radius: @bc-border-radius-small;\n    }\n}\n#find-counter {\n    font-weight: @font-weight-semibold;\n    padding: 0 5px;\n    margin-right: 17px;\n}\n\n.tickmark-track {\n    position: absolute;\n    bottom: 0;\n    top: 0;\n    right: 0;\n    width: 12px;\n    z-index: @z-index-cm-max;\n    pointer-events: none;\n\n    .tickmark {\n        position: absolute;\n        width: 12px;\n        height: 1px;\n        background-color: #eddd23;\n        border-top: 1px solid #e0d123;\n        border-bottom: 1px solid #d4c620;\n        opacity: 0.85;  // allow thumb to show through\n        &.tickmark-current {\n            background-color: #ed9823;\n            border-top: 1px solid #dd9128;\n            border-bottom: 1px solid #cb8320;\n            z-index: 1;  // ensure this one appears above overlapping sibling highlights\n        }\n    }\n}\n\n\n/* Quick Open search bar & dropdown */\n\n.find-dialog-label {\n    background: @bc-input-bg;\n    color: @bc-text-quiet;\n    position: absolute;\n    right: 15px;\n    text-align: right;\n    top: 12px;\n    z-index: 9999;\n\n    .dark & {\n        background: @dark-bc-input-bg;\n        color: @dark-bc-text-quiet;\n    }\n}\n\n.quick-search-container {\n    border: 1px solid @bc-panel-border;\n    box-sizing: border-box;  // lets QuickSearchField size the width more nicely\n    background-color: @bc-panel-bg;\n    border-radius: 0 0 4px 4px;\n    box-shadow: 0 5px 10px @bc-shadow;\n    opacity: 0;\n    overflow-wrap: break-word;\n\n    .animation (autocomplete, 90ms, cubic-bezier(.01, .91, 0, .99));\n    -webkit-animation-fill-mode: forwards;\n    animation-fill-mode: forwards;\n    -webkit-transform-origin: 0 0;\n    transform-origin: 0 0;\n\n    padding: 0;\n    margin: 9px 0 0;\n\n    z-index: @z-index-brackets-context-menu-base;\n\n    .dark & {\n        background-color: @dark-bc-panel-bg;\n        border-radius: 0 0 4px 4px;\n        box-shadow: 0 5px 10px @dark-bc-shadow;\n    }\n\n    .quick-open-path {\n        color: @bc-text-medium;\n        font-size: 11px;\n        letter-spacing: 0.04em;\n        line-height: 11px;\n\n        .dark & {\n            color: @dark-bc-text-medium;\n        }\n    }\n\n    li {\n        color: @bc-text-emphasized;\n        line-height: 15px;\n        list-style: none;\n        cursor: default;\n        padding: 6px 10px;\n\n        .dark & {\n            color: @dark-bc-text-emphasized;\n        }\n\n        &:nth-child(odd) {\n            background-color: @bc-panel-bg-alt;\n\n            .dark & {\n                background-color: @dark-bc-panel-bg-alt;\n            }\n        }\n        &:last-child {\n            border-radius: 0 0 4px 4px;  // don't cover over quick-search-container's rounded corners\n        }\n\n        &:hover {\n            background-color: @bc-panel-bg-hover;\n\n            .dark & {\n                background-color: @dark-bc-panel-bg-hover;\n            }\n        }\n\n        &.highlight {\n            background-color: @bc-bg-highlight;\n            color: @bc-menu-text;\n\n            .dark & {\n                background-color: @dark-bc-bg-highlight;\n                color: @dark-bc-menu-text;\n            }\n        }\n    }\n}\n\n@-webkit-keyframes autocomplete {\n    0%   { opacity: 0.6; -webkit-transform: translate3d(0, 0, 0) scale(0.6); }\n    100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0) scale(1); }\n}\n@keyframes autocomplete {\n    0%   { opacity: 0.6; transform: translate3d(0, 0, 0) scale(0.6); }\n    100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }\n}\n\n.quicksearch-pathmatch,\n.quicksearch-namematch {\n    font-weight: @font-weight-semibold;\n}\n\n.quicksearch-pathmatch {\n    color: @bc-text-medium;\n\n    .dark & {\n        color: @dark-bc-text-medium;\n    }\n}\n\n\n/* Spinner */\n\n.spinner {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 14px;\n    height: 14px;\n    border-left: 3px solid @bc-spinner;\n    border-right: 3px solid @bc-spinner;\n    overflow: hidden;\n    position: relative;\n    visibility: hidden;\n\n    .dark & {\n        border-left: 3px solid @dark-bc-spinner;\n        border-right: 3px solid @dark-bc-spinner;\n    }\n\n    &:before,\n    &:after {\n        border-left: 3px solid @bc-spinner;\n        border-right: 3px solid @bc-spinner;\n        box-sizing: border-box;\n        content: \"\";\n        display: block;\n        position: absolute;\n        width: 100%;\n        height: 3px;\n        left: 0;\n\n        .dark & {\n            border-left: 3px solid @dark-bc-spinner;\n            border-right: 3px solid @dark-bc-spinner;\n        }\n    }\n    &:before {\n        top: 0;\n    }\n    &:after {\n        bottom: 0;\n    }\n\n    &.spin {\n        -webkit-animation: spinner-rotateplane 1.2s infinite ease-in-out;\n        animation: spinner-rotateplane 1.2s infinite ease-in-out;\n        visibility: visible;\n    }\n\n    &.large {\n        width: 36px;\n        height: 36px;\n        border-left: 9px solid @bc-spinner;\n        border-right: 9px solid @bc-spinner;\n\n        .dark & {\n            border-left: 9px solid @dark-bc-spinner;\n            border-right: 9px solid @dark-bc-spinner;\n        }\n\n        &:before,\n        &:after {\n            border-left: 7px solid @bc-spinner;\n            border-right: 7px solid @bc-spinner;\n            height: 9px;\n\n            .dark & {\n                border-left: 7px solid @dark-bc-spinner;\n                border-right: 7px solid @dark-bc-spinner;\n            }\n        }\n    }\n\n    &.inline {\n        margin-left: 8px;\n        position: relative;\n        top: 3px;\n    }\n}\n\n@-webkit-keyframes spinner-rotateplane {\n    0% { -webkit-transform: perspective(120px); }\n    50% { -webkit-transform: perspective(120px) rotateY(180deg); }\n    100% { -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg); }\n}\n@keyframes spinner-rotateplane {\n    0% { transform: perspective(120px) rotateX(0deg) rotateY(0deg); }\n    50% { transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); }\n    100% { transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); }\n}\n\n\n\n/* Problems panel & CodeInspection status bar indicator */\n\n#status-indicators #status-inspection {\n    border: none;\n    cursor: default;\n    width: 13px;\n\n    &.inspection-errors {\n        cursor: pointer;\n    }\n}\n\n.inspection-disabled {\n    background: url(images/topcoat-inactive-15.svg) 9px 5px no-repeat;\n}\n\n.inspection-errors {\n    background: url(images/topcoat-warning-15.svg) 9px 5px no-repeat;\n}\n\n.inspection-errors:hover {\n    background-color: rgba(0, 0, 0, 0.03);\n}\n\n.inspection-errors:active {\n    background-color: rgba(0, 0, 0, 0.05);\n}\n\n.inspection-valid {\n    background: url(images/topcoat-okay-15.svg) 9px 5px no-repeat;\n}\n\n#problems-panel {\n    .user-select(text);  // allow selecting error messages for easy web searching\n    .line {\n        text-align: right;  // make line number line up with editor line numbers\n    }\n\n    .line-icon {\n        vertical-align: middle;\n\n        .line-icon-default {\n            width: 20px;\n            height: 18px;\n            background-image: url(images/topcoat-inactive-15.svg);\n            background-repeat: no-repeat;\n            background-position: 0px 1px;\n        }\n\n        // Add an image based on the type of the problem.\n        .line-icon-problem_type_error {\n            background-image: url(images/topcoat-error-15.svg);\n        }\n        .line-icon-problem_type_warning {\n            background-image: url(images/topcoat-warning-15.svg);\n        }\n        .line-icon-problem_type_meta {\n            background-image: url(images/topcoat-inactive-15.svg);\n        }\n    }\n\n    .line-text {\n        white-space: nowrap;\n        width: auto;\n        padding-left: 5px;\n    }\n\n    .line-snippet {\n        white-space: nowrap;\n        width: 100%;\n        padding-left: 10px;\n    }\n\n    .inspector-section > td {\n        padding-left: 5px;\n    }\n}\n\n/* Line up label text and input text */\nlabel input {\n    position: relative;\n    top: -2px;\n}\n\n/* Live Preview */\n\n// CodeMirror uses inline styles for active line number, so must use !important here to override\n.live-preview-sync-error .CodeMirror-linenumber {\n    background-color: @live-preview-sync-error-background !important;\n    color: @live-preview-sync-error-color !important;\n}\n\n/* Quick Edit, Quick Docs */\n.popover-message {\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: @z-index-brackets-inline-editor-error;\n    opacity: 1.0;\n\n    -webkit-transform: scale(0);\n    transform: scale(0);\n\n    .text {\n        padding: 5px 10px;\n        background-color: @bc-error;\n        border-radius: 3px;\n        color: @bc-text-alt;\n        box-shadow: 0 3px 9px @bc-shadow;\n        white-space: nowrap;\n\n        .dark & {\n            background-color: @dark-bc-error;\n            border-radius: 3px;\n            color: @dark-bc-text-alt;\n            box-shadow: 0 3px 9px @dark-bc-shadow;\n        }\n    }\n    .arrowAbove {\n        height: 0;\n        width: 0;\n        border-width: 0 10px 10px 10px;\n        border-color: transparent transparent @bc-error transparent;\n        border-style: solid;\n\n        .dark & {\n            border-color: transparent transparent @dark-bc-error transparent;\n        }\n    }\n    .arrowBelow {\n        height: 0;\n        width: 0;\n        border-width: 10px 10px 0 10px;\n        border-color: @bc-error transparent transparent transparent;\n        border-style: solid;\n\n        .dark & {\n            border-color: @dark-bc-error transparent transparent transparent;\n        }\n    }\n    &.animateOpen {\n        transition: -webkit-transform 125ms;\n        transition: transform 125ms;\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n    &.animateClose {\n        // Make the animation use the GPU--especially important for retina.\n        -webkit-transform: translateZ(0);\n        transform: translateZ(0);\n        transition: opacity 500ms 5s ease-in, -webkit-transform 500ms 5s;\n        transition: opacity 500ms 5s ease-in, transform 500ms 5s;\n        opacity: 0.0;\n    }\n    &.open {\n        -webkit-transform: scale(1);\n        transform: scale(1);\n    }\n}\n\n.emphasized {\n    font-weight: 900;\n    font-size: 1.01em;\n}\n\n/* Extension Manager */\n#install-drop-zone {\n    background-color: transparent;\n    box-shadow: initial;\n    font-weight: normal;\n    border-style: dashed;\n    position: relative;\n\n    .dark & {\n        border-color: #5f5f5f;\n    }\n}\n\n#install-drop-zone .install-from-url {\n    cursor: pointer;\n}\n\n#install-drop-zone-mask {\n    position: absolute;\n    top: -1px;\n    left: -1px;\n\n    padding: 1px;\n    width: 100%;\n    height: 100%;\n    display: none;\n\n    cursor: copy;\n}\n\n#install-drop-zone.drop #install-drop-zone-mask {\n    display: block;\n}\n\n#install-drop-zone.drop {\n    background: @bc-primary-btn-bg;\n    box-shadow: initial;\n    font-weight: normal;\n    border: 1px solid @bc-primary-btn-bg;\n    color: @bc-text-alt;\n    text-shadow: none;\n\n    .dark & {\n        background: @dark-bc-primary-btn-bg;\n        border: 1px solid @dark-bc-primary-btn-bg;\n        color: @dark-bc-text-alt;\n    }\n}\n\n.install-drag-message {\n    display: none;\n}\n\n.install-drop-message {\n    display: none;\n}\n\n.install-validating-message {\n    display: none;\n}\n\n#install-drop-zone.drag .install-drag-message {\n    display: inline;\n}\n\n#install-drop-zone.drop .install-drop-message {\n    display: inline;\n}\n\n#install-drop-zone.validating .install-validating-message {\n    display: inline;\n}\n\n#hidden-editors {\n    display: none;\n}\n\n.theme-settings td {\n    padding: 2px;\n}\n\n.theme-settings .modal-body {\n    min-height: 300px;\n    max-height: 300px;\n}\n\n#status-language button, #status-encoding button {\n    width: auto;\n}\n"
  },
  {
    "path": "src/styles/brackets_codemirror_override.less",
    "content": "// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//  \n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"), \n// to deal in the Software without restriction, including without limitation \n// the rights to use, copy, modify, merge, publish, distribute, sublicense, \n// and/or sell copies of the Software, and to permit persons to whom the \n// Software is furnished to do so, subject to the following conditions:\n//  \n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//  \n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n// DEALINGS IN THE SOFTWARE.\n\n/* Brackets / CodeMirror Code Formatting */\n\n@code-padding: 15px;\n\n.CodeMirror pre {\n    padding: 0 @code-padding 0 0;\n\n    > * {\n        text-indent: 0;\n    }\n}\n\n.show-line-padding .CodeMirror pre {\n    padding-left: 0;\n}\n\n.CodeMirror-scroll {\n    background-color: @background;\n}\n\n.CodeMirror {\n    .code-font();\n}\n\n.platform-mac .CodeMirror {\n    .code-font-mac();\n}\n\n.platform-win .CodeMirror {\n    .code-font-win();\n}\n\n.CodeMirror-activeline-background {\n    background: transparent;\n}\n\n.CodeMirror-focused .CodeMirror-activeline-background {\n    background: @activeline-bg;\n}\n\n.show-line-padding .CodeMirror-focused .CodeMirror-activeline-background {\n    box-shadow: inset @code-padding 0 0 0 @activeline-number-bg;\n}\n\n.CodeMirror-focused .CodeMirror-activeline {\n    & > div, .CodeMirror-gutter-elt {\n        height: 100%;\n    }\n    .CodeMirror-gutter-elt {\n        background: @activeline-number-bg;\n        color: @activeline-number;\n    }\n    .inline-widget .CodeMirror-gutter-elt {\n        color: @accent-comment;    \n    }\n}\n\n.CodeMirror-focused .cm-matchhighlight {\n    border-bottom: 2px solid #78B2F2;\n}\n\nspan.cm-keyword {color: @accent-keyword;}\nspan.cm-atom {color: @accent-atom;}\nspan.cm-number {color: @accent-number;}\nspan.cm-def {color: @accent-def;}\nspan.cm-variable {color: @accent-variable;}\nspan.cm-variable-2 {color: @accent-variable-2;}\nspan.cm-variable-3 {color: @accent-variable-3;}\nspan.cm-operator {color: @accent-operator;}\nspan.cm-comment {color: @accent-comment;}\nspan.cm-string {color: @accent-string;}\nspan.cm-string-2 {color: @accent-string-2;}\nspan.cm-meta {color: @accent-meta;}\nspan.cm-qualifier {color: @accent-qualifier;}\nspan.cm-builtin {color: @accent-builtin;}\nspan.cm-bracket {color: @accent-bracket;}\nspan.cm-tag {color: @accent-tag;}\nspan.cm-attribute {color: @accent-attribute;}\nspan.cm-header {color: @accent-header;}\nspan.cm-quote {color: @accent-quote;}\nspan.cm-hr {color: @accent-hr;}\nspan.cm-link {color: @accent-link; text-decoration: none;}\nspan.cm-rangeinfo {color: @accent-rangeinfo;}\nspan.cm-minus {color: @accent-minus;}\nspan.cm-plus {color: @accent-plus;}\nspan.cm-property {color: @accent-property;} //cm-property has go after cm-string for a better JSON look.\nspan.cm-error {color: @accent-error;}\n\nspan.CodeMirror-matchingbracket {color: @accent-bracket !important; background-color: @matching-bracket;}\nspan.CodeMirror-nonmatchingbracket {color: @accent-bracket;}\n\ndiv.CodeMirror-cursors {\n    .CodeMirror-cursor {\n        .code-cursor();\n    }\n\n    /* Ensure the cursor shows up in front of code spans with a background color\n     * (e.g. matchingbracket).\n     */\n    z-index: 3;\n}\n\n.CodeMirror-lines {\n    padding: @code-padding 0;\n\n    /* This is necessary for issue #2780. The logic for closing dropdowns depends on \"click\" events. Now\n     * that each line has a separate div element, there is a good chance that mouseDown and mouseUp events\n     * occur on different elements, which means a click event will not be sent. By disabling pointer events here,\n     * we are guaranteed that the mouse event will be captured by our parent div, and click events will \n     * be dispatched.\n     */\n    pointer-events: none;\n}\n\n.CodeMirror-linewidget {\n    /* Re-enable pointer events for line widget. Pointer events are disabled for \"CodeMirror-lines\", which is the\n     * parent of line widgets, so they need to be explicitly re-enabled here in order for selection to work. */\n    pointer-events: auto;\n}\n\n.CodeMirror-gutters {\n    background-color: @background;\n    border-right: none;\n}\n\n.platform-mac {\n    .CodeMirror-scrollbar-filler {\n        background-image: url(images/scrollbar-mac-corner.png);\n    }\n    .CodeMirror-gutter-filler {\n        background-image: url(images/scrollbar-mac-bg.png);\n    }\n}\n.platform-win {\n    .CodeMirror-scrollbar-filler,\n    .CodeMirror-gutter-filler {\n        background-color: @win-scrollbar-track;\n        height: 12px !important;\n    }\n    .CodeMirror-scrollbar-filler {\n        width: 12px !important;\n    }\n}\n.platform-linux {\n    .CodeMirror-scrollbar-filler,\n    .CodeMirror-gutter-filler {\n        background-color: @background;\n        height: 12px !important;\n    }\n    .CodeMirror-scrollbar-filler {\n        width: 12px !important;\n    }\n}\n\n.CodeMirror-linenumber {\n    color: @accent-comment;\n    min-width: 2.5em;\n    /*font-size: 0.9em;*/  /* restore after SourceCodePro font fix? */\n    padding: 0 @code-padding 0 10px;  // note: overridden if code-folding gutter is shown\n}\n.CodeMirror .CodeMirror-selected {\n    background: @selection-color-unfocused;\n}\n.CodeMirror-focused .CodeMirror-selected {\n    background: @selection-color-focused;\n}\n\n/*\n    CodeMirror's use of descendant selectors for certain styling causes problems when editors are\n    nested because, for items in the inner editor, the left-hand clause in the selector will now\n    match either the actual containing CodeMirror instance *OR* the outer \"host\" CodeMirror instance.\n    \n    TODO (issue #324): We'll still have problems if editors can be nested more than one level deep,\n    or if any other descendant-selector-driven CM styles can differ between inner & outer editors\n    (potential problem areas include line wrap and coloring theme: basically, anything in codemirror.css\n    that uses a descandant selector where the CSS class name to the left of the space is something\n    other than a vanilla .CodeMirror)\n */\n.CodeMirror {\n    .CodeMirror-overwrite .CodeMirror-cursor {\n        border-left: none !important;\n        border-bottom: 1px solid black;\n        width: 1.2ex;\n    }\n    \n    .CodeMirror {\n        background: transparent;\n    }\n    \n    .CodeMirror span.CodeMirror-matchingbracket {\n        /* Ensure visibility against gray inline editor background */\n        background-color: @matching-bracket;\n        color: @accent-bracket !important;\n    }\n\n    .CodeMirror .CodeMirror-cursors {\n        visibility: hidden;\n    }\n    .CodeMirror.CodeMirror-focused .CodeMirror-cursors {\n        visibility: visible;\n    }\n    \n    .CodeMirror .CodeMirror-selected {\n        background: @selection-color-unfocused;\n    }\n    .CodeMirror.CodeMirror-focused .CodeMirror-selected {\n        background: @selection-color-focused;\n    }\n    .CodeMirror .CodeMirror-gutters {\n        background: transparent;\n        border-right: none;\n    }\n    \n    .CodeMirror-scroll {\n        outline: none;\n    }\n    \n    .CodeMirror-sizer {\n        cursor: text;\n    }\n    \n    .CodeMirror .CodeMirror-vscrollbar, .CodeMirror .CodeMirror-hscrollbar {\n        cursor: default;\n    }\n    \n    .CodeMirror .CodeMirror-activeline-background {\n        background: transparent;\n    }\n    \n    .show-line-padding & .CodeMirror .CodeMirror-activeline-background {\n        box-shadow: none;\n    }\n    \n    .CodeMirror .CodeMirror-activeline .CodeMirror-gutter-elt {\n        background: transparent;\n        color: @accent-comment;\n    }\n    \n    .CodeMirror-focused .CodeMirror-activeline-background {\n        background: @activeline-bg;\n    }\n    \n    .show-line-padding & .CodeMirror-focused .CodeMirror-activeline-background {\n        box-shadow: inset @code-padding 0 0 0 @background;\n    }\n    \n    .CodeMirror-focused .CodeMirror-activeline {\n        .CodeMirror-gutter-elt {\n            background: @activeline-number-bg-inline;\n            color: @activeline-number;\n        }\n    }\n\n    .CodeMirror-matchingtag { background: @matching-bracket; }\n}\n\n/*\n * Temporarily override bold and italic syntax highlighting until\n * SourceCodePro supports them in a fixed pitch\n */\nspan.cm-em {\n    font-style: normal;\n}\nspan.cm-header, span.cm-strong {\n    font-weight: normal;\n}\nspan.cm-emstrong {\n    font-style: normal;\n    font-weight: normal;\n}\n"
  },
  {
    "path": "src/styles/brackets_core_ui_variables.less",
    "content": "// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n/*\n * Brackets Colors\n *\n * These are general purpose colors that can be used in defining\n * themes or UI elements.\n \n * IMPORTANT: IF we want a UI element to be themeable, these variable names or\n * color literals (#aaa) should not be used in its definition.\n *\n * Instead, a new semantically-meaningful variables/mixins should be added\n * to the \"brackets_theme_default.less\" file, and then these variables/mixins\n * should be used in the definition of the UI element\n *\n * For UI elements we do NOT want to theme, we should use these color names\n *\n * All brackets color variable names (that refer to an actual color)\n * are prefixed with \"bc-\" for \"brackets\". This is to avoid confusion\n * with system and css color names. (We define our own colors because system\n * colors are ugly.)\n */\n\n// General\n@bc-bg-highlight:               #e0f0fa;\n@bc-bg-inline-widget:           #e6e9e9;\n@bc-bg-tool-bar:                #5D5F60;\n@bc-bg-status-bar:              #fff;\n@bc-disabled-opacity:           0.3;\n@bc-error:                      #f74687;\n@bc-modal-backdrop-opacity:     0.4;\n@bc-spinner:                    #78b2f2;\n\n// Highlights and Shadows\n@bc-highlight:                  rgba(255, 255, 255, 0.12);\n@bc-highlight-hard:             rgba(255, 255, 255, 0.5);\n@bc-shadow:                     rgba(0, 0, 0, 0.24);\n@bc-shadow-large:               rgba(0, 0, 0, 0.5);\n@bc-shadow-small:               rgba(0, 0, 0, 0.06);\n\n// Border Radius\n@bc-border-radius:              3px;\n@bc-border-radius-large:        5px;\n@bc-border-radius-small:        2px;\n\n// Menu\n@bc-menu-bg:                    #fff;\n@bc-menu-text:                  #000;\n@bc-menu-separator:             #eaeaea;\n\n// inline menu widget\n@bc-inlinemenu-text:            #d4d4d4;\n\n// Warning\n@bc-warning-bg:                 #fdf5cc;\n@bc-warning-text:               #635301;\n\n// Text\n@bc-text:                       #333;\n@bc-text-alt:                   #fff;\n@bc-text-emphasized:            #111;\n@bc-text-link:                  #0083e8;\n@bc-text-medium:                #606060;\n@bc-text-quiet:                 #aaa;\n@bc-text-thin:                  #000;\n@bc-text-thin-quiet:            #777;\n\n// Panel\n@bc-panel-bg:                   #dfe2e2;\n@bc-panel-bg-alt:               #e6e9e9;\n@bc-panel-bg-promoted:          #d4d7d7;\n@bc-panel-bg-hover:             rgba(255, 255, 255, 0.6);\n@bc-panel-bg-hover-alt:         rgba(0, 0, 0, 0.04);\n@bc-panel-bg-selected:          #d0d5d5;\n@bc-panel-bg-text-highlight:    #fff;\n@bc-panel-border:               rgba(0, 0, 0, 0.09);\n@bc-panel-separator:            #c3c6c5;\n\n// Default Button\n@bc-btn-bg:                     #e5e9e9;\n@bc-btn-bg-down:                #d3d7d7;\n@bc-btn-bg-down-alt:            #404141;\n@bc-btn-border:                 #b2b5b5;\n@bc-btn-border-error:           #fa689d;\n@bc-btn-border-error-glow:      #ffb0cd;\n@bc-btn-border-focused:         #2893ef;\n@bc-btn-border-focused-glow:    #94ceff;\n@bc-btn-triangle:               #9b9b9b;\n@bc-input-bg:                   #fff;\n\n// Primary Button\n@bc-primary-btn-bg:             #288edf;\n@bc-primary-btn-bg-down:        #0380e8;\n@bc-primary-btn-border:         #1474bf;\n\n// Secondary Button\n@bc-secondary-btn-bg:           #91cc41;\n@bc-secondary-btn-bg-down:      #82b839;\n@bc-secondary-btn-border:       #74B120;\n\n// Sidebar\n@bc-sidebar-bg:                 #3C3F41;\n@bc-sidebar-selection:          #2D2E30;\n\n// images\n@button-icon:                   \"images/find-replace-sprites.svg\";\n@jstree-sprite:                 url(\"images/jsTreeSprites.svg\") !important;\n\n// Codehint description\n@bc-codehint-desc:              #e6e6e6;\n@bc-codehint-desc-type-details: #1473e6;\n@bc-codehint-desc-documentation:#424242;\n\n/* Dark Core UI variables -----------------------------------------------------------------------------*/\n\n// General\n@dark-bc-bg-highlight:               #284160;\n@dark-bc-bg-inline-widget:           #1b1b1b;\n@dark-bc-bg-tool-bar:                #5D5F60;\n@dark-bc-bg-status-bar:              #1c1c1e;\n@dark-bc-disabled-opacity:           0.3;\n@dark-bc-error:                      #f74687;\n@dark-bc-modal-backdrop-opacity:     0.7;\n@dark-bc-spinner:                    #2b85ea;\n\n// Highlights and Shadows\n@dark-bc-highlight:                  rgba(255, 255, 255, 0.06);\n@dark-bc-highlight-hard:             rgba(255, 255, 255, 0.2);\n@dark-bc-shadow:                     rgba(0, 0, 0, 0.24);\n@dark-bc-shadow-medium:              rgba(0, 0, 0, 0.12);\n@dark-bc-shadow-large:               rgba(0, 0, 0, 0.5);\n@dark-bc-shadow-small:               rgba(0, 0, 0, 0.06);\n\n// Border Radius\n@dark-bc-border-radius:              3px;\n@dark-bc-border-radius-large:        5px;\n@dark-bc-border-radius-small:        2px;\n\n// Menu\n@dark-bc-menu-bg:                    #000;\n@dark-bc-menu-text:                  #fff;\n@dark-bc-menu-separator:             #343434;\n\n// inline menu widget\n@dark-bc-inlinemenu-text:            #d4d4d4;\n\n// Warning\n@dark-bc-warning-bg:                 #c95800;\n@dark-bc-warning-text:               #fff;\n\n// Text\n@dark-bc-text:                       #ccc;\n@dark-bc-text-alt:                   #fff;\n@dark-bc-text-emphasized:            #fff;\n@dark-bc-text-link:                  #6bbeff;\n@dark-bc-text-medium:                #ccc;\n@dark-bc-text-quiet:                 #9a9a9a;\n@dark-bc-text-thin:                  #fff;\n@dark-bc-text-thin-quiet:            #bbb;\n\n// Panel\n@dark-bc-panel-bg:                   #2c2c2c;\n@dark-bc-panel-bg-alt:               #313131;\n@dark-bc-panel-bg-promoted:          #222;\n@dark-bc-panel-bg-hover:             rgba(255, 255, 255, 0.12);\n@dark-bc-panel-bg-hover-alt:         rgba(0, 0, 0, 0.1);\n@dark-bc-panel-bg-selected:          #3d3e40;\n@dark-bc-panel-bg-text-highlight:    #000;\n@dark-bc-panel-border:               #000;\n@dark-bc-panel-separator:            #343434;\n\n// Default Button\n@dark-bc-btn-bg:                     #3f3f3f;\n@dark-bc-btn-bg-down:                #383838;\n@dark-bc-btn-bg-down-alt:            #404141;\n@dark-bc-btn-border:                 #202020;\n@dark-bc-btn-border-error:           #fa689d;\n@dark-bc-btn-border-error-glow:      transparent;\n@dark-bc-btn-border-focused:         #2893ef;\n@dark-bc-btn-border-focused-glow:    transparent;\n@dark-bc-btn-triangle:               #767676;\n@dark-bc-input-bg:                   #555;\n\n// Primary Button\n@dark-bc-primary-btn-bg:             #016dc4;\n@dark-bc-primary-btn-bg-down:        #00569b;\n@dark-bc-primary-btn-border:         #202020;\n\n// Secondary Button\n@dark-bc-secondary-btn-bg:           #5b9e00;\n@dark-bc-secondary-btn-bg-down:      #437900;\n@dark-bc-secondary-btn-border:       #202020;\n\n// Sidebar\n@dark-bc-sidebar-bg:                 #3C3F41;\n@dark-bc-sidebar-selection:          #2D2E30;\n\n// images\n@dark-button-icon:                   \"images/find-replace-sprites-dark.svg\";\n@dark-jstree-sprite:                 url(\"images/jsTreeSprites-dark.svg\") !important;\n\n// Codehint description\n@dark-bc-codehint-desc:              #2c2c2c;\n@dark-bc-codehint-desc-type-details: #46a0f5;\n@dark-bc-codehint-desc-documentation:#b1b1b1;\n"
  },
  {
    "path": "src/styles/brackets_fonts.less",
    "content": "// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//  \n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"), \n// to deal in the Software without restriction, including without limitation \n// the rights to use, copy, modify, merge, publish, distribute, sublicense, \n// and/or sell copies of the Software, and to permit persons to whom the \n// Software is furnished to do so, subject to the following conditions:\n//  \n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//  \n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n// DEALINGS IN THE SOFTWARE.\n\n\n/* Brackets Fonts */\n\n/* Alternative weights */\n\n@font-weight-semibold: 500;\n@font-weight-light: 200;\n\n\n/* SourceSansPro Regular */\n@font-face {\n    font-family: 'SourceSansPro';\n    src: url('fonts/SourceSansPro/SourceSansPro-Regular.ttf');\n    font-weight: normal;\n    font-style: normal;\n}\n\n\n/* SourceSansPro Light */\n@font-face {\n    font-family: 'SourceSansPro';\n    src: url('fonts/SourceSansPro/SourceSansPro-Light.ttf');\n    font-weight: @font-weight-light;\n    font-style: normal;\n}\n\n\n/* SourceSansPro Semibold */\n@font-face {\n    font-family: 'SourceSansPro';\n    src: url('fonts/SourceSansPro/SourceSansPro-Semibold.ttf');\n    font-weight: @font-weight-semibold;\n    font-style: normal;\n}\n\n/* SourceSansPro Italic */\n@font-face {\n    font-family: 'SourceSansPro';\n    src: url('fonts/SourceSansPro/SourceSansPro-It.ttf');\n    font-weight: normal;\n    font-style: italic;\n}\n\n\n/* SourceCodePro Regular */\n@font-face {\n    font-family: 'SourceCodePro';\n    src: url('fonts/SourceCodePro/SourceCodePro-Regular.ttf');\n    font-weight: normal;\n    font-style: normal;\n}\n\n/* SourceCodePro Medium */\n@font-face {\n    font-family: 'SourceCodePro-Medium';\n    src: url('fonts/SourceCodePro/SourceCodePro-Medium.ttf');\n    font-weight: normal;\n    font-style: normal;\n}\n\n/* Font Stacks */\n\n@sansFontFamily: 'SourceSansPro', Helvetica, Arial, \"Meiryo UI\", \"ＭＳ Ｐゴシック\", \"MS PGothic\", sans-serif;\n\n@sourceFontFamily: \"SourceCodePro\", \"Menlo Regular\", Consolas, Inconsolata, \"Vera Sans\", \"Lucida Console\", Courier, fixed;\n@sourceFontFamily-Medium: \"SourceCodePro-Medium\", \"ＭＳ ゴシック\", \"MS Gothic\", monospace;\n"
  },
  {
    "path": "src/styles/brackets_mixins.less",
    "content": "\n// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//  \n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"), \n// to deal in the Software without restriction, including without limitation \n// the rights to use, copy, modify, merge, publish, distribute, sublicense, \n// and/or sell copies of the Software, and to permit persons to whom the \n// Software is furnished to do so, subject to the following conditions:\n//  \n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//  \n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n// DEALINGS IN THE SOFTWARE.\n\n/* Brackets mixins */\n\n/* Helpers for working with flex layouts */\n/* see: https://developer.mozilla.org/en-US/docs/Web/CSS/flex */\n.flex-box(@direction: row) {\n    display: flex;\n    flex-direction: @direction;\n}\n.flex-item(@grow: 0, @shrink: 1, @basis: auto) {\n    flex: @grow @shrink @basis;\n}\n\n/* Helpers for working with box layouts */\n.box {\n    display: -webkit-box;\n    display: -moz-box;\n    display: box;\n}\n.hbox {\n    .box;\n    -webkit-box-orient: horizontal;\n    -moz-box-orient: horizontal;\n    box-orient: horizontal;\n}\n.vbox {\n    .box;\n    -webkit-box-orient: vertical;\n    -moz-box-orient: vertical;\n    box-orient: vertical;\n}\n.box-flex(@ratio) {\n    -webkit-box-flex: @ratio;\n    -moz-box-flex: @ratio;\n    box-flex: @ratio;\n}\n.box-pack(@pack) {\n    -webkit-box-pack: @pack;\n    -moz-box-pack: @pack;\n    box-pack: @pack;\n}\n.box-align(@align) {\n    -webkit-box-align: @align;\n    -moz-box-align: @align;\n    box-align: @align;\n}\n\n/* Helpful for percentage-sizing items that have border/padding */\n.sane-box-model {\n    box-sizing: border-box;\n}\n\n/* Helpers for spritesheet images */\n/* Sets the background to the given offset in the spritesheet. Typically, the element you set this on requires\n   a fixed size so that other parts of the spritesheet don't show. */\n.sprite(@x-offset, @y-offset, @sprite-sheet) {\n    background: url(\"@{sprite-sheet}\") -@x-offset -@y-offset no-repeat;\n}\n\n/* Turns the given element into an icon showing the given rectangle in the spritesheet. Can be used on empty elements\n   (e.g. a link with no text) or on the :before/:after selector of elements that have content. */\n.sprite-icon(@x-offset, @y-offset, @width, @height, @sprite-sheet) {\n    content: \"\";\n    .sprite(@x-offset, @y-offset, @sprite-sheet);\n    width: @width;\n    height: @height;\n}\n\n/* Like .sprite-icon, but for retina. Note that the x-offset/y-offset/width/height are non-retina\n * sizes. The background-width/background-height are the *total* non-retina size of the\n * spritesheet. .sprite-swap() works as usual (again with non-retina sizes). So, for example, if you have\n * a non-retina \"spritesheet.png\" at 48x24 (with two icons that are 24x24 each) and a retina version\n * \"spritesheet@2x.png\" at 96x48, you would call:\n *     .sprite-icon-retina(0, 0, 24px, 24px, \"spritesheet.png\", 48px, 24px, \"spritesheet@2x.png\");\n *     &:hover { .sprite-swap(-24px, 0); }\n */\n.sprite-icon-retina(@x-offset, @y-offset, @width, @height, @sprite-sheet, @background-width, @background-height, @sprite-sheet-2x) {\n    content: \"\";\n    .sprite-icon(@x-offset, @y-offset, @width, @height, @sprite-sheet);\n    background-size: @background-width @background-height;\n    @media only screen and (-webkit-min-device-pixel-ratio: 2),\n        only screen and (min-device-pixel-ratio: 2) {\n            background-image: url(\"@{sprite-sheet-2x}\");\n        }\n}\n\n/* Changes an element that's already showing one area of a spritesheet to show a different area of the same size.\n   Should be used with an element whose base styling includes .sprite() or .sprite-icon() */\n.sprite-swap(@x-offset, @y-offset) {\n    background-position: -@x-offset -@y-offset;\n}\n\n    \n/* Scale x-axis using top-left as the origin  */\n.scale-x (@value: 1.0, @horizontal: 50%, @vertical: 50%) {\n    -ms-transform: scaleX(@value);\n    -moz-transform: scaleX(@value);\n    -webkit-transform: scaleX(@value);\n    -o-transform: scaleX(@value);\n    transform: scaleX(@value);\n    \n    -ms-transform-origin: @horizontal @vertical;\n    -moz-transform-origin: @horizontal @vertical;\n    -webkit-transform-origin: @horizontal @vertical;\n    -o-transform-origin: @horizontal @vertical;\n    transform-origin: @horizontal @vertical;\n}\n\n/* Change the settings for user-select and its counterparts, defaulting to none. */\n.user-select(@type: none) {\n    -webkit-user-select: @type;\n    -khtml-user-select: @type;\n    -moz-user-select: @type;\n    -ms-user-select: @type;\n    -o-user-select: @type;\n    user-select: @type;\n}\n\n.animation (@name, @duration: 300ms, @ease: ease, @delay: 0ms, @iteration-count: 1) {\n    -webkit-animation: @name @duration @ease @delay @iteration-count;\n    animation: @name @duration @ease @delay @iteration-count;\n}\n"
  },
  {
    "path": "src/styles/brackets_patterns_override.less",
    "content": "\n// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n\n/* Brackets patterns (and overrides and re-definitions of Bootstrap patterns)\n *\n * This file should contain all _reusable_ UI elements / LESS definitions\n * That is, things that will either a.) be used for more than one element or\n * b.) exist in multiple versions of brackets (e.g. App, In-Browser, etc.)\n *\n * Note that if you want a UI element to be themeable, you should put the\n * themeable part in \"brackets_theme_default\" as variables/mixins.\n *\n */\n\n/* Links */\n\na {\n    color: @bc-text-link;\n    text-decoration: none;\n\n    .dark & {\n        color: @dark-bc-text-link;\n    }\n}\n\na:hover {\n    color: @bc-text-link;\n    text-decoration: underline;\n\n    .dark & {\n        color: @dark-bc-text-link;\n    }\n}\n\na:focus {\n    color: @bc-text-link;\n    outline: 0;\n    box-shadow: 0 0 0 1px @bc-btn-border-focused-glow;\n    text-decoration: none;\n\n    .dark & {\n        color: @dark-bc-text-link;\n        box-shadow: 0 0 0 1px @dark-bc-btn-border-focused;\n    }\n}\n\n.panel {\n    .vbox;\n    .box-flex(1);\n\n    padding: 0;\n    margin: 0;\n\n    background: @project-panel-base-color;\n    color: #bbb;\n    letter-spacing: .01em;\n    text-shadow: 0 1px 2px @bc-shadow-large;\n\n    .dark & {\n        text-shadow: 0 1px 2px @dark-bc-shadow-large;\n    }\n}\n\n/* working set drag ghost styles */\n\n.wsv-drag-ghost {\n    letter-spacing: .01em;\n    position: absolute;\n    z-index: @z-index-brackets-drag-ghost;\n    background-color: transparent;\n\n    text-shadow: 0 1px 2px @bc-shadow-large;\n\n    .dark & {\n        text-shadow: 0 1px 2px @dark-bc-shadow-large;\n    }\n}\n\n.wsv-drag-ghost.dragging-current-file {\n    background-color: @bc-sidebar-selection;\n}\n\n#working-set-list-container .drag-show-as-selected {\n    background-color: @bc-sidebar-selection;\n}\n\n/* Toolbar-related styles */\n\n/* Simple toolbar layout (project panel, find in files, etc.)\n   We don't set this directly on .toolbar because it'd be a pain to override all the pieces\n   if other code (e.g. #main-toolbar) wants to do a different layout */\n.simple-toolbar-layout.toolbar {\n    .hbox;\n    .box-align(center);\n    overflow: hidden;\n\n    .title-wrapper {\n        /* This is necessary because text-overflow: ellipsis doesn't work when it's set\n           directly on a flexing box in Chrome currently. */\n        .box-flex(1);\n    }\n    .buttons {\n        .hbox;\n        margin-left: 4px;\n    }\n}\n\n/* Horizontal titlebar/menubar (in-browser only)\n\n   CSS hack based on this code: http://jsfiddle.net/cD657/3/ (via StackOverflow)\n   This center-aligns the title across the full width of the toolbar (ignoring the width of the nav floated\n   left and buttons floated right), yet still have the browser automatically wrap the floats onto a 2nd row\n   if they collide with the title. But the centered content must be a block element with fixed width. Since\n   the editor title (filename) varies in width, we rely on JS code to update the width whenever the string\n   changes.\n\n   Another wrinkle: wrapping to/from the two-line toolbar layout requires notifying the CodeMirror editor that\n   its height changed. Currently, we assume this can ONLY happen in two cases:\n    - the window resizes (handled by general listener in EditorManager)\n    - title content changes (the same JS code that sets .title-wrapper's fixed width is expected to handle this)\n*/\n#titlebar {\n    // Visible only in-browser\n    body.has-appshell-menus & {\n        display: none;\n    }\n\n    text-align: center;\n    .nav {  // menubar\n        float: left;\n        text-align: left;\n        > li {\n            float: left;\n        }\n        .dropdown-menu {\n            //max-height: calc(~\"100vh - 34px\"); doesn't seem to work...\n            max-height: 90vh;\n            overflow-y: auto;\n            -webkit-animation: none;\n            animation: none;\n        }\n    }\n    .title {\n        float: none;\n        display: inline;  // must be an inline for JS to measure text size\n    }\n    .title-wrapper {\n        margin: 0 auto;\n        display: block;  // must be a block for the fixed width applied by JS to be respected\n        // width set in px is appled/updated by JavaScript in DocumentCommandHandlers\n    }\n}\n\n/* Vertical icon toolbar on right */\n#main-toolbar {\n    position: absolute;\n    top: 0;\n    right: 0;\n    width: @main-toolbar-width;\n    height: 100%;\n    box-sizing: border-box;\n\n    background: @main-toolbar-background-color;\n    padding: 7px 0;\n\n    // Ensure icons are vertically stacked & horizontally centered\n    .vbox;\n    .box-flex(1);\n    text-align: center;\n\n    // Ensure that it stays on top\n    z-index: @z-index-brackets-main-toolbar;\n\n    .buttons,\n    .bottom-buttons {\n        text-align: center;\n        margin: 0;\n\n        > a {\n            border-radius: @bc-border-radius;\n            background-repeat: no-repeat;\n            display: block;\n            height: 24px;\n            margin: 7px 0 0 3px;\n            width: 24px;\n        }\n\n        > a:hover {\n            background-color: @bc-shadow !important;\n\n            .dark & {\n                background-color: @dark-bc-shadow !important;\n            }\n        }\n\n        > a:active {\n            background-color: @bc-shadow-large !important;\n\n            .dark & {\n                background-color: @dark-bc-shadow-large !important;\n            }\n        }\n    }\n\n    .bottom-buttons {\n        position: absolute;\n        bottom: 5px;\n    }\n}\n\n/* Toolbar appearance - shared by all toolbars, independent of layout */\n\n@toolbar-top-gap-px: 5px;\n\n.toolbar {\n    font-size: @label-font-size;\n    padding: 4px 8px;\n    background-color: @bc-menu-bg;\n    color: @bc-menu-text;\n\n    position: relative;  // needed for abs-positioned elements in toolbar (e.g. right-aligned \"X\")\n\n    .dark & {\n        background-color: @dark-bc-panel-bg-promoted;\n        color: @dark-bc-menu-text;\n    }\n\n    .title-wrapper {\n        // Title is taller than menu text, so reduce top padding to keep its baseline aligned\n        padding: (@toolbar-top-gap-px - 3px) 0 3px 0;\n    }\n    .title {\n        font-size: @title-font-size;\n        line-height: normal;\n        font-weight: @font-weight-light;\n\n        // On Win, the size+weight combo used above does not look good for the bullet character\n        .dirty-dot {\n            font-weight: normal;\n        }\n\n        white-space: nowrap;\n        overflow: hidden;\n        text-overflow: ellipsis;\n    }\n\n    .buttons {\n        margin: @toolbar-top-gap-px 0 0 4px;\n\n        span, a {\n            cursor: default;\n        }\n    }\n}\n\n\n/* Menu-related styles */\n\n@menubar-top-padding: 8px;\n@menubar-bottom-padding: 6px;\n@menubar-h-padding: 9px;\n\n// Dropdown Menu Animation\n.dropdown-menu {\n    .animation(dropdown, 90ms, cubic-bezier(0, .97, .2, .99));\n    -webkit-transform-origin: 0 0;\n    transform-origin: 0 0;\n    border: none;\n    border-radius: @bc-border-radius;\n\n    .dark & {\n        border: 1px solid rgba(255, 255, 255, 0.09) !important;\n    }\n}\n\n@-webkit-keyframes dropdown {\n    0%   { opacity: 0.5; -webkit-transform: translate3d(0, 0, 0) scale(0.5); }\n    100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0) scale(1); }\n}\n@keyframes dropdown {\n    0%   { opacity: 0.5; transform: translate3d(0, 0, 0) scale(0.5); }\n    100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }\n}\n\n// Code hints and inlinemenu don't need scaling navigation so we're removing it\n.codehint-menu.open .dropdown-menu, .inlinemenu-menu .dropdown-menu {\n    -webkit-animation: none;\n    animation: none;\n}\n\n.toolbar .nav, .context-menu, .codehint-menu, .inlinemenu-menu {\n\n    // The 1px adjustments here are to account for the border around the top-level menu items.\n    margin: (@toolbar-top-gap-px - @menubar-top-padding - 1) 0 (-@menubar-bottom-padding + 1) (-@menubar-h-padding + 4);\n\n    // General item appearance\n    a {\n        color: @bc-menu-text;\n        text-shadow: none;\n        cursor: default;\n\n        .dark & {\n            color: @dark-bc-menu-text;\n        }\n    }\n\n    // Menubar item appearance\n    .dropdown-toggle {\n        padding: @menubar-top-padding @menubar-h-padding @menubar-bottom-padding;\n        border: 1px solid rgba(0, 0, 0, 0); // transparent border just to hold the layout so it doesn't shift on hover\n        color: fadeout(@bc-menu-text, 25%);\n\n        .dark & {\n            color: fadeout(@dark-bc-menu-text, 25%);\n        }\n    }\n    .dropdown-toggle:focus {\n        background-color: @bc-menu-bg;\n        outline: 0;\n\n        .dark & {\n            background-color: @dark-bc-menu-bg;\n        }\n    }\n    .dropdown-toggle:hover, .dropdown.open .dropdown-toggle {\n        /* Note: we need several selectors for this in order to match the specificity of all the various Bootstrap\n           color rules we need to override (and Bootstrap has several selectors because the colors really differ\n           in their defaults). */\n        color: @bc-menu-text;\n        background: @bc-bg-highlight;\n        border-color: @bc-bg-highlight;\n\n        .dark & {\n            color: @dark-bc-menu-text;\n            background: @dark-bc-bg-highlight;\n            border-color: @dark-bc-bg-highlight;\n        }\n    }\n\n    // no triangle icon after menu items\n    .dropdown-toggle:after {\n        border: 0;\n        margin: 0;\n    }\n\n    // Menu dropdown appearance\n    .dropdown-menu {\n        // Offset for better alignment with button\n        top: 34px;\n        margin-top: 0;\n\n        // Fix for #4593: don't let narrow parent (menubar item) cause text wrap at the float boundary between\n        // the menu item label and keyboard shortcut. This takes away the \"gotta get narrower\" pressure.\n        // This technique won't work on all browsers; see comments in #4593 for alternative options.\n        width: -webkit-max-content;\n        width: -moz-max-content;\n        width: max-content;\n\n        background-color: @bc-menu-bg;\n        border-radius: 0 0 3px 3px;\n        box-shadow: 0 3px 9px @bc-shadow;\n        border: none;\n\n        .dark & {\n            background-color: @dark-bc-menu-bg;\n            box-shadow: 0 3px 9px @dark-bc-shadow;\n        }\n\n        // Menu items\n        li {\n            a {\n                font-size: @menu-item-font-size;\n                line-height: 18px;\n\n                // Slightly less padding on left to account for checkmark.\n                // More padding on top than bottom to center font within its bg highlight better.\n                padding: 2px 10px 0 6px;\n\n                color: @bc-menu-text;\n                text-shadow: none;\n                white-space: nowrap;\n                .box-shadow(none);\n\n                .dark & {\n                    color: @dark-bc-menu-text;\n                }\n\n                &.wide-result {\n                    white-space: normal;\n                }\n\n                &:hover, &.highlight {\n                    color: @bc-menu-text;\n                    background: @bc-bg-highlight;\n\n                    .dark & {\n                        color: @dark-bc-menu-text;\n                        background: @dark-bc-bg-highlight;\n                    }\n                }\n\n                &.disabled {\n                    color: @bc-text-thin-quiet;\n\n                    .dark & {\n                        color: @dark-bc-text-thin-quiet;\n                    }\n\n                    &:hover {\n                        background: @bc-menu-bg;\n\n                        .dark & {\n                            background: @dark-bc-menu-bg;\n                        }\n                    }\n                }\n\n                /* hidden checkmark for all list item content ensures consistent left spacing */\n                &::before {\n                    content: \"✓\\00a0\"; /* non-breaking space */\n                    visibility: hidden;\n                }\n                /* toggle checkmark visibility */\n                &.checked::before {\n                    visibility: visible;\n                }\n            }\n        }\n\n        .divider {\n            background-color: @bc-menu-separator;\n            border: 0;\n            margin: 5px 1px;\n\n            .dark & {\n                 background-color: @dark-bc-menu-separator;\n            }\n        }\n    }\n\n    // Ensure a minimum amount of space to the left of the shortcut\n    .menu-shortcut {\n        float: right;\n        margin-left: 15px;\n    }\n}\n\n\n/* Context menu styles */\n\n\n.context-menu, .codehint-menu, .inlinemenu-menu {\n    position: absolute;\n    z-index: @z-index-brackets-context-menu-base;\n    list-style-type: none;\n\n    .dropdown-menu {\n        border-radius: 3px;\n        box-shadow: 0 3px 9px @bc-shadow;\n\n        .dark & {\n            box-shadow: 0 3px 9px @dark-bc-shadow;\n        }\n    }\n\n    .menu-shortcut {\n        float: right;\n    }\n}\n\n.codehint-menu, .inlinemenu-menu {\n    opacity: 0;\n    .dropdown-menu {\n        box-shadow: 0 3px 9px @bc-shadow;\n        max-height: 160px;\n        overflow-y: auto;\n        padding: 0;\n\n        .dark & {\n            box-shadow: 0 3px 9px @dark-bc-shadow;\n        }\n\n        // Styles used for inlinemenu widget header\n        li.inlinemenu-header a {\n            background-color: @bc-bg-tool-bar;\n            color: @bc-inlinemenu-text;\n            padding-bottom: 5px;\n\n            .dark & {\n                background-color: @dark-bc-bg-tool-bar;\n                color: @dark-bc-inlinemenu-text;\n                padding-bottom: 5px;\n            }\n\n            &:hover {\n                background-color: @bc-bg-tool-bar;\n                color: @bc-inlinemenu-text;\n                padding-bottom: 5px;\n\n                .dark & {\n                    background-color: @dark-bc-bg-tool-bar;\n                    color: @dark-bc-inlinemenu-text;\n                    padding-bottom: 5px;\n                }\n            }\n        }\n\n        li {\n            a {\n                // Less padding than on menus. More padding on top than bottom\n                // to center font within its bg highlight better.\n                padding: 2px 20px 4px 0;\n\n                // Don't show highlighting on hover for code hints...\n                &:hover {\n                    color: @bc-menu-text;\n                    background-color: @bc-menu-bg;\n\n                    .dark & {\n                        color: @dark-bc-menu-text;\n                        background-color: @dark-bc-menu-bg;\n                    }\n                }\n\n                // ...except for selected item\n                &.highlight:hover {\n                    color: @bc-menu-text;\n                    background-color: @bc-bg-highlight;\n\n                    .dark & {\n                        color: @dark-bc-menu-text;\n                        background-color: @dark-bc-bg-highlight;\n                    }\n                }\n\n                .color-swatch {\n                    border-radius: 2px;\n                    width: 12px;\n                    height: 12px;\n                    float: left;\n                    margin: 2px -8px 0 4px;\n                    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.24);\n\n                    .dark & {\n                        box-shadow: inset 0 0 1px rgba(255, 255, 255, 0.24);\n                    }\n                }\n\n                // Used to align non-swatch items with the others. Only applied\n                // if there's at least one item with a swatch in the list\n                .no-swatch-margin {\n                    margin-left: 8px;\n                }\n            }\n        }\n    }\n}\n\n.codehint-menu.open, .inlinemenu-menu.open {\n    opacity: 1;\n    transition: opacity 67ms cubic-bezier(0.03, 0.78, 0.17, 0.97);\n}\n\n.codehint-menu.apply-transition, .inlinemenu.apply-transition {\n    transition: right 167ms, left 167ms;\n}\n\n#codehint-desc {\n\tbackground: @bc-codehint-desc;\n\tposition: absolute;\n\twidth: 100%;\n\tbox-sizing: border-box;\n\tfloat: left;\n\tborder-radius: 1px !important;\n\tborder-top-left-radius: 0px !important;\n\tborder-top-right-radius: 0px !important;\n\toverflow-x: hidden;\n\tmin-height: 30px;\n\tmax-height: 120px !important;\n    \n    .dark & {\n\t\tbackground: @dark-bc-codehint-desc;\n\t}\n}\n\n.codehint-desc-type-details {\n\tpadding: 5px 15px 5px 15px;\n\tcolor: @bc-codehint-desc-type-details;\n\tfont-weight: bold;\n\tfont-size: 1.2em;\n    line-height: inherit;\n    \n    .dark & {\n\t\tcolor: @dark-bc-codehint-desc-type-details;\n\t}\n}\n\n.codehint-desc-documentation {\n\tpadding: 5px 15px 5px 15px;\n\tcolor: @bc-codehint-desc-documentation;\n\tfont-size: 1.1em;\n\twhite-space: pre-wrap;\n    \n    .dark & {\n\t\tcolor: @dark-bc-codehint-desc-documentation;\n\t}\n}\n\n#context-menu-bar {\n    margin: 0;\n}\n\n/* DropdownButton widget */\n\n.btn-dropdown, .btn-dropdown.btn-mini {\n    position: relative;   // needed to position ::after arrow\n    padding-right: 24px;  // makes room for ::after arrow\n}\n.btn-dropdown::after {\n    content: \"\";\n    display: block;\n    height: 0;\n    width: 0;\n    position: absolute;\n    right: 7px;\n    top: 11px;\n\n    /* dropdown triangle */\n    border-top: 5px solid @bc-btn-triangle;\n    border-left: 4px solid transparent;\n    border-right: 4px solid transparent;\n\n    .dark & {\n        border-top: 5px solid @dark-bc-btn-triangle;\n    }\n}\n.btn-dropdown.btn-mini::after {\n    top: 7px;\n}\n\n.dropdownbutton-popup {\n    &.dropdown-menu:focus {\n        outline: none;\n    }\n\n    &.dropdown-menu {\n        border: none;\n        border-radius: @bc-border-radius;\n        padding: 5px 0;\n        position: absolute;\n        display: block;\n        box-shadow: 0 3px 9px @bc-shadow;\n        max-height: 160px;\n        overflow-y: auto;\n        max-width: none;\n        min-width: 200px;\n        z-index: @z-index-brackets-stylesheet-menu;\n\n        .dark & {\n            box-shadow: 0 3px 9px @dark-bc-shadow;\n        }\n    }\n\n    &.dropdown-menu li a {\n        padding: 1px 15px 1px 15px;\n        color: @bc-menu-text;\n\n        .dark & {\n            color: @dark-bc-menu-text;\n        }\n\n        &.disabled {\n            color: @bc-text-thin-quiet;\n\n            .dark & {\n                color: @dark-bc-text-thin-quiet;\n            }\n        }\n    }\n\n    &.dropdown-menu .stylesheet-link {\n        display: block;\n    }\n\n    &.dropdown-menu a.selected {\n        background: @bc-bg-highlight;\n        color: @bc-menu-text !important;\n\n        .dark & {\n            background: @dark-bc-bg-highlight;\n            color: @dark-bc-menu-text !important;\n        }\n    }\n\n    &.dropdown-menu a {\n        &::before {\n            position: absolute;\n            left: 10px;\n            text-align: center;\n            content: \"✓\";\n            display: none;\n        }\n        /* toggle checkmark visibility */\n        &.checked::before {\n            display: inline-block;\n        }\n    }\n\n    &.dropdown-menu a:hover {\n        /* toggle checkmark visibility */\n        &.checked::before {\n            display: none;\n        }\n    }\n\n    &.dropdown-menu a:not(.selected):hover {\n        background: none;\n    }\n\n    .divider {\n        margin: 5px 1px;\n    }\n\n}\n\n/* Status bar language picker's DropdownButton */\n.dropdownbutton-popup.dropdown-status-bar {\n    -webkit-transform-origin: 0 100%;\n    transform-origin: 0 100%;\n    height: auto;\n    max-height: 80%;\n\n    // Improve how bottom of the dropdown joins with top of status bar button\n    margin-top: -6px;\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n\n    li a .default-language {\n        font-style: italic;\n        color: @bc-text-quiet;\n\n        .dark & {\n            color: @dark-bc-text-quiet;\n        }\n    }\n\n    li a .checked-language::before {\n        content: \"✓\";\n        margin-left: -11px;\n        margin-right: 3px;\n    }\n}\n\n/* Inline editor stylesheet-picker DropdownButton */\n\n.stylesheet-button.btn-mini {\n    margin-left: 8px;\n    top: -1px;\n}\n\n.dropdownbutton-popup {\n    .stylesheet-link, .stylesheet-name {\n        white-space: nowrap;\n    }\n\n    .stylesheet-name {\n        color: @bc-text;\n\n        .dark & {\n            color: @dark-bc-text;\n        }\n    }\n\n    .stylesheet-dir {\n        color: @bc-text-quiet;\n\n        .dark & {\n            color: @dark-bc-text-quiet;\n        }\n    }\n}\n\n/* Dialog-related styles */\n\n.modal-wrapper {\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    top: 0;\n    left: 0;\n    overflow: auto;\n    display: table;\n}\n\n.modal-inner-wrapper {\n    display: table-cell;\n    vertical-align: middle;\n}\n\n.modal {\n    background-color: @bc-panel-bg;\n    border: 1px solid @bc-panel-border;\n    min-width: 200px;\n    position: relative;\n    top: 0;\n    margin: auto;\n    .animation(modal, 240ms, cubic-bezier(0, 1.05, .35, 1));\n\n    .dark & {\n        background-color: @dark-bc-panel-bg;\n        border: 1px solid @dark-bc-panel-border;\n    }\n}\n\n.modal .close {\n    cursor: default;\n    margin: 7px 5px 0 0;\n}\n\n.modal-header {\n    background: @bc-panel-bg-promoted;;\n    border-radius: 4px 4px 0 0;\n    border-bottom: 1px solid @bc-panel-separator;\n    box-shadow: inset 0 1px 0 @bc-highlight;\n\n    .dark & {\n        background: @dark-bc-panel-bg-promoted;;\n        border-bottom: 1px solid @dark-bc-panel-separator;\n        box-shadow: inset 0 1px 0 @dark-bc-highlight;\n    }\n}\n\n.modal-body {\n    background-color: @bc-panel-bg;\n\n    .dark & {\n        background-color: @dark-bc-panel-bg;\n    }\n}\n\n.modal-body.no-padding {\n    padding: 0;\n}\n\n.modal-body.no-padding td:first-child,\n.modal-body.no-padding th:first-child {\n    padding-left: 15px;\n}\n\n.modal-body.no-padding td:last-child,\n.modal-body.no-padding th:last-child {\n    padding-right: 15px;\n}\n\n.modal-body, .modal-header, .modal-footer {\n    /* See styles/bootstrap/patterns.less .modal class.\n       Pushing this value down to .modal-header and .modal-body\n       to allow the overall modal to take the width of the footer */\n    width: auto;\n}\n\n.modal-footer {\n    text-align: right;\n    background-color: @bc-panel-bg;\n    border-top: 1px solid @bc-panel-separator;\n    box-shadow: none;\n    padding: 10px 15px 12px;\n    white-space: nowrap;\n\n    .dark & {\n        background-color: @dark-bc-panel-bg;\n        border-top: 1px solid @dark-bc-panel-separator;\n    }\n}\n\n.modal-footer .btn {\n    float: none;\n}\n.modal-footer .left {\n    float: left;\n\n    /* Transfer the margin to the right of each left-aligned button, so the left side lines up properly\n     * with the title.\n     */\n    margin-left: 0;\n    margin-right: 5px;\n}\n.modal-footer .btn:not(.left) {\n    margin-left: 5px;\n}\n\n.platform-win {\n    /* Reverse Save/Cancel button order on Win */\n    .modal-footer {\n        text-align: left;\n    }\n    .modal-footer .btn:not(.left) {\n        float: right;\n    }\n}\n\n.modal-body ul {\n    /* Bootstrap's type.less defines a heavy margin-bottom on ul/ol that we don't want in dialogs\n       since they have heavy padding instead. */\n    margin-bottom: 0;\n}\n\n.modal-backdrop {\n    .animation (backdrop, 200ms, linear);\n    opacity: @bc-modal-backdrop-opacity;\n\n    .dark & {\n        opacity: @dark-bc-modal-backdrop-opacity;\n    }\n}\n\n@-webkit-keyframes backdrop {\n    0%   { opacity: 0; -webkit-transform: translate3d(0, 0, 0); }\n    100% { opacity: 0.4; -webkit-transform: translate3d(0, 0, 0); }\n}\n@keyframes backdrop {\n    0%   { opacity: 0; transform: translate3d(0, 0, 0); }\n    100% { opacity: 0.4; transform: translate3d(0, 0, 0); }\n}\n\n@-webkit-keyframes modal {\n    0%   { opacity: 0; -webkit-transform: translate3d(0, 0, 0) scale(0); }\n    100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0) scale(1); }\n}\n@keyframes modal {\n    0%   { opacity: 0; transform: translate3d(0, 0, 0) scale(0); }\n    100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }\n}\n\n\n.dialog-title {\n    color: @bc-text-thin;\n    margin-bottom: 0;\n    margin-top: 0;\n    font-size: 22px;\n    line-height: 30px;\n    font-weight: normal;\n\n    .dark & {\n        color: @dark-bc-text-thin;\n    }\n}\n\n.dialog-message {\n    color: @bc-text;\n    font-size: 14px;\n    line-height: 20px;\n    margin-bottom: 20px;\n    font-weight: normal;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\n.dialog-message li {\n    line-height: 20px;\n    color: @bc-text-thin;\n    padding: 0 0 5px;\n\n    .dark & {\n        color: @dark-bc-text-thin;\n    }\n}\n\n.dialog-message select {\n    margin-left: 10px;\n}\n\n.dialog-message select {\n    margin-left: 10px;\n}\n\n.dialog-list {\n    list-style: none;\n    margin: 5px 0 20px 10px;\n}\n\n.dialog-list > li:before {\n    content: \"•  \";\n    color: @bc-text-quiet;\n    font-size: 1.5em;\n    position: relative;\n    top: 2px;\n\n    .dark & {\n        color: @dark-bc-text-quiet;\n    }\n}\n\n.dialog-filename {\n    word-wrap: break-word;\n\n    font-weight: @font-weight-semibold;\n}\n\n/* Any Dialog text in this style is automatically turned into a link that opens in the browser. Use href for the link's target. */\na[href^=\"http\"] {\n    cursor: pointer;\n}\n\n/* Update dialog */\n.update-dialog .modal-header {\n    position: relative;\n    .update-icon {\n        position: absolute;\n        left: 15px; // relative to border of modal-body\n        top: 10px;\n        width: 28px;\n        height: 28px;\n    }\n     .dialog-title {\n        // Icon is 28px, so we need at least that much left padding/margin to avoid overlap\n        margin-left: 34px;\n     }\t     \n}\n\n.update-dialog .modal-body {\n        position: relative;\n    \n    .update-text {\n        // Icon is 120px, so we need at least that much left padding/margin to avoid overlap\n        margin-left: 29px;\n\n        padding-top: 21px;\n        max-height: 280px;\n        overflow: auto;\n\n        .dialog-message {\n           font-size: 16px;\n        }\n        .update-info {\n            margin-right: 10px;\n            // Enable text selection\n            cursor: auto;\n            .user-select(text);\n\n            h3 {\n                font-weight: normal;\n                margin: 0 0 10px;\n                font-size: 20px;\n            }\n\n            ul {\n                margin-bottom: 0 0 20px;\n\n                > li {\n                    margin-bottom: 10px;\n                }\n            }\n        }\n    }\n}\n\n/* Project Settings and Install Extension dialogs */\n.project-settings-dialog .modal-body, .install-extension-dialog .modal-body {\n    text-align: center;\n\n    .field-container {\n        display: inline-block;\n    }\n    label {\n        float: none;\n    }\n    input.url {\n        display: inline;\n    }\n}\n\n.project-settings-dialog .modal-body input.url {\n    margin: 0 0 0 5px;\n    width: 400px;\n}\n\n.install-extension-dialog .modal-body input.url {\n    margin: 10px 0;\n    width: 550px;\n}\n\n/* Extension Manager dialog */\n.extension-manager-dialog {\n    background-color: @bc-panel-bg-promoted;\n    min-width: @extension-manager-min-width;\n\n    .dark & {\n        background-color: @dark-bc-panel-bg-promoted;\n    }\n\n    .modal-header {\n        border-bottom: none;\n        padding: 0;\n\n        .nav-tabs {\n            margin: 0;\n            border-color: @bc-panel-separator;\n\n            .dark & {\n                border-color: @dark-bc-panel-separator;\n            }\n\n            /* Tab styling */\n            > li > a {\n                min-width: 80px;\n                min-height: 60px;\n                color: @bc-text-thin;\n                cursor: default;\n                font-size: 12px;\n\n                .box;\n                box-sizing: border-box;\n                .box-align(center);\n                .box-pack(center);\n                padding: 0;\n                margin: 0;\n\n                text-align: center;\n\n                .dark & {\n                    color: @dark-bc-text-thin;\n                }\n\n                &:hover {\n                    background-color: @bc-panel-bg-hover-alt;\n                    border-color: @bc-panel-bg-hover-alt;\n\n                    .dark & {\n                        background-color: @dark-bc-panel-bg-hover-alt;\n                        border-color: @dark-bc-panel-bg-hover-alt;\n                    }\n                }\n\n                &:focus {\n                    background-color: @bc-menu-bg;\n                    border-color: @bc-menu-bg;\n\n                    .dark & {\n                        background-color: @dark-bc-menu-bg;\n                        border-color: @dark-bc-menu-bg;\n                    }\n                }\n\n                > img {\n                    margin-top: 5px;\n                    padding-bottom: 2px;\n                }\n            }\n\n            /* Remove border-left from the first tab */\n            > li:nth-child(1) > a {\n                border-left: transparent;\n            }\n\n            /* Colors for the active tab, remove bottom border */\n            > .active > a,\n            > .active > a:hover {\n                background-color: @bc-panel-bg;\n                border-color: @bc-btn-border @bc-btn-border transparent @bc-btn-border;\n\n                .dark & {\n                    background-color: @dark-bc-panel-bg;\n                    border-color: @dark-bc-btn-border @dark-bc-btn-border transparent @dark-bc-btn-border;\n                }\n            }\n\n            > .active > a:focus {\n                background-color: @bc-panel-bg;\n                border-color: @bc-btn-border-focused @bc-btn-border-focused transparent @bc-btn-border-focused;\n                box-shadow: none;\n\n                .dark & {\n                    background-color: @dark-bc-panel-bg;\n                    border-color: @dark-bc-btn-border-focused @dark-bc-btn-border-focused transparent @dark-bc-btn-border-focused;\n                }\n            }\n\n            > li {\n                position: relative;  // for positioning .notification icon\n                .notification {\n                    display: none;  // hidden by default\n                    background-color: @bc-secondary-btn-bg;\n                    color: @bc-text-alt;\n                    border-radius: 16px;\n                    padding: 0 5px;\n                    position: absolute;\n                    right: 19px;\n                    top: 8px;\n\n                    .dark & {\n                        background-color: @dark-bc-secondary-btn-bg;\n                        color: @dark-bc-text-alt;\n                    }\n                }\n            }\n        }\n\n        /* Search box */\n        > :nth-child(2) {\n            @media (max-width: (@extension-manager-min-width - 1px)) {\n                display: flex;\n                overflow: hidden;\n                padding: 8px 1em;\n            }\n\n            @media (min-width: @extension-manager-min-width) {\n                position: absolute;\n                top: 15px;\n                right: 15px;\n            }\n        }\n\n        .search-container {\n            float: right;\n            .flex-item(1);\n        }\n\n        .search {\n            @media (max-width: (@extension-manager-min-width - 1px)) {\n                width: calc(~'100% - 27px - 20px'); // 100% minus padding etc.\n            }\n\n            background: @bc-input-bg url(\"images/topcoat-search-20.svg\") 2px 2px no-repeat;\n            margin: 0;\n            padding-left: 27px;\n            padding-right: 20px;\n\n            .dark & {\n                background: @dark-bc-input-bg url(\"images/topcoat-search-20.svg\") 2px 2px no-repeat;\n            }\n        }\n        .search-clear {\n            background: transparent;\n            position: relative;\n            display: block;\n            float: right;\n            font-size: 20px;\n            left: -6px;\n            line-height: 0;\n            margin: 6px 0 0 -20px;\n            opacity: 0.5;\n            padding: 0;\n            width: 16px;\n            height: 16px;\n            z-index: 1;\n            border: 0;\n\n            &:disabled {\n                opacity: 0.3;\n                cursor: default;\n            }\n        }\n        .search-clear:active {\n            opacity: 0.7;\n            &:disabled {\n                opacity: 0.3;\n            }\n        }\n        .sort-extensions {\n            float: left;\n            margin-right: 10px;\n            margin-bottom: 0;\n            width: auto;\n            padding-right: 18px;\n            border-bottom-left-radius: 0px;\n            border-top-left-radius: 0px;\n            border-color: #707070;\n            border-left: 0px;\n        }\n        .ext-sort-group {\n            float: left;\n        }\n        #sort-attributes-icon {\n            width: 15px;\n            height: 14px;\n            float:left;\n            padding: 6px;\n            border-bottom-left-radius: 3px;\n            border-top-left-radius: 3px;\n            border: 1px solid #707070;\n            box-shadow: inset 0 1px rgba(255, 255, 255, 0.12);\n            background: @bc-btn-bg url(\"images/sort-by-attributes.svg\") no-repeat right 5px center;\n            .dark & {\n                box-shadow: inset 0 1px rgba(255, 255, 255, 0.06);\n                background-color: @dark-bc-btn-bg;\n            }\n        }\n    }\n    .modal-body {\n        height: 400px;\n        overflow-y: scroll;\n        background-color: @bc-panel-bg;\n        padding: 0;\n\n        .dark & {\n            background-color: @dark-bc-panel-bg;\n        }\n\n        .empty-message {\n            position: absolute;\n            top: 50%;\n            width: 100%;\n            margin-top: -1em;\n            text-align: center;\n        }\n\n        .info-message {\n            background-color: @bc-panel-bg;\n            color: @bc-text-thin-quiet;\n            padding: 1em;\n\n            .dark & {\n                background-color: @dark-bc-panel-bg;\n                color: @dark-bc-text-quiet;\n            }\n        }\n\n        .spinner {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            margin-top: -18px;\n            margin-left: -18px;\n        }\n\n        .extension-list {\n            td {\n                height: 2em;\n            }\n            .ext-info {\n                padding-left: 15px;\n                width: 220px;\n            }\n            .ext-name {\n                color: @bc-text;\n                display: block;\n                font-size: 15px;\n                font-weight: normal;\n                .user-select(text);\n                cursor: text;\n\n                .dark & {\n                    color: @dark-bc-text;\n                }\n            }\n            .ext-desc {\n                width: auto;\n                color: @bc-text;\n                font-weight: normal;\n                .user-select(text);\n                cursor: text;\n\n                .dark & {\n                    color: @dark-bc-text;\n                }\n            }\n            .ext-translated,\n            .muted {\n                color: @bc-text-thin-quiet;\n\n                .dark & {\n                    color: @dark-bc-text-quiet;\n                }\n            }\n            .alert {\n                font-size: 11px;\n                margin: 0 0 10px;\n\n                .dark & {\n                    background: @dark-bc-warning-bg;\n                    border-radius: 2px;\n                    color: @dark-bc-warning-text;\n                }\n            }\n            .error {\n                font-weight: @font-weight-semibold;\n                color: @bc-error;\n\n                .dark & {\n                    color: @dark-bc-error;\n                }\n            }\n            .ext-version,\n            .ext-date,\n            .ext-author {\n                font-size: 11px;\n            }\n            .ext-author {\n                display: block;\n            }\n            .ext-action {\n                font-size: 12px;\n                padding-right: 15px;\n                text-align: right;\n                vertical-align: middle;\n                width: 150px;\n            }\n            .load-error {\n                display: inline-block;\n                margin-top: 240px;\n            }\n        }\n    }\n}\n\n/* About dialog */\n.about-dialog .modal-body {\n    // Simple two-column layout: image on left, text taking up remaining space on right\n    position: relative;\n    .about-icon {\n        position: absolute;\n        left: 19px;  // relative to border of modal-body (bounds outside padding)\n        top:  15px;\n        width: 100px;\n        height: 100px;\n    }\n    .about-text {\n        // Icon is 120px, so we need at least that much left padding/margin to avoid overlap\n        margin-left: 130px;\n        overflow: auto;\n\n        #about-build-number {\n            color: @bc-text-thin-quiet;\n\n            .dark & {\n                color: @dark-bc-text-thin-quiet;\n            }\n        }\n        .about-info {\n            max-height: 300px;\n            margin-right: 10px;\n        }\n        .about-contributors {\n            min-height: 100px;\n            padding-bottom: 13px;\n\n            a {\n                text-decoration: none;\n            }\n            img {\n                opacity: 0;\n                transition: opacity 1s;\n\n                .dark & {\n                    background-color: #f0f0f0; // same as GitHub's avatar background color.\n                }\n            }\n        }\n    }\n\n    h2 {\n        font-weight: normal;\n        font-size: 25px;\n        margin-bottom: -4px;\n        margin-top: 13px;\n    }\n    .dialog-message {\n        font-size: 14px;\n        line-height: 17px;\n\n        // Enable text selection\n        cursor: auto;\n        .user-select(text);\n    }\n}\n\n/* Input */\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n    background-color: @bc-input-bg;\n    border: 1px solid @bc-btn-border;\n    color: @bc-text-thin;\n    font-size: (@baseFontSize + 1px);\n    font-weight: normal;\n    -webkit-font-smoothing: antialiased;\n    box-shadow: inset 0 1px 0 @bc-shadow-small;\n    border-radius: @bc-border-radius;\n    .transition(~\"border linear 180ms, box-shadow linear 180ms\");\n\n    .dark & {\n        background-color: @dark-bc-input-bg;\n        border: 1px solid @dark-bc-btn-border;\n        color: @dark-bc-text-thin;\n        box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n    }\n\n    &::-webkit-input-placeholder {\n        color: @bc-text-thin-quiet;\n        font-weight: normal;\n        -webkit-font-smoothing: antialiased;\n\n        .dark & {\n            color: @dark-bc-text-thin-quiet;\n        }\n    }\n\n    &:focus {\n        outline: 0;\n        background-color: @bc-input-bg;\n        text-shadow: none;\n        border: 1px solid @bc-btn-border-focused;\n        box-shadow: inset 0 1px 0 @bc-shadow-small, 0 0 0 1px @bc-btn-border-focused-glow;\n\n        .dark & {\n            background-color: @dark-bc-input-bg;\n            border: 1px solid @dark-bc-btn-border-focused;\n            box-shadow: inset 0 1px 0 @dark-bc-shadow-small, 0 0 0 1px @dark-bc-btn-border-focused-glow;\n        }\n    }\n\n    &:disabled {\n        opacity: @bc-disabled-opacity;\n        cursor: default;\n\n        .dark & {\n            opacity: @dark-bc-disabled-opacity;\n        }\n    }\n}\n\n/* Twipsy tooltips */\n\n.tooltip {\n    &.in { opacity: 1; }\n}\n\n.tooltip-inner {\n    background: @bc-menu-bg;\n    box-shadow: 0 3px 9px @bc-shadow;\n    color: @bc-menu-text;\n    max-width: 220px;\n    text-align: left;\n\n    .dark & {\n        background: @dark-bc-menu-bg;\n        box-shadow: 0 3px 9px @dark-bc-shadow;\n        color: @dark-bc-menu-text;\n    }\n}\n\n.tooltip {\n    &.top .tooltip-arrow {\n        border-top-color: @bc-menu-bg;\n        left: 50%;\n\n        .dark & {\n            border-top-color: @dark-bc-menu-bg;\n        }\n    }\n    &.right .tooltip-arrow {\n        border-right-color: @bc-menu-bg;\n        top: 15px;\n\n        .dark & {\n            border-right-color: @dark-bc-menu-bg;\n        }\n    }\n    &.left .tooltip-arrow {\n        border-left-color: @bc-menu-bg;\n        top: 15px;\n\n        .dark & {\n            border-left-color: @dark-bc-menu-bg;\n        }\n    }\n    &.bottom .tooltip-arrow {\n        border-bottom-color: @bc-menu-bg;\n        left: 50%;\n\n        .dark & {\n            border-bottom-color: @dark-bc-menu-bg;\n        }\n    }\n}\n\n/* Buttons */\n\n// Base .btn styles\n\n.btn:hover,\n.btn:focus,\n.btn.disabled,\n.btn[disabled] {\n    background-color: @bc-btn-bg;\n    color: @bc-text;\n\n    .dark & {\n        background-color: @dark-bc-btn-bg;\n        color: @dark-bc-text;\n    }\n}\n\n.btn.primary:hover,\n.btn.primary:focus,\n.btn.primary.disabled,\n.btn.primary[disabled] {\n    background-color: @bc-primary-btn-bg;\n\n    .dark & {\n        background-color: @dark-bc-primary-btn-bg;\n    }\n}\n\n.btn {\n    // Button Base\n    background-image: none;\n\n    background-color: @bc-btn-bg;\n    color: @bc-text;\n    cursor: default;\n    font-size: (@baseFontSize + 1);\n    font-weight: @font-weight-semibold;\n    line-height: normal;\n    border: 1px solid @bc-btn-border;\n    border-radius: @bc-border-radius;\n    box-shadow: inset 0 1px @bc-highlight-hard;\n    -webkit-font-smoothing: antialiased;\n    text-shadow: none;\n    margin: 3px 0 3px 3px;\n\n    .dark & {\n        background-color: @dark-bc-btn-bg;\n        color: @dark-bc-text;\n        border: 1px solid @dark-bc-btn-border;\n        box-shadow: inset 0 1px @dark-bc-highlight;\n    }\n\n    &:hover {\n        background-color: @bc-btn-bg;\n        color: @bc-text;\n\n        .dark & {\n            background-color: @dark-bc-btn-bg;\n            color: @dark-bc-text;\n        }\n    }\n\n    // Focus state for keyboard and accessibility\n    &:focus {\n        border: 1px solid @bc-btn-border-focused;\n        box-shadow: inset 0 1px 0 @bc-highlight, 0 0 0 1px @bc-btn-border-focused-glow;\n        color: @bc-text;\n        outline: none;\n\n        .dark & {\n            border: 1px solid @dark-bc-btn-border-focused;\n            box-shadow: inset 0 1px 0 @dark-bc-highlight, 0 0 0 1px @dark-bc-btn-border-focused-glow;\n            color: @dark-bc-text;\n        }\n    }\n\n    // Active and Disabled states\n    &.active:active {\n        background-color: @bc-bg-highlight !important;\n\n        .dark & {\n            background-color:@dark-bc-bg-highlight !important;\n        }\n    }\n\n    &.active:not([disabled]) {\n        background-image: none;\n        background-color: @bc-bg-highlight;\n        box-shadow: inset 0 1px 0 @bc-shadow-small;\n        color: @bc-text-alt;\n\n        .dark & {\n            background-color:@dark-bc-bg-highlight;\n            box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n            color: @dark-bc-text-alt;\n        }\n    }\n\n    &:active:not([disabled]) {\n        background-image: none;\n        background-color: @bc-btn-bg-down;\n        box-shadow: inset 0 1px 0 @bc-shadow-small;\n        color: @bc-text;\n\n        .dark & {\n            background-color: @dark-bc-btn-bg-down;\n            box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n            color: @dark-bc-text;\n        }\n    }\n\n    &.disabled, &[disabled] {\n        opacity: @bc-disabled-opacity;\n\n        .dark & {\n            opacity: @dark-bc-disabled-opacity;\n        }\n    }\n\n    // Primary Button Type\n    &.primary {\n        background-image: none;\n        background-color: @bc-primary-btn-bg;\n        border: 1px solid  @bc-primary-btn-border;\n        box-shadow: inset 0 1px 0 @bc-highlight;\n        color: @bc-text-alt;\n        text-shadow: none;\n\n        .dark & {\n            background-color: @dark-bc-primary-btn-bg;\n            border: 1px solid  @dark-bc-primary-btn-border;\n            box-shadow: inset 0 1px 0 @dark-bc-highlight;\n            color: @dark-bc-text-alt\n        }\n\n        &.active,\n        &:active {\n            background-image: none;\n            background-color: @bc-primary-btn-bg-down;\n            box-shadow: inset 0 1px 0 @bc-shadow-small;\n            color: @bc-text-alt;\n\n            .dark & {\n                background-color: @dark-bc-primary-btn-bg-down;\n                box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n                color: @dark-bc-text-alt;\n            }\n        }\n\n        &:focus {\n            border: 1px solid @bc-primary-btn-border;\n            box-shadow: inset 0 1px 0 @bc-highlight, 0 0 0 1px @bc-btn-border-focused-glow;\n            outline: none;\n\n            .dark & {\n                border: 1px solid @dark-bc-primary-btn-border;\n                box-shadow: inset 0 1px 0 @dark-bc-highlight, 0 0 0 1px @dark-bc-btn-border-focused-glow;\n            }\n        }\n    }\n\n    // Update Button Type\n    &.update {\n        background-color: @bc-secondary-btn-bg;\n        border-color: @bc-secondary-btn-border;\n        box-shadow: inset 0 1px 0 @bc-highlight;\n        color: @bc-text-alt;\n        font-weight: @font-weight-semibold;\n        text-shadow: 0 -1px 0 @bc-shadow-small;\n\n        .dark & {\n            background-color: @dark-bc-secondary-btn-bg;\n            border-color: @dark-bc-secondary-btn-border;\n            box-shadow: inset 0 1px 0 @dark-bc-highlight;\n            color: @dark-bc-text-alt;\n            text-shadow: 0 -1px 0 @dark-bc-shadow-small;\n        }\n\n        &:active {\n            background-color: @bc-secondary-btn-bg-down;\n            border-color: @bc-secondary-btn-border;\n            box-shadow: inset 0 1px 0 @bc-shadow-small;\n            color: @bc-text-alt;\n\n            .dark & {\n                background-color: @dark-bc-secondary-btn-bg-down;\n                border-color: @dark-bc-secondary-btn-border;\n                box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n                color: @dark-bc-text-alt\n            }\n        }\n    }\n\n    // Button Sizes\n    &.large {\n        font-size: (@baseFontSize + 1px);\n        border-radius: @bc-border-radius;\n    }\n    &.small {\n        font-size: (@baseFontSize - 1px);\n    }\n}\n\n.btn-alt-quiet {    // No dark style required because these reside in the sidebar.\n    border: 1px solid transparent;\n    border-radius: @bc-border-radius;\n    text-decoration: none;\n\n    &:hover {\n        border: 1px solid @bc-shadow;\n        box-shadow: inset 0 1px 0 @bc-highlight;\n    }\n    &:active {\n        background-color: @bc-btn-bg-down-alt;\n        border: 1px solid @bc-shadow;\n        box-shadow: inset 0 1px 0 @bc-shadow-small;\n    }\n}\n\n.btn-mini {\n    padding: 2px 6px;\n    font-size: 11px;\n    font-weight: normal;\n    line-height: 14px;\n    &:focus {\n        border: 1px solid @bc-btn-border-focused;\n        box-shadow: 0 0 0 1px @bc-btn-border-focused-glow;\n        outline: none;\n\n        .dark & {\n            border: 1px solid @dark-bc-btn-border-focused;\n            box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow;\n        }\n    }\n}\n\n\n/* Tables */\n\n.table, table {\n    th {\n        font-weight: @font-weight-semibold;\n    }\n    td {\n        border-top: 1px solid transparent;\n    }\n    tbody th {\n        border-top: 1px solid transparent;\n    }\n    .right {\n        text-align: right;\n    }\n}\n\n.table-striped tbody {\n    tr:nth-child(odd) td,\n    tr:nth-child(odd) th {\n        background-color: @bc-panel-bg-alt;\n\n        .dark & {\n            background-color: @dark-bc-panel-bg-alt;\n        }\n    }\n    tr:nth-child(even) td,\n    tr:nth-child(even) th {\n        background-color: @bc-panel-bg; // turn off bootstrap hover highlight\n\n        .dark & {\n            background-color: @dark-bc-panel-bg;\n        }\n    }\n}\n.row-highlight tbody {\n    tr:hover td,\n    tr:hover th {\n        background-color: @bc-bg-highlight;\n        color: @bc-menu-text;\n\n        .dark & {\n            background-color: @dark-bc-bg-highlight;\n            color: @dark-bc-menu-text;\n        }\n    }\n}\n\n/* Emphasis */\n\nstrong {\n    font-weight: @font-weight-semibold;\n}\n\n/* Type */\n\ncode {\n    color: @bc-text;\n    background-color: transparent;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\nlabel {\n    font-size: @label-font-size;\n}\n\nlabel.inline {\n    display: inline;\n}\n\n/* Overriding Bootstrap's bold properties */\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nb,\nstrong,\ndt,\n.label {\n    color: @bc-text;\n    font-weight: @font-weight-semibold;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\n.alert-message a,\n.form-stacked label {\n    font-weight: @font-weight-semibold;\n}\n\n.alert {\n    text-shadow: none;\n    background-color: @bc-warning-bg;\n    border: none;\n\n    .dark & {\n        color: @dark-bc-warning-bg;\n    }\n}\n.alert h4 {\n    // Specified for the h4 to prevent conflicts of changing @headingsColor\n    color: @bc-warning-bg;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n    margin: 0 5px 0 0;\n}\n\ninput[type=\"checkbox\"] {\n    height: 13px;\n    width: 13px;\n    vertical-align: middle;\n    border: 1px solid @bc-btn-border;\n    border-radius: @bc-border-radius;\n    background-color: @bc-btn-bg;\n    -webkit-appearance: none;\n    box-shadow: inset 0 1px 0 @bc-highlight;\n\n    .dark & {\n        border: 1px solid @dark-bc-btn-border;\n        background-color: @dark-bc-btn-bg;\n        box-shadow: inset 0 1px 0 @dark-bc-highlight;\n    }\n}\n\ninput[type=\"checkbox\"]:active:not(:disabled) {\n    background-color: @bc-btn-bg-down;\n    box-shadow: inset 0 1px 0 @bc-shadow-small;\n\n    .dark & {\n        background-color: @dark-bc-btn-bg-down;\n        box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n    }\n}\n\nselect:focus,\ninput[type=\"checkbox\"]:focus {\n    outline:none;\n    border: 1px solid @bc-btn-border-focused;\n    box-shadow: 0 0 0 1px @bc-btn-border-focused-glow;\n\n    .dark & {\n        border: 1px solid @dark-bc-btn-border-focused;\n        box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow;\n    }\n}\n\nselect {\n    background: @bc-btn-bg url(\"images/select-triangles.svg\") no-repeat right 7px center;\n    border: 1px solid @bc-btn-border;\n    border-radius: @bc-border-radius;\n    box-shadow: inset 0 1px @bc-highlight;\n    color: @bc-text;\n    line-height: 1.3;\n    position: relative;\n    -webkit-appearance: none;\n\n    &:active {\n        background-color: @bc-btn-bg-down;\n        box-shadow: inset 0 1px 0 @bc-shadow-small;\n\n        .dark & {\n            background-color: @dark-bc-btn-bg-down;\n            box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n        }\n    }\n\n    > option { // Windows (but not Mac) lets you style the dropdown items\n        background-color: @bc-menu-bg;\n        color: @bc-menu-text;\n\n        .dark & {\n            background: @dark-bc-menu-bg;\n            color: @dark-bc-menu-text;\n        }\n    }\n\n    .dark & {\n        background-color: @dark-bc-btn-bg;\n        border: 1px solid @dark-bc-btn-border;\n        box-shadow: inset 0 1px @dark-bc-highlight;\n        color: @dark-bc-text;\n    }\n}\n\ninput[type=\"checkbox\"]:checked:before {\n    font-weight: bold;\n    color: @bc-text;\n    content: '\\2713';\n    -webkit-margin-start: 0;\n    position: relative;\n    left: 2px;\n    top: -7px;\n    font-size: 16px;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\ncode {\n    border: none;\n}\n\n\n.close {\n    color: @bc-text;\n    text-shadow: none;\n    opacity: 0.7;\n    filter: alpha(opacity=70);\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\n.close:hover {\n    color: @bc-text;\n    opacity: 1;\n    filter: alpha(opacity=100);\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n}\n\n.dropdown-menu {\n    background-color: @bc-menu-bg;\n    color: @bc-menu-text;\n\n    .dark & {\n        background-color: @dark-bc-menu-bg;\n        color: @dark-bc-menu-text;\n    }\n\n    .divider {\n        background-color: @bc-menu-separator;\n        border: none;\n\n        .dark & {\n            background-color: @dark-bc-menu-separator;\n        }\n    }\n}\n\n.form-horizontal {\n    .controls {\n        margin-left: 170px;\n\n        input[type='checkbox'] {\n             margin-top: 8px;\n        }\n     }\n }\n"
  },
  {
    "path": "src/styles/brackets_scrollbars.less",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n /* Temporary fix for issue#10150 for weird project tree scrollbar behaviour on mac. Scrollbar not appearing on hover. Forcing the project tree div to render displays the scrollbar. So setting transparent background color of div on hover.\n*/\n\n.platform-mac\n{\n    .open-files-container:hover,\n    #project-files-container:hover {\n        background-color: rgba(128, 128, 128, 0);\n    }\n}\n\n/* Temporary implementation of unobtrusive scrollbars.\n   FUTURE: These currently rely on nonstandard WebKit styles, and don't have all the right behavior.\n   Longer-term, we'll need to implement custom scrollbars. */\n\n.platform-mac .quiet-scrollbars,\n.platform-win .quiet-scrollbars,\n.platform-linux .quiet-scrollbars,\n.dark.platform-mac .quiet-scrollbars,\n.dark.platform-win .quiet-scrollbars,\n.dark.platform-linux .quiet-scrollbars {\n\n    ::-webkit-scrollbar {\n        width: 9px;\n        height: 9px;\n        background-color: transparent;\n    }\n\n    ::-webkit-scrollbar-corner {\n        background-color: transparent;\n    }\n\n    ::-webkit-scrollbar-thumb {\n        box-shadow: none;\n        border: none;\n    }\n\n    /* This looks like a dupe, but without it the thumb doesn't fade in\n     * properly, probably due to flakiness in how these styles are handled\n     * in the build of WebKit that's in CEF.\n     */\n    ::-webkit-scrollbar-corner {\n        background-color: transparent;\n    }\n\n    .dragging ::-webkit-scrollbar-thumb,\n    :hover::-webkit-scrollbar-thumb,\n    :focus::-webkit-scrollbar-thumb {\n        border-radius: 999px;\n        box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.6) inset;\n        border: 2px solid transparent;\n    }\n\n    .dragging ::-webkit-scrollbar-thumb,\n    :hover::-webkit-scrollbar-thumb:vertical,\n    :focus::-webkit-scrollbar-thumb:vertical {\n        min-height: 20px;\n    }\n\n    .dragging :-webkit-scrollbar-thumb,\n    :hover::-webkit-scrollbar-thumb:horizontal,\n    :focus::-webkit-scrollbar-thumb:horizontal {\n        min-width: 20px;\n    }\n}\n\n.platform-linux {\n    // Note: when changing padding/margins, may need to adjust metrics in ScrollTrackMarkers.js\n    \n    ::-webkit-scrollbar {\n        width: 12px;\n        height: 12px;\n    }\n\n    ::-webkit-scrollbar-track:vertical {\n        margin: 0 0 8px 0;\n    }\n\n    ::-webkit-scrollbar-track:horizontal {\n        margin: 0 8px 0 0;\n    }\n\n    ::-webkit-scrollbar-thumb {\n        border-radius: 999px;\n        box-shadow: 0 0 0 4px @linux-scrollbar-thumb inset;\n        border: 2px solid transparent;\n    }\n\n    ::-webkit-scrollbar-corner {\n        background: none;\n    }\n\n    ::-webkit-scrollbar-thumb:window-inactive {\n        box-shadow: 0 0 0 5px @linux-scrollbar-thumb-inactive inset;\n    }\n}\n\n.platform-win {\n    // Note: when changing padding/margins, may need to adjust metrics in ScrollTrackMarkers.js\n    \n    ::-webkit-scrollbar {\n        width: 12px;\n        height: 12px;\n        background-color: @win-scrollbar-track;\n    }\n    \n    ::-webkit-scrollbar-thumb {\n        box-shadow: 0 0 0 12px @win-scrollbar-thumb inset;\n    }\n\n    .dragging ::-webkit-scrollbar-thumb,\n    ::-webkit-scrollbar-thumb:hover,\n    ::-webkit-scrollbar-thumb:focus {\n        box-shadow: 0 0 0 12px @win-scrollbar-thumb-hover inset;\n    }\n    ::-webkit-scrollbar-thumb:active {\n        box-shadow: 0 0 0 12px @win-scrollbar-thumb-active inset;\n    }\n    \n    ::-webkit-scrollbar-thumb:vertical {\n        min-height: 20px;\n    }\n    ::-webkit-scrollbar-thumb:horizontal {\n        min-width: 20px;\n    }\n    \n    ::-webkit-scrollbar-corner {\n        background: none;\n    }\n}\n\n\n// Dark Scrollbars\n\n.dark {\n    /* Custom scrollbar colors */\n    &.platform-win {\n        .CodeMirror-scrollbar-filler,\n        .CodeMirror-gutter-filler {\n            background-color: rgb(15, 15, 15);\n        }\n\n        // Note: when changing padding/margins, may need to adjust metrics in ScrollTrackMarkers.js\n\n        ::-webkit-scrollbar {\n            background-color: rgb(15, 15, 15);\n        }\n\n        ::-webkit-scrollbar-thumb {\n            box-shadow: 0 0 0 12px rgb(49, 49, 49) inset;\n        }\n        ::-webkit-scrollbar-thumb:hover,\n        ::-webkit-scrollbar-thumb:focus {\n            box-shadow: 0 0 0 12px rgb(89, 89, 89) inset;\n        }\n        ::-webkit-scrollbar-thumb:active {\n            box-shadow: 0 0 0 12px rgb(169, 169, 169) inset;\n        }\n    }\n\n    &.platform-linux {\n        .CodeMirror-scrollbar-filler,\n        .CodeMirror-gutter-filler {\n            background-color: #1d1f21;\n        }\n\n        ::-webkit-scrollbar-thumb {\n            box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.24) inset;\n        }\n\n        ::-webkit-scrollbar-thumb:window-inactive {\n            box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.12) inset;\n        }\n    }\n}\n"
  },
  {
    "path": "src/styles/brackets_shared.less",
    "content": "\n// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n\n/* Shared LESS for all versions of Brackets (e.g. App, In-Browser, etc.)\n *\n * IMPORTANT: Importing this file should be the first step in creating a\n * version-specific LESS file.\n *\n * ALSO IMPORTANT: All CSS imports should occur first in this file. This is\n * because LESS puts all CSS imports at the top of the file anyway (because\n * this is required by CSS2). So, we don't want to be misleading about the\n * processing order.\n */\n\n/* LESS imports */\n\n// Bootstrap @ v.2.3.1\n@import url(\"bootstrap/bootstrap.less\");\n\n// Brackets-specific variables, mixins and overrides\n@import url(\"brackets_variables.less\");\n@import url(\"brackets_mixins.less\");\n@import url(\"brackets_patterns_override.less\");\n\n// Brackets-specific default font\n@import url(\"brackets_fonts.less\");\n\n// Default theme -- all UI styling comes from variables in a theme\n// Themes can rely on variables defined above\n@import url(\"brackets_theme_default.less\");\n@import url(\"brackets_core_ui_variables.less\");\n\n// Codemirror styling overrides\n@import url(\"brackets_codemirror_override.less\");\n\n// Styling for file tree\n@import url(\"jsTreeTheme.less\");\n\n// Styling for scrollbars\n@import url(\"brackets_scrollbars.less\");\n\n@import url(\"infobar-styles.less\");\n"
  },
  {
    "path": "src/styles/brackets_theme_default.less",
    "content": "\n// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n\n/*\n * Brackets Default Theme\n *\n * Defines all the variables that one can configure in a theme. This should\n * contain all variables / mixins for UI styling that we want to be able to\n * change in a theme.\n *\n * Throughout the rest of the LESS files we should _only_ use color\n * variable names that are on the LHS of the list below. So, if we\n * need a new color for some UI element, we should add a variable\n * in this file.\n */\n\n/* Overall Colors */\n\n/*\n * Background colors are ordered from least \"intense\" to most \"intense\"\n * So, if the background is light, then @background-color-3 should be\n * lightest, -2 should be darker, and -1 should be darker still.\n *\n * The opposite is true for a dark background -- background-color-3 should be\n * the darkest, -2 should be lighter, and -1 should be lighter still.\n */\n\n@background: #f8f8f8;\n@foreground: #535353;\n\n/* Code Styling */\n\n/* code accent colors */\n@accent-keyword: #446fbd;\n@accent-atom: #e88501;\n@accent-number: #6d8600;\n@accent-def: #8757ad;\n@accent-variable: #535353;\n@accent-variable-2: #535353;\n@accent-variable-3: #535353;\n@accent-property: #8757ad;\n@accent-operator: #535353;\n@accent-comment: #949494;\n@accent-string: #e88501;\n@accent-string-2: #e88501;\n@accent-meta: #535353;\n@accent-error: #dc322f;\n@accent-qualifier: #446fbd;\n@accent-builtin: #446fbd;\n@accent-bracket: #222;\n@accent-tag: #446fbd;\n@accent-attribute: #6d8600;\n@accent-header: #d33682;\n@accent-quote: #446fbd;\n@accent-hr: #e88501;\n@accent-link: #8757ad;\n@accent-rangeinfo: #6c71c4;\n@accent-minus: #dc322f;\n@accent-plus: #859900;\n@match-text: #121212;\n@cm-match-highlight: #f5ee92;\n@cm-current-match-highlight: #f7c44e;\n\n/* code highlight */\n@matching-bracket: #cfead6;\n\n/* sidebar/toolbar colors */\n@project-panel-base-color: #47484B;\n@project-panel-text-1: #ffffff;\n@project-panel-text-2: #adb9bd;\n@main-toolbar-background-color: #5D5F60;\n\n/* open working file highlight */\n@open-working-file-name-highlight: #8fddff;\n@open-working-file-ext-highlight: #8fddff;\n\n/* selection colors */\n@selection-color-focused: #abdffa;\n@selection-color-unfocused: #d5dee3;\n\n/* background color of the line that has the cursor */\n@activeline-bg: #ebefef;\n@activeline-number: #000;\n@activeline-number-bg: #dee5e6;\n@activeline-number-bg-inline: #d7dede;\n\n/* custom scrollbar colors */\n@win-scrollbar-track: rgb(240, 240, 240);\n@win-scrollbar-thumb: rgb(206, 206, 206);\n@win-scrollbar-thumb-hover: rgb(166, 166, 166);\n@win-scrollbar-thumb-active: rgb(96, 96, 96);\n\n@linux-scrollbar-thumb: rgba(0, 0, 0, 0.24);\n@linux-scrollbar-thumb-inactive: rgba(0, 0, 0, 0.12);\n\n/* live preview */\n@live-preview-sync-error-background: #ff5d99;\n@live-preview-sync-error-color: #fff;\n\n/* Code font formatting\n *\n * NOTE (JRB): In order to get the web font to load early enough, we have a div called \"dummy-text\" that\n * is styled with .code-font().\n *\n * The platform-specific selector gets added to the body tag *before* document ready time.\n * We rely on this behavior to load platform-specific web fonts early.\n */\n.code-font() {\n    color: @foreground;\n    line-height: 1.25;\n\n    .dark & {\n        color: @dark-bc-text;\n    }\n\n    font-family: @sourceFontFamily-Medium;\n}\n\n.code-font-win() {\n}\n\n.code-font-mac() {\n}\n\n.code-cursor() {\n    // to make a block cursor, use something like this:\n    // background-color: fadeout(@blue, 50%);\n    // border: none !important;\n\n    // to make an I-cursor, use something like this:\n    border-left: 1px solid black;\n\n}\n\n/* Dark theme styling\n * \n * These are overrides to make the UI look better when the editor theme is dark.\n * Eventually, these will likely be replaced by full-featured UI themes.\n */\n\n.dark {\n    .inline-widget {\n        color: @dark-bc-text;\n        background-color: @dark-bc-bg-inline-widget;\n        border-top: 1px solid rgba(255, 255, 255, 0.1);\n        border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n\n        .inline-editor-header {\n            .filename {\n                color: #fff;\n\n                .dirty-indicator {\n                    color: #aaa;\n                }\n\n                .line-number {\n                    color: #bbb;\n                }\n            }\n        }\n\n        .btn {\n            background-color: @dark-bc-btn-bg;\n            color: @dark-bc-text;\n            border: 1px solid @dark-bc-btn-border;\n            box-shadow: inset 0 1px 0 @dark-bc-highlight;\n\n            &:hover {\n                background-color: @dark-bc-btn-bg;\n                color: @dark-bc-text;\n            }\n\n            &:focus {\n                border: 1px solid @dark-bc-btn-border-focused;\n                box-shadow: inset 0 1px 0 @dark-bc-highlight, 0 0 0 1px @dark-bc-btn-border-focused-glow;\n                color: @dark-bc-text;\n            }\n\n            &:active:not([disabled]) {\n                background-color: @dark-bc-btn-bg-down;\n                box-shadow: inset 0 1px 0 @dark-bc-shadow-small;\n                color: @dark-bc-text;\n            }\n        }\n\n        .close {\n            color: @dark-bc-text;\n        }\n            \n        .CodeMirror-scroll {\n            .CodeMirror-linenumbers {\n                background-color: @dark-bc-bg-inline-widget;\n            }\n        }            \n        \n    }\n\n    #editor-holder .inline-widget .CodeMirror, #editor-holder .inline-widget .CodeMirror-gutters {\n        background: transparent;\n    }\n\n    .related-container {\n        background: @dark-bc-panel-bg;\n\n        .selection {\n            background: @dark-bc-panel-bg-selected;\n        }\n\n        .selection:before {\n            border-left: @inline-triangle-size solid @dark-bc-bg-inline-widget;\n        }\n\n        .related {\n            li {\n                color: @dark-bc-text-alt;\n\n                .related-file {\n                    color: @dark-bc-text-thin-quiet;\n                }\n            }\n\n            .selected {\n                color: @dark-bc-text-alt;\n            }\n        }\n\n        .inline-editor-message {\n            color: @dark-bc-text-thin-quiet;\n        }\n    }\n}\n\n/* Variables and Mixins for non-code UI elements that can be styled */\n\n"
  },
  {
    "path": "src/styles/brackets_variables.less",
    "content": "// Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n\n/* Brackets Variables */\n\n/* All paddings, gutters, etc. should be multiples of this */\n@base-padding: 10px;\n\n/* Common font sizes */\n@title-font-size: 18px;  // headings such as the editor titlebar\n@label-font-size: 14px;  // labels on buttons, menubar, etc.\n@menu-item-font-size: 13px; // individual menu items\n\n/* CSS triangles */\n@inline-triangle-size: 9px;\n\n/* Main layout */\n@sidebar-width: 200px;  // user resizable, however\n@main-toolbar-width: 30px;\n\n/* Extension Manager */\n@extension-manager-min-width: 760px; // Used for responsive styling\n\n/* z-index */\n@z-index-cm-dialog-override: 11;\n@z-index-cm-dialog: 15;\n@z-index-cm-max: @z-index-cm-dialog;\n\n@z-index-brackets-ui: (@z-index-cm-max + 1);\n@z-index-brackets-results-panel: @z-index-brackets-ui;\n@z-index-brackets-selection-extension: (@z-index-brackets-ui + 1);\n@z-index-brackets-scroller-shadow: (@z-index-brackets-selection-extension + 1);\n@z-index-brackets-inline-editor-shadow: @z-index-brackets-ui;\n@z-index-brackets-toolbar: (@z-index-brackets-ui + 1);\n@z-index-brackets-max: @z-index-brackets-toolbar;\n@z-index-brackets-modalbar: (@z-index-brackets-toolbar - 1);\n@z-index-brackets-main-toolbar: (@z-index-brackets-toolbar + 1);\n\n@z-index-brackets-sidebar-resizer: (@z-index-brackets-ui + 2);\n@z-index-brackets-resizer-div: (@z-index-brackets-sidebar-resizer + 1);\n@z-index-brackets-panel-resizer: (@z-index-brackets-ui + 2);\n\n@z-index-brackets-drag-ghost:            999;\n@z-index-brackets-context-menu-base:    1000;\n@z-index-brackets-stylesheet-menu:      1000;\n@z-index-brackets-inline-editor-error:  1000;\n"
  },
  {
    "path": "src/styles/infobar-styles.less",
    "content": "/*\n * Copyright (c) 2019 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*info Bar*/\n#info-bar-template {\n    display: block;\n    background-color: #105F9C;\n    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.53);\n    height: 38px;\n    width: 100%;\n    position: absolute;\n    z-index: 15;\n    left: 0px;\n    bottom: 25px;\n    outline: none;\n\toverflow: hidden;\n}\n\n#info-bar-template #icon-container {\n    width: auto;\n    height: auto;\n    padding: 11px;\n    float: left;\n}\n#info-bar-template #icon-container #info-icon {\n    background: url(\"images/infobar-info.svg\") no-repeat 0 0;\n    width: 16px;\n    height: 16px;\n    display: block;\n}\n\n#info-bar-template #content-container {\n    padding: 10px 7px;\n    float: left;\n    max-width: 78%;\n}\n\n#info-bar-template #content-container #info-content {\n    margin: 0px !important; /*Check if this important is necessary*/\n    line-height: 18px;\n    font-size: 14px;\n    font-family: 'SourceSansPro';\n    color: #FFFFFF;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n#info-bar-template #content-container #info-content #heading{\n    font-weight: bold;\n}\n/*For focussed link of brackets.io*/\n#info-bar-template #content-container #info-content #description a:focus{\n    box-shadow: none;\n}\n\n#info-bar-template #content-container #info-content #description a{\n    text-decoration: underline;\n\tcolor: #FFFFFF;\n}\n\n#info-bar-template #close-icon-container {\n    height: auto;\n    padding: 9px;\n    position: fixed;\n    float: right;\n    text-align: center;\n    width: auto;\n\tmin-width: 66px;\n\tright: 30px;\n\tbackground-color: #105F9C;\n}\n\n#info-bar-template #close-icon-container #close-icon {\n    display: block;\n    color: white;\n    font-size: 18px;\n    line-height: 18px;\n    text-decoration: none;\n    width: 18px;\n    height: 18px;\n    background-color: transparent;\n    border: none;\n    padding: 0px; /*This is needed to center the icon*/\n\tfloat: right;\n}\n\n#info-bar-template #close-icon-container #close-icon:hover {\n    background-color: rgba(255, 255, 255 ,0.16);\n    border-radius: 50%;    \n}\n\n#info-bar-template #close-icon-container #close-icon:focus {\n    background-color: rgba(255, 255, 255 ,0.16);\n    border-radius: 50%;\n    border: 1px solid #C3E3FF;\n    outline: 0;\n}\n\n#info-bar-template #close-icon-container #close-icon:focus:active {\n    background-color: rgba(255, 255, 255 ,0.32);  \n    border: none;\n}\n\n/*Warning Message in info Bar*/\n#info-bar-template.warning, #info-bar-template.warning #close-icon-container {\n    background-color: #DA7A12;\n}\n\n.dark #info-bar-template.warning, .dark #info-bar-template.warning #close-icon-container {\n    background-color: #E6851A;\n}\n\n#info-bar-template.warning #icon-container #info-icon,\n#info-bar-template.error #icon-container #info-icon {\n    background: url(\"images/infobar-alert.svg\") no-repeat 0 0;\n}\n\n/*Error message in info Bar*/\n#info-bar-template.error, #info-bar-template.error #close-icon-container {\n    background-color: #D7373F;\n}\n\n.dark #info-bar-template.error, .dark #info-bar-template.error #close-icon-container{\n    background-color: #E4484F;\n}\n/*Success message in info Bar*/\n#info-bar-template.success, #info-bar-template.success #close-icon-container {\n    background-color: #278E6B;\n}\n\n.dark #info-bar-template.success, .dark #info-bar-template.success #close-icon-container {\n    background-color: #2E9D77;\n}\n\n#info-bar-template.success #icon-container #info-icon{\n    background: url(\"images/infobar-checkmarkcircle.svg\") no-repeat 0 0;\n}\n"
  },
  {
    "path": "src/styles/jsTreeTheme.less",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n\n/* Styles for jsTree control */\n/* (these are based on jsTree's default theme .css file, so they are not very LESS-like) */\n@li-min-height: 23px;\n\n.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; z-index:1; }\n.jstree li { display:block; min-height:@li-min-height; line-height:16px; white-space:nowrap; min-width:18px; }\n.jstree-rtl li { margin-left:0; margin-right:18px; }\n.jstree > ul > li { margin-left:0; }\n.jstree-rtl > ul > li { margin-right:0; }\n.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; }\n.jstree a:focus { outline: none; box-shadow: none; color: @project-panel-text-1; }\n.jstree a > ins { height:16px; width:16px; }\n.jstree a > .jstree-icon { margin-right:3px; }\n.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; }\nli.jstree-open > ul { display:block; }\nli.jstree-closed > ul { display:none; }\n\n.jstree-brackets li,\n.jstree-brackets ins { background-image:url(\"images/jsTreeSprites.svg\"); background-repeat:no-repeat; background-color:transparent; }\n.jstree-brackets li { background-position:-90px 0; background-repeat:repeat-y; }\n.jstree-brackets li.jstree-last { background:transparent; }\n.jstree-brackets .jstree-open > ins { background-position:-72px 0; }\n.jstree-brackets .jstree-closed > ins { background-position:-54px 0; }\n.jstree-brackets .jstree-leaf > ins { background-position:-36px 0; }\n\n.jstree-brackets li a:hover {\n    text-decoration: none;\n}\n\n.jstree-draggedOver {\n    background-color: @bc-sidebar-selection !important;\n}\n\n.jstree-dragImage {\n    position: absolute;\n    background-color: #66676B;\n    padding: 4px 8px 3px 8px;\n    color: #fff;\n}\n\n@jstree-icon-backindent: 12px;\n\n/* Make the links in the JS tree the width of the container\n * by shifting the off the screen by negative margin and moving the\n * content back by pushing the padding. The icons are positioned absolute\n * relative to the containing list item so they sit above the a's background.\n * This also means we need to include the size of the sprite in the padding\n * so the text ends up back in the same spot visually\n */\n.jstree-brackets li > a {\n    @jstree-icon-text-overlap: 2px;\n    padding-left: (@jstree-sprite-size - @jstree-icon-backindent - @jstree-icon-text-overlap);\n    display: block;\n}\n\n.jstree li {\n    position: relative;\n}\n\n.jstree-brackets li {\n    vertical-align: baseline;\n    a,\n    a:hover {\n        color: @project-panel-text-1;\n        font-size: 13px;\n        cursor: default;\n\n        &.jstree-clicked, &.jstree-clicked .extension {\n            color: @open-working-file-name-highlight;\n        }\n    }\n    .extension {\n        color: @project-panel-text-2;\n    }\n    &.jstree-closed, &.jstree-open {\n        > a {\n            color: @project-panel-text-2;\n        }\n    }\n}\n\n.jstree ins {\n    position: absolute;\n}\nins.jstree-icon {\n    left: -@jstree-icon-backindent !important;\n}\n\n.jstree-brackets a .jstree-icon { background-position:-56px -19px; }\n.jstree-brackets a.jstree-loading .jstree-icon { background:url(\"images/throbber.gif\") center center no-repeat !important; }\n\n.jstree-brackets li > a {\n    padding-top: 3px;\n    padding-bottom: 3px;\n}\n.jstree-brackets li > ins {\n    margin-top: 2px;\n    margin-bottom: 2px;\n}\n\n// These styles control the expand/collapse arrow icons. Most other styles in this file with background-position are unused.\n.jstree-brackets .jstree-no-dots li,\n.jstree-brackets .jstree-no-dots .jstree-leaf > ins { background:transparent; }\n.jstree-brackets .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }\n.jstree-brackets .jstree-no-dots .jstree-closed > ins { background-position:0 0; }\n\n.jstree-brackets .jstree-no-icons a .jstree-icon { display:none; }\n\n.jstree-brackets .jstree-search { font-style:italic; }\n\n.jstree-brackets .jstree-no-icons .jstree-checkbox { display:inline-block; }\n.jstree-brackets .jstree-no-checkboxes .jstree-checkbox { display:none !important; }\n.jstree-brackets .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }\n.jstree-brackets .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }\n.jstree-brackets .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }\n.jstree-brackets .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; }\n.jstree-brackets .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }\n.jstree-brackets .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }\n\n#vakata-dragged.jstree-brackets ins { background:transparent !important; }\n#vakata-dragged.jstree-brackets .jstree-ok { background:url(\"images/jsTreeSprites.svg\") -2px -53px no-repeat !important; }\n#vakata-dragged.jstree-brackets .jstree-invalid { background:url(\"images/jsTreeSprites.svg\") -18px -53px no-repeat !important; }\n#jstree-marker.jstree-brackets { background:url(\"images/jsTreeSprites.svg\") -41px -57px no-repeat !important; text-indent:-100px; }\n\n.jstree-brackets a.jstree-search { color:aqua; }\n.jstree-brackets .jstree-locked a { color:silver; cursor:default; }\n\n#project-files-container .jstree-brackets .jstree-rename-input {\n    background: #000;\n    border: 1px solid #000;\n    border-radius: 2px;\n    box-shadow: @bc-shadow-small;\n    box-sizing: border-box;\n    color: #fff;\n    font-style: normal;\n    font-weight: 400;\n    font-size: 13px;\n    left: 3px !important;\n    top: 2px !important;\n    margin: 0;\n    margin-bottom: 5px; /* It should instead be applyed only to folders */\n    padding: 0;\n    position: relative;\n    width: 150px;\n    height: 17px;\n    line-height: 17px;\n}\n\n#project-files-container .jstree-brackets .jstree-rename-input:focus {\n    border: 1px solid @bc-btn-border-focused;\n    box-shadow: none;\n    outline: none;\n}\n\n#vakata-contextmenu.jstree-brackets-context,\n#vakata-contextmenu.jstree-brackets-context li ul { background:#f0f0f0; border:1px solid #979797; box-shadow: 1px 1px 2px #999; }\n#vakata-contextmenu.jstree-brackets-context li { }\n#vakata-contextmenu.jstree-brackets-context a { color:black; }\n#vakata-contextmenu.jstree-brackets-context a:hover,\n#vakata-contextmenu.jstree-brackets-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; border-radius:2px; }\n#vakata-contextmenu.jstree-brackets-context li.jstree-contextmenu-disabled a,\n#vakata-contextmenu.jstree-brackets-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }\n#vakata-contextmenu.jstree-brackets-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }\n#vakata-contextmenu.jstree-brackets-context li ul { margin-left:-4px; }\n"
  },
  {
    "path": "src/supported-encodings.json",
    "content": "[\n    \"ASMO-708\",\n    \"BIG5\",\n    \"CP437\",\n    \"CP852\",\n    \"CP866\",\n    \"DOS-720\",\n    \"DOS-862\",\n    \"EUC-JP\",\n    \"EUC-KR\",\n    \"GB18030\",\n    \"GB2312\",\n    \"GBK\",\n    \"HZ-GB-2312\",\n    \"IBM420\",\n    \"ISO-2022-CN\",\n    \"ISO-2022-JP\",\n    \"ISO-2022-KR\",\n    \"ISO-8859-1\",\n    \"ISO-8859-11\",\n    \"ISO-8859-13\",\n    \"ISO-8859-2\",\n    \"ISO-8859-3\",\n    \"ISO-8859-4\",\n    \"ISO-8859-5\",\n    \"ISO-8859-6\",\n    \"ISO-8859-7\",\n    \"ISO-8859-8\",\n    \"ISO-8859-8-I\",\n    \"ISO-8859-9\",\n    \"KOI8-R\",\n    \"KOI8-RU\",\n    \"SHIFT_JIS\",\n    \"UTF-8\",\n    \"WINDOWS-1250\",\n    \"WINDOWS-1251\",\n    \"WINDOWS-1252\",\n    \"WINDOWS-1253\",\n    \"WINDOWS-1254\",\n    \"WINDOWS-1255\",\n    \"WINDOWS-1256\",\n    \"WINDOWS-1257\",\n    \"WINDOWS-1258\",\n    \"WINDOWS-874\"\n]"
  },
  {
    "path": "src/thirdparty/classnames.js",
    "content": "//    https://github.com/JedWatson/classnames\n//\n//    The MIT License (MIT)\n//\n//    Copyright (c) 2015 Jed Watson\n//\n//    Permission is hereby granted, free of charge, to any person obtaining a copy\n//    of this software and associated documentation files (the \"Software\"), to deal\n//    in the Software without restriction, including without limitation the rights\n//    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//    copies of the Software, and to permit persons to whom the Software is\n//    furnished to do so, subject to the following conditions:\n//\n//    The above copyright notice and this permission notice shall be included in all\n//    copies or substantial portions of the Software.\n//\n//    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n//    SOFTWARE.\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    function classNames() {\n        var classes = '';\n        var arg;\n\n        for (var i = 0; i < arguments.length; i++) {\n            arg = arguments[i];\n            if (!arg) {\n                continue;\n            }\n\n            if ('string' === typeof arg || 'number' === typeof arg) {\n                classes += ' ' + arg;\n            } else if (Object.prototype.toString.call(arg) === '[object Array]') {\n                classes += ' ' + classNames.apply(null, arg);\n            } else if ('object' === typeof arg) {\n                for (var key in arg) {\n                    if (!arg.hasOwnProperty(key) || !arg[key]) {\n                        continue;\n                    }\n                    classes += ' ' + key;\n                }\n            }\n        }\n        return classes.substr(1);\n    }\n\n    // safely export classNames in case the script is included directly on a page\n    if (typeof module !== 'undefined' && module.exports) {\n        module.exports = classNames;\n    }\n    \n});\n"
  },
  {
    "path": "src/thirdparty/globmatch.js",
    "content": "// This is a slightly modified version of the minimatch library\n// https://github.com/isaacs/minimatch\n// (MIT-licensed, Copyright 2009-2011 Isaac Z. Schlueter)\n//\n// It has been modified to work properly with RequireJS and\n// to export an fnmatch function adapted from the EditorConfig project:\n// https://github.com/editorconfig/editorconfig-core-js/\n// (MIT-licensed, Copyright 2012 EditorConfig Team)\n\n\ndefine(function (r, exports, module, platform) {\n\nmodule.exports = fnmatch;\nminimatch.Minimatch = Minimatch;\n    \nfunction fnmatch(filepath, glob) {\n  var matchOptions = {dot: true, noext: true};\n  \n  // brackets #7374: don't try to match base if a directory name is passed in\n  if (filepath[filepath.length - 1] !== \"/\") {\n    matchOptions.matchBase = true;\n  }\n  \n  glob = glob.replace(/\\*\\*/g, '{*,**/**/**}');\n  return minimatch(filepath, glob, matchOptions);\n};\n\nvar LRU = function LRUCache () {\n        // not quite an LRU, but still space-limited.\n        var cache = {}\n        var cnt = 0\n        this.set = function (k, v) {\n          cnt ++\n          if (cnt >= 100) cache = {}\n          cache[k] = v\n        }\n        this.get = function (k) { return cache[k] }\n      }\n  , cache = minimatch.cache = new LRU({max: 100})\n  , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}\n  , sigmund = function sigmund (obj) {\n        return JSON.stringify(obj)\n      };\n\nvar path = { basename: function (f) {\n        f = f.split(/[\\/\\\\]/)\n        var e = f.pop()\n        if (!e) e = f.pop()\n        return e\n      }}\n  // any single thing other than /\n  // don't need to escape / when using new RegExp()\n  , qmark = \"[^/]\"\n\n  // * => any number of characters\n  , star = qmark + \"*?\"\n\n  // ** when dots are allowed.  Anything goes, except .. and .\n  // not (^ or / followed by one or two dots followed by $ or /),\n  // followed by anything, any number of times.\n  , twoStarDot = \"(?:(?!(?:\\\\\\/|^)(?:\\\\.{1,2})($|\\\\\\/)).)*?\"\n\n  // not a ^ or / followed by a dot,\n  // followed by anything, any number of times.\n  , twoStarNoDot = \"(?:(?!(?:\\\\\\/|^)\\\\.).)*?\"\n\n  // characters that need to be escaped in RegExp.\n  , reSpecials = charSet(\"().*{}+?[]^$\\\\!\")\n\n// \"abc\" -> { a:true, b:true, c:true }\nfunction charSet (s) {\n  return s.split(\"\").reduce(function (set, c) {\n    set[c] = true\n    return set\n  }, {})\n}\n\n// normalizes slashes.\nvar slashSplit = /\\/+/\n\nminimatch.monkeyPatch = monkeyPatch\nfunction monkeyPatch () {\n  var desc = Object.getOwnPropertyDescriptor(String.prototype, \"match\")\n  var orig = desc.value\n  desc.value = function (p) {\n    if (p instanceof Minimatch) return p.match(this)\n    return orig.call(this, p)\n  }\n  Object.defineProperty(String.prototype, desc)\n}\n\nminimatch.filter = filter\nfunction filter (pattern, options) {\n  options = options || {}\n  return function (p, i, list) {\n    return minimatch(p, pattern, options)\n  }\n}\n\nfunction ext (a, b) {\n  a = a || {}\n  b = b || {}\n  var t = {}\n  Object.keys(b).forEach(function (k) {\n    t[k] = b[k]\n  })\n  Object.keys(a).forEach(function (k) {\n    t[k] = a[k]\n  })\n  return t\n}\n\nminimatch.defaults = function (def) {\n  if (!def || !Object.keys(def).length) return minimatch\n\n  var orig = minimatch\n\n  var m = function minimatch (p, pattern, options) {\n    return orig.minimatch(p, pattern, ext(def, options))\n  }\n\n  m.Minimatch = function Minimatch (pattern, options) {\n    return new orig.Minimatch(pattern, ext(def, options))\n  }\n\n  return m\n}\n\nMinimatch.defaults = function (def) {\n  if (!def || !Object.keys(def).length) return Minimatch\n  return minimatch.defaults(def).Minimatch\n}\n\n\nfunction minimatch (p, pattern, options) {\n  if (typeof pattern !== \"string\") {\n    throw new TypeError(\"glob pattern string required\")\n  }\n\n  if (!options) options = {}\n\n  // shortcut: comments match nothing.\n  if (!options.nocomment && pattern.charAt(0) === \"#\") {\n    return false\n  }\n\n  // \"\" only matches \"\"\n  if (pattern.trim() === \"\") return p === \"\"\n\n  return new Minimatch(pattern, options).match(p)\n}\n\nfunction Minimatch (pattern, options) {\n  if (!(this instanceof Minimatch)) {\n    return new Minimatch(pattern, options, cache)\n  }\n\n  if (typeof pattern !== \"string\") {\n    throw new TypeError(\"glob pattern string required\")\n  }\n\n  if (!options) options = {}\n  pattern = pattern.trim()\n\n  // windows: need to use /, not \\\n  // On other platforms, \\ is a valid (albeit bad) filename char.\n  if (platform === \"win32\") {\n    pattern = pattern.split(\"\\\\\").join(\"/\")\n  }\n\n  // lru storage.\n  // these things aren't particularly big, but walking down the string\n  // and turning it into a regexp can get pretty costly.\n  var cacheKey = pattern + \"\\n\" + sigmund(options)\n  var cached = minimatch.cache.get(cacheKey)\n  if (cached) return cached\n  minimatch.cache.set(cacheKey, this)\n\n  this.options = options\n  this.set = []\n  this.pattern = pattern\n  this.regexp = null\n  this.negate = false\n  this.comment = false\n  this.empty = false\n\n  // make the set of regexps etc.\n  this.make()\n}\n\nMinimatch.prototype.make = make\nfunction make () {\n  // don't do it more than once.\n  if (this._made) return\n\n  var pattern = this.pattern\n  var options = this.options\n\n  // empty patterns and comments match nothing.\n  if (!options.nocomment && pattern.charAt(0) === \"#\") {\n    this.comment = true\n    return\n  }\n  if (!pattern) {\n    this.empty = true\n    return\n  }\n\n  // step 1: figure out negation, etc.\n  this.parseNegate()\n\n  // step 2: expand braces\n  var set = this.globSet = this.braceExpand()\n\n  if (options.debug) console.error(this.pattern, set)\n\n  // step 3: now we have a set, so turn each one into a series of path-portion\n  // matching patterns.\n  // These will be regexps, except in the case of \"**\", which is\n  // set to the GLOBSTAR object for globstar behavior,\n  // and will not contain any / characters\n  set = this.globParts = set.map(function (s) {\n    return s.split(slashSplit)\n  })\n\n  if (options.debug) console.error(this.pattern, set)\n\n  // glob --> regexps\n  set = set.map(function (s, si, set) {\n    return s.map(this.parse, this)\n  }, this)\n\n  if (options.debug) console.error(this.pattern, set)\n\n  // filter out everything that didn't compile properly.\n  set = set.filter(function (s) {\n    return -1 === s.indexOf(false)\n  })\n\n  if (options.debug) console.error(this.pattern, set)\n\n  this.set = set\n}\n\nMinimatch.prototype.parseNegate = parseNegate\nfunction parseNegate () {\n  var pattern = this.pattern\n    , negate = false\n    , options = this.options\n    , negateOffset = 0\n\n  if (options.nonegate) return\n\n  for ( var i = 0, l = pattern.length\n      ; i < l && pattern.charAt(i) === \"!\"\n      ; i ++) {\n    negate = !negate\n    negateOffset ++\n  }\n\n  if (negateOffset) this.pattern = pattern.substr(negateOffset)\n  this.negate = negate\n}\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nminimatch.braceExpand = function (pattern, options) {\n  return new Minimatch(pattern, options).braceExpand()\n}\n\nMinimatch.prototype.braceExpand = braceExpand\nfunction braceExpand (pattern, options) {\n  options = options || this.options\n  pattern = typeof pattern === \"undefined\"\n    ? this.pattern : pattern\n\n  if (typeof pattern === \"undefined\") {\n    throw new Error(\"undefined pattern\")\n  }\n\n  if (options.nobrace ||\n      !pattern.match(/\\{.*\\}/)) {\n    // shortcut. no need to expand.\n    return [pattern]\n  }\n\n  var escaping = false\n\n  // examples and comments refer to this crazy pattern:\n  // a{b,c{d,e},{f,g}h}x{y,z}\n  // expected:\n  // abxy\n  // abxz\n  // acdxy\n  // acdxz\n  // acexy\n  // acexz\n  // afhxy\n  // afhxz\n  // aghxy\n  // aghxz\n\n  // everything before the first \\{ is just a prefix.\n  // So, we pluck that off, and work with the rest,\n  // and then prepend it to everything we find.\n  if (pattern.charAt(0) !== \"{\") {\n    // console.error(pattern)\n    var prefix = null\n    for (var i = 0, l = pattern.length; i < l; i ++) {\n      var c = pattern.charAt(i)\n      // console.error(i, c)\n      if (c === \"\\\\\") {\n        escaping = !escaping\n      } else if (c === \"{\" && !escaping) {\n        prefix = pattern.substr(0, i)\n        break\n      }\n    }\n\n    // actually no sets, all { were escaped.\n    if (prefix === null) {\n      // console.error(\"no sets\")\n      return [pattern]\n    }\n\n    var tail = braceExpand(pattern.substr(i), options)\n    return tail.map(function (t) {\n      return prefix + t\n    })\n  }\n\n  // now we have something like:\n  // {b,c{d,e},{f,g}h}x{y,z}\n  // walk through the set, expanding each part, until\n  // the set ends.  then, we'll expand the suffix.\n  // If the set only has a single member, then'll put the {} back\n\n  // first, handle numeric sets, since they're easier\n  var numset = pattern.match(/^\\{(-?[0-9]+)\\.\\.(-?[0-9]+)\\}/)\n  if (numset) {\n    // console.error(\"numset\", numset[1], numset[2])\n    var suf = braceExpand(pattern.substr(numset[0].length), options)\n      , start = +numset[1]\n      , end = +numset[2]\n      , inc = start > end ? -1 : 1\n      , set = []\n    for (var i = start; i != (end + inc); i += inc) {\n      // append all the suffixes\n      for (var ii = 0, ll = suf.length; ii < ll; ii ++) {\n        set.push(i + suf[ii])\n      }\n    }\n    return set\n  }\n\n  // ok, walk through the set\n  // We hope, somewhat optimistically, that there\n  // will be a } at the end.\n  // If the closing brace isn't found, then the pattern is\n  // interpreted as braceExpand(\"\\\\\" + pattern) so that\n  // the leading \\{ will be interpreted literally.\n  var i = 1 // skip the \\{\n    , depth = 1\n    , set = []\n    , member = \"\"\n    , sawEnd = false\n    , escaping = false\n\n  function addMember () {\n    set.push(member)\n    member = \"\"\n  }\n\n  // console.error(\"Entering for\")\n  FOR: for (i = 1, l = pattern.length; i < l; i ++) {\n    var c = pattern.charAt(i)\n    // console.error(\"\", i, c)\n\n    if (escaping) {\n      escaping = false\n      member += \"\\\\\" + c\n    } else {\n      switch (c) {\n        case \"\\\\\":\n          escaping = true\n          continue\n\n        case \"{\":\n          depth ++\n          member += \"{\"\n          continue\n\n        case \"}\":\n          depth --\n          // if this closes the actual set, then we're done\n          if (depth === 0) {\n            addMember()\n            // pluck off the close-brace\n            i ++\n            break FOR\n          } else {\n            member += c\n            continue\n          }\n\n        case \",\":\n          if (depth === 1) {\n            addMember()\n          } else {\n            member += c\n          }\n          continue\n\n        default:\n          member += c\n          continue\n      } // switch\n    } // else\n  } // for\n\n  // now we've either finished the set, and the suffix is\n  // pattern.substr(i), or we have *not* closed the set,\n  // and need to escape the leading brace\n  if (depth !== 0) {\n    // console.error(\"didn't close\", pattern)\n    return braceExpand(\"\\\\\" + pattern, options)\n  }\n\n  // x{y,z} -> [\"xy\", \"xz\"]\n  // console.error(\"set\", set)\n  // console.error(\"suffix\", pattern.substr(i))\n  var suf = braceExpand(pattern.substr(i), options)\n  // [\"b\", \"c{d,e}\",\"{f,g}h\"] ->\n  //   [[\"b\"], [\"cd\", \"ce\"], [\"fh\", \"gh\"]]\n  var addBraces = set.length === 1\n  // console.error(\"set pre-expanded\", set)\n  set = set.map(function (p) {\n    return braceExpand(p, options)\n  })\n  // console.error(\"set expanded\", set)\n\n\n  // [[\"b\"], [\"cd\", \"ce\"], [\"fh\", \"gh\"]] ->\n  //   [\"b\", \"cd\", \"ce\", \"fh\", \"gh\"]\n  set = set.reduce(function (l, r) {\n    return l.concat(r)\n  })\n\n  if (addBraces) {\n    set = set.map(function (s) {\n      return \"{\" + s + \"}\"\n    })\n  }\n\n  // now attach the suffixes.\n  var ret = []\n  for (var i = 0, l = set.length; i < l; i ++) {\n    for (var ii = 0, ll = suf.length; ii < ll; ii ++) {\n      ret.push(set[i] + suf[ii])\n    }\n  }\n  return ret\n}\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion.  Otherwise, any series\n// of * is equivalent to a single *.  Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\nMinimatch.prototype.parse = parse\nvar SUBPARSE = {}\nfunction parse (pattern, isSub) {\n  var options = this.options\n\n  // shortcuts\n  if (!options.noglobstar && pattern === \"**\") return GLOBSTAR\n  if (pattern === \"\") return \"\"\n\n  var re = \"\"\n    , hasMagic = !!options.nocase\n    , escaping = false\n    // ? => one single character\n    , patternListStack = []\n    , plType\n    , stateChar\n    , inClass = false\n    , reClassStart = -1\n    , classStart = -1\n    // . and .. never match anything that doesn't start with .,\n    // even when options.dot is set.\n    , patternStart = pattern.charAt(0) === \".\" ? \"\" // anything\n      // not (start or / followed by . or .. followed by / or end)\n      : options.dot ? \"(?!(?:^|\\\\\\/)\\\\.{1,2}(?:$|\\\\\\/))\"\n      : \"(?!\\\\.)\"\n\n  function clearStateChar () {\n    if (stateChar) {\n      // we had some state-tracking character\n      // that wasn't consumed by this pass.\n      switch (stateChar) {\n        case \"*\":\n          re += star\n          hasMagic = true\n          break\n        case \"?\":\n          re += qmark\n          hasMagic = true\n          break\n        default:\n          re += \"\\\\\"+stateChar\n          break\n      }\n      stateChar = false\n    }\n  }\n\n  for ( var i = 0, len = pattern.length, c\n      ; (i < len) && (c = pattern.charAt(i))\n      ; i ++ ) {\n\n    if (options.debug) {\n      console.error(\"%s\\t%s %s %j\", pattern, i, re, c)\n    }\n\n    // skip over any that are escaped.\n    if (escaping && reSpecials[c]) {\n      re += \"\\\\\" + c\n      escaping = false\n      continue\n    }\n\n    SWITCH: switch (c) {\n      case \"/\":\n        // completely not allowed, even escaped.\n        // Should already be path-split by now.\n        return false\n\n      case \"\\\\\":\n        clearStateChar()\n        escaping = true\n        continue\n\n      // the various stateChar values\n      // for the \"extglob\" stuff.\n      case \"?\":\n      case \"*\":\n      case \"+\":\n      case \"@\":\n      case \"!\":\n        if (options.debug) {\n          console.error(\"%s\\t%s %s %j <-- stateChar\", pattern, i, re, c)\n        }\n\n        // all of those are literals inside a class, except that\n        // the glob [!a] means [^a] in regexp\n        if (inClass) {\n          if (c === \"!\" && i === classStart + 1) c = \"^\"\n          re += c\n          continue\n        }\n\n        // if we already have a stateChar, then it means\n        // that there was something like ** or +? in there.\n        // Handle the stateChar, then proceed with this one.\n        clearStateChar()\n        stateChar = c\n        // if extglob is disabled, then +(asdf|foo) isn't a thing.\n        // just clear the statechar *now*, rather than even diving into\n        // the patternList stuff.\n        if (options.noext) clearStateChar()\n        continue\n\n      case \"(\":\n        if (inClass) {\n          re += \"(\"\n          continue\n        }\n\n        if (!stateChar) {\n          re += \"\\\\(\"\n          continue\n        }\n\n        plType = stateChar\n        patternListStack.push({ type: plType\n                              , start: i - 1\n                              , reStart: re.length })\n        // negation is (?:(?!js)[^/]*)\n        re += stateChar === \"!\" ? \"(?:(?!\" : \"(?:\"\n        stateChar = false\n        continue\n\n      case \")\":\n        if (inClass || !patternListStack.length) {\n          re += \"\\\\)\"\n          continue\n        }\n\n        hasMagic = true\n        re += \")\"\n        plType = patternListStack.pop().type\n        // negation is (?:(?!js)[^/]*)\n        // The others are (?:<pattern>)<type>\n        switch (plType) {\n          case \"!\":\n            re += \"[^/]*?)\"\n            break\n          case \"?\":\n          case \"+\":\n          case \"*\": re += plType\n          case \"@\": break // the default anyway\n        }\n        continue\n\n      case \"|\":\n        if (inClass || !patternListStack.length || escaping) {\n          re += \"\\\\|\"\n          escaping = false\n          continue\n        }\n\n        re += \"|\"\n        continue\n\n      // these are mostly the same in regexp and glob\n      case \"[\":\n        // swallow any state-tracking char before the [\n        clearStateChar()\n\n        if (inClass) {\n          re += \"\\\\\" + c\n          continue\n        }\n\n        inClass = true\n        classStart = i\n        reClassStart = re.length\n        re += c\n        continue\n\n      case \"]\":\n        //  a right bracket shall lose its special\n        //  meaning and represent itself in\n        //  a bracket expression if it occurs\n        //  first in the list.  -- POSIX.2 2.8.3.2\n        if (i === classStart + 1 || !inClass) {\n          re += \"\\\\\" + c\n          escaping = false\n          continue\n        }\n\n        // finish up the class.\n        hasMagic = true\n        inClass = false\n        re += c\n        continue\n\n      default:\n        // swallow any state char that wasn't consumed\n        clearStateChar()\n\n        if (escaping) {\n          // no need\n          escaping = false\n        } else if (reSpecials[c]\n                   && !(c === \"^\" && inClass)) {\n          re += \"\\\\\"\n        }\n\n        re += c\n\n    } // switch\n  } // for\n\n\n  // handle the case where we left a class open.\n  // \"[abc\" is valid, equivalent to \"\\[abc\"\n  if (inClass) {\n    // split where the last [ was, and escape it\n    // this is a huge pita.  We now have to re-walk\n    // the contents of the would-be class to re-translate\n    // any characters that were passed through as-is\n    var cs = pattern.substr(classStart + 1)\n      , sp = this.parse(cs, SUBPARSE)\n    re = re.substr(0, reClassStart) + \"\\\\[\" + sp[0]\n    hasMagic = hasMagic || sp[1]\n  }\n\n  // handle the case where we had a +( thing at the *end*\n  // of the pattern.\n  // each pattern list stack adds 3 chars, and we need to go through\n  // and escape any | chars that were passed through as-is for the regexp.\n  // Go through and escape them, taking care not to double-escape any\n  // | chars that were already escaped.\n  var pl\n  while (pl = patternListStack.pop()) {\n    var tail = re.slice(pl.reStart + 3)\n    // maybe some even number of \\, then maybe 1 \\, followed by a |\n    tail = tail.replace(/((?:\\\\{2})*)(\\\\?)\\|/g, function (_, $1, $2) {\n      if (!$2) {\n        // the | isn't already escaped, so escape it.\n        $2 = \"\\\\\"\n      }\n\n      // need to escape all those slashes *again*, without escaping the\n      // one that we need for escaping the | character.  As it works out,\n      // escaping an even number of slashes can be done by simply repeating\n      // it exactly after itself.  That's why this trick works.\n      //\n      // I am sorry that you have to see this.\n      return $1 + $1 + $2 + \"|\"\n    })\n\n    // console.error(\"tail=%j\\n   %s\", tail, tail)\n    var t = pl.type === \"*\" ? star\n          : pl.type === \"?\" ? qmark\n          : \"\\\\\" + pl.type\n\n    hasMagic = true\n    re = re.slice(0, pl.reStart)\n       + t + \"\\\\(\"\n       + tail\n  }\n\n  // handle trailing things that only matter at the very end.\n  clearStateChar()\n  if (escaping) {\n    // trailing \\\\\n    re += \"\\\\\\\\\"\n  }\n\n  // only need to apply the nodot start if the re starts with\n  // something that could conceivably capture a dot\n  var addPatternStart = false\n  switch (re.charAt(0)) {\n    case \".\":\n    case \"[\":\n    case \"(\": addPatternStart = true\n  }\n\n  // if the re is not \"\" at this point, then we need to make sure\n  // it doesn't match against an empty path part.\n  // Otherwise a/* will match a/, which it should not.\n  if (re !== \"\" && hasMagic) re = \"(?=.)\" + re\n\n  if (addPatternStart) re = patternStart + re\n\n  // parsing just a piece of a larger pattern.\n  if (isSub === SUBPARSE) {\n    return [ re, hasMagic ]\n  }\n\n  // skip the regexp for non-magical patterns\n  // unescape anything in it, though, so that it'll be\n  // an exact match against a file etc.\n  if (!hasMagic) {\n    return globUnescape(pattern)\n  }\n\n  var flags = options.nocase ? \"i\" : \"\"\n    , regExp = new RegExp(\"^\" + re + \"$\", flags)\n\n  regExp._glob = pattern\n  regExp._src = re\n\n  return regExp\n}\n\nminimatch.makeRe = function (pattern, options) {\n  return new Minimatch(pattern, options || {}).makeRe()\n}\n\nMinimatch.prototype.makeRe = makeRe\nfunction makeRe () {\n  if (this.regexp || this.regexp === false) return this.regexp\n\n  // at this point, this.set is a 2d array of partial\n  // pattern strings, or \"**\".\n  //\n  // It's better to use .match().  This function shouldn't\n  // be used, really, but it's pretty convenient sometimes,\n  // when you just want to work with a regex.\n  var set = this.set\n\n  if (!set.length) return this.regexp = false\n  var options = this.options\n\n  var twoStar = options.noglobstar ? star\n      : options.dot ? twoStarDot\n      : twoStarNoDot\n    , flags = options.nocase ? \"i\" : \"\"\n\n  var re = set.map(function (pattern) {\n    return pattern.map(function (p) {\n      return (p === GLOBSTAR) ? twoStar\n           : (typeof p === \"string\") ? regExpEscape(p)\n           : p._src\n    }).join(\"\\\\\\/\")\n  }).join(\"|\")\n\n  // must match entire pattern\n  // ending in a * or ** will make it less strict.\n  re = \"^(?:\" + re + \")$\"\n\n  // can match anything, as long as it's not this.\n  if (this.negate) re = \"^(?!\" + re + \").*$\"\n\n  try {\n    return this.regexp = new RegExp(re, flags)\n  } catch (ex) {\n    return this.regexp = false\n  }\n}\n\nminimatch.match = function (list, pattern, options) {\n  var mm = new Minimatch(pattern, options)\n  list = list.filter(function (f) {\n    return mm.match(f)\n  })\n  if (options.nonull && !list.length) {\n    list.push(pattern)\n  }\n  return list\n}\n\nMinimatch.prototype.match = match\nfunction match (f, partial) {\n  // console.error(\"match\", f, this.pattern)\n  // short-circuit in the case of busted things.\n  // comments, etc.\n  if (this.comment) return false\n  if (this.empty) return f === \"\"\n\n  if (f === \"/\" && partial) return true\n\n  var options = this.options\n\n  // windows: need to use /, not \\\n  // On other platforms, \\ is a valid (albeit bad) filename char.\n  if (platform === \"win32\") {\n    f = f.split(\"\\\\\").join(\"/\")\n  }\n\n  // treat the test path as a set of pathparts.\n  f = f.split(slashSplit)\n  if (options.debug) {\n    console.error(this.pattern, \"split\", f)\n  }\n\n  // just ONE of the pattern sets in this.set needs to match\n  // in order for it to be valid.  If negating, then just one\n  // match means that we have failed.\n  // Either way, return on the first hit.\n\n  var set = this.set\n  // console.error(this.pattern, \"set\", set)\n\n  for (var i = 0, l = set.length; i < l; i ++) {\n    var pattern = set[i]\n    var hit = this.matchOne(f, pattern, partial)\n    if (hit) {\n      if (options.flipNegate) return true\n      return !this.negate\n    }\n  }\n\n  // didn't get any hits.  this is success if it's a negative\n  // pattern, failure otherwise.\n  if (options.flipNegate) return false\n  return this.negate\n}\n\n// set partial to true to test if, for example,\n// \"/a/b\" matches the start of \"/*/b/*/d\"\n// Partial means, if you run out of file before you run\n// out of pattern, then that's fine, as long as all\n// the parts match.\nMinimatch.prototype.matchOne = function (file, pattern, partial) {\n  var options = this.options\n\n  if (options.debug) {\n    console.error(\"matchOne\",\n                  { \"this\": this\n                  , file: file\n                  , pattern: pattern })\n  }\n\n  if (options.matchBase && pattern.length === 1) {\n    file = path.basename(file.join(\"/\")).split(\"/\")\n  }\n\n  if (options.debug) {\n    console.error(\"matchOne\", file.length, pattern.length)\n  }\n\n  for ( var fi = 0\n          , pi = 0\n          , fl = file.length\n          , pl = pattern.length\n      ; (fi < fl) && (pi < pl)\n      ; fi ++, pi ++ ) {\n\n    if (options.debug) {\n      console.error(\"matchOne loop\")\n    }\n    var p = pattern[pi]\n      , f = file[fi]\n\n    if (options.debug) {\n      console.error(pattern, p, f)\n    }\n\n    // should be impossible.\n    // some invalid regexp stuff in the set.\n    if (p === false) return false\n\n    if (p === GLOBSTAR) {\n      if (options.debug)\n        console.error('GLOBSTAR', [pattern, p, f])\n\n      // \"**\"\n      // a/**/b/**/c would match the following:\n      // a/b/x/y/z/c\n      // a/x/y/z/b/c\n      // a/b/x/b/x/c\n      // a/b/c\n      // To do this, take the rest of the pattern after\n      // the **, and see if it would match the file remainder.\n      // If so, return success.\n      // If not, the ** \"swallows\" a segment, and try again.\n      // This is recursively awful.\n      //\n      // a/**/b/**/c matching a/b/x/y/z/c\n      // - a matches a\n      // - doublestar\n      //   - matchOne(b/x/y/z/c, b/**/c)\n      //     - b matches b\n      //     - doublestar\n      //       - matchOne(x/y/z/c, c) -> no\n      //       - matchOne(y/z/c, c) -> no\n      //       - matchOne(z/c, c) -> no\n      //       - matchOne(c, c) yes, hit\n      var fr = fi\n        , pr = pi + 1\n      if (pr === pl) {\n        if (options.debug)\n          console.error('** at the end')\n        // a ** at the end will just swallow the rest.\n        // We have found a match.\n        // however, it will not swallow /.x, unless\n        // options.dot is set.\n        // . and .. are *never* matched by **, for explosively\n        // exponential reasons.\n        for ( ; fi < fl; fi ++) {\n          if (file[fi] === \".\" || file[fi] === \"..\" ||\n              (!options.dot && file[fi].charAt(0) === \".\")) return false\n        }\n        return true\n      }\n\n      // ok, let's see if we can swallow whatever we can.\n      WHILE: while (fr < fl) {\n        var swallowee = file[fr]\n\n        if (options.debug) {\n          console.error('\\nglobstar while',\n                        file, fr, pattern, pr, swallowee)\n        }\n\n        // XXX remove this slice.  Just pass the start index.\n        if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n          if (options.debug)\n            console.error('globstar found match!', fr, fl, swallowee)\n          // found a match.\n          return true\n        } else {\n          // can't swallow \".\" or \"..\" ever.\n          // can only swallow \".foo\" when explicitly asked.\n          if (swallowee === \".\" || swallowee === \"..\" ||\n              (!options.dot && swallowee.charAt(0) === \".\")) {\n            if (options.debug)\n              console.error(\"dot detected!\", file, fr, pattern, pr)\n            break WHILE\n          }\n\n          // ** swallows a segment, and continue.\n          if (options.debug)\n            console.error('globstar swallow a segment, and continue')\n          fr ++\n        }\n      }\n      // no match was found.\n      // However, in partial mode, we can't say this is necessarily over.\n      // If there's more *pattern* left, then \n      if (partial) {\n        // ran out of file\n        // console.error(\"\\n>>> no match, partial?\", file, fr, pattern, pr)\n        if (fr === fl) return true\n      }\n      return false\n    }\n\n    // something other than **\n    // non-magic patterns just have to match exactly\n    // patterns with magic have been turned into regexps.\n    var hit\n    if (typeof p === \"string\") {\n      if (options.nocase) {\n        hit = f.toLowerCase() === p.toLowerCase()\n      } else {\n        hit = f === p\n      }\n      if (options.debug) {\n        console.error(\"string match\", p, f, hit)\n      }\n    } else {\n      hit = f.match(p)\n      if (options.debug) {\n        console.error(\"pattern match\", p, f, hit)\n      }\n    }\n\n    if (!hit) return false\n  }\n\n  // Note: ending in / means that we'll get a final \"\"\n  // at the end of the pattern.  This can only match a\n  // corresponding \"\" at the end of the file.\n  // If the file ends in /, then it can only match a\n  // a pattern that ends in /, unless the pattern just\n  // doesn't have any more for it. But, a/b/ should *not*\n  // match \"a/b/*\", even though \"\" matches against the\n  // [^/]*? pattern, except in partial mode, where it might\n  // simply not be reached yet.\n  // However, a/b/ should still satisfy a/*\n\n  // now either we fell off the end of the pattern, or we're done.\n  if (fi === fl && pi === pl) {\n    // ran out of pattern and filename at the same time.\n    // an exact hit!\n    return true\n  } else if (fi === fl) {\n    // ran out of file, but still had pattern left.\n    // this is ok if we're doing the match as part of\n    // a glob fs traversal.\n    return partial\n  } else if (pi === pl) {\n    // ran out of pattern, still have file left.\n    // this is only acceptable if we're on the very last\n    // empty segment of a file with a trailing slash.\n    // a/* should match a/b/\n    var emptyFileEnd = (fi === fl - 1) && (file[fi] === \"\")\n    return emptyFileEnd\n  }\n\n  // should be unreachable.\n  throw new Error(\"wtf?\")\n}\n\n\n// replace stuff like \\* with *\nfunction globUnescape (s) {\n  return s.replace(/\\\\(.)/g, \"$1\")\n}\n\n\nfunction regExpEscape (s) {\n  return s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, \"\\\\$&\")\n}\n\n});"
  },
  {
    "path": "src/thirdparty/immutable.js",
    "content": "/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n  typeof define === 'function' && define.amd ? define(factory) :\n  (global.Immutable = factory());\n}(this, function () { 'use strict';var SLICE$0 = Array.prototype.slice;\n\n  function createClass(ctor, superClass) {\n    if (superClass) {\n      ctor.prototype = Object.create(superClass.prototype);\n    }\n    ctor.prototype.constructor = ctor;\n  }\n\n  function Iterable(value) {\n      return isIterable(value) ? value : Seq(value);\n    }\n\n\n  createClass(KeyedIterable, Iterable);\n    function KeyedIterable(value) {\n      return isKeyed(value) ? value : KeyedSeq(value);\n    }\n\n\n  createClass(IndexedIterable, Iterable);\n    function IndexedIterable(value) {\n      return isIndexed(value) ? value : IndexedSeq(value);\n    }\n\n\n  createClass(SetIterable, Iterable);\n    function SetIterable(value) {\n      return isIterable(value) && !isAssociative(value) ? value : SetSeq(value);\n    }\n\n\n\n  function isIterable(maybeIterable) {\n    return !!(maybeIterable && maybeIterable[IS_ITERABLE_SENTINEL]);\n  }\n\n  function isKeyed(maybeKeyed) {\n    return !!(maybeKeyed && maybeKeyed[IS_KEYED_SENTINEL]);\n  }\n\n  function isIndexed(maybeIndexed) {\n    return !!(maybeIndexed && maybeIndexed[IS_INDEXED_SENTINEL]);\n  }\n\n  function isAssociative(maybeAssociative) {\n    return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);\n  }\n\n  function isOrdered(maybeOrdered) {\n    return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]);\n  }\n\n  Iterable.isIterable = isIterable;\n  Iterable.isKeyed = isKeyed;\n  Iterable.isIndexed = isIndexed;\n  Iterable.isAssociative = isAssociative;\n  Iterable.isOrdered = isOrdered;\n\n  Iterable.Keyed = KeyedIterable;\n  Iterable.Indexed = IndexedIterable;\n  Iterable.Set = SetIterable;\n\n\n  var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@';\n  var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';\n  var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@';\n  var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';\n\n  // Used for setting prototype methods that IE8 chokes on.\n  var DELETE = 'delete';\n\n  // Constants describing the size of trie nodes.\n  var SHIFT = 5; // Resulted in best performance after ______?\n  var SIZE = 1 << SHIFT;\n  var MASK = SIZE - 1;\n\n  // A consistent shared value representing \"not set\" which equals nothing other\n  // than itself, and nothing that could be provided externally.\n  var NOT_SET = {};\n\n  // Boolean references, Rough equivalent of `bool &`.\n  var CHANGE_LENGTH = { value: false };\n  var DID_ALTER = { value: false };\n\n  function MakeRef(ref) {\n    ref.value = false;\n    return ref;\n  }\n\n  function SetRef(ref) {\n    ref && (ref.value = true);\n  }\n\n  // A function which returns a value representing an \"owner\" for transient writes\n  // to tries. The return value will only ever equal itself, and will not equal\n  // the return of any subsequent call of this function.\n  function OwnerID() {}\n\n  // http://jsperf.com/copy-array-inline\n  function arrCopy(arr, offset) {\n    offset = offset || 0;\n    var len = Math.max(0, arr.length - offset);\n    var newArr = new Array(len);\n    for (var ii = 0; ii < len; ii++) {\n      newArr[ii] = arr[ii + offset];\n    }\n    return newArr;\n  }\n\n  function ensureSize(iter) {\n    if (iter.size === undefined) {\n      iter.size = iter.__iterate(returnTrue);\n    }\n    return iter.size;\n  }\n\n  function wrapIndex(iter, index) {\n    // This implements \"is array index\" which the ECMAString spec defines as:\n    //\n    //     A String property name P is an array index if and only if\n    //     ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal\n    //     to 2^32−1.\n    //\n    // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects\n    if (typeof index !== 'number') {\n      var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32\n      if ('' + uint32Index !== index || uint32Index === 4294967295) {\n        return NaN;\n      }\n      index = uint32Index;\n    }\n    return index < 0 ? ensureSize(iter) + index : index;\n  }\n\n  function returnTrue() {\n    return true;\n  }\n\n  function wholeSlice(begin, end, size) {\n    return (begin === 0 || (size !== undefined && begin <= -size)) &&\n      (end === undefined || (size !== undefined && end >= size));\n  }\n\n  function resolveBegin(begin, size) {\n    return resolveIndex(begin, size, 0);\n  }\n\n  function resolveEnd(end, size) {\n    return resolveIndex(end, size, size);\n  }\n\n  function resolveIndex(index, size, defaultIndex) {\n    return index === undefined ?\n      defaultIndex :\n      index < 0 ?\n        Math.max(0, size + index) :\n        size === undefined ?\n          index :\n          Math.min(size, index);\n  }\n\n  /* global Symbol */\n\n  var ITERATE_KEYS = 0;\n  var ITERATE_VALUES = 1;\n  var ITERATE_ENTRIES = 2;\n\n  var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\n  var FAUX_ITERATOR_SYMBOL = '@@iterator';\n\n  var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;\n\n\n  function Iterator(next) {\n      this.next = next;\n    }\n\n    Iterator.prototype.toString = function() {\n      return '[Iterator]';\n    };\n\n\n  Iterator.KEYS = ITERATE_KEYS;\n  Iterator.VALUES = ITERATE_VALUES;\n  Iterator.ENTRIES = ITERATE_ENTRIES;\n\n  Iterator.prototype.inspect =\n  Iterator.prototype.toSource = function () { return this.toString(); }\n  Iterator.prototype[ITERATOR_SYMBOL] = function () {\n    return this;\n  };\n\n\n  function iteratorValue(type, k, v, iteratorResult) {\n    var value = type === 0 ? k : type === 1 ? v : [k, v];\n    iteratorResult ? (iteratorResult.value = value) : (iteratorResult = {\n      value: value, done: false\n    });\n    return iteratorResult;\n  }\n\n  function iteratorDone() {\n    return { value: undefined, done: true };\n  }\n\n  function hasIterator(maybeIterable) {\n    return !!getIteratorFn(maybeIterable);\n  }\n\n  function isIterator(maybeIterator) {\n    return maybeIterator && typeof maybeIterator.next === 'function';\n  }\n\n  function getIterator(iterable) {\n    var iteratorFn = getIteratorFn(iterable);\n    return iteratorFn && iteratorFn.call(iterable);\n  }\n\n  function getIteratorFn(iterable) {\n    var iteratorFn = iterable && (\n      (REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||\n      iterable[FAUX_ITERATOR_SYMBOL]\n    );\n    if (typeof iteratorFn === 'function') {\n      return iteratorFn;\n    }\n  }\n\n  function isArrayLike(value) {\n    return value && typeof value.length === 'number';\n  }\n\n  createClass(Seq, Iterable);\n    function Seq(value) {\n      return value === null || value === undefined ? emptySequence() :\n        isIterable(value) ? value.toSeq() : seqFromValue(value);\n    }\n\n    Seq.of = function(/*...values*/) {\n      return Seq(arguments);\n    };\n\n    Seq.prototype.toSeq = function() {\n      return this;\n    };\n\n    Seq.prototype.toString = function() {\n      return this.__toString('Seq {', '}');\n    };\n\n    Seq.prototype.cacheResult = function() {\n      if (!this._cache && this.__iterateUncached) {\n        this._cache = this.entrySeq().toArray();\n        this.size = this._cache.length;\n      }\n      return this;\n    };\n\n    // abstract __iterateUncached(fn, reverse)\n\n    Seq.prototype.__iterate = function(fn, reverse) {\n      return seqIterate(this, fn, reverse, true);\n    };\n\n    // abstract __iteratorUncached(type, reverse)\n\n    Seq.prototype.__iterator = function(type, reverse) {\n      return seqIterator(this, type, reverse, true);\n    };\n\n\n\n  createClass(KeyedSeq, Seq);\n    function KeyedSeq(value) {\n      return value === null || value === undefined ?\n        emptySequence().toKeyedSeq() :\n        isIterable(value) ?\n          (isKeyed(value) ? value.toSeq() : value.fromEntrySeq()) :\n          keyedSeqFromValue(value);\n    }\n\n    KeyedSeq.prototype.toKeyedSeq = function() {\n      return this;\n    };\n\n\n\n  createClass(IndexedSeq, Seq);\n    function IndexedSeq(value) {\n      return value === null || value === undefined ? emptySequence() :\n        !isIterable(value) ? indexedSeqFromValue(value) :\n        isKeyed(value) ? value.entrySeq() : value.toIndexedSeq();\n    }\n\n    IndexedSeq.of = function(/*...values*/) {\n      return IndexedSeq(arguments);\n    };\n\n    IndexedSeq.prototype.toIndexedSeq = function() {\n      return this;\n    };\n\n    IndexedSeq.prototype.toString = function() {\n      return this.__toString('Seq [', ']');\n    };\n\n    IndexedSeq.prototype.__iterate = function(fn, reverse) {\n      return seqIterate(this, fn, reverse, false);\n    };\n\n    IndexedSeq.prototype.__iterator = function(type, reverse) {\n      return seqIterator(this, type, reverse, false);\n    };\n\n\n\n  createClass(SetSeq, Seq);\n    function SetSeq(value) {\n      return (\n        value === null || value === undefined ? emptySequence() :\n        !isIterable(value) ? indexedSeqFromValue(value) :\n        isKeyed(value) ? value.entrySeq() : value\n      ).toSetSeq();\n    }\n\n    SetSeq.of = function(/*...values*/) {\n      return SetSeq(arguments);\n    };\n\n    SetSeq.prototype.toSetSeq = function() {\n      return this;\n    };\n\n\n\n  Seq.isSeq = isSeq;\n  Seq.Keyed = KeyedSeq;\n  Seq.Set = SetSeq;\n  Seq.Indexed = IndexedSeq;\n\n  var IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@';\n\n  Seq.prototype[IS_SEQ_SENTINEL] = true;\n\n\n\n  createClass(ArraySeq, IndexedSeq);\n    function ArraySeq(array) {\n      this._array = array;\n      this.size = array.length;\n    }\n\n    ArraySeq.prototype.get = function(index, notSetValue) {\n      return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;\n    };\n\n    ArraySeq.prototype.__iterate = function(fn, reverse) {\n      var array = this._array;\n      var maxIndex = array.length - 1;\n      for (var ii = 0; ii <= maxIndex; ii++) {\n        if (fn(array[reverse ? maxIndex - ii : ii], ii, this) === false) {\n          return ii + 1;\n        }\n      }\n      return ii;\n    };\n\n    ArraySeq.prototype.__iterator = function(type, reverse) {\n      var array = this._array;\n      var maxIndex = array.length - 1;\n      var ii = 0;\n      return new Iterator(function() \n        {return ii > maxIndex ?\n          iteratorDone() :\n          iteratorValue(type, ii, array[reverse ? maxIndex - ii++ : ii++])}\n      );\n    };\n\n\n\n  createClass(ObjectSeq, KeyedSeq);\n    function ObjectSeq(object) {\n      var keys = Object.keys(object);\n      this._object = object;\n      this._keys = keys;\n      this.size = keys.length;\n    }\n\n    ObjectSeq.prototype.get = function(key, notSetValue) {\n      if (notSetValue !== undefined && !this.has(key)) {\n        return notSetValue;\n      }\n      return this._object[key];\n    };\n\n    ObjectSeq.prototype.has = function(key) {\n      return this._object.hasOwnProperty(key);\n    };\n\n    ObjectSeq.prototype.__iterate = function(fn, reverse) {\n      var object = this._object;\n      var keys = this._keys;\n      var maxIndex = keys.length - 1;\n      for (var ii = 0; ii <= maxIndex; ii++) {\n        var key = keys[reverse ? maxIndex - ii : ii];\n        if (fn(object[key], key, this) === false) {\n          return ii + 1;\n        }\n      }\n      return ii;\n    };\n\n    ObjectSeq.prototype.__iterator = function(type, reverse) {\n      var object = this._object;\n      var keys = this._keys;\n      var maxIndex = keys.length - 1;\n      var ii = 0;\n      return new Iterator(function()  {\n        var key = keys[reverse ? maxIndex - ii : ii];\n        return ii++ > maxIndex ?\n          iteratorDone() :\n          iteratorValue(type, key, object[key]);\n      });\n    };\n\n  ObjectSeq.prototype[IS_ORDERED_SENTINEL] = true;\n\n\n  createClass(IterableSeq, IndexedSeq);\n    function IterableSeq(iterable) {\n      this._iterable = iterable;\n      this.size = iterable.length || iterable.size;\n    }\n\n    IterableSeq.prototype.__iterateUncached = function(fn, reverse) {\n      if (reverse) {\n        return this.cacheResult().__iterate(fn, reverse);\n      }\n      var iterable = this._iterable;\n      var iterator = getIterator(iterable);\n      var iterations = 0;\n      if (isIterator(iterator)) {\n        var step;\n        while (!(step = iterator.next()).done) {\n          if (fn(step.value, iterations++, this) === false) {\n            break;\n          }\n        }\n      }\n      return iterations;\n    };\n\n    IterableSeq.prototype.__iteratorUncached = function(type, reverse) {\n      if (reverse) {\n        return this.cacheResult().__iterator(type, reverse);\n      }\n      var iterable = this._iterable;\n      var iterator = getIterator(iterable);\n      if (!isIterator(iterator)) {\n        return new Iterator(iteratorDone);\n      }\n      var iterations = 0;\n      return new Iterator(function()  {\n        var step = iterator.next();\n        return step.done ? step : iteratorValue(type, iterations++, step.value);\n      });\n    };\n\n\n\n  createClass(IteratorSeq, IndexedSeq);\n    function IteratorSeq(iterator) {\n      this._iterator = iterator;\n      this._iteratorCache = [];\n    }\n\n    IteratorSeq.prototype.__iterateUncached = function(fn, reverse) {\n      if (reverse) {\n        return this.cacheResult().__iterate(fn, reverse);\n      }\n      var iterator = this._iterator;\n      var cache = this._iteratorCache;\n      var iterations = 0;\n      while (iterations < cache.length) {\n        if (fn(cache[iterations], iterations++, this) === false) {\n          return iterations;\n        }\n      }\n      var step;\n      while (!(step = iterator.next()).done) {\n        var val = step.value;\n        cache[iterations] = val;\n        if (fn(val, iterations++, this) === false) {\n          break;\n        }\n      }\n      return iterations;\n    };\n\n    IteratorSeq.prototype.__iteratorUncached = function(type, reverse) {\n      if (reverse) {\n        return this.cacheResult().__iterator(type, reverse);\n      }\n      var iterator = this._iterator;\n      var cache = this._iteratorCache;\n      var iterations = 0;\n      return new Iterator(function()  {\n        if (iterations >= cache.length) {\n          var step = iterator.next();\n          if (step.done) {\n            return step;\n          }\n          cache[iterations] = step.value;\n        }\n        return iteratorValue(type, iterations, cache[iterations++]);\n      });\n    };\n\n\n\n\n  // # pragma Helper functions\n\n  function isSeq(maybeSeq) {\n    return !!(maybeSeq && maybeSeq[IS_SEQ_SENTINEL]);\n  }\n\n  var EMPTY_SEQ;\n\n  function emptySequence() {\n    return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));\n  }\n\n  function keyedSeqFromValue(value) {\n    var seq =\n      Array.isArray(value) ? new ArraySeq(value).fromEntrySeq() :\n      isIterator(value) ? new IteratorSeq(value).fromEntrySeq() :\n      hasIterator(value) ? new IterableSeq(value).fromEntrySeq() :\n      typeof value === 'object' ? new ObjectSeq(value) :\n      undefined;\n    if (!seq) {\n      throw new TypeError(\n        'Expected Array or iterable object of [k, v] entries, '+\n        'or keyed object: ' + value\n      );\n    }\n    return seq;\n  }\n\n  function indexedSeqFromValue(value) {\n    var seq = maybeIndexedSeqFromValue(value);\n    if (!seq) {\n      throw new TypeError(\n        'Expected Array or iterable object of values: ' + value\n      );\n    }\n    return seq;\n  }\n\n  function seqFromValue(value) {\n    var seq = maybeIndexedSeqFromValue(value) ||\n      (typeof value === 'object' && new ObjectSeq(value));\n    if (!seq) {\n      throw new TypeError(\n        'Expected Array or iterable object of values, or keyed object: ' + value\n      );\n    }\n    return seq;\n  }\n\n  function maybeIndexedSeqFromValue(value) {\n    return (\n      isArrayLike(value) ? new ArraySeq(value) :\n      isIterator(value) ? new IteratorSeq(value) :\n      hasIterator(value) ? new IterableSeq(value) :\n      undefined\n    );\n  }\n\n  function seqIterate(seq, fn, reverse, useKeys) {\n    var cache = seq._cache;\n    if (cache) {\n      var maxIndex = cache.length - 1;\n      for (var ii = 0; ii <= maxIndex; ii++) {\n        var entry = cache[reverse ? maxIndex - ii : ii];\n        if (fn(entry[1], useKeys ? entry[0] : ii, seq) === false) {\n          return ii + 1;\n        }\n      }\n      return ii;\n    }\n    return seq.__iterateUncached(fn, reverse);\n  }\n\n  function seqIterator(seq, type, reverse, useKeys) {\n    var cache = seq._cache;\n    if (cache) {\n      var maxIndex = cache.length - 1;\n      var ii = 0;\n      return new Iterator(function()  {\n        var entry = cache[reverse ? maxIndex - ii : ii];\n        return ii++ > maxIndex ?\n          iteratorDone() :\n          iteratorValue(type, useKeys ? entry[0] : ii - 1, entry[1]);\n      });\n    }\n    return seq.__iteratorUncached(type, reverse);\n  }\n\n  function fromJS(json, converter) {\n    return converter ?\n      fromJSWith(converter, json, '', {'': json}) :\n      fromJSDefault(json);\n  }\n\n  function fromJSWith(converter, json, key, parentJSON) {\n    if (Array.isArray(json)) {\n      return converter.call(parentJSON, key, IndexedSeq(json).map(function(v, k)  {return fromJSWith(converter, v, k, json)}));\n    }\n    if (isPlainObj(json)) {\n      return converter.call(parentJSON, key, KeyedSeq(json).map(function(v, k)  {return fromJSWith(converter, v, k, json)}));\n    }\n    return json;\n  }\n\n  function fromJSDefault(json) {\n    if (Array.isArray(json)) {\n      return IndexedSeq(json).map(fromJSDefault).toList();\n    }\n    if (isPlainObj(json)) {\n      return KeyedSeq(json).map(fromJSDefault).toMap();\n    }\n    return json;\n  }\n\n  function isPlainObj(value) {\n    return value && (value.constructor === Object || value.constructor === undefined);\n  }\n\n  /**\n   * An extension of the \"same-value\" algorithm as [described for use by ES6 Map\n   * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)\n   *\n   * NaN is considered the same as NaN, however -0 and 0 are considered the same\n   * value, which is different from the algorithm described by\n   * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).\n   *\n   * This is extended further to allow Objects to describe the values they\n   * represent, by way of `valueOf` or `equals` (and `hashCode`).\n   *\n   * Note: because of this extension, the key equality of Immutable.Map and the\n   * value equality of Immutable.Set will differ from ES6 Map and Set.\n   *\n   * ### Defining custom values\n   *\n   * The easiest way to describe the value an object represents is by implementing\n   * `valueOf`. For example, `Date` represents a value by returning a unix\n   * timestamp for `valueOf`:\n   *\n   *     var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...\n   *     var date2 = new Date(1234567890000);\n   *     date1.valueOf(); // 1234567890000\n   *     assert( date1 !== date2 );\n   *     assert( Immutable.is( date1, date2 ) );\n   *\n   * Note: overriding `valueOf` may have other implications if you use this object\n   * where JavaScript expects a primitive, such as implicit string coercion.\n   *\n   * For more complex types, especially collections, implementing `valueOf` may\n   * not be performant. An alternative is to implement `equals` and `hashCode`.\n   *\n   * `equals` takes another object, presumably of similar type, and returns true\n   * if the it is equal. Equality is symmetrical, so the same result should be\n   * returned if this and the argument are flipped.\n   *\n   *     assert( a.equals(b) === b.equals(a) );\n   *\n   * `hashCode` returns a 32bit integer number representing the object which will\n   * be used to determine how to store the value object in a Map or Set. You must\n   * provide both or neither methods, one must not exist without the other.\n   *\n   * Also, an important relationship between these methods must be upheld: if two\n   * values are equal, they *must* return the same hashCode. If the values are not\n   * equal, they might have the same hashCode; this is called a hash collision,\n   * and while undesirable for performance reasons, it is acceptable.\n   *\n   *     if (a.equals(b)) {\n   *       assert( a.hashCode() === b.hashCode() );\n   *     }\n   *\n   * All Immutable collections implement `equals` and `hashCode`.\n   *\n   */\n  function is(valueA, valueB) {\n    if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {\n      return true;\n    }\n    if (!valueA || !valueB) {\n      return false;\n    }\n    if (typeof valueA.valueOf === 'function' &&\n        typeof valueB.valueOf === 'function') {\n      valueA = valueA.valueOf();\n      valueB = valueB.valueOf();\n      if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {\n        return true;\n      }\n      if (!valueA || !valueB) {\n        return false;\n      }\n    }\n    if (typeof valueA.equals === 'function' &&\n        typeof valueB.equals === 'function' &&\n        valueA.equals(valueB)) {\n      return true;\n    }\n    return false;\n  }\n\n  function deepEqual(a, b) {\n    if (a === b) {\n      return true;\n    }\n\n    if (\n      !isIterable(b) ||\n      a.size !== undefined && b.size !== undefined && a.size !== b.size ||\n      a.__hash !== undefined && b.__hash !== undefined && a.__hash !== b.__hash ||\n      isKeyed(a) !== isKeyed(b) ||\n      isIndexed(a) !== isIndexed(b) ||\n      isOrdered(a) !== isOrdered(b)\n    ) {\n      return false;\n    }\n\n    if (a.size === 0 && b.size === 0) {\n      return true;\n    }\n\n    var notAssociative = !isAssociative(a);\n\n    if (isOrdered(a)) {\n      var entries = a.entries();\n      return b.every(function(v, k)  {\n        var entry = entries.next().value;\n        return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));\n      }) && entries.next().done;\n    }\n\n    var flipped = false;\n\n    if (a.size === undefined) {\n      if (b.size === undefined) {\n        if (typeof a.cacheResult === 'function') {\n          a.cacheResult();\n        }\n      } else {\n        flipped = true;\n        var _ = a;\n        a = b;\n        b = _;\n      }\n    }\n\n    var allEqual = true;\n    var bSize = b.__iterate(function(v, k)  {\n      if (notAssociative ? !a.has(v) :\n          flipped ? !is(v, a.get(k, NOT_SET)) : !is(a.get(k, NOT_SET), v)) {\n        allEqual = false;\n        return false;\n      }\n    });\n\n    return allEqual && a.size === bSize;\n  }\n\n  createClass(Repeat, IndexedSeq);\n\n    function Repeat(value, times) {\n      if (!(this instanceof Repeat)) {\n        return new Repeat(value, times);\n      }\n      this._value = value;\n      this.size = times === undefined ? Infinity : Math.max(0, times);\n      if (this.size === 0) {\n        if (EMPTY_REPEAT) {\n          return EMPTY_REPEAT;\n        }\n        EMPTY_REPEAT = this;\n      }\n    }\n\n    Repeat.prototype.toString = function() {\n      if (this.size === 0) {\n        return 'Repeat []';\n      }\n      return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]';\n    };\n\n    Repeat.prototype.get = function(index, notSetValue) {\n      return this.has(index) ? this._value : notSetValue;\n    };\n\n    Repeat.prototype.includes = function(searchValue) {\n      return is(this._value, searchValue);\n    };\n\n    Repeat.prototype.slice = function(begin, end) {\n      var size = this.size;\n      return wholeSlice(begin, end, size) ? this :\n        new Repeat(this._value, resolveEnd(end, size) - resolveBegin(begin, size));\n    };\n\n    Repeat.prototype.reverse = function() {\n      return this;\n    };\n\n    Repeat.prototype.indexOf = function(searchValue) {\n      if (is(this._value, searchValue)) {\n        return 0;\n      }\n      return -1;\n    };\n\n    Repeat.prototype.lastIndexOf = function(searchValue) {\n      if (is(this._value, searchValue)) {\n        return this.size;\n      }\n      return -1;\n    };\n\n    Repeat.prototype.__iterate = function(fn, reverse) {\n      for (var ii = 0; ii < this.size; ii++) {\n        if (fn(this._value, ii, this) === false) {\n          return ii + 1;\n        }\n      }\n      return ii;\n    };\n\n    Repeat.prototype.__iterator = function(type, reverse) {var this$0 = this;\n      var ii = 0;\n      return new Iterator(function() \n        {return ii < this$0.size ? iteratorValue(type, ii++, this$0._value) : iteratorDone()}\n      );\n    };\n\n    Repeat.prototype.equals = function(other) {\n      return other instanceof Repeat ?\n        is(this._value, other._value) :\n        deepEqual(other);\n    };\n\n\n  var EMPTY_REPEAT;\n\n  function invariant(condition, error) {\n    if (!condition) throw new Error(error);\n  }\n\n  createClass(Range, IndexedSeq);\n\n    function Range(start, end, step) {\n      if (!(this instanceof Range)) {\n        return new Range(start, end, step);\n      }\n      invariant(step !== 0, 'Cannot step a Range by 0');\n      start = start || 0;\n      if (end === undefined) {\n        end = Infinity;\n      }\n      step = step === undefined ? 1 : Math.abs(step);\n      if (end < start) {\n        step = -step;\n      }\n      this._start = start;\n      this._end = end;\n      this._step = step;\n      this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1);\n      if (this.size === 0) {\n        if (EMPTY_RANGE) {\n          return EMPTY_RANGE;\n        }\n        EMPTY_RANGE = this;\n      }\n    }\n\n    Range.prototype.toString = function() {\n      if (this.size === 0) {\n        return 'Range []';\n      }\n      return 'Range [ ' +\n        this._start + '...' + this._end +\n        (this._step !== 1 ? ' by ' + this._step : '') +\n      ' ]';\n    };\n\n    Range.prototype.get = function(index, notSetValue) {\n      return this.has(index) ?\n        this._start + wrapIndex(this, index) * this._step :\n        notSetValue;\n    };\n\n    Range.prototype.includes = function(searchValue) {\n      var possibleIndex = (searchValue - this._start) / this._step;\n      return possibleIndex >= 0 &&\n        possibleIndex < this.size &&\n        possibleIndex === Math.floor(possibleIndex);\n    };\n\n    Range.prototype.slice = function(begin, end) {\n      if (wholeSlice(begin, end, this.size)) {\n        return this;\n      }\n      begin = resolveBegin(begin, this.size);\n      end = resolveEnd(end, this.size);\n      if (end <= begin) {\n        return new Range(0, 0);\n      }\n      return new Range(this.get(begin, this._end), this.get(end, this._end), this._step);\n    };\n\n    Range.prototype.indexOf = function(searchValue) {\n      var offsetValue = searchValue - this._start;\n      if (offsetValue % this._step === 0) {\n        var index = offsetValue / this._step;\n        if (index >= 0 && index < this.size) {\n          return index\n        }\n      }\n      return -1;\n    };\n\n    Range.prototype.lastIndexOf = function(searchValue) {\n      return this.indexOf(searchValue);\n    };\n\n    Range.prototype.__iterate = function(fn, reverse) {\n      var maxIndex = this.size - 1;\n      var step = this._step;\n      var value = reverse ? this._start + maxIndex * step : this._start;\n      for (var ii = 0; ii <= maxIndex; ii++) {\n        if (fn(value, ii, this) === false) {\n          return ii + 1;\n        }\n        value += reverse ? -step : step;\n      }\n      return ii;\n    };\n\n    Range.prototype.__iterator = function(type, reverse) {\n      var maxIndex = this.size - 1;\n      var step = this._step;\n      var value = reverse ? this._start + maxIndex * step : this._start;\n      var ii = 0;\n      return new Iterator(function()  {\n        var v = value;\n        value += reverse ? -step : step;\n        return ii > maxIndex ? iteratorDone() : iteratorValue(type, ii++, v);\n      });\n    };\n\n    Range.prototype.equals = function(other) {\n      return other instanceof Range ?\n        this._start === other._start &&\n        this._end === other._end &&\n        this._step === other._step :\n        deepEqual(this, other);\n    };\n\n\n  var EMPTY_RANGE;\n\n  createClass(Collection, Iterable);\n    function Collection() {\n      throw TypeError('Abstract');\n    }\n\n\n  createClass(KeyedCollection, Collection);function KeyedCollection() {}\n\n  createClass(IndexedCollection, Collection);function IndexedCollection() {}\n\n  createClass(SetCollection, Collection);function SetCollection() {}\n\n\n  Collection.Keyed = KeyedCollection;\n  Collection.Indexed = IndexedCollection;\n  Collection.Set = SetCollection;\n\n  var imul =\n    typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 ?\n    Math.imul :\n    function imul(a, b) {\n      a = a | 0; // int\n      b = b | 0; // int\n      var c = a & 0xffff;\n      var d = b & 0xffff;\n      // Shift by 0 fixes the sign on the high part.\n      return (c * d) + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0) | 0; // int\n    };\n\n  // v8 has an optimization for storing 31-bit signed numbers.\n  // Values which have either 00 or 11 as the high order bits qualify.\n  // This function drops the highest order bit in a signed number, maintaining\n  // the sign bit.\n  function smi(i32) {\n    return ((i32 >>> 1) & 0x40000000) | (i32 & 0xBFFFFFFF);\n  }\n\n  function hash(o) {\n    if (o === false || o === null || o === undefined) {\n      return 0;\n    }\n    if (typeof o.valueOf === 'function') {\n      o = o.valueOf();\n      if (o === false || o === null || o === undefined) {\n        return 0;\n      }\n    }\n    if (o === true) {\n      return 1;\n    }\n    var type = typeof o;\n    if (type === 'number') {\n      if (o !== o || o === Infinity) {\n        return 0;\n      }\n      var h = o | 0;\n      if (h !== o) {\n        h ^= o * 0xFFFFFFFF;\n      }\n      while (o > 0xFFFFFFFF) {\n        o /= 0xFFFFFFFF;\n        h ^= o;\n      }\n      return smi(h);\n    }\n    if (type === 'string') {\n      return o.length > STRING_HASH_CACHE_MIN_STRLEN ? cachedHashString(o) : hashString(o);\n    }\n    if (typeof o.hashCode === 'function') {\n      return o.hashCode();\n    }\n    if (type === 'object') {\n      return hashJSObj(o);\n    }\n    if (typeof o.toString === 'function') {\n      return hashString(o.toString());\n    }\n    throw new Error('Value type ' + type + ' cannot be hashed.');\n  }\n\n  function cachedHashString(string) {\n    var hash = stringHashCache[string];\n    if (hash === undefined) {\n      hash = hashString(string);\n      if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {\n        STRING_HASH_CACHE_SIZE = 0;\n        stringHashCache = {};\n      }\n      STRING_HASH_CACHE_SIZE++;\n      stringHashCache[string] = hash;\n    }\n    return hash;\n  }\n\n  // http://jsperf.com/hashing-strings\n  function hashString(string) {\n    // This is the hash from JVM\n    // The hash code for a string is computed as\n    // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],\n    // where s[i] is the ith character of the string and n is the length of\n    // the string. We \"mod\" the result to make it between 0 (inclusive) and 2^31\n    // (exclusive) by dropping high bits.\n    var hash = 0;\n    for (var ii = 0; ii < string.length; ii++) {\n      hash = 31 * hash + string.charCodeAt(ii) | 0;\n    }\n    return smi(hash);\n  }\n\n  function hashJSObj(obj) {\n    var hash;\n    if (usingWeakMap) {\n      hash = weakMap.get(obj);\n      if (hash !== undefined) {\n        return hash;\n      }\n    }\n\n    hash = obj[UID_HASH_KEY];\n    if (hash !== undefined) {\n      return hash;\n    }\n\n    if (!canDefineProperty) {\n      hash = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];\n      if (hash !== undefined) {\n        return hash;\n      }\n\n      hash = getIENodeHash(obj);\n      if (hash !== undefined) {\n        return hash;\n      }\n    }\n\n    hash = ++objHashUID;\n    if (objHashUID & 0x40000000) {\n      objHashUID = 0;\n    }\n\n    if (usingWeakMap) {\n      weakMap.set(obj, hash);\n    } else if (isExtensible !== undefined && isExtensible(obj) === false) {\n      throw new Error('Non-extensible objects are not allowed as keys.');\n    } else if (canDefineProperty) {\n      Object.defineProperty(obj, UID_HASH_KEY, {\n        'enumerable': false,\n        'configurable': false,\n        'writable': false,\n        'value': hash\n      });\n    } else if (obj.propertyIsEnumerable !== undefined &&\n               obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable) {\n      // Since we can't define a non-enumerable property on the object\n      // we'll hijack one of the less-used non-enumerable properties to\n      // save our hash on it. Since this is a function it will not show up in\n      // `JSON.stringify` which is what we want.\n      obj.propertyIsEnumerable = function() {\n        return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments);\n      };\n      obj.propertyIsEnumerable[UID_HASH_KEY] = hash;\n    } else if (obj.nodeType !== undefined) {\n      // At this point we couldn't get the IE `uniqueID` to use as a hash\n      // and we couldn't use a non-enumerable property to exploit the\n      // dontEnum bug so we simply add the `UID_HASH_KEY` on the node\n      // itself.\n      obj[UID_HASH_KEY] = hash;\n    } else {\n      throw new Error('Unable to set a non-enumerable property on object.');\n    }\n\n    return hash;\n  }\n\n  // Get references to ES5 object methods.\n  var isExtensible = Object.isExtensible;\n\n  // True if Object.defineProperty works as expected. IE8 fails this test.\n  var canDefineProperty = (function() {\n    try {\n      Object.defineProperty({}, '@', {});\n      return true;\n    } catch (e) {\n      return false;\n    }\n  }());\n\n  // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it\n  // and avoid memory leaks from the IE cloneNode bug.\n  function getIENodeHash(node) {\n    if (node && node.nodeType > 0) {\n      switch (node.nodeType) {\n        case 1: // Element\n          return node.uniqueID;\n        case 9: // Document\n          return node.documentElement && node.documentElement.uniqueID;\n      }\n    }\n  }\n\n  // If possible, use a WeakMap.\n  var usingWeakMap = typeof WeakMap === 'function';\n  var weakMap;\n  if (usingWeakMap) {\n    weakMap = new WeakMap();\n  }\n\n  var objHashUID = 0;\n\n  var UID_HASH_KEY = '__immutablehash__';\n  if (typeof Symbol === 'function') {\n    UID_HASH_KEY = Symbol(UID_HASH_KEY);\n  }\n\n  var STRING_HASH_CACHE_MIN_STRLEN = 16;\n  var STRING_HASH_CACHE_MAX_SIZE = 255;\n  var STRING_HASH_CACHE_SIZE = 0;\n  var stringHashCache = {};\n\n  function assertNotInfinite(size) {\n    invariant(\n      size !== Infinity,\n      'Cannot perform this action with an infinite size.'\n    );\n  }\n\n  createClass(Map, KeyedCollection);\n\n    // @pragma Construction\n\n    function Map(value) {\n      return value === null || value === undefined ? emptyMap() :\n        isMap(value) && !isOrdered(value) ? value :\n        emptyMap().withMutations(function(map ) {\n          var iter = KeyedIterable(value);\n          assertNotInfinite(iter.size);\n          iter.forEach(function(v, k)  {return map.set(k, v)});\n        });\n    }\n\n    Map.of = function() {var keyValues = SLICE$0.call(arguments, 0);\n      return emptyMap().withMutations(function(map ) {\n        for (var i = 0; i < keyValues.length; i += 2) {\n          if (i + 1 >= keyValues.length) {\n            throw new Error('Missing value for key: ' + keyValues[i]);\n          }\n          map.set(keyValues[i], keyValues[i + 1]);\n        }\n      });\n    };\n\n    Map.prototype.toString = function() {\n      return this.__toString('Map {', '}');\n    };\n\n    // @pragma Access\n\n    Map.prototype.get = function(k, notSetValue) {\n      return this._root ?\n        this._root.get(0, undefined, k, notSetValue) :\n        notSetValue;\n    };\n\n    // @pragma Modification\n\n    Map.prototype.set = function(k, v) {\n      return updateMap(this, k, v);\n    };\n\n    Map.prototype.setIn = function(keyPath, v) {\n      return this.updateIn(keyPath, NOT_SET, function()  {return v});\n    };\n\n    Map.prototype.remove = function(k) {\n      return updateMap(this, k, NOT_SET);\n    };\n\n    Map.prototype.deleteIn = function(keyPath) {\n      return this.updateIn(keyPath, function()  {return NOT_SET});\n    };\n\n    Map.prototype.update = function(k, notSetValue, updater) {\n      return arguments.length === 1 ?\n        k(this) :\n        this.updateIn([k], notSetValue, updater);\n    };\n\n    Map.prototype.updateIn = function(keyPath, notSetValue, updater) {\n      if (!updater) {\n        updater = notSetValue;\n        notSetValue = undefined;\n      }\n      var updatedValue = updateInDeepMap(\n        this,\n        forceIterator(keyPath),\n        notSetValue,\n        updater\n      );\n      return updatedValue === NOT_SET ? undefined : updatedValue;\n    };\n\n    Map.prototype.clear = function() {\n      if (this.size === 0) {\n        return this;\n      }\n      if (this.__ownerID) {\n        this.size = 0;\n        this._root = null;\n        this.__hash = undefined;\n        this.__altered = true;\n        return this;\n      }\n      return emptyMap();\n    };\n\n    // @pragma Composition\n\n    Map.prototype.merge = function(/*...iters*/) {\n      return mergeIntoMapWith(this, undefined, arguments);\n    };\n\n    Map.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1);\n      return mergeIntoMapWith(this, merger, iters);\n    };\n\n    Map.prototype.mergeIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1);\n      return this.updateIn(\n        keyPath,\n        emptyMap(),\n        function(m ) {return typeof m.merge === 'function' ?\n          m.merge.apply(m, iters) :\n          iters[iters.length - 1]}\n      );\n    };\n\n    Map.prototype.mergeDeep = function(/*...iters*/) {\n      return mergeIntoMapWith(this, deepMerger, arguments);\n    };\n\n    Map.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1);\n      return mergeIntoMapWith(this, deepMergerWith(merger), iters);\n    };\n\n    Map.prototype.mergeDeepIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1);\n      return this.updateIn(\n        keyPath,\n        emptyMap(),\n        function(m ) {return typeof m.mergeDeep === 'function' ?\n          m.mergeDeep.apply(m, iters) :\n          iters[iters.length - 1]}\n      );\n    };\n\n    Map.prototype.sort = function(comparator) {\n      // Late binding\n      return OrderedMap(sortFactory(this, comparator));\n    };\n\n    Map.prototype.sortBy = function(mapper, comparator) {\n      // Late binding\n      return OrderedMap(sortFactory(this, comparator, mapper));\n    };\n\n    // @pragma Mutability\n\n    Map.prototype.withMutations = function(fn) {\n      var mutable = this.asMutable();\n      fn(mutable);\n      return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;\n    };\n\n    Map.prototype.asMutable = function() {\n      return this.__ownerID ? this : this.__ensureOwner(new OwnerID());\n    };\n\n    Map.prototype.asImmutable = function() {\n      return this.__ensureOwner();\n    };\n\n    Map.prototype.wasAltered = function() {\n      return this.__altered;\n    };\n\n    Map.prototype.__iterator = function(type, reverse) {\n      return new MapIterator(this, type, reverse);\n    };\n\n    Map.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      var iterations = 0;\n      this._root && this._root.iterate(function(entry ) {\n        iterations++;\n        return fn(entry[1], entry[0], this$0);\n      }, reverse);\n      return iterations;\n    };\n\n    Map.prototype.__ensureOwner = function(ownerID) {\n      if (ownerID === this.__ownerID) {\n        return this;\n      }\n      if (!ownerID) {\n        this.__ownerID = ownerID;\n        this.__altered = false;\n        return this;\n      }\n      return makeMap(this.size, this._root, ownerID, this.__hash);\n    };\n\n\n  function isMap(maybeMap) {\n    return !!(maybeMap && maybeMap[IS_MAP_SENTINEL]);\n  }\n\n  Map.isMap = isMap;\n\n  var IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@';\n\n  var MapPrototype = Map.prototype;\n  MapPrototype[IS_MAP_SENTINEL] = true;\n  MapPrototype[DELETE] = MapPrototype.remove;\n  MapPrototype.removeIn = MapPrototype.deleteIn;\n\n\n  // #pragma Trie Nodes\n\n\n\n    function ArrayMapNode(ownerID, entries) {\n      this.ownerID = ownerID;\n      this.entries = entries;\n    }\n\n    ArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) {\n      var entries = this.entries;\n      for (var ii = 0, len = entries.length; ii < len; ii++) {\n        if (is(key, entries[ii][0])) {\n          return entries[ii][1];\n        }\n      }\n      return notSetValue;\n    };\n\n    ArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {\n      var removed = value === NOT_SET;\n\n      var entries = this.entries;\n      var idx = 0;\n      for (var len = entries.length; idx < len; idx++) {\n        if (is(key, entries[idx][0])) {\n          break;\n        }\n      }\n      var exists = idx < len;\n\n      if (exists ? entries[idx][1] === value : removed) {\n        return this;\n      }\n\n      SetRef(didAlter);\n      (removed || !exists) && SetRef(didChangeSize);\n\n      if (removed && entries.length === 1) {\n        return; // undefined\n      }\n\n      if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) {\n        return createNodes(ownerID, entries, key, value);\n      }\n\n      var isEditable = ownerID && ownerID === this.ownerID;\n      var newEntries = isEditable ? entries : arrCopy(entries);\n\n      if (exists) {\n        if (removed) {\n          idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop());\n        } else {\n          newEntries[idx] = [key, value];\n        }\n      } else {\n        newEntries.push([key, value]);\n      }\n\n      if (isEditable) {\n        this.entries = newEntries;\n        return this;\n      }\n\n      return new ArrayMapNode(ownerID, newEntries);\n    };\n\n\n\n\n    function BitmapIndexedNode(ownerID, bitmap, nodes) {\n      this.ownerID = ownerID;\n      this.bitmap = bitmap;\n      this.nodes = nodes;\n    }\n\n    BitmapIndexedNode.prototype.get = function(shift, keyHash, key, notSetValue) {\n      if (keyHash === undefined) {\n        keyHash = hash(key);\n      }\n      var bit = (1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK));\n      var bitmap = this.bitmap;\n      return (bitmap & bit) === 0 ? notSetValue :\n        this.nodes[popCount(bitmap & (bit - 1))].get(shift + SHIFT, keyHash, key, notSetValue);\n    };\n\n    BitmapIndexedNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {\n      if (keyHash === undefined) {\n        keyHash = hash(key);\n      }\n      var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;\n      var bit = 1 << keyHashFrag;\n      var bitmap = this.bitmap;\n      var exists = (bitmap & bit) !== 0;\n\n      if (!exists && value === NOT_SET) {\n        return this;\n      }\n\n      var idx = popCount(bitmap & (bit - 1));\n      var nodes = this.nodes;\n      var node = exists ? nodes[idx] : undefined;\n      var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter);\n\n      if (newNode === node) {\n        return this;\n      }\n\n      if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) {\n        return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode);\n      }\n\n      if (exists && !newNode && nodes.length === 2 && isLeafNode(nodes[idx ^ 1])) {\n        return nodes[idx ^ 1];\n      }\n\n      if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) {\n        return newNode;\n      }\n\n      var isEditable = ownerID && ownerID === this.ownerID;\n      var newBitmap = exists ? newNode ? bitmap : bitmap ^ bit : bitmap | bit;\n      var newNodes = exists ? newNode ?\n        setIn(nodes, idx, newNode, isEditable) :\n        spliceOut(nodes, idx, isEditable) :\n        spliceIn(nodes, idx, newNode, isEditable);\n\n      if (isEditable) {\n        this.bitmap = newBitmap;\n        this.nodes = newNodes;\n        return this;\n      }\n\n      return new BitmapIndexedNode(ownerID, newBitmap, newNodes);\n    };\n\n\n\n\n    function HashArrayMapNode(ownerID, count, nodes) {\n      this.ownerID = ownerID;\n      this.count = count;\n      this.nodes = nodes;\n    }\n\n    HashArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) {\n      if (keyHash === undefined) {\n        keyHash = hash(key);\n      }\n      var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;\n      var node = this.nodes[idx];\n      return node ? node.get(shift + SHIFT, keyHash, key, notSetValue) : notSetValue;\n    };\n\n    HashArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {\n      if (keyHash === undefined) {\n        keyHash = hash(key);\n      }\n      var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;\n      var removed = value === NOT_SET;\n      var nodes = this.nodes;\n      var node = nodes[idx];\n\n      if (removed && !node) {\n        return this;\n      }\n\n      var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter);\n      if (newNode === node) {\n        return this;\n      }\n\n      var newCount = this.count;\n      if (!node) {\n        newCount++;\n      } else if (!newNode) {\n        newCount--;\n        if (newCount < MIN_HASH_ARRAY_MAP_SIZE) {\n          return packNodes(ownerID, nodes, newCount, idx);\n        }\n      }\n\n      var isEditable = ownerID && ownerID === this.ownerID;\n      var newNodes = setIn(nodes, idx, newNode, isEditable);\n\n      if (isEditable) {\n        this.count = newCount;\n        this.nodes = newNodes;\n        return this;\n      }\n\n      return new HashArrayMapNode(ownerID, newCount, newNodes);\n    };\n\n\n\n\n    function HashCollisionNode(ownerID, keyHash, entries) {\n      this.ownerID = ownerID;\n      this.keyHash = keyHash;\n      this.entries = entries;\n    }\n\n    HashCollisionNode.prototype.get = function(shift, keyHash, key, notSetValue) {\n      var entries = this.entries;\n      for (var ii = 0, len = entries.length; ii < len; ii++) {\n        if (is(key, entries[ii][0])) {\n          return entries[ii][1];\n        }\n      }\n      return notSetValue;\n    };\n\n    HashCollisionNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {\n      if (keyHash === undefined) {\n        keyHash = hash(key);\n      }\n\n      var removed = value === NOT_SET;\n\n      if (keyHash !== this.keyHash) {\n        if (removed) {\n          return this;\n        }\n        SetRef(didAlter);\n        SetRef(didChangeSize);\n        return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]);\n      }\n\n      var entries = this.entries;\n      var idx = 0;\n      for (var len = entries.length; idx < len; idx++) {\n        if (is(key, entries[idx][0])) {\n          break;\n        }\n      }\n      var exists = idx < len;\n\n      if (exists ? entries[idx][1] === value : removed) {\n        return this;\n      }\n\n      SetRef(didAlter);\n      (removed || !exists) && SetRef(didChangeSize);\n\n      if (removed && len === 2) {\n        return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);\n      }\n\n      var isEditable = ownerID && ownerID === this.ownerID;\n      var newEntries = isEditable ? entries : arrCopy(entries);\n\n      if (exists) {\n        if (removed) {\n          idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop());\n        } else {\n          newEntries[idx] = [key, value];\n        }\n      } else {\n        newEntries.push([key, value]);\n      }\n\n      if (isEditable) {\n        this.entries = newEntries;\n        return this;\n      }\n\n      return new HashCollisionNode(ownerID, this.keyHash, newEntries);\n    };\n\n\n\n\n    function ValueNode(ownerID, keyHash, entry) {\n      this.ownerID = ownerID;\n      this.keyHash = keyHash;\n      this.entry = entry;\n    }\n\n    ValueNode.prototype.get = function(shift, keyHash, key, notSetValue) {\n      return is(key, this.entry[0]) ? this.entry[1] : notSetValue;\n    };\n\n    ValueNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {\n      var removed = value === NOT_SET;\n      var keyMatch = is(key, this.entry[0]);\n      if (keyMatch ? value === this.entry[1] : removed) {\n        return this;\n      }\n\n      SetRef(didAlter);\n\n      if (removed) {\n        SetRef(didChangeSize);\n        return; // undefined\n      }\n\n      if (keyMatch) {\n        if (ownerID && ownerID === this.ownerID) {\n          this.entry[1] = value;\n          return this;\n        }\n        return new ValueNode(ownerID, this.keyHash, [key, value]);\n      }\n\n      SetRef(didChangeSize);\n      return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]);\n    };\n\n\n\n  // #pragma Iterators\n\n  ArrayMapNode.prototype.iterate =\n  HashCollisionNode.prototype.iterate = function (fn, reverse) {\n    var entries = this.entries;\n    for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) {\n      if (fn(entries[reverse ? maxIndex - ii : ii]) === false) {\n        return false;\n      }\n    }\n  }\n\n  BitmapIndexedNode.prototype.iterate =\n  HashArrayMapNode.prototype.iterate = function (fn, reverse) {\n    var nodes = this.nodes;\n    for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) {\n      var node = nodes[reverse ? maxIndex - ii : ii];\n      if (node && node.iterate(fn, reverse) === false) {\n        return false;\n      }\n    }\n  }\n\n  ValueNode.prototype.iterate = function (fn, reverse) {\n    return fn(this.entry);\n  }\n\n  createClass(MapIterator, Iterator);\n\n    function MapIterator(map, type, reverse) {\n      this._type = type;\n      this._reverse = reverse;\n      this._stack = map._root && mapIteratorFrame(map._root);\n    }\n\n    MapIterator.prototype.next = function() {\n      var type = this._type;\n      var stack = this._stack;\n      while (stack) {\n        var node = stack.node;\n        var index = stack.index++;\n        var maxIndex;\n        if (node.entry) {\n          if (index === 0) {\n            return mapIteratorValue(type, node.entry);\n          }\n        } else if (node.entries) {\n          maxIndex = node.entries.length - 1;\n          if (index <= maxIndex) {\n            return mapIteratorValue(type, node.entries[this._reverse ? maxIndex - index : index]);\n          }\n        } else {\n          maxIndex = node.nodes.length - 1;\n          if (index <= maxIndex) {\n            var subNode = node.nodes[this._reverse ? maxIndex - index : index];\n            if (subNode) {\n              if (subNode.entry) {\n                return mapIteratorValue(type, subNode.entry);\n              }\n              stack = this._stack = mapIteratorFrame(subNode, stack);\n            }\n            continue;\n          }\n        }\n        stack = this._stack = this._stack.__prev;\n      }\n      return iteratorDone();\n    };\n\n\n  function mapIteratorValue(type, entry) {\n    return iteratorValue(type, entry[0], entry[1]);\n  }\n\n  function mapIteratorFrame(node, prev) {\n    return {\n      node: node,\n      index: 0,\n      __prev: prev\n    };\n  }\n\n  function makeMap(size, root, ownerID, hash) {\n    var map = Object.create(MapPrototype);\n    map.size = size;\n    map._root = root;\n    map.__ownerID = ownerID;\n    map.__hash = hash;\n    map.__altered = false;\n    return map;\n  }\n\n  var EMPTY_MAP;\n  function emptyMap() {\n    return EMPTY_MAP || (EMPTY_MAP = makeMap(0));\n  }\n\n  function updateMap(map, k, v) {\n    var newRoot;\n    var newSize;\n    if (!map._root) {\n      if (v === NOT_SET) {\n        return map;\n      }\n      newSize = 1;\n      newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]);\n    } else {\n      var didChangeSize = MakeRef(CHANGE_LENGTH);\n      var didAlter = MakeRef(DID_ALTER);\n      newRoot = updateNode(map._root, map.__ownerID, 0, undefined, k, v, didChangeSize, didAlter);\n      if (!didAlter.value) {\n        return map;\n      }\n      newSize = map.size + (didChangeSize.value ? v === NOT_SET ? -1 : 1 : 0);\n    }\n    if (map.__ownerID) {\n      map.size = newSize;\n      map._root = newRoot;\n      map.__hash = undefined;\n      map.__altered = true;\n      return map;\n    }\n    return newRoot ? makeMap(newSize, newRoot) : emptyMap();\n  }\n\n  function updateNode(node, ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {\n    if (!node) {\n      if (value === NOT_SET) {\n        return node;\n      }\n      SetRef(didAlter);\n      SetRef(didChangeSize);\n      return new ValueNode(ownerID, keyHash, [key, value]);\n    }\n    return node.update(ownerID, shift, keyHash, key, value, didChangeSize, didAlter);\n  }\n\n  function isLeafNode(node) {\n    return node.constructor === ValueNode || node.constructor === HashCollisionNode;\n  }\n\n  function mergeIntoNode(node, ownerID, shift, keyHash, entry) {\n    if (node.keyHash === keyHash) {\n      return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]);\n    }\n\n    var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK;\n    var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;\n\n    var newNode;\n    var nodes = idx1 === idx2 ?\n      [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)] :\n      ((newNode = new ValueNode(ownerID, keyHash, entry)), idx1 < idx2 ? [node, newNode] : [newNode, node]);\n\n    return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes);\n  }\n\n  function createNodes(ownerID, entries, key, value) {\n    if (!ownerID) {\n      ownerID = new OwnerID();\n    }\n    var node = new ValueNode(ownerID, hash(key), [key, value]);\n    for (var ii = 0; ii < entries.length; ii++) {\n      var entry = entries[ii];\n      node = node.update(ownerID, 0, undefined, entry[0], entry[1]);\n    }\n    return node;\n  }\n\n  function packNodes(ownerID, nodes, count, excluding) {\n    var bitmap = 0;\n    var packedII = 0;\n    var packedNodes = new Array(count);\n    for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) {\n      var node = nodes[ii];\n      if (node !== undefined && ii !== excluding) {\n        bitmap |= bit;\n        packedNodes[packedII++] = node;\n      }\n    }\n    return new BitmapIndexedNode(ownerID, bitmap, packedNodes);\n  }\n\n  function expandNodes(ownerID, nodes, bitmap, including, node) {\n    var count = 0;\n    var expandedNodes = new Array(SIZE);\n    for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) {\n      expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined;\n    }\n    expandedNodes[including] = node;\n    return new HashArrayMapNode(ownerID, count + 1, expandedNodes);\n  }\n\n  function mergeIntoMapWith(map, merger, iterables) {\n    var iters = [];\n    for (var ii = 0; ii < iterables.length; ii++) {\n      var value = iterables[ii];\n      var iter = KeyedIterable(value);\n      if (!isIterable(value)) {\n        iter = iter.map(function(v ) {return fromJS(v)});\n      }\n      iters.push(iter);\n    }\n    return mergeIntoCollectionWith(map, merger, iters);\n  }\n\n  function deepMerger(existing, value, key) {\n    return existing && existing.mergeDeep && isIterable(value) ?\n      existing.mergeDeep(value) :\n      is(existing, value) ? existing : value;\n  }\n\n  function deepMergerWith(merger) {\n    return function(existing, value, key)  {\n      if (existing && existing.mergeDeepWith && isIterable(value)) {\n        return existing.mergeDeepWith(merger, value);\n      }\n      var nextValue = merger(existing, value, key);\n      return is(existing, nextValue) ? existing : nextValue;\n    };\n  }\n\n  function mergeIntoCollectionWith(collection, merger, iters) {\n    iters = iters.filter(function(x ) {return x.size !== 0});\n    if (iters.length === 0) {\n      return collection;\n    }\n    if (collection.size === 0 && !collection.__ownerID && iters.length === 1) {\n      return collection.constructor(iters[0]);\n    }\n    return collection.withMutations(function(collection ) {\n      var mergeIntoMap = merger ?\n        function(value, key)  {\n          collection.update(key, NOT_SET, function(existing )\n            {return existing === NOT_SET ? value : merger(existing, value, key)}\n          );\n        } :\n        function(value, key)  {\n          collection.set(key, value);\n        }\n      for (var ii = 0; ii < iters.length; ii++) {\n        iters[ii].forEach(mergeIntoMap);\n      }\n    });\n  }\n\n  function updateInDeepMap(existing, keyPathIter, notSetValue, updater) {\n    var isNotSet = existing === NOT_SET;\n    var step = keyPathIter.next();\n    if (step.done) {\n      var existingValue = isNotSet ? notSetValue : existing;\n      var newValue = updater(existingValue);\n      return newValue === existingValue ? existing : newValue;\n    }\n    invariant(\n      isNotSet || (existing && existing.set),\n      'invalid keyPath'\n    );\n    var key = step.value;\n    var nextExisting = isNotSet ? NOT_SET : existing.get(key, NOT_SET);\n    var nextUpdated = updateInDeepMap(\n      nextExisting,\n      keyPathIter,\n      notSetValue,\n      updater\n    );\n    return nextUpdated === nextExisting ? existing :\n      nextUpdated === NOT_SET ? existing.remove(key) :\n      (isNotSet ? emptyMap() : existing).set(key, nextUpdated);\n  }\n\n  function popCount(x) {\n    x = x - ((x >> 1) & 0x55555555);\n    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);\n    x = (x + (x >> 4)) & 0x0f0f0f0f;\n    x = x + (x >> 8);\n    x = x + (x >> 16);\n    return x & 0x7f;\n  }\n\n  function setIn(array, idx, val, canEdit) {\n    var newArray = canEdit ? array : arrCopy(array);\n    newArray[idx] = val;\n    return newArray;\n  }\n\n  function spliceIn(array, idx, val, canEdit) {\n    var newLen = array.length + 1;\n    if (canEdit && idx + 1 === newLen) {\n      array[idx] = val;\n      return array;\n    }\n    var newArray = new Array(newLen);\n    var after = 0;\n    for (var ii = 0; ii < newLen; ii++) {\n      if (ii === idx) {\n        newArray[ii] = val;\n        after = -1;\n      } else {\n        newArray[ii] = array[ii + after];\n      }\n    }\n    return newArray;\n  }\n\n  function spliceOut(array, idx, canEdit) {\n    var newLen = array.length - 1;\n    if (canEdit && idx === newLen) {\n      array.pop();\n      return array;\n    }\n    var newArray = new Array(newLen);\n    var after = 0;\n    for (var ii = 0; ii < newLen; ii++) {\n      if (ii === idx) {\n        after = 1;\n      }\n      newArray[ii] = array[ii + after];\n    }\n    return newArray;\n  }\n\n  var MAX_ARRAY_MAP_SIZE = SIZE / 4;\n  var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;\n  var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;\n\n  createClass(List, IndexedCollection);\n\n    // @pragma Construction\n\n    function List(value) {\n      var empty = emptyList();\n      if (value === null || value === undefined) {\n        return empty;\n      }\n      if (isList(value)) {\n        return value;\n      }\n      var iter = IndexedIterable(value);\n      var size = iter.size;\n      if (size === 0) {\n        return empty;\n      }\n      assertNotInfinite(size);\n      if (size > 0 && size < SIZE) {\n        return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));\n      }\n      return empty.withMutations(function(list ) {\n        list.setSize(size);\n        iter.forEach(function(v, i)  {return list.set(i, v)});\n      });\n    }\n\n    List.of = function(/*...values*/) {\n      return this(arguments);\n    };\n\n    List.prototype.toString = function() {\n      return this.__toString('List [', ']');\n    };\n\n    // @pragma Access\n\n    List.prototype.get = function(index, notSetValue) {\n      index = wrapIndex(this, index);\n      if (index >= 0 && index < this.size) {\n        index += this._origin;\n        var node = listNodeFor(this, index);\n        return node && node.array[index & MASK];\n      }\n      return notSetValue;\n    };\n\n    // @pragma Modification\n\n    List.prototype.set = function(index, value) {\n      return updateList(this, index, value);\n    };\n\n    List.prototype.remove = function(index) {\n      return !this.has(index) ? this :\n        index === 0 ? this.shift() :\n        index === this.size - 1 ? this.pop() :\n        this.splice(index, 1);\n    };\n\n    List.prototype.insert = function(index, value) {\n      return this.splice(index, 0, value);\n    };\n\n    List.prototype.clear = function() {\n      if (this.size === 0) {\n        return this;\n      }\n      if (this.__ownerID) {\n        this.size = this._origin = this._capacity = 0;\n        this._level = SHIFT;\n        this._root = this._tail = null;\n        this.__hash = undefined;\n        this.__altered = true;\n        return this;\n      }\n      return emptyList();\n    };\n\n    List.prototype.push = function(/*...values*/) {\n      var values = arguments;\n      var oldSize = this.size;\n      return this.withMutations(function(list ) {\n        setListBounds(list, 0, oldSize + values.length);\n        for (var ii = 0; ii < values.length; ii++) {\n          list.set(oldSize + ii, values[ii]);\n        }\n      });\n    };\n\n    List.prototype.pop = function() {\n      return setListBounds(this, 0, -1);\n    };\n\n    List.prototype.unshift = function(/*...values*/) {\n      var values = arguments;\n      return this.withMutations(function(list ) {\n        setListBounds(list, -values.length);\n        for (var ii = 0; ii < values.length; ii++) {\n          list.set(ii, values[ii]);\n        }\n      });\n    };\n\n    List.prototype.shift = function() {\n      return setListBounds(this, 1);\n    };\n\n    // @pragma Composition\n\n    List.prototype.merge = function(/*...iters*/) {\n      return mergeIntoListWith(this, undefined, arguments);\n    };\n\n    List.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1);\n      return mergeIntoListWith(this, merger, iters);\n    };\n\n    List.prototype.mergeDeep = function(/*...iters*/) {\n      return mergeIntoListWith(this, deepMerger, arguments);\n    };\n\n    List.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1);\n      return mergeIntoListWith(this, deepMergerWith(merger), iters);\n    };\n\n    List.prototype.setSize = function(size) {\n      return setListBounds(this, 0, size);\n    };\n\n    // @pragma Iteration\n\n    List.prototype.slice = function(begin, end) {\n      var size = this.size;\n      if (wholeSlice(begin, end, size)) {\n        return this;\n      }\n      return setListBounds(\n        this,\n        resolveBegin(begin, size),\n        resolveEnd(end, size)\n      );\n    };\n\n    List.prototype.__iterator = function(type, reverse) {\n      var index = 0;\n      var values = iterateList(this, reverse);\n      return new Iterator(function()  {\n        var value = values();\n        return value === DONE ?\n          iteratorDone() :\n          iteratorValue(type, index++, value);\n      });\n    };\n\n    List.prototype.__iterate = function(fn, reverse) {\n      var index = 0;\n      var values = iterateList(this, reverse);\n      var value;\n      while ((value = values()) !== DONE) {\n        if (fn(value, index++, this) === false) {\n          break;\n        }\n      }\n      return index;\n    };\n\n    List.prototype.__ensureOwner = function(ownerID) {\n      if (ownerID === this.__ownerID) {\n        return this;\n      }\n      if (!ownerID) {\n        this.__ownerID = ownerID;\n        return this;\n      }\n      return makeList(this._origin, this._capacity, this._level, this._root, this._tail, ownerID, this.__hash);\n    };\n\n\n  function isList(maybeList) {\n    return !!(maybeList && maybeList[IS_LIST_SENTINEL]);\n  }\n\n  List.isList = isList;\n\n  var IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@';\n\n  var ListPrototype = List.prototype;\n  ListPrototype[IS_LIST_SENTINEL] = true;\n  ListPrototype[DELETE] = ListPrototype.remove;\n  ListPrototype.setIn = MapPrototype.setIn;\n  ListPrototype.deleteIn =\n  ListPrototype.removeIn = MapPrototype.removeIn;\n  ListPrototype.update = MapPrototype.update;\n  ListPrototype.updateIn = MapPrototype.updateIn;\n  ListPrototype.mergeIn = MapPrototype.mergeIn;\n  ListPrototype.mergeDeepIn = MapPrototype.mergeDeepIn;\n  ListPrototype.withMutations = MapPrototype.withMutations;\n  ListPrototype.asMutable = MapPrototype.asMutable;\n  ListPrototype.asImmutable = MapPrototype.asImmutable;\n  ListPrototype.wasAltered = MapPrototype.wasAltered;\n\n\n\n    function VNode(array, ownerID) {\n      this.array = array;\n      this.ownerID = ownerID;\n    }\n\n    // TODO: seems like these methods are very similar\n\n    VNode.prototype.removeBefore = function(ownerID, level, index) {\n      if (index === level ? 1 << level : 0 || this.array.length === 0) {\n        return this;\n      }\n      var originIndex = (index >>> level) & MASK;\n      if (originIndex >= this.array.length) {\n        return new VNode([], ownerID);\n      }\n      var removingFirst = originIndex === 0;\n      var newChild;\n      if (level > 0) {\n        var oldChild = this.array[originIndex];\n        newChild = oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);\n        if (newChild === oldChild && removingFirst) {\n          return this;\n        }\n      }\n      if (removingFirst && !newChild) {\n        return this;\n      }\n      var editable = editableVNode(this, ownerID);\n      if (!removingFirst) {\n        for (var ii = 0; ii < originIndex; ii++) {\n          editable.array[ii] = undefined;\n        }\n      }\n      if (newChild) {\n        editable.array[originIndex] = newChild;\n      }\n      return editable;\n    };\n\n    VNode.prototype.removeAfter = function(ownerID, level, index) {\n      if (index === (level ? 1 << level : 0) || this.array.length === 0) {\n        return this;\n      }\n      var sizeIndex = ((index - 1) >>> level) & MASK;\n      if (sizeIndex >= this.array.length) {\n        return this;\n      }\n\n      var newChild;\n      if (level > 0) {\n        var oldChild = this.array[sizeIndex];\n        newChild = oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);\n        if (newChild === oldChild && sizeIndex === this.array.length - 1) {\n          return this;\n        }\n      }\n\n      var editable = editableVNode(this, ownerID);\n      editable.array.splice(sizeIndex + 1);\n      if (newChild) {\n        editable.array[sizeIndex] = newChild;\n      }\n      return editable;\n    };\n\n\n\n  var DONE = {};\n\n  function iterateList(list, reverse) {\n    var left = list._origin;\n    var right = list._capacity;\n    var tailPos = getTailOffset(right);\n    var tail = list._tail;\n\n    return iterateNodeOrLeaf(list._root, list._level, 0);\n\n    function iterateNodeOrLeaf(node, level, offset) {\n      return level === 0 ?\n        iterateLeaf(node, offset) :\n        iterateNode(node, level, offset);\n    }\n\n    function iterateLeaf(node, offset) {\n      var array = offset === tailPos ? tail && tail.array : node && node.array;\n      var from = offset > left ? 0 : left - offset;\n      var to = right - offset;\n      if (to > SIZE) {\n        to = SIZE;\n      }\n      return function()  {\n        if (from === to) {\n          return DONE;\n        }\n        var idx = reverse ? --to : from++;\n        return array && array[idx];\n      };\n    }\n\n    function iterateNode(node, level, offset) {\n      var values;\n      var array = node && node.array;\n      var from = offset > left ? 0 : (left - offset) >> level;\n      var to = ((right - offset) >> level) + 1;\n      if (to > SIZE) {\n        to = SIZE;\n      }\n      return function()  {\n        do {\n          if (values) {\n            var value = values();\n            if (value !== DONE) {\n              return value;\n            }\n            values = null;\n          }\n          if (from === to) {\n            return DONE;\n          }\n          var idx = reverse ? --to : from++;\n          values = iterateNodeOrLeaf(\n            array && array[idx], level - SHIFT, offset + (idx << level)\n          );\n        } while (true);\n      };\n    }\n  }\n\n  function makeList(origin, capacity, level, root, tail, ownerID, hash) {\n    var list = Object.create(ListPrototype);\n    list.size = capacity - origin;\n    list._origin = origin;\n    list._capacity = capacity;\n    list._level = level;\n    list._root = root;\n    list._tail = tail;\n    list.__ownerID = ownerID;\n    list.__hash = hash;\n    list.__altered = false;\n    return list;\n  }\n\n  var EMPTY_LIST;\n  function emptyList() {\n    return EMPTY_LIST || (EMPTY_LIST = makeList(0, 0, SHIFT));\n  }\n\n  function updateList(list, index, value) {\n    index = wrapIndex(list, index);\n\n    if (index !== index) {\n      return list;\n    }\n\n    if (index >= list.size || index < 0) {\n      return list.withMutations(function(list ) {\n        index < 0 ?\n          setListBounds(list, index).set(0, value) :\n          setListBounds(list, 0, index + 1).set(index, value)\n      });\n    }\n\n    index += list._origin;\n\n    var newTail = list._tail;\n    var newRoot = list._root;\n    var didAlter = MakeRef(DID_ALTER);\n    if (index >= getTailOffset(list._capacity)) {\n      newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);\n    } else {\n      newRoot = updateVNode(newRoot, list.__ownerID, list._level, index, value, didAlter);\n    }\n\n    if (!didAlter.value) {\n      return list;\n    }\n\n    if (list.__ownerID) {\n      list._root = newRoot;\n      list._tail = newTail;\n      list.__hash = undefined;\n      list.__altered = true;\n      return list;\n    }\n    return makeList(list._origin, list._capacity, list._level, newRoot, newTail);\n  }\n\n  function updateVNode(node, ownerID, level, index, value, didAlter) {\n    var idx = (index >>> level) & MASK;\n    var nodeHas = node && idx < node.array.length;\n    if (!nodeHas && value === undefined) {\n      return node;\n    }\n\n    var newNode;\n\n    if (level > 0) {\n      var lowerNode = node && node.array[idx];\n      var newLowerNode = updateVNode(lowerNode, ownerID, level - SHIFT, index, value, didAlter);\n      if (newLowerNode === lowerNode) {\n        return node;\n      }\n      newNode = editableVNode(node, ownerID);\n      newNode.array[idx] = newLowerNode;\n      return newNode;\n    }\n\n    if (nodeHas && node.array[idx] === value) {\n      return node;\n    }\n\n    SetRef(didAlter);\n\n    newNode = editableVNode(node, ownerID);\n    if (value === undefined && idx === newNode.array.length - 1) {\n      newNode.array.pop();\n    } else {\n      newNode.array[idx] = value;\n    }\n    return newNode;\n  }\n\n  function editableVNode(node, ownerID) {\n    if (ownerID && node && ownerID === node.ownerID) {\n      return node;\n    }\n    return new VNode(node ? node.array.slice() : [], ownerID);\n  }\n\n  function listNodeFor(list, rawIndex) {\n    if (rawIndex >= getTailOffset(list._capacity)) {\n      return list._tail;\n    }\n    if (rawIndex < 1 << (list._level + SHIFT)) {\n      var node = list._root;\n      var level = list._level;\n      while (node && level > 0) {\n        node = node.array[(rawIndex >>> level) & MASK];\n        level -= SHIFT;\n      }\n      return node;\n    }\n  }\n\n  function setListBounds(list, begin, end) {\n    // Sanitize begin & end using this shorthand for ToInt32(argument)\n    // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32\n    if (begin !== undefined) {\n      begin = begin | 0;\n    }\n    if (end !== undefined) {\n      end = end | 0;\n    }\n    var owner = list.__ownerID || new OwnerID();\n    var oldOrigin = list._origin;\n    var oldCapacity = list._capacity;\n    var newOrigin = oldOrigin + begin;\n    var newCapacity = end === undefined ? oldCapacity : end < 0 ? oldCapacity + end : oldOrigin + end;\n    if (newOrigin === oldOrigin && newCapacity === oldCapacity) {\n      return list;\n    }\n\n    // If it's going to end after it starts, it's empty.\n    if (newOrigin >= newCapacity) {\n      return list.clear();\n    }\n\n    var newLevel = list._level;\n    var newRoot = list._root;\n\n    // New origin might need creating a higher root.\n    var offsetShift = 0;\n    while (newOrigin + offsetShift < 0) {\n      newRoot = new VNode(newRoot && newRoot.array.length ? [undefined, newRoot] : [], owner);\n      newLevel += SHIFT;\n      offsetShift += 1 << newLevel;\n    }\n    if (offsetShift) {\n      newOrigin += offsetShift;\n      oldOrigin += offsetShift;\n      newCapacity += offsetShift;\n      oldCapacity += offsetShift;\n    }\n\n    var oldTailOffset = getTailOffset(oldCapacity);\n    var newTailOffset = getTailOffset(newCapacity);\n\n    // New size might need creating a higher root.\n    while (newTailOffset >= 1 << (newLevel + SHIFT)) {\n      newRoot = new VNode(newRoot && newRoot.array.length ? [newRoot] : [], owner);\n      newLevel += SHIFT;\n    }\n\n    // Locate or create the new tail.\n    var oldTail = list._tail;\n    var newTail = newTailOffset < oldTailOffset ?\n      listNodeFor(list, newCapacity - 1) :\n      newTailOffset > oldTailOffset ? new VNode([], owner) : oldTail;\n\n    // Merge Tail into tree.\n    if (oldTail && newTailOffset > oldTailOffset && newOrigin < oldCapacity && oldTail.array.length) {\n      newRoot = editableVNode(newRoot, owner);\n      var node = newRoot;\n      for (var level = newLevel; level > SHIFT; level -= SHIFT) {\n        var idx = (oldTailOffset >>> level) & MASK;\n        node = node.array[idx] = editableVNode(node.array[idx], owner);\n      }\n      node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;\n    }\n\n    // If the size has been reduced, there's a chance the tail needs to be trimmed.\n    if (newCapacity < oldCapacity) {\n      newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);\n    }\n\n    // If the new origin is within the tail, then we do not need a root.\n    if (newOrigin >= newTailOffset) {\n      newOrigin -= newTailOffset;\n      newCapacity -= newTailOffset;\n      newLevel = SHIFT;\n      newRoot = null;\n      newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);\n\n    // Otherwise, if the root has been trimmed, garbage collect.\n    } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {\n      offsetShift = 0;\n\n      // Identify the new top root node of the subtree of the old root.\n      while (newRoot) {\n        var beginIndex = (newOrigin >>> newLevel) & MASK;\n        if (beginIndex !== (newTailOffset >>> newLevel) & MASK) {\n          break;\n        }\n        if (beginIndex) {\n          offsetShift += (1 << newLevel) * beginIndex;\n        }\n        newLevel -= SHIFT;\n        newRoot = newRoot.array[beginIndex];\n      }\n\n      // Trim the new sides of the new root.\n      if (newRoot && newOrigin > oldOrigin) {\n        newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);\n      }\n      if (newRoot && newTailOffset < oldTailOffset) {\n        newRoot = newRoot.removeAfter(owner, newLevel, newTailOffset - offsetShift);\n      }\n      if (offsetShift) {\n        newOrigin -= offsetShift;\n        newCapacity -= offsetShift;\n      }\n    }\n\n    if (list.__ownerID) {\n      list.size = newCapacity - newOrigin;\n      list._origin = newOrigin;\n      list._capacity = newCapacity;\n      list._level = newLevel;\n      list._root = newRoot;\n      list._tail = newTail;\n      list.__hash = undefined;\n      list.__altered = true;\n      return list;\n    }\n    return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);\n  }\n\n  function mergeIntoListWith(list, merger, iterables) {\n    var iters = [];\n    var maxSize = 0;\n    for (var ii = 0; ii < iterables.length; ii++) {\n      var value = iterables[ii];\n      var iter = IndexedIterable(value);\n      if (iter.size > maxSize) {\n        maxSize = iter.size;\n      }\n      if (!isIterable(value)) {\n        iter = iter.map(function(v ) {return fromJS(v)});\n      }\n      iters.push(iter);\n    }\n    if (maxSize > list.size) {\n      list = list.setSize(maxSize);\n    }\n    return mergeIntoCollectionWith(list, merger, iters);\n  }\n\n  function getTailOffset(size) {\n    return size < SIZE ? 0 : (((size - 1) >>> SHIFT) << SHIFT);\n  }\n\n  createClass(OrderedMap, Map);\n\n    // @pragma Construction\n\n    function OrderedMap(value) {\n      return value === null || value === undefined ? emptyOrderedMap() :\n        isOrderedMap(value) ? value :\n        emptyOrderedMap().withMutations(function(map ) {\n          var iter = KeyedIterable(value);\n          assertNotInfinite(iter.size);\n          iter.forEach(function(v, k)  {return map.set(k, v)});\n        });\n    }\n\n    OrderedMap.of = function(/*...values*/) {\n      return this(arguments);\n    };\n\n    OrderedMap.prototype.toString = function() {\n      return this.__toString('OrderedMap {', '}');\n    };\n\n    // @pragma Access\n\n    OrderedMap.prototype.get = function(k, notSetValue) {\n      var index = this._map.get(k);\n      return index !== undefined ? this._list.get(index)[1] : notSetValue;\n    };\n\n    // @pragma Modification\n\n    OrderedMap.prototype.clear = function() {\n      if (this.size === 0) {\n        return this;\n      }\n      if (this.__ownerID) {\n        this.size = 0;\n        this._map.clear();\n        this._list.clear();\n        return this;\n      }\n      return emptyOrderedMap();\n    };\n\n    OrderedMap.prototype.set = function(k, v) {\n      return updateOrderedMap(this, k, v);\n    };\n\n    OrderedMap.prototype.remove = function(k) {\n      return updateOrderedMap(this, k, NOT_SET);\n    };\n\n    OrderedMap.prototype.wasAltered = function() {\n      return this._map.wasAltered() || this._list.wasAltered();\n    };\n\n    OrderedMap.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      return this._list.__iterate(\n        function(entry ) {return entry && fn(entry[1], entry[0], this$0)},\n        reverse\n      );\n    };\n\n    OrderedMap.prototype.__iterator = function(type, reverse) {\n      return this._list.fromEntrySeq().__iterator(type, reverse);\n    };\n\n    OrderedMap.prototype.__ensureOwner = function(ownerID) {\n      if (ownerID === this.__ownerID) {\n        return this;\n      }\n      var newMap = this._map.__ensureOwner(ownerID);\n      var newList = this._list.__ensureOwner(ownerID);\n      if (!ownerID) {\n        this.__ownerID = ownerID;\n        this._map = newMap;\n        this._list = newList;\n        return this;\n      }\n      return makeOrderedMap(newMap, newList, ownerID, this.__hash);\n    };\n\n\n  function isOrderedMap(maybeOrderedMap) {\n    return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);\n  }\n\n  OrderedMap.isOrderedMap = isOrderedMap;\n\n  OrderedMap.prototype[IS_ORDERED_SENTINEL] = true;\n  OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;\n\n\n\n  function makeOrderedMap(map, list, ownerID, hash) {\n    var omap = Object.create(OrderedMap.prototype);\n    omap.size = map ? map.size : 0;\n    omap._map = map;\n    omap._list = list;\n    omap.__ownerID = ownerID;\n    omap.__hash = hash;\n    return omap;\n  }\n\n  var EMPTY_ORDERED_MAP;\n  function emptyOrderedMap() {\n    return EMPTY_ORDERED_MAP || (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()));\n  }\n\n  function updateOrderedMap(omap, k, v) {\n    var map = omap._map;\n    var list = omap._list;\n    var i = map.get(k);\n    var has = i !== undefined;\n    var newMap;\n    var newList;\n    if (v === NOT_SET) { // removed\n      if (!has) {\n        return omap;\n      }\n      if (list.size >= SIZE && list.size >= map.size * 2) {\n        newList = list.filter(function(entry, idx)  {return entry !== undefined && i !== idx});\n        newMap = newList.toKeyedSeq().map(function(entry ) {return entry[0]}).flip().toMap();\n        if (omap.__ownerID) {\n          newMap.__ownerID = newList.__ownerID = omap.__ownerID;\n        }\n      } else {\n        newMap = map.remove(k);\n        newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);\n      }\n    } else {\n      if (has) {\n        if (v === list.get(i)[1]) {\n          return omap;\n        }\n        newMap = map;\n        newList = list.set(i, [k, v]);\n      } else {\n        newMap = map.set(k, list.size);\n        newList = list.set(list.size, [k, v]);\n      }\n    }\n    if (omap.__ownerID) {\n      omap.size = newMap.size;\n      omap._map = newMap;\n      omap._list = newList;\n      omap.__hash = undefined;\n      return omap;\n    }\n    return makeOrderedMap(newMap, newList);\n  }\n\n  createClass(ToKeyedSequence, KeyedSeq);\n    function ToKeyedSequence(indexed, useKeys) {\n      this._iter = indexed;\n      this._useKeys = useKeys;\n      this.size = indexed.size;\n    }\n\n    ToKeyedSequence.prototype.get = function(key, notSetValue) {\n      return this._iter.get(key, notSetValue);\n    };\n\n    ToKeyedSequence.prototype.has = function(key) {\n      return this._iter.has(key);\n    };\n\n    ToKeyedSequence.prototype.valueSeq = function() {\n      return this._iter.valueSeq();\n    };\n\n    ToKeyedSequence.prototype.reverse = function() {var this$0 = this;\n      var reversedSequence = reverseFactory(this, true);\n      if (!this._useKeys) {\n        reversedSequence.valueSeq = function()  {return this$0._iter.toSeq().reverse()};\n      }\n      return reversedSequence;\n    };\n\n    ToKeyedSequence.prototype.map = function(mapper, context) {var this$0 = this;\n      var mappedSequence = mapFactory(this, mapper, context);\n      if (!this._useKeys) {\n        mappedSequence.valueSeq = function()  {return this$0._iter.toSeq().map(mapper, context)};\n      }\n      return mappedSequence;\n    };\n\n    ToKeyedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      var ii;\n      return this._iter.__iterate(\n        this._useKeys ?\n          function(v, k)  {return fn(v, k, this$0)} :\n          ((ii = reverse ? resolveSize(this) : 0),\n            function(v ) {return fn(v, reverse ? --ii : ii++, this$0)}),\n        reverse\n      );\n    };\n\n    ToKeyedSequence.prototype.__iterator = function(type, reverse) {\n      if (this._useKeys) {\n        return this._iter.__iterator(type, reverse);\n      }\n      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);\n      var ii = reverse ? resolveSize(this) : 0;\n      return new Iterator(function()  {\n        var step = iterator.next();\n        return step.done ? step :\n          iteratorValue(type, reverse ? --ii : ii++, step.value, step);\n      });\n    };\n\n  ToKeyedSequence.prototype[IS_ORDERED_SENTINEL] = true;\n\n\n  createClass(ToIndexedSequence, IndexedSeq);\n    function ToIndexedSequence(iter) {\n      this._iter = iter;\n      this.size = iter.size;\n    }\n\n    ToIndexedSequence.prototype.includes = function(value) {\n      return this._iter.includes(value);\n    };\n\n    ToIndexedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      var iterations = 0;\n      return this._iter.__iterate(function(v ) {return fn(v, iterations++, this$0)}, reverse);\n    };\n\n    ToIndexedSequence.prototype.__iterator = function(type, reverse) {\n      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);\n      var iterations = 0;\n      return new Iterator(function()  {\n        var step = iterator.next();\n        return step.done ? step :\n          iteratorValue(type, iterations++, step.value, step)\n      });\n    };\n\n\n\n  createClass(ToSetSequence, SetSeq);\n    function ToSetSequence(iter) {\n      this._iter = iter;\n      this.size = iter.size;\n    }\n\n    ToSetSequence.prototype.has = function(key) {\n      return this._iter.includes(key);\n    };\n\n    ToSetSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      return this._iter.__iterate(function(v ) {return fn(v, v, this$0)}, reverse);\n    };\n\n    ToSetSequence.prototype.__iterator = function(type, reverse) {\n      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);\n      return new Iterator(function()  {\n        var step = iterator.next();\n        return step.done ? step :\n          iteratorValue(type, step.value, step.value, step);\n      });\n    };\n\n\n\n  createClass(FromEntriesSequence, KeyedSeq);\n    function FromEntriesSequence(entries) {\n      this._iter = entries;\n      this.size = entries.size;\n    }\n\n    FromEntriesSequence.prototype.entrySeq = function() {\n      return this._iter.toSeq();\n    };\n\n    FromEntriesSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      return this._iter.__iterate(function(entry ) {\n        // Check if entry exists first so array access doesn't throw for holes\n        // in the parent iteration.\n        if (entry) {\n          validateEntry(entry);\n          var indexedIterable = isIterable(entry);\n          return fn(\n            indexedIterable ? entry.get(1) : entry[1],\n            indexedIterable ? entry.get(0) : entry[0],\n            this$0\n          );\n        }\n      }, reverse);\n    };\n\n    FromEntriesSequence.prototype.__iterator = function(type, reverse) {\n      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);\n      return new Iterator(function()  {\n        while (true) {\n          var step = iterator.next();\n          if (step.done) {\n            return step;\n          }\n          var entry = step.value;\n          // Check if entry exists first so array access doesn't throw for holes\n          // in the parent iteration.\n          if (entry) {\n            validateEntry(entry);\n            var indexedIterable = isIterable(entry);\n            return iteratorValue(\n              type,\n              indexedIterable ? entry.get(0) : entry[0],\n              indexedIterable ? entry.get(1) : entry[1],\n              step\n            );\n          }\n        }\n      });\n    };\n\n\n  ToIndexedSequence.prototype.cacheResult =\n  ToKeyedSequence.prototype.cacheResult =\n  ToSetSequence.prototype.cacheResult =\n  FromEntriesSequence.prototype.cacheResult =\n    cacheResultThrough;\n\n\n  function flipFactory(iterable) {\n    var flipSequence = makeSequence(iterable);\n    flipSequence._iter = iterable;\n    flipSequence.size = iterable.size;\n    flipSequence.flip = function()  {return iterable};\n    flipSequence.reverse = function () {\n      var reversedSequence = iterable.reverse.apply(this); // super.reverse()\n      reversedSequence.flip = function()  {return iterable.reverse()};\n      return reversedSequence;\n    };\n    flipSequence.has = function(key ) {return iterable.includes(key)};\n    flipSequence.includes = function(key ) {return iterable.has(key)};\n    flipSequence.cacheResult = cacheResultThrough;\n    flipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;\n      return iterable.__iterate(function(v, k)  {return fn(k, v, this$0) !== false}, reverse);\n    }\n    flipSequence.__iteratorUncached = function(type, reverse) {\n      if (type === ITERATE_ENTRIES) {\n        var iterator = iterable.__iterator(type, reverse);\n        return new Iterator(function()  {\n          var step = iterator.next();\n          if (!step.done) {\n            var k = step.value[0];\n            step.value[0] = step.value[1];\n            step.value[1] = k;\n          }\n          return step;\n        });\n      }\n      return iterable.__iterator(\n        type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,\n        reverse\n      );\n    }\n    return flipSequence;\n  }\n\n\n  function mapFactory(iterable, mapper, context) {\n    var mappedSequence = makeSequence(iterable);\n    mappedSequence.size = iterable.size;\n    mappedSequence.has = function(key ) {return iterable.has(key)};\n    mappedSequence.get = function(key, notSetValue)  {\n      var v = iterable.get(key, NOT_SET);\n      return v === NOT_SET ?\n        notSetValue :\n        mapper.call(context, v, key, iterable);\n    };\n    mappedSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;\n      return iterable.__iterate(\n        function(v, k, c)  {return fn(mapper.call(context, v, k, c), k, this$0) !== false},\n        reverse\n      );\n    }\n    mappedSequence.__iteratorUncached = function (type, reverse) {\n      var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);\n      return new Iterator(function()  {\n        var step = iterator.next();\n        if (step.done) {\n          return step;\n        }\n        var entry = step.value;\n        var key = entry[0];\n        return iteratorValue(\n          type,\n          key,\n          mapper.call(context, entry[1], key, iterable),\n          step\n        );\n      });\n    }\n    return mappedSequence;\n  }\n\n\n  function reverseFactory(iterable, useKeys) {\n    var reversedSequence = makeSequence(iterable);\n    reversedSequence._iter = iterable;\n    reversedSequence.size = iterable.size;\n    reversedSequence.reverse = function()  {return iterable};\n    if (iterable.flip) {\n      reversedSequence.flip = function () {\n        var flipSequence = flipFactory(iterable);\n        flipSequence.reverse = function()  {return iterable.flip()};\n        return flipSequence;\n      };\n    }\n    reversedSequence.get = function(key, notSetValue) \n      {return iterable.get(useKeys ? key : -1 - key, notSetValue)};\n    reversedSequence.has = function(key )\n      {return iterable.has(useKeys ? key : -1 - key)};\n    reversedSequence.includes = function(value ) {return iterable.includes(value)};\n    reversedSequence.cacheResult = cacheResultThrough;\n    reversedSequence.__iterate = function (fn, reverse) {var this$0 = this;\n      return iterable.__iterate(function(v, k)  {return fn(v, k, this$0)}, !reverse);\n    };\n    reversedSequence.__iterator =\n      function(type, reverse)  {return iterable.__iterator(type, !reverse)};\n    return reversedSequence;\n  }\n\n\n  function filterFactory(iterable, predicate, context, useKeys) {\n    var filterSequence = makeSequence(iterable);\n    if (useKeys) {\n      filterSequence.has = function(key ) {\n        var v = iterable.get(key, NOT_SET);\n        return v !== NOT_SET && !!predicate.call(context, v, key, iterable);\n      };\n      filterSequence.get = function(key, notSetValue)  {\n        var v = iterable.get(key, NOT_SET);\n        return v !== NOT_SET && predicate.call(context, v, key, iterable) ?\n          v : notSetValue;\n      };\n    }\n    filterSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;\n      var iterations = 0;\n      iterable.__iterate(function(v, k, c)  {\n        if (predicate.call(context, v, k, c)) {\n          iterations++;\n          return fn(v, useKeys ? k : iterations - 1, this$0);\n        }\n      }, reverse);\n      return iterations;\n    };\n    filterSequence.__iteratorUncached = function (type, reverse) {\n      var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);\n      var iterations = 0;\n      return new Iterator(function()  {\n        while (true) {\n          var step = iterator.next();\n          if (step.done) {\n            return step;\n          }\n          var entry = step.value;\n          var key = entry[0];\n          var value = entry[1];\n          if (predicate.call(context, value, key, iterable)) {\n            return iteratorValue(type, useKeys ? key : iterations++, value, step);\n          }\n        }\n      });\n    }\n    return filterSequence;\n  }\n\n\n  function countByFactory(iterable, grouper, context) {\n    var groups = Map().asMutable();\n    iterable.__iterate(function(v, k)  {\n      groups.update(\n        grouper.call(context, v, k, iterable),\n        0,\n        function(a ) {return a + 1}\n      );\n    });\n    return groups.asImmutable();\n  }\n\n\n  function groupByFactory(iterable, grouper, context) {\n    var isKeyedIter = isKeyed(iterable);\n    var groups = (isOrdered(iterable) ? OrderedMap() : Map()).asMutable();\n    iterable.__iterate(function(v, k)  {\n      groups.update(\n        grouper.call(context, v, k, iterable),\n        function(a ) {return (a = a || [], a.push(isKeyedIter ? [k, v] : v), a)}\n      );\n    });\n    var coerce = iterableClass(iterable);\n    return groups.map(function(arr ) {return reify(iterable, coerce(arr))});\n  }\n\n\n  function sliceFactory(iterable, begin, end, useKeys) {\n    var originalSize = iterable.size;\n\n    // Sanitize begin & end using this shorthand for ToInt32(argument)\n    // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32\n    if (begin !== undefined) {\n      begin = begin | 0;\n    }\n    if (end !== undefined) {\n      if (end === Infinity) {\n        end = originalSize;\n      } else {\n        end = end | 0;\n      }\n    }\n\n    if (wholeSlice(begin, end, originalSize)) {\n      return iterable;\n    }\n\n    var resolvedBegin = resolveBegin(begin, originalSize);\n    var resolvedEnd = resolveEnd(end, originalSize);\n\n    // begin or end will be NaN if they were provided as negative numbers and\n    // this iterable's size is unknown. In that case, cache first so there is\n    // a known size and these do not resolve to NaN.\n    if (resolvedBegin !== resolvedBegin || resolvedEnd !== resolvedEnd) {\n      return sliceFactory(iterable.toSeq().cacheResult(), begin, end, useKeys);\n    }\n\n    // Note: resolvedEnd is undefined when the original sequence's length is\n    // unknown and this slice did not supply an end and should contain all\n    // elements after resolvedBegin.\n    // In that case, resolvedSize will be NaN and sliceSize will remain undefined.\n    var resolvedSize = resolvedEnd - resolvedBegin;\n    var sliceSize;\n    if (resolvedSize === resolvedSize) {\n      sliceSize = resolvedSize < 0 ? 0 : resolvedSize;\n    }\n\n    var sliceSeq = makeSequence(iterable);\n\n    // If iterable.size is undefined, the size of the realized sliceSeq is\n    // unknown at this point unless the number of items to slice is 0\n    sliceSeq.size = sliceSize === 0 ? sliceSize : iterable.size && sliceSize || undefined;\n\n    if (!useKeys && isSeq(iterable) && sliceSize >= 0) {\n      sliceSeq.get = function (index, notSetValue) {\n        index = wrapIndex(this, index);\n        return index >= 0 && index < sliceSize ?\n          iterable.get(index + resolvedBegin, notSetValue) :\n          notSetValue;\n      }\n    }\n\n    sliceSeq.__iterateUncached = function(fn, reverse) {var this$0 = this;\n      if (sliceSize === 0) {\n        return 0;\n      }\n      if (reverse) {\n        return this.cacheResult().__iterate(fn, reverse);\n      }\n      var skipped = 0;\n      var isSkipping = true;\n      var iterations = 0;\n      iterable.__iterate(function(v, k)  {\n        if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {\n          iterations++;\n          return fn(v, useKeys ? k : iterations - 1, this$0) !== false &&\n                 iterations !== sliceSize;\n        }\n      });\n      return iterations;\n    };\n\n    sliceSeq.__iteratorUncached = function(type, reverse) {\n      if (sliceSize !== 0 && reverse) {\n        return this.cacheResult().__iterator(type, reverse);\n      }\n      // Don't bother instantiating parent iterator if taking 0.\n      var iterator = sliceSize !== 0 && iterable.__iterator(type, reverse);\n      var skipped = 0;\n      var iterations = 0;\n      return new Iterator(function()  {\n        while (skipped++ < resolvedBegin) {\n          iterator.next();\n        }\n        if (++iterations > sliceSize) {\n          return iteratorDone();\n        }\n        var step = iterator.next();\n        if (useKeys || type === ITERATE_VALUES) {\n          return step;\n        } else if (type === ITERATE_KEYS) {\n          return iteratorValue(type, iterations - 1, undefined, step);\n        } else {\n          return iteratorValue(type, iterations - 1, step.value[1], step);\n        }\n      });\n    }\n\n    return sliceSeq;\n  }\n\n\n  function takeWhileFactory(iterable, predicate, context) {\n    var takeSequence = makeSequence(iterable);\n    takeSequence.__iterateUncached = function(fn, reverse) {var this$0 = this;\n      if (reverse) {\n        return this.cacheResult().__iterate(fn, reverse);\n      }\n      var iterations = 0;\n      iterable.__iterate(function(v, k, c) \n        {return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$0)}\n      );\n      return iterations;\n    };\n    takeSequence.__iteratorUncached = function(type, reverse) {var this$0 = this;\n      if (reverse) {\n        return this.cacheResult().__iterator(type, reverse);\n      }\n      var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);\n      var iterating = true;\n      return new Iterator(function()  {\n        if (!iterating) {\n          return iteratorDone();\n        }\n        var step = iterator.next();\n        if (step.done) {\n          return step;\n        }\n        var entry = step.value;\n        var k = entry[0];\n        var v = entry[1];\n        if (!predicate.call(context, v, k, this$0)) {\n          iterating = false;\n          return iteratorDone();\n        }\n        return type === ITERATE_ENTRIES ? step :\n          iteratorValue(type, k, v, step);\n      });\n    };\n    return takeSequence;\n  }\n\n\n  function skipWhileFactory(iterable, predicate, context, useKeys) {\n    var skipSequence = makeSequence(iterable);\n    skipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;\n      if (reverse) {\n        return this.cacheResult().__iterate(fn, reverse);\n      }\n      var isSkipping = true;\n      var iterations = 0;\n      iterable.__iterate(function(v, k, c)  {\n        if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) {\n          iterations++;\n          return fn(v, useKeys ? k : iterations - 1, this$0);\n        }\n      });\n      return iterations;\n    };\n    skipSequence.__iteratorUncached = function(type, reverse) {var this$0 = this;\n      if (reverse) {\n        return this.cacheResult().__iterator(type, reverse);\n      }\n      var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);\n      var skipping = true;\n      var iterations = 0;\n      return new Iterator(function()  {\n        var step, k, v;\n        do {\n          step = iterator.next();\n          if (step.done) {\n            if (useKeys || type === ITERATE_VALUES) {\n              return step;\n            } else if (type === ITERATE_KEYS) {\n              return iteratorValue(type, iterations++, undefined, step);\n            } else {\n              return iteratorValue(type, iterations++, step.value[1], step);\n            }\n          }\n          var entry = step.value;\n          k = entry[0];\n          v = entry[1];\n          skipping && (skipping = predicate.call(context, v, k, this$0));\n        } while (skipping);\n        return type === ITERATE_ENTRIES ? step :\n          iteratorValue(type, k, v, step);\n      });\n    };\n    return skipSequence;\n  }\n\n\n  function concatFactory(iterable, values) {\n    var isKeyedIterable = isKeyed(iterable);\n    var iters = [iterable].concat(values).map(function(v ) {\n      if (!isIterable(v)) {\n        v = isKeyedIterable ?\n          keyedSeqFromValue(v) :\n          indexedSeqFromValue(Array.isArray(v) ? v : [v]);\n      } else if (isKeyedIterable) {\n        v = KeyedIterable(v);\n      }\n      return v;\n    }).filter(function(v ) {return v.size !== 0});\n\n    if (iters.length === 0) {\n      return iterable;\n    }\n\n    if (iters.length === 1) {\n      var singleton = iters[0];\n      if (singleton === iterable ||\n          isKeyedIterable && isKeyed(singleton) ||\n          isIndexed(iterable) && isIndexed(singleton)) {\n        return singleton;\n      }\n    }\n\n    var concatSeq = new ArraySeq(iters);\n    if (isKeyedIterable) {\n      concatSeq = concatSeq.toKeyedSeq();\n    } else if (!isIndexed(iterable)) {\n      concatSeq = concatSeq.toSetSeq();\n    }\n    concatSeq = concatSeq.flatten(true);\n    concatSeq.size = iters.reduce(\n      function(sum, seq)  {\n        if (sum !== undefined) {\n          var size = seq.size;\n          if (size !== undefined) {\n            return sum + size;\n          }\n        }\n      },\n      0\n    );\n    return concatSeq;\n  }\n\n\n  function flattenFactory(iterable, depth, useKeys) {\n    var flatSequence = makeSequence(iterable);\n    flatSequence.__iterateUncached = function(fn, reverse) {\n      var iterations = 0;\n      var stopped = false;\n      function flatDeep(iter, currentDepth) {var this$0 = this;\n        iter.__iterate(function(v, k)  {\n          if ((!depth || currentDepth < depth) && isIterable(v)) {\n            flatDeep(v, currentDepth + 1);\n          } else if (fn(v, useKeys ? k : iterations++, this$0) === false) {\n            stopped = true;\n          }\n          return !stopped;\n        }, reverse);\n      }\n      flatDeep(iterable, 0);\n      return iterations;\n    }\n    flatSequence.__iteratorUncached = function(type, reverse) {\n      var iterator = iterable.__iterator(type, reverse);\n      var stack = [];\n      var iterations = 0;\n      return new Iterator(function()  {\n        while (iterator) {\n          var step = iterator.next();\n          if (step.done !== false) {\n            iterator = stack.pop();\n            continue;\n          }\n          var v = step.value;\n          if (type === ITERATE_ENTRIES) {\n            v = v[1];\n          }\n          if ((!depth || stack.length < depth) && isIterable(v)) {\n            stack.push(iterator);\n            iterator = v.__iterator(type, reverse);\n          } else {\n            return useKeys ? step : iteratorValue(type, iterations++, v, step);\n          }\n        }\n        return iteratorDone();\n      });\n    }\n    return flatSequence;\n  }\n\n\n  function flatMapFactory(iterable, mapper, context) {\n    var coerce = iterableClass(iterable);\n    return iterable.toSeq().map(\n      function(v, k)  {return coerce(mapper.call(context, v, k, iterable))}\n    ).flatten(true);\n  }\n\n\n  function interposeFactory(iterable, separator) {\n    var interposedSequence = makeSequence(iterable);\n    interposedSequence.size = iterable.size && iterable.size * 2 -1;\n    interposedSequence.__iterateUncached = function(fn, reverse) {var this$0 = this;\n      var iterations = 0;\n      iterable.__iterate(function(v, k) \n        {return (!iterations || fn(separator, iterations++, this$0) !== false) &&\n        fn(v, iterations++, this$0) !== false},\n        reverse\n      );\n      return iterations;\n    };\n    interposedSequence.__iteratorUncached = function(type, reverse) {\n      var iterator = iterable.__iterator(ITERATE_VALUES, reverse);\n      var iterations = 0;\n      var step;\n      return new Iterator(function()  {\n        if (!step || iterations % 2) {\n          step = iterator.next();\n          if (step.done) {\n            return step;\n          }\n        }\n        return iterations % 2 ?\n          iteratorValue(type, iterations++, separator) :\n          iteratorValue(type, iterations++, step.value, step);\n      });\n    };\n    return interposedSequence;\n  }\n\n\n  function sortFactory(iterable, comparator, mapper) {\n    if (!comparator) {\n      comparator = defaultComparator;\n    }\n    var isKeyedIterable = isKeyed(iterable);\n    var index = 0;\n    var entries = iterable.toSeq().map(\n      function(v, k)  {return [k, v, index++, mapper ? mapper(v, k, iterable) : v]}\n    ).toArray();\n    entries.sort(function(a, b)  {return comparator(a[3], b[3]) || a[2] - b[2]}).forEach(\n      isKeyedIterable ?\n      function(v, i)  { entries[i].length = 2; } :\n      function(v, i)  { entries[i] = v[1]; }\n    );\n    return isKeyedIterable ? KeyedSeq(entries) :\n      isIndexed(iterable) ? IndexedSeq(entries) :\n      SetSeq(entries);\n  }\n\n\n  function maxFactory(iterable, comparator, mapper) {\n    if (!comparator) {\n      comparator = defaultComparator;\n    }\n    if (mapper) {\n      var entry = iterable.toSeq()\n        .map(function(v, k)  {return [v, mapper(v, k, iterable)]})\n        .reduce(function(a, b)  {return maxCompare(comparator, a[1], b[1]) ? b : a});\n      return entry && entry[0];\n    } else {\n      return iterable.reduce(function(a, b)  {return maxCompare(comparator, a, b) ? b : a});\n    }\n  }\n\n  function maxCompare(comparator, a, b) {\n    var comp = comparator(b, a);\n    // b is considered the new max if the comparator declares them equal, but\n    // they are not equal and b is in fact a nullish value.\n    return (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) || comp > 0;\n  }\n\n\n  function zipWithFactory(keyIter, zipper, iters) {\n    var zipSequence = makeSequence(keyIter);\n    zipSequence.size = new ArraySeq(iters).map(function(i ) {return i.size}).min();\n    // Note: this a generic base implementation of __iterate in terms of\n    // __iterator which may be more generically useful in the future.\n    zipSequence.__iterate = function(fn, reverse) {\n      /* generic:\n      var iterator = this.__iterator(ITERATE_ENTRIES, reverse);\n      var step;\n      var iterations = 0;\n      while (!(step = iterator.next()).done) {\n        iterations++;\n        if (fn(step.value[1], step.value[0], this) === false) {\n          break;\n        }\n      }\n      return iterations;\n      */\n      // indexed:\n      var iterator = this.__iterator(ITERATE_VALUES, reverse);\n      var step;\n      var iterations = 0;\n      while (!(step = iterator.next()).done) {\n        if (fn(step.value, iterations++, this) === false) {\n          break;\n        }\n      }\n      return iterations;\n    };\n    zipSequence.__iteratorUncached = function(type, reverse) {\n      var iterators = iters.map(function(i )\n        {return (i = Iterable(i), getIterator(reverse ? i.reverse() : i))}\n      );\n      var iterations = 0;\n      var isDone = false;\n      return new Iterator(function()  {\n        var steps;\n        if (!isDone) {\n          steps = iterators.map(function(i ) {return i.next()});\n          isDone = steps.some(function(s ) {return s.done});\n        }\n        if (isDone) {\n          return iteratorDone();\n        }\n        return iteratorValue(\n          type,\n          iterations++,\n          zipper.apply(null, steps.map(function(s ) {return s.value}))\n        );\n      });\n    };\n    return zipSequence\n  }\n\n\n  // #pragma Helper Functions\n\n  function reify(iter, seq) {\n    return isSeq(iter) ? seq : iter.constructor(seq);\n  }\n\n  function validateEntry(entry) {\n    if (entry !== Object(entry)) {\n      throw new TypeError('Expected [K, V] tuple: ' + entry);\n    }\n  }\n\n  function resolveSize(iter) {\n    assertNotInfinite(iter.size);\n    return ensureSize(iter);\n  }\n\n  function iterableClass(iterable) {\n    return isKeyed(iterable) ? KeyedIterable :\n      isIndexed(iterable) ? IndexedIterable :\n      SetIterable;\n  }\n\n  function makeSequence(iterable) {\n    return Object.create(\n      (\n        isKeyed(iterable) ? KeyedSeq :\n        isIndexed(iterable) ? IndexedSeq :\n        SetSeq\n      ).prototype\n    );\n  }\n\n  function cacheResultThrough() {\n    if (this._iter.cacheResult) {\n      this._iter.cacheResult();\n      this.size = this._iter.size;\n      return this;\n    } else {\n      return Seq.prototype.cacheResult.call(this);\n    }\n  }\n\n  function defaultComparator(a, b) {\n    return a > b ? 1 : a < b ? -1 : 0;\n  }\n\n  function forceIterator(keyPath) {\n    var iter = getIterator(keyPath);\n    if (!iter) {\n      // Array might not be iterable in this environment, so we need a fallback\n      // to our wrapped type.\n      if (!isArrayLike(keyPath)) {\n        throw new TypeError('Expected iterable or array-like: ' + keyPath);\n      }\n      iter = getIterator(Iterable(keyPath));\n    }\n    return iter;\n  }\n\n  createClass(Record, KeyedCollection);\n\n    function Record(defaultValues, name) {\n      var hasInitialized;\n\n      var RecordType = function Record(values) {\n        if (values instanceof RecordType) {\n          return values;\n        }\n        if (!(this instanceof RecordType)) {\n          return new RecordType(values);\n        }\n        if (!hasInitialized) {\n          hasInitialized = true;\n          var keys = Object.keys(defaultValues);\n          setProps(RecordTypePrototype, keys);\n          RecordTypePrototype.size = keys.length;\n          RecordTypePrototype._name = name;\n          RecordTypePrototype._keys = keys;\n          RecordTypePrototype._defaultValues = defaultValues;\n        }\n        this._map = Map(values);\n      };\n\n      var RecordTypePrototype = RecordType.prototype = Object.create(RecordPrototype);\n      RecordTypePrototype.constructor = RecordType;\n\n      return RecordType;\n    }\n\n    Record.prototype.toString = function() {\n      return this.__toString(recordName(this) + ' {', '}');\n    };\n\n    // @pragma Access\n\n    Record.prototype.has = function(k) {\n      return this._defaultValues.hasOwnProperty(k);\n    };\n\n    Record.prototype.get = function(k, notSetValue) {\n      if (!this.has(k)) {\n        return notSetValue;\n      }\n      var defaultVal = this._defaultValues[k];\n      return this._map ? this._map.get(k, defaultVal) : defaultVal;\n    };\n\n    // @pragma Modification\n\n    Record.prototype.clear = function() {\n      if (this.__ownerID) {\n        this._map && this._map.clear();\n        return this;\n      }\n      var RecordType = this.constructor;\n      return RecordType._empty || (RecordType._empty = makeRecord(this, emptyMap()));\n    };\n\n    Record.prototype.set = function(k, v) {\n      if (!this.has(k)) {\n        throw new Error('Cannot set unknown key \"' + k + '\" on ' + recordName(this));\n      }\n      if (this._map && !this._map.has(k)) {\n        var defaultVal = this._defaultValues[k];\n        if (v === defaultVal) {\n          return this;\n        }\n      }\n      var newMap = this._map && this._map.set(k, v);\n      if (this.__ownerID || newMap === this._map) {\n        return this;\n      }\n      return makeRecord(this, newMap);\n    };\n\n    Record.prototype.remove = function(k) {\n      if (!this.has(k)) {\n        return this;\n      }\n      var newMap = this._map && this._map.remove(k);\n      if (this.__ownerID || newMap === this._map) {\n        return this;\n      }\n      return makeRecord(this, newMap);\n    };\n\n    Record.prototype.wasAltered = function() {\n      return this._map.wasAltered();\n    };\n\n    Record.prototype.__iterator = function(type, reverse) {var this$0 = this;\n      return KeyedIterable(this._defaultValues).map(function(_, k)  {return this$0.get(k)}).__iterator(type, reverse);\n    };\n\n    Record.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      return KeyedIterable(this._defaultValues).map(function(_, k)  {return this$0.get(k)}).__iterate(fn, reverse);\n    };\n\n    Record.prototype.__ensureOwner = function(ownerID) {\n      if (ownerID === this.__ownerID) {\n        return this;\n      }\n      var newMap = this._map && this._map.__ensureOwner(ownerID);\n      if (!ownerID) {\n        this.__ownerID = ownerID;\n        this._map = newMap;\n        return this;\n      }\n      return makeRecord(this, newMap, ownerID);\n    };\n\n\n  var RecordPrototype = Record.prototype;\n  RecordPrototype[DELETE] = RecordPrototype.remove;\n  RecordPrototype.deleteIn =\n  RecordPrototype.removeIn = MapPrototype.removeIn;\n  RecordPrototype.merge = MapPrototype.merge;\n  RecordPrototype.mergeWith = MapPrototype.mergeWith;\n  RecordPrototype.mergeIn = MapPrototype.mergeIn;\n  RecordPrototype.mergeDeep = MapPrototype.mergeDeep;\n  RecordPrototype.mergeDeepWith = MapPrototype.mergeDeepWith;\n  RecordPrototype.mergeDeepIn = MapPrototype.mergeDeepIn;\n  RecordPrototype.setIn = MapPrototype.setIn;\n  RecordPrototype.update = MapPrototype.update;\n  RecordPrototype.updateIn = MapPrototype.updateIn;\n  RecordPrototype.withMutations = MapPrototype.withMutations;\n  RecordPrototype.asMutable = MapPrototype.asMutable;\n  RecordPrototype.asImmutable = MapPrototype.asImmutable;\n\n\n  function makeRecord(likeRecord, map, ownerID) {\n    var record = Object.create(Object.getPrototypeOf(likeRecord));\n    record._map = map;\n    record.__ownerID = ownerID;\n    return record;\n  }\n\n  function recordName(record) {\n    return record._name || record.constructor.name || 'Record';\n  }\n\n  function setProps(prototype, names) {\n    try {\n      names.forEach(setProp.bind(undefined, prototype));\n    } catch (error) {\n      // Object.defineProperty failed. Probably IE8.\n    }\n  }\n\n  function setProp(prototype, name) {\n    Object.defineProperty(prototype, name, {\n      get: function() {\n        return this.get(name);\n      },\n      set: function(value) {\n        invariant(this.__ownerID, 'Cannot set on an immutable record.');\n        this.set(name, value);\n      }\n    });\n  }\n\n  createClass(Set, SetCollection);\n\n    // @pragma Construction\n\n    function Set(value) {\n      return value === null || value === undefined ? emptySet() :\n        isSet(value) && !isOrdered(value) ? value :\n        emptySet().withMutations(function(set ) {\n          var iter = SetIterable(value);\n          assertNotInfinite(iter.size);\n          iter.forEach(function(v ) {return set.add(v)});\n        });\n    }\n\n    Set.of = function(/*...values*/) {\n      return this(arguments);\n    };\n\n    Set.fromKeys = function(value) {\n      return this(KeyedIterable(value).keySeq());\n    };\n\n    Set.prototype.toString = function() {\n      return this.__toString('Set {', '}');\n    };\n\n    // @pragma Access\n\n    Set.prototype.has = function(value) {\n      return this._map.has(value);\n    };\n\n    // @pragma Modification\n\n    Set.prototype.add = function(value) {\n      return updateSet(this, this._map.set(value, true));\n    };\n\n    Set.prototype.remove = function(value) {\n      return updateSet(this, this._map.remove(value));\n    };\n\n    Set.prototype.clear = function() {\n      return updateSet(this, this._map.clear());\n    };\n\n    // @pragma Composition\n\n    Set.prototype.union = function() {var iters = SLICE$0.call(arguments, 0);\n      iters = iters.filter(function(x ) {return x.size !== 0});\n      if (iters.length === 0) {\n        return this;\n      }\n      if (this.size === 0 && !this.__ownerID && iters.length === 1) {\n        return this.constructor(iters[0]);\n      }\n      return this.withMutations(function(set ) {\n        for (var ii = 0; ii < iters.length; ii++) {\n          SetIterable(iters[ii]).forEach(function(value ) {return set.add(value)});\n        }\n      });\n    };\n\n    Set.prototype.intersect = function() {var iters = SLICE$0.call(arguments, 0);\n      if (iters.length === 0) {\n        return this;\n      }\n      iters = iters.map(function(iter ) {return SetIterable(iter)});\n      var originalSet = this;\n      return this.withMutations(function(set ) {\n        originalSet.forEach(function(value ) {\n          if (!iters.every(function(iter ) {return iter.includes(value)})) {\n            set.remove(value);\n          }\n        });\n      });\n    };\n\n    Set.prototype.subtract = function() {var iters = SLICE$0.call(arguments, 0);\n      if (iters.length === 0) {\n        return this;\n      }\n      iters = iters.map(function(iter ) {return SetIterable(iter)});\n      var originalSet = this;\n      return this.withMutations(function(set ) {\n        originalSet.forEach(function(value ) {\n          if (iters.some(function(iter ) {return iter.includes(value)})) {\n            set.remove(value);\n          }\n        });\n      });\n    };\n\n    Set.prototype.merge = function() {\n      return this.union.apply(this, arguments);\n    };\n\n    Set.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1);\n      return this.union.apply(this, iters);\n    };\n\n    Set.prototype.sort = function(comparator) {\n      // Late binding\n      return OrderedSet(sortFactory(this, comparator));\n    };\n\n    Set.prototype.sortBy = function(mapper, comparator) {\n      // Late binding\n      return OrderedSet(sortFactory(this, comparator, mapper));\n    };\n\n    Set.prototype.wasAltered = function() {\n      return this._map.wasAltered();\n    };\n\n    Set.prototype.__iterate = function(fn, reverse) {var this$0 = this;\n      return this._map.__iterate(function(_, k)  {return fn(k, k, this$0)}, reverse);\n    };\n\n    Set.prototype.__iterator = function(type, reverse) {\n      return this._map.map(function(_, k)  {return k}).__iterator(type, reverse);\n    };\n\n    Set.prototype.__ensureOwner = function(ownerID) {\n      if (ownerID === this.__ownerID) {\n        return this;\n      }\n      var newMap = this._map.__ensureOwner(ownerID);\n      if (!ownerID) {\n        this.__ownerID = ownerID;\n        this._map = newMap;\n        return this;\n      }\n      return this.__make(newMap, ownerID);\n    };\n\n\n  function isSet(maybeSet) {\n    return !!(maybeSet && maybeSet[IS_SET_SENTINEL]);\n  }\n\n  Set.isSet = isSet;\n\n  var IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';\n\n  var SetPrototype = Set.prototype;\n  SetPrototype[IS_SET_SENTINEL] = true;\n  SetPrototype[DELETE] = SetPrototype.remove;\n  SetPrototype.mergeDeep = SetPrototype.merge;\n  SetPrototype.mergeDeepWith = SetPrototype.mergeWith;\n  SetPrototype.withMutations = MapPrototype.withMutations;\n  SetPrototype.asMutable = MapPrototype.asMutable;\n  SetPrototype.asImmutable = MapPrototype.asImmutable;\n\n  SetPrototype.__empty = emptySet;\n  SetPrototype.__make = makeSet;\n\n  function updateSet(set, newMap) {\n    if (set.__ownerID) {\n      set.size = newMap.size;\n      set._map = newMap;\n      return set;\n    }\n    return newMap === set._map ? set :\n      newMap.size === 0 ? set.__empty() :\n      set.__make(newMap);\n  }\n\n  function makeSet(map, ownerID) {\n    var set = Object.create(SetPrototype);\n    set.size = map ? map.size : 0;\n    set._map = map;\n    set.__ownerID = ownerID;\n    return set;\n  }\n\n  var EMPTY_SET;\n  function emptySet() {\n    return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap()));\n  }\n\n  createClass(OrderedSet, Set);\n\n    // @pragma Construction\n\n    function OrderedSet(value) {\n      return value === null || value === undefined ? emptyOrderedSet() :\n        isOrderedSet(value) ? value :\n        emptyOrderedSet().withMutations(function(set ) {\n          var iter = SetIterable(value);\n          assertNotInfinite(iter.size);\n          iter.forEach(function(v ) {return set.add(v)});\n        });\n    }\n\n    OrderedSet.of = function(/*...values*/) {\n      return this(arguments);\n    };\n\n    OrderedSet.fromKeys = function(value) {\n      return this(KeyedIterable(value).keySeq());\n    };\n\n    OrderedSet.prototype.toString = function() {\n      return this.__toString('OrderedSet {', '}');\n    };\n\n\n  function isOrderedSet(maybeOrderedSet) {\n    return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);\n  }\n\n  OrderedSet.isOrderedSet = isOrderedSet;\n\n  var OrderedSetPrototype = OrderedSet.prototype;\n  OrderedSetPrototype[IS_ORDERED_SENTINEL] = true;\n\n  OrderedSetPrototype.__empty = emptyOrderedSet;\n  OrderedSetPrototype.__make = makeOrderedSet;\n\n  function makeOrderedSet(map, ownerID) {\n    var set = Object.create(OrderedSetPrototype);\n    set.size = map ? map.size : 0;\n    set._map = map;\n    set.__ownerID = ownerID;\n    return set;\n  }\n\n  var EMPTY_ORDERED_SET;\n  function emptyOrderedSet() {\n    return EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap()));\n  }\n\n  createClass(Stack, IndexedCollection);\n\n    // @pragma Construction\n\n    function Stack(value) {\n      return value === null || value === undefined ? emptyStack() :\n        isStack(value) ? value :\n        emptyStack().unshiftAll(value);\n    }\n\n    Stack.of = function(/*...values*/) {\n      return this(arguments);\n    };\n\n    Stack.prototype.toString = function() {\n      return this.__toString('Stack [', ']');\n    };\n\n    // @pragma Access\n\n    Stack.prototype.get = function(index, notSetValue) {\n      var head = this._head;\n      index = wrapIndex(this, index);\n      while (head && index--) {\n        head = head.next;\n      }\n      return head ? head.value : notSetValue;\n    };\n\n    Stack.prototype.peek = function() {\n      return this._head && this._head.value;\n    };\n\n    // @pragma Modification\n\n    Stack.prototype.push = function(/*...values*/) {\n      if (arguments.length === 0) {\n        return this;\n      }\n      var newSize = this.size + arguments.length;\n      var head = this._head;\n      for (var ii = arguments.length - 1; ii >= 0; ii--) {\n        head = {\n          value: arguments[ii],\n          next: head\n        };\n      }\n      if (this.__ownerID) {\n        this.size = newSize;\n        this._head = head;\n        this.__hash = undefined;\n        this.__altered = true;\n        return this;\n      }\n      return makeStack(newSize, head);\n    };\n\n    Stack.prototype.pushAll = function(iter) {\n      iter = IndexedIterable(iter);\n      if (iter.size === 0) {\n        return this;\n      }\n      assertNotInfinite(iter.size);\n      var newSize = this.size;\n      var head = this._head;\n      iter.reverse().forEach(function(value ) {\n        newSize++;\n        head = {\n          value: value,\n          next: head\n        };\n      });\n      if (this.__ownerID) {\n        this.size = newSize;\n        this._head = head;\n        this.__hash = undefined;\n        this.__altered = true;\n        return this;\n      }\n      return makeStack(newSize, head);\n    };\n\n    Stack.prototype.pop = function() {\n      return this.slice(1);\n    };\n\n    Stack.prototype.unshift = function(/*...values*/) {\n      return this.push.apply(this, arguments);\n    };\n\n    Stack.prototype.unshiftAll = function(iter) {\n      return this.pushAll(iter);\n    };\n\n    Stack.prototype.shift = function() {\n      return this.pop.apply(this, arguments);\n    };\n\n    Stack.prototype.clear = function() {\n      if (this.size === 0) {\n        return this;\n      }\n      if (this.__ownerID) {\n        this.size = 0;\n        this._head = undefined;\n        this.__hash = undefined;\n        this.__altered = true;\n        return this;\n      }\n      return emptyStack();\n    };\n\n    Stack.prototype.slice = function(begin, end) {\n      if (wholeSlice(begin, end, this.size)) {\n        return this;\n      }\n      var resolvedBegin = resolveBegin(begin, this.size);\n      var resolvedEnd = resolveEnd(end, this.size);\n      if (resolvedEnd !== this.size) {\n        // super.slice(begin, end);\n        return IndexedCollection.prototype.slice.call(this, begin, end);\n      }\n      var newSize = this.size - resolvedBegin;\n      var head = this._head;\n      while (resolvedBegin--) {\n        head = head.next;\n      }\n      if (this.__ownerID) {\n        this.size = newSize;\n        this._head = head;\n        this.__hash = undefined;\n        this.__altered = true;\n        return this;\n      }\n      return makeStack(newSize, head);\n    };\n\n    // @pragma Mutability\n\n    Stack.prototype.__ensureOwner = function(ownerID) {\n      if (ownerID === this.__ownerID) {\n        return this;\n      }\n      if (!ownerID) {\n        this.__ownerID = ownerID;\n        this.__altered = false;\n        return this;\n      }\n      return makeStack(this.size, this._head, ownerID, this.__hash);\n    };\n\n    // @pragma Iteration\n\n    Stack.prototype.__iterate = function(fn, reverse) {\n      if (reverse) {\n        return this.reverse().__iterate(fn);\n      }\n      var iterations = 0;\n      var node = this._head;\n      while (node) {\n        if (fn(node.value, iterations++, this) === false) {\n          break;\n        }\n        node = node.next;\n      }\n      return iterations;\n    };\n\n    Stack.prototype.__iterator = function(type, reverse) {\n      if (reverse) {\n        return this.reverse().__iterator(type);\n      }\n      var iterations = 0;\n      var node = this._head;\n      return new Iterator(function()  {\n        if (node) {\n          var value = node.value;\n          node = node.next;\n          return iteratorValue(type, iterations++, value);\n        }\n        return iteratorDone();\n      });\n    };\n\n\n  function isStack(maybeStack) {\n    return !!(maybeStack && maybeStack[IS_STACK_SENTINEL]);\n  }\n\n  Stack.isStack = isStack;\n\n  var IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@';\n\n  var StackPrototype = Stack.prototype;\n  StackPrototype[IS_STACK_SENTINEL] = true;\n  StackPrototype.withMutations = MapPrototype.withMutations;\n  StackPrototype.asMutable = MapPrototype.asMutable;\n  StackPrototype.asImmutable = MapPrototype.asImmutable;\n  StackPrototype.wasAltered = MapPrototype.wasAltered;\n\n\n  function makeStack(size, head, ownerID, hash) {\n    var map = Object.create(StackPrototype);\n    map.size = size;\n    map._head = head;\n    map.__ownerID = ownerID;\n    map.__hash = hash;\n    map.__altered = false;\n    return map;\n  }\n\n  var EMPTY_STACK;\n  function emptyStack() {\n    return EMPTY_STACK || (EMPTY_STACK = makeStack(0));\n  }\n\n  /**\n   * Contributes additional methods to a constructor\n   */\n  function mixin(ctor, methods) {\n    var keyCopier = function(key ) { ctor.prototype[key] = methods[key]; };\n    Object.keys(methods).forEach(keyCopier);\n    Object.getOwnPropertySymbols &&\n      Object.getOwnPropertySymbols(methods).forEach(keyCopier);\n    return ctor;\n  }\n\n  Iterable.Iterator = Iterator;\n\n  mixin(Iterable, {\n\n    // ### Conversion to other types\n\n    toArray: function() {\n      assertNotInfinite(this.size);\n      var array = new Array(this.size || 0);\n      this.valueSeq().__iterate(function(v, i)  { array[i] = v; });\n      return array;\n    },\n\n    toIndexedSeq: function() {\n      return new ToIndexedSequence(this);\n    },\n\n    toJS: function() {\n      return this.toSeq().map(\n        function(value ) {return value && typeof value.toJS === 'function' ? value.toJS() : value}\n      ).__toJS();\n    },\n\n    toJSON: function() {\n      return this.toSeq().map(\n        function(value ) {return value && typeof value.toJSON === 'function' ? value.toJSON() : value}\n      ).__toJS();\n    },\n\n    toKeyedSeq: function() {\n      return new ToKeyedSequence(this, true);\n    },\n\n    toMap: function() {\n      // Use Late Binding here to solve the circular dependency.\n      return Map(this.toKeyedSeq());\n    },\n\n    toObject: function() {\n      assertNotInfinite(this.size);\n      var object = {};\n      this.__iterate(function(v, k)  { object[k] = v; });\n      return object;\n    },\n\n    toOrderedMap: function() {\n      // Use Late Binding here to solve the circular dependency.\n      return OrderedMap(this.toKeyedSeq());\n    },\n\n    toOrderedSet: function() {\n      // Use Late Binding here to solve the circular dependency.\n      return OrderedSet(isKeyed(this) ? this.valueSeq() : this);\n    },\n\n    toSet: function() {\n      // Use Late Binding here to solve the circular dependency.\n      return Set(isKeyed(this) ? this.valueSeq() : this);\n    },\n\n    toSetSeq: function() {\n      return new ToSetSequence(this);\n    },\n\n    toSeq: function() {\n      return isIndexed(this) ? this.toIndexedSeq() :\n        isKeyed(this) ? this.toKeyedSeq() :\n        this.toSetSeq();\n    },\n\n    toStack: function() {\n      // Use Late Binding here to solve the circular dependency.\n      return Stack(isKeyed(this) ? this.valueSeq() : this);\n    },\n\n    toList: function() {\n      // Use Late Binding here to solve the circular dependency.\n      return List(isKeyed(this) ? this.valueSeq() : this);\n    },\n\n\n    // ### Common JavaScript methods and properties\n\n    toString: function() {\n      return '[Iterable]';\n    },\n\n    __toString: function(head, tail) {\n      if (this.size === 0) {\n        return head + tail;\n      }\n      return head + ' ' + this.toSeq().map(this.__toStringMapper).join(', ') + ' ' + tail;\n    },\n\n\n    // ### ES6 Collection methods (ES6 Array and Map)\n\n    concat: function() {var values = SLICE$0.call(arguments, 0);\n      return reify(this, concatFactory(this, values));\n    },\n\n    includes: function(searchValue) {\n      return this.some(function(value ) {return is(value, searchValue)});\n    },\n\n    entries: function() {\n      return this.__iterator(ITERATE_ENTRIES);\n    },\n\n    every: function(predicate, context) {\n      assertNotInfinite(this.size);\n      var returnValue = true;\n      this.__iterate(function(v, k, c)  {\n        if (!predicate.call(context, v, k, c)) {\n          returnValue = false;\n          return false;\n        }\n      });\n      return returnValue;\n    },\n\n    filter: function(predicate, context) {\n      return reify(this, filterFactory(this, predicate, context, true));\n    },\n\n    find: function(predicate, context, notSetValue) {\n      var entry = this.findEntry(predicate, context);\n      return entry ? entry[1] : notSetValue;\n    },\n\n    forEach: function(sideEffect, context) {\n      assertNotInfinite(this.size);\n      return this.__iterate(context ? sideEffect.bind(context) : sideEffect);\n    },\n\n    join: function(separator) {\n      assertNotInfinite(this.size);\n      separator = separator !== undefined ? '' + separator : ',';\n      var joined = '';\n      var isFirst = true;\n      this.__iterate(function(v ) {\n        isFirst ? (isFirst = false) : (joined += separator);\n        joined += v !== null && v !== undefined ? v.toString() : '';\n      });\n      return joined;\n    },\n\n    keys: function() {\n      return this.__iterator(ITERATE_KEYS);\n    },\n\n    map: function(mapper, context) {\n      return reify(this, mapFactory(this, mapper, context));\n    },\n\n    reduce: function(reducer, initialReduction, context) {\n      assertNotInfinite(this.size);\n      var reduction;\n      var useFirst;\n      if (arguments.length < 2) {\n        useFirst = true;\n      } else {\n        reduction = initialReduction;\n      }\n      this.__iterate(function(v, k, c)  {\n        if (useFirst) {\n          useFirst = false;\n          reduction = v;\n        } else {\n          reduction = reducer.call(context, reduction, v, k, c);\n        }\n      });\n      return reduction;\n    },\n\n    reduceRight: function(reducer, initialReduction, context) {\n      var reversed = this.toKeyedSeq().reverse();\n      return reversed.reduce.apply(reversed, arguments);\n    },\n\n    reverse: function() {\n      return reify(this, reverseFactory(this, true));\n    },\n\n    slice: function(begin, end) {\n      return reify(this, sliceFactory(this, begin, end, true));\n    },\n\n    some: function(predicate, context) {\n      return !this.every(not(predicate), context);\n    },\n\n    sort: function(comparator) {\n      return reify(this, sortFactory(this, comparator));\n    },\n\n    values: function() {\n      return this.__iterator(ITERATE_VALUES);\n    },\n\n\n    // ### More sequential methods\n\n    butLast: function() {\n      return this.slice(0, -1);\n    },\n\n    isEmpty: function() {\n      return this.size !== undefined ? this.size === 0 : !this.some(function()  {return true});\n    },\n\n    count: function(predicate, context) {\n      return ensureSize(\n        predicate ? this.toSeq().filter(predicate, context) : this\n      );\n    },\n\n    countBy: function(grouper, context) {\n      return countByFactory(this, grouper, context);\n    },\n\n    equals: function(other) {\n      return deepEqual(this, other);\n    },\n\n    entrySeq: function() {\n      var iterable = this;\n      if (iterable._cache) {\n        // We cache as an entries array, so we can just return the cache!\n        return new ArraySeq(iterable._cache);\n      }\n      var entriesSequence = iterable.toSeq().map(entryMapper).toIndexedSeq();\n      entriesSequence.fromEntrySeq = function()  {return iterable.toSeq()};\n      return entriesSequence;\n    },\n\n    filterNot: function(predicate, context) {\n      return this.filter(not(predicate), context);\n    },\n\n    findEntry: function(predicate, context, notSetValue) {\n      var found = notSetValue;\n      this.__iterate(function(v, k, c)  {\n        if (predicate.call(context, v, k, c)) {\n          found = [k, v];\n          return false;\n        }\n      });\n      return found;\n    },\n\n    findKey: function(predicate, context) {\n      var entry = this.findEntry(predicate, context);\n      return entry && entry[0];\n    },\n\n    findLast: function(predicate, context, notSetValue) {\n      return this.toKeyedSeq().reverse().find(predicate, context, notSetValue);\n    },\n\n    findLastEntry: function(predicate, context, notSetValue) {\n      return this.toKeyedSeq().reverse().findEntry(predicate, context, notSetValue);\n    },\n\n    findLastKey: function(predicate, context) {\n      return this.toKeyedSeq().reverse().findKey(predicate, context);\n    },\n\n    first: function() {\n      return this.find(returnTrue);\n    },\n\n    flatMap: function(mapper, context) {\n      return reify(this, flatMapFactory(this, mapper, context));\n    },\n\n    flatten: function(depth) {\n      return reify(this, flattenFactory(this, depth, true));\n    },\n\n    fromEntrySeq: function() {\n      return new FromEntriesSequence(this);\n    },\n\n    get: function(searchKey, notSetValue) {\n      return this.find(function(_, key)  {return is(key, searchKey)}, undefined, notSetValue);\n    },\n\n    getIn: function(searchKeyPath, notSetValue) {\n      var nested = this;\n      // Note: in an ES6 environment, we would prefer:\n      // for (var key of searchKeyPath) {\n      var iter = forceIterator(searchKeyPath);\n      var step;\n      while (!(step = iter.next()).done) {\n        var key = step.value;\n        nested = nested && nested.get ? nested.get(key, NOT_SET) : NOT_SET;\n        if (nested === NOT_SET) {\n          return notSetValue;\n        }\n      }\n      return nested;\n    },\n\n    groupBy: function(grouper, context) {\n      return groupByFactory(this, grouper, context);\n    },\n\n    has: function(searchKey) {\n      return this.get(searchKey, NOT_SET) !== NOT_SET;\n    },\n\n    hasIn: function(searchKeyPath) {\n      return this.getIn(searchKeyPath, NOT_SET) !== NOT_SET;\n    },\n\n    isSubset: function(iter) {\n      iter = typeof iter.includes === 'function' ? iter : Iterable(iter);\n      return this.every(function(value ) {return iter.includes(value)});\n    },\n\n    isSuperset: function(iter) {\n      iter = typeof iter.isSubset === 'function' ? iter : Iterable(iter);\n      return iter.isSubset(this);\n    },\n\n    keyOf: function(searchValue) {\n      return this.findKey(function(value ) {return is(value, searchValue)});\n    },\n\n    keySeq: function() {\n      return this.toSeq().map(keyMapper).toIndexedSeq();\n    },\n\n    last: function() {\n      return this.toSeq().reverse().first();\n    },\n\n    lastKeyOf: function(searchValue) {\n      return this.toKeyedSeq().reverse().keyOf(searchValue);\n    },\n\n    max: function(comparator) {\n      return maxFactory(this, comparator);\n    },\n\n    maxBy: function(mapper, comparator) {\n      return maxFactory(this, comparator, mapper);\n    },\n\n    min: function(comparator) {\n      return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator);\n    },\n\n    minBy: function(mapper, comparator) {\n      return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator, mapper);\n    },\n\n    rest: function() {\n      return this.slice(1);\n    },\n\n    skip: function(amount) {\n      return this.slice(Math.max(0, amount));\n    },\n\n    skipLast: function(amount) {\n      return reify(this, this.toSeq().reverse().skip(amount).reverse());\n    },\n\n    skipWhile: function(predicate, context) {\n      return reify(this, skipWhileFactory(this, predicate, context, true));\n    },\n\n    skipUntil: function(predicate, context) {\n      return this.skipWhile(not(predicate), context);\n    },\n\n    sortBy: function(mapper, comparator) {\n      return reify(this, sortFactory(this, comparator, mapper));\n    },\n\n    take: function(amount) {\n      return this.slice(0, Math.max(0, amount));\n    },\n\n    takeLast: function(amount) {\n      return reify(this, this.toSeq().reverse().take(amount).reverse());\n    },\n\n    takeWhile: function(predicate, context) {\n      return reify(this, takeWhileFactory(this, predicate, context));\n    },\n\n    takeUntil: function(predicate, context) {\n      return this.takeWhile(not(predicate), context);\n    },\n\n    valueSeq: function() {\n      return this.toIndexedSeq();\n    },\n\n\n    // ### Hashable Object\n\n    hashCode: function() {\n      return this.__hash || (this.__hash = hashIterable(this));\n    }\n\n\n    // ### Internal\n\n    // abstract __iterate(fn, reverse)\n\n    // abstract __iterator(type, reverse)\n  });\n\n  // var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@';\n  // var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';\n  // var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@';\n  // var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';\n\n  var IterablePrototype = Iterable.prototype;\n  IterablePrototype[IS_ITERABLE_SENTINEL] = true;\n  IterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.values;\n  IterablePrototype.__toJS = IterablePrototype.toArray;\n  IterablePrototype.__toStringMapper = quoteString;\n  IterablePrototype.inspect =\n  IterablePrototype.toSource = function() { return this.toString(); };\n  IterablePrototype.chain = IterablePrototype.flatMap;\n  IterablePrototype.contains = IterablePrototype.includes;\n\n  mixin(KeyedIterable, {\n\n    // ### More sequential methods\n\n    flip: function() {\n      return reify(this, flipFactory(this));\n    },\n\n    mapEntries: function(mapper, context) {var this$0 = this;\n      var iterations = 0;\n      return reify(this,\n        this.toSeq().map(\n          function(v, k)  {return mapper.call(context, [k, v], iterations++, this$0)}\n        ).fromEntrySeq()\n      );\n    },\n\n    mapKeys: function(mapper, context) {var this$0 = this;\n      return reify(this,\n        this.toSeq().flip().map(\n          function(k, v)  {return mapper.call(context, k, v, this$0)}\n        ).flip()\n      );\n    }\n\n  });\n\n  var KeyedIterablePrototype = KeyedIterable.prototype;\n  KeyedIterablePrototype[IS_KEYED_SENTINEL] = true;\n  KeyedIterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.entries;\n  KeyedIterablePrototype.__toJS = IterablePrototype.toObject;\n  KeyedIterablePrototype.__toStringMapper = function(v, k)  {return JSON.stringify(k) + ': ' + quoteString(v)};\n\n\n\n  mixin(IndexedIterable, {\n\n    // ### Conversion to other types\n\n    toKeyedSeq: function() {\n      return new ToKeyedSequence(this, false);\n    },\n\n\n    // ### ES6 Collection methods (ES6 Array and Map)\n\n    filter: function(predicate, context) {\n      return reify(this, filterFactory(this, predicate, context, false));\n    },\n\n    findIndex: function(predicate, context) {\n      var entry = this.findEntry(predicate, context);\n      return entry ? entry[0] : -1;\n    },\n\n    indexOf: function(searchValue) {\n      var key = this.keyOf(searchValue);\n      return key === undefined ? -1 : key;\n    },\n\n    lastIndexOf: function(searchValue) {\n      var key = this.lastKeyOf(searchValue);\n      return key === undefined ? -1 : key;\n    },\n\n    reverse: function() {\n      return reify(this, reverseFactory(this, false));\n    },\n\n    slice: function(begin, end) {\n      return reify(this, sliceFactory(this, begin, end, false));\n    },\n\n    splice: function(index, removeNum /*, ...values*/) {\n      var numArgs = arguments.length;\n      removeNum = Math.max(removeNum | 0, 0);\n      if (numArgs === 0 || (numArgs === 2 && !removeNum)) {\n        return this;\n      }\n      // If index is negative, it should resolve relative to the size of the\n      // collection. However size may be expensive to compute if not cached, so\n      // only call count() if the number is in fact negative.\n      index = resolveBegin(index, index < 0 ? this.count() : this.size);\n      var spliced = this.slice(0, index);\n      return reify(\n        this,\n        numArgs === 1 ?\n          spliced :\n          spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum))\n      );\n    },\n\n\n    // ### More collection methods\n\n    findLastIndex: function(predicate, context) {\n      var entry = this.findLastEntry(predicate, context);\n      return entry ? entry[0] : -1;\n    },\n\n    first: function() {\n      return this.get(0);\n    },\n\n    flatten: function(depth) {\n      return reify(this, flattenFactory(this, depth, false));\n    },\n\n    get: function(index, notSetValue) {\n      index = wrapIndex(this, index);\n      return (index < 0 || (this.size === Infinity ||\n          (this.size !== undefined && index > this.size))) ?\n        notSetValue :\n        this.find(function(_, key)  {return key === index}, undefined, notSetValue);\n    },\n\n    has: function(index) {\n      index = wrapIndex(this, index);\n      return index >= 0 && (this.size !== undefined ?\n        this.size === Infinity || index < this.size :\n        this.indexOf(index) !== -1\n      );\n    },\n\n    interpose: function(separator) {\n      return reify(this, interposeFactory(this, separator));\n    },\n\n    interleave: function(/*...iterables*/) {\n      var iterables = [this].concat(arrCopy(arguments));\n      var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, iterables);\n      var interleaved = zipped.flatten(true);\n      if (zipped.size) {\n        interleaved.size = zipped.size * iterables.length;\n      }\n      return reify(this, interleaved);\n    },\n\n    keySeq: function() {\n      return Range(0, this.size);\n    },\n\n    last: function() {\n      return this.get(-1);\n    },\n\n    skipWhile: function(predicate, context) {\n      return reify(this, skipWhileFactory(this, predicate, context, false));\n    },\n\n    zip: function(/*, ...iterables */) {\n      var iterables = [this].concat(arrCopy(arguments));\n      return reify(this, zipWithFactory(this, defaultZipper, iterables));\n    },\n\n    zipWith: function(zipper/*, ...iterables */) {\n      var iterables = arrCopy(arguments);\n      iterables[0] = this;\n      return reify(this, zipWithFactory(this, zipper, iterables));\n    }\n\n  });\n\n  IndexedIterable.prototype[IS_INDEXED_SENTINEL] = true;\n  IndexedIterable.prototype[IS_ORDERED_SENTINEL] = true;\n\n\n\n  mixin(SetIterable, {\n\n    // ### ES6 Collection methods (ES6 Array and Map)\n\n    get: function(value, notSetValue) {\n      return this.has(value) ? value : notSetValue;\n    },\n\n    includes: function(value) {\n      return this.has(value);\n    },\n\n\n    // ### More sequential methods\n\n    keySeq: function() {\n      return this.valueSeq();\n    }\n\n  });\n\n  SetIterable.prototype.has = IterablePrototype.includes;\n  SetIterable.prototype.contains = SetIterable.prototype.includes;\n\n\n  // Mixin subclasses\n\n  mixin(KeyedSeq, KeyedIterable.prototype);\n  mixin(IndexedSeq, IndexedIterable.prototype);\n  mixin(SetSeq, SetIterable.prototype);\n\n  mixin(KeyedCollection, KeyedIterable.prototype);\n  mixin(IndexedCollection, IndexedIterable.prototype);\n  mixin(SetCollection, SetIterable.prototype);\n\n\n  // #pragma Helper functions\n\n  function keyMapper(v, k) {\n    return k;\n  }\n\n  function entryMapper(v, k) {\n    return [k, v];\n  }\n\n  function not(predicate) {\n    return function() {\n      return !predicate.apply(this, arguments);\n    }\n  }\n\n  function neg(predicate) {\n    return function() {\n      return -predicate.apply(this, arguments);\n    }\n  }\n\n  function quoteString(value) {\n    return typeof value === 'string' ? JSON.stringify(value) : String(value);\n  }\n\n  function defaultZipper() {\n    return arrCopy(arguments);\n  }\n\n  function defaultNegComparator(a, b) {\n    return a < b ? 1 : a > b ? -1 : 0;\n  }\n\n  function hashIterable(iterable) {\n    if (iterable.size === Infinity) {\n      return 0;\n    }\n    var ordered = isOrdered(iterable);\n    var keyed = isKeyed(iterable);\n    var h = ordered ? 1 : 0;\n    var size = iterable.__iterate(\n      keyed ?\n        ordered ?\n          function(v, k)  { h = 31 * h + hashMerge(hash(v), hash(k)) | 0; } :\n          function(v, k)  { h = h + hashMerge(hash(v), hash(k)) | 0; } :\n        ordered ?\n          function(v ) { h = 31 * h + hash(v) | 0; } :\n          function(v ) { h = h + hash(v) | 0; }\n    );\n    return murmurHashOfSize(size, h);\n  }\n\n  function murmurHashOfSize(size, h) {\n    h = imul(h, 0xCC9E2D51);\n    h = imul(h << 15 | h >>> -15, 0x1B873593);\n    h = imul(h << 13 | h >>> -13, 5);\n    h = (h + 0xE6546B64 | 0) ^ size;\n    h = imul(h ^ h >>> 16, 0x85EBCA6B);\n    h = imul(h ^ h >>> 13, 0xC2B2AE35);\n    h = smi(h ^ h >>> 16);\n    return h;\n  }\n\n  function hashMerge(a, b) {\n    return a ^ b + 0x9E3779B9 + (a << 6) + (a >> 2) | 0; // int\n  }\n\n  var Immutable = {\n\n    Iterable: Iterable,\n\n    Seq: Seq,\n    Collection: Collection,\n    Map: Map,\n    OrderedMap: OrderedMap,\n    List: List,\n    Stack: Stack,\n    Set: Set,\n    OrderedSet: OrderedSet,\n\n    Record: Record,\n    Range: Range,\n    Repeat: Repeat,\n\n    is: is,\n    fromJS: fromJS\n\n  };\n\n  return Immutable;\n\n}));"
  },
  {
    "path": "src/thirdparty/jquery-2.1.3.js",
    "content": "/*!\n * jQuery JavaScript Library v2.1.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-18T15:11Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can't be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\n\nvar arr = [];\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\tversion = \"2.1.3\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\t// Support: Android<4.0, iOS<6 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE9-11+\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: Date.now,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\f]' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tlen = this.length,\n\t\t\tret = [],\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[0] === \"<\" && selector[ selector.length - 1 ] === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Support: Blackberry 4.6\n\t\t\t\t\t// gEBID returns nodes no longer in the document (#6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// Add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n});\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\twindow.removeEventListener( \"load\", completed, false );\n\tjQuery.ready();\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// We once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlen ? fn( elems[0], key ) : emptyGet;\n};\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\t/* jshint -W018 */\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\nfunction Data() {\n\t// Support: Android<4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\nData.accepts = jQuery.acceptData;\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android<4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\nvar data_priv = new Data();\n\nvar data_user = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend({\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Safari<=5.1\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Safari<=5.1, Android<4.2\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<=11+\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n})();\nvar strundefined = typeof undefined;\n\n\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome<28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\t// Support: Android<4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// Support: Firefox, Chrome, Safari\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdata_priv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdata_priv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdata_priv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\n\nvar\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\n\t\t// Support: IE9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type, key,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( jQuery.acceptData( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each(function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( node.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because push.apply(_, arraylike) throws\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optimization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" )).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = iframe[ 0 ].contentDocument;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\nvar rmargin = (/^margin/);\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// Support: IE9\n\t// getPropertyValue is only needed for .css('filter') (#12537)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\t}\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: iOS < 6\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\n(function() {\n\tvar pixelPositionVal, boxSizingReliableVal,\n\t\tdocElem = document.documentElement,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE9-11+\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer.style.cssText = \"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;\" +\n\t\t\"position:absolute\";\n\tcontainer.appendChild( div );\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computePixelPositionAndBoxSizingReliable() {\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocElem.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div, null );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\tdocElem.removeChild( container );\n\t}\n\n\t// Support: node.js jsdom\n\t// Don't assume that getComputedStyle is a property of the global object\n\tif ( window.getComputedStyle ) {\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\n\t\t\t\t// This test is executed only once but we still do memoizing\n\t\t\t\t// since we can use the boxSizingReliable pre-computing.\n\t\t\t\t// No need to check if the test was already performed, though.\n\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\t}\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\treliableMarginRight: function() {\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// This support function is only executed once so no memoizing is needed.\n\t\t\t\tvar ret,\n\t\t\t\t\tmarginDiv = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\t\tmarginDiv.style.cssText = div.style.cssText =\n\t\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\t\tdiv.style.width = \"1px\";\n\t\t\t\tdocElem.appendChild( container );\n\n\t\t\t\tret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );\n\n\t\t\t\tdocElem.removeChild( container );\n\t\t\t\tdiv.removeChild( marginDiv );\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t});\n\t}\n})();\n\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar\n\t// Swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + pnum + \")\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[0].toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// Both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// At this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// Check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// Use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = data_priv.access( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display !== \"none\" || !hidden ) {\n\t\t\t\tdata_priv.set( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.extend({\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t\"float\": \"cssFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n});\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\n// Support: Android 2.3\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE9\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t}\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur(),\n\t\t\t\t// break the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = data_priv.get( elem, \"fxshow\" );\n\n\t// Handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// Height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE9-10 do not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tdata_priv.get( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t});\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = data_priv.access( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// Store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\n\t\t\tdata_priv.remove( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( (display === \"none\" ? defaultDisplay( elem.nodeName ) : display) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || data_priv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = data_priv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = data_priv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\n\n(function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: iOS<=5.1, Android<=4.2+\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE<=11+\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: Android<=2.3\n\t// Options inside disabled selects are incorrectly marked as disabled\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<=11+\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n})();\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle;\n\t\tif ( !isXML ) {\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ name ];\n\t\t\tattrHandle[ name ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tname.toLowerCase() :\n\t\t\t\tnull;\n\t\t\tattrHandle[ name ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n});\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i;\n\njQuery.fn.extend({\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// Toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tdata_priv.set( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n});\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend({\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ? !option.disabled : option.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\t\t\t\t\tif ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Radios and checkboxes getter/setter\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n\nvar nonce = jQuery.now();\n\nvar rquery = (/\\?/);\n\n\n\n// Support: Android 2.3\n// Workaround failure to string-cast null input\njQuery.parseJSON = function( data ) {\n\treturn JSON.parse( data + \"\" );\n};\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE9\n\ttry {\n\t\ttmp = new DOMParser();\n\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Document location\n\tajaxLocation = window.location.href,\n\n\t// Segment location into parts\n\tajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t});\n};\n\n\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0;\n};\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function() {\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE9\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]();\n\t\t}\n\t});\n}\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[ id ] = callback(\"abort\");\n\n\t\t\t\ttry {\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context, defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[1] ) ];\n\t}\n\n\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n});\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t}).length;\n};\n\n\n\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend({\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each(function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t});\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\telem = this[ 0 ],\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// Support: BlackBerry 5, iOS 3 (original iPhone)\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top + win.pageYOffset - docElem.clientTop,\n\t\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\n// Support: Safari<7+, Chrome<37+\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n});\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t});\n}\n\n\n\n\nvar\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n\n}));\n"
  },
  {
    "path": "src/thirdparty/lodash.js",
    "content": "/**\n * @license\n * lodash 3.10.0 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE\n * Build: `lodash modern exports=\"amd\"`\n */\n;(function(){function n(n,t){if(n!==t){var r=null===n,e=n===w,u=n===n,o=null===t,i=t===w,f=t===t;if(n>t&&!o||!u||r&&!i&&f||e&&f)return 1;if(n<t&&!r||!f||o&&!e&&u||i&&u)return-1}return 0}function t(n,t,r){for(var e=n.length,u=r?e:-1;r?u--:++u<e;)if(t(n[u],u,n))return u;return-1}function r(n,t,r){if(t!==t)return p(n,r);r-=1;for(var e=n.length;++r<e;)if(n[r]===t)return r;return-1}function e(n){return typeof n==\"function\"||false}function u(n){return null==n?\"\":n+\"\"}function o(n,t){for(var r=-1,e=n.length;++r<e&&-1<t.indexOf(n.charAt(r)););\nreturn r}function i(n,t){for(var r=n.length;r--&&-1<t.indexOf(n.charAt(r)););return r}function f(t,r){return n(t.a,r.a)||t.b-r.b}function a(n){return Nn[n]}function c(n){return Tn[n]}function l(n,t,r){return t?n=Bn[n]:r&&(n=Dn[n]),\"\\\\\"+n}function s(n){return\"\\\\\"+Dn[n]}function p(n,t,r){var e=n.length;for(t+=r?0:-1;r?t--:++t<e;){var u=n[t];if(u!==u)return t}return-1}function h(n){return!!n&&typeof n==\"object\"}function _(n){return 160>=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n);\n}function v(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r<e;)n[r]===t&&(n[r]=z,o[++u]=r);return o}function g(n){for(var t=-1,r=n.length;++t<r&&_(n.charCodeAt(t)););return t}function y(n){for(var t=n.length;t--&&_(n.charCodeAt(t)););return t}function d(n){return Ln[n]}function m(_){function Nn(n){if(h(n)&&!(Oo(n)||n instanceof zn)){if(n instanceof Ln)return n;if(nu.call(n,\"__chain__\")&&nu.call(n,\"__wrapped__\"))return Mr(n)}return new Ln(n)}function Tn(){}function Ln(n,t,r){this.__wrapped__=n,this.__actions__=r||[],\nthis.__chain__=!!t}function zn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=Ru,this.__views__=[]}function Bn(){this.__data__={}}function Dn(n){var t=n?n.length:0;for(this.data={hash:gu(null),set:new lu};t--;)this.push(n[t])}function Mn(n,t){var r=n.data;return(typeof t==\"string\"||ge(t)?r.set.has(t):r.hash[t])?0:-1}function qn(n,t){var r=-1,e=n.length;for(t||(t=Be(e));++r<e;)t[r]=n[r];return t}function Pn(n,t){for(var r=-1,e=n.length;++r<e&&false!==t(n[r],r,n););\nreturn n}function Zn(n,t){for(var r=-1,e=n.length;++r<e;)if(!t(n[r],r,n))return false;return true}function Yn(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r<e;){var i=n[r];t(i,r,n)&&(o[++u]=i)}return o}function Gn(n,t){for(var r=-1,e=n.length,u=Be(e);++r<e;)u[r]=t(n[r],r,n);return u}function Jn(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function Xn(n,t,r,e){var u=-1,o=n.length;for(e&&o&&(r=n[++u]);++u<o;)r=t(r,n[u],u,n);return r}function Hn(n,t){for(var r=-1,e=n.length;++r<e;)if(t(n[r],r,n))return true;\nreturn false}function Qn(n,t,r,e){return n!==w&&nu.call(e,r)?n:t}function nt(n,t,r){for(var e=-1,u=zo(t),o=u.length;++e<o;){var i=u[e],f=n[i],a=r(f,t[i],i,n,t);(a===a?a===f:f!==f)&&(f!==w||i in n)||(n[i]=a)}return n}function tt(n,t){return null==t?n:et(t,zo(t),n)}function rt(n,t){for(var r=-1,e=null==n,u=!e&&Er(n),o=u?n.length:0,i=t.length,f=Be(i);++r<i;){var a=t[r];f[r]=u?Cr(a,o)?n[a]:w:e?w:n[a]}return f}function et(n,t,r){r||(r={});for(var e=-1,u=t.length;++e<u;){var o=t[e];r[o]=n[o]}return r}function ut(n,t,r){\nvar e=typeof n;return\"function\"==e?t===w?n:Bt(n,t,r):null==n?Fe:\"object\"==e?bt(n):t===w?ze(n):xt(n,t)}function ot(n,t,r,e,u,o,i){var f;if(r&&(f=u?r(n,e,u):r(n)),f!==w)return f;if(!ge(n))return n;if(e=Oo(n)){if(f=kr(n),!t)return qn(n,f)}else{var a=ru.call(n),c=a==K;if(a!=Z&&a!=B&&(!c||u))return Fn[a]?Rr(n,a,t):u?n:{};if(f=Ir(c?{}:n),!t)return tt(f,n)}for(o||(o=[]),i||(i=[]),u=o.length;u--;)if(o[u]==n)return i[u];return o.push(n),i.push(f),(e?Pn:_t)(n,function(e,u){f[u]=ot(e,t,r,u,n,o,i)}),f}function it(n,t,r){\nif(typeof n!=\"function\")throw new Ge(L);return su(function(){n.apply(w,r)},t)}function ft(n,t){var e=n?n.length:0,u=[];if(!e)return u;var o=-1,i=xr(),f=i==r,a=f&&t.length>=F&&gu&&lu?new Dn(t):null,c=t.length;a&&(i=Mn,f=false,t=a);n:for(;++o<e;)if(a=n[o],f&&a===a){for(var l=c;l--;)if(t[l]===a)continue n;u.push(a)}else 0>i(t,a,0)&&u.push(a);return u}function at(n,t){var r=true;return Su(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ct(n,t,r,e){var u=e,o=u;return Su(n,function(n,i,f){i=+t(n,i,f),(r(i,u)||i===e&&i===o)&&(u=i,\no=n)}),o}function lt(n,t){var r=[];return Su(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function st(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function pt(n,t,r,e){e||(e=[]);for(var u=-1,o=n.length;++u<o;){var i=n[u];h(i)&&Er(i)&&(r||Oo(i)||pe(i))?t?pt(i,t,r,e):Jn(e,i):r||(e[e.length]=i)}return e}function ht(n,t){Nu(n,t,Re)}function _t(n,t){return Nu(n,t,zo)}function vt(n,t){return Tu(n,t,zo)}function gt(n,t){for(var r=-1,e=t.length,u=-1,o=[];++r<e;){var i=t[r];\nve(n[i])&&(o[++u]=i)}return o}function yt(n,t,r){if(null!=n){r!==w&&r in Br(n)&&(t=[r]),r=0;for(var e=t.length;null!=n&&r<e;)n=n[t[r++]];return r&&r==e?n:w}}function dt(n,t,r,e,u,o){if(n===t)n=true;else if(null==n||null==t||!ge(n)&&!h(t))n=n!==n&&t!==t;else n:{var i=dt,f=Oo(n),a=Oo(t),c=D,l=D;f||(c=ru.call(n),c==B?c=Z:c!=Z&&(f=xe(n))),a||(l=ru.call(t),l==B?l=Z:l!=Z&&xe(t));var s=c==Z,a=l==Z,l=c==l;if(!l||f||s){if(!e&&(c=s&&nu.call(n,\"__wrapped__\"),a=a&&nu.call(t,\"__wrapped__\"),c||a)){n=i(c?n.value():n,a?t.value():t,r,e,u,o);\nbreak n}if(l){for(u||(u=[]),o||(o=[]),c=u.length;c--;)if(u[c]==n){n=o[c]==t;break n}u.push(n),o.push(t),n=(f?yr:mr)(n,t,i,r,e,u,o),u.pop(),o.pop()}else n=false}else n=dr(n,t,c)}return n}function mt(n,t,r){var e=t.length,u=e,o=!r;if(null==n)return!u;for(n=Br(n);e--;){var i=t[e];if(o&&i[2]?i[1]!==n[i[0]]:!(i[0]in n))return false}for(;++e<u;){var i=t[e],f=i[0],a=n[f],c=i[1];if(o&&i[2]){if(a===w&&!(f in n))return false}else if(i=r?r(a,c,f):w,i===w?!dt(c,a,r,true):!i)return false}return true}function wt(n,t){var r=-1,e=Er(n)?Be(n.length):[];\nreturn Su(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function bt(n){var t=Ar(n);if(1==t.length&&t[0][2]){var r=t[0][0],e=t[0][1];return function(n){return null==n?false:n[r]===e&&(e!==w||r in Br(n))}}return function(n){return mt(n,t)}}function xt(n,t){var r=Oo(n),e=Wr(n)&&t===t&&!ge(t),u=n+\"\";return n=Dr(n),function(o){if(null==o)return false;var i=u;if(o=Br(o),!(!r&&e||i in o)){if(o=1==n.length?o:yt(o,Et(n,0,-1)),null==o)return false;i=Zr(n),o=Br(o)}return o[i]===t?t!==w||i in o:dt(t,o[i],w,true)}}function At(n,t,r,e,u){\nif(!ge(n))return n;var o=Er(t)&&(Oo(t)||xe(t)),i=o?w:zo(t);return Pn(i||t,function(f,a){if(i&&(a=f,f=t[a]),h(f)){e||(e=[]),u||(u=[]);n:{for(var c=a,l=e,s=u,p=l.length,_=t[c];p--;)if(l[p]==_){n[c]=s[p];break n}var p=n[c],v=r?r(p,_,c,n,t):w,g=v===w;g&&(v=_,Er(_)&&(Oo(_)||xe(_))?v=Oo(p)?p:Er(p)?qn(p):[]:me(_)||pe(_)?v=pe(p)?ke(p):me(p)?p:{}:g=false),l.push(_),s.push(v),g?n[c]=At(v,_,r,l,s):(v===v?v!==p:p===p)&&(n[c]=v)}}else c=n[a],l=r?r(c,f,a,n,t):w,(s=l===w)&&(l=f),l===w&&(!o||a in n)||!s&&(l===l?l===c:c!==c)||(n[a]=l);\n}),n}function jt(n){return function(t){return null==t?w:t[n]}}function kt(n){var t=n+\"\";return n=Dr(n),function(r){return yt(r,n,t)}}function It(n,t){for(var r=n?t.length:0;r--;){var e=t[r];if(e!=u&&Cr(e)){var u=e;pu.call(n,e,1)}}}function Rt(n,t){return n+yu(ku()*(t-n+1))}function Ot(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function Et(n,t,r){var e=-1,u=n.length;for(t=null==t?0:+t||0,0>t&&(t=-t>u?0:u+t),r=r===w||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Be(u);++e<u;)r[e]=n[e+t];\nreturn r}function Ct(n,t){var r;return Su(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function Ut(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function Wt(t,r,e){var u=wr(),o=-1;return r=Gn(r,function(n){return u(n)}),t=wt(t,function(n){return{a:Gn(r,function(t){return t(n)}),b:++o,c:n}}),Ut(t,function(t,r){var u;n:{for(var o=-1,i=t.a,f=r.a,a=i.length,c=e.length;++o<a;)if(u=n(i[o],f[o])){if(o>=c)break n;o=e[o],u*=\"asc\"===o||true===o?1:-1;break n}u=t.b-r.b}return u})}function $t(n,t){\nvar r=0;return Su(n,function(n,e,u){r+=+t(n,e,u)||0}),r}function St(n,t){var e=-1,u=xr(),o=n.length,i=u==r,f=i&&o>=F,a=f&&gu&&lu?new Dn(void 0):null,c=[];a?(u=Mn,i=false):(f=false,a=t?[]:c);n:for(;++e<o;){var l=n[e],s=t?t(l,e,n):l;if(i&&l===l){for(var p=a.length;p--;)if(a[p]===s)continue n;t&&a.push(s),c.push(l)}else 0>u(a,s,0)&&((t||f)&&a.push(s),c.push(l))}return c}function Ft(n,t){for(var r=-1,e=t.length,u=Be(e);++r<e;)u[r]=n[t[r]];return u}function Nt(n,t,r,e){for(var u=n.length,o=e?u:-1;(e?o--:++o<u)&&t(n[o],o,n););\nreturn r?Et(n,e?0:o,e?o+1:u):Et(n,e?o+1:0,e?u:o)}function Tt(n,t){var r=n;r instanceof zn&&(r=r.value());for(var e=-1,u=t.length;++e<u;)var o=t[e],r=o.func.apply(o.thisArg,Jn([r],o.args));return r}function Lt(n,t,r){var e=0,u=n?n.length:e;if(typeof t==\"number\"&&t===t&&u<=Eu){for(;e<u;){var o=e+u>>>1,i=n[o];(r?i<=t:i<t)&&null!==i?e=o+1:u=o}return u}return zt(n,t,Fe,r)}function zt(n,t,r,e){t=r(t);for(var u=0,o=n?n.length:0,i=t!==t,f=null===t,a=t===w;u<o;){var c=yu((u+o)/2),l=r(n[c]),s=l!==w,p=l===l;\n(i?p||e:f?p&&s&&(e||null!=l):a?p&&(e||s):null==l?0:e?l<=t:l<t)?u=c+1:o=c}return xu(o,Ou)}function Bt(n,t,r){if(typeof n!=\"function\")return Fe;if(t===w)return n;switch(r){case 1:return function(r){return n.call(t,r)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,o){return n.call(t,r,e,u,o)};case 5:return function(r,e,u,o,i){return n.call(t,r,e,u,o,i)}}return function(){return n.apply(t,arguments)}}function Dt(n){var t=new ou(n.byteLength);return new hu(t).set(new hu(n)),\nt}function Mt(n,t,r){for(var e=r.length,u=-1,o=bu(n.length-e,0),i=-1,f=t.length,a=Be(f+o);++i<f;)a[i]=t[i];for(;++u<e;)a[r[u]]=n[u];for(;o--;)a[i++]=n[u++];return a}function qt(n,t,r){for(var e=-1,u=r.length,o=-1,i=bu(n.length-u,0),f=-1,a=t.length,c=Be(i+a);++o<i;)c[o]=n[o];for(i=o;++f<a;)c[i+f]=t[f];for(;++e<u;)c[i+r[e]]=n[o++];return c}function Pt(n,t){return function(r,e,u){var o=t?t():{};if(e=wr(e,u,3),Oo(r)){u=-1;for(var i=r.length;++u<i;){var f=r[u];n(o,f,e(f,u,r),r)}}else Su(r,function(t,r,u){\nn(o,t,e(t,r,u),u)});return o}}function Kt(n){return le(function(t,r){var e=-1,u=null==t?0:r.length,o=2<u?r[u-2]:w,i=2<u?r[2]:w,f=1<u?r[u-1]:w;for(typeof o==\"function\"?(o=Bt(o,f,5),u-=2):(o=typeof f==\"function\"?f:w,u-=o?1:0),i&&Ur(r[0],r[1],i)&&(o=3>u?w:o,u=1);++e<u;)(i=r[e])&&n(t,i,o);return t})}function Vt(n,t){return function(r,e){var u=r?Bu(r):0;if(!Sr(u))return n(r,e);for(var o=t?u:-1,i=Br(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}function Zt(n){return function(t,r,e){var u=Br(t);e=e(t);for(var o=e.length,i=n?o:-1;n?i--:++i<o;){\nvar f=e[i];if(false===r(u[f],f,u))break}return t}}function Yt(n,t){function r(){return(this&&this!==Kn&&this instanceof r?e:n).apply(t,arguments)}var e=Jt(n);return r}function Gt(n){return function(t){var r=-1;t=$e(Ce(t));for(var e=t.length,u=\"\";++r<e;)u=n(u,t[r],r);return u}}function Jt(n){return function(){var t=arguments;switch(t.length){case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:\nreturn new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=$u(n.prototype),t=n.apply(r,t);return ge(t)?t:r}}function Xt(n){function t(r,e,u){return u&&Ur(r,e,u)&&(e=w),r=gr(r,n,w,w,w,w,w,e),r.placeholder=t.placeholder,r}return t}function Ht(n,t){return le(function(r){var e=r[0];return null==e?e:(r.push(t),n.apply(w,r))})}function Qt(n,t){return function(r,e,u){if(u&&Ur(r,e,u)&&(e=w),e=wr(e,u,3),1==e.length){\nu=r=Oo(r)?r:zr(r);for(var o=e,i=-1,f=u.length,a=t,c=a;++i<f;){var l=u[i],s=+o(l);n(s,a)&&(a=s,c=l)}if(u=c,!r.length||u!==t)return u}return ct(r,e,n,t)}}function nr(n,r){return function(e,u,o){return u=wr(u,o,3),Oo(e)?(u=t(e,u,r),-1<u?e[u]:w):st(e,u,n)}}function tr(n){return function(r,e,u){return r&&r.length?(e=wr(e,u,3),t(r,e,n)):-1}}function rr(n){return function(t,r,e){return r=wr(r,e,3),st(t,r,n,true)}}function er(n){return function(){for(var t,r=arguments.length,e=n?r:-1,u=0,o=Be(r);n?e--:++e<r;){\nvar i=o[u++]=arguments[e];if(typeof i!=\"function\")throw new Ge(L);!t&&Ln.prototype.thru&&\"wrapper\"==br(i)&&(t=new Ln([],true))}for(e=t?-1:r;++e<r;){var i=o[e],u=br(i),f=\"wrapper\"==u?zu(i):w;t=f&&$r(f[0])&&f[1]==(E|k|R|C)&&!f[4].length&&1==f[9]?t[br(f[0])].apply(t,f[3]):1==i.length&&$r(i)?t[u]():t.thru(i)}return function(){var n=arguments,e=n[0];if(t&&1==n.length&&Oo(e)&&e.length>=F)return t.plant(e).value();for(var u=0,n=r?o[u].apply(this,n):e;++u<r;)n=o[u].call(this,n);return n}}}function ur(n,t){\nreturn function(r,e,u){return typeof e==\"function\"&&u===w&&Oo(r)?n(r,e):t(r,Bt(e,u,3))}}function or(n){return function(t,r,e){return(typeof r!=\"function\"||e!==w)&&(r=Bt(r,e,3)),n(t,r,Re)}}function ir(n){return function(t,r,e){return(typeof r!=\"function\"||e!==w)&&(r=Bt(r,e,3)),n(t,r)}}function fr(n){return function(t,r,e){var u={};return r=wr(r,e,3),_t(t,function(t,e,o){o=r(t,e,o),e=n?o:e,t=n?t:o,u[e]=t}),u}}function ar(n){return function(t,r,e){return t=u(t),(n?t:\"\")+pr(t,r,e)+(n?\"\":t)}}function cr(n){\nvar t=le(function(r,e){var u=v(e,t.placeholder);return gr(r,n,w,e,u)});return t}function lr(n,t){return function(r,e,u,o){var i=3>arguments.length;return typeof e==\"function\"&&o===w&&Oo(r)?n(r,e,u,i):Ot(r,wr(e,o,4),u,i,t)}}function sr(n,t,r,e,u,o,i,f,a,c){function l(){for(var m=arguments.length,b=m,j=Be(m);b--;)j[b]=arguments[b];if(e&&(j=Mt(j,e,u)),o&&(j=qt(j,o,i)),_||y){var b=l.placeholder,k=v(j,b),m=m-k.length;if(m<c){var I=f?qn(f):w,m=bu(c-m,0),E=_?k:w,k=_?w:k,C=_?j:w,j=_?w:j;return t|=_?R:O,t&=~(_?O:R),\ng||(t&=~(x|A)),j=[n,t,r,C,E,j,k,I,a,m],I=sr.apply(w,j),$r(n)&&Du(I,j),I.placeholder=b,I}}if(b=p?r:this,I=h?b[n]:n,f)for(m=j.length,E=xu(f.length,m),k=qn(j);E--;)C=f[E],j[E]=Cr(C,m)?k[C]:w;return s&&a<j.length&&(j.length=a),this&&this!==Kn&&this instanceof l&&(I=d||Jt(n)),I.apply(b,j)}var s=t&E,p=t&x,h=t&A,_=t&k,g=t&j,y=t&I,d=h?w:Jt(n);return l}function pr(n,t,r){return n=n.length,t=+t,n<t&&mu(t)?(t-=n,r=null==r?\" \":r+\"\",Ue(r,vu(t/r.length)).slice(0,t)):\"\"}function hr(n,t,r,e){function u(){for(var t=-1,f=arguments.length,a=-1,c=e.length,l=Be(c+f);++a<c;)l[a]=e[a];\nfor(;f--;)l[a++]=arguments[++t];return(this&&this!==Kn&&this instanceof u?i:n).apply(o?r:this,l)}var o=t&x,i=Jt(n);return u}function _r(n){var t=Pe[n];return function(n,r){return(r=r===w?0:+r||0)?(r=au(10,r),t(n*r)/r):t(n)}}function vr(n){return function(t,r,e,u){var o=wr(e);return null==e&&o===ut?Lt(t,r,n):zt(t,r,o(e,u,1),n)}}function gr(n,t,r,e,u,o,i,f){var a=t&A;if(!a&&typeof n!=\"function\")throw new Ge(L);var c=e?e.length:0;if(c||(t&=~(R|O),e=u=w),c-=u?u.length:0,t&O){var l=e,s=u;e=u=w}var p=a?w:zu(n);\nreturn r=[n,t,r,e,u,l,s,o,i,f],p&&(e=r[1],t=p[1],f=e|t,u=t==E&&e==k||t==E&&e==C&&r[7].length<=p[8]||t==(E|C)&&e==k,(f<E||u)&&(t&x&&(r[2]=p[2],f|=e&x?0:j),(e=p[3])&&(u=r[3],r[3]=u?Mt(u,e,p[4]):qn(e),r[4]=u?v(r[3],z):qn(p[4])),(e=p[5])&&(u=r[5],r[5]=u?qt(u,e,p[6]):qn(e),r[6]=u?v(r[5],z):qn(p[6])),(e=p[7])&&(r[7]=qn(e)),t&E&&(r[8]=null==r[8]?p[8]:xu(r[8],p[8])),null==r[9]&&(r[9]=p[9]),r[0]=p[0],r[1]=f),t=r[1],f=r[9]),r[9]=null==f?a?0:n.length:bu(f-c,0)||0,(p?Lu:Du)(t==x?Yt(r[0],r[2]):t!=R&&t!=(x|R)||r[4].length?sr.apply(w,r):hr.apply(w,r),r);\n}function yr(n,t,r,e,u,o,i){var f=-1,a=n.length,c=t.length;if(a!=c&&(!u||c<=a))return false;for(;++f<a;){var l=n[f],c=t[f],s=e?e(u?c:l,u?l:c,f):w;if(s!==w){if(s)continue;return false}if(u){if(!Hn(t,function(n){return l===n||r(l,n,e,u,o,i)}))return false}else if(l!==c&&!r(l,c,e,u,o,i))return false}return true}function dr(n,t,r){switch(r){case M:case q:return+n==+t;case P:return n.name==t.name&&n.message==t.message;case V:return n!=+n?t!=+t:n==+t;case Y:case G:return n==t+\"\"}return false}function mr(n,t,r,e,u,o,i){var f=zo(n),a=f.length,c=zo(t).length;\nif(a!=c&&!u)return false;for(c=a;c--;){var l=f[c];if(!(u?l in t:nu.call(t,l)))return false}for(var s=u;++c<a;){var l=f[c],p=n[l],h=t[l],_=e?e(u?h:p,u?p:h,l):w;if(_===w?!r(p,h,e,u,o,i):!_)return false;s||(s=\"constructor\"==l)}return s||(r=n.constructor,e=t.constructor,!(r!=e&&\"constructor\"in n&&\"constructor\"in t)||typeof r==\"function\"&&r instanceof r&&typeof e==\"function\"&&e instanceof e)?true:false}function wr(n,t,r){var e=Nn.callback||Se,e=e===Se?ut:e;return r?e(n,t,r):e}function br(n){for(var t=n.name,r=Wu[t],e=r?r.length:0;e--;){\nvar u=r[e],o=u.func;if(null==o||o==n)return u.name}return t}function xr(n,t,e){var u=Nn.indexOf||Vr,u=u===Vr?r:u;return n?u(n,t,e):u}function Ar(n){n=Oe(n);for(var t=n.length;t--;){var r=n[t][1];n[t][2]=r===r&&!ge(r)}return n}function jr(n,t){var r=null==n?w:n[t];return ye(r)?r:w}function kr(n){var t=n.length,r=new n.constructor(t);return t&&\"string\"==typeof n[0]&&nu.call(n,\"index\")&&(r.index=n.index,r.input=n.input),r}function Ir(n){return n=n.constructor,typeof n==\"function\"&&n instanceof n||(n=Ve),\nnew n}function Rr(n,t,r){var e=n.constructor;switch(t){case J:return Dt(n);case M:case q:return new e(+n);case X:case H:case Q:case nn:case tn:case rn:case en:case un:case on:return t=n.buffer,new e(r?Dt(t):t,n.byteOffset,n.length);case V:case G:return new e(n);case Y:var u=new e(n.source,kn.exec(n));u.lastIndex=n.lastIndex}return u}function Or(n,t,r){return null==n||Wr(t,n)||(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),t=Zr(t)),t=null==n?n:n[t],null==t?w:t.apply(n,r)}function Er(n){return null!=n&&Sr(Bu(n));\n}function Cr(n,t){return n=typeof n==\"number\"||On.test(n)?+n:-1,t=null==t?Cu:t,-1<n&&0==n%1&&n<t}function Ur(n,t,r){if(!ge(r))return false;var e=typeof t;return(\"number\"==e?Er(r)&&Cr(t,r.length):\"string\"==e&&t in r)?(t=r[t],n===n?n===t:t!==t):false}function Wr(n,t){var r=typeof n;return\"string\"==r&&dn.test(n)||\"number\"==r?true:Oo(n)?false:!yn.test(n)||null!=t&&n in Br(t)}function $r(n){var t=br(n);return t in zn.prototype?(t=Nn[t],n===t?true:(t=zu(t),!!t&&n===t[0])):false}function Sr(n){return typeof n==\"number\"&&-1<n&&0==n%1&&n<=Cu;\n}function Fr(n,t){return n===w?t:Eo(n,t,Fr)}function Nr(n,t){n=Br(n);for(var r=-1,e=t.length,u={};++r<e;){var o=t[r];o in n&&(u[o]=n[o])}return u}function Tr(n,t){var r={};return ht(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r}function Lr(n){for(var t=Re(n),r=t.length,e=r&&n.length,u=!!e&&Sr(e)&&(Oo(n)||pe(n)),o=-1,i=[];++o<r;){var f=t[o];(u&&Cr(f,e)||nu.call(n,f))&&i.push(f)}return i}function zr(n){return null==n?[]:Er(n)?ge(n)?n:Ve(n):Ee(n)}function Br(n){return ge(n)?n:Ve(n)}function Dr(n){if(Oo(n))return n;\nvar t=[];return u(n).replace(mn,function(n,r,e,u){t.push(e?u.replace(An,\"$1\"):r||n)}),t}function Mr(n){return n instanceof zn?n.clone():new Ln(n.__wrapped__,n.__chain__,qn(n.__actions__))}function qr(n,t,r){return n&&n.length?((r?Ur(n,t,r):null==t)&&(t=1),Et(n,0>t?0:t)):[]}function Pr(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0,0>t?0:t)):[]}function Kr(n){return n?n[0]:w}function Vr(n,t,e){var u=n?n.length:0;if(!u)return-1;if(typeof e==\"number\")e=0>e?bu(u+e,0):e;else if(e)return e=Lt(n,t),\ne<u&&(t===t?t===n[e]:n[e]!==n[e])?e:-1;return r(n,t,e||0)}function Zr(n){var t=n?n.length:0;return t?n[t-1]:w}function Yr(n){return qr(n,1)}function Gr(n,t,e,u){if(!n||!n.length)return[];null!=t&&typeof t!=\"boolean\"&&(u=e,e=Ur(n,t,u)?w:t,t=false);var o=wr();if((null!=e||o!==ut)&&(e=o(e,u,3)),t&&xr()==r){t=e;var i;e=-1,u=n.length;for(var o=-1,f=[];++e<u;){var a=n[e],c=t?t(a,e,n):a;e&&i===c||(i=c,f[++o]=a)}n=f}else n=St(n,e);return n}function Jr(n){if(!n||!n.length)return[];var t=-1,r=0;n=Yn(n,function(n){\nreturn Er(n)?(r=bu(n.length,r),true):void 0});for(var e=Be(r);++t<r;)e[t]=Gn(n,jt(t));return e}function Xr(n,t,r){return n&&n.length?(n=Jr(n),null==t?n:(t=Bt(t,r,4),Gn(n,function(n){return Xn(n,t,w,true)}))):[]}function Hr(n,t){var r=-1,e=n?n.length:0,u={};for(!e||t||Oo(n[0])||(t=[]);++r<e;){var o=n[r];t?u[o]=t[r]:o&&(u[o[0]]=o[1])}return u}function Qr(n){return n=Nn(n),n.__chain__=true,n}function ne(n,t,r){return t.call(r,n)}function te(n,t,r){var e=Oo(n)?Zn:at;return r&&Ur(n,t,r)&&(t=w),(typeof t!=\"function\"||r!==w)&&(t=wr(t,r,3)),\ne(n,t)}function re(n,t,r){var e=Oo(n)?Yn:lt;return t=wr(t,r,3),e(n,t)}function ee(n,t,r,e){var u=n?Bu(n):0;return Sr(u)||(n=Ee(n),u=n.length),r=typeof r!=\"number\"||e&&Ur(t,r,e)?0:0>r?bu(u+r,0):r||0,typeof n==\"string\"||!Oo(n)&&be(n)?r<=u&&-1<n.indexOf(t,r):!!u&&-1<xr(n,t,r)}function ue(n,t,r){var e=Oo(n)?Gn:wt;return t=wr(t,r,3),e(n,t)}function oe(n,t,r){if(r?Ur(n,t,r):null==t){n=zr(n);var e=n.length;return 0<e?n[Rt(0,e-1)]:w}r=-1,n=je(n);var e=n.length,u=e-1;for(t=xu(0>t?0:+t||0,e);++r<t;){var e=Rt(r,u),o=n[e];\nn[e]=n[r],n[r]=o}return n.length=t,n}function ie(n,t,r){var e=Oo(n)?Hn:Ct;return r&&Ur(n,t,r)&&(t=w),(typeof t!=\"function\"||r!==w)&&(t=wr(t,r,3)),e(n,t)}function fe(n,t){var r;if(typeof t!=\"function\"){if(typeof n!=\"function\")throw new Ge(L);var e=n;n=t,t=e}return function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=w),r}}function ae(n,t,r){function e(t,r){r&&iu(r),a=p=h=w,t&&(_=ho(),c=n.apply(s,f),p||a||(f=s=w))}function u(){var n=t-(ho()-l);0>=n||n>t?e(h,a):p=su(u,n)}function o(){e(g,p);\n}function i(){if(f=arguments,l=ho(),s=this,h=g&&(p||!y),false===v)var r=y&&!p;else{a||y||(_=l);var e=v-(l-_),i=0>=e||e>v;i?(a&&(a=iu(a)),_=l,c=n.apply(s,f)):a||(a=su(o,e))}return i&&p?p=iu(p):p||t===v||(p=su(u,t)),r&&(i=true,c=n.apply(s,f)),!i||p||a||(f=s=w),c}var f,a,c,l,s,p,h,_=0,v=false,g=true;if(typeof n!=\"function\")throw new Ge(L);if(t=0>t?0:+t||0,true===r)var y=true,g=false;else ge(r)&&(y=!!r.leading,v=\"maxWait\"in r&&bu(+r.maxWait||0,t),g=\"trailing\"in r?!!r.trailing:g);return i.cancel=function(){p&&iu(p),a&&iu(a),\n_=0,a=p=h=w},i}function ce(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=n.apply(this,e),r.cache=o.set(u,e),e)}if(typeof n!=\"function\"||t&&typeof t!=\"function\")throw new Ge(L);return r.cache=new ce.Cache,r}function le(n,t){if(typeof n!=\"function\")throw new Ge(L);return t=bu(t===w?n.length-1:+t||0,0),function(){for(var r=arguments,e=-1,u=bu(r.length-t,0),o=Be(u);++e<u;)o[e]=r[t+e];switch(t){case 0:return n.call(this,o);case 1:return n.call(this,r[0],o);\ncase 2:return n.call(this,r[0],r[1],o)}for(u=Be(t+1),e=-1;++e<t;)u[e]=r[e];return u[t]=o,n.apply(this,u)}}function se(n,t){return n>t}function pe(n){return h(n)&&Er(n)&&nu.call(n,\"callee\")&&!cu.call(n,\"callee\")}function he(n,t,r,e){return e=(r=typeof r==\"function\"?Bt(r,e,3):w)?r(n,t):w,e===w?dt(n,t,r):!!e}function _e(n){return h(n)&&typeof n.message==\"string\"&&ru.call(n)==P}function ve(n){return ge(n)&&ru.call(n)==K}function ge(n){var t=typeof n;return!!n&&(\"object\"==t||\"function\"==t)}function ye(n){\nreturn null==n?false:ve(n)?uu.test(Qe.call(n)):h(n)&&Rn.test(n)}function de(n){return typeof n==\"number\"||h(n)&&ru.call(n)==V}function me(n){var t;if(!h(n)||ru.call(n)!=Z||pe(n)||!(nu.call(n,\"constructor\")||(t=n.constructor,typeof t!=\"function\"||t instanceof t)))return false;var r;return ht(n,function(n,t){r=t}),r===w||nu.call(n,r)}function we(n){return ge(n)&&ru.call(n)==Y}function be(n){return typeof n==\"string\"||h(n)&&ru.call(n)==G}function xe(n){return h(n)&&Sr(n.length)&&!!Sn[ru.call(n)]}function Ae(n,t){\nreturn n<t}function je(n){var t=n?Bu(n):0;return Sr(t)?t?qn(n):[]:Ee(n)}function ke(n){return et(n,Re(n))}function Ie(n){return gt(n,Re(n))}function Re(n){if(null==n)return[];ge(n)||(n=Ve(n));for(var t=n.length,t=t&&Sr(t)&&(Oo(n)||pe(n))&&t||0,r=n.constructor,e=-1,r=typeof r==\"function\"&&r.prototype===n,u=Be(t),o=0<t;++e<t;)u[e]=e+\"\";for(var i in n)o&&Cr(i,t)||\"constructor\"==i&&(r||!nu.call(n,i))||u.push(i);return u}function Oe(n){n=Br(n);for(var t=-1,r=zo(n),e=r.length,u=Be(e);++t<e;){var o=r[t];\nu[t]=[o,n[o]]}return u}function Ee(n){return Ft(n,zo(n))}function Ce(n){return(n=u(n))&&n.replace(En,a).replace(xn,\"\")}function Ue(n,t){var r=\"\";if(n=u(n),t=+t,1>t||!n||!mu(t))return r;do t%2&&(r+=n),t=yu(t/2),n+=n;while(t);return r}function We(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(g(n),y(n)+1):(t+=\"\",n.slice(o(n,t),i(n,t)+1)):n}function $e(n,t,r){return r&&Ur(n,t,r)&&(t=w),n=u(n),n.match(t||Wn)||[]}function Se(n,t,r){return r&&Ur(n,t,r)&&(t=w),h(n)?Ne(n):ut(n,t)}function Fe(n){\nreturn n}function Ne(n){return bt(ot(n,true))}function Te(n,t,r){if(null==r){var e=ge(t),u=e?zo(t):w;((u=u&&u.length?gt(t,u):w)?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=gt(t,zo(t)));var o=true,e=-1,i=ve(n),f=u.length;false===r?o=false:ge(r)&&\"chain\"in r&&(o=r.chain);for(;++e<f;){r=u[e];var a=t[r];n[r]=a,i&&(n.prototype[r]=function(t){return function(){var r=this.__chain__;if(o||r){var e=n(this.__wrapped__);return(e.__actions__=qn(this.__actions__)).push({func:t,args:arguments,thisArg:n}),e.__chain__=r,e}return t.apply(n,Jn([this.value()],arguments));\n}}(a))}return n}function Le(){}function ze(n){return Wr(n)?jt(n):kt(n)}_=_?Vn.defaults(Kn.Object(),_,Vn.pick(Kn,$n)):Kn;var Be=_.Array,De=_.Date,Me=_.Error,qe=_.Function,Pe=_.Math,Ke=_.Number,Ve=_.Object,Ze=_.RegExp,Ye=_.String,Ge=_.TypeError,Je=Be.prototype,Xe=Ve.prototype,He=Ye.prototype,Qe=qe.prototype.toString,nu=Xe.hasOwnProperty,tu=0,ru=Xe.toString,eu=Kn._,uu=Ze(\"^\"+Qe.call(nu).replace(/[\\\\^$.*+?()[\\]{}|]/g,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\"),ou=_.ArrayBuffer,iu=_.clearTimeout,fu=_.parseFloat,au=Pe.pow,cu=Xe.propertyIsEnumerable,lu=jr(_,\"Set\"),su=_.setTimeout,pu=Je.splice,hu=_.Uint8Array,_u=jr(_,\"WeakMap\"),vu=Pe.ceil,gu=jr(Ve,\"create\"),yu=Pe.floor,du=jr(Be,\"isArray\"),mu=_.isFinite,wu=jr(Ve,\"keys\"),bu=Pe.max,xu=Pe.min,Au=jr(De,\"now\"),ju=_.parseInt,ku=Pe.random,Iu=Ke.NEGATIVE_INFINITY,Ru=Ke.POSITIVE_INFINITY,Ou=4294967294,Eu=2147483647,Cu=9007199254740991,Uu=_u&&new _u,Wu={};\nNn.support={},Nn.templateSettings={escape:_n,evaluate:vn,interpolate:gn,variable:\"\",imports:{_:Nn}};var $u=function(){function n(){}return function(t){if(ge(t)){n.prototype=t;var r=new n;n.prototype=w}return r||{}}}(),Su=Vt(_t),Fu=Vt(vt,true),Nu=Zt(),Tu=Zt(true),Lu=Uu?function(n,t){return Uu.set(n,t),n}:Fe,zu=Uu?function(n){return Uu.get(n)}:Le,Bu=jt(\"length\"),Du=function(){var n=0,t=0;return function(r,e){var u=ho(),o=S-(u-t);if(t=u,0<o){if(++n>=$)return r}else n=0;return Lu(r,e)}}(),Mu=le(function(n,t){\nreturn h(n)&&Er(n)?ft(n,pt(t,false,true)):[]}),qu=tr(),Pu=tr(true),Ku=le(function(n){for(var t=n.length,e=t,u=Be(l),o=xr(),i=o==r,f=[];e--;){var a=n[e]=Er(a=n[e])?a:[];u[e]=i&&120<=a.length&&gu&&lu?new Dn(e&&a):null}var i=n[0],c=-1,l=i?i.length:0,s=u[0];n:for(;++c<l;)if(a=i[c],0>(s?Mn(s,a):o(f,a,0))){for(e=t;--e;){var p=u[e];if(0>(p?Mn(p,a):o(n[e],a,0)))continue n}s&&s.push(a),f.push(a)}return f}),Vu=le(function(t,r){r=pt(r);var e=rt(t,r);return It(t,r.sort(n)),e}),Zu=vr(),Yu=vr(true),Gu=le(function(n){return St(pt(n,false,true));\n}),Ju=le(function(n,t){return Er(n)?ft(n,t):[]}),Xu=le(Jr),Hu=le(function(n){var t=n.length,r=2<t?n[t-2]:w,e=1<t?n[t-1]:w;return 2<t&&typeof r==\"function\"?t-=2:(r=1<t&&typeof e==\"function\"?(--t,e):w,e=w),n.length=t,Xr(n,r,e)}),Qu=le(function(n){return n=pt(n),this.thru(function(t){t=Oo(t)?t:[Br(t)];for(var r=n,e=-1,u=t.length,o=-1,i=r.length,f=Be(u+i);++e<u;)f[e]=t[e];for(;++o<i;)f[e++]=r[o];return f})}),no=le(function(n,t){return rt(n,pt(t))}),to=Pt(function(n,t,r){nu.call(n,r)?++n[r]:n[r]=1}),ro=nr(Su),eo=nr(Fu,true),uo=ur(Pn,Su),oo=ur(function(n,t){\nfor(var r=n.length;r--&&false!==t(n[r],r,n););return n},Fu),io=Pt(function(n,t,r){nu.call(n,r)?n[r].push(t):n[r]=[t]}),fo=Pt(function(n,t,r){n[r]=t}),ao=le(function(n,t,r){var e=-1,u=typeof t==\"function\",o=Wr(t),i=Er(n)?Be(n.length):[];return Su(n,function(n){var f=u?t:o&&null!=n?n[t]:w;i[++e]=f?f.apply(n,r):Or(n,t,r)}),i}),co=Pt(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),lo=lr(Xn,Su),so=lr(function(n,t,r,e){var u=n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r},Fu),po=le(function(n,t){\nif(null==n)return[];var r=t[2];return r&&Ur(t[0],t[1],r)&&(t.length=1),Wt(n,pt(t),[])}),ho=Au||function(){return(new De).getTime()},_o=le(function(n,t,r){var e=x;if(r.length)var u=v(r,_o.placeholder),e=e|R;return gr(n,e,t,r,u)}),vo=le(function(n,t){t=t.length?pt(t):Ie(n);for(var r=-1,e=t.length;++r<e;){var u=t[r];n[u]=gr(n[u],x,n)}return n}),go=le(function(n,t,r){var e=x|A;if(r.length)var u=v(r,go.placeholder),e=e|R;return gr(t,e,n,r,u)}),yo=Xt(k),mo=Xt(I),wo=le(function(n,t){return it(n,1,t)}),bo=le(function(n,t,r){\nreturn it(n,t,r)}),xo=er(),Ao=er(true),jo=le(function(n,t){if(t=pt(t),typeof n!=\"function\"||!Zn(t,e))throw new Ge(L);var r=t.length;return le(function(e){for(var u=xu(e.length,r);u--;)e[u]=t[u](e[u]);return n.apply(this,e)})}),ko=cr(R),Io=cr(O),Ro=le(function(n,t){return gr(n,C,w,w,w,pt(t))}),Oo=du||function(n){return h(n)&&Sr(n.length)&&ru.call(n)==D},Eo=Kt(At),Co=Kt(function(n,t,r){return r?nt(n,t,r):tt(n,t)}),Uo=Ht(Co,function(n,t){return n===w?t:n}),Wo=Ht(Eo,Fr),$o=rr(_t),So=rr(vt),Fo=or(Nu),No=or(Tu),To=ir(_t),Lo=ir(vt),zo=wu?function(n){\nvar t=null==n?w:n.constructor;return typeof t==\"function\"&&t.prototype===n||typeof n!=\"function\"&&Er(n)?Lr(n):ge(n)?wu(n):[]}:Lr,Bo=fr(true),Do=fr(),Mo=le(function(n,t){if(null==n)return{};if(\"function\"!=typeof t[0])return t=Gn(pt(t),Ye),Nr(n,ft(Re(n),t));var r=Bt(t[0],t[1],3);return Tr(n,function(n,t,e){return!r(n,t,e)})}),qo=le(function(n,t){return null==n?{}:\"function\"==typeof t[0]?Tr(n,Bt(t[0],t[1],3)):Nr(n,pt(t))}),Po=Gt(function(n,t,r){return t=t.toLowerCase(),n+(r?t.charAt(0).toUpperCase()+t.slice(1):t);\n}),Ko=Gt(function(n,t,r){return n+(r?\"-\":\"\")+t.toLowerCase()}),Vo=ar(),Zo=ar(true),Yo=Gt(function(n,t,r){return n+(r?\"_\":\"\")+t.toLowerCase()}),Go=Gt(function(n,t,r){return n+(r?\" \":\"\")+(t.charAt(0).toUpperCase()+t.slice(1))}),Jo=le(function(n,t){try{return n.apply(w,t)}catch(r){return _e(r)?r:new Me(r)}}),Xo=le(function(n,t){return function(r){return Or(r,n,t)}}),Ho=le(function(n,t){return function(r){return Or(n,r,t)}}),Qo=_r(\"ceil\"),ni=_r(\"floor\"),ti=Qt(se,Iu),ri=Qt(Ae,Ru),ei=_r(\"round\");return Nn.prototype=Tn.prototype,\nLn.prototype=$u(Tn.prototype),Ln.prototype.constructor=Ln,zn.prototype=$u(Tn.prototype),zn.prototype.constructor=zn,Bn.prototype[\"delete\"]=function(n){return this.has(n)&&delete this.__data__[n]},Bn.prototype.get=function(n){return\"__proto__\"==n?w:this.__data__[n]},Bn.prototype.has=function(n){return\"__proto__\"!=n&&nu.call(this.__data__,n)},Bn.prototype.set=function(n,t){return\"__proto__\"!=n&&(this.__data__[n]=t),this},Dn.prototype.push=function(n){var t=this.data;typeof n==\"string\"||ge(n)?t.set.add(n):t.hash[n]=true;\n},ce.Cache=Bn,Nn.after=function(n,t){if(typeof t!=\"function\"){if(typeof n!=\"function\")throw new Ge(L);var r=n;n=t,t=r}return n=mu(n=+n)?n:0,function(){return 1>--n?t.apply(this,arguments):void 0}},Nn.ary=function(n,t,r){return r&&Ur(n,t,r)&&(t=w),t=n&&null==t?n.length:bu(+t||0,0),gr(n,E,w,w,w,w,t)},Nn.assign=Co,Nn.at=no,Nn.before=fe,Nn.bind=_o,Nn.bindAll=vo,Nn.bindKey=go,Nn.callback=Se,Nn.chain=Qr,Nn.chunk=function(n,t,r){t=(r?Ur(n,t,r):null==t)?1:bu(yu(t)||1,1),r=0;for(var e=n?n.length:0,u=-1,o=Be(vu(e/t));r<e;)o[++u]=Et(n,r,r+=t);\nreturn o},Nn.compact=function(n){for(var t=-1,r=n?n.length:0,e=-1,u=[];++t<r;){var o=n[t];o&&(u[++e]=o)}return u},Nn.constant=function(n){return function(){return n}},Nn.countBy=to,Nn.create=function(n,t,r){var e=$u(n);return r&&Ur(n,t,r)&&(t=w),t?tt(e,t):e},Nn.curry=yo,Nn.curryRight=mo,Nn.debounce=ae,Nn.defaults=Uo,Nn.defaultsDeep=Wo,Nn.defer=wo,Nn.delay=bo,Nn.difference=Mu,Nn.drop=qr,Nn.dropRight=Pr,Nn.dropRightWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3),true,true):[]},Nn.dropWhile=function(n,t,r){\nreturn n&&n.length?Nt(n,wr(t,r,3),true):[]},Nn.fill=function(n,t,r,e){var u=n?n.length:0;if(!u)return[];for(r&&typeof r!=\"number\"&&Ur(n,t,r)&&(r=0,e=u),u=n.length,r=null==r?0:+r||0,0>r&&(r=-r>u?0:u+r),e=e===w||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;r<u;)n[r++]=t;return n},Nn.filter=re,Nn.flatten=function(n,t,r){var e=n?n.length:0;return r&&Ur(n,t,r)&&(t=false),e?pt(n,t):[]},Nn.flattenDeep=function(n){return n&&n.length?pt(n,true):[]},Nn.flow=xo,Nn.flowRight=Ao,Nn.forEach=uo,Nn.forEachRight=oo,Nn.forIn=Fo,\nNn.forInRight=No,Nn.forOwn=To,Nn.forOwnRight=Lo,Nn.functions=Ie,Nn.groupBy=io,Nn.indexBy=fo,Nn.initial=function(n){return Pr(n,1)},Nn.intersection=Ku,Nn.invert=function(n,t,r){r&&Ur(n,t,r)&&(t=w),r=-1;for(var e=zo(n),u=e.length,o={};++r<u;){var i=e[r],f=n[i];t?nu.call(o,f)?o[f].push(i):o[f]=[i]:o[f]=i}return o},Nn.invoke=ao,Nn.keys=zo,Nn.keysIn=Re,Nn.map=ue,Nn.mapKeys=Bo,Nn.mapValues=Do,Nn.matches=Ne,Nn.matchesProperty=function(n,t){return xt(n,ot(t,true))},Nn.memoize=ce,Nn.merge=Eo,Nn.method=Xo,Nn.methodOf=Ho,\nNn.mixin=Te,Nn.modArgs=jo,Nn.negate=function(n){if(typeof n!=\"function\")throw new Ge(L);return function(){return!n.apply(this,arguments)}},Nn.omit=Mo,Nn.once=function(n){return fe(2,n)},Nn.pairs=Oe,Nn.partial=ko,Nn.partialRight=Io,Nn.partition=co,Nn.pick=qo,Nn.pluck=function(n,t){return ue(n,ze(t))},Nn.property=ze,Nn.propertyOf=function(n){return function(t){return yt(n,Dr(t),t+\"\")}},Nn.pull=function(){var n=arguments,t=n[0];if(!t||!t.length)return t;for(var r=0,e=xr(),u=n.length;++r<u;)for(var o=0,i=n[r];-1<(o=e(t,i,o));)pu.call(t,o,1);\nreturn t},Nn.pullAt=Vu,Nn.range=function(n,t,r){r&&Ur(n,t,r)&&(t=r=w),n=+n||0,r=null==r?1:+r||0,null==t?(t=n,n=0):t=+t||0;var e=-1;t=bu(vu((t-n)/(r||1)),0);for(var u=Be(t);++e<t;)u[e]=n,n+=r;return u},Nn.rearg=Ro,Nn.reject=function(n,t,r){var e=Oo(n)?Yn:lt;return t=wr(t,r,3),e(n,function(n,r,e){return!t(n,r,e)})},Nn.remove=function(n,t,r){var e=[];if(!n||!n.length)return e;var u=-1,o=[],i=n.length;for(t=wr(t,r,3);++u<i;)r=n[u],t(r,u,n)&&(e.push(r),o.push(u));return It(n,o),e},Nn.rest=Yr,Nn.restParam=le,\nNn.set=function(n,t,r){if(null==n)return n;var e=t+\"\";t=null!=n[e]||Wr(t,n)?[e]:Dr(t);for(var e=-1,u=t.length,o=u-1,i=n;null!=i&&++e<u;){var f=t[e];ge(i)&&(e==o?i[f]=r:null==i[f]&&(i[f]=Cr(t[e+1])?[]:{})),i=i[f]}return n},Nn.shuffle=function(n){return oe(n,Ru)},Nn.slice=function(n,t,r){var e=n?n.length:0;return e?(r&&typeof r!=\"number\"&&Ur(n,t,r)&&(t=0,r=e),Et(n,t,r)):[]},Nn.sortBy=function(n,t,r){if(null==n)return[];r&&Ur(n,t,r)&&(t=w);var e=-1;return t=wr(t,r,3),n=wt(n,function(n,r,u){return{a:t(n,r,u),\nb:++e,c:n}}),Ut(n,f)},Nn.sortByAll=po,Nn.sortByOrder=function(n,t,r,e){return null==n?[]:(e&&Ur(t,r,e)&&(r=w),Oo(t)||(t=null==t?[]:[t]),Oo(r)||(r=null==r?[]:[r]),Wt(n,t,r))},Nn.spread=function(n){if(typeof n!=\"function\")throw new Ge(L);return function(t){return n.apply(this,t)}},Nn.take=function(n,t,r){return n&&n.length?((r?Ur(n,t,r):null==t)&&(t=1),Et(n,0,0>t?0:t)):[]},Nn.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0>t?0:t)):[]},Nn.takeRightWhile=function(n,t,r){\nreturn n&&n.length?Nt(n,wr(t,r,3),false,true):[]},Nn.takeWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3)):[]},Nn.tap=function(n,t,r){return t.call(r,n),n},Nn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!=\"function\")throw new Ge(L);return false===r?e=false:ge(r)&&(e=\"leading\"in r?!!r.leading:e,u=\"trailing\"in r?!!r.trailing:u),ae(n,t,{leading:e,maxWait:+t,trailing:u})},Nn.thru=ne,Nn.times=function(n,t,r){if(n=yu(n),1>n||!mu(n))return[];var e=-1,u=Be(xu(n,4294967295));for(t=Bt(t,r,1);++e<n;)4294967295>e?u[e]=t(e):t(e);\nreturn u},Nn.toArray=je,Nn.toPlainObject=ke,Nn.transform=function(n,t,r,e){var u=Oo(n)||xe(n);return t=wr(t,e,4),null==r&&(u||ge(n)?(e=n.constructor,r=u?Oo(n)?new e:[]:$u(ve(e)?e.prototype:w)):r={}),(u?Pn:_t)(n,function(n,e,u){return t(r,n,e,u)}),r},Nn.union=Gu,Nn.uniq=Gr,Nn.unzip=Jr,Nn.unzipWith=Xr,Nn.values=Ee,Nn.valuesIn=function(n){return Ft(n,Re(n))},Nn.where=function(n,t){return re(n,bt(t))},Nn.without=Ju,Nn.wrap=function(n,t){return t=null==t?Fe:t,gr(t,R,w,[n],[])},Nn.xor=function(){for(var n=-1,t=arguments.length;++n<t;){\nvar r=arguments[n];if(Er(r))var e=e?Jn(ft(e,r),ft(r,e)):r}return e?St(e):[]},Nn.zip=Xu,Nn.zipObject=Hr,Nn.zipWith=Hu,Nn.backflow=Ao,Nn.collect=ue,Nn.compose=Ao,Nn.each=uo,Nn.eachRight=oo,Nn.extend=Co,Nn.iteratee=Se,Nn.methods=Ie,Nn.object=Hr,Nn.select=re,Nn.tail=Yr,Nn.unique=Gr,Te(Nn,Nn),Nn.add=function(n,t){return(+n||0)+(+t||0)},Nn.attempt=Jo,Nn.camelCase=Po,Nn.capitalize=function(n){return(n=u(n))&&n.charAt(0).toUpperCase()+n.slice(1)},Nn.ceil=Qo,Nn.clone=function(n,t,r,e){return t&&typeof t!=\"boolean\"&&Ur(n,t,r)?t=false:typeof t==\"function\"&&(e=r,\nr=t,t=false),typeof r==\"function\"?ot(n,t,Bt(r,e,1)):ot(n,t)},Nn.cloneDeep=function(n,t,r){return typeof t==\"function\"?ot(n,true,Bt(t,r,1)):ot(n,true)},Nn.deburr=Ce,Nn.endsWith=function(n,t,r){n=u(n),t+=\"\";var e=n.length;return r=r===w?e:xu(0>r?0:+r||0,e),r-=t.length,0<=r&&n.indexOf(t,r)==r},Nn.escape=function(n){return(n=u(n))&&hn.test(n)?n.replace(sn,c):n},Nn.escapeRegExp=function(n){return(n=u(n))&&bn.test(n)?n.replace(wn,l):n||\"(?:)\"},Nn.every=te,Nn.find=ro,Nn.findIndex=qu,Nn.findKey=$o,Nn.findLast=eo,\nNn.findLastIndex=Pu,Nn.findLastKey=So,Nn.findWhere=function(n,t){return ro(n,bt(t))},Nn.first=Kr,Nn.floor=ni,Nn.get=function(n,t,r){return n=null==n?w:yt(n,Dr(t),t+\"\"),n===w?r:n},Nn.gt=se,Nn.gte=function(n,t){return n>=t},Nn.has=function(n,t){if(null==n)return false;var r=nu.call(n,t);if(!r&&!Wr(t)){if(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),null==n)return false;t=Zr(t),r=nu.call(n,t)}return r||Sr(n.length)&&Cr(t,n.length)&&(Oo(n)||pe(n))},Nn.identity=Fe,Nn.includes=ee,Nn.indexOf=Vr,Nn.inRange=function(n,t,r){\nreturn t=+t||0,r===w?(r=t,t=0):r=+r||0,n>=xu(t,r)&&n<bu(t,r)},Nn.isArguments=pe,Nn.isArray=Oo,Nn.isBoolean=function(n){return true===n||false===n||h(n)&&ru.call(n)==M},Nn.isDate=function(n){return h(n)&&ru.call(n)==q},Nn.isElement=function(n){return!!n&&1===n.nodeType&&h(n)&&!me(n)},Nn.isEmpty=function(n){return null==n?true:Er(n)&&(Oo(n)||be(n)||pe(n)||h(n)&&ve(n.splice))?!n.length:!zo(n).length},Nn.isEqual=he,Nn.isError=_e,Nn.isFinite=function(n){return typeof n==\"number\"&&mu(n)},Nn.isFunction=ve,Nn.isMatch=function(n,t,r,e){\nreturn r=typeof r==\"function\"?Bt(r,e,3):w,mt(n,Ar(t),r)},Nn.isNaN=function(n){return de(n)&&n!=+n},Nn.isNative=ye,Nn.isNull=function(n){return null===n},Nn.isNumber=de,Nn.isObject=ge,Nn.isPlainObject=me,Nn.isRegExp=we,Nn.isString=be,Nn.isTypedArray=xe,Nn.isUndefined=function(n){return n===w},Nn.kebabCase=Ko,Nn.last=Zr,Nn.lastIndexOf=function(n,t,r){var e=n?n.length:0;if(!e)return-1;var u=e;if(typeof r==\"number\")u=(0>r?bu(e+r,0):xu(r||0,e-1))+1;else if(r)return u=Lt(n,t,true)-1,n=n[u],(t===t?t===n:n!==n)?u:-1;\nif(t!==t)return p(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},Nn.lt=Ae,Nn.lte=function(n,t){return n<=t},Nn.max=ti,Nn.min=ri,Nn.noConflict=function(){return Kn._=eu,this},Nn.noop=Le,Nn.now=ho,Nn.pad=function(n,t,r){n=u(n),t=+t;var e=n.length;return e<t&&mu(t)?(e=(t-e)/2,t=yu(e),e=vu(e),r=pr(\"\",e,r),r.slice(0,t)+n+r):n},Nn.padLeft=Vo,Nn.padRight=Zo,Nn.parseInt=function(n,t,r){return(r?Ur(n,t,r):null==t)?t=0:t&&(t=+t),n=We(n),ju(n,t||(In.test(n)?16:10))},Nn.random=function(n,t,r){r&&Ur(n,t,r)&&(t=r=w);\nvar e=null==n,u=null==t;return null==r&&(u&&typeof n==\"boolean\"?(r=n,n=1):typeof t==\"boolean\"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=ku(),xu(n+r*(t-n+fu(\"1e-\"+((r+\"\").length-1))),t)):Rt(n,t)},Nn.reduce=lo,Nn.reduceRight=so,Nn.repeat=Ue,Nn.result=function(n,t,r){var e=null==n?w:n[t];return e===w&&(null==n||Wr(t,n)||(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),e=null==n?w:n[Zr(t)]),e=e===w?r:e),ve(e)?e.call(n):e},Nn.round=ei,Nn.runInContext=m,Nn.size=function(n){var t=n?Bu(n):0;\nreturn Sr(t)?t:zo(n).length},Nn.snakeCase=Yo,Nn.some=ie,Nn.sortedIndex=Zu,Nn.sortedLastIndex=Yu,Nn.startCase=Go,Nn.startsWith=function(n,t,r){return n=u(n),r=null==r?0:xu(0>r?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Nn.sum=function(n,t,r){if(r&&Ur(n,t,r)&&(t=w),t=wr(t,r,3),1==t.length){n=Oo(n)?n:zr(n),r=n.length;for(var e=0;r--;)e+=+t(n[r])||0;n=e}else n=$t(n,t);return n},Nn.template=function(n,t,r){var e=Nn.templateSettings;r&&Ur(n,t,r)&&(t=r=w),n=u(n),t=nt(tt({},r||t),e,Qn),r=nt(tt({},t.imports),e.imports,Qn);\nvar o,i,f=zo(r),a=Ft(r,f),c=0;r=t.interpolate||Cn;var l=\"__p+='\";r=Ze((t.escape||Cn).source+\"|\"+r.source+\"|\"+(r===gn?jn:Cn).source+\"|\"+(t.evaluate||Cn).source+\"|$\",\"g\");var p=\"sourceURL\"in t?\"//# sourceURL=\"+t.sourceURL+\"\\n\":\"\";if(n.replace(r,function(t,r,e,u,f,a){return e||(e=u),l+=n.slice(c,a).replace(Un,s),r&&(o=true,l+=\"'+__e(\"+r+\")+'\"),f&&(i=true,l+=\"';\"+f+\";\\n__p+='\"),e&&(l+=\"'+((__t=(\"+e+\"))==null?'':__t)+'\"),c=a+t.length,t}),l+=\"';\",(t=t.variable)||(l=\"with(obj){\"+l+\"}\"),l=(i?l.replace(fn,\"\"):l).replace(an,\"$1\").replace(cn,\"$1;\"),\nl=\"function(\"+(t||\"obj\")+\"){\"+(t?\"\":\"obj||(obj={});\")+\"var __t,__p=''\"+(o?\",__e=_.escape\":\"\")+(i?\",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}\":\";\")+l+\"return __p}\",t=Jo(function(){return qe(f,p+\"return \"+l).apply(w,a)}),t.source=l,_e(t))throw t;return t},Nn.trim=We,Nn.trimLeft=function(n,t,r){var e=n;return(n=u(n))?n.slice((r?Ur(e,t,r):null==t)?g(n):o(n,t+\"\")):n},Nn.trimRight=function(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+\"\")+1):n;\n},Nn.trunc=function(n,t,r){r&&Ur(n,t,r)&&(t=w);var e=U;if(r=W,null!=t)if(ge(t)){var o=\"separator\"in t?t.separator:o,e=\"length\"in t?+t.length||0:e;r=\"omission\"in t?u(t.omission):r}else e=+t||0;if(n=u(n),e>=n.length)return n;if(e-=r.length,1>e)return r;if(t=n.slice(0,e),null==o)return t+r;if(we(o)){if(n.slice(e).search(o)){var i,f=n.slice(0,e);for(o.global||(o=Ze(o.source,(kn.exec(o)||\"\")+\"g\")),o.lastIndex=0;n=o.exec(f);)i=n.index;t=t.slice(0,null==i?e:i)}}else n.indexOf(o,e)!=e&&(o=t.lastIndexOf(o),\n-1<o&&(t=t.slice(0,o)));return t+r},Nn.unescape=function(n){return(n=u(n))&&pn.test(n)?n.replace(ln,d):n},Nn.uniqueId=function(n){var t=++tu;return u(n)+t},Nn.words=$e,Nn.all=te,Nn.any=ie,Nn.contains=ee,Nn.eq=he,Nn.detect=ro,Nn.foldl=lo,Nn.foldr=so,Nn.head=Kr,Nn.include=ee,Nn.inject=lo,Te(Nn,function(){var n={};return _t(Nn,function(t,r){Nn.prototype[r]||(n[r]=t)}),n}(),false),Nn.sample=oe,Nn.prototype.sample=function(n){return this.__chain__||null!=n?this.thru(function(t){return oe(t,n)}):oe(this.value());\n},Nn.VERSION=b,Pn(\"bind bindKey curry curryRight partial partialRight\".split(\" \"),function(n){Nn[n].placeholder=Nn}),Pn([\"drop\",\"take\"],function(n,t){zn.prototype[n]=function(r){var e=this.__filtered__;if(e&&!t)return new zn(this);r=null==r?1:bu(yu(r)||0,0);var u=this.clone();return e?u.__takeCount__=xu(u.__takeCount__,r):u.__views__.push({size:r,type:n+(0>u.__dir__?\"Right\":\"\")}),u},zn.prototype[n+\"Right\"]=function(t){return this.reverse()[n](t).reverse()}}),Pn([\"filter\",\"map\",\"takeWhile\"],function(n,t){\nvar r=t+1,e=r!=T;zn.prototype[n]=function(n,t){var u=this.clone();return u.__iteratees__.push({iteratee:wr(n,t,1),type:r}),u.__filtered__=u.__filtered__||e,u}}),Pn([\"first\",\"last\"],function(n,t){var r=\"take\"+(t?\"Right\":\"\");zn.prototype[n]=function(){return this[r](1).value()[0]}}),Pn([\"initial\",\"rest\"],function(n,t){var r=\"drop\"+(t?\"\":\"Right\");zn.prototype[n]=function(){return this.__filtered__?new zn(this):this[r](1)}}),Pn([\"pluck\",\"where\"],function(n,t){var r=t?\"filter\":\"map\",e=t?bt:ze;zn.prototype[n]=function(n){\nreturn this[r](e(n))}}),zn.prototype.compact=function(){return this.filter(Fe)},zn.prototype.reject=function(n,t){return n=wr(n,t,1),this.filter(function(t){return!n(t)})},zn.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=this;return r.__filtered__&&(0<n||0>t)?new zn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==w&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r)},zn.prototype.takeRightWhile=function(n,t){return this.reverse().takeWhile(n,t).reverse()},zn.prototype.toArray=function(){return this.take(Ru);\n},_t(zn.prototype,function(n,t){var r=/^(?:filter|map|reject)|While$/.test(t),e=/^(?:first|last)$/.test(t),u=Nn[e?\"take\"+(\"last\"==t?\"Right\":\"\"):t];u&&(Nn.prototype[t]=function(){function t(n){return e&&i?u(n,1)[0]:u.apply(w,Jn([n],o))}var o=e?[1]:arguments,i=this.__chain__,f=this.__wrapped__,a=!!this.__actions__.length,c=f instanceof zn,l=o[0],s=c||Oo(f);return s&&r&&typeof l==\"function\"&&1!=l.length&&(c=s=false),l={func:ne,args:[t],thisArg:w},a=c&&!a,e&&!i?a?(f=f.clone(),f.__actions__.push(l),n.call(f)):u.call(w,this.value())[0]:!e&&s?(f=a?f:new zn(this),\nf=n.apply(f,o),f.__actions__.push(l),new Ln(f,i)):this.thru(t)})}),Pn(\"join pop push replace shift sort splice split unshift\".split(\" \"),function(n){var t=(/^(?:replace|split)$/.test(n)?He:Je)[n],r=/^(?:push|sort|unshift)$/.test(n)?\"tap\":\"thru\",e=/^(?:join|pop|replace|shift)$/.test(n);Nn.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),_t(zn.prototype,function(n,t){var r=Nn[t];if(r){var e=r.name;(Wu[e]||(Wu[e]=[])).push({\nname:t,func:r})}}),Wu[sr(w,A).name]=[{name:\"wrapper\",func:w}],zn.prototype.clone=function(){var n=new zn(this.__wrapped__);return n.__actions__=qn(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=qn(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=qn(this.__views__),n},zn.prototype.reverse=function(){if(this.__filtered__){var n=new zn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},zn.prototype.value=function(){\nvar n,t=this.__wrapped__.value(),r=this.__dir__,e=Oo(t),u=0>r,o=e?t.length:0;n=o;for(var i=this.__views__,f=0,a=-1,c=i.length;++a<c;){var l=i[a],s=l.size;switch(l.type){case\"drop\":f+=s;break;case\"dropRight\":n-=s;break;case\"take\":n=xu(n,f+s);break;case\"takeRight\":f=bu(f,n-s)}}if(n={start:f,end:n},i=n.start,f=n.end,n=f-i,i=u?f:i-1,f=this.__iteratees__,a=f.length,c=0,l=xu(n,this.__takeCount__),!e||o<F||o==n&&l==n)return Tt(u&&e?t.reverse():t,this.__actions__);e=[];n:for(;n--&&c<l;){for(i+=r,u=-1,o=t[i];++u<a;){\nvar p=f[u],s=p.type,p=p.iteratee(o);if(s==T)o=p;else if(!p){if(s==N)continue n;break n}}e[c++]=o}return e},Nn.prototype.chain=function(){return Qr(this)},Nn.prototype.commit=function(){return new Ln(this.value(),this.__chain__)},Nn.prototype.concat=Qu,Nn.prototype.plant=function(n){for(var t,r=this;r instanceof Tn;){var e=Mr(r);t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},Nn.prototype.reverse=function(){function n(n){return r&&0>r.__dir__?n:n.reverse()}var t=this.__wrapped__;\nif(t instanceof zn){var r=t;return this.__actions__.length&&(r=new zn(this)),r=r.reverse(),r.__actions__.push({func:ne,args:[n],thisArg:w}),new Ln(r,this.__chain__)}return this.thru(n)},Nn.prototype.toString=function(){return this.value()+\"\"},Nn.prototype.run=Nn.prototype.toJSON=Nn.prototype.valueOf=Nn.prototype.value=function(){return Tt(this.__wrapped__,this.__actions__)},Nn.prototype.collect=Nn.prototype.map,Nn.prototype.head=Nn.prototype.first,Nn.prototype.select=Nn.prototype.filter,Nn.prototype.tail=Nn.prototype.rest,\nNn}var w,b=\"3.10.0\",x=1,A=2,j=4,k=8,I=16,R=32,O=64,E=128,C=256,U=30,W=\"...\",$=150,S=16,F=200,N=1,T=2,L=\"Expected a function\",z=\"__lodash_placeholder__\",B=\"[object Arguments]\",D=\"[object Array]\",M=\"[object Boolean]\",q=\"[object Date]\",P=\"[object Error]\",K=\"[object Function]\",V=\"[object Number]\",Z=\"[object Object]\",Y=\"[object RegExp]\",G=\"[object String]\",J=\"[object ArrayBuffer]\",X=\"[object Float32Array]\",H=\"[object Float64Array]\",Q=\"[object Int8Array]\",nn=\"[object Int16Array]\",tn=\"[object Int32Array]\",rn=\"[object Uint8Array]\",en=\"[object Uint8ClampedArray]\",un=\"[object Uint16Array]\",on=\"[object Uint32Array]\",fn=/\\b__p\\+='';/g,an=/\\b(__p\\+=)''\\+/g,cn=/(__e\\(.*?\\)|\\b__t\\))\\+'';/g,ln=/&(?:amp|lt|gt|quot|#39|#96);/g,sn=/[&<>\"'`]/g,pn=RegExp(ln.source),hn=RegExp(sn.source),_n=/<%-([\\s\\S]+?)%>/g,vn=/<%([\\s\\S]+?)%>/g,gn=/<%=([\\s\\S]+?)%>/g,yn=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*?\\1)\\]/,dn=/^\\w*$/,mn=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\n\\\\]|\\\\.)*?)\\2)\\]/g,wn=/^[:!,]|[\\\\^$.*+?()[\\]{}|\\/]|(^[0-9a-fA-Fnrtuvx])|([\\n\\r\\u2028\\u2029])/g,bn=RegExp(wn.source),xn=/[\\u0300-\\u036f\\ufe20-\\ufe23]/g,An=/\\\\(\\\\)?/g,jn=/\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g,kn=/\\w*$/,In=/^0[xX]/,Rn=/^\\[object .+?Constructor\\]$/,On=/^\\d+$/,En=/[\\xc0-\\xd6\\xd8-\\xde\\xdf-\\xf6\\xf8-\\xff]/g,Cn=/($^)/,Un=/['\\n\\r\\u2028\\u2029\\\\]/g,Wn=RegExp(\"[A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde]+(?=[A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde][a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff]+)|[A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde]?[a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff]+|[A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde]+|[0-9]+\",\"g\"),$n=\"Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout isFinite parseFloat parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap\".split(\" \"),Sn={};\nSn[X]=Sn[H]=Sn[Q]=Sn[nn]=Sn[tn]=Sn[rn]=Sn[en]=Sn[un]=Sn[on]=true,Sn[B]=Sn[D]=Sn[J]=Sn[M]=Sn[q]=Sn[P]=Sn[K]=Sn[\"[object Map]\"]=Sn[V]=Sn[Z]=Sn[Y]=Sn[\"[object Set]\"]=Sn[G]=Sn[\"[object WeakMap]\"]=false;var Fn={};Fn[B]=Fn[D]=Fn[J]=Fn[M]=Fn[q]=Fn[X]=Fn[H]=Fn[Q]=Fn[nn]=Fn[tn]=Fn[V]=Fn[Z]=Fn[Y]=Fn[G]=Fn[rn]=Fn[en]=Fn[un]=Fn[on]=true,Fn[P]=Fn[K]=Fn[\"[object Map]\"]=Fn[\"[object Set]\"]=Fn[\"[object WeakMap]\"]=false;var Nn={\"\\xc0\":\"A\",\"\\xc1\":\"A\",\"\\xc2\":\"A\",\"\\xc3\":\"A\",\"\\xc4\":\"A\",\"\\xc5\":\"A\",\"\\xe0\":\"a\",\"\\xe1\":\"a\",\"\\xe2\":\"a\",\n\"\\xe3\":\"a\",\"\\xe4\":\"a\",\"\\xe5\":\"a\",\"\\xc7\":\"C\",\"\\xe7\":\"c\",\"\\xd0\":\"D\",\"\\xf0\":\"d\",\"\\xc8\":\"E\",\"\\xc9\":\"E\",\"\\xca\":\"E\",\"\\xcb\":\"E\",\"\\xe8\":\"e\",\"\\xe9\":\"e\",\"\\xea\":\"e\",\"\\xeb\":\"e\",\"\\xcc\":\"I\",\"\\xcd\":\"I\",\"\\xce\":\"I\",\"\\xcf\":\"I\",\"\\xec\":\"i\",\"\\xed\":\"i\",\"\\xee\":\"i\",\"\\xef\":\"i\",\"\\xd1\":\"N\",\"\\xf1\":\"n\",\"\\xd2\":\"O\",\"\\xd3\":\"O\",\"\\xd4\":\"O\",\"\\xd5\":\"O\",\"\\xd6\":\"O\",\"\\xd8\":\"O\",\"\\xf2\":\"o\",\"\\xf3\":\"o\",\"\\xf4\":\"o\",\"\\xf5\":\"o\",\"\\xf6\":\"o\",\"\\xf8\":\"o\",\"\\xd9\":\"U\",\"\\xda\":\"U\",\"\\xdb\":\"U\",\"\\xdc\":\"U\",\"\\xf9\":\"u\",\"\\xfa\":\"u\",\"\\xfb\":\"u\",\"\\xfc\":\"u\",\"\\xdd\":\"Y\",\n\"\\xfd\":\"y\",\"\\xff\":\"y\",\"\\xc6\":\"Ae\",\"\\xe6\":\"ae\",\"\\xde\":\"Th\",\"\\xfe\":\"th\",\"\\xdf\":\"ss\"},Tn={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\",\"`\":\"&#96;\"},Ln={\"&amp;\":\"&\",\"&lt;\":\"<\",\"&gt;\":\">\",\"&quot;\":'\"',\"&#39;\":\"'\",\"&#96;\":\"`\"},zn={\"function\":true,object:true},Bn={0:\"x30\",1:\"x31\",2:\"x32\",3:\"x33\",4:\"x34\",5:\"x35\",6:\"x36\",7:\"x37\",8:\"x38\",9:\"x39\",A:\"x41\",B:\"x42\",C:\"x43\",D:\"x44\",E:\"x45\",F:\"x46\",a:\"x61\",b:\"x62\",c:\"x63\",d:\"x64\",e:\"x65\",f:\"x66\",n:\"x6e\",r:\"x72\",t:\"x74\",u:\"x75\",v:\"x76\",x:\"x78\"},Dn={\"\\\\\":\"\\\\\",\n\"'\":\"'\",\"\\n\":\"n\",\"\\r\":\"r\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},Mn=zn[typeof module]&&module&&!module.nodeType&&module,qn=zn[typeof self]&&self&&self.Object&&self,Pn=zn[typeof window]&&window&&window.Object&&window,Kn=zn[typeof exports]&&exports&&!exports.nodeType&&exports&&Mn&&typeof global==\"object\"&&global&&global.Object&&global||Pn!==(this&&this.window)&&Pn||qn||this,Vn=m();typeof define==\"function\"&&typeof define.amd==\"object\"&&define.amd&& define(function(){return Vn})}).call(this);"
  },
  {
    "path": "src/thirdparty/murmurhash3_gc.js",
    "content": "/* Public Domain MurmurHash3 implementation. Altered to have AMD header and function wrapper. */\n\ndefine(function (require, exports, module) {\n\n/*\n *  The MurmurHash3 algorithm was created by Austin Appleby.  This JavaScript port was authored\n *  by Peter Zotov (based on Java port by Yonik Seeley) and is placed into the public domain.\n *  The author hereby disclaims copyright to this source code.\n *\n *  This produces exactly the same hash values as the final C++ version of MurmurHash3 and\n *  is thus suitable for producing the same hash values across platforms.\n *\n *  There are two versions of this hash implementation. First interprets the string as a\n *  sequence of bytes, ignoring most significant byte of each codepoint. The second one\n *  interprets the string as a UTF-16 codepoint sequence, and appends each 16-bit codepoint\n *  to the hash independently. The latter mode was not written to be compatible with\n *  any other implementation, but it should offer better performance for JavaScript-only\n *  applications.\n *\n *  See http://github.com/whitequark/murmurhash3-js for future updates to this file.\n */\n\nvar MurmurHash3 = {\n\tmul32: function(m, n) {\n\t\tvar nlo = n & 0xffff;\n\t\tvar nhi = n - nlo;\n\t\treturn ((nhi * m | 0) + (nlo * m | 0)) | 0;\n\t},\n\n\thashBytes: function(data, len, seed) {\n\t\tvar c1 = 0xcc9e2d51, c2 = 0x1b873593;\n\n\t\tvar h1 = seed;\n\t\tvar roundedEnd = len & ~0x3;\n\n\t\tfor (var i = 0; i < roundedEnd; i += 4) {\n\t\t\tvar k1 = (data.charCodeAt(i)     & 0xff)        |\n\t\t\t\t((data.charCodeAt(i + 1) & 0xff) << 8)  |\n\t\t\t\t((data.charCodeAt(i + 2) & 0xff) << 16) |\n\t\t\t\t((data.charCodeAt(i + 3) & 0xff) << 24);\n\n\t\t\tk1 = this.mul32(k1, c1);\n\t\t\tk1 = ((k1 & 0x1ffff) << 15) | (k1 >>> 17);  // ROTL32(k1,15);\n\t\t\tk1 = this.mul32(k1, c2);\n\n\t\t\th1 ^= k1;\n\t\t\th1 = ((h1 & 0x7ffff) << 13) | (h1 >>> 19);  // ROTL32(h1,13);\n\t\t\th1 = (h1 * 5 + 0xe6546b64) | 0;\n\t\t}\n\n\t\tk1 = 0;\n\n\t\tswitch(len % 4) {\n\t\t\tcase 3:\n\t\t\t\tk1 = (data.charCodeAt(roundedEnd + 2) & 0xff) << 16;\n\t\t\t\t// fallthrough\n\t\t\tcase 2:\n\t\t\t\tk1 |= (data.charCodeAt(roundedEnd + 1) & 0xff) << 8;\n\t\t\t\t// fallthrough\n\t\t\tcase 1:\n\t\t\t\tk1 |= (data.charCodeAt(roundedEnd) & 0xff);\n\t\t\t\tk1 = this.mul32(k1, c1);\n\t\t\t\tk1 = ((k1 & 0x1ffff) << 15) | (k1 >>> 17);  // ROTL32(k1,15);\n\t\t\t\tk1 = this.mul32(k1, c2);\n\t\t\t\th1 ^= k1;\n\t\t}\n\n\t\t// finalization\n\t\th1 ^= len;\n\n\t\t// fmix(h1);\n\t\th1 ^= h1 >>> 16;\n\t\th1  = this.mul32(h1, 0x85ebca6b);\n\t\th1 ^= h1 >>> 13;\n\t\th1  = this.mul32(h1, 0xc2b2ae35);\n\t\th1 ^= h1 >>> 16;\n\n\t\treturn h1;\n\t},\n\n\thashString: function(data, len, seed) {\n\t\tvar c1 = 0xcc9e2d51, c2 = 0x1b873593;\n\n\t\tvar h1 = seed;\n\t\tvar roundedEnd = len & ~0x1;\n\n\t\tfor (var i = 0; i < roundedEnd; i += 2) {\n\t\t\tvar k1 = data.charCodeAt(i) | (data.charCodeAt(i + 1) << 16);\n\n\t\t\tk1 = this.mul32(k1, c1);\n\t\t\tk1 = ((k1 & 0x1ffff) << 15) | (k1 >>> 17);  // ROTL32(k1,15);\n\t\t\tk1 = this.mul32(k1, c2);\n\n\t\t\th1 ^= k1;\n\t\t\th1 = ((h1 & 0x7ffff) << 13) | (h1 >>> 19);  // ROTL32(h1,13);\n\t\t\th1 = (h1 * 5 + 0xe6546b64) | 0;\n\t\t}\n\n\t\tif((len % 2) == 1) {\n\t\t\tk1 = data.charCodeAt(roundedEnd);\n\t\t\tk1 = this.mul32(k1, c1);\n\t\t\tk1 = ((k1 & 0x1ffff) << 15) | (k1 >>> 17);  // ROTL32(k1,15);\n\t\t\tk1 = this.mul32(k1, c2);\n\t\t\th1 ^= k1;\n\t\t}\n\n\t\t// finalization\n\t\th1 ^= (len << 1);\n\n\t\t// fmix(h1);\n\t\th1 ^= h1 >>> 16;\n\t\th1  = this.mul32(h1, 0x85ebca6b);\n\t\th1 ^= h1 >>> 13;\n\t\th1  = this.mul32(h1, 0xc2b2ae35);\n\t\th1 ^= h1 >>> 16;\n\n\t\treturn h1;\n\t}\n};\n\nif(typeof module !== \"undefined\" && typeof module.exports !== \"undefined\") {\n\tmodule.exports = MurmurHash3;\n}\n});"
  },
  {
    "path": "src/utils/AnimationUtils.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities for dealing with animations in the UI.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _     = require(\"thirdparty/lodash\"),\n        Async = require(\"utils/Async\");\n\n    /**\n     * @private\n     * Detect the browser's supported transitionend event.\n     * @return {string} The supported transitionend event name.\n     */\n    function _detectTransitionEvent() {\n        var event, el = window.document.createElement(\"fakeelement\");\n\n        var transitions = {\n            \"OTransition\"     : \"oTransitionEnd\",\n            \"MozTransition\"   : \"transitionend\",\n            \"WebkitTransition\": \"webkitTransitionEnd\",\n            \"transition\"      : \"transitionend\"\n        };\n\n        _.forEach(transitions, function (value, key) {\n            if (el.style[key] !== undefined) {\n                event = value;\n            }\n        });\n        return event;\n    }\n\n    var _transitionEvent = _detectTransitionEvent();\n\n    /**\n     * Start an animation by adding the given class to the given target. When the\n     * animation is complete, removes the class, clears the event handler we attach\n     * to watch for the animation to finish, and resolves the returned promise.\n     *\n     * @param {Element} target The DOM node to animate.\n     * @param {string} animClass The class that applies the animation/transition to the target.\n     * @param {number=} timeoutDuration Time to wait in ms before rejecting promise. Default is 400.\n     * @return {$.Promise} A promise that is resolved when the animation completes. Never rejected.\n     */\n    function animateUsingClass(target, animClass, timeoutDuration) {\n        var result  = new $.Deferred(),\n            $target = $(target);\n\n        timeoutDuration = timeoutDuration || 400;\n\n        function finish(e) {\n            if (e.target === target) {\n                result.resolve();\n            }\n        }\n\n        function cleanup() {\n            $target\n                .removeClass(animClass)\n                .off(_transitionEvent, finish);\n        }\n\n        if ($target.is(\":hidden\")) {\n            // Don't do anything if the element is hidden because transitionEnd wouldn't fire\n            result.resolve();\n        } else {\n            // Note that we can't just use $.one() here because we only want to remove\n            // the handler when we get the transition end event for the correct target (not\n            // a child).\n            $target\n                .addClass(animClass)\n                .on(_transitionEvent, finish);\n        }\n\n        // Use timeout in case transition end event is not sent\n        return Async.withTimeout(result.promise(), timeoutDuration, true)\n            .done(cleanup);\n    }\n\n    exports.animateUsingClass = animateUsingClass;\n});\n"
  },
  {
    "path": "src/utils/AppInit.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Defines hooks to assist with module initialization.\n *\n * This module defines 3 methods for client modules to attach callbacks:\n *    - htmlReady - When the main application template is rendered\n *    - extensionsLoaded - When the extension manager has loaded all extensions\n *    - appReady - When Brackets completes loading all modules and extensions\n *\n * These are *not* jQuery events. Each method is similar to $(document).ready\n * in that it will call the handler immediately if brackets is already done\n * loading.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /*\n     * Fires when the base htmlContent/main-view.html is loaded\n     * @type {string}\n     * @const\n     */\n    var HTML_READY  = \"htmlReady\";\n\n    /*\n     * Fires when all extensions are loaded\n     * @type {string}\n     * @const\n     */\n    var APP_READY   = \"appReady\";\n\n    /*\n     * Fires after extensions have been loaded\n     * @type {string}\n     * @const\n     */\n    var EXTENSIONS_LOADED = \"extensionsLoaded\";\n\n    /*\n     * Map of each state's trigger\n     * @type {Object.<string, boolean>}\n     * @private\n     */\n    var _status      = { HTML_READY : false, APP_READY : false, EXTENSIONS_LOADED: false };\n\n    /*\n     * Map of callbacks to states\n     * @type {Object.<string, Array.<function()>>}\n     * @private\n     */\n    var _callbacks   = {};\n\n    _callbacks[HTML_READY]        = [];\n    _callbacks[APP_READY]         = [];\n    _callbacks[EXTENSIONS_LOADED] = [];\n\n\n    /*\n     * calls the specified handler inside a try/catch handler\n     * @param {function()} handler - the callback to call\n     * @private\n     */\n    function _callHandler(handler) {\n        try {\n            // TODO (issue 1034): We *could* use a $.Deferred for this, except deferred objects enter a broken\n            // state if any resolution callback throws an exception. Since third parties (e.g. extensions) may\n            // add callbacks to this, we need to be robust to exceptions\n            handler();\n        } catch (e) {\n            console.error(\"Exception when calling a 'brackets done loading' handler: \" + e);\n            console.log(e.stack);\n        }\n    }\n\n    /*\n     * dispatches the event by calling all handlers registered for that type\n     * @param {string} type - the event type to dispatch (APP_READY, EXTENSIONS_READY, HTML_READY)\n     * @private\n     */\n    function _dispatchReady(type) {\n        var i,\n            myHandlers = _callbacks[type];\n\n        // mark this status complete\n        _status[type] = true;\n\n        for (i = 0; i < myHandlers.length; i++) {\n            _callHandler(myHandlers[i]);\n        }\n\n        // clear all callbacks after being called\n        _callbacks[type] = [];\n    }\n\n    /*\n     * adds a callback to the list of functions to call for the specified event type\n     * @param {string} type - the event type to dispatch (APP_READY, EXTENSIONS_READY, HTML_READY)\n     * @param {function} handler - callback funciton to call when the event is triggered\n     * @private\n     */\n    function _addListener(type, handler) {\n        if (_status[type]) {\n            _callHandler(handler);\n        } else {\n            _callbacks[type].push(handler);\n        }\n    }\n\n    /**\n     * Adds a callback for the ready hook. Handlers are called after\n     * htmlReady is done, the initial project is loaded, and all extensions are\n     * loaded.\n     * @param {function} handler - callback function to call when the event is fired\n     */\n    function appReady(handler) {\n        _addListener(APP_READY, handler);\n    }\n\n    /**\n     * Adds a callback for the htmlReady hook. Handlers are called after the\n     * main application html template is rendered.\n     * @param {function} handler - callback function to call when the event is fired\n     */\n    function htmlReady(handler) {\n        _addListener(HTML_READY, handler);\n    }\n\n    /**\n     * Adds a callback for the extensionsLoaded hook. Handlers are called after the\n     * extensions have been loaded\n     * @param {function} handler - callback function to call when the event is fired\n     */\n    function extensionsLoaded(handler) {\n        _addListener(EXTENSIONS_LOADED, handler);\n    }\n\n    // Public API\n    exports.appReady = appReady;\n    exports.htmlReady = htmlReady;\n    exports.extensionsLoaded = extensionsLoaded;\n\n    exports.HTML_READY = HTML_READY;\n    exports.APP_READY = APP_READY;\n    exports.EXTENSIONS_LOADED = EXTENSIONS_LOADED;\n\n    // Unit Test API\n    exports._dispatchReady = _dispatchReady;\n});\n"
  },
  {
    "path": "src/utils/Async.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities for working with Deferred, Promise, and other asynchronous processes.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Further ideas for Async utilities...\n    //  - Utilities for blocking UI until a Promise completes?\n    //  - A \"SuperDeferred\" could feature some very useful enhancements:\n    //     - API for cancellation (non guaranteed, best attempt)\n    //     - Easier way to add a timeout clause (withTimeout() wrapper below is more verbose)\n    //     - Encapsulate the task kickoff code so you can start it later, e.g. superDeferred.start()\n    //  - Deferred/Promise are unable to do anything akin to a 'finally' block. It'd be nice if we\n    //    could harvest exceptions across all steps of an async process and pipe them to a handler,\n    //    so that we don't leave UI-blocking overlays up forever, etc. But this is hard: we'd have\n    //    wrap every async callback (including low-level native ones that don't use [Super]Deferred)\n    //    to catch exceptions, and then understand which Deferred(s) the code *would* have resolved/\n    //    rejected had it run to completion.\n\n\n    /**\n     * Executes a series of tasks in parallel, returning a \"master\" Promise that is resolved once\n     * all the tasks have resolved. If one or more tasks fail, behavior depends on the failFast\n     * flag:\n     *   - If true, the master Promise is rejected as soon as the first task fails. The remaining\n     *     tasks continue to completion in the background.\n     *   - If false, the master Promise is rejected after all tasks have completed.\n     *\n     * If nothing fails:          (M = master promise; 1-4 = tasks; d = done; F = fail)\n     *  M  ------------d\n     *  1 >---d        .\n     *  2 >------d     .\n     *  3 >---------d  .\n     *  4 >------------d\n     *\n     * With failFast = false:\n     *  M  ------------F\n     *  1 >---d     .  .\n     *  2 >------d  .  .\n     *  3 >---------F  .\n     *  4 >------------d\n     *\n     * With failFast = true: -- equivalent to $.when()\n     *  M  ---------F\n     *  1 >---d     .\n     *  2 >------d  .\n     *  3 >---------F\n     *  4 >------------d   (#4 continues even though master Promise has failed)\n     * (Note: if tasks finish synchronously, the behavior is more like failFast=false because you\n     * won't get a chance to respond to the master Promise until after all items have been processed)\n     *\n     * To perform task-specific work after an individual task completes, attach handlers to each\n     * Promise before beginProcessItem() returns it.\n     *\n     * Note: don't use this if individual tasks (or their done/fail handlers) could ever show a user-\n     * visible dialog: because they run in parallel, you could show multiple dialogs atop each other.\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @param {!boolean} failFast\n     * @return {$.Promise}\n     */\n    function doInParallel(items, beginProcessItem, failFast) {\n        var promises = [];\n        var masterDeferred = new $.Deferred();\n\n        if (items.length === 0) {\n            masterDeferred.resolve();\n\n        } else {\n            var numCompleted = 0;\n            var hasFailed = false;\n\n            items.forEach(function (item, i) {\n                var itemPromise = beginProcessItem(item, i);\n                promises.push(itemPromise);\n\n                itemPromise.fail(function () {\n                    if (failFast) {\n                        masterDeferred.reject();\n                    } else {\n                        hasFailed = true;\n                    }\n                });\n                itemPromise.always(function () {\n                    numCompleted++;\n                    if (numCompleted === items.length) {\n                        if (hasFailed) {\n                            masterDeferred.reject();\n                        } else {\n                            masterDeferred.resolve();\n                        }\n                    }\n                });\n            });\n\n        }\n\n        return masterDeferred.promise();\n    }\n\n    /**\n     * Executes a series of tasks in serial (task N does not begin until task N-1 has completed).\n     * Returns a \"master\" Promise that is resolved once all the tasks have resolved. If one or more\n     * tasks fail, behavior depends on the failAndStopFast flag:\n     *   - If true, the master Promise is rejected as soon as the first task fails. The remaining\n     *     tasks are never started (the serial sequence is stopped).\n     *   - If false, the master Promise is rejected after all tasks have completed.\n     *\n     * If nothing fails:\n     *  M  ------------d\n     *  1 >---d        .\n     *  2     >--d     .\n     *  3        >--d  .\n     *  4           >--d\n     *\n     * With failAndStopFast = false:\n     *  M  ------------F\n     *  1 >---d     .  .\n     *  2     >--d  .  .\n     *  3        >--F  .\n     *  4           >--d\n     *\n     * With failAndStopFast = true:\n     *  M  ---------F\n     *  1 >---d     .\n     *  2     >--d  .\n     *  3        >--F\n     *  4          (#4 never runs)\n     *\n     * To perform task-specific work after an individual task completes, attach handlers to each\n     * Promise before beginProcessItem() returns it.\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @param {!boolean} failAndStopFast\n     * @return {$.Promise}\n     */\n    function doSequentially(items, beginProcessItem, failAndStopFast) {\n\n        var masterDeferred = new $.Deferred(),\n            hasFailed = false;\n\n        function doItem(i) {\n            if (i >= items.length) {\n                if (hasFailed) {\n                    masterDeferred.reject();\n                } else {\n                    masterDeferred.resolve();\n                }\n                return;\n            }\n\n            var itemPromise = beginProcessItem(items[i], i);\n\n            itemPromise.done(function () {\n                doItem(i + 1);\n            });\n            itemPromise.fail(function () {\n                if (failAndStopFast) {\n                    masterDeferred.reject();\n                    // note: we do NOT process any further items in this case\n                } else {\n                    hasFailed = true;\n                    doItem(i + 1);\n                }\n            });\n        }\n\n        doItem(0);\n\n        return masterDeferred.promise();\n    }\n\n    /**\n     * Executes a series of synchronous tasks sequentially spread over time-slices less than maxBlockingTime.\n     * Processing yields by idleTime between time-slices.\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number)} fnProcessItem  Function that synchronously processes one item\n     * @param {number=} maxBlockingTime\n     * @param {number=} idleTime\n     * @return {$.Promise}\n     */\n    function doSequentiallyInBackground(items, fnProcessItem, maxBlockingTime, idleTime) {\n\n        maxBlockingTime = maxBlockingTime || 15;\n        idleTime = idleTime || 30;\n\n        var sliceStartTime = (new Date()).getTime();\n\n        return doSequentially(items, function (item, i) {\n            var result = new $.Deferred();\n\n            // process the next item\n            fnProcessItem(item, i);\n\n            // if we've exhausted our maxBlockingTime\n            if ((new Date()).getTime() - sliceStartTime >= maxBlockingTime) {\n                //yield\n                window.setTimeout(function () {\n                    sliceStartTime = (new Date()).getTime();\n                    result.resolve();\n                }, idleTime);\n            } else {\n                //continue processing\n                result.resolve();\n            }\n\n            return result;\n        }, false);\n    }\n\n    /**\n     * Executes a series of tasks in serial (task N does not begin until task N-1 has completed).\n     * Returns a \"master\" Promise that is resolved when the first task has resolved. If all tasks\n     * fail, the master Promise is rejected.\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @return {$.Promise}\n     */\n    function firstSequentially(items, beginProcessItem) {\n\n        var masterDeferred = new $.Deferred();\n\n        function doItem(i) {\n            if (i >= items.length) {\n                masterDeferred.reject();\n                return;\n            }\n\n            beginProcessItem(items[i], i)\n                .fail(function () {\n                    doItem(i + 1);\n                })\n                .done(function () {\n                    masterDeferred.resolve(items[i]);\n                });\n        }\n\n        doItem(0);\n        return masterDeferred.promise();\n    }\n\n    /**\n     * Executes a series of tasks in parallel, saving up error info from any that fail along the way.\n     * Returns a Promise that is only resolved/rejected once all tasks are complete. This is\n     * essentially a wrapper around doInParallel(..., false).\n     *\n     * If one or more tasks failed, the entire \"master\" promise is rejected at the end - with one\n     * argument: an array objects, one per failed task. Each error object contains:\n     *  - item -- the entry in items whose task failed\n     *  - error -- the first argument passed to the fail() handler when the task failed\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @return {$.Promise}\n     */\n    function doInParallel_aggregateErrors(items, beginProcessItem) {\n        var errors = [];\n\n        var masterDeferred = new $.Deferred();\n\n        var parallelResult = doInParallel(\n            items,\n            function (item, i) {\n                var itemResult = beginProcessItem(item, i);\n                itemResult.fail(function (error) {\n                    errors.push({ item: item, error: error });\n                });\n                return itemResult;\n            },\n            false\n        );\n\n        parallelResult\n            .done(function () {\n                masterDeferred.resolve();\n            })\n            .fail(function () {\n                masterDeferred.reject(errors);\n            });\n\n        return masterDeferred.promise();\n    }\n\n    /** Value passed to fail() handlers that have been triggered due to withTimeout()'s timeout */\n    var ERROR_TIMEOUT = {};\n\n    /**\n     * Adds timeout-driven termination to a Promise: returns a new Promise that is resolved/rejected when\n     * the given original Promise is resolved/rejected, OR is resolved/rejected after the given delay -\n     * whichever happens first.\n     *\n     * If the original Promise is resolved/rejected first, done()/fail() handlers receive arguments\n     * piped from the original Promise. If the timeout occurs first instead, then resolve() or\n     * fail() (with Async.ERROR_TIMEOUT) is called based on value of resolveTimeout.\n     *\n     * @param {$.Promise} promise\n     * @param {number} timeout\n     * @param {boolean=} resolveTimeout If true, then resolve deferred on timeout, otherwise reject. Default is false.\n     * @return {$.Promise}\n     */\n    function withTimeout(promise, timeout, resolveTimeout) {\n        var wrapper = new $.Deferred();\n\n        var timer = window.setTimeout(function () {\n            if (resolveTimeout) {\n                wrapper.resolve();\n            } else {\n                wrapper.reject(ERROR_TIMEOUT);\n            }\n        }, timeout);\n        promise.always(function () {\n            window.clearTimeout(timer);\n        });\n\n        // If the wrapper was already rejected due to timeout, the Promise's calls to resolve/reject\n        // won't do anything\n        promise.then(wrapper.resolve, wrapper.reject);\n\n        return wrapper.promise();\n    }\n\n    /**\n     * Allows waiting for all the promises to be either resolved or rejected.\n     * Unlike $.when(), it does not call .fail() or .always() handlers on first\n     * reject. The caller should take all the precaution to make sure all the\n     * promises passed to this function are completed to avoid blocking.\n     *\n     * If failOnReject is set to true, promise returned by the function will be\n     * rejected if at least one of the promises was rejected. The default value\n     * is false, which will cause the call to this function to be always\n     * successfully resolved.\n     *\n     * If timeout is specified, the promise will be rejected on timeout as per\n     * Async.withTimeout.\n     *\n     * @param {!Array.<$.Promise>} promises Array of promises to wait for\n     * @param {boolean=} failOnReject       Whether to reject or not if one of the promises has been rejected.\n     * @param {number=} timeout             Number of milliseconds to wait until rejecting the promise\n     *\n     * @return {$.Promise} A Promise which will be resolved once all dependent promises are resolved.\n     *                     It is resolved with an array of results from the successfully resolved dependent promises.\n     *                     The resulting array may not be in the same order or contain as many items as there were\n     *                     promises to wait on and it will contain 'undefined' entries for those promises that resolve\n     *                     without a result.\n     *\n     */\n    function waitForAll(promises, failOnReject, timeout) {\n        var masterDeferred = new $.Deferred(),\n            results = [],\n            count = 0,\n            sawRejects = false;\n\n        if (!promises || promises.length === 0) {\n            masterDeferred.resolve();\n            return masterDeferred.promise();\n        }\n\n        // set defaults if needed\n        failOnReject = (failOnReject === undefined) ? false : true;\n\n        if (timeout !== undefined) {\n            withTimeout(masterDeferred, timeout);\n        }\n\n        promises.forEach(function (promise) {\n            promise\n                .fail(function (err) {\n                    sawRejects = true;\n                })\n                .done(function (result) {\n                    results.push(result);\n                })\n                .always(function () {\n                    count++;\n                    if (count === promises.length) {\n                        if (failOnReject && sawRejects) {\n                            masterDeferred.reject();\n                        } else {\n                            masterDeferred.resolve(results);\n                        }\n                    }\n                });\n        });\n\n        return masterDeferred.promise();\n    }\n\n    /**\n     * Chains a series of synchronous and asynchronous (jQuery promise-returning) functions\n     * together, using the result of each successive function as the argument(s) to the next.\n     * A promise is returned that resolves with the result of the final call if all calls\n     * resolve or return normally. Otherwise, if any of the functions reject or throw, the\n     * computation is halted immediately and the promise is rejected with this halting error.\n     *\n     * @param {Array.<function(*)>} functions Functions to be chained\n     * @param {?Array} args Arguments to call the first function with\n     * @return {jQuery.Promise} A promise that resolves with the result of the final call, or\n     *      rejects with the first error.\n     */\n    function chain(functions, args) {\n        var deferred = $.Deferred();\n\n        function chainHelper(index, args) {\n            if (functions.length === index) {\n                deferred.resolveWith(null, args);\n            } else {\n                var nextFunction = functions[index++];\n                try {\n                    var responseOrPromise = nextFunction.apply(null, args);\n                    if (responseOrPromise.hasOwnProperty(\"done\") &&\n                            responseOrPromise.hasOwnProperty(\"fail\")) {\n                        responseOrPromise.done(function () {\n                            chainHelper(index, arguments);\n                        });\n                        responseOrPromise.fail(function () {\n                            deferred.rejectWith(null, arguments);\n                        });\n                    } else {\n                        chainHelper(index, [responseOrPromise]);\n                    }\n                } catch (e) {\n                    deferred.reject(e);\n                }\n            }\n        }\n\n        chainHelper(0, args || []);\n\n        return deferred.promise();\n    }\n\n    /**\n     * Utility for converting a method that takes (error, callback) to one that returns a promise;\n     * useful for using FileSystem methods (or other Node-style API methods) in a promise-oriented\n     * workflow. For example, instead of\n     *\n     *      var deferred = new $.Deferred();\n     *      file.read(function (err, contents) {\n     *          if (err) {\n     *              deferred.reject(err);\n     *          } else {\n     *              // ...process the contents...\n     *              deferred.resolve();\n     *          }\n     *      }\n     *      return deferred.promise();\n     *\n     * you can just do\n     *\n     *      return Async.promisify(file, \"read\").then(function (contents) {\n     *          // ...process the contents...\n     *      });\n     *\n     * The object/method are passed as an object/string pair so that we can\n     * properly call the method without the caller having to deal with \"bind\" all the time.\n     *\n     * @param {Object} obj The object to call the method on.\n     * @param {string} method The name of the method. The method should expect the errback\n     *      as its last parameter.\n     * @param {...Object} varargs The arguments you would have normally passed to the method\n     *      (excluding the errback itself).\n     * @return {$.Promise} A promise that is resolved with the arguments that were passed to the\n     *      errback (not including the err argument) if err is null, or rejected with the err if\n     *      non-null.\n     */\n    function promisify(obj, method) {\n        var result = new $.Deferred(),\n            args = Array.prototype.slice.call(arguments, 2);\n        args.push(function (err) {\n            if (err) {\n                result.reject(err);\n            } else {\n                result.resolve.apply(result, Array.prototype.slice.call(arguments, 1));\n            }\n        });\n        obj[method].apply(obj, args);\n        return result.promise();\n    }\n\n    /**\n     * Creates a queue of async operations that will be executed sequentially. Operations can be added to the\n     * queue at any time. If the queue is empty and nothing is currently executing when an operation is added,\n     * it will execute immediately. Otherwise, it will execute when the last operation currently in the queue\n     * has finished.\n     * @constructor\n     */\n    function PromiseQueue() {\n        this._queue = [];\n    }\n\n    /**\n     * @private\n     * @type {Array.<function(): $.Promise>}\n     * The queue of operations to execute sequentially. Note that even if this array is empty, there might\n     * still be an operation we need to wait on; that operation's promise is stored in _curPromise.\n     */\n    PromiseQueue.prototype._queue = null;\n\n    /**\n     * @private\n     * @type {$.Promise}\n     * The promise we're currently waiting on, or null if there's nothing currently executing.\n     */\n    PromiseQueue.prototype._curPromise = null;\n\n    /**\n     * @type {number} The number of queued promises.\n     */\n    Object.defineProperties(PromiseQueue.prototype, {\n        \"length\": {\n            get: function () { return this._queue.length; },\n            set: function () { throw new Error(\"Cannot set length\"); }\n        }\n    });\n\n    /**\n     * Adds an operation to the queue. If nothing is currently executing, it will execute immediately (and\n     * the next operation added to the queue will wait for it to complete). Otherwise, it will wait until\n     * the last operation in the queue (or the currently executing operation if nothing is in the queue) is\n     * finished. The operation must return a promise that will be resolved or rejected when it's finished;\n     * the queue will continue with the next operation regardless of whether the current operation's promise\n     * is resolved or rejected.\n     * @param {function(): $.Promise} op The operation to add to the queue.\n     */\n    PromiseQueue.prototype.add = function (op) {\n        this._queue.push(op);\n\n        // If something is currently executing, then _doNext() will get called when it's done. If nothing\n        // is executing (in which case the queue should have been empty), we need to call _doNext() to kickstart\n        // the queue.\n        if (!this._curPromise) {\n            this._doNext();\n        }\n    };\n\n    /**\n     * Removes all pending promises from the queue.\n     */\n    PromiseQueue.prototype.removeAll = function () {\n        this._queue = [];\n    };\n\n    /**\n     * @private\n     * Pulls the next operation off the queue and executes it.\n     */\n    PromiseQueue.prototype._doNext = function () {\n        var self = this;\n        if (this._queue.length) {\n            var op = this._queue.shift();\n            this._curPromise = op();\n            this._curPromise.always(function () {\n                self._curPromise = null;\n                self._doNext();\n            });\n        }\n    };\n\n    // Define public API\n    exports.doInParallel        = doInParallel;\n    exports.doSequentially      = doSequentially;\n    exports.doSequentiallyInBackground   = doSequentiallyInBackground;\n    exports.doInParallel_aggregateErrors = doInParallel_aggregateErrors;\n    exports.firstSequentially   = firstSequentially;\n    exports.withTimeout         = withTimeout;\n    exports.waitForAll          = waitForAll;\n    exports.ERROR_TIMEOUT       = ERROR_TIMEOUT;\n    exports.chain               = chain;\n    exports.promisify           = promisify;\n    exports.PromiseQueue        = PromiseQueue;\n});\n"
  },
  {
    "path": "src/utils/BuildInfoUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities for determining the git SHA from an optional repository or from the\n * installed copy of Brackets.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var FileSystem  = require(\"filesystem/FileSystem\"),\n        FileUtils   = require(\"file/FileUtils\");\n\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    /**\n     * Loads a SHA from Git metadata file. If the file contains a symbolic ref name, follows the ref\n     * and loads the SHA from that file in turn.\n     */\n    function _loadSHA(path, callback) {\n        var result = new $.Deferred();\n\n        if (brackets.inBrowser) {\n            result.reject();\n        } else {\n            // HEAD contains a SHA in detached-head mode; otherwise it contains a relative path\n            // to a file in /refs which in turn contains the SHA\n            var file = FileSystem.getFileForPath(path);\n            FileUtils.readAsText(file).done(function (text) {\n                if (text.indexOf(\"ref: \") === 0) {\n                    // e.g. \"ref: refs/heads/branchname\"\n                    var basePath    = path.substr(0, path.lastIndexOf(\"/\")),\n                        refRelPath  = text.substr(5).trim(),\n                        branch      = text.substr(16).trim();\n\n                    _loadSHA(basePath + \"/\" + refRelPath, callback).done(function (data) {\n                        result.resolve({ branch: branch, sha: data.sha.trim() });\n                    }).fail(function () {\n                        result.resolve({ branch: branch });\n                    });\n                } else {\n                    result.resolve({ sha: text });\n                }\n            }).fail(function () {\n                result.reject();\n            });\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * @return {$.Promise} A promise resolved with the git branch and SHA\n     *     of a local copy of a repository or the branch and SHA\n     *     embedded at build-time in the package.json repository metadata.\n     */\n    function getBracketsSHA() {\n        var result = new $.Deferred();\n\n        // Look for Git metadata on disk to load the SHAs for 'brackets'. Done on\n        // startup instead of on demand because the version that's currently running is what was\n        // loaded at startup (the src on disk may be updated to a different version later).\n        // Git metadata may be missing (e.g. in the release builds) - silently ignore if so.\n        var bracketsSrc = FileUtils.getNativeBracketsDirectoryPath();\n\n        // Assumes Brackets is a standalone repo and not a submodule (prior to brackets-shell,\n        // brackets-app was setup this way)\n        var bracketsGitRoot = bracketsSrc.substr(0, bracketsSrc.lastIndexOf(\"/\")) + \"/.git/HEAD\";\n\n        _loadSHA(bracketsGitRoot).done(function (data) {\n            // Found a repository\n            result.resolve(data.branch || \"HEAD\", data.sha || \"unknown\", true);\n        }).fail(function () {\n            // If package.json has repository data, Brackets is running from the installed /www folder\n            result.resolve(brackets.metadata.repository.branch, brackets.metadata.repository.SHA, false);\n        });\n\n        return result.promise();\n    }\n\n    exports.getBracketsSHA      = getBracketsSHA;\n\n    // FIXME (jasonsanjose): Since the move to brackets-shell, can't reliably get SHA for shell.\n    // exports._getBracketsShellSHA = getBracketsShellSHA;\n});\n"
  },
  {
    "path": "src/utils/ColorUtils.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n *  Utilities functions related to color matching\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * Sorted array of all the color names in the CSS Color Module Level 3 (http://www.w3.org/TR/css3-color/)\n     * and \"rebeccapurple\" from CSS Color Module Level 4\n     * @const @type {Array}\n     */\n    var COLOR_NAMES = [\"aliceblue\", \"antiquewhite\", \"aqua\", \"aquamarine\", \"azure\", \"beige\", \"bisque\", \"black\", \"blanchedalmond\", \"blue\", \"blueviolet\", \"brown\", \"burlywood\", \"cadetblue\", \"chartreuse\", \"chocolate\", \"coral\", \"cornflowerblue\", \"cornsilk\", \"crimson\", \"cyan\", \"darkblue\", \"darkcyan\", \"darkgoldenrod\", \"darkgray\", \"darkgreen\", \"darkgrey\", \"darkkhaki\", \"darkmagenta\", \"darkolivegreen\", \"darkorange\", \"darkorchid\", \"darkred\", \"darksalmon\", \"darkseagreen\", \"darkslateblue\", \"darkslategray\", \"darkslategrey\", \"darkturquoise\", \"darkviolet\", \"deeppink\", \"deepskyblue\", \"dimgray\", \"dimgrey\", \"dodgerblue\", \"firebrick\", \"floralwhite\", \"forestgreen\", \"fuchsia\", \"gainsboro\", \"ghostwhite\", \"gold\", \"goldenrod\", \"gray\", \"green\", \"greenyellow\", \"grey\", \"honeydew\", \"hotpink\", \"indianred\", \"indigo\", \"ivory\", \"khaki\", \"lavender\", \"lavenderblush\", \"lawngreen\", \"lemonchiffon\", \"lightblue\", \"lightcoral\", \"lightcyan\", \"lightgoldenrodyellow\", \"lightgray\", \"lightgreen\", \"lightgrey\", \"lightpink\", \"lightsalmon\", \"lightseagreen\", \"lightskyblue\", \"lightslategray\", \"lightslategrey\", \"lightsteelblue\", \"lightyellow\", \"lime\", \"limegreen\", \"linen\", \"magenta\", \"maroon\", \"mediumaquamarine\", \"mediumblue\", \"mediumorchid\", \"mediumpurple\", \"mediumseagreen\", \"mediumslateblue\", \"mediumspringgreen\", \"mediumturquoise\", \"mediumvioletred\", \"midnightblue\", \"mintcream\", \"mistyrose\", \"moccasin\", \"navajowhite\", \"navy\", \"oldlace\", \"olive\", \"olivedrab\", \"orange\", \"orangered\", \"orchid\", \"palegoldenrod\", \"palegreen\", \"paleturquoise\", \"palevioletred\", \"papayawhip\", \"peachpuff\", \"peru\", \"pink\", \"plum\", \"powderblue\", \"purple\", \"rebeccapurple\", \"red\", \"rosybrown\", \"royalblue\", \"saddlebrown\", \"salmon\", \"sandybrown\", \"seagreen\", \"seashell\", \"sienna\", \"silver\", \"skyblue\", \"slateblue\", \"slategray\", \"slategrey\", \"snow\", \"springgreen\", \"steelblue\", \"tan\", \"teal\", \"thistle\", \"tomato\", \"turquoise\", \"violet\", \"wheat\", \"white\", \"whitesmoke\", \"yellow\", \"yellowgreen\"];\n\n    /**\n     * Regular expression that matches reasonably well-formed colors in hex format (3 or 6 digits),\n     * rgb()/rgba() function format, hsl()/hsla() function format, 0x notation format\n     * or color name format according to CSS Color Module Level 3 (http://www.w3.org/TR/css3-color/)\n     * or \"rebeccapurple\" from CSS Color Module Level 4.\n     * @const @type {RegExp}\n     */\n    // use RegExp.source of the RegExp literal to avoid doubled backslashes\n    var COLOR_REGEX = new RegExp(/0x([a-f0-9]{6})\\b|#[a-f0-9]{6}\\b|#[a-f0-9]{3}\\b|\\brgb\\(\\s*(?:[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*(?:[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*(?:[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\\s*\\)|\\brgb\\(\\s*(?:[0-9]{1,2}%|100%)\\s*,\\s*(?:[0-9]{1,2}%|100%)\\s*,\\s*(?:[0-9]{1,2}%|100%)\\s*\\)|\\brgba\\(\\s*(?:[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*(?:[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*(?:[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\\s*,\\s*(?:1|1\\.0|0|0?\\.[0-9]{1,3})\\s*\\)|\\brgba\\(\\s*(?:[0-9]{1,2}%|100%)\\s*,\\s*(?:[0-9]{1,2}%|100%)\\s*,\\s*(?:[0-9]{1,2}%|100%)\\s*,\\s*(?:1|1\\.0|0|0?\\.[0-9]{1,3})\\s*\\)|\\bhsl\\(\\s*(?:[0-9]{1,3})\\b\\s*,\\s*(?:[0-9]{1,2}|100)\\b%\\s*,\\s*(?:[0-9]{1,2}|100)\\b%\\s*\\)|\\bhsla\\(\\s*(?:[0-9]{1,3})\\b\\s*,\\s*(?:[0-9]{1,2}|100)\\b%\\s*,\\s*(?:[0-9]{1,2}|100)\\b%\\s*,\\s*(?:1|1\\.0|0|0?\\.[0-9]{1,3})\\s*\\)|\\b/.source + COLOR_NAMES.join(\"\\\\b|\\\\b\") + \"\\\\b\", \"gi\");\n\n    /*\n     * Adds a color swatch to code hints where this is supported.\n     * @param {!jQuery} $hintObj - list item where the swatch will be in\n     * @param {?string} color - color the swatch should have, or null to add extra left margin to\n     *      align with the other hints\n     * @return {jQuery} jQuery object with the correct class and/or style applied\n     */\n    function formatColorHint($hintObj, color) {\n        if (color) {\n            $hintObj.prepend($(\"<span>\")\n                .addClass(\"color-swatch\")\n                .css(\"backgroundColor\", color));\n        } else {\n            $hintObj.addClass(\"no-swatch-margin\");\n        }\n        return $hintObj;\n    }\n\n\n    // Define public API\n    exports.COLOR_NAMES     = COLOR_NAMES;\n    exports.COLOR_REGEX     = COLOR_REGEX;\n    exports.formatColorHint = formatColorHint;\n});\n"
  },
  {
    "path": "src/utils/Compatibility.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Compatibility shims for running Brackets in various environments, browsers.\n */\ndefine(function () {\n    \"use strict\";\n\n    // [IE10] String.prototype missing trimRight() and trimLeft()\n    if (!String.prototype.trimRight) {\n        String.prototype.trimRight = function () { return this.replace(/\\s+$/, \"\"); };\n    }\n    if (!String.prototype.trimLeft) {\n        String.prototype.trimLeft = function () { return this.replace(/^\\s+/, \"\"); };\n    }\n\n    // Feature detection for Error.stack. Not all browsers expose it\n    // and Brackets assumes it will be a non-null string.\n    if (typeof (new Error()).stack === \"undefined\") {\n        Error.prototype.stack = \"\";\n    }\n\n});\n"
  },
  {
    "path": "src/utils/DeprecationWarning.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n *  Utilities functions to display deprecation warning in the console.\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher = require(\"utils/EventDispatcher\");\n\n\n    var displayedWarnings = {};\n\n    /**\n     * Trim the stack so that it does not have the call to this module,\n     * and all the calls to require.js to load the extension that shows\n     * this deprecation warning.\n     */\n    function _trimStack(stack) {\n        var indexOfFirstRequireJSline;\n\n        // Remove everything in the stack up to the end of the line that shows this module file path\n        stack = stack.substr(stack.indexOf(\")\\n\") + 2);\n\n        // Find the very first line of require.js in the stack if the call is from an extension.\n        // Remove all those lines from the call stack.\n        indexOfFirstRequireJSline = stack.indexOf(\"requirejs/require.js\");\n        if (indexOfFirstRequireJSline !== -1) {\n            indexOfFirstRequireJSline = stack.lastIndexOf(\")\", indexOfFirstRequireJSline) + 1;\n            stack = stack.substr(0, indexOfFirstRequireJSline);\n        }\n\n        return stack;\n    }\n\n    /**\n     * Show deprecation warning with the call stack if it\n     * has never been displayed before.\n     * @param {!string} message The deprecation message to be displayed.\n     * @param {boolean=} oncePerCaller If true, displays the message once for each unique call location.\n     *     If false (the default), only displays the message once no matter where it's called from.\n     *     Note that setting this to true can cause a slight performance hit (because it has to generate\n     *     a stack trace), so don't set this for functions that you expect to be called from performance-\n     *     sensitive code (e.g. tight loops).\n     * @param {number=} callerStackPos Only used if oncePerCaller=true. Overrides the `Error().stack` depth\n     *     where the client-code caller can be found. Only needed if extra shim layers are involved.\n     */\n    function deprecationWarning(message, oncePerCaller, callerStackPos) {\n        // If oncePerCaller isn't set, then only show the message once no matter who calls it.\n        if (!message || (!oncePerCaller && displayedWarnings[message])) {\n            return;\n        }\n\n        // Don't show the warning again if we've already gotten it from the current caller.\n        // The true caller location is the fourth line in the stack trace:\n        // * 0 is the word \"Error\"\n        // * 1 is this function\n        // * 2 is the caller of this function (the one throwing the deprecation warning)\n        // * 3 is the actual caller of the deprecated function.\n        var stack = new Error().stack,\n            callerLocation = stack.split(\"\\n\")[callerStackPos || 3];\n        if (oncePerCaller && displayedWarnings[message] && displayedWarnings[message][callerLocation]) {\n            return;\n        }\n\n        console.warn(message + \"\\n\" + _trimStack(stack));\n        if (!displayedWarnings[message]) {\n            displayedWarnings[message] = {};\n        }\n        displayedWarnings[message][callerLocation] = true;\n    }\n\n\n    /**\n     * Show a deprecation warning if there are listeners for the event\n     *\n     * ```\n     *    DeprecationWarning.deprecateEvent(exports,\n     *                                      MainViewManager,\n     *                                      \"workingSetAdd\",\n     *                                      \"workingSetAdd\",\n     *                                      \"DocumentManager.workingSetAdd\",\n     *                                      \"MainViewManager.workingSetAdd\");\n     * ```\n     *\n     * @param {Object} outbound - the object with the old event to dispatch\n     * @param {Object} inbound - the object with the new event to map to the old event\n     * @param {string} oldEventName - the name of the old event\n     * @param {string} newEventName - the name of the new event\n     * @param {string=} canonicalOutboundName - the canonical name of the old event\n     * @param {string=} canonicalInboundName - the canonical name of the new event\n     */\n    function deprecateEvent(outbound, inbound, oldEventName, newEventName, canonicalOutboundName, canonicalInboundName) {\n        // Mark deprecated so EventDispatcher.on() will emit warnings\n        EventDispatcher.markDeprecated(outbound, oldEventName, canonicalInboundName);\n\n        // create an event handler for the new event to listen for\n        inbound.on(newEventName, function () {\n            // Dispatch the event in case anyone is still listening\n            EventDispatcher.triggerWithArray(outbound, oldEventName, Array.prototype.slice.call(arguments, 1));\n        });\n    }\n\n\n    /**\n     * Create a deprecation warning and action for updated constants\n     * @param {!string} old Menu Id\n     * @param {!string} new Menu Id\n     */\n    function deprecateConstant(obj, oldId, newId) {\n        var warning     = \"Use Menus.\" + newId + \" instead of Menus.\" + oldId,\n            newValue    = obj[newId];\n\n        Object.defineProperty(obj, oldId, {\n            get: function () {\n                deprecationWarning(warning, true);\n                return newValue;\n            }\n        });\n    }\n\n    // Define public API\n    exports.deprecationWarning   = deprecationWarning;\n    exports.deprecateEvent       = deprecateEvent;\n    exports.deprecateConstant      = deprecateConstant;\n});\n"
  },
  {
    "path": "src/utils/DragAndDrop.js",
    "content": " /*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Async           = require(\"utils/Async\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        Commands        = require(\"command/Commands\"),\n        Dialogs         = require(\"widgets/Dialogs\"),\n        DefaultDialogs  = require(\"widgets/DefaultDialogs\"),\n        MainViewManager = require(\"view/MainViewManager\"),\n        FileSystem      = require(\"filesystem/FileSystem\"),\n        FileUtils       = require(\"file/FileUtils\"),\n        ProjectManager  = require(\"project/ProjectManager\"),\n        Strings         = require(\"strings\"),\n        StringUtils     = require(\"utils/StringUtils\");\n\n    /**\n     * Returns true if the drag and drop items contains valid drop objects.\n     * @param {Array.<DataTransferItem>} items Array of items being dragged\n     * @return {boolean} True if one or more items can be dropped.\n     */\n    function isValidDrop(items) {\n        var i, len = items.length;\n\n        for (i = 0; i < len; i++) {\n            if (items[i].kind === \"file\") {\n                var entry = items[i].webkitGetAsEntry();\n\n                if (entry.isFile) {\n                    // If any files are being dropped, this is a valid drop\n                    return true;\n                } else if (len === 1) {\n                    // If exactly one folder is being dropped, this is a valid drop\n                    return true;\n                }\n            }\n        }\n\n        // No valid entries found\n        return false;\n    }\n    \n    /**\n     * Determines if the event contains a type list that has a URI-list.\n     * If it does and contains an empty file list, then what is being dropped is a URL.\n     * If that is true then we stop the event propagation and default behavior to save Brackets editor from the browser taking over.\n     * @param {Array.<File>} files Array of File objects from the event datastructure. URLs are the only drop item that would contain a URI-list.\n     * @param {event} event The event datastucture containing datatransfer information about the drag/drop event. Contains a type list which may or may not hold a URI-list depending on what was dragged/dropped. Interested if it does.\n     */\n    function stopURIListPropagation(files, event) {\n        var types = event.dataTransfer.types;\n            \n        if ((!files || !files.length) && types) { // We only want to check if a string of text was dragged into the editor\n            types.forEach(function (value) {\n                //Dragging text externally (dragging text from another file): types has \"text/plain\" and \"text/html\"\n                //Dragging text internally (dragging text to another line): types has just \"text/plain\"\n                //Dragging a file: types has \"Files\"\n                //Dragging a url: types has \"text/plain\" and \"text/uri-list\" <-what we are interested in\n                if (value === \"text/uri-list\") { \n                    event.stopPropagation();\n                    event.preventDefault();\n                    return;\n                }\n            });\n        }\n    }\n\n    /**\n     * Open dropped files\n     * @param {Array.<string>} files Array of files dropped on the application.\n     * @return {Promise} Promise that is resolved if all files are opened, or rejected\n     *     if there was an error.\n     */\n    function openDroppedFiles(paths) {\n        var errorFiles = [],\n            ERR_MULTIPLE_ITEMS_WITH_DIR = {};\n\n        return Async.doInParallel(paths, function (path, idx) {\n            var result = new $.Deferred();\n\n            // Only open files.\n            FileSystem.resolve(path, function (err, item) {\n                if (!err && item.isFile) {\n                    // If the file is already open, and this isn't the last\n                    // file in the list, return. If this *is* the last file,\n                    // always open it so it gets selected.\n                    if (idx < paths.length - 1) {\n                        if (MainViewManager.findInWorkingSet(MainViewManager.ALL_PANES, path) !== -1) {\n                            result.resolve();\n                            return;\n                        }\n                    }\n\n                    CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN,\n                                           {fullPath: path, silent: true})\n                        .done(function () {\n                            result.resolve();\n                        })\n                        .fail(function (openErr) {\n                            errorFiles.push({path: path, error: openErr});\n                            result.reject();\n                        });\n                } else if (!err && item.isDirectory && paths.length === 1) {\n                    // One folder was dropped, open it.\n                    ProjectManager.openProject(path)\n                        .done(function () {\n                            result.resolve();\n                        })\n                        .fail(function () {\n                            // User was already notified of the error.\n                            result.reject();\n                        });\n                } else {\n                    errorFiles.push({path: path, error: err || ERR_MULTIPLE_ITEMS_WITH_DIR});\n                    result.reject();\n                }\n            });\n\n            return result.promise();\n        }, false)\n            .fail(function () {\n                function errorToString(err) {\n                    if (err === ERR_MULTIPLE_ITEMS_WITH_DIR) {\n                        return Strings.ERROR_MIXED_DRAGDROP;\n                    } else {\n                        return FileUtils.getFileErrorString(err);\n                    }\n                }\n\n                if (errorFiles.length > 0) {\n                    var message = Strings.ERROR_OPENING_FILES;\n\n                    message += \"<ul class='dialog-list'>\";\n                    errorFiles.forEach(function (info) {\n                        message += \"<li><span class='dialog-filename'>\" +\n                            StringUtils.breakableUrl(ProjectManager.makeProjectRelativeIfPossible(info.path)) +\n                            \"</span> - \" + errorToString(info.error) +\n                            \"</li>\";\n                    });\n                    message += \"</ul>\";\n\n                    Dialogs.showModalDialog(\n                        DefaultDialogs.DIALOG_ID_ERROR,\n                        Strings.ERROR_OPENING_FILE_TITLE,\n                        message\n                    );\n                }\n            });\n    }\n\n\n    /**\n     * Attaches global drag & drop handlers to this window. This enables dropping files/folders to open them, and also\n     * protects the Brackets app from being replaced by the browser trying to load the dropped file in its place.\n     */\n    function attachHandlers() {\n\n        function handleDragOver(event) {\n            event = event.originalEvent || event;\n\n            var files = event.dataTransfer.files;\n\n            stopURIListPropagation(files, event);\n\n            if (files && files.length) {\n                event.stopPropagation();\n                event.preventDefault();\n\n                var dropEffect = \"none\";\n\n                // Don't allow drag-and-drop of files/folders when a modal dialog is showing.\n                if ($(\".modal.instance\").length === 0 && isValidDrop(event.dataTransfer.items)) {\n                    dropEffect = \"copy\";\n                }\n                event.dataTransfer.dropEffect = dropEffect;\n            }\n        }\n\n        function handleDrop(event) {\n            event = event.originalEvent || event;\n\n            var files = event.dataTransfer.files;\n\n            stopURIListPropagation(files, event);\n\n            if (files && files.length) {\n                event.stopPropagation();\n                event.preventDefault();\n\n                brackets.app.getDroppedFiles(function (err, paths) {\n                    if (!err) {\n                        openDroppedFiles(paths);\n                    }\n                });\n            }\n        }\n\n        // For most of the window, only respond if nothing more specific in the UI has already grabbed the event (e.g.\n        // the Extension Manager drop-to-install zone, or an extension with a drop-to-upload zone in its panel)\n        $(window.document.body)\n            .on(\"dragover\", handleDragOver)\n            .on(\"drop\", handleDrop);\n\n        // Over CodeMirror specifically, always pre-empt CodeMirror's drag event handling if files are being dragged - CM stops\n        // propagation on any drag event it sees, even when it's not a text drag/drop. But allow CM to handle all non-file drag\n        // events. See bug #10617.\n        window.document.body.addEventListener(\"dragover\", function (event) {\n            if ($(event.target).closest(\".CodeMirror\").length) {\n                handleDragOver(event);\n            }\n        }, true);\n        window.document.body.addEventListener(\"drop\", function (event) {\n            if ($(event.target).closest(\".CodeMirror\").length) {\n                handleDrop(event);\n            }\n        }, true);\n    }\n\n\n    CommandManager.register(Strings.CMD_OPEN_DROPPED_FILES, Commands.FILE_OPEN_DROPPED_FILES, openDroppedFiles);\n\n    // Export public API\n    exports.attachHandlers      = attachHandlers;\n    exports.isValidDrop         = isValidDrop;\n    exports.openDroppedFiles    = openDroppedFiles;\n});\n"
  },
  {
    "path": "src/utils/DropdownEventHandler.js",
    "content": " /*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var KeyBindingManager = require(\"command/KeyBindingManager\"),\n        KeyEvent          = require(\"utils/KeyEvent\"),\n        PopUpManager      = require(\"widgets/PopUpManager\"),\n        ViewUtils         = require(\"utils/ViewUtils\");\n\n    /**\n     * Object to handle events for a dropdown list.\n     *\n     * DropdownEventHandler handles these events:\n     *\n     * Mouse:\n     * - click       - execute selection callback and dismiss list\n     * - mouseover   - highlight item\n     * - mouseleave  - remove mouse highlighting\n     *\n     * Keyboard:\n     * - Enter       - execute selection callback and dismiss list\n     * - Esc         - dismiss list\n     * - Up/Down     - change selection\n     * - PageUp/Down - change selection\n     *\n     * Items whose <a> has the .disabled class do not respond to selection.\n     *\n     * @constructor\n     * @param {jQueryObject} $list  associated list object\n     * @param {Function} selectionCallback  function called when list item is selected.\n     */\n    function DropdownEventHandler($list, selectionCallback, closeCallback) {\n\n        this.$list = $list;\n        this.$items = $list.find(\"li\");\n        this.selectionCallback = selectionCallback;\n        this.closeCallback = closeCallback;\n        this.scrolling = false;\n\n        /**\n         * @private\n         * The selected position in the list; otherwise -1.\n         * @type {number}\n         */\n        this._selectedIndex = -1;\n    }\n\n    /**\n     * Public open method\n     */\n    DropdownEventHandler.prototype.open = function () {\n        var self = this;\n\n        /**\n         * Convert keydown events into hint list navigation actions.\n         *\n         * @param {KeyboardEvent} event\n         * @return {boolean} true if key was handled, otherwise false.\n         */\n        function _keydownHook(event) {\n            var keyCode;\n\n            // (page) up, (page) down, enter and tab key are handled by the list\n            if (event.type === \"keydown\") {\n                keyCode = event.keyCode;\n\n                if (keyCode === KeyEvent.DOM_VK_TAB) {\n                    self.close();\n                } else if (keyCode === KeyEvent.DOM_VK_UP) {\n                    // Move up one, wrapping at edges (if nothing selected, select the last item)\n                    self._tryToSelect(self._selectedIndex === -1 ? -1 : self._selectedIndex - 1, -1);\n                } else if (keyCode === KeyEvent.DOM_VK_DOWN) {\n                    // Move down one, wrapping at edges (if nothing selected, select the first item)\n                    self._tryToSelect(self._selectedIndex === -1 ? 0 : self._selectedIndex + 1, +1);\n                } else if (keyCode === KeyEvent.DOM_VK_PAGE_UP) {\n                    // Move up roughly one 'page', stopping at edges (not wrapping) (if nothing selected, selects the first item)\n                    self._tryToSelect((self._selectedIndex || 0) - self._itemsPerPage(), -1, true);\n                } else if (keyCode === KeyEvent.DOM_VK_PAGE_DOWN) {\n                    // Move down roughly one 'page', stopping at edges (not wrapping) (if nothing selected, selects the item one page down from the top)\n                    self._tryToSelect((self._selectedIndex || 0) + self._itemsPerPage(), +1, true);\n\n                } else if (keyCode === KeyEvent.DOM_VK_HOME) {\n                    self._tryToSelect(0, +1);\n                } else if (keyCode === KeyEvent.DOM_VK_END) {\n                    self._tryToSelect(self.$items.length - 1, -1);\n\n                } else if (self._selectedIndex !== -1 &&\n                        (keyCode === KeyEvent.DOM_VK_RETURN)) {\n\n                    // Trigger a click handler to commmit the selected item\n                    self._selectionHandler();\n                } else {\n                    // Let the event bubble.\n                    return false;\n                }\n\n                event.stopImmediatePropagation();\n                event.preventDefault();\n                return true;\n            }\n\n            // If we didn't handle it, let other global keydown hooks handle it.\n            return false;\n        }\n\n        /**\n         * PopUpManager callback\n         */\n        function closeCallback() {\n            KeyBindingManager.removeGlobalKeydownHook(_keydownHook);\n            self._cleanup();\n        }\n\n        KeyBindingManager.addGlobalKeydownHook(_keydownHook);\n\n        if (this.$list) {\n            this._registerMouseEvents();\n            PopUpManager.addPopUp(this.$list, closeCallback, true);\n        }\n    };\n\n    /**\n     * Public close method\n     */\n    DropdownEventHandler.prototype.close = function () {\n        if (this.$list) {\n            PopUpManager.removePopUp(this.$list);\n        }\n    };\n\n    /**\n     * Cleanup\n     */\n    DropdownEventHandler.prototype._cleanup = function () {\n        if (this.$list) {\n            this.$list.off(\".dropdownEventHandler\");\n        }\n        if (this.closeCallback) {\n            this.closeCallback();\n        }\n    };\n\n    /**\n     * Try to select item at the given index. If it's disabled or a divider, keep trying by incrementing\n     * index by 'direction' each time (wrapping around if needed).\n     * @param {number} index  If out of bounds, index either wraps around to remain in range (e.g. -1 yields\n     *                      last item, length+1 yields 2nd item) or if noWrap set, clips instead (e.g. -1 yields\n     *                      first item, length+1 yields last item).\n     * @param {number} direction  Either +1 or -1\n     * @param {boolean=} noWrap  Clip out of range index values instead of wrapping. Default false (wrap).\n     */\n    DropdownEventHandler.prototype._tryToSelect = function (index, direction, noWrap) {\n        // Fix up 'index' if out of bounds (>= len or < 0)\n        var len = this.$items.length;\n        if (noWrap) {\n            // Clip to stay in range (and set direction so we don't wrap in the recursion case either)\n            if (index < 0) {\n                index = 0;\n                direction = +1;\n            } else if (index >= len) {\n                index = len - 1;\n                direction = -1;\n            }\n        } else {\n            // Wrap around to keep index in bounds\n            index %= len;\n            if (index < 0) {\n                index += len;\n            }\n        }\n\n        var $item = this.$items.eq(index);\n        if ($item.hasClass(\"divider\") || $item.find(\"a.disabled\").length) {\n            // Desired item is ineligible for selection: try next one\n            this._tryToSelect(index + direction, direction, noWrap);\n        } else {\n            this._setSelectedIndex(index, true);\n        }\n    };\n\n    /**\n     * @return {number} The number of items per scroll page.\n     */\n    DropdownEventHandler.prototype._itemsPerPage = function () {\n        var itemsPerPage = 1,\n            itemHeight;\n\n        if (this.$items.length !== 0) {\n            itemHeight = $(this.$items[0]).height();\n            if (itemHeight) {\n                // round down to integer value\n                itemsPerPage = Math.floor(this.$list.height() / itemHeight);\n                itemsPerPage = Math.max(1, Math.min(itemsPerPage, this.$items.length));\n            }\n        }\n\n        return itemsPerPage;\n    };\n\n    /**\n     * Call selectionCallback with selected index\n     */\n    DropdownEventHandler.prototype._selectionHandler = function () {\n\n        if (this._selectedIndex === -1) {\n            return;\n        }\n\n        var $link = this.$items.eq(this._selectedIndex).find(\"a\");\n        this._clickHandler($link);\n    };\n\n    /**\n     * Call selectionCallback with selected item\n     *\n     * @param {jQueryObject} $item\n     */\n    DropdownEventHandler.prototype._clickHandler = function ($link) {\n\n        if (!this.selectionCallback || !this.$list || !$link) {\n            return;\n        }\n        if ($link.hasClass(\"disabled\")) {\n            return;\n        }\n\n        this.selectionCallback($link);\n        PopUpManager.removePopUp(this.$list);\n    };\n\n    /**\n     * Select the item in the hint list at the specified index, or remove the\n     * selection if index < 0.\n     *\n     * @private\n     * @param {number} index\n     */\n    DropdownEventHandler.prototype._setSelectedIndex = function (index, scrollIntoView) {\n\n        // Range check\n        index = Math.max(-1, Math.min(index, this.$items.length - 1));\n\n        // Clear old highlight\n        if (this._selectedIndex !== -1) {\n            this.$items.eq(this._selectedIndex).find(\"a\").removeClass(\"selected\");\n        }\n\n        this._selectedIndex = index;\n\n        // Highlight the new selected item, if necessary\n        if (this._selectedIndex !== -1) {\n            var $item = this.$items.eq(this._selectedIndex);\n\n            $item.find(\"a\").addClass(\"selected\");\n            if (scrollIntoView) {\n                this.scrolling = true;\n                ViewUtils.scrollElementIntoView(this.$list, $item, false);\n            }\n        }\n    };\n\n    /**\n     * Register mouse event handlers\n     */\n    DropdownEventHandler.prototype._registerMouseEvents = function () {\n        var self = this;\n\n        this.$list\n            .on(\"click.dropdownEventHandler\", \"a\", function () {\n                self._clickHandler($(this));\n            })\n            .on(\"mouseover.dropdownEventHandler\", \"a\", function (e) {\n                // Don't select item under mouse cursor when scrolling.\n                if (self.scrolling) {\n                    self.scrolling = false;\n                    return;\n                }\n\n                var $link = $(e.currentTarget),\n                    $item = $link.closest(\"li\"),\n                    viewOffset = self.$list.offset(),\n                    elementOffset = $item.offset();\n\n                // Only set selected if enabled & in view\n                // (dividers are already screened out since they don't have an \"a\" tag in them)\n                if (!$link.hasClass(\"disabled\")) {\n                    if (elementOffset.top < viewOffset.top + self.$list.height() && viewOffset.top <= elementOffset.top) {\n                        self._setSelectedIndex(self.$items.index($item), false);\n                    }\n                }\n            });\n    };\n\n    /**\n     * Re-register mouse event handlers\n     * @param {!jQueryObject} $list  newly updated list object\n     */\n    DropdownEventHandler.prototype.reRegisterMouseHandlers = function ($list) {\n        if (this.$list) {\n            this.$list.off(\".dropdownEventHandler\");\n\n            this.$list = $list;\n            this.$items = $list.find(\"li\");\n\n            this._registerMouseEvents();\n        }\n    };\n\n    // Export public API\n    exports.DropdownEventHandler    = DropdownEventHandler;\n});\n"
  },
  {
    "path": "src/utils/EventDispatcher.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Implements a jQuery-like event dispatch pattern for non-DOM objects:\n *  - Listeners are attached via on()/one() & detached via off()\n *  - Listeners can use namespaces for easy removal\n *  - Listeners can attach to multiple events at once via a space-separated list\n *  - Events are fired via trigger()\n *  - The same listener can be attached twice, and will be called twice; but off() will detach all\n *    duplicate copies at once ('duplicate' means '===' equality - see http://jsfiddle.net/bf4p29g5/1/)\n *\n * But it has some important differences from jQuery's non-DOM event mechanism:\n *  - More robust to listeners that throw exceptions (other listeners will still be called, and\n *    trigger() will still return control to its caller).\n *  - Events can be marked deprecated, causing on() to issue warnings\n *  - Easier to debug, since the dispatch code is much simpler\n *  - Faster, for the same reason\n *  - Uses less memory, since $(nonDOMObj).on() leaks memory in jQuery\n *  - API is simplified:\n *      - Event handlers do not have 'this' set to the event dispatcher object\n *      - Event object passed to handlers only has 'type' and 'target' fields\n *      - trigger() uses a simpler argument-list signature (like Promise APIs), rather than requiring\n *        an Array arg and ignoring additional args\n *      - trigger() does not support namespaces\n *      - For simplicity, on() does not accept a map of multiple events -> multiple handlers, nor a\n *        missing arg standing in for a bare 'return false' handler.\n *\n * For now, Brackets uses a jQuery patch to ensure $(obj).on() and obj.on() (etc.) are identical\n * for any obj that has the EventDispatcher pattern. In the future, this may be deprecated.\n *\n * To add EventDispatcher methods to any object, call EventDispatcher.makeEventDispatcher(obj).\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var LEAK_WARNING_THRESHOLD = 15;\n\n\n    /**\n     * Split \"event.namespace\" string into its two parts; both parts are optional.\n     * @param {string} eventName Event name and/or trailing \".namespace\"\n     * @return {!{event:string, ns:string}} Uses \"\" for missing parts.\n     */\n    function splitNs(eventStr) {\n        var dot = eventStr.indexOf(\".\");\n        if (dot === -1) {\n            return { eventName: eventStr };\n        } else {\n            return { eventName: eventStr.substring(0, dot), ns: eventStr.substring(dot) };\n        }\n    }\n\n\n    // These functions are added as mixins to any object by makeEventDispatcher()\n\n    /**\n     * Adds the given handler function to 'events': a space-separated list of one or more event names, each\n     * with an optional \".namespace\" (used by off() - see below). If the handler is already listening to this\n     * event, a duplicate copy is added.\n     * @param {string} events\n     * @param {!function(!{type:string, target:!Object}, ...)} fn\n     */\n    var on = function (events, fn) {\n        var eventsList = events.split(/\\s+/).map(splitNs),\n            i;\n\n        if (!fn) {\n            throw new Error(\"EventListener.on() called with no listener fn for event '\" + events + \"'\");\n        }\n\n        // Check for deprecation warnings\n        if (this._deprecatedEvents) {\n            for (i = 0; i < eventsList.length; i++) {\n                var deprecation = this._deprecatedEvents[eventsList[i].eventName];\n                if (deprecation) {\n                    var message = \"Registering for deprecated event '\" + eventsList[i].eventName + \"'.\";\n                    if (typeof deprecation === \"string\") {\n                        message += \" Instead, use \" + deprecation + \".\";\n                    }\n                    console.warn(message, new Error().stack);\n                }\n            }\n        }\n\n        // Attach listener for each event clause\n        for (i = 0; i < eventsList.length; i++) {\n            var eventName = eventsList[i].eventName;\n            if (!this._eventHandlers) {\n                this._eventHandlers = {};\n            }\n            if (!this._eventHandlers[eventName]) {\n                this._eventHandlers[eventName] = [];\n            }\n            eventsList[i].handler = fn;\n            this._eventHandlers[eventName].push(eventsList[i]);\n\n            // Check for suspicious number of listeners being added to one object-event pair\n            if (this._eventHandlers[eventName].length > LEAK_WARNING_THRESHOLD) {\n                console.error(\"Possible memory leak: \" + this._eventHandlers[eventName].length + \" '\" + eventName + \"' listeners attached to\", this);\n            }\n        }\n\n        return this;  // for chaining\n    };\n\n    /**\n     * Removes one or more handler functions based on the space-separated 'events' list. Each item in\n     * 'events' can be: bare event name, bare .namespace, or event.namespace pair. This yields a set of\n     * matching handlers. If 'fn' is omitted, all these handlers are removed. If 'fn' is provided,\n     * only handlers exactly equal to 'fn' are removed (there may still be >1, if duplicates were added).\n     * @param {string} events\n     * @param {?function(!{type:string, target:!Object}, ...)} fn\n     */\n    var off = function (events, fn) {\n        if (!this._eventHandlers) {\n            return this;\n        }\n\n        var eventsList = events.split(/\\s+/).map(splitNs),\n            i;\n\n        var removeAllMatches = function (eventRec, eventName) {\n            var handlerList = this._eventHandlers[eventName],\n                k;\n            if (!handlerList) {\n                return;\n            }\n\n            // Walk backwards so it's easy to remove items\n            for (k = handlerList.length - 1; k >= 0; k--) {\n                // Look at ns & fn only - doRemove() has already taken care of eventName\n                if (!eventRec.ns || eventRec.ns === handlerList[k].ns) {\n                    var handler = handlerList[k].handler;\n                    if (!fn || fn === handler || fn._eventOnceWrapper === handler) {\n                        handlerList.splice(k, 1);\n                    }\n                }\n            }\n            if (!handlerList.length) {\n                delete this._eventHandlers[eventName];\n            }\n        }.bind(this);\n\n        var doRemove = function (eventRec) {\n            if (eventRec.eventName) {\n                // If arg calls out an event name, look at that handler list only\n                removeAllMatches(eventRec, eventRec.eventName);\n            } else {\n                // If arg only gives a namespace, look at handler lists for all events\n                _.forEach(this._eventHandlers, function (handlerList, eventName) {\n                    removeAllMatches(eventRec, eventName);\n                });\n            }\n        }.bind(this);\n\n        // Detach listener for each event clause\n        // Each clause may be: bare eventname, bare .namespace, full eventname.namespace\n        for (i = 0; i < eventsList.length; i++) {\n            doRemove(eventsList[i]);\n        }\n\n        return this;  // for chaining\n    };\n\n    /**\n     * Attaches a handler so it's only called once (per event in the 'events' list).\n     * @param {string} events\n     * @param {?function(!{type:string, target:!Object}, ...)} fn\n     */\n    var one = function (events, fn) {\n        // Wrap fn in a self-detaching handler; saved on the original fn so off() can detect it later\n        if (!fn._eventOnceWrapper) {\n            fn._eventOnceWrapper = function (event) {\n                // Note: this wrapper is reused for all attachments of the same fn, so it shouldn't reference\n                // anything from the outer closure other than 'fn'\n                event.target.off(event.type, fn._eventOnceWrapper);\n                fn.apply(this, arguments);\n            };\n        }\n        return this.on(events, fn._eventOnceWrapper);\n    };\n\n    /**\n     * Invokes all handlers for the given event (in the order they were added).\n     * @param {string} eventName\n     * @param {*} ... Any additional args are passed to the event handler after the event object\n     */\n    var trigger = function (eventName) {\n        var event = { type: eventName, target: this },\n            handlerList = this._eventHandlers && this._eventHandlers[eventName],\n            i;\n\n        if (!handlerList) {\n            return;\n        }\n\n        // Use a clone of the list in case handlers call on()/off() while we're still in the loop\n        handlerList = handlerList.slice();\n\n        // Pass 'event' object followed by any additional args trigger() was given\n        var applyArgs = Array.prototype.slice.call(arguments, 1);\n        applyArgs.unshift(event);\n\n        for (i = 0; i < handlerList.length; i++) {\n            try {\n                // Call one handler\n                handlerList[i].handler.apply(null, applyArgs);\n            } catch (err) {\n                console.error(\"Exception in '\" + eventName + \"' listener on\", this, String(err), err.stack);\n                console.assert();  // causes dev tools to pause, just like an uncaught exception\n            }\n        }\n    };\n\n\n    /**\n     * Adds the EventDispatcher APIs to the given object: on(), one(), off(), and trigger(). May also be\n     * called on a prototype object - each instance will still behave independently.\n     * @param {!Object} obj Object to add event-dispatch methods to\n     */\n    function makeEventDispatcher(obj) {\n        $.extend(obj, {\n            on: on,\n            off: off,\n            one: one,\n            trigger: trigger,\n            _EventDispatcher: true\n        });\n        // Later, on() may add _eventHandlers: Object.<string, Array.<{event:string, namespace:?string,\n        //   handler:!function(!{type:string, target:!Object}, ...)}>> - map from eventName to an array\n        //   of handler records\n        // Later, markDeprecated() may add _deprecatedEvents: Object.<string, string|boolean> - map from\n        //   eventName to deprecation warning info\n    }\n\n    /**\n     * Utility for calling on() with an array of arguments to pass to event handlers (rather than a varargs\n     * list). makeEventDispatcher() must have previously been called on 'dispatcher'.\n     * @param {!Object} dispatcher\n     * @param {string} eventName\n     * @param {!Array.<*>} argsArray\n     */\n    function triggerWithArray(dispatcher, eventName, argsArray) {\n        var triggerArgs = [eventName].concat(argsArray);\n        dispatcher.trigger.apply(dispatcher, triggerArgs);\n    }\n\n    /**\n     * Utility for attaching an event handler to an object that has not YET had makeEventDispatcher() called\n     * on it, but will in the future. Once 'futureDispatcher' becomes a real event dispatcher, any handlers\n     * attached here will be retained.\n     *\n     * Useful with core modules that have circular dependencies (one module initially gets an empty copy of the\n     * other, with no on() API present yet). Unlike other strategies like waiting for htmlReady(), this helper\n     * guarantees you won't miss any future events, regardless of how soon the other module finishes init and\n     * starts calling trigger().\n     *\n     * @param {!Object} futureDispatcher\n     * @param {string} events\n     * @param {?function(!{type:string, target:!Object}, ...)} fn\n     */\n    function on_duringInit(futureDispatcher, events, fn) {\n        on.call(futureDispatcher, events, fn);\n    }\n\n    /**\n     * Mark a given event name as deprecated, such that on() will emit warnings when called with it.\n     * May be called before makeEventDispatcher(). May be called on a prototype where makeEventDispatcher()\n     * is called separately per instance (i.e. in the constructor). Should be called before clients have\n     * a chance to start calling on().\n     * @param {!Object} obj Event dispatcher object\n     * @param {string} eventName Name of deprecated event\n     * @param {string=} insteadStr Suggested thing to use instead\n     */\n    function markDeprecated(obj, eventName, insteadStr) {\n        // Mark event as deprecated - on() will emit warnings when called with this event\n        if (!obj._deprecatedEvents) {\n            obj._deprecatedEvents = {};\n        }\n        obj._deprecatedEvents[eventName] = insteadStr || true;\n    }\n\n\n    exports.makeEventDispatcher = makeEventDispatcher;\n    exports.triggerWithArray    = triggerWithArray;\n    exports.on_duringInit       = on_duringInit;\n    exports.markDeprecated      = markDeprecated;\n});\n"
  },
  {
    "path": "src/utils/ExtensionLoader.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * ExtensionLoader searches the filesystem for extensions, then creates a new context for each one and loads it.\n * This module dispatches the following events:\n *      \"load\" - when an extension is successfully loaded. The second argument is the file path to the\n *          extension root.\n *      \"loadFailed\" - when an extension load is unsuccessful. The second argument is the file path to the\n *          extension root.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var _              = require(\"thirdparty/lodash\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        FileSystem     = require(\"filesystem/FileSystem\"),\n        FileUtils      = require(\"file/FileUtils\"),\n        Async          = require(\"utils/Async\"),\n        ExtensionUtils = require(\"utils/ExtensionUtils\"),\n        UrlParams      = require(\"utils/UrlParams\").UrlParams,\n        PathUtils      = require(\"thirdparty/path-utils/path-utils\");\n\n    // default async initExtension timeout\n    var INIT_EXTENSION_TIMEOUT = 10000;\n\n    var _init       = false,\n        _extensions = {},\n        _initExtensionTimeout = INIT_EXTENSION_TIMEOUT,\n        srcPath     = FileUtils.getNativeBracketsDirectoryPath();\n\n    /**\n     * Stores require.js contexts of extensions\n     * @type {Object.<string, Object>}\n     */\n    var contexts    = {};\n\n    // The native directory path ends with either \"test\" or \"src\". We need \"src\" to\n    // load the text and i18n modules.\n    srcPath = srcPath.replace(/\\/test$/, \"/src\"); // convert from \"test\" to \"src\"\n\n\n    // Retrieve the global paths\n    var globalPaths = brackets._getGlobalRequireJSConfig().paths;\n\n    // Convert the relative paths to absolute\n    Object.keys(globalPaths).forEach(function (key) {\n        globalPaths[key] = PathUtils.makePathAbsolute(srcPath + \"/\" + globalPaths[key]);\n    });\n\n    /**\n     * Returns the full path to the default extensions directory.\n     */\n    function getDefaultExtensionPath() {\n        return FileUtils.getNativeBracketsDirectoryPath() + \"/extensions/default\";\n    }\n\n    /**\n     * Returns the full path of the default user extensions directory. This is in the users\n     * application support directory, which is typically\n     * /Users/<user>/Application Support/Brackets/extensions/user on the mac, and\n     * C:\\Users\\<user>\\AppData\\Roaming\\Brackets\\extensions\\user on windows.\n     */\n    function getUserExtensionPath() {\n        if (brackets.app.getApplicationSupportDirectory) {\n            return brackets.app.getApplicationSupportDirectory() + \"/extensions/user\";\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns the require.js require context used to load an extension\n     *\n     * @param {!string} name, used to identify the extension\n     * @return {!Object} A require.js require object used to load the extension, or undefined if\n     * there is no require object with that name\n     */\n    function getRequireContextForExtension(name) {\n        return contexts[name];\n    }\n\n    /**\n     * @private\n     * Get timeout value for rejecting an extension's async initExtension promise.\n     * @return {number} Timeout in milliseconds\n     */\n    function _getInitExtensionTimeout() {\n        return _initExtensionTimeout;\n    }\n\n    /**\n     * @private\n     * Set timeout for rejecting an extension's async initExtension promise.\n     * @param {number} value Timeout in milliseconds\n     */\n    function _setInitExtensionTimeout(value) {\n        _initExtensionTimeout = value;\n    }\n\n    /**\n     * @private\n     * Loads optional requirejs-config.json file for an extension\n     * @param {Object} baseConfig\n     * @return {$.Promise}\n     */\n    function _mergeConfig(baseConfig) {\n        var deferred = new $.Deferred(),\n            extensionConfigFile = FileSystem.getFileForPath(baseConfig.baseUrl + \"/requirejs-config.json\");\n\n        // Optional JSON config for require.js\n        FileUtils.readAsText(extensionConfigFile).done(function (text) {\n            try {\n                var extensionConfig = JSON.parse(text);\n\n                // baseConfig.paths properties will override any extension config paths\n                _.extend(extensionConfig.paths, baseConfig.paths);\n\n                // Overwrite baseUrl, context, locale (paths is already merged above)\n                _.extend(extensionConfig, _.omit(baseConfig, \"paths\"));\n\n                deferred.resolve(extensionConfig);\n            } catch (err) {\n                // Failed to parse requirejs-config.json\n                deferred.reject(\"failed to parse requirejs-config.json\");\n            }\n        }).fail(function () {\n            // If requirejs-config.json isn't specified, resolve with the baseConfig only\n            deferred.resolve(baseConfig);\n        });\n\n        return deferred.promise();\n    }\n\n    /**\n     * Loads the extension module that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!{baseUrl: string}} config object with baseUrl property containing absolute path of extension\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when the extension is loaded, or rejected\n     *              if the extension fails to load or throws an exception immediately when loaded.\n     *              (Note: if extension contains a JS syntax error, promise is resolved not rejected).\n     */\n    function loadExtensionModule(name, config, entryPoint) {\n        var extensionConfig = {\n            context: name,\n            baseUrl: config.baseUrl,\n            paths: globalPaths,\n            locale: brackets.getLocale()\n        };\n\n        // Read optional requirejs-config.json\n        var promise = _mergeConfig(extensionConfig).then(function (mergedConfig) {\n            // Create new RequireJS context and load extension entry point\n            var extensionRequire = brackets.libRequire.config(mergedConfig),\n                extensionRequireDeferred = new $.Deferred();\n\n            contexts[name] = extensionRequire;\n            extensionRequire([entryPoint], extensionRequireDeferred.resolve, extensionRequireDeferred.reject);\n\n            return extensionRequireDeferred.promise();\n        }).then(function (module) {\n            // Extension loaded normally\n            var initPromise;\n\n            _extensions[name] = module;\n\n            // Optional sync/async initExtension\n            if (module && module.initExtension && (typeof module.initExtension === \"function\")) {\n                // optional async extension init\n                try {\n                    initPromise = Async.withTimeout(module.initExtension(), _getInitExtensionTimeout());\n                } catch (err) {\n                    // Synchronous error while initializing extension\n                    console.error(\"[Extension] Error -- error thrown during initExtension for \" + name + \": \" + err);\n                    return new $.Deferred().reject(err).promise();\n                }\n\n                // initExtension may be synchronous and may not return a promise\n                if (initPromise) {\n                    // WARNING: These calls to initPromise.fail() and initPromise.then(),\n                    // could also result in a runtime error if initPromise is not a valid\n                    // promise. Currently, the promise is wrapped via Async.withTimeout(),\n                    // so the call is safe as-is.\n                    initPromise.fail(function (err) {\n                        if (err === Async.ERROR_TIMEOUT) {\n                            console.error(\"[Extension] Error -- timeout during initExtension for \" + name);\n                        } else {\n                            console.error(\"[Extension] Error -- failed initExtension for \" + name + (err ? \": \" + err : \"\"));\n                        }\n                    });\n\n                    return initPromise;\n                }\n            }\n        }, function errback(err) {\n            // Extension failed to load during the initial require() call\n            var additionalInfo = String(err);\n            if (err.requireType === \"scripterror\" && err.originalError) {\n                // This type has a misleading error message - replace it with something clearer (URL of require() call that got a 404 result)\n                additionalInfo = \"Module does not exist: \" + err.originalError.target.src;\n            }\n            console.error(\"[Extension] failed to load \" + config.baseUrl + \" - \" + additionalInfo);\n\n            if (err.requireType === \"define\") {\n                // This type has a useful stack (exception thrown by ext code or info on bad getModule() call)\n                console.log(err.stack);\n            }\n        });\n\n        return promise;\n    }\n\n    /**\n     * Loads the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!{baseUrl: string}} config object with baseUrl property containing absolute path of extension\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when the extension is loaded, or rejected\n     *              if the extension fails to load or throws an exception immediately when loaded.\n     *              (Note: if extension contains a JS syntax error, promise is resolved not rejected).\n     */\n    function loadExtension(name, config, entryPoint) {\n        var promise = new $.Deferred();\n\n        // Try to load the package.json to figure out if we are loading a theme.\n        ExtensionUtils.loadMetadata(config.baseUrl).always(promise.resolve);\n\n        return promise\n            .then(function (metadata) {\n                // No special handling for themes... Let the promise propagate into the ExtensionManager\n                if (metadata && metadata.theme) {\n                    return;\n                }\n\n                if (!metadata.disabled) {\n                    return loadExtensionModule(name, config, entryPoint);\n                } else {\n                    return new $.Deferred().reject(\"disabled\").promise();\n                }\n            })\n            .then(function () {\n                exports.trigger(\"load\", config.baseUrl);\n            }, function (err) {\n                if (err === \"disabled\") {\n                    exports.trigger(\"disabled\", config.baseUrl);\n                } else {\n                    exports.trigger(\"loadFailed\", config.baseUrl);\n                }\n            });\n    }\n\n    /**\n     * Runs unit tests for the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!{baseUrl: string}} config object with baseUrl property containing absolute path of extension\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function testExtension(name, config, entryPoint) {\n        var result = new $.Deferred(),\n            extensionPath = config.baseUrl + \"/\" + entryPoint + \".js\";\n\n        FileSystem.resolve(extensionPath, function (err, entry) {\n            if (!err && entry.isFile) {\n                // unit test file exists\n                var extensionRequire = brackets.libRequire.config({\n                    context: name,\n                    baseUrl: config.baseUrl,\n                    paths: $.extend({}, config.paths, globalPaths)\n                });\n\n                extensionRequire([entryPoint], function () {\n                    result.resolve();\n                });\n            } else {\n                result.reject();\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * @private\n     * Loads a file entryPoint from each extension folder within the baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!{baseUrl: string}} config object with baseUrl property containing absolute path of extension folder\n     * @param {!string} entryPoint Module name to load (without .js suffix)\n     * @param {function} processExtension\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function _loadAll(directory, config, entryPoint, processExtension) {\n        var result = new $.Deferred();\n\n        FileSystem.getDirectoryForPath(directory).getContents(function (err, contents) {\n            if (!err) {\n                var i,\n                    extensions = [];\n\n                for (i = 0; i < contents.length; i++) {\n                    if (contents[i].isDirectory) {\n                        // FUTURE (JRB): read package.json instead of just using the entrypoint \"main\".\n                        // Also, load sub-extensions defined in package.json.\n                        extensions.push(contents[i].name);\n                    }\n                }\n\n                if (extensions.length === 0) {\n                    result.resolve();\n                    return;\n                }\n\n                Async.doInParallel(extensions, function (item) {\n                    var extConfig = {\n                        baseUrl: config.baseUrl + \"/\" + item,\n                        paths: config.paths\n                    };\n                    return processExtension(item, extConfig, entryPoint);\n                }).always(function () {\n                    // Always resolve the promise even if some extensions had errors\n                    result.resolve();\n                });\n            } else {\n                console.error(\"[Extension] Error -- could not read native directory: \" + directory);\n                result.reject();\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Loads the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function loadAllExtensionsInNativeDirectory(directory) {\n        return _loadAll(directory, {baseUrl: directory}, \"main\", loadExtension);\n    }\n\n    /**\n     * Runs unit test for the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function testAllExtensionsInNativeDirectory(directory) {\n        var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(),\n            config = {\n                baseUrl: directory\n            };\n\n        config.paths = {\n            \"perf\": bracketsPath + \"/perf\",\n            \"spec\": bracketsPath + \"/spec\"\n        };\n\n        return _loadAll(directory, config, \"unittests\", testExtension);\n    }\n\n    /**\n     * Load extensions.\n     *\n     * @param {?Array.<string>} A list containing references to extension source\n     *      location. A source location may be either (a) a folder name inside\n     *      src/extensions or (b) an absolute path.\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function init(paths) {\n        var params = new UrlParams();\n\n        if (_init) {\n            // Only init once. Return a resolved promise.\n            return new $.Deferred().resolve().promise();\n        }\n\n        if (!paths) {\n            params.parse();\n\n            if (params.get(\"reloadWithoutUserExts\") === \"true\") {\n                paths = [\"default\"];\n            } else {\n                paths = [\n                    getDefaultExtensionPath(),\n                    \"dev\",\n                    getUserExtensionPath()\n                ];\n            }\n        }\n\n        // Load extensions before restoring the project\n\n        // Get a Directory for the user extension directory and create it if it doesn't exist.\n        // Note that this is an async call and there are no success or failure functions passed\n        // in. If the directory *doesn't* exist, it will be created. Extension loading may happen\n        // before the directory is finished being created, but that is okay, since the extension\n        // loading will work correctly without this directory.\n        // If the directory *does* exist, nothing else needs to be done. It will be scanned normally\n        // during extension loading.\n        var extensionPath = getUserExtensionPath();\n        FileSystem.getDirectoryForPath(extensionPath).create();\n\n        // Create the extensions/disabled directory, too.\n        var disabledExtensionPath = extensionPath.replace(/\\/user$/, \"/disabled\");\n        FileSystem.getDirectoryForPath(disabledExtensionPath).create();\n\n        var promise = Async.doSequentially(paths, function (item) {\n            var extensionPath = item;\n\n            // If the item has \"/\" in it, assume it is a full path. Otherwise, load\n            // from our source path + \"/extensions/\".\n            if (item.indexOf(\"/\") === -1) {\n                extensionPath = FileUtils.getNativeBracketsDirectoryPath() + \"/extensions/\" + item;\n            }\n\n            return loadAllExtensionsInNativeDirectory(extensionPath);\n        }, false);\n\n        promise.always(function () {\n            _init = true;\n        });\n\n        return promise;\n    }\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // unit tests\n    exports._setInitExtensionTimeout = _setInitExtensionTimeout;\n    exports._getInitExtensionTimeout = _getInitExtensionTimeout;\n\n    // public API\n    exports.init = init;\n    exports.getDefaultExtensionPath = getDefaultExtensionPath;\n    exports.getUserExtensionPath = getUserExtensionPath;\n    exports.getRequireContextForExtension = getRequireContextForExtension;\n    exports.loadExtension = loadExtension;\n    exports.testExtension = testExtension;\n    exports.loadAllExtensionsInNativeDirectory = loadAllExtensionsInNativeDirectory;\n    exports.testAllExtensionsInNativeDirectory = testAllExtensionsInNativeDirectory;\n});\n"
  },
  {
    "path": "src/utils/ExtensionUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global less */\n\n/**\n * ExtensionUtils defines utility methods for implementing extensions.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Async              = require(\"utils/Async\"),\n        FileSystem         = require(\"filesystem/FileSystem\"),\n        FileUtils          = require(\"file/FileUtils\"),\n        PathUtils          = require(\"thirdparty/path-utils/path-utils\"),\n        PreferencesManager = require(\"preferences/PreferencesManager\");\n\n    /**\n     * Appends a <style> tag to the document's head.\n     *\n     * @param {!string} css CSS code to use as the tag's content\n     * @return {!HTMLStyleElement} The generated HTML node\n     **/\n    function addEmbeddedStyleSheet(css) {\n        return $(\"<style>\").text(css).appendTo(\"head\")[0];\n    }\n\n    /**\n     * Appends a <link> tag to the document's head.\n     *\n     * @param {!string} url URL to a style sheet\n     * @param {$.Deferred=} deferred Optionally check for load and error events\n     * @return {!HTMLLinkElement} The generated HTML node\n     **/\n    function addLinkedStyleSheet(url, deferred) {\n        var attributes = {\n            type: \"text/css\",\n            rel:  \"stylesheet\",\n            href: url\n        };\n\n        var $link = $(\"<link/>\").attr(attributes);\n\n        if (deferred) {\n            $link.on('load', deferred.resolve).on('error', deferred.reject);\n        }\n\n        $link.appendTo(\"head\");\n\n        return $link[0];\n    }\n\n    /**\n     * getModuleUrl returns different urls for win platform\n     * so that's why we need a different check here\n     * @see #getModuleUrl\n     * @param {!string} pathOrUrl that should be checked if it's absolute\n     * @return {!boolean} returns true if pathOrUrl is absolute url on win platform\n     *                    or when it's absolute path on other platforms\n     */\n    function isAbsolutePathOrUrl(pathOrUrl) {\n        return brackets.platform === \"win\" ? PathUtils.isAbsoluteUrl(pathOrUrl) : FileSystem.isAbsolutePath(pathOrUrl);\n    }\n\n    /**\n     * Parses LESS code and returns a promise that resolves with plain CSS code.\n     *\n     * Pass the {@link url} argument to resolve relative URLs contained in the code.\n     * Make sure URLs in the code are wrapped in quotes, like so:\n     *     background-image: url(\"image.png\");\n     *\n     * @param {!string} code LESS code to parse\n     * @param {?string} url URL to the file containing the code\n     * @return {!$.Promise} A promise object that is resolved with CSS code if the LESS code can be parsed\n     */\n    function parseLessCode(code, url) {\n        var result = new $.Deferred(),\n            options;\n\n        if (url) {\n            var dir = url.slice(0, url.lastIndexOf(\"/\") + 1);\n\n            options = {\n                filename: url,\n                rootpath: dir\n            };\n\n            if (isAbsolutePathOrUrl(url)) {\n                options.currentFileInfo = {\n                    currentDirectory: dir,\n                    entryPath: dir,\n                    filename: url,\n                    rootFilename: url,\n                    rootpath: dir\n                };\n            }\n        }\n\n        less.render(code, options, function onParse(err, tree) {\n            if (err) {\n                result.reject(err);\n            } else {\n                result.resolve(tree.css);\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Returns a path to an extension module.\n     *\n     * @param {!module} module Module provided by RequireJS\n     * @param {?string} path Relative path from the extension folder to a file\n     * @return {!string} The path to the module's folder\n     **/\n    function getModulePath(module, path) {\n        var modulePath = module.uri.substr(0, module.uri.lastIndexOf(\"/\") + 1);\n        if (path) {\n            modulePath += path;\n        }\n\n        return modulePath;\n    }\n\n    /**\n     * Returns a URL to an extension module.\n     *\n     * @param {!module} module Module provided by RequireJS\n     * @param {?string} path Relative path from the extension folder to a file\n     * @return {!string} The URL to the module's folder\n     **/\n    function getModuleUrl(module, path) {\n        var url = encodeURI(getModulePath(module, path));\n\n        // On Windows, $.get() fails if the url is a full pathname. To work around this,\n        // prepend \"file:///\". On the Mac, $.get() works fine if the url is a full pathname,\n        // but *doesn't* work if it is prepended with \"file://\". Go figure.\n        // However, the prefix \"file://localhost\" does work.\n        if (brackets.platform === \"win\" && url.indexOf(\":\") !== -1) {\n            url = \"file:///\" + url;\n        }\n\n        return url;\n    }\n\n    /**\n     * Performs a GET request using a path relative to an extension module.\n     *\n     * The resulting URL can be retrieved in the resolve callback by accessing\n     *\n     * @param {!module} module Module provided by RequireJS\n     * @param {!string} path Relative path from the extension folder to a file\n     * @return {!$.Promise} A promise object that is resolved with the contents of the requested file\n     **/\n    function loadFile(module, path) {\n        var url     = PathUtils.isAbsoluteUrl(path) ? path : getModuleUrl(module, path),\n            promise = $.get(url);\n\n        return promise;\n    }\n\n    /**\n     * Loads a style sheet (CSS or LESS) relative to the extension module.\n     *\n     * @param {!module} module Module provided by RequireJS\n     * @param {!string} path Relative path from the extension folder to a CSS or LESS file\n     * @return {!$.Promise} A promise object that is resolved with an HTML node if the file can be loaded.\n     */\n    function loadStyleSheet(module, path) {\n        var result = new $.Deferred();\n\n        loadFile(module, path)\n            .done(function (content) {\n                var url = this.url;\n\n                if (url.slice(-5) === \".less\") {\n                    parseLessCode(content, url)\n                        .done(function (css) {\n                            result.resolve(addEmbeddedStyleSheet(css));\n                        })\n                        .fail(result.reject);\n                } else {\n                    var deferred = new $.Deferred(),\n                        link = addLinkedStyleSheet(url, deferred);\n\n                    deferred\n                        .done(function () {\n                            result.resolve(link);\n                        })\n                        .fail(result.reject);\n                }\n            })\n            .fail(result.reject);\n\n        // Summarize error info to console for easier debugging\n        result.fail(function (error, textStatus, httpError) {\n            if (error.readyState !== undefined) {\n                // If first arg is a jQXHR object, the real error info is in the next two args\n                console.error(\"[Extension] Unable to read stylesheet \" + path + \":\", textStatus, httpError);\n            } else {\n                console.error(\"[Extension] Unable to process stylesheet \" + path, error);\n            }\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * Loads the package.json file in the given extension folder as well as any additional\n     * metadata.\n     *\n     * If there's a .disabled file in the extension directory, then the content of package.json\n     * will be augmented with disabled property set to true. It will override whatever value of\n     * disabled might be set.\n     *\n     * @param {string} folder The extension folder.\n     * @return {$.Promise} A promise object that is resolved with the parsed contents of the package.json file,\n     *     or rejected if there is no package.json with the boolean indicating whether .disabled file exists.\n     */\n    function loadMetadata(folder) {\n        var packageJSONFile = FileSystem.getFileForPath(folder + \"/package.json\"),\n            disabledFile = FileSystem.getFileForPath(folder + \"/.disabled\"),\n            baseName = FileUtils.getBaseName(folder),\n            result = new $.Deferred(),\n            jsonPromise = new $.Deferred(),\n            disabledPromise = new $.Deferred(),\n            json,\n            disabled;\n        FileUtils.readAsText(packageJSONFile)\n            .then(function (text) {\n                try {\n                    json = JSON.parse(text);\n                    jsonPromise.resolve();\n                } catch (e) {\n                    jsonPromise.reject();\n                }\n            })\n            .fail(jsonPromise.reject);\n        disabledFile.exists(function (err, exists) {\n            if (err) {\n                disabled = false;\n            } else {\n                disabled = exists;\n            }\n\n            var defaultDisabled = PreferencesManager.get(\"extensions.default.disabled\");\n            if (Array.isArray(defaultDisabled) && defaultDisabled.indexOf(folder) !== -1) {\n                console.warn(\"Default extension has been disabled on startup: \" + baseName);\n                disabled = true;\n            }\n\n            disabledPromise.resolve();\n        });\n        Async.waitForAll([jsonPromise, disabledPromise])\n            .always(function () {\n                if (!json) {\n                    // if we don't have any metadata for the extension\n                    // we should still create an empty one, so we can attach\n                    // disabled property on it in case it's disabled\n                    json = {\n                        name: baseName\n                    };\n                }\n                json.disabled = disabled;\n                result.resolve(json);\n            });\n        return result.promise();\n    }\n\n    exports.addEmbeddedStyleSheet = addEmbeddedStyleSheet;\n    exports.addLinkedStyleSheet   = addLinkedStyleSheet;\n    exports.parseLessCode         = parseLessCode;\n    exports.getModulePath         = getModulePath;\n    exports.getModuleUrl          = getModuleUrl;\n    exports.loadFile              = loadFile;\n    exports.loadStyleSheet        = loadStyleSheet;\n    exports.loadMetadata          = loadMetadata;\n});\n"
  },
  {
    "path": "src/utils/Global.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Initializes the global \"brackets\" variable and it's properties.\n * Modules should not access the global.brackets object until either\n * (a) the module requires this module, i.e. require(\"utils/Global\") or\n * (b) the module receives a \"appReady\" callback from the utils/AppReady module.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var configJSON  = require(\"text!config.json\"),\n        UrlParams   = require(\"utils/UrlParams\").UrlParams;\n\n    // Define core brackets namespace if it isn't already defined\n    //\n    // We can't simply do 'brackets = {}' to define it in the global namespace because\n    // we're in \"use strict\" mode. Most likely, 'window' will always point to the global\n    // object when this code is running. However, in case it isn't (e.g. if we're running\n    // inside Node for CI testing) we use this trick to get the global object.\n    var Fn = Function, global = (new Fn(\"return this\"))();\n    if (!global.brackets) {\n\n        // Earlier brackets object was initialized at \n        // https://github.com/adobe/brackets-shell/blob/908ed1503995c1b5ae013473c4b181a9aa64fd22/appshell/appshell_extensions.js#L945.\n        // With the newer versions of CEF, the initialization was crashing the render process, citing\n        // JS eval error. So moved the brackets object initialization from appshell_extensions.js to here.\n        if (global.appshell) {\n            global.brackets = global.appshell;\n        } else {\n            global.brackets = {};\n        }\n    }\n\n    // Parse URL params\n    var params = new UrlParams();\n    params.parse();\n\n    // Parse src/config.json\n    try {\n        global.brackets.metadata = JSON.parse(configJSON);\n        global.brackets.config = global.brackets.metadata.config;\n    } catch (err) {\n        console.log(err);\n    }\n\n    // Uncomment the following line to force all low level file i/o routines to complete\n    // asynchronously. This should only be done for testing/debugging.\n    // NOTE: Make sure this line is commented out again before committing!\n    //brackets.forceAsyncCallbacks = true;\n\n    // Load native shell when brackets is run in a native shell rather than the browser\n    // TODO: (issue #266) load conditionally\n    global.brackets.shellAPI = require(\"utils/ShellAPI\");\n\n    // Determine OS/platform\n    if (global.navigator.platform === \"MacIntel\" || global.navigator.platform === \"MacPPC\") {\n        global.brackets.platform = \"mac\";\n    } else if (global.navigator.platform.indexOf(\"Linux\") >= 0) {\n        global.brackets.platform = \"linux\";\n    } else {\n        global.brackets.platform = \"win\";\n    }\n\n    // Expose platform info for build applicability consumption\n    global.brackets.getPlatformInfo = function () {\n        var OS = \"\";\n\n        if (/Windows|Win32|WOW64|Win64/.test(window.navigator.userAgent)) {\n            OS = \"WIN\";\n        } else if (/Mac/.test(window.navigator.userAgent)) {\n            OS = \"OSX\";\n        } else if (/Linux|X11/.test(window.navigator.userAgent)) {\n            OS = \"LINUX32\";\n            if (/x86_64/.test(window.navigator.appVersion + window.navigator.userAgent)) {\n                OS = \"LINUX64\";\n            }\n        }\n\n        return OS;\n    };\n\n    global.brackets.inBrowser = !global.brackets.hasOwnProperty(\"fs\");\n\n    // Are we in a desktop shell with a native menu bar?\n    var hasNativeMenus = params.get(\"hasNativeMenus\");\n    if (hasNativeMenus) {\n        global.brackets.nativeMenus = (hasNativeMenus === \"true\");\n    } else {\n        global.brackets.nativeMenus = (!global.brackets.inBrowser);\n    }\n\n    // Locale-related APIs\n    global.brackets.isLocaleDefault = function () {\n        return !global.localStorage.getItem(\"locale\");\n    };\n\n    global.brackets.getLocale = function () {\n        // By default use the locale that was determined in brackets.js\n        return params.get(\"testEnvironment\") ? \"en\" : (global.localStorage.getItem(\"locale\") || global.require.s.contexts._.config.locale);\n    };\n\n    global.brackets.setLocale = function (locale) {\n        if (locale) {\n            global.localStorage.setItem(\"locale\", locale);\n        } else {\n            global.localStorage.removeItem(\"locale\");\n        }\n    };\n\n    // Create empty app namespace if running in-browser\n    if (!global.brackets.app) {\n        global.brackets.app = {};\n    }\n\n    // Loading extensions requires creating new require.js contexts, which\n    // requires access to the global 'require' object that always gets hidden\n    // by the 'require' in the AMD wrapper. We store this in the brackets\n    // object here so that the ExtensionLoader doesn't have to have access to\n    // the global object.\n    global.brackets.libRequire = global.require;\n\n    // Also store our current require.js context (the one that loads brackets\n    // core modules) so that extensions can use it.\n    // Note: we change the name to \"getModule\" because this won't do exactly\n    // the same thing as 'require' in AMD-wrapped modules. The extension will\n    // only be able to load modules that have already been loaded once.\n    global.brackets.getModule = require;\n\n    /* API for retrieving the global RequireJS config\n     * For internal use only\n     */\n    global.brackets._getGlobalRequireJSConfig = function () {\n        return global.require.s.contexts._.config;\n    };\n    \n    exports.global = global;\n});\n"
  },
  {
    "path": "src/utils/HealthLogger.js",
    "content": "/*\n * Copyright (c) 2015 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n *  Utilities functions related to Health Data logging\n */\n/*global Map*/\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var PreferencesManager          = require(\"preferences/PreferencesManager\"),\n        LanguageManager             = require(\"language/LanguageManager\"),\n        FileUtils                   = require(\"file/FileUtils\"),\n        PerfUtils                   = require(\"utils/PerfUtils\"),\n        FindUtils                   = require(\"search/FindUtils\"),\n        StringUtils                 = require(\"utils/StringUtils\"),\n        EventDispatcher             = require(\"utils/EventDispatcher\"),\n\n        HEALTH_DATA_STATE_KEY       = \"HealthData.Logs\",\n        logHealthData               = true,\n        analyticsEventMap           = new Map();\n\n    var commonStrings = { USAGE: \"usage\",\n        FILE_OPEN: \"fileOpen\",\n        FILE_NEW: \"newfile\",\n        FILE_SAVE: \"fileSave\",\n        FILE_CLOSE: \"fileClose\",\n        LANGUAGE_CHANGE: \"languageChange\",\n        LANGUAGE_SERVER_PROTOCOL: \"languageServerProtocol\",\n        CODE_HINTS: \"codeHints\",\n        PARAM_HINTS: \"parameterHints\",\n        JUMP_TO_DEF: \"jumpToDefinition\"\n    };\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    /**\n     * Init: creates the health log preference keys in the state.json file\n     */\n    function init() {\n        PreferencesManager.stateManager.definePreference(HEALTH_DATA_STATE_KEY, \"object\", {});\n    }\n\n    /**\n     * All the logging functions should be disabled if this returns false\n     * @return {boolean} true if health data can be logged\n     */\n    function shouldLogHealthData() {\n        return logHealthData;\n    }\n\n    /**\n     * Return all health data logged till now stored in the state prefs\n     * @return {Object} Health Data aggregated till now\n     */\n    function getStoredHealthData() {\n        var storedData = PreferencesManager.getViewState(HEALTH_DATA_STATE_KEY) || {};\n        return storedData;\n    }\n\n    /**\n     * Return the aggregate of all health data logged till now from all sources\n     * @return {Object} Health Data aggregated till now\n     */\n    function getAggregatedHealthData() {\n        var healthData = getStoredHealthData();\n        $.extend(healthData, PerfUtils.getHealthReport());\n        $.extend(healthData, FindUtils.getHealthReport());\n        return healthData;\n    }\n\n    /**\n     * Sets the health data\n     * @param {Object} dataObject The object to be stored as health data\n     */\n    function setHealthData(dataObject) {\n        if (!shouldLogHealthData()) {\n            return;\n        }\n        PreferencesManager.setViewState(HEALTH_DATA_STATE_KEY, dataObject);\n    }\n\n    /**\n     * Returns health data logged for the given key\n     * @return {Object} Health Data object for the key or undefined if no health data stored\n     */\n    function getHealthDataLog(key) {\n        var healthData = getStoredHealthData();\n        return healthData[key];\n    }\n\n    /**\n     * Sets the health data for the given key\n     * @param {Object} dataObject The object to be stored as health data for the key\n     */\n    function setHealthDataLog(key, dataObject) {\n        var healthData = getStoredHealthData();\n        healthData[key] = dataObject;\n        setHealthData(healthData);\n    }\n\n    /**\n     * Clears all the health data recorded till now\n     */\n    function clearHealthData() {\n        PreferencesManager.setViewState(HEALTH_DATA_STATE_KEY, {});\n        //clear the performance related health data also\n        PerfUtils.clear();\n    }\n\n    /**\n     * Enable or disable health data logs\n     * @param {boolean} enabled true to enable health logs\n     */\n    function setHealthLogsEnabled(enabled) {\n        logHealthData = enabled;\n        if (!enabled) {\n            clearHealthData();\n        }\n    }\n\n    /**\n     * Whenever a file is opened call this function. The function will record the number of times\n     * the standard file types have been opened. We only log the standard filetypes\n     * @param {String} filePath          The path of the file to be registered\n     * @param {boolean} addedToWorkingSet set to true if extensions of files added to the\n     *                                    working set needs to be logged\n     */\n    function fileOpened(filePath, addedToWorkingSet, encoding) {\n        if (!shouldLogHealthData()) {\n            return;\n        }\n        var fileExtension = FileUtils.getFileExtension(filePath),\n            language = LanguageManager.getLanguageForPath(filePath),\n            healthData = getStoredHealthData(),\n            fileExtCountMap = [];\n        healthData.fileStats = healthData.fileStats || {\n            openedFileExt     : {},\n            workingSetFileExt : {},\n            openedFileEncoding: {}\n        };\n        if (language.getId() !== \"unknown\") {\n            fileExtCountMap = addedToWorkingSet ? healthData.fileStats.workingSetFileExt : healthData.fileStats.openedFileExt;\n            if (!fileExtCountMap[fileExtension]) {\n                fileExtCountMap[fileExtension] = 0;\n            }\n            fileExtCountMap[fileExtension]++;\n            setHealthData(healthData);\n        }\n        if (encoding) {\n            var fileEncCountMap = healthData.fileStats.openedFileEncoding;\n            if (!fileEncCountMap) {\n                healthData.fileStats.openedFileEncoding = {};\n                fileEncCountMap = healthData.fileStats.openedFileEncoding;\n            }\n            if (!fileEncCountMap[encoding]) {\n                fileEncCountMap[encoding] = 0;\n            }\n            fileEncCountMap[encoding]++;\n            setHealthData(healthData);\n        }\n\n\n        sendAnalyticsData(commonStrings.USAGE + commonStrings.FILE_OPEN + language._name,\n                            commonStrings.USAGE,\n                            commonStrings.FILE_OPEN,\n                            language._name.toLowerCase()\n                         );\n\n    }\n\n    /**\n     * Whenever a file is saved call this function.\n     * The function will send the analytics Data\n     * We only log the standard filetypes and fileSize\n     * @param {String} filePath The path of the file to be registered\n     */\n    function fileSaved(docToSave) {\n        if (!docToSave) {\n            return;\n        }\n        var fileType = docToSave.language ? docToSave.language._name : \"\";\n        sendAnalyticsData(commonStrings.USAGE + commonStrings.FILE_SAVE + fileType,\n                            commonStrings.USAGE,\n                            commonStrings.FILE_SAVE,\n                            fileType.toLowerCase()\n                         );\n    }\n\n    /**\n     * Whenever a file is closed call this function.\n     * The function will send the analytics Data.\n     * We only log the standard filetypes and fileSize\n     * @param {String} filePath The path of the file to be registered\n     */\n    function fileClosed(file) {\n        if (!file) {\n            return;\n        }\n        var language = LanguageManager.getLanguageForPath(file._path),\n            size = -1;\n\n        function _sendData(fileSize) {\n            var subType = \"\";\n\n            if(fileSize/1024 <= 1) {\n\n                if(fileSize < 0) {\n                    subType = \"\";\n                }\n                if(fileSize <= 10) {\n                    subType = \"Size_0_10KB\";\n                } else if (fileSize <= 50) {\n                    subType = \"Size_10_50KB\";\n                } else if (fileSize <= 100) {\n                    subType = \"Size_50_100KB\";\n                } else if (fileSize <= 500) {\n                    subType = \"Size_100_500KB\";\n                } else {\n                    subType = \"Size_500KB_1MB\";\n                }\n\n            } else {\n                fileSize = fileSize/1024;\n                if(fileSize <= 2) {\n                    subType = \"Size_1_2MB\";\n                } else if(fileSize <= 5) {\n                    subType = \"Size_2_5MB\";\n                } else {\n                    subType = \"Size_Above_5MB\";\n                }\n            }\n\n            sendAnalyticsData(commonStrings.USAGE + commonStrings.FILE_CLOSE + language._name + subType,\n                                commonStrings.USAGE,\n                                commonStrings.FILE_CLOSE,\n                                language._name.toLowerCase(),\n                                subType\n                             );\n        }\n\n        file.stat(function(err, fileStat) {\n            if(!err) {\n                size = fileStat.size.valueOf()/1024;\n            }\n            _sendData(size);\n        });\n    }\n\n    /**\n     * Sets the project details(a probably unique prjID, number of files in the project and the node cache size) in the health log\n     * The name of the project is never saved into the health data log, only the hash(name) is for privacy requirements.\n     * @param {string} projectName The name of the project\n     * @param {number} numFiles    The number of file in the project\n     * @param {number} cacheSize   The node file cache memory consumed by the project\n     */\n    function setProjectDetail(projectName, numFiles, cacheSize) {\n        var projectNameHash = StringUtils.hashCode(projectName),\n            FIFLog = getHealthDataLog(\"ProjectDetails\");\n        if (!FIFLog) {\n            FIFLog = {};\n        }\n        FIFLog[\"prj\" + projectNameHash] = {\n            numFiles : numFiles,\n            cacheSize : cacheSize\n        };\n        setHealthDataLog(\"ProjectDetails\", FIFLog);\n    }\n\n    /**\n     * Increments health log count for a particular kind of search done\n     * @param {string} searchType The kind of search type that needs to be logged- should be a js var compatible string\n     */\n    function searchDone(searchType) {\n        var searchDetails = getHealthDataLog(\"searchDetails\");\n        if (!searchDetails) {\n            searchDetails = {};\n        }\n        if (!searchDetails[searchType]) {\n            searchDetails[searchType] = 0;\n        }\n        searchDetails[searchType]++;\n        setHealthDataLog(\"searchDetails\", searchDetails);\n    }\n\n     /**\n     * Notifies the HealthData extension to send Analytics Data to server\n     * @param{Object} eventParams Event Data to be sent to Analytics Server\n     */\n    function notifyHealthManagerToSendData(eventParams) {\n        exports.trigger(\"SendAnalyticsData\", eventParams);\n    }\n\n    /**\n     * Send Analytics Data\n     * @param {string} eventCategory The kind of Event Category that\n     * needs to be logged- should be a js var compatible string\n     * @param {string} eventSubCategory The kind of Event Sub Category that\n     * needs to be logged- should be a js var compatible string\n     * @param {string} eventType The kind of Event Type that needs to be logged- should be a js var compatible string\n     * @param {string} eventSubType The kind of Event Sub Type that\n     * needs to be logged- should be a js var compatible string\n     */\n    function sendAnalyticsData(eventName, eventCategory, eventSubCategory, eventType, eventSubType) {\n        var isEventDataAlreadySent = analyticsEventMap.get(eventName),\n            isHDTracking   = PreferencesManager.getExtensionPrefs(\"healthData\").get(\"healthDataTracking\"),\n            eventParams = {};\n\n        if (isHDTracking && !isEventDataAlreadySent && eventName && eventCategory) {\n            eventParams =  {\n                eventName: eventName,\n                eventCategory: eventCategory,\n                eventSubCategory: eventSubCategory || \"\",\n                eventType: eventType || \"\",\n                eventSubType: eventSubType || \"\"\n            };\n            notifyHealthManagerToSendData(eventParams);\n        }\n    }\n\n    // Define public API\n    exports.getHealthDataLog          = getHealthDataLog;\n    exports.setHealthDataLog          = setHealthDataLog;\n    exports.getAggregatedHealthData   = getAggregatedHealthData;\n    exports.clearHealthData           = clearHealthData;\n    exports.fileOpened                = fileOpened;\n    exports.fileSaved                 = fileSaved;\n    exports.fileClosed                = fileClosed;\n    exports.setProjectDetail          = setProjectDetail;\n    exports.searchDone                = searchDone;\n    exports.setHealthLogsEnabled      = setHealthLogsEnabled;\n    exports.shouldLogHealthData       = shouldLogHealthData;\n    exports.init                      = init;\n    exports.sendAnalyticsData         = sendAnalyticsData;\n\n    // constants\n    // searchType for searchDone()\n    exports.SEARCH_INSTANT            = \"searchInstant\";\n    exports.SEARCH_ON_RETURN_KEY      = \"searchOnReturnKey\";\n    exports.SEARCH_REPLACE_ALL        = \"searchReplaceAll\";\n    exports.SEARCH_NEXT_PAGE          = \"searchNextPage\";\n    exports.SEARCH_PREV_PAGE          = \"searchPrevPage\";\n    exports.SEARCH_LAST_PAGE          = \"searchLastPage\";\n    exports.SEARCH_FIRST_PAGE         = \"searchFirstPage\";\n    exports.SEARCH_REGEXP             = \"searchRegExp\";\n    exports.SEARCH_CASE_SENSITIVE     = \"searchCaseSensitive\";\n    // A new search context on search bar up-Gives an idea of number of times user did a discrete search\n    exports.SEARCH_NEW                = \"searchNew\";\n    exports.commonStrings = commonStrings;\n    exports.analyticsEventMap = analyticsEventMap;\n});\n"
  },
  {
    "path": "src/utils/KeyEvent.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities module to provide constants for keyCodes\n */\ndefine({\n    DOM_VK_CANCEL: 3,\n    DOM_VK_HELP: 6,\n    DOM_VK_BACK_SPACE: 8,\n    DOM_VK_TAB: 9,\n    DOM_VK_CLEAR: 12,\n    DOM_VK_RETURN: 13,\n    DOM_VK_ENTER: 14,\n    DOM_VK_SHIFT: 16,\n    DOM_VK_CONTROL: 17,\n    DOM_VK_ALT: 18,\n    DOM_VK_PAUSE: 19,\n    DOM_VK_CAPS_LOCK: 20,\n    DOM_VK_ESCAPE: 27,\n    DOM_VK_SPACE: 32,\n    DOM_VK_PAGE_UP: 33,\n    DOM_VK_PAGE_DOWN: 34,\n    DOM_VK_END: 35,\n    DOM_VK_HOME: 36,\n    DOM_VK_LEFT: 37,\n    DOM_VK_UP: 38,\n    DOM_VK_RIGHT: 39,\n    DOM_VK_DOWN: 40,\n    DOM_VK_PRINTSCREEN: 44,\n    DOM_VK_INSERT: 45,\n    DOM_VK_DELETE: 46,\n    DOM_VK_0: 48,\n    DOM_VK_1: 49,\n    DOM_VK_2: 50,\n    DOM_VK_3: 51,\n    DOM_VK_4: 52,\n    DOM_VK_5: 53,\n    DOM_VK_6: 54,\n    DOM_VK_7: 55,\n    DOM_VK_8: 56,\n    DOM_VK_9: 57,\n    DOM_VK_A: 65,\n    DOM_VK_B: 66,\n    DOM_VK_C: 67,\n    DOM_VK_D: 68,\n    DOM_VK_E: 69,\n    DOM_VK_F: 70,\n    DOM_VK_G: 71,\n    DOM_VK_H: 72,\n    DOM_VK_I: 73,\n    DOM_VK_J: 74,\n    DOM_VK_K: 75,\n    DOM_VK_L: 76,\n    DOM_VK_M: 77,\n    DOM_VK_N: 78,\n    DOM_VK_O: 79,\n    DOM_VK_P: 80,\n    DOM_VK_Q: 81,\n    DOM_VK_R: 82,\n    DOM_VK_S: 83,\n    DOM_VK_T: 84,\n    DOM_VK_U: 85,\n    DOM_VK_V: 86,\n    DOM_VK_W: 87,\n    DOM_VK_X: 88,\n    DOM_VK_Y: 89,\n    DOM_VK_Z: 90,\n    DOM_VK_CONTEXT_MENU: 93,\n    DOM_VK_NUMPAD0: 96,\n    DOM_VK_NUMPAD1: 97,\n    DOM_VK_NUMPAD2: 98,\n    DOM_VK_NUMPAD3: 99,\n    DOM_VK_NUMPAD4: 100,\n    DOM_VK_NUMPAD5: 101,\n    DOM_VK_NUMPAD6: 102,\n    DOM_VK_NUMPAD7: 103,\n    DOM_VK_NUMPAD8: 104,\n    DOM_VK_NUMPAD9: 105,\n    DOM_VK_MULTIPLY: 106,\n    DOM_VK_ADD: 107,\n    DOM_VK_SEPARATOR: 108,\n    DOM_VK_SUBTRACT: 109,\n    DOM_VK_DECIMAL: 110,\n    DOM_VK_DIVIDE: 111,\n    DOM_VK_F1: 112,\n    DOM_VK_F2: 113,\n    DOM_VK_F3: 114,\n    DOM_VK_F4: 115,\n    DOM_VK_F5: 116,\n    DOM_VK_F6: 117,\n    DOM_VK_F7: 118,\n    DOM_VK_F8: 119,\n    DOM_VK_F9: 120,\n    DOM_VK_F10: 121,\n    DOM_VK_F11: 122,\n    DOM_VK_F12: 123,\n    DOM_VK_F13: 124,\n    DOM_VK_F14: 125,\n    DOM_VK_F15: 126,\n    DOM_VK_F16: 127,\n    DOM_VK_F17: 128,\n    DOM_VK_F18: 129,\n    DOM_VK_F19: 130,\n    DOM_VK_F20: 131,\n    DOM_VK_F21: 132,\n    DOM_VK_F22: 133,\n    DOM_VK_F23: 134,\n    DOM_VK_F24: 135,\n    DOM_VK_NUM_LOCK: 144,\n    DOM_VK_SCROLL_LOCK: 145,\n    DOM_VK_SEMICOLON: 186,\n    DOM_VK_EQUALS: 187,\n    DOM_VK_COMMA: 188,\n    DOM_VK_DASH: 189,\n    DOM_VK_PERIOD: 190,\n    DOM_VK_SLASH: 191,\n    DOM_VK_BACK_QUOTE: 192,\n    DOM_VK_OPEN_BRACKET: 219,\n    DOM_VK_BACK_SLASH: 220,\n    DOM_VK_CLOSE_BRACKET: 221,\n    DOM_VK_QUOTE: 222,\n    DOM_VK_META: 224\n\n});\n"
  },
  {
    "path": "src/utils/LocalizationUtils.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n *  Utilities functions related to localization/i18n\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Strings = require(\"strings\");\n\n    /*\n     * Converts a language code to its written name, if possible.\n     * If not possible, the language code is simply returned.\n     *\n     * @param {string} locale The two-char language code\n     * @return {string} The language's name or the given language code\n     */\n    function getLocalizedLabel(locale) {\n        var key  = \"LOCALE_\" + locale.toUpperCase().replace(\"-\", \"_\"),\n            i18n = Strings[key];\n\n        return i18n === undefined ? locale : i18n;\n    }\n\n\n    // Define public API\n    exports.getLocalizedLabel = getLocalizedLabel;\n});\n"
  },
  {
    "path": "src/utils/NativeApp.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Async           = require(\"utils/Async\"),\n        FileSystemError = require(\"filesystem/FileSystemError\");\n\n    /**\n     * @private\n     * Map an fs error code to a FileError.\n     */\n    function _browserErrToFileError(err) {\n        if (err === brackets.fs.ERR_NOT_FOUND) {\n            return FileSystemError.NOT_FOUND;\n        }\n\n        // All other errors are mapped to the generic \"unknown\" error\n        return FileSystemError.UNKNOWN;\n    }\n\n    var liveBrowserOpenedPIDs = [];\n\n    /** openLiveBrowser\n     * Open the given URL in the user's system browser, optionally enabling debugging.\n     * @param {string} url The URL to open.\n     * @param {boolean=} enableRemoteDebugging Whether to turn on remote debugging. Default false.\n     * @return {$.Promise}\n     */\n    function openLiveBrowser(url, enableRemoteDebugging) {\n        var result = new $.Deferred();\n\n        brackets.app.openLiveBrowser(url, !!enableRemoteDebugging, function onRun(err, pid) {\n            if (!err) {\n                // Undefined ids never get removed from list, so don't push them on\n                if (pid !== undefined) {\n                    liveBrowserOpenedPIDs.push(pid);\n                }\n                result.resolve(pid);\n            } else {\n                result.reject(_browserErrToFileError(err));\n            }\n        });\n\n        return result.promise();\n    }\n\n    /** closeLiveBrowser\n     *\n     * @return {$.Promise}\n     */\n    function closeLiveBrowser(pid) {\n        var result = new $.Deferred();\n\n        if (isNaN(pid)) {\n            pid = 0;\n        }\n        brackets.app.closeLiveBrowser(function (err) {\n            if (!err) {\n                var i = liveBrowserOpenedPIDs.indexOf(pid);\n                if (i !== -1) {\n                    liveBrowserOpenedPIDs.splice(i, 1);\n                }\n                result.resolve();\n            } else {\n                result.reject(_browserErrToFileError(err));\n            }\n        }, pid);\n\n        return result.promise();\n    }\n\n    /** closeAllLiveBrowsers\n     * Closes all the browsers that were tracked on open\n     * TODO: does not seem to work on Windows\n     * @return {$.Promise}\n     */\n    function closeAllLiveBrowsers() {\n        //make a copy incase the array is edited as we iterate\n        var closeIDs = liveBrowserOpenedPIDs.concat();\n        return Async.doSequentially(closeIDs, closeLiveBrowser, false);\n    }\n\n    /**\n     * Opens a URL in the system default browser\n     */\n    function openURLInDefaultBrowser(url) {\n        brackets.app.openURLInDefaultBrowser(url);\n    }\n\n\n    // Define public API\n    exports.openLiveBrowser = openLiveBrowser;\n    exports.closeLiveBrowser = closeLiveBrowser;\n    exports.closeAllLiveBrowsers = closeAllLiveBrowsers;\n    exports.openURLInDefaultBrowser = openURLInDefaultBrowser;\n});\n"
  },
  {
    "path": "src/utils/NodeConnection.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var EventDispatcher = require(\"utils/EventDispatcher\");\n\n\n    /**\n     * Connection attempts to make before failing\n     * @type {number}\n     */\n    var CONNECTION_ATTEMPTS = 10;\n\n    /**\n     * Milliseconds to wait before a particular connection attempt is considered failed.\n     * NOTE: It's okay for the connection timeout to be long because the\n     * expected behavior of WebSockets is to send a \"close\" event as soon\n     * as they realize they can't connect. So, we should rarely hit the\n     * connection timeout even if we try to connect to a port that isn't open.\n     * @type {number}\n     */\n    var CONNECTION_TIMEOUT  = 10000; // 10 seconds\n\n    /**\n     * Milliseconds to wait before retrying connecting\n     * @type {number}\n     */\n    var RETRY_DELAY         = 500;   // 1/2 second\n\n    /**\n     * Maximum value of the command ID counter\n     * @type  {number}\n     */\n    var MAX_COUNTER_VALUE = 4294967295; // 2^32 - 1\n\n    /**\n     * @private\n     * Helper function to auto-reject a deferred after a given amount of time.\n     * If the deferred is resolved/rejected manually, then the timeout is\n     * automatically cleared.\n     */\n    function setDeferredTimeout(deferred, delay) {\n        var timer = setTimeout(function () {\n            deferred.reject(\"timeout\");\n        }, delay);\n        deferred.always(function () { clearTimeout(timer); });\n    }\n\n    /**\n     * @private\n     * Helper function to attempt a single connection to the node server\n     */\n    function attemptSingleConnect() {\n        var deferred = $.Deferred();\n        var port = null;\n        var ws = null;\n        setDeferredTimeout(deferred, CONNECTION_TIMEOUT);\n\n        brackets.app.getNodeState(function (err, nodePort) {\n            if (!err && nodePort && deferred.state() !== \"rejected\") {\n                port = nodePort;\n                ws = new WebSocket(\"ws://localhost:\" + port);\n\n                // Expect ArrayBuffer objects from Node when receiving binary\n                // data instead of DOM Blobs, which are the default.\n                ws.binaryType = \"arraybuffer\";\n\n                // If the server port isn't open, we get a close event\n                // at some point in the future (and will not get an onopen\n                // event)\n                ws.onclose = function () {\n                    deferred.reject(\"WebSocket closed\");\n                };\n\n                ws.onopen = function () {\n                    // If we successfully opened, remove the old onclose\n                    // handler (which was present to detect failure to\n                    // connect at all).\n                    ws.onclose = null;\n                    deferred.resolveWith(null, [ws, port]);\n                };\n            } else {\n                deferred.reject(\"brackets.app.getNodeState error: \" + err);\n            }\n        });\n\n        return deferred.promise();\n    }\n\n    /**\n     * Provides an interface for interacting with the node server.\n     * @constructor\n     */\n    function NodeConnection() {\n        this.domains = {};\n        this._registeredModules = [];\n        this._pendingInterfaceRefreshDeferreds = [];\n        this._pendingCommandDeferreds = [];\n    }\n    EventDispatcher.makeEventDispatcher(NodeConnection.prototype);\n\n    /**\n     * @type {Object}\n     * Exposes the domains registered with the server. This object will\n     * have a property for each registered domain. Each of those properties\n     * will be an object containing properties for all the commands in that\n     * domain. So, myConnection.base.enableDebugger would point to the function\n     * to call to enable the debugger.\n     *\n     * This object is automatically replaced every time the API changes (based\n     * on the base:newDomains event from the server). Therefore, code that\n     * uses this object should not keep their own pointer to the domain property.\n     */\n    NodeConnection.prototype.domains = null;\n\n    /**\n     * @private\n     * @type {Array.<string>}\n     * List of module pathnames that should be re-registered if there is\n     * a disconnection/connection (i.e. if the server died).\n     */\n    NodeConnection.prototype._registeredModules = null;\n\n    /**\n     * @private\n     * @type {WebSocket}\n     * The connection to the server\n     */\n    NodeConnection.prototype._ws = null;\n\n    /**\n     * @private\n     * @type {?number}\n     * The port the WebSocket is currently connected to\n     */\n    NodeConnection.prototype._port = null;\n\n    /**\n     * @private\n     * @type {number}\n     * Unique ID for commands\n     */\n    NodeConnection.prototype._commandCount = 1;\n\n    /**\n     * @private\n     * @type {boolean}\n     * Whether to attempt reconnection if connection fails\n     */\n    NodeConnection.prototype._autoReconnect = false;\n\n    /**\n     * @private\n     * @type {Array.<jQuery.Deferred>}\n     * List of deferred objects that should be resolved pending\n     * a successful refresh of the API\n     */\n    NodeConnection.prototype._pendingInterfaceRefreshDeferreds = null;\n\n    /**\n     * @private\n     * @type {Array.<jQuery.Deferred>}\n     * Array (indexed on command ID) of deferred objects that should be\n     * resolved/rejected with the response of commands.\n     */\n    NodeConnection.prototype._pendingCommandDeferreds = null;\n\n    /**\n     * @private\n     * @return {number} The next command ID to use. Always representable as an\n     * unsigned 32-bit integer.\n     */\n    NodeConnection.prototype._getNextCommandID = function () {\n        var nextID;\n\n        if (this._commandCount > MAX_COUNTER_VALUE) {\n            nextID = this._commandCount = 0;\n        } else {\n            nextID = this._commandCount++;\n        }\n\n        return nextID;\n    };\n\n    /**\n     * @private\n     * Helper function to do cleanup work when a connection fails\n     */\n    NodeConnection.prototype._cleanup = function () {\n        // clear out the domains, since we may get different ones\n        // on the next connection\n        this.domains = {};\n\n        // shut down the old connection if there is one\n        if (this._ws && this._ws.readyState !== WebSocket.CLOSED) {\n            try {\n                this._ws.close();\n            } catch (e) { }\n        }\n        var failedDeferreds = this._pendingInterfaceRefreshDeferreds\n            .concat(this._pendingCommandDeferreds);\n        failedDeferreds.forEach(function (d) {\n            d.reject(\"cleanup\");\n        });\n        this._pendingInterfaceRefreshDeferreds = [];\n        this._pendingCommandDeferreds = [];\n\n        this._ws = null;\n        this._port = null;\n    };\n\n    /**\n     * Connect to the node server. After connecting, the NodeConnection\n     * object will trigger a \"close\" event when the underlying socket\n     * is closed. If the connection is set to autoReconnect, then the\n     * event will also include a jQuery promise for the connection.\n     *\n     * @param {boolean} autoReconnect Whether to automatically try to\n     *    reconnect to the server if the connection succeeds and then\n     *    later disconnects. Note if this connection fails initially, the\n     *    autoReconnect flag is set to false. Future calls to connect()\n     *    can reset it to true\n     * @return {jQuery.Promise} Promise that resolves/rejects when the\n     *    connection succeeds/fails\n     */\n    NodeConnection.prototype.connect = function (autoReconnect) {\n        var self = this;\n        self._autoReconnect = autoReconnect;\n        var deferred = $.Deferred();\n        var attemptCount = 0;\n        var attemptTimestamp = null;\n\n        // Called after a successful connection to do final setup steps\n        function registerHandlersAndDomains(ws, port) {\n            // Called if we succeed at the final setup\n            function success() {\n                self._ws.onclose = function () {\n                    if (self._autoReconnect) {\n                        var $promise = self.connect(true);\n                        self.trigger(\"close\", $promise);\n                    } else {\n                        self._cleanup();\n                        self.trigger(\"close\");\n                    }\n                };\n                deferred.resolve();\n            }\n            // Called if we fail at the final setup\n            function fail(err) {\n                self._cleanup();\n                deferred.reject(err);\n            }\n\n            self._ws = ws;\n            self._port = port;\n            self._ws.onmessage = self._receive.bind(self);\n\n            // refresh the current domains, then re-register any\n            // \"autoregister\" modules\n            self._refreshInterface().then(\n                function () {\n                    if (self._registeredModules.length > 0) {\n                        self.loadDomains(self._registeredModules, false).then(\n                            success,\n                            fail\n                        );\n                    } else {\n                        success();\n                    }\n                },\n                fail\n            );\n        }\n\n        // Repeatedly tries to connect until we succeed or until we've\n        // failed CONNECTION_ATTEMPT times. After each attempt, waits\n        // at least RETRY_DELAY before trying again.\n        function doConnect() {\n            attemptCount++;\n            attemptTimestamp = new Date();\n            attemptSingleConnect().then(\n                registerHandlersAndDomains, // succeded\n                function () { // failed this attempt, possibly try again\n                    if (attemptCount < CONNECTION_ATTEMPTS) { //try again\n                        // Calculate how long we should wait before trying again\n                        var now = new Date();\n                        var delay = Math.max(\n                            RETRY_DELAY - (now - attemptTimestamp),\n                            1\n                        );\n                        setTimeout(doConnect, delay);\n                    } else { // too many attempts, give up\n                        deferred.reject(\"Max connection attempts reached\");\n                    }\n                }\n            );\n        }\n\n        // Start the connection process\n        self._cleanup();\n        doConnect();\n\n        return deferred.promise();\n    };\n\n    /**\n     * Determines whether the NodeConnection is currently connected\n     * @return {boolean} Whether the NodeConnection is connected.\n     */\n    NodeConnection.prototype.connected = function () {\n        return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n    };\n\n    /**\n     * Explicitly disconnects from the server. Note that even if\n     * autoReconnect was set to true at connection time, the connection\n     * will not reconnect after this call. Reconnection can be manually done\n     * by calling connect() again.\n     */\n    NodeConnection.prototype.disconnect = function () {\n        this._autoReconnect = false;\n        this._cleanup();\n    };\n\n    /**\n     * Load domains into the server by path\n     * @param {Array.<string>} List of absolute paths to load\n     * @param {boolean} autoReload Whether to auto-reload the domains if the server\n     *    fails and restarts. Note that the reload is initiated by the\n     *    client, so it will only happen after the client reconnects.\n     * @return {jQuery.Promise} Promise that resolves after the load has\n     *    succeeded and the new API is availale at NodeConnection.domains,\n     *    or that rejects on failure.\n     */\n    NodeConnection.prototype.loadDomains = function (paths, autoReload) {\n        var deferred = $.Deferred();\n        setDeferredTimeout(deferred, CONNECTION_TIMEOUT);\n        var pathArray = paths;\n        if (!Array.isArray(paths)) {\n            pathArray = [paths];\n        }\n\n        if (autoReload) {\n            Array.prototype.push.apply(this._registeredModules, pathArray);\n        }\n\n        if (this.domains.base && this.domains.base.loadDomainModulesFromPaths) {\n            this.domains.base.loadDomainModulesFromPaths(pathArray).then(\n                function (success) { // command call succeeded\n                    if (!success) {\n                        // response from commmand call was \"false\" so we know\n                        // the actual load failed.\n                        deferred.reject(\"loadDomainModulesFromPaths failed\");\n                    }\n                    // if the load succeeded, we wait for the API refresh to\n                    // resolve the deferred.\n                },\n                function (reason) { // command call failed\n                    deferred.reject(\"Unable to load one of the modules: \" + pathArray + (reason ? \", reason: \" + reason : \"\"));\n                }\n            );\n\n            this._pendingInterfaceRefreshDeferreds.push(deferred);\n        } else {\n            deferred.reject(\"this.domains.base is undefined\");\n        }\n\n        return deferred.promise();\n    };\n\n    /**\n     * @private\n     * Sends a message over the WebSocket. Automatically JSON.stringifys\n     * the message if necessary.\n     * @param {Object|string} m Object to send. Must be JSON.stringify-able.\n     */\n    NodeConnection.prototype._send = function (m) {\n        if (this.connected()) {\n\n            // Convert the message to a string\n            var messageString = null;\n            if (typeof m === \"string\") {\n                messageString = m;\n            } else {\n                try {\n                    messageString = JSON.stringify(m);\n                } catch (stringifyError) {\n                    console.error(\"[NodeConnection] Unable to stringify message in order to send: \" + stringifyError.message);\n                }\n            }\n\n            // If we succeded in making a string, try to send it\n            if (messageString) {\n                try {\n                    this._ws.send(messageString);\n                } catch (sendError) {\n                    console.error(\"[NodeConnection] Error sending message: \" + sendError.message);\n                }\n            }\n        } else {\n            console.error(\"[NodeConnection] Not connected to node, unable to send.\");\n        }\n    };\n\n    /**\n     * @private\n     * Handler for receiving events on the WebSocket. Parses the message\n     * and dispatches it appropriately.\n     * @param {WebSocket.Message} message Message object from WebSocket\n     */\n    NodeConnection.prototype._receive = function (message) {\n        var responseDeferred = null;\n        var data = message.data;\n        var m;\n\n        if (message.data instanceof ArrayBuffer) {\n            // The first four bytes encode the command ID as an unsigned 32-bit integer\n            if (data.byteLength < 4) {\n                console.error(\"[NodeConnection] received malformed binary message\");\n                return;\n            }\n\n            var header = data.slice(0, 4),\n                body = data.slice(4),\n                headerView = new Uint32Array(header),\n                id = headerView[0];\n\n            // Unpack the binary message into a commandResponse\n            m = {\n                type: \"commandResponse\",\n                message: {\n                    id: id,\n                    response: body\n                }\n            };\n        } else {\n            try {\n                m = JSON.parse(data);\n            } catch (e) {\n                console.error(\"[NodeConnection] received malformed message\", message, e.message);\n                return;\n            }\n        }\n\n        switch (m.type) {\n        case \"event\":\n            if (m.message.domain === \"base\" && m.message.event === \"newDomains\") {\n                this._refreshInterface();\n            }\n\n            // Event type \"domain:event\"\n            EventDispatcher.triggerWithArray(this, m.message.domain + \":\" + m.message.event,\n                                             m.message.parameters);\n            break;\n        case \"commandResponse\":\n            responseDeferred = this._pendingCommandDeferreds[m.message.id];\n            if (responseDeferred) {\n                responseDeferred.resolveWith(this, [m.message.response]);\n                delete this._pendingCommandDeferreds[m.message.id];\n            }\n            break;\n        case \"commandProgress\":\n            responseDeferred = this._pendingCommandDeferreds[m.message.id];\n            if (responseDeferred) {\n                responseDeferred.notifyWith(this, [m.message.message]);\n            }\n            break;\n        case \"commandError\":\n            responseDeferred = this._pendingCommandDeferreds[m.message.id];\n            if (responseDeferred) {\n                responseDeferred.rejectWith(\n                    this,\n                    [m.message.message, m.message.stack]\n                );\n                delete this._pendingCommandDeferreds[m.message.id];\n            }\n            break;\n        case \"error\":\n            console.error(\"[NodeConnection] received error: \" +\n                            m.message.message);\n            break;\n        default:\n            console.error(\"[NodeConnection] unknown event type: \" + m.type);\n        }\n    };\n\n    /**\n     * @private\n     * Helper function for refreshing the interface in the \"domain\" property.\n     * Automatically called when the connection receives a base:newDomains\n     * event from the server, and also called at connection time.\n     */\n    NodeConnection.prototype._refreshInterface = function () {\n        var deferred = $.Deferred();\n        var self = this;\n\n        var pendingDeferreds = this._pendingInterfaceRefreshDeferreds;\n        this._pendingInterfaceRefreshDeferreds = [];\n        deferred.then(\n            function () {\n                pendingDeferreds.forEach(function (d) { d.resolve(); });\n            },\n            function (err) {\n                pendingDeferreds.forEach(function (d) { d.reject(err); });\n            }\n        );\n\n        function refreshInterfaceCallback(spec) {\n            function makeCommandFunction(domainName, commandSpec) {\n                return function () {\n                    var deferred = $.Deferred();\n                    var parameters = Array.prototype.slice.call(arguments, 0);\n                    var id = self._getNextCommandID();\n                    self._pendingCommandDeferreds[id] = deferred;\n                    self._send({id: id,\n                               domain: domainName,\n                               command: commandSpec.name,\n                               parameters: parameters\n                               });\n                    return deferred;\n                };\n            }\n\n            // TODO: Don't replace the domain object every time. Instead, merge.\n            self.domains = {};\n            self.domainEvents = {};\n            spec.forEach(function (domainSpec) {\n                self.domains[domainSpec.domain] = {};\n                domainSpec.commands.forEach(function (commandSpec) {\n                    self.domains[domainSpec.domain][commandSpec.name] =\n                        makeCommandFunction(domainSpec.domain, commandSpec);\n                });\n                self.domainEvents[domainSpec.domain] = {};\n                domainSpec.events.forEach(function (eventSpec) {\n                    var parameters = eventSpec.parameters;\n                    self.domainEvents[domainSpec.domain][eventSpec.name] = parameters;\n                });\n            });\n            deferred.resolve();\n        }\n\n        if (this.connected()) {\n            $.getJSON(\"http://localhost:\" + this._port + \"/api\")\n                .done(refreshInterfaceCallback)\n                .fail(function (err) { deferred.reject(err); });\n        } else {\n            deferred.reject(\"Attempted to call _refreshInterface when not connected.\");\n        }\n\n        return deferred.promise();\n    };\n\n    /**\n     * @private\n     * Get the default timeout value\n     * @return {number} Timeout value in milliseconds\n     */\n    NodeConnection._getConnectionTimeout = function () {\n        return CONNECTION_TIMEOUT;\n    };\n\n    module.exports = NodeConnection;\n\n});\n"
  },
  {
    "path": "src/utils/NodeDomain.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var NodeConnection = require(\"utils/NodeConnection\"),\n        EventDispatcher = require(\"utils/EventDispatcher\");\n\n    // Used to remove all listeners at once when the connection drops\n    var EVENT_NAMESPACE = \".NodeDomainEvent\";\n\n    /**\n     * Provides a simple abstraction for executing the commands of a single\n     * domain loaded via a NodeConnection. Automatically handles connection\n     * management and domain loading, and exposes each command in the domain as\n     * a promise-returning method that can safely be called regardless of the\n     * current status of the underlying connection. Example usage:\n     *\n     *     var myDomain = new NodeDomain(\"someDomain\", \"/path/to/SomeDomainDef.js\"),\n     *         $result = myDomain.exec(\"someCommand\", arg1, arg2);\n     *\n     *     $result.done(function (value) {\n     *         // the command succeeded!\n     *     });\n     *\n     *     $result.fail(function (err) {\n     *         // the command failed; act accordingly!\n     *     });\n     *\n     * To handle domain events, just listen for the event on the domain:\n     *\n     *     myDomain.on(\"someEvent\", someHandler);\n     *\n     * @constructor\n     * @param {string} domainName Name of the registered Node Domain\n     * @param {string} domainPath Full path of the JavaScript Node domain specification\n     */\n    function NodeDomain(domainName, domainPath) {\n        var connection = new NodeConnection();\n\n        this.connection = connection;\n        this._domainName = domainName;\n        this._domainPath = domainPath;\n        this._domainLoaded = false;\n        this._load = this._load.bind(this);\n        this._connectionPromise = connection.connect(true)\n            .then(this._load);\n\n        connection.on(\"close\", function (event, promise) {\n            this.connection.off(EVENT_NAMESPACE);\n            this._domainLoaded = false;\n            this._connectionPromise = promise.then(this._load);\n        }.bind(this));\n    }\n    EventDispatcher.makeEventDispatcher(NodeDomain.prototype);\n\n    /**\n     * The underlying Node connection object for this domain.\n     *\n     * @type {NodeConnection}\n     */\n    NodeDomain.prototype.connection = null;\n\n    /**\n     * A promise that is resolved once the NodeConnection is connected and the\n     * domain has been loaded.\n     *\n     * @type {?jQuery.Promise}\n     * @private\n     */\n    NodeDomain.prototype._connectionPromise = null;\n\n    /**\n     * The name of this domain.\n     *\n     * @type {string}\n     * @private\n     */\n    NodeDomain.prototype._domainName = null;\n\n    /**\n     * The path at which the Node definition of this domain resides.\n     *\n     * @type {string}\n     * @private\n     */\n    NodeDomain.prototype._domainPath = null;\n\n    /**\n     * Whether or not the domain has been successfully loaded.\n     *\n     * @type {boolean}\n     * @private\n     */\n    NodeDomain.prototype._domainLoaded = false;\n\n    /**\n     * Loads the domain via the underlying connection object and exposes the\n     * domain's commands as methods on this object. Assumes the underlying\n     * connection has already been opened.\n     *\n     * @return {jQuery.Promise} Resolves once the domain is been loaded.\n     * @private\n     */\n    NodeDomain.prototype._load = function () {\n        var connection = this.connection;\n        return connection.loadDomains(this._domainPath, true)\n            .done(function () {\n                this._domainLoaded = true;\n                this._connectionPromise = null;\n\n                var eventNames = Object.keys(connection.domainEvents[this._domainName]);\n                eventNames.forEach(function (domainEvent) {\n                    var connectionEvent = this._domainName + \":\" + domainEvent + EVENT_NAMESPACE;\n\n                    connection.on(connectionEvent, function () {\n                        var params = Array.prototype.slice.call(arguments, 1);\n                        EventDispatcher.triggerWithArray(this, domainEvent, params);\n                    }.bind(this));\n                }, this);\n            }.bind(this))\n            .fail(function (err) {\n                console.error(\"[NodeDomain] Error loading domain \\\"\" + this._domainName + \"\\\": \" + err);\n            }.bind(this));\n    };\n\n    /**\n     * Synchronously determine whether the domain is ready; i.e., whether the\n     * connection is open and the domain is loaded.\n     *\n     * @return {boolean} Whether or not the domain is currently ready.\n     */\n    NodeDomain.prototype.ready = function () {\n        return this._domainLoaded && this.connection.connected();\n    };\n\n    /**\n     * Get a promise that resolves when the connection is open and the domain\n     * is loaded.\n     *\n     * @return {jQuery.Promise}\n     */\n    NodeDomain.prototype.promise = function () {\n        if (this._connectionPromise) {\n            return this._connectionPromise;\n        } else {\n            var deferred = new $.Deferred();\n\n            if (this.ready()) {\n                deferred.resolve();\n            } else {\n                deferred.reject();\n            }\n\n            return deferred.promise();\n        }\n    };\n\n    /**\n     * Applies the named command from the domain to a list of parameters, which\n     * are passed as extra arguments to this method. If the connection is open\n     * and the domain is loaded, the function is applied immediately. Otherwise\n     * the function is applied as soon as the connection has been opened and the\n     * domain has finished loading.\n     *\n     * @param {string} name The name of the domain command to execute\n     * @return {jQuery.Promise} Resolves with the result of the command\n     */\n    NodeDomain.prototype.exec = function (name) {\n        var connection = this.connection,\n            params = Array.prototype.slice.call(arguments, 1),\n            execConnected = function () {\n                var domain  = connection.domains[this._domainName],\n                    fn      = domain && domain[name],\n                    execResult;\n\n                if (fn) {\n                    execResult = fn.apply(domain, params);\n                } else {\n                    execResult = new $.Deferred().reject().promise();\n                }\n                return execResult;\n            }.bind(this);\n\n        var result;\n        if (this.ready()) {\n            result = execConnected();\n        } else if (this._connectionPromise) {\n            result = this._connectionPromise.then(execConnected);\n        } else {\n            result = new $.Deferred.reject().promise();\n        }\n        return result;\n    };\n\n    module.exports = NodeDomain;\n});\n"
  },
  {
    "path": "src/utils/PerfUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * This is a collection of utility functions for gathering performance data.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _            = require(\"thirdparty/lodash\"),\n        StringUtils  = require(\"utils/StringUtils\");\n\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    /**\n     * Flag to enable/disable performance data gathering. Default is true (enabled)\n     * @type {boolean} enabled\n     */\n    var enabled = brackets && !!brackets.app.getElapsedMilliseconds;\n\n    /**\n     * Performance data is stored in this hash object. The key is the name of the\n     * test (passed to markStart/addMeasurement), and the value is the time, in\n     * milliseconds, that it took to run the test. If multiple runs of the same test\n     * are made, the value is an Array with each run stored as an entry in the Array.\n     */\n    var perfData = {};\n\n    /**\n     * Active tests. This is a hash of all tests that have had markStart() called,\n     * but have not yet had addMeasurement() called.\n     */\n    var activeTests = {};\n\n    /**\n     * Updatable tests. This is a hash of all tests that have had markStart() called,\n     * and have had updateMeasurement() called. Caller must explicitly remove tests\n     * from this list using finalizeMeasurement()\n     */\n    var updatableTests = {};\n\n    /**\n     * @private\n     * Keeps the track of measurements sequence number for re-entrant sequences with\n     * the same name currently running. Entries are created and deleted as needed.\n     */\n    var _reentTests = {};\n\n    /**\n     * @private\n     * A unique key to log performance data\n     *\n     * @param {(string|undefined)} id Unique ID for this measurement name\n     * @param {!string} name A short name for this measurement\n     * @param {?number} reent Sequence identifier for parallel tests of the same name\n     */\n    function PerfMeasurement(id, name, reent) {\n        this.name = name;\n        this.reent = reent;\n        if (id) {\n            this.id = id;\n        } else {\n            this.id = (reent) ? \"[reent \" + this.reent + \"] \" + name : name;\n        }\n    }\n\n    /**\n     * Override toString() to allow using PerfMeasurement as an array key without\n     * explicit conversion.\n     */\n    PerfMeasurement.prototype.toString = function () {\n        return this.name;\n    };\n\n    /**\n     * Create a new PerfMeasurement key. Adds itself to the module export.\n     * Can be accessed on the module, e.g. PerfUtils.MY_PERF_KEY.\n     *\n     * @param {!string} id Unique ID for this measurement name\n     * @param {!name} name A short name for this measurement\n     */\n    function createPerfMeasurement(id, name) {\n        var pm = new PerfMeasurement(id, name);\n        exports[id] = pm;\n\n        return pm;\n    }\n\n    /**\n     * @private\n     * Generates PerfMeasurements based on the name or array of names.\n     */\n    function _generatePerfMeasurements(name) {\n        // always convert it to array so that the rest of the routines could rely on it\n        var id = (!Array.isArray(name)) ? [name] : name;\n        // generate unique identifiers for each name\n        var i;\n        for (i = 0; i < id.length; i++) {\n            if (!(id[i] instanceof PerfMeasurement)) {\n                if (_reentTests[id[i]] === undefined) {\n                    _reentTests[id[i]] = 0;\n                } else {\n                    _reentTests[id[i]]++;\n                }\n                id[i] = new PerfMeasurement(undefined, id[i], _reentTests[id[i]]);\n            }\n        }\n        return id;\n    }\n\n    /**\n     * @private\n     * Helper function for markStart()\n     *\n     * @param {Object} id  Timer id.\n     * @param {number} time  Timer start time.\n     */\n    function _markStart(id, time) {\n        if (activeTests[id.id]) {\n            console.error(\"Recursive tests with the same id are not supported. Timer id: \" + id.id);\n        }\n\n        activeTests[id.id] = { startTime: time };\n    }\n\n    /**\n     * Start a new named timer. The name should be as descriptive as possible, since\n     * this name will appear as an entry in the performance report.\n     * For example: \"Open file: /Users/brackets/src/ProjectManager.js\"\n     *\n     * Multiple timers can be opened simultaneously.\n     *\n     * Returns an opaque set of timer ids which can be stored and used for calling\n     * addMeasurement(). Since name is often creating via concatenating strings this\n     * return value allows clients to construct the name once.\n     *\n     * @param {(string|Array.<string>)} name  Single name or an Array of names.\n     * @return {(Object|Array.<Object>)} Opaque timer id or array of timer ids.\n     */\n    function markStart(name) {\n        if (!enabled) {\n            return;\n        }\n\n        var time = brackets.app.getElapsedMilliseconds();\n        var id = _generatePerfMeasurements(name);\n        var i;\n\n        for (i = 0; i < id.length; i++) {\n            _markStart(id[i], time);\n        }\n        return id.length > 1 ? id : id[0];\n    }\n\n    /**\n     * Stop a timer and add its measurements to the performance data.\n     *\n     * Multiple measurements can be stored for any given name. If there are\n     * multiple values for a name, they are stored in an Array.\n     *\n     * If markStart() was not called for the specified timer, the\n     * measured time is relative to app startup.\n     *\n     * @param {Object} id  Timer id.\n     */\n    function addMeasurement(id) {\n        if (!enabled) {\n            return;\n        }\n\n        if (!(id instanceof PerfMeasurement)) {\n            id = new PerfMeasurement(id, id);\n        }\n\n        var elapsedTime = brackets.app.getElapsedMilliseconds();\n\n        if (activeTests[id.id]) {\n            elapsedTime -= activeTests[id.id].startTime;\n            delete activeTests[id.id];\n        }\n\n        if (perfData[id]) {\n            // We have existing data, add to it\n            if (Array.isArray(perfData[id])) {\n                perfData[id].push(elapsedTime);\n            } else {\n                // Current data is a number, convert to Array\n                perfData[id] = [perfData[id], elapsedTime];\n            }\n        } else {\n            perfData[id] = elapsedTime;\n        }\n\n        if (id.reent !== undefined) {\n            if (_reentTests[id] === 0) {\n                delete _reentTests[id];\n            } else {\n                _reentTests[id]--;\n            }\n        }\n\n    }\n\n    /**\n     * This function is similar to addMeasurement(), but it allows timing the\n     * *last* event, when you don't know which event will be the last one.\n     *\n     * Tests that are in the activeTests list, have not yet been added, so add\n     * measurements to the performance data, and move test to updatableTests list.\n     * A test is moved to the updatable list so that it no longer passes isActive().\n     *\n     * Tests that are already in the updatableTests list are updated.\n     *\n     * Caller must explicitly remove test from the updatableTests list using\n     * finalizeMeasurement().\n     *\n     * If markStart() was not called for the specified timer, there is no way to\n     * determine if this is the first or subsequent call, so the measurement is\n     * not updatable, and it is handled in addMeasurement().\n     *\n     * @param {Object} id  Timer id.\n     */\n    function updateMeasurement(id) {\n        var elapsedTime = brackets.app.getElapsedMilliseconds();\n\n        if (updatableTests[id.id]) {\n            // update existing measurement\n            elapsedTime -= updatableTests[id].startTime;\n\n            // update\n            if (perfData[id] && Array.isArray(perfData[id])) {\n                // We have existing data and it's an array, so update the last entry\n                perfData[id][perfData[id].length - 1] = elapsedTime;\n            } else {\n                // No current data or a single entry, so set/update it\n                perfData[id] = elapsedTime;\n            }\n\n        } else {\n            // not yet in updatable list\n\n            if (activeTests[id.id]) {\n                // save startTime in updatable list before addMeasurement() deletes it\n                updatableTests[id.id] = { startTime: activeTests[id.id].startTime };\n            }\n\n            // let addMeasurement() handle the initial case\n            addMeasurement(id);\n        }\n    }\n\n    /**\n     * Remove timer from lists so next action starts a new measurement\n     *\n     * updateMeasurement may not have been called, so timer may be\n     * in either or neither list, but should never be in both.\n     *\n     * @param {Object} id  Timer id.\n     */\n    function finalizeMeasurement(id) {\n        if (activeTests[id.id]) {\n            delete activeTests[id.id];\n        }\n\n        if (updatableTests[id.id]) {\n            delete updatableTests[id.id];\n        }\n    }\n\n    /**\n     * Returns whether a timer is active or not, where \"active\" means that\n     * timer has been started with addMark(), but has not been added to perfdata\n     * with addMeasurement().\n     *\n     * @param {Object} id  Timer id.\n     * @return {boolean} Whether a timer is active or not.\n     */\n    function isActive(id) {\n        return (activeTests[id.id]) ? true : false;\n    }\n\n    /**\n     * return single value, or comma separated values for an array or return aggregated values with\n     * <min value, average, max value, standard deviation>\n     * @param   {Array}    entry          An array or a single value\n     * @param   {Boolean} aggregateStats If set, the returned value will be aggregated in the form -\n     *                                   <min(avg)max[standard deviation]>\n     * @return {String}   a single value, or comma separated values in an array or\n     *                     <min(avg)max[standard deviation]> if aggregateStats is set\n     */\n    function getValueAsString(entry, aggregateStats) {\n        if (!Array.isArray(entry)) {\n            return entry;\n        }\n\n        if (aggregateStats) {\n            var sum = 0,\n                avg,\n                min = _.min(entry),\n                max = _.max(entry),\n                sd,\n                variationSum = 0;\n\n            entry.forEach(function (value) {\n                sum += value;\n            });\n            avg = Math.round(sum / entry.length);\n            entry.forEach(function (value) {\n                variationSum += Math.pow(value - avg, 2);\n            });\n            sd = Math.round(Math.sqrt(variationSum / entry.length));\n            return min + \"(\" + avg + \")\" + max + \"[\" + sd + \"]\";\n        } else {\n            return entry.join(\", \");\n        }\n    }\n\n    /**\n     * Returns the performance data as a tab delimited string\n     * @return {string}\n     */\n    function getDelimitedPerfData() {\n        var result = \"\";\n        _.forEach(perfData, function (entry, testName) {\n            result += getValueAsString(entry) + \"\\t\" + testName + \"\\n\";\n        });\n\n        return result;\n    }\n\n    /**\n     * Returns the measured value for the given measurement name.\n     * @param {Object} id The measurement to retreive.\n     */\n    function getData(id) {\n        if (!id) {\n            return perfData;\n        }\n\n        return perfData[id];\n    }\n\n    /**\n     * Returns the Performance metrics to be logged for health report\n     * @return {Object} An object with the health data logs to be sent\n     */\n    function getHealthReport() {\n        var healthReport = {\n            projectLoadTimes : \"\",\n            fileOpenTimes : \"\"\n        };\n\n        _.forEach(perfData, function (entry, testName) {\n            if (StringUtils.startsWith(testName, \"Application Startup\")) {\n                healthReport.AppStartupTime = getValueAsString(entry);\n            } else if (StringUtils.startsWith(testName, \"brackets module dependencies resolved\")) {\n                healthReport.ModuleDepsResolved = getValueAsString(entry);\n            } else if (StringUtils.startsWith(testName, \"Load Project\")) {\n                healthReport.projectLoadTimes += \":\" + getValueAsString(entry, true);\n            } else if (StringUtils.startsWith(testName, \"Open File\")) {\n                healthReport.fileOpenTimes += \":\" + getValueAsString(entry, true);\n            }\n        });\n\n        return healthReport;\n    }\n\n    function searchData(regExp) {\n        var keys = Object.keys(perfData).filter(function (key) {\n            return regExp.test(key);\n        });\n\n        var datas = [];\n\n        keys.forEach(function (key) {\n            datas.push(perfData[key]);\n        });\n\n        return datas;\n    }\n\n    /**\n     * Clear all logs including metric data and active tests.\n     */\n    function clear() {\n        perfData = {};\n        activeTests = {};\n        updatableTests = {};\n        _reentTests = {};\n    }\n\n    // create performance measurement constants\n    createPerfMeasurement(\"INLINE_WIDGET_OPEN\", \"Open inline editor or docs\");\n    createPerfMeasurement(\"INLINE_WIDGET_CLOSE\", \"Close inline editor or docs\");\n\n    // extensions may create additional measurement constants during their lifecycle\n\n    exports.addMeasurement          = addMeasurement;\n    exports.finalizeMeasurement     = finalizeMeasurement;\n    exports.isActive                = isActive;\n    exports.markStart               = markStart;\n    exports.getData                 = getData;\n    exports.searchData              = searchData;\n    exports.updateMeasurement       = updateMeasurement;\n    exports.getDelimitedPerfData    = getDelimitedPerfData;\n    exports.createPerfMeasurement   = createPerfMeasurement;\n    exports.clear                   = clear;\n    exports.getHealthReport         = getHealthReport;\n});\n"
  },
  {
    "path": "src/utils/Resizer.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Resizer is a Module utility to inject resizing capabilities to any element\n * inside Brackets.\n *\n * On initialization, Resizer discovers all nodes tagged as \"vert-resizable\"\n * and \"horz-resizable\" to add the resizer handler. Additionally, \"top-resizer\",\n * \"bottom-resizer\", \"left-resizer\" and \"right-resizer\" classes control the\n * position of the resizer on the element.\n *\n * An element can be made resizable at any time using the `makeResizable()` API.\n * Panel sizes are saved via preferences and restored when the DOM node becomes resizable\n * again in a subsequent launch.\n *\n * The resizable elements trigger a panelResizeStart, panelResizeUpdate and panelResizeEnd\n * event that can be used to create performance optimizations (such as hiding/showing elements\n * while resizing), custom layout logic, etc. See makeResizable() for details on the events.\n *\n * A resizable element can be collapsed/expanded using the `show`, `hide` and `toggle` APIs or\n * via user action. This triggers panelCollapsed/panelExpanded events - see makeResizable().\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var DIRECTION_VERTICAL = \"vert\";\n    var DIRECTION_HORIZONTAL = \"horz\";\n\n    var POSITION_TOP = \"top\";\n    var POSITION_BOTTOM = \"bottom\";\n    var POSITION_LEFT = \"left\";\n    var POSITION_RIGHT = \"right\";\n    var PREFS_PURE_CODE = \"noDistractions\";\n\n    // Minimum size (height or width) for autodiscovered resizable panels\n    var DEFAULT_MIN_SIZE = 100;\n\n    // Load dependent modules\n    var AppInit                 = require(\"utils/AppInit\"),\n        EventDispatcher         = require(\"utils/EventDispatcher\"),\n        ViewUtils               = require(\"utils/ViewUtils\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\");\n\n    var $mainView,\n        $sideBar;\n\n    var isResizing = false,\n        isWindowResizing = false;\n\n    /**\n     * Shows a resizable element.\n     * @param {DOMNode} element Html element to show if possible\n     */\n    function show(element) {\n        var showFunc = $(element).data(\"show\");\n        if (showFunc) {\n            showFunc.apply(element);\n        }\n    }\n\n    /**\n     * Hides a resizable element.\n     * @param {DOMNode} element Html element to hide if possible\n     */\n    function hide(element) {\n        var hideFunc = $(element).data(\"hide\");\n        if (hideFunc) {\n            hideFunc.apply(element);\n        }\n    }\n\n    /**\n     * Changes the visibility state of a resizable element. The toggle\n     * functionality is added when an element is made resizable.\n     * @param {DOMNode} element Html element to toggle\n     */\n    function toggle(element) {\n        if ($(element).is(\":visible\")) {\n            hide(element);\n        } else {\n            show(element);\n        }\n    }\n\n    /**\n     * Removes the resizability of an element if it's resizable\n     * @param {DOMNode} element Html element in which to remove sizing\n     */\n    function removeSizable(element) {\n        var removeSizableFunc = $(element).data(\"removeSizable\");\n        if (removeSizableFunc) {\n            removeSizableFunc.apply(element);\n        }\n    }\n\n    /**\n     * Updates the sizing div by resyncing to the sizing edge of the element\n     * Call this method after manually changing the size of the element\n     * @param {DOMNode} element Html element whose sizer should be resynchronized\n     */\n    function resyncSizer(element) {\n        var resyncSizerFunc = $(element).data(\"resyncSizer\");\n        if (resyncSizerFunc) {\n            resyncSizerFunc.apply(element);\n        }\n    }\n\n    /**\n     * Returns the visibility state of a resizable element.\n     * @param {DOMNode} element Html element to toggle\n     * @return {boolean} true if element is visible, false if it is not visible\n     */\n    function isVisible(element) {\n        return $(element).is(\":visible\");\n    }\n\n    function _isPercentage(value) {\n        return !$.isNumeric(value) && value.indexOf('%') > -1;\n    }\n\n    function _percentageToPixels(value, total) {\n        return parseFloat(value.replace('%', '')) * (total / 100);\n    }\n\n    function _sideBarMaxSize() {\n        var siblingsWidth = 0;\n        $sideBar.siblings().not(\".content\").each(function (i, elem) {\n            var $elem = $(elem);\n            if ($elem.css(\"display\") !== \"none\") {\n                siblingsWidth += $elem.outerWidth();\n            }\n        });\n        return $(\".main-view\").width() - siblingsWidth - 1;\n    }\n\n    /**\n     * Adds resizing and (optionally) expand/collapse capabilities to a given html element. The element's size\n     * & visibility are automatically saved & restored as a view-state preference.\n     *\n     * Resizing can be configured in two directions:\n     *  - Vertical (\"vert\"): Resizes the height of the element\n     *  - Horizontal (\"horz\"): Resizes the width of the element\n     *\n     * Resizer handlers can be positioned on the element at:\n     *  - Top (\"top\") or bottom (\"bottom\") for vertical resizing\n     *  - Left (\"left\") or right (\"right\") for horizontal resizing\n     *\n     * A resizable element triggers the following events while resizing:\n     *  - panelResizeStart: When the resize starts. Passed the new size.\n     *  - panelResizeUpdate: When the resize gets updated. Passed the new size.\n     *  - panelResizeEnd: When the resize ends. Passed the final size.\n     *  - panelCollapsed: When the panel gets collapsed (or hidden). Passed the last size\n     *      before collapse. May occur without any resize events.\n     *  - panelExpanded: When the panel gets expanded (or shown). Passed the initial size.\n     *      May occur without any resize events.\n     *\n     * @param {!DOMNode} element DOM element which should be made resizable. Must have an id attribute, for\n     *                          use as a preferences key.\n     * @param {!string} direction Direction of the resize action: one of the DIRECTION_* constants.\n     * @param {!string} position Which side of the element can be dragged: one of the POSITION_* constants\n     *                          (TOP/BOTTOM for vertical resizing or LEFT/RIGHT for horizontal).\n     * @param {?number} minSize Minimum size (width or height) of the element's outer dimensions, including\n     *                          border & padding. Defaults to DEFAULT_MIN_SIZE.\n     * @param {?boolean} collapsible Indicates the panel is collapsible on double click on the\n     *                          resizer. Defaults to false.\n     * @param {?string} forceLeft CSS selector indicating element whose 'left' should be locked to the\n     *                          the resizable element's size (useful for siblings laid out to the right of\n     *                          the element). Must lie in element's parent's subtree.\n     * @param {?boolean} createdByWorkspaceManager For internal use only\n     * @param {?boolean} usePercentages Maintain the size of the element as a percentage of its parent\n     *                          the default is to maintain the size of the element in pixels\n     * @param {?boolean} _attachToParent Attaches the resizer element to parent of the element rather than\n     *                          to element itself. Attach the resizer to the parent *ONLY* if element has the\n     *                          same offset as parent otherwise the resizer will be incorrectly positioned.\n     *                          FOR INTERNAL USE ONLY\n     */\n    function makeResizable(element, direction, position, minSize, collapsible, forceLeft, createdByWorkspaceManager, usePercentages, _attachToParent) {\n        var $resizer            = $('<div class=\"' + direction + '-resizer\"></div>'),\n            $element            = $(element),\n            $parent             = $element.parent(),\n            $resizableElement   = $($element.find(\".resizable-content:first\")[0]),\n            $body               = $(window.document.body),\n            elementID           = $element.attr(\"id\"),\n            elementPrefs        = PreferencesManager.getViewState(elementID) || {},\n            animationRequest    = null,\n            directionProperty   = direction === DIRECTION_HORIZONTAL ? \"clientX\" : \"clientY\",\n            directionIncrement  = (position === POSITION_TOP || position === POSITION_LEFT) ? 1 : -1,\n            parentSizeFunction  = direction === DIRECTION_HORIZONTAL ? $parent.innerWidth : $parent.innerHeight,\n\n            elementSizeFunction = function (newSize) {\n                if (!newSize) {\n                    // calling the function as a getter\n                    if (direction === DIRECTION_HORIZONTAL) {\n                        return this.width();\n                    } else {\n                        return this.height();\n                    }\n                } else if (!usePercentages) {\n                    if (direction === DIRECTION_HORIZONTAL) {\n                        return this.width(newSize);\n                    } else {\n                        return this.height(newSize);\n                    }\n                } else {\n                    // calling the function as a setter\n                    var parentSize = parentSizeFunction.apply($parent),\n                        percentage,\n                        prop;\n\n                    if (direction === DIRECTION_HORIZONTAL) {\n                        prop = \"width\";\n                    } else {\n                        prop = \"height\";\n                    }\n                    percentage = newSize / parentSize;\n                    this.css(prop, (percentage * 100) + \"%\");\n\n                    return this; // chainable\n                }\n            },\n\n            resizerCSSPosition  = direction === DIRECTION_HORIZONTAL ? \"left\" : \"top\",\n            contentSizeFunction = direction === DIRECTION_HORIZONTAL ? $resizableElement.width : $resizableElement.height;\n\n        if (PreferencesManager.get(PREFS_PURE_CODE) &&\n                ($element.hasClass(\"bottom-panel\") || $element.hasClass(\"sidebar\"))) {\n            elementPrefs.visible = false;\n        }\n\n        if (!elementID) {\n            console.error(\"Resizable panels must have a DOM id to use as a preferences key:\", element);\n            return;\n        }\n        // Detect legacy cases where panels in the editor area are created without using WorkspaceManager APIs\n        if ($parent[0] && $parent.is(\".content\") && !createdByWorkspaceManager) {\n            console.error(\"Resizable panels within the editor area should be created via WorkspaceManager.createBottomPanel(). \\nElement:\", element);\n            return;\n        }\n\n        if (minSize === undefined) {\n            minSize = DEFAULT_MIN_SIZE;\n        }\n\n        collapsible = collapsible || false;\n\n        if (_attachToParent) {\n            $parent.prepend($resizer);\n        } else {\n            $element.prepend($resizer);\n        }\n        // Important so min/max sizes behave predictably\n        $element.css(\"box-sizing\", \"border-box\");\n\n        function adjustSibling(size) {\n            if (forceLeft !== undefined) {\n                $(forceLeft, $parent).css(\"left\", size);\n            }\n        }\n\n        function resizeElement(elementSize, contentSize) {\n            elementSizeFunction.apply($element, [elementSize]);\n\n            if ($resizableElement.length) {\n                contentSizeFunction.apply($resizableElement, [contentSize]);\n            }\n        }\n\n        // If the resizer is positioned right or bottom of the panel, we need to listen to\n        // reposition it if the element size changes externally\n        function repositionResizer(elementSize) {\n            var resizerPosition = elementSize || 1;\n            if (position === POSITION_RIGHT || position === POSITION_BOTTOM) {\n                $resizer.css(resizerCSSPosition, resizerPosition);\n            }\n        }\n\n        $element.data(\"removeSizable\", function () {\n            $resizer.off(\".resizer\");\n\n            $element.removeData(\"show\");\n            $element.removeData(\"hide\");\n            $element.removeData(\"resyncSizer\");\n            $element.removeData(\"removeSizable\");\n\n            $resizer.remove();\n        });\n\n        $element.data(\"resyncSizer\", function () {\n            repositionResizer(elementSizeFunction.apply($element));\n        });\n\n        $element.data(\"show\", function () {\n            var elementOffset   = $element.offset(),\n                elementSize     = elementSizeFunction.apply($element) || elementPrefs.size,\n                contentSize     = contentSizeFunction.apply($resizableElement) || elementPrefs.contentSize;\n\n            // Resize the element before showing it again. If the panel was collapsed by dragging\n            // the resizer, the size of the element should be 0, so we restore size in preferences\n            resizeElement(elementSize, contentSize);\n\n            $element.show();\n            elementPrefs.visible = true;\n\n            if (collapsible) {\n                if (_attachToParent) {\n                    $parent.prepend($resizer);\n                } else {\n                    $element.prepend($resizer);\n                }\n                if (position === POSITION_TOP) {\n                    $resizer.css(resizerCSSPosition, \"\");\n                } else if (position === POSITION_RIGHT) {\n                    $resizer.css(resizerCSSPosition, elementOffset[resizerCSSPosition] + elementSize);\n                }\n            }\n\n            adjustSibling(elementSize);\n\n            $element.trigger(\"panelExpanded\", [elementSize]);\n            PreferencesManager.setViewState(elementID, elementPrefs, null, isResizing);\n        });\n\n        $element.data(\"hide\", function () {\n            var elementOffset   = $element.offset(),\n                elementSize     = elementSizeFunction.apply($element),\n                resizerSize     = elementSizeFunction.apply($resizer);\n\n            $element.hide();\n            elementPrefs.visible = false;\n            if (collapsible) {\n                $resizer.insertBefore($element);\n                if (position === POSITION_RIGHT) {\n                    $resizer.css(resizerCSSPosition, \"\");\n                } else if (position === POSITION_TOP) {\n                    $resizer.css(resizerCSSPosition, elementOffset[resizerCSSPosition] + elementSize - resizerSize);\n                }\n            }\n\n            adjustSibling(0);\n\n            $element.trigger(\"panelCollapsed\", [elementSize]);\n            PreferencesManager.setViewState(elementID, elementPrefs, null, isResizing);\n        });\n\n\n        $resizer.on(\"mousedown.resizer\", function (e) {\n            var $resizeShield   = $(\"<div class='resizing-container \" + direction + \"-resizing' />\"),\n                startPosition   = e[directionProperty],\n                startSize       = $element.is(\":visible\") ? elementSizeFunction.apply($element) : 0,\n                newSize         = startSize,\n                previousSize    = startSize,\n                baseSize        = 0,\n                resizeStarted   = false;\n\n            isResizing = true;\n            $body.append($resizeShield);\n\n            if ($resizableElement.length) {\n                $element.children().not(\".horz-resizer, .vert-resizer, .resizable-content\").each(function (index, child) {\n                    if (direction === DIRECTION_HORIZONTAL) {\n                        baseSize += $(child).outerWidth();\n                    } else {\n                        baseSize += $(child).outerHeight();\n                    }\n                });\n            }\n\n            function doRedraw() {\n                // only run this if the mouse is down so we don't constantly loop even\n                // after we're done resizing.\n                if (!isResizing) {\n                    return;\n                }\n\n                // Check for real size changes to avoid unnecessary resizing and events\n                if (newSize !== previousSize) {\n                    previousSize = newSize;\n\n                    if ($element.is(\":visible\")) {\n                        if (newSize < 10) {\n                            toggle($element);\n                            elementSizeFunction.apply($element, [0]);\n                        } else {\n                            // Trigger resizeStarted just before the first successful resize update\n                            if (!resizeStarted) {\n                                resizeStarted = true;\n                                $element.trigger(\"panelResizeStart\", newSize);\n                            }\n\n                            // Resize the main element to the new size. If there is a content element,\n                            // its size is the new size minus the size of the non-resizable elements\n                            resizeElement(newSize, (newSize - baseSize));\n                            adjustSibling(newSize);\n\n                            $element.trigger(\"panelResizeUpdate\", [newSize]);\n                        }\n                    } else if (newSize > 10) {\n                        elementSizeFunction.apply($element, [newSize]);\n                        toggle($element);\n\n                        // Trigger resizeStarted after expanding the element if it was previously collapsed\n                        if (!resizeStarted) {\n                            resizeStarted = true;\n                            $element.trigger(\"panelResizeStart\", newSize);\n                        }\n                    }\n                }\n\n                animationRequest = window.requestAnimationFrame(doRedraw);\n            }\n\n            function onMouseMove(e) {\n                // calculate newSize adding to startSize the difference\n                // between starting and current position, capped at minSize\n                newSize = Math.max(startSize + directionIncrement * (startPosition - e[directionProperty]), minSize);\n\n                // respect max size if one provided (e.g. by WorkspaceManager)\n                var maxSize = $element.data(\"maxsize\");\n                if (maxSize !== undefined) {\n                    // if provided as percentage size convert it to a pixel size\n                    if (_isPercentage(maxSize)) {\n                        maxSize = _percentageToPixels(maxSize, _sideBarMaxSize());\n                    }\n                    newSize = Math.min(newSize, maxSize);\n                }\n\n                e.preventDefault();\n\n                if (animationRequest === null) {\n                    animationRequest = window.requestAnimationFrame(doRedraw);\n                }\n            }\n\n            $(window.document).on(\"mousemove\", onMouseMove);\n\n            // If the element is marked as collapsible, check for double click\n            // to toggle the element visibility\n            if (collapsible) {\n                $resizeShield.on(\"mousedown\", function (e) {\n                    $(window.document).off(\"mousemove\", onMouseMove);\n                    $resizeShield.off(\"mousedown\");\n                    $resizeShield.remove();\n                    animationRequest = null;\n                    toggle($element);\n                });\n            }\n\n            function endResize(e) {\n                if (isResizing) {\n\n                    var elementSize\t= elementSizeFunction.apply($element);\n                    if ($element.is(\":visible\")) {\n                        elementPrefs.size = elementSize;\n                        if ($resizableElement.length) {\n                            elementPrefs.contentSize = contentSizeFunction.apply($resizableElement);\n                        }\n                        PreferencesManager.setViewState(elementID, elementPrefs);\n                        repositionResizer(elementSize);\n                    }\n\n                    isResizing = false;\n\n                    if (resizeStarted) {\n                        $element.trigger(\"panelResizeEnd\", [elementSize]);\n                    }\n\n                    // We wait 300ms to remove the resizer container to capture a mousedown\n                    // on the container that would account for double click\n                    window.setTimeout(function () {\n                        $(window.document).off(\"mousemove\", onMouseMove);\n                        $resizeShield.off(\"mousedown\");\n                        $resizeShield.remove();\n                        animationRequest = null;\n                    }, 300);\n                }\n            }\n\n            $(window.document).one(\"mouseup\", endResize);\n\n            e.preventDefault();\n        });\n\n        // Panel preferences initialization\n        if (elementPrefs) {\n\n            if (elementPrefs.size !== undefined) {\n                elementSizeFunction.apply($element, [elementPrefs.size]);\n            }\n\n            if (elementPrefs.contentSize !== undefined) {\n                contentSizeFunction.apply($resizableElement, [elementPrefs.contentSize]);\n            }\n\n            if (elementPrefs.visible !== undefined && !elementPrefs.visible) {\n                hide($element);\n            } else {\n                adjustSibling(elementSizeFunction.apply($element));\n                repositionResizer(elementSizeFunction.apply($element));\n            }\n        }\n    }\n\n    function updateResizeLimits() {\n        var sideBarMaxSize = _sideBarMaxSize(),\n            maxSize = $sideBar.data(\"maxsize\"),\n            width = false;\n\n        if (maxSize !== undefined && _isPercentage(maxSize)) {\n            sideBarMaxSize = _percentageToPixels(maxSize, sideBarMaxSize);\n        }\n\n        if ($sideBar.width() > sideBarMaxSize) {\n            // Adjust the sideBar's width in case it exceeds the window's width when resizing the window.\n            $sideBar.width(sideBarMaxSize);\n            resyncSizer($sideBar);\n            $(\".content\").css(\"left\", $sideBar.width());\n            $sideBar.trigger(\"panelResizeStart\", $sideBar.width());\n            $sideBar.trigger(\"panelResizeUpdate\", [$sideBar.width()]);\n            $sideBar.trigger(\"panelResizeEnd\", [$sideBar.width()]);\n        }\n    }\n\n    function onWindowResize(e) {\n        if ($sideBar.css(\"display\") === \"none\") {\n            return;\n        }\n\n        if (!isWindowResizing) {\n            isWindowResizing = true;\n\n            // We don't need any fancy debouncing here - we just need to react before the user can start\n            // resizing any panels at the new window size. So just listen for first mousemove once the\n            // window resize releases mouse capture.\n            $(window.document).one(\"mousemove\", function () {\n                isWindowResizing = false;\n                updateResizeLimits();\n            });\n        }\n    }\n\n    window.addEventListener(\"resize\", onWindowResize, true);\n\n    // Scan DOM for horz-resizable and vert-resizable classes and make them resizable\n    AppInit.htmlReady(function () {\n        var minSize = DEFAULT_MIN_SIZE;\n\n        $mainView = $(\".main-view\");\n        $sideBar = $(\"#sidebar\");\n\n        $(\".vert-resizable\").each(function (index, element) {\n\n            if ($(element).data().minsize !== undefined) {\n                minSize = $(element).data().minsize;\n            }\n\n            if ($(element).hasClass(\"top-resizer\")) {\n                makeResizable(element, DIRECTION_VERTICAL, POSITION_TOP, minSize, $(element).hasClass(\"collapsible\"));\n            }\n\n            //if ($(element).hasClass(\"bottom-resizer\")) {\n            //    makeResizable(element, DIRECTION_VERTICAL, POSITION_BOTTOM, DEFAULT_MIN_SIZE);\n            //}\n        });\n\n        $(\".horz-resizable\").each(function (index, element) {\n\n            if ($(element).data().minsize !== undefined) {\n                minSize = $(element).data().minsize;\n            }\n\n            //if ($(element).hasClass(\"left-resizer\")) {\n            //    makeResizable(element, DIRECTION_HORIZONTAL, POSITION_LEFT, DEFAULT_MIN_SIZE);\n            //}\n\n            if ($(element).hasClass(\"right-resizer\")) {\n                makeResizable(element, DIRECTION_HORIZONTAL, POSITION_RIGHT, minSize, $(element).hasClass(\"collapsible\"), $(element).data().forceleft);\n            }\n        });\n\n        // The main toolbar is only collapsible.\n        if ($(\"#main-toolbar\").hasClass(\"collapsible\") && PreferencesManager.get(PREFS_PURE_CODE)) {\n            ViewUtils.hideMainToolBar();\n        }\n    });\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    exports.makeResizable   = makeResizable;\n    exports.removeSizable   = removeSizable;\n    exports.resyncSizer     = resyncSizer;\n    exports.toggle          = toggle;\n    exports.show            = show;\n    exports.hide            = hide;\n    exports.isVisible       = isVisible;\n\n    //Resizer Constants\n    exports.DIRECTION_VERTICAL   = DIRECTION_VERTICAL;\n    exports.DIRECTION_HORIZONTAL = DIRECTION_HORIZONTAL;\n    exports.POSITION_TOP         = POSITION_TOP;\n    exports.POSITION_RIGHT       = POSITION_RIGHT;\n    exports.POSITION_BOTTOM      = POSITION_BOTTOM;\n    exports.POSITION_LEFT        = POSITION_LEFT;\n});\n"
  },
  {
    "path": "src/utils/ShellAPI.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n /**\n  * This is JavaScript API exposed to the native shell when Brackets is run in a native shell rather than a browser.\n  */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var AppInit        = require(\"utils/AppInit\"),\n        CommandManager = require(\"command/CommandManager\"),\n        Commands       = require(\"command/Commands\");\n\n    var appReady = false; // Set to true after app is fully initialized\n\n    /**\n     * The native function BracketsShellAPI::DispatchBracketsJSCommand calls this function in order to enable\n     * calling Brackets commands from the native shell.\n     */\n    function executeCommand(eventName) {\n        // Temporary fix for #2616 - don't execute the command if a modal dialog is open.\n        // This should really be fixed with proper menu enabling.\n        if ($(\".modal.instance\").length || !appReady) {\n            // Another hack to fix issue #3219 so that all test windows are closed\n            // as before the fix for #3152 has been introduced. isBracketsTestWindow\n            // property is explicitly set in createTestWindowAndRun() in SpecRunnerUtils.js.\n            if (window.isBracketsTestWindow) {\n                return false;\n            }\n            // Return false for all commands except file.close_window command for\n            // which we have to return true (issue #3152).\n            return (eventName === Commands.FILE_CLOSE_WINDOW);\n        }\n\n        // Use E for Error so that uglify doesn't change this to simply Error()\n        var promise, E = Error, e = new E(), stackDepth = e.stack.split(\"\\n\").length;\n\n        // This function should *only* be called as a top-level function. If the current\n        // stack depth is > 2, it is most likely because we are at a breakpoint.\n        if (stackDepth < 3) {\n            promise = CommandManager.execute(eventName);\n        } else {\n            console.error(\"Skipping command \" + eventName + \" because it looks like you are \" +\n                          \"at a breakpoint. If you are NOT at a breakpoint, please \" +\n                          \"file a bug and mention this comment. Stack depth = \" + stackDepth + \".\");\n        }\n        return (promise && promise.state() === \"rejected\") ? false : true;\n    }\n\n    AppInit.appReady(function () {\n        appReady = true;\n    });\n\n    exports.executeCommand = executeCommand;\n});\n"
  },
  {
    "path": "src/utils/StringMatch.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*unittests: StringMatch */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    /*\n     * Performs matching that is useful for QuickOpen and similar searches.\n     */\n\n    /** Object representing a search result with associated metadata (added as extra ad hoc fields) */\n    function SearchResult(label) {\n        this.label = label;\n    }\n\n\n\n    /*\n     * Identifies the \"special\" characters in the given string.\n     * Special characters for matching purposes are:\n     *\n     * * the first character\n     * * \"/\" and the character following the \"/\"\n     * * \"_\", \".\" and \"-\" and the character following it\n     * * an uppercase character that follows a lowercase one (think camelCase)\n     *\n     * The returned object contains an array called \"specials\". This array is\n     * a list of indexes into the original string where all of the special\n     * characters are. It also has a property \"lastSegmentSpecialsIndex\" which\n     * is an index into the specials array that denotes which location is the\n     * beginning of the last path segment. (This is used to allow scanning of\n     * the last segment's specials separately.)\n     *\n     * @param {string} input string to break apart (e.g. filename that is being searched)\n     * @return {{specials:Array.<number>, lastSegmentSpecialsIndex:number}}\n     */\n    function findSpecialCharacters(str) {\n        var i, c;\n\n        // the beginning of the string is always special\n        var specials = [0];\n\n        // lastSegmentSpecialsIndex starts off with the assumption that\n        // there are no segments\n        var lastSegmentSpecialsIndex = 0;\n\n        // used to track down the camelCase changeovers\n        var lastWasLowerCase = false;\n\n        for (i = 0; i < str.length; i++) {\n            c = str[i];\n            if (c === \"/\") {\n                // new segment means this character and the next are special\n                specials.push(i++);\n                specials.push(i);\n                lastSegmentSpecialsIndex = specials.length - 1;\n                lastWasLowerCase = false;\n            } else if (c === \".\" || c === \"-\" || c === \"_\") {\n                // _, . and - are separators so they are\n                // special and so is the next character\n                specials.push(i);\n                if (str[i + 1] !== \"/\") {\n                    // if the next key is a slash, handle it separately\n                    // see #10871\n                    specials.push(++i);\n                }\n                lastWasLowerCase = false;\n            } else if (c.toUpperCase() === c) {\n                // this is the check for camelCase changeovers\n                if (lastWasLowerCase) {\n                    specials.push(i);\n                }\n                lastWasLowerCase = false;\n            } else {\n                lastWasLowerCase = true;\n            }\n        }\n        return {\n            specials: specials,\n            lastSegmentSpecialsIndex: lastSegmentSpecialsIndex\n        };\n    }\n\n    // states used during the scanning of the string\n    var SPECIALS_MATCH = 0;\n    var ANY_MATCH = 1;\n\n    // Scores can be hard to make sense of. The DEBUG_SCORES flag\n    // provides a way to peek into the parts that made up a score.\n    // This flag is used for manual debugging and in the unit tests only.\n    var DEBUG_SCORES = false;\n    function _setDebugScores(ds) {\n        DEBUG_SCORES = ds;\n    }\n\n\n    // Constants for scoring\n    var SPECIAL_POINTS = 40;\n    var MATCH_POINTS = 10;\n    var UPPER_CASE_MATCH = 100;\n    var CONSECUTIVE_MATCHES_POINTS = 8;\n    var BEGINNING_OF_NAME_POINTS = 13;\n    var LAST_SEGMENT_BOOST = 1;\n    var DEDUCTION_FOR_LENGTH = 0.2;\n    var NOT_STARTING_ON_SPECIAL_PENALTY = 25;\n\n    // Used in match lists to designate matches of \"special\" characters (see\n    // findSpecialCharacters above\n    function SpecialMatch(index, upper) {\n        this.index = index;\n        if (upper) {\n            this.upper = upper;\n        }\n    }\n\n    // Used in match lists to designate any matched characters that are not special\n    function NormalMatch(index, upper) {\n        this.index = index;\n        if (upper) {\n            this.upper = upper;\n        }\n    }\n\n    /*\n     * Finds the best matches between the query and the string. The query is\n     * compared with str (usually a lower case string with a lower case\n     * query).\n     *\n     * Generally speaking, this function tries to find \"special\" characters\n     * (see findSpecialCharacters above) first. Failing that, it starts scanning\n     * the \"normal\" characters. Sometimes, it will find a special character that matches\n     * but then not be able to match the rest of the query. In cases like that, the\n     * search will backtrack and try to find matches for the whole query earlier in the\n     * string.\n     *\n     * A contrived example will help illustrate how the searching and backtracking works. It's a bit long,\n     * but it illustrates different pieces of the algorithm which can be tricky. Let's say that we're\n     * searching the string \"AzzBzzCzdzezzDgxgEF\" for \"abcdex\".\n     *\n     * To start with, it will match \"abcde\" from the query to \"A B C D E\" in the string (the spaces\n     * represent gaps in the matched part of the string), because those are all \"special characters\".\n     * However, the \"x\" in the query doesn't match the \"F\" which is the only character left in the\n     * string.\n     *\n     * Backtracking kicks in. The \"E\" is pulled off of the match list.\n     * deadBranches[4] is set to the \"g\" before the \"E\". This means that for the 5th\n     * query character (the \"e\") we know that we don't have a match beyond that point in the string.\n     *\n     * To resume searching, the backtrack function looks at the previous match (the \"D\") and starts\n     * searching in character-by-character (ANY_MATCH) mode right after that. It fails to find an\n     * \"e\" before it gets to deadBranches[4], so it has to backtrack again.\n     *\n     * This time, the \"D\" is pulled off the match list.\n     * deadBranches[3] is set to the \"z\" before the \"D\", because we know that for the \"dex\" part of the\n     * query, we can't make it work past the \"D\". We'll resume searching with the \"z\" after the \"C\".\n     *\n     * Doing an ANY_MATCH search, we find the \"d\". We then start searching specials for \"e\", but we\n     * stop before we get to \"E\" because deadBranches[4] tells us that's a dead end. So, we switch\n     * to ANY_MATCH and find the \"e\".\n     *\n     * Finally, we search for the \"x\". We don't find a special that matches, so we start an ANY_MATCH\n     * search. Then we find the \"x\", and we have a successful match.\n     *\n     * Here are some notes on how the algorithm works:\n     *\n     * * We only backtrack() when we're exhausted both special AND normal forward searches past that point,\n     *   for the query remainder we currently have.  For a different query remainder, we may well get further\n     *   along - hence deadBranches[] being dependent on queryCounter; but in order to get a different query\n     *   remainder, we must give up one or more current matches by backtracking.\n     *\n     * * Normal \"any char\" forward search is a superset of special matching mode -- anything that would have\n     *   been matched in special mode *could* also be matched by normal mode. In practice, however,\n     *   any special characters that could have matched would be picked up first by the specials matching\n     *   code.\n     *\n     * * backtrack() always goes at least as far back as str[deadBranches[queryCounter]-1] before allowing\n     *   forward searching to resume\n     *\n     * * When `deadBranches[queryCounter] = strCounter` it means if we're still trying to match\n     *   `queryLower[queryCounter]` and we get to `str[strCounter]`, there's no way we can match the\n     *   remainer of `queryLower` with the remainder of `str` -- either using specials-only or\n     *   full any-char matching.\n     *\n     * * We know this because deadBranches[] is set in backtrack(), and we don't get to backtrack() unless\n     *   either:\n     *   1. We've already exhausted both special AND normal forward searches past that point\n     *      (i.e. backtrack() due to `strCounter >= str.length`, yet `queryCounter < query.length`)\n     *   2. We stopped searching further forward due to a previously set deadBranches[] value\n     *      (i.e. backtrack() due to `strCounter > deadBranches[queryCounter]`, yet\n     *      `queryCounter < query.length`)\n     *\n     * @param {string} query the search string (generally lower cased)\n     * @param {string} str the string to compare with (generally lower cased)\n     * @param {string} originalQuery the \"non-normalized\" query string (used to detect case match priority)\n     * @param {string} originalStr the \"non-normalized\" string to compare with (used to detect case match priority)\n     * @param {Array} specials list of special indexes in str (from findSpecialCharacters)\n     * @param {int} startingSpecial index into specials array to start scanning with\n     * @return {Array.<SpecialMatch|NormalMatch>} matched indexes or null if no matches possible\n     */\n    function _generateMatchList(query, str, originalQuery, originalStr, specials, startingSpecial) {\n        var result = [];\n\n        // used to keep track of which special character we're testing now\n        var specialsCounter = startingSpecial;\n\n        // strCounter and queryCounter are the indexes used for pulling characters\n        // off of the str/compareLower and query.\n        var strCounter = specials[startingSpecial];\n        var queryCounter;\n\n        // the search branches out between special characters and normal characters\n        // that are found via consecutive character scanning. In the process of\n        // performing these scans, we discover that parts of the query will not match\n        // beyond a given point in the string. We keep track of that information\n        // in deadBranches, which has a slot for each character in the query.\n        // The value stored in the slot is the index into the string after which we\n        // are certain there is no match.\n        var deadBranches = [];\n\n        for (queryCounter = 0; queryCounter < query.length; queryCounter++) {\n            deadBranches[queryCounter] = Infinity;\n        }\n\n        queryCounter = 0;\n\n        var state = SPECIALS_MATCH;\n\n        // Compares the current character from the query string against the\n        // special characters in str. Returns true if a match was found,\n        // false otherwise.\n        function findMatchingSpecial() {\n            // used to loop through the specials\n            var i;\n\n            for (i = specialsCounter; i < specials.length; i++) {\n                // short circuit this search when we know there are no matches following\n                if (specials[i] >= deadBranches[queryCounter]) {\n                    break;\n                }\n\n                // First, ensure that we're not comparing specials that\n                // come earlier in the string than our current search position.\n                // This can happen when the string position changes elsewhere.\n                if (specials[i] < strCounter) {\n                    specialsCounter = i;\n                } else if (query[queryCounter] === str[specials[i]]) {\n                    // we have a match! do the required tracking\n                    strCounter = specials[i];\n\n                    // Upper case match check:\n                    // If the query and original string matched, but the original string\n                    // and the lower case version did not, that means that the original\n                    // was upper case.\n                    var upper = originalQuery[queryCounter] === originalStr[strCounter] && originalStr[strCounter] !== str[strCounter];\n                    result.push(new SpecialMatch(strCounter, upper));\n                    specialsCounter = i;\n                    queryCounter++;\n                    strCounter++;\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        // This function implements the backtracking that is done when we fail to find\n        // a match with the query using the \"search for specials first\" approach.\n        //\n        // returns false when it is not able to backtrack successfully\n        function backtrack() {\n\n            // The idea is to pull matches off of our match list, rolling back\n            // characters from the query. We pay special attention to the special\n            // characters since they are searched first.\n            while (result.length > 0) {\n                var item = result.pop();\n\n                // nothing in the list? there's no possible match then.\n                if (!item) {\n                    return false;\n                }\n\n                // we pulled off a match, which means that we need to put a character\n                // back into our query. strCounter is going to be set once we've pulled\n                // off the right special character and know where we're going to restart\n                // searching from.\n                queryCounter--;\n\n                if (item instanceof SpecialMatch) {\n                    // pulled off a special, which means we need to make that special available\n                    // for matching again\n                    specialsCounter--;\n\n                    // check to see if we've gone back as far as we need to\n                    if (item.index < deadBranches[queryCounter]) {\n                        // we now know that this part of the query does not match beyond this\n                        // point\n                        deadBranches[queryCounter] = item.index - 1;\n\n                        // since we failed with the specials along this track, we're\n                        // going to reset to looking for matches consecutively.\n                        state = ANY_MATCH;\n\n                        // we figure out where to start looking based on the new\n                        // last item in the list. If there isn't anything else\n                        // in the match list, we'll start over at the starting special\n                        // (which is generally the beginning of the string, or the\n                        // beginning of the last segment of the string)\n                        item = result[result.length - 1];\n                        if (!item) {\n                            strCounter = specials[startingSpecial] + 1;\n                            return true;\n                        }\n                        strCounter = item.index + 1;\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        while (true) {\n\n            // keep looping until we've either exhausted the query or the string\n            while (queryCounter < query.length && strCounter < str.length && strCounter <= deadBranches[queryCounter]) {\n                if (state === SPECIALS_MATCH) {\n                    if (!findMatchingSpecial()) {\n                        state = ANY_MATCH;\n                    }\n                }\n\n                if (state === ANY_MATCH) {\n                    // we look character by character for matches\n                    if (query[queryCounter] === str[strCounter]) {\n                        // got a match! record it, and switch back to searching specials\n\n                        // See the specials section above for a comment on the expression\n                        // for `upper` below.\n                        var upper = originalQuery[queryCounter] === originalStr[strCounter] && originalStr[strCounter] !== str[strCounter];\n                        result.push(new NormalMatch(strCounter++, upper));\n\n                        queryCounter++;\n                        state = SPECIALS_MATCH;\n                    } else {\n                        // no match, keep looking\n                        strCounter++;\n                    }\n                }\n            }\n\n            // if we've finished the query, or we haven't finished the query but we have no\n            // more backtracking we can do, then we're all done searching.\n            if (queryCounter >= query.length || (queryCounter < query.length && !backtrack())) {\n                break;\n            }\n        }\n\n        // return null when we don't find anything\n        if (queryCounter < query.length || result.length === 0) {\n            return null;\n        }\n        return result;\n    }\n\n\n    /*\n     * Seek out the best match in the last segment (generally the filename).\n     * Matches in the filename are preferred, but the query entered could match\n     * any part of the path. So, we find the best match we can get in the filename\n     * and then allow for searching the rest of the string with any characters that\n     * are left from the beginning of the query.\n     *\n     * The parameters and return value are the same as for getMatchRanges,\n     * except this function is always working on the last segment and the\n     * result can optionally include a remainder, which is the characters\n     * at the beginning of the query which did not match in the last segment.\n     *\n     * @param {string} query the search string (generally lower cased)\n     * @param {string} str the string to compare with (generally lower cased)\n     * @param {string} originalQuery the \"non-normalized\" query string (used to detect case match priority)\n     * @param {string} originalStr the \"non-normalized\" string to compare with (used to detect case match priority)\n     * @param {Array} specials list of special indexes in str (from findSpecialCharacters)\n     * @param {int} startingSpecial index into specials array to start scanning with\n     * @param {boolean} lastSegmentStart which character does the last segment start at\n     * @return {{remainder:int, matchList:Array.<SpecialMatch|NormalMatch>}} matched indexes or null if no matches possible\n     */\n    function _lastSegmentSearch(query, str, originalQuery, originalStr, specials, startingSpecial, lastSegmentStart) {\n        var queryCounter, matchList;\n\n        // It's possible that the query is longer than the last segment.\n        // If so, we can chop off the bit that we know couldn't possibly be there.\n        var remainder = \"\",\n            originalRemainder = \"\",\n            extraCharacters = specials[startingSpecial] + query.length - str.length;\n\n        if (extraCharacters > 0) {\n            remainder = query.substring(0, extraCharacters);\n            originalRemainder = originalQuery.substring(0, extraCharacters);\n            query = query.substring(extraCharacters);\n            originalQuery = originalQuery.substring(extraCharacters);\n        }\n\n        for (queryCounter = 0; queryCounter < query.length; queryCounter++) {\n            matchList = _generateMatchList(query.substring(queryCounter),\n                                     str, originalQuery.substring(queryCounter),\n                                     originalStr, specials, startingSpecial);\n\n            // if we've got a match *or* there are no segments in this string, we're done\n            if (matchList || startingSpecial === 0) {\n                break;\n            }\n        }\n\n        if (queryCounter === query.length || !matchList) {\n            return null;\n        } else {\n            return {\n                remainder: remainder + query.substring(0, queryCounter),\n                originalRemainder: originalRemainder + originalQuery.substring(0, queryCounter),\n                matchList: matchList\n            };\n        }\n    }\n\n    /*\n     * Implements the top-level search algorithm. Search the last segment first,\n     * then search the rest of the string with the remainder.\n     *\n     * The parameters and return value are the same as for getMatchRanges.\n     *\n     * @param {string} queryLower the search string (will be searched lower case)\n     * @param {string} compareLower the lower-cased string to search\n     * @param {string} originalQuery the \"non-normalized\" query string (used to detect case match priority)\n     * @param {string} originalStr the \"non-normalized\" string to compare with (used to detect case match priority)\n     * @param {Array} specials list of special indexes in str (from findSpecialCharacters)\n     * @param {int} lastSegmentSpecialsIndex index into specials array to start scanning with\n     * @return {Array.<SpecialMatch|NormalMatch>} matched indexes or null if no matches possible\n     */\n    function _wholeStringSearch(queryLower, compareLower, originalQuery, originalStr, specials, lastSegmentSpecialsIndex) {\n        var lastSegmentStart = specials[lastSegmentSpecialsIndex];\n        var result;\n        var matchList;\n\n        result = _lastSegmentSearch(queryLower, compareLower, originalQuery, originalStr, specials, lastSegmentSpecialsIndex, lastSegmentStart);\n\n        if (result) {\n            matchList = result.matchList;\n\n            // Do we have more query characters that did not fit?\n            if (result.remainder) {\n                // Scan with the remainder only through the beginning of the last segment\n                var remainderMatchList = _generateMatchList(result.remainder,\n                                              compareLower.substring(0, lastSegmentStart),\n                                              result.originalRemainder,\n                                              originalStr.substring(0, lastSegmentStart),\n                                              specials.slice(0, lastSegmentSpecialsIndex), 0);\n\n                if (remainderMatchList) {\n                    // add the new matched ranges to the beginning of the set of ranges we had\n                    matchList.unshift.apply(matchList, remainderMatchList);\n                } else {\n                    // no match\n                    return null;\n                }\n            }\n        } else {\n            // No match in the last segment, so we start over searching the whole\n            // string\n            matchList = _generateMatchList(queryLower, compareLower, originalQuery, originalStr, specials, 0);\n        }\n\n        return matchList;\n    }\n\n    /**\n     * Converts a list of matches into a form suitable for returning from stringMatch.\n     *\n     * @param {Array.<SpecialMatch|NormalMatch>} matchList to convert\n     * @param {string} original string\n     * @param {int} character index where last segment begins\n     * @return {{ranges:Array.<{text:string, matched:boolean, includesLastSegment:boolean}>, matchGoodness:int, scoreDebug: Object}} matched ranges and score\n     */\n    function _computeRangesAndScore(matchList, str, lastSegmentStart) {\n        var matchCounter;\n        var ranges = [];\n        var lastMatchIndex = -1;\n        var lastSegmentScore = 0;\n        var currentRangeStartedOnSpecial = false;\n\n        var score = 0;\n        var scoreDebug;\n        if (DEBUG_SCORES) {\n            scoreDebug = {\n                special: 0,\n                match: 0,\n                upper: 0,\n                lastSegment: 0,\n                beginning: 0,\n                lengthDeduction: 0,\n                consecutive: 0,\n                notStartingOnSpecial: 0\n            };\n        }\n\n        var currentRange = null;\n\n        // Records the current range and adds any additional ranges required to\n        // get to character index c. This function is called before starting a new range\n        // or returning from the function.\n        function closeRangeGap(c) {\n            // Close the current range\n            if (currentRange) {\n                currentRange.includesLastSegment = lastMatchIndex >= lastSegmentStart;\n                if (currentRange.matched && currentRange.includesLastSegment) {\n                    if (DEBUG_SCORES) {\n                        scoreDebug.lastSegment += lastSegmentScore * LAST_SEGMENT_BOOST;\n                    }\n                    score += lastSegmentScore * LAST_SEGMENT_BOOST;\n                }\n\n                if (currentRange.matched && !currentRangeStartedOnSpecial) {\n                    if (DEBUG_SCORES) {\n                        scoreDebug.notStartingOnSpecial -= NOT_STARTING_ON_SPECIAL_PENALTY;\n                    }\n                    score -= NOT_STARTING_ON_SPECIAL_PENALTY;\n                }\n                ranges.push(currentRange);\n            }\n\n            // If there was space between the new range and the last,\n            // add a new unmatched range before the new range can be added.\n            if (lastMatchIndex + 1 < c) {\n                ranges.push({\n                    text: str.substring(lastMatchIndex + 1, c),\n                    matched: false,\n                    includesLastSegment: c > lastSegmentStart\n                });\n            }\n            currentRange = null;\n            lastSegmentScore = 0;\n        }\n\n        // In some cases (see the use of this variable below), we accelerate the\n        // bonus the more consecutive matches there are.\n        var numConsecutive = 0;\n\n        // Adds a matched character to the appropriate range\n        function addMatch(match) {\n            // Pull off the character index\n            var c = match.index;\n            var newPoints = 0;\n\n            // A match means that we need to do some scoring bookkeeping.\n            // Start with points added for any match\n            if (DEBUG_SCORES) {\n                scoreDebug.match += MATCH_POINTS;\n            }\n            newPoints += MATCH_POINTS;\n\n            if (match.upper) {\n                if (DEBUG_SCORES) {\n                    scoreDebug.upper += UPPER_CASE_MATCH;\n                }\n                newPoints += UPPER_CASE_MATCH;\n            }\n\n            // A bonus is given for characters that match at the beginning\n            // of the filename\n            if (c === lastSegmentStart) {\n                if (DEBUG_SCORES) {\n                    scoreDebug.beginning += BEGINNING_OF_NAME_POINTS;\n                }\n                newPoints += BEGINNING_OF_NAME_POINTS;\n            }\n\n            // If the new character immediately follows the last matched character,\n            // we award the consecutive matches bonus. The check for score > 0\n            // handles the initial value of lastMatchIndex which is used for\n            // constructing ranges but we don't yet have a true match.\n            if (score > 0 && lastMatchIndex + 1 === c) {\n                // Continue boosting for each additional match at the beginning\n                // of the name\n                if (c - numConsecutive === lastSegmentStart) {\n                    if (DEBUG_SCORES) {\n                        scoreDebug.beginning += BEGINNING_OF_NAME_POINTS;\n                    }\n                    newPoints += BEGINNING_OF_NAME_POINTS;\n                }\n\n                numConsecutive++;\n\n                var boost = CONSECUTIVE_MATCHES_POINTS * numConsecutive;\n\n                // Consecutive matches that started on a special are a\n                // good indicator of intent, so we award an added bonus there.\n                if (currentRangeStartedOnSpecial) {\n                    boost = boost * 2;\n                }\n\n                if (DEBUG_SCORES) {\n                    scoreDebug.consecutive += boost;\n                }\n                newPoints += boost;\n            } else {\n                numConsecutive = 1;\n            }\n\n            // add points for \"special\" character matches\n            if (match instanceof SpecialMatch) {\n                if (DEBUG_SCORES) {\n                    scoreDebug.special += SPECIAL_POINTS;\n                }\n                newPoints += SPECIAL_POINTS;\n            }\n\n            score += newPoints;\n\n            // points accumulated in the last segment get an extra bonus\n            if (c >= lastSegmentStart) {\n                lastSegmentScore += newPoints;\n            }\n\n            // if the last range wasn't a match or there's a gap, we need to close off\n            // the range to start a new one.\n            if ((currentRange && !currentRange.matched) || c > lastMatchIndex + 1) {\n                closeRangeGap(c);\n            }\n            lastMatchIndex = c;\n\n            // set up a new match range or add to the current one\n            if (!currentRange) {\n                currentRange = {\n                    text: str[c],\n                    matched: true\n                };\n\n                // Check to see if this new matched range is starting on a special\n                // character. We penalize those ranges that don't, because most\n                // people will search on the logical boundaries of the name\n                currentRangeStartedOnSpecial = match instanceof SpecialMatch;\n            } else {\n                currentRange.text += str[c];\n            }\n        }\n\n        // scan through the matches, adding each one in turn\n        for (matchCounter = 0; matchCounter < matchList.length; matchCounter++) {\n            var match = matchList[matchCounter];\n            addMatch(match);\n        }\n\n        // add a range for the last part of the string\n        closeRangeGap(str.length);\n\n        // shorter strings that match are often better than longer ones\n        var lengthPenalty = -1 * Math.round(str.length * DEDUCTION_FOR_LENGTH);\n        if (DEBUG_SCORES) {\n            scoreDebug.lengthDeduction = lengthPenalty;\n        }\n        score = score + lengthPenalty;\n\n        var result = {\n            ranges: ranges,\n            matchGoodness: score\n        };\n\n        if (DEBUG_SCORES) {\n            result.scoreDebug = scoreDebug;\n        }\n        return result;\n    }\n\n    /*\n     * If we short circuit normal matching to produce a prefix match,\n     * this function will generate the appropriate SearchResult.\n     * This function assumes that the prefix match check has already\n     * been performed.\n     *\n     * @param {string} str  The string with the prefix match for the query\n     * @param {string} query  The query that matched the beginning of str\n     * @return {{ranges:Array.<{text:string, matched:boolean, includesLastSegment:boolean}>, matchGoodness:int, scoreDebug: Object}} ranges has a matching range for beginning of str\n     *                      and a non-matching range for the end of the str\n     *                      the score is -Number.MAX_VALUE in all cases\n     */\n    function _prefixMatchResult(str, query) {\n        var result = new SearchResult(str);\n\n        result.matchGoodness = -Number.MAX_VALUE;\n\n        if (str.substr(0, query.length) !== query) {\n            // Penalize for not matching case\n            result.matchGoodness *= 0.5;\n        }\n\n        if (DEBUG_SCORES) {\n            result.scoreDebug = {\n                beginning: -result.matchGoodness\n            };\n        }\n\n        result.stringRanges = [{\n            text: str.substr(0, query.length),\n            matched: true,\n            includesLastSegment: true\n        }];\n        if (str.length > query.length) {\n            result.stringRanges.push({\n                text: str.substring(query.length),\n                matched: false,\n                includesLastSegment: true\n            });\n        }\n        return result;\n    }\n\n\n    /*\n     * Match str against the query using the QuickOpen algorithm provided by\n     * the functions above. The general idea is to prefer matches of \"special\" characters and,\n     * optionally, matches that occur in the \"last segment\" (generally, the filename). stringMatch\n     * will try to provide the best match and produces a \"matchGoodness\" score\n     * to allow for relative ranking.\n     *\n     * The result object returned includes \"stringRanges\" which can be used to highlight\n     * the matched portions of the string, in addition to the \"matchGoodness\"\n     * mentioned above. If DEBUG_SCORES is true, scoreDebug is set on the result\n     * to provide insight into the score.\n     *\n     * The matching is done in a case-insensitive manner.\n     *\n     * @param {string} str  The string to search\n     * @param {string} query  The query string to find in string\n     * @param {{preferPrefixMatches:?boolean, segmentedSearch:?boolean}} options to control search behavior.\n     *                  preferPrefixMatches puts an exact case-insensitive prefix match ahead of all other matches,\n     *                  even short-circuiting the match logic. This option implies segmentedSearch=false.\n     *                  When segmentedSearch is true, the string is broken into segments by \"/\" characters\n     *                  and the last segment is searched first and matches there are scored higher.\n     * @param {?Object} special (optional) the specials data from findSpecialCharacters, if already known\n     *                  This is generally just used by StringMatcher for optimization.\n     * @return {{ranges:Array.<{text:string, matched:boolean, includesLastSegment:boolean}>, matchGoodness:int, scoreDebug: Object}} matched ranges and score\n     */\n    function stringMatch(str, query, options, special) {\n        var result;\n\n        options = options || {};\n\n        // No query? Short circuit the normal work done and just\n        // return a single range that covers the whole string.\n        if (!query) {\n            result = new SearchResult(str);\n            result.matchGoodness = 0;\n            if (DEBUG_SCORES) {\n                result.scoreDebug = {};\n            }\n            result.stringRanges = [{\n                text: str,\n                matched: false,\n                includesLastSegment: true\n            }];\n            return result;\n        }\n\n        // comparisons are case insensitive, so switch to lower case here\n        var queryLower = query.toLowerCase();\n        var compareLower = str.toLowerCase();\n\n        if (options.preferPrefixMatches) {\n            options.segmentedSearch = false;\n        }\n\n        if (options.preferPrefixMatches && compareLower.substr(0, queryLower.length) === queryLower) {\n            // NOTE: we compare against the case insensitive match\n            //        above but we pass the case-sensitive version in\n            //        because we want to weight the match to give case-matches\n            //        a higher score\n            return _prefixMatchResult(str, query);\n        }\n\n        // Locate the special characters and then use orderedCompare to do the real\n        // work.\n        if (!special) {\n            special = findSpecialCharacters(str);\n        }\n        var lastSegmentStart, matchList;\n\n        // For strings that are not broken into multiple segments, we can potentially\n        // avoid some extra work\n        if (options.segmentedSearch) {\n            lastSegmentStart = special.specials[special.lastSegmentSpecialsIndex];\n            matchList = _wholeStringSearch(queryLower, compareLower, query, str, special.specials,\n                              special.lastSegmentSpecialsIndex);\n        } else {\n            lastSegmentStart = 0;\n            matchList = _generateMatchList(queryLower, compareLower, query, str, special.specials, 0);\n        }\n\n        // If we get a match, turn this into a SearchResult as expected by the consumers\n        // of this API.\n        if (matchList) {\n            var compareData = _computeRangesAndScore(matchList, str, lastSegmentStart);\n            result = new SearchResult(str);\n            result.stringRanges = compareData.ranges;\n            result.matchGoodness = -1 * compareData.matchGoodness;\n            if (DEBUG_SCORES) {\n                result.scoreDebug = compareData.scoreDebug;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * Sorts an array of SearchResult objects on a primary field, followed by secondary fields\n     * in case of ties. 'fieldSpec' provides the priority order for fields, where the first entry is the primary field, for example:\n     *      multiFieldSort(bugList, [ \"milestone\", \"severity\" ]);\n     * Would sort a bug list by milestone, and within each milestone sort bugs by severity.\n     *\n     * fieldSpec can also include comparator functions of the form normally used by the sort()\n     * function.\n     *\n     * Any fields that have a string value are compared case-insensitively. Fields used should be\n     * present on all SearchResult objects (no optional/undefined fields).\n     *\n     * @param {!Array.<SearchResult>} searchResults\n     * @param {!Array.<string, function>} fieldSpec\n     */\n    function multiFieldSort(searchResults, fieldSpec) {\n        // Move field names into an array, with primary field first\n        var comparisons;\n        if (Array.isArray(fieldSpec)) {\n            comparisons = fieldSpec;\n        } else {\n            // TODO Deprecate this form of calling this function\n            comparisons = [];\n            _.forEach(fieldSpec, function (priority, key) {\n                comparisons[priority] = key;\n            });\n        }\n\n        searchResults.sort(function (a, b) {\n            var priority;\n            for (priority = 0; priority < comparisons.length; priority++) {\n                var comparison = comparisons[priority];\n                if (typeof comparison === \"function\") {\n                    var result = comparison(a, b);\n                    if (result) {\n                        return result;\n                    }\n                } else {\n                    var valueA = a[comparison];\n                    var valueB = b[comparison];\n                    if (typeof valueA === \"string\") {\n                        valueA = valueA.toLowerCase();\n                        valueB = valueB.toLowerCase();\n                    }\n\n                    if (valueA < valueB) {\n                        return -1;\n                    } else if (valueA > valueB) {\n                        return 1;\n                    }\n                }\n                // otherwise, move on to next sort priority\n            }\n            return 0; // all sort fields are equal\n        });\n    }\n\n    /**\n     * Sorts search results generated by stringMatch(): results are sorted into several\n     * tiers based on how well they matched the search query, then sorted alphabetically\n     * within each tier.\n     */\n    function basicMatchSort(searchResults) {\n        multiFieldSort(searchResults, { matchGoodness: 0, label: 1 });\n    }\n\n    /**\n     * A StringMatcher provides an interface to the stringMatch function with built-in\n     * caching. You should use a StringMatcher for the lifetime of queries over a\n     * single data set.\n     *\n     * You are free to store other data on this object to assist in higher-level caching.\n     * (This object's caches are all stored in \"_\" prefixed properties.)\n     *\n     * @param {{preferPrefixMatches:?boolean, segmentedSearch:?boolean}} options to control search behavior.\n     *                  preferPrefixMatches puts an exact case-insensitive prefix match ahead of all other matches,\n     *                  even short-circuiting the match logic. This option implies segmentedSearch=false.\n     *                  segmentedSearch treats segments of the string specially.\n     */\n    function StringMatcher(options) {\n        this.options = options;\n        this.reset();\n    }\n\n    /**\n     * Map from search-result string to the findSpecialCharacters() result for that string - easy to cache\n     * since this info doesn't change as the query changes.\n     * @type {Object.<string, {specials:Array.<number>, lastSegmentSpecialsIndex:number}>}\n     */\n    StringMatcher.prototype._specialsCache = null;\n\n    /**\n     * Set of search-result strings that we know don't match the query _lastQuery - or any other query with\n     * that prefix.\n     * @type {Object.<string, boolean>}\n     */\n    StringMatcher.prototype._noMatchCache = null;\n\n    /**\n     * Clears the caches. Use this in the event that the caches may be invalid.\n     */\n    StringMatcher.prototype.reset = function () {\n        // We keep track of the last query to know when we need to invalidate.\n        this._lastQuery = null;\n\n        this._specialsCache = {};\n        this._noMatchCache = {};\n    };\n\n    /**\n     * Performs a single match using the stringMatch function. See stringMatch for full documentation.\n     *\n     * @param {string} str  The string to search\n     * @param {string} query  The query string to find in string\n     * @return {{ranges:Array.<{text:string, matched:boolean, includesLastSegment:boolean}>, matchGoodness:int, scoreDebug: Object}} matched ranges and score\n     */\n    StringMatcher.prototype.match = function (str, query) {\n\n        // If the query is not just added characters from the previous query, we invalidate\n        // the no match cache and will re-match everything.\n        if (this._lastQuery !== null && (this._lastQuery !== query.substring(0, this._lastQuery.length))) {\n            this._noMatchCache = {};\n        }\n\n        this._lastQuery = query;\n\n        // Check for a known non-matching string.\n        if (_.has(this._noMatchCache, str)) {\n            return undefined;\n        }\n\n        // Load up the cached specials information (or build it if this is our first time through).\n        var special = _.has(this._specialsCache, str) ? this._specialsCache[str] : undefined;\n        if (special === undefined) {\n            special = findSpecialCharacters(str);\n            this._specialsCache[str] = special;\n        }\n\n        var result = stringMatch(str, query, this.options, special);\n\n        // If this query was not a match, we cache that fact for next time.\n        if (!result) {\n            this._noMatchCache[str] = true;\n        }\n        return result;\n    };\n\n    exports._findSpecialCharacters  = findSpecialCharacters;\n    exports._wholeStringSearch      = _wholeStringSearch;\n    exports._lastSegmentSearch      = _lastSegmentSearch;\n    exports._setDebugScores         = _setDebugScores;\n    exports._generateMatchList      = _generateMatchList;\n    exports._SpecialMatch           = SpecialMatch;\n    exports._NormalMatch            = NormalMatch;\n    exports._computeRangesAndScore  = _computeRangesAndScore;\n\n    // public exports\n    exports.SearchResult            = SearchResult;\n    exports.stringMatch             = stringMatch;\n    exports.basicMatchSort          = basicMatchSort;\n    exports.multiFieldSort          = multiFieldSort;\n    exports.StringMatcher           = StringMatcher;\n});\n"
  },
  {
    "path": "src/utils/StringUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/* The hash code routne is taken from http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery\n   @CC wiki attribution: esmiralha\n*/\n\n/*eslint no-bitwise: off */\n/*jslint bitwise: true */\n\n/**\n *  Utilities functions related to string manipulation\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    /**\n     * Format a string by replacing placeholder symbols with passed in arguments.\n     *\n     * Example: var formatted = StringUtils.format(\"Hello {0}\", \"World\");\n     *\n     * @param {string} str The base string\n     * @param {...} Arguments to be substituted into the string\n     *\n     * @return {string} Formatted string\n     */\n    function format(str) {\n        // arguments[0] is the base string, so we need to adjust index values here\n        var args = [].slice.call(arguments, 1);\n        return str.replace(/\\{(\\d+)\\}/g, function (match, num) {\n            return typeof args[num] !== \"undefined\" ? args[num] : match;\n        });\n    }\n\n    function regexEscape(str) {\n        return str.replace(/([.?*+\\^$\\[\\]\\\\(){}|\\-])/g, \"\\\\$1\");\n    }\n\n    // Periods (aka \"dots\") are allowed in HTML identifiers, but jQuery interprets\n    // them as the start of a class selector, so they need to be escaped\n    function jQueryIdEscape(str) {\n        return str.replace(/\\./g, \"\\\\.\");\n    }\n\n    /**\n     * Splits the text by new line characters and returns an array of lines\n     * @param {string} text\n     * @return {Array.<string>} lines\n     */\n    function getLines(text) {\n        return text.split(\"\\n\");\n    }\n\n    /**\n     * Returns a line number corresponding to an offset in some text. The text can\n     * be specified as a single string or as an array of strings that correspond to\n     * the lines of the string.\n     *\n     * Specify the text in lines when repeatedly calling the function on the same\n     * text in a loop. Use getLines() to divide the text into lines, then repeatedly call\n     * this function to compute a line number from the offset.\n     *\n     * @param {string | Array.<string>} textOrLines - string or array of lines from which\n     *      to compute the line number from the offset\n     * @param {number} offset\n     * @return {number} line number\n     */\n    function offsetToLineNum(textOrLines, offset) {\n        if (Array.isArray(textOrLines)) {\n            var lines = textOrLines,\n                total = 0,\n                line;\n            for (line = 0; line < lines.length; line++) {\n                if (total < offset) {\n                    // add 1 per line since /n were removed by splitting, but they needed to\n                    // contribute to the total offset count\n                    total += lines[line].length + 1;\n                } else if (total === offset) {\n                    return line;\n                } else {\n                    return line - 1;\n                }\n            }\n\n            // if offset is NOT over the total then offset is in the last line\n            if (offset <= total) {\n                return line - 1;\n            } else {\n                return undefined;\n            }\n        } else {\n            return textOrLines.substr(0, offset).split(\"\\n\").length - 1;\n        }\n    }\n\n    /**\n     * Returns true if the given string starts with the given prefix.\n     * @param   {String} str\n     * @param   {String} prefix\n     * @return {Boolean}\n     */\n    function startsWith(str, prefix) {\n        return str.slice(0, prefix.length) === prefix;\n    }\n\n    /**\n     * Returns true if the given string ends with the given suffix.\n     *\n     * @param {string} str\n     * @param {string} suffix\n     */\n    function endsWith(str, suffix) {\n        return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    }\n\n    function urlSort(a, b) {\n        var a2, b2;\n        function isFile(s) {\n            return ((s.lastIndexOf(\"/\") + 1) < s.length);\n        }\n\n        if (brackets.platform === \"win\") {\n            // Windows: prepend folder names with a '0' and file names with a '1' so folders are listed first\n            a2 = ((isFile(a)) ? \"1\" : \"0\") + a.toLowerCase();\n            b2 = ((isFile(b)) ? \"1\" : \"0\") + b.toLowerCase();\n        } else {\n            a2 = a.toLowerCase();\n            b2 = b.toLowerCase();\n        }\n\n        if (a2 === b2) {\n            return 0;\n        } else {\n            return (a2 > b2) ? 1 : -1;\n        }\n    }\n\n    /**\n     * Return an escaped path or URL string that can be broken near path separators.\n     * @param {string} url the path or URL to format\n     * @return {string} the formatted path or URL\n     */\n    function breakableUrl(url) {\n        // This is for displaying in UI, so always want it escaped\n        var escUrl = _.escape(url);\n\n        // Inject zero-width space character (U+200B) near path separators (/) to allow line breaking there\n        return escUrl.replace(\n            new RegExp(regexEscape(\"/\"), \"g\"),\n            \"/\" + \"&#8203;\"\n        );\n    }\n\n    /**\n     * Converts number of bytes into human readable format.\n     * If param bytes is negative it returns the number without any changes.\n     *\n     * @param {number} bytes     Number of bytes to convert\n     * @param {number} precision Number of digits after the decimal separator\n     * @return {string}\n     */\n    function prettyPrintBytes(bytes, precision) {\n        var kilobyte = 1024,\n            megabyte = kilobyte * 1024,\n            gigabyte = megabyte * 1024,\n            terabyte = gigabyte * 1024,\n            returnVal = bytes;\n\n        if ((bytes >= 0) && (bytes < kilobyte)) {\n            returnVal = bytes + \" B\";\n        } else if (bytes < megabyte) {\n            returnVal = (bytes / kilobyte).toFixed(precision) + \" KB\";\n        } else if (bytes < gigabyte) {\n            returnVal = (bytes / megabyte).toFixed(precision) + \" MB\";\n        } else if (bytes < terabyte) {\n            returnVal = (bytes / gigabyte).toFixed(precision) + \" GB\";\n        } else if (bytes >= terabyte) {\n            return (bytes / terabyte).toFixed(precision) + \" TB\";\n        }\n\n        return returnVal;\n    }\n\n    /**\n     * Truncate text to specified length.\n     * @param {string} str Text to be truncated.\n     * @param {number} len Length to which text should be truncated\n     * @return {?string} Returns truncated text only if it was changed\n     */\n    function truncate(str, len) {\n        // Truncate text to specified length\n        if (str.length > len) {\n            str = str.substr(0, len);\n\n            // To prevent awkwardly truncating in the middle of a word,\n            // attempt to truncate at the end of the last whole word\n            var lastSpaceChar = str.lastIndexOf(\" \");\n            if (lastSpaceChar < len && lastSpaceChar > -1) {\n                str = str.substr(0, lastSpaceChar);\n            }\n            return str;\n        }\n    }\n\n    /**\n     * Computes a 32bit hash from the given string\n     * Taken from http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery\n     * @CC wiki attribution: esmiralha\n     * @param   {string}   str The string for which hash is to be computed\n     * @return {number} The 32-bit hash\n     */\n    function hashCode(str) {\n        var hash = 0, i, chr, len;\n        if (str.length === 0) {\n            return hash;\n        }\n        for (i = 0, len = str.length; i < len; i++) {\n            chr   = str.charCodeAt(i);\n            hash  = ((hash << 5) - hash) + chr;\n            hash |= 0; // Convert to 32bit integer\n        }\n        return hash;\n    }\n\n    // Define public API\n    exports.format              = format;\n    exports.regexEscape         = regexEscape;\n    exports.jQueryIdEscape      = jQueryIdEscape;\n    exports.getLines            = getLines;\n    exports.offsetToLineNum     = offsetToLineNum;\n    exports.urlSort             = urlSort;\n    exports.breakableUrl        = breakableUrl;\n    exports.startsWith          = startsWith;\n    exports.endsWith            = endsWith;\n    exports.prettyPrintBytes    = prettyPrintBytes;\n    exports.truncate            = truncate;\n    exports.hashCode            = hashCode;\n});\n"
  },
  {
    "path": "src/utils/TokenUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Functions for iterating through tokens in the current editor buffer. Useful for doing\n * light parsing that can rely purely on information gathered by the code coloring mechanism.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _           = require(\"thirdparty/lodash\"),\n        CodeMirror  = require(\"thirdparty/CodeMirror/lib/codemirror\");\n\n    var cache;\n\n\n    function _clearCache(cm) {\n        cache = null;\n        if (cm) { // event handler\n            cm.off(\"changes\", _clearCache);\n        }\n    }\n\n    /*\n     * Caches the tokens for the given editor/line if needed\n     * @param {!CodeMirror} cm\n     * @param {!number} line\n     * @return {Array.<Object>} (Cached) array of tokens\n     */\n    function _manageCache(cm, line) {\n        if (!cache || !cache.tokens || cache.line !== line || cache.cm !== cm) {\n            // Cache is no longer matching -> Update\n            var tokens = cm.getLineTokens(line, false);\n            // Add empty beginning-of-line token for backwards compatibility\n            tokens.unshift(cm.getTokenAt({line: line, ch: 0}, false));\n            cache = {\n                cm: cm,\n                line: line,\n                timeStamp: Date.now(),\n                tokens: tokens\n            };\n            cm.off(\"changes\", _clearCache);\n            cm.on(\"changes\", _clearCache);\n        }\n        return cache.tokens;\n    }\n\n    /*\n     * Like cm.getTokenAt, but with caching. Way more performant for long lines.\n     * @param {!CodeMirror} cm\n     * @param {!{ch:number, line:number}} pos\n     * @param {boolean} precise If given, results in more current results. Suppresses caching.\n     * @return {Object} Token for position\n     */\n    function getTokenAt(cm, pos, precise) {\n        if (precise) {\n            _clearCache(); // reset cache\n            return cm.getTokenAt(pos, precise);\n        }\n        var cachedTokens    = _manageCache(cm, pos.line),\n            tokenIndex      = _.sortedIndex(cachedTokens, {end: pos.ch}, \"end\"), // binary search is faster for long arrays\n            token           = cachedTokens[tokenIndex];\n        return token || cm.getTokenAt(pos, precise); // fall back to CMs getTokenAt, for example in an empty line\n    }\n\n   /**\n     * Creates a context object for the given editor and position, suitable for passing to the\n     * move functions.\n     * @param {!CodeMirror} cm\n     * @param {!{ch:number, line:number}} pos\n     * @return {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}}\n     */\n    function getInitialContext(cm, pos) {\n        return {\n            \"editor\": cm,\n            \"pos\": pos,\n            \"token\": cm.getTokenAt(pos, true)\n        };\n    }\n\n    /**\n     * Moves the given context backwards by one token.\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} ctx\n     * @param {boolean=} precise If code is being edited, use true (default) for accuracy.\n     *      If parsing unchanging code, use false to use cache for performance.\n     * @return {boolean} whether the context changed\n     */\n    function movePrevToken(ctx, precise) {\n        if (precise === undefined) {\n            precise = true;\n        }\n\n        if (ctx.pos.ch <= 0 || ctx.token.start <= 0) {\n            //move up a line\n            if (ctx.pos.line <= 0) {\n                return false; //at the top already\n            }\n            ctx.pos.line--;\n            ctx.pos.ch = ctx.editor.getLine(ctx.pos.line).length;\n        } else {\n            ctx.pos.ch = ctx.token.start;\n        }\n        ctx.token = getTokenAt(ctx.editor, ctx.pos, precise);\n        return true;\n    }\n\n    /**\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} ctx\n     * @return {boolean} true if movePrevToken() would return false without changing pos\n     */\n    function isAtStart(ctx) {\n        return (ctx.pos.ch <= 0 || ctx.token.start <= 0) && (ctx.pos.line <= 0);\n    }\n\n    /**\n     * Moves the given context forward by one token.\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} ctx\n     * @param {boolean=} precise If code is being edited, use true (default) for accuracy.\n     *      If parsing unchanging code, use false to use cache for performance.\n     * @return {boolean} whether the context changed\n     */\n    function moveNextToken(ctx, precise) {\n        var eol = ctx.editor.getLine(ctx.pos.line).length;\n        if (precise === undefined) {\n            precise = true;\n        }\n\n        if (ctx.pos.ch >= eol || ctx.token.end >= eol) {\n            //move down a line\n            if (ctx.pos.line >= ctx.editor.lineCount() - 1) {\n                return false; //at the bottom\n            }\n            ctx.pos.line++;\n            ctx.pos.ch = 0;\n        } else {\n            ctx.pos.ch = ctx.token.end + 1;\n        }\n        ctx.token = getTokenAt(ctx.editor, ctx.pos, precise);\n        return true;\n    }\n\n    /**\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} ctx\n     * @return {boolean} true if moveNextToken() would return false without changing pos\n     */\n    function isAtEnd(ctx) {\n        var eol = ctx.editor.getLine(ctx.pos.line).length;\n        return (ctx.pos.ch >= eol || ctx.token.end >= eol) && (ctx.pos.line >= ctx.editor.lineCount() - 1);\n    }\n\n   /**\n     * Moves the given context in the given direction, skipping any whitespace it hits.\n     * @param {function} moveFxn the function to move the context\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function moveSkippingWhitespace(moveFxn, ctx) {\n        if (!moveFxn(ctx)) {\n            return false;\n        }\n        while (!ctx.token.type && !/\\S/.test(ctx.token.string)) {\n            if (!moveFxn(ctx)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * In the given context, get the character offset of pos from the start of the token.\n     * @param {!{editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}} context\n     * @return {number}\n     */\n    function offsetInToken(ctx) {\n        var offset = ctx.pos.ch - ctx.token.start;\n        if (offset < 0) {\n            console.log(\"CodeHintUtils: _offsetInToken - Invalid context: pos not in the current token!\");\n        }\n        return offset;\n    }\n\n    /**\n     * Returns the mode object and mode name string at a given position\n     * @param {!CodeMirror} cm CodeMirror instance\n     * @param {!{line:number, ch:number}} pos Position to query for mode\n     * @param {boolean} precise If given, results in more current results. Suppresses caching.\n     * @return {mode:{Object}, name:string}\n     */\n    function getModeAt(cm, pos, precise) {\n        precise = precise || true;\n        var modeData = cm.getMode(),\n            name;\n\n        if (modeData.innerMode) {\n            modeData = CodeMirror.innerMode(modeData, getTokenAt(cm, pos, precise).state).mode;\n        }\n\n        name = (modeData.name === \"xml\") ?\n                modeData.configuration : modeData.name;\n\n        return {mode: modeData, name: name};\n    }\n\n    exports.getTokenAt              = getTokenAt;\n    exports.movePrevToken           = movePrevToken;\n    exports.moveNextToken           = moveNextToken;\n    exports.isAtStart               = isAtStart;\n    exports.isAtEnd                 = isAtEnd;\n    exports.moveSkippingWhitespace  = moveSkippingWhitespace;\n    exports.getInitialContext       = getInitialContext;\n    exports.offsetInToken           = offsetInToken;\n    exports.getModeAt               = getModeAt;\n});\n"
  },
  {
    "path": "src/utils/UpdateNotification.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n *  Utilities functions for displaying update notifications\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Dialogs              = require(\"widgets/Dialogs\"),\n        DefaultDialogs       = require(\"widgets/DefaultDialogs\"),\n        ExtensionManager     = require(\"extensibility/ExtensionManager\"),\n        PreferencesManager   = require(\"preferences/PreferencesManager\"),\n        NativeApp            = require(\"utils/NativeApp\"),\n        Strings              = require(\"strings\"),\n        UpdateDialogTemplate = require(\"text!htmlContent/update-dialog.html\"),\n        UpdateListTemplate   = require(\"text!htmlContent/update-list.html\"),\n        Mustache             = require(\"thirdparty/mustache/mustache\"),\n        HealthLogger         = brackets.getModule(\"utils/HealthLogger\");\n\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    // Private variable to hold the registered update process handler\n    var _updateProcessHandler = null;\n\n    // Private variable to hold the default update process handler\n    var _defaultUpdateProcessHandler = function(updateInfo) {\n        if (updateInfo) {\n            // The first entry in the updates array has the latest download link\n            NativeApp.openURLInDefaultBrowser(updateInfo[0].downloadURL);\n        }\n    };\n    // duration of one day in milliseconds\n    var ONE_DAY = 1000 * 60 * 60 * 24;\n\n    // duration of two minutes in milliseconds\n    var TWO_MINUTES = 1000 * 60 * 2;\n\n    // Extract current build number from package.json version field 0.0.0-0\n    var _buildNumber = Number(/-([0-9]+)/.exec(brackets.metadata.version)[1]);\n\n    var eventNames = {\n        AUTOUPDATE_CANCEL_CLICK: \"UserClickCancelInUpdateDialog\",\n        AUTOUPDATE_UPDATENOW_CLICK: \"UserClickUpdateNowInUpdateDialog\",\n        AUTOUPDATE_UPDATE_AVAILABLE_DIALOG_BOX_RENDERED: \"UpdateAvailableDialogBoxRendered\"\n    };\n    // Init default last build number\n    PreferencesManager.stateManager.definePreference(\"lastNotifiedBuildNumber\", \"number\", 0);\n\n    // Init default last info URL fetch time\n    PreferencesManager.stateManager.definePreference(\"lastInfoURLFetchTime\", \"number\", 0);\n\n    // Time of last registry check for update\n    PreferencesManager.stateManager.definePreference(\"lastExtensionRegistryCheckTime\", \"number\", 0);\n    // Data about available updates in the registry\n    PreferencesManager.stateManager.definePreference(\"extensionUpdateInfo\", \"Array\", []);\n\n    // URL to load version info from. By default this is loaded no more than once a day. If\n    // you force an update check it is always loaded.\n\n    // Information on all posted builds of Brackets. This is an Array, where each element is\n    // an Object with the following fields:\n    //\n    //  {Number} buildNumber Number of the build\n    //  {String} versionString String representation of the build number (ie \"Release 0.40\")\n    //  {String} dateString Date of the build\n    //  {String} releaseNotesURL URL of the release notes for this build\n    //  {String} downloadURL URL to download this build\n    //  {Array} newFeatures Array of new features in this build. Each entry has two fields:\n    //      {String} name Name of the feature\n    //      {String} description Description of the feature\n    //\n    // This array must be reverse sorted by buildNumber (newest build info first)\n\n    /**\n     * @private\n     * Flag that indicates if we've added a click handler to the update notification icon.\n     */\n    var _addedClickHandler = false;\n\n    /**\n     * Construct a new version update url with the given locale.\n     *\n     * @param {string=} locale - optional locale, defaults to 'brackets.getLocale()' when omitted.\n     * @param {boolean=} removeCountryPartOfLocale - optional, remove existing country information from locale 'en-gb' => 'en'\n     * return {string} the new version update url\n     */\n    function _getVersionInfoUrl(locale, removeCountryPartOfLocale) {\n\n        locale = locale || brackets.getLocale();\n\n        if (removeCountryPartOfLocale) {\n            locale = locale.substring(0, 2);\n        }\n\n        return brackets.config.update_info_url.replace('<locale>', locale || 'en');\n    }\n\n    /**\n     * Get a data structure that has information for all builds of Brackets.\n     *\n     * If force is true, the information is always fetched from _versionInfoURL.\n     * If force is false, we try to use cached information. If more than\n     * 24 hours have passed since the last fetch, or if cached data can't be found,\n     * the data is fetched again.\n     *\n     * If new data is fetched and dontCache is false, the data is saved in preferences\n     * for quick fetching later.\n     * _versionInfoUrl is used for unit testing.\n     */\n    function _getUpdateInformation(force, dontCache, _versionInfoUrl) {\n        // Last time the versionInfoURL was fetched\n        var lastInfoURLFetchTime = PreferencesManager.getViewState(\"lastInfoURLFetchTime\");\n\n        var result = new $.Deferred();\n        var fetchData = false;\n        var data;\n\n        // If force is true, always fetch\n        if (force) {\n            fetchData = true;\n        }\n\n        // If we don't have data saved in prefs, fetch\n        data = PreferencesManager.getViewState(\"updateInfo\");\n        if (!data) {\n            fetchData = true;\n        }\n\n        // If more than 24 hours have passed since our last fetch, fetch again\n        if ((new Date()).getTime() > lastInfoURLFetchTime + ONE_DAY) {\n            fetchData = true;\n        }\n\n        if (fetchData) {\n            var lookupPromise = new $.Deferred(),\n                localVersionInfoUrl;\n\n            // If the current locale isn't \"en\" or \"en-US\", check whether we actually have a\n            //   locale-specific update notification, and fall back to \"en\" if not.\n            // Note: we check for both \"en\" and \"en-US\" to watch for the general case or\n            //    country-specific English locale.  The former appears default on Mac, while\n            //    the latter appears default on Windows.\n            var locale = brackets.getLocale().toLowerCase();\n            if (locale !== \"en\" && locale !== \"en-us\") {\n                localVersionInfoUrl = _versionInfoUrl || _getVersionInfoUrl();\n                $.ajax({\n                    url: localVersionInfoUrl,\n                    cache: false,\n                    type: \"HEAD\"\n                }).fail(function (jqXHR, status, error) {\n                    // get rid of any country information from locale and try again\n                    var tmpUrl = _getVersionInfoUrl(brackets.getLocale(), true);\n                    if (tmpUrl !== localVersionInfoUrl) {\n                        $.ajax({\n                            url: tmpUrl,\n                            cache: false,\n                            type: \"HEAD\"\n                        }).fail(function (jqXHR, status, error) {\n                            localVersionInfoUrl = _getVersionInfoUrl(\"en\");\n                        }).done(function (jqXHR, status, error) {\n                            localVersionInfoUrl = tmpUrl;\n                        }).always(function (jqXHR, status, error) {\n                            lookupPromise.resolve();\n                        });\n                    } else {\n                        localVersionInfoUrl = _getVersionInfoUrl(\"en\");\n                        lookupPromise.resolve();\n                    }\n                }).done(function (jqXHR, status, error) {\n                    lookupPromise.resolve();\n                });\n            } else {\n                localVersionInfoUrl = _versionInfoUrl || _getVersionInfoUrl(\"en\");\n                lookupPromise.resolve();\n            }\n\n            lookupPromise.done(function () {\n                $.ajax({\n                    url: localVersionInfoUrl,\n                    dataType: \"json\",\n                    cache: false\n                }).done(function (updateInfo, textStatus, jqXHR) {\n                    if (!dontCache) {\n                        lastInfoURLFetchTime = (new Date()).getTime();\n                        PreferencesManager.setViewState(\"lastInfoURLFetchTime\", lastInfoURLFetchTime);\n                        PreferencesManager.setViewState(\"updateInfo\", updateInfo);\n                    }\n                    result.resolve(updateInfo);\n                }).fail(function (jqXHR, status, error) {\n                    // When loading data for unit tests, the error handler is\n                    // called but the responseText is valid. Try to use it here,\n                    // but *don't* save the results in prefs.\n\n                    if (!jqXHR.responseText) {\n                        // Text is NULL or empty string, reject().\n                        result.reject();\n                        return;\n                    }\n\n                    try {\n                        data = JSON.parse(jqXHR.responseText);\n                        result.resolve(data);\n                    } catch (e) {\n                        result.reject();\n                    }\n                });\n            });\n        } else {\n            result.resolve(data);\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * Checks whether a build is applicable to the current platform.\n     */\n    function _checkBuildApplicability(buildInfo) {\n        return !buildInfo.platforms || buildInfo.platforms[brackets.getPlatformInfo()];\n    }\n\n    /**\n     * Return a new array of version information that is newer than \"buildNumber\".\n     * Returns null if there is no new version information.\n     */\n    function _stripOldVersionInfo(versionInfo, buildNumber) {\n        // Do a simple linear search. Since we are going in reverse-chronological order, we\n        // should get through the search quickly.\n        var lastIndex = 0;\n        var len = versionInfo.length;\n        var versionEntry;\n        var validBuildEntries;\n\n        while (lastIndex < len) {\n            versionEntry = versionInfo[lastIndex];\n            if (versionEntry.buildNumber <= buildNumber) {\n                break;\n            }\n            lastIndex++;\n        }\n\n        if (lastIndex > 0) {\n            // Filter recent update entries based on applicability to current platform\n            validBuildEntries = versionInfo.slice(0, lastIndex).filter(_checkBuildApplicability);\n        }\n\n        return validBuildEntries;\n    }\n\n    /**\n     * Show a dialog that shows the update\n     */\n    function _showUpdateNotificationDialog(updates, force) {\n        Dialogs.showModalDialogUsingTemplate(Mustache.render(UpdateDialogTemplate, Strings))\n            .done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_DOWNLOAD) {\n                    HealthLogger.sendAnalyticsData(\n                        eventNames.AUTOUPDATE_UPDATENOW_CLICK,\n                        \"autoUpdate\",\n                        \"updateNotification\",\n                        \"updateNow\",\n                        \"click\"\n                    );\n                    handleUpdateProcess(updates);\n                } else {\n                    HealthLogger.sendAnalyticsData(\n                        eventNames.AUTOUPDATE_CANCEL_CLICK,\n                        \"autoUpdate\",\n                        \"updateNotification\",\n                        \"cancel\",\n                        \"click\"\n                    );\n                }\n            });\n\n        // Populate the update data\n        var $dlg        = $(\".update-dialog.instance\"),\n            $updateList = $dlg.find(\".update-info\"),\n            subTypeString = force ? \"userAction\" : \"auto\";\n\n        // Make the update notification icon clickable again\n        _addedClickHandler = false;\n\n        updates.Strings = Strings;\n        $updateList.html(Mustache.render(UpdateListTemplate, updates));\n        HealthLogger.sendAnalyticsData(\n            eventNames.AUTOUPDATE_UPDATE_AVAILABLE_DIALOG_BOX_RENDERED,\n            \"autoUpdate\",\n            \"updateNotification\",\n            \"render\",\n            subTypeString\n        );\n    }\n\n    /**\n     * Calculate state of notification everytime registries are downloaded - no matter who triggered the download\n     */\n    function _onRegistryDownloaded() {\n        var availableUpdates = ExtensionManager.getAvailableUpdates();\n        PreferencesManager.setViewState(\"extensionUpdateInfo\", availableUpdates);\n        PreferencesManager.setViewState(\"lastExtensionRegistryCheckTime\", (new Date()).getTime());\n        $(\"#toolbar-extension-manager\").toggleClass(\"updatesAvailable\", availableUpdates.length > 0);\n    }\n\n    /**\n     *  Every 24 hours downloads registry information to check for update, but only if the registry download\n     *  wasn't triggered by another action (like opening extension manager)\n     *  If there isn't 24 hours elapsed from the last download, use cached information from last download\n     *  to determine state of the update notification.\n     */\n    function checkForExtensionsUpdate() {\n        var lastExtensionRegistryCheckTime = PreferencesManager.getViewState(\"lastExtensionRegistryCheckTime\"),\n            timeOfNextCheck = lastExtensionRegistryCheckTime + ONE_DAY,\n            currentTime = (new Date()).getTime();\n\n        // update icon according to previously saved information\n        var availableUpdates = PreferencesManager.getViewState(\"extensionUpdateInfo\");\n        availableUpdates = ExtensionManager.cleanAvailableUpdates(availableUpdates);\n        $(\"#toolbar-extension-manager\").toggleClass(\"updatesAvailable\", availableUpdates.length > 0);\n\n        if (availableUpdates.length === 0) {\n            // icon is gray, no updates available\n            if (currentTime > timeOfNextCheck) {\n                // downloadRegistry, will be resolved in _onRegistryDownloaded\n                ExtensionManager.downloadRegistry().done(function () {\n                    // schedule another check in 24 hours + 2 minutes\n                    setTimeout(checkForExtensionsUpdate, ONE_DAY + TWO_MINUTES);\n                });\n            } else {\n                // schedule the download of the registry in appropriate time\n                setTimeout(checkForExtensionsUpdate, (timeOfNextCheck - currentTime) + TWO_MINUTES);\n            }\n        }\n    }\n\n    /**\n     *\n     * @param {boolean} enable when false Update Notification Icon in\n                        TollBar will grayed and Click will be blocked.\n                        when true icon will be green and clickable.\n     */\n    function enableUpdateNotificationIcon(enable) {\n        var $updateNotification = $(\"#update-notification\");\n        _addedClickHandler = !enable;\n\n        $updateNotification.toggleClass(\"update-in-progress\", !enable);\n    }\n\n    /**\n     * Check for updates. If \"force\" is true, update notification dialogs are always displayed\n     * (if an update is available). If \"force\" is false, the update notification is only\n     * displayed for newly available updates.\n     *\n     * If an update is available, show the \"update available\" notification icon in the title bar.\n     *\n     * @param {boolean} force If true, always show the notification dialog.\n     * @param {Object} _testValues This should only be used for testing purposes. See comments for details.\n     * @return {$.Promise} jQuery Promise object that is resolved or rejected after the update check is complete.\n     */\n    function checkForUpdate(force, _testValues) {\n        // This is the last version we notified the user about. If checkForUpdate()\n        // is called with \"false\", only show the update notification dialog if there\n        // is an update newer than this one. This value is saved in preferences.\n        var lastNotifiedBuildNumber = PreferencesManager.getViewState(\"lastNotifiedBuildNumber\");\n\n        // The second param, if non-null, is an Object containing value overrides. Values\n        // in the object temporarily override the local values. This should *only* be used for testing.\n        // If any overrides are set, permanent changes are not made (including showing\n        // the update notification icon and saving prefs).\n        var oldValues;\n        var usingOverrides = false; // true if any of the values are overridden.\n        var result = new $.Deferred();\n        var versionInfoUrl;\n\n        if (_testValues) {\n            oldValues = {};\n\n            if (_testValues.hasOwnProperty(\"_buildNumber\")) {\n                oldValues._buildNumber = _buildNumber;\n                _buildNumber = _testValues._buildNumber;\n                usingOverrides = true;\n            }\n\n            if (_testValues.hasOwnProperty(\"lastNotifiedBuildNumber\")) {\n                oldValues.lastNotifiedBuildNumber = lastNotifiedBuildNumber;\n                lastNotifiedBuildNumber = _testValues.lastNotifiedBuildNumber;\n                usingOverrides = true;\n            }\n\n            if (_testValues.hasOwnProperty(\"_versionInfoURL\")) {\n                versionInfoUrl = _testValues._versionInfoURL;\n                usingOverrides = true;\n            }\n        }\n\n        _getUpdateInformation(force || usingOverrides, usingOverrides, versionInfoUrl)\n            .done(function (versionInfo) {\n                // Get all available updates\n                var allUpdates = _stripOldVersionInfo(versionInfo, _buildNumber);\n\n                // When running directly from GitHub source (as opposed to\n                // an installed build), _buildNumber is 0. In this case, if the\n                // test is not forced, don't show the update notification icon or\n                // dialog.\n                if (_buildNumber === 0 && !force) {\n                    result.resolve();\n                    return;\n                }\n\n                if (allUpdates && allUpdates.length > 0) {\n                    // Always show the \"update available\" icon if any updates are available\n                    var $updateNotification = $(\"#update-notification\");\n\n                    $updateNotification.css(\"display\", \"block\");\n\n                    $updateNotification.on(\"click\", function () {\n                        // Block the click until the Notification Dialog opens\n                        if (!_addedClickHandler) {\n                            _addedClickHandler = true;\n                            checkForUpdate(true);\n                        }\n                    });\n\n                    // Only show the update dialog if force = true, or if the user hasn't been\n                    // alerted of this update\n                    if (force || allUpdates[0].buildNumber >  lastNotifiedBuildNumber) {\n                        _showUpdateNotificationDialog(allUpdates, force);\n\n                        // Update prefs with the last notified build number\n                        lastNotifiedBuildNumber = allUpdates[0].buildNumber;\n                        // Don't save prefs is we have overridden values\n                        if (!usingOverrides) {\n                            PreferencesManager.setViewState(\"lastNotifiedBuildNumber\", lastNotifiedBuildNumber);\n                        }\n                    }\n                } else if (force) {\n                    // No updates are available. If force == true, let the user know.\n                    Dialogs.showModalDialog(\n                        DefaultDialogs.DIALOG_ID_ERROR,\n                        Strings.NO_UPDATE_TITLE,\n                        Strings.NO_UPDATE_MESSAGE\n                    );\n                }\n\n                if (oldValues) {\n                    if (oldValues.hasOwnProperty(\"_buildNumber\")) {\n                        _buildNumber = oldValues._buildNumber;\n                    }\n                    if (oldValues.hasOwnProperty(\"lastNotifiedBuildNumber\")) {\n                        lastNotifiedBuildNumber = oldValues.lastNotifiedBuildNumber;\n                    }\n                }\n                result.resolve();\n            })\n            .fail(function () {\n                // Error fetching the update data. If this is a forced check, alert the user\n                if (force) {\n                    Dialogs.showModalDialog(\n                        DefaultDialogs.DIALOG_ID_ERROR,\n                        Strings.ERROR_FETCHING_UPDATE_INFO_TITLE,\n                        Strings.ERROR_FETCHING_UPDATE_INFO_MSG\n                    );\n                }\n                result.reject();\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * Handles the update process\n     * @param {Array} updates - array object containing info of updates\n     */\n    function handleUpdateProcess(updates) {\n        var handler = _updateProcessHandler || _defaultUpdateProcessHandler;\n        var initSuccess = handler(updates);\n        if (_updateProcessHandler && !initSuccess) {\n            // Give a chance to default handler in case\n            // the auot update mechanism has failed.\n            _defaultUpdateProcessHandler(updates);\n        }\n    }\n\n    /**\n     * Launches both check for Brackets update and check for installed extensions update\n     */\n    function launchAutomaticUpdate() {\n        // launch immediately and then every 24 hours + 2 minutes\n        checkForUpdate();\n        checkForExtensionsUpdate();\n        window.setInterval(checkForUpdate, ONE_DAY + TWO_MINUTES);\n    }\n\n    /**\n     * Registers the update process handler function\n     * @param {function} handler - function for update process handler\n     */\n    function registerUpdateHandler(handler) {\n        _updateProcessHandler = handler;\n    }\n\n    /**\n     * Utility function to reset back to the default update handler\n     */\n    function resetToDefaultUpdateHandler() {\n        _updateProcessHandler = null;\n    }\n\n    // Events listeners\n    ExtensionManager.on(\"registryDownload\", _onRegistryDownloaded);\n\n    // Define public API\n    exports.registerUpdateHandler = registerUpdateHandler;\n    exports.resetToDefaultUpdateHandler = resetToDefaultUpdateHandler;\n    exports.launchAutomaticUpdate = launchAutomaticUpdate;\n    exports.checkForUpdate        = checkForUpdate;\n    exports.enableUpdateNotificationIcon = enableUpdateNotificationIcon;\n});\n"
  },
  {
    "path": "src/utils/UrlParams.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    /**\n     * Convert between URL querystring and name/value pairs. Decodes and encodes URL parameters.\n     */\n    function UrlParams() {\n        this._store = {};\n    }\n\n    /**\n     * Parse the window location by default. Optionally specify a URL to parse.\n     * @param {string} url\n     */\n    UrlParams.prototype.parse = function (url) {\n        var queryString = \"\",\n            urlParams,\n            p,\n            self = this;\n\n        self._store = {};\n\n        if (!url) {\n            queryString = window.document.location.search.substring(1);\n        } else if (url.indexOf(\"?\") !== -1) {\n            queryString = url.substring(url.indexOf(\"?\") + 1);\n        }\n\n        queryString = queryString.trimRight();\n\n        if (queryString) {\n            urlParams = queryString.split(\"&\");\n\n            urlParams.forEach(function (param) {\n                p = param.split(\"=\");\n                p[1] = p[1] || \"\";\n                self._store[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);\n            });\n        }\n    };\n\n    /**\n     * Store a name/value string pair\n     * @param {!string} name\n     * @param {!string} value\n     */\n    UrlParams.prototype.put = function (name, value) {\n        this._store[name] = value;\n    };\n\n    /**\n     * Retrieve a value by name\n     * @param {!string} name\n     * @return {string}\n     */\n    UrlParams.prototype.get = function (name) {\n        return this._store[name];\n    };\n\n    /**\n     * Remove a name/value string pair\n     * @param {!string} name\n     */\n    UrlParams.prototype.remove = function (name) {\n        delete this._store[name];\n    };\n\n    /**\n     * Returns true if the parameter list is empty, else returns false.\n     * @return {boolean}\n     */\n    UrlParams.prototype.isEmpty = function (name) {\n        return _.isEmpty(this._store);\n    };\n\n    /**\n     * Encode name/value pairs as URI components.\n     * @return {string}\n     */\n    UrlParams.prototype.toString = function () {\n        var strs = [],\n            self = this;\n\n        _.forEach(self._store, function (value, key) {\n            strs.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(value));\n        });\n\n        return strs.join(\"&\");\n    };\n\n    // Define public API\n    exports.UrlParams = UrlParams;\n});\n"
  },
  {
    "path": "src/utils/ValidationUtils.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n\n    /**\n     * Used to validate whether type of unknown value is an integer.\n     *\n     * @param {*} value Value for which to validate its type\n     * @return {boolean} true if value is a finite integer\n     */\n    function isInteger(value) {\n        // Validate value is a number\n        if (typeof (value) !== \"number\" || isNaN(parseInt(value, 10))) {\n            return false;\n        }\n\n        // Validate number is an integer\n        if (Math.floor(value) !== value) {\n            return false;\n        }\n\n        // Validate number is finite\n        if (!isFinite(value)) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Used to validate whether type of unknown value is an integer, and, if so,\n     * is it within the option lower and upper limits.\n     *\n     * @param {*} value Value for which to validate its type\n     * @param {number=} lowerLimit Optional lower limit (inclusive)\n     * @param {number=} upperLimit Optional upper limit (inclusive)\n     * @return {boolean} true if value is an interger, and optionally in specified range.\n     */\n    function isIntegerInRange(value, lowerLimit, upperLimit) {\n        // Validate value is an integer\n        if (!isInteger(value)) {\n            return false;\n        }\n\n        // Validate integer is in range\n        var hasLowerLimt = (typeof (lowerLimit) === \"number\"),\n            hasUpperLimt = (typeof (upperLimit) === \"number\");\n\n        return ((!hasLowerLimt || value >= lowerLimit) && (!hasUpperLimt || value <= upperLimit));\n    }\n\n\n    // Define public API\n    exports.isInteger               = isInteger;\n    exports.isIntegerInRange        = isIntegerInRange;\n});\n"
  },
  {
    "path": "src/utils/ViewUtils.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                   = require(\"thirdparty/lodash\"),\n        LanguageManager     = require(\"language/LanguageManager\");\n\n    var SCROLL_SHADOW_HEIGHT = 5;\n\n    /**\n     * @private\n     */\n    var _resizeHandlers = [];\n\n    /**\n     * Positions shadow background elements to indicate vertical scrolling.\n     * @param {!DOMElement} $displayElement the DOMElement that displays the shadow\n     * @param {!Object} $scrollElement the object that is scrolled\n     * @param {!DOMElement} $shadowTop div .scroller-shadow.top\n     * @param {!DOMElement} $shadowBottom div .scroller-shadow.bottom\n     * @param {boolean} isPositionFixed When using absolute position, top remains at 0.\n     */\n    function _updateScrollerShadow($displayElement, $scrollElement, $shadowTop, $shadowBottom, isPositionFixed) {\n        var offsetTop           = 0,\n            scrollElement       = $scrollElement.get(0),\n            scrollTop           = scrollElement.scrollTop,\n            topShadowOffset     = Math.min(scrollTop - SCROLL_SHADOW_HEIGHT, 0),\n            displayElementWidth = $displayElement.width();\n\n        if ($shadowTop) {\n            $shadowTop.css(\"background-position\", \"0px \" + topShadowOffset + \"px\");\n\n            if (isPositionFixed) {\n                offsetTop = $displayElement.offset().top;\n                $shadowTop.css(\"top\", offsetTop);\n            }\n\n            if (isPositionFixed) {\n                $shadowTop.css(\"width\", displayElementWidth);\n            }\n        }\n\n        if ($shadowBottom) {\n            var clientHeight        = scrollElement.clientHeight,\n                outerHeight         = $displayElement.outerHeight(),\n                scrollHeight        = scrollElement.scrollHeight,\n                bottomShadowOffset  = SCROLL_SHADOW_HEIGHT; // outside of shadow div viewport\n\n            if (scrollHeight > clientHeight) {\n                bottomShadowOffset -= Math.min(SCROLL_SHADOW_HEIGHT, (scrollHeight - (scrollTop + clientHeight)));\n            }\n\n            $shadowBottom.css(\"background-position\", \"0px \" + bottomShadowOffset + \"px\");\n            $shadowBottom.css(\"top\", offsetTop + outerHeight - SCROLL_SHADOW_HEIGHT);\n            $shadowBottom.css(\"width\", displayElementWidth);\n        }\n    }\n\n    function getOrCreateShadow($displayElement, position, isPositionFixed) {\n        var $findShadow = $displayElement.find(\".scroller-shadow.\" + position);\n\n        if ($findShadow.length === 0) {\n            $findShadow = $(window.document.createElement(\"div\")).addClass(\"scroller-shadow \" + position);\n            $displayElement.append($findShadow);\n        }\n\n        if (!isPositionFixed) {\n            // position is fixed by default\n            $findShadow.css(\"position\", \"absolute\");\n            $findShadow.css(position, \"0\");\n        }\n\n        return $findShadow;\n    }\n\n    /**\n     * Installs event handlers for updatng shadow background elements to indicate vertical scrolling.\n     * @param {!DOMElement} displayElement the DOMElement that displays the shadow. Must fire\n     *  \"contentChanged\" events when the element is resized or repositioned.\n     * @param {?Object} scrollElement the object that is scrolled. Must fire \"scroll\" events\n     *  when the element is scrolled. If null, the displayElement is used.\n     * @param {?boolean} showBottom optionally show the bottom shadow\n     */\n    function addScrollerShadow(displayElement, scrollElement, showBottom) {\n        // use fixed positioning when the display and scroll elements are the same\n        var isPositionFixed = false;\n\n        if (!scrollElement) {\n            scrollElement = displayElement;\n            isPositionFixed = true;\n        }\n\n        // update shadows when the scrolling element is scrolled\n        var $displayElement = $(displayElement),\n            $scrollElement = $(scrollElement);\n\n        var $shadowTop = getOrCreateShadow($displayElement, \"top\", isPositionFixed);\n        var $shadowBottom = (showBottom) ? getOrCreateShadow($displayElement, \"bottom\", isPositionFixed) : null;\n\n        var doUpdate = function () {\n            _updateScrollerShadow($displayElement, $scrollElement, $shadowTop, $shadowBottom, isPositionFixed);\n        };\n\n        // remove any previously installed listeners on this node\n        $scrollElement.off(\"scroll.scroller-shadow\");\n        $displayElement.off(\"contentChanged.scroller-shadow\");\n\n        // add new ones\n        $scrollElement.on(\"scroll.scroller-shadow\", doUpdate);\n        $displayElement.on(\"contentChanged.scroller-shadow\", doUpdate);\n\n        // update immediately\n        doUpdate();\n    }\n\n    /**\n     * Remove scroller-shadow effect.\n     * @param {!DOMElement} displayElement the DOMElement that displays the shadow\n     * @param {?Object} scrollElement the object that is scrolled\n     */\n    function removeScrollerShadow(displayElement, scrollElement) {\n        if (!scrollElement) {\n            scrollElement = displayElement;\n        }\n\n        var $displayElement = $(displayElement),\n            $scrollElement = $(scrollElement);\n\n        // remove scrollerShadow elements from DOM\n        $displayElement.find(\".scroller-shadow.top\").remove();\n        $displayElement.find(\".scroller-shadow.bottom\").remove();\n\n        // remove event handlers\n        $scrollElement.off(\"scroll.scroller-shadow\");\n        $displayElement.off(\"contentChanged.scroller-shadow\");\n    }\n\n    /**\n     * Utility function to replace jQuery.toggleClass when used with the second argument, which needs to be a true boolean for jQuery\n     * @param {!jQueryObject} $domElement The jQueryObject to toggle the Class on\n     * @param {!string} className Class name or names (separated by spaces) to toggle\n     * @param {!boolean} addClass A truthy value to add the class and a falsy value to remove the class\n     */\n    function toggleClass($domElement, className, addClass) {\n        if (addClass) {\n            $domElement.addClass(className);\n        } else {\n            $domElement.removeClass(className);\n        }\n    }\n\n    /**\n     * Within a scrolling DOMElement, creates and positions a styled selection\n     * div to align a single selected list item from a ul list element.\n     *\n     * Assumptions:\n     * - scrollerElement is a child of the #sidebar div\n     * - ul list element fires a \"selectionChanged\" event after the\n     *   selectedClassName is assigned to a new list item\n     *\n     * @param {!DOMElement} scrollElement A DOMElement containing a ul list element\n     * @param {!string} selectedClassName A CSS class name on at most one list item in the contained list\n     */\n    function sidebarList($scrollerElement, selectedClassName, leafClassName) {\n        var $listElement = $scrollerElement.find(\"ul\"),\n            $selectionMarker,\n            $selectionExtension,\n            $sidebar = $(\"#sidebar\"),\n            showExtension = true;\n\n        // build selectionMarker and position absolute within the scroller\n        $selectionMarker = $(window.document.createElement(\"div\")).addClass(\"sidebar-selection\");\n        $scrollerElement.prepend($selectionMarker);\n\n        // enable scrolling\n        $scrollerElement.css(\"overflow\", \"auto\");\n\n        // use relative postioning for clipping the selectionMarker within the scrollElement\n        $scrollerElement.css(\"position\", \"relative\");\n\n        // build selectionExtension and position fixed to the window\n        $selectionExtension = $(window.document.createElement(\"div\")).addClass(\"sidebar-selection-extension\");\n\n        $scrollerElement.append($selectionExtension);\n\n        selectedClassName = \".\" + (selectedClassName || \"selected\");\n\n        var updateSelectionExtension = function () {\n            var selectionMarkerHeight = $selectionMarker.height(),\n                selectionMarkerOffset = $selectionMarker.offset(),  // offset relative to *document*\n                scrollerOffset = $scrollerElement.offset(),\n                selectionExtensionHeight = $selectionExtension.outerHeight(),\n                scrollerTop = scrollerOffset.top,\n                scrollerBottom = scrollerTop + $scrollerElement.outerHeight(),\n                selectionExtensionTop = selectionMarkerOffset.top;\n\n            $selectionExtension.css(\"top\", selectionExtensionTop);\n            $selectionExtension.css(\"left\", $sidebar.width() - $selectionExtension.outerWidth());\n            toggleClass($selectionExtension, \"selectionExtension-visible\", showExtension);\n\n            var selectionExtensionClipOffsetYBy = Math.floor((selectionMarkerHeight - selectionExtensionHeight) / 2),\n                selectionExtensionBottom = selectionExtensionTop + selectionExtensionHeight + selectionExtensionClipOffsetYBy;\n\n            if (selectionExtensionTop < scrollerTop || selectionExtensionBottom > scrollerBottom) {\n                $selectionExtension.css(\"clip\", \"rect(\" + Math.max(scrollerTop - selectionExtensionTop - selectionExtensionClipOffsetYBy, 0) + \"px, auto, \" +\n                                           (selectionExtensionHeight - Math.max(selectionExtensionBottom - scrollerBottom, 0)) + \"px, auto)\");\n            } else {\n                $selectionExtension.css(\"clip\", \"\");\n            }\n        };\n\n        var hideSelectionMarker = function (event) {\n            $selectionExtension.addClass(\"forced-hidden\");\n            $selectionMarker.addClass(\"forced-hidden\");\n        };\n\n        var updateSelectionMarker = function (event, reveal) {\n            // find the selected list item\n            var $listItem = $listElement.find(selectedClassName).closest(\"li\");\n\n            if (leafClassName) {\n                showExtension = $listItem.hasClass(leafClassName);\n            }\n\n            $selectionExtension.removeClass(\"forced-hidden\");\n            $selectionMarker.removeClass(\"forced-hidden\");\n\n            // always hide selection visuals first to force layout (issue #719)\n            $selectionExtension.hide();\n            $selectionMarker.hide();\n\n            if ($listItem.length === 1) {\n                // list item position is relative to scroller\n                var selectionMarkerTop = $listItem.offset().top - $scrollerElement.offset().top + $scrollerElement.get(0).scrollTop;\n\n                // move the selectionMarker position to align with the list item\n                $selectionMarker.css(\"top\", selectionMarkerTop);\n                $selectionMarker.show();\n\n                updateSelectionExtension();\n                $selectionExtension.show();\n\n                // fully scroll to the selectionMarker if it's not initially in the viewport\n                var scrollerElement = $scrollerElement.get(0),\n                    scrollerHeight = scrollerElement.clientHeight,\n                    selectionMarkerHeight = $selectionMarker.height(),\n                    selectionMarkerBottom = selectionMarkerTop + selectionMarkerHeight,\n                    currentScrollBottom = scrollerElement.scrollTop + scrollerHeight;\n\n                // update scrollTop to reveal the selected list item\n                if (reveal) {\n                    if (selectionMarkerTop >= currentScrollBottom) {\n                        $listItem.get(0).scrollIntoView(false);\n                    } else if (selectionMarkerBottom <= scrollerElement.scrollTop) {\n                        $listItem.get(0).scrollIntoView(true);\n                    }\n                }\n            }\n        };\n\n        $listElement.on(\"selectionChanged\", updateSelectionMarker);\n        $scrollerElement.on(\"scroll\", updateSelectionExtension);\n        $scrollerElement.on(\"selectionRedraw\", updateSelectionExtension);\n        $scrollerElement.on(\"selectionHide\", hideSelectionMarker);\n\n        // update immediately\n        updateSelectionMarker();\n\n        // update clipping when the window resizes\n        _resizeHandlers.push(updateSelectionExtension);\n    }\n\n    /**\n     * @private\n     */\n    function _handleResize() {\n        _resizeHandlers.forEach(function (f) {\n            f.apply();\n        });\n    }\n\n    /**\n     * Determine how much of an element rect is clipped in view.\n     *\n     * @param {!DOMElement} $view - A jQuery scrolling container\n     * @param {!{top: number, left: number, height: number, width: number}}\n     *          elementRect - rectangle of element's default position/size\n     * @return {{top: number, right: number, bottom: number, left: number}}\n     *          amount element rect is clipped in each direction\n     */\n    function getElementClipSize($view, elementRect) {\n        var delta,\n            clip = { top: 0, right: 0, bottom: 0, left: 0 },\n            viewOffset = $view.offset() || { top: 0, left: 0};\n\n        // Check if element extends below viewport\n        delta = (elementRect.top + elementRect.height) - (viewOffset.top + $view.height());\n        if (delta > 0) {\n            clip.bottom = delta;\n        }\n\n        // Check if element extends above viewport\n        delta = viewOffset.top - elementRect.top;\n        if (delta > 0) {\n            clip.top = delta;\n        }\n\n        // Check if element extends to the left of viewport\n        delta = viewOffset.left - elementRect.left;\n        if (delta > 0) {\n            clip.left = delta;\n        }\n\n        // Check if element extends to the right of viewport\n        delta = (elementRect.left + elementRect.width) - (viewOffset.left + $view.width());\n        if (delta > 0) {\n            clip.right = delta;\n        }\n\n        return clip;\n    }\n\n    /**\n     * Within a scrolling DOMElement, if necessary, scroll element into viewport.\n     *\n     * To Perform the minimum amount of scrolling necessary, cases should be handled as follows:\n     * - element already completely in view : no scrolling\n     * - element above    viewport          : scroll view so element is at top\n     * - element left of  viewport          : scroll view so element is at left\n     * - element below    viewport          : scroll view so element is at bottom\n     * - element right of viewport          : scroll view so element is at right\n     *\n     * Assumptions:\n     * - $view is a scrolling container\n     *\n     * @param {!DOMElement} $view - A jQuery scrolling container\n     * @param {!DOMElement} $element - A jQuery element\n     * @param {?boolean} scrollHorizontal - whether to also scroll horizontally\n     */\n    function scrollElementIntoView($view, $element, scrollHorizontal) {\n        var elementOffset = $element.offset();\n\n        // scroll minimum amount\n        var elementRect = {\n                top:    elementOffset.top,\n                left:   elementOffset.left,\n                height: $element.height(),\n                width:  $element.width()\n            },\n            clip = getElementClipSize($view, elementRect);\n\n        if (clip.bottom > 0) {\n            // below viewport\n            $view.scrollTop($view.scrollTop() + clip.bottom);\n        } else if (clip.top > 0) {\n            // above viewport\n            $view.scrollTop($view.scrollTop() - clip.top);\n        }\n\n        if (scrollHorizontal) {\n            if (clip.left > 0) {\n                $view.scrollLeft($view.scrollLeft() - clip.left);\n            } else if (clip.right > 0) {\n                $view.scrollLeft($view.scrollLeft() + clip.right);\n            }\n        }\n    }\n\n    /**\n     * HTML formats a file entry name  for display in the sidebar.\n     * @param {!File} entry File entry to display\n     * @return {string} HTML formatted string\n     */\n    function getFileEntryDisplay(entry) {\n        var name = entry.name,\n            ext = LanguageManager.getCompoundFileExtension(name),\n            i = name.lastIndexOf(\".\" + ext);\n\n        if (i > 0) {\n            // Escape all HTML-sensitive characters in filename.\n            name = _.escape(name.substring(0, i)) + \"<span class='extension'>\" + _.escape(name.substring(i)) + \"</span>\";\n        } else {\n            name = _.escape(name);\n        }\n\n        return name;\n    }\n\n    /**\n     * Determine the minimum directory path to distinguish duplicate file names\n     * for each file in list.\n     *\n     * @param {Array.<File>} files - list of Files with the same filename\n     * @return {Array.<string>} directory paths to match list of files\n     */\n    function getDirNamesForDuplicateFiles(files) {\n        // Must have at least two files in list for this to make sense\n        if (files.length <= 1) {\n            return [];\n        }\n\n        // First collect paths from the list of files and fill map with them\n        var map = {}, filePaths = [], displayPaths = [];\n        files.forEach(function (file, index) {\n            var fp = file.fullPath.split(\"/\");\n            fp.pop(); // Remove the filename itself\n            displayPaths[index] = fp.pop();\n            filePaths[index] = fp;\n\n            if (!map[displayPaths[index]]) {\n                map[displayPaths[index]] = [index];\n            } else {\n                map[displayPaths[index]].push(index);\n            }\n        });\n\n        // This function is used to loop through map and resolve duplicate names\n        var processMap = function (map) {\n            var didSomething = false;\n            _.forEach(map, function (arr, key) {\n                // length > 1 means we have duplicates that need to be resolved\n                if (arr.length > 1) {\n                    arr.forEach(function (index) {\n                        if (filePaths[index].length !== 0) {\n                            displayPaths[index] = filePaths[index].pop() + \"/\" + displayPaths[index];\n                            didSomething = true;\n\n                            if (!map[displayPaths[index]]) {\n                                map[displayPaths[index]] = [index];\n                            } else {\n                                map[displayPaths[index]].push(index);\n                            }\n                        }\n                    });\n                }\n                delete map[key];\n            });\n            return didSomething;\n        };\n\n        var repeat;\n        do {\n            repeat = processMap(map);\n        } while (repeat);\n\n        return displayPaths;\n    }\n\n    function traverseViewArray(viewArray, startIndex, direction) {\n        if (Math.abs(direction) !== 1) {\n            console.error(\"traverseViewArray called with unsupported direction: \" + direction.toString());\n            return null;\n        }\n        if (startIndex === -1) {\n            // If doc not in view list, return most recent view list item\n            if (viewArray.length > 0) {\n                return viewArray[0];\n            }\n        } else if (viewArray.length > 1) {\n            // If doc is in view list, return next/prev item with wrap-around\n            startIndex += direction;\n            if (startIndex >= viewArray.length) {\n                startIndex = 0;\n            } else if (startIndex < 0) {\n                startIndex = viewArray.length - 1;\n            }\n\n            return viewArray[startIndex];\n        }\n\n        // If no doc open or view list empty, there is no \"next\" file\n        return null;\n    }\n\n    function hideMainToolBar() {\n        $(\"#main-toolbar\").addClass(\"forced-hidden\");\n        $(\".main-view .content\").each(function (index, element) {\n            $(element).addClass(\"force-right-zero\");\n        });\n    }\n\n    function showMainToolBar() {\n        $(\"#main-toolbar\").removeClass(\"forced-hidden\");\n        $(\".main-view .content\").each(function (index, element) {\n            $(element).removeClass(\"force-right-zero\");\n        });\n    }\n\n    // handle all resize handlers in a single listener\n    $(window).resize(_handleResize);\n\n    // Define public API\n    exports.SCROLL_SHADOW_HEIGHT         = SCROLL_SHADOW_HEIGHT;\n    exports.addScrollerShadow            = addScrollerShadow;\n    exports.removeScrollerShadow         = removeScrollerShadow;\n    exports.sidebarList                  = sidebarList;\n    exports.showMainToolBar              = showMainToolBar;\n    exports.hideMainToolBar              = hideMainToolBar;\n    exports.scrollElementIntoView        = scrollElementIntoView;\n    exports.getElementClipSize           = getElementClipSize;\n    exports.getFileEntryDisplay          = getFileEntryDisplay;\n    exports.toggleClass                  = toggleClass;\n    exports.getDirNamesForDuplicateFiles = getDirNamesForDuplicateFiles;\n    exports.traverseViewArray            = traverseViewArray;\n});\n"
  },
  {
    "path": "src/view/MainViewFactory.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * MainViewFactory is a singleton for managing view factories.\n *\n * Registering a view factory:\n *\n *      registerViewFactory({\n *           canOpenFile: function (fullPath) {\n *               return (fullPath.slice(-4) === \".ico\");\n *           },\n *           openFile: function(file, pane) {\n *               return createIconView(file, pane);\n *           }\n *      });\n *\n *  The openFile method is used to open the file and construct\n *  a view of it.  Implementation should add the view to the pane\n *\n *      function createIconView(file, pane) {\n *          // IconView will construct its DOM and append\n *          //  it to pane.$el\n *          var view = new IconView(file, pane.$el);\n *          // Then tell the pane to add it to\n *          //  its view map and show it\n *          pane.addView(view, true);\n *          return new $.Deferred().resolve().promise();\n *      }\n *\n *  Factories should only create 1 view of a file per pane.  Brackets currently only supports 1 view of\n *  a file open at a given time but that may change to allow the same file open in more than 1 pane. Therefore\n *  Factories can do a simple check to see if a view already exists and show it before creating a new one:\n *\n *      var view = pane.getViewForPath(file.fullPath);\n *      if (view) {\n *          pane.showView(view);\n *      } else {\n *          return createIconView(file, pane);\n *      }\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n\n    /**\n     * @typedef {canOpenFile:function(path:string):boolean, openFile:function(path:string, pane:Pane)} Factory\n     */\n\n    /**\n     * The view registration Database\n     * @private\n     * @type {Array.<Factory>}\n     */\n    var _factories = [];\n\n    /**\n     * Registers a view factory\n     * @param {!Factory} factory - the view factory to register\n     */\n    function registerViewFactory(factory) {\n        _factories.push(factory);\n    }\n\n    /**\n     * Finds a factory that can open the specified file\n     * @param {!string} fullPath - the file to open\n     * @return {?Factory} A factory that can create a view for the path or undefined if there isn't one.\n     */\n    function findSuitableFactoryForPath(fullPath) {\n        return _.find(_factories, function (factory) {\n            // This could get more complex in the future by searching in this order\n            //  1) a factory that can open the file by fullPath\n            //  2) a factory that can open the file by name\n            //  3) a factory that can open the file by filetype\n            return factory.canOpenFile(fullPath);\n        });\n    }\n\n    /*\n     * Public API\n     */\n    exports.registerViewFactory         = registerViewFactory;\n    exports.findSuitableFactoryForPath  = findSuitableFactoryForPath;\n});\n"
  },
  {
    "path": "src/view/MainViewManager.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * MainViewManager manages the arrangement of all open panes as well as provides the controller\n * logic behind all views in the MainView (e.g. ensuring that a file doesn't appear in 2 lists)\n *\n * Each pane contains one or more views wich are created by a view factory and inserted into a pane list.\n * There may be several panes managed by the MainViewManager with each pane containing a list of views.\n * The panes are always visible and the layout is determined by the MainViewManager and the user.\n *\n * Currently we support only 2 panes.\n *\n * All of the WorkingSet APIs take a paneId Argument.  This can be an actual pane Id, ALL_PANES (in most cases)\n * or ACTIVE_PANE. ALL_PANES may not be supported for some APIs.  See the API for details.\n *\n * This module dispatches several events:\n *\n *    - activePaneChange - When the active pane changes.  There will always be an active pane.\n *          (e, newPaneId:string, oldPaneId:string)\n *    - currentFileChange -- When the user has switched to another pane, file, document. When the user closes a view\n *      and there are no other views to show the current file will be null.\n *          (e, newFile:File, newPaneId:string, oldFile:File, oldPaneId:string)\n *    - paneLayoutChange -- When Orientation changes.\n *          (e, orientation:string)\n *    - paneCreate -- When a pane is created\n *          (e, paneId:string)\n *    - paneDestroy -- When a pane is destroyed\n *          (e, paneId:string)\n *\n *\n *    To listen for working set changes, you must listen to *all* of these events:\n *    - workingSetAdd -- When a file is added to the working set\n *          (e, fileAdded:File, index:number, paneId:string)\n *    - workingSetAddList -- When multiple files are added to the working set\n *          (e, fileAdded:Array.<File>, paneId:string)\n *    - workingSetMove - When a File has moved to a different working set\n *          (e, File:FILE, sourcePaneId:string, destinationPaneId:string)\n *    - workingSetRemove -- When a file is removed from the working set\n *          (e, fileRemoved:File, suppressRedraw:boolean, paneId:string)\n *    - workingSetRemoveList -- When multiple files are removed from the working set\n *          (e, filesRemoved:Array.<File>, paneId:string)\n *    - workingSetSort -- When a pane's view array is reordered without additions or removals.\n *          (e, paneId:string)\n *    - workingSetUpdate -- When changes happen due to system events such as a file being deleted.\n *                              listeners should discard all working set info and rebuilt it from the pane\n *                              by calling getWorkingSet()\n *          (e, paneId:string)\n *    - _workingSetDisableAutoSort -- When the working set is reordered by manually dragging a file.\n *          (e, paneId:string) For Internal Use Only.\n *\n * To listen for events, do something like this: (see EventDispatcher for details on this pattern)\n *    `MainViewManager.on(\"eventname\", handler);`\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                   = require(\"thirdparty/lodash\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        Strings             = require(\"strings\"),\n        AppInit             = require(\"utils/AppInit\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        MainViewFactory     = require(\"view/MainViewFactory\"),\n        ViewStateManager    = require(\"view/ViewStateManager\"),\n        Commands            = require(\"command/Commands\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileSystemError     = require(\"filesystem/FileSystemError\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        WorkspaceManager    = require(\"view/WorkspaceManager\"),\n        AsyncUtils          = require(\"utils/Async\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        Resizer             = require(\"utils/Resizer\"),\n        Pane                = require(\"view/Pane\").Pane,\n        KeyBindingManager   = brackets.getModule(\"command/KeyBindingManager\");\n\n    /**\n     * Preference setting name for the MainView Saved State\n     * @const\n     * @private\n     */\n    var PREFS_NAME          = \"mainView.state\";\n\n    /**\n     * Legacy Preference setting name used to migrate old preferences\n     * @const\n     * @private\n     */\n    var OLD_PREFS_NAME      = \"project.files\";\n\n    /**\n     * Special paneId shortcut that can be used to specify that\n     * all panes should be targeted by the API.\n     * Not all APIs support this constnant.\n     * Check the API documentation before use.\n     * @const\n     */\n    var ALL_PANES           = \"ALL_PANES\";\n\n    /**\n     * Special paneId shortcut that can be used to specify that\n     * the API should target the focused pane only.\n     * All APIs support this shortcut.\n     * @const\n     */\n    var ACTIVE_PANE        = \"ACTIVE_PANE\";\n\n    /**\n     * Internal pane id\n     * @const\n     * @private\n     */\n    var FIRST_PANE          = \"first-pane\";\n\n    /**\n     * Internal pane id\n     * @const\n     * @private\n     */\n    var SECOND_PANE         = \"second-pane\";\n\n    /*\n     * NOTE: The following commands and constants will change\n     *        when implementing the UX UI Treatment @larz0\n     */\n\n    /**\n     * Vertical layout state name\n     * @const\n     * @private\n     */\n    var VERTICAL            = \"VERTICAL\";\n\n    /**\n     * Horizontal layout state name\n     * @const\n     * @private\n     */\n    var HORIZONTAL          = \"HORIZONTAL\";\n\n    /**\n     * The minimum width or height that a pane can be\n     * @const\n     * @private\n     */\n    var MIN_PANE_SIZE      = 75;\n\n    /**\n     * current orientation (null, VERTICAL or HORIZONTAL)\n     * @type {string=}\n     * @private\n     */\n    var _orientation = null;\n\n    /**\n     * current pane id. May not be null\n     * @type {!string}\n     * @private\n     */\n    var _activePaneId = null;\n\n    /**\n     * DOM element hosting the Main View.\n     * @type {jQuery}\n     * @private\n     */\n    var _$el;\n\n    /**\n     * Maps paneId to Pane objects\n     * @type {Object.<string, Pane>}\n     * @private\n     */\n    var _panes = {};\n\n\n    /**\n     * map of pane scroll states\n     * @type {Object.map<string, *>}\n     * @private\n     */\n    var _paneScrollStates = {};\n\n\n    /**\n     * flag indicating if traversing is currently taking place\n     * When True, changes the current pane's MRU list will not be updated.\n     * Useful for next/previous keyboard navigation (until Ctrl is released)\n     * or for incremental-search style document preview like Quick Open will eventually have.\n     * @type {!boolean}\n     * @private\n     */\n    var _traversingFileList = false;\n\n    /**\n     * The global MRU list (for traversing)\n     * @type {Array.<file:File, paneId:string>}\n     */\n    var _mruList = [];\n\n    /**\n     * localized pane titles\n     * @type {Object.<FIRST_PANE|SECOND_PANE, <VERTICAL.string, HORIZONTAL.string>}}\n     *  Localized string for first and second panes in the current orientation.\n     * @see {@link #getPaneTitle} for more information\n     * @private\n     */\n    var _paneTitles  = {};\n\n    /*\n     * Initialize _paneTitles\n     */\n    _paneTitles[FIRST_PANE] = {};\n    _paneTitles[SECOND_PANE] = {};\n\n    _paneTitles[FIRST_PANE][VERTICAL]     = Strings.LEFT;\n    _paneTitles[FIRST_PANE][HORIZONTAL]   = Strings.TOP;\n    _paneTitles[SECOND_PANE][VERTICAL]    = Strings.RIGHT;\n    _paneTitles[SECOND_PANE][HORIZONTAL]  = Strings.BOTTOM;\n\n    /**\n     * Makes a MRU List Entry\n     * @param {!File} File - the file\n     * @param {!string} paneId - the paneId\n     * @return {{file:File, paneId:string}}\n     * @private\n     */\n    function _makeMRUListEntry(file, paneId) {\n        return {file: file, paneId: paneId};\n    }\n\n    /**\n     * Locates the first  MRU entry of a file for the requested pane\n     * @param {!string} paneId - the paneId\n     * @param {!File} File - the file\n     * @return {{file:File, paneId:string}}\n     * @private\n     */\n    function _findFileInMRUList(paneId, file) {\n        return _.findIndex(_mruList, function (record) {\n            return (record.file.fullPath === file.fullPath && record.paneId === paneId);\n        });\n    }\n\n    /**\n     * Checks whether a file is listed exclusively in the provided pane\n     * @param {!File} File - the file\n     * @return {{file:File, paneId:string}}\n     */\n    function isExclusiveToPane(file, paneId) {\n        paneId = paneId === ACTIVE_PANE && _activePaneId ? _activePaneId : paneId;\n        var index = _.findIndex(_mruList, function (record) {\n            return (record.file.fullPath === file.fullPath && record.paneId !== paneId);\n        });\n        return index === -1;\n    }\n\n\n    /**\n     * Retrieves the currently active Pane Id\n     * @return {!string} Active Pane's ID.\n     */\n    function getActivePaneId() {\n        return _activePaneId;\n    }\n\n    /**\n     * Resolve paneId to actual pane.\n     * @param {?string} paneId - id of the desired pane. May be symbolic or null (to indicate current pane)\n     * @return {string} id of the pane in which to open the document\n     */\n    function _resolvePaneId(paneId) {\n        if (!paneId || paneId === ACTIVE_PANE) {\n            return getActivePaneId();\n        }\n        return paneId;\n    }\n\n    /**\n     * Retrieves the Pane object for the given paneId\n     * @param {!string} paneId - id of the pane to retrieve\n     * @return {?Pane} the Pane object or null if a pane object doesn't exist for the pane\n     * @private\n     */\n    function _getPane(paneId) {\n        paneId = _resolvePaneId(paneId);\n\n        if (_panes[paneId]) {\n            return _panes[paneId];\n        }\n\n        return null;\n    }\n\n    /**\n     * Focuses the current pane. If the current pane has a current view, then the pane will focus the view.\n     */\n    function focusActivePane() {\n        _getPane(ACTIVE_PANE).focus();\n    }\n\n    /**\n     * Determines if the pane id is a special pane id\n     * @param {!string} paneId - the id to test\n     * @return {boolean} true if the pane id is a special identifier, false if not\n     */\n    function _isSpecialPaneId(paneId) {\n        return paneId === ACTIVE_PANE || paneId === ALL_PANES;\n    }\n\n    /**\n     * Makes the file the most recent for the pane and the global mru lists\n     * @param {!string} paneId - id of the pane to mae th file most recent or ACTIVE_PANE\n     * @param {!File} file - File object to make most recent\n     * @private\n     */\n    function _makeFileMostRecent(paneId, file) {\n        var index,\n            entry,\n            pane = _getPane(paneId);\n\n        if (!_traversingFileList) {\n            pane.makeViewMostRecent(file);\n\n            index = _findFileInMRUList(pane.id, file);\n\n            entry = _makeMRUListEntry(file, pane.id);\n\n            if (index !== -1) {\n                _mruList.splice(index, 1);\n            }\n\n            if (_findFileInMRUList(pane.id, file) !== -1) {\n                console.log(file.fullPath + \" duplicated in mru list\");\n            }\n\n            // add it to the front of the list\n            _mruList.unshift(entry);\n        }\n    }\n\n    /**\n     * Makes the Pane's current file the most recent\n     * @param {!string} paneId - id of the pane to make the file most recent, or ACTIVE_PANE\n     * @param {!File} file - File object to make most recent\n     * @private\n     */\n    function _makePaneMostRecent(paneId) {\n        var pane = _getPane(paneId);\n\n        if (pane.getCurrentlyViewedFile()) {\n            _makeFileMostRecent(paneId, pane.getCurrentlyViewedFile());\n        }\n    }\n\n    /**\n     * Switch active pane to the specified pane id (or ACTIVE_PANE/ALL_PANES, in which case this\n     * call does nothing).\n     * @param {!string} paneId - the id of the pane to activate\n     */\n    function setActivePaneId(newPaneId) {\n        if (!_isSpecialPaneId(newPaneId) && newPaneId !== _activePaneId) {\n            var oldPaneId = _activePaneId,\n                oldPane = _getPane(ACTIVE_PANE),\n                newPane = _getPane(newPaneId);\n\n            if (!newPane) {\n                throw new Error(\"invalid pane id: \" + newPaneId);\n            }\n\n            _activePaneId = newPaneId;\n\n            exports.trigger(\"activePaneChange\", newPaneId, oldPaneId);\n            exports.trigger(\"currentFileChange\", _getPane(ACTIVE_PANE).getCurrentlyViewedFile(),\n                                                            newPaneId,\n                                                            oldPane.getCurrentlyViewedFile(),\n                                                            oldPaneId);\n\n            _makePaneMostRecent(_activePaneId);\n            focusActivePane();\n        }\n    }\n\n    /**\n     * Retrieves the Pane ID for the specified container\n     * @param {!jQuery} $el - the element of the pane to fetch\n     * @return {?string} the id of the pane that matches the container or undefined if a pane doesn't exist for that container\n     */\n    function _getPaneFromElement($el) {\n        return _.find(_panes, function (pane) {\n            if (pane.$el[0] === $el[0]) {\n                return pane;\n            }\n        });\n    }\n\n    /**\n     * Retrieves the currently viewed file of the specified paneId\n     * @param {?string} paneId - the id of the pane in which to retrieve the currently viewed file\n     * @return {?File} File object of the currently viewed file, or null if there isn't one or there's no such pane\n     */\n    function getCurrentlyViewedFile(paneId) {\n        var pane = _getPane(paneId);\n        return pane ? pane.getCurrentlyViewedFile() : null;\n    }\n\n    /**\n     * Retrieves the currently viewed path of the pane specified by paneId\n     * @param {?string} paneId - the id of the pane in which to retrieve the currently viewed path\n     * @return {?string} the path of the currently viewed file or null if there isn't one\n     */\n    function getCurrentlyViewedPath(paneId) {\n        var file = getCurrentlyViewedFile(paneId);\n        return file ? file.fullPath : null;\n    }\n\n    /**\n     * EditorManager.activeEditorChange handler\n     *   This event is triggered when an visible editor gains focus\n     *   Therefore we need to Activate the pane that the active editor belongs to\n     * @private\n     * @param {!jQuery.Event} e - jQuery Event object\n     * @param {Editor=} current - editor being made the current editor\n     */\n    function _activeEditorChange(e, current) {\n        if (current) {\n            var $container = current.$el.parent().parent(),\n                pane = _getPaneFromElement($container);\n\n            if (pane) {\n                // Editor is a full editor\n                if (pane.id !== _activePaneId) {\n                    // we just need to set the active pane in this case\n                    //  it will dispatch the currentFileChange message as well\n                    //  as dispatching other events when the active pane changes\n                    setActivePaneId(pane.id);\n                }\n            } else {\n                // Editor is an inline editor, find the parent pane\n                var parents = $container.parents(\".view-pane\");\n                if (parents.length === 1) {\n                    $container = $(parents[0]);\n                    pane = _getPaneFromElement($container);\n                    if (pane) {\n                        if (pane.id !== _activePaneId) {\n                            // activate the pane which will put focus in the pane's doc\n                            setActivePaneId(pane.id);\n                            // reset the focus to the inline editor\n                            current.focus();\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Iterates over the pane or ALL_PANES and calls the callback function for each.\n     * @param {!string} paneId - id of the pane in which to adjust the scroll state, ALL_PANES or ACTIVE_PANE\n     * @param {!function(!pane:Pane):boolean} callback - function to callback on to perform work.\n     * The callback will receive a Pane and should return false to stop iterating.\n     * @private\n     */\n    function _forEachPaneOrPanes(paneId, callback) {\n        if (paneId === ALL_PANES) {\n            _.forEach(_panes, callback);\n        } else {\n            callback(_getPane(paneId));\n        }\n    }\n\n    /**\n     * Caches the specified pane's current scroll state\n     * If there was already cached state for the specified pane, it is discarded and overwritten\n     * @param {!string} paneId - id of the pane in which to cache the scroll state,\n     *                            ALL_PANES or ACTIVE_PANE\n     */\n    function cacheScrollState(paneId) {\n        _forEachPaneOrPanes(paneId, function (pane) {\n            _paneScrollStates[pane.id] = pane.getScrollState();\n        });\n    }\n\n\n    /**\n     * Restores the scroll state from cache and applies the heightDelta\n     * The view implementation is responsible for applying or ignoring the heightDelta.\n     * This is used primarily when a modal bar opens to keep the editor from scrolling the current\n     * page out of view in order to maintain the appearance.\n     * The state is removed from the cache after calling this function.\n     * @param {!string} paneId - id of the pane in which to adjust the scroll state,\n     *                              ALL_PANES or ACTIVE_PANE\n     * @param {!number} heightDelta - delta H to apply to the scroll state\n     */\n    function restoreAdjustedScrollState(paneId, heightDelta) {\n        _forEachPaneOrPanes(paneId, function (pane) {\n            pane.restoreAndAdjustScrollState(_paneScrollStates[pane.id], heightDelta);\n            delete _paneScrollStates[pane.id];\n        });\n    }\n\n\n    /**\n     * Retrieves the WorkingSet for the given paneId not including temporary views\n     * @param {!string} paneId - id of the pane in which to get the view list, ALL_PANES or ACTIVE_PANE\n     * @return {Array.<File>}\n     */\n    function getWorkingSet(paneId) {\n        var result = [];\n\n        _forEachPaneOrPanes(paneId, function (pane) {\n            var viewList = pane.getViewList();\n            result = _.union(result, viewList);\n        });\n\n        return result;\n    }\n\n\n    /**\n     * Retrieves the list of all open files including temporary views\n     * @return {array.<File>} the list of all open files in all open panes\n     */\n    function getAllOpenFiles() {\n        var result = getWorkingSet(ALL_PANES);\n        _.forEach(_panes, function (pane) {\n            var file = pane.getCurrentlyViewedFile();\n            if (file) {\n                result = _.union(result, [file]);\n            }\n        });\n        return result;\n    }\n\n    /**\n     * Retrieves the list of all open pane ids\n     * @return {array.<string>} the list of all open panes\n     */\n    function getPaneIdList() {\n        return Object.keys(_panes);\n    }\n\n    /**\n     * Retrieves the size of the selected pane's view list\n     * @param {!string} paneId - id of the pane in which to get the workingset size.\n     *      Can use `ALL_PANES` or `ACTIVE_PANE`\n     * @return {!number} the number of items in the specified pane\n     */\n    function getWorkingSetSize(paneId) {\n        var result = 0;\n        _forEachPaneOrPanes(paneId, function (pane) {\n            result += pane.getViewListSize();\n        });\n        return result;\n    }\n\n    /**\n     * Retrieves the title to display in the workingset view\n     * @param {!string} paneId - id of the pane in which to get the title\n     * @return {?string} title\n     */\n    function getPaneTitle(paneId) {\n        return _paneTitles[paneId][_orientation];\n    }\n\n    /**\n     * Retrieves the number of panes\n     * @return {number}\n     */\n    function getPaneCount() {\n        return Object.keys(_panes).length;\n    }\n\n    /**\n     * Helper to abastract the common working set search functions\n     * @param {!string} paneId - id of the pane to search or ALL_PANES to search all panes\n     * @param {!string} fullPath - path of the file to locate\n     * @param {!string} method - name of the method to use for searching\n     *       \"findInViewList\", \"findInViewListAddedOrder\" or \"FindInViewListMRUOrder\"\n     *\n     * @private\n     */\n    function _doFindInWorkingSet(paneId, fullPath, method) {\n        var result = -1;\n        _forEachPaneOrPanes(paneId, function (pane) {\n            var index = pane[method].call(pane, fullPath);\n            if (index >= 0) {\n                result = index;\n                return false;\n            }\n        });\n        return result;\n    }\n\n    /**\n     * Finds all instances of the specified file in all working sets.\n     * If there is a temporary view of the file, it is not part of the result set\n     * @param {!string} fullPath - path of the file to find views of\n     * @return {Array.<{pane:string, index:number}>} an array of paneId/index records\n     */\n    function findInAllWorkingSets(fullPath) {\n        var index,\n            result = [];\n\n        _.forEach(_panes, function (pane) {\n            index = pane.findInViewList(fullPath);\n            if (index >= 0) {\n                result.push({paneId: pane.id, index: index});\n            }\n        });\n\n        return result;\n    }\n\n    /**\n     * Gets the index of the file matching fullPath in the workingset\n     * @param {!string} paneId - id of the pane in which to search or ALL_PANES or ACTIVE_PANE\n     * @param {!string} fullPath - full path of the file to search for\n     * @return {number} index, -1 if not found.\n     */\n    function findInWorkingSet(paneId, fullPath) {\n        return _doFindInWorkingSet(paneId, fullPath, \"findInViewList\");\n    }\n\n    /**\n     * Gets the index of the file matching fullPath in the added order workingset\n     * @param {!string} paneId - id of the pane in which to search or ALL_PANES or ACTIVE_PANE\n     * @param {!string} fullPath - full path of the file to search for\n     * @return {number} index, -1 if not found.\n     */\n    function findInWorkingSetByAddedOrder(paneId, fullPath) {\n        return _doFindInWorkingSet(paneId, fullPath, \"findInViewListAddedOrder\");\n    }\n\n    /**\n     * Gets the index of the file matching fullPath in the MRU order workingset\n     * @param {!string} paneId - id of the pane in which to search or ALL_PANES or ACTIVE_PANE\n     * @param {!string} fullPath - full path of the file to search for\n     * @return {number} index, -1 if not found.\n     */\n    function findInWorkingSetByMRUOrder(paneId, fullPath) {\n        return _doFindInWorkingSet(paneId, fullPath, \"findInViewListMRUOrder\");\n    }\n\n    /**\n     * @private\n     * Retrieves pane id where the specified file has been opened. Used to ensure that a file\n     *  is open in only one pane so this will change once support for multiple views is added\n     * The result includes panes with a temporary view of the file not just working set instances\n     * @param {!string} fullPath - full path of the file to search for\n     * @return {?string} pane id where the file has been opened or null if it wasn't found\n     */\n    function _getPaneIdForPath(fullPath) {\n        // Search all working sets and pull off the first one\n        var info = findInAllWorkingSets(fullPath).shift();\n\n        // Look for a view that has not been added to a working set\n        if (!info) {\n            _.forEach(_panes, function (pane) {\n                if (pane.getCurrentlyViewedPath() === fullPath) {\n                    info = {paneId: pane.id};\n                    return false;\n                }\n            });\n        }\n\n        if (!info) {\n            return null;\n        }\n\n        return info.paneId;\n    }\n\n    /**\n     * Adds the given file to the end of the workingset, if it is not already there.\n     *  This API does not create a view of the file, it just adds it to the working set\n     * Views of files in the working set are persisted and are not destroyed until the user\n     *  closes the file using FILE_CLOSE; Views are created using FILE_OPEN and, when opened, are\n     *  made the current view. If a File is already opened then the file is just made current\n     *  and its view is shown.\n     * @param {!string} paneId - The id of the pane in which to add the file object to or ACTIVE_PANE\n     * @param {!File} file - The File object to add to the workingset\n     * @param {number=} index - Position to add to list (defaults to last); -1 is ignored\n     * @param {boolean=} forceRedraw - If true, a workingset change notification is always sent\n     *    (useful if suppressRedraw was used with removeView() earlier)\n     */\n    function addToWorkingSet(paneId, file, index, force) {\n        // look for the file to have already been added to another pane\n        var pane = _getPane(paneId);\n        if (!pane) {\n            throw new Error(\"invalid pane id: \" + paneId);\n        }\n\n        var result = pane.reorderItem(file, index, force),\n            entry = _makeMRUListEntry(file, pane.id);\n\n\n        // handles the case of save as so that the file remains in the\n        //  the same location in the working set as the file that was renamed\n        if (result === pane.ITEM_FOUND_NEEDS_SORT) {\n            console.warn(\"pane.reorderItem returned pane.ITEM_FOUND_NEEDS_SORT which shouldn't happen \" + file);\n            exports.trigger(\"workingSetSort\", pane.id);\n        } else if (result === pane.ITEM_NOT_FOUND) {\n            index = pane.addToViewList(file, index);\n\n            if (_findFileInMRUList(pane.id, file) === -1) {\n                // Add to or update the position in MRU\n                if (pane.getCurrentlyViewedFile() === file) {\n                    _mruList.unshift(entry);\n                } else {\n                    _mruList.push(entry);\n                }\n            }\n\n            exports.trigger(\"workingSetAdd\", file, index, pane.id);\n        }\n    }\n\n    /**\n     * Adds the given file list to the end of the workingset.\n     * @param {!string} paneId - The id of the pane in which to add the file object to or ACTIVE_PANE\n     * @param {!Array.<File>} fileList - Array of files to add to the pane\n     */\n    function addListToWorkingSet(paneId, fileList) {\n        var uniqueFileList,\n            pane = _getPane(paneId);\n\n        uniqueFileList = pane.addListToViewList(fileList);\n\n        uniqueFileList.forEach(function (file) {\n            if (_findFileInMRUList(pane.id, file) !== -1) {\n                console.log(file.fullPath + \" duplicated in mru list\");\n            }\n            _mruList.push(_makeMRUListEntry(file, pane.id));\n        });\n\n        exports.trigger(\"workingSetAddList\", uniqueFileList, pane.id);\n\n        //  find all of the files that could be added but were not\n        var unsolvedList = fileList.filter(function (item) {\n            // if the file open in another pane, then add it to the list of unsolvedList\n            return (pane.findInViewList(item.fullPath) === -1 && _getPaneIdForPath(item.fullPath));\n        });\n\n        // Use the pane id of the first one in the list for pane id and recurse\n        //  if we add more panes, then this will recurse until all items in the list are satisified\n        if (unsolvedList.length) {\n            addListToWorkingSet(_getPaneIdForPath(unsolvedList[0].fullPath), unsolvedList);\n        }\n    }\n\n    /**\n     * Removes a file from the global MRU list. Future versions of this\n     *  implementation may support the ALL_PANES constant but FOCUS_PANE is not allowed\n     * @param {!string} paneId - Must be a valid paneId (not a shortcut e.g. ALL_PANES)\n     @ @param {File} file The file object to remove.\n     * @private\n     */\n    function _removeFileFromMRU(paneId, file) {\n        var index,\n            compare = function (record) {\n                return (record.file === file && record.paneId === paneId);\n            };\n\n        // find and remove all instances\n        do {\n            index = _.findIndex(_mruList, compare);\n            if (index !== -1) {\n                _mruList.splice(index, 1);\n            }\n        } while (index !== -1);\n    }\n\n    /**\n     * Removes a file the specified pane\n     * @param {!string} paneId - Must be a valid paneId (not a shortcut e.g. ALL_PANES)\n     * @param {!File} file - the File to remove\n     * @param {boolean=} suppressRedraw - true to tell listeners not to redraw\n     *          Use the suppressRedraw flag when calling this function along with many changes to prevent flicker\n     * @private\n     */\n    function _removeView(paneId, file, suppressRedraw) {\n        var pane = _getPane(paneId);\n\n        if (pane.removeView(file)) {\n            _removeFileFromMRU(pane.id, file);\n            exports.trigger(\"workingSetRemove\", file, suppressRedraw, pane.id);\n        }\n    }\n\n    /**\n     * moves a view from one pane to another\n     * @param {!string} sourcePaneId - id of the source pane\n     * @param {!string} destinationPaneId - id of the destination pane\n     * @param {!File} file - the File to move\n     * @param {Number} destinationIndex - the working set index of the file in the destination pane\n     * @return {jQuery.Promise} a promise that resolves when the move has completed.\n     * @private\n     */\n    function _moveView(sourcePaneId, destinationPaneId, file, destinationIndex) {\n        var result = new $.Deferred(),\n            sourcePane = _getPane(sourcePaneId),\n            destinationPane = _getPane(destinationPaneId);\n\n        sourcePane.moveView(file, destinationPane, destinationIndex)\n            .done(function () {\n                // remove existing entry from mrulist for the same document if present \n                _removeFileFromMRU(destinationPane.id, file);\n                // update the mru list\n                _mruList.every(function (record) {\n                    if (record.file === file && record.paneId === sourcePane.id) {\n                        record.paneId = destinationPane.id;\n                        return false;\n                    }\n                    return true;\n                });\n                exports.trigger(\"workingSetMove\", file, sourcePane.id, destinationPane.id);\n                result.resolve();\n            });\n\n        return result.promise();\n    }\n\n    /**\n     * Switch between panes\n     */\n    function switchPaneFocus() {\n        var $firstPane = $('#first-pane'), $secondPane = $('#second-pane');\n        if($firstPane.hasClass('active-pane')) {\n            $secondPane.click();\n        }\n        else {\n            $firstPane.click();\n        }\n    }\n\n    /**\n     * DocumentManager.pathDeleted Event handler to remove a file\n     * from the MRU list\n     * @param {!jQuery.event} e -\n     * @param {!string} fullPath - path of the file to remove\n     * @private\n     */\n    function _removeDeletedFileFromMRU(e, fullPath) {\n        var index,\n            compare = function (record) {\n                return (record.file.fullPath === fullPath);\n            };\n\n        // find and remove all instances\n        do {\n            index = _.findIndex(_mruList, compare);\n            if (index !== -1) {\n                _mruList.splice(index, 1);\n            }\n        } while (index !== -1);\n    }\n\n    /**\n     * sorts the pane's view list\n     * @param {!string} paneId - id of the pane to sort, ALL_PANES or ACTIVE_PANE\n     * @param {sortFunctionCallback} compareFn - callback to determine sort order (called on each item)\n     * @see {@link Pane#sortViewList} for more information\n     * @see {@link https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort|Sort Array - MDN}\n     * @private\n     */\n    function _sortWorkingSet(paneId, compareFn) {\n        _forEachPaneOrPanes(paneId, function (pane) {\n            pane.sortViewList(compareFn);\n            exports.trigger(\"workingSetSort\", pane.id);\n        });\n    }\n\n    /**\n     * moves a working set item from one index to another shifting the items\n     * after in the working set up and reinserting it at the desired location\n     * @param {!string} paneId - id of the pane to sort\n     * @param {!number} fromIndex - the index of the item to move\n     * @param {!number} toIndex - the index to move to\n     * @private\n     */\n    function _moveWorkingSetItem(paneId, fromIndex, toIndex) {\n        var pane = _getPane(paneId);\n\n        pane.moveWorkingSetItem(fromIndex, toIndex);\n        exports.trigger(\"workingSetSort\", pane.id);\n        exports.trigger(\"_workingSetDisableAutoSort\", pane.id);\n    }\n\n    /**\n     * Mutually exchanges the files at the indexes passed by parameters.\n     * @param {!string} paneId - id of the pane to swap indices or ACTIVE_PANE\n     * @param {!number} index1 - the index on the left\n     * @param {!number} index2 - the index on the rigth\n     * @private\n     */\n    function _swapWorkingSetListIndexes(paneId, index1, index2) {\n        var pane = _getPane(paneId);\n\n        pane.swapViewListIndexes(index1, index2);\n        exports.trigger(\"workingSetSort\", pane.id);\n        exports.trigger(\"_workingSetDisableAutoSort\", pane.id);\n    }\n\n    /**\n     * Get the next or previous file in the MRU list.\n     * @param {!number} direction - Must be 1 or -1 to traverse forward or backward\n     * @return {?{file:File, paneId:string}} The File object of the next item in the traversal order or null if there aren't any files to traverse.\n     *                                       May return current file if there are no other files to traverse.\n     */\n    function traverseToNextViewByMRU(direction) {\n        var file = getCurrentlyViewedFile(),\n            paneId = getActivePaneId(),\n            index = _.findIndex(_mruList, function (record) {\n                return (record.file === file && record.paneId === paneId);\n            });\n\n        return ViewUtils.traverseViewArray(_mruList, index, direction);\n    }\n\n    /**\n     * Get the next or previous file in list order.\n     * @param {!number} direction - Must be 1 or -1 to traverse forward or backward\n     * @return {?{file:File, paneId:string}} The File object of the next item in the traversal order or null if there aren't any files to traverse.\n     *                                       May return current file if there are no other files to traverse.\n     */\n    function traverseToNextViewInListOrder(direction) {\n        var file = getCurrentlyViewedFile(),\n            curPaneId = getActivePaneId(),\n            allFiles = [],\n            index;\n\n        getPaneIdList().forEach(function (paneId) {\n            var paneFiles = getWorkingSet(paneId).map(function (file) {\n                return { file: file, pane: paneId };\n            });\n            allFiles = allFiles.concat(paneFiles);\n        });\n\n        index = _.findIndex(allFiles, function (record) {\n            return (record.file === file && record.pane === curPaneId);\n        });\n\n        return ViewUtils.traverseViewArray(allFiles, index, direction);\n    }\n\n    /**\n     * Indicates that traversal has begun.\n     * Can be called any number of times.\n     */\n    function beginTraversal() {\n        _traversingFileList = true;\n    }\n\n    /**\n     * Un-freezes the MRU list after one or more beginTraversal() calls.\n     * Whatever file is current is bumped to the front of the MRU list.\n     */\n    function endTraversal() {\n        var pane = _getPane(ACTIVE_PANE);\n\n        if (_traversingFileList) {\n            _traversingFileList = false;\n\n            _makeFileMostRecent(pane.id, pane.getCurrentlyViewedFile());\n        }\n    }\n\n    /**\n     * Synchronizes the pane's sizer element, updates the pane's resizer maxsize value\n     *   and tells the pane to update its layout\n     * @param {boolean} forceRefresh - true to force a resize and refresh of the entire view\n     * @private\n     */\n    function _synchronizePaneSize(pane, forceRefresh) {\n        var available;\n\n        if (_orientation === VERTICAL) {\n            available = _$el.innerWidth();\n        } else {\n            available = _$el.innerHeight();\n        }\n\n        // Update the pane's sizer element if it has one and update the max size\n        Resizer.resyncSizer(pane.$el);\n        pane.$el.data(\"maxsize\", available - MIN_PANE_SIZE);\n        pane.updateLayout(forceRefresh);\n    }\n\n\n    /**\n     * Event handler for \"workspaceUpdateLayout\" to update the layout\n     * @param {jQuery.Event} event - jQuery event object\n     * @param {number} viewAreaHeight - unused\n     * @param {boolean} forceRefresh - true to force a resize and refresh of the entire view\n     * @private\n     */\n    function _updateLayout(event, viewAreaHeight, forceRefresh) {\n        var available;\n\n        if (_orientation === VERTICAL) {\n            available = _$el.innerWidth();\n        } else {\n            available = _$el.innerHeight();\n        }\n\n        _.forEach(_panes, function (pane) {\n            // For VERTICAL orientation, we set the second pane to be width: auto\n            //  so that it resizes to fill the available space in the containing div\n            // unfortunately, that doesn't work in the HORIZONTAL orientation so we\n            //  must update the height and convert it into a percentage\n            if (pane.id === SECOND_PANE && _orientation === HORIZONTAL) {\n                var percentage = ((_panes[FIRST_PANE].$el.height() + 1) / available);\n                pane.$el.css(\"height\", 100 - (percentage * 100) + \"%\");\n            }\n\n            _synchronizePaneSize(pane, forceRefresh);\n        });\n    }\n\n    /**\n     * Sets up the initial layout so panes are evenly distributed\n     * This also sets css properties that aid in the layout when _updateLayout is called\n     * @param {boolean} forceRefresh - true to force a resize and refresh of the entire view\n     * @private\n     */\n    function _initialLayout(forceRefresh) {\n        var panes = Object.keys(_panes),\n            size = 100 / panes.length;\n\n        _.forEach(_panes, function (pane) {\n            if (pane.id === FIRST_PANE) {\n                if (_orientation === VERTICAL) {\n                    pane.$el.css({height: \"100%\",\n                                  width: size + \"%\",\n                                  float: \"left\"\n                                 });\n                } else {\n                    pane.$el.css({ height: size + \"%\",\n                                   width: \"100%\"\n                                 });\n                }\n            } else {\n                if (_orientation === VERTICAL) {\n                    pane.$el.css({  height: \"100%\",\n                                    width: \"auto\",\n                                    float: \"none\"\n                                 });\n                } else {\n                    pane.$el.css({ width: \"100%\",\n                                   height: \"50%\"\n                                 });\n                }\n            }\n\n            _synchronizePaneSize(pane, forceRefresh);\n        });\n    }\n\n    /**\n     * Updates the header text for all panes\n     */\n    function _updatePaneHeaders() {\n        _forEachPaneOrPanes(ALL_PANES, function (pane) {\n            pane.updateHeaderText();\n        });\n\n    }\n\n    /**\n     * Creates a pane for paneId if one doesn't already exist\n     * @param {!string} paneId - id of the pane to create\n     * @private\n     * @return {?Pane} - the pane object of the new pane, or undefined if no pane created\n     */\n    function _createPaneIfNecessary(paneId) {\n        var newPane;\n\n        if (!_panes.hasOwnProperty(paneId)) {\n            newPane = new Pane(paneId, _$el);\n            _panes[paneId] = newPane;\n\n            exports.trigger(\"paneCreate\", newPane.id);\n\n            newPane.$el.on(\"click.mainview dragover.mainview\", function () {\n                setActivePaneId(newPane.id);\n            });\n\n            newPane.on(\"viewListChange.mainview\", function () {\n                _updatePaneHeaders();\n                exports.trigger(\"workingSetUpdate\", newPane.id);\n            });\n            newPane.on(\"currentViewChange.mainview\", function (e, newView, oldView) {\n                _updatePaneHeaders();\n                if (_activePaneId === newPane.id) {\n                    exports.trigger(\"currentFileChange\",\n                                               newView && newView.getFile(),\n                                               newPane.id, oldView && oldView.getFile(),\n                                               newPane.id);\n                }\n            });\n            newPane.on(\"viewDestroy.mainView\", function (e, view) {\n                _removeFileFromMRU(newPane.id, view.getFile());\n            });\n        }\n\n        return newPane;\n    }\n\n    /**\n     * Makes the first pane resizable\n     * @private\n     */\n    function _makeFirstPaneResizable() {\n        var firstPane = _panes[FIRST_PANE];\n        Resizer.makeResizable(firstPane.$el,\n                              _orientation === HORIZONTAL ? Resizer.DIRECTION_VERTICAL : Resizer.DIRECTION_HORIZONTAL,\n                              _orientation === HORIZONTAL ? Resizer.POSITION_BOTTOM : Resizer.POSITION_RIGHT,\n                              MIN_PANE_SIZE, false, false, false, true, true);\n\n        firstPane.$el.on(\"panelResizeUpdate\", function () {\n            _updateLayout();\n        });\n    }\n\n\n    /**\n     * Creates a split for the specified orientation\n     * @private\n     * @param {!string} orientation (VERTICAL|HORIZONTAL)\n     */\n    function _doSplit(orientation) {\n        var firstPane, newPane;\n\n        if (orientation === _orientation) {\n            return;\n        }\n\n        firstPane = _panes[FIRST_PANE];\n        Resizer.removeSizable(firstPane.$el);\n\n        if (_orientation) {\n            _$el.removeClass(\"split-\" + _orientation.toLowerCase());\n        }\n        _$el.addClass(\"split-\" + orientation.toLowerCase());\n\n        _orientation = orientation;\n        newPane = _createPaneIfNecessary(SECOND_PANE);\n        _makeFirstPaneResizable();\n\n        // reset the layout to 50/50 split\n        // if we changed orientation then\n        //  the percentages are reset as well\n        _initialLayout();\n\n        exports.trigger(\"paneLayoutChange\", _orientation);\n\n        // if new pane was created, and original pane is not empty, make new pane the active pane\n        if (newPane && getCurrentlyViewedFile(firstPane.id)) {\n            setActivePaneId(newPane.id);\n        }\n    }\n\n    /**\n     * Edits a document in the specified pane.\n     * This function is only used by:\n     *  - Unit Tests (which construct Mock Document objects),\n     *  - by File > New  because there is yet to be an established File object\n     *  - by Find In Files which needs to open documents synchronously in some cases\n     * Do not use this API it is for internal use only\n     * @param {!string} paneId - id of the pane in which to open the document\n     * @param {!Document} doc - document to edit\n     * @param {{noPaneActivate:boolean=}=} optionsIn - options\n     * @private\n     */\n    function _edit(paneId, doc, optionsIn) {\n        var options = optionsIn || {};\n\n        var pane = _getPane(paneId);\n\n        // If file is untitled or otherwise not within project tree, add it to\n        // working set right now (don't wait for it to become dirty)\n        if (doc.isUntitled() || !ProjectManager.isWithinProject(doc.file.fullPath)) {\n            addToWorkingSet(paneId, doc.file);\n        }\n\n        // open document will show the editor if there is one already\n        EditorManager.openDocument(doc, pane, options);\n        _makeFileMostRecent(paneId, doc.file);\n\n        if (!options.noPaneActivate) {\n            setActivePaneId(paneId);\n        }\n    }\n\n    /**\n     * Opens a file in the specified pane this can be used to open a file with a custom viewer\n     * or a document for editing.  If it's a document for editing, edit is called on the document\n     * @param {!string} paneId - id of the pane in which to open the document\n     * @param {!File} file - file to open\n     * @param {{noPaneActivate:boolean=}=} optionsIn - options\n     * @return {jQuery.Promise}  promise that resolves to a File object or\n     *                           rejects with a File error or string\n     */\n    function _open(paneId, file, optionsIn) {\n        var result = new $.Deferred(),\n            options = optionsIn || {};\n\n        function doPostOpenActivation() {\n            if (!options.noPaneActivate) {\n                setActivePaneId(paneId);\n            }\n        }\n\n        if (!file || !_getPane(paneId)) {\n            return result.reject(\"bad argument\").promise();\n        }\n\n\n        // See if there is already a view for the file\n        var pane = _getPane(paneId);\n\n        // See if there is a factory to create a view for this file\n        //  we want to do this first because, we don't want our internal\n        //  editor to edit files for which there are suitable viewfactories\n        var factory = MainViewFactory.findSuitableFactoryForPath(file.fullPath);\n\n        if (factory) {\n            file.exists(function (fileError, fileExists) {\n                if (fileExists) {\n                    // let the factory open the file and create a view for it\n                    factory.openFile(file, pane)\n                        .done(function () {\n                            // if we opened a file that isn't in the project\n                            //  then add the file to the working set\n                            if (!ProjectManager.isWithinProject(file.fullPath)) {\n                                addToWorkingSet(paneId, file);\n                            }\n                            doPostOpenActivation();\n                            result.resolve(file);\n                        })\n                        .fail(function (fileError) {\n                            result.reject(fileError);\n                        });\n                } else {\n                    result.reject(fileError || FileSystemError.NOT_FOUND);\n                }\n            });\n        } else {\n            DocumentManager.getDocumentForPath(file.fullPath, file)\n                .done(function (doc) {\n                    if (doc) {\n                        _edit(paneId, doc, $.extend({}, options, {\n                            noPaneActivate: true\n                        }));\n                        doPostOpenActivation();\n                        result.resolve(doc.file);\n                    } else {\n                        result.resolve(null);\n                    }\n                })\n                .fail(function (fileError) {\n                    result.reject(fileError);\n                });\n        }\n\n       result.done(function () {\n           _makeFileMostRecent(paneId, file);\n       });\n\n        return result;\n    }\n\n    /**\n     * Merges second pane into first pane and opens the current file\n     * @private\n     */\n    function _mergePanes() {\n        if (_panes.hasOwnProperty(SECOND_PANE)) {\n\n            var firstPane = _panes[FIRST_PANE],\n                secondPane = _panes[SECOND_PANE],\n                fileList = secondPane.getViewList(),\n                lastViewed = getCurrentlyViewedFile();\n\n            Resizer.removeSizable(firstPane.$el);\n            firstPane.mergeFrom(secondPane);\n\n            exports.trigger(\"workingSetRemoveList\", fileList, secondPane.id);\n\n            setActivePaneId(firstPane.id);\n\n            secondPane.$el.off(\".mainview\");\n            secondPane.off(\".mainview\");\n\n            secondPane.destroy();\n            delete _panes[SECOND_PANE];\n            exports.trigger(\"paneDestroy\", secondPane.id);\n            exports.trigger(\"workingSetAddList\", fileList, firstPane.id);\n\n            _mruList.forEach(function (record) {\n                if (record.paneId === secondPane.id) {\n                    record.paneId = firstPane.id;\n                }\n            });\n\n            _$el.removeClass(\"split-\" + _orientation.toLowerCase());\n            _orientation = null;\n            // this will set the remaining pane to 100%\n            _initialLayout();\n\n            exports.trigger(\"paneLayoutChange\", _orientation);\n\n            // if the current view before the merger was in the pane\n            //  that went away then reopen it so that it's now the current view again\n            if (lastViewed && getCurrentlyViewedFile() !== lastViewed) {\n                exports._open(firstPane.id, lastViewed);\n            }\n        }\n    }\n\n    /**\n     * Closes a file in the specified pane or panes\n     * @param {!string} paneId - id of the pane in which to open the document\n     * @param {!File} file - file to close\n     * @param {Object={noOpenNextFile:boolean}} optionsIn - options\n     * This function does not fail if the file is not open\n     */\n    function _close(paneId, file, optionsIn) {\n        var options = optionsIn || {};\n        _forEachPaneOrPanes(paneId, function (pane) {\n            if (pane.removeView(file, options.noOpenNextFile) && (paneId === ACTIVE_PANE || pane.id === paneId)) {\n                _removeFileFromMRU(pane.id, file);\n                exports.trigger(\"workingSetRemove\", file, false, pane.id);\n                return false;\n            }\n        });\n    }\n\n    /**\n     * Closes a list of file in the specified pane or panes\n     * @param {!string} paneId - id of the pane in which to open the document\n     * @param {!Array.<File>} fileList - files to close\n     * This function does not fail if the file is not open\n     */\n    function _closeList(paneId, fileList) {\n        _forEachPaneOrPanes(paneId, function (pane) {\n            var closedList = pane.removeViews(fileList);\n            closedList.forEach(function (file) {\n                _removeFileFromMRU(pane.id, file);\n            });\n\n            exports.trigger(\"workingSetRemoveList\", closedList, pane.id);\n        });\n    }\n\n    /**\n     * Closes all files in the specified pane or panes\n     * @param {!string} paneId - id of the pane in which to open the document\n     * This function does not fail if the file is not open\n     */\n    function _closeAll(paneId) {\n        _forEachPaneOrPanes(paneId, function (pane) {\n            var closedList = pane.getViewList();\n            closedList.forEach(function (file) {\n                _removeFileFromMRU(pane.id, file);\n            });\n\n            pane._reset();\n            exports.trigger(\"workingSetRemoveList\", closedList, pane.id);\n        });\n    }\n\n\n    /**\n     * Finds which pane a document belongs to\n     * @param {!Document} document - the document to locate\n     * @return {?Pane} the pane where the document lives or NULL if it isn't in a pane\n     * @private\n     */\n    function _findPaneForDocument(document) {\n        // First check for an editor view of the document\n        var pane = _getPaneFromElement($(document._masterEditor.$el.parent().parent()));\n\n        if (!pane) {\n            // No view of the document, it may be in a working set and not yet opened\n            var info = findInAllWorkingSets(document.file.fullPath).shift();\n            if (info) {\n                pane = _panes[info.paneId];\n            }\n        }\n\n        return pane;\n    }\n\n    /**\n     * Destroys an editor object if a document is no longer referenced\n     * @param {!Document} doc - document to destroy\n     */\n    function _destroyEditorIfNotNeeded(document) {\n        if (!(document instanceof DocumentManager.Document)) {\n            throw new Error(\"_destroyEditorIfUnneeded() should be passed a Document\");\n        }\n        if (document._masterEditor) {\n            // findPaneForDocument tries to locate the pane in which the document\n            //  is either opened or will be opened (in the event that the document is\n            //  in a working set but has yet to be opened) and then asks the pane\n            //  to destroy the view if it doesn't need it anymore\n            var pane = _findPaneForDocument(document);\n\n            if (pane) {\n                // let the pane deceide if it wants to destroy the view if it's no needed\n                pane.destroyViewIfNotNeeded(document._masterEditor);\n            } else {\n                // in this case, the document isn't referenced at all so just destroy it\n                document._masterEditor.destroy();\n            }\n        }\n    }\n\n\n    /**\n     * Loads the workingset state\n     * @private\n     */\n    function _loadViewState(e) {\n        // file root is appended for each project\n        var panes,\n            promises = [],\n            context = { location : { scope: \"user\",\n                                     layer: \"project\" } },\n            state = PreferencesManager.getViewState(PREFS_NAME, context);\n\n        function convertViewState() {\n            var context = { location : { scope: \"user\",\n                                         layer: \"project\" } },\n                files = PreferencesManager.getViewState(OLD_PREFS_NAME, context);\n\n            if (!files) {\n                // nothing to convert\n                return;\n            }\n\n            var result = {\n                orientation: null,\n                activePaneId: FIRST_PANE,\n                panes: {\n                    \"first-pane\": []\n                }\n            };\n\n            // Add all files to the workingset without verifying that\n            // they still exist on disk (for faster project switching)\n            files.forEach(function (value) {\n                result.panes[FIRST_PANE].push(value);\n            });\n\n            return result;\n        }\n\n        if (!state) {\n            // not converted yet\n            state = convertViewState();\n        }\n\n        // reset\n        _mergePanes();\n        _mruList = [];\n        ViewStateManager.reset();\n\n        if (state) {\n\n            panes = Object.keys(state.panes);\n            _orientation = (panes.length > 1) ? state.orientation : null;\n\n            _.forEach(state.panes, function (paneState, paneId) {\n                _createPaneIfNecessary(paneId);\n                promises.push(_panes[paneId].loadState(paneState));\n            });\n\n            AsyncUtils.waitForAll(promises).then(function (opensList) {\n\n                // this will set the default layout of 50/50 or 100\n                //  based on the number of panes\n                _initialLayout();\n\n                // More than 1 pane, then make it resizable\n                //  and layout the panes from serialized state\n                if (panes.length > 1) {\n                    _makeFirstPaneResizable();\n\n                    // If the split state was serialized correctly\n                    //  then setup the splits according to was serialized\n                    // Avoid a zero and negative split percentages\n                    if ($.isNumeric(state.splitPercentage) && state.splitPercentage > 0) {\n                        var prop;\n                        if (_orientation === VERTICAL) {\n                            prop = \"width\";\n                        } else {\n                            prop = \"height\";\n                        }\n\n                        _panes[FIRST_PANE].$el.css(prop, state.splitPercentage * 100 + \"%\");\n                        _updateLayout();\n                    }\n                }\n\n                if (_orientation) {\n                    _$el.addClass(\"split-\" + _orientation.toLowerCase());\n                    exports.trigger(\"paneLayoutChange\", _orientation);\n                }\n\n                _.forEach(_panes, function (pane) {\n                    var fileList = pane.getViewList();\n\n                    fileList.forEach(function (file) {\n                        if (_findFileInMRUList(pane.id, file) !== -1) {\n                            console.log(file.fullPath + \" duplicated in mru list\");\n                        }\n                        _mruList.push(_makeMRUListEntry(file, pane.id));\n                    });\n                    exports.trigger(\"workingSetAddList\", fileList, pane.id);\n                });\n\n                promises = [];\n\n                opensList.forEach(function (openData) {\n                    if (openData) {\n                        promises.push(CommandManager.execute(Commands.FILE_OPEN, openData));\n                    }\n                });\n\n                // finally set the active pane\n                AsyncUtils.waitForAll(promises).then(function () {\n                    setActivePaneId(state.activePaneId);\n                });\n            });\n        }\n    }\n\n    /**\n     * Saves the workingset state\n     * @private\n     */\n    function _saveViewState() {\n        function _computeSplitPercentage() {\n            var available,\n                used;\n\n            if (getPaneCount() === 1) {\n                // just short-circuit here and\n                //  return 100% to avoid any rounding issues\n                return 1;\n            } else {\n                if (_orientation === VERTICAL) {\n                    available = _$el.innerWidth();\n                    used = _panes[FIRST_PANE].$el.width();\n                } else {\n                    available = _$el.innerHeight();\n                    used = _panes[FIRST_PANE].$el.height();\n                }\n\n                return used / available;\n            }\n        }\n\n        var projectRoot     = ProjectManager.getProjectRoot(),\n            context         = { location : { scope: \"user\",\n                                         layer: \"project\",\n                                         layerID: projectRoot.fullPath } },\n\n            state = {\n                orientation: _orientation,\n                activePaneId: getActivePaneId(),\n                splitPercentage: _computeSplitPercentage(),\n                panes: {\n                }\n            };\n\n\n        if (!projectRoot) {\n            return;\n        }\n\n        _.forEach(_panes, function (pane) {\n            state.panes[pane.id] = pane.saveState();\n        });\n\n        PreferencesManager.setViewState(PREFS_NAME, state, context);\n    }\n\n    /**\n     * Initializes the MainViewManager's view state\n     * @param {jQuery} $container - the container where the main view will live\n     * @private\n     */\n    function _initialize($container) {\n        if (_activePaneId) {\n            throw new Error(\"MainViewManager has already been initialized\");\n        }\n\n        _$el = $container;\n        _createPaneIfNecessary(FIRST_PANE);\n        _activePaneId = FIRST_PANE;\n        // One-time init so the pane has the \"active\" appearance\n        _panes[FIRST_PANE]._handleActivePaneChange(undefined, _activePaneId);\n        _initialLayout();\n\n        // This ensures that unit tests that use this function\n        //  get an event handler for workspace events and we don't listen\n        //  to the event before we've been initialized\n        WorkspaceManager.on(\"workspaceUpdateLayout\", _updateLayout);\n\n        // Listen to key Alt-W to toggle between panes\n        CommandManager.register(Strings.CMD_SWITCH_PANE_FOCUS, Commands.CMD_SWITCH_PANE_FOCUS, switchPaneFocus);\n        KeyBindingManager.addBinding(Commands.CMD_SWITCH_PANE_FOCUS, {key: 'Alt-W'});\n    }\n\n    /**\n     * Changes the layout scheme\n     * @param {!number} rows (may be 1 or 2)\n     * @param {!number} columns (may be 1 or 2)\n     * @summay Rows or Columns may be 1 or 2 but both cannot be 2. 1x2, 2x1 or 1x1 are the legal values\n     */\n    function setLayoutScheme(rows, columns) {\n        if ((rows < 1) || (rows > 2) || (columns < 1) || (columns > 2) || (columns === 2 && rows === 2)) {\n            console.error(\"setLayoutScheme unsupported layout \" + rows + \", \" + columns);\n            return false;\n        }\n\n        if (rows === columns) {\n            _mergePanes();\n        } else if (rows > columns) {\n            _doSplit(HORIZONTAL);\n        } else {\n            _doSplit(VERTICAL);\n        }\n        return true;\n    }\n\n    /**\n     * Retrieves the current layout scheme\n     * @return {!{rows: number, columns: number>}}\n     */\n    function getLayoutScheme() {\n        var result = {\n            rows: 1,\n            columns: 1\n        };\n\n        if (_orientation === HORIZONTAL) {\n            result.rows = 2;\n        } else if (_orientation === VERTICAL) {\n            result.columns = 2;\n        }\n\n        return result;\n    }\n    \n    \n    /**\n     * Setup a ready event to initialize ourself\n     */\n    AppInit.htmlReady(function () {\n        _initialize($(\"#editor-holder\"));\n    });\n\n    // Event handlers - not safe to call on() directly, due to circular dependencies\n    EventDispatcher.on_duringInit(ProjectManager, \"projectOpen\",                       _loadViewState);\n    EventDispatcher.on_duringInit(ProjectManager, \"beforeProjectClose beforeAppClose\", _saveViewState);\n    EventDispatcher.on_duringInit(EditorManager, \"activeEditorChange\",                 _activeEditorChange);\n    EventDispatcher.on_duringInit(DocumentManager, \"pathDeleted\",                      _removeDeletedFileFromMRU);\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Unit Test Helpers\n    exports._initialize                   = _initialize;\n    exports._getPane                      = _getPane;\n\n    // Private Helpers\n    exports._removeView                   = _removeView;\n    exports._moveView                     = _moveView;\n\n    // Private API\n    exports._sortWorkingSet               = _sortWorkingSet;\n    exports._moveWorkingSetItem           = _moveWorkingSetItem;\n    exports._swapWorkingSetListIndexes    = _swapWorkingSetListIndexes;\n    exports._destroyEditorIfNotNeeded     = _destroyEditorIfNotNeeded;\n    exports._edit                         = _edit;\n    exports._open                         = _open;\n    exports._close                        = _close;\n    exports._closeAll                     = _closeAll;\n    exports._closeList                    = _closeList;\n    exports._getPaneIdForPath             = _getPaneIdForPath;\n\n    // WorkingSet Management\n    exports.addToWorkingSet               = addToWorkingSet;\n    exports.addListToWorkingSet           = addListToWorkingSet;\n    exports.getWorkingSetSize             = getWorkingSetSize;\n    exports.getWorkingSet                 = getWorkingSet;\n\n    // Pane state\n    exports.cacheScrollState              = cacheScrollState;\n    exports.restoreAdjustedScrollState    = restoreAdjustedScrollState;\n\n    // Searching\n    exports.findInWorkingSet              = findInWorkingSet;\n    exports.findInWorkingSetByAddedOrder  = findInWorkingSetByAddedOrder;\n    exports.findInWorkingSetByMRUOrder    = findInWorkingSetByMRUOrder;\n    exports.findInAllWorkingSets          = findInAllWorkingSets;\n    exports.findInGlobalMRUList           = _findFileInMRUList;\n\n    // Traversal\n    exports.beginTraversal                = beginTraversal;\n    exports.endTraversal                  = endTraversal;\n    exports.traverseToNextViewByMRU       = traverseToNextViewByMRU;\n    exports.traverseToNextViewInListOrder = traverseToNextViewInListOrder;\n\n    // PaneView Attributes\n    exports.getActivePaneId               = getActivePaneId;\n    exports.setActivePaneId               = setActivePaneId;\n    exports.getPaneIdList                 = getPaneIdList;\n    exports.getPaneTitle                  = getPaneTitle;\n    exports.getPaneCount                  = getPaneCount;\n    exports.isExclusiveToPane             = isExclusiveToPane;\n\n    exports.getAllOpenFiles               = getAllOpenFiles;\n    exports.focusActivePane               = focusActivePane;\n    exports.switchPaneFocus               = switchPaneFocus;\n\n    // Layout\n    exports.setLayoutScheme               = setLayoutScheme;\n    exports.getLayoutScheme               = getLayoutScheme;\n\n    // Convenience\n    exports.getCurrentlyViewedFile        = getCurrentlyViewedFile;\n    exports.getCurrentlyViewedPath        = getCurrentlyViewedPath;\n\n    // Constants\n    exports.ALL_PANES                     = ALL_PANES;\n    exports.ACTIVE_PANE                   = ACTIVE_PANE;\n    exports.FIRST_PANE                    = FIRST_PANE;\n    exports.SECOND_PANE                   = SECOND_PANE;\n});\n"
  },
  {
    "path": "src/view/Pane.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n /**\n  * Pane objects host views of files, editors, etc... Clients cannot access\n  * Pane objects directly. Instead the implementation is protected by the\n  * MainViewManager -- however View Factories are given a Pane object which\n  * they can use to add views.  References to Pane objects should not be kept\n  * as they may be destroyed and removed from the DOM.\n  *\n  * To get a custom view, there are two components:\n  *\n  *  1) A View Factory\n  *  2) A View Object\n  *\n  * View objects are anonymous object that have a particular interface.\n  *\n  * Views can be added to a pane but do not have to exist in the Pane object's view list.\n  * Such views are \"temporary views\".  Temporary views are not serialized with the Pane state\n  * or reconstituted when the pane is serialized from disk.  They are destroyed at the earliest\n  * opportunity.\n  *\n  * Temporary views are added by calling `Pane.showView()` and passing it the view object. The view\n  * will be destroyed when the next view is shown, the pane is mereged with another pane or the \"Close All\"\n  * command is exectuted on the Pane.  Temporary Editor Views do not contain any modifications and are\n  * added to the workingset (and are no longer tempoary views) once the document has been modified. They\n  * will remain in the working set until closed from that point on.\n  *\n  * Views that have a longer life span are added by calling addView to associate the view with a\n  * filename in the _views object.  These views are not destroyed until they are removed from the pane\n  * by calling one of the following: removeView, removeViews, or _reset\n  *\n  * Pane Object Events:\n  *\n  *  - viewListChange - Whenever there is a file change to a file in the working set.  These 2 events: `DocumentManager.pathRemove`\n  *  and `DocumentManager.fileNameChange` will cause a `viewListChange` event so the WorkingSetView can update.\n  *\n  *  - currentViewChange - Whenever the current view changes.\n  *             (e, newView:View, oldView:View)\n  *\n  *  - viewDestroy - Whenever a view has been destroyed\n  *             (e, view:View)\n  *\n  * View Interface:\n  *\n  * The view is an anonymous object which has the following method signatures. see ImageViewer for an example or the sample\n  * provided with Brackets `src/extensions/samples/BracketsConfigCentral`\n  *\n  *     {\n  *         $el:jQuery\n  *         getFile: function ():!File\n  *         updateLayout: function(forceRefresh:boolean)\n  *         destroy: function()\n  *         getScrollPos: function():*=\n  *         adjustScrollPos: function(state:Object=, heightDelta:number)=\n  *         notifyContainerChange: function()=\n  *         notifyVisibilityChange: function(boolean)=\n  *         focus:function()=\n  *     }\n  *\n  * When views are created they can be added to the pane by calling `pane.addView()`.\n  * Views can be created and parented by attaching directly  to `pane.$el`\n  *\n  *     this._codeMirror = new CodeMirror(pane.$el, ...)\n  *\n  * Factories can create a view that's initially hidden by calling `pane.addView(view)` and passing `false` for the show parameter.\n  * Hidden views can be later shown by calling `pane.showView(view)`\n  *\n  * `$el:jQuery!`\n  *\n  *  property that stores the jQuery wrapped DOM element of the view. All views must have one so pane objects can manipulate the DOM\n  *  element when necessary (e.g. `showView`, `_reparent`, etc...)\n  *\n  * `getFile():File!`\n  *\n  *  Called throughout the life of a View when the current file is queried by the system.\n  *\n  * `updateLayout(forceRefresh:boolean)`\n  *\n  *  Called to notify the view that it should be resized to fit its parent container.  This may be called several times\n  *  or only once.  Views can ignore the `forceRefresh` flag. It is used for editor views to force a relayout of the editor\n  *  which probably isn't necessary for most views.  Views should implement their html to be dynamic and not rely on this\n  *  function to be called whenever possible.\n  *\n  * `destroy()`\n  *\n  *  Views must implement a destroy method to remove their DOM element at the very least.  There is no default\n  *  implementation and views are hidden before this method is called. The Pane object doesn't make assumptions\n  *  about when it is safe to remove a node. In some instances other cleanup  must take place before a the DOM\n  *  node is destroyed so the implementation details are left to the view.\n  *\n  *  Views can implement a simple destroy by calling\n  *\n  *      this.$el.remove()\n  *\n  *  These members are optional and need not be implemented by Views\n  *\n  *      getScrollPos()\n  *      adjustScrollPos()\n  *\n  *  The system at various times will want to save and restore a view's scroll position.  The data returned by `getScrollPos()`\n  *  is specific to the view and will be passed back to `adjustScrollPos()` when the scroll position needs to be restored.\n  *\n  *  When Modal Bars are invoked, the system calls `getScrollPos()` so that the current scroll psotion of all visible Views can be cached.\n  *  That cached scroll position is later passed to `adjustScrollPos()` along with a height delta.  The height delta is used to\n  *  scroll the view so that it doesn't appear to have \"jumped\" when invoking the Modal Bar.\n  *\n  *  Height delta will be a positive when the Modal Bar is being shown and negative number when the Modal Bar is being hidden.\n  *\n  *  `getViewState()` is another optional member that is used to cache a view's state when hiding or destroying a view or closing the project.\n  *  The data returned by this member is stored in `ViewStateManager` and is saved with the project.\n  *\n  *  Views or View Factories are responsible for restoring the view state when the view of that file is created by recalling the cached state\n  *\n  *      var view = createIconView(file, pane);\n  *      view.restoreViewState(ViewStateManager.getViewState(file.fullPath));\n  *\n  *  Notifications\n  *  The following optional methods receive notifications from the Pane object when certain events take place which affect the view:\n  *\n  * `notifyContainerChange()`\n  *\n  *  Optional Notification callback called when the container changes. The view can perform any synchronization or state update\n  *  it needs to do when its parent container changes.\n  *\n  * `notifyVisiblityChange()`\n  *\n  *  Optional Notification callback called when the view's vsibility changes.  The view can perform any synchronization or\n  *  state update it needs to do when its visiblity state changes.\n  */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                   = require(\"thirdparty/lodash\"),\n        Mustache            = require(\"thirdparty/mustache/mustache\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        FileSystem          = require(\"filesystem/FileSystem\"),\n        InMemoryFile        = require(\"document/InMemoryFile\"),\n        ViewStateManager    = require(\"view/ViewStateManager\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        paneTemplate        = require(\"text!htmlContent/pane.html\");\n\n    /**\n     * Internal pane id\n     * @const\n     * @private\n     */\n    var FIRST_PANE          = \"first-pane\";\n\n    /**\n     * Internal pane id\n     * @const\n     * @private\n     */\n    var SECOND_PANE         = \"second-pane\";\n\n    // Define showPaneHeaderButtons, which controls when to show close and flip-view buttons\n    // on the header.\n    PreferencesManager.definePreference(\"pane.showPaneHeaderButtons\", \"string\", \"hover\", {\n        description: Strings.DESCRIPTION_SHOW_PANE_HEADER_BUTTONS,\n        values: [\"hover\", \"always\", \"never\"]\n    });\n\n    // Define mergePanesWhenLastFileClosed, which controls if a split view pane should be\n    // closed when the last file is closed, skipping the \"Open a file while this pane has focus\"\n    // step completely.\n    PreferencesManager.definePreference(\"pane.mergePanesWhenLastFileClosed\", \"boolean\", false, {\n        description: Strings.DESCRIPTION_MERGE_PANES_WHEN_LAST_FILE_CLOSED\n    });\n\n    /**\n     * Make an index request object\n     * @param {boolean} requestIndex - true to request an index, false if not\n     * @param {number} index - the index to request\n     * @return {indexRequested:boolean, index:number} an object that can be passed to\n     * {@link Pane#addToViewList} to insert the item at a specific index\n     * @see Pane#addToViewList\n     */\n    function _makeIndexRequestObject(requestIndex, index) {\n        return {indexRequested: requestIndex, index: index};\n    }\n\n    /**\n     * Ensures that the given pane is focused after other focus related events occur\n     * @params {string} paneId - paneId of the pane to focus\n     * @private\n     */\n    function _ensurePaneIsFocused(paneId) {\n        var pane = MainViewManager._getPane(paneId);\n\n        // Defer the focusing until other focus events have occurred.\n        setTimeout(function () {\n            // Focus has most likely changed: give it back to the given pane.\n            pane.focus();\n            this._lastFocusedElement = pane.$el[0];\n            MainViewManager.setActivePaneId(paneId);\n        }, 1);\n    }\n\n    /**\n     * @typedef {!$el: jQuery, getFile:function():!File, updateLayout:function(forceRefresh:boolean), destroy:function(),  getScrollPos:function():?,  adjustScrollPos:function(state:Object=, heightDelta:number)=, getViewState:function():?*=, restoreViewState:function(viewState:!*)=, notifyContainerChange:function()=, notifyVisibilityChange:function(boolean)=} View\n     */\n\n    /**\n     * Pane Objects are constructed by the MainViewManager object when a Pane view is needed\n     * @see {@link MainViewManager} for more information\n     *\n     * @constructor\n     * @param {!string} id - The id to use to identify this pane\n     * @param {!JQuery} $container - The parent $container to place the pane view\n     */\n    function Pane(id, $container) {\n        this._initialize();\n\n        // Setup the container and the element we're inserting\n        var self = this,\n            showPaneHeaderButtonsPref = PreferencesManager.get(\"pane.showPaneHeaderButtons\"),\n            $el = $container.append(Mustache.render(paneTemplate, {id: id})).find(\"#\" + id),\n            $header  = $el.find(\".pane-header\"),\n            $headerText = $header.find(\".pane-header-text\"),\n            $headerFlipViewBtn = $header.find(\".pane-header-flipview-btn\"),\n            $headerCloseBtn = $header.find(\".pane-header-close-btn\"),\n            $content = $el.find(\".pane-content\");\n\n        $el.on(\"focusin.pane\", function (e) {\n            self._lastFocusedElement = e.target;\n        });\n\n        // Flips the current file to the other pane when clicked\n        $headerFlipViewBtn.on(\"click.pane\", function (e) {\n            var currentFile = self.getCurrentlyViewedFile();\n            var otherPaneId = self.id === FIRST_PANE ? SECOND_PANE : FIRST_PANE;\n            var otherPane = MainViewManager._getPane(otherPaneId);\n            var sameDocInOtherView = otherPane.getViewForPath(currentFile.fullPath);\n            \n            // If the same doc view is present in the destination, show the file instead of flipping it\n            if (sameDocInOtherView) {\n                CommandManager.execute(Commands.FILE_OPEN, {fullPath: currentFile.fullPath,\n                                                            paneId: otherPaneId}).always(function () {\n                    _ensurePaneIsFocused(otherPaneId);\n                });\n                return;\n            }\n\n            // Currently active pane is not necessarily self.id as just clicking the button does not\n            // give focus to the pane. This way it is possible to flip multiple panes to the active one\n            // without losing focus.\n            var activePaneIdBeforeFlip = MainViewManager.getActivePaneId();\n\n            MainViewManager._moveView(self.id, otherPaneId, currentFile).always(function () {\n                CommandManager.execute(Commands.FILE_OPEN, {fullPath: currentFile.fullPath,\n                                                            paneId: otherPaneId}).always(function () {\n                    // Trigger view list changes for both panes\n                    self.trigger(\"viewListChange\");\n                    otherPane.trigger(\"viewListChange\");\n                    _ensurePaneIsFocused(activePaneIdBeforeFlip);\n                });\n            });\n        });\n\n        // Closes the current view on the pane when clicked. If pane has no files, merge\n        // panes.\n        $headerCloseBtn.on(\"click.pane\", function () {\n            //set clicked pane as active to ensure that this._currentView is updated before closing\n            MainViewManager.setActivePaneId(self.id);\n            var file = self.getCurrentlyViewedFile();\n\n            if (file) {\n                CommandManager.execute(Commands.FILE_CLOSE, {File: file, paneId: self.id});\n\n                if (!self.getCurrentlyViewedFile() && PreferencesManager.get(\"pane.mergePanesWhenLastFileClosed\")) {\n                    MainViewManager.setLayoutScheme(1, 1);\n                }\n            } else {\n                MainViewManager.setLayoutScheme(1, 1);\n            }\n        });\n\n        this._lastFocusedElement = $el[0];\n\n        // Make these properties read only\n        Object.defineProperty(this,  \"id\", {\n            get: function () {\n                return id;\n            },\n            set: function () {\n                console.error(\"cannot change the id of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$el\", {\n            get: function () {\n                return $el;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$header\", {\n            get: function () {\n                return $header;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$headerText\", {\n            get: function () {\n                return $headerText;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$headerFlipViewBtn\", {\n            get: function () {\n                return $headerFlipViewBtn;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$headerCloseBtn\", {\n            get: function () {\n                return $headerCloseBtn;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$content\", {\n            get: function () {\n                return $content;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        Object.defineProperty(this,  \"$container\", {\n            get: function () {\n                return $container;\n            },\n            set: function () {\n                console.error(\"cannot change the DOM node of a working pane\");\n            }\n        });\n\n        this.updateHeaderText();\n\n        switch (showPaneHeaderButtonsPref) {\n        case \"always\":\n            this.$header.addClass(\"always-show-header-buttons\");\n            break;\n        case \"never\":\n            this.$headerFlipViewBtn.css(\"display\", \"none\");\n            this.$headerCloseBtn.css(\"display\", \"none\");\n            break;\n        }\n\n        // Listen to document events so we can update ourself\n        DocumentManager.on(this._makeEventName(\"fileNameChange\"),  _.bind(this._handleFileNameChange, this));\n        DocumentManager.on(this._makeEventName(\"pathDeleted\"), _.bind(this._handleFileDeleted, this));\n        MainViewManager.on(this._makeEventName(\"activePaneChange\"), _.bind(this._handleActivePaneChange, this));\n        MainViewManager.on(this._makeEventName(\"workingSetAdd\"), _.bind(this.updateHeaderText, this));\n        MainViewManager.on(this._makeEventName(\"workingSetRemove\"), _.bind(this.updateHeaderText, this));\n        MainViewManager.on(this._makeEventName(\"workingSetAddList\"), _.bind(this.updateHeaderText, this));\n        MainViewManager.on(this._makeEventName(\"workingSetRemoveList\"), _.bind(this.updateHeaderText, this));\n        MainViewManager.on(this._makeEventName(\"paneLayoutChange\"), _.bind(this.updateFlipViewIcon, this));\n    }\n    EventDispatcher.makeEventDispatcher(Pane.prototype);\n\n    /**\n     * id of the pane\n     * @readonly\n     * @type {!string}\n     */\n    Pane.prototype.id = null;\n\n    /**\n     * container where the pane lives\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$container = null;\n\n    /**\n     * the wrapped DOM node of this pane\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$el = null;\n\n    /**\n     * the wrapped DOM node container that contains name of current view and the switch view button, or informational string if there is no view\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$header = null;\n\n    /**\n     * the wrapped DOM node that contains name of current view, or informational string if there is no view\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$headerText = null;\n\n    /**\n     * the wrapped DOM node that is used to flip the view to another pane\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$headerFlipViewBtn = null;\n\n    /**\n     * close button of the pane\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$headerCloseBtn = null;\n\n    /**\n     * the wrapped DOM node that contains views\n     * @readonly\n     * @type {JQuery}\n     */\n    Pane.prototype.$content = null;\n\n    /**\n     * The list of files views\n     * @type {Array.<File>}\n     */\n    Pane.prototype._viewList = [];\n\n    /**\n     * The list of files views in MRU order\n     * @type {Array.<File>}\n     */\n    Pane.prototype._viewListMRUOrder = [];\n\n    /**\n     * The list of files views in Added order\n     * @type {Array.<File>}\n     */\n    Pane.prototype._viewListAddedOrder = [];\n\n    /**\n     * Dictionary mapping fullpath to view\n     * @type {Object.<!string, !View>}\n     * @private\n     */\n    Pane.prototype._views = {};\n\n    /**\n     * The current view\n     * @type {?View}\n     * @private\n     */\n    Pane.prototype._currentView = null;\n\n    /**\n     * The last thing that received a focus event\n     * @type {?DomElement}\n     * @private\n     */\n    Pane.prototype._lastFocusedElement = null;\n\n    /**\n     * Initializes the Pane to its default state\n     * @private\n     */\n    Pane.prototype._initialize = function () {\n        this._viewList = [];\n        this._viewListMRUOrder = [];\n        this._viewListAddedOrder = [];\n        this._views = {};\n        this._currentView = null;\n        this.showInterstitial(true);\n    };\n\n   /**\n     * Creates a pane event namespaced to this pane\n     * (pass an empty string to generate just the namespace key to pass to jQuery to turn off all events handled by this pane)\n     * @private\n     * @param {!string} name - the name of the event to namespace\n     * @return {string} an event namespaced to this pane\n     */\n    Pane.prototype._makeEventName = function (name) {\n        return name + \".pane-\" + this.id;\n    };\n\n   /**\n     * Reparents a view to this pane\n     * @private\n     * @param {!View} view - the view to reparent\n     */\n    Pane.prototype._reparent = function (view) {\n        view.$el.appendTo(this.$content);\n        this._views[view.getFile().fullPath] = view;\n        if (view.notifyContainerChange) {\n            view.notifyContainerChange();\n        }\n    };\n\n    /**\n     * Hides the current view if there is one, shows the\n     *  interstitial screen and notifies that the view changed\n     */\n    Pane.prototype._hideCurrentView = function () {\n        if (this._currentView) {\n            var currentView = this._currentView;\n            this._setViewVisibility(this._currentView, false);\n            this.showInterstitial(true);\n            this._currentView = null;\n            this._notifyCurrentViewChange(null, currentView);\n        }\n    };\n\n    /**\n     * moves a view from one pane to another\n     * @param {!File} file - the File to move\n     * @param {Pane} destinationPane - the destination pane\n     * @param {Number} destinationIndex - the working set index of the file in the destination pane\n     * @return {jQuery.Promise} a promise object which resolves after the view has been moved and its\n     * replacement document has been opened\n     * @private\n     */\n    Pane.prototype.moveView = function (file, destinationPane, destinationIndex) {\n        var self = this,\n            openNextPromise = new $.Deferred(),\n            result = new $.Deferred();\n\n        // if we're moving the currently viewed file we\n        //  need to open another file so wait for that operation\n        //  to finish before we move the view\n        if ((this.getCurrentlyViewedPath() === file.fullPath)) {\n            var nextFile = this.traverseViewListByMRU(1, file.fullPath);\n            if (nextFile) {\n                this._execOpenFile(nextFile.fullPath)\n                    .fail(function () {\n                        // the FILE_OPEN failed\n                        self._hideCurrentView();\n                    })\n                    .always(function () {\n                        openNextPromise.resolve();\n                    });\n            } else {\n                this._hideCurrentView();\n                openNextPromise.resolve();\n            }\n        } else {\n            openNextPromise.resolve();\n        }\n\n        // Once the next file has opened, we can\n        //  move the item in the working set and\n        //  open it in the destination pane\n        openNextPromise.done(function () {\n            var viewListIndex = self.findInViewList(file.fullPath);\n            var shouldAddView = viewListIndex !== -1;\n            var view = self._views[file.fullPath];\n\n            // If the file isn't in working set, destroy the view and delete it from\n            // source pane's view map and return as solved\n            if (!shouldAddView) {\n                if (view) {\n                    self._doDestroyView(view);\n                }\n                return result.resolve();\n            }\n\n            // Remove file from all 3 view lists\n            self._viewList.splice(viewListIndex, 1);\n            self._viewListMRUOrder.splice(self.findInViewListMRUOrder(file.fullPath), 1);\n            self._viewListAddedOrder.splice(self.findInViewListAddedOrder(file.fullPath), 1);\n\n            // insert the view into the working set\n            destinationPane._addToViewList(file,  _makeIndexRequestObject(true, destinationIndex));\n\n            // if we had a view, it had previously been opened\n            // otherwise, the file was in the working set unopened\n            if (view) {\n                // delete it from the source pane's view map and add it to the destination pane's view map\n                delete self._views[file.fullPath];\n                destinationPane.addView(view, !destinationPane.getCurrentlyViewedFile());\n\n                // we're done\n                result.resolve();\n            } else if (!destinationPane.getCurrentlyViewedFile()) {\n                // The view has not have been created and the pane was\n                //  not showing anything so open the file moved in to the pane\n                destinationPane._execOpenFile(file.fullPath).always(function () {\n                    // wait until the file has been opened before\n                    //  we resolve the promise so the working set\n                    //  view can sync appropriately\n                    result.resolve();\n                });\n            } else {\n                // nothing to do, we're done\n                result.resolve();\n            }\n        });\n        return result.promise();\n    };\n\n    /**\n     * Merges the another Pane object's contents into this Pane\n     * @param {!Pane} Other - Pane from which to copy\n     */\n    Pane.prototype.mergeFrom = function (other) {\n        // save this because we're setting it to null and we\n        //  may need to destroy it if it's a temporary view\n        var otherCurrentView = other._currentView;\n\n        // Hide the current view while we\n        //  merge the 2 panes together\n        other._hideCurrentView();\n\n        // Copy the File lists\n        this._viewList = _.union(this._viewList, other._viewList);\n        this._viewListMRUOrder = _.union(this._viewListMRUOrder, other._viewListMRUOrder);\n        this._viewListAddedOrder = _.union(this._viewListAddedOrder, other._viewListAddedOrder);\n\n        var self = this,\n            viewsToDestroy = [];\n\n        // Copy the views\n        _.forEach(other._views, function (view) {\n            var file = view.getFile(),\n                fullPath = file && file.fullPath;\n            if (fullPath && other.findInViewList(fullPath) !== -1) {\n                // switch the container to this Pane\n                self._reparent(view);\n            } else {\n                // We don't copy temporary views so destroy them\n                viewsToDestroy.push(view);\n            }\n        });\n\n        // 1-off views\n        if (otherCurrentView && !other._isViewNeeded(otherCurrentView) && viewsToDestroy.indexOf(otherCurrentView) === -1) {\n            viewsToDestroy.push(otherCurrentView);\n        }\n\n        // Destroy temporary views\n        _.forEach(viewsToDestroy, function (view) {\n            self.trigger(\"viewDestroy\", view);\n            view.destroy();\n        });\n\n        // this _reset all internal data structures\n        //  and will set the current view to null\n        other._initialize();\n    };\n\n    /**\n     * Removes the DOM node for the Pane, removes all\n     *  event handlers and _resets all internal data structures\n     */\n    Pane.prototype.destroy = function () {\n        if (this._currentView ||\n                Object.keys(this._views).length > 0 ||\n                this._viewList.length > 0) {\n            console.warn(\"destroying a pane that isn't empty\");\n        }\n\n        this._reset();\n\n        DocumentManager.off(this._makeEventName(\"\"));\n        MainViewManager.off(this._makeEventName(\"\"));\n\n        this.$el.off(\".pane\");\n        this.$el.remove();\n    };\n\n   /**\n     * Returns a copy of the view file list\n     * @return {!Array.<File>}\n     */\n    Pane.prototype.getViewList = function () {\n        return _.clone(this._viewList);\n    };\n\n    /**\n     * Returns the number of entries in the view file list\n     * @return {number}\n     */\n    Pane.prototype.getViewListSize = function () {\n        return this._viewList.length;\n    };\n\n    /**\n     * Returns the index of the item in the view file list\n     * @param {!string} fullPath the full path of the item to look for\n     * @return {number} index of the item or -1 if not found\n     */\n    Pane.prototype.findInViewList = function (fullPath) {\n        return _.findIndex(this._viewList, function (file) {\n            return file.fullPath === fullPath;\n        });\n    };\n\n    /**\n     * Returns the order in which the item was added\n     * @param {!string} fullPath the full path of the item to look for\n     * @return {number} order of the item or -1 if not found\n     */\n    Pane.prototype.findInViewListAddedOrder = function (fullPath) {\n        return _.findIndex(this._viewListAddedOrder, function (file) {\n            return file.fullPath === fullPath;\n        });\n    };\n\n   /**\n     * Returns the order in which the item was last used\n     * @param {!string} fullPath the full path of the item to look for\n     * @return {number} order of the item or -1 if not found.\n     *      0 indicates most recently used, followed by 1 and so on...\n     */\n    Pane.prototype.findInViewListMRUOrder = function (fullPath) {\n        return _.findIndex(this._viewListMRUOrder, function (file) {\n            return file.fullPath === fullPath;\n        });\n    };\n\n    /**\n     * Return value from reorderItem when the Item was not found\n     * @see {@link Pane#reorderItem}\n     * @const\n     */\n    Pane.prototype.ITEM_NOT_FOUND = -1;\n\n    /**\n     * Return value from reorderItem when the Item was found at its natural index\n     * and the workingset does not need to be resorted\n     * @see {@link Pane#reorderItem}\n     * @const\n     */\n    Pane.prototype.ITEM_FOUND_NO_SORT = 0;\n\n    /**\n     * Return value from reorderItem when the Item was found and reindexed\n     * and the workingset needs to be resorted\n     * @see {@link Pane#reorderItem}\n     * @const\n     */\n    Pane.prototype.ITEM_FOUND_NEEDS_SORT = 1;\n\n    /**\n     * reorders the specified file in the view list to the desired position\n     *\n     * @param {File} file - the file object of the item to reorder\n     * @param {number=} index - the new position of the item\n     * @param {boolean=} force - true to force the item into that position, false otherwise.  (Requires an index be requested)\n     * @return {number} this function returns one of the following manifest constants:\n     *            ITEM_NOT_FOUND        : The request file object was not found\n     *            ITEM_FOUND_NO_SORT    : The request file object was found but it was already at the requested index\n     *            ITEM_FOUND_NEEDS_SORT : The request file object was found and moved to a new index and the list should be resorted\n     */\n    Pane.prototype.reorderItem = function (file, index, force) {\n        var indexRequested = (index !== undefined && index !== null && index >= 0),\n            curIndex = this.findInViewList(file.fullPath);\n\n        if (curIndex !== -1) {\n            // File is in view list, but not at the specifically requested index - only need to reorder\n            if (force || (indexRequested && curIndex !== index)) {\n                var entry = this._viewList.splice(curIndex, 1)[0];\n                this._viewList.splice(index, 0, entry);\n                return this.ITEM_FOUND_NEEDS_SORT;\n            }\n            return this.ITEM_FOUND_NO_SORT;\n        }\n\n        return this.ITEM_NOT_FOUND;\n    };\n\n    /**\n     * Determines if a file can be added to our file list\n     * @private\n     * @param {!File} file - file object to test\n     * @return {boolean} true if it can be added, false if not\n     */\n    Pane.prototype._canAddFile = function (file) {\n        return ((this._views.hasOwnProperty(file.fullPath) && this.findInViewList(file.fullPath) === -1) ||\n                    (MainViewManager._getPaneIdForPath(file.fullPath) !== this.id));\n    };\n\n    /**\n     * Adds the given file to the end of the workingset, if it is not already in the list\n     * @private\n     * @param {!File} file\n     * @param {Object=} inPlace record with inPlace add data (index, indexRequested). Used internally\n     */\n    Pane.prototype._addToViewList = function (file, inPlace) {\n        if (inPlace && inPlace.indexRequested) {\n            // If specified, insert into the workingset at this 0-based index\n            this._viewList.splice(inPlace.index, 0, file);\n        } else {\n            // If no index is specified, just add the file to the end of the workingset.\n            this._viewList.push(file);\n        }\n\n        // Add to MRU order: either first or last, depending on whether it's already the current doc or not\n        var currentPath = this.getCurrentlyViewedPath();\n        if (currentPath && currentPath === file.fullPath) {\n            this._viewListMRUOrder.unshift(file);\n        } else {\n            this._viewListMRUOrder.push(file);\n        }\n\n        // Add first to Added order\n        this._viewListAddedOrder.unshift(file);\n    };\n\n\n    /**\n     * Adds the given file to the end of the workingset, if it is not already in the list\n     * Does not change which document is currently open in the editor. Completes synchronously.\n     * @param {!File} file - file to add\n     * @param {number=} index - position where to add the item\n     * @return {number} index of where the item was added\n     */\n    Pane.prototype.addToViewList = function (file, index) {\n        var indexRequested = (index !== undefined && index !== null && index >= 0 && index < this._viewList.length);\n        this._addToViewList(file, _makeIndexRequestObject(indexRequested, index));\n\n        if (!indexRequested) {\n            index = this._viewList.length - 1;\n        }\n\n        return index;\n    };\n\n\n    /**\n     * Adds the given file list to the end of the workingset.\n     * @param {!Array.<File>} fileList\n     * @return {!Array.<File>} list of files added to the list\n     */\n    Pane.prototype.addListToViewList = function (fileList) {\n        var self = this,\n            uniqueFileList = [];\n\n        // Process only files not already in view list\n        fileList.forEach(function (file) {\n            if (self._canAddFile(file)) {\n                self._addToViewList(file);\n                uniqueFileList.push(file);\n            }\n        });\n\n        return uniqueFileList;\n    };\n\n    /**\n     * Dispatches a currentViewChange event\n     * @param {?View} newView - the view become the current view\n     * @param {?View} oldView - the view being replaced\n     */\n    Pane.prototype._notifyCurrentViewChange = function (newView, oldView) {\n        this.updateHeaderText();\n\n        this.trigger(\"currentViewChange\", newView, oldView);\n    };\n\n\n    /**\n     * Destroys a view and removes it from the view map. If it is the current view then the view\n     * is first hidden and the interstitial page is displayed\n     * @private\n     * @param {!View} view - view to destroy\n     */\n    Pane.prototype._doDestroyView = function (view) {\n        if (this._currentView === view) {\n            // if we're removing the current\n            //  view then we need to hide the view\n            this._hideCurrentView();\n        }\n        delete this._views[view.getFile().fullPath];\n        this.trigger(\"viewDestroy\", view);\n        view.destroy();\n    };\n\n    /**\n     * Removes the specifed file from all internal lists, destroys the view of the file (if there is one)\n     *  and shows the interstitial page if the current view is destroyed\n     * @private\n     * @param {!File} file - file to remove\n     * @param {boolean} preventViewChange - false to hide the current view if removing the current view, true\n     *                                      to prevent the current view from changing.\n     *\n     * When passing true for preventViewChange, it is assumed that the caller will perform an OPEN_FILE op\n     * to show the next file in line to view.  Since the file was removed from the workingset in _doRemove\n     * its view is now considered to be a temporary view and the call to showView for the OPEN_FILE op\n     * will destroy the view. the caller needs to handle the reject case in the event of failure\n     *\n     * @return {boolean} true if removed, false if the file was not found either in a list or view\n     */\n    Pane.prototype._doRemove = function (file, preventViewChange) {\n\n        // If it's in the view list then we need to remove it\n        var index = this.findInViewList(file.fullPath);\n\n        if (index > -1) {\n            // Remove it from all 3 view lists\n            this._viewList.splice(index, 1);\n            this._viewListMRUOrder.splice(this.findInViewListMRUOrder(file.fullPath), 1);\n            this._viewListAddedOrder.splice(this.findInViewListAddedOrder(file.fullPath), 1);\n        }\n\n        // Destroy the view\n        var view = this._views[file.fullPath];\n\n        if (view) {\n            if (!preventViewChange) {\n                this._doDestroyView(view);\n            }\n        }\n\n        return ((index > -1) || Boolean(view));\n    };\n\n    /**\n     * Moves the specified file to the front of the MRU list\n     * @param {!File} file\n     */\n    Pane.prototype.makeViewMostRecent = function (file) {\n        var index = this.findInViewListMRUOrder(file.fullPath);\n        if (index !== -1) {\n            this._viewListMRUOrder.splice(index, 1);\n            this._viewListMRUOrder.unshift(file);\n        }\n    };\n\n    /**\n     * Sorts items in the pane's view list\n     * @param {function(paneId:!string, left:!string, right:!string):number} compareFn - the function used to compare items in the viewList\n     */\n\n    /**\n     * invokes Array.sort method on the internal view list.\n     * @param {sortFunctionCallback} compareFn - the function to call to determine if the\n     */\n    Pane.prototype.sortViewList = function (compareFn) {\n        this._viewList.sort(_.partial(compareFn, this.id));\n    };\n\n    /**\n     * moves a working set item from one index to another shifting the items\n     * after in the working set up and reinserting it at the desired location\n     * @param {!number} fromIndex - the index of the item to move\n     * @param {!number} toIndex - the index to move to\n     * @private\n     */\n    Pane.prototype.moveWorkingSetItem = function (fromIndex, toIndex) {\n        this._viewList.splice(toIndex, 0, this._viewList.splice(fromIndex, 1)[0]);\n    };\n\n    /**\n     * Swaps two items in the file view list (used while dragging items in the working set view)\n     * @param {number} index1 - the index of the first item to swap\n     * @param {number} index2 - the index of the second item to swap\n     * @return {boolean}} true\n     */\n    Pane.prototype.swapViewListIndexes = function (index1, index2) {\n        var temp = this._viewList[index1];\n        this._viewList[index1] = this._viewList[index2];\n        this._viewList[index2] = temp;\n        return true;\n    };\n\n    /**\n     * Traverses the list and returns the File object of the next item in the MRU order\n     * @param {!number} direction - Must be 1 or -1 to traverse forward or backward\n     * @param {string=} current - the fullPath of the item where traversal is to start.\n     *                              If this parameter is omitted then the path of the current view is used.\n     *                              If the current view is a temporary view then the first item in the MRU list is returned\n     * @return {?File}  The File object of the next item in the travesal order or null if there isn't one.\n     */\n    Pane.prototype.traverseViewListByMRU = function (direction, current) {\n        if (!current && this._currentView) {\n            var file = this._currentView.getFile();\n            current = file && file.fullPath;\n        }\n\n        var index = current ? this.findInViewListMRUOrder(current) : -1;\n        return ViewUtils.traverseViewArray(this._viewListMRUOrder, index, direction);\n    };\n\n    /**\n     * Updates flipview icon in pane header\n     * @private\n     */\n    Pane.prototype.updateFlipViewIcon = function () {\n        var paneID = this.id,\n            directionIndex = 0,\n            ICON_CLASSES = [\"flipview-icon-none\", \"flipview-icon-top\", \"flipview-icon-right\", \"flipview-icon-bottom\", \"flipview-icon-left\"],\n            DIRECTION_STRINGS = [\"\", Strings.TOP, Strings.RIGHT, Strings.BOTTOM, Strings.LEFT],\n            layoutScheme = MainViewManager.getLayoutScheme(),\n            hasFile = this.getCurrentlyViewedFile();\n\n        if (layoutScheme.columns > 1 && hasFile) {\n            directionIndex = paneID === FIRST_PANE ? 2 : 4;\n        } else if (layoutScheme.rows > 1 && hasFile) {\n            directionIndex = paneID === FIRST_PANE ? 3 : 1;\n        }\n\n        this.$headerFlipViewBtn.removeClass(ICON_CLASSES.join(\" \"))\n                      .addClass(ICON_CLASSES[directionIndex]);\n\n        this.$headerFlipViewBtn.attr(\"title\", StringUtils.format(Strings.FLIPVIEW_BTN_TOOLTIP,  DIRECTION_STRINGS[directionIndex].toLowerCase()));\n    };\n\n    /**\n     * Updates text in pane header\n     * @private\n     */\n    Pane.prototype.updateHeaderText = function () {\n        var file = this.getCurrentlyViewedFile(),\n            files,\n            displayName;\n\n        if (file) {\n            files = MainViewManager.getAllOpenFiles().filter(function (item) {\n                return (item.name === file.name);\n            });\n            if (files.length < 2) {\n                this.$headerText.text(file.name);\n            } else {\n                displayName = ProjectManager.makeProjectRelativeIfPossible(file.fullPath);\n                this.$headerText.text(displayName);\n            }\n        } else {\n            this.$headerText.html(Strings.EMPTY_VIEW_HEADER);\n        }\n\n        this.updateFlipViewIcon();\n    };\n\n    /**\n     * Event handler when a file changes name\n     * @private\n     * @param {!JQuery.Event} e - jQuery event object\n     * @param {!string} oldname - path of the file that was renamed\n     * @param {!string} newname - the new path to the file\n     */\n    Pane.prototype._handleFileNameChange = function (e, oldname, newname) {\n        // Check to see if we need to dispatch a viewListChange event\n        // The list contains references to file objects and, for a rename event,\n        // the File object's name has changed by the time we've gotten the event.\n        // So, we need to look for the file by its new name to determine if\n        // if we need to dispatch the event which may look funny\n        var dispatchEvent = (this.findInViewList(newname) >= 0);\n\n        // rename the view\n        if (this._views.hasOwnProperty(oldname)) {\n            var view = this._views[oldname];\n\n            this._views[newname] = view;\n            delete this._views[oldname];\n        }\n\n        this.updateHeaderText();\n\n        // dispatch the change event\n        if (dispatchEvent) {\n            this.trigger(\"viewListChange\");\n        }\n    };\n\n    /**\n     * Event handler when a file is deleted\n     * @private\n     * @param {!JQuery.Event} e - jQuery event object\n     * @param {!string} fullPath - path of the file that was deleted\n     */\n    Pane.prototype._handleFileDeleted = function (e, fullPath) {\n        if (this.removeView({fullPath: fullPath})) {\n            this.trigger(\"viewListChange\");\n        }\n    };\n\n    /**\n     * Shows the pane's interstitial page\n     * @param {boolean} show - show or hide the interstitial page\n     */\n    Pane.prototype.showInterstitial = function (show) {\n        if (this.$content) {\n            this.$content.find(\".not-editor\").css(\"display\", (show) ? \"\" : \"none\");\n        }\n    };\n\n    /**\n     * retrieves the view object for the given path\n     * @param {!string}  path - the fullPath of the view to retrieve\n     * @return {boolean} show - show or hide the interstitial page\n     */\n    Pane.prototype.getViewForPath = function (path) {\n        return this._views[path];\n    };\n\n    /**\n     * Adds a view to the pane\n     * @param {!View} view - the View object to add\n     * @param {boolean} show - true to show the view right away, false otherwise\n     */\n    Pane.prototype.addView = function (view, show) {\n        var file = view.getFile(),\n            path = file && file.fullPath;\n\n        if (!path) {\n            console.error(\"cannot add a view that does not have a fullPath\");\n            return;\n        }\n\n        if (view.$el.parent() !== this.$content) {\n            this._reparent(view);\n        } else {\n            this._views[path] = view;\n        }\n\n        // Ensure that we don't endup marking the custom views\n        if (view.markPaneId) {\n            view.markPaneId(this.id);\n        }\n\n        if (show) {\n            this.showView(view);\n        }\n    };\n\n    /**\n     * Shows or hides a view\n     * @param {!View} view - the to show or hide\n     * @param {boolean} visible - true to show the view, false to hide it\n     * @private\n     */\n    Pane.prototype._setViewVisibility = function (view, visible) {\n        view.$el.css(\"display\", (visible ? \"\" : \"none\"));\n        if (view.notifyVisibilityChange) {\n            view.notifyVisibilityChange(visible);\n        }\n    };\n\n    /**\n     * Swaps the current view with the requested view.\n     * If the interstitial page is shown, it is hidden.\n     * If the currentView is a temporary view, it is destroyed.\n     * @param {!View} view - the to show\n     */\n    Pane.prototype.showView = function (view) {\n        if (this._currentView && this._currentView === view) {\n            this._setViewVisibility(this._currentView, true);\n            this.updateLayout(true);\n            return;\n        }\n\n        var file = view.getFile(),\n            newPath = file && file.fullPath,\n            oldView = this._currentView;\n\n        if (this._currentView) {\n            if (this._currentView.getFile()) {\n                ViewStateManager.updateViewState(this._currentView);\n            }\n            this._setViewVisibility(this._currentView, false);\n        } else {\n            this.showInterstitial(false);\n        }\n\n        this._currentView = view;\n        this._setViewVisibility(this._currentView, true);\n        this.updateLayout();\n\n        this._notifyCurrentViewChange(view, oldView);\n\n        if (oldView) {\n            this.destroyViewIfNotNeeded(oldView);\n        }\n\n        if (!this._views.hasOwnProperty(newPath)) {\n            console.error(newPath + \" found in pane working set but pane.addView() has not been called for the view created for it\");\n        }\n    };\n\n    /**\n     * Update header and content height\n     */\n    Pane.prototype._updateHeaderHeight = function () {\n        var paneContentHeight = this.$el.height();\n\n        // Adjust pane content height for header\n        if (MainViewManager.getPaneCount() > 1) {\n            this.$header.show();\n            paneContentHeight -= this.$header.outerHeight();\n        } else {\n            this.$header.hide();\n        }\n\n        this.$content.height(paneContentHeight);\n    };\n\n    /**\n     * Sets pane content height. Updates the layout causing the current view to redraw itself\n     * @param {boolean} forceRefresh - true to force a resize and refresh of the current view,\n     * false if just to resize forceRefresh is only used by Editor views to force a relayout\n     * of all editor DOM elements. Custom View implementations should just ignore this flag.\n     */\n    Pane.prototype.updateLayout = function (forceRefresh) {\n        this._updateHeaderHeight();\n        if (this._currentView) {\n            this._currentView.updateLayout(forceRefresh);\n        }\n    };\n\n    /**\n     * Determines if the view can be disposed of\n     * @private\n     * @param {!View} view - the View object to test\n     * @return {boolean}} true if the view can be disposed, false if not\n     */\n    Pane.prototype._isViewNeeded = function (view) {\n        var path = view.getFile().fullPath,\n            currentPath = this.getCurrentlyViewedPath();\n\n        return ((this._currentView && currentPath === path) || (this.findInViewList(path) !== -1));\n    };\n\n\n    /**\n     * Retrieves the File object of the current view\n     * @return {?File} the File object of the current view or null if there isn't one\n     */\n    Pane.prototype.getCurrentlyViewedFile = function () {\n        return this._currentView ? this._currentView.getFile() : null;\n    };\n\n    /**\n     * Retrieves the path of the current view\n     * @return {?string} the path of the current view or null if there isn't one\n     */\n    Pane.prototype.getCurrentlyViewedPath = function () {\n        var file = this.getCurrentlyViewedFile();\n        return file ? file.fullPath : null;\n    };\n\n    /**\n     * destroys the view if it isn't needed\n     * @param {View} view - the view to destroy\n     */\n    Pane.prototype.destroyViewIfNotNeeded = function (view) {\n        if (!this._isViewNeeded(view)) {\n            var file = view.getFile(),\n                path = file && file.fullPath;\n            delete this._views[path];\n            this.trigger(\"viewDestroy\", view);\n            view.destroy();\n        }\n    };\n\n    /**\n     * _resets the pane to an empty state\n     * @private\n     */\n    Pane.prototype._reset = function () {\n        var self = this,\n            views = [],\n            view = this._currentView;\n\n        _.forEach(this._views, function (_view) {\n            views.push(_view);\n        });\n\n        // If the current view is a temporary view,\n        //  add it to the destroy list to dispose of\n        if (this._currentView && views.indexOf(this._currentView) === -1) {\n            views.push(this._currentView);\n        }\n\n        // This will reinitialize the object back to\n        //  the default state\n        this._initialize();\n\n        if (view) {\n            this._notifyCurrentViewChange(null, view);\n        }\n\n        // Now destroy the views\n        views.forEach(function (_view) {\n            self.trigger(\"viewDestroy\", _view);\n            _view.destroy();\n        });\n    };\n\n    /**\n     * Executes a FILE_OPEN command to open a file\n     * @param  {!string} fullPath - path of the file to open\n     * @return {jQuery.promise} promise that will resolve when the file is opened\n     */\n    Pane.prototype._execOpenFile = function (fullPath) {\n        return CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, { fullPath: fullPath, paneId: this.id, options: {noPaneActivate: true}});\n    };\n\n    /**\n     * Removes the view and opens the next view\n     * @param {File} file - the file to close\n     * @param {boolean} suppressOpenNextFile - suppresses opening the next file in MRU order\n     * @param {boolean} preventViewChange - if suppressOpenNextFile is truthy, this flag can be used to\n     *                                      prevent the current view from being destroyed.\n     *                                      Ignored if suppressOpenNextFile is falsy\n     * @return {boolean} true if the file was removed from the working set\n     *  This function will remove a temporary view of a file but will return false in that case\n     */\n    Pane.prototype.removeView = function (file, suppressOpenNextFile, preventViewChange) {\n        var nextFile = !suppressOpenNextFile && this.traverseViewListByMRU(1, file.fullPath);\n        if (nextFile && nextFile.fullPath !== file.fullPath && this.getCurrentlyViewedPath() === file.fullPath) {\n            var self = this,\n                fullPath = nextFile.fullPath,\n                needOpenNextFile = this.findInViewList(fullPath) !== -1;\n\n            if (this._doRemove(file, needOpenNextFile)) {\n                if (needOpenNextFile) {\n                    // this will destroy the current view\n                    this._execOpenFile(fullPath)\n                        .fail(function () {\n                            // the FILE_OPEN op failed so destroy the current view\n                            self._doDestroyView(self._currentView);\n                        });\n                }\n                return true;\n            } else {\n                // Nothing was removed so don't try to remove it again\n                return false;\n            }\n        } else {\n            return this._doRemove(file, preventViewChange);\n        }\n    };\n\n    /**\n     * Removes the specifed file from all internal lists, destroys the view of the file (if there is one)\n     *  and shows the interstitial page if the current view is destroyed.\n     * @param {!Array.<File>}  list - Array of files to remove\n     * @return {!Array.<File>} Array of File objects removed from the working set.\n     *  This function will remove temporary views but the file objects for those views will not be found\n     *  in the result set.  Only the file objects removed from the working set are returned.\n     */\n    Pane.prototype.removeViews = function (list) {\n        var self = this,\n            needsDestroyCurrentView = false,\n            result;\n\n        // Check to see if we need to destroy the current view later\n        needsDestroyCurrentView = _.findIndex(list, function (file) {\n            return file.fullPath === self.getCurrentlyViewedPath();\n        }) !== -1;\n\n        // destroy the views in the list\n        result = list.filter(function (file) {\n            return (self.removeView(file, true, true));\n        });\n\n        // we may have been passed a list of files that did not include the current view\n        if (needsDestroyCurrentView) {\n            // _doRemove will have whittled the MRU list down to just the remaining views\n            var nextFile = this.traverseViewListByMRU(1, this.getCurrentlyViewedPath()),\n                fullPath = nextFile && nextFile.fullPath,\n                needOpenNextFile = fullPath && (this.findInViewList(fullPath) !== -1);\n\n            if (needOpenNextFile) {\n                // A successful open will destroy the current view\n                this._execOpenFile(fullPath)\n                    .fail(function () {\n                        // the FILE_OPEN op failed so destroy the current view\n                        self._doDestroyView(self._currentView);\n                    });\n            } else {\n                // Nothing left to show so destroy the current view\n                this._doDestroyView(this._currentView);\n            }\n        }\n\n        // return the result\n        return result;\n    };\n\n    /**\n     * Gives focus to the last thing that had focus, the current view or the pane in that order\n     */\n    Pane.prototype.focus = function () {\n        var current = window.document.activeElement,\n            self = this;\n\n        // Helper to focus the current view if it can\n        function tryFocusingCurrentView() {\n            if (self._currentView) {\n                if (self._currentView.focus) {\n                    //  Views can implement a focus\n                    //  method for focusing a complex\n                    //  DOM like codemirror\n                    self._currentView.focus();\n                } else {\n                    //  Otherwise, no focus method\n                    //  just try and give the DOM\n                    //  element focus\n                    self._currentView.$el.focus();\n                }\n            } else {\n                // no view so just focus the pane\n                self.$el.focus();\n            }\n        }\n\n        // short-circuit for performance\n        if (this._lastFocusedElement === current) {\n            return;\n        }\n\n        // If the focus was in a <textarea> (assumed to be CodeMirror) and currentView is\n        // anything other than an Editor, blur the textarea explicitly, in case the new\n        // _currentView's $el isn't focusable. E.g.:\n        //  1. Open a js file in the left pane and an image in the right pane and\n        //  2. Focus the js file using the working-set\n        //  3. Focus the image view using the working-set.\n        //  ==> Focus is still in the text area. Any keyboard input will modify the document\n        if (current.tagName.toLowerCase() === \"textarea\" &&\n                (!this._currentView || !this._currentView._codeMirror)) {\n            current.blur();\n        }\n\n        var $lfe = $(this._lastFocusedElement);\n\n        if ($lfe.length && !$lfe.is(\".view-pane\") && $lfe.is(\":visible\")) {\n            // if we had a last focused element\n            //  and it wasn't a pane element\n            //  and it's still visible, focus it\n            $lfe.focus();\n        } else {\n            // otherwise, just try to give focus\n            //  to the currently active view\n            tryFocusingCurrentView();\n        }\n    };\n\n    /**\n     * MainViewManager.activePaneChange handler\n     * @param {jQuery.event} e - event data\n     * @param {!string} activePaneId - the new active pane id\n     */\n    Pane.prototype._handleActivePaneChange = function (e, activePaneId) {\n        this.$el.toggleClass(\"active-pane\", Boolean(activePaneId === this.id));\n    };\n\n\n\n    /**\n     * serializes the pane state from JSON\n     * @param {!Object} state - the state to load\n     * @return {jQuery.Promise} A promise which resolves to\n     *              {fullPath:string, paneId:string}\n     *              which can be passed as command data to FILE_OPEN\n     */\n    Pane.prototype.loadState = function (state) {\n        var filesToAdd = [],\n            viewStates = {},\n            activeFile,\n            data,\n            self = this;\n\n        var getInitialViewFilePath = function () {\n            return (self._viewList.length > 0) ? self._viewList[0].fullPath : null;\n        };\n\n        _.forEach(state, function (entry) {\n            filesToAdd.push(FileSystem.getFileForPath(entry.file));\n            if (entry.active) {\n                activeFile = entry.file;\n            }\n            if (entry.viewState) {\n                viewStates[entry.file] = entry.viewState;\n            }\n        });\n\n        this.addListToViewList(filesToAdd);\n\n        ViewStateManager.addViewStates(viewStates);\n\n        activeFile = activeFile || getInitialViewFilePath();\n\n        if (activeFile) {\n            data = {paneId: self.id, fullPath: activeFile};\n        }\n\n        return new $.Deferred().resolve(data);\n    };\n\n    /**\n     * Returns the JSON-ified state of the object so it can be serialize\n     * @return {!Object} state - the state to save\n     */\n    Pane.prototype.saveState = function () {\n        var result = [],\n            currentlyViewedPath = this.getCurrentlyViewedPath();\n\n        // Save the current view state first\n        if (this._currentView && this._currentView.getFile()) {\n            // We save the view state of the current view before\n            //  hiding the view and showing to a different file\n            // But the current view's view state may not be\n            //  up to date in the view state cache so update it\n            //  before we save so we don't JSON-ify stale data.\n            ViewStateManager.updateViewState(this._currentView);\n        }\n\n        // walk the list of views and save\n        this._viewList.forEach(function (file) {\n            // Do not persist untitled document paths\n            if (!(file instanceof InMemoryFile)) {\n                result.push({\n                    file: file.fullPath,\n                    active: (file.fullPath === currentlyViewedPath),\n                    viewState:  ViewStateManager.getViewState(file)\n                });\n            }\n        });\n\n        return result;\n    };\n\n    /**\n     * gets the current view's scroll state data\n     * @return {Object=} scroll state - the current scroll state\n     */\n    Pane.prototype.getScrollState = function () {\n        if (this._currentView && this._currentView.getScrollPos) {\n            return {scrollPos: this._currentView.getScrollPos()};\n        }\n    };\n\n    /**\n     * tells the current view to restore its scroll state from cached data and apply a height delta\n     * @param {Object=} state - the current scroll state\n     * @param {number=} heightDelta - the amount to add or subtract from the state\n     */\n    Pane.prototype.restoreAndAdjustScrollState = function (state, heightDelta) {\n        if (this._currentView && state && state.scrollPos && this._currentView.adjustScrollPos) {\n            this._currentView.adjustScrollPos(state.scrollPos, heightDelta);\n        }\n    };\n\n    exports.Pane = Pane;\n});\n"
  },
  {
    "path": "src/view/ThemeManager.js",
    "content": "/**\n * Brackets Themes Copyright (c) 2014 Miguel Castillo.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n/*global less */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                  = require(\"thirdparty/lodash\"),\n        EventDispatcher    = require(\"utils/EventDispatcher\"),\n        FileSystem         = require(\"filesystem/FileSystem\"),\n        FileUtils          = require(\"file/FileUtils\"),\n        EditorManager      = require(\"editor/EditorManager\"),\n        ExtensionUtils     = require(\"utils/ExtensionUtils\"),\n        ThemeSettings      = require(\"view/ThemeSettings\"),\n        ThemeView          = require(\"view/ThemeView\"),\n        PreferencesManager = require(\"preferences/PreferencesManager\"),\n        prefs              = PreferencesManager.getExtensionPrefs(\"themes\");\n\n    var loadedThemes    = {},\n        currentTheme    = null,\n        styleNode       = $(ExtensionUtils.addEmbeddedStyleSheet(\"\")),\n        defaultTheme    = \"thor-light-theme\",\n        commentRegex    = /\\/\\*([\\s\\S]*?)\\*\\//mg,\n        scrollbarsRegex = /((?:[^}|,]*)::-webkit-scrollbar(?:[^{]*)[{](?:[^}]*?)[}])/mgi,\n        stylesPath      = FileUtils.getNativeBracketsDirectoryPath() + \"/styles/\";\n\n\n    /**\n     * @private\n     * Takes all dashes and converts them to white spaces. Then takes all first letters\n     * and capitalizes them.\n     *\n     * @param {string} name is what needs to be procseed to generate a display name\n     * @return {string} theme name properly formatted for display\n     */\n    function toDisplayName(name) {\n        var extIndex = name.lastIndexOf('.');\n        name = name.substring(0, extIndex !== -1 ? extIndex : undefined).replace(/-/g, ' ');\n\n        return name.split(\" \").map(function (part) {\n            return part[0].toUpperCase() + part.substring(1);\n        }).join(\" \");\n    }\n\n\n    /**\n     * @constructor\n     * Theme contains all the essential bit to load a theme from disk, display a theme in the settings\n     * dialog, and to properly add a theme into CodeMirror along with the rest of brackets.\n     *\n     * @param {File} file for the theme\n     * @param {{name: string, title: string}} options to configure different\n     *   properties in the theme\n     */\n    function Theme(file, options) {\n        options = options || {};\n        var fileName = file.name;\n\n        // If no options.name is provided, then we derive the name of the theme from whichever we find\n        // first, the options.title or the filename.\n        if (!options.name) {\n            if (options.title) {\n                options.name = options.title;\n            } else {\n                // Remove the file extension when the filename is used as the theme name. This is to\n                // follow CodeMirror conventions where themes are just a CSS file and the filename\n                // (without the extension) is used to build CSS rules.  Also handle removing .min\n                // in case the \".min\" is part of the file name.\n                options.name = FileUtils.getFilenameWithoutExtension(fileName).replace(/\\.min$/, \"\");\n            }\n\n            // We do a bit of string treatment here to make sure we generate theme names that can be\n            // used as a CSS class name by CodeMirror.\n            options.name = options.name.toLocaleLowerCase().replace(/[\\W]/g, '-');\n        }\n\n        this.file           = file;\n        this.name           = options.name;\n        this.displayName    = options.title || toDisplayName(fileName);\n        this.dark           = options.theme !== undefined && options.theme.dark === true;\n        this.addModeClass   = options.theme !== undefined && options.theme.addModeClass === true;\n    }\n\n\n    /**\n     * @private\n     * Extracts the scrollbar text from the css/less content so that it can be treated\n     * as a separate styling component that can be anabled/disabled independently from\n     * the theme.\n     *\n     * @param {string} content is the css/less input string to be processed\n     * @return {{content: string, scrollbar: Array.<string>}} content is the new css/less content\n     *   with the scrollbar rules extracted out and put in scrollbar\n     */\n    function extractScrollbars(content) {\n        var scrollbar = [];\n\n        // Go through and extract out scrollbar customizations so that we can\n        // enable/disable via settings.\n        content = content\n            .replace(scrollbarsRegex, function (match) {\n                scrollbar.push(match);\n                return \"\";\n            });\n\n        return {\n            content: content,\n            scrollbar: scrollbar\n        };\n    }\n\n\n    /**\n     * @private\n     * Function will process a string and figure out if it looks like window path with a\n     * a drive.  If that's the case, then we lower case everything.\n     * --- NOTE: There is a bug in less that only checks for lowercase in order to handle\n     * the rootPath configuration...  Hopefully a PR will be coming their way soon.\n     *\n     * @param {string} path is a string to search for drive letters that need to be converted\n     *   to lower case.\n     *\n     * @return {string} Windows Drive letter in lowercase.\n     */\n    function fixPath(path) {\n        return path.replace(/^([A-Z]+:)?\\//, function (match) {\n            return match.toLocaleLowerCase();\n        });\n    }\n\n\n    /**\n     * @private\n     * Takes the content of a file and feeds it through the less processor in order\n     * to provide support for less files.\n     *\n     * @param {string} content is the css/less string to be processed\n     * @param {Theme} theme is the object the css/less corresponds to\n     * @return {$.Promise} promise with the processed css/less as the resolved value\n     */\n    function lessifyTheme(content, theme) {\n        var deferred = new $.Deferred();\n\n        less.render(\"#editor-holder {\" + content + \"\\n}\", {\n            rootpath: fixPath(stylesPath),\n            filename: fixPath(theme.file._path)\n        }, function (err, tree) {\n            if (err) {\n                deferred.reject(err);\n            } else {\n                deferred.resolve(tree.css);\n            }\n        });\n\n        return deferred.promise();\n    }\n\n    /**\n     * @private\n     * Will search all loaded themes for one the matches the file passed in\n     *\n     * @param {File} file is the search criteria\n     * @return {Theme} theme that matches the file\n     */\n    function getThemeByFile(file) {\n        var path = file._path;\n        return _.find(loadedThemes, function (item) {\n            return item.file._path === path;\n        });\n    }\n\n\n    /**\n     * Get current theme object that is loaded in the editor.\n     *\n     * @return {Theme} the current theme instance\n     */\n    function getCurrentTheme() {\n        if (!currentTheme) {\n            currentTheme = loadedThemes[prefs.get(\"theme\")] || loadedThemes[defaultTheme];\n        }\n\n        return currentTheme;\n    }\n\n\n    /**\n     * Gets all available themes\n     * @return {Array.<Theme>} collection of all available themes\n     */\n    function getAllThemes() {\n        return _.map(loadedThemes, function (theme) {\n            return theme;\n        });\n    }\n\n\n    /**\n     * @private\n     * Process and load the current theme into the editor\n     *\n     * @return {$.Promise} promise object resolved with the theme object and all\n     *    corresponding new css/less and scrollbar information\n     */\n    function loadCurrentTheme() {\n        var theme = getCurrentTheme();\n\n        var pending = theme && FileUtils.readAsText(theme.file)\n            .then(function (lessContent) {\n                return lessifyTheme(lessContent.replace(commentRegex, \"\"), theme);\n            })\n            .then(function (content) {\n                var result = extractScrollbars(content);\n                theme.scrollbar = result.scrollbar;\n                return result.content;\n            })\n            .then(function (cssContent) {\n                $(\"body\").toggleClass(\"dark\", theme.dark);\n                styleNode.text(cssContent);\n                return theme;\n            });\n\n        return $.when(pending);\n    }\n\n\n    /**\n     * Refresh current theme in the editor\n     *\n     * @param {boolean} force Forces a reload of the current theme.  It reloads the theme file.\n     */\n    function refresh(force) {\n        if (force) {\n            currentTheme = null;\n        }\n\n        $.when(force && loadCurrentTheme()).done(function () {\n            var editor = EditorManager.getActiveEditor();\n            if (!editor || !editor._codeMirror) {\n                return;\n            }\n\n            var cm = editor._codeMirror;\n            ThemeView.updateThemes(cm);\n\n            // currentTheme can be undefined, so watch out\n            cm.setOption(\"addModeClass\", !!(currentTheme && currentTheme.addModeClass));\n        });\n    }\n\n\n    /**\n     * Loads a theme from a file.\n     *\n     * @param {string} fileName is the full path to the file to be opened\n     * @param {Object} options is an optional parameter to specify metadata\n     *    for the theme.\n     * @return {$.Promise} promise object resolved with the theme to be loaded from fileName\n     */\n    function loadFile(fileName, options) {\n        var deferred         = new $.Deferred(),\n            file             = FileSystem.getFileForPath(fileName),\n            currentThemeName = prefs.get(\"theme\");\n\n        file.exists(function (err, exists) {\n            var theme;\n\n            if (exists) {\n                theme = new Theme(file, options);\n                loadedThemes[theme.name] = theme;\n                ThemeSettings._setThemes(loadedThemes);\n\n                // For themes that are loaded after ThemeManager has been loaded,\n                // we should check if it's the current theme.  If it is, then we just\n                // load it.\n                if (currentThemeName === theme.name) {\n                    refresh(true);\n                }\n\n                deferred.resolve(theme);\n            } else if (err || !exists) {\n                deferred.reject(err);\n            }\n        });\n\n        return deferred.promise();\n    }\n\n\n    /**\n     * Loads a theme from an extension package.\n     *\n     * @param {Object} themePackage is a package from the extension manager for the theme to be loaded.\n     * @return {$.Promise} promise object resolved with the theme to be loaded from the pacakge\n     */\n    function loadPackage(themePackage) {\n        var fileName = themePackage.path + \"/\" + themePackage.metadata.theme.file;\n        return loadFile(fileName, themePackage.metadata);\n    }\n\n\n    prefs.on(\"change\", \"theme\", function () {\n        // Make sure we don't reprocess a theme that's already loaded\n        if (currentTheme && currentTheme.name === prefs.get(\"theme\")) {\n            return;\n        }\n\n        // Refresh editor with the new theme\n        refresh(true);\n\n        // Process the scrollbars for the editor\n        ThemeView.updateScrollbars(getCurrentTheme());\n\n        // Expose event for theme changes\n        exports.trigger(\"themeChange\", getCurrentTheme());\n    });\n\n    prefs.on(\"change\", \"themeScrollbars\", function () {\n        refresh();\n        ThemeView.updateScrollbars(getCurrentTheme());\n    });\n\n    // Monitor file changes.  If the file that has changed is actually the currently loaded\n    // theme, then we just reload the theme.  This allows to live edit the theme\n    FileSystem.on(\"change\", function (evt, file) {\n        if (!file || file.isDirectory) {\n            return;\n        }\n\n        if (getThemeByFile(file)) {\n            refresh(true);\n        }\n    });\n\n    EditorManager.on(\"activeEditorChange\", function () {\n        refresh();\n    });\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    exports.refresh         = refresh;\n    exports.loadFile        = loadFile;\n    exports.loadPackage     = loadPackage;\n    exports.getCurrentTheme = getCurrentTheme;\n    exports.getAllThemes    = getAllThemes;\n\n    // Exposed for testing purposes\n    exports._toDisplayName     = toDisplayName;\n    exports._extractScrollbars = extractScrollbars;\n});\n"
  },
  {
    "path": "src/view/ThemeSettings.js",
    "content": "/**\n * Brackets Themes Copyright (c) 2014 Miguel Castillo.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _                   = require(\"thirdparty/lodash\"),\n        Mustache            = require(\"thirdparty/mustache/mustache\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        ViewCommandHandlers = require(\"view/ViewCommandHandlers\"),\n        settingsTemplate    = require(\"text!htmlContent/themes-settings.html\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        prefs               = PreferencesManager.getExtensionPrefs(\"themes\");\n\n    /**\n     * @type {Object}\n     * Currently loaded themes that are available to choose from.\n     */\n    var loadedThemes = {};\n\n    /**\n     * Object with all default values that can be configure via the settings UI\n     */\n    var defaults = {\n        \"themeScrollbars\": true,\n        \"theme\": \"light-theme\"\n    };\n\n\n    /**\n     * Cached html settings jQuery object for easier processing when opening the settings dialog\n     */\n    var $settings = $(settingsTemplate).addClass(\"themeSettings\");\n\n    /**\n     * @private\n     * Gets all the configurable settings that need to be loaded in the settings dialog\n     *\n     * @return {Object} a collection with all the settings\n     */\n    function getValues() {\n        var result = {};\n\n        Object.keys(defaults).forEach(function (key) {\n            result[key] = prefs.get(key);\n        });\n\n        result.fontFamily = ViewCommandHandlers.getFontFamily();\n        result.fontSize   = ViewCommandHandlers.getFontSize();\n        result.validFontSizeRegExp = ViewCommandHandlers.validFontSizeRegExp;\n        return result;\n    }\n\n    /**\n     * Opens the settings dialog\n     */\n    function showDialog() {\n        var currentSettings = getValues();\n        var newSettings     = {};\n        var themes          = _.map(loadedThemes, function (theme) { return theme; });\n        var template        = $(\"<div>\").append($settings).html();\n        var $template       = $(Mustache.render(template, {\"settings\": currentSettings, \"themes\": themes, \"Strings\": Strings}));\n\n        // Select the correct theme.\n        var $currentThemeOption = $template\n            .find(\"[value='\" + currentSettings.theme + \"']\");\n\n        if ($currentThemeOption.length === 0) {\n            $currentThemeOption = $template.find(\"[value='\" + defaults.theme + \"']\");\n        }\n        $currentThemeOption.attr(\"selected\", \"selected\");\n\n        $template\n            .find(\"[data-toggle=tab].default\")\n            .tab(\"show\");\n\n        $template\n            .on(\"change\", \"[data-target]:checkbox\", function () {\n                var $target = $(this);\n                var attr = $target.attr(\"data-target\");\n                newSettings[attr] = $target.is(\":checked\");\n            })\n            .on(\"input\", \"[data-target='fontSize']\", function () {\n                var target = this;\n                var targetValue = $(this).val();\n                var $btn = $(\"#theme-settings-done-btn\")[0];\n\n                // Make sure that the font size is expressed in terms\n                // we can handle (px or em). If not, 'done' button is\n                // disabled until input has been corrected.\n\n                if (target.checkValidity() === true) {\n                    $btn.disabled = false;\n                    newSettings[\"fontSize\"] = targetValue;\n                } else {\n                    $btn.disabled = true;\n                }\n            })\n            .on(\"input\", \"[data-target='fontFamily']\", function () {\n                var targetValue = $(this).val();\n                newSettings[\"fontFamily\"] = targetValue;\n            })\n            .on(\"change\", \"select\", function () {\n                var $target = $(\":selected\", this);\n                var attr = $target.attr(\"data-target\");\n\n                if (attr) {\n                    prefs.set(attr, $target.val());\n                }\n            });\n\n        Dialogs.showModalDialogUsingTemplate($template).done(function (id) {\n            var setterFn;\n\n            if (id === \"save\") {\n                // Go through each new setting and apply it\n                Object.keys(newSettings).forEach(function (setting) {\n                    if (defaults.hasOwnProperty(setting)) {\n                        prefs.set(setting, newSettings[setting]);\n                    } else {\n                        // Figure out if the setting is in the ViewCommandHandlers, which means it is\n                        // a font setting\n                        setterFn = \"set\" + setting[0].toLocaleUpperCase() + setting.substr(1);\n                        if (typeof ViewCommandHandlers[setterFn] === \"function\") {\n                            ViewCommandHandlers[setterFn](newSettings[setting]);\n                        }\n                    }\n                });\n            } else if (id === \"cancel\") {\n                // Make sure we revert any changes to theme selection\n                prefs.set(\"theme\", currentSettings.theme);\n            }\n        });\n    }\n\n    /**\n     * Interface to set the themes that are available to chose from in the setting dialog\n     * @param {ThemeManager.Theme} themes is a collection of themes created by the ThemeManager\n     */\n    function setThemes(themes) {\n        loadedThemes = themes;\n    }\n\n    /**\n     * Restores themes to factory settings.\n     */\n    function restore() {\n        prefs.set(\"theme\", defaults.theme);\n        prefs.set(\"themeScrollbars\", defaults.themeScrollbars);\n    }\n\n    prefs.definePreference(\"theme\", \"string\", defaults.theme, {\n        description: Strings.DESCRIPTION_THEME\n    });\n    prefs.definePreference(\"themeScrollbars\", \"boolean\", defaults.themeScrollbars, {\n        description: Strings.DESCRIPTION_USE_THEME_SCROLLBARS\n    });\n\n    exports._setThemes = setThemes;\n    exports.restore    = restore;\n    exports.showDialog = showDialog;\n});\n"
  },
  {
    "path": "src/view/ThemeView.js",
    "content": "/**\n * Brackets Themes Copyright (c) 2014 Miguel Castillo.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var CodeMirror         = require(\"thirdparty/CodeMirror/lib/codemirror\"),\n        PreferencesManager = require(\"preferences/PreferencesManager\"),\n        prefs              = PreferencesManager.getExtensionPrefs(\"themes\");\n\n    var $scrollbars = $(\"<style id='scrollbars'>\").appendTo(\"head\");\n\n\n    /**\n     * Load scrollbar styling based on whether or not theme scrollbars are enabled.\n     *\n     * @param {ThemeManager.Theme} theme Is the theme object with the corresponding scrollbar style\n     *   to be updated\n     */\n    function updateScrollbars(theme) {\n        theme = theme || {};\n        if (prefs.get(\"themeScrollbars\")) {\n            var scrollbar = (theme.scrollbar || []).join(\" \");\n            $scrollbars.text(scrollbar || \"\");\n        } else {\n            $scrollbars.text(\"\");\n        }\n    }\n\n\n    /**\n     *  Handles updating codemirror with the current selection of themes.\n     *\n     * @param {CodeMirror} cm is the CodeMirror instance currently loaded\n     */\n    function updateThemes(cm) {\n        var newTheme = prefs.get(\"theme\"),\n            cmTheme  = (cm.getOption(\"theme\") || \"\").replace(/[\\s]*/, \"\"); // Normalize themes string\n\n        // Check if the editor already has the theme applied...\n        if (cmTheme === newTheme) {\n            return;\n        }\n\n        // Setup current and further documents to get the new theme...\n        CodeMirror.defaults.theme = newTheme;\n        cm.setOption(\"theme\", newTheme);\n    }\n\n\n    exports.updateScrollbars = updateScrollbars;\n    exports.updateThemes     = updateThemes;\n});\n"
  },
  {
    "path": "src/view/ViewCommandHandlers.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global less */\n\n/**\n * The ViewCommandHandlers object dispatches the following event(s):\n *    - fontSizeChange -- Triggered when the font size is changed via the\n *      Increase Font Size, Decrease Font Size, or Restore Font Size commands.\n *      The 2nd arg to the listener is the amount of the change. The 3rd arg\n *      is a string containing the new font size after applying the change.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var Commands            = require(\"command/Commands\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        ThemeSettings       = require(\"view/ThemeSettings\"),\n        MainViewManager     = require(\"view/MainViewManager\"),\n        AppInit             = require(\"utils/AppInit\"),\n        _                   = require(\"thirdparty/lodash\"),\n        FontRuleTemplate    = require(\"text!view/fontrules/font-based-rules.less\");\n\n    var prefs = PreferencesManager.getExtensionPrefs(\"fonts\");\n    \n    \n    /**\n     * Font sizes should be validated by this regexp\n     */\n    var validFontSizeRegExpStr = \"^([0-9]+)?(\\\\.)?([0-9]+)(px|em)$\";\n    // Need RegExp as a string to be exported for use with HTML5 pattern attribute\n\n    /**\n     * @private\n     * The currently present font size. Used to detect no-op changes.\n     * @type {string}\n     */\n    var currFontSize;\n\n    /**\n     * @private\n     * The currently present font family. Used to detect no-op changes.\n     * @type {string}\n     */\n    var currFontFamily;\n\n    /**\n     * @const\n     * @type {string}\n     */\n    var DYNAMIC_FONT_STYLE_ID = \"codemirror-dynamic-fonts\";\n\n    /**\n     * @const\n     * @type {string}\n     */\n    var DYNAMIC_FONT_FAMILY_ID = \"codemirror-dynamic-font-family\";\n\n    /**\n     * @const\n     * @private\n     * The smallest font size in pixels\n     * @type {number}\n     */\n    var MIN_FONT_SIZE = 1;\n\n    /**\n     * @const\n     * @private\n     * The largest font size in pixels\n     * @type {number}\n     */\n    var MAX_FONT_SIZE = 72;\n\n    /**\n     * @const\n     * @private\n     * The default font size used only to convert the old fontSizeAdjustment view state to the new fontSize\n     * @type {number}\n     */\n    var DEFAULT_FONT_SIZE = 12;\n\n    /**\n     * @const\n     * @private\n     * The default font family\n     * @type {string}\n     */\n    var DEFAULT_FONT_FAMILY = \"'SourceCodePro-Medium', ＭＳ ゴシック, 'MS Gothic', monospace\";\n    \n    /**\n     * @private\n     * Removes style property from the DOM\n     * @param {string} propertyID is the id of the property to be removed\n     */\n    function _removeDynamicProperty(propertyID) {\n        $(\"#\" + propertyID).remove();\n    }\n    \n    /**\n     * @private\n     * Add the style property to the DOM\n     * @param {string} propertyID Is the property ID to be added\n     * @param {object} ruleCfg Is the CSS Rule configuration object\n     * @param {string} ruleCfg.propName Is the name of the style property\n     * @param {string} ruleCfg.propValue Is the value of the style property\n     * @param {boolean} ruleCfg.priorityFlag Is a flag to make the style property !important\n     * @param {string} ruleCfg.ruleName Optional Selctor name to be used for the rule\n     * @param {string} ruleCfg.ruleText Optional selector definition text\n     */\n    function _addDynamicProperty(propertyID, ruleCfg) {\n        var $style   = $(\"<style type='text/css'></style>\").attr(\"id\", propertyID);\n        if (ruleCfg.ruleText) {\n            $style.html(ruleCfg.ruleText);\n        } else {\n            var cssRule = ruleCfg.ruleName || \".CodeMirror\";\n            var styleStr = ruleCfg.ruleText || StringUtils.format(\"{0}: {1} {2}\", ruleCfg.propName, ruleCfg.propValue, ruleCfg.priorityFlag ? \"!important\" : \"\");\n            $style.html(cssRule + \"{ \" + styleStr + \" }\");\n        }\n\n        // Let's make sure we remove the already existing item from the DOM.\n        _removeDynamicProperty(propertyID);\n        $(\"head\").append($style);\n    }\n    \n    /**\n     * @private\n     * Removes the styles used to update the font size\n     */\n    function _removeDynamicFontSize() {\n        _removeDynamicProperty(DYNAMIC_FONT_STYLE_ID);\n    }\n\n    /**\n     * @private\n     * Add the styles used to update the font size\n     * @param {string} fontSize  A string with the font size and the size unit\n     */\n    function _addDynamicFontSize(fontSize) {\n        var template = FontRuleTemplate.split(\"{font-size-param}\").join(fontSize);\n        less.render(template, null, function onParse(err, tree) {\n            if (err) {\n                console.error(err);\n            } else {\n                _addDynamicProperty(DYNAMIC_FONT_STYLE_ID, {\n                    ruleText: tree.css\n                });\n            }\n        });\n    }\n\n    /**\n     * @private\n     * Removes the styles used to update the font family\n     */\n    function _removeDynamicFontFamily() {\n        _removeDynamicProperty(DYNAMIC_FONT_FAMILY_ID);\n    }\n\n    /**\n     * @private\n     * Add the styles used to update the font family\n     * @param {string} fontFamily  A string with the font family\n     */\n    function _addDynamicFontFamily(fontFamily) {\n        _addDynamicProperty(DYNAMIC_FONT_FAMILY_ID, {\n            propName: \"font-family\",\n            propValue: fontFamily\n        });\n    }\n\n    /**\n     * @private\n     * Sets the font size and restores the scroll position as best as possible.\n     * @param {!Editor} editor  Editor to update.\n     * @param {string=} fontSize  A string with the font size and the size unit\n     */\n    function _updateScroll(editor, fontSize) {\n        var oldWidth    = editor._codeMirror.defaultCharWidth(),\n            oldFontSize = prefs.get(\"fontSize\"),\n            newFontSize = fontSize,\n            delta       = 0,\n            adjustment  = 0,\n            scrollPos   = editor.getScrollPos(),\n            line        = editor._codeMirror.lineAtHeight(scrollPos.y, \"local\");\n\n        delta = /em$/.test(oldFontSize) ? 10 : 1;\n        adjustment = parseInt((parseFloat(newFontSize) - parseFloat(oldFontSize)) * delta, 10);\n\n        // Only adjust the scroll position if there was any adjustments to the font size.\n        // Otherwise there will be unintended scrolling.\n        //\n        if (adjustment) {\n            editor.refreshAll();\n        }\n\n        // Calculate the new scroll based on the old font sizes and scroll position\n        var newWidth   = editor._codeMirror.defaultCharWidth(),\n            deltaX     = scrollPos.x / oldWidth,\n            scrollPosX = scrollPos.x + Math.round(deltaX * (newWidth  - oldWidth)),\n            scrollPosY = editor._codeMirror.heightAtLine(line, \"local\");\n\n        editor.setScrollPos(scrollPosX, scrollPosY);\n    }\n\n    /**\n     * Font size setter to set the font size for the document editor\n     * @param {string} fontSize The font size with size unit as 'px' or 'em'\n     */\n    function setFontSize(fontSize) {\n        if (currFontSize === fontSize) {\n            return;\n        }\n\n        _removeDynamicFontSize();\n        if (fontSize) {\n            _addDynamicFontSize(fontSize);\n        }\n\n        // Update scroll metrics in viewed editors\n        _.forEach(MainViewManager.getPaneIdList(), function (paneId) {\n            var currentPath = MainViewManager.getCurrentlyViewedPath(paneId),\n                doc = currentPath && DocumentManager.getOpenDocumentForPath(currentPath);\n            if (doc && doc._masterEditor) {\n                _updateScroll(doc._masterEditor, fontSize);\n            }\n        });\n\n        exports.trigger(\"fontSizeChange\", fontSize, currFontSize);\n        currFontSize = fontSize;\n        prefs.set(\"fontSize\", fontSize);\n    }\n\n    /**\n     * Font size getter to get the current font size for the document editor\n     * @return {string} Font size with size unit as 'px' or 'em'\n     */\n    function getFontSize() {\n        return prefs.get(\"fontSize\");\n    }\n\n\n    /**\n     * Font family setter to set the font family for the document editor\n     * @param {string} fontFamily The font family to be set.  It can be a string with multiple comma separated fonts\n     */\n    function setFontFamily(fontFamily) {\n        var editor = EditorManager.getCurrentFullEditor();\n\n        if (currFontFamily === fontFamily) {\n            return;\n        }\n\n        _removeDynamicFontFamily();\n        if (fontFamily) {\n            _addDynamicFontFamily(fontFamily);\n        }\n\n        exports.trigger(\"fontFamilyChange\", fontFamily, currFontFamily);\n        currFontFamily = fontFamily;\n        prefs.set(\"fontFamily\", fontFamily);\n\n        if (editor) {\n            editor.refreshAll();\n        }\n    }\n\n\n    /**\n     * Font smoothing setter to set the anti-aliasing type for the code area on Mac.\n     * @param {string} aaType The antialiasing type to be set. It can take either \"subpixel-antialiased\" or \"antialiased\"\n     */\n    function setMacFontSmoothingType(aaType) {\n        var $editor_holder  = $(\"#editor-holder\");\n\n        // Add/Remove the class based on the preference. Also\n        // default to subpixel AA in case of invalid entries.\n        if (aaType === \"antialiased\") {\n            $editor_holder.removeClass(\"subpixel-aa\");\n        } else {\n            $editor_holder.addClass(\"subpixel-aa\");\n        }\n    }\n\n    /**\n     * Font family getter to get the currently configured font family for the document editor\n     * @return {string} The font family for the document editor\n     */\n    function getFontFamily() {\n        return prefs.get(\"fontFamily\");\n    }\n\n\n    /**\n     * @private\n     * Increases or decreases the editor's font size.\n     * @param {number} adjustment  Negative number to make the font smaller; positive number to make it bigger\n     * @return {boolean} true if adjustment occurred, false if it did not occur\n     */\n     function _adjustFontSize(adjustment) {\n        var fsStyle    = prefs.get(\"fontSize\");\n        var validFontSizeRegExp = new RegExp(validFontSizeRegExpStr);\n        \n        // Make sure that the font size is expressed in terms we can\n        // handle (px or em). If not, simply bail.\n        \n         if (fsStyle.search(validFontSizeRegExp) === -1) {\n            return false;\n        }\n\n        // Guaranteed to work by validation above.\n        var fsUnits = fsStyle.substring(fsStyle.length - 2, fsStyle.length),\n            delta   = fsUnits === \"px\" ? 1 : 0.1,\n            fsOld   = parseFloat(fsStyle.substring(0, fsStyle.length - 2)),\n            fsNew   = fsOld + (delta * adjustment),\n            fsStr   = fsNew + fsUnits;\n\n        // Don't let the font size get too small or too large. The minimum font size is 1px or 0.1em\n        // and the maximum font size is 72px or 7.2em depending on the unit used\n        if (fsNew < MIN_FONT_SIZE * delta || fsNew > MAX_FONT_SIZE * delta) {\n            return false;\n        }\n\n        setFontSize(fsStr);\n        return true;\n    }\n\n    /** Increases the font size by 1 */\n    function _handleIncreaseFontSize() {\n        _adjustFontSize(1);\n    }\n\n    /** Decreases the font size by 1 */\n    function _handleDecreaseFontSize() {\n        _adjustFontSize(-1);\n    }\n\n    /** Restores the font size to the original size */\n    function _handleRestoreFontSize() {\n        setFontSize(DEFAULT_FONT_SIZE + \"px\");\n    }\n\n    /**\n     * @private\n     * Updates the user interface appropriately based on whether or not a document is\n     * currently open in the editor.\n     */\n    function _updateUI() {\n        if (DocumentManager.getCurrentDocument() !== null) {\n            if (!CommandManager.get(Commands.VIEW_INCREASE_FONT_SIZE).getEnabled()) {\n                // If one is disabled then they all are disabled, so enable them all\n                CommandManager.get(Commands.VIEW_INCREASE_FONT_SIZE).setEnabled(true);\n                CommandManager.get(Commands.VIEW_DECREASE_FONT_SIZE).setEnabled(true);\n                CommandManager.get(Commands.VIEW_RESTORE_FONT_SIZE).setEnabled(true);\n            }\n        } else {\n            // No current document so disable all of the Font Size commands\n            CommandManager.get(Commands.VIEW_INCREASE_FONT_SIZE).setEnabled(false);\n            CommandManager.get(Commands.VIEW_DECREASE_FONT_SIZE).setEnabled(false);\n            CommandManager.get(Commands.VIEW_RESTORE_FONT_SIZE).setEnabled(false);\n        }\n    }\n\n    /**\n     * Initializes the different settings that need to loaded\n     */\n    function init() {\n        currFontFamily = prefs.get(\"fontFamily\");\n        _addDynamicFontFamily(currFontFamily);\n        currFontSize = prefs.get(\"fontSize\");\n        _addDynamicFontSize(currFontSize);\n        _updateUI();\n    }\n\n    /**\n     * Restores the font size using the saved style and migrates the old fontSizeAdjustment\n     * view state to the new fontSize, when required\n     */\n    function restoreFontSize() {\n        var fsStyle      = prefs.get(\"fontSize\"),\n            fsAdjustment = PreferencesManager.getViewState(\"fontSizeAdjustment\");\n\n        if (fsAdjustment) {\n            // Always remove the old view state even if we also have the new view state.\n            PreferencesManager.setViewState(\"fontSizeAdjustment\");\n\n            if (!fsStyle) {\n                // Migrate the old view state to the new one.\n                fsStyle = (DEFAULT_FONT_SIZE + fsAdjustment) + \"px\";\n                prefs.set(\"fontSize\", fsStyle);\n            }\n        }\n\n        if (fsStyle) {\n            _removeDynamicFontSize();\n            _addDynamicFontSize(fsStyle);\n        }\n    }\n\n    /**\n     * Restores the font size and font family back to factory settings.\n     */\n    function restoreFonts() {\n        setFontFamily(DEFAULT_FONT_FAMILY);\n        setFontSize(DEFAULT_FONT_SIZE + \"px\");\n    }\n\n\n    /**\n     * @private\n     * Calculates the first and last visible lines of the focused editor\n     * @param {number} textHeight\n     * @param {number} scrollTop\n     * @param {number} editorHeight\n     * @return {{first: number, last: number}}\n     */\n    function _getLinesInView(textHeight, scrollTop, editorHeight) {\n        var scrolledTop    = scrollTop / textHeight,\n            scrolledBottom = (scrollTop + editorHeight) / textHeight;\n\n        // Adjust the last line to round inward to show a whole lines.\n        var firstLine      = Math.ceil(scrolledTop),\n            lastLine       = Math.floor(scrolledBottom) - 1;\n\n        return { first: firstLine, last: lastLine };\n    }\n\n    /**\n     * @private\n     * Scroll the viewport one line up or down.\n     * @param {number} direction -1 to scroll one line up; 1 to scroll one line down.\n     */\n    function _scrollLine(direction) {\n        var editor        = EditorManager.getCurrentFullEditor(),\n            textHeight    = editor.getTextHeight(),\n            cursorPos     = editor.getCursorPos(),\n            hasSelecction = editor.hasSelection(),\n            inlineEditors = editor.getInlineWidgets(),\n            scrollInfo    = editor._codeMirror.getScrollInfo(),\n            paddingTop    = editor._getLineSpaceElement().offsetTop,\n            editorHeight  = scrollInfo.clientHeight,\n            scrollTop     = scrollInfo.top - paddingTop,\n            removedScroll = paddingTop;\n\n        // Go through all the editors and reduce the scroll top and editor height to properly calculate the lines in view\n        var line, coords;\n        inlineEditors.forEach(function (inlineEditor) {\n            line   = editor._getInlineWidgetLineNumber(inlineEditor);\n            coords = editor._codeMirror.charCoords({line: line, ch: 0}, \"local\");\n\n            if (coords.top < scrollInfo.top) {\n                scrollTop     -= inlineEditor.info.height;\n                removedScroll += inlineEditor.info.height;\n\n            } else if (coords.top + inlineEditor.info.height < scrollInfo.top + editorHeight) {\n                editorHeight -= inlineEditor.info.height;\n            }\n        });\n\n        // Calculate the lines in view\n        var linesInView = _getLinesInView(textHeight, scrollTop, editorHeight);\n\n        // If there is no selection move the cursor so that is always visible.\n        if (!hasSelecction) {\n            // Move the cursor to the first visible line.\n            if (cursorPos.line < linesInView.first) {\n                editor.setCursorPos({line: linesInView.first + direction, ch: cursorPos.ch});\n\n            // Move the cursor to the last visible line.\n            } else if (cursorPos.line > linesInView.last) {\n                editor.setCursorPos({line: linesInView.last + direction, ch: cursorPos.ch});\n\n            // Move the cursor up or down using moveV to keep the goal column intact, since setCursorPos deletes it.\n            } else if ((direction > 0 && cursorPos.line === linesInView.first) ||\n                    (direction < 0 && cursorPos.line === linesInView.last)) {\n                editor._codeMirror.moveV(direction, \"line\");\n            }\n        }\n\n        // Scroll and make it snap to lines\n        var lines = linesInView.first + direction;\n        editor.setScrollPos(scrollInfo.left, (textHeight * lines) + removedScroll);\n    }\n\n    /** Scrolls one line up */\n    function _handleScrollLineUp() {\n        _scrollLine(-1);\n    }\n\n    /** Scrolls one line down */\n    function _handleScrollLineDown() {\n        _scrollLine(1);\n    }\n\n    /** Open theme settings dialog */\n    function _handleThemeSettings() {\n        ThemeSettings.showDialog();\n    }\n\n    // Register command handlers\n    CommandManager.register(Strings.CMD_INCREASE_FONT_SIZE, Commands.VIEW_INCREASE_FONT_SIZE,  _handleIncreaseFontSize);\n    CommandManager.register(Strings.CMD_DECREASE_FONT_SIZE, Commands.VIEW_DECREASE_FONT_SIZE,  _handleDecreaseFontSize);\n    CommandManager.register(Strings.CMD_RESTORE_FONT_SIZE,  Commands.VIEW_RESTORE_FONT_SIZE,   _handleRestoreFontSize);\n    CommandManager.register(Strings.CMD_SCROLL_LINE_UP,     Commands.VIEW_SCROLL_LINE_UP,      _handleScrollLineUp);\n    CommandManager.register(Strings.CMD_SCROLL_LINE_DOWN,   Commands.VIEW_SCROLL_LINE_DOWN,    _handleScrollLineDown);\n    CommandManager.register(Strings.CMD_THEMES,             Commands.CMD_THEMES_OPEN_SETTINGS, _handleThemeSettings);\n\n    prefs.definePreference(\"fontSize\",   \"string\", DEFAULT_FONT_SIZE + \"px\", {\n        description: Strings.DESCRIPTION_FONT_SIZE\n    }).on(\"change\", function () {\n        setFontSize(prefs.get(\"fontSize\"));\n    });\n    prefs.definePreference(\"fontFamily\", \"string\", DEFAULT_FONT_FAMILY, {\n        description: Strings.DESCRIPTION_FONT_FAMILY\n    }).on(\"change\", function () {\n        setFontFamily(prefs.get(\"fontFamily\"));\n    });\n\n    // Define a preference for font smoothing mode on Mac.\n    // By default fontSmoothing is set to \"subpixel-antialiased\"\n    // for the text inside code editor. It can be overridden\n    // to \"antialiased\", that would set text rendering AA to use\n    // gray scale antialiasing.\n    if (brackets.platform === \"mac\") {\n        prefs.definePreference(\"fontSmoothing\", \"string\", \"subpixel-antialiased\", {\n            description: Strings.DESCRIPTION_FONT_SMOOTHING,\n            values: [\"subpixel-antialiased\", \"antialiased\"]\n        }).on(\"change\", function () {\n            setMacFontSmoothingType(prefs.get(\"fontSmoothing\"));\n        });\n    }\n\n    // Update UI when opening or closing a document\n    MainViewManager.on(\"currentFileChange\", _updateUI);\n\n    // Update UI when Brackets finishes loading\n    AppInit.appReady(init);\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    exports.restoreFontSize = restoreFontSize;\n    exports.restoreFonts    = restoreFonts;\n    exports.getFontSize     = getFontSize;\n    exports.setFontSize     = setFontSize;\n    exports.getFontFamily   = getFontFamily;\n    exports.setFontFamily   = setFontFamily;\n    exports.validFontSizeRegExp = validFontSizeRegExpStr;\n}); \n"
  },
  {
    "path": "src/view/ViewStateManager.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * ViewStateManager is a singleton for views to park their global viwe state. The state is saved\n * with project data but the View or View Factory is responsible for restoring the view state\n * when the view is created.\n *\n * Views should implement `getViewState()` so that the view state can be saved and that data is cached\n * for later use.\n *\n * Views or View Factories are responsible for restoring the view state when the view of that file is created\n * by recalling the cached state.  Views determine what data is store in the view state and how to restore it.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var _ = require(\"thirdparty/lodash\");\n\n    /**\n     * The view state cache.\n     * @type {Object.<string,*>}\n     * @private\n     */\n    var _viewStateCache = {};\n\n    /**\n     * resets the view state cache\n     */\n    function reset() {\n        _viewStateCache = {};\n    }\n\n    /**\n     * Sets the view state for the specfied file\n     * @param {!File} file - the file to record the view state for\n     * @param {?*} viewState - any data that the view needs to restore the view state.\n     */\n    function _setViewState(file, viewState) {\n        _viewStateCache[file.fullPath] = viewState;\n    }\n\n\n    /**\n     * Updates the view state for the specified view\n     * @param {!{!getFile:function():File, getViewState:function():*}} view - the to save state\n     * @param {?*} viewState - any data that the view needs to restore the view state.\n     */\n    function updateViewState(view) {\n        if (view.getViewState) {\n            _setViewState(view.getFile(), view.getViewState());\n        }\n    }\n\n    /**\n     * gets the view state for the specified file\n     * @param {!File} file - the file to record the view state for\n     * @return {?*} whatever data that was saved earlier with a call setViewState\n     */\n    function getViewState(file) {\n        return _viewStateCache[file.fullPath];\n    }\n\n    /**\n     * adds an array of view states\n     * @param {!object.<string, *>} viewStates - View State object to append to the current set of view states\n     */\n    function addViewStates(viewStates) {\n        _viewStateCache = _.extend(_viewStateCache, viewStates);\n    }\n\n    /*\n     * Public API\n     */\n    exports.reset           = reset;\n    exports.updateViewState = updateViewState;\n    exports.getViewState    = getViewState;\n    exports.addViewStates   = addViewStates;\n});\n"
  },
  {
    "path": "src/view/WorkspaceManager.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n* Manages layout of panels surrounding the editor area, and size of the editor area (but not its contents).\n *\n * Updates panel sizes when the window is resized. Maintains the max resizing limits for panels, based on\n * currently available window size.\n *\n * Events:\n * `workspaceUpdateLayout` When workspace size changes for any reason (including panel show/hide panel resize, or the window resize).\n *              The 2nd arg is the available workspace height.\n *              The 3rd arg is a refreshHint flag for internal use (passed in to recomputeLayout)\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit                 = require(\"utils/AppInit\"),\n        EventDispatcher         = require(\"utils/EventDispatcher\"),\n        Resizer                 = require(\"utils/Resizer\");\n\n    //constants\n    var EVENT_WORKSPACE_UPDATE_LAYOUT  = \"workspaceUpdateLayout\",\n        EVENT_WORKSPACE_PANEL_SHOWN    = \"workspacePanelShown\",\n        EVENT_WORKSPACE_PANEL_HIDDEN   = \"workspacePanelHidden\";\n\n    /**\n     * The \".content\" vertical stack (editor + all header/footer panels)\n     * @type {jQueryObject}\n     */\n    var $windowContent;\n\n    /**\n     * The \"#editor-holder\": has only one visible child, the current CodeMirror instance (or the no-editor placeholder)\n     * @type {jQueryObject}\n     */\n    var $editorHolder;\n\n    /**\n     * A map from panel ID's to all reated panels\n     */\n    var panelIDMap = {};\n\n    /**\n     * Have we already started listening for the end of the ongoing window resize?\n     * @type {boolean}\n     */\n    var windowResizing = false;\n\n\n    /**\n     * Calculates the available height for the full-size Editor (or the no-editor placeholder),\n     * accounting for the current size of all visible panels, toolbar, & status bar.\n     * @return {number}\n     */\n    function calcAvailableHeight() {\n        var availableHt = $windowContent.height();\n\n        $editorHolder.siblings().each(function (i, elem) {\n            var $elem = $(elem);\n            if ($elem.css(\"display\") !== \"none\" && $elem.css(\"position\") !== \"absolute\") {\n                availableHt -= $elem.outerHeight();\n            }\n        });\n\n        // Clip value to 0 (it could be negative if a panel wants more space than we have)\n        return Math.max(availableHt, 0);\n    }\n\n    /** Updates panel resize limits to disallow making panels big enough to shrink editor area below 0 */\n    function updateResizeLimits() {\n        var editorAreaHeight = $editorHolder.height();\n\n        $editorHolder.siblings().each(function (i, elem) {\n            var $elem = $(elem);\n            if ($elem.css(\"display\") === \"none\") {\n                $elem.data(\"maxsize\", editorAreaHeight);\n            } else {\n                $elem.data(\"maxsize\", editorAreaHeight + $elem.outerHeight());\n            }\n        });\n    }\n\n\n    /**\n     * Calculates a new size for editor-holder and resizes it accordingly, then and dispatches the \"workspaceUpdateLayout\"\n     * event. (The editors within are resized by EditorManager, in response to that event).\n     *\n     * @param {boolean=} refreshHint  true to force a complete refresh\n     */\n    function triggerUpdateLayout(refreshHint) {\n        // Find how much space is left for the editor\n        var editorAreaHeight = calcAvailableHeight();\n\n        $editorHolder.height(editorAreaHeight);  // affects size of \"not-editor\" placeholder as well\n\n        // Resize editor to fill the space\n        exports.trigger(EVENT_WORKSPACE_UPDATE_LAYOUT, editorAreaHeight, refreshHint);\n    }\n\n\n    /** Trigger editor area resize whenever the window is resized */\n    function handleWindowResize() {\n        // These are not initialized in Jasmine Spec Runner window until a test\n        // is run that creates a mock document.\n        if (!$windowContent || !$editorHolder) {\n            return;\n        }\n\n        // FIXME (issue #4564) Workaround https://github.com/codemirror/CodeMirror/issues/1787\n        triggerUpdateLayout();\n\n        if (!windowResizing) {\n            windowResizing = true;\n\n            // We don't need any fancy debouncing here - we just need to react before the user can start\n            // resizing any panels at the new window size. So just listen for first mousemove once the\n            // window resize releases mouse capture.\n            $(window.document).one(\"mousemove\", function () {\n                windowResizing = false;\n                updateResizeLimits();\n            });\n        }\n    }\n\n    /** Trigger editor area resize whenever the given panel is shown/hidden/resized\n     *  @param {!jQueryObject} $panel the jquery object in which to attach event handlers\n     */\n    function listenToResize($panel) {\n        // Update editor height when shown/hidden, & continuously as panel is resized\n        $panel.on(\"panelCollapsed panelExpanded panelResizeUpdate\", function () {\n            triggerUpdateLayout();\n        });\n        // Update max size of sibling panels when shown/hidden, & at *end* of resize gesture\n        $panel.on(\"panelCollapsed panelExpanded panelResizeEnd\", function () {\n            updateResizeLimits();\n        });\n    }\n\n\n    /**\n     * Represents a panel below the editor area (a child of \".content\").\n     * @constructor\n     * @param {!jQueryObject} $panel  The entire panel, including any chrome, already in the DOM.\n     * @param {number=} minSize  Minimum height of panel in px.\n     */\n    function Panel($panel, minSize) {\n        this.$panel = $panel;\n\n        Resizer.makeResizable($panel[0], Resizer.DIRECTION_VERTICAL, Resizer.POSITION_TOP, minSize, false, undefined, true);\n        listenToResize($panel);\n    }\n\n    /**\n     * Dom node holding the rendered panel\n     * @type {jQueryObject}\n     */\n    Panel.prototype.$panel = null;\n\n    /**\n     * Determines if the panel is visible\n     * @return {boolean} true if visible, false if not\n     */\n    Panel.prototype.isVisible = function () {\n        return this.$panel.is(\":visible\");\n    };\n\n    /**\n     * Shows the panel\n     */\n    Panel.prototype.show = function () {\n        Resizer.show(this.$panel[0]);\n        exports.trigger(EVENT_WORKSPACE_PANEL_SHOWN, this.panelID);\n    };\n\n    /**\n     * Hides the panel\n     */\n    Panel.prototype.hide = function () {\n        Resizer.hide(this.$panel[0]);\n        exports.trigger(EVENT_WORKSPACE_PANEL_HIDDEN, this.panelID);\n    };\n\n    /**\n     * Sets the panel's visibility state\n     * @param {boolean} visible true to show, false to hide\n     */\n    Panel.prototype.setVisible = function (visible) {\n        if (visible) {\n            this.show();\n        } else {\n            this.hide();\n        }\n    };\n\n\n    /**\n     * Creates a new resizable panel beneath the editor area and above the status bar footer. Panel is initially invisible.\n     * The panel's size & visibility are automatically saved & restored as a view-state preference.\n     *\n     * @param {!string} id  Unique id for this panel. Use package-style naming, e.g. \"myextension.feature.panelname\"\n     * @param {!jQueryObject} $panel  DOM content to use as the panel. Need not be in the document yet. Must have an id\n     *      attribute, for use as a preferences key.\n     * @param {number=} minSize  Minimum height of panel in px.\n     * @return {!Panel}\n     */\n    function createBottomPanel(id, $panel, minSize) {\n        $panel.insertBefore(\"#status-bar\");\n        $panel.hide();\n        updateResizeLimits();  // initialize panel's max size\n\n        panelIDMap[id] = new Panel($panel, minSize);\n        panelIDMap[id].panelID = id;\n\n        return panelIDMap[id];\n    }\n\n    /**\n     * Returns an array of all panel ID's\n     * @returns {Array} List of ID's of all bottom panels\n     */\n    function getAllPanelIDs() {\n        var property, panelIDs = [];\n        for (property in panelIDMap) {\n            if (panelIDMap.hasOwnProperty(property)) {\n                panelIDs.push(property);\n            }\n        }\n        return panelIDs;\n    }\n\n    /**\n     * Gets the Panel interface for the given ID. Can return undefined if no panel with the ID is found.\n     * @param   {string} panelID\n     * @returns {Object} Panel object for the ID or undefined\n     */\n    function getPanelForID(panelID) {\n        return panelIDMap[panelID];\n    }\n\n    /**\n     * Called when an external widget has appeared and needs some of the space occupied\n     *  by the mainview manager\n     * @param {boolean} refreshHint true to refresh the editor, false if not\n     */\n    function recomputeLayout(refreshHint) {\n        triggerUpdateLayout(refreshHint);\n        updateResizeLimits();\n    }\n\n\n    /* Attach to key parts of the overall UI, once created */\n    AppInit.htmlReady(function () {\n        $windowContent = $(\".content\");\n        $editorHolder = $(\"#editor-holder\");\n\n        // Sidebar is a special case: it isn't a Panel, and is not created dynamically. Need to explicitly\n        // listen for resize here.\n        listenToResize($(\"#sidebar\"));\n    });\n\n    /* Unit test only: allow passing in mock DOM notes, e.g. for use with SpecRunnerUtils.createMockEditor() */\n    function _setMockDOM($mockWindowContent, $mockEditorHolder) {\n        $windowContent = $mockWindowContent;\n        $editorHolder = $mockEditorHolder;\n    }\n\n    /* Add this as a capture handler so we're guaranteed to run it before the editor does its own\n     * refresh on resize.\n     */\n    window.addEventListener(\"resize\", handleWindowResize, true);\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Define public API\n    exports.createBottomPanel               = createBottomPanel;\n    exports.recomputeLayout                 = recomputeLayout;\n    exports.getAllPanelIDs                  = getAllPanelIDs;\n    exports.getPanelForID                   = getPanelForID;\n    exports._setMockDOM                     = _setMockDOM;\n    exports.EVENT_WORKSPACE_UPDATE_LAYOUT   = EVENT_WORKSPACE_UPDATE_LAYOUT;\n    exports.EVENT_WORKSPACE_PANEL_SHOWN     = EVENT_WORKSPACE_PANEL_SHOWN;\n    exports.EVENT_WORKSPACE_PANEL_HIDDEN    = EVENT_WORKSPACE_PANEL_HIDDEN;\n});\n"
  },
  {
    "path": "src/view/fontrules/font-based-rules.less",
    "content": "@basefontsize: 16;\n\n/* mixin for converting EM to PX */\n.emtoPx( @emvalue ) when (isem( @emvalue)) {\n    @return: (unit(@emvalue) * @basefontsize) + 0px;\n}\n\n/* mixin for passthrough other units */\n.emtoPx( @emvalue ) when (isem(@emvalue) = false) {\n    @return: @emvalue;\n}\n\n@fontsizeparam : {font-size-param};\n\n@value: return;\n.emtoPx(@fontsizeparam);\n@fontsize: @@value;\n\n@defaultfontsize : 12px;\n@maxvisibleitems: 8;\n@lineheightoffset: 5px/@defaultfontsize;\n@defaultmenuwidth: 300px/@defaultfontsize;\n\n@lineheight: @fontsize +  @fontsize * @lineheightoffset;\n\n.CodeMirror {\n    font-size: @fontsize !important;\n}\n\n.codehint-menu .dropdown-menu li a, .inlinemenu-menu .dropdown-menu li a {\n    font-size: @fontsize !important;\n    line-height: @lineheight  !important;\n}\n\nspan.brackets-js-hints-with-type-details {\n    width: @defaultmenuwidth * @fontsize !important;\n}\n\n.codehint-menu .dropdown-menu, .inlinemenu-menu .dropdown-menu {\n    max-height: @maxvisibleitems * @lineheight !important;\n}"
  },
  {
    "path": "src/widgets/DefaultDialogs.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    /**\n     * List of constants for the default dialogs IDs.\n     */\n    exports.DIALOG_ID_ERROR             = \"error-dialog\";\n    exports.DIALOG_ID_INFO              = \"error-dialog\"; // uses the same template for now--could be different in future\n    exports.DIALOG_ID_SAVE_CLOSE        = \"save-close-dialog\";\n    exports.DIALOG_ID_EXT_CHANGED       = \"ext-changed-dialog\";\n    exports.DIALOG_ID_EXT_DELETED       = \"ext-deleted-dialog\";\n    exports.DIALOG_ID_LIVE_DEVELOPMENT  = \"live-development-error-dialog\";\n    exports.DIALOG_ID_CHANGE_EXTENSIONS = \"change-marked-extensions\";\n});\n"
  },
  {
    "path": "src/widgets/Dialogs.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities for creating and managing standard modal dialogs.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    require(\"utils/Global\");\n\n    var KeyBindingManager = require(\"command/KeyBindingManager\"),\n        KeyEvent          = require(\"utils/KeyEvent\"),\n        Strings           = require(\"strings\"),\n        DialogTemplate    = require(\"text!htmlContent/dialog-template.html\"),\n        Mustache          = require(\"thirdparty/mustache/mustache\");\n\n    /**\n     * Dialog Buttons IDs\n     * @const {string}\n     */\n    var DIALOG_BTN_CANCEL           = \"cancel\",\n        DIALOG_BTN_OK               = \"ok\",\n        DIALOG_BTN_DONTSAVE         = \"dontsave\",\n        DIALOG_BTN_SAVE_AS          = \"save_as\",\n        DIALOG_CANCELED             = \"_canceled\",\n        DIALOG_BTN_DOWNLOAD         = \"download\";\n\n    /**\n     * Dialog Buttons Class Names\n     * @const {string}\n     */\n    var DIALOG_BTN_CLASS_PRIMARY    = \"primary\",\n        DIALOG_BTN_CLASS_NORMAL     = \"\",\n        DIALOG_BTN_CLASS_LEFT       = \"left\";\n\n    /**\n     * The z-index used for the dialogs. Each new dialog increase this number by 2\n     * @type {number}\n     */\n    var zIndex = 1050;\n\n    /**\n     * @private\n     * Dismises a modal dialog\n     * @param {$.Element} $dlg\n     * @param {string} buttonId\n     */\n    function _dismissDialog($dlg, buttonId) {\n        $dlg.data(\"buttonId\", buttonId);\n        $dlg.modal(\"hide\");\n    }\n\n    /**\n     * @private\n     * If autoDismiss is true, then dismisses the dialog. Otherwise just raises an event that the\n     * given button was clicked.\n     * @param {$.Element} $dlg The dialog element to be dismissed.\n     * @param {string} buttonId The ID of the button that was clicked.\n     * @param {boolean} autoDismiss Whether to autodismiss the dialog on a button click.\n     */\n    function _processButton($dlg, buttonId, autoDismiss) {\n        if (autoDismiss) {\n            _dismissDialog($dlg, buttonId);\n        } else {\n            $dlg.triggerHandler(\"buttonClick\", buttonId);\n        }\n    }\n\n    /**\n     * @private\n     * Returns true if the modal dialog has a button with the given ID\n     * @param {$.Element} $dlg\n     * @param {string} buttonId\n     * @return {boolean}\n     */\n    function _hasButton($dlg, buttonId) {\n        return ($dlg.find(\"[data-button-id='\" + buttonId + \"']\").length > 0);\n    }\n\n\n    /**\n     * @private\n     * Handles the use of Tab so that it stays inside the Dialog\n     * @param {$.Event} event\n     * @param {$.Element} $dlg\n     */\n    function _handleTab(event, $dlg) {\n        var $inputs = $(\":input:enabled, a\", $dlg).filter(\":visible\");\n\n        function stopEvent() {\n            event.stopPropagation();\n            event.preventDefault();\n        }\n\n        if ($(event.target).closest($dlg).length) {\n            // If it's the first or last tabbable element, focus the last/first element\n            if ((!event.shiftKey && event.target === $inputs[$inputs.length - 1]) ||\n                    (event.shiftKey && event.target === $inputs[0])) {\n                $inputs.filter(event.shiftKey ? \":last\" : \":first\").focus();\n                stopEvent();\n\n            // If there is no element to focus, don't let it focus outside of the dialog\n            } else if (!$inputs.length) {\n                stopEvent();\n            }\n\n        // If the focus left the dialog, focus the first element in the dialog\n        } else {\n            $inputs.first().focus();\n            stopEvent();\n        }\n    }\n\n\n    /**\n     * Handles the keyDown event for the dialogs\n     * @param {$.Event} e\n     * @param {boolean} autoDismiss\n     * @return {boolean}\n     */\n    var _keydownHook = function (e, autoDismiss) {\n        var $primaryBtn     = this.find(\".primary\"),\n            buttonId        = null,\n            which           = String.fromCharCode(e.which),\n            $focusedElement = this.find(\".dialog-button:focus, a:focus\");\n\n        function stopEvent() {\n            e.preventDefault();\n            e.stopPropagation();\n        }\n\n        // There might be a textfield in the dialog's UI; don't want to mistake normal typing for dialog dismissal\n        var inTextArea    = (e.target.tagName === \"TEXTAREA\"),\n            inTypingField = inTextArea || ($(e.target).filter(\":text, :password\").length > 0);\n\n        if (e.which === KeyEvent.DOM_VK_TAB) {\n            // We don't want to stopEvent() in this case since we might want the default behavior.\n            // _handleTab takes care of stopping/preventing default as necessary.\n            _handleTab(e, this);\n        } else if (e.which === KeyEvent.DOM_VK_ESCAPE) {\n            buttonId = DIALOG_BTN_CANCEL;\n        } else if (e.which === KeyEvent.DOM_VK_RETURN && (!inTextArea || e.ctrlKey)) {\n            // Enter key in single-line text input always dismisses; in text area, only Ctrl+Enter dismisses\n            // Click primary\n            stopEvent();\n            if (e.target.tagName === \"BUTTON\") {\n                this.find(e.target).click();\n            } else if (e.target.tagName !== \"INPUT\") {\n                // If the target element is not BUTTON or INPUT, click the primary button\n                // We're making an exception for INPUT element because of this issue: GH-11416\n                $primaryBtn.click();\n            }\n        } else if (e.which === KeyEvent.DOM_VK_SPACE) {\n            if ($focusedElement.length) {\n                // Space bar on focused button or link\n                stopEvent();\n                $focusedElement.click();\n            }\n        } else if (brackets.platform === \"mac\") {\n            // CMD+Backspace Don't Save\n            if (e.metaKey && (e.which === KeyEvent.DOM_VK_BACK_SPACE)) {\n                if (_hasButton(this, DIALOG_BTN_DONTSAVE)) {\n                    buttonId = DIALOG_BTN_DONTSAVE;\n                }\n            // FIXME (issue #418) CMD+. Cancel swallowed by native shell\n            } else if (e.metaKey && (e.which === KeyEvent.DOM_VK_PERIOD)) {\n                buttonId = DIALOG_BTN_CANCEL;\n            }\n        } else { // if (brackets.platform === \"win\") {\n            // 'N' Don't Save\n            if (which === \"N\" && !inTypingField) {\n                if (_hasButton(this, DIALOG_BTN_DONTSAVE)) {\n                    buttonId = DIALOG_BTN_DONTSAVE;\n                }\n            }\n        }\n\n        if (buttonId) {\n            stopEvent();\n            _processButton(this, buttonId, autoDismiss);\n        }\n\n        // Stop any other global hooks from processing the event (but\n        // allow it to continue bubbling if we haven't otherwise stopped it).\n        return true;\n    };\n\n\n\n    /**\n     * @constructor\n     * @private\n     *\n     * @param {$.Element} $dlg The dialog jQuery element\n     * @param {$.Promise} promise A promise that will be resolved with the ID of the clicked button when the dialog\n     *     is dismissed. Never rejected.\n     */\n    function Dialog($dlg, promise) {\n        this._$dlg    = $dlg;\n        this._promise = promise;\n    }\n\n    /**\n     * The dialog jQuery element\n     * @type {$.Element}\n     */\n    Dialog.prototype.getElement = function () {\n        return this._$dlg;\n    };\n\n    /**\n     * The dialog promise\n     * @type {$.Promise}\n     */\n    Dialog.prototype.getPromise = function () {\n        return this._promise;\n    };\n\n    /**\n     * Closes the dialog if is visible\n     */\n    Dialog.prototype.close = function () {\n        if (this._$dlg.is(\":visible\")) {   // Bootstrap breaks if try to hide dialog that's already hidden\n            _dismissDialog(this._$dlg, DIALOG_CANCELED);\n        }\n    };\n\n    /**\n     * Adds a done callback to the dialog promise\n     */\n    Dialog.prototype.done = function (callback) {\n        this._promise.done(callback);\n    };\n\n\n    /**\n     * Don't allow dialog to exceed viewport size\n     */\n    function setDialogMaxSize() {\n        var maxWidth, maxHeight,\n            $dlgs = $(\".modal-inner-wrapper > .instance\");\n\n        // Verify 1 or more modal dialogs are showing\n        if ($dlgs.length > 0) {\n            maxWidth  = $(\"body\").width();\n            maxHeight = $(\"body\").height();\n\n            $dlgs.css({\n                \"max-width\":  maxWidth,\n                \"max-height\": maxHeight,\n                \"overflow\":   \"auto\"\n            });\n        }\n    }\n\n    /**\n     * Creates a new modal dialog from a given template.\n     * The template can either be a string or a jQuery object representing a DOM node that is *not* in the current DOM.\n     *\n     * @param {string} template A string template or jQuery object to use as the dialog HTML.\n     * @param {boolean=} autoDismiss Whether to automatically dismiss the dialog when one of the buttons\n     *      is clicked. Default true. If false, you'll need to manually handle button clicks and the Esc\n     *      key, and dismiss the dialog yourself when ready by calling `close()` on the returned dialog.\n     * @return {Dialog}\n     */\n    function showModalDialogUsingTemplate(template, autoDismiss) {\n        if (autoDismiss === undefined) {\n            autoDismiss = true;\n        }\n\n        $(\"body\").append(\"<div class='modal-wrapper'><div class='modal-inner-wrapper'></div></div>\");\n\n        var result  = new $.Deferred(),\n            promise = result.promise(),\n            $dlg    = $(template)\n                .addClass(\"instance\")\n                .appendTo(\".modal-inner-wrapper:last\");\n\n        // Don't allow dialog to exceed viewport size\n        setDialogMaxSize();\n\n        // Save the dialog promise for unit tests\n        $dlg.data(\"promise\", promise);\n\n        var keydownHook = function (e) {\n            return _keydownHook.call($dlg, e, autoDismiss);\n        };\n\n        // Store current focus\n        var lastFocus = window.document.activeElement;\n\n        // Pipe dialog-closing notification back to client code\n        $dlg.one(\"hidden\", function () {\n            var buttonId = $dlg.data(\"buttonId\");\n            if (!buttonId) {    // buttonId will be undefined if closed via Bootstrap's \"x\" button\n                buttonId = DIALOG_BTN_CANCEL;\n            }\n\n            // Let call stack return before notifying that dialog has closed; this avoids issue #191\n            // if the handler we're triggering might show another dialog (as long as there's no\n            // fade-out animation)\n            window.setTimeout(function () {\n                result.resolve(buttonId);\n            }, 0);\n\n            // Remove the dialog instance from the DOM.\n            $dlg.remove();\n\n            // Remove our global keydown handler.\n            KeyBindingManager.removeGlobalKeydownHook(keydownHook);\n\n            // Restore previous focus\n            if (lastFocus) {\n                lastFocus.focus();    \n            }\n\n            //Remove wrapper\n            $(\".modal-wrapper:last\").remove();\n        }).one(\"shown\", function () {\n            var $primaryBtn = $dlg.find(\".primary:enabled\"),\n                $otherBtn   = $dlg.find(\".modal-footer .dialog-button:enabled:eq(0)\");\n\n            // Set focus to the primary button, to any other button, or to the dialog depending\n            // if there are buttons\n            if ($primaryBtn.length) {\n                $primaryBtn.focus();\n            } else if ($otherBtn.length) {\n                $otherBtn.focus();\n            } else {\n                window.document.activeElement.blur();\n            }\n\n            // Push our global keydown handler onto the global stack of handlers.\n            KeyBindingManager.addGlobalKeydownHook(keydownHook);\n        });\n\n        // Click handler for buttons\n        $dlg.one(\"click\", \".dialog-button\", function (e) {\n            _processButton($dlg, $(this).attr(\"data-button-id\"), autoDismiss);\n        });\n\n        // Run the dialog\n        $dlg\n            .modal({\n                backdrop: \"static\",\n                show:     true,\n                selector: \".modal-inner-wrapper:last\",\n                keyboard: false // handle the ESC key ourselves so we can deal with nested dialogs\n            })\n            // Updates the z-index of the modal dialog and the backdrop\n            .css(\"z-index\", zIndex + 1)\n            .next()\n            .css(\"z-index\", zIndex);\n\n        zIndex += 2;\n\n        return (new Dialog($dlg, promise));\n    }\n\n\n    /**\n     * Creates a new general purpose modal dialog using the default template and the template variables given\n     * as parameters as described.\n     *\n     * @param {string} dlgClass A class name identifier for the dialog. Typically one of DefaultDialogs.*\n     * @param {string=} title The title of the dialog. Can contain HTML markup. Defaults to \"\".\n     * @param {string=} message The message to display in the dialog. Can contain HTML markup. Defaults to \"\".\n     * @param {Array.<{className: string, id: string, text: string}>=} buttons An array of buttons where each button\n     *      has a class, id and text property. The id is used in \"data-button-id\". Defaults to a single Ok button.\n     *      Typically className is one of DIALOG_BTN_CLASS_*, id is one of DIALOG_BTN_*\n     * @param {boolean=} autoDismiss Whether to automatically dismiss the dialog when one of the buttons\n     *      is clicked. Default true. If false, you'll need to manually handle button clicks and the Esc\n     *      key, and dismiss the dialog yourself when ready by calling `close()` on the returned dialog.\n     * @return {Dialog}\n     */\n    function showModalDialog(dlgClass, title, message, buttons, autoDismiss) {\n        var templateVars = {\n            dlgClass: dlgClass,\n            title:    title   || \"\",\n            message:  message || \"\",\n            buttons:  buttons || [{ className: DIALOG_BTN_CLASS_PRIMARY, id: DIALOG_BTN_OK, text: Strings.OK }]\n        };\n        var template = Mustache.render(DialogTemplate, templateVars);\n\n        return showModalDialogUsingTemplate(template, autoDismiss);\n    }\n\n    /**\n     * Immediately closes any dialog instances with the given class. The dialog callback for each instance will\n     * be called with the special buttonId DIALOG_CANCELED (note: callback is run asynchronously).\n     * @param {string} dlgClass The class name identifier for the dialog.\n     * @param {string=} buttonId The button id to use when closing the dialog. Defaults to DIALOG_CANCELED\n     */\n    function cancelModalDialogIfOpen(dlgClass, buttonId) {\n        $(\".\" + dlgClass + \".instance\").each(function () {\n            if ($(this).is(\":visible\")) {   // Bootstrap breaks if try to hide dialog that's already hidden\n                _dismissDialog($(this), buttonId || DIALOG_CANCELED);\n            }\n        });\n    }\n\n    /**\n     * Ensures that all <a> tags with a URL have a tooltip showing the same URL\n     * @param {!jQueryObject|Dialog} elementOrDialog  Dialog intance, or root of other DOM tree to add tooltips to\n     */\n    function addLinkTooltips(elementOrDialog) {\n        var $element;\n        if (elementOrDialog.getElement) {\n            $element = elementOrDialog.getElement().find(\".dialog-message\");\n        } else {\n            $element = elementOrDialog;\n        }\n        $element.find(\"a\").each(function (index, elem) {\n            var $elem = $(elem);\n            var url = $elem.attr(\"href\");\n            if (url && url !== \"#\" && !$elem.attr(\"title\")) {\n                $elem.attr(\"title\", url);\n            }\n        });\n    }\n\n    window.addEventListener(\"resize\", setDialogMaxSize);\n\n    exports.DIALOG_BTN_CANCEL            = DIALOG_BTN_CANCEL;\n    exports.DIALOG_BTN_OK                = DIALOG_BTN_OK;\n    exports.DIALOG_BTN_DONTSAVE          = DIALOG_BTN_DONTSAVE;\n    exports.DIALOG_BTN_SAVE_AS           = DIALOG_BTN_SAVE_AS;\n    exports.DIALOG_CANCELED              = DIALOG_CANCELED;\n    exports.DIALOG_BTN_DOWNLOAD          = DIALOG_BTN_DOWNLOAD;\n\n    exports.DIALOG_BTN_CLASS_PRIMARY     = DIALOG_BTN_CLASS_PRIMARY;\n    exports.DIALOG_BTN_CLASS_NORMAL      = DIALOG_BTN_CLASS_NORMAL;\n    exports.DIALOG_BTN_CLASS_LEFT        = DIALOG_BTN_CLASS_LEFT;\n\n    exports.showModalDialog              = showModalDialog;\n    exports.showModalDialogUsingTemplate = showModalDialogUsingTemplate;\n    exports.cancelModalDialogIfOpen      = cancelModalDialogIfOpen;\n    exports.addLinkTooltips              = addLinkTooltips;\n});\n"
  },
  {
    "path": "src/widgets/DropdownButton.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Button that opens a dropdown list when clicked. More akin to a popup menu than a combobox. Compared to a\n * simple <select> element:\n *  - There's no \"selected\" state\n *  - The button's label is not automatically changed when an item in the list is clicked\n *  - Its width is not the max of all the dropdown items' labels\n *  - The button & dropdown's appearance can be customized far more\n * Events\n *  - listRendered -- This event is dispatched after the entire list is rendered so that custom event handlers can be\n *                    set up for any custom UI in the list.\n *\n * TODO: merge DropdownEventHandler into this? Are there any other widgets that might want to use it separately?\n *\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var DropdownEventHandler    = require(\"utils/DropdownEventHandler\").DropdownEventHandler,\n        EventDispatcher         = require(\"utils/EventDispatcher\"),\n        WorkspaceManager        = require(\"view/WorkspaceManager\"),\n        Menus                   = require(\"command/Menus\"),\n        ViewUtils               = require(\"utils/ViewUtils\"),\n        _                       = require(\"thirdparty/lodash\");\n\n    /**\n     * Creates a single dropdown-button instance. The DOM node is created but not attached to\n     * the document anywhere - clients should append this.$button to the appropriate location.\n     *\n     * DropdownButton dispatches the following events:\n     *  - \"select\" - when an option in the dropdown is clicked. Passed item object and index.\n     *\n     * @param {!string} label  Label to display on the button\n     * @param {!Array.<*>} items  Items in the dropdown list. It generally doesn't matter what type/value the\n     *          items have, except that any item === \"---\" will be treated as a divider. Such items are not\n     *          clickable and itemRenderer() will not be called for them.\n     * @param {?function(*, number):!string|{html:string, enabled:boolean} itemRenderer  Optional function to\n     *          convert a single item to HTML (see itemRenderer() docs below). If not provided, items are\n     *          assumed to be plain text strings.\n     */\n    function DropdownButton(label, items, itemRenderer) {\n        this.items = items;\n\n        this.itemRenderer = itemRenderer || this.itemRenderer;\n\n        this._onClick        = this._onClick.bind(this);\n        this.closeDropdown   = this.closeDropdown.bind(this);\n        this._onClickOutside = this._onClickOutside.bind(this);\n\n        this.$button = $(\"<button class='btn btn-dropdown'/>\")\n            .text(label)\n            .on(\"click\", this._onClick);\n    }\n    EventDispatcher.makeEventDispatcher(DropdownButton.prototype);\n\n    /**\n     * Items in dropdown list - may be changed any time dropdown isn't open\n     * @type {!Array.<*>}\n     */\n    DropdownButton.prototype.items = null;\n\n    /**\n     * The clickable button. Available as soon as the DropdownButton is constructed.\n     * @type {!jQueryObject}\n     */\n    DropdownButton.prototype.$button = null;\n\n    /**\n     * The dropdown element. Only non-null while open.\n     * @type {?jQueryObject}\n     */\n    DropdownButton.prototype.$dropdown = null;\n\n    /**\n     * Extra CSS class(es) to apply to $dropdown\n     * @type {?string}\n     */\n    DropdownButton.prototype.dropdownExtraClasses = null;\n\n    /**\n     * @private\n     * Where to restore focus when dropdown closed\n     * @type {?HTMLElement}\n     */\n    DropdownButton.prototype._lastFocus = null;\n\n    /**\n     * @private\n     * Helper object for dropdown. Only non-null while open.\n     * @type {?DropdownEventHandler}\n     */\n    DropdownButton.prototype._dropdownEventHandler = null;\n\n\n    /**\n     * @private\n     * Handle clicking button\n     */\n    DropdownButton.prototype._onClick = function (event) {\n        if (!this.$button.hasClass(\"disabled\")) {\n            this.toggleDropdown();\n        }\n        // Indicate click was handled (e.g. to shield from MultiRangeInlineEditor._onClick())\n        event.stopPropagation();\n    };\n\n    /**\n     * Update the button label.\n     * @param {string} label\n     */\n    DropdownButton.prototype.setButtonLabel = function (label) {\n        if (!this.$button) {\n            return;\n        }\n        $(this.$button).text(label);\n    };\n\n    /**\n     * Called for each item when rendering the dropdown.\n     * @param {*} item from items array\n     * @param {number} index in items array\n     * @return {!string|{html:string, enabled:boolean}} Formatted & escaped HTML, either as a simple string\n     *      or as the 'html' field in an object that also conveys enabled state. Disabled items inherit gray\n     *      text color and cannot be selected.\n     */\n    DropdownButton.prototype.itemRenderer = function (item, index) {\n        return _.escape(String(item));\n    };\n\n    /**\n     * Converts the list of item objects into HTML list items in format required by DropdownEventHandler\n     * @param {!jQueryObject} parent The dropdown element\n     * @return {!jQueryObject} The dropdown element with the rendered list items appended.\n     */\n    DropdownButton.prototype._renderList = function (parent) {\n        if (!parent) {\n            return null;\n        }\n\n        var html = \"\";\n        this.items.forEach(function (item, i) {\n            if (item === \"---\") {\n                html += \"<li class='divider'></li>\";\n            } else {\n                var rendered = this.itemRenderer(item, i),\n                    itemHtml = rendered.html || rendered,\n                    disabledClass = (rendered.html && !rendered.enabled) ? \"disabled\" : \"\";\n\n                html += \"<li><a class='stylesheet-link \" + disabledClass + \"' data-index='\" + i + \"'>\";\n                html += itemHtml;\n                html += \"</a></li>\";\n            }\n        }.bind(this));\n\n        parent.append(html);\n\n        // Also trigger listRendered handler so that custom event handlers can be\n        // set up for any custom UI in the list.\n        this.trigger(\"listRendered\", parent);\n\n        // Also need to re-register mouse event handlers with the updated list.\n        if (this._dropdownEventHandler) {\n            this._dropdownEventHandler.reRegisterMouseHandlers(parent);\n        }\n\n        return parent;\n    };\n\n    /**\n     * Refresh the dropdown list by removing and re-creating all list items.\n     * Call this after deleting/adding any item in the dropdown list.\n     */\n    DropdownButton.prototype.refresh = function () {\n        if (!this.$dropdown) {\n            return;\n        }\n\n        // Remove all list items and then re-create them from this.items.\n        $(\"li\", this.$dropdown).remove();\n        this._renderList(this.$dropdown);\n    };\n\n    /**\n     * Check/Uncheck the list item of the given index.\n     * @param {number} index The index of the list item to be checked or unchecked\n     * @param {boolean} checked True if the list item is to be checked, false to get check\n     *    mark removed.\n     */\n    DropdownButton.prototype.setChecked = function (index, checked) {\n        if (!this.$dropdown) {\n            return;\n        }\n\n        var listItems = $(\"li\", this.$dropdown),\n            count     = listItems.length;\n\n        if (index > -1 && index < count) {\n            $(\"a\", listItems[index]).toggleClass(\"checked\", checked);\n        }\n    };\n\n    /** Pops open the dropdown if currently closed. Does nothing if items.length == 0 */\n    DropdownButton.prototype.showDropdown = function () {\n        // Act like a plain old button if no items to show\n        if (!this.items.length) {\n            return;\n        }\n\n        if (this.$dropdown) {\n            return;\n        }\n\n        Menus.closeAll();\n\n        var $dropdown = $(\"<ul class='dropdown-menu dropdownbutton-popup' tabindex='-1'>\")\n            .addClass(this.dropdownExtraClasses)  // (no-op if unspecified)\n            .css(\"min-width\", this.$button.outerWidth());  // do this before the clipping calcs below\n\n        this.$dropdown = $dropdown;\n        this._renderList(this.$dropdown)\n            .appendTo($(\"body\"))\n            .data(\"attached-to\", this.$button[0]);  // keep ModalBar open while dropdown focused\n\n        // Calculate position of dropdown\n        var toggleOffset = this.$button.offset(),\n            posLeft      = toggleOffset.left,\n            posTop       = toggleOffset.top + this.$button.outerHeight(),\n            elementRect  = {\n                top:     posTop,\n                left:    posLeft,\n                height:  $dropdown.height(),\n                width:   $dropdown.width()\n            },\n            clip = ViewUtils.getElementClipSize($(window), elementRect);\n\n        if (clip.bottom > 0) {\n            // Bottom is clipped, so move entire menu above button\n            posTop = Math.max(0, toggleOffset.top - $dropdown.height() - 4);\n        }\n\n        // Take in consideration the scrollbar to prevent unexpected behaviours (see #10963).\n        var dropdownElement = this.$dropdown[0];\n        var scrollWidth = dropdownElement.offsetWidth - dropdownElement.clientWidth + 1;\n\n        if (clip.right > 0) {\n            // Right is clipped, so adjust left to fit menu in editor.\n            posLeft = Math.max(0, posLeft - clip.right - scrollWidth);\n        }\n\n        $dropdown.css({\n            left: posLeft,\n            top: posTop,\n            width: $dropdown.width() + scrollWidth\n        });\n\n        // Attach event handlers\n        this._dropdownEventHandler = new DropdownEventHandler($dropdown, this._onSelect.bind(this), this._onDropdownClose.bind(this));\n        this._dropdownEventHandler.open();\n\n        window.document.body.addEventListener(\"mousedown\", this._onClickOutside, true);\n        WorkspaceManager.on(\"workspaceUpdateLayout\", this.closeDropdown);\n\n        // Manage focus\n        this._lastFocus = window.document.activeElement;\n        $dropdown.focus();\n    };\n\n    /**\n     * @private\n     * Clean up event handlers after dropdown closed & dispose old dropdown DOM. Called regardless of how the dropdown\n     * was closed.\n     */\n    DropdownButton.prototype._onDropdownClose = function () {\n        window.document.body.removeEventListener(\"mousedown\", this._onClickOutside, true);\n        WorkspaceManager.off(\"workspaceUpdateLayout\", this.closeDropdown);\n\n        // Restore focus to old pos, unless \"select\" handler changed it\n        if (window.document.activeElement === this.$dropdown[0]) {\n            this._lastFocus.focus();\n        }\n\n        this._dropdownEventHandler = null;\n        this.$dropdown = null;  // already remvoed from DOM automatically by PopUpManager\n    };\n\n    /** Closes the dropdown if currently open */\n    DropdownButton.prototype.closeDropdown = function () {\n        if (this._dropdownEventHandler) {\n            this._dropdownEventHandler.close();\n        }\n    };\n\n    /**\n     * @private\n     * Clicking outside the dropdown closes it\n     */\n    DropdownButton.prototype._onClickOutside = function (event) {\n        var $container = $(event.target).closest(\".dropdownbutton-popup\");\n\n        // If click is outside dropdown list or dropdown button, then close dropdown list\n        if (!$(event.target).is(this.$button) &&\n                ($container.length === 0 || $container[0] !== this.$dropdown[0])) {\n            this.closeDropdown();\n            event.stopPropagation();\n            event.preventDefault();\n        }\n    };\n\n    /** Opens the dropdown if closed; closes it if open */\n    DropdownButton.prototype.toggleDropdown = function () {\n        if (this.$dropdown) {\n            this.closeDropdown();\n        } else {\n            this.showDropdown();\n        }\n    };\n\n    /**\n     * @private\n     * Callback from DropdownEventHandler when item in dropdown list is selected (via mouse or keyboard)\n     * @param {!jQueryObject} $link  The `a` element selected\n     */\n    DropdownButton.prototype._onSelect = function ($link) {\n        var itemIndex = Number($link.data(\"index\"));\n        this.trigger(\"select\", this.items[itemIndex], itemIndex);\n    };\n\n\n    exports.DropdownButton = DropdownButton;\n});\n"
  },
  {
    "path": "src/widgets/InlineMenu.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var KeyBindingManager = require(\"command/KeyBindingManager\"),\n        Menus             = require(\"command/Menus\"),\n        KeyEvent          = require(\"utils/KeyEvent\"),\n        StringUtils       = require(\"utils/StringUtils\"),\n        ValidationUtils   = require(\"utils/ValidationUtils\"),\n        ViewUtils         = require(\"utils/ViewUtils\"),\n        PopUpManager      = require(\"widgets/PopUpManager\"),\n        Mustache          = require(\"thirdparty/mustache/mustache\");\n\n    var MenuHTML  = require(\"text!htmlContent/inline-menu.html\");\n\n    /**\n     * Displays a popup list of items for a given editor context\n     *\n     * @constructor\n     * @param {Editor} editor\n     * @param {string} menuText\n     */\n    function InlineMenu(editor, menuText) {\n        /**\n         * The list of items to display\n         *\n         * @type {Array.<{id: number, name: string>}\n         */\n        this.items = [];\n\n        /**\n         * The selected position in the list; otherwise -1.\n         *\n         * @type {number}\n         */\n        this.selectedIndex = -1;\n\n\n        /**\n         * Is the list currently open?\n         *\n         * @type {boolean}\n         */\n        this.opened = false;\n\n\n        /**\n         * The editor context\n         *\n         * @type {Editor}\n         */\n        this.editor = editor;\n\n\n        /**\n         * The menu selection callback function\n         *\n         * @type {Function}\n         */\n        this.handleSelect = null;\n\n        /**\n         * The menu closure callback function\n         *\n         * @type {Function}\n         */\n        this.handleClose = null;\n\n        /**\n         * The menu object\n         *\n         * @type {jQuery.Object}\n         */\n        this.$menu =\n            $(\"<li class='dropdown inlinemenu-menu'></li>\")\n                .append($(\"<a href='#' class='dropdown-toggle' data-toggle='dropdown'></a>\")\n                        .hide())\n                .append(\"<ul class='dropdown-menu'>\" +\n                            \"<li class='inlinemenu-header'>\" +\n                                \"<a>\" + menuText + \"</a>\" +\n                            \"</li>\" +\n                         \"</ul>\");\n\n        this._keydownHook = this._keydownHook.bind(this);\n    }\n\n    /**\n     * Select the item in the menu at the specified index, or remove the\n     * selection if index < 0.\n     *\n     * @private\n     * @param {number} index\n     */\n    InlineMenu.prototype._setSelectedIndex = function (index) {\n        var items = this.$menu.find(\"li.inlinemenu-item\");\n\n        // Range check\n        index = Math.max(-1, Math.min(index, items.length - 1));\n\n        // Clear old highlight\n        if (this.selectedIndex !== -1) {\n            $(items[this.selectedIndex]).find(\"a\").removeClass(\"highlight\");\n        }\n\n        this.selectedIndex = index;\n\n        // Highlight the new selected item, if necessary\n        if (this.selectedIndex !== -1) {\n            var $item = $(items[this.selectedIndex]);\n            var $view = this.$menu.find(\"ul.dropdown-menu\");\n\n            $item.find(\"a\").addClass(\"highlight\");\n            ViewUtils.scrollElementIntoView($view, $item, false);\n        }\n\n        // Invoke handleHover callback if any\n        if (this.handleHover) {\n            this.handleHover(this.items[index].id);\n        }\n    };\n\n    /**\n     * Rebuilds the list items for the menu.\n     *\n     * @private\n     */\n    InlineMenu.prototype._buildListView = function (items) {\n        var self            = this,\n            view            = { items: [] },\n            _addItem;\n\n        this.items = items;\n\n        _addItem = function (item) {\n            view.items.push({ formattedItem: \"<span>\" + item.name + \"</span>\"});\n        };\n\n        // clear the list\n        this.$menu.find(\"li.inlinemenu-item\").remove();\n\n        // if there are no items then close the list; otherwise add them and\n        // set the selection\n        if (this.items.length === 0) {\n            if (this.handleClose) {\n                this.handleClose();\n            }\n        } else {\n            this.items.some(function (item, index) {\n                _addItem(item);\n            });\n\n            // render the menu list\n            var $ul = this.$menu.find(\"ul.dropdown-menu\"),\n                $parent = $ul.parent();\n\n            // remove list temporarily to save rendering time\n            $ul.remove().append(Mustache.render(MenuHTML, view));\n\n            $ul.children(\"li.inlinemenu-item\").each(function (index, element) {\n                var item      = self.items[index],\n                    $element    = $(element);\n\n                // store id of item in the element\n                $element.data(\"itemid\", item.id);\n            });\n\n            // delegate list item events to the top-level ul list element\n            $ul.on(\"click\", \"li.inlinemenu-item\", function (e) {\n                // Don't let the click propagate upward (otherwise it will\n                // hit the close handler in bootstrap-dropdown).\n                e.stopPropagation();\n                if (self.handleSelect) {\n                    self.handleSelect($(this).data(\"itemid\"));\n                }\n            });\n\n            $ul.on(\"mouseover\", \"li.inlinemenu-item\", function (e) {\n                e.stopPropagation();\n                // _setSelectedIndex sets the selected index and call handle hover\n                // callback funtion\n                self._setSelectedIndex(self.items.findIndex(function(element) {\n                    return element.id === $(e.currentTarget).data(\"itemid\");\n                }));\n            });\n\n            $parent.append($ul);\n\n            this._setSelectedIndex(0);\n        }\n    };\n\n    /**\n     * Computes top left location for menu so that the menu is not clipped by the window.\n     * Also computes the largest available width.\n     *\n     * @private\n     * @return {{left: number, top: number, width: number}}\n     */\n    InlineMenu.prototype._calcMenuLocation = function () {\n        var cursor      = this.editor._codeMirror.cursorCoords(),\n            posTop      = cursor.bottom,\n            posLeft     = cursor.left,\n            textHeight  = this.editor.getTextHeight(),\n            $window     = $(window),\n            $menuWindow = this.$menu.children(\"ul\"),\n            menuHeight  = $menuWindow.outerHeight();\n\n        // TODO Ty: factor out menu repositioning logic so inline menu and Context menus share code\n        // adjust positioning so menu is not clipped off bottom or right\n        var bottomOverhang = posTop + menuHeight - $window.height();\n        if (bottomOverhang > 0) {\n            posTop -= (textHeight + 2 + menuHeight);\n        }\n\n        posTop -= 30;   // shift top for hidden parent element\n\n        var menuWidth = $menuWindow.width();\n        var availableWidth = menuWidth;\n        var rightOverhang = posLeft + menuWidth - $window.width();\n        if (rightOverhang > 0) {\n            // Right overhang is negative\n            posLeft = Math.max(0, posLeft - rightOverhang);\n        }\n\n        return {left: posLeft, top: posTop, width: availableWidth};\n    };\n\n\n    /**\n     * Check whether Event is one of the keys that we handle or not.\n     *\n     * @param {KeyBoardEvent|keyBoardEvent.keyCode} keyEvent\n     */\n    InlineMenu.prototype.isHandlingKeyCode = function (keyCodeOrEvent) {\n        var keyCode = typeof keyCodeOrEvent === \"object\" ? keyCodeOrEvent.keyCode : keyCodeOrEvent;\n        var ctrlKey = typeof keyCodeOrEvent === \"object\" ? keyCodeOrEvent.ctrlKey : false;\n\n\n        return (keyCode === KeyEvent.DOM_VK_UP || keyCode === KeyEvent.DOM_VK_DOWN ||\n            keyCode === KeyEvent.DOM_VK_PAGE_UP || keyCode === KeyEvent.DOM_VK_PAGE_DOWN ||\n            keyCode === KeyEvent.DOM_VK_RETURN ||\n            keyCode === KeyEvent.DOM_VK_ESCAPE\n        );\n    };\n\n    /**\n     * Convert keydown events into hint list navigation actions.\n     *\n     * @param {KeyBoardEvent} keyEvent\n     */\n    InlineMenu.prototype._keydownHook = function (event) {\n        var keyCode,\n            self = this;\n\n        // positive distance rotates down; negative distance rotates up\n        function _rotateSelection(distance) {\n            var len = self.items.length,\n                pos;\n\n            if (self.selectedIndex < 0) {\n                // set the initial selection\n                pos = (distance > 0) ? distance - 1 : len - 1;\n\n            } else {\n                // adjust current selection\n                pos = self.selectedIndex;\n\n                // Don't \"rotate\" until all items have been shown\n                if (distance > 0) {\n                    if (pos === (len - 1)) {\n                        pos = 0;  // wrap\n                    } else {\n                        pos = Math.min(pos + distance, len - 1);\n                    }\n                } else {\n                    if (pos === 0) {\n                        pos = (len - 1);  // wrap\n                    } else {\n                        pos = Math.max(pos + distance, 0);\n                    }\n                }\n            }\n\n            self._setSelectedIndex(pos);\n        }\n\n        // Calculate the number of items per scroll page.\n        function _itemsPerPage() {\n            var itemsPerPage = 1,\n                $items = self.$menu.find(\"li.inlinemenu-item\"),\n                $view = self.$menu.find(\"ul.dropdown-menu\"),\n                itemHeight;\n\n            if ($items.length !== 0) {\n                itemHeight = $($items[0]).height();\n                if (itemHeight) {\n                    // round down to integer value\n                    itemsPerPage = Math.floor($view.height() / itemHeight);\n                    itemsPerPage = Math.max(1, Math.min(itemsPerPage, $items.length));\n                }\n            }\n\n            return itemsPerPage;\n        }\n\n        // If we're no longer visible, skip handling the key and end the session.\n        if (!this.isOpen()) {\n            this.handleClose();\n            return false;\n        }\n\n        // (page) up, (page) down, enter are handled by the list\n        if ((event.type === \"keydown\") && this.isHandlingKeyCode(event)) {\n            keyCode = event.keyCode;\n\n            if (event.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n                event.stopImmediatePropagation();\n                this.handleClose();\n\n                return false;\n            } else if (event.shiftKey &&\n                    (event.keyCode === KeyEvent.DOM_VK_UP ||\n                     event.keyCode === KeyEvent.DOM_VK_DOWN ||\n                     event.keyCode === KeyEvent.DOM_VK_PAGE_UP ||\n                     event.keyCode === KeyEvent.DOM_VK_PAGE_DOWN)) {\n                this.handleClose();\n                // Let the event bubble.\n                return false;\n            } else if (keyCode === KeyEvent.DOM_VK_UP) {\n                _rotateSelection.call(this, -1);\n            } else if (keyCode === KeyEvent.DOM_VK_DOWN) {\n                _rotateSelection.call(this, 1);\n            } else if (keyCode === KeyEvent.DOM_VK_PAGE_UP) {\n                _rotateSelection.call(this, -_itemsPerPage());\n            } else if (keyCode === KeyEvent.DOM_VK_PAGE_DOWN) {\n                _rotateSelection.call(this, _itemsPerPage());\n            } else if (this.selectedIndex !== -1 &&\n                    (keyCode === KeyEvent.DOM_VK_RETURN)) {\n                // Trigger a click handler to commmit the selected item\n                $(this.$menu.find(\"li.inlinemenu-item\")[this.selectedIndex]).trigger(\"click\");\n            } else {\n                return false;\n            }\n\n            event.stopImmediatePropagation();\n            event.preventDefault();\n            return true;\n        }\n\n        return false;\n    };\n\n    /**\n     * Is the Inline menu open?\n     *\n     * @return {boolean}\n     */\n    InlineMenu.prototype.isOpen = function () {\n        // We don't get a notification when the dropdown closes. The best\n        // we can do is keep an \"opened\" flag and check to see if we\n        // still have the \"open\" class applied.\n        if (this.opened && !this.$menu.hasClass(\"open\")) {\n            this.opened = false;\n        }\n\n        return this.opened;\n    };\n\n    /**\n     * Displays the menu at the current cursor position\n     *\n     * @param {Array.<{id: number, name: string>} hints\n     */\n    InlineMenu.prototype.open = function (items) {\n        Menus.closeAll();\n\n        this._buildListView(items);\n\n        if (this.items.length) {\n            // Need to add the menu to the DOM before trying to calculate its ideal location.\n            $(\"#inlinemenu-menu-bar > ul\").append(this.$menu);\n\n            var menuPos = this._calcMenuLocation();\n\n            this.$menu.addClass(\"open\")\n                .css({\"left\": menuPos.left, \"top\": menuPos.top, \"width\": menuPos.width + \"px\"});\n            this.opened = true;\n\n            KeyBindingManager.addGlobalKeydownHook(this._keydownHook);\n        }\n    };\n\n    /**\n     * Displays the last menu which was closed due to Scrolling\n     */\n    InlineMenu.prototype.openRemovedMenu = function () {\n        if (this.opened === true) {\n            if (this.$menu && !this.$menu.hasClass(\"open\")) {\n                var menuPos = this._calcMenuLocation();\n                this.$menu.addClass(\"open\")\n                    .css({\"left\": menuPos.left, \"top\": menuPos.top, \"width\": menuPos.width + \"px\"});\n            }\n        }\n    };\n\n    /**\n     * Closes the menu\n     */\n    InlineMenu.prototype.close = function () {\n        this.opened = false;\n\n        if (this.$menu) {\n            this.$menu.removeClass(\"open\");\n            PopUpManager.removePopUp(this.$menu);\n            this.$menu.remove();\n        }\n\n        KeyBindingManager.removeGlobalKeydownHook(this._keydownHook);\n    };\n\n    /**\n     * Set the menu selection callback function\n     *\n     * @param {Function} callback\n     */\n    InlineMenu.prototype.onSelect = function (callback) {\n        this.handleSelect = callback;\n    };\n\n    /**\n     * Set the hover callback function\n     *\n     * @param {Function} callback\n     */\n    InlineMenu.prototype.onHover = function (callback) {\n        this.handleHover = callback;\n    };\n\n    /**\n     * Set the menu closure callback function\n     *\n     * @param {Function} callback\n     */\n    InlineMenu.prototype.onClose = function (callback) {\n        this.handleClose = callback;\n    };\n\n    // Define public API\n    exports.InlineMenu = InlineMenu;\n});\n"
  },
  {
    "path": "src/widgets/ModalBar.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * A \"modal bar\" component. This is a lightweight replacement for modal dialogs that\n * appears at the top of the editor area for operations like Find and Quick Open.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var MainViewManager  = require(\"view/MainViewManager\"),\n        EventDispatcher  = require(\"utils/EventDispatcher\"),\n        KeyEvent         = require(\"utils/KeyEvent\"),\n        AnimationUtils   = require(\"utils/AnimationUtils\"),\n        WorkspaceManager = require(\"view/WorkspaceManager\");\n\n    /**\n     * Creates a modal bar whose contents are the given template.\n     *\n     * Dispatches one event:\n     * - close - When the bar is closed, either via close() or via autoClose. After this event, the\n     *     bar may remain visible and in the DOM while its closing animation is playing. However,\n     *     by the time \"close\" is fired, the bar has been \"popped out\" of the layout and the\n     *     editor scroll position has already been restored.\n     *     Second argument is the reason for closing (one of ModalBar.CLOSE_*).\n     *     Third argument is the Promise that close() will be returning.\n     *\n     * @constructor\n     *\n     * @param {string} template The HTML contents of the modal bar.\n     * @param {boolean} autoClose If true, then close the dialog if the user hits Esc\n     *      or if the bar loses focus.\n     * @param {boolean} animate If true (the default), animate the dialog closed, otherwise\n     *      close it immediately.\n     */\n    function ModalBar(template, autoClose, animate) {\n        if (animate === undefined) {\n            animate = true;\n        }\n\n        this._handleKeydown = this._handleKeydown.bind(this);\n        this._handleFocusChange = this._handleFocusChange.bind(this);\n\n        this._$root = $(\"<div class='modal-bar'/>\")\n            .html(template)\n            .insertBefore(\"#editor-holder\");\n\n        if (animate) {\n            this._$root.addClass(\"popout offscreen\");\n            // Forcing the renderer to do a layout, which will cause it to apply the transform for the \"offscreen\"\n            // class, so it will animate when you remove the class.\n            window.getComputedStyle(this._$root.get(0)).getPropertyValue(\"top\");\n            this._$root.removeClass(\"popout offscreen\");\n        }\n\n        // If something *other* than an editor (like another modal bar) has focus, set the focus\n        // to the editor here, before opening up the new modal bar. This ensures that the old\n        // focused item has time to react and close before the new modal bar is opened.\n        // See bugs #4287 and #3424\n        MainViewManager.focusActivePane();\n\n        if (autoClose) {\n            this._autoClose = true;\n            this._$root.on(\"keydown\", this._handleKeydown);\n            window.document.body.addEventListener(\"focusin\", this._handleFocusChange, true);\n\n            // Set focus to the first input field, or the first button if there is no input field.\n            // TODO: remove this logic?\n            var $firstInput = $(\"input[type='text']\", this._$root).first();\n            if ($firstInput.length > 0) {\n                $firstInput.focus();\n            } else {\n                $(\"button\", this._$root).first().focus();\n            }\n        }\n\n        // Preserve scroll position of the current full editor across the editor refresh, adjusting for the\n        // height of the modal bar so the code doesn't appear to shift if possible.\n        MainViewManager.cacheScrollState(MainViewManager.ALL_PANES);\n        WorkspaceManager.recomputeLayout();  // changes available ht for editor area\n        MainViewManager.restoreAdjustedScrollState(MainViewManager.ALL_PANES, this.height());\n    }\n    EventDispatcher.makeEventDispatcher(ModalBar.prototype);\n\n    /**\n     * A jQuery object containing the root node of the ModalBar.\n     */\n    ModalBar.prototype._$root = null;\n\n    /**\n     * True if this ModalBar is set to autoclose.\n     */\n    ModalBar.prototype._autoClose = false;\n\n    /**\n     * Allows client code to block autoClose from closing the ModalBar: if set, this function is called whenever\n     * autoClose would normally close the ModalBar. Returning true prevents the close from occurring. Programmatically\n     * calling close() will still close the bar, however.\n     * @type {?function():boolean}\n     */\n    ModalBar.prototype.isLockedOpen = null;\n\n    ModalBar.CLOSE_ESCAPE = \"escape\";\n    ModalBar.CLOSE_BLUR = \"blur\";\n    ModalBar.CLOSE_API = \"api\";\n\n    /**\n     * @return {number} Height of the modal bar in pixels, if open.\n     */\n    ModalBar.prototype.height = function () {\n        return this._$root.outerHeight();\n    };\n\n    /**\n     * Prepares the ModalBar for closing by popping it out of the main flow and resizing/\n     * rescrolling the Editor to maintain its current apparent code position. Useful if\n     * you want to do that as a separate operation from actually animating the ModalBar\n     * closed and removing it (for example, if you need to switch full editors in between).\n     * If you don't call this explicitly, it will get called at the beginning of `close()`.\n     *\n     * @param {boolean=} restoreScrollPos If true (the default), adjust the scroll position\n     *     of the editor to account for the ModalBar disappearing. If not set, the caller\n     *     should do it immediately on return of this function (before the animation completes),\n     *     because the editor will already have been resized.\n     */\n    ModalBar.prototype.prepareClose = function (restoreScrollPos) {\n        if (restoreScrollPos === undefined) {\n            restoreScrollPos = true;\n        }\n\n        this._$root.addClass(\"popout\");\n\n        // Since the modal bar has now an absolute position relative to the editor holder,\n        // when there are html menus we need to adjust the top position\n        if (!brackets.nativeMenus) {\n            var top = $(\"#titlebar\").outerHeight();\n            this._$root.css(\"top\", top + \"px\");\n        }\n\n        // Preserve scroll position of all visible views\n        //  adjusting for the height of the modal bar so the code doesn't appear to shift if possible.\n        var barHeight = this.height();\n        if (restoreScrollPos) {\n            MainViewManager.cacheScrollState(MainViewManager.ALL_PANES);\n        }\n        WorkspaceManager.recomputeLayout();  // changes available ht for editor area\n        // restore scroll position of all views\n        if (restoreScrollPos) {\n            MainViewManager.restoreAdjustedScrollState(MainViewManager.ALL_PANES, -barHeight);\n        }\n    };\n\n    /**\n     * Closes the modal bar and returns focus to the active editor. Returns a promise that is\n     * resolved when the bar is fully closed and the container is removed from the DOM.\n     * @param {boolean=} restoreScrollPos If true (the default), adjust the scroll position\n     *     of the editor to account for the ModalBar disappearing. If not set, the caller\n     *     should do it immediately on return of this function (before the animation completes),\n     *     because the editor will already have been resized. Note that this is ignored if\n     *     `prepareClose()` was already called (you need to pass the parameter to that\n     *     function if you call it first).\n     * @param {boolean=} animate If true (the default), animate the closing of the ModalBar,\n     *     otherwise close it immediately.\n     * @param {string=} _reason For internal use only.\n     * @return {$.Promise} promise resolved when close is finished\n     */\n    ModalBar.prototype.close = function (restoreScrollPos, animate, _reason) {\n        var result = new $.Deferred(),\n            self = this;\n\n        if (restoreScrollPos === undefined) {\n            restoreScrollPos = true;\n        }\n        if (animate === undefined) {\n            animate = true;\n        }\n\n        // If someone hasn't already called `prepareClose()` to pop the ModalBar out of the flow\n        // and resize the editor, then do that here.\n        if (!this._$root.hasClass(\"popout\")) {\n            this.prepareClose(restoreScrollPos);\n        }\n\n        if (this._autoClose) {\n            window.document.body.removeEventListener(\"focusin\", this._handleFocusChange, true);\n        }\n\n        this.trigger(\"close\", _reason, result);\n\n        function doRemove() {\n            self._$root.remove();\n            result.resolve();\n        }\n\n        if (animate) {\n            AnimationUtils.animateUsingClass(this._$root.get(0), \"offscreen\")\n                .done(doRemove);\n        } else {\n            doRemove();\n        }\n\n        MainViewManager.focusActivePane();\n\n        return result.promise();\n    };\n\n    /**\n     * If autoClose is set, close the bar when Escape is pressed\n     */\n    ModalBar.prototype._handleKeydown = function (e) {\n        if (e.keyCode === KeyEvent.DOM_VK_ESCAPE) {\n            e.stopPropagation();\n            e.preventDefault();\n            this.close(undefined, undefined, ModalBar.CLOSE_ESCAPE);\n        }\n    };\n\n    /**\n     * If autoClose is set, detects when something other than the modal bar is getting focus and\n     * dismisses the modal bar. DOM nodes with \"attached-to\" jQuery metadata referencing an element\n     * within the ModalBar are allowed to take focus without closing it.\n     */\n    ModalBar.prototype._handleFocusChange = function (e) {\n        if (this.isLockedOpen && this.isLockedOpen()) {\n            return;\n        }\n\n        var effectiveElem = $(e.target).data(\"attached-to\") || e.target;\n\n        if (!$.contains(this._$root.get(0), effectiveElem)) {\n            this.close(undefined, undefined, ModalBar.CLOSE_BLUR);\n        }\n    };\n\n    /**\n     * @return {jQueryObject} A jQuery object representing the root of the ModalBar.\n     */\n    ModalBar.prototype.getRoot = function () {\n        return this._$root;\n    };\n\n    exports.ModalBar = ModalBar;\n});\n"
  },
  {
    "path": "src/widgets/PopUpManager.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Utilities for managing pop-ups.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var AppInit         = require(\"utils/AppInit\"),\n        EventDispatcher = require(\"utils/EventDispatcher\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        KeyEvent        = require(\"utils/KeyEvent\");\n\n    var _popUps = [];\n\n    /**\n     * Add Esc key handling for a popup DOM element.\n     *\n     * @param {!jQuery} $popUp jQuery object for the DOM element pop-up\n     * @param {function} removeHandler Pop-up specific remove (e.g. display:none or DOM removal)\n     * @param {?Boolean} autoRemove - Specify true to indicate the PopUpManager should\n     *      remove the popup from the _popUps array when the popup is closed. Specify false\n     *      when the popup is always persistant in the _popUps array.\n     *\n     */\n    function addPopUp($popUp, removeHandler, autoRemove) {\n        autoRemove = autoRemove || false;\n\n        _popUps.push($popUp[0]);\n        $popUp.data(\"PopUpManager-autoRemove\", autoRemove);\n        $popUp.data(\"PopUpManager-removeHandler\", removeHandler);\n    }\n\n    /**\n     * Remove Esc key handling for a pop-up. Removes the pop-up from the DOM\n     * if the pop-up is currently visible and was not originally attached.\n     *\n     * @param {!jQuery} $popUp\n     */\n    function removePopUp($popUp) {\n        // check visible first to help protect against recursive calls\n        // via removeHandler\n        if ($popUp.find(\":visible\").length > 0) {\n            var removeHandler = $popUp.data(\"PopUpManager-removeHandler\");\n            if (removeHandler) {\n                removeHandler();\n            }\n        }\n\n        // check index after removeHandler is done processing to protect\n        // against recursive calls\n        var index = _popUps.indexOf($popUp[0]);\n        if (index >= 0) {\n            var autoRemove = $popUp.data(\"PopUpManager-autoRemove\");\n            if (autoRemove) {\n                $popUp.remove();\n                _popUps.splice(index, 1);\n            }\n        }\n    }\n\n    /**\n     * Remove Esc key handling for a pop-up. Removes the pop-up from the DOM\n     * if the pop-up is currently visible and was not originally attached.\n     *\n     * @param {KeyboardEvent=} keyEvent (optional)\n     */\n    function removeCurrentPopUp(keyEvent) {\n        // allow the popUp to prevent closing\n        var $popUp,\n            i,\n            event = new $.Event(\"popUpClose\");\n\n        for (i = _popUps.length - 1; i >= 0; i--) {\n            $popUp = $(_popUps[i]);\n\n            if ($popUp.find(\":visible\").length > 0) {\n                $popUp.trigger(event);\n\n                if (!event.isDefaultPrevented()) {\n                    // Stop the DOM event from propagating\n                    if (keyEvent) {\n                        keyEvent.stopImmediatePropagation();\n                    }\n\n                    removePopUp($popUp);\n\n                    // TODO: right now Menus and Context Menus do not take focus away from\n                    // the editor. We need to have a focus manager to correctly manage focus\n                    // between editors and other UI elements.\n                    // For now we don't set focus here and assume individual popups\n                    // adjust focus if necessary\n                    // See story in Trello card #404\n                    //EditorManager.focusEditor();\n                }\n\n                break;\n            }\n        }\n    }\n\n    function _keydownCaptureListener(keyEvent) {\n         // Escape key or Alt key (Windows-only)\n        if (keyEvent.keyCode !== KeyEvent.DOM_VK_ESCAPE &&\n                !(keyEvent.keyCode === KeyEvent.DOM_VK_ALT && brackets.platform === \"win\")) {\n            return;\n        }\n\n        // Don't dismiss the popup if both Ctrl and Alt keys are pressed.\n        if (keyEvent.keyCode === KeyEvent.DOM_VK_ALT && keyEvent.ctrlKey) {\n            return;\n        }\n\n        removeCurrentPopUp(keyEvent);\n    }\n\n    /**\n     * A menu is being popped up, so remove any menu that is currently popped up\n     */\n    function _beforeMenuPopup() {\n        removeCurrentPopUp();\n    }\n\n    /**\n     * Context menus are also created in AppInit.htmlReady(), so they may not\n     * yet have been created when we get our AppInit.htmlReady() callback, so\n     * we provide this method to tell us when to start listening for their events\n     *\n     * @param {ContextMenu} contextMenu\n     */\n    function listenToContextMenu(contextMenu) {\n        contextMenu.on(\"beforeContextMenuOpen\", _beforeMenuPopup);\n    }\n\n    AppInit.htmlReady(function () {\n        // Register for events\n        window.document.body.addEventListener(\"keydown\", _keydownCaptureListener, true);\n        exports.on(\"beforeMenuPopup\", _beforeMenuPopup);\n\n        // Close all popups when a command is executed\n        CommandManager.on(\"beforeExecuteCommand\", function (event, commandId) {\n            removeCurrentPopUp();\n        });\n    });\n\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    exports.addPopUp            = addPopUp;\n    exports.removePopUp         = removePopUp;\n    exports.listenToContextMenu = listenToContextMenu;\n});\n"
  },
  {
    "path": "src/widgets/StatusBar.html",
    "content": "<div id=\"status-bar\" class=\"statusbar no-focus\">\n    <div id=\"status-info\" class=\"info\" >\n        <div id=\"status-cursor\"></div>\n        <div id=\"status-file\"></div>\n    </div>\n    <div id=\"status-indicators\" class=\"indicators\">\n        <div id=\"status-indent\">\n            <div id=\"indent-type\"></div>\n            <div id=\"indent-width-label\"></div>\n            <input id=\"indent-width-input\" type=\"number\" min=\"1\" max=\"10\" maxlength=\"2\" size=\"2\" class=\"hidden\">\n        </div>\n        <div id=\"status-language\"></div>\n        <div id=\"status-encoding\"></div>\n        <div id=\"status-overwrite\">{{STATUSBAR_INSERT}}</div>\n        <div class=\"spinner\"></div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/widgets/StatusBar.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * A status bar with support for file information and busy and status indicators. This is a semi-generic\n * container; for the code that decides what content appears in the status bar, see client modules like\n * EditorStatusBar. (Although in practice StatusBar's HTML structure and initialization\n * assume it's only used for this one purpose, and all the APIs are on a singleton).\n */\ndefine(function (require, exports, module) {\n    'use strict';\n\n    var AppInit          = require(\"utils/AppInit\"),\n        StatusBarHTML    = require(\"text!widgets/StatusBar.html\"),\n        Strings          = require(\"strings\"),\n        WorkspaceManager = require(\"view/WorkspaceManager\"),\n        Mustache         = require(\"thirdparty/mustache/mustache\");\n\n    var _init = false;\n\n    // Indicates if the busy cursor is active to avoid unnecesary operations\n    var _busyCursor = false;\n\n    // A simple regexp to sanitize indicator ids\n    var _indicatorIDRegexp = new RegExp(\"[^a-zA-Z 0-9]+\", \"g\");\n\n    // These vars are initialized by the AppInit.htmlReady handler\n    // below since they refer to DOM elements\n    var $statusInfo,\n        $statusBar,\n        $indicators,\n        $busyIndicator;\n\n    /**\n     * Shows the 'busy' indicator\n     * @param {boolean} updateCursor Sets the cursor to \"wait\"\n     */\n    function showBusyIndicator(updateCursor) {\n        if (!_init) {\n            console.error(\"StatusBar API invoked before status bar created\");\n            return;\n        }\n\n        if (updateCursor) {\n            _busyCursor = true;\n            $(\"*\").addClass(\"busyCursor\");\n        }\n\n        $busyIndicator.addClass(\"spin\");\n    }\n\n    /**\n     * Hides the 'busy' indicator\n     */\n    function hideBusyIndicator() {\n        if (!_init) {\n            console.error(\"StatusBar API invoked before status bar created\");\n            return;\n        }\n\n        // Check if we are using the busyCursor class to avoid\n        // unnecesary calls to $('*').removeClass()\n        if (_busyCursor) {\n            _busyCursor = false;\n            $(\"*\").removeClass(\"busyCursor\");\n        }\n\n        $busyIndicator.removeClass(\"spin\");\n    }\n\n    /**\n     * Registers a new status indicator\n     * @param {string} id Registration id of the indicator to be updated.\n     * @param {(DOMNode|jQueryObject)=} indicator Optional DOMNode for the indicator\n     * @param {boolean=} visible Shows or hides the indicator over the statusbar.\n     * @param {string=} style Sets the attribute \"class\" of the indicator.\n     * @param {string=} tooltip Sets the attribute \"title\" of the indicator.\n     * @param {string=} insertBefore An id of an existing status bar indicator.\n     *          The new indicator will be inserted before (i.e. to the left of)\n     *          the indicator specified by this parameter.\n     */\n    function addIndicator(id, indicator, visible, style, tooltip, insertBefore) {\n        if (!_init) {\n            console.error(\"StatusBar API invoked before status bar created\");\n            return;\n        }\n\n        indicator = indicator || window.document.createElement(\"div\");\n        tooltip = tooltip || \"\";\n        style = style || \"\";\n        id = id.replace(_indicatorIDRegexp, \"-\") || \"\";\n\n        var $indicator = $(indicator);\n\n        $indicator.attr(\"id\", id);\n        $indicator.attr(\"title\", tooltip);\n        $indicator.addClass(\"indicator\");\n        $indicator.addClass(style);\n\n        if (!visible) {\n            $indicator.hide();\n        }\n\n        // This code looks backwards because the DOM model is ordered\n        // top-to-bottom but the UI view is ordered right-to-left. The concept\n        // of \"before\" in the model is \"after\" in the view, and vice versa.\n        if (insertBefore && $(\"#\" + insertBefore).length > 0) {\n            $indicator.insertAfter(\"#\" + insertBefore);\n        } else {\n            // No positioning is provided, put on left end of indicators, but\n            // to right of \"busy\" indicator (which is usually hidden).\n            var $busyIndicator = $(\"#status-bar .spinner\");\n            $indicator.insertBefore($busyIndicator);\n        }\n    }\n\n    /**\n     * Updates a status indicator\n     * @param {string} id Registration id of the indicator to be updated.\n     * @param {boolean} visible Shows or hides the indicator over the statusbar.\n     * @param {string=} style Sets the attribute \"class\" of the indicator.\n     * @param {string=} tooltip Sets the attribute \"title\" of the indicator.\n     */\n    function updateIndicator(id, visible, style, tooltip) {\n        if (!_init && !!brackets.test) {\n            console.error(\"StatusBar API invoked before status bar created\");\n            return;\n        }\n\n        var $indicator = $(\"#\" + id.replace(_indicatorIDRegexp, \"-\"));\n\n        if ($indicator) {\n\n            if (visible) {\n                $indicator.show();\n            } else {\n                $indicator.hide();\n            }\n\n            if (style) {\n                $indicator.removeClass();\n                $indicator.addClass(style);\n            } else {\n                $indicator.removeClass();\n                $indicator.addClass(\"indicator\");\n            }\n\n            if (tooltip) {\n                $indicator.attr(\"title\", tooltip);\n            }\n        }\n    }\n\n    /**\n     * Hide the statusbar Information Panel\n     */\n    function hideInformation() {\n        $statusInfo.css(\"display\", \"none\");\n    }\n\n    /**\n     * Show the statusbar Information Panel\n     */\n    function showInformation() {\n        $statusInfo.css(\"display\", \"\");\n    }\n\n    /**\n     * Hide the statusbar Indicators\n     */\n    function hideIndicators() {\n        $indicators.css(\"display\", \"none\");\n    }\n\n    /**\n     * Show the statusbar Indicators\n     */\n    function showIndicators() {\n        $indicators.css(\"display\", \"\");\n    }\n\n\n    /**\n     * Hides all panels but not the status bar\n     */\n    function hideAllPanes() {\n        hideInformation();\n        hideIndicators();\n    }\n\n    /**\n     * Shows all panels (will not show a hidden statusbar)\n     */\n    function showAllPanes() {\n        showInformation();\n        showIndicators();\n    }\n\n\n    /**\n     * Hide the statusbar\n     */\n    function hide() {\n        if (!_init) {\n            console.error(\"StatusBar API invoked before status bar created\");\n            return;\n        }\n\n        if ($statusBar.is(\":visible\")) {\n            $statusBar.hide();\n            WorkspaceManager.recomputeLayout();\n        }\n    }\n\n    /**\n     * Show the statusbar\n     */\n    function show() {\n        if (!_init) {\n            console.error(\"StatusBar API invoked before status bar created\");\n            return;\n        }\n\n        if (!$statusBar.is(\":visible\")) {\n            $statusBar.show();\n            WorkspaceManager.recomputeLayout();\n        }\n    }\n\n    AppInit.htmlReady(function () {\n        var $parent = $(\".main-view .content\");\n        $parent.append(Mustache.render(StatusBarHTML, Strings));\n\n        // Initialize items dependent on HTML DOM\n        $statusBar          = $(\"#status-bar\");\n        $indicators         = $(\"#status-indicators\");\n        $busyIndicator      = $(\"#status-bar .spinner\");\n        $statusInfo         = $(\"#status-info\");\n\n        _init = true;\n\n        // hide on init\n        hide();\n    });\n\n    exports.hideInformation   = hideInformation;\n    exports.showInformation   = showInformation;\n    exports.showBusyIndicator = showBusyIndicator;\n    exports.hideBusyIndicator = hideBusyIndicator;\n    exports.hideIndicators    = hideIndicators;\n    exports.showIndicators    = showIndicators;\n    exports.hideAllPanes      = hideAllPanes;\n    exports.showAllPanes      = showAllPanes;\n    exports.addIndicator      = addIndicator;\n    exports.updateIndicator   = updateIndicator;\n    exports.hide              = hide;\n    exports.show              = show;\n});\n"
  },
  {
    "path": "src/widgets/bootstrap-alerts.js",
    "content": "/* ==========================================================\n * bootstrap-alert.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#alerts\n * ==========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* ALERT CLASS DEFINITION\n  * ====================== */\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n    , Alert = function (el) {\n        $(el).on('click', dismiss, this.close)\n      }\n\n  Alert.prototype.close = function (e) {\n    var $this = $(this)\n      , selector = $this.attr('data-target')\n      , $parent\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    $parent = $(selector)\n\n    e && e.preventDefault()\n\n    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())\n\n    $parent.trigger(e = $.Event('close'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent\n        .trigger('closed')\n        .remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent.on($.support.transition.end, removeElement) :\n      removeElement()\n  }\n\n\n /* ALERT PLUGIN DEFINITION\n  * ======================= */\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('alert')\n      if (!data) $this.data('alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n /* ALERT NO CONFLICT\n  * ================= */\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n /* ALERT DATA-API\n  * ============== */\n\n  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);"
  },
  {
    "path": "src/widgets/bootstrap-button.js",
    "content": "/* ============================================================\n * bootstrap-button.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#buttons\n * ============================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ============================================================ */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* BUTTON PUBLIC CLASS DEFINITION\n  * ============================== */\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options = $.extend({}, $.fn.button.defaults, options)\n  }\n\n  Button.prototype.setState = function (state) {\n    var d = 'disabled'\n      , $el = this.$element\n      , data = $el.data()\n      , val = $el.is('input') ? 'val' : 'html'\n\n    state = state + 'Text'\n    data.resetText || $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d)\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons-radio\"]')\n\n    $parent && $parent\n      .find('.active')\n      .removeClass('active')\n\n    this.$element.toggleClass('active')\n  }\n\n\n /* BUTTON PLUGIN DEFINITION\n  * ======================== */\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('button')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('button', (data = new Button(this, options)))\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.defaults = {\n    loadingText: 'loading...'\n  }\n\n  $.fn.button.Constructor = Button\n\n\n /* BUTTON NO CONFLICT\n  * ================== */\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n /* BUTTON DATA-API\n  * =============== */\n\n  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n  })\n\n}(window.jQuery);"
  },
  {
    "path": "src/widgets/bootstrap-dropdown.js",
    "content": "/* ============================================================\n * bootstrap-dropdown.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#dropdowns\n * ============================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ============================================================ */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* DROPDOWN CLASS DEFINITION\n  * ========================= */\n\n  var toggle = '[data-toggle=dropdown]'\n    , Dropdown = function (element) {\n        var $el = $(element).on('click.dropdown.data-api', this.toggle)\n        $('html').on('click.dropdown.data-api', function () {\n          $el.parent().removeClass('open')\n        })\n      }\n\n  Dropdown.prototype = {\n\n    constructor: Dropdown\n\n  , toggle: function (e) {\n      var $this = $(this)\n        , $parent\n        , isActive\n\n      if ($this.is('.disabled, :disabled')) return\n\n      $parent = getParent($this)\n\n      isActive = $parent.hasClass('open')\n\n      clearMenus()\n\n      if (!isActive) {\n        $parent.toggleClass('open')\n      }\n\n      $this.focus()\n\n      return false\n    }\n\n  , keydown: function (e) {\n      var $this\n        , $items\n        , $active\n        , $parent\n        , isActive\n        , index\n\n      if (!/(38|40|27)/.test(e.keyCode)) return\n\n      $this = $(this)\n\n      e.preventDefault()\n      e.stopPropagation()\n\n      if ($this.is('.disabled, :disabled')) return\n\n      $parent = getParent($this)\n\n      isActive = $parent.hasClass('open')\n\n      if (!isActive || (isActive && e.keyCode == 27)) {\n        if (e.which == 27) $parent.find(toggle).focus()\n        return $this.click()\n      }\n\n      $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n      if (!$items.length) return\n\n      index = $items.index($items.filter(':focus'))\n\n      if (e.keyCode == 38 && index > 0) index--                                        // up\n      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n      if (!~index) index = 0\n\n      $items\n        .eq(index)\n        .focus()\n    }\n\n  }\n\n  function clearMenus() {\n    $(toggle).each(function () {\n      getParent($(this)).removeClass('open')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n      , $parent\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    $parent = selector && $(selector)\n\n    if (!$parent || !$parent.length) $parent = $this.parent()\n\n    return $parent\n  }\n\n\n  /* DROPDOWN PLUGIN DEFINITION\n   * ========================== */\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('dropdown')\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n /* DROPDOWN NO CONFLICT\n  * ==================== */\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  /* APPLY TO STANDARD DROPDOWN ELEMENTS\n   * =================================== */\n\n  $(document)\n    .on('click.dropdown.data-api', clearMenus)\n    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.dropdown-menu', function (e) { e.stopPropagation() })\n    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n"
  },
  {
    "path": "src/widgets/bootstrap-modal.js",
    "content": "/* =========================================================\n * bootstrap-modal.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#modals\n * =========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================= */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* MODAL CLASS DEFINITION\n  * ====================== */\n\n  var Modal = function (element, options) {\n    this.options = options\n    this.$element = $(element)\n      .delegate('[data-dismiss=\"modal\"]', 'click.dismiss.modal', $.proxy(this.hide, this))\n    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)\n  }\n\n  Modal.prototype = {\n\n      constructor: Modal\n\n    , toggle: function () {\n        return this[!this.isShown ? 'show' : 'hide']()\n      }\n\n    , show: function () {\n        var that = this\n          , e = $.Event('show')\n\n        this.$element.trigger(e)\n\n        if (this.isShown || e.isDefaultPrevented()) return\n\n        this.isShown = true\n\n        this.escape()\n\n        this.backdrop(function () {\n          var transition = $.support.transition && that.$element.hasClass('fade')\n\n          if (!that.$element.parent().length) {\n            that.$element.appendTo(this.options.selector) //don't move modals dom position\n          }\n\n          that.$element.show()\n\n          if (transition) {\n            that.$element[0].offsetWidth // force reflow\n          }\n\n          that.$element\n            .addClass('in')\n            .attr('aria-hidden', false)\n\n          that.enforceFocus()\n\n          transition ?\n            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :\n            that.$element.focus().trigger('shown')\n\n        })\n      }\n\n    , hide: function (e) {\n        e && e.preventDefault()\n\n        var that = this\n\n        e = $.Event('hide')\n\n        this.$element.trigger(e)\n\n        if (!this.isShown || e.isDefaultPrevented()) return\n\n        this.isShown = false\n\n        this.escape()\n\n        $(document).off('focusin.modal')\n\n        this.$element\n          .removeClass('in')\n          .attr('aria-hidden', true)\n\n        $.support.transition && this.$element.hasClass('fade') ?\n          this.hideWithTransition() :\n          this.hideModal()\n      }\n\n    , enforceFocus: function () {\n        var that = this\n        $(document).on('focusin.modal', function (e) {\n          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {\n            that.$element.focus()\n          }\n        })\n      }\n\n    , escape: function () {\n        var that = this\n        if (this.isShown && this.options.keyboard) {\n          this.$element.on('keyup.dismiss.modal', function ( e ) {\n            e.which == 27 && that.hide()\n          })\n        } else if (!this.isShown) {\n          this.$element.off('keyup.dismiss.modal')\n        }\n      }\n\n    , hideWithTransition: function () {\n        var that = this\n          , timeout = setTimeout(function () {\n              that.$element.off($.support.transition.end)\n              that.hideModal()\n            }, 500)\n\n        this.$element.one($.support.transition.end, function () {\n          clearTimeout(timeout)\n          that.hideModal()\n        })\n      }\n\n    , hideModal: function () {\n        var that = this\n        this.$element.hide()\n        this.backdrop(function () {\n          that.removeBackdrop()\n          that.$element.trigger('hidden')\n        })\n      }\n\n    , removeBackdrop: function () {\n        this.$backdrop && this.$backdrop.remove()\n        this.$backdrop = null\n      }\n\n    , backdrop: function (callback) {\n        var that = this\n          , animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n        if (this.isShown && this.options.backdrop) {\n          var doAnimate = $.support.transition && animate\n\n          this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n            .appendTo(this.options.selector)\n\n          this.$backdrop.click(\n            this.options.backdrop == 'static' ?\n              $.proxy(this.$element[0].focus, this.$element[0])\n            : $.proxy(this.hide, this)\n          )\n\n          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n          this.$backdrop.addClass('in')\n\n          if (!callback) return\n\n          doAnimate ?\n            this.$backdrop.one($.support.transition.end, callback) :\n            callback()\n\n        } else if (!this.isShown && this.$backdrop) {\n          this.$backdrop.removeClass('in')\n\n          $.support.transition && this.$element.hasClass('fade')?\n            this.$backdrop.one($.support.transition.end, callback) :\n            callback()\n\n        } else if (callback) {\n          callback()\n        }\n      }\n  }\n\n\n /* MODAL PLUGIN DEFINITION\n  * ======================= */\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('modal')\n        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)\n      if (!data) $this.data('modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option]()\n      else if (options.show) data.show()\n    })\n  }\n\n  $.fn.modal.defaults = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n    , selector: \"body\"\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n /* MODAL NO CONFLICT\n  * ================= */\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n /* MODAL DATA-API\n  * ============== */\n\n  $(document).on('click.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this = $(this)\n      , href = $this.attr('href')\n      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option)\n      .one('hide', function () {\n        $this.focus()\n      })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "src/widgets/bootstrap-popover.js",
    "content": "/* ===========================================================\n * bootstrap-popover.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#popovers\n * ===========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * =========================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* POPOVER PUBLIC CLASS DEFINITION\n  * =============================== */\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n\n  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js\n     ========================================== */\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {\n\n    constructor: Popover\n\n  , setContent: function () {\n      var $tip = this.tip()\n        , title = this.getTitle()\n        , content = this.getContent()\n\n      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n      $tip.removeClass('fade top bottom left right in')\n    }\n\n  , hasContent: function () {\n      return this.getTitle() || this.getContent()\n    }\n\n  , getContent: function () {\n      var content\n        , $e = this.$element\n        , o = this.options\n\n      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)\n        || $e.attr('data-content')\n\n      return content\n    }\n\n  , tip: function () {\n      if (!this.$tip) {\n        this.$tip = $(this.options.template)\n      }\n      return this.$tip\n    }\n\n  , destroy: function () {\n      this.hide().$element.off('.' + this.type).removeData(this.type)\n    }\n\n  })\n\n\n /* POPOVER PLUGIN DEFINITION\n  * ======================= */\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('popover')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n /* POPOVER NO CONFLICT\n  * =================== */\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n"
  },
  {
    "path": "src/widgets/bootstrap-scrollspy.js",
    "content": "/* =============================================================\n * bootstrap-scrollspy.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#scrollspy\n * =============================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ============================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* SCROLLSPY CLASS DEFINITION\n  * ========================== */\n\n  function ScrollSpy(element, options) {\n    var process = $.proxy(this.process, this)\n      , $element = $(element).is('body') ? $(window) : $(element)\n      , href\n    this.options = $.extend({}, $.fn.scrollspy.defaults, options)\n    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)\n    this.selector = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.$body = $('body')\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.prototype = {\n\n      constructor: ScrollSpy\n\n    , refresh: function () {\n        var self = this\n\n        this.offsets = $([])\n        this.targets = $([])\n\n        this.$body\n          .find(this.selector)\n          .map(function () {\n            var $el = $(this)\n              , href = $el.data('target') || $el.attr('href')\n              , $href = /^#\\w/.test(href) && $(href)\n            return ( $href\n              && $href.length\n              && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null\n          })\n          .sort(function (a, b) { return a[0] - b[0] })\n          .each(function () {\n            self.offsets.push(this[0])\n            self.targets.push(this[1])\n          })\n      }\n\n    , process: function () {\n        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset\n          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n          , maxScroll = scrollHeight - this.$scrollElement.height()\n          , offsets = this.offsets\n          , targets = this.targets\n          , activeTarget = this.activeTarget\n          , i\n\n        if (scrollTop >= maxScroll) {\n          return activeTarget != (i = targets.last()[0])\n            && this.activate ( i )\n        }\n\n        for (i = offsets.length; i--;) {\n          activeTarget != targets[i]\n            && scrollTop >= offsets[i]\n            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n            && this.activate( targets[i] )\n        }\n      }\n\n    , activate: function (target) {\n        var active\n          , selector\n\n        this.activeTarget = target\n\n        $(this.selector)\n          .parent('.active')\n          .removeClass('active')\n\n        selector = this.selector\n          + '[data-target=\"' + target + '\"],'\n          + this.selector + '[href=\"' + target + '\"]'\n\n        active = $(selector)\n          .parent('li')\n          .addClass('active')\n\n        if (active.parent('.dropdown-menu').length)  {\n          active = active.closest('li.dropdown').addClass('active')\n        }\n\n        active.trigger('activate')\n      }\n\n  }\n\n\n /* SCROLLSPY PLUGIN DEFINITION\n  * =========================== */\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('scrollspy')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n  $.fn.scrollspy.defaults = {\n    offset: 10\n  }\n\n\n /* SCROLLSPY NO CONFLICT\n  * ===================== */\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n /* SCROLLSPY DATA-API\n  * ================== */\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);"
  },
  {
    "path": "src/widgets/bootstrap-tab.js",
    "content": "/* ========================================================\n * bootstrap-tab.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#tabs\n * ========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TAB CLASS DEFINITION\n  * ==================== */\n\n  var Tab = function (element) {\n    this.element = $(element)\n  }\n\n  Tab.prototype = {\n\n    constructor: Tab\n\n  , show: function () {\n      var $this = this.element\n        , $ul = $this.closest('ul:not(.dropdown-menu)')\n        , selector = $this.attr('data-target')\n        , previous\n        , $target\n        , e\n\n      if (!selector) {\n        selector = $this.attr('href')\n        selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n      }\n\n      if ( $this.parent('li').hasClass('active') ) return\n\n      previous = $ul.find('.active:last a')[0]\n\n      e = $.Event('show', {\n        relatedTarget: previous\n      })\n\n      $this.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      $target = $(selector)\n\n      this.activate($this.parent('li'), $ul)\n      this.activate($target, $target.parent(), function () {\n        $this.trigger({\n          type: 'shown'\n        , relatedTarget: previous\n        })\n      })\n    }\n\n  , activate: function ( element, container, callback) {\n      var $active = container.find('> .active')\n        , transition = callback\n            && $.support.transition\n            && $active.hasClass('fade')\n\n      function next() {\n        $active\n          .removeClass('active')\n          .find('> .dropdown-menu > .active')\n          .removeClass('active')\n\n        element.addClass('active')\n\n        if (transition) {\n          element[0].offsetWidth // reflow for transition\n          element.addClass('in')\n        } else {\n          element.removeClass('fade')\n        }\n\n        if ( element.parent('.dropdown-menu') ) {\n          element.closest('li.dropdown').addClass('active')\n        }\n\n        callback && callback()\n      }\n\n      transition ?\n        $active.one($.support.transition.end, next) :\n        next()\n\n      $active.removeClass('in')\n    }\n  }\n\n\n /* TAB PLUGIN DEFINITION\n  * ===================== */\n\n  var old = $.fn.tab\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('tab')\n      if (!data) $this.data('tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tab.Constructor = Tab\n\n\n /* TAB NO CONFLICT\n  * =============== */\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n /* TAB DATA-API\n  * ============ */\n\n  $(document).on('click.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n    e.preventDefault()\n    $(this).tab('show')\n  })\n\n}(window.jQuery);"
  },
  {
    "path": "src/widgets/bootstrap-tooltip.js",
    "content": "/* ===========================================================\n * bootstrap-tooltip.js v2.3.1\n * http://twitter.github.com/bootstrap/javascript.html#tooltips\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ===========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TOOLTIP PUBLIC CLASS DEFINITION\n  * =============================== */\n\n  var Tooltip = function (element, options) {\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.prototype = {\n\n    constructor: Tooltip\n\n  , init: function (type, element, options) {\n      var eventIn\n        , eventOut\n        , triggers\n        , trigger\n        , i\n\n      this.type = type\n      this.$element = $(element)\n      this.options = this.getOptions(options)\n      this.enabled = true\n\n      triggers = this.options.trigger.split(' ')\n\n      for (i = triggers.length; i--;) {\n        trigger = triggers[i]\n        if (trigger == 'click') {\n          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n        } else if (trigger != 'manual') {\n          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'\n          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n        }\n      }\n\n      this.options.selector ?\n        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n        this.fixTitle()\n    }\n\n  , getOptions: function (options) {\n      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)\n\n      if (options.delay && typeof options.delay == 'number') {\n        options.delay = {\n          show: options.delay\n        , hide: options.delay\n        }\n      }\n\n      return options\n    }\n\n  , enter: function (e) {\n      var defaults = $.fn[this.type].defaults\n        , options = {}\n        , self\n\n      this._options && $.each(this._options, function (key, value) {\n        if (defaults[key] != value) options[key] = value\n      }, this)\n\n      self = $(e.currentTarget)[this.type](options).data(this.type)\n\n      if (!self.options.delay || !self.options.delay.show) return self.show()\n\n      clearTimeout(this.timeout)\n      self.hoverState = 'in'\n      this.timeout = setTimeout(function() {\n        if (self.hoverState == 'in') self.show()\n      }, self.options.delay.show)\n    }\n\n  , leave: function (e) {\n      var self = $(e.currentTarget)[this.type](this._options).data(this.type)\n\n      if (this.timeout) clearTimeout(this.timeout)\n      if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n      self.hoverState = 'out'\n      this.timeout = setTimeout(function() {\n        if (self.hoverState == 'out') self.hide()\n      }, self.options.delay.hide)\n    }\n\n  , show: function () {\n      var $tip\n        , pos\n        , actualWidth\n        , placement\n        , tp\n        , e = $.Event('show')\n\n      if (this.hasContent() && this.enabled) {\n        this.$element.trigger(e)\n        if (e.isDefaultPrevented()) return\n        $tip = this.tip()\n        this.setContent()\n\n        if (this.options.animation) {\n          $tip.addClass('fade')\n        }\n\n        placement = typeof this.options.placement == 'function' ?\n          this.options.placement.call(this, $tip[0], this.$element[0]) :\n          this.options.placement\n\n        $tip\n          .detach()\n          .css({ top: 0, left: 0, display: 'block' })\n\n        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n        pos = this.getPosition()\n\n        actualWidth = $tip[0].offsetWidth\n\n        switch (placement) {\n          case 'bottom':\n            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}\n            break\n          case 'top':\n            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}\n            break\n          case 'left':\n            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}\n            break\n          case 'right':\n            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}\n            break\n        }\n\n        this.applyPlacement(tp, placement)\n        this.$element.trigger('shown')\n      }\n    }\n\n  , applyPlacement: function(offset, placement){\n      var $tip = this.tip()\n        , width = $tip[0].offsetWidth\n        , height = $tip[0].offsetHeight\n        , actualWidth\n        , actualHeight\n        , delta\n        , replace\n\n      $tip\n        .offset(offset)\n        .addClass(placement)\n        .addClass('in')\n\n      actualWidth = $tip[0].offsetWidth\n      actualHeight = $tip[0].offsetHeight\n\n      if (placement == 'top' && actualHeight != height) {\n        offset.top = offset.top + height - actualHeight\n        replace = true\n      }\n\n      if (placement == 'bottom' || placement == 'top') {\n        delta = 0\n\n        if (offset.left < 0){\n          delta = offset.left * -2\n          offset.left = 0\n          $tip.offset(offset)\n          actualWidth = $tip[0].offsetWidth\n          actualHeight = $tip[0].offsetHeight\n        }\n\n        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n      } else {\n        this.replaceArrow(actualHeight - height, actualHeight, 'top')\n      }\n\n      if (replace) $tip.offset(offset)\n    }\n\n  , replaceArrow: function(delta, dimension, position){\n      this\n        .arrow()\n        .css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n    }\n\n  , setContent: function () {\n      var $tip = this.tip()\n        , title = this.getTitle()\n\n      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n      $tip.removeClass('fade in top bottom left right')\n    }\n\n  , hide: function () {\n      var that = this\n        , $tip = this.tip()\n        , e = $.Event('hide')\n\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n\n      $tip.removeClass('in')\n\n      function removeWithAnimation() {\n        var timeout = setTimeout(function () {\n          $tip.off($.support.transition.end).detach()\n        }, 500)\n\n        $tip.one($.support.transition.end, function () {\n          clearTimeout(timeout)\n          $tip.detach()\n        })\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        removeWithAnimation() :\n        $tip.detach()\n\n      this.$element.trigger('hidden')\n\n      return this\n    }\n\n  , fixTitle: function () {\n      var $e = this.$element\n      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n      }\n    }\n\n  , hasContent: function () {\n      return this.getTitle()\n    }\n\n  , getPosition: function () {\n      var el = this.$element[0]\n      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n        width: el.offsetWidth\n      , height: el.offsetHeight\n      }, this.$element.offset())\n    }\n\n  , getTitle: function () {\n      var title\n        , $e = this.$element\n        , o = this.options\n\n      title = $e.attr('data-original-title')\n        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n      return title\n    }\n\n  , tip: function () {\n      return this.$tip = this.$tip || $(this.options.template)\n    }\n\n  , arrow: function(){\n      return this.$arrow = this.$arrow || this.tip().find(\".tooltip-arrow\")\n    }\n\n  , validate: function () {\n      if (!this.$element[0].parentNode) {\n        this.hide()\n        this.$element = null\n        this.options = null\n      }\n    }\n\n  , enable: function () {\n      this.enabled = true\n    }\n\n  , disable: function () {\n      this.enabled = false\n    }\n\n  , toggleEnabled: function () {\n      this.enabled = !this.enabled\n    }\n\n  , toggle: function (e) {\n      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this\n      self.tip().hasClass('in') ? self.hide() : self.show()\n    }\n\n  , destroy: function () {\n      this.hide().$element.off('.' + this.type).removeData(this.type)\n    }\n\n  }\n\n\n /* TOOLTIP PLUGIN DEFINITION\n  * ========================= */\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('tooltip')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n  $.fn.tooltip.defaults = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n\n /* TOOLTIP NO CONFLICT\n  * =================== */\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(window.jQuery);\n"
  },
  {
    "path": "src/widgets/bootstrap-twipsy-mod.js",
    "content": "/* ==========================================================\n * bootstrap-twipsy.js v1.4.0\n * http://twitter.github.com/bootstrap/javascript.html#twipsy\n * Adapted from the original jQuery.tipsy by Jason Frame\n * Adjusted for Brackets\n * ==========================================================\n * Copyright 2011 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================== */\n\n\n!function( $ ) {\n\n  \"use strict\"\n\n  /***** [changed for Brackets] *****/\n  // Undefined until the focus state changed once\n  var _windowHasFocus;\n\n  $(window)\n    .focus(function _onWindowGainedFocus() {\n      _windowHasFocus = true;\n    })\n    .blur(function _onWindowLostFocus() {\n      _windowHasFocus = false;\n    });\n  /***** [/changed for Brackets] *****/\n\n /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)\n  * ======================================================= */\n\n  var transitionEnd\n\n  $(document).ready(function () {\n\n    $.support.transition = (function () {\n\n      var transitionEnd = (function () {\n\n        var el = document.createElement('bootstrap')\n          , transEndEventNames = {\n               'WebkitTransition' : 'webkitTransitionEnd'\n            ,  'MozTransition'    : 'transitionend'\n            ,  'OTransition'      : 'oTransitionEnd'\n            ,  'msTransition'     : 'MSTransitionEnd'\n            ,  'transition'       : 'transitionend'\n            }\n          , name\n\n        for (name in transEndEventNames){\n          if (el.style[name] !== undefined) {\n            return transEndEventNames[name]\n          }\n        }\n\n      }())\n\n      return transitionEnd && {\n        end: transitionEnd\n      }\n\n    })()\n\n    // set CSS transition event type\n    if ( $.support.transition ) {\n      transitionEnd = $.support.transition.end\n    }\n\n  })\n\n\n /* TWIPSY PUBLIC CLASS DEFINITION\n  * ============================== */\n\n  var Twipsy = function ( element, options ) {\n    this.$element = $(element)\n    this.options = options\n    this.enabled = true\n    /***** [changed for Brackets] *****/\n    this.autoHideTimeout = null;\n    /***** [/changed for Brackets] *****/\n    this.fixTitle()\n  }\n\n  Twipsy.prototype = {\n\n    show: function() {\n      /***** [changed for Brackets: moved some variables to updatePosition()] *****/\n      var $tip\n        , that = this;\n      /***** [/changed for Brackets] *****/\n\n      if (this.hasContent() && this.enabled) {\n        $tip = this.tip()\n        this.setContent()\n\n        if (this.options.animate) {\n          $tip.addClass('fade')\n        }\n\n        $tip\n          .remove()\n          .css({ top: 0, left: 0, display: 'block' })\n          .prependTo(document.body)\n\n/***** [changed for Brackets] *****/\n        this.updatePosition();\n\n        $(window).off(\"resize\", this.resizeHandler);\n        this.resizeHandler = function(e) {\n          that.updatePosition();\n        };\n        $(window).on(\"resize\", this.resizeHandler);\n\n        if (this.options.autoHideDelay) {\n          var startAutoHide = function () {\n            window.clearTimeout(that.autoHideTimeout);\n            that.autoHideTimeout = window.setTimeout(function () {\n              that.hide();\n            }, that.options.autoHideDelay);\n          }\n          if (_windowHasFocus) {\n            startAutoHide();\n          } else {\n            $(window).one(\"focus\", startAutoHide);\n          }\n        }\n\n        $tip.addClass('in');\n      }\n    }\n\n  , updatePosition: function () {\n      var pos\n        , actualWidth\n        , actualHeight\n        , paddingLeft\n        , paddingRight\n        , surplusRight\n        , shiftArrow\n        , placement\n        , $tip\n        , $arrow\n        , tp\n        , that = this\n\n      $tip = this.tip()\n\n      pos = $.extend({}, this.$element.offset(), {\n        width: this.$element[0].offsetWidth\n      , height: this.$element[0].offsetHeight\n      })\n\n      paddingLeft  = parseInt(this.$element.css(\"padding-left\"),  10);\n      paddingRight = parseInt(this.$element.css(\"padding-right\"), 10);\n\n      pos.left += paddingLeft;\n      pos.width -= (paddingLeft + paddingRight);\n\n      actualWidth = $tip[0].offsetWidth\n      actualHeight = $tip[0].offsetHeight\n\n      placement = maybeCall(this.options.placement, this, [ $tip[0], this.$element[0] ])\n      // Add the placement class so the arrow's margin can be determined\n      $tip.addClass(placement)\n\n      switch (placement) {\n        case 'below':\n          tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}\n          break\n        case 'above':\n          tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}\n          break\n        case 'left':\n          /***** [changed for Brackets] *****/\n          tp = {top: pos.top + pos.height + 20 - actualHeight, left: pos.left - actualWidth - this.options.offset}\n          break\n        case 'right':\n          /***** [changed for Brackets] *****/\n          tp = {top: pos.top + pos.height + 20 - actualHeight, left: pos.left + pos.width + this.options.offset}\n          break\n      }\n\n      shiftArrow = 0;\n\n      surplusRight = (tp.left + actualWidth - $(document.body).width());\n      if (surplusRight > 0) {\n        shiftArrow = surplusRight;\n        tp.left -= surplusRight;\n      } else if (tp.left < 0) {\n        shiftArrow = tp.left;\n        tp.left = 0;\n      }\n\n      if (surplusRight > 0) {\n        $arrow = $tip.find(\".tooltip-arrow\");\n        if (! this.defaultMargin) {\n          this.defaultMargin = parseInt($arrow.css(\"margin-left\"), 10);\n        }\n        $arrow.css(\"margin-left\", this.defaultMargin + shiftArrow);\n      }\n\n      $tip.css(tp);\n    }\n/***** [/changed for Brackets] *****/\n\n  , setContent: function () {\n      var $tip = this.tip()\n      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](this.getTitle())\n      $tip[0].className = 'tooltip'\n    }\n\n  , hide: function() {\n      var that = this\n        , $tip = this.tip()\n\n      $tip.removeClass('in')\n\n      function removeElement () {\n        $tip.remove()\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        $tip.bind(transitionEnd, removeElement) :\n        removeElement()\n\n      /***** [changed for Brackets] *****/\n      window.clearTimeout(this.autoHideTimeout);\n      $(window).off(\"resize\", this.resizeHandler)\n      /***** [/changed for Brackets] *****/\n    }\n\n  , fixTitle: function() {\n      var $e = this.$element\n      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n        $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')\n      }\n    }\n\n  , hasContent: function () {\n      return this.getTitle()\n    }\n\n  , getTitle: function() {\n      var title\n        , $e = this.$element\n        , o = this.options\n\n        this.fixTitle()\n\n        if (typeof o.title == 'string') {\n          title = $e.attr(o.title == 'title' ? 'data-original-title' : o.title)\n        } else if (typeof o.title == 'function') {\n          title = o.title.call($e[0])\n        }\n\n        title = ('' + title).replace(/(^\\s*|\\s*$)/, \"\")\n\n        return title || o.fallback\n    }\n\n  , tip: function() {\n      return this.$tip = this.$tip || $('<div class=\"tooltip\" />').html(this.options.template)\n    }\n\n  , validate: function() {\n      if (!this.$element[0].parentNode) {\n        this.hide()\n        this.$element = null\n        this.options = null\n      }\n    }\n\n  , enable: function() {\n      this.enabled = true\n    }\n\n  , disable: function() {\n      this.enabled = false\n    }\n\n  , toggleEnabled: function() {\n      this.enabled = !this.enabled\n    }\n\n  , toggle: function () {\n      this[this.tip().hasClass('in') ? 'hide' : 'show']()\n    }\n\n  }\n\n\n /* TWIPSY PRIVATE METHODS\n  * ====================== */\n\n   function maybeCall ( thing, ctx, args ) {\n     return typeof thing == 'function' ? thing.apply(ctx, args) : thing\n   }\n\n /* TWIPSY PLUGIN DEFINITION\n  * ======================== */\n\n  $.fn.twipsy = function (options) {\n    $.fn.twipsy.initWith.call(this, options, Twipsy, 'twipsy')\n    return this\n  }\n\n  $.fn.twipsy.initWith = function (options, Constructor, name) {\n    var twipsy\n      , binder\n      , eventIn\n      , eventOut\n\n    if (options === true) {\n      return this.data(name)\n    } else if (typeof options == 'string') {\n      twipsy = this.data(name)\n      if (twipsy) {\n        twipsy[options]()\n      }\n      return this\n    }\n\n    options = $.extend({}, $.fn[name].defaults, options)\n\n    function get(ele) {\n      var twipsy = $.data(ele, name)\n\n      if (!twipsy) {\n        twipsy = new Constructor(ele, $.fn.twipsy.elementOptions(ele, options))\n        $.data(ele, name, twipsy)\n      }\n\n      return twipsy\n    }\n\n    function enter() {\n      var twipsy = get(this)\n      twipsy.hoverState = 'in'\n\n      if (options.delayIn == 0) {\n        twipsy.show()\n      } else {\n        twipsy.fixTitle()\n        setTimeout(function() {\n          if (twipsy.hoverState == 'in') {\n            twipsy.show()\n          }\n        }, options.delayIn)\n      }\n    }\n\n    function leave() {\n      var twipsy = get(this)\n      twipsy.hoverState = 'out'\n      if (options.delayOut == 0) {\n        twipsy.hide()\n      } else {\n        setTimeout(function() {\n          if (twipsy.hoverState == 'out') {\n            twipsy.hide()\n          }\n        }, options.delayOut)\n      }\n    }\n\n    if (!options.live) {\n      this.each(function() {\n        get(this)\n      })\n    }\n\n    if (options.trigger != 'manual') {\n      binder   = options.live ? 'live' : 'bind'\n      eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus'\n      eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'\n      this[binder](eventIn, enter)[binder](eventOut, leave)\n    }\n\n    return this\n  }\n\n  $.fn.twipsy.Twipsy = Twipsy\n\n  $.fn.twipsy.defaults = {\n    animate: true\n  , delayIn: 0\n  , delayOut: 0\n  , fallback: ''\n  , placement: 'above'\n  , html: false\n  , live: false\n  , offset: 0\n  , title: 'title'\n  , trigger: 'hover'\n  , template: '<div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div>'\n  }\n\n  $.fn.twipsy.rejectAttrOptions = [ 'title' ]\n\n  $.fn.twipsy.elementOptions = function(ele, options) {\n    var data = $(ele).data()\n      , rejects = $.fn.twipsy.rejectAttrOptions\n      , i = rejects.length\n\n    while (i--) {\n      delete data[rejects[i]]\n    }\n\n    return $.extend({}, options, data)\n  }\n\n}( window.jQuery || window.ender );\n"
  },
  {
    "path": "src/widgets/infobar.js",
    "content": "/*\n * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var MainViewManager     = require(\"view/MainViewManager\"),\n        Mustache            = require(\"thirdparty/mustache/mustache\"),\n        EventDispatcher     = require(\"utils/EventDispatcher\"),\n        InfoBarHtml         = require(\"text!htmlContent/infobar-template.html\"),\n        _                   =  require(\"thirdparty/lodash\");\n\n    EventDispatcher.makeEventDispatcher(exports);\n\n    // Key handlers for buttons in UI\n    var ESC_KEY   = 27; // keycode for escape key\n\n    /**\n     * Generates the json to be used by Mustache for rendering\n     * @param   {object}   msgObj - json object containing message information to be displayed\n     * @returns {object} - the generated json object\n     */\n    function generateJsonForMustache(msgObj) {\n        var msgJsonObj = {};\n        if (msgObj.type) {\n            msgJsonObj.type = \"'\" + msgObj.type + \"'\";\n        }\n        msgJsonObj.title = msgObj.title;\n        msgJsonObj.description = msgObj.description;\n        return msgJsonObj;\n    }\n    /**\n     * Removes and cleans up the info bar from DOM\n     */\n    function cleanInfoBar() {\n        var $infoBar = $('#info-bar-template');\n        if ($infoBar.length > 0) {\n            $infoBar.remove();\n        }\n        $(window.document).off(\"keydown.InfoBarTemplateDoc\");\n        $(window).off('resize.InfoBarTemplate');\n    }\n\n    /**\n     * Displays the Info Bar UI\n     * @param   {object} msgObj - json object containing message info to be displayed\n     *\n     */\n    function showInfoBar(msgObj) {\n        var jsonToMustache = generateJsonForMustache(msgObj),\n            $infoBarElement = $(Mustache.render(InfoBarHtml, jsonToMustache));\n\n        cleanInfoBar(); //Remove an already existing info bar, if any\n        $infoBarElement.prependTo(\".content\");\n\n        var $infoBar = $('#info-bar-template'),\n            $infoContent = $infoBar.find('#info-content'),\n            $contentContainer = $infoBar.find('#content-container'),\n            $iconContainer = $infoBar.find('#icon-container'),\n            $closeIconContainer = $infoBar.find('#close-icon-container'),\n            $heading = $infoBar.find('#heading'),\n            $description = $infoBar.find('#description'),\n            $closeIcon = $infoBar.find('#close-icon');\n\n        if ($infoContent.length > 0) {\n            if ($infoContent[0].scrollWidth > $infoContent.innerWidth()) {\n            //Text has over-flown, show the info content as tooltip message\n                if ($contentContainer.length > 0 &&\n                        $heading.length > 0 &&\n                        $description.length > 0) {\n                    $contentContainer.attr(\"title\", $heading.text() + $description.text());\n                }\n            }\n        }\n        // Content Container Width between Icon Container and Button Container or Close Icon Container\n        // will be assigned when window will be rezied.\n        var resizeContentContainer = function () {\n            if($infoContent.length > 0 && $contentContainer.length > 0 && $infoBar.length > 0) {\n                var newWidth = $infoBar.outerWidth() - 38;\n                if($iconContainer.length > 0) {\n                    newWidth = newWidth - $iconContainer.outerWidth();\n                }\n                if($closeIconContainer.length > 0) {\n                    newWidth = newWidth - $closeIconContainer.outerWidth();\n                }\n\n                $contentContainer.css({\n                    \"maxWidth\": newWidth\n                });\n            }\n        };\n\n        resizeContentContainer();\n        $(window).on('resize.InfoBarTemplate', _.debounce(resizeContentContainer, 150));\n\n        //Event handlers on the Info Bar\n        // Click and key handlers on Close button\n        if ($closeIcon.length > 0) {\n            $closeIcon.click(function () {\n                cleanInfoBar();\n                MainViewManager.focusActivePane();\n            });\n        }\n        $(window.document).on(\"keydown.InfoBarTemplateDoc\", function (event) {\n            var code = event.which;\n            if (code === ESC_KEY) {\n                // Keyboard input of Esc key on Info Bar dismisses and removes the bar\n                cleanInfoBar();\n                MainViewManager.focusActivePane();\n                event.stopImmediatePropagation();\n            }\n        });\n    }\n    exports.showInfoBar = showInfoBar;\n});\n"
  },
  {
    "path": "src/xorigin.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Function to test whether a given error represents an illegal cross origin access\n */\n(function () {\n    \"use strict\";\n\n    var testCrossOriginError;\n\n    if (window.navigator.userAgent.search(\" Chrome/\") !== -1) {\n        // Chrome support\n        testCrossOriginError = function (message, url, line) {\n            return url === \"\" && line === 0 && message === \"Script error.\";\n        };\n    } else if (window.navigator.userAgent.slice(0, 6) === 'Opera/') {\n        // Opera support\n        testCrossOriginError = function (message, url, line) {\n            return message === \"Uncaught exception: DOMException: NETWORK_ERR\";\n        };\n    }\n\n    // Abort if running in the shell, running on a server or not running in a supported and affected browser\n    if (typeof (brackets) !== \"undefined\" ||\n            window.document.location.href.substr(0, 7) !== \"file://\" ||\n            !testCrossOriginError) {\n        return;\n    }\n\n    // Remember the current error handler to restore it once we're done\n    var previousErrorHandler = window.onerror;\n\n    // Our error handler\n    function handleError(message, url, line) {\n        // Ignore this error if it does not look like the rather vague cross origin error in Chrome\n        // Chrome will print it to the console anyway\n        if (!testCrossOriginError(message, url, line)) {\n            if (previousErrorHandler) {\n                return previousErrorHandler(message, url, line);\n            }\n            return;\n        }\n\n        // Show an error message\n        window.alert(\"Oops! This application doesn't run in browsers yet.\\n\\nIt is built in HTML, but right now it runs as a desktop app so you can use it to edit local files. Please use the application shell in the following repo to run this application:\\n\\ngithub.com/adobe/brackets-shell\");\n\n        // Restore the original handler for later errors\n        window.onerror = previousErrorHandler;\n    }\n\n    // Install our error handler\n    window.onerror = handleError;\n}());\n"
  },
  {
    "path": "tasks/build.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true, regexp: true */\n\"use strict\";\n\nmodule.exports = function (grunt) {\n    var child_process   = require(\"child_process\"),\n        http            = require(\"http\"),\n        https           = require(\"https\"),\n        build           = {},\n        path            = require(\"path\"),\n        q               = require(\"q\"),\n        querystring     = require(\"querystring\"),\n        qexec           = q.denodeify(child_process.exec);\n\n    function getGitInfo(cwd) {\n        var opts = { cwd: cwd, maxBuffer: 1024 * 1024 },\n            json = {};\n\n        // count the number of commits for our version number\n        //     <major>.<minor>.<patch>-<number of commits>\n        return qexec(\"git log --format=%h\", opts).then(function (stdout) {\n            json.commits = stdout.toString().match(/[0-9a-f]\\n/g).length;\n\n            // get the hash for the current commit (HEAD)\n            return qexec(\"git rev-parse HEAD\", opts);\n        }).then(function (stdout) {\n            json.sha = /([a-f0-9]+)/.exec(stdout.toString())[1];\n\n            // compare HEAD to the HEADs on the remote\n            return qexec(\"git ls-remote --heads origin\", opts);\n        }).then(function (stdout) {\n            var log = stdout.toString(),\n                re = new RegExp(json.sha + \"\\\\srefs/heads/(\\\\S+)\\\\s\"),\n                match = re.exec(log),\n                reflog;\n\n            // if HEAD matches to a remote branch HEAD, grab the branch name\n            if (match) {\n                json.branch = match[1];\n                return json;\n            }\n\n            // else, try match HEAD using reflog\n            reflog = qexec(\"git reflog show --no-abbrev-commit --all\", opts);\n\n            return reflog.then(function (stdout) {\n                var log = stdout.toString(),\n                    re = new RegExp(json.sha + \"\\\\srefs/(remotes/origin|heads)/(\\\\S+)@\"),\n                    match = re.exec(log);\n\n                json.branch = (match && match[2]) || \"(no branch)\";\n\n                return json;\n            });\n        });\n    }\n\n    function toProperties(prefix, json) {\n        var out = \"\";\n\n        Object.keys(json).forEach(function (key) {\n            out += prefix + key + \"=\" + json[key] + \"\\n\";\n        });\n\n        return out;\n    }\n\n    // task: build-num\n    grunt.registerTask(\"build-prop\", \"Write build.prop properties file for Jenkins\", function () {\n        var done        = this.async(),\n            out         = \"\",\n            version     = grunt.config(\"pkg\").version,\n            www_repo    = process.cwd(),\n            shell_repo  = path.resolve(www_repo, grunt.config(\"shell.repo\")),\n            www_git,\n            shell_git;\n\n        getGitInfo(www_repo).then(function (json) {\n            www_git = json;\n            return getGitInfo(shell_repo);\n        }).then(function (json) {\n            shell_git = json;\n        }, function (err) {\n            // shell git info is optional\n            grunt.log.writeln(err);\n        }).finally(function () {\n            out += \"brackets_build_version=\" + version.substr(0, version.lastIndexOf(\"-\") + 1) + www_git.commits + \"\\n\";\n            out += toProperties(\"brackets_www_\", www_git);\n\n            if (shell_git) {\n                out += toProperties(\"brackets_shell_\", shell_git);\n            }\n\n            grunt.log.write(out);\n            grunt.file.write(\"build.prop\", out);\n\n            done();\n        });\n    });\n\n    // task: cla-check-pull\n    grunt.registerTask(\"cla-check-pull\", \"Check if a given GitHub user has signed the CLA\", function () {\n        var done        = this.async(),\n            body        = \"\",\n            options     = {},\n            travis      = process.env.TRAVIS === \"true\",\n            pull        = travis ? process.env.TRAVIS_PULL_REQUEST : (grunt.option(\"pull\") || false),\n            request;\n\n        pull = parseInt(pull, 10);\n\n        if (isNaN(pull)) {\n            grunt.log.writeln(JSON.stringify(process.env));\n\n            if (travis) {\n                // Kicked off a travis build without a pull request, skip CLA check\n                grunt.log.writeln(\"Travis build without pull request\");\n                done();\n            } else {\n                // Grunt command-line option missing, fail CLA check\n                grunt.log.writeln(\"Missing pull request number. Use 'grunt cla-check-pull --pull=<NUMBER>'.\");\n                done(false);\n            }\n\n            return;\n        }\n\n        options.host    = \"api.github.com\";\n        options.path    = \"/repos/adobe/brackets/issues/\" + pull;\n        options.method  = \"GET\";\n        options.headers = {\n            \"User-Agent\" : \"Node.js\"\n        };\n        \n        // Append secret env var only when it's available \n        // Refer to https://docs.travis-ci.com/user/pull-requests/#Pull-Requests-and-Security-Restrictions\n        if (process.env.BRACKETS_REPO_OAUTH_TOKEN) {\n            options.path += \"?access_token=\" + process.env.BRACKETS_REPO_OAUTH_TOKEN;\n        }\n\n        request = https.request(options, function (res) {\n            res.on(\"data\", function (chunk) {\n                body += chunk;\n            });\n\n            res.on(\"end\", function () {\n                var json    = JSON.parse(body),\n                    login   = json.user && json.user.login;\n\n                if (login) {\n                    grunt.option(\"user\", login);\n                    grunt.task.run(\"cla-check\");\n\n                    done();\n                } else {\n                    grunt.log.writeln(\"Unexpected response from api.github.com\");\n                    grunt.log.writeln(\"statusCode: \" + res.statusCode);\n                    grunt.log.writeln(\"headers: \" + JSON.stringify(res.headers));\n                    grunt.log.writeln(\"data: \" + body);\n\n                    done(false);\n                }\n            });\n\n            res.on(\"error\", function (err) {\n                grunt.log.writeln(err);\n                done(false);\n            });\n        });\n\n        request.end();\n    });\n\n    // task: cla-check\n    grunt.registerTask(\"cla-check\", \"Check if a given GitHub user has signed the CLA\", function () {\n        var done    = this.async(),\n            user    = grunt.option(\"user\") || \"\",\n            body    = \"\",\n            options = {},\n            postdata = querystring.stringify({contributor: user}),\n            request;\n\n        if (!user) {\n            grunt.log.writeln(\"Missing user name. Use 'grunt cla-check --user=<GITHUB USER NAME>'.\");\n            done(false);\n            return;\n        }\n\n        // Check CLA exceptions first\n        var exceptions = grunt.file.readJSON(\"tasks/cla-exceptions.json\");\n\n        if (exceptions[user]) {\n            grunt.log.writeln(user + \" exempt from the standard contributor license agreement\");\n            done();\n            return;\n        }\n\n        // Query dev.brackets.io for CLA status\n        options.host    = \"dev.brackets.io\";\n        options.path    = \"/cla/brackets/check.cfm\";\n        options.method  = \"POST\";\n        options.headers = {\n            \"Content-Type\"      : \"application/x-www-form-urlencoded\",\n            \"Content-Length\"    : postdata.length\n        };\n\n        request = http.request(options, function (res) {\n            res.on(\"data\", function (chunk) {\n                body += chunk;\n            });\n\n            res.on(\"end\", function () {\n                if (body.match(/.*REJECTED.*/)) {\n                    grunt.log.error(user + \" has NOT submitted the contributor license agreement. See http://dev.brackets.io/brackets-contributor-license-agreement.html.\");\n                    done(false);\n                } else {\n                    grunt.log.writeln(user + \" has submitted the contributor license agreement\");\n                    done();\n                }\n            });\n\n            res.on(\"error\", function (err) {\n                grunt.log.writeln(err);\n                done(false);\n            });\n        });\n\n        request.write(postdata);\n        request.end();\n    });\n\n    grunt.registerTask(\"nls-check\", \"Checks if all the keys in nls files are defined in root\", function () {\n        var done = this.async(),\n            PATH = \"src/nls\",\n            ROOT_LANG = \"root\",\n            encounteredErrors = false,\n            rootDefinitions = {},\n            definitions,\n            unknownKeys;\n\n        function getDefinitions(abspath) {\n            var fileContent,\n                definitions = [];\n\n            fileContent = grunt.file.read(abspath);\n            fileContent.split(\"\\n\").forEach(function (line) {\n                var match = line.match(/^\\s*\"(\\S+)\"\\s*:/);\n                if (match && match[1]) {\n                    definitions.push(match[1]);\n                }\n            });\n            return definitions;\n        }\n\n        // Extracts all nls keys from nls/root\n        grunt.file.recurse(PATH + \"/\" + ROOT_LANG, function (abspath, rootdir, subdir, filename) {\n            rootDefinitions[filename] = getDefinitions(abspath);\n        });\n\n        // Compares nls keys in translations with root ones\n        grunt.file.recurse(PATH, function (abspath, rootdir, subdir, filename) {\n            if (!subdir || subdir === ROOT_LANG) {\n                return;\n            }\n            definitions = getDefinitions(abspath);\n            unknownKeys = [];\n\n            unknownKeys = definitions.filter(function (key) {\n                return rootDefinitions[filename].indexOf(key) < 0;\n            });\n\n            if (unknownKeys.length) {\n                grunt.log.writeln(\"There are unknown keys included in \" + PATH + \"/\" + subdir + \"/\" + filename + \":\", unknownKeys);\n                encounteredErrors = true;\n            }\n        });\n\n        done(!encounteredErrors);\n    });\n\n    build.getGitInfo = getGitInfo;\n\n    return build;\n};\n"
  },
  {
    "path": "tasks/cla-exceptions.json",
    "content": "{\n    \"busykai\": true,\n    \"mjherna1\": true,\n    \"shahabl\": true,\n    \"sebaslv\": true,\n    \"albertinad\": true,\n    \"walfgithub\": true,\n    \"mfatekho\": true\n}\n"
  },
  {
    "path": "tasks/lib/common.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nmodule.exports = function (grunt) {\n    var common      = {},\n        path        = require(\"path\"),\n        _platform;\n\n    function resolve(relPath) {\n        return path.resolve(process.cwd(), relPath);\n    }\n\n    function platform() {\n        if (!_platform) {\n            if (process.platform === \"darwin\") {\n                _platform = \"mac\";\n            } else if (process.platform === \"win32\") {\n                _platform = \"win\";\n            } else {\n                _platform = \"linux\";\n            }\n        }\n\n        return _platform;\n    }\n    \n    function writeJSON(grunt, path, obj) {\n        var content = JSON.stringify(obj, null, \"    \");\n        if (platform() === \"win\") {\n            content = content.split(\"\\n\").join(\"\\r\\n\");\n        }\n        grunt.file.write(path, content);\n    }\n\n    common.writeJSON    = writeJSON;\n    common.resolve      = resolve;\n    common.platform     = platform;\n\n    return common;\n};\n"
  },
  {
    "path": "tasks/npm-install.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global Promise */\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nmodule.exports = function (grunt) {\n\n    var _       = require(\"lodash\"),\n        build   = require(\"./build\")(grunt),\n        common  = require(\"./lib/common\")(grunt),        \n        exec    = require(\"child_process\").exec,\n        fs      = require(\"fs-extra\"),\n        glob    = require(\"glob\"),\n        https   = require(\"https\"),\n        path    = require(\"path\"),\n        tar     = require(\"tar\"),\n        temp    = require(\"temp\"),        \n        zlib    = require(\"zlib\");\n    \n    temp.track();\n    \n    function runNpmInstall(where, callback, includeDevDependencies) {\n        var envFlag = includeDevDependencies ? \"\" : \" --production\";\n        grunt.log.writeln(\"running npm install\" + envFlag + \" in \" + where);\n        exec('npm install' + envFlag, { cwd: './' + where }, function (err, stdout, stderr) {\n            if (err) {\n                grunt.log.error(stderr);\n            } else {\n                grunt.log.writeln(stdout || \"finished npm install in \" + where);\n            }\n            return err ? callback(stderr) : callback(null, stdout);\n        });\n    }\n\n    grunt.registerTask(\"npm-install\", \"Install node_modules to the dist folder so it gets bundled with release\", function () {\n        var npmShrinkwrapJSON = grunt.file.readJSON(\"npm-shrinkwrap.json\");\n        common.writeJSON(grunt, \"dist/npm-shrinkwrap.json\", npmShrinkwrapJSON);\n\n        var packageJSON = grunt.file.readJSON(\"package.json\");\n        delete packageJSON.devDependencies;\n        delete packageJSON.scripts; // we don't want to run post-install scripts in dist folder\n        common.writeJSON(grunt, \"dist/package.json\", packageJSON);\n\n        var done = this.async();\n        runNpmInstall(\"dist\", function (err) {\n            return err ? done(false) : done();\n        });\n    });\n\n    grunt.registerTask(\"npm-install-src\", \"Install node_modules to the src folder\", function () {\n        var _done = this.async(),\n            dirs = [\"src\", \"src/JSUtils\", \"src/JSUtils/node\", \"src/languageTools/LanguageClient\"],\n            done = _.after(dirs.length, _done);\n        dirs.forEach(function (dir) {\n            runNpmInstall(dir, function (err) {\n                return err ? _done(false) : done();\n            });\n        });\n    });\n    \n    grunt.registerTask(\"npm-install-extensions\", \"Install node_modules for default extensions which have package.json defined\", function () {\n        var _done = this.async();\n        glob(\"src/extensions/**/package.json\", function (err, files) {\n            if (err) {\n                grunt.log.error(err);\n                return _done(false);\n            }\n            files = files.filter(function (path) {\n                return path.indexOf(\"node_modules\") === -1;\n            });\n            var done = _.after(files.length, _done);\n            files.forEach(function (file) {\n                runNpmInstall(path.dirname(file), function (err) {\n                    return err ? _done(false) : done();\n                });\n            });\n        });\n    });\n\n    grunt.registerTask(\"npm-install-test\", \"Install node_modules for tests\", function () {\n        var _done = this.async();\n        var testDirs = [\n            \"spec/LanguageTools-test-files\"\n        ];\n        testDirs.forEach(function (dir) {\n            glob(\"test/\" + dir + \"/**/package.json\", function (err, files) {\n                if (err) {\n                    grunt.log.error(err);\n                    return _done(false);\n                }\n                files = files.filter(function (path) {\n                    return path.indexOf(\"node_modules\") === -1;\n                });\n                var done = _.after(files.length, _done);\n                files.forEach(function (file) {\n                    runNpmInstall(path.dirname(file), function (err) {\n                        return err ? _done(false) : done();\n                    }, true);\n                });\n            });\n        });\n    });\n\n    grunt.registerTask(\n        \"npm-install-source\",\n        \"Install node_modules for src folder and default extensions which have package.json defined\",\n        [\"npm-install-src\", \"copy:thirdparty\", \"npm-install-extensions\", \"npm-install-test\"]\n    );\n    \n    function getNodeModulePackageUrl(extensionName) {\n        return new Promise(function (resolve, reject) {\n            exec(\"npm view \" + extensionName + \" dist.tarball\", {}, function (err, stdout, stderr) {\n                if (err) {\n                    grunt.log.error(stderr);\n                }\n                return err ? reject(stderr) : resolve(stdout.toString(\"utf8\").trim());\n            });\n        });\n    }\n    \n    function getTempDirectory(tempName) {\n        return new Promise(function (resolve, reject) {\n            temp.mkdir(tempName, function(err, dirPath) {\n                return err ? reject(err) : resolve(dirPath);\n            });\n        });\n    }\n    \n    function downloadUrlToFolder(url, dirPath) {\n        return new Promise(function (resolve, reject) {\n            grunt.log.writeln(url + \" downloading...\");            \n            https.get(url, function (res) {\n                \n                if (res.statusCode !== 200) {\n                    return reject(new Error(\"Request failed: \" + res.statusCode));\n                }\n                \n                var unzipStream = zlib.createGunzip();\n                res.pipe(unzipStream);\n                \n                var extractStream = tar.Extract({ path: dirPath, strip: 0 });\n                unzipStream.pipe(extractStream);\n                \n                extractStream.on('finish', function() {\n                    grunt.log.writeln(url + \" successfully downloaded\");\n                    resolve(path.resolve(dirPath, \"package\"));\n                });\n                \n            }).on('error', function(err) {\n                reject(err);\n            });\n        });\n    }\n    \n    function move(from, to) {\n        return new Promise(function (resolve, reject) {\n            fs.remove(to, function (err) {\n                if (err) {\n                    return reject(err);\n                }\n                fs.move(from, to, function (err) {\n                    if (err) {\n                        return reject(err);\n                    }\n                    return resolve();\n                });\n            });\n        });\n    }\n    \n    function downloadAndInstallExtensionFromNpm(obj) {\n        var extensionName = obj.name;            \n        var extensionVersion = obj.version ? \"@\" + obj.version : \"\";\n        var data = {};\n        return getNodeModulePackageUrl(extensionName + extensionVersion)\n            .then(function (urlToDownload) {\n                data.urlToDownload = urlToDownload;\n                return getTempDirectory(extensionName);\n            })\n            .then(function (tempDirPath) {\n                data.tempDirPath = tempDirPath;                \n                return downloadUrlToFolder(data.urlToDownload, data.tempDirPath);\n            })\n            .then(function (extensionPath) {\n                var target = path.resolve(__dirname, '..', 'src', 'extensions', 'default', extensionName);\n                return move(extensionPath, target);\n            });\n    }\n    \n    grunt.registerTask(\"npm-download-default-extensions\",\n                       \"Downloads extensions from npm and puts them to the src/extensions/default folder\",\n                       function () {\n        \n        var packageJSON = grunt.file.readJSON(\"package.json\");\n        var extensionsToDownload = Object.keys(packageJSON.defaultExtensions).map(function (name) {\n            return {\n                name: name,\n                version: packageJSON.defaultExtensions[name]\n            };\n        });\n        \n        var done = this.async();\n        Promise.all(extensionsToDownload.map(function (extension) {\n            return downloadAndInstallExtensionFromNpm(extension);\n        })).then(function () {\n            return done();\n        }).catch(function (err) {\n            grunt.log.error(err);\n            return done(false);\n        });\n        \n    });\n\n};\n"
  },
  {
    "path": "tasks/pack-web-dependencies.js",
    "content": "/* eslint-env node */\n\n\"use strict\";\n\nmodule.exports = function (grunt) {\n\n    var _       = require(\"lodash\"),\n        common  = require(\"./lib/common\")(grunt),\n        build   = require(\"./build\")(grunt),\n        glob    = require(\"glob\"),\n        path    = require(\"path\"),\n        spawn   = require(\"child_process\").spawn;\n\n    grunt.registerTask(\"pack-web-dependencies\", \"Runs webpack on stuff we need to use from browser\", function () {\n        var done = this.async();\n        var webpackPath = path.resolve(\n            __dirname,\n            \"..\",\n            \"node_modules\",\n            \".bin\",\n            process.platform === \"win32\" ? \"webpack.cmd\" : \"webpack\"\n        );\n        var webpackTasks = [\n            [\n                \"./node_modules/semver/semver.js\",\n                \"./src/thirdparty/semver.browser.js\",\n                \"-p\",\n                \"--output-library-target=amd\"\n            ],\n            [\n                \"./src/node_modules/preact/dist/preact.min.js\",\n                \"./src/thirdparty/preact/preact.js\",\n                \"-p\",\n                \"--output-library-target=amd\"\n            ],\n            [\n                \"./src/node_modules/preact-test-utils/lib/index.js\",\n                \"./src/thirdparty/preact-test-utils/preact-test-utils.js\",\n                \"-p\",\n                \"--output-library-target=amd\"\n            ]\n        ];\n        var doneWithWebpackTask = _.after(webpackTasks.length, done);\n        webpackTasks.forEach(function (args) {\n            var wp = spawn(webpackPath, args, {\n                cwd: path.resolve(__dirname, \"..\")\n            });\n            wp.stdout.on('data', function (data) {\n                console.log(\"webpack-stdout: \" + data.toString());\n            });\n            wp.stderr.on('data', function (data) {\n                console.log(\"webpack-stderr: \" + data.toString());\n            });\n            wp.on('close', function (code) {\n                console.log(\"webpack-exit code \" + code.toString());\n                return code === 0 ? doneWithWebpackTask() : done(false);\n            });\n        });\n    });\n\n};\n"
  },
  {
    "path": "tasks/test.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nmodule.exports = function (grunt) {\n    var common          = require(\"./lib/common\")(grunt),\n        child_process   = require(\"child_process\"),\n        q               = require(\"q\"),\n        qexec           = q.denodeify(child_process.exec),\n        XmlDocument     = require(\"xmldoc\").XmlDocument;\n\n    /**\n     * Check the unit test results for failures\n     */\n    function checkForTestFailures(pathToResult) {\n        var resultXml = grunt.file.read(pathToResult),\n            xmlDocument = new XmlDocument(resultXml),\n            testSuites = xmlDocument.childrenNamed(\"testsuite\"),\n            failures = 0;\n\n        testSuites.forEach(function (testSuite) {\n            failures += Number(testSuite.attr.failures);\n        });\n\n        return failures;\n    }\n\n    // task: test-integration\n    grunt.registerTask(\"test-integration\", \"Run tests in brackets-shell. Requires 'grunt full-build' in shell.\", function () {\n        var done            = this.async(),\n            platform        = common.platform(),\n            opts            = { cwd: process.cwd() },\n            cmd             = common.resolve(grunt.option(\"shell\") || grunt.config(\"shell.\" + platform)),\n            spec            = grunt.option(\"spec\") || \"all\",\n            suite           = grunt.option(\"suite\") || \"all\",\n            results         = grunt.option(\"results\") || process.cwd() + \"/results.xml\",\n            resultsPath     = common.resolve(results).replace(/\\\\/g, \"/\"),\n            specRunnerPath  = common.resolve(\"test/SpecRunner.html\"),\n            args            = \" --startup-path=\\\"\" + specRunnerPath + \"?suite=\" + encodeURIComponent(suite) + \"&spec=\" + encodeURIComponent(spec) + \"&resultsPath=\" + encodeURIComponent(resultsPath) + \"\\\"\";\n\n        if (platform === \"mac\") {\n            cmd = \"open \\\"\" + cmd + \"\\\" -W --args \" + args;\n        } else {\n            cmd += args;\n        }\n\n        grunt.log.writeln(cmd);\n\n        qexec(cmd, opts).then(function (stdout, stderr) {\n            var failures = checkForTestFailures(resultsPath);\n            if (failures) {\n                var e = new Error(failures + ' test failure(s). Results are available from ' + resultsPath);\n                done(e);\n            } else {\n                done();\n            }\n        }, function (err) {\n            grunt.log.writeln(err);\n            done(false);\n        });\n    });\n};\n"
  },
  {
    "path": "tasks/update-release-number.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nmodule.exports = function (grunt) {\n    var common = require(\"./lib/common\")(grunt),\n        semver = require(\"semver\");\n\n    // task: update-release-number\n    // Updates the version property in package.json\n    grunt.registerTask('update-release-number', function () {\n        var path        = \"package.json\",\n            packageJSON = grunt.file.readJSON(path),\n            release     = grunt.option(\"release\") || \"\";\n\n        if (!release || !semver.valid(release)) {\n            grunt.fail.fatal(\"Please specify a release. e.g. grunt update-release-number --release=1.1.0\");\n        }\n\n        packageJSON.version = release + \"-0\";\n        packageJSON.apiVersion = release;\n\n        common.writeJSON(grunt, path, packageJSON);\n    });\n};\n"
  },
  {
    "path": "tasks/write-config.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\"use strict\";\n\nmodule.exports = function (grunt) {\n    var common  = require(\"./lib/common\")(grunt),\n        build   = require(\"./build\")(grunt);\n\n    // task: write-config\n    grunt.registerTask(\"write-config\", \"Merge package.json and src/brackets.config.json into src/config.json\", function () {\n        var name = \"dev\";\n        if (this.flags.dist === true) {\n            name = \"dist\";\n        } else if (this.flags.prerelease === true) {\n            name = \"prerelease\";\n        }\n\n        var appConfigJSON = grunt.file.readJSON(\"src/brackets.config.json\"),\n            appConfigEnvJSON = grunt.file.readJSON(\"src/brackets.config.\" + name + \".json\"),\n            key;\n        for (key in appConfigEnvJSON) {\n            if (appConfigEnvJSON.hasOwnProperty(key)) {\n                appConfigJSON.config[key] = appConfigEnvJSON[key];\n            }\n        }\n\n        var packageJSON = grunt.file.readJSON(\"package.json\");\n        Object.keys(packageJSON).forEach(function (key) {\n            if (appConfigJSON[key] === undefined) {\n                appConfigJSON[key] = packageJSON[key];\n            }\n        });\n\n        common.writeJSON(grunt, \"src/config.json\", appConfigJSON);\n    });\n\n    // task: build-config\n    grunt.registerTask(\"build-config\", \"Update config.json with the build timestamp, branch and SHA being built\", function () {\n        var done = this.async(),\n            distConfig = grunt.file.readJSON(\"src/config.json\");\n\n        build.getGitInfo(process.cwd()).then(function (gitInfo) {\n            distConfig.buildnumber = gitInfo.commits;\n            distConfig.version = distConfig.version.substr(0, distConfig.version.lastIndexOf(\"-\") + 1) + gitInfo.commits;\n            distConfig.repository.SHA = gitInfo.sha;\n            distConfig.repository.branch = gitInfo.branch;\n            distConfig.config.build_timestamp = new Date().toString().split('(')[0].trim();\n\n            common.writeJSON(grunt, \"dist/config.json\", distConfig);\n\n            done();\n        }, function (err) {\n            grunt.log.writeln(err);\n            done(false);\n        });\n    });\n};\n"
  },
  {
    "path": "test/BootstrapReporterView.css",
    "content": "@media (min-width: 728px) {\n    body {\n        /* make the container go all the way to the bottom of the topbar */\n        padding-top: 60px;\n    }\n}\n\npre {\n    overflow-x: scroll;\n    white-space: pre;\n    word-wrap: normal;\n}\n.nav .badge {\n    float: right;\n}\n\n/* Make fail (red) color bolder so easier to see */\n.label-important, .badge-important {\n    background-color: #F00;\n}\n\n/* Reduce padding between lines to show more tests */\n.nav-pills > li > a {\n    padding-top: 4px;\n    padding-bottom: 4px;\n}\n\n@media (max-width: 767px) {\n    /* Reduce font size for smaller viewport */\n    .nav-pills > li > a {\n        font-size: 11px;\n    }\n}\n\n.link-to-source {\n    /* Behavioral style - indicates that clicking opens a file in the parent Brackets window */\n}\n/* De-emphasize source links to Jasmine framework code (vs. links to test spec & Brackets core code) */\n.testframework-link {\n    opacity: 0.45;\n}\n\n/* Add some space between the menu and the list of tests.  */\n.container-fluid {\n    margin-top: 1.5em;\n}\n\n@media (min-width: 728px) and (max-width: 1199px) {\n    .navbar-fixed-top .container,\n    .navbar-fixed-bottom .container {\n        width: 800px;\n    }\n}\n"
  },
  {
    "path": "test/BootstrapReporterView.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jslint regexp: true */\n\ndefine(function (require, exports, module) {\n    'use strict';\n\n    var _ = require(\"thirdparty/lodash\");\n\n    var BootstrapReporterView = function (doc, reporter) {\n        doc = doc || window.document;\n\n        $(reporter)\n            .on(\"runnerStart\", this._handleRunnerStart.bind(this))\n            .on(\"runnerEnd\", this._handleRunnerEnd.bind(this))\n            .on(\"suiteEnd\", this._handleSuiteEnd.bind(this))\n            .on(\"specStart\", this._handleSpecStart.bind(this))\n            .on(\"specEnd\", this._handleSpecEnd.bind(this));\n\n        // build DOM immediately\n        var container = $(\n            '<div class=\"container-fluid\">' +\n                '<div class=\"row-fluid\">' +\n                    '<div class=\"span4\">' +\n                        '<ul id=\"suite-list\" class=\"nav nav-pills nav-stacked\">' +\n                        '</ul>' +\n                    '</div>' +\n                    '<div id=\"results-container\" class=\"span8\">' +\n                    '</div>' +\n                '</div>' +\n                '</div>'\n        );\n\n        $(doc.body).append(container);\n\n        this._topLevelSuiteMap = {};\n        this.$suiteList = $(\"#suite-list\");\n        this.$resultsContainer = $(\"#results-container\");\n    };\n\n    BootstrapReporterView.prototype._createSuiteListItem = function (suiteName, specCount) {\n        var $badgeAll = $('<span class=\"badge\">' + specCount + \"</span>\"),\n            $badgePassed = $('<span class=\"badge badge-success\" style=\"display:none\"/>'),\n            $badgeFailed = $('<span class=\"badge badge-important\" style=\"display:none\"/>'),\n            $anchor = $('<a href=\"?spec=' + encodeURIComponent(suiteName) + '\">' + suiteName + '</a>').append($badgeAll).append($badgePassed).append($badgeFailed),\n            $listItem = $('<li/>').append($anchor);\n\n        this._topLevelSuiteMap[suiteName] = {\n            $badgeAll: $badgeAll,\n            $badgePassed: $badgePassed,\n            $badgeFailed: $badgeFailed,\n            $anchor: $anchor,\n            $listItem: $listItem\n        };\n\n        return $listItem;\n    };\n\n    BootstrapReporterView.prototype._createSuiteList = function (suites, sortedNames, totalSpecCount) {\n        var self = this;\n\n        sortedNames.forEach(function (name, index) {\n            var count = suites[name].specCount;\n            if (count > 0) {\n                self.$suiteList.append(self._createSuiteListItem(name, count));\n            }\n        });\n\n        // add an \"all\" top-level suite\n        this.$suiteList.prepend(this._createSuiteListItem(\"All\", totalSpecCount));\n    };\n\n    BootstrapReporterView.prototype._showProgressBar = function (spec) {\n        if (!this.$progressBar) {\n            this.$progress = $('<div class=\"bar\"/>');\n            this.$progressBar = $('<div class=\"progress progress-striped\"/>').append(this.$progress);\n        }\n\n        this.$resultsContainer.append(this.$progressBar);\n    };\n\n    BootstrapReporterView.prototype._handleRunnerStart = function (event, reporter) {\n        var topLevelData;\n\n        // create top level suite list navigation\n        this._createSuiteList(reporter.suites, reporter.sortedNames, reporter.totalSpecCount);\n\n        // highlight the current suite\n        topLevelData = reporter.activeSuite ? this._topLevelSuiteMap[reporter.activeSuite] : null;\n\n        if (topLevelData) {\n            topLevelData.$listItem.toggleClass(\"active\", true);\n        }\n\n        if (reporter.activeSpecCount) {\n            this._showProgressBar();\n\n            // display current running test\n            this.$info = $('<div class=\"alert alert-info\"/>');\n            this.$resultsContainer.append(this.$info);\n            this.$resultsContainer.append($('<hr/>'));\n        }\n    };\n\n    BootstrapReporterView.prototype._handleRunnerEnd = function (event, reporter) {\n        if (this.$info) {\n            this.$info.toggleClass(\"alert-info\", false);\n\n            if (reporter.passed) {\n                this.$info.toggleClass(\"alert-success\", true).text(\"Complete. No failures.\");\n            } else {\n                this.$info.toggleClass(\"alert-error\", true).text(\"Complete. See failures.\");\n            }\n        }\n    };\n\n    BootstrapReporterView.prototype._handleSuiteEnd = function (event, reporter, suiteData) {\n        var data = this._topLevelSuiteMap[suiteData.name];\n        if ((suiteData.name === reporter.activeSuite) && data) {\n            data.$badgeAll.hide();\n        }\n    };\n\n    BootstrapReporterView.prototype._handleSpecStart = function (event, reporter, specName) {\n        this.$info.text(\"Running \" + specName);\n    };\n\n    BootstrapReporterView.prototype._updateSuiteStatus = function (name, specCount, passedCount, failedCount) {\n        var data = this._topLevelSuiteMap[name];\n\n        if (!data) {\n            return;\n        }\n\n        // update status badges\n        if (passedCount) {\n            data.$badgePassed.show().text(passedCount);\n        } else {\n            data.$badgePassed.hide();\n        }\n\n        if (failedCount) {\n            data.$badgeFailed.show().text(failedCount);\n        } else {\n            data.$badgeFailed.hide();\n        }\n\n        var specsRemaining = specCount - passedCount - failedCount;\n\n        if (specsRemaining === 0) {\n            data.$badgeAll.hide();\n        } else {\n            data.$badgeAll.text(specsRemaining);\n        }\n    };\n\n    BootstrapReporterView.prototype._createRows = function (record, level) {\n        var rows = [],\n            $row,\n            indent = \"\",\n            i,\n            self = this;\n\n        level = (level || 0);\n\n        for (i = 0; i < level; i++) {\n            indent = indent.concat(\"&nbsp;&nbsp;&nbsp;\");\n        }\n\n        if (level > 0) {\n            indent = indent.concat(\"•&nbsp;\");\n        } else if (record.children) {\n            indent = \"»&nbsp;\".concat(indent);\n        }\n\n        $row = $(\"<tr/>\");\n        $row.append($(\"<td>\" + indent + record.name + \"</td><td>\" + record.value + \"</td>\"));\n\n        rows.push($row);\n\n        if (record.children) {\n            level++;\n            record.children.forEach(function (child) {\n                Array.prototype.push.apply(rows, self._createRows(child, level));\n            });\n        }\n\n        return rows;\n    };\n\n    BootstrapReporterView.prototype._handleSpecEnd = function (event, reporter, specData, suiteData) {\n        var $specLink,\n            $resultDisplay,\n            self = this;\n\n        this._updateSuiteStatus(suiteData.name, suiteData.specCount, suiteData.passedCount, suiteData.failedCount);\n        this._updateSuiteStatus(\"All\", reporter.totalSpecCount, reporter.totalPassedCount, reporter.totalFailedCount);\n\n        this.$progress.css(\"width\", Math.round((reporter.activeSpecCompleteCount / reporter.activeSpecCount) * 100) + \"%\");\n\n        if (!specData.passed) {\n            // print suite name if not present\n            var $suiteHeader = $(\"#suite-results-\" + suiteData.id);\n\n            if ($suiteHeader.length === 0) {\n                this.$resultsContainer.append($('<div id=\"suite-results-' + suiteData.id + '\" class=\"alert alert-info\"/>').text(suiteData.name));\n            }\n\n            // print spec name\n            $specLink = $('<a href=\"?spec=' + encodeURIComponent(specData.name) + '\"/>').text(specData.description);\n            $resultDisplay = $('<div class=\"alert alert-error\"/>').append($specLink);\n\n            // print failure details\n            if (specData.messages) {\n                specData.messages.forEach(function (message) {\n                    // Render with clickable links if parent Brackets window available; plain text otherwise\n                    if (window.opener) {\n                        var htmlMessage = self._linkerizeStack(message);\n                        $resultDisplay.append($('<pre/>').html(htmlMessage));\n                    } else {\n                        $resultDisplay.append($('<pre/>').text(message));\n                    }\n                });\n            }\n\n            $resultDisplay.on(\"click\", \".link-to-source\", this._handleSourceLinkClick.bind(this));\n\n            this.$resultsContainer.append($resultDisplay);\n        }\n\n        if (specData.passed && specData.perf) {\n            // add spec name\n            $specLink = $('<a href=\"?spec=' + encodeURIComponent(specData.name) + '\"/>').text(specData.name);\n            this.$resultsContainer.append($('<div class=\"alert alert-info\"/>').append($specLink));\n\n            // add table\n            var $table = $('<table class=\"table table-striped table-bordered table-condensed\"><thead><tr><th>Measurement</th><th>Value</th></tr></thead></table>'),\n                $tbody = $table.append($('<tbody/>')),\n                rows,\n                specRecords = specData.perf;\n\n            this.$resultsContainer.append($table);\n\n            specRecords.forEach(function (record) {\n                rows = self._createRows(record);\n\n                rows.forEach(function (row) {\n                    $tbody.append(row);\n                });\n            });\n        }\n    };\n\n\n    var _codeRefRegExp = /file:\\/\\/.*?:(\\d+):(\\d+)/g;  // matches file:// followed by two :-prefixed numbers, all on the same line\n\n    /**\n     * Given a plaintext stack trace, returns an HTML version where all source file references are .link-to-source links\n     * @param {!string} text\n     * @return {!string} HTML\n     */\n    BootstrapReporterView.prototype._linkerizeStack = function (text) {\n        var html = \"\",\n            indexAfterLastMatch = 0,  // index into 'text'\n            plainText,\n            match;\n\n        // We'll style links to Jasmine code less prominently (vs. test spec code / core Brackets code)\n        function isTestFrameworkCode() {\n            return match[0].indexOf(\"/jasmine-core/\") !== -1;\n        }\n\n        while ((match = _codeRefRegExp.exec(text)) !== null) {\n            // Add any plain text before the link\n            plainText = text.substring(indexAfterLastMatch, match.index);\n            html += _.escape(plainText);\n\n            // Create a clickable link for the file\n            var line = match[1], ch = match[2];\n            var cssClasses = \"link-to-source\";\n            if (isTestFrameworkCode()) {\n                cssClasses += \" testframework-link\";\n            }\n            var linkPrefix = \"<a href='#' class='\" + cssClasses + \"' data-line='\" + line + \"' data-ch='\" + ch + \"'>\";\n            html += linkPrefix + _.escape(match[0]) + \"</a>\";\n\n            indexAfterLastMatch = match.index + match[0].length;\n        }\n\n        // Add any trailing plain text after last link\n        plainText = text.substring(indexAfterLastMatch);\n        html += _.escape(plainText);\n\n        return html;\n    };\n\n    /** Handles links generated by _linkerizeStack(), opening the source file in our parent Brackets window */\n    BootstrapReporterView.prototype._handleSourceLinkClick = function (event) {\n        var CommandManager = window.opener.brackets.getModule(\"command/CommandManager\"),\n            Commands       = window.opener.brackets.getModule(\"command/Commands\"),\n            EditorManager  = window.opener.brackets.getModule(\"editor/EditorManager\"),\n            ProjectManager = window.opener.brackets.getModule(\"project/ProjectManager\"),\n            FileUtils      = window.opener.brackets.getModule(\"file/FileUtils\");\n\n        var uri = $(event.target).text(),\n            lineData = $(event.target).attr(\"data-line\"),\n            chData   = $(event.target).attr(\"data-ch\"),\n            lineNum = parseInt(lineData, 10) - 1,\n            chNum   = parseInt(chData,   10) - 1;\n\n        // Remove file:// prefix and :line:ch suffix, then convert that \"clean\" URI to a native path\n        var path = uri.substring(\"file://\".length, uri.length - lineData.length - chData.length - 2);\n        if (path.indexOf(\"localhost\") === 0) {      // Macs also bizarrely prepend the URI with \"localhost\"\n            path = path.substring(\"localhost\".length);\n        }\n        path = FileUtils.convertToNativePath(path);\n\n        // Convert from symlinked path to real path - otherwise Brackets will think they are two separate files.\n        // Note: we assume the current project open in our parent Brackets window is the Brackets source\n        var bracketsRoot = FileUtils.getNativeBracketsDirectoryPath();\n        if (bracketsRoot.substr(bracketsRoot.length - 4) === \"/src\") {\n            var symlinkPrefix = bracketsRoot.substring(0, bracketsRoot.length - 3);  // include trailing \"/\"\n            if (path.indexOf(symlinkPrefix) === 0) {\n                var realPrefix = ProjectManager.getProjectRoot().fullPath;\n                path = realPrefix + path.substring(symlinkPrefix.length);\n            }\n        }\n\n        // Open file in parent Brackets window & jump cursor to indicated pos\n        // TODO: can we bring the Brackets window to the front?\n        CommandManager.execute(Commands.FILE_OPEN, {fullPath: path})\n            .done(function (doc) {\n                EditorManager.getCurrentFullEditor().setCursorPos(lineNum, chNum, true);\n            });\n    };\n\n\n    BootstrapReporterView.prototype.log = function (str) {\n    };\n\n    exports.BootstrapReporterView = BootstrapReporterView;\n});\n"
  },
  {
    "path": "test/PerformanceTestSuite.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    'use strict';\n\n    // Each suite or spec must have this.category === \"performance\" to be filtered properly\n    require(\"perf/Performance-test\");\n});\n"
  },
  {
    "path": "test/SpecRunner.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n  \"http://www.w3.org/TR/html4/loose.dtd\">\n\n<!--\n  Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n   \n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the \"Software\"),\n  to deal in the Software without restriction, including without limitation\n  the rights to use, copy, modify, merge, publish, distribute, sublicense,\n  and/or sell copies of the Software, and to permit persons to whom the\n  Software is furnished to do so, subject to the following conditions:\n   \n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n   \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n  DEALINGS IN THE SOFTWARE.\n-->\n\n<html>\n<head>\n  <title>Jasmine Spec Runner</title>\n\n  <link href=\"thirdparty/bootstrap2/css/bootstrap.min.css\" rel=\"stylesheet\">\n  <link href=\"thirdparty/bootstrap2/css/bootstrap-responsive.min.css\" rel=\"stylesheet\">\n  <link href=\"BootstrapReporterView.css\" rel=\"stylesheet\">\n\n  <script src=\"thirdparty/jasmine-core/jasmine.js\"></script>\n\n  <!-- Pre-load third party scripts that cannot be async loaded. -->\n  <!-- Keep in sync with Gruntfile.js jasmine vendor dependencies -->\n  <script src=\"../src/thirdparty/jquery-2.1.3.min.js\"></script>\n  <script src=\"../src/thirdparty/less.min.js\"></script>\n  <script src=\"thirdparty/bootstrap2/js/bootstrap.min.js\"></script>\n\n  <!-- All other scripts are loaded through require. -->\n  <script src=\"../src/thirdparty/requirejs/require.js\" data-main=\"SpecRunner\"></script>\n\n</head>\n\n<body>\n    <div class=\"navbar navbar-fixed-top\">\n      <div class=\"navbar-inner\">\n        <div class=\"container\">\n          <a class=\"btn btn-navbar\" data-toggle=\"collapse\" data-target=\".nav-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </a>\n          <a class=\"brand\" href=\"#\">Brackets Tests</a>\n          <div class=\"nav-collapse\">\n            <ul class=\"nav\">\n              <li><a id=\"all\" href=\"?suite=all\">All</a></li>\n              <li><a id=\"unit\" href=\"?suite=unit\">Unit</a></li>\n              <li><a id=\"integration\" href=\"?suite=integration\">Integration</a></li>\n              <li><a id=\"livepreview\" href=\"?suite=livepreview\">Live&nbsp;Preview</a></li>\n              <li><a id=\"mainview\"    href=\"?suite=mainview\">Main&nbsp;View</a></li>\n              <li><a id=\"performance\" href=\"?suite=performance\">Performance</a></li>\n              <li><a id=\"extension\" href=\"?suite=extension\">Extensions</a></li>\n              <li><a id=\"reload\" href=\"#\">Reload</a></li>\n              <li><a id=\"show-dev-tools\" href=\"#\">Show&nbsp;Developer&nbsp;Tools</a></li>\n            </ul>\n          </div>\n        </div>\n      </div>\n    </div>\n    <div id=\"mock-main-view\" style=\"position:absolute; height:1000px; width:1000px; left:-10000px; top:-10000px;\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "test/SpecRunner.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global beforeEach, afterEach, beforeFirst, afterLast, jasmine */\n\n// Set the baseUrl to brackets/src\nrequire.config({\n    baseUrl: \"../src\",\n    paths: {\n        \"test\"                          : \"../test\",\n        \"perf\"                          : \"../test/perf\",\n        \"spec\"                          : \"../test/spec\",\n        \"text\"                          : \"thirdparty/text/text\",\n        \"i18n\"                          : \"thirdparty/i18n/i18n\",\n        \"fileSystemImpl\"                : \"filesystem/impls/appshell/AppshellFileSystem\",\n        \"preferences/PreferencesImpl\"   : \"../test/TestPreferencesImpl\",\n        \"preact-compat\"                 : \"thirdparty/preact-compat/preact-compat.min\",\n        \"preact\"                        : \"thirdparty/preact/preact\",\n        \"preact-test-utils\"             : \"thirdparty/preact-test-utils/preact-test-utils\",\n        \"simulate-event\"                : \"thirdparty/simulate-event/simulate-event\",\n        \"xtend\"                         : \"thirdparty/xtend\"\n    },\n    map: {\n        \"*\": {\n            \"thirdparty/preact\"            : \"preact-compat\",\n            \"thirdparty/preact-test-utils\" : \"preact-test-utils\"\n        }\n    }\n});\n\ndefine(function (require, exports, module) {\n    'use strict';\n\n    // Utility dependencies\n    var AppInit                 = require(\"utils/AppInit\"),\n        SpecRunnerUtils         = require(\"spec/SpecRunnerUtils\"),\n        ExtensionLoader         = require(\"utils/ExtensionLoader\"),\n        Async                   = require(\"utils/Async\"),\n        FileSystem              = require(\"filesystem/FileSystem\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        UrlParams               = require(\"utils/UrlParams\").UrlParams,\n        UnitTestReporter        = require(\"test/UnitTestReporter\").UnitTestReporter,\n        NodeConnection          = require(\"utils/NodeConnection\"),\n        BootstrapReporterView   = require(\"test/BootstrapReporterView\").BootstrapReporterView,\n        NativeApp               = require(\"utils/NativeApp\");\n\n    // Load modules for later use\n    require(\"language/CodeInspection\");\n    require(\"thirdparty/lodash\");\n    require(\"editor/CodeHintManager\");\n    require(\"utils/Global\");\n    require(\"command/Menus\");\n    require(\"utils/NodeDomain\");\n    require(\"utils/ColorUtils\");\n    require(\"preferences/PreferencesBase\");\n    require(\"JSUtils/Session\");\n    require(\"JSUtils/ScopeManager\");\n    require(\"widgets/InlineMenu\");\n\n    // Load modules that self-register and just need to get included in the test-runner window\n    require(\"document/ChangedDocumentTracker\");\n\n    // TODO (#2155): These are used by extensions via brackets.getModule(), so tests that run those\n    // extensions need these to be required up front. We need a better solution for this eventually.\n    require(\"utils/ExtensionUtils\");\n\n    // Load both top-level suites. Filtering is applied at the top-level as a filter to BootstrapReporter.\n    require(\"test/UnitTestSuite\");\n    require(\"test/PerformanceTestSuite\");\n\n    // Load JUnitXMLReporter\n    require(\"test/thirdparty/jasmine-reporters/jasmine.junit_reporter\");\n\n    // Load CodeMirror add-ons--these attach themselves to the CodeMirror module\n    require(\"thirdparty/CodeMirror/addon/fold/xml-fold\");\n    require(\"thirdparty/CodeMirror/addon/edit/matchtags\");\n    require(\"thirdparty/CodeMirror/addon/edit/matchbrackets\");\n    require(\"thirdparty/CodeMirror/addon/edit/closebrackets\");\n    require(\"thirdparty/CodeMirror/addon/edit/closetag\");\n    require(\"thirdparty/CodeMirror/addon/selection/active-line\");\n    require(\"thirdparty/CodeMirror/addon/mode/multiplex\");\n    require(\"thirdparty/CodeMirror/addon/mode/overlay\");\n    require(\"thirdparty/CodeMirror/addon/search/searchcursor\");\n    require(\"thirdparty/CodeMirror/keymap/sublime\");\n    \n    //load Language Tools Module\n    require(\"languageTools/PathConverters\");\n    require(\"languageTools/LanguageTools\");\n    require(\"languageTools/ClientLoader\");\n    require(\"languageTools/BracketsToNodeInterface\");\n    require(\"languageTools/DefaultProviders\");\n    require(\"languageTools/DefaultEventHandlers\");\n\n\t//load language features\n    require(\"features/ParameterHintsManager\");\n    require(\"features/JumpToDefManager\");\n\n    var selectedSuites,\n        params          = new UrlParams(),\n        reporter,\n        reporterView,\n        _writeResults   = new $.Deferred(),\n        resultsPath;\n\n    /**\n     * @const\n     * Amount of time to wait before automatically rejecting the connection\n     * deferred. If we hit this timeout, we'll never have a node connection\n     * for the installer in this run of Brackets.\n     */\n    var NODE_CONNECTION_TIMEOUT = 30000; // 30 seconds - TODO: share with StaticServer?\n\n    // parse URL parameters\n    params.parse();\n    resultsPath = params.get(\"resultsPath\");\n\n    function _loadExtensionTests() {\n        // augment jasmine to identify extension unit tests\n        var addSuite = jasmine.Runner.prototype.addSuite;\n        jasmine.Runner.prototype.addSuite = function (suite) {\n            suite.category = \"extension\";\n            addSuite.call(this, suite);\n        };\n\n        var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(),\n            paths = [\"default\"];\n\n        // load dev and user extensions only when running the extension test suite\n        if (selectedSuites.indexOf(\"extension\") >= 0) {\n            paths.push(\"dev\");\n            paths.push(ExtensionLoader.getUserExtensionPath());\n        }\n\n        // This returns path to test folder, so convert to src\n        bracketsPath = bracketsPath.replace(/\\/test$/, \"/src\");\n\n        return Async.doInParallel(paths, function (dir) {\n            var extensionPath = dir;\n\n            // If the item has \"/\" in it, assume it is a full path. Otherwise, load\n            // from our source path + \"/extensions/\".\n            if (dir.indexOf(\"/\") === -1) {\n                extensionPath = bracketsPath + \"/extensions/\" + dir;\n            }\n\n            return ExtensionLoader.testAllExtensionsInNativeDirectory(extensionPath);\n        });\n    }\n\n    function _documentReadyHandler() {\n        if (brackets.app.showDeveloperTools) {\n            $(\"#show-dev-tools\").click(function () {\n                brackets.app.showDeveloperTools();\n            });\n        } else {\n            $(\"#show-dev-tools\").remove();\n        }\n\n        $(\"#reload\").click(function () {\n            window.location.reload(true);\n        });\n\n        if (selectedSuites.length === 1) {\n            $(\"#\" + (selectedSuites[0])).closest(\"li\").toggleClass(\"active\", true);\n        }\n\n        AppInit._dispatchReady(AppInit.APP_READY);\n\n        jasmine.getEnv().execute();\n    }\n\n    function writeResults(path, text) {\n        // check if the file already exists\n        var file = FileSystem.getFileForPath(path);\n\n        file.exists(function (err, exists) {\n            if (err) {\n                _writeResults.reject(err);\n                return;\n            }\n\n            if (exists) {\n                // file exists, do not overwrite\n                _writeResults.reject();\n            } else {\n                // file not found, write the new file with xml content\n                FileUtils.writeText(file, text)\n                    .done(function () {\n                        _writeResults.resolve();\n                    })\n                    .fail(function (err) {\n                        _writeResults.reject(err);\n                    });\n            }\n        });\n    }\n\n    /**\n     * Listener for UnitTestReporter \"runnerEnd\" event. Attached only if\n     * \"resultsPath\" URL parameter exists. Does not overwrite existing file.\n     *\n     * @param {!$.Event} event\n     * @param {!UnitTestReporter} reporter\n     */\n    function _runnerEndHandler(event, reporter) {\n        if (resultsPath && resultsPath.substr(-5) === \".json\") {\n            writeResults(resultsPath, reporter.toJSON());\n        }\n\n        _writeResults.always(function () { brackets.app.quit(); });\n    }\n\n    /**\n     * Patch JUnitXMLReporter to use FileSystem and to consolidate all results\n     * into a single file.\n     */\n    function _patchJUnitReporter() {\n        jasmine.JUnitXmlReporter.prototype.reportSpecResultsOriginal = jasmine.JUnitXmlReporter.prototype.reportSpecResults;\n        jasmine.JUnitXmlReporter.prototype.getNestedOutputOriginal = jasmine.JUnitXmlReporter.prototype.getNestedOutput;\n\n        jasmine.JUnitXmlReporter.prototype.reportSpecResults = function (spec) {\n            if (spec.results().skipped) {\n                return;\n            }\n\n            this.reportSpecResultsOriginal(spec);\n        };\n\n        jasmine.JUnitXmlReporter.prototype.getNestedOutput = function (suite) {\n            if (suite.results().totalCount === 0) {\n                return \"\";\n            }\n\n            return this.getNestedOutputOriginal(suite);\n        };\n\n        jasmine.JUnitXmlReporter.prototype.reportRunnerResults = function (runner) {\n            var suites = runner.suites(),\n                output = '<?xml version=\"1.0\" encoding=\"UTF-8\" ?>',\n                i;\n\n            output += \"\\n<testsuites>\";\n\n            for (i = 0; i < suites.length; i++) {\n                var suite = suites[i];\n                if (!suite.parentSuite) {\n                    output += this.getNestedOutput(suite);\n                }\n            }\n\n            output += \"\\n</testsuites>\";\n            writeResults(resultsPath, output);\n\n            // When all done, make it known on JUnitXmlReporter\n            jasmine.JUnitXmlReporter.finished_at = (new Date()).getTime();\n        };\n\n        jasmine.JUnitXmlReporter.prototype.writeFile = function (path, filename, text) {\n            // do nothing\n        };\n    }\n\n    function _registerBeforeAfterHandlers() {\n        // Initiailize unit test preferences for each spec\n        beforeEach(function () {\n            // Unique key for unit testing\n            window.localStorage.setItem(\"preferencesKey\", SpecRunnerUtils.TEST_PREFERENCES_KEY);\n\n            // Reset preferences from previous test runs\n            window.localStorage.removeItem(\"doLoadPreferences\");\n            window.localStorage.removeItem(SpecRunnerUtils.TEST_PREFERENCES_KEY);\n\n            SpecRunnerUtils.runBeforeFirst();\n        });\n\n        // Revert unit test preferences after each spec\n        afterEach(function () {\n            // Clean up preferencesKey\n            window.localStorage.removeItem(\"preferencesKey\");\n\n            SpecRunnerUtils.runAfterLast();\n        });\n\n        // Delete temp folder before running the first test\n        beforeFirst(function () {\n            SpecRunnerUtils.removeTempDirectory();\n        });\n\n        // Delete temp folder after running the last test\n        afterLast(function () {\n            SpecRunnerUtils.removeTempDirectory();\n        });\n    }\n\n    function init() {\n        selectedSuites = (params.get(\"suite\") || window.localStorage.getItem(\"SpecRunner.suite\") || \"unit\").split(\",\");\n\n        // Create a top-level filter to show/hide performance and extensions tests\n        var runAll = (selectedSuites.indexOf(\"all\") >= 0);\n\n        var topLevelFilter = function (spec) {\n            // special case \"all\" suite to run unit, perf, extension, and integration tests\n            if (runAll) {\n                return true;\n            }\n\n            var currentSuite = spec.suite,\n                category = spec.category;\n\n            if (!category) {\n                // find the category from the closest suite\n                while (currentSuite) {\n                    if (currentSuite.category) {\n                        category = currentSuite.category;\n                        break;\n                    }\n\n                    currentSuite = currentSuite.parentSuite;\n                }\n            }\n\n            // if unit tests are selected, make sure there is no category in the heirarchy\n            // if not a unit test, make sure the category is selected\n            return (selectedSuites.indexOf(\"unit\") >= 0 && category === undefined) ||\n                (selectedSuites.indexOf(category) >= 0);\n        };\n\n        /*\n         * TODO (jason-sanjose): extension unit tests should only load the\n         * extension and the extensions dependencies. We should not load\n         * unrelated extensions. Currently, this solution is all or nothing.\n         */\n\n        // configure spawned test windows to load extensions\n        SpecRunnerUtils.setLoadExtensionsInTestWindow(selectedSuites.indexOf(\"extension\") >= 0);\n\n        _loadExtensionTests(selectedSuites).always(function () {\n            var jasmineEnv = jasmine.getEnv();\n            jasmineEnv.updateInterval = 1000;\n\n            _registerBeforeAfterHandlers();\n\n            // Create the reporter, which is really a model class that just gathers\n            // spec and performance data.\n            reporter = new UnitTestReporter(jasmineEnv, topLevelFilter, params.get(\"spec\"));\n            SpecRunnerUtils.setUnitTestReporter(reporter);\n\n            // Optionally emit JUnit XML file for automated runs\n            if (resultsPath) {\n                if (resultsPath.substr(-4) === \".xml\") {\n                    _patchJUnitReporter();\n                    jasmineEnv.addReporter(new jasmine.JUnitXmlReporter(null, true, false));\n                }\n\n                // Close the window\n                $(reporter).on(\"runnerEnd\", _runnerEndHandler);\n            } else {\n                _writeResults.resolve();\n            }\n\n            jasmineEnv.addReporter(reporter);\n\n            // Create the view that displays the data from the reporter. (Usually in\n            // Jasmine this is part of the reporter, but we separate them out so that\n            // we can more easily grab just the model data for output during automatic\n            // testing.)\n            reporterView = new BootstrapReporterView(window.document, reporter);\n\n            // remember the suite for the next unit test window launch\n            window.localStorage.setItem(\"SpecRunner.suite\", selectedSuites);\n\n            $(window.document).ready(_documentReadyHandler);\n        });\n\n\n        // Prevent clicks on any link from navigating to a different page (which could lose unsaved\n        // changes). We can't use a simple .on(\"click\", \"a\") because of http://bugs.jquery.com/ticket/3861:\n        // jQuery hides non-left clicks from such event handlers, yet middle-clicks still cause CEF to\n        // navigate. Also, a capture handler is more reliable than bubble.\n        window.document.body.addEventListener(\"click\", function (e) {\n            // Check parents too, in case link has inline formatting tags\n            var node = e.target, url;\n\n            while (node) {\n                if (node.tagName === \"A\") {\n                    url = node.getAttribute(\"href\");\n                    if (url && url.match(/^http/)) {\n                        NativeApp.openURLInDefaultBrowser(url);\n                        e.preventDefault();\n                    }\n                    break;\n                }\n                node = node.parentElement;\n            }\n        }, true);\n    }\n\n    function connectToTestDomain() {\n        var _nodeConnectionDeferred = new $.Deferred(),\n            _nodeConnection = new NodeConnection();\n\n        _nodeConnection.connect(true).then(function () {\n            var domainPath = FileUtils.getNativeBracketsDirectoryPath() + \"/\" + FileUtils.getNativeModuleDirectoryPath(module) + \"/../test/node/TestingDomain\";\n\n            _nodeConnection.loadDomains(domainPath, true)\n                .then(init, function () {\n                    // Failed to connect\n                    console.error(\"[SpecRunner] Failed to connect to node\", arguments);\n\n                    var container = $('<div class=\"container-fluid\">');\n                    container.append('<div class=\"alert alert-error\">Failed to connect to Node</div>');\n\n                    $(window.document.body).append(container);\n                });\n        });\n\n        Async.withTimeout(_nodeConnectionDeferred.promise(), NODE_CONNECTION_TIMEOUT);\n\n        brackets.testing = { nodeConnection: _nodeConnection };\n    }\n\n    connectToTestDomain();\n});\n"
  },
  {
    "path": "test/TestPreferencesImpl.js",
    "content": "/*\n * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Generates the fully configured preferences systems used IN TESTING. This configuration does\n * not manipulate the user's preferences.\n */\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var PreferencesBase = require(\"./PreferencesBase\"),\n\n        // The SETTINGS_FILENAME is used with a preceding \".\" within user projects\n        SETTINGS_FILENAME = \"brackets.json\",\n        STATE_FILENAME    = \"state.json\",\n\n        // User-level preferences\n        userPrefFile = null;\n\n    /**\n     * A deferred object which is used to indicate PreferenceManager readiness during the start-up.\n     * @private\n     * @type {$.Deferred}\n     */\n    var _prefManagerReadyDeferred = new $.Deferred();\n\n    /**\n     * A boolean property indicating if the user scope configuration file is malformed.\n     */\n    var userScopeCorrupt = false;\n\n    function isUserScopeCorrupt() {\n        return userScopeCorrupt;\n    }\n\n    var manager = new PreferencesBase.PreferencesSystem();\n    manager.pauseChangeEvents();\n\n    // Create a Project scope\n    var projectStorage          = new PreferencesBase.FileStorage(undefined, true),\n        projectScope            = new PreferencesBase.Scope(projectStorage),\n        projectPathLayer        = new PreferencesBase.PathLayer(),\n        projectLanguageLayer    = new PreferencesBase.LanguageLayer();\n\n    projectScope.addLayer(projectPathLayer);\n    projectScope.addLayer(projectLanguageLayer);\n\n    var userScope           = new PreferencesBase.Scope(new PreferencesBase.MemoryStorage()),\n        userPathLayer       = new PreferencesBase.PathLayer(),\n        userLanguageLayer   = new PreferencesBase.LanguageLayer();\n\n    userScope.addLayer(userPathLayer);\n    userScope.addLayer(userLanguageLayer);\n\n    var userScopeLoading = manager.addScope(\"user\", userScope);\n\n    // Set up the .brackets.json file handling\n    manager.addScope(\"project\", projectScope, {\n        before: \"user\"\n    });\n\n    // Session Scope is for storing prefs in memory only but with the highest precedence.\n    manager.addScope(\"session\", new PreferencesBase.MemoryStorage());\n\n    // Memory storages take no time to initialize\n    _prefManagerReadyDeferred.resolve();\n\n    // \"State\" is stored like preferences but it is not generally intended to be user-editable.\n    // It's for more internal, implicit things like window size, working set, etc.\n    var stateManager = new PreferencesBase.PreferencesSystem();\n    var smUserScope = new PreferencesBase.Scope(new PreferencesBase.MemoryStorage());\n    var stateProjectLayer = new PreferencesBase.ProjectLayer();\n    smUserScope.addLayer(stateProjectLayer);\n    var smUserScopeLoading = stateManager.addScope(\"user\", smUserScope);\n\n    function _reloadUserPrefs() {\n        return;\n    }\n\n    // Semi-Public API. Use this at your own risk. The public API is in PreferencesManager.\n    exports.manager             = manager;\n    exports.projectStorage      = projectStorage;\n    exports.projectPathLayer    = projectPathLayer;\n    exports.userScopeLoading    = userScopeLoading;\n    exports.stateManager        = stateManager;\n    exports.stateProjectLayer   = stateProjectLayer;\n    exports.smUserScopeLoading  = smUserScopeLoading;\n    exports.userPrefFile        = userPrefFile;\n    exports.isUserScopeCorrupt  = isUserScopeCorrupt;\n    exports.managerReady        = _prefManagerReadyDeferred.promise();\n    exports.reloadUserPrefs    = _reloadUserPrefs;\n    exports.STATE_FILENAME      = STATE_FILENAME;\n    exports.SETTINGS_FILENAME   = SETTINGS_FILENAME;\n});\n"
  },
  {
    "path": "test/UnitTestReporter.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * A Jasmine reporter that summarizes test results data:\n *  - summarizes the results for each top-level suite (instead of flattening out all suites)\n *  - counts the number of passed/failed specs instead of counting each expect()\n *  - tracks performance data for tests that want to log it\n * and rebroadcasts the summarized results to the reporter view, as well as serializing the data\n * to JSON.\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    var SpecRunnerUtils = require(\"spec/SpecRunnerUtils\"),\n        BuildInfoUtils = require(\"utils/BuildInfoUtils\");\n\n    // make sure the global brackets variable is loaded\n    require(\"utils/Global\");\n\n    var activeReporter;\n\n    /**\n     * @constructor\n     * Creates a UnitTestReporter object. This has a number public properties:\n     *\n     * suites - an object with entries for each top-level suite; each value is an object containing:\n     *    name - the full name of the suite\n     *    specCount - number of specs in the suite and its descendants\n     *    passedCount - number of passed specs in the suite and its descendants\n     *    failedCount - number of failed specs in the suite and its descendants\n     *    specs - an array of results for each spec; each result is an object containing:\n     *        name - the full name of the spec\n     *        passed - true if the spec passed, false otherwise\n     *        messages - if defined, an array of message objects for the failed spec\n     *        perf - if defined, the performance record for the spec\n     *\n     * passed - true if all specs passed, false otherwise\n     * sortedNames - a sorted list of suite names (including all the keys in the suites object except All).\n     * activeSuite - the suite currently selected in the URL params, \"all\" if all are being run, and null if no tests are being run.\n     * activeSpecCount - the number of specs that will actually be run given the current filter\n     * activeSpecCompleteCount - the number of specs that have been run so far\n     * totalSpecCount - the total number of specs (ignoring filter)\n     * totalPassedCount - the total number of specs passed across all suites\n     * totalFailedCount - the total number of specs failed across all suites\n     *\n     * runInfo - an object containing info about the current run:\n     *     app - name of the app\n     *     version - version number\n     *     branch - branch the current build is running on\n     *     sha - sha of the current build\n     *     platform - platform of the current run\n     *     startTime - time the run was started\n     *     endTime - time the run finished\n     *\n     * @param {!Object} env The Jasmine environment we're running in.\n     * @param {Function} filter The filter being used to determine whether a given spec is run or not.\n     * @param {string} activeSuite The suite currently selected in the URL params, or null if all are being run.\n     */\n    function UnitTestReporter(env, filter, activeSuite) {\n        var self = this;\n\n        this.activeSuite = activeSuite;\n\n        this.runInfo = {\n            app: brackets.metadata.name,\n            version: brackets.metadata.version,\n            platform: brackets.platform\n        };\n        BuildInfoUtils.getBracketsSHA().done(function (branch, sha) {\n            self.runInfo.branch = branch;\n            self.runInfo.sha = sha;\n        });\n\n        // _topLevelFilter is applied first - selects Performance vs. Unit test suites\n        this._topLevelFilter = filter;\n\n        // Jasmine's runner uses the specFilter to choose which tests to run.\n        // If you selected an option other than \"All\" this will be a subset of all tests loaded.\n        env.specFilter = this._createSpecFilter(this.activeSuite);\n\n        this.suites = {};\n        this.passed = false;\n\n        this.totalSpecCount = 0;\n        this.totalPassedCount = 0;\n        this.totalFailedCount = 0;\n        env.currentRunner().topLevelSuites().forEach(function (suite) {\n            var specCount = self._countSpecs(suite, filter);\n            self.suites[suite.getFullName()] = {\n                id: suite.id,\n                name: suite.getFullName(),\n                specCount: specCount,\n                passedCount: 0,\n                failedCount: 0,\n                specs: []\n            };\n            self.totalSpecCount += specCount;\n        });\n\n        this.sortedNames = Object.keys(this.suites).sort(function (a, b) {\n            a = a.toLowerCase();\n            b = b.toLowerCase();\n            if (a < b) {\n                return -1;\n            } else if (a > b) {\n                return 1;\n            }\n            return 0;\n        });\n\n        this.activeSpecCount = 0;\n        this.activeSpecCompleteCount = 0;\n\n        env.currentRunner().specs().forEach(function (spec, index) {\n            if (env.specFilter(spec)) {\n                self.activeSpecCount++;\n            }\n        });\n    }\n\n    /**\n     * @private\n     * Filters specs by full name. Applies _topLevelFilter first before checking\n     * for a matching starting substring.\n     */\n    UnitTestReporter.prototype._createSpecFilter = function (filterString) {\n        var self = this,\n            filter = filterString ? filterString.toLowerCase() : undefined;\n\n        return function (spec) {\n            // filterString is undefined when no top-level suite is active (e.g. \"All\", \"HTMLUtils\", etc.)\n            // When undefined, all specs fail this filter and no tests are ran. This is by design.\n            // This setup allows the SpecRunner to load initially without automatically running all tests.\n            if (filter === undefined) {\n                return false;\n            }\n\n            if (!self._topLevelFilter(spec)) {\n                return false;\n            }\n\n            if (filter === \"all\") {\n                return true;\n            }\n\n            if (filter === spec.getFullName().toLowerCase()) {\n                return true;\n            }\n\n            // spec.getFullName() concatenates the names of all containing describe()s. We want to filter\n            // on just the outermost suite's name (i.e., the item that was selected in the spec list UI)\n            // to avoid ambiguity when suite names share the same prefix.\n            var topLevelSuite = spec.suite;\n            while (topLevelSuite.parentSuite) {\n                topLevelSuite = topLevelSuite.parentSuite;\n            }\n\n            return filter === topLevelSuite.description.toLowerCase();\n        };\n    };\n\n    /**\n     * @private\n     *\n     * @param {!jasmine.Suite} suite\n     * @param {Function} filter\n     * @return {Number} count The number of specs in the given suite (and its descendants) that match the filter.\n     */\n    UnitTestReporter.prototype._countSpecs = function (suite, filter) {\n        var count = 0,\n            self = this;\n\n        // count specs attached directly to this suite\n        suite.specs().forEach(function (spec) {\n            if (!filter || filter(spec)) {\n                count++;\n            }\n        });\n\n        // recursively count child suites\n        suite.suites().forEach(function (child) {\n            count += self._countSpecs(child, filter);\n        });\n\n        return count;\n    };\n\n    /**\n     * Returns the name of the top-level suite containing the given spec.\n     * @param {!jasmine.Spec} spec\n     * @return {string} the top level suite name\n     */\n    UnitTestReporter.prototype.getTopLevelSuiteName = function (spec) {\n        var topLevelSuite = spec.suite;\n\n        while (topLevelSuite.parentSuite) {\n            topLevelSuite = topLevelSuite.parentSuite;\n        }\n\n        return topLevelSuite.getFullName();\n    };\n\n    /**\n     * @private\n     * Adds the passed/failed counts and failure messages for the given spec to the data for its top level suite,\n     * and updates the total counts on the All record.\n     * @param {!jasmine.Spec} spec The spec to record\n     * @param {Object} results Jasmine result object for that spec\n     * @return {Object} the spec data for the given spec, listing whether it passed and any\n     * messages/perf data\n     */\n    UnitTestReporter.prototype._addSpecResults = function (spec, results, perfRecord) {\n        var suiteData = this.suites[this.getTopLevelSuiteName(spec)],\n            specData = {\n                name: spec.getFullName(),\n                description: spec.description,\n                passed: results.passed()\n            };\n\n        this.activeSpecCompleteCount++;\n\n        if (specData.passed) {\n            suiteData.passedCount++;\n            this.totalPassedCount++;\n        } else {\n            suiteData.failedCount++;\n            this.totalFailedCount++;\n        }\n\n        results.getItems().forEach(function (item) {\n            var message = SpecRunnerUtils.getResultMessage(item);\n            if (message) {\n                specData.messages = specData.messages || [];\n                specData.messages.push(message);\n            }\n        });\n\n        if (perfRecord && perfRecord.length) {\n            specData.perf = perfRecord;\n        }\n\n        suiteData.specs.push(specData);\n        return specData;\n    };\n\n    /**\n     * Returns a JSON string containing all our public data. See the constructor\n     * docs for a list.\n     * @return {string} the JSON string\n     */\n    UnitTestReporter.prototype.toJSON = function () {\n        var data = {}, prop;\n        for (prop in this) {\n            if (this.hasOwnProperty(prop) && prop.charAt(0) !== \"_\") {\n                data[prop] = this[prop];\n            }\n        }\n        return JSON.stringify(data, null, \"    \");\n    };\n\n    // Handlers for Jasmine callback functions\n\n    UnitTestReporter.prototype.reportRunnerStarting = function (runner) {\n        activeReporter = this;\n        this.runInfo.startTime = new Date().toString();\n        $(this).triggerHandler(\"runnerStart\", [this]);\n    };\n\n    UnitTestReporter.prototype.reportRunnerResults = function (runner) {\n        this.passed = runner.results().passed();\n        this.runInfo.endTime = new Date().toString();\n        $(this).triggerHandler(\"runnerEnd\", [this]);\n        activeReporter = null;\n    };\n\n    UnitTestReporter.prototype.reportSuiteResults = function (suite) {\n        if (suite.parentSuite === null) {\n            $(this).triggerHandler(\"suiteEnd\", [this, this.suites[suite.getFullName()]]);\n        }\n    };\n\n    /**\n     * @private\n     * @param {!Object} spec the Jasmine spec to find the category for\n     * @return {string} the category for the given spec, or null if it has no category\n     */\n    UnitTestReporter.prototype._getCategory = function (spec) {\n        if (spec.category) {\n            return spec.category;\n        } else {\n            var suite = spec.suite;\n            while (suite) {\n                if (suite.category) {\n                    return suite.category;\n                }\n                suite = suite.parentSuite;\n            }\n        }\n        return null;\n    };\n\n    UnitTestReporter.prototype.reportSpecStarting = function (spec) {\n        if (this._getCategory(spec) === \"performance\") {\n            this._currentPerfRecord = [];\n        }\n        $(this).triggerHandler(\"specStart\", [this, spec.getFullName()]);\n    };\n\n    UnitTestReporter.prototype.reportSpecResults = function (spec) {\n        if (!spec.results().skipped) {\n            var specData = this._addSpecResults(spec, spec.results(), this._currentPerfRecord);\n            $(this).triggerHandler(\"specEnd\", [this, specData, this.suites[this.getTopLevelSuiteName(spec)]]);\n        }\n        this._currentPerfRecord = null;\n    };\n\n    // Performance tracking\n\n    UnitTestReporter.prototype._getTestWindowPerf = function () {\n        return SpecRunnerUtils.getTestWindow().brackets.test.PerfUtils;\n    };\n\n    UnitTestReporter.prototype._logTestWindowMeasurement = function (measureInfo) {\n        var value,\n            printName = measureInfo.measure.name || measureInfo.name,\n            record = {},\n            self = this;\n\n        if (measureInfo.measure instanceof RegExp) {\n            value = this._currentPerfUtils.searchData(measureInfo.measure);\n        } else {\n            value = this._currentPerfUtils.getData(measureInfo.measure.id);\n        }\n\n        if (value === undefined) {\n            value = \"(None)\";\n        }\n\n        if (measureInfo.measure.name && measureInfo.name) {\n            printName = measureInfo.measure.name + \" - \" + measureInfo.name;\n        }\n\n        if (measureInfo.operation === \"sum\") {\n            if (Array.isArray(value)) {\n                value = value.reduce(function (a, b) { return a + b; });\n            }\n\n            printName = \"Sum of all \" + printName;\n        }\n\n        record.name = printName;\n        record.value = value;\n\n        if (measureInfo.children) {\n            record.children = [];\n            measureInfo.children.forEach(function (child) {\n                record.children.push(self._logTestWindowMeasurement(child));\n            });\n        }\n\n        return record;\n    };\n\n    /**\n     * Records a performance measurement from the test window for the current running spec.\n     * @param {!(PerfMeasurement|string)} measure A PerfMeasurement or string key to query PerfUtils for metrics.\n     * @param {string} name An optional name or description to print with the measurement name\n     * @param {string} operation An optional operation to perform on the measurement data. Currently supports sum.\n     */\n    UnitTestReporter.prototype.logTestWindow = function (measures, name, operation) {\n        var self = this;\n\n        if (!this._currentPerfRecord) {\n            return;\n        }\n\n        this._currentPerfUtils = this._getTestWindowPerf();\n\n        if (!Array.isArray(measures)) {\n            measures = [{measure: measures, name: name, operation: operation}];\n        }\n\n        measures.forEach(function (measure) {\n            self._currentPerfRecord.push(self._logTestWindowMeasurement(measure));\n        });\n\n        this._currentPerfUtils = null;\n    };\n\n    /**\n     * Clears the current set of performance measurements.\n     */\n    UnitTestReporter.prototype.clearTestWindow = function () {\n        this._getTestWindowPerf().clear();\n    };\n\n    /**\n     * @return The active unit test reporter, or null if no unit test is running.\n     */\n    function getActiveReporter() {\n        return activeReporter;\n    }\n\n    // Exports\n\n    exports.UnitTestReporter = UnitTestReporter;\n    exports.getActiveReporter = getActiveReporter;\n});\n"
  },
  {
    "path": "test/UnitTestSuite.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    require(\"spec/Async-test\");\n    require(\"spec/CodeHint-test\");\n    require(\"spec/CodeHintUtils-test\");\n    require(\"spec/CodeInspection-test\");\n    require(\"spec/CommandManager-test\");\n    require(\"spec/CSSUtils-test\");\n    require(\"spec/CSSInlineEdit-test\");\n    require(\"spec/JSUtils-test\");\n    require(\"spec/Document-test\");\n    require(\"spec/DocumentCommandHandlers-test\");\n    require(\"spec/DocumentManager-test\");\n    require(\"spec/DragAndDrop-test\");\n    require(\"spec/Editor-test\");\n    require(\"spec/EditorRedraw-test\");\n    require(\"spec/EditorCommandHandlers-test\");\n    require(\"spec/EditorOptionHandlers-test\");\n    require(\"spec/EditorManager-test\");\n    require(\"spec/EventDispatcher-test\");\n    require(\"spec/ExtensionInstallation-test\");\n    require(\"spec/ExtensionLoader-test\");\n    require(\"spec/ExtensionManager-test\");\n    require(\"spec/ExtensionUtils-test\");\n    require(\"spec/FileFilters-test\");\n    require(\"spec/FileSystem-test\");\n    require(\"spec/FileTreeView-test\");\n    require(\"spec/FileTreeViewModel-test\");\n    require(\"spec/FileUtils-test\");\n    require(\"spec/FindInFiles-test\");\n    require(\"spec/FindReplace-test\");\n    require(\"spec/HTMLInstrumentation-test\");\n    require(\"spec/HTMLSimpleDOM-test\");\n    require(\"spec/HTMLTokenizer-test\");\n    require(\"spec/InlineEditorProviders-test\");\n    require(\"spec/InstallExtensionDialog-test\");\n    require(\"spec/JSONUtils-test\");\n    require(\"spec/KeyBindingManager-test\");\n    require(\"spec/LanguageManager-test\");\n    require(\"spec/LanguageTools-test\");\n    require(\"spec/LiveDevelopment-test\");\n    require(\"spec/LiveDevelopmentMultiBrowser-test\");\n    require(\"spec/LowLevelFileIO-test\");\n    require(\"spec/MainViewFactory-test\");\n    require(\"spec/MainViewManager-test\");\n    require(\"spec/Menu-test\");\n    require(\"spec/MultiRangeInlineEditor-test\");\n    require(\"spec/NativeMenu-test\");\n    require(\"spec/NodeConnection-test\");\n    require(\"spec/Pane-test\");\n    require(\"spec/PreferencesBase-test\");\n    require(\"spec/PreferencesManager-test\");\n    require(\"spec/ProjectManager-test\");\n    require(\"spec/ProjectModel-test\");\n    require(\"spec/QuickOpen-test\");\n    require(\"spec/QuickSearchField-test\");\n    require(\"spec/RemoteFunctions-test\");\n    require(\"spec/SpecRunnerUtils-test\");\n    require(\"spec/StringMatch-test\");\n    require(\"spec/StringUtils-test\");\n    require(\"spec/TextRange-test\");\n    require(\"spec/ThemeManager-test\");\n    require(\"spec/UpdateNotification-test\");\n    require(\"spec/UrlParams-test\");\n    require(\"spec/ValidationUtils-test\");\n    require(\"spec/ViewFactory-test\");\n    require(\"spec/ViewCommandHandlers-test\");\n    require(\"spec/ViewUtils-test\");\n    require(\"spec/WorkingSetView-test\");\n    require(\"spec/WorkingSetSort-test\");\n    require(\"spec/XMLUtils-test\");\n});\n"
  },
  {
    "path": "test/jasmine.sh",
    "content": "#\n# Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n#  \n# Permission is hereby granted, free of charge, to any person obtaining a\n# copy of this software and associated documentation files (the \"Software\"), \n# to deal in the Software without restriction, including without limitation \n# the rights to use, copy, modify, merge, publish, distribute, sublicense, \n# and/or sell copies of the Software, and to permit persons to whom the \n# Software is furnished to do so, subject to the following conditions:\n#  \n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#  \n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n# DEALINGS IN THE SOFTWARE.\n# \n#\n\n\n#!/bin/bash\nBASEDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\necho $BASEDIR\n\n# open the Jasmine SpecRunner\ncase $OSTYPE in\ndarwin*)\n    open ${BASEDIR}/../../bin/mac/Brackets.app --args file:///${BASEDIR}/SpecRunner.html\n    ;;\nlinux*)\n    echo Linux Not Yet Implemented\n    ;;\ncygwin* | msys | win32 )\n    echo Windows Not Yet Implemented\n    ;;\nfreebsd*)\n    echo FreeBSD Not Yet Implemented\n    ;;\n*)\n    echo Unknown operating system $OSTYPE\n    ;;\nesac\n"
  },
  {
    "path": "test/node/TestingDomain.js",
    "content": "/*\n * Copyright (c) 2013 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*eslint-env node */\n/*jslint node: true */\n\n\"use strict\";\n\nvar fs = require(\"fs-extra\");\n\nfunction remove(path, cb) {\n    fs.remove(path, cb);\n}\n\nfunction copy(src, dest, cb) {\n    fs.copy(src, dest, cb);\n}\n\nfunction rename(src, dest, cb) {\n    fs.rename(src, dest, cb);\n}\n\n/**\n * Initialize the \"testing\" domain.\n * The testing domain provides utilities for tests.\n */\nfunction init(domainManager) {\n    if (!domainManager.hasDomain(\"testing\")) {\n        domainManager.registerDomain(\"testing\", {major: 0, minor: 1});\n    }\n    domainManager.registerCommand(\n        \"testing\",\n        \"remove\",\n        remove,\n        true,\n        \"Remove the directory at the path\",\n        [{\n            name: \"path\",\n            type: \"string\",\n            description: \"path to the directory to remove\"\n        }]\n    );\n    domainManager.registerCommand(\n        \"testing\",\n        \"copy\",\n        copy,\n        true,\n        \"Copy a file or directory. The directory can have contents. Like cp -r.\",\n        [\n            {\n                name: \"src\",\n                type: \"string\",\n                description: \"directory source to copy\"\n            },\n            {\n                name: \"dest\",\n                type: \"string\",\n                description: \"destination directory\"\n            }\n        ]\n    );\n    domainManager.registerCommand(\n        \"testing\",\n        \"rename\",\n        rename,\n        true,\n        \"Rename a file or directory.\",\n        [\n            {\n                name: \"src\",\n                type: \"string\",\n                description: \"source path\"\n            },\n            {\n                name: \"dest\",\n                type: \"string\",\n                description: \"destination path\"\n            }\n        ]\n    );\n}\n\nexports.init = init;\n"
  },
  {
    "path": "test/perf/OpenFile-perf-files/England(Chinese).htm",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html dir=\"ltr\" class=\"client-js\" xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"zh\"><head>\n<title>英国 - 维基百科，自由的百科全书</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<meta http-equiv=\"Content-Style-Type\" content=\"text/css\">\n<meta name=\"generator\" content=\"MediaWiki 1.20wmf1\">\n<link rel=\"alternate\" type=\"application/x-wiki\" title=\"编辑本页\" href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit\">\n<link rel=\"edit\" title=\"编辑本页\" href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit\">\n<link rel=\"apple-touch-icon\" href=\"http://zh.wikipedia.org/apple-touch-icon.png\">\n<link rel=\"shortcut icon\" href=\"http://zh.wikipedia.org/favicon.ico\">\n<link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"http://zh.wikipedia.org/w/opensearch_desc.php\" title=\"Wikipedia (zh)\">\n<link rel=\"EditURI\" type=\"application/rsd+xml\" href=\"http://zh.wikipedia.org/w/api.php?action=rsd\">\n<link rel=\"alternate\" hreflang=\"zh\" href=\"http://zh.wikipedia.org/zh/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"alternate\" hreflang=\"zh-hans\" href=\"http://zh.wikipedia.org/zh-hans/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"alternate\" hreflang=\"zh-hant\" href=\"http://zh.wikipedia.org/zh-hant/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"alternate\" hreflang=\"zh-cn\" href=\"http://zh.wikipedia.org/zh-cn/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"alternate\" hreflang=\"zh-hk\" href=\"http://zh.wikipedia.org/zh-hk/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"alternate\" hreflang=\"zh-sg\" href=\"http://zh.wikipedia.org/zh-sg/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"alternate\" hreflang=\"zh-tw\" href=\"http://zh.wikipedia.org/zh-tw/%E8%8B%B1%E5%9B%BD\">\n<link rel=\"copyright\" href=\"http://creativecommons.org/licenses/by-sa/3.0/\">\n<link rel=\"alternate\" type=\"application/atom+xml\" title=\"Wikipedia的Atom\" href=\"http://zh.wikipedia.org/w/index.php?title=Special:%E6%9C%80%E8%BF%91%E6%9B%B4%E6%94%B9&amp;feed=atom\">\n<link rel=\"stylesheet\" href=\"England%28Chinese%29_files/load_002.css\" type=\"text/css\" media=\"all\">\n<style type=\"text/css\">.js-messagebox{margin:1em 5%;padding:0.5em 2.5%;border:1px solid #ccc;background-color:#fcfcfc;font-size:0.8em}.js-messagebox .js-messagebox-group{margin:1px;padding:0.5em 2.5%;border-bottom:1px solid #ddd}.js-messagebox .js-messagebox-group:last-child{border-bottom:thin none transparent}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:8b08bdc91c52a9ffba396dccfb5b473c */</style><style type=\"text/css\">li#ca-0,li#ca-1,li#ca-2,li#ca-varlang-0,li#ca-varlang-1,li#ca-varlang-2{display:none}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:4a0a05a9c73253ee46f1064aa133e91d */</style><style type=\"text/css\">.skin-vector #bodyContent{font-size:92% !important}.skin-monobook #bodyContent{font-size:118% !important}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:e3fcbf85aca7918b068336bfc5d9dcec */</style><style type=\"text/css\">.mw-collapsible-toggle{float:right} li .mw-collapsible-toggle{float:none} .mw-collapsible-toggle-li{list-style:none}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:4250852ed2349a0d4d0fc6509a3e7d4c */</style><style type=\"text/css\">.suggestions{overflow:hidden;position:absolute;top:0;left:0;width:0;border:none;z-index:1099;padding:0;margin:-1px -1px 0 0} html > body .suggestions{margin:-1px 0 0 0}.suggestions-special{position:relative;background-color:white;font-size:0.8em;cursor:pointer;border:solid 1px #aaaaaa;padding:0;margin:0;margin-top:-2px;display:none;padding:0.25em 0.25em;line-height:1.25em}.suggestions-results{background-color:white;font-size:0.8em;cursor:pointer;border:solid 1px #aaaaaa;padding:0;margin:0}.suggestions-result{color:black;margin:0;line-height:1.5em;padding:0.01em 0.25em;text-align:left}.suggestions-result-current{background-color:#4C59A6;color:white}.suggestions-special .special-label{font-size:0.8em;color:gray;text-align:left}.suggestions-special .special-query{color:black;font-style:italic;text-align:left}.suggestions-special .special-hover{background-color:silver}.suggestions-result-current .special-label,.suggestions-result-current .special-query{color:white}.autoellipsis-matched,.highlight{font-weight:bold}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:d3d0fccf9f8cf3b31866dd3fd3326a6a */</style><style type=\"text/css\">#mw-panel.collapsible-nav div.portal{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAAABCAMAAAA7MLYKAAAAS1BMVEXb29vy8vLv7+/c3NzZ2dni4uLr6+vt7e3s7Ozw8PDn5+fj4+Ph4eHd3d3f39/o6Ojl5eXp6enx8fHa2trg4ODq6urk5OTz8/PY2NjolWftAAAAO0lEQVR4XrXAhwGAMAgEQB5I71X3n9QpPHqAGZidt2e02G8yedciQkv1/YPqIpFSdzbp9tjGsd4xhwl8yuMKHhkJhm8AAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/Vector/modules/images/portal-break.png?2012-04-10T19:16:40Z)!ie;background-position:left top;background-repeat:no-repeat;padding:0.25em 0 !important;margin:-11px 9px 10px 11px}#mw-panel.collapsible-nav div.portal h5{color:#4D4D4D;font-weight:normal;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEX////d3d2ampqxsbF5eXmCtCYvAAAAAXRSTlMAQObYZgAAADBJREFUeF6dzNEJACAMA1HdINQJCp1Ebv+ZlLYLaD4f4cbnDNi6MAO8KCHJ+7X02j3mzgMQe93HcQAAAABJRU5ErkJggg==) left center no-repeat;background:url(//bits.wikimedia.org/w/extensions-1.20wmf1/Vector/modules/images/open.png?2012-04-10T19:16:40Z) left center no-repeat!ie;padding:4px 0 3px 1.5em;margin-bottom:0px}#mw-panel.collapsible-nav div.collapsed h5{color:#0645AD;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///95eXnd3d2dnZ3aAo3QAAAAAXRSTlMAQObYZgAAADFJREFUeF5dyzEKACAMA0CXolNe2Id09Kl5igZahWY4AiGjZwmIuS9GEcJfY63Ix88Bol4EYP1O7JMAAAAASUVORK5CYII=) left center no-repeat;background:url(//bits.wikimedia.org/w/extensions-1.20wmf1/Vector/modules/images/closed-ltr.png?2012-04-10T19:16:40Z) left center no-repeat!ie;margin-bottom:0px}#mw-panel.collapsible-nav div h5:hover{cursor:pointer;text-decoration:none}#mw-panel.collapsible-nav div.collapsed h5:hover{text-decoration:underline}#mw-panel.collapsible-nav div.portal div.body{background:none !important;padding-top:0px;display:none}#mw-panel.collapsible-nav div.persistent div.body{display:block}#mw-panel.collapsible-nav div.first h5{display:none}#mw-panel.collapsible-nav div.persistent h5{background:none !important;padding-left:0.7em;cursor:default}#mw-panel.collapsible-nav div.portal div.body ul li{padding:0.25em 0}#mw-panel.collapsible-nav div.first{background-image:none;margin-top:0px}#mw-panel.collapsible-nav div.persistent div.body{margin-left:0.5em}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:44fa362f739f64019ade8fb4434dff59 */</style><style type=\"text/css\">.tipsy{padding:5px;position:absolute;z-index:100000;cursor:default}.tipsy-inner{padding:5px 8px 4px 8px; background-color:#ffffff;border:solid 1px #a7d7f9;color:black;max-width:15em;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px; }.tipsy-arrow{position:absolute;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAMAAACecocUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRFp9f5+fn5////cvEDKAAAAAJ0Uk5T/wDltzBKAAAAMklEQVR42mJgBAEGBMnAxABjMzAxgTkMECaYwwBlgjgMMCaQgyKOoh7FHBTzYSRAgAEAJSAAj5EcAeEAAAAASUVORK5CYII=) no-repeat top left;background:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.tipsy/images/tipsy.png?2012-04-10T18:40:00Z) no-repeat top left!ie;width:11px;height:6px} .tipsy-n .tipsy-arrow{top:0px;left:50%;margin-left:-5px} .tipsy-nw .tipsy-arrow{top:1px;left:10px} .tipsy-ne .tipsy-arrow{top:1px;right:10px} .tipsy-s .tipsy-arrow{bottom:0px;left:50%;margin-left:-5px;background-position:bottom left} .tipsy-sw .tipsy-arrow{bottom:0px;left:10px;background-position:bottom left} .tipsy-se .tipsy-arrow{bottom:0px;right:10px;background-position:bottom left} .tipsy-e .tipsy-arrow{top:50%;margin-top:-5px;right:1px;width:5px;height:11px;background-position:top right} .tipsy-w .tipsy-arrow{top:50%;margin-top:-5px;left:0px;width:6px;height:11px}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:3242f4958e7a2bbf89c80f8607a388b9 */</style><style type=\"text/css\">.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute;left:-99999999px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:after{content:\".\";display:block;height:0;clear:both;visibility:hidden}.ui-helper-clearfix{display:inline-block} * html .ui-helper-clearfix{height:1%}.ui-helper-clearfix{display:block} .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)} .ui-state-disabled{cursor:default !important}  .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}  .ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}  .ui-widget{font-family:sans-serif;font-size:0.8em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:sans-serif;font-size:1em}.ui-widget-content{border:1px solid #cccccc;background:#f2f5f7 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAALklEQVQYld3KsQ0AIAzEwFP2Xxgongoo2CCNZUs25kpBQwQlOYbKy1CRa//cExv8DRSkjiA77AAAAABJRU5ErkJggg==) 50% top repeat-x;background:#f2f5f7 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png?2012-04-10T18:40:00Z) 50% top repeat-x!ie;color:#362b36}.ui-widget-content a{color:#362b36}.ui-widget-header{border-bottom:1px solid #bbbbbb;line-height:1em;background:#ffffff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAHUlEQVQYlWP49+/ffyYGBgaGIU4wMjIOBmcMBQIAf6oEw6+MsKoAAAAASUVORK5CYII=) 50% 50% repeat-x;background:#ffffff url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png?2012-04-10T18:40:00Z) 50% 50% repeat-x!ie;color:#222222;font-weight:bold}.ui-widget-header a{color:#222222} .ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #aed0ea;background:#d7ebf9 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAANklEQVQYld3PsQkAIBQD0SP7T2ptKf+sRBcQweY1SYrQ+jAAfyEShQik3KyggFR5Vvbi/YVrTPt2HIFGqL5zAAAAAElFTkSuQmCC) 50% 50% repeat-x;background:#d7ebf9 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png?2012-04-10T18:40:00Z) 50% 50% repeat-x!ie;font-weight:normal;color:#2779aa}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#2779aa;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #74b2e2;background:#e4f1fb url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAN0lEQVQYlWP48vPvfyYGBgaGIUT8/w9nwQmG//+RuUhK/jNgSEB1MDAw/Wf4j6kDSXagvUoLAgBheh6WDv5kIgAAAABJRU5ErkJggg==) 50% 50% repeat-x;background:#e4f1fb url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png?2012-04-10T18:40:00Z) 50% 50% repeat-x!ie;font-weight:normal;color:#0070a3}.ui-state-hover a,.ui-state-hover a:hover{color:#0070a3;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #cccccc;background:#f0f0f0 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAIklEQVQYlWP48OHDfyYGBgaG4UowMjIis7Bx0cTQWMOOAABBiwSuT/SJQAAAAABJRU5ErkJggg==) 50% 50% repeat-x;url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png?2012-04-10T18:40:00Z) 50% 50% repeat-x!ie;font-weight:normal;color:#000000}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#000000;text-decoration:none}.ui-widget :active{outline:none} .ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #f9dd34;background:#ffef8f url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAAEwK2r2AAAAYElEQVQYla2QMRLCQAzE5P3/I/giXQKcleYmDYEJQxqNC3stG+83A/COQeyFwIPUYQtwFCBN8ElwJcU4P/sFTXQQeBH2qvBkwD/Lf8A8X1Il0Z720FNXexdvIn5+8dXYAKv0NbGis6yGAAAAAElFTkSuQmCC) 50% top repeat-x;url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png?2012-04-10T18:40:00Z) 50% top repeat-x!ie;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#cd0a0a url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABkAQMAAADOquA5AAAAA1BMVEXNCgokNzldAAAAFklEQVR4Xu3AMQEAAABAMP1TS+EzApsCWAABXdUwuQAAAABJRU5ErkJggg==) 50% 50% repeat-x;url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png?2012-04-10T18:40:00Z) 50% 50% repeat-x!ie;color:#ffffff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#ffffff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#ffffff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}  .ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon,.ui-widget-header .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEV0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psx0psyPQTyXAAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_72a7cf_256x240.png?2012-04-10T18:40:00Z)!ie}.ui-state-default .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEU8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grQ8grTq2f41AAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_3d80b3_256x240.png?2012-04-10T18:40:00Z)!ie}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEUkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwkluwOSETqAAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_2694e8_256x240.png?2012-04-10T18:40:00Z)!ie}.ui-state-active .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEVkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmRkZmTo2+rBAAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_666666_256x240.png?2012-04-10T18:40:00Z)!ie}.ui-state-highlight .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEUsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvwsgvzLrJBNAAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_2e83ff_256x240.png?2012-04-10T18:40:00Z)!ie}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEX8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vywC3+8AAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_ffffff_256x240.png?2012-04-10T18:40:00Z)!ie} .ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-off{background-position:-96px -144px}.ui-icon-radio-on{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px} .ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}  .ui-corner-tl{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0}.ui-corner-tr{-moz-border-radius-topright:0;-webkit-border-top-right-radius:0}.ui-corner-bl{-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0}.ui-corner-br{-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0}.ui-corner-top{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0}.ui-corner-bottom{-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0}.ui-corner-right{-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0}.ui-corner-left{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0}.ui-corner-all{-moz-border-radius:0;-webkit-border-radius:0} .ui-widget-overlay{background:#000000;opacity:.75;filter:Alpha(Opacity=75)}.ui-widget-shadow{margin:-7px 0 0 -7px;padding:7px;background:#000000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABkAQMAAADOquA5AAAAA1BMVEUAAACnej3aAAAAFklEQVR4Xu3AMQEAAABAMP1TS+EzApsCWAABXdUwuQAAAABJRU5ErkJggg==) 50% 50% repeat-x;background:#000000 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-bg_flat_70_000000_40x100.png?2012-04-10T18:40:00Z) 50% 50% repeat-x!ie;opacity:.20;filter:Alpha(Opacity=20);-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:9b1f4faea1e603fc0fc84f0209967589 */</style><style type=\"text/css\">.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;z-index:99999;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:c3a005c034055064ab5f5553477e56aa */</style><style type=\"text/css\">.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;text-decoration:none !important;cursor:pointer;text-align:center;zoom:1;overflow:visible} .ui-button-icon-only{width:2.2em} button.ui-button-icon-only{width:2.4em} .ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em} .ui-button .ui-button-text{display:block;line-height:1.4em}.ui-button-text-only .ui-button-text{padding:0.3em 1em 0.25em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:0.3em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:0.3em 1em 0.25em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:0.3em 2.1em 0.25em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em} .ui-button-text-icon .ui-button-text{padding:0.3em 1em 0.3em 2.1em} input.ui-button{padding:0.3em 1em} .ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-text-icon .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icon .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:0.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icon .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:0.5em} .ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em} button.ui-button::-moz-focus-inner{border:0;padding:0} body .ui-button{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;margin:0.5em 0 0.5em 0.4em !important;border:1px solid #a6a6a6 !important;background:#f2f2f2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWBAMAAADz6OuZAAAALVBMVEXh4eHR0dHr6+vb29vo6Ojl5eXV1dXv7+/w8PDt7e3d3d3X19fx8fHy8vLPz88WlQFaAAAAM0lEQVR4XkXBURXAEAAAwIuwCIsggggiiCCCCCKIIIIIIojCn3fWNa+qaH5RQhcM2Wc/BwNbDIE7SpS7AAAAAElFTkSuQmCC) repeat-x scroll 50% 100% !important;background:#f2f2f2 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-off.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie;cursor:pointer;font-size:1em;line-height:1.4em;width:auto;overflow:visible}body .ui-button:hover{border-color:#6e7273;background:#e1e1e1 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWBAMAAADz6OuZAAAALVBMVEXR0dHe3t7Y2NjIyMjV1dXf39/CwsLc3NzGxsbNzc3a2trh4eHg4ODMzMzAwMAj4qyZAAAAM0lEQVR4XkXBURXAEAAAwIuwCIsggggiiCCCCCKIIIIIIojCn3fGNa/kU3S/iGYJqmw/B/OMDGHTHKjcAAAAAElFTkSuQmCC) repeat-x scroll 50% 100% !important;background:#e1e1e1 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-over.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button:active,body .ui-button:focus{border-color:#707271;background:#bfbfbf url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAgBAMAAAAhyw8pAAAAGFBMVEXc3NzGxsba2tre3t7V1dXQ0NDMzMzAwMAJtu+DAAAAK0lEQVR4XmXBSREAIAzF0EhAQiUgoRK+BCTU/wqTK/OImgK2oNRPOFqa3wXmgAjBrktk/wAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#bfbfbf url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-down.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.disabled{color:#7f7f7f;border-color:#cccccc;background:#f2f2f2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWAQMAAAA7CGTpAAAAA1BMVEXy8vJkA4prAAAAFElEQVR4XpXAgQAAAACAoP2pZ6jAACwAAVJj6TIAAAAASUVORK5CYII=) repeat-x scroll 50% 100% !important;background:#f2f2f2 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-disabled.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie} body button.ui-button::-moz-focus-inner{border:0} body .ui-button-large{padding:5px} .ui-button-green .ui-icon,.ui-button-blue .ui-icon,.ui-button-red .ui-icon,.ui-button-orange .ui-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEX8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vz8/vywC3+8AAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAM6klEQVR4XuybAYrjMAxFrRzw3f84C2F2g+ex34Q0NKV6sCzNl2xLVpy47own0DRNUV8ePw/PAHU5xChSUJMx9cYKBGAy0ATBL7VA6kGBOpD/ZAz1vgoEQHPkBHgGrdrdHdhYLrfg8ccQgl5ABe/QuoFSj/cC5QBdAblCPMOxAsIAVAFvwUNUfCIYFCzSC6U14DueAr6FdmOqX4Sapmmapmm+4k2wHvUi5t0OVAiIHZSv/H1A+EKoUBO34gEoATaYzScD5avcHBU3j2riBjz+POIgF1AhXzGfBtj/3Y0r+KDSiMvmDrhSPmUeKuBNFHd+H+A7xGtAPwW+gqZpmqZpGq55A1xqn/cGMIB4weJJONe/E4o+WI8esX0GNpndsZY60ACkrvvP8SBZutQQgbvjl4jEWEFywGLuP26XcQKCzE6OILnHAThAdmYDZnN21P+JFOUShlV+HTHZ3QM418OJ8KzaAHQh60Ng/1zQoUPLvpRVxkV4qH9+TDZN0zRN01z/WSpcHkDcL2aNnRHIasG5AYQOZBUjyAOYj5WoScpQaQONj/chbjCX/ctdAUjLAwCYDxahJi1WEFRMQKm7dZnFDECMH4m6YncOkSlFjFBB3g47wfgKYz0ApKoBjVD+0uVvGTUwQoBKgBK0ToAGIHsZrGWI++dhd98CoYuRboGCOnMLuMbdP2ERwwEIT5kkLYJpjsIiKNCyJP8hqDxHWR6GeA+PRK4Aw86Hvog0TdM0TcO4kyI/mLEHMF7Iujlk/joKfAUqxj9ljdNTRjqvxgGD9NfBTunKFMusswoWSAZMTsxGoIQk8+swZcAh7tKkg/x9Pk6YMYbhly9yvysBBQ6KSd+RGo+vo86wNYowGvPCFJQj8HYXPOPr82Z7aPT2dwKsA7c9Cqjh3RmUlsj8C4RgAMrPKiFYfzHkv2ihzuxecfz6JDFmqN9zHkvTNE3TbIwPxptP7+f8Ea7FT42H4GC9HRjb8jSQbZx826unVsC//daRno1jkvmROKZ/Fw/75Z8csMNzosc5mPSNbTDbHx783APM7vzvOLp4VgL4S0jQUd5KgP53Rc1ygW6Bp1eA7XemBLkC9HuFufyp8SlrgKbXzmyDTWuA7HX/P/spkJb8+QEBhKTOWsHHvQesYbtwDPHR5Pibpmma5k87Z6PctnFF4cPdAIxBCwRFsbalmLVTKXVtN02atAnj1q4Up3Hq5nv/x6kEE7jYHS0kJSyjH3yUhnOwEIhz5vJiYS/pAbwuzUfZKR9pS+TAOFcPHwOgJNyDPos+Hva1SvtXAYUsAR8ffgJMFOlIGPfXyJhgltgpy5yaNhCCQJDElORktvLUVIFf8LEODhifjVnICrKMIkv+X2FDeEKRMGB63is2GyjL0n0gCmQcBGAJiOwMrAKCAECzU9Qm3FQAiQDIsuCAGdnurqcbwHw+F0oCglikA5gEAeJOoaYJZNQEYn7DwPfOSFUAOfYkiaYHNBoRnvEeAHsWwO5i8rsggAcPHgjTNUltG+IAzP/DbgBAEMDIEUVUgxp4cEayAmY5EvmsDUAevCwABzgID2cHzAoePeq+BebKskzzVuPrx5UDMP/39x+mAxhFG8RoNJqNRqiBxWKR7gHMZjnks24AUjcAD3gLgAOAgwPWelcFFNqN7EBPAIoDUBTAJzLJtLoPlKkAQi0xqUENPH78GLJkBfhZns+8BfBBpwN4/AFUMypYFMWSYhQE4GUB/L5+dP1mcQBZFABBBUzNfzoAC/xJTVRyWZaqAD+r8SQ0OZATvCeLor0KFKwpEhVgAVy+B0D4eubfAsCHrxfNA/g4PQ+49GXQzmcKMvBMFPvlsk2vsvyjDXEAlkCpzeF9VeP1i4HJZr84qZ8Jpe4MAwMDAwNPn6oXB05pQAL14/GN+BSATxuZA9177Ck1TKPbs8mF2vgDqEtZqoc92FNIVVUmHN5bAuMMOCxybKIzhek9eldtesD8IywBmJ4BPffzRVFcQUsgtQ5KHDjK1g5TTTFHOoKjyD9QLcw/WALEq8OJtfiMz9hBhleON4MIkobRH/VMf5IZohAqAq1Q72V7pqUKqip1ggBT01OIK045laMNEA/gSQbgakzr+cGLl/sHuVo8ubwuG8Cf+ZzPGXcNAkWkn3R1pqyI576tdtS48wN/2kjrAxqzU1E51dzz1Ph7qQAkkDDNDn/hKV3/eF06AH2hL/XXrNF63FaAaQU6rICKYK5fAhJQnh/4V9R8pYbFIrp3AO9B6g8gqIBPJqeP8/0L4vtxh3PO9Bd8zdf8rdEj2h5g2pu2cfNfnTJJBOAIK0Ln3Tv1dHmyXAugTAXgWRP5j14vCsA0B18+GD/4+zdrPWPN5EJt/mXYW8B0LI+OTFdUjnFfAIpAck5CCcD821UQPu0GIKV6AvBExsVa5j9xA++6/vXi26k0/fZFG8BOhev5exQxJW6iBLuZ/3AekPhn71jDSMbFujL/8WWwxXUdlvcl6X6poILSFLp59E+EEnOg34qBgYGBgRysb5cAj9UD6P9JAVCoB0C/GMdK0gqnlkOwBB6S5999xzd2OuzI0HKf58/ZXybWW+SsySMdb8hTa1ULxnn+KkgAfk0AFYUKKkuPlVbxbHzRav5xxj8bKVY5hao2Ic67O0UNtt2Gg/tXhPeedkccCm62GEsrXrGxAIAK87sC6t+wACyA16+l16/NSC7KCiqlAgiWjCCPF1gA2qH7MRbAT6dgAfBydkr3BVes8mQANKTsxuMF4XtqBYF/d97ce9JIvQHG5l9kNbQ6/HsywHYQzkGuhQWgOgCZ4WK5LIrCdL5ipZzYUSqAhAQpMd1eRf493R7wNZNTeNOZ1wZ/z15/ALvALuw22h0COQvH+efvefly9nLJodbwipU03lwAcQX8C4Cj0L8ZLFY1i1ZHBYNze3t7QQDBe35xysHpD2E+q2QPWC5ns1nQBF/l+Zhi8z3A/K8sATyUToaWAK1/sdrhEEsASbvW9uQJA3jyZP0TBkCyB+R+uVyyJHkZ3PxV4EhHQCtLhaym069MUYrSWQLYk23RRJx/GWTRkOgB5GewRGlgo/OAI0lHONWAVwRA0DFeOTloR4+fj0QQQHfJSubxHp/pqvOA68PuycmujGrHSXJycc+JV05uhoGBgYE8l7H/PcD3+7o7vIW3rfiBNT/orvAI4NFa7ANIAFYDc+Yy9G+gVESpTTEHYL7NAnCuLYEfLYAf+7/7KqSkTNwL2YaUZu4lmWMAtloAUlsCGKRngg5i/1D2L9w0zbvsnenEUtCtdgDn4G2QfhjAlGnsf2zezX9q6W7lKjD9TtI704L5bxhAyZoyEUBb3wY8c50x858IwAUlQyYpw9xGAXjm8zleW8IMpwOIAfMPmP8NVMC2m2AJ4ByNhxML4CSugPQBbHwDPcDkNoib3guTL5JNEM7rfxu7Ckhoa8ypsaI7buSxenqAFIzeqi8Y/OkNwJuf9BuC7gwDAwMDAwMlsdwmjMveT0hsnnv3Yv/EcpuARRAEYPG47g7l2EnlmDC/aaunH3ZK396WUCrUxFKU2hZgEUQBWDztOZdQ2wt3CAKw8TgA06EybZLtBgDTZAAwloC1lMZAtEMQQDAukXSclohbWwGY7pPc2h5g9PeAW3sVoOZ6XAWGecDAwMDAwACV7jDuP+L9gVMLcOjukH/G4n2JWS7KN1Aogvj7D66srykr/ivei1WQypg4AeJnf2V9LXE8k96XemYlAKuFxjgZwoxke9npT7t8m71mPbtpQp2RUevriOewFod4rSkqWDh2EgHMzhjNRqz1iNHobAPNODNOdXecGfX4ta0AqakA6wsrQvuN5JsP4K+srydjKkkVYzWAchZ5GMDtbYIFPDt81m37IFGWhPbRbaV4C7wtdBcZGBgYGLDPB/TrxCKqK2o73lZ0muTnA/p1vIzu6tqOtw19Mfu07F+k44WUV9Xx8bag+4k/H9Bq6OpjgY7X+gRAAJy0mlgrMd4cP3o9xZre8bmkribWgGp9CeLF0TSYlo6PJeCS+4PUr5H6xiUiHT8jdfXPP/9sukZawmUDaJNIaI6l48iQ6NlfsaHe/c3xZc9HQJ9e1v43GEAlVYkAUs9pQ1fXIHGFCliq9g+bewtUVe8J9WvD9EUBAhdUSI9mqSWXCsCamtJNzZrgSbJJEWslxhNNUrEmPd6otIal6V62fRmLj7cF3cu2JzLx8baj+9n+VNaOtxXdz8DAwMDAwAA1bFzfGMjO4AJ9uwOgPwAyuhrUH4DQzQoAyIh1OiAk0afRUAFDD2C4CtxZBgYGBgYGBkbopoBQL3j81f2PdFMYafSrAxiR8H/7K8D8xvpmVgCj5pEIgIbQLwr17e0BviH0P4r9M7oLFWD+Sfi//RWQ9n9XrgIJ/3duHmD+b2QP2BiM7PeaMzDwP8nmcxwZc6CLAAAAAElFTkSuQmCC) !important;background-image:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/ui-icons_ffffff_256x240.png?2012-04-10T18:40:00Z) !important!ie} body .ui-button.ui-button-green{color:white !important;border-color:#97af7e !important;background:#3cb677 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEUpflI7tXYxl2MujVwqgFQ1omk2pWwoeU8vkF4sh1gwlGA5rnI7s3Uzm2U3qG4oe1A0n2c4q3AtilovfVUrg1Y6sXPiEyGEAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJYLVZ3HZVcVpE01dchteGYfm+QEULwDomj1/qwAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#3cb677 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-green.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-green:hover{border-color:#778e61 !important;background:#339b65 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEUkbUcpflIja0Yxl2IoakgxlGEymGQsh1goe1Awkl8tilkqgFQrhFYvj14neE4lb0klc0siZ0MiaUQymmQmdU0ujFwT8ddqAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJR5VUgybz9SsFkG3e50ORLdL/gET1wDo6WccxwAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#339b65 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-green-hover.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-green.ui-button-large{background:#3cb677 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAMAAACT+SJTAAAAhFBMVEUpflI7tXYxl2MujVwznGYrglUqgFQ1omk2pWw2p20wkl8oeU8shVc0oGgpfVExlmIvkF4sh1g5sHMwlGA8tnc5rnI7s3Uzm2U3qm83qG4ui1soe1AymWQneE4qf1Mvj100n2c6snQ1pGstiFkoelA4q3Atilo4rXEvfVUrg1Y7tHY6sXMmHHEHAAAAQElEQVR4XgXAgxHDAAAAwI/t2ub+++UsBH5Wrv5GS29PG1uF3E2mcRFbOwh1JqXeWWTn5W5Q+0qkTmjtPVSOPjOmhAOzqcaxkwAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#3cb677 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-green-large.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-green.ui-button-large:hover{background:#339b65 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAMAAACT+SJTAAAAhFBMVEUkbUcoek8kbEcpflIpfFEja0Yxl2Ioakgxl2MxlGExlmIymGQsh1goe1Awkl8hZkIjakUndk0tilkqgFQlb0grhFYvj14ujl0rglUmdEwzm2UsiFkiaEQymWQneE4lb0klcUovkV4lc0siZ0MiaUQymmQtjFsqgFMwk2AmdU0rhVcujFzu4mGUAAAAQElEQVR4XgXAgxHDAAAAwI/t2ub+++XsPB1VcqlS4aN1tbL29zLaq/0sbUzeIrFG4GTwtXVzcbZAKNF7OLjrZDOnXAOzVTrJJQAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#339b65 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-green-hover-large.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-green.disabled{filter:alpha(opacity=50);-moz-opacity:0.50;-khtml-opacity:0.50;opacity:0.50} body .ui-button.ui-button-blue{color:white !important;border-color:#628acb !important;background:#3365ba url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEUuXKkmS4ozZbkkSIQtW6YiRHwrV58hQ3owYLAxY7UnTY0jRoEqVZsyZLcvXq0oT5EqU5gxYbMsWaMlSocjRX8pUZU8hDFrAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJaLNcOl2ZLdqdfocpuCRLF5F+wETiQDocXjMfwAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#3365ba url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-blue.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-blue:hover{border-color:#5375ad !important;background:#2b569e url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEUkSIQlSocqVJokR4EfPXArVZwnTpAjRX8fP3MoUJMhQngiQ3sePG4gQHUeO2wmTY0qU5gcOWglTIspUpYdOmorVp0vaG5sAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJT5FdHoM1eEWkDSLadNlq93r+gETbQDoYR8TFAAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#2b569e url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-blue-hover.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-blue.ui-button-large{background:#3365ba url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAMAAACT+SJTAAAAhFBMVEUuXKksWKEmS4ouXKgqVJovX64wYbEyY7YzZbkkSIQyZbgtW6YkR4MnTpAiRHwrV58lS4khQ3owYLAxY7UnTY0jRoEoUJMqVZsyZLctWqQiQ3svXq0kSYYoT5ExYrQqU5gjRoAxYbMsWaMpUpYmTIwlSocjRX8zZborVp0pUZUiRH0vXauCMiDmAAAAQElEQVR4XgXAgxHDAAAAwI/t2ub+++W85UobmcnJVWqU2PsjUtm6CXQ+1mJnd18rR42Fh1Dv6aBQW7p4+WntDDOZVAOzgFhMmgAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#3365ba url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-blue-large.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-blue.ui-button-large:hover{background:#2b569e url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAMAAACT+SJTAAAAflBMVEUfPG8kSIQfPnIlSocqVJokR4MkR4EfPXAiRH0rVZwoT5InTpAlS4koUZQjRX8fP3MoUJMhQngiQ3sePG0qU5kePG4rVJsgQHUlSYYmTYwrVp4eO2wpU5cnTo8gQXcmTY0qU5gfQHUjRoAcOWglTIspUpYhQnsdOWkdOmorVp3M0v8uAAAAQUlEQVR4Xg3BgxVDQQAAsHybta39F+y92PsFlbXU0tXRS2dUa5xc7Dy1EluRTO6uV5q9Tc42bgaxAisLB9/g4/EHoJ4Dr9t5q84AAAAASUVORK5CYII=) repeat-x scroll 50% 100% !important;background:#2b569e url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-blue-hover-large.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-blue.disabled{filter:alpha(opacity=50);-moz-opacity:0.50;-khtml-opacity:0.50;opacity:0.50} body .ui-button.ui-button-red{color:white !important;border-color:#af977e !important;background:#cb0000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEWUAACeAACIAADIAACQAACKAACaAADDAAC8AACxAACFAADFAADAAACuAACXAACqAACmAAC5AACiAACNAADKAAC1AAB6LXXpAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJV7Joll1l8+wOZxuQbUjexTR/AEV+QDoUwTrkQAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#cb0000 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-red.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-red:hover{border-color:#8e7761 !important;background:#ad0000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEWdAACUAACaAACDAAB0AACjAACNAAB4AAB7AACgAACKAABxAACsAACXAACqAACAAACoAAB+AACmAACRAAB1AACGAAAFpPfGAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJVa7060YiDbBo5o+yeHSNa9s+QET9wDo7y8jggAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#ad0000 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-red-hover.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-red.ui-button-large{background:#cb0000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEWUAACeAACIAADIAACQAACKAACaAADDAAC8AACxAACFAADFAADAAACuAACXAACqAACmAAC5AACiAACNAADKAAC1AAB6LXXpAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJV7Joll1l8+wOZxuQbUjexTR/AEV+QDoUwTrkQAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#cb0000 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-red.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-red.ui-button-large:hover{background:#ad0000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEWdAACUAACaAACDAAB0AACjAACNAAB4AAB7AACgAACKAABxAACsAACXAACqAACAAACoAAB+AACmAACRAAB1AACGAAAFpPfGAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJVa7060YiDbBo5o+yeHSNa9s+QET9wDo7y8jggAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#ad0000 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-red-hover.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-red.disabled{filter:alpha(opacity=50);-moz-opacity:0.50;-khtml-opacity:0.50;opacity:0.50} body .ui-button.ui-button-orange{color:white !important;border-color:#f3a863 !important;background:#f07f14 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEXhdxOmWA61YA+pWg6iWxbQbhHsfRTddRLUcBLCZxCgVQ3vfhSiVg3ZcxLHaRDpexOxXg+tXA7leRO+ZBDMbBG6Yg+ZlQMbAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJRbV4Uaz6YrXbnh8otMlCVZT/gEUsQDogjg6swAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#f07f14 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-orange.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-orange:hover{border-color:#ce9055 !important;background:#cc6c11 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAMAAAA2GAaYAAAAQlBMVEWXUA2ISAueUw2NSwyxXg6lWA68ZA+TTgyQTQy5Yg+pWQ6KSQu0Xw/LaxGiVQ6uXA6/ZRDGaRDDZxCaUg2KTRPJahH2OJVtAAAAKElEQVR4XgXAhQ2AMAAAsM4Ft/9fJTafy+1UDavsMBW76EHTJYvg/QEWxQDo2m2cEgAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#cc6c11 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-orange-hover.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-orange.ui-button-large{background:#f07f14 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAMAAACT+SJTAAAAhFBMVEWnWA7hdxOmWA63YQ+1YA+pWg7AZhCiWxbQbhGeVA3sfRTtfhTbdBLddRLUcBLFaBDCZxCgVQ3SbxHjeBPvfhSvXQ+kVw6iVg3ZcxLHaRCrWw7pexPfdhK8YxCxXg+tXA7leRPqfBO+ZBDMbBG6Yg+zXw/wfxShVQ3nehPJahHXchLObRGV62MnAAAAQElEQVR4XgXAgxHDAAAAwI/t2ub+++W8LFRKV3sfF5PAQaO28dMa5f7uvrY6vdTN0UMk9nSydLaTILSy9jYoZDOtXgOzmKJnqAAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#f07f14 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-orange-large.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-orange.ui-button-large:hover{background:#cc6c11 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAMAAACT+SJTAAAAhFBMVEWJSAuXUA2ISAueUw2cUw2NSwyxXg6lWA6+ZA+8ZA+TTgzFaBCQTQySTQy5Yg+zXg6pWQ63YQ+KSQurWg60Xw/HahCOSwzLaxGiVQ6uXA66Yw+/ZRDKaxHBZhDGaRCoWQ6YUQ2GRwvMbBHDZxCgVA6VTw2jVw6vXQ6MSgyaUg2KTRPJahHiODFfAAAAQElEQVR4XgXAgxHDAAAAwI/t2ub+++XcrB38LZ1U7o72coWd1mChk3rbmvTOMi8bD5HY10XgqdSorSQ+RoSufjOr8AOzYAWVRAAAAABJRU5ErkJggg==) repeat-x scroll 50% 100% !important;background:#cc6c11 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/button-orange-hover-large.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie}body .ui-button.ui-button-orange.disabled{filter:alpha(opacity=50);-moz-opacity:0.50;-khtml-opacity:0.50;opacity:0.50}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:6c7425383377fd7a8b898d9a4d9635b6 */</style><style type=\"text/css\">.ui-dialog{position:absolute;padding:0;width:300px}.ui-dialog .ui-dialog-titlebar{padding:.75em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.75em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane button{float:right}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move} body .ui-dialog .ui-dialog-titlebar-close:hover{text-decoration:none}body .ui-dialog .ui-dialog-content .status-invalid input{border:2px solid red;padding:2px 1px}body .ui-dialog .ui-dialog-titlebar{padding:0.9em 1.4em 0.6em !important}body .ui-dialog .ui-widget-header{background:#f0f0f0 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAASFBMVEXn5+fZ2dns7Ozc3Nzj4+Pg4ODq6url5eXk5OTh4eHe3t7o6Oju7u7r6+vb29vi4uLv7+/f39/p6enm5ubw8PDt7e3d3d3a2tpM98B4AAAAL0lEQVR4Xg3BhRHAMACAQOJ1l/03Dfc8OrToVWRV5dIM3GoMZHaNFE5NfEps+hU6RiYB51j6ttcAAAAASUVORK5CYII=) repeat-x scroll 50% 100% !important;background:#f0f0f0 url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/titlebar-fade.png?2012-04-10T18:40:00Z) repeat-x scroll 50% 100% !important!ie} body .ui-dialog .ui-icon-closethick{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAElBMVEUAAAAAAAD///8AAAAAAAAAAAAtTix5AAAABXRSTlMNTQC/s2KwEqEAAAAvSURBVHheHYqxCQAgEANjXMAm/Y9g8yM4QND9ZxHSHBx3eKwD7WmM2wslM4gmZPliBwTrQLNRjAAAAABJRU5ErkJggg==) no-repeat 50% 50% !important;background:url(//bits.wikimedia.org/resources-1.20wmf1/resources/jquery.ui/themes/vector/images/close.png?2012-04-10T18:40:00Z) no-repeat 50% 50% !important!ie}body .ui-dialog .ui-dialog-buttonpane{margin-top:0 !important;padding:0.3em 1.4em 0.5em 1.4em !important}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:939702fe73ad5f6db728e6901f7b02f0 */</style><style type=\"text/css\">.articleFeedback{position:relative;display:inline-block;margin-top:1em}@media print{.articleFeedback{display:none}}.articleFeedback-panel{background-color:#f9f9f9;border:1px solid #cccccc;padding-bottom:1px}.articleFeedback-error-message{padding:3em;text-align:center}.articleFeedback-error{display:none;position:absolute;top:0;bottom:0;left:0;right:0;background-color:#f9f9f9;border:1px solid #cccccc;padding-bottom:1px}.articleFeedback-lock{display:none;position:absolute;top:0;left:0;right:0}.articleFeedback-pitches{float:absolute;top:1;left:1;right:1;background-color:#f9f9f9}.articleFeedback-pitch{display:none}.articleFeedback-lock{background-color:transparent}.articleFeedback-pitch-or{margin-left:0.75em;margin-right:0.25em}.articleFeedback-reject{border:none;background-color:transparent;cursor:pointer;color:#0645AD;line-height:1.4em}.articleFeedback-reject:hover{text-decoration:underline}.articleFeedback-pitch .articleFeedback-buffer{padding:0.75em 1em}.articleFeedback-panel{float:left}.articleFeedback-panel .articleFeedback-buffer{padding:0.75em 1em}.articleFeedback-title{font-size:1.4em}.articleFeedback-pitch .articleFeedback-title{font-size:1em;padding-left:28px;line-height:32px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAulBMVEX5+fl8pFWDqjTi6Nx5n05/pjOQtEWLsT2kwmR3nyeoyl10lFJ6nVN1mkuJrF2TtWSwzXi82X2PtEKTu0W92oWnxXWZvkuuyXT29/WszGaXuGaQsW3U286GpmbN08eryXru8eyKrjzq7efd49jF0biy0XGawUyrvZaswpZqhFCatny4xaqbvGyhwVqkwXN3m1OgvWK41XuFq1mQr3Ocs4Su0WOUtUuz1mWGqTubuVehv1uCplWjx1Z8pC93iUb/AAAAAXRSTlMAQObYZgAAAMRJREFUeF6lkUVuQ0EQBYc/MzObmcL3v5aTlceZ2bkW3VI99aL1wOss1nIf5g0sZQEJ38LiLPp5dJ3pYSH4lHjxzDMHIVg137G+mwu+hVMQHPdAALox0/ORM0P6N0s784MEcn5tE/y7TFdRVBs/fE+8hIygdLadH1XcgZkhJSsuRoLQ9qvnAstFCH06G4aUzQpwYBL5P5QxSlUrfX7Y2N00SmmXL8A/KudDo9oBpmINJ1V7d2Rd1Et1WgIZrWHVQArG4CXuoiYOJw5+/RcAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/success.png?2012-04-10T19:11:40Z)!ie;background-repeat:no-repeat;background-position:left center;margin-bottom:0.5em}.articleFeedback-pitch .articleFeedback-pop{padding:1em;margin:0;background-color:white;border:solid 1px silver; -webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.articleFeedback-message{margin:0.33em;font-size:1.5em}.articleFeedback-body{margin:0.5em;color:#333333}.articleFeedback-switch{cursor:pointer;color:#0645AD;float:right;line-height:1.4em;background-repeat:no-repeat;background-position:right center;padding-right:22px}.articleFeedback-switch:hover{text-decoration:underline}.articleFeedback-switch-form{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAMFBMVEXx8fHz8/PNzc3Z2dnc3NzIyMjf39/19fX4+Pjo6Ojl5eXu7u7Ozs7v7+/Gxsb5+fkia50iAAAAaElEQVR4XpXPsRFGQBQE4L+DvwmxDpwWVEIHRGIdkEjVoAMjkRIg3WFIb7hjx0vZ5H2z85L9HU+W9/6L10C8jeIONa1LF051O4RNdHm3nPivjH06BeaMjgEkdI8GA517WhV0ay77T1tOIsTW/fHbXVUAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/form.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-switch-report{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVAQMAAACT2TfVAAAABlBMVEXGxsb5+fnsr7DUAAAAJUlEQVR4XmXKoQ0AAAgDMCSOd3mXL+aGICGQiboaCRWH56pvrmoALTCmf8G/BQAAAABJRU5ErkJggg==);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/report.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-switch-form:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAMFBMVEWmpqbDw8OdnZ3q6uq+vr7m5ua7u7vn5+fZ2dny8vLU1NT4+PjIyMju7u6ZmZn5+flWE2OtAAAAZklEQVR4Xo3KsRFAMABGYRbIEvahMEAqrRGSDdiAU1jAAjZgBgrlf5yLzsWF/6TNq77iRfZvD7f2vhPva/NWkLTpBOL+8wTX/PpwXPinADJ6ANaRbgC0tIKApqvClDWdW3tKmgX5Ac8L1W9+Xeh1AAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/form-hover.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-switch-report:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVAQMAAACT2TfVAAAABlBMVEWZmZn5+fk4Wk0YAAAAJUlEQVR4XmXKoQ0AAAgDMCSOd3mXL+aGICGQiboaCRWH56pvrmoALTCmf8G/BQAAAABJRU5ErkJggg==);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/report-hover.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-explanation,.articleFeedback-description{float:left;font-weight:bold;margin-bottom:0.75em}.articleFeedback-rating-labels{margin-left:10px}.articleFeedback-rating-label,.articleFeedback-rating-clear{float:left;height:21px;width:21px;background-repeat:no-repeat;background-position:center center;cursor:pointer}.articleFeedback-rating-label{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAASFBMVEXz8/P4+Pi9vb3i4uLDw8O+vr7t7e3g4ODW1tbm5ubl5eXCwsLV1dXb29vk5OTT09PExMTc3Nzy8vLU1NTPz8/S0tLQ0ND5+flW2nGXAAAAWElEQVR4XsXQxw6AQAgEUGBrsdf//1Pj6kGQo4lzfCEzCbBr+VQnTcGCopHiSyE5cgmY5kJXinnezreurAG3igvy3q6qEWtj1VZoYwOEoRfqz0b0+h9+0QNg2iL1y1GKrwAAAABJRU5ErkJggg==);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/star-empty.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-rating-clear{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVAgMAAADUeU0FAAAADFBMVEXx8fH8/PzJycn5+flEd5eJAAAAO0lEQVR4Xo3NsREAEBQDUCuozRWNDWMIltHYgIaLhubfSfMuRS5uKdWCRXRSNMSnDaSDDz/cwWQW9u0GujBmctnuAjcAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/trash.png?2012-04-10T19:11:40Z)!ie;display:none}.articleFeedback-rating-labels:hover .articleFeedback-rating-clear{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVAgMAAADUeU0FAAAADFBMVEXPz8////+ZmZn5+fnMM0knAAAAO0lEQVR4Xo3NsREAEBQDUCuozRWNDWMIltHYgIaLhubfSfMuRS5uKdWCRXRSNMSnDaSDDz/cwWQW9u0GujBmctnuAjcAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/trash-hover.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-rating-label.articleFeedback-rating-label-full{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAclBMVEVDctAzZsw1aM3r7/bU3fHd5PPK1u6etuSnvOaAn904ac3b4/I/b8/y9Pf09vh5mtxPe9JIdtG/zuzi6PTk6fT5+fmMqOCctORbg9X4+PjD0e1NedKOqeGswOiQq+HBz+yqvueTreLR3PBYgtTY4fKlu+aQMOVWAAAAg0lEQVR4XpXORw7DMBBD0aGKey/pvdz/ihHiWCFibfI3At6CIxlDkeqQ6kYH9ITVUvsMmV1oDaD+UfNUcMU3r126wbd72r11aMG1w7RghVDyedcUHgvjYDtdi9QHVUR/qDBXkVqvD9Kd1zPpEZB1HwuQkF73Seme8tIcSPNxjna5v/UFoeEbk8m/710AAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/star-full.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-expired .articleFeedback-rating-label.articleFeedback-rating-label-full{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAb1BMVEWisc6aqsrs7vKbq8vn6vDy8/b29vegr82crMvu8PPv8fS8xtvd4uvq7fLj5u6ntdGkss+/ydzN1eP39/jS2OamtNDHz+De4+ytutPGzuDEzd/p7PHU2ufI0OHR2OXM1OOsudPT2ebm6fDf5Oz5+fk1ZxUDAAAAgUlEQVR4XpXQxQ7DMBRE0TeGMEOR4f+/sVHhZdR407uxdBZjy/IIRepD6msf0BV2S00TJGahOYD8R93JYqq7qRbtBnOXtnhp1oBrsveCEUIpv7suVozdfFtlP2grekOvAz2pUd2T3lXXpAdAzmknwEB6HIdoOqJrvSUt9bdol/tbn5e/LEunDQ/5AAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/star-full-expired.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-rating-new .articleFeedback-rating-label.articleFeedback-rating-label-full,.articleFeedback-rating .articleFeedback-rating-label.articleFeedback-rating-label-hover-tail{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAb1BMVEW/FRW6AAD15+ftysrw1ta7AwPDIyPqvr6+Dw/fkpLy3Nz48/Py39/38PDSYWHv09PQWFjmsLC7Bgbch4fBGhrYeHjHMjLYdXXhmJjekJDsx8fv0NDglZXotrbWb2/ns7PXcnLbhITCICDGLy/5+fmoneOTAAAAgUlEQVR4XpXQxQ7DMBRE0TeGMEOR4f+/sVHhZdR407uxdBZjy/IIRWpCaiIT0DVOS806dG6hDYDmR+3WY6rfqbbVCnP3qn1pMYAbiveCE0Kpv7s2UUzsfFvsP+hjekOuAzmpU92THlXPpBtArlkvQEo63tJyOspDdCGt9bdol/tbn6NzLEuinjAbAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/star-new.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-rating .articleFeedback-rating-label.articleFeedback-rating-label-hover-head{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAwFBMVEXi4uLp6enl5eXn5+fh4eHc3Ny6AADy8vLe3t709PTf39/5+fnd3d3v7+/gvb3a2triyMjj4+O7AwPb29vMWlrm2dm9Dg7WiYn19fW/GRnx8fG7BQXhw8PixcXo6Ojk5OTbpKTg4ODTfn7o5OTcqam+ExPesrLBISHk0NDLUlLn4eHjzs7r6+vAHh7PaGjq6urk19fDLCzTe3vQa2vDLy/w8PDXj4/m5ub29vbs7Oz39/fVhobQbm7RcHDWjIzgurqyWtoLAAAA+klEQVR4Xk3RxXYDMQyGUf2S7eEJMzOVmfv+b1U5Pknz7XQ3so8oO1ZM4kqlEb/2w3jUKLWG5U7YWJOc9L1BArQ2LUDIFkGvGgzty91AY/vsNQp4GLhBNXCimhJ8O+fcDj6qZVRYUSs/606b/6qKTahmps0n9999c2pAlrc9d1lvyzOqCKqrC1yNILFXlO0ztktA8qNiXXeh+hqqMeWsunCnFqpsaGJUq2cdqpox9a0Ay7MuAckTygwBL7r74TDXt3QAYv1xYhnf1509gP3P5hEcv6lmheURTg05jzJVzyQICcWKqlq35m8hwibnjyyoLxnP0jQ1t90w/gFYfxMie6zZxgAAAABJRU5ErkJggg==);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/star-new-hover.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-rating-new .articleFeedback-rating-label.articleFeedback-rating-label-down{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAwFBMVEXk5OTl5eXp6empAADh4eHc3Nz09PTn5+eaAQHi4uLe3t7v7+/f39/d3d2iAACyAACSAQH5+fmtAADb29vZvLzMiora2trx8fGjLi7dyMiiHBzy8vLj4+Po6Oji2dnm4eHg4ODdxcXdw8OxExO4b2/o5OTg0ND39/fVrKy5AADr6+vNpKS2AACaFhbLfX2uWlqXISHs7Oy6UlKwUlK0WlrduLirISHg19eqERG0Dg7izs7Aa2vezs64aGjFhobGj4/tunCpAAABE0lEQVR4XjXR1ZIEMQgF0EC8Xcfdfd3t//9qoXvmvqQ4RUFSEXmTUASdThlAty0bHUZagX2zoLQyN30ovUWc3E8Qrddhq4cSkLLKfvgA3WUdtvidOddv2ZBGHjlPLkkekeNHuQi1Jat+XSILealIrTZipI53vcwRpmkqE9d7PioUGjbnjBvT0+mUFjIZbGAmOhb75wb3+z3xco42YMXqXTIyf9BkGzeKO1lc9QWRe2MgXdOuRtM1KSghFGnfyevcBakaiy7fd+doHafY8VgjcuUR/1yyvHxeloWsET3Qi40GXA3qKSJO69cvhGBLmoca5njLAuJhTsrs7RWtDwhJKWbEf2EtqBi2DKzs41kURepg2vIfy7cbkARQ4ucAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/star-new-down.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-rating-tooltip{float:left;width:12em;margin-left:12px;color:#999999;font-size:0.9em;display:none}.articleFeedback-rating{float:left;width:11em;height:5em;margin-bottom:0.5em}.articleFeedback-rating-average{float:left;margin-right:0.5em;width:2em;text-align:right;font-size:0.8em;line-height:17px}.articleFeedback-rating-meter{float:left;height:17px;width:104px;border:solid 1px #cccccc;border-radius:3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAMFBMVEXPz8/R0dHr6+vo6Ojl5eXv7+/p6ent7e3n5+fk5OTu7u7i4uLs7Ozm5ubj4+Pq6uriFcL7AAAARUlEQVR4XlXGQQ2AMBQFwZXwNWChFrCAhVrAAhawgIVaqAUs1ALcNnlzGoaIL+Vv5XfBq/wlaIIu+FTxTcVU/lTxKH+ofmHJh1+heZyrAAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/segment-empty.png?2012-04-10T19:11:40Z)!ie;background-repeat:repeat-x;background-position:center left;overflow:hidden}.articleFeedback-rating-meter div{float:left;height:17px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAUVBMVEUxYrLF0+vD0enG1OzE0urE0+o1ZbbC0ejD0uk8bL05aboyY7M2ZrczY7Q8bb06ars3Z7g4aLkyYrM0ZLU9br4xYbI6a7s3aLg7a7w0ZbU9bb64TMrYAAAASklEQVR4XnXIxwHEMAzAMEq209v1sv+gWYDBEzxF4S+udhOFURS+IniLYBfBJIKbaHxE4xCVRVQ6UfmJgYdIVpHMIrmLxPS8RH8C5R0bZN8+lMYAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/segment-full.png?2012-04-10T19:11:40Z)!ie;background-repeat:repeat-x;background-position:center left}.articleFeedback-rating-count{float:right;font-size:0.8em;color:#999999;cursor:default;margin-right:1em}.articleFeedback-label{cursor:pointer;padding-left:20px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAMFBMVEX09PR9fX3g4OCioqJzc3Pe3t7c3Nytra1mZmbQ0NDb29u+vr7X19eZmZn////5+fmnjGD8AAAAXElEQVR4Xp3OMQ5AQBRFUb0dKCSin06psRW9Qq9TS2zAzp5YAI/4UQrFz/zp51anvMlnXRG+BwC9WjqSrfrlPC6Hd5bmZu5rcOHMZ0MzGbxN3uJIluqnBlCpo/9/71rVS3Lpa5IAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/question.png?2012-04-10T19:11:40Z)!ie;background-repeat:no-repeat;background-position:center left}.articleFeedback-label:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAMFBMVEWKior09PTZ2dl7e3vg4OBzc3Ov2vm43vnKysrl8flmZmbi7/nj8v2n1/n////5+flMFkeiAAAAXUlEQVR4Xp3OoQ2AMABEUSZAMwcr4FFs0XQABArPFljGQLLBCfAcKBJCGiBpuApcTz11+cmt7RE+GwC19zGRHL0d275bP+dZKnMJZlHKW0WZDJ4Hrv//ywIwcc3yA80N14TxKYl7AAAAAElFTkSuQmCC);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/question-hover.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-submit{float:right}.articleFeedback-expertise-disabled,.articleFeedback-helpimprove-disabled{color:silver}.articleFeedback-expertise{float:left;margin-bottom:0.5em;margin-top:0.75em}.articleFeedback-expertise input{float:left;margin-bottom:0.5em;clear:both;cursor:pointer}.articleFeedback-expertise label{margin-left:0.5em;margin-bottom:0.5em;float:left;line-height:1.4em;cursor:pointer}.articleFeedback-expertise-options{clear:both;display:none}.articleFeedback-expertise-options input{display:block;clear:both;margin-left:2em}.articleFeedback-expertise-options label{line-height:1.6em}.articleFeedback-expertise-options .articleFeedback-helpimprove-email{width:20em;margin-left:4em;margin-top:0.25em;cursor:text}.articleFeedback-helpimprove-note{margin-left:4em;font-size:0.8em;clear:both}.articleFeedback-helpimprove-email.valid{background-color:#C0FFC0}.articleFeedback-helpimprove-email.invalid{background-color:#FFC0C0}.articleFeedback-pending,.articleFeedback-success{float:right}.articleFeedback-pending span,.articleFeedback-success span{display:none;padding:12px 12px 12px 28px;font-size:0.8em;line-height:3.6em;background-repeat:no-repeat;background-position:center left;color:green}.articleFeedback-pending span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAwFBMVEX5+flstCdarQt9vEB5tj6Eq194o1CbxnSCqVx5s0K+z69gqByiyX5UpAjx8fGUtXVitw9mvxFesg2EulF+qlWBukpRnQmIrmWExUVyrzmfwX+v0Y5XqAqhvIiPv2GLr2l9tkj19fRToAtym0qV21HO18WJzkZuyRXo6ejw8u2ZxW+Ls2VmqiVZjCmFtllPmwad3GCDsFXY4s6JtV1vrTXB3KhPhBt/zTOIu1fc3dqky4CRv2Tj692wyJuPylWQx1oK/jCbAAAAAXRSTlMAQObYZgAAAMNJREFUeF610TV2A0EQRdHGYWZmMcvM+9+VS8FY7eNxqBfWjf4pdJPK8z+gZNo08IesnIZcNuL2F9TxpV1eVYayEsE2jFdIfvZ9OXgXYKM2YehDYaO+KTMRVCCIsjT1Nx9XuE8Zo5RivegO0fbOHoHr+hZjx/MIAen20gjBwSyI5zhAhamfbPQDkQl313Udj+CgvG7hjCbJfP4EQiVN2Cj1lx6HhZv0M7iLtZalDItP6QX9LT5+8SWaqF6X1vSjNHSbvgFSNhGzJvYynQAAAABJRU5ErkJggg==);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/attention.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-success span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAulBMVEX5+fl8pFWDqjTi6Nx5n05/pjOQtEWLsT2kwmR3nyeoyl10lFJ6nVN1mkuJrF2TtWSwzXi82X2PtEKTu0W92oWnxXWZvkuuyXT29/WszGaXuGaQsW3U286GpmbN08eryXru8eyKrjzq7efd49jF0biy0XGawUyrvZaswpZqhFCatny4xaqbvGyhwVqkwXN3m1OgvWK41XuFq1mQr3Ocs4Su0WOUtUuz1mWGqTubuVehv1uCplWjx1Z8pC93iUb/AAAAAXRSTlMAQObYZgAAAMRJREFUeF6lkUVuQ0EQBYc/MzObmcL3v5aTlceZ2bkW3VI99aL1wOss1nIf5g0sZQEJ38LiLPp5dJ3pYSH4lHjxzDMHIVg137G+mwu+hVMQHPdAALox0/ORM0P6N0s784MEcn5tE/y7TFdRVBs/fE+8hIygdLadH1XcgZkhJSsuRoLQ9qvnAstFCH06G4aUzQpwYBL5P5QxSlUrfX7Y2N00SmmXL8A/KudDo9oBpmINJ1V7d2Rd1Et1WgIZrWHVQArG4CXuoiYOJw5+/RcAAAAASUVORK5CYII=);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/success.png?2012-04-10T19:11:40Z)!ie}.articleFeedback-expiry{display:none;border:solid 1px orange;background-color:white;padding:0.5em}.articleFeedback-expiry-title{font-size:1.2em;padding-left:28px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAABelBMVEX/ngD/owD/qAD/qwD/44j/89L/lgD/jgD////+nQD/y1P//fz/kwLzjwD8rADVcgDfegP//vv/y1//4p7/6rT/tFrxxFr6lwD/pzL//Pf/sgD/xFX/2Xz/7cf++/P/1pj6sAD/tir/8MX++vPfoFf/uBX+7LfyuRv/nxX/7rrzxnjuphv99uT/9d/9pwD/mgH/yFv/uQX66cP/rgD/kgD/mgD//vz/iwDZdQD/9df/6rP/yDDz0371pAD/9t7/7bv/u0b/kwz537r/24j/uwj/xU7/4Zj/34L8kAD/sA71y5b/x3z1hgD3swD/vEX/4oH88Nv/0W3/+u7fgxX/79nunTD/2Wn/zUj9t2b/wCH/9+r/2nb/wVv/2X3/4r7/sj32iQD/4JfusjD/myT/xj722Zz/v0j/pgf/5ZH+tgD/wE3/uFP/2IT/6qX/vzXzqgDwlwb/qR3//v3wsAz/887/1Xj/0mHvr0v/4av/7K/4nwD/zW3/sEz/wU+nYJHVAAAA1klEQVR4XoXRU5MDQRSG4e4exrZte23btm3vf9/pZHeSTrYq78V3qp7bA/j/qmtlJdiqms3OkLNF9atD013NuvCynjl/jDfpyJG9Z9ttJDUhDTAVxnqbJfTqJtfx1JtTHhQb1DE8Tu17dRTVfVxXy6cHoefIIELJmE/Ut5lTCLXv8xDCj+ifbmzdAwBOrtPCSu7mftW1myqImV5runQZZoUuzmwsTjGA9WHSnMeN0rQc37HloqA7X/0crm/2m6u2NyGo4bBENrUoA/yaukym8vPtftFefwCV7jDM8Iy11wAAAABJRU5ErkJggg==);background-image:url(//bits.wikimedia.org/w/extensions-1.20wmf1/ArticleFeedback/modules/jquery.articleFeedback/images/alert.png?2012-04-10T19:11:40Z)!ie;background-repeat:no-repeat;background-position:center left}.articleFeedback-expiry-message{padding-left:28px;color:#777777}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:89022500e420fcd271f2996fe8292835 */</style><style type=\"text/css\">#articleFeedback-dialog{padding:2em;padding-top:1em}.articleFeedback-survey-disclaimer{font-weight:normal; font-style:italic}.articleFeedback-survey-disclaimer a{color:#0645AD; }\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:dc196b791bc596864c79249f49472c3c */</style><meta name=\"ResourceLoaderDynamicStyles\" content=\"\">\n<link rel=\"stylesheet\" href=\"England%28Chinese%29_files/load.css\" type=\"text/css\" media=\"all\">\n<style type=\"text/css\" media=\"all\">a:lang(ar),a:lang(ckb),a:lang(fa),a:lang(kk-arab),a:lang(mzn),a:lang(ps),a:lang(ur){text-decoration:none}\n\n/* cache key: zhwiki:resourceloader:filter:minify-css:7:d5a1bf6cbd05fc6cc2705e47f52062dc */</style>\n\n<script src=\"England%28Chinese%29_files/load_008.php\" type=\"text/javascript\"></script><script src=\"England%28Chinese%29_files/load.php\" type=\"text/javascript\"></script>\n<script type=\"text/javascript\">if(window.mw){\nmw.config.set({\"wgCanonicalNamespace\":\"\",\"wgCanonicalSpecialPageName\":false,\"wgNamespaceNumber\":0,\"wgPageName\":\"英国\",\"wgTitle\":\"英国\",\"wgCurRevisionId\":20918917,\"wgArticleId\":39793,\"wgIsArticle\":true,\"wgAction\":\"view\",\"wgUserName\":null,\"wgUserGroups\":[\"*\"],\"wgCategories\":[\"含有英語的條目\",\"自2012年2月需补充来源的条目\",\"自2012年3月需要维基化的页面\",\"含有法語的條目\",\"含有蘇格蘭蓋爾語的條目\",\"含有低地蘇格蘭語的條目\",\"英联邦\",\"北大西洋公约组织\",\"八國集團\",\"地中海聯盟成員國\",\"环印度洋区域合作联盟成员国\",\"英国\",\"欧洲岛国\",\"核武國家\",\"新教国家\",\"君主立憲國\",\"联合国创始会员国\",\"联合国安全理事会常任理事国\"],\"wgBreakFrames\":false,\"wgPageContentLanguage\":\"zh\",\"wgSeparatorTransformTable\":[\"\",\"\"],\"wgDigitTransformTable\":[\"\",\"\"],\"wgRelevantPageName\":\"英国\",\"wgUserVariant\":\"zh\",\"wgRestrictionEdit\":[],\"wgRestrictionMove\":[],\"wgSearchNamespaces\":[0],\"wgVectorEnabledModules\":{\"collapsiblenav\":true,\"collapsibletabs\":true,\"editwarning\":true,\"expandablesearch\":false,\"footercleanup\":false,\"sectioneditlinks\":false,\"simplesearch\":true,\"experiments\":true},\"wgWikiEditorEnabledModules\":{\"toolbar\":true,\"dialogs\":true,\"hidesig\":true,\"templateEditor\":false,\"templates\":false,\"preview\":false,\"previewDialog\":false,\"publish\":false,\"toc\":false},\"wgTrackingToken\":\"aa85e752d36ce4fc7df098ea0179055f\",\"wikilove-recipient\":\"\",\"wikilove-edittoken\":\"+\\\\\",\"wikilove-anon\":0,\"wgCategoryTreePageCategoryOptions\":\"{\\\"mode\\\":0,\\\"hideprefix\\\":20,\\\"showcount\\\":true,\\\"namespaces\\\":false}\",\"Geo\":{\"city\":\"\",\"country\":\"\"},\"wgNoticeProject\":\"wikipedia\"});\n}</script><script type=\"text/javascript\">if(window.mw){\nmw.loader.implement(\"user.options\",function(){mw.user.options.set({\"ccmeonemails\":0,\"cols\":80,\"date\":\"default\",\"diffonly\":0,\"disablemail\":0,\"disablesuggest\":0,\"editfont\":\"default\",\"editondblclick\":0,\"editsection\":1,\"editsectiononrightclick\":0,\"enotifminoredits\":0,\"enotifrevealaddr\":0,\"enotifusertalkpages\":1,\"enotifwatchlistpages\":0,\"extendwatchlist\":0,\"externaldiff\":0,\"externaleditor\":0,\"fancysig\":0,\"forceeditsummary\":0,\"gender\":\"unknown\",\"hideminor\":0,\"hidepatrolled\":0,\"imagesize\":2,\"justify\":0,\"math\":0,\"minordefault\":0,\"newpageshidepatrolled\":0,\"nocache\":0,\"noconvertlink\":0,\"norollbackdiff\":0,\"numberheadings\":0,\"previewonfirst\":0,\"previewontop\":1,\"quickbar\":5,\"rcdays\":7,\"rclimit\":50,\"rememberpassword\":0,\"rows\":25,\"searchlimit\":20,\"showhiddencats\":false,\"showjumplinks\":1,\"shownumberswatching\":1,\"showtoc\":1,\"showtoolbar\":1,\"skin\":\"vector\",\"stubthreshold\":0,\"thumbsize\":4,\"underline\":2,\"uselivepreview\":0,\"usenewrc\":0,\"watchcreations\":1,\"watchdefault\":0,\"watchdeletion\":0,\"watchlistdays\":3\n,\"watchlisthideanons\":0,\"watchlisthidebots\":0,\"watchlisthideliu\":0,\"watchlisthideminor\":0,\"watchlisthideown\":0,\"watchlisthidepatrolled\":0,\"watchmoves\":0,\"wllimit\":250,\"vector-simplesearch\":1,\"useeditwarning\":1,\"vector-collapsiblenav\":1,\"usebetatoolbar\":1,\"usebetatoolbar-cgd\":1,\"wikilove-enabled\":1,\"variant\":\"zh\",\"language\":\"zh\",\"searchNs0\":true,\"searchNs1\":false,\"searchNs2\":false,\"searchNs3\":false,\"searchNs4\":false,\"searchNs5\":false,\"searchNs6\":false,\"searchNs7\":false,\"searchNs8\":false,\"searchNs9\":false,\"searchNs10\":false,\"searchNs11\":false,\"searchNs12\":false,\"searchNs13\":false,\"searchNs14\":false,\"searchNs15\":false,\"searchNs100\":false,\"searchNs101\":false,\"gadget-AdvancedSiteNotices\":1,\"gadget-hideConversionTab\":1,\"gadget-large-font\":1,\"gadget-WikiMiniAtlas\":1});;},{},{});mw.loader.implement(\"user.tokens\",function(){mw.user.tokens.set({\"editToken\":\"+\\\\\",\"watchToken\":false});;},{},{});\n\n/* cache key: zhwiki:resourceloader:filter:minify-js:7:10e4f2bfceaabe778b63a9beb06d67ad */\n}</script>\n<script type=\"text/javascript\">if(window.mw){\nmw.loader.load([\"mediawiki.page.startup\",\"mediawiki.legacy.wikibits\",\"mediawiki.legacy.ajax\"]);\n}</script><script type=\"text/javascript\" src=\"England%28Chinese%29_files/load_007.php\"></script>\n<script src=\"England%28Chinese%29_files/OggPlayer.js\" type=\"text/javascript\"></script><script type=\"text/javascript\">\nwgOggPlayer.msg = {\"ogg-play\":\"播放\",\"ogg-pause\":\"暂停\",\"ogg-stop\":\"停止\",\"ogg-no-player\":\"抱歉，您的系统并无任何可以支持播放的播放器。请安装\\x3ca href=\\\"http://www.java.com/zh_CN/download/manual.jsp\\\"\\x3eJava\\x3c/a\\x3e。\",\"ogg-player-videoElement\":\"\\x3cvideo\\x3e元素\",\"ogg-player-oggPlugin\":\"Ogg插件\",\"ogg-player-cortado\":\"Cortado (Java)\",\"ogg-player-vlc-mozilla\":\"VLC\",\"ogg-player-vlc-activex\":\"VLC (ActiveX)\",\"ogg-player-quicktime-mozilla\":\"QuickTime\",\"ogg-player-quicktime-activex\":\"QuickTime (ActiveX)\",\"ogg-player-totem\":\"Totem\",\"ogg-player-kaffeine\":\"Kaffeine\",\"ogg-player-kmplayer\":\"KMPlayer\",\"ogg-player-mplayerplug-in\":\"mplayerplug-in\",\"ogg-player-thumbnail\":\"只有静止图像\",\"ogg-player-selected\":\"（已选取）\",\"ogg-use-player\":\"使用播放器:\",\"ogg-more\":\"更多...\",\"ogg-download\":\"下载文件\",\"ogg-desc-link\":\"关于这个文件\",\"ogg-dismiss\":\"关闭\",\"ogg-player-soundthumb\":\"沒有播放器\",\"ogg-no-xiphqt\":\"您似乎没有给QuickTime用的XiphQT组件。在未有这个组件的情况下，QuickTime是不能播放Ogg文件的。请\\x3ca href=\\\"http://www.mediawiki.org/wiki/Extension:OggHandler/Client_download\\\"\\x3e下载XiphQT\\x3c/a\\x3e或者选取另一个播放器。\"};\nwgOggPlayer.cortadoUrl = \"//upload.wikimedia.org/jars/cortado.jar\";\nwgOggPlayer.extPathUrl = \"//bits.wikimedia.org/w/extensions-1.20wmf1/OggHandler\";\n</script><style type=\"text/css\" media=\"all\">\n.ogg-player-options {\n\tborder: solid 1px #ccc;\n\tpadding: 2pt;\n\ttext-align: left;\n\tfont-size: 10pt;\n}\n\n.center .ogg-player-options ul {\n\tmargin: 0.3em 0px 0px 1.5em;\n}\n</style><!--[if lt IE 7]><style type=\"text/css\">body{behavior:url(\"/w/skins-1.20wmf1/vector/csshover.min.htc\")}</style><![endif]--></head>\n<body class=\"mediawiki ltr sitedir-ltr ns-0 ns-subject page-英国 skin-vector action-view\">\n\t\t<div id=\"mw-page-base\" class=\"noprint\"></div>\n\t\t<div id=\"mw-head-base\" class=\"noprint\"></div>\n\t\t<!-- content -->\n\t\t<div id=\"content\" class=\"mw-body\">\n\t\t\t<a id=\"top\"></a>\n\t\t\t<div class=\"js-messagebox\" id=\"mw-js-message\" style=\"display:none;\"></div>\n\t\t\t\t\t\t<!-- sitenotice -->\n\t\t\t<div id=\"siteNotice\"><!-- centralNotice loads here --><script type=\"text/javascript\">\n/* <![CDATA[ */\ndocument.writeln(\"\\x3cdiv id=\\\"localNotice\\\" lang=\\\"zh\\\" dir=\\\"ltr\\\"\\x3e\\x3c/div\\x3e\");\n/* ]]> */\n</script><div id=\"localNotice\" dir=\"ltr\" lang=\"zh\"></div>\n<table id=\"asn-dismissable-notice\" style=\"background: none repeat scroll 0% 0% transparent;\" width=\"100%\"><tbody><tr><td><div style=\"min-height: 24px; display: block;\" id=\"advancedSiteNotices\"><b><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:WPTP-W\" title=\"Wikipedia:WPTP-W\" class=\"mw-redirect\">「維基台北寫作聚」每月第二個禮拜六舉辦</a></b>；<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E8%81%9A%E4%BC%9A/%E5%8F%B0%E7%81%A3%E7%B6%AD%E5%9F%BA%E4%BA%BA%E5%8F%B0%E4%B8%AD%E8%81%9A%E6%9C%83\" title=\"Wikipedia:聚会/台灣維基人台中聚會\"><b>維基人台中聚會</b></a>每月舉辦，有興趣參與者請點選<a href=\"http://zh.wikipedia.org/wiki/Wikipedia_talk:%E8%81%9A%E4%BC%9A/%E5%8F%B0%E7%81%A3%E7%B6%AD%E5%9F%BA%E4%BA%BA%E5%8F%B0%E4%B8%AD%E8%81%9A%E6%9C%83\" title=\"Wikipedia talk:聚会/台灣維基人台中聚會\">了解時間與地點</a>。</div></td><td>[<a href=\"#\">关闭</a>]</td></tr></tbody></table></div>\n\t\t\t<!-- /sitenotice -->\n\t\t\t\t\t\t<!-- firstHeading -->\n\t\t\t<h1 id=\"firstHeading\" class=\"firstHeading\"><div style=\"float: right;\"><div class=\"topicon\" style=\"float: right; position: static;\"><span id=\"coordinates\" style=\"font-size: small;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%B0%E7%90%86%E5%9D%90%E6%A0%87\" title=\"地理坐标\" class=\"mw-redirect\">坐标</a>：<span class=\"Unicode\"><span class=\"plainlinks nourlexpansion\"><span style=\"white-space: nowrap;\"><img style=\"padding: 0px 3px 0px 0px; cursor: pointer;\" class=\"noprint\" alt=\"\" title=\"显示该地在地图上的位置\" src=\"England%28Chinese%29_files/17px-WMA_button2b.png\"><a style=\"white-space: normal;\" rel=\"nofollow\" class=\"external text\" href=\"http://toolserver.org/%7Egeohack/geohack.php?language=zh&amp;pagename=%E8%8B%B1%E5%9B%BD&amp;params=55_0_46_N_3_26_48_W_region:ID_type:landmark\"><span class=\"geo-default\"><span class=\"geo-dms\" title=\"此地的地图、航拍照片和其他数据\"><span class=\"latitude\">55°0′46″N</span> <span class=\"longitude\">3°26′48″W</span></span></span><span class=\"geo-multi-punct\">﻿ / ﻿</span><span class=\"geo-nondefault\"><span class=\"geo-dec\" title=\"此地的地图、航拍照片和其他数据\">55.01278°N 3.44667°W</span><span style=\"display:none\">﻿ / <span class=\"geo\">55.01278; -3.44667</span></span></span></a></span></span></span></span></div></div>\n\t\t\t\t<span dir=\"auto\">英国</span>\n\t\t\t</h1>\n\t\t\t<!-- /firstHeading -->\n\t\t\t<!-- bodyContent -->\n\t\t\t<div id=\"bodyContent\">\n\t\t\t\t\t\t\t\t<!-- tagline -->\n\t\t\t\t<div id=\"siteSub\">维基百科，自由的百科全书</div>\n\t\t\t\t<!-- /tagline -->\n\t\t\t\t\t\t\t\t<!-- subtitle -->\n\t\t\t\t<div id=\"contentSub\"></div>\n\t\t\t\t<!-- /subtitle -->\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<!-- jumpto -->\n\t\t\t\t<div id=\"jump-to-nav\" class=\"mw-jump\">\n\t\t\t\t\t跳转到： <a href=\"#mw-head\">导航</a>,\n\t\t\t\t\t<a href=\"#p-search\">搜索</a>\n\t\t\t\t</div>\n\t\t\t\t<!-- /jumpto -->\n\t\t\t\t\t\t\t\t<!-- bodycontent -->\n\t\t\t\t<div id=\"mw-content-text\" dir=\"ltr\" class=\"mw-content-ltr\" lang=\"zh\"><table class=\"metadata plainlinks ambox ambox-content\" style=\"\">\n<tbody><tr>\n<td class=\"mbox-image\">\n<div style=\"width: 52px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Question_book-4.svg\" class=\"image\"><img alt=\"Question book-4.svg\" src=\"England%28Chinese%29_files/50px-Question_book-4.png\" height=\"39\" width=\"50\"></a></div>\n</td>\n<td class=\"mbox-text\" style=\"\"><b>此条目需要补充更多<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%88%97%E6%98%8E%E6%9D%A5%E6%BA%90\" title=\"Wikipedia:列明来源\">来源</a></b>。<small><i>（2012年2月26日）</i></small><br>\n<small>请协助添加来自<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%8F%AF%E9%9D%A0%E6%9D%A5%E6%BA%90\" title=\"Wikipedia:可靠来源\">可靠来源</a>的引用以<a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit\">改善这篇条目</a>。<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%8F%AF%E4%BE%9B%E6%9F%A5%E8%AF%81\" title=\"Wikipedia:可供查证\" class=\"mw-redirect\">无法查证</a>的内容会被<a href=\"http://zh.wikipedia.org/wiki/Template:Fact\" title=\"Template:Fact\">提出异议</a>而移除。</small></td>\n</tr>\n</tbody></table>\n<table class=\"metadata plainlinks ambox ambox-style\" style=\"\">\n<tbody><tr>\n<td class=\"mbox-image\">\n<div style=\"width: 52px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Wikify_logo-2.svg\" class=\"image\"><img alt=\"Wikify logo-2.svg\" src=\"England%28Chinese%29_files/50px-Wikify_logo-2.png\" height=\"11\" width=\"50\"></a></div>\n</td>\n<td class=\"mbox-text\" style=\"\"><b>此條目或章节需要被<a href=\"http://zh.wikipedia.org/wiki/Help:Wikify\" title=\"Help:Wikify\" class=\"mw-redirect\">修正為維基格式</a>以符合<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E6%A0%BC%E5%BC%8F%E6%8C%87%E5%8D%97\" title=\"Wikipedia:格式指南\" class=\"mw-redirect\">质量标准</a>。</b><small><i>（2012年3月29日）</i></small><br>\n<small>请协助添加<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%8F%AA%E5%BB%BA%E7%AB%8B%E8%88%87%E5%85%A7%E5%AE%B9%E7%9B%B8%E9%97%9C%E7%9A%84%E9%80%A3%E7%B5%90\" title=\"Wikipedia:只建立與內容相關的連結\">相关</a>的<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E6%A7%8B%E7%AF%89%E7%B6%B2%E8%B7%AF\" title=\"Wikipedia:構築網路\">内部链接</a>，并使用百科全书的语气来<a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit\">改善这篇条目</a>。</small></td>\n</tr>\n</tbody></table>\n<div class=\"notice metadata dablink\" style=\"font-size: small;\">\n<div>「<b>聯合王國</b>」重定向至此。關於与其同名的其他主题，詳見「<b><a href=\"http://zh.wikipedia.org/wiki/%E8%81%AF%E5%90%88%E7%8E%8B%E5%9C%8B_%28%E6%B6%88%E6%AD%A7%E7%BE%A9%29\" title=\"聯合王國 (消歧義)\">聯合王國 (消歧义)</a></b>」。</div>\n</div>\n<div class=\"nomobile\"><span style=\"display: none;\"><a href=\"#_skip_noteTA\">跳过字词转换说明</a></span>\n<div class=\"NavFrame collapsed noprint nohandheld metadata\" style=\"z-index: 1; margin: 0 0.5em 0.5em auto; top: -1.2em; position: relative; background-color: transparent; border: none;\">\n<div tabindex=\"0\" class=\"uncollapse toggleHotspot\" style=\"position: absolute; right: 0pt; background-color: transparent; padding: 0pt; width: 4em; cursor: pointer;\" title=\"本頁使用了標題或全文手工轉換，單擊檢視\"><span style=\"font-family:微软雅黑,Arial Unicode MS,黑体;\"><span style=\"padding:1px 3px; background: slategray; color:white;\">汉</span><span style=\"padding:1px 3px; background: sienna; color:white;\">漢</span></span><span class=\"toggleShow\" style=\"color: black;\">▼</span><span class=\"toggleHide\" style=\"color: black; display: none;\">▲</span></div>\n<div class=\"NavContent toggleHide\" style=\"position: absolute; display: none; right: 0; top: 1.5em; border: 1px gray solid; background-color: lightyellow; padding: 0.3em; z-index: 100; width: 650px; font-size: 90%; z-index: 100; background-color: #ffffff; color: #bf0a30;\">\n<div style=\"background: #FFEA88; background-color: #bf0a30; color: #ffffff;\">为了阅读方便，本文使用<a href=\"http://zh.wikipedia.org/wiki/Help:%E4%B8%AD%E6%96%87%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91%E7%9A%84%E7%B9%81%E7%AE%80%E5%A4%84%E7%90%86#.E6.8E.A7.E5.88.B6.E8.87.AA.E5.8A.A8.E8.BD.AC.E6.8D.A2.E7.9A.84.E4.BB.A3.E7.A2.BC\" title=\"Help:中文维基百科的繁简处理\" class=\"mw-redirect\"><span style=\"color:#ffff00;\">全文手工轉換</span></a>。转换内容：</div>\n<div style=\"height: 220px; overflow: auto; padding: 3px\">\n<p>下方采用<b>英国政治人物</b>組全文轉換 [<span class=\"editlink noprint plainlinksneverexpand\"><a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:CGroup/PoliticiansUK&amp;action=edit\"><span style=\"{{subst:substVar|linkStyle}}\">編輯</span></a></span>]</p>\n<ul>\n<li>Ashton, Catherine：<b>原文：艾嘉蓮女男爵；大陆：艾什顿女男爵；台灣：艾希頓女男爵；香港：艾嘉蓮女男爵；新加坡：艾什顿女男爵；</b> 当前語言下顯示→<b>艾嘉蓮女男爵</b></li>\n<li>Alan Johnson：<b>大陆：阿兰·约翰逊；台灣：艾倫·強生；香港：莊翰生；</b> 当前語言下顯示→<b>阿兰·约翰逊</b></li>\n<li>Beckett, Margaret：<b>大陆：玛格丽特·贝克特；台灣：瑪格麗特·貝克特；香港：貝嘉晴；新加坡：玛格丽特·贝克特；</b> 当前語言下顯示→<b>玛格丽特·贝克特</b></li>\n<li>Blair, Cherie：<b>大陆：切丽·布莱尔；台灣：雪麗·布萊爾；香港：彭雪玲；新加坡：切丽·布莱尔；</b> 当前語言下顯示→<b>切丽·布莱尔</b></li>\n<li>Blair, Tony：<b>大陆：托尼·布莱尔；台灣：東尼·布萊爾；香港：貝理雅；新加坡：托尼·布莱尔；</b> 当前語言下顯示→<b>托尼·布莱尔</b></li>\n<li>Brown, Gordon：<b>大陆：戈登·布朗；台灣：戈登·布朗；香港：白高敦；新加坡：戈登·布朗；</b> 当前語言下顯示→<b>戈登·布朗</b></li>\n</ul>\n<ul>\n<li>Cameron, David：<b>大陆：卡梅伦；台灣：卡麥隆；香港：卡梅倫；</b> 当前語言下顯示→<b>卡梅伦</b></li>\n<li>Cameron, David：<b>大陆：戴维·卡梅伦；台灣：大衛·卡麥隆；香港：大衛·卡梅倫；</b> 当前語言下顯示→<b>戴维·卡梅伦</b></li>\n<li>Camilla：<b>大陆：卡米拉；台灣：卡蜜拉；香港：卡米拉；</b> 当前語言下顯示→<b>卡米拉</b></li>\n<li>Charles：<b>大陆：查尔斯；台灣：查爾斯；香港：查理斯；</b> 当前語言下顯示→<b>查尔斯</b></li>\n<li>Cook, Robert：<b>简体：罗伯特·库克；台灣：羅伯特·庫克；香港：郭偉邦；</b> 当前語言下顯示→<b>罗伯特·库克</b></li>\n<li>Darling, Alistair：<b>大陆：阿利斯泰尔·达林；台灣：阿利斯泰爾·達林；香港：戴理德；新加坡：阿利斯泰尔·达林；</b> 当前語言下顯示→<b>阿利斯泰尔·达林</b></li>\n<li>Diana：<b>大陆：戴安娜；台灣：黛安娜；香港：戴安娜；新加坡：戴安娜；</b> 当前語言下顯示→<b>戴安娜</b></li>\n<li>Douglas Smith, Iain：<b>大陆：伊恩·邓肯·史密斯；台灣：伊恩·鄧肯·史密斯；香港：施志安；</b> 当前語言下顯示→<b>伊恩·邓肯·史密斯</b></li>\n<li>David Wright Miliband：<b>大陆：戴维·米利班德；台灣：大衛·米勒班；香港：文禮彬；</b> 当前語言下顯示→<b>戴维·米利班德</b></li>\n</ul>\n<ul>\n<li>Elizabeth：<b>大陆：伊丽莎白；台灣：伊麗莎白；香港：伊利沙伯；新加坡：伊丽莎白；</b> 当前語言下顯示→<b>伊丽莎白</b></li>\n<li>Edward Samuel Miliband：<b>大陆：爱德华·塞缪尔·米利班德；台灣：艾德·米勒班；香港：文立彬；</b> 当前語言下顯示→<b>爱德华·塞缪尔·米利班德</b></li>\n</ul>\n<ul>\n<li>Foot, Michael：<b>简体：迈克尔·富特；繁體：邁克爾·富特；香港：米高·富特；</b> 当前語言下顯示→<b>迈克尔·富特</b></li>\n</ul>\n<ul>\n<li>Geoff Hoon：<b>大陆：杰弗里·胡恩；台灣：傑夫·胡恩；香港：禤智輝；</b> 当前語言下顯示→<b>杰弗里·胡恩</b></li>\n<li>Hague, William：<b>大陆：威廉·黑格；台灣：威廉·海格；香港：夏偉林；新加坡：威廉·黑格；</b> 当前語言下顯示→<b>威廉·黑格</b></li>\n<li>Heseltine, Michael：<b>大陆：迈克尔·赫塞尔廷；台灣：麥可·赫塞爾廷；香港：夏舜霆；</b> 当前語言下顯示→<b>迈克尔·赫塞尔廷</b></li>\n<li>Howard, Michael：<b>大陆：迈克尔·霍华德；台灣：麥可·霍華德；香港：夏偉明；新加坡：迈克尔·霍华德；</b> 当前語言下顯示→<b>迈克尔·霍华德</b></li>\n<li>Hurd, Douglas：<b>大陆：道格拉斯·赫德；台灣：道格拉斯·赫德；香港：韓達德；</b> 当前語言下顯示→<b>道格拉斯·赫德</b></li>\n<li>Howe, Geoffery：<b>大陆：杰弗里·豪；台灣：杰弗里·豪；香港：賀維；</b> 当前語言下顯示→<b>杰弗里·豪</b></li>\n</ul>\n<ul>\n<li>Jack Straw：<b>大陆：杰克·斯特劳；台灣：傑克·斯特勞；香港：施仲宏；</b> 当前語言下顯示→<b>杰克·斯特劳</b></li>\n<li>Jacqui Smith：<b>大陆：雅基·史密斯；台灣：賈姬·史密斯；香港：施卓琪；</b> 当前語言下顯示→<b>雅基·史密斯</b></li>\n<li>John Reid：<b>大陆：约翰·里德；台灣：約翰·里德；香港：韋俊安；</b> 当前語言下顯示→<b>约翰·里德</b></li>\n<li>John Leslie Prescott：<b>大陆：约翰·普雷斯科特；台灣：約翰·普雷斯科特；香港：彭仕國；</b> 当前語言下顯示→<b>约翰·普雷斯科特</b></li>\n<li>King, The：<b>大陆：英王；台灣：英王；香港：英皇；新加坡：英王；</b> 当前語言下顯示→<b>英王</b></li>\n<li>Macmillan, Harold ：<b>大陆：麦克米伦；台灣：麥克米倫；香港：麥美倫；</b> 当前語言下顯示→<b>麦克米伦</b></li>\n<li>Major, John：<b>大陆：约翰·梅杰；台灣：約翰·梅傑；香港：馬卓安；新加坡：约翰·梅杰；</b> 当前語言下顯示→<b>约翰·梅杰</b></li>\n<li>Margaret：<b>大陆：玛格丽特；台灣：瑪格麗特；香港：瑪嘉烈；新加坡：玛格丽特；</b> 当前語言下顯示→<b>玛格丽特</b></li>\n<li>Michael：<b>大陆：迈克尔；台灣：麥可；香港：米高；新加坡：迈克尔；</b> 当前語言下顯示→<b>迈克尔</b></li>\n<li>Mandelson, Peter：<b>原文：文德森；大陆：曼德尔森；台灣：曼德森；香港：文德森；新加坡：曼德尔森；</b> 当前語言下顯示→<b>文德森</b></li>\n<li>May, Teresa：<b>原文：文翠珊；大陆：特雷莎·梅；台灣：特雷莎·梅；香港：文翠珊；新加坡：特雷莎·梅；</b> 当前語言下顯示→<b>文翠珊</b></li>\n<li>Miliband, David：<b>大陆：戴维·米利班德；台灣：大衛·米勒班；香港：文禮彬；</b> 当前語言下顯示→<b>戴维·米利班德</b></li>\n</ul>\n<ul>\n<li>Osborne, George：<b>大陆：乔治·奥斯本；台灣：喬治·奧斯本；香港：歐思邦；新加坡：乔治·奥斯本；</b> 当前語言下顯示→<b>乔治·奥斯本</b></li>\n<li>Peter Hain：<b>大陆：彼得·海恩；台灣：彼得·海恩；香港：韓培德；</b> 当前語言下顯示→<b>彼得·海恩</b></li>\n<li>Philip：<b>大陆：菲利普；台灣：菲利普；香港：菲臘；新加坡：菲利普；</b> 当前語言下顯示→<b>菲利普</b></li>\n<li>Philip,Nicholas：<b>大陆：菲利普斯勋爵；台灣：菲利普斯勋爵；香港：范理申勳爵；</b> 当前語言下顯示→<b>菲利普斯勋爵</b></li>\n<li>Queen, The：<b>大陆：英女王；台灣：英女王；香港：英女皇；新加坡：英女王；</b> 当前語言下顯示→<b>英女王</b></li>\n<li>Queen, The：<b>大陆：女王；台灣：女王；香港：女皇；新加坡：女王；</b> 当前語言下顯示→<b>女王</b></li>\n<li>Queen Mother, The：<b>大陆：英王太后；台灣：英王太后；香港：英皇太后；新加坡：英王太后；</b> 当前語言下顯示→<b>英王太后</b></li>\n<li>Queen Mother, The：<b>大陆：王太后；台灣：王太后；香港：皇太后；新加坡：王太后；</b> 当前語言下顯示→<b>王太后</b></li>\n<li>Richard：<b>大陆：理查德·；台灣：理查·；香港：理查·；新加坡：理查德·；</b> 当前語言下顯示→<b>理查德·</b></li>\n<li>Richard：<b>大陆：·理查德；台灣：·理查；香港：·理查；新加坡：·理查德；</b> 当前語言下顯示→<b>·理查德</b></li>\n<li>Royal Family：<b>大陆：王室；台灣：王室；香港：皇室；新加坡：王室；</b> 当前語言下顯示→<b>王室</b></li>\n<li>Shaun Woodward：<b>大陆：肖恩‧伍德沃德；香港：伍劭恩；</b> 当前語言下顯示→<b>肖恩‧伍德沃德</b></li>\n<li>Thatcher：<b>大陆：撒切尔；台灣：柴契爾；香港：戴卓爾；新加坡：撒切尔；</b> 当前語言下顯示→<b>撒切尔</b></li>\n<li>Thatcher, Margaret：<b>大陆：撒切尔夫人；台灣：瑪格麗特·柴契爾；香港：戴卓爾夫人；新加坡：玛格丽特·撒切尔；</b> 当前語言下顯示→<b>撒切尔夫人</b></li>\n<li>Wilson：<b>原文：韋爾遜；大陆：威尔逊；台灣：威爾遜；香港：韋爾遜；新加坡：威尔逊；</b> 当前語言下顯示→<b>韋爾遜</b></li>\n</ul>\n<p>以下為本條目單獨的全文轉換，請從本頁面進行編輯：</p>\n<ol>\n<li><b><span class=\"lanLabel\">简体：托尼·布莱尔；繁體：東尼·布萊爾；香港：貝理雅；</span></b> 当前用字模式下显示为→<b>托尼·布莱尔</b></li>\n<li><b><span class=\"lanLabel\">简体：英吉利海峡；繁體：英吉利海峽；香港：英倫海峽；</span></b> 当前用字模式下显示为→<b>英吉利海峡</b></li>\n<li><b><span class=\"lanLabel\">简体：英联邦；繁體：大英國協；香港：英聯邦；</span></b> 当前用字模式下显示为→<b>英联邦</b></li>\n<li><b><span class=\"lanLabel\">简体：撒切尔；繁體：柴契爾；香港：戴卓爾；</span></b> 当前用字模式下显示为→<b>撒切尔</b></li>\n<li><b><span class=\"lanLabel\">简体：乐队；繁體：樂團；香港：樂隊；</span></b> 当前用字模式下显示为→<b>乐队</b></li>\n<li><b><span class=\"lanLabel\">简体：披头士；繁體：披頭四；香港：披頭四；</span></b> 当前用字模式下显示为→<b>披头士</b></li>\n<li><b><span class=\"lanLabel\">简体：斯汀；繁體：史汀；</span></b> 当前用字模式下显示为→<b>斯汀</b></li>\n<li><b><span class=\"lanLabel\">原文：南喬治亞島與南桑威奇群島；简体：南乔治亚与南桑威奇群岛；台灣：南喬治亞與南三明治群島；香港：南喬治亞和桑威奇群島；</span></b> 当前用字模式下显示为→<b>南喬治亞島與南桑威奇群島</b></li>\n<li><b><span class=\"lanLabel\">简体：戈登·布朗；繁體：戈登·布朗；香港：白高敦；</span></b> 当前用字模式下显示为→<b>戈登·布朗</b></li>\n<li><b><span class=\"lanLabel\">台灣：西敏；大陆：威斯特敏斯特；</span></b> 当前用字模式下显示为→<b>威斯特敏斯特</b></li>\n</ol>\n</div>\n<div class=\"toccolours mw-collapsible mw-made-collapsible mw-collapsed\" style=\"background-color: transparent; border: none; margin:0; padding:0;\"><span class=\"mw-collapsible-toggle mw-collapsible-toggle-collapsed\">&nbsp;[<a href=\"#\">展开</a>]&nbsp;</span>\n<div style=\"background-color: #FFEA88; font-weight: normal; height: 1.5em; text-align: left; background-color: #bf0a30; color: #ffffff;\"><a href=\"http://zh.wikipedia.org/wiki/Help:%E4%B8%AD%E6%96%87%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91%E7%9A%84%E7%B9%81%E7%AE%80%E3%80%81%E5%9C%B0%E5%8C%BA%E8%AF%8D%E5%A4%84%E7%90%86\" title=\"Help:中文维基百科的繁简、地区词处理\"><span style=\"color: #cc9900;\">字詞轉換</span></a>说明</div>\n<div style=\"display: none;\" class=\"mw-collapsible-content\">\n<p>字詞轉換是中文维基的一項自動轉換，目的是通過计算机程序自動消除繁简、地区词等不同<b>用字模式</b>的差異，以達到閱讀方便。字詞轉換包括全局轉換和手動轉換，本說明所使用的标题转换和全文转换技術，都屬於手動轉換。</p>\n<p>如果您想对我们的字词转换系统提出一些改进建议，或者提交应用面更广的转换（<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%87%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91\" title=\"中文维基百科\">中文维基百科</a>全站乃至<a href=\"http://zh.wikipedia.org/wiki/MediaWiki\" title=\"MediaWiki\">MediaWiki</a>软件），或者报告转换系统的错误，请前往<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%AD%97%E8%AF%8D%E8%BD%AC%E6%8D%A2%E8%AF%B7%E6%B1%82%E6%88%96%E5%80%99%E9%80%89\" title=\"Wikipedia:字词转换请求或候选\">Wikipedia:字词转换请求或候选</a>发表您的意见。</p>\n</div>\n</div>\n</div>\n</div>\n<span id=\"_skip_noteTA\"></span></div>\n\n<table class=\"infobox\" style=\"font-size: 90%; width: 23em;\">\n<tbody><tr>\n<th colspan=\"2\" align=\"center\" bgcolor=\"#E3E3E3\">大不列顛及北愛爾蘭聯合王國<br>\n<small>United Kingdom of Great Britain and Northern Ireland</small><small>（英語）</small></th>\n</tr>\n<tr class=\"hiddenStructure英國\">\n<th colspan=\"2\" align=\"center\" bgcolor=\"#E3E3E3\">通稱：英國</th>\n</tr>\n<tr>\n<td colspan=\"2\">\n<table style=\"text-align: center; margin: 0pt auto; background: none repeat scroll 0% 0% transparent;\">\n<tbody><tr>\n<td style=\"border: 0pt none; vertical-align: middle;\"><span style=\"border: 1px solid #bbbbbb; display: table-cell;\"><a href=\"http://zh.wikipedia.org/wiki/File:Flag_of_the_United_Kingdom.svg\" class=\"image\"><img alt=\"Flag of the United Kingdom.svg\" src=\"England%28Chinese%29_files/125px-Flag_of_the_United_Kingdom.png\" height=\"63\" width=\"125\"></a></span></td>\n<td style=\"border: 0pt none; vertical-align: middle;\"><a href=\"http://zh.wikipedia.org/wiki/File:Royal_Coat_of_Arms_of_the_United_Kingdom.svg\" class=\"image\"><img alt=\"Royal Coat of Arms of the United Kingdom.svg\" src=\"England%28Chinese%29_files/125px-Royal_Coat_of_Arms_of_the_United_Kingdom.png\" height=\"121\" width=\"125\"></a></td>\n</tr>\n<tr style=\"font-size: 95%;\">\n<td style=\"border: 0pt none;\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%9B%BD%E6%97%97\" title=\"英国国旗\">英国國旗</a></td>\n<td style=\"border: 0pt none;\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%9B%BD%E5%BE%BD\" title=\"英国国徽\" class=\"mw-redirect\">英国國徽</a></td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr id=\"cite_ref-0\">\n<td colspan=\"2\" align=\"center\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9B%BD%E5%AE%B6%E6%A0%BC%E8%A8%80%E5%88%97%E8%A1%A8\" title=\"国家格言列表\">国家格言</a>：<i><span xml:lang=\"fr\" lang=\"fr\">Dieu et mon droit</span></i><sup id=\"cite_ref-0\" class=\"reference\"><a href=\"#cite_note-0\">[1]</a></sup><small>(<a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E8%AF%AD\" title=\"法语\">法语</a>)<br>\n（“<a href=\"http://zh.wikipedia.org/wiki/%E6%88%91%E6%AC%8A%E5%A4%A9%E6%8E%88\" title=\"我權天授\">我权天授</a>”或译“天有上帝，我有权利。”）</small></td>\n</tr>\n<tr>\n<td colspan=\"2\" align=\"center\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E6%AD%8C\" title=\"國歌\" class=\"mw-redirect\">國歌</a>：《<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A9%E4%BD%91%E5%A5%B3%E7%8E%8B\" title=\"天佑女王\" class=\"mw-redirect\">天佑女王（吾王）</a>》<br>\n（God Save the King/Queen）\n<center>\n<div id=\"ogg_player_1\">\n<div><button onclick=\"if (typeof(wgOggPlayer) != 'undefined') wgOggPlayer.init(false, {&quot;id&quot;:&quot;ogg_player_1&quot;,&quot;videoUrl&quot;:&quot;//upload.wikimedia.org/wikipedia/commons/d/de/United_States_Navy_Band_-_God_Save_the_Queen.ogg&quot;,&quot;width&quot;:220,&quot;height&quot;:35,&quot;length&quot;:63,&quot;linkUrl&quot;:&quot;/wiki/File:United_States_Navy_Band_-_God_Save_the_Queen.ogg&quot;,&quot;isVideo&quot;:false});\" style=\"width: 220px; text-align: center\" title=\"播放声音\"><img src=\"England%28Chinese%29_files/play.png\" alt=\"播放声音\" height=\"22\" width=\"22\"></button></div>\n<div><a href=\"http://zh.wikipedia.org/wiki/File:United_States_Navy_Band_-_God_Save_the_Queen.ogg\" class=\"image\" title=\"关于这个文件\"><img src=\"England%28Chinese%29_files/info.png\" alt=\"United States Navy Band - God Save the Queen.ogg\" height=\"22\" width=\"22\"></a></div>\n</div>\n</center>\n</td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\" align=\"center\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%9A%87%E5%AE%A4%E9%A0%8C%E6%AD%8C&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"皇室頌歌\">皇室頌歌</a>：{{{皇室頌歌}}}</td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\" align=\"center\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E6%97%97%E6%AD%8C\" title=\"國旗歌\" class=\"mw-redirect\">國旗歌</a>：</td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\" align=\"center\"></td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr>\n<td colspan=\"2\" align=\"center\">\n<p><a href=\"http://zh.wikipedia.org/wiki/File:Location_UK_EU_Europe.png\" class=\"image\"><img alt=\"Location UK EU Europe.png\" src=\"England%28Chinese%29_files/250px-Location_UK_EU_Europe.png\" height=\"210\" width=\"250\"></a></p>\n</td>\n</tr>\n<tr>\n<th colspan=\"2\" bgcolor=\"#E3E3E3\">自然地理<small>（實際管轄區）</small></th>\n</tr>\n<tr>\n<td colspan=\"2\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%AE%B6%E9%9D%A2%E7%A9%8D%E5%88%97%E8%A1%A8\" title=\"國家面積列表\" class=\"mw-redirect\">面積</a></b>\n<ul>\n<li>國土面積：244,820平方公里（<a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%AE%B6%E9%9D%A2%E7%A9%8D%E5%88%97%E8%A1%A8\" title=\"國家面積列表\" class=\"mw-redirect\">世界第78名</a>）</li>\n<li>水域率：1.34%</li>\n</ul>\n</td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%96%E9%83%BD\" title=\"首都\">首都</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\">最大城市</th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E6%99%82%E5%8D%80\" title=\"時區\" class=\"mw-redirect\">時區</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/UTC\" title=\"UTC\" class=\"mw-redirect\">UTC</a><a href=\"http://zh.wikipedia.org/wiki/UTC%2B0\" title=\"UTC+0\" class=\"mw-redirect\">+0</a><br>\n（夏時制：<a href=\"http://zh.wikipedia.org/wiki/UTC\" title=\"UTC\" class=\"mw-redirect\">UTC</a><a href=\"http://zh.wikipedia.org/wiki/UTC%2B1\" title=\"UTC+1\">+1</a>）</td>\n</tr>\n<tr>\n<th colspan=\"2\" bgcolor=\"#E3E3E3\">人民生活</th>\n</tr>\n<tr>\n<td colspan=\"2\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%AE%B6%E4%BA%BA%E5%8F%A3%E5%88%97%E8%A1%A8\" title=\"國家人口列表\" class=\"mw-redirect\">人口</a></b>\n<ul>\n<li>總人口：62,435,709人（<a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%AE%B6%E4%BA%BA%E5%8F%A3%E5%88%97%E8%A1%A8\" title=\"國家人口列表\" class=\"mw-redirect\">世界第22名</a>）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%9B%BD%E5%AE%B6%E4%BA%BA%E5%8F%A3%E5%AF%86%E5%BA%A6%E5%88%97%E8%A1%A8\" title=\"国家人口密度列表\">人口密度</a>：246/km<sup>2</sup>（<a href=\"http://zh.wikipedia.org/wiki/%E5%9B%BD%E5%AE%B6%E4%BA%BA%E5%8F%A3%E5%AF%86%E5%BA%A6%E5%88%97%E8%A1%A8\" title=\"国家人口密度列表\">世界第48名</a>）</li>\n</ul>\n</td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%98%E6%96%B9%E8%AA%9E%E8%A8%80\" title=\"官方語言\" class=\"mw-redirect\">官方語言</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AA%9E\" title=\"英語\" class=\"mw-redirect\">英語</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%98%E6%96%B9%E6%96%87%E5%AD%97\" title=\"官方文字\">官方文字</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%96%87\" title=\"英文\" class=\"mw-redirect\">英文</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E6%9B%86%E6%B3%95\" title=\"曆法\" class=\"mw-redirect\">曆法</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%85%AC%E6%9B%86\" title=\"公曆\" class=\"mw-redirect\">公曆</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E9%81%93%E8%B7%AF%E9%80%9A%E8%A1%8C%E6%96%B9%E5%90%91\" title=\"道路通行方向\">道路通行方向</a></th>\n<td>靠左行駛</td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure230V\">\n<td colspan=\"2\"><b><a href=\"http://zh.wikipedia.org/wiki/%E9%9B%BB\" title=\"電\">家用電源</a></b>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%9B%BB%E5%A3%93\" title=\"電壓\">電壓</a>：230V</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%B6%E7%94%A8%E9%9B%BB%E6%BA%90%E5%88%97%E8%A1%A8#.E4.B8.BB.E8.A6.81.E5.AE.B6.E7.94.A8.E9.9B.BB.E6.BA.90.2F.E6.8F.92.E5.BA.A7.2F.E6.8F.92.E9.A0.AD.E5.BD.A2.E5.BC.8F\" title=\"家用電源列表\">插座</a>：G</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%A0%BB%E7%8E%87\" title=\"頻率\">頻率</a>：50 Hz</li>\n</ul>\n</td>\n</tr>\n<tr>\n<th colspan=\"2\" bgcolor=\"#E3E3E3\">政治文化</th>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%AE%B6%E6%86%B2%E6%B3%95\" title=\"國家憲法\" class=\"mw-redirect\">國家憲法</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%AE%AA%E6%B3%95\" title=\"英国宪法\">英國憲法</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\">國家結構形式</th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%95%E4%B8%80%E5%88%B6\" title=\"单一制\">單一制</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E6%94%BF%E6%B2%BB%E9%AB%94%E5%88%B6\" title=\"政治體制\" class=\"mw-redirect\">政治體制</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%90%9B%E4%B8%BB%E7%AB%8B%E5%AE%AA%E5%88%B6\" title=\"君主立宪制\">君主立宪制</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%AE%AE%E4%BC%9A%E6%B0%91%E4%B8%BB%E5%88%B6\" title=\"议会民主制\" class=\"mw-redirect\">議會民主制</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%BE%8B%E9%AB%94%E7%B3%BB\" title=\"法律體系\">法律體系</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E7%BE%8E%E6%B3%95%E7%B3%BB\" title=\"英美法系\" class=\"mw-redirect\">英美法系</a></td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure女王\">\n<td colspan=\"2\"><b>國家領袖</b>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%AE%B6%E5%85%83%E9%A6%96\" title=\"國家元首\">國家元首</a>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%A5%B3%E7%8E%8B\" title=\"英国女王\" class=\"mw-redirect\">女王</a>）：<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E8%8E%89%E8%8E%8E%E7%99%BD%E4%BA%8C%E4%B8%96\" title=\"伊莉莎白二世\" class=\"mw-redirect\">伊莉莎白二世</a></li>\n</ul>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%94%BF%E5%BA%9C%E9%A6%96%E8%84%91\" title=\"政府首脑\">政府首腦</a>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8\" title=\"英国首相\">首相</a>）：<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E5%8D%A1%E6%A2%85%E4%BC%A6\" title=\"大卫·卡梅伦\" class=\"mw-redirect\">大卫·卡梅伦</a></li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure女王\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\"><b>國家主要領袖（<a href=\"http://zh.wikipedia.org/wiki/%E4%BA%94%E6%AC%8A%E5%88%86%E7%AB%8B\" title=\"五權分立\">五權分立</a>）</b>\n<ul>\n<li>行政（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8\" title=\"英国首相\">首相</a>）：<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E5%8D%A1%E6%A2%85%E4%BC%A6\" title=\"大卫·卡梅伦\" class=\"mw-redirect\">大卫·卡梅伦</a></li>\n<li>立法（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%9B%BD%E4%BC%9A\" title=\"英国国会\">國會</a>）：[[]]</li>\n<li>司法（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%9C%80%E9%AB%98%E6%B3%95%E9%99%A2\" title=\"英国最高法院\" class=\"mw-redirect\">最高法院</a>）：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8C%83%E7%90%86%E7%94%B3%E5%8B%B3%E7%88%B5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"范理申勳爵\">范理申勳爵</a></li>\n<li>考試（[[英国|]]）：[[]]</li>\n<li>監察（[[英国|]]）：[[]]</li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure[[三權分立]]\">\n<td colspan=\"2\"><b>國家主要領袖（<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%89%E6%AC%8A%E5%88%86%E7%AB%8B\" title=\"三權分立\" class=\"mw-redirect\">三權分立</a>）</b>\n<ul>\n<li>行政（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8\" title=\"英国首相\">首相</a>）：<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E5%8D%A1%E6%A2%85%E4%BC%A6\" title=\"大卫·卡梅伦\" class=\"mw-redirect\">大卫·卡梅伦</a></li>\n<li>立法（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%9B%BD%E4%BC%9A\" title=\"英国国会\">國會</a>）：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E9%81%94%E8%98%87%E6%B2%99%E5%A5%B3%E7%94%B7%E7%88%B5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"達蘇沙女男爵\">達蘇沙女男爵</a>、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%B4%84%E7%BF%B0%C2%B7%E8%B2%9D%E7%88%BE%E8%80%83&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"約翰·貝爾考\">約翰·貝爾考</a></li>\n<li>司法（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%9C%80%E9%AB%98%E6%B3%95%E9%99%A2\" title=\"英国最高法院\" class=\"mw-redirect\">最高法院</a>）：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8C%83%E7%90%86%E7%94%B3%E5%8B%B3%E7%88%B5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"范理申勳爵\">范理申勳爵</a></li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure[[三權分立]]\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\"><b>國家主要領袖（）</b></td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\"></td>\n</tr>\n<tr>\n<th colspan=\"2\" bgcolor=\"#E3E3E3\">經濟實力</th>\n</tr>\n<tr class=\"hiddenStructure2.139兆[[美元]]\">\n<td colspan=\"2\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%85%A7%E7%94%9F%E7%94%A2%E7%B8%BD%E5%80%BC\" title=\"國內生產總值\" class=\"mw-redirect\">國內生產總值</a>（<a href=\"http://zh.wikipedia.org/wiki/%E8%B3%BC%E8%B2%B7%E5%8A%9B%E5%B9%B3%E5%83%B9\" title=\"購買力平價\" class=\"mw-redirect\">購買力平價</a>）</b>\n<p>以下資訊是以<a href=\"http://zh.wikipedia.org/wiki/2009%E5%B9%B4\" title=\"2009年\">2009年</a>估計</p>\n<ul>\n<li>總計：2.139兆<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%85%83\" title=\"美元\">美元</a></li>\n<li>人均：34,619<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%85%83\" title=\"美元\">美元</a></li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure2.139兆[[美元]]\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure2.183兆[[美元]]\">\n<td colspan=\"2\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E5%85%A7%E7%94%9F%E7%94%A2%E7%B8%BD%E5%80%BC\" title=\"國內生產總值\" class=\"mw-redirect\">國內生產總值</a>（國際匯率）</b>\n<p>以下資訊是以<a href=\"http://zh.wikipedia.org/wiki/2009%E5%B9%B4\" title=\"2009年\">2009年</a>估計</p>\n<ul>\n<li>總計：2.183兆<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%85%83\" title=\"美元\">美元</a></li>\n<li>人均：35,334<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%85%83\" title=\"美元\">美元</a></li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure2.183兆[[美元]]\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure0.849\">\n<td colspan=\"2\"><b><a href=\"http://zh.wikipedia.org/wiki/%E4%BA%BA%E9%A1%9E%E7%99%BC%E5%B1%95%E6%8C%87%E6%95%B8\" title=\"人類發展指數\" class=\"mw-redirect\">人類發展指數</a></b>\n<p>以下資訊是以<a href=\"http://zh.wikipedia.org/wiki/2010%E5%B9%B4\" title=\"2010年\">2010年</a>估計</p>\n<ul>\n<li>0.849（第26名）－<span style=\"color:#009900\">极高</span></li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure0.849\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%A4%AE%E9%8A%80%E8%A1%8C\" title=\"中央銀行\" class=\"mw-redirect\">中央銀行</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E9%93%B6%E8%A1%8C\" title=\"英格兰银行\">英格兰银行</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\">貨幣單位</th>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E9%95%91\" title=\"英镑\">英镑</a>（GBP，<a href=\"http://zh.wikipedia.org/wiki/%C2%A3\" title=\"£\">£</a>）</td>\n</tr>\n<tr>\n<th colspan=\"2\" bgcolor=\"#E3E3E3\">其他資料</th>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\"><b>立國歷史</b>\n<ul>\n<li>立國日期：</li>\n<li>立國事件：（）</li>\n</ul>\n</td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\">國家象徵</th>\n<td>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E5%A5%B3%E7%8E%8B\" title=\"英國女王\" class=\"mw-redirect\">女王</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%96%94%E8%96%87\" title=\"薔薇\" class=\"mw-redirect\">薔薇</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%87%91%E8%89%B2\" title=\"金色\">金色</a><a href=\"http://zh.wikipedia.org/wiki/%E7%8D%85%E5%AD%90\" title=\"獅子\" class=\"mw-redirect\">獅子</a></li>\n</ul>\n</td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/ISO_3166-1\" title=\"ISO 3166-1\">國家代碼</a></th>\n<td>GBR</td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E9%9A%9B%E5%9F%9F%E5%90%8D%E7%B8%AE%E5%AF%AB\" title=\"國際域名縮寫\" class=\"mw-redirect\">國際域名縮寫</a></th>\n<td><a href=\"http://zh.wikipedia.org/wiki/.uk\" title=\".uk\">.uk</a></td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%8B%E9%9A%9B%E9%9B%BB%E8%A9%B1%E5%8D%80%E8%99%9F%E5%88%97%E8%A1%A8\" title=\"國際電話區號列表\" class=\"mw-redirect\">國際電話區號</a></th>\n<td>44</td>\n</tr>\n<tr>\n<th style=\"width: 92px;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%90%84%E5%9C%8B%E6%AD%A6%E8%A3%9D%E9%83%A8%E9%9A%8A%E5%88%97%E8%A1%A8\" title=\"各國武裝部隊列表\" class=\"mw-redirect\">現役軍人數</a></th>\n<td>195,000（<a href=\"http://zh.wikipedia.org/wiki/%E5%90%84%E5%9C%8B%E6%AD%A6%E8%A3%9D%E9%83%A8%E9%9A%8A%E5%88%97%E8%A1%A8\" title=\"各國武裝部隊列表\" class=\"mw-redirect\">第28名</a>）</td>\n</tr>\n<tr>\n<td colspan=\"2\">\n<hr></td>\n</tr>\n<tr class=\"hiddenStructure\">\n<td colspan=\"2\"></td>\n</tr>\n</tbody></table>\n<p><b>大不列颠及北爱尔兰联合王国</b><small>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AF%AD\" title=\"英语\">英语</a>：<span xml:lang=\"en\" lang=\"en\">The United Kingdom of Great Britain and Northern Ireland</span>；<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB%E8%AF%AD\" title=\"威尔士语\">威尔士语</a>：Teyrnas Unedig Prydain Fawra Gogledd Iwerddon；<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E7%9B%96%E5%B0%94%E8%AF%AD\" title=\"苏格兰盖尔语\">苏格兰盖尔语</a>：<span xml:lang=\"gd\" lang=\"gd\">An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath</span>；<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E8%AF%AD\" title=\"爱尔兰语\" class=\"mw-redirect\">爱尔兰语</a>：Ríocht Aontaithe na Breataine Móire agus Thuaisceart Éireann；<a href=\"http://zh.wikipedia.org/wiki/%E4%BD%8E%E5%9C%B0%E8%98%87%E6%A0%BC%E8%98%AD%E8%AA%9E\" title=\"低地蘇格蘭語\">低地苏格兰语</a>：<span xml:lang=\"sco\" lang=\"sco\">Unitit Kingdom o Great Britain an Norlin Airlann</span>）</small>，简称<b>联合王国</b><small>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%96%87\" title=\"英文\" class=\"mw-redirect\">英文</a>：<span xml:lang=\"en\" lang=\"en\">United Kingdom</span>）</small>或<b>不列颠</b><small>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%96%87\" title=\"英文\" class=\"mw-redirect\">英文</a>：<span xml:lang=\"en\" lang=\"en\">Britain</span>）</small><sup id=\"cite_ref-1\" class=\"reference\"><a href=\"#cite_note-1\">[2]</a></sup>，通稱<b>英国</b>，是由<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0%E5%B2%9B\" title=\"大不列颠岛\" class=\"mw-redirect\">大不列颠岛</a>上的<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"英格兰\">英格兰</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0\" title=\"苏格兰\" class=\"mw-redirect\">苏格兰</a>和<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB\" title=\"威尔士\" class=\"mw-redirect\">威尔士</a>，以及<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%B2%9B\" title=\"爱尔兰岛\">爱尔兰岛</a>东北部的<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"北爱尔兰\">北爱尔兰</a>以及一系列附属岛屿共同组成的一個<a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%AC%A7\" title=\"西欧\">西欧</a><a href=\"http://zh.wikipedia.org/wiki/%E5%B2%9B%E5%9B%BD\" title=\"岛国\" class=\"mw-redirect\">岛国</a>。中文裡的“英国”一词，即由“英格兰”而来，其國際代碼為GB。</p>\n<p>英国本土位于欧洲大陆西北面的<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A2%A0%E7%BE%A4%E5%B2%9B\" title=\"不列颠群岛\" class=\"mw-redirect\">不列颠群岛</a>，被<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%B5%B7_%28%E5%A4%A7%E8%A5%BF%E6%B4%8B%29\" title=\"北海 (大西洋)\">北海</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%90%89%E5%88%A9%E6%B5%B7%E5%B3%A1\" title=\"英吉利海峡\">英吉利海峡</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%87%B1%E7%88%BE%E7%89%B9%E6%B5%B7\" title=\"凱爾特海\">凯尔特海</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E7%88%BE%E8%98%AD%E6%B5%B7\" title=\"愛爾蘭海\">爱尔兰海</a>和<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%A5%BF%E6%B4%8B\" title=\"大西洋\">大西洋</a>包围。除了英國本土之外，还包括十四个海外领地<sup id=\"cite_ref-FCO_global_network_2-0\" class=\"reference\"><a href=\"#cite_note-FCO_global_network-2\">[3]</a></sup>。</p>\n<p>联合王国由四个国家联合而成，分别是<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"英格兰\">英格兰</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0\" title=\"苏格兰\" class=\"mw-redirect\">苏格兰</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"北爱尔兰\">北爱尔兰</a>和<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB\" title=\"威尔士\" class=\"mw-redirect\">威尔士</a><sup id=\"cite_ref-The_Countries_of_the_UK_3-0\" class=\"reference\"><a href=\"#cite_note-The_Countries_of_the_UK-3\">[4]</a></sup>。英国采用<a href=\"http://zh.wikipedia.org/wiki/%E8%AE%AE%E4%BC%9A%E5%88%B6\" title=\"议会制\" class=\"mw-redirect\">议会制</a>政体，王国政府所在地为<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a>，但是同时拥有其他三个国家级行政机构分别位于<a href=\"http://zh.wikipedia.org/wiki/%E8%B4%9D%E5%B0%94%E6%B3%95%E6%96%AF%E7%89%B9\" title=\"贝尔法斯特\">贝尔法斯特</a>（北爱尔兰），<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A1%E5%9C%B0%E5%A4%AB\" title=\"卡地夫\" class=\"mw-redirect\">卡地夫</a>（威尔士）和<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E4%B8%81%E5%A0%A1\" title=\"爱丁堡\">爱丁堡</a>（苏格兰）。英国是世界上第一个<a href=\"http://zh.wikipedia.org/wiki/%E5%90%9B%E4%B8%BB%E7%AB%8B%E5%AE%AA%E5%88%B6\" title=\"君主立宪制\">君主立宪制</a>国家，现任<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%90%9B%E4%B8%BB\" title=\"英国君主\">君主</a>是<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E4%B8%BD%E8%8E%8E%E7%99%BD%E4%BA%8C%E4%B8%96\" title=\"伊丽莎白二世\">伊丽莎白二世</a>女王。</p>\n<p>英王国在最强盛时期连同其海外<a href=\"http://zh.wikipedia.org/wiki/%E6%AE%96%E6%B0%91%E5%9C%B0\" title=\"殖民地\">殖民地</a>被称为<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a>，该帝国在<a href=\"http://zh.wikipedia.org/wiki/1922%E5%B9%B4\" title=\"1922年\">1922年</a>的时候达到巅峰，拥有全世界四分之一的<a href=\"http://zh.wikipedia.org/wiki/%E9%99%86%E5%9C%B0\" title=\"陆地\">陆地</a>，是有史以来世界上面积最大的国家。大英帝国解体后，英国继续在语言，文化，政治上对其前<a href=\"http://zh.wikipedia.org/wiki/%E6%AE%96%E6%B0%91%E5%9C%B0\" title=\"殖民地\">殖民地</a>保留了巨大的影响力，英国女王伊丽莎白二世现在仍然是<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"英联邦\">英联邦</a>组织的首脑，和其他15个英联邦国家的国家元首。</p>\n<p>英国是一个<a href=\"http://zh.wikipedia.org/wiki/%E5%8F%91%E8%BE%BE%E5%9B%BD%E5%AE%B6\" title=\"发达国家\" class=\"mw-redirect\">发达国家</a>、世界上第一个<a href=\"http://zh.wikipedia.org/wiki/%E5%B7%A5%E4%B8%9A%E5%8C%96%E5%9B%BD%E5%AE%B6\" title=\"工业化国家\" class=\"mw-redirect\">工业化国家</a><sup id=\"cite_ref-Industrial_Revolution_4-0\" class=\"reference\"><a href=\"#cite_note-Industrial_Revolution-4\">[5]</a></sup>，在19世纪和20世纪早期是世界上最强大的国家<sup id=\"cite_ref-Ferguson.2C_Niall_5-0\" class=\"reference\"><a href=\"#cite_note-Ferguson.2C_Niall-5\">[6]</a></sup>，但是经过两次世界大战和20世纪下半葉大英帝国的崩溃，英国已经失去了曾经在国际事务上的领导力。不过，英国仍然是一个在世界范围内拥有巨大影响力、舉足輕重的政治、经济、文化和军事强国。</p>\n<p>英国是<a href=\"http://zh.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%96%E7%95%8C%E5%A4%A7%E6%88%98\" title=\"第一次世界大战\">第一</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%AC%AC%E4%BA%8C%E6%AC%A1%E4%B8%96%E7%95%8C%E5%A4%A7%E6%88%98\" title=\"第二次世界大战\">第二次世界大战</a>主要战胜国，拥有<a href=\"http://zh.wikipedia.org/wiki/%E6%A0%B8%E6%AD%A6%E5%99%A8\" title=\"核武器\">核武器</a>和世界上第三的军费开支，是<a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD\" title=\"联合国\">联合国</a><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E7%90%86%E4%BC%9A%E5%B8%B8%E4%BB%BB%E7%90%86%E4%BA%8B%E5%9B%BD\" title=\"安理会常任理事国\" class=\"mw-redirect\">安理会常任理事国</a>，對議案擁有<a href=\"http://zh.wikipedia.org/wiki/%E5%90%A6%E6%B1%BA%E6%AC%8A\" title=\"否決權\" class=\"mw-redirect\">否決權</a>。英国亦為<a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E7%9B%9F\" title=\"欧盟\" class=\"mw-redirect\">欧盟</a>成员国、<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E7%BA%A6\" title=\"北约\" class=\"mw-redirect\">北约</a>創始會員國、<a href=\"http://zh.wikipedia.org/wiki/%E5%85%AB%E5%A4%A7%E5%B7%A5%E6%A5%AD%E5%9C%8B%E7%B5%84%E7%B9%94\" title=\"八大工業國組織\">八大工業國組織</a>成员国之一和<a href=\"http://zh.wikipedia.org/wiki/%E6%AD%90%E6%B4%B2%E5%9B%9B%E5%A4%A7%E7%B6%93%E6%BF%9F%E9%AB%94\" title=\"歐洲四大經濟體\">歐洲四大經濟體</a>之一、全球前七大经济体、也是一系列国际组织如<a href=\"http://zh.wikipedia.org/wiki/%E7%B6%93%E6%BF%9F%E5%90%88%E4%BD%9C%E8%88%87%E7%99%BC%E5%B1%95%E7%B5%84%E7%B9%94\" title=\"經濟合作與發展組織\" class=\"mw-redirect\">經合組織</a>、<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%96%E7%95%8C%E8%B2%BF%E6%98%93%E7%B5%84%E7%B9%94\" title=\"世界貿易組織\" class=\"mw-redirect\">世界貿易組織</a>的一员。</p>\n<table id=\"toc\" class=\"toc\">\n<tbody><tr>\n<td>\n<div id=\"toctitle\">\n<h2>目录</h2>\n<span class=\"toctoggle\">&nbsp;[<a href=\"#\" class=\"internal\" id=\"togglelink\">隐藏</a>]&nbsp;</span></div>\n<ul>\n<li class=\"toclevel-1 tocsection-1\"><a href=\"#.E5.8E.86.E5.8F.B2\"><span class=\"tocnumber\">1</span> <span class=\"toctext\">历史</span></a></li>\n<li class=\"toclevel-1 tocsection-2\"><a href=\"#.E5.9C.B0.E7.90.86\"><span class=\"tocnumber\">2</span> <span class=\"toctext\">地理</span></a>\n<ul>\n<li class=\"toclevel-2 tocsection-3\"><a href=\"#.E6.B0.94.E5.80.99\"><span class=\"tocnumber\">2.1</span> <span class=\"toctext\">气候</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-1 tocsection-4\"><a href=\"#.E6.94.BF.E6.B2.BB\"><span class=\"tocnumber\">3</span> <span class=\"toctext\">政治</span></a>\n<ul>\n<li class=\"toclevel-2 tocsection-5\"><a href=\"#.E6.B3.95.E5.BE.8B\"><span class=\"tocnumber\">3.1</span> <span class=\"toctext\">法律</span></a></li>\n<li class=\"toclevel-2 tocsection-6\"><a href=\"#.E8.A1.8C.E6.94.BF.E5.8C.BA.E5.88.92\"><span class=\"tocnumber\">3.2</span> <span class=\"toctext\">行政区划</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-1 tocsection-7\"><a href=\"#.E5.A4.96.E4.BA.A4\"><span class=\"tocnumber\">4</span> <span class=\"toctext\">外交</span></a></li>\n<li class=\"toclevel-1 tocsection-8\"><a href=\"#.E5.86.9B.E4.BA.8B\"><span class=\"tocnumber\">5</span> <span class=\"toctext\">军事</span></a>\n<ul>\n<li class=\"toclevel-2 tocsection-9\"><a href=\"#.E6.B5.B7.E5.86.9B\"><span class=\"tocnumber\">5.1</span> <span class=\"toctext\">海军</span></a></li>\n<li class=\"toclevel-2 tocsection-10\"><a href=\"#.E9.99.86.E5.86.9B\"><span class=\"tocnumber\">5.2</span> <span class=\"toctext\">陆军</span></a></li>\n<li class=\"toclevel-2 tocsection-11\"><a href=\"#.E7.A9.BA.E5.86.9B\"><span class=\"tocnumber\">5.3</span> <span class=\"toctext\">空军</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-1 tocsection-12\"><a href=\"#.E7.BB.8F.E6.B5.8E\"><span class=\"tocnumber\">6</span> <span class=\"toctext\">经济</span></a>\n<ul>\n<li class=\"toclevel-2 tocsection-13\"><a href=\"#.E8.B4.A7.E5.B8.81\"><span class=\"tocnumber\">6.1</span> <span class=\"toctext\">货币</span></a></li>\n<li class=\"toclevel-2 tocsection-14\"><a href=\"#.E9.81.8B.E8.BC.B8\"><span class=\"tocnumber\">6.2</span> <span class=\"toctext\">運輸</span></a></li>\n<li class=\"toclevel-2 tocsection-15\"><a href=\"#.E9.80.9A.E8.AE.AF\"><span class=\"tocnumber\">6.3</span> <span class=\"toctext\">通讯</span></a></li>\n<li class=\"toclevel-2 tocsection-16\"><a href=\"#.E8.83.BD.E6.BA.90\"><span class=\"tocnumber\">6.4</span> <span class=\"toctext\">能源</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-1 tocsection-17\"><a href=\"#.E4.BA.BA.E5.8F.A3\"><span class=\"tocnumber\">7</span> <span class=\"toctext\">人口</span></a>\n<ul>\n<li class=\"toclevel-2 tocsection-18\"><a href=\"#.E8.AF.AD.E8.A8.80\"><span class=\"tocnumber\">7.1</span> <span class=\"toctext\">语言</span></a></li>\n<li class=\"toclevel-2 tocsection-19\"><a href=\"#.E9.83.BD.E5.B8.82\"><span class=\"tocnumber\">7.2</span> <span class=\"toctext\">都市</span></a></li>\n<li class=\"toclevel-2 tocsection-20\"><a href=\"#.E5.AE.97.E6.95.99\"><span class=\"tocnumber\">7.3</span> <span class=\"toctext\">宗教</span></a></li>\n<li class=\"toclevel-2 tocsection-21\"><a href=\"#.E6.95.99.E8.82.B2\"><span class=\"tocnumber\">7.4</span> <span class=\"toctext\">教育</span></a></li>\n<li class=\"toclevel-2 tocsection-22\"><a href=\"#.E9.86.AB.E7.99.82\"><span class=\"tocnumber\">7.5</span> <span class=\"toctext\">醫療</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-1 tocsection-23\"><a href=\"#.E6.96.87.E5.8C.96\"><span class=\"tocnumber\">8</span> <span class=\"toctext\">文化</span></a>\n<ul>\n<li class=\"toclevel-2 tocsection-24\"><a href=\"#.E6.96.87.E5.AD.A6\"><span class=\"tocnumber\">8.1</span> <span class=\"toctext\">文学</span></a>\n<ul>\n<li class=\"toclevel-3 tocsection-25\"><a href=\"#.E6.96.87.E5.AD.A6.E5.AE.B6\"><span class=\"tocnumber\">8.1.1</span> <span class=\"toctext\">文学家</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-2 tocsection-26\"><a href=\"#.E6.88.8F.E5.89.A7\"><span class=\"tocnumber\">8.2</span> <span class=\"toctext\">戏剧</span></a></li>\n<li class=\"toclevel-2 tocsection-27\"><a href=\"#.E4.BD.93.E8.82.B2\"><span class=\"tocnumber\">8.3</span> <span class=\"toctext\">体育</span></a></li>\n<li class=\"toclevel-2 tocsection-28\"><a href=\"#.E5.93.B2.E5.AD.A6.E6.80.9D.E6.83.B3\"><span class=\"tocnumber\">8.4</span> <span class=\"toctext\">哲学思想</span></a>\n<ul>\n<li class=\"toclevel-3 tocsection-29\"><a href=\"#.E6.80.9D.E6.83.B3.E5.AE.B6\"><span class=\"tocnumber\">8.4.1</span> <span class=\"toctext\">思想家</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-2 tocsection-30\"><a href=\"#.E5.AA.92.E9.AB.94\"><span class=\"tocnumber\">8.5</span> <span class=\"toctext\">媒體</span></a></li>\n<li class=\"toclevel-2 tocsection-31\"><a href=\"#.E9.9F.B3.E4.B9.90\"><span class=\"tocnumber\">8.6</span> <span class=\"toctext\">音乐</span></a>\n<ul>\n<li class=\"toclevel-3 tocsection-32\"><a href=\"#.E4.B8.BB.E8.A6.81.E7.9A.84.E6.A8.82.E6.89.8B.E8.88.87.E6.A8.82.E5.9C.98\"><span class=\"tocnumber\">8.6.1</span> <span class=\"toctext\">主要的樂手與樂團</span></a></li>\n</ul>\n</li>\n<li class=\"toclevel-2 tocsection-33\"><a href=\"#.E8.8A.82.E6.97.A5.E5.81.87.E6.9C.9F\"><span class=\"tocnumber\">8.7</span> <span class=\"toctext\">节日假期</span></a>\n<ul>\n<li class=\"toclevel-3 tocsection-34\"><a href=\"#.E6.B3.A8.E8.AD.AF\"><span class=\"tocnumber\">8.7.1</span> <span class=\"toctext\">注譯</span></a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li class=\"toclevel-1 tocsection-35\"><a href=\"#.E6.B3.A8.E9.87.8A.E4.B8.8E.E5.8F.82.E8.80.83.E8.B5.84.E6.96.99\"><span class=\"tocnumber\">9</span> <span class=\"toctext\">注释与参考资料</span></a></li>\n<li class=\"toclevel-1 tocsection-36\"><a href=\"#.E5.A4.96.E9.83.A8.E9.93.BE.E6.8E.A5\"><span class=\"tocnumber\">10</span> <span class=\"toctext\">外部链接</span></a></li>\n<li class=\"toclevel-1 tocsection-37\"><a href=\"#.E5.8F.82.E8.A7.81\"><span class=\"tocnumber\">11</span> <span class=\"toctext\">参见</span></a></li>\n</ul>\n</td>\n</tr>\n</tbody></table>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=1\" title=\"编辑段落：历史\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.8E.86.E5.8F.B2\">历史</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%81%AF%E5%90%88%E7%8E%8B%E5%9C%8B%E6%AD%B7%E5%8F%B2\" title=\"聯合王國歷史\">聯合王國歷史</a>、<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A1%9B%E7%BE%A4%E5%B3%B6%E6%AD%B7%E5%8F%B2\" title=\"不列顛群島歷史\">不列顛群島歷史</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"英联邦\">英联邦</a></div>\n</dd>\n</dl>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:202px;\"><a href=\"http://zh.wikipedia.org/wiki/File:British_Empire_1897.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/200px-British_Empire_1897.jpg\" class=\"thumbimage\" height=\"152\" width=\"200\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:British_Empire_1897.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/1897%E5%B9%B4\" title=\"1897年\">1897年</a>的<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a></div>\n</div>\n</div>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:202px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Commonwealth_of_Nations.png\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/200px-Commonwealth_of_Nations.png\" class=\"thumbimage\" height=\"84\" width=\"200\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Commonwealth_of_Nations.png\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"英联邦\">英联邦</a>的版图</div>\n</div>\n</div>\n<p>现在的英国是过去1000年中几次合併的结果。<a href=\"http://zh.wikipedia.org/wiki/10%E4%B8%96%E7%BA%AA\" title=\"10世纪\">10世纪</a>以后<a href=\"http://zh.wikipedia.org/wiki/%E8%98%87%E6%A0%BC%E8%98%AD\" title=\"蘇格蘭\">蘇格蘭</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD\" title=\"英格蘭\" class=\"mw-redirect\">英格蘭</a>各自是独立的国家。<a href=\"http://zh.wikipedia.org/wiki/1284%E5%B9%B4\" title=\"1284年\">1284年</a><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E7%88%BE%E6%96%AF\" title=\"威爾斯\" class=\"mw-redirect\">威爾斯</a>被<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"英格兰\">英格兰</a>控制，<a href=\"http://zh.wikipedia.org/wiki/1535%E5%B9%B4\" title=\"1535年\">1535年</a>成为<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E7%8E%8B%E5%9B%BD\" title=\"英格兰王国\">英格兰王国</a>的一部分。<a href=\"http://zh.wikipedia.org/wiki/1603%E5%B9%B4\" title=\"1603年\">1603年</a>，<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"英格兰\">英格兰</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0\" title=\"苏格兰\" class=\"mw-redirect\">苏格兰</a>两国共有一位君主，<a href=\"http://zh.wikipedia.org/wiki/1707%E5%B9%B4\" title=\"1707年\">1707年</a>正式合併为<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0\" title=\"大不列颠\" class=\"mw-redirect\">大不列颠王国</a>。<a href=\"http://zh.wikipedia.org/wiki/1800%E5%B9%B4\" title=\"1800年\">1800年</a>，<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0%E7%8E%8B%E5%9B%BD\" title=\"大不列颠王国\" class=\"mw-redirect\">大不列颠王国</a>和<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"爱尔兰\">爱尔兰</a>（<a href=\"http://zh.wikipedia.org/wiki/1169%E5%B9%B4\" title=\"1169年\">1169年</a>－<a href=\"http://zh.wikipedia.org/wiki/1691%E5%B9%B4\" title=\"1691年\">1691年</a>逐步被英格蘭控制）合併，组成<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A1%9B%E8%88%87%E6%84%9B%E7%88%BE%E8%98%AD%E8%81%AF%E5%90%88%E7%8E%8B%E5%9C%8B\" title=\"大不列顛與愛爾蘭聯合王國\" class=\"mw-redirect\">大不列顛與愛爾蘭聯合王國</a>。<a href=\"http://zh.wikipedia.org/wiki/1922%E5%B9%B4\" title=\"1922年\">1922年</a>，<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"爱尔兰共和国\">爱尔兰共和国</a>独立，<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"爱尔兰\">爱尔兰</a>北部仍留在<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A1%9B%E8%88%87%E6%84%9B%E7%88%BE%E8%98%AD%E8%81%AF%E5%90%88%E7%8E%8B%E5%9C%8B\" title=\"大不列顛與愛爾蘭聯合王國\" class=\"mw-redirect\">联合王国</a>内。</p>\n<p>英国是<a href=\"http://zh.wikipedia.org/wiki/19%E4%B8%96%E7%BA%AA\" title=\"19世纪\">19世纪</a>遥遥领先的世界<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%9B%BD\" title=\"大国\">大国</a>和海上霸主，有着当时“世界工厂”的称号，亦是世界上第一个<a href=\"http://zh.wikipedia.org/wiki/%E5%B7%A5%E4%B8%9A%E9%9D%A9%E5%91%BD\" title=\"工业革命\">工业革命</a>和<a href=\"http://zh.wikipedia.org/wiki/%E5%B7%A5%E4%B8%9A%E5%8C%96\" title=\"工业化\" class=\"mw-redirect\">工业化</a>的国家，西方<a href=\"http://zh.wikipedia.org/wiki/%E8%B5%84%E6%9C%AC%E4%B8%BB%E4%B9%89\" title=\"资本主义\">资本主义</a>的倡导者，并且是早期<a href=\"http://zh.wikipedia.org/wiki/%E8%AE%AE%E4%BC%9A%E6%B0%91%E4%B8%BB%E5%88%B6%E5%BA%A6\" title=\"议会民主制度\" class=\"mw-redirect\">议会民主制度</a>的诞生地，无论在<a href=\"http://zh.wikipedia.org/wiki/%E7%A7%91%E5%AD%A6\" title=\"科学\">科学</a>技术还是<a href=\"http://zh.wikipedia.org/wiki/%E6%96%87%E5%AD%A6\" title=\"文学\" class=\"mw-redirect\">文学</a><a href=\"http://zh.wikipedia.org/wiki/%E8%89%BA%E6%9C%AF\" title=\"艺术\">艺术</a>水平亦有显著的贡献。在其顶峰时期，<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a>曾经控制了世界四分之一的土地和三分之一的人口，因其控制的土地覆盖了<a href=\"http://zh.wikipedia.org/wiki/%E5%9C%B0%E7%90%83\" title=\"地球\">地球</a>大部分经度，太阳时刻都会照耀<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%AE%96%E6%B0%91%E5%9C%B0\" title=\"英国殖民地\" class=\"mw-redirect\">英属领土</a>，故号称“日不落帝国”，是人类历史上最大的<a href=\"http://zh.wikipedia.org/wiki/%E5%B8%9D%E5%9B%BD\" title=\"帝国\">帝国</a>。然而<a href=\"http://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8D%81%E4%B8%96%E7%BA%AA\" title=\"二十世纪\" class=\"mw-redirect\">二十世纪</a>头50年，经历了两次<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%96%E7%95%8C%E5%A4%A7%E6%88%98\" title=\"世界大战\" class=\"mw-redirect\">世界大战</a>的英国國力減退。而在后半个世纪中，这个庞大的殖民帝国的殖民地紛紛開始<a href=\"http://zh.wikipedia.org/wiki/%E7%8D%A8%E7%AB%8B\" title=\"獨立\" class=\"mw-redirect\">獨立</a>。在处理殖民地独立问题的时候，英国巧妙地利用“分而治之”的策略，最大限度地维持英国在原殖民地的影响力，但是也增添了不安定的因素<sup id=\"cite_ref-6\" class=\"reference\"><a href=\"#cite_note-6\">[7]</a></sup>。在<a href=\"http://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8D%81%E4%B8%96%E7%B4%80\" title=\"二十世紀\" class=\"mw-redirect\">二十世紀</a>最後一個脫離英國的前英殖民地，是主權在<a href=\"http://zh.wikipedia.org/wiki/1997%E5%B9%B4\" title=\"1997年\">1997年</a><a href=\"http://zh.wikipedia.org/wiki/7%E6%9C%881%E6%97%A5\" title=\"7月1日\">7月1日</a>移交給<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8F%AF%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"中華人民共和國\" class=\"mw-redirect\">中華人民共和國</a>的<a href=\"http://zh.wikipedia.org/wiki/%E9%A6%99%E6%B8%AF\" title=\"香港\">香港</a>。</p>\n<p>雖然英國在<a href=\"http://zh.wikipedia.org/wiki/%E7%AC%AC%E4%BA%8C%E6%AC%A1%E4%B8%96%E7%95%8C%E5%A4%A7%E6%88%98\" title=\"第二次世界大战\">第二次世界大战</a>後國力減弱和經濟不景，但保守党领导人「<a href=\"http://zh.wikipedia.org/wiki/%E9%90%B5%E5%A8%98%E5%AD%90\" title=\"鐵娘子\" class=\"mw-redirect\">鐵娘子</a>」<a href=\"http://zh.wikipedia.org/wiki/%E7%8E%9B%E6%A0%BC%E5%88%A9%E7%89%B9%C2%B7%E6%92%92%E5%88%87%E5%B0%94\" title=\"玛格利特·撒切尔\" class=\"mw-redirect\">撒切尔夫人</a>在<a href=\"http://zh.wikipedia.org/wiki/1979%E5%B9%B4\" title=\"1979年\">1979年</a>當\n選為首相後，便大力推行改革，倡議“撒切尔主义”（Thatcherism），成功削減部分福利開支和削弱工會的力量，同时，压缩政府公共开支，降低税\n收，提倡自由经济，在经济上实行大规模私有化政策，减少对经济活动的政府管制和干预。于是，英国经济最终走出了长期“滞胀”的局面。自1981年以后，其\n年实际增长率达3%以上，在主要西方发达国家中仅次于日本。但是撒切尔夫人在帮助英國經濟復甦和保持國際上的影響力同时，也逐步加大了贫富差距，导致部分\n英国人的反对。之后與玛格利特·撒切尔同黨繼任者<a href=\"http://zh.wikipedia.org/wiki/%E6%A2%85%E6%9D%B0\" title=\"梅杰\" class=\"mw-redirect\">梅傑</a>首相任內英國經濟一直不振。其後工党领袖<a href=\"http://zh.wikipedia.org/wiki/%E6%89%98%E5%B0%BC%C2%B7%E5%B8%83%E8%8E%B1%E5%B0%94\" title=\"托尼·布莱尔\">托尼·布莱尔</a>於<a href=\"http://zh.wikipedia.org/wiki/1997%E5%B9%B4\" title=\"1997年\">1997年</a>當選為首相後，英國經濟慢慢才得以恢复。</p>\n<p>現在，英國雖然國家富強、但在國際政治和外交舞台上扮演的角色已大不如前，幸好經濟表現勝過其他<a href=\"http://zh.wikipedia.org/wiki/%E5%8F%91%E8%BE%BE%E5%9B%BD%E5%AE%B6\" title=\"发达国家\" class=\"mw-redirect\">发达国家</a>，也是失業率最低的<a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%96%B9\" title=\"西方\" class=\"mw-redirect\">西方</a>國家之一。</p>\n<p>英国是<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"英联邦\">英联邦</a>（<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a>的继任组织）成员，并在<a href=\"http://zh.wikipedia.org/wiki/1973%E5%B9%B4\" title=\"1973年\">1973年</a>正式加入<a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E7%9B%9F\" title=\"欧盟\" class=\"mw-redirect\">欧盟</a>。<a href=\"http://zh.wikipedia.org/wiki/2010%E5%B9%B4\" title=\"2010年\">2010年</a><a href=\"http://zh.wikipedia.org/wiki/5%E6%9C%8811%E6%97%A5\" title=\"5月11日\">5月11日</a>，<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E5%8D%A1%E6%A2%85%E4%BC%A6\" title=\"大卫·卡梅伦\" class=\"mw-redirect\">大衛·卡梅倫</a>正式接替<a href=\"http://zh.wikipedia.org/wiki/%E6%88%88%E7%99%BB%C2%B7%E5%B8%83%E6%9C%97\" title=\"戈登·布朗\">戈登·布朗</a>，出任<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8\" title=\"英国首相\">英国首相</a>。</p>\n<dl>\n<dd><span class=\"noprint\" style=\"font-size:small\">参见：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%90%9B%E4%B8%BB\" title=\"英国君主\">英国君主</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%8E%8B%E5%AE%A4%E6%97%97%E5%B8%9C\" title=\"英国王室旗帜\" class=\"mw-redirect\">英國王室旗幟</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%88%98%E4%BA%89%E5%8F%B2\" title=\"英国战争史\">英国战争史</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E5%8E%86%E5%8F%B2\" title=\"英格兰历史\" class=\"mw-redirect\">英格兰历史</a>、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A8%81%E5%B0%94%E5%A3%AB%E5%8E%86%E5%8F%B2&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"威尔士历史\">威尔士历史</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E5%8E%86%E5%8F%B2\" title=\"苏格兰历史\">苏格兰历史</a>及<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%8E%86%E5%8F%B2\" title=\"爱尔兰历史\" class=\"mw-redirect\">爱尔兰历史</a></span></dd>\n</dl>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=2\" title=\"编辑段落：地理\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.9C.B0.E7.90.86\">地理</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%9C%B0%E7%90%86\" title=\"英国地理\" class=\"mw-redirect\">英国地理</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:172px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Uk_topo_en.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/170px-Uk_topo_en.jpg\" class=\"thumbimage\" height=\"263\" width=\"170\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Uk_topo_en.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n英国地形图</div>\n</div>\n</div>\n<p>英国总面积约243,610平方千米（94,060平方英里）。她占有<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A2%A0%E7%BE%A4%E5%B2%9B\" title=\"不列颠群岛\" class=\"mw-redirect\">不列颠群岛</a>大部分地方，当中包括整个<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A1%9B%E5%B3%B6\" title=\"不列顛島\" class=\"mw-redirect\">不列颠岛</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%B2%9B\" title=\"爱尔兰岛\">爱尔兰岛</a>东北（面积占整个爱尔兰岛1/6）和一些围绕不列颠群岛的小岛屿。<sup id=\"cite_ref-7\" class=\"reference\"><a href=\"#cite_note-7\">[8]</a></sup>该国坐落在<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E5%A4%A7%E8%A5%BF%E6%B4%8B\" title=\"北大西洋\" class=\"mw-redirect\">北大西洋</a>和<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%B5%B7\" title=\"北海\">北海</a>之间，东南海岸朝向法国，距离法国北部海岸 35千米（22英里），中间被<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%90%89%E5%88%A9%E6%B5%B7%E5%B3%A1\" title=\"英吉利海峡\">英吉利海峡</a>分隔。<sup id=\"cite_ref-factbook_8-0\" class=\"reference\"><a href=\"#cite_note-factbook-8\">[9]</a></sup>根据一个1993年的调查，英国10％的国土是森林，其中46％用作畜牧业用途，另有25％用作农业用途。<sup id=\"cite_ref-Atlapedia_9-0\" class=\"reference\"><a href=\"#cite_note-Atlapedia-9\">[10]</a></sup><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a><a href=\"http://zh.wikipedia.org/wiki/%E6%A0%BC%E6%9E%97%E5%B0%BC%E6%B2%BB%E7%9A%87%E5%AE%B6%E5%A4%A9%E6%96%87%E5%8F%B0\" title=\"格林尼治皇家天文台\">格林尼治皇家天文台</a>是<a href=\"http://zh.wikipedia.org/wiki/%E6%9C%AC%E5%88%9D%E5%AD%90%E5%8D%88%E7%B7%9A\" title=\"本初子午線\">本初子午线</a>的起点。</p>\n<p>英国国土最北端的横坐标是北纬61°，最南端的横坐标是北纬49°，而最西端的纵坐标是西经9°，最东端的纵坐标是东经2°。<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"北爱尔兰\">北爱尔兰</a>与<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"爱尔兰共和国\">爱尔兰共和国</a>的边界长达360千米（224英里）。<sup id=\"cite_ref-factbook_8-1\" class=\"reference\"><a href=\"#cite_note-factbook-8\">[9]</a></sup>不列颠海岸线长达17,820千米（11,073英里）。<sup id=\"cite_ref-10\" class=\"reference\"><a href=\"#cite_note-10\">[11]</a></sup>不列颠岛以<a href=\"http://zh.wikipedia.org/wiki/%E6%B5%B7%E5%B3%BD%E9%9A%A7%E9%81%93\" title=\"海峽隧道\" class=\"mw-redirect\">海峡隧道</a>连接<a href=\"http://zh.wikipedia.org/wiki/%E6%AD%90%E6%B4%B2%E5%A4%A7%E9%99%B8\" title=\"歐洲大陸\">欧洲大陆</a>，总长度达50千米（31英里）（水底部分长达38千米（24英里）），是当前世界上最长的水底隧道。<sup id=\"cite_ref-11\" class=\"reference\"><a href=\"#cite_note-11\">[12]</a></sup></p>\n<p><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD%E5%9C%B0%E7%90%86\" title=\"英格蘭地理\">英格兰</a>占了联合王国总面积的一半，达130,395平方千米（50,350平方英里）。<sup id=\"cite_ref-12\" class=\"reference\"><a href=\"#cite_note-12\">[13]</a></sup>大部分是低地，<sup id=\"cite_ref-Atlapedia_9-1\" class=\"reference\"><a href=\"#cite_note-Atlapedia-9\">[10]</a></sup>在过了Tees-Exe线后，西北有一些山脉；其中包括有<a href=\"http://zh.wikipedia.org/wiki/%E6%B9%96%E5%8C%BA\" title=\"湖区\">湖区</a>，Peak区、Exmoor区和<a href=\"http://zh.wikipedia.org/wiki/%E8%BE%BE%E7%89%B9%E7%A9%86%E5%B0%94\" title=\"达特穆尔\">达特穆尔</a>的<a href=\"http://zh.wikipedia.org/wiki/%E5%A5%94%E5%AE%81%E5%B1%B1%E8%84%89\" title=\"奔宁山脉\">奔宁山脉</a>和一些石灰岩山脉。英格兰最高的山峰是湖区<a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E7%A7%91%E8%B2%BB%E7%88%BE%E5%B3%B0\" title=\"斯科費爾峰\">斯科費爾峰</a>（高达978米（3,209英尺））。主要河流、入海口有<a href=\"http://zh.wikipedia.org/wiki/%E6%B3%B0%E6%99%A4%E5%A3%AB%E6%B2%B3\" title=\"泰晤士河\">泰晤士河</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E6%96%87%E6%B2%B3\" title=\"塞文河\">塞文河</a>和Humber河。<sup id=\"cite_ref-Atlapedia_9-2\" class=\"reference\"><a href=\"#cite_note-Atlapedia-9\">[10]</a></sup></p>\n<p><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%8F%E6%A0%BC%E5%85%B0%E5%9C%B0%E7%90%86&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"苏格兰地理\">苏格兰</a>占英国总面积的1/3，面积达78,772平方千米（30,410平方英里）。<sup id=\"cite_ref-13\" class=\"reference\"><a href=\"#cite_note-13\">[14]</a></sup>当中有近八百个<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%8F%E6%A0%BC%E5%85%B0%E5%B2%9B%E5%B1%BF%E5%88%97%E8%A1%A8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"苏格兰岛屿列表\">岛屿</a>，<sup id=\"cite_ref-14\" class=\"reference\"><a href=\"#cite_note-14\">[15]</a></sup>大部分分布在苏格兰岛的西部、北部；分别称为<a href=\"http://zh.wikipedia.org/wiki/%E8%B5%AB%E5%B8%83%E9%87%8C%E5%BA%95%E7%BE%A4%E5%B2%9B\" title=\"赫布里底群岛\">赫布里底群岛</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A5%E5%85%8B%E5%B0%BC%E7%BE%A4%E5%B2%9B\" title=\"奥克尼群岛\">奥克尼群岛</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%AE%BE%E5%BE%B7%E5%85%B0%E7%BE%A4%E5%B2%9B\" title=\"设德兰群岛\">设德兰群岛</a>。苏格兰的地形是Highland Boundary Fault造成的，这个断层，西至Isle of Arran ，东至Stonehaven 。<sup id=\"cite_ref-15\" class=\"reference\"><a href=\"#cite_note-15\">[16]</a></sup>断层造成两个不同的区域；西北部的<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E9%AB%98%E5%9C%B0\" title=\"苏格兰高地\" class=\"mw-redirect\">苏格兰高地</a>和东南部的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%8F%E6%A0%BC%E5%85%B0%E4%BD%8E%E5%9C%B0&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"苏格兰低地\">苏格兰低地</a>。苏格兰大部分山地都在高低区域，其中有不列颠岛最高的<a href=\"http://zh.wikipedia.org/wiki/%E6%9C%AC%E5%B0%BC%E7%BB%B4%E6%96%AF%E5%B1%B1\" title=\"本尼维斯山\">本尼维斯山</a>（高达1,343米（4,406英尺））<sup id=\"cite_ref-16\" class=\"reference\"><a href=\"#cite_note-16\">[17]</a></sup>在低地区域的福斯湾和 Firth of Clyde 之间的狭窄被称作Central Lowlands ，这个地带里坐落着拥有最多人口的<a href=\"http://zh.wikipedia.org/wiki/%E6%A0%BC%E6%8B%89%E6%96%AF%E5%93%A5\" title=\"格拉斯哥\">格拉斯哥</a>和首府、政治中心<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E4%B8%81%E5%A0%A1\" title=\"爱丁堡\">爱丁堡</a>。</p>\n<p><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A8%81%E5%B0%94%E5%A3%AB%E5%9C%B0%E7%90%86&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"威尔士地理\">威尔士</a>占全英面积不到1/10，约20,779平方千米（8,020平方英里）。<sup id=\"cite_ref-17\" class=\"reference\"><a href=\"#cite_note-17\">[18]</a></sup>威尔士在全英来说，是最多山地的，只有<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8D%97%E5%A8%81%E5%B0%94%E5%A3%AB&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"南威尔士\">南威尔士</a>山地较少。海滨城市<a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E7%9A%84%E5%A4%AB\" title=\"加的夫\">加的夫</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%97%BA%E8%A5%BF\" title=\"斯旺西\">斯旺西</a>和<a href=\"http://zh.wikipedia.org/wiki/%E7%BA%BD%E6%B3%A2%E7%89%B9\" title=\"纽波特\">纽波特</a>都坐落在南威尔士。在这三个城市的北部，有South Wales Valleys 。Snowdonia 和<a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E8%AB%BE%E7%99%BB%E5%B1%B1\" title=\"斯諾登山\">斯諾登山</a> （高达1,085米（3,560英尺），是威尔士最高的山）是威尔士最高的两座山。威尔士14座超过914米（3000尺）的山一起被称为Welsh 3000s。威尔士的海岸线长达1200公路（750里）。威尔士也有几个岛，当中最大的是西北部的Anglesey。</p>\n<p><a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E7%88%BE%E8%98%AD%E5%9C%B0%E7%90%86\" title=\"愛爾蘭地理\">北爱尔兰</a>面积只有14,160平方千米（5,470平方英里），大部分都是山地。北爱有不列颠群岛最大的湖，<a href=\"http://zh.wikipedia.org/wiki/%E5%85%A7%E6%B9%96_%28%E8%8B%B1%E5%9C%8B%29\" title=\"內湖 (英國)\">內湖</a>，面积达388平方千米（150平方英里）。<sup id=\"cite_ref-18\" class=\"reference\"><a href=\"#cite_note-18\">[19]</a></sup>北爱的高峰是Mourne Mountains的Slieve Donard（高达852米（2,795英尺））。<sup id=\"cite_ref-Atlapedia_9-3\" class=\"reference\"><a href=\"#cite_note-Atlapedia-9\">[10]</a></sup></p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=3\" title=\"编辑段落：气候\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.B0.94.E5.80.99\">气候</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%B0%94%E5%80%99&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国气候\">英国气候</a></div>\n</dd>\n</dl>\n<p>英国气候适中，全年多雨。四季气温甚少低于-11C°，高于35C°。<sup id=\"cite_ref-19\" class=\"reference\"><a href=\"#cite_note-19\">[20]</a></sup> 风多从西北吹来，带来大西洋的潮湿天气，<sup id=\"cite_ref-factbook_8-2\" class=\"reference\"><a href=\"#cite_note-factbook-8\">[9]</a></sup>只是东部总是免于受西北风吹袭，所以东部总是比西部干燥。近来，大西洋受到<a href=\"http://zh.wikipedia.org/wiki/%E5%A2%A8%E8%A5%BF%E5%93%A5%E7%81%A3%E6%9A%96%E6%B5%81\" title=\"墨西哥灣暖流\">墨西哥灣暖流</a> 影响，所以英国现时的冬季比起旧时温和。夏季最温暖的是<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E6%A0%BC%E5%85%B0%E4%B8%9C%E5%8C%97%E9%83%A8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英格兰东北部\">英格兰东北部</a>，因为她靠近欧洲大陆，而较寒冷的是英格兰北部。大雪在冬季、高地早春落下（有时低地也会落下大雪）。<sup id=\"cite_ref-20\" class=\"reference\"><a href=\"#cite_note-20\">[21]</a></sup></p>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=4\" title=\"编辑段落：政治\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.94.BF.E6.B2.BB\">政治</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%94%BF%E6%B2%BB\" title=\"英国政治\">英国政治</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%85%9A%E6%B4%BE\" title=\"英国党派\" class=\"mw-redirect\">英国党派</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E6%94%BF%E5%BA%9C\" title=\"英國政府\">英国政府</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E5%85%A7%E9%96%A3\" title=\"英國內閣\" class=\"mw-redirect\">英國內閣</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:172px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Elizabeth_II_greets_NASA_GSFC_employees,_May_8,_2007_edit.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/170px-Elizabeth_II_greets_NASA_GSFC_employees_May_8_2007_edi.jpg\" class=\"thumbimage\" height=\"235\" width=\"170\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Elizabeth_II_greets_NASA_GSFC_employees,_May_8,_2007_edit.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n今<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%90%9B%E4%B8%BB\" title=\"英国君主\">英国女王</a>及<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%9C%8B%E5%8D%94\" title=\"大英國協\" class=\"mw-redirect\">大英國協</a>領袖 <a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E4%B8%BD%E8%8E%8E%E7%99%BD%E4%BA%8C%E4%B8%96\" title=\"伊丽莎白二世\">伊丽莎白二世</a></div>\n</div>\n</div>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:172px;\"><a href=\"http://zh.wikipedia.org/wiki/File:David_Cameron_-_World_Economic_Forum_Annual_Meeting_Davos_2010.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/170px-David_Cameron_-_World_Economic_Forum_Annual_Meeting_Da.jpg\" class=\"thumbimage\" height=\"255\" width=\"170\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:David_Cameron_-_World_Economic_Forum_Annual_Meeting_Davos_2010.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n現任<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8\" title=\"英国首相\">首相</a><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E5%8D%A1%E6%A2%85%E4%BC%A6\" title=\"大卫·卡梅伦\" class=\"mw-redirect\">大衛·卡梅倫</a></div>\n</div>\n</div>\n<p>英国是采用<a href=\"http://zh.wikipedia.org/wiki/%E5%90%9B%E4%B8%BB%E7%AB%8B%E5%AE%AA%E5%88%B6\" title=\"君主立宪制\">君主立宪制</a>为管治国家的管治制度，女王<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E4%B8%BD%E8%8E%8E%E7%99%BD%E4%BA%8C%E4%B8%96\" title=\"伊丽莎白二世\">伊丽莎白二世</a>是英国和其他15个英联邦成员国的<a href=\"http://zh.wikipedia.org/wiki/%E5%9B%BD%E5%AE%B6%E5%85%83%E9%A6%96\" title=\"国家元首\" class=\"mw-redirect\">国家元首</a>，也对<a href=\"http://zh.wikipedia.org/wiki/%E6%B3%BD%E8%A5%BF%E5%B2%9B\" title=\"泽西岛\" class=\"mw-redirect\">泽西岛</a>，<a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E6%81%A9%E5%B2%9B\" title=\"马恩岛\" class=\"mw-redirect\">马恩岛</a>和<a href=\"http://zh.wikipedia.org/wiki/%E6%A0%B9%E8%A5%BF%E5%B2%9B\" title=\"根西岛\">根西岛</a>等君主领地拥有统治权，在名义上，这些君主领地不是联合王国的一部分，但也是由联合王国政府来管理其国防和外交事务，包括由联合王国议会为这些领地立法。</p>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Hdr_parliament.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Hdr_parliament.jpg\" class=\"thumbimage\" height=\"143\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Hdr_parliament.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n泰唔士河畔的<a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%95%8F%E5%AE%AE\" title=\"西敏宮\" class=\"mw-redirect\">西敏宮</a>，是聯合王國的議會</div>\n</div>\n</div>\n<p>英國的民主制度是漸進緩慢開放而形成，<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8A%E8%AD%B0%E9%99%A2\" title=\"上議院\">上議院</a>議員由世襲貴族與<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%BB%E6%95%99\" title=\"主教\">主教</a>擔任，並非選舉產生，<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8B%E8%AD%B0%E9%99%A2\" title=\"下議院\">下議院</a>議員由各地貴族、大地主、富豪操縱指派，平民並無選舉權，後來甚至出現已經荒涼的市鎮仍有權派出議員，新興城市如<a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%BE%B9%E6%96%AF%E7%89%B9\" title=\"曼徹斯特\" class=\"mw-redirect\">曼徹斯特</a>或<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E6%98%8E%E7%BD%95\" title=\"伯明罕\" class=\"mw-redirect\">伯明罕</a>卻無權派出議員的怪現象。1832年執政的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E6%B0%91%E9%BB%A8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"民黨\">民黨</a>（Whig）才取消頹廢市鎮的選舉權，讓成年男性家境小康者有選舉權。1867年執政的保守黨進一步降低選民的財產限制給工人選舉權，1884年執政的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%87%AA%E7%94%B1%E9%BB%A8_%2819%E4%B8%96%E7%B4%80%E5%88%9D%29&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"自由黨 (19世紀初)\">自由黨</a>才完全取銷選民的財產限制，給農民選舉權使成年男性都有選舉權。但英國婦女則是等到<a href=\"http://zh.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%96%E7%95%8C%E5%A4%A7%E6%88%B0\" title=\"第一次世界大戰\" class=\"mw-redirect\">第一次世界大戰</a>後才獲得選舉權。</p>\n<p>英国的议会政体被称为<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E6%96%AF%E7%89%B9%E6%95%8F%E6%96%AF%E7%89%B9%E4%BD%93%E7%B3%BB\" title=\"威斯特敏斯特体系\" class=\"mw-redirect\">威斯特敏斯特体系</a>，该法令系统由世界很多国家采用。英国议会的办公地点在<a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%95%8F%E5%AE%AE\" title=\"西敏宮\" class=\"mw-redirect\">威斯特敏斯特宫</a>，分为选举产生的下议会和指定产生的上议会，所有通过的法案草案需要由英国君主批准后成为法律，但是按照英国习惯宪法，君主不能否定议会通过的法律草案，在苏格兰和北爱尔兰设置议会之前，英国议会拥有最高的立法权。</p>\n<p>英国的政府首脑是首相，首相是议会的议员，必须取得下议会中多数议员的信任方可就任，所以首相往往是国会获得最多席位的政党的领袖，首相和内阁形式\n上由君主指派，但是根据习惯宪法君主不能否决当选首相和首相所指派的内阁成员。内阁成员来自议会两院，大部分来自下议院，首相和内阁拥有实际的最高的行政\n权力，所有的内阁成员均是君主的<a href=\"http://zh.wikipedia.org/wiki/%E6%9E%A2%E5%AF%86%E9%99%A2\" title=\"枢密院\">枢密院</a>的成员。现任首相是来自保守党的<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E5%8D%A1%E6%A2%85%E4%BC%A6\" title=\"大卫·卡梅伦\" class=\"mw-redirect\">大衛·卡梅倫</a><sup id=\"cite_ref-BBC_News_21-0\" class=\"reference\"><a href=\"#cite_note-BBC_News-21\">[22]</a></sup>。</p>\n<p>英国议会下院由英国现有的646个选区选举产生，其中529个选区在英格兰，18个在北爱尔兰，59个在苏格兰，40个在威尔士<sup id=\"cite_ref-election_22-0\" class=\"reference\"><a href=\"#cite_note-election-22\">[23]</a></sup>，下一屆大选英国选区数量将提高到650个。任何一个选区选举以简单多数方式产生一个议会议员，君主在首相的建议下可以提前举行大选，英国<a href=\"http://zh.wikipedia.org/wiki/1911%E5%B9%B4\" title=\"1911年\">1911年</a>议会法案规定大选每5年举行一次。</p>\n<p>英国最大的三个主要政党为工党、保守党和<a href=\"http://zh.wikipedia.org/wiki/%E8%87%AA%E7%94%B1%E6%B0%91%E4%B8%BB%E9%BB%A8_%28%E8%8B%B1%E5%9C%8B%29\" title=\"自由民主黨 (英國)\" class=\"mw-redirect\">自由民主党</a>。这三大政党据有现议会下院646个席位中的616席，其餘席位由<a href=\"http://zh.wikipedia.org/wiki/%E8%98%87%E6%A0%BC%E8%98%AD%E6%B0%91%E6%97%8F%E9%BB%A8\" title=\"蘇格蘭民族黨\" class=\"mw-redirect\">苏格兰国民党</a>、威尔士党、工会民主党、社会民主党和<a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E8%8A%AC%E5%85%9A\" title=\"新芬党\" class=\"mw-redirect\">新芬党</a>等瓜分。作为欧洲议会的成员，英国现有78位<a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E6%B4%B2%E8%AE%AE%E4%BC%9A\" title=\"欧洲议会\">欧洲议会</a>议员，自英国的12个欧洲议会选区內選舉出。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=5\" title=\"编辑段落：法律\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.B3.95.E5.BE.8B\">法律</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%AE%AA%E6%B3%95\" title=\"英国宪法\">英国宪法</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%B3%95%E5%BE%8B&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国法律\">英国法律</a></div>\n</dd>\n</dl>\n<p>联合王国是全世界三个<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E6%88%90%E6%96%87%E6%86%B2%E6%B3%95\" title=\"不成文憲法\">没有成文宪法</a>的国家之一<sup id=\"cite_ref-Sarah_Carter_23-0\" class=\"reference\"><a href=\"#cite_note-Sarah_Carter-23\">[24]</a></sup>，英国的宪法由习惯、判例法和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%9B%BD%E9%99%85%E6%9D%A1%E7%BA%A6&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"国际条约\">国际条约</a>等构成。所以<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E7%BE%8E%E6%99%AE%E9%80%9A%E6%B3%95%E7%B3%BB\" title=\"英美普通法系\">英国的宪法制度</a>和<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E9%99%86%E6%B3%95%E7%B3%BB\" title=\"大陆法系\" class=\"mw-redirect\">大陆法系</a>不同，理论上，英国议会可以通过法案来进行宪法改革。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=6\" title=\"编辑段落：行政区划\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E8.A1.8C.E6.94.BF.E5.8C.BA.E5.88.92\">行政区划</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%88%92\" title=\"英国行政区划\">英国行政区划</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Map_of_the_administrative_geography_of_the_United_Kingdom.png\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Map_of_the_administrative_geography_of_the_United_King.png\" class=\"thumbimage\" height=\"328\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Map_of_the_administrative_geography_of_the_United_Kingdom.png\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n英国行政区划</div>\n</div>\n</div>\n<p>联合王国每一个组成国家都有自己的、源自联合王国组成前的管理制度、行政区划。所以英国并无“全国通用的行政系统”。<sup id=\"cite_ref-UN_24-0\" class=\"reference\"><a href=\"#cite_note-UN-24\">[25]</a></sup>直到19世纪，行政系统才有一些细微的变化。但是，这个变化并无为苏格兰、威尔士和爱尔兰带来一个统一的管理系统，即使在未来，管理系统也不太可能统一。</p>\n<p><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E6%A0%BC%E5%85%B0%E5%9C%B0%E5%8C%BA%E6%94%BF%E5%BA%9C&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英格兰地区政府\">英格兰地区政府</a>的制度是多元的，随地方而变。英格兰法令由联合王国议会、<a href=\"http://zh.wikipedia.org/wiki/%E5%A5%B3%E7%8E%8B%E9%99%9B%E4%B8%8B%E6%94%BF%E5%BA%9C\" title=\"女王陛下政府\">联合王国政府</a>制定，因为英格兰并无议会。英格兰有9个<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8C%BA\" title=\"大区\">大区</a>。<sup id=\"cite_ref-25\" class=\"reference\"><a href=\"#cite_note-25\">[26]</a></sup>其中一个区域，<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%BC%A6%E6%95%A6\" title=\"大伦敦\" class=\"mw-redirect\">大伦敦</a>，自2000年起开始，选出市议会、市长（因为<a href=\"http://zh.wikipedia.org/w/index.php?title=1998%E5%B9%B4%E5%A4%A7%E4%BC%A6%E6%95%A6%E6%94%BF%E5%BA%9C%E5%85%AC%E6%8A%95&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"1998年大伦敦政府公投\">1998年大伦敦政府公投</a>）。<sup id=\"cite_ref-26\" class=\"reference\"><a href=\"#cite_note-26\">[27]</a></sup>其他区域也有权选出他们的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8C%BA%E5%9F%9F%E8%AE%AE%E4%BC%9A_%28%E8%8B%B1%E6%A0%BC%E5%85%B0%29&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"区域议会 (英格兰)\">区域议会</a>（Regional assembly），唯独<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%9C%E5%8C%97%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"东北英格兰\">东北英格兰</a>没有议会（因<a href=\"http://zh.wikipedia.org/w/index.php?title=2004%E5%B9%B4%E4%B8%9C%E5%8C%97%E8%8B%B1%E6%A0%BC%E5%85%B0%E6%9D%83%E5%8A%9B%E4%B8%8B%E6%94%BE%E5%85%AC%E6%8A%95&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"2004年东北英格兰权力下放公投\">2004年东北英格兰权力下放公投</a>）。<sup id=\"cite_ref-27\" class=\"reference\"><a href=\"#cite_note-27\">[28]</a></sup>在第二层行政区划之下，有<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD%E7%9A%84%E9%83%BD%E6%9C%83%E9%83%A1%E5%92%8C%E9%9D%9E%E9%83%BD%E6%9C%83%E9%83%A1\" title=\"英格蘭的都會郡和非都會郡\">郡议会</a>和区议会（District council）（或<a href=\"http://zh.wikipedia.org/wiki/%E5%96%AE%E4%B8%80%E7%AE%A1%E7%90%86%E5%8D%80\" title=\"單一管理區\">單一管理區</a>），而伦敦则划分为32个<a href=\"http://zh.wikipedia.org/wiki/%E5%80%AB%E6%95%A6%E8%87%AA%E6%B2%BB%E5%B8%82\" title=\"倫敦自治市\">倫敦自治市</a>。在单一席位的选区，使用<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%9A%E6%95%B8%E5%88%B6\" title=\"多數制\">多數制</a> ，而在多个席位的选区，使用<a href=\"http://zh.wikipedia.org/wiki/%E5%85%A8%E7%A5%A8%E5%88%B6\" title=\"全票制\">全票制</a> 。<sup id=\"cite_ref-28\" class=\"reference\"><a href=\"#cite_note-28\">[29]</a></sup></p>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=7\" title=\"编辑段落：外交\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.A4.96.E4.BA.A4\">外交</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E5%A4%96%E4%BA%A4&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国外交\">英国外交</a></div>\n</dd>\n</dl>\n<div class=\"floatright\"><a href=\"http://zh.wikipedia.org/wiki/File:BritishVisaFree.png\" class=\"image\" title=\"英國免簽證待遇分布\"><img alt=\"英國免簽證待遇分布\" src=\"England%28Chinese%29_files/300px-BritishVisaFree.png\" height=\"132\" width=\"300\"></a></div>\n<p>英国可以获得世界上大多数国家的免签待遇。而對一些英國前殖民地，會有絕對性的免簽證待遇。</p>\n<dl>\n<dd><span class=\"noprint\" style=\"font-size:small\">参见：<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8B%B1%E5%85%B3%E7%B3%BB\" title=\"中英关系\">中英关系</a></span></dd>\n</dl>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=8\" title=\"编辑段落：军事\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.86.9B.E4.BA.8B\">军事</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%86%9B%E9%98%9F\" title=\"英国军队\" class=\"mw-redirect\">英国军队</a></div>\n</dd>\n</dl>\n<p>英国<a href=\"http://zh.wikipedia.org/wiki/%E5%86%9B%E9%98%9F\" title=\"军队\" class=\"mw-redirect\">军队</a>的<a href=\"http://zh.wikipedia.org/wiki/%E6%9C%80%E9%AB%98%E7%B5%B1%E5%B8%A5\" title=\"最高統帥\" class=\"mw-redirect\">最高统帅</a>是<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%90%9B%E4%B8%BB\" title=\"英国君主\">英国君主</a>；统领<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E6%B5%B7%E8%BB%8D\" title=\"英國海軍\" class=\"mw-redirect\">海</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%99%86%E5%86%9B\" title=\"英国陆军\" class=\"mw-redirect\">陆</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%A9%BA%E5%86%9B\" title=\"英国空军\" class=\"mw-redirect\">空</a>三\n军。英國海、陸、空三軍總司令並由英國國防部（Ministry of Defence）內的國防委員會（Defence Council of the\n United Kingdom）管理。 \n英國海陸空三軍受英國國會委託，保護英國本土及其海外領土的職責、促進英國政府廣泛的治安利益、及出力支援國際維持和平。 \n英國軍隊經常活躍地參與北約和其他盟國的軍事行動</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=9\" title=\"编辑段落：海军\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.B5.B7.E5.86.9B\">海军</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%9A%87%E5%AE%B6%E6%B5%B7%E5%86%9B\" title=\"英国皇家海军\" class=\"mw-redirect\">英国皇家海军</a>和<a href=\"http://zh.wikipedia.org/wiki/%E7%9A%87%E5%AE%B6%E6%B5%B7%E8%BB%8D%E9%99%B8%E6%88%B0%E9%9A%8A\" title=\"皇家海軍陸戰隊\" class=\"mw-redirect\">皇家海军陸戰隊</a></div>\n</dd>\n</dl>\n<p>皇家海軍曾是世界上最大、最強的海軍；並幫助英國成為18和19世紀最強盛的軍事及經濟強國；也是把大英帝國的影響力投射至全世界的重要工具。雖然現已势微，皇家海軍仍是歐洲最大、世界上第二大的海軍；也是世界上最先進的海軍之一</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=10\" title=\"编辑段落：陆军\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E9.99.86.E5.86.9B\">陆军</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%99%86%E5%86%9B\" title=\"英国陆军\" class=\"mw-redirect\">英国陆军</a></div>\n</dd>\n</dl>\n<p>英國軍隊的陸上武裝部隊，是從蘇格蘭與英格蘭的武裝部隊、政經文架構，在1707年合併為大不列顛王國時形成。至2006年止，英國陸軍人數大約為\n十萬七千七百三十名正規軍官兵，及三萬八千四百六十名國土軍官兵。英國陸軍經常被部署於全球每一角落的戰地參與戰鬥部隊、多國聯軍、或聯合國維持和平部隊\n行動。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=11\" title=\"编辑段落：空军\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E7.A9.BA.E5.86.9B\">空军</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%9A%87%E5%AE%B6%E7%A9%BA%E5%86%9B\" title=\"英国皇家空军\" class=\"mw-redirect\">英国皇家空军</a></div>\n</dd>\n</dl>\n<p>英國皇家空軍（Royal Air \nForce，RAF）為英國軍隊的空中武裝部門。皇家空軍創始於1918年4月1日，自此之後於英國軍事史扮演重要角色，而於第二次世界大戰及伊拉克戰爭\n等衝突扮演要角。英國空軍有1000架以上飛行器，及45710位常備兵員（2007年統計）。</p>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=12\" title=\"编辑段落：经济\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E7.BB.8F.E6.B5.8E\">经济</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%BB%8F%E6%B5%8E\" title=\"英国经济\">英国经济</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E4%BC%81%E4%B8%9A%E5%88%97%E8%A1%A8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国企业列表\">英国企业列表</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:City_of_London_skyline_from_London_City_Hall_-_Oct_2008.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-City_of_London_skyline_from_London_City_Hall_-_Oct_200.jpg\" class=\"thumbimage\" height=\"115\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:City_of_London_skyline_from_London_City_Hall_-_Oct_2008.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n倫敦是全世界最大的<a href=\"http://zh.wikipedia.org/wiki/%E9%87%91%E8%9E%8D%E4%B8%AD%E5%BF%83\" title=\"金融中心\">金融中心</a>之一。</div>\n</div>\n</div>\n<p>英国作为一个重要的<a href=\"http://zh.wikipedia.org/wiki/%E8%B4%B8%E6%98%93\" title=\"贸易\">贸易</a>实体、經濟強國以及<a href=\"http://zh.wikipedia.org/wiki/%E9%87%91%E8%9E%8D\" title=\"金融\">金融</a>中心，是世界第六大<a href=\"http://zh.wikipedia.org/wiki/%E7%BB%8F%E6%B5%8E%E4%BD%93%E7%B3%BB\" title=\"经济体系\">经济体系</a>，也是全球最富裕、經濟最發達和生活水準最高的國家之一。在过去的三十年间，<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E6%94%BF%E5%BA%9C\" title=\"英國政府\">政府</a>大量减少了国有资产，并减缓了<a href=\"http://zh.wikipedia.org/wiki/%E7%A4%BE%E4%BC%9A%E7%A6%8F%E5%88%A9\" title=\"社会福利\">社会福利</a>计划的发展。十八世紀時英國本地產<a href=\"http://zh.wikipedia.org/wiki/%E5%B0%8F%E9%BA%A5\" title=\"小麥\" class=\"mw-redirect\">小麥</a>開始不敵北美廉價小麥，放棄大量種植小麥，大量從美洲進口糧產，逐漸轉以<a href=\"http://zh.wikipedia.org/w/index.php?title=%E4%B9%B3%E7%95%9C%E4%B8%9A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"乳畜业\">乳畜业</a>为主，较为集中，高度<a href=\"http://zh.wikipedia.org/wiki/%E5%86%9C%E4%B8%9A%E6%9C%BA%E6%A2%B0%E5%8C%96\" title=\"农业机械化\">机械化</a>，并且效益十分高：1%的劳动人口能够满足大约60%的食品需要。</p>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:London.bankofengland.arp.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-London.jpg\" class=\"thumbimage\" height=\"165\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:London.bankofengland.arp.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD%E9%8A%80%E8%A1%8C\" title=\"英格蘭銀行\" class=\"mw-redirect\">英格蘭銀行</a>-聯合王國中央銀行</div>\n</div>\n</div>\n<p>英国拥有大量的<a href=\"http://zh.wikipedia.org/wiki/%E7%85%A4\" title=\"煤\">煤</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A9%E7%84%B6%E6%B0%94\" title=\"天然气\">天然气</a>和<a href=\"http://zh.wikipedia.org/wiki/%E7%9F%B3%E6%B2%B9\" title=\"石油\">石油</a>储备；英国的主要能源生产大约占总<a href=\"http://zh.wikipedia.org/wiki/%E5%9B%BD%E6%B0%91%E7%94%9F%E4%BA%A7%E6%80%BB%E5%80%BC\" title=\"国民生产总值\">GDP</a>的10%，在工业国家是算非常高的。<a href=\"http://zh.wikipedia.org/wiki/%E6%9C%8D%E5%8A%A1%E4%B8%9A\" title=\"服务业\" class=\"mw-redirect\">服务业</a>，特别是<a href=\"http://zh.wikipedia.org/wiki/%E9%93%B6%E8%A1%8C%E4%B8%9A\" title=\"银行业\" class=\"mw-redirect\">银行业</a>、<a href=\"http://zh.wikipedia.org/wiki/%E9%87%91%E8%9E%8D%E4%B8%9A\" title=\"金融业\" class=\"mw-redirect\">金融業</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%88%AA%E9%81%8B%E6%A5%AD\" title=\"航運業\" class=\"mw-redirect\">航運業</a>、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E4%BF%9D%E9%99%A9%E4%B8%9A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"保险业\">保险业</a>以及<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%95%86%E4%B8%9A%E6%9C%8D%E5%8A%A1%E4%B8%9A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"商业服务业\">商业服务业</a>占GDP的比重最大，而且處於世界領導地位，首都<a href=\"http://zh.wikipedia.org/wiki/%E5%80%AB%E6%95%A6\" title=\"倫敦\" class=\"mw-redirect\">倫敦</a>更是世界數一數二的金融、航運和服務中心。尽管英国仍是欧洲最大的<a href=\"http://zh.wikipedia.org/wiki/%E8%BB%8D%E4%BA%8B%E5%B7%A5%E6%A5%AD\" title=\"軍事工業\" class=\"mw-redirect\">军火</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%9F%B3%E6%B2%B9%E5%88%B6%E5%93%81\" title=\"石油制品\" class=\"mw-redirect\">石油产品</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%94%B5%E8%84%91\" title=\"电脑\" class=\"mw-redirect\">电脑</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%94%B5%E8%A7%86\" title=\"电视\">电视</a>和<a href=\"http://zh.wikipedia.org/wiki/%E6%89%8B%E6%8F%90%E7%94%B5%E8%AF%9D\" title=\"手提电话\" class=\"mw-redirect\">手机</a>的制造地，<a href=\"http://zh.wikipedia.org/wiki/%E5%B7%A5%E4%B8%9A\" title=\"工业\" class=\"mw-redirect\">工业</a>的重要性不断下降。</p>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:202px;\"><a href=\"http://zh.wikipedia.org/wiki/File:HansomCab.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/200px-HansomCab.jpg\" class=\"thumbimage\" height=\"150\" width=\"200\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:HansomCab.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n倫敦街頭觀光馬車</div>\n</div>\n</div>\n<p>英國的<a href=\"http://zh.wikipedia.org/wiki/%E6%95%99%E8%82%B2\" title=\"教育\">教育</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%AD%A6%E6%9C%AF%E7%A0%94%E7%A9%B6\" title=\"学术研究\" class=\"mw-redirect\">學術研究</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%A7%91%E5%AD%B8%E7%A0%94%E7%A9%B6&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"科學研究\">科學研究</a>亦處於世界領導地位，举世闻名的<a href=\"http://zh.wikipedia.org/wiki/%E5%8A%8D%E6%A9%8B%E5%A4%A7%E5%AD%B8\" title=\"劍橋大學\" class=\"mw-redirect\">劍橋大學</a>和<a href=\"http://zh.wikipedia.org/wiki/%E7%89%9B%E6%B4%A5%E5%A4%A7%E5%AD%B8\" title=\"牛津大學\" class=\"mw-redirect\">牛津大學</a>都位於英國，是<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9C%8B\" title=\"美國\">美國</a>以外全球最重要的教育樞紐。英國每年吸引不少來自世界各地的留學生慕名前來升學，不僅為國家帶來豐厚的外匯，也為這個屬<a href=\"http://zh.wikipedia.org/wiki/%E7%9F%A5%E8%AD%98%E5%9E%8B%E7%B6%93%E6%BF%9F\" title=\"知識型經濟\" class=\"mw-redirect\">知識型經濟</a>體系的國家吸納不少人才。</p>\n<p>英国的<a href=\"http://zh.wikipedia.org/wiki/%E6%97%85%E6%B8%B8%E4%B8%9A\" title=\"旅游业\" class=\"mw-redirect\">旅游业</a>也相当重要：每年有超过2700万游客，<a href=\"http://zh.wikipedia.org/w/index.php?title=%E4%B8%96%E7%95%8C%E6%97%85%E6%B8%B8%E4%B8%9A%E6%A6%82%E5%86%B5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"世界旅游业概况\">排名世界第六</a>，低于<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%9B%BD\" title=\"中国\" class=\"mw-redirect\">中国</a>（3300万）而高于<a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\">澳大利亚</a>（1910万）。</p>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Qantas_a380_vh-oqa_takeoff_heathrow_arp.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Qantas_a380_vh-oqa_takeoff_heathrow_arp.jpg\" class=\"thumbimage\" height=\"150\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Qantas_a380_vh-oqa_takeoff_heathrow_arp.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%A9%BA%E4%B8%AD%E5%B7%B4%E5%A3%ABA380\" title=\"空中巴士A380\" class=\"mw-redirect\">空中巴士A380</a>的機翼與引擎於英國製造。</div>\n</div>\n</div>\n<dl>\n<dd><span class=\"noprint\" style=\"font-size:small\">参见：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E5%B7%A5%E4%B8%9A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国工业\">英国工业</a>、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E5%95%86%E4%B8%9A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国商业\">英国商业</a>及<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%97%85%E6%B8%B8%E4%B8%9A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国旅游业\">英国旅游业</a></span></dd>\n</dl>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=13\" title=\"编辑段落：货币\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E8.B4.A7.E5.B8.81\">货币</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E9%95%91\" title=\"英镑\">英镑</a>和<a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E5%85%83\" title=\"欧元\">欧元</a></div>\n</dd>\n</dl>\n<p>英国虽在<a href=\"http://zh.wikipedia.org/wiki/1973%E5%B9%B4\" title=\"1973年\">1973年</a>加入<a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E7%9B%9F\" title=\"欧盟\" class=\"mw-redirect\">欧盟</a>，但英国出于<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%94%BF%E6%B2%BB\" title=\"英国政治\">国内政治</a>及<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%BB%8F%E6%B5%8E\" title=\"英国经济\">内部經濟</a>的考虑而拒绝加入<a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E5%85%83\" title=\"欧元\">欧元</a>区。<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%AE%AA%E6%B3%95\" title=\"英国宪法\">宪法</a>的改革也同样是现在英国所面临的问题。目前，英国国内商业已经开始接受欧元及美元等外国货币，但是，主要的货币还是以英镑为主。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=14\" title=\"编辑段落：運輸\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E9.81.8B.E8.BC.B8\">運輸</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9C%8B%E9%81%8B%E8%BC%B8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英國運輸\">英國運輸</a></div>\n</dd>\n</dl>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Heathrow_T5.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Heathrow_T5.jpg\" class=\"thumbimage\" height=\"107\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Heathrow_T5.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n希斯路機場5號航站樓大廈。<a href=\"http://zh.wikipedia.org/wiki/%E5%80%AB%E6%95%A6%E5%B8%8C%E6%96%AF%E6%B4%9B%E6%A9%9F%E5%A0%B4\" title=\"倫敦希斯洛機場\" class=\"mw-redirect\">倫敦希斯洛機場</a>是世界上最繁忙的機場之一</div>\n</div>\n</div>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=15\" title=\"编辑段落：通讯\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E9.80.9A.E8.AE.AF\">通讯</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%80%9A%E8%AE%AF\" title=\"英国通讯\">英国通讯</a></div>\n</dd>\n</dl>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=16\" title=\"编辑段落：能源\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E8.83.BD.E6.BA.90\">能源</span></h3>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Oil_platform_in_the_North_SeaPros.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Oil_platform_in_the_North_SeaPros.jpg\" class=\"thumbimage\" height=\"146\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Oil_platform_in_the_North_SeaPros.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%B5%B7%E6%B2%B9%E7%94%B0\" title=\"北海油田\">北海油田</a></div>\n</div>\n</div>\n<p>在2006年，英國是世界上第九大的能源及15大生產消費國。</p>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=17\" title=\"编辑段落：人口\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E4.BA.BA.E5.8F.A3\">人口</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E4%BA%BA%E5%8F%A3\" title=\"英国人口\">英国人口</a></div>\n</dd>\n</dl>\n<p>根据最新数据统计，英国人口大约有6120万，其中三分之一居住在<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E4%B8%9C%E5%8D%97\" title=\"英格兰东南\" class=\"mw-redirect\">英格兰东南部</a>（<a href=\"http://zh.wikipedia.org/wiki/%E9%A6%96%E9%83%BD\" title=\"首都\">首都</a><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a>就有720万）。其中<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"英格兰\">英格兰</a>人占83.6%；<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0\" title=\"苏格兰\" class=\"mw-redirect\">苏格兰</a>人占8.6%；其他还有<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E6%96%AF\" title=\"威尔斯\" class=\"mw-redirect\">威尔斯</a>人占4.9%、<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"北爱尔兰\">北爱尔兰</a>人占2.9%、<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6\" title=\"印度\">印度</a>人占1.8%以及<a href=\"http://zh.wikipedia.org/wiki/%E9%9D%9E%E6%B4%B2\" title=\"非洲\">非洲</a>人占1.8%等等。英國醫療採用公醫制度，醫師幾乎全是公務員，看病動手術皆不需繳任何醫藥費，較偏遠地區醫師會親自到病患家裏看病。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=18\" title=\"编辑段落：语言\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E8.AF.AD.E8.A8.80\">语言</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AF%AD\" title=\"英语\">英语</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%BC%8F%E8%8B%B1%E8%AA%9E\" title=\"英式英語\" class=\"mw-redirect\">英式英語</a></div>\n</dd>\n</dl>\n<p>英國名義上沒有官方語，實際上是以<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AA%9E\" title=\"英語\" class=\"mw-redirect\">英語</a>為主要語言。<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD\" title=\"英格蘭\" class=\"mw-redirect\">英格蘭</a>以外的地區也有其他官方<a href=\"http://zh.wikipedia.org/wiki/%E8%AA%9E%E8%A8%80\" title=\"語言\">語言</a>，例如<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB%E8%AF%AD\" title=\"威尔士语\">威尔士语</a>（威尔士人口的26%）、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E7%9B%96%E5%B0%94%E8%AF%AD\" title=\"苏格兰盖尔语\">苏格兰盖尔语</a>（6万人使用）等。世界各地移民到英國的人也講自己的家鄉語言，如<a href=\"http://zh.wikipedia.org/wiki/%E5%AD%9F%E5%8A%A0%E6%8B%89%E8%AF%AD\" title=\"孟加拉语\">孟加拉语</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%B2%A4%E8%AF%AD\" title=\"粤语\">粤语</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%AE%A2%E5%AE%B6%E8%A9%B1\" title=\"客家話\" class=\"mw-redirect\">客家話</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%9C%B0%E8%AF%AD\" title=\"印地语\">印地语</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%97%81%E9%81%AE%E6%99%AE%E8%AF%AD\" title=\"旁遮普语\" class=\"mw-redirect\">旁遮普语</a>和<a href=\"http://zh.wikipedia.org/wiki/%E4%B9%8C%E5%B0%94%E9%83%BD%E8%AF%AD\" title=\"乌尔都语\">乌尔都语</a>。英国是<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6\" title=\"印度\">印度</a>以外说<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%9C%B0%E8%AF%AD\" title=\"印地语\">印地语</a>人数最多的地方。</p>\n<p>由于过去<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a>的扩张，<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AF%AD\" title=\"英语\">英语</a>几乎扩散到世界每一个角落，是<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%96%E7%95%8C\" title=\"世界\">世界</a>上学习最普遍的<a href=\"http://zh.wikipedia.org/wiki/%E8%AF%AD%E8%A8%80\" title=\"语言\" class=\"mw-redirect\">语言</a>，并且还产生了许多其他种系的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E8%AF%AD%E6%96%B9%E8%A8%80&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英语方言\">英语</a>，又因為二十世紀美國的強大，英語亦成為普遍认同的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E4%B8%96%E7%95%8C%E6%80%A7%E8%AF%AD%E8%A8%80&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"世界性语言\">世界性语言</a>。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=19\" title=\"编辑段落：都市\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E9.83.BD.E5.B8.82\">都市</span></h3>\n<table class=\"navbox\" width=\"97%\">\n<tbody><tr>\n<th colspan=\"10\" style=\"padding: 0.3em 0pt; line-height: 1.2em; font-size: 120%;\">\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><span style=\"font-size:smaller; float: left; margin-left:0.75em\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Template:Largest_Urban_Areas_of_the_United_Kingdom&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template:Largest Urban Areas of the United Kingdom\"><span style=\"color:#002bb8\">查看</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:Largest_Urban_Areas_of_the_United_Kingdom&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:Largest Urban Areas of the United Kingdom\"><span style=\"color:#002bb8\" title=\"关于这个模板的讨论页面\">討論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:Largest_Urban_Areas_of_the_United_Kingdom&amp;action=edit\"><span style=\"color:#002bb8\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編輯</span></a></span></div>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><span style=\"font-size:smaller; float: right; margin-right:0.75em\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Template:Largest_Urban_Areas_of_the_United_Kingdom&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template:Largest Urban Areas of the United Kingdom\"><span style=\"color:#002bb8\">查看</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:Largest_Urban_Areas_of_the_United_Kingdom&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:Largest Urban Areas of the United Kingdom\"><span style=\"color:#002bb8\" title=\"关于这个模板的讨论页面\">討論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:Largest_Urban_Areas_of_the_United_Kingdom&amp;action=edit\"><span style=\"color:#002bb8\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編輯</span></a></span></div>\n<strong class=\"selflink\">英國</strong>最大城市<br>\n<span style=\"font-weight:normal;\"><small><a href=\"http://zh.wikipedia.org/w/index.php?title=2001%E5%B9%B4%E8%8B%B1%E5%9C%8B%E4%BA%BA%E5%8F%A3%E6%99%AE%E6%9F%A5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"2001年英國人口普查\">2001人口普查</a><sup id=\"cite_ref-29\" class=\"reference\"><a href=\"#cite_note-29\">[30]</a></sup><sup id=\"cite_ref-30\" class=\"reference\"><a href=\"#cite_note-30\">[31]</a></sup><sup id=\"cite_ref-31\" class=\"reference\"><a href=\"#cite_note-31\">[32]</a></sup></small></span></th>\n</tr>\n<tr>\n<th></th>\n<th><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E7%B5%84%E5%90%88%E5%9F%8E%E5%B8%82\" title=\"英國組合城市\">排名</a></th>\n<th>城市名稱</th>\n<th><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E7%B5%84%E5%90%88%E5%9F%8E%E5%B8%82\" title=\"英國組合城市\">都會區</a></th>\n<th><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E7%B5%84%E5%90%88%E5%9F%8E%E5%B8%82\" title=\"英國組合城市\">人口</a></th>\n<th><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E7%B5%84%E5%90%88%E5%9F%8E%E5%B8%82\" title=\"英國組合城市\">排名</a></th>\n<th>城市名稱</th>\n<th><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E7%B5%84%E5%90%88%E5%9F%8E%E5%B8%82\" title=\"英國組合城市\">都會區</a></th>\n<th><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E7%B5%84%E5%90%88%E5%9F%8E%E5%B8%82\" title=\"英國組合城市\">人口</a></th>\n<th></th>\n</tr>\n<tr>\n<td rowspan=\"11\" style=\"text-align: center;\"><a href=\"http://zh.wikipedia.org/wiki/File:London_from_above.jpg\" class=\"image\" title=\"伦敦\"><img alt=\"伦敦\" src=\"England%28Chinese%29_files/135px-London_from_above.jpg\" class=\"thumbborder\" height=\"90\" width=\"135\"></a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a><br>\n<p><a href=\"http://zh.wikipedia.org/wiki/File:Birmingham_Skyline_from_Bartley_Green.jpg\" class=\"image\" title=\"伯明翰\"><img alt=\"伯明翰\" src=\"England%28Chinese%29_files/135px-Birmingham_Skyline_from_Bartley_Green.jpg\" class=\"thumbborder\" height=\"101\" width=\"135\"></a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E6%98%8E%E7%BF%B0\" title=\"伯明翰\">伯明翰</a></p>\n</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">1</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6\" title=\"伦敦\">伦敦</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%BC%A6%E6%95%A6%E9%83%BD%E5%B8%82%E5%8C%BA\" title=\"大伦敦都市区\">大倫敦都市區</a></td>\n<td>8,278,251</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">11</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E9%87%8C%E6%96%AF%E6%89%98%E5%B0%94\" title=\"布里斯托尔\">布里斯托尔</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Bristol_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Bristol Urban Area\">Bristol Urban Area</a></td>\n<td>551,066</td>\n<td rowspan=\"11\" style=\"text-align: center;\"><a href=\"http://zh.wikipedia.org/wiki/File:ManchesterCore.PNG\" class=\"image\" title=\"曼彻斯特\"><img alt=\"曼彻斯特\" src=\"England%28Chinese%29_files/135px-ManchesterCore.PNG\" class=\"thumbborder\" height=\"90\" width=\"135\"></a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%BD%BB%E6%96%AF%E7%89%B9\" title=\"曼彻斯特\">曼彻斯特</a><br>\n<p><a href=\"http://zh.wikipedia.org/wiki/File:Leedsnight.jpg\" class=\"image\" title=\"利兹\"><img alt=\"利兹\" src=\"England%28Chinese%29_files/135px-Leedsnight.jpg\" class=\"thumbborder\" height=\"84\" width=\"135\"></a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%88%A9%E5%85%B9\" title=\"利兹\">利兹</a></p>\n</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">2</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E6%98%8E%E7%BF%B0\" title=\"伯明翰\">伯明翰</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=West_Midlands_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"West Midlands Urban Area\">West Midlands Urban Area</a></td>\n<td>2,284,093</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">12</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E8%B5%96%E9%A1%BF\" title=\"布赖顿\">布赖顿</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Brighton/Worthing/Littlehampton&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Brighton/Worthing/Littlehampton\">Brighton/Worthing/Littlehampton</a></td>\n<td>461,181</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">3</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%BD%BB%E6%96%AF%E7%89%B9\" title=\"曼彻斯特\">曼彻斯特</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Greater_Manchester_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Greater Manchester Urban Area\">Greater Manchester Urban Area</a></td>\n<td>2,240,230</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">13</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E6%9C%B4%E6%AC%A1%E8%8C%85%E6%96%AF\" title=\"朴次茅斯\">樸次茅夫</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Portsmouth_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Portsmouth Urban Area\">Portsmouth Urban Area</a></td>\n<td>442,252</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">4</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%88%A9%E5%85%B9\" title=\"利兹\">利兹</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=West_Yorkshire_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"West Yorkshire Urban Area\">West Yorkshire Urban Area</a></td>\n<td>1,499,465</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">14</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E8%8E%B1%E6%96%AF%E7%89%B9\" title=\"莱斯特\">莱斯特</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Leicester_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Leicester Urban Area\">Leicester Urban Area</a></td>\n<td>441,213</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">5</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E6%A0%BC%E6%8B%89%E6%96%AF%E5%93%A5\" title=\"格拉斯哥\">格拉斯哥</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Greater_Glasgow&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Greater Glasgow\">Greater Glasgow</a></td>\n<td>1,199,629</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">15</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E4%B8%81%E5%A0%A1\" title=\"爱丁堡\">爱丁堡</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E4%B8%81%E5%A0%A1\" title=\"爱丁堡\">爱丁堡</a></td>\n<td>420,893</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">6</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%B0%E6%81%A9%E6%B2%B3%E7%95%94%E7%BA%BD%E5%8D%A1%E6%96%AF%E5%B0%94\" title=\"泰恩河畔纽卡斯尔\">纽卡斯尔</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Tyneside&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Tyneside\">Tyneside</a></td>\n<td>879,996</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">16</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E6%81%A9%E8%8C%85%E6%96%AF\" title=\"伯恩茅斯\">伯恩茅斯</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=South_East_Dorset_conurbation&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"South East Dorset conurbation\">South East Dorset conurbation</a></td>\n<td>383,713</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">7</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%88%A9%E7%89%A9%E6%B5%A6\" title=\"利物浦\">利物浦</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Liverpool_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Liverpool Urban Area\">Liverpool Urban Area</a></td>\n<td>816,216</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">17</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E9%9B%B7%E4%B8%81\" title=\"雷丁\">雷丁</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Reading/Wokingham_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Reading/Wokingham Urban Area\">Reading/Wokingham Urban Area</a></td>\n<td>369,804</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">8</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E8%AF%BA%E4%B8%81%E6%B1%89\" title=\"诺丁汉\">诺丁汉</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Nottingham_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Nottingham Urban Area\">Nottingham Urban Area</a></td>\n<td>666,358</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">18</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E7%B1%B3%E5%BE%B7%E7%88%BE%E6%96%AF%E4%BC%AF%E5%8B%92\" title=\"米德爾斯伯勒\">米德爾斯伯勒</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Teesside&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Teesside\">Teesside</a></td>\n<td>365,323</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">9</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E8%B0%A2%E8%8F%B2%E5%B0%94%E5%BE%B7\" title=\"谢菲尔德\">谢菲尔德</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Sheffield_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Sheffield Urban Area\">Sheffield Urban Area</a></td>\n<td>640,720</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">19</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E7%89%B9%E5%80%AB%E7%89%B9%E6%B2%B3%E7%95%94%E6%96%AF%E6%89%98%E5%85%8B\" title=\"特倫特河畔斯托克\">特倫特河畔斯托克</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=The_Potteries_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"The Potteries Urban Area\">The Potteries Urban Area</a></td>\n<td>362,403</td>\n</tr>\n<tr>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">10</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E8%B4%9D%E5%B0%94%E6%B3%95%E6%96%AF%E7%89%B9\" title=\"贝尔法斯特\">贝尔法斯特</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Belfast_Metropolitan_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Belfast Metropolitan Urban Area\">Belfast Metropolitan Urban Area</a></td>\n<td>579,554</td>\n<td style=\"background: none repeat scroll 0% 0% rgb(240, 240, 240);\" align=\"center\">20</td>\n<td align=\"left\"><b><a href=\"http://zh.wikipedia.org/wiki/%E8%80%83%E6%96%87%E5%9E%82\" title=\"考文垂\">考文垂</a></b></td>\n<td align=\"left\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Coventry/Bedworth_Urban_Area&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Coventry/Bedworth Urban Area\">Coventry/Bedworth Urban Area</a></td>\n<td>336,452</td>\n</tr>\n</tbody></table>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=20\" title=\"编辑段落：宗教\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.AE.97.E6.95.99\">宗教</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E5%9C%8B%E6%95%99\" title=\"英國國教\" class=\"mw-redirect\">英國國教</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E5%AE%97%E6%95%99&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国宗教\">英国宗教</a></div>\n</dd>\n</dl>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:172px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Westminster_Abbey_-_West_Door.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/170px-Westminster_Abbey_-_West_Door.jpg\" class=\"thumbimage\" height=\"227\" width=\"170\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Westminster_Abbey_-_West_Door.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n歷任<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E5%90%9B%E4%B8%BB\" title=\"英國君主\" class=\"mw-redirect\">英國君主</a>皆於<a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%95%8F%E5%AF%BA\" title=\"西敏寺\">西敏寺</a><a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E5%86%95\" title=\"加冕\">加冕</a>。</div>\n</div>\n</div>\n<p><a href=\"http://zh.wikipedia.org/wiki/16%E4%B8%96%E7%BA%AA\" title=\"16世纪\">16世纪</a>以后，英国是好几个重要的<a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E6%95%99\" title=\"新教\">新教</a>教派的发源地：<a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E5%85%AC%E4%BC%9A\" title=\"圣公会\" class=\"mw-redirect\">圣公会</a>(此為大公教教派)、<a href=\"http://zh.wikipedia.org/wiki/%E5%85%AC%E7%90%86%E4%BC%9A\" title=\"公理会\">公理会</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%B5%B8%E4%BF%A1%E4%BC%9A\" title=\"浸信会\">浸信会</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%85%AC%E8%AA%BC%E6%9C%83\" title=\"公誼會\" class=\"mw-redirect\">公谊会</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%BE%AA%E9%81%93%E5%85%AC%E4%BC%9A\" title=\"循道公会\" class=\"mw-redirect\">循道公会</a>－<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%AB%E7%90%86%E5%85%AC%E4%BC%9A\" title=\"卫理公会\" class=\"mw-redirect\">卫理公会</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%BC%9F%E5%85%84%E4%BC%9A\" title=\"弟兄会\" class=\"mw-redirect\">弟兄会</a>等。<a href=\"http://zh.wikipedia.org/wiki/18%E4%B8%96%E7%BA%AA\" title=\"18世纪\">18世纪</a>和<a href=\"http://zh.wikipedia.org/wiki/19%E4%B8%96%E7%BA%AA\" title=\"19世纪\">19世纪</a>，英国曾经是<a href=\"http://zh.wikipedia.org/wiki/%E5%9F%BA%E7%9D%A3%E6%95%99\" title=\"基督教\">基督教</a>多次<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%B1%9E%E7%81%B5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"属灵\">属灵</a><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%9F%BA%E7%9D%A3%E6%95%99%E5%A4%8D%E5%85%B4%E8%BF%90%E5%8A%A8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"基督教复兴运动\">复兴运动</a>的中心和海外<a href=\"http://zh.wikipedia.org/w/index.php?title=%E4%BC%A0%E6%95%99&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"传教\">传教</a>的重要基地，诞生过<a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%BF%B0%C2%B7%E5%8D%AB%E6%96%AF%E7%90%86\" title=\"约翰·卫斯理\" class=\"mw-redirect\">约翰·卫斯理</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%87%B7%E7%89%B9%E8%85%93\" title=\"懷特腓\" class=\"mw-redirect\">怀特腓</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%9C%E7%BB%B4%E5%BB%89\" title=\"卜维廉\" class=\"mw-redirect\">卜维廉</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%90%86%E5%A8%81%E5%BB%89\" title=\"克理威廉\" class=\"mw-redirect\">克理威廉</a>、<a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E7%A4%BC%E9%80%8A\" title=\"马礼逊\">马礼逊</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%BE%BE%E7%A7%98\" title=\"达秘\" class=\"mw-redirect\">达秘</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%88%B4%E5%BE%B7%E7%94%9F\" title=\"戴德生\">戴德生</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%9D%8E%E6%96%87%E6%96%AF%E6%95%A6\" title=\"李文斯敦\" class=\"mw-redirect\">李文斯敦</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%AE%BE%E8%B7%AF%E6%98%93%E5%B8%88%E6%AF%8D\" title=\"宾路易师母\">宾路易师母</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%8F%B2%E7%99%BE%E5%85%8B\" title=\"史百克\">史百克</a>等众多著名基督教徒。</p>\n<p>2001年人口调查数据显示：<a href=\"http://zh.wikipedia.org/wiki/%E5%9F%BA%E7%9D%A3%E5%AE%97%E6%95%99\" title=\"基督宗教\" class=\"mw-redirect\">基督宗教</a>佔總人口的71.6%。<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E6%96%AF%E5%85%B0%E6%95%99\" title=\"伊斯兰教\">伊斯兰教</a>佔2.7%。<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6%E6%95%99\" title=\"印度教\">印度教</a>佔1%。其他佔1.6%。 「不明/沒有宗教人士」佔23.1%。<sup id=\"cite_ref-32\" class=\"reference\"><a href=\"#cite_note-32\">[33]</a></sup>其他宗教还包括<a href=\"http://zh.wikipedia.org/wiki/%E4%BD%9B%E6%95%99\" title=\"佛教\">佛教</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%8C%B6%E5%A4%AA%E6%95%99\" title=\"猶太教\" class=\"mw-redirect\">猶太教</a>等<sup id=\"cite_ref-mt20120313_33-0\" class=\"reference\"><a href=\"#cite_note-mt20120313-33\">[34]</a></sup>。</p>\n<p>2007年调查显示：基督宗教佔總人口的64%。伊斯兰教佔4%。在不同歲數的群體在信仰方面有不同的趨勢。當受訪者年齡越大，承認有宗教信仰的比率便越高<sup id=\"cite_ref-34\" class=\"reference\"><a href=\"#cite_note-34\">[35]</a></sup>。</p>\n<p>2012年3月英国君主<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E4%B8%BD%E8%8E%8E%E7%99%BD%E4%BA%8C%E4%B8%96\" title=\"伊丽莎白二世\">伊丽莎白二世</a>在<a href=\"http://zh.wikipedia.org/wiki/%E5%85%B0%E6%9F%8F%E5%AE%AB\" title=\"兰柏宫\">兰柏宫</a>演說表示“<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E5%9C%8B%E6%95%99%E6%9C%83\" title=\"英國國教會\">聖公會</a>的理念偶爾被誤解”<sup id=\"cite_ref-mt20120313_33-1\" class=\"reference\"><a href=\"#cite_note-mt20120313-33\">[34]</a></sup>。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=21\" title=\"编辑段落：教育\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.95.99.E8.82.B2\">教育</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%95%99%E8%82%B2\" title=\"英国教育\">英国教育</a>和<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%A4%A7%E5%AD%A6\" title=\"英国大学\" class=\"mw-redirect\">英國大學</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:KingsCollegeChapelWest.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-KingsCollegeChapelWest.jpg\" class=\"thumbimage\" height=\"165\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:KingsCollegeChapelWest.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%89%91%E6%A1%A5%E5%A4%A7%E5%AD%A6%E5%9B%BD%E7%8E%8B%E5%AD%A6%E9%99%A2\" title=\"剑桥大学国王学院\">國王學院</a>，<a href=\"http://zh.wikipedia.org/wiki/%E5%8A%8D%E6%A9%8B%E5%A4%A7%E5%AD%B8\" title=\"劍橋大學\" class=\"mw-redirect\">劍橋大學</a>的一部分，於1209年成立</div>\n</div>\n</div>\n<p>英国最闻名于世的两所<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%AD%A6\" title=\"大学\" class=\"mw-redirect\">大学</a>是<a href=\"http://zh.wikipedia.org/wiki/%E7%89%9B%E6%B4%A5%E5%A4%A7%E5%AD%A6\" title=\"牛津大学\">牛津大学</a>（Oxford）和<a href=\"http://zh.wikipedia.org/wiki/%E5%89%91%E6%A1%A5%E5%A4%A7%E5%AD%A6\" title=\"剑桥大学\">剑桥大学</a>（Cambridge），此外，<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6%E5%A4%A7%E5%AD%A6%E5%AD%A6%E9%99%A2\" title=\"伦敦大学学院\">伦敦大学学院</a>（UCL）、<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6%E6%94%BF%E6%B2%BB%E7%BB%8F%E6%B5%8E%E5%AD%A6%E9%99%A2\" title=\"伦敦政治经济学院\" class=\"mw-redirect\">伦敦政治经济学院</a>（LSE）、<a href=\"http://zh.wikipedia.org/wiki/%E5%B8%9D%E5%9B%BD%E7%90%86%E5%B7%A5%E5%AD%A6%E9%99%A2\" title=\"帝国理工学院\" class=\"mw-redirect\">帝国理工学院</a>（Imperial College）、<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%8E%E5%A8%81%E5%A4%A7%E5%AD%A6\" title=\"华威大学\">华威大学</a>（Warwick）、<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E4%B8%81%E5%A0%A1%E5%A4%A7%E5%AD%A6\" title=\"爱丁堡大学\">爱丁堡大学</a>（Edinburgh）等等也是世界一流的著名学府。她们为英国以及整个世界培养了众多著名的<a href=\"http://zh.wikipedia.org/wiki/%E7%A7%91%E5%AD%A6%E5%AE%B6\" title=\"科学家\">科学家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%96%87%E5%AD%A6%E5%AE%B6\" title=\"文学家\" class=\"mw-redirect\">文学家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%93%B2%E5%AD%A6%E5%AE%B6\" title=\"哲学家\">哲学家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%94%BF%E6%B2%BB%E5%AE%B6\" title=\"政治家\">政治家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%B7%A5%E7%A8%8B%E5%B8%88\" title=\"工程师\">工程师</a>，例如<a href=\"http://zh.wikipedia.org/wiki/%E8%89%BE%E8%90%A8%E5%85%8B%C2%B7%E7%89%9B%E9%A1%BF\" title=\"艾萨克·牛顿\">艾萨克·牛顿</a>、<a href=\"http://zh.wikipedia.org/wiki/%E9%9B%AA%E8%8E%B1\" title=\"雪莱\" class=\"mw-redirect\">雪莱</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%9F%A5%E5%B0%94%E6%96%AF%C2%B7%E8%BE%BE%E5%B0%94%E6%96%87\" title=\"查尔斯·达尔文\">查尔斯·达尔文</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%AF%BA%E6%9B%BC%C2%B7%E7%A6%8F%E6%96%AF%E7%89%B9\" title=\"诺曼·福斯特\">诺曼·福斯特</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%8F%B2%E8%92%82%E8%8A%AC%C2%B7%E9%9C%8D%E9%87%91\" title=\"史蒂芬·霍金\">史蒂芬·霍金</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%C2%B7%E6%9D%8E%E6%96%AF%E7%89%B9\" title=\"约瑟夫·李斯特\" class=\"mw-redirect\">约瑟夫·李斯特</a>（Joseph Lister）、<a href=\"http://zh.wikipedia.org/wiki/%E4%BA%9A%E5%BD%93%C2%B7%E6%96%AF%E5%AF%86\" title=\"亚当·斯密\">亚当·斯密</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%A9%B9%E5%A7%86%E6%96%AF%C2%B7%E7%93%A6%E7%89%B9\" title=\"詹姆斯·瓦特\">詹姆斯·瓦特</a>（James Watt）、<a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%C2%B7%E6%B1%A4%E5%A7%86%E9%80%8A\" title=\"约瑟夫·汤姆逊\" class=\"mw-redirect\">約瑟夫·汤姆逊</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%B7%AF%E5%BE%B7%E7%BB%B4%E5%B8%8C%C2%B7%E7%BB%B4%E7%89%B9%E6%A0%B9%E6%96%AF%E5%9D%A6\" title=\"路德维希·维特根斯坦\">路德维希·维特根斯坦</a>和<a href=\"http://zh.wikipedia.org/wiki/%E4%BA%9A%E5%8E%86%E5%B1%B1%E5%A4%A7%C2%B7%E5%BC%97%E8%8E%B1%E6%98%8E\" title=\"亚历山大·弗莱明\">亚历山大·弗莱明</a>等等。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=22\" title=\"编辑段落：醫療\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E9.86.AB.E7.99.82\">醫療</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9C%8B%E9%86%AB%E7%99%82&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英國醫療\">英國醫療</a></div>\n</dd>\n</dl>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Royal_Aberdeen_Children%27s_Hospital.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Royal_Aberdeen_Childrens_Hospital.jpg\" class=\"thumbimage\" height=\"165\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Royal_Aberdeen_Children%27s_Hospital.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n皇家亞伯丁兒童醫院，是蘇格蘭兒童專科醫院。</div>\n</div>\n</div>\n<p>在英國，醫療有關於權力下放，國家有其自己的私人和公費醫療制度，整體性和互補性的醫療。<br style=\"clear:both;\"></p>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=23\" title=\"编辑段落：文化\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.96.87.E5.8C.96\">文化</span></h2>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%96%87%E5%8C%96&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国文化\">英国文化</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%96%87%E5%8C%96%E5%8F%B2&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国文化史\">英国文化史</a></div>\n</dd>\n</dl>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=24\" title=\"编辑段落：文学\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.96.87.E5.AD.A6\">文学</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%96%87%E5%AD%A6\" title=\"英国文学\" class=\"mw-redirect\">英国文学</a></div>\n</dd>\n</dl>\n<h4><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=25\" title=\"编辑段落：文学家\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.96.87.E5.AD.A6.E5.AE.B6\">文学家</span></h4>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%96%87%E5%AD%A6%E5%AE%B6&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国文学家\">英国文学家</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:172px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Shakespeare.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/170px-Shakespeare.jpg\" class=\"thumbimage\" height=\"218\" width=\"170\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Shakespeare.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n錢多斯畫像，藝術家和真實性未經證實的，<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%BB%89%C2%B7%E8%8E%8E%E5%A3%AB%E6%AF%94%E4%BA%9E\" title=\"威廉·莎士比亞\" class=\"mw-redirect\">威廉·莎士比亞</a></div>\n</div>\n</div>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%B8%A9%E6%96%AF%E9%A1%BF%C2%B7%E4%B8%98%E5%90%89%E5%B0%94\" title=\"温斯顿·丘吉尔\">温斯顿·丘吉尔</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%9D%B0%E5%BC%97%E9%87%8C%C2%B7%E4%B9%94%E5%8F%9F\" title=\"杰弗里·乔叟\">杰弗里·乔叟</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%BB%89%C2%B7%E8%8E%8E%E5%A3%AB%E6%AF%94%E4%BA%9A\" title=\"威廉·莎士比亚\">威廉·莎士比亚</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%BF%B0%C2%B7%E5%BC%A5%E5%B0%94%E9%A1%BF\" title=\"约翰·弥尔顿\">约翰·弥尔顿</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%BB%89%C2%B7%E5%8D%8E%E5%85%B9%E5%8D%8E%E6%96%AF\" title=\"威廉·华兹华斯\">威廉·华兹华斯</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%8B%9C%E4%BC%A6\" title=\"拜伦\" class=\"mw-redirect\">拜伦</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%9B%AA%E8%8E%B1\" title=\"雪莱\" class=\"mw-redirect\">雪莱</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%BF%B0%C2%B7%E6%B5%8E%E6%85%88\" title=\"约翰·济慈\">约翰·济慈</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%8B%83%E6%9C%97%E7%89%B9\" title=\"勃朗特\">勃朗特</a>姐妹</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E5%98%89%E8%8E%8E%C2%B7%E5%85%8B%E8%8E%89%E4%B8%9D%E8%92%82\" title=\"阿嘉莎·克莉丝蒂\" class=\"mw-redirect\">阿嘉莎·克莉丝蒂</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%9F%A5%E5%B0%94%E6%96%AF%C2%B7%E7%8B%84%E6%9B%B4%E6%96%AF\" title=\"查尔斯·狄更斯\">查尔斯·狄更斯</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%BB%89%C2%B7%E8%90%A8%E5%85%8B%E9%9B%B7\" title=\"威廉·萨克雷\" class=\"mw-redirect\">威廉·萨克雷</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%AE%80%C2%B7%E5%A5%A5%E6%96%AF%E4%B8%81\" title=\"简·奥斯丁\">简·奥斯丁</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%89%98%E9%A9%AC%E6%96%AF%C2%B7%E5%93%88%E4%BB%A3\" title=\"托马斯·哈代\">托马斯·哈代</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E7%91%9F%C2%B7%E6%9F%AF%E5%8D%97%C2%B7%E9%81%93%E5%B0%94\" title=\"阿瑟·柯南·道尔\">阿瑟·柯南·道尔</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/J%C2%B7K%C2%B7%E7%BD%97%E7%90%B3\" title=\"J·K·罗琳\">J·K·罗琳</a>（J. K. Rowling）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%BF%B0%C2%B7%E7%BD%97%E7%BA%B3%E5%BE%B7%C2%B7%E9%B2%81%E5%9F%83%E5%B0%94%C2%B7%E6%89%98%E5%B0%94%E9%87%91\" title=\"约翰·罗纳德·鲁埃尔·托尔金\" class=\"mw-redirect\">約翰·羅納德·鲁埃爾·托爾金</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/D%C2%B7H%C2%B7%E5%8A%B3%E4%BC%A6%E6%96%AF\" title=\"D·H·劳伦斯\" class=\"mw-redirect\">D·H·劳伦斯</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%C2%B7%E5%BA%B7%E6%8B%89%E5%BE%B7\" title=\"约瑟夫·康拉德\">约瑟夫·康拉德</a><small>（<a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E5%85%B0\" title=\"波兰\">波兰</a>裔）</small></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%9B%E5%A7%86\" title=\"毛姆\" class=\"mw-redirect\">毛姆</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%89%98%E9%A9%AC%E6%96%AF%C2%B7%E6%96%AF%E7%89%B9%E5%B0%94%E9%82%A3%E6%96%AF%C2%B7%E8%89%BE%E7%95%A5%E7%89%B9\" title=\"托马斯·斯特尔那斯·艾略特\" class=\"mw-redirect\">T·S·艾略特</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%BC%97%E5%90%89%E5%B0%BC%E4%BA%9A%C2%B7%E4%BC%8D%E5%B0%94%E5%A4%AB\" title=\"弗吉尼亚·伍尔夫\" class=\"mw-redirect\">弗吉尼亚·伍尔夫</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%B5%AB%E4%BC%AF%E7%89%B9%C2%B7%E5%96%AC%E6%B2%BB%C2%B7%E5%A8%81%E7%88%BE%E6%96%AF\" title=\"赫伯特·喬治·威爾斯\" class=\"mw-redirect\">赫伯特·喬治·威爾斯</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%BB%89%C2%B7%E5%B8%83%E8%8E%B1%E5%85%8B\" title=\"威廉·布莱克\">威廉·布莱克</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BD%97%E4%BC%AF%E7%89%B9%C2%B7%E5%BD%AD%E6%96%AF\" title=\"罗伯特·彭斯\" class=\"mw-redirect\">罗伯特·彭斯</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%81%E5%B0%BC%E7%94%9F\" title=\"丁尼生\">丁尼生</a></li>\n</ul>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=26\" title=\"编辑段落：戏剧\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.88.8F.E5.89.A7\">戏剧</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%88%8F%E5%89%A7&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国戏剧\">英国戏剧</a></div>\n</dd>\n</dl>\n<p>英國劇場一向興盛，<a href=\"http://zh.wikipedia.org/wiki/%E8%8E%8E%E5%A3%AB%E6%AF%94%E4%BA%9E\" title=\"莎士比亞\" class=\"mw-redirect\">莎士比亞</a>與其同時代作家<a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E9%87%8C%E6%96%AF%E6%89%98%E5%A4%AB%C2%B7%E9%A6%AC%E6%B4%9B\" title=\"克里斯托夫·馬洛\" class=\"mw-redirect\">克里斯托夫·馬洛</a>（Christopher Marlowe）、<a href=\"http://zh.wikipedia.org/wiki/%E6%9C%AC%C2%B7%E7%90%BC%E6%A3%AE\" title=\"本·琼森\">本·琼森</a>為早期英國劇場帶來了深度。近現代的著名劇作家則有<a href=\"http://zh.wikipedia.org/wiki/%E5%93%88%E7%BD%97%E5%BE%B7%C2%B7%E5%93%81%E7%89%B9\" title=\"哈罗德·品特\">哈罗德·品特</a>、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A4%A7%E8%A1%9B%C2%B7%E6%B5%B7%E7%88%BE&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"大衛·海爾\">大衛·海爾</a>（David Hare）、<a href=\"http://zh.wikipedia.org/wiki/%E6%B9%AF%E5%A7%86%C2%B7%E6%96%AF%E6%89%98%E5%B8%95%E5%BE%B7\" title=\"湯姆·斯托帕德\">汤姆·斯托帕德</a>（Tom Stoppard）、<a href=\"http://zh.wikipedia.org/wiki/%E5%BD%BC%E5%BE%97%C2%B7%E8%AC%9D%E5%BC%97\" title=\"彼得·謝弗\">彼得·謝弗</a>（Peter Shaffer）、<a href=\"http://zh.wikipedia.org/wiki/%E8%8E%8E%E6%8B%89%C2%B7%E8%82%AF%E6%81%A9\" title=\"莎拉·肯恩\">莎拉·肯恩</a>（Sarah Kane）、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E9%A6%AC%E4%B8%81%C2%B7%E9%BA%A5%E7%95%B6%E8%AB%BE&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"馬丁·麥當諾\">馬丁·麥當諾</a>（Martin McDonagh）等等。</p>\n<p>當代最著名的英國舞台劇導演首推<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%BD%BC%E5%BE%97%C2%B7%E5%B8%83%E9%AD%AF%E5%85%8B&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"彼得·布魯克\">彼得·布魯克</a>（Peter Brook），著作《空的空間》（<i>The Empty Space</i>）為劇場經典書籍之一。最為人熟知的英國舞台劇演員則公認是<a href=\"http://zh.wikipedia.org/wiki/%E5%8A%B3%E4%BC%A6%E6%96%AF%C2%B7%E5%A5%A5%E5%88%A9%E7%BB%B4%E5%B0%94\" title=\"劳伦斯·奥利维尔\">劳伦斯·奥利维尔</a>。</p>\n<p><a href=\"http://zh.wikipedia.org/wiki/17%E4%B8%96%E7%BA%AA\" title=\"17世纪\">17世纪</a>著\n名的 乔治·弗雷德里希·韩德尔（George Friedrich Handel ,Georg Frideric Handel \n英国国籍，德国民族）对英国的戏剧（Opera）发展做出了很大的贡献，韩德尔曾经参与过小提琴（Violin）, Oboe Organ \n（奥根古乐器）等音乐演奏。George Friedrich Handel 生于<a href=\"http://zh.wikipedia.org/wiki/1685%E5%B9%B4\" title=\"1685年\">1685年</a>的<a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\">德国</a>，<a href=\"http://zh.wikipedia.org/wiki/1702%E5%B9%B4\" title=\"1702年\">1702年</a>毕业于在 Halle的德国音乐学院，<a href=\"http://zh.wikipedia.org/wiki/1707%E5%B9%B4\" title=\"1707年\">1707年</a>他曾经在意大利定居并且开始学习戏剧表演，<a href=\"http://zh.wikipedia.org/wiki/1712%E5%B9%B4\" title=\"1712年\">1712年</a>韩德尔在英格兰定居，并且成功加入了北爱尔兰王家乐队进行演奏，在<a href=\"http://zh.wikipedia.org/wiki/1728%E5%B9%B4\" title=\"1728年\">1728</a>-<a href=\"http://zh.wikipedia.org/wiki/1737%E5%B9%B4\" title=\"1737年\">1737年</a>，他成功创建了自己的戏剧演奏公司并且给爱尔兰的贵族进行演奏，1759年，他于英格兰去世。</p>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=27\" title=\"编辑段落：体育\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E4.BD.93.E8.82.B2\">体育</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E4%BD%93%E8%82%B2&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国体育\">英国体育</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E8%BF%90%E5%8A%A8%E5%91%98&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国运动员\">英国运动员</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Wembley_Stadium,_illuminated.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Wembley_Stadium_illuminated.jpg\" class=\"thumbimage\" height=\"147\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Wembley_Stadium,_illuminated.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n倫敦的<a href=\"http://zh.wikipedia.org/wiki/%E6%B8%A9%E5%B8%83%E5%88%A9%E7%90%83%E5%9C%BA\" title=\"温布利球场\">溫布利球場</a>，是有史以來最造價昂貴的體育場館之一</div>\n</div>\n</div>\n<p>英國是體育大國，<a href=\"http://zh.wikipedia.org/wiki/%E8%B6%B3%E7%90%83\" title=\"足球\">足球</a>，<a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E7%90%83\" title=\"馬球\" class=\"mw-redirect\">馬球</a>，<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%BC%8F%E6%A9%84%E6%AC%96%E7%90%83\" title=\"英式橄欖球\" class=\"mw-redirect\">英式橄欖球</a>，<a href=\"http://zh.wikipedia.org/wiki/%E6%9D%BF%E7%90%83\" title=\"板球\">板球</a>，<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%BD%E6%AF%9B%E7%90%83\" title=\"羽毛球\">羽毛球</a>，<a href=\"http://zh.wikipedia.org/wiki/%E4%B9%92%E4%B9%93%E7%90%83\" title=\"乒乓球\">乒乓球</a>，等均起源於英國。其中足球為英國的第一運動，尤其在英格蘭，蘇格蘭和北愛爾蘭地區，國家足球代表隊往往是民眾最為在意以及支持的運動團隊。足球亦不單被民眾，政府乃至皇室視作單一的體育運動，更加被視為整個國家，民族的文化象徵之一。</p>\n<div class=\"thumb tleft\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Inside_the_Millennium_Stadium,_Cardiff.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Inside_the_Millennium_Stadium_Cardiff.jpg\" class=\"thumbimage\" height=\"165\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Inside_the_Millennium_Stadium,_Cardiff.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A1%E5%9C%B0%E5%A4%AB\" title=\"卡地夫\" class=\"mw-redirect\">卡地夫</a>的<a href=\"http://zh.wikipedia.org/wiki/%E5%8D%83%E7%A6%A7%E7%90%83%E5%A0%B4\" title=\"千禧球場\">千禧球場</a>為<a href=\"http://en.wikipedia.org/wiki/1999_Rugby_World_Cup\" class=\"extiw\" title=\"en:1999 Rugby World Cup\">1999年橄欖球世界杯</a>開幕</div>\n</div>\n</div>\n<p><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD%E8%B6%B3%E7%90%83%E8%B6%85%E7%B4%9A%E8%81%AF%E8%B3%BD\" title=\"英格蘭足球超級聯賽\" class=\"mw-redirect\">英格蘭足球超級聯賽</a>亦是世界上最為成功的體育聯盟之一，聯盟中有<a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E8%81%AF\" title=\"曼聯\" class=\"mw-redirect\">曼聯</a>，<a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E4%BB%99%E5%A5%B4\" title=\"阿仙奴\" class=\"mw-redirect\">阿仙奴</a>，<a href=\"http://zh.wikipedia.org/wiki/%E8%BB%8A%E8%B7%AF%E5%A3%AB\" title=\"車路士\" class=\"mw-redirect\">車路士</a>，<a href=\"http://zh.wikipedia.org/wiki/%E5%88%A9%E7%89%A9%E6%B5%A6\" title=\"利物浦\">利物浦</a>，<a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%9F%8E\" title=\"曼城\" class=\"mw-redirect\">曼城</a>,以及<a href=\"http://zh.wikipedia.org/wiki/%E6%89%98%E7%89%B9%E7%BA%B3%E5%A7%86%E7%83%AD%E5%88%BA\" title=\"托特纳姆热刺\" class=\"mw-redirect\">托特納姆熱刺</a>等歐洲著名球會。而<a href=\"http://zh.wikipedia.org/wiki/%E5%9B%9B%E5%A4%A7%E6%BB%A1%E8%B4%AF\" title=\"四大满贯\">四大滿貫</a>之一的<a href=\"http://zh.wikipedia.org/wiki/%E6%B8%A9%E5%B8%83%E5%B0%94%E7%99%BB%E7%BD%91%E7%90%83%E5%85%AC%E5%BC%80%E8%B5%9B\" title=\"温布尔登网球公开赛\" class=\"mw-redirect\">温布尔登網球公開賽</a>亦會每年與溫布頓舉行。</p>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Centre_Court_roof.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-Centre_Court_roof.jpg\" class=\"thumbimage\" height=\"147\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Centre_Court_roof.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%BA%AB%E5%B8%83%E9%A0%93%E7%B6%B2%E7%90%83%E9%8C%A6%E6%A8%99%E8%B3%BD\" title=\"溫布頓網球錦標賽\" class=\"mw-redirect\">溫布頓網球錦標賽</a>，<a href=\"http://zh.wikipedia.org/wiki/%E7%B6%B2%E7%90%83%E5%A4%A7%E6%BB%BF%E8%B2%AB\" title=\"網球大滿貫\" class=\"mw-redirect\">大滿貫賽</a>，每年六月或七月舉行的溫布爾登網球公開賽，於<a href=\"http://zh.wikipedia.org/wiki/%E5%80%AB%E6%95%A6\" title=\"倫敦\" class=\"mw-redirect\">倫敦</a></div>\n</div>\n</div>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=28\" title=\"编辑段落：哲学思想\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.93.B2.E5.AD.A6.E6.80.9D.E6.83.B3\">哲学思想</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E5%93%B2%E5%AD%A6&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国哲学\">英国哲学</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E5%93%B2%E5%AD%A6%E5%8F%B2&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国哲学史\">英国哲学史</a></div>\n</dd>\n</dl>\n<h4><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=29\" title=\"编辑段落：思想家\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.80.9D.E6.83.B3.E5.AE.B6\">思想家</span></h4>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%80%9D%E6%83%B3%E5%AE%B6&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国思想家\">英国思想家</a></div>\n</dd>\n</dl>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%BF%B0%C2%B7%E6%B4%9B%E5%85%8B\" title=\"约翰·洛克\">约翰·洛克</a>（John Locke），最早提出<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%89%E6%9D%83%E5%88%86%E7%AB%8B\" title=\"三权分立\" class=\"mw-redirect\">三权分立</a>理论；</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%89%98%E9%A9%AC%E6%96%AF%C2%B7%E8%8E%AB%E5%B0%94\" title=\"托马斯·莫尔\">托马斯·莫尔</a>（Thomas More），<a href=\"http://zh.wikipedia.org/wiki/%E7%A9%BA%E6%83%B3%E7%A4%BE%E4%BC%9A%E4%B8%BB%E4%B9%89\" title=\"空想社会主义\">空想社会主义</a>的代表人物；</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BD%97%E4%BC%AF%E7%89%B9%C2%B7%E6%AC%A7%E6%96%87\" title=\"罗伯特·欧文\">罗伯特·欧文</a>（Robert Owen），空想社会主义的代表人物；</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E7%BA%B3%E5%BE%B7%C2%B7%E9%B2%8D%E6%A1%91%E8%91%B5\" title=\"伯纳德·鲍桑葵\">伯纳德·鲍桑葵</a>（Bernard Bosanquet），英国<a href=\"http://zh.wikipedia.org/wiki/%E5%94%AF%E5%BF%83%E4%B8%BB%E4%B9%89\" title=\"唯心主义\" class=\"mw-redirect\">唯心主义</a>的代表人物；</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%BC%97%E5%85%B0%E8%A5%BF%E6%96%AF%C2%B7%E5%9F%B9%E6%A0%B9\" title=\"弗兰西斯·培根\">弗蘭西斯·培根</a>（Francis Bacon），<a href=\"http://zh.wikipedia.org/wiki/%E6%95%A3%E6%96%87\" title=\"散文\">散文</a><a href=\"http://zh.wikipedia.org/wiki/%E4%BD%9C%E5%AE%B6\" title=\"作家\">作家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%93%B2%E5%AD%B8%E5%AE%B6\" title=\"哲學家\" class=\"mw-redirect\">哲學家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E6%94%BF%E6%B2%BB%E5%AE%B6\" title=\"政治家\">政治家</a>，是<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8F%A4%E5%85%B8%E7%B6%93%E9%A9%97%E8%AB%96&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"古典經驗論\">古典經驗論</a>的始祖；</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E5%8D%AB%C2%B7%E4%BC%91%E8%B0%9F\" title=\"大卫·休谟\">大卫·休谟</a>（David Hume），哲学家、<a href=\"http://zh.wikipedia.org/wiki/%E7%BB%8F%E6%B5%8E%E5%AD%A6%E5%AE%B6\" title=\"经济学家\">经济学家</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%8E%86%E5%8F%B2%E5%AD%A6%E5%AE%B6\" title=\"历史学家\">历史学家</a>；</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E4%BA%9E%E7%95%B6%C2%B7%E6%96%AF%E5%AF%86\" title=\"亞當·斯密\" class=\"mw-redirect\">亞當·斯密</a>（Adam Smith），经济学家、哲学家，代表作为《<a href=\"http://zh.wikipedia.org/wiki/%E5%9B%BD%E5%AF%8C%E8%AE%BA\" title=\"国富论\" class=\"mw-redirect\">国富论</a>》。</li>\n</ul>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=30\" title=\"编辑段落：媒體\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.AA.92.E9.AB.94\">媒體</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9C%8B%E5%AA%92%E9%AB%94&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英國媒體\">英國媒體</a></div>\n</dd>\n</dl>\n<p>英國廣播公司，成立於1922年，是英國政府資助的電台，電視和互聯網廣播公司，是世界上最古老和最大的廣播。</p>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:182px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Bbc_broadcasting_house_front.jpg\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/180px-Bbc_broadcasting_house_front.jpg\" class=\"thumbimage\" height=\"250\" width=\"180\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:Bbc_broadcasting_house_front.jpg\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n於倫敦的<a href=\"http://en.wikipedia.org/wiki/Broadcasting_House\" class=\"extiw\" title=\"en:Broadcasting House\">廣播大廈</a>，是英國廣播公司總部</div>\n</div>\n</div>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=31\" title=\"编辑段落：音乐\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E9.9F.B3.E4.B9.90\">音乐</span></h3>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B%E9%9F%B3%E6%A8%82\" title=\"英國音樂\">英国音乐</a></div>\n</dd>\n</dl>\n<p><a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%95%B6%E4%BB%A3%E8%8B%B1%E5%9C%8B&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"當代英國\">當代英國</a>擁有多樣的<a href=\"http://zh.wikipedia.org/w/index.php?title=%E9%9F%B3%E6%A8%82%E6%96%87%E5%8C%96&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"音樂文化\">音樂文化</a>。<a href=\"http://zh.wikipedia.org/wiki/%E5%8F%A4%E5%85%B8%E9%9F%B3%E6%A8%82\" title=\"古典音樂\" class=\"mw-redirect\">古典音樂</a>方面，來自英國的知名<a href=\"http://zh.wikipedia.org/wiki/%E4%BA%A4%E9%9F%BF%E6%A8%82%E5%9C%98\" title=\"交響樂團\" class=\"mw-redirect\">交響樂團</a>包括<a href=\"http://zh.wikipedia.org/w/index.php?title=BBC%E4%BA%A4%E9%9F%BF%E6%A8%82%E5%9C%98&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"BBC交響樂團\">BBC交響樂團</a>、<a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%9A%87%E5%AE%B6%E6%84%9B%E6%A8%82%E6%A8%82%E5%9C%98&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"皇家愛樂樂團\">皇家愛樂樂團</a>、<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E4%B9%90%E4%B9%90%E5%9B%A2\" title=\"爱乐乐团\">愛樂樂團</a>、<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6%E4%BA%A4%E5%93%8D%E4%B9%90%E5%9B%A2\" title=\"伦敦交响乐团\">倫敦交響樂團</a>以及<a href=\"http://zh.wikipedia.org/wiki/%E4%BC%A6%E6%95%A6%E7%88%B1%E4%B9%90%E4%B9%90%E5%9B%A2\" title=\"伦敦爱乐乐团\">倫敦愛樂樂團</a>等。知名的<a href=\"http://zh.wikipedia.org/wiki/%E4%BD%9C%E6%9B%B2%E5%AE%B6\" title=\"作曲家\">作曲家</a>有<a href=\"http://zh.wikipedia.org/wiki/%E7%8F%80%E5%A1%9E%E7%88%BE\" title=\"珀塞爾\" class=\"mw-redirect\">珀塞爾</a>（<a href=\"http://en.wikipedia.org/wiki/Henry_Purcell\" class=\"extiw\" title=\"en:Henry Purcell\">Purcell, Henry</a>）、<a href=\"http://zh.wikipedia.org/wiki/%E5%9F%83%E7%88%BE%E5%8A%A0\" title=\"埃爾加\" class=\"mw-redirect\">埃爾加</a>（Elgar, Edward）、<a href=\"http://zh.wikipedia.org/wiki/%E9%9C%8D%E7%88%BE%E6%96%AF%E7%89%B9\" title=\"霍爾斯特\" class=\"mw-redirect\">霍爾斯特</a>（Holst, Gustav）、<a href=\"http://zh.wikipedia.org/wiki/%E4%BD%9B%E6%BC%A2%C2%B7%E5%A8%81%E5%BB%89%E6%96%AF\" title=\"佛漢·威廉斯\" class=\"mw-redirect\">沃恩·威廉斯</a>（Vaughan Williams, Ralph）、<a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E5%BE%B7%E9%AD%AF%C2%B7%E6%B4%9B%E4%BC%8A%C2%B7%E9%9F%8B%E4%BC%AF\" title=\"安德魯·洛伊·韋伯\" class=\"mw-redirect\">安德魯·洛伊·韋伯</a>（Andrew Lloyd Webber）等。</p>\n<h4><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=32\" title=\"编辑段落：主要的樂手與樂團\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E4.B8.BB.E8.A6.81.E7.9A.84.E6.A8.82.E6.89.8B.E8.88.87.E6.A8.82.E5.9C.98\">主要的樂手與樂團</span></h4>\n<dl>\n<dd>\n<div class=\"noprint\" style=\"font-size:small\">主条目：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9C%8B%E6%A8%82%E6%89%8B&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英國樂手\">英國樂手</a>和<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9C%8B%E6%A8%82%E9%9A%8A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英國樂隊\">英國樂隊</a></div>\n</dd>\n</dl>\n<div class=\"thumb tright\">\n<div class=\"thumbinner\" style=\"width:222px;\"><a href=\"http://zh.wikipedia.org/wiki/File:The_Fabs.JPG\" class=\"image\"><img alt=\"\" src=\"England%28Chinese%29_files/220px-The_Fabs.JPG\" class=\"thumbimage\" height=\"220\" width=\"220\"></a>\n<div class=\"thumbcaption\">\n<div class=\"magnify\"><a href=\"http://zh.wikipedia.org/wiki/File:The_Fabs.JPG\" class=\"internal\" title=\"放大\"><img src=\"England%28Chinese%29_files/magnify-clip.png\" alt=\"\" height=\"11\" width=\"15\"></a></div>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%8A%AB%E9%A0%AD%E5%9B%9B\" title=\"披頭四\" class=\"mw-redirect\">披頭四</a>在音樂史上是最成功與廣受好評的樂隊之一，國際銷售超過10億張的記錄。</div>\n</div>\n</div>\n<p>（依照團名或姓氏字母的順序排列）</p>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%8A%AB%E9%A0%AD%E5%9B%9B%E6%A8%82%E9%9A%8A\" title=\"披頭四樂隊\">披頭四樂隊</a>（The Beatles）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%BB%91%E8%89%B2%E5%AE%89%E6%81%AF%E6%97%A5\" title=\"黑色安息日\">黑色安息日</a>（Black Sabbath）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/Blur\" title=\"Blur\" class=\"mw-redirect\">Blur</a>（Blur）</li>\n<li><a href=\"http://zh.wikipedia.org/w/index.php?title=%E9%A6%99%E8%95%89%E5%A5%B3%E9%83%8E%E6%A8%82%E9%9A%8A&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"香蕉女郎樂隊\">香蕉女郎樂隊</a>（BANANARAMA）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%85%B7%E7%8E%A9%E6%A8%82%E5%9C%98\" title=\"酷玩樂團\">酷玩樂團</a>（Coldplay）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%B7%B1%E7%B4%AB\" title=\"深紫\">深紫</a>（Deep Purple）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%BB%91%E6%9A%97%E6%A8%82%E9%9A%8A\" title=\"黑暗樂隊\" class=\"mw-redirect\">黑暗樂隊</a>（The Darkness）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%A1%9B%C2%B7%E9%AE%91%E4%BC%8A\" title=\"大衛·鮑伊\" class=\"mw-redirect\">大衛·鮑伊</a>（David Bowie）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%9F%83%E9%87%8C%E5%85%8B%C2%B7%E5%85%8B%E8%8E%B1%E6%99%AE%E9%A1%BF\" title=\"埃里克·克莱普顿\">埃裏克·克萊普頓</a>(Eric Clapton)</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%90%B5%E5%A8%98%E5%AD%90%E6%A8%82%E5%9C%98\" title=\"鐵娘子樂團\">鐵娘子樂團</a>（Iron Maiden）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%8A%B9%E5%A4%A7%E5%9C%A3%E5%BE%92\" title=\"犹大圣徒\" class=\"mw-redirect\">猶大聖徒</a>（Judas Priest）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%BD%8A%E6%9F%8F%E6%9E%97%E9%A3%9B%E8%88%B9_%28%E6%A8%82%E5%9C%98%29\" title=\"齊柏林飛船 (樂團)\" class=\"mw-redirect\">齊柏林飛船</a>（Led Zeppelin）</li>\n<li><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%B0%8F%E9%A3%9B%E4%BF%A0_%28%E6%A8%82%E5%9C%98%29&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"小飛俠 (樂團)\">小飛俠 (樂團)</a> ( McFLY )</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E6%89%98%E9%A0%AD\" title=\"摩托頭\" class=\"mw-redirect\">摩托頭</a>（Motörhead）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%B9%86%E6%96%AF%E6%A8%82%E9%9A%8A\" title=\"繆斯樂隊\" class=\"mw-redirect\">繆斯樂隊</a>（Muse）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%B6%A0%E6%B4%B2%E6%A8%82%E5%9C%98\" title=\"綠洲樂團\" class=\"mw-redirect\">綠洲樂團</a>（Oasis）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%B9%B3%E5%85%8B%C2%B7%E5%BC%97%E6%B4%9B%E4%BC%8A%E5%BE%B7\" title=\"平克·弗洛伊德\">平克·弗洛伊德</a>（Pink Floyd）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%AD%A6%E5%AF%9F%E4%B9%90%E9%98%9F\" title=\"警察乐队\">警察樂隊</a>（The Police）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%9A%87%E5%90%8E%E6%A8%82%E9%9A%8A\" title=\"皇后樂隊\" class=\"mw-redirect\">皇后樂隊</a>（Queen）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%9B%BB%E5%8F%B0%E5%8F%B8%E4%BB%A4\" title=\"電台司令\" class=\"mw-redirect\">電台司令</a>（Radiohead）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%85%E6%AF%94%C2%B7%E5%A8%81%E5%BB%89%E6%96%AF\" title=\"羅比·威廉斯\" class=\"mw-redirect\">羅比·威廉斯</a>（Robbie Williams）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%BB%BE%E7%9F%B3%E6%A8%82%E9%9A%8A\" title=\"滾石樂隊\" class=\"mw-redirect\">滾石樂隊</a>（The Rolling Stones）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%80%A7%E6%89%8B%E6%A7%8D\" title=\"性手槍\" class=\"mw-redirect\">性手槍</a>（Sex Pistols）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/Suede\" title=\"Suede\">Suede</a>（Suede）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%BE%A3%E5%A6%B9%E5%90%88%E5%94%B1%E5%9C%98\" title=\"辣妹合唱團\">辣妹合唱團</a>（Spice Girls）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%8F%B2%E6%B1%80\" title=\"史汀\">史汀</a>（Sting）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%8E%A5%E6%8B%9B\" title=\"接招\">接招</a>（Take That）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E9%AD%94%E6%80%AA\" title=\"魔怪\" class=\"mw-redirect\">魔怪</a>（Mogwai)</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%A5%B5%E6%BD%91%E7%8C%B4\" title=\"北極潑猴\">北極潑猴</a>（Arctic Monkeys）</li>\n<li><a href=\"http://zh.wikipedia.org/w/index.php?title=%E6%96%87%E5%8C%96%E4%BF%B1%E6%A8%82%E9%83%A8&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"文化俱樂部\">文化俱樂部</a>（Culture Club）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E6%9D%9C%E8%98%AD%E6%9D%9C%E8%98%AD\" title=\"杜蘭杜蘭\">杜蘭杜蘭</a>（Duran Duran）</li>\n<li><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%B0%8F%E8%89%BE%E7%95%A5%E7%89%B9&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"小艾略特\">小艾略特</a>（Elliot Minor）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/Placebo\" title=\"Placebo\">Placebo</a>（Placebo）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/Travis\" title=\"Travis\" class=\"mw-redirect\">Travis</a>（Travis）</li>\n<li><a href=\"http://zh.wikipedia.org/wiki/Plan_B\" title=\"Plan B\">Plan B</a>（B計畫）</li>\n</ul>\n<h3><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=33\" title=\"编辑段落：节日假期\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E8.8A.82.E6.97.A5.E5.81.87.E6.9C.9F\">节日假期</span></h3>\n<table class=\"wikitable\">\n<caption><b>假期<sup>1</sup></b></caption>\n<tbody><tr>\n<th style=\"background: none repeat scroll 0% 0% rgb(239, 239, 239);\">日期</th>\n<th style=\"background: none repeat scroll 0% 0% rgb(239, 239, 239);\">中文譯名</th>\n<th style=\"background: none repeat scroll 0% 0% rgb(239, 239, 239);\">當地名稱</th>\n<th style=\"background: none repeat scroll 0% 0% rgb(239, 239, 239);\">備注</th>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/1%E6%9C%881%E6%97%A5\" title=\"1月1日\">1月1日</a></td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%85%83%E6%97%A6\" title=\"元旦\">元旦</a></td>\n<td>New Year's Day</td>\n<td>……</td>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/1%E6%9C%882%E6%97%A5\" title=\"1月2日\">1月2日</a></td>\n<td>元旦翌日</td>\n<td>The Day following New Year's Day</td>\n<td>只適用於<a href=\"http://zh.wikipedia.org/wiki/%E8%98%87%E6%A0%BC%E8%98%AD\" title=\"蘇格蘭\">蘇格蘭</a>地區</td>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/3%E6%9C%8817%E6%97%A5\" title=\"3月17日\">3月17日</a></td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E5%B8%95%E7%89%B9%E9%87%8C%E5%85%8B%E8%8A%82\" title=\"圣帕特里克节\">圣帕特里克节</a></td>\n<td>St. Patrick's Day</td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A9%E4%B8%BB%E6%95%99\" title=\"天主教\">天主教</a>節日，只適用於<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%84%9B%E7%88%BE%E8%98%AD\" title=\"北愛爾蘭\" class=\"mw-redirect\">北愛爾蘭</a>地區</td>\n</tr>\n<tr>\n<td>……</td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%80%B6%E7%A9%8C%E5%8F%97%E9%9B%A3%E6%97%A5\" title=\"耶穌受難日\" class=\"mw-redirect\">耶穌受難日</a></td>\n<td>Good Friday</td>\n<td>復活節之前的一個星期五</td>\n</tr>\n<tr>\n<td>……</td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%8D%E6%B4%BB%E8%8A%82%E6%98%9F%E6%9C%9F%E4%B8%80\" title=\"复活节星期一\">復活節星期一</a></td>\n<td>Easter Monday</td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E6%98%A5%E5%88%86\" title=\"春分\">春分</a>後第一個<a href=\"http://zh.wikipedia.org/wiki/%E6%BB%BF%E6%9C%88\" title=\"滿月\" class=\"mw-redirect\">滿月</a>後的第一個星期一，不適用於蘇格蘭地區</td>\n</tr>\n<tr>\n<td>……</td>\n<td><a href=\"http://zh.wikipedia.org/w/index.php?title=%E4%BA%94%E6%9C%88%E5%88%9D%E5%85%AC%E5%85%B1%E5%81%87%E6%97%A5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"五月初公共假日\">五月初公共假日</a></td>\n<td>Early May Bank Holiday</td>\n<td>五月份第一個星期一</td>\n</tr>\n<tr>\n<td>……</td>\n<td><a href=\"http://zh.wikipedia.org/w/index.php?title=%E6%98%A5%E5%A4%A9%E5%85%AC%E5%85%B1%E5%81%87%E6%97%A5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"春天公共假日\">春天公共假日</a></td>\n<td>Spring Bank Holiday</td>\n<td>五月份最後一個星期一</td>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/7%E6%9C%8812%E6%97%A5\" title=\"7月12日\">7月12日</a><sup><b>2</b></sup></td>\n<td><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A5%A7%E8%98%AD%E6%B2%BB%E6%97%A5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"奧蘭治日\">奧蘭治日</a></td>\n<td>Orangemen's Day (Battle of the Boyne's Day)</td>\n<td>只適用於<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%84%9B%E7%88%BE%E8%98%AD\" title=\"北愛爾蘭\" class=\"mw-redirect\">北愛爾蘭</a>地區</td>\n</tr>\n<tr>\n<td>……</td>\n<td><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A4%8F%E5%A4%A9%E5%85%AC%E5%85%B1%E5%81%87%E6%97%A5&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"夏天公共假日\">夏天公共假日</a></td>\n<td>Summer Bank Holiday</td>\n<td>八月份最後一個星期一</td>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/11%E6%9C%885%E6%97%A5\" title=\"11月5日\">11月5日</a></td>\n<td><a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%84%B0%E7%81%AB%E7%AF%80&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"焰火節\">焰火節</a></td>\n<td>Bonfire Night</td>\n<td>非官方假期</td>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/12%E6%9C%8825%E6%97%A5\" title=\"12月25日\">12月25日</a></td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E8%AF%9E%E8%8A%82\" title=\"圣诞节\">圣诞节</a></td>\n<td>Christmas Day</td>\n<td>……</td>\n</tr>\n<tr>\n<td><a href=\"http://zh.wikipedia.org/wiki/12%E6%9C%8826%E6%97%A5\" title=\"12月26日\">12月26日</a></td>\n<td><a href=\"http://zh.wikipedia.org/wiki/%E8%8A%82%E7%A4%BC%E6%97%A5\" title=\"节礼日\">节礼日</a>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8A%82%E7%A4%BC%E6%97%A5\" title=\"节礼日\">拆禮物日</a>）</td>\n<td>Boxing Day</td>\n<td>……</td>\n</tr>\n</tbody></table>\n<h4><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=34\" title=\"编辑段落：注譯\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.B3.A8.E8.AD.AF\">注譯</span></h4>\n<ol>\n<li>除特別說明（見<b>備註</b>一項）外，以上假期普遍適用於<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E8%98%AD\" title=\"英格蘭\" class=\"mw-redirect\">英格蘭</a>、<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E7%88%BE%E6%96%AF\" title=\"威爾斯\" class=\"mw-redirect\">威爾斯</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%98%87%E6%A0%BC%E8%98%AD\" title=\"蘇格蘭\">蘇格蘭</a>及<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%84%9B%E7%88%BE%E8%98%AD\" title=\"北愛爾蘭\" class=\"mw-redirect\">北愛爾蘭</a>地區；</li>\n<li>該假日<a href=\"http://zh.wikipedia.org/wiki/%E6%97%A5%E6%9C%9F\" title=\"日期\">日期</a>以<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8C%97%E6%84%9B%E7%88%BE%E8%98%AD%E4%BA%8B%E5%8B%99%E5%A4%A7%E8%87%A3&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"北愛爾蘭事務大臣\">北愛爾蘭事務大臣</a><small>（<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AF%AD\" title=\"英语\">英语</a>：<b>Secretary of State for North Ireland</b>）</small>公佈為準。</li>\n</ol>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=35\" title=\"编辑段落：注释与参考资料\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E6.B3.A8.E9.87.8A.E4.B8.8E.E5.8F.82.E8.80.83.E8.B5.84.E6.96.99\">注释与参考资料</span></h2>\n<div class=\"references-small references-column-count references-column-count-2\" style=\"-moz-column-count:2; -webkit-column-count:2; column-count:2;\">\n<ol class=\"references\">\n<li id=\"cite_note-0\"><b><a href=\"#cite_ref-0\">^</a></b> <span class=\"reference-text\">此为王室格言。在苏格兰，王室格言则是<a href=\"http://zh.wikipedia.org/wiki/%E4%BD%8E%E5%9C%B0%E8%98%87%E6%A0%BC%E8%98%AD%E8%AA%9E\" title=\"低地蘇格蘭語\">低地苏格兰语</a>谚语<a href=\"http://zh.wikipedia.org/w/index.php?title=In_My_Defens_God_Me_Defend&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"In My Defens God Me Defend\">In My Defens God Me Defend</a>（“主为我的防御而辩护”，常简写为“IN DEFENS”）。苏格兰的纹章使用有差异，请见<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E7%9A%87%E5%AE%B6%E5%BE%BD%E7%AB%A0\" title=\"英国皇家徽章\">英国皇家徽章</a>。</span></li>\n<li id=\"cite_note-1\"><b><a href=\"#cite_ref-1\">^</a></b> <span class=\"reference-text\">常用的英文简称还有“<span xml:lang=\"en\" lang=\"en\">UK</span>”、“<span xml:lang=\"en\" lang=\"en\">Great Britain</span>”</span></li>\n<li id=\"cite_note-FCO_global_network-2\"><b><a href=\"#cite_ref-FCO_global_network_2-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.fco.gov.uk/en/fco-in-action/global-network\">FCO global network</a> <span class=\"reference-accessdate\">[2006-05-16]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=FCO+global+network&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.fco.gov.uk%2Fen%2Ffco-in-action%2Fglobal-network&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-The_Countries_of_the_UK-3\"><b><a href=\"#cite_ref-The_Countries_of_the_UK_3-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.statistics.gov.uk/geography/uk_countries.asp\">The Countries of the UK</a> <span class=\"reference-accessdate\">[2006-05-16]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=The+Countries+of+the+UK&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.statistics.gov.uk%2Fgeography%2Fuk_countries.asp&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-Industrial_Revolution-4\"><b><a href=\"#cite_ref-Industrial_Revolution_4-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.ace.mmu.ac.uk/eae/Global_Warming/Older/Industrial_Revolution.htm\">Industrial Revolution</a> <span class=\"reference-accessdate\">[2006-05-16]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Industrial+Revolution&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.ace.mmu.ac.uk%2Feae%2FGlobal_Warming%2FOlder%2FIndustrial_Revolution.htm&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-Ferguson.2C_Niall-5\"><b><a href=\"#cite_ref-Ferguson.2C_Niall_5-0\">^</a></b> <span class=\"reference-text\">{{ |title=Empire, The rise and demise of the British world order and the lessons for global power Basic Books. <a href=\"http://zh.wikipedia.org/wiki/Special:%E7%BD%91%E7%BB%9C%E4%B9%A6%E6%BA%90/0465023282\" class=\"internal mw-magiclink-isbn\">ISBN 0-465-02328-2</a>}}</span></li>\n<li id=\"cite_note-6\"><b><a href=\"#cite_ref-6\">^</a></b> <span class=\"reference-text\"><a rel=\"nofollow\" class=\"external text\" href=\"http://huopost.com/%E5%88%86%E8%80%8C%E4%B9%B1%E4%B9%8B-%E8%8B%B1%E5%9B%BD%E4%BA%BA%E6%B0%B8%E6%81%92%E7%9A%84%E6%94%BF%E6%B2%BB%E6%99%BA%E6%85%A7/\">分而乱之—英国人永恒的政治“智慧”</a></span></li>\n<li id=\"cite_note-7\"><b><a href=\"#cite_ref-7\">^</a></b> <span class=\"reference-text\">Oxford\n English Dictionary: \"British Isles: a geographical term for the islands\n comprising Great Britain and Ireland with all their offshore islands \nincluding the Isle of Man and the Channel Islands.\"</span></li>\n<li id=\"cite_note-factbook-8\">^ <a href=\"#cite_ref-factbook_8-0\"><sup><b>9.0</b></sup></a> <a href=\"#cite_ref-factbook_8-1\"><sup><b>9.1</b></sup></a> <a href=\"#cite_ref-factbook_8-2\"><sup><b>9.2</b></sup></a> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"https://www.cia.gov/library/publications/the-world-factbook/geos/uk.html\">United Kingdom</a>. <a href=\"http://zh.wikipedia.org/wiki/The_World_Factbook\" title=\"The World Factbook\" class=\"mw-redirect\">The World Factbook</a>. Central Intelligence Agency <span class=\"reference-accessdate\">[23 September 2008]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=United+Kingdom&amp;rft.atitle=%5B%5BThe+World+Factbook%5D%5D&amp;rft.pub=Central+Intelligence+Agency&amp;rft_id=https%3A%2F%2Fwww.cia.gov%2Flibrary%2Fpublications%2Fthe-world-factbook%2Fgeos%2Fuk.html&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-Atlapedia-9\">^ <a href=\"#cite_ref-Atlapedia_9-0\"><sup><b>10.0</b></sup></a> <a href=\"#cite_ref-Atlapedia_9-1\"><sup><b>10.1</b></sup></a> <a href=\"#cite_ref-Atlapedia_9-2\"><sup><b>10.2</b></sup></a> <a href=\"#cite_ref-Atlapedia_9-3\"><sup><b>10.3</b></sup></a> <span class=\"reference-text\"><span class=\"citation web\">Latimer Clarke Corporation Pty Ltd. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.atlapedia.com/online/countries/unitedki.htm\">United Kingdom&nbsp;– Atlapedia Online</a>. Atlapedia.com <span class=\"reference-accessdate\">[26 October 2010]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=United+Kingdom%26nbsp%3B%E2%80%93+Atlapedia+Online&amp;rft.atitle=&amp;rft.aulast=Latimer+Clarke+Corporation+Pty+Ltd&amp;rft.au=Latimer+Clarke+Corporation+Pty+Ltd&amp;rft.pub=Atlapedia.com&amp;rft_id=http%3A%2F%2Fwww.atlapedia.com%2Fonline%2Fcountries%2Funitedki.htm&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-10\"><b><a href=\"#cite_ref-10\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\">Neal, Clare. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.cartography.org.uk/default.asp?contentID=749\">How long is the UK coastline?</a>. British Cartographic Society <span class=\"reference-accessdate\">[26 October 2010]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=How+long+is+the+UK+coastline%3F&amp;rft.atitle=&amp;rft.aulast=Neal%2C+Clare&amp;rft.au=Neal%2C+Clare&amp;rft.pub=British+Cartographic+Society&amp;rft_id=http%3A%2F%2Fwww.cartography.org.uk%2Fdefault.asp%3FcontentID%3D749&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-11\"><b><a href=\"#cite_ref-11\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.eurotunnel.com/ukcP3Main/ukcCorporate/ukcTunnelInfrastructure/ukcInfrastructure/\">The Channel Tunnel</a>. Eurotunnel <span class=\"reference-accessdate\">[29 November 2010]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=The+Channel+Tunnel&amp;rft.atitle=&amp;rft.pub=Eurotunnel&amp;rft_id=http%3A%2F%2Fwww.eurotunnel.com%2FukcP3Main%2FukcCorporate%2FukcTunnelInfrastructure%2FukcInfrastructure%2F&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-12\"><b><a href=\"#cite_ref-12\">^</a></b> <span class=\"reference-text\"><span class=\"citation news\"><a rel=\"nofollow\" class=\"external text\" href=\"http://news.bbc.co.uk/2/hi/europe/country_profiles/7327029.stm\">England&nbsp;– Profile</a>. BBC News. 11 February 2010.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.atitle=England%26nbsp%3B%E2%80%93+Profile&amp;rft.jtitle=BBC+News&amp;rft.date=11+February+2010&amp;rft_id=http%3A%2F%2Fnews.bbc.co.uk%2F2%2Fhi%2Feurope%2Fcountry_profiles%2F7327029.stm&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-13\"><b><a href=\"#cite_ref-13\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://web.archive.org/web/20080621045248/http://www.scotland.org/about/fact-file/index.html\">Scotland Facts</a>. Scotland Online Gateway <span class=\"reference-accessdate\">[16 July 2008]</span> (<a rel=\"nofollow\" class=\"external text\" href=\"http://www.scotland.org/about/fact-file/index.html\">原始内容</a>存档於21 June 2008).</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Scotland+Facts&amp;rft.atitle=&amp;rft.pub=Scotland+Online+Gateway&amp;rft_id=http%3A%2F%2Fweb.archive.org%2Fweb%2F20080621045248%2Fhttp%3A%2F%2Fwww.scotland.org%2Fabout%2Ffact-file%2Findex.html&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-14\"><b><a href=\"#cite_ref-14\">^</a></b> <span class=\"reference-text\"><span class=\"citation news\">Winter, Jon. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.independent.co.uk/travel/uk/the-complete-guide-to--scottish-islands-754070.html\">The complete guide to Scottish Islands</a>. The Independent. London. 19 May 2001.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.atitle=The+complete+guide+to+Scottish+Islands&amp;rft.jtitle=The+Independent&amp;rft.aulast=Winter&amp;rft.aufirst=Jon&amp;rft.au=Winter%2C%26%2332%3BJon&amp;rft.date=19+May+2001&amp;rft.place=London&amp;rft_id=http%3A%2F%2Fwww.independent.co.uk%2Ftravel%2Fuk%2Fthe-complete-guide-to--scottish-islands-754070.html&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-15\"><b><a href=\"#cite_ref-15\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.scottish-places.info/features/featurefirst7728.html\">Overview of Highland Boundary Fault</a>. Gazetteer for Scotland. University of Edinburgh <span class=\"reference-accessdate\">[27 December 2010]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Overview+of+Highland+Boundary+Fault&amp;rft.atitle=Gazetteer+for+Scotland&amp;rft.pub=University+of+Edinburgh&amp;rft_id=http%3A%2F%2Fwww.scottish-places.info%2Ffeatures%2Ffeaturefirst7728.html&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-16\"><b><a href=\"#cite_ref-16\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.bennevisweather.co.uk/index.asp\">Ben Nevis Weather</a>. Ben Nevis Weather <span class=\"reference-accessdate\">[26 October 2008]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Ben+Nevis+Weather&amp;rft.atitle=&amp;rft.pub=Ben+Nevis+Weather&amp;rft_id=http%3A%2F%2Fwww.bennevisweather.co.uk%2Findex.asp&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-17\"><b><a href=\"#cite_ref-17\">^</a></b> <span class=\"reference-text\"><span class=\"citation news\"><a rel=\"nofollow\" class=\"external text\" href=\"http://news.bbc.co.uk/2/hi/europe/country_profiles/6233450.stm\">Profile: Wales</a>. BBC News. 9 June 2010 <span class=\"reference-accessdate\">[7 November 2010]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.atitle=Profile%3A+Wales&amp;rft.jtitle=BBC+News&amp;rft.date=9+June+2010&amp;rft_id=http%3A%2F%2Fnews.bbc.co.uk%2F2%2Fhi%2Feurope%2Fcountry_profiles%2F6233450.stm&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-18\"><b><a href=\"#cite_ref-18\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://cain.ulst.ac.uk/ni/geog.htm\">Geography of Northern Ireland</a>. University of Ulster <span class=\"reference-accessdate\">[22 May 2006]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Geography+of+Northern+Ireland&amp;rft.atitle=&amp;rft.pub=University+of+Ulster&amp;rft_id=http%3A%2F%2Fcain.ulst.ac.uk%2Fni%2Fgeog.htm&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-19\"><b><a href=\"#cite_ref-19\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.metoffice.gov.uk/climate/uk/\">UK climate summaries</a>. Met Office <span class=\"reference-accessdate\">[1 May 2011]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=UK+climate+summaries&amp;rft.atitle=&amp;rft.pub=Met+Office&amp;rft_id=http%3A%2F%2Fwww.metoffice.gov.uk%2Fclimate%2Fuk%2F&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-20\"><b><a href=\"#cite_ref-20\">^</a></b> <span class=\"reference-text\"><span class=\"citation news\">Salkeld, Luke. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.dailymail.co.uk/news/article-2070541/UK-weather-Snow-gales-blizzards-arctic-conditions-leave-Britain-shivering.html\">Snow News</a>. <a rel=\"nofollow\" class=\"external free\" href=\"http://www.dailymail.co.uk/news/article-2070541/UK-weather-Snow-gales-blizzards-arctic-conditions-leave-Britain-shivering.html\">http://www.dailymail.co.uk/news/article-2070541/UK-weather-Snow-gales-blizzards-arctic-conditions-leave-Britain-shivering.html</a>. London. 8 December 2011 <span class=\"reference-accessdate\">[8 December 2011]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.atitle=Snow+News&amp;rft.jtitle=http%3A%2F%2Fwww.dailymail.co.uk%2Fnews%2Farticle-2070541%2FUK-weather-Snow-gales-blizzards-arctic-conditions-leave-Britain-shivering.html&amp;rft.aulast=Salkeld&amp;rft.aufirst=Luke&amp;rft.au=Salkeld%2C%26%2332%3BLuke&amp;rft.date=8+December+2011&amp;rft.place=London&amp;rft_id=http%3A%2F%2Fwww.dailymail.co.uk%2Fnews%2Farticle-2070541%2FUK-weather-Snow-gales-blizzards-arctic-conditions-leave-Britain-shivering.html&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-BBC_News-21\"><b><a href=\"#cite_ref-BBC_News_21-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://news.bbc.co.uk/1/hi/uk_politics/6245682.stm\">Gorden Brown became the PM of UK</a> <span class=\"reference-accessdate\">[2008-01-23]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Gorden+Brown+became+the+PM+of+UK&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fnews.bbc.co.uk%2F1%2Fhi%2Fuk_politics%2F6245682.stm&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-election-22\"><b><a href=\"#cite_ref-election_22-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://statistics.gov.uk/\">Westminster Parliamentary Constituencies statistic</a> <span class=\"reference-accessdate\">[2008-01-23]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Westminster+Parliamentary+Constituencies+statistic&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fstatistics.gov.uk&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-Sarah_Carter-23\"><b><a href=\"#cite_ref-Sarah_Carter_23-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.llrx.com/features/uk2.htm#UK%20Legal%20System\">A Guide To the UK Legal System</a> <span class=\"reference-accessdate\">[2006-05-16]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=A+Guide+To+the+UK+Legal+System&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.llrx.com%2Ffeatures%2Fuk2.htm%23UK%2520Legal%2520System&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-UN-24\"><b><a href=\"#cite_ref-UN_24-0\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a href=\"http://zh.wikipedia.org/w/index.php?title=United_Nations_Economic_and_Social_Council&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"United Nations Economic and Social Council\">United Nations Economic and Social Council</a>. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.webcitation.org/5lhCIacyi\">Ninth UN Conference on the standardization of Geographical Names</a>. UN Statistics Division <span class=\"reference-accessdate\">[21 October 2008]</span> (<a rel=\"nofollow\" class=\"external text\" href=\"http://unstats.un.org/unsd/geoinfo/9th-UNCSGN-Docs/E-CONF-98-48-Add1.pdf\">原始内容</a>存档於1 December 2009).</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Ninth+UN+Conference+on+the+standardization+of+Geographical+Names&amp;rft.atitle=&amp;rft.aulast=%5B%5BUnited+Nations+Economic+and+Social+Council%5D%5D&amp;rft.au=%5B%5BUnited+Nations+Economic+and+Social+Council%5D%5D&amp;rft.pub=UN+Statistics+Division&amp;rft_id=http%3A%2F%2Fwww.webcitation.org%2F5lhCIacyi&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-25\"><b><a href=\"#cite_ref-25\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.webcitation.org/5hYQkeu1p\">Welcome to the national site of the Government Office Network</a>. Government Offices <span class=\"reference-accessdate\">[3 July 2008]</span> (<a rel=\"nofollow\" class=\"external text\" href=\"http://www.gos.gov.uk/national/\">原始内容</a>存档於15 June 2009).</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Welcome+to+the+national+site+of+the+Government+Office+Network&amp;rft.atitle=&amp;rft.pub=Government+Offices&amp;rft_id=http%3A%2F%2Fwww.webcitation.org%2F5hYQkeu1p&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-26\"><b><a href=\"#cite_ref-26\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://web.archive.org/web/20080421023053/http://www.london.gov.uk/london-life/city-government/history.jsp\">A short history of London government</a>. Greater London Authority <span class=\"reference-accessdate\">[4 October 2008]</span> (<a rel=\"nofollow\" class=\"external text\" href=\"http://www.london.gov.uk/london-life/city-government/history.jsp\">原始内容</a>存档於21 April 2008).</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=A+short+history+of+London+government&amp;rft.atitle=&amp;rft.pub=Greater+London+Authority&amp;rft_id=http%3A%2F%2Fweb.archive.org%2Fweb%2F20080421023053%2Fhttp%3A%2F%2Fwww.london.gov.uk%2Flondon-life%2Fcity-government%2Fhistory.jsp&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-27\"><b><a href=\"#cite_ref-27\">^</a></b> <span class=\"reference-text\"><span class=\"citation news\">Sherman, Jill; Norfolk, Andrew. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.timesonline.co.uk/tol/news/uk/article503255.ece\">Prescott's dream in tatters as North East rejects assembly</a>. The Times. London. 5 November 2004 <span class=\"reference-accessdate\">[15 February 2008]</span>.\n \"The Government is now expected to tear up its twelve-year-old plan to \ncreate eight or nine regional assemblies in England to mirror devolution\n in Scotland and Wales.\"</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.atitle=Prescott%27s+dream+in+tatters+as+North+East+rejects+assembly&amp;rft.jtitle=The+Times&amp;rft.aulast=Sherman&amp;rft.aufirst=Jill&amp;rft.au=Sherman%2C%26%2332%3BJill&amp;rft.au=Norfolk%2C%26%2332%3BAndrew&amp;rft.date=5+November+2004&amp;rft.place=London&amp;rft_id=http%3A%2F%2Fwww.timesonline.co.uk%2Ftol%2Fnews%2Fuk%2Farticle503255.ece&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-28\"><b><a href=\"#cite_ref-28\">^</a></b> <span class=\"reference-text\"><span class=\"citation web\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.lga.gov.uk/lga/aio/39780\">Local Authority Elections</a>. Local Government Association <span class=\"reference-accessdate\">[3 October 2008]</span>.</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Local+Authority+Elections&amp;rft.atitle=&amp;rft.pub=Local+Government+Association&amp;rft_id=http%3A%2F%2Fwww.lga.gov.uk%2Flga%2Faio%2F39780&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-29\"><b><a href=\"#cite_ref-29\">^</a></b> <span class=\"reference-text\"><a rel=\"nofollow\" class=\"external free\" href=\"http://www.ons.gov.uk/ons/rel/census/census-2001-key-statistics/urban-areas-in-england-and-wales/index.html\">http://www.ons.gov.uk/ons/rel/census/census-2001-key-statistics/urban-areas-in-england-and-wales/index.html</a></span></li>\n<li id=\"cite_note-30\"><b><a href=\"#cite_ref-30\">^</a></b> <span class=\"reference-text\"><a rel=\"nofollow\" class=\"external text\" href=\"http://www.gro-scotland.gov.uk/files/setloc-ks01.xls\">KS01 Usual resident population, Key Statistics for Settlements and Localities Scotland</a> General Register Office for Scotland</span></li>\n<li id=\"cite_note-31\"><b><a href=\"#cite_ref-31\">^</a></b> <span class=\"reference-text\"><a rel=\"nofollow\" class=\"external free\" href=\"http://www.nisranew.nisra.gov.uk/census/pdf/ks_sett_tables.pdf\">http://www.nisranew.nisra.gov.uk/census/pdf/ks_sett_tables.pdf</a></span></li>\n<li id=\"cite_note-32\"><b><a href=\"#cite_ref-32\">^</a></b> <span class=\"reference-text\"><span style=\"font-family: sans-serif; cursor: default; color:#555; font-size: 0.8em; bottom: 0.1em; font-weight: bold;\" title=\"连接到英文网页\">（英文）</span><a rel=\"nofollow\" class=\"external text\" href=\"https://www.cia.gov/library/publications/the-world-factbook/geos/uk.html\">CIA - The World Factbook -- United Kingdom (2001 census)</a></span></li>\n<li id=\"cite_note-mt20120313-33\">^ <a href=\"#cite_ref-mt20120313_33-0\"><sup><b>34.0</b></sup></a> <a href=\"#cite_ref-mt20120313_33-1\"><sup><b>34.1</b></sup></a> <span class=\"reference-text\"><span style=\"font-family: sans-serif; cursor: default; color:#555; font-size: 0.8em; bottom: 0.1em; font-weight: bold;\" title=\"连接到正体中文网页\">（正体中文）</span><span class=\"citation news\">觀琰綜合外電報導. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.merit-times.com.tw/NewsPage.aspx?unid=255374\">“英女王登基60年 公開支持國教”</a>. <a href=\"http://zh.wikipedia.org/wiki/%E4%BA%BA%E9%96%93%E7%A6%8F%E5%A0%B1\" title=\"人間福報\">人間福報</a>. 2012-03-13: (第9版) <span class=\"reference-accessdate\">[2012-3-13]</span>. \"“逾七成信奉基督教，其他宗教包括佛教、印度教、猶太教、伊斯蘭教等\"</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=%E2%80%9C%E8%8B%B1%E5%A5%B3%E7%8E%8B%E7%99%BB%E5%9F%BA60%E5%B9%B4+%E5%85%AC%E9%96%8B%E6%94%AF%E6%8C%81%E5%9C%8B%E6%95%99%E2%80%9D&amp;rft.atitle=&amp;rft.aulast=%E8%A7%80%E7%90%B0%E7%B6%9C%E5%90%88%E5%A4%96%E9%9B%BB%E5%A0%B1%E5%B0%8E&amp;rft.au=%E8%A7%80%E7%90%B0%E7%B6%9C%E5%90%88%E5%A4%96%E9%9B%BB%E5%A0%B1%E5%B0%8E&amp;rft.date=2012-03-13&amp;rft.pages=%28%E7%AC%AC9%E7%89%88%29&amp;rft.pub=%5B%5B%E4%BA%BA%E9%96%93%E7%A6%8F%E5%A0%B1%5D%5D&amp;rft_id=http%3A%2F%2Fwww.merit-times.com.tw%2FNewsPage.aspx%3Funid%3D255374&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n<li id=\"cite_note-34\"><b><a href=\"#cite_ref-34\">^</a></b> <span class=\"reference-text\"><span style=\"font-family: sans-serif; cursor: default; color:#555; font-size: 0.8em; bottom: 0.1em; font-weight: bold;\" title=\"连接到中文网页\">（中文）</span><span class=\"citation news\">陳永輝編譯. <a rel=\"nofollow\" class=\"external text\" href=\"http://www.krt.com.hk/modules/news/article.php?storyid=4534\">“英國調查顯示四成青少年沒有信仰”</a>. <a href=\"http://en.wikipedia.org/wiki/The_Christian_Post\" class=\"extiw\" title=\"en:The Christian Post\">en:The Christian Post</a>. 國度復興報. 2007-09-14 <span class=\"reference-accessdate\">[2007-10-05]</span>. \"是否表示當人年紀越老，便越找到或變得更有信仰？……由<a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%9C%96%E6%9B%B8%E9%A4%A8\" title=\"大英圖書館\" class=\"mw-redirect\">大英圖書館</a>委託英國極負盛名的Ipsos MORI專業研究公司調查……在沒有信仰的受訪者中，有32％說他們曾經是基督徒\"</span><span class=\"Z3988\" title=\"ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.atitle=%E2%80%9C%E8%8B%B1%E5%9C%8B%E8%AA%BF%E6%9F%A5%E9%A1%AF%E7%A4%BA%E5%9B%9B%E6%88%90%E9%9D%92%E5%B0%91%E5%B9%B4%E6%B2%92%E6%9C%89%E4%BF%A1%E4%BB%B0%E2%80%9D&amp;rft.jtitle=%5B%5B%3Aen%3AThe+Christian+Post%5D%5D&amp;rft.aulast=%E9%99%B3%E6%B0%B8%E8%BC%9D%E7%B7%A8%E8%AD%AF&amp;rft.au=%E9%99%B3%E6%B0%B8%E8%BC%9D%E7%B7%A8%E8%AD%AF&amp;rft.date=2007-09-14&amp;rft.pub=%E5%9C%8B%E5%BA%A6%E5%BE%A9%E8%88%88%E5%A0%B1&amp;rft_id=http%3A%2F%2Fwww.krt.com.hk%2Fmodules%2Fnews%2Farticle.php%3Fstoryid%3D4534&amp;rfr_id=info:sid/zh.wikipedia.org:%E8%8B%B1%E5%9B%BD\"><span style=\"display: none;\">&nbsp;</span></span></span></li>\n</ol>\n</div>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=36\" title=\"编辑段落：外部链接\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.A4.96.E9.83.A8.E9.93.BE.E6.8E.A5\">外部链接</span></h2>\n<div class=\"infobox sisterproject plainlinks\">\n<div class=\"floatleft\"><a href=\"http://zh.wikipedia.org/wiki/File:Commons-logo.svg\" class=\"image\" title=\"维基媒体共享资源标志\"><img alt=\"维基媒体共享资源标志\" src=\"England%28Chinese%29_files/30px-Commons-logo.png\" height=\"40\" width=\"30\"></a></div>\n<div style=\"margin-left:40px;\">相關的<a href=\"http://zh.wikipedia.org/wiki/%E7%BB%B4%E5%9F%BA%E5%85%B1%E4%BA%AB%E8%B5%84%E6%BA%90\" title=\"维基共享资源\">维基共享资源</a>：\n<dl>\n<dd><a class=\"external text\" href=\"http://commons.wikimedia.org/wiki/Category:United_Kingdom\"><b>英国</b></a></dd>\n</dl>\n</div>\n</div>\n<ul>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.worldatlas.com/webimage/countrys/europe/uk.htm\">英国版图和国家介绍</a></li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.visitbritain.com/\">英國旅遊局</a></li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.britishcouncil.org/\">英國文化協會</a> （留學英國）</li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.ukba.homeoffice.gov.uk/\">英國移民署</a>（簽證相關規定）</li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.yingguo123.com/\">英国生活百科</a></li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.vfs-uk-tw.com/chinese/index.aspx\">英國簽證申請中心</a>（提供予台灣的便民資訊）</li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"http://www.vfs-uk-cn.com/chinese/index1.aspx\">英国签证申请中心</a>（提供予中国大陆的便民资讯）</li>\n<li><a rel=\"nofollow\" class=\"external text\" href=\"https://www.uktradeinvest.gov.uk/\">英國貿易暨投資署</a> （英國貿易投資）</li>\n</ul>\n<h2><span class=\"editsection\">[<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit&amp;section=37\" title=\"编辑段落：参见\">编辑</a>]</span> <span class=\"mw-headline\" id=\".E5.8F.82.E8.A7.81\">参见</span></h2>\n<div style=\"position: relative; float: right; clear: right; margin: 0 0 1em 1em; border: solid #aaa 1px; background: #f9f9f9; padding: 0.5em; font-size: 90%;\" class=\"noprint\"><span style=\"white-space:nowrap;\"><a href=\"http://zh.wikipedia.org/wiki/File:Flag_of_the_United_Kingdom.svg\" class=\"image\" title=\"英國主題\"><img alt=\"英國主題\" src=\"England%28Chinese%29_files/36px-Flag_of_the_United_Kingdom.png\" height=\"18\" width=\"36\"></a> <b><a href=\"http://zh.wikipedia.org/wiki/Portal:%E8%8B%B1%E5%9B%BD\" title=\"Portal:英国\">英國主題首頁</a></b></span></div>\n<ul>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E8%8B%B1%E5%B8%9D%E5%9B%BD\" title=\"大英帝国\">大英帝国</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"英联邦\">英联邦</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%9B%BD%E4%BC%9A\" title=\"英国国会\">国会</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E8%AE%AE%E4%BC%9A\" title=\"英国议会\" class=\"mw-redirect\">议会</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8\" title=\"英国首相\">英国首相</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E5%90%9B%E4%B8%BB\" title=\"英国君主\">英国君主</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E9%A6%96%E7%9B%B8%E5%88%97%E8%A1%A8\" title=\"英国首相列表\">英国首相列表</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E4%BA%BA%E5%88%97%E8%A1%A8\" title=\"英国人列表\">英国人列表</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E8%8D%A3%E8%AA%89%E5%88%B6%E5%BA%A6\" title=\"英国荣誉制度\" class=\"mw-redirect\">英国荣誉制度</a></li>\n<li><a href=\"http://zh.wikipedia.org/wiki/%E8%98%87%E6%A0%BC%E8%98%AD%E7%8D%A8%E7%AB%8B%E9%81%8B%E5%8B%95\" title=\"蘇格蘭獨立運動\">蘇格蘭獨立運動</a></li>\n</ul>\n<p><br style=\"clear: both;\"></p>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span><span style=\"float:left;width:8em;font-size:80%;margin-right:0.5em;\">&nbsp;</span>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E6%B4%B2\" title=\"欧洲\">欧洲</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%AC%A7\" title=\"西欧\">西欧</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%97%B6\" title=\"比利时\">比利时</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"爱尔兰共和国\">爱尔兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A2%E6%A3%AE%E5%A0%A1\" title=\"卢森堡\">卢森堡</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E7%BA%B3%E5%93%A5\" title=\"摩纳哥\">摩纳哥</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8D%B7%E5%85%B0\" title=\"荷兰\">荷兰</a> ·</span> <span style=\"white-space:nowrap\"><strong class=\"selflink\">英国</strong></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%AC%A7\" title=\"北欧\" class=\"mw-redirect\">北欧</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%B9%E9%BA%A6\" title=\"丹麦\">丹麦</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8A%AC%E5%85%B0\" title=\"芬兰\">芬兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%86%B0%E5%B2%9B\" title=\"冰岛\">冰岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%8C%AA%E5%A8%81\" title=\"挪威\">挪威</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%91%9E%E5%85%B8\" title=\"瑞典\">瑞典</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%AC%A7\" title=\"中欧\">中欧</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A5%E5%9C%B0%E5%88%A9\" title=\"奥地利\">奥地利</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%8D%B7%E5%85%8B\" title=\"捷克\">捷克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\">德国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9\" title=\"匈牙利\">匈牙利</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%88%97%E6%94%AF%E6%95%A6%E6%96%AF%E7%99%BB\" title=\"列支敦斯登\">列支敦斯登</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E5%85%B0\" title=\"波兰\">波兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E4%BC%90%E5%85%8B\" title=\"斯洛伐克\">斯洛伐克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%91%9E%E5%A3%AB\" title=\"瑞士\">瑞士</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%9C%E6%AC%A7\" title=\"东欧\">东欧</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%84%E7%BD%97%E6%96%AF\" title=\"俄罗斯\">俄罗斯</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%99%BD%E4%BF%84%E7%BD%97%E6%96%AF\" title=\"白俄罗斯\">白俄罗斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E6%B2%99%E5%B0%BC%E4%BA%9A\" title=\"爱沙尼亚\">爱沙尼亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%8B%89%E8%84%AB%E7%B6%AD%E4%BA%9E\" title=\"拉脫維亞\">拉脫維亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%AB%8B%E9%99%B6%E5%AE%9B\" title=\"立陶宛\">立陶宛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E5%B0%94%E5%A4%9A%E7%93%A6\" title=\"摩尔多瓦\">摩尔多瓦</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B9%8C%E5%85%8B%E5%85%B0\" title=\"乌克兰\">乌克兰</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E6%AC%A7\" title=\"南欧\">南欧</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E5%B0%94%E5%B7%B4%E5%B0%BC%E4%BA%9A\" title=\"阿尔巴尼亚\">阿尔巴尼亚</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E9%81%93%E5%B0%94\" title=\"安道尔\">安道尔</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E6%96%AF%E5%B0%BC%E4%BA%9A%E5%92%8C%E9%BB%91%E5%A1%9E%E5%93%A5%E7%BB%B4%E9%82%A3\" title=\"波斯尼亚和黑塞哥维那\">波斯尼亚和黑塞哥维那</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%9D%E5%8A%A0%E5%88%A9%E4%BA%9A\" title=\"保加利亚\">保加利亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%BD%97%E5%9C%B0%E4%BA%9A\" title=\"克罗地亚\">克罗地亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%B3%BD%E6%99%AE%E5%8B%92%E6%96%AF\" title=\"賽普勒斯\">賽普勒斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%8C%E8%85%8A\" title=\"希腊\">希腊</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%84%8F%E5%A4%A7%E5%88%A9\" title=\"意大利\">意大利</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%A7%91%E7%B4%A2%E6%B2%83\" title=\"科索沃\">科索沃</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%85%B6%E9%A0%93%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"馬其頓共和國\">馬其頓</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E8%80%B3%E4%BB%96\" title=\"马耳他\">马耳他</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%92%99%E7%89%B9%E5%85%A7%E5%93%A5%E7%BE%85\" title=\"蒙特內哥羅\">黑山</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%91%A1%E8%90%84%E7%89%99\" title=\"葡萄牙\">葡萄牙</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%85%E9%A6%AC%E5%B0%BC%E4%BA%9E\" title=\"羅馬尼亞\">羅馬尼亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E9%A9%AC%E5%8A%9B%E8%AF%BA\" title=\"圣马力诺\">圣马力诺</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E5%B0%94%E7%BB%B4%E4%BA%9A\" title=\"塞尔维亚\">塞尔维亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E6%96%87%E5%B0%BC%E4%BA%9A\" title=\"斯洛文尼亚\">斯洛文尼亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E7%8F%AD%E7%89%99\" title=\"西班牙\">西班牙</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%A2%B5%E8%92%82%E5%86%88\" title=\"梵蒂冈\">梵蒂冈</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">歐亞國家跨洲地區</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%9F%E8%80%B3%E5%85%B6\" title=\"土耳其\">土耳其</a><a href=\"http://zh.wikipedia.org/wiki/%E8%89%B2%E9%9B%B7%E6%96%AF\" title=\"色雷斯\">色雷斯</a>地區 · <span style=\"white-space:nowrap\">俄羅斯<a href=\"http://zh.wikipedia.org/wiki/%E4%B9%8C%E6%8B%89%E5%B0%94%E8%81%94%E9%82%A6%E7%AE%A1%E5%8C%BA\" title=\"乌拉尔联邦管区\">烏拉爾</a>、<a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E4%BC%AF%E5%88%A9%E4%BA%9E%E8%81%AF%E9%82%A6%E7%AE%A1%E5%8D%80\" title=\"西伯利亞聯邦管區\" class=\"mw-redirect\">西伯利亞</a>、<a href=\"http://zh.wikipedia.org/wiki/%E9%81%A0%E6%9D%B1%E8%81%AF%E9%82%A6%E7%AE%A1%E5%8D%80\" title=\"遠東聯邦管區\">遠東聯邦管區</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A2%83%E5%A4%96%E9%A0%98%E5%9C%9F\" title=\"境外領土\">境外領土</a>與<br>\n其他特殊<a href=\"http://zh.wikipedia.org/wiki/%E6%94%BF%E5%8D%80\" title=\"政區\">政區</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E7%BD%97%E7%BE%A4%E5%B2%9B\" title=\"法罗群岛\">法罗群岛</a>（丹麥） · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%9B%B4%E5%B8%83%E7%BD%97%E9%99%80\" title=\"直布罗陀\">直布罗陀</a>（英國） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%A0%B9%E8%A5%BF%E5%B2%9B\" title=\"根西岛\">根西岛</a>（英國） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%90%8C%E5%B3%B6\" title=\"萌島\" class=\"mw-redirect\">马恩岛</a>（英國） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%8F%9A%E9%A6%AC%E5%BB%B6%E5%B3%B6\" title=\"揚馬延島\">揚馬延島</a>（挪威） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%BE%A4%E8%A5%BF%E5%B3%B6\" title=\"澤西島\">澤西島</a>（英國） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E7%93%A6%E5%B0%94%E5%B7%B4%E7%BE%A4%E5%B2%9B\" title=\"斯瓦尔巴群岛\">斯瓦尔巴群岛</a>（挪威）</span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td class=\"navbox-abovebelow\" style=\"\" colspan=\"2\">\n<div><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%96%E7%95%8C%E5%9C%B0%E7%90%86%E7%B4%A2%E5%BC%95\" title=\"世界地理索引\">世界地理索引</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%9D%9E%E6%B4%B2\" title=\"非洲\">非洲</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E6%B4%B2\" title=\"美洲\">美洲</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E6%9E%81%E6%B4%B2\" title=\"南极洲\">南极洲</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BA%9E%E6%B4%B2\" title=\"亞洲\" class=\"mw-redirect\">亞洲</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E6%B4%8B%E6%B4%B2\" title=\"大洋洲\">大洋洲</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%90%84%E5%9B%BD%E9%A6%96%E9%83%BD%E5%88%97%E8%A1%A8\" title=\"各国首都列表\">各国首都列表</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:%E4%B8%8D%E5%88%97%E9%A1%9B%E7%BE%A4%E5%B3%B6\" title=\"Template:不列顛群島\" class=\"mw-redirect\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:%E4%B8%8D%E5%88%97%E9%A2%A0%E7%BE%A4%E5%B2%9B&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:不列颠群岛\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:%E4%B8%8D%E5%88%97%E9%A2%A0%E7%BE%A4%E5%B2%9B&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A2%A0%E7%BE%A4%E5%B2%9B\" title=\"不列颠群岛\" class=\"mw-redirect\">不列顛群島</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td class=\"navbox-abovebelow\" style=\"\" colspan=\"2\">\n<div><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A1%9B%E7%BE%A4%E5%B3%B6_%28%E7%94%A8%E8%AA%9E%29\" title=\"不列顛群島 (用語)\">用语</a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A1%9B_%28%E5%90%8D%E7%A8%B1%29\" title=\"不列顛 (名稱)\">名称</a></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.35em 1em; line-height: 1.1em;\">政治</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% transparent;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">主权国家</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"爱尔兰共和国\">爱尔兰共和国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0%E5%92%8C%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0%E8%81%94%E5%90%88%E7%8E%8B%E5%9B%BD\" title=\"大不列颠和北爱尔兰联合王国\" class=\"mw-redirect\">大不列颠和北爱尔兰联合王国</a> （<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0\" title=\"英格兰\">英格兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0\" title=\"北爱尔兰\">北爱尔兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0\" title=\"苏格兰\" class=\"mw-redirect\">苏格兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB\" title=\"威尔士\" class=\"mw-redirect\">威尔士</a>）</span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">英国皇室属地</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E6%A0%B9%E8%A5%BF%E5%B2%9B\" title=\"根西岛\">根西岛</a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/wiki/%E6%B3%BD%E8%A5%BF%E5%B2%9B\" title=\"泽西岛\" class=\"mw-redirect\">泽西岛</a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%B3%B6\" title=\"曼島\">曼岛</a></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.35em 1em; line-height: 1.1em;\">地理</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% transparent;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">岛屿</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B5%B7%E5%B3%A1%E7%BE%A4%E5%B2%9B\" title=\"海峡群岛\">海峡群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0%E5%B2%9B\" title=\"大不列颠岛\" class=\"mw-redirect\">大不列颠岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%B5%AB%E5%B8%83%E9%87%8C%E5%BA%95%E7%BE%A4%E5%B2%9B\" title=\"赫布里底群岛\">赫布里底群岛</a> （<a href=\"http://zh.wikipedia.org/wiki/%E5%86%85%E8%B5%AB%E5%B8%83%E9%87%8C%E5%BA%95%E7%BE%A4%E5%B2%9B\" title=\"内赫布里底群岛\">内</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%96%E8%B5%AB%E5%B8%83%E9%87%8C%E5%BA%95%E7%BE%A4%E5%B3%B6\" title=\"外赫布里底群島\" class=\"mw-redirect\">外</a>） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%B2%9B\" title=\"爱尔兰岛\">爱尔兰岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%B3%B6\" title=\"曼島\">曼岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%94%A1%E5%88%A9%E7%BE%A4%E5%B2%9B\" title=\"锡利群岛\">锡利群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8C%97%E6%96%B9%E7%BE%A4%E5%B2%9B&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"北方群岛\">北方群岛</a> （<a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A5%E5%85%8B%E5%B0%BC%E7%BE%A4%E5%B2%9B\" title=\"奥克尼群岛\">奥克尼群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%AE%BE%E5%BE%97%E5%85%B0%E7%BE%A4%E5%B2%9B\" title=\"设得兰群岛\" class=\"mw-redirect\">设得兰群岛</a>）</span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">河流</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E6%96%87%E6%B2%B3\" title=\"塞文河\">塞文河</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%B0%E6%99%A4%E5%A3%AB%E6%B2%B3\" title=\"泰晤士河\">泰晤士河</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E7%83%8F%E8%8C%B2%E6%B2%B3\" title=\"大烏茲河\">大乌兹河</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%B0%E6%B2%B3\" title=\"泰河\">泰河</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.35em 1em; line-height: 1.1em;\">历史</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% transparent;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">历史</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A2%A0%E7%BE%A4%E5%B2%9B%E5%8E%86%E5%8F%B2\" title=\"不列颠群岛历史\" class=\"mw-redirect\">不列颠群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%8E%86%E5%8F%B2\" title=\"爱尔兰历史\" class=\"mw-redirect\">爱尔兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E7%8E%8B%E5%9B%BD%E5%8E%86%E5%8F%B2\" title=\"联合王国历史\" class=\"mw-redirect\">联合王国</a> （<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E5%8E%86%E5%8F%B2\" title=\"英格兰历史\" class=\"mw-redirect\">英格兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0%E5%8E%86%E5%8F%B2&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"北爱尔兰历史\">北爱尔兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E5%8E%86%E5%8F%B2\" title=\"苏格兰历史\">苏格兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A8%81%E5%B0%94%E5%A3%AB%E5%8E%86%E5%8F%B2&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"威尔士历史\">威尔士</a>）</span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">历史上的国家</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E8%87%AA%E7%94%B1%E9%82%A6\" title=\"爱尔兰自由邦\">爱尔兰自由邦</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E7%8E%8B%E5%9B%BD\" title=\"英格兰王国\">英格兰王国</a> （<a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB%E5%85%AC%E5%9B%BD\" title=\"威尔士公国\" class=\"mw-redirect\">威尔士公国</a>） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0%E7%8E%8B%E5%9B%BD\" title=\"大不列颠王国\" class=\"mw-redirect\">大不列颠王国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E7%88%BE%E8%98%AD%E7%8E%8B%E5%9C%8B\" title=\"愛爾蘭王國\">爱尔兰王国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E7%8E%8B%E5%9B%BD\" title=\"苏格兰王国\">苏格兰王国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%A7%E4%B8%8D%E5%88%97%E9%A2%A0%E5%92%8C%E7%88%B1%E5%B0%94%E5%85%B0%E8%81%94%E5%90%88%E7%8E%8B%E5%9B%BD\" title=\"大不列颠和爱尔兰联合王国\" class=\"mw-redirect\">大不列颠和爱尔兰联合王国</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.35em 1em; line-height: 1.1em;\">社会</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% transparent;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">现代语言</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%97%A5%E8%80%B3%E6%9B%BC%E8%AF%AD%E6%97%8F\" title=\"日耳曼语族\">日耳曼语族</a>：<a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%AF%AD\" title=\"英语\">英语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E8%AF%AD\" title=\"苏格兰语\" class=\"mw-redirect\">苏格兰语</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%87%AF%E5%B0%94%E7%89%B9%E8%AF%AD%E6%97%8F\" title=\"凯尔特语族\">凯尔特语族</a>：<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E8%AF%AD\" title=\"爱尔兰语\" class=\"mw-redirect\">爱尔兰语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E6%A0%BC%E5%85%B0%E7%9B%96%E5%B0%94%E8%AF%AD\" title=\"苏格兰盖尔语\">苏格兰盖尔语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%9B%BC%E5%B2%9B%E8%AF%AD\" title=\"曼岛语\" class=\"mw-redirect\">曼岛语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E5%B0%94%E5%A3%AB%E8%AF%AD\" title=\"威尔士语\">威尔士语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BA%B7%E6%B2%83%E5%B0%94%E8%AF%AD\" title=\"康沃尔语\" class=\"mw-redirect\">康沃尔语</a><br>\n　<a href=\"http://zh.wikipedia.org/wiki/%E7%BD%97%E6%9B%BC%E8%AF%AD%E6%97%8F\" title=\"罗曼语族\">罗曼语族</a>：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%A5%A5%E5%B0%94%E5%BE%B7%E5%B0%BC%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"奥尔德尼语\">奥尔德尼语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E8%AF%AD\" title=\"法语\">法语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E6%A0%B9%E8%A5%BF%E6%B3%95%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"根西法语\">根西法语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E6%B3%BD%E8%A5%BF%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"泽西语\">泽西语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%90%A8%E5%85%8B%E6%B3%95%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"萨克法语\">萨克法语</a><br>\n　其　　他：<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD%E6%89%8B%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"英国手语\">英国手语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%88%B1%E5%B0%94%E5%85%B0%E6%89%8B%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"爱尔兰手语\">爱尔兰手语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E5%8C%97%E7%88%B1%E5%B0%94%E5%85%B0%E6%89%8B%E8%AF%AD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"北爱尔兰手语\">北爱尔兰手语</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%9B%AA%E5%B0%94%E5%A1%94%E8%AF%AD\" title=\"雪尔塔语\" class=\"mw-redirect\">雪尔塔语</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"padding: 0.2em 0pt; line-height: 1.1em; width: 11em; font-weight: normal;\">\n<div style=\"padding:0em 0.75em;\">民族</div>\n</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; padding: 0.4em 0pt; line-height: 1.4em; width: auto;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%88%97%E9%A1%9B%E4%BA%BA\" title=\"不列顛人\">不列颠人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BA%B7%E6%B2%83%E5%B0%94%E4%BA%BA\" title=\"康沃尔人\">康沃尔人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E6%A0%BC%E5%85%B0%E4%BA%BA\" title=\"英格兰人\" class=\"mw-redirect\">英格兰人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%90%89%E5%8D%9C%E8%B5%9B%E4%BA%BA\" title=\"吉卜赛人\" class=\"mw-redirect\">英国吉卜赛人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E4%BA%BA\" title=\"爱尔兰人\">爱尔兰人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%88%B1%E5%B0%94%E5%85%B0%E7%A7%BB%E6%B0%91&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"爱尔兰移民\">爱尔兰移民</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E6%9B%BC%E5%B2%9B%E4%BA%BA&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"曼岛人\">曼岛人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%98%87%E6%A0%BC%E8%98%AD%E4%BA%BA\" title=\"蘇格蘭人\">苏格兰人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E9%98%BF%E5%B0%94%E6%96%AF%E7%89%B9-%E8%8B%8F%E6%A0%BC%E5%85%B0%E4%BA%BA&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"阿尔斯特-苏格兰人\">阿尔斯特-苏格兰人</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A8%81%E7%88%BE%E5%A3%AB%E4%BA%BA\" title=\"威爾士人\" class=\"mw-redirect\">威尔士人</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible collapsed navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span><span style=\"float:left;width:8em;font-size:80%;margin-right:0.5em;\">&nbsp;</span>\n<div class=\"\" style=\"font-size:110%;\">國際組織成員</div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td colspan=\"2\" style=\"width: 100%; padding: 0px; font-size: 111%;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\">\n<div>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:UNSC\" title=\"Template:UNSC\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:UNSC&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:UNSC\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:UNSC&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Nations.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD\" title=\"联合国\">联合国</a><a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E4%BC%9A\" title=\"联合国安全理事会\">安全理事会</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E4%BC%9A%E5%B8%B8%E4%BB%BB%E7%90%86%E4%BA%8B%E5%9B%BD\" title=\"联合国安全理事会常任理事国\">常任理事国</a><br>\n（<a href=\"http://zh.wikipedia.org/wiki/%E8%81%AF%E5%90%88%E5%9C%8B%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E6%9C%83%E5%90%A6%E6%B1%BA%E6%AC%8A\" title=\"聯合國安全理事會否決權\">否決權</a>）</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td colspan=\"2\" style=\"width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks collapsible collapsed navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span><span style=\"float:left;width:8em;font-size:80%;margin-right:0.5em;\">&nbsp;</span>\n<div class=\"\" style=\"font-size:110%;\">1945－1991</div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td colspan=\"2\" style=\"width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td class=\"navbox-abovebelow\" style=\"font-size: 90%;\" colspan=\"2\">\n<div><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD\" title=\"英国\"><img alt=\"英国\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9B%BD\" title=\"美国\"><img alt=\"美国\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_States.png\" class=\"thumbborder\" height=\"12\" width=\"22\"></a></span><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E8%81%94\" title=\"苏联\"><img alt=\"苏联\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Soviet_Union.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E9%9B%85%E5%B0%94%E5%A1%94%E4%BC%9A%E8%AE%AE\" title=\"雅尔塔会议\">雅尔塔会议</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B\" title=\"中華民國\"><img alt=\"中華民國\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Republic_of_China.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span>→<span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"中华人民共和国\"><img alt=\"中华人民共和国\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Peoples_Republic_of_China.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E5%A4%A7%E4%BC%9A2758%E5%8F%B7%E5%86%B3%E8%AE%AE\" title=\"联合国大会2758号决议\" class=\"mw-redirect\">联合国大会2758号决议</a>（<a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%9C%8B%E8%88%87%E8%81%AF%E5%90%88%E5%9C%8B%E9%97%9C%E4%BF%82\" title=\"中國與聯合國關係\">中國與聯合國關係</a>）</span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E8%81%94\" title=\"苏联\"><img alt=\"苏联\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Soviet_Union.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span>→<span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%84%E7%BD%97%E6%96%AF\" title=\"俄罗斯\"><img alt=\"俄罗斯\" src=\"England%28Chinese%29_files/22px-Flag_of_Russia.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E8%81%94%E8%A7%A3%E4%BD%93\" title=\"苏联解体\">苏联解体</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E8%A5%BF\" title=\"巴西\"><img alt=\"巴西\" src=\"England%28Chinese%29_files/22px-Flag_of_Brazil.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\"><img alt=\"德国\" src=\"England%28Chinese%29_files/22px-Flag_of_Germany.png\" class=\"thumbborder\" height=\"13\" width=\"22\"></a></span><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6\" title=\"印度\"><img alt=\"印度\" src=\"England%28Chinese%29_files/22px-Flag_of_India.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC\" title=\"日本\"><img alt=\"日本\" src=\"England%28Chinese%29_files/22px-Flag_of_Japan.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E5%9B%9B%E5%9C%8B%E8%81%AF%E7%9B%9F\" title=\"四國聯盟\">四国联盟</a>（<a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E6%94%B9%E9%9D%A9\" title=\"联合国改革\">联合国改革</a>）</span></div>\n</td>\n</tr>\n</tbody></table>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\">1945－1971</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B\" title=\"中華民國\"><img alt=\"中華民國\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Republic_of_China.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B\" title=\"中華民國\">中華民國</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_France.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><strong class=\"selflink\">英國</strong></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Soviet_Union.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E8%81%94\" title=\"苏联\">蘇聯</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_States.png\" class=\"thumbborder\" height=\"12\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9B%BD\" title=\"美国\" class=\"mw-redirect\">美国</a></span></div>\n</td>\n</tr>\n</tbody></table>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\">1971－1991</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Peoples_Republic_of_China.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"中华人民共和国\">中华人民共和国</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_France.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><strong class=\"selflink\">英國</strong></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Soviet_Union.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%8F%E8%81%94\" title=\"苏联\">蘇聯</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_States.png\" class=\"thumbborder\" height=\"12\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9B%BD\" title=\"美国\" class=\"mw-redirect\">美国</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\">1991－&nbsp; <span class=\"Unicode\"> </span>&nbsp;</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Peoples_Republic_of_China.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"中华人民共和国\">中华人民共和国</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_France.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><strong class=\"selflink\">英國</strong></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Russia.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%84%E7%BD%97%E6%96%AF\" title=\"俄罗斯\">俄罗斯</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_States.png\" class=\"thumbborder\" height=\"12\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9B%BD\" title=\"美国\" class=\"mw-redirect\">美国</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E4%BC%9A#.E9.9D.9E.E5.B8.B8.E4.BB.BB.E7.90.86.E4.BA.8B.E5.9B.BD\" title=\"联合国安全理事会\">非常任理事国</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td colspan=\"2\" style=\"width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks collapsible collapsed navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span><span style=\"float:left;width:8em;font-size:80%;margin-right:0.5em;\">&nbsp;</span>\n<div class=\"\" style=\"font-size:110%;\">1946－2010</div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td colspan=\"2\" style=\"width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">1946－1946</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Egypt_1922.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%9F%83%E5%8F%8A\" title=\"埃及\">埃及</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Mexico.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%A2%A8%E8%A5%BF%E5%93%A5\" title=\"墨西哥\">墨西哥</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Netherlands.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%8D%B7%E5%85%B0\" title=\"荷兰\">荷兰</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">1946－1947</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\"><img alt=\"澳大利亚\" src=\"England%28Chinese%29_files/22px-Flag_of_Australia.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\">澳大利亚</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Brazil.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E8%A5%BF\" title=\"巴西\">巴西</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Poland.png\" class=\"thumbborder\" height=\"14\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E5%85%B0\" title=\"波兰\">波兰</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">1947－1948</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Belgium_civil.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%97%B6\" title=\"比利时\">比利时</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Colombia.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%93%A5%E4%BC%A6%E6%AF%94%E4%BA%9A\" title=\"哥伦比亚\">哥伦比亚</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Syria-flag_1932-58_1961-63.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8F%99%E5%88%A9%E4%BA%9A\" title=\"叙利亚\">叙利亚</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<td colspan=\"2\" style=\"width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\">　<a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E4%BC%9A#.E9.9D.9E.E5.B8.B8.E4.BB.BB.E7.90.86.E4.BA.8B.E5.9B.BD\" title=\"联合国安全理事会\">……………</a></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">2007－2008</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Belgium_civil.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%97%B6\" title=\"比利时\">比利时</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Italy.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%84%8F%E5%A4%A7%E5%88%A9\" title=\"意大利\">意大利</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_South_Africa.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E9%9D%9E\" title=\"南非\">南非</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Indonesia.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6%E5%B0%BC%E8%A5%BF%E4%BA%9A\" title=\"印度尼西亚\">印尼</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Panama.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E6%8B%BF%E9%A9%AC\" title=\"巴拿马\">巴拿马</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">2008－2009</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E5%9F%BA%E7%BA%B3%E6%B3%95%E7%B4%A2\" title=\"布基纳法索\"><img alt=\"布基纳法索\" src=\"England%28Chinese%29_files/22px-Flag_of_Burkina_Faso.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E5%90%89%E7%B4%8D%E6%B3%95%E7%B4%A2\" title=\"布吉納法索\">布基拉法索</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Costa_Rica.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%93%A5%E6%96%AF%E8%BE%BE%E9%BB%8E%E5%8A%A0\" title=\"哥斯达黎加\">哥斯达黎加</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Croatia.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%BD%97%E5%9C%B0%E4%BA%9A\" title=\"克罗地亚\">克罗地亚</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Libya.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%88%A9%E6%AF%94%E4%BA%9A\" title=\"利比亚\">利比亚</a></span>　<span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/File:Flag_of_Vietnam.svg\" class=\"image\" title=\"越南\"><img alt=\"越南\" src=\"England%28Chinese%29_files/22px-Flag_of_Vietnam.png\" height=\"15\" width=\"22\"></a> <a href=\"http://zh.wikipedia.org/wiki/%E8%B6%8A%E5%8D%97\" title=\"越南\">越南</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">2009－2010</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Japan.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC\" title=\"日本\">日本</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Turkey.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%9F%E8%80%B3%E5%85%B6\" title=\"土耳其\">土耳其</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Austria.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A5%E5%9C%B0%E5%88%A9\" title=\"奥地利\">奥地利</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Mexico.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%A2%A8%E8%A5%BF%E5%93%A5\" title=\"墨西哥\">墨西哥</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Uganda.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%B9%8C%E5%B9%B2%E8%BE%BE\" title=\"乌干达\">乌干达</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"font-weight: normal; text-align: left;\">2010－2011</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Lebanon.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E9%BB%8E%E5%B7%B4%E5%AB%A9\" title=\"黎巴嫩\">黎巴嫩</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Nigeria.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%B0%BC%E6%97%A5%E5%88%A9%E4%BA%9E\" title=\"尼日利亞\" class=\"mw-redirect\">尼日利亞</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Gabon.png\" class=\"thumbborder\" height=\"17\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E8%93%AC\" title=\"加蓬\">加蓬</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Brazil.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E8%A5%BF\" title=\"巴西\">巴西</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E6%96%AF%E5%B0%BC%E4%BA%9A%E5%92%8C%E9%BB%91%E5%A1%9E%E5%93%A5%E7%BB%B4%E9%82%A3\" title=\"波斯尼亚和黑塞哥维那\"><img alt=\"波斯尼亚和黑塞哥维那\" src=\"England%28Chinese%29_files/22px-Flag_of_Bosnia_and_Herzegovina.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E6%96%AF%E5%B0%BC%E4%BA%9A%E5%92%8C%E9%BB%91%E5%A1%9E%E5%93%A5%E7%BB%B4%E9%82%A3\" title=\"波斯尼亚和黑塞哥维那\">波黑</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\">2011－2012</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_India.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6\" title=\"印度\">印度</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_South_Africa.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E9%9D%9E\" title=\"南非\">南非</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Colombia.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%93%A5%E4%BC%A6%E6%AF%94%E4%BA%9A\" title=\"哥伦比亚\">哥伦比亚</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Germany.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\">德国</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Portugal.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%91%A1%E8%90%84%E7%89%99\" title=\"葡萄牙\">葡萄牙</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\">2012－2013</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Azerbaijan.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E5%A1%9E%E6%8B%9C%E7%96%86\" title=\"阿塞拜疆\">阿塞拜疆</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Guatemala.png\" class=\"thumbborder\" height=\"14\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B1%E5%9C%B0%E9%A9%AC%E6%8B%89\" title=\"危地马拉\">危地马拉</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Morocco.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E6%B4%9B%E5%93%A5\" title=\"摩洛哥\">摩洛哥</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Pakistan.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E5%9F%BA%E6%96%AF%E5%9D%A6\" title=\"巴基斯坦\">巴基斯坦</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Togo.png\" class=\"thumbborder\" height=\"14\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%9A%E5%93%A5\" title=\"多哥\">多哥</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td class=\"navbox-abovebelow\" style=\"\" colspan=\"2\">\n<div><a href=\"http://zh.wikipedia.org/wiki/%E8%81%94%E5%90%88%E5%9B%BD%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E4%BC%9A%E5%86%B3%E8%AE%AE\" title=\"联合国安全理事会决议\">联合国安全理事会决议</a></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span><span style=\"float:left;width:8em;font-size:80%;margin-right:0.5em;\">&nbsp;</span>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"英联邦\">英联邦</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%BB%E6%9D%83%E5%9B%BD%E5%AE%B6\" title=\"主权国家\">主权国家</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% rgb(247, 247, 247);\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E6%8F%90%E7%93%9C%E5%92%8C%E5%B7%B4%E5%B8%83%E8%BE%BE\" title=\"安提瓜和巴布达\">安提瓜和巴布达</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\">澳大利亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E5%93%88%E9%A9%AC\" title=\"巴哈马\">巴哈马</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AD%9F%E5%8A%A0%E6%8B%89%E5%9B%BD\" title=\"孟加拉国\">孟加拉国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E5%B7%B4%E5%A4%9A%E6%96%AF\" title=\"巴巴多斯\">巴巴多斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E5%88%A9%E5%85%B9\" title=\"伯利兹\">伯利兹</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E6%9C%AD%E9%82%A3\" title=\"波札那\">波札那</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%87%E8%8E%B1\" title=\"文莱\">文莱</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%96%80%E9%BA%A6%E9%9A%86\" title=\"喀麦隆\">喀麦隆</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E6%8B%BF%E5%A4%A7\" title=\"加拿大\">加拿大</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%B3%BD%E6%99%AE%E5%8B%92%E6%96%AF\" title=\"賽普勒斯\">塞浦路斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A4%9A%E7%B1%B3%E5%B0%BC%E5%85%8B\" title=\"多米尼克\">多米尼克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%86%88%E6%AF%94%E4%BA%9A\" title=\"冈比亚\">冈比亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E7%BA%B3\" title=\"加纳\">加纳</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%A0%BC%E6%9E%97%E7%BA%B3%E8%BE%BE\" title=\"格林纳达\">格林纳达</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%AD%E4%BA%9A%E9%82%A3\" title=\"圭亚那\">圭亚那</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6\" title=\"印度\">印度</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%89%99%E4%B9%B0%E5%8A%A0\" title=\"牙买加\">牙买加</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%82%AF%E5%B0%BC%E4%BA%9A\" title=\"肯尼亚\">肯尼亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9F%BA%E9%87%8C%E5%B7%B4%E6%96%AF\" title=\"基里巴斯\">基里巴斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8E%B1%E7%B4%A2%E6%89%98\" title=\"莱索托\">莱索托</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E6%8B%89%E7%BB%B4\" title=\"马拉维\">马拉维</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E6%9D%A5%E8%A5%BF%E4%BA%9A\" title=\"马来西亚\">马来西亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E5%B0%94%E4%BB%A3%E5%A4%AB\" title=\"马尔代夫\">马尔代夫</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E8%80%B3%E4%BB%96\" title=\"马耳他\">马耳他</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%9B%E9%87%8C%E6%B1%82%E6%96%AF\" title=\"毛里求斯\">毛里求斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8E%AB%E6%A1%91%E6%AF%94%E5%85%8B\" title=\"莫桑比克\">莫桑比克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%B3%E7%B1%B3%E6%AF%94%E4%BA%9A\" title=\"纳米比亚\">纳米比亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%91%99%E9%B2%81\" title=\"瑙鲁\" class=\"mw-redirect\">瑙鲁</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E8%A5%BF%E5%85%B0\" title=\"新西兰\">新西兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A5%88%E5%8F%8A%E5%88%A9%E4%BA%9E\" title=\"奈及利亞\">尼日利亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E5%9F%BA%E6%96%AF%E5%9D%A6\" title=\"巴基斯坦\">巴基斯坦</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E5%B8%83%E4%BA%9A%E6%96%B0%E5%87%A0%E5%86%85%E4%BA%9A\" title=\"巴布亚新几内亚\">巴布亚新几内亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A2%E6%97%BA%E8%BE%BE\" title=\"卢旺达\">卢旺达</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%81%96%E5%85%8B%E9%87%8C%E6%96%AF%E5%A4%9A%E7%A6%8F%E8%88%87%E5%B0%BC%E7%B6%AD%E6%96%AF\" title=\"聖克里斯多福與尼維斯\">聖克里斯多福與尼維斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E5%8D%A2%E8%A5%BF%E4%BA%9A\" title=\"圣卢西亚\">圣卢西亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E6%96%87%E6%A3%AE%E7%89%B9%E5%92%8C%E6%A0%BC%E6%9E%97%E7%BA%B3%E4%B8%81%E6%96%AF\" title=\"圣文森特和格林纳丁斯\">圣文森特和格林纳丁斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%90%A8%E6%91%A9%E4%BA%9A\" title=\"萨摩亚\">萨摩亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E8%88%8C%E5%B0%94\" title=\"塞舌尔\">塞舌尔</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E6%8B%89%E5%88%A9%E6%98%82\" title=\"塞拉利昂\">塞拉利昂</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E5%8A%A0%E5%9D%A1\" title=\"新加坡\">新加坡</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%89%80%E7%BD%97%E9%97%A8%E7%BE%A4%E5%B2%9B\" title=\"所罗门群岛\">所罗门群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E9%9D%9E\" title=\"南非\">南非</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E9%87%8C%E8%98%AD%E5%8D%A1\" title=\"斯里蘭卡\">斯里蘭卡</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E5%A8%81%E5%A3%AB%E5%85%B0\" title=\"斯威士兰\">斯威士兰</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9D%A6%E6%A1%91%E5%B0%BC%E4%BA%9A\" title=\"坦桑尼亚\">坦桑尼亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B9%AF%E5%8A%A0\" title=\"湯加\" class=\"mw-redirect\">汤加</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%83%E9%87%8C%E9%81%94%E5%8F%8A%E6%89%98%E5%B7%B4%E5%93%A5\" title=\"千里達及托巴哥\">特立尼达和多巴哥</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%96%E7%93%A6%E7%9B%A7\" title=\"圖瓦盧\">圖瓦盧</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B9%8C%E5%B9%B2%E8%BE%BE\" title=\"乌干达\">乌干达</a> ·</span> <span style=\"white-space:nowrap\"><strong class=\"selflink\">英国</strong> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%93%A6%E5%8A%AA%E9%98%BF%E5%9B%BE\" title=\"瓦努阿图\">瓦努阿图</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%B5%9E%E6%AF%94%E4%BA%9A\" title=\"赞比亚\">赞比亚</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A2%83%E5%A4%96%E9%A2%86\" title=\"境外领\" class=\"mw-redirect\">海外领土与属地</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% white;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"></div>\n<table class=\"nowraplinks navbox-subgroup\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\"><img alt=\"澳大利亚\" src=\"England%28Chinese%29_files/22px-Flag_of_Australia.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\">澳属</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% rgb(247, 247, 247);\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BA%9E%E4%BB%80%E6%91%A9%E5%8F%8A%E5%8D%A1%E5%9C%B0%E7%88%BE%E7%BE%A4%E5%B3%B6\" title=\"亞什摩及卡地爾群島\" class=\"mw-redirect\">亚什摩及卡地尔群岛</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A%E5%8D%97%E6%9E%81%E9%A2%86%E5%9C%B0\" title=\"澳大利亚南极领地\" class=\"mw-redirect\">澳大利亚南极领地</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E8%AF%9E%E5%B2%9B\" title=\"圣诞岛\">圣诞岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%A7%91%E7%A7%91%E6%96%AF%E7%BE%A4%E5%B2%9B\" title=\"科科斯群岛\" class=\"mw-redirect\">科科斯群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%8F%8A%E7%91%9A%E6%B5%B7%E7%BE%A4%E5%B2%9B\" title=\"珊瑚海群岛\">珊瑚海群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%B3%80%E5%BE%97%E5%8F%8A%E9%BA%A5%E5%94%90%E7%B4%8D%E7%BE%A4%E5%B3%B6\" title=\"賀得及麥唐納群島\" class=\"mw-redirect\">贺得及麦唐纳群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%AF%BA%E7%A6%8F%E5%85%8B%E5%B2%9B\" title=\"诺福克岛\">诺福克岛</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E8%A5%BF%E5%85%B0\" title=\"新西兰\"><img alt=\"新西兰\" src=\"England%28Chinese%29_files/22px-Flag_of_New_Zealand.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E8%A5%BF%E5%85%B0\" title=\"新西兰\">新属</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% white;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BA%93%E5%85%8B%E7%BE%A4%E5%B2%9B\" title=\"库克群岛\">库克群岛</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BA%BD%E5%9F%83\" title=\"纽埃\" class=\"mw-redirect\">纽埃</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E8%A5%BF%E5%85%B0%E7%BD%97%E6%96%AF%E5%B1%9E%E5%9C%B0\" title=\"新西兰罗斯属地\">新西兰罗斯属地</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%89%98%E5%85%8B%E5%8A%B3\" title=\"托克劳\">托克劳</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B0%BC%E7%83%8F%E5%9F%83\" title=\"尼烏埃\" class=\"mw-redirect\">尼烏埃</a></span></div>\n</td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr>\n<th scope=\"row\" class=\"navbox-group\" style=\"\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B\" title=\"英國\"><img alt=\"英國\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD%E6%B5%B7%E5%A4%96%E9%A2%86%E5%9C%9F\" title=\"英国海外领土\" class=\"mw-redirect\">英属</a></th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px; background: none repeat scroll 0% 0% rgb(247, 247, 247);\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\">\n<p><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E5%85%8B%E7%BD%97%E8%92%82%E9%87%8C%E5%92%8C%E5%BE%B7%E5%87%AF%E5%88%A9%E4%BA%9A\" title=\"阿克罗蒂里和德凯利亚\" class=\"mw-redirect\">阿克罗蒂里和德凯利亚</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E5%9C%AD%E6%8B%89\" title=\"安圭拉\">安圭拉</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%99%BE%E6%85%95%E5%A4%A7\" title=\"百慕大\">百慕大</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%B1%9E%E5%8D%97%E6%9E%81%E9%A2%86%E5%9C%B0\" title=\"英属南极领地\">英属南极领地</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%B1%9E%E5%8D%B0%E5%BA%A6%E6%B4%8B%E9%A2%86%E5%9C%B0\" title=\"英属印度洋领地\" class=\"mw-redirect\">英属印度洋领地</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%B1%9E%E7%BB%B4%E5%B0%94%E4%BA%AC%E7%BE%A4%E5%B2%9B\" title=\"英属维尔京群岛\" class=\"mw-redirect\">英属维尔京群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BC%80%E6%9B%BC%E7%BE%A4%E5%B2%9B\" title=\"开曼群岛\" class=\"mw-redirect\">开曼群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%A6%8F%E5%85%8B%E5%85%B0%E7%BE%A4%E5%B2%9B\" title=\"福克兰群岛\">福克兰群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%9B%B4%E5%B8%83%E7%BD%97%E9%99%80\" title=\"直布罗陀\">直布罗陀</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%A0%B9%E8%A5%BF%E5%B2%9B\" title=\"根西岛\">根西岛</a> ·</span></p>\n<span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E6%81%A9%E5%B2%9B\" title=\"马恩岛\" class=\"mw-redirect\">马恩岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%BD%E8%A5%BF%E5%B2%9B\" title=\"泽西岛\" class=\"mw-redirect\">泽西岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%92%99%E5%A1%9E%E6%8B%89%E7%89%B9%E5%B3%B6\" title=\"蒙塞拉特島\">蒙塞拉特島</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%9A%AE%E7%89%B9%E5%87%AF%E6%81%A9%E7%BE%A4%E5%B2%9B\" title=\"皮特凯恩群岛\">皮特凯恩群岛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%A3%E8%B5%AB%E4%BC%A6%E9%82%A3\" title=\"圣赫伦那\" class=\"mw-redirect\">圣赫伦那</a>（包括<a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E6%A3%AE%E6%9D%BE%E5%B2%9B\" title=\"阿森松岛\">阿森松岛</a>和<a href=\"http://zh.wikipedia.org/wiki/%E7%89%B9%E9%87%8C%E6%96%AF%E5%9D%A6-%E8%BE%BE%E5%BA%93%E5%B0%BC%E4%BA%9A%E7%BE%A4%E5%B2%9B\" title=\"特里斯坦-达库尼亚群岛\">特里斯坦-达库尼亚群岛</a>） ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E5%96%AC%E6%B2%BB%E4%BA%9E%E5%B3%B6%E8%88%87%E5%8D%97%E6%A1%91%E5%A8%81%E5%A5%87%E7%BE%A4%E5%B3%B6\" title=\"南喬治亞島與南桑威奇群島\">南乔治亚岛和南桑威奇群岛群島</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%89%B9%E5%85%8B%E6%96%AF%E4%B8%8E%E5%87%AF%E7%A7%91%E6%96%AF%E7%BE%A4%E5%B2%9B\" title=\"特克斯与凯科斯群岛\" class=\"mw-redirect\">特克斯与凯科斯群岛</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt; width: 100%;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:%E6%AD%90%E6%B4%B2%E8%81%AF%E7%9B%9F\" title=\"Template:歐洲聯盟\" class=\"mw-redirect\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/wiki/Template_talk:%E6%AD%90%E6%B4%B2%E8%81%AF%E7%9B%9F\" title=\"Template talk:歐洲聯盟\" class=\"mw-redirect\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:%E6%AD%90%E6%B4%B2%E8%81%AF%E7%9B%9F&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AD%90%E7%9B%9F\" title=\"歐盟\"><img alt=\"歐盟\" src=\"England%28Chinese%29_files/22px-Flag_of_Europe.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span> <a href=\"http://zh.wikipedia.org/wiki/%E6%AC%A7%E6%B4%B2%E8%81%94%E7%9B%9F\" title=\"欧洲联盟\">欧洲联盟</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">成员国</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"></div>\n<span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Austria.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A5%E5%9C%B0%E5%88%A9\" title=\"奥地利\">奥地利</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Belgium_civil.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%97%B6\" title=\"比利时\">比利时</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Bulgaria.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%9D%E5%8A%A0%E5%88%A9%E4%BA%9A\" title=\"保加利亚\">保加利亚</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E6%B5%A6%E8%B7%AF%E6%96%AF\" title=\"塞浦路斯\"><img alt=\"塞浦路斯\" src=\"England%28Chinese%29_files/22px-Flag_of_Cyprus.png\" class=\"thumbborder\" height=\"13\" width=\"22\"></a></span><a href=\"http://zh.wikipedia.org/wiki/%E8%B3%BD%E6%99%AE%E5%8B%92%E6%96%AF\" title=\"賽普勒斯\">塞浦路斯</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Czech_Republic.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%8D%B7%E5%85%8B\" title=\"捷克\">捷克</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Denmark.png\" class=\"thumbborder\" height=\"17\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%B9%E9%BA%A6\" title=\"丹麦\">丹麦</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Estonia.png\" class=\"thumbborder\" height=\"14\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E6%B2%99%E5%B0%BC%E4%BA%9A\" title=\"爱沙尼亚\">爱沙尼亚</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Finland.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%8A%AC%E5%85%B0\" title=\"芬兰\">芬兰</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_France.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Germany.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\">德国</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%8C%E8%87%98\" title=\"希臘\"><img alt=\"希臘\" src=\"England%28Chinese%29_files/22px-Flag_of_Greece.png\" class=\"thumbborder\" height=\"15\" width=\"22\"></a></span><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%8C%E8%85%8A\" title=\"希腊\">希腊</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Hungary.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9\" title=\"匈牙利\">匈牙利</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Italy.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%84%8F%E5%A4%A7%E5%88%A9\" title=\"意大利\">意大利</a>　</span><span style=\"float:left;height:25px;\"><a href=\"http://zh.wikipedia.org/wiki/File:Flag_of_Ireland.svg\" class=\"image\" title=\"爱尔兰\"><img alt=\"爱尔兰\" src=\"England%28Chinese%29_files/25px-Flag_of_Ireland.png\" height=\"13\" width=\"25\"></a>&nbsp;<a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E5%B0%94%E5%85%B0%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"爱尔兰共和国\">爱尔兰</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Latvia.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%8B%89%E8%84%AB%E7%B6%AD%E4%BA%9E\" title=\"拉脫維亞\">拉脫維亞</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Lithuania.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%AB%8B%E9%99%B6%E5%AE%9B\" title=\"立陶宛\">立陶宛</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Luxembourg.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A2%E6%A3%AE%E5%A0%A1\" title=\"卢森堡\">卢森堡</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Malta.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E8%80%B3%E4%BB%96\" title=\"马耳他\">马耳他</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_Netherlands.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%8D%B7%E5%85%B0\" title=\"荷兰\">荷兰</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Poland.png\" class=\"thumbborder\" height=\"14\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E5%85%B0\" title=\"波兰\">波兰</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Portugal.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%91%A1%E8%90%84%E7%89%99\" title=\"葡萄牙\">葡萄牙</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Romania.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%BD%97%E9%A9%AC%E5%B0%BC%E4%BA%9A\" title=\"罗马尼亚\" class=\"mw-redirect\">罗马尼亚</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Slovakia.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E4%BC%90%E5%85%8B\" title=\"斯洛伐克\">斯洛伐克</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Slovenia.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E6%96%87%E5%B0%BC%E4%BA%9A\" title=\"斯洛文尼亚\">斯洛文尼亚</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Spain.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E7%8F%AD%E7%89%99\" title=\"西班牙\">西班牙</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Sweden.png\" class=\"thumbborder\" height=\"14\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%91%9E%E5%85%B8\" title=\"瑞典\">瑞典</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><strong class=\"selflink\">英國</strong></span>\n<div style=\"display:none\"></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">获承认<br>\n候选国</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Croatia.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%BD%97%E5%9C%B0%E4%BA%9A\" title=\"克罗地亚\">克罗地亚</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%85%B6%E9%A0%93%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"馬其頓共和國\"><img alt=\"馬其頓共和國\" src=\"England%28Chinese%29_files/22px-Flag_of_Macedonia.png\" class=\"thumbborder\" height=\"11\" width=\"22\"></a></span><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%85%B6%E9%A0%93%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"馬其頓共和國\">马其顿</a>　</span><span style=\"float:left;height:25px;\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Turkey.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%9F%E8%80%B3%E5%85%B6\" title=\"土耳其\">土耳其</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:NATO\" title=\"Template:NATO\" class=\"mw-redirect\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/wiki/Template_talk:NATO\" title=\"Template talk:NATO\" class=\"mw-redirect\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:NATO&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E5%A4%A7%E8%A5%BF%E6%B4%8B%E5%85%AC%E7%B4%84%E7%B5%84%E7%B9%94\" title=\"北大西洋公約組織\" class=\"mw-redirect\">北大西洋公約組織</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">成员国</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%97%B6\" title=\"比利时\">比利时</a> - <a href=\"http://zh.wikipedia.org/wiki/%E4%BF%9D%E5%8A%A0%E5%88%A9%E4%BA%9A\" title=\"保加利亚\">保加利亚</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E6%8B%BF%E5%A4%A7\" title=\"加拿大\">加拿大</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%8D%B7%E5%85%8B\" title=\"捷克\">捷克</a> - <a href=\"http://zh.wikipedia.org/wiki/%E4%B8%B9%E9%BA%A6\" title=\"丹麦\">丹麦</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%88%B1%E6%B2%99%E5%B0%BC%E4%BA%9A\" title=\"爱沙尼亚\">爱沙尼亚</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\">德国</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B8%8C%E8%85%8A\" title=\"希腊\">希腊</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9\" title=\"匈牙利\">匈牙利</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%86%B0%E5%B2%9B\" title=\"冰岛\">冰岛</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%84%8F%E5%A4%A7%E5%88%A9\" title=\"意大利\">意大利</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%8B%89%E8%84%B1%E7%BB%B4%E4%BA%9A\" title=\"拉脱维亚\" class=\"mw-redirect\">拉脱维亚</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%AB%8B%E9%99%B6%E5%AE%9B\" title=\"立陶宛\">立陶宛</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A2%E6%A3%AE%E5%A0%A1\" title=\"卢森堡\">卢森堡</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%8D%B7%E5%85%B0\" title=\"荷兰\">荷兰</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%8C%AA%E5%A8%81\" title=\"挪威\">挪威</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E5%85%B0\" title=\"波兰\">波兰</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%91%A1%E8%90%84%E7%89%99\" title=\"葡萄牙\">葡萄牙</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%BD%97%E9%A9%AC%E5%B0%BC%E4%BA%9A\" title=\"罗马尼亚\" class=\"mw-redirect\">罗马尼亚</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E4%BC%90%E5%85%8B\" title=\"斯洛伐克\">斯洛伐克</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E6%96%87%E5%B0%BC%E4%BA%9A\" title=\"斯洛文尼亚\">斯洛文尼亚</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E7%8F%AD%E7%89%99\" title=\"西班牙\">西班牙</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%9C%9F%E8%80%B3%E5%85%B6\" title=\"土耳其\">土耳其</a> - <strong class=\"selflink\">英國</strong> - <a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9C%8B\" title=\"美國\">美國</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E7%88%BE%E5%B7%B4%E5%B0%BC%E4%BA%9E\" title=\"阿爾巴尼亞\" class=\"mw-redirect\">阿爾巴尼亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%BE%85%E5%9F%83%E8%A5%BF%E4%BA%9E\" title=\"克羅埃西亞\" class=\"mw-redirect\">克羅埃西亞</a></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">候选国</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%85%B6%E9%A0%93%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"馬其頓共和國\">馬其頓</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%83%8F%E5%85%8B%E8%98%AD\" title=\"烏克蘭\" class=\"mw-redirect\">烏克蘭</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%A0%BC%E9%AD%AF%E5%90%89%E4%BA%9E\" title=\"格魯吉亞\" class=\"mw-redirect\">格魯吉亞</a></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span><span style=\"float:left;width:8em;font-size:80%;margin-right:0.5em;\">&nbsp;</span>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%85%AB%E5%A4%A7%E5%B7%A5%E6%A5%AD%E5%9C%8B%E7%B5%84%E7%B9%94\" title=\"八大工業國組織\">八大工業國組織</a>（G8）</div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td colspan=\"2\" style=\"width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Canada.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%8A%A0%E6%8B%BF%E5%A4%A7\" title=\"加拿大\">加拿大</a>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_France.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Germany.png\" class=\"thumbborder\" height=\"13\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9B%BD\" title=\"德国\">德国</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Italy.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%84%8F%E5%A4%A7%E5%88%A9\" title=\"意大利\">意大利</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Japan.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC\" title=\"日本\">日本</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_Russia.png\" class=\"thumbborder\" height=\"15\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%84%E7%BD%97%E6%96%AF\" title=\"俄罗斯\">俄罗斯</a></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_Kingdom.png\" class=\"thumbborder\" height=\"11\" width=\"22\">&nbsp;</span><strong class=\"selflink\">英國</strong></span>　<span style=\"white-space:nowrap\"><span class=\"flagicon\"><img alt=\"\" src=\"England%28Chinese%29_files/22px-Flag_of_the_United_States.png\" class=\"thumbborder\" height=\"12\" width=\"22\">&nbsp;</span><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%8E%E5%9B%BD\" title=\"美国\" class=\"mw-redirect\">美国</a></span></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt; width: 100%;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:%E5%9C%B0%E4%B8%AD%E6%B5%B7%E8%81%AF%E7%9B%9F\" title=\"Template:地中海聯盟\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:%E5%9C%B0%E4%B8%AD%E6%B5%B7%E8%81%AF%E7%9B%9F&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:地中海聯盟\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:%E5%9C%B0%E4%B8%AD%E6%B5%B7%E8%81%AF%E7%9B%9F&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%B0%E4%B8%AD%E6%B5%B7%E8%81%AF%E7%9B%9F\" title=\"地中海聯盟\">地中海聯盟</a></div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">成員國</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A5%E5%9C%B0%E5%88%A9\" title=\"奥地利\">奥地利</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%99%82\" title=\"比利時\" class=\"mw-redirect\">比利時</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BF%9D%E5%8A%A0%E5%88%A9%E4%BA%9E\" title=\"保加利亞\" class=\"mw-redirect\">保加利亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%B3%BD%E6%99%AE%E5%8B%92%E6%96%AF\" title=\"賽普勒斯\">塞浦路斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%8D%B7%E5%85%8B\" title=\"捷克\">捷克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%B9%E9%BA%A5\" title=\"丹麥\" class=\"mw-redirect\">丹麥</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E6%B2%99%E5%B0%BC%E4%BA%9E\" title=\"愛沙尼亞\" class=\"mw-redirect\">愛沙尼亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8A%AC%E8%98%AD\" title=\"芬蘭\" class=\"mw-redirect\">芬蘭</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9C%8B\" title=\"法國\" class=\"mw-redirect\">法國</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9C%8B\" title=\"德國\" class=\"mw-redirect\">德國</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%B8%8C%E8%87%98\" title=\"希臘\" class=\"mw-redirect\">希臘</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9\" title=\"匈牙利\">匈牙利</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%A9%E5%A4%A7%E5%88%A9\" title=\"義大利\" class=\"mw-redirect\">義大利</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E7%88%BE%E8%98%AD%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"愛爾蘭共和國\" class=\"mw-redirect\">愛爾蘭</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%8B%89%E8%84%AB%E7%B6%AD%E4%BA%9E\" title=\"拉脫維亞\">拉脫維亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%AB%8B%E9%99%B6%E5%AE%9B\" title=\"立陶宛\">立陶宛</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%9B%A7%E6%A3%AE%E5%A0%A1\" title=\"盧森堡\" class=\"mw-redirect\">盧森堡</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E7%88%BE%E4%BB%96\" title=\"馬爾他\" class=\"mw-redirect\">馬爾他</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8D%B7%E8%98%AD\" title=\"荷蘭\" class=\"mw-redirect\">荷蘭</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E8%98%AD\" title=\"波蘭\" class=\"mw-redirect\">波蘭</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%91%A1%E8%90%84%E7%89%99\" title=\"葡萄牙\">葡萄牙</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%BE%85%E9%A6%AC%E5%B0%BC%E4%BA%9E\" title=\"羅馬尼亞\">羅馬尼亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E4%BC%90%E5%85%8B\" title=\"斯洛伐克\">斯洛伐克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E7%B6%AD%E5%B0%BC%E4%BA%9E\" title=\"斯洛維尼亞\" class=\"mw-redirect\">斯洛維尼亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E7%8F%AD%E7%89%99\" title=\"西班牙\">西班牙</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%91%9E%E5%85%B8\" title=\"瑞典\">瑞典</a> ·</span> <span style=\"white-space:nowrap\"><strong class=\"selflink\">英国</strong> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E6%B4%9B%E5%93%A5\" title=\"摩洛哥\">摩洛哥</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8C%85%E5%88%A9%E5%A1%94%E5%B0%BC%E4%BA%9E\" title=\"茅利塔尼亞\" class=\"mw-redirect\">茅利塔尼亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%AA%81%E5%B0%BC%E8%A5%BF%E4%BA%9E\" title=\"突尼西亞\">突尼西亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E7%88%BE%E5%8F%8A%E5%88%A9%E4%BA%9E\" title=\"阿爾及利亞\" class=\"mw-redirect\">阿爾及利亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9F%83%E5%8F%8A\" title=\"埃及\">埃及</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BB%A5%E8%89%B2%E5%88%97\" title=\"以色列\">以色列</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E7%B4%84%E6%97%A6\" title=\"約旦\" class=\"mw-redirect\">約旦</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9C%9F%E8%80%B3%E5%85%B6\" title=\"土耳其\">土耳其</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E7%88%BE%E5%B7%B4%E5%B0%BC%E4%BA%9E\" title=\"阿爾巴尼亞\" class=\"mw-redirect\">阿爾巴尼亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%92%99%E7%89%B9%E5%85%A7%E5%93%A5%E7%BE%85\" title=\"蒙特內哥羅\">蒙特內哥羅</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%85%B6%E9%A0%93\" title=\"馬其頓\">馬其頓</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%BE%85%E5%9F%83%E8%A5%BF%E4%BA%9E\" title=\"克羅埃西亞\" class=\"mw-redirect\">克羅埃西亞</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%BB%8E%E5%B7%B4%E5%AB%A9\" title=\"黎巴嫩\">黎巴嫩</a></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">觀察員國</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E5%88%A9%E6%AF%94%E4%BA%9E\" title=\"利比亞\" class=\"mw-redirect\">利比亞</a></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible autocollapse navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"3\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:%E7%92%B0%E5%8D%B0%E5%BA%A6%E6%B4%8B%E5%8D%80%E5%9F%9F%E5%90%88%E4%BD%9C%E8%81%AF%E7%9B%9F\" title=\"Template:環印度洋區域合作聯盟\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:%E7%92%B0%E5%8D%B0%E5%BA%A6%E6%B4%8B%E5%8D%80%E5%9F%9F%E5%90%88%E4%BD%9C%E8%81%AF%E7%9B%9F&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:環印度洋區域合作聯盟\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:%E7%92%B0%E5%8D%B0%E5%BA%A6%E6%B4%8B%E5%8D%80%E5%9F%9F%E5%90%88%E4%BD%9C%E8%81%AF%E7%9B%9F&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\"><a href=\"http://zh.wikipedia.org/wiki/%E7%8E%AF%E5%8D%B0%E5%BA%A6%E6%B4%8B%E5%8C%BA%E5%9F%9F%E5%90%88%E4%BD%9C%E8%81%94%E7%9B%9F\" title=\"环印度洋区域合作联盟\">环印度洋区域合作联盟</a>（<span xml:lang=\"en\" lang=\"en\">IOR-ARC</span>）</div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">會員國</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E6%BE%B3%E5%A4%A7%E5%88%A9%E4%BA%9A\" title=\"澳大利亚\">澳大利亚</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6\" title=\"印度\">印度</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%82%AF%E5%B0%BC%E4%BA%9A\" title=\"肯尼亚\">肯尼亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%AF%9B%E9%87%8C%E6%B1%82%E6%96%AF\" title=\"毛里求斯\">毛里求斯</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E6%9B%BC\" title=\"阿曼\">阿曼</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%B0%E5%8A%A0%E5%9D%A1\" title=\"新加坡\">新加坡</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E9%9D%9E\" title=\"南非\">南非</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%B0%E5%BA%A6%E5%B0%BC%E8%A5%BF%E4%BA%9A\" title=\"印度尼西亚\">印度尼西亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E6%9D%A5%E8%A5%BF%E4%BA%9A\" title=\"马来西亚\">马来西亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%A9%AC%E8%BE%BE%E5%8A%A0%E6%96%AF%E5%8A%A0\" title=\"马达加斯加\">马达加斯加</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%8E%AB%E6%A1%91%E6%AF%94%E5%85%8B\" title=\"莫桑比克\">莫桑比克</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E9%87%8C%E5%85%B0%E5%8D%A1\" title=\"斯里兰卡\" class=\"mw-redirect\">斯里兰卡</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9D%A6%E6%A1%91%E5%B0%BC%E4%BA%9A\" title=\"坦桑尼亚\">坦桑尼亚</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B9%9F%E9%97%A8\" title=\"也门\">也门</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%AD%9F%E5%8A%A0%E6%8B%89%E5%9B%BD\" title=\"孟加拉国\">孟加拉国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%BC%8A%E6%9C%97\" title=\"伊朗\">伊朗</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%B0%E5%9B%BD\" title=\"泰国\">泰国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E6%8B%89%E4%BC%AF%E8%81%94%E5%90%88%E9%85%8B%E9%95%BF%E5%9B%BD\" title=\"阿拉伯联合酋长国\">阿拉伯联合酋长国</a></span></div>\n</td>\n<td class=\"navbox-image\" style=\"width: 0%; padding: 0px 0px 0px 2px;\" rowspan=\"5\">\n<div><a href=\"http://zh.wikipedia.org/wiki/File:IOR-ARC_Map.PNG\" class=\"image\"><img alt=\"IOR-ARC Map.PNG\" src=\"England%28Chinese%29_files/120px-IOR-ARC_Map.PNG\" height=\"56\" width=\"120\"></a></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">觀察員國</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-even\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD\" title=\"中华人民共和国\">中国</a> · <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E5%9F%83%E5%8F%8A\" title=\"埃及\">埃及</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9B%BD\" title=\"法国\">法国</a> ·</span> <span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC\" title=\"日本\">日本</a> ·</span> <span style=\"white-space:nowrap\"><strong class=\"selflink\">英国</strong></span></div>\n</td>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<th scope=\"row\" class=\"navbox-group\" style=\"\">國際組織觀察員</th>\n<td style=\"text-align: left; border-left-width: 2px; border-left-style: solid; width: 100%; padding: 0px;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0em 0.25em\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E7%8E%AF%E5%8D%B0%E5%BA%A6%E6%B4%8B%E6%97%85%E6%B8%B8%E7%BB%84%E7%BB%87&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"环印度洋旅游组织\">环印度洋旅游组织</a></div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n</div>\n</div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<table class=\"navbox\" style=\"border-spacing: 0pt;\" cellspacing=\"0\">\n<tbody><tr>\n<td style=\"padding: 2px;\">\n<table class=\"nowraplinks collapsible collapsed navbox-inner\" style=\"border-spacing: 0pt; background: none repeat scroll 0% 0% transparent; color: inherit;\" cellspacing=\"0\">\n<tbody><tr tabindex=\"0\" style=\"cursor: pointer;\" class=\" uncollapse toggleHotspot\">\n<th scope=\"col\" style=\"\" class=\"navbox-title\" colspan=\"2\"><span style=\"visibility: visible;\" class=\"NavToggle collapseButton\"><span class=\"toggleShow\">显示▼</span><span style=\"display: none;\" class=\"toggleHide\">隐藏▲</span></span>\n<div class=\"noprint plainlinks hlist navbar nomobile\" style=\"\"><a href=\"http://zh.wikipedia.org/wiki/Template:%E6%AD%90%E6%B4%B2%E5%90%84%E5%9C%8B%E5%8F%8A%E5%85%B6%E9%A6%96%E9%83%BD\" title=\"Template:歐洲各國及其首都\"><span style=\";;background:none transparent;border:none;\" title=\"查看这个模板\">查</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a href=\"http://zh.wikipedia.org/w/index.php?title=Template_talk:%E6%AD%90%E6%B4%B2%E5%90%84%E5%9C%8B%E5%8F%8A%E5%85%B6%E9%A6%96%E9%83%BD&amp;action=edit&amp;redlink=1\" class=\"new\" title=\"Template talk:歐洲各國及其首都\"><span style=\";;background:none transparent;border:none;\" title=\"关于这个模板的讨论页面\">論</span></a><span style=\"white-space:nowrap; font-weight:bold;\">&nbsp;·</span> <a class=\"external text\" href=\"http://zh.wikipedia.org/w/index.php?title=Template:%E6%AD%90%E6%B4%B2%E5%90%84%E5%9C%8B%E5%8F%8A%E5%85%B6%E9%A6%96%E9%83%BD&amp;action=edit\"><span style=\";;background:none transparent;border:none;\" title=\"您可以编辑这个模板。请在储存变更之前先预览\">編</span></a></div>\n<div class=\"\" style=\"font-size:110%;\">歐洲各國及其首都</div>\n</th>\n</tr>\n<tr class=\" toggleHide\" style=\"height: 2px; display: none;\">\n<td></td>\n</tr>\n<tr style=\"display: none;\" class=\" toggleHide\">\n<td colspan=\"2\" style=\"width: 100%; padding: 0px; background: none repeat scroll 0% 0% transparent; color: inherit;\" class=\"navbox-list navbox-odd\">\n<div style=\"padding:0px;\">\n<table class=\"navbox-columns-table\" style=\"text-align: left; width: 100%;\" cellspacing=\"0\">\n<tbody><tr>\n<td class=\"navbox-abovebelow\" colspan=\"1\" style=\"\"><b><a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E6%AD%90\" title=\"西歐\" class=\"mw-redirect\">西歐</a></b></td>\n<td class=\"navbox-abovebelow\" colspan=\"1\" style=\"border-left: 2px solid rgb(253, 253, 253);\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%8C%97%E6%AD%90\" title=\"北歐\">北歐</a></b></td>\n<td class=\"navbox-abovebelow\" colspan=\"1\" style=\"border-left: 2px solid rgb(253, 253, 253);\"><b><a href=\"http://zh.wikipedia.org/wiki/%E5%8D%97%E6%AD%90\" title=\"南歐\" class=\"mw-redirect\">南歐</a></b></td>\n<td class=\"navbox-abovebelow\" colspan=\"1\" style=\"border-left: 2px solid rgb(253, 253, 253);\"><b><a href=\"http://zh.wikipedia.org/wiki/%E6%9D%B1%E6%AD%90\" title=\"東歐\" class=\"mw-redirect\">東歐</a></b></td>\n</tr>\n<tr style=\"height: 2px;\">\n<td></td>\n</tr>\n<tr style=\"vertical-align: top;\">\n<td style=\"padding: 0px; width: 20em;\">\n<div>\n<div style=\"padding-left:0.75em;\">\n<p><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%95%E5%9C%8B\" title=\"法國\" class=\"mw-redirect\">法國</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B7%B4%E9%BB%8E\" title=\"巴黎\">巴黎</a><br>\n<strong class=\"selflink\">英國</strong> - <a href=\"http://zh.wikipedia.org/wiki/%E5%80%AB%E6%95%A6\" title=\"倫敦\" class=\"mw-redirect\">倫敦</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%BE%B7%E5%9C%8B\" title=\"德國\" class=\"mw-redirect\">德國</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%9F%8F%E6%9E%97\" title=\"柏林\">柏林</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%8D%B7%E8%98%AD\" title=\"荷蘭\" class=\"mw-redirect\">荷蘭</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E5%A7%86%E6%96%AF%E7%89%B9%E4%B8%B9\" title=\"阿姆斯特丹\">阿姆斯特丹</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%AF%94%E5%88%A9%E6%99%82\" title=\"比利時\" class=\"mw-redirect\">比利時</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E9%AD%AF%E5%A1%9E%E7%88%BE\" title=\"布魯塞爾\" class=\"mw-redirect\">布魯塞爾</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%9B%A7%E6%A3%AE%E5%A0%A1\" title=\"盧森堡\" class=\"mw-redirect\">盧森堡</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%9B%A7%E6%A3%AE%E5%A0%A1%E5%B8%82\" title=\"盧森堡市\">盧森堡市</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%91%9E%E5%A3%AB\" title=\"瑞士\">瑞士</a> - <a href=\"http://zh.wikipedia.org/wiki/%E4%BC%AF%E6%81%A9\" title=\"伯恩\" class=\"mw-redirect\">伯恩</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A7%E5%9C%B0%E5%88%A9\" title=\"奧地利\" class=\"mw-redirect\">奧地利</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%B6%AD%E4%B9%9F%E7%B4%8D\" title=\"維也納\">維也納</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E7%88%BE%E8%98%AD%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"愛爾蘭共和國\" class=\"mw-redirect\">愛爾蘭</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%83%BD%E6%9F%8F%E6%9E%97\" title=\"都柏林\">都柏林</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E7%B4%8D%E5%93%A5\" title=\"摩納哥\" class=\"mw-redirect\">摩納哥</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E7%B4%8D%E5%93%A5\" title=\"摩納哥\" class=\"mw-redirect\">摩納哥</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%88%97%E6%94%AF%E6%95%A6%E6%96%AF%E7%99%BB\" title=\"列支敦斯登\">列支敦斯登</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%93%A6%E6%9D%9C%E5%85%B9\" title=\"瓦杜兹\" class=\"mw-redirect\">瓦杜茲</a><br></span></p>\n</div>\n</div>\n</td>\n<td style=\"border-left: 2px solid rgb(253, 253, 253); padding: 0px; width: 18em;\">\n<div>\n<p><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E4%B8%B9%E9%BA%A5\" title=\"丹麥\" class=\"mw-redirect\">丹麥</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%93%A5%E6%9C%AC%E5%93%88%E6%A0%B9\" title=\"哥本哈根\">哥本哈根</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%8C%AA%E5%A8%81\" title=\"挪威\">挪威</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%A5%A7%E6%96%AF%E9%99%B8\" title=\"奧斯陸\" class=\"mw-redirect\">奧斯陸</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%91%9E%E5%85%B8\" title=\"瑞典\">瑞典</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E5%BE%B7%E5%93%A5%E7%88%BE%E6%91%A9\" title=\"斯德哥爾摩\" class=\"mw-redirect\">斯德哥爾摩</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%8A%AC%E8%98%AD\" title=\"芬蘭\" class=\"mw-redirect\">芬蘭</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%B5%AB%E7%88%BE%E8%BE%9B%E5%9F%BA\" title=\"赫爾辛基\" class=\"mw-redirect\">赫爾辛基</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%86%B0%E5%B3%B6\" title=\"冰島\" class=\"mw-redirect\">冰島</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%9B%B7%E5%85%8B%E9%9B%85%E7%B6%AD%E5%85%8B\" title=\"雷克雅維克\">雷克雅維克</a><br></span></p>\n</div>\n</td>\n<td style=\"border-left: 2px solid rgb(253, 253, 253); padding: 0px; width: 18em;\">\n<div>\n<p><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E8%A5%BF%E7%8F%AD%E7%89%99\" title=\"西班牙\">西班牙</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%BE%B7%E9%87%8C\" title=\"馬德里\" class=\"mw-redirect\">馬德里</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%91%A1%E8%90%84%E7%89%99\" title=\"葡萄牙\">葡萄牙</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%87%8C%E6%96%AF%E6%9C%AC\" title=\"里斯本\">里斯本</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%84%8F%E5%A4%A7%E5%88%A9\" title=\"意大利\">意大利</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%BD%97%E9%A9%AC\" title=\"罗马\">羅馬</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%B8%8C%E8%87%98\" title=\"希臘\" class=\"mw-redirect\">希臘</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%9B%85%E5%85%B8\" title=\"雅典\">雅典</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%A2%B5%E8%92%82%E5%86%88\" title=\"梵蒂冈\">梵蒂岡</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%A2%B5%E8%92%82%E5%86%88\" title=\"梵蒂冈\">梵蒂岡城</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%81%96%E9%A6%AC%E5%8A%9B%E8%AB%BE\" title=\"聖馬力諾\" class=\"mw-redirect\">聖馬力諾</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%81%96%E9%A6%AC%E5%8A%9B%E8%AB%BE_%28%E5%9F%8E%E5%B8%82%29\" title=\"聖馬力諾 (城市)\">聖馬力諾</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E7%88%BE%E4%BB%96\" title=\"馬爾他\" class=\"mw-redirect\">馬爾他</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%93%A6%E8%8E%B1%E5%A1%94\" title=\"瓦莱塔\">瓦萊塔</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E9%81%93%E7%88%BE\" title=\"安道爾\" class=\"mw-redirect\">安道爾</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%AE%89%E9%81%93%E5%B0%94%E5%9F%8E\" title=\"安道尔城\">安道爾城</a><br></span></p>\n</div>\n</td>\n<td style=\"border-left: 2px solid rgb(253, 253, 253); padding: 0px; width: 16.25em;\">\n<div>\n<p><span style=\"white-space:nowrap\"><a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E8%98%AD\" title=\"波蘭\" class=\"mw-redirect\">波蘭</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%8F%AF%E6%B2%99\" title=\"華沙\" class=\"mw-redirect\">華沙</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%8D%B7%E5%85%8B\" title=\"捷克\">捷克</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E6%8B%89%E6%A0%BC\" title=\"布拉格\">布拉格</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%84%9B%E6%B2%99%E5%B0%BC%E4%BA%9E\" title=\"愛沙尼亞\" class=\"mw-redirect\">愛沙尼亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%A1%94%E6%9E%97\" title=\"塔林\">塔林</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%8B%89%E8%84%AB%E7%B6%AD%E4%BA%9E\" title=\"拉脫維亞\">拉脫維亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E9%87%8C%E5%8A%A0\" title=\"里加\">里加</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%AB%8B%E9%99%B6%E5%AE%9B\" title=\"立陶宛\">立陶宛</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%B6%AD%E7%88%BE%E7%B4%90%E6%96%AF\" title=\"維爾紐斯\" class=\"mw-redirect\">維爾紐斯</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%83%8F%E5%85%8B%E8%98%AD\" title=\"烏克蘭\" class=\"mw-redirect\">烏克蘭</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%9F%BA%E8%BC%94\" title=\"基輔\">基輔</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9\" title=\"匈牙利\">匈牙利</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E9%81%94%E4%BD%A9%E6%96%AF\" title=\"布達佩斯\" class=\"mw-redirect\">布達佩斯</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E4%BC%90%E5%85%8B\" title=\"斯洛伐克\">斯洛伐克</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E6%8B%89%E8%BF%AA%E6%96%AF%E6%8B%89%E5%8F%91\" title=\"布拉迪斯拉发\">布拉迪斯拉发</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%99%BD%E4%BF%84%E7%BE%85%E6%96%AF\" title=\"白俄羅斯\" class=\"mw-redirect\">白俄羅斯</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%98%8E%E6%96%AF%E5%85%8B\" title=\"明斯克\">明斯克</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%91%A9%E7%88%BE%E5%A4%9A%E7%93%A6\" title=\"摩爾多瓦\" class=\"mw-redirect\">摩爾多瓦</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%9F%BA%E5%B8%8C%E8%AE%B7%E4%B9%8C\" title=\"基希讷乌\">基希讷乌</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%BE%85%E9%A6%AC%E5%B0%BC%E4%BA%9E\" title=\"羅馬尼亞\">羅馬尼亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%B8%83%E5%8A%A0%E5%8B%92%E6%96%AF%E7%89%B9\" title=\"布加勒斯特\">布加勒斯特</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E4%BF%9D%E5%8A%A0%E5%88%A9%E4%BA%9E\" title=\"保加利亞\" class=\"mw-redirect\">保加利亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E7%B4%A2%E9%9D%9E%E4%BA%9E\" title=\"索非亞\" class=\"mw-redirect\">索非亞</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E8%92%99%E7%89%B9%E5%85%A7%E5%93%A5%E7%BE%85\" title=\"蒙特內哥羅\">黑山</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E5%BE%B7%E6%88%88%E9%87%8C%E5%AF%9F\" title=\"波德戈里察\">波德戈里察</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E7%A7%91%E7%B4%A2%E6%B2%83\" title=\"科索沃\">科索沃</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%99%AE%E9%87%8C%E4%BB%80%E8%92%82%E7%B4%8D\" title=\"普里什蒂納\" class=\"mw-redirect\">普里什蒂納</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%B3%A2%E6%96%AF%E5%B0%BC%E4%BA%9A%E5%92%8C%E9%BB%91%E5%A1%9E%E5%93%A5%E7%BB%B4%E9%82%A3\" title=\"波斯尼亚和黑塞哥维那\">波士尼亞赫塞哥維納</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%90%A8%E6%8B%89%E7%83%AD%E7%AA%9D\" title=\"萨拉热窝\" class=\"mw-redirect\">萨拉热窝</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E9%A6%AC%E5%85%B6%E9%A0%93%E5%85%B1%E5%92%8C%E5%9C%8B\" title=\"馬其頓共和國\">馬其頓</a> - <a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E7%A7%91%E6%99%AE%E9%87%8C\" title=\"斯科普里\">斯科普里</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E9%98%BF%E7%88%BE%E5%B7%B4%E5%B0%BC%E4%BA%9E\" title=\"阿爾巴尼亞\" class=\"mw-redirect\">阿爾巴尼亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%9C%B0%E6%8B%89%E9%82%A3\" title=\"地拉那\">地拉那</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%A1%9E%E7%88%BE%E7%B6%AD%E4%BA%9E\" title=\"塞爾維亞\" class=\"mw-redirect\">塞爾維亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%B2%9D%E7%88%BE%E6%A0%BC%E8%90%8A%E5%BE%B7\" title=\"貝爾格萊德\" class=\"mw-redirect\">貝爾格萊德</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E6%96%AF%E6%B4%9B%E6%96%87%E5%B0%BC%E4%BA%9E\" title=\"斯洛文尼亞\" class=\"mw-redirect\">斯洛文尼亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E5%8D%A2%E5%B8%83%E5%B0%94%E9%9B%85%E9%82%A3\" title=\"卢布尔雅那\">卢布尔雅那</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E5%85%8B%E7%BE%85%E5%9C%B0%E4%BA%9E\" title=\"克羅地亞\" class=\"mw-redirect\">克羅地亞</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%90%A8%E6%A0%BC%E5%8B%92%E5%B8%83\" title=\"萨格勒布\">萨格勒布</a><br>\n<a href=\"http://zh.wikipedia.org/wiki/%E4%BF%84%E7%BE%85%E6%96%AF\" title=\"俄羅斯\" class=\"mw-redirect\">俄羅斯</a> - <a href=\"http://zh.wikipedia.org/wiki/%E8%8E%AB%E6%96%AF%E7%A7%91\" title=\"莫斯科\">莫斯科</a></span></p>\n</div>\n</td>\n</tr>\n</tbody></table>\n</div>\n</td>\n</tr>\n</tbody></table>\n</td>\n</tr>\n</tbody></table>\n<p><span id=\"interwiki-es-fa\"></span> <span id=\"interwiki-ta-fa\"></span> <span id=\"interwiki-en-ga\"></span> <span id=\"interwiki-gv-fa\"></span> <span id=\"interwiki-yi-fa\"></span></p>\n\n\n<!-- \nNewPP limit report\nPreprocessor node count: 34368/1000000\nPost-expand include size: 808535/2048000 bytes\nTemplate argument size: 456169/2048000 bytes\nExpensive parser function count: 16/500\n-->\n\n<!-- Saved in parser cache with key zhwiki:pcache:idhash:39793-0!*!0!!zh!4!zh!* and timestamp 20120430225400 -->\n</div>\t\t\t\t<!-- /bodycontent -->\n\t\t\t\t\t\t\t\t<!-- printfooter -->\n\t\t\t\t<div class=\"printfooter\">\n\t\t\t\t来自“<a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;oldid=20918917\">http://zh.wikipedia.org/w/index.php?title=英国&amp;oldid=20918917</a>”\t\t\t\t</div>\n\t\t\t\t<!-- /printfooter -->\n\t\t\t\t\t\t\t\t\t\t\t\t<!-- catlinks -->\n\t\t\t\t<div class=\"articleFeedback\" id=\"mw-articlefeedback\"><div class=\"articleFeedback-panel\">\t<div class=\"articleFeedback-buffer articleFeedback-ui\">\t\t<div class=\"articleFeedback-switch articleFeedback-switch-report articleFeedback-visibleWith-form\" rel=\"report\">查看条目评分</div>\t\t<div style=\"display: none;\" class=\"articleFeedback-switch articleFeedback-switch-form articleFeedback-visibleWith-report\" rel=\"form\">给本文评分</div>\t\t<div class=\"articleFeedback-title articleFeedback-visibleWith-form\">给本文评分</div>\t\t<div style=\"display: none;\" class=\"articleFeedback-title articleFeedback-visibleWith-report\">条目评分</div>\t\t<div class=\"articleFeedback-explanation articleFeedback-visibleWith-form\"><a href=\"http://zh.wikipedia.org/wiki/Project:%E6%9D%A1%E7%9B%AE%E8%AF%84%E5%88%86%E5%B7%A5%E5%85%B7\" class=\"articleFeedback-explanation-link\">这是什么？</a></div>\t\t<div style=\"display: none;\" class=\"articleFeedback-description articleFeedback-visibleWith-report\">当前平均分。</div>\t\t<div style=\"clear:both;\"></div>\t\t<div class=\"articleFeedback-ratings\"><div rel=\"trustworthy\" class=\"articleFeedback-rating\">\t<div original-title=\"你觉得本条目有足够的参考文献，而且这些文献的来源可靠吗？\" class=\"articleFeedback-label\">可信度</div>\t<input name=\"r1\" type=\"hidden\">\t<div class=\"articleFeedback-rating-labels articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-label\" rel=\"1\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"2\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"3\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"4\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"5\"></div>\t\t<div original-title=\"删除该评分\" class=\"articleFeedback-rating-clear\"></div>\t</div>\t<div class=\"articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-tooltip\"></div>\t</div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-average articleFeedback-visibleWith-report\"></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-meter articleFeedback-visibleWith-report\"><div></div></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-count articleFeedback-visibleWith-report\"></div>\t<div style=\"clear:both;\"></div></div><div rel=\"objective\" class=\"articleFeedback-rating\">\t<div original-title=\"你觉得本条目所描述的所有观点对相关问题的表述是否公平合理，具有代表性？\" class=\"articleFeedback-label\">客观性</div>\t<input name=\"r2\" type=\"hidden\">\t<div class=\"articleFeedback-rating-labels articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-label\" rel=\"1\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"2\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"3\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"4\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"5\"></div>\t\t<div original-title=\"删除该评分\" class=\"articleFeedback-rating-clear\"></div>\t</div>\t<div class=\"articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-tooltip\"></div>\t</div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-average articleFeedback-visibleWith-report\"></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-meter articleFeedback-visibleWith-report\"><div></div></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-count articleFeedback-visibleWith-report\"></div>\t<div style=\"clear:both;\"></div></div><div rel=\"complete\" class=\"articleFeedback-rating\">\t<div original-title=\"您觉得本条目是否已经涵盖了所有必要的内容？\" class=\"articleFeedback-label\">完整性</div>\t<input name=\"r3\" type=\"hidden\">\t<div class=\"articleFeedback-rating-labels articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-label\" rel=\"1\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"2\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"3\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"4\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"5\"></div>\t\t<div original-title=\"删除该评分\" class=\"articleFeedback-rating-clear\"></div>\t</div>\t<div class=\"articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-tooltip\"></div>\t</div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-average articleFeedback-visibleWith-report\"></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-meter articleFeedback-visibleWith-report\"><div></div></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-count articleFeedback-visibleWith-report\"></div>\t<div style=\"clear:both;\"></div></div><div rel=\"wellwritten\" class=\"articleFeedback-rating\">\t<div original-title=\"你觉得本条目内容的组织和撰写是否精心完美？\" class=\"articleFeedback-label\">可读性</div>\t<input name=\"r4\" type=\"hidden\">\t<div class=\"articleFeedback-rating-labels articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-label\" rel=\"1\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"2\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"3\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"4\"></div>\t\t<div class=\"articleFeedback-rating-label\" rel=\"5\"></div>\t\t<div original-title=\"删除该评分\" class=\"articleFeedback-rating-clear\"></div>\t</div>\t<div class=\"articleFeedback-visibleWith-form\">\t\t<div class=\"articleFeedback-rating-tooltip\"></div>\t</div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-average articleFeedback-visibleWith-report\"></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-meter articleFeedback-visibleWith-report\"><div></div></div>\t<div style=\"display: none;\" class=\"articleFeedback-rating-count articleFeedback-visibleWith-report\"></div>\t<div style=\"clear:both;\"></div></div></div>\t\t<div style=\"clear:both;\"></div>\t\t<div class=\"articleFeedback-options\">\t\t\t<div class=\"articleFeedback-expertise articleFeedback-visibleWith-form\">\t\t\t\t<input id=\"articleFeedback-expertise-general\" value=\"general\" disabled=\"disabled\" type=\"checkbox\"><label for=\"articleFeedback-expertise-general\" class=\"articleFeedback-expertise-disabled\">我非常了解与本主题相关的知识（可选）</label>\t\t\t\t<div class=\"articleFeedback-expertise-options\">\t\t\t\t\t<div><input id=\"articleFeedback-expertise-studies\" value=\"studies\" type=\"checkbox\"><label for=\"articleFeedback-expertise-studies\">我有与其有关的大学学位</label></div>\t\t\t\t\t<div><input id=\"articleFeedback-expertise-profession\" value=\"profession\" type=\"checkbox\"><label for=\"articleFeedback-expertise-profession\">这是我专业的一部分</label></div>\t\t\t\t\t<div><input id=\"articleFeedback-expertise-hobby\" value=\"hobby\" type=\"checkbox\"><label for=\"articleFeedback-expertise-hobby\">个人对此有深厚的兴趣</label></div>\t\t\t\t\t<div><input id=\"articleFeedback-expertise-other\" value=\"other\" type=\"checkbox\"><label for=\"articleFeedback-expertise-other\">文中未列出我所了解知识的来源</label></div>\t\t\t\t\t<div class=\"articleFeedback-helpimprove\">\t\t\t\t\t\t<input id=\"articleFeedback-expertise-helpimprove-email\" value=\"helpimprove-email\" type=\"checkbox\">\t\t\t\t\t\t<label for=\"articleFeedback-expertise-helpimprove-email\">我想帮助改善维基百科，请给我发送一封电子邮件（可选）</label>\t\t\t\t\t\t<input placeholder=\"email@example.org\" class=\"articleFeedback-helpimprove-email\" type=\"text\">\t\t\t\t\t\t<div class=\"articleFeedback-helpimprove-note\">我们将向您发送确认电子邮件。基于<a href=\"http://wikimediafoundation.org/wiki/Feedback_privacy_statement\">反馈隐私政策</a>，我们不会与任何人共享您的地址。</div>\t\t\t\t\t</div>\t\t\t\t</div>\t\t\t</div>\t\t\t<div style=\"clear:both;\"></div>\t\t</div>\t\t<button aria-disabled=\"true\" role=\"button\" class=\"articleFeedback-submit articleFeedback-visibleWith-form ui-button ui-widget ui-state-default ui-corner-all ui-button-disabled ui-state-disabled ui-button-text-only ui-button-blue\" type=\"submit\" disabled=\"disabled\"><span class=\"ui-button-text\">提交评分</span></button>\t\t<div class=\"articleFeedback-success articleFeedback-visibleWith-form\"><span>保存成功</span></div>\t\t<div class=\"articleFeedback-pending articleFeedback-visibleWith-form\"><span>你的评分尚未提交</span></div>\t\t<div style=\"clear:both;\"></div>\t\t<div class=\"articleFeedback-notices articleFeedback-visibleWith-form\">\t\t\t<div class=\"articleFeedback-expiry\">\t\t\t\t<div class=\"articleFeedback-expiry-title\">你的评分已过期</div>\t\t\t\t<div class=\"articleFeedback-expiry-message\">请重新评估本条目并重新评分。</div>\t\t\t</div>\t\t</div>\t</div>\t<div class=\"articleFeedback-error\"><div class=\"articleFeedback-error-message\">发生了一个错误。请稍后重试。</div></div>\t<div class=\"articleFeedback-pitches\"><div rel=\"survey\" class=\"articleFeedback-pitch\">\t<div class=\"articleFeedback-buffer\">\t\t<div class=\"articleFeedback-title\">谢谢！你的评分已保存。</div>\t\t<div class=\"articleFeedback-pop\">\t\t\t<div class=\"articleFeedback-message\">请花些时间完成简短的调查。</div>\t\t\t<div class=\"articleFeedback-body\"></div>\t\t\t<button aria-disabled=\"false\" role=\"button\" class=\"articleFeedback-accept ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-button-green\"><span class=\"ui-button-text\">开始调查</span></button>\t\t\t<button class=\"articleFeedback-reject\">以后再说</button>\t\t</div>\t</div></div><div rel=\"join\" class=\"articleFeedback-pitch\">\t<div class=\"articleFeedback-buffer\">\t\t<div class=\"articleFeedback-title\">谢谢！你的评分已保存。</div>\t\t<div class=\"articleFeedback-pop\">\t\t\t<div class=\"articleFeedback-message\">您要创建帐户吗？</div>\t\t\t<div class=\"articleFeedback-body\">帐户将帮助您跟踪您所做的编辑，参与讨论，并成为社群的一分子。</div>\t\t\t<button aria-disabled=\"false\" role=\"button\" class=\"articleFeedback-accept ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-button-green\"><span class=\"ui-button-text\">创建帐户</span></button><span class=\"articleFeedback-pitch-or\">或者</span><button aria-disabled=\"false\" role=\"button\" class=\"articleFeedback-altAccept ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-button-green\"><span class=\"ui-button-text\">登录</span></button>\t\t\t<button class=\"articleFeedback-reject\">以后再说</button>\t\t</div>\t</div></div><div rel=\"edit\" class=\"articleFeedback-pitch\">\t<div class=\"articleFeedback-buffer\">\t\t<div class=\"articleFeedback-title\">谢谢！你的评分已保存。</div>\t\t<div class=\"articleFeedback-pop\">\t\t\t<div class=\"articleFeedback-message\">您知道您可以编辑这个页面吗？</div>\t\t\t<div class=\"articleFeedback-body\"></div>\t\t\t<button aria-disabled=\"false\" role=\"button\" class=\"articleFeedback-accept ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-button-green\"><span class=\"ui-button-text\">编辑本页</span></button>\t\t\t<button class=\"articleFeedback-reject\">以后再说</button>\t\t</div>\t</div></div></div>\t<div style=\"clear:both;\"></div></div><div class=\"articleFeedback-lock\"></div>\t\t</div><div id=\"catlinks\" class=\"catlinks\"><div id=\"mw-normal-catlinks\" class=\"mw-normal-catlinks\"><a href=\"http://zh.wikipedia.org/wiki/Special:%E9%A1%B5%E9%9D%A2%E5%88%86%E7%B1%BB\" title=\"Special:页面分类\">12个分类</a>: <ul><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E8%8B%B1%E8%81%94%E9%82%A6\" title=\"Category:英联邦\">英联邦</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%8C%97%E5%A4%A7%E8%A5%BF%E6%B4%8B%E5%85%AC%E7%BA%A6%E7%BB%84%E7%BB%87\" title=\"Category:北大西洋公约组织\">北大西洋公约组织</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%85%AB%E5%9C%8B%E9%9B%86%E5%9C%98\" title=\"Category:八國集團\">八國集團</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%9C%B0%E4%B8%AD%E6%B5%B7%E8%81%AF%E7%9B%9F%E6%88%90%E5%93%A1%E5%9C%8B\" title=\"Category:地中海聯盟成員國\">地中海聯盟成員國</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E7%8E%AF%E5%8D%B0%E5%BA%A6%E6%B4%8B%E5%8C%BA%E5%9F%9F%E5%90%88%E4%BD%9C%E8%81%94%E7%9B%9F%E6%88%90%E5%91%98%E5%9B%BD\" title=\"Category:环印度洋区域合作联盟成员国\">环印度洋区域合作联盟成员国</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E8%8B%B1%E5%9B%BD\" title=\"Category:英国\">英国</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E6%AC%A7%E6%B4%B2%E5%B2%9B%E5%9B%BD\" title=\"Category:欧洲岛国\">欧洲岛国</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E6%A0%B8%E6%AD%A6%E5%9C%8B%E5%AE%B6\" title=\"Category:核武國家\">核武國家</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E6%96%B0%E6%95%99%E5%9B%BD%E5%AE%B6\" title=\"Category:新教国家\">新教国家</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%90%9B%E4%B8%BB%E7%AB%8B%E6%86%B2%E5%9C%8B\" title=\"Category:君主立憲國\">君主立憲國</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E8%81%94%E5%90%88%E5%9B%BD%E5%88%9B%E5%A7%8B%E4%BC%9A%E5%91%98%E5%9B%BD\" title=\"Category:联合国创始会员国\">联合国创始会员国</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E8%81%94%E5%90%88%E5%9B%BD%E5%AE%89%E5%85%A8%E7%90%86%E4%BA%8B%E4%BC%9A%E5%B8%B8%E4%BB%BB%E7%90%86%E4%BA%8B%E5%9B%BD\" title=\"Category:联合国安全理事会常任理事国\">联合国安全理事会常任理事国</a></li></ul></div><div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks mw-hidden-cats-hidden\">6个隐藏分类: <ul><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%90%AB%E6%9C%89%E8%8B%B1%E8%AA%9E%E7%9A%84%E6%A2%9D%E7%9B%AE\" title=\"Category:含有英語的條目\">含有英語的條目</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E8%87%AA2012%E5%B9%B42%E6%9C%88%E9%9C%80%E8%A1%A5%E5%85%85%E6%9D%A5%E6%BA%90%E7%9A%84%E6%9D%A1%E7%9B%AE\" title=\"Category:自2012年2月需补充来源的条目\">自2012年2月需补充来源的条目</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E8%87%AA2012%E5%B9%B43%E6%9C%88%E9%9C%80%E8%A6%81%E7%BB%B4%E5%9F%BA%E5%8C%96%E7%9A%84%E9%A1%B5%E9%9D%A2\" title=\"Category:自2012年3月需要维基化的页面\">自2012年3月需要维基化的页面</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%90%AB%E6%9C%89%E6%B3%95%E8%AA%9E%E7%9A%84%E6%A2%9D%E7%9B%AE\" title=\"Category:含有法語的條目\">含有法語的條目</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%90%AB%E6%9C%89%E8%98%87%E6%A0%BC%E8%98%AD%E8%93%8B%E7%88%BE%E8%AA%9E%E7%9A%84%E6%A2%9D%E7%9B%AE\" title=\"Category:含有蘇格蘭蓋爾語的條目\">含有蘇格蘭蓋爾語的條目</a></li><li><a href=\"http://zh.wikipedia.org/wiki/Category:%E5%90%AB%E6%9C%89%E4%BD%8E%E5%9C%B0%E8%98%87%E6%A0%BC%E8%98%AD%E8%AA%9E%E7%9A%84%E6%A2%9D%E7%9B%AE\" title=\"Category:含有低地蘇格蘭語的條目\">含有低地蘇格蘭語的條目</a></li></ul></div></div>\t\t\t\t<!-- /catlinks -->\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"visualClear\"></div>\n\t\t\t\t<!-- debughtml -->\n\t\t\t\t\t\t\t\t<!-- /debughtml -->\n\t\t\t</div>\n\t\t\t<!-- /bodyContent -->\n\t\t</div>\n\t\t<!-- /content -->\n\t\t<!-- header -->\n\t\t<div id=\"mw-head\" class=\"noprint\">\n\t\t\t\n<!-- 0 -->\n<div id=\"p-personal\" class=\"\">\n\t<h5>个人工具</h5>\n\t<ul>\n\t\t<li id=\"pt-login\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Special:%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95&amp;returnto=%E8%8B%B1%E5%9B%BD\" title=\"建议你登录，尽管并非必须。 [alt-shift-o]\" accesskey=\"o\">登录/创建账户</a></li>\n\t</ul>\n</div>\n\n<!-- /0 -->\n\t\t\t<div id=\"left-navigation\">\n\t\t\t\t\n<!-- 0 -->\n<div id=\"p-namespaces\" class=\"vectorTabs\">\n\t<h5>名字空间</h5>\n\t<ul>\n\t\t\t\t\t<li id=\"ca-nstab-main\" class=\"selected\"><span><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD\" title=\"查看页面内容 [alt-shift-c]\" accesskey=\"c\">条目</a></span></li>\n\t\t\t\t\t<li id=\"ca-talk\"><span><a href=\"http://zh.wikipedia.org/wiki/Talk:%E8%8B%B1%E5%9B%BD\" title=\"关于此页面的讨论 [alt-shift-t]\" accesskey=\"t\">讨论</a></span></li>\n\t\t\t</ul>\n</div>\n\n<!-- /0 -->\n\n<!-- 1 -->\n<div id=\"p-variants\" class=\"vectorMenu\">\n\t<h4>\n\t\t\t\t\t\t不转换\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</h4>\n\t<h5><span>变换</span><a href=\"#\"></a></h5>\n\t<div class=\"menu\">\n\t\t<ul>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-0\" class=\"selected\"><a href=\"http://zh.wikipedia.org/zh/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh\" lang=\"zh\">不转换</a></li>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-1\"><a href=\"http://zh.wikipedia.org/zh-hans/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh-hans\" lang=\"zh-hans\">简体</a></li>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-2\"><a href=\"http://zh.wikipedia.org/zh-hant/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh-hant\" lang=\"zh-hant\">繁體</a></li>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-3\"><a href=\"http://zh.wikipedia.org/zh-cn/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh-cn\" lang=\"zh-cn\">大陆简体</a></li>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-4\"><a href=\"http://zh.wikipedia.org/zh-hk/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh-hk\" lang=\"zh-hk\">港澳繁體</a></li>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-5\"><a href=\"http://zh.wikipedia.org/zh-sg/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh-sg\" lang=\"zh-sg\">马新简体</a></li>\n\t\t\t\t\t\t\t<li id=\"ca-varlang-6\"><a href=\"http://zh.wikipedia.org/zh-tw/%E8%8B%B1%E5%9B%BD\" hreflang=\"zh-tw\" lang=\"zh-tw\">台灣正體</a></li>\n\t\t\t\t\t</ul>\n\t</div>\n</div>\n\n<!-- /1 -->\n\t\t\t</div>\n\t\t\t<div id=\"right-navigation\">\n\t\t\t\t\n<!-- 0 -->\n<div id=\"p-views\" class=\"vectorTabs\">\n\t<h5>查看</h5>\n\t<ul>\n\t\t\t\t\t<li id=\"ca-view\" class=\"selected\"><span><a href=\"http://zh.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD\">阅读</a></span></li>\n\t\t\t\t\t<li id=\"ca-edit\"><span><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=edit\" title=\"你可以编辑本页面。请在保存前使用预览按钮。 [alt-shift-e]\" accesskey=\"e\">编辑</a></span></li>\n\t\t\t\t\t<li id=\"ca-history\" class=\"collapsible\"><span><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;action=history\" title=\"本页面的早前版本。 [alt-shift-h]\" accesskey=\"h\">查看历史</a></span></li>\n\t\t\t</ul>\n</div>\n\n<!-- /0 -->\n\n<!-- 1 -->\n<div id=\"p-cactions\" class=\"vectorMenu emptyPortlet\">\n\t<h5><span>操作</span><a href=\"#\"></a></h5>\n\t<div class=\"menu\">\n\t\t<ul>\n\t\t\t\t\t</ul>\n\t</div>\n</div>\n\n<!-- /1 -->\n\n<!-- 2 -->\n<div id=\"p-search\">\n\t<h5><label for=\"searchInput\">搜索</label></h5>\n\t<form action=\"/w/index.php\" id=\"searchform\">\n\t\t\t\t<div id=\"simpleSearch\">\n\t\t\t\t\t\t<input autocomplete=\"off\" placeholder=\"搜索\" tabindex=\"1\" name=\"search\" title=\"搜索维基百科 [alt-shift-f]\" accesskey=\"f\" id=\"searchInput\" type=\"text\">\t\t\t\t\t\t<button type=\"submit\" name=\"button\" title=\"搜索含这些文字的页面\" id=\"searchButton\" width=\"12\" height=\"13\"><img src=\"England%28Chinese%29_files/search-ltr.png\" alt=\"搜索\"></button>\t\t\t\t\t\t\t\t<input name=\"title\" value=\"Special:搜索\" type=\"hidden\">\n\t\t</div>\n\t</form>\n</div>\n\n<!-- /2 -->\n\t\t\t</div>\n\t\t</div>\n\t\t<!-- /header -->\n\t\t<!-- panel -->\n\t\t\t<div id=\"mw-panel\" class=\"noprint collapsible-nav\">\n\t\t\t\t<!-- logo -->\n\t\t\t\t\t<div id=\"p-logo\"><a style=\"background-image: url(&quot;//upload.wikimedia.org/wikipedia/zh/b/bc/Wiki.png&quot;);\" href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5\" title=\"首页\"></a></div>\n\t\t\t\t<!-- /logo -->\n\t\t\t\t\n<!-- SEARCH -->\n\n<!-- /SEARCH -->\n\n<!-- navigation -->\n<div class=\"portal first persistent\" id=\"p-navigation\">\n\t<h5>导航</h5>\n\t<div class=\"body\">\n\t\t<ul>\n\t\t\t<li id=\"n-mainpage-description\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5\" title=\"访问首页 [alt-shift-z]\" accesskey=\"z\">首页</a></li>\n\t\t\t<li id=\"n-indexpage\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%88%86%E9%A1%9E%E7%B4%A2%E5%BC%95\">分類索引</a></li>\n\t\t\t<li id=\"n-Featured_content\"><a href=\"http://zh.wikipedia.org/wiki/Portal:%E7%89%B9%E8%89%B2%E5%85%A7%E5%AE%B9\">特色内容</a></li>\n\t\t\t<li id=\"n-currentevents\"><a href=\"http://zh.wikipedia.org/wiki/Portal:%E6%96%B0%E8%81%9E%E5%8B%95%E6%85%8B\" title=\"提供当前新闻事件的背景资料\">新闻动态</a></li>\n\t\t\t<li id=\"n-recentchanges\"><a href=\"http://zh.wikipedia.org/wiki/Special:%E6%9C%80%E8%BF%91%E6%9B%B4%E6%94%B9\" title=\"列出维基百科中的最近修改 [alt-shift-r]\" accesskey=\"r\">最近更改</a></li>\n\t\t\t<li id=\"n-randompage\"><a href=\"http://zh.wikipedia.org/wiki/Special:%E9%9A%8F%E6%9C%BA%E9%A1%B5%E9%9D%A2\" title=\"随机载入一个页面 [alt-shift-x]\" accesskey=\"x\">随机条目</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n<!-- /navigation -->\n\n<!-- help -->\n<div class=\"portal expanded\" id=\"p-help\">\n\t<h5 tabindex=\"2\">帮助</h5>\n\t<div style=\"display: block;\" class=\"body\">\n\t\t<ul>\n\t\t\t<li id=\"n-help\"><a href=\"http://zh.wikipedia.org/wiki/Help:%E7%9B%AE%E5%BD%95\" title=\"寻求帮助\">帮助</a></li>\n\t\t\t<li id=\"n-portal\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E7%A4%BE%E5%8C%BA%E4%B8%BB%E9%A1%B5\" title=\"关于本计划、你可以做什么、应该如何做\">维基社群</a></li>\n\t\t\t<li id=\"n-policy\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E6%96%B9%E9%87%9D%E8%88%87%E6%8C%87%E5%BC%95\">方针与指引</a></li>\n\t\t\t<li id=\"n-villagepump\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E4%BA%92%E5%8A%A9%E5%AE%A2%E6%A0%88\">互助客栈</a></li>\n\t\t\t<li id=\"n-Information_desk\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E8%A9%A2%E5%95%8F%E8%99%95\">询问处</a></li>\n\t\t\t<li id=\"n-conversion\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%AD%97%E8%AF%8D%E8%BD%AC%E6%8D%A2%E8%AF%B7%E6%B1%82%E6%88%96%E5%80%99%E9%80%89\">字词转换</a></li>\n\t\t\t<li id=\"n-IRC\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:IRC%E8%81%8A%E5%A4%A9%E9%A2%91%E9%81%93\">IRC即时聊天</a></li>\n\t\t\t<li id=\"n-contact\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E8%81%94%E7%B3%BB%E6%88%91%E4%BB%AC\">联系我们</a></li>\n\t\t\t<li id=\"n-about\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%85%B3%E4%BA%8E\">关于维基百科</a></li>\n\t\t\t<li id=\"n-sitesupport\"><a href=\"http://wikimediafoundation.org/wiki/Special:Landingcheck?landing_page=WMFJA085&amp;language=zh&amp;utm_source=donate&amp;utm_medium=sidebar&amp;utm_campaign=20101204SB002\" title=\"如果您在維基百科受益良多，您可以考慮資助我們\">资助维基百科</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n<!-- /help -->\n\n<!-- TOOLBOX -->\n<div class=\"portal collapsed\" id=\"p-tb\">\n\t<h5 tabindex=\"3\">工具</h5>\n\t<div class=\"body\">\n\t\t<ul>\n\t\t\t<li id=\"t-whatlinkshere\"><a href=\"http://zh.wikipedia.org/wiki/Special:%E9%93%BE%E5%85%A5%E9%A1%B5%E9%9D%A2/%E8%8B%B1%E5%9B%BD\" title=\"列出所有与本页相链的页面 [alt-shift-j]\" accesskey=\"j\">链入页面</a></li>\n\t\t\t<li id=\"t-recentchangeslinked\"><a href=\"http://zh.wikipedia.org/wiki/Special:%E9%93%BE%E5%87%BA%E6%9B%B4%E6%94%B9/%E8%8B%B1%E5%9B%BD\" title=\"页面链出所有页面的更改 [alt-shift-k]\" accesskey=\"k\">相关更改</a></li>\n\t\t\t<li id=\"t-upload\"><a href=\"http://zh.wikipedia.org/wiki/Project:%E4%B8%8A%E4%BC%A0\" title=\"上传图像或多媒体文件 [alt-shift-u]\" accesskey=\"u\">上传文件</a></li>\n\t\t\t<li id=\"t-specialpages\"><a href=\"http://zh.wikipedia.org/wiki/Special:%E7%89%B9%E6%AE%8A%E9%A1%B5%E9%9D%A2\" title=\"全部特殊页面的列表 [alt-shift-q]\" accesskey=\"q\">特殊页面</a></li>\n\t\t\t<li><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;printable=yes\" rel=\"alternate\">打印页面</a></li>\n\t\t\t<li id=\"t-permalink\"><a href=\"http://zh.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;oldid=20918917\" title=\"本页面该版本的永久链接\">永久链接</a></li>\n<li id=\"t-cite\"><a href=\"http://zh.wikipedia.org/w/index.php?title=Special:%E5%BC%95%E7%94%A8&amp;page=%E8%8B%B1%E5%9B%BD&amp;id=20918917\" title=\"关于如何引用此页的资讯\">引用此文</a></li>\t\t<li id=\"t-articlefeedback\"><a href=\"#mw-articlefeedback\">给本文评分</a></li></ul>\n\t</div>\n</div>\n\n<!-- /TOOLBOX -->\n\n<!-- LANGUAGES -->\n<div class=\"portal expanded\" id=\"p-lang\">\n\t<h5 tabindex=\"4\">其他语言</h5>\n\t<div style=\"display: block;\" class=\"body\">\n\t\t<ul>\n\t\t\t<li class=\"interwiki-ab\"><a href=\"http://ab.wikipedia.org/wiki/%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D0%B0_%D0%94%D1%83\" title=\"Британиа Ду\" hreflang=\"ab\" lang=\"ab\">Аҧсшәа</a></li>\n\t\t\t<li class=\"interwiki-af\"><a href=\"http://af.wikipedia.org/wiki/Verenigde_Koninkryk\" title=\"Verenigde Koninkryk\" hreflang=\"af\" lang=\"af\">Afrikaans</a></li>\n\t\t\t<li class=\"interwiki-ak\"><a href=\"http://ak.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"ak\" lang=\"ak\">Akan</a></li>\n\t\t\t<li class=\"interwiki-als\"><a href=\"http://als.wikipedia.org/wiki/Grossbritannien_und_Nordirland\" title=\"Grossbritannien und Nordirland\" hreflang=\"als\" lang=\"als\">Alemannisch</a></li>\n\t\t\t<li class=\"interwiki-am\"><a href=\"http://am.wikipedia.org/wiki/%E1%8B%A9%E1%8A%93%E1%8B%AD%E1%89%B5%E1%8B%B5_%E1%8A%AA%E1%8A%95%E1%8C%8D%E1%8B%B0%E1%88%9D\" title=\"ዩናይትድ ኪንግደም\" hreflang=\"am\" lang=\"am\">አማርኛ</a></li>\n\t\t\t<li class=\"interwiki-an\"><a href=\"http://an.wikipedia.org/wiki/Reino_Unito\" title=\"Reino Unito\" hreflang=\"an\" lang=\"an\">Aragonés</a></li>\n\t\t\t<li class=\"interwiki-ang\"><a href=\"http://ang.wikipedia.org/wiki/Ge%C4%81ned_Cyner%C4%ABce\" title=\"Geāned Cynerīce\" hreflang=\"ang\" lang=\"ang\">Ænglisc</a></li>\n\t\t\t<li class=\"interwiki-ar\"><a href=\"http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D9%85%D9%85%D9%84%D9%83%D8%A9_%D8%A7%D9%84%D9%85%D8%AA%D8%AD%D8%AF%D8%A9\" title=\"المملكة المتحدة\" hreflang=\"ar\" lang=\"ar\">العربية</a></li>\n\t\t\t<li class=\"interwiki-arc\"><a href=\"http://arc.wikipedia.org/wiki/%DC%A1%DC%A0%DC%9F%DC%98%DC%AC%DC%90_%DC%A1%DC%9A%DC%9D%DC%95%DC%AC%DC%90\" title=\"ܡܠܟܘܬܐ ܡܚܝܕܬܐ\" hreflang=\"arc\" lang=\"arc\">ܐܪܡܝܐ</a></li>\n\t\t\t<li class=\"interwiki-arz\"><a href=\"http://arz.wikipedia.org/wiki/%D8%A7%D9%84%D9%85%D9%85%D9%84%D9%83%D9%87_%D8%A7%D9%84%D9%85%D8%AA%D8%AD%D8%AF%D9%87\" title=\"المملكه المتحده\" hreflang=\"arz\" lang=\"arz\">مصرى</a></li>\n\t\t\t<li class=\"interwiki-ast\"><a href=\"http://ast.wikipedia.org/wiki/Reinu_Xun%C3%ADu\" title=\"Reinu Xuníu\" hreflang=\"ast\" lang=\"ast\">Asturianu</a></li>\n\t\t\t<li class=\"interwiki-az\"><a href=\"http://az.wikipedia.org/wiki/B%C3%B6y%C3%BCk_Britaniya\" title=\"Böyük Britaniya\" hreflang=\"az\" lang=\"az\">Azərbaycanca</a></li>\n\t\t\t<li class=\"interwiki-ba\"><a href=\"http://ba.wikipedia.org/wiki/%D0%91%D3%A9%D0%B9%D3%A9%D0%BA_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"Бөйөк Британия\" hreflang=\"ba\" lang=\"ba\">Башҡортса</a></li>\n\t\t\t<li class=\"interwiki-bar\"><a href=\"http://bar.wikipedia.org/wiki/Vaeinigts_Kinireich\" title=\"Vaeinigts Kinireich\" hreflang=\"bar\" lang=\"bar\">Boarisch</a></li>\n\t\t\t<li class=\"interwiki-bat-smg\"><a href=\"http://bat-smg.wikipedia.org/wiki/Jongt%C4%97n%C4%97_Karal%C4%ABst%C4%97\" title=\"Jongtėnė Karalīstė\" hreflang=\"bat-smg\" lang=\"bat-smg\">Žemaitėška</a></li>\n\t\t\t<li class=\"interwiki-bcl\"><a href=\"http://bcl.wikipedia.org/wiki/Reyno_Unido\" title=\"Reyno Unido\" hreflang=\"bcl\" lang=\"bcl\">Bikol Central</a></li>\n\t\t\t<li class=\"interwiki-be\"><a href=\"http://be.wikipedia.org/wiki/%D0%92%D1%8F%D0%BB%D1%96%D0%BA%D0%B0%D0%B1%D1%80%D1%8B%D1%82%D0%B0%D0%BD%D1%96%D1%8F\" title=\"Вялікабрытанія\" hreflang=\"be\" lang=\"be\">Беларуская</a></li>\n\t\t\t<li class=\"interwiki-be-x-old\"><a href=\"http://be-x-old.wikipedia.org/wiki/%D0%92%D1%8F%D0%BB%D1%96%D0%BA%D0%B0%D0%B1%D1%80%D1%8B%D1%82%D0%B0%D0%BD%D1%96%D1%8F\" title=\"Вялікабрытанія\" hreflang=\"be-x-old\" lang=\"be-x-old\">‪Беларуская (тарашкевіца)‬</a></li>\n\t\t\t<li class=\"interwiki-bg\"><a href=\"http://bg.wikipedia.org/wiki/%D0%9E%D0%B1%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%BE_%D0%BA%D1%80%D0%B0%D0%BB%D1%81%D1%82%D0%B2%D0%BE_%D0%92%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%B1%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F_%D0%B8_%D0%A1%D0%B5%D0%B2%D0%B5%D1%80%D0%BD%D0%B0_%D0%98%D1%80%D0%BB%D0%B0%D0%BD%D0%B4%D0%B8%D1%8F\" title=\"Обединено кралство Великобритания и Северна Ирландия\" hreflang=\"bg\" lang=\"bg\">Български</a></li>\n\t\t\t<li class=\"interwiki-bi\"><a href=\"http://bi.wikipedia.org/wiki/Unaeted_Kingdom\" title=\"Unaeted Kingdom\" hreflang=\"bi\" lang=\"bi\">Bislama</a></li>\n\t\t\t<li class=\"interwiki-bjn\"><a href=\"http://bjn.wikipedia.org/wiki/Britania_Raya\" title=\"Britania Raya\" hreflang=\"bjn\" lang=\"bjn\">Bahasa Banjar</a></li>\n\t\t\t<li class=\"interwiki-bn\"><a href=\"http://bn.wikipedia.org/wiki/%E0%A6%AF%E0%A7%81%E0%A6%95%E0%A7%8D%E0%A6%A4%E0%A6%B0%E0%A6%BE%E0%A6%9C%E0%A7%8D%E0%A6%AF\" title=\"যুক্তরাজ্য\" hreflang=\"bn\" lang=\"bn\">বাংলা</a></li>\n\t\t\t<li class=\"interwiki-bo\"><a href=\"http://bo.wikipedia.org/wiki/%E0%BD%91%E0%BD%96%E0%BE%B1%E0%BD%B2%E0%BD%93%E0%BC%8B%E0%BD%87%E0%BD%B2%E0%BC%8B%E0%BD%98%E0%BD%89%E0%BD%98%E0%BC%8B%E0%BD%A0%E0%BD%96%E0%BE%B2%E0%BD%BA%E0%BD%A3%E0%BC%8D\" title=\"དབྱིན་ཇི་མཉམ་འབྲེལ།\" hreflang=\"bo\" lang=\"bo\">བོད་ཡིག</a></li>\n\t\t\t<li class=\"interwiki-bpy\"><a href=\"http://bpy.wikipedia.org/wiki/%E0%A6%A4%E0%A6%BF%E0%A6%B2%E0%A6%AA%E0%A6%BE%E0%A6%B0%E0%A6%BE%E0%A6%9C%E0%A7%8D%E0%A6%AF\" title=\"তিলপারাজ্য\" hreflang=\"bpy\" lang=\"bpy\">ইমার ঠার/বিষ্ণুপ্রিয়া মণিপুরী</a></li>\n\t\t\t<li class=\"interwiki-br\"><a href=\"http://br.wikipedia.org/wiki/Rouantelezh-Unanet\" title=\"Rouantelezh-Unanet\" hreflang=\"br\" lang=\"br\">Brezhoneg</a></li>\n\t\t\t<li class=\"interwiki-bs\"><a href=\"http://bs.wikipedia.org/wiki/Ujedinjeno_Kraljevstvo_Velike_Britanije_i_Sjeverne_Irske\" title=\"Ujedinjeno Kraljevstvo Velike Britanije i Sjeverne Irske\" hreflang=\"bs\" lang=\"bs\">Bosanski</a></li>\n\t\t\t<li class=\"interwiki-bug\"><a href=\"http://bug.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"bug\" lang=\"bug\">ᨅᨔ ᨕᨘᨁᨗ</a></li>\n\t\t\t<li class=\"interwiki-ca\"><a href=\"http://ca.wikipedia.org/wiki/Regne_Unit\" title=\"Regne Unit\" hreflang=\"ca\" lang=\"ca\">Català</a></li>\n\t\t\t<li class=\"interwiki-cbk-zam\"><a href=\"http://cbk-zam.wikipedia.org/wiki/Reinos_Unidos_de_Gran_Britania_y_Norte_Irelandia\" title=\"Reinos Unidos de Gran Britania y Norte Irelandia\" hreflang=\"cbk-zam\" lang=\"cbk-zam\">Chavacano de Zamboanga</a></li>\n\t\t\t<li class=\"interwiki-cdo\"><a href=\"http://cdo.wikipedia.org/wiki/%C4%ACng-gu%C3%B3k\" title=\"Ĭng-guók\" hreflang=\"cdo\" lang=\"cdo\">Mìng-dĕ̤ng-ngṳ̄</a></li>\n\t\t\t<li class=\"interwiki-ce\"><a href=\"http://ce.wikipedia.org/wiki/%D0%9B%D0%B0%D0%BA%D1%85%D0%B0%D1%80%D0%B0%D0%B1%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8\" title=\"Лакхарабритани\" hreflang=\"ce\" lang=\"ce\">Нохчийн</a></li>\n\t\t\t<li class=\"interwiki-ceb\"><a href=\"http://ceb.wikipedia.org/wiki/Hiniusang_Gingharian\" title=\"Hiniusang Gingharian\" hreflang=\"ceb\" lang=\"ceb\">Cebuano</a></li>\n\t\t\t<li class=\"interwiki-chr\"><a href=\"http://chr.wikipedia.org/wiki/%E1%8E%A1%E1%8E%B5%E1%8F%8F%E1%8E%AF\" title=\"ᎡᎵᏏᎯ\" hreflang=\"chr\" lang=\"chr\">ᏣᎳᎩ</a></li>\n\t\t\t<li class=\"interwiki-ckb\"><a href=\"http://ckb.wikipedia.org/wiki/%D8%B4%D8%A7%D9%86%D8%B4%DB%8C%D9%86%DB%8C_%DB%8C%DB%95%DA%A9%DA%AF%D8%B1%D8%AA%D9%88%D9%88\" title=\"شانشینی یەکگرتوو\" hreflang=\"ckb\" lang=\"ckb\">کوردی</a></li>\n\t\t\t<li class=\"interwiki-co\"><a href=\"http://co.wikipedia.org/wiki/Regnu_Unitu\" title=\"Regnu Unitu\" hreflang=\"co\" lang=\"co\">Corsu</a></li>\n\t\t\t<li class=\"interwiki-crh\"><a href=\"http://crh.wikipedia.org/wiki/B%C3%BCy%C3%BCk_Britaniya\" title=\"Büyük Britaniya\" hreflang=\"crh\" lang=\"crh\">Qırımtatarca</a></li>\n\t\t\t<li class=\"interwiki-cs\"><a href=\"http://cs.wikipedia.org/wiki/Spojen%C3%A9_kr%C3%A1lovstv%C3%AD\" title=\"Spojené království\" hreflang=\"cs\" lang=\"cs\">Česky</a></li>\n\t\t\t<li class=\"interwiki-csb\"><a href=\"http://csb.wikipedia.org/wiki/Wi%C3%B4lg%C3%B4_Britanij%C3%B4\" title=\"Wiôlgô Britanijô\" hreflang=\"csb\" lang=\"csb\">Kaszëbsczi</a></li>\n\t\t\t<li class=\"interwiki-cu\"><a href=\"http://cu.wikipedia.org/wiki/%D0%92%D1%94%D0%BB%D0%B8%D0%BA%D0%B0_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D1%97%EA%99%97\" title=\"Вєлика Британїꙗ\" hreflang=\"cu\" lang=\"cu\">Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ</a></li>\n\t\t\t<li class=\"interwiki-cv\"><a href=\"http://cv.wikipedia.org/wiki/%D0%90%D1%81%D0%BB%C4%83_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8\" title=\"Аслă Британи\" hreflang=\"cv\" lang=\"cv\">Чӑвашла</a></li>\n\t\t\t<li class=\"interwiki-cy\"><a href=\"http://cy.wikipedia.org/wiki/Y_Deyrnas_Unedig\" title=\"Y Deyrnas Unedig\" hreflang=\"cy\" lang=\"cy\">Cymraeg</a></li>\n\t\t\t<li class=\"interwiki-da\"><a href=\"http://da.wikipedia.org/wiki/Storbritannien\" title=\"Storbritannien\" hreflang=\"da\" lang=\"da\">Dansk</a></li>\n\t\t\t<li class=\"interwiki-de\"><a href=\"http://de.wikipedia.org/wiki/Vereinigtes_K%C3%B6nigreich\" title=\"Vereinigtes Königreich\" hreflang=\"de\" lang=\"de\">Deutsch</a></li>\n\t\t\t<li class=\"interwiki-diq\"><a href=\"http://diq.wikipedia.org/wiki/Britanya_G%C4%B1rde\" title=\"Britanya Gırde\" hreflang=\"diq\" lang=\"diq\">Zazaki</a></li>\n\t\t\t<li class=\"interwiki-dsb\"><a href=\"http://dsb.wikipedia.org/wiki/Wjelika_Britaniska\" title=\"Wjelika Britaniska\" hreflang=\"dsb\" lang=\"dsb\">Dolnoserbski</a></li>\n\t\t\t<li class=\"interwiki-dv\"><a href=\"http://dv.wikipedia.org/wiki/%DE%94%DE%AA%DE%82%DE%A6%DE%87%DE%A8%DE%93%DE%AC%DE%91%DE%B0_%DE%86%DE%A8%DE%82%DE%B0%DE%8E%DE%B0%DE%91%DE%A6%DE%89%DE%B0\" title=\"ޔުނައިޓެޑް ކިންގްޑަމް\" hreflang=\"dv\" lang=\"dv\">ދިވެހިބަސް</a></li>\n\t\t\t<li class=\"interwiki-dz\"><a href=\"http://dz.wikipedia.org/wiki/%E0%BD%A1%E0%BD%B4%E0%BC%8B%E0%BD%93%E0%BD%A0%E0%BD%B2%E0%BC%8B%E0%BD%8A%E0%BD%BA%E0%BD%8A%E0%BC%8B%E0%BD%80%E0%BD%B2%E0%BD%84%E0%BC%8B%E0%BD%8C%E0%BD%98\" title=\"ཡུ་ནའི་ཊེཊ་ཀིང་ཌམ\" hreflang=\"dz\" lang=\"dz\">ཇོང་ཁ</a></li>\n\t\t\t<li class=\"interwiki-ee\"><a href=\"http://ee.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"ee\" lang=\"ee\">Eʋegbe</a></li>\n\t\t\t<li class=\"interwiki-el\"><a href=\"http://el.wikipedia.org/wiki/%CE%97%CE%BD%CF%89%CE%BC%CE%AD%CE%BD%CE%BF_%CE%92%CE%B1%CF%83%CE%AF%CE%BB%CE%B5%CE%B9%CE%BF\" title=\"Ηνωμένο Βασίλειο\" hreflang=\"el\" lang=\"el\">Ελληνικά</a></li>\n\t\t\t<li title=\"此条目在此语言版本中为优良条目\" class=\"interwiki-en GA\"><a href=\"http://en.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"en\" lang=\"en\">English</a></li>\n\t\t\t<li class=\"interwiki-eo\"><a href=\"http://eo.wikipedia.org/wiki/Unui%C4%9Dinta_Re%C4%9Dlando\" title=\"Unuiĝinta Reĝlando\" hreflang=\"eo\" lang=\"eo\">Esperanto</a></li>\n\t\t\t<li title=\"此条目在此语言版本中为特色条目\" class=\"interwiki-es FA\"><a href=\"http://es.wikipedia.org/wiki/Reino_Unido\" title=\"Reino Unido\" hreflang=\"es\" lang=\"es\">Español</a></li>\n\t\t\t<li class=\"interwiki-et\"><a href=\"http://et.wikipedia.org/wiki/Suurbritannia\" title=\"Suurbritannia\" hreflang=\"et\" lang=\"et\">Eesti</a></li>\n\t\t\t<li class=\"interwiki-eu\"><a href=\"http://eu.wikipedia.org/wiki/Erresuma_Batua\" title=\"Erresuma Batua\" hreflang=\"eu\" lang=\"eu\">Euskara</a></li>\n\t\t\t<li class=\"interwiki-ext\"><a href=\"http://ext.wikipedia.org/wiki/R%C3%A9inu_Uniu\" title=\"Réinu Uniu\" hreflang=\"ext\" lang=\"ext\">Estremeñu</a></li>\n\t\t\t<li class=\"interwiki-fa\"><a href=\"http://fa.wikipedia.org/wiki/%D8%A8%D8%B1%DB%8C%D8%AA%D8%A7%D9%86%DB%8C%D8%A7\" title=\"بریتانیا\" hreflang=\"fa\" lang=\"fa\">فارسی</a></li>\n\t\t\t<li class=\"interwiki-fi\"><a href=\"http://fi.wikipedia.org/wiki/Yhdistynyt_kuningaskunta\" title=\"Yhdistynyt kuningaskunta\" hreflang=\"fi\" lang=\"fi\">Suomi</a></li>\n\t\t\t<li class=\"interwiki-fiu-vro\"><a href=\"http://fiu-vro.wikipedia.org/wiki/%C3%9Ctiskuningriik\" title=\"Ütiskuningriik\" hreflang=\"fiu-vro\" lang=\"fiu-vro\">Võro</a></li>\n\t\t\t<li class=\"interwiki-fo\"><a href=\"http://fo.wikipedia.org/wiki/St%C3%B3ra_Bretland\" title=\"Stóra Bretland\" hreflang=\"fo\" lang=\"fo\">Føroyskt</a></li>\n\t\t\t<li class=\"interwiki-fr\"><a href=\"http://fr.wikipedia.org/wiki/Royaume-Uni\" title=\"Royaume-Uni\" hreflang=\"fr\" lang=\"fr\">Français</a></li>\n\t\t\t<li class=\"interwiki-frp\"><a href=\"http://frp.wikipedia.org/wiki/Roy%C3%B4mo-Uni\" title=\"Royômo-Uni\" hreflang=\"frp\" lang=\"frp\">Arpetan</a></li>\n\t\t\t<li class=\"interwiki-frr\"><a href=\"http://frr.wikipedia.org/wiki/Feriind_Kiningrik\" title=\"Feriind Kiningrik\" hreflang=\"frr\" lang=\"frr\">Nordfriisk</a></li>\n\t\t\t<li class=\"interwiki-fur\"><a href=\"http://fur.wikipedia.org/wiki/Ream_Un%C3%AEt\" title=\"Ream Unît\" hreflang=\"fur\" lang=\"fur\">Furlan</a></li>\n\t\t\t<li class=\"interwiki-fy\"><a href=\"http://fy.wikipedia.org/wiki/Grut-Brittanje\" title=\"Grut-Brittanje\" hreflang=\"fy\" lang=\"fy\">Frysk</a></li>\n\t\t\t<li class=\"interwiki-ga\"><a href=\"http://ga.wikipedia.org/wiki/An_R%C3%ADocht_Aontaithe\" title=\"An Ríocht Aontaithe\" hreflang=\"ga\" lang=\"ga\">Gaeilge</a></li>\n\t\t\t<li class=\"interwiki-gag\"><a href=\"http://gag.wikipedia.org/wiki/B%C3%BC%C3%BCk_Britaniya\" title=\"Büük Britaniya\" hreflang=\"gag\" lang=\"gag\">Gagauz</a></li>\n\t\t\t<li class=\"interwiki-gan\"><a href=\"http://gan.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B\" title=\"英國\" hreflang=\"gan\" lang=\"gan\">贛語</a></li>\n\t\t\t<li class=\"interwiki-gd\"><a href=\"http://gd.wikipedia.org/wiki/An_R%C3%ACoghachd_Aonaichte\" title=\"An Rìoghachd Aonaichte\" hreflang=\"gd\" lang=\"gd\">Gàidhlig</a></li>\n\t\t\t<li class=\"interwiki-gl\"><a href=\"http://gl.wikipedia.org/wiki/Reino_Unido_-_United_Kingdom\" title=\"Reino Unido - United Kingdom\" hreflang=\"gl\" lang=\"gl\">Galego</a></li>\n\t\t\t<li class=\"interwiki-gu\"><a href=\"http://gu.wikipedia.org/wiki/%E0%AA%AF%E0%AB%81%E0%AA%A8%E0%AA%BE%E0%AA%87%E0%AA%9F%E0%AB%87%E0%AA%A1_%E0%AA%95%E0%AA%BF%E0%AA%82%E0%AA%97%E0%AA%A1%E0%AA%AE\" title=\"યુનાઇટેડ કિંગડમ\" hreflang=\"gu\" lang=\"gu\">ગુજરાતી</a></li>\n\t\t\t<li title=\"此条目在此语言版本中为特色条目\" class=\"interwiki-gv FA\"><a href=\"http://gv.wikipedia.org/wiki/Reeriaght_Unnaneysit\" title=\"Reeriaght Unnaneysit\" hreflang=\"gv\" lang=\"gv\">Gaelg</a></li>\n\t\t\t<li class=\"interwiki-ha\"><a href=\"http://ha.wikipedia.org/wiki/Birtaniya\" title=\"Birtaniya\" hreflang=\"ha\" lang=\"ha\">هَوُسَ</a></li>\n\t\t\t<li class=\"interwiki-hak\"><a href=\"http://hak.wikipedia.org/wiki/Y%C3%AEn-koet\" title=\"Yîn-koet\" hreflang=\"hak\" lang=\"hak\">Hak-kâ-fa</a></li>\n\t\t\t<li class=\"interwiki-haw\"><a href=\"http://haw.wikipedia.org/wiki/Aupuni_M%C5%8D%CA%BB%C4%AB_Hui_P%C5%AB_%CA%BBia\" title=\"Aupuni Mōʻī Hui Pū ʻia\" hreflang=\"haw\" lang=\"haw\">Hawai`i</a></li>\n\t\t\t<li class=\"interwiki-he\"><a href=\"http://he.wikipedia.org/wiki/%D7%94%D7%9E%D7%9E%D7%9C%D7%9B%D7%94_%D7%94%D7%9E%D7%90%D7%95%D7%97%D7%93%D7%AA\" title=\"הממלכה המאוחדת\" hreflang=\"he\" lang=\"he\">עברית</a></li>\n\t\t\t<li class=\"interwiki-hi\"><a href=\"http://hi.wikipedia.org/wiki/%E0%A4%B8%E0%A4%82%E0%A4%AF%E0%A5%81%E0%A4%95%E0%A5%8D%E0%A4%A4_%E0%A4%B0%E0%A4%BE%E0%A4%9C%E0%A4%B6%E0%A4%BE%E0%A4%B9%E0%A5%80\" title=\"संयुक्त राजशाही\" hreflang=\"hi\" lang=\"hi\">हिन्दी</a></li>\n\t\t\t<li class=\"interwiki-hif\"><a href=\"http://hif.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"hif\" lang=\"hif\">Fiji Hindi</a></li>\n\t\t\t<li class=\"interwiki-hr\"><a href=\"http://hr.wikipedia.org/wiki/Ujedinjeno_Kraljevstvo\" title=\"Ujedinjeno Kraljevstvo\" hreflang=\"hr\" lang=\"hr\">Hrvatski</a></li>\n\t\t\t<li class=\"interwiki-hsb\"><a href=\"http://hsb.wikipedia.org/wiki/Zjedno%C4%87ene_kralestwo\" title=\"Zjednoćene kralestwo\" hreflang=\"hsb\" lang=\"hsb\">Hornjoserbsce</a></li>\n\t\t\t<li class=\"interwiki-ht\"><a href=\"http://ht.wikipedia.org/wiki/Way%C3%B2m_Ini\" title=\"Wayòm Ini\" hreflang=\"ht\" lang=\"ht\">Kreyòl ayisyen</a></li>\n\t\t\t<li class=\"interwiki-hu\"><a href=\"http://hu.wikipedia.org/wiki/Egyes%C3%BClt_Kir%C3%A1lys%C3%A1g\" title=\"Egyesült Királyság\" hreflang=\"hu\" lang=\"hu\">Magyar</a></li>\n\t\t\t<li class=\"interwiki-hy\"><a href=\"http://hy.wikipedia.org/wiki/%D5%84%D5%AB%D5%A1%D6%81%D5%B5%D5%A1%D5%AC_%D4%B9%D5%A1%D5%A3%D5%A1%D5%BE%D5%B8%D6%80%D5%B8%D6%82%D5%A9%D5%B5%D5%B8%D6%82%D5%B6\" title=\"Միացյալ Թագավորություն\" hreflang=\"hy\" lang=\"hy\">Հայերեն</a></li>\n\t\t\t<li class=\"interwiki-ia\"><a href=\"http://ia.wikipedia.org/wiki/Regno_Unite\" title=\"Regno Unite\" hreflang=\"ia\" lang=\"ia\">Interlingua</a></li>\n\t\t\t<li class=\"interwiki-id\"><a href=\"http://id.wikipedia.org/wiki/Britania_Raya\" title=\"Britania Raya\" hreflang=\"id\" lang=\"id\">Bahasa Indonesia</a></li>\n\t\t\t<li class=\"interwiki-ie\"><a href=\"http://ie.wikipedia.org/wiki/Reyatu_Unit\" title=\"Reyatu Unit\" hreflang=\"ie\" lang=\"ie\">Interlingue</a></li>\n\t\t\t<li class=\"interwiki-ig\"><a href=\"http://ig.wikipedia.org/wiki/Obodo%C3%A9z%C3%A8_N%C3%A0_Of%C3%BA\" title=\"Obodoézè Nà Ofú\" hreflang=\"ig\" lang=\"ig\">Igbo</a></li>\n\t\t\t<li class=\"interwiki-ilo\"><a href=\"http://ilo.wikipedia.org/wiki/Nagkaykaysa_a_Pagarian\" title=\"Nagkaykaysa a Pagarian\" hreflang=\"ilo\" lang=\"ilo\">Ilokano</a></li>\n\t\t\t<li class=\"interwiki-io\"><a href=\"http://io.wikipedia.org/wiki/Unionita_Rejio\" title=\"Unionita Rejio\" hreflang=\"io\" lang=\"io\">Ido</a></li>\n\t\t\t<li class=\"interwiki-is\"><a href=\"http://is.wikipedia.org/wiki/Bretland\" title=\"Bretland\" hreflang=\"is\" lang=\"is\">Íslenska</a></li>\n\t\t\t<li class=\"interwiki-it\"><a href=\"http://it.wikipedia.org/wiki/Regno_Unito\" title=\"Regno Unito\" hreflang=\"it\" lang=\"it\">Italiano</a></li>\n\t\t\t<li class=\"interwiki-ja\"><a href=\"http://ja.wikipedia.org/wiki/%E3%82%A4%E3%82%AE%E3%83%AA%E3%82%B9\" title=\"イギリス\" hreflang=\"ja\" lang=\"ja\">日本語</a></li>\n\t\t\t<li class=\"interwiki-jbo\"><a href=\"http://jbo.wikipedia.org/wiki/ritygu%27e\" title=\"ritygu'e\" hreflang=\"jbo\" lang=\"jbo\">Lojban</a></li>\n\t\t\t<li class=\"interwiki-jv\"><a href=\"http://jv.wikipedia.org/wiki/Britania_Raya\" title=\"Britania Raya\" hreflang=\"jv\" lang=\"jv\">Basa Jawa</a></li>\n\t\t\t<li class=\"interwiki-ka\"><a href=\"http://ka.wikipedia.org/wiki/%E1%83%92%E1%83%90%E1%83%94%E1%83%A0%E1%83%97%E1%83%98%E1%83%90%E1%83%9C%E1%83%94%E1%83%91%E1%83%A3%E1%83%9A%E1%83%98_%E1%83%A1%E1%83%90%E1%83%9B%E1%83%94%E1%83%A4%E1%83%9D\" title=\"გაერთიანებული სამეფო\" hreflang=\"ka\" lang=\"ka\">ქართული</a></li>\n\t\t\t<li class=\"interwiki-kab\"><a href=\"http://kab.wikipedia.org/wiki/Legliz\" title=\"Legliz\" hreflang=\"kab\" lang=\"kab\">Taqbaylit</a></li>\n\t\t\t<li class=\"interwiki-kbd\"><a href=\"http://kbd.wikipedia.org/wiki/%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8D%D1%88%D1%85%D1%83%D1%8D\" title=\"Британиэшхуэ\" hreflang=\"kbd\" lang=\"kbd\">Адыгэбзэ</a></li>\n\t\t\t<li class=\"interwiki-kg\"><a href=\"http://kg.wikipedia.org/wiki/Royaume-Uni\" title=\"Royaume-Uni\" hreflang=\"kg\" lang=\"kg\">Kongo</a></li>\n\t\t\t<li class=\"interwiki-kk\"><a href=\"http://kk.wikipedia.org/wiki/%D2%9A%D2%B1%D1%80%D0%B0%D0%BC%D0%B0_%D0%9F%D0%B0%D1%82%D1%88%D0%B0%D0%BB%D1%8B%D2%9B\" title=\"Құрама Патшалық\" hreflang=\"kk\" lang=\"kk\">Қазақша</a></li>\n\t\t\t<li class=\"interwiki-kl\"><a href=\"http://kl.wikipedia.org/wiki/Tuluit_Nunaat\" title=\"Tuluit Nunaat\" hreflang=\"kl\" lang=\"kl\">Kalaallisut</a></li>\n\t\t\t<li class=\"interwiki-km\"><a href=\"http://km.wikipedia.org/wiki/%E1%9E%9A%E1%9E%B6%E1%9E%87%E1%9E%B6%E1%9E%8E%E1%9E%B6%E1%9E%85%E1%9E%80%E1%9F%92%E1%9E%9A%E1%9E%9A%E1%9E%BD%E1%9E%98\" title=\"រាជាណាចក្ររួម\" hreflang=\"km\" lang=\"km\">ភាសាខ្មែរ</a></li>\n\t\t\t<li class=\"interwiki-kn\"><a href=\"http://kn.wikipedia.org/wiki/%E0%B2%AF%E0%B3%81%E0%B2%A8%E0%B3%88%E0%B2%9F%E0%B3%86%E0%B2%A1%E0%B3%8D_%E0%B2%95%E0%B2%BF%E0%B2%82%E0%B2%97%E0%B3%8D%E2%80%8C%E0%B2%A1%E0%B2%82\" title=\"ಯುನೈಟೆಡ್ ಕಿಂಗ್‌ಡಂ\" hreflang=\"kn\" lang=\"kn\">ಕನ್ನಡ</a></li>\n\t\t\t<li class=\"interwiki-ko\"><a href=\"http://ko.wikipedia.org/wiki/%EC%98%81%EA%B5%AD\" title=\"영국\" hreflang=\"ko\" lang=\"ko\">한국어</a></li>\n\t\t\t<li class=\"interwiki-koi\"><a href=\"http://koi.wikipedia.org/wiki/%D0%AB%D0%B4%D0%B6%D1%8B%D1%82_%D0%91%D1%80%D0%B8%D1%82%D0%BC%D1%83\" title=\"Ыджыт Бритму\" hreflang=\"koi\" lang=\"koi\">Перем Коми</a></li>\n\t\t\t<li class=\"interwiki-krc\"><a href=\"http://krc.wikipedia.org/wiki/%D0%A3%D0%BB%D0%BB%D1%83_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"Уллу Британия\" hreflang=\"krc\" lang=\"krc\">Къарачай-Малкъар</a></li>\n\t\t\t<li class=\"interwiki-ksh\"><a href=\"http://ksh.wikipedia.org/wiki/Jru%C3%9Fbritannie\" title=\"Jrußbritannie\" hreflang=\"ksh\" lang=\"ksh\">Ripoarisch</a></li>\n\t\t\t<li class=\"interwiki-ku\"><a href=\"http://ku.wikipedia.org/wiki/Keyaniya_Yekb%C3%BBy%C3%AE\" title=\"Keyaniya Yekbûyî\" hreflang=\"ku\" lang=\"ku\">Kurdî</a></li>\n\t\t\t<li class=\"interwiki-kv\"><a href=\"http://kv.wikipedia.org/wiki/%D0%AB%D0%B4%D0%B6%D1%8B%D0%B4_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"Ыджыд Британия\" hreflang=\"kv\" lang=\"kv\">Коми</a></li>\n\t\t\t<li class=\"interwiki-kw\"><a href=\"http://kw.wikipedia.org/wiki/Ruwvaneth_Unys\" title=\"Ruwvaneth Unys\" hreflang=\"kw\" lang=\"kw\">Kernowek</a></li>\n\t\t\t<li class=\"interwiki-ky\"><a href=\"http://ky.wikipedia.org/wiki/%D0%A3%D0%BB%D1%83%D1%83_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F_%D0%B6%D0%B0%D0%BD%D0%B0_%D0%A2%D2%AF%D0%BD%D0%B4%D2%AF%D0%BA_%D0%98%D1%80%D0%BB%D0%B0%D0%BD%D0%B4%D0%B8%D1%8F\" title=\"Улуу Британия жана Түндүк Ирландия\" hreflang=\"ky\" lang=\"ky\">Кыргызча</a></li>\n\t\t\t<li class=\"interwiki-la\"><a href=\"http://la.wikipedia.org/wiki/Britanniarum_Regnum\" title=\"Britanniarum Regnum\" hreflang=\"la\" lang=\"la\">Latina</a></li>\n\t\t\t<li class=\"interwiki-lad\"><a href=\"http://lad.wikipedia.org/wiki/Reyno_Unido\" title=\"Reyno Unido\" hreflang=\"lad\" lang=\"lad\">Ladino</a></li>\n\t\t\t<li class=\"interwiki-lb\"><a href=\"http://lb.wikipedia.org/wiki/Groussbritannien_an_Nordirland\" title=\"Groussbritannien an Nordirland\" hreflang=\"lb\" lang=\"lb\">Lëtzebuergesch</a></li>\n\t\t\t<li class=\"interwiki-lez\"><a href=\"http://lez.wikipedia.org/wiki/%D0%A7%D3%80%D0%B5%D1%85%D0%B8%D0%B1%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"ЧӀехибритания\" hreflang=\"lez\" lang=\"lez\">Лезги</a></li>\n\t\t\t<li class=\"interwiki-li\"><a href=\"http://li.wikipedia.org/wiki/Vereineg_Keuninkriek\" title=\"Vereineg Keuninkriek\" hreflang=\"li\" lang=\"li\">Limburgs</a></li>\n\t\t\t<li class=\"interwiki-lij\"><a href=\"http://lij.wikipedia.org/wiki/Regno_Un%C3%AFo\" title=\"Regno Unïo\" hreflang=\"lij\" lang=\"lij\">Ligure</a></li>\n\t\t\t<li class=\"interwiki-lmo\"><a href=\"http://lmo.wikipedia.org/wiki/Regn_%C3%9Cn%C3%AC\" title=\"Regn Ünì\" hreflang=\"lmo\" lang=\"lmo\">Lumbaart</a></li>\n\t\t\t<li class=\"interwiki-ln\"><a href=\"http://ln.wikipedia.org/wiki/Ing%C9%9Bl%C9%9B%CC%81t%C9%9Bl%C9%9B\" title=\"Ingɛlɛ́tɛlɛ\" hreflang=\"ln\" lang=\"ln\">Lingála</a></li>\n\t\t\t<li class=\"interwiki-lt\"><a href=\"http://lt.wikipedia.org/wiki/Jungtin%C4%97_Karalyst%C4%97\" title=\"Jungtinė Karalystė\" hreflang=\"lt\" lang=\"lt\">Lietuvių</a></li>\n\t\t\t<li class=\"interwiki-ltg\"><a href=\"http://ltg.wikipedia.org/wiki/Lelbrytaneja\" title=\"Lelbrytaneja\" hreflang=\"ltg\" lang=\"ltg\">Latgaļu</a></li>\n\t\t\t<li class=\"interwiki-lv\"><a href=\"http://lv.wikipedia.org/wiki/Apvienot%C4%81_Karaliste\" title=\"Apvienotā Karaliste\" hreflang=\"lv\" lang=\"lv\">Latviešu</a></li>\n\t\t\t<li class=\"interwiki-mg\"><a href=\"http://mg.wikipedia.org/wiki/Fanjakana_Mitambatra\" title=\"Fanjakana Mitambatra\" hreflang=\"mg\" lang=\"mg\">Malagasy</a></li>\n\t\t\t<li class=\"interwiki-mhr\"><a href=\"http://mhr.wikipedia.org/wiki/%D0%A3%D1%88%D1%8B%D0%BC%D0%BE_%D0%9A%D0%BE%D1%80%D0%BE%D0%BB%D0%B5%D0%B2%D1%81%D1%82%D0%B2%D0%B5\" title=\"Ушымо Королевстве\" hreflang=\"mhr\" lang=\"mhr\">Олык Марий</a></li>\n\t\t\t<li class=\"interwiki-mi\"><a href=\"http://mi.wikipedia.org/wiki/K%C4%ABngitanga_Kotahi\" title=\"Kīngitanga Kotahi\" hreflang=\"mi\" lang=\"mi\">Māori</a></li>\n\t\t\t<li class=\"interwiki-mk\"><a href=\"http://mk.wikipedia.org/wiki/%D0%9E%D0%B1%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D1%82%D0%BE_%D0%9A%D1%80%D0%B0%D0%BB%D1%81%D1%82%D0%B2%D0%BE\" title=\"Обединето Кралство\" hreflang=\"mk\" lang=\"mk\">Македонски</a></li>\n\t\t\t<li class=\"interwiki-ml\"><a href=\"http://ml.wikipedia.org/wiki/%E0%B4%AF%E0%B5%81%E0%B4%A3%E0%B5%88%E0%B4%B1%E0%B5%8D%E0%B4%B1%E0%B4%A1%E0%B5%8D_%E0%B4%95%E0%B4%BF%E0%B4%99%E0%B5%8D%E0%B4%A1%E0%B4%82\" title=\"യുണൈറ്റഡ് കിങ്ഡം\" hreflang=\"ml\" lang=\"ml\">മലയാളം</a></li>\n\t\t\t<li class=\"interwiki-mn\"><a href=\"http://mn.wikipedia.org/wiki/%D0%9D%D1%8D%D0%B3%D0%B4%D1%81%D1%8D%D0%BD_%D0%92%D0%B0%D0%BD%D1%82_%D0%A3%D0%BB%D1%81\" title=\"Нэгдсэн Вант Улс\" hreflang=\"mn\" lang=\"mn\">Монгол</a></li>\n\t\t\t<li class=\"interwiki-mr\"><a href=\"http://mr.wikipedia.org/wiki/%E0%A4%AF%E0%A5%81%E0%A4%A8%E0%A4%BE%E0%A4%AF%E0%A4%9F%E0%A5%87%E0%A4%A1_%E0%A4%95%E0%A4%BF%E0%A4%82%E0%A4%97%E0%A5%8D%E0%A4%A1%E0%A4%AE\" title=\"युनायटेड किंग्डम\" hreflang=\"mr\" lang=\"mr\">मराठी</a></li>\n\t\t\t<li class=\"interwiki-mrj\"><a href=\"http://mrj.wikipedia.org/wiki/%D0%9A%D0%BE%D0%B3%D0%BE_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8\" title=\"Кого Британи\" hreflang=\"mrj\" lang=\"mrj\">Кырык мары</a></li>\n\t\t\t<li class=\"interwiki-ms\"><a href=\"http://ms.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"ms\" lang=\"ms\">Bahasa Melayu</a></li>\n\t\t\t<li class=\"interwiki-mt\"><a href=\"http://mt.wikipedia.org/wiki/Renju_Unit\" title=\"Renju Unit\" hreflang=\"mt\" lang=\"mt\">Malti</a></li>\n\t\t\t<li class=\"interwiki-mwl\"><a href=\"http://mwl.wikipedia.org/wiki/Reino_Ounido\" title=\"Reino Ounido\" hreflang=\"mwl\" lang=\"mwl\">Mirandés</a></li>\n\t\t\t<li class=\"interwiki-my\"><a href=\"http://my.wikipedia.org/wiki/%E1%80%9A%E1%80%B0%E1%80%94%E1%80%AD%E1%80%AF%E1%80%80%E1%80%BA%E1%80%90%E1%80%80%E1%80%BA_%E1%80%80%E1%80%84%E1%80%BA%E1%80%B8%E1%80%92%E1%80%99%E1%80%BA%E1%80%B8\" title=\"ယူနိုက်တက် ကင်းဒမ်း\" hreflang=\"my\" lang=\"my\">မြန်မာဘာသာ</a></li>\n\t\t\t<li class=\"interwiki-mzn\"><a href=\"http://mzn.wikipedia.org/wiki/%D8%A8%D8%B1%DB%8C%D8%AA%D8%A7%D9%86%DB%8C%D8%A7\" title=\"بریتانیا\" hreflang=\"mzn\" lang=\"mzn\">مازِرونی</a></li>\n\t\t\t<li class=\"interwiki-na\"><a href=\"http://na.wikipedia.org/wiki/Ingerand\" title=\"Ingerand\" hreflang=\"na\" lang=\"na\">Dorerin Naoero</a></li>\n\t\t\t<li class=\"interwiki-nah\"><a href=\"http://nah.wikipedia.org/wiki/Tlacetil%C4%ABlli_Hu%C4%93yitlahtohc%C4%81y%C5%8Dtl\" title=\"Tlacetilīlli Huēyitlahtohcāyōtl\" hreflang=\"nah\" lang=\"nah\">Nāhuatl</a></li>\n\t\t\t<li class=\"interwiki-nap\"><a href=\"http://nap.wikipedia.org/wiki/Gran_Vretagna\" title=\"Gran Vretagna\" hreflang=\"nap\" lang=\"nap\">Nnapulitano</a></li>\n\t\t\t<li class=\"interwiki-nds\"><a href=\"http://nds.wikipedia.org/wiki/Vereenigt_K%C3%B6nigriek_vun_Grootbritannien_un_Noordirland\" title=\"Vereenigt Königriek vun Grootbritannien un Noordirland\" hreflang=\"nds\" lang=\"nds\">Plattdüütsch</a></li>\n\t\t\t<li class=\"interwiki-nds-nl\"><a href=\"http://nds-nl.wikipedia.org/wiki/Verienigd_Keuninkriek\" title=\"Verienigd Keuninkriek\" hreflang=\"nds-nl\" lang=\"nds-nl\">Nedersaksisch</a></li>\n\t\t\t<li class=\"interwiki-ne\"><a href=\"http://ne.wikipedia.org/wiki/%E0%A4%B8%E0%A4%82%E0%A4%AF%E0%A5%81%E0%A4%95%E0%A5%8D%E0%A4%A4_%E0%A4%85%E0%A4%A7%E0%A4%BF%E0%A4%B0%E0%A4%BE%E0%A4%9C%E0%A5%8D%E0%A4%AF\" title=\"संयुक्त अधिराज्य\" hreflang=\"ne\" lang=\"ne\">नेपाली</a></li>\n\t\t\t<li class=\"interwiki-nl\"><a href=\"http://nl.wikipedia.org/wiki/Verenigd_Koninkrijk\" title=\"Verenigd Koninkrijk\" hreflang=\"nl\" lang=\"nl\">Nederlands</a></li>\n\t\t\t<li class=\"interwiki-nn\"><a href=\"http://nn.wikipedia.org/wiki/Storbritannia\" title=\"Storbritannia\" hreflang=\"nn\" lang=\"nn\">‪Norsk (nynorsk)‬</a></li>\n\t\t\t<li class=\"interwiki-no\"><a href=\"http://no.wikipedia.org/wiki/Storbritannia\" title=\"Storbritannia\" hreflang=\"no\" lang=\"no\">‪Norsk (bokmål)‬</a></li>\n\t\t\t<li class=\"interwiki-nov\"><a href=\"http://nov.wikipedia.org/wiki/Unionati_Regia\" title=\"Unionati Regia\" hreflang=\"nov\" lang=\"nov\">Novial</a></li>\n\t\t\t<li class=\"interwiki-nrm\"><a href=\"http://nrm.wikipedia.org/wiki/Rouoyaume_Unni\" title=\"Rouoyaume Unni\" hreflang=\"nrm\" lang=\"nrm\">Nouormand</a></li>\n\t\t\t<li class=\"interwiki-nv\"><a href=\"http://nv.wikipedia.org/wiki/T%C3%B3_T%C3%A1%CA%BC_Din%C3%A9%CA%BCi%CA%BC_Bik%C3%A9yah\" title=\"Tó Táʼ Dinéʼiʼ Bikéyah\" hreflang=\"nv\" lang=\"nv\">Diné bizaad</a></li>\n\t\t\t<li class=\"interwiki-oc\"><a href=\"http://oc.wikipedia.org/wiki/Reialme_Unit\" title=\"Reialme Unit\" hreflang=\"oc\" lang=\"oc\">Occitan</a></li>\n\t\t\t<li class=\"interwiki-or\"><a href=\"http://or.wikipedia.org/wiki/%E0%AD%9F%E0%AD%81%E0%AC%A8%E0%AC%BE%E0%AC%87%E0%AC%9F%E0%AD%87%E0%AC%A1_%E0%AC%95%E0%AC%BF%E0%AC%99%E0%AD%8D%E0%AC%97%E0%AC%A1%E0%AC%AE\" title=\"ୟୁନାଇଟେଡ କିଙ୍ଗଡମ\" hreflang=\"or\" lang=\"or\">ଓଡ଼ିଆ</a></li>\n\t\t\t<li class=\"interwiki-os\"><a href=\"http://os.wikipedia.org/wiki/%D0%A1%D1%82%D1%8B%D1%80_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8\" title=\"Стыр Британи\" hreflang=\"os\" lang=\"os\">Ирон</a></li>\n\t\t\t<li class=\"interwiki-pa\"><a href=\"http://pa.wikipedia.org/wiki/%E0%A8%AF%E0%A9%82%E0%A8%A8%E0%A8%BE%E0%A8%88%E0%A8%9F%E0%A8%A1_%E0%A8%95%E0%A8%BF%E0%A9%B0%E0%A8%97%E0%A8%A1%E0%A8%AE\" title=\"ਯੂਨਾਈਟਡ ਕਿੰਗਡਮ\" hreflang=\"pa\" lang=\"pa\">ਪੰਜਾਬੀ</a></li>\n\t\t\t<li class=\"interwiki-pam\"><a href=\"http://pam.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"pam\" lang=\"pam\">Kapampangan</a></li>\n\t\t\t<li class=\"interwiki-pap\"><a href=\"http://pap.wikipedia.org/wiki/Reino_Uni\" title=\"Reino Uni\" hreflang=\"pap\" lang=\"pap\">Papiamentu</a></li>\n\t\t\t<li class=\"interwiki-pcd\"><a href=\"http://pcd.wikipedia.org/wiki/Ro%C3%A9y%C3%B4me-uni\" title=\"Roéyôme-uni\" hreflang=\"pcd\" lang=\"pcd\">Picard</a></li>\n\t\t\t<li class=\"interwiki-pih\"><a href=\"http://pih.wikipedia.org/wiki/Yunitid_Kingdum\" title=\"Yunitid Kingdum\" hreflang=\"pih\" lang=\"pih\">Norfuk / Pitkern</a></li>\n\t\t\t<li class=\"interwiki-pl\"><a href=\"http://pl.wikipedia.org/wiki/Wielka_Brytania\" title=\"Wielka Brytania\" hreflang=\"pl\" lang=\"pl\">Polski</a></li>\n\t\t\t<li class=\"interwiki-pms\"><a href=\"http://pms.wikipedia.org/wiki/Regn_Un%C3%AC\" title=\"Regn Unì\" hreflang=\"pms\" lang=\"pms\">Piemontèis</a></li>\n\t\t\t<li class=\"interwiki-pnb\"><a href=\"http://pnb.wikipedia.org/wiki/%D8%A8%D8%B1%D8%B7%D8%A7%D9%86%DB%8C%DB%81\" title=\"برطانیہ\" hreflang=\"pnb\" lang=\"pnb\">پنجابی</a></li>\n\t\t\t<li class=\"interwiki-pnt\"><a href=\"http://pnt.wikipedia.org/wiki/%CE%97%CE%BD%CF%89%CE%BC%CE%AD%CE%BD%CE%BF_%CE%92%CE%B1%CF%83%CE%AF%CE%BB%CE%B5%CE%B9%CE%BF\" title=\"Ηνωμένο Βασίλειο\" hreflang=\"pnt\" lang=\"pnt\">Ποντιακά</a></li>\n\t\t\t<li class=\"interwiki-ps\"><a href=\"http://ps.wikipedia.org/wiki/%D8%A8%D8%B1%D9%8A%D8%AA%D8%A7%D9%86%D9%8A%D8%A7\" title=\"بريتانيا\" hreflang=\"ps\" lang=\"ps\">پښتو</a></li>\n\t\t\t<li class=\"interwiki-pt\"><a href=\"http://pt.wikipedia.org/wiki/Reino_Unido\" title=\"Reino Unido\" hreflang=\"pt\" lang=\"pt\">Português</a></li>\n\t\t\t<li class=\"interwiki-qu\"><a href=\"http://qu.wikipedia.org/wiki/Hukllachasqa_Qhapaq_Suyu\" title=\"Hukllachasqa Qhapaq Suyu\" hreflang=\"qu\" lang=\"qu\">Runa Simi</a></li>\n\t\t\t<li class=\"interwiki-rm\"><a href=\"http://rm.wikipedia.org/wiki/Reginavel_Un%C3%AC\" title=\"Reginavel Unì\" hreflang=\"rm\" lang=\"rm\">Rumantsch</a></li>\n\t\t\t<li class=\"interwiki-rmy\"><a href=\"http://rmy.wikipedia.org/wiki/Phandlo_Thagaripen_la_Bare_Britaniyako_thai_le_Nordutne_Irlandesko\" title=\"Phandlo Thagaripen la Bare Britaniyako thai le Nordutne Irlandesko\" hreflang=\"rmy\" lang=\"rmy\">Romani</a></li>\n\t\t\t<li class=\"interwiki-ro\"><a href=\"http://ro.wikipedia.org/wiki/Regatul_Unit_al_Marii_Britanii_%C8%99i_al_Irlandei_de_Nord\" title=\"Regatul Unit al Marii Britanii și al Irlandei de Nord\" hreflang=\"ro\" lang=\"ro\">Română</a></li>\n\t\t\t<li class=\"interwiki-roa-rup\"><a href=\"http://roa-rup.wikipedia.org/wiki/Britania_Mari\" title=\"Britania Mari\" hreflang=\"roa-rup\" lang=\"roa-rup\">Armãneashce</a></li>\n\t\t\t<li class=\"interwiki-roa-tara\"><a href=\"http://roa-tara.wikipedia.org/wiki/Regne_Aun%C3%ACte\" title=\"Regne Aunìte\" hreflang=\"roa-tara\" lang=\"roa-tara\">Tarandíne</a></li>\n\t\t\t<li class=\"interwiki-ru\"><a href=\"http://ru.wikipedia.org/wiki/%D0%92%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%B1%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"Великобритания\" hreflang=\"ru\" lang=\"ru\">Русский</a></li>\n\t\t\t<li class=\"interwiki-rue\"><a href=\"http://rue.wikipedia.org/wiki/%D0%92%D0%B5%D0%BB%D0%B8%D0%BA%D0%B0_%D0%91%D1%80%D1%96%D1%82%D0%B0%D0%BD%D1%96%D1%8F\" title=\"Велика Брітанія\" hreflang=\"rue\" lang=\"rue\">Русиньскый</a></li>\n\t\t\t<li class=\"interwiki-rw\"><a href=\"http://rw.wikipedia.org/wiki/Ubwongereza\" title=\"Ubwongereza\" hreflang=\"rw\" lang=\"rw\">Kinyarwanda</a></li>\n\t\t\t<li class=\"interwiki-sah\"><a href=\"http://sah.wikipedia.org/wiki/%D0%A5%D0%BE%D0%BB%D0%B1%D0%BEh%D1%83%D0%BA%D1%82%D0%B0%D0%B0%D1%85_%D0%A5%D0%BE%D1%80%D1%83%D0%BE%D0%BB%D0%BB%D1%83%D0%BA\" title=\"Холбоhуктаах Хоруоллук\" hreflang=\"sah\" lang=\"sah\">Саха тыла</a></li>\n\t\t\t<li class=\"interwiki-sc\"><a href=\"http://sc.wikipedia.org/wiki/Rennu_Auniadu\" title=\"Rennu Auniadu\" hreflang=\"sc\" lang=\"sc\">Sardu</a></li>\n\t\t\t<li class=\"interwiki-scn\"><a href=\"http://scn.wikipedia.org/wiki/Regnu_Unitu\" title=\"Regnu Unitu\" hreflang=\"scn\" lang=\"scn\">Sicilianu</a></li>\n\t\t\t<li class=\"interwiki-sco\"><a href=\"http://sco.wikipedia.org/wiki/Unitit_Kinrick\" title=\"Unitit Kinrick\" hreflang=\"sco\" lang=\"sco\">Scots</a></li>\n\t\t\t<li class=\"interwiki-se\"><a href=\"http://se.wikipedia.org/wiki/Ovttastuvvan_gonagasriika\" title=\"Ovttastuvvan gonagasriika\" hreflang=\"se\" lang=\"se\">Sámegiella</a></li>\n\t\t\t<li class=\"interwiki-sh\"><a href=\"http://sh.wikipedia.org/wiki/Ujedinjeno_Kraljevstvo\" title=\"Ujedinjeno Kraljevstvo\" hreflang=\"sh\" lang=\"sh\">Srpskohrvatski / Српскохрватски</a></li>\n\t\t\t<li class=\"interwiki-si\"><a href=\"http://si.wikipedia.org/wiki/%E0%B6%B6%E0%B7%8A%E2%80%8D%E0%B6%BB%E0%B7%92%E0%B6%AD%E0%B7%8F%E0%B6%B1%E0%B7%8A%E2%80%8D%E0%B6%BA_%28%E0%B7%80%E0%B6%9A%E0%B7%8A%E2%80%8D%E0%B6%BB%E0%B7%9D%E0%B6%9A%E0%B7%8A%E0%B6%AD%E0%B7%92%E0%B7%84%E0%B6%BB%E0%B6%AB%E0%B6%BA%29\" title=\"බ්‍රිතාන්‍ය (වක්‍රෝක්තිහරණය)\" hreflang=\"si\" lang=\"si\">සිංහල</a></li>\n\t\t\t<li class=\"interwiki-simple\"><a href=\"http://simple.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"simple\" lang=\"simple\">Simple English</a></li>\n\t\t\t<li class=\"interwiki-sk\"><a href=\"http://sk.wikipedia.org/wiki/Spojen%C3%A9_kr%C3%A1%C4%BEovstvo\" title=\"Spojené kráľovstvo\" hreflang=\"sk\" lang=\"sk\">Slovenčina</a></li>\n\t\t\t<li class=\"interwiki-sl\"><a href=\"http://sl.wikipedia.org/wiki/Zdru%C5%BEeno_kraljestvo_Velike_Britanije_in_Severne_Irske\" title=\"Združeno kraljestvo Velike Britanije in Severne Irske\" hreflang=\"sl\" lang=\"sl\">Slovenščina</a></li>\n\t\t\t<li class=\"interwiki-so\"><a href=\"http://so.wikipedia.org/wiki/Midowga_boqortooyada_Britan\" title=\"Midowga boqortooyada Britan\" hreflang=\"so\" lang=\"so\">Soomaaliga</a></li>\n\t\t\t<li class=\"interwiki-sq\"><a href=\"http://sq.wikipedia.org/wiki/Britania_e_Madhe\" title=\"Britania e Madhe\" hreflang=\"sq\" lang=\"sq\">Shqip</a></li>\n\t\t\t<li class=\"interwiki-sr\"><a href=\"http://sr.wikipedia.org/wiki/%D0%A3%D1%98%D0%B5%D0%B4%D0%B8%D1%9A%D0%B5%D0%BD%D0%BE_%D0%9A%D1%80%D0%B0%D1%99%D0%B5%D0%B2%D1%81%D1%82%D0%B2%D0%BE\" title=\"Уједињено Краљевство\" hreflang=\"sr\" lang=\"sr\">Српски / Srpski</a></li>\n\t\t\t<li class=\"interwiki-srn\"><a href=\"http://srn.wikipedia.org/wiki/Ingriskondre\" title=\"Ingriskondre\" hreflang=\"srn\" lang=\"srn\">Sranantongo</a></li>\n\t\t\t<li class=\"interwiki-ss\"><a href=\"http://ss.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"ss\" lang=\"ss\">SiSwati</a></li>\n\t\t\t<li class=\"interwiki-stq\"><a href=\"http://stq.wikipedia.org/wiki/Fereeniged_K%C3%B6%C3%B6nichriek_fon_Groot-Britannien_un_Noudirlound\" title=\"Fereeniged Köönichriek fon Groot-Britannien un Noudirlound\" hreflang=\"stq\" lang=\"stq\">Seeltersk</a></li>\n\t\t\t<li class=\"interwiki-su\"><a href=\"http://su.wikipedia.org/wiki/Britania\" title=\"Britania\" hreflang=\"su\" lang=\"su\">Basa Sunda</a></li>\n\t\t\t<li class=\"interwiki-sv\"><a href=\"http://sv.wikipedia.org/wiki/Storbritannien\" title=\"Storbritannien\" hreflang=\"sv\" lang=\"sv\">Svenska</a></li>\n\t\t\t<li class=\"interwiki-sw\"><a href=\"http://sw.wikipedia.org/wiki/Ufalme_wa_Muungano\" title=\"Ufalme wa Muungano\" hreflang=\"sw\" lang=\"sw\">Kiswahili</a></li>\n\t\t\t<li class=\"interwiki-szl\"><a href=\"http://szl.wikipedia.org/wiki/Wjelgo_Bryta%C5%84ijo\" title=\"Wjelgo Brytańijo\" hreflang=\"szl\" lang=\"szl\">Ślůnski</a></li>\n\t\t\t<li title=\"此条目在此语言版本中为特色条目\" class=\"interwiki-ta FA\"><a href=\"http://ta.wikipedia.org/wiki/%E0%AE%90%E0%AE%95%E0%AF%8D%E0%AE%95%E0%AE%BF%E0%AE%AF_%E0%AE%87%E0%AE%B0%E0%AE%BE%E0%AE%9A%E0%AF%8D%E0%AE%9A%E0%AE%BF%E0%AE%AF%E0%AE%AE%E0%AF%8D\" title=\"ஐக்கிய இராச்சியம்\" hreflang=\"ta\" lang=\"ta\">தமிழ்</a></li>\n\t\t\t<li class=\"interwiki-te\"><a href=\"http://te.wikipedia.org/wiki/%E0%B0%AF%E0%B1%81%E0%B0%A8%E0%B1%88%E0%B0%9F%E0%B1%86%E0%B0%A1%E0%B1%8D_%E0%B0%95%E0%B0%BF%E0%B0%82%E0%B0%97%E0%B1%8D%E2%80%8C%E0%B0%A1%E0%B0%AE%E0%B1%8D\" title=\"యునైటెడ్ కింగ్‌డమ్\" hreflang=\"te\" lang=\"te\">తెలుగు</a></li>\n\t\t\t<li class=\"interwiki-tet\"><a href=\"http://tet.wikipedia.org/wiki/Reinu_Naklibur\" title=\"Reinu Naklibur\" hreflang=\"tet\" lang=\"tet\">Tetun</a></li>\n\t\t\t<li class=\"interwiki-tg\"><a href=\"http://tg.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B4%D1%88%D0%BE%D2%B3%D0%B8%D0%B8_%D0%9C%D1%83%D1%82%D1%82%D0%B0%D2%B3%D0%B8%D0%B4%D0%B0\" title=\"Подшоҳии Муттаҳида\" hreflang=\"tg\" lang=\"tg\">Тоҷикӣ</a></li>\n\t\t\t<li class=\"interwiki-th\"><a href=\"http://th.wikipedia.org/wiki/%E0%B8%AA%E0%B8%AB%E0%B8%A3%E0%B8%B2%E0%B8%8A%E0%B8%AD%E0%B8%B2%E0%B8%93%E0%B8%B2%E0%B8%88%E0%B8%B1%E0%B8%81%E0%B8%A3\" title=\"สหราชอาณาจักร\" hreflang=\"th\" lang=\"th\">ไทย</a></li>\n\t\t\t<li class=\"interwiki-tl\"><a href=\"http://tl.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"tl\" lang=\"tl\">Tagalog</a></li>\n\t\t\t<li class=\"interwiki-tpi\"><a href=\"http://tpi.wikipedia.org/wiki/Yunaitet_Kingdom\" title=\"Yunaitet Kingdom\" hreflang=\"tpi\" lang=\"tpi\">Tok Pisin</a></li>\n\t\t\t<li class=\"interwiki-tr\"><a href=\"http://tr.wikipedia.org/wiki/Birle%C5%9Fik_Krall%C4%B1k\" title=\"Birleşik Krallık\" hreflang=\"tr\" lang=\"tr\">Türkçe</a></li>\n\t\t\t<li class=\"interwiki-tt\"><a href=\"http://tt.wikipedia.org/wiki/%D0%91%D3%A9%D0%B5%D0%BA%D0%B1%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"Бөекбритания\" hreflang=\"tt\" lang=\"tt\">Татарча/Tatarça</a></li>\n\t\t\t<li class=\"interwiki-tw\"><a href=\"http://tw.wikipedia.org/wiki/United_Kingdom\" title=\"United Kingdom\" hreflang=\"tw\" lang=\"tw\">Twi</a></li>\n\t\t\t<li class=\"interwiki-ty\"><a href=\"http://ty.wikipedia.org/wiki/Parat%C4%81ne\" title=\"Paratāne\" hreflang=\"ty\" lang=\"ty\">Reo Mā`ohi</a></li>\n\t\t\t<li class=\"interwiki-udm\"><a href=\"http://udm.wikipedia.org/wiki/%D0%92%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%B1%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D0%B8%D1%8F\" title=\"Великобритания\" hreflang=\"udm\" lang=\"udm\">Удмурт</a></li>\n\t\t\t<li class=\"interwiki-ug\"><a href=\"http://ug.wikipedia.org/wiki/%D8%A8%DB%88%D9%8A%DB%88%D9%83_%D8%A8%DB%90%D8%B1%D9%89%D8%AA%D8%A7%D9%86%D9%89%D9%8A%DB%95\" title=\"بۈيۈك بېرىتانىيە\" hreflang=\"ug\" lang=\"ug\">ئۇيغۇرچە / Uyghurche</a></li>\n\t\t\t<li class=\"interwiki-uk\"><a href=\"http://uk.wikipedia.org/wiki/%D0%92%D0%B5%D0%BB%D0%B8%D0%BA%D0%B0_%D0%91%D1%80%D0%B8%D1%82%D0%B0%D0%BD%D1%96%D1%8F\" title=\"Велика Британія\" hreflang=\"uk\" lang=\"uk\">Українська</a></li>\n\t\t\t<li class=\"interwiki-ur\"><a href=\"http://ur.wikipedia.org/wiki/%D8%A8%D8%B1%D8%B7%D8%A7%D9%86%DB%8C%DB%81\" title=\"برطانیہ\" hreflang=\"ur\" lang=\"ur\">اردو</a></li>\n\t\t\t<li class=\"interwiki-uz\"><a href=\"http://uz.wikipedia.org/wiki/Birlashgan_Qirollik\" title=\"Birlashgan Qirollik\" hreflang=\"uz\" lang=\"uz\">Oʻzbek</a></li>\n\t\t\t<li class=\"interwiki-vec\"><a href=\"http://vec.wikipedia.org/wiki/Regno_Un%C3%ACo\" title=\"Regno Unìo\" hreflang=\"vec\" lang=\"vec\">Vèneto</a></li>\n\t\t\t<li class=\"interwiki-vep\"><a href=\"http://vep.wikipedia.org/wiki/Sur%27_Britanii\" title=\"Sur' Britanii\" hreflang=\"vep\" lang=\"vep\">Vepsän kel’</a></li>\n\t\t\t<li class=\"interwiki-vi\"><a href=\"http://vi.wikipedia.org/wiki/V%C6%B0%C6%A1ng_qu%E1%BB%91c_Li%C3%AAn_hi%E1%BB%87p_Anh_v%C3%A0_B%E1%BA%AFc_Ireland\" title=\"Vương quốc Liên hiệp Anh và Bắc Ireland\" hreflang=\"vi\" lang=\"vi\">Tiếng Việt</a></li>\n\t\t\t<li class=\"interwiki-vls\"><a href=\"http://vls.wikipedia.org/wiki/Ver%C3%AAnigd_Keunienkryk\" title=\"Verênigd Keunienkryk\" hreflang=\"vls\" lang=\"vls\">West-Vlams</a></li>\n\t\t\t<li class=\"interwiki-vo\"><a href=\"http://vo.wikipedia.org/wiki/Reg%C3%A4n_Pebal%C3%B6l\" title=\"Regän Pebalöl\" hreflang=\"vo\" lang=\"vo\">Volapük</a></li>\n\t\t\t<li class=\"interwiki-war\"><a href=\"http://war.wikipedia.org/wiki/Reino_Unido\" title=\"Reino Unido\" hreflang=\"war\" lang=\"war\">Winaray</a></li>\n\t\t\t<li class=\"interwiki-wo\"><a href=\"http://wo.wikipedia.org/wiki/Nguur-Yu-Bennoo\" title=\"Nguur-Yu-Bennoo\" hreflang=\"wo\" lang=\"wo\">Wolof</a></li>\n\t\t\t<li class=\"interwiki-wuu\"><a href=\"http://wuu.wikipedia.org/wiki/%E8%8B%B1%E5%9B%BD\" title=\"英国\" hreflang=\"wuu\" lang=\"wuu\">吴语</a></li>\n\t\t\t<li class=\"interwiki-xal\"><a href=\"http://xal.wikipedia.org/wiki/%D0%98%D0%BA_%D0%91%D1%80%D0%B8%D1%82%D0%B8%D1%88%D0%B8%D0%BD_%D0%B1%D0%BE%D0%BB%D0%BD_%D0%90%D1%80_%D0%93%D3%99%D3%99%D0%BB%D0%B3%D2%AF%D0%B4%D0%B8%D0%BD_%D0%9D%D0%B8%D0%B8%D1%86%D3%99%D1%82%D3%99_%D0%9D%D1%83%D1%82%D0%B3\" title=\"Ик Бритишин болн Ар Гәәлгүдин Ниицәтә Нутг\" hreflang=\"xal\" lang=\"xal\">Хальмг</a></li>\n\t\t\t<li class=\"interwiki-xmf\"><a href=\"http://xmf.wikipedia.org/wiki/%E1%83%92%E1%83%9D%E1%83%90%E1%83%A0%E1%83%97%E1%83%9D%E1%83%98%E1%83%90%E1%83%9C%E1%83%90%E1%83%A4%E1%83%98%E1%83%9A%E1%83%98_%E1%83%9D%E1%83%9B%E1%83%90%E1%83%A4%E1%83%94\" title=\"გოართოიანაფილი ომაფე\" hreflang=\"xmf\" lang=\"xmf\">მარგალური</a></li>\n\t\t\t<li title=\"此条目在此语言版本中为特色条目\" class=\"interwiki-yi FA\"><a href=\"http://yi.wikipedia.org/wiki/%D7%A4%D7%90%D7%A8%D7%90%D7%99%D7%99%D7%A0%D7%99%D7%92%D7%98%D7%A2_%D7%A7%D7%A2%D7%A0%D7%99%D7%92%D7%A8%D7%99%D7%99%D7%9A\" title=\"פאראייניגטע קעניגרייך\" hreflang=\"yi\" lang=\"yi\">ייִדיש</a></li>\n\t\t\t<li class=\"interwiki-yo\"><a href=\"http://yo.wikipedia.org/wiki/Il%E1%BA%B9%CC%80%E1%BB%8Dba_A%E1%B9%A3%E1%BB%8D%CC%80kan\" title=\"Ilẹ̀ọba Aṣọ̀kan\" hreflang=\"yo\" lang=\"yo\">Yorùbá</a></li>\n\t\t\t<li class=\"interwiki-za\"><a href=\"http://za.wikipedia.org/wiki/Yinghgoz\" title=\"Yinghgoz\" hreflang=\"za\" lang=\"za\">Vahcuengh</a></li>\n\t\t\t<li class=\"interwiki-zea\"><a href=\"http://zea.wikipedia.org/wiki/Vere%C3%AAnigd_Konienkriek\" title=\"Vereênigd Konienkriek\" hreflang=\"zea\" lang=\"zea\">Zeêuws</a></li>\n\t\t\t<li class=\"interwiki-zh-classical\"><a href=\"http://zh-classical.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B\" title=\"英國\" hreflang=\"zh-classical\" lang=\"zh-classical\">文言</a></li>\n\t\t\t<li class=\"interwiki-zh-min-nan\"><a href=\"http://zh-min-nan.wikipedia.org/wiki/Li%C3%A2n-ha%CC%8Dp_%C3%94ng-kok\" title=\"Liân-ha̍p Ông-kok\" hreflang=\"zh-min-nan\" lang=\"zh-min-nan\">Bân-lâm-gú</a></li>\n\t\t\t<li class=\"interwiki-zh-yue\"><a href=\"http://zh-yue.wikipedia.org/wiki/%E8%8B%B1%E5%9C%8B\" title=\"英國\" hreflang=\"zh-yue\" lang=\"zh-yue\">粵語</a></li>\n\t\t\t<li class=\"interwiki-zu\"><a href=\"http://zu.wikipedia.org/wiki/Umbuso_Ohlangeneyo\" title=\"Umbuso Ohlangeneyo\" hreflang=\"zu\" lang=\"zu\">isiZulu</a></li>\n\t\t</ul>\n\t</div>\n</div>\n\n<!-- /LANGUAGES -->\n\t\t\t</div>\n\t\t<!-- /panel -->\n\t\t<!-- footer -->\n\t\t<div id=\"footer\">\n\t\t\t\t\t\t\t<ul id=\"footer-info\">\n\t\t\t\t\t\t\t\t\t\t\t<li id=\"footer-info-lastmod\"> 本页面最后修订于2012年4月28日 (星期六) 12:15。<br></li>\n\t\t\t\t\t\t\t\t\t\t\t<li id=\"footer-info-copyright\">本站的全部文字在<a href=\"http://zh.wikipedia.org/wiki/Wikipedia:CC-by-sa-3.0%E5%8D%8F%E8%AE%AE%E6%96%87%E6%9C%AC\" title=\"Wikipedia:CC-by-sa-3.0协议文本\">知识共享 署名-相同方式共享 3.0协议</a><a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/3.0/deed.zh\" style=\"display: none;\"></a>之条款下提供，附加条款亦可能应用。（请参阅<a href=\"http://wikimediafoundation.org/wiki/%E4%BD%BF%E7%94%A8%E6%9D%A1%E6%AC%BE\">使用条款</a>）<br>\nWikipedia®和维基百科标志是<a href=\"http://wikimediafoundation.org/\">维基媒体基金会</a>的注册商标；维基™是维基媒体基金会的商标。<br>\n维基媒体基金会是在美国佛罗里达州登记的501(c)(3)<a href=\"http://wikimediafoundation.org/wiki/%E8%B5%84%E5%8A%A9%E7%9A%84%E5%85%8D%E7%A8%8E%E6%94%BF%E7%AD%96\">免税</a>、非营利、慈善机构。<br></li>\n\t\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t<ul id=\"footer-places\">\n\t\t\t\t\t\t\t\t\t\t\t<li id=\"footer-places-privacy\"><a href=\"http://wikimediafoundation.org/wiki/%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96\" title=\"wikimedia:隐私政策\">隐私政策</a></li>\n\t\t\t\t\t\t\t\t\t\t\t<li id=\"footer-places-about\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%85%B3%E4%BA%8E\" title=\"Wikipedia:关于\">关于维基百科</a></li>\n\t\t\t\t\t\t\t\t\t\t\t<li id=\"footer-places-disclaimer\"><a href=\"http://zh.wikipedia.org/wiki/Wikipedia:%E5%85%8D%E8%B4%A3%E5%A3%B0%E6%98%8E\" title=\"Wikipedia:免责声明\">免责声明</a></li>\n\t\t\t\t\t\t\t\t\t\t\t<li id=\"footer-places-mobileview\"><a href=\"http://zh.m.wikipedia.org/w/index.php?title=%E8%8B%B1%E5%9B%BD&amp;mobileaction=toggle_view_mobile\" class=\"noprint\">移动浏览</a></li>\n\t\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t\t\t\t<ul id=\"footer-icons\" class=\"noprint\">\n\t\t\t\t\t<li id=\"footer-copyrightico\">\n\t\t\t\t\t\t<a href=\"http://wikimediafoundation.org/\"><img src=\"England%28Chinese%29_files/wikimedia-button.png\" alt=\"Wikimedia Foundation\" height=\"31\" width=\"88\"></a>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li id=\"footer-poweredbyico\">\n\t\t\t\t\t\t<a href=\"http://www.mediawiki.org/\"><img src=\"England%28Chinese%29_files/poweredby_mediawiki_88x31.png\" alt=\"Powered by MediaWiki\" height=\"31\" width=\"88\"></a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t\t\t<div style=\"clear:both\"></div>\n\t\t</div>\n\t\t<!-- /footer -->\n\t\t<script src=\"England%28Chinese%29_files/load_005.php\" type=\"text/javascript\"></script>\n<script type=\"text/javascript\">if(window.mw){\nmw.loader.load([\"mediawiki.user\",\"mediawiki.page.ready\",\"mediawiki.legacy.mwsuggest\",\"ext.gadget.AdvancedSiteNotices\",\"ext.gadget.hideConversionTab\",\"ext.gadget.large-font\",\"ext.gadget.WikiMiniAtlas\",\"ext.vector.collapsibleNav\",\"ext.vector.collapsibleTabs\",\"ext.vector.editWarning\",\"ext.vector.simpleSearch\",\"ext.UserBuckets\",\"ext.articleFeedback.startup\"], null, true);\n}</script><script type=\"text/javascript\" src=\"England%28Chinese%29_files/load_002.php\"></script><script type=\"text/javascript\" src=\"England%28Chinese%29_files/load_006.php\"></script>\n<script src=\"England%28Chinese%29_files/index_002.php\" type=\"text/javascript\"></script>\n<script src=\"England%28Chinese%29_files/load_004.php\" type=\"text/javascript\"></script><script type=\"text/javascript\" src=\"England%28Chinese%29_files/load_010.php\"></script><script type=\"text/javascript\" src=\"England%28Chinese%29_files/index.php\"></script>\n<script src=\"England%28Chinese%29_files/a\" type=\"text/javascript\"></script><!-- Served by srv211 in 0.555 secs. -->\n\t\n\n<div class=\"suggestions\" style=\"top: 71px; width: 204px; display: none; left: auto; right: 29px;\"><div class=\"suggestions-results\"></div><div class=\"suggestions-special\"></div></div><script type=\"text/javascript\" src=\"England%28Chinese%29_files/load_009.php\"></script><script type=\"text/javascript\" src=\"England%28Chinese%29_files/load_003.php\"></script></body></html>"
  },
  {
    "path": "test/perf/OpenFile-perf-files/InlineWidget.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\ndefine(function (require, exports, module) {\n    \"use strict\";\n\n    // Load dependent modules\n    var EditorManager       = require(\"editor/EditorManager\");\n    \n    /**\n     * @constructor\n     *\n     */\n    function InlineWidget() {\n        var self = this;\n        \n        // create the outer wrapper div\n        this.htmlContent = window.document.createElement(\"div\");\n        this.$htmlContent = $(this.htmlContent).addClass(\"inline-widget\");\n        this.$htmlContent.append(\"<div class='shadow top' />\")\n            .append(\"<div class='shadow bottom' />\");\n        \n        this.$htmlContent.on(\"keydown\", function (e) {\n            if (e.keyCode === 27) {\n                self.close();\n                e.stopImmediatePropagation();\n            }\n        });\n    }\n    InlineWidget.prototype.htmlContent = null;\n    InlineWidget.prototype.$htmlContent = null;\n    InlineWidget.prototype.id = null;\n    InlineWidget.prototype.hostEditor = null;\n\n    /**\n     * Initial height of inline widget in pixels. Can be changed later via hostEditor.setInlineWidgetHeight()\n     * @type {number}\n     */\n    InlineWidget.prototype.height = 0;\n    \n    /**\n     * Closes this inline widget and all its contained Editors\n     */\n    InlineWidget.prototype.close = function () {\n        var shouldMoveFocus = this._editorHasFocus();\n        EditorManager.closeInlineWidget(this.hostEditor, this, shouldMoveFocus);\n        // closeInlineWidget() causes our onClosed() handler to be called\n    };\n    \n    /**\n     * Called any time inline is closed, whether manually or automatically\n     */\n    InlineWidget.prototype.onClosed = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * Called once content is parented in the host editor's DOM. Useful for performing tasks like setting\n     * focus or measuring content, which require htmlContent to be in the DOM tree.\n     */\n    InlineWidget.prototype.onAdded = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineWidget.prototype.load = function (hostEditor) {\n        this.hostEditor = hostEditor;\n\n        // TODO: incomplete impelementation. It's not clear yet if InlineTextEditor\n        // will fuction as an abstract class or as generic inline editor implementation\n        // that just shows a range of text. See CSSInlineEditor.css for an implementation of load()\n    };\n    \n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineWidget.prototype.onParentShown = function () {\n        // do nothing - base implementation\n    };\n\n    exports.InlineWidget = InlineWidget;\n\n});\n"
  },
  {
    "path": "test/perf/OpenFile-perf-files/blank.js",
    "content": ""
  },
  {
    "path": "test/perf/OpenFile-perf-files/brackets-concat.js",
    "content": "\n/* ============================================================\n * bootstrap-dropdown.js v1.4.0\n * http://twitter.github.com/bootstrap/javascript.html#dropdown\n * ============================================================\n * Copyright 2011 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ============================================================ */\n\n\n!function( $ ){\n\n  \"use strict\"\n\n  /* DROPDOWN PLUGIN DEFINITION\n   * ========================== */\n\n  $.fn.dropdown = function ( selector ) {\n    return this.each(function () {\n      $(this).delegate(selector || d, 'click', function (e) {\n        var li = $(this).parent('li')\n          , isActive = li.hasClass('open')\n\n        clearMenus()\n        !isActive && li.toggleClass('open')\n        return false\n      })\n    })\n  }\n\n  /* APPLY TO STANDARD DROPDOWN ELEMENTS\n   * =================================== */\n\n  var d = 'a.menu, .dropdown-toggle'\n\n  function clearMenus() {\n    $(d).parent('li').removeClass('open')\n  }\n\n  $(function () {\n    $('html').bind(\"click\", clearMenus)\n    $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' )\n  })\n\n}( window.jQuery || window.ender );\n\ndefine(\"widgets/bootstrap-dropdown\", function(){});\n\n/* =========================================================\n * bootstrap-modal.js v1.4.0\n * http://twitter.github.com/bootstrap/javascript.html#modal\n * =========================================================\n * Copyright 2011 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================= */\n\n\n!function( $ ){\n\n  \"use strict\"\n\n /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)\n  * ======================================================= */\n\n  var transitionEnd\n\n  $(document).ready(function () {\n\n    $.support.transition = (function () {\n      var thisBody = document.body || document.documentElement\n        , thisStyle = thisBody.style\n        , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined\n      return support\n    })()\n\n    // set CSS transition event type\n    if ( $.support.transition ) {\n      transitionEnd = \"TransitionEnd\"\n      if ( $.browser.webkit ) {\n      \ttransitionEnd = \"webkitTransitionEnd\"\n      } else if ( $.browser.mozilla ) {\n      \ttransitionEnd = \"transitionend\"\n      } else if ( $.browser.opera ) {\n      \ttransitionEnd = \"oTransitionEnd\"\n      }\n    }\n\n  })\n\n\n /* MODAL PUBLIC CLASS DEFINITION\n  * ============================= */\n\n  var Modal = function ( content, options ) {\n    this.settings = $.extend({}, $.fn.modal.defaults, options)\n    this.$element = $(content)\n      .delegate('.close', 'click.modal', $.proxy(this.hide, this))\n\n    if ( this.settings.show ) {\n      this.show()\n    }\n\n    return this\n  }\n\n  Modal.prototype = {\n\n      toggle: function () {\n        return this[!this.isShown ? 'show' : 'hide']()\n      }\n\n    , show: function () {\n        var that = this\n        this.isShown = true\n        this.$element.trigger('show')\n\n        escape.call(this)\n        backdrop.call(this, function () {\n          var transition = $.support.transition && that.$element.hasClass('fade')\n\n          that.$element\n            .appendTo(document.body)\n            .show()\n\n          if (transition) {\n            that.$element[0].offsetWidth // force reflow\n          }\n\n          that.$element.addClass('in')\n\n          transition ?\n            that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) :\n            that.$element.trigger('shown')\n\n        })\n\n        return this\n      }\n\n    , hide: function (e) {\n        e && e.preventDefault()\n\n        if ( !this.isShown ) {\n          return this\n        }\n\n        var that = this\n        this.isShown = false\n\n        escape.call(this)\n\n        this.$element\n          .trigger('hide')\n          .removeClass('in')\n\n        $.support.transition && this.$element.hasClass('fade') ?\n          hideWithTransition.call(this) :\n          hideModal.call(this)\n\n        return this\n      }\n\n  }\n\n\n /* MODAL PRIVATE METHODS\n  * ===================== */\n\n  function hideWithTransition() {\n    // firefox drops transitionEnd events :{o\n    var that = this\n      , timeout = setTimeout(function () {\n          that.$element.unbind(transitionEnd)\n          hideModal.call(that)\n        }, 500)\n\n    this.$element.one(transitionEnd, function () {\n      clearTimeout(timeout)\n      hideModal.call(that)\n    })\n  }\n\n  function hideModal (that) {\n    this.$element\n      .hide()\n      .trigger('hidden')\n\n    backdrop.call(this)\n  }\n\n  function backdrop ( callback ) {\n    var that = this\n      , animate = this.$element.hasClass('fade') ? 'fade' : ''\n    if ( this.isShown && this.settings.backdrop ) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      if ( this.settings.backdrop != 'static' ) {\n        this.$backdrop.click($.proxy(this.hide, this))\n      }\n\n      if ( doAnimate ) {\n        this.$backdrop[0].offsetWidth // force reflow\n      }\n\n      this.$backdrop.addClass('in')\n\n      doAnimate ?\n        this.$backdrop.one(transitionEnd, callback) :\n        callback()\n\n    } else if ( !this.isShown && this.$backdrop ) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) :\n        removeBackdrop.call(this)\n\n    } else if ( callback ) {\n       callback()\n    }\n  }\n\n  function removeBackdrop() {\n    this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  function escape() {\n    var that = this\n    if ( this.isShown && this.settings.keyboard ) {\n      $(document).bind('keyup.modal', function ( e ) {\n        if ( e.which == 27 ) {\n          that.hide()\n        }\n      })\n    } else if ( !this.isShown ) {\n      $(document).unbind('keyup.modal')\n    }\n  }\n\n\n /* MODAL PLUGIN DEFINITION\n  * ======================= */\n\n  $.fn.modal = function ( options ) {\n    var modal = this.data('modal')\n\n    if (!modal) {\n\n      if (typeof options == 'string') {\n        options = {\n          show: /show|toggle/.test(options)\n        }\n      }\n\n      return this.each(function () {\n        $(this).data('modal', new Modal(this, options))\n      })\n    }\n\n    if ( options === true ) {\n      return modal\n    }\n\n    if ( typeof options == 'string' ) {\n      modal[options]()\n    } else if ( modal ) {\n      modal.toggle()\n    }\n\n    return this\n  }\n\n  $.fn.modal.Modal = Modal\n\n  $.fn.modal.defaults = {\n    backdrop: false\n  , keyboard: false\n  , show: false\n  }\n\n\n /* MODAL DATA- IMPLEMENTATION\n  * ========================== */\n\n  $(document).ready(function () {\n    $('body').delegate('[data-controls-modal]', 'click', function (e) {\n      e.preventDefault()\n      var $this = $(this).data('show', true)\n      $('#' + $this.attr('data-controls-modal')).modal( $this.data() )\n    })\n  })\n\n}( window.jQuery || window.ender );\n\ndefine(\"widgets/bootstrap-modal\", function(){});\n\n// path-utils.js - version 0.1\n// Copyright (c) 2011, Kin Blas\n// All rights reserved.\n// \n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n//     * Redistributions of source code must retain the above copyright\n//       notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above copyright\n//       notice, this list of conditions and the following disclaimer in the\n//       documentation and/or other materials provided with the distribution.\n//     * Neither the name of the <organization> nor the\n//       names of its contributors may be used to endorse or promote products\n//       derived from this software without specific prior written permission.\n// \n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\n// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n(function(l){function m(a){return function(e){return b.parseUrl(e)[a]}}var b={urlParseRE:/^(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#\\.]*(?:\\.[^\\?#\\.]+)*(\\.[^\\?#\\.]+)|[^\\?#]*)))?(\\?[^#]+)?)(#.*)?/,parsedUrlPropNames:\"href,hrefNoHash,hrefNoSearch,domain,protocol,doubleSlash,authority,userinfo,username,password,host,hostname,port,pathname,directory,filename,filenameExtension,search,hash\".split(\",\"),\ndefaultPorts:{http:\"80\",https:\"443\",ftp:\"20\",ftps:\"990\"},parseUrl:function(a){if(a&&typeof a===\"object\")return a;var a=b.urlParseRE.exec(a||\"\")||[],e=b.parsedUrlPropNames,c=e.length,f={},d;for(d=0;d<c;d++)f[e[d]]=a[d]||\"\";return f},port:function(a){a=b.parseUrl(a);return a.port||b.defaultPorts[a.protocol]},isSameDomain:function(a,e){return b.parseUrl(a).domain===b.parseUrl(e).domain},isRelativeUrl:function(a){return b.parseUrl(a).protocol===\"\"},isAbsoluteUrl:function(a){return b.parseUrl(a).protocol!==\n\"\"},makePathAbsolute:function(a,e){if(a&&a.charAt(0)===\"/\")return a;for(var a=a||\"\",c=(e=e?e.replace(/^\\/|(\\/[^\\/]*|[^\\/]+)$/g,\"\"):\"\")?e.split(\"/\"):[],b=a.split(\"/\"),d=0;d<b.length;d++){var j=b[d];switch(j){case \".\":break;case \"..\":c.length&&c.pop();break;default:c.push(j)}}return\"/\"+c.join(\"/\")},makePathRelative:function(a,b){for(var b=b?b.replace(/^\\/|\\/?[^\\/]*$/g,\"\"):\"\",a=a?a.replace(/^\\//,\"\"):\"\",c=b?b.split(\"/\"):[],f=a.split(\"/\"),d=[],j=c.length,g=false,i=0;i<j;i++)(g=g||f[0]!==c[i])?d.push(\"..\"):\nf.shift();return d.concat(f).join(\"/\")},makeUrlAbsolute:function(a,e){if(!b.isRelativeUrl(a))return a;var c=b.parseUrl(a),f=b.parseUrl(e),d=c.protocol||f.protocol,g=c.protocol?c.doubleSlash:c.doubleSlash||f.doubleSlash,h=c.authority||f.authority,i=c.pathname!==\"\",k=b.makePathAbsolute(c.pathname||f.filename,f.pathname);return d+g+h+k+(c.search||!i&&f.search||\"\")+c.hash}},g,h,k=b.parsedUrlPropNames,n=k.length;for(g=0;g<n;g++)h=k[g],b[h]||(b[h]=m(h));l.PathUtils=b})(window);\n\ndefine(\"thirdparty/path-utils/path-utils.min\", function(){});\n\n/**\n * Smart Auto Complete plugin \n * \n * Copyright (c) 2011 Lakshan Perera (laktek.com)\n * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)  licenses.\n * \n*/\n\n/*\n Requirements: jQuery 1.5 or above\n\n  Usage:\n  $(target).smartAutoComplete({options})\n\n  Options:\n  minCharLimit: (integer) minimum characters user have to type before invoking the autocomplete (default: 1)\n  maxCharLimit: (integer) maximum characters user can type while invoking the autocomplete (default: null (unlimited))\n  maxResults: (integer) maximum number of results to return (default: null (unlimited))\n  delay: (integer) delay before autocomplete starts (default: 0)\n  disabled: (boolean) whether autocomplete disabled on the field (default: false)\n  forceSelect: (boolean) If set to true, field will be always filled with best matching result, without leaving the custom input.\n               Better to enable this option, if you want autocomplete field to behave similar to a HTML select field. (Check Example 2 in the demo)\n               (default: false)\n  typeAhead: (boolean) If set to true, it will offer the best matching result in grey within the field; that can be auto-completed by pressing the right arrow-key or enter.\n             This is similar to behaviour in Google Instant Search's query field (Check Example 3 in the demo) \n             (default: false)\n  source:  (string/array) you can supply an array with items or a string containing a URL to fetch items for the source\n           this is optional if you prefer to have your own filter method \n  filter: (function) define a custom function that would return matching items to the entered text (this will override the default filtering algorithm)\n          should return an array or a Deferred object (ajax call)\n          parameters available: term, source \n  resultFormatter: (function) the function you supply here will be called to format the output of an individual result.\n                   should return a string\n                   parameters available: result \n  resultsContainer: (selector) to which element(s) the result should be appended.\n  resultElement: (selector) references to the result elements collection (e.g. li, div.result) \n\n  Events:\n  keyIn: fires when user types into the field (parameters: query)\n  resultsReady: fires when the filter function returns (parameters: results)\n  showResults: fires when results are shown (parameters: results)\n  noResults: fires when filter returns an empty array\n  itemSelect: fires when user selects an item from the result list (paramters: item)\n  itemFocus: fires when user highlights an item with mouse or arrow keys (paramters: item)\n  itemUnfocus: fires when user moves out from an highlighted item (paramters: item)\n  lostFocus: fires when autocomplete field loses focus by user clicking outside of the field or focusing on another field. Also, this event is fired when a value is selected\n\n })\n*/\n\n(function($){\n  $.fn.smartAutoComplete = function(){    \n\n    if(arguments.length < 1){\n      // get the smart autocomplete object of the first element and return \n      var first_element = this[0];\n      return $(first_element).data(\"smart-autocomplete\")\n    }\n\n    var default_filter_matcher = function(term, source, context){\n                                    var matcher = new RegExp(term.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, \"\\\\$&\"), \"i\" );\n\n                                    return $.grep(source, function(value) {\n                                      return matcher.test( value );\n                                    });\n\n                                 }\n\n    var default_options = {\n                            minCharLimit: 1, \n                            maxCharLimit: null, \n                            maxResults: null,\n                            delay: 0,\n                            disabled: false,\n                            forceSelect: false,\n                            typeAhead: false,\n                            resultElement: \"li\",\n                            resultFormatter: function(r){ return (\"<li>\" + r + \"</li>\"); },\n                            filter: function(term, source){    \n                              var context = this;\n                              var options = $(context).data('smart-autocomplete');\n                              \n\n                              //when source is an array\n                              if($.type(source) === \"array\") {\n                                // directly map\n                                var results = default_filter_matcher(term, source, context);\n                                return results; \n                              }\n                              //when source is a string\n                              else if($.type(source) === \"string\"){\n                                // treat the string as a URL endpoint\n                                // pass the query as 'term'\n                                \n                                return $.Deferred(function(dfd){ \n                                  $.ajax({\n                                    url: source,\n                                    data: {\"term\": term},\n                                    dataType: \"json\"\n                                  }).success( function(data){\n                                    dfd.resolve( default_filter_matcher(term, data, context) );          \n                                  }); \n                                }).promise();\n                                \n                              }\n\n                            },\n\n                            alignResultsContainer: false,\n\n                            clearResults: function(){\n                              //remove type ahead field\n                              var type_ahead_field = $(this.context).prev(\".smart_autocomplete_type_ahead_field\");\n                              $(this.context).css({ background: type_ahead_field.css(\"background\") });\n                              type_ahead_field.remove();\n                              \n                              //clear results div\n                              $(this.resultsContainer).html(\"\");\n                            },\n\n                            setCurrentSelectionToContext: function(){\n                                if(this.rawResults.length > 0 && this.currentSelection >= 0)\n                                  $(this.context).val(this.rawResults[(this.currentSelection)]);\n                            },\n\n                            setItemSelected: function(val){\n                              this.itemSelected = val;\n                            },\n\n                            autocompleteFocused: false,\n\n                            setAutocompleteFocused: function(val){\n                              this.autocompleteFocused = val;\n                            }\n\n    };\n\n    //define the default events\n    $.event.special.keyIn = {\n      setup: function(){ return false; }, \n\n      _default: function(ev){\n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n        var source = options.source || null;\n        var filter = options.filter;\n        var maxChars = (options.maxCharLimit > 0 ?  options.maxCharLimit : Number.POSITIVE_INFINITY)\n\n        //event specific data\n        var query = ev.smartAutocompleteData.query;\n\n        if(options.disabled || (query.length > maxChars)){\n          return false;\n        }\n\n        //set item selected property\n        options.setItemSelected(false);\n\n        //set autocomplete focused\n        options.setAutocompleteFocused(true);\n\n        //call the filter function with delay\n        setTimeout(function(){\n          $.when( filter.apply(options, [query, options.source]) ).done(function( results ){\n            //do the trimming\n            var trimmed_results = (options.maxResults > 0 ? results.splice(0, options.maxResults) : results);\n\n            $(context).trigger('resultsReady', [trimmed_results]);\n          });\n        }, options.delay);\n      }\n    };\n\n    $.event.special.resultsReady = {\n      setup: function(){ return false },\n\n      _default: function(ev){\n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n\n        //event specific data\n        var results = ev.smartAutocompleteData.results;\n\n        //exit if smart complete is disabled\n        if(options.disabled)\n          return false;\n\n        //clear all previous results \n        $(context).smartAutoComplete().clearResults();\n\n        //save the raw results\n        options.rawResults = results;\n\n        //fire the no match event and exit if no matching results\n        if(results.length < 1){\n          $(context).trigger('noResults');\n          return false\n        }\n\n        //call the results formatter function\n        var formatted_results = $.map(results, function(result){\n        return options.resultFormatter.apply(options, [result]);\n        });\n\n        var formatted_results_html = formatted_results.join(\"\");\n\n        //append the results to the container\n        if(options.resultsContainer)\n          $(options.resultsContainer).append(formatted_results_html);\n\n        //trigger results ready event\n        $(context).trigger('showResults', [results]);\n      }             \n    };\n\n    $.event.special.showResults = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n        var results_container = $(options.resultsContainer);\n\n        //event specific data\n        var raw_results = ev.smartAutocompleteData.results; \n\n        //type ahead\n        if(options.typeAhead && (raw_results[0].substr(0, $(context).val().length) == $(context).val()) ){\n          var suggestion = raw_results[0]; //options.typeAheadExtractor($(context).val(), raw_results[0]); \n          \n          //add new typeAhead field\n          $(context).before(\"<input class='smart_autocomplete_type_ahead_field' type='text' autocomplete='off' disabled='disabled' value='\" + suggestion + \"'/>\");\n\n          $(context).css({\n            position: \"relative\",\n            zIndex: 2,\n            background: 'transparent'\n          });\n\n          var typeAheadField = $(context).prev(\"input\");\n          typeAheadField.css({\n            position: \"absolute\",\n            zIndex: 1,\n            overflow: 'hidden',\n            background: $(context).css(\"background\"),\n            borderColor: 'transparent',\n            width: $(context).width(),\n            color: 'silver'\n          });\n\n          //trigger item over for first item\n          options.currentSelection = 0;\n          if(results_container)\n            $(context).trigger('itemFocus', results_container.children()[options.currentSelection]);\n        }\n\n        //show the results container after aligning it with the field \n        if(results_container){\n          if(options.alignResultsContainer){\n            results_container.css({ \n                  position: \"absolute\",\n                  top: function(){ return $(context).offset().top + $(context).height(); }, \n                  left: function(){ return $(context).offset().left; }, \n                  width: function(){ return $(context).width(); }, \n                  zIndex: 1000\n            })\n          }  \n          results_container.show();\n        }\n\n      }\n    };\n\n    $.event.special.noResults = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n        var result_container = $(options.resultsContainer);\n\n        if(result_container){\n         //clear previous results\n         options.clearResults(); \n        }\n\n      }\n    };\n\n    $.event.special.itemSelect = { \n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n\n        //event specific data\n        var selected_item = ev.smartAutocompleteData.item;\n\n        //get the text from selected item\n        var selected_value = $(selected_item).text() || $(selected_item).val();\n        //set it as the value of the autocomplete field\n        $(context).val(selected_value); \n\n        //set item selected property\n        options.setItemSelected(true);\n\n        //set number of current chars in field \n        options.originalCharCount = $(context).val().length;\n        \n        //trigger lost focus\n        $(context).trigger('lostFocus');\n      }\n    };\n\n    $.event.special.itemFocus = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n\n        //event specific data\n        var item = ev.smartAutocompleteData.item;\n\n        $(item).addClass(\"smart_autocomplete_highlight\");\n      }\n    };\n\n    $.event.special.itemUnfocus = { \n      setup: function(){ return false },\n\n      _default: function(ev){    \n\n        //event specific data\n        var item = ev.smartAutocompleteData.item;\n\n        $(item).removeClass(\"smart_autocomplete_highlight\");\n      }\n    }\n\n    $.event.special.lostFocus = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n\n        //if force select is selected and no item is selected, clear currently entered text \n        if(options.forceSelect && !options.itemSelected)\n          $(options.context).val(\"\");\n\n        //unset autocomplete focused\n        options.setAutocompleteFocused(false);\n\n        //clear results\n        options.clearResults(); \n\n        //hide the results container\n        if(options.resultsContainer)\n          $(options.resultsContainer).hide();\n\n        //set current selection to null\n        options.currentSelection = null;\n      }\n    };\n\n    var passed_options = arguments[0];\n\n    return this.each(function(i) { \n      //set the options\n      var options = $.extend(default_options, $(this).data(\"smart-autocomplete\"), passed_options);\n      //set the context\n      options['context'] = this;\n\n      //if a result container is not defined\n      if($.type(options.resultsContainer) === 'undefined' ){\n        //define the default result container if it is already not defined\n        var default_container = $(\"<ul class='smart_autocomplete_container' style='display:none'></ul>\");\n        default_container.appendTo(\"body\");\n\n        options.resultsContainer = default_container;\n        options.alignResultsContainer = true;\n      }\n\n      $(this).data(\"smart-autocomplete\", options);\n\n      // bind user events\n      $(this).keyup(function(ev){\n        //get the options\n        var options = $(this).data(\"smart-autocomplete\");\n\n        //up arrow\n        if(ev.keyCode == '38'){\n\n          if(options.resultsContainer){\n            var current_selection = options.currentSelection || 0;\n            var result_suggestions = $(options.resultsContainer).children();\n\n            if(current_selection >= 0)\n              $(options.context).trigger('itemUnfocus', result_suggestions[current_selection] );\n\n            if(--current_selection <= 0)\n              current_selection = 0;\n\n            options['currentSelection'] = current_selection;\n\n            $(options.context).trigger('itemFocus', [ result_suggestions[current_selection] ] );\n          }\n        }\n\n        //down arrow\n        else if(ev.keyCode == '40'){\n\n          if(options.resultsContainer && options.resultsContainer.is(':visible')){\n            var current_selection = options.currentSelection;\n            var result_suggestions = $(options.resultsContainer).children();\n\n            if(current_selection >= 0)\n              $(options.context).trigger('itemUnfocus', result_suggestions[current_selection] );\n\n            if(isNaN(current_selection) || null == current_selection || (++current_selection >= result_suggestions.length) )\n              current_selection = 0;\n\n            options['currentSelection'] = current_selection;\n\n            $(options.context).trigger('itemFocus', [ result_suggestions[current_selection] ] );\n          }\n          //trigger keyIn event on down key\n          else {\n            $(options.context).trigger('keyIn', [$(this).val()]); \n          }\n          \n        }\n\n        //right arrow & enter key\n        else if(ev.keyCode == '39' || ev.keyCode == '13'){\n          var type_ahead_field = $(options.context).prev('.smart_autocomplete_type_ahead_field');\n          if(options.resultsContainer && $(options.resultsContainer).is(':visible')){\n            var current_selection = options.currentSelection;\n            var result_suggestions = $(options.resultsContainer).children();\n\n            $(options.context).trigger('itemSelect', [ result_suggestions[current_selection] ] );\n          }\n          else if(options.typeAhead && type_ahead_field.is(':visible'))\n            $(options.context).trigger('itemSelect', [ type_ahead_field ] );\n\n          return false;\n        }\n\n        else {\n         var current_char_count = $(options.context).val().length;\n         //check whether the string has modified\n         if(options.originalCharCount == current_char_count)\n           return;\n\n         //check minimum and maximum number of characters are typed\n         if(current_char_count >= options.minCharLimit){\n          $(options.context).trigger('keyIn', [$(this).val()]); \n         }\n         else{\n            if(options.autocompleteFocused){ \n              options.currentSelection = null;\n              $(options.context).trigger('lostFocus');\n            }\n         }\n\n        }\n      });\n\n      $(this).focus(function(){\n        //if the field is in a form capture the return key event \n        $(this).closest(\"form\").bind(\"keydown.block_for_smart_autocomplete\", function(ev){\n          var type_ahead_field = $(options.context).prev('.smart_autocomplete_type_ahead_field');\n          if(ev.keyCode == '13'){\n            if(options.resultsContainer && $(options.resultsContainer).is(':visible')){\n              var current_selection = options.currentSelection;\n              var result_suggestions = $(options.resultsContainer).children();\n\n              $(options.context).trigger('itemSelect', [ result_suggestions[current_selection] ] );\n              return false;\n            }\n            else if(options.typeAhead && type_ahead_field.is(':visible') ){\n              $(options.context).trigger('itemSelect', [ type_ahead_field ] );\n              return false;\n            }\n          }\n        });\n\n        if(options.forceSelect){\n          $(this).select(); \n        }\n      });\n\n      //check for loosing focus on smart complete field and results container\n      //$(this).blur(function(ev){\n      $(document).bind(\"focusin click\", function(ev){\n        if(options.autocompleteFocused){ \n          var elemIsParent = $.contains(options.resultsContainer[0], ev.target);\n          if(ev.target == options.resultsContainer[0] || ev.target == options.context || elemIsParent) return\n\n          $(options.context).closest(\"form\").unbind(\"keydown.block_for_smart_autocomplete\");\n          $(options.context).trigger('lostFocus');\n        }\n      });\n\n      //bind events to results container\n      $(options.resultsContainer).delegate(options.resultElement, 'mouseenter.smart_autocomplete', function(){\n        var current_selection = options.currentSelection || 0;\n        var result_suggestions = $(options.resultsContainer).children();\n\n        options['currentSelection'] = $(this).prevAll().length;\n\n        $(options.context).trigger('itemFocus', [this] );\n          \n      });\n\n      $(options.resultsContainer).delegate(options.resultElement, 'mouseleave.smart_autocomplete', function(){\n        $(options.context).trigger('itemUnfocus', [this] );\n      });\n\n      $(options.resultsContainer).delegate(options.resultElement, 'click.smart_autocomplete', function(){\n        $(options.context).trigger('itemSelect', [this]);\n        return false\n      });\n\n      //bind plugin specific events\n      $(this).bind({\n        keyIn: function(ev, query){ ev.smartAutocompleteData  = {'query': query }; },\n        resultsReady: function(ev, results){ ev.smartAutocompleteData  = {'results': results }; }, \n        showResults: function(ev, results){ ev.smartAutocompleteData = {'results': results } },\n        noResults: function(){},\n        lostFocus: function(){},\n        itemSelect: function(ev, item){ ev.smartAutocompleteData = {'item': item }; },\n        itemFocus: function(ev, item){ ev.smartAutocompleteData = {'item': item }; },\n        itemUnfocus: function(ev, item){ ev.smartAutocompleteData = {'item': item }; }\n      });\n    });\n      \n  }\n})(jQuery);\n\ndefine(\"thirdparty/smart-auto-complete/jquery.smart_autocomplete\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n/**\n * Utilities for working with Deferred, Promise, and other asynchronous processes.\n */\ndefine('utils/Async',['require','exports','module'],function (require, exports, module) {\n    \n    \n    // Further ideas for Async utilities...\n    //  - Utilities for blocking UI until a Promise completes?\n    //  - A \"SuperDeferred\" could feature some very useful enhancements:\n    //     - API for cancellation (non guaranteed, best attempt)\n    //     - Easier way to add a timeout clause (withTimeout() wrapper below is more verbose)\n    //     - Encapsulate the task kickoff code so you can start it later, e.g. superDeferred.start()\n    //  - Deferred/Promise are unable to do anything akin to a 'finally' block. It'd be nice if we\n    //    could harvest exceptions across all steps of an async process and pipe them to a handler,\n    //    so that we don't leave UI-blocking overlays up forever, etc. But this is hard: we'd have\n    //    wrap every async callback (including low-level native ones that don't use [Super]Deferred)\n    //    to catch exceptions, and then understand which Deferred(s) the code *would* have resolved/\n    //    rejected had it run to completion.\n    \n\n    /**\n     * Executes a series of tasks in parallel, returning a \"master\" Promise that is resolved once\n     * all the tasks have resolved. If one or more tasks fail, behavior depends on the failFast\n     * flag:\n     *   - If true, the master Promise is rejected as soon as the first task fails. The remaining\n     *     tasks continue to completion in the background.\n     *   - If false, the master Promise is rejected after all tasks have completed.\n     *\n     * If nothing fails:          (M = master promise; 1-4 = tasks; d = done; F = fail)\n     *  M  ------------d\n     *  1 >---d        .\n     *  2 >------d     .\n     *  3 >---------d  .\n     *  4 >------------d\n     *\n     * With failFast = false:\n     *  M  ------------F\n     *  1 >---d     .  .\n     *  2 >------d  .  .\n     *  3 >---------F  .\n     *  4 >------------d\n     *\n     * With failFast = true: -- equivalent to $.when()\n     *  M  ---------F\n     *  1 >---d     .\n     *  2 >------d  .\n     *  3 >---------F\n     *  4 >------------d   (#4 continues even though master Promise has failed)\n     * (Note: if tasks finish synchronously, the behavior is more like failFast=false because you\n     * won't get a chance to respond to the master Promise until after all items have been processed)\n     *\n     * To perform task-specific work after an individual task completes, attach handlers to each\n     * Promise before beginProcessItem() returns it.\n     *\n     * Note: don't use this if individual tasks (or their done/fail handlers) could ever show a user-\n     * visible dialog: because they run in parallel, you could show multiple dialogs atop each other.\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @param {!boolean} failFast\n     * @return {$.Promise}\n     */\n    function doInParallel(items, beginProcessItem, failFast) {\n        var promises = [];\n        var masterDeferred = new $.Deferred();\n        \n        if (items.length === 0) {\n            masterDeferred.resolve();\n            \n        } else {\n            var numCompleted = 0;\n            var hasFailed = false;\n            \n            items.forEach(function (item, i) {\n                var itemPromise = beginProcessItem(item, i);\n                promises.push(itemPromise);\n                \n                itemPromise.fail(function () {\n                    if (failFast) {\n                        masterDeferred.reject();\n                    } else {\n                        hasFailed = true;\n                    }\n                });\n                itemPromise.always(function () {\n                    numCompleted++;\n                    if (numCompleted === items.length) {\n                        if (hasFailed) {\n                            masterDeferred.reject();\n                        } else {\n                            masterDeferred.resolve();\n                        }\n                    }\n                });\n            });\n            \n        }\n        \n        return masterDeferred.promise();\n    }\n    \n    /**\n     * Executes a series of tasks in serial (task N does not begin until task N-1 has completed).\n     * Returns a \"master\" Promise that is resolved once all the tasks have resolved. If one or more\n     * tasks fail, behavior depends on the failAndStopFast flag:\n     *   - If true, the master Promise is rejected as soon as the first task fails. The remaining\n     *     tasks are never started (the serial sequence is stopped).\n     *   - If false, the master Promise is rejected after all tasks have completed.\n     *\n     * If nothing fails:\n     *  M  ------------d\n     *  1 >---d        .\n     *  2     >--d     .\n     *  3        >--d  .\n     *  4           >--d\n     *\n     * With failAndStopFast = false:\n     *  M  ------------F\n     *  1 >---d     .  .\n     *  2     >--d  .  .\n     *  3        >--F  .\n     *  4           >--d\n     *\n     * With failAndStopFast = true:\n     *  M  ---------F\n     *  1 >---d     .\n     *  2     >--d  .\n     *  3        >--F\n     *  4          (#4 never runs)\n     *\n     * To perform task-specific work after an individual task completes, attach handlers to each\n     * Promise before beginProcessItem() returns it.\n     * \n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @param {!boolean} failAndStopFast\n     * @return {$.Promise}\n     */\n    function doSequentially(items, beginProcessItem, failAndStopFast) {\n\n        var masterDeferred = new $.Deferred(),\n            hasFailed = false;\n        \n        function doItem(i) {\n            if (i >= items.length) {\n                if (hasFailed) {\n                    masterDeferred.reject();\n                } else {\n                    masterDeferred.resolve();\n                }\n                return;\n            }\n            \n            var itemPromise = beginProcessItem(items[i], i);\n            \n            itemPromise.done(function () {\n                doItem(i + 1);\n            });\n            itemPromise.fail(function () {\n                if (failAndStopFast) {\n                    masterDeferred.reject();\n                    // note: we do NOT process any further items in this case\n                } else {\n                    hasFailed = true;\n                    doItem(i + 1);\n                }\n            });\n        }\n        \n        doItem(0);\n        \n        return masterDeferred.promise();\n    }\n    \n    /**\n     * Executes a series of tasks sequentially in time-slices less than maxBlockingTime.\n     * Processing yields by idleTime between time-slices.\n     * \n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} fnProcessItem\n     * @param {!number} maxBlockingTime\n     * @param {!number} idleTime\n     * @return {$.Promise}\n     */\n    function doSequentiallyInBackground(items, fnProcessItem, maxBlockingTime, idleTime) {\n        \n        maxBlockingTime = maxBlockingTime || 15;\n        idleTime = idleTime || 30;\n        \n        var sliceStartTime = (new Date()).getTime();\n        \n        return doSequentially(items, function (item, i) {\n            var result = new $.Deferred();\n            \n            // process the next item\n            fnProcessItem(item, i);\n            \n            // if we've exhausted our maxBlockingTime\n            if ((new Date()).getTime() - sliceStartTime >= maxBlockingTime) {\n                //yield\n                window.setTimeout(function () {\n                    sliceStartTime = (new Date()).getTime();\n                    result.resolve();\n                }, idleTime);\n            } else {\n                //continue processing\n                result.resolve();\n            }\n\n            return result;\n        }, false);\n    }\n    \n    \n    /**\n     * Executes a series of tasks in parallel, saving up error info from any that fail along the way.\n     * Returns a Promise that is only resolved/rejected once all tasks are complete. This is\n     * essentially a wrapper around doInParallel(..., false).\n     *\n     * If one or more tasks failed, the entire \"master\" promise is rejected at the end - with one\n     * argument: an array objects, one per failed task. Each error object contains:\n     *  - item -- the entry in items whose task failed\n     *  - error -- the first argument passed to the fail() handler when the task failed\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @return {$.Promise}\n     */\n    function doInParallel_aggregateErrors(items, beginProcessItem) {\n        var errors = [];\n        \n        var masterDeferred = new $.Deferred();\n        \n        var parallelResult = doInParallel(\n            items,\n            function (item, i) {\n                var itemResult = beginProcessItem(item, i);\n                itemResult.fail(function (error) {\n                    errors.push({ item: item, error: error });\n                });\n                return itemResult;\n            },\n            false\n        );\n        \n        parallelResult\n            .done(function () {\n                masterDeferred.resolve();\n            })\n            .fail(function () {\n                masterDeferred.reject(errors);\n            });\n        \n        return masterDeferred.promise();\n    }\n    \n    \n    /** Value passed to fail() handlers that have been triggered due to withTimeout()'s timeout */\n    var ERROR_TIMEOUT = {};\n    \n    /**\n     * Adds timeout-driven failure to a Promise: returns a new Promise that is resolved/rejected when\n     * the given original Promise is resolved/rejected, OR is rejected after the given delay - whichever\n     * happens first.\n     * \n     * If the original Promise is resolved/rejected first, done()/fail() handlers receive arguments\n     * piped from the original Promise. If the timeout occurs first instead, fail() is called with the\n     * token Async.ERROR_TIMEOUT.\n     * \n     * @param {$.Promise} promise\n     * @param {number} timeout\n     * @return {$.Promise}\n     */\n    function withTimeout(promise, timeout) {\n        var wrapper = new $.Deferred();\n        \n        var timer = window.setTimeout(function () {\n            wrapper.reject(ERROR_TIMEOUT);\n        }, timeout);\n        promise.always(function () {\n            window.clearTimeout(timer);\n        });\n        \n        // If the wrapper was already rejected due to timeout, the Promise's calls to resolve/reject\n        // won't do anything\n        promise.pipe(wrapper.resolve, wrapper.reject);\n        \n        return wrapper.promise();\n    }\n    \n    \n\n    // Define public API\n    exports.doInParallel   = doInParallel;\n    exports.doSequentially = doSequentially;\n    exports.doSequentiallyInBackground = doSequentiallyInBackground;\n    exports.doInParallel_aggregateErrors = doInParallel_aggregateErrors;\n    exports.withTimeout    = withTimeout;\n    exports.ERROR_TIMEOUT  = ERROR_TIMEOUT;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/\n/*global $, define, brackets, FileError, InvalidateStateError */\n\ndefine('file/NativeFileSystem',['require','exports','module','utils/Async'],function (require, exports, module) {\n    \n    \n    var Async = require(\"utils/Async\");\n\n    /*\n     * Generally NativeFileSystem mimics the File API working draft\n     * http://www.w3.org/TR/file-system-api/. The w3 entry point\n     * requestFileSystem is replaced with our own requestNativeFileSystem.\n     *\n     * The current implementation is incomplete and noteably does not\n     * support the Blob data type and synchronous APIs. DirectoryEntry\n     * and FileEntry read/write capabilities are mostly implemented, but\n     * delete is not. File writing is limited to UTF-8 text.\n     */\n    var NativeFileSystem = {\n        \n        /** \n         * Amount of time we wait for async calls to return (in milliseconds)\n         * Not all async calls are wrapped with something that times out and \n         * calls the error callback. Timeouts are not specified in the W3C spec.\n         * @const\n         * @type {number}\n         */\n        ASYNC_TIMEOUT: 2000,\n        \n        /** showOpenDialog\n         *\n         * @param {bool} allowMultipleSelection\n         * @param {bool} chooseDirectories\n         * @param {string} title\n         * @param {string} initialPath\n         * @param {Array.<string>} fileTypes\n         * @param {function(...)} successCallback\n         * @param {function(...)} errorCallback\n         * @constructor\n         */\n        showOpenDialog: function (allowMultipleSelection,\n                                  chooseDirectories,\n                                  title,\n                                  initialPath,\n                                  fileTypes,\n                                  successCallback,\n                                  errorCallback) {\n            if (!successCallback) {\n                return;\n            }\n\n            var files = brackets.fs.showOpenDialog(\n                allowMultipleSelection,\n                chooseDirectories,\n                title,\n                initialPath,\n                fileTypes,\n                function (err, data) {\n                    if (!err) {\n                        successCallback(data);\n                    } else if (errorCallback) {\n                        errorCallback(NativeFileSystem._nativeToFileError(err));\n                    }\n                }\n            );\n        },\n\n        /** requestNativeFileSystem\n         *\n         * @param {string} path\n         * @param {function(...)} successCallback\n         * @param {function(...)} errorCallback\n         */\n        requestNativeFileSystem: function (path, successCallback, errorCallback) {\n            brackets.fs.stat(path, function (err, data) {\n                if (!err) {\n                    // FIXME (issue #247): return a NativeFileSystem object\n                    var root = new NativeFileSystem.DirectoryEntry(path);\n                    successCallback(root);\n                } else if (errorCallback) {\n                    errorCallback(NativeFileSystem._nativeToFileError(err));\n                }\n            });\n        },\n\n        _nativeToFileError: function (nativeErr) {\n            var error;\n\n            switch (nativeErr) {\n                // We map ERR_UNKNOWN and ERR_INVALID_PARAMS to SECURITY_ERR,\n                // since there aren't specific mappings for these.\n            case brackets.fs.ERR_UNKNOWN:\n            case brackets.fs.ERR_INVALID_PARAMS:\n                error = FileError.SECURITY_ERR;\n                break;\n            case brackets.fs.ERR_NOT_FOUND:\n                error = FileError.NOT_FOUND_ERR;\n                break;\n            case brackets.fs.ERR_CANT_READ:\n                error = FileError.NOT_READABLE_ERR;\n                break;\n            // It might seem like you should use FileError.ENCODING_ERR for this,\n            // but according to the spec that's for malformed URLs.\n            case brackets.fs.ERR_UNSUPPORTED_ENCODING:\n                error = FileError.SECURITY_ERR;\n                break;\n            case brackets.fs.ERR_CANT_WRITE:\n                error = FileError.NO_MODIFICATION_ALLOWED_ERR;\n                break;\n            case brackets.fs.ERR_OUT_OF_SPACE:\n                error = FileError.QUOTA_EXCEEDED_ERR;\n                break;\n            case brackets.fs.PATH_EXISTS_ERR:\n                error = FileError.PATH_EXISTS_ERR;\n                break;\n            default:\n                // The HTML file spec says SECURITY_ERR is a catch-all to be used in situations\n                // not covered by other error codes. \n                error = FileError.SECURITY_ERR;\n            }\n            return new NativeFileSystem.FileError(error);\n        }\n    };\n    \n    /** class: Encodings\n     *\n     * Static class that contains constants for file\n     * encoding types.\n     */\n    NativeFileSystem.Encodings = {};\n    NativeFileSystem.Encodings.UTF8 = \"UTF-8\";\n    NativeFileSystem.Encodings.UTF16 = \"UTF-16\";\n    \n    /** class: _FSEncodings\n     *\n     * Internal static class that contains constants for file\n     * encoding types to be used by internal file system\n     * implimentation.\n    */\n    NativeFileSystem._FSEncodings = {};\n    NativeFileSystem._FSEncodings.UTF8 = \"utf8\";\n    NativeFileSystem._FSEncodings.UTF16 = \"utf16\";\n    \n    /**\n     * Converts an IANA encoding name to internal encoding name.\n     * http://www.iana.org/assignments/character-sets\n     *\n     * @param {String} encoding The IANA encoding string.\n     */\n    NativeFileSystem.Encodings._IANAToFS = function (encoding) {\n        //IANA names are case-insensitive\n        encoding = encoding.toUpperCase();\n\n        switch (encoding) {\n        case (NativeFileSystem.Encodings.UTF8):\n            return NativeFileSystem._FSEncodings.UTF8;\n        case (NativeFileSystem.Encodings.UTF16):\n            return NativeFileSystem._FSEncodings.UTF16;\n        default:\n            return undefined;\n        }\n    };\n    \n    var Encodings = NativeFileSystem.Encodings;\n    var _FSEncodings = NativeFileSystem._FSEncodings;\n    \n    /** class: Entry\n     *\n     * @param {string} name\n     * @param {string} isFile\n     * @constructor\n     */\n    NativeFileSystem.Entry = function (fullPath, isDirectory) {\n        this.isDirectory = isDirectory;\n        this.isFile = !isDirectory;\n        \n        if (fullPath) {\n            // add trailing \"/\" to directory paths\n            if (isDirectory && (fullPath.charAt(fullPath.length - 1) !== \"/\")) {\n                fullPath = fullPath.concat(\"/\");\n            }\n        }\n        \n        this.fullPath = fullPath;\n\n        this.name = null; // default if extraction fails\n        if (fullPath) {\n            var pathParts = fullPath.split(\"/\");\n            \n            // Extract name from the end of the fullPath (account for trailing slash(es))\n            while (!this.name && pathParts.length) {\n                this.name = pathParts.pop();\n            }\n        }\n\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-filesystem\n        this.filesystem = null;\n    };\n    \n    NativeFileSystem.Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-moveTo\n    };\n    \n    NativeFileSystem.Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-copyTo\n    };\n    \n    NativeFileSystem.Entry.prototype.toURL = function (mimeType) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-toURL\n    };\n    \n    NativeFileSystem.Entry.prototype.remove = function (successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-remove\n    };\n    \n    NativeFileSystem.Entry.prototype.getParent = function (successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-remove\n    };\n    \n    NativeFileSystem.Entry.prototype.getMetadata = function (successCallBack, errorCallback) {\n        brackets.fs.stat(this.fullPath, function (err, stat) {\n            if (err === brackets.fs.NO_ERROR) {\n                var metadata = new NativeFileSystem.Metadata(stat.mtime);\n                successCallBack(metadata);\n            } else {\n                errorCallback(NativeFileSystem._nativeToFileError(err));\n            }\n        });\n    };\n\n\n    /**\n     * Stores information about a FileEntry\n    */\n    NativeFileSystem.Metadata = function (modificationTime) {\n        // modificationTime is read only\n        this.modificationTime = modificationTime;\n    };\n\n    /** class: FileEntry\n     * This interface represents a file on a file system.\n     *\n     * @param {string} name\n     * @constructor\n     * @extends {Entry}\n     */\n    NativeFileSystem.FileEntry = function (name) {\n        NativeFileSystem.Entry.call(this, name, false);\n    };\n    NativeFileSystem.FileEntry.prototype = new NativeFileSystem.Entry();\n\n    NativeFileSystem.FileEntry.prototype.toString = function () {\n        return \"[FileEntry \" + this.fullPath + \"]\";\n    };\n    \n    /**\n     * Creates a new FileWriter associated with the file that this FileEntry represents.\n     *\n     * @param {function (FileWriter)} successCallback\n     * @param {function (FileError)} errorCallback\n     */\n    NativeFileSystem.FileEntry.prototype.createWriter = function (successCallback, errorCallback) {\n        var fileEntry = this;\n\n        // [NoInterfaceObject]\n        // interface FileWriter : FileSaver\n        var FileWriter = function (data) {\n            NativeFileSystem.FileSaver.call(this, data);\n\n            // FileWriter private memeber vars\n            this._length = 0;\n            this._position = 0;\n        };\n\n        FileWriter.prototype.length = function () {\n            return this._length;\n        };\n\n        FileWriter.prototype.position = function () {\n            return this._position;\n        };\n\n        // TODO (issue #241): handle Blob data instead of string\n        FileWriter.prototype.write = function (data) {\n            if (data === null || data === undefined) {\n                throw new Error();\n            }\n\n            if (this.readyState === NativeFileSystem.FileSaver.WRITING) {\n                throw new NativeFileSystem.FileException(NativeFileSystem.FileException.INVALID_STATE_ERR);\n            }\n\n            this._readyState = NativeFileSystem.FileSaver.WRITING;\n\n            if (this.onwritestart) {\n                // TODO (issue #241): progressevent\n                this.onwritestart();\n            }\n\n            var self = this;\n\n            brackets.fs.writeFile(fileEntry.fullPath, data, _FSEncodings.UTF8, function (err) {\n\n                if ((err !== brackets.fs.NO_ERROR) && self.onerror) {\n                    var fileError = NativeFileSystem._nativeToFileError(err);\n\n                    // TODO (issue #241): set readonly FileSaver.error attribute\n                    // self._error = fileError;\n                    self.onerror(fileError);\n\n                    // TODO (issue #241): partial write, update length and position\n                }\n                // else {\n                    // TODO (issue #241): After changing data argument to Blob, use\n                    // Blob.size to update position and length upon successful\n                    // completion of a write.\n\n                    // self.position = ;\n                    // self.length = ;\n                // }\n\n                // DONE is set regardless of error\n                self._readyState = NativeFileSystem.FileSaver.DONE;\n                \n                if (self.onwrite) {\n                    // TODO (issue #241): progressevent\n                    self.onwrite();\n                }\n\n                if (self.onwriteend) {\n                    // TODO (issue #241): progressevent\n                    self.onwriteend();\n                }\n            });\n        };\n\n        FileWriter.prototype.seek = function (offset) {\n        };\n\n        FileWriter.prototype.truncate = function (size) {\n        };\n\n        var fileWriter = new FileWriter();\n\n        // initialize file length\n        var result = new $.Deferred();\n        brackets.fs.readFile(fileEntry.fullPath, _FSEncodings.UTF8, function (err, contents) {\n            // Ignore \"file not found\" errors. It's okay if the file doesn't exist yet.\n            if (err !== brackets.fs.ERR_NOT_FOUND) {\n                fileWriter._err = err;\n            }\n            \n            if (contents) {\n                fileWriter._length = contents.length;\n            }\n            \n            result.resolve();\n        });\n\n        result.done(function () {\n            if (fileWriter._err && (errorCallback !== undefined)) {\n                errorCallback(NativeFileSystem._nativeToFileError(fileWriter._err));\n            } else if (successCallback !== undefined) {\n                successCallback(fileWriter);\n            }\n        });\n    };\n\n    /**\n     * Obtains the File objecte for a FileEntry object\n     *\n     * @param {function(...)} successCallback\n     * @param {function(...)} errorCallback\n     */\n    NativeFileSystem.FileEntry.prototype.file = function (successCallback, errorCallback) {\n        var newFile = new NativeFileSystem.File(this);\n        successCallback(newFile);\n\n        // TODO (issue #241): errorCallback\n    };\n\n    /**\n     * This interface extends the FileException interface described in to add\n     * several new error codes. Any errors that need to be reported synchronously,\n     * including all that occur during use of the synchronous filesystem methods,\n     * are reported using the FileException exception.\n     *\n     * @param {number} code The code attribute, on getting, must return one of the\n     * constants of the FileException exception, which must be the most appropriate\n     * code from the table below.\n     */\n    NativeFileSystem.FileException = function (code) {\n        this.code = code || 0;\n    };\n\n    // FileException constants\n    Object.defineProperties(\n        NativeFileSystem.FileException,\n        {\n            NOT_FOUND_ERR:                { value: 1, writable: false },\n            SECURITY_ERR:                 { value: 2, writable: false },\n            ABORT_ERR:                    { value: 3, writable: false },\n            NOT_READABLE_ERR:             { value: 4, writable: false },\n            ENCODING_ERR:                 { value: 5, writable: false },\n            NO_MODIFICATION_ALLOWED_ERR:  { value: 6, writable: false },\n            INVALID_STATE_ERR:            { value: 7, writable: false },\n            SYNTAX_ERR:                   { value: 8, writable: false },\n            QUOTA_EXCEEDED_ERR:           { value: 10, writable: false }\n        }\n    );\n\n    /**\n     * This interface provides methods to monitor the asynchronous writing of blobs\n     * to disk using progress events and event handler attributes.\n     *\n     * This interface is specified to be used within the context of the global\n     * object (Window) and within Web Workers.\n     *\n     * @param {Blob} data\n     * @constructor\n     */\n    NativeFileSystem.FileSaver = function (data) {\n        // FileSaver private member vars\n        this._data = data;\n        this._readyState = NativeFileSystem.FileSaver.INIT;\n        this._error = null;\n    };\n\n    // FileSaver constants\n    Object.defineProperties(\n        NativeFileSystem.FileSaver,\n        {\n            INIT:     { value: 1, writable: false },\n            WRITING:  { value: 2, writable: false },\n            DONE:     { value: 3, writable: false }\n        }\n    );\n\n    // FileSaver methods\n\n    /**\n     *\n     */\n    NativeFileSystem.FileSaver.prototype.readyState = function () {\n        return this._readyState;\n    };\n\n    // TODO (issue #241): http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void\n    NativeFileSystem.FileSaver.prototype.abort = function () {\n        // If readyState is DONE or INIT, terminate this overall series of steps without doing anything else..\n        if (this._readyState === NativeFileSystem.FileSaver.INIT || this._readyState === NativeFileSystem.FileSaver.DONE) {\n            return;\n        }\n\n        // TODO (issue #241): Terminate any steps having to do with writing a file.\n\n        // Set the error attribute to a FileError object with the code ABORT_ERR.\n        this._error = new NativeFileSystem.FileError(FileError.ABORT_ERR);\n\n        // Set readyState to DONE.\n        this._readyState = NativeFileSystem.FileSaver.DONE;\n\n        /*\n        TODO (issue #241): \n        Dispatch a progress event called abort\n        Dispatch a progress event called writeend\n        Stop dispatching any further progress events.\n        Terminate this overall set of steps.\n        */\n    };\n\n    /**\n     * This interface represents a directory on a file system.\n     *\n     * @constructor\n     * @param {string} name\n     * @extends {Entry}\n     */\n    NativeFileSystem.DirectoryEntry = function (name) {\n        NativeFileSystem.Entry.call(this, name, true);\n\n        // TODO (issue #241): void removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback);\n    };\n    NativeFileSystem.DirectoryEntry.prototype = new NativeFileSystem.Entry();\n    \n    NativeFileSystem.DirectoryEntry.prototype.toString = function () {\n        return \"[DirectoryEntry \" + this.fullPath + \"]\";\n    };\n    \n    NativeFileSystem.DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-DirectoryEntry-getDirectory\n    };\n    \n    NativeFileSystem.DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-DirectoryEntry-removeRecursively\n    };\n\n    NativeFileSystem.DirectoryEntry.prototype.createReader = function () {\n        var dirReader = new NativeFileSystem.DirectoryReader();\n        dirReader._directory = this;\n\n        return dirReader;\n    };\n\n    /**\n     * Creates or looks up a file.\n     *\n     * @param {string} path Either an absolute path or a relative path from this\n     *        DirectoryEntry to the file to be looked up or created. It is an error\n     *        to attempt to create a file whose immediate parent does not yet\n     *        exist.\n     * @param {Object.<string, boolean>} options\n     * @param {function (number)} successCallback\n     * @param {function (number)} errorCallback\n     */\n    NativeFileSystem.DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {\n        var fileFullPath = path;\n        \n        function isRelativePath(path) {\n            // If the path contains a colons it must be a full path on Windows (colons are\n            // not valid path characters on mac or in URIs)\n            if (path.indexOf(\":\") !== -1) {\n                return false;\n            }\n            \n            // For everyone else, absolute paths start with a \"/\"\n            return path[0] !== \"/\";\n        }\n\n        // resolve relative paths relative to the DirectoryEntry\n        if (isRelativePath(path)) {\n            fileFullPath = this.fullPath + path;\n        }\n\n        var createFileEntry = function () {\n            if (successCallback) {\n                successCallback(new NativeFileSystem.FileEntry(fileFullPath));\n            }\n        };\n\n        var createFileError = function (err) {\n            if (errorCallback) {\n                errorCallback(NativeFileSystem._nativeToFileError(err));\n            }\n        };\n\n        // Use stat() to check if file exists\n        brackets.fs.stat(fileFullPath, function (err, stats) {\n            if ((err === brackets.fs.NO_ERROR)) {\n                // NO_ERROR implies the path already exists\n\n                // throw error if the file the path is a directory\n                if (stats.isDirectory()) {\n                    if (errorCallback) {\n                        errorCallback(new NativeFileSystem.FileError(FileError.TYPE_MISMATCH_ERR));\n                    }\n\n                    return;\n                }\n\n                // throw error if the file exists but create is exclusive\n                if (options.create && options.exclusive) {\n                    if (errorCallback) {\n                        errorCallback(new NativeFileSystem.FileError(FileError.PATH_EXISTS_ERR));\n                    }\n\n                    return;\n                }\n\n                // Create a file entry for the existing file. If create == true,\n                // a file entry is created without error.\n                createFileEntry();\n            } else if (err === brackets.fs.ERR_NOT_FOUND) {\n                // ERR_NOT_FOUND implies we write a new, empty file\n\n                // create the file\n                if (options.create) {\n                    brackets.fs.writeFile(fileFullPath, \"\", _FSEncodings.UTF8, function (err) {\n                        if (err) {\n                            createFileError(err);\n                        } else {\n                            createFileEntry();\n                        }\n                    });\n\n                    return;\n                }\n\n                // throw error if file not found and the create == false\n                if (errorCallback) {\n                    errorCallback(new NativeFileSystem.FileError(FileError.NOT_FOUND_ERR));\n                }\n            } else {\n                // all other brackets.fs.stat() errors\n                createFileError(err);\n            }\n        });\n    };\n\n    /** class: DirectoryReader\n     */\n    NativeFileSystem.DirectoryReader = function () {\n\n    };\n\n    /** readEntries\n     *\n     * @param {function(...)} successCallback\n     * @param {function(...)} errorCallback\n     * @returns {Array.<Entry>}\n     */\n    NativeFileSystem.DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {\n        var rootPath = this._directory.fullPath;\n        brackets.fs.readdir(rootPath, function (err, filelist) {\n            if (!err) {\n                var entries = [];\n                var lastError = null;\n\n                // stat() to determine type of each entry, then populare entries array with objects\n                var masterPromise = Async.doInParallel(filelist, function (filename, index) {\n                    \n                    var deferred = new $.Deferred();\n                    var itemFullPath = rootPath + filelist[index];\n                    \n                    brackets.fs.stat(itemFullPath, function (statErr, statData) {\n                        if (!statErr) {\n                            if (statData.isDirectory()) {\n                                entries[index] = new NativeFileSystem.DirectoryEntry(itemFullPath);\n                            } else if (statData.isFile()) {\n                                entries[index] = new NativeFileSystem.FileEntry(itemFullPath);\n                            } else {\n                                entries[index] = null;  // neither a file nor a dir, so don't include it\n                            }\n                            deferred.resolve();\n                        } else {\n                            lastError = NativeFileSystem._nativeToFileError(statErr);\n                            deferred.reject(lastError);\n                        }\n                    });\n                    \n                    return deferred.promise();\n                }, true);\n\n                // We want the error callback to get called after some timeout (in case some deferreds don't return).\n                // So, we need to wrap masterPromise in another deferred that has this timeout functionality    \n                var timeoutWrapper = Async.withTimeout(masterPromise, NativeFileSystem.ASYNC_TIMEOUT);\n\n                // Add the callbacks to this top-level Promise, which wraps all the individual deferred objects\n                timeoutWrapper.then(\n                    function () { // success\n                        // The entries array may have null values if stat returned things that were\n                        // neither a file nor a dir. So, we need to clean those out.\n                        var cleanedEntries = [], i;\n                        for (i = 0; i < entries.length; i++) {\n                            if (entries[i]) {\n                                cleanedEntries.push(entries[i]);\n                            }\n                        }\n                        successCallback(cleanedEntries);\n                    },\n                    function (err) { // error\n                        if (err === Async.ERROR_TIMEOUT) {\n                            // SECURITY_ERR is the HTML5 File catch-all error, and there isn't anything\n                            // more fitting for a timeout.\n                            err = new NativeFileSystem.FileError(FileError.SECURITY_ERR);\n                        } else {\n                            err = lastError;\n                        }\n                        \n                        if (errorCallback) {\n                            errorCallback(err);\n                        }\n                    }\n                );\n\n            } else { // There was an error reading the initial directory.\n                errorCallback(NativeFileSystem._nativeToFileError(err));\n            }\n        });\n    };\n\n    /** class: FileReader\n     *\n     * @extends {EventTarget}\n     */\n    NativeFileSystem.FileReader = function () {\n        // TODO (issue #241): this classes should extend EventTarget\n\n        // states\n        this.EMPTY = 0;\n        this.LOADING = 1;\n        this.DONE = 2;\n\n        // readyState is read only\n        this.readyState = this.EMPTY;\n\n        // File or Blob data\n        // TODO (issue #241): readonly attribute any result;\n        // TODO (issue #241): readonly attribute DOMError error;\n\n        // event handler attributes\n        this.onloadstart = null;\n        this.onprogress = null;\n        this.onload = null;\n        this.onabort = null;\n        this.onerror = null;\n        this.onloadend = null;\n    };\n    // TODO (issue #241): extend EventTarget (draft status, not implememnted in webkit)\n    // NativeFileSystem.FileReader.prototype = new NativeFileSystem.EventTarget()\n    \n    NativeFileSystem.FileReader.prototype.readAsArrayBuffer = function (blob) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsArrayBuffer\n    };\n    \n    NativeFileSystem.FileReader.prototype.readAsBinaryString = function (blob) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsBinaryStringAsync\n    };\n    \n    NativeFileSystem.FileReader.prototype.readAsDataURL = function (blob) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsDataURL\n    };\n    \n    NativeFileSystem.FileReader.prototype.abort = function () {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-abort\n    };\n    \n    /** readAsText\n     *\n     * @param {Blob} blob\n     * @param {string} encoding (IANA Encoding Name)\n     */\n    NativeFileSystem.FileReader.prototype.readAsText = function (blob, encoding) {\n        var self = this;\n\n        if (!encoding) {\n            encoding = Encodings.UTF8;\n        }\n        \n        var internalEncoding  = Encodings._IANAToFS(encoding);\n\n        if (this.readyState === this.LOADING) {\n            throw new InvalidateStateError();\n        }\n\n        this.readyState = this.LOADING;\n\n        if (this.onloadstart) {\n            this.onloadstart(); // TODO (issue #241): progressevent\n        }\n\n        brackets.fs.readFile(blob._fullPath, internalEncoding, function (err, data) {\n\n            // TODO (issue #241): the event objects passed to these event handlers is fake and incomplete right now\n            var fakeEvent = {\n                loaded: 0,\n                total: 0\n            };\n\n            // The target for this event is the FileReader and the data/err result is stored in the FileReader\n            fakeEvent.target = self;\n            self.result = data;\n            self.error = NativeFileSystem._nativeToFileError(err);\n\n            if (err) {\n                self.readyState = self.DONE;\n                if (self.onerror) {\n                    self.onerror(fakeEvent);\n                }\n            } else {\n                self.readyState = self.DONE;\n\n                // TODO (issue #241): this should be the file/blob size, but we don't have code to get that yet, so for know assume a file size of 1\n                // and since we read the file in one go, assume 100% after the first read\n                fakeEvent.loaded = 1;\n                fakeEvent.total = 1;\n\n                if (self.onprogress) {\n                    self.onprogress(fakeEvent);\n                }\n\n                // TODO (issue #241): onabort not currently supported since our native implementation doesn't support it\n                // if (self.onabort)\n                //    self.onabort(fakeEvent);\n\n                if (self.onload) {\n                    self.onload(fakeEvent);\n                }\n\n                if (self.onloadend) {\n                    self.onloadend();\n                }\n            }\n\n        });\n    };\n\n    /** class: Blob\n     *\n     * @constructor\n     * param {Entry} entry\n     */\n    NativeFileSystem.Blob = function (fullPath) {\n        this._fullPath = fullPath;\n        \n        // TODO (issue #241): implement, readonly\n        this.size = 0;\n        \n        // TODO (issue #241): implement, readonly\n        this.type = null;\n    };\n    \n    NativeFileSystem.Blob.prototype.slice = function (start, end, contentType) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-slice\n    };\n    \n    /** class: File\n     *\n     * @constructor\n     * param {Entry} entry\n     * @extends {Blob}\n     */\n    NativeFileSystem.File = function (entry) {\n        NativeFileSystem.Blob.call(this, entry.fullPath);\n        \n        // TODO (issue #241): implement, readonly\n        this.name = \"\";\n        \n        // TODO (issue #241): implement, readonly\n        this.lastModifiedDate = null;\n    };\n\n    /** class: FileError\n     *\n     * Implementation of HTML file API error code return class. Note that we don't\n     * actually define the error codes here--we rely on the browser's built-in FileError\n     * class's constants. In other words, external clients of this API should always\n     * use FileError.<constant-name>, not NativeFileSystem.FileError.<constant-name>.\n     *\n     * @constructor\n     * @param {number} code The error code to return with this FileError. Must be\n     * one of the codes defined in the FileError class.\n     */\n    NativeFileSystem.FileError = function (code) {\n        this.code = code || 0;\n    };\n\n    // Define public API\n    exports.NativeFileSystem    = NativeFileSystem;\n});\n\n/*\n * jsTree 1.0-rc3\n * http://jstree.com/\n *\n * Copyright (c) 2010 Ivan Bozhanov (vakata.com)\n *\n * Licensed same as jquery - under the terms of either the MIT License or the GPL Version 2 License\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n *\n * $Date: 2011-02-09 01:17:14 +0200 (ср, 09 февр 2011) $\n * $Revision: 236 $\n */\n\n/*jslint browser: true, onevar: true, undef: true, bitwise: true, strict: true */\n/*global window : false, clearInterval: false, clearTimeout: false, document: false, setInterval: false, setTimeout: false, jQuery: false, navigator: false, XSLTProcessor: false, DOMParser: false, XMLSerializer: false*/\n\n\n\n// top wrapper to prevent multiple inclusion (is this OK?)\n(function () { if(jQuery && jQuery.jstree) { return; }\n\tvar is_ie6 = false, is_ie7 = false, is_ff2 = false;\n\n/* \n * jsTree core\n */\n(function ($) {\n\t// Common functions not related to jsTree \n\t// decided to move them to a `vakata` \"namespace\"\n\t$.vakata = {};\n\t// CSS related functions\n\t$.vakata.css = {\n\t\tget_css : function(rule_name, delete_flag, sheet) {\n\t\t\trule_name = rule_name.toLowerCase();\n\t\t\tvar css_rules = sheet.cssRules || sheet.rules,\n\t\t\t\tj = 0;\n\t\t\tdo {\n\t\t\t\tif(css_rules.length && j > css_rules.length + 5) { return false; }\n\t\t\t\tif(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) {\n\t\t\t\t\tif(delete_flag === true) {\n\t\t\t\t\t\tif(sheet.removeRule) { sheet.removeRule(j); }\n\t\t\t\t\t\tif(sheet.deleteRule) { sheet.deleteRule(j); }\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\telse { return css_rules[j]; }\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile (css_rules[++j]);\n\t\t\treturn false;\n\t\t},\n\t\tadd_css : function(rule_name, sheet) {\n\t\t\tif($.jstree.css.get_css(rule_name, false, sheet)) { return false; }\n\t\t\tif(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); }\n\t\t\treturn $.vakata.css.get_css(rule_name);\n\t\t},\n\t\tremove_css : function(rule_name, sheet) { \n\t\t\treturn $.vakata.css.get_css(rule_name, true, sheet); \n\t\t},\n\t\tadd_sheet : function(opts) {\n\t\t\tvar tmp = false, is_new = true;\n\t\t\tif(opts.str) {\n\t\t\t\tif(opts.title) { tmp = $(\"style[id='\" + opts.title + \"-stylesheet']\")[0]; }\n\t\t\t\tif(tmp) { is_new = false; }\n\t\t\t\telse {\n\t\t\t\t\ttmp = document.createElement(\"style\");\n\t\t\t\t\ttmp.setAttribute('type',\"text/css\");\n\t\t\t\t\tif(opts.title) { tmp.setAttribute(\"id\", opts.title + \"-stylesheet\"); }\n\t\t\t\t}\n\t\t\t\tif(tmp.styleSheet) {\n\t\t\t\t\tif(is_new) { \n\t\t\t\t\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(tmp); \n\t\t\t\t\t\ttmp.styleSheet.cssText = opts.str; \n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\ttmp.styleSheet.cssText = tmp.styleSheet.cssText + \" \" + opts.str; \n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttmp.appendChild(document.createTextNode(opts.str));\n\t\t\t\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(tmp);\n\t\t\t\t}\n\t\t\t\treturn tmp.sheet || tmp.styleSheet;\n\t\t\t}\n\t\t\tif(opts.url) {\n\t\t\t\tif(document.createStyleSheet) {\n\t\t\t\t\ttry { tmp = document.createStyleSheet(opts.url); } catch (e) { }\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttmp\t\t\t= document.createElement('link');\n\t\t\t\t\ttmp.rel\t\t= 'stylesheet';\n\t\t\t\t\ttmp.type\t= 'text/css';\n\t\t\t\t\ttmp.media\t= \"all\";\n\t\t\t\t\ttmp.href\t= opts.url;\n\t\t\t\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(tmp);\n\t\t\t\t\treturn tmp.styleSheet;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t// private variables \n\tvar instances = [],\t\t\t// instance array (used by $.jstree.reference/create/focused)\n\t\tfocused_instance = -1,\t// the index in the instance array of the currently focused instance\n\t\tplugins = {},\t\t\t// list of included plugins\n\t\tprepared_move = {};\t\t// for the move_node function\n\n\t// jQuery plugin wrapper (thanks to jquery UI widget function)\n\t$.fn.jstree = function (settings) {\n\t\tvar isMethodCall = (typeof settings == 'string'), // is this a method call like $().jstree(\"open_node\")\n\t\t\targs = Array.prototype.slice.call(arguments, 1), \n\t\t\treturnValue = this;\n\n\t\t// if a method call execute the method on all selected instances\n\t\tif(isMethodCall) {\n\t\t\tif(settings.substring(0, 1) == '_') { return returnValue; }\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = instances[$.data(this, \"jstree_instance_id\")],\n\t\t\t\t\tmethodValue = (instance && $.isFunction(instance[settings])) ? instance[settings].apply(instance, args) : instance;\n\t\t\t\t\tif(typeof methodValue !== \"undefined\" && (settings.indexOf(\"is_\") === 0 || (methodValue !== true && methodValue !== false))) { returnValue = methodValue; return false; }\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tthis.each(function() {\n\t\t\t\t// extend settings and allow for multiple hashes and $.data\n\t\t\t\tvar instance_id = $.data(this, \"jstree_instance_id\"),\n\t\t\t\t\ta = [],\n\t\t\t\t\tb = settings ? $.extend({}, true, settings) : {},\n\t\t\t\t\tc = $(this), \n\t\t\t\t\ts = false, \n\t\t\t\t\tt = [];\n\t\t\t\ta = a.concat(args);\n\t\t\t\tif(c.data(\"jstree\")) { a.push(c.data(\"jstree\")); }\n\t\t\t\tb = a.length ? $.extend.apply(null, [true, b].concat(a)) : b;\n\n\t\t\t\t// if an instance already exists, destroy it first\n\t\t\t\tif(typeof instance_id !== \"undefined\" && instances[instance_id]) { instances[instance_id].destroy(); }\n\t\t\t\t// push a new empty object to the instances array\n\t\t\t\tinstance_id = parseInt(instances.push({}),10) - 1;\n\t\t\t\t// store the jstree instance id to the container element\n\t\t\t\t$.data(this, \"jstree_instance_id\", instance_id);\n\t\t\t\t// clean up all plugins\n\t\t\t\tb.plugins = $.isArray(b.plugins) ? b.plugins : $.jstree.defaults.plugins.slice();\n\t\t\t\tb.plugins.unshift(\"core\");\n\t\t\t\t// only unique plugins\n\t\t\t\tb.plugins = b.plugins.sort().join(\",,\").replace(/(,|^)([^,]+)(,,\\2)+(,|$)/g,\"$1$2$4\").replace(/,,+/g,\",\").replace(/,$/,\"\").split(\",\");\n\n\t\t\t\t// extend defaults with passed data\n\t\t\t\ts = $.extend(true, {}, $.jstree.defaults, b);\n\t\t\t\ts.plugins = b.plugins;\n\t\t\t\t$.each(plugins, function (i, val) { \n\t\t\t\t\tif($.inArray(i, s.plugins) === -1) { s[i] = null; delete s[i]; } \n\t\t\t\t\telse { t.push(i); }\n\t\t\t\t});\n\t\t\t\ts.plugins = t;\n\n\t\t\t\t// push the new object to the instances array (at the same time set the default classes to the container) and init\n\t\t\t\tinstances[instance_id] = new $.jstree._instance(instance_id, $(this).addClass(\"jstree jstree-\" + instance_id), s); \n\t\t\t\t// init all activated plugins for this instance\n\t\t\t\t$.each(instances[instance_id]._get_settings().plugins, function (i, val) { instances[instance_id].data[val] = {}; });\n\t\t\t\t$.each(instances[instance_id]._get_settings().plugins, function (i, val) { if(plugins[val]) { plugins[val].__init.apply(instances[instance_id]); } });\n\t\t\t\t// initialize the instance\n\t\t\t\tsetTimeout(function() { if(instances[instance_id]) { instances[instance_id].init(); } }, 0);\n\t\t\t});\n\t\t}\n\t\t// return the jquery selection (or if it was a method call that returned a value - the returned value)\n\t\treturn returnValue;\n\t};\n\t// object to store exposed functions and objects\n\t$.jstree = {\n\t\tdefaults : {\n\t\t\tplugins : []\n\t\t},\n\t\t_focused : function () { return instances[focused_instance] || null; },\n\t\t_reference : function (needle) { \n\t\t\t// get by instance id\n\t\t\tif(instances[needle]) { return instances[needle]; }\n\t\t\t// get by DOM (if still no luck - return null\n\t\t\tvar o = $(needle); \n\t\t\tif(!o.length && typeof needle === \"string\") { o = $(\"#\" + needle); }\n\t\t\tif(!o.length) { return null; }\n\t\t\treturn instances[o.closest(\".jstree\").data(\"jstree_instance_id\")] || null; \n\t\t},\n\t\t_instance : function (index, container, settings) { \n\t\t\t// for plugins to store data in\n\t\t\tthis.data = { core : {} };\n\t\t\tthis.get_settings\t= function () { return $.extend(true, {}, settings); };\n\t\t\tthis._get_settings\t= function () { return settings; };\n\t\t\tthis.get_index\t\t= function () { return index; };\n\t\t\tthis.get_container\t= function () { return container; };\n\t\t\tthis.get_container_ul = function () { return container.children(\"ul:eq(0)\"); };\n\t\t\tthis._set_settings\t= function (s) { \n\t\t\t\tsettings = $.extend(true, {}, settings, s);\n\t\t\t};\n\t\t},\n\t\t_fn : { },\n\t\tplugin : function (pname, pdata) {\n\t\t\tpdata = $.extend({}, {\n\t\t\t\t__init\t\t: $.noop, \n\t\t\t\t__destroy\t: $.noop,\n\t\t\t\t_fn\t\t\t: {},\n\t\t\t\tdefaults\t: false\n\t\t\t}, pdata);\n\t\t\tplugins[pname] = pdata;\n\n\t\t\t$.jstree.defaults[pname] = pdata.defaults;\n\t\t\t$.each(pdata._fn, function (i, val) {\n\t\t\t\tval.plugin\t\t= pname;\n\t\t\t\tval.old\t\t\t= $.jstree._fn[i];\n\t\t\t\t$.jstree._fn[i] = function () {\n\t\t\t\t\tvar rslt,\n\t\t\t\t\t\tfunc = val,\n\t\t\t\t\t\targs = Array.prototype.slice.call(arguments),\n\t\t\t\t\t\tevnt = new $.Event(\"before.jstree\"),\n\t\t\t\t\t\trlbk = false;\n\n\t\t\t\t\tif(this.data.core.locked === true && i !== \"unlock\" && i !== \"is_locked\") { return; }\n\n\t\t\t\t\t// Check if function belongs to the included plugins of this instance\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif(func && func.plugin && $.inArray(func.plugin, this._get_settings().plugins) !== -1) { break; }\n\t\t\t\t\t\tfunc = func.old;\n\t\t\t\t\t} while(func);\n\t\t\t\t\tif(!func) { return; }\n\n\t\t\t\t\t// context and function to trigger events, then finally call the function\n\t\t\t\t\tif(i.indexOf(\"_\") === 0) {\n\t\t\t\t\t\trslt = func.apply(this, args);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\trslt = this.get_container().triggerHandler(evnt, { \"func\" : i, \"inst\" : this, \"args\" : args, \"plugin\" : func.plugin });\n\t\t\t\t\t\tif(rslt === false) { return; }\n\t\t\t\t\t\tif(typeof rslt !== \"undefined\") { args = rslt; }\n\n\t\t\t\t\t\trslt = func.apply(\n\t\t\t\t\t\t\t$.extend({}, this, { \n\t\t\t\t\t\t\t\t__callback : function (data) { \n\t\t\t\t\t\t\t\t\tthis.get_container().triggerHandler( i + '.jstree', { \"inst\" : this, \"args\" : args, \"rslt\" : data, \"rlbk\" : rlbk });\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t__rollback : function () { \n\t\t\t\t\t\t\t\t\trlbk = this.get_rollback();\n\t\t\t\t\t\t\t\t\treturn rlbk;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t__call_old : function (replace_arguments) {\n\t\t\t\t\t\t\t\t\treturn func.old.apply(this, (replace_arguments ? Array.prototype.slice.call(arguments, 1) : args ) );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}), args);\n\t\t\t\t\t}\n\n\t\t\t\t\t// return the result\n\t\t\t\t\treturn rslt;\n\t\t\t\t};\n\t\t\t\t$.jstree._fn[i].old = val.old;\n\t\t\t\t$.jstree._fn[i].plugin = pname;\n\t\t\t});\n\t\t},\n\t\trollback : function (rb) {\n\t\t\tif(rb) {\n\t\t\t\tif(!$.isArray(rb)) { rb = [ rb ]; }\n\t\t\t\t$.each(rb, function (i, val) {\n\t\t\t\t\tinstances[val.i].set_rollback(val.h, val.d);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\t// set the prototype for all instances\n\t$.jstree._fn = $.jstree._instance.prototype = {};\n\n\t// load the css when DOM is ready\n\t$(function() {\n\t\t// code is copied from jQuery ($.browser is deprecated + there is a bug in IE)\n\t\tvar u = navigator.userAgent.toLowerCase(),\n\t\t\tv = (u.match( /.+?(?:rv|it|ra|ie)[\\/: ]([\\d.]+)/ ) || [0,'0'])[1],\n\t\t\tcss_string = '' + \n\t\t\t\t'.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; } ' + \n\t\t\t\t'.jstree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; } ' + \n\t\t\t\t'.jstree-rtl li { margin-left:0; margin-right:18px; } ' + \n\t\t\t\t'.jstree > ul > li { margin-left:0px; } ' + \n\t\t\t\t'.jstree-rtl > ul > li { margin-right:0px; } ' + \n\t\t\t\t'.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; } ' + \n\t\t\t\t'.jstree a { display:inline-block; line-height:16px; height:16px; color:black; white-space:nowrap; text-decoration:none; padding:1px 2px; margin:0; } ' + \n\t\t\t\t'.jstree a:focus { outline: none; } ' + \n\t\t\t\t'.jstree a > ins { height:16px; width:16px; } ' + \n\t\t\t\t'.jstree a > .jstree-icon { margin-right:3px; } ' + \n\t\t\t\t'.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; } ' + \n\t\t\t\t'li.jstree-open > ul { display:block; } ' + \n\t\t\t\t'li.jstree-closed > ul { display:none; } ';\n\t\t// Correct IE 6 (does not support the > CSS selector)\n\t\tif(/msie/.test(u) && parseInt(v, 10) == 6) { \n\t\t\tis_ie6 = true;\n\n\t\t\t// fix image flicker and lack of caching\n\t\t\ttry {\n\t\t\t\tdocument.execCommand(\"BackgroundImageCache\", false, true);\n\t\t\t} catch (err) { }\n\n\t\t\tcss_string += '' + \n\t\t\t\t'.jstree li { height:18px; margin-left:0; margin-right:0; } ' + \n\t\t\t\t'.jstree li li { margin-left:18px; } ' + \n\t\t\t\t'.jstree-rtl li li { margin-left:0px; margin-right:18px; } ' + \n\t\t\t\t'li.jstree-open ul { display:block; } ' + \n\t\t\t\t'li.jstree-closed ul { display:none !important; } ' + \n\t\t\t\t'.jstree li a { display:inline; border-width:0 !important; padding:0px 2px !important; } ' + \n\t\t\t\t'.jstree li a ins { height:16px; width:16px; margin-right:3px; } ' + \n\t\t\t\t'.jstree-rtl li a ins { margin-right:0px; margin-left:3px; } ';\n\t\t}\n\t\t// Correct IE 7 (shifts anchor nodes onhover)\n\t\tif(/msie/.test(u) && parseInt(v, 10) == 7) { \n\t\t\tis_ie7 = true;\n\t\t\tcss_string += '.jstree li a { border-width:0 !important; padding:0px 2px !important; } ';\n\t\t}\n\t\t// correct ff2 lack of display:inline-block\n\t\tif(!/compatible/.test(u) && /mozilla/.test(u) && parseFloat(v, 10) < 1.9) {\n\t\t\tis_ff2 = true;\n\t\t\tcss_string += '' + \n\t\t\t\t'.jstree ins { display:-moz-inline-box; } ' + \n\t\t\t\t'.jstree li { line-height:12px; } ' + // WHY??\n\t\t\t\t'.jstree a { display:-moz-inline-box; } ' + \n\t\t\t\t'.jstree .jstree-no-icons .jstree-checkbox { display:-moz-inline-stack !important; } ';\n\t\t\t\t/* this shouldn't be here as it is theme specific */\n\t\t}\n\t\t// the default stylesheet\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n\t});\n\n\t// core functions (open, close, create, update, delete)\n\t$.jstree.plugin(\"core\", {\n\t\t__init : function () {\n\t\t\tthis.data.core.locked = false;\n\t\t\tthis.data.core.to_open = this.get_settings().core.initially_open;\n\t\t\tthis.data.core.to_load = this.get_settings().core.initially_load;\n\t\t},\n\t\tdefaults : { \n\t\t\thtml_titles\t: false,\n\t\t\tanimation\t: 500,\n\t\t\tinitially_open : [],\n\t\t\tinitially_load : [],\n\t\t\topen_parents : true,\n\t\t\tnotify_plugins : true,\n\t\t\trtl\t\t\t: false,\n\t\t\tload_open\t: false,\n\t\t\tstrings\t\t: {\n\t\t\t\tloading\t\t: \"Loading ...\",\n\t\t\t\tnew_node\t: \"New node\",\n\t\t\t\tmultiple_selection : \"Multiple selection\"\n\t\t\t}\n\t\t},\n\t\t_fn : { \n\t\t\tinit\t: function () { \n\t\t\t\tthis.set_focus(); \n\t\t\t\tif(this._get_settings().core.rtl) {\n\t\t\t\t\tthis.get_container().addClass(\"jstree-rtl\").css(\"direction\", \"rtl\");\n\t\t\t\t}\n\t\t\t\tthis.get_container().html(\"<ul><li class='jstree-last jstree-leaf'><ins>&#160;</ins><a class='jstree-loading' href='#'><ins class='jstree-icon'>&#160;</ins>\" + this._get_string(\"loading\") + \"</a></li></ul>\");\n\t\t\t\tthis.data.core.li_height = this.get_container_ul().find(\"li.jstree-closed, li.jstree-leaf\").eq(0).height() || 18;\n\n\t\t\t\tthis.get_container()\n\t\t\t\t\t.delegate(\"li > ins\", \"click.jstree\", $.proxy(function (event) {\n\t\t\t\t\t\t\tvar trgt = $(event.target);\n\t\t\t\t\t\t\t// if(trgt.is(\"ins\") && event.pageY - trgt.offset().top < this.data.core.li_height) { this.toggle_node(trgt); }\n\t\t\t\t\t\t\tthis.toggle_node(trgt);\n\t\t\t\t\t\t}, this))\n\t\t\t\t\t.bind(\"mousedown.jstree\", $.proxy(function () { \n\t\t\t\t\t\t\tthis.set_focus(); // This used to be setTimeout(set_focus,0) - why?\n\t\t\t\t\t\t}, this))\n\t\t\t\t\t.bind(\"dblclick.jstree\", function (event) { \n\t\t\t\t\t\tvar sel;\n\t\t\t\t\t\tif(document.selection && document.selection.empty) { document.selection.empty(); }\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif(window.getSelection) {\n\t\t\t\t\t\t\t\tsel = window.getSelection();\n\t\t\t\t\t\t\t\ttry { \n\t\t\t\t\t\t\t\t\tsel.removeAllRanges();\n\t\t\t\t\t\t\t\t\tsel.collapse();\n\t\t\t\t\t\t\t\t} catch (err) { }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\tif(this._get_settings().core.notify_plugins) {\n\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t.bind(\"load_node.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\t\t\tvar o = this._get_node(data.rslt.obj),\n\t\t\t\t\t\t\t\t\tt = this;\n\t\t\t\t\t\t\t\tif(o === -1) { o = this.get_container_ul(); }\n\t\t\t\t\t\t\t\tif(!o.length) { return; }\n\t\t\t\t\t\t\t\to.find(\"li\").each(function () {\n\t\t\t\t\t\t\t\t\tvar th = $(this);\n\t\t\t\t\t\t\t\t\tif(th.data(\"jstree\")) {\n\t\t\t\t\t\t\t\t\t\t$.each(th.data(\"jstree\"), function (plugin, values) {\n\t\t\t\t\t\t\t\t\t\t\tif(t.data[plugin] && $.isFunction(t[\"_\" + plugin + \"_notify\"])) {\n\t\t\t\t\t\t\t\t\t\t\t\tt[\"_\" + plugin + \"_notify\"].call(t, th, values);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t}\n\t\t\t\tif(this._get_settings().core.load_open) {\n\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t.bind(\"load_node.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\t\t\tvar o = this._get_node(data.rslt.obj),\n\t\t\t\t\t\t\t\t\tt = this;\n\t\t\t\t\t\t\t\tif(o === -1) { o = this.get_container_ul(); }\n\t\t\t\t\t\t\t\tif(!o.length) { return; }\n\t\t\t\t\t\t\t\to.find(\"li.jstree-open:not(:has(ul))\").each(function () {\n\t\t\t\t\t\t\t\t\tt.load_node(this, $.noop, $.noop);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t}\n\t\t\t\tthis.__callback();\n\t\t\t\tthis.load_node(-1, function () { this.loaded(); this.reload_nodes(); });\n\t\t\t},\n\t\t\tdestroy\t: function () { \n\t\t\t\tvar i,\n\t\t\t\t\tn = this.get_index(),\n\t\t\t\t\ts = this._get_settings(),\n\t\t\t\t\t_this = this;\n\n\t\t\t\t$.each(s.plugins, function (i, val) {\n\t\t\t\t\ttry { plugins[val].__destroy.apply(_this); } catch(err) { }\n\t\t\t\t});\n\t\t\t\tthis.__callback();\n\t\t\t\t// set focus to another instance if this one is focused\n\t\t\t\tif(this.is_focused()) { \n\t\t\t\t\tfor(i in instances) { \n\t\t\t\t\t\tif(instances.hasOwnProperty(i) && i != n) { \n\t\t\t\t\t\t\tinstances[i].set_focus(); \n\t\t\t\t\t\t\tbreak; \n\t\t\t\t\t\t} \n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// if no other instance found\n\t\t\t\tif(n === focused_instance) { focused_instance = -1; }\n\t\t\t\t// remove all traces of jstree in the DOM (only the ones set using jstree*) and cleans all events\n\t\t\t\tthis.get_container()\n\t\t\t\t\t.unbind(\".jstree\")\n\t\t\t\t\t.undelegate(\".jstree\")\n\t\t\t\t\t.removeData(\"jstree_instance_id\")\n\t\t\t\t\t.find(\"[class^='jstree']\")\n\t\t\t\t\t\t.andSelf()\n\t\t\t\t\t\t.attr(\"class\", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });\n\t\t\t\t$(document)\n\t\t\t\t\t.unbind(\".jstree-\" + n)\n\t\t\t\t\t.undelegate(\".jstree-\" + n);\n\t\t\t\t// remove the actual data\n\t\t\t\tinstances[n] = null;\n\t\t\t\tdelete instances[n];\n\t\t\t},\n\n\t\t\t_core_notify : function (n, data) {\n\t\t\t\tif(data.opened) {\n\t\t\t\t\tthis.open_node(n, false, true);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tlock : function () {\n\t\t\t\tthis.data.core.locked = true;\n\t\t\t\tthis.get_container().children(\"ul\").addClass(\"jstree-locked\").css(\"opacity\",\"0.7\");\n\t\t\t\tthis.__callback({});\n\t\t\t},\n\t\t\tunlock : function () {\n\t\t\t\tthis.data.core.locked = false;\n\t\t\t\tthis.get_container().children(\"ul\").removeClass(\"jstree-locked\").css(\"opacity\",\"1\");\n\t\t\t\tthis.__callback({});\n\t\t\t},\n\t\t\tis_locked : function () { return this.data.core.locked; },\n\t\t\tsave_opened : function () {\n\t\t\t\tvar _this = this;\n\t\t\t\tthis.data.core.to_open = [];\n\t\t\t\tthis.get_container_ul().find(\"li.jstree-open\").each(function () { \n\t\t\t\t\tif(this.id) { _this.data.core.to_open.push(\"#\" + this.id.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\")); }\n\t\t\t\t});\n\t\t\t\tthis.__callback(_this.data.core.to_open);\n\t\t\t},\n\t\t\tsave_loaded : function () { },\n\t\t\treload_nodes : function (is_callback) {\n\t\t\t\tvar _this = this,\n\t\t\t\t\tdone = true,\n\t\t\t\t\tcurrent = [],\n\t\t\t\t\tremaining = [];\n\t\t\t\tif(!is_callback) { \n\t\t\t\t\tthis.data.core.reopen = false; \n\t\t\t\t\tthis.data.core.refreshing = true; \n\t\t\t\t\tthis.data.core.to_open = $.map($.makeArray(this.data.core.to_open), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n\t\t\t\t\tthis.data.core.to_load = $.map($.makeArray(this.data.core.to_load), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n\t\t\t\t\tif(this.data.core.to_open.length) {\n\t\t\t\t\t\tthis.data.core.to_load = this.data.core.to_load.concat(this.data.core.to_open);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(this.data.core.to_load.length) {\n\t\t\t\t\t$.each(this.data.core.to_load, function (i, val) {\n\t\t\t\t\t\tif(val == \"#\") { return true; }\n\t\t\t\t\t\tif($(val).length) { current.push(val); }\n\t\t\t\t\t\telse { remaining.push(val); }\n\t\t\t\t\t});\n\t\t\t\t\tif(current.length) {\n\t\t\t\t\t\tthis.data.core.to_load = remaining;\n\t\t\t\t\t\t$.each(current, function (i, val) { \n\t\t\t\t\t\t\tif(!_this._is_loaded(val)) {\n\t\t\t\t\t\t\t\t_this.load_node(val, function () { _this.reload_nodes(true); }, function () { _this.reload_nodes(true); });\n\t\t\t\t\t\t\t\tdone = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(this.data.core.to_open.length) {\n\t\t\t\t\t$.each(this.data.core.to_open, function (i, val) {\n\t\t\t\t\t\t_this.open_node(val, false, true); \n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(done) { \n\t\t\t\t\t// TODO: find a more elegant approach to syncronizing returning requests\n\t\t\t\t\tif(this.data.core.reopen) { clearTimeout(this.data.core.reopen); }\n\t\t\t\t\tthis.data.core.reopen = setTimeout(function () { _this.__callback({}, _this); }, 50);\n\t\t\t\t\tthis.data.core.refreshing = false;\n\t\t\t\t\tthis.reopen();\n\t\t\t\t}\n\t\t\t},\n\t\t\treopen : function () {\n\t\t\t\tvar _this = this;\n\t\t\t\tif(this.data.core.to_open.length) {\n\t\t\t\t\t$.each(this.data.core.to_open, function (i, val) {\n\t\t\t\t\t\t_this.open_node(val, false, true); \n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthis.__callback({});\n\t\t\t},\n\t\t\trefresh : function (obj) {\n\t\t\t\tvar _this = this;\n\t\t\t\tthis.save_opened();\n\t\t\t\tif(!obj) { obj = -1; }\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj) { obj = -1; }\n\t\t\t\tif(obj !== -1) { obj.children(\"UL\").remove(); }\n\t\t\t\telse { this.get_container_ul().empty(); }\n\t\t\t\tthis.load_node(obj, function () { _this.__callback({ \"obj\" : obj}); _this.reload_nodes(); });\n\t\t\t},\n\t\t\t// Dummy function to fire after the first load (so that there is a jstree.loaded event)\n\t\t\tloaded\t: function () { \n\t\t\t\tthis.__callback(); \n\t\t\t},\n\t\t\t// deal with focus\n\t\t\tset_focus\t: function () { \n\t\t\t\tif(this.is_focused()) { return; }\n\t\t\t\tvar f = $.jstree._focused();\n\t\t\t\tif(f) { f.unset_focus(); }\n\n\t\t\t\tthis.get_container().addClass(\"jstree-focused\"); \n\t\t\t\tfocused_instance = this.get_index(); \n\t\t\t\tthis.__callback();\n\t\t\t},\n\t\t\tis_focused\t: function () { \n\t\t\t\treturn focused_instance == this.get_index(); \n\t\t\t},\n\t\t\tunset_focus\t: function () {\n\t\t\t\tif(this.is_focused()) {\n\t\t\t\t\tthis.get_container().removeClass(\"jstree-focused\"); \n\t\t\t\t\tfocused_instance = -1; \n\t\t\t\t}\n\t\t\t\tthis.__callback();\n\t\t\t},\n\n\t\t\t// traverse\n\t\t\t_get_node\t\t: function (obj) { \n\t\t\t\tvar $obj = $(obj, this.get_container()); \n\t\t\t\tif($obj.is(\".jstree\") || obj == -1) { return -1; } \n\t\t\t\t$obj = $obj.closest(\"li\", this.get_container()); \n\t\t\t\treturn $obj.length ? $obj : false; \n\t\t\t},\n\t\t\t_get_next\t\t: function (obj, strict) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj === -1) { return this.get_container().find(\"> ul > li:first-child\"); }\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tif(strict) { return (obj.nextAll(\"li\").size() > 0) ? obj.nextAll(\"li:eq(0)\") : false; }\n\n\t\t\t\tif(obj.hasClass(\"jstree-open\")) { return obj.find(\"li:eq(0)\"); }\n\t\t\t\telse if(obj.nextAll(\"li\").size() > 0) { return obj.nextAll(\"li:eq(0)\"); }\n\t\t\t\telse { return obj.parentsUntil(\".jstree\",\"li\").next(\"li\").eq(0); }\n\t\t\t},\n\t\t\t_get_prev\t\t: function (obj, strict) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj === -1) { return this.get_container().find(\"> ul > li:last-child\"); }\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tif(strict) { return (obj.prevAll(\"li\").length > 0) ? obj.prevAll(\"li:eq(0)\") : false; }\n\n\t\t\t\tif(obj.prev(\"li\").length) {\n\t\t\t\t\tobj = obj.prev(\"li\").eq(0);\n\t\t\t\t\twhile(obj.hasClass(\"jstree-open\")) { obj = obj.children(\"ul:eq(0)\").children(\"li:last\"); }\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t\telse { var o = obj.parentsUntil(\".jstree\",\"li:eq(0)\"); return o.length ? o : false; }\n\t\t\t},\n\t\t\t_get_parent\t\t: function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj == -1 || !obj.length) { return false; }\n\t\t\t\tvar o = obj.parentsUntil(\".jstree\", \"li:eq(0)\");\n\t\t\t\treturn o.length ? o : -1;\n\t\t\t},\n\t\t\t_get_children\t: function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj === -1) { return this.get_container().children(\"ul:eq(0)\").children(\"li\"); }\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\treturn obj.children(\"ul:eq(0)\").children(\"li\");\n\t\t\t},\n\t\t\tget_path\t\t: function (obj, id_mode) {\n\t\t\t\tvar p = [],\n\t\t\t\t\t_this = this;\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj === -1 || !obj || !obj.length) { return false; }\n\t\t\t\tobj.parentsUntil(\".jstree\", \"li\").each(function () {\n\t\t\t\t\tp.push( id_mode ? this.id : _this.get_text(this) );\n\t\t\t\t});\n\t\t\t\tp.reverse();\n\t\t\t\tp.push( id_mode ? obj.attr(\"id\") : this.get_text(obj) );\n\t\t\t\treturn p;\n\t\t\t},\n\n\t\t\t// string functions\n\t\t\t_get_string : function (key) {\n\t\t\t\treturn this._get_settings().core.strings[key] || key;\n\t\t\t},\n\n\t\t\tis_open\t\t: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass(\"jstree-open\"); },\n\t\t\tis_closed\t: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass(\"jstree-closed\"); },\n\t\t\tis_leaf\t\t: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass(\"jstree-leaf\"); },\n\t\t\tcorrect_state\t: function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj || obj === -1) { return false; }\n\t\t\t\tobj.removeClass(\"jstree-closed jstree-open\").addClass(\"jstree-leaf\").children(\"ul\").remove();\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\t// open/close\n\t\t\topen_node\t: function (obj, callback, skip_animation) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tif(!obj.hasClass(\"jstree-closed\")) { if(callback) { callback.call(); } return false; }\n\t\t\t\tvar s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,\n\t\t\t\t\tt = this;\n\t\t\t\tif(!this._is_loaded(obj)) {\n\t\t\t\t\tobj.children(\"a\").addClass(\"jstree-loading\");\n\t\t\t\t\tthis.load_node(obj, function () { t.open_node(obj, callback, skip_animation); }, callback);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(this._get_settings().core.open_parents) {\n\t\t\t\t\t\tobj.parentsUntil(\".jstree\",\".jstree-closed\").each(function () {\n\t\t\t\t\t\t\tt.open_node(this, false, true);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif(s) { obj.children(\"ul\").css(\"display\",\"none\"); }\n\t\t\t\t\tobj.removeClass(\"jstree-closed\").addClass(\"jstree-open\").children(\"a\").removeClass(\"jstree-loading\");\n\t\t\t\t\tif(s) { obj.children(\"ul\").stop(true, true).slideDown(s, function () { this.style.display = \"\"; t.after_open(obj); }); }\n\t\t\t\t\telse { t.after_open(obj); }\n\t\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t\t\tif(callback) { callback.call(); }\n\t\t\t\t}\n\t\t\t},\n\t\t\tafter_open\t: function (obj) { this.__callback({ \"obj\" : obj }); },\n\t\t\tclose_node\t: function (obj, skip_animation) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,\n\t\t\t\t\tt = this;\n\t\t\t\tif(!obj.length || !obj.hasClass(\"jstree-open\")) { return false; }\n\t\t\t\tif(s) { obj.children(\"ul\").attr(\"style\",\"display:block !important\"); }\n\t\t\t\tobj.removeClass(\"jstree-open\").addClass(\"jstree-closed\");\n\t\t\t\tif(s) { obj.children(\"ul\").stop(true, true).slideUp(s, function () { this.style.display = \"\"; t.after_close(obj); }); }\n\t\t\t\telse { t.after_close(obj); }\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\tafter_close\t: function (obj) { this.__callback({ \"obj\" : obj }); },\n\t\t\ttoggle_node\t: function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj.hasClass(\"jstree-closed\")) { return this.open_node(obj); }\n\t\t\t\tif(obj.hasClass(\"jstree-open\")) { return this.close_node(obj); }\n\t\t\t},\n\t\t\topen_all\t: function (obj, do_animation, original_obj) {\n\t\t\t\tobj = obj ? this._get_node(obj) : -1;\n\t\t\t\tif(!obj || obj === -1) { obj = this.get_container_ul(); }\n\t\t\t\tif(original_obj) { \n\t\t\t\t\tobj = obj.find(\"li.jstree-closed\");\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\toriginal_obj = obj;\n\t\t\t\t\tif(obj.is(\".jstree-closed\")) { obj = obj.find(\"li.jstree-closed\").andSelf(); }\n\t\t\t\t\telse { obj = obj.find(\"li.jstree-closed\"); }\n\t\t\t\t}\n\t\t\t\tvar _this = this;\n\t\t\t\tobj.each(function () { \n\t\t\t\t\tvar __this = this; \n\t\t\t\t\tif(!_this._is_loaded(this)) { _this.open_node(this, function() { _this.open_all(__this, do_animation, original_obj); }, !do_animation); }\n\t\t\t\t\telse { _this.open_node(this, false, !do_animation); }\n\t\t\t\t});\n\t\t\t\t// so that callback is fired AFTER all nodes are open\n\t\t\t\tif(original_obj.find('li.jstree-closed').length === 0) { this.__callback({ \"obj\" : original_obj }); }\n\t\t\t},\n\t\t\tclose_all\t: function (obj, do_animation) {\n\t\t\t\tvar _this = this;\n\t\t\t\tobj = obj ? this._get_node(obj) : this.get_container();\n\t\t\t\tif(!obj || obj === -1) { obj = this.get_container_ul(); }\n\t\t\t\tobj.find(\"li.jstree-open\").andSelf().each(function () { _this.close_node(this, !do_animation); });\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\tclean_node\t: function (obj) {\n\t\t\t\tobj = obj && obj != -1 ? $(obj) : this.get_container_ul();\n\t\t\t\tobj = obj.is(\"li\") ? obj.find(\"li\").andSelf() : obj.find(\"li\");\n\t\t\t\tobj.removeClass(\"jstree-last\")\n\t\t\t\t\t.filter(\"li:last-child\").addClass(\"jstree-last\").end()\n\t\t\t\t\t.filter(\":has(li)\")\n\t\t\t\t\t\t.not(\".jstree-open\").removeClass(\"jstree-leaf\").addClass(\"jstree-closed\");\n\t\t\t\tobj.not(\".jstree-open, .jstree-closed\").addClass(\"jstree-leaf\").children(\"ul\").remove();\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\t// rollback\n\t\t\tget_rollback : function () { \n\t\t\t\tthis.__callback();\n\t\t\t\treturn { i : this.get_index(), h : this.get_container().children(\"ul\").clone(true), d : this.data }; \n\t\t\t},\n\t\t\tset_rollback : function (html, data) {\n\t\t\t\tthis.get_container().empty().append(html);\n\t\t\t\tthis.data = data;\n\t\t\t\tthis.__callback();\n\t\t\t},\n\t\t\t// Dummy functions to be overwritten by any datastore plugin included\n\t\t\tload_node\t: function (obj, s_call, e_call) { this.__callback({ \"obj\" : obj }); },\n\t\t\t_is_loaded\t: function (obj) { return true; },\n\n\t\t\t// Basic operations: create\n\t\t\tcreate_node\t: function (obj, position, js, callback, is_loaded) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tposition = typeof position === \"undefined\" ? \"last\" : position;\n\t\t\t\tvar d = $(\"<li />\"),\n\t\t\t\t\ts = this._get_settings().core,\n\t\t\t\t\ttmp;\n\n\t\t\t\tif(obj !== -1 && !obj.length) { return false; }\n\t\t\t\tif(!is_loaded && !this._is_loaded(obj)) { this.load_node(obj, function () { this.create_node(obj, position, js, callback, true); }); return false; }\n\n\t\t\t\tthis.__rollback();\n\n\t\t\t\tif(typeof js === \"string\") { js = { \"data\" : js }; }\n\t\t\t\tif(!js) { js = {}; }\n\t\t\t\tif(js.attr) { d.attr(js.attr); }\n\t\t\t\tif(js.metadata) { d.data(js.metadata); }\n\t\t\t\tif(js.state) { d.addClass(\"jstree-\" + js.state); }\n\t\t\t\tif(!js.data) { js.data = this._get_string(\"new_node\"); }\n\t\t\t\tif(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }\n\t\t\t\t$.each(js.data, function (i, m) {\n\t\t\t\t\ttmp = $(\"<a />\");\n\t\t\t\t\tif($.isFunction(m)) { m = m.call(this, js); }\n\t\t\t\t\tif(typeof m == \"string\") { tmp.attr('href','#')[ s.html_titles ? \"html\" : \"text\" ](m); }\n\t\t\t\t\telse {\n\t\t\t\t\t\tif(!m.attr) { m.attr = {}; }\n\t\t\t\t\t\tif(!m.attr.href) { m.attr.href = '#'; }\n\t\t\t\t\t\ttmp.attr(m.attr)[ s.html_titles ? \"html\" : \"text\" ](m.title);\n\t\t\t\t\t\tif(m.language) { tmp.addClass(m.language); }\n\t\t\t\t\t}\n\t\t\t\t\ttmp.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n\t\t\t\t\tif(!m.icon && js.icon) { m.icon = js.icon; }\n\t\t\t\t\tif(m.icon) { \n\t\t\t\t\t\tif(m.icon.indexOf(\"/\") === -1) { tmp.children(\"ins\").addClass(m.icon); }\n\t\t\t\t\t\telse { tmp.children(\"ins\").css(\"background\",\"url('\" + m.icon + \"') center center no-repeat\"); }\n\t\t\t\t\t}\n\t\t\t\t\td.append(tmp);\n\t\t\t\t});\n\t\t\t\td.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n\t\t\t\tif(obj === -1) {\n\t\t\t\t\tobj = this.get_container();\n\t\t\t\t\tif(position === \"before\") { position = \"first\"; }\n\t\t\t\t\tif(position === \"after\") { position = \"last\"; }\n\t\t\t\t}\n\t\t\t\tswitch(position) {\n\t\t\t\t\tcase \"before\": obj.before(d); tmp = this._get_parent(obj); break;\n\t\t\t\t\tcase \"after\" : obj.after(d);  tmp = this._get_parent(obj); break;\n\t\t\t\t\tcase \"inside\":\n\t\t\t\t\tcase \"first\" :\n\t\t\t\t\t\tif(!obj.children(\"ul\").length) { obj.append(\"<ul />\"); }\n\t\t\t\t\t\tobj.children(\"ul\").prepend(d);\n\t\t\t\t\t\ttmp = obj;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"last\":\n\t\t\t\t\t\tif(!obj.children(\"ul\").length) { obj.append(\"<ul />\"); }\n\t\t\t\t\t\tobj.children(\"ul\").append(d);\n\t\t\t\t\t\ttmp = obj;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif(!obj.children(\"ul\").length) { obj.append(\"<ul />\"); }\n\t\t\t\t\t\tif(!position) { position = 0; }\n\t\t\t\t\t\ttmp = obj.children(\"ul\").children(\"li\").eq(position);\n\t\t\t\t\t\tif(tmp.length) { tmp.before(d); }\n\t\t\t\t\t\telse { obj.children(\"ul\").append(d); }\n\t\t\t\t\t\ttmp = obj;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif(tmp === -1 || tmp.get(0) === this.get_container().get(0)) { tmp = -1; }\n\t\t\t\tthis.clean_node(tmp);\n\t\t\t\tthis.__callback({ \"obj\" : d, \"parent\" : tmp });\n\t\t\t\tif(callback) { callback.call(this, d); }\n\t\t\t\treturn d;\n\t\t\t},\n\t\t\t// Basic operations: rename (deal with text)\n\t\t\tget_text\t: function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tvar s = this._get_settings().core.html_titles;\n\t\t\t\tobj = obj.children(\"a:eq(0)\");\n\t\t\t\tif(s) {\n\t\t\t\t\tobj = obj.clone();\n\t\t\t\t\tobj.children(\"INS\").remove();\n\t\t\t\t\treturn obj.html();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tobj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n\t\t\t\t\treturn obj.nodeValue;\n\t\t\t\t}\n\t\t\t},\n\t\t\tset_text\t: function (obj, val) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tobj = obj.children(\"a:eq(0)\");\n\t\t\t\tif(this._get_settings().core.html_titles) {\n\t\t\t\t\tvar tmp = obj.children(\"INS\").clone();\n\t\t\t\t\tobj.html(val).prepend(tmp);\n\t\t\t\t\tthis.__callback({ \"obj\" : obj, \"name\" : val });\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tobj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n\t\t\t\t\tthis.__callback({ \"obj\" : obj, \"name\" : val });\n\t\t\t\t\treturn (obj.nodeValue = val);\n\t\t\t\t}\n\t\t\t},\n\t\t\trename_node : function (obj, val) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tthis.__rollback();\n\t\t\t\tif(obj && obj.length && this.set_text.apply(this, Array.prototype.slice.call(arguments))) { this.__callback({ \"obj\" : obj, \"name\" : val }); }\n\t\t\t},\n\t\t\t// Basic operations: deleting nodes\n\t\t\tdelete_node : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tthis.__rollback();\n\t\t\t\tvar p = this._get_parent(obj), prev = $([]), t = this;\n\t\t\t\tobj.each(function () {\n\t\t\t\t\tprev = prev.add(t._get_prev(this));\n\t\t\t\t});\n\t\t\t\tobj = obj.detach();\n\t\t\t\tif(p !== -1 && p.find(\"> ul > li\").length === 0) {\n\t\t\t\t\tp.removeClass(\"jstree-open jstree-closed\").addClass(\"jstree-leaf\");\n\t\t\t\t}\n\t\t\t\tthis.clean_node(p);\n\t\t\t\tthis.__callback({ \"obj\" : obj, \"prev\" : prev, \"parent\" : p });\n\t\t\t\treturn obj;\n\t\t\t},\n\t\t\tprepare_move : function (o, r, pos, cb, is_cb) {\n\t\t\t\tvar p = {};\n\n\t\t\t\tp.ot = $.jstree._reference(o) || this;\n\t\t\t\tp.o = p.ot._get_node(o);\n\t\t\t\tp.r = r === - 1 ? -1 : this._get_node(r);\n\t\t\t\tp.p = (typeof pos === \"undefined\" || pos === false) ? \"last\" : pos; // TODO: move to a setting\n\t\t\t\tif(!is_cb && prepared_move.o && prepared_move.o[0] === p.o[0] && prepared_move.r[0] === p.r[0] && prepared_move.p === p.p) {\n\t\t\t\t\tthis.__callback(prepared_move);\n\t\t\t\t\tif(cb) { cb.call(this, prepared_move); }\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.ot = $.jstree._reference(p.o) || this;\n\t\t\t\tp.rt = $.jstree._reference(p.r) || this; // r === -1 ? p.ot : $.jstree._reference(p.r) || this\n\t\t\t\tif(p.r === -1 || !p.r) {\n\t\t\t\t\tp.cr = -1;\n\t\t\t\t\tswitch(p.p) {\n\t\t\t\t\t\tcase \"first\":\n\t\t\t\t\t\tcase \"before\":\n\t\t\t\t\t\tcase \"inside\":\n\t\t\t\t\t\t\tp.cp = 0; \n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"after\":\n\t\t\t\t\t\tcase \"last\":\n\t\t\t\t\t\t\tp.cp = p.rt.get_container().find(\" > ul > li\").length; \n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tp.cp = p.p;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(!/^(before|after)$/.test(p.p) && !this._is_loaded(p.r)) {\n\t\t\t\t\t\treturn this.load_node(p.r, function () { this.prepare_move(o, r, pos, cb, true); });\n\t\t\t\t\t}\n\t\t\t\t\tswitch(p.p) {\n\t\t\t\t\t\tcase \"before\":\n\t\t\t\t\t\t\tp.cp = p.r.index();\n\t\t\t\t\t\t\tp.cr = p.rt._get_parent(p.r);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"after\":\n\t\t\t\t\t\t\tp.cp = p.r.index() + 1;\n\t\t\t\t\t\t\tp.cr = p.rt._get_parent(p.r);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"inside\":\n\t\t\t\t\t\tcase \"first\":\n\t\t\t\t\t\t\tp.cp = 0;\n\t\t\t\t\t\t\tp.cr = p.r;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"last\":\n\t\t\t\t\t\t\tp.cp = p.r.find(\" > ul > li\").length; \n\t\t\t\t\t\t\tp.cr = p.r;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault: \n\t\t\t\t\t\t\tp.cp = p.p;\n\t\t\t\t\t\t\tp.cr = p.r;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tp.np = p.cr == -1 ? p.rt.get_container() : p.cr;\n\t\t\t\tp.op = p.ot._get_parent(p.o);\n\t\t\t\tp.cop = p.o.index();\n\t\t\t\tif(p.op === -1) { p.op = p.ot ? p.ot.get_container() : this.get_container(); }\n\t\t\t\tif(!/^(before|after)$/.test(p.p) && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp++; }\n\t\t\t\t//if(p.p === \"before\" && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp--; }\n\t\t\t\tp.or = p.np.find(\" > ul > li:nth-child(\" + (p.cp + 1) + \")\");\n\t\t\t\tprepared_move = p;\n\t\t\t\tthis.__callback(prepared_move);\n\t\t\t\tif(cb) { cb.call(this, prepared_move); }\n\t\t\t},\n\t\t\tcheck_move : function () {\n\t\t\t\tvar obj = prepared_move, ret = true, r = obj.r === -1 ? this.get_container() : obj.r;\n\t\t\t\tif(!obj || !obj.o || obj.or[0] === obj.o[0]) { return false; }\n\t\t\t\tif(obj.op && obj.np && obj.op[0] === obj.np[0] && obj.cp - 1 === obj.o.index()) { return false; }\n\t\t\t\tobj.o.each(function () { \n\t\t\t\t\tif(r.parentsUntil(\".jstree\", \"li\").andSelf().index(this) !== -1) { ret = false; return false; }\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t},\n\t\t\tmove_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {\n\t\t\t\tif(!is_prepared) { \n\t\t\t\t\treturn this.prepare_move(obj, ref, position, function (p) {\n\t\t\t\t\t\tthis.move_node(p, false, false, is_copy, true, skip_check);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(is_copy) { \n\t\t\t\t\tprepared_move.cy = true;\n\t\t\t\t}\n\t\t\t\tif(!skip_check && !this.check_move()) { return false; }\n\n\t\t\t\tthis.__rollback();\n\t\t\t\tvar o = false;\n\t\t\t\tif(is_copy) {\n\t\t\t\t\to = obj.o.clone(true);\n\t\t\t\t\to.find(\"*[id]\").andSelf().each(function () {\n\t\t\t\t\t\tif(this.id) { this.id = \"copy_\" + this.id; }\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse { o = obj.o; }\n\n\t\t\t\tif(obj.or.length) { obj.or.before(o); }\n\t\t\t\telse { \n\t\t\t\t\tif(!obj.np.children(\"ul\").length) { $(\"<ul />\").appendTo(obj.np); }\n\t\t\t\t\tobj.np.children(\"ul:eq(0)\").append(o); \n\t\t\t\t}\n\n\t\t\t\ttry { \n\t\t\t\t\tobj.ot.clean_node(obj.op);\n\t\t\t\t\tobj.rt.clean_node(obj.np);\n\t\t\t\t\tif(!obj.op.find(\"> ul > li\").length) {\n\t\t\t\t\t\tobj.op.removeClass(\"jstree-open jstree-closed\").addClass(\"jstree-leaf\").children(\"ul\").remove();\n\t\t\t\t\t}\n\t\t\t\t} catch (e) { }\n\n\t\t\t\tif(is_copy) { \n\t\t\t\t\tprepared_move.cy = true;\n\t\t\t\t\tprepared_move.oc = o; \n\t\t\t\t}\n\t\t\t\tthis.__callback(prepared_move);\n\t\t\t\treturn prepared_move;\n\t\t\t},\n\t\t\t_get_move : function () { return prepared_move; }\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree ui plugin\n * This plugins handles selecting/deselecting/hovering/dehovering nodes\n */\n(function ($) {\n\tvar scrollbar_width, e1, e2;\n\t$(function() {\n\t\tif (/msie/.test(navigator.userAgent.toLowerCase())) {\n\t\t\te1 = $('<textarea cols=\"10\" rows=\"2\"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');\n\t\t\te2 = $('<textarea cols=\"10\" rows=\"2\" style=\"overflow: hidden;\"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');\n\t\t\tscrollbar_width = e1.width() - e2.width();\n\t\t\te1.add(e2).remove();\n\t\t} \n\t\telse {\n\t\t\te1 = $('<div />').css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: 0 })\n\t\t\t\t\t.prependTo('body').append('<div />').find('div').css({ width: '100%', height: 200 });\n\t\t\tscrollbar_width = 100 - e1.width();\n\t\t\te1.parent().remove();\n\t\t}\n\t});\n\t$.jstree.plugin(\"ui\", {\n\t\t__init : function () { \n\t\t\tthis.data.ui.selected = $(); \n\t\t\tthis.data.ui.last_selected = false; \n\t\t\tthis.data.ui.hovered = null;\n\t\t\tthis.data.ui.to_select = this.get_settings().ui.initially_select;\n\n\t\t\tthis.get_container()\n\t\t\t\t.delegate(\"a\", \"click.jstree\", $.proxy(function (event) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.currentTarget.blur();\n\t\t\t\t\t\tif(!$(event.currentTarget).hasClass(\"jstree-loading\")) {\n\t\t\t\t\t\t\tthis.select_node(event.currentTarget, true, event);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mouseenter.jstree\", $.proxy(function (event) {\n\t\t\t\t\t\tif(!$(event.currentTarget).hasClass(\"jstree-loading\")) {\n\t\t\t\t\t\t\tthis.hover_node(event.target);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mouseleave.jstree\", $.proxy(function (event) {\n\t\t\t\t\t\tif(!$(event.currentTarget).hasClass(\"jstree-loading\")) {\n\t\t\t\t\t\t\tthis.dehover_node(event.target);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"reopen.jstree\", $.proxy(function () { \n\t\t\t\t\t\tthis.reselect();\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"get_rollback.jstree\", $.proxy(function () { \n\t\t\t\t\t\tthis.dehover_node();\n\t\t\t\t\t\tthis.save_selected();\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"set_rollback.jstree\", $.proxy(function () { \n\t\t\t\t\t\tthis.reselect();\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"close_node.jstree\", $.proxy(function (event, data) { \n\t\t\t\t\t\tvar s = this._get_settings().ui,\n\t\t\t\t\t\t\tobj = this._get_node(data.rslt.obj),\n\t\t\t\t\t\t\tclk = (obj && obj.length) ? obj.children(\"ul\").find(\"a.jstree-clicked\") : $(),\n\t\t\t\t\t\t\t_this = this;\n\t\t\t\t\t\tif(s.selected_parent_close === false || !clk.length) { return; }\n\t\t\t\t\t\tclk.each(function () { \n\t\t\t\t\t\t\t_this.deselect_node(this);\n\t\t\t\t\t\t\tif(s.selected_parent_close === \"select_parent\") { _this.select_node(obj); }\n\t\t\t\t\t\t});\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"delete_node.jstree\", $.proxy(function (event, data) { \n\t\t\t\t\t\tvar s = this._get_settings().ui.select_prev_on_delete,\n\t\t\t\t\t\t\tobj = this._get_node(data.rslt.obj),\n\t\t\t\t\t\t\tclk = (obj && obj.length) ? obj.find(\"a.jstree-clicked\") : [],\n\t\t\t\t\t\t\t_this = this;\n\t\t\t\t\t\tclk.each(function () { _this.deselect_node(this); });\n\t\t\t\t\t\tif(s && clk.length) { \n\t\t\t\t\t\t\tdata.rslt.prev.each(function () { \n\t\t\t\t\t\t\t\tif(this.parentNode) { _this.select_node(this); return false; /* if return false is removed all prev nodes will be selected */}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"move_node.jstree\", $.proxy(function (event, data) { \n\t\t\t\t\t\tif(data.rslt.cy) { \n\t\t\t\t\t\t\tdata.rslt.oc.find(\"a.jstree-clicked\").removeClass(\"jstree-clicked\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : {\n\t\t\tselect_limit : -1, // 0, 1, 2 ... or -1 for unlimited\n\t\t\tselect_multiple_modifier : \"ctrl\", // on, or ctrl, shift, alt\n\t\t\tselect_range_modifier : \"shift\",\n\t\t\tselected_parent_close : \"select_parent\", // false, \"deselect\", \"select_parent\"\n\t\t\tselected_parent_open : true,\n\t\t\tselect_prev_on_delete : true,\n\t\t\tdisable_selecting_children : false,\n\t\t\tinitially_select : []\n\t\t},\n\t\t_fn : { \n\t\t\t_get_node : function (obj, allow_multiple) {\n\t\t\t\tif(typeof obj === \"undefined\" || obj === null) { return allow_multiple ? this.data.ui.selected : this.data.ui.last_selected; }\n\t\t\t\tvar $obj = $(obj, this.get_container()); \n\t\t\t\tif($obj.is(\".jstree\") || obj == -1) { return -1; } \n\t\t\t\t$obj = $obj.closest(\"li\", this.get_container()); \n\t\t\t\treturn $obj.length ? $obj : false; \n\t\t\t},\n\t\t\t_ui_notify : function (n, data) {\n\t\t\t\tif(data.selected) {\n\t\t\t\t\tthis.select_node(n, false);\n\t\t\t\t}\n\t\t\t},\n\t\t\tsave_selected : function () {\n\t\t\t\tvar _this = this;\n\t\t\t\tthis.data.ui.to_select = [];\n\t\t\t\tthis.data.ui.selected.each(function () { if(this.id) { _this.data.ui.to_select.push(\"#\" + this.id.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\")); } });\n\t\t\t\tthis.__callback(this.data.ui.to_select);\n\t\t\t},\n\t\t\treselect : function () {\n\t\t\t\tvar _this = this,\n\t\t\t\t\ts = this.data.ui.to_select;\n\t\t\t\ts = $.map($.makeArray(s), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n\t\t\t\t// this.deselect_all(); WHY deselect, breaks plugin state notifier?\n\t\t\t\t$.each(s, function (i, val) { if(val && val !== \"#\") { _this.select_node(val); } });\n\t\t\t\tthis.data.ui.selected = this.data.ui.selected.filter(function () { return this.parentNode; });\n\t\t\t\tthis.__callback();\n\t\t\t},\n\t\t\trefresh : function (obj) {\n\t\t\t\tthis.save_selected();\n\t\t\t\treturn this.__call_old();\n\t\t\t},\n\t\t\thover_node : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\t//if(this.data.ui.hovered && obj.get(0) === this.data.ui.hovered.get(0)) { return; }\n\t\t\t\tif(!obj.hasClass(\"jstree-hovered\")) { this.dehover_node(); }\n\t\t\t\tthis.data.ui.hovered = obj.children(\"a\").addClass(\"jstree-hovered\").parent();\n\t\t\t\t// brackets: jstree uses default scroll bar widths, and there's no clean way to override the code from brackets, which causes continuous scrolling, so just disable for now\n\t\t\t\t//this._fix_scroll(obj);\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\tdehover_node : function () {\n\t\t\t\tvar obj = this.data.ui.hovered, p;\n\t\t\t\tif(!obj || !obj.length) { return false; }\n\t\t\t\tp = obj.children(\"a\").removeClass(\"jstree-hovered\").parent();\n\t\t\t\tif(this.data.ui.hovered[0] === p[0]) { this.data.ui.hovered = null; }\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\tselect_node : function (obj, check, e) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj == -1 || !obj || !obj.length) { return false; }\n\t\t\t\tvar s = this._get_settings().ui,\n\t\t\t\t\tis_multiple = (s.select_multiple_modifier == \"on\" || (s.select_multiple_modifier !== false && e && e[s.select_multiple_modifier + \"Key\"])),\n\t\t\t\t\tis_range = (s.select_range_modifier !== false && e && e[s.select_range_modifier + \"Key\"] && this.data.ui.last_selected && this.data.ui.last_selected[0] !== obj[0] && this.data.ui.last_selected.parent()[0] === obj.parent()[0]),\n\t\t\t\t\tis_selected = this.is_selected(obj),\n\t\t\t\t\tproceed = true,\n\t\t\t\t\tt = this;\n\t\t\t\tif(check) {\n\t\t\t\t\tif(s.disable_selecting_children && is_multiple && \n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(obj.parentsUntil(\".jstree\",\"li\").children(\"a.jstree-clicked\").length) ||\n\t\t\t\t\t\t\t(obj.children(\"ul\").find(\"a.jstree-clicked:eq(0)\").length)\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tproceed = false;\n\t\t\t\t\tswitch(!0) {\n\t\t\t\t\t\tcase (is_range):\n\t\t\t\t\t\t\tthis.data.ui.last_selected.addClass(\"jstree-last-selected\");\n\t\t\t\t\t\t\tobj = obj[ obj.index() < this.data.ui.last_selected.index() ? \"nextUntil\" : \"prevUntil\" ](\".jstree-last-selected\").andSelf();\n\t\t\t\t\t\t\tif(s.select_limit == -1 || obj.length < s.select_limit) {\n\t\t\t\t\t\t\t\tthis.data.ui.last_selected.removeClass(\"jstree-last-selected\");\n\t\t\t\t\t\t\t\tthis.data.ui.selected.each(function () {\n\t\t\t\t\t\t\t\t\tif(this !== t.data.ui.last_selected[0]) { t.deselect_node(this); }\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tis_selected = false;\n\t\t\t\t\t\t\t\tproceed = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tproceed = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase (is_selected && !is_multiple): \n\t\t\t\t\t\t\tthis.deselect_all();\n\t\t\t\t\t\t\tis_selected = false;\n\t\t\t\t\t\t\tproceed = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase (!is_selected && !is_multiple): \n\t\t\t\t\t\t\tif(s.select_limit == -1 || s.select_limit > 0) {\n\t\t\t\t\t\t\t\tthis.deselect_all();\n\t\t\t\t\t\t\t\tproceed = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase (is_selected && is_multiple): \n\t\t\t\t\t\t\tthis.deselect_node(obj);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase (!is_selected && is_multiple): \n\t\t\t\t\t\t\tif(s.select_limit == -1 || this.data.ui.selected.length + 1 <= s.select_limit) { \n\t\t\t\t\t\t\t\tproceed = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(proceed && !is_selected) {\n\t\t\t\t\tif(!is_range) { this.data.ui.last_selected = obj; }\n\t\t\t\t\tobj.children(\"a\").addClass(\"jstree-clicked\");\n\t\t\t\t\tif(s.selected_parent_open) {\n\t\t\t\t\t\tobj.parents(\".jstree-closed\").each(function () { t.open_node(this, false, true); });\n\t\t\t\t\t}\n\t\t\t\t\tthis.data.ui.selected = this.data.ui.selected.add(obj);\n\t\t\t\t\tthis._fix_scroll(obj.eq(0));\n\t\t\t\t\tthis.__callback({ \"obj\" : obj, \"e\" : e });\n\t\t\t\t}\n\t\t\t},\n\t\t\t_fix_scroll : function (obj) {\n\t\t\t\tvar c = this.get_container()[0], t;\n\t\t\t\tif(c.scrollHeight > c.offsetHeight) {\n\t\t\t\t\tobj = this._get_node(obj);\n\t\t\t\t\tif(!obj || obj === -1 || !obj.length || !obj.is(\":visible\")) { return; }\n\t\t\t\t\tt = obj.offset().top - this.get_container().offset().top;\n\t\t\t\t\tif(t < 0) { \n\t\t\t\t\t\tc.scrollTop = c.scrollTop + t - 1; \n\t\t\t\t\t}\n\t\t\t\t\tif(t + this.data.core.li_height + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0) > c.offsetHeight) { \n\t\t\t\t\t\tc.scrollTop = c.scrollTop + (t - c.offsetHeight + this.data.core.li_height + 1 + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0)); \n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeselect_node : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tif(this.is_selected(obj)) {\n\t\t\t\t\tobj.children(\"a\").removeClass(\"jstree-clicked\");\n\t\t\t\t\tthis.data.ui.selected = this.data.ui.selected.not(obj);\n\t\t\t\t\tif(this.data.ui.last_selected.get(0) === obj.get(0)) { this.data.ui.last_selected = this.data.ui.selected.eq(0); }\n\t\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t\t}\n\t\t\t},\n\t\t\ttoggle_select : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return false; }\n\t\t\t\tif(this.is_selected(obj)) { this.deselect_node(obj); }\n\t\t\t\telse { this.select_node(obj); }\n\t\t\t},\n\t\t\tis_selected : function (obj) { return this.data.ui.selected.index(this._get_node(obj)) >= 0; },\n\t\t\tget_selected : function (context) { \n\t\t\t\treturn context ? $(context).find(\"a.jstree-clicked\").parent() : this.data.ui.selected; \n\t\t\t},\n\t\t\tdeselect_all : function (context) {\n\t\t\t\tvar ret = context ? $(context).find(\"a.jstree-clicked\").parent() : this.get_container().find(\"a.jstree-clicked\").parent();\n\t\t\t\tret.children(\"a.jstree-clicked\").removeClass(\"jstree-clicked\");\n\t\t\t\tthis.data.ui.selected = $([]);\n\t\t\t\tthis.data.ui.last_selected = false;\n\t\t\t\tthis.__callback({ \"obj\" : ret });\n\t\t\t}\n\t\t}\n\t});\n\t// include the selection plugin by default\n\t$.jstree.defaults.plugins.push(\"ui\");\n})(jQuery);\n//*/\n\n/* \n * jsTree CRRM plugin\n * Handles creating/renaming/removing/moving nodes by user interaction.\n */\n(function ($) {\n\t$.jstree.plugin(\"crrm\", { \n\t\t__init : function () {\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"move_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\tif(this._get_settings().crrm.move.open_onmove) {\n\t\t\t\t\t\tvar t = this;\n\t\t\t\t\t\tdata.rslt.np.parentsUntil(\".jstree\").andSelf().filter(\".jstree-closed\").each(function () {\n\t\t\t\t\t\t\tt.open_node(this, false, true);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : {\n\t\t\tinput_width_limit : 200,\n\t\t\tmove : {\n\t\t\t\talways_copy\t\t\t: false, // false, true or \"multitree\"\n\t\t\t\topen_onmove\t\t\t: true,\n\t\t\t\tdefault_position\t: \"last\",\n\t\t\t\tcheck_move\t\t\t: function (m) { return true; }\n\t\t\t}\n\t\t},\n\t\t_fn : {\n\t\t\t_show_input : function (obj, callback) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar rtl = this._get_settings().core.rtl,\n\t\t\t\t\tw = this._get_settings().crrm.input_width_limit,\n\t\t\t\t\tw1 = obj.children(\"ins\").width(),\n\t\t\t\t\tw2 = obj.find(\"> a:visible > ins\").width() * obj.find(\"> a:visible > ins\").length,\n\t\t\t\t\tt = this.get_text(obj),\n\t\t\t\t\th1 = $(\"<div />\", { css : { \"position\" : \"absolute\", \"top\" : \"-200px\", \"left\" : (rtl ? \"0px\" : \"-1000px\"), \"visibility\" : \"hidden\" } }).appendTo(\"body\"),\n\t\t\t\t\th2 = obj.css(\"position\",\"relative\").append(\n\t\t\t\t\t$(\"<input />\", { \n\t\t\t\t\t\t\"value\" : t,\n\t\t\t\t\t\t\"class\" : \"jstree-rename-input\",\n\t\t\t\t\t\t// \"size\" : t.length,\n\t\t\t\t\t\t\"css\" : {\n\t\t\t\t\t\t\t\"padding\" : \"0\",\n\t\t\t\t\t\t\t\"border\" : \"1px solid silver\",\n\t\t\t\t\t\t\t\"position\" : \"absolute\",\n\t\t\t\t\t\t\t\"left\"  : (rtl ? \"auto\" : (w1 + w2 + 4) + \"px\"),\n\t\t\t\t\t\t\t\"right\" : (rtl ? (w1 + w2 + 4) + \"px\" : \"auto\"),\n\t\t\t\t\t\t\t\"top\" : \"0px\",\n\t\t\t\t\t\t\t\"height\" : (this.data.core.li_height - 2) + \"px\",\n\t\t\t\t\t\t\t\"lineHeight\" : (this.data.core.li_height - 2) + \"px\",\n\t\t\t\t\t\t\t\"width\" : \"150px\" // will be set a bit further down\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"blur\" : $.proxy(function () {\n\t\t\t\t\t\t\tvar i = obj.children(\".jstree-rename-input\"),\n\t\t\t\t\t\t\t\tv = i.val();\n\t\t\t\t\t\t\tif(v === \"\") { v = t; }\n\t\t\t\t\t\t\th1.remove();\n\t\t\t\t\t\t\ti.remove(); // rollback purposes\n\t\t\t\t\t\t\tthis.set_text(obj,t); // rollback purposes\n\t\t\t\t\t\t\tthis.rename_node(obj, v);\n\t\t\t\t\t\t\tcallback.call(this, obj, v, t);\n\t\t\t\t\t\t\tobj.css(\"position\",\"\");\n\t\t\t\t\t\t}, this),\n\t\t\t\t\t\t\"keyup\" : function (event) {\n\t\t\t\t\t\t\tvar key = event.keyCode || event.which;\n\t\t\t\t\t\t\tif(key == 27) { this.value = t; this.blur(); return; }\n\t\t\t\t\t\t\telse if(key == 13) { this.blur(); return; }\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\th2.width(Math.min(h1.text(\"pW\" + this.value).width(),w));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"keypress\" : function(event) {\n\t\t\t\t\t\t\tvar key = event.keyCode || event.which;\n\t\t\t\t\t\t\tif(key == 13) { return false; }\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t).children(\".jstree-rename-input\"); \n\t\t\t\tthis.set_text(obj, \"\");\n\t\t\t\th1.css({\n\t\t\t\t\t\tfontFamily\t\t: h2.css('fontFamily')\t\t|| '',\n\t\t\t\t\t\tfontSize\t\t: h2.css('fontSize')\t\t|| '',\n\t\t\t\t\t\tfontWeight\t\t: h2.css('fontWeight')\t\t|| '',\n\t\t\t\t\t\tfontStyle\t\t: h2.css('fontStyle')\t\t|| '',\n\t\t\t\t\t\tfontStretch\t\t: h2.css('fontStretch')\t\t|| '',\n\t\t\t\t\t\tfontVariant\t\t: h2.css('fontVariant')\t\t|| '',\n\t\t\t\t\t\tletterSpacing\t: h2.css('letterSpacing')\t|| '',\n\t\t\t\t\t\twordSpacing\t\t: h2.css('wordSpacing')\t\t|| ''\n\t\t\t\t});\n\t\t\t\th2.width(Math.min(h1.text(\"pW\" + h2[0].value).width(),w))[0].select();\n\t\t\t},\n\t\t\trename : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tthis.__rollback();\n\t\t\t\tvar f = this.__callback;\n\t\t\t\tthis._show_input(obj, function (obj, new_name, old_name) { \n\t\t\t\t\tf.call(this, { \"obj\" : obj, \"new_name\" : new_name, \"old_name\" : old_name });\n\t\t\t\t});\n\t\t\t},\n\t\t\tcreate : function (obj, position, js, callback, skip_rename) {\n\t\t\t\tvar t, _this = this;\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj) { obj = -1; }\n\t\t\t\tthis.__rollback();\n\t\t\t\tt = this.create_node(obj, position, js, function (t) {\n\t\t\t\t\tvar p = this._get_parent(t),\n\t\t\t\t\t\tpos = $(t).index();\n\t\t\t\t\tif(callback) { callback.call(this, t); }\n\t\t\t\t\tif(p.length && p.hasClass(\"jstree-closed\")) { this.open_node(p, false, true); }\n\t\t\t\t\tif(!skip_rename) { \n\t\t\t\t\t\tthis._show_input(t, function (obj, new_name, old_name) { \n\t\t\t\t\t\t\t_this.__callback({ \"obj\" : obj, \"name\" : new_name, \"parent\" : p, \"position\" : pos });\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\telse { _this.__callback({ \"obj\" : t, \"name\" : this.get_text(t), \"parent\" : p, \"position\" : pos }); }\n\t\t\t\t});\n\t\t\t\treturn t;\n\t\t\t},\n\t\t\tremove : function (obj) {\n\t\t\t\tobj = this._get_node(obj, true);\n\t\t\t\tvar p = this._get_parent(obj), prev = this._get_prev(obj);\n\t\t\t\tthis.__rollback();\n\t\t\t\tobj = this.delete_node(obj);\n\t\t\t\tif(obj !== false) { this.__callback({ \"obj\" : obj, \"prev\" : prev, \"parent\" : p }); }\n\t\t\t},\n\t\t\tcheck_move : function () {\n\t\t\t\tif(!this.__call_old()) { return false; }\n\t\t\t\tvar s = this._get_settings().crrm.move;\n\t\t\t\tif(!s.check_move.call(this, this._get_move())) { return false; }\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tmove_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {\n\t\t\t\tvar s = this._get_settings().crrm.move;\n\t\t\t\tif(!is_prepared) { \n\t\t\t\t\tif(typeof position === \"undefined\") { position = s.default_position; }\n\t\t\t\t\tif(position === \"inside\" && !s.default_position.match(/^(before|after)$/)) { position = s.default_position; }\n\t\t\t\t\treturn this.__call_old(true, obj, ref, position, is_copy, false, skip_check);\n\t\t\t\t}\n\t\t\t\t// if the move is already prepared\n\t\t\t\tif(s.always_copy === true || (s.always_copy === \"multitree\" && obj.rt.get_index() !== obj.ot.get_index() )) {\n\t\t\t\t\tis_copy = true;\n\t\t\t\t}\n\t\t\t\tthis.__call_old(true, obj, ref, position, is_copy, true, skip_check);\n\t\t\t},\n\n\t\t\tcut : function (obj) {\n\t\t\t\tobj = this._get_node(obj, true);\n\t\t\t\tif(!obj || !obj.length) { return false; }\n\t\t\t\tthis.data.crrm.cp_nodes = false;\n\t\t\t\tthis.data.crrm.ct_nodes = obj;\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\tcopy : function (obj) {\n\t\t\t\tobj = this._get_node(obj, true);\n\t\t\t\tif(!obj || !obj.length) { return false; }\n\t\t\t\tthis.data.crrm.ct_nodes = false;\n\t\t\t\tthis.data.crrm.cp_nodes = obj;\n\t\t\t\tthis.__callback({ \"obj\" : obj });\n\t\t\t},\n\t\t\tpaste : function (obj) { \n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj || !obj.length) { return false; }\n\t\t\t\tvar nodes = this.data.crrm.ct_nodes ? this.data.crrm.ct_nodes : this.data.crrm.cp_nodes;\n\t\t\t\tif(!this.data.crrm.ct_nodes && !this.data.crrm.cp_nodes) { return false; }\n\t\t\t\tif(this.data.crrm.ct_nodes) { this.move_node(this.data.crrm.ct_nodes, obj); this.data.crrm.ct_nodes = false; }\n\t\t\t\tif(this.data.crrm.cp_nodes) { this.move_node(this.data.crrm.cp_nodes, obj, false, true); }\n\t\t\t\tthis.__callback({ \"obj\" : obj, \"nodes\" : nodes });\n\t\t\t}\n\t\t}\n\t});\n\t// include the crr plugin by default\n\t// $.jstree.defaults.plugins.push(\"crrm\");\n})(jQuery);\n//*/\n\n/* \n * jsTree themes plugin\n * Handles loading and setting themes, as well as detecting path to themes, etc.\n */\n(function ($) {\n\tvar themes_loaded = [];\n\t// this variable stores the path to the themes folder - if left as false - it will be autodetected\n\t$.jstree._themes = false;\n\t$.jstree.plugin(\"themes\", {\n\t\t__init : function () { \n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"init.jstree\", $.proxy(function () {\n\t\t\t\t\t\tvar s = this._get_settings().themes;\n\t\t\t\t\t\tthis.data.themes.dots = s.dots; \n\t\t\t\t\t\tthis.data.themes.icons = s.icons; \n\t\t\t\t\t\tthis.set_theme(s.theme, s.url);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"loaded.jstree\", $.proxy(function () {\n\t\t\t\t\t\t// bound here too, as simple HTML tree's won't honor dots & icons otherwise\n\t\t\t\t\t\tif(!this.data.themes.dots) { this.hide_dots(); }\n\t\t\t\t\t\telse { this.show_dots(); }\n\t\t\t\t\t\tif(!this.data.themes.icons) { this.hide_icons(); }\n\t\t\t\t\t\telse { this.show_icons(); }\n\t\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : { \n\t\t\ttheme : \"default\", \n\t\t\turl : false,\n\t\t\tdots : true,\n\t\t\ticons : true\n\t\t},\n\t\t_fn : {\n\t\t\tset_theme : function (theme_name, theme_url) {\n\t\t\t\tif(!theme_name) { return false; }\n\t\t\t\tif(!theme_url) { theme_url = $.jstree._themes + theme_name + '/style.css'; }\n\t\t\t\tif($.inArray(theme_url, themes_loaded) == -1) {\n\t\t\t\t\t$.vakata.css.add_sheet({ \"url\" : theme_url });\n\t\t\t\t\tthemes_loaded.push(theme_url);\n\t\t\t\t}\n\t\t\t\tif(this.data.themes.theme != theme_name) {\n\t\t\t\t\tthis.get_container().removeClass('jstree-' + this.data.themes.theme);\n\t\t\t\t\tthis.data.themes.theme = theme_name;\n\t\t\t\t}\n\t\t\t\tthis.get_container().addClass('jstree-' + theme_name);\n\t\t\t\tif(!this.data.themes.dots) { this.hide_dots(); }\n\t\t\t\telse { this.show_dots(); }\n\t\t\t\tif(!this.data.themes.icons) { this.hide_icons(); }\n\t\t\t\telse { this.show_icons(); }\n\t\t\t\tthis.__callback();\n\t\t\t},\n\t\t\tget_theme\t: function () { return this.data.themes.theme; },\n\n\t\t\tshow_dots\t: function () { this.data.themes.dots = true; this.get_container().children(\"ul\").removeClass(\"jstree-no-dots\"); },\n\t\t\thide_dots\t: function () { this.data.themes.dots = false; this.get_container().children(\"ul\").addClass(\"jstree-no-dots\"); },\n\t\t\ttoggle_dots\t: function () { if(this.data.themes.dots) { this.hide_dots(); } else { this.show_dots(); } },\n\n\t\t\tshow_icons\t: function () { this.data.themes.icons = true; this.get_container().children(\"ul\").removeClass(\"jstree-no-icons\"); },\n\t\t\thide_icons\t: function () { this.data.themes.icons = false; this.get_container().children(\"ul\").addClass(\"jstree-no-icons\"); },\n\t\t\ttoggle_icons: function () { if(this.data.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }\n\t\t}\n\t});\n\t// autodetect themes path\n\t$(function () {\n\t\tif($.jstree._themes === false) {\n\t\t\t$(\"script\").each(function () { \n\t\t\t\tif(this.src.toString().match(/jquery\\.jstree[^\\/]*?\\.js(\\?.*)?$/)) { \n\t\t\t\t\t$.jstree._themes = this.src.toString().replace(/jquery\\.jstree[^\\/]*?\\.js(\\?.*)?$/, \"\") + 'themes/'; \n\t\t\t\t\treturn false; \n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif($.jstree._themes === false) { $.jstree._themes = \"themes/\"; }\n\t});\n\t// include the themes plugin by default\n\t$.jstree.defaults.plugins.push(\"themes\");\n})(jQuery);\n//*/\n\n/*\n * jsTree hotkeys plugin\n * Enables keyboard navigation for all tree instances\n * Depends on the jstree ui & jquery hotkeys plugins\n */\n(function ($) {\n\tvar bound = [];\n\tfunction exec(i, event) {\n\t\tvar f = $.jstree._focused(), tmp;\n\t\tif(f && f.data && f.data.hotkeys && f.data.hotkeys.enabled) { \n\t\t\ttmp = f._get_settings().hotkeys[i];\n\t\t\tif(tmp) { return tmp.call(f, event); }\n\t\t}\n\t}\n\t$.jstree.plugin(\"hotkeys\", {\n\t\t__init : function () {\n\t\t\tif(typeof $.hotkeys === \"undefined\") { throw \"jsTree hotkeys: jQuery hotkeys plugin not included.\"; }\n\t\t\tif(!this.data.ui) { throw \"jsTree hotkeys: jsTree UI plugin not included.\"; }\n\t\t\t$.each(this._get_settings().hotkeys, function (i, v) {\n\t\t\t\tif(v !== false && $.inArray(i, bound) == -1) {\n\t\t\t\t\t$(document).bind(\"keydown\", i, function (event) { return exec(i, event); });\n\t\t\t\t\tbound.push(i);\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"lock.jstree\", $.proxy(function () {\n\t\t\t\t\t\tif(this.data.hotkeys.enabled) { this.data.hotkeys.enabled = false; this.data.hotkeys.revert = true; }\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"unlock.jstree\", $.proxy(function () {\n\t\t\t\t\t\tif(this.data.hotkeys.revert) { this.data.hotkeys.enabled = true; }\n\t\t\t\t\t}, this));\n\t\t\tthis.enable_hotkeys();\n\t\t},\n\t\tdefaults : {\n\t\t\t\"up\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n\t\t\t\tthis.hover_node(this._get_prev(o));\n\t\t\t\treturn false; \n\t\t\t},\n\t\t\t\"ctrl+up\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n\t\t\t\tthis.hover_node(this._get_prev(o));\n\t\t\t\treturn false; \n\t\t\t},\n\t\t\t\"shift+up\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n\t\t\t\tthis.hover_node(this._get_prev(o));\n\t\t\t\treturn false; \n\t\t\t},\n\t\t\t\"down\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n\t\t\t\tthis.hover_node(this._get_next(o));\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"ctrl+down\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n\t\t\t\tthis.hover_node(this._get_next(o));\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"shift+down\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n\t\t\t\tthis.hover_node(this._get_next(o));\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"left\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected;\n\t\t\t\tif(o) {\n\t\t\t\t\tif(o.hasClass(\"jstree-open\")) { this.close_node(o); }\n\t\t\t\t\telse { this.hover_node(this._get_prev(o)); }\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"ctrl+left\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected;\n\t\t\t\tif(o) {\n\t\t\t\t\tif(o.hasClass(\"jstree-open\")) { this.close_node(o); }\n\t\t\t\t\telse { this.hover_node(this._get_prev(o)); }\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"shift+left\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected;\n\t\t\t\tif(o) {\n\t\t\t\t\tif(o.hasClass(\"jstree-open\")) { this.close_node(o); }\n\t\t\t\t\telse { this.hover_node(this._get_prev(o)); }\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"right\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected;\n\t\t\t\tif(o && o.length) {\n\t\t\t\t\tif(o.hasClass(\"jstree-closed\")) { this.open_node(o); }\n\t\t\t\t\telse { this.hover_node(this._get_next(o)); }\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"ctrl+right\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected;\n\t\t\t\tif(o && o.length) {\n\t\t\t\t\tif(o.hasClass(\"jstree-closed\")) { this.open_node(o); }\n\t\t\t\t\telse { this.hover_node(this._get_next(o)); }\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"shift+right\" : function () { \n\t\t\t\tvar o = this.data.ui.hovered || this.data.ui.last_selected;\n\t\t\t\tif(o && o.length) {\n\t\t\t\t\tif(o.hasClass(\"jstree-closed\")) { this.open_node(o); }\n\t\t\t\t\telse { this.hover_node(this._get_next(o)); }\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"space\" : function () { \n\t\t\t\tif(this.data.ui.hovered) { this.data.ui.hovered.children(\"a:eq(0)\").click(); } \n\t\t\t\treturn false; \n\t\t\t},\n\t\t\t\"ctrl+space\" : function (event) { \n\t\t\t\tevent.type = \"click\";\n\t\t\t\tif(this.data.ui.hovered) { this.data.ui.hovered.children(\"a:eq(0)\").trigger(event); } \n\t\t\t\treturn false; \n\t\t\t},\n\t\t\t\"shift+space\" : function (event) { \n\t\t\t\tevent.type = \"click\";\n\t\t\t\tif(this.data.ui.hovered) { this.data.ui.hovered.children(\"a:eq(0)\").trigger(event); } \n\t\t\t\treturn false; \n\t\t\t},\n\t\t\t\"f2\" : function () { this.rename(this.data.ui.hovered || this.data.ui.last_selected); },\n\t\t\t\"del\" : function () { this.remove(this.data.ui.hovered || this._get_node(null)); }\n\t\t},\n\t\t_fn : {\n\t\t\tenable_hotkeys : function () {\n\t\t\t\tthis.data.hotkeys.enabled = true;\n\t\t\t},\n\t\t\tdisable_hotkeys : function () {\n\t\t\t\tthis.data.hotkeys.enabled = false;\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree JSON plugin\n * The JSON data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.\n */\n(function ($) {\n\t$.jstree.plugin(\"json_data\", {\n\t\t__init : function() {\n\t\t\tvar s = this._get_settings().json_data;\n\t\t\tif(s.progressive_unload) {\n\t\t\t\tthis.get_container().bind(\"after_close.jstree\", function (e, data) {\n\t\t\t\t\tdata.rslt.obj.children(\"ul\").remove();\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tdefaults : { \n\t\t\t// `data` can be a function:\n\t\t\t//  * accepts two arguments - node being loaded and a callback to pass the result to\n\t\t\t//  * will be executed in the current tree's scope & ajax won't be supported\n\t\t\tdata : false, \n\t\t\tajax : false,\n\t\t\tcorrect_state : true,\n\t\t\tprogressive_render : false,\n\t\t\tprogressive_unload : false\n\t\t},\n\t\t_fn : {\n\t\t\tload_node : function (obj, s_call, e_call) { var _this = this; this.load_node_json(obj, function () { _this.__callback({ \"obj\" : _this._get_node(obj) }); s_call.call(this); }, e_call); },\n\t\t\t_is_loaded : function (obj) { \n\t\t\t\tvar s = this._get_settings().json_data;\n\t\t\t\tobj = this._get_node(obj); \n\t\t\t\treturn obj == -1 || !obj || (!s.ajax && !s.progressive_render && !$.isFunction(s.data)) || obj.is(\".jstree-open, .jstree-leaf\") || obj.children(\"ul\").children(\"li\").length > 0;\n\t\t\t},\n\t\t\trefresh : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar s = this._get_settings().json_data;\n\t\t\t\tif(obj && obj !== -1 && s.progressive_unload && ($.isFunction(s.data) || !!s.ajax)) {\n\t\t\t\t\tobj.removeData(\"jstree_children\");\n\t\t\t\t}\n\t\t\t\treturn this.__call_old();\n\t\t\t},\n\t\t\tload_node_json : function (obj, s_call, e_call) {\n\t\t\t\tvar s = this.get_settings().json_data, d,\n\t\t\t\t\terror_func = function () {},\n\t\t\t\t\tsuccess_func = function () {};\n\t\t\t\tobj = this._get_node(obj);\n\n\t\t\t\tif(obj && obj !== -1 && (s.progressive_render || s.progressive_unload) && !obj.is(\".jstree-open, .jstree-leaf\") && obj.children(\"ul\").children(\"li\").length === 0 && obj.data(\"jstree_children\")) {\n\t\t\t\t\td = this._parse_json(obj.data(\"jstree_children\"), obj);\n\t\t\t\t\tif(d) {\n\t\t\t\t\t\tobj.append(d);\n\t\t\t\t\t\tif(!s.progressive_unload) { obj.removeData(\"jstree_children\"); }\n\t\t\t\t\t}\n\t\t\t\t\tthis.clean_node(obj);\n\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif(obj && obj !== -1) {\n\t\t\t\t\tif(obj.data(\"jstree_is_loading\")) { return; }\n\t\t\t\t\telse { obj.data(\"jstree_is_loading\",true); }\n\t\t\t\t}\n\t\t\t\tswitch(!0) {\n\t\t\t\t\tcase (!s.data && !s.ajax): throw \"Neither data nor ajax settings supplied.\";\n\t\t\t\t\t// function option added here for easier model integration (also supporting async - see callback)\n\t\t\t\t\tcase ($.isFunction(s.data)):\n\t\t\t\t\t\ts.data.call(this, obj, $.proxy(function (d) {\n\t\t\t\t\t\t\td = this._parse_json(d, obj);\n\t\t\t\t\t\t\tif(!d) { \n\t\t\t\t\t\t\t\tif(obj === -1 || !obj) {\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { this.get_container().children(\"ul\").empty(); }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { this.correct_state(obj); }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif(e_call) { e_call.call(this); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n\t\t\t\t\t\t\t\telse { obj.append(d).children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.removeData(\"jstree_is_loading\"); }\n\t\t\t\t\t\t\t\tthis.clean_node(obj);\n\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):\n\t\t\t\t\t\tif(!obj || obj == -1) {\n\t\t\t\t\t\t\td = this._parse_json(s.data, obj);\n\t\t\t\t\t\t\tif(d) {\n\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty().append(d.children());\n\t\t\t\t\t\t\t\tthis.clean_node();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse { \n\t\t\t\t\t\t\t\tif(s.correct_state) { this.get_container().children(\"ul\").empty(); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):\n\t\t\t\t\t\terror_func = function (x, t, e) {\n\t\t\t\t\t\t\tvar ef = this.get_settings().json_data.ajax.error; \n\t\t\t\t\t\t\tif(ef) { ef.call(this, x, t, e); }\n\t\t\t\t\t\t\tif(obj != -1 && obj.length) {\n\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\tif(t === \"success\" && s.correct_state) { this.correct_state(obj); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(t === \"success\" && s.correct_state) { this.get_container().children(\"ul\").empty(); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(e_call) { e_call.call(this); }\n\t\t\t\t\t\t};\n\t\t\t\t\t\tsuccess_func = function (d, t, x) {\n\t\t\t\t\t\t\tvar sf = this.get_settings().json_data.ajax.success; \n\t\t\t\t\t\t\tif(sf) { d = sf.call(this,d,t,x) || d; }\n\t\t\t\t\t\t\tif(d === \"\" || (d && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") === \"\") || (!$.isArray(d) && !$.isPlainObject(d))) {\n\t\t\t\t\t\t\t\treturn error_func.call(this, x, t, \"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\td = this._parse_json(d, obj);\n\t\t\t\t\t\t\tif(d) {\n\t\t\t\t\t\t\t\tif(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n\t\t\t\t\t\t\t\telse { obj.append(d).children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.removeData(\"jstree_is_loading\"); }\n\t\t\t\t\t\t\t\tthis.clean_node(obj);\n\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(obj === -1 || !obj) {\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty(); \n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.correct_state(obj);\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\ts.ajax.context = this;\n\t\t\t\t\t\ts.ajax.error = error_func;\n\t\t\t\t\t\ts.ajax.success = success_func;\n\t\t\t\t\t\tif(!s.ajax.dataType) { s.ajax.dataType = \"json\"; }\n\t\t\t\t\t\tif($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }\n\t\t\t\t\t\tif($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }\n\t\t\t\t\t\t$.ajax(s.ajax);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\t_parse_json : function (js, obj, is_callback) {\n\t\t\t\tvar d = false, \n\t\t\t\t\tp = this._get_settings(),\n\t\t\t\t\ts = p.json_data,\n\t\t\t\t\tt = p.core.html_titles,\n\t\t\t\t\ttmp, i, j, ul1, ul2;\n\n\t\t\t\tif(!js) { return d; }\n\t\t\t\tif(s.progressive_unload && obj && obj !== -1) { \n\t\t\t\t\tobj.data(\"jstree_children\", d);\n\t\t\t\t}\n\t\t\t\tif($.isArray(js)) {\n\t\t\t\t\td = $();\n\t\t\t\t\tif(!js.length) { return false; }\n\t\t\t\t\tfor(i = 0, j = js.length; i < j; i++) {\n\t\t\t\t\t\ttmp = this._parse_json(js[i], obj, true);\n\t\t\t\t\t\tif(tmp.length) { d = d.add(tmp); }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(typeof js == \"string\") { js = { data : js }; }\n\t\t\t\t\tif(!js.data && js.data !== \"\") { return d; }\n\t\t\t\t\td = $(\"<li />\");\n\t\t\t\t\tif(js.attr) { d.attr(js.attr); }\n\t\t\t\t\tif(js.metadata) { d.data(js.metadata); }\n\t\t\t\t\tif(js.state) { d.addClass(\"jstree-\" + js.state); }\n\t\t\t\t\tif(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }\n\t\t\t\t\t$.each(js.data, function (i, m) {\n\t\t\t\t\t\ttmp = $(\"<a />\");\n\t\t\t\t\t\tif($.isFunction(m)) { m = m.call(this, js); }\n\t\t\t\t\t\tif(typeof m == \"string\") { tmp.attr('href','#')[ t ? \"html\" : \"text\" ](m); }\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif(!m.attr) { m.attr = {}; }\n\t\t\t\t\t\t\tif(!m.attr.href) { m.attr.href = '#'; }\n\t\t\t\t\t\t\ttmp.attr(m.attr)[ t ? \"html\" : \"text\" ](m.title);\n\t\t\t\t\t\t\tif(m.language) { tmp.addClass(m.language); }\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmp.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n\t\t\t\t\t\tif(!m.icon && js.icon) { m.icon = js.icon; }\n\t\t\t\t\t\tif(m.icon) { \n\t\t\t\t\t\t\tif(m.icon.indexOf(\"/\") === -1) { tmp.children(\"ins\").addClass(m.icon); }\n\t\t\t\t\t\t\telse { tmp.children(\"ins\").css(\"background\",\"url('\" + m.icon + \"') center center no-repeat\"); }\n\t\t\t\t\t\t}\n\t\t\t\t\t\td.append(tmp);\n\t\t\t\t\t});\n\t\t\t\t\td.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n\t\t\t\t\tif(js.children) { \n\t\t\t\t\t\tif(s.progressive_render && js.state !== \"open\") {\n\t\t\t\t\t\t\td.addClass(\"jstree-closed\").data(\"jstree_children\", js.children);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif(s.progressive_unload) { d.data(\"jstree_children\", js.children); }\n\t\t\t\t\t\t\tif($.isArray(js.children) && js.children.length) {\n\t\t\t\t\t\t\t\ttmp = this._parse_json(js.children, obj, true);\n\t\t\t\t\t\t\t\tif(tmp.length) {\n\t\t\t\t\t\t\t\t\tul2 = $(\"<ul />\");\n\t\t\t\t\t\t\t\t\tul2.append(tmp);\n\t\t\t\t\t\t\t\t\td.append(ul2);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(!is_callback) {\n\t\t\t\t\tul1 = $(\"<ul />\");\n\t\t\t\t\tul1.append(d);\n\t\t\t\t\td = ul1;\n\t\t\t\t}\n\t\t\t\treturn d;\n\t\t\t},\n\t\t\tget_json : function (obj, li_attr, a_attr, is_callback) {\n\t\t\t\tvar result = [], \n\t\t\t\t\ts = this._get_settings(), \n\t\t\t\t\t_this = this,\n\t\t\t\t\ttmp1, tmp2, li, a, t, lang;\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj || obj === -1) { obj = this.get_container().find(\"> ul > li\"); }\n\t\t\t\tli_attr = $.isArray(li_attr) ? li_attr : [ \"id\", \"class\" ];\n\t\t\t\tif(!is_callback && this.data.types) { li_attr.push(s.types.type_attr); }\n\t\t\t\ta_attr = $.isArray(a_attr) ? a_attr : [ ];\n\n\t\t\t\tobj.each(function () {\n\t\t\t\t\tli = $(this);\n\t\t\t\t\ttmp1 = { data : [] };\n\t\t\t\t\tif(li_attr.length) { tmp1.attr = { }; }\n\t\t\t\t\t$.each(li_attr, function (i, v) { \n\t\t\t\t\t\ttmp2 = li.attr(v); \n\t\t\t\t\t\tif(tmp2 && tmp2.length && tmp2.replace(/jstree[^ ]*/ig,'').length) {\n\t\t\t\t\t\t\ttmp1.attr[v] = (\" \" + tmp2).replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\"); \n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif(li.hasClass(\"jstree-open\")) { tmp1.state = \"open\"; }\n\t\t\t\t\tif(li.hasClass(\"jstree-closed\")) { tmp1.state = \"closed\"; }\n\t\t\t\t\tif(li.data()) { tmp1.metadata = li.data(); }\n\t\t\t\t\ta = li.children(\"a\");\n\t\t\t\t\ta.each(function () {\n\t\t\t\t\t\tt = $(this);\n\t\t\t\t\t\tif(\n\t\t\t\t\t\t\ta_attr.length || \n\t\t\t\t\t\t\t$.inArray(\"languages\", s.plugins) !== -1 || \n\t\t\t\t\t\t\tt.children(\"ins\").get(0).style.backgroundImage.length || \n\t\t\t\t\t\t\t(t.children(\"ins\").get(0).className && t.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').length)\n\t\t\t\t\t\t) { \n\t\t\t\t\t\t\tlang = false;\n\t\t\t\t\t\t\tif($.inArray(\"languages\", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {\n\t\t\t\t\t\t\t\t$.each(s.languages, function (l, lv) {\n\t\t\t\t\t\t\t\t\tif(t.hasClass(lv)) {\n\t\t\t\t\t\t\t\t\t\tlang = lv;\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttmp2 = { attr : { }, title : _this.get_text(t, lang) }; \n\t\t\t\t\t\t\t$.each(a_attr, function (k, z) {\n\t\t\t\t\t\t\t\ttmp2.attr[z] = (\" \" + (t.attr(z) || \"\")).replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\");\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif($.inArray(\"languages\", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {\n\t\t\t\t\t\t\t\t$.each(s.languages, function (k, z) {\n\t\t\t\t\t\t\t\t\tif(t.hasClass(z)) { tmp2.language = z; return true; }\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(t.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\\s+$/ig,\"\").length) {\n\t\t\t\t\t\t\t\ttmp2.icon = t.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(t.children(\"ins\").get(0).style.backgroundImage.length) {\n\t\t\t\t\t\t\t\ttmp2.icon = t.children(\"ins\").get(0).style.backgroundImage.replace(\"url(\",\"\").replace(\")\",\"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\ttmp2 = _this.get_text(t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(a.length > 1) { tmp1.data.push(tmp2); }\n\t\t\t\t\t\telse { tmp1.data = tmp2; }\n\t\t\t\t\t});\n\t\t\t\t\tli = li.find(\"> ul > li\");\n\t\t\t\t\tif(li.length) { tmp1.children = _this.get_json(li, li_attr, a_attr, true); }\n\t\t\t\t\tresult.push(tmp1);\n\t\t\t\t});\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree languages plugin\n * Adds support for multiple language versions in one tree\n * This basically allows for many titles coexisting in one node, but only one of them being visible at any given time\n * This is useful for maintaining the same structure in many languages (hence the name of the plugin)\n */\n(function ($) {\n\t$.jstree.plugin(\"languages\", {\n\t\t__init : function () { this._load_css();  },\n\t\tdefaults : [],\n\t\t_fn : {\n\t\t\tset_lang : function (i) { \n\t\t\t\tvar langs = this._get_settings().languages,\n\t\t\t\t\tst = false,\n\t\t\t\t\tselector = \".jstree-\" + this.get_index() + ' a';\n\t\t\t\tif(!$.isArray(langs) || langs.length === 0) { return false; }\n\t\t\t\tif($.inArray(i,langs) == -1) {\n\t\t\t\t\tif(!!langs[i]) { i = langs[i]; }\n\t\t\t\t\telse { return false; }\n\t\t\t\t}\n\t\t\t\tif(i == this.data.languages.current_language) { return true; }\n\t\t\t\tst = $.vakata.css.get_css(selector + \".\" + this.data.languages.current_language, false, this.data.languages.language_css);\n\t\t\t\tif(st !== false) { st.style.display = \"none\"; }\n\t\t\t\tst = $.vakata.css.get_css(selector + \".\" + i, false, this.data.languages.language_css);\n\t\t\t\tif(st !== false) { st.style.display = \"\"; }\n\t\t\t\tthis.data.languages.current_language = i;\n\t\t\t\tthis.__callback(i);\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tget_lang : function () {\n\t\t\t\treturn this.data.languages.current_language;\n\t\t\t},\n\t\t\t_get_string : function (key, lang) {\n\t\t\t\tvar langs = this._get_settings().languages,\n\t\t\t\t\ts = this._get_settings().core.strings;\n\t\t\t\tif($.isArray(langs) && langs.length) {\n\t\t\t\t\tlang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;\n\t\t\t\t}\n\t\t\t\tif(s[lang] && s[lang][key]) { return s[lang][key]; }\n\t\t\t\tif(s[key]) { return s[key]; }\n\t\t\t\treturn key;\n\t\t\t},\n\t\t\tget_text : function (obj, lang) {\n\t\t\t\tobj = this._get_node(obj) || this.data.ui.last_selected;\n\t\t\t\tif(!obj.size()) { return false; }\n\t\t\t\tvar langs = this._get_settings().languages,\n\t\t\t\t\ts = this._get_settings().core.html_titles;\n\t\t\t\tif($.isArray(langs) && langs.length) {\n\t\t\t\t\tlang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;\n\t\t\t\t\tobj = obj.children(\"a.\" + lang);\n\t\t\t\t}\n\t\t\t\telse { obj = obj.children(\"a:eq(0)\"); }\n\t\t\t\tif(s) {\n\t\t\t\t\tobj = obj.clone();\n\t\t\t\t\tobj.children(\"INS\").remove();\n\t\t\t\t\treturn obj.html();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tobj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n\t\t\t\t\treturn obj.nodeValue;\n\t\t\t\t}\n\t\t\t},\n\t\t\tset_text : function (obj, val, lang) {\n\t\t\t\tobj = this._get_node(obj) || this.data.ui.last_selected;\n\t\t\t\tif(!obj.size()) { return false; }\n\t\t\t\tvar langs = this._get_settings().languages,\n\t\t\t\t\ts = this._get_settings().core.html_titles,\n\t\t\t\t\ttmp;\n\t\t\t\tif($.isArray(langs) && langs.length) {\n\t\t\t\t\tlang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;\n\t\t\t\t\tobj = obj.children(\"a.\" + lang);\n\t\t\t\t}\n\t\t\t\telse { obj = obj.children(\"a:eq(0)\"); }\n\t\t\t\tif(s) {\n\t\t\t\t\ttmp = obj.children(\"INS\").clone();\n\t\t\t\t\tobj.html(val).prepend(tmp);\n\t\t\t\t\tthis.__callback({ \"obj\" : obj, \"name\" : val, \"lang\" : lang });\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tobj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n\t\t\t\t\tthis.__callback({ \"obj\" : obj, \"name\" : val, \"lang\" : lang });\n\t\t\t\t\treturn (obj.nodeValue = val);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_load_css : function () {\n\t\t\t\tvar langs = this._get_settings().languages,\n\t\t\t\t\tstr = \"/* languages css */\",\n\t\t\t\t\tselector = \".jstree-\" + this.get_index() + ' a',\n\t\t\t\t\tln;\n\t\t\t\tif($.isArray(langs) && langs.length) {\n\t\t\t\t\tthis.data.languages.current_language = langs[0];\n\t\t\t\t\tfor(ln = 0; ln < langs.length; ln++) {\n\t\t\t\t\t\tstr += selector + \".\" + langs[ln] + \" {\";\n\t\t\t\t\t\tif(langs[ln] != this.data.languages.current_language) { str += \" display:none; \"; }\n\t\t\t\t\t\tstr += \" } \";\n\t\t\t\t\t}\n\t\t\t\t\tthis.data.languages.language_css = $.vakata.css.add_sheet({ 'str' : str, 'title' : \"jstree-languages\" });\n\t\t\t\t}\n\t\t\t},\n\t\t\tcreate_node : function (obj, position, js, callback) {\n\t\t\t\tvar t = this.__call_old(true, obj, position, js, function (t) {\n\t\t\t\t\tvar langs = this._get_settings().languages,\n\t\t\t\t\t\ta = t.children(\"a\"),\n\t\t\t\t\t\tln;\n\t\t\t\t\tif($.isArray(langs) && langs.length) {\n\t\t\t\t\t\tfor(ln = 0; ln < langs.length; ln++) {\n\t\t\t\t\t\t\tif(!a.is(\".\" + langs[ln])) {\n\t\t\t\t\t\t\t\tt.append(a.eq(0).clone().removeClass(langs.join(\" \")).addClass(langs[ln]));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\ta.not(\".\" + langs.join(\", .\")).remove();\n\t\t\t\t\t}\n\t\t\t\t\tif(callback) { callback.call(this, t); }\n\t\t\t\t});\n\t\t\t\treturn t;\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/*\n * jsTree cookies plugin\n * Stores the currently opened/selected nodes in a cookie and then restores them\n * Depends on the jquery.cookie plugin\n */\n(function ($) {\n\t$.jstree.plugin(\"cookies\", {\n\t\t__init : function () {\n\t\t\tif(typeof $.cookie === \"undefined\") { throw \"jsTree cookie: jQuery cookie plugin not included.\"; }\n\n\t\t\tvar s = this._get_settings().cookies,\n\t\t\t\ttmp;\n\t\t\tif(!!s.save_loaded) {\n\t\t\t\ttmp = $.cookie(s.save_loaded);\n\t\t\t\tif(tmp && tmp.length) { this.data.core.to_load = tmp.split(\",\"); }\n\t\t\t}\n\t\t\tif(!!s.save_opened) {\n\t\t\t\ttmp = $.cookie(s.save_opened);\n\t\t\t\tif(tmp && tmp.length) { this.data.core.to_open = tmp.split(\",\"); }\n\t\t\t}\n\t\t\tif(!!s.save_selected) {\n\t\t\t\ttmp = $.cookie(s.save_selected);\n\t\t\t\tif(tmp && tmp.length && this.data.ui) { this.data.ui.to_select = tmp.split(\",\"); }\n\t\t\t}\n\t\t\tthis.get_container()\n\t\t\t\t.one( ( this.data.ui ? \"reselect\" : \"reopen\" ) + \".jstree\", $.proxy(function () {\n\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t.bind(\"open_node.jstree close_node.jstree select_node.jstree deselect_node.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\t\t\tif(this._get_settings().cookies.auto_save) { this.save_cookie((e.handleObj.namespace + e.handleObj.type).replace(\"jstree\",\"\")); }\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : {\n\t\t\tsave_loaded\t\t: \"jstree_load\",\n\t\t\tsave_opened\t\t: \"jstree_open\",\n\t\t\tsave_selected\t: \"jstree_select\",\n\t\t\tauto_save\t\t: true,\n\t\t\tcookie_options\t: {}\n\t\t},\n\t\t_fn : {\n\t\t\tsave_cookie : function (c) {\n\t\t\t\tif(this.data.core.refreshing) { return; }\n\t\t\t\tvar s = this._get_settings().cookies;\n\t\t\t\tif(!c) { // if called manually and not by event\n\t\t\t\t\tif(s.save_loaded) {\n\t\t\t\t\t\tthis.save_loaded();\n\t\t\t\t\t\t$.cookie(s.save_loaded, this.data.core.to_load.join(\",\"), s.cookie_options);\n\t\t\t\t\t}\n\t\t\t\t\tif(s.save_opened) {\n\t\t\t\t\t\tthis.save_opened();\n\t\t\t\t\t\t$.cookie(s.save_opened, this.data.core.to_open.join(\",\"), s.cookie_options);\n\t\t\t\t\t}\n\t\t\t\t\tif(s.save_selected && this.data.ui) {\n\t\t\t\t\t\tthis.save_selected();\n\t\t\t\t\t\t$.cookie(s.save_selected, this.data.ui.to_select.join(\",\"), s.cookie_options);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch(c) {\n\t\t\t\t\tcase \"open_node\":\n\t\t\t\t\tcase \"close_node\":\n\t\t\t\t\t\tif(!!s.save_opened) { \n\t\t\t\t\t\t\tthis.save_opened(); \n\t\t\t\t\t\t\t$.cookie(s.save_opened, this.data.core.to_open.join(\",\"), s.cookie_options); \n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!!s.save_loaded) { \n\t\t\t\t\t\t\tthis.save_loaded(); \n\t\t\t\t\t\t\t$.cookie(s.save_loaded, this.data.core.to_load.join(\",\"), s.cookie_options); \n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"select_node\":\n\t\t\t\t\tcase \"deselect_node\":\n\t\t\t\t\t\tif(!!s.save_selected && this.data.ui) { \n\t\t\t\t\t\t\tthis.save_selected(); \n\t\t\t\t\t\t\t$.cookie(s.save_selected, this.data.ui.to_select.join(\",\"), s.cookie_options); \n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// include cookies by default\n\t// $.jstree.defaults.plugins.push(\"cookies\");\n})(jQuery);\n//*/\n\n/*\n * jsTree sort plugin\n * Sorts items alphabetically (or using any other function)\n */\n(function ($) {\n\t$.jstree.plugin(\"sort\", {\n\t\t__init : function () {\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"load_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tvar obj = this._get_node(data.rslt.obj);\n\t\t\t\t\t\tobj = obj === -1 ? this.get_container().children(\"ul\") : obj.children(\"ul\");\n\t\t\t\t\t\tthis.sort(obj);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"rename_node.jstree create_node.jstree create.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tthis.sort(data.rslt.obj.parent());\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"move_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tvar m = data.rslt.np == -1 ? this.get_container() : data.rslt.np;\n\t\t\t\t\t\tthis.sort(m.children(\"ul\"));\n\t\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : function (a, b) { return this.get_text(a) > this.get_text(b) ? 1 : -1; },\n\t\t_fn : {\n\t\t\tsort : function (obj) {\n\t\t\t\tvar s = this._get_settings().sort,\n\t\t\t\t\tt = this;\n\t\t\t\tobj.append($.makeArray(obj.children(\"li\")).sort($.proxy(s, t)));\n\t\t\t\tobj.find(\"> li > ul\").each(function() { t.sort($(this)); });\n\t\t\t\tthis.clean_node(obj);\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/*\n * jsTree DND plugin\n * Drag and drop plugin for moving/copying nodes\n */\n(function ($) {\n\tvar o = false,\n\t\tr = false,\n\t\tm = false,\n\t\tml = false,\n\t\tsli = false,\n\t\tsti = false,\n\t\tdir1 = false,\n\t\tdir2 = false,\n\t\tlast_pos = false;\n\t$.vakata.dnd = {\n\t\tis_down : false,\n\t\tis_drag : false,\n\t\thelper : false,\n\t\tscroll_spd : 10,\n\t\tinit_x : 0,\n\t\tinit_y : 0,\n\t\tthreshold : 5,\n\t\thelper_left : 5,\n\t\thelper_top : 10,\n\t\tuser_data : {},\n\n\t\tdrag_start : function (e, data, html) { \n\t\t\tif($.vakata.dnd.is_drag) { $.vakata.drag_stop({}); }\n\t\t\ttry {\n\t\t\t\te.currentTarget.unselectable = \"on\";\n\t\t\t\te.currentTarget.onselectstart = function() { return false; };\n\t\t\t\tif(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = \"none\"; }\n\t\t\t} catch(err) { }\n\t\t\t$.vakata.dnd.init_x = e.pageX;\n\t\t\t$.vakata.dnd.init_y = e.pageY;\n\t\t\t$.vakata.dnd.user_data = data;\n\t\t\t$.vakata.dnd.is_down = true;\n\t\t\t$.vakata.dnd.helper = $(\"<div id='vakata-dragged' />\").html(html); //.fadeTo(10,0.25);\n\t\t\t$(document).bind(\"mousemove\", $.vakata.dnd.drag);\n\t\t\t$(document).bind(\"mouseup\", $.vakata.dnd.drag_stop);\n\t\t\treturn false;\n\t\t},\n\t\tdrag : function (e) { \n\t\t\tif(!$.vakata.dnd.is_down) { return; }\n\t\t\tif(!$.vakata.dnd.is_drag) {\n\t\t\t\tif(Math.abs(e.pageX - $.vakata.dnd.init_x) > 5 || Math.abs(e.pageY - $.vakata.dnd.init_y) > 5) { \n\t\t\t\t\t$.vakata.dnd.helper.appendTo(\"body\");\n\t\t\t\t\t$.vakata.dnd.is_drag = true;\n\t\t\t\t\t$(document).triggerHandler(\"drag_start.vakata\", { \"event\" : e, \"data\" : $.vakata.dnd.user_data });\n\t\t\t\t}\n\t\t\t\telse { return; }\n\t\t\t}\n\n\t\t\t// maybe use a scrolling parent element instead of document?\n\t\t\tif(e.type === \"mousemove\") { // thought of adding scroll in order to move the helper, but mouse poisition is n/a\n\t\t\t\tvar d = $(document), t = d.scrollTop(), l = d.scrollLeft();\n\t\t\t\tif(e.pageY - t < 20) { \n\t\t\t\t\tif(sti && dir1 === \"down\") { clearInterval(sti); sti = false; }\n\t\t\t\t\tif(!sti) { dir1 = \"up\"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() - $.vakata.dnd.scroll_spd); }, 150); }\n\t\t\t\t}\n\t\t\t\telse { \n\t\t\t\t\tif(sti && dir1 === \"up\") { clearInterval(sti); sti = false; }\n\t\t\t\t}\n\t\t\t\tif($(window).height() - (e.pageY - t) < 20) {\n\t\t\t\t\tif(sti && dir1 === \"up\") { clearInterval(sti); sti = false; }\n\t\t\t\t\tif(!sti) { dir1 = \"down\"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() + $.vakata.dnd.scroll_spd); }, 150); }\n\t\t\t\t}\n\t\t\t\telse { \n\t\t\t\t\tif(sti && dir1 === \"down\") { clearInterval(sti); sti = false; }\n\t\t\t\t}\n\n\t\t\t\tif(e.pageX - l < 20) {\n\t\t\t\t\tif(sli && dir2 === \"right\") { clearInterval(sli); sli = false; }\n\t\t\t\t\tif(!sli) { dir2 = \"left\"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() - $.vakata.dnd.scroll_spd); }, 150); }\n\t\t\t\t}\n\t\t\t\telse { \n\t\t\t\t\tif(sli && dir2 === \"left\") { clearInterval(sli); sli = false; }\n\t\t\t\t}\n\t\t\t\tif($(window).width() - (e.pageX - l) < 20) {\n\t\t\t\t\tif(sli && dir2 === \"left\") { clearInterval(sli); sli = false; }\n\t\t\t\t\tif(!sli) { dir2 = \"right\"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() + $.vakata.dnd.scroll_spd); }, 150); }\n\t\t\t\t}\n\t\t\t\telse { \n\t\t\t\t\tif(sli && dir2 === \"right\") { clearInterval(sli); sli = false; }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$.vakata.dnd.helper.css({ left : (e.pageX + $.vakata.dnd.helper_left) + \"px\", top : (e.pageY + $.vakata.dnd.helper_top) + \"px\" });\n\t\t\t$(document).triggerHandler(\"drag.vakata\", { \"event\" : e, \"data\" : $.vakata.dnd.user_data });\n\t\t},\n\t\tdrag_stop : function (e) {\n\t\t\tif(sli) { clearInterval(sli); }\n\t\t\tif(sti) { clearInterval(sti); }\n\t\t\t$(document).unbind(\"mousemove\", $.vakata.dnd.drag);\n\t\t\t$(document).unbind(\"mouseup\", $.vakata.dnd.drag_stop);\n\t\t\t$(document).triggerHandler(\"drag_stop.vakata\", { \"event\" : e, \"data\" : $.vakata.dnd.user_data });\n\t\t\t$.vakata.dnd.helper.remove();\n\t\t\t$.vakata.dnd.init_x = 0;\n\t\t\t$.vakata.dnd.init_y = 0;\n\t\t\t$.vakata.dnd.user_data = {};\n\t\t\t$.vakata.dnd.is_down = false;\n\t\t\t$.vakata.dnd.is_drag = false;\n\t\t}\n\t};\n\t$(function() {\n\t\tvar css_string = '#vakata-dragged { display:block; margin:0 0 0 0; padding:4px 4px 4px 24px; position:absolute; top:-2000px; line-height:16px; z-index:10000; } ';\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"vakata\" });\n\t});\n\n\t$.jstree.plugin(\"dnd\", {\n\t\t__init : function () {\n\t\t\tthis.data.dnd = {\n\t\t\t\tactive : false,\n\t\t\t\tafter : false,\n\t\t\t\tinside : false,\n\t\t\t\tbefore : false,\n\t\t\t\toff : false,\n\t\t\t\tprepared : false,\n\t\t\t\tw : 0,\n\t\t\t\tto1 : false,\n\t\t\t\tto2 : false,\n\t\t\t\tcof : false,\n\t\t\t\tcw : false,\n\t\t\t\tch : false,\n\t\t\t\ti1 : false,\n\t\t\t\ti2 : false,\n\t\t\t\tmto : false\n\t\t\t};\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"mouseenter.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tif(this.data.themes) {\n\t\t\t\t\t\t\t\tm.attr(\"class\", \"jstree-\" + this.data.themes.theme); \n\t\t\t\t\t\t\t\tif(ml) { ml.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n\t\t\t\t\t\t\t\t$.vakata.dnd.helper.attr(\"class\", \"jstree-dnd-helper jstree-\" + this.data.themes.theme);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t//if($(e.currentTarget).find(\"> ul > li\").length === 0) {\n\t\t\t\t\t\t\tif(e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(\".jstree:eq(0)\")[0] !== e.target) { // node should not be from the same tree\n\t\t\t\t\t\t\t\tvar tr = $.jstree._reference(e.target), dc;\n\t\t\t\t\t\t\t\tif(tr.data.dnd.foreign) {\n\t\t\t\t\t\t\t\t\tdc = tr._get_settings().dnd.drag_check.call(this, { \"o\" : o, \"r\" : tr.get_container(), is_root : true });\n\t\t\t\t\t\t\t\t\tif(dc === true || dc.inside === true || dc.before === true || dc.after === true) {\n\t\t\t\t\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\ttr.prepare_move(o, tr.get_container(), \"last\");\n\t\t\t\t\t\t\t\t\tif(tr.check_move()) {\n\t\t\t\t\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"mouseup.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\t//if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && $(e.currentTarget).find(\"> ul > li\").length === 0) {\n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(\".jstree:eq(0)\")[0] !== e.target) { // node should not be from the same tree\n\t\t\t\t\t\t\tvar tr = $.jstree._reference(e.currentTarget), dc;\n\t\t\t\t\t\t\tif(tr.data.dnd.foreign) {\n\t\t\t\t\t\t\t\tdc = tr._get_settings().dnd.drag_check.call(this, { \"o\" : o, \"r\" : tr.get_container(), is_root : true });\n\t\t\t\t\t\t\t\tif(dc === true || dc.inside === true || dc.before === true || dc.after === true) {\n\t\t\t\t\t\t\t\t\ttr._get_settings().dnd.drag_finish.call(this, { \"o\" : o, \"r\" : tr.get_container(), is_root : true });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\ttr.move_node(o, tr.get_container(), \"last\", e[tr._get_settings().dnd.copy_modifier + \"Key\"]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"mouseleave.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tif(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === \"jstree-marker-line\") {\n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tif(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n\t\t\t\t\t\t\tif(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n\t\t\t\t\t\t\tif(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }\n\t\t\t\t\t\t\tif(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }\n\t\t\t\t\t\t\tif($.vakata.dnd.helper.children(\"ins\").hasClass(\"jstree-ok\")) {\n\t\t\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"mousemove.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tvar cnt = this.get_container()[0];\n\n\t\t\t\t\t\t\t// Horizontal scroll\n\t\t\t\t\t\t\tif(e.pageX + 24 > this.data.dnd.cof.left + this.data.dnd.cw) {\n\t\t\t\t\t\t\t\tif(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n\t\t\t\t\t\t\t\tthis.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft += $.vakata.dnd.scroll_spd; }, cnt), 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(e.pageX - 24 < this.data.dnd.cof.left) {\n\t\t\t\t\t\t\t\tif(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n\t\t\t\t\t\t\t\tthis.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft -= $.vakata.dnd.scroll_spd; }, cnt), 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Vertical scroll\n\t\t\t\t\t\t\tif(e.pageY + 24 > this.data.dnd.cof.top + this.data.dnd.ch) {\n\t\t\t\t\t\t\t\tif(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n\t\t\t\t\t\t\t\tthis.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop += $.vakata.dnd.scroll_spd; }, cnt), 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(e.pageY - 24 < this.data.dnd.cof.top) {\n\t\t\t\t\t\t\t\tif(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n\t\t\t\t\t\t\t\tthis.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop -= $.vakata.dnd.scroll_spd; }, cnt), 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"scroll.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && m && ml) {\n\t\t\t\t\t\t\tm.hide();\n\t\t\t\t\t\t\tml.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mousedown.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\tif(e.which === 1) {\n\t\t\t\t\t\t\tthis.start_drag(e.currentTarget, e);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mouseenter.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tthis.dnd_enter(e.currentTarget);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mousemove.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tif(!r || !r.length || r.children(\"a\")[0] !== e.currentTarget) {\n\t\t\t\t\t\t\t\tthis.dnd_enter(e.currentTarget);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(typeof this.data.dnd.off.top === \"undefined\") { this.data.dnd.off = $(e.target).offset(); }\n\t\t\t\t\t\t\tthis.data.dnd.w = (e.pageY - (this.data.dnd.off.top || 0)) % this.data.core.li_height;\n\t\t\t\t\t\t\tif(this.data.dnd.w < 0) { this.data.dnd.w += this.data.core.li_height; }\n\t\t\t\t\t\t\tthis.dnd_show();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mouseleave.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tif(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === \"jstree-marker-line\") {\n\t\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif(m) { m.hide(); }\n\t\t\t\t\t\t\t\tif(ml) { ml.hide(); }\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tvar ec = $(e.currentTarget).closest(\"li\"), \n\t\t\t\t\t\t\t\ter = $(e.relatedTarget).closest(\"li\");\n\t\t\t\t\t\t\tif(er[0] !== ec.prev()[0] && er[0] !== ec.next()[0]) {\n\t\t\t\t\t\t\t\tif(m) { m.hide(); }\n\t\t\t\t\t\t\t\tif(ml) { ml.hide(); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tthis.data.dnd.mto = setTimeout( \n\t\t\t\t\t\t\t\t(function (t) { return function () { t.dnd_leave(e); }; })(this),\n\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"mouseup.jstree\", $.proxy(function (e) { \n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n\t\t\t\t\t\t\tthis.dnd_finish(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\n\t\t\t$(document)\n\t\t\t\t.bind(\"drag_stop.vakata\", $.proxy(function () {\n\t\t\t\t\t\tif(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }\n\t\t\t\t\t\tif(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }\n\t\t\t\t\t\tif(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n\t\t\t\t\t\tif(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n\t\t\t\t\t\tthis.data.dnd.after\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.before\t= false;\n\t\t\t\t\t\tthis.data.dnd.inside\t= false;\n\t\t\t\t\t\tthis.data.dnd.off\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.prepared\t= false;\n\t\t\t\t\t\tthis.data.dnd.w\t\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.to1\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.to2\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.i1\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.i2\t\t= false;\n\t\t\t\t\t\tthis.data.dnd.active\t= false;\n\t\t\t\t\t\tthis.data.dnd.foreign\t= false;\n\t\t\t\t\t\tif(m) { m.css({ \"top\" : \"-2000px\" }); }\n\t\t\t\t\t\tif(ml) { ml.css({ \"top\" : \"-2000px\" }); }\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"drag_start.vakata\", $.proxy(function (e, data) {\n\t\t\t\t\t\tif(data.data.jstree) { \n\t\t\t\t\t\t\tvar et = $(data.event.target);\n\t\t\t\t\t\t\tif(et.closest(\".jstree\").hasClass(\"jstree-\" + this.get_index())) {\n\t\t\t\t\t\t\t\tthis.dnd_enter(et);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\t\t\t\t/*\n\t\t\t\t.bind(\"keydown.jstree-\" + this.get_index() + \" keyup.jstree-\" + this.get_index(), $.proxy(function(e) {\n\t\t\t\t\t\tif($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && !this.data.dnd.foreign) {\n\t\t\t\t\t\t\tvar h = $.vakata.dnd.helper.children(\"ins\");\n\t\t\t\t\t\t\tif(e[this._get_settings().dnd.copy_modifier + \"Key\"] && h.hasClass(\"jstree-ok\")) {\n\t\t\t\t\t\t\t\th.parent().html(h.parent().html().replace(/ \\(Copy\\)$/, \"\") + \" (Copy)\");\n\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\th.parent().html(h.parent().html().replace(/ \\(Copy\\)$/, \"\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this)); */\n\n\n\n\t\t\tvar s = this._get_settings().dnd;\n\t\t\tif(s.drag_target) {\n\t\t\t\t$(document)\n\t\t\t\t\t.delegate(s.drag_target, \"mousedown.jstree-\" + this.get_index(), $.proxy(function (e) {\n\t\t\t\t\t\to = e.target;\n\t\t\t\t\t\t$.vakata.dnd.drag_start(e, { jstree : true, obj : e.target }, \"<ins class='jstree-icon'></ins>\" + $(e.target).text() );\n\t\t\t\t\t\tif(this.data.themes) { \n\t\t\t\t\t\t\tif(m) { m.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n\t\t\t\t\t\t\tif(ml) { ml.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n\t\t\t\t\t\t\t$.vakata.dnd.helper.attr(\"class\", \"jstree-dnd-helper jstree-\" + this.data.themes.theme); \n\t\t\t\t\t\t}\n\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n\t\t\t\t\t\tvar cnt = this.get_container();\n\t\t\t\t\t\tthis.data.dnd.cof = cnt.offset();\n\t\t\t\t\t\tthis.data.dnd.cw = parseInt(cnt.width(),10);\n\t\t\t\t\t\tthis.data.dnd.ch = parseInt(cnt.height(),10);\n\t\t\t\t\t\tthis.data.dnd.foreign = true;\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}, this));\n\t\t\t}\n\t\t\tif(s.drop_target) {\n\t\t\t\t$(document)\n\t\t\t\t\t.delegate(s.drop_target, \"mouseenter.jstree-\" + this.get_index(), $.proxy(function (e) {\n\t\t\t\t\t\t\tif(this.data.dnd.active && this._get_settings().dnd.drop_check.call(this, { \"o\" : o, \"r\" : $(e.target), \"e\" : e })) {\n\t\t\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this))\n\t\t\t\t\t.delegate(s.drop_target, \"mouseleave.jstree-\" + this.get_index(), $.proxy(function (e) {\n\t\t\t\t\t\t\tif(this.data.dnd.active) {\n\t\t\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this))\n\t\t\t\t\t.delegate(s.drop_target, \"mouseup.jstree-\" + this.get_index(), $.proxy(function (e) {\n\t\t\t\t\t\t\tif(this.data.dnd.active && $.vakata.dnd.helper.children(\"ins\").hasClass(\"jstree-ok\")) {\n\t\t\t\t\t\t\t\tthis._get_settings().dnd.drop_finish.call(this, { \"o\" : o, \"r\" : $(e.target), \"e\" : e });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this));\n\t\t\t}\n\t\t},\n\t\tdefaults : {\n\t\t\tcopy_modifier\t: \"ctrl\",\n\t\t\tcheck_timeout\t: 100,\n\t\t\topen_timeout\t: 500,\n\t\t\tdrop_target\t\t: \".jstree-drop\",\n\t\t\tdrop_check\t\t: function (data) { return true; },\n\t\t\tdrop_finish\t\t: $.noop,\n\t\t\tdrag_target\t\t: \".jstree-draggable\",\n\t\t\tdrag_finish\t\t: $.noop,\n\t\t\tdrag_check\t\t: function (data) { return { after : false, before : false, inside : true }; }\n\t\t},\n\t\t_fn : {\n\t\t\tdnd_prepare : function () {\n\t\t\t\tif(!r || !r.length) { return; }\n\t\t\t\tthis.data.dnd.off = r.offset();\n\t\t\t\tif(this._get_settings().core.rtl) {\n\t\t\t\t\tthis.data.dnd.off.right = this.data.dnd.off.left + r.width();\n\t\t\t\t}\n\t\t\t\tif(this.data.dnd.foreign) {\n\t\t\t\t\tvar a = this._get_settings().dnd.drag_check.call(this, { \"o\" : o, \"r\" : r });\n\t\t\t\t\tthis.data.dnd.after = a.after;\n\t\t\t\t\tthis.data.dnd.before = a.before;\n\t\t\t\t\tthis.data.dnd.inside = a.inside;\n\t\t\t\t\tthis.data.dnd.prepared = true;\n\t\t\t\t\treturn this.dnd_show();\n\t\t\t\t}\n\t\t\t\tthis.prepare_move(o, r, \"before\");\n\t\t\t\tthis.data.dnd.before = this.check_move();\n\t\t\t\tthis.prepare_move(o, r, \"after\");\n\t\t\t\tthis.data.dnd.after = this.check_move();\n\t\t\t\tif(this._is_loaded(r)) {\n\t\t\t\t\tthis.prepare_move(o, r, \"inside\");\n\t\t\t\t\tthis.data.dnd.inside = this.check_move();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.data.dnd.inside = false;\n\t\t\t\t}\n\t\t\t\tthis.data.dnd.prepared = true;\n\t\t\t\treturn this.dnd_show();\n\t\t\t},\n\t\t\tdnd_show : function () {\n\t\t\t\tif(!this.data.dnd.prepared) { return; }\n\t\t\t\tvar o = [\"before\",\"inside\",\"after\"],\n\t\t\t\t\tr = false,\n\t\t\t\t\trtl = this._get_settings().core.rtl,\n\t\t\t\t\tpos;\n\t\t\t\tif(this.data.dnd.w < this.data.core.li_height/3) { o = [\"before\",\"inside\",\"after\"]; }\n\t\t\t\telse if(this.data.dnd.w <= this.data.core.li_height*2/3) {\n\t\t\t\t\to = this.data.dnd.w < this.data.core.li_height/2 ? [\"inside\",\"before\",\"after\"] : [\"inside\",\"after\",\"before\"];\n\t\t\t\t}\n\t\t\t\telse { o = [\"after\",\"inside\",\"before\"]; }\n\t\t\t\t$.each(o, $.proxy(function (i, val) { \n\t\t\t\t\tif(this.data.dnd[val]) {\n\t\t\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n\t\t\t\t\t\tr = val;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}, this));\n\t\t\t\tif(r === false) { $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\"); }\n\t\t\t\t\n\t\t\t\tpos = rtl ? (this.data.dnd.off.right - 18) : (this.data.dnd.off.left + 10);\n\t\t\t\tswitch(r) {\n\t\t\t\t\tcase \"before\":\n\t\t\t\t\t\tm.css({ \"left\" : pos + \"px\", \"top\" : (this.data.dnd.off.top - 6) + \"px\" }).show();\n\t\t\t\t\t\tif(ml) { ml.css({ \"left\" : (pos + 8) + \"px\", \"top\" : (this.data.dnd.off.top - 1) + \"px\" }).show(); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"after\":\n\t\t\t\t\t\tm.css({ \"left\" : pos + \"px\", \"top\" : (this.data.dnd.off.top + this.data.core.li_height - 6) + \"px\" }).show();\n\t\t\t\t\t\tif(ml) { ml.css({ \"left\" : (pos + 8) + \"px\", \"top\" : (this.data.dnd.off.top + this.data.core.li_height - 1) + \"px\" }).show(); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"inside\":\n\t\t\t\t\t\tm.css({ \"left\" : pos + ( rtl ? -4 : 4) + \"px\", \"top\" : (this.data.dnd.off.top + this.data.core.li_height/2 - 5) + \"px\" }).show();\n\t\t\t\t\t\tif(ml) { ml.hide(); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tm.hide();\n\t\t\t\t\t\tif(ml) { ml.hide(); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlast_pos = r;\n\t\t\t\treturn r;\n\t\t\t},\n\t\t\tdnd_open : function () {\n\t\t\t\tthis.data.dnd.to2 = false;\n\t\t\t\tthis.open_node(r, $.proxy(this.dnd_prepare,this), true);\n\t\t\t},\n\t\t\tdnd_finish : function (e) {\n\t\t\t\tif(this.data.dnd.foreign) {\n\t\t\t\t\tif(this.data.dnd.after || this.data.dnd.before || this.data.dnd.inside) {\n\t\t\t\t\t\tthis._get_settings().dnd.drag_finish.call(this, { \"o\" : o, \"r\" : r, \"p\" : last_pos });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.dnd_prepare();\n\t\t\t\t\tthis.move_node(o, r, last_pos, e[this._get_settings().dnd.copy_modifier + \"Key\"]);\n\t\t\t\t}\n\t\t\t\to = false;\n\t\t\t\tr = false;\n\t\t\t\tm.hide();\n\t\t\t\tif(ml) { ml.hide(); }\n\t\t\t},\n\t\t\tdnd_enter : function (obj) {\n\t\t\t\tif(this.data.dnd.mto) { \n\t\t\t\t\tclearTimeout(this.data.dnd.mto);\n\t\t\t\t\tthis.data.dnd.mto = false;\n\t\t\t\t}\n\t\t\t\tvar s = this._get_settings().dnd;\n\t\t\t\tthis.data.dnd.prepared = false;\n\t\t\t\tr = this._get_node(obj);\n\t\t\t\tif(s.check_timeout) { \n\t\t\t\t\t// do the calculations after a minimal timeout (users tend to drag quickly to the desired location)\n\t\t\t\t\tif(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }\n\t\t\t\t\tthis.data.dnd.to1 = setTimeout($.proxy(this.dnd_prepare, this), s.check_timeout); \n\t\t\t\t}\n\t\t\t\telse { \n\t\t\t\t\tthis.dnd_prepare(); \n\t\t\t\t}\n\t\t\t\tif(s.open_timeout) { \n\t\t\t\t\tif(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }\n\t\t\t\t\tif(r && r.length && r.hasClass(\"jstree-closed\")) { \n\t\t\t\t\t\t// if the node is closed - open it, then recalculate\n\t\t\t\t\t\tthis.data.dnd.to2 = setTimeout($.proxy(this.dnd_open, this), s.open_timeout);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(r && r.length && r.hasClass(\"jstree-closed\")) { \n\t\t\t\t\t\tthis.dnd_open();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdnd_leave : function (e) {\n\t\t\t\tthis.data.dnd.after\t\t= false;\n\t\t\t\tthis.data.dnd.before\t= false;\n\t\t\t\tthis.data.dnd.inside\t= false;\n\t\t\t\t$.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n\t\t\t\tm.hide();\n\t\t\t\tif(ml) { ml.hide(); }\n\t\t\t\tif(r && r[0] === e.target.parentNode) {\n\t\t\t\t\tif(this.data.dnd.to1) {\n\t\t\t\t\t\tclearTimeout(this.data.dnd.to1);\n\t\t\t\t\t\tthis.data.dnd.to1 = false;\n\t\t\t\t\t}\n\t\t\t\t\tif(this.data.dnd.to2) {\n\t\t\t\t\t\tclearTimeout(this.data.dnd.to2);\n\t\t\t\t\t\tthis.data.dnd.to2 = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tstart_drag : function (obj, e) {\n\t\t\t\to = this._get_node(obj);\n\t\t\t\tif(this.data.ui && this.is_selected(o)) { o = this._get_node(null, true); }\n\t\t\t\tvar dt = o.length > 1 ? this._get_string(\"multiple_selection\") : this.get_text(o),\n\t\t\t\t\tcnt = this.get_container();\n\t\t\t\tif(!this._get_settings().core.html_titles) { dt = dt.replace(/</ig,\"&lt;\").replace(/>/ig,\"&gt;\"); }\n\t\t\t\t$.vakata.dnd.drag_start(e, { jstree : true, obj : o }, \"<ins class='jstree-icon'></ins>\" + dt );\n\t\t\t\tif(this.data.themes) { \n\t\t\t\t\tif(m) { m.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n\t\t\t\t\tif(ml) { ml.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n\t\t\t\t\t$.vakata.dnd.helper.attr(\"class\", \"jstree-dnd-helper jstree-\" + this.data.themes.theme); \n\t\t\t\t}\n\t\t\t\tthis.data.dnd.cof = cnt.offset();\n\t\t\t\tthis.data.dnd.cw = parseInt(cnt.width(),10);\n\t\t\t\tthis.data.dnd.ch = parseInt(cnt.height(),10);\n\t\t\t\tthis.data.dnd.active = true;\n\t\t\t}\n\t\t}\n\t});\n\t$(function() {\n\t\tvar css_string = '' + \n\t\t\t'#vakata-dragged ins { display:block; text-decoration:none; width:16px; height:16px; margin:0 0 0 0; padding:0; position:absolute; top:4px; left:4px; ' + \n\t\t\t' -moz-border-radius:4px; border-radius:4px; -webkit-border-radius:4px; ' +\n\t\t\t'} ' + \n\t\t\t'#vakata-dragged .jstree-ok { background:green; } ' + \n\t\t\t'#vakata-dragged .jstree-invalid { background:red; } ' + \n\t\t\t'#jstree-marker { padding:0; margin:0; font-size:12px; overflow:hidden; height:12px; width:8px; position:absolute; top:-30px; z-index:10001; background-repeat:no-repeat; display:none; background-color:transparent; text-shadow:1px 1px 1px white; color:black; line-height:10px; } ' + \n\t\t\t'#jstree-marker-line { padding:0; margin:0; line-height:0%; font-size:1px; overflow:hidden; height:1px; width:100px; position:absolute; top:-30px; z-index:10000; background-repeat:no-repeat; display:none; background-color:#456c43; ' + \n\t\t\t' cursor:pointer; border:1px solid #eeeeee; border-left:0; -moz-box-shadow: 0px 0px 2px #666; -webkit-box-shadow: 0px 0px 2px #666; box-shadow: 0px 0px 2px #666; ' + \n\t\t\t' -moz-border-radius:1px; border-radius:1px; -webkit-border-radius:1px; ' +\n\t\t\t'}' + \n\t\t\t'';\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n\t\tm = $(\"<div />\").attr({ id : \"jstree-marker\" }).hide().html(\"&raquo;\")\n\t\t\t.bind(\"mouseleave mouseenter\", function (e) { \n\t\t\t\tm.hide();\n\t\t\t\tml.hide();\n\t\t\t\te.preventDefault(); \n\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\treturn false; \n\t\t\t})\n\t\t\t.appendTo(\"body\");\n\t\tml = $(\"<div />\").attr({ id : \"jstree-marker-line\" }).hide()\n\t\t\t.bind(\"mouseup\", function (e) { \n\t\t\t\tif(r && r.length) { \n\t\t\t\t\tr.children(\"a\").trigger(e); \n\t\t\t\t\te.preventDefault(); \n\t\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\t\treturn false; \n\t\t\t\t} \n\t\t\t})\n\t\t\t.bind(\"mouseleave\", function (e) { \n\t\t\t\tvar rt = $(e.relatedTarget);\n\t\t\t\tif(rt.is(\".jstree\") || rt.closest(\".jstree\").length === 0) {\n\t\t\t\t\tif(r && r.length) { \n\t\t\t\t\t\tr.children(\"a\").trigger(e); \n\t\t\t\t\t\tm.hide();\n\t\t\t\t\t\tml.hide();\n\t\t\t\t\t\te.preventDefault(); \n\t\t\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\t\t\treturn false; \n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\t.appendTo(\"body\");\n\t\t$(document).bind(\"drag_start.vakata\", function (e, data) {\n\t\t\tif(data.data.jstree) { m.show(); if(ml) { ml.show(); } }\n\t\t});\n\t\t$(document).bind(\"drag_stop.vakata\", function (e, data) {\n\t\t\tif(data.data.jstree) { m.hide(); if(ml) { ml.hide(); } }\n\t\t});\n\t});\n})(jQuery);\n//*/\n\n/*\n * jsTree checkbox plugin\n * Inserts checkboxes in front of every node\n * Depends on the ui plugin\n * DOES NOT WORK NICELY WITH MULTITREE DRAG'N'DROP\n */\n(function ($) {\n\t$.jstree.plugin(\"checkbox\", {\n\t\t__init : function () {\n\t\t\tthis.data.checkbox.noui = this._get_settings().checkbox.override_ui;\n\t\t\tif(this.data.ui && this.data.checkbox.noui) {\n\t\t\t\tthis.select_node = this.deselect_node = this.deselect_all = $.noop;\n\t\t\t\tthis.get_selected = this.get_checked;\n\t\t\t}\n\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"open_node.jstree create_node.jstree clean_node.jstree refresh.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tthis._prepare_checkboxes(data.rslt.obj);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"loaded.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tthis._prepare_checkboxes();\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate( (this.data.ui && this.data.checkbox.noui ? \"a\" : \"ins.jstree-checkbox\") , \"click.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tif(this._get_node(e.target).hasClass(\"jstree-checked\")) { this.uncheck_node(e.target); }\n\t\t\t\t\t\telse { this.check_node(e.target); }\n\t\t\t\t\t\tif(this.data.ui && this.data.checkbox.noui) {\n\t\t\t\t\t\t\tthis.save_selected();\n\t\t\t\t\t\t\tif(this.data.cookies) { this.save_cookie(\"select_node\"); }\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : {\n\t\t\toverride_ui : false,\n\t\t\ttwo_state : false,\n\t\t\treal_checkboxes : false,\n\t\t\tchecked_parent_open : true,\n\t\t\treal_checkboxes_names : function (n) { return [ (\"check_\" + (n[0].id || Math.ceil(Math.random() * 10000))) , 1]; }\n\t\t},\n\t\t__destroy : function () {\n\t\t\tthis.get_container()\n\t\t\t\t.find(\"input.jstree-real-checkbox\").removeClass(\"jstree-real-checkbox\").end()\n\t\t\t\t.find(\"ins.jstree-checkbox\").remove();\n\t\t},\n\t\t_fn : {\n\t\t\t_checkbox_notify : function (n, data) {\n\t\t\t\tif(data.checked) {\n\t\t\t\t\tthis.check_node(n, false);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_prepare_checkboxes : function (obj) {\n\t\t\t\tobj = !obj || obj == -1 ? this.get_container().find(\"> ul > li\") : this._get_node(obj);\n\t\t\t\tif(obj === false) { return; } // added for removing root nodes\n\t\t\t\tvar c, _this = this, t, ts = this._get_settings().checkbox.two_state, rc = this._get_settings().checkbox.real_checkboxes, rcn = this._get_settings().checkbox.real_checkboxes_names;\n\t\t\t\tobj.each(function () {\n\t\t\t\t\tt = $(this);\n\t\t\t\t\tc = t.is(\"li\") && (t.hasClass(\"jstree-checked\") || (rc && t.children(\":checked\").length)) ? \"jstree-checked\" : \"jstree-unchecked\";\n\t\t\t\t\tt.find(\"li\").andSelf().each(function () {\n\t\t\t\t\t\tvar $t = $(this), nm;\n\t\t\t\t\t\t$t.children(\"a\" + (_this.data.languages ? \"\" : \":eq(0)\") ).not(\":has(.jstree-checkbox)\").prepend(\"<ins class='jstree-checkbox'>&#160;</ins>\").parent().not(\".jstree-checked, .jstree-unchecked\").addClass( ts ? \"jstree-unchecked\" : c );\n\t\t\t\t\t\tif(rc) {\n\t\t\t\t\t\t\tif(!$t.children(\":checkbox\").length) {\n\t\t\t\t\t\t\t\tnm = rcn.call(_this, $t);\n\t\t\t\t\t\t\t\t$t.prepend(\"<input type='checkbox' class='jstree-real-checkbox' id='\" + nm[0] + \"' name='\" + nm[0] + \"' value='\" + nm[1] + \"' />\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t$t.children(\":checkbox\").addClass(\"jstree-real-checkbox\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!ts) {\n\t\t\t\t\t\t\tif(c === \"jstree-checked\" || $t.hasClass(\"jstree-checked\") || $t.children(':checked').length) {\n\t\t\t\t\t\t\t\t$t.find(\"li\").andSelf().addClass(\"jstree-checked\").children(\":checkbox\").prop(\"checked\", true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif($t.hasClass(\"jstree-checked\") || $t.children(':checked').length) {\n\t\t\t\t\t\t\t\t$t.addClass(\"jstree-checked\").children(\":checkbox\").prop(\"checked\", true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tif(!ts) {\n\t\t\t\t\tobj.find(\".jstree-checked\").parent().parent().each(function () { _this._repair_state(this); }); \n\t\t\t\t}\n\t\t\t},\n\t\t\tchange_state : function (obj, state) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar coll = false, rc = this._get_settings().checkbox.real_checkboxes;\n\t\t\t\tif(!obj || obj === -1) { return false; }\n\t\t\t\tstate = (state === false || state === true) ? state : obj.hasClass(\"jstree-checked\");\n\t\t\t\tif(this._get_settings().checkbox.two_state) {\n\t\t\t\t\tif(state) { \n\t\t\t\t\t\tobj.removeClass(\"jstree-checked\").addClass(\"jstree-unchecked\"); \n\t\t\t\t\t\tif(rc) { obj.children(\":checkbox\").prop(\"checked\", false); }\n\t\t\t\t\t}\n\t\t\t\t\telse { \n\t\t\t\t\t\tobj.removeClass(\"jstree-unchecked\").addClass(\"jstree-checked\"); \n\t\t\t\t\t\tif(rc) { obj.children(\":checkbox\").prop(\"checked\", true); }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(state) { \n\t\t\t\t\t\tcoll = obj.find(\"li\").andSelf();\n\t\t\t\t\t\tif(!coll.filter(\".jstree-checked, .jstree-undetermined\").length) { return false; }\n\t\t\t\t\t\tcoll.removeClass(\"jstree-checked jstree-undetermined\").addClass(\"jstree-unchecked\"); \n\t\t\t\t\t\tif(rc) { coll.children(\":checkbox\").prop(\"checked\", false); }\n\t\t\t\t\t}\n\t\t\t\t\telse { \n\t\t\t\t\t\tcoll = obj.find(\"li\").andSelf();\n\t\t\t\t\t\tif(!coll.filter(\".jstree-unchecked, .jstree-undetermined\").length) { return false; }\n\t\t\t\t\t\tcoll.removeClass(\"jstree-unchecked jstree-undetermined\").addClass(\"jstree-checked\"); \n\t\t\t\t\t\tif(rc) { coll.children(\":checkbox\").prop(\"checked\", true); }\n\t\t\t\t\t\tif(this.data.ui) { this.data.ui.last_selected = obj; }\n\t\t\t\t\t\tthis.data.checkbox.last_selected = obj;\n\t\t\t\t\t}\n\t\t\t\t\tobj.parentsUntil(\".jstree\", \"li\").each(function () {\n\t\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\t\tif(state) {\n\t\t\t\t\t\t\tif($this.children(\"ul\").children(\"li.jstree-checked, li.jstree-undetermined\").length) {\n\t\t\t\t\t\t\t\t$this.parentsUntil(\".jstree\", \"li\").andSelf().removeClass(\"jstree-checked jstree-unchecked\").addClass(\"jstree-undetermined\");\n\t\t\t\t\t\t\t\tif(rc) { $this.parentsUntil(\".jstree\", \"li\").andSelf().children(\":checkbox\").prop(\"checked\", false); }\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t$this.removeClass(\"jstree-checked jstree-undetermined\").addClass(\"jstree-unchecked\");\n\t\t\t\t\t\t\t\tif(rc) { $this.children(\":checkbox\").prop(\"checked\", false); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif($this.children(\"ul\").children(\"li.jstree-unchecked, li.jstree-undetermined\").length) {\n\t\t\t\t\t\t\t\t$this.parentsUntil(\".jstree\", \"li\").andSelf().removeClass(\"jstree-checked jstree-unchecked\").addClass(\"jstree-undetermined\");\n\t\t\t\t\t\t\t\tif(rc) { $this.parentsUntil(\".jstree\", \"li\").andSelf().children(\":checkbox\").prop(\"checked\", false); }\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t$this.removeClass(\"jstree-unchecked jstree-undetermined\").addClass(\"jstree-checked\");\n\t\t\t\t\t\t\t\tif(rc) { $this.children(\":checkbox\").prop(\"checked\", true); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(this.data.ui && this.data.checkbox.noui) { this.data.ui.selected = this.get_checked(); }\n\t\t\t\tthis.__callback(obj);\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tcheck_node : function (obj) {\n\t\t\t\tif(this.change_state(obj, false)) { \n\t\t\t\t\tobj = this._get_node(obj);\n\t\t\t\t\tif(this._get_settings().checkbox.checked_parent_open) {\n\t\t\t\t\t\tvar t = this;\n\t\t\t\t\t\tobj.parents(\".jstree-closed\").each(function () { t.open_node(this, false, true); });\n\t\t\t\t\t}\n\t\t\t\t\tthis.__callback({ \"obj\" : obj }); \n\t\t\t\t}\n\t\t\t},\n\t\t\tuncheck_node : function (obj) {\n\t\t\t\tif(this.change_state(obj, true)) { this.__callback({ \"obj\" : this._get_node(obj) }); }\n\t\t\t},\n\t\t\tcheck_all : function () {\n\t\t\t\tvar _this = this, \n\t\t\t\t\tcoll = this._get_settings().checkbox.two_state ? this.get_container_ul().find(\"li\") : this.get_container_ul().children(\"li\");\n\t\t\t\tcoll.each(function () {\n\t\t\t\t\t_this.change_state(this, false);\n\t\t\t\t});\n\t\t\t\tthis.__callback();\n\t\t\t},\n\t\t\tuncheck_all : function () {\n\t\t\t\tvar _this = this,\n\t\t\t\t\tcoll = this._get_settings().checkbox.two_state ? this.get_container_ul().find(\"li\") : this.get_container_ul().children(\"li\");\n\t\t\t\tcoll.each(function () {\n\t\t\t\t\t_this.change_state(this, true);\n\t\t\t\t});\n\t\t\t\tthis.__callback();\n\t\t\t},\n\n\t\t\tis_checked : function(obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\treturn obj.length ? obj.is(\".jstree-checked\") : false;\n\t\t\t},\n\t\t\tget_checked : function (obj, get_all) {\n\t\t\t\tobj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);\n\t\t\t\treturn get_all || this._get_settings().checkbox.two_state ? obj.find(\".jstree-checked\") : obj.find(\"> ul > .jstree-checked, .jstree-undetermined > ul > .jstree-checked\");\n\t\t\t},\n\t\t\tget_unchecked : function (obj, get_all) { \n\t\t\t\tobj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);\n\t\t\t\treturn get_all || this._get_settings().checkbox.two_state ? obj.find(\".jstree-unchecked\") : obj.find(\"> ul > .jstree-unchecked, .jstree-undetermined > ul > .jstree-unchecked\");\n\t\t\t},\n\n\t\t\tshow_checkboxes : function () { this.get_container().children(\"ul\").removeClass(\"jstree-no-checkboxes\"); },\n\t\t\thide_checkboxes : function () { this.get_container().children(\"ul\").addClass(\"jstree-no-checkboxes\"); },\n\n\t\t\t_repair_state : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj.length) { return; }\n\t\t\t\tif(this._get_settings().checkbox.two_state) {\n\t\t\t\t\tobj.find('li').andSelf().not('.jstree-checked').removeClass('jstree-undetermined').addClass('jstree-unchecked').children(':checkbox').prop('checked', true);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvar rc = this._get_settings().checkbox.real_checkboxes,\n\t\t\t\t\ta = obj.find(\"> ul > .jstree-checked\").length,\n\t\t\t\t\tb = obj.find(\"> ul > .jstree-undetermined\").length,\n\t\t\t\t\tc = obj.find(\"> ul > li\").length;\n\t\t\t\tif(c === 0) { if(obj.hasClass(\"jstree-undetermined\")) { this.change_state(obj, false); } }\n\t\t\t\telse if(a === 0 && b === 0) { this.change_state(obj, true); }\n\t\t\t\telse if(a === c) { this.change_state(obj, false); }\n\t\t\t\telse { \n\t\t\t\t\tobj.parentsUntil(\".jstree\",\"li\").andSelf().removeClass(\"jstree-checked jstree-unchecked\").addClass(\"jstree-undetermined\");\n\t\t\t\t\tif(rc) { obj.parentsUntil(\".jstree\", \"li\").andSelf().children(\":checkbox\").prop(\"checked\", false); }\n\t\t\t\t}\n\t\t\t},\n\t\t\treselect : function () {\n\t\t\t\tif(this.data.ui && this.data.checkbox.noui) { \n\t\t\t\t\tvar _this = this,\n\t\t\t\t\t\ts = this.data.ui.to_select;\n\t\t\t\t\ts = $.map($.makeArray(s), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n\t\t\t\t\tthis.deselect_all();\n\t\t\t\t\t$.each(s, function (i, val) { _this.check_node(val); });\n\t\t\t\t\tthis.__callback();\n\t\t\t\t}\n\t\t\t\telse { \n\t\t\t\t\tthis.__call_old(); \n\t\t\t\t}\n\t\t\t},\n\t\t\tsave_loaded : function () {\n\t\t\t\tvar _this = this;\n\t\t\t\tthis.data.core.to_load = [];\n\t\t\t\tthis.get_container_ul().find(\"li.jstree-closed.jstree-undetermined\").each(function () {\n\t\t\t\t\tif(this.id) { _this.data.core.to_load.push(\"#\" + this.id); }\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\t$(function() {\n\t\tvar css_string = '.jstree .jstree-real-checkbox { display:none; } ';\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree XML plugin\n * The XML data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.\n */\n(function ($) {\n\t$.vakata.xslt = function (xml, xsl, callback) {\n\t\tvar rs = \"\", xm, xs, processor, support;\n\t\t// TODO: IE9 no XSLTProcessor, no document.recalc\n\t\tif(document.recalc) {\n\t\t\txm = document.createElement('xml');\n\t\t\txs = document.createElement('xml');\n\t\t\txm.innerHTML = xml;\n\t\t\txs.innerHTML = xsl;\n\t\t\t$(\"body\").append(xm).append(xs);\n\t\t\tsetTimeout( (function (xm, xs, callback) {\n\t\t\t\treturn function () {\n\t\t\t\t\tcallback.call(null, xm.transformNode(xs.XMLDocument));\n\t\t\t\t\tsetTimeout( (function (xm, xs) { return function () { $(xm).remove(); $(xs).remove(); }; })(xm, xs), 200);\n\t\t\t\t};\n\t\t\t})(xm, xs, callback), 100);\n\t\t\treturn true;\n\t\t}\n\t\tif(typeof window.DOMParser !== \"undefined\" && typeof window.XMLHttpRequest !== \"undefined\" && typeof window.XSLTProcessor === \"undefined\") {\n\t\t\txml = new DOMParser().parseFromString(xml, \"text/xml\");\n\t\t\txsl = new DOMParser().parseFromString(xsl, \"text/xml\");\n\t\t\t// alert(xml.transformNode());\n\t\t\t// callback.call(null, new XMLSerializer().serializeToString(rs));\n\t\t\t\n\t\t}\n\t\tif(typeof window.DOMParser !== \"undefined\" && typeof window.XMLHttpRequest !== \"undefined\" && typeof window.XSLTProcessor !== \"undefined\") {\n\t\t\tprocessor = new XSLTProcessor();\n\t\t\tsupport = $.isFunction(processor.transformDocument) ? (typeof window.XMLSerializer !== \"undefined\") : true;\n\t\t\tif(!support) { return false; }\n\t\t\txml = new DOMParser().parseFromString(xml, \"text/xml\");\n\t\t\txsl = new DOMParser().parseFromString(xsl, \"text/xml\");\n\t\t\tif($.isFunction(processor.transformDocument)) {\n\t\t\t\trs = document.implementation.createDocument(\"\", \"\", null);\n\t\t\t\tprocessor.transformDocument(xml, xsl, rs, null);\n\t\t\t\tcallback.call(null, new XMLSerializer().serializeToString(rs));\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tprocessor.importStylesheet(xsl);\n\t\t\t\trs = processor.transformToFragment(xml, document);\n\t\t\t\tcallback.call(null, $(\"<div />\").append(rs).html());\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\tvar xsl = {\n\t\t'nest' : '<' + '?xml version=\"1.0\" encoding=\"utf-8\" ?>' + \n\t\t\t'<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >' + \n\t\t\t'<xsl:output method=\"html\" encoding=\"utf-8\" omit-xml-declaration=\"yes\" standalone=\"no\" indent=\"no\" media-type=\"text/html\" />' + \n\t\t\t'<xsl:template match=\"/\">' + \n\t\t\t'\t<xsl:call-template name=\"nodes\">' + \n\t\t\t'\t\t<xsl:with-param name=\"node\" select=\"/root\" />' + \n\t\t\t'\t</xsl:call-template>' + \n\t\t\t'</xsl:template>' + \n\t\t\t'<xsl:template name=\"nodes\">' + \n\t\t\t'\t<xsl:param name=\"node\" />' + \n\t\t\t'\t<ul>' + \n\t\t\t'\t<xsl:for-each select=\"$node/item\">' + \n\t\t\t'\t\t<xsl:variable name=\"children\" select=\"count(./item) &gt; 0\" />' + \n\t\t\t'\t\t<li>' + \n\t\t\t'\t\t\t<xsl:attribute name=\"class\">' + \n\t\t\t'\t\t\t\t<xsl:if test=\"position() = last()\">jstree-last </xsl:if>' + \n\t\t\t'\t\t\t\t<xsl:choose>' + \n\t\t\t'\t\t\t\t\t<xsl:when test=\"@state = \\'open\\'\">jstree-open </xsl:when>' + \n\t\t\t'\t\t\t\t\t<xsl:when test=\"$children or @hasChildren or @state = \\'closed\\'\">jstree-closed </xsl:when>' + \n\t\t\t'\t\t\t\t\t<xsl:otherwise>jstree-leaf </xsl:otherwise>' + \n\t\t\t'\t\t\t\t</xsl:choose>' + \n\t\t\t'\t\t\t\t<xsl:value-of select=\"@class\" />' + \n\t\t\t'\t\t\t</xsl:attribute>' + \n\t\t\t'\t\t\t<xsl:for-each select=\"@*\">' + \n\t\t\t'\t\t\t\t<xsl:if test=\"name() != \\'class\\' and name() != \\'state\\' and name() != \\'hasChildren\\'\">' + \n\t\t\t'\t\t\t\t\t<xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n\t\t\t'\t\t\t\t</xsl:if>' + \n\t\t\t'\t\t\t</xsl:for-each>' + \n\t\t\t'\t<ins class=\"jstree-icon\"><xsl:text>&#xa0;</xsl:text></ins>' + \n\t\t\t'\t\t\t<xsl:for-each select=\"content/name\">' + \n\t\t\t'\t\t\t\t<a>' + \n\t\t\t'\t\t\t\t<xsl:attribute name=\"href\">' + \n\t\t\t'\t\t\t\t\t<xsl:choose>' + \n\t\t\t'\t\t\t\t\t<xsl:when test=\"@href\"><xsl:value-of select=\"@href\" /></xsl:when>' + \n\t\t\t'\t\t\t\t\t<xsl:otherwise>#</xsl:otherwise>' + \n\t\t\t'\t\t\t\t\t</xsl:choose>' + \n\t\t\t'\t\t\t\t</xsl:attribute>' + \n\t\t\t'\t\t\t\t<xsl:attribute name=\"class\"><xsl:value-of select=\"@lang\" /> <xsl:value-of select=\"@class\" /></xsl:attribute>' + \n\t\t\t'\t\t\t\t<xsl:attribute name=\"style\"><xsl:value-of select=\"@style\" /></xsl:attribute>' + \n\t\t\t'\t\t\t\t<xsl:for-each select=\"@*\">' + \n\t\t\t'\t\t\t\t\t<xsl:if test=\"name() != \\'style\\' and name() != \\'class\\' and name() != \\'href\\'\">' + \n\t\t\t'\t\t\t\t\t\t<xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n\t\t\t'\t\t\t\t\t</xsl:if>' + \n\t\t\t'\t\t\t\t</xsl:for-each>' + \n\t\t\t'\t\t\t\t\t<ins>' + \n\t\t\t'\t\t\t\t\t\t<xsl:attribute name=\"class\">jstree-icon ' + \n\t\t\t'\t\t\t\t\t\t\t<xsl:if test=\"string-length(attribute::icon) > 0 and not(contains(@icon,\\'/\\'))\"><xsl:value-of select=\"@icon\" /></xsl:if>' + \n\t\t\t'\t\t\t\t\t\t</xsl:attribute>' + \n\t\t\t'\t\t\t\t\t\t<xsl:if test=\"string-length(attribute::icon) > 0 and contains(@icon,\\'/\\')\"><xsl:attribute name=\"style\">background:url(<xsl:value-of select=\"@icon\" />) center center no-repeat;</xsl:attribute></xsl:if>' + \n\t\t\t'\t\t\t\t\t\t<xsl:text>&#xa0;</xsl:text>' + \n\t\t\t'\t\t\t\t\t</ins>' + \n\t\t\t'\t\t\t\t\t<xsl:copy-of select=\"./child::node()\" />' + \n\t\t\t'\t\t\t\t</a>' + \n\t\t\t'\t\t\t</xsl:for-each>' + \n\t\t\t'\t\t\t<xsl:if test=\"$children or @hasChildren\"><xsl:call-template name=\"nodes\"><xsl:with-param name=\"node\" select=\"current()\" /></xsl:call-template></xsl:if>' + \n\t\t\t'\t\t</li>' + \n\t\t\t'\t</xsl:for-each>' + \n\t\t\t'\t</ul>' + \n\t\t\t'</xsl:template>' + \n\t\t\t'</xsl:stylesheet>',\n\n\t\t'flat' : '<' + '?xml version=\"1.0\" encoding=\"utf-8\" ?>' + \n\t\t\t'<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >' + \n\t\t\t'<xsl:output method=\"html\" encoding=\"utf-8\" omit-xml-declaration=\"yes\" standalone=\"no\" indent=\"no\" media-type=\"text/xml\" />' + \n\t\t\t'<xsl:template match=\"/\">' + \n\t\t\t'\t<ul>' + \n\t\t\t'\t<xsl:for-each select=\"//item[not(@parent_id) or @parent_id=0 or not(@parent_id = //item/@id)]\">' + /* the last `or` may be removed */\n\t\t\t'\t\t<xsl:call-template name=\"nodes\">' + \n\t\t\t'\t\t\t<xsl:with-param name=\"node\" select=\".\" />' + \n\t\t\t'\t\t\t<xsl:with-param name=\"is_last\" select=\"number(position() = last())\" />' + \n\t\t\t'\t\t</xsl:call-template>' + \n\t\t\t'\t</xsl:for-each>' + \n\t\t\t'\t</ul>' + \n\t\t\t'</xsl:template>' + \n\t\t\t'<xsl:template name=\"nodes\">' + \n\t\t\t'\t<xsl:param name=\"node\" />' + \n\t\t\t'\t<xsl:param name=\"is_last\" />' + \n\t\t\t'\t<xsl:variable name=\"children\" select=\"count(//item[@parent_id=$node/attribute::id]) &gt; 0\" />' + \n\t\t\t'\t<li>' + \n\t\t\t'\t<xsl:attribute name=\"class\">' + \n\t\t\t'\t\t<xsl:if test=\"$is_last = true()\">jstree-last </xsl:if>' + \n\t\t\t'\t\t<xsl:choose>' + \n\t\t\t'\t\t\t<xsl:when test=\"@state = \\'open\\'\">jstree-open </xsl:when>' + \n\t\t\t'\t\t\t<xsl:when test=\"$children or @hasChildren or @state = \\'closed\\'\">jstree-closed </xsl:when>' + \n\t\t\t'\t\t\t<xsl:otherwise>jstree-leaf </xsl:otherwise>' + \n\t\t\t'\t\t</xsl:choose>' + \n\t\t\t'\t\t<xsl:value-of select=\"@class\" />' + \n\t\t\t'\t</xsl:attribute>' + \n\t\t\t'\t<xsl:for-each select=\"@*\">' + \n\t\t\t'\t\t<xsl:if test=\"name() != \\'parent_id\\' and name() != \\'hasChildren\\' and name() != \\'class\\' and name() != \\'state\\'\">' + \n\t\t\t'\t\t<xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n\t\t\t'\t\t</xsl:if>' + \n\t\t\t'\t</xsl:for-each>' + \n\t\t\t'\t<ins class=\"jstree-icon\"><xsl:text>&#xa0;</xsl:text></ins>' + \n\t\t\t'\t<xsl:for-each select=\"content/name\">' + \n\t\t\t'\t\t<a>' + \n\t\t\t'\t\t<xsl:attribute name=\"href\">' + \n\t\t\t'\t\t\t<xsl:choose>' + \n\t\t\t'\t\t\t<xsl:when test=\"@href\"><xsl:value-of select=\"@href\" /></xsl:when>' + \n\t\t\t'\t\t\t<xsl:otherwise>#</xsl:otherwise>' + \n\t\t\t'\t\t\t</xsl:choose>' + \n\t\t\t'\t\t</xsl:attribute>' + \n\t\t\t'\t\t<xsl:attribute name=\"class\"><xsl:value-of select=\"@lang\" /> <xsl:value-of select=\"@class\" /></xsl:attribute>' + \n\t\t\t'\t\t<xsl:attribute name=\"style\"><xsl:value-of select=\"@style\" /></xsl:attribute>' + \n\t\t\t'\t\t<xsl:for-each select=\"@*\">' + \n\t\t\t'\t\t\t<xsl:if test=\"name() != \\'style\\' and name() != \\'class\\' and name() != \\'href\\'\">' + \n\t\t\t'\t\t\t\t<xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n\t\t\t'\t\t\t</xsl:if>' + \n\t\t\t'\t\t</xsl:for-each>' + \n\t\t\t'\t\t\t<ins>' + \n\t\t\t'\t\t\t\t<xsl:attribute name=\"class\">jstree-icon ' + \n\t\t\t'\t\t\t\t\t<xsl:if test=\"string-length(attribute::icon) > 0 and not(contains(@icon,\\'/\\'))\"><xsl:value-of select=\"@icon\" /></xsl:if>' + \n\t\t\t'\t\t\t\t</xsl:attribute>' + \n\t\t\t'\t\t\t\t<xsl:if test=\"string-length(attribute::icon) > 0 and contains(@icon,\\'/\\')\"><xsl:attribute name=\"style\">background:url(<xsl:value-of select=\"@icon\" />) center center no-repeat;</xsl:attribute></xsl:if>' + \n\t\t\t'\t\t\t\t<xsl:text>&#xa0;</xsl:text>' + \n\t\t\t'\t\t\t</ins>' + \n\t\t\t'\t\t\t<xsl:copy-of select=\"./child::node()\" />' + \n\t\t\t'\t\t</a>' + \n\t\t\t'\t</xsl:for-each>' + \n\t\t\t'\t<xsl:if test=\"$children\">' + \n\t\t\t'\t\t<ul>' + \n\t\t\t'\t\t<xsl:for-each select=\"//item[@parent_id=$node/attribute::id]\">' + \n\t\t\t'\t\t\t<xsl:call-template name=\"nodes\">' + \n\t\t\t'\t\t\t\t<xsl:with-param name=\"node\" select=\".\" />' + \n\t\t\t'\t\t\t\t<xsl:with-param name=\"is_last\" select=\"number(position() = last())\" />' + \n\t\t\t'\t\t\t</xsl:call-template>' + \n\t\t\t'\t\t</xsl:for-each>' + \n\t\t\t'\t\t</ul>' + \n\t\t\t'\t</xsl:if>' + \n\t\t\t'\t</li>' + \n\t\t\t'</xsl:template>' + \n\t\t\t'</xsl:stylesheet>'\n\t},\n\tescape_xml = function(string) {\n\t\treturn string\n\t\t\t.toString()\n\t\t\t.replace(/&/g, '&amp;')\n\t\t\t.replace(/</g, '&lt;')\n\t\t\t.replace(/>/g, '&gt;')\n\t\t\t.replace(/\"/g, '&quot;')\n\t\t\t.replace(/'/g, '&apos;');\n\t};\n\t$.jstree.plugin(\"xml_data\", {\n\t\tdefaults : { \n\t\t\tdata : false,\n\t\t\tajax : false,\n\t\t\txsl : \"flat\",\n\t\t\tclean_node : false,\n\t\t\tcorrect_state : true,\n\t\t\tget_skip_empty : false,\n\t\t\tget_include_preamble : true\n\t\t},\n\t\t_fn : {\n\t\t\tload_node : function (obj, s_call, e_call) { var _this = this; this.load_node_xml(obj, function () { _this.__callback({ \"obj\" : _this._get_node(obj) }); s_call.call(this); }, e_call); },\n\t\t\t_is_loaded : function (obj) { \n\t\t\t\tvar s = this._get_settings().xml_data;\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\treturn obj == -1 || !obj || (!s.ajax && !$.isFunction(s.data)) || obj.is(\".jstree-open, .jstree-leaf\") || obj.children(\"ul\").children(\"li\").size() > 0;\n\t\t\t},\n\t\t\tload_node_xml : function (obj, s_call, e_call) {\n\t\t\t\tvar s = this.get_settings().xml_data,\n\t\t\t\t\terror_func = function () {},\n\t\t\t\t\tsuccess_func = function () {};\n\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj && obj !== -1) {\n\t\t\t\t\tif(obj.data(\"jstree_is_loading\")) { return; }\n\t\t\t\t\telse { obj.data(\"jstree_is_loading\",true); }\n\t\t\t\t}\n\t\t\t\tswitch(!0) {\n\t\t\t\t\tcase (!s.data && !s.ajax): throw \"Neither data nor ajax settings supplied.\";\n\t\t\t\t\tcase ($.isFunction(s.data)):\n\t\t\t\t\t\ts.data.call(this, obj, $.proxy(function (d) {\n\t\t\t\t\t\t\tthis.parse_xml(d, $.proxy(function (d) {\n\t\t\t\t\t\t\t\tif(d) {\n\t\t\t\t\t\t\t\t\td = d.replace(/ ?xmlns=\"[^\"]*\"/ig, \"\");\n\t\t\t\t\t\t\t\t\tif(d.length > 10) {\n\t\t\t\t\t\t\t\t\t\td = $(d);\n\t\t\t\t\t\t\t\t\t\tif(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n\t\t\t\t\t\t\t\t\t\telse { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d); obj.removeData(\"jstree_is_loading\"); }\n\t\t\t\t\t\t\t\t\t\tif(s.clean_node) { this.clean_node(obj); }\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tif(obj && obj !== -1) { \n\t\t\t\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\t\t\tthis.correct_state(obj);\n\t\t\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty();\n\t\t\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t}, this));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):\n\t\t\t\t\t\tif(!obj || obj == -1) {\n\t\t\t\t\t\t\tthis.parse_xml(s.data, $.proxy(function (d) {\n\t\t\t\t\t\t\t\tif(d) {\n\t\t\t\t\t\t\t\t\td = d.replace(/ ?xmlns=\"[^\"]*\"/ig, \"\");\n\t\t\t\t\t\t\t\t\tif(d.length > 10) {\n\t\t\t\t\t\t\t\t\t\td = $(d);\n\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty().append(d.children());\n\t\t\t\t\t\t\t\t\t\tif(s.clean_node) { this.clean_node(obj); }\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse { \n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty(); \n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):\n\t\t\t\t\t\terror_func = function (x, t, e) {\n\t\t\t\t\t\t\tvar ef = this.get_settings().xml_data.ajax.error; \n\t\t\t\t\t\t\tif(ef) { ef.call(this, x, t, e); }\n\t\t\t\t\t\t\tif(obj !== -1 && obj.length) {\n\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\tif(t === \"success\" && s.correct_state) { this.correct_state(obj); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(t === \"success\" && s.correct_state) { this.get_container().children(\"ul\").empty(); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(e_call) { e_call.call(this); }\n\t\t\t\t\t\t};\n\t\t\t\t\t\tsuccess_func = function (d, t, x) {\n\t\t\t\t\t\t\td = x.responseText;\n\t\t\t\t\t\t\tvar sf = this.get_settings().xml_data.ajax.success; \n\t\t\t\t\t\t\tif(sf) { d = sf.call(this,d,t,x) || d; }\n\t\t\t\t\t\t\tif(d === \"\" || (d && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") === \"\")) {\n\t\t\t\t\t\t\t\treturn error_func.call(this, x, t, \"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.parse_xml(d, $.proxy(function (d) {\n\t\t\t\t\t\t\t\tif(d) {\n\t\t\t\t\t\t\t\t\td = d.replace(/ ?xmlns=\"[^\"]*\"/ig, \"\");\n\t\t\t\t\t\t\t\t\tif(d.length > 10) {\n\t\t\t\t\t\t\t\t\t\td = $(d);\n\t\t\t\t\t\t\t\t\t\tif(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n\t\t\t\t\t\t\t\t\t\telse { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d); obj.removeData(\"jstree_is_loading\"); }\n\t\t\t\t\t\t\t\t\t\tif(s.clean_node) { this.clean_node(obj); }\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tif(obj && obj !== -1) { \n\t\t\t\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\t\t\tthis.correct_state(obj);\n\t\t\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty();\n\t\t\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, this));\n\t\t\t\t\t\t};\n\t\t\t\t\t\ts.ajax.context = this;\n\t\t\t\t\t\ts.ajax.error = error_func;\n\t\t\t\t\t\ts.ajax.success = success_func;\n\t\t\t\t\t\tif(!s.ajax.dataType) { s.ajax.dataType = \"xml\"; }\n\t\t\t\t\t\tif($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }\n\t\t\t\t\t\tif($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }\n\t\t\t\t\t\t$.ajax(s.ajax);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tparse_xml : function (xml, callback) {\n\t\t\t\tvar s = this._get_settings().xml_data;\n\t\t\t\t$.vakata.xslt(xml, xsl[s.xsl], callback);\n\t\t\t},\n\t\t\tget_xml : function (tp, obj, li_attr, a_attr, is_callback) {\n\t\t\t\tvar result = \"\", \n\t\t\t\t\ts = this._get_settings(), \n\t\t\t\t\t_this = this,\n\t\t\t\t\ttmp1, tmp2, li, a, lang;\n\t\t\t\tif(!tp) { tp = \"flat\"; }\n\t\t\t\tif(!is_callback) { is_callback = 0; }\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(!obj || obj === -1) { obj = this.get_container().find(\"> ul > li\"); }\n\t\t\t\tli_attr = $.isArray(li_attr) ? li_attr : [ \"id\", \"class\" ];\n\t\t\t\tif(!is_callback && this.data.types && $.inArray(s.types.type_attr, li_attr) === -1) { li_attr.push(s.types.type_attr); }\n\n\t\t\t\ta_attr = $.isArray(a_attr) ? a_attr : [ ];\n\n\t\t\t\tif(!is_callback) { \n\t\t\t\t\tif(s.xml_data.get_include_preamble) { \n\t\t\t\t\t\tresult += '<' + '?xml version=\"1.0\" encoding=\"UTF-8\"?' + '>'; \n\t\t\t\t\t}\n\t\t\t\t\tresult += \"<root>\"; \n\t\t\t\t}\n\t\t\t\tobj.each(function () {\n\t\t\t\t\tresult += \"<item\";\n\t\t\t\t\tli = $(this);\n\t\t\t\t\t$.each(li_attr, function (i, v) { \n\t\t\t\t\t\tvar t = li.attr(v);\n\t\t\t\t\t\tif(!s.xml_data.get_skip_empty || typeof t !== \"undefined\") {\n\t\t\t\t\t\t\tresult += \" \" + v + \"=\\\"\" + escape_xml((\" \" + (t || \"\")).replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\")) + \"\\\"\"; \n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif(li.hasClass(\"jstree-open\")) { result += \" state=\\\"open\\\"\"; }\n\t\t\t\t\tif(li.hasClass(\"jstree-closed\")) { result += \" state=\\\"closed\\\"\"; }\n\t\t\t\t\tif(tp === \"flat\") { result += \" parent_id=\\\"\" + escape_xml(is_callback) + \"\\\"\"; }\n\t\t\t\t\tresult += \">\";\n\t\t\t\t\tresult += \"<content>\";\n\t\t\t\t\ta = li.children(\"a\");\n\t\t\t\t\ta.each(function () {\n\t\t\t\t\t\ttmp1 = $(this);\n\t\t\t\t\t\tlang = false;\n\t\t\t\t\t\tresult += \"<name\";\n\t\t\t\t\t\tif($.inArray(\"languages\", s.plugins) !== -1) {\n\t\t\t\t\t\t\t$.each(s.languages, function (k, z) {\n\t\t\t\t\t\t\t\tif(tmp1.hasClass(z)) { result += \" lang=\\\"\" + escape_xml(z) + \"\\\"\"; lang = z; return false; }\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(a_attr.length) { \n\t\t\t\t\t\t\t$.each(a_attr, function (k, z) {\n\t\t\t\t\t\t\t\tvar t = tmp1.attr(z);\n\t\t\t\t\t\t\t\tif(!s.xml_data.get_skip_empty || typeof t !== \"undefined\") {\n\t\t\t\t\t\t\t\t\tresult += \" \" + z + \"=\\\"\" + escape_xml((\" \" + t || \"\").replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\")) + \"\\\"\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(tmp1.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\\s+$/ig,\"\").length) {\n\t\t\t\t\t\t\tresult += ' icon=\"' + escape_xml(tmp1.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\")) + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(tmp1.children(\"ins\").get(0).style.backgroundImage.length) {\n\t\t\t\t\t\t\tresult += ' icon=\"' + escape_xml(tmp1.children(\"ins\").get(0).style.backgroundImage.replace(\"url(\",\"\").replace(\")\",\"\").replace(/'/ig,\"\").replace(/\"/ig,\"\")) + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult += \">\";\n\t\t\t\t\t\tresult += \"<![CDATA[\" + _this.get_text(tmp1, lang) + \"]]>\";\n\t\t\t\t\t\tresult += \"</name>\";\n\t\t\t\t\t});\n\t\t\t\t\tresult += \"</content>\";\n\t\t\t\t\ttmp2 = li[0].id || true;\n\t\t\t\t\tli = li.find(\"> ul > li\");\n\t\t\t\t\tif(li.length) { tmp2 = _this.get_xml(tp, li, li_attr, a_attr, tmp2); }\n\t\t\t\t\telse { tmp2 = \"\"; }\n\t\t\t\t\tif(tp == \"nest\") { result += tmp2; }\n\t\t\t\t\tresult += \"</item>\";\n\t\t\t\t\tif(tp == \"flat\") { result += tmp2; }\n\t\t\t\t});\n\t\t\t\tif(!is_callback) { result += \"</root>\"; }\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/*\n * jsTree search plugin\n * Enables both sync and async search on the tree\n * DOES NOT WORK WITH JSON PROGRESSIVE RENDER\n */\n(function ($) {\n\t$.expr[':'].jstree_contains = function(a,i,m){\n\t\treturn (a.textContent || a.innerText || \"\").toLowerCase().indexOf(m[3].toLowerCase())>=0;\n\t};\n\t$.expr[':'].jstree_title_contains = function(a,i,m) {\n\t\treturn (a.getAttribute(\"title\") || \"\").toLowerCase().indexOf(m[3].toLowerCase())>=0;\n\t};\n\t$.jstree.plugin(\"search\", {\n\t\t__init : function () {\n\t\t\tthis.data.search.str = \"\";\n\t\t\tthis.data.search.result = $();\n\t\t\tif(this._get_settings().search.show_only_matches) {\n\t\t\t\tthis.get_container()\n\t\t\t\t\t.bind(\"search.jstree\", function (e, data) {\n\t\t\t\t\t\t$(this).children(\"ul\").find(\"li\").hide().removeClass(\"jstree-last\");\n\t\t\t\t\t\tdata.rslt.nodes.parentsUntil(\".jstree\").andSelf().show()\n\t\t\t\t\t\t\t.filter(\"ul\").each(function () { $(this).children(\"li:visible\").eq(-1).addClass(\"jstree-last\"); });\n\t\t\t\t\t})\n\t\t\t\t\t.bind(\"clear_search.jstree\", function () {\n\t\t\t\t\t\t$(this).children(\"ul\").find(\"li\").css(\"display\",\"\").end().end().jstree(\"clean_node\", -1);\n\t\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tdefaults : {\n\t\t\tajax : false,\n\t\t\tsearch_method : \"jstree_contains\", // for case insensitive - jstree_contains\n\t\t\tshow_only_matches : false\n\t\t},\n\t\t_fn : {\n\t\t\tsearch : function (str, skip_async) {\n\t\t\t\tif($.trim(str) === \"\") { this.clear_search(); return; }\n\t\t\t\tvar s = this.get_settings().search, \n\t\t\t\t\tt = this,\n\t\t\t\t\terror_func = function () { },\n\t\t\t\t\tsuccess_func = function () { };\n\t\t\t\tthis.data.search.str = str;\n\n\t\t\t\tif(!skip_async && s.ajax !== false && this.get_container_ul().find(\"li.jstree-closed:not(:has(ul)):eq(0)\").length > 0) {\n\t\t\t\t\tthis.search.supress_callback = true;\n\t\t\t\t\terror_func = function () { };\n\t\t\t\t\tsuccess_func = function (d, t, x) {\n\t\t\t\t\t\tvar sf = this.get_settings().search.ajax.success; \n\t\t\t\t\t\tif(sf) { d = sf.call(this,d,t,x) || d; }\n\t\t\t\t\t\tthis.data.search.to_open = d;\n\t\t\t\t\t\tthis._search_open();\n\t\t\t\t\t};\n\t\t\t\t\ts.ajax.context = this;\n\t\t\t\t\ts.ajax.error = error_func;\n\t\t\t\t\ts.ajax.success = success_func;\n\t\t\t\t\tif($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, str); }\n\t\t\t\t\tif($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, str); }\n\t\t\t\t\tif(!s.ajax.data) { s.ajax.data = { \"search_string\" : str }; }\n\t\t\t\t\tif(!s.ajax.dataType || /^json/.exec(s.ajax.dataType)) { s.ajax.dataType = \"json\"; }\n\t\t\t\t\t$.ajax(s.ajax);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif(this.data.search.result.length) { this.clear_search(); }\n\t\t\t\tthis.data.search.result = this.get_container().find(\"a\" + (this.data.languages ? \".\" + this.get_lang() : \"\" ) + \":\" + (s.search_method) + \"(\" + this.data.search.str + \")\");\n\t\t\t\tthis.data.search.result.addClass(\"jstree-search\").parent().parents(\".jstree-closed\").each(function () {\n\t\t\t\t\tt.open_node(this, false, true);\n\t\t\t\t});\n\t\t\t\tthis.__callback({ nodes : this.data.search.result, str : str });\n\t\t\t},\n\t\t\tclear_search : function (str) {\n\t\t\t\tthis.data.search.result.removeClass(\"jstree-search\");\n\t\t\t\tthis.__callback(this.data.search.result);\n\t\t\t\tthis.data.search.result = $();\n\t\t\t},\n\t\t\t_search_open : function (is_callback) {\n\t\t\t\tvar _this = this,\n\t\t\t\t\tdone = true,\n\t\t\t\t\tcurrent = [],\n\t\t\t\t\tremaining = [];\n\t\t\t\tif(this.data.search.to_open.length) {\n\t\t\t\t\t$.each(this.data.search.to_open, function (i, val) {\n\t\t\t\t\t\tif(val == \"#\") { return true; }\n\t\t\t\t\t\tif($(val).length && $(val).is(\".jstree-closed\")) { current.push(val); }\n\t\t\t\t\t\telse { remaining.push(val); }\n\t\t\t\t\t});\n\t\t\t\t\tif(current.length) {\n\t\t\t\t\t\tthis.data.search.to_open = remaining;\n\t\t\t\t\t\t$.each(current, function (i, val) { \n\t\t\t\t\t\t\t_this.open_node(val, function () { _this._search_open(true); }); \n\t\t\t\t\t\t});\n\t\t\t\t\t\tdone = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(done) { this.search(this.data.search.str, true); }\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree contextmenu plugin\n */\n(function ($) {\n\t$.vakata.context = {\n\t\thide_on_mouseleave : false,\n\n\t\tcnt\t\t: $(\"<div id='vakata-contextmenu' />\"),\n\t\tvis\t\t: false,\n\t\ttgt\t\t: false,\n\t\tpar\t\t: false,\n\t\tfunc\t: false,\n\t\tdata\t: false,\n\t\trtl\t\t: false,\n\t\tshow\t: function (s, t, x, y, d, p, rtl) {\n\t\t\t$.vakata.context.rtl = !!rtl;\n\t\t\tvar html = $.vakata.context.parse(s), h, w;\n\t\t\tif(!html) { return; }\n\t\t\t$.vakata.context.vis = true;\n\t\t\t$.vakata.context.tgt = t;\n\t\t\t$.vakata.context.par = p || t || null;\n\t\t\t$.vakata.context.data = d || null;\n\t\t\t$.vakata.context.cnt\n\t\t\t\t.html(html)\n\t\t\t\t.css({ \"visibility\" : \"hidden\", \"display\" : \"block\", \"left\" : 0, \"top\" : 0 });\n\n\t\t\tif($.vakata.context.hide_on_mouseleave) {\n\t\t\t\t$.vakata.context.cnt\n\t\t\t\t\t.one(\"mouseleave\", function(e) { $.vakata.context.hide(); });\n\t\t\t}\n\n\t\t\th = $.vakata.context.cnt.height();\n\t\t\tw = $.vakata.context.cnt.width();\n\t\t\tif(x + w > $(document).width()) { \n\t\t\t\tx = $(document).width() - (w + 5); \n\t\t\t\t$.vakata.context.cnt.find(\"li > ul\").addClass(\"right\"); \n\t\t\t}\n\t\t\tif(y + h > $(document).height()) { \n\t\t\t\ty = y - (h + t[0].offsetHeight); \n\t\t\t\t$.vakata.context.cnt.find(\"li > ul\").addClass(\"bottom\"); \n\t\t\t}\n\n\t\t\t$.vakata.context.cnt\n\t\t\t\t.css({ \"left\" : x, \"top\" : y })\n\t\t\t\t.find(\"li:has(ul)\")\n\t\t\t\t\t.bind(\"mouseenter\", function (e) { \n\t\t\t\t\t\tvar w = $(document).width(),\n\t\t\t\t\t\t\th = $(document).height(),\n\t\t\t\t\t\t\tul = $(this).children(\"ul\").show(); \n\t\t\t\t\t\tif(w !== $(document).width()) { ul.toggleClass(\"right\"); }\n\t\t\t\t\t\tif(h !== $(document).height()) { ul.toggleClass(\"bottom\"); }\n\t\t\t\t\t})\n\t\t\t\t\t.bind(\"mouseleave\", function (e) { \n\t\t\t\t\t\t$(this).children(\"ul\").hide(); \n\t\t\t\t\t})\n\t\t\t\t\t.end()\n\t\t\t\t.css({ \"visibility\" : \"visible\" })\n\t\t\t\t.show();\n\t\t\t$(document).triggerHandler(\"context_show.vakata\");\n\t\t},\n\t\thide\t: function () {\n\t\t\t$.vakata.context.vis = false;\n\t\t\t$.vakata.context.cnt.attr(\"class\",\"\").css({ \"visibility\" : \"hidden\" });\n\t\t\t$(document).triggerHandler(\"context_hide.vakata\");\n\t\t},\n\t\tparse\t: function (s, is_callback) {\n\t\t\tif(!s) { return false; }\n\t\t\tvar str = \"\",\n\t\t\t\ttmp = false,\n\t\t\t\twas_sep = true;\n\t\t\tif(!is_callback) { $.vakata.context.func = {}; }\n\t\t\tstr += \"<ul>\";\n\t\t\t$.each(s, function (i, val) {\n\t\t\t\tif(!val) { return true; }\n\t\t\t\t$.vakata.context.func[i] = val.action;\n\t\t\t\tif(!was_sep && val.separator_before) {\n\t\t\t\t\tstr += \"<li class='vakata-separator vakata-separator-before'></li>\";\n\t\t\t\t}\n\t\t\t\twas_sep = false;\n\t\t\t\tstr += \"<li class='\" + (val._class || \"\") + (val._disabled ? \" jstree-contextmenu-disabled \" : \"\") + \"'><ins \";\n\t\t\t\tif(val.icon && val.icon.indexOf(\"/\") === -1) { str += \" class='\" + val.icon + \"' \"; }\n\t\t\t\tif(val.icon && val.icon.indexOf(\"/\") !== -1) { str += \" style='background:url(\" + val.icon + \") center center no-repeat;' \"; }\n\t\t\t\tstr += \">&#160;</ins><a href='#' rel='\" + i + \"'>\";\n\t\t\t\tif(val.submenu) {\n\t\t\t\t\tstr += \"<span style='float:\" + ($.vakata.context.rtl ? \"left\" : \"right\") + \";'>&raquo;</span>\";\n\t\t\t\t}\n\t\t\t\tstr += val.label + \"</a>\";\n\t\t\t\tif(val.submenu) {\n\t\t\t\t\ttmp = $.vakata.context.parse(val.submenu, true);\n\t\t\t\t\tif(tmp) { str += tmp; }\n\t\t\t\t}\n\t\t\t\tstr += \"</li>\";\n\t\t\t\tif(val.separator_after) {\n\t\t\t\t\tstr += \"<li class='vakata-separator vakata-separator-after'></li>\";\n\t\t\t\t\twas_sep = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tstr = str.replace(/<li class\\='vakata-separator vakata-separator-after'\\><\\/li\\>$/,\"\");\n\t\t\tstr += \"</ul>\";\n\t\t\t$(document).triggerHandler(\"context_parse.vakata\");\n\t\t\treturn str.length > 10 ? str : false;\n\t\t},\n\t\texec\t: function (i) {\n\t\t\tif($.isFunction($.vakata.context.func[i])) {\n\t\t\t\t// if is string - eval and call it!\n\t\t\t\t$.vakata.context.func[i].call($.vakata.context.data, $.vakata.context.par);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse { return false; }\n\t\t}\n\t};\n\t$(function () {\n\t\tvar css_string = '' + \n\t\t\t'#vakata-contextmenu { display:block; visibility:hidden; left:0; top:-200px; position:absolute; margin:0; padding:0; min-width:180px; background:#ebebeb; border:1px solid silver; z-index:10000; *width:180px; } ' + \n\t\t\t'#vakata-contextmenu ul { min-width:180px; *width:180px; } ' + \n\t\t\t'#vakata-contextmenu ul, #vakata-contextmenu li { margin:0; padding:0; list-style-type:none; display:block; } ' + \n\t\t\t'#vakata-contextmenu li { line-height:20px; min-height:20px; position:relative; padding:0px; } ' + \n\t\t\t'#vakata-contextmenu li a { padding:1px 6px; line-height:17px; display:block; text-decoration:none; margin:1px 1px 0 1px; } ' + \n\t\t\t'#vakata-contextmenu li ins { float:left; width:16px; height:16px; text-decoration:none; margin-right:2px; } ' + \n\t\t\t'#vakata-contextmenu li a:hover, #vakata-contextmenu li.vakata-hover > a { background:gray; color:white; } ' + \n\t\t\t'#vakata-contextmenu li ul { display:none; position:absolute; top:-2px; left:100%; background:#ebebeb; border:1px solid gray; } ' + \n\t\t\t'#vakata-contextmenu .right { right:100%; left:auto; } ' + \n\t\t\t'#vakata-contextmenu .bottom { bottom:-1px; top:auto; } ' + \n\t\t\t'#vakata-contextmenu li.vakata-separator { min-height:0; height:1px; line-height:1px; font-size:1px; overflow:hidden; margin:0 2px; background:silver; /* border-top:1px solid #fefefe; */ padding:0; } ';\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"vakata\" });\n\t\t$.vakata.context.cnt\n\t\t\t.delegate(\"a\",\"click\", function (e) { e.preventDefault(); })\n\t\t\t.delegate(\"a\",\"mouseup\", function (e) {\n\t\t\t\tif(!$(this).parent().hasClass(\"jstree-contextmenu-disabled\") && $.vakata.context.exec($(this).attr(\"rel\"))) {\n\t\t\t\t\t$.vakata.context.hide();\n\t\t\t\t}\n\t\t\t\telse { $(this).blur(); }\n\t\t\t})\n\t\t\t.delegate(\"a\",\"mouseover\", function () {\n\t\t\t\t$.vakata.context.cnt.find(\".vakata-hover\").removeClass(\"vakata-hover\");\n\t\t\t})\n\t\t\t.appendTo(\"body\");\n\t\t$(document).bind(\"mousedown\", function (e) { if($.vakata.context.vis && !$.contains($.vakata.context.cnt[0], e.target)) { $.vakata.context.hide(); } });\n\t\tif(typeof $.hotkeys !== \"undefined\") {\n\t\t\t$(document)\n\t\t\t\t.bind(\"keydown\", \"up\", function (e) { \n\t\t\t\t\tif($.vakata.context.vis) { \n\t\t\t\t\t\tvar o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\".vakata-hover\").removeClass(\"vakata-hover\").prevAll(\"li:not(.vakata-separator)\").first();\n\t\t\t\t\t\tif(!o.length) { o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\"li:not(.vakata-separator)\").last(); }\n\t\t\t\t\t\to.addClass(\"vakata-hover\");\n\t\t\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t} \n\t\t\t\t})\n\t\t\t\t.bind(\"keydown\", \"down\", function (e) { \n\t\t\t\t\tif($.vakata.context.vis) { \n\t\t\t\t\t\tvar o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\".vakata-hover\").removeClass(\"vakata-hover\").nextAll(\"li:not(.vakata-separator)\").first();\n\t\t\t\t\t\tif(!o.length) { o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\"li:not(.vakata-separator)\").first(); }\n\t\t\t\t\t\to.addClass(\"vakata-hover\");\n\t\t\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t} \n\t\t\t\t})\n\t\t\t\t.bind(\"keydown\", \"right\", function (e) { \n\t\t\t\t\tif($.vakata.context.vis) { \n\t\t\t\t\t\t$.vakata.context.cnt.find(\".vakata-hover\").children(\"ul\").show().children(\"li:not(.vakata-separator)\").removeClass(\"vakata-hover\").first().addClass(\"vakata-hover\");\n\t\t\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t} \n\t\t\t\t})\n\t\t\t\t.bind(\"keydown\", \"left\", function (e) { \n\t\t\t\t\tif($.vakata.context.vis) { \n\t\t\t\t\t\t$.vakata.context.cnt.find(\".vakata-hover\").children(\"ul\").hide().children(\".vakata-separator\").removeClass(\"vakata-hover\");\n\t\t\t\t\t\te.stopImmediatePropagation(); \n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t} \n\t\t\t\t})\n\t\t\t\t.bind(\"keydown\", \"esc\", function (e) { \n\t\t\t\t\t$.vakata.context.hide(); \n\t\t\t\t\te.preventDefault();\n\t\t\t\t})\n\t\t\t\t.bind(\"keydown\", \"space\", function (e) { \n\t\t\t\t\t$.vakata.context.cnt.find(\".vakata-hover\").last().children(\"a\").click();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t});\n\t\t}\n\t});\n\n\t$.jstree.plugin(\"contextmenu\", {\n\t\t__init : function () {\n\t\t\tthis.get_container()\n\t\t\t\t.delegate(\"a\", \"contextmenu.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tif(!$(e.currentTarget).hasClass(\"jstree-loading\")) {\n\t\t\t\t\t\t\tthis.show_contextmenu(e.currentTarget, e.pageX, e.pageY);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"a\", \"click.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tif(this.data.contextmenu) {\n\t\t\t\t\t\t\t$.vakata.context.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"destroy.jstree\", $.proxy(function () {\n\t\t\t\t\t\t// TODO: move this to descruct method\n\t\t\t\t\t\tif(this.data.contextmenu) {\n\t\t\t\t\t\t\t$.vakata.context.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\t\t\t$(document).bind(\"context_hide.vakata\", $.proxy(function () { this.data.contextmenu = false; }, this));\n\t\t},\n\t\tdefaults : { \n\t\t\tselect_node : false, // requires UI plugin\n\t\t\tshow_at_node : true,\n\t\t\titems : { // Could be a function that should return an object like this one\n\t\t\t\t\"create\" : {\n\t\t\t\t\t\"separator_before\"\t: false,\n\t\t\t\t\t\"separator_after\"\t: true,\n\t\t\t\t\t\"label\"\t\t\t\t: \"Create\",\n\t\t\t\t\t\"action\"\t\t\t: function (obj) { this.create(obj); }\n\t\t\t\t},\n\t\t\t\t\"rename\" : {\n\t\t\t\t\t\"separator_before\"\t: false,\n\t\t\t\t\t\"separator_after\"\t: false,\n\t\t\t\t\t\"label\"\t\t\t\t: \"Rename\",\n\t\t\t\t\t\"action\"\t\t\t: function (obj) { this.rename(obj); }\n\t\t\t\t},\n\t\t\t\t\"remove\" : {\n\t\t\t\t\t\"separator_before\"\t: false,\n\t\t\t\t\t\"icon\"\t\t\t\t: false,\n\t\t\t\t\t\"separator_after\"\t: false,\n\t\t\t\t\t\"label\"\t\t\t\t: \"Delete\",\n\t\t\t\t\t\"action\"\t\t\t: function (obj) { if(this.is_selected(obj)) { this.remove(); } else { this.remove(obj); } }\n\t\t\t\t},\n\t\t\t\t\"ccp\" : {\n\t\t\t\t\t\"separator_before\"\t: true,\n\t\t\t\t\t\"icon\"\t\t\t\t: false,\n\t\t\t\t\t\"separator_after\"\t: false,\n\t\t\t\t\t\"label\"\t\t\t\t: \"Edit\",\n\t\t\t\t\t\"action\"\t\t\t: false,\n\t\t\t\t\t\"submenu\" : { \n\t\t\t\t\t\t\"cut\" : {\n\t\t\t\t\t\t\t\"separator_before\"\t: false,\n\t\t\t\t\t\t\t\"separator_after\"\t: false,\n\t\t\t\t\t\t\t\"label\"\t\t\t\t: \"Cut\",\n\t\t\t\t\t\t\t\"action\"\t\t\t: function (obj) { this.cut(obj); }\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"copy\" : {\n\t\t\t\t\t\t\t\"separator_before\"\t: false,\n\t\t\t\t\t\t\t\"icon\"\t\t\t\t: false,\n\t\t\t\t\t\t\t\"separator_after\"\t: false,\n\t\t\t\t\t\t\t\"label\"\t\t\t\t: \"Copy\",\n\t\t\t\t\t\t\t\"action\"\t\t\t: function (obj) { this.copy(obj); }\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"paste\" : {\n\t\t\t\t\t\t\t\"separator_before\"\t: false,\n\t\t\t\t\t\t\t\"icon\"\t\t\t\t: false,\n\t\t\t\t\t\t\t\"separator_after\"\t: false,\n\t\t\t\t\t\t\t\"label\"\t\t\t\t: \"Paste\",\n\t\t\t\t\t\t\t\"action\"\t\t\t: function (obj) { this.paste(obj); }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t_fn : {\n\t\t\tshow_contextmenu : function (obj, x, y) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar s = this.get_settings().contextmenu,\n\t\t\t\t\ta = obj.children(\"a:visible:eq(0)\"),\n\t\t\t\t\to = false,\n\t\t\t\t\ti = false;\n\t\t\t\tif(s.select_node && this.data.ui && !this.is_selected(obj)) {\n\t\t\t\t\tthis.deselect_all();\n\t\t\t\t\tthis.select_node(obj, true);\n\t\t\t\t}\n\t\t\t\tif(s.show_at_node || typeof x === \"undefined\" || typeof y === \"undefined\") {\n\t\t\t\t\to = a.offset();\n\t\t\t\t\tx = o.left;\n\t\t\t\t\ty = o.top + this.data.core.li_height;\n\t\t\t\t}\n\t\t\t\ti = obj.data(\"jstree\") && obj.data(\"jstree\").contextmenu ? obj.data(\"jstree\").contextmenu : s.items;\n\t\t\t\tif($.isFunction(i)) { i = i.call(this, obj); }\n\t\t\t\tthis.data.contextmenu = true;\n\t\t\t\t$.vakata.context.show(i, a, x, y, this, obj, this._get_settings().core.rtl);\n\t\t\t\tif(this.data.themes) { $.vakata.context.cnt.attr(\"class\", \"jstree-\" + this.data.themes.theme + \"-context\"); }\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree types plugin\n * Adds support types of nodes\n * You can set an attribute on each li node, that represents its type.\n * According to the type setting the node may get custom icon/validation rules\n */\n(function ($) {\n\t$.jstree.plugin(\"types\", {\n\t\t__init : function () {\n\t\t\tvar s = this._get_settings().types;\n\t\t\tthis.data.types.attach_to = [];\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"init.jstree\", $.proxy(function () { \n\t\t\t\t\t\tvar types = s.types, \n\t\t\t\t\t\t\tattr  = s.type_attr, \n\t\t\t\t\t\t\ticons_css = \"\", \n\t\t\t\t\t\t\t_this = this;\n\n\t\t\t\t\t\t$.each(types, function (i, tp) {\n\t\t\t\t\t\t\t$.each(tp, function (k, v) { \n\t\t\t\t\t\t\t\tif(!/^(max_depth|max_children|icon|valid_children)$/.test(k)) { _this.data.types.attach_to.push(k); }\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif(!tp.icon) { return true; }\n\t\t\t\t\t\t\tif( tp.icon.image || tp.icon.position) {\n\t\t\t\t\t\t\t\tif(i == \"default\")\t{ icons_css += '.jstree-' + _this.get_index() + ' a > .jstree-icon { '; }\n\t\t\t\t\t\t\t\telse\t\t\t\t{ icons_css += '.jstree-' + _this.get_index() + ' li[' + attr + '=\"' + i + '\"] > a > .jstree-icon { '; }\n\t\t\t\t\t\t\t\tif(tp.icon.image)\t{ icons_css += ' background-image:url(' + tp.icon.image + '); '; }\n\t\t\t\t\t\t\t\tif(tp.icon.position){ icons_css += ' background-position:' + tp.icon.position + '; '; }\n\t\t\t\t\t\t\t\telse\t\t\t\t{ icons_css += ' background-position:0 0; '; }\n\t\t\t\t\t\t\t\ticons_css += '} ';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif(icons_css !== \"\") { $.vakata.css.add_sheet({ 'str' : icons_css, title : \"jstree-types\" }); }\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"before.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tvar s, t, \n\t\t\t\t\t\t\to = this._get_settings().types.use_data ? this._get_node(data.args[0]) : false, \n\t\t\t\t\t\t\td = o && o !== -1 && o.length ? o.data(\"jstree\") : false;\n\t\t\t\t\t\tif(d && d.types && d.types[data.func] === false) { e.stopImmediatePropagation(); return false; }\n\t\t\t\t\t\tif($.inArray(data.func, this.data.types.attach_to) !== -1) {\n\t\t\t\t\t\t\tif(!data.args[0] || (!data.args[0].tagName && !data.args[0].jquery)) { return; }\n\t\t\t\t\t\t\ts = this._get_settings().types.types;\n\t\t\t\t\t\t\tt = this._get_type(data.args[0]);\n\t\t\t\t\t\t\tif(\n\t\t\t\t\t\t\t\t( \n\t\t\t\t\t\t\t\t\t(s[t] && typeof s[t][data.func] !== \"undefined\") || \n\t\t\t\t\t\t\t\t\t(s[\"default\"] && typeof s[\"default\"][data.func] !== \"undefined\") \n\t\t\t\t\t\t\t\t) && this._check(data.func, data.args[0]) === false\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\t\t\tif(is_ie6) {\n\t\t\t\tthis.get_container()\n\t\t\t\t\t.bind(\"load_node.jstree set_type.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\t\tvar r = data && data.rslt && data.rslt.obj && data.rslt.obj !== -1 ? this._get_node(data.rslt.obj).parent() : this.get_container_ul(),\n\t\t\t\t\t\t\t\tc = false,\n\t\t\t\t\t\t\t\ts = this._get_settings().types;\n\t\t\t\t\t\t\t$.each(s.types, function (i, tp) {\n\t\t\t\t\t\t\t\tif(tp.icon && (tp.icon.image || tp.icon.position)) {\n\t\t\t\t\t\t\t\t\tc = i === \"default\" ? r.find(\"li > a > .jstree-icon\") : r.find(\"li[\" + s.type_attr + \"='\" + i + \"'] > a > .jstree-icon\");\n\t\t\t\t\t\t\t\t\tif(tp.icon.image) { c.css(\"backgroundImage\",\"url(\" + tp.icon.image + \")\"); }\n\t\t\t\t\t\t\t\t\tc.css(\"backgroundPosition\", tp.icon.position || \"0 0\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}, this));\n\t\t\t}\n\t\t},\n\t\tdefaults : {\n\t\t\t// defines maximum number of root nodes (-1 means unlimited, -2 means disable max_children checking)\n\t\t\tmax_children\t\t: -1,\n\t\t\t// defines the maximum depth of the tree (-1 means unlimited, -2 means disable max_depth checking)\n\t\t\tmax_depth\t\t\t: -1,\n\t\t\t// defines valid node types for the root nodes\n\t\t\tvalid_children\t\t: \"all\",\n\n\t\t\t// whether to use $.data\n\t\t\tuse_data : false, \n\t\t\t// where is the type stores (the rel attribute of the LI element)\n\t\t\ttype_attr : \"rel\",\n\t\t\t// a list of types\n\t\t\ttypes : {\n\t\t\t\t// the default type\n\t\t\t\t\"default\" : {\n\t\t\t\t\t\"max_children\"\t: -1,\n\t\t\t\t\t\"max_depth\"\t\t: -1,\n\t\t\t\t\t\"valid_children\": \"all\"\n\n\t\t\t\t\t// Bound functions - you can bind any other function here (using boolean or function)\n\t\t\t\t\t//\"select_node\"\t: true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t_fn : {\n\t\t\t_types_notify : function (n, data) {\n\t\t\t\tif(data.type && this._get_settings().types.use_data) {\n\t\t\t\t\tthis.set_type(data.type, n);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_get_type : function (obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\treturn (!obj || !obj.length) ? false : obj.attr(this._get_settings().types.type_attr) || \"default\";\n\t\t\t},\n\t\t\tset_type : function (str, obj) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar ret = (!obj.length || !str) ? false : obj.attr(this._get_settings().types.type_attr, str);\n\t\t\t\tif(ret) { this.__callback({ obj : obj, type : str}); }\n\t\t\t\treturn ret;\n\t\t\t},\n\t\t\t_check : function (rule, obj, opts) {\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tvar v = false, t = this._get_type(obj), d = 0, _this = this, s = this._get_settings().types, data = false;\n\t\t\t\tif(obj === -1) { \n\t\t\t\t\tif(!!s[rule]) { v = s[rule]; }\n\t\t\t\t\telse { return; }\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif(t === false) { return; }\n\t\t\t\t\tdata = s.use_data ? obj.data(\"jstree\") : false;\n\t\t\t\t\tif(data && data.types && typeof data.types[rule] !== \"undefined\") { v = data.types[rule]; }\n\t\t\t\t\telse if(!!s.types[t] && typeof s.types[t][rule] !== \"undefined\") { v = s.types[t][rule]; }\n\t\t\t\t\telse if(!!s.types[\"default\"] && typeof s.types[\"default\"][rule] !== \"undefined\") { v = s.types[\"default\"][rule]; }\n\t\t\t\t}\n\t\t\t\tif($.isFunction(v)) { v = v.call(this, obj); }\n\t\t\t\tif(rule === \"max_depth\" && obj !== -1 && opts !== false && s.max_depth !== -2 && v !== 0) {\n\t\t\t\t\t// also include the node itself - otherwise if root node it is not checked\n\t\t\t\t\tobj.children(\"a:eq(0)\").parentsUntil(\".jstree\",\"li\").each(function (i) {\n\t\t\t\t\t\t// check if current depth already exceeds global tree depth\n\t\t\t\t\t\tif(s.max_depth !== -1 && s.max_depth - (i + 1) <= 0) { v = 0; return false; }\n\t\t\t\t\t\td = (i === 0) ? v : _this._check(rule, this, false);\n\t\t\t\t\t\t// check if current node max depth is already matched or exceeded\n\t\t\t\t\t\tif(d !== -1 && d - (i + 1) <= 0) { v = 0; return false; }\n\t\t\t\t\t\t// otherwise - set the max depth to the current value minus current depth\n\t\t\t\t\t\tif(d >= 0 && (d - (i + 1) < v || v < 0) ) { v = d - (i + 1); }\n\t\t\t\t\t\t// if the global tree depth exists and it minus the nodes calculated so far is less than `v` or `v` is unlimited\n\t\t\t\t\t\tif(s.max_depth >= 0 && (s.max_depth - (i + 1) < v || v < 0) ) { v = s.max_depth - (i + 1); }\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn v;\n\t\t\t},\n\t\t\tcheck_move : function () {\n\t\t\t\tif(!this.__call_old()) { return false; }\n\t\t\t\tvar m  = this._get_move(),\n\t\t\t\t\ts  = m.rt._get_settings().types,\n\t\t\t\t\tmc = m.rt._check(\"max_children\", m.cr),\n\t\t\t\t\tmd = m.rt._check(\"max_depth\", m.cr),\n\t\t\t\t\tvc = m.rt._check(\"valid_children\", m.cr),\n\t\t\t\t\tch = 0, d = 1, t;\n\n\t\t\t\tif(vc === \"none\") { return false; } \n\t\t\t\tif($.isArray(vc) && m.ot && m.ot._get_type) {\n\t\t\t\t\tm.o.each(function () {\n\t\t\t\t\t\tif($.inArray(m.ot._get_type(this), vc) === -1) { d = false; return false; }\n\t\t\t\t\t});\n\t\t\t\t\tif(d === false) { return false; }\n\t\t\t\t}\n\t\t\t\tif(s.max_children !== -2 && mc !== -1) {\n\t\t\t\t\tch = m.cr === -1 ? this.get_container().find(\"> ul > li\").not(m.o).length : m.cr.find(\"> ul > li\").not(m.o).length;\n\t\t\t\t\tif(ch + m.o.length > mc) { return false; }\n\t\t\t\t}\n\t\t\t\tif(s.max_depth !== -2 && md !== -1) {\n\t\t\t\t\td = 0;\n\t\t\t\t\tif(md === 0) { return false; }\n\t\t\t\t\tif(typeof m.o.d === \"undefined\") {\n\t\t\t\t\t\t// TODO: deal with progressive rendering and async when checking max_depth (how to know the depth of the moved node)\n\t\t\t\t\t\tt = m.o;\n\t\t\t\t\t\twhile(t.length > 0) {\n\t\t\t\t\t\t\tt = t.find(\"> ul > li\");\n\t\t\t\t\t\t\td ++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm.o.d = d;\n\t\t\t\t\t}\n\t\t\t\t\tif(md - m.o.d < 0) { return false; }\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tcreate_node : function (obj, position, js, callback, is_loaded, skip_check) {\n\t\t\t\tif(!skip_check && (is_loaded || this._is_loaded(obj))) {\n\t\t\t\t\tvar p  = (typeof position == \"string\" && position.match(/^before|after$/i) && obj !== -1) ? this._get_parent(obj) : this._get_node(obj),\n\t\t\t\t\t\ts  = this._get_settings().types,\n\t\t\t\t\t\tmc = this._check(\"max_children\", p),\n\t\t\t\t\t\tmd = this._check(\"max_depth\", p),\n\t\t\t\t\t\tvc = this._check(\"valid_children\", p),\n\t\t\t\t\t\tch;\n\t\t\t\t\tif(typeof js === \"string\") { js = { data : js }; }\n\t\t\t\t\tif(!js) { js = {}; }\n\t\t\t\t\tif(vc === \"none\") { return false; } \n\t\t\t\t\tif($.isArray(vc)) {\n\t\t\t\t\t\tif(!js.attr || !js.attr[s.type_attr]) { \n\t\t\t\t\t\t\tif(!js.attr) { js.attr = {}; }\n\t\t\t\t\t\t\tjs.attr[s.type_attr] = vc[0]; \n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif($.inArray(js.attr[s.type_attr], vc) === -1) { return false; }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(s.max_children !== -2 && mc !== -1) {\n\t\t\t\t\t\tch = p === -1 ? this.get_container().find(\"> ul > li\").length : p.find(\"> ul > li\").length;\n\t\t\t\t\t\tif(ch + 1 > mc) { return false; }\n\t\t\t\t\t}\n\t\t\t\t\tif(s.max_depth !== -2 && md !== -1 && (md - 1) < 0) { return false; }\n\t\t\t\t}\n\t\t\t\treturn this.__call_old(true, obj, position, js, callback, is_loaded, skip_check);\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree HTML plugin\n * The HTML data store. Datastores are build by replacing the `load_node` and `_is_loaded` functions.\n */\n(function ($) {\n\t$.jstree.plugin(\"html_data\", {\n\t\t__init : function () { \n\t\t\t// this used to use html() and clean the whitespace, but this way any attached data was lost\n\t\t\tthis.data.html_data.original_container_html = this.get_container().find(\" > ul > li\").clone(true);\n\t\t\t// remove white space from LI node - otherwise nodes appear a bit to the right\n\t\t\tthis.data.html_data.original_container_html.find(\"li\").andSelf().contents().filter(function() { return this.nodeType == 3; }).remove();\n\t\t},\n\t\tdefaults : { \n\t\t\tdata : false,\n\t\t\tajax : false,\n\t\t\tcorrect_state : true\n\t\t},\n\t\t_fn : {\n\t\t\tload_node : function (obj, s_call, e_call) { var _this = this; this.load_node_html(obj, function () { _this.__callback({ \"obj\" : _this._get_node(obj) }); s_call.call(this); }, e_call); },\n\t\t\t_is_loaded : function (obj) { \n\t\t\t\tobj = this._get_node(obj); \n\t\t\t\treturn obj == -1 || !obj || (!this._get_settings().html_data.ajax && !$.isFunction(this._get_settings().html_data.data)) || obj.is(\".jstree-open, .jstree-leaf\") || obj.children(\"ul\").children(\"li\").size() > 0;\n\t\t\t},\n\t\t\tload_node_html : function (obj, s_call, e_call) {\n\t\t\t\tvar d,\n\t\t\t\t\ts = this.get_settings().html_data,\n\t\t\t\t\terror_func = function () {},\n\t\t\t\t\tsuccess_func = function () {};\n\t\t\t\tobj = this._get_node(obj);\n\t\t\t\tif(obj && obj !== -1) {\n\t\t\t\t\tif(obj.data(\"jstree_is_loading\")) { return; }\n\t\t\t\t\telse { obj.data(\"jstree_is_loading\",true); }\n\t\t\t\t}\n\t\t\t\tswitch(!0) {\n\t\t\t\t\tcase ($.isFunction(s.data)):\n\t\t\t\t\t\ts.data.call(this, obj, $.proxy(function (d) {\n\t\t\t\t\t\t\tif(d && d !== \"\" && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") !== \"\") {\n\t\t\t\t\t\t\t\td = $(d);\n\t\t\t\t\t\t\t\tif(!d.is(\"ul\")) { d = $(\"<ul />\").append(d); }\n\t\t\t\t\t\t\t\tif(obj == -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()).find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); }\n\t\t\t\t\t\t\t\telse { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d).children(\"ul\").find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); obj.removeData(\"jstree_is_loading\"); }\n\t\t\t\t\t\t\t\tthis.clean_node(obj);\n\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(obj && obj !== -1) {\n\t\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.correct_state(obj);\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty();\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!s.data && !s.ajax):\n\t\t\t\t\t\tif(!obj || obj == -1) {\n\t\t\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t\t\t.children(\"ul\").empty()\n\t\t\t\t\t\t\t\t.append(this.data.html_data.original_container_html)\n\t\t\t\t\t\t\t\t.find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end()\n\t\t\t\t\t\t\t\t.filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\");\n\t\t\t\t\t\t\tthis.clean_node();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):\n\t\t\t\t\t\tif(!obj || obj == -1) {\n\t\t\t\t\t\t\td = $(s.data);\n\t\t\t\t\t\t\tif(!d.is(\"ul\")) { d = $(\"<ul />\").append(d); }\n\t\t\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t\t\t.children(\"ul\").empty().append(d.children())\n\t\t\t\t\t\t\t\t.find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end()\n\t\t\t\t\t\t\t\t.filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\");\n\t\t\t\t\t\t\tthis.clean_node();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):\n\t\t\t\t\t\tobj = this._get_node(obj);\n\t\t\t\t\t\terror_func = function (x, t, e) {\n\t\t\t\t\t\t\tvar ef = this.get_settings().html_data.ajax.error; \n\t\t\t\t\t\t\tif(ef) { ef.call(this, x, t, e); }\n\t\t\t\t\t\t\tif(obj != -1 && obj.length) {\n\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\tif(t === \"success\" && s.correct_state) { this.correct_state(obj); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(t === \"success\" && s.correct_state) { this.get_container().children(\"ul\").empty(); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(e_call) { e_call.call(this); }\n\t\t\t\t\t\t};\n\t\t\t\t\t\tsuccess_func = function (d, t, x) {\n\t\t\t\t\t\t\tvar sf = this.get_settings().html_data.ajax.success; \n\t\t\t\t\t\t\tif(sf) { d = sf.call(this,d,t,x) || d; }\n\t\t\t\t\t\t\tif(d === \"\" || (d && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") === \"\")) {\n\t\t\t\t\t\t\t\treturn error_func.call(this, x, t, \"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(d) {\n\t\t\t\t\t\t\t\td = $(d);\n\t\t\t\t\t\t\t\tif(!d.is(\"ul\")) { d = $(\"<ul />\").append(d); }\n\t\t\t\t\t\t\t\tif(obj == -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()).find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); }\n\t\t\t\t\t\t\t\telse { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d).children(\"ul\").find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); obj.removeData(\"jstree_is_loading\"); }\n\t\t\t\t\t\t\t\tthis.clean_node(obj);\n\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif(obj && obj !== -1) {\n\t\t\t\t\t\t\t\t\tobj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n\t\t\t\t\t\t\t\t\tobj.removeData(\"jstree_is_loading\");\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.correct_state(obj);\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tif(s.correct_state) { \n\t\t\t\t\t\t\t\t\t\tthis.get_container().children(\"ul\").empty();\n\t\t\t\t\t\t\t\t\t\tif(s_call) { s_call.call(this); } \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t\ts.ajax.context = this;\n\t\t\t\t\t\ts.ajax.error = error_func;\n\t\t\t\t\t\ts.ajax.success = success_func;\n\t\t\t\t\t\tif(!s.ajax.dataType) { s.ajax.dataType = \"html\"; }\n\t\t\t\t\t\tif($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }\n\t\t\t\t\t\tif($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }\n\t\t\t\t\t\t$.ajax(s.ajax);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// include the HTML data plugin by default\n\t$.jstree.defaults.plugins.push(\"html_data\");\n})(jQuery);\n//*/\n\n/* \n * jsTree themeroller plugin\n * Adds support for jQuery UI themes. Include this at the end of your plugins list, also make sure \"themes\" is not included.\n */\n(function ($) {\n\t$.jstree.plugin(\"themeroller\", {\n\t\t__init : function () {\n\t\t\tvar s = this._get_settings().themeroller;\n\t\t\tthis.get_container()\n\t\t\t\t.addClass(\"ui-widget-content\")\n\t\t\t\t.addClass(\"jstree-themeroller\")\n\t\t\t\t.delegate(\"a\",\"mouseenter.jstree\", function (e) {\n\t\t\t\t\tif(!$(e.currentTarget).hasClass(\"jstree-loading\")) {\n\t\t\t\t\t\t$(this).addClass(s.item_h);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.delegate(\"a\",\"mouseleave.jstree\", function () {\n\t\t\t\t\t$(this).removeClass(s.item_h);\n\t\t\t\t})\n\t\t\t\t.bind(\"init.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tdata.inst.get_container().find(\"> ul > li > .jstree-loading > ins\").addClass(\"ui-icon-refresh\");\n\t\t\t\t\t\tthis._themeroller(data.inst.get_container().find(\"> ul > li\"));\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"open_node.jstree create_node.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tthis._themeroller(data.rslt.obj);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"loaded.jstree refresh.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tthis._themeroller();\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"close_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tthis._themeroller(data.rslt.obj);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"delete_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tthis._themeroller(data.rslt.parent);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"correct_state.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tdata.rslt.obj\n\t\t\t\t\t\t\t.children(\"ins.jstree-icon\").removeClass(s.opened + \" \" + s.closed + \" ui-icon\").end()\n\t\t\t\t\t\t\t.find(\"> a > ins.ui-icon\")\n\t\t\t\t\t\t\t\t.filter(function() { \n\t\t\t\t\t\t\t\t\treturn this.className.toString()\n\t\t\t\t\t\t\t\t\t\t.replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n\t\t\t\t\t\t\t\t\t\t.indexOf(\"ui-icon-\") === -1; \n\t\t\t\t\t\t\t\t}).removeClass(s.item_open + \" \" + s.item_clsd).addClass(s.item_leaf || \"jstree-no-icon\");\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"select_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tdata.rslt.obj.children(\"a\").addClass(s.item_a);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"deselect_node.jstree deselect_all.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t\t.find(\"a.\" + s.item_a).removeClass(s.item_a).end()\n\t\t\t\t\t\t\t.find(\"a.jstree-clicked\").addClass(s.item_a);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"dehover_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tdata.rslt.obj.children(\"a\").removeClass(s.item_h);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"hover_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tthis.get_container()\n\t\t\t\t\t\t\t.find(\"a.\" + s.item_h).not(data.rslt.obj).removeClass(s.item_h);\n\t\t\t\t\t\tdata.rslt.obj.children(\"a\").addClass(s.item_h);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"move_node.jstree\", $.proxy(function (e, data) {\n\t\t\t\t\t\tthis._themeroller(data.rslt.o);\n\t\t\t\t\t\tthis._themeroller(data.rslt.op);\n\t\t\t\t\t}, this));\n\t\t},\n\t\t__destroy : function () {\n\t\t\tvar s = this._get_settings().themeroller,\n\t\t\t\tc = [ \"ui-icon\" ];\n\t\t\t$.each(s, function (i, v) {\n\t\t\t\tv = v.split(\" \");\n\t\t\t\tif(v.length) { c = c.concat(v); }\n\t\t\t});\n\t\t\tthis.get_container()\n\t\t\t\t.removeClass(\"ui-widget-content\")\n\t\t\t\t.find(\".\" + c.join(\", .\")).removeClass(c.join(\" \"));\n\t\t},\n\t\t_fn : {\n\t\t\t_themeroller : function (obj) {\n\t\t\t\tvar s = this._get_settings().themeroller;\n\t\t\t\tobj = !obj || obj == -1 ? this.get_container_ul() : this._get_node(obj).parent();\n\t\t\t\tobj\n\t\t\t\t\t.find(\"li.jstree-closed\")\n\t\t\t\t\t\t.children(\"ins.jstree-icon\").removeClass(s.opened).addClass(\"ui-icon \" + s.closed).end()\n\t\t\t\t\t\t.children(\"a\").addClass(s.item)\n\t\t\t\t\t\t\t.children(\"ins.jstree-icon\").addClass(\"ui-icon\")\n\t\t\t\t\t\t\t\t.filter(function() { \n\t\t\t\t\t\t\t\t\treturn this.className.toString()\n\t\t\t\t\t\t\t\t\t\t.replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n\t\t\t\t\t\t\t\t\t\t.indexOf(\"ui-icon-\") === -1; \n\t\t\t\t\t\t\t\t}).removeClass(s.item_leaf + \" \" + s.item_open).addClass(s.item_clsd || \"jstree-no-icon\")\n\t\t\t\t\t\t\t\t.end()\n\t\t\t\t\t\t\t.end()\n\t\t\t\t\t\t.end()\n\t\t\t\t\t.end()\n\t\t\t\t\t.find(\"li.jstree-open\")\n\t\t\t\t\t\t.children(\"ins.jstree-icon\").removeClass(s.closed).addClass(\"ui-icon \" + s.opened).end()\n\t\t\t\t\t\t.children(\"a\").addClass(s.item)\n\t\t\t\t\t\t\t.children(\"ins.jstree-icon\").addClass(\"ui-icon\")\n\t\t\t\t\t\t\t\t.filter(function() { \n\t\t\t\t\t\t\t\t\treturn this.className.toString()\n\t\t\t\t\t\t\t\t\t\t.replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n\t\t\t\t\t\t\t\t\t\t.indexOf(\"ui-icon-\") === -1; \n\t\t\t\t\t\t\t\t}).removeClass(s.item_leaf + \" \" + s.item_clsd).addClass(s.item_open || \"jstree-no-icon\")\n\t\t\t\t\t\t\t\t.end()\n\t\t\t\t\t\t\t.end()\n\t\t\t\t\t\t.end()\n\t\t\t\t\t.end()\n\t\t\t\t\t.find(\"li.jstree-leaf\")\n\t\t\t\t\t\t.children(\"ins.jstree-icon\").removeClass(s.closed + \" ui-icon \" + s.opened).end()\n\t\t\t\t\t\t.children(\"a\").addClass(s.item)\n\t\t\t\t\t\t\t.children(\"ins.jstree-icon\").addClass(\"ui-icon\")\n\t\t\t\t\t\t\t\t.filter(function() { \n\t\t\t\t\t\t\t\t\treturn this.className.toString()\n\t\t\t\t\t\t\t\t\t\t.replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n\t\t\t\t\t\t\t\t\t\t.indexOf(\"ui-icon-\") === -1; \n\t\t\t\t\t\t\t\t}).removeClass(s.item_clsd + \" \" + s.item_open).addClass(s.item_leaf || \"jstree-no-icon\");\n\t\t\t}\n\t\t},\n\t\tdefaults : {\n\t\t\t\"opened\"\t: \"ui-icon-triangle-1-se\",\n\t\t\t\"closed\"\t: \"ui-icon-triangle-1-e\",\n\t\t\t\"item\"\t\t: \"ui-state-default\",\n\t\t\t\"item_h\"\t: \"ui-state-hover\",\n\t\t\t\"item_a\"\t: \"ui-state-active\",\n\t\t\t\"item_open\"\t: \"ui-icon-folder-open\",\n\t\t\t\"item_clsd\"\t: \"ui-icon-folder-collapsed\",\n\t\t\t\"item_leaf\"\t: \"ui-icon-document\"\n\t\t}\n\t});\n\t$(function() {\n\t\tvar css_string = '' + \n\t\t\t'.jstree-themeroller .ui-icon { overflow:visible; } ' + \n\t\t\t'.jstree-themeroller a { padding:0 2px; } ' + \n\t\t\t'.jstree-themeroller .jstree-no-icon { display:none; }';\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n\t});\n})(jQuery);\n//*/\n\n/* \n * jsTree unique plugin\n * Forces different names amongst siblings (still a bit experimental)\n * NOTE: does not check language versions (it will not be possible to have nodes with the same title, even in different languages)\n */\n(function ($) {\n\t$.jstree.plugin(\"unique\", {\n\t\t__init : function () {\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"before.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tvar nms = [], res = true, p, t;\n\t\t\t\t\t\tif(data.func == \"move_node\") {\n\t\t\t\t\t\t\t// obj, ref, position, is_copy, is_prepared, skip_check\n\t\t\t\t\t\t\tif(data.args[4] === true) {\n\t\t\t\t\t\t\t\tif(data.args[0].o && data.args[0].o.length) {\n\t\t\t\t\t\t\t\t\tdata.args[0].o.children(\"a\").each(function () { nms.push($(this).text().replace(/^\\s+/g,\"\")); });\n\t\t\t\t\t\t\t\t\tres = this._check_unique(nms, data.args[0].np.find(\"> ul > li\").not(data.args[0].o), \"move_node\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(data.func == \"create_node\") {\n\t\t\t\t\t\t\t// obj, position, js, callback, is_loaded\n\t\t\t\t\t\t\tif(data.args[4] || this._is_loaded(data.args[0])) {\n\t\t\t\t\t\t\t\tp = this._get_node(data.args[0]);\n\t\t\t\t\t\t\t\tif(data.args[1] && (data.args[1] === \"before\" || data.args[1] === \"after\")) {\n\t\t\t\t\t\t\t\t\tp = this._get_parent(data.args[0]);\n\t\t\t\t\t\t\t\t\tif(!p || p === -1) { p = this.get_container(); }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif(typeof data.args[2] === \"string\") { nms.push(data.args[2]); }\n\t\t\t\t\t\t\t\telse if(!data.args[2] || !data.args[2].data) { nms.push(this._get_string(\"new_node\")); }\n\t\t\t\t\t\t\t\telse { nms.push(data.args[2].data); }\n\t\t\t\t\t\t\t\tres = this._check_unique(nms, p.find(\"> ul > li\"), \"create_node\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(data.func == \"rename_node\") {\n\t\t\t\t\t\t\t// obj, val\n\t\t\t\t\t\t\tnms.push(data.args[1]);\n\t\t\t\t\t\t\tt = this._get_node(data.args[0]);\n\t\t\t\t\t\t\tp = this._get_parent(t);\n\t\t\t\t\t\t\tif(!p || p === -1) { p = this.get_container(); }\n\t\t\t\t\t\t\tres = this._check_unique(nms, p.find(\"> ul > li\").not(t), \"rename_node\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(!res) {\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this));\n\t\t},\n\t\tdefaults : { \n\t\t\terror_callback : $.noop\n\t\t},\n\t\t_fn : { \n\t\t\t_check_unique : function (nms, p, func) {\n\t\t\t\tvar cnms = [];\n\t\t\t\tp.children(\"a\").each(function () { cnms.push($(this).text().replace(/^\\s+/g,\"\")); });\n\t\t\t\tif(!cnms.length || !nms.length) { return true; }\n\t\t\t\tcnms = cnms.sort().join(\",,\").replace(/(,|^)([^,]+)(,,\\2)+(,|$)/g,\"$1$2$4\").replace(/,,+/g,\",\").replace(/,$/,\"\").split(\",\");\n\t\t\t\tif((cnms.length + nms.length) != cnms.concat(nms).sort().join(\",,\").replace(/(,|^)([^,]+)(,,\\2)+(,|$)/g,\"$1$2$4\").replace(/,,+/g,\",\").replace(/,$/,\"\").split(\",\").length) {\n\t\t\t\t\tthis._get_settings().unique.error_callback.call(null, nms, p, func);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tcheck_move : function () {\n\t\t\t\tif(!this.__call_old()) { return false; }\n\t\t\t\tvar p = this._get_move(), nms = [];\n\t\t\t\tif(p.o && p.o.length) {\n\t\t\t\t\tp.o.children(\"a\").each(function () { nms.push($(this).text().replace(/^\\s+/g,\"\")); });\n\t\t\t\t\treturn this._check_unique(nms, p.np.find(\"> ul > li\").not(p.o), \"check_move\");\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n/*\n * jsTree wholerow plugin\n * Makes select and hover work on the entire width of the node\n * MAY BE HEAVY IN LARGE DOM\n */\n(function ($) {\n\t$.jstree.plugin(\"wholerow\", {\n\t\t__init : function () {\n\t\t\tif(!this.data.ui) { throw \"jsTree wholerow: jsTree UI plugin not included.\"; }\n\t\t\tthis.data.wholerow.html = false;\n\t\t\tthis.data.wholerow.to = false;\n\t\t\tthis.get_container()\n\t\t\t\t.bind(\"init.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tthis._get_settings().core.animation = 0;\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"open_node.jstree create_node.jstree clean_node.jstree loaded.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tthis._prepare_wholerow_span( data && data.rslt && data.rslt.obj ? data.rslt.obj : -1 );\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"search.jstree clear_search.jstree reopen.jstree after_open.jstree after_close.jstree create_node.jstree delete_node.jstree clean_node.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tif(this.data.to) { clearTimeout(this.data.to); }\n\t\t\t\t\t\tthis.data.to = setTimeout( (function (t, o) { return function() { t._prepare_wholerow_ul(o); }; })(this,  data && data.rslt && data.rslt.obj ? data.rslt.obj : -1), 0);\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"deselect_all.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tthis.get_container().find(\" > .jstree-wholerow .jstree-clicked\").removeClass(\"jstree-clicked \" + (this.data.themeroller ? this._get_settings().themeroller.item_a : \"\" ));\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"select_node.jstree deselect_node.jstree \", $.proxy(function (e, data) { \n\t\t\t\t\t\tdata.rslt.obj.each(function () { \n\t\t\t\t\t\t\tvar ref = data.inst.get_container().find(\" > .jstree-wholerow li:visible:eq(\" + ( parseInt((($(this).offset().top - data.inst.get_container().offset().top + data.inst.get_container()[0].scrollTop) / data.inst.data.core.li_height),10)) + \")\");\n\t\t\t\t\t\t\t// ref.children(\"a\")[e.type === \"select_node\" ? \"addClass\" : \"removeClass\"](\"jstree-clicked\");\n\t\t\t\t\t\t\tref.children(\"a\").attr(\"class\",data.rslt.obj.children(\"a\").attr(\"class\"));\n\t\t\t\t\t\t});\n\t\t\t\t\t}, this))\n\t\t\t\t.bind(\"hover_node.jstree dehover_node.jstree\", $.proxy(function (e, data) { \n\t\t\t\t\t\tthis.get_container().find(\" > .jstree-wholerow .jstree-hovered\").removeClass(\"jstree-hovered \" + (this.data.themeroller ? this._get_settings().themeroller.item_h : \"\" ));\n\t\t\t\t\t\tif(e.type === \"hover_node\") {\n\t\t\t\t\t\t\tvar ref = this.get_container().find(\" > .jstree-wholerow li:visible:eq(\" + ( parseInt(((data.rslt.obj.offset().top - this.get_container().offset().top + this.get_container()[0].scrollTop) / this.data.core.li_height),10)) + \")\");\n\t\t\t\t\t\t\t// ref.children(\"a\").addClass(\"jstree-hovered\");\n\t\t\t\t\t\t\tref.children(\"a\").attr(\"class\",data.rslt.obj.children(\".jstree-hovered\").attr(\"class\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\".jstree-wholerow-span, ins.jstree-icon, li\", \"click.jstree\", function (e) {\n\t\t\t\t\t\tvar n = $(e.currentTarget);\n\t\t\t\t\t\tif(e.target.tagName === \"A\" || (e.target.tagName === \"INS\" && n.closest(\"li\").is(\".jstree-open, .jstree-closed\"))) { return; }\n\t\t\t\t\t\tn.closest(\"li\").children(\"a:visible:eq(0)\").click();\n\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t})\n\t\t\t\t.delegate(\"li\", \"mouseover.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\tif($(e.currentTarget).children(\".jstree-hovered, .jstree-clicked\").length) { return false; }\n\t\t\t\t\t\tthis.hover_node(e.currentTarget);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}, this))\n\t\t\t\t.delegate(\"li\", \"mouseleave.jstree\", $.proxy(function (e) {\n\t\t\t\t\t\tif($(e.currentTarget).children(\"a\").hasClass(\"jstree-hovered\").length) { return; }\n\t\t\t\t\t\tthis.dehover_node(e.currentTarget);\n\t\t\t\t\t}, this));\n\t\t\tif(is_ie7 || is_ie6) {\n\t\t\t\t$.vakata.css.add_sheet({ str : \".jstree-\" + this.get_index() + \" { position:relative; } \", title : \"jstree\" });\n\t\t\t}\n\t\t},\n\t\tdefaults : {\n\t\t},\n\t\t__destroy : function () {\n\t\t\tthis.get_container().children(\".jstree-wholerow\").remove();\n\t\t\tthis.get_container().find(\".jstree-wholerow-span\").remove();\n\t\t},\n\t\t_fn : {\n\t\t\t_prepare_wholerow_span : function (obj) {\n\t\t\t\tobj = !obj || obj == -1 ? this.get_container().find(\"> ul > li\") : this._get_node(obj);\n\t\t\t\tif(obj === false) { return; } // added for removing root nodes\n\t\t\t\tobj.each(function () {\n\t\t\t\t\t$(this).find(\"li\").andSelf().each(function () {\n\t\t\t\t\t\tvar $t = $(this);\n\t\t\t\t\t\tif($t.children(\".jstree-wholerow-span\").length) { return true; }\n\t\t\t\t\t\t$t.prepend(\"<span class='jstree-wholerow-span' style='width:\" + ($t.parentsUntil(\".jstree\",\"li\").length * 18) + \"px;'>&#160;</span>\");\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\t_prepare_wholerow_ul : function () {\n\t\t\t\tvar o = this.get_container().children(\"ul\").eq(0), h = o.html();\n\t\t\t\to.addClass(\"jstree-wholerow-real\");\n\t\t\t\tif(this.data.wholerow.last_html !== h) {\n\t\t\t\t\tthis.data.wholerow.last_html = h;\n\t\t\t\t\tthis.get_container().children(\".jstree-wholerow\").remove();\n\t\t\t\t\tthis.get_container().append(\n\t\t\t\t\t\to.clone().removeClass(\"jstree-wholerow-real\")\n\t\t\t\t\t\t\t.wrapAll(\"<div class='jstree-wholerow' />\").parent()\n\t\t\t\t\t\t\t.width(o.parent()[0].scrollWidth)\n\t\t\t\t\t\t\t.css(\"top\", (o.height() + ( is_ie7 ? 5 : 0)) * -1 )\n\t\t\t\t\t\t\t.find(\"li[id]\").each(function () { this.removeAttribute(\"id\"); }).end()\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t$(function() {\n\t\tvar css_string = '' + \n\t\t\t'.jstree .jstree-wholerow-real { position:relative; z-index:1; } ' + \n\t\t\t'.jstree .jstree-wholerow-real li { cursor:pointer; } ' + \n\t\t\t'.jstree .jstree-wholerow-real a { border-left-color:transparent !important; border-right-color:transparent !important; } ' + \n\t\t\t'.jstree .jstree-wholerow { position:relative; z-index:0; height:0; } ' + \n\t\t\t'.jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { width:100%; } ' + \n\t\t\t'.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li, .jstree .jstree-wholerow a { margin:0 !important; padding:0 !important; } ' + \n\t\t\t'.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { background:transparent !important; }' + \n\t\t\t'.jstree .jstree-wholerow ins, .jstree .jstree-wholerow span, .jstree .jstree-wholerow input { display:none !important; }' + \n\t\t\t'.jstree .jstree-wholerow a, .jstree .jstree-wholerow a:hover { text-indent:-9999px; !important; width:100%; padding:0 !important; border-right-width:0px !important; border-left-width:0px !important; } ' + \n\t\t\t'.jstree .jstree-wholerow-span { position:absolute; left:0; margin:0px; padding:0; height:18px; border-width:0; padding:0; z-index:0; }';\n\t\tif(is_ff2) {\n\t\t\tcss_string += '' + \n\t\t\t\t'.jstree .jstree-wholerow a { display:block; height:18px; margin:0; padding:0; border:0; } ' + \n\t\t\t\t'.jstree .jstree-wholerow-real a { border-color:transparent !important; } ';\n\t\t}\n\t\tif(is_ie7 || is_ie6) {\n\t\t\tcss_string += '' + \n\t\t\t\t'.jstree .jstree-wholerow, .jstree .jstree-wholerow li, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow a { margin:0; padding:0; line-height:18px; } ' + \n\t\t\t\t'.jstree .jstree-wholerow a { display:block; height:18px; line-height:18px; overflow:hidden; } ';\n\t\t}\n\t\t$.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n\t});\n})(jQuery);\n//*/\n\n/*\n* jsTree model plugin\n* This plugin gets jstree to use a class model to retrieve data, creating great dynamism\n*/\n(function ($) {\n\tvar nodeInterface = [\"getChildren\",\"getChildrenCount\",\"getAttr\",\"getName\",\"getProps\"],\n\t\tvalidateInterface = function(obj, inter) {\n\t\t\tvar valid = true;\n\t\t\tobj = obj || {};\n\t\t\tinter = [].concat(inter);\n\t\t\t$.each(inter, function (i, v) {\n\t\t\t\tif(!$.isFunction(obj[v])) { valid = false; return false; }\n\t\t\t});\n\t\t\treturn valid;\n\t\t};\n\t$.jstree.plugin(\"model\", {\n\t\t__init : function () {\n\t\t\tif(!this.data.json_data) { throw \"jsTree model: jsTree json_data plugin not included.\"; }\n\t\t\tthis._get_settings().json_data.data = function (n, b) {\n\t\t\t\tvar obj = (n == -1) ? this._get_settings().model.object : n.data(\"jstree_model\");\n\t\t\t\tif(!validateInterface(obj, nodeInterface)) { return b.call(null, false); }\n\t\t\t\tif(this._get_settings().model.async) {\n\t\t\t\t\tobj.getChildren($.proxy(function (data) {\n\t\t\t\t\t\tthis.model_done(data, b);\n\t\t\t\t\t}, this));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.model_done(obj.getChildren(), b);\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tdefaults : {\n\t\t\tobject : false,\n\t\t\tid_prefix : false,\n\t\t\tasync : false\n\t\t},\n\t\t_fn : {\n\t\t\tmodel_done : function (data, callback) {\n\t\t\t\tvar ret = [], \n\t\t\t\t\ts = this._get_settings(),\n\t\t\t\t\t_this = this;\n\n\t\t\t\tif(!$.isArray(data)) { data = [data]; }\n\t\t\t\t$.each(data, function (i, nd) {\n\t\t\t\t\tvar r = nd.getProps() || {};\n\t\t\t\t\tr.attr = nd.getAttr() || {};\n\t\t\t\t\tif(nd.getChildrenCount()) { r.state = \"closed\"; }\n\t\t\t\t\tr.data = nd.getName();\n\t\t\t\t\tif(!$.isArray(r.data)) { r.data = [r.data]; }\n\t\t\t\t\tif(_this.data.types && $.isFunction(nd.getType)) {\n\t\t\t\t\t\tr.attr[s.types.type_attr] = nd.getType();\n\t\t\t\t\t}\n\t\t\t\t\tif(r.attr.id && s.model.id_prefix) { r.attr.id = s.model.id_prefix + r.attr.id; }\n\t\t\t\t\tif(!r.metadata) { r.metadata = { }; }\n\t\t\t\t\tr.metadata.jstree_model = nd;\n\t\t\t\t\tret.push(r);\n\t\t\t\t});\n\t\t\t\tcallback.call(null, ret);\n\t\t\t}\n\t\t}\n\t});\n})(jQuery);\n//*/\n\n})();\ndefine(\"thirdparty/jstree_pre1.0_fix_1/jquery.jstree\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * PreferenceStorage defines an interface for persisting preference data as\n * name/value pairs for a module or plugin.\n */\ndefine('preferences/PreferenceStorage',['require','exports','module','preferences/PreferencesManager'],function (require, exports, module) {\n    \n    \n    var PreferencesManager = require(\"preferences/PreferencesManager\");\n    \n    /**\n     * @private\n     * Validate JSON keys and values.\n     */\n    function _validateJSONPair(key, value) {\n        if (typeof key === \"string\") {\n            // validate temporary JSON\n            var temp = {},\n                error = null;\n            temp[key] = value;\n            \n            try {\n                temp = JSON.parse(JSON.stringify(temp));\n            } catch (err) {\n                error = err;\n            }\n            \n            // set value to JSON storage if no errors occurred\n            if (!error && (temp[key] !== undefined)) {\n                return true;\n            } else {\n                throw new Error(\"Value '\" + value + \"' for key '\" + key + \"' must be a valid JSON value\");\n            }\n        } else {\n            throw new Error(\"Preference key '\" + key + \"' must be a string\");\n        }\n    }\n    \n    /**\n     * @private\n     * Save to persistent storage.\n     */\n    function _commit() {\n        PreferencesManager.savePreferences();\n    }\n    \n    /**\n     * Creates a new PreferenceStorage object.\n     * @param {!string} clientID Unique identifier for PreferencesManager to\n     *  associate this PreferenceStorage data with.\n     * @param {!object} json JSON object to persist preference data.\n     */\n    function PreferenceStorage(clientID, json) {\n        this._clientID = clientID;\n        this._json = json;\n    }\n    \n    /**\n     * Unique clientID for this PreferenceStorage object.\n     * @return {!string} clientID\n     */\n    PreferenceStorage.prototype.getClientID = function () {\n        return this._clientID;\n    };\n    \n    /**\n     * Removes a preference from this PreferenceStorage object.\n     * @param {!string} key A unique identifier\n     */\n    PreferenceStorage.prototype.remove = function (key) {\n        // remove value from JSON storage\n        delete this._json[key];\n        _commit();\n    };\n    \n    /**\n     * Assigns a value for a key. Overwrites existing value if present.\n     * @param {!string} key A unique identifier\n     * @param {object} value A valid JSON value\n     */\n    PreferenceStorage.prototype.setValue = function (key, value) {\n        if (_validateJSONPair(key, value)) {\n            this._json[key] = value;\n            _commit();\n        }\n    };\n    \n    /**\n     * Retreive the value associated with the specified key.\n     * @param {!string} key Key name to lookup.\n     * @return {object} Returns the value for the key or undefined.\n     */\n    PreferenceStorage.prototype.getValue = function (key) {\n        return this._json[key];\n    };\n    \n    /**\n     * Return all name-value pairs as a single JSON object.\n     * @return {!object} JSON object containing name/value pairs for all keys\n     *  in this PreferenceStorage object.\n     */\n    PreferenceStorage.prototype.getAllValues = function () {\n        return JSON.parse(JSON.stringify(this._json));\n    };\n    \n    /**\n     * Writes name-value pairs from a JSON object as preference properties.\n     * Invalid JSON values throw an error and all changes are discarded.\n     *\n     * @param {!object} obj A JSON object with zero or more preference properties to write.\n     * @param {boolean} append Defaults to false. When true, properties in the JSON object\n     *  overwrite and/or append to the existing set of preference properties. When false,\n     *  all existing preferences are deleted before writing new properties from the JSON object.\n     */\n    PreferenceStorage.prototype.setAllValues = function (obj, append) {\n        var self = this,\n            error = null;\n        \n        // validate all name/value pairs before committing\n        $.each(obj, function (key, value) {\n            try {\n                _validateJSONPair(key, value);\n            } catch (err) {\n                // fail fast\n                error = err;\n                return false;\n            }\n        });\n        \n        // skip changes if any error is detected\n        if (error) {\n            throw error;\n        }\n        \n        // delete all exiting properties if not appending\n        if (!append) {\n            $.each(this._json, function (key, value) {\n                delete self._json[key];\n            });\n        }\n        \n        // copy properties from incoming JSON object\n        $.each(obj, function (key, value) {\n            self._json[key] = value;\n        });\n        \n        _commit();\n    };\n    \n    exports.PreferenceStorage = PreferenceStorage;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, localStorage */\n\n/**\n * PreferencesManager\n *\n */\ndefine('preferences/PreferencesManager',['require','exports','module','preferences/PreferenceStorage'],function (require, exports, module) {\n    \n    \n    var PreferenceStorage = require(\"preferences/PreferenceStorage\").PreferenceStorage;\n    \n    var PREFERENCES_KEY = \"com.adobe.brackets.preferences\";\n\n    // Private Properties\n    var preferencesKey,\n        prefStorage,\n        persistentStorage,\n        doLoadPreferences   = false;\n\n    /**\n     * Retreive preferences data for the given clientID.\n     *\n     * @param {string} clientID Unique identifier\n     * @param {string} defaults Default preferences stored as JSON\n     * @return {PreferenceStorage} \n     */\n    function getPreferenceStorage(clientID, defaults) {\n        if ((clientID === undefined) || (clientID === null)) {\n            throw new Error(\"Invalid clientID\");\n        }\n\n        var prefs = prefStorage[clientID];\n\n        if (prefs === undefined) {\n            // create a new empty preferences object\n            prefs = (defaults && JSON.stringify(defaults)) ? defaults : {};\n            prefStorage[clientID] = prefs;\n        }\n\n        return new PreferenceStorage(clientID, prefs);\n    }\n\n    /**\n     * Save all preference clients.\n     */\n    function savePreferences() {\n        // save all preferences\n        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));\n    }\n\n    /**\n     * @private\n     * Reset preferences and callbacks\n     */\n    function _reset() {\n        prefStorage = {};\n\n        // Note that storage.clear() is not used. Production and unit test code\n        // both rely on the same backing storage but unique item keys.\n        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));\n    }\n\n    /**\n     * @private\n     * Initialize persistent storage implementation\n     */\n    function _initStorage(storage) {\n        persistentStorage = storage;\n\n        if (doLoadPreferences) {\n            prefStorage = JSON.parse(persistentStorage.getItem(preferencesKey));\n        }\n\n        // initialize empty preferences if none were found in storage\n        if (!prefStorage) {\n            _reset();\n        }\n    }\n\n    // Check localStorage for a preferencesKey. Production and unit test keys\n    // are used to keep preferences separate within the same storage implementation.\n    preferencesKey = localStorage.getItem(\"preferencesKey\");\n\n    if (!preferencesKey) {\n        // use default key if none is found\n        preferencesKey = PREFERENCES_KEY;\n        doLoadPreferences = true;\n    } else {\n        // using a non-default key, check for additional settings\n        doLoadPreferences = !!(localStorage.getItem(\"doLoadPreferences\"));\n    }\n\n    // Use localStorage by default\n    _initStorage(localStorage);\n\n    // Public API\n    exports.getPreferenceStorage    = getPreferenceStorage;\n    exports.savePreferences         = savePreferences;\n\n    // Unit test use only\n    exports._reset                  = _reset;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n /**\n  * Manages global application commands that can be called from menu items, key bindings, or subparts\n  * of the application.\n  */\ndefine('command/CommandManager',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * Map of all registered global commands\n     * @type Object.<commandID: string, Command>\n     */\n    var _commands = {};\n    \n    /**\n     * Temporary copy of commands map for restoring after testing\n     * TODO (issue #1039): implement separate require contexts for unit tests\n     * @type Object.<commandID: string, Command>\n     */\n    var _commandsOriginal = {};\n    \n    /**\n     * @constructor\n     * @private\n     *\n     * @param {string} name - text that will be displayed in the UI to represent command\n     * @param {string} id\n     * @param {function} commandFn - the function that is called when the command is executed.\n     *\n     * TODO: where should this be triggered, The Command or Exports?\n     * Events:\n     *      enabledStateChange\n     *      checkedStateChange\n     *      keyBindingAdded\n     *      keyBindingRemoved\n     */\n    function Command(name, id, commandFn) {\n        this._name = name;\n        this._id = id;\n        this._commandFn = commandFn;\n        this._checked = undefined;\n        this._enabled = true;\n    }\n\n    /** @return {Command} */\n    Command.prototype.getID = function () {\n        return this._id;\n    };\n\n    /**\n     * Executes the command. Additional arguments are passed to the executing function\n     *\n     * @return {$.Promise} a jQuery promise that will be resolved when the command completes.\n     */\n    Command.prototype.execute = function () {\n        if (!this._enabled) {\n            return;\n        }\n        \n        var result = this._commandFn.apply(this, arguments);\n        if (!result) {\n            return (new $.Deferred()).resolve().promise();\n        } else {\n            return result;\n        }\n    };\n\n    /** @return {boolean} */\n    Command.prototype.getEnabled = function () {\n        return this._enabled;\n    };\n\n    /** \n     * Sets enabled state of Command and dispatches \"enabledStateChange\"\n     * when the enabled state changes.\n     * @param {boolean} enabled\n     */\n    Command.prototype.setEnabled = function (enabled) {\n        var changed = this._enabled !== enabled;\n        this._enabled = enabled;\n\n        if (changed) {\n            $(this).triggerHandler(\"enabledStateChange\");\n        }\n    };\n\n    /** \n     * Sets enabled state of Command and dispatches \"checkedStateChange\"\n     * when the enabled state changes.\n     * @param {boolean} checked\n     */\n    Command.prototype.setChecked = function (checked) {\n        var changed = this._checked !== checked;\n        this._checked = checked;\n\n        if (changed) {\n            $(this).triggerHandler(\"checkedStateChange\");\n        }\n    };\n\n    /** @return {boolean} */\n    Command.prototype.getChecked = function () {\n        return this._checked;\n    };\n\n    /**\n     * Sets the name of the Command and dispatches \"nameChange\" so that\n     * UI that reflects the command name can update.\n     * \n     * Note, a Command name can appear in either HTML or native UI\n     * so HTML tags should not be used. To add a Unicode character,\n     * use \\uXXXX instead of an HTML entity.\n     * \n     * @param {string} name\n     */\n    Command.prototype.setName = function (name) {\n        var changed = this._name !== name;\n        this._name = name;\n\n        if (changed) {\n            $(this).triggerHandler(\"nameChange\");\n        }\n    };\n\n    /** @return {string} */\n    Command.prototype.getName = function () {\n        return this._name;\n    };\n\n\n\n    /**\n     * Registers a global command.\n     * @param {string} name - text that will be displayed in the UI to represent command\n     * @param {string} id - unique identifier for command.\n     *      Core commands in Brackets use a simple command title as an id, for example \"open.file\".\n     *      Extensions should use the following format: \"author.myextension.mycommandname\". \n     *      For example, \"lschmitt.csswizard.format.css\".\n     * @param {function(...)} commandFn - the function to call when the command is executed. Any arguments passed to\n     *     execute() (after the id) are passed as arguments to the function. If the function is asynchronous,\n     *     it must return a jQuery promise that is resolved when the command completes. Otherwise, the\n     *     CommandManager will assume it is synchronous, and return a promise that is already resolved.\n     * @return {?Command}\n     */\n    function register(name, id, commandFn) {\n        if (_commands[id]) {\n            console.log(\"Attempting to register an already-registered command: \" + id);\n            return null;\n        }\n        if (!name || !id || !commandFn) {\n            throw new Error(\"Attempting to register a command with a missing name, id, or command function:\" + name + \" \" + id);\n        }\n\n        var command = new Command(name, id, commandFn);\n        _commands[id] = command;\n        return command;\n    }\n\n    /**\n     * Clear all commands for unit testing, but first make copy of commands so that\n     * they can be restored afterward\n     */\n    function _testReset() {\n        _commandsOriginal = _commands;\n        _commands = {};\n    }\n\n    /**\n     * Restore original commands after test and release copy\n     */\n    function _testRestore() {\n        _commands = _commandsOriginal;\n        _commandsOriginal = {};\n    }\n    \n    /**\n     * Retrieves a Command object by id\n     * @param {string} id\n     * @return {Command}\n     */\n    function get(id) {\n        return _commands[id];\n    }\n    \n    /**\n     * Returns the ids of all registered commands\n     * @return {Array.<string>}\n     */\n    function getAll() {\n        return Object.keys(_commands);\n    }\n\n    /**\n     * Looks up and runs a global command. Additional arguments are passed to the command.\n     *\n     * @param {string} id The ID of the command to run.\n     * @return {$.Promise} a jQuery promise that will be resolved when the command completes.\n     */\n    function execute(id) {\n        var command = _commands[id];\n        if (command) {\n            return command.execute.apply(command, Array.prototype.slice.call(arguments, 1));\n        } else {\n            return (new $.Deferred()).reject().promise();\n        }\n    }\n\n    // Define public API\n    exports.register        = register;\n    exports.execute         = execute;\n    exports.get             = get;\n    exports.getAll          = getAll;\n    exports._testReset      = _testReset;\n    exports._testRestore    = _testRestore;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\ndefine('command/Commands',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * List of constants for global command IDs.\n     */\n\n    // FILE\n    exports.FILE_NEW                    = \"file.new\";\n    exports.FILE_OPEN                   = \"file.open\";\n    exports.FILE_OPEN_FOLDER            = \"file.openFolder\";\n    exports.FILE_SAVE                   = \"file.save\";\n    exports.FILE_SAVE_ALL               = \"file.saveAll\";\n    exports.FILE_CLOSE                  = \"file.close\";\n    exports.FILE_CLOSE_ALL              = \"file.close_all\";\n    exports.FILE_CLOSE_WINDOW           = \"file.close_window\"; // string must MATCH string in native code (brackets_extensions)\n    exports.FILE_ADD_TO_WORKING_SET     = \"file.addToWorkingSet\";\n    exports.FILE_LIVE_FILE_PREVIEW      = \"file.liveFilePreview\";\n    exports.FILE_QUIT                   = \"file.quit\"; // string must MATCH string in native code (brackets_extensions)\n\n    // EDIT\n    exports.EDIT_UNDO                   = \"edit.undo\";\n    exports.EDIT_REDO                   = \"edit.redo\";\n    exports.EDIT_CUT                    = \"edit.cut\";\n    exports.EDIT_COPY                   = \"edit.copy\";\n    exports.EDIT_PASTE                  = \"edit.paste\";\n    exports.EDIT_SELECT_ALL             = \"edit.selectAll\";\n    exports.EDIT_FIND                   = \"edit.find\";\n    exports.EDIT_FIND_IN_FILES          = \"edit.findInFiles\";\n    exports.EDIT_FIND_NEXT              = \"edit.findNext\";\n    exports.EDIT_FIND_PREVIOUS          = \"edit.findPrevious\";\n    exports.EDIT_REPLACE                = \"edit.replace\";\n    exports.EDIT_INDENT                 = \"edit.indent\";\n    exports.EDIT_UNINDENT               = \"edit.unindent\";\n    exports.EDIT_DUPLICATE              = \"edit.duplicate\";\n    exports.EDIT_LINE_COMMENT           = \"edit.lineComment\";\n    exports.EDIT_LINE_UP                = \"edit.lineUp\";\n    exports.EDIT_LINE_DOWN              = \"edit.lineDown\";\n    exports.TOGGLE_USE_TAB_CHARS        = \"debug.useTabChars\";\n\n    // VIEW\n    exports.VIEW_HIDE_SIDEBAR           = \"view.toggleSidebar\";\n    exports.VIEW_INCREASE_FONT_SIZE     = \"view.increaseFontSize\";\n    exports.VIEW_DECREASE_FONT_SIZE     = \"view.decreaseFontSize\";\n    exports.VIEW_RESTORE_FONT_SIZE      = \"view.restoreFontSize\";\n    exports.TOGGLE_JSLINT               = \"debug.jslint\";\n    \n    // Navigate\n    exports.NAVIGATE_NEXT_DOC           = \"navigate.nextDoc\";\n    exports.NAVIGATE_PREV_DOC           = \"navigate.prevDoc\";\n    exports.NAVIGATE_QUICK_OPEN         = \"navigate.quickOpen\";\n    exports.NAVIGATE_GOTO_DEFINITION    = \"navigate.gotoDefinition\";\n    exports.NAVIGATE_GOTO_LINE          = \"navigate.gotoLine\";\n    exports.TOGGLE_QUICK_EDIT           = \"navigate.toggleQuickEdit\";\n    exports.QUICK_EDIT_NEXT_MATCH       = \"navigate.nextMatch\";\n    exports.QUICK_EDIT_PREV_MATCH       = \"navigate.previousMatch\";\n\n    // Debug\n    exports.DEBUG_REFRESH_WINDOW        = \"debug.refreshWindow\"; // string must MATCH string in native code (brackets_extensions)\n    exports.DEBUG_SHOW_DEVELOPER_TOOLS  = \"debug.showDeveloperTools\";\n    exports.DEBUG_RUN_UNIT_TESTS        = \"debug.runUnitTests\";\n    exports.DEBUG_SHOW_PERF_DATA        = \"debug.showPerfData\";\n    exports.DEBUG_NEW_BRACKETS_WINDOW   = \"debug.newBracketsWindow\";\n    exports.DEBUG_SHOW_EXT_FOLDER       = \"debug.showExtensionsFolder\";\n    exports.DEBUG_SWITCH_LANGUAGE       = \"debug.switchLanguage\";\n    exports.CHECK_FOR_UPDATE            = \"app.checkForUpdate\";\n\n\t// Command that does nothing. Can be used for place holder menuItems\n    \n    exports.HELP_ABOUT                  = \"help.about\";\n\n    // File shell callbacks\n    exports.APP_ABORT_QUIT              = \"app.abort_quit\"; // string must MATCH string in native code (appshell_extensions)\n});\n\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */\n/*global define, $, brackets, window */\n\n/**\n * Manages the mapping of keyboard inputs to commands.\n */\ndefine('command/KeyBindingManager',['require','exports','module','command/CommandManager'],function (require, exports, module) {\n    \n\n    var CommandManager = require(\"command/CommandManager\");\n\n    /**\n     * Maps normalized shortcut descriptor to key binding info.\n     * @type {!Object.<string, {commandID: string, key: string, displayKey: string}>}\n     */\n    var _keyMap = {};\n\n    /**\n     * Maps commandID to the list of shortcuts that are bound to it.\n     * @type {!Object.<string, Array.<{key: string, displayKey: string}>>}\n     */\n    var _commandMap = {};\n\n    /**\n     * Allow clients to toggle key binding\n     */\n    var _enabled = true;\n\n    /**\n     * @private\n     */\n    function _reset() {\n        _keyMap = {};\n        _commandMap = {};\n    }\n\n    /**\n     * @private\n     * Initialize an empty keymap as the current keymap. It overwrites the current keymap if there is one.\n     * builds the keyDescriptor string from the given parts\n     * @param {boolean} hasCtrl Is Ctrl key enabled\n     * @param {boolean} hasAlt Is Alt key enabled\n     * @param {boolean} hasShift Is Shift key enabled\n     * @param {string} key The key that's pressed\n     * @return {string} The normalized key descriptor\n     */\n    function _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key) {\n        if (!key) {\n            console.log(\"KeyBindingManager _buildKeyDescriptor() - No key provided!\");\n            return \"\";\n        }\n        \n        var keyDescriptor = [];\n       \n        if (hasMacCtrl) {\n            keyDescriptor.push(\"Ctrl\");\n        }\n        if (hasAlt) {\n            keyDescriptor.push(\"Alt\");\n        }\n        if (hasShift) {\n            keyDescriptor.push(\"Shift\");\n        }\n\n        if (hasCtrl) {\n            // Windows display Ctrl first, Mac displays Command symbol last\n            if (brackets.platform === \"mac\") {\n                keyDescriptor.push(\"Cmd\");\n            } else {\n                keyDescriptor.unshift(\"Ctrl\");\n            }\n        }\n\n        keyDescriptor.push(key);\n        \n        return keyDescriptor.join(\"-\");\n    }\n    \n    \n    /**\n     * normalizes the incoming key descriptor so the modifier keys are always specified in the correct order\n     * @param {string} The string for a key descriptor, can be in any order, the result will be Ctrl-Alt-Shift-<Key>\n     * @return {string} The normalized key descriptor or null if the descriptor invalid\n     */\n    function normalizeKeyDescriptorString(origDescriptor) {\n        var hasMacCtrl = false,\n            hasCtrl = false,\n            hasAlt = false,\n            hasShift = false,\n            key = \"\",\n            error = false;\n\n        function _compareModifierString(left, right, previouslyFound, origDescriptor) {\n            if (!left || !right) {\n                return false;\n            }\n            left = left.trim().toLowerCase();\n            right = right.trim().toLowerCase();\n            var matched = (left.length > 0 && left === right);\n            if (matched && previouslyFound) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Modifier defined twice: \" + origDescriptor);\n            }\n            return matched;\n        }\n        \n        origDescriptor.split(\"-\").forEach(function parseDescriptor(ele, i, arr) {\n            if (_compareModifierString(\"ctrl\", ele, hasCtrl)) {\n                if (brackets.platform === \"mac\") {\n                    hasMacCtrl = true;\n                } else {\n                    hasCtrl = true;\n                }\n            } else if (_compareModifierString(\"cmd\", ele, hasCtrl, origDescriptor)) {\n                hasCtrl = true;\n            } else if (_compareModifierString(\"alt\", ele, hasAlt, origDescriptor)) {\n                hasAlt = true;\n            } else if (_compareModifierString(\"opt\", ele, hasAlt, origDescriptor)) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Opt getting mapped to Alt from: \" + origDescriptor);\n                hasAlt = true;\n            } else if (_compareModifierString(\"shift\", ele, hasShift, origDescriptor)) {\n                hasShift = true;\n            } else if (key.length > 0) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Multiple keys defined. Using key: \" + key + \" from: \" + origDescriptor);\n                error = true;\n            } else {\n                key = ele;\n            }\n        });\n        \n        if (error) {\n            return null;\n        }\n\n        // Check to see if the binding is for \"-\".\n        if (key === \"\" && origDescriptor.search(/^.+--$/) !== -1) {\n            key = \"-\";\n        }\n        \n        // '+' char is valid if it's the only key. Keyboard shortcut strings should use\n        // unicode characters (unescaped). Keyboard shortcut display strings may use\n        // unicode escape sequences (e.g. \\u20AC euro sign)\n        if ((key.indexOf(\"+\")) >= 0 && (key.length > 1)) {\n            return null;\n        }\n        \n        return _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key);\n    }\n    \n    /**\n     * @private\n     * Looks for keycodes that have os-inconsistent keys and fixes them.\n     * @param {number} The keycode from the keyboard event.\n     * @param {string} The current best guess at what the key is.\n     * @return {string} If the key is OS-inconsistent, the correct key; otherwise, the original key.\n     **/\n    function _mapKeycodeToKey(keycode, key) {\n        switch (keycode) {\n        case 186:\n            return \";\";\n        case 187:\n            return \"=\";\n        case 188:\n            return \",\";\n        case 189:\n            return \"-\";\n        case 190:\n            return \".\";\n        case 191:\n            return \"/\";\n        case 192:\n            return \"`\";\n        case 219:\n            return \"[\";\n        case 220:\n            return \"\\\\\";\n        case 221:\n            return \"]\";\n        case 222:\n            return \"'\";\n        default:\n            return key;\n        }\n    }\n    \n    /**\n     * Takes a keyboard event and translates it into a key in a key map\n     */\n    function _translateKeyboardEvent(event) {\n        var hasMacCtrl = (brackets.platform === \"win\") ? false : (event.ctrlKey),\n            hasCtrl = (brackets.platform === \"win\") ? (event.ctrlKey) : (event.metaKey),\n            hasAlt = (event.altKey),\n            hasShift = (event.shiftKey),\n            key = String.fromCharCode(event.keyCode);\n        \n        //From the W3C, if we can get the KeyboardEvent.keyIdentifier then look here\n        //As that will let us use keys like then function keys \"F5\" for commands. The\n        //full set of values we can use is here\n        //http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set\n        var ident = event.keyIdentifier;\n        if (ident) {\n            if (ident.charAt(0) === \"U\" && ident.charAt(1) === \"+\") {\n                //This is a unicode code point like \"U+002A\", get the 002A and use that\n                key = String.fromCharCode(parseInt(ident.substring(2), 16));\n            } else {\n                //This is some non-character key, just use the raw identifier\n                key = ident;\n            }\n        }\n        \n        // Translate some keys to their common names\n        if (key === \"\\t\") {\n            key = \"Tab\";\n        } else if (key === \" \") {\n            key = \"Space\";\n        } else {\n            key = _mapKeycodeToKey(event.keyCode, key);\n        }\n\n        return _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key);\n    }\n    \n    /**\n     * Convert normalized key representation to display appropriate for platform.\n     * @param {!string} descriptor Normalized key descriptor.\n     * @return {!string} Display/Operating system appropriate string\n     */\n    function formatKeyDescriptor(descriptor) {\n        var displayStr;\n        \n        if (brackets.platform === \"mac\") {\n            displayStr = descriptor.replace(/-/g, \"\");          // remove dashes\n            displayStr = displayStr.replace(\"Ctrl\", \"\\u2303\");  // Ctrl > control symbol\n            displayStr = displayStr.replace(\"Cmd\", \"\\u2318\");   // Cmd > command symbol\n            displayStr = displayStr.replace(\"Shift\", \"\\u21E7\"); // Shift > shift symbol\n            displayStr = displayStr.replace(\"Alt\", \"\\u2325\");   // Alt > option symbol\n        } else {\n            displayStr = descriptor.replace(/-/g, \"+\");\n        }\n\n        return displayStr;\n    }\n\n    /**\n     * @private\n     * @param {string} A normalized key-description string.\n     * @return {boolean} true if the key is already assigned, false otherwise.\n     */\n    function _isKeyAssigned(key) {\n        return (_keyMap[key] !== undefined);\n    }\n\n    /**\n     * @private\n     *\n     * @param {string} commandID\n     * @param {string|{{key: string, displayKey: string}}} keyBinding - a single shortcut.\n     * @param {?string} platform - undefined indicates all platforms\n     * @return {?{key: string, displayKey:String}} Returns a record for valid key bindings\n     */\n    function _addBinding(commandID, keyBinding, platform) {\n        var key,\n            result = null,\n            normalized,\n            normalizedDisplay,\n            explicitPlatform = keyBinding.platform || platform,\n            targetPlatform = explicitPlatform || brackets.platform,\n            command;\n        \n        // skip if this binding doesn't match the current platform\n        if (targetPlatform !== brackets.platform) {\n            return null;\n        }\n        \n        key = (keyBinding.key) || keyBinding;\n        if (brackets.platform === \"mac\" && explicitPlatform === undefined) {\n            key = key.replace(\"Ctrl\", \"Cmd\");\n            if (keyBinding.displayKey !== undefined) {\n                keyBinding.displayKey = keyBinding.displayKey.replace(\"Ctrl\", \"Cmd\");\n            }\n        }\n        normalized = normalizeKeyDescriptorString(key);\n        \n        // skip if the key binding is invalid \n        if (!normalized) {\n            console.log(\"Failed to normalize \" + key);\n            return null;\n        }\n        \n        // skip if the key is already assigned\n        if (_isKeyAssigned(normalized)) {\n            console.log(\"Cannot assign \" + normalized + \" to \" + commandID +\n                        \". It is already assigned to \" + _keyMap[normalized]);\n            return null;\n        }\n        \n        // optional display-friendly string (e.g. CMD-+ instead of CMD-=)\n        normalizedDisplay = (keyBinding.displayKey) ? normalizeKeyDescriptorString(keyBinding.displayKey) : normalized;\n        \n        // 1-to-many commandID mapping to key binding\n        if (!_commandMap[commandID]) {\n            _commandMap[commandID] = [];\n        }\n        \n        result = {key: normalized, displayKey: normalizedDisplay};\n        _commandMap[commandID].push(result);\n        \n        // 1-to-1 key binding to commandID\n        _keyMap[normalized] = {commandID: commandID, key: normalized, displayKey: normalizedDisplay};\n        \n        // notify listeners\n        command = CommandManager.get(commandID);\n        \n        if (command) {\n            $(command).triggerHandler(\"keyBindingAdded\", [result]);\n        }\n        \n        return result;\n    }\n\n    /**\n     * Returns a copy of the keymap\n     * @returns {!Object.<string, {commandID: string, key: string, displayKey: string}>}\n     */\n    function getKeymap() {\n        return $.extend({}, _keyMap);\n    }\n\n    /**\n     * Process the keybinding for the current key.\n     *\n     * @param {string} A key-description string.\n     * @return {boolean} true if the key was processed, false otherwise\n     */\n    function handleKey(key) {\n        if (_enabled && _keyMap[key]) {\n            CommandManager.execute(_keyMap[key].commandID);\n            return true;\n        }\n        return false;\n    }\n\n    // TODO (issue #414): Replace this temporary fix with a more robust solution to handle focus and modality\n    /**\n     * Enable or disable key bindings. Clients such as dialogs may wish to disable \n     * global key bindings temporarily.\n     *\n     * @param {string} A key-description string.\n     * @return {boolean} true if the key was processed, false otherwise\n     */\n    function setEnabled(value) {\n        _enabled = value;\n    }\n\n    /**\n     * Add one or more key bindings to a particular Command.\n     * \n     * @param {!string} commandID\n     * @param {?({key: string, displayKey: string} | Array.<{key: string, displayKey: string, platform: string)}>}  keyBindings - a single key binding\n     *      or an array of keybindings. Example: \"Shift-Cmd-F\". Mac and Win key equivalents are automatically\n     *      mapped to each other. Use displayKey property to display a different string (e.g. \"CMD+\" instead of \"CMD=\").\n     * @param {?string} platform - the target OS of the keyBindings either \"mac\" or \"win\". If undefined, all platforms will use\n     *      the key binding. Ignored if keyBindings is passed an Array.\n     * @return {{key: string, displayKey:String}|Array.<{key: string, displayKey:String}>} Returns record(s) for valid key binding(s)\n     */\n    function addBinding(commandID, keyBindings, platform) {\n        if ((commandID === null) || (commandID === undefined) || !keyBindings) {\n            return;\n        }\n        \n        var normalizedBindings = [],\n            targetPlatform,\n            results;\n\n        if (Array.isArray(keyBindings)) {\n            var keyBinding;\n            results = [];\n                                            \n            keyBindings.forEach(function (keyBindingRequest) {\n                keyBinding = _addBinding(commandID, keyBindingRequest, keyBindingRequest.platform);\n                \n                if (keyBinding) {\n                    results.push(keyBinding);\n                }\n            });\n        } else {\n            results = _addBinding(commandID, keyBindings, platform);\n        }\n        \n        return results;\n    }\n\n    /**\n     * Remove a key binding from _keymap\n     *\n     * @param {!string} key - a key-description string that may or may not be normalized.\n     * @param {?string} platform - OS from which to remove the binding (all platforms if unspecified)\n     */\n    function removeBinding(key, platform) {\n        if (!key || ((platform !== null) && (platform !== undefined) && (platform !== brackets.platform))) {\n            return;\n        }\n\n        var normalizedKey = normalizeKeyDescriptorString(key);\n        \n        if (!normalizedKey) {\n            console.log(\"Fail to nomalize \" + key);\n        } else if (_isKeyAssigned(normalizedKey)) {\n            var binding = _keyMap[normalizedKey],\n                command = CommandManager.get(binding.commandID),\n                bindings = _commandMap[binding.commandID];\n            \n            // delete key binding record\n            delete _keyMap[normalizedKey];\n            \n            if (bindings) {\n                // delete mapping from command to key binding\n                _commandMap[binding.commandID] = bindings.filter(function (b) {\n                    return (b.key !== normalizedKey);\n                });\n    \n                if (command) {\n                    $(command).triggerHandler(\"keyBindingRemoved\", [{key: normalizedKey, displayKey: binding.displayKey}]);\n                }\n            }\n        }\n    }\n    \n    /**\n     * Retrieve key bindings currently associated with a command\n     *\n     * @param {!string} command - A command ID\n     * @return {!Array.<{{key: string, displayKey: string}}>} An array of associated key bindings.\n     */\n    function getKeyBindings(commandID) {\n        var bindings = _commandMap[commandID];\n        return bindings || [];\n    }\n\n    /**\n     * Install keydown event listener.\n     */\n    function init() {\n        // init\n        window.document.body.addEventListener(\n            \"keydown\",\n            function (event) {\n                if (handleKey(_translateKeyboardEvent(event))) {\n                    event.stopPropagation();\n                }\n            },\n            true\n        );\n    }\n\n    // unit test only\n    exports._reset = _reset;\n\n    // Define public API\n    exports.init = init;\n    exports.getKeymap = getKeymap;\n    exports.handleKey = handleKey;\n    exports.setEnabled = setEnabled;\n    exports.addBinding = addBinding;\n    exports.removeBinding = removeBinding;\n    exports.formatKeyDescriptor = formatKeyDescriptor;\n    exports.getKeyBindings = getKeyBindings;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window */\n\n/**\n * Utilities for creating and managing standard modal dialogs.\n */\ndefine('widgets/Dialogs',['require','exports','module','command/KeyBindingManager'],function (require, exports, module) {\n    \n    \n    var KeyBindingManager = require(\"command/KeyBindingManager\");\n\n    var DIALOG_BTN_CANCEL = \"cancel\",\n        DIALOG_BTN_OK = \"ok\",\n        DIALOG_BTN_DONTSAVE = \"dontsave\",\n        DIALOG_CANCELED = \"_canceled\",\n        DIALOG_BTN_DOWNLOAD = \"download\";\n    \n    // TODO: (issue #258) In future, we should templatize the HTML for the dialogs rather than having \n    // it live directly in the HTML.\n    var DIALOG_ID_ERROR = \"error-dialog\",\n        DIALOG_ID_SAVE_CLOSE = \"save-close-dialog\",\n        DIALOG_ID_EXT_CHANGED = \"ext-changed-dialog\",\n        DIALOG_ID_EXT_DELETED = \"ext-deleted-dialog\",\n        DIALOG_ID_LIVE_DEVELOPMENT = \"live-development-error-dialog\",\n        DIALOG_ID_ABOUT = \"about-dialog\",\n        DIALOG_ID_UPDATE = \"update-dialog\";\n\n    function _dismissDialog(dlg, buttonId) {\n        dlg.data(\"buttonId\", buttonId);\n        dlg.modal(true).hide();\n    }\n    \n    function _hasButton(dlg, buttonId) {\n        return dlg.find(\"[data-button-id='\" + buttonId + \"']\");\n    }\n\n    var _handleKeyDown = function (e) {\n        var primaryBtn = this.find(\".primary\"),\n            buttonId = null,\n            which = String.fromCharCode(e.which);\n        \n        if (e.which === 13) {\n            // Click primary button\n            if (primaryBtn) {\n                buttonId = primaryBtn.attr(\"data-button-id\");\n            }\n        } else if (e.which === 32) {\n            // Space bar on focused button\n            this.find(\".dialog-button:focus\").click();\n        } else if (brackets.platform === \"mac\") {\n            // CMD+D Don't Save\n            if (e.metaKey && (which === \"D\")) {\n                if (_hasButton(this, DIALOG_BTN_DONTSAVE)) {\n                    buttonId = DIALOG_BTN_DONTSAVE;\n                }\n            // FIXME (issue #418) CMD+. Cancel swallowed by native shell\n            } else if (e.metaKey && (e.which === 190)) {\n                buttonId = DIALOG_BTN_CANCEL;\n            }\n        } else { // if (brackets.platform === \"win\") {\n            // 'N' Don't Save\n            if (which === \"N\") {\n                if (_hasButton(this, DIALOG_BTN_DONTSAVE)) {\n                    buttonId = DIALOG_BTN_DONTSAVE;\n                }\n            }\n        }\n        \n        if (buttonId) {\n            _dismissDialog(this, buttonId);\n        } else if (!($.contains(this.get(0), e.target)) ||\n                  ($(e.target).filter(\":input\").length === 0)) {\n            // Stop the event if the target is not inside the dialog\n            // or if the target is not a form element.\n            // TODO (issue #414): more robust handling of dialog scoped\n            //                    vs. global key bindings\n            e.stopPropagation();\n            e.preventDefault();\n        }\n    };\n    \n    /**\n     * General purpose modal dialog. Assumes that:\n     * -- the root tag of the dialog is marked with a unique class name (passed as dlgClass), as well as the\n     *    classes \"template modal hide\".\n     * -- the HTML for the dialog contains elements with \"title\" and \"message\" classes, as well as a number \n     *    of elements with \"dialog-button\" class, each of which has a \"data-button-id\".\n     *\n     * @param {string} dlgClass The class of the dialog node in the HTML.\n     * @param {string=} title The title of the error dialog. Can contain HTML markup. If unspecified, title in\n     *      the HTML template is used unchanged.\n     * @param {string=} message The message to display in the error dialog. Can contain HTML markup. If\n     *      unspecified, body in the HTML template is used unchanged.\n     * @return {$.Promise} a promise that will be resolved with the ID of the clicked button when the dialog\n     *     is dismissed. Never rejected.\n     */\n    function showModalDialog(dlgClass, title, message) {\n        var result = $.Deferred(),\n            promise = result.promise();\n        \n        // We clone the HTML rather than using it directly so that if two dialogs of the same\n        // type happen to show up, they can appear at the same time. (This is an edge case that\n        // shouldn't happen often, but we can't prevent it from happening since everything is\n        // asynchronous.)\n        var $dlg = $(\".\" + dlgClass + \".template\")\n            .clone()\n            .removeClass(\"template\")\n            .addClass(\"instance\")\n            .appendTo(window.document.body);\n        \n        if ($dlg.length === 0) {\n            throw new Error(\"Dialog id \" + dlgClass + \" does not exist\");\n        }\n\n        // Save the dialog promise for unit tests\n        $dlg.data(\"promise\", promise);\n\n        // Set title and message\n        if (title) {\n            $(\".dialog-title\", $dlg).html(title);\n        }\n        if (message) {\n            $(\".dialog-message\", $dlg).html(message);\n        }\n\n        var handleKeyDown = _handleKeyDown.bind($dlg);\n\n        // Pipe dialog-closing notification back to client code\n        $dlg.one(\"hidden\", function () {\n            var buttonId = $dlg.data(\"buttonId\");\n            if (!buttonId) {    // buttonId will be undefined if closed via Bootstrap's \"x\" button\n                buttonId = DIALOG_BTN_CANCEL;\n            }\n            \n            // Let call stack return before notifying that dialog has closed; this avoids issue #191\n            // if the handler we're triggering might show another dialog (as long as there's no\n            // fade-out animation)\n            window.setTimeout(function () {\n                result.resolve(buttonId);\n            }, 0);\n            \n            // Remove the dialog instance from the DOM.\n            $dlg.remove();\n\n            // Remove keydown event handler\n            window.document.body.removeEventListener(\"keydown\", handleKeyDown, true);\n            KeyBindingManager.setEnabled(true);\n        }).one(\"shown\", function () {\n            // Set focus to the default button\n            var primaryBtn = $dlg.find(\".primary\");\n\n            if (primaryBtn) {\n                primaryBtn.focus();\n            }\n\n            // Listen for dialog keyboard shortcuts\n            window.document.body.addEventListener(\"keydown\", handleKeyDown, true);\n            KeyBindingManager.setEnabled(false);\n        });\n        \n        // Click handler for buttons\n        $dlg.one(\"click\", \".dialog-button\", function (e) {\n            _dismissDialog($dlg, $(this).attr(\"data-button-id\"));\n        });\n\n        // Run the dialog\n        $dlg.modal({\n            backdrop: \"static\",\n            show: true,\n            keyboard: true\n        });\n\n        return promise;\n    }\n    \n    /**\n     * Immediately closes any dialog instances with the given class. The dialog callback for each instance will \n     * be called with the special buttonId DIALOG_CANCELED (note: callback is run asynchronously).\n     */\n    function cancelModalDialogIfOpen(dlgClass) {\n        $(\".\" + dlgClass + \".instance\").each(function (index, dlg) {\n            if ($(dlg).is(\":visible\")) {   // Bootstrap breaks if try to hide dialog that's already hidden\n                _dismissDialog($(dlg), DIALOG_CANCELED);\n            }\n        });\n    }\n    \n    exports.DIALOG_BTN_CANCEL = DIALOG_BTN_CANCEL;\n    exports.DIALOG_BTN_OK = DIALOG_BTN_OK;\n    exports.DIALOG_BTN_DONTSAVE = DIALOG_BTN_DONTSAVE;\n    exports.DIALOG_CANCELED = DIALOG_CANCELED;\n    exports.DIALOG_BTN_DOWNLOAD = DIALOG_BTN_DOWNLOAD;\n    \n    exports.DIALOG_ID_ERROR = DIALOG_ID_ERROR;\n    exports.DIALOG_ID_SAVE_CLOSE = DIALOG_ID_SAVE_CLOSE;\n    exports.DIALOG_ID_EXT_CHANGED = DIALOG_ID_EXT_CHANGED;\n    exports.DIALOG_ID_EXT_DELETED = DIALOG_ID_EXT_DELETED;\n    exports.DIALOG_ID_LIVE_DEVELOPMENT = DIALOG_ID_LIVE_DEVELOPMENT;\n    exports.DIALOG_ID_ABOUT = DIALOG_ID_ABOUT;\n    exports.DIALOG_ID_UPDATE = DIALOG_ID_UPDATE;\n    \n    exports.showModalDialog = showModalDialog;\n    exports.cancelModalDialogIfOpen = cancelModalDialogIfOpen;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, brackets, $, window */\n\n/**\n * This is a collection of utility functions for gathering performance data.\n */\ndefine('utils/PerfUtils',['require','exports','module'],function (require, exports, module) {\n    \n\n    /**\n     * Flag to enable/disable performance data gathering. Default is true (enabled)\n     * @type {boolean} enabled\n     */\n    var enabled = true;\n    \n    /**\n     * Performance data is stored in this hash object. The key is the name of the\n     * test (passed to markStart/addMeasurement), and the value is the time, in \n     * milliseconds, that it took to run the test. If multiple runs of the same test\n     * are made, the value is an Array with each run stored as an entry in the Array.\n     */\n    var perfData = {};\n    \n    /**\n     * Active tests. This is a hash of all tests that have had markStart() called,\n     * but have not yet had addMeasurement() called.\n     */\n    var activeTests = {};\n\n    /**\n     * Updatable tests. This is a hash of all tests that have had markStart() called,\n     * and have had updateMeasurement() called. Caller must explicitly remove tests\n     * from this list using finalizeMeasurement()\n     */\n    var updatableTests = {};\n    \n    /**\n     * Hash of measurement IDs\n     */\n    var perfMeasurementIds = {};\n    \n    /**\n     * @private\n     * A unique key to log performance data\n     *\n     * @param {!string} id Unique ID for this measurement name\n     * @param {!name} name A short name for this measurement\n     */\n    function PerfMeasurement(id, name) {\n        this.id = id;\n        this.name = name;\n    }\n    \n    /**\n     * Create a new PerfMeasurement key. Adds itself to the module export.\n     * Can be accessed on the module, e.g. PerfUtils.MY_PERF_KEY.\n     *\n     * @param {!string} id Unique ID for this measurement name\n     * @param {!name} name A short name for this measurement\n     */\n    function createPerfMeasurement(id, name) {\n        if (perfMeasurementIds[id]) {\n            throw new Error(\"Performance measurement \" + id + \" is already defined\");\n        }\n        \n        var pm = new PerfMeasurement(id, name);\n        exports[id] = pm;\n        \n        return pm;\n    }\n    \n    /**\n     * @private\n     * Convert a PerfMeasurement instance to it's id. Otherwise uses the string name for backwards compatibility.\n     */\n    function toMeasurementId(o) {\n        return (o instanceof PerfMeasurement) ? o.id : o;\n    }\n    \n    /**\n     * @private\n     * Helper function for markStart()\n     *\n     * @param {string} name  Timer name.\n     * @param {number} time  Timer start time.\n     */\n    function _markStart(name, time) {\n        if (activeTests[name]) {\n            throw new Error(\"Recursive tests with the same name are not supported. Timer name: \" + name);\n        }\n        \n        activeTests[name] = { startTime: time };\n    }\n    \n    /**\n     * Start a new named timer. The name should be as descriptive as possible, since\n     * this name will appear as an entry in the performance report. \n     * For example: \"Open file: /Users/brackets/src/ProjectManager.js\"\n     *\n     * Multiple timers can be opened simultaneously, but all open timers must have\n     * a unique name.\n     *\n     * @param {(string|Array.<string>)} name  Single name or an Array of names.\n     * @returns {string} timer name. Returned for convenience to store and use\n     *      for calling addMeasure(). Since name is often creating via concatenating\n     *      strings this return value allows clients to construct the name once.\n     */\n    function markStart(name) {\n        if (!enabled) {\n            return;\n        }\n\n        var time = brackets.app.getElapsedMilliseconds();\n        name = toMeasurementId(name);\n\n        // Array of names can be passed in to have multiple timers with same start time\n        if (Array.isArray(name)) {\n            var i;\n            for (i = 0; i < name.length; i++) {\n                _markStart(name[i], time);\n            }\n        } else {\n            _markStart(name, time);\n        }\n\n        return name;\n    }\n    \n    /**\n     * Stop a timer and add its measurements to the performance data.\n     *\n     * Multiple measurements can be stored for any given name. If there are\n     * multiple values for a name, they are stored in an Array.\n     *\n     * If markStart() was not called for the specified timer, the\n     * measured time is relative to app startup.\n     *\n     * @param {string} name  Timer name.\n     */\n    function addMeasurement(name) {\n        if (!enabled) {\n            return;\n        }\n\n        var elapsedTime = brackets.app.getElapsedMilliseconds();\n        name = toMeasurementId(name);\n        \n        if (activeTests[name]) {\n            elapsedTime -= activeTests[name].startTime;\n            delete activeTests[name];\n        }\n        \n        if (perfData[name]) {\n            // We have existing data, add to it\n            if (Array.isArray(perfData[name])) {\n                perfData[name].push(elapsedTime);\n            } else {\n                // Current data is a number, convert to Array\n                perfData[name] = [perfData[name], elapsedTime];\n            }\n        } else {\n            perfData[name] = elapsedTime;\n        }\n\n        // Real time logging\n        //console.log(name + \" \" + elapsedTime);\n    }\n\n    /**\n     * This function is similar to addMeasurement(), but it allows timing the\n     * *last* event, when you don't know which event will be the last one.\n     *\n     * Tests that are in the activeTests list, have not yet been added, so add\n     * measurements to the performance data, and move test to updatableTests list.\n     * A test is moved to the updatable list so that it no longer passes isActive().\n     *\n     * Tests that are already in the updatableTests list are updated.\n     *\n     * Caller must explicitly remove test from the updatableTests list using\n     * finalizeMeasurement().\n     *\n     * If markStart() was not called for the specified timer, there is no way to\n     * determine if this is the first or subsequent call, so the measurement is\n     * not updatable, and it is handled in addMeasurement().\n     *\n     * @param {string} name  Timer name.\n     */\n    function updateMeasurement(name) {\n        var elapsedTime = brackets.app.getElapsedMilliseconds();\n\n        name = toMeasurementId(name);\n\n        if (updatableTests[name]) {\n            // update existing measurement\n            elapsedTime -= updatableTests[name].startTime;\n            \n            // update\n            if (perfData[name] && Array.isArray(perfData[name])) {\n                // We have existing data and it's an array, so update the last entry\n                perfData[name][perfData[name].length - 1] = elapsedTime;\n            } else {\n                // No current data or a single entry, so set/update it\n                perfData[name] = elapsedTime;\n            }\n            \n        } else {\n            // not yet in updatable list\n\n            if (activeTests[name]) {\n                // save startTime in updatable list before addMeasurement() deletes it\n                updatableTests[name] = { startTime: activeTests[name].startTime };\n            }\n            \n            // let addMeasurement() handle the initial case\n            addMeasurement(name);\n        }\n    }\n\n    /**\n     * Remove timer from lists so next action starts a new measurement\n     * \n     * updateMeasurement may not have been called, so timer may be\n     * in either or neither list, but should never be in both.\n     *\n     * @param {string} name  Timer name.\n     */\n    function finalizeMeasurement(name) {\n\n        name = toMeasurementId(name);\n\n        if (activeTests[name]) {\n            delete activeTests[name];\n        }\n\n        if (updatableTests[name]) {\n            delete updatableTests[name];\n        }\n    }\n    \n    /**\n     * Returns whether a timer is active or not, where \"active\" means that\n     * timer has been started with addMark(), but has not been added to perfdata\n     * with addMeasurement().\n     *\n     * @param {string} name  Timer name.\n     * @return {boolean} Whether a timer is active or not.\n     */\n    function isActive(name) {\n        return (activeTests[name]) ? true : false;\n    }\n\n    /**\n      * Returns the performance data as a tab deliminted string\n      * @returns {string}\n      */\n    function getDelimitedPerfData() {\n        var getValue = function (entry) {\n            // return single value, or tab deliminted values for an array\n            if (Array.isArray(entry)) {\n                var i, values = \"\";\n                 \n                for (i = 0; i < entry.length; i++) {\n                    values += entry[i];\n                    if (i < entry.length - 1) {\n                        values += \", \";\n                    }\n                }\n                return values;\n            } else {\n                return entry;\n            }\n        };\n\n        var testName,\n            index,\n            result = \"\";\n        $.each(perfData, function (testName, entry) {\n            result += getValue(entry) + \"\\t\" + testName + \"\\n\";\n        });\n\n        return result;\n    }\n    \n    /**\n     * Returns the measured value for the given measurement name.\n     * @param {string|PerfMeasurement} name The measurement to retreive.\n     */\n    function getData(name) {\n        if (!name) {\n            return perfData;\n        }\n        \n        return perfData[toMeasurementId(name)];\n    }\n    \n    function searchData(regExp) {\n        var keys = Object.keys(perfData).filter(function (key) {\n            return regExp.test(key);\n        });\n        \n        var datas = [];\n        \n        keys.forEach(function (key) {\n            datas.push(perfData[key]);\n        });\n        \n        return datas;\n    }\n    \n    /**\n     * Clear all logs including metric data and active tests.\n     */\n    function clear() {\n        perfData = {};\n        activeTests = {};\n        updatableTests = {};\n    }\n    \n    // create performance measurement constants\n    createPerfMeasurement(\"INLINE_EDITOR_OPEN\", \"Open inline editor\");\n    createPerfMeasurement(\"INLINE_EDITOR_CLOSE\", \"Close inline editor\");\n    \n    // extensions may create additional measurement constants during their lifecycle\n\n    exports.addMeasurement          = addMeasurement;\n    exports.finalizeMeasurement     = finalizeMeasurement;\n    exports.isActive                = isActive;\n    exports.markStart               = markStart;\n    exports.getData                 = getData;\n    exports.searchData              = searchData;\n    exports.updateMeasurement       = updateMeasurement;\n    exports.getDelimitedPerfData    = getDelimitedPerfData;\n    exports.createPerfMeasurement   = createPerfMeasurement;\n    exports.clear                   = clear;\n});\n\n/**\n * @license RequireJS i18n 1.0.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n/*jslint regexp: false, nomen: false, plusplus: false, strict: false */\n/*global require: false, navigator: false, define: false */\n\n/**\n * This plugin handles i18n! prefixed modules. It does the following:\n *\n * 1) A regular module can have a dependency on an i18n bundle, but the regular\n * module does not want to specify what locale to load. So it just specifies\n * the top-level bundle, like \"i18n!nls/colors\".\n *\n * This plugin will load the i18n bundle at nls/colors, see that it is a root/master\n * bundle since it does not have a locale in its name. It will then try to find\n * the best match locale available in that master bundle, then request all the\n * locale pieces for that best match locale. For instance, if the locale is \"en-us\",\n * then the plugin will ask for the \"en-us\", \"en\" and \"root\" bundles to be loaded\n * (but only if they are specified on the master bundle).\n *\n * Once all the bundles for the locale pieces load, then it mixes in all those\n * locale pieces into each other, then finally sets the context.defined value\n * for the nls/colors bundle to be that mixed in locale.\n *\n * 2) A regular module specifies a specific locale to load. For instance,\n * i18n!nls/fr-fr/colors. In this case, the plugin needs to load the master bundle\n * first, at nls/colors, then figure out what the best match locale is for fr-fr,\n * since maybe only fr or just root is defined for that locale. Once that best\n * fit is found, all of its locale pieces need to have their bundles loaded.\n *\n * Once all the bundles for the locale pieces load, then it mixes in all those\n * locale pieces into each other, then finally sets the context.defined value\n * for the nls/fr-fr/colors bundle to be that mixed in locale.\n */\n(function () {\n    //regexp for reconstructing the master bundle name from parts of the regexp match\n    //nlsRegExp.exec(\"foo/bar/baz/nls/en-ca/foo\") gives:\n    //[\"foo/bar/baz/nls/en-ca/foo\", \"foo/bar/baz/nls/\", \"/\", \"/\", \"en-ca\", \"foo\"]\n    //nlsRegExp.exec(\"foo/bar/baz/nls/foo\") gives:\n    //[\"foo/bar/baz/nls/foo\", \"foo/bar/baz/nls/\", \"/\", \"/\", \"foo\", \"\"]\n    //so, if match[5] is blank, it means this is the top bundle definition.\n    var nlsRegExp = /(^.*(^|\\/)nls(\\/|$))([^\\/]*)\\/?([^\\/]*)/,\n        empty = {};\n\n    //Helper function to avoid repeating code. Lots of arguments in the\n    //desire to stay functional and support RequireJS contexts without having\n    //to know about the RequireJS contexts.\n    function addPart(locale, master, needed, toLoad, prefix, suffix) {\n        if (master[locale]) {\n            needed.push(locale);\n            if (master[locale] === true || master[locale] === 1) {\n                toLoad.push(prefix + locale + '/' + suffix);\n            }\n        }\n    }\n\n    function addIfExists(req, locale, toLoad, prefix, suffix) {\n        var fullName = prefix + locale + '/' + suffix;\n        if (require._fileExists(req.toUrl(fullName))) {\n            toLoad.push(fullName);\n        }\n    }\n\n    /**\n     * Simple function to mix in properties from source into target,\n     * but only if target does not already have a property of the same name.\n     * This is not robust in IE for transferring methods that match\n     * Object.prototype names, but the uses of mixin here seem unlikely to\n     * trigger a problem related to that.\n     */\n    function mixin(target, source, force) {\n        for (var prop in source) {\n            if (!(prop in empty) && (!(prop in target) || force)) {\n                target[prop] = source[prop];\n            }\n        }\n    }\n\n    define('i18n',{\n        version: '1.0.0',\n        /**\n         * Called when a dependency needs to be loaded.\n         */\n        load: function (name, req, onLoad, config) {\n            config = config || {};\n\n            var masterName,\n                match = nlsRegExp.exec(name),\n                prefix = match[1],\n                locale = match[4],\n                suffix = match[5],\n                parts = locale.split(\"-\"),\n                toLoad = [],\n                value = {},\n                i, part, current = \"\";\n\n            //If match[5] is blank, it means this is the top bundle definition,\n            //so it does not have to be handled. Locale-specific requests\n            //will have a match[4] value but no match[5]\n            if (match[5]) {\n                //locale-specific bundle\n                prefix = match[1];\n                masterName = prefix + suffix;\n            } else {\n                //Top-level bundle.\n                masterName = name;\n                suffix = match[4];\n                locale = config.locale || (config.locale =\n                        typeof navigator === \"undefined\" ? \"root\" :\n                        (navigator.language ||\n                         navigator.userLanguage || \"root\").toLowerCase());\n                parts = locale.split(\"-\");\n            }\n\n            if (config.isBuild) {\n                //Check for existence of all locale possible files and\n                //require them if exist.\n                toLoad.push(masterName);\n                addIfExists(req, \"root\", toLoad, prefix, suffix);\n                for (i = 0; (part = parts[i]); i++) {\n                    current += (current ? \"-\" : \"\") + part;\n                    addIfExists(req, current, toLoad, prefix, suffix);\n                }\n\n                req(toLoad, function () {\n                    onLoad();\n                });\n            } else {\n                //First, fetch the master bundle, it knows what locales are available.\n                req([masterName], function (master) {\n                    //Figure out the best fit\n                    var needed = [];\n\n                    //Always allow for root, then do the rest of the locale parts.\n                    addPart(\"root\", master, needed, toLoad, prefix, suffix);\n                    for (i = 0; (part = parts[i]); i++) {\n                        current += (current ? \"-\" : \"\") + part;\n                        addPart(current, master, needed, toLoad, prefix, suffix);\n                    }\n\n                    //Load all the parts missing.\n                    req(toLoad, function () {\n                        var i, partBundle;\n                        for (i = needed.length - 1; i > -1 && (part = needed[i]); i--) {\n                            partBundle = master[part];\n                            if (partBundle === true || partBundle === 1) {\n                                partBundle = req(prefix + part + '/' + suffix);\n                            }\n                            mixin(value, partBundle);\n                        }\n\n                        //All done, notify the loader.\n                        onLoad(value);\n                    });\n                });\n            }\n        }\n    });\n}());\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\ndefine('nls/strings',['require','exports','module'],function (require, exports, module) {\n    \n    \n    \n    // Code that needs to display user strings should call require(\"strings\") to load\n    // src/strings.js. This file will dynamically load strings.js for the specified brackets.locale.\n    //\n    // See the README.md file in this folder for information on how to add a new translation for\n    // another language or locale.\n    //\n    // TODO: dynamically populate the local prefix list below?\n    module.exports = {\n        root: true,\n        \"de\": true,\n        \"fr\": true\n    };\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\ndefine('nls/root/strings',{\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(error {0})\",\n    \"NOT_FOUND_ERR\"                     : \"The file could not be found.\",\n    \"NOT_READABLE_ERR\"                  : \"The file could not be read.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"The target directory cannot be modified.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"The permissions do not allow you to make modifications.\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Error loading project\",\n    \"OPEN_DIALOG_ERROR\"                 : \"An error occurred when showing the open file dialog. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"An error occurred when trying to load the directory <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"An error occurred when reading the contents of the directory <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Error opening file\",\n    \"ERROR_OPENING_FILE\"                : \"An error occurred when trying to open the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Error reloading changes from disk\",\n    \"ERROR_RELOADING_FILE\"              : \"An error occurred when trying to reload the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Error saving file\",\n    \"ERROR_SAVING_FILE\"                 : \"An error occurred when trying to save the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Invalid file name\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Filenames cannot contain the following characters: /?*:;{}<>\\\\|\",\n    \"FILE_ALREADY_EXISTS\"               : \"The file <span class='dialog-filename'>{0}</span> already exists.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Error creating file\",\n    \"ERROR_CREATING_FILE\"               : \"An error occurred when trying to create the file <span class='dialog-filename'>{0}</span>. {1}\",\n\n    // Application error strings\n    \"ERROR_BRACKETS_IN_BROWSER_TITLE\"   : \"Oops! Brackets doesn't run in browsers yet.\",\n    \"ERROR_BRACKETS_IN_BROWSER\"         : \"Brackets is built in HTML, but right now it runs as a desktop app so you can use it to edit local files. Please use the application shell in the <b>github.com/adobe/brackets-app</b> repo to run Brackets.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Error Indexing Files\",\n    \"ERROR_MAX_FILES\"                   : \"The maximum number of files have been indexed. Actions that look up files in the index may function incorrectly.\",\n    \n    // CSSManager error strings\n    \"ERROR_PARSE_TITLE\"                 : \"Error parsing CSS file(s):\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Error launching browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"The Google Chrome browser could not be found. Please make sure it is installed.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"An error occurred when launching the browser. (error {0})\",\n    \n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Live Development Error\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"A live development connection to Chrome could not be established. For live development to work, Chrome needs to be started with remote debugging enabled.<br /><br />Would you like to relaunch Chrome and enable remote debugging?\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Open an HTML file in order to launch live preview.\",\n    \n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live File Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live File Preview: Connecting...\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live File Preview: Initializing...\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Disconnect Live File Preview\",\n    \n    \"SAVE_CLOSE_TITLE\"                  : \"Save Changes\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Do you want to save the changes you made in the document <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Do you want to save your changes to the following files?\",\n    \"EXT_MODIFIED_TITLE\"                : \"External Changes\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> has been modified on disk, but also has unsaved changes in Brackets.<br /><br />Which version do you want to keep?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> has been deleted on disk, but has unsaved changes in Brackets.<br /><br />Do you want to keep your changes?\",\n    \n    // Find, Replace, Find in Files\n    \"SEARCH_REGEXP_INFO\"                : \"Use /re/ syntax for regexp search\",\n    \"WITH\"                              : \"With\",\n    \"BUTTON_YES\"                        : \"Yes\",\n    \"BUTTON_NO\"                         : \"No\",\n    \"BUTTON_STOP\"                       : \"Stop\",\n\n    \"OPEN_FILE\"                         : \"Open File\",\n\n    \"RELEASE_NOTES\"                     : \"Release Notes\",\n    \"NO_UPDATE_TITLE\"                   : \"You're up to date!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"You are running the latest version of Brackets.\",\n\n    // Switch language\n    \"LANGUAGE_TITLE\"                    : \"Switch Language\",\n    \"LANGUAGE_MESSAGE\"                  : \"Please select the desired language from the list below:\",\n    \"LANGUAGE_SUBMIT\"                   : \"Reload Brackets\",\n    \"LANGUAGE_CANCEL\"                   : \"Cancel\",\n\n    /**\n     * ProjectManager\n     */\n\n    \"UNTITLED\" : \"Untitled\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"File\",\n    \"CMD_FILE_NEW\"                        : \"New\",\n    \"CMD_FILE_OPEN\"                       : \"Open\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Add To Working Set\",\n    \"CMD_OPEN_FOLDER\"                     : \"Open Folder\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Close\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Close All\",\n    \"CMD_FILE_SAVE\"                       : \"Save\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Save All\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live File Preview\",\n    \"CMD_QUIT\"                            : \"Quit\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edit\",\n    \"CMD_SELECT_ALL\"                      : \"Select All\",\n    \"CMD_FIND\"                            : \"Find\",\n    \"CMD_FIND_IN_FILES\"                   : \"Find in Files\",\n    \"CMD_FIND_NEXT\"                       : \"Find Next\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Find Previous\",\n    \"CMD_REPLACE\"                         : \"Replace\",\n    \"CMD_INDENT\"                          : \"Indent\",\n    \"CMD_UNINDENT\"                        : \"Unindent\",\n    \"CMD_DUPLICATE\"                       : \"Duplicate\",\n    \"CMD_COMMENT\"                         : \"Comment/Uncomment Lines\",\n    \"CMD_LINE_UP\"                         : \"Move Line(s) Up\",\n    \"CMD_LINE_DOWN\"                       : \"Move Line(s) Down\",\n     \n    // View menu commands\n    \"VIEW_MENU\"                           : \"View\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Hide Sidebar\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Show Sidebar\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Increase Font Size\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Decrease Font Size\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restore Font Size\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigate\",\n    \"CMD_QUICK_OPEN\"                      : \"Quick Open\",\n    \"CMD_GOTO_LINE\"                       : \"Go to Line\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Go to Definition\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Quick Edit\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Previous Match\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Next Match\",\n    \"CMD_NEXT_DOC\"                        : \"Next Document\",\n    \"CMD_PREV_DOC\"                        : \"Previous Document\",\n    \n    // Debug menu commands\n    \"DEBUG_MENU\"                          : \"Debug\",\n    \"CMD_REFRESH_WINDOW\"                  : \"Reload Brackets\",\n    \"CMD_SHOW_DEV_TOOLS\"                  : \"Show Developer Tools\",\n    \"CMD_RUN_UNIT_TESTS\"                  : \"Run Tests\",\n    \"CMD_JSLINT\"                          : \"Enable JSLint\",\n    \"CMD_SHOW_PERF_DATA\"                  : \"Show Performance Data\",\n    \"CMD_NEW_BRACKETS_WINDOW\"             : \"New Brackets Window\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Show Extensions Folder\",\n    \"CMD_USE_TAB_CHARS\"                   : \"Use Tab Characters\",\n    \"CMD_SWITCH_LANGUAGE\"                 : \"Switch Language\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Check for Updates\",\n\n    // Help menu commands\n    \"CMD_ABOUT\"                           : \"About\",\n\n    // Special commands invoked by the native shell\n    \"CMD_CLOSE_WINDOW\"                    : \"Close Window\",\n    \"CMD_ABORT_QUIT\"                      : \"Abort Quit\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"Experimental Build\",\n    \"JSLINT_ERRORS\"                        : \"JSLint Errors\",\n    \"SEARCH_RESULTS\"                       : \"Search Results\",\n    \"OK\"                                   : \"OK\",\n    \"DONT_SAVE\"                            : \"Don't Save\",\n    \"SAVE\"                                 : \"Save\",\n    \"CANCEL\"                               : \"Cancel\",\n    \"RELOAD_FROM_DISK\"                     : \"Reload from Disk\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Keep Changes in Editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Close (Don't Save)\",\n    \"RELAUNCH_CHROME\"                      : \"Relaunch Chrome\",\n    \"ABOUT\"                                : \"About\",\n    \"BRACKETS\"                             : \"Brackets\",\n    \"CLOSE\"                                : \"Close\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint 13 experimental build \",\n    \"ABOUT_TEXT_LINE2\"                     : \"Copyright 2012 Adobe Systems Incorporated and its licensors. All rights reserved.\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Notices; terms and conditions pertaining to third party software are located at \",\n    \"ABOUT_TEXT_LINE4\"                     : \" and incorporated by reference herein.\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Documentation and source at \",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"There's a new build of Brackets available! Click here for details.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Update Available\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, there's a new build of Brackets available. Here are some of the new features:\",\n    \"GET_IT_NOW\"                           : \"Get it now!\"\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\n/**\n * This file provides the interface to user visible strings in Brackets. Code that needs\n * to display strings should should load this module by calling var Strings = require(\"strings\").\n * The i18n plugin will dynamically load the strings for the right locale and populate\n * the exports variable. See src\\nls\\strings.js for the master file of English strings.\n */\ndefine('strings',['require','exports','module','i18n!nls/strings'],function (require, exports, module) {\n    \n\n    module.exports = require(\"i18n!nls/strings\");\n\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n *  Utilities functions related to string manipulation\n *\n */\ndefine('utils/StringUtils',['require','exports','module'],function (require, exports, module) {\n    \n\n    /**\n     * Format a string by replacing placeholder symbols with passed in arguments.\n     *\n     * Example: var formatted = StringUtils.format(\"Hello {0}\", \"World\");\n     *\n     * @param {string} str The base string\n     * @param {...} Arguments to be substituted into the string\n     *\n     * @return {string} Formatted string\n     */\n    function format(str) {\n        // arguments[0] is the base string, so we need to adjust index values here\n        var args = [].slice.call(arguments, 1);\n        return str.replace(/\\{(\\d+)\\}/g, function (match, num) {\n            return typeof args[num] !== \"undefined\" ? args[num] : match;\n        });\n    }\n\n    function htmlEscape(str) {\n        return String(str)\n            .replace(/&/g, \"&amp;\")\n            .replace(/\"/g, \"&quot;\")\n            .replace(/'/g, \"&#39;\")\n            .replace(/</g, \"&lt;\")\n            .replace(/>/g, \"&gt;\");\n    }\n\n    function regexEscape(str) {\n        return str.replace(/([.?*+\\^$\\[\\]\\\\(){}|\\-])/g, \"\\\\$1\");\n    }\n\n    // Periods (aka \"dots\") are allowed in HTML identifiers, but jQuery interprets\n    // them as the start of a class selector, so they need to be escaped\n    function jQueryIdEscape(str) {\n        return str.replace(/\\./g, \"\\\\.\");\n    }\n\n    /**\n     * Splits the text by new line characters and returns an array of lines\n     * @param {string} text\n     * @return {Array.<string>} lines\n     */\n    function getLines(text) {\n        return text.split(\"\\n\");\n    }\n\n    /**\n     * Returns a line number corresponding to an offset in some text. The text can\n     * be specified as a single string or as an array of strings that correspond to\n     * the lines of the string.\n     *\n     * Specify the text in lines when repeatedly calling the function on the same\n     * text in a loop. Use getLines() to divide the text into lines, then repeatedly call\n     * this function to compute a line number from the offset.\n     *\n     * @param {string | Array.<string>} textOrLines - string or array of lines from which\n     *      to compute the line number from the offset\n     * @param {number} offset\n     * @return {number} line number\n     */\n    function offsetToLineNum(textOrLines, offset) {\n        if (Array.isArray(textOrLines)) {\n            var lines = textOrLines,\n                total = 0,\n                line;\n            for (line = 0; line < lines.length; line++) {\n                if (total < offset) {\n                    // add 1 per line since /n were removed by splitting, but they needed to \n                    // contribute to the total offset count\n                    total += lines[line].length + 1;\n                } else if (total === offset) {\n                    return line;\n                } else {\n                    return line - 1;\n                }\n            }\n\n            // if offset is NOT over the total then offset is in the last line\n            if (offset <= total) {\n                return line - 1;\n            } else {\n                return undefined;\n            }\n        } else {\n            return textOrLines.substr(0, offset).split(\"\\n\").length - 1;\n        }\n    }\n\n    // Define public API\n    exports.format          = format;\n    exports.htmlEscape      = htmlEscape;\n    exports.regexEscape     = regexEscape;\n    exports.jQueryIdEscape  = jQueryIdEscape;\n    exports.getLines        = getLines;\n    exports.offsetToLineNum = offsetToLineNum;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, FileError, brackets, unescape, window */\n\n/**\n * Set of utilites for working with files and text content.\n */\ndefine('file/FileUtils',['require','exports','module','file/NativeFileSystem','utils/PerfUtils','widgets/Dialogs','strings','utils/StringUtils'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Encodings           = NativeFileSystem.Encodings;\n\n    \n    /**\n     * Asynchronously reads a file as UTF-8 encoded text.\n     * @return {$.Promise} a jQuery promise that will be resolved with the \n     *  file's text content plus its timestamp, or rejected with a FileError if\n     *  the file can not be read.\n     */\n    function readAsText(fileEntry) {\n        var result = new $.Deferred(),\n            reader;\n\n        // Measure performance\n        var perfTimerName = PerfUtils.markStart(\"readAsText:\\t\" + fileEntry.fullPath);\n        result.always(function () {\n            PerfUtils.addMeasurement(perfTimerName);\n        });\n\n        // Read file\n        reader = new NativeFileSystem.FileReader();\n        fileEntry.file(function (file) {\n            reader.onload = function (event) {\n                var text = event.target.result;\n                \n                fileEntry.getMetadata(\n                    function (metadata) {\n                        result.resolve(text, metadata.modificationTime);\n                    },\n                    function (error) {\n                        result.reject(error);\n                    }\n                );\n            };\n\n            reader.onerror = function (event) {\n                result.reject(event.target.error);\n            };\n\n            reader.readAsText(file, Encodings.UTF8);\n        });\n\n        return result.promise();\n    }\n    \n    /**\n     * Asynchronously writes a file as UTF-8 encoded text.\n     * @param {!FileEntry} fileEntry\n     * @param {!string} text\n     * @return {$.Promise} a jQuery promise that will be resolved when\n     * file writing completes, or rejected with a FileError.\n     */\n    function writeText(fileEntry, text) {\n        var result = new $.Deferred();\n        \n        fileEntry.createWriter(function (fileWriter) {\n            fileWriter.onwriteend = function (e) {\n                result.resolve();\n            };\n            fileWriter.onerror = function (err) {\n                result.reject(err);\n            };\n\n            // TODO (issue #241): NativeFileSystem.BlobBulder\n            fileWriter.write(text);\n        });\n        \n        return result.promise();\n    }\n\n    /** @const */\n    var LINE_ENDINGS_CRLF = \"CRLF\";\n    /** @const */\n    var LINE_ENDINGS_LF = \"LF\";\n    \n    /**\n     * Returns the standard line endings for the current platform\n     * @return {LINE_ENDINGS_CRLF|LINE_ENDINGS_LF}\n     */\n    function getPlatformLineEndings() {\n        return brackets.platform === \"win\" ? LINE_ENDINGS_CRLF : LINE_ENDINGS_LF;\n    }\n    \n    /**\n     * Scans the first 1000 chars of the text to determine how it encodes line endings. Returns\n     * null if usage is mixed or if no line endings found.\n     * @param {!string} text\n     * @return {null|LINE_ENDINGS_CRLF|LINE_ENDINGS_LF}\n     */\n    function sniffLineEndings(text) {\n        var subset = text.substr(0, 1000);  // (length is clipped to text.length)\n        var hasCRLF = /\\r\\n/.test(subset);\n        var hasLF = /[^\\r]\\n/.test(subset);\n        \n        if ((hasCRLF && hasLF) || (!hasCRLF && !hasLF)) {\n            return null;\n        } else {\n            return hasCRLF ? LINE_ENDINGS_CRLF : LINE_ENDINGS_LF;\n        }\n    }\n\n    /**\n     * Translates any line ending types in the given text to the be the single form specified\n     * @param {!string} text\n     * @param {null|LINE_ENDINGS_CRLF|LINE_ENDINGS_LF} lineEndings\n     * @return {string}\n     */\n    function translateLineEndings(text, lineEndings) {\n        if (lineEndings !== LINE_ENDINGS_CRLF && lineEndings !== LINE_ENDINGS_LF) {\n            lineEndings = getPlatformLineEndings();\n        }\n        \n        var eolStr = (lineEndings === LINE_ENDINGS_CRLF ? \"\\r\\n\" : \"\\n\");\n        var findAnyEol = /\\r\\n|\\r|\\n/g;\n        \n        return text.replace(findAnyEol, eolStr);\n    }\n\n    function getFileErrorString(code) {\n        // There are a few error codes that we have specific error messages for. The rest are\n        // displayed with a generic \"(error N)\" message.\n        var result;\n\n        if (code === FileError.NOT_FOUND_ERR) {\n            result = Strings.NOT_FOUND_ERR;\n        } else if (code === FileError.NOT_READABLE_ERR) {\n            result = Strings.NOT_READABLE_ERR;\n        } else if (code === FileError.NO_MODIFICATION_ALLOWED_ERR) {\n            result = Strings.NO_MODIFICATION_ALLOWED_ERR_FILE;\n        } else {\n            result = StringUtils.format(Strings.GENERIC_ERROR, code);\n        }\n\n        return result;\n    }\n    \n    function showFileOpenError(code, path) {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_OPENING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_OPENING_FILE,\n                StringUtils.htmlEscape(path),\n                getFileErrorString(code)\n            )\n        );\n    }\n\n    /**\n     * Convert a URI path to a native path.\n     * On both platforms, this unescapes the URI\n     * On windows, URI paths start with a \"/\", but have a drive letter (\"C:\"). In this\n     * case, remove the initial \"/\".\n     * @param {!string} path\n     * @return {string}\n     */\n    function convertToNativePath(path) {\n        path = unescape(path);\n        if (path.indexOf(\":\") !== -1 && path[0] === \"/\") {\n            return path.substr(1);\n        }\n        \n        return path;\n    }\n\n    /**\n     * Returns a native absolute path to the 'brackets' source directory.\n     * Note that this only works when run in brackets/src/index.html, so it does\n     * not work for unit tests (which is run from brackets/test/SpecRunner.html)\n     * @return {string}\n     */\n    function getNativeBracketsDirectoryPath() {\n        var pathname = decodeURI(window.location.pathname);\n        var directory = pathname.substr(0, pathname.lastIndexOf(\"/\"));\n        return convertToNativePath(directory);\n    }\n    \n    /**\n     * Given the module object passed to JS module define function,\n     * convert the path (which is relative to the current window)\n     * to a native absolute path.\n     * Returns a native absolute path to the module folder.\n     * @return {string}\n     */\n    function getNativeModuleDirectoryPath(module) {\n        var path, relPath, index, pathname;\n\n        if (module && module.uri) {\n\n            // Remove window name from base path. Maintain trailing slash.\n            pathname = decodeURI(window.location.pathname);\n            path = convertToNativePath(pathname.substr(0, pathname.lastIndexOf(\"/\") + 1));\n\n            // Remove module name from relative path. Remove trailing slash.\n            pathname = decodeURI(module.uri);\n            relPath = pathname.substr(0, pathname.lastIndexOf(\"/\"));\n\n            // handle leading \"../\" in relative directory\n            while (relPath.substr(0, 3) === \"../\") {\n                path = path.substr(0, path.length - 1); // strip trailing slash from base path\n                index = path.lastIndexOf(\"/\");          // find next slash from end\n                if (index !== -1) {\n                    path = path.substr(0, index + 1);   // remove last dir while maintaining slash\n                }\n                relPath = relPath.substr(3);            // remove leading \"../\" from relative path\n            }\n            path += relPath;\n        }\n        return path;\n    }\n\n    // Define public API\n    exports.LINE_ENDINGS_CRLF              = LINE_ENDINGS_CRLF;\n    exports.LINE_ENDINGS_LF                = LINE_ENDINGS_LF;\n    exports.getPlatformLineEndings         = getPlatformLineEndings;\n    exports.sniffLineEndings               = sniffLineEndings;\n    exports.translateLineEndings           = translateLineEndings;\n    exports.showFileOpenError              = showFileOpenError;\n    exports.getFileErrorString             = getFileErrorString;\n    exports.readAsText                     = readAsText;\n    exports.writeText                      = writeText;\n    exports.convertToNativePath            = convertToNativePath;\n    exports.getNativeBracketsDirectoryPath = getNativeBracketsDirectoryPath;\n    exports.getNativeModuleDirectoryPath   = getNativeModuleDirectoryPath;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\ndefine('language/HTMLUtils',['require','exports','module'],function (require, exports, module) {\n    \n    \n    //constants\n    var TAG_NAME = \"tagName\",\n        ATTR_NAME = \"attr.name\",\n        ATTR_VALUE = \"attr.value\";\n    \n    /**\n     * @private\n     * moves the current context backwards by one token\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function _movePrevToken(ctx) {\n        if (ctx.pos.ch <= 0 || ctx.token.start <= 0) {\n            //move up a line\n            if (ctx.pos.line <= 0) {\n                return false; //at the top already\n            }\n            ctx.pos.line--;\n            ctx.pos.ch = ctx.editor.getLine(ctx.pos.line).length;\n        } else {\n            ctx.pos.ch = ctx.token.start;\n        }\n        ctx.token = ctx.editor.getTokenAt(ctx.pos);\n        return true;\n    }\n    \n    /**\n     * @private\n     * moves the current context forward by one token\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function _moveNextToken(ctx) {\n        var eol = ctx.editor.getLine(ctx.pos.line).length;\n        if (ctx.pos.ch >= eol || ctx.token.end >= eol) {\n            //move down a line\n            if (ctx.pos.line >= ctx.editor.lineCount() - 1) {\n                return false; //at the bottom\n            }\n            ctx.pos.line++;\n            ctx.pos.ch = 0;\n        } else {\n            ctx.pos.ch = ctx.token.end + 1;\n        }\n        ctx.token = ctx.editor.getTokenAt(ctx.pos);\n        return true;\n    }\n    \n   /**\n     * @private\n     * moves the current context in the given direction, skipping any whitespace it hits\n     * @param {function} moveFxn the funciton to move the context\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function _moveSkippingWhitespace(moveFxn, ctx) {\n        if (!moveFxn(ctx)) {\n            return false;\n        }\n        while (!ctx.token.className && ctx.token.string.trim().length === 0) {\n            if (!moveFxn(ctx)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n   /**\n     * @private\n     * creates a context object\n     * @param {CodeMirror} editor\n     * @param {{ch:{string}, line:{number}} pos\n     * @return {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}\n     */\n    function _getInitialContext(editor, pos) {\n        return {\n            \"editor\": editor,\n            \"pos\": pos,\n            \"token\": editor.getTokenAt(pos)\n        };\n    }\n    \n    /**\n     * @private\n     * in the given context, get the character offset of pos from the start of the token\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {number}\n     */\n    function _offsetInToken(ctx) {\n        var offset = ctx.pos.ch - ctx.token.start;\n        if (offset < 0) {\n            console.log(\"CodeHintUtils: _offsetInToken - Invalid context: the pos what not in the current token!\");\n        }\n        return offset;\n    }\n \n   /**\n     * @private\n     * Sometimes as attr values are getting typed, if the quotes aren't balanced yet\n     * some extra 'non attribute value' text gets included in the token. This attempts\n     * to assure the attribute value we grab is always good\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return { val:{string}, offset:{number}}\n     */\n    function _extractAttrVal(ctx) {\n        var attrValue = ctx.token.string,\n            startChar = attrValue.charAt(0),\n            endChar = attrValue.charAt(attrValue.length - 1),\n            offset = _offsetInToken(ctx),\n            foundEqualSign = false;\n        \n        //If this is a fully quoted value, return the whole\n        //thing regardless of position\n        if (attrValue.length > 1 &&\n                (startChar === \"'\" || startChar === '\"') &&\n                endChar === startChar) {\n            \n            // Find an equal sign before the end quote. If found, \n            // then the user may be entering an attribute value right before \n            // another attribute and we're getting a false balanced string.\n            // An example of this case is <link rel\" href=\"foo\"> where the \n            // cursor is right after the first double quote.\n            foundEqualSign = (attrValue.match(/\\=\\s*['\"]$/) !== null);\n            \n            if (!foundEqualSign) {\n                //strip the quotes and return;\n                attrValue = attrValue.substring(1, attrValue.length - 1);\n                offset = offset - 1 > attrValue.length ? attrValue.length : offset - 1;\n                return {val: attrValue, offset: offset, quoteChar: startChar, hasEndQuote: true};\n            }\n        }\n        \n        if (foundEqualSign) {\n            var spaceIndex = attrValue.indexOf(\" \");\n            attrValue = attrValue.substring(0, (spaceIndex > offset) ? spaceIndex : offset);\n        } else if (offset > 0) {\n            //The att value it getting edit in progress. There is possible extra\n            //stuff in this token state since the quote isn't closed, so we assume\n            //the stuff from the quote to the current pos is definitely in the attribute \n            //value.\n            attrValue = attrValue.substring(0, offset);\n        }\n        \n        //If the attrValue start with a quote, trim that now\n        startChar = attrValue.charAt(0);\n        if (startChar === \"'\" || startChar === '\"') {\n            attrValue = attrValue.substring(1);\n            offset--;\n        } else {\n            startChar = \"\";\n        }\n        \n        return {val: attrValue, offset: offset, quoteChar: startChar, hasEndQuote: false};\n    }\n    \n    /**\n     * @private\n     * Gets the tagname from where ever you are in the currect state\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string}\n     */\n    function _extractTagName(ctx) {\n        if (ctx.token.state.tagName) {\n            return ctx.token.state.tagName; //XML mode\n        } else if (ctx.token.state.htmlState) {\n            return ctx.token.state.htmlState.tagName; //HTML mode\n        }\n        // Some mixed modes that offer HTML as a nested mode don't actually expose the HTML state\n        return null;\n    }\n    \n    /**\n     * Creates a tagInfo object and assures all the values are entered or are empty strings\n     * @param {string} tokenType what is getting edited and should be hinted\n     * @param {number} offset where the cursor is for the part getting hinted\n     * @param {string} tagName The name of the tag\n     * @param {string} attrName The name of the attribute\n     * @param {string} attrValue The value of the attribute\n     * @return {{tagName:string, attr{name:string, value:string}, hint:{type:{string}, offset{number}}}}\n     *              A tagInfo object with some context about the current tag hint.            \n     */\n    function createTagInfo(tokenType, offset, tagName, attrName, attrValue, valueAssigned, quoteChar, hasEndQuote) {\n        return { tagName: tagName || \"\",\n                 attr:\n                    { name: attrName || \"\",\n                      value: attrValue || \"\",\n                      valueAssigned: valueAssigned || false,\n                      quoteChar: quoteChar || \"\",\n                      hasEndQuote: hasEndQuote || false },\n                 position:\n                    { tokenType: tokenType || \"\",\n                      offset: offset || 0 } };\n    }\n    \n    /**\n     * @private\n     * Gets the taginfo starting from the attribute value and moving backwards\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string}\n     */\n    function _getTagInfoStartingFromAttrValue(ctx) {\n        // Assume we in the attr value\n        // and validate that by going backwards\n        var attrInfo = _extractAttrVal(ctx),\n            attrVal = attrInfo.val,\n            offset = attrInfo.offset,\n            quoteChar = attrInfo.quoteChar,\n            hasEndQuote = attrInfo.hasEndQuote,\n            strLength = ctx.token.string.length;\n        \n        if (ctx.token.className === \"string\" && ctx.pos.ch === ctx.token.end && strLength > 1) {\n            var firstChar = ctx.token.string[0],\n                lastChar = ctx.token.string[strLength - 1];\n            \n            // We get here only when the cursor is immediately on the right of the end quote\n            // of an attribute value. So we want to return an empty tag info so that the caller\n            // can dismiss the code hint popup if it is still open.\n            if (firstChar === lastChar && (firstChar === \"'\" || firstChar === \"\\\"\")) {\n                return createTagInfo();\n            }\n        }\n        \n        //Move to the prev token, and check if it's \"=\"\n        if (!_moveSkippingWhitespace(_movePrevToken, ctx) || ctx.token.string !== \"=\") {\n            return createTagInfo();\n        }\n        \n        //Move to the prev token, and check if it's an attribute\n        if (!_moveSkippingWhitespace(_movePrevToken, ctx) || ctx.token.className !== \"attribute\") {\n            return createTagInfo();\n        }\n        \n        var attrName = ctx.token.string;\n        var tagName = _extractTagName(ctx);\n \n        //We're good. \n        return createTagInfo(ATTR_VALUE, offset, tagName, attrName, attrVal, true, quoteChar, hasEndQuote);\n    }\n\n    /**\n     * @private\n     * Gets the taginfo starting from the attribute name and moving forwards\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @param {boolean} isPriorAttr indicates whether we're getting info for a prior attribute\n     * @return {string}\n     */\n    function _getTagInfoStartingFromAttrName(ctx, isPriorAttr) {\n        //Verify We're in the attribute name, move forward and try to extract the rest of\n        //the info. If the user it typing the attr the rest might not be here\n        if (isPriorAttr === false && ctx.token.className !== \"attribute\") {\n            return createTagInfo();\n        }\n        \n        var tagName = _extractTagName(ctx);\n        var attrName = ctx.token.string;\n        var offset = _offsetInToken(ctx);\n        \n        if (!_moveSkippingWhitespace(_moveNextToken, ctx) || ctx.token.string !== \"=\") {\n            return createTagInfo(ATTR_NAME, offset, tagName, attrName);\n        }\n        \n        if (!_moveSkippingWhitespace(_moveNextToken, ctx)) {\n            return createTagInfo(ATTR_NAME, offset, tagName, attrName);\n        }\n        //this should be the attrvalue\n        var attrInfo = _extractAttrVal(ctx),\n            attrVal = attrInfo.val,\n            quoteChar = attrInfo.quoteChar,\n            hasEndQuote = attrInfo.hasEndQuote;\n        \n        return createTagInfo(ATTR_NAME, offset, tagName, attrName, attrVal, true, quoteChar, hasEndQuote);\n    }\n    \n    /**\n     * Figure out if we're in a tag, and if we are return info about what to hint about it\n     * An example token stream for this tag is <span id=\"open-files-disclosure-arrow\"></span> : \n     *      className:tag       string:\"<span\"\n     *      className:          string:\" \"\n     *      className:attribute string:\"id\"\n     *      className:          string:\"=\"\n     *      className:string    string:\"\"open-files-disclosure-arrow\"\"\n     *      className:tag       string:\"></span>\"\n     * @param {Editor} editor An instance of a Brackets editor\n     * @param {{ch: number, line: number}} constPos  A CM pos (likely from editor.getCursor())\n     * @return {{tagName:string, attr{name:string, value:string}, hint:{type:{string}, offset{number}}}}\n     *              A tagInfo object with some context about the current tag hint.\n     */\n    function getTagInfo(editor, constPos) {\n        //we're going to changing pos a lot, but we don't want to mess up\n        //the pos the caller passed in so we use extend to make a safe copy of it.\t\n        //This is what pass by value in c++ would do.\t\n        var pos = $.extend({}, constPos),\n            ctx = _getInitialContext(editor._codeMirror, pos),\n            offset = _offsetInToken(ctx),\n            tagInfo,\n            tokenType;\n        \n        // check if this is inside a style block.\n        if (editor.getModeForSelection() !== \"html\") {\n            return createTagInfo();\n        }\n        \n        //check and see where we are in the tag\n        if (ctx.token.string.length > 0 && ctx.token.string.trim().length === 0) {\n\n            // token at (i.e. before) pos is whitespace, so test token at next pos\n            //\n            // note: getTokenAt() does range checking for ch. If it detects that ch is past\n            // EOL, it uses EOL, same token is returned, and the following condition fails,\n            // so we don't need to worry about testPos being valid.\n            var testPos = {ch: ctx.pos.ch + 1, line: ctx.pos.line},\n                testToken = editor._codeMirror.getTokenAt(testPos);\n\n            if (testToken.string.length > 0 && testToken.string.trim().length > 0 &&\n                    testToken.string.charAt(0) !== \">\") {\n                // pos has whitespace before it and non-whitespace after it, so use token after\n                ctx.token = testToken;\n\n                if (ctx.token.className === \"tag\") {\n                    // check to see if the cursor is just before a \"<\" but not in any tag.\n                    if (ctx.token.string.charAt(0) === \"<\") {\n                        return createTagInfo();\n                    }\n                } else if (ctx.token.className === \"attribute\") {\n                    // check to see if the user is going to add a new attr before an existing one\n                    return _getTagInfoStartingFromAttrName(ctx, false);\n                } else if (ctx.token.className === \"string\") {\n                    // we're either before a \"=\" or an attribute value.\n                    return createTagInfo();\n                }\n\n                ctx.pos = testPos;\n                // Get the new offset from test token and subtract one for testPos adjustment\n                offset = _offsetInToken(ctx) - 1;\n            } else {\n                // We get here if \">\" or white spaces after testPos.\n                // next, see what's before pos\n                if (!_movePrevToken(ctx)) {\n                    return createTagInfo();\n                }\n            \n                if (ctx.token.className !== \"tag\") {\n                    //if wasn't the tag name, assume it was an attr value\n                    tagInfo = _getTagInfoStartingFromAttrValue(ctx);\n\n                    //if it wasn't an attr value, assume it was an empty attr (ie. attr with no value)\n                    if (!tagInfo.tagName) {\n                        tagInfo = _getTagInfoStartingFromAttrName(ctx, true);\n                    }\n\n                    //We don't want to give context for the previous attr\n                    //and we want it to look like the user is going to add a new attr\n                    if (tagInfo.tagName) {\n                        return createTagInfo(ATTR_NAME, 0, tagInfo.tagName);\n                    }\n                    return createTagInfo();\n                }\n                \n                //we know the tag was here, so they user is adding an attr name\n                tokenType = ATTR_NAME;\n                offset = 0;\n            }\n        }\n        \n        if (ctx.token.className === \"tag\") {\n            // Check if the user just typed a white space after \"<\" that made an existing tag invalid.\n            if (ctx.token.string.indexOf(\"< \") === 0) {\n                return createTagInfo();\n            }\n            \n            //check to see if this is the closing of a tag (either the start or end)\n            if (ctx.token.string === \">\" ||\n                    (ctx.token.string.charAt(0) === \"<\" && ctx.token.string.charAt(1) === \"/\")) {\n                return createTagInfo();\n            }\n            \n            if (!tokenType) {\n                tokenType = TAG_NAME;\n                offset--; //need to take off 1 for the leading \"<\"\n            }\n            \n            //we're actually in the tag, just return that as we have no relevant \n            //info about what attr is selected\n            return createTagInfo(tokenType, offset, _extractTagName(ctx));\n        }\n        \n        if (ctx.token.string === \"=\") {\n            // To discourage unquoted attribute value usage we intentionally return an invalid tag info here.\n            // This will also spare us from handling the conversion between quoted and unquoted attribute values.\n            return createTagInfo();\n        }\n        \n        if (ctx.token.className === \"attribute\") {\n            tagInfo = _getTagInfoStartingFromAttrName(ctx, false);\n        } else {\n            // if we're not at a tag, \"=\", or attribute name, assume we're in the value\n            tagInfo = _getTagInfoStartingFromAttrValue(ctx);\n        }\n        \n        if (tokenType && tagInfo.tagName) {\n            tagInfo.position.tokenType = tokenType;\n            tagInfo.position.offset = offset;\n        }\n        \n        return tagInfo;\n    }\n    \n    \n    /**\n     * Returns an Array of info about all <style> blocks in the given Editor's HTML document (assumes\n     * the Editor contains HTML text).\n     * @param {!Editor} editor\n     */\n    function findStyleBlocks(editor) {\n        // Start scanning from beginning of file\n        var ctx = _getInitialContext(editor._codeMirror, {line: 0, ch: 0});\n        \n        var styleBlocks = [];\n        var currentStyleBlock = null;\n        var inStyleBlock = false;\n        \n        while (_moveNextToken(ctx)) {\n            if (inStyleBlock) {\n                // Check for end of this <style> block\n                if (ctx.token.state.mode !== \"css\") {\n                    currentStyleBlock.text = editor.document.getRange(currentStyleBlock.start, currentStyleBlock.end);\n                    inStyleBlock = false;\n                } else {\n                    currentStyleBlock.end = { line: ctx.pos.line, ch: ctx.pos.ch };\n                }\n            } else {\n                // Check for start of a <style> block\n                if (ctx.token.state.mode === \"css\") {\n                    currentStyleBlock = {\n                        start: { line: ctx.pos.line, ch: ctx.pos.ch }\n                    };\n                    styleBlocks.push(currentStyleBlock);\n                    inStyleBlock = true;\n                }\n                // else, random token in non-CSS content: ignore\n            }\n        }\n        \n        return styleBlocks;\n    }\n    \n    \n    // Define public API\n    exports.TAG_NAME = TAG_NAME;\n    exports.ATTR_NAME = ATTR_NAME;\n    exports.ATTR_VALUE = ATTR_VALUE;\n    \n    exports.getTagInfo = getTagInfo;\n    //The createTagInfo is really only for the unit tests so they can make the same structure to \n    //compare results with\n    exports.createTagInfo = createTagInfo;\n    exports.findStyleBlocks = findStyleBlocks;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window */\n\n/**\n * Utilities for managing pop-ups.\n */\ndefine('widgets/PopUpManager',['require','exports','module','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    var EditorManager = require(\"editor/EditorManager\");\n    \n    var _popUps = [];\n        \n    /**\n     * Add Esc key handling for a popup DOM element.\n     *\n     * @param {!jQuery} $popUp jQuery object for the DOM element pop-up\n     * @param {function} removeHandler Pop-up specific remove (e.g. display:none or DOM removal)\n     * @param {?Boolean} autoAddRemove - Specify true to indicate the PopUpManager should \n     *      add/remove the popup from the DOM when the popup is open/closed. Specify false\n     *      when the popup is either always persistant in the DOM or the add/remove is handled \n     *      external to the PopupManager \n     *      \n     */\n    function addPopUp($popUp, removeHandler, autoAddRemove) {\n        autoAddRemove = autoAddRemove || false;\n        \n        _popUps.push($popUp[0]);\n        $popUp.data(\"PopUpManager-autoAddRemove\", autoAddRemove);\n        $popUp.data(\"PopUpManager-removeHandler\", removeHandler);\n        \n        if (autoAddRemove) {\n            $(window.document.body).append($popUp);\n        }\n    }\n    \n    /**\n     * Remove Esc key handling for a pop-up. Removes the pop-up from the DOM\n     * if the pop-up is currently visible and was not originally attached.\n     *\n     * @param {!jQuery} $popUp\n     */\n    function removePopUp($popUp) {\n        var index = _popUps.indexOf($popUp[0]);\n        if (index >= 0) {\n            var autoAddRemove = $popUp.data(\"PopUpManager-autoAddRemove\"),\n                removeHandler = $popUp.data(\"PopUpManager-removeHandler\");\n            \n            if (removeHandler && $popUp.find(\":visible\").length > 0) {\n                removeHandler();\n            }\n            \n            if (autoAddRemove) {\n                $popUp.remove();\n                _popUps = _popUps.slice(index);\n            }\n        }\n    }\n    \n    function _keydownCaptureListener(keyEvent) {\n        if (keyEvent.keyCode !== 27) { // escape key\n            return;\n        }\n        \n        // allow the popUp to prevent closing\n        var $popUp,\n            i,\n            event = new $.Event(\"popUpClose\");\n        \n        for (i = _popUps.length - 1; i >= 0; i--) {\n            $popUp = $(_popUps[i]);\n            \n            if ($popUp.find(\":visible\").length > 0) {\n                $popUp.trigger(event);\n                \n                if (!event.isDefaultPrevented()) {\n                    // Stop the DOM event from propagating\n                    keyEvent.stopImmediatePropagation();\n                    \n                    removePopUp($popUp);\n\n                    // TODO: right now Menus and Context Menus do not take focus away from\n                    // the editor. We need to have a focus manager to correctly manage focus\n                    // between editors and other UI elements.\n                    // For now we don't set focus here and assume individual popups\n                    // adjust focus if necessary\n                    // See story in Trello card #404\n                    //EditorManager.focusEditor();\n                }\n                \n                break;\n            }\n        }\n    }\n    \n    window.document.body.addEventListener(\"keydown\", _keydownCaptureListener, true);\n    \n    exports.addPopUp        = addPopUp;\n    exports.removePopUp     = removePopUp;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\ndefine('utils/ViewUtils',['require','exports','module'],function (require, exports, module) {\n    \n    \n    var SCROLL_SHADOW_HEIGHT = 5;\n    \n    /**\n     * @private\n     */\n    var _resizeHandlers = [];\n\n    /** \n     * Positions shadow background elements to indicate vertical scrolling.\n     * @param {!DOMElement} $displayElement the DOMElement that displays the shadow\n     * @param {!Object} $scrollElement the object that is scrolled\n     * @param {!DOMElement} $shadowTop div .scroller-shadow.top\n     * @param {!DOMElement} $shadowBottom div .scroller-shadow.bottom\n     * @param {boolean} isPositionFixed When using absolute position, top remains at 0.\n     */\n    function _updateScrollerShadow($displayElement, $scrollElement, $shadowTop, $shadowBottom, isPositionFixed) {\n        var offsetTop           = 0,\n            scrollElement       = $scrollElement.get(0),\n            scrollTop           = scrollElement.scrollTop,\n            topShadowOffset     = Math.min(scrollTop - SCROLL_SHADOW_HEIGHT, 0),\n            displayElementWidth = $displayElement.width();\n        \n        if ($shadowTop) {\n            $shadowTop.css(\"background-position\", \"0px \" + topShadowOffset + \"px\");\n            \n            if (isPositionFixed) {\n                offsetTop = $displayElement.offset().top;\n                $shadowTop.css(\"top\", offsetTop);\n            }\n            \n            if (isPositionFixed) {\n                $shadowTop.css(\"width\", displayElementWidth);\n            }\n        }\n        \n        if ($shadowBottom) {\n            var clientHeight        = scrollElement.clientHeight,\n                outerHeight         = $displayElement.outerHeight(),\n                scrollHeight        = scrollElement.scrollHeight,\n                bottomOffset        = outerHeight - clientHeight,\n                bottomShadowOffset  = SCROLL_SHADOW_HEIGHT; // outside of shadow div viewport\n            \n            if (scrollHeight > clientHeight) {\n                bottomShadowOffset -= Math.min(SCROLL_SHADOW_HEIGHT, (scrollHeight - (scrollTop + clientHeight)));\n            }\n    \n            $shadowBottom.css(\"background-position\", \"0px \" + bottomShadowOffset + \"px\");\n            $shadowBottom.css(\"top\", offsetTop + outerHeight - SCROLL_SHADOW_HEIGHT);\n            $shadowBottom.css(\"width\", displayElementWidth);\n        }\n    }\n\n    function getOrCreateShadow($displayElement, position, isPositionFixed) {\n        var $findShadow = $displayElement.find(\".scroller-shadow.\" + position);\n\n        if ($findShadow.length === 0) {\n            $findShadow = $(window.document.createElement(\"div\")).addClass(\"scroller-shadow \" + position);\n            $displayElement.append($findShadow);\n        }\n        \n        if (!isPositionFixed) {\n            // position is fixed by default\n            $findShadow.css(\"position\", \"absolute\");\n            $findShadow.css(position, \"0\");\n        }\n\n        return $findShadow;\n    }\n\n    /** \n     * Installs event handlers for updatng shadow background elements to indicate vertical scrolling.\n     * @param {!DOMElement} displayElement the DOMElement that displays the shadow. Must fire\n     *  \"contentChanged\" events when the element is resized or repositioned.\n     * @param {?Object} scrollElement the object that is scrolled. Must fire \"scroll\" events\n     *  when the element is scrolled. If null, the displayElement is used.\n     * @param {?boolean} showBottom optionally show the bottom shadow\n     */\n    function addScrollerShadow(displayElement, scrollElement, showBottom) {\n        // use fixed positioning when the display and scroll elements are the same\n        var isPositionFixed = false;\n        \n        if (!scrollElement) {\n            scrollElement = displayElement;\n            isPositionFixed = true;\n        }\n        \n        // update shadows when the scrolling element is scrolled\n        var $displayElement = $(displayElement),\n            $scrollElement = $(scrollElement);\n        \n        var $shadowTop = getOrCreateShadow($displayElement, \"top\", isPositionFixed);\n        var $shadowBottom = (showBottom) ? getOrCreateShadow($displayElement, \"bottom\", isPositionFixed) : null;\n        \n        var doUpdate = function () {\n            _updateScrollerShadow($displayElement, $scrollElement, $shadowTop, $shadowBottom, isPositionFixed);\n        };\n        \n        $scrollElement.on(\"scroll.scroller-shadow\", doUpdate);\n        $displayElement.on(\"contentChanged.scroller-shadow\", doUpdate);\n        \n        // update immediately\n        doUpdate();\n    }\n    \n    /**\n     * Remove scroller-shadow effect.\n     * @param {!DOMElement} displayElement the DOMElement that displays the shadow\n     * @param {?Object} scrollElement the object that is scrolled\n     */\n    function removeScrollerShadow(displayElement, scrollElement) {\n        if (!scrollElement) {\n            scrollElement = displayElement;\n        }\n        \n        var $displayElement = $(displayElement),\n            $scrollElement = $(scrollElement);\n        \n        // remove scrollerShadow elements from DOM\n        $displayElement.find(\".scroller-shadow.top\").remove();\n        $displayElement.find(\".scroller-shadow.bottom\").remove();\n        \n        // remove event handlers\n        $scrollElement.off(\"scroll.scroller-shadow\");\n        $displayElement.off(\"contentChanged.scroller-shadow\");\n    }\n    \n    /** \n     * Within a scrolling DOMElement, creates and positions a styled selection\n     * div to align a single selected list item from a ul list element.\n     *\n     * Assumptions:\n     * - scrollElement is a child of the #file-section div\n     * - ul list element fires a \"selectionChanged\" event after the\n     *   selectedClassName is assigned to a new list item\n     * \n     * @param {!DOMElement} scrollElement A DOMElement containing a ul list element\n     * @param {!string} selectedClassName A CSS class name on at most one list item in the contained list\n     */\n    function sidebarList($scrollerElement, selectedClassName, leafClassName) {\n        var $listElement = $scrollerElement.find(\"ul\"),\n            $selectionMarker,\n            $selectionTriangle,\n            $sidebar = $(\"#sidebar\"),\n            showTriangle = true;\n        \n        // build selectionMarker and position absolute within the scroller\n        $selectionMarker = $(window.document.createElement(\"div\")).addClass(\"sidebar-selection\");\n        $scrollerElement.prepend($selectionMarker);\n        \n        // enable scrolling\n        $scrollerElement.css(\"overflow\", \"auto\");\n        \n        // use relative postioning for clipping the selectionMarker within the scrollElement\n        $scrollerElement.css(\"position\", \"relative\");\n        \n        // build selectionTriangle and position fixed to the window\n        $selectionTriangle = $(window.document.createElement(\"div\")).addClass(\"sidebar-selection-triangle\");\n        \n        $scrollerElement.append($selectionTriangle);\n        \n        selectedClassName = \".\" + (selectedClassName || \"selected\");\n        \n        var updateSelectionTriangle = function () {\n            var selectionMarkerHeight = $selectionMarker.height(),\n                selectionMarkerOffset = $selectionMarker.offset(),\n                scrollerOffset = $scrollerElement.offset(),\n                triangleHeight = $selectionTriangle.outerHeight(),\n                scrollerTop = scrollerOffset.top,\n                scrollerBottom = scrollerTop + $scrollerElement.outerHeight(),\n                scrollerLeft = scrollerOffset.left,\n                triangleTop = selectionMarkerOffset.top;\n            \n            $selectionTriangle.css(\"top\", triangleTop);\n            $selectionTriangle.css(\"left\", $sidebar.width() - $selectionTriangle.outerWidth());\n            $selectionTriangle.toggleClass(\"triangle-visible\", showTriangle);\n            \n            var triangleClipOffsetYBy = Math.floor((selectionMarkerHeight - triangleHeight) / 2),\n                triangleBottom = triangleTop + triangleHeight + triangleClipOffsetYBy;\n            \n            if (triangleTop < scrollerTop || triangleBottom > scrollerBottom) {\n                $selectionTriangle.css(\"clip\", \"rect(\" + Math.max(scrollerTop - triangleTop - triangleClipOffsetYBy, 0) + \"px, auto, \" +\n                                           (triangleHeight - Math.max(triangleBottom - scrollerBottom, 0)) + \"px, auto)\");\n            } else {\n                $selectionTriangle.css(\"clip\", \"\");\n            }\n        };\n        \n        var updateSelectionMarker = function (event, reveal) {\n            // find the selected list item\n            var $listItem = $listElement.find(selectedClassName).closest(\"li\");\n            \n            if (leafClassName) {\n                showTriangle = $listItem.hasClass(leafClassName);\n            }\n            \n            // always hide selection visuals first to force layout (issue #719)\n            $selectionTriangle.hide();\n            $selectionMarker.hide();\n            \n            if ($listItem.length === 1) {\n                // list item position is relative to scroller\n                var selectionMarkerTop = $listItem.offset().top - $scrollerElement.offset().top + $scrollerElement.get(0).scrollTop;\n                    \n                // force selection width to match scroller\n                $selectionMarker.width($scrollerElement.get(0).scrollWidth);\n                \n                // move the selectionMarker position to align with the list item\n                $selectionMarker.css(\"top\", selectionMarkerTop);\n                $selectionMarker.show();\n                \n                updateSelectionTriangle();\n                $selectionTriangle.show();\n            \n                // fully scroll to the selectionMarker if it's not initially in the viewport\n                var scrollerElement = $scrollerElement.get(0),\n                    scrollerHeight = scrollerElement.clientHeight,\n                    selectionMarkerHeight = $selectionMarker.height(),\n                    selectionMarkerBottom = selectionMarkerTop + selectionMarkerHeight,\n                    currentScrollBottom = scrollerElement.scrollTop + scrollerHeight;\n                \n                // update scrollTop to reveal the selected list item\n                if (reveal) {\n                    if (selectionMarkerTop >= currentScrollBottom) {\n                        $listItem.get(0).scrollIntoView(false);\n                    } else if (selectionMarkerBottom <= scrollerElement.scrollTop) {\n                        $listItem.get(0).scrollIntoView(true);\n                    }\n                }\n            }\n        };\n        \n        $listElement.on(\"selectionChanged\", updateSelectionMarker);\n        $scrollerElement.on(\"scroll\", updateSelectionTriangle);\n        \n        // update immediately\n        updateSelectionMarker();\n        \n        // update clipping when the window resizes\n        _resizeHandlers.push(updateSelectionTriangle);\n    }\n    \n    /**\n     * @private\n     */\n    function _handleResize() {\n        _resizeHandlers.forEach(function (f) {\n            f.apply();\n        });\n    }\n\n    /**\n     * Within a scrolling DOMElement, if necessary, scroll element into viewport.\n     *\n     * To Perform the minimum amount of scrolling necessary, cases should be handled as follows:\n     * - element already completely in view : no scrolling\n     * - element above    viewport          : scroll view so element is at top\n     * - element left of  viewport          : scroll view so element is at left\n     * - element below    viewport          : scroll view so element is at bottom\n     * - element right of viewport          : scroll view so element is at right\n     *\n     * Assumptions:\n     * - $view is a scrolling container\n     *\n     * @param {!DOMElement} $view - A jQuery scrolling container\n     * @param {!DOMElement} $element - A jQuery element\n     * @param {?boolean} scrollHorizontal - whether to also scroll horizonally\n     */\n    function scrollElementIntoView($view, $element, scrollHorizontal) {\n        var viewOffset = $view.offset(),\n            viewScroller = $view.get(0),\n            element = $element.get(0),\n            elementOffset = $element.offset();\n\n        // scroll minimum amount\n        if (elementOffset.top + $element.height() >= (viewOffset.top + $view.height())) {\n            // below viewport\n            element.scrollIntoView(false);\n        } else if (elementOffset.top <= viewOffset.top) {\n            // above viewport\n            element.scrollIntoView(true);\n        }\n\n        if (scrollHorizontal) {\n            if (elementOffset.left < 0) {\n                $view.scrollLeft($view.scrollLeft() + elementOffset.left);\n            } else if (elementOffset.left + $element.width() >= viewOffset.left + $view.width()) {\n                $view.scrollLeft(elementOffset.left - viewOffset.left);\n            }\n        }\n    }\n    \n    // handle all resize handlers in a single listener\n    $(window).resize(_handleResize);\n\n    // Define public API\n    exports.SCROLL_SHADOW_HEIGHT    = SCROLL_SHADOW_HEIGHT;\n    exports.addScrollerShadow       = addScrollerShadow;\n    exports.removeScrollerShadow    = removeScrollerShadow;\n    exports.sidebarList             = sidebarList;\n    exports.scrollElementIntoView   = scrollElementIntoView;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window, brackets */\n\ndefine('editor/CodeHintManager',['require','exports','module','language/HTMLUtils','command/Menus','utils/StringUtils','editor/EditorManager','widgets/PopUpManager','utils/ViewUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var HTMLUtils       = require(\"language/HTMLUtils\"),\n        Menus           = require(\"command/Menus\"),\n        StringUtils     = require(\"utils/StringUtils\"),\n        EditorManager   = require(\"editor/EditorManager\"),\n        PopUpManager    = require(\"widgets/PopUpManager\"),\n        ViewUtils       = require(\"utils/ViewUtils\");\n\n\n    var hintProviders = [],\n        hintList,\n        shouldShowHintsOnKeyUp = false;\n\n\n    /**\n     * @constructor\n     *\n     * Displays a popup list of code completions.\n     * Currently only HTML tags are supported, but this will greatly be extended in coming sprint\n     * to include: extensibility API, HTML attributes hints, JavaScript hints, CSS hints\n     */\n    function CodeHintList() {\n        this.currentProvider = null;\n        this.query = {queryStr: null};\n        this.displayList = [];\n        this.options = {\n            maxResults: 999\n        };\n\n        this.opened = false;\n        this.selectedIndex = -1;\n        this.editor = null;\n\n        this.$hintMenu = $(\"<li class='dropdown codehint-menu'></li>\");\n        var $toggle = $(\"<a href='#' class='dropdown-toggle'></a>\")\n            .hide();\n\n        this.$hintMenu.append($toggle)\n            .append(\"<ul class='dropdown-menu'></ul>\");\n    }\n\n    /**\n     * @private\n     * Enters the code completion text into the editor\n     * @string {string} completion - text to insert into current code editor\n     */\n    CodeHintList.prototype._handleItemClick = function (completion) {\n        this.currentProvider.handleSelect(completion, this.editor, this.editor.getCursorPos());\n        this.close();\n    };\n\n    /**\n     * Adds a single item to the hint list\n     * @param {string} name\n     */\n    CodeHintList.prototype.addItem = function (name) {\n        var self = this;\n        var displayName = name.replace(\n            new RegExp(StringUtils.regexEscape(this.query.queryStr), \"i\"),\n            \"<strong>$&</strong>\"\n        );\n\n        var $item = $(\"<li><a href='#'><span class='codehint-item'>\" + displayName + \"</span></a></li>\")\n            .on(\"click\", function (e) {\n                // Don't let the click propagate upward (otherwise it will hit the close handler in\n                // bootstrap-dropdown).\n                e.stopPropagation();\n                self._handleItemClick(name);\n            });\n\n        this.$hintMenu.find(\"ul.dropdown-menu\")\n            .append($item);\n    };\n\n    /**\n     * Rebuilds the hint list based on this.query\n     */\n    CodeHintList.prototype.updateList = function () {\n        this.displayList = this.currentProvider.search(this.query);\n        this.buildListView();\n    };\n\n    /**\n     * Removes all list items from hint list\n     */\n    CodeHintList.prototype.clearList = function () {\n        this.$hintMenu.find(\"li\").remove();\n    };\n            \n    /**\n     * Rebuilds the list items for the hint list based on this.displayList\n     */\n    CodeHintList.prototype.buildListView = function () {\n        this.clearList();\n        var self = this;\n        var count = 0;\n        $.each(this.displayList, function (index, item) {\n            if (count > self.options.maxResults) {\n                return false;\n            }\n            self.addItem(item);\n            count++;\n        });\n\n        if (count === 0) {\n            this.close();\n        } else {\n            // Select the first item in the list\n            this.setSelectedIndex(0);\n        }\n    };\n\n\n    /**\n     * Selects the item in the hint list specified by index\n     * @param {Number} index\n     */\n    CodeHintList.prototype.setSelectedIndex = function (index) {\n        var items = this.$hintMenu.find(\"li\");\n        \n        // Range check\n        index = Math.max(0, Math.min(index, items.length - 1));\n        \n        // Clear old highlight\n        if (this.selectedIndex !== -1) {\n            $(items[this.selectedIndex]).find(\"a\").removeClass(\"highlight\");\n        }\n        \n        // Highlight the new selected item\n        this.selectedIndex = index;\n\n        if (this.selectedIndex !== -1) {\n            var $item = $(items[this.selectedIndex]);\n            var $view = this.$hintMenu.find(\"ul.dropdown-menu\");\n\n            ViewUtils.scrollElementIntoView($view, $item, false);\n            $item.find(\"a\").addClass(\"highlight\");\n        }\n    };\n    \n    /**\n     * Handles key presses when the hint list is being displayed\n     * @param {Editor} editor\n     * @param {KeyBoardEvent} keyEvent\n     */\n    CodeHintList.prototype.handleKeyEvent = function (editor, event) {\n        var keyCode = event.keyCode;\n        \n        // Up arrow, down arrow and enter key are always handled here\n        if (event.type !== \"keypress\" &&\n                (keyCode === 38 || keyCode === 40 || keyCode === 13 ||\n                keyCode === 33 || keyCode === 34)) {\n\n            if (event.type === \"keydown\") {\n                if (keyCode === 38) {\n                    // Up arrow\n                    this.setSelectedIndex(this.selectedIndex - 1);\n                } else if (keyCode === 40) {\n                    // Down arrow\n                    this.setSelectedIndex(this.selectedIndex + 1);\n                } else if (keyCode === 33) {\n                    // Page Up\n                    this.setSelectedIndex(this.selectedIndex - this.getItemsPerPage());\n                } else if (keyCode === 34) {\n                    // Page Down\n                    this.setSelectedIndex(this.selectedIndex + this.getItemsPerPage());\n                } else {\n                    // Enter/return key\n                    // Trigger a click handler to commmit the selected item\n                    $(this.$hintMenu.find(\"li\")[this.selectedIndex]).triggerHandler(\"click\");\n                }\n            }\n            \n            event.preventDefault();\n            return;\n        }\n        \n        // All other key events trigger a rebuild of the list, but only\n        // on keyup events\n        if (event.type !== \"keyup\") {\n            return;\n        }\n\n        this.query = this.currentProvider.getQueryInfo(this.editor, this.editor.getCursorPos());\n        this.updateList();\n\n        // Update the CodeHintList location\n        if (this.displayList.length) {\n            var hintPos = this.calcHintListLocation();\n            this.$hintMenu.css({\"left\": hintPos.left, \"top\": hintPos.top});\n        }\n    };\n\n    /**\n     * Return true if the CodeHintList is open.\n     * @return {Boolean}\n     */\n    CodeHintList.prototype.isOpen = function () {\n        // We don't get a notification when the dropdown closes. The best\n        // we can do is keep an \"opened\" flag and check to see if we\n        // still have the \"open\" class applied.\n        if (this.opened && !this.$hintMenu.hasClass(\"open\")) {\n            this.opened = false;\n        }\n        \n        return this.opened;\n    };\n    \n    /**\n     * Displays the hint list at the current cursor position\n     * @param {Editor} editor\n     */\n    CodeHintList.prototype.open = function (editor) {\n        var self = this;\n        this.editor = editor;\n\n        Menus.closeAll();\n\n        this.currentProvider = null;\n        $.each(hintProviders, function (index, item) {\n            var query = item.getQueryInfo(self.editor, self.editor.getCursorPos());\n            if (query.queryStr !== null) {\n                self.query = query;\n                self.currentProvider = item;\n                return false;\n            }\n        });\n        if (!this.currentProvider) {\n            return;\n        }\n\n        this.updateList();\n    \n        if (this.displayList.length) {\n            // Need to add the menu to the DOM before trying to calculate its ideal location.\n            $(\"#codehint-menu-bar > ul\").append(this.$hintMenu);\n            \n            var hintPos = this.calcHintListLocation();\n            \n            this.$hintMenu.addClass(\"open\")\n                       .css({\"left\": hintPos.left, \"top\": hintPos.top});\n            this.opened = true;\n            \n            PopUpManager.addPopUp(this.$hintMenu, function () {\n                self.close();\n            });\n        }\n    };\n\n    /**\n     * Closes the hint list\n     */\n    CodeHintList.prototype.close = function () {\n        // TODO: Due to #1381, this won't get called if the user clicks out of the code hint menu.\n        // That's (sort of) okay right now since it doesn't really matter if a single old invisible\n        // code hint list is lying around (it'll get closed the next time the user pops up a code\n        // hint). Once #1381 is fixed this issue should go away.\n        this.$hintMenu.removeClass(\"open\");\n        this.opened = false;\n        this.currentProvider = null;\n        \n        PopUpManager.removePopUp(this.$hintMenu);\n        this.$hintMenu.remove();\n        if (hintList === this) {\n            hintList = null;\n        }\n    };\n        \n    /**\n     * Computes top left location for hint list so that the list is not clipped by the window\n     * @return {Object.<left: Number, top: Number> }\n     */\n    CodeHintList.prototype.calcHintListLocation = function () {\n        var cursor = this.editor._codeMirror.cursorCoords(),\n            posTop  = cursor.y,\n            posLeft = cursor.x,\n            $window = $(window),\n            $menuWindow = this.$hintMenu.children(\"ul\");\n\n        // TODO Ty: factor out menu repositioning logic so code hints and Context menus share code\n        // adjust positioning so menu is not clipped off bottom or right\n        var bottomOverhang = posTop + 25 + $menuWindow.height() - $window.height();\n        if (bottomOverhang > 0) {\n            posTop -= (27 + $menuWindow.height());\n        }\n        // todo: should be shifted by line height\n        posTop -= 15;   // shift top for hidden parent element\n        //posLeft += 5;\n\n        var rightOverhang = posLeft + $menuWindow.width() - $window.width();\n        if (rightOverhang > 0) {\n            posLeft = Math.max(0, posLeft - rightOverhang);\n        }\n\n        return {left: posLeft, top: posTop};\n    };\n\n    /**\n     * @private\n     * Calculate the number of items per scroll page. Used for PageUp and PageDown.\n     * @return {number}\n     */\n    CodeHintList.prototype.getItemsPerPage = function () {\n        var itemsPerPage = 1,\n            $items = this.$hintMenu.find(\"li\"),\n            $view = this.$hintMenu.find(\"ul.dropdown-menu\"),\n            itemHeight;\n\n        if ($items.length !== 0) {\n            itemHeight = $($items[0]).height();\n            if (itemHeight) {\n                // round down to integer value\n                itemsPerPage = Math.floor($view.height() / itemHeight);\n                itemsPerPage = Math.max(1, Math.min(itemsPerPage, $items.length));\n            }\n        }\n\n        return itemsPerPage;\n    };\n        \n     /**\n      * Show the code hint list near the current cursor position for the specified editor\n      * @param {Editor}\n      */\n    function showHint(editor) {\n        if (hintList) {\n            hintList.close();\n        }\n        hintList = new CodeHintList();\n        hintList.open(editor);\n    }\n    \n    /**\n     * Handles keys related to displaying, searching, and navigating the hint list\n     * @param {Editor} editor\n     * @param {KeyboardEvent} event\n     */\n    function handleKeyEvent(editor, event) {\n        var provider = null;\n        \n        // Check for Control+Space\n        if (event.type === \"keydown\" && event.keyCode === 32 && event.ctrlKey) {\n            showHint(editor);\n            event.preventDefault();\n        } else if (event.type === \"keypress\") {\n            // Check if any provider wants to show hints on this key.\n            $.each(hintProviders, function (index, item) {\n                if (item.shouldShowHintsOnKey(String.fromCharCode(event.charCode))) {\n                    provider = item;\n                    return false;\n                }\n            });\n            \n            shouldShowHintsOnKeyUp = !!provider;\n        } else if (event.type === \"keyup\") {\n            if (shouldShowHintsOnKeyUp) {\n                shouldShowHintsOnKeyUp = false;\n                showHint(editor);\n            }\n        }\n\n        // Pass to the hint list, if it's open\n        if (hintList && hintList.isOpen()) {\n            shouldShowHintsOnKeyUp = false;\n            hintList.handleKeyEvent(editor, event);\n        }\n    }\n\n    /**\n     * Registers an object that is able to provide code hints. When the user requests a code\n     * hint getQueryInfo() will be called on every hint provider. Providers should examine\n     * the state of the editor and return a search query object with a filter string if hints \n     * can be provided. search() will then be called allowing the hint provider to create a \n     * list of hints for the search query. When the user chooses a hint handleSelect() is called\n     * so that the hint provider can insert the hint into the editor.\n     *\n     * @param {Object.< getQueryInfo: function(editor, cursor),\n     *                  search: function(string),\n     *                  handleSelect: function(string, Editor, cursor),\n     *                  shouldShowHintsOnKey: function(string)>}\n     *\n     * Parameter Details:\n     * - getQueryInfo - examines cursor location of editor and returns an object representing\n     *      the search query to be used for hinting. queryStr is a required property of the search object\n     *      and a client may provide other properties on the object to carry more context about the query.\n     * - search - takes a query object and returns an array of hint strings based on the queryStr property\n     *      of the query object.\n     * - handleSelect - takes a completion string and inserts it into the editor near the cursor\n     *      position\n     * - shouldShowHintsOnKey - inspects the char code and returns true if it wants to show code hints on that key.\n     */\n    function registerHintProvider(providerInfo) {\n        hintProviders.push(providerInfo);\n    }\n\n    /**\n     * Expose CodeHintList for unit testing\n     */\n    function _getCodeHintList() {\n        return hintList;\n    }\n    \n    // Define public API\n    exports.handleKeyEvent          = handleKeyEvent;\n    exports.showHint                = showHint;\n    exports._getCodeHintList        = _getCodeHintList;\n    exports.registerHintProvider    = registerHintProvider;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror */\n\n/**\n */\ndefine('document/TextRange',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * @constructor\n     *\n     * Stores a range of lines that is automatically maintained as the Document changes. The range\n     * MAY drop out of sync with the Document in certain edge cases; startLine & endLine will become\n     * null when that happens.\n     *\n     * Important: you must dispose() a TextRange when you're done with it. Because TextRange addRef()s\n     * the Document (in order to listen to it), you will leak Documents otherwise.\n     *\n     * TextRange dispatches two events:\n     *  - change -- When the range changes (due to a Document change)\n     *  - lostSync -- When the backing Document changes in such a way that the range can no longer\n     *          accurately be maintained. Generally, occurs whenever an edit spans a range boundary.\n     *          After this, startLine & endLine will be unusable (set to null).\n     * These events only ever occur in response to Document changes, so if you are already listening\n     * to the Document, you could ignore the TextRange events and just read its updated value in your\n     * own Document change handler.\n     *\n     * @param {!Document} document\n     * @param {number} startLine First line in range (0-based, inclusive)\n     * @param {number} endLine   Last line in range (0-based, inclusive)\n     */\n    function TextRange(document, startLine, endLine) {\n        this.startLine = startLine;\n        this.endLine = endLine;\n        \n        this.document = document;\n        document.addRef();\n        // store this-bound version of listener so we can remove them later\n        this._handleDocumentChange = this._handleDocumentChange.bind(this);\n        $(document).on(\"change\", this._handleDocumentChange);\n    }\n    \n    /** Detaches from the Document. The TextRange will no longer update or send change events */\n    TextRange.prototype.dispose = function (editor, change) {\n        // Disconnect from Document\n        this.document.releaseRef();\n        $(this.document).off(\"change\", this._handleDocumentChange);\n    };\n    \n    \n    /** @type {!Document} */\n    TextRange.prototype.document = null;\n    /** @type {?number} Null after \"lostSync\" is dispatched */\n    TextRange.prototype.startLine = null;\n    /** @type {?number} Null after \"lostSync\" is dispatched */\n    TextRange.prototype.endLine = null;\n    \n    \n    /**\n     * Applies a single Document change object (out of the linked list of multiple such objects)\n     * to this range. Returns true if the range was changed as a result.\n     */\n    TextRange.prototype._applySingleChangeToRange = function (change) {\n        // console.log(this + \" applying change to (\" +\n        //         (change.from && (change.from.line+\",\"+change.from.ch)) + \" - \" +\n        //         (change.to && (change.to.line+\",\"+change.to.ch)) + \")\");\n        \n        // Special case: the range is no longer meaningful since the entire text was replaced\n        if (!change.from || !change.to) {\n            this.startLine = null;\n            this.endLine = null;\n            return true;\n            \n        // Special case: certain changes around the edges of the range are problematic, because\n        // if they're undone, we'll be unable to determine how to fix up the range to include the\n        // undone content. (The \"undo\" will just look like an insertion outside our bounds.) So\n        // in those cases, we destroy the range instead of fixing it up incorrectly. The specific\n        // cases are:\n        // 1. Edit crosses the start boundary of the inline editor (defined as character 0 \n        //    of the first line).\n        // 2. Edit crosses the end boundary of the inline editor (defined as the newline at\n        //    the end of the last line).\n        // Note: we also used to disallow edits that start at the beginning of the range (character 0\n        //    of the first line) if they crossed a newline. This was a vestige from before case #1\n        //    was added; now that edits crossing the top boundary (actually, undos of such edits) are\n        //    out of the picture, edits on the first line of the range unambiguously belong inside it.\n        } else if ((change.from.line < this.startLine && change.to.line >= this.startLine) ||\n                   (change.from.line <= this.endLine && change.to.line > this.endLine)) {\n            this.startLine = null;\n            this.endLine = null;\n            return true;\n            \n        // Normal case: update the range end points if any content was added before them. Note that\n        // we don't rely on line handles for this since we want to gracefully handle cases where the\n        // start or end line was deleted during a change.\n        } else {\n            var numAdded = change.text.length - (change.to.line - change.from.line + 1);\n            var hasChanged = false;\n            \n            // This logic is so simple because we've already excluded all cases where the change\n            // crosses the range boundaries\n            if (change.to.line < this.startLine) {\n                this.startLine += numAdded;\n                hasChanged = true;\n            }\n            if (change.to.line <= this.endLine) {\n                this.endLine += numAdded;\n                hasChanged = true;\n            }\n            \n            // console.log(\"Now \" + this);\n            \n            return hasChanged;\n        }\n    };\n    \n    /**\n     * Updates the range based on the changeList from a Document \"change\" event. Dispatches a\n     * \"change\" event if the range was adjusted at all. Dispatches a \"lostSync\" event instead if the\n     * range can no longer be accurately maintained.\n     */\n    TextRange.prototype._applyChangesToRange = function (changeList) {\n        var hasChanged = false;\n        var change;\n        for (change = changeList; change; change = change.next) {\n            // Apply this step of the change list\n            var result = this._applySingleChangeToRange(change);\n            hasChanged = hasChanged || result;\n            \n            // If we lost sync with the range, just bail now\n            if (this.startLine === null || this.endLine === null) {\n                $(this).triggerHandler(\"lostSync\");\n                break;\n            }\n        }\n        \n        if (hasChanged) {\n            $(this).triggerHandler(\"change\");\n        }\n    };\n    \n    TextRange.prototype._handleDocumentChange = function (event, doc, changeList) {\n        this._applyChangesToRange(changeList);\n    };\n    \n    \n    /* (pretty toString(), to aid debugging) */\n    TextRange.prototype.toString = function () {\n        return \"[TextRange \" + this.startLine + \"-\" + this.endLine + \" in \" + this.document + \"]\";\n    };\n    \n    \n    // Define public API\n    exports.TextRange = TextRange;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\n/**\n * Editor is a 1-to-1 wrapper for a CodeMirror editor instance. It layers on Brackets-specific\n * functionality and provides APIs that cleanly pass through the bits of CodeMirror that the rest\n * of our codebase may want to interact with. An Editor is always backed by a Document, and stays\n * in sync with its content; because Editor keeps the Document alive, it's important to always\n * destroy() an Editor that's going away so it can release its Document ref.\n *\n * For now, there's a distinction between the \"master\" Editor for a Document - which secretly acts\n * as the Document's internal model of the text state - and the multitude of \"slave\" secondary Editors\n * which, via Document, sync their changes to and from that master.\n *\n * For now, direct access to the underlying CodeMirror object is still possible via _codeMirror --\n * but this is considered deprecated and may go away.\n *  \n * The Editor object dispatches the following events:\n *    - keyEvent -- When any key event happens in the editor (whether it changes the text or not).\n *          Event handlers are passed ({Editor}, {KeyboardEvent}). The 2nd arg is the raw DOM event.\n *          Note: most listeners will only want to respond when event.type === \"keypress\".\n *    - cursorActivity -- When the user moves the cursor or changes the selection, or an edit occurs.\n *          Note: do not listen to this in order to be generally informed of edits--listen to the\n *          \"change\" event on Document instead.\n *    - scroll -- When the editor is scrolled, either by user action or programmatically.\n *    - lostContent -- When the backing Document changes in such a way that this Editor is no longer\n *          able to display accurate text. This occurs if the Document's file is deleted, or in certain\n *          Document->editor syncing edge cases that we do not yet support (the latter cause will\n *          eventually go away). \n *\n * The Editor also dispatches \"change\" events internally, but you should listen for those on\n * Documents, not Editors.\n *\n * These are jQuery events, so to listen for them you do something like this:\n *    $(editorInstance).on(\"eventname\", handler);\n */\ndefine('editor/Editor',['require','exports','module','editor/EditorManager','editor/CodeHintManager','command/Commands','command/CommandManager','command/Menus','utils/PerfUtils','strings','document/TextRange','utils/ViewUtils'],function (require, exports, module) {\n    \n    \n    var EditorManager   = require(\"editor/EditorManager\"),\n        CodeHintManager = require(\"editor/CodeHintManager\"),\n        Commands        = require(\"command/Commands\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        Menus           = require(\"command/Menus\"),\n        PerfUtils       = require(\"utils/PerfUtils\"),\n        Strings         = require(\"strings\"),\n        TextRange       = require(\"document/TextRange\").TextRange,\n        ViewUtils       = require(\"utils/ViewUtils\");\n    \n\n    /**\n     * @private\n     * Handle Tab key press.\n     * @param {!CodeMirror} instance CodeMirror instance.\n     */\n    function _handleTabKey(instance) {\n        // Tab key handling is done as follows:\n        // 1. If the selection is before any text and the indentation is to the left of \n        //    the proper indentation then indent it to the proper place. Otherwise,\n        //    add another tab. In either case, move the insertion point to the \n        //    beginning of the text.\n        // 2. If the selection is after the first non-space character, and is not an \n        //    insertion point, indent the entire line(s).\n        // 3. If the selection is after the first non-space character, and is an \n        //    insertion point, insert a tab character or the appropriate number \n        //    of spaces to pad to the nearest tab boundary.\n        var from = instance.getCursor(true),\n            to = instance.getCursor(false),\n            line = instance.getLine(from.line),\n            indentAuto = false,\n            insertTab = false;\n        \n        if (from.line === to.line) {\n            if (line.search(/\\S/) > to.ch || to.ch === 0) {\n                indentAuto = true;\n            }\n        }\n\n        if (indentAuto) {\n            var currentLength = line.length;\n            CodeMirror.commands.indentAuto(instance);\n            // If the amount of whitespace didn't change, insert another tab\n            if (instance.getLine(from.line).length === currentLength) {\n                insertTab = true;\n                to.ch = 0;\n            }\n        } else if (instance.somethingSelected()) {\n            CodeMirror.commands.indentMore(instance);\n        } else {\n            insertTab = true;\n        }\n        \n        if (insertTab) {\n            if (instance.getOption(\"indentWithTabs\")) {\n                CodeMirror.commands.insertTab(instance);\n            } else {\n                var i, ins = \"\", numSpaces = instance.getOption(\"tabSize\");\n                numSpaces -= to.ch % numSpaces;\n                for (i = 0; i < numSpaces; i++) {\n                    ins += \" \";\n                }\n                instance.replaceSelection(ins, \"end\");\n            }\n        }\n    }\n    \n    /**\n     * @private\n     * Handle left arrow, right arrow, backspace and delete keys when soft tabs are used.\n     * @param {!CodeMirror} instance CodeMirror instance \n     * @param {number} direction Direction of movement: 1 for forward, -1 for backward\n     * @param {function} functionName name of the CodeMirror function to call\n     * @return {boolean} true if key was handled\n     */\n    function _handleSoftTabNavigation(instance, direction, functionName) {\n        var handled = false;\n        if (!instance.getOption(\"indentWithTabs\")) {\n            var cursor = instance.getCursor(),\n                tabSize = instance.getOption(\"tabSize\"),\n                jump = cursor.ch % tabSize,\n                line = instance.getLine(cursor.line);\n\n            if (direction === 1) {\n                jump = tabSize - jump;\n\n                if (cursor.ch + jump > line.length) { // Jump would go beyond current line\n                    return false;\n                }\n\n                if (line.substr(cursor.ch, jump).search(/\\S/) === -1) {\n                    instance[functionName](jump, \"char\");\n                    handled = true;\n                }\n            } else {\n                // Quick exit if we are at the beginning of the line\n                if (cursor.ch === 0) {\n                    return false;\n                }\n                \n                // If we are on the tab boundary, jump by the full amount, \n                // but not beyond the start of the line.\n                if (jump === 0) {\n                    jump = tabSize;\n                }\n\n                // Search backwards to the first non-space character\n                var offset = line.substr(cursor.ch - jump, jump).search(/\\s*$/g);\n\n                if (offset !== -1) { // Adjust to jump to first non-space character\n                    jump -= offset;\n                }\n\n                if (jump > 0) {\n                    instance[functionName](-jump, \"char\");\n                    handled = true;\n                }\n            }\n        }\n\n        return handled;\n    }\n    \n    /**\n     * Checks if the user just typed a closing brace/bracket/paren, and considers automatically\n     * back-indenting it if so.\n     */\n    function _checkElectricChars(jqEvent, editor, event) {\n        var instance = editor._codeMirror;\n        if (event.type === \"keypress\") {\n            var keyStr = String.fromCharCode(event.which || event.keyCode);\n            if (/[\\]\\{\\}\\)]/.test(keyStr)) {\n                // If all text before the cursor is whitespace, auto-indent it\n                var cursor = instance.getCursor();\n                var lineStr = instance.getLine(cursor.line);\n                var nonWS = lineStr.search(/\\S/);\n                \n                if (nonWS === -1 || nonWS >= cursor.ch) {\n                    // Need to do the auto-indent on a timeout to ensure\n                    // the keypress is handled before auto-indenting.\n                    // This is the same timeout value used by the\n                    // electricChars feature in CodeMirror.\n                    window.setTimeout(function () {\n                        instance.indentLine(cursor.line);\n                    }, 75);\n                }\n            }\n        }\n    }\n\n    function _handleKeyEvents(jqEvent, editor, event) {\n        _checkElectricChars(jqEvent, editor, event);\n\n        // Pass the key event to the code hint manager. It may call preventDefault() on the event.\n        CodeHintManager.handleKeyEvent(editor, event);\n    }\n\n    function _handleSelectAll() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            editor._selectAllVisible();\n        }\n    }\n    \n    \n    /**\n     * List of all current (non-destroy()ed) Editor instances. Needed when changing global preferences\n     * that affect all editors, e.g. tabbing or color scheme settings.\n     * @type {Array.<Editor>}\n     */\n    var _instances = [];\n    \n    /** @type {boolean}  Global setting: When inserting new text, use tab characters? (instead of spaces) */\n    var _useTabChar = false;\n    \n    \n    \n    /**\n     * @constructor\n     *\n     * Creates a new CodeMirror editor instance bound to the given Document. The Document need not have\n     * a \"master\" Editor realized yet, even if makeMasterEditor is false; in that case, the first time\n     * an edit occurs we will automatically ask EditorManager to create a \"master\" editor to render the\n     * Document modifiable.\n     *\n     * ALWAYS call destroy() when you are done with an Editor - otherwise it will leak a Document ref.\n     *\n     * @param {!Document} document  \n     * @param {!boolean} makeMasterEditor  If true, this Editor will set itself as the (secret) \"master\"\n     *          Editor for the Document. If false, this Editor will attach to the Document as a \"slave\"/\n     *          secondary editor.\n     * @param {!string} mode  Syntax-highlighting language mode; \"\" means plain-text mode.\n     *          See {@link EditorUtils#getModeFromFileExtension()}.\n     * @param {!jQueryObject} container  Container to add the editor to.\n     * @param {!Object<string, function(Editor)>} additionalKeys  Mapping of keyboard shortcuts to\n     *          custom handler functions. Mapping is in CodeMirror format\n     * @param {{startLine: number, endLine: number}=} range If specified, range of lines within the document\n     *          to display in this editor. Inclusive.\n     */\n    function Editor(document, makeMasterEditor, mode, container, additionalKeys, range) {\n        var self = this;\n        \n        _instances.push(this);\n        \n        // Attach to document: add ref & handlers\n        this.document = document;\n        document.addRef();\n        \n        if (range) {    // attach this first: want range updated before we process a change\n            this._visibleRange = new TextRange(document, range.startLine, range.endLine);\n        }\n        \n        // store this-bound version of listeners so we can remove them later\n        this._handleDocumentChange = this._handleDocumentChange.bind(this);\n        this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);\n        $(document).on(\"change\", this._handleDocumentChange);\n        $(document).on(\"deleted\", this._handleDocumentDeleted);\n        \n        // (if makeMasterEditor, we attach the Doc back to ourselves below once we're fully initialized)\n        \n        this._inlineWidgets = [];\n        \n        // Editor supplies some standard keyboard behavior extensions of its own\n        var codeMirrorKeyMap = {\n            \"Tab\": _handleTabKey,\n            \"Shift-Tab\": \"indentLess\",\n\n            \"Left\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, -1, \"moveH\")) {\n                    CodeMirror.commands.goCharLeft(instance);\n                }\n            },\n            \"Right\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, 1, \"moveH\")) {\n                    CodeMirror.commands.goCharRight(instance);\n                }\n            },\n            \"Backspace\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, -1, \"deleteH\")) {\n                    CodeMirror.commands.delCharLeft(instance);\n                }\n            },\n            \"Delete\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, 1, \"deleteH\")) {\n                    CodeMirror.commands.delCharRight(instance);\n                }\n            },\n            \"Esc\": function (instance) {\n                self.removeAllInlineWidgets();\n            },\n            \"Shift-Delete\": \"cut\",\n            \"Ctrl-Insert\": \"copy\",\n            \"Shift-Insert\": \"paste\"\n        };\n        \n        EditorManager.mergeExtraKeys(self, codeMirrorKeyMap, additionalKeys);\n        \n        // We'd like null/\"\" to mean plain text mode. CodeMirror defaults to plaintext for any\n        // unrecognized mode, but it complains on the console in that fallback case: so, convert\n        // here so we're always explicit, avoiding console noise.\n        if (!mode) {\n            mode = \"text/plain\";\n        }\n        \n        // Create the CodeMirror instance\n        // (note: CodeMirror doesn't actually require using 'new', but jslint complains without it)\n        this._codeMirror = new CodeMirror(container, {\n            electricChars: false,   // we use our own impl of this to avoid CodeMirror bugs; see _checkElectricChars()\n            indentUnit: 4,\n            indentWithTabs: _useTabChar,\n            lineNumbers: true,\n            matchBrackets: true,\n            dragDrop: false,    // work around issue #1123\n            extraKeys: codeMirrorKeyMap\n        });\n        \n        this._installEditorListeners();\n        \n        $(this)\n            .on(\"keyEvent\", _handleKeyEvents)\n            .on(\"change\", this._handleEditorChange.bind(this));\n        \n        // Set code-coloring mode BEFORE populating with text, to avoid a flash of uncolored text\n        this._codeMirror.setOption(\"mode\", mode);\n        \n        // Initially populate with text. This will send a spurious change event, so need to make\n        // sure this is understood as a 'sync from document' case, not a genuine edit\n        this._duringSync = true;\n        this._resetText(document.getText());\n        this._duringSync = false;\n        \n        if (range) {\n            // Hide all lines other than those we want to show. We do this rather than trimming the\n            // text itself so that the editor still shows accurate line numbers.\n            this._codeMirror.operation(function () {\n                var i;\n                for (i = 0; i < range.startLine; i++) {\n                    self._hideLine(i);\n                }\n                var lineCount = self.lineCount();\n                for (i = range.endLine + 1; i < lineCount; i++) {\n                    self._hideLine(i);\n                }\n            });\n            this.setCursorPos(range.startLine, 0);\n        }\n\n        // Now that we're fully initialized, we can point the document back at us if needed\n        if (makeMasterEditor) {\n            document._makeEditable(this);\n        }\n        \n        // Add scrollTop property to this object for the scroll shadow code to use\n        Object.defineProperty(this, \"scrollTop\", {\n            get: function () {\n                return this._codeMirror.getScrollInfo().y;\n            }\n        });\n    }\n    \n    /**\n     * Removes this editor from the DOM and detaches from the Document. If this is the \"master\"\n     * Editor that is secretly providing the Document's backing state, then the Document reverts to\n     * a read-only string-backed mode.\n     */\n    Editor.prototype.destroy = function () {\n        // CodeMirror docs for getWrapperElement() say all you have to do is \"Remove this from your\n        // tree to delete an editor instance.\"\n        $(this.getRootElement()).remove();\n        \n        _instances.splice(_instances.indexOf(this), 1);\n        \n        // Disconnect from Document\n        this.document.releaseRef();\n        $(this.document).off(\"change\", this._handleDocumentChange);\n        $(this.document).off(\"deleted\", this._handleDocumentDeleted);\n        \n        if (this._visibleRange) {   // TextRange also refs the Document\n            this._visibleRange.dispose();\n        }\n        \n        // If we're the Document's master editor, disconnecting from it has special meaning\n        if (this.document._masterEditor === this) {\n            this.document._makeNonEditable();\n        }\n        \n        // Destroying us destroys any inline widgets we're hosting. Make sure their closeCallbacks\n        // run, at least, since they may also need to release Document refs\n        this._inlineWidgets.forEach(function (inlineWidget) {\n            inlineWidget.onClosed();\n        });\n    };\n    \n        \n    /** \n     * Handles Select All specially when we have a visible range in order to work around\n     * bugs in CodeMirror when lines are hidden.\n     */\n    Editor.prototype._selectAllVisible = function () {\n        var startLine = this.getFirstVisibleLine(),\n            endLine = this.getLastVisibleLine();\n        this.setSelection({line: startLine, ch: 0},\n                          {line: endLine, ch: this.document.getLine(endLine).length});\n    };\n    \n    Editor.prototype._applyChanges = function (changeList) {\n        var self = this;\n        \n        // _visibleRange has already updated via its own Document listener. See if this change caused\n        // it to lose sync. If so, our whole view is stale - signal our owner to close us.\n        if (this._visibleRange) {\n            if (this._visibleRange.startLine === null || this._visibleRange.endLine === null) {\n                $(self).triggerHandler(\"lostContent\");\n                return;\n            }\n        }\n        \n        // Apply text changes to CodeMirror editor\n        var cm = this._codeMirror;\n        cm.operation(function () {\n            var change, newText;\n            for (change = changeList; change; change = change.next) {\n                newText = change.text.join('\\n');\n                if (!change.from || !change.to) {\n                    if (change.from || change.to) {\n                        console.assert(false, \"Change record received with only one end undefined--replacing entire text\");\n                    }\n                    cm.setValue(newText);\n                } else {\n                    cm.replaceRange(newText, change.from, change.to);\n                }\n                \n            }\n        });\n        \n        // The update above may have inserted new lines - must hide any that fall outside our range\n        if (self._visibleRange) {\n            cm.operation(function () {\n                // TODO: could make this more efficient by only iterating across the min-max line\n                // range of the union of all changes\n                var i;\n                for (i = 0; i < cm.lineCount(); i++) {\n                    if (i < self._visibleRange.startLine || i > self._visibleRange.endLine) {\n                        self._hideLine(i);\n                    } else {\n                        // Double-check that the set of NON-hidden lines matches our range too\n                        console.assert(!cm.getLineHandle(i).hidden);\n                    }\n                }\n            });\n        }\n    };\n    \n    /**\n     * Responds to changes in the CodeMirror editor's text, syncing the changes to the Document.\n     * There are several cases where we want to ignore a CodeMirror change:\n     *  - if we're the master editor, editor changes can be ignored because Document is already listening\n     *    for our changes\n     *  - if we're a secondary editor, editor changes should be ignored if they were caused by us reacting\n     *    to a Document change\n     */\n    Editor.prototype._handleEditorChange = function (event, editor, changeList) {\n        // we're currently syncing from the Document, so don't echo back TO the Document\n        if (this._duringSync) {\n            return;\n        }\n        \n        // Secondary editor: force creation of \"master\" editor backing the model, if doesn't exist yet\n        this.document._ensureMasterEditor();\n        \n        if (this.document._masterEditor !== this) {\n            // Secondary editor:\n            // we're not the ground truth; if we got here, this was a real editor change (not a\n            // sync from the real ground truth), so we need to sync from us into the document\n            // (which will directly push the change into the master editor).\n            // FUTURE: Technically we should add a replaceRange() method to Document and go through\n            // that instead of talking to its master editor directly. It's not clear yet exactly\n            // what the right Document API would be, though.\n            this._duringSync = true;\n            this.document._masterEditor._applyChanges(changeList);\n            this._duringSync = false;\n        }\n        // Else, Master editor:\n        // we're the ground truth; nothing else to do, since Document listens directly to us\n        // note: this change might have been a real edit made by the user, OR this might have\n        // been a change synced from another editor\n        \n        if (this._visibleRange) {\n            // _visibleRange has already updated via its own Document listener, when we pushed our\n            // change into the Document above (_masterEditor._applyChanges()). But changes due to our\n            // own edits should never cause the range to lose sync - verify that.\n            if (this._visibleRange.startLine === null || this._visibleRange.endLine === null) {\n                throw new Error(\"ERROR: Typing in Editor should not destroy its own _visibleRange\");\n            }\n        }\n    };\n    \n    /**\n     * Responds to changes in the Document's text, syncing the changes into our CodeMirror instance.\n     * There are several cases where we want to ignore a Document change:\n     *  - if we're the master editor, Document changes should be ignored becuase we already have the right\n     *    text (either the change originated with us, or it has already been set into us by Document)\n     *  - if we're a secondary editor, Document changes should be ignored if they were caused by us sending\n     *    the document an editor change that originated with us\n     */\n    Editor.prototype._handleDocumentChange = function (event, doc, changeList) {\n        var change;\n        \n        // we're currently syncing to the Document, so don't echo back FROM the Document\n        if (this._duringSync) {\n            return;\n        }\n        \n        if (this.document._masterEditor !== this) {\n            // Secondary editor:\n            // we're not the ground truth; and if we got here, this was a Document change that\n            // didn't come from us (e.g. a sync from another editor, a direct programmatic change\n            // to the document, or a sync from external disk changes)... so sync from the Document\n            this._duringSync = true;\n            this._applyChanges(changeList);\n            this._duringSync = false;\n        }\n        // Else, Master editor:\n        // we're the ground truth; nothing to do since Document change is just echoing our\n        // editor changes\n    };\n    \n    /**\n     * Responds to the Document's underlying file being deleted. The Document is now basically dead,\n     * so we must close.\n     */\n    Editor.prototype._handleDocumentDeleted = function () {\n        $(this).triggerHandler(\"lostContent\");\n    };\n    \n    \n    /**\n     * Install singleton event handlers on the CodeMirror instance, translating them into multi-\n     * listener-capable jQuery events on the Editor instance.\n     */\n    Editor.prototype._installEditorListeners = function () {\n        var self = this;\n        \n        // FUTURE: if this list grows longer, consider making this a more generic mapping\n        // NOTE: change is a \"private\" event--others shouldn't listen to it on Editor, only on\n        // Document\n        this._codeMirror.setOption(\"onChange\", function (instance, changeList) {\n            $(self).triggerHandler(\"change\", [self, changeList]);\n        });\n        this._codeMirror.setOption(\"onKeyEvent\", function (instance, event) {\n            $(self).triggerHandler(\"keyEvent\", [self, event]);\n            return event.defaultPrevented;   // false tells CodeMirror we didn't eat the event\n        });\n        this._codeMirror.setOption(\"onCursorActivity\", function (instance) {\n            $(self).triggerHandler(\"cursorActivity\", [self]);\n        });\n        this._codeMirror.setOption(\"onScroll\", function (instance) {\n            // close all dropdowns on scroll\n            Menus.closeAll();\n\n            $(self).triggerHandler(\"scroll\", [self]);\n        \n            // notify all inline widgets of a position change\n            self._fireWidgetOffsetTopChanged(self.getFirstVisibleLine() - 1);\n        });\n    };\n    \n    /**\n     * Sets the contents of the editor and clears the undo/redo history. Dispatches a change event.\n     * Semi-private: only Document should call this.\n     * @param {!string} text\n     */\n    Editor.prototype._resetText = function (text) {\n        var perfTimerName = PerfUtils.markStart(\"Edtitor._resetText()\\t\" + (!this.document || this.document.file.fullPath));\n\n        var cursorPos = this.getCursorPos(),\n            scrollPos = this.getScrollPos();\n        \n        // This *will* fire a change event, but we clear the undo immediately afterward\n        this._codeMirror.setValue(text);\n        \n        // Make sure we can't undo back to the empty state before setValue()\n        this._codeMirror.clearHistory();\n        \n        // restore cursor and scroll positions\n        this.setCursorPos(cursorPos);\n        this.setScrollPos(scrollPos.x, scrollPos.y);\n\n        PerfUtils.addMeasurement(perfTimerName);\n    };\n    \n    \n    /**\n     * Gets the current cursor position within the editor. If there is a selection, returns whichever\n     * end of the range the cursor lies at.\n     * @return !{line:number, ch:number}\n     */\n    Editor.prototype.getCursorPos = function () {\n        return this._codeMirror.getCursor();\n    };\n    \n    /**\n     * Sets the cursor position within the editor. Removes any selection.\n     * @param {number} line The 0 based line number.\n     * @param {number=} ch  The 0 based character position; treated as 0 if unspecified.\n     */\n    Editor.prototype.setCursorPos = function (line, ch) {\n        this._codeMirror.setCursor(line, ch);\n    };\n\n    /**\n     * Given a position, returns its index within the text (assuming \\n newlines)\n     * @param {!{line:number, ch:number}}\n     * @return {number}\n     */\n    Editor.prototype.indexFromPos = function (coords) {\n        return this._codeMirror.indexFromPos(coords);\n    };\n\n    /**\n     * Returns true if pos is between start and end (inclusive at both ends)\n     * @param {{line:number, ch:number}} pos\n     * @param {{line:number, ch:number}} start\n     * @param {{line:number, ch:number}} end\n     *\n     */\n    Editor.prototype.posWithinRange = function (pos, start, end) {\n        var startIndex = this.indexFromPos(start),\n            endIndex = this.indexFromPos(end),\n            posIndex = this.indexFromPos(pos);\n\n        return posIndex >= startIndex && posIndex <= endIndex;\n    };\n    \n    /**\n     * @return {boolean} True if there's a text selection; false if there's just an insertion point\n     */\n    Editor.prototype.hasSelection = function () {\n        return this._codeMirror.somethingSelected();\n    };\n    \n    /**\n     * Gets the current selection. Start is inclusive, end is exclusive. If there is no selection,\n     * returns the current cursor position as both the start and end of the range (i.e. a selection\n     * of length zero).\n     * @return {!{start:{line:number, ch:number}, end:{line:number, ch:number}}}\n     */\n    Editor.prototype.getSelection = function () {\n        var selStart = this._codeMirror.getCursor(true),\n            selEnd   = this._codeMirror.getCursor(false);\n        return { start: selStart, end: selEnd };\n    };\n    \n    /**\n     * @return {!string} The currently selected text, or \"\" if no selection. Includes \\n if the\n     * selection spans multiple lines (does NOT reflect the Document's line-endings style).\n     */\n    Editor.prototype.getSelectedText = function () {\n        return this._codeMirror.getSelection();\n    };\n    \n    /**\n     * Sets the current selection. Start is inclusive, end is exclusive. Places the cursor at the\n     * end of the selection range.\n     * @param {!{line:number, ch:number}} start\n     * @param {!{line:number, ch:number}} end\n     */\n    Editor.prototype.setSelection = function (start, end) {\n        this._codeMirror.setSelection(start, end);\n    };\n\n    /**\n     * Selects word that the given pos lies within or adjacent to. If pos isn't touching a word\n     * (e.g. within a token like \"//\"), moves the cursor to pos without selecting a range.\n     * @param {!{line:number, ch:number}}\n     */\n    Editor.prototype.selectWordAt = function (pos) {\n        this._codeMirror.selectWordAt(pos);\n    };\n    \n\n    /**\n     * Gets the total number of lines in the the document (includes lines not visible in the viewport)\n     * @returns {!number}\n     */\n    Editor.prototype.lineCount = function () {\n        return this._codeMirror.lineCount();\n    };\n    \n    /**\n     * Gets the number of the first visible line in the editor.\n     * @returns {number} The 0-based index of the first visible line.\n     */\n    Editor.prototype.getFirstVisibleLine = function () {\n        return (this._visibleRange ? this._visibleRange.startLine : 0);\n    };\n    \n    /**\n     * Gets the number of the last visible line in the editor.\n     * @returns {number} The 0-based index of the last visible line.\n     */\n    Editor.prototype.getLastVisibleLine = function () {\n        return (this._visibleRange ? this._visibleRange.endLine : this.lineCount() - 1);\n    };\n\n    // FUTURE change to \"hideLines()\" API that hides a range of lines at once in a single operation, then fires offsetTopChanged afterwards.\n    /* Hides the specified line number in the editor\n     * @param {!number}\n     */\n    Editor.prototype._hideLine = function (lineNumber) {\n        var value = this._codeMirror.hideLine(lineNumber);\n        \n        // when this line is hidden, notify all following inline widgets of a position change\n        this._fireWidgetOffsetTopChanged(lineNumber);\n        \n        return value;\n    };\n\n    /**\n     * Gets the total height of the document in pixels (not the viewport)\n     * @param {!boolean} includePadding\n     * @returns {!number} height in pixels\n     */\n    Editor.prototype.totalHeight = function (includePadding) {\n        return this._codeMirror.totalHeight(includePadding);\n    };\n\n    /**\n     * Gets the scroller element from the editor.\n     * @returns {!HTMLDivElement} scroller\n     */\n    Editor.prototype.getScrollerElement = function () {\n        return this._codeMirror.getScrollerElement();\n    };\n    \n    /**\n     * Gets the root DOM node of the editor.\n     * @returns {Object} The editor's root DOM node.\n     */\n    Editor.prototype.getRootElement = function () {\n        return this._codeMirror.getWrapperElement();\n    };\n    \n    /**\n     * Gets the lineSpace element within the editor (the container around the individual lines of code).\n     * FUTURE: This is fairly CodeMirror-specific. Logic that depends on this may break if we switch\n     * editors.\n     * @returns {Object} The editor's lineSpace element.\n     */\n    Editor.prototype._getLineSpaceElement = function () {\n        return $(\".CodeMirror-lines\", this.getScrollerElement()).children().get(0);\n    };\n    \n    /**\n     * Returns the current scroll position of the editor.\n     * @returns {{x:number, y:number}} The x,y scroll position in pixels\n     */\n    Editor.prototype.getScrollPos = function () {\n        return this._codeMirror.getScrollInfo();\n    };\n    \n    /**\n     * Sets the current scroll position of the editor.\n     * @param {number} x scrollLeft position in pixels\n     * @param {number} y scrollTop position in pixels\n     */\n    Editor.prototype.setScrollPos = function (x, y) {\n        this._codeMirror.scrollTo(x, y);\n    };\n\n    /**\n     * Adds an inline widget below the given line. If any inline widget was already open for that\n     * line, it is closed without warning.\n     * @param {!{line:number, ch:number}} pos  Position in text to anchor the inline.\n     * @param {!InlineWidget} inlineWidget The widget to add.\n     */\n    Editor.prototype.addInlineWidget = function (pos, inlineWidget) {\n        var self = this;\n        inlineWidget.id = this._codeMirror.addInlineWidget(pos, inlineWidget.htmlContent, inlineWidget.height, function (id) {\n            self._removeInlineWidgetInternal(id);\n            inlineWidget.onClosed();\n        });\n        this._inlineWidgets.push(inlineWidget);\n        inlineWidget.onAdded();\n        \n        // once this widget is added, notify all following inline widgets of a position change\n        this._fireWidgetOffsetTopChanged(pos.line);\n    };\n    \n    /**\n     * Removes all inline widgets\n     */\n    Editor.prototype.removeAllInlineWidgets = function () {\n        // copy the array because _removeInlineWidgetInternal will modifying the original\n        var widgets = [].concat(this.getInlineWidgets());\n        \n        widgets.forEach(function (widget) {\n            this.removeInlineWidget(widget);\n        }, this);\n    };\n    \n    /**\n     * Removes the given inline widget.\n     * @param {number} inlineWidget The widget to remove.\n     */\n    Editor.prototype.removeInlineWidget = function (inlineWidget) {\n        var lineNum = this._getInlineWidgetLineNumber(inlineWidget);\n        \n        // _removeInlineWidgetInternal will get called from the destroy callback in CodeMirror.\n        this._codeMirror.removeInlineWidget(inlineWidget.id);\n        \n        // once this widget is removed, notify all following inline widgets of a position change\n        this._fireWidgetOffsetTopChanged(lineNum);\n    };\n    \n    /**\n     * Cleans up the given inline widget from our internal list of widgets.\n     * @param {number} inlineId  id returned by addInlineWidget().\n     */\n    Editor.prototype._removeInlineWidgetInternal = function (inlineId) {\n        var i;\n        var l = this._inlineWidgets.length;\n        for (i = 0; i < l; i++) {\n            if (this._inlineWidgets[i].id === inlineId) {\n                this._inlineWidgets.splice(i, 1);\n                break;\n            }\n        }\n    };\n\n    /**\n     * Returns a list of all inline widgets currently open in this editor. Each entry contains the\n     * inline's id, and the data parameter that was passed to addInlineWidget().\n     * @return {!Array.<{id:number, data:Object}>}\n     */\n    Editor.prototype.getInlineWidgets = function () {\n        return this._inlineWidgets;\n    };\n\n    /**\n     * Sets the height of an inline widget in this editor. \n     * @param {!InlineWidget} inlineWidget The widget whose height should be set.\n     * @param {!number} height The height of the widget.\n     * @param {boolean} ensureVisible Whether to scroll the entire widget into view.\n     */\n    Editor.prototype.setInlineWidgetHeight = function (inlineWidget, height, ensureVisible) {\n        var info = this._codeMirror.getInlineWidgetInfo(inlineWidget.id),\n            oldHeight = (info && info.height) || 0;\n        \n        this._codeMirror.setInlineWidgetHeight(inlineWidget.id, height, ensureVisible);\n        \n        // update position for all following inline editors\n        if (oldHeight !== height) {\n            var lineNum = this._getInlineWidgetLineNumber(inlineWidget);\n            this._fireWidgetOffsetTopChanged(lineNum);\n        }\n    };\n    \n    /**\n     * @private\n     * Get the starting line number for an inline widget.\n     * @param {!InlineWidget} inlineWidget \n     * @return {number} The line number of the widget or -1 if not found.\n     */\n    Editor.prototype._getInlineWidgetLineNumber = function (inlineWidget) {\n        var info = this._codeMirror.getInlineWidgetInfo(inlineWidget.id);\n        return (info && info.line) || -1;\n    };\n    \n    /**\n     * @private\n     * Fire \"offsetTopChanged\" events when inline editor positions change due to\n     * height changes of other inline editors.\n     * @param {!InlineWidget} inlineWidget \n     */\n    Editor.prototype._fireWidgetOffsetTopChanged = function (lineNum) {\n        var self = this,\n            otherLineNum;\n        \n        this.getInlineWidgets().forEach(function (other) {\n            otherLineNum = self._getInlineWidgetLineNumber(other);\n            \n            if (otherLineNum > lineNum) {\n                $(other).triggerHandler(\"offsetTopChanged\");\n            }\n        });\n    };\n    \n    /** Gives focus to the editor control */\n    Editor.prototype.focus = function () {\n        this._codeMirror.focus();\n    };\n    \n    /** Returns true if the editor has focus */\n    Editor.prototype.hasFocus = function () {\n        // The CodeMirror instance wrapper has a \"CodeMirror-focused\" class set when focused\n        return $(this.getScrollerElement()).hasClass(\"CodeMirror-focused\");\n    };\n    \n    /**\n     * Re-renders the editor UI\n     */\n    Editor.prototype.refresh = function () {\n        this._codeMirror.refresh();\n    };\n    \n    /**\n     * Re-renders the editor, and all children inline editors.\n     */\n    Editor.prototype.refreshAll = function () {\n        this.refresh();\n        this.getInlineWidgets().forEach(function (multilineEditor, i, arr) {\n            multilineEditor.sizeInlineWidgetToContents(true);\n            multilineEditor._updateRelatedContainer();\n            multilineEditor.editors.forEach(function (editor, j, arr) {\n                editor.refresh();\n            });\n        });\n    };\n    \n    /**\n     * Shows or hides the editor within its parent. Does not force its ancestors to\n     * become visible.\n     * @param {boolean} show true to show the editor, false to hide it\n     */\n    Editor.prototype.setVisible = function (show) {\n        $(this.getRootElement()).css(\"display\", (show ? \"\" : \"none\"));\n        this._codeMirror.refresh();\n        if (show) {\n            this._inlineWidgets.forEach(function (inlineWidget) {\n                inlineWidget.onParentShown();\n            });\n        }\n    };\n    \n    /**\n     * Returns true if the editor is fully visible--i.e., is in the DOM, all ancestors are\n     * visible, and has a non-zero width/height.\n     */\n    Editor.prototype.isFullyVisible = function () {\n        return $(this.getRootElement()).is(\":visible\");\n    };\n    \n    /**\n     * Gets the syntax-highlighting mode for the current selection or cursor position. (The mode may\n     * vary within one file due to embedded languages, e.g. JS embedded in an HTML script block).\n     *\n     * Returns null if the mode at the start of the selection differs from the mode at the end -\n     * an *approximation* of whether the mode is consistent across the whole range (a pattern like\n     * A-B-A would return A as the mode, not null).\n     *\n     * @return {?string} Name of syntax-highlighting mode; see {@link EditorUtils#getModeFromFileExtension()}.\n     */\n    Editor.prototype.getModeForSelection = function () {\n        var sel = this.getSelection();\n        \n        // Check for mixed mode info (meaning mode varies depending on position)\n        // TODO (#921): this only works for certain mixed modes; some do not expose this info\n        var startState = this._codeMirror.getTokenAt(sel.start).state;\n        if (startState.mode) {\n            var startMode = startState.mode;\n            \n            // If mixed mode, check that mode is the same at start & end of selection\n            if (sel.start.line !== sel.end.line || sel.start.ch !== sel.end.ch) {\n                var endState = this._codeMirror.getTokenAt(sel.end).state;\n                var endMode = endState.mode;\n                if (startMode !== endMode) {\n                    return null;\n                }\n            }\n            return startMode;\n            \n        } else {\n            // Mode does not vary: just use the editor-wide mode\n            return this._codeMirror.getOption(\"mode\");\n        }\n    };\n    \n    /**\n     * The Document we're bound to\n     * @type {!Document}\n     */\n    Editor.prototype.document = null;\n    \n    /**\n     * If true, we're in the middle of syncing to/from the Document. Used to ignore spurious change\n     * events caused by us (vs. change events caused by others, which we need to pay attention to).\n     * @type {!boolean}\n     */\n    Editor.prototype._duringSync = false;\n    \n    /**\n     * @private\n     * NOTE: this is actually \"semi-private\": EditorManager also accesses this field... as well as\n     * a few other modules. However, we should try to gradually move most code away from talking to\n     * CodeMirror directly.\n     * @type {!CodeMirror}\n     */\n    Editor.prototype._codeMirror = null;\n    \n    /**\n     * @private\n     * @type {!Array.<{id:number, data:Object}>}\n     */\n    Editor.prototype._inlineWidgets = null;\n\n    /**\n     * @private\n     * @type {?TextRange}\n     */\n    Editor.prototype._visibleRange = null;\n    \n    \n    // Global settings that affect all Editor instances (both currently open Editors as well as those created\n    // in the future)\n\n    /**\n     * Sets whether to use tab characters (vs. spaces) when inserting new text. Affects all Editors.\n     * @param {boolean} value\n     */\n    Editor.setUseTabChar = function (value) {\n        _useTabChar = value;\n        _instances.forEach(function (editor) {\n            editor._codeMirror.setOption(\"indentWithTabs\", _useTabChar);\n        });\n    };\n    \n    /** @type {boolean}  Gets whether all Editors use tab characters (vs. spaces) when inserting new text */\n    Editor.getUseTabChar = function (value) {\n        return _useTabChar;\n    };\n\n    \n    // Global commands that affect the currently focused Editor instance, wherever it may be\n    CommandManager.register(Strings.CMD_SELECT_ALL,     Commands.EDIT_SELECT_ALL, _handleSelectAll);\n\n    // Define public API\n    exports.Editor = Editor;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\ndefine('editor/InlineWidget',['require','exports','module','editor/EditorManager'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var EditorManager       = require(\"editor/EditorManager\");\n    \n    /**\n     * @constructor\n     *\n     */\n    function InlineWidget() {\n        var self = this;\n        \n        // create the outer wrapper div\n        this.htmlContent = window.document.createElement(\"div\");\n        this.$htmlContent = $(this.htmlContent).addClass(\"inline-widget\");\n        this.$htmlContent.append(\"<div class='shadow top' />\")\n            .append(\"<div class='shadow bottom' />\");\n        \n        this.$htmlContent.on(\"keydown\", function (e) {\n            if (e.keyCode === 27) {\n                self.close();\n                e.stopImmediatePropagation();\n            }\n        });\n    }\n    InlineWidget.prototype.htmlContent = null;\n    InlineWidget.prototype.$htmlContent = null;\n    InlineWidget.prototype.id = null;\n    InlineWidget.prototype.hostEditor = null;\n\n    /**\n     * Initial height of inline widget in pixels. Can be changed later via hostEditor.setInlineWidgetHeight()\n     * @type {number}\n     */\n    InlineWidget.prototype.height = 0;\n    \n    /**\n     * Closes this inline widget and all its contained Editors\n     */\n    InlineWidget.prototype.close = function () {\n        var shouldMoveFocus = this._editorHasFocus();\n        EditorManager.closeInlineWidget(this.hostEditor, this, shouldMoveFocus);\n        // closeInlineWidget() causes our onClosed() handler to be called\n    };\n    \n    /**\n     * Called any time inline is closed, whether manually or automatically\n     */\n    InlineWidget.prototype.onClosed = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * Called once content is parented in the host editor's DOM. Useful for performing tasks like setting\n     * focus or measuring content, which require htmlContent to be in the DOM tree.\n     */\n    InlineWidget.prototype.onAdded = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineWidget.prototype.load = function (hostEditor) {\n        this.hostEditor = hostEditor;\n\n        // TODO: incomplete impelementation. It's not clear yet if InlineTextEditor\n        // will fuction as an abstract class or as generic inline editor implementation\n        // that just shows a range of text. See CSSInlineEditor.css for an implementation of load()\n    };\n    \n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineWidget.prototype.onParentShown = function () {\n        // do nothing - base implementation\n    };\n\n    exports.InlineWidget = InlineWidget;\n\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n// FUTURE: Merge part (or all) of this class with MultiRangeInlineEditor\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\ndefine('editor/InlineTextEditor',['require','exports','module','document/DocumentManager','editor/EditorManager','command/CommandManager','command/Commands','editor/InlineWidget'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        InlineWidget        = require(\"editor/InlineWidget\").InlineWidget;\n\n    /**\n     * Returns editor holder width (not CodeMirror's width).\n     * @private\n     */\n    function _editorHolderWidth() {\n        return $(\"#editor-holder\").width();\n    }\n\n    /**\n     * Shows or hides the dirty indicator\n     * @private\n     */\n    function _showDirtyIndicator($indicatorDiv, isDirty) {\n        // Show or hide the dirty indicator by adjusting\n        // the width of the div.\n        $indicatorDiv.css(\"width\", isDirty ? 16 : 0);\n    }\n    \n    /**\n     * Respond to dirty flag change event. If the dirty flag is associated with an inline editor,\n     * show (or hide) the dirty indicator.\n     * @private\n     */\n    function _dirtyFlagChangeHandler(event, doc) {\n        var $dirtyIndicators = $(\".inlineEditorHolder .dirty-indicator\"),\n            $indicator;\n        \n        $.each($dirtyIndicators, function (index, indicator) {\n            $indicator = $(indicator);\n            if ($indicator.data(\"fullPath\") === doc.file.fullPath) {\n                _showDirtyIndicator($indicator, doc.isDirty);\n            }\n        });\n    }\n    \n    /**\n     * @constructor\n     * @extends {InlineWidget}\n     */\n    function InlineTextEditor() {\n        InlineWidget.call(this);\n\n        /* @type {Array.<{Editor}>}*/\n        this.editors = [];\n    }\n    InlineTextEditor.prototype = new InlineWidget();\n    InlineTextEditor.prototype.constructor = InlineTextEditor;\n    InlineTextEditor.prototype.parentClass = InlineWidget.prototype;\n    \n    InlineTextEditor.prototype.editors = null;\n\n   /**\n     * Given a host editor and its inline editors, find the widest gutter and make all the others match\n     * @param {!Editor} hostEditor Host editor containing all the inline editors to sync\n     * @private\n     */\n    function _syncGutterWidths(hostEditor) {\n        var allHostedEditors = EditorManager.getInlineEditors(hostEditor);\n        \n        // add the host itself to the list too\n        allHostedEditors.push(hostEditor);\n        \n        var maxWidth = 0;\n        allHostedEditors.forEach(function (editor) {\n            var $gutter = $(editor._codeMirror.getGutterElement());\n            $gutter.css(\"min-width\", \"\");\n            var curWidth = $gutter.width();\n            if (curWidth > maxWidth) {\n                maxWidth = curWidth;\n            }\n        });\n        \n        if (allHostedEditors.length === 1) {\n            //There's only the host, just bail\n            allHostedEditors[0]._codeMirror.setOption(\"gutter\", true);\n            return;\n        }\n        \n        maxWidth = maxWidth + \"px\";\n        allHostedEditors.forEach(function (editor) {\n            $(editor._codeMirror.getGutterElement()).css(\"min-width\", maxWidth);\n            editor._codeMirror.setOption(\"gutter\", true);\n        });\n    }\n\n    /**\n     * Called any time inline was closed, whether manually (via close()) or automatically\n     */\n    InlineTextEditor.prototype.onClosed = function () {\n        _syncGutterWidths(this.hostEditor);\n        \n        this.editors.forEach(function (editor) {\n            editor.destroy(); //release ref on Document\n        });\n    };\n    \n    /**\n     * Update the inline editor's height when the number of lines change\n     * @param {boolean} force the editor to resize\n     */\n    InlineTextEditor.prototype.sizeInlineWidgetToContents = function (force) {\n        var i,\n            len = this.editors.length,\n            editor;\n        \n        // TODO: only handles 1 editor right now. Add multiple editor support when\n        // the design is finalized\n\n        // Reize the editors to the content\n        for (i = 0; i < len; i++) {\n            // Only supports 1 editor right now\n            if (i === 1) {\n                break;\n            }\n            \n            editor = this.editors[i];\n            \n            if (editor.isFullyVisible()) {\n                var height = editor.totalHeight(true);\n                if (force || height !== this.height) {\n                    $(editor.getScrollerElement()).height(height);\n                    this.height = height;\n                    editor.refresh();\n                }\n            }\n        }\n    };\n\n    /**\n     * Some tasks have to wait until we've been parented into the outer editor\n     * @param {string} the inline ID that is generated by CodeMirror after the widget that holds the inline\n     *  editor is constructed and added to the DOM\n     */\n    InlineTextEditor.prototype.onAdded = function () {\n        this.editors.forEach(function (editor) {\n            editor.refresh();\n        });\n        \n        _syncGutterWidths(this.hostEditor);\n        \n        // Set initial size\n        // Note that the second argument here (ensureVisibility) is only used by CSSInlineEditor.\n        // FUTURE: Should clean up this API so it's consistent between the two.\n        this.sizeInlineWidgetToContents(true, true);\n        \n        this.editors[0].focus();\n    };\n\n    /**\n     *\n     * @param {Document} doc\n     * @param {number} startLine of text to show in inline editor\n     * @param {number} endLine of text to show in inline editor\n     * @param {HTMLDivElement} container container to hold the inline editor\n     */\n    InlineTextEditor.prototype.createInlineEditorFromText = function (doc, startLine, endLine, container, additionalKeys) {\n        var self = this;\n        \n        var range = {\n            startLine: startLine,\n            endLine: endLine\n        };\n        \n        // root container holding header & editor\n        var $wrapperDiv = $(\"<div/>\");\n        var wrapperDiv = $wrapperDiv[0];\n        \n        // header containing filename, dirty indicator, line number\n        var $header = $(\"<div/>\").addClass(\"inline-editor-header\");\n        var $filenameInfo = $(\"<a/>\").addClass(\"filename\");\n        \n        // dirty indicator, with file path stored on it\n        var $dirtyIndicatorDiv = $(\"<div/>\")\n            .addClass(\"dirty-indicator\")\n            .width(0); // initialize indicator as hidden\n        $dirtyIndicatorDiv.data(\"fullPath\", doc.file.fullPath);\n        \n        var $lineNumber = $(\"<span class='line-number'>\" + (startLine + 1) + \"</span>\");\n\n        // wrap filename & line number in clickable link with tooltip\n        $filenameInfo.append($dirtyIndicatorDiv)\n            .append(doc.file.name + \" : \")\n            .append($lineNumber)\n            .attr(\"title\", doc.file.fullPath);\n        \n        // clicking filename jumps to full editor view\n        $filenameInfo.click(function () {\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: doc.file.fullPath })\n                .done(function () {\n                    EditorManager.getCurrentFullEditor().setCursorPos(startLine);\n                });\n        });\n\n        $header.append($filenameInfo);\n        $wrapperDiv.append($header);\n        \n        \n        // Create actual Editor instance\n        var inlineInfo = EditorManager.createInlineEditorForDocument(doc, range, wrapperDiv, additionalKeys);\n        this.editors.push(inlineInfo.editor);\n        container.appendChild(wrapperDiv);\n\n        // Size editor to content whenever it changes (via edits here or any other view of the doc)\n        $(inlineInfo.editor).on(\"change\", function () {\n            self.sizeInlineWidgetToContents();\n            \n            // And update line number since a change to the Editor equals a change to the Document,\n            // which may mean a change to the line range too\n            $lineNumber.text(inlineInfo.editor.getFirstVisibleLine() + 1);\n        });\n        \n        // If Document's file is deleted, or Editor loses sync with Document, just close\n        $(inlineInfo.editor).on(\"lostContent\", function () {\n            // Note: this closes the entire inline widget if any one Editor loses sync. This seems\n            // better than leaving it open but suddenly removing one rule from the result list.\n            self.close();\n        });\n        \n        // set dirty indicator state\n        _showDirtyIndicator($dirtyIndicatorDiv, doc.isDirty);\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineTextEditor.prototype.load = function (hostEditor) {\n        this.hostEditor = hostEditor;\n\n        // TODO: incomplete impelementation. It's not clear yet if InlineTextEditor\n        // will fuction as an abstract class or as generic inline editor implementation\n        // that just shows a range of text. See CSSInlineEditor.css for an implementation of load()\n    };\n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineTextEditor.prototype.onParentShown = function () {\n        // We need to call this explicitly whenever the host editor is reshown, since\n        // we don't actually resize the inline editor while its host is invisible (see\n        // isFullyVisible() check in sizeInlineWidgetToContents()).\n        this.sizeInlineWidgetToContents(true);\n    };\n    \n    InlineTextEditor.prototype._editorHasFocus = function () {\n        return this.editors.some(function (editor) {\n            return editor.hasFocus();\n        });\n    };\n        \n    \n    // consolidate all dirty document updates\n    $(DocumentManager).on(\"dirtyFlagChange\", _dirtyFlagChangeHandler);\n\n    exports.InlineTextEditor = InlineTextEditor;\n\n});\n\nCodeMirror.defineMode(\"xml\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var Kludges = parserConfig.htmlMode ? {\n    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,\n                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,\n                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,\n                      'track': true, 'wbr': true},\n    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,\n                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,\n                       'th': true, 'tr': true},\n    contextGrabbers: {\n      'dd': {'dd': true, 'dt': true},\n      'dt': {'dd': true, 'dt': true},\n      'li': {'li': true},\n      'option': {'option': true, 'optgroup': true},\n      'optgroup': {'optgroup': true},\n      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,\n            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,\n            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,\n            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,\n            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},\n      'rp': {'rp': true, 'rt': true},\n      'rt': {'rp': true, 'rt': true},\n      'tbody': {'tbody': true, 'tfoot': true},\n      'td': {'td': true, 'th': true},\n      'tfoot': {'tbody': true},\n      'th': {'td': true, 'th': true},\n      'thead': {'tbody': true, 'tfoot': true},\n      'tr': {'tr': true}\n    },\n    doNotIndent: {\"pre\": true},\n    allowUnquoted: true,\n    allowMissing: false\n  } : {\n    autoSelfClosers: {},\n    implicitlyClosed: {},\n    contextGrabbers: {},\n    doNotIndent: {},\n    allowUnquoted: false,\n    allowMissing: false\n  };\n  var alignCDATA = parserConfig.alignCDATA;\n\n  // Return variables for tokenizers\n  var tagName, type;\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var ch = stream.next();\n    if (ch == \"<\") {\n      if (stream.eat(\"!\")) {\n        if (stream.eat(\"[\")) {\n          if (stream.match(\"CDATA[\")) return chain(inBlock(\"atom\", \"]]>\"));\n          else return null;\n        }\n        else if (stream.match(\"--\")) return chain(inBlock(\"comment\", \"-->\"));\n        else if (stream.match(\"DOCTYPE\", true, true)) {\n          stream.eatWhile(/[\\w\\._\\-]/);\n          return chain(doctype(1));\n        }\n        else return null;\n      }\n      else if (stream.eat(\"?\")) {\n        stream.eatWhile(/[\\w\\._\\-]/);\n        state.tokenize = inBlock(\"meta\", \"?>\");\n        return \"meta\";\n      }\n      else {\n        type = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n        stream.eatSpace();\n        tagName = \"\";\n        var c;\n        while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n        state.tokenize = inTag;\n        return \"tag\";\n      }\n    }\n    else if (ch == \"&\") {\n      var ok;\n      if (stream.eat(\"#\")) {\n        if (stream.eat(\"x\")) {\n          ok = stream.eatWhile(/[a-fA-F\\d]/) && stream.eat(\";\");          \n        } else {\n          ok = stream.eatWhile(/[\\d]/) && stream.eat(\";\");\n        }\n      } else {\n        ok = stream.eatWhile(/[\\w\\.\\-:]/) && stream.eat(\";\");\n      }\n      return ok ? \"atom\" : \"error\";\n    }\n    else {\n      stream.eatWhile(/[^&<]/);\n      return null;\n    }\n  }\n\n  function inTag(stream, state) {\n    var ch = stream.next();\n    if (ch == \">\" || (ch == \"/\" && stream.eat(\">\"))) {\n      state.tokenize = inText;\n      type = ch == \">\" ? \"endTag\" : \"selfcloseTag\";\n      return \"tag\";\n    }\n    else if (ch == \"=\") {\n      type = \"equals\";\n      return null;\n    }\n    else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return state.tokenize(stream, state);\n    }\n    else {\n      stream.eatWhile(/[^\\s\\u00a0=<>\\\"\\'\\/?]/);\n      return \"word\";\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inTag;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n  function doctype(depth) {\n    return function(stream, state) {\n      var ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == \"<\") {\n          state.tokenize = doctype(depth + 1);\n          return state.tokenize(stream, state);\n        } else if (ch == \">\") {\n          if (depth == 1) {\n            state.tokenize = inText;\n            break;\n          } else {\n            state.tokenize = doctype(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n      }\n      return \"meta\";\n    };\n  }\n\n  var curState, setStyle;\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushContext(tagName, startOfLine) {\n    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);\n    curState.context = {\n      prev: curState.context,\n      tagName: tagName,\n      indent: curState.indented,\n      startOfLine: startOfLine,\n      noIndent: noIndent\n    };\n  }\n  function popContext() {\n    if (curState.context) curState.context = curState.context.prev;\n  }\n\n  function element(type) {\n    if (type == \"openTag\") {\n      curState.tagName = tagName;\n      return cont(attributes, endtag(curState.startOfLine));\n    } else if (type == \"closeTag\") {\n      var err = false;\n      if (curState.context) {\n        if (curState.context.tagName != tagName) {\n          if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {\n            popContext();\n          }\n          err = !curState.context || curState.context.tagName != tagName;\n        }\n      } else {\n        err = true;\n      }\n      if (err) setStyle = \"error\";\n      return cont(endclosetag(err));\n    }\n    return cont();\n  }\n  function endtag(startOfLine) {\n    return function(type) {\n      if (type == \"selfcloseTag\" ||\n          (type == \"endTag\" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {\n        maybePopContext(curState.tagName.toLowerCase());\n        return cont();\n      }\n      if (type == \"endTag\") {\n        maybePopContext(curState.tagName.toLowerCase());\n        pushContext(curState.tagName, startOfLine);\n        return cont();\n      }\n      return cont();\n    };\n  }\n  function endclosetag(err) {\n    return function(type) {\n      if (err) setStyle = \"error\";\n      if (type == \"endTag\") { popContext(); return cont(); }\n      setStyle = \"error\";\n      return cont(arguments.callee);\n    }\n  }\n  function maybePopContext(nextTagName) {\n    var parentTagName;\n    while (true) {\n      if (!curState.context) {\n        return;\n      }\n      parentTagName = curState.context.tagName.toLowerCase();\n      if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||\n          !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {\n        return;\n      }\n      popContext();\n    }\n  }\n\n  function attributes(type) {\n    if (type == \"word\") {setStyle = \"attribute\"; return cont(attribute, attributes);}\n    if (type == \"endTag\" || type == \"selfcloseTag\") return pass();\n    setStyle = \"error\";\n    return cont(attributes);\n  }\n  function attribute(type) {\n    if (type == \"equals\") return cont(attvalue, attributes);\n    if (!Kludges.allowMissing) setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfcloseTag\") ? pass() : cont();\n  }\n  function attvalue(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    if (type == \"word\" && Kludges.allowUnquoted) {setStyle = \"string\"; return cont();}\n    setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfCloseTag\") ? pass() : cont();\n  }\n  function attvaluemaybe(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    else return pass();\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        state.startOfLine = true;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n\n      setStyle = type = tagName = null;\n      var style = state.tokenize(stream, state);\n      state.type = type;\n      if ((style || type) && style != \"comment\") {\n        curState = state;\n        while (true) {\n          var comb = state.cc.pop() || element;\n          if (comb(type || style)) break;\n        }\n      }\n      state.startOfLine = false;\n      return setStyle || style;\n    },\n\n    indent: function(state, textAfter, fullLine) {\n      var context = state.context;\n      if ((state.tokenize != inTag && state.tokenize != inText) ||\n          context && context.noIndent)\n        return fullLine ? fullLine.match(/^(\\s*)/)[0].length : 0;\n      if (alignCDATA && /<!\\[CDATA\\[/.test(textAfter)) return 0;\n      if (context && /^<\\//.test(textAfter))\n        context = context.prev;\n      while (context && !context.startOfLine)\n        context = context.prev;\n      if (context) return context.indent + indentUnit;\n      else return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.indented != b.indented || a.tokenize != b.tokenize) return false;\n      for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {\n        if (!ca || !cb) return ca == cb;\n        if (ca.tagName != cb.tagName) return false;\n      }\n    },\n\n    electricChars: \"/\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/xml\", \"xml\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/html\"))\n  CodeMirror.defineMIME(\"text/html\", {name: \"xml\", htmlMode: true});\n\ndefine(\"thirdparty/CodeMirror2/mode/xml/xml\", function(){});\n\nCodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var jsonMode = parserConfig.json;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n    return {\n      \"if\": A, \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": C, \"delete\": C, \"throw\": C,\n      \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n      \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom\n    };\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next == end && !escaped)\n        return false;\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return escaped;\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n\n  function jsTokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, jsTokenString(ch));\n    else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch))\n      return ret(ch);\n    else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    }      \n    else if (/\\d/.test(ch) || ch == \"-\" && stream.eat(/\\d/)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, jsTokenComment);\n      }\n      else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else if (state.reAllowed) {\n        nextUntilUnescaped(stream, \"/\");\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string-2\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", null, stream.current());\n      }\n    }\n    else if (ch == \"#\") {\n        stream.skipToEnd();\n        return ret(\"error\", \"error\");\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", null, stream.current());\n    }\n    else {\n      stream.eatWhile(/[\\w\\$_]/);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return (known && state.kwAllowed) ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function jsTokenString(quote) {\n    return function(stream, state) {\n      if (!nextUntilUnescaped(stream, quote))\n        state.tokenize = jsTokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function jsTokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true};\n\n  function JSLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n  }\n\n  function parseJS(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n  \n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n        return style;\n      }\n    }\n  }\n\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      for (var v = state.localVars; v; v = v.next)\n        if (v.name == varname) return;\n      state.localVars = {name: varname, next: state.localVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    if (!cx.state.context) cx.state.localVars = defaultVars;\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state;\n      state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    return function expecting(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(arguments.callee);\n    };\n  }\n\n  function statement(type) {\n    if (type == \"var\") return cont(pushlex(\"vardef\"), vardef1, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), expression, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    if (type == \";\") return cont();\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), expect(\"(\"), pushlex(\")\"), forspec1, expect(\")\"),\n                                      poplex, statement, poplex);\n    if (type == \"variable\") return cont(pushlex(\"stat\"), maybelabel);\n    if (type == \"switch\") return cont(pushlex(\"form\"), expression, pushlex(\"}\", \"switch\"), expect(\"{\"),\n                                         block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                        statement, poplex, popcontext);\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex, maybeoperator);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(objprop, \"}\"), poplex, maybeoperator);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n    \n  function maybeoperator(type, value) {\n    if (type == \"operator\" && /\\+\\+|--/.test(value)) return cont(maybeoperator);\n    if (type == \"operator\" || type == \":\") return cont(expression);\n    if (type == \";\") return;\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(expression, \")\"), poplex, maybeoperator);\n    if (type == \".\") return cont(property, maybeoperator);\n    if (type == \"[\") return cont(pushlex(\"]\"), expression, expect(\"]\"), poplex, maybeoperator);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperator, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type) {\n    if (type == \"variable\") cx.marked = \"property\";\n    if (atomicTypes.hasOwnProperty(type)) return cont(expect(\":\"), expression);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") return cont(what, proceed);\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function commaSeparated(type) {\n      if (type == end) return cont();\n      else return pass(what, proceed);\n    };\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function vardef1(type, value) {\n    if (type == \"variable\"){register(value); return cont(vardef2);}\n    return cont();\n  }\n  function vardef2(type, value) {\n    if (value == \"=\") return cont(expression, vardef2);\n    if (type == \",\") return cont(vardef1);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef1, forspec2);\n    if (type == \";\") return pass(forspec2);\n    if (type == \"variable\") return cont(formaybein);\n    return pass(forspec2);\n  }\n  function formaybein(type, value) {\n    if (value == \"in\") return cont(expression);\n    return cont(maybeoperator, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\") return cont(expression);\n    return cont(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushlex(\")\"), pushcontext, commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type, value) {\n    if (type == \"variable\") {register(value); return cont();}\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: jsTokenBase,\n        reAllowed: true,\n        kwAllowed: true,\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: 0\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.reAllowed = !!(type == \"operator\" || type == \"keyword c\" || type.match(/^[\\[{}\\(,;:]$/));\n      state.kwAllowed = type != '.';\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != jsTokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n      if (type == \"vardef\") return lexical.indented + 4;\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"stat\" || type == \"form\") return lexical.indented + indentUnit;\n      else if (lexical.info == \"switch\" && !closing)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \":{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\n\ndefine(\"thirdparty/CodeMirror2/mode/javascript/javascript\", function(){});\n\nCodeMirror.defineMode(\"css\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\\\\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"#\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"atom\", \"hash\");\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,.+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]]/.test(ch)) {\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"variable\", \"variable\");\n    }\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context != \"rule\") style = \"string-2\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = \"number\";\n        else if (!context || context == \"@media{\") style = \"tag\";\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/css\", \"css\");\n\ndefine(\"thirdparty/CodeMirror2/mode/css/css\", function(){});\n\n/*\nLESS mode - http://www.lesscss.org/\nPorted to CodeMirror by Peter Kroon\n*/\n\nCodeMirror.defineMode(\"less\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n  //html5 tags\n  var tags = [\"a\",\"abbr\",\"acronym\",\"address\",\"applet\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"basefont\",\"bdi\",\"bdo\",\"big\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"command\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"dir\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"font\",\"footer\",\"form\",\"frame\",\"frameset\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"keygen\",\"kbd\",\"label\",\"legend\",\"li\",\"link\",\"map\",\"mark\",\"menu\",\"meta\",\"meter\",\"nav\",\"noframes\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strike\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"track\",\"tt\",\"u\",\"ul\",\"var\",\"video\",\"wbr\"];\n  \n  function inTagsArray(val){\n\t  for(var i=0; i<tags.length; i++){\n\t\t  if(val === tags[i]){\n\t\t\t  return true;\n\t\t  }\n\t  }\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n\tif (ch == \"@\") {stream.eatWhile(/[\\w\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n\telse if (ch == \"/\") { // lesscss e.g.: .png will not be parsed as a class\n\t  if(stream.eat(\"/\")){\n\t\tstate.tokenize = tokenSComment\n      \treturn tokenSComment(stream, state);\n\t  }else{\n\t    stream.eatWhile(/[\\a-zA-Z0-9\\-_.\\s]/);\n\t\tif(/\\/|\\)|#/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == \")\")))return ret(\"string\", \"string\");//let url(/images/logo.png) without quotes return as string\n        return ret(\"number\", \"unit\");\n\t  }\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,+<>*\\/]/.test(ch)) {//removed . dot character original was [,.+>*\\/]\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\\[\\]]\n      if(ch == \":\"){\n\t\tstream.eatWhile(/[active|hover|link|visited]/);\n\t\tif( stream.current().match(/active|hover|link|visited/)){\n\t\t  return ret(\"tag\", \"tag\");\n\t\t}else{\n\t\t  return ret(null, ch);\t\n\t\t}\n\t  }else{\n  \t    return ret(null, ch);\n\t  }\n    }\n\telse if (ch == \".\") { // lesscss\n\t  stream.eatWhile(/[\\a-zA-Z0-9\\-_]/);\n      return ret(\"tag\", \"tag\");\n    }\n\telse if (ch == \"#\") { // lesscss\n\t  //we don't eat white-space, we want the hex color and or id only\n\t  stream.eatWhile(/[A-Za-z0-9]/);\n\t  //check if there is a proper hex color length e.g. #eee || #eeeEEE\n\t  if(stream.current().length ===4 || stream.current().length ===7){\n\t\t  if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream\n\t\t  \t//when not a valid hex value, parse as id\n\t\t\tif(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret(\"atom\", \"tag\");\n\t\t\t//eat white-space\n\t\t\tstream.eatSpace();\n\t\t\t//when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]\n\t\t\tif( /[\\/<>.(){!$%^&*_\\-\\\\?=+\\|#'~`]/.test(stream.peek()) )return ret(\"atom\", \"tag\");\n\t\t\t//#time { color: #aaa }\n\t\t\telse if(stream.peek() == \"}\" )return ret(\"number\", \"unit\");\n\t\t\t//we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa\n\t\t\telse if( /[a-zA-Z\\\\]/.test(stream.peek()) )return ret(\"atom\", \"tag\");\n\t\t\t//when a hex value is on the end of a line, parse as id\n\t\t\telse if(stream.eol())return ret(\"atom\", \"tag\");\n\t\t\t//default\n\t\t\telse return ret(\"number\", \"unit\");\n\t\t  }else{//when not a valid hexvalue in the current stream e.g. #footer\n\t\t\tstream.eatWhile(/[\\w\\\\\\-]/);\n\t\t\treturn ret(\"atom\", \"tag\"); \n\t\t  }\n\t  }else{\n\t\tstream.eatWhile(/[\\w\\\\\\-]/);\t\t\n\t\treturn ret(\"atom\", \"tag\");\n\t  }\n    }\n\telse if (ch == \"&\") {\n\t  stream.eatWhile(/[\\w\\-]/);\n\t  return ret(null, ch);\n\t}\n    else {\n      stream.eatWhile(/[\\w\\\\\\-_%.{]/);\n\t  if(stream.current().match(/http|https/) != null){\n\t\tstream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n\t\treturn ret(\"string\", \"string\");\n\t  }else if(stream.peek() == \"<\" || stream.peek() == \">\"){\n\t\treturn ret(\"tag\", \"tag\");\n\t  }else if( stream.peek().match(/\\(/) != null ){// lessc\n\t\treturn ret(null, ch);\n\t  }else if (stream.peek() == \"/\" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)\n\t  \treturn ret(\"string\", \"string\");\n\t  }else if( stream.current().match(/\\-\\d|\\-.\\d/) ){ // lesscss match e.g.: -5px -0.4 etc... only colorize the minus sign\n\t\t//stream.backUp(stream.current().length-1); //commment out these 2 comment if you want the minus sign to be parsed as null -500px\n\t  \t//return ret(null, ch);\n\t\treturn ret(\"number\", \"unit\");\n\t  }else if( inTagsArray(stream.current()) ){ // lesscss match html tags\n\t  \treturn ret(\"tag\", \"tag\");\n\t  }else if( /\\/|[\\s\\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == \"/\")) && stream.current().indexOf(\".\") !== -1){\n\t\tif(stream.current().substring(stream.current().length-1,stream.current().length) == \"{\"){\n\t\t\tstream.backUp(1);\n\t\t\treturn ret(\"tag\", \"tag\");\n\t\t}//end if\n\t\tif( (stream.eatSpace() && stream.peek().match(/[{<>.a-zA-Z]/) != null)  || stream.eol() )return ret(\"tag\", \"tag\");//e.g. button.icon-plus\n\t\treturn ret(\"string\", \"string\");//let url(/images/logo.png) without quotes return as string\n\t  }else if( stream.eol() ){\n\t\t  if(stream.current().substring(stream.current().length-1,stream.current().length) == \"{\")stream.backUp(1);\n\t\t  return ret(\"tag\", \"tag\");\n\t  }else{\n      \treturn ret(\"variable\", \"variable\");\n\t  }\n    }\n    \n  }\n\n  function tokenSComment(stream, state) {// SComment = Slash comment\n    stream.skipToEnd();\n\tstate.tokenize = tokenBase;\n    return ret(\"comment\", \"comment\");\n  }\n    \n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) { \n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context == \"rule\") style = \"atom\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = null; //\"tag\"\n        else if (!context || context == \"@media{\"){ \n\t\t\tstyle = stream.current() \t== \"when\" \t? \"variable\" \t: \n\t\t\tstream.string.match(/#/g) \t!= undefined \t? null \t\t: \n\t\t\t/[\\s,|\\s\\)]/.test(stream.peek()) \t\t? \"tag\" \t: null;\n\t\t}\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-less\", \"less\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/css\"))\n  CodeMirror.defineMIME(\"text/css\", \"less\");\n\ndefine(\"thirdparty/CodeMirror2/mode/less/less\", function(){});\n\nCodeMirror.defineMode(\"htmlmixed\", function(config, parserConfig) {\n  var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n  var unknownScriptMode = CodeMirror.getMode(config, \"text/plain\");\n  var jsMode = CodeMirror.getMode(config, \"javascript\");\n  var cssMode = CodeMirror.getMode(config, \"css\");\n\n  function html(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style == \"tag\" && stream.current() == \">\" && state.htmlState.context) {\n      if (/^script$/i.test(state.htmlState.context.tagName)) {\n        // Script block: mode to change to depends on type attribute\n        var scriptType = stream.string.match(/type\\s*=\\s*[\"'](.+)[\"']/i);\n        scriptType = scriptType && scriptType[1];\n        if (!scriptType || scriptType.match(/(text|application)\\/(java|ecma)script/i)) {\n          state.token = javascript;\n          state.localState = jsMode.startState(htmlMode.indent(state.htmlState, \"\"));\n          state.mode = \"javascript\";\n        } else if (scriptType.match(/\\/x-handlebars-template/i) || scriptType.match(/\\/x-mustache/i)) {\n            // Handlebars or Mustache template: leave it in HTML mode\n        } else {\n          state.token = unknownScript;\n          state.localState = null;\n          state.mode = \"\";\n        }\n      }\n      else if (/^style$/i.test(state.htmlState.context.tagName)) {\n        state.token = css;\n        state.localState = cssMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"css\";\n      }\n    }\n    return style;\n  }\n  function maybeBackup(stream, pat, style) {\n    var cur = stream.current();\n    var close = cur.search(pat);\n    if (close > -1) stream.backUp(cur.length - close);\n    return style;\n  }\n  function unknownScript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       unknownScriptMode.token(stream, state.localState));\n  }\n  function javascript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       jsMode.token(stream, state.localState));\n  }\n  function css(stream, state) {\n    if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n                       cssMode.token(stream, state.localState));\n  }\n\n  return {\n    startState: function() {\n      var state = htmlMode.startState();\n      return {token: html, localState: null, mode: \"html\", htmlState: state};\n    },\n\n    copyState: function(state) {\n      if (state.localState)\n        var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);\n      return {token: state.token, localState: local, mode: state.mode,\n              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == html || /^\\s*<\\//.test(textAfter))\n        return htmlMode.indent(state.htmlState, textAfter);\n      else if (state.token == javascript)\n        return jsMode.indent(state.localState, textAfter);\n      else if (state.token == css)\n        return cssMode.indent(state.localState, textAfter);\n      else  // unknownScriptMode\n        return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.mode != b.mode) return false;\n      if (a.localState) return CodeMirror.Pass;\n      return htmlMode.compareStates(a.htmlState, b.htmlState);\n    },\n\n    electricChars: \"/{}:\"\n  }\n}, \"xml\", \"javascript\", \"css\");\n\nCodeMirror.defineMIME(\"text/html\", \"htmlmixed\");\n\ndefine(\"thirdparty/CodeMirror2/mode/htmlmixed/htmlmixed\", function(){});\n\nCodeMirror.defineMode(\"clike\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      keywords = parserConfig.keywords || {},\n      builtin = parserConfig.builtin || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    if (builtin.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\n(function() {\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  var cKeywords = \"auto if break int case long char register continue return default short do sizeof \" +\n    \"double static else struct entry switch extern typedef float union for unsigned \" +\n    \"goto while enum void const signed volatile\";\n\n  function cppHook(stream, state) {\n    if (!state.startOfLine) return false;\n    stream.skipToEnd();\n    return \"meta\";\n  }\n\n  // C#-style strings where \"\" escapes a quote.\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  CodeMirror.defineMIME(\"text/x-csrc\", {\n    name: \"clike\",\n    keywords: words(cKeywords),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null\"),\n    hooks: {\"#\": cppHook}\n  });\n  CodeMirror.defineMIME(\"text/x-c++src\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \" asm dynamic_cast namespace reinterpret_cast try bool explicit new \" +\n                    \"static_cast typeid catch operator template typename class friend private \" +\n                    \"this using const_cast inline public throw virtual delete mutable protected \" +\n                    \"wchar_t\"),\n    blockKeywords: words(\"catch class do else finally for if struct switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\"#\": cppHook}\n  });\n  CodeMirror.defineMIME(\"text/x-java\", {\n    name: \"clike\",\n    keywords: words(\"abstract assert boolean break byte case catch char class const continue default \" + \n                    \"do double else enum extends final finally float for goto if implements import \" +\n                    \"instanceof int interface long native new package private protected public \" +\n                    \"return short static strictfp super switch synchronized this throw throws transient \" +\n                    \"try void volatile while\"),\n    blockKeywords: words(\"catch class do else finally for if switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n  CodeMirror.defineMIME(\"text/x-csharp\", {\n    name: \"clike\",\n    keywords: words(\"abstract as base break case catch checked class const continue\" + \n                    \" default delegate do else enum event explicit extern finally fixed for\" + \n                    \" foreach goto if implicit in interface internal is lock namespace new\" + \n                    \" operator out override params private protected public readonly ref return sealed\" + \n                    \" sizeof stackalloc static struct switch this throw try typeof unchecked\" + \n                    \" unsafe using virtual void volatile while add alias ascending descending dynamic from get\" + \n                    \" global group into join let orderby partial remove select set value var yield\"),\n    blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n    builtin: words(\"Boolean Byte Char DateTime DateTimeOffset Decimal Double\" +\n                    \" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32\" +\n                    \" UInt64 bool byte char decimal double short int long object\"  +\n                    \" sbyte float string ushort uint ulong\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        if (stream.eat('\"')) {\n          state.tokenize = tokenAtString;\n          return tokenAtString(stream, state);\n        }\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n  CodeMirror.defineMIME(\"text/x-scala\", {\n    name: \"clike\",\n    keywords: words(\n      \n      /* scala */\n      \"abstract case catch class def do else extends false final finally for forSome if \" +\n      \"implicit import lazy match new null object override package private protected return \" +\n      \"sealed super this throw trait try trye type val var while with yield _ : = => <- <: \" +\n      \"<% >: # @ \" +\n                    \n      /* package scala */\n      \"assert assume require print println printf readLine readBoolean readByte readShort \" +\n      \"readChar readInt readLong readFloat readDouble \" +\n      \n      \"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either \" +\n      \"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable \" +\n      \"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering \" +\n      \"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder \" +\n      \"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: \" +\n      \n      /* package java.lang */            \n      \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n      \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n      \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n      \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n      \n      \n    ),\n    blockKeywords: words(\"catch class do else finally for forSome if match switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n}());\n\ndefine(\"thirdparty/CodeMirror2/mode/clike/clike\", function(){});\n\n(function() {\n  function keywords(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  function heredoc(delim) {\n    return function(stream, state) {\n      if (stream.match(delim)) state.tokenize = null;\n      else stream.skipToEnd();\n      return \"string\";\n    }\n  }\n  var phpConfig = {\n    name: \"clike\",\n    keywords: keywords(\"abstract and array as break case catch class clone const continue declare default \" +\n                       \"do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final \" +\n                       \"for foreach function global goto if implements interface instanceof namespace \" +\n                       \"new or private protected public static switch throw trait try use var while xor \" +\n                       \"die echo empty exit eval include include_once isset list require require_once return \" +\n                       \"print unset __halt_compiler self static parent\"),\n    blockKeywords: keywords(\"catch do else elseif for foreach if switch try while\"),\n    atoms: keywords(\"true false null TRUE FALSE NULL\"),\n    multiLineStrings: true,\n    hooks: {\n      \"$\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"variable-2\";\n      },\n      \"<\": function(stream, state) {\n        if (stream.match(/<</)) {\n          stream.eatWhile(/[\\w\\.]/);\n          state.tokenize = heredoc(stream.current().slice(3));\n          return state.tokenize(stream, state);\n        }\n        return false;\n      },\n      \"#\": function(stream, state) {\n        while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n        return \"comment\";\n      },\n      \"/\": function(stream, state) {\n        if (stream.eat(\"/\")) {\n          while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n          return \"comment\";\n        }\n        return false;\n      }\n    }\n  };\n\n  CodeMirror.defineMode(\"php\", function(config, parserConfig) {\n    var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n    var jsMode = CodeMirror.getMode(config, \"javascript\");\n    var cssMode = CodeMirror.getMode(config, \"css\");\n    var phpMode = CodeMirror.getMode(config, phpConfig);\n\n    function dispatch(stream, state) { // TODO open PHP inside text/css\n      var isPHP = state.mode == \"php\";\n      if (stream.sol() && state.pending != '\"') state.pending = null;\n      if (state.curMode == htmlMode) {\n        if (stream.match(/^<\\?\\w*/)) {\n          state.curMode = phpMode;\n          state.curState = state.php;\n          state.curClose = \"?>\";\n\t  state.mode = \"php\";\n          return \"meta\";\n        }\n        if (state.pending == '\"') {\n          while (!stream.eol() && stream.next() != '\"') {}\n          var style = \"string\";\n        } else if (state.pending && stream.pos < state.pending.end) {\n          stream.pos = state.pending.end;\n          var style = state.pending.style;\n        } else {\n          var style = htmlMode.token(stream, state.curState);\n        }\n        state.pending = null;\n        var cur = stream.current(), openPHP = cur.search(/<\\?/);\n        if (openPHP != -1) {\n          if (style == \"string\" && /\\\"$/.test(cur) && !/\\?>/.test(cur)) state.pending = '\"';\n          else state.pending = {end: stream.pos, style: style};\n          stream.backUp(cur.length - openPHP);\n        } else if (style == \"tag\" && stream.current() == \">\" && state.curState.context) {\n          if (/^script$/i.test(state.curState.context.tagName)) {\n            state.curMode = jsMode;\n            state.curState = jsMode.startState(htmlMode.indent(state.curState, \"\"));\n            state.curClose = /^<\\/\\s*script\\s*>/i;\n\t    state.mode = \"javascript\";\n          }\n          else if (/^style$/i.test(state.curState.context.tagName)) {\n            state.curMode = cssMode;\n            state.curState = cssMode.startState(htmlMode.indent(state.curState, \"\"));\n            state.curClose = /^<\\/\\s*style\\s*>/i;\n            state.mode = \"css\";\n          }\n        }\n        return style;\n      } else if ((!isPHP || state.php.tokenize == null) &&\n                 stream.match(state.curClose, isPHP)) {\n        state.curMode = htmlMode;\n        state.curState = state.html;\n        state.curClose = null;\n\tstate.mode = \"html\";\n        if (isPHP) return \"meta\";\n        else return dispatch(stream, state);\n      } else {\n        return state.curMode.token(stream, state.curState);\n      }\n    }\n\n    return {\n      startState: function() {\n        var html = htmlMode.startState();\n        return {html: html,\n                php: phpMode.startState(),\n                curMode: parserConfig.startOpen ? phpMode : htmlMode,\n                curState: parserConfig.startOpen ? phpMode.startState() : html,\n                curClose: parserConfig.startOpen ? /^\\?>/ : null,\n\t\tmode: parserConfig.startOpen ? \"php\" : \"html\",\n                pending: null}\n      },\n\n      copyState: function(state) {\n        var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),\n            php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;\n        if (state.curState == html) cur = htmlNew;\n        else if (state.curState == php) cur = phpNew;\n        else cur = CodeMirror.copyState(state.curMode, state.curState);\n        return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,\n                curClose: state.curClose, mode: state.mode,\n                pending: state.pending};\n      },\n\n      token: dispatch,\n\n      indent: function(state, textAfter) {\n        if ((state.curMode != phpMode && /^\\s*<\\//.test(textAfter)) ||\n            (state.curMode == phpMode && /^\\?>/.test(textAfter)))\n          return htmlMode.indent(state.html, textAfter);\n        return state.curMode.indent(state.curState, textAfter);\n      },\n\n      electricChars: \"/{}:\"\n    }\n  }, \"xml\", \"clike\", \"javascript\", \"css\");\n  CodeMirror.defineMIME(\"application/x-httpd-php\", \"php\");\n  CodeMirror.defineMIME(\"application/x-httpd-php-open\", {name: \"php\", startOpen: true});\n  CodeMirror.defineMIME(\"text/x-php\", phpConfig);\n})();\n\ndefine(\"thirdparty/CodeMirror2/mode/php/php\", function(){});\n\n/**\n * Link to the project's GitHub page:\n * https://github.com/pickhardt/coffeescript-codemirror-mode\n */\nCodeMirror.defineMode('coffeescript', function(conf) {\n    var ERRORCLASS = 'error';\n\n    function wordRegexp(words) {\n        return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n    }\n\n    var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!\\?]\");\n    var singleDelimiters = new RegExp('^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]');\n    var doubleOperators = new RegExp(\"^((\\->)|(\\=>)|(\\\\+\\\\+)|(\\\\+\\\\=)|(\\\\-\\\\-)|(\\\\-\\\\=)|(\\\\*\\\\*)|(\\\\*\\\\=)|(\\\\/\\\\/)|(\\\\/\\\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))\");\n    var doubleDelimiters = new RegExp(\"^((\\\\.\\\\.)|(\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n    var tripleDelimiters = new RegExp(\"^((\\\\.\\\\.\\\\.)|(//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\n    var identifiers = new RegExp(\"^[_A-Za-z$][_A-Za-z$0-9]*\");\n\n    var wordOperators = wordRegexp(['and', 'or', 'not',\n                                    'is', 'isnt', 'in',\n                                    'instanceof', 'typeof']);\n    var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',\n                          'switch', 'try', 'catch', 'finally', 'class'];\n    var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',\n                          'do', 'in', 'of', 'new', 'return', 'then',\n                          'this', 'throw', 'when', 'until'];\n\n    var keywords = wordRegexp(indentKeywords.concat(commonKeywords));\n\n    indentKeywords = wordRegexp(indentKeywords);\n\n\n    var stringPrefixes = new RegExp(\"^('{3}|\\\"{3}|['\\\"])\");\n    var regexPrefixes = new RegExp(\"^(/{3}|/)\");\n    var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];\n    var constants = wordRegexp(commonConstants);\n\n    // Tokenizers\n    function tokenBase(stream, state) {\n        // Handle scope changes\n        if (stream.sol()) {\n            var scopeOffset = state.scopes[0].offset;\n            if (stream.eatSpace()) {\n                var lineOffset = stream.indentation();\n                if (lineOffset > scopeOffset) {\n                    return 'indent';\n                } else if (lineOffset < scopeOffset) {\n                    return 'dedent';\n                }\n                return null;\n            } else {\n                if (scopeOffset > 0) {\n                    dedent(stream, state);\n                }\n            }\n        }\n        if (stream.eatSpace()) {\n            return null;\n        }\n\n        var ch = stream.peek();\n\n        // Handle docco title comment (single line)\n        if (stream.match(\"####\")) {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n        // Handle multi line comments\n        if (stream.match(\"###\")) {\n            state.tokenize = longComment;\n            return state.tokenize(stream, state);\n        }\n\n        // Single line comment\n        if (ch === '#') {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n        // Handle number literals\n        if (stream.match(/^-?[0-9\\.]/, false)) {\n            var floatLiteral = false;\n            // Floats\n            if (stream.match(/^-?\\d*\\.\\d+(e[\\+\\-]?\\d+)?/i)) {\n              floatLiteral = true;\n            }\n            if (stream.match(/^-?\\d+\\.\\d*/)) {\n              floatLiteral = true;\n            }\n            if (stream.match(/^-?\\.\\d+/)) {\n              floatLiteral = true;\n            }\n\n            if (floatLiteral) {\n                // prevent from getting extra . on 1..\n                if (stream.peek() == \".\"){\n                    stream.backUp(1);\n                }\n                return 'number';\n            }\n            // Integers\n            var intLiteral = false;\n            // Hex\n            if (stream.match(/^-?0x[0-9a-f]+/i)) {\n              intLiteral = true;\n            }\n            // Decimal\n            if (stream.match(/^-?[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n                intLiteral = true;\n            }\n            // Zero by itself with no other piece of number.\n            if (stream.match(/^-?0(?![\\dx])/i)) {\n              intLiteral = true;\n            }\n            if (intLiteral) {\n                return 'number';\n            }\n        }\n\n        // Handle strings\n        if (stream.match(stringPrefixes)) {\n            state.tokenize = tokenFactory(stream.current(), 'string');\n            return state.tokenize(stream, state);\n        }\n        // Handle regex literals\n        if (stream.match(regexPrefixes)) {\n            if (stream.current() != '/' || stream.match(/^.*\\//, false)) { // prevent highlight of division\n                state.tokenize = tokenFactory(stream.current(), 'string-2');\n                return state.tokenize(stream, state);\n            } else {\n                stream.backUp(1);\n            }\n        }\n\n        // Handle operators and delimiters\n        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {\n            return 'punctuation';\n        }\n        if (stream.match(doubleOperators)\n            || stream.match(singleOperators)\n            || stream.match(wordOperators)) {\n            return 'operator';\n        }\n        if (stream.match(singleDelimiters)) {\n            return 'punctuation';\n        }\n\n        if (stream.match(constants)) {\n            return 'atom';\n        }\n\n        if (stream.match(keywords)) {\n            return 'keyword';\n        }\n\n        if (stream.match(identifiers)) {\n            return 'variable';\n        }\n\n        // Handle non-detected items\n        stream.next();\n        return ERRORCLASS;\n    }\n\n    function tokenFactory(delimiter, outclass) {\n        var singleline = delimiter.length == 1;\n        return function tokenString(stream, state) {\n            while (!stream.eol()) {\n                stream.eatWhile(/[^'\"\\/\\\\]/);\n                if (stream.eat('\\\\')) {\n                    stream.next();\n                    if (singleline && stream.eol()) {\n                        return outclass;\n                    }\n                } else if (stream.match(delimiter)) {\n                    state.tokenize = tokenBase;\n                    return outclass;\n                } else {\n                    stream.eat(/['\"\\/]/);\n                }\n            }\n            if (singleline) {\n                if (conf.mode.singleLineStringErrors) {\n                    outclass = ERRORCLASS\n                } else {\n                    state.tokenize = tokenBase;\n                }\n            }\n            return outclass;\n        };\n    }\n\n    function longComment(stream, state) {\n        while (!stream.eol()) {\n            stream.eatWhile(/[^#]/);\n            if (stream.match(\"###\")) {\n                state.tokenize = tokenBase;\n                break;\n            }\n            stream.eatWhile(\"#\");\n        }\n        return \"comment\"\n    }\n\n    function indent(stream, state, type) {\n        type = type || 'coffee';\n        var indentUnit = 0;\n        if (type === 'coffee') {\n            for (var i = 0; i < state.scopes.length; i++) {\n                if (state.scopes[i].type === 'coffee') {\n                    indentUnit = state.scopes[i].offset + conf.indentUnit;\n                    break;\n                }\n            }\n        } else {\n            indentUnit = stream.column() + stream.current().length;\n        }\n        state.scopes.unshift({\n            offset: indentUnit,\n            type: type\n        });\n    }\n\n    function dedent(stream, state) {\n        if (state.scopes.length == 1) return;\n        if (state.scopes[0].type === 'coffee') {\n            var _indent = stream.indentation();\n            var _indent_index = -1;\n            for (var i = 0; i < state.scopes.length; ++i) {\n                if (_indent === state.scopes[i].offset) {\n                    _indent_index = i;\n                    break;\n                }\n            }\n            if (_indent_index === -1) {\n                return true;\n            }\n            while (state.scopes[0].offset !== _indent) {\n                state.scopes.shift();\n            }\n            return false\n        } else {\n            state.scopes.shift();\n            return false;\n        }\n    }\n\n    function tokenLexer(stream, state) {\n        var style = state.tokenize(stream, state);\n        var current = stream.current();\n\n        // Handle '.' connected identifiers\n        if (current === '.') {\n            style = state.tokenize(stream, state);\n            current = stream.current();\n            if (style === 'variable') {\n                return 'variable';\n            } else {\n                return ERRORCLASS;\n            }\n        }\n\n        // Handle properties\n        if (current === '@') {\n            stream.eat('@');\n            return 'keyword';\n        }\n\n        // Handle scope changes.\n        if (current === 'return') {\n            state.dedent += 1;\n        }\n        if (((current === '->' || current === '=>') &&\n                  !state.lambda &&\n                  state.scopes[0].type == 'coffee' &&\n                  stream.peek() === '')\n               || style === 'indent') {\n            indent(stream, state);\n        }\n        var delimiter_index = '[({'.indexOf(current);\n        if (delimiter_index !== -1) {\n            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));\n        }\n        if (indentKeywords.exec(current)){\n            indent(stream, state);\n        }\n        if (current == 'then'){\n            dedent(stream, state);\n        }\n\n\n        if (style === 'dedent') {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        delimiter_index = '])}'.indexOf(current);\n        if (delimiter_index !== -1) {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {\n            if (state.scopes.length > 1) state.scopes.shift();\n            state.dedent -= 1;\n        }\n\n        return style;\n    }\n\n    var external = {\n        startState: function(basecolumn) {\n            return {\n              tokenize: tokenBase,\n              scopes: [{offset:basecolumn || 0, type:'coffee'}],\n              lastToken: null,\n              lambda: false,\n              dedent: 0\n          };\n        },\n\n        token: function(stream, state) {\n            var style = tokenLexer(stream, state);\n\n            state.lastToken = {style:style, content: stream.current()};\n\n            if (stream.eol() && stream.lambda) {\n                state.lambda = false;\n            }\n\n            return style;\n        },\n\n        indent: function(state, textAfter) {\n            if (state.tokenize != tokenBase) {\n                return 0;\n            }\n\n            return state.scopes[0].offset;\n        }\n\n    };\n    return external;\n});\n\nCodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');\n\ndefine(\"thirdparty/CodeMirror2/mode/coffeescript/coffeescript\", function(){});\n\n/**\n * Author: Hans Engel\n * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)\n */\nCodeMirror.defineMode(\"clojure\", function (config, mode) {\n    var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\", TAG = \"tag\",\n        ATOM = \"atom\", NUMBER = \"number\", BRACKET = \"bracket\", KEYWORD = \"keyword\";\n    var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;\n\n    function makeKeywords(str) {\n        var obj = {}, words = str.split(\" \");\n        for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n        return obj;\n    }\n\n    var atoms = makeKeywords(\"true false nil\");\n    \n    var keywords = makeKeywords(\n      \"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle\");\n\n    var builtins = makeKeywords(\n        \"* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq\");\n\n    var indentKeys = makeKeywords(\n        // Built-ins\n        \"ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch \" +\n\n        // Binding forms\n        \"let letfn binding loop for doseq dotimes when-let if-let \" +\n\n        // Data structures\n        \"defstruct struct-map assoc \" +\n\n        // clojure.test\n        \"testing deftest \" +\n\n        // contrib\n        \"handler-case handle dotrace deftrace\");\n\n    var tests = {\n        digit: /\\d/,\n        digit_or_colon: /[\\d:]/,\n        hex: /[0-9a-fA-F]/,\n        sign: /[+-]/,\n        exponent: /[eE]/,\n        keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n        basic: /[\\w\\$_\\-]/,\n        lang_keyword: /[\\w*+!\\-_?:\\/]/\n    };\n\n    function stateStack(indent, type, prev) { // represents a state stack object\n        this.indent = indent;\n        this.type = type;\n        this.prev = prev;\n    }\n\n    function pushStack(state, indent, type) {\n        state.indentStack = new stateStack(indent, type, state.indentStack);\n    }\n\n    function popStack(state) {\n        state.indentStack = state.indentStack.prev;\n    }\n\n    function isNumber(ch, stream){\n        // hex\n        if ( ch === '0' && 'x' == stream.peek().toLowerCase() ) {\n            stream.eat('x');\n            stream.eatWhile(tests.hex);\n            return true;\n        }\n\n        // leading sign\n        if ( ch == '+' || ch == '-' ) {\n          stream.eat(tests.sign);\n          ch = stream.next();\n        }\n\n        if ( tests.digit.test(ch) ) {\n            stream.eat(ch);\n            stream.eatWhile(tests.digit);\n\n            if ( '.' == stream.peek() ) {\n                stream.eat('.');\n                stream.eatWhile(tests.digit);\n            }\n\n            if ( 'e' == stream.peek().toLowerCase() ) {\n                stream.eat(tests.exponent);\n                stream.eat(tests.sign);\n                stream.eatWhile(tests.digit);\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    return {\n        startState: function () {\n            return {\n                indentStack: null,\n                indentation: 0,\n                mode: false\n            };\n        },\n\n        token: function (stream, state) {\n            if (state.indentStack == null && stream.sol()) {\n                // update indentation, but only if indentStack is empty\n                state.indentation = stream.indentation();\n            }\n\n            // skip spaces\n            if (stream.eatSpace()) {\n                return null;\n            }\n            var returnType = null;\n\n            switch(state.mode){\n                case \"string\": // multi-line string parsing mode\n                    var next, escaped = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"\\\"\" && !escaped) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        escaped = !escaped && next == \"\\\\\";\n                    }\n                    returnType = STRING; // continue on in string mode\n                    break;\n                default: // default parsing mode\n                    var ch = stream.next();\n\n                    if (ch == \"\\\"\") {\n                        state.mode = \"string\";\n                        returnType = STRING;\n                    } else if (ch == \"'\" && !( tests.digit_or_colon.test(stream.peek()) )) {\n                        returnType = ATOM;\n                    } else if (ch == \";\") { // comment\n                        stream.skipToEnd(); // rest of the line is a comment\n                        returnType = COMMENT;\n                    } else if (isNumber(ch,stream)){\n                        returnType = NUMBER;\n                    } else if (ch == \"(\" || ch == \"[\") {\n                        var keyWord = ''; var indentTemp = stream.column();\n                        /**\n                        Either\n                        (indent-word ..\n                        (non-indent-word ..\n                        (;something else, bracket, etc.\n                        */\n\n                        if (ch == \"(\") while ((letter = stream.eat(tests.keyword_char)) != null) {\n                            keyWord += letter;\n                        }\n\n                        if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word\n                            pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);\n                        } else { // non-indent word\n                            // we continue eating the spaces\n                            stream.eatSpace();\n                            if (stream.eol() || stream.peek() == \";\") {\n                                // nothing significant after\n                                // we restart indentation 1 space after\n                                pushStack(state, indentTemp + 1, ch);\n                            } else {\n                                pushStack(state, indentTemp + stream.current().length, ch); // else we match\n                            }\n                        }\n                        stream.backUp(stream.current().length - 1); // undo all the eating\n\n                        returnType = BRACKET;\n                    } else if (ch == \")\" || ch == \"]\") {\n                        returnType = BRACKET;\n                        if (state.indentStack != null && state.indentStack.type == (ch == \")\" ? \"(\" : \"[\")) {\n                            popStack(state);\n                        }\n                    } else if ( ch == \":\" ) {\n                        stream.eatWhile(tests.lang_keyword);\n                        return ATOM;\n                    } else {\n                        stream.eatWhile(tests.basic);\n\n                        if (keywords && keywords.propertyIsEnumerable(stream.current())) {\n                            returnType = KEYWORD;\n                        } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {\n                            returnType = BUILTIN;\n                        } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {\n                            returnType = ATOM;\n                        } else returnType = null;\n                    }\n            }\n\n            return returnType;\n        },\n\n        indent: function (state, textAfter) {\n            if (state.indentStack == null) return state.indentation;\n            return state.indentStack.indent;\n        }\n    };\n});\n\nCodeMirror.defineMIME(\"text/x-clojure\", \"clojure\");\n\ndefine(\"thirdparty/CodeMirror2/mode/clojure/clojure\", function(){});\n\n// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)\n// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)\nCodeMirror.defineMode(\"perl\",function(config,parserConfig){\n\t// http://perldoc.perl.org\n\tvar PERL={\t\t\t\t    \t//   null - magic touch\n\t\t\t\t\t\t\t//   1 - keyword\n\t\t\t\t\t\t\t//   2 - def\n\t\t\t\t\t\t\t//   3 - atom\n\t\t\t\t\t\t\t//   4 - operator\n\t\t\t\t\t\t\t//   5 - variable-2 (predefined)\n\t\t\t\t\t\t\t//   [x,y] - x=1,2,3; y=must be defined if x{...}\n\t\t\t\t\t\t//\tPERL operators\n\t\t'->'\t\t\t\t:   4,\n\t\t'++'\t\t\t\t:   4,\n\t\t'--'\t\t\t\t:   4,\n\t\t'**'\t\t\t\t:   4,\n\t\t\t\t\t\t\t//   ! ~ \\ and unary + and -\n\t\t'=~'\t\t\t\t:   4,\n\t\t'!~'\t\t\t\t:   4,\n\t\t'*'\t\t\t\t:   4,\n\t\t'/'\t\t\t\t:   4,\n\t\t'%'\t\t\t\t:   4,\n\t\t'x'\t\t\t\t:   4,\n\t\t'+'\t\t\t\t:   4,\n\t\t'-'\t\t\t\t:   4,\n\t\t'.'\t\t\t\t:   4,\n\t\t'<<'\t\t\t\t:   4,\n\t\t'>>'\t\t\t\t:   4,\n\t\t\t\t\t\t\t//   named unary operators\n\t\t'<'\t\t\t\t:   4,\n\t\t'>'\t\t\t\t:   4,\n\t\t'<='\t\t\t\t:   4,\n\t\t'>='\t\t\t\t:   4,\n\t\t'lt'\t\t\t\t:   4,\n\t\t'gt'\t\t\t\t:   4,\n\t\t'le'\t\t\t\t:   4,\n\t\t'ge'\t\t\t\t:   4,\n\t\t'=='\t\t\t\t:   4,\n\t\t'!='\t\t\t\t:   4,\n\t\t'<=>'\t\t\t\t:   4,\n\t\t'eq'\t\t\t\t:   4,\n\t\t'ne'\t\t\t\t:   4,\n\t\t'cmp'\t\t\t\t:   4,\n\t\t'~~'\t\t\t\t:   4,\n\t\t'&'\t\t\t\t:   4,\n\t\t'|'\t\t\t\t:   4,\n\t\t'^'\t\t\t\t:   4,\n\t\t'&&'\t\t\t\t:   4,\n\t\t'||'\t\t\t\t:   4,\n\t\t'//'\t\t\t\t:   4,\n\t\t'..'\t\t\t\t:   4,\n\t\t'...'\t\t\t\t:   4,\n\t\t'?'\t\t\t\t:   4,\n\t\t':'\t\t\t\t:   4,\n\t\t'='\t\t\t\t:   4,\n\t\t'+='\t\t\t\t:   4,\n\t\t'-='\t\t\t\t:   4,\n\t\t'*='\t\t\t\t:   4,\t//   etc. ???\n\t\t','\t\t\t\t:   4,\n\t\t'=>'\t\t\t\t:   4,\n\t\t'::'\t\t\t\t:   4,\n\t\t\t\t   \t\t\t//   list operators (rightward)\n\t\t'not'\t\t\t\t:   4,\n\t\t'and'\t\t\t\t:   4,\n\t\t'or'\t\t\t\t:   4,\n\t\t'xor'\t\t\t\t:   4,\n\t\t\t\t\t\t//\tPERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)\n\t\t'BEGIN'\t\t\t\t:   [5,1],\n\t\t'END'\t\t\t\t:   [5,1],\n\t\t'PRINT'\t\t\t\t:   [5,1],\n\t\t'PRINTF'\t\t\t:   [5,1],\n\t\t'GETC'\t\t\t\t:   [5,1],\n\t\t'READ'\t\t\t\t:   [5,1],\n\t\t'READLINE'\t\t\t:   [5,1],\n\t\t'DESTROY'\t\t\t:   [5,1],\n\t\t'TIE'\t\t\t\t:   [5,1],\n\t\t'TIEHANDLE'\t\t\t:   [5,1],\n\t\t'UNTIE'\t\t\t\t:   [5,1],\n\t\t'STDIN'\t\t\t\t:    5,\n\t\t'STDIN_TOP'\t\t\t:    5,\n\t\t'STDOUT'\t\t\t:    5,\n\t\t'STDOUT_TOP'\t\t\t:    5,\n\t\t'STDERR'\t\t\t:    5,\n\t\t'STDERR_TOP'\t\t\t:    5,\n\t\t'$ARG'\t\t\t\t:    5,\n\t\t'$_'\t\t\t\t:    5,\n\t\t'@ARG'\t\t\t\t:    5,\n\t\t'@_'\t\t\t\t:    5,\n\t\t'$LIST_SEPARATOR'\t\t:    5,\n\t\t'$\"'\t\t\t\t:    5,\n\t\t'$PROCESS_ID'\t\t\t:    5,\n\t\t'$PID'\t\t\t\t:    5,\n\t\t'$$'\t\t\t\t:    5,\n\t\t'$REAL_GROUP_ID'\t\t:    5,\n\t\t'$GID'\t\t\t\t:    5,\n\t\t'$('\t\t\t\t:    5,\n\t\t'$EFFECTIVE_GROUP_ID'\t\t:    5,\n\t\t'$EGID'\t\t\t\t:    5,\n\t\t'$)'\t\t\t\t:    5,\n\t\t'$PROGRAM_NAME'\t\t\t:    5,\n\t\t'$0'\t\t\t\t:    5,\n\t\t'$SUBSCRIPT_SEPARATOR'\t\t:    5,\n\t\t'$SUBSEP'\t\t\t:    5,\n\t\t'$;'\t\t\t\t:    5,\n\t\t'$REAL_USER_ID'\t\t\t:    5,\n\t\t'$UID'\t\t\t\t:    5,\n\t\t'$<'\t\t\t\t:    5,\n\t\t'$EFFECTIVE_USER_ID'\t\t:    5,\n\t\t'$EUID'\t\t\t\t:    5,\n\t\t'$>'\t\t\t\t:    5,\n\t\t'$a'\t\t\t\t:    5,\n\t\t'$b'\t\t\t\t:    5,\n\t\t'$COMPILING'\t\t\t:    5,\n\t\t'$^C'\t\t\t\t:    5,\n\t\t'$DEBUGGING'\t\t\t:    5,\n\t\t'$^D'\t\t\t\t:    5,\n\t\t'${^ENCODING}'\t\t\t:    5,\n\t\t'$ENV'\t\t\t\t:    5,\n\t\t'%ENV'\t\t\t\t:    5,\n\t\t'$SYSTEM_FD_MAX'\t\t:    5,\n\t\t'$^F'\t\t\t\t:    5,\n\t\t'@F'\t\t\t\t:    5,\n\t\t'${^GLOBAL_PHASE}'\t\t:    5,\n\t\t'$^H'\t\t\t\t:    5,\n\t\t'%^H'\t\t\t\t:    5,\n\t\t'@INC'\t\t\t\t:    5,\n\t\t'%INC'\t\t\t\t:    5,\n\t\t'$INPLACE_EDIT'\t\t\t:    5,\n\t\t'$^I'\t\t\t\t:    5,\n\t\t'$^M'\t\t\t\t:    5,\n\t\t'$OSNAME'\t\t\t:    5,\n\t\t'$^O'\t\t\t\t:    5,\n\t\t'${^OPEN}'\t\t\t:    5,\n\t\t'$PERLDB'\t\t\t:    5,\n\t\t'$^P'\t\t\t\t:    5,\n\t\t'$SIG'\t\t\t\t:    5,\n\t\t'%SIG'\t\t\t\t:    5,\n\t\t'$BASETIME'\t\t\t:    5,\n\t\t'$^T'\t\t\t\t:    5,\n\t\t'${^TAINT}'\t\t\t:    5,\n\t\t'${^UNICODE}'\t\t\t:    5,\n\t\t'${^UTF8CACHE}'\t\t\t:    5,\n\t\t'${^UTF8LOCALE}'\t\t:    5,\n\t\t'$PERL_VERSION'\t\t\t:    5,\n\t\t'$^V'\t\t\t\t:    5,\n\t\t'${^WIN32_SLOPPY_STAT}'\t\t:    5,\n\t\t'$EXECUTABLE_NAME'\t\t:    5,\n\t\t'$^X'\t\t\t\t:    5,\n\t\t'$1'\t\t\t\t:    5,\t// - regexp $1, $2...\n\t\t'$MATCH'\t\t\t:    5,\n\t\t'$&'\t\t\t\t:    5,\n\t\t'${^MATCH}'\t\t\t:    5,\n\t\t'$PREMATCH'\t\t\t:    5,\n\t\t'$`'\t\t\t\t:    5,\n\t\t'${^PREMATCH}'\t\t\t:    5,\n\t\t'$POSTMATCH'\t\t\t:    5,\n\t\t\"$'\"\t\t\t\t:    5,\n\t\t'${^POSTMATCH}'\t\t\t:    5,\n\t\t'$LAST_PAREN_MATCH'\t\t:    5,\n\t\t'$+'\t\t\t\t:    5,\n\t\t'$LAST_SUBMATCH_RESULT'\t\t:    5,\n\t\t'$^N'\t\t\t\t:    5,\n\t\t'@LAST_MATCH_END'\t\t:    5,\n\t\t'@+'\t\t\t\t:    5,\n\t\t'%LAST_PAREN_MATCH'\t\t:    5,\n\t\t'%+'\t\t\t\t:    5,\n\t\t'@LAST_MATCH_START'\t\t:    5,\n\t\t'@-'\t\t\t\t:    5,\n\t\t'%LAST_MATCH_START'\t\t:    5,\n\t\t'%-'\t\t\t\t:    5,\n\t\t'$LAST_REGEXP_CODE_RESULT'\t:    5,\n\t\t'$^R'\t\t\t\t:    5,\n\t\t'${^RE_DEBUG_FLAGS}'\t\t:    5,\n\t\t'${^RE_TRIE_MAXBUF}'\t\t:    5,\n\t\t'$ARGV'\t\t\t\t:    5,\n\t\t'@ARGV'\t\t\t\t:    5,\n\t\t'ARGV'\t\t\t\t:    5,\n\t\t'ARGVOUT'\t\t\t:    5,\n\t\t'$OUTPUT_FIELD_SEPARATOR'\t:    5,\n\t\t'$OFS'\t\t\t\t:    5,\n\t\t'$,'\t\t\t\t:    5,\n\t\t'$INPUT_LINE_NUMBER'\t\t:    5,\n\t\t'$NR'\t\t\t\t:    5,\n\t\t'$.'\t\t\t\t:    5,\n\t\t'$INPUT_RECORD_SEPARATOR'\t:    5,\n\t\t'$RS'\t\t\t\t:    5,\n\t\t'$/'\t\t\t\t:    5,\n\t\t'$OUTPUT_RECORD_SEPARATOR'\t:    5,\n\t\t'$ORS'\t\t\t\t:    5,\n\t\t'$\\\\'\t\t\t\t:    5,\n\t\t'$OUTPUT_AUTOFLUSH'\t\t:    5,\n\t\t'$|'\t\t\t\t:    5,\n\t\t'$ACCUMULATOR'\t\t\t:    5,\n\t\t'$^A'\t\t\t\t:    5,\n\t\t'$FORMAT_FORMFEED'\t\t:    5,\n\t\t'$^L'\t\t\t\t:    5,\n\t\t'$FORMAT_PAGE_NUMBER'\t\t:    5,\n\t\t'$%'\t\t\t\t:    5,\n\t\t'$FORMAT_LINES_LEFT'\t\t:    5,\n\t\t'$-'\t\t\t\t:    5,\n\t\t'$FORMAT_LINE_BREAK_CHARACTERS'\t:    5,\n\t\t'$:'\t\t\t\t:    5,\n\t\t'$FORMAT_LINES_PER_PAGE'\t:    5,\n\t\t'$='\t\t\t\t:    5,\n\t\t'$FORMAT_TOP_NAME'\t\t:    5,\n\t\t'$^'\t\t\t\t:    5,\n\t\t'$FORMAT_NAME'\t\t\t:    5,\n\t\t'$~'\t\t\t\t:    5,\n\t\t'${^CHILD_ERROR_NATIVE}'\t:    5,\n\t\t'$EXTENDED_OS_ERROR'\t\t:    5,\n\t\t'$^E'\t\t\t\t:    5,\n\t\t'$EXCEPTIONS_BEING_CAUGHT'\t:    5,\n\t\t'$^S'\t\t\t\t:    5,\n\t\t'$WARNING'\t\t\t:    5,\n\t\t'$^W'\t\t\t\t:    5,\n\t\t'${^WARNING_BITS}'\t\t:    5,\n\t\t'$OS_ERROR'\t\t\t:    5,\n\t\t'$ERRNO'\t\t\t:    5,\n\t\t'$!'\t\t\t\t:    5,\n\t\t'%OS_ERROR'\t\t\t:    5,\n\t\t'%ERRNO'\t\t\t:    5,\n\t\t'%!'\t\t\t\t:    5,\n\t\t'$CHILD_ERROR'\t\t\t:    5,\n\t\t'$?'\t\t\t\t:    5,\n\t\t'$EVAL_ERROR'\t\t\t:    5,\n\t\t'$@'\t\t\t\t:    5,\n\t\t'$OFMT'\t\t\t\t:    5,\n\t\t'$#'\t\t\t\t:    5,\n\t\t'$*'\t\t\t\t:    5,\n\t\t'$ARRAY_BASE'\t\t\t:    5,\n\t\t'$['\t\t\t\t:    5,\n\t\t'$OLD_PERL_VERSION'\t\t:    5,\n\t\t'$]'\t\t\t\t:    5,\n\t\t\t\t\t\t//\tPERL blocks\n\t\t'if'\t\t\t\t:[1,1],\n\t\telsif\t\t\t\t:[1,1],\n\t\t'else'\t\t\t\t:[1,1],\n\t\t'while'\t\t\t\t:[1,1],\n\t\tunless\t\t\t\t:[1,1],\n\t\t'for'\t\t\t\t:[1,1],\n\t\tforeach\t\t\t\t:[1,1],\n\t\t\t\t\t\t//\tPERL functions\n\t\t'abs'\t\t\t\t:1,\t// - absolute value function\n\t\taccept\t\t\t\t:1,\t// - accept an incoming socket connect\n\t\talarm\t\t\t\t:1,\t// - schedule a SIGALRM\n\t\t'atan2'\t\t\t\t:1,\t// - arctangent of Y/X in the range -PI to PI\n\t\tbind\t\t\t\t:1,\t// - binds an address to a socket\n\t\tbinmode\t\t\t\t:1,\t// - prepare binary files for I/O\n\t\tbless\t\t\t\t:1,\t// - create an object\n\t\tbootstrap\t\t\t:1,\t//\n\t\t'break'\t\t\t\t:1,\t// - break out of a \"given\" block\n\t\tcaller\t\t\t\t:1,\t// - get context of the current subroutine call\n\t\tchdir\t\t\t\t:1,\t// - change your current working directory\n\t\tchmod\t\t\t\t:1,\t// - changes the permissions on a list of files\n\t\tchomp\t\t\t\t:1,\t// - remove a trailing record separator from a string\n\t\tchop\t\t\t\t:1,\t// - remove the last character from a string\n\t\tchown\t\t\t\t:1,\t// - change the owership on a list of files\n\t\tchr\t\t\t\t:1,\t// - get character this number represents\n\t\tchroot\t\t\t\t:1,\t// - make directory new root for path lookups\n\t\tclose\t\t\t\t:1,\t// - close file (or pipe or socket) handle\n\t\tclosedir\t\t\t:1,\t// - close directory handle\n\t\tconnect\t\t\t\t:1,\t// - connect to a remote socket\n\t\t'continue'\t\t\t:[1,1],\t// - optional trailing block in a while or foreach\n\t\t'cos'\t\t\t\t:1,\t// - cosine function\n\t\tcrypt\t\t\t\t:1,\t// - one-way passwd-style encryption\n\t\tdbmclose\t\t\t:1,\t// - breaks binding on a tied dbm file\n\t\tdbmopen\t\t\t\t:1,\t// - create binding on a tied dbm file\n\t\t'default'\t\t\t:1,\t//\n\t\tdefined\t\t\t\t:1,\t// - test whether a value, variable, or function is defined\n\t\t'delete'\t\t\t:1,\t// - deletes a value from a hash\n\t\tdie\t\t\t\t:1,\t// - raise an exception or bail out\n\t\t'do'\t\t\t\t:1,\t// - turn a BLOCK into a TERM\n\t\tdump\t\t\t\t:1,\t// - create an immediate core dump\n\t\teach\t\t\t\t:1,\t// - retrieve the next key/value pair from a hash\n\t\tendgrent\t\t\t:1,\t// - be done using group file\n\t\tendhostent\t\t\t:1,\t// - be done using hosts file\n\t\tendnetent\t\t\t:1,\t// - be done using networks file\n\t\tendprotoent\t\t\t:1,\t// - be done using protocols file\n\t\tendpwent\t\t\t:1,\t// - be done using passwd file\n\t\tendservent\t\t\t:1,\t// - be done using services file\n\t\teof\t\t\t\t:1,\t// - test a filehandle for its end\n\t\t'eval'\t\t\t\t:1,\t// - catch exceptions or compile and run code\n\t\t'exec'\t\t\t\t:1,\t// - abandon this program to run another\n\t\texists\t\t\t\t:1,\t// - test whether a hash key is present\n\t\texit\t\t\t\t:1,\t// - terminate this program\n\t\t'exp'\t\t\t\t:1,\t// - raise I to a power\n\t\tfcntl\t\t\t\t:1,\t// - file control system call\n\t\tfileno\t\t\t\t:1,\t// - return file descriptor from filehandle\n\t\tflock\t\t\t\t:1,\t// - lock an entire file with an advisory lock\n\t\tfork\t\t\t\t:1,\t// - create a new process just like this one\n\t\tformat\t\t\t\t:1,\t// - declare a picture format with use by the write() function\n\t\tformline\t\t\t:1,\t// - internal function used for formats\n\t\tgetc\t\t\t\t:1,\t// - get the next character from the filehandle\n\t\tgetgrent\t\t\t:1,\t// - get next group record\n\t\tgetgrgid\t\t\t:1,\t// - get group record given group user ID\n\t\tgetgrnam\t\t\t:1,\t// - get group record given group name\n\t\tgethostbyaddr\t\t\t:1,\t// - get host record given its address\n\t\tgethostbyname\t\t\t:1,\t// - get host record given name\n\t\tgethostent\t\t\t:1,\t// - get next hosts record\n\t\tgetlogin\t\t\t:1,\t// - return who logged in at this tty\n\t\tgetnetbyaddr\t\t\t:1,\t// - get network record given its address\n\t\tgetnetbyname\t\t\t:1,\t// - get networks record given name\n\t\tgetnetent\t\t\t:1,\t// - get next networks record\n\t\tgetpeername\t\t\t:1,\t// - find the other end of a socket connection\n\t\tgetpgrp\t\t\t\t:1,\t// - get process group\n\t\tgetppid\t\t\t\t:1,\t// - get parent process ID\n\t\tgetpriority\t\t\t:1,\t// - get current nice value\n\t\tgetprotobyname\t\t\t:1,\t// - get protocol record given name\n\t\tgetprotobynumber\t\t:1,\t// - get protocol record numeric protocol\n\t\tgetprotoent\t\t\t:1,\t// - get next protocols record\n\t\tgetpwent\t\t\t:1,\t// - get next passwd record\n\t\tgetpwnam\t\t\t:1,\t// - get passwd record given user login name\n\t\tgetpwuid\t\t\t:1,\t// - get passwd record given user ID\n\t\tgetservbyname\t\t\t:1,\t// - get services record given its name\n\t\tgetservbyport\t\t\t:1,\t// - get services record given numeric port\n\t\tgetservent\t\t\t:1,\t// - get next services record\n\t\tgetsockname\t\t\t:1,\t// - retrieve the sockaddr for a given socket\n\t\tgetsockopt\t\t\t:1,\t// - get socket options on a given socket\n\t\tgiven\t\t\t\t:1,\t//\n\t\tglob\t\t\t\t:1,\t// - expand filenames using wildcards\n\t\tgmtime\t\t\t\t:1,\t// - convert UNIX time into record or string using Greenwich time\n\t\t'goto'\t\t\t\t:1,\t// - create spaghetti code\n\t\tgrep\t\t\t\t:1,\t// - locate elements in a list test true against a given criterion\n\t\thex\t\t\t\t:1,\t// - convert a string to a hexadecimal number\n\t\t'import'\t\t\t:1,\t// - patch a module's namespace into your own\n\t\tindex\t\t\t\t:1,\t// - find a substring within a string\n\t\t'int'\t\t\t\t:1,\t// - get the integer portion of a number\n\t\tioctl\t\t\t\t:1,\t// - system-dependent device control system call\n\t\t'join'\t\t\t\t:1,\t// - join a list into a string using a separator\n\t\tkeys\t\t\t\t:1,\t// - retrieve list of indices from a hash\n\t\tkill\t\t\t\t:1,\t// - send a signal to a process or process group\n\t\tlast\t\t\t\t:1,\t// - exit a block prematurely\n\t\tlc\t\t\t\t:1,\t// - return lower-case version of a string\n\t\tlcfirst\t\t\t\t:1,\t// - return a string with just the next letter in lower case\n\t\tlength\t\t\t\t:1,\t// - return the number of bytes in a string\n\t\t'link'\t\t\t\t:1,\t// - create a hard link in the filesytem\n\t\tlisten\t\t\t\t:1,\t// - register your socket as a server\n\t\tlocal\t\t\t\t: 2,\t// - create a temporary value for a global variable (dynamic scoping)\n\t\tlocaltime\t\t\t:1,\t// - convert UNIX time into record or string using local time\n\t\tlock\t\t\t\t:1,\t// - get a thread lock on a variable, subroutine, or method\n\t\t'log'\t\t\t\t:1,\t// - retrieve the natural logarithm for a number\n\t\tlstat\t\t\t\t:1,\t// - stat a symbolic link\n\t\tm\t\t\t\t:null,\t// - match a string with a regular expression pattern\n\t\tmap\t\t\t\t:1,\t// - apply a change to a list to get back a new list with the changes\n\t\tmkdir\t\t\t\t:1,\t// - create a directory\n\t\tmsgctl\t\t\t\t:1,\t// - SysV IPC message control operations\n\t\tmsgget\t\t\t\t:1,\t// - get SysV IPC message queue\n\t\tmsgrcv\t\t\t\t:1,\t// - receive a SysV IPC message from a message queue\n\t\tmsgsnd\t\t\t\t:1,\t// - send a SysV IPC message to a message queue\n\t\tmy\t\t\t\t: 2,\t// - declare and assign a local variable (lexical scoping)\n\t\t'new'\t\t\t\t:1,\t//\n\t\tnext\t\t\t\t:1,\t// - iterate a block prematurely\n\t\tno\t\t\t\t:1,\t// - unimport some module symbols or semantics at compile time\n\t\toct\t\t\t\t:1,\t// - convert a string to an octal number\n\t\topen\t\t\t\t:1,\t// - open a file, pipe, or descriptor\n\t\topendir\t\t\t\t:1,\t// - open a directory\n\t\tord\t\t\t\t:1,\t// - find a character's numeric representation\n\t\tour\t\t\t\t: 2,\t// - declare and assign a package variable (lexical scoping)\n\t\tpack\t\t\t\t:1,\t// - convert a list into a binary representation\n\t\t'package'\t\t\t:1,\t// - declare a separate global namespace\n\t\tpipe\t\t\t\t:1,\t// - open a pair of connected filehandles\n\t\tpop\t\t\t\t:1,\t// - remove the last element from an array and return it\n\t\tpos\t\t\t\t:1,\t// - find or set the offset for the last/next m//g search\n\t\tprint\t\t\t\t:1,\t// - output a list to a filehandle\n\t\tprintf\t\t\t\t:1,\t// - output a formatted list to a filehandle\n\t\tprototype\t\t\t:1,\t// - get the prototype (if any) of a subroutine\n\t\tpush\t\t\t\t:1,\t// - append one or more elements to an array\n\t\tq\t\t\t\t:null,\t// - singly quote a string\n\t\tqq\t\t\t\t:null,\t// - doubly quote a string\n\t\tqr\t\t\t\t:null,\t// - Compile pattern\n\t\tquotemeta\t\t\t:null,\t// - quote regular expression magic characters\n\t\tqw\t\t\t\t:null,\t// - quote a list of words\n\t\tqx\t\t\t\t:null,\t// - backquote quote a string\n\t\trand\t\t\t\t:1,\t// - retrieve the next pseudorandom number\n\t\tread\t\t\t\t:1,\t// - fixed-length buffered input from a filehandle\n\t\treaddir\t\t\t\t:1,\t// - get a directory from a directory handle\n\t\treadline\t\t\t:1,\t// - fetch a record from a file\n\t\treadlink\t\t\t:1,\t// - determine where a symbolic link is pointing\n\t\treadpipe\t\t\t:1,\t// - execute a system command and collect standard output\n\t\trecv\t\t\t\t:1,\t// - receive a message over a Socket\n\t\tredo\t\t\t\t:1,\t// - start this loop iteration over again\n\t\tref\t\t\t\t:1,\t// - find out the type of thing being referenced\n\t\trename\t\t\t\t:1,\t// - change a filename\n\t\trequire\t\t\t\t:1,\t// - load in external functions from a library at runtime\n\t\treset\t\t\t\t:1,\t// - clear all variables of a given name\n\t\t'return'\t\t\t:1,\t// - get out of a function early\n\t\treverse\t\t\t\t:1,\t// - flip a string or a list\n\t\trewinddir\t\t\t:1,\t// - reset directory handle\n\t\trindex\t\t\t\t:1,\t// - right-to-left substring search\n\t\trmdir\t\t\t\t:1,\t// - remove a directory\n\t\ts\t\t\t\t:null,\t// - replace a pattern with a string\n\t\tsay\t\t\t\t:1,\t// - print with newline\n\t\tscalar\t\t\t\t:1,\t// - force a scalar context\n\t\tseek\t\t\t\t:1,\t// - reposition file pointer for random-access I/O\n\t\tseekdir\t\t\t\t:1,\t// - reposition directory pointer\n\t\tselect\t\t\t\t:1,\t// - reset default output or do I/O multiplexing\n\t\tsemctl\t\t\t\t:1,\t// - SysV semaphore control operations\n\t\tsemget\t\t\t\t:1,\t// - get set of SysV semaphores\n\t\tsemop\t\t\t\t:1,\t// - SysV semaphore operations\n\t\tsend\t\t\t\t:1,\t// - send a message over a socket\n\t\tsetgrent\t\t\t:1,\t// - prepare group file for use\n\t\tsethostent\t\t\t:1,\t// - prepare hosts file for use\n\t\tsetnetent\t\t\t:1,\t// - prepare networks file for use\n\t\tsetpgrp\t\t\t\t:1,\t// - set the process group of a process\n\t\tsetpriority\t\t\t:1,\t// - set a process's nice value\n\t\tsetprotoent\t\t\t:1,\t// - prepare protocols file for use\n\t\tsetpwent\t\t\t:1,\t// - prepare passwd file for use\n\t\tsetservent\t\t\t:1,\t// - prepare services file for use\n\t\tsetsockopt\t\t\t:1,\t// - set some socket options\n\t\tshift\t\t\t\t:1,\t// - remove the first element of an array, and return it\n\t\tshmctl\t\t\t\t:1,\t// - SysV shared memory operations\n\t\tshmget\t\t\t\t:1,\t// - get SysV shared memory segment identifier\n\t\tshmread\t\t\t\t:1,\t// - read SysV shared memory\n\t\tshmwrite\t\t\t:1,\t// - write SysV shared memory\n\t\tshutdown\t\t\t:1,\t// - close down just half of a socket connection\n\t\t'sin'\t\t\t\t:1,\t// - return the sine of a number\n\t\tsleep\t\t\t\t:1,\t// - block for some number of seconds\n\t\tsocket\t\t\t\t:1,\t// - create a socket\n\t\tsocketpair\t\t\t:1,\t// - create a pair of sockets\n\t\t'sort'\t\t\t\t:1,\t// - sort a list of values\n\t\tsplice\t\t\t\t:1,\t// - add or remove elements anywhere in an array\n\t\t'split'\t\t\t\t:1,\t// - split up a string using a regexp delimiter\n\t\tsprintf\t\t\t\t:1,\t// - formatted print into a string\n\t\t'sqrt'\t\t\t\t:1,\t// - square root function\n\t\tsrand\t\t\t\t:1,\t// - seed the random number generator\n\t\tstat\t\t\t\t:1,\t// - get a file's status information\n\t\tstate\t\t\t\t:1,\t// - declare and assign a state variable (persistent lexical scoping)\n\t\tstudy\t\t\t\t:1,\t// - optimize input data for repeated searches\n\t\t'sub'\t\t\t\t:1,\t// - declare a subroutine, possibly anonymously\n\t\t'substr'\t\t\t:1,\t// - get or alter a portion of a stirng\n\t\tsymlink\t\t\t\t:1,\t// - create a symbolic link to a file\n\t\tsyscall\t\t\t\t:1,\t// - execute an arbitrary system call\n\t\tsysopen\t\t\t\t:1,\t// - open a file, pipe, or descriptor\n\t\tsysread\t\t\t\t:1,\t// - fixed-length unbuffered input from a filehandle\n\t\tsysseek\t\t\t\t:1,\t// - position I/O pointer on handle used with sysread and syswrite\n\t\tsystem\t\t\t\t:1,\t// - run a separate program\n\t\tsyswrite\t\t\t:1,\t// - fixed-length unbuffered output to a filehandle\n\t\ttell\t\t\t\t:1,\t// - get current seekpointer on a filehandle\n\t\ttelldir\t\t\t\t:1,\t// - get current seekpointer on a directory handle\n\t\ttie\t\t\t\t:1,\t// - bind a variable to an object class\n\t\ttied\t\t\t\t:1,\t// - get a reference to the object underlying a tied variable\n\t\ttime\t\t\t\t:1,\t// - return number of seconds since 1970\n\t\ttimes\t\t\t\t:1,\t// - return elapsed time for self and child processes\n\t\ttr\t\t\t\t:null,\t// - transliterate a string\n\t\ttruncate\t\t\t:1,\t// - shorten a file\n\t\tuc\t\t\t\t:1,\t// - return upper-case version of a string\n\t\tucfirst\t\t\t\t:1,\t// - return a string with just the next letter in upper case\n\t\tumask\t\t\t\t:1,\t// - set file creation mode mask\n\t\tundef\t\t\t\t:1,\t// - remove a variable or function definition\n\t\tunlink\t\t\t\t:1,\t// - remove one link to a file\n\t\tunpack\t\t\t\t:1,\t// - convert binary structure into normal perl variables\n\t\tunshift\t\t\t\t:1,\t// - prepend more elements to the beginning of a list\n\t\tuntie\t\t\t\t:1,\t// - break a tie binding to a variable\n\t\tuse\t\t\t\t:1,\t// - load in a module at compile time\n\t\tutime\t\t\t\t:1,\t// - set a file's last access and modify times\n\t\tvalues\t\t\t\t:1,\t// - return a list of the values in a hash\n\t\tvec\t\t\t\t:1,\t// - test or set particular bits in a string\n\t\twait\t\t\t\t:1,\t// - wait for any child process to die\n\t\twaitpid\t\t\t\t:1,\t// - wait for a particular child process to die\n\t\twantarray\t\t\t:1,\t// - get void vs scalar vs list context of current subroutine call\n\t\twarn\t\t\t\t:1,\t// - print debugging info\n\t\twhen\t\t\t\t:1,\t//\n\t\twrite\t\t\t\t:1,\t// - print a picture record\n\t\ty\t\t\t\t:null};\t// - transliterate a string\n\n\tvar RXstyle=\"string-2\";\n\tvar RXmodifiers=/[goseximacplud]/;\t\t// NOTE: \"m\", \"s\", \"y\" and \"tr\" need to correct real modifiers for each regexp type\n\n\tfunction tokenChain(stream,state,chain,style,tail){\t// NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)\n\t\tstate.chain=null;                               //                                                          12   3tail\n\t\tstate.style=null;\n\t\tstate.tail=null;\n\t\tstate.tokenize=function(stream,state){\n\t\t\tvar e=false,c,i=0;\n\t\t\twhile(c=stream.next()){\n\t\t\t\tif(c===chain[i]&&!e){\n\t\t\t\t\tif(chain[++i]!==undefined){\n\t\t\t\t\t\tstate.chain=chain[i];\n\t\t\t\t\t\tstate.style=style;\n\t\t\t\t\t\tstate.tail=tail}\n\t\t\t\t\telse if(tail)\n\t\t\t\t\t\tstream.eatWhile(tail);\n\t\t\t\t\tstate.tokenize=tokenPerl;\n\t\t\t\t\treturn style}\n\t\t\t\te=!e&&c==\"\\\\\"}\n\t\t\treturn style};\n\t\treturn state.tokenize(stream,state)}\n\n\tfunction tokenSOMETHING(stream,state,string){\n\t\tstate.tokenize=function(stream,state){\n\t\t\tif(stream.string==string)\n\t\t\t\tstate.tokenize=tokenPerl;\n\t\t\tstream.skipToEnd();\n\t\t\treturn \"string\"};\n\t\treturn state.tokenize(stream,state)}\n\n\tfunction tokenPerl(stream,state){\n\t\tif(stream.eatSpace())\n\t\t\treturn null;\n\t\tif(state.chain)\n\t\t\treturn tokenChain(stream,state,state.chain,state.style,state.tail);\n\t\tif(stream.match(/^\\-?[\\d\\.]/,false))\n\t\t\tif(stream.match(/^(\\-?(\\d*\\.\\d+(e[+-]?\\d+)?|\\d+\\.\\d*)|0x[\\da-fA-F]+|0b[01]+|\\d+(e[+-]?\\d+)?)/))\n\t\t\t\treturn 'number';\n\t\tif(stream.match(/^<<(?=\\w)/)){\t\t\t// NOTE: <<SOMETHING\\n...\\nSOMETHING\\n\n\t\t\tstream.eatWhile(/\\w/);\n\t\t\treturn tokenSOMETHING(stream,state,stream.current().substr(2))}\n\t\tif(stream.sol()&&stream.match(/^\\=item(?!\\w)/)){// NOTE: \\n=item...\\n=cut\\n\n\t\t\treturn tokenSOMETHING(stream,state,'=cut')}\n\t\tvar ch=stream.next();\n\t\tif(ch=='\"'||ch==\"'\"){\t\t\t\t// NOTE: ' or \" or <<'SOMETHING'\\n...\\nSOMETHING\\n or <<\"SOMETHING\"\\n...\\nSOMETHING\\n\n\t\t\tif(stream.prefix(3)==\"<<\"+ch){\n\t\t\t\tvar p=stream.pos;\n\t\t\t\tstream.eatWhile(/\\w/);\n\t\t\t\tvar n=stream.current().substr(1);\n\t\t\t\tif(n&&stream.eat(ch))\n\t\t\t\t\treturn tokenSOMETHING(stream,state,n);\n\t\t\t\tstream.pos=p}\n\t\t\treturn tokenChain(stream,state,[ch],\"string\")}\n\t\tif(ch==\"q\"){\n\t\t\tvar c=stream.look(-2);\n\t\t\tif(!(c&&/\\w/.test(c))){\n\t\t\t\tc=stream.look(0);\n\t\t\t\tif(c==\"x\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}\n\t\t\t\telse if(c==\"q\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],\"string\")}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],\"string\")}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],\"string\")}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],\"string\")}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],\"string\")}}\n\t\t\t\telse if(c==\"w\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],\"bracket\")}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],\"bracket\")}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],\"bracket\")}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],\"bracket\")}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],\"bracket\")}}\n\t\t\t\telse if(c==\"r\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}\n\t\t\t\telse if(/[\\^'\"!~\\/(\\[{<]/.test(c)){\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],\"string\")}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],\"string\")}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],\"string\")}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],\"string\")}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],\"string\")}}}}\n\t\tif(ch==\"m\"){\n\t\t\tvar c=stream.look(-2);\n\t\t\tif(!(c&&/\\w/.test(c))){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\treturn tokenChain(stream,state,[c],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}}}}\n\t\tif(ch==\"s\"){\n\t\t\tvar c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n\t\t\tif(!c){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(c==\"[\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"{\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"<\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"(\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n\t\t\t\t\treturn tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}\n\t\tif(ch==\"y\"){\n\t\t\tvar c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n\t\t\tif(!c){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(c==\"[\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"{\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"<\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"(\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n\t\t\t\t\treturn tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}\n\t\tif(ch==\"t\"){\n\t\t\tvar c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n\t\t\tif(!c){\n\t\t\t\tc=stream.eat(\"r\");if(c){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(c==\"[\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"{\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"<\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"(\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n\t\t\t\t\treturn tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}}\n\t\tif(ch==\"`\"){\n\t\t\treturn tokenChain(stream,state,[ch],\"variable-2\")}\n\t\tif(ch==\"/\"){\n\t\t\tif(!/~\\s*$/.test(stream.prefix()))\n\t\t\t\treturn \"operator\";\n\t\t\telse\n\t\t\t\treturn tokenChain(stream,state,[ch],RXstyle,RXmodifiers)}\n\t\tif(ch==\"$\"){\n\t\t\tvar p=stream.pos;\n\t\t\tif(stream.eatWhile(/\\d/)||stream.eat(\"{\")&&stream.eatWhile(/\\d/)&&stream.eat(\"}\"))\n\t\t\t\treturn \"variable-2\";\n\t\t\telse\n\t\t\t\tstream.pos=p}\n\t\tif(/[$@%]/.test(ch)){\n\t\t\tvar p=stream.pos;\n\t\t\tif(stream.eat(\"^\")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\\\\-#?@;:&`~\\^!\\[\\]*'\"$+.,\\/<>()]/)){\n\t\t\t\tvar c=stream.current();\n\t\t\t\tif(PERL[c])\n\t\t\t\t\treturn \"variable-2\"}\n\t\t\tstream.pos=p}\n\t\tif(/[$@%&]/.test(ch)){\n\t\t\tif(stream.eatWhile(/[\\w$\\[\\]]/)||stream.eat(\"{\")&&stream.eatWhile(/[\\w$\\[\\]]/)&&stream.eat(\"}\")){\n\t\t\t\tvar c=stream.current();\n\t\t\t\tif(PERL[c])\n\t\t\t\t\treturn \"variable-2\";\n\t\t\t\telse\n\t\t\t\t\treturn \"variable\"}}\n\t\tif(ch==\"#\"){\n\t\t\tif(stream.look(-2)!=\"$\"){\n\t\t\t\tstream.skipToEnd();\n\t\t\t\treturn \"comment\"}}\n\t\tif(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/.test(ch)){\n\t\t\tvar p=stream.pos;\n\t\t\tstream.eatWhile(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/);\n\t\t\tif(PERL[stream.current()])\n\t\t\t\treturn \"operator\";\n\t\t\telse\n\t\t\t\tstream.pos=p}\n\t\tif(ch==\"_\"){\n\t\t\tif(stream.pos==1){\n\t\t\t\tif(stream.suffix(6)==\"_END__\"){\n\t\t\t\t\treturn tokenChain(stream,state,['\\0'],\"comment\")}\n\t\t\t\telse if(stream.suffix(7)==\"_DATA__\"){\n\t\t\t\t\treturn tokenChain(stream,state,['\\0'],\"variable-2\")}\n\t\t\t\telse if(stream.suffix(7)==\"_C__\"){\n\t\t\t\t\treturn tokenChain(stream,state,['\\0'],\"string\")}}}\n\t\tif(/\\w/.test(ch)){\n\t\t\tvar p=stream.pos;\n\t\t\tif(stream.look(-2)==\"{\"&&(stream.look(0)==\"}\"||stream.eatWhile(/\\w/)&&stream.look(0)==\"}\"))\n\t\t\t\treturn \"string\";\n\t\t\telse\n\t\t\t\tstream.pos=p}\n\t\tif(/[A-Z]/.test(ch)){\n\t\t\tvar l=stream.look(-2);\n\t\t\tvar p=stream.pos;\n\t\t\tstream.eatWhile(/[A-Z_]/);\n\t\t\tif(/[\\da-z]/.test(stream.look(0))){\n\t\t\t\tstream.pos=p}\n\t\t\telse{\n\t\t\t\tvar c=PERL[stream.current()];\n\t\t\t\tif(!c)\n\t\t\t\t\treturn \"meta\";\n\t\t\t\tif(c[1])\n\t\t\t\t\tc=c[0];\n\t\t\t\tif(l!=\":\"){\n\t\t\t\t\tif(c==1)\n\t\t\t\t\t\treturn \"keyword\";\n\t\t\t\t\telse if(c==2)\n\t\t\t\t\t\treturn \"def\";\n\t\t\t\t\telse if(c==3)\n\t\t\t\t\t\treturn \"atom\";\n\t\t\t\t\telse if(c==4)\n\t\t\t\t\t\treturn \"operator\";\n\t\t\t\t\telse if(c==5)\n\t\t\t\t\t\treturn \"variable-2\";\n\t\t\t\t\telse\n\t\t\t\t\t\treturn \"meta\"}\n\t\t\t\telse\n\t\t\t\t\treturn \"meta\"}}\n\t\tif(/[a-zA-Z_]/.test(ch)){\n\t\t\tvar l=stream.look(-2);\n\t\t\tstream.eatWhile(/\\w/);\n\t\t\tvar c=PERL[stream.current()];\n\t\t\tif(!c)\n\t\t\t\treturn \"meta\";\n\t\t\tif(c[1])\n\t\t\t\tc=c[0];\n\t\t\tif(l!=\":\"){\n\t\t\t\tif(c==1)\n\t\t\t\t\treturn \"keyword\";\n\t\t\t\telse if(c==2)\n\t\t\t\t\treturn \"def\";\n\t\t\t\telse if(c==3)\n\t\t\t\t\treturn \"atom\";\n\t\t\t\telse if(c==4)\n\t\t\t\t\treturn \"operator\";\n\t\t\t\telse if(c==5)\n\t\t\t\t\treturn \"variable-2\";\n\t\t\t\telse\n\t\t\t\t\treturn \"meta\"}\n\t\t\telse\n\t\t\t\treturn \"meta\"}\n\t\treturn null}\n\n\treturn{\n\t\tstartState:function(){\n\t\t\treturn{\n\t\t\t\ttokenize:tokenPerl,\n\t\t\t\tchain:null,\n\t\t\t\tstyle:null,\n\t\t\t\ttail:null}},\n\t\ttoken:function(stream,state){\n\t\t\treturn (state.tokenize||tokenPerl)(stream,state)},\n\t\telectricChars:\"{}\"}});\n\nCodeMirror.defineMIME(\"text/x-perl\", \"perl\");\n\n// it's like \"peek\", but need for look-ahead or look-behind if index < 0\nCodeMirror.StringStream.prototype.look=function(c){\n\treturn this.string.charAt(this.pos+(c||0))};\n\n// return a part of prefix of current stream from current position\nCodeMirror.StringStream.prototype.prefix=function(c){\n\tif(c){\n\t\tvar x=this.pos-c;\n\t\treturn this.string.substr((x>=0?x:0),c)}\n\telse{\n\t\treturn this.string.substr(0,this.pos-1)}};\n\n// return a part of suffix of current stream from current position\nCodeMirror.StringStream.prototype.suffix=function(c){\n\tvar y=this.string.length;\n\tvar x=y-this.pos+1;\n\treturn this.string.substr(this.pos,(c&&c<y?c:x))};\n\n// return a part of suffix of current stream from current position and change current position\nCodeMirror.StringStream.prototype.nsuffix=function(c){\n\tvar p=this.pos;\n\tvar l=c||(this.string.length-this.pos+1);\n\tthis.pos+=l;\n\treturn this.string.substr(p,l)};\n\n// eating and vomiting a part of stream from current position\nCodeMirror.StringStream.prototype.eatSuffix=function(c){\n\tvar x=this.pos+c;\n\tvar y;\n\tif(x<=0)\n\t\tthis.pos=0;\n\telse if(x>=(y=this.string.length-1))\n\t\tthis.pos=y;\n\telse\n\t\tthis.pos=x};\n\ndefine(\"thirdparty/CodeMirror2/mode/perl/perl\", function(){});\n\nCodeMirror.defineMode(\"ruby\", function(config, parserConfig) {\n  function wordObj(words) {\n    var o = {};\n    for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;\n    return o;\n  }\n  var keywords = wordObj([\n    \"alias\", \"and\", \"BEGIN\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"defined?\", \"do\", \"else\",\n    \"elsif\", \"END\", \"end\", \"ensure\", \"false\", \"for\", \"if\", \"in\", \"module\", \"next\", \"not\", \"or\",\n    \"redo\", \"rescue\", \"retry\", \"return\", \"self\", \"super\", \"then\", \"true\", \"undef\", \"unless\",\n    \"until\", \"when\", \"while\", \"yield\", \"nil\", \"raise\", \"throw\", \"catch\", \"fail\", \"loop\", \"callcc\",\n    \"caller\", \"lambda\", \"proc\", \"public\", \"protected\", \"private\", \"require\", \"load\",\n    \"require_relative\", \"extend\", \"autoload\"\n  ]);\n  var indentWords = wordObj([\"def\", \"class\", \"case\", \"for\", \"while\", \"do\", \"module\", \"then\",\n                             \"catch\", \"loop\", \"proc\", \"begin\"]);\n  var dedentWords = wordObj([\"end\", \"until\"]);\n  var matching = {\"[\": \"]\", \"{\": \"}\", \"(\": \")\"};\n  var curPunc;\n\n  function chain(newtok, stream, state) {\n    state.tokenize.push(newtok);\n    return newtok(stream, state);\n  }\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    if (stream.sol() && stream.match(\"=begin\") && stream.eol()) {\n      state.tokenize.push(readBlockComment);\n      return \"comment\";\n    }\n    if (stream.eatSpace()) return null;\n    var ch = stream.next(), m;\n    if (ch == \"`\" || ch == \"'\" || ch == '\"' ||\n        (ch == \"/\" && !stream.eol() && stream.peek() != \" \")) {\n      return chain(readQuoted(ch, \"string\", ch == '\"' || ch == \"`\"), stream, state);\n    } else if (ch == \"%\") {\n      var style, embed = false;\n      if (stream.eat(\"s\")) style = \"atom\";\n      else if (stream.eat(/[WQ]/)) { style = \"string\"; embed = true; }\n      else if (stream.eat(/[wxqr]/)) style = \"string\";\n      var delim = stream.eat(/[^\\w\\s]/);\n      if (!delim) return \"operator\";\n      if (matching.propertyIsEnumerable(delim)) delim = matching[delim];\n      return chain(readQuoted(delim, style, embed, true), stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"<\" && (m = stream.match(/^<-?[\\`\\\"\\']?([a-zA-Z_?]\\w*)[\\`\\\"\\']?(?:;|$)/))) {\n      return chain(readHereDoc(m[1]), stream, state);\n    } else if (ch == \"0\") {\n      if (stream.eat(\"x\")) stream.eatWhile(/[\\da-fA-F]/);\n      else if (stream.eat(\"b\")) stream.eatWhile(/[01]/);\n      else stream.eatWhile(/[0-7]/);\n      return \"number\";\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^[\\d_]*(?:\\.[\\d_]+)?(?:[eE][+\\-]?[\\d_]+)?/);\n      return \"number\";\n    } else if (ch == \"?\") {\n      while (stream.match(/^\\\\[CM]-/)) {}\n      if (stream.eat(\"\\\\\")) stream.eatWhile(/\\w/);\n      else stream.next();\n      return \"string\";\n    } else if (ch == \":\") {\n      if (stream.eat(\"'\")) return chain(readQuoted(\"'\", \"atom\", false), stream, state);\n      if (stream.eat('\"')) return chain(readQuoted('\"', \"atom\", true), stream, state);\n      stream.eatWhile(/[\\w\\?]/);\n      return \"atom\";\n    } else if (ch == \"@\") {\n      stream.eat(\"@\");\n      stream.eatWhile(/[\\w\\?]/);\n      return \"variable-2\";\n    } else if (ch == \"$\") {\n      stream.next();\n      stream.eatWhile(/[\\w\\?]/);\n      return \"variable-3\";\n    } else if (/\\w/.test(ch)) {\n      stream.eatWhile(/[\\w\\?]/);\n      if (stream.eat(\":\")) return \"atom\";\n      return \"ident\";\n    } else if (ch == \"|\" && (state.varList || state.lastTok == \"{\" || state.lastTok == \"do\")) {\n      curPunc = \"|\";\n      return null;\n    } else if (/[\\(\\)\\[\\]{}\\\\;]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    } else if (ch == \"-\" && stream.eat(\">\")) {\n      return \"arrow\";\n    } else if (/[=+\\-\\/*:\\.^%<>~|]/.test(ch)) {\n      stream.eatWhile(/[=+\\-\\/*:\\.^%<>~|]/);\n      return \"operator\";\n    } else {\n      return null;\n    }\n  }\n\n  function tokenBaseUntilBrace() {\n    var depth = 1;\n    return function(stream, state) {\n      if (stream.peek() == \"}\") {\n        depth--;\n        if (depth == 0) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length-1](stream, state);\n        }\n      } else if (stream.peek() == \"{\") {\n        depth++;\n      }\n      return tokenBase(stream, state);\n    };\n  }\n  function readQuoted(quote, style, embed, unescaped) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && (unescaped || !escaped)) {\n          state.tokenize.pop();\n          break;\n        }\n        if (embed && ch == \"#\" && !escaped && stream.eat(\"{\")) {\n          state.tokenize.push(tokenBaseUntilBrace(arguments.callee));\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return style;\n    };\n  }\n  function readHereDoc(phrase) {\n    return function(stream, state) {\n      if (stream.match(phrase)) state.tokenize.pop();\n      else stream.skipToEnd();\n      return \"string\";\n    };\n  }\n  function readBlockComment(stream, state) {\n    if (stream.sol() && stream.match(\"=end\") && stream.eol())\n      state.tokenize.pop();\n    stream.skipToEnd();\n    return \"comment\";\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: [tokenBase],\n              indented: 0,\n              context: {type: \"top\", indented: -config.indentUnit},\n              continuedLine: false,\n              lastTok: null,\n              varList: false};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) state.indented = stream.indentation();\n      var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;\n      if (style == \"ident\") {\n        var word = stream.current();\n        style = keywords.propertyIsEnumerable(stream.current()) ? \"keyword\"\n          : /^[A-Z]/.test(word) ? \"tag\"\n          : (state.lastTok == \"def\" || state.lastTok == \"class\" || state.varList) ? \"def\"\n          : \"variable\";\n        if (indentWords.propertyIsEnumerable(word)) kwtype = \"indent\";\n        else if (dedentWords.propertyIsEnumerable(word)) kwtype = \"dedent\";\n        else if ((word == \"if\" || word == \"unless\") && stream.column() == stream.indentation())\n          kwtype = \"indent\";\n      }\n      if (curPunc || (style && style != \"comment\")) state.lastTok = word || curPunc || style;\n      if (curPunc == \"|\") state.varList = !state.varList;\n\n      if (kwtype == \"indent\" || /[\\(\\[\\{]/.test(curPunc))\n        state.context = {prev: state.context, type: curPunc || style, indented: state.indented};\n      else if ((kwtype == \"dedent\" || /[\\)\\]\\}]/.test(curPunc)) && state.context.prev)\n        state.context = state.context.prev;\n\n      if (stream.eol())\n        state.continuedLine = (curPunc == \"\\\\\" || style == \"operator\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0);\n      var ct = state.context;\n      var closing = ct.type == matching[firstChar] ||\n        ct.type == \"keyword\" && /^(?:end|until|else|elsif|when|rescue)\\b/.test(textAfter);\n      return ct.indented + (closing ? 0 : config.indentUnit) +\n        (state.continuedLine ? config.indentUnit : 0);\n    },\n     electricChars: \"}de\" // enD and rescuE\n\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-ruby\", \"ruby\");\n\n\ndefine(\"thirdparty/CodeMirror2/mode/ruby/ruby\", function(){});\n\n/*\n *\tMySQL Mode for CodeMirror 2 by MySQL-Tools\n *\t@author James Thorne (partydroid)\n *\t@link \thttp://github.com/partydroid/MySQL-Tools\n * \t@link \thttp://mysqltools.org\n *\t@version 02/Jan/2012\n*/\nCodeMirror.defineMode(\"mysql\", function(config) {\n  var indentUnit = config.indentUnit;\n  var curPunc;\n\n  function wordRegexp(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var ops = wordRegexp([\"str\", \"lang\", \"langmatches\", \"datatype\", \"bound\", \"sameterm\", \"isiri\", \"isuri\",\n                        \"isblank\", \"isliteral\", \"union\", \"a\"]);\n  var keywords = wordRegexp([\n  \t('ACCESSIBLE'),('ALTER'),('AS'),('BEFORE'),('BINARY'),('BY'),('CASE'),('CHARACTER'),('COLUMN'),('CONTINUE'),('CROSS'),('CURRENT_TIMESTAMP'),('DATABASE'),('DAY_MICROSECOND'),('DEC'),('DEFAULT'),\n\t('DESC'),('DISTINCT'),('DOUBLE'),('EACH'),('ENCLOSED'),('EXIT'),('FETCH'),('FLOAT8'),('FOREIGN'),('GRANT'),('HIGH_PRIORITY'),('HOUR_SECOND'),('IN'),('INNER'),('INSERT'),('INT2'),('INT8'),\n\t('INTO'),('JOIN'),('KILL'),('LEFT'),('LINEAR'),('LOCALTIME'),('LONG'),('LOOP'),('MATCH'),('MEDIUMTEXT'),('MINUTE_SECOND'),('NATURAL'),('NULL'),('OPTIMIZE'),('OR'),('OUTER'),('PRIMARY'),\n\t('RANGE'),('READ_WRITE'),('REGEXP'),('REPEAT'),('RESTRICT'),('RIGHT'),('SCHEMAS'),('SENSITIVE'),('SHOW'),('SPECIFIC'),('SQLSTATE'),('SQL_CALC_FOUND_ROWS'),('STARTING'),('TERMINATED'),\n\t('TINYINT'),('TRAILING'),('UNDO'),('UNLOCK'),('USAGE'),('UTC_DATE'),('VALUES'),('VARCHARACTER'),('WHERE'),('WRITE'),('ZEROFILL'),('ALL'),('AND'),('ASENSITIVE'),('BIGINT'),('BOTH'),('CASCADE'),\n\t('CHAR'),('COLLATE'),('CONSTRAINT'),('CREATE'),('CURRENT_TIME'),('CURSOR'),('DAY_HOUR'),('DAY_SECOND'),('DECLARE'),('DELETE'),('DETERMINISTIC'),('DIV'),('DUAL'),('ELSEIF'),('EXISTS'),('FALSE'),\n\t('FLOAT4'),('FORCE'),('FULLTEXT'),('HAVING'),('HOUR_MINUTE'),('IGNORE'),('INFILE'),('INSENSITIVE'),('INT1'),('INT4'),('INTERVAL'),('ITERATE'),('KEYS'),('LEAVE'),('LIMIT'),('LOAD'),('LOCK'),\n\t('LONGTEXT'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MEDIUMINT'),('MINUTE_MICROSECOND'),('MODIFIES'),('NO_WRITE_TO_BINLOG'),('ON'),('OPTIONALLY'),('OUT'),('PRECISION'),('PURGE'),('READS'),\n\t('REFERENCES'),('RENAME'),('REQUIRE'),('REVOKE'),('SCHEMA'),('SELECT'),('SET'),('SPATIAL'),('SQLEXCEPTION'),('SQL_BIG_RESULT'),('SSL'),('TABLE'),('TINYBLOB'),('TO'),('TRUE'),('UNIQUE'),\n\t('UPDATE'),('USING'),('UTC_TIMESTAMP'),('VARCHAR'),('WHEN'),('WITH'),('YEAR_MONTH'),('ADD'),('ANALYZE'),('ASC'),('BETWEEN'),('BLOB'),('CALL'),('CHANGE'),('CHECK'),('CONDITION'),('CONVERT'),\n\t('CURRENT_DATE'),('CURRENT_USER'),('DATABASES'),('DAY_MINUTE'),('DECIMAL'),('DELAYED'),('DESCRIBE'),('DISTINCTROW'),('DROP'),('ELSE'),('ESCAPED'),('EXPLAIN'),('FLOAT'),('FOR'),('FROM'),\n\t('GROUP'),('HOUR_MICROSECOND'),('IF'),('INDEX'),('INOUT'),('INT'),('INT3'),('INTEGER'),('IS'),('KEY'),('LEADING'),('LIKE'),('LINES'),('LOCALTIMESTAMP'),('LONGBLOB'),('LOW_PRIORITY'),\n\t('MEDIUMBLOB'),('MIDDLEINT'),('MOD'),('NOT'),('NUMERIC'),('OPTION'),('ORDER'),('OUTFILE'),('PROCEDURE'),('READ'),('REAL'),('RELEASE'),('REPLACE'),('RETURN'),('RLIKE'),('SECOND_MICROSECOND'),\n\t('SEPARATOR'),('SMALLINT'),('SQL'),('SQLWARNING'),('SQL_SMALL_RESULT'),('STRAIGHT_JOIN'),('THEN'),('TINYTEXT'),('TRIGGER'),('UNION'),('UNSIGNED'),('USE'),('UTC_TIME'),('VARBINARY'),('VARYING'),\n\t('WHILE'),('XOR'),('FULL'),('COLUMNS'),('MIN'),('MAX'),('STDEV'),('COUNT')\n  ]);\n  var operatorChars = /[*+\\-<>=&|]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    curPunc = null;\n    if (ch == \"$\" || ch == \"?\") {\n      stream.match(/^[\\w\\d]*/);\n      return \"variable-2\";\n    }\n    else if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n      stream.match(/^[^\\s\\u00a0>]*>?/);\n      return \"atom\";\n    }\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"`\") {\n      state.tokenize = tokenOpLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    else if (ch == \"-\") {\n\t\tch2 = stream.next();\n\t\tif(ch2==\"-\")\n\t\t{\n\t\t\tstream.skipToEnd();\n\t\t\treturn \"comment\";\n\t\t}\n\n    }\n    else if (operatorChars.test(ch)) {\n      stream.eatWhile(operatorChars);\n      return null;\n    }\n    else if (ch == \":\") {\n      stream.eatWhile(/[\\w\\d\\._\\-]/);\n      return \"atom\";\n    }\n    else {\n      stream.eatWhile(/[_\\w\\d]/);\n      if (stream.eat(\":\")) {\n        stream.eatWhile(/[\\w\\d_\\-]/);\n        return \"atom\";\n      }\n      var word = stream.current(), type;\n      if (ops.test(word))\n        return null;\n      else if (keywords.test(word))\n        return \"keyword\";\n      else\n        return \"variable\";\n    }\n  }\n\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n\n  function tokenOpLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"variable-2\";\n    };\n  }\n\n\n  function pushContext(state, type, col) {\n    state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n  }\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              context: null,\n              indent: 0,\n              col: 0};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null) state.context.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n        state.context.align = true;\n      }\n\n      if (curPunc == \"(\") pushContext(state, \")\", stream.column());\n      else if (curPunc == \"[\") pushContext(state, \"]\", stream.column());\n      else if (curPunc == \"{\") pushContext(state, \"}\", stream.column());\n      else if (/[\\]\\}\\)]/.test(curPunc)) {\n        while (state.context && state.context.type == \"pattern\") popContext(state);\n        if (state.context && curPunc == state.context.type) popContext(state);\n      }\n      else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n      else if (/atom|string|variable/.test(style) && state.context) {\n        if (/[\\}\\]]/.test(state.context.type))\n          pushContext(state, \"pattern\", stream.column());\n        else if (state.context.type == \"pattern\" && !state.context.align) {\n          state.context.align = true;\n          state.context.col = stream.column();\n        }\n      }\n\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var firstChar = textAfter && textAfter.charAt(0);\n      var context = state.context;\n      if (/[\\]\\}]/.test(firstChar))\n        while (context && context.type == \"pattern\") context = context.prev;\n\n      var closing = context && firstChar == context.type;\n      if (!context)\n        return 0;\n      else if (context.type == \"pattern\")\n        return context.col;\n      else if (context.align)\n        return context.col + (closing ? 0 : 1);\n      else\n        return context.indent + (closing ? 0 : indentUnit);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-mysql\", \"mysql\");\n\ndefine(\"thirdparty/CodeMirror2/mode/mysql/mysql\", function(){});\n\nCodeMirror.defineMode(\"diff\", function() {\n\n  var TOKEN_NAMES = {\n    '+': 'tag',\n    '-': 'string',\n    '@': 'meta'\n  };\n\n  return {\n    token: function(stream) {\n      var tw_pos = stream.string.search(/[\\t ]+?$/);\n\n      if (!stream.sol() || tw_pos === 0) {\n        stream.skipToEnd();\n        return (\"error \" + (\n          TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');\n      }\n\n      var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();\n\n      if (tw_pos === -1) {\n        stream.skipToEnd();\n      } else {\n        stream.pos = tw_pos;\n      }\n\n      return token_name;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-diff\", \"diff\");\n\ndefine(\"thirdparty/CodeMirror2/mode/diff/diff\", function(){});\n\nCodeMirror.defineMode(\"markdown\", function(cmCfg, modeCfg) {\n\n  var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });\n\n  var header   = 'header'\n  ,   code     = 'comment'\n  ,   quote    = 'quote'\n  ,   list     = 'string'\n  ,   hr       = 'hr'\n  ,   linktext = 'link'\n  ,   linkhref = 'string'\n  ,   em       = 'em'\n  ,   strong   = 'strong'\n  ,   emstrong = 'emstrong';\n\n  var hrRE = /^([*\\-=_])(?:\\s*\\1){2,}\\s*$/\n  ,   ulRE = /^[*\\-+]\\s+/\n  ,   olRE = /^[0-9]+\\.\\s+/\n  ,   headerRE = /^(?:\\={3,}|-{3,})$/\n  ,   textRE = /^[^\\[*_\\\\<>`]+/;\n\n  function switchInline(stream, state, f) {\n    state.f = state.inline = f;\n    return f(stream, state);\n  }\n\n  function switchBlock(stream, state, f) {\n    state.f = state.block = f;\n    return f(stream, state);\n  }\n\n\n  // Blocks\n\n  function blankLine(state) {\n    // Reset EM state\n    state.em = false;\n    // Reset STRONG state\n    state.strong = false;\n    return null;\n  }\n\n  function blockNormal(stream, state) {\n    var match;\n    if (state.indentationDiff >= 4) {\n      state.indentation -= state.indentationDiff;\n      stream.skipToEnd();\n      return code;\n    } else if (stream.eatSpace()) {\n      return null;\n    } else if (stream.peek() === '#' || stream.match(headerRE)) {\n      state.header = true;\n    } else if (stream.eat('>')) {\n      state.indentation++;\n      state.quote = true;\n    } else if (stream.peek() === '[') {\n      return switchInline(stream, state, footnoteLink);\n    } else if (stream.match(hrRE, true)) {\n      return hr;\n    } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {\n      state.indentation += match[0].length;\n      return list;\n    }\n    \n    return switchInline(stream, state, state.inline);\n  }\n\n  function htmlBlock(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {\n      state.f = inlineNormal;\n      state.block = blockNormal;\n    }\n    return style;\n  }\n\n\n  // Inline\n  function getType(state) {\n    var styles = [];\n    \n    if (state.strong) { styles.push(state.em ? emstrong : strong); }\n    else if (state.em) { styles.push(em); }\n    \n    if (state.header) { styles.push(header); }\n    if (state.quote) { styles.push(quote); }\n\n    return styles.length ? styles.join(' ') : null;\n  }\n\n  function handleText(stream, state) {\n    if (stream.match(textRE, true)) {\n      return getType(state);\n    }\n    return undefined;        \n  }\n\n  function inlineNormal(stream, state) {\n    var style = state.text(stream, state)\n    if (typeof style !== 'undefined')\n      return style;\n    \n    var ch = stream.next();\n    \n    if (ch === '\\\\') {\n      stream.next();\n      return getType(state);\n    }\n    if (ch === '`') {\n      return switchInline(stream, state, inlineElement(code, '`'));\n    }\n    if (ch === '[') {\n      return switchInline(stream, state, linkText);\n    }\n    if (ch === '<' && stream.match(/^\\w/, false)) {\n      stream.backUp(1);\n      return switchBlock(stream, state, htmlBlock);\n    }\n\n    var t = getType(state);\n    if (ch === '*' || ch === '_') {\n      if (stream.eat(ch)) {\n        return (state.strong = !state.strong) ? getType(state) : t;\n      }\n      return (state.em = !state.em) ? getType(state) : t;\n    }\n    \n    return getType(state);\n  }\n\n  function linkText(stream, state) {\n    while (!stream.eol()) {\n      var ch = stream.next();\n      if (ch === '\\\\') stream.next();\n      if (ch === ']') {\n        state.inline = state.f = linkHref;\n        return linktext;\n      }\n    }\n    return linktext;\n  }\n\n  function linkHref(stream, state) {\n    stream.eatSpace();\n    var ch = stream.next();\n    if (ch === '(' || ch === '[') {\n      return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));\n    }\n    return 'error';\n  }\n\n  function footnoteLink(stream, state) {\n    if (stream.match(/^[^\\]]*\\]:/, true)) {\n      state.f = footnoteUrl;\n      return linktext;\n    }\n    return switchInline(stream, state, inlineNormal);\n  }\n\n  function footnoteUrl(stream, state) {\n    stream.eatSpace();\n    stream.match(/^[^\\s]+/, true);\n    state.f = state.inline = inlineNormal;\n    return linkhref;\n  }\n\n  function inlineRE(endChar) {\n    if (!inlineRE[endChar]) {\n      // match any not-escaped-non-endChar and any escaped char\n      // then match endChar or eol\n      inlineRE[endChar] = new RegExp('^(?:[^\\\\\\\\\\\\' + endChar + ']|\\\\\\\\.)*(?:\\\\' + endChar + '|$)');\n    }\n    return inlineRE[endChar];\n  }\n\n  function inlineElement(type, endChar, next) {\n    next = next || inlineNormal;\n    return function(stream, state) {\n      stream.match(inlineRE(endChar));\n      state.inline = state.f = next;\n      return type;\n    };\n  }\n\n  return {\n    startState: function() {\n      return {\n        f: blockNormal,\n        \n        block: blockNormal,\n        htmlState: htmlMode.startState(),\n        indentation: 0,\n        \n        inline: inlineNormal,\n        text: handleText,\n        em: false,\n        strong: false,\n        header: false,\n        quote: false\n      };\n    },\n\n    copyState: function(s) {\n      return {\n        f: s.f,\n        \n        block: s.block,\n        htmlState: CodeMirror.copyState(htmlMode, s.htmlState),\n        indentation: s.indentation,\n        \n        inline: s.inline,\n        text: s.text,\n        em: s.em,\n        strong: s.strong,\n        header: s.header,\n        quote: s.quote\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (stream.match(/^\\s*$/, true)) { return blankLine(state); }\n\n        // Reset state.header\n        state.header = false;\n        // Reset state.quote\n        state.quote = false;\n\n        state.f = state.block;\n        var indentation = stream.match(/^\\s*/, true)[0].replace(/\\t/g, '    ').length;\n        state.indentationDiff = indentation - state.indentation;\n        state.indentation = indentation;\n        if (indentation > 0) { return null; }\n      }\n      return state.f(stream, state);\n    },\n\n    blankLine: blankLine,\n\n    getType: getType\n  };\n\n}, \"xml\");\n\nCodeMirror.defineMIME(\"text/x-markdown\", \"markdown\");\n\ndefine(\"thirdparty/CodeMirror2/mode/markdown/markdown\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, PathUtils, FileError, brackets */\n\n/**\n * Set of utilites for working with the code editor\n */\ndefine('editor/EditorUtils',['require','exports','module','thirdparty/path-utils/path-utils.min','thirdparty/CodeMirror2/mode/xml/xml','thirdparty/CodeMirror2/mode/javascript/javascript','thirdparty/CodeMirror2/mode/css/css','thirdparty/CodeMirror2/mode/less/less','thirdparty/CodeMirror2/mode/htmlmixed/htmlmixed','thirdparty/CodeMirror2/mode/clike/clike','thirdparty/CodeMirror2/mode/php/php','thirdparty/CodeMirror2/mode/coffeescript/coffeescript','thirdparty/CodeMirror2/mode/clojure/clojure','thirdparty/CodeMirror2/mode/perl/perl','thirdparty/CodeMirror2/mode/ruby/ruby','thirdparty/CodeMirror2/mode/mysql/mysql','thirdparty/CodeMirror2/mode/diff/diff','thirdparty/CodeMirror2/mode/markdown/markdown'],function (require, exports, module) {\n    \n\n    require(\"thirdparty/path-utils/path-utils.min\");\n    require(\"thirdparty/CodeMirror2/mode/xml/xml\");\n    require(\"thirdparty/CodeMirror2/mode/javascript/javascript\");\n    require(\"thirdparty/CodeMirror2/mode/css/css\");\n    require(\"thirdparty/CodeMirror2/mode/less/less\");\n    require(\"thirdparty/CodeMirror2/mode/htmlmixed/htmlmixed\");\n    require(\"thirdparty/CodeMirror2/mode/clike/clike\");\n    require(\"thirdparty/CodeMirror2/mode/php/php\");\n    require(\"thirdparty/CodeMirror2/mode/coffeescript/coffeescript\");\n    require(\"thirdparty/CodeMirror2/mode/clojure/clojure\");\n    require(\"thirdparty/CodeMirror2/mode/perl/perl\");\n    require(\"thirdparty/CodeMirror2/mode/ruby/ruby\");\n    require(\"thirdparty/CodeMirror2/mode/mysql/mysql\");\n    require(\"thirdparty/CodeMirror2/mode/diff/diff\");\n    require(\"thirdparty/CodeMirror2/mode/markdown/markdown\");\n\n    /**\n     * @private\n     * Given a file URL, determines the mode to use based\n     * off the file's extension.\n     * @param {string} fileUrl  A cannonical file URL to extract the extension from\n     */\n    function getModeFromFileExtension(fileUrl) {\n        var ext = PathUtils.filenameExtension(fileUrl);\n        //incase the arg is just the ext\n        if (!ext) {\n            ext = fileUrl;\n        }\n        if (ext.charAt(0) === \".\") {\n            ext = ext.substr(1);\n        }\n\n        switch (ext) {\n\n        case \"js\":\n            return \"javascript\";\n\n        case \"json\":\n            return {name: \"javascript\", json: true};\n\n        case \"css\":\n            return \"css\";\n\n        case \"less\":\n            return \"less\";\n\n        case \"html\":\n        case \"htm\":\n        case \"xhtml\":\n        case \"cfm\":\n        case \"cfc\":\n            return \"htmlmixed\";\n\n        case \"xml\":\n            return \"xml\";\n\n        case \"php\":\n        case \"php3\":\n        case \"php4\":\n        case \"php5\":\n        case \"phtm\":\n        case \"phtml\":\n            return \"php\";\n\n        case \"cc\":\n        case \"cp\":\n        case \"cpp\":\n        case \"c++\":\n        case \"cxx\":\n        case \"hh\":\n        case \"hpp\":\n        case \"hxx\":\n        case \"h++\":\n        case \"ii\":\n            return \"text/x-c++src\";\n\n        case \"c\":\n        case \"h\":\n        case \"i\":\n            return \"text/x-csrc\";\n\n        case \"cs\":\n            return \"text/x-csharp\";\n\n        case \"java\":\n            return \"text/x-java\";\n\n        case \"coffee\":\n            return \"coffeescript\";\n\n        case \"clj\":\n            return \"clojure\";\n\n        case \"pl\":\n            return \"perl\";\n\n        case \"rb\":\n            return \"ruby\";\n\n        case \"sql\":\n            return \"mysql\";\n\n        case \"diff\":\n        case \"patch\":\n            return \"diff\";\n\n        case \"md\":\n            return \"markdown\";\n\n        default:\n            console.log(\"Called EditorUtils.js _getModeFromFileExtensions with an unhandled file extension: \" + ext);\n            return \"\";\n        }\n    }\n\n    // Define public API\n    exports.getModeFromFileExtension = getModeFromFileExtension;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\n/**\n * EditorManager owns the UI for the editor area. This essentially mirrors the 'current document'\n * property maintained by DocumentManager's model.\n *\n * Note that there is a little bit of unusual overlap between EditorManager and DocumentManager:\n * because the Document state is actually stored in the CodeMirror editor UI, DocumentManager is\n * not a pure headless model. Each Document encapsulates an editor instance, and thus EditorManager\n * must have some knowledge about Document's internal state (we access its _editor property).\n *\n * This module dispatches the following events:\n *    - focusedEditorChange -- When the focused editor (full or inline) changes and size/visibility are complete.\n */\ndefine('editor/EditorManager',['require','exports','module','file/FileUtils','command/Commands','command/CommandManager','document/DocumentManager','utils/PerfUtils','editor/Editor','editor/InlineTextEditor','editor/EditorUtils','utils/ViewUtils','strings'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var FileUtils           = require(\"file/FileUtils\"),\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Editor              = require(\"editor/Editor\").Editor,\n        InlineTextEditor    = require(\"editor/InlineTextEditor\").InlineTextEditor,\n        EditorUtils         = require(\"editor/EditorUtils\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        Strings             = require(\"strings\");\n    \n    /** @type {jQueryObject} DOM node that contains all editors (visible and hidden alike) */\n    var _editorHolder = null;\n    \n    /** @type {Editor} */\n    var _currentEditor = null;\n    /** @type {Document} */\n    var _currentEditorsDocument = null;\n    \n    /** @type {number} Used by {@link #_updateEditorSize()} */\n    var _resizeTimeout = null;\n    \n    /**\n     * Registered inline-editor widget providers. See {@link #registerInlineEditProvider()}.\n     * @type {Array.<function(...)>}\n     */\n    var _inlineEditProviders = [];\n    \n    \n    /**\n     * Adds keyboard command handlers to an Editor instance.\n     * @param {Editor} editor \n     * @param {!Object.<string,function(Editor)>} to destination key mapping\n     * @param {!Object.<string,function(Editor)>} from source key mapping\n     */\n    function mergeExtraKeys(editor, to, from) {\n        // Merge in the additionalKeys we were passed\n        function wrapEventHandler(externalHandler) {\n            return function (instance) {\n                externalHandler(editor);\n            };\n        }\n        var key;\n        for (key in from) {\n            if (from.hasOwnProperty(key)) {\n                if (to.hasOwnProperty(key)) {\n                    console.log(\"Warning: overwriting standard Editor shortcut \" + key);\n                }\n                to[key] = (editor !== null) ? wrapEventHandler(from[key]) : from[key];\n            }\n        }\n    }\n    \n    /**\n     * Creates a new Editor bound to the given Document. The editor's mode is inferred based on the\n     * file extension. The editor is appended to the given container as a visible child.\n     * @param {!Document} doc  Document for the Editor's content\n     * @param {!boolean} makeMasterEditor  If true, the Editor will set itself as the private \"master\"\n     *          Editor for the Document. If false, the Editor will attach to the Document as a \"slave.\"\n     * @param {!jQueryObject} container  Container to add the editor to.\n     * @param {{startLine: number, endLine: number}=} range If specified, range of lines within the document\n     *          to display in this editor. Inclusive.\n     * @return {Editor} the newly created editor.\n     */\n    function _createEditorForDocument(doc, makeMasterEditor, container, range, additionalKeys) {\n        var mode = EditorUtils.getModeFromFileExtension(doc.file.fullPath);\n        \n        return new Editor(doc, makeMasterEditor, mode, container, additionalKeys, range);\n    }\n    \n    /**\n     * @private\n     * Bound to Ctrl+E on outermost editors.\n     * @param {!Editor} editor the candidate host editor\n     * @return {$.Promise} a promise that will be resolved when an InlineWidget \n     *      is created or rejected when no inline editors are available.\n     */\n    function _openInlineWidget(editor) {\n        PerfUtils.markStart(PerfUtils.INLINE_EDITOR_OPEN);\n        \n        // Run through inline-editor providers until one responds\n        var pos = editor.getCursorPos(),\n            inlinePromise,\n            i,\n            result = new $.Deferred();\n        \n        for (i = 0; i < _inlineEditProviders.length && !inlinePromise; i++) {\n            var provider = _inlineEditProviders[i];\n            inlinePromise = provider(editor, pos);\n        }\n        \n        // If one of them will provide a widget, show it inline once ready\n        if (inlinePromise) {\n            inlinePromise.done(function (inlineWidget) {\n                editor.addInlineWidget(pos, inlineWidget);\n                PerfUtils.addMeasurement(PerfUtils.INLINE_EDITOR_OPEN);\n                result.resolve();\n            }).fail(function () {\n                // terminate timer that was started above\n                PerfUtils.finalizeMeasurement(PerfUtils.INLINE_EDITOR_OPEN);\n                result.reject();\n            });\n        } else {\n            // terminate timer that was started above\n            PerfUtils.finalizeMeasurement(PerfUtils.INLINE_EDITOR_OPEN);\n            result.reject();\n        }\n        \n        return result.promise();\n    }\n    \n    /**\n     * Removes the given widget UI from the given hostEditor (agnostic of what the widget's content\n     * is). The widget's onClosed() callback will be run as a result.\n     * @param {!Editor} hostEditor The editor containing the widget.\n     * @param {!InlineWidget} inlineWidget The inline widget to close.\n     * @param {!boolean} moveFocus  If true, focuses hostEditor and ensures the cursor position lies\n     *      near the inline's location.\n     */\n    function closeInlineWidget(hostEditor, inlineWidget, moveFocus) {\n        if (moveFocus) {\n            // Place cursor back on the line just above the inline (the line from which it was opened)\n            // If cursor's already on that line, leave it be to preserve column position\n            var widgetLine = hostEditor._codeMirror.getInlineWidgetInfo(inlineWidget.id).line;\n            var cursorLine = hostEditor.getCursorPos().line;\n            if (cursorLine !== widgetLine) {\n                hostEditor.setCursorPos({ line: widgetLine, pos: 0 });\n            }\n            \n            hostEditor.focus();\n        }\n        \n        hostEditor.removeInlineWidget(inlineWidget);\n    }\n    \n    /**\n     * Registers a new inline provider. When _openInlineWidget() is called each registered inline\n     * widget is called and asked if it wants to provide an inline widget given the current cursor\n     * location and document.\n     * @param {function} provider \n     *      Parameters: \n     *      {!Editor} editor, {!{line:Number, ch:Number}} pos\n     *      \n     *      Returns:\n     *      {$.Promise} a promise that will be resolved with an inlineWidget\n     *      or null to indicate the provider doesn't create an editor in this case\n     */\n    function registerInlineEditProvider(provider) {\n        _inlineEditProviders.push(provider);\n    }\n    \n    /**\n     * @private\n     * Given a host editor, return a list of all Editors in all its open inline widgets. (Ignoring\n     * any other inline widgets that might be open but don't contain Editors).\n     * @param {!Editor} hostEditor\n     * @return {Array.<Editor>}\n     *\n     */\n    function getInlineEditors(hostEditor) {\n        var inlineEditors = [];\n        hostEditor.getInlineWidgets().forEach(function (widget) {\n            if (widget instanceof InlineTextEditor) {\n                inlineEditors = inlineEditors.concat(widget.editors);\n            }\n        });\n        return inlineEditors;\n    }\n    \n    \n    \n    /**\n     * @private\n     * Creates a new \"full-size\" (not inline) Editor for the given Document, and sets it as the\n     * Document's master backing editor. The editor is not yet visible; to show it, use\n     * DocumentManager.setCurrentDocument().\n     * Semi-private: should only be called within this module or by Document.\n     * @param {!Document} document  Document whose main/full Editor to create\n     */\n    function _createFullEditorForDocument(document) {\n        // Create editor; make it initially invisible\n        var container = _editorHolder.get(0);\n        var editor = _createEditorForDocument(document, true, container);\n        editor.setVisible(false);\n    }\n    \n    /** Returns the visible full-size Editor corresponding to DocumentManager.getCurrentDocument() */\n    function getCurrentFullEditor() {\n        // This *should* always be equivalent to DocumentManager.getCurrentDocument()._masterEditor\n        return _currentEditor;\n    }\n\n    \n    /**\n     * Creates a new inline Editor instance for the given Document. The editor's mode is inferred\n     * based on the file extension. The editor is not yet visible or attached to a host editor.\n     * @param {!Document} doc  Document for the Editor's content\n     * @param {?{startLine:Number, endLine:Number}} range  If specified, all lines outside the given\n     *      range are hidden from the editor. Range is inclusive. Line numbers start at 0.\n     * @param {HTMLDivContainer} inlineContent\n     * @param  {function(inlineWidget)} closeThisInline\n     *\n     * @return {{content:DOMElement, editor:Editor}}\n     */\n    function createInlineEditorForDocument(doc, range, inlineContent, additionalKeys) {\n        // Create the Editor\n        var inlineEditor = _createEditorForDocument(doc, false, inlineContent, range, additionalKeys);\n        \n        $(exports).triggerHandler(\"focusedEditorChange\", inlineEditor);\n        \n        return { content: inlineContent, editor: inlineEditor };\n    }\n    \n    \n    /**\n     * Disposes the given Document's full-size editor if the doc is no longer \"open\" from the user's\n     * standpoint - not in the working set and not currentDocument).\n     * \n     * Destroying the full-size editor releases ONE ref to the Document; if inline editors or other\n     * UI elements are still referencing the Document it will still be 'open' (kept alive) from\n     * DocumentManager's standpoint. However, destroying the full-size editor does remove the backing\n     * \"master\" editor from the Document, rendering it immutable until either inline-editor edits or\n     * currentDocument change triggers _createFullEditorForDocument() full-size editor again.\n     *\n     * In certain edge cases, this is called directly by DocumentManager; see _gcDocuments() for details.\n     *\n     * @param {!Document} document Document whose \"master\" editor we may destroy\n     */\n    function _destroyEditorIfUnneeded(document) {\n        var editor = document._masterEditor;\n\n        if (!editor) {\n            return;\n        }\n        \n        // If outgoing editor is no longer needed, dispose it\n        var isCurrentDocument = (DocumentManager.getCurrentDocument() === document);\n        var isInWorkingSet = (DocumentManager.findInWorkingSet(document.file.fullPath) !== -1);\n        if (!isCurrentDocument && !isInWorkingSet) {\n            // Destroy the editor widget (which un-refs the Document and reverts it to read-only mode)\n            editor.destroy();\n            \n            // Our callers should really ensure this, but just for safety...\n            if (_currentEditor === editor) {\n                _currentEditorsDocument = null;\n                _currentEditor = null;\n            }\n        }\n    }\n\n    /** Focus the currently visible full-size editor. If no editor visible, does nothing. */\n    function focusEditor() {\n        if (_currentEditor) {\n            _currentEditor.focus();\n        }\n    }\n    \n    \n    /** \n     * Resize the editor. This should only be called if the contents of the editor holder are changed\n     * or if the height of the editor holder changes (except for overall window resizes, which are\n     * already taken care of automatically).\n     * @see #_updateEditorSize()\n     */\n    function resizeEditor() {\n        if (_currentEditor) {\n            $(_currentEditor.getScrollerElement()).height(_editorHolder.height());\n            _currentEditor.refresh();\n        }\n    }\n    \n    /**\n     * NJ's editor-resizing fix. Whenever the window resizes, we immediately adjust the editor's\n     * height.\n     * @see #resizeEditor()\n     */\n    function _updateEditorSize() {\n        // The editor itself will call refresh() when it gets the window resize event.\n        if (_currentEditor) {\n            $(_currentEditor.getScrollerElement()).height(_editorHolder.height());\n        }\n    }\n    \n    \n    /**\n     * @private\n     */\n    function _doShow(document) {\n        // Show new editor\n        _currentEditorsDocument = document;\n        _currentEditor = document._masterEditor;\n        \n        _currentEditor.setVisible(true);\n        \n        // Window may have been resized since last time editor was visible, so kick it now\n        resizeEditor();\n        \n        $(exports).triggerHandler(\"focusedEditorChange\", _currentEditor);\n    }\n\n    /**\n     * Make the given document's editor visible in the UI, hiding whatever was\n     * visible before. Creates a new editor if none is assigned.\n     * @param {!Document} document\n     */\n    function _showEditor(document) {\n        // Hide whatever was visible before\n        if (!_currentEditor) {\n            $(\"#not-editor\").css(\"display\", \"none\");\n        } else {\n            _currentEditor.setVisible(false);\n            _destroyEditorIfUnneeded(_currentEditorsDocument);\n        }\n        \n        // Ensure a main editor exists for this document to show in the UI\n        if (!document._masterEditor) {\n            // Editor doesn't exist: populate a new Editor with the text\n            _createFullEditorForDocument(document);\n        }\n        \n        _doShow(document);\n    }\n    \n\n    /** Hide the currently visible editor and show a placeholder UI in its place */\n    function _showNoEditor() {\n        if (_currentEditor) {\n            _currentEditor.setVisible(false);\n            _destroyEditorIfUnneeded(_currentEditorsDocument);\n            \n            _currentEditorsDocument = null;\n            _currentEditor = null;\n            \n            $(\"#not-editor\").css(\"display\", \"\");\n        \n            $(exports).triggerHandler(\"focusedEditorChange\", _currentEditor);\n        }\n    }\n\n    /** Handles changes to DocumentManager.getCurrentDocument() */\n    function _onCurrentDocumentChange() {\n        var doc = DocumentManager.getCurrentDocument(),\n            container = _editorHolder.get(0);\n        \n        var perfTimerName = PerfUtils.markStart(\"EditorManager._onCurrentDocumentChange():\\t\" + (!doc || doc.file.fullPath));\n\n        // Remove scroller-shadow from the current editor\n        if (_currentEditor) {\n            ViewUtils.removeScrollerShadow(container, _currentEditor);\n        }\n        \n        // Update the UI to show the right editor (or nothing), and also dispose old editor if no\n        // longer needed.\n        if (doc) {\n            _showEditor(doc);\n            ViewUtils.addScrollerShadow(container, _currentEditor);\n        } else {\n            _showNoEditor();\n        }\n\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n    \n    /** Handles removals from DocumentManager's working set list */\n    function _onWorkingSetRemove(event, removedFile) {\n        // There's one case where an editor should be disposed even though the current document\n        // didn't change: removing a document from the working set (via the \"X\" button). (This may\n        // also cover the case where the document WAS current, if the editor-swap happens before the\n        // removal from the working set.\n        var doc = DocumentManager.getOpenDocumentForPath(removedFile.fullPath);\n        if (doc) {\n            _destroyEditorIfUnneeded(doc);\n        }\n        // else, file was listed in working set but never shown in the editor - ignore\n    }\n\n    function _onWorkingSetRemoveList(event, removedFiles) {\n        removedFiles.forEach(function (removedFile) {\n            _onWorkingSetRemove(event, removedFile);\n        });\n    }\n\n    // Note: there are several paths that can lead to an editor getting destroyed\n    //  - file was in working set, but not in current editor; then closed (via working set \"X\" button)\n    //      --> handled by _onWorkingSetRemove()\n    //  - file was in current editor, but not in working set; then navigated away from\n    //      --> handled by _onCurrentDocumentChange()\n    //  - file was in current editor, but not in working set; then closed (via File > Close) (and thus\n    //    implicitly navigated away from)\n    //      --> handled by _onCurrentDocumentChange()\n    //  - file was in current editor AND in working set; then closed (via File > Close OR working set\n    //    \"X\" button) (and thus implicitly navigated away from)\n    //      --> handled by _onWorkingSetRemove() currently, but could be _onCurrentDocumentChange()\n    //      just as easily (depends on the order of events coming from DocumentManager)\n    \n    /**\n     * Designates the DOM node that will contain the currently active editor instance. EditorManager\n     * will own the content of this DOM node.\n     * @param {!jQueryObject} holder\n     */\n    function setEditorHolder(holder) {\n        if (_currentEditor) {\n            throw new Error(\"Cannot change editor area after an editor has already been created!\");\n        }\n        \n        _editorHolder = holder;\n    }\n    \n    /**\n     * Returns the currently focused inline widget.\n     * @returns {?{widget:!InlineTextEditor, editor:!Editor}}\n     */\n    function getFocusedInlineWidget() {\n        var result = null;\n        \n        if (_currentEditor) {\n            _currentEditor.getInlineWidgets().forEach(function (widget) {\n                if (widget instanceof InlineTextEditor) {\n                    widget.editors.forEach(function (editor) {\n                        if (editor.hasFocus()) {\n                            result = { widget: widget, editor: editor };\n                        }\n                    });\n                }\n            });\n        }\n        \n        return result;\n    }\n    \n    /**\n     * Returns the currently focused editor instance (full-sized OR inline editor).\n     * @returns {Editor}\n     */\n    function getFocusedEditor() {\n        if (_currentEditor) {\n            \n            // See if any inlines have focus\n            var focusedInline = getFocusedInlineWidget();\n            if (focusedInline) {\n                return focusedInline.editor;\n            }\n\n            // otherwise, see if full-sized editor has focus\n            if (_currentEditor.hasFocus()) {\n                return _currentEditor;\n            }\n        }\n        \n        return null;\n    }\n \n    /**\n     * Toggle Quick Edit command handler\n     * @return {!Promise} A promise resolved with true if an inline editor\n     *   is opened or false when closed. The promise is rejected if there\n     *   is no current editor or an inline editor is not created.\n     */\n    function _toggleQuickEdit() {\n        var result = new $.Deferred();\n        \n        if (_currentEditor) {\n            var inlineWidget = null,\n                focusedWidgetResult = getFocusedInlineWidget();\n            \n            if (focusedWidgetResult) {\n                inlineWidget = focusedWidgetResult.widget;\n            }\n            \n            if (inlineWidget) {\n                // an inline widget's editor has focus, so close it\n                PerfUtils.markStart(PerfUtils.INLINE_EDITOR_CLOSE);\n                inlineWidget.close();\n                PerfUtils.addMeasurement(PerfUtils.INLINE_EDITOR_CLOSE);\n        \n                // return a resolved promise to CommandManager\n                result.resolve(false);\n            } else {\n                // main editor has focus, so create an inline editor\n                _openInlineWidget(_currentEditor).done(function () {\n                    result.resolve(true);\n                }).fail(function () {\n                    result.reject();\n                });\n            }\n        } else {\n            // Can not open an inline editor without a host editor\n            result.reject();\n        }\n        \n        return result.promise();\n    }\n\n    CommandManager.register(Strings.CMD_TOGGLE_QUICK_EDIT, Commands.TOGGLE_QUICK_EDIT, _toggleQuickEdit);\n    \n    // Initialize: register listeners\n    $(DocumentManager).on(\"currentDocumentChange\", _onCurrentDocumentChange);\n    $(DocumentManager).on(\"workingSetRemove\", _onWorkingSetRemove);\n    $(DocumentManager).on(\"workingSetRemoveList\", _onWorkingSetRemoveList);\n\n    // Add this as a capture handler so we're guaranteed to run it before the editor does its own\n    // refresh on resize.\n    window.addEventListener(\"resize\", _updateEditorSize, true);\n    \n    // For unit tests\n    exports._openInlineWidget = _openInlineWidget;\n    \n    // Define public API\n    exports.setEditorHolder = setEditorHolder;\n    exports.getCurrentFullEditor = getCurrentFullEditor;\n    exports.createInlineEditorForDocument = createInlineEditorForDocument;\n    exports._createFullEditorForDocument = _createFullEditorForDocument;\n    exports._destroyEditorIfUnneeded = _destroyEditorIfUnneeded;\n    exports.focusEditor = focusEditor;\n    exports.getFocusedEditor = getFocusedEditor;\n    exports.getFocusedInlineWidget = getFocusedInlineWidget;\n    exports.resizeEditor = resizeEditor;\n    exports.registerInlineEditProvider = registerInlineEditProvider;\n    exports.getInlineEditors = getInlineEditors;\n    exports.closeInlineWidget = closeInlineWidget;\n    exports.mergeExtraKeys = mergeExtraKeys;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window, MouseEvent */\n\ndefine('command/Menus',['require','exports','module','command/Commands','command/KeyBindingManager','editor/EditorManager','strings','utils/StringUtils','command/CommandManager','widgets/PopUpManager'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var Commands                = require(\"command/Commands\"),\n        KeyBindingManager       = require(\"command/KeyBindingManager\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        Strings                 = require(\"strings\"),\n        StringUtils             = require(\"utils/StringUtils\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        PopUpManager            = require(\"widgets/PopUpManager\");\n\n    /**\n     * Brackets Application Menu Constants\n     * @enum {string}\n     */\n    var AppMenuBar = {\n        FILE_MENU:     \"file-menu\",\n        EDIT_MENU:     \"edit-menu\",\n        VIEW_MENU :    \"view-menu\",\n        NAVIGATE_MENU: \"navigate-menu\",\n        DEBUG_MENU:    \"debug-menu\"\n    };\n\n    /**\n     * Brackets Context Menu Constants\n     * @enum {string}\n     */\n    var ContextMenuIds = {\n        EDITOR_MENU:        \"editor-context-menu\",\n        INLINE_EDITOR_MENU: \"inline-editor-context-menu\",\n        PROJECT_MENU:       \"project-context-menu\"\n    };\n\n\n    /**\n     * Brackets Application Menu Section Constants\n     * It is preferred that plug-ins specify the location of new MenuItems\n     * in terms of a menu section rather than a specific MenuItem. This provides\n     * looser coupling to Bracket's internal MenuItems and makes menu organization\n     * more semantic. \n     * Use these constants as the \"relativeID\" parameter when calling addMenuItem() and\n     * specify a position of FIRST_IN_SECTION or LAST_IN_SECTION.\n     *\n     * Menu sections are denoted by dividers or the beginning/end of a menu\n     */\n    var MenuSection = {\n        // Menu Section                     Command ID to mark the section\n        FILE_OPEN_CLOSE_COMMANDS:           {sectionMarker: Commands.FILE_NEW},\n        FILE_SAVE_COMMANDS:                 {sectionMarker: Commands.FILE_SAVE},\n        FILE_LIVE:                          {sectionMarker: Commands.FILE_LIVE_FILE_PREVIEW},\n\n        EDIT_SELECTION_COMMANDS:            {sectionMarker: Commands.EDIT_SELECT_ALL},\n        EDIT_FIND:                          {sectionMarker: Commands.EDIT_FIND},\n        EDIT_REPLACE_COMMANDS:              {sectionMarker: Commands.EDIT_REPLACE},\n        EDIT_MODIFY_SELECTION:              {sectionMarker: Commands.EDIT_INDENT},\n\n        VIEW_HIDESHOW_COMMANDS:             {sectionMarker: Commands.VIEW_HIDE_SIDEBAR},\n        VIEW_FONTSIZE_COMMANDS:             {sectionMarker: Commands.VIEW_INCREASE_FONT_SIZE},\n\n        NAVIGATE_GOTO_COMMANDS:             {sectionMarker: Commands.NAVIGATE_QUICK_OPEN},\n        NAVIGATE_QUICK_EDIT_COMMANDS:       {sectionMarker: Commands.TOGGLE_QUICK_EDIT}\n    };\n\n    \n    /**\n      * Insertion position constants\n      * Used by addMenu(), addMenuItem(), and addSubMenu() to\n      * specify the relative position of a newly created menu object\n      * @enum {string}\n      */\n    var BEFORE =            \"before\";\n    var AFTER =             \"after\";\n    var FIRST =             \"first\";\n    var LAST =              \"last\";\n    var FIRST_IN_SECTION =  \"firstInSection\";\n    var LAST_IN_SECTION =   \"lastInSection\";\n\n    /**\n      * Other constants\n      */\n    var DIVIDER = \"---\";\n\n    /**\n     * Maps menuID's to Menu objects\n     * @type {Object.<string, Menu>}\n     */\n    var menuMap = {};\n\n    /**\n     * Maps contextMenuID's to ContextMenu objects\n     * @type {Object.<string, ContextMenu>}\n     */\n    var contextMenuMap = {};\n\n    /**\n     * Maps menuItemID's to MenuItem objects\n     * @type {Object.<string, MenuItem>}\n     */\n    var menuItemMap = {};\n    \n    /**\n     * Retrieves the Menu object for the corresponding id. \n     * @param {string} id\n     * @return {Menu}\n     */\n    function getMenu(id) {\n        return menuMap[id];\n    }\n\n    /**\n     * Retrieves the ContextMenu object for the corresponding id. \n     * @param {string} id\n     * @return {ContextMenu}\n     */\n    function getContextMenu(id) {\n        return contextMenuMap[id];\n    }\n\n    /**\n     * Retrieves the MenuItem object for the corresponding id. \n     * @param {string} id\n     * @return {MenuItem}\n     */\n    function getMenuItem(id) {\n        return menuItemMap[id];\n    }\n\n    function _getHTMLMenu(id) {\n        return $(\"#\" + StringUtils.jQueryIdEscape(id)).get(0);\n    }\n\n    function _getHTMLMenuItem(id) {\n        return $(\"#\" + StringUtils.jQueryIdEscape(id)).get(0);\n    }\n    \n    function _addKeyBindingToMenuItem($menuItem, key, displayKey) {\n        var $shortcut = $menuItem.find(\".menu-shortcut\");\n        \n        if ($shortcut.length === 0) {\n            $shortcut = $(\"<span class='menu-shortcut' />\");\n            $menuItem.append($shortcut);\n        }\n        \n        $shortcut.data(\"key\", key);\n        $shortcut.text(KeyBindingManager.formatKeyDescriptor(displayKey));\n    }\n    \n    function _addExistingKeyBinding(menuItem) {\n        var bindings = KeyBindingManager.getKeyBindings(menuItem.getCommand().getID()),\n            binding = null;\n        \n        if (bindings.length > 0) {\n            // add the latest key binding\n            binding = bindings[bindings.length - 1];\n            _addKeyBindingToMenuItem($(_getHTMLMenuItem(menuItem.id)), binding.key, binding.displayKey);\n        }\n        \n        return binding;\n    }\n    \n    /** NOT IMPLEMENTED\n     * Removes MenuItem\n     * \n     * TODO Question: for convenience should API provide a way to remove related\n     * keybindings and Command object?\n     */\n    // function removeMenuItem(id) {\n    //    NOT IMPLEMENTED\n    // }\n\n    var _menuDividerIDCount = 1;\n    function _getNextMenuItemDividerID() {\n        return \"brackets-menuDivider-\" + _menuDividerIDCount++;\n    }\n\n    // Help function for inserting elements into a list\n    function _insertInList($list, $element, position, $relativeElement) {\n        // Determine where to insert. Default is LAST.\n        var inserted = false;\n        if (position) {\n\n            // Adjust relative position for menu section positions since $relativeElement\n            // has already been resolved by _getRelativeMenuItem() to a menuItem\n            if (position === FIRST_IN_SECTION) {\n                position = BEFORE;\n            } else if (position === LAST_IN_SECTION) {\n                position = AFTER;\n            }\n\n            if (position === FIRST) {\n                $list.prepend($element);\n                inserted = true;\n            } else if ($relativeElement && $relativeElement.length > 0) {\n                if (position === AFTER) {\n                    $relativeElement.after($element);\n                    inserted = true;\n                } else if (position === BEFORE) {\n                    $relativeElement.before($element);\n                    inserted = true;\n                }\n            }\n        }\n\n        // Default to LAST\n        if (!inserted) {\n            $list.append($element);\n        }\n    }\n\n    /**\n     * @constructor\n     * @private\n     *\n     * MenuItem represents a single menu item that executes a Command or a menu divider. MenuItems\n     * may have a sub-menu. A MenuItem may correspond to an HTML-based\n     * menu item or a native menu item if Brackets is running in a native application shell\n     *\n     * Since MenuItems may have a native implementation clients should create MenuItems through \n     * addMenuItem() and should NOT construct a MenuItem object directly. \n     * Clients should also not access HTML content of a menu directly and instead use\n     * the MenuItem API to query and modify menus items.\n     *\n     * MenuItems are views on to Command objects so modify the underlying Command to modify the\n     * name, enabled, and checked state of a MenuItem. The MenuItem will update automatically\n     *\n     * @param {string} id\n     * @param {string|Command} command - the Command this MenuItem will reflect.\n     *                                   Use DIVIDER to specify a menu divider\n     */\n    function MenuItem(id, command) {\n        this.id = id;\n        this.isDivider = (command === DIVIDER);\n\n        if (!this.isDivider) {\n            // Bind event handlers\n            this._enabledChanged = this._enabledChanged.bind(this);\n            this._checkedChanged = this._checkedChanged.bind(this);\n            this._nameChanged = this._nameChanged.bind(this);\n            this._keyBindingAdded = this._keyBindingAdded.bind(this);\n            this._keyBindingRemoved = this._keyBindingRemoved.bind(this);\n\n            this._command = command;\n            $(this._command)\n                .on(\"enabledStateChange\", this._enabledChanged)\n                .on(\"checkedStateChange\", this._checkedChanged)\n                .on(\"nameChange\", this._nameChanged)\n                .on(\"keyBindingAdded\", this._keyBindingAdded)\n                .on(\"keyBindingRemoved\", this._keyBindingRemoved);\n        }\n    }\n\n    /**\n     * @constructor\n     * @private\n     *\n     * Menu represents a top-level menu in the menu bar. A Menu may correspond to an HTML-based\n     * menu or a native menu if Brackets is running in a native application shell. \n     * \n     * Since menus may have a native implementation clients should create Menus through \n     * addMenu() and should NOT construct a Menu object directly. \n     * Clients should also not access HTML content of a menu directly and instead use\n     * the Menu API to query and modify menus.\n     *\n     */\n    function Menu(id) {\n        this.id = id;\n    }\n\n    Menu.prototype._getMenuItemId = function (commandId) {\n        return (this.id + \"-\" + commandId);\n    };\n\n    /**\n     * Determine MenuItem in this Menu, that has the specified command\n     *\n     * @param {Command} command - the command to search for.\n     * @return {?HTMLLIElement} menu item list element\n     */\n    Menu.prototype._getMenuItemForCommand = function (command) {\n        if (!command) {\n            return null;\n        }\n        var foundMenuItem = menuItemMap[this._getMenuItemId(command.getID())];\n        if (!foundMenuItem) {\n            return null;\n        }\n        return $(_getHTMLMenuItem(foundMenuItem.id)).closest(\"li\");\n    };\n\n    /**\n     * Determine relative MenuItem\n     *\n     * @param {?string} relativeID - id of command (future: sub-menu).\n     * @param {?string} position - only needed when relativeID is a MenuSection\n     * @return {?HTMLLIElement} menu item list element\n     */\n    Menu.prototype._getRelativeMenuItem = function (relativeID, position) {\n        var $relativeElement,\n            key,\n            menuItem,\n            map,\n            foundMenuItem;\n        \n        if (relativeID) {\n            if (position === FIRST_IN_SECTION || position === LAST_IN_SECTION) {\n                if (!relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.log(\"Bad Parameter in _getRelativeMenuItem(): relativeID must be a MenuSection when position refers to a menu section\");\n                    return null;\n                }\n\n                // Determine the $relativeElement by traversing the sibling list and\n                // stop at the first divider found\n                // TODO: simplify using nextUntil()/prevUntil()\n                var $sectionMarker = this._getMenuItemForCommand(CommandManager.get(relativeID.sectionMarker));\n                if (!$sectionMarker) {\n                    console.log(\"_getRelativeMenuItem(): MenuSection \" + relativeID.sectionMarker +\n                                \" not found in Menu \" + this.id);\n                    return null;\n                }\n                var $listElem = $sectionMarker;\n                $relativeElement = $listElem;\n                while (true) {\n                    $listElem = (position === FIRST_IN_SECTION ? $listElem.prev() : $listElem.next());\n                    if ($listElem.length === 0) {\n                        break;\n                    } else if ($listElem.find(\".divider\").length > 0) {\n                        break;\n                    } else {\n                        $relativeElement = $listElem;\n                    }\n                }\n                \n            } else {\n                if (relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.log(\"Bad Parameter in _getRelativeMenuItem(): if relativeID is a MenuSection, position must be FIRST_IN_SECTION or LAST_IN_SECTION\");\n                    return null;\n                }\n                \n                // handle FIRST, LAST, BEFORE, & AFTER\n                var command = CommandManager.get(relativeID);\n                if (command) {\n                    // Lookup Command for this Command id\n                    // Find MenuItem that has this command\n                    $relativeElement = this._getMenuItemForCommand(command);\n                }\n                if (!$relativeElement) {\n                    console.log(\"_getRelativeMenuItem(): MenuItem with Command id \" + relativeID +\n                                \" not found in Menu \" + this.id);\n                    return null;\n                }\n            }\n            \n            return $relativeElement;\n            \n        } else if (position && position !== FIRST && position !== LAST) {\n            console.log(\"Bad Parameter in _getRelativeMenuItem(): relative position specified with no relativeID\");\n            return null;\n        }\n        \n        return $relativeElement;\n    };\n    \n    /**\n     * Adds a new menu item with the specified id and display text. The insertion position is\n     * specified via the relativeID and position arguments which describe a position \n     * relative to another MenuItem or MenuGroup. It is preferred that plug-ins \n     * insert new  MenuItems relative to a menu section rather than a specific \n     * MenuItem (see Menu Section Constants).\n     *\n     * TODO: Sub-menus are not yet supported, but when they are implemented this API will\n     * allow adding new MenuItems to sub-menus as well.\n     *\n     * Note, keyBindings are bound to Command objects not MenuItems. The provided keyBindings\n     *      will be bound to the supplied Command object rather than the MenuItem.\n     * \n     * @param {!string | Command} command - the command the menu will execute.\n     *      Pass Menus.DIVIDER for a menu divider, or just call addMenuDivider() instead.\n     * @param {?string | Array.<{key: string, platform: string}>}  keyBindings - register one\n     *      one or more key bindings to associate with the supplied command.\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants). \n     * @param {?string} relativeID - id of command or menu section (future: sub-menu) that \n     *      the new menuItem will be positioned relative to. Required for all position constants\n     *      except FIRST and LAST.\n     *\n     * @return {MenuItem} the newly created MenuItem\n     */\n    Menu.prototype.addMenuItem = function (command, keyBindings, position, relativeID) {\n        var id,\n            $menuItem,\n            $link,\n            menuItem,\n            name,\n            commandID;\n\n        if (!command) {\n            throw new Error(\"addMenuItem(): missing required parameters: command\");\n        }\n\n        if (typeof (command) === \"string\") {\n            if (command === DIVIDER) {\n                name = DIVIDER;\n                commandID = _getNextMenuItemDividerID();\n            } else {\n                commandID = command;\n                command = CommandManager.get(commandID);\n                if (!command) {\n                    throw new Error(\"addMenuItem(): commandID not found: \" + commandID);\n                }\n                name = command.getName();\n            }\n        } else {\n            commandID = command.getID();\n        }\n\n        // Internal id is the a composite of the parent menu id and the command id.\n        id = this._getMenuItemId(commandID);\n        \n        if (menuItemMap[id]) {\n            console.log(\"MenuItem added with same id of existing MenuItem: \" + id);\n            return null;\n        }\n\n        // create MenuItem\n        menuItem = new MenuItem(id, command);\n        menuItemMap[id] = menuItem;\n\n        // create MenuItem DOM\n        if (name === DIVIDER) {\n            $menuItem = $(\"<li><hr class='divider' /></li>\");\n        } else {\n            // Create the HTML Menu\n            $menuItem = $(\"<li><a href='#' id='\" + id + \"'> <span class='menu-name'></span></a></li>\");\n\n            $menuItem.on(\"click\", function () {\n                menuItem._command.execute();\n            });\n        }\n\n        // Insert menu item\n        var $relativeElement = this._getRelativeMenuItem(relativeID, position);\n        _insertInList($(\"li#\" + StringUtils.jQueryIdEscape(this.id) + \" > ul.dropdown-menu\"),\n                      $menuItem, position, $relativeElement);\n\n        // Initialize MenuItem state\n        if (!menuItem.isDivider) {\n            if (keyBindings) {\n                // Add key bindings. The MenuItem listens to the Command object to update MenuItem DOM with shortcuts.\n                if (!Array.isArray(keyBindings)) {\n                    keyBindings = [keyBindings];\n                }\n                \n                // Note that keyBindings passed during MenuItem creation take precedent over any existing key bindings\n                KeyBindingManager.addBinding(commandID, keyBindings);\n            } else {\n                // Look for existing key bindings\n                _addExistingKeyBinding(menuItem, commandID);\n            }\n\n            menuItem._checkedChanged();\n            menuItem._enabledChanged();\n            menuItem._nameChanged();\n        }\n\n        return menuItem;\n    };\n\n    /**\n     * Inserts divider item in menu.\n     * @param {?string} position - constant defining the position of new the divider relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants). \n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new \n     *      divider will be positioned relative to. Required for all position constants\n     *      except FIRST and LAST\n     * \n     * @return {MenuItem} the newly created divider\n     */\n    Menu.prototype.addMenuDivider = function (position, relativeID) {\n        return this.addMenuItem(DIVIDER, \"\", position, relativeID);\n    };\n\n    /**\n     * NOT IMPLEMENTED\n     * Alternative JSON based API to addMenuItem()\n     * \n     * All properties are required unless noted as optional.\n     *\n     * @param { Array.<{\n     *              id:         string,\n     *              command:    string | Command,\n     *              ?bindings:   string | Array.<{key: string, platform: string}>,\n     *          }>} jsonStr\n     *        }\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants). \n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new \n     *      menuItem will be positioned relative to. Required when position is \n     *      AFTER or BEFORE, ignored when position is FIRST or LAST.\n     *\n     * @return {MenuItem} the newly created MenuItem\n     */\n    // Menu.prototype.createMenuItemsFromJSON = function (jsonStr, position, relativeID) {\n    //     NOT IMPLEMENTED\n    // };\n\n\n    /**\n     * NOT IMPLEMENTED\n     * @param {!string} text displayed in menu item\n     * @param {!string} id\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants) \n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new \n     *      menuItem will be positioned relative to. Required when position is \n     *      AFTER or BEFORE, ignored when position is FIRST or LAST.\n     * \n     * @return {MenuItem} newly created menuItem for sub-menu\n     */\n    // MenuItem.prototype.createSubMenu = function (text, id, position, relativeID) {\n    //     NOT IMPLEMENTED\n    // };\n\n    /**\n     * Gets the Command associated with a MenuItem\n     * @return {Command}\n     */\n    MenuItem.prototype.getCommand = function () {\n        return this._command;\n    };\n\n    /**\n     * NOT IMPLEMENTED\n     * Returns the parent MenuItem if the menu item is a sub-menu, returns null otherwise.\n     * @return {MenuItem}\n     */\n    // MenuItem.prototype.getParentMenuItem = function () {\n    //     NOT IMPLEMENTED;\n    // };\n\n    /**\n     * Returns the parent Menu for this MenuItem\n     * @return {Menu} \n     */\n    MenuItem.prototype.getParentMenu = function () {\n        var parent = $(_getHTMLMenuItem(this.id)).parents(\".dropdown\").get(0);\n        if (!parent) {\n            return null;\n        }\n\n        return getMenu(parent.id);\n    };\n    \n    /**\n     * Synchronizes MenuItem checked state with underlying Command checked state\n     */\n    MenuItem.prototype._checkedChanged = function () {\n        var checked = this._command.getChecked();\n        // Note, checked can also be undefined, so we explicitly check\n        // for truthiness and don't use toggleClass().\n        if (checked) {\n            $(_getHTMLMenuItem(this.id)).addClass(\"checked\");\n        } else {\n            $(_getHTMLMenuItem(this.id)).removeClass(\"checked\");\n        }\n    };\n\n    /**\n     * Synchronizes MenuItem enabled state with underlying Command enabled state\n     */\n    MenuItem.prototype._enabledChanged = function () {\n        $(_getHTMLMenuItem(this.id)).toggleClass(\"disabled\", !this._command.getEnabled());\n    };\n\n    /**\n     * Synchronizes MenuItem name with underlying Command name\n     */\n    MenuItem.prototype._nameChanged = function () {\n        $(_getHTMLMenuItem(this.id)).find(\".menu-name\").text(this._command.getName());\n    };\n    \n    /**\n     * @private\n     * Updates MenuItem DOM with a keyboard shortcut label\n     */\n    MenuItem.prototype._keyBindingAdded = function (event, keyBinding) {\n        _addKeyBindingToMenuItem($(_getHTMLMenuItem(this.id)), keyBinding.key, keyBinding.displayKey);\n    };\n    \n    /**\n     * @private\n     * Updates MenuItem DOM to remove keyboard shortcut label\n     */\n    MenuItem.prototype._keyBindingRemoved = function (event, keyBinding) {\n        var $shortcut = $(_getHTMLMenuItem(this.id)).find(\".menu-shortcut\");\n        \n        if ($shortcut.length > 0 && $shortcut.data(\"key\") === keyBinding.key) {\n            // check for any other bindings\n            if (_addExistingKeyBinding(this) === null) {\n                $shortcut.empty();\n            }\n        }\n    };\n\n    /**\n     * Closes all menus that are open\n     */\n    function closeAll() {\n        $(\".dropdown\").removeClass(\"open\");\n    }\n    \n    /**\n     * Adds a top-level menu to the application menu bar which may be native or HTML-based.\n     *\n     * @param {!string} name - display text for menu \n     * @param {!string} id - unique identifier for a menu.\n     *      Core Menus in Brackets use a simple  title as an id, for example \"file-menu\".\n     *      Extensions should use the following format: \"author.myextension.mymenuname\". \n     * @param {?string} position - constant defining the position of new the Menu relative\n     *  to other Menus. Default is LAST (see Insertion position constants).\n     *      \n     * @param {?string} relativeID - id of Menu the new Menu will be positioned relative to. Required\n     *      when position is AFTER or BEFORE, ignored when position is FIRST or LAST\n     * \n     * @return {?Menu} the newly created Menu\n     */\n    function addMenu(name, id, position, relativeID) {\n        name = StringUtils.htmlEscape(name);\n        var $menubar = $(\"#main-toolbar .nav\"),\n            menu;\n\n        if (!name || !id) {\n            throw new Error(\"call to addMenu() is missing required parameters\");\n        }\n        \n        // Guard against duplicate menu ids\n        if (menuMap[id]) {\n            console.log(\"Menu added with same name and id of existing Menu: \" + id);\n            return null;\n        }\n\n        menu = new Menu(id);\n        menuMap[id] = menu;\n\n        var $toggle = $(\"<a href='#' class='dropdown-toggle'>\" + name + \"</a>\"),\n            $popUp = $(\"<ul class='dropdown-menu'></ul>\"),\n            $newMenu = $(\"<li class='dropdown' id='\" + id + \"'></li>\").append($toggle).append($popUp);\n\n        // Insert menu\n        var $relativeElement = relativeID && $(_getHTMLMenu(relativeID));\n        _insertInList($menubar, $newMenu, position, $relativeElement);\n        \n        // Install ESC key handling\n        PopUpManager.addPopUp($popUp, closeAll, false);\n\n        // todo error handling\n\n        return menu;\n    }\n\n\n    /**\n     * @constructor\n     * @extends {Menu}\n     *\n     * Represents a context menu that can open at a specific location in the UI. \n     *\n     * Clients should not create this object directly and should instead use registerContextMenu()\n     * to create new ContextMenu objects.\n     *\n     * Context menus in brackets may be HTML-based or native so clients should not reach into\n     * the HTML and should instead manipulate ContextMenus through the API.\n     *\n     * Events:\n     *      beforeContextMenuOpen\n     *      contextMenuClose\n     *\n     */\n    function ContextMenu(id) {\n        this.id = id;\n        this.menu = new Menu(id);\n\n        var $newMenu = $(\"<li class='dropdown context-menu' id='\" + StringUtils.jQueryIdEscape(id) + \"'></li>\"),\n            $popUp = $(\"<ul class='dropdown-menu'></ul>\"),\n            $toggle = $(\"<a href='#' class='dropdown-toggle'></a>\").hide();\n\n        // assemble the menu fragments\n        $newMenu.append($toggle).append($popUp);\n\n        // insert into DOM\n        $(\"#context-menu-bar > ul\").append($newMenu);\n        \n        var self = this;\n        PopUpManager.addPopUp($popUp,\n            function () {\n                self.close();\n            },\n            false);\n    }\n    ContextMenu.prototype = new Menu();\n    ContextMenu.prototype.constructor = ContextMenu;\n    ContextMenu.prototype.parentClass = Menu.prototype;\n\n\n    /**\n     * Displays the ContextMenu at the specified location and dispatches the \n     * \"beforeContextMenuOpen\" event.The menu location may be adjusted to prevent\n     * clipping by the browser window. All other menus and ContextMenus will be closed\n     * bofore a new menu is shown.\n     *\n     * @param {MouseEvent | {pageX:number, pageY:number}} mouseOrLocation - pass a MouseEvent\n     *      to display the menu near the mouse or pass in an object with page x/y coordinates\n     *      for a specific location.\n     */\n    ContextMenu.prototype.open = function (mouseOrLocation) {\n\n        if (!mouseOrLocation || !mouseOrLocation.hasOwnProperty(\"pageX\") || !mouseOrLocation.hasOwnProperty(\"pageY\")) {\n            throw new Error(\"ContextMenu open(): missing required parameter\");\n        }\n\n        var $window = $(window),\n            escapedId = StringUtils.jQueryIdEscape(this.id),\n            $menuAnchor = $(\"#\" + escapedId),\n            $menuWindow = $(\"#\" + escapedId + \" > ul\"),\n            posTop  = mouseOrLocation.pageY,\n            posLeft = mouseOrLocation.pageX;\n\n        // only show context menu if it has menu items\n        if ($menuWindow.children().length <= 0) {\n            return;\n        }\n\n        $(this).triggerHandler(\"beforeContextMenuOpen\");\n\n        // close all other dropdowns\n        closeAll();\n\n        // adjust positioning so menu is not clipped off bottom or right\n        var bottomOverhang = posTop + 25 + $menuWindow.height() - $window.height();\n        if (bottomOverhang > 0) {\n            posTop = Math.max(0, posTop - bottomOverhang);\n        }\n        posTop -= 30;   // shift top for hidden parent element\n        posLeft += 5;\n\n        var rightOverhang = posLeft + $menuWindow.width() - $window.width();\n        if (rightOverhang > 0) {\n            posLeft = Math.max(0, posLeft - rightOverhang);\n        }\n\n        // open the context menu at final location\n        $menuAnchor.addClass(\"open\")\n                   .css({\"left\": posLeft, \"top\": posTop});\n    };\n\n    /**\n     * Closes the context menu and dispatches the \"contextMenuClose\" event.\n     */\n    ContextMenu.prototype.close = function () {\n        $(\"#\" + StringUtils.jQueryIdEscape(this.id)).removeClass(\"open\");\n\n        $(this).triggerHandler(\"contextMenuClose\");\n    };\n\n    /**\n     * Registers new context menu with Brackets. \n\n     * Extensions should generally use the predefined context menus built into Brackets. Use this \n     * API to add a new context menu to UI that is specific to an extension.\n     *\n     * After registering  a new context menu clients should:\n     *      - use addMenuItem() to add items to the context menu\n     *      - call open() to show the context menu. \n     *      For example:\n     *      $(\"#my_ID\").contextmenu(function (e) {\n     *          if (e.which === 3) {\n     *              my_cmenu.open(e);\n     *          }\n     *      });\n     *\n     * To make menu items be contextual to things like selection, listen for the \"beforeContextMenuOpen\"\n     * to make changes to Command objects before the context menu is shown. MenuItems are views of\n     * Commands, which control a MenuItem's name, enabled state, and checked state.\n     *\n     * @param {string} id - unique identifier for context menu.\n     *      Core context menus in Brackets use a simple title as an id.\n     *      Extensions should use the following format: \"author.myextension.mycontextmenu name\"\n     * @return {?ContextMenu} the newly created context menu\n     */\n    function registerContextMenu(id) {\n        if (!id) {\n            throw new Error(\"call to registerContextMenu() is missing required parameters\");\n        }\n        \n        // Guard against duplicate menu ids\n        if (contextMenuMap[id]) {\n            console.log(\"Context Menu added with same name and id of existing Context Menu: \" + id);\n            return null;\n        }\n\n        var cmenu = new ContextMenu(id);\n        contextMenuMap[id] = cmenu;\n        return cmenu;\n    }\n\n    /** NOT IMPLEMENTED\n     * Removes Menu\n     */\n    // function removeMenu(id) {\n    //     NOT IMPLEMENTED\n    // }\n\n\n    function init() {\n\n        /*\n         * File menu\n         */\n        var menu;\n        menu = addMenu(Strings.FILE_MENU, AppMenuBar.FILE_MENU);\n        menu.addMenuItem(Commands.FILE_NEW,                 \"Ctrl-N\");\n        menu.addMenuItem(Commands.FILE_OPEN,                \"Ctrl-O\");\n        menu.addMenuItem(Commands.FILE_OPEN_FOLDER);\n        menu.addMenuItem(Commands.FILE_CLOSE,               \"Ctrl-W\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_SAVE,                \"Ctrl-S\");\n        menu.addMenuItem(Commands.FILE_SAVE_ALL,            \"Ctrl-Alt-S\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW,   \"Ctrl-Alt-P\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_QUIT,                \"Ctrl-Q\");\n\n        /*\n         * Edit  menu\n         */\n        menu = addMenu(Strings.EDIT_MENU, AppMenuBar.EDIT_MENU);\n        menu.addMenuItem(Commands.EDIT_SELECT_ALL,          \"Ctrl-A\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_FIND,                \"Ctrl-F\");\n        menu.addMenuItem(Commands.EDIT_FIND_IN_FILES,       \"Ctrl-Shift-F\");\n        menu.addMenuItem(Commands.EDIT_FIND_NEXT,           [{key: \"F3\",     platform: \"win\"},\n                                                             {key: \"Cmd-G\", platform: \"mac\"}]);\n\n        menu.addMenuItem(Commands.EDIT_FIND_PREVIOUS,       [{key: \"Shift-F3\",      platform: \"win\"},\n                                                             {key:  \"Cmd-Shift-G\", platform: \"mac\"}]);\n\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_REPLACE,             [{key: \"Ctrl-H\",     platform: \"win\"},\n                                                             {key: \"Cmd-Alt-F\", platform: \"mac\"}]);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_INDENT,          [{key: \"Indent\", displayKey: \"Tab\"}]);\n        menu.addMenuItem(Commands.EDIT_UNINDENT,        [{key: \"Unindent\", displayKey: \"Shift-Tab\"}]);\n        menu.addMenuItem(Commands.EDIT_DUPLICATE,       \"Ctrl-D\");\n        menu.addMenuItem(Commands.EDIT_LINE_UP,         [{key: \"Ctrl-Shift-Up\", displayKey: \"Ctrl-Shift-\\u2191\",\n                                                          platform: \"win\"},\n                                                         {key:  \"Cmd-Ctrl-Up\", displayKey: \"Cmd-Ctrl-\\u2191\",\n                                                          platform: \"mac\"}]);\n        menu.addMenuItem(Commands.EDIT_LINE_DOWN,       [{key: \"Ctrl-Shift-Down\", displayKey: \"Ctrl-Shift-\\u2193\",\n                                                          platform: \"win\"},\n                                                         {key:  \"Cmd-Ctrl-Down\", displayKey: \"Cmd-Ctrl-\\u2193\",\n                                                          platform: \"mac\"}]);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_LINE_COMMENT,    \"Ctrl-/\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_USE_TAB_CHARS);\n\n        /*\n         * View menu\n         */\n        menu = addMenu(Strings.VIEW_MENU, AppMenuBar.VIEW_MENU);\n        menu.addMenuItem(Commands.VIEW_HIDE_SIDEBAR,        \"Ctrl-Shift-H\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.VIEW_INCREASE_FONT_SIZE, [{key: \"Ctrl-=\", displayKey: \"Ctrl-+\"}]);\n        menu.addMenuItem(Commands.VIEW_DECREASE_FONT_SIZE, [{key: \"Ctrl--\", displayKey: \"Ctrl-\\u2212\"}]);\n        menu.addMenuItem(Commands.VIEW_RESTORE_FONT_SIZE, \"Ctrl-0\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_JSLINT);\n\n        /*\n         * Navigate menu\n         */\n        menu = addMenu(Strings.NAVIGATE_MENU, AppMenuBar.NAVIGATE_MENU);\n        menu.addMenuItem(Commands.NAVIGATE_QUICK_OPEN,      \"Ctrl-Shift-O\");\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_LINE,       [{key: \"Ctrl-G\", platform: \"win\"},\n                                                             {key: \"Cmd-L\", platform: \"mac\"}]);\n\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_DEFINITION, \"Ctrl-T\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_QUICK_EDIT,        \"Ctrl-E\");\n        menu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH,    {key: \"Alt-Up\", displayKey: \"Alt-\\u2191\"});\n        menu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH,    {key: \"Alt-Down\", displayKey: \"Alt-\\u2193\"});\n\n        /*\n         * Debug menu\n         */\n        menu = addMenu(Strings.DEBUG_MENU, AppMenuBar.DEBUG_MENU);\n        menu.addMenuItem(Commands.DEBUG_SHOW_DEVELOPER_TOOLS, [{key: \"F12\",        platform: \"win\"},\n                                                               {key: \"Cmd-Opt-I\", platform: \"mac\"}]);\n        menu.addMenuItem(Commands.DEBUG_REFRESH_WINDOW, [{key: \"F5\",     platform: \"win\"},\n                                                         {key: \"Cmd-R\", platform:  \"mac\"}]);\n        menu.addMenuItem(Commands.DEBUG_NEW_BRACKETS_WINDOW);\n        menu.addMenuItem(Commands.DEBUG_SHOW_EXT_FOLDER);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.DEBUG_SWITCH_LANGUAGE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.DEBUG_RUN_UNIT_TESTS);\n        menu.addMenuItem(Commands.DEBUG_SHOW_PERF_DATA);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.CHECK_FOR_UPDATE);\n\n\n        /*\n         * Context Menus\n         */\n        var project_cmenu = registerContextMenu(ContextMenuIds.PROJECT_MENU);\n        project_cmenu.addMenuItem(Commands.FILE_NEW);\n\n        var editor_cmenu = registerContextMenu(ContextMenuIds.EDITOR_MENU);\n        editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);\n\n        var inline_editor_cmenu = registerContextMenu(ContextMenuIds.INLINE_EDITOR_MENU);\n        inline_editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        inline_editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);\n        inline_editor_cmenu.addMenuDivider();\n        inline_editor_cmenu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH);\n        inline_editor_cmenu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH);\n        \n        /**\n         * Context menu for code editors (both full-size and inline)\n         * Auto selects the word the user clicks if the click does not occur over\n         * an existing selection\n         */\n        $(\"#editor-holder\").on(\"contextmenu\", function (e) {\n            if ($(e.target).parents(\".CodeMirror-gutter\").length !== 0) {\n                return;\n            }\n            \n            // Note: on mousedown before this event, CodeMirror automatically checks mouse pos, and\n            // if not clicking on a selection moves the cursor to click location. When triggered\n            // from keyboard, no pre-processing occurs and the cursor/selection is left as is.\n            \n            var editor = EditorManager.getFocusedEditor(),\n                inlineWidget = EditorManager.getFocusedInlineWidget();\n            \n            if (editor) {\n                // If there's just an insertion point select the word token at the cursor pos so\n                // it's more clear what the context menu applies to.\n                if (!editor.hasSelection()) {\n                    editor.selectWordAt(editor.getCursorPos());\n                    \n                    // Prevent menu from overlapping text by moving it down a little\n                    // Temporarily backout this change for now to help mitigate issue #1111,\n                    // which only happens if mouse is not over context menu. Better fix\n                    // requires change to bootstrap, which is too risky for now.\n                    //e.pageY += 6;\n                }\n                \n                if (inlineWidget) {\n                    inline_editor_cmenu.open(e);\n                } else {\n                    editor_cmenu.open(e);\n                }\n            }\n        });\n\n        /**\n         * Context menu for folder tree & working set list\n         *\n         * TODO (#1069): change selection on right mousedown if not on something already selected\n         */\n        $(\"#projects\").on(\"contextmenu\", function (e) {\n            project_cmenu.open(e);\n        });\n\n        // Prevent the browser context menu since Brackets creates a custom context menu\n        $(window).contextmenu(function (e) {\n            e.preventDefault();\n        });\n        \n        /*\n         * General menu event processing\n         */\n        // Prevent clicks on top level menus and menu items from taking focus\n        $(window.document).on(\"mousedown\", \".dropdown\", function (e) {\n            e.preventDefault();\n        });\n\n        // Switch menus when the mouse enters an adjacent menu\n        // Only open the menu if another one has already been opened\n        // by clicking\n        $(window.document).on(\"mouseenter\", \"#main-toolbar .dropdown\", function (e) {\n            var open = $(this).siblings(\".open\");\n            if (open.length > 0) {\n                open.removeClass(\"open\");\n                $(this).addClass(\"open\");\n            }\n        });\n    }\n\n    // Define public API\n    exports.init = init;\n    exports.AppMenuBar = AppMenuBar;\n    exports.ContextMenuIds = ContextMenuIds;\n    exports.MenuSection = MenuSection;\n    exports.BEFORE = BEFORE;\n    exports.AFTER = AFTER;\n    exports.LAST = LAST;\n    exports.FIRST = FIRST;\n    exports.FIRST_IN_SECTION = FIRST_IN_SECTION;\n    exports.LAST_IN_SECTION = LAST_IN_SECTION;\n    exports.DIVIDER = DIVIDER;\n    exports.getMenu = getMenu;\n    exports.getMenuItem = getMenuItem;\n    exports.getContextMenu = getContextMenu;\n    exports.addMenu = addMenu;\n    exports.registerContextMenu = registerContextMenu;\n    exports.closeAll = closeAll;\n    exports.Menu = Menu;\n    exports.MenuItem = MenuItem;\n    exports.ContextMenu = ContextMenu;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * Responsible for coordinating file selection between views by permitting only one view\n * to show the current file selection at a time. Currently, only WorkingSetView and \n * ProjectManager can show file selection. In general the WorkingSetView takes higher\n * priority until the user selects a file in the ProjectManager.\n *\n * Events dispatched:\n * - documentSelectionFocusChange - indicates a document change has caused the focus to \n *   change between the working set and file tree.\n *\n * - fileViewFocusChange - indicates the selection focus has changed between the working\n *   set and the project tree, but the document selection has NOT changed\n *\n * Current file selection rules in views:\n * - select a file in WorkingSetView > select in WorkingSetView\n * - add a file to the WorkingSetView > select in WorkingSetView\n * - select a file in ProjectManager > select in ProjectManager\n * - open a file from places other than the WorkingSetView or ProjectManager > \n *       select file in WorkignSetView if its in the working set, otherwise select in ProjectManager\n */\n\ndefine('project/FileViewController',['require','exports','module','document/DocumentManager','command/CommandManager','editor/EditorManager','utils/PerfUtils','command/Commands'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Commands            = require(\"command/Commands\");\n\n    /** \n     * Tracks whether a \"currentDocumentChange\" notification occured due to a call to \n     * openAndSelectDocument.\n     * @see FileviewController.openAndSelectDocument\n     * @private \n     */\n    var _curDocChangedDueToMe = false;\n    var WORKING_SET_VIEW = \"WorkingSetView\";\n    var PROJECT_MANAGER = \"ProjectManager\";\n\n    /**\n     * @private\n     * @see FileViewController.getFileSelectionFocus()\n     */\n    var _fileSelectionFocus = PROJECT_MANAGER;\n    \n    /** \n     * Change the doc selection to the working set when ever a new file is added to the working set\n     */\n    $(DocumentManager).on(\"workingSetAdd\", function (event, addedFile) {\n        _fileSelectionFocus = WORKING_SET_VIEW;\n        $(exports).triggerHandler(\"documentSelectionFocusChange\");\n    });\n\n    /** \n      * Update the file selection focus when ever the current document changes\n      */\n    $(DocumentManager).on(\"currentDocumentChange\", function (event) {\n        var perfTimerName;\n        // The the cause of the doc change was not openAndSelectDocument, so pick the best fileSelectionFocus\n        if (!_curDocChangedDueToMe) {\n            var curDoc = DocumentManager.getCurrentDocument();\n            perfTimerName = PerfUtils.markStart(\"FileViewController._onCurrentDocumentChange():\\t\" + (!curDoc || curDoc.file.fullPath));\n            if (curDoc && DocumentManager.findInWorkingSet(curDoc.file.fullPath) !== -1) {\n                _fileSelectionFocus = WORKING_SET_VIEW;\n            } else {\n                _fileSelectionFocus = PROJECT_MANAGER;\n            }\n        }\n\n        $(exports).triggerHandler(\"documentSelectionFocusChange\");\n\n        if (!_curDocChangedDueToMe) {\n            PerfUtils.addMeasurement(perfTimerName);\n        }\n    });\n    \n    /** \n     * @private\n     * @returns {$.Promise}\n     */\n    function _selectCurrentDocument() {\n        // If fullPath corresonds to the current doc being viewed then opening the file won't\n        // trigger a currentDocumentChanged event, so we need to trigger a documentSelectionFocusChange \n        // in this case to signify the selection focus has changed even though the current document has not.\n        $(exports).triggerHandler(\"documentSelectionFocusChange\");\n        \n        // Ensure the editor has focus even though we didn't open a new file.\n        EditorManager.focusEditor();\n    }\n\n    /**\n     * Modifies the selection focus in the project side bar. A file can either be selected\n     * in the working set (the open files) or in the file tree, but not both.\n     * @param {String} fileSelectionFocus - either PROJECT_MANAGER or WORKING_SET_VIEW\n     */\n    function setFileViewFocus(fileSelectionFocus) {\n        if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {\n            throw new Error(\"Bad parameter passed to FileViewController.setFileViewFocus\");\n        }\n\n        _fileSelectionFocus = fileSelectionFocus;\n        $(exports).triggerHandler(\"fileViewFocusChange\");\n    }\n\n    /** \n     * Opens a document if it's not open and selects the file in the UI corresponding to\n     * fileSelectionFocus\n     * @param {!fullPath}\n     * @param {string} - must be either WORKING_SET_VIEW or PROJECT_MANAGER\n     * @returns {$.Promise}\n     */\n    function openAndSelectDocument(fullPath, fileSelectionFocus) {\n        var result;\n\n        if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {\n            throw new Error(\"Bad parameter passed to FileViewController.openAndSelectDocument\");\n        }\n\n        // Opening files are asynchronous and we want to know when this function caused a file\n        // to open so that _fileSelectionFocus is set appropriatly. _curDocChangedDueToMe is set here\n        // and checked in the currentDocumentChange handler\n        _curDocChangedDueToMe = true;\n\n        _fileSelectionFocus = fileSelectionFocus;\n\n        // If fullPath corresonds to the current doc being viewed then opening the file won't\n        // trigger a currentDocumentChanged event, so we need to trigger a documentSelectionFocusChange \n        // in this case to signify the selection focus has changed even though the current document has not.\n        var curDoc = DocumentManager.getCurrentDocument();\n        if (curDoc && curDoc.file.fullPath === fullPath) {\n            _selectCurrentDocument();\n            result = (new $.Deferred()).resolve().promise();\n        } else {\n            result = CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath});\n        }\n        \n        // clear after notification is done\n        result.always(function () {\n            _curDocChangedDueToMe = false;\n        });\n        \n        return result;\n    }\n\n    /** \n     * Opens the specified document if it's not already open, adds it to the working set,\n     * and selects it in the WorkingSetView\n     * @param {!fullPath}\n     * @param {?String} selectIn - specify either WORING_SET_VIEW or PROJECT_MANAGER.\n     *      Default is WORING_SET_VIEW.\n     * @return {!$.Promise}\n     */\n    function addToWorkingSetAndSelect(fullPath, selectIn) {\n        var result = new $.Deferred(),\n            promise = CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath});\n\n        // This properly handles sending the right nofications in cases where the document\n        // is already the current one. In that case we will want to notify with\n        // documentSelectionFocusChange so the views change their selection\n        promise.done(function (doc) {\n            // FILE_ADD_TO_WORKING_SET command sets the current document. Update the \n            // selection focus and trigger documentSelectionFocusChange event\n            _fileSelectionFocus = selectIn || WORKING_SET_VIEW;\n            _selectCurrentDocument();\n            \n            result.resolve(doc);\n        }).fail(function (err) {\n            result.reject(err);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * returns either WORKING_SET_VIEW or PROJECT_MANAGER\n     * @return {!String}\n     */\n    function getFileSelectionFocus() {\n        return _fileSelectionFocus;\n    }\n\n\n\n    // Define public API\n    exports.getFileSelectionFocus = getFileSelectionFocus;\n    exports.openAndSelectDocument = openAndSelectDocument;\n    exports.addToWorkingSetAndSelect = addToWorkingSetAndSelect;\n    exports.setFileViewFocus = setFileViewFocus;\n    exports.WORKING_SET_VIEW = WORKING_SET_VIEW;\n    exports.PROJECT_MANAGER = PROJECT_MANAGER;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, FileError, window */\n\n/**\n * ProjectManager is the model for the set of currently open project. It is responsible for\n * creating and updating the project tree when projects are opened and when changes occur to\n * the file tree.\n *\n * This module dispatches these events:\n *    - beforeProjectClose -- before _projectRoot changes\n *    - projectOpen        -- after  _projectRoot changes\n *\n * These are jQuery events, so to listen for them you do something like this:\n *    $(ProjectManager).on(\"eventname\", handler);\n */\ndefine('project/ProjectManager',['require','exports','module','thirdparty/jstree_pre1.0_fix_1/jquery.jstree','file/NativeFileSystem','preferences/PreferencesManager','document/DocumentManager','command/CommandManager','command/Commands','widgets/Dialogs','command/Menus','utils/StringUtils','strings','project/FileViewController','utils/PerfUtils','utils/ViewUtils','file/FileUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent non-module scripts\n    require(\"thirdparty/jstree_pre1.0_fix_1/jquery.jstree\");\n\n    // Load dependent modules\n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Menus               = require(\"command/Menus\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Strings             = require(\"strings\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        FileUtils           = require(\"file/FileUtils\");\n    \n    /**\n     * @private\n     * Reference to the tree control container div. Initialized by\n     * htmlContentLoadComplete handler\n     * @type {jQueryObject}\n     */\n    var $projectTreeContainer;\n    \n    /**\n     * @private\n     * Reference to the tree control\n     * @type {jQueryObject}\n     */\n    var _projectTree = null;\n    \n    /**\n     * @private\n     * Reference to previous selected jstree leaf node when ProjectManager had\n     * selection focus from FileViewController.\n     * @type {DOMElement}\n     */\n    var _lastSelected = null;\n    \n    /**\n     * @private\n     * Internal flag to suppress firing of selectionChanged event.\n     * @type {boolean}\n     */\n    var _suppressSelectionChange = false;\n    \n    /**\n     * @private\n     * Reference to the tree control UL element\n     * @type {DOMElement}\n     */\n    var $projectTreeList;\n    \n    /**\n     * @private\n     * @see getProjectRoot()\n     */\n    var _projectRoot = null;\n\n    /**\n     * Unique PreferencesManager clientID\n     */\n    var PREFERENCES_CLIENT_ID = \"com.adobe.brackets.ProjectManager\";\n    \n    /**\n     * @private\n     * @type {PreferenceStorage}\n     */\n    var _prefs = null;\n\n    /**\n     * @private\n     * Used to initialize jstree state\n     */\n    var _projectInitialLoad = {\n        previous        : [],   /* array of arrays containing full paths to open at each depth of the tree */\n        id              : 0,    /* incrementing id */\n        fullPathToIdMap : {}    /* mapping of fullPath to tree node id attr */\n    };\n    \n    /**\n     * @private\n     */\n    function _hasFileSelectionFocus() {\n        return FileViewController.getFileSelectionFocus() === FileViewController.PROJECT_MANAGER;\n    }\n    \n    /**\n     * @private\n     */\n    function _redraw(selectionChanged, reveal) {\n        reveal = (reveal === undefined) ? true : reveal;\n        \n        // redraw selection\n        if ($projectTreeList) {\n            if (selectionChanged && !_suppressSelectionChange) {\n                $projectTreeList.triggerHandler(\"selectionChanged\", reveal);\n            }\n\n            // reposition the selection triangle\n            $projectTreeContainer.triggerHandler(\"scroll\");\n            \n            // in-lieu of resize events, manually trigger contentChanged for every\n            // FileViewController focus change. This event triggers scroll shadows\n            // on the jstree to update. documentSelectionFocusChange fires when\n            // a new file is added and removed (causing a new selection) from the working set\n            _projectTree.triggerHandler(\"contentChanged\");\n        }\n    }\n    \n    /**\n     * Returns the FileEntry or DirectoryEntry corresponding to the selected item, or null\n     * if no item is selected.\n     *\n     * @return {?Entry}\n     */\n    function getSelectedItem() {\n        var selected = _projectTree.jstree(\"get_selected\");\n        if (selected) {\n            return selected.data(\"entry\");\n        }\n        return null;\n    }\n\n    function _fileViewFocusChange() {\n        _redraw(true);\n    }\n    \n    function _documentSelectionFocusChange() {\n        var curDoc = DocumentManager.getCurrentDocument();\n        if (curDoc && _hasFileSelectionFocus()) {\n            $(\"#project-files-container li\").is(function (index) {\n                var entry = $(this).data(\"entry\");\n                if (entry && entry.fullPath === curDoc.file.fullPath && !_projectTree.jstree(\"is_selected\", $(this))) {\n                    //we don't want to trigger another selection change event, so manually deselect\n                    //and select without sending out notifications\n                    _projectTree.jstree(\"deselect_all\");\n                    _projectTree.jstree(\"select_node\", $(this), false);\n                    return true;\n                }\n                return false;\n            });\n        } else if (_projectTree !== null) {\n            _projectTree.jstree(\"deselect_all\");\n            _lastSelected = null;\n        }\n        \n        _redraw(true);\n    }\n\n    /**\n     * Returns the root folder of the currently loaded project, or null if no project is open (during\n     * startup, or running outside of app shell).\n     * @return {DirectoryEntry}\n     */\n    function getProjectRoot() {\n        return _projectRoot;\n    }\n    \n    /**\n     * Returns true if absPath lies within the project, false otherwise.\n     * Does not support paths containing \"..\"\n     */\n    function isWithinProject(absPath) {\n        return (_projectRoot && absPath.indexOf(_projectRoot.fullPath) === 0);\n    }\n    /**\n     * If absPath lies within the project, returns a project-relative path. Else returns absPath\n     * unmodified.\n     * Does not support paths containing \"..\"\n     */\n    function makeProjectRelativeIfPossible(absPath) {\n        if (isWithinProject(absPath)) {\n            return absPath.slice(_projectRoot.fullPath.length);\n        }\n        return absPath;\n    }\n\n    /**\n     * Initial project path is stored in prefs, which defaults to brackets/src\n     */\n    function getInitialProjectPath() {\n        return _prefs.getValue(\"projectPath\");\n    }\n\n    /**\n     * @private\n     * Get prefs tree state lookup key for given project path.\n     */\n    function _getTreeStateKey(path) {\n        // generate unique tree state key for this project path\n        var key = \"projectTreeState_\" + path;\n\n        // normalize to always have slash at end\n        if (key[key.length - 1] !== \"/\") {\n            key += \"/\";\n        }\n        return key;\n    }\n\n    /**\n     * @private\n     * Save ProjectManager project path and tree state.\n     */\n    function _savePreferences() {\n        \n        // save the current project\n        _prefs.setValue(\"projectPath\", _projectRoot.fullPath);\n\n        // save jstree state\n        var openNodes = [],\n            projectPathLength = _projectRoot.fullPath.length,\n            entry,\n            fullPath,\n            shortPath,\n            depth;\n\n        // Query open nodes by class selector\n        $(\".jstree-open:visible\").each(function (index) {\n            entry = $(this).data(\"entry\");\n\n            if (entry.fullPath) {\n                fullPath = entry.fullPath;\n\n                // Truncate project path prefix, remove the trailing slash\n                shortPath = fullPath.slice(projectPathLength, -1);\n\n                // Determine depth of the node by counting path separators.\n                // Children at the root have depth of zero\n                depth = shortPath.split(\"/\").length - 1;\n\n                // Map tree depth to list of open nodes\n                if (openNodes[depth] === undefined) {\n                    openNodes[depth] = [];\n                }\n\n                openNodes[depth].push(fullPath);\n            }\n        });\n\n        // Store the open nodes by their full path and persist to storage\n        _prefs.setValue(_getTreeStateKey(_projectRoot.fullPath), openNodes);\n    }\n    \n    /**\n     * @private\n     */\n    function _forceSelection(current, target) {\n        // select_node will force the target to be revealed. Instead,\n        // keep the scroller position stable.\n        var savedScrollTop = $projectTreeContainer.get(0).scrollTop;\n        \n        // suppress selectionChanged event from firing by jstree select_node\n        _suppressSelectionChange = true;\n        _projectTree.jstree(\"deselect_node\", current);\n        _projectTree.jstree(\"select_node\", target, false);\n        _suppressSelectionChange = false;\n        \n        $projectTreeContainer.get(0).scrollTop = savedScrollTop;\n        \n        _redraw(true, false);\n    }\n\n    /**\n     * @private\n     * Given an input to jsTree's json_data.data setting, display the data in the file tree UI\n     * (replacing any existing file tree that was previously displayed). This input could be\n     * raw JSON data, or it could be a dataprovider function. See jsTree docs for details:\n     * http://www.jstree.com/documentation/json_data\n     */\n    function _renderTree(treeDataProvider) {\n        var result = new $.Deferred(),\n            suppressToggleOpen = false;\n\n        // Instantiate tree widget\n        // (jsTree is smart enough to replace the old tree if there's already one there)\n        $projectTreeContainer.hide();\n        _projectTree = $projectTreeContainer\n            .jstree(\n                {\n                    plugins : [\"ui\", \"themes\", \"json_data\", \"crrm\", \"sort\"],\n                    json_data : { data: treeDataProvider, correct_state: false },\n                    core : { animation: 0 },\n                    themes : { theme: \"brackets\", url: \"styles/jsTreeTheme.css\", dots: false, icons: false },\n                        //(note: our actual jsTree theme CSS lives in brackets.less; we specify an empty .css\n                        // file because jsTree insists on loading one itself)\n                    strings : { loading : \"Loading ...\", new_node : \"New node\" },\n                    sort :  function (a, b) {\n                        if (brackets.platform === \"win\") {\n                            // Windows: prepend folder names with a '0' and file names with a '1' so folders are listed first\n                            var a1 = ($(a).hasClass(\"jstree-leaf\") ? \"1\" : \"0\") + this.get_text(a).toLowerCase(),\n                                b1 = ($(b).hasClass(\"jstree-leaf\") ? \"1\" : \"0\") + this.get_text(b).toLowerCase();\n                            return (a1 > b1) ? 1 : -1;\n                        } else {\n                            return this.get_text(a).toLowerCase() > this.get_text(b).toLowerCase() ? 1 : -1;\n                        }\n                    }\n                }\n            )\n            .bind(\n                \"before.jstree\",\n                function (event, data) {\n                    if (data.func === \"toggle_node\") {\n                        // jstree will automaticaly select parent node when the parent is closed\n                        // and any descendant is selected. Prevent the select_node handler from\n                        // immediately toggling open again in this case.\n                        suppressToggleOpen = _projectTree.jstree(\"is_open\", data.args[0]);\n                    }\n                }\n            )\n            .bind(\n                \"select_node.jstree\",\n                function (event, data) {\n                    var entry = data.rslt.obj.data(\"entry\");\n                    if (entry.isFile) {\n                        var openResult = FileViewController.openAndSelectDocument(entry.fullPath, FileViewController.PROJECT_MANAGER);\n                    \n                        openResult.done(function () {\n                            // update when tree display state changes\n                            _redraw(true);\n                            _lastSelected = data.rslt.obj;\n                        }).fail(function () {\n                            if (_lastSelected) {\n                                // revert this new selection and restore previous selection\n                                _forceSelection(data.rslt.obj, _lastSelected);\n                            } else {\n                                _projectTree.jstree(\"deselect_all\");\n                                _lastSelected = null;\n                            }\n                        });\n                    } else {\n                        FileViewController.setFileViewFocus(FileViewController.PROJECT_MANAGER);\n                        // show selection marker on folders\n                        _redraw(true);\n                        \n                        // toggle folder open/closed\n                        // suppress if this selection was triggered by clicking the disclousre triangle\n                        if (!suppressToggleOpen) {\n                            _projectTree.jstree(\"toggle_node\", data.rslt.obj);\n                        }\n                    }\n                    \n                    suppressToggleOpen = false;\n                }\n            )\n            .bind(\n                \"reopen.jstree\",\n                function (event, data) {\n                    // This handler fires for the initial load and subsequent\n                    // reload_nodes events. For each depth level of the tree, we open\n                    // the saved nodes by a fullPath lookup.\n                    if (_projectInitialLoad.previous.length > 0) {\n                        // load previously open nodes by increasing depth\n                        var toOpenPaths = _projectInitialLoad.previous.shift(),\n                            toOpenIds   = [],\n                            node        = null;\n        \n                        // use path to lookup ID\n                        $.each(toOpenPaths, function (index, value) {\n                            node = _projectInitialLoad.fullPathToIdMap[value];\n                            \n                            if (node) {\n                                toOpenIds.push(node);\n                            }\n                        });\n        \n                        // specify nodes to open and load\n                        data.inst.data.core.to_open = toOpenIds;\n                        _projectTree.jstree(\"reload_nodes\", false);\n                    }\n                    if (_projectInitialLoad.previous.length === 0) {\n                        // resolve after all paths are opened\n                        result.resolve();\n                    }\n                }\n            )\n            .bind(\n                \"scroll.jstree\",\n                function (e) {\n                    // close all dropdowns on scroll\n                    Menus.closeAll();\n                }\n            )\n            .bind(\n                \"loaded.jstree open_node.jstree close_node.jstree\",\n                function (event, data) {\n                    if (event.type === \"open_node\") {\n                        // select the current document if it becomes visible when this folder is opened\n                        var curDoc = DocumentManager.getCurrentDocument();\n                        \n                        if (_hasFileSelectionFocus() && curDoc) {\n                            var entry = data.rslt.obj.data(\"entry\");\n                            \n                            if (curDoc.file.fullPath.indexOf(entry.fullPath) === 0) {\n                                _forceSelection(data.rslt.obj, _lastSelected);\n                            } else {\n                                _redraw(true, false);\n                            }\n                        }\n                    } else if (event.type === \"close_node\") {\n                        // always update selection marker position when collapsing a node\n                        _redraw(true, false);\n                    } else {\n                        _redraw(false);\n                    }\n                    \n                    _savePreferences();\n                }\n            )\n            .bind(\n                \"mousedown.jstree\",\n                function (event) {\n                    // select tree node on right-click\n                    if (event.which === 3) {\n                        var treenode = $(event.target).closest(\"li\");\n                        if (treenode) {\n                            var saveSuppressToggleOpen = suppressToggleOpen;\n                            \n                            // don't toggle open folders (just select)\n                            suppressToggleOpen = true;\n                            _projectTree.jstree(\"deselect_all\");\n                            _projectTree.jstree(\"select_node\", treenode, false);\n                            suppressToggleOpen = saveSuppressToggleOpen;\n                        }\n                    }\n                }\n            );\n\n        // jstree has a default event handler for dblclick that attempts to clear the\n        // global window selection (presumably because it doesn't want text within the tree\n        // to be selected). This ends up messing up CodeMirror, and we don't need this anyway\n        // since we've turned off user selection of UI text globally. So we just unbind it,\n        // and add our own double-click handler here.\n        // Filed this bug against jstree at https://github.com/vakata/jstree/issues/163\n        _projectTree.bind(\"init.jstree\", function () {\n            // install scroller shadows\n            ViewUtils.addScrollerShadow(_projectTree.get(0));\n            \n            _projectTree\n                .unbind(\"dblclick.jstree\")\n                .bind(\"dblclick.jstree\", function (event) {\n                    var entry = $(event.target).closest(\"li\").data(\"entry\");\n                    if (entry && entry.isFile) {\n                        FileViewController.addToWorkingSetAndSelect(entry.fullPath);\n                    }\n                });\n\n            // fire selection changed events for sidebar-selection\n            $projectTreeList = $projectTreeContainer.find(\"ul\");\n            ViewUtils.sidebarList($projectTreeContainer, \"jstree-clicked\", \"jstree-leaf\");\n            $projectTreeContainer.show();\n        });\n\n        return result.promise();\n    }\n    \n    /** @param {Entry} entry File or directory to filter */\n    function shouldShow(entry) {\n        return [\".git\", \".svn\", \".DS_Store\", \"Thumbs.db\"].indexOf(entry.name) === -1;\n    }\n\n    /**\n     * @private\n     * Given an array of NativeFileSystem entries, returns a JSON array representing them in the format\n     * required by jsTree. Saves the corresponding Entry object as metadata (which jsTree will store in\n     * the DOM via $.data()).\n     *\n     * Does NOT recursively traverse the file system: folders are marked as expandable but are given no\n     * children initially.\n     *\n     * @param {Array.<Entry>} entries  Array of NativeFileSystem entry objects.\n     * @return {Array} jsTree node data: array of JSON objects\n     */\n    function _convertEntriesToJSON(entries) {\n        var jsonEntryList = [],\n            entry,\n            entryI;\n\n        for (entryI = 0; entryI < entries.length; entryI++) {\n            entry = entries[entryI];\n            \n            if (shouldShow(entry)) {\n                var jsonEntry = {\n                    data: entry.name,\n                    attr: { id: \"node\" + _projectInitialLoad.id++ },\n                    metadata: { entry: entry }\n                };\n                if (entry.isDirectory) {\n                    jsonEntry.children = [];\n                    jsonEntry.state = \"closed\";\n                }\n    \n                // For more info on jsTree's JSON format see: http://www.jstree.com/documentation/json_data\n                jsonEntryList.push(jsonEntry);\n    \n                // Map path to ID to initialize loaded and opened states\n                _projectInitialLoad.fullPathToIdMap[entry.fullPath] = jsonEntry.attr.id;\n            }\n        }\n        return jsonEntryList;\n    }\n\n    /**\n     * @private\n     * Called by jsTree when the user has expanded a node that has never been expanded before. We call\n     * jsTree back asynchronously with the node's immediate children data once the subfolder is done\n     * being fetched.\n     *\n     * @param {jQueryObject} treeNode  jQ object for the DOM node being expanded\n     * @param {function(Array)} jsTreeCallback  jsTree callback to provide children to\n     */\n    function _treeDataProvider(treeNode, jsTreeCallback) {\n        var dirEntry, isProjectRoot = false;\n\n        if (treeNode === -1) {\n            // Special case: root of tree\n            dirEntry = _projectRoot;\n            isProjectRoot = true;\n        } else {\n            // All other nodes: the DirectoryEntry is saved as jQ data in the tree (by _convertEntriesToJSON())\n            dirEntry = treeNode.data(\"entry\");\n        }\n\n        // Fetch dirEntry's contents\n        dirEntry.createReader().readEntries(\n            function (entries) {\n                var subtreeJSON = _convertEntriesToJSON(entries),\n                    wasNodeOpen = false,\n                    emptyDirectory = (subtreeJSON.length === 0);\n                \n                if (emptyDirectory) {\n                    if (!isProjectRoot) {\n                        wasNodeOpen = treeNode.hasClass(\"jstree-open\");\n                    } else {\n                        // project root is a special case, add a placeholder\n                        subtreeJSON.push({});\n                    }\n                }\n                \n                jsTreeCallback(subtreeJSON);\n                \n                if (!isProjectRoot && emptyDirectory) {\n                    // If the directory is empty, force it to appear as an open or closed node.\n                    // This is a workaround for issue #149 where jstree would show this node as a leaf.\n                    var classToAdd = (wasNodeOpen) ? \"jstree-closed\" : \"jstree-open\";\n                    \n                    treeNode.removeClass(\"jstree-leaf jstree-closed jstree-open\")\n                            .addClass(classToAdd);\n                }\n            },\n            function (error) {\n                Dialogs.showModalDialog(\n                    Dialogs.DIALOG_ID_ERROR,\n                    Strings.ERROR_LOADING_PROJECT,\n                    StringUtils.format(Strings.READ_DIRECTORY_ENTRIES_ERROR,\n                        StringUtils.htmlEscape(dirEntry.fullPath),\n                        error.code)\n                );\n            }\n        );\n\n    }\n    \n    /** Returns the full path to the default project folder. The path is currently the brackets src folder.\n     * TODO: (issue #267): Brackets does not yet support operating when there is no project folder. This code will likely\n     * not be needed when this support is added.\n     * @private\n     * @return {!string} fullPath reference\n     */\n    function _getDefaultProjectPath() {\n        var loadedPath = decodeURI(window.location.pathname);\n        var bracketsSrc = loadedPath.substr(0, loadedPath.lastIndexOf(\"/\"));\n        \n        bracketsSrc = FileUtils.convertToNativePath(bracketsSrc);\n\n        return bracketsSrc;\n    }\n    \n    /**\n     * Loads the given folder as a project. Normally, you would call openProject() instead to let the\n     * user choose a folder.\n     *\n     * @param {string} rootPath  Absolute path to the root folder of the project. \n     *  If rootPath is undefined or null, the last open project will be restored.\n     * @return {$.Promise} A promise object that will be resolved when the\n     *  project is loaded and tree is rendered, or rejected if the project path\n     *  fails to load.\n     */\n    function _loadProject(rootPath) {\n        if (_projectRoot) {\n            // close current project\n            $(exports).triggerHandler(\"beforeProjectClose\", _projectRoot);\n        }\n\n        // close all the old files\n        DocumentManager.closeAll();\n\n        // reset tree node id's\n        _projectInitialLoad.id = 0;\n\n        var result = new $.Deferred(),\n            resultRenderTree;\n\n        // restore project tree state from last time this project was open\n        _projectInitialLoad.previous = _prefs.getValue(_getTreeStateKey(rootPath)) || [];\n\n        // Populate file tree as long as we aren't running in the browser\n        if (!brackets.inBrowser) {\n            // Point at a real folder structure on local disk\n            NativeFileSystem.requestNativeFileSystem(rootPath,\n                function (rootEntry) {\n                    var projectRootChanged = (!_projectRoot || !rootEntry)\n                        || _projectRoot.fullPath !== rootEntry.fullPath;\n\n                    // Success!\n                    var perfTimerName = PerfUtils.markStart(\"Load Project: \" + rootPath);\n\n                    _projectRoot = rootEntry;\n\n                    // The tree will invoke our \"data provider\" function to populate the top-level items, then\n                    // go idle until a node is expanded - at which time it'll call us again to fetch the node's\n                    // immediate children, and so on.\n                    resultRenderTree = _renderTree(_treeDataProvider);\n\n                    resultRenderTree.done(function () {\n                        if (projectRootChanged) {\n                            $(exports).triggerHandler(\"projectOpen\", _projectRoot);\n                        }\n                        \n                        result.resolve();\n                    });\n                    resultRenderTree.fail(function () {\n                        PerfUtils.terminateMeasurement(perfTimerName);\n                        result.reject();\n                    });\n                    resultRenderTree.always(function () {\n                        PerfUtils.addMeasurement(perfTimerName);\n                    });\n                },\n                function (error) {\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_ERROR,\n                        Strings.ERROR_LOADING_PROJECT,\n                        StringUtils.format(\n                            Strings.REQUEST_NATIVE_FILE_SYSTEM_ERROR,\n                            StringUtils.htmlEscape(rootPath),\n                            error.code,\n                            function () {\n                                result.reject();\n                            }\n                        )\n                    ).done(function () {\n                        // The project folder stored in preference doesn't exist, so load the default \n                        // project directory.\n                        // TODO (issue #267): When Brackets supports having no project directory\n                        // defined this code will need to change\n                        return _loadProject(_getDefaultProjectPath());\n                    });\n                }\n                );\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * Open a new project. Currently, Brackets must always have a project open, so\n     * this method handles both closing the current project and opening a new project.\n     *\n     * @param {string=} path Optional absolute path to the root folder of the project. \n     *  If path is undefined or null, displays a  dialog where the user can choose a\n     *  folder to load. If the user cancels the dialog, nothing more happens.\n     * @return {$.Promise} A promise object that will be resolved when the\n     *  project is loaded and tree is rendered, or rejected if the project path\n     *  fails to load.\n     */\n    function openProject(path) {\n\n        var result = new $.Deferred();\n\n        // Confirm any unsaved changes first. We run the command in \"prompt-only\" mode, meaning it won't\n        // actually close any documents even on success; we'll do that manually after the user also oks\n        //the folder-browse dialog.\n        CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })\n            .done(function () {\n                if (path) {\n                    // use specified path\n                    _loadProject(path).pipe(result.resolve, result.reject);\n                } else {\n                    // Pop up a folder browse dialog\n                    NativeFileSystem.showOpenDialog(false, true, \"Choose a folder\", _projectRoot.fullPath, null,\n                        function (files) {\n                            // If length == 0, user canceled the dialog; length should never be > 1\n                            if (files.length > 0) {\n                                // Load the new project into the folder tree\n                                _loadProject(files[0]).pipe(result.resolve, result.reject);\n                            } else {\n                                result.reject();\n                            }\n                        },\n                        function (error) {\n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_LOADING_PROJECT,\n                                StringUtils.format(Strings.OPEN_DIALOG_ERROR, error.code)\n                            );\n                            result.reject();\n                        }\n                        );\n                }\n            })\n            .fail(function () {\n                result.reject();\n            });\n\n        // if fail, don't open new project: user canceled (or we failed to save its unsaved changes)\n        return result.promise();\n    }\n\n\n    /**\n     * Create a new item in the project tree.\n     *\n     * @param baseDir {string} Full path of the directory where the item should go\n     * @param initialName {string} Initial name for the item\n     * @param skipRename {boolean} If true, don't allow the user to rename the item\n     * @return {$.Promise} A promise object that will be resolved with the FileEntry\n     *  of the created object, or rejected if the user cancelled or entered an illegal\n     *  filename.\n     */\n    function createNewItem(baseDir, initialName, skipRename) {\n        var node                = null,\n            selection           = _projectTree.jstree(\"get_selected\"),\n            selectionEntry      = null,\n            position            = \"inside\",\n            escapeKeyPressed    = false,\n            result              = new $.Deferred(),\n            wasNodeOpen         = true;\n\n        // get the FileEntry or DirectoryEntry\n        if (selection) {\n            selectionEntry = selection.data(\"entry\");\n        }\n\n        // move selection to parent DirectoryEntry\n        if (selectionEntry) {\n            if (selectionEntry.isFile) {\n                position = \"after\";\n                \n                var parent = $.jstree._reference(_projectTree)._get_parent(selection);\n                \n                if (typeof (parent.data) === \"function\") {\n                    // get Entry from tree node\n                    // note that the jstree root will return undefined\n                    selectionEntry = parent.data(\"entry\");\n                } else {\n                    // reset here. will be replaced with project root.\n                    selectionEntry = null;\n                }\n            } else if (selectionEntry.isDirectory) {\n                wasNodeOpen = selection.hasClass(\"jstree-open\");\n            }\n        }\n\n        // use the project root DirectoryEntry\n        if (!selectionEntry) {\n            selectionEntry = getProjectRoot();\n        }\n\n        _projectTree.on(\"create.jstree\", function (event, data) {\n            $(event.target).off(\"create.jstree\");\n\n            function errorCleanup() {\n                // TODO (issue #115): If an error occurred, we should allow the user to fix the filename.\n                // For now we just remove the node so you have to start again.\n                var parent = data.inst._get_parent(data.rslt.obj);\n                \n                _projectTree.jstree(\"remove\", data.rslt.obj);\n                \n                // Restore tree node state and styling when errors occur.\n                // parent returns -1 when at the root\n                if (parent && (parent !== -1)) {\n                    var methodName = (wasNodeOpen) ? \"open_node\" : \"close_node\";\n                    var classToAdd = (wasNodeOpen) ? \"jstree-open\" : \"jstree-closed\";\n                    \n                    // This is a workaround for issue #149 where jstree would show this node as a leaf.\n                    _projectTree.jstree(methodName, parent);\n                    parent.removeClass(\"jstree-leaf jstree-closed jstree-open\")\n                          .addClass(classToAdd);\n                }\n                \n                result.reject();\n            }\n\n            if (!escapeKeyPressed) {\n                // Validate file name\n                // TODO (issue #270): There are some filenames like COM1, LPT3, etc. that are not valid on Windows.\n                // We may want to add checks for those here.\n                // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx\n                if (data.rslt.name.search(/[\\/?*:;\\{\\}<>\\\\|]+/) !== -1) {\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_ERROR,\n                        Strings.INVALID_FILENAME_TITLE,\n                        Strings.INVALID_FILENAME_MESSAGE\n                    );\n\n                    errorCleanup();\n                    return;\n                }\n\n                // Use getFile() to create the new file\n                selectionEntry.getFile(\n                    data.rslt.name,\n                    {create: true, exclusive: true},\n                    function (entry) {\n                        data.rslt.obj.data(\"entry\", entry);\n                        _projectTree.jstree(\"select_node\", data.rslt.obj, true);\n                        result.resolve(entry);\n                    },\n                    function (error) {\n                        if ((error.code === FileError.PATH_EXISTS_ERR)\n                                || (error.code === FileError.TYPE_MISMATCH_ERR)) {\n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.INVALID_FILENAME_TITLE,\n                                StringUtils.format(Strings.FILE_ALREADY_EXISTS,\n                                    StringUtils.htmlEscape(data.rslt.name))\n                            );\n                        } else {\n                            var errString = error.code === FileError.NO_MODIFICATION_ALLOWED_ERR ?\n                                             Strings.NO_MODIFICATION_ALLOWED_ERR :\n                                             StringUtils.format(String.GENERIC_ERROR, error.code);\n\n                            var errMsg = StringUtils.format(Strings.ERROR_CREATING_FILE,\n                                            StringUtils.htmlEscape(data.rslt.name),\n                                            errString);\n                          \n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_CREATING_FILE_TITLE,\n                                errMsg\n                            );\n                        }\n\n                        errorCleanup();\n                    }\n                );\n            } else { //escapeKeyPressed\n                errorCleanup();\n            }\n        });\n        \n        // TODO (issue #115): Need API to get tree node for baseDir.\n        // In the meantime, pass null for node so new item is placed\n        // relative to the selection\n        node = selection;\n        \n        // Open the node before creating the new child\n        _projectTree.jstree(\"open_node\", node);\n\n        // Create the node and open the editor\n        _projectTree.jstree(\"create\", node, position, {data: initialName}, null, skipRename);\n\n        if (!skipRename) {\n            var $renameInput = _projectTree.find(\".jstree-rename-input\");\n\n            $renameInput.on(\"keydown\", function (event) {\n                // Listen for escape key on keydown, so we can remove the node in the create.jstree handler above\n                if (event.keyCode === 27) {\n                    escapeKeyPressed = true;\n                }\n            });\n\n            ViewUtils.scrollElementIntoView(_projectTree, $renameInput, true);\n        }\n        \n        return result.promise();\n    }\n\n    /**\n     * Forces createNewItem() to complete by removing focus from the rename field which causes\n     * the new file to be written to disk\n     */\n    function forceFinishRename() {\n        $(\".jstree-rename-input\").blur();\n    }\n\n\n    // Initialize variables and listeners that depend on the HTML DOM\n    $(brackets).on(\"htmlContentLoadComplete\", function () {\n        $projectTreeContainer = $(\"#project-files-container\");\n\n        $(\"#open-files-container\").on(\"contentChanged\", function () {\n            _redraw(false); // redraw jstree when working set size changes\n        });\n    });\n\n    // Init PreferenceStorage\n    var defaults = {\n        projectPath:      _getDefaultProjectPath()  /* initialize to brackets source */\n    };\n    _prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaults);\n\n    // Event Handlers\n    $(FileViewController).on(\"documentSelectionFocusChange\", _documentSelectionFocusChange);\n    $(FileViewController).on(\"fileViewFocusChange\", _fileViewFocusChange);\n\n    // Commands\n    CommandManager.register(Strings.CMD_OPEN_FOLDER,    Commands.FILE_OPEN_FOLDER,  openProject);\n\n    // Define public API\n    exports.getProjectRoot          = getProjectRoot;\n    exports.isWithinProject         = isWithinProject;\n    exports.makeProjectRelativeIfPossible = makeProjectRelativeIfPossible;\n    exports.shouldShow              = shouldShow;\n    exports.openProject             = openProject;\n    exports.getSelectedItem         = getSelectedItem;\n    exports.getInitialProjectPath   = getInitialProjectPath;\n    exports.createNewItem           = createNewItem;\n    exports.forceFinishRename       = forceFinishRename;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * DocumentManager maintains a list of currently 'open' Documents. It also owns the list of files in\n * the working set, and the notion of which Document is currently shown in the main editor UI area.\n * \n * Document is the model for a file's contents; it dispatches events whenever those contents change.\n * To transiently inspect a file's content, simply get a Document and call getText() on it. However,\n * to be notified of Document changes or to modify a Document, you MUST call addRef() to ensure the\n * Document instance 'stays alive' and is shared by all other who read/modify that file. ('Open'\n * Documents are all Documents that are 'kept alive', i.e. have ref count > 0).\n *\n * To get a Document, call getDocumentForPath(); never new up a Document yourself.\n * \n * Secretly, a Document may use an Editor instance to act as the model for its internal state. (This\n * is unavoidable because CodeMirror does not separate its model from its UI). Documents are not\n * modifiable until they have a backing 'master Editor'. Creation of the backing Editor is owned by\n * EditorManager. A Document only gets a backing Editor if it becomes the currentDocument, or if edits\n * occur in any Editor (inline or full-sized) bound to the Document; there is currently no other way\n * to ensure a Document is modifiable.\n *\n * A non-modifiable Document may still dispatch change notifications, if the Document was changed\n * externally on disk.\n *\n * Aside from the text content, Document tracks a few pieces of metadata - notably, whether there are\n * any unsaved changes.\n *\n * This module dispatches several events:\n *    - dirtyFlagChange -- When any Document's isDirty flag changes. The 2nd arg to the listener is the\n *      Document whose flag changed.\n *    - documentSaved -- When a Document's changes have been saved. The 2nd arg to the listener is the \n *      Document that has been saved.\n *    - currentDocumentChange -- When the value of getCurrentDocument() changes.\n *    - workingSetAdd -- When a file is added to the working set (see getWorkingSet()). The 2nd arg\n *      to the listener is the added FileEntry.\n *    - workingSetAddList -- When a list of files are added to the working set (e.g. project open, multiple file open).\n *      The 2nd arg to the listener is the array of added FileEntry objects.\n *    - workingSetRemove -- When a file is removed from the working set (see getWorkingSet()). The\n *      2nd arg to the listener is the removed FileEntry.\n *    - workingSetRemoveList -- When a list of files is to be removed from the working set (e.g. project close).\n *      The 2nd arg to the listener is the array of removed FileEntry objects.\n *\n * These are jQuery events, so to listen for them you do something like this:\n *    $(DocumentManager).on(\"eventname\", handler);\n */\ndefine('document/DocumentManager',['require','exports','module','file/NativeFileSystem','project/ProjectManager','editor/EditorManager','preferences/PreferencesManager','file/FileUtils','command/CommandManager','utils/Async','utils/PerfUtils','command/Commands'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        ProjectManager      = require(\"project/ProjectManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Async               = require(\"utils/Async\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Commands            = require(\"command/Commands\");\n    \n    /**\n     * Unique PreferencesManager clientID\n     */\n    var PREFERENCES_CLIENT_ID = \"com.adobe.brackets.DocumentManager\";\n    \n    /**\n     * @private\n     * @see DocumentManager.getCurrentDocument()\n     */\n    var _currentDocument = null;\n    \n    /**\n     * @private\n     * @type {PreferenceStorage}\n     */\n    var _prefs = {};\n    \n    /**\n     * Returns the Document that is currently open in the editor UI. May be null.\n     * When this changes, DocumentManager dispatches a \"currentDocumentChange\" event. The current\n     * document always has a backing Editor (Document._masterEditor != null) and is thus modifiable.\n     * @return {?Document}\n     */\n    function getCurrentDocument() {\n        return _currentDocument;\n    }\n    \n    /**\n     * @private\n     * @type {Array.<FileEntry>}\n     * @see DocumentManager.getWorkingSet()\n     */\n    var _workingSet = [];\n    \n    /**\n     * @private\n     * Contains the same set of items as _workinSet, but ordered by how recently they were _currentDocument (0 = most recent).\n     * @type {Array.<FileEntry>}\n     */\n    var _workingSetMRUOrder = [];\n    \n    /**\n     * While true, the MRU order is frozen\n     * @type {boolean}\n     */\n    var _documentNavPending = false;\n    \n    /**\n     * While true, allow preferences to be saved\n     * @type {boolean}\n     */\n    var _isProjectChanging = false;\n    \n    /**\n     * All documents with refCount > 0. Maps Document.file.fullPath -> Document.\n     * @private\n     * @type {Object.<string, Document>}\n     */\n    var _openDocuments = {};\n    \n    /**\n     * Returns a list of items in the working set in UI list order. May be 0-length, but never null.\n     *\n     * When a file is added this list, DocumentManager dispatches a \"workingSetAdd\" event.\n     * When a file is removed from list, DocumentManager dispatches a \"workingSetRemove\" event.\n     * To listen for ALL changes to this list, you must listen for both events.\n     *\n     * Which items belong in the working set is managed entirely by DocumentManager. Callers cannot\n     * (yet) change this collection on their own.\n     *\n     * @return {Array.<FileEntry>}\n     */\n    function getWorkingSet() {\n        return _workingSet;\n        // TODO: (issue #297) return a clone to prevent meddling?\n    }\n\n    /** \n     * Returns the index of the file matching fullPath in the working set.\n     * Returns -1 if not found.\n     * @param {!string} fullPath\n     * @param {Array.<FileEntry>=} list Pass this arg to search a different array of files. Internal\n     *          use only.\n     * @returns {number} index\n     */\n    function findInWorkingSet(fullPath, list) {\n        list = list || _workingSet;\n        \n        var ret = -1;\n        var found = list.some(function findByPath(file, i) {\n                ret = i;\n                return file.fullPath === fullPath;\n            });\n            \n        return (found ? ret : -1);\n    }\n\n    /**\n     * Returns all Documents that are 'open' in the UI somewhere (for now, this means open in an\n     * inline editor and/or a full-size editor). Only these Documents can be modified, and only\n     * these Documents are synced with external changes on disk.\n     * @return {Array.<Document>}\n     */\n    function getAllOpenDocuments() {\n        var result = [];\n        var path;\n        for (path in _openDocuments) {\n            if (_openDocuments.hasOwnProperty(path)) {\n                result.push(_openDocuments[path]);\n            }\n        }\n        return result;\n    }\n    \n    \n    /**\n     * Adds the given file to the end of the working set list, if it is not already in the list.\n     * Does not change which document is currently open in the editor. Completes synchronously.\n     * @param {!FileEntry} file\n     */\n    function addToWorkingSet(file) {\n        // If doc is already in working set, don't add it again\n        if (findInWorkingSet(file.fullPath) !== -1) {\n            return;\n        }\n        \n        // Add\n        _workingSet.push(file);\n        \n        // Add to MRU order: either first or last, depending on whether it's already the current doc or not\n        if (_currentDocument && _currentDocument.file.fullPath === file.fullPath) {\n            _workingSetMRUOrder.unshift(file);\n        } else {\n            _workingSetMRUOrder.push(file);\n        }\n        \n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetAdd\", file);\n    }\n\n    /**\n     * Adds the given file list to the end of the working set list.\n     * Does not change which document is currently open in the editor.\n     * More efficient than calling addToWorkingSet() (in a loop) for\n     * a list of files because there's only 1 redraw at the end\n     * @param {!FileEntryArray} fileList\n     */\n    function addListToWorkingSet(fileList) {\n        var uniqueFileList = [];\n\n        // Process only files not already in working set\n        fileList.forEach(function (file) {\n            // If doc is already in working set, don't add it again\n            if (findInWorkingSet(file.fullPath) === -1) {\n                uniqueFileList.push(file);\n\n                // Add\n                _workingSet.push(file);\n\n                // Add to MRU order: either first or last, depending on whether it's already the current doc or not\n                if (_currentDocument && _currentDocument.file.fullPath === file.fullPath) {\n                    _workingSetMRUOrder.unshift(file);\n                } else {\n                    _workingSetMRUOrder.push(file);\n                }\n            }\n        });\n\n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetAddList\", [uniqueFileList]);\n    }\n\n    /**\n     * Removes the given file from the working set list, if it was in the list. Does not change\n     * the current editor even if it's for this file.\n     * @param {!FileEntry} file\n     */\n    function removeFromWorkingSet(file) {\n        // If doc isn't in working set, do nothing\n        var index = findInWorkingSet(file.fullPath);\n        if (index === -1) {\n            return;\n        }\n        \n        // Remove\n        _workingSet.splice(index, 1);\n        _workingSetMRUOrder.splice(findInWorkingSet(file.fullPath, _workingSetMRUOrder), 1);\n        \n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetRemove\", file);\n    }\n\n    /**\n     * Removes all files from the working set list.\n     */\n    function _removeAllFromWorkingSet() {\n        var fileList = _workingSet;\n\n        // Remove all\n        _workingSet = [];\n        _workingSetMRUOrder = [];\n\n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetRemoveList\", [fileList]);\n    }\n\n    /**\n     * Moves document to the front of the MRU list, IF it's in the working set; no-op otherwise.\n     * @param {!Document}\n     */\n    function _markMostRecent(doc) {\n        var mruI = findInWorkingSet(doc.file.fullPath, _workingSetMRUOrder);\n        if (mruI !== -1) {\n            _workingSetMRUOrder.splice(mruI, 1);\n            _workingSetMRUOrder.unshift(doc.file);\n        }\n    }\n    \n    \n    /**\n     * Indicate that changes to currentDocument are temporary for now, and should not update the MRU\n     * ordering of the working set. Useful for next/previous keyboard navigation (until Ctrl is released)\n     * or for incremental-search style document preview like Quick Open will eventually have.\n     * Can be called any number of times, and ended by a single finalizeDocumentNavigation() call.\n     */\n    function beginDocumentNavigation() {\n        _documentNavPending = true;\n    }\n    \n    /**\n     * Un-freezes the MRU list after one or more beginDocumentNavigation() calls. Whatever document is\n     * current is bumped to the front of the MRU list.\n     */\n    function finalizeDocumentNavigation() {\n        if (_documentNavPending) {\n            _documentNavPending = false;\n            \n            _markMostRecent(_currentDocument);\n        }\n    }\n    \n    \n    /**\n     * Changes currentDocument to the given Document, firing currentDocumentChange, which in turn\n     * causes this Document's main editor UI to be shown in the editor pane, updates the selection\n     * in the file tree / working set UI, etc. This call may also add the item to the working set.\n     * \n     * @param {!Document} document  The Document to make current. May or may not already be in the\n     *      working set.\n     */\n    function setCurrentDocument(doc) {\n        \n        // If this doc is already current, do nothing\n        if (_currentDocument === doc) {\n            return;\n        }\n\n        var perfTimerName = PerfUtils.markStart(\"setCurrentDocument:\\t\" + doc.file.fullPath);\n        \n        // If file not within project tree, add it to working set right now (don't wait for it to\n        // become dirty)\n        if (!ProjectManager.isWithinProject(doc.file.fullPath)) {\n            addToWorkingSet(doc.file);\n        }\n        \n        // Adjust MRU working set ordering (except while in the middle of a Ctrl+Tab sequence)\n        if (!_documentNavPending) {\n            _markMostRecent(doc);\n        }\n        \n        // Make it the current document\n        _currentDocument = doc;\n        $(exports).triggerHandler(\"currentDocumentChange\");\n        // (this event triggers EditorManager to actually switch editors in the UI)\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n    \n    /** Changes currentDocument to null, causing no full Editor to be shown in the UI */\n    function _clearCurrentDocument() {\n        // If editor already blank, do nothing\n        if (!_currentDocument) {\n            return;\n        }\n        \n        // Change model & dispatch event\n        _currentDocument = null;\n        $(exports).triggerHandler(\"currentDocumentChange\");\n        // (this event triggers EditorManager to actually clear the editor UI)\n    }\n    \n    /**\n     * Closes the full editor for the given file (if there is one), and removes it from the working\n     * set. Any other editors for this Document remain open. Discards any unsaved changes - it is\n     * expected that the UI has already confirmed with the user before calling this.\n     *\n     * Changes currentDocument if this file was the current document (may change to null).\n     *\n     * This is a subset of notifyFileDeleted(). Use this for the user-facing Close command.\n     *\n     * @param {!FileEntry} file\n     */\n    function closeFullEditor(file) {\n        // If this was the current document shown in the editor UI, we're going to switch to a\n        // different document (or none if working set has no other options)\n        if (_currentDocument && _currentDocument.file.fullPath === file.fullPath) {\n            var wsIndex = findInWorkingSet(file.fullPath);\n            \n            // Decide which doc to show in editor after this one\n            var nextFile;\n            if (wsIndex === -1) {\n                // If doc wasn't in working set, use bottommost working set item\n                if (_workingSet.length > 0) {\n                    nextFile = _workingSet[_workingSet.length  - 1];\n                }\n                // else: leave nextDocument null; editor area will be blank\n            } else {\n                // If doc was in working set, use item next to it (below if possible)\n                if (wsIndex < _workingSet.length - 1) {\n                    nextFile = _workingSet[wsIndex + 1];\n                } else if (wsIndex > 0) {\n                    nextFile = _workingSet[wsIndex - 1];\n                }\n                // else: leave nextDocument null; editor area will be blank\n            }\n            \n            // Switch editor to next document (or blank it out)\n            if (nextFile) {\n                CommandManager.execute(Commands.FILE_OPEN, { fullPath: nextFile.fullPath });\n            } else {\n                _clearCurrentDocument();\n            }\n        }\n        \n        // (Now we're guaranteed that the current document is not the one we're closing)\n        console.assert(!(_currentDocument && _currentDocument.file.fullPath === file.fullPath));\n        \n        // Remove closed doc from working set, if it was in there\n        // This happens regardless of whether the document being closed was the current one or not\n        removeFromWorkingSet(file);\n        \n        // Note: EditorManager will dispose the closed document's now-unneeded editor either in\n        // response to the editor-swap call above, or the removeFromWorkingSet() call, depending on\n        // circumstances. See notes in EditorManager for more.\n    }\n\n    /**\n     * Equivalent to calling closeFullEditor() for all Documents. Same caveat: this discards any\n     * unsaved changes, so the UI should confirm with the user before calling this.\n     */\n    function closeAll() {\n        _clearCurrentDocument();\n        _removeAllFromWorkingSet();\n    }\n    \n    \n    /**\n     * Cleans up any loose Documents whose only ref is its own master Editor, and that Editor is not\n     * rooted in the UI anywhere. This can happen if the Editor is auto-created via Document APIs that\n     * trigger _ensureMasterEditor() without making it dirty. E.g. a command invoked on the focused\n     * inline editor makes no-op edits or does a read-only operation.\n     */\n    function _gcDocuments() {\n        getAllOpenDocuments().forEach(function (doc) {\n            // Is the only ref to this document its own master Editor?\n            if (doc._refCount === 1 && doc._masterEditor) {\n                // Destroy the Editor if it's not being kept alive by the UI\n                EditorManager._destroyEditorIfUnneeded(doc);\n            }\n        });\n    }\n    \n    \n    /**\n     * @constructor\n     * Model for the contents of a single file and its current modification state.\n     * See DocumentManager documentation for important usage notes.\n     *\n     * Document dispatches these events:\n     *\n     * change -- When the text of the editor changes (including due to undo/redo). \n     *\n     *        Passes ({Document}, {ChangeList}), where ChangeList is a linked list (NOT an array)\n     *        of change record objects. Each change record looks like:\n     *\n     *            { from: start of change, expressed as {line: <line number>, ch: <character offset>},\n     *              to: end of change, expressed as {line: <line number>, ch: <chracter offset>},\n     *              text: array of lines of text to replace existing text,\n     *              next: next change record in the linked list, or undefined if this is the last record }\n     *      \n     *        The line and ch offsets are both 0-based.\n     *\n     *        The ch offset in \"from\" is inclusive, but the ch offset in \"to\" is exclusive. For example,\n     *        an insertion of new content (without replacing existing content) is expressed by a range\n     *        where from and to are the same.\n     *\n     *        If \"from\" and \"to\" are undefined, then this is a replacement of the entire text content.\n     *\n     *        IMPORTANT: If you listen for the \"change\" event, you MUST also addRef() the document \n     *        (and releaseRef() it whenever you stop listening). You should also listen to the \"deleted\"\n     *        event.\n     *  \n     *        (FUTURE: this is a modified version of the raw CodeMirror change event format; may want to make \n     *        it an ordinary array)\n     *\n     * deleted -- When the file for this document has been deleted. All views onto the document should\n     *      be closed. The document will no longer be editable or dispatch \"change\" events.\n     *\n     * @param {!FileEntry} file  Need not lie within the project.\n     * @param {!Date} initialTimestamp  File's timestamp when we read it off disk.\n     * @param {!string} rawText  Text content of the file.\n     */\n    function Document(file, initialTimestamp, rawText) {\n        if (!(this instanceof Document)) {  // error if constructor called without 'new'\n            throw new Error(\"Document constructor must be called with 'new'\");\n        }\n        if (_openDocuments[file.fullPath]) {\n            throw new Error(\"Creating a document when one already exists, for: \" + file);\n        }\n        \n        this.file = file;\n        this.refreshText(rawText, initialTimestamp);\n        \n        // This is a good point to clean up any old dangling Documents\n        _gcDocuments();\n    }\n    \n    /**\n     * Number of clients who want this Document to stay alive. The Document is listed in\n     * DocumentManager._openDocuments whenever refCount > 0.\n     */\n    Document.prototype._refCount = 0;\n    \n    /**\n     * The FileEntry for this document. Need not lie within the project.\n     * @type {!FileEntry}\n     */\n    Document.prototype.file = null;\n    \n    /**\n     * Whether this document has unsaved changes or not.\n     * When this changes on any Document, DocumentManager dispatches a \"dirtyFlagChange\" event.\n     * @type {boolean}\n     */\n    Document.prototype.isDirty = false;\n    \n    /**\n     * What we expect the file's timestamp to be on disk. If the timestamp differs from this, then\n     * it means the file was modified by an app other than Brackets.\n     * @type {!Date}\n     */\n    Document.prototype.diskTimestamp = null;\n    \n    /**\n     * The text contents of the file, or null if our backing model is _masterEditor.\n     * @type {?string}\n     */\n    Document.prototype._text = null;\n    \n    /**\n     * Editor object representing the full-size editor UI for this document. May be null if Document\n     * has not yet been modified or been the currentDocument; in that case, our backing model is the\n     * string _text.\n     * @type {?Editor}\n     */\n    Document.prototype._masterEditor = null;\n    \n    /**\n     * The content's line-endings style. If a Document is created on empty text, or text with\n     * inconsistent line endings, defaults to the current platform's standard endings.\n     * @type {FileUtils.LINE_ENDINGS_CRLF|FileUtils.LINE_ENDINGS_LF}\n     */\n    Document.prototype._lineEndings = null;\n\n    /** Add a ref to keep this Document alive */\n    Document.prototype.addRef = function () {\n        //console.log(\"+++REF+++ \"+this);\n        \n        if (this._refCount === 0) {\n            //console.log(\"+++ adding to open list\");\n            if (_openDocuments[this.file.fullPath]) {\n                throw new Error(\"Document for this path already in _openDocuments!\");\n            }\n\n            _openDocuments[this.file.fullPath] = this;\n            $(exports).triggerHandler(\"afterDocumentCreate\", this);\n        }\n        this._refCount++;\n    };\n    /** Remove a ref that was keeping this Document alive */\n    Document.prototype.releaseRef = function () {\n        //console.log(\"---REF--- \"+this);\n\n        this._refCount--;\n        if (this._refCount < 0) {\n            throw new Error(\"Document ref count has fallen below zero!\");\n        }\n        if (this._refCount === 0) {\n            //console.log(\"--- removing from open list\");\n            if (!_openDocuments[this.file.fullPath]) {\n                throw new Error(\"Document with references was not in _openDocuments!\");\n            }\n\n            $(exports).triggerHandler(\"beforeDocumentDelete\", this);\n            delete _openDocuments[this.file.fullPath];\n        }\n    };\n    \n    /**\n     * Attach a backing Editor to the Document, enabling setText() to be called. Assumes Editor has\n     * already been initialized with the value of getText(). ONLY Editor should call this (and only\n     * when EditorManager has told it to act as the master editor).\n     * @param {!Editor} masterEditor\n     */\n    Document.prototype._makeEditable = function (masterEditor) {\n        if (this._masterEditor) {\n            throw new Error(\"Document is already editable\");\n        } else {\n            this._text = null;\n            this._masterEditor = masterEditor;\n            $(masterEditor).on(\"change\", this._handleEditorChange.bind(this));\n        }\n    };\n    \n    /**\n     * Detach the backing Editor from the Document, disallowing setText(). The text content is\n     * stored back onto _text so other Document clients continue to have read-only access. ONLY\n     * Editor.destroy() should call this.\n     */\n    Document.prototype._makeNonEditable = function () {\n        if (!this._masterEditor) {\n            throw new Error(\"Document is already non-editable\");\n        } else {\n            // _text represents the raw text, so fetch without normalized line endings\n            this._text = this.getText(true);\n            this._masterEditor = null;\n        }\n    };\n    \n    /**\n     * Guarantees that _masterEditor is non-null. If needed, asks EditorManager to create a new master\n     * editor bound to this Document (which in turn causes Document._makeEditable() to be called).\n     * Should ONLY be called by Editor and Document.\n     */\n    Document.prototype._ensureMasterEditor = function () {\n        if (!this._masterEditor) {\n            EditorManager._createFullEditorForDocument(this);\n        }\n    };\n    \n    /**\n     * Returns the document's current contents; may not be saved to disk yet. Whenever this\n     * value changes, the Document dispatches a \"change\" event.\n     *\n     * @param {boolean=} useOriginalLineEndings If true, line endings in the result depend on the\n     *      Document's line endings setting (based on OS & the original text loaded from disk).\n     *      If false, line endings are always \\n (like all the other Document text getter methods).\n     * @return {string}\n     */\n    Document.prototype.getText = function (useOriginalLineEndings) {\n        if (this._masterEditor) {\n            // CodeMirror.getValue() always returns text with LF line endings; fix up to match line\n            // endings preferred by the document, if necessary\n            var codeMirrorText = this._masterEditor._codeMirror.getValue();\n            if (useOriginalLineEndings) {\n                if (this._lineEndings === FileUtils.LINE_ENDINGS_CRLF) {\n                    return codeMirrorText.replace(/\\n/g, \"\\r\\n\");\n                }\n            }\n            return codeMirrorText;\n            \n        } else {\n            // Optimized path that doesn't require creating master editor\n            if (useOriginalLineEndings) {\n                return this._text;\n            } else {\n                return this._text.replace(/\\r\\n/g, \"\\n\");\n            }\n        }\n    };\n    \n    /**\n     * Sets the contents of the document. Treated as an edit. Line endings will be rewritten to\n     * match the document's current line-ending style.\n     * @param {!string} text The text to replace the contents of the document with.\n     */\n    Document.prototype.setText = function (text) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.setValue(text);\n        // _handleEditorChange() triggers \"change\" event\n    };\n    \n    /**\n     * Sets the contents of the document. Treated as reloading the document from disk: the document\n     * will be marked clean with a new timestamp, the undo/redo history is cleared, and we re-check\n     * the text's line-ending style. CAN be called even if there is no backing editor.\n     * @param {!string} text The text to replace the contents of the document with.\n     * @param {!Date} newTimestamp Timestamp of file at the time we read its new contents from disk.\n     */\n    Document.prototype.refreshText = function (text, newTimestamp) {\n        var perfTimerName = PerfUtils.markStart(\"refreshText:\\t\" + (!this.file || this.file.fullPath));\n\n        if (this._masterEditor) {\n            this._masterEditor._resetText(text);\n            // _handleEditorChange() triggers \"change\" event for us\n        } else {\n            this._text = text;\n            // We fake a change record here that looks like CodeMirror's text change records, but\n            // omits \"from\" and \"to\", by which we mean the entire text has changed.\n            // TODO: Dumb to split it here just to join it again in the change handler, but this is\n            // the CodeMirror change format. Should we document our change format to allow this to\n            // either be an array of lines or a single string?\n            $(this).triggerHandler(\"change\", [this, {text: text.split(/\\r?\\n/)}]);\n        }\n        this._markClean();\n        this.diskTimestamp = newTimestamp;\n        \n        // Sniff line-ending style\n        this._lineEndings = FileUtils.sniffLineEndings(text);\n        if (!this._lineEndings) {\n            this._lineEndings = FileUtils.getPlatformLineEndings();\n        }\n\n        PerfUtils.addMeasurement(perfTimerName);\n    };\n    \n    /**\n     * Adds, replaces, or removes text. If a range is given, the text at that range is replaced with the\n     * given new text; if text == \"\", then the entire range is effectively deleted. If 'end' is omitted,\n     * then the new text is inserted at that point and all existing text is preserved. Line endings will\n     * be rewritten to match the document's current line-ending style.\n     * @param {!string} text  Text to insert or replace the range with\n     * @param {!{line:number, ch:number}} start  Start of range, inclusive (if 'to' specified) or insertion point (if not)\n     * @param {?{line:number, ch:number}} end  End of range, exclusive; optional\n     */\n    Document.prototype.replaceRange = function (text, start, end) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.replaceRange(text, start, end);\n        // _handleEditorChange() triggers \"change\" event\n    };\n    \n    /**\n     * Returns the characters in the given range. Line endings are normalized to '\\n'.\n     * @param {!{line:number, ch:number}} start  Start of range, inclusive\n     * @param {!{line:number, ch:number}} end  End of range, exclusive\n     * @return {!string}\n     */\n    Document.prototype.getRange = function (start, end) {\n        this._ensureMasterEditor();\n        return this._masterEditor._codeMirror.getRange(start, end);\n    };\n    \n    /**\n     * Returns the text of the given line (excluding any line ending characters)\n     * @param {number} Zero-based line number\n     * @return {!string}\n     */\n    Document.prototype.getLine = function (lineNum) {\n        this._ensureMasterEditor();\n        return this._masterEditor._codeMirror.getLine(lineNum);\n    };\n    \n    /**\n     * Batches a series of related Document changes. Repeated calls to replaceRange() should be wrapped in a\n     * batch for efficiency. Begins the batch, calls doOperation(), ends the batch, and then returns.\n     * @param {function()} doOperation\n     */\n    Document.prototype.batchOperation = function (doOperation) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.operation(doOperation);\n    };\n    \n    /**\n     * Handles changes from the master backing Editor. Changes are triggered either by direct edits\n     * to that Editor's UI, OR by our setText()/refreshText() methods.\n     * @private\n     */\n    Document.prototype._handleEditorChange = function (event, editor, changeList) {\n        // On any change, mark the file dirty. In the future, we should make it so that if you\n        // undo back to the last saved state, we mark the file clean.\n        var wasDirty = this.isDirty;\n        this.isDirty = editor._codeMirror.isDirty();\n        \n        // If file just became dirty, notify listeners, and add it to working set (if not already there)\n        if (wasDirty !== this.isDirty) {\n            $(exports).triggerHandler(\"dirtyFlagChange\", [this]);\n            addToWorkingSet(this.file);\n        }\n        \n        // Notify that Document's text has changed\n        // TODO: This needs to be kept in sync with SpecRunnerUtils.createMockDocument(). In the\n        // future, we should fix things so that we either don't need mock documents or that this\n        // is factored so it will just run in both.\n        $(this).triggerHandler(\"change\", [this, changeList]);\n    };\n    \n    /**\n     * @private\n     */\n    Document.prototype._markClean = function () {\n        this.isDirty = false;\n        if (this._masterEditor) {\n            this._masterEditor._codeMirror.markClean();\n        }\n        $(exports).triggerHandler(\"dirtyFlagChange\", this);\n    };\n    \n    /** \n     * Called when the document is saved (which currently happens in DocumentCommandHandlers). Marks the\n     * document not dirty and notifies listeners of the save.\n     */\n    Document.prototype.notifySaved = function () {\n        if (!this._masterEditor) {\n            console.log(\"### Warning: saving a Document that is not modifiable!\");\n        }\n        \n        this._markClean();\n        $(exports).triggerHandler(\"documentSaved\", this);\n        \n        // TODO: (issue #295) fetching timestamp async creates race conditions (albeit unlikely ones)\n        var thisDoc = this;\n        this.file.getMetadata(\n            function (metadata) {\n                thisDoc.diskTimestamp = metadata.modificationTime;\n            },\n            function (error) {\n                console.log(\"Error updating timestamp after saving file: \" + thisDoc.file.fullPath);\n            }\n        );\n    };\n    \n    /* (pretty toString(), to aid debugging) */\n    Document.prototype.toString = function () {\n        var dirtyInfo = (this.isDirty ? \" (dirty!)\" : \" (clean)\");\n        var editorInfo = (this._masterEditor ? \" (Editable)\" : \" (Non-editable)\");\n        var refInfo = \" refs:\" + this._refCount;\n        return \"[Document \" + this.file.fullPath + dirtyInfo + editorInfo + refInfo + \"]\";\n    };\n    \n    /**\n     * Gets an existing open Document for the given file, or creates a new one if the Document is\n     * not currently open ('open' means referenced by the UI somewhere). Always use this method to\n     * get Documents; do not call the Document constructor directly. This method is safe to call\n     * in parallel.\n     *\n     * If you are going to hang onto the Document for more than just the duration of a command - e.g.\n     * if you are going to display its contents in a piece of UI - then you must addRef() the Document\n     * and listen for changes on it. (Note: opening the Document in an Editor automatically manages\n     * refs and listeners for that Editor UI).\n     *\n     * @param {!string} fullPath\n     * @return {$.Promise} A promise object that will be resolved with the Document, or rejected\n     *      with a FileError if the file is not yet open and can't be read from disk.\n     */\n    function getDocumentForPath(fullPath) {\n        var doc             = _openDocuments[fullPath],\n            pendingPromise  = getDocumentForPath._pendingDocumentPromises[fullPath];\n\n        if (doc) {\n            // use existing document\n            return new $.Deferred().resolve(doc).promise();\n        } else if (pendingPromise) {\n            // wait for the result of a previous request\n            return pendingPromise;\n        } else {\n            var result = new $.Deferred(),\n                promise = result.promise();\n            \n            // log this document's Promise as pending\n            getDocumentForPath._pendingDocumentPromises[fullPath] = promise;\n\n            // create a new document\n            var fileEntry = new NativeFileSystem.FileEntry(fullPath),\n                perfTimerName = PerfUtils.markStart(\"getDocumentForPath:\\t\" + fullPath);\n\n            result.done(function () {\n                PerfUtils.addMeasurement(perfTimerName);\n            }).fail(function () {\n                PerfUtils.finalizeMeasurement(perfTimerName);\n            });\n\n            FileUtils.readAsText(fileEntry)\n                .always(function () {\n                    // document is no longer pending\n                    delete getDocumentForPath._pendingDocumentPromises[fullPath];\n                })\n                .done(function (rawText, readTimestamp) {\n                    doc = new Document(fileEntry, readTimestamp, rawText);\n                    result.resolve(doc);\n                })\n                .fail(function (fileError) {\n                    result.reject(fileError);\n                });\n            \n            return promise;\n        }\n    }\n    \n    /**\n     * Document promises that are waiting to be resolved. It is possible for multiple clients\n     * to request the same document simultaneously before the initial request has completed.\n     * In particular, this happens at app startup where the working set is created and the\n     * intial active document is opened in an editor. This is essential to ensure that only\n     * 1 Document exists for any FileEntry.\n     * @private\n     * @type {Object.<string, $.Promise>}\n     */\n    getDocumentForPath._pendingDocumentPromises = {};\n    \n    /**\n     * Returns the existing open Document for the given file, or null if the file is not open ('open'\n     * means referenced by the UI somewhere). If you will hang onto the Document, you must addRef()\n     * it; see {@link getDocumentForPath()} for details.\n     */\n    function getOpenDocumentForPath(fullPath) {\n        return _openDocuments[fullPath];\n    }\n    \n    \n    /**\n     * Reacts to a file being deleted: if there is a Document for this file, causes it to dispatch a\n     * \"deleted\" event; ensures it's not the currentDocument; and removes this file from the working\n     * set. These actions in turn cause all open editors for this file to close. Discards any unsaved\n     * changes - it is expected that the UI has already confirmed with the user before calling.\n     *\n     * To simply close a main editor when the file hasn't been deleted, use closeFullEditor() or FILE_CLOSE.\n     *\n     * FUTURE: Instead of an explicit notify, we should eventually listen for deletion events on some\n     * sort of \"project file model,\" making this just a private event handler.\n     */\n    function notifyFileDeleted(file) {\n        // First ensure it's not currentDocument, and remove from working set\n        closeFullEditor(file);\n        \n        // Notify all other editors to close as well\n        var doc = getOpenDocumentForPath(file.fullPath);\n        if (doc) {\n            $(doc).triggerHandler(\"deleted\");\n        }\n        \n        // At this point, all those other views SHOULD have released the Doc\n        if (doc && doc._refCount > 0) {\n            console.log(\"WARNING: deleted Document still has \" + doc._refCount + \" references. Did someone addRef() without listening for 'deleted'?\");\n        }\n    }\n    \n    \n    /**\n     * Get the next or previous file in the working set, in MRU order (relative to currentDocument).\n     * @param {Number} inc  -1 for previous, +1 for next; no other values allowed\n     * @return {?FileEntry}  null if working set empty\n     */\n    function getNextPrevFile(inc) {\n        if (inc !== -1 && inc !== +1) {\n            throw new Error(\"Illegal argument: inc = \" + inc);\n        }\n        \n        if (_currentDocument) {\n            var mruI = findInWorkingSet(_currentDocument.file.fullPath, _workingSetMRUOrder);\n            if (mruI === -1) {\n                // If doc not in working set, return most recent working set item\n                if (_workingSetMRUOrder.length > 0) {\n                    return _workingSetMRUOrder[0];\n                }\n            } else {\n                // If doc is in working set, return next/prev item with wrap-around\n                var newI = mruI + inc;\n                if (newI >= _workingSetMRUOrder.length) {\n                    newI = 0;\n                } else if (newI < 0) {\n                    newI = _workingSetMRUOrder.length - 1;\n                }\n                \n                return _workingSetMRUOrder[newI];\n            }\n        }\n        \n        // If no doc open or working set empty, there is no \"next\" file\n        return null;\n    }\n    \n    \n    /**\n     * @private\n     * Preferences callback. Saves the document file paths for the working set.\n     */\n    function _savePreferences() {\n\n        if (_isProjectChanging) {\n            return;\n        }\n        \n        // save the working set file paths\n        var files       = [],\n            isActive    = false,\n            workingSet  = getWorkingSet(),\n            currentDoc  = getCurrentDocument(),\n            projectRoot = ProjectManager.getProjectRoot();\n\n        if (!projectRoot) {\n            return;\n        }\n\n        workingSet.forEach(function (file, index) {\n            // flag the currently active editor\n            isActive = currentDoc && (file.fullPath === currentDoc.file.fullPath);\n\n            files.push({\n                file: file.fullPath,\n                active: isActive\n            });\n        });\n\n        // append file root to make file list unique for each project\n        _prefs.setValue(\"files_\" + projectRoot.fullPath, files);\n    }\n\n    /**\n     * @private\n     * Handle beforeProjectClose event\n     */\n    function _beforeProjectClose() {\n        _savePreferences();\n\n        // When app is shutdown via shortcut key, the command goes directly to the\n        // app shell, so we can't reliably fire the beforeProjectClose event on\n        // app shutdown. To compensate, we listen for currentDocumentChange,\n        // workingSetAdd, and workingSetRemove events so that the prefs for\n        // last project used get updated. But when switching projects, after\n        // the beforeProjectChange event gets fired, DocumentManager.closeAll()\n        // causes workingSetRemove event to get fired and update the prefs to an empty\n        // list. So, temporarily (until projectOpen event) disallow saving prefs.\n        _isProjectChanging = true;\n    }\n\n    /**\n     * @private\n     * Initializes the working set.\n     */\n    function _projectOpen() {\n        _isProjectChanging = false;\n        \n        // file root is appended for each project\n        var projectRoot = ProjectManager.getProjectRoot(),\n            files = _prefs.getValue(\"files_\" + projectRoot.fullPath);\n\n        if (!files) {\n            return;\n        }\n\n        var filesToOpen = [],\n            activeFile;\n\n        // Add all files to the working set without verifying that\n        // they still exist on disk (for faster project switching)\n        files.forEach(function (value, index) {\n            filesToOpen.push(new NativeFileSystem.FileEntry(value.file));\n            if (value.active) {\n                activeFile = value.file;\n            }\n        });\n        addListToWorkingSet(filesToOpen);\n\n        // Initialize the active editor\n        if (!activeFile && _workingSet.length > 0) {\n            activeFile = _workingSet[0].fullPath;\n        }\n\n        if (activeFile) {\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: activeFile });\n        }\n    }\n\n\n    // Define public API\n    exports.Document = Document;\n    exports.getCurrentDocument = getCurrentDocument;\n    exports.getDocumentForPath = getDocumentForPath;\n    exports.getOpenDocumentForPath = getOpenDocumentForPath;\n    exports.getWorkingSet = getWorkingSet;\n    exports.findInWorkingSet = findInWorkingSet;\n    exports.getAllOpenDocuments = getAllOpenDocuments;\n    exports.setCurrentDocument = setCurrentDocument;\n    exports.addToWorkingSet = addToWorkingSet;\n    exports.addListToWorkingSet = addListToWorkingSet;\n    exports.removeFromWorkingSet = removeFromWorkingSet;\n    exports.getNextPrevFile = getNextPrevFile;\n    exports.beginDocumentNavigation = beginDocumentNavigation;\n    exports.finalizeDocumentNavigation = finalizeDocumentNavigation;\n    exports.closeFullEditor = closeFullEditor;\n    exports.closeAll = closeAll;\n    exports.notifyFileDeleted = notifyFileDeleted;\n\n    // Setup preferences\n    _prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID);\n    $(exports).bind(\"currentDocumentChange workingSetAdd workingSetAddList workingSetRemove workingSetRemoveList\", _savePreferences);\n    \n    // Performance measurements\n    PerfUtils.createPerfMeasurement(\"DOCUMENT_MANAGER_GET_DOCUMENT_FOR_PATH\", \"DocumentManager.getDocumentForPath()\");\n\n    // Handle project change events\n    $(ProjectManager).on(\"projectOpen\", _projectOpen);\n    $(ProjectManager).on(\"beforeProjectClose\", _beforeProjectClose);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/\n/*global $, define, brackets, FileError */\n\ndefine('utils/NativeApp',['require','exports','module','utils/Async'],function (require, exports, module) {\n    \n    \n    var Async = require(\"utils/Async\");\n\n    /**\n     * @private\n     * Map an fs error code to a FileError.\n     */\n    function _browserErrToFileError(err) {\n        if (err === brackets.fs.ERR_NOT_FOUND) {\n            return FileError.NOT_FOUND_ERR;\n        }\n        \n        // All other errors are mapped to the generic \"security\" error\n        return FileError.SECURITY_ERR;\n    }\n    \n    var liveBrowserOpenedPIDs = [];\n    var liveBrowserUserDataDir = \"\";\n\n    /** openLiveBrowser\n     *\n     * @param {string} url\n     * @return {$.Promise} \n     */\n    function openLiveBrowser(url, enableRemoteDebugging) {\n        var result = new $.Deferred();\n        \n        brackets.app.openLiveBrowser(url, enableRemoteDebugging, function onRun(err, pid) {\n            if (!err) {\n                liveBrowserOpenedPIDs.push(pid);\n                result.resolve(pid);\n            } else {\n                result.reject(_browserErrToFileError(err));\n            }\n        }, liveBrowserUserDataDir);\n        \n        return result.promise();\n    }\n    \n    /** closeLiveBrowser\n     *\n     * @return {$.Promise}\n     */\n    function closeLiveBrowser(pid) {\n        var result = new $.Deferred();\n        \n        if (isNaN(pid)) {\n            pid = 0;\n        }\n        console.log(\"calling to close: \" + pid);\n        brackets.app.closeLiveBrowser(function (err) {\n            console.log(\"called closing: \" + pid + \" with err: \" + err);\n            if (!err) {\n                var i = liveBrowserOpenedPIDs.indexOf(pid);\n                if (i !== -1) {\n                    liveBrowserOpenedPIDs.splice(i, 1);\n                }\n                result.resolve();\n            } else {\n                result.reject(_browserErrToFileError(err));\n            }\n        }, pid);\n        \n        return result.promise();\n    }\n    \n    /** closeAllLiveBrowsers\n     * Closes all the browsers that were tracked on open\n     * TODO: does not seem to work on Windows\n     * @return {$.Promise}\n     */\n    function closeAllLiveBrowsers() {\n        //make a copy incase the array is edited as we iterate\n        var closeIDs = liveBrowserOpenedPIDs.concat();\n        return Async.doSequentially(closeIDs, closeLiveBrowser, false);\n    }\n    \n    /** _setLiveBrowserUserDataDir\n     * For Unit Tests only, changes the default dir the browser use for it's user data\n     * @return {$.Promise}\n     */\n    function _setLiveBrowserUserDataDir(path) {\n        liveBrowserUserDataDir = path;\n    }\n    \n    /**\n     * Opens a URL in the system default browser\n     */\n    function openURLInDefaultBrowser(url) {\n        brackets.app.openURLInDefaultBrowser(function (err) {}, url);\n    }\n    \n\n    // Define public API\n    exports.openLiveBrowser = openLiveBrowser;\n    exports.closeLiveBrowser = closeLiveBrowser;\n    exports.closeAllLiveBrowsers = closeAllLiveBrowsers;\n    exports.openURLInDefaultBrowser = openURLInDefaultBrowser;\n    //API for Unit Tests\n    exports._setLiveBrowserUserDataDir = _setLiveBrowserUserDataDir;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, WebSocket, FileError, window, XMLHttpRequest */\n\n /**\n * Inspector manages the connection to Chrome/Chromium's remote debugger.\n * See inspector.html for the documentation of the remote debugger.\n *\n * # SETUP\n *\n * To enable remote debugging in Chrome or Chromium open either application\n * with the following parameters:\n *\n *   --enable-remote-debugger --remote-debugging-port=9222\n *\n * This will open an HTTP server on the specified port, which can be used to\n * browse the available remote debugger sessions. In general, every open\n * browser tab can host an individual remote debugger session. The\n * available interfaces can be exported by requesting:\n *\n *   http://127.0.0.1:9222/json\n *\n * The response is a JSON-formatted array that specifies all available remote\n * debugger sessions including the remote debugging web sockets.\n *\n * Inspector can connect directly to a web socket via `connect(socketURL)`, or\n * it can find the web socket that corresponds to the tab at the given URL and\n * connect to it via `connectToURL(url)`. The later returns a promise. To \n * disconnect use `disconnect()`.\n *\n * # EVENTS\n *\n * Inspector dispatches several connectivity-related events + all remote debugger\n * events (see below). Event handlers are attached via `on(event, function)` and\n * detached via `off(event, function)`.\n *\n *   `connect`    Inspector did successfully connect to the remote debugger\n *   `disconnect` Inspector did disconnect from the remote debugger\n *   `error`      Inspector encountered an error\n *   `message`    Inspector received a message from the remote debugger - this\n *                  provides a low-level entry point to remote debugger events\n *\n * # REMOTE DEBUGGER COMMANDS\n *\n * Commands are executed by calling `{Domain}.{Command}()` with the parameters\n * specified in the order of the remote debugger documentation. These command\n * functions are generated automatically at runtime from Inspector.json. The\n * actual implementation of these functions is found in\n * `_send(method, signature, varargs)`, which verifies, serializes, and\n * transmits the command to the remote debugger. If the last parameter of any\n * command function call is a function, it will be used as the callback.\n *\n * # REMOTE DEBUGGER EVENTS\n *\n * Debugger events are dispatched as regular events using {Domain}.{Event} as\n * the event name. The handler function will be called with a single parameter\n * that stores all returned values as an object.\n */\ndefine('LiveDevelopment/Inspector/Inspector',['require','exports','module'],function Inspector(require, exports, module) {\n    \n\n    // jQuery exports object for events\n    var $exports = $(exports);\n\n    var _messageId = 1; // id used for remote method calls, auto-incrementing\n    var _messageCallbacks = {}; // {id -> function} for remote method calls\n    var _socket; // remote debugger WebSocket\n    var _connectDeferred; // The deferred connect\n\n    /** Check a parameter value against the given signature\n     * This only checks for optional parameters, not types\n     * Type checking is complex because of $ref and done on the remote end anyways\n     * @param {signature}\n     * @param {value}\n     */\n    function _verifySignature(signature, value) {\n        if (value === undefined) {\n            console.assert(signature.optional === true, \"Missing argument: \" + signature.name);\n        }\n        return true;\n    }\n\n    /** Send a message to the remote debugger\n     * All passed arguments after the signature are passed on as parameters.\n     * If the last argument is a function, it is used as the callback function.\n     * @param {string} remote method\n     * @param {object} the method signature\n     */\n    function _send(method, signature, varargs) {\n        if (!_socket) {\n            // FUTURE: Our current implementation closes and re-opens an inspector connection whenever\n            // a new HTML file is selected. If done quickly enough, pending requests from the previous\n            // connection could come in before the new socket connection is established. For now we \n            // simply ignore this condition. \n            // This race condition will go away once we support multiple inspector connections and turn\n            // off auto re-opening when a new HTML file is selected.\n            return;\n        }\n\n        console.assert(_socket, \"You must connect to the WebSocket before sending messages.\");\n        var id, callback, args, i, params = {};\n\n        // extract the parameters, the callback function, and the message id\n        args = Array.prototype.slice.call(arguments, 2);\n        if (typeof args[args.length - 1] === \"function\") {\n            id = _messageId++;\n            _messageCallbacks[id] = args.pop();\n        } else {\n            id = 0;\n        }\n\n        // verify the parameters against the method signature\n        // this also constructs the params object of type {name -> value}\n        for (i in signature) {\n            if (_verifySignature(args[i], signature[i])) {\n                params[signature[i].name] = args[i];\n            }\n        }\n        _socket.send(JSON.stringify({ method: method, id: id, params: params }));\n    }\n\n    /** WebSocket did close */\n    function _onDisconnect() {\n        _socket = undefined;\n        $exports.triggerHandler(\"disconnect\");\n    }\n\n    /** WebSocket reported an error */\n    function _onError(error) {\n        $exports.triggerHandler(\"error\", [error]);\n    }\n\n    /** WebSocket did open */\n    function _onConnect() {\n        $exports.triggerHandler(\"connect\");\n    }\n\n    /** Received message from the WebSocket\n     * A message can be one of three things:\n     *   1. an error -> report it\n     *   2. the response to a previous command -> run the stored callback\n     *   3. an event -> trigger an event handler method\n     * @param {object} message\n     */\n    function _onMessage(message) {\n        var response = JSON.parse(message.data);\n        $exports.triggerHandler(\"message\", [response]);\n        if (response.error) {\n            $exports.triggerHandler(\"error\", [response.error]);\n        } else if (response.result) {\n            if (_messageCallbacks[response.id]) {\n                _messageCallbacks[response.id](response.result);\n            }\n        } else {\n            var domainAndMethod = response.method.split(\".\");\n            var domain = domainAndMethod[0];\n            var method = domainAndMethod[1];\n            $(exports[domain]).triggerHandler(method, response.params);\n        }\n    }\n\n\n    /** Public Functions *****************************************************/\n\n    /** Get the available debugger sockets from the remote debugger\n     * @param {string} host IP or name\n     * @param {integer} debugger port\n     */\n    function getAvailableSockets(host, port) {\n        if (!host) {\n            host = \"127.0.0.1\";\n        }\n        if (!port) {\n            port = 9222;\n        }\n        var def = new $.Deferred();\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"http://\" + host + \":\" + port + \"/json\");\n        request.onload = function onLoad() {\n            var sockets = JSON.parse(request.response);\n            def.resolve(sockets);\n        };\n        request.onerror = function onError() {\n            def.reject(request.response);\n        };\n        request.send(null);\n        return def.promise();\n    }\n\n    /** Register a handler to be called when the given event is triggered\n     * @param {string} event name\n     * @param {function} handler function\n     */\n    function on(name, handler) {\n        $exports.on(name, handler);\n    }\n\n    /** Remove the given or all event handler(s) for the given event or remove all event handlers\n     * @param {string} optional event name\n     * @param {function} optional handler function\n     */\n    function off(name, handler) {\n        $exports.off(name, handler);\n    }\n\n    /** Disconnect from the remote debugger WebSocket */\n    function disconnect() {\n        if (_socket) {\n            if (_socket.readyState === 1) {\n                _socket.close();\n            } else {\n                delete _socket.onmessage;\n                delete _socket.onopen;\n                delete _socket.onclose;\n                delete _socket.onerror;\n            }\n            _socket = undefined;\n        }\n    }\n\n    /** Connect to the remote debugger WebSocket at the given URL\n     * @param {string} WebSocket URL\n     */\n    function connect(socketURL) {\n        disconnect();\n        _socket = new WebSocket(socketURL);\n        _socket.onmessage = _onMessage;\n        _socket.onopen = _onConnect;\n        _socket.onclose = _onDisconnect;\n        _socket.onerror = _onError;\n    }\n\n    /** Connect to the remote debugger of the page that is at the given URL\n     * @param {string} url\n     */\n    function connectToURL(url) {\n        if (_connectDeferred) {\n            // reject an existing connection attempt\n            _connectDeferred.reject(\"CANCEL\");\n        }\n        var deferred = new $.Deferred();\n        _connectDeferred = deferred;\n        var promise = getAvailableSockets();\n        promise.done(function onGetAvailableSockets(response) {\n            if (deferred.isRejected()) {\n                return;\n            }\n            var i, page;\n            for (i in response) {\n                page = response[i];\n                if (page.webSocketDebuggerUrl && page.url.search(url) === 0) {\n                    connect(page.webSocketDebuggerUrl);\n                    deferred.resolve();\n                    return;\n                }\n            }\n            deferred.reject(FileError.ERR_NOT_FOUND); // Reject with a \"not found\" error\n        });\n        promise.fail(function onFail(err) {\n            deferred.reject(err);\n        });\n        return deferred.promise();\n    }\n\n    /** Check if the inspector is connected */\n    function connected() {\n        return _socket !== undefined;\n    }\n\n    /** Initialize the Inspector\n     * Read the Inspector.json configuration and define the command objects\n     * -> Inspector.domain.command()\n     */\n    function init(theConfig) {\n        exports.config = theConfig;\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"LiveDevelopment/Inspector/Inspector.json\");\n        request.onload = function onLoad() {\n            var InspectorJSON = JSON.parse(request.response);\n            var i, j, domain, domainDef, command;\n            for (i in InspectorJSON.domains) {\n                domain = InspectorJSON.domains[i];\n                exports[domain.domain] = {};\n                for (j in domain.commands) {\n                    command = domain.commands[j];\n                    exports[domain.domain][command.name] = _send.bind(undefined, domain.domain + \".\" + command.name, command.parameters);\n                }\n            }\n        };\n        request.send(null);\n    }\n\n    // Export public functions\n    exports.getAvailableSockets = getAvailableSockets;\n    exports.on = on;\n    exports.off = off;\n    exports.disconnect = disconnect;\n    exports.connect = connect;\n    exports.connectToURL = connectToURL;\n    exports.connected = connected;\n    exports.init = init;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, XMLHttpRequest */\n\n/**\n * RemoteAgent defines and provides an interface for custom remote functions\n * loaded from RemoteFunctions. Remote commands are executed via\n * `call(name, varargs)`.\n *\n * Remote events are dispatched as events on this object.\n */\ndefine('LiveDevelopment/Agents/RemoteAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector'],function RemoteAgent(require, exports, module) {\n    \n\n    var $exports = $(exports);\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _load; // deferred load\n    var _objectId; // the object id of the remote object\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"LiveDevelopment/Agents/RemoteFunctions.js\");\n        request.onload = function onLoad() {\n            var run = \"window._LD=\" + request.response + \"()\";\n            Inspector.Runtime.evaluate(run, function onEvaluate(res) {\n                console.assert(!res.wasThrown, res.result.description);\n                _objectId = res.result.objectId;\n                _load.resolve();\n            });\n        };\n        request.send(null);\n    }\n\n    // WebInspector Event: DOM.attributeModified\n    function _onAttributeModified(event, res) {\n        // res = {nodeId, name, value}\n        var matches = /^data-ld-(.*)/.exec(res.name);\n        if (matches) {\n            $exports.triggerHandler(matches[1], res);\n        }\n    }\n\n    /** Call a remote function\n     * The parameters are passed on to the remote functions. Nodes are resolved\n     * and sent as objectIds.\n     * @param {string} function name\n     */\n    function call(method, varargs) {\n        console.assert(_objectId, \"Attempted to call remote method without objectId set.\");\n        var args = Array.prototype.slice.call(arguments, 1);\n\n        // if the last argument is a function it is the callback function\n        var callback;\n        if (typeof args[args.length - 1] === \"function\") {\n            callback = args.pop();\n        }\n\n        // Resolve node parameters\n        var i;\n        for (i in args) {\n            if (args[i].nodeId) {\n                args[i] = args[i].resolve();\n            }\n        }\n        $.when.apply(undefined, args).then(function onResolvedAllNodes() {\n            var i, arg, params = [];\n            for (i in arguments) {\n                arg = args[i];\n                if (arg.objectId) {\n                    params.push({objectId: arg.objectId});\n                } else {\n                    params.push({value: arg});\n                }\n            }\n            Inspector.Runtime.callFunctionOn(_objectId, \"_LD.\" + method, params, undefined, callback);\n        });\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        $(Inspector.Page).on(\"loadEventFired.RemoteAgent\", _onLoadEventFired);\n        $(Inspector.DOM).on(\"attributeModified.RemoteAgent\", _onAttributeModified);\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Page).off(\".RemoteAgent\");\n        $(Inspector.DOM).off(\".RemoteAgent\");\n    }\n\n    // Export public functions\n    exports.call = call;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * DOMHelpers is a collection of functions used by the DOMAgent exports `eachNode(src, callback)`\n */\ndefine('LiveDevelopment/Agents/DOMHelpers',['require','exports','module'],function DOMHelpersModule(require, exports, module) {\n    \n\n    /** Test if the given character is a quote character\n     * {char} source character\n     * {char} escape (previous) character\n     * {char} quote character\n     */\n    function _isQuote(c, escape, quote) {\n        if (escape === \"\\\\\") {\n            return false;\n        }\n        if (quote !== undefined) {\n            return c === quote;\n        }\n        return c === \"\\\"\" || c === \"'\";\n    }\n\n    /** Remove quotes from the string and adjust escaped quotes\n     * @param {string} source string\n     */\n    function _removeQuotes(src) {\n        if (_isQuote(src[0]) && src[src.length - 1] === src[0]) {\n            var q = src[0];\n            src = src.substr(1, src.length - 2);\n            src = src.replace(\"\\\\\" + q, q);\n        }\n        return src;\n    }\n\n    /** Find the next match using several constraints\n     * @param {string} source string\n     * @param {string} or [{regex}, {length}] the match definition\n     * @param {integer} ignore characters before this offset\n     * @param {boolean} watch for quotes\n     * @param [{string},{string}] watch for comments\n     */\n    function _find(src, match, skip, quotes, comments) {\n        if (typeof match === \"string\") {\n            match = [match, match.length];\n        }\n        if (skip === undefined) {\n            skip = 0;\n        }\n        var i, activeQuote, isComment = false;\n        for (i = skip; i < src.length; i++) {\n            if (quotes && _isQuote(src[i], src[i - 1], activeQuote)) {\n                // starting quote\n                activeQuote = activeQuote ? undefined : src[i];\n            } else if (!activeQuote) {\n                if (comments && !isComment && src.substr(i, comments[0].length) === comments[0]) {\n                    // opening comment\n                    isComment = true;\n                    i += comments[0].length - 1;\n                } else if (isComment) {\n                    // we are commented\n                    if (src.substr(i, comments[1].length) === comments[1]) {\n                        isComment = false;\n                        i += comments[1].length - 1;\n                    }\n                } else if (src.substr(i, match[1]).search(match[0]) === 0) {\n                    // match\n                    return i;\n                }\n            }\n        }\n        return -1;\n    }\n\n    /** Callback iterator using `_find` */\n    function _findEach(src, match, quotes, comments, callback) {\n        var from = 0;\n        var to;\n        while (from < src.length) {\n            to = _find(src, match, from, quotes, comments);\n            if (to < 0) {\n                to = src.length;\n            }\n            callback(src.substr(from, to - from));\n            from = to + 1;\n        }\n    }\n\n    /** Find the next tag\n     * @param {string} source string\n     * @param {integer} ignore characters before this offset\n     */\n    function _findTag(src, skip) {\n        var from, to, inc;\n        from = _find(src, [/<[a-z!\\/]/, 2], skip);\n        if (from < 0) {\n            return null;\n        }\n        if (src.substr(from, 4) === \"<!--\") {\n            // html comments\n            to = _find(src, \"-->\", from + 4);\n            inc = 3;\n        } else if (src.substr(from, 7) === \"<script\") {\n            // script tag\n            to = _find(src, \"</script>\", from + 7);\n            inc = 9;\n        } else {\n            to = _find(src, \">\", from + 1, true);\n            inc = 1;\n        }\n        if (to < 0) {\n            return null;\n        }\n        return {from: from, length: to + inc - from};\n    }\n\n    /** Extract tag attributes from the given source of a single tag\n     * @param {string} source content\n     */\n    function _extractAttributes(content) {\n\n        // remove the node name and the closing bracket and optional slash\n        content = content.replace(/^<\\S+\\s*/, \"\");\n        content = content.replace(/\\s*\\/?>$/, \"\");\n        if (content.length === 0) {\n            return;\n        }\n\n        // go through the items and identify key value pairs split by =\n        var index, key, value;\n        var attributes = {};\n        _findEach(content, [/\\s/, 1], true, undefined, function each(item) {\n            index = item.search(\"=\");\n            if (index < 0) {\n                return;\n            }\n\n            // get the key\n            key = item.substr(0, index).trim();\n            if (key.length === 0) {\n                return;\n            }\n\n            // get the value\n            value = item.substr(index + 1).trim();\n            value = _removeQuotes(value);\n            attributes[key] = value;\n        });\n\n        return attributes;\n    }\n\n    /** Extract the node payload\n     * @param {string} source content\n     */\n    function extractPayload(content) {\n        var payload = {};\n\n        if (content[0] !== \"<\") {\n            // text\n            payload.nodeType = 3;\n            payload.nodeValue = content;\n        } else if (content.substr(0, 4) === \"<!--\") {\n            // comment\n            payload.nodeType = 8;\n            payload.nodeValue = content.substr(4, content.length - 7);\n        } else if (content[1] === \"!\") {\n            // doctype\n            payload.nodeType = 10;\n        } else {\n            // regular element\n            payload.nodeType = 1;\n            payload.nodeName = /^<([^>\\s]+)/.exec(content)[1].toUpperCase();\n            payload.attributes = _extractAttributes(content);\n\n            // closing node (/ at the beginning)\n            if (payload.nodeName[0] === \"/\") {\n                payload.nodeName = payload.nodeName.substr(1);\n                payload.closing = true;\n            }\n\n            // closed node (/ at the end)\n            if (content[content.length - 2] === \"/\") {\n                payload.closed = true;\n            }\n        }\n        return payload;\n    }\n\n    /** Split the source string into payloads representing individual nodes\n     * @param {string} source\n     * @param {function(payload)} callback\n     */\n    // split a string into individual node contents\n    function eachNode(src, callback) {\n        var index = 0;\n        var text, range, length, payload;\n        var x = 0;\n        while (index < src.length) {\n\n            // find the next tag\n            range = _findTag(src, index);\n            if (!range) {\n                range = { from: src.length, length: 0 };\n            }\n\n            // add the text before the tag\n            length = range.from - index;\n            if (length > 0) {\n                text = src.substr(index, length);\n                if (/\\S/.test(text)) {\n                    payload = extractPayload(text);\n                    payload.sourceOffset = index;\n                    payload.sourceLength = length;\n                    callback(payload);\n                }\n            }\n\n            // add the tag\n            if (range.length > 0) {\n                payload = extractPayload(src.substr(range.from, range.length));\n                payload.sourceOffset = range.from;\n                payload.sourceLength = range.length;\n                callback(payload);\n            }\n\n            // advance\n            index = range.from + range.length;\n        }\n    }\n\n    // Export public functions\n    exports.extractPayload = extractPayload;\n    exports.eachNode = eachNode;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * DOMNode represents a node in the DOM tree. It is constructed from a payload\n * similar to {DOM.Node} and supports all basic tree operations. If a node has\n * a nodeId it is registered with the `DOMAgent` via `addNode()`. The node's\n * sourceOffset and sourceLength is stored as its location and length. Nodes can\n * iterated using `each()` or `find()`. `dump` shows the entire tree on the console.\n */\ndefine('LiveDevelopment/Agents/DOMNode',['require','exports','module','LiveDevelopment/Agents/DOMHelpers'],function DOMNodeModule(require, exports, module) {\n    \n\n    var DOMHelpers = require(\"LiveDevelopment/Agents/DOMHelpers\");\n\n    /** Fill a string to the given length (used for debug output)\n     * @param {string} source string\n     * @param {integer} length\n     * @param {char} fill character\n     */\n    function _fill(string, length, c) {\n        if (c === undefined) {\n            c = \" \";\n        }\n        while (string.length < length) {\n            string += c;\n        }\n        return string;\n    }\n\n    /** Construct a find condition (used in `find` and `findParent`)\n     * The match can be a callback returning true or false, the node\n     * name or the node type.\n     * @param {function} or {string} or {number} match criteria\n     */\n    function _makeFindCondition(match) {\n        switch (typeof match) {\n        case \"function\":\n            return match;\n        case \"string\":\n            return function findCondition(name, node) {\n                return node.name === name;\n            }.bind(undefined, match.toUpperCase());\n        case \"number\":\n            return function findCondition(type, node) {\n                return node.type === type;\n            }.bind(undefined, match);\n        default:\n            console.error(\"Invalid find condition: \" + match);\n        }\n    }\n\n    /** Constructor\n     * @param {DOMAgent} the agent is passed to avoid circular relationships\n     * @param {DOM.Node} node payload\n     */\n    var DOMNode = function DOMNode(agent, payload) {\n        this.agent = agent;\n        this.children = [];\n        this.attributes = {};\n\n        // set the payload\n        if (typeof payload === \"string\") {\n            payload = DOMHelpers.extractPayload(payload);\n        }\n        if (payload) {\n            this.setPayload(payload);\n        }\n        this.agent.addNode(this);\n    };\n\n    var TYPE_ELEMENT = DOMNode.TYPE_ELEMENT = 1; // element node\n    var TYPE_ATTRIBUTE = DOMNode.TYPE_ATTRIBUTE = 2; // attribute node (unused)\n    var TYPE_TEXT = DOMNode.TYPE_TEXT = 3; // text node\n    var TYPE_COMMENT = DOMNode.TYPE_COMMENT = 8; // comment node <!-- -->\n    var TYPE_DOCUMENT = DOMNode.TYPE_DOCUMENT = 9; // document node <!DOCUMENT>\n\n    /** Remove a node */\n    DOMNode.prototype.remove = function remove() {\n        this.agent.removeNode(this);\n        if (this.parent) {\n            this.parent.removeChild(this);\n        }\n    };\n\n\n    /** Node Payload ***********************************************************/\n\n    /** Set the node payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.setPayload = function setPayload(payload) {\n        this.nodeId = payload.nodeId;\n        this.type = payload.nodeType;\n        if (payload.nodeName) {\n            this.name = payload.nodeName;\n        }\n        if (payload.nodeValue) {\n            this.value = payload.nodeValue;\n        }\n        this.attributes = {};\n        if (payload.attributes) {\n            var i, k, v;\n            for (i = 0; i < payload.attributes.length; i += 2) {\n                k = payload.attributes[i];\n                v = payload.attributes[i + 1];\n                this.attributes[k] = v;\n            }\n        }\n        if (payload.sourceOffset) {\n            this.location = payload.sourceOffset;\n        }\n        if (payload.sourceLength) {\n            this.length = payload.sourceLength;\n        } else {\n            if (this.value) {\n                this.length = this.value.length;\n            } else if (this.name) {\n                this.length = this.name.length + 2;\n            }\n        }\n        if (payload.children) {\n            this.setChildrenPayload(payload.children);\n        } else if (payload.childNodeCount) {\n            this.agent.requestChildNodes(this);\n        }\n    };\n\n    /** Create child nodes from the given payload\n     * @param [{DOM.Node}] payload of the children\n     */\n    DOMNode.prototype.setChildrenPayload = function setChildrenPayload(childrenPayload) {\n        var i, payload, node;\n        for (i in childrenPayload) {\n            payload = childrenPayload[i];\n            node = new DOMNode(this.agent, payload);\n            this.appendChild(node);\n        }\n    };\n\n    /** Construct the payload for this node */\n    DOMNode.prototype.payload = function payload() {\n        var res = { type: this.type };\n        if (this.nodeType === TYPE_ELEMENT) {\n            res.nodeName = this.name;\n        } else {\n            res.value = this.value;\n        }\n        return res;\n    };\n\n    /** Find the next node that matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.findParentForNextNodeMatchingPayload = function findParentForNextNodeMatchingPayload(payload) {\n        var parent = this.canHaveChildren() ? this : this.parent;\n        while (parent && !parent.matchesPayload(payload)) {\n            parent = parent.parent;\n        }\n        return parent;\n    };\n\n    /** Find the next node that matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.findNextNodeMatchingPayload = function findNextNodeMatchingPayload(payload) {\n        var next = this.nextNode();\n        while (next && !next.matchesPayload(payload)) {\n            next = next.nextNode();\n        }\n        return next;\n    };\n\n    /** Test if the node matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.matchesPayload = function matchesPayload(payload) {\n        var r = false;\n        if (this.type === payload.nodeType) {\n            switch (this.type) {\n            case 1:\n                r = this.name === payload.nodeName;\n                break;\n            case 3:\n                // TODO payload.nodeValue's HTML Entities must be decoded\n                // r = this.value === payload.nodeValue;\n                r = true;\n                break;\n            default:\n                r = true;\n            }\n        }\n        // Useful output for debugging this - do not remove\n        // console.debug(this.type + \",\" + this.name + \",\" + this.value + \" = \" + payload.nodeType + \",\" + payload.nodeName + \",\" + payload.value + \" -> \" + r);\n        return r;\n    };\n\n    /** Resolve the node and retrieve its objectId from the remote debugger */\n    DOMNode.prototype.resolve = function resolve() {\n        var def = new $.Deferred();\n        if (this.objectId) {\n            def.resolve(this);\n        } else if (!this.nodeId) {\n            def.reject();\n        } else {\n            this.agent.resolveNode(this, function onResolve(res) {\n                this.objectId = res.object.objectId;\n                def.resolve(this);\n            }.bind(this));\n        }\n        return def.promise();\n    };\n\n\n    /** Tree Operations ******************************************************/\n\n    /** Can the node have children? */\n    DOMNode.prototype.canHaveChildren = function canHaveChildren() {\n        return (this.type === 1 && !this.closed && !this.closing && this.nodeName !== \"LINK\");\n    };\n\n    /** Remove a child\n     * @param {DOMNode} child node to remove\n     */\n    DOMNode.prototype.removeChild = function removeChild(node) {\n        this.children.splice(this.indexOfChild(node), 1);\n        delete node.parent;\n    };\n\n    /** Insert a child node at the given index\n     * @param {DOMNode} node to insert\n     * @param {integer} optional index (node is appended if missing)\n     */\n    DOMNode.prototype.insertChildAt = function insertChildAt(node, index) {\n        if (node.parent) {\n            node.parent.removeChild(node);\n        }\n        if (!index || index < 0 || index > this.children.length) {\n            index = this.children.length;\n        }\n        this.children.splice(index, 0, node);\n        node.parent = this;\n        return node;\n    };\n\n    /** Append a child to this node\n     * @param {DOMNode} child node to append\n     */\n    DOMNode.prototype.appendChild = function appendChild(node) {\n        return this.insertChildAt(node);\n    };\n\n    /** Insert a child node after the given node\n     * @param {DOMNode} child node to insert\n     * @param {DOMNode} existing child node\n     */\n    DOMNode.prototype.insertChildAfter = function insertChildAfter(node, sibling) {\n        var index = this.indexOfChild(sibling);\n        if (index >= 0) {\n            index++;\n        }\n        return this.insertChildAt(node, index);\n    };\n\n    /** Insert a child node before the given node\n     * @param {DOMNode} child node to insert\n     * @param {DOMNode} existing child node\n     */\n    DOMNode.prototype.insertChildBefore = function insertChildBefore(node, sibling) {\n        var index = this.indexOfChild(sibling);\n        return this.insertChildAt(node, index);\n    };\n\n    /** Determine the index of a child node\n     * @param {DOMNode} child node\n     */\n    DOMNode.prototype.indexOfChild = function indexOfChild(node) {\n        if (!node) {\n            return -1;\n        }\n        var i;\n        for (i in this.children) {\n            if (this.children[i] === node) {\n                return parseInt(i, 0);\n            }\n        }\n        return -1;\n    };\n\n    /** Get the previous sibling */\n    DOMNode.prototype.previousSibling = function previousSibling() {\n        if (!this.parent) {\n            return null;\n        }\n        return this.parent.children[this.parent.indexOfChild(this) - 1];\n    };\n\n    /** Get the next sibling */\n    DOMNode.prototype.nextSibling = function nextSibling() {\n        if (!this.parent) {\n            return null;\n        }\n        return this.parent.children[this.parent.indexOfChild(this) + 1];\n    };\n\n    /** Get the previous node */\n    DOMNode.prototype.previousNode = function previousNode() {\n        var node = this.previousSibling();\n        if (node) {\n            if (node.children.length > 0) {\n                node = node.children[node.children.length - 1];\n            }\n        } else {\n            node = this.parent;\n        }\n        return node;\n    };\n\n    /** Get the next node */\n    DOMNode.prototype.nextNode = function nextNode() {\n        if (this.children.length > 0) {\n            // return the first child\n            return this.children[0];\n        }\n        // return this or any ancestor's next sibling\n        var node, parent = this;\n        while (parent) {\n            node = parent.nextSibling();\n            if (node) {\n                return node;\n            }\n            parent = parent.parent;\n        }\n        return null;\n    };\n\n    /** Traverse the tree\n     * @param {function({DOM.Node})} called for this node and all descendants\n     */\n    DOMNode.prototype.each = function each(callback) {\n        if (callback(this) === false) {\n            return false;\n        }\n        var i;\n        for (i in this.children) {\n            if (this.children[i].each(callback) === false) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    /** Find a node in the tree\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.find = function find(match) {\n        var findCondition = _makeFindCondition(match);\n        var node = null;\n        this.each(function each(n) {\n            if (findCondition(n)) {\n                node = n;\n                return false;\n            }\n        });\n        return node;\n    };\n\n    /** Find all nodes with the given find condition\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.findAll = function findAll(match) {\n        var nodes = [];\n        var findCondition = _makeFindCondition(match);\n        this.each(function each(node) {\n            if (findCondition(node)) {\n                nodes.push(node);\n            }\n        });\n        return nodes;\n    };\n\n    /** Iterate over all parent nodes\n     * @param {function({DOM.Node})} called for each ancestor\n     */\n    DOMNode.prototype.eachParent = function eachParent(callback) {\n        var node = this.parent;\n        while (node) {\n            if (callback(node) === false) {\n                return;\n            }\n            node = node.parent;\n        }\n        return null;\n    };\n\n    /** Find a parent node that matches the find condition\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.findParent = function findParent(findCondition) {\n        var theParent = null;\n        this.eachParent(function each(parent) {\n            if (findCondition(parent)) {\n                theParent = parent;\n                return false;\n            }\n        });\n        return theParent;\n    };\n\n    /** Find the root of the tree */\n    DOMNode.prototype.root = function root() {\n        var node = this;\n        while (node.parent) {\n            node = node.parent;\n        }\n        return node;\n    };\n\n\n   /** Node Info ***********************************************************/\n\n   /** Test if the given location is inside this node\n    * @param {integer} location\n    * @param {boolean} also include children\n    */\n    DOMNode.prototype.isAtLocation = function isAtLocation(location, includeChildren) {\n        if (includeChildren === undefined) {\n            includeChildren = true;\n        }\n        if (!this.location || location < this.location) {\n            return false;\n        }\n        var to;\n        if (includeChildren && this.closeLocation) {\n            to = this.closeLocation + this.closeLength;\n        } else {\n            to = this.location + this.length;\n        }\n        if (this.type === TYPE_TEXT) {\n            to += 1;\n        }\n        return location < to;\n    };\n\n    /** Test if this node is empty */\n    DOMNode.prototype.isEmpty = function isEmpty() {\n        return this.type === TYPE_TEXT && /^\\s*$/.test(this.value);\n    };\n\n    /** Debug Output */\n    DOMNode.prototype.toString = function toString() {\n        var r;\n        switch (this.type) {\n        case TYPE_ELEMENT:\n            r = \"<\" + this.name + \">\";\n            break;\n        case TYPE_ATTRIBUTE:\n            r = \"[ATTRIBUTE]\";\n            break;\n        case TYPE_TEXT:\n            r = this.value.replace(/\\s+/, \" \").substr(0, 40);\n            break;\n        case TYPE_COMMENT:\n            r = \"<!--\" + this.value.replace(/\\s+/, \" \").substr(0, 33) + \"-->\";\n            break;\n        case TYPE_DOCUMENT:\n            r = \"<!DOCTYPE>\";\n            break;\n        }\n        return r;\n    };\n\n    /** Detailed Debug Output */\n    DOMNode.prototype.dump = function dump(pre) {\n        if (pre === undefined) {\n            pre = \"\";\n        }\n        var r = pre + this.toString();\n        if (this.location) {\n            r = _fill(r, 60);\n            r += \" (\" + this.location + \",\" + (this.location + this.length) + \")\";\n            if (this.closeLocation) {\n                r += \" (\" + this.closeLocation + \",\" + (this.closeLocation + this.closeLength) + \")\";\n            }\n        }\n        if (this.nodeId) {\n            r = _fill(r, 80);\n            r += \" {\" + this.nodeId + \"}\";\n        }\n        console.info(r);\n        pre += \". \";\n        var i;\n        for (i in this.children) {\n            this.children[i].dump(pre);\n        }\n    };\n\n    return DOMNode;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, XMLHttpRequest */\n\n/**\n * DOMAgent constructs and maintains a tree of {DOMNode}s that represents the\n * rendered DOM tree in the remote browser. Nodes can be accessed by id or\n * location (source offset). To update the DOM tree in response to a change of\n * the source document (replace [from,to] with text) call\n * `applyChange(from, to, text)`.\n *\n * The DOMAgent triggers `getDocument` once it has loaded\n * the document.\n */\ndefine('LiveDevelopment/Agents/DOMAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/DOMNode','LiveDevelopment/Agents/DOMHelpers'],function DOMAgent(require, exports, module) {\n    \n\n    var $exports = $(exports);\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var DOMNode = require(\"LiveDevelopment/Agents/DOMNode\");\n    var DOMHelpers = require(\"LiveDevelopment/Agents/DOMHelpers\");\n\n    var _load; // {$.Deferred} load promise\n    var _idToNode; // {nodeId -> node}\n    var _pendingRequests; // {integer} number of pending requests before initial loading is complete\n\n    /** Get the last node before the given location\n     * @param {integer} location\n     */\n    function nodeBeforeLocation(location) {\n        var node;\n        exports.root.each(function each(n) {\n            if (!n.location || location < n.location) {\n                return true;\n            }\n            if (!node || node.location < n.location) {\n                node = n;\n            }\n        });\n        return node;\n    }\n\n    /** Get the element node that encloses the given location\n     * @param {location}\n     */\n    function allNodesAtLocation(location) {\n        var nodes = [];\n        exports.root.each(function each(n) {\n            if (n.type === DOMNode.TYPE_ELEMENT && n.isAtLocation(location)) {\n                nodes.push(n);\n            }\n        });\n        return nodes;\n    }\n\n    /** Get the node at the given location\n     * @param {location}\n     */\n    function nodeAtLocation(location) {\n        return exports.root.find(function each(n) {\n            return n.isAtLocation(location, false);\n        });\n    }\n\n    /** Find the node for the given id\n     * @param {DOMNode} node\n     */\n    function nodeWithId(nodeId) {\n        return _idToNode[nodeId];\n    }\n\n    /** Update the node index\n     * @param {DOMNode} node\n     */\n    function removeNode(node) {\n        if (node.nodeId) {\n            delete _idToNode[node.nodeId];\n        }\n    }\n\n    /** Update the node index\n     * @param {DOMNode} node\n     */\n    function addNode(node) {\n        if (node.nodeId) {\n            _idToNode[node.nodeId] = node;\n        }\n    }\n\n    /** Request the child nodes for a node\n     * @param {DOMNode} node\n     */\n    function requestChildNodes(node) {\n        if (_pendingRequests >= 0) {\n            _pendingRequests++;\n        }\n        Inspector.DOM.requestChildNodes(node.nodeId);\n    }\n\n    /** Resolve a node\n     * @param {DOMNode} node\n     */\n    function resolveNode(node, callback) {\n        console.assert(node.nodeId, \"Attempted to resolve node without id\");\n        Inspector.DOM.resolveNode(node.nodeId, callback);\n    }\n\n    /** Eliminate the query string from a URL\n     * @param {string} URL\n     */\n    function _cleanURL(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Map the DOM document to the source text\n     * @param {string} source\n     */\n    function _mapDocumentToSource(source) {\n        var node = exports.root;\n        DOMHelpers.eachNode(source, function each(payload) {\n            if (!node) {\n                return true;\n            }\n            if (payload.closing) {\n                var parent = node.findParentForNextNodeMatchingPayload(payload);\n                if (!parent) {\n                    return console.warn(\"Matching Parent not at \" + payload.sourceOffset + \" (\" + payload.nodeName + \")\");\n                }\n                parent.closeLocation = payload.sourceOffset;\n                parent.closeLength = payload.sourceLength;\n            } else {\n                var next = node.findNextNodeMatchingPayload(payload);\n                if (!next) {\n                    return console.warn(\"Skipping Source Node at \" + payload.sourceOffset);\n                }\n                node = next;\n                node.location = payload.sourceOffset;\n                node.length = payload.sourceLength;\n                if (payload.closed) {\n                    node.closed = payload.closed;\n                }\n            }\n        });\n    }\n\n    /** Load the source document and match it with the DOM tree*/\n    function _onFinishedLoadingDOM() {\n        console.assert(exports.url.substr(0, 7) === \"file://\", \"Can only load file urls\");\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", exports.url);\n        request.onload = function onLoad() {\n            _mapDocumentToSource(request.response);\n            _load.resolve();\n        };\n        request.onerror = function onError() {\n            _load.reject(\"Could not load source file at \" + exports.url);\n        };\n        request.send(null);\n    }\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        Inspector.DOM.getDocument(function onGetDocument(res) {\n            $exports.triggerHandler(\"getDocument\", res);\n            // res = {root}\n            _idToNode = {};\n            _pendingRequests = 0;\n            exports.root = new DOMNode(exports, res.root);\n        });\n    }\n\n    // WebInspector Event: Page.frameNavigated\n    function _onFrameNavigated(event, res) {\n        // res = {frame}\n        exports.url = _cleanURL(res.frame.url);\n    }\n\n     // WebInspector Event: DOM.documentUpdated\n    function _onDocumentUpdated(event, res) {\n        // res = {}\n    }\n\n    // WebInspector Event: DOM.setChildNodes\n    function _onSetChildNodes(event, res) {\n        // res = {parentId, nodes}\n        var node = nodeWithId(res.parentId);\n        node.setChildrenPayload(res.nodes);\n        if (_pendingRequests > 0 && --_pendingRequests === 0) {\n            _onFinishedLoadingDOM();\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeCountUpdated\n    function _onChildNodeCountUpdated(event, res) {\n        // res = {nodeId, childNodeCount}\n        if (res.nodeId > 0) {\n            Inspector.DOM.requestChildNodes(res.nodeId);\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeInserted\n    function _onChildNodeInserted(event, res) {\n        // res = {parentNodeId, previousNodeId, node}\n        if (res.node.nodeId > 0) {\n            var parent = nodeWithId(res.parentNodeId);\n            var previousNode = nodeWithId(res.previousNodeId);\n            var node = new DOMNode(exports, res.node);\n            parent.insertChildAfter(node, previousNode);\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeRemoved\n    function _onChildNodeRemoved(event, res) {\n        // res = {parentNodeId, nodeId}\n        if (res.nodeId > 0) {\n            var node = nodeWithId(res.nodeId);\n            node.remove();\n        }\n    }\n\n    /** Apply a change\n     * @param {integer} start offset of the change\n     * @param {integer} end offset of the change\n     * @param {string} change text\n     */\n    function applyChange(from, to, text) {\n        var delta = from - to + text.length;\n        var node = nodeAtLocation(from);\n\n        // insert a text node\n        if (!node) {\n            if (!(/^\\s*$/).test(text)) {\n                console.warn(\"Inserting nodes not supported.\");\n                node = nodeBeforeLocation(from);\n            }\n        } else if (node.type === 3) {\n            // update a text node\n            var value = node.value.substr(0, from - node.location);\n            value += text;\n            value += node.value.substr(to - node.location);\n            node.value = value;\n            Inspector.DOM.setNodeValue(node.nodeId, node.value);\n        } else {\n            console.warn(\"Changing non-text nodes not supported.\");\n        }\n\n        // adjust the location of all nodes after the change\n        if (node) {\n            node.length += delta;\n            exports.root.each(function each(n) {\n                if (n.location > node.location) {\n                    n.location += delta;\n                }\n            });\n        }\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        $(Inspector.Page)\n            .on(\"frameNavigated.DOMAgent\", _onFrameNavigated)\n            .on(\"loadEventFired.DOMAgent\", _onLoadEventFired);\n        $(Inspector.DOM)\n            .on(\"documentUpdated.DOMAgent\", _onDocumentUpdated)\n            .on(\"setChildNodes.DOMAgent\", _onSetChildNodes)\n            .on(\"childNodeCountUpdated.DOMAgent\", _onChildNodeCountUpdated)\n            .on(\"childNodeInserted.DOMAgent\", _onChildNodeInserted)\n            .on(\"childNodeRemoved.DOMAgent\", _onChildNodeRemoved);\n        Inspector.Page.enable();\n        Inspector.Page.reload();\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Page).off(\".DOMAgent\");\n        $(Inspector.DOM).off(\".DOMAgent\");\n    }\n\n    // Export private functions\n    exports.nodeBeforeLocation = nodeBeforeLocation;\n    exports.allNodesAtLocation = allNodesAtLocation;\n    exports.nodeAtLocation = nodeAtLocation;\n    exports.nodeWithId = nodeWithId;\n    exports.removeNode = removeNode;\n    exports.addNode = addNode;\n    exports.requestChildNodes = requestChildNodes;\n    exports.applyChange = applyChange;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * HighlightAgent dispatches events for highlight requests from in-browser\n * highlight requests, and allows highlighting nodes and rules in the browser.\n *\n * Trigger \"highlight\" when a node should be highlighted\n */\ndefine('LiveDevelopment/Agents/HighlightAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/DOMAgent'],function HighlightAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n\n    var _highlight; // active highlight\n\n    // Remote Event: Highlight\n    function _onRemoteHighlight(event, res) {\n        var node;\n        if (res.value === \"1\") {\n            node = DOMAgent.nodeWithId(res.nodeId);\n        }\n        $(exports).triggerHandler(\"highlight\", node);\n    }\n\n    /** Hide in-browser highlighting */\n    function hide() {\n        switch (_highlight.type) {\n        case \"node\":\n            Inspector.DOM.hideHighlight();\n            break;\n        case \"css\":\n            RemoteAgent.call(\"hideHighlight\");\n            break;\n        }\n        _highlight = {};\n    }\n\n    /** Highlight a single node using DOM.highlightNode\n     * @param {DOMNode} node\n     */\n    function node(n) {\n        if (!Inspector.config.highlight) {\n            return;\n        }\n\n        // go to the parent of a text node\n        if (n && n.type === 3) {\n            n = n.parent;\n        }\n\n        // node cannot be highlighted\n        if (!n || !n.nodeId || n.type !== 1) {\n            return hide();\n        }\n\n        // node is already highlighted\n        if (_highlight.type === \"node\" && _highlight.ref === n.nodeId) {\n            return;\n        }\n\n        // highlight the node\n        _highlight = {type: \"node\", ref: n.nodeId};\n        Inspector.DOM.highlightNode(n.nodeId, Inspector.config.highlightConfig);\n    }\n\n    /** Highlight all nodes affected by a CSS rule\n     * @param {string} rule selector\n     */\n    function rule(name) {\n        if (_highlight.rule === name) {\n            return;\n        }\n        hide();\n        _highlight = {type: \"css\", ref: name};\n        RemoteAgent.call(\"highlightRule\", name);\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _highlight = {};\n        $(RemoteAgent).on(\"highlight.HighlightAgent\", _onRemoteHighlight);\n    }\n\n    /** Clean up */\n    function unload() {\n        $(RemoteAgent).off(\".HighlightAgent\");\n    }\n\n    // Export public functions\n    exports.hide = hide;\n    exports.node = node;\n    exports.rule = rule;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * HTMLDocument manages a single HTML source document\n *\n * # EDITING\n *\n * Editing the document will cause the corresponding node to be updated\n * by calling `applyChanges` on the DOMAgent. This will only work for\n * altering text nodes and will break when attempting to change DOM elements\n * or inserting or deleting nodes.\n *\n * # HIGHLIGHTING\n *\n * HTMLDocument supports highlighting nodes from the HighlightAgent and\n * highlighting the DOMNode corresponding to the cursor position in the\n * editor.\n */\ndefine('LiveDevelopment/Documents/HTMLDocument',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/HighlightAgent'],function HTMLDocumentModule(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var HighlightAgent = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /** Constructor\n     *\n     * @param Document the source document from Brackets\n     */\n    var HTMLDocument = function HTMLDocument(doc, editor) {\n        this.doc = doc;\n        this.editor = editor;\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onChange = this.onChange.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        $(HighlightAgent).on(\"highlight\", this.onHighlight);\n        $(this.editor).on(\"change\", this.onChange);\n        $(this.editor).on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n    };\n\n    /** Close the document */\n    HTMLDocument.prototype.close = function close() {\n        $(HighlightAgent).off(\"highlight\", this.onHighlight);\n        $(this.editor).off(\"change\", this.onChange);\n        $(this.editor).off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity by the editor */\n    HTMLDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n        var codeMirror = this.editor._codeMirror;\n        if (Inspector.config.highlight) {\n            var location = codeMirror.indexFromPos(codeMirror.getCursor());\n            var node = DOMAgent.allNodesAtLocation(location).pop();\n            HighlightAgent.node(node);\n        }\n    };\n\n    /** Triggered on change by the editor */\n    HTMLDocument.prototype.onChange = function onChange(event, editor, change) {\n        var codeMirror = this.editor._codeMirror;\n        while (change) {\n            var from = codeMirror.indexFromPos(change.from);\n            var to = codeMirror.indexFromPos(change.to);\n            var text = change.text.join(\"\\n\");\n            DOMAgent.applyChange(from, to, text);\n            change = change.next;\n        }\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    HTMLDocument.prototype.onHighlight = function onHighlight(node) {\n        if (!node || !node.location) {\n            if (this._highlight) {\n                this._highlight.clear();\n                delete this._highlight;\n            }\n            return;\n        }\n        var codeMirror = this.editor._codeMirror;\n        var to, from = codeMirror.posFromIndex(node.location);\n        if (node.closeLocation) {\n            to = node.closeLocation + node.closeLength;\n        } else {\n            to = node.location + node.length;\n        }\n        to = codeMirror.posFromIndex(to);\n        if (this._highlight) {\n            this._highlight.clear();\n        }\n        this._highlight = codeMirror.markText(from, to, \"highlight\");\n    };\n\n    // Export the class\n    module.exports = HTMLDocument;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, PathUtils */\n\n/**\n * CSSAgent keeps track of loaded style sheets and allows reloading them\n * from a {Document}.\n */\n\ndefine('LiveDevelopment/Agents/CSSAgent',['require','exports','module','thirdparty/path-utils/path-utils.min','LiveDevelopment/Inspector/Inspector'],function CSSAgent(require, exports, module) {\n    \n\n    require(\"thirdparty/path-utils/path-utils.min\");\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _load; // {$.Deferred} load promise\n    var _urlToStyle; // {url -> loaded} style definition\n\n    /** \n     * Create a canonicalized version of the given URL, stripping off query strings and hashes.\n     * @param {string} url the URL to canonicalize\n     * @return the canonicalized URL\n     */\n    function _canonicalize(url) {\n        return PathUtils.parseUrl(url).hrefNoSearch;\n    }\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        _urlToStyle = {};\n        Inspector.CSS.getAllStyleSheets(function onGetAllStyleSheets(res) {\n            var i, header;\n            for (i in res.headers) {\n                header = res.headers[i];\n                _urlToStyle[_canonicalize(header.sourceURL)] = header;\n            }\n            _load.resolve();\n        });\n    }\n\n    /** Get a style sheet for a url\n     * @param {string} url\n     */\n    function styleForURL(url) {\n        return _urlToStyle[_canonicalize(url)];\n    }\n\n    /** Get a list of all loaded stylesheet files by URL */\n    function getStylesheetURLs() {\n        var urls = [], url;\n        for (url in _urlToStyle) {\n            if (_urlToStyle.hasOwnProperty(url)) {\n                urls.push(url);\n            }\n        }\n        return urls;\n    }\n\n    /** Reload a CSS style sheet from a document\n     * @param {Document} document\n     */\n    function reloadCSSForDocument(doc) {\n        var style = styleForURL(doc.url);\n        console.assert(style, \"Style Sheet for document not loaded: \" + doc.url);\n        Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());\n    }\n\n    /** Empties a CSS style sheet given a document that has been deleted\n     * @param {Document} document\n     */\n    function clearCSSForDocument(doc) {\n        var style = styleForURL(doc.url);\n        console.assert(style, \"Style Sheet for document not loaded: \" + doc.url);\n        Inspector.CSS.setStyleSheetText(style.styleSheetId, \"\");\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        $(Inspector.Page).on(\"loadEventFired.CSSAgent\", _onLoadEventFired);\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Page).off(\".CSSAgent\");\n    }\n\n    // Export public functions\n    exports.styleForURL = styleForURL;\n    exports.getStylesheetURLs = getStylesheetURLs;\n    exports.reloadCSSForDocument = reloadCSSForDocument;\n    exports.clearCSSForDocument = clearCSSForDocument;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * CSSDocument manages a single CSS source document\n *\n * # EDITING\n *\n * Editing the document will cause the style sheet to be reloaded via the\n * CSSAgent, which immediately updates the appearance of the rendered document.\n *\n * # HIGHLIGHTING\n *\n * CSSDocument supports highlighting nodes from the HighlightAgent and\n * highlighting all DOMNode corresponding to the rule at the cursor position\n * in the editor.\n *\n * # EVENTS\n *\n * CSSDocument dispatches these events:\n *  deleted - When the file for the underlying Document has been deleted. The\n *      2nd argument to the listener will be this CSSDocument.\n */\ndefine('LiveDevelopment/Documents/CSSDocument',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/CSSAgent','LiveDevelopment/Agents/HighlightAgent'],function CSSDocumentModule(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var CSSAgent = require(\"LiveDevelopment/Agents/CSSAgent\");\n    var HighlightAgent = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /** Constructor\n     *\n     * @param Document the source document from Brackets\n     */\n    var CSSDocument = function CSSDocument(doc, editor, inspector) {\n        this.doc = doc;\n\n        // FUTURE: Highlighting is currently disabled, since this code doesn't yet know\n        // how to deal with different editors pointing at the same document.\n/*\n        this.editor = editor;\n        this._highlight = [];\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        $(HighlightAgent).on(\"highlight\", this.onHighlight);\n*/\n\n        // Add a ref to the doc since we're listening for change events\n        this.doc.addRef();\n        this.onChange = this.onChange.bind(this);\n        this.onDeleted = this.onDeleted.bind(this);\n        $(this.doc).on(\"change\", this.onChange);\n        $(this.doc).on(\"deleted\", this.onDeleted);\n\n/*\n        $(this.editor).on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n*/\n\n        // get the style sheet\n        this.styleSheet = CSSAgent.styleForURL(this.doc.url);\n\n        // WebInspector Command: CSS.getStyleSheet\n        Inspector.CSS.getStyleSheet(this.styleSheet.styleSheetId, function callback(res) {\n            // res = {styleSheet}\n            this.rules = res.styleSheet.rules;\n        }.bind(this));\n\n        // If the CSS document is dirty, push the changes into the browser now\n        if (doc.isDirty) {\n            CSSAgent.reloadCSSForDocument(this.doc);\n        }\n    };\n\n    /** Get the browser version of the StyleSheet object */\n    CSSDocument.prototype.getStyleSheetFromBrowser = function getStyleSheetFromBrowser() {\n        var deferred = new $.Deferred();\n\n        // WebInspector Command: CSS.getStyleSheet\n        Inspector.CSS.getStyleSheet(this.styleSheet.styleSheetId, function callback(res) {\n            // res = {styleSheet}\n            if (res.styleSheet) {\n                deferred.resolve(res.styleSheet);\n            } else {\n                deferred.reject();\n            }\n        });\n\n        return deferred.promise();\n    };\n\n    /** Get the browser version of the source */\n    CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() {\n        var deferred = new $.Deferred();\n\n        this.getStyleSheetFromBrowser().done(function onDone(styleSheet) {\n            deferred.resolve(styleSheet.text);\n        }).fail(function onFail() {\n            deferred.reject();\n        });\n\n        return deferred.promise();\n    };\n\n    /** Close the document */\n    CSSDocument.prototype.close = function close() {\n        $(this.doc).off(\"change\", this.onChange);\n        $(this.doc).off(\"deleted\", this.onDeleted);\n        this.doc.releaseRef();\n/*\n        $(HighlightAgent).off(\"highlight\", this.onHighlight);\n        $(this.editor).off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n*/\n    };\n\n    // find a rule in the given rules\n    CSSDocument.prototype.ruleAtLocation = function ruleAtLocation(location) {\n        var i, rule;\n        for (i in this.rules) {\n            rule = this.rules[i];\n            if (rule.selectorRange.start <= location && location <= rule.style.range.end) {\n                return rule;\n            }\n        }\n        return null;\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity of the editor */\n    CSSDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n        if (Inspector.config.highlight) {\n            var codeMirror = this.editor._codeMirror;\n            var location = codeMirror.indexFromPos(codeMirror.getCursor());\n            var rule = this.ruleAtLocation(location);\n            if (rule) {\n                HighlightAgent.rule(rule.selectorText);\n            } else {\n                HighlightAgent.hide();\n            }\n        }\n    };\n\n    /** Triggered whenever the Document is edited */\n    CSSDocument.prototype.onChange = function onChange(event, editor, change) {\n        // brute force: update the CSS\n        CSSAgent.reloadCSSForDocument(this.doc);\n    };\n    /** Triggered if the Document's file is deleted */\n    CSSDocument.prototype.onDeleted = function onDeleted(event, editor, change) {\n        // clear the CSS\n        CSSAgent.clearCSSForDocument(this.doc);\n\n        // shut down, since our Document is now dead\n        this.close();\n        $(this).triggerHandler(\"deleted\", [this]);\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    CSSDocument.prototype.onHighlight = function onHighlight(node) {\n        // clear an existing highlight\n        var i;\n        for (i in this._highlight) {\n            this._highlight[i].clear();\n        }\n        this._highlight = [];\n        if (!node || !node.location) {\n            return;\n        }\n\n        // WebInspector Command: CSS.getMatchedStylesForNode\n        Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) {\n            // res = {matchedCSSRules, pseudoElements, inherited}\n            var codeMirror = this.editor._codeMirror;\n            var i, rule, from, to;\n            for (i in res.matchedCSSRules) {\n                rule = res.matchedCSSRules[i];\n                if (rule.ruleId && rule.ruleId.styleSheetId === this.styleSheet.styleSheetId) {\n                    from = codeMirror.posFromIndex(rule.selectorRange.start);\n                    to = codeMirror.posFromIndex(rule.style.range.end);\n                    this._highlight.push(codeMirror.markText(from, to, \"highlight\"));\n                }\n            }\n        }.bind(this));\n    };\n\n    // Export the class\n    module.exports = CSSDocument;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * ScriptAgent tracks all executed scripts, defines internal breakpoints, and\n * interfaces with the remote debugger.\n */\ndefine('LiveDevelopment/Agents/ScriptAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent'],function ScriptAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n\n    var _load; // the load promise\n    var _urlToScript; // url -> script info\n    var _idToScript; // id -> script info\n    var _insertTrace; // the last recorded trace of a DOM insertion\n\n    /** Add a call stack trace to a node\n     * @param {integer} node id\n     * @param [{Debugger.CallFrame}] call stack\n     */\n    function _addTraceToNode(nodeId, trace) {\n        var node = DOMAgent.nodeWithId(nodeId);\n        node.trace = trace;\n    }\n\n    // TODO: should the parameter to this be an ID rather than a URL?\n    /** Get the script information for a given url\n     * @param {string} url\n     */\n    function scriptWithId(url) {\n        return _idToScript[url];\n    }\n\n    // TODO: Strip off query/hash strings from URL (see CSSAgent._canonicalize())\n    /** Get the script information for a given url\n     * @param {string} url\n     */\n    function scriptForURL(url) {\n        return _urlToScript[url];\n    }\n\n    // DOMAgent Event: Document root loaded\n    function _onGetDocument(event, res) {\n        Inspector.DOMDebugger.setDOMBreakpoint(res.root.nodeId, \"subtree-modified\");\n        _load.resolve();\n    }\n\n    // WebInspector Event: DOM.childNodeInserted\n    function _onChildNodeInserted(event, res) {\n        // res = {parentNodeId, previousNodeId, node}\n        if (_insertTrace) {\n            var node = DOMAgent.nodeWithId(res.node.nodeId);\n            node.trace = _insertTrace;\n            _insertTrace = undefined;\n        }\n    }\n\n    // TODO: Strip off query/hash strings from URL (see CSSAgent._canonicalize())\n    // WebInspector Event: Debugger.scriptParsed\n    function _onScriptParsed(event, res) {\n        // res = {scriptId, url, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL}\n        _idToScript[res.scriptId] = res;\n        _urlToScript[res.url] = res;\n    }\n\n    // WebInspector Event: Debugger.scriptFailedToParse\n    function _onScriptFailedToParse(event, res) {\n        // res = {url, scriptSource, startLine, errorLine, errorMessage}\n    }\n\n    // WebInspector Event: Debugger.paused\n    function _onPaused(event, res) {\n        // res = {callFrames, reason, data}\n        switch (res.reason) {\n\n        // Exception\n        case \"exception\":\n            Inspector.Debugger.resume();\n            // var callFrame = res.callFrames[0];\n            // var script = scriptWithId(callFrame.location.scriptId);\n            break;\n\n        // DOMBreakpoint\n        case \"DOM\":\n            Inspector.Debugger.resume();\n            if (res.data.type === \"subtree-modified\" && res.data.insertion === true) {\n                _insertTrace = res.callFrames;\n            }\n            break;\n        }\n\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _urlToScript = {};\n        _idToScript = {};\n        _load = new $.Deferred();\n        Inspector.Debugger.enable();\n        Inspector.Debugger.setPauseOnExceptions(\"uncaught\");\n        $(DOMAgent).on(\"getDocument.ScriptAgent\", _onGetDocument);\n        $(Inspector.Debugger)\n            .on(\"scriptParsed.ScriptAgent\", _onScriptParsed)\n            .on(\"scriptFailedToParse.ScriptAgent\", _onScriptFailedToParse)\n            .on(\"paused.ScriptAgent\", _onPaused);\n        $(Inspector.DOM).on(\"childNodeInserted.ScriptAgent\", _onChildNodeInserted);\n        return _load;\n    }\n\n    /** Clean up */\n    function unload() {\n        $(DOMAgent).off(\".ScriptAgent\");\n        $(Inspector.Debugger).off(\".ScriptAgent\");\n        $(Inspector.DOM).off(\".ScriptAgent\");\n    }\n\n    // Export public functions\n    exports.scriptWithId = scriptWithId;\n    exports.scriptForURL = scriptForURL;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * JSDocument manages a single JavaScript source document\n *\n * # EDITING\n *\n * Editing the document will cause the script to be reloaded via the\n * ScriptAgent, which updates the implementation of all functions without\n * loosing any state. To support redrawing canvases, jQuery must be loaded\n * and a rerender method must be attached to every canvas that clears and\n * renders the canvas.\n *\n * # HIGHLIGHTING\n *\n * JSDocument supports highlighting nodes from the HighlightAgent. Support\n * for highlighting the nodes that were created / touched by the current\n * line is missing.\n */\ndefine('LiveDevelopment/Documents/JSDocument',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/ScriptAgent','LiveDevelopment/Agents/HighlightAgent'],function JSDocumentModule(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var ScriptAgent = require(\"LiveDevelopment/Agents/ScriptAgent\");\n    var HighlightAgent = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /** Constructor\n     *\n     * @param {Document} the source document\n     */\n    var JSDocument = function JSDocument(doc, editor) {\n        this.doc = doc;\n        this.editor = editor;\n        this.script = ScriptAgent.scriptForURL(this.doc.url);\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onChange = this.onChange.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        $(HighlightAgent).on(\"highlight\", this.onHighlight);\n        $(this.editor).on(\"change\", this.onChange);\n        $(this.editor).on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n    };\n\n    /** Close the document */\n    JSDocument.prototype.close = function close() {\n        $(HighlightAgent).off(\"highlight\", this.onHighlight);\n        $(this.editor).off(\"change\", this.onChange);\n        $(this.editor).off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity by the editor */\n    JSDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n    };\n\n    /** Triggered on change by the editor */\n    JSDocument.prototype.onChange = function onChange(event, editor, change) {\n        var src = this.doc.getText();\n        Inspector.Debugger.setScriptSource(this.script.scriptId, src, function onSetScriptSource(res) {\n            Inspector.Runtime.evaluate(\"if($)$(\\\"canvas\\\").each(function(i,e){if(e.rerender)e.rerender()})\");\n        }.bind(this));\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    JSDocument.prototype.onHighlight = function onHighlight(node) {\n        // clear an existing highlight\n        var codeMirror = this.editor._codeMirror;\n        var i;\n        for (i in this._highlight) {\n            codeMirror.setLineClass(this._highlight[i]);\n        }\n        this._highlight = [];\n        if (!node || !node.trace) {\n            return;\n        }\n\n        // go through the trace and find highlight the lines of this script\n        var callFrame, line;\n        for (i in node.trace) {\n            callFrame = node.trace[i];\n            if (callFrame.location && callFrame.location.scriptId === this.script.scriptId) {\n                line = callFrame.location.lineNumber;\n                codeMirror.setLineClass(line, \"highlight\");\n                this._highlight.push(line);\n            }\n        }\n    };\n\n    // Export the class\n    module.exports = JSDocument;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * ConsoleAgent forwards all console message from the remote console to the\n * local console.\n */\ndefine('LiveDevelopment/Agents/ConsoleAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector'],function ConsoleAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _lastMessage; // {Console.ConsoleMessage} the last received message\n\n    /** Log a remote message to the local console\n     * @param {Console.ConsoleMessage} message\n     */\n    function _log(message) {\n        var level = message.level;\n        if (level === \"warning\") {\n            level = \"warn\";\n        }\n        var text = \"ConsoleAgent: \" + message.text;\n        if (message.stackTrace) {\n            var callFrame = message.stackTrace[0];\n            text += \" in \" + callFrame.functionName + \":\" + callFrame.columnNumber;\n        }\n        console[level](text);\n    }\n\n    // WebInspector Event: Console.messageAdded\n    function _onMessageAdded(event, res) {\n        // res = {message}\n        _lastMessage = res.message;\n        _log(_lastMessage);\n    }\n\n    // WebInspector Event: Console.messageRepeatCountUpdated\n    function _onMessageRepeatCountUpdated(event, res) {\n        // res = {count}\n        if (_lastMessage) {\n            _log(_lastMessage);\n        }\n    }\n\n    // WebInspector Event: Console.messagesCleared\n    function _onMessagesCleared(event, res) {\n        // res = {}\n    }\n\n    /** Initialize the agent */\n    function load() {\n        Inspector.Console.enable();\n        $(Inspector.Console)\n            .on(\"messageAdded.ConsoleAgent\", _onMessageAdded)\n            .on(\"messageRepeatCountUpdated.ConsoleAgent\", _onMessageRepeatCountUpdated)\n            .on(\"messagesCleared.ConsoleAgent\", _onMessagesCleared);\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Console).off(\".ConsoleAgent\");\n    }\n\n    // Export public functions\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * NetworkAgent tracks all resources loaded by the remote debugger. Use\n * `wasURLRequested(url)` to query whether a resource was loaded.\n */\ndefine('LiveDevelopment/Agents/NetworkAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector'],function NetworkAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _urlRequested; // url -> request info\n\n    /** Return the URL without the query string\n     * @param {string} URL\n     */\n    function _urlWithoutQueryString(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Return the resource information for a given URL\n     * @param {string} url\n     */\n    function wasURLRequested(url) {\n        return _urlRequested && _urlRequested[url];\n    }\n\n    // WebInspector Event: Network.requestWillBeSent\n    function _onRequestWillBeSent(event, res) {\n        // res = {requestId, frameId, loaderId, documentURL, request, timestamp, initiator, stackTrace, redirectResponse}\n        var url = _urlWithoutQueryString(res.request.url);\n        _urlRequested[url] = true;\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _urlRequested = {};\n        Inspector.Network.enable();\n        $(Inspector.Network).on(\"requestWillBeSent.NetworkAgent\", _onRequestWillBeSent);\n    }\n\n    /** Unload the agent */\n    function unload() {\n        $(Inspector.Network).off(\".NetworkAgent\");\n    }\n\n    // Export public functions\n    exports.wasURLRequested = wasURLRequested;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, brackets, $, window */\n\n/**\n * GotoAgent constructs and responds to the in-browser goto dialog.\n */\ndefine('LiveDevelopment/Agents/GotoAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/ScriptAgent','LiveDevelopment/Agents/RemoteAgent','document/DocumentManager','editor/EditorManager'],function GotoAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var ScriptAgent = require(\"LiveDevelopment/Agents/ScriptAgent\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n\n    var DocumentManager = require(\"document/DocumentManager\");\n    var EditorManager = require(\"editor/EditorManager\");\n\n    /** Return the URL without the query string\n     * @param {string} URL\n     */\n    function _urlWithoutQueryString(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Get the file component of the given url\n     * @param {string} URL\n     */\n    function _fileFromURL(url) {\n        var comp = url.split(\"/\");\n        return comp[comp.length - 1];\n    }\n\n    /** Make the given node a target for goto\n     * @param [] targets array\n     * @param {DOMNode} node\n     */\n    function _makeHTMLTarget(targets, node) {\n        if (node.location) {\n            var target = {};\n            var url = DOMAgent.url;\n            var location = node.location;\n            if (node.canHaveChildren()) {\n                location += node.length;\n            }\n            url += \":\" + location;\n            var name = \"&lt;\" + node.name + \"&gt;\";\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"html\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Make the given css rule a target for goto\n     * @param [] targets array\n     * @param {CSS.Rule} node\n     */\n    function _makeCSSTarget(targets, rule) {\n        if (rule.sourceURL) {\n            var target = {};\n            var url = rule.sourceURL;\n            url += \":\" + rule.style.range.start;\n            var name = rule.selectorText;\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"css\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Make the given javascript callFrame the target for goto\n     * @param [] targets array\n     * @param {Debugger.CallFrame} node\n     */\n    function _makeJSTarget(targets, callFrame) {\n        var script = ScriptAgent.scriptWithId(callFrame.location.scriptId);\n        if (script && script.url) {\n            var target = {};\n            var url = script.url;\n            url += \":\" + callFrame.location.lineNumber + \",\" + callFrame.location.columnNumber;\n            var name = callFrame.functionName;\n            if (name === \"\") {\n                name = \"anonymous function\";\n            }\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"js\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Gather options where to go to from the given source node */\n    function _onRemoteShowGoto(event, res) {\n        // res = {nodeId, name, value}\n        var node = DOMAgent.nodeWithId(res.nodeId);\n\n        // get all css rules that apply to the given node\n        Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onMatchedStyles(res) {\n            var i, callFrame, name, script, url, rule, targets = [];\n            _makeHTMLTarget(targets, node);\n            for (i in node.trace) {\n                _makeJSTarget(targets, node.trace[i]);\n            }\n            for (i in res.matchedCSSRules) {\n                _makeCSSTarget(targets, res.matchedCSSRules[i]);\n            }\n            RemoteAgent.call(\"showGoto\", targets);\n        });\n    }\n\n    /** Point the master editor to the given location\n     * @param {integer} location in file\n     */\n    function openLocation(location, noFlash) {\n        var editor = EditorManager.getCurrentFullEditor();\n        var codeMirror = editor._codeMirror;\n        if (typeof location === \"number\") {\n            location = codeMirror.posFromIndex(location);\n        }\n        codeMirror.setCursor(location);\n        editor.focus();\n\n        if (!noFlash) {\n            codeMirror.setLineClass(location.line, \"flash\");\n            window.setTimeout(codeMirror.setLineClass.bind(codeMirror, location.line), 1000);\n        }\n    }\n\n    /** Open the editor at the given url and editor location\n     * @param {string} url\n     * @param {integer} optional location in file\n     */\n    function open(url, location, noFlash) {\n        console.assert(url.substr(0, 7) === \"file://\", \"Cannot open non-file URLs\");\n\n        var result = new $.Deferred();\n        \n        url = _urlWithoutQueryString(url);\n        // Extract the path, also strip the third slash when on Windows\n        var path = url.slice(brackets.platform === \"win\" ? 8 : 7);\n        var promise = DocumentManager.getDocumentForPath(path);\n        promise.done(function onDone(doc) {\n            DocumentManager.setCurrentDocument(doc);\n            if (location) {\n                openLocation(location, noFlash);\n            }\n            result.resolve();\n        });\n        promise.fail(function onErr(err) {\n            console.error(err);\n            result.reject(err);\n        });\n\n        return result.promise();\n    }\n\n    /** Go to the given source node */\n    function _onRemoteGoto(event, res) {\n        // res = {nodeId, name, value}\n        var location, url = res.value;\n        var matches = /^(.*):([^:]+)$/.exec(url);\n        if (matches) {\n            url = matches[1];\n            location = matches[2].split(\",\");\n            if (location.length === 1) {\n                location = parseInt(location[0], 10);\n            } else {\n                location = { line: parseInt(location[0], 10), ch: parseInt(location[1], 10) };\n            }\n        }\n        open(url, location);\n    }\n\n    /** Initialize the agent */\n    function load() {\n        $(RemoteAgent)\n            .on(\"showgoto.GotoAgent\", _onRemoteShowGoto)\n            .on(\"goto.GotoAgent\", _onRemoteGoto);\n    }\n\n    /** Initialize the agent */\n    function unload() {\n        $(RemoteAgent).off(\".GotoAgent\");\n    }\n\n    // Export public functions\n    exports.openLocation = openLocation;\n    exports.open = open;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * EditAgent propagates changes from the in-document editor to the source\n * document.\n */\ndefine('LiveDevelopment/Agents/EditAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/GotoAgent','editor/EditorManager'],function EditAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var GotoAgent = require(\"LiveDevelopment/Agents/GotoAgent\");\n\n    var EditorManager = require(\"editor/EditorManager\");\n\n    /** Find changed characters\n     * @param {string} old value\n     * @param {string} changed value\n     * @return {from, to, text}\n     */\n    function _findChangedCharacters(oldValue, value) {\n        if (oldValue === value) {\n            return undefined;\n        }\n        var length = oldValue.length;\n        var index = 0;\n\n        // find the first character that changed\n        var i;\n        for (i = 0; i < length; i++) {\n            if (value[i] !== oldValue[i]) {\n                break;\n            }\n        }\n        index += i;\n        value = value.substr(i);\n        length -= i;\n\n        // find the last character that changed\n        for (i = 0; i < length; i++) {\n            if (value[value.length - 1 - i] !== oldValue[oldValue.length - 1 - i]) {\n                break;\n            }\n        }\n        length -= i;\n        value = value.substr(0, value.length - i);\n\n        return { from: index, to: index + length, text: value };\n    }\n\n    // Remote Event: Go to the given source node\n    function _onRemoteEdit(event, res) {\n        // res = {nodeId, name, value}\n        var node = DOMAgent.nodeWithId(res.nodeId);\n        node = node.children[0];\n        if (!node.location) {\n            return;\n        }\n        GotoAgent.open(DOMAgent.url);\n        var editor = EditorManager.getCurrentFullEditor();\n        var codeMirror = editor._codeMirror;\n        var change = _findChangedCharacters(node.value, res.value);\n        if (change) {\n            var from = codeMirror.posFromIndex(node.location + change.from);\n            var to = codeMirror.posFromIndex(node.location + change.to);\n            editor.document.replaceRange(change.text, from, to);\n\n            var newPos = codeMirror.posFromIndex(node.location + change.from + change.text.length);\n            editor.setCursorPos(newPos.line, newPos.ch);\n        }\n    }\n\n    /** Initialize the agent */\n    function load() {\n        $(RemoteAgent).on(\"edit.EditAgent\", _onRemoteEdit);\n    }\n\n    /** Initialize the agent */\n    function unload() {\n        $(RemoteAgent).off(\".EditAgent\");\n    }\n\n    // Export public functions\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, FileError, brackets, window */\n\n/**\n * LiveDevelopment manages the Inspector, all Agents, and the active LiveDocument\n *\n * # STARTING\n *\n * To start a session call `open`. This will read the currentDocument from brackets,\n * launch the LiveBrowser (currently Chrome) with the remote debugger port open,\n * establish the Inspector connection to the remote debugger, and finally load all\n * agents.\n *\n * # STOPPING\n *\n * To stop a session call `close`. This will close the active browser window,\n * disconnect the Inspector, unload all agents, and clean up.\n *\n * # STATUS\n *\n * Status updates are dispatched as `statusChange` jQuery events. The status\n * codes are:\n *\n * -1: Error\n * 0: Inactive\n * 1: Connecting to the remote debugger\n * 2: Loading agents\n * 3: Active\n */\ndefine('LiveDevelopment/LiveDevelopment',['require','exports','module','document/DocumentManager','editor/EditorManager','utils/NativeApp','widgets/Dialogs','strings','utils/StringUtils','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Documents/HTMLDocument','LiveDevelopment/Documents/CSSDocument','LiveDevelopment/Documents/JSDocument','LiveDevelopment/Agents/ConsoleAgent','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/NetworkAgent','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/CSSAgent','LiveDevelopment/Agents/ScriptAgent','LiveDevelopment/Agents/HighlightAgent','LiveDevelopment/Agents/GotoAgent','LiveDevelopment/Agents/EditAgent'],function LiveDevelopment(require, exports, module) {\n    \n\n    // Status Codes\n    var STATUS_ERROR          = exports.STATUS_ERROR = -1;\n    var STATUS_INACTIVE       = exports.STATUS_INACTIVE = 0;\n    var STATUS_CONNECTING     = exports.STATUS_CONNECTING = 1;\n    var STATUS_LOADING_AGENTS = exports.STATUS_LOADING_AGENTS = 2;\n    var STATUS_ACTIVE         = exports.STATUS_ACTIVE = 3;\n\n    var DocumentManager = require(\"document/DocumentManager\");\n    var EditorManager = require(\"editor/EditorManager\");\n    var NativeApp = require(\"utils/NativeApp\");\n    var Dialogs = require(\"widgets/Dialogs\");\n    var Strings = require(\"strings\");\n    var StringUtils = require(\"utils/StringUtils\");\n\n    // Inspector\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    // Documents\n    var HTMLDocument = require(\"LiveDevelopment/Documents/HTMLDocument\");\n    var CSSDocument = require(\"LiveDevelopment/Documents/CSSDocument\");\n    var JSDocument = require(\"LiveDevelopment/Documents/JSDocument\");\n\n    // Agents\n    var agents = {\n        \"console\": require(\"LiveDevelopment/Agents/ConsoleAgent\"),\n        \"remote\": require(\"LiveDevelopment/Agents/RemoteAgent\"),\n        \"network\": require(\"LiveDevelopment/Agents/NetworkAgent\"),\n        \"dom\": require(\"LiveDevelopment/Agents/DOMAgent\"),\n        \"css\": require(\"LiveDevelopment/Agents/CSSAgent\"),\n        \"script\": require(\"LiveDevelopment/Agents/ScriptAgent\"),\n        \"highlight\": require(\"LiveDevelopment/Agents/HighlightAgent\"),\n        \"goto\": require(\"LiveDevelopment/Agents/GotoAgent\"),\n        \"edit\": require(\"LiveDevelopment/Agents/EditAgent\")\n    };\n\n    // Some agents are still experimental, so we don't enable them all by default\n    // However, extensions can enable them by calling enableAgent().\n    // This object is used as a set (thus all properties have the value 'true').\n    // Property names should match property names in the 'agents' object.\n    var _enabledAgentNames = {\n        \"console\": true,\n        \"remote\": true,\n        \"network\": true,\n        \"dom\": true,\n        \"css\": true\n    };\n    // store the names (matching property names in the 'agent' object) of agents that we've loaded\n    var _loadedAgentNames = [];\n\n    var _htmlDocumentPath; // the path of the html file open for live development\n    var _liveDocument; // the document open for live editing.\n    var _relatedDocuments; // CSS and JS documents that are used by the live HTML document\n\n    /** Augments the given Brackets document with information that's useful for live development. */\n    function _setDocInfo(doc) {\n        // FUTURE: some of these things should just be moved into core Document; others should\n        // be in a LiveDevelopment-specific object attached to the doc.\n        var matches = /^(.*\\/)(.+\\.([^.]+))$/.exec(doc.file.fullPath);\n        if (matches) {\n            var prefix = \"file://\";\n\n            // The file.fullPath on Windows starts with a drive letter (\"C:\").\n            // In order to make it a valid file: URL we need to add an \n            // additional slash to the prefix.\n            if (brackets.platform === \"win\") {\n                prefix += \"/\";\n            }\n\n            doc.extension = matches[3];\n            doc.url = encodeURI(prefix + doc.file.fullPath);\n\n            // the root represents the document that should be displayed in the browser\n            // for live development (the file for HTML files, index.html for others)\n            var fileName = /^html?$/.test(matches[3]) ? matches[2] : \"index.html\";\n            doc.root = {url: encodeURI(prefix + matches[1] + fileName)};\n        }\n    }\n\n    /** Get the current document from the document manager\n     * _adds extension, url and root to the document\n     */\n    function _getCurrentDocument() {\n        var doc = DocumentManager.getCurrentDocument();\n        if (doc) {\n            _setDocInfo(doc);\n        }\n        return doc;\n    }\n\n    /** Determine which document class should be used for a given document\n     * @param {Document} document\n     */\n    function _classForDocument(doc) {\n        switch (doc.extension) {\n        case \"css\":\n            return CSSDocument;\n        /* FUTURE:\n        case \"js\":\n            return JSDocument;\n        case \"html\":\n        case \"htm\":\n            return HTMLDocument;\n        default:\n            throw \"Invalid document type: \" + doc.extension;\n        */\n        }\n\n        return null;\n    }\n\n    /**\n     * Removes the given CSS/JSDocument from _relatedDocuments. Signals that the\n     * given file is no longer associated with the HTML document that is live (e.g.\n     * if the related file has been deleted on disk).\n     */\n    function _handleRelatedDocumentDeleted(event, liveDoc) {\n        var index = _relatedDocuments.indexOf(liveDoc);\n        if (index !== -1) {\n            $(liveDoc).on(\"deleted\", _handleRelatedDocumentDeleted);\n            _relatedDocuments.splice(index, 1);\n        }\n    }\n\n    /** Close a live document */\n    function _closeDocument() {\n        if (_liveDocument) {\n            _liveDocument.close();\n            _liveDocument = undefined;\n        }\n        if (_relatedDocuments) {\n            _relatedDocuments.forEach(function (liveDoc) {\n                liveDoc.close();\n                $(liveDoc).off(\"deleted\", _handleRelatedDocumentDeleted);\n            });\n            _relatedDocuments = undefined;\n        }\n    }\n\n    /** Create a live version of a Brackets document */\n    function _createDocument(doc, editor) {\n        var DocClass = _classForDocument(doc);\n        if (DocClass) {\n            return new DocClass(doc, editor);\n        } else {\n            return null;\n        }\n    }\n\n    /** Convert a file: URL to a local full file path */\n    function _urlToPath(url) {\n        var path;\n        if (url.indexOf(\"file://\") === 0) {\n            path = url.slice(7);\n            if (path && brackets.platform === \"win\" && path.charAt(0) === \"/\") {\n                path = path.slice(1);\n            }\n        }\n        return decodeURI(path);\n    }\n\n    /** Open a live document\n     * @param {Document} source document to open\n     */\n    function _openDocument(doc, editor) {\n        _closeDocument();\n        _liveDocument = _createDocument(doc, editor);\n\n        // Gather related CSS documents.\n        // FUTURE: Gather related JS documents as well.\n        _relatedDocuments = [];\n        agents.css.getStylesheetURLs().forEach(function (url) {\n            // FUTURE: when we get truly async file handling, we might need to prevent other\n            // stuff from happening while we wait to add these listeners\n            DocumentManager.getDocumentForPath(_urlToPath(url))\n                .done(function (doc) {\n                    _setDocInfo(doc);\n                    var liveDoc = _createDocument(doc);\n                    if (liveDoc) {\n                        _relatedDocuments.push(liveDoc);\n                        $(liveDoc).on(\"deleted\", _handleRelatedDocumentDeleted);\n                    }\n                });\n        });\n    }\n\n    /** Unload the agents */\n    function unloadAgents() {\n        _loadedAgentNames.forEach(function (name) {\n            agents[name].unload();\n        });\n        _loadedAgentNames = [];\n    }\n\n    /** Load the agents */\n    function loadAgents() {\n        var name, promises = [];\n        for (name in _enabledAgentNames) {\n            if (_enabledAgentNames.hasOwnProperty(name) && agents[name].load) {\n                promises.push(agents[name].load());\n                _loadedAgentNames.push(name);\n            }\n        }\n        return promises;\n    }\n\n    /** Enable an agent. Takes effect next time a connection is made. Does not affect\n     *  current live development sessions.\n     *\n     *  @param {string} name of agent to enable\n     */\n    function enableAgent(name) {\n        if (agents.hasOwnProperty(name) && !_enabledAgentNames.hasOwnProperty(name)) {\n            _enabledAgentNames[name] = true;\n        }\n    }\n\n    /** Disable an agent. Takes effect next time a connection is made. Does not affect\n     *  current live development sessions.\n     *\n     *  @param {string} name of agent to disable\n     */\n    function disableAgent(name) {\n        if (_enabledAgentNames.hasOwnProperty(name)) {\n            delete _enabledAgentNames[name];\n        }\n    }\n\n    /** Update the status\n     * @param {integer} new status\n     */\n    function _setStatus(status) {\n        exports.status = status;\n        $(exports).triggerHandler(\"statusChange\", status);\n    }\n\n    /** Triggered by Inspector.error */\n    function _onError(event, error) {\n        var message = error.message;\n\n        // Additional information, like exactly which parameter could not be processed.\n        var data = error.data;\n        if (Array.isArray(data)) {\n            message += \"\\n\" + data.join(\"\\n\");\n        }\n\n        // Show the message, but include the error object for further information (e.g. error code)\n        console.error(message, error);\n    }\n\n    /** Run when all agents are loaded */\n    function _onLoad() {\n        var doc = _getCurrentDocument();\n        if (doc) {\n            var editor = EditorManager.getCurrentFullEditor();\n            _openDocument(doc, editor);\n        }\n        _setStatus(STATUS_ACTIVE);\n    }\n\n    /** Triggered by Inspector.connect */\n    function _onConnect(event) {\n        var promises = loadAgents();\n        _setStatus(STATUS_LOADING_AGENTS);\n        $.when.apply(undefined, promises).then(_onLoad, _onError);\n    }\n\n    /** Triggered by Inspector.disconnect */\n    function _onDisconnect(event) {\n        unloadAgents();\n        _closeDocument();\n        _setStatus(STATUS_INACTIVE);\n    }\n\n    /** Open the Connection and go live */\n    function open() {\n        var result = new $.Deferred(),\n            promise = result.promise();\n        var doc = _getCurrentDocument();\n        var browserStarted = false;\n        var retryCount = 0;\n\n        function showWrongDocError() {\n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_ERROR,\n                Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n                Strings.LIVE_DEV_NEED_HTML_MESSAGE\n            );\n            result.reject(\"WRONG_DOC\");\n        }\n\n        if (!doc || !doc.root) {\n            showWrongDocError();\n\n        } else {\n            // For Sprint 6, we only open live development connections for HTML files\n            // FUTURE: Remove this test when we support opening connections for different\n            // file types.\n            if (!doc.extension || doc.extension.indexOf(\"htm\") !== 0) {\n                showWrongDocError();\n                return promise;\n            }\n\n            _setStatus(STATUS_CONNECTING);\n            Inspector.connectToURL(doc.root.url).then(result.resolve, function onConnectFail(err) {\n                if (err === \"CANCEL\") {\n                    result.reject(err);\n                    return;\n                }\n                if (retryCount > 6) {\n                    _setStatus(STATUS_ERROR);\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_LIVE_DEVELOPMENT,\n                        Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n                        Strings.LIVE_DEVELOPMENT_ERROR_MESSAGE\n                    ).done(function (id) {\n                        if (id === Dialogs.DIALOG_BTN_OK) {\n                            // User has chosen to reload Chrome, quit the running instance\n                            _setStatus(STATUS_INACTIVE);\n                            NativeApp.closeLiveBrowser()\n                                .done(function () {\n                                    browserStarted = false;\n                                    window.setTimeout(function () {\n                                        open().then(result.resolve, result.reject);\n                                    });\n                                })\n                                .fail(function (err) {\n                                    // Report error?\n                                    _setStatus(STATUS_ERROR);\n                                    browserStarted = false;\n                                    result.reject(\"CLOSE_LIVE_BROWSER\");\n                                });\n                        } else {\n                            result.reject(\"CANCEL\");\n                        }\n                    });\n                    return;\n                }\n                retryCount++;\n\n                if (!browserStarted && exports.status !== STATUS_ERROR) {\n                    // If err === FileError.ERR_NOT_FOUND, it means a remote debugger connection\n                    // is available, but the requested URL is not loaded in the browser. In that\n                    // case we want to launch the live browser (to open the url in a new tab)\n                    // without using the --remote-debugging-port flag. This works around issues\n                    // on Windows where Chrome can't be opened more than once with the\n                    // --remote-debugging-port flag set.\n                    NativeApp.openLiveBrowser(\n                        doc.root.url,\n                        err !== FileError.ERR_NOT_FOUND\n                    )\n                        .done(function () {\n                            browserStarted = true;\n                        })\n                        .fail(function (err) {\n                            var message;\n\n                            _setStatus(STATUS_ERROR);\n                            if (err === FileError.NOT_FOUND_ERR) {\n                                message = Strings.ERROR_CANT_FIND_CHROME;\n                            } else {\n                                message = StringUtils.format(Strings.ERROR_LAUNCHING_BROWSER, err);\n                            }\n\n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_LAUNCHING_BROWSER_TITLE,\n                                message\n                            );\n\n                            result.reject(\"OPEN_LIVE_BROWSER\");\n                        });\n                }\n\n                if (exports.status !== STATUS_ERROR) {\n                    window.setTimeout(function retryConnect() {\n                        Inspector.connectToURL(doc.root.url).then(result.resolve, onConnectFail);\n                    }, 500);\n                }\n            });\n        }\n\n        return promise;\n    }\n\n    /** Close the Connection */\n    function close() {\n        if (Inspector.connected()) {\n            Inspector.Runtime.evaluate(\"window.close()\");\n        }\n        Inspector.disconnect();\n        _setStatus(STATUS_INACTIVE);\n    }\n\n    /** Triggered by a document change from the DocumentManager */\n    function _onDocumentChange() {\n        var doc = _getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        if (Inspector.connected()) {\n            if (agents.network && agents.network.wasURLRequested(doc.url)) {\n                _closeDocument();\n                var editor = EditorManager.getCurrentFullEditor();\n                _openDocument(doc, editor);\n            } else {\n                /* FUTURE: support live connections for docments other than html */\n                if (doc.extension && doc.extension.indexOf(\"htm\") === 0 && doc.file.fullPath !== _htmlDocumentPath) {\n                    close();\n                    window.setTimeout(open);\n                    _htmlDocumentPath = doc.file.fullPath;\n                }\n            }\n        } else if (exports.config.autoconnect) {\n            window.setTimeout(open);\n        }\n    }\n\n    function getLiveDocForPath(path) {\n        var docsToSearch = [];\n        if (_relatedDocuments) {\n            docsToSearch = docsToSearch.concat(_relatedDocuments);\n        }\n        if (_liveDocument) {\n            docsToSearch = docsToSearch.concat(_liveDocument);\n        }\n        var foundDoc;\n        docsToSearch.some(function matchesPath(ele) {\n            if (ele.doc.file.fullPath === path) {\n                foundDoc = ele;\n                return true;\n            }\n            return false;\n        });\n\n        return foundDoc;\n    }\n\n    /** Hide any active highlighting */\n    function hideHighlight() {\n        if (Inspector.connected() && agents.highlight) {\n            agents.highlight.hide();\n        }\n    }\n\n    /** Initialize the LiveDevelopment Session */\n    function init(theConfig) {\n        exports.config = theConfig;\n        $(Inspector).on(\"connect\", _onConnect)\n            .on(\"disconnect\", _onDisconnect)\n            .on(\"error\", _onError);\n        $(DocumentManager).on(\"currentDocumentChange\", _onDocumentChange);\n    }\n\n    // Export public functions\n    exports.agents = agents;\n    exports.open = open;\n    exports.close = close;\n    exports.enableAgent = enableAgent;\n    exports.disableAgent = disableAgent;\n    exports.getLiveDocForPath = getLiveDocForPath;\n    exports.hideHighlight = hideHighlight;\n    exports.init = init;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, less, window, XMLHttpRequest */\n\n/**\n * main integrates LiveDevelopment into Brackets\n *\n * This module creates two menu items:\n *\n *  \"Go Live\": open or close a Live Development session and visualize the status\n *  \"Highlight\": toggle source highlighting\n *\n * @require DocumentManager\n */\ndefine('LiveDevelopment/main',['require','exports','module','document/DocumentManager','command/Commands','LiveDevelopment/LiveDevelopment','LiveDevelopment/Inspector/Inspector','command/CommandManager','strings'],function main(require, exports, module) {\n    \n\n    var DocumentManager = require(\"document/DocumentManager\"),\n        Commands        = require(\"command/Commands\"),\n        LiveDevelopment = require(\"LiveDevelopment/LiveDevelopment\"),\n        Inspector       = require(\"LiveDevelopment/Inspector/Inspector\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        Strings = require(\"strings\");\n\n    var config = {\n        debug: true, // enable debug output and helpers\n        autoconnect: false, // go live automatically after startup?\n        highlight: false, // enable highlighting?\n        highlightConfig: { // the highlight configuration for the Inspector\n            borderColor:  {r: 255, g: 229, b: 153, a: 0.66},\n            contentColor: {r: 111, g: 168, b: 220, a: 0.55},\n            marginColor:  {r: 246, g: 178, b: 107, a: 0.66},\n            paddingColor: {r: 147, g: 196, b: 125, a: 0.66},\n            showInfo: true\n        }\n    };\n    var _checkMark = \"✓\"; // Check mark character\n    // Status labels/styles are ordered: error, not connected, progress1, progress2, connected.\n    var _statusTooltip = [Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, Strings.LIVE_DEV_STATUS_TIP_PROGRESS1,\n                          Strings.LIVE_DEV_STATUS_TIP_PROGRESS2, Strings.LIVE_DEV_STATUS_TIP_CONNECTED];  // Status indicator tooltip\n    var _statusStyle = [\"warning\", \"\", \"info\", \"info\", \"success\"];  // Status indicator's CSS class\n    var _allStatusStyles = _statusStyle.join(\" \");\n\n    var _$btnGoLive; // reference to the GoLive button\n    var _$btnHighlight; // reference to the HighlightButton\n\n    /** Load Live Development LESS Style */\n    function _loadStyles() {\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"LiveDevelopment/main.less\", true);\n        request.onload = function onLoad(event) {\n            var parser = new less.Parser();\n            parser.parse(request.responseText, function onParse(err, tree) {\n                console.assert(!err, err);\n                $(\"<style>\" + tree.toCSS() + \"</style>\")\n                    .appendTo(window.document.head);\n            });\n        };\n        request.send(null);\n    }\n\n    /**\n     * Change the appearance of a button. Omit text to remove any extra text; omit style to return to default styling;\n     * omit tooltip to leave tooltip unchanged.\n     */\n    function _setLabel($btn, text, style, tooltip) {\n        // Clear text/styles from previous status\n        $(\"span\", $btn).remove();\n        $btn.removeClass(_allStatusStyles);\n\n        // Set text/styles for new status\n        if (text && text.length > 0) {\n            $(\"<span class=\\\"label\\\">\")\n                .addClass(style)\n                .text(text)\n                .appendTo($btn);\n        } else {\n            $btn.addClass(style);\n        }\n\n        if (tooltip) {\n            $btn.attr(\"title\", tooltip);\n        }\n    }\n\n    /** Toggles LiveDevelopment and synchronizes the state of UI elements that reports LiveDevelopment status */\n    function _handleGoLiveCommand() {\n        if (LiveDevelopment.status >= LiveDevelopment.STATUS_CONNECTING) {\n            LiveDevelopment.close();\n            // TODO Ty: when checkmark support lands, remove checkmark\n        } else {\n            LiveDevelopment.open();\n            // TODO Ty: when checkmark support lands, add checkmark\n        }\n    }\n\n    /** Create the menu item \"Go Live\" */\n    function _setupGoLiveButton() {\n        _$btnGoLive = $(\"#toolbar-go-live\");\n        _$btnGoLive.click(function onGoLive() {\n            _handleGoLiveCommand();\n        });\n        $(LiveDevelopment).on(\"statusChange\", function statusChange(event, status) {\n            // status starts at -1 (error), so add one when looking up name and style\n            // See the comments at the top of LiveDevelopment.js for details on the \n            // various status codes.\n            _setLabel(_$btnGoLive, null, _statusStyle[status + 1], _statusTooltip[status + 1]);\n        });\n\n        // Initialize tooltip for 'not connected' state\n        _setLabel(_$btnGoLive, null, _statusStyle[1], _statusTooltip[1]);\n    }\n\n    /** Create the menu item \"Highlight\" */\n    function _setupHighlightButton() {\n        // TODO: this should be moved into index.html like the Go Live button once it's re-enabled\n        _$btnHighlight = $(\"<a href=\\\"#\\\">Highlight </a>\");\n        $(\".nav\").append($(\"<li>\").append(_$btnHighlight));\n        _$btnHighlight.click(function onClick() {\n            config.highlight = !config.highlight;\n            if (config.highlight) {\n                _setLabel(_$btnHighlight, _checkMark, \"success\");\n            } else {\n                _setLabel(_$btnHighlight);\n                LiveDevelopment.hideHighlight();\n            }\n        });\n        if (config.highlight) {\n            _setLabel(_$btnHighlight, _checkMark, \"success\");\n        }\n    }\n\n    /** Setup window references to useful LiveDevelopment modules */\n    function _setupDebugHelpers() {\n        window.ld = LiveDevelopment;\n        window.i = Inspector;\n        window.report = function report(params) { window.params = params; console.info(params); };\n    }\n\n    /** Initialize LiveDevelopment */\n    function init() {\n        Inspector.init(config);\n        LiveDevelopment.init(config);\n        _loadStyles();\n        _setupGoLiveButton();\n        /* _setupHighlightButton(); FUTURE - Highlight button */\n        if (config.debug) {\n            _setupDebugHelpers();\n        }\n    }\n    window.setTimeout(init);\n\n    CommandManager.register(Strings.CMD_LIVE_FILE_PREVIEW,  Commands.FILE_LIVE_FILE_PREVIEW, _handleGoLiveCommand);\n\n    // Export public functions\n    exports.init = init;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils */\n\n/*\n * Manages a collection of FileIndexes where each index maintains a list of information about\n * files that meet the criteria specified by the index. The indexes are created lazily when\n * they are queried and marked dirty when Brackets becomes active.\n *\n * TODO (issue 325 ) - FileIndexer doesn't currently add a file to the index when the user createa\n * a new file within brackets.\n *\n */\n\n\ndefine('project/FileIndexManager',['require','exports','module','file/NativeFileSystem','utils/PerfUtils','project/ProjectManager','widgets/Dialogs','strings'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\");\n\n    /**\n     * All the indexes are stored in this object. The key is the name of the index\n     * and the value is a FileIndex. \n     */\n    var _indexList = {};\n\n    /**\n     * Tracks whether _indexList should be considered dirty and invalid. Calls that access\n     * any data in _indexList should call syncFileIndex prior to accessing the data.\n     * @type {boolean}\n     */\n    var _indexListDirty = true;\n\n    /** class FileIndex\n     *\n     * A FileIndex contains an array of fileInfos that meet the criteria specified by\n     * the filterFunction. FileInfo's in the fileInfo array should unique map to one file.\n     *  \n     * @constructor\n     * @param {!string} indexname\n     * @param {function({!entry})} filterFunction returns true to indicate the entry\n     *                             should be included in the index\n     */\n    function FileIndex(indexName, filterFunction) {\n        this.name = indexName;\n        this.fileInfos = [];\n        this.filterFunction = filterFunction;\n    }\n\n    /** class FileInfo\n     * \n     *  Class to hold info about a file that a FileIndex wishes to retain.\n     *\n     * @constructor\n     * @param {!string}\n     */\n    function FileInfo(entry) {\n        this.name = entry.name;\n        this.fullPath = entry.fullPath;\n    }\n\n\n    /**\n    * Adds a new index to _indexList and marks the list dirty \n    *\n    * A future performance optimization is to only build the new index rather than \n    * marking them all dirty\n    *\n    * @private\n    * @param {!string} indexName must be unque\n    * @param {!function({entry} filterFunction should return true to include an\n    *   entry in the index\n\n    */\n    function _addIndex(indexName, filterFunction) {\n        if (_indexList.hasOwnProperty(indexName)) {\n            throw new Error(\"Duplicate index name\");\n        }\n        if (typeof filterFunction !== \"function\") {\n            throw new Error(\"Invalid arguments\");\n        }\n\n        _indexList[indexName] = new FileIndex(indexName, filterFunction);\n\n        _indexListDirty = true;\n    }\n\n\n    /**\n    * Checks the entry against the filterFunction for each index and adds\n    * a fileInfo to the index if the entry meets the criteria. FileInfo's are\n    * shared between indexes.\n    *\n    * @private\n    * @param {!entry} entry to be added to the indexes\n    */\n    // future use when files are incrementally added\n    //\n    function _addFileToIndexes(entry) {\n\n        // skip invisible files\n        if (!ProjectManager.shouldShow(entry)) {\n            return;\n        }\n\n        var fileInfo = new FileInfo(entry);\n        //console.log(entry.name);\n  \n        $.each(_indexList, function (indexName, index) {\n            if (index.filterFunction(entry)) {\n                index.fileInfos.push(fileInfo);\n            }\n        });\n    }\n    \n  /**\n    * Error dialog when max files in index is hit\n    */\n    function _showMaxFilesDialog() {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_MAX_FILES_TITLE,\n            Strings.ERROR_MAX_FILES\n        );\n    }\n\n    /* Recursively visits all files that are descendent of dirEntry and adds\n    * files files to each index when the file matches the filter critera\n    * @private\n    * @param {!DirectoryEntry} dirEntry\n    * @returns {$.Promise}\n    */\n    function _scanDirectorySubTree(dirEntry) {\n        if (!dirEntry) {\n            throw new Error(\"Bad dirEntry passed to _scanDirectorySubTree\");\n        }\n\n        // keep track of directories as they are asynchronously read. We know we are done\n        // when dirInProgress becomes empty again.\n        var state = { fileCount: 0,\n                      dirInProgress: {},    // directory names that are in progress of being read\n                      dirError: {},         // directory names with read errors. key=dir path, value=error\n                      maxFilesHit: false    // used to show warning dialog only once\n                    };\n\n        var deferred = new $.Deferred();\n\n        // inner helper function\n        function _dirScanDone() {\n            var key;\n            for (key in state.dirInProgress) {\n                if (state.dirInProgress.hasOwnProperty(key)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _finishDirScan(dirEntry) {\n            //console.log(\"finished: \" + dirEntry.fullPath);\n            delete state.dirInProgress[dirEntry.fullPath];\n\n            if (_dirScanDone()) {\n                //console.log(\"dir scan completly done\");\n                deferred.resolve();\n            }\n        }\n\n        // inner helper function\n        function _scanDirectoryRecurse(dirEntry) {\n            // skip invisible directories\n            if (!ProjectManager.shouldShow(dirEntry)) {\n                return;\n            }\n\n            state.dirInProgress[dirEntry.fullPath] = true;\n            //console.log(\"started dir: \" + dirEntry.fullPath);\n\n            dirEntry.createReader().readEntries(\n                // success callback\n                function (entries) {\n                    // inspect all children of dirEntry\n                    entries.forEach(function (entry) {\n                        // For now limit the number of files that are indexed by preventing adding files\n                        // or scanning additional directories once a max has been hit. Also notify the \n                        // user once via a dialog. This limit could be increased\n                        // if files were indexed in a worker thread so scanning didn't block the UI\n                        if (state.fileCount > 10000) {\n                            if (!state.maxFilesHit) {\n                                state.maxFilesHit = true;\n                                _showMaxFilesDialog();\n                            }\n                            return;\n                        }\n\n                        if (entry.isFile) {\n                            _addFileToIndexes(entry);\n                            state.fileCount++;\n\n                        } else if (entry.isDirectory) {\n                            _scanDirectoryRecurse(entry);\n                        }\n                    });\n\n                    _finishDirScan(dirEntry);\n                },\n                // error callback\n                function (error) {\n                    state.dirError[dirEntry.fullPath] = error;\n                    _finishDirScan(dirEntry);\n                }\n            );\n        }\n\n        _scanDirectoryRecurse(dirEntry);\n\n        return deferred.promise();\n    }\n    \n    \n\n\n    \n    // debug \n    function _logFileList(list) {\n        list.forEach(function (fileInfo) {\n            console.log(fileInfo.name);\n        });\n        console.log(\"length: \" + list.length);\n    }\n    \n\n    /**\n    * Clears the fileInfo array for all the indexes in _indexList\n    * @private\n    */\n    function _clearIndexes() {\n        $.each(_indexList, function (indexName, index) {\n            index.fileInfos = [];\n        });\n    }\n\n    /**\n     * Markes all file indexes dirty\n     */\n    function markDirty() {\n        _indexListDirty = true;\n    }\n\n    /**\n     * Used by syncFileIndex function to prevent reentrancy\n     * @private\n     */\n    var _syncFileIndexReentracyGuard = false;\n\n    /**\n    * Clears and rebuilds all of the fileIndexes and sets _indexListDirty to false\n    * @return {$.Promise} resolved when index has been updated\n    */\n    function syncFileIndex() {\n\n        // TODO (issue 330) - allow multiple calls to syncFileIndex to be batched up so that this code isn't necessary\n        if (_syncFileIndexReentracyGuard) {\n            throw new Error(\"syncFileIndex cannot be called Recursively\");\n        }\n\n        _syncFileIndexReentracyGuard = true;\n\n        var rootDir = ProjectManager.getProjectRoot();\n        if (_indexListDirty) {\n            PerfUtils.markStart(PerfUtils.FILE_INDEX_MANAGER_SYNC);\n\n            _clearIndexes();\n\n            return _scanDirectorySubTree(rootDir)\n                .done(function () {\n                    PerfUtils.addMeasurement(PerfUtils.FILE_INDEX_MANAGER_SYNC);\n                    _indexListDirty = false;\n                    _syncFileIndexReentracyGuard = false;\n\n                    //_logFileList(_indexList[\"all\"].fileInfos);\n                    //_logFileList(_indexList[\"css\"].fileInfos);\n                });\n        } else {\n            _syncFileIndexReentracyGuard = false;\n            return $.Deferred().resolve().promise();\n        }\n    }\n\n    /**\n    * Returns the FileInfo array for the specified index\n    * @param {!string} indexname\n    * @return {$.Promise} a promise that is resolved with an Array of FileInfo's\n    */\n    function getFileInfoList(indexName) {\n        var result = new $.Deferred();\n\n        if (!_indexList.hasOwnProperty(indexName)) {\n            throw new Error(\"indexName not found\");\n        }\n\n        syncFileIndex()\n            .done(function () {\n                result.resolve(_indexList[indexName].fileInfos);\n            });\n\n        return result.promise();\n    }\n    \n    /**\n     * Calls the filterFunction on every in the index specified by indexName\n     * and return a a new list of FileInfo's\n     * @param {!string}\n     * @param {function({string})} filterFunction\n     * @return {$.Promise} a promise that is resolved with an Array of FileInfo's\n     */\n    function getFilteredList(indexName, filterFunction) {\n        var result = new $.Deferred();\n\n        if (!_indexList.hasOwnProperty(indexName)) {\n            throw new Error(\"indexName not found\");\n        }\n\n        syncFileIndex()\n            .done(function () {\n                var resultList = [];\n                getFileInfoList(indexName)\n                    .done(function (fileList) {\n                        resultList = fileList.filter(function (fileInfo) {\n                            return filterFunction(fileInfo.name);\n                        });\n\n                        result.resolve(resultList);\n                    });\n            });\n\n        return result.promise();\n    }\n    \n    /**\n     * returns an array of fileInfo's that match the filename parameter\n     * @param {!string} indexName\n     * @param {!filename}\n     * @return {$.Promise} a promise that is resolved with an Array of FileInfo's\n     */\n    function getFilenameMatches(indexName, filename) {\n        return getFilteredList(indexName, function (item) {\n            return item === filename;\n        });\n    }\n    \n    /**\n    * Add the indexes\n    */\n\n    _addIndex(\n        \"all\",\n        function (entry) {\n            return true;\n        }\n    );\n\n    _addIndex(\n        \"css\",\n        function (entry) {\n            var filename = entry.name;\n            return PathUtils.filenameExtension(filename) === \".css\";\n        }\n    );\n    \n    $(ProjectManager).on(\"projectOpen\", function (event, projectRoot) {\n        markDirty();\n    });\n    \n    PerfUtils.createPerfMeasurement(\"FILE_INDEX_MANAGER_SYNC\", \"syncFileIndex\");\n\n    exports.markDirty = markDirty;\n    exports.getFileInfoList = getFileInfoList;\n    exports.getFilenameMatches = getFilenameMatches;\n\n\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, _parseRuleList: true */\n\n// JSLint Note: _parseRuleList() is cyclical dependency, not a global function.\n// It was added to this list to prevent JSLint warning about being used before being defined.\n\n/**\n * Set of utilities for simple parsing of CSS text.\n */\ndefine('language/CSSUtils',['require','exports','module','utils/Async','document/DocumentManager','editor/EditorManager','language/HTMLUtils','project/FileIndexManager','file/NativeFileSystem'],function (require, exports, module) {\n    \n    \n    var Async               = require(\"utils/Async\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        HTMLUtils           = require(\"language/HTMLUtils\"),\n        FileIndexManager    = require(\"project/FileIndexManager\"),\n        NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem;\n\n    /**\n     * Extracts all CSS selectors from the given text\n     * Returns an array of selectors. Each selector is an object with the following properties:\n         selector:                 the text of the selector (note: comma separated selector groups like \n                                   \"h1, h2\" are broken into separate selectors)\n         ruleStartLine:            line in the text where the rule (including preceding comment) appears\n         ruleStartChar:            column in the line where the rule (including preceding comment) starts\n         selectorStartLine:        line in the text where the selector appears\n         selectorStartChar:        column in the line where the selector starts\n         selectorEndLine:          line where the selector ends\n         selectorEndChar:          column where the selector ends\n         selectorGroupStartLine:   line where the comma-separated selector group (e.g. .foo, .bar, .baz)\n                                   starts that this selector (e.g. .baz) is part of. Particularly relevant for\n                                   groups that are on multiple lines.\n         selectorGroupStartChar:   column in line where the selector group starts.\n         declListStartLine:        line where the declaration list for the rule starts\n         declListStartChar:        column in line where the declaration list for the rule starts\n         declListEndLine:          line where the declaration list for the rule ends\n         declListEndChar:          column in the line where the declaration list for the rule ends\n     * @param text {!String} CSS text to extract from\n     * @return {Array.<Object>} Array with objects specifying selectors.\n     */\n    function extractAllSelectors(text) {\n        var selectors = [];\n        var mode = CodeMirror.getMode({indentUnit: 2}, \"css\");\n        var state, lines, lineCount;\n        var token, style, stream, line;\n        var currentSelector = \"\";\n        var ruleStartChar = -1, ruleStartLine = -1;\n        var selectorStartChar = -1, selectorStartLine = -1;\n        var selectorGroupStartLine = -1, selectorGroupStartChar = -1;\n        var declListStartLine = -1, declListStartChar = -1;\n\n        // implement _firstToken()/_nextToken() methods to\n        // provide a single stream of tokens\n        \n        function _hasStream() {\n            while (stream.eol()) {\n                line++;\n                if (line >= lineCount) {\n                    return false;\n                }\n                if (currentSelector.match(/\\S/)) {\n                    // If we are in a current selector and starting a newline,\n                    // make sure there is whitespace in the selector\n                    currentSelector += \" \";\n                }\n                stream = new CodeMirror.StringStream(lines[line]);\n            }\n            return true;\n        }\n        \n        function _firstToken() {\n            state = CodeMirror.startState(mode);\n            lines = CodeMirror.splitLines(text);\n            lineCount = lines.length;\n            if (lineCount === 0) {\n                return false;\n            }\n            line = 0;\n            stream = new CodeMirror.StringStream(lines[line]);\n            if (!_hasStream()) {\n                return false;\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            return true;\n        }\n        \n        function _nextToken() {\n            // advance the stream past this token\n            stream.start = stream.pos;\n            if (!_hasStream()) {\n                return false;\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            return true;\n        }\n        \n        function _firstTokenSkippingWhitespace() {\n            if (!_firstToken()) {\n                return false;\n            }\n            while (!token.match(/\\S/)) {\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        \n        function _nextTokenSkippingWhitespace() {\n            if (!_nextToken()) {\n                return false;\n            }\n            while (!token.match(/\\S/)) {\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _isStartComment() {\n            return (token.match(/^\\/\\*/));\n        }\n        \n        function _parseComment() {\n            while (!token.match(/\\*\\/$/)) {\n                if (!_nextToken()) {\n                    break;\n                }\n            }\n        }\n\n        function _nextTokenSkippingComments() {\n            if (!_nextToken()) {\n                return false;\n            }\n            while (_isStartComment()) {\n                _parseComment();\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _parseSelector() {\n            \n            currentSelector = \"\";\n            selectorStartChar = stream.start;\n            selectorStartLine = line;\n            \n            // Everything until the next ',' or '{' is part of the current selector\n            while (token !== \",\" && token !== \"{\") {\n                currentSelector += token;\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n            }\n\n            currentSelector = currentSelector.trim();\n            if (currentSelector !== \"\") {\n                selectors.push({selector: currentSelector,\n                                ruleStartLine: ruleStartLine,\n                                ruleStartChar: ruleStartChar,\n                                selectorStartLine: selectorStartLine,\n                                selectorStartChar: selectorStartChar,\n                                declListEndLine: -1,\n                                selectorEndLine: line,\n                                selectorEndChar: stream.start - 1, // stream.start points to the first char of the non-selector token\n                                selectorGroupStartLine: selectorGroupStartLine,\n                                selectorGroupStartChar: selectorGroupStartChar\n                               });\n                currentSelector = \"\";\n            }\n            selectorStartChar = -1;\n        }\n        \n        function _parseSelectorList() {\n\n            selectorGroupStartLine = line;\n            selectorGroupStartChar = stream.start;\n\n            _parseSelector();\n            while (token === \",\") {\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n                _parseSelector();\n            }\n        }\n\n        function _parseDeclarationList() {\n\n            var j;\n            declListStartLine = line;\n            declListStartChar = stream.start;\n\n            // Since we're now in a declaration list, that means we also finished\n            // parsing the whole selector group. Therefore, reset selectorGroupStartLine\n            // so that next time we parse a selector we know it's a new group\n            selectorGroupStartLine = -1;\n            selectorGroupStartChar = -1;\n            ruleStartLine = -1;\n            ruleStartChar = -1;\n\n            // Skip everything until the next '}'\n            while (token !== \"}\") {\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n            }\n            \n            // assign this declaration list position to every selector on the stack\n            // that doesn't have a declaration list start and end line\n            for (j = selectors.length - 1; j >= 0; j--) {\n                if (selectors[j].declListEndLine !== -1) {\n                    break;\n                } else {\n                    selectors[j].declListStartLine = declListStartLine;\n                    selectors[j].declListStartChar = declListStartChar;\n                    selectors[j].declListEndLine = line;\n                    selectors[j].declListEndChar = stream.pos - 1; // stream.pos actually points to the char after the }\n                }\n            }\n        }\n        \n        function includeCommentInNextRule() {\n            if (ruleStartChar !== -1) {\n                return false;       // already included\n            }\n            if (stream.start > 0 && lines[line].substr(0, stream.start).indexOf(\"}\") !== -1) {\n                return false;       // on same line as '}', so it's for previous rule\n            }\n            return true;\n        }\n        \n        function _isStartAtRule() {\n            return (token.match(/^@/));\n        }\n        \n        function _parseAtRule() {\n\n            // reset these fields to ignore comments preceding @rules\n            ruleStartLine = -1;\n            ruleStartChar = -1;\n            selectorStartLine = -1;\n            selectorStartChar = -1;\n            selectorGroupStartLine = -1;\n            selectorGroupStartChar = -1;\n            \n            if (token.match(/@media/i)) {\n                // @media rule holds a rule list\n                \n                // Skip everything until the opening '{'\n                while (token !== \"{\") {\n                    if (!_nextTokenSkippingComments()) {\n                        break;\n                    }\n                }\n                _nextTokenSkippingWhitespace();    // skip past '{', to next non-ws token\n\n                // Parse rules until we see '}'\n                _parseRuleList(\"}\");\n\n            } else if (token.match(/@(charset|import|namespace)/i)) {\n                \n                // This code handles @rules in this format:\n                //   @rule ... ;\n                // Skip everything until the next ';'\n                while (token !== \";\") {\n                    if (!_nextTokenSkippingComments()) {\n                        break;\n                    }\n                }\n                \n            } else {\n                // This code handle @rules that use this format:\n                //    @rule ... { ... }\n                // such as @page, @keyframes (also -webkit-keyframes, etc.), and @font-face.\n                // Skip everything until the next '}'\n                while (token !== \"}\") {\n                    if (!_nextTokenSkippingComments()) {\n                        break;\n                    }\n                }\n            }\n        }\n\n        // parse a style rule\n        function _parseRule() {\n            _parseSelectorList();\n            _parseDeclarationList();\n        }\n        \n        function _parseRuleList(escapeToken) {\n            \n            while ((!escapeToken) || token !== escapeToken) {\n                if (_isStartAtRule()) {\n                    // @rule\n                    _parseAtRule();\n    \n                } else if (_isStartComment()) {\n                    // comment - make this part of style rule\n                    if (includeCommentInNextRule()) {\n                        ruleStartChar = stream.start;\n                        ruleStartLine = line;\n                    }\n                    _parseComment();\n    \n                } else {\n                    // Otherwise, it's style rule\n                    if (ruleStartChar === -1) {\n                        ruleStartChar = stream.start;\n                        ruleStartLine = line;\n                    }\n                    _parseRule();\n                }\n                \n                if (!_nextTokenSkippingWhitespace()) {\n                    break;\n                }\n            }\n        }\n        \n        // Do parsing\n\n        if (_firstTokenSkippingWhitespace()) {\n\n            // Style sheet is a rule list\n            _parseRuleList();\n        }\n\n        return selectors;\n    }\n    \n    /*\n     * This code can be used to create an \"independent\" HTML document that can be passed to jQuery\n     * calls. Allows using jQuery's CSS selector engine without actually putting anything in the browser's DOM\n     *\n    var _htmlDoctype = document.implementation.createDocumentType('html',\n        '-//W3C//DTD XHTML 1.0 Strict//EN',\n        'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'\n    );\n    var _htmlDocument = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', _htmlDoctype);\n\n    function checkIfSelectorSelectsHTML(selector, theHTML) {\n        $('html', _htmlDocument).html(theHTML);\n        return ($(selector, _htmlDocument).length > 0);\n    }\n    */\n    \n    /**\n     * Finds all instances of the specified selector in \"text\".\n     * Returns an Array of Objects with start and end properties.\n     *\n     * For Sprint 4, we only support simple selectors. This function will need to change\n     * dramatically to support full selectors.\n     *\n     * FUTURE: (JRB) It would be nice to eventually use the browser/jquery to do the selector evaluation.\n     * One way to do this would be to take the user's HTML, add a special attribute to every tag with a UID,\n     * and then construct a DOM (using the commented out code above). Then, give this DOM and the selector to \n     * jquery and ask what matches. If the node that the user's cursor is in comes back from jquery, then \n     * we know the selector applies.\n     *\n     * @param text {!String} CSS text to search\n     * @param selector {!String} selector to search for\n     * @return {Array.<{selectorGroupStartLine:number, declListEndLine:number, selector:string}>}\n     *      Array of objects containing the start and end line numbers (0-based, inclusive range) for each\n     *      matched selector.\n     */\n    function _findAllMatchingSelectorsInText(text, selector) {\n        var allSelectors = extractAllSelectors(text);\n        var result = [];\n        var i;\n        \n        // For sprint 4 we only match the rightmost simple selector, and ignore \n        // attribute selectors and pseudo selectors\n        var classOrIdSelector = selector[0] === \".\" || selector[0] === \"#\";\n        var prefix = \"\";\n        \n        // Escape initial \".\" in selector, if present.\n        if (selector[0] === \".\") {\n            selector = \"\\\\\" + selector;\n        }\n        \n        if (!classOrIdSelector) {\n            // Tag selectors must have nothing or whitespace before it.\n            selector = \"(^|\\\\s)\" + selector;\n        }\n        \n        var re = new RegExp(selector + \"(\\\\[[^\\\\]]*\\\\]|:{1,2}[\\\\w-()]+|\\\\.[\\\\w-]+|#[\\\\w-]+)*\\\\s*$\", classOrIdSelector ? \"\" : \"i\");\n        allSelectors.forEach(function (entry) {\n            if (entry.selector.search(re) !== -1) {\n                result.push(entry);\n            } else if (!classOrIdSelector) {\n                // Special case for tag selectors - match \"*\" as the rightmost character\n                if (entry.selector.trim().search(/\\*$/) !== -1) {\n                    result.push(entry);\n                }\n            }\n        });\n        \n        return result;\n    }\n    \n    \n    /**\n     * Converts the results of _findAllMatchingSelectorsInText() into a simpler bag of data and\n     * appends those new objects to the given 'resultSelectors' Array.\n     * @param {Array.<{document:Document, lineStart:number, lineEnd:number}>} resultSelectors\n     * @param {Array.<{selectorGroupStartLine:number, declListEndLine:number, selector:string}>} selectorsToAdd\n     * @param {!Document} sourceDoc\n     * @param {!number} lineOffset Amount to offset all line number info by. Used if the first line\n     *          of the parsed CSS text is not the first line of the sourceDoc.\n     */\n    function _addSelectorsToResults(resultSelectors, selectorsToAdd, sourceDoc, lineOffset) {\n        selectorsToAdd.forEach(function (selectorInfo) {\n            resultSelectors.push({\n                name: selectorInfo.selector,\n                document: sourceDoc,\n                lineStart: selectorInfo.ruleStartLine + lineOffset,\n                lineEnd: selectorInfo.declListEndLine + lineOffset\n            });\n        });\n    }\n    \n    /** Finds matching selectors in CSS files; adds them to 'resultSelectors' */\n    function _findMatchingRulesInCSSFiles(selector, resultSelectors) {\n        var result          = new $.Deferred(),\n            cssFilesResult  = FileIndexManager.getFileInfoList(\"css\");\n        \n        // Load one CSS file and search its contents\n        function _loadFileAndScan(fullPath, selector) {\n            var oneFileResult = new $.Deferred();\n            \n            DocumentManager.getDocumentForPath(fullPath)\n                .done(function (doc) {\n                    // Find all matching rules for the given CSS file's content, and add them to the\n                    // overall search result\n                    var oneCSSFileMatches = _findAllMatchingSelectorsInText(doc.getText(), selector);\n                    _addSelectorsToResults(resultSelectors, oneCSSFileMatches, doc, 0);\n                    \n                    oneFileResult.resolve();\n                })\n                .fail(function (error) {\n                    oneFileResult.reject(error);\n                });\n        \n            return oneFileResult.promise();\n        }\n        \n        // Load index of all CSS files; then process each CSS file in turn (see above)\n        cssFilesResult.done(function (fileInfos) {\n            Async.doInParallel(fileInfos, function (fileInfo, number) {\n                return _loadFileAndScan(fileInfo.fullPath, selector);\n            })\n                .pipe(result.resolve, result.reject);\n        });\n        \n        return result.promise();\n    }\n    \n    /** Finds matching selectors in the <style> block of a single HTML file; adds them to 'resultSelectors' */\n    function _findMatchingRulesInStyleBlocks(htmlDocument, selector, resultSelectors) {\n        // HTMLUtils requires a real CodeMirror instance; make sure we can give it the right Editor\n        var htmlEditor = EditorManager.getCurrentFullEditor();\n        if (htmlEditor.document !== htmlDocument) {\n            console.error(\"Cannot search for <style> blocks in HTML file other than current editor\");\n            return;\n        }\n        \n        // Find all <style> blocks in the HTML file\n        var styleBlocks = HTMLUtils.findStyleBlocks(htmlEditor);\n        \n        styleBlocks.forEach(function (styleBlockInfo) {\n            // Search this one <style> block's content, appending results to 'resultSelectors'\n            var oneStyleBlockMatches = _findAllMatchingSelectorsInText(styleBlockInfo.text, selector);\n            _addSelectorsToResults(resultSelectors, oneStyleBlockMatches, htmlDocument, styleBlockInfo.start.line);\n        });\n    }\n    \n    /**\n     * Return all rules matching the specified selector.\n     * For Sprint 4, we only look at the rightmost simple selector. For example, searching for \".foo\" will \n     * match these rules:\n     *  .foo {}\n     *  div .foo {}\n     *  div.foo {}\n     *  div .foo[bar=\"42\"] {}\n     *  div .foo:hovered {}\n     *  div .foo::first-child\n     * but will *not* match these rules:\n     *  .foobar {}\n     *  .foo .bar {}\n     *  div .foo .bar {}\n     *  .foo.bar {}\n     *\n     * @param {!String} selector The selector to match. This can be a tag selector, class selector or id selector\n     * @param {?Document} htmlDocument An HTML file for context (so we can search <style> blocks)\n     * @return {$.Promise} that will be resolved with an Array of objects containing the\n     *      source document, start line, and end line (0-based, inclusive range) for each matching declaration list.\n     *      Does not addRef() the documents returned in the array.\n     */\n    function findMatchingRules(selector, htmlDocument) {\n        var result          = new $.Deferred(),\n            resultSelectors = [];\n        \n        // Synchronously search for matches in <style> blocks\n        if (htmlDocument) {\n            _findMatchingRulesInStyleBlocks(htmlDocument, selector, resultSelectors);\n        }\n        \n        // Asynchronously search for matches in all the project's CSS files\n        // (results are appended together in same 'resultSelectors' array)\n        _findMatchingRulesInCSSFiles(selector, resultSelectors)\n            .done(function () {\n                result.resolve(resultSelectors);\n            })\n            .fail(function (error) {\n                result.reject(error);\n            });\n        \n        return result.promise();\n    }\n    \n    \n    exports._findAllMatchingSelectorsInText = _findAllMatchingSelectorsInText; // For testing only\n    exports.findMatchingRules = findMatchingRules;\n    exports.extractAllSelectors = extractAllSelectors;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n// FUTURE: Merge part (or all) of this class with InlineTextEditor\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\n/**\n * An inline editor for displaying and editing multiple text ranges. Each range corresponds to a \n * contiguous set of lines in a file. \n * \n * In the current implementation, only one range is visible at a time. A list on the right side\n * of the editor allows the user to select which range is visible. \n *\n * This module does not dispatch any events.\n */\n\ndefine('editor/MultiRangeInlineEditor',['require','exports','module','document/TextRange','editor/InlineTextEditor','editor/EditorManager','command/Commands','strings','command/CommandManager','utils/PerfUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var TextRange           = require(\"document/TextRange\").TextRange,\n        InlineTextEditor    = require(\"editor/InlineTextEditor\").InlineTextEditor,\n        EditorManager       = require(\"editor/EditorManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\");\n\n    /**\n     * Remove trailing \"px\" from a style size value.\n     * @param {!JQuery} $target Element in DOM\n     * @param {!string} styleName Style name to query\n     * @return {number} Style value converted from string to number, removing \"px\" units\n     */\n    function _parseStyleSize($target, styleName) {\n        return parseInt($target.css(styleName), 10);\n    }\n    \n    \n    /**\n     * @constructor\n     * Stores one search result: its source file, line range, etc. plus the DOM node representing it\n     * in the results list.\n     */\n    function SearchResultItem(rangeResult) {\n        this.name = rangeResult.name;\n        this.textRange = new TextRange(rangeResult.document, rangeResult.lineStart, rangeResult.lineEnd);\n        // this.$listItem is assigned in load()\n    }\n    SearchResultItem.prototype.name = null;\n    SearchResultItem.prototype.textRange = null;\n    SearchResultItem.prototype.$listItem = null;\n    \n    function _updateRangeLabel(listItem, range) {\n        var text = range.name + \" \" + range.textRange.document.file.name + \" : \" + (range.textRange.startLine + 1);\n        listItem.text(text);\n        listItem.attr(\"title\", text);\n    }\n    \n    /**\n     * @constructor\n     * @param {Array.<{name:String,document:Document,startLine:number,endLine:number}>} ranges The text ranges to display.\n     * @extends {InlineTextEditor}\n     */\n    function MultiRangeInlineEditor(ranges) {\n        InlineTextEditor.call(this);\n        \n        // Store the results to show in the range list. This creates TextRanges bound to the Document,\n        // which will stay up to date automatically (but we must be sure to detach them later)\n        this._ranges = ranges.map(function (rangeResult) {\n            return new SearchResultItem(rangeResult);\n        });\n        \n        this._selectedRangeIndex = -1;\n    }\n    MultiRangeInlineEditor.prototype = new InlineTextEditor();\n    MultiRangeInlineEditor.prototype.constructor = MultiRangeInlineEditor;\n    MultiRangeInlineEditor.prototype.parentClass = InlineTextEditor.prototype;\n    \n    MultiRangeInlineEditor.prototype.$editorsDiv = null;\n    MultiRangeInlineEditor.prototype.$relatedContainer = null;\n    MultiRangeInlineEditor.prototype.$selectedMarker = null;\n    \n    /** @type {Array.<SearchResultItem>} */\n    MultiRangeInlineEditor.prototype._ranges = null;\n    MultiRangeInlineEditor.prototype._selectedRangeIndex = null;\n\n    /** \n     * @override\n     * @param {!Editor} hostEditor  Outer Editor instance that inline editor will sit within.\n     * \n     */\n    MultiRangeInlineEditor.prototype.load = function (hostEditor) {\n        this.parentClass.load.call(this, hostEditor);\n        \n        // Container to hold all editors\n        var self = this;\n\n        // Bind event handlers\n        this._updateRelatedContainer = this._updateRelatedContainer.bind(this);\n        this._ensureCursorVisible = this._ensureCursorVisible.bind(this);\n        this._handleChange = this._handleChange.bind(this);\n        this._onClick = this._onClick.bind(this);\n\n        // Create DOM to hold editors and related list\n        this.$editorsDiv = $(window.document.createElement(\"div\")).addClass(\"inlineEditorHolder\");\n        \n        // Outer container for border-left and scrolling\n        this.$relatedContainer = $(window.document.createElement(\"div\")).addClass(\"related-container\");\n        this._relatedContainerInserted = false;\n        this._relatedContainerInsertedHandler = this._relatedContainerInsertedHandler.bind(this);\n        \n        // FIXME (jasonsj): deprecated event http://www.w3.org/TR/DOM-Level-3-Events/\n        this.$relatedContainer.on(\"DOMNodeInserted\", this._relatedContainerInsertedHandler);\n        \n        // List \"selection\" highlight\n        this.$selectedMarker = $(window.document.createElement(\"div\")).appendTo(this.$relatedContainer).addClass(\"selection\");\n        \n        // Inner container\n        var $related = $(window.document.createElement(\"div\")).appendTo(this.$relatedContainer).addClass(\"related\");\n        \n        // Range list\n        var $rangeList = $(window.document.createElement(\"ul\")).appendTo($related);\n        \n        // create range list & add listeners for range textrange changes\n        var rangeItemText;\n        this._ranges.forEach(function (range, i) {\n            // Create list item UI\n            var $rangeItem = $(window.document.createElement(\"li\")).appendTo($rangeList);\n            _updateRangeLabel($rangeItem, range);\n            $rangeItem.mousedown(function () {\n                self.setSelectedIndex(i);\n            });\n\n            self._ranges[i].$listItem = $rangeItem;\n            \n            // Update list item as TextRange changes\n            $(self._ranges[i].textRange).on(\"change\", function () {\n                _updateRangeLabel($rangeItem, range);\n            });\n            \n            // If TextRange lost sync, react just as we do for an inline Editor's lostContent event:\n            // close the whole inline widget\n            $(self._ranges[i].textRange).on(\"lostSync\", function () {\n                self.close();\n            });\n        });\n        \n        // select the first range\n        self.setSelectedIndex(0);\n        \n        // attach to main container\n        this.$htmlContent.append(this.$editorsDiv).append(this.$relatedContainer);\n        \n        // initialize position based on the main #editor-holder\n        window.setTimeout(this._updateRelatedContainer, 0);\n        \n        // Changes to the host editor should update the relatedContainer\n        // Note: normally it's not kosher to listen to changes on a specific editor,\n        // but in this case we're specifically concerned with changes in the given\n        // editor, not general document changes.\n        $(this.hostEditor).on(\"change\", this._updateRelatedContainer);\n        \n        // Update relatedContainer when this widget's position changes\n        $(this).on(\"offsetTopChanged\", this._updateRelatedContainer);\n        \n        // Listen to the window resize event to reposition the relatedContainer\n        // when the hostEditor's scrollbars visibility changes\n        $(window).on(\"resize\", this._updateRelatedContainer);\n        \n        // Listen for clicks directly on us, so we can set focus back to the editor\n        this.$htmlContent.on(\"click\", this._onClick);\n    };\n\n    /**\n     * Specify the range that is shown in the editor.\n     *\n     * @param {!number} index The index of the range to select.\n     */\n    MultiRangeInlineEditor.prototype.setSelectedIndex = function (index) {\n        var newIndex = Math.min(Math.max(0, index), this._ranges.length - 1);\n        \n        if (newIndex === this._selectedRangeIndex) {\n            return;\n        }\n\n        // Remove selected class(es)\n        var previousItem = (this._selectedRangeIndex >= 0) ? this._ranges[this._selectedRangeIndex].$listItem : null;\n        \n        if (previousItem) {\n            previousItem.toggleClass(\"selected\", false);\n        }\n        \n        this._selectedRangeIndex = newIndex;\n        \n        var $rangeItem = this._ranges[this._selectedRangeIndex].$listItem;\n        \n        this._ranges[this._selectedRangeIndex].$listItem.toggleClass(\"selected\", true);\n\n        // Remove previous editors\n        $(this.editors[0]).off(\"change\", this._updateRelatedContainer);\n\n        this.editors.forEach(function (editor) {\n            editor.destroy(); //release ref on Document\n        });\n        \n        this.editors = [];\n        this.$editorsDiv.children().remove();\n\n        // Add new editor\n        var range = this._getSelectedRange();\n        this.createInlineEditorFromText(range.textRange.document, range.textRange.startLine, range.textRange.endLine, this.$editorsDiv.get(0));\n        this.editors[0].focus();\n\n        // Changes in size to the inline editor should update the relatedContainer\n        // Note: normally it's not kosher to listen to changes on a specific editor,\n        // but in this case we're specifically concerned with changes in the given\n        // editor, not general document changes.\n        $(this.editors[0]).on(\"change\", this._handleChange);\n        \n        // Cursor activity in the inline editor may cause us to horizontally scroll.\n        $(this.editors[0]).on(\"cursorActivity\", this._ensureCursorVisible);\n\n        \n        this.editors[0].refresh();\n        // ensureVisibility is set to false because we don't want to scroll the main editor when the user selects a view\n        this.sizeInlineWidgetToContents(true, false);\n        this._updateRelatedContainer();\n\n        // scroll the selection to the rangeItem, use setTimeout to wait for DOM updates\n        var self = this;\n        window.setTimeout(function () {\n            var containerHeight = self.$relatedContainer.height(),\n                itemTop = $rangeItem.position().top,\n                scrollTop = self.$relatedContainer.scrollTop();\n            \n            self.$selectedMarker.css(\"top\", itemTop);\n            self.$selectedMarker.height($rangeItem.outerHeight());\n            \n            if (containerHeight <= 0) {\n                return;\n            }\n            \n            var paddingTop = _parseStyleSize($rangeItem.parent(), \"paddingTop\");\n            \n            if ((itemTop - paddingTop) < scrollTop) {\n                self.$relatedContainer.scrollTop(itemTop - paddingTop);\n            } else {\n                var itemBottom = itemTop + $rangeItem.height() + _parseStyleSize($rangeItem.parent(), \"paddingBottom\");\n                \n                if (itemBottom > (scrollTop + containerHeight)) {\n                    self.$relatedContainer.scrollTop(itemBottom - containerHeight);\n                }\n            }\n        }, 0);\n    };\n\n    /**\n     * Called any time inline is closed, whether manually (via closeThisInline()) or automatically\n     */\n    MultiRangeInlineEditor.prototype.onClosed = function () {\n        this.parentClass.onClosed.call(this); // super.onClosed()\n        \n        // remove resize handlers for relatedContainer\n        $(this.hostEditor).off(\"change\", this._updateRelatedContainer);\n        $(this.editors[0]).off(\"change\", this._handleChange);\n        $(this.editors[0]).off(\"cursorActivity\", this._ensureCursorVisible);\n        $(this).off(\"offsetTopChanged\", this._updateRelatedContainer);\n        $(window).off(\"resize\", this._updateRelatedContainer);\n        \n        // de-ref all the Documents in the search results\n        this._ranges.forEach(function (searchResult) {\n            searchResult.textRange.dispose();\n        });\n    };\n    \n    /**\n     * @private\n     * Set _relatedContainerInserted flag once the $relatedContainer is inserted in the DOM.\n     */\n    MultiRangeInlineEditor.prototype._relatedContainerInsertedHandler = function () {\n        this.$relatedContainer.off(\"DOMNodeInserted\", this._relatedContainerInsertedHandler);\n        this._relatedContainerInserted = true;\n    };\n    \n    /**\n     * Prevent clicks in the dead areas of the inlineWidget from changing the focus and insertion point in the editor.\n     * This is done by detecting clicks in the inlineWidget that are not inside the editor or the range list and\n     * restoring focus and the insertion point.\n     */\n    MultiRangeInlineEditor.prototype._onClick = function (event) {\n        var childEditor = this.editors[0],\n            editorRoot = childEditor.getRootElement(),\n            editorPos = $(editorRoot).offset();\n        \n        function containsClick($parent) {\n            return $parent.find(event.target) > 0 || $parent[0] === event.target;\n        }\n        \n        // Ignore clicks in editor and clicks on filename link\n        if (!containsClick($(editorRoot)) && !containsClick($(\".filename\", this.$editorsDiv))) {\n            childEditor.focus();\n            // Only set the cursor if the click isn't in the range list.\n            if (!containsClick(this.$relatedContainer)) {\n                if (event.pageY < editorPos.top) {\n                    childEditor.setCursorPos(0, 0);\n                } else if (event.pageY > editorPos.top + $(editorRoot).height()) {\n                    var lastLine = childEditor.getLastVisibleLine();\n                    childEditor.setCursorPos(lastLine, childEditor.document.getLine(lastLine).length);\n                }\n            }\n        }\n    };\n    \n    /**\n     * Set the size, position, and clip rect of the range list.\n     */\n    MultiRangeInlineEditor.prototype._updateRelatedContainer = function () {\n        var borderThickness = (this.$htmlContent.outerHeight() - this.$htmlContent.innerHeight()) / 2;\n        this.$relatedContainer.css(\"top\", this.$htmlContent.offset().top + borderThickness);\n        this.$relatedContainer.height(this.$htmlContent.height());\n        \n        // Because we're using position: fixed, we need to explicitly clip the range list if it crosses\n        // out of the top or bottom of the scroller area.\n        var hostScroller = this.hostEditor.getScrollerElement(),\n            rcTop = this.$relatedContainer.offset().top,\n            rcHeight = this.$relatedContainer.outerHeight(),\n            rcBottom = rcTop + rcHeight,\n            scrollerOffset = $(hostScroller).offset(),\n            scrollerTop = scrollerOffset.top,\n            scrollerBottom = scrollerTop + hostScroller.clientHeight,\n            scrollerLeft = scrollerOffset.left,\n            rightOffset = $(window.document.body).outerWidth() - (scrollerLeft + hostScroller.clientWidth);\n        if (rcTop < scrollerTop || rcBottom > scrollerBottom) {\n            this.$relatedContainer.css(\"clip\", \"rect(\" + Math.max(scrollerTop - rcTop, 0) + \"px, auto, \" +\n                                       (rcHeight - Math.max(rcBottom - scrollerBottom, 0)) + \"px, auto)\");\n        } else {\n            this.$relatedContainer.css(\"clip\", \"\");\n        }\n        \n        // Constrain relatedContainer width to half of the scroller width\n        var relatedContainerWidth = this.$relatedContainer.width();\n        if (this._relatedContainerInserted) {\n            if (this._relatedContainerDefaultWidth === undefined) {\n                this._relatedContainerDefaultWidth = relatedContainerWidth;\n            }\n            \n            var halfWidth = Math.floor(hostScroller.clientWidth / 2);\n            relatedContainerWidth = Math.min(this._relatedContainerDefaultWidth, halfWidth);\n            this.$relatedContainer.width(relatedContainerWidth);\n        }\n        \n        // Position immediately to the left of the main editor's scrollbar.\n        this.$relatedContainer.css(\"right\", rightOffset + \"px\");\n\n        // Add extra padding to the right edge of the widget to account for the range list.\n        this.$htmlContent.css(\"padding-right\", this.$relatedContainer.outerWidth() + \"px\");\n        \n        // Set the minimum width of the widget (which doesn't include the padding) to the width\n        // of CodeMirror's linespace, so that the total width will be at least as large as the\n        // width of the host editor's code plus the padding for the range list. We need to do this\n        // rather than just setting min-width to 100% because adding padding for the range list\n        // actually pushes out the width of the container, so we would end up continuously\n        // growing the overall width.\n        // This is a bit of a hack since it relies on knowing some detail about the innards of CodeMirror.\n        var lineSpace = this.hostEditor._getLineSpaceElement(),\n            minWidth = $(lineSpace).offset().left - this.$htmlContent.offset().left + lineSpace.scrollWidth;\n        this.$htmlContent.css(\"min-width\", minWidth + \"px\");\n    };\n    \n    /**\n     * Based on the position of the cursor in the inline editor, determine whether we need to change the\n     * scroll position of the host editor to ensure that the cursor is visible.\n     */\n    MultiRangeInlineEditor.prototype._ensureCursorVisible = function () {\n        if ($.contains(this.editors[0].getRootElement(), window.document.activeElement)) {\n            var cursorCoords = this.editors[0]._codeMirror.cursorCoords(),\n                lineSpaceOffset = $(this.editors[0]._getLineSpaceElement()).offset(),\n                rangeListOffset = this.$relatedContainer.offset();\n            // If we're off the left-hand side, we just want to scroll it into view normally. But\n            // if we're underneath the range list on the right, we want to ask the host editor to \n            // scroll far enough that the current cursor position is visible to the left of the range \n            // list. (Because we always add extra padding for the range list, this is always possible.)\n            if (cursorCoords.x >= rangeListOffset.left) {\n                cursorCoords.x += this.$relatedContainer.outerWidth();\n            }\n            \n            // Vertically, we want to set the scroll position relative to the overall host editor, not\n            // the lineSpace of the widget itself. Also, we can't use the lineSpace here, because its top\n            // position just corresponds to whatever CodeMirror happens to have rendered at the top. So\n            // we need to figure out our position relative to the top of the virtual scroll area, which is\n            // the top of the actual scroller minus the scroll position.\n            var scrollerTop = $(this.hostEditor.getScrollerElement()).offset().top - this.hostEditor.getScrollPos().y;\n            this.hostEditor._codeMirror.scrollIntoView(cursorCoords.x - lineSpaceOffset.left,\n                                                       cursorCoords.y - scrollerTop,\n                                                       cursorCoords.x - lineSpaceOffset.left,\n                                                       cursorCoords.yBot - scrollerTop);\n        }\n    };\n    \n    /**\n     * Handle a change event from the editor. Update the related container and make sure the\n     * cursor is visible.\n     */\n    MultiRangeInlineEditor.prototype._handleChange = function () {\n        this._updateRelatedContainer();\n        this._ensureCursorVisible();\n    };\n\n    /**\n     * @return {Array.<SearchResultItem>}\n     */\n    MultiRangeInlineEditor.prototype._getRanges = function () {\n        return this._ranges;\n    };\n\n    /**\n     * @return {!SearchResultItem}\n     */\n    MultiRangeInlineEditor.prototype._getSelectedRange = function () {\n        return this._ranges[this._selectedRangeIndex];\n    };\n\n    /**\n     * Display the next range in the range list\n     */\n    MultiRangeInlineEditor.prototype._selectNextRange = function () {\n        this.setSelectedIndex(this._selectedRangeIndex + 1);\n    };\n    \n    /**\n     *  Display the previous range in the range list\n     */\n    MultiRangeInlineEditor.prototype._selectPreviousRange = function () {\n        this.setSelectedIndex(this._selectedRangeIndex - 1);\n    };\n\n    /**\n     * Sizes the inline widget height to be the maximum between the range list height and the editor height\n     * @override \n     * @param {boolean} force the editor to resize\n     * @param {boolean} ensureVisibility makes the parent editor scroll to display the inline editor. Default true.\n     */\n    MultiRangeInlineEditor.prototype.sizeInlineWidgetToContents = function (force, ensureVisibility) {\n        // Size the code mirror editors height to the editor content\n        this.parentClass.sizeInlineWidgetToContents.call(this, force);\n        // Size the widget height to the max between the editor content and the related ranges list\n        var widgetHeight = Math.max(this.$relatedContainer.find(\".related\").height(), this.$editorsDiv.height());\n        this.hostEditor.setInlineWidgetHeight(this, widgetHeight, ensureVisibility);\n\n        // The related ranges container size itself based on htmlContent which is set by setInlineWidgetHeight above.\n        this._updateRelatedContainer();\n    };\n\n    /**\n     * Returns the currently focused MultiRangeInlineEditor.\n     * @returns {MultiRangeInlineEditor}\n     */\n    function _getFocusedMultiRangeInlineEditor() {\n        \n        var focusedMultiRangeInlineEditor = null,\n            result = EditorManager.getFocusedInlineWidget();\n        \n        if (result) {\n            var focusedWidget = result.widget;\n            if (focusedWidget && focusedWidget instanceof MultiRangeInlineEditor) {\n                focusedMultiRangeInlineEditor = focusedWidget;\n            }\n        }\n        \n        return focusedMultiRangeInlineEditor;\n    }\n\n    /**\n     * Previous Range command handler\n     */\n    function _previousRange() {\n        var focusedMultiRangeInlineEditor = _getFocusedMultiRangeInlineEditor();\n        if (focusedMultiRangeInlineEditor) {\n            focusedMultiRangeInlineEditor._selectPreviousRange();\n        }\n    }\n    \n    /**\n     * Next Range command handler\n     */\n    function _nextRange() {\n        var focusedMultiRangeInlineEditor = _getFocusedMultiRangeInlineEditor();\n        if (focusedMultiRangeInlineEditor) {\n            focusedMultiRangeInlineEditor._selectNextRange();\n        }\n    }\n    \n    CommandManager.register(Strings.CMD_QUICK_EDIT_PREV_MATCH,      Commands.QUICK_EDIT_PREV_MATCH, _previousRange);\n    CommandManager.register(Strings.CMD_QUICK_EDIT_NEXT_MATCH,      Commands.QUICK_EDIT_NEXT_MATCH, _nextRange);\n\n    exports.MultiRangeInlineEditor = MultiRangeInlineEditor;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\ndefine('editor/CSSInlineEditor',['require','exports','module','language/CSSUtils','editor/EditorManager','language/HTMLUtils','editor/MultiRangeInlineEditor'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var CSSUtils                = require(\"language/CSSUtils\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        HTMLUtils               = require(\"language/HTMLUtils\"),\n        MultiRangeInlineEditor  = require(\"editor/MultiRangeInlineEditor\").MultiRangeInlineEditor;\n\n    /**\n     * Given a position in an HTML editor, returns the relevant selector for the attribute/tag\n     * surrounding that position, or \"\" if none is found.\n     * @param {!Editor} editor\n     * @private\n     */\n    function _getSelectorName(editor, pos) {\n        var tagInfo = HTMLUtils.getTagInfo(editor, pos),\n            selectorName = \"\";\n        \n        if (tagInfo.position.tokenType === HTMLUtils.TAG_NAME) {\n            // Type selector\n            selectorName = tagInfo.tagName;\n        } else if (tagInfo.position.tokenType === HTMLUtils.ATTR_NAME ||\n                   tagInfo.position.tokenType === HTMLUtils.ATTR_VALUE) {\n            if (tagInfo.attr.name === \"class\") {\n                // Class selector. We only look for the class name\n                // that includes the insertion point. For example, if\n                // the attribute is: \n                //   class=\"error-dialog modal hide\"\n                // and the insertion point is inside \"modal\", we want \".modal\"\n                var attributeValue = tagInfo.attr.value;\n                var startIndex = attributeValue.substr(0, tagInfo.position.offset).lastIndexOf(\" \");\n                var endIndex = attributeValue.indexOf(\" \", tagInfo.position.offset);\n                selectorName = \".\" +\n                    attributeValue.substring(\n                        startIndex === -1 ? 0 : startIndex + 1,\n                        endIndex === -1 ? attributeValue.length : endIndex\n                    );\n                \n                // If the insertion point is surrounded by space, selectorName is \".\"\n                // Check for that here\n                if (selectorName === \".\") {\n                    selectorName = \"\";\n                }\n            } else if (tagInfo.attr.name === \"id\") {\n                // ID selector\n                selectorName = \"#\" + tagInfo.attr.value;\n            }\n        }\n        \n        return selectorName;\n    }\n\n    /**\n     * This function is registered with EditManager as an inline editor provider. It creates a CSSInlineEditor\n     * when cursor is on an HTML tag name, class attribute, or id attribute, find associated\n     * CSS rules and show (one/all of them) in an inline editor.\n     *\n     * @param {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {$.Promise} a promise that will be resolved with an InlineWidget\n     *      or null if we're not going to provide anything.\n     */\n    function htmlToCSSProvider(hostEditor, pos) {\n        // Only provide a CSS editor when cursor is in HTML content\n        if (hostEditor.getModeForSelection() !== \"html\") {\n            return null;\n        }\n        \n        // Only provide CSS editor if the selection is within a single line\n        var sel = hostEditor.getSelection(false);\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n        \n        // Always use the selection start for determining selector name. The pos\n        // parameter is usually the selection end.        \n        var selectorName = _getSelectorName(hostEditor, hostEditor.getSelection(false).start);\n        if (selectorName === \"\") {\n            return null;\n        }\n\n        var result = new $.Deferred();\n\n        CSSUtils.findMatchingRules(selectorName, hostEditor.document)\n            .done(function (rules) {\n                if (rules && rules.length > 0) {\n                    var cssInlineEditor = new MultiRangeInlineEditor(rules);\n                    cssInlineEditor.load(hostEditor);\n                    \n                    result.resolve(cssInlineEditor);\n                } else {\n                    // No matching rules were found.\n                    result.reject();\n                }\n            })\n            .fail(function () {\n                console.log(\"Error in findMatchingRules()\");\n                result.reject();\n            });\n        \n        return result.promise();\n    }\n\n    EditorManager.registerInlineEditProvider(htmlToCSSProvider);\n\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n/**\n * Defines a ChangedDocumentTracker class to monitor changes to files in the current project.\n */\ndefine('document/ChangedDocumentTracker',['require','exports','module','document/DocumentManager','project/ProjectManager'],function (require, exports, module) {\n    \n    \n    var DocumentManager = require(\"document/DocumentManager\"),\n        ProjectManager  = require(\"project/ProjectManager\");\n    \n    /**\n     * Tracks \"change\" events on opened Documents. Used to monitor changes\n     * to documents in-memory and update caches. Assumes all documents have\n     * changed when the Brackets window loses and regains focus. Does not\n     * read timestamps of files on disk. Clients may optionally track file\n     * timestamps on disk independently.\n     */\n    function ChangedDocumentTracker() {\n        var self = this;\n        \n        this._changedPaths = {};\n        this._windowFocus = true;\n        this._addListener = this._addListener.bind(this);\n        this._removeListener = this._removeListener.bind(this);\n        this._onChange = this._onChange.bind(this);\n        this._onWindowFocus = this._onWindowFocus.bind(this);\n\n        $(DocumentManager).on(\"afterDocumentCreate\", function (event, doc) {\n            // Only track documents in the current project\n            if (ProjectManager.isWithinProject(doc.file.fullPath)) {\n                self._addListener(doc);\n            }\n        });\n\n        $(DocumentManager).on(\"beforeDocumentDelete\", function (event, doc) {\n            // In case a document somehow remains loaded after its project\n            // has been closed, unconditionally attempt to remove the listener.\n            self._removeListener(doc);\n        });\n\n        $(window).focus(this._onWindowFocus);\n    }\n    \n    /**\n     * @private\n     * Assumes all files are changed when the window loses and regains focus.\n     */\n    ChangedDocumentTracker.prototype._addListener = function (doc) {\n        $(doc).on(\"change\", this._onChange);\n    };\n\n    /**\n     * @private\n     */\n    ChangedDocumentTracker.prototype._removeListener = function (doc) {\n        $(doc).off(\"change\", this._onChange);\n    };\n\n    /**\n     * @private\n     * Assumes all files are changed when the window loses and regains focus.\n     */\n    ChangedDocumentTracker.prototype._onWindowFocus = function (event, doc) {\n        this._windowFocus = true;\n    };\n    \n    /**\n     * @private\n     * Tracks changed documents.\n     */\n    ChangedDocumentTracker.prototype._onChange = function (event, doc) {\n        // if it was already changed, and the client hasn't reset the tracker,\n        // then leave it changed.\n        this._changedPaths[doc.file.fullPath] = true;\n    };\n    \n    /**\n     * Empty the set of dirty paths. Begin tracking new dirty documents. \n     */\n    ChangedDocumentTracker.prototype.reset = function () {\n        this._changedPaths = {};\n        this._windowFocus = false;\n    };\n    \n    /**\n     * Check if a file path is dirty.\n     * @param {!string} file path\n     * @return {!boolean} Returns true if the file was dirtied since the last reset.\n     */\n    ChangedDocumentTracker.prototype.isPathChanged = function (path) {\n        return this._windowFocus || this._changedPaths[path];\n    };\n    \n    /**\n     * Get the set of changed paths since the last reset.\n     * @return {Array.<string>} Changed file paths\n     */\n    ChangedDocumentTracker.prototype.getChangedPaths = function () {\n        return $.makeArray(this._changedPaths);\n    };\n\n    module.exports = ChangedDocumentTracker;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils, CodeMirror */\n\n/**\n * Set of utilities for simple parsing of JS text.\n */\ndefine('language/JSUtils',['require','exports','module','utils/Async','document/DocumentManager','document/ChangedDocumentTracker','file/NativeFileSystem','utils/PerfUtils','utils/StringUtils'],function (require, exports, module) {\n    \n    \n    // Load brackets modules\n    var Async                   = require(\"utils/Async\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        ChangedDocumentTracker  = require(\"document/ChangedDocumentTracker\"),\n        NativeFileSystem        = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        StringUtils             = require(\"utils/StringUtils\");\n\n    /**\n     * Tracks dirty documents between invocations of findMatchingFunctions.\n     * @type {ChangedDocumentTracker}\n     */\n    var _changedDocumentTracker = new ChangedDocumentTracker();\n    \n    /**\n     * Function matching regular expression. Recognizes the forms:\n     * \"function functionName()\", \"functionName = function()\", and\n     * \"functionName: function()\".\n     *\n     * Note: JavaScript identifier matching is not strictly to spec. This\n     * RegExp matches any sequence of characters that is not whitespace.\n     * @type {RegExp}\n     */\n    var _functionRegExp = /(function\\s+([$_A-Za-z\\u007F-\\uFFFF][$_A-Za-z0-9\\u007F-\\uFFFF]*)\\s*(\\([^)]*\\)))|(([$_A-Za-z\\u007F-\\uFFFF][$_A-Za-z0-9\\u007F-\\uFFFF]*)\\s*[:=]\\s*function\\s*(\\([^)]*\\)))/g;\n    \n    /**\n     * @private\n     * Return an Array with names and offsets for all functions in the specified text\n     * @param {!string} text Document text\n     * @return {Object.<string, Array.<{offsetStart: number, offsetEnd: number}>}\n     */\n    function _findAllFunctionsInText(text) {\n        var results = {},\n            functionName,\n            match;\n        \n        PerfUtils.markStart(PerfUtils.JSUTILS_REGEXP);\n        \n        while ((match = _functionRegExp.exec(text)) !== null) {\n            functionName = (match[2] || match[5]).trim();\n            \n            if (!Array.isArray(results[functionName])) {\n                results[functionName] = [];\n            }\n            \n            results[functionName].push({offsetStart: match.index});\n        }\n        \n        PerfUtils.addMeasurement(PerfUtils.JSUTILS_REGEXP);\n        \n        return results;\n    }\n    \n    // Given the start offset of a function definition (before the opening brace), find\n    // the end offset for the function (the closing \"}\"). Returns the position one past the\n    // close brace. Properly ignores braces inside comments, strings, and regexp literals.\n    function _getFunctionEndOffset(text, offsetStart) {\n        var mode = CodeMirror.getMode({}, \"javascript\");\n        var state = CodeMirror.startState(mode), stream, style, token;\n        var curOffset = offsetStart, length = text.length, blockCount = 0, lineStart;\n        var foundStartBrace = false;\n        \n        // Get a stream for the next line, and update curOffset and lineStart to point to the \n        // beginning of that next line. Returns false if we're at the end of the text.\n        function nextLine() {\n            if (stream) {\n                curOffset++; // account for \\n\n                if (curOffset >= length) {\n                    return false;\n                }\n            }\n            lineStart = curOffset;\n            var lineEnd = text.indexOf(\"\\n\", lineStart);\n            if (lineEnd === -1) {\n                lineEnd = length;\n            }\n            stream = new CodeMirror.StringStream(text.slice(curOffset, lineEnd));\n            return true;\n        }\n        \n        // Get the next token, updating the style and token to refer to the current\n        // token, and updating the curOffset to point to the end of the token (relative\n        // to the start of the original text).\n        function nextToken() {\n            if (curOffset >= length) {\n                return false;\n            }\n            if (stream) {\n                // Set the start of the next token to the current stream position.\n                stream.start = stream.pos;\n            }\n            while (!stream || stream.eol()) {\n                if (!nextLine()) {\n                    return false;\n                }\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            curOffset = lineStart + stream.pos;\n            return true;\n        }\n\n        while (nextToken()) {\n            if (style !== \"comment\" && style !== \"regexp\" && style !== \"string\") {\n                if (token === \"{\") {\n                    foundStartBrace = true;\n                    blockCount++;\n                } else if (token === \"}\") {\n                    blockCount--;\n                }\n            }\n\n            // blockCount starts at 0, so we don't want to check if it hits 0\n            // again until we've actually gone past the start of the function body.\n            if (foundStartBrace && blockCount <= 0) {\n                return curOffset;\n            }\n        }\n        \n        // Shouldn't get here, but if we do, return the end of the text as the offset.\n        return length;\n    }\n\n    /**\n     * @private\n     * Computes function offsetEnd, lineStart and lineEnd. Appends a result record to rangeResults.\n     * @param {!Document} doc\n     * @param {!string} functionName\n     * @param {!Array.<{offsetStart: number, offsetEnd: number}>} functions\n     * @param {!Array.<{document: Document, name: string, lineStart: number, lineEnd: number}>} rangeResults\n     */\n    function _computeOffsets(doc, functionName, functions, rangeResults) {\n        var text    = doc.getText(),\n            lines   = StringUtils.getLines(text);\n        \n        functions.forEach(function (funcEntry) {\n            if (!funcEntry.offsetEnd) {\n                PerfUtils.markStart(PerfUtils.JSUTILS_END_OFFSET);\n                \n                funcEntry.offsetEnd = _getFunctionEndOffset(text, funcEntry.offsetStart);\n                funcEntry.lineStart = StringUtils.offsetToLineNum(lines, funcEntry.offsetStart);\n                funcEntry.lineEnd   = StringUtils.offsetToLineNum(lines, funcEntry.offsetEnd);\n                \n                PerfUtils.addMeasurement(PerfUtils.JSUTILS_END_OFFSET);\n            }\n            \n            rangeResults.push({\n                document:   doc,\n                name:       functionName,\n                lineStart:  funcEntry.lineStart,\n                lineEnd:    funcEntry.lineEnd\n            });\n        });\n    }\n    \n    /**\n     * @private\n     * Read a file and build a function list. Result is cached in fileInfo.\n     * @param {!FileInfo} fileInfo File to parse\n     * @param {!$.Deferred} result Deferred to resolve with all functions found and the document\n     */\n    function _readFile(fileInfo, result) {\n        DocumentManager.getDocumentForPath(fileInfo.fullPath)\n            .done(function (doc) {\n                var allFunctions = _findAllFunctionsInText(doc.getText());\n                \n                // Cache the result in the fileInfo object\n                fileInfo.JSUtils = {};\n                fileInfo.JSUtils.functions = allFunctions;\n                fileInfo.JSUtils.timestamp = doc.diskTimestamp;\n                \n                result.resolve({doc: doc, functions: allFunctions});\n            })\n            .fail(function (error) {\n                result.reject(error);\n            });\n    }\n    \n    /**\n     * Determines if the document function cache is up to date. \n     * @param {FileInfo} fileInfo\n     * @return {$.Promise} A promise resolved with true with true when a function cache is available for the document. Resolves\n     *   with false when there is no cache or the cache is stale.\n     */\n    function _shouldGetFromCache(fileInfo) {\n        var result = new $.Deferred(),\n            isChanged = _changedDocumentTracker.isPathChanged(fileInfo.fullPath);\n        \n        if (isChanged && fileInfo.JSUtils) {\n            // See if it's dirty and in the working set first\n            var doc = DocumentManager.getOpenDocumentForPath(fileInfo.fullPath);\n            \n            if (doc && doc.isDirty) {\n                result.resolve(false);\n            } else {\n                // If a cache exists, check the timestamp on disk\n                var file = new NativeFileSystem.FileEntry(fileInfo.fullPath);\n                \n                file.getMetadata(\n                    function (metadata) {\n                        result.resolve(fileInfo.JSUtils.timestamp === metadata.diskTimestamp);\n                    },\n                    function (error) {\n                        result.reject(error);\n                    }\n                );\n            }\n        } else {\n            // Use the cache if the file did not change and the cache exists\n            result.resolve(!isChanged && fileInfo.JSUtils);\n        }\n\n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Compute lineStart and lineEnd for each matched function\n     * @param {!Array.<{doc: Document, fileInfo: FileInfo, functions: Array.<offsetStart: number, offsetEnd: number>}>} docEntries\n     * @param {!string} functionName\n     * @param {!Array.<document: Document, name: string, lineStart: number, lineEnd: number>} rangeResults\n     * @return {$.Promise} A promise resolved with an array of document ranges to populate a MultiRangeInlineEditor.\n     */\n    function _getOffsetsForFunction(docEntries, functionName) {\n        // Filter for documents that contain the named function\n        var result              = new $.Deferred(),\n            matchedDocuments    = [],\n            rangeResults        = [],\n            functionsInDocument;\n        \n        docEntries.forEach(function (docEntry) {\n            functionsInDocument = docEntry.functions[functionName];\n            \n            if (functionsInDocument) {\n                matchedDocuments.push({doc: docEntry.doc, fileInfo: docEntry.fileInfo, functions: functionsInDocument});\n            }\n        });\n        \n        Async.doInParallel(matchedDocuments, function (docEntry) {\n            var doc         = docEntry.doc,\n                oneResult   = new $.Deferred();\n            \n            // doc will be undefined if we hit the cache\n            if (!doc) {\n                DocumentManager.getDocumentForPath(docEntry.fileInfo.fullPath)\n                    .done(function (fetchedDoc) {\n                        _computeOffsets(fetchedDoc, functionName, docEntry.functions, rangeResults);\n                    })\n                    .always(function () {\n                        oneResult.resolve();\n                    });\n            } else {\n                _computeOffsets(doc, functionName, docEntry.functions, rangeResults);\n                oneResult.resolve();\n            }\n            \n            return oneResult.promise();\n        }).done(function () {\n            result.resolve(rangeResults);\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n     * Resolves with a record containing the Document or FileInfo and an Array of all\n     * function names with offsets for the specified file. Results may be cached.\n     * @param {FileInfo} fileInfo\n     * @return {$.Promise} A promise resolved with a document info object that\n     *   contains a map of all function names from the document and each function's start offset. \n     */\n    function _getFunctionsForFile(fileInfo) {\n        var result = new $.Deferred();\n            \n        _shouldGetFromCache(fileInfo)\n            .done(function (useCache) {\n                if (useCache) {\n                    // Return cached data. doc property is undefined since we hit the cache.\n                    // _getOffsets() will fetch the Document if necessary.\n                    result.resolve({/*doc: undefined,*/fileInfo: fileInfo, functions: fileInfo.JSUtils.functions});\n                } else {\n                    _readFile(fileInfo, result);\n                }\n            }).fail(function (err) {\n                result.reject(err);\n            });\n        \n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Get all functions for each FileInfo.\n     * @param {Array.<FileInfo>} fileInfos\n     * @return {$.Promise} A promise resolved with an array of document info objects that each\n     *   contain a map of all function names from the document and each function's start offset.\n     */\n    function _getFunctionsInFiles(fileInfos) {\n        var result          = new $.Deferred(),\n            docEntries      = [];\n        \n        PerfUtils.markStart(PerfUtils.JSUTILS_GET_ALL_FUNCTIONS);\n        \n        Async.doInParallel(fileInfos, function (fileInfo) {\n            var oneResult = new $.Deferred();\n            \n            _getFunctionsForFile(fileInfo)\n                .done(function (docInfo) {\n                    docEntries.push(docInfo);\n                })\n                .always(function (error) {\n                    // If one file fails, continue to search\n                    oneResult.resolve();\n                });\n            \n            return oneResult.promise();\n        }).always(function () {\n            // Reset ChangedDocumentTracker now that the cache is up to date.\n            _changedDocumentTracker.reset();\n            \n            PerfUtils.addMeasurement(PerfUtils.JSUTILS_GET_ALL_FUNCTIONS);\n            result.resolve(docEntries);\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n     * Return all functions that have the specified name.\n     *\n     * @param {!String} functionName The name to match.\n     * @param {!Array.<FileIndexManager.FileInfo>} fileInfos The array of files to search.\n     * @return {$.Promise} that will be resolved with an Array of objects containing the\n     *      source document, start line, and end line (0-based, inclusive range) for each matching function list.\n     *      Does not addRef() the documents returned in the array.\n     */\n    function findMatchingFunctions(functionName, fileInfos) {\n        var result          = new $.Deferred(),\n            jsFiles         = [],\n            docEntries      = [];\n        \n        // Filter fileInfos for .js files\n        jsFiles = fileInfos.filter(function (fileInfo) {\n            return (/^\\.js/i).test(PathUtils.filenameExtension(fileInfo.fullPath));\n        });\n        \n        // RegExp search (or cache lookup) for all functions in the project\n        _getFunctionsInFiles(jsFiles).done(function (docEntries) {\n            // Compute offsets for all matched functions\n            _getOffsetsForFunction(docEntries, functionName).done(function (rangeResults) {\n                result.resolve(rangeResults);\n            });\n        });\n        \n        return result.promise();\n    }\n\n    /**\n     * Finds all instances of the specified functionName in \"text\".\n     * Returns an Array of Objects with start and end properties.\n     *\n     * @param text {!String} JS text to search\n     * @param functionName {!String} function name to search for\n     * @return {Array.<{offset:number, functionName:string}>}\n     *      Array of objects containing the start offset for each matched function name.\n     */\n    function findAllMatchingFunctionsInText(text, functionName) {\n        var allFunctions = _findAllFunctionsInText(text);\n        var result = [];\n        var lines = text.split(\"\\n\");\n        \n        $.each(allFunctions, function (index, functions) {\n            if (index === functionName || functionName === \"*\") {\n                functions.forEach(function (funcEntry) {\n                    var endOffset = _getFunctionEndOffset(text, funcEntry.offsetStart);\n                    result.push({\n                        name: index,\n                        lineStart: StringUtils.offsetToLineNum(lines, funcEntry.offsetStart),\n                        lineEnd: StringUtils.offsetToLineNum(lines, endOffset)\n                    });\n                });\n            }\n        });\n         \n        return result;\n    }\n    \n    PerfUtils.createPerfMeasurement(\"JSUTILS_GET_ALL_FUNCTIONS\", \"Parallel file search across project\");\n    PerfUtils.createPerfMeasurement(\"JSUTILS_REGEXP\", \"RegExp search for all functions\");\n    PerfUtils.createPerfMeasurement(\"JSUTILS_END_OFFSET\", \"Find end offset for a single matched function\");\n\n    exports.findAllMatchingFunctionsInText = findAllMatchingFunctionsInText;\n    exports._getFunctionEndOffset = _getFunctionEndOffset; // For testing only\n    exports.findMatchingFunctions = findMatchingFunctions;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $  */\n\n/**\n * WorkingSetView generates the UI for the list of the files user is editing based on the model provided by EditorManager.\n * The UI allows the user to see what files are open/dirty and allows them to close files and specify the current editor.\n *\n */\ndefine('project/WorkingSetView',['require','exports','module','document/DocumentManager','command/CommandManager','command/Commands','editor/EditorManager','project/FileViewController','file/NativeFileSystem','utils/ViewUtils'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var DocumentManager       = require(\"document/DocumentManager\"),\n        CommandManager        = require(\"command/CommandManager\"),\n        Commands              = require(\"command/Commands\"),\n        EditorManager         = require(\"editor/EditorManager\"),\n        FileViewController    = require(\"project/FileViewController\"),\n        NativeFileSystem      = require(\"file/NativeFileSystem\").NativeFileSystem,\n        ViewUtils             = require(\"utils/ViewUtils\");\n    \n    \n    /** Each list item in the working set stores a references to the related document in the list item's data.  \n     *  Use listItem.data(_FILE_KEY) to get the document reference\n     */\n    var _FILE_KEY = \"file\",\n        $openFilesContainer,\n        $openFilesList;\n    \n    /**\n     * @private\n     * Redraw selection when list size changes or DocumentManager currentDocument changes.\n     */\n    function _fireSelectionChanged() {\n        // redraw selection\n        $openFilesList.trigger(\"selectionChanged\");\n\n        // in-lieu of resize events, manually trigger contentChanged to update scroll shadows\n        $openFilesContainer.triggerHandler(\"contentChanged\");\n    }\n\n    /**\n     * @private\n     * adds the style 'vertical-scroll' if a vertical scroll bar is present\n     */\n    function _adjustForScrollbars() {\n        if ($openFilesContainer[0].scrollHeight > $openFilesContainer[0].clientHeight) {\n            if (!$openFilesContainer.hasClass(\"vertical-scroll\")) {\n                $openFilesContainer.addClass(\"vertical-scroll\");\n            }\n        } else {\n            $openFilesContainer.removeClass(\"vertical-scroll\");\n        }\n    }\n    \n    /**\n     * @private\n     * Shows/Hides open files list based on working set content.\n     */\n    function _redraw() {\n        if (DocumentManager.getWorkingSet().length === 0) {\n            $openFilesContainer.hide();\n        } else {\n            $openFilesContainer.show();\n        }\n        _adjustForScrollbars();\n        _fireSelectionChanged();\n    }\n    \n    /** \n     * Updates the appearance of the list element based on the parameters provided\n     * @private\n     * @param {!HTMLLIElement} listElement\n     * @param {bool} isDirty \n     * @param {bool} canClose\n     */\n    function _updateFileStatusIcon(listElement, isDirty, canClose) {\n        var $fileStatusIcon = listElement.find(\".file-status-icon\");\n        var showIcon = isDirty || canClose;\n\n        // remove icon if its not needed\n        if (!showIcon && $fileStatusIcon.length !== 0) {\n            $fileStatusIcon.remove();\n            $fileStatusIcon = null;\n            \n        // create icon if its needed and doesn't exist\n        } else if (showIcon && $fileStatusIcon.length === 0) {\n            \n            $fileStatusIcon = $(\"<div class='file-status-icon'></div>\")\n                .prependTo(listElement)\n                .mousedown(function (e) {\n                    // stopPropagation of mousedown for fileStatusIcon so the parent <LI> item, which\n                    // selects documents on mousedown, doesn't select the document in the case \n                    // when the click is on fileStatusIcon\n                    e.stopPropagation();\n                })\n                .click(function () {\n                    // Clicking the \"X\" button is equivalent to File > Close; it doesn't merely\n                    // remove a file from the working set\n                    var file = listElement.data(_FILE_KEY);\n                    CommandManager.execute(Commands.FILE_CLOSE, {file: file});\n                });\n        }\n\n        // Set icon's class\n        if ($fileStatusIcon) {\n            // cast to Boolean needed because toggleClass() distinguishes true/false from truthy/falsy\n            $fileStatusIcon.toggleClass(\"dirty\", Boolean(isDirty));\n            $fileStatusIcon.toggleClass(\"can-close\", Boolean(canClose));\n        }\n    }\n    \n    /** \n     * Updates the appearance of the list element based on the parameters provided.\n     * @private\n     * @param {!HTMLLIElement} listElement\n     * @param {?Document} selectedDoc\n     */\n    function _updateListItemSelection(listItem, selectedDoc) {\n        var shouldBeSelected = (selectedDoc && $(listItem).data(_FILE_KEY).fullPath === selectedDoc.file.fullPath);\n        \n        // cast to Boolean needed because toggleClass() distinguishes true/false from truthy/falsy\n        $(listItem).toggleClass(\"selected\", Boolean(shouldBeSelected));\n    }\n\n    function isOpenAndDirty(file) {\n        var docIfOpen = DocumentManager.getOpenDocumentForPath(file.fullPath);\n        return (docIfOpen && docIfOpen.isDirty);\n    }\n    \n    /** \n     * Builds the UI for a new list item and inserts in into the end of the list\n     * @private\n     * @param {FileEntry} file\n     * @return {HTMLLIElement} newListItem\n     */\n    function _createNewListItem(file) {\n        var curDoc = DocumentManager.getCurrentDocument();\n\n        // Create new list item with a link\n        var $link = $(\"<a href='#'></a>\").text(file.name);\n        var $newItem = $(\"<li></li>\")\n            .append($link)\n            .data(_FILE_KEY, file);\n\n        $openFilesContainer.find(\"ul\").append($newItem);\n        \n        // working set item might never have been opened; if so, then it's definitely not dirty\n\n        // Update the listItem's apperance\n        _updateFileStatusIcon($newItem, isOpenAndDirty(file), false);\n        _updateListItemSelection($newItem, curDoc);\n\n        $newItem.mousedown(function (e) {\n            FileViewController.openAndSelectDocument(file.fullPath, FileViewController.WORKING_SET_VIEW);\n            e.preventDefault();\n        });\n\n        $newItem.hover(\n            function () {\n                _updateFileStatusIcon($(this), isOpenAndDirty(file), true);\n            },\n            function () {\n                _updateFileStatusIcon($(this), isOpenAndDirty(file), false);\n            }\n        );\n    }\n    \n    /** \n     * Deletes all the list items in the view and rebuilds them from the working set model\n     * @private\n     */\n    function _rebuildWorkingSet() {\n        $openFilesContainer.find(\"ul\").empty();\n\n        DocumentManager.getWorkingSet().forEach(function (file) {\n            _createNewListItem(file);\n        });\n\n        _redraw();\n    }\n\n    /**\n     * Finds the listItem item assocated with the file. Returns null if not found.\n     * @private\n     * @param {!FileEntry} file\n     * @return {HTMLLIItem}\n     */\n    function _findListItemFromFile(file) {\n        var result = null;\n\n        if (file) {\n            var items = $openFilesContainer.find(\"ul\").children();\n            items.each(function () {\n                var $listItem = $(this);\n                if ($listItem.data(_FILE_KEY).fullPath === file.fullPath) {\n                    result = $listItem;\n                    return false;\n                    // breaks each\n                }\n            });\n        }\n\n        return result;\n    }\n\n    /**\n     * @private\n     */\n    function _scrollSelectedDocIntoView() {\n        if (FileViewController.getFileSelectionFocus() !== FileViewController.WORKING_SET_VIEW) {\n            return;\n        }\n\n        var doc = DocumentManager.getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        var $selectedDoc = _findListItemFromFile(doc.file);\n        if (!$selectedDoc) {\n            return;\n        }\n\n        ViewUtils.scrollElementIntoView($openFilesContainer, $selectedDoc, false);\n    }\n\n    /** \n     * @private\n     */\n    function _updateListSelection() {\n        var doc;\n        if (FileViewController.getFileSelectionFocus() === FileViewController.WORKING_SET_VIEW) {\n            doc = DocumentManager.getCurrentDocument();\n        } else {\n            doc = null;\n        }\n            \n        // Iterate through working set list and update the selection on each\n        var items = $openFilesContainer.find(\"ul\").children().each(function () {\n            _updateListItemSelection(this, doc);\n        });\n\n        // Make sure selection is in view\n        _scrollSelectedDocIntoView();\n\n        _fireSelectionChanged();\n    }\n\n    /** \n     * @private\n     */\n    function _handleFileAdded(file) {\n        _createNewListItem(file);\n        _redraw();\n    }\n\n    /**\n     * @private\n     */\n    function _handleFileListAdded(files) {\n        files.forEach(function (file) {\n            _createNewListItem(file);\n        });\n        _redraw();\n    }\n\n    /** \n     * @private\n     */\n    function _handleDocumentSelectionChange() {\n        _updateListSelection();\n        _fireSelectionChanged();\n    }\n\n    /** \n     * @private\n     * @param {FileEntry} file \n     */\n    function _handleFileRemoved(file) {\n        var $listItem = _findListItemFromFile(file);\n        if ($listItem) {\n            $listItem.remove();\n        }\n\n        _redraw();\n    }\n\n    function _handleRemoveList(removedFiles) {\n        removedFiles.forEach(function (file) {\n            var $listItem = _findListItemFromFile(file);\n            if ($listItem) {\n                $listItem.remove();\n            }\n        });\n\n        _redraw();\n    }\n\n    /** \n     * @private\n     * @param {Document} doc \n     */\n    function _handleDirtyFlagChanged(doc) {\n        var listItem = _findListItemFromFile(doc.file);\n        if (listItem) {\n            var canClose = $(listItem).find(\".can-close\").length === 1;\n            _updateFileStatusIcon(listItem, doc.isDirty, canClose);\n        }\n\n    }\n\n    function create(element) {\n        // Init DOM element\n        $openFilesContainer = element;\n        $openFilesList = $openFilesContainer.find(\"ul\");\n        \n        // Register listeners\n        $(DocumentManager).on(\"workingSetAdd\", function (event, addedFile) {\n            _handleFileAdded(addedFile);\n        });\n\n        $(DocumentManager).on(\"workingSetAddList\", function (event, addedFiles) {\n            _handleFileListAdded(addedFiles);\n        });\n\n        $(DocumentManager).on(\"workingSetRemove\", function (event, removedFile) {\n            _handleFileRemoved(removedFile);\n        });\n\n        $(DocumentManager).on(\"workingSetRemoveList\", function (event, removedFiles) {\n            _handleRemoveList(removedFiles);\n        });\n\n        $(DocumentManager).on(\"dirtyFlagChange\", function (event, doc) {\n            _handleDirtyFlagChanged(doc);\n        });\n    \n        $(FileViewController).on(\"documentSelectionFocusChange fileViewFocusChange\", _handleDocumentSelectionChange);\n        \n        // Show scroller shadows when open-files-container scrolls\n        ViewUtils.addScrollerShadow($openFilesContainer[0], null, true);\n        ViewUtils.sidebarList($openFilesContainer);\n        \n        _redraw();\n    }\n    \n    exports.create = create;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils, window */\n\ndefine('document/DocumentCommandHandlers',['require','exports','module','thirdparty/path-utils/path-utils.min','command/CommandManager','command/Commands','command/KeyBindingManager','file/NativeFileSystem','project/ProjectManager','document/DocumentManager','editor/EditorManager','project/FileViewController','file/FileUtils','utils/StringUtils','utils/Async','widgets/Dialogs','strings','preferences/PreferencesManager','utils/PerfUtils'],function (require, exports, module) {\n    \n    \n    require(\"thirdparty/path-utils/path-utils.min\");\n    \n    // Load dependent modules\n    var CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        KeyBindingManager   = require(\"command/KeyBindingManager\"),\n        NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        ProjectManager      = require(\"project/ProjectManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Async               = require(\"utils/Async\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\");\n    \n    /**\n     * Handlers for commands related to document handling (opening, saving, etc.)\n     */\n    \n    /** @type {jQueryObject} Container for label shown above editor; must be an inline element */\n    var _$title = null;\n    /** @type {jQueryObject} Container for dirty dot; must be an inline element */\n    var _$dirtydot = null;\n    /** @type {jQueryObject} Container for _$title; need not be an inline element */\n    var _$titleWrapper = null;\n    /** @type {string} Label shown above editor for current document: filename and potentially some of its path */\n    var _currentTitlePath = null;\n    \n    /** @type {jQueryObject} Container for _$titleWrapper; if changing title changes this element's height, must kick editor to resize */\n    var _$titleContainerToolbar = null;\n    /** @type {Number} Last known height of _$titleContainerToolbar */\n    var _lastToolbarHeight = null;\n    \n    function updateTitle() {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        if (currentDoc) {\n            _$title.text(_currentTitlePath);\n            _$title.attr(\"title\", currentDoc.file.fullPath);\n            // dirty dot is always in DOM so layout doesn't change, and visibility is toggled\n            _$dirtydot.css(\"visibility\", (currentDoc.isDirty) ? \"visible\" : \"hidden\");\n        } else {\n            _$title.text(\"\");\n            _$title.attr(\"title\", \"\");\n            _$dirtydot.css(\"visibility\", \"hidden\");\n        }\n        \n        // Set _$titleWrapper to a fixed width just large enough to accomodate _$title. This seems equivalent to what\n        // the browser would do automatically, but the CSS trick we use for layout requires _$titleWrapper to have a\n        // fixed width set on it (see the \"#main-toolbar.toolbar\" CSS rule for details).\n        _$titleWrapper.css(\"width\", \"\");\n        var newWidth = _$title.width();\n        _$titleWrapper.css(\"width\", newWidth);\n        \n        // Changing the width of the title may cause the toolbar layout to change height, which needs to resize the\n        // editor beneath it (toolbar changing height due to window resize is already caught by EditorManager).\n        var newToolbarHeight = _$titleContainerToolbar.height();\n        if (_lastToolbarHeight !== newToolbarHeight) {\n            _lastToolbarHeight = newToolbarHeight;\n            EditorManager.resizeEditor();\n        }\n    }\n    \n    function handleCurrentDocumentChange() {\n        var newDocument = DocumentManager.getCurrentDocument();\n        var perfTimerName = PerfUtils.markStart(\"DocumentCommandHandlers._onCurrentDocumentChange():\\t\" + (!newDocument || newDocument.file.fullPath));\n        \n        if (newDocument) {\n            var fullPath = newDocument.file.fullPath;\n    \n            // In the main toolbar, show the project-relative path (if the file is inside the current project)\n            // or the full absolute path (if it's not in the project).\n            _currentTitlePath = ProjectManager.makeProjectRelativeIfPossible(fullPath);\n            \n        } else {\n            _currentTitlePath = null;\n        }\n        \n        // Update title text & \"dirty dot\" display\n        updateTitle();\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n    \n    function handleDirtyChange(event, changedDoc) {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        \n        if (currentDoc && changedDoc.file.fullPath === currentDoc.file.fullPath) {\n            updateTitle();\n        }\n    }\n\n    /**\n     * @private\n     * Creates a document and displays an editor for the specified file path.\n     * @param {!string} fullPath\n     * @return {$.Promise} a jQuery promise that will be resolved with a\n     *  document for the specified file path, or rejected if the file can not be read.\n     */\n    function doOpen(fullPath) {\n        var result = new $.Deferred();\n\n        if (!fullPath) {\n            console.log(\"doOpen() called without fullPath\");\n            result.reject();\n        } else {\n            var perfTimerName = PerfUtils.markStart(\"Open File:\\t\" + fullPath);\n            result.always(function () {\n                PerfUtils.addMeasurement(perfTimerName);\n            });\n            \n            // Load the file if it was never open before, and then switch to it in the UI\n            DocumentManager.getDocumentForPath(fullPath)\n                .done(function (doc) {\n                    DocumentManager.setCurrentDocument(doc);\n                    result.resolve(doc);\n                })\n                .fail(function (fileError) {\n                    FileUtils.showFileOpenError(fileError.code, fullPath).done(function () {\n                        // For performance, we do lazy checking of file existence, so it may be in working set\n                        DocumentManager.removeFromWorkingSet(new NativeFileSystem.FileEntry(fullPath));\n                        EditorManager.focusEditor();\n                        result.reject();\n                    });\n                });\n        }\n\n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Used to track the default directory for the file open dialog\n     */\n    var _defaultOpenDialogFullPath = null;\n    \n    /**\n     * @private\n     * Creates a document and displays an editor for the specified file path. \n     * If no path is specified, a file prompt is provided for input.\n     * @param {?string} fullPath - The path of the file to open; if it's null we'll prompt for it\n     * @return {$.Promise} a jQuery promise that will be resolved with a new \n     *  document for the specified file path, or rejected if the file can not be read.\n     */\n    function _doOpenWithOptionalPath(fullPath) {\n        var result;\n        if (!fullPath) {\n            // Create placeholder deferred\n            result = new $.Deferred();\n            \n            //first time through, default to the current project path\n            if (!_defaultOpenDialogFullPath) {\n                _defaultOpenDialogFullPath = ProjectManager.getProjectRoot().fullPath;\n            }\n            // Prompt the user with a dialog\n            NativeFileSystem.showOpenDialog(true, false, Strings.OPEN_FILE, _defaultOpenDialogFullPath,\n                null, function (paths) {\n                    var i;\n                    \n                    if (paths.length > 0) {\n                        // Add all files to the working set without verifying that\n                        // they still exist on disk (for faster opening)\n                        var filesToOpen = [];\n                        paths.forEach(function (file) {\n                            filesToOpen.push(new NativeFileSystem.FileEntry(file));\n                        });\n                        DocumentManager.addListToWorkingSet(filesToOpen);\n                        \n                        doOpen(paths[paths.length - 1])\n                            .done(function (doc) {\n                                var url = PathUtils.parseUrl(doc.file.fullPath);\n                                //reconstruct the url but use the directory and stop there\n                                _defaultOpenDialogFullPath = url.protocol + url.doubleSlash + url.authority + url.directory;\n                                \n                                DocumentManager.addToWorkingSet(doc.file);\n                            })\n                            // Send the resulting document that was opened\n                            .pipe(result.resolve, result.reject);\n                    } else {\n                        // Reject if the user canceled the dialog\n                        result.reject();\n                    }\n                });\n        } else {\n            result = doOpen(fullPath);\n        }\n        \n        return result.promise();\n    }\n\n    /**\n     * Opens the given file and makes it the current document. Does NOT add it to the working set.\n     * @param {!{fullPath:string}} Params for FILE_OPEN command\n     */\n    function handleFileOpen(commandData) {\n        var fullPath = null;\n        if (commandData) {\n            fullPath = commandData.fullPath;\n        }\n        \n        return _doOpenWithOptionalPath(fullPath)\n            .always(EditorManager.focusEditor);\n    }\n\n    /**\n     * Opens the given file, makes it the current document, AND adds it to the working set.\n     * @param {!{fullPath:string}} Params for FILE_OPEN command\n     */\n    function handleFileAddToWorkingSet(commandData) {\n        return handleFileOpen(commandData).done(function (doc) {\n            // addToWorkingSet is synchronous\n            DocumentManager.addToWorkingSet(doc.file);\n        });\n    }\n\n    /**\n     * @private\n     * Ensures the suggested file name doesn't already exit.\n     * @param {string} dir  The directory to use\n     * @param {string} baseFileName  The base to start with, \"-n\" will get appened to make unique\n     * @param {string} fileExt  The file extension\n     * @return {$.Promise} a jQuery promise that will be resolved with a unique name starting with \n     *   the given base name\n     */\n    function _getUntitledFileSuggestion(dir, baseFileName, fileExt) {\n        var result = new $.Deferred();\n        var suggestedName = baseFileName + fileExt;\n        var dirEntry = new NativeFileSystem.DirectoryEntry(dir);\n\n        result.progress(function attemptNewName(suggestedName, nextIndexToUse) {\n            if (nextIndexToUse > 99) {\n                //we've tried this enough\n                result.reject();\n                return;\n            }\n\n            //check this name\n            dirEntry.getFile(\n                suggestedName,\n                {},\n                function successCallback(entry) {\n                    //file exists, notify to the next progress\n                    result.notify(baseFileName + \"-\" + nextIndexToUse + fileExt, nextIndexToUse + 1);\n                },\n                function errorCallback(error) {\n                    //most likely error is FNF, user is better equiped to handle the rest\n                    result.resolve(suggestedName);\n                }\n            );\n        });\n\n        //kick it off\n        result.notify(baseFileName + fileExt, 1);\n\n        return result.promise();\n    }\n\n    /**\n     * Prevents re-entrancy into handleFileNewInProject()\n     *\n     * handleFileNewInProject() first prompts the user to name a file and then asynchronously writes the file when the\n     * filename field loses focus. This boolean prevent additional calls to handleFileNewInProject() when an existing\n     * file creation call is outstanding\n     */\n    var fileNewInProgress = false;\n\n    function handleFileNewInProject() {\n\n        if (fileNewInProgress) {\n            ProjectManager.forceFinishRename();\n            return;\n        }\n        fileNewInProgress = true;\n\n        // Determine the directory to put the new file\n        // If a file is currently selected, put it next to it.\n        // If a directory is currently selected, put it in it.\n        // If nothing is selected, put it at the root of the project\n        var baseDir,\n            selected = ProjectManager.getSelectedItem() || ProjectManager.getProjectRoot();\n        \n        baseDir = selected.fullPath;\n        if (selected.isFile) {\n            baseDir = baseDir.substr(0, baseDir.lastIndexOf(\"/\"));\n        }\n        \n        // Create the new node. The createNewItem function does all the heavy work\n        // of validating file name, creating the new file and selecting.\n        var deferred = _getUntitledFileSuggestion(baseDir, Strings.UNTITLED, \".js\");\n        var createWithSuggestedName = function (suggestedName) {\n            ProjectManager.createNewItem(baseDir, suggestedName, false)\n                .pipe(deferred.resolve, deferred.reject, deferred.notify)\n                .always(function () { fileNewInProgress = false; })\n                .done(function (entry) {\n                    FileViewController.addToWorkingSetAndSelect(entry.fullPath, FileViewController.PROJECT_MANAGER);\n                });\n        };\n\n        deferred.done(createWithSuggestedName);\n        deferred.fail(function createWithDefault() { createWithSuggestedName(\"Untitled.js\"); });\n        return deferred;\n    }\n    \n    function showSaveFileError(code, path) {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_SAVING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_SAVING_FILE,\n                StringUtils.htmlEscape(path),\n                FileUtils.getFileErrorString(code)\n            )\n        );\n    }\n    \n    /** Note: if there is an error, the promise is not rejected until the user has dimissed the dialog */\n    function doSave(docToSave) {\n        var result = new $.Deferred();\n        \n        function handleError(error, fileEntry) {\n            showSaveFileError(error.code, fileEntry.fullPath)\n                .always(function () {\n                    result.reject(error);\n                });\n        }\n            \n        if (docToSave && docToSave.isDirty) {\n            var fileEntry = docToSave.file;\n            var writeError = false;\n            \n            fileEntry.createWriter(\n                function (writer) {\n                    writer.onwriteend = function () {\n                        // Per spec, onwriteend is called after onerror too\n                        if (!writeError) {\n                            docToSave.notifySaved();\n                            result.resolve();\n                        }\n                    };\n                    writer.onerror = function (error) {\n                        writeError = true;\n                        handleError(error, fileEntry);\n                    };\n\n                    // We don't want normalized line endings, so it's important to pass true to getText()\n                    writer.write(docToSave.getText(true));\n                },\n                function (error) {\n                    handleError(error, fileEntry);\n                }\n            );\n        } else {\n            result.resolve();\n        }\n        result.always(function () {\n            EditorManager.focusEditor();\n        });\n        return result.promise();\n    }\n    \n    /**\n     * Saves the given file. If no file specified, assumes the current document.\n     * @param {?{doc: Document}} commandData  Document to close, or null\n     * @return {$.Promise} a promise that is resolved after the save completes\n     */\n    function handleFileSave(commandData) {\n        // Default to current document if doc is null\n        var doc = null;\n        if (commandData) {\n            doc = commandData.doc;\n        }\n        if (!doc) {\n            var focusedEditor = EditorManager.getFocusedEditor();\n            \n            if (focusedEditor) {\n                doc = focusedEditor.document;\n            }\n            \n            // doc may still be null, e.g. if no editors are open, but doSave() does a null check on\n            // doc and makes sure the document is dirty before saving.\n        }\n        \n        return doSave(doc);\n    }\n    \n    /**\n     * Saves all unsaved documents. Returns a Promise that will be resolved once ALL the save\n     * operations have been completed. If ANY save operation fails, an error dialog is immediately\n     * shown and the other files wait to save until it is dismissed; after all files have been\n     * processed, the Promise is rejected if any ONE save operation failed.\n     *\n     * @return {$.Promise}\n     */\n    function saveAll() {\n        // Do in serial because doSave shows error UI for each file, and we don't want to stack\n        // multiple dialogs on top of each other\n        return Async.doSequentially(\n            DocumentManager.getWorkingSet(),\n            function (file) {\n                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n                if (doc) {\n                    return doSave(doc);\n                } else {\n                    // working set entry that was never actually opened - ignore\n                    return (new $.Deferred()).resolve().promise();\n                }\n            },\n            false\n        );\n    }\n    \n    /**\n     * Saves all unsaved documents.\n     * @return {$.Promise} a promise that is resolved once ALL the saves have been completed; or rejected\n     *      after all operations completed if any ONE of them failed.\n     */\n    function handleFileSaveAll() {\n        return saveAll();\n    }\n    \n    /**\n     * Reverts the Document to the current contents of its file on disk. Discards any unsaved changes\n     * in the Document.\n     * @param {Document} doc\n     * @return {$.Promise} a Promise that's resolved when done, or rejected with a FileError if the\n     *      file cannot be read (after showing an error dialog to the user).\n     */\n    function doRevert(doc) {\n        var result = new $.Deferred();\n        \n        FileUtils.readAsText(doc.file)\n            .done(function (text, readTimestamp) {\n                doc.refreshText(text, readTimestamp);\n                result.resolve();\n            })\n            .fail(function (error) {\n                FileUtils.showFileOpenError(error.code, doc.file.fullPath)\n                    .always(function () {\n                        result.reject(error);\n                    });\n            });\n        \n        return result.promise();\n    }\n    \n\n    /**\n     * Closes the specified file: removes it from the working set, and closes the main editor if one\n     * is open. Prompts user about saving changes first, if document is dirty.\n     *\n     * @param {?{file: FileEntry, promptOnly:boolean}} commandData  Optional bag of arguments:\n     *      file - File to close; assumes the current document if not specified.\n     *      promptOnly - If true, only displays the relevant confirmation UI and does NOT actually\n     *          close the document. This is useful when chaining file-close together with other user\n     *          prompts that may be cancelable.\n     * @return {$.Promise} a promise that is resolved when the file is closed, or if no file is open.\n     *      FUTURE: should we reject the promise if no file is open?\n     */\n    function handleFileClose(commandData) {\n        // If not specified, file defaults to null; promptOnly defaults to falsy\n        var file       = commandData && commandData.file,\n            promptOnly = commandData && commandData.promptOnly;\n        \n        // utility function for handleFileClose: closes document & removes from working set\n        function doClose(file) {\n            if (!promptOnly) {\n                // This selects a different document if the working set has any other options\n                DocumentManager.closeFullEditor(file);\n            \n                EditorManager.focusEditor();\n            }\n        }\n        \n        \n        var result = new $.Deferred(), promise = result.promise();\n        \n        // Default to current document if doc is null\n        if (!file) {\n            if (DocumentManager.getCurrentDocument()) {\n                file = DocumentManager.getCurrentDocument().file;\n            }\n        }\n        \n        // No-op if called when nothing is open; TODO: (issue #273) should command be grayed out instead?\n        if (!file) {\n            result.resolve();\n            return promise;\n        }\n        \n        var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n        \n        if (doc && doc.isDirty) {\n            // Document is dirty: prompt to save changes before closing\n            var filename = PathUtils.parseUrl(doc.file.fullPath).filename;\n            \n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_SAVE_CLOSE,\n                Strings.SAVE_CLOSE_TITLE,\n                StringUtils.format(Strings.SAVE_CLOSE_MESSAGE, StringUtils.htmlEscape(filename))\n            ).done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                    result.reject();\n                } else if (id === Dialogs.DIALOG_BTN_OK) {\n                    // \"Save\" case: wait until we confirm save has succeeded before closing\n                    doSave(doc)\n                        .done(function () {\n                            doClose(file);\n                            result.resolve();\n                        })\n                        .fail(function () {\n                            result.reject();\n                        });\n                } else {\n                    // \"Don't Save\" case: even though we're closing the main editor, other views of\n                    // the Document may remain in the UI. So we need to revert the Document to a clean\n                    // copy of whatever's on disk.\n                    doClose(file);\n                    \n                    // Only reload from disk if we've executed the Close for real,\n                    // *and* if at least one other view still exists\n                    if (!promptOnly && DocumentManager.getOpenDocumentForPath(file.fullPath)) {\n                        doRevert(doc)\n                            .pipe(result.resolve, result.reject);\n                    } else {\n                        result.resolve();\n                    }\n                }\n            });\n            result.always(function () {\n                EditorManager.focusEditor();\n            });\n        } else {\n            // File is not open, or IS open but Document not dirty: close immediately\n            doClose(file);\n            EditorManager.focusEditor();\n            result.resolve();\n        }\n        return promise;\n    }\n    \n    /**\n     * Closes all open documents; equivalent to calling handleFileClose() for each document, except\n     * that unsaved changes are confirmed once, in bulk.\n     * @param {?{promptOnly: boolean}}  If true, only displays the relevant confirmation UI and does NOT\n     *          actually close any documents. This is useful when chaining close-all together with\n     *          other user prompts that may be cancelable.\n     * @return {$.Promise} a promise that is resolved when all files are closed\n     */\n    function handleFileCloseAll(commandData) {\n        var result = new $.Deferred();\n        \n        var unsavedDocs = [];\n        DocumentManager.getWorkingSet().forEach(function (file) {\n            var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n            if (doc && doc.isDirty) {\n                unsavedDocs.push(doc);\n            }\n        });\n        \n        if (unsavedDocs.length === 0) {\n            // No unsaved changes, so we can proceed without a prompt\n            result.resolve();\n            \n        } else if (unsavedDocs.length === 1) {\n            // Only one unsaved file: show the usual single-file-close confirmation UI\n            var fileCloseArgs = { file: unsavedDocs[0].file, promptOnly: commandData.promptOnly };\n\n            handleFileClose(fileCloseArgs).done(function () {\n                // still need to close any other, non-unsaved documents\n                result.resolve();\n            }).fail(function () {\n                result.reject();\n            });\n            \n        } else {\n            // Multiple unsaved files: show a single bulk prompt listing all files\n            var message = Strings.SAVE_CLOSE_MULTI_MESSAGE;\n            \n            message += \"<ul>\";\n            unsavedDocs.forEach(function (doc) {\n                message += \"<li><span class='dialog-filename'>\"\n                    + StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n                    + \"</span></li>\";\n            });\n            message += \"</ul>\";\n            \n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_SAVE_CLOSE,\n                Strings.SAVE_CLOSE_TITLE,\n                message\n            ).done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                    result.reject();\n                } else if (id === Dialogs.DIALOG_BTN_OK) {\n                    // Save all unsaved files, then if that succeeds, close all\n                    saveAll().done(function () {\n                        result.resolve();\n                    }).fail(function () {\n                        result.reject();\n                    });\n                } else {\n                    // \"Don't Save\" case--we can just go ahead and close all  files.\n                    result.resolve();\n                }\n            });\n        }\n        \n        // If all the unsaved-changes confirmations pan out above, then go ahead & close all editors\n        // NOTE: this still happens before any done() handlers added by our caller, because jQ\n        // guarantees that handlers run in the order they are added.\n        result.done(function () {\n            if (!commandData || !commandData.promptOnly) {\n                DocumentManager.closeAll();\n            }\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n    * @private - tracks our closing state if we get called again\n    */\n    var _windowGoingAway = false;\n    \n    /**\n    * @private\n    * Common implementation for close/quit/reload which all mostly\n    * the same except for the final step\n    */\n    function _handleWindowGoingAway(commandData, postCloseHandler, failHandler) {\n        if (_windowGoingAway) {\n            //if we get called back while we're closing, then just return\n            return (new $.Deferred()).resolve().promise();\n        }\n        \n        //prevent the default action of closing the window until we can save all the files\n        if (commandData && commandData.evt && commandData.evt.cancelable) {\n            commandData.evt.preventDefault();\n        }\n\n        return CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })\n            .done(function () {\n                _windowGoingAway = true;\n                PreferencesManager.savePreferences();\n                postCloseHandler();\n            })\n            .fail(function () {\n                _windowGoingAway = false;\n                if (failHandler) {\n                    failHandler();\n                }\n            });\n    }\n\n    /**\n    * @private\n    * Implementation for abortQuit callback to reset quit sequence settings\n    */\n    function _handleAbortQuit() {\n        _windowGoingAway = false;\n    }\n    \n    /** Confirms any unsaved changes, then closes the window */\n    function handleFileCloseWindow(commandData) {\n        return _handleWindowGoingAway(\n            commandData,\n            function () {\n                window.close();\n            },\n            function () {\n                // if fail, tell the app to abort any pending quit operation.\n                // TODO: remove this if statement when we move to the new CEF3 shell\n                if (brackets.app.abortQuit) {\n                    brackets.app.abortQuit();\n                }\n            }\n        );\n    }\n    \n    /** Closes the window, then quits the app */\n    function handleFileQuit(commandData) {\n        return _handleWindowGoingAway(\n            commandData,\n            function () {\n                brackets.app.quit();\n            },\n            function () {\n                // if fail, don't exit: user canceled (or asked us to save changes first, but we failed to do so)\n                // TODO: remove this if statement when we move to the new CEF3 shell\n                if (brackets.app.abortQuit) {\n                    brackets.app.abortQuit();\n                }\n            }\n        );\n    }\n\n    /** Does a full reload of the browser window */\n    function handleFileReload(commandData) {\n        return _handleWindowGoingAway(commandData, function () {\n            window.location.reload(true);\n        });\n    }\n    \n    \n    /** Are we already listening for a keyup to call detectDocumentNavEnd()? */\n    var _addedNavKeyHandler = false;\n    \n    /**\n     * When the Ctrl key is released, if we were in the middle of a next/prev document navigation\n     * sequence, now is the time to end it and update the MRU order. If we allowed the order to update\n     * on every next/prev increment, the 1st & 2nd entries would just switch places forever and we'd\n     * never get further down the list.\n     * @param {jQueryEvent} event Key-up event\n     */\n    function detectDocumentNavEnd(event) {\n        if (event.keyCode === 17) {  // Ctrl key\n            DocumentManager.finalizeDocumentNavigation();\n            \n            _addedNavKeyHandler = false;\n            $(window.document.body).off(\"keyup\", detectDocumentNavEnd);\n        }\n    }\n    \n    /** Navigate to the next/previous (MRU) document. Don't update MRU order yet */\n    function goNextPrevDoc(inc) {\n        var file = DocumentManager.getNextPrevFile(inc);\n        if (file) {\n            DocumentManager.beginDocumentNavigation();\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: file.fullPath });\n            \n            // Listen for ending of Ctrl+Tab sequence\n            if (!_addedNavKeyHandler) {\n                _addedNavKeyHandler = true;\n                $(window.document.body).keyup(detectDocumentNavEnd);\n            }\n        }\n    }\n    \n    function handleGoNextDoc() {\n        goNextPrevDoc(+1);\n    }\n    function handleGoPrevDoc() {\n        goNextPrevDoc(-1);\n    }\n    \n\n    function init($titleContainerToolbar) {\n        _$titleContainerToolbar = $titleContainerToolbar;\n        _$titleWrapper = $(\".title-wrapper\", _$titleContainerToolbar);\n        _$title = $(\".title\", _$titleWrapper);\n        _$dirtydot = $(\".dirty-dot\", _$titleWrapper);\n\n        // Register global commands\n        CommandManager.register(Strings.CMD_FILE_OPEN,          Commands.FILE_OPEN, handleFileOpen);\n        CommandManager.register(Strings.CMD_ADD_TO_WORKING_SET, Commands.FILE_ADD_TO_WORKING_SET, handleFileAddToWorkingSet);\n        // TODO: (issue #274) For now, hook up File > New to the \"new in project\" handler. Eventually\n        // File > New should open a new blank tab, and handleFileNewInProject should\n        // be called from a \"+\" button in the project\n        CommandManager.register(Strings.CMD_FILE_NEW,           Commands.FILE_NEW, handleFileNewInProject);\n        CommandManager.register(Strings.CMD_FILE_SAVE,          Commands.FILE_SAVE, handleFileSave);\n        CommandManager.register(Strings.CMD_FILE_SAVE_ALL,      Commands.FILE_SAVE_ALL, handleFileSaveAll);\n\n        CommandManager.register(Strings.CMD_FILE_CLOSE,         Commands.FILE_CLOSE, handleFileClose);\n        CommandManager.register(Strings.CMD_FILE_CLOSE_ALL,     Commands.FILE_CLOSE_ALL, handleFileCloseAll);\n        CommandManager.register(Strings.CMD_CLOSE_WINDOW,       Commands.FILE_CLOSE_WINDOW, handleFileCloseWindow);\n        CommandManager.register(Strings.CMD_QUIT,               Commands.FILE_QUIT, handleFileQuit);\n        CommandManager.register(Strings.CMD_REFRESH_WINDOW,     Commands.DEBUG_REFRESH_WINDOW, handleFileReload);\n        CommandManager.register(Strings.CMD_NEXT_DOC,           Commands.NAVIGATE_NEXT_DOC, handleGoNextDoc);\n        CommandManager.register(Strings.CMD_PREV_DOC,           Commands.NAVIGATE_PREV_DOC, handleGoPrevDoc);\n        CommandManager.register(Strings.CMD_ABORT_QUIT,         Commands.APP_ABORT_QUIT, _handleAbortQuit);\n\n        KeyBindingManager.addBinding(Commands.NAVIGATE_NEXT_DOC, [{key: \"Ctrl-Tab\",   platform: \"win\"},\n                                                                    {key: \"Ctrl-Tab\",  platform:  \"mac\"}]);\n        KeyBindingManager.addBinding(Commands.NAVIGATE_PREV_DOC, [{key: \"Ctrl-Shift-Tab\",   platform: \"win\"},\n                                                                    {key: \"Ctrl-Shift-Tab\",  platform:  \"mac\"}]);\n        \n        // Listen for changes that require updating the editor titlebar\n        $(DocumentManager).on(\"dirtyFlagChange\", handleDirtyChange);\n        $(DocumentManager).on(\"currentDocumentChange\", handleCurrentDocumentChange);\n    }\n\n    // Define public API\n    exports.init = init;\n});\n\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, FileError */\n\n/**\n * FileSyncManager is a set of utilities to help track external modifications to the files and folders\n * in the currently open project.\n *\n * Currently, we look for external changes purely by checking file timestamps against the last-sync\n * timestamp recorded on Document. Later, we will use actual native directory-watching callbacks\n * instead.\n *\n * FUTURE: Whenever we have a 'project file tree model,' we should manipulate that instead of notifying\n * DocumentManager directly. DocumentManager, the tree UI, etc. then all listen to that model for changes.\n */\ndefine('project/FileSyncManager',['require','exports','module','project/ProjectManager','document/DocumentManager','editor/EditorManager','command/Commands','command/CommandManager','utils/Async','widgets/Dialogs','strings','utils/StringUtils','file/FileUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var ProjectManager      = require(\"project/ProjectManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Async               = require(\"utils/Async\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        FileUtils           = require(\"file/FileUtils\");\n\n    \n    /**\n     * Guard to spot re-entrancy while syncOpenDocuments() is still in progress\n     * @type {boolean}\n     */\n    var _alreadyChecking = false;\n    \n    /**\n     * If true, we should bail from the syncOpenDocuments() process and then re-run it. See\n     * comments in syncOpenDocuments() for how this works.\n     * @type {boolean}\n     */\n    var _restartPending = false;\n    \n    /** @type {Array.<Document>} */\n    var toReload;\n    /** @type {Array.<Document>} */\n    var toClose;\n    /** @type {Array.<Document>} */\n    var editConflicts;\n    /** @type {Array.<Document>} */\n    var deleteConflicts;\n    \n    \n    /**\n     * Scans all the given Documents for changes on disk, and sorts them into four buckets,\n     * populating the corresponding arrays:\n     *  toReload        - changed on disk; unchanged within Brackets\n     *  toClose         - deleted on disk; unchanged within Brackets\n     *  editConflicts   - changed on disk; also dirty in Brackets\n     *  deleteConflicts - deleted on disk; also dirty in Brackets\n     *\n     * @param {!Array.<Document>} docs\n     * @return {$.Promise}  Resolved when all scanning done, or rejected immediately if there's any\n     *      error while reading file timestamps. Errors are logged but no UI is shown.\n     */\n    function findExternalChanges(docs) {\n\n        toReload = [];\n        toClose = [];\n        editConflicts = [];\n        deleteConflicts = [];\n    \n        function checkDoc(doc) {\n            var result = new $.Deferred();\n            \n            // Check file timestamp / existence\n            doc.file.getMetadata(\n                function (metadata) {\n                    // Does file's timestamp differ from last sync time on the Document?\n                    if (metadata.modificationTime.getTime() !== doc.diskTimestamp.getTime()) {\n                        if (doc.isDirty) {\n                            editConflicts.push(doc);\n                        } else {\n                            toReload.push(doc);\n                        }\n                    }\n                    result.resolve();\n                },\n                function (error) {\n                    // File has been deleted externally\n                    if (error.code === FileError.NOT_FOUND_ERR) {\n                        if (doc.isDirty) {\n                            deleteConflicts.push(doc);\n                        } else {\n                            toClose.push(doc);\n                        }\n                        result.resolve();\n                    } else {\n                        // Some other error fetching metadata: treat as a real error\n                        console.log(\"Error checking modification status of \" + doc.file.fullPath, error.code);\n                        result.reject();\n                    }\n                }\n            );\n            return result.promise();\n        }\n        \n        // Check all docs in parallel\n        // (fail fast b/c we won't continue syncing if there was any error fetching timestamps)\n        return Async.doInParallel(docs, checkDoc, true);\n    }\n    \n    /**\n     * Scans all the files in the working set that do not have Documents (and thus were not scanned\n     * by findExternalChanges()). If any were deleted on disk, removes them from the working set.\n     */\n    function syncUnopenWorkingSet() {\n        // We only care about working set entries that have never been open (have no Document).\n        var unopenWorkingSetFiles = DocumentManager.getWorkingSet().filter(function (wsFile) {\n            return !DocumentManager.getOpenDocumentForPath(wsFile.fullPath);\n        });\n        \n        function checkWorkingSetFile(file) {\n            var result = new $.Deferred();\n            \n            file.getMetadata(\n                function (metadata) {\n                    // File still exists\n                    result.resolve();\n                },\n                function (error) {\n                    // File has been deleted externally\n                    if (error.code === FileError.NOT_FOUND_ERR) {\n                        DocumentManager.notifyFileDeleted(file);\n                        result.resolve();\n                    } else {\n                        // Some other error fetching metadata: treat as a real error\n                        console.log(\"Error checking for deletion of \" + file.fullPath, error.code);\n                        result.reject();\n                    }\n                }\n            );\n            return result.promise();\n        }\n        \n        // Check all these files in parallel\n        return Async.doInParallel(unopenWorkingSetFiles, checkWorkingSetFile, false);\n    }\n    \n    \n    /**\n     * Reloads the Document's contents from disk, discarding any unsaved changes in the editor.\n     *\n     * @param {!Document} doc\n     * @return {$.Promise} Resolved after editor has been refreshed; rejected if unable to load the\n     *      file's new content. Errors are logged but no UI is shown.\n     */\n    function reloadDoc(doc) {\n        \n        var promise = FileUtils.readAsText(doc.file);\n        \n        promise.done(function (text, readTimestamp) {\n            doc.refreshText(text, readTimestamp);\n        });\n        promise.fail(function (error) {\n            console.log(\"Error reloading contents of \" + doc.file.fullPath, error.code);\n        });\n        return promise;\n    }\n    \n    /**\n     * Reloads all the documents in \"toReload\" silently (no prompts). The operations are all run\n     * in parallel.\n     * @return {$.Promise} Resolved/rejected after all reloads done; will be rejected if any one\n     *      file's reload failed. Errors are logged (by reloadDoc()) but no UI is shown.\n     */\n    function reloadChangedDocs() {\n        // Reload each doc in turn, and once all are (async) done, signal that we're done\n        return Async.doInParallel(toReload, reloadDoc, false);\n    }\n    \n    /**\n     * @param {FileError} error\n     * @param {!Document} doc\n     * @return {$.Promise}\n     */\n    function showReloadError(error, doc) {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_RELOADING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_RELOADING_FILE,\n                StringUtils.htmlEscape(doc.file.fullPath),\n                FileUtils.getFileErrorString(error.code)\n            )\n        );\n    }\n    \n    \n    /**\n     * Closes all the documents in \"toClose\" silently (no prompts). Completes synchronously.\n     */\n    function closeDeletedDocs() {\n        toClose.forEach(function (doc) {\n            DocumentManager.notifyFileDeleted(doc.file);\n        });\n    }\n    \n    \n    /**\n     * Walks through all the documents in \"editConflicts\" & \"deleteConflicts\" and prompts the user\n     * about each one. Processing is sequential: if the user chooses to reload a document, the next\n     * prompt is not shown until after the reload has completed.\n     *\n     * @return {$.Promise} Resolved/rejected after all documents have been prompted and (if\n     *      applicable) reloaded (and any resulting error UI has been dismissed). Rejected if any\n     *      one reload failed.\n     */\n    function presentConflicts() {\n        \n        var allConflicts = editConflicts.concat(deleteConflicts);\n        \n        function presentConflict(doc, i) {\n            var result = new $.Deferred(), promise = result.promise();\n            \n            // If window has been re-focused, skip all remaining conflicts so the sync can bail & restart\n            if (_restartPending) {\n                result.resolve();\n                return promise;\n            }\n            \n            var message;\n            var dialogId;\n            var toClose;\n            \n            // Prompt UI varies depending on whether the file on disk was modified vs. deleted\n            if (i < editConflicts.length) {\n                toClose = false;\n                dialogId = Dialogs.DIALOG_ID_EXT_CHANGED;\n                message = StringUtils.format(\n                    Strings.EXT_MODIFIED_MESSAGE,\n                    StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n                );\n                \n            } else {\n                toClose = true;\n                dialogId = Dialogs.DIALOG_ID_EXT_DELETED;\n                message = StringUtils.format(\n                    Strings.EXT_DELETED_MESSAGE,\n                    StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n                );\n            }\n            \n            Dialogs.showModalDialog(dialogId, Strings.EXT_MODIFIED_TITLE, message)\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_DONTSAVE) {\n                        if (toClose) {\n                            // Discard - close all editors\n                            DocumentManager.notifyFileDeleted(doc.file);\n                            result.resolve();\n                        } else {\n                            // Discard - load changes from disk\n                            reloadDoc(doc)\n                                .done(function () {\n                                    result.resolve();\n                                })\n                                .fail(function (error) {\n                                    // Unable to load changed version from disk - show error UI\n                                    showReloadError(error, doc)\n                                        .always(function () {\n                                            // After user dismisses, move on to next conflict prompt\n                                            result.reject();\n                                        });\n                                });\n                        }\n                        \n                    } else {\n                        // Cancel - if user doesn't manually save or close, we'll prompt again next\n                        // time window is reactivated;\n                        // OR programmatically canceled due to _resetPending - we'll skip all\n                        // remaining files in the conflicts list (see above)\n                        result.resolve();\n                    }\n                });\n            \n            return promise;\n        }\n        \n        // Begin walking through the conflicts, one at a time\n        return Async.doSequentially(allConflicts, presentConflict, false);\n    }\n    \n    \n    \n    /**\n     * Check to see whether any open files have been modified by an external app since the last time\n     * Brackets synced up with the copy on disk (either by loading or saving the file). For clean\n     * files, we silently upate the editor automatically. For files with unsaved changes, we prompt\n     * the user.\n     */\n    function syncOpenDocuments() {\n        \n        // We can become \"re-entrant\" if the user leaves & then returns to Brackets before we're\n        // done -- easy if a prompt dialog is left open. Since the user may have left Brackets to\n        // revert some of the disk changes, etc. we want to cancel the current sync and immediately\n        // begin a new one. We let the orig sync run until the user-visible dialog phase, then\n        // bail; if we're already there we programmatically close the dialog to bail right away.\n        if (_alreadyChecking) {\n            _restartPending = true;\n            \n            // Close dialog if it was open. This will 'unblock' presentConflict(), which bails back\n            // to us immediately upon seeing _restartPending. We then restart the sync - see below\n            Dialogs.cancelModalDialogIfOpen(Dialogs.DIALOG_ID_EXT_CHANGED);\n            Dialogs.cancelModalDialogIfOpen(Dialogs.DIALOG_ID_EXT_DELETED);\n            \n            return;\n        }\n        \n        _alreadyChecking = true;\n        \n        \n        // Syncing proceeds in four phases:\n        //  1) Check all open files for external modifications\n        //  2) Check any other working set entries (that are not open) for deletion, and remove\n        //     from working set if deleted\n        //  3) Refresh all Documents that are clean (if file changed on disk)\n        //  4) Close all Documents that are clean (if file deleted on disk)\n        //  5) Prompt about any Documents that are dirty (if file changed/deleted on disk)\n        // Each phase fully completes (asynchronously) before the next one begins.\n        \n        \n        // 1) Check for external modifications\n        var allDocs = DocumentManager.getAllOpenDocuments();\n        \n        findExternalChanges(allDocs)\n            .done(function () {\n                // 2) Check un-open working set entries for deletion (& \"close\" if needed)\n                syncUnopenWorkingSet()\n                    .always(function () {\n                        // If we were unable to check any un-open files for deletion, silently ignore\n                        // (after logging to console). This doesn't have any bearing on syncing truly\n                        // open Documents (which we've already successfully checked).\n                        \n                        // 3) Reload clean docs as needed\n                        reloadChangedDocs()\n                            .always(function () {\n                                // 4) Close clean docs as needed\n                                // This phase completes synchronously\n                                closeDeletedDocs();\n                                \n                                // 5) Prompt for dirty editors (conflicts)\n                                presentConflicts()\n                                    .always(function () {\n                                        if (_restartPending) {\n                                            // Restart the sync if needed\n                                            _restartPending = false;\n                                            _alreadyChecking = false;\n                                            syncOpenDocuments();\n                                        } else {\n                                            // We're really done!\n                                            _alreadyChecking = false;\n                                            \n                                            // If we showed a dialog, restore focus to editor\n                                            if (editConflicts.length > 0 || deleteConflicts.length > 0) {\n                                                EditorManager.focusEditor();\n                                            }\n                                            \n                                            // (Any errors that ocurred during presentConflicts() have already\n                                            // shown UI & been dismissed, so there's no fail() handler here)\n                                        }\n                                    });\n                            });\n                            // Note: if any auto-reloads failed, we silently ignore (after logging to console)\n                            // and we still continue onto phase 4 and try to process those files anyway.\n                            // (We'll retry the auto-reloads next time window is activated... and evenually\n                            // we'll also be double checking before each Save).\n                    });\n            }).fail(function () {\n                // Unable to fetch timestamps for some reason - silently ignore (after logging to console)\n                // (We'll retry next time window is activated... and evenually we'll also be double\n                // checking before each Save).\n                \n                // We can't go on without knowing which files are dirty, so bail now\n                _alreadyChecking = false;\n            });\n        \n    }\n    \n    \n    // Define public API\n    exports.syncOpenDocuments = syncOpenDocuments;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * Utilities for determining the current \"build number\" / version\n */\ndefine('utils/BuildInfoUtils',['require','exports','module','file/NativeFileSystem','file/FileUtils'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        FileUtils           = require(\"file/FileUtils\");\n    \n    \n    var _bracketsSHA = null;\n    var _bracketsAppSHA = null;\n    \n    /**\n     * @return {?string} the Git SHA of the brackets submodule at the time when Brackets launched,\n     *      or null if no Git metadata was found on disk.\n     */\n    function getBracketsSHA() {\n        return _bracketsSHA;\n    }\n    \n    /**\n     * @return {?string} the Git SHA of the brackets-app module at the time when Brackets launched,\n     *      or null if no Git metadata was found on disk.\n     */\n    function getBracketsAppSHA() {\n        return _bracketsAppSHA;\n    }\n    \n    \n    /**\n     * Loads a SHA from Git metadata file. If the file contains a symbolic ref name, follows the ref\n     * and loads the SHA from that file in turn.\n     */\n    function _loadSHA(path, callback) {\n        var fileEntry = new NativeFileSystem.FileEntry(path);\n        var reader = new NativeFileSystem.FileReader();\n        \n        var result = new $.Deferred();\n        \n        // HEAD contains a SHA in detached-head mode; otherwise it contains a relative path\n        // to a file in /refs which in turn contains the SHA\n        fileEntry.file(function (file) {\n            reader.onload = function (event) {\n                var text = event.target.result;\n                \n                if (text.indexOf(\"ref: \") === 0) {\n                    var basePath = path.substr(0, path.lastIndexOf(\"/\"));\n                    var refRelPath = text.substr(5).trim();\n                    _loadSHA(basePath + \"/\" + refRelPath, callback)\n                        .pipe(result.resolve, result.reject);\n                } else {\n                    result.resolve(text);\n                }\n            };\n            reader.onerror = function (event) {\n                result.reject();\n            };\n            \n            reader.readAsText(file, \"utf8\");\n        });\n        \n        return result.promise();\n    }\n    \n    function init() {\n        // Look for Git metadata on disk to load the SHAs for 'brackets' and 'brackets-app'. Done on\n        // startup instead of on demand because the version that's currently running is what was\n        // loaded at startup (the src on disk may be updated to a different version later).\n        // Git metadata may be missing (e.g. in the per-sprint ZIP builds) - silently ignore if so.\n        var bracketsSrc = FileUtils.getNativeBracketsDirectoryPath();\n        var bracketsGitRoot = bracketsSrc + \"/../../.git/\";\n        var bracketsSubmoduleRoot_inParent = bracketsGitRoot + \"modules/brackets/\";\n        var bracketsSubmoduleRoot_inSubmodule = bracketsSrc + \"/../.git/\";\n        \n        _loadSHA(bracketsGitRoot + \"HEAD\")\n            .done(function (text) {\n                _bracketsAppSHA = text;\n            });\n        \n        // brackets submodule metadata may be in brackets/.git OR a subfolder of brackets-app/.git,\n        // so try both locations\n        _loadSHA(bracketsSubmoduleRoot_inSubmodule + \"HEAD\")\n            .done(function (text) {\n                _bracketsSHA = text;\n            })\n            .fail(function () {\n                _loadSHA(bracketsSubmoduleRoot_inParent + \"HEAD\")\n                    .done(function (text) {\n                        _bracketsSHA = text;\n                    });\n            });\n    }\n    \n    \n    // Define public API\n    exports.init                = init;\n    exports.getBracketsSHA      = getBracketsSHA;\n    exports.getBracketsAppSHA   = getBracketsAppSHA;\n});\n// jslint.js\n// 2012-01-13\n\n// Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n\n// The Software shall be used for Good, not Evil.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// WARNING: JSLint will hurt your feelings.\n\n// JSLINT is a global function. It takes two parameters.\n\n//     var myResult = JSLINT(source, option);\n\n// The first parameter is either a string or an array of strings. If it is a\n// string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n// is assumed that each string represents one line. The source can be a\n// JavaScript text, or HTML text, or a JSON text, or a CSS text.\n\n// The second parameter is an optional object of options that control the\n// operation of JSLINT. Most of the options are booleans: They are all\n// optional and have a default value of false. One of the options, predef,\n// can be an array of names, which will be used to declare global variables,\n// or an object whose keys are used as global names, with a boolean value\n// that determines if they are assignable.\n\n// If it checks out, JSLINT returns true. Otherwise, it returns false.\n\n// If false, you can inspect JSLINT.errors to find out the problems.\n// JSLINT.errors is an array of objects containing these properties:\n\n//  {\n//      line      : The line (relative to 0) at which the lint was found\n//      character : The character (relative to 0) at which the lint was found\n//      reason    : The problem\n//      evidence  : The text line in which the problem occurred\n//      raw       : The raw message before the details were inserted\n//      a         : The first detail\n//      b         : The second detail\n//      c         : The third detail\n//      d         : The fourth detail\n//  }\n\n// If a stopping error was found, a null will be the last element of the\n// JSLINT.errors array. A stopping error means that JSLint was not confident\n// enough to continue. It does not necessarily mean that the error was\n// especially heinous.\n\n// You can request a Function Report, which shows all of the functions\n// and the parameters and vars that they use. This can be used to find\n// implied global variables and other problems. The report is in HTML and\n// can be inserted in an HTML <body>.\n\n//     var myReport = JSLINT.report(errors_only);\n\n// If errors_only is true, then the report will be limited to only errors.\n\n// You can request a data structure that contains JSLint's results.\n\n//     var myData = JSLINT.data();\n\n// It returns a structure with this form:\n\n//     {\n//         errors: [\n//             {\n//                 line: NUMBER,\n//                 character: NUMBER,\n//                 reason: STRING,\n//                 evidence: STRING\n//             }\n//         ],\n//         functions: [\n//             {\n//                 name: STRING,\n//                 line: NUMBER,\n//                 last: NUMBER,\n//                 params: [\n//                     {\n//                         string: STRING\n//                     }\n//                 ],\n//                 closure: [\n//                     STRING\n//                 ],\n//                 var: [\n//                     STRING\n//                 ],\n//                 exception: [\n//                     STRING\n//                 ],\n//                 outer: [\n//                     STRING\n//                 ],\n//                 unused: [\n//                     STRING\n//                 ],\n//                 undef: [\n//                     STRING\n//                 ],\n//                 global: [\n//                     STRING\n//                 ],\n//                 label: [\n//                     STRING\n//                 ]\n//             }\n//         ],\n//         globals: [\n//             STRING\n//         ],\n//         member: {\n//             STRING: NUMBER\n//         },\n//         urls: [\n//             STRING\n//         ],\n//         json: BOOLEAN\n//     }\n\n// Empty arrays will not be included.\n\n// You can obtain the parse tree that JSLint constructed while parsing. The\n// latest tree is kept in JSLINT.tree. A nice stringication can be produced\n// with\n\n//     JSON.stringify(JSLINT.tree, [\n//         'string',  'arity', 'name',  'first',\n//         'second', 'third', 'block', 'else'\n//     ], 4));\n\n// JSLint provides three directives. They look like slashstar comments, and\n// allow for setting options, declaring global variables, and establishing a\n// set of allowed property names.\n\n// These directives respect function scope.\n\n// The jslint directive is a special comment that can set one or more options.\n// The current option set is\n\n//     anon       true, if the space may be omitted in anonymous function declarations\n//     bitwise    true, if bitwise operators should be allowed\n//     browser    true, if the standard browser globals should be predefined\n//     cap        true, if upper case HTML should be allowed\n//     confusion  true, if types can be used inconsistently\n//     'continue' true, if the continuation statement should be tolerated\n//     css        true, if CSS workarounds should be tolerated\n//     debug      true, if debugger statements should be allowed\n//     devel      true, if logging should be allowed (console, alert, etc.)\n//     eqeq       true, if == should be allowed\n//     es5        true, if ES5 syntax should be allowed\n//     evil       true, if eval should be allowed\n//     forin      true, if for in statements need not filter\n//     fragment   true, if HTML fragments should be allowed\n//     indent     the indentation factor\n//     maxerr     the maximum number of errors to allow\n//     maxlen     the maximum length of a source line\n//     newcap     true, if constructor names capitalization is ignored\n//     node       true, if Node.js globals should be predefined\n//     nomen      true, if names may have dangling _\n//     on         true, if HTML event handlers should be allowed\n//     passfail   true, if the scan should stop on first error\n//     plusplus   true, if increment/decrement should be allowed\n//     properties true, if all property names must be declared with /*properties*/\n//     regexp     true, if the . should be allowed in regexp literals\n//     rhino      true, if the Rhino environment globals should be predefined\n//     undef      true, if variables can be declared out of order\n//     unparam    true, if unused parameters should be tolerated\n//     sloppy     true, if the  pragma is optional\n//     sub        true, if all forms of subscript notation are tolerated\n//     vars       true, if multiple var statements per function should be allowed\n//     white      true, if sloppy whitespace is tolerated\n//     widget     true  if the Yahoo Widgets globals should be predefined\n//     windows    true, if MS Windows-specific globals should be predefined\n\n// For example:\n\n/*jslint\n    evil: true, nomen: true, regexp: true\n*/\n\n// The properties directive declares an exclusive list of property names.\n// Any properties named in the program that are not in the list will\n// produce a warning.\n\n// For example:\n\n/*properties\n    '\\b': string, '\\t': string, '\\n': string, '\\f': string, '\\r': string,\n    '!=': boolean, '!==': boolean, '\"': string, '%': boolean, '\\'': string,\n    '(begin)', '(breakage)': number, '(confusion)': boolean,\n    '(context)': object, '(error)', '(identifier)', '(line)': number,\n    '(loopage)': number, '(name)', '(old_property_type)', '(params)',\n    '(scope)': object, '(token)', '(vars)', '(verb)', '*': boolean,\n    '+': boolean, '-': boolean, '/': *, '<': boolean, '<=': boolean,\n    '==': boolean, '===': boolean, '>': boolean, '>=': boolean,\n    ADSAFE: boolean, Array, Date, E: string, Function, LN10: string,\n    LN2: string, LOG10E: string, LOG2E: string, MAX_VALUE: string,\n    MIN_VALUE: string, NEGATIVE_INFINITY: string, Object, PI: string,\n    POSITIVE_INFINITY: string, SQRT1_2: string, SQRT2: string, '\\\\': string,\n    a: object, a_label: string, a_not_allowed: string, a_not_defined: string,\n    a_scope: string, abbr: object, acronym: object, address: object, adsafe,\n    adsafe_a: string, adsafe_autocomplete: string, adsafe_bad_id: string,\n    adsafe_div: string, adsafe_fragment: string, adsafe_go: string,\n    adsafe_html: string, adsafe_id: string, adsafe_id_go: string,\n    adsafe_lib: string, adsafe_lib_second: string, adsafe_missing_id: string,\n    adsafe_name_a: string, adsafe_placement: string, adsafe_prefix_a: string,\n    adsafe_script: string, adsafe_source: string, adsafe_subscript_a: string,\n    adsafe_tag: string, all: boolean, already_defined: string, and: string,\n    anon, applet: object, apply: string, approved: array, area: object,\n    arity: string, article: object, aside: object, assign: boolean,\n    assign_exception: string, assignment_function_expression: string,\n    at: number, attribute_case_a: string, audio: object, autocomplete: string,\n    avoid_a: string, b: *, background: array, 'background-attachment': array,\n    'background-color': array, 'background-image': array,\n    'background-position': array, 'background-repeat': array,\n    bad_assignment: string, bad_color_a: string, bad_constructor: string,\n    bad_entity: string, bad_html: string, bad_id_a: string, bad_in_a: string,\n    bad_invocation: string, bad_name_a: string, bad_new: string,\n    bad_number: string, bad_operand: string, bad_style: string,\n    bad_type: string, bad_url_a: string, bad_wrap: string, base: object,\n    bdo: object, big: object, bind: string, bitwise: boolean, block: array,\n    blockquote: object, body: object, border: array, 'border-bottom': array,\n    'border-bottom-color', 'border-bottom-left-radius',\n    'border-bottom-right-radius', 'border-bottom-style': array,\n    'border-bottom-width', 'border-collapse': array, 'border-color': array,\n    'border-left': array, 'border-left-color', 'border-left-style': array,\n    'border-left-width', 'border-radius', 'border-right': array,\n    'border-right-color', 'border-right-style': array, 'border-right-width',\n    'border-spacing': array, 'border-style': array, 'border-top': array,\n    'border-top-color', 'border-top-left-radius', 'border-top-right-radius',\n    'border-top-style': array, 'border-top-width', 'border-width': array,\n    bottom: array, br: object, braille: boolean, browser: boolean,\n    button: object, c, call: string, canvas: object, cap, caption: object,\n    'caption-side': array, ceil: string, center: object, charAt: *,\n    charCodeAt: *, character, cite: object, clear: array, clip: array, closure,\n    cm: boolean, code: object, col: object, colgroup: object, color,\n    combine_var: string, command: object, concat: string,\n    conditional_assignment: string, confusing_a: string,\n    confusing_regexp: string, confusion: boolean, constructor: string,\n    constructor_name_a: string, content: array, continue, control_a: string,\n    'counter-increment': array, 'counter-reset': array, create: *, css: string,\n    cursor: array, d, dangerous_comment: string, dangling_a: string,\n    data: function object, datalist: object, dd: object, debug,\n    defineProperties: string, defineProperty: string, del: object,\n    deleted: string, details: object, devel: boolean, dfn: object,\n    dialog: object, dir: object, direction: array, display: array,\n    disrupt: boolean, div: object, dl: object, dt: object, duplicate_a: string,\n    edge: string, edition: string, else, em: *, embed: object,\n    embossed: boolean, empty: boolean, 'empty-cells': array,\n    empty_block: string, empty_case: string, empty_class: string,\n    entityify: function, eqeq, errors: array, es5: string, eval, every: string,\n    evidence, evil: string, ex: boolean, exception, exec: *,\n    expected_a: string, expected_a_at_b_c: string, expected_a_b: string,\n    expected_a_b_from_c_d: string, expected_at_a: string,\n    expected_attribute_a: string, expected_attribute_value_a: string,\n    expected_class_a: string, expected_fraction_a: string,\n    expected_id_a: string, expected_identifier_a: string,\n    expected_identifier_a_reserved: string, expected_lang_a: string,\n    expected_linear_a: string, expected_media_a: string,\n    expected_name_a: string, expected_nonstandard_style_attribute: string,\n    expected_number_a: string, expected_operator_a: string,\n    expected_percent_a: string, expected_positive_a: string,\n    expected_pseudo_a: string, expected_selector_a: string,\n    expected_small_a: string, expected_space_a_b: string,\n    expected_string_a: string, expected_style_attribute: string,\n    expected_style_pattern: string, expected_tagname_a: string,\n    expected_type_a: string, f: string, fieldset: object, figure: object,\n    filter: *, first: *, flag, float: array, floor: *, font: *, 'font-family',\n    'font-size': array, 'font-size-adjust': array, 'font-stretch': array,\n    'font-style': array, 'font-variant': array, 'font-weight': array,\n    footer: object, for, forEach: *, for_if: string, forin, form: object,\n    fragment, frame: object, frameset: object, freeze: string, from: number,\n    fromCharCode: function, fud: function, funct: object, function,\n    function_block: string, function_eval: string, function_loop: string,\n    function_statement: string, function_strict: string, functions: array,\n    getDate: string, getDay: string, getFullYear: string, getHours: string,\n    getMilliseconds: string, getMinutes: string, getMonth: string,\n    getOwnPropertyDescriptor: string, getOwnPropertyNames: string,\n    getPrototypeOf: string, getSeconds: string, getTime: string,\n    getTimezoneOffset: string, getUTCDate: string, getUTCDay: string,\n    getUTCFullYear: string, getUTCHours: string, getUTCMilliseconds: string,\n    getUTCMinutes: string, getUTCMonth: string, getUTCSeconds: string,\n    getYear: string, global, globals, h1: object, h2: object, h3: object,\n    h4: object, h5: object, h6: object, handheld: boolean, hasOwnProperty: *,\n    head: object, header: object, height: array, hgroup: object, hr: object,\n    'hta:application': object, html: *, html_confusion_a: string,\n    html_handlers: string, i: object, id: string, identifier: boolean,\n    identifier_function: string, iframe: object, img: object, immed: boolean,\n    implied_evil: string, in, indent: number, indexOf: *, infix_in: string,\n    init: function, input: object, ins: object, insecure_a: string,\n    isAlpha: function, isArray: function boolean, isDigit: function,\n    isExtensible: string, isFrozen: string, isNaN: string,\n    isPrototypeOf: string, isSealed: string, join: *, jslint: function boolean,\n    json: boolean, kbd: object, keygen: object, keys: *, label: object,\n    label_a_b: string, labeled: boolean, lang: string, lastIndex: string,\n    lastIndexOf: *, lbp: number, leading_decimal_a: string, led: function,\n    left: array, legend: object, length: *, 'letter-spacing': array,\n    li: object, lib: boolean, line: number, 'line-height': array, link: object,\n    'list-style': array, 'list-style-image': array,\n    'list-style-position': array, 'list-style-type': array, map: *,\n    margin: array, 'margin-bottom', 'margin-left', 'margin-right',\n    'margin-top', mark: object, 'marker-offset': array, match: function,\n    'max-height': array, 'max-width': array, maxerr: number,\n    maxlen: number, member: object, menu: object, message, meta: object,\n    meter: object, 'min-height': function, 'min-width': function,\n    missing_a: string, missing_a_after_b: string, missing_option: string,\n    missing_property: string, missing_space_a_b: string, missing_url: string,\n    missing_use_strict: string, mixed: string, mm: boolean, mode: string,\n    move_invocation: string, move_var: string, n: string, name: string,\n    name_function: string, nav: object, nested_comment: string,\n    newcap: boolean, node: boolean, noframes: object, nomen, noscript: object,\n    not: string, not_a_constructor: string, not_a_defined: string,\n    not_a_function: string, not_a_label: string, not_a_scope: string,\n    not_greater: string, now: string, nud: function, number: number,\n    object: object, ol: object, on, opacity, open: boolean, optgroup: object,\n    option: object, outer: regexp, outline: array, 'outline-color': array,\n    'outline-style': array, 'outline-width', output: object, overflow: array,\n    'overflow-x': array, 'overflow-y': array, p: object, padding: array,\n    'padding-bottom': function, 'padding-left': function,\n    'padding-right': function, 'padding-top': function,\n    'page-break-after': array, 'page-break-before': array, param: object,\n    parameter_a_get_b: string, parameter_set_a: string, params: array,\n    paren: boolean, parent: string, parse: string, passfail, pc: boolean,\n    plusplus, pop: *, position: array, postscript: boolean, pre: object,\n    predef, preventExtensions: string, print: boolean, progress: object,\n    projection: boolean, properties: boolean, propertyIsEnumerable: string,\n    prototype: string, pt: boolean, push: *, px: boolean, q: object, quote,\n    quotes: array, r: string, radix: string, range: function, raw,\n    read_only: string, reason, redefinition_a: string, reduce: string,\n    reduceRight: string, regexp, replace: function, report: function,\n    reserved: boolean, reserved_a: string, reverse: string, rhino: boolean,\n    right: array, rp: object, rt: object, ruby: object, safe: boolean,\n    samp: object, scanned_a_b: string, screen: boolean, script: object,\n    seal: string, search: function, second: *, section: object, select: object,\n    setDate: string, setDay: string, setFullYear: string, setHours: string,\n    setMilliseconds: string, setMinutes: string, setMonth: string,\n    setSeconds: string, setTime: string, setTimezoneOffset: string,\n    setUTCDate: string, setUTCDay: string, setUTCFullYear: string,\n    setUTCHours: string, setUTCMilliseconds: string, setUTCMinutes: string,\n    setUTCMonth: string, setUTCSeconds: string, setYear: string, shift: *,\n    slash_equal: string, slice: string, sloppy, small: object, some: string,\n    sort: *, source: object, span: object, speech: boolean, splice: string,\n    split: function, src, statement_block: string, stopping: string,\n    strange_loop: string, strict: string, string: string, stringify: string,\n    strong: object, style: *, styleproperty: regexp, sub: object,\n    subscript: string, substr: *, substring: string, sup: object,\n    supplant: function, t: string, table: object, 'table-layout': array,\n    tag_a_in_b: string, tbody: object, td: object, test: *,\n    'text-align': array, 'text-decoration': array, 'text-indent': function,\n    'text-shadow': array, 'text-transform': array, textarea: object,\n    tfoot: object, th: object, thead: object, third: array, thru: number,\n    time: object, title: object, toDateString: string, toExponential: string,\n    toFixed: string, toISOString: string, toJSON: string,\n    toLocaleDateString: string, toLocaleLowerCase: string,\n    toLocaleString: string, toLocaleTimeString: string,\n    toLocaleUpperCase: string, toLowerCase: *, toPrecision: string,\n    toString: function, toTimeString: string, toUTCString: string,\n    toUpperCase: *, token: function, too_long: string, too_many: string,\n    top: array, tr: object, trailing_decimal_a: string, tree: string,\n    trim: string, tt: object, tty: boolean, tv: boolean, type: string,\n    type_confusion_a_b: string, u: object, ul: object, unclosed: string,\n    unclosed_comment: string, unclosed_regexp: string, undef: boolean,\n    undefined, unescaped_a: string, unexpected_a: string,\n    unexpected_char_a_b: string, unexpected_comment: string,\n    unexpected_property_a: string, unexpected_space_a_b: string,\n    'unicode-bidi': array, unnecessary_initialize: string,\n    unnecessary_use: string, unparam, unreachable_a_b: string,\n    unrecognized_style_attribute_a: string, unrecognized_tag_a: string,\n    unsafe: string, unshift: string, unused: array, url: string, urls: array,\n    use_array: string, use_braces: string, use_charAt: string,\n    use_object: string, use_or: string, use_param: string,\n    used_before_a: string, valueOf: string, var: object, var_a_not: string,\n    vars, 'vertical-align': array, video: object, visibility: array,\n    warn: boolean, was: object, weird_assignment: string,\n    weird_condition: string, weird_new: string, weird_program: string,\n    weird_relation: string, weird_ternary: string, white: boolean,\n    'white-space': array, widget: boolean, width: array, windows: boolean,\n    'word-spacing': array, 'word-wrap': array, wrap: boolean,\n    wrap_immediate: string, wrap_regexp: string, write_is_wrong: string,\n    writeable: boolean, 'z-index': array\n*/\n\n// The global directive is used to declare global variables that can\n// be accessed by the program. If a declaration is true, then the variable\n// is writeable. Otherwise, it is read-only.\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSLINT function itself. That function is also an object that\n// can contain data and other functions.\n\nvar JSLINT = (function () {\n    \n\n    function array_to_object(array, value) {\n\n// Make an object from an array of keys and a common value.\n\n        var i, length = array.length, object = {};\n        for (i = 0; i < length; i += 1) {\n            object[array[i]] = value;\n        }\n        return object;\n    }\n\n\n    var adsafe_id,      // The widget's ADsafe id.\n        adsafe_may,     // The widget may load approved scripts.\n        adsafe_top,     // At the top of the widget script.\n        adsafe_went,    // ADSAFE.go has been called.\n        allowed_option = {\n            anon      : true,\n            bitwise   : true,\n            browser   : true,\n            cap       : true,\n            confusion : true,\n            'continue': true,\n            css       : true,\n            debug     : true,\n            devel     : true,\n            eqeq      : true,\n            es5       : true,\n            evil      : true,\n            forin     : true,\n            fragment  : true,\n            indent    :   10,\n            maxerr    : 1000,\n            maxlen    :  256,\n            newcap    : true,\n            node      : true,\n            nomen     : true,\n            on        : true,\n            passfail  : true,\n            plusplus  : true,\n            properties: true,\n            regexp    : true,\n            rhino     : true,\n            undef     : true,\n            unparam   : true,\n            sloppy    : true,\n            sub       : true,\n            vars      : true,\n            white     : true,\n            widget    : true,\n            windows   : true\n        },\n        anonname,       // The guessed name for anonymous functions.\n        approved,       // ADsafe approved urls.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n// These are property names that should not be permitted in the safe subset.\n\n        banned = array_to_object([\n            'arguments', 'callee', 'caller', 'constructor', 'eval', 'prototype',\n            'stack', 'unwatch', 'valueOf', 'watch'\n        ], true),\n        begin,          // The root token\n\n// browser contains a set of global names that are commonly provided by a\n// web browser environment.\n\n        browser = array_to_object([\n            'clearInterval', 'clearTimeout', 'document', 'event', 'frames',\n            'history', 'Image', 'localStorage', 'location', 'name', 'navigator',\n            'Option', 'parent', 'screen', 'sessionStorage', 'setInterval',\n            'setTimeout', 'Storage', 'window', 'XMLHttpRequest'\n        ], false),\n\n// bundle contains the text messages.\n\n        bundle = {\n            a_label: \"'{a}' is a statement label.\",\n            a_not_allowed: \"'{a}' is not allowed.\",\n            a_not_defined: \"'{a}' is not defined.\",\n            a_scope: \"'{a}' used out of scope.\",\n            adsafe_a: \"ADsafe violation: '{a}'.\",\n            adsafe_autocomplete: \"ADsafe autocomplete violation.\",\n            adsafe_bad_id: \"ADSAFE violation: bad id.\",\n            adsafe_div: \"ADsafe violation: Wrap the widget in a div.\",\n            adsafe_fragment: \"ADSAFE: Use the fragment option.\",\n            adsafe_go: \"ADsafe violation: Misformed ADSAFE.go.\",\n            adsafe_html: \"Currently, ADsafe does not operate on whole HTML \" +\n                \"documents. It operates on <div> fragments and .js files.\",\n            adsafe_id: \"ADsafe violation: id does not match.\",\n            adsafe_id_go: \"ADsafe violation: Missing ADSAFE.id or ADSAFE.go.\",\n            adsafe_lib: \"ADsafe lib violation.\",\n            adsafe_lib_second: \"ADsafe: The second argument to lib must be a function.\",\n            adsafe_missing_id: \"ADSAFE violation: missing ID_.\",\n            adsafe_name_a: \"ADsafe name violation: '{a}'.\",\n            adsafe_placement: \"ADsafe script placement violation.\",\n            adsafe_prefix_a: \"ADsafe violation: An id must have a '{a}' prefix\",\n            adsafe_script: \"ADsafe script violation.\",\n            adsafe_source: \"ADsafe unapproved script source.\",\n            adsafe_subscript_a: \"ADsafe subscript '{a}'.\",\n            adsafe_tag: \"ADsafe violation: Disallowed tag '{a}'.\",\n            already_defined: \"'{a}' is already defined.\",\n            and: \"The '&&' subexpression should be wrapped in parens.\",\n            assign_exception: \"Do not assign to the exception parameter.\",\n            assignment_function_expression: \"Expected an assignment or \" +\n                \"function call and instead saw an expression.\",\n            attribute_case_a: \"Attribute '{a}' not all lower case.\",\n            avoid_a: \"Avoid '{a}'.\",\n            bad_assignment: \"Bad assignment.\",\n            bad_color_a: \"Bad hex color '{a}'.\",\n            bad_constructor: \"Bad constructor.\",\n            bad_entity: \"Bad entity.\",\n            bad_html: \"Bad HTML string\",\n            bad_id_a: \"Bad id: '{a}'.\",\n            bad_in_a: \"Bad for in variable '{a}'.\",\n            bad_invocation: \"Bad invocation.\",\n            bad_name_a: \"Bad name: '{a}'.\",\n            bad_new: \"Do not use 'new' for side effects.\",\n            bad_number: \"Bad number '{a}'.\",\n            bad_operand: \"Bad operand.\",\n            bad_style: \"Bad style.\",\n            bad_type: \"Bad type.\",\n            bad_url_a: \"Bad url '{a}'.\",\n            bad_wrap: \"Do not wrap function literals in parens unless they \" +\n                \"are to be immediately invoked.\",\n            combine_var: \"Combine this with the previous 'var' statement.\",\n            conditional_assignment: \"Expected a conditional expression and \" +\n                \"instead saw an assignment.\",\n            confusing_a: \"Confusing use of '{a}'.\",\n            confusing_regexp: \"Confusing regular expression.\",\n            constructor_name_a: \"A constructor name '{a}' should start with \" +\n                \"an uppercase letter.\",\n            control_a: \"Unexpected control character '{a}'.\",\n            css: \"A css file should begin with @charset 'UTF-8';\",\n            dangling_a: \"Unexpected dangling '_' in '{a}'.\",\n            dangerous_comment: \"Dangerous comment.\",\n            deleted: \"Only properties should be deleted.\",\n            duplicate_a: \"Duplicate '{a}'.\",\n            empty_block: \"Empty block.\",\n            empty_case: \"Empty case.\",\n            empty_class: \"Empty class.\",\n            es5: \"This is an ES5 feature.\",\n            evil: \"eval is evil.\",\n            expected_a: \"Expected '{a}'.\",\n            expected_a_b: \"Expected '{a}' and instead saw '{b}'.\",\n            expected_a_b_from_c_d: \"Expected '{a}' to match '{b}' from line \" +\n                \"{c} and instead saw '{d}'.\",\n            expected_at_a: \"Expected an at-rule, and instead saw @{a}.\",\n            expected_a_at_b_c: \"Expected '{a}' at column {b}, not column {c}.\",\n            expected_attribute_a: \"Expected an attribute, and instead saw [{a}].\",\n            expected_attribute_value_a: \"Expected an attribute value and \" +\n                \"instead saw '{a}'.\",\n            expected_class_a: \"Expected a class, and instead saw .{a}.\",\n            expected_fraction_a: \"Expected a number between 0 and 1 and \" +\n                \"instead saw '{a}'\",\n            expected_id_a: \"Expected an id, and instead saw #{a}.\",\n            expected_identifier_a: \"Expected an identifier and instead saw '{a}'.\",\n            expected_identifier_a_reserved: \"Expected an identifier and \" +\n                \"instead saw '{a}' (a reserved word).\",\n            expected_linear_a: \"Expected a linear unit and instead saw '{a}'.\",\n            expected_lang_a: \"Expected a lang code, and instead saw :{a}.\",\n            expected_media_a: \"Expected a CSS media type, and instead saw '{a}'.\",\n            expected_name_a: \"Expected a name and instead saw '{a}'.\",\n            expected_nonstandard_style_attribute: \"Expected a non-standard \" +\n                \"style attribute and instead saw '{a}'.\",\n            expected_number_a: \"Expected a number and instead saw '{a}'.\",\n            expected_operator_a: \"Expected an operator and instead saw '{a}'.\",\n            expected_percent_a: \"Expected a percentage and instead saw '{a}'\",\n            expected_positive_a: \"Expected a positive number and instead saw '{a}'\",\n            expected_pseudo_a: \"Expected a pseudo, and instead saw :{a}.\",\n            expected_selector_a: \"Expected a CSS selector, and instead saw {a}.\",\n            expected_small_a: \"Expected a small positive integer and instead saw '{a}'\",\n            expected_space_a_b: \"Expected exactly one space between '{a}' and '{b}'.\",\n            expected_string_a: \"Expected a string and instead saw {a}.\",\n            expected_style_attribute: \"Excepted a style attribute, and instead saw '{a}'.\",\n            expected_style_pattern: \"Expected a style pattern, and instead saw '{a}'.\",\n            expected_tagname_a: \"Expected a tagName, and instead saw {a}.\",\n            expected_type_a: \"Expected a type, and instead saw {a}.\",\n            for_if: \"The body of a for in should be wrapped in an if \" +\n                \"statement to filter unwanted properties from the prototype.\",\n            function_block: \"Function statements should not be placed in blocks. \" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\",\n            function_eval: \"The Function constructor is eval.\",\n            function_loop: \"Don't make functions within a loop.\",\n            function_statement: \"Function statements are not invocable. \" +\n                \"Wrap the whole function invocation in parens.\",\n            function_strict: \"Use the function form of 'use strict'.\",\n            html_confusion_a: \"HTML confusion in regular expression '<{a}'.\",\n            html_handlers: \"Avoid HTML event handlers.\",\n            identifier_function: \"Expected an identifier in an assignment \" +\n                \"and instead saw a function invocation.\",\n            implied_evil: \"Implied eval is evil. Pass a function instead of a string.\",\n            infix_in: \"Unexpected 'in'. Compare with undefined, or use the \" +\n                \"hasOwnProperty method instead.\",\n            insecure_a: \"Insecure '{a}'.\",\n            isNaN: \"Use the isNaN function to compare with NaN.\",\n            label_a_b: \"Label '{a}' on '{b}' statement.\",\n            lang: \"lang is deprecated.\",\n            leading_decimal_a: \"A leading decimal point can be confused with a dot: '.{a}'.\",\n            missing_a: \"Missing '{a}'.\",\n            missing_a_after_b: \"Missing '{a}' after '{b}'.\",\n            missing_option: \"Missing option value.\",\n            missing_property: \"Missing property name.\",\n            missing_space_a_b: \"Missing space between '{a}' and '{b}'.\",\n            missing_url: \"Missing url.\",\n            missing_use_strict: \"Missing 'use strict' statement.\",\n            mixed: \"Mixed spaces and tabs.\",\n            move_invocation: \"Move the invocation into the parens that \" +\n                \"contain the function.\",\n            move_var: \"Move 'var' declarations to the top of the function.\",\n            name_function: \"Missing name in function statement.\",\n            nested_comment: \"Nested comment.\",\n            not: \"Nested not.\",\n            not_a_constructor: \"Do not use {a} as a constructor.\",\n            not_a_defined: \"'{a}' has not been fully defined yet.\",\n            not_a_function: \"'{a}' is not a function.\",\n            not_a_label: \"'{a}' is not a label.\",\n            not_a_scope: \"'{a}' is out of scope.\",\n            not_greater: \"'{a}' should not be greater than '{b}'.\",\n            parameter_a_get_b: \"Unexpected parameter '{a}' in get {b} function.\",\n            parameter_set_a: \"Expected parameter (value) in set {a} function.\",\n            radix: \"Missing radix parameter.\",\n            read_only: \"Read only.\",\n            redefinition_a: \"Redefinition of '{a}'.\",\n            reserved_a: \"Reserved name '{a}'.\",\n            scanned_a_b: \"{a} ({b}% scanned).\",\n            slash_equal: \"A regular expression literal can be confused with '/='.\",\n            statement_block: \"Expected to see a statement and instead saw a block.\",\n            stopping: \"Stopping. \",\n            strange_loop: \"Strange loop.\",\n            strict: \"Strict violation.\",\n            subscript: \"['{a}'] is better written in dot notation.\",\n            tag_a_in_b: \"A '<{a}>' must be within '<{b}>'.\",\n            too_long: \"Line too long.\",\n            too_many: \"Too many errors.\",\n            trailing_decimal_a: \"A trailing decimal point can be confused \" +\n                \"with a dot: '.{a}'.\",\n            type: \"type is unnecessary.\",\n            type_confusion_a_b: \"Type confusion: {a} and {b}.\",\n            unclosed: \"Unclosed string.\",\n            unclosed_comment: \"Unclosed comment.\",\n            unclosed_regexp: \"Unclosed regular expression.\",\n            unescaped_a: \"Unescaped '{a}'.\",\n            unexpected_a: \"Unexpected '{a}'.\",\n            unexpected_char_a_b: \"Unexpected character '{a}' in {b}.\",\n            unexpected_comment: \"Unexpected comment.\",\n            unexpected_property_a: \"Unexpected /*property*/ '{a}'.\",\n            unexpected_space_a_b: \"Unexpected space between '{a}' and '{b}'.\",\n            unnecessary_initialize: \"It is not necessary to initialize '{a}' \" +\n                \"to 'undefined'.\",\n            unnecessary_use: \"Unnecessary 'use strict'.\",\n            unreachable_a_b: \"Unreachable '{a}' after '{b}'.\",\n            unrecognized_style_attribute_a: \"Unrecognized style attribute '{a}'.\",\n            unrecognized_tag_a: \"Unrecognized tag '<{a}>'.\",\n            unsafe: \"Unsafe character.\",\n            url: \"JavaScript URL.\",\n            use_array: \"Use the array literal notation [].\",\n            use_braces: \"Spaces are hard to count. Use {{a}}.\",\n            use_charAt: \"Use the charAt method.\",\n            use_object: \"Use the object literal notation {}.\",\n            use_or: \"Use the || operator.\",\n            use_param: \"Use a named parameter.\",\n            used_before_a: \"'{a}' was used before it was defined.\",\n            var_a_not: \"Variable {a} was not declared correctly.\",\n            weird_assignment: \"Weird assignment.\",\n            weird_condition: \"Weird condition.\",\n            weird_new: \"Weird construction. Delete 'new'.\",\n            weird_program: \"Weird program.\",\n            weird_relation: \"Weird relation.\",\n            weird_ternary: \"Weird ternary.\",\n            wrap_immediate: \"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\",\n            wrap_regexp: \"Wrap the /regexp/ literal in parens to \" +\n                \"disambiguate the slash operator.\",\n            write_is_wrong: \"document.write can be a form of eval.\"\n        },\n        comments_off,\n        css_attribute_data,\n        css_any,\n\n        css_colorData = array_to_object([\n            \"aliceblue\", \"antiquewhite\", \"aqua\", \"aquamarine\", \"azure\", \"beige\",\n            \"bisque\", \"black\", \"blanchedalmond\", \"blue\", \"blueviolet\", \"brown\",\n            \"burlywood\", \"cadetblue\", \"chartreuse\", \"chocolate\", \"coral\",\n            \"cornflowerblue\", \"cornsilk\", \"crimson\", \"cyan\", \"darkblue\",\n            \"darkcyan\", \"darkgoldenrod\", \"darkgray\", \"darkgreen\", \"darkkhaki\",\n            \"darkmagenta\", \"darkolivegreen\", \"darkorange\", \"darkorchid\",\n            \"darkred\", \"darksalmon\", \"darkseagreen\", \"darkslateblue\",\n            \"darkslategray\", \"darkturquoise\", \"darkviolet\", \"deeppink\",\n            \"deepskyblue\", \"dimgray\", \"dodgerblue\", \"firebrick\", \"floralwhite\",\n            \"forestgreen\", \"fuchsia\", \"gainsboro\", \"ghostwhite\", \"gold\",\n            \"goldenrod\", \"gray\", \"green\", \"greenyellow\", \"honeydew\", \"hotpink\",\n            \"indianred\", \"indigo\", \"ivory\", \"khaki\", \"lavender\",\n            \"lavenderblush\", \"lawngreen\", \"lemonchiffon\", \"lightblue\",\n            \"lightcoral\", \"lightcyan\", \"lightgoldenrodyellow\", \"lightgreen\",\n            \"lightpink\", \"lightsalmon\", \"lightseagreen\", \"lightskyblue\",\n            \"lightslategray\", \"lightsteelblue\", \"lightyellow\", \"lime\",\n            \"limegreen\", \"linen\", \"magenta\", \"maroon\", \"mediumaquamarine\",\n            \"mediumblue\", \"mediumorchid\", \"mediumpurple\", \"mediumseagreen\",\n            \"mediumslateblue\", \"mediumspringgreen\", \"mediumturquoise\",\n            \"mediumvioletred\", \"midnightblue\", \"mintcream\", \"mistyrose\",\n            \"moccasin\", \"navajowhite\", \"navy\", \"oldlace\", \"olive\", \"olivedrab\",\n            \"orange\", \"orangered\", \"orchid\", \"palegoldenrod\", \"palegreen\",\n            \"paleturquoise\", \"palevioletred\", \"papayawhip\", \"peachpuff\",\n            \"peru\", \"pink\", \"plum\", \"powderblue\", \"purple\", \"red\", \"rosybrown\",\n            \"royalblue\", \"saddlebrown\", \"salmon\", \"sandybrown\", \"seagreen\",\n            \"seashell\", \"sienna\", \"silver\", \"skyblue\", \"slateblue\", \"slategray\",\n            \"snow\", \"springgreen\", \"steelblue\", \"tan\", \"teal\", \"thistle\",\n            \"tomato\", \"turquoise\", \"violet\", \"wheat\", \"white\", \"whitesmoke\",\n            \"yellow\", \"yellowgreen\",\n\n            \"activeborder\", \"activecaption\", \"appworkspace\", \"background\",\n            \"buttonface\", \"buttonhighlight\", \"buttonshadow\", \"buttontext\",\n            \"captiontext\", \"graytext\", \"highlight\", \"highlighttext\",\n            \"inactiveborder\", \"inactivecaption\", \"inactivecaptiontext\",\n            \"infobackground\", \"infotext\", \"menu\", \"menutext\", \"scrollbar\",\n            \"threeddarkshadow\", \"threedface\", \"threedhighlight\",\n            \"threedlightshadow\", \"threedshadow\", \"window\", \"windowframe\",\n            \"windowtext\"\n        ], true),\n\n        css_border_style,\n        css_break,\n\n        css_lengthData = {\n            '%': true,\n            'cm': true,\n            'em': true,\n            'ex': true,\n            'in': true,\n            'mm': true,\n            'pc': true,\n            'pt': true,\n            'px': true\n        },\n\n        css_media,\n        css_overflow,\n\n        descapes = {\n            'b': '\\b',\n            't': '\\t',\n            'n': '\\n',\n            'f': '\\f',\n            'r': '\\r',\n            '\"': '\"',\n            '/': '/',\n            '\\\\': '\\\\'\n        },\n\n        devel = array_to_object([\n            'alert', 'confirm', 'console', 'Debug', 'opera', 'prompt', 'WSH'\n        ], false),\n        directive,\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\\'': '\\\\\\'',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function, including the labels used in\n                        // the function, as well as (breakage),\n                        // (context), (loopage), (name), (params), (token),\n                        // (vars), (verb)\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label', 'outer', 'undef',\n            'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n        global_funct,   // The global body\n        global_scope,   // The global scope\n        html_tag = {\n            a:        {},\n            abbr:     {},\n            acronym:  {},\n            address:  {},\n            applet:   {},\n            area:     {empty: true, parent: ' map '},\n            article:  {},\n            aside:    {},\n            audio:    {},\n            b:        {},\n            base:     {empty: true, parent: ' head '},\n            bdo:      {},\n            big:      {},\n            blockquote: {},\n            body:     {parent: ' html noframes '},\n            br:       {empty: true},\n            button:   {},\n            canvas:   {parent: ' body p div th td '},\n            caption:  {parent: ' table '},\n            center:   {},\n            cite:     {},\n            code:     {},\n            col:      {empty: true, parent: ' table colgroup '},\n            colgroup: {parent: ' table '},\n            command:  {parent: ' menu '},\n            datalist: {},\n            dd:       {parent: ' dl '},\n            del:      {},\n            details:  {},\n            dialog:   {},\n            dfn:      {},\n            dir:      {},\n            div:      {},\n            dl:       {},\n            dt:       {parent: ' dl '},\n            em:       {},\n            embed:    {},\n            fieldset: {},\n            figure:   {},\n            font:     {},\n            footer:   {},\n            form:     {},\n            frame:    {empty: true, parent: ' frameset '},\n            frameset: {parent: ' html frameset '},\n            h1:       {},\n            h2:       {},\n            h3:       {},\n            h4:       {},\n            h5:       {},\n            h6:       {},\n            head:     {parent: ' html '},\n            header:   {},\n            hgroup:   {},\n            hr:       {empty: true},\n            'hta:application':\n                      {empty: true, parent: ' head '},\n            html:     {parent: '*'},\n            i:        {},\n            iframe:   {},\n            img:      {empty: true},\n            input:    {empty: true},\n            ins:      {},\n            kbd:      {},\n            keygen:   {},\n            label:    {},\n            legend:   {parent: ' details fieldset figure '},\n            li:       {parent: ' dir menu ol ul '},\n            link:     {empty: true, parent: ' head '},\n            map:      {},\n            mark:     {},\n            menu:     {},\n            meta:     {empty: true, parent: ' head noframes noscript '},\n            meter:    {},\n            nav:      {},\n            noframes: {parent: ' html body '},\n            noscript: {parent: ' body head noframes '},\n            object:   {},\n            ol:       {},\n            optgroup: {parent: ' select '},\n            option:   {parent: ' optgroup select '},\n            output:   {},\n            p:        {},\n            param:    {empty: true, parent: ' applet object '},\n            pre:      {},\n            progress: {},\n            q:        {},\n            rp:       {},\n            rt:       {},\n            ruby:     {},\n            samp:     {},\n            script:   {empty: true, parent: ' body div frame head iframe p pre span '},\n            section:  {},\n            select:   {},\n            small:    {},\n            span:     {},\n            source:   {},\n            strong:   {},\n            style:    {parent: ' head ', empty: true},\n            sub:      {},\n            sup:      {},\n            table:    {},\n            tbody:    {parent: ' table '},\n            td:       {parent: ' tr '},\n            textarea: {},\n            tfoot:    {parent: ' table '},\n            th:       {parent: ' tr '},\n            thead:    {parent: ' table '},\n            time:     {},\n            title:    {parent: ' head '},\n            tr:       {parent: ' table tbody thead tfoot '},\n            tt:       {},\n            u:        {},\n            ul:       {},\n            'var':    {},\n            video:    {}\n        },\n\n        ids,            // HTML ids\n        in_block,\n        indent,\n//         infer_statement,// Inference rules for statements\n        is_type = array_to_object([\n            '*', 'array', 'boolean', 'function', 'number', 'object',\n            'regexp', 'string'\n        ], true),\n        itself,         // JSLint itself\n        json_mode,\n        lex,            // the tokenizer\n        lines,\n        lookahead,\n        member,\n        node = array_to_object([\n            'Buffer', 'clearInterval', 'clearTimeout', 'console', 'exports',\n            'global', 'module', 'process', 'querystring', 'require',\n            'setInterval', 'setTimeout', '__dirname', '__filename'\n        ], false),\n        node_js,\n        numbery = array_to_object(['indexOf', 'lastIndexOf', 'search'], true),\n        next_token,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prev_token,\n        property_type,\n        regexp_flag = array_to_object(['g', 'i', 'm'], true),\n        return_this = function return_this() {\n            return this;\n        },\n        rhino = array_to_object([\n            'defineClass', 'deserialize', 'gc', 'help', 'load', 'loadClass',\n            'print', 'quit', 'readFile', 'readUrl', 'runCommand', 'seal',\n            'serialize', 'spawn', 'sync', 'toint32', 'version'\n        ], false),\n\n        scope,      // An object containing an object for each variable in scope\n        semicolon_coda = array_to_object([';', '\"', '\\'', ')'], true),\n        src,\n        stack,\n\n// standard contains the global names that are provided by the\n// ECMAScript standard.\n\n        standard = array_to_object([\n            'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent',\n            'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError',\n            'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number', 'Object',\n            'parseInt', 'parseFloat', 'RangeError', 'ReferenceError', 'RegExp',\n            'String', 'SyntaxError', 'TypeError', 'URIError'\n        ], false),\n\n        standard_property_type = {\n            E                   : 'number',\n            LN2                 : 'number',\n            LN10                : 'number',\n            LOG2E               : 'number',\n            LOG10E              : 'number',\n            MAX_VALUE           : 'number',\n            MIN_VALUE           : 'number',\n            NEGATIVE_INFINITY   : 'number',\n            PI                  : 'number',\n            POSITIVE_INFINITY   : 'number',\n            SQRT1_2             : 'number',\n            SQRT2               : 'number',\n            apply               : 'function',\n            bind                : 'function function',\n            call                : 'function',\n            ceil                : 'function number',\n            charAt              : 'function string',\n            concat              : 'function',\n            constructor         : 'function object',\n            create              : 'function object',\n            defineProperty      : 'function object',\n            defineProperties    : 'function object',\n            every               : 'function boolean',\n            exec                : 'function array',\n            filter              : 'function array',\n            floor               : 'function number',\n            forEach             : 'function',\n            freeze              : 'function object',\n            getDate             : 'function number',\n            getDay              : 'function number',\n            getFullYear         : 'function number',\n            getHours            : 'function number',\n            getMilliseconds     : 'function number',\n            getMinutes          : 'function number',\n            getMonth            : 'function number',\n            getOwnPropertyDescriptor\n                                : 'function object',\n            getOwnPropertyNames : 'function array',\n            getPrototypeOf      : 'function object',\n            getSeconds          : 'function number',\n            getTime             : 'function number',\n            getTimezoneOffset   : 'function number',\n            getUTCDate          : 'function number',\n            getUTCDay           : 'function number',\n            getUTCFullYear      : 'function number',\n            getUTCHours         : 'function number',\n            getUTCMilliseconds  : 'function number',\n            getUTCMinutes       : 'function number',\n            getUTCMonth         : 'function number',\n            getUTCSeconds       : 'function number',\n            getYear             : 'function number',\n            hasOwnProperty      : 'function boolean',\n            indexOf             : 'function number',\n            isExtensible        : 'function boolean',\n            isFrozen            : 'function boolean',\n            isPrototypeOf       : 'function boolean',\n            isSealed            : 'function boolean',\n            join                : 'function string',\n            keys                : 'function array',\n            lastIndexOf         : 'function number',\n            lastIndex           : 'number',\n            length              : 'number',\n            map                 : 'function array',\n            now                 : 'function number',\n            parse               : 'function',\n            pop                 : 'function',\n            preventExtensions   : 'function object',\n            propertyIsEnumerable: 'function boolean',\n            prototype           : 'object',\n            push                : 'function number',\n            reduce              : 'function',\n            reduceRight         : 'function',\n            reverse             : 'function',\n            seal                : 'function object',\n            setDate             : 'function',\n            setDay              : 'function',\n            setFullYear         : 'function',\n            setHours            : 'function',\n            setMilliseconds     : 'function',\n            setMinutes          : 'function',\n            setMonth            : 'function',\n            setSeconds          : 'function',\n            setTime             : 'function',\n            setTimezoneOffset   : 'function',\n            setUTCDate          : 'function',\n            setUTCDay           : 'function',\n            setUTCFullYear      : 'function',\n            setUTCHours         : 'function',\n            setUTCMilliseconds  : 'function',\n            setUTCMinutes       : 'function',\n            setUTCMonth         : 'function',\n            setUTCSeconds       : 'function',\n            setYear             : 'function',\n            shift               : 'function',\n            slice               : 'function',\n            some                : 'function boolean',\n            sort                : 'function',\n            splice              : 'function',\n            stringify           : 'function string',\n            substr              : 'function string',\n            substring           : 'function string',\n            test                : 'function boolean',\n            toDateString        : 'function string',\n            toExponential       : 'function string',\n            toFixed             : 'function string',\n            toJSON              : 'function',\n            toISOString         : 'function string',\n            toLocaleDateString  : 'function string',\n            toLocaleLowerCase   : 'function string',\n            toLocaleUpperCase   : 'function string',\n            toLocaleString      : 'function string',\n            toLocaleTimeString  : 'function string',\n            toLowerCase         : 'function string',\n            toPrecision         : 'function string',\n            toTimeString        : 'function string',\n            toUpperCase         : 'function string',\n            toUTCString         : 'function string',\n            trim                : 'function string',\n            unshift             : 'function number',\n            valueOf             : 'function'\n        },\n\n        strict_mode,\n        syntax = {},\n        tab,\n        token,\n//         type_state_change,\n        urls,\n        var_mode,\n        warnings,\n\n// widget contains the global names which are provided to a Yahoo\n// (fna Konfabulator) widget.\n\n        widget = array_to_object([\n            'alert', 'animator', 'appleScript', 'beep', 'bytesToUIString',\n            'Canvas', 'chooseColor', 'chooseFile', 'chooseFolder',\n            'closeWidget', 'COM', 'convertPathToHFS', 'convertPathToPlatform',\n            'CustomAnimation', 'escape', 'FadeAnimation', 'filesystem', 'Flash',\n            'focusWidget', 'form', 'FormField', 'Frame', 'HotKey', 'Image',\n            'include', 'isApplicationRunning', 'iTunes', 'konfabulatorVersion',\n            'log', 'md5', 'MenuItem', 'MoveAnimation', 'openURL', 'play',\n            'Point', 'popupMenu', 'preferenceGroups', 'preferences', 'print',\n            'prompt', 'random', 'Rectangle', 'reloadWidget', 'ResizeAnimation',\n            'resolvePath', 'resumeUpdates', 'RotateAnimation', 'runCommand',\n            'runCommandInBg', 'saveAs', 'savePreferences', 'screen',\n            'ScrollBar', 'showWidgetPreferences', 'sleep', 'speak', 'Style',\n            'suppressUpdates', 'system', 'tellWidget', 'Text', 'TextArea',\n            'Timer', 'unescape', 'updateNow', 'URL', 'Web', 'widget', 'Window',\n            'XMLDOM', 'XMLHttpRequest', 'yahooCheckLogin', 'yahooLogin',\n            'yahooLogout'\n        ], true),\n\n        windows = array_to_object([\n            'ActiveXObject', 'CScript', 'Debug', 'Enumerator', 'System',\n            'VBArray', 'WScript', 'WSH'\n        ], false),\n\n//  xmode is used to adapt to the exceptions in html parsing.\n//  It can have these states:\n//      ''      .js script file\n//      'html'\n//      'outer'\n//      'script'\n//      'style'\n//      'scriptstring'\n//      'styleproperty'\n\n        xmode,\n        xquote,\n\n// Regular expressions. Some of these are stupidly long.\n\n// unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i,\n// carriage return, or carriage return linefeed\n        crx = /\\r/g,\n        crlfx = /\\r\\n/g,\n// unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n// query characters for ids\n        dx = /[\\[\\]\\/\\\\\"'*<>.&:(){}+=#]/,\n// html token\n        hx = /^\\s*(['\"=>\\/&#]|<(?:\\/|\\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\\-:]*|[0-9]+|--)/,\n// identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,\n// javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i,\n// star slash\n        lx = /\\*\\/|\\/\\*/,\n// characters in strings that need escapement\n        nx = /[\\u0000-\\u001f'\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n// outer html token\n        ox = /[>&]|<[\\/!]?|--/,\n// attributes characters\n        qx = /[^a-zA-Z0-9+\\-_\\/ ]/,\n// style\n        sx = /^\\s*([{}:#%.=,>+\\[\\]@()\"';]|[*$\\^~]=|[a-zA-Z_][a-zA-Z0-9_\\-]*|[0-9]+|<\\/|\\/\\*)/,\n        ssx = /^\\s*([@#!\"'};:\\-%.=,+\\[\\]()*_]|[a-zA-Z][a-zA-Z0-9._\\-]*|\\/\\*?|\\d+(?:\\.\\d+)?|<\\/)/,\n// token\n        tx = /^\\s*([(){}\\[\\]\\?.,:;'\"~#@`]|={1,3}|\\/(\\*(jslint|properties|property|members?|globals?)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|[\\^%]=?|&[&=]?|\\|[|=]?|>{1,3}=?|<(?:[\\/=!]|\\!(\\[|--)?|<=?)?|\\!={0,2}|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\\.[0-9]*)?(?:[eE][+\\-]?[0-9]+)?)/,\n// url badness\n        ux = /&|\\+|\\u00AD|\\.\\.|\\/\\*|%[^;]|base64|url|expression|data|mailto|script/i,\n\n        rx = {\n            outer: hx,\n            html: hx,\n            style: sx,\n            styleproperty: ssx\n        };\n\n\n    function F() {}     // Used by Object.create\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.prototype.filter !== 'function') {\n        Array.prototype.filter = function (f) {\n            var i, length = this.length, result = [], value;\n            for (i = 0; i < length; i += 1) {\n                try {\n                    value = this[i];\n                    if (f(value)) {\n                        result.push(value);\n                    }\n                } catch (ignore) {\n                }\n            }\n            return result;\n        };\n    }\n\n    if (typeof Array.prototype.forEach !== 'function') {\n        Array.prototype.forEach = function (f) {\n            var i, length = this.length;\n            for (i = 0; i < length; i += 1) {\n                try {\n                    f(this[i]);\n                } catch (ignore) {\n                }\n            }\n        };\n    }\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (!Object.prototype.hasOwnProperty.call(Object, 'create')) {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var array = [], key;\n            for (key in o) {\n                if (Object.prototype.hasOwnProperty.call(o, key)) {\n                    array.push(key);\n                }\n            }\n            return array;\n        };\n    }\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var replacement = o[b];\n                return typeof replacement === 'string' ||\n                    typeof replacement === 'number' ? replacement : a;\n            });\n        };\n    }\n\n\n    function sanitize(a) {\n\n//  Escapify a troublesome character.\n\n        return escapes[a] ||\n            '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n    }\n\n\n    function add_to_predefined(group) {\n        Object.keys(group).forEach(function (name) {\n            predefined[name] = group[name];\n        });\n    }\n\n\n    function assume() {\n        if (!option.safe) {\n            if (option.rhino) {\n                add_to_predefined(rhino);\n                option.rhino = false;\n            }\n            if (option.devel) {\n                add_to_predefined(devel);\n                option.devel = false;\n            }\n            if (option.browser) {\n                add_to_predefined(browser);\n                option.browser = false;\n            }\n            if (option.windows) {\n                add_to_predefined(windows);\n                option.windows = false;\n            }\n            if (option.node) {\n                add_to_predefined(node);\n                option.node = false;\n                node_js = true;\n            }\n            if (option.widget) {\n                add_to_predefined(widget);\n                option.widget = false;\n            }\n        }\n        if (option.type) {\n            option.confusion = true;\n        }\n    }\n\n\n// Produce an error warning.\n\n    function artifact(tok) {\n        if (!tok) {\n            tok = next_token;\n        }\n        return tok.number || tok.string;\n    }\n\n    function quit(message, line, character) {\n        throw {\n            name: 'JSLintError',\n            line: line,\n            character: character,\n            message: bundle.scanned_a_b.supplant({\n                a: message,\n                b: Math.floor((line / lines.length) * 100)\n            })\n        };\n    }\n\n    function warn(message, offender, a, b, c, d) {\n        var character, line, warning;\n        offender = offender || next_token;  // `~\n        line = offender.line || 0;\n        character = offender.from || 0;\n        warning = {\n            id: '(error)',\n            raw: bundle[message] || message,\n            evidence: lines[line - 1] || '',\n            line: line,\n            character: character,\n            a: a || (offender.id === '(number)'\n                ? String(offender.number)\n                : offender.string),\n            b: b,\n            c: c,\n            d: d\n        };\n        warning.reason = warning.raw.supplant(warning);\n        JSLINT.errors.push(warning);\n        if (option.passfail) {\n            quit(bundle.stopping, line, character);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(bundle.too_many, line, character);\n        }\n        return warning;\n    }\n\n    function warn_at(message, line, character, a, b, c, d) {\n        return warn(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function stop(message, offender, a, b, c, d) {\n        var warning = warn(message, offender, a, b, c, d);\n        quit(bundle.stopping, warning.line, warning.character);\n    }\n\n    function stop_at(message, line, character, a, b, c, d) {\n        return stop(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function expected_at(at) {\n        if (!option.white && next_token.from !== at) {\n            warn('expected_a_at_b_c', next_token, '', at,\n                next_token.from);\n        }\n    }\n\n    function aint(it, name, expected) {\n        if (it[name] !== expected) {\n            warn('expected_a_b', it, expected, it[name]);\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n// lexical analysis and token construction\n\n    lex = (function lex() {\n        var character, c, from, length, line, pos, source_row;\n\n// Private lex methods\n\n        function next_line() {\n            var at;\n            if (line >= lines.length) {\n                return false;\n            }\n            character = 1;\n            source_row = lines[line];\n            line += 1;\n            at = source_row.search(/ \\t/);\n            if (at >= 0) {\n                warn_at('mixed', line, at + 1);\n            }\n            source_row = source_row.replace(/\\t/g, tab);\n            at = source_row.search(cx);\n            if (at >= 0) {\n                warn_at('unsafe', line, at);\n            }\n            if (option.maxlen && option.maxlen < source_row.length) {\n                warn_at('too_long', line, source_row.length);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var id, the_token;\n            if (type === '(string)' || type === '(range)') {\n                if (jx.test(value)) {\n                    warn_at('url', line, from);\n                }\n            }\n            the_token = Object.create(syntax[(\n                type === '(punctuator)' || (type === '(identifier)' &&\n                        Object.prototype.hasOwnProperty.call(syntax, value))\n                    ? value\n                    : type\n            )] || syntax['(error)']);\n            if (type === '(identifier)') {\n                the_token.identifier = true;\n                if (value === '__iterator__' || value === '__proto__') {\n                    stop_at('reserved_a', line, from, value);\n                } else if (!option.nomen &&\n                        (value.charAt(0) === '_' ||\n                        value.charAt(value.length - 1) === '_')) {\n                    warn_at('dangling_a', line, from, value);\n                }\n            }\n            if (type === '(number)') {\n                the_token.number = +value;\n            } else if (value !== undefined) {\n                the_token.string = String(value);\n            }\n            the_token.line = line;\n            the_token.from = from;\n            the_token.thru = character;\n            id = the_token.id;\n            prereg = id && (\n                ('(,=:[!&|?{};'.indexOf(id.charAt(id.length - 1)) >= 0) ||\n                id === 'return' || id === 'case'\n            );\n            return the_token;\n        }\n\n        function match(x) {\n            var exec = x.exec(source_row), first;\n            if (exec) {\n                length = exec[0].length;\n                first = exec[1];\n                c = first.charAt(0);\n                source_row = source_row.slice(length);\n                from = character + length - first.length;\n                character += length;\n                return first;\n            }\n        }\n\n        function string(x) {\n            var c, pos = 0, r = '', result;\n\n            function hex(n) {\n                var i = parseInt(source_row.substr(pos + 1, n), 16);\n                pos += n;\n                if (i >= 32 && i <= 126 &&\n                        i !== 34 && i !== 92 && i !== 39) {\n                    warn_at('unexpected_a', line, character, '\\\\');\n                }\n                character += n;\n                c = String.fromCharCode(i);\n            }\n\n            if (json_mode && x !== '\"') {\n                warn_at('expected_a', line, character, '\"');\n            }\n\n            if (xquote === x || (xmode === 'scriptstring' && !xquote)) {\n                return it('(punctuator)', x);\n            }\n\n            for (;;) {\n                while (pos >= source_row.length) {\n                    pos = 0;\n                    if (xmode !== 'html' || !next_line()) {\n                        stop_at('unclosed', line, from);\n                    }\n                }\n                c = source_row.charAt(pos);\n                if (c === x) {\n                    character += 1;\n                    source_row = source_row.slice(pos + 1);\n                    result = it('(string)', r);\n                    result.quote = x;\n                    return result;\n                }\n                if (c < ' ') {\n                    if (c === '\\n' || c === '\\r') {\n                        break;\n                    }\n                    warn_at('control_a', line, character + pos,\n                        source_row.slice(0, pos));\n                } else if (c === xquote) {\n                    warn_at('bad_html', line, character + pos);\n                } else if (c === '<') {\n                    if (option.safe && xmode === 'html') {\n                        warn_at('adsafe_a', line, character + pos, c);\n                    } else if (source_row.charAt(pos + 1) === '/' && (xmode || option.safe)) {\n                        warn_at('expected_a_b', line, character,\n                            '<\\\\/', '</');\n                    } else if (source_row.charAt(pos + 1) === '!' && (xmode || option.safe)) {\n                        warn_at('unexpected_a', line, character, '<!');\n                    }\n                } else if (c === '\\\\') {\n                    if (xmode === 'html') {\n                        if (option.safe) {\n                            warn_at('adsafe_a', line, character + pos, c);\n                        }\n                    } else if (xmode === 'styleproperty') {\n                        pos += 1;\n                        character += 1;\n                        c = source_row.charAt(pos);\n                        if (c !== x) {\n                            warn_at('unexpected_a', line, character, '\\\\');\n                        }\n                    } else {\n                        pos += 1;\n                        character += 1;\n                        c = source_row.charAt(pos);\n                        switch (c) {\n                        case '':\n                            if (!option.es5) {\n                                warn_at('es5', line, character);\n                            }\n                            next_line();\n                            pos = -1;\n                            break;\n                        case xquote:\n                            warn_at('bad_html', line, character + pos);\n                            break;\n                        case '\\'':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\\\'');\n                            }\n                            break;\n                        case 'u':\n                            hex(4);\n                            break;\n                        case 'v':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\v');\n                            }\n                            c = '\\v';\n                            break;\n                        case 'x':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\x');\n                            }\n                            hex(2);\n                            break;\n                        default:\n                            c = descapes[c];\n                            if (typeof c !== 'string') {\n                                warn_at('unexpected_a', line, character, '\\\\');\n                            }\n                        }\n                    }\n                }\n                r += c;\n                character += 1;\n                pos += 1;\n            }\n        }\n\n        function number(snippet) {\n            var digit;\n            if (xmode !== 'style' && xmode !== 'styleproperty' &&\n                    source_row.charAt(0).isAlpha()) {\n                warn_at('expected_space_a_b',\n                    line, character, c, source_row.charAt(0));\n            }\n            if (c === '0') {\n                digit = snippet.charAt(1);\n                if (digit.isDigit()) {\n                    if (token.id !== '.' && xmode !== 'styleproperty') {\n                        warn_at('unexpected_a', line, character, snippet);\n                    }\n                } else if (json_mode && (digit === 'x' || digit === 'X')) {\n                    warn_at('unexpected_a', line, character, '0x');\n                }\n            }\n            if (snippet.slice(snippet.length - 1) === '.') {\n                warn_at('trailing_decimal_a', line, character, snippet);\n            }\n            if (xmode !== 'style') {\n                digit = +snippet;\n                if (!isFinite(digit)) {\n                    warn_at('bad_number', line, character, snippet);\n                }\n                snippet = digit;\n            }\n            return it('(number)', snippet);\n        }\n\n        function comment(snippet) {\n            if (comments_off || src || (xmode && xmode !== 'script' &&\n                    xmode !== 'style' && xmode !== 'styleproperty')) {\n                warn_at('unexpected_comment', line, character);\n            } else if (xmode === 'script' && /<\\//i.test(source_row)) {\n                warn_at('unexpected_a', line, character, '<\\/');\n            } else if (option.safe && ax.test(snippet)) {\n                warn_at('dangerous_comment', line, character);\n            }\n        }\n\n        function regexp() {\n            var b,\n                bit,\n                captures = 0,\n                depth = 0,\n                flag = '',\n                high,\n                letter,\n                length = 0,\n                low,\n                potential,\n                quote,\n                result;\n            for (;;) {\n                b = true;\n                c = source_row.charAt(length);\n                length += 1;\n                switch (c) {\n                case '':\n                    stop_at('unclosed_regexp', line, from);\n                    return;\n                case '/':\n                    if (depth > 0) {\n                        warn_at('unescaped_a', line, from + length, '/');\n                    }\n                    c = source_row.slice(0, length - 1);\n                    potential = Object.create(regexp_flag);\n                    for (;;) {\n                        letter = source_row.charAt(length);\n                        if (potential[letter] !== true) {\n                            break;\n                        }\n                        potential[letter] = false;\n                        length += 1;\n                        flag += letter;\n                    }\n                    if (source_row.charAt(length).isAlpha()) {\n                        stop_at('unexpected_a', line, from, source_row.charAt(length));\n                    }\n                    character += length;\n                    source_row = source_row.slice(length);\n                    quote = source_row.charAt(0);\n                    if (quote === '/' || quote === '*') {\n                        stop_at('confusing_regexp', line, from);\n                    }\n                    result = it('(regexp)', c);\n                    result.flag = flag;\n                    return result;\n                case '\\\\':\n                    c = source_row.charAt(length);\n                    if (c < ' ') {\n                        warn_at('control_a', line, from + length, String(c));\n                    } else if (c === '<') {\n                        warn_at(bundle.unexpected_a, line, from + length, '\\\\');\n                    }\n                    length += 1;\n                    break;\n                case '(':\n                    depth += 1;\n                    b = false;\n                    if (source_row.charAt(length) === '?') {\n                        length += 1;\n                        switch (source_row.charAt(length)) {\n                        case ':':\n                        case '=':\n                        case '!':\n                            length += 1;\n                            break;\n                        default:\n                            warn_at(bundle.expected_a_b, line, from + length,\n                                ':', source_row.charAt(length));\n                        }\n                    } else {\n                        captures += 1;\n                    }\n                    break;\n                case '|':\n                    b = false;\n                    break;\n                case ')':\n                    if (depth === 0) {\n                        warn_at('unescaped_a', line, from + length, ')');\n                    } else {\n                        depth -= 1;\n                    }\n                    break;\n                case ' ':\n                    pos = 1;\n                    while (source_row.charAt(length) === ' ') {\n                        length += 1;\n                        pos += 1;\n                    }\n                    if (pos > 1) {\n                        warn_at('use_braces', line, from + length, pos);\n                    }\n                    break;\n                case '[':\n                    c = source_row.charAt(length);\n                    if (c === '^') {\n                        length += 1;\n                        if (!option.regexp) {\n                            warn_at('insecure_a', line, from + length, c);\n                        } else if (source_row.charAt(length) === ']') {\n                            stop_at('unescaped_a', line, from + length, '^');\n                        }\n                    }\n                    bit = false;\n                    if (c === ']') {\n                        warn_at('empty_class', line, from + length - 1);\n                        bit = true;\n                    }\nklass:              do {\n                        c = source_row.charAt(length);\n                        length += 1;\n                        switch (c) {\n                        case '[':\n                        case '^':\n                            warn_at('unescaped_a', line, from + length, c);\n                            bit = true;\n                            break;\n                        case '-':\n                            if (bit) {\n                                bit = false;\n                            } else {\n                                warn_at('unescaped_a', line, from + length, '-');\n                                bit = true;\n                            }\n                            break;\n                        case ']':\n                            if (!bit) {\n                                warn_at('unescaped_a', line, from + length - 1, '-');\n                            }\n                            break klass;\n                        case '\\\\':\n                            c = source_row.charAt(length);\n                            if (c < ' ') {\n                                warn_at(bundle.control_a, line, from + length, String(c));\n                            } else if (c === '<') {\n                                warn_at(bundle.unexpected_a, line, from + length, '\\\\');\n                            }\n                            length += 1;\n                            bit = true;\n                            break;\n                        case '/':\n                            warn_at('unescaped_a', line, from + length - 1, '/');\n                            bit = true;\n                            break;\n                        case '<':\n                            if (xmode === 'script') {\n                                c = source_row.charAt(length);\n                                if (c === '!' || c === '/') {\n                                    warn_at(bundle.html_confusion_a, line,\n                                        from + length, c);\n                                }\n                            }\n                            bit = true;\n                            break;\n                        default:\n                            bit = true;\n                        }\n                    } while (c);\n                    break;\n                case '.':\n                    if (!option.regexp) {\n                        warn_at('insecure_a', line, from + length, c);\n                    }\n                    break;\n                case ']':\n                case '?':\n                case '{':\n                case '}':\n                case '+':\n                case '*':\n                    warn_at('unescaped_a', line, from + length, c);\n                    break;\n                case '<':\n                    if (xmode === 'script') {\n                        c = source_row.charAt(length);\n                        if (c === '!' || c === '/') {\n                            warn_at(bundle.html_confusion_a, line, from + length, c);\n                        }\n                    }\n                    break;\n                }\n                if (b) {\n                    switch (source_row.charAt(length)) {\n                    case '?':\n                    case '+':\n                    case '*':\n                        length += 1;\n                        if (source_row.charAt(length) === '?') {\n                            length += 1;\n                        }\n                        break;\n                    case '{':\n                        length += 1;\n                        c = source_row.charAt(length);\n                        if (c < '0' || c > '9') {\n                            warn_at(bundle.expected_number_a, line,\n                                from + length, c);\n                        }\n                        length += 1;\n                        low = +c;\n                        for (;;) {\n                            c = source_row.charAt(length);\n                            if (c < '0' || c > '9') {\n                                break;\n                            }\n                            length += 1;\n                            low = +c + (low * 10);\n                        }\n                        high = low;\n                        if (c === ',') {\n                            length += 1;\n                            high = Infinity;\n                            c = source_row.charAt(length);\n                            if (c >= '0' && c <= '9') {\n                                length += 1;\n                                high = +c;\n                                for (;;) {\n                                    c = source_row.charAt(length);\n                                    if (c < '0' || c > '9') {\n                                        break;\n                                    }\n                                    length += 1;\n                                    high = +c + (high * 10);\n                                }\n                            }\n                        }\n                        if (source_row.charAt(length) !== '}') {\n                            warn_at(bundle.expected_a_b, line, from + length,\n                                '}', c);\n                        } else {\n                            length += 1;\n                        }\n                        if (source_row.charAt(length) === '?') {\n                            length += 1;\n                        }\n                        if (low > high) {\n                            warn_at(bundle.not_greater, line, from + length,\n                                low, high);\n                        }\n                        break;\n                    }\n                }\n            }\n            c = source_row.slice(0, length - 1);\n            character += length;\n            source_row = source_row.slice(length);\n            return it('(regexp)', c);\n        }\n\n// Public lex methods\n\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source\n                        .replace(crlfx, '\\n')\n                        .replace(crx, '\\n')\n                        .split('\\n');\n                } else {\n                    lines = source;\n                }\n                line = 0;\n                next_line();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (source_row.charAt(0) !== begin) {\n                    stop_at('expected_a_b', line, character, begin,\n                        source_row.charAt(0));\n                }\n                for (;;) {\n                    source_row = source_row.slice(1);\n                    character += 1;\n                    c = source_row.charAt(0);\n                    switch (c) {\n                    case '':\n                        stop_at('missing_a', line, character, c);\n                        break;\n                    case end:\n                        source_row = source_row.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case xquote:\n                    case '\\\\':\n                        warn_at('unexpected_a', line, character, c);\n                        break;\n                    }\n                    value += c;\n                }\n            },\n\n// token -- this is called by advance to get the next token.\n\n            token: function () {\n                var c, i, snippet;\n\n                for (;;) {\n                    while (!source_row) {\n                        if (!next_line()) {\n                            return it('(end)');\n                        }\n                    }\n                    while (xmode === 'outer') {\n                        i = source_row.search(ox);\n                        if (i === 0) {\n                            break;\n                        } else if (i > 0) {\n                            character += 1;\n                            source_row = source_row.slice(i);\n                            break;\n                        } else {\n                            if (!next_line()) {\n                                return it('(end)', '');\n                            }\n                        }\n                    }\n                    snippet = match(rx[xmode] || tx);\n                    if (!snippet) {\n                        if (source_row) {\n                            if (source_row.charAt(0) === ' ') {\n                                if (!option.white) {\n                                    warn_at('unexpected_a', line, character,\n                                        '(space)');\n                                }\n                                character += 1;\n                                source_row = '';\n                            } else {\n                                stop_at('unexpected_a', line, character,\n                                    source_row.charAt(0));\n                            }\n                        }\n                    } else {\n\n//      identifier\n\n                        c = snippet.charAt(0);\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', snippet);\n                        }\n\n//      number\n\n                        if (c.isDigit()) {\n                            return number(snippet);\n                        }\n                        switch (snippet) {\n\n//      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(snippet);\n\n//      // comment\n\n                        case '//':\n                            comment(source_row);\n                            source_row = '';\n                            break;\n\n//      /* comment\n\n                        case '/*':\n                            for (;;) {\n                                i = source_row.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                comment(source_row);\n                                if (!next_line()) {\n                                    stop_at('unclosed_comment', line, character);\n                                }\n                            }\n                            comment(source_row.slice(0, i));\n                            character += i + 2;\n                            if (source_row.charAt(i) === '/') {\n                                stop_at('nested_comment', line, character);\n                            }\n                            source_row = source_row.slice(i + 2);\n                            break;\n\n                        case '':\n                            break;\n//      /\n                        case '/':\n                            if (token.id === '/=') {\n                                stop_at(\n                                    bundle.slash_equal,\n                                    line,\n                                    from\n                                );\n                            }\n                            return prereg\n                                ? regexp()\n                                : it('(punctuator)', snippet);\n\n//      punctuator\n\n                        case '<!--':\n                            length = line;\n//                            c = character;\n                            for (;;) {\n                                i = source_row.indexOf('--');\n                                if (i >= 0) {\n                                    break;\n                                }\n                                i = source_row.indexOf('<!');\n                                if (i >= 0) {\n                                    stop_at('nested_comment',\n                                        line, character + i);\n                                }\n                                if (!next_line()) {\n                                    stop_at('unclosed_comment', length, c);\n                                }\n                            }\n                            length = source_row.indexOf('<!');\n                            if (length >= 0 && length < i) {\n                                stop_at('nested_comment',\n                                    line, character + length);\n                            }\n                            character += i;\n                            if (source_row.charAt(i + 2) !== '>') {\n                                stop_at('expected_a', line, character, '-->');\n                            }\n                            character += 3;\n                            source_row = source_row.slice(i + 3);\n                            break;\n                        case '#':\n                            if (xmode === 'html' || xmode === 'styleproperty') {\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    if ((c < '0' || c > '9') &&\n                                            (c < 'a' || c > 'f') &&\n                                            (c < 'A' || c > 'F')) {\n                                        break;\n                                    }\n                                    character += 1;\n                                    source_row = source_row.slice(1);\n                                    snippet += c;\n                                }\n                                if (snippet.length !== 4 && snippet.length !== 7) {\n                                    warn_at('bad_color_a', line,\n                                        from + length, snippet);\n                                }\n                                return it('(color)', snippet);\n                            }\n                            return it('(punctuator)', snippet);\n\n                        default:\n                            if (xmode === 'outer' && c === '&') {\n                                character += 1;\n                                source_row = source_row.slice(1);\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    character += 1;\n                                    source_row = source_row.slice(1);\n                                    if (c === ';') {\n                                        break;\n                                    }\n                                    if (!((c >= '0' && c <= '9') ||\n                                            (c >= 'a' && c <= 'z') ||\n                                            c === '#')) {\n                                        stop_at('bad_entity', line, from + length,\n                                            character);\n                                    }\n                                }\n                                break;\n                            }\n                            return it('(punctuator)', snippet);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function add_label(token, kind, name) {\n\n// Define the symbol in the current function in the current scope.\n\n        name = name || token.string;\n\n// Global variables cannot be created in the safe subset. If a global variable\n// already exists, do nothing. If it is predefined, define it.\n\n        if (funct === global_funct) {\n            if (option.safe) {\n                warn('adsafe_a', token, name);\n            }\n            if (typeof global_funct[name] !== 'string') {\n                token.writeable = typeof predefined[name] === 'boolean'\n                    ? predefined[name]\n                    : true;\n                token.funct = funct;\n                global_scope[name] = token;\n            }\n            if (kind === 'becoming') {\n                kind = 'var';\n            }\n\n// Ordinary variables.\n\n        } else {\n\n// Warn if the variable already exists.\n\n            if (typeof funct[name] === 'string') {\n                if (funct[name] === 'undef') {\n                    if (!option.undef) {\n                        warn('used_before_a', token, name);\n                    }\n                    kind = 'var';\n                } else {\n                    warn('already_defined', token, name);\n                }\n            } else {\n\n// Add the symbol to the current function.\n\n                token.funct = funct;\n                token.writeable = true;\n                scope[name] = token;\n            }\n        }\n        funct[name] = kind;\n    }\n\n\n    function peek(distance) {\n\n// Peek ahead to a future token. The distance is how far ahead to look. The\n// default is the next token.\n\n        var found, slot = 0;\n\n        distance = distance || 0;\n        while (slot <= distance) {\n            found = lookahead[slot];\n            if (!found) {\n                found = lookahead[slot] = lex.token();\n            }\n            slot += 1;\n        }\n        return found;\n    }\n\n\n    function advance(id, match) {\n\n// Produce the next token, also looking for programming errors.\n\n        if (indent) {\n\n// If indentation checking was requested, then inspect all of the line breakings.\n// The var statement is tricky because the names might be aligned or not. We\n// look at the first line break after the var to determine the programmer's\n// intention.\n\n            if (var_mode && next_token.line !== token.line) {\n                if ((var_mode !== indent || !next_token.edge) &&\n                        next_token.from === indent.at -\n                        (next_token.edge ? option.indent : 0)) {\n                    var dent = indent;\n                    for (;;) {\n                        dent.at -= option.indent;\n                        if (dent === var_mode) {\n                            break;\n                        }\n                        dent = dent.was;\n                    }\n                    dent.open = false;\n                }\n                var_mode = null;\n            }\n            if (next_token.id === '?' && indent.mode === ':' &&\n                    token.line !== next_token.line) {\n                indent.at -= option.indent;\n            }\n            if (indent.open) {\n\n// If the token is an edge.\n\n                if (next_token.edge) {\n                    if (next_token.edge === 'label') {\n                        expected_at(1);\n                    } else if (next_token.edge === 'case' || indent.mode === 'statement') {\n                        expected_at(indent.at - option.indent);\n                    } else if (indent.mode !== 'array' || next_token.line !== token.line) {\n                        expected_at(indent.at);\n                    }\n\n// If the token is not an edge, but is the first token on the line.\n\n                } else if (next_token.line !== token.line) {\n                    if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                    indent.wrap = true;\n                }\n            } else if (next_token.line !== token.line) {\n                if (next_token.edge) {\n                    expected_at(indent.at);\n                } else {\n                    indent.wrap = true;\n                    if (indent.mode === 'statement' || indent.mode === 'var') {\n                        expected_at(indent.at + option.indent);\n                    } else if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                }\n            }\n        }\n\n        switch (token.id) {\n        case '(number)':\n            if (next_token.id === '.') {\n                warn('trailing_decimal_a');\n            }\n            break;\n        case '-':\n            if (next_token.id === '-' || next_token.id === '--') {\n                warn('confusing_a');\n            }\n            break;\n        case '+':\n            if (next_token.id === '+' || next_token.id === '++') {\n                warn('confusing_a');\n            }\n            break;\n        }\n        if (token.id === '(string)' || token.identifier) {\n            anonname = token.string;\n        }\n\n        if (id && next_token.id !== id) {\n            if (match) {\n                warn('expected_a_b_from_c_d', next_token, id,\n                    match.id, match.line, artifact());\n            } else if (!next_token.identifier || next_token.string !== id) {\n                warn('expected_a_b', next_token, id, artifact());\n            }\n        }\n        prev_token = token;\n        token = next_token;\n        next_token = lookahead.shift() || lex.token();\n    }\n\n\n    function advance_identifier(string) {\n        if (next_token.identifier && next_token.string === string) {\n            advance();\n        } else {\n            warn('expected_a_b', next_token, string, artifact());\n        }\n    }\n\n\n    function do_safe() {\n        if (option.adsafe) {\n            option.safe = true;\n        }\n        if (option.safe) {\n            option.browser     =\n                option['continue'] =\n                option.css     =\n                option.debug   =\n                option.devel   =\n                option.evil    =\n                option.forin   =\n                option.newcap  =\n                option.nomen   =\n                option.on      =\n                option.rhino   =\n                option.sloppy  =\n                option.sub     =\n                option.undef   =\n                option.widget  =\n                option.windows = false;\n\n\n            delete predefined.Array;\n            delete predefined.Date;\n            delete predefined.Function;\n            delete predefined.Object;\n            delete predefined['eval'];\n\n            add_to_predefined({\n                ADSAFE: false,\n                lib: false\n            });\n        }\n    }\n\n\n    function do_globals() {\n        var name, writeable;\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            advance();\n            writeable = false;\n            if (next_token.id === ':') {\n                advance(':');\n                switch (next_token.id) {\n                case 'true':\n                    writeable = predefined[name] !== false;\n                    advance('true');\n                    break;\n                case 'false':\n                    advance('false');\n                    break;\n                default:\n                    stop('unexpected_a');\n                }\n            }\n            predefined[name] = writeable;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    function do_jslint() {\n        var name, value;\n        while (next_token.id === '(string)' || next_token.identifier) {\n            name = next_token.string;\n            if (!allowed_option[name]) {\n                stop('unexpected_a');\n            }\n            advance();\n            if (next_token.id !== ':') {\n                stop('expected_a_b', next_token, ':', artifact());\n            }\n            advance(':');\n            if (typeof allowed_option[name] === 'number') {\n                value = next_token.number;\n                if (value > allowed_option[name] || value <= 0 ||\n                        Math.floor(value) !== value) {\n                    stop('expected_small_a');\n                }\n                option[name] = value;\n            } else {\n                if (next_token.id === 'true') {\n                    option[name] = true;\n                } else if (next_token.id === 'false') {\n                    option[name] = false;\n                } else {\n                    stop('unexpected_a');\n                }\n            }\n            advance();\n            if (next_token.id === ',') {\n                advance(',');\n            }\n        }\n        assume();\n    }\n\n\n    function do_properties() {\n        var name, type;\n        option.properties = true;\n        if (!funct['(old_property_type)']) {\n            funct['(old_property_type)'] = property_type;\n            property_type = Object.create(property_type);\n        }\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            type = '';\n            advance();\n            if (next_token.id === ':') {\n                advance(':');\n                if (next_token.id === 'function') {\n                    advance('function');\n                    if (is_type[next_token.string] === true) {\n                        type = 'function ' + next_token.string;\n                        advance();\n                    } else {\n                        type = 'function';\n                    }\n                } else {\n                    type = next_token.string;\n                    if (is_type[type] !== true) {\n                        warn('expected_type_a', next_token);\n                        type = '';\n                    }\n                    advance();\n                }\n            }\n            property_type[name] = type;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    directive = function directive() {\n        var command = this.id,\n            old_comments_off = comments_off,\n            old_indent = indent;\n        comments_off = true;\n        indent = null;\n        if (next_token.line === token.line && next_token.from === token.thru) {\n            warn('missing_space_a_b', next_token, artifact(token), artifact());\n        }\n        if (lookahead.length > 0) {\n            warn('unexpected_a', this);\n        }\n        switch (command) {\n        case '/*properties':\n        case '/*property':\n        case '/*members':\n        case '/*member':\n            do_properties();\n            break;\n        case '/*jslint':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            do_jslint();\n            break;\n        case '/*globals':\n        case '/*global':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            do_globals();\n            break;\n        default:\n            stop('unexpected_a', this);\n        }\n        comments_off = old_comments_off;\n        advance('*/');\n        indent = old_indent;\n    };\n\n\n// Indentation intention\n\n    function edge(mode) {\n        next_token.edge = indent ? indent.open && (mode || 'edge') : '';\n    }\n\n\n    function step_in(mode) {\n        var open;\n        if (typeof mode === 'number') {\n            indent = {\n                at: +mode,\n                open: true,\n                was: indent\n            };\n        } else if (mode === 'statement') {\n            indent = {\n                at: indent.at,\n                open: true,\n                was: indent\n            };\n        } else if (!indent) {\n            indent = {\n                at: 1,\n                mode: 'statement',\n                open: true\n            };\n        } else {\n            open = mode === 'var' || next_token.line !== token.line;\n            indent = {\n                at: (open || mode === 'control'\n                    ? indent.at + option.indent\n                    : indent.at) + (indent.wrap ? option.indent : 0),\n                mode: mode,\n                open: open,\n                was: indent\n            };\n            if (mode === 'var' && open) {\n                var_mode = indent;\n            }\n        }\n    }\n\n    function step_out(id, symbol) {\n        if (id) {\n            if (indent && indent.open) {\n                indent.at -= option.indent;\n                edge();\n            }\n            advance(id, symbol);\n        }\n        if (indent) {\n            indent = indent.was;\n        }\n    }\n\n// Functions for conformance of whitespace.\n\n    function one_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && !option.white &&\n                (token.line !== right.line ||\n                token.thru + 1 !== right.from)) {\n            warn('expected_space_a_b', right, artifact(token), artifact(right));\n        }\n    }\n\n    function one_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru + 1 !== right.from))) {\n            warn('expected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function no_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if ((!option.white || xmode === 'styleproperty' || xmode === 'style') &&\n                left.thru !== right.from && left.line === right.line) {\n            warn('unexpected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function no_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru !== right.from))) {\n            warn('unexpected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function spaces(left, right) {\n        if (!option.white) {\n            left = left || token;\n            right = right || next_token;\n            if (left.thru === right.from && left.line === right.line) {\n                warn('missing_space_a_b', right, artifact(left), artifact(right));\n            }\n        }\n    }\n\n    function comma() {\n        if (next_token.id !== ',') {\n            warn_at('expected_a_b', token.line, token.thru, ',', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(',');\n            spaces();\n        }\n    }\n\n\n    function semicolon() {\n        if (next_token.id !== ';') {\n            warn_at('expected_a_b', token.line, token.thru, ';', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(';');\n            if (semicolon_coda[next_token.id] !== true) {\n                spaces();\n            }\n        }\n    }\n\n    function use_strict() {\n        if (next_token.string === 'use strict') {\n            if (strict_mode) {\n                warn('unnecessary_use');\n            }\n            edge();\n            advance();\n            semicolon();\n            strict_mode = true;\n            option.newcap = false;\n            option.undef = false;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n    function are_similar(a, b) {\n        if (a === b) {\n            return true;\n        }\n        if (Array.isArray(a)) {\n            if (Array.isArray(b) && a.length === b.length) {\n                var i;\n                for (i = 0; i < a.length; i += 1) {\n                    if (!are_similar(a[i], b[i])) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n            return false;\n        }\n        if (Array.isArray(b)) {\n            return false;\n        }\n        if (a.id === '(number)' && b.id === '(number)') {\n            return a.number === b.number;\n        }\n        if (a.arity === b.arity && a.string === b.string) {\n            switch (a.arity) {\n            case 'prefix':\n            case 'suffix':\n            case undefined:\n                return a.id === b.id && are_similar(a.first, b.first);\n            case 'infix':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second);\n            case 'ternary':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second) &&\n                    are_similar(a.third, b.third);\n            case 'function':\n            case 'regexp':\n                return false;\n            default:\n                return true;\n            }\n        } else {\n            if (a.id === '.' && b.id === '[' && b.arity === 'infix') {\n                return a.second.string === b.second.string && b.second.id === '(string)';\n            } else if (a.id === '[' && a.arity === 'infix' && b.id === '.') {\n                return a.second.string === b.second.string && a.second.id === '(string)';\n            }\n        }\n        return false;\n    }\n\n\n// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n\n// rbp is the right binding power.\n// initial indicates that this is the first expression of a statement.\n\n        var left;\n        if (next_token.id === '(end)') {\n            stop('unexpected_a', token, next_token.id);\n        }\n        advance();\n        if (option.safe && scope[token.string] &&\n                scope[token.string] === global_scope[token.string] &&\n                (next_token.id !== '(' && next_token.id !== '.')) {\n            warn('adsafe_a', token);\n        }\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.string;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (next_token.id === '(number)' && token.id === '.') {\n                    warn('leading_decimal_a', token, artifact());\n                    advance();\n                    return token;\n                } else {\n                    stop('expected_identifier_a', token, token.id);\n                }\n            }\n            while (rbp < next_token.lbp) {\n                advance();\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    stop('expected_operator_a', token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p || 0,\n                string: s\n            };\n        }\n        return x;\n    }\n\n    function postscript(x) {\n        x.postscript = true;\n        return x;\n    }\n\n    function ultimate(s) {\n        var x = symbol(s, 0);\n        x.from = 1;\n        x.thru = 1;\n        x.line = 0;\n        x.edge = 'edge';\n        s.string = s;\n        return postscript(x);\n    }\n\n\n    function stmt(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n    function labeled_stmt(s, f) {\n        var x = stmt(s, f);\n        x.labeled = true;\n    }\n\n    function disrupt_stmt(s, f) {\n        var x = stmt(s, f);\n        x.disrupt = true;\n    }\n\n\n    function reserve_name(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f, type) {\n        var x = symbol(s, 150);\n        reserve_name(x);\n        x.nud = typeof f === 'function'\n            ? f\n            : function () {\n                if (s === 'typeof') {\n                    one_space();\n                } else {\n                    no_space_only();\n                }\n                this.first = expression(150);\n                this.arity = 'prefix';\n                if (this.id === '++' || this.id === '--') {\n                    if (!option.plusplus) {\n                        warn('unexpected_a', this);\n                    } else if ((!this.first.identifier || this.first.reserved) &&\n                            this.first.id !== '.' && this.first.id !== '[') {\n                        warn('bad_operand', this);\n                    }\n                }\n                this.type = type;\n                return this;\n            };\n        return x;\n    }\n\n\n    function type(s, t, nud) {\n        var x = symbol(s);\n        x.arity = x.type = t;\n        if (nud) {\n            x.nud = nud;\n        }\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        if (typeof f === 'function') {\n            x.nud = f;\n        }\n        return x;\n    }\n\n\n    function constant(name, type) {\n        var x = reserve(name);\n        x.type = type;\n        x.string = name;\n        x.nud = return_this;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, p, f, type, w) {\n        var x = symbol(s, p);\n        reserve_name(x);\n        x.led = function (left) {\n            this.arity = 'infix';\n            if (!w) {\n                spaces(prev_token, token);\n                spaces();\n            }\n            if (!option.bitwise && this.bitwise) {\n                warn('unexpected_a', this);\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            } else {\n                this.first = left;\n                this.second = expression(p);\n                return this;\n            }\n        };\n        if (type) {\n            x.type = type;\n        }\n        return x;\n    }\n\n    function expected_relation(node, message) {\n        if (node.assign) {\n            warn(message || bundle.conditional_assignment, node);\n        }\n        return node;\n    }\n\n    function expected_condition(node, message) {\n        switch (node.id) {\n        case '[':\n        case '-':\n            if (node.arity !== 'infix') {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        case 'false':\n        case 'function':\n        case 'Infinity':\n        case 'NaN':\n        case 'null':\n        case 'true':\n        case 'undefined':\n        case 'void':\n        case '(number)':\n        case '(regexp)':\n        case '(string)':\n        case '{':\n            warn(message || bundle.weird_condition, node);\n            break;\n        case '(':\n            if (node.first.id === '.' && numbery[node.first.second.string] === true) {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        }\n        return node;\n    }\n\n    function check_relation(node) {\n        switch (node.arity) {\n        case 'prefix':\n            switch (node.id) {\n            case '{':\n            case '[':\n                warn('unexpected_a', node);\n                break;\n            case '!':\n                warn('confusing_a', node);\n                break;\n            }\n            break;\n        case 'function':\n        case 'regexp':\n            warn('unexpected_a', node);\n            break;\n        default:\n            if (node.id  === 'NaN') {\n                warn('isnan', node);\n            }\n        }\n        return node;\n    }\n\n\n    function relation(s, eqeq) {\n        return infix(s, 100, function (left, that) {\n            check_relation(left);\n            if (eqeq && !option.eqeq) {\n                warn('expected_a_b', that, eqeq, that.id);\n            }\n            var right = expression(100);\n            if (are_similar(left, right) ||\n                    ((left.id === '(string)' || left.id === '(number)') &&\n                    (right.id === '(string)' || right.id === '(number)'))) {\n                warn('weird_relation', that);\n            }\n            that.first = left;\n            that.second = check_relation(right);\n            return that;\n        }, 'boolean');\n    }\n\n\n    function assignop(s, op) {\n        var x = infix(s, 20, function (left, that) {\n            var l;\n            that.first = left;\n            if (left.identifier) {\n                if (scope[left.string]) {\n                    if (scope[left.string].writeable === false) {\n                        warn('read_only', left);\n                    }\n                } else {\n                    stop('read_only');\n                }\n            } else if (option.safe) {\n                l = left;\n                do {\n                    if (typeof predefined[l.string] === 'boolean') {\n                        warn('adsafe_a', l);\n                    }\n                    l = l.first;\n                } while (l);\n            }\n            if (left === syntax['function']) {\n                warn('identifier_function', token);\n            }\n            if (left.id === '.' || left.id === '[') {\n                if (!left.first || left.first.string === 'arguments') {\n                    warn('bad_assignment', that);\n                }\n            } else if (left.identifier) {\n                if (!left.reserved && funct[left.string] === 'exception') {\n                    warn('assign_exception', left);\n                }\n            } else {\n                warn('bad_assignment', that);\n            }\n            that.second = expression(19);\n            if (that.id === '=' && are_similar(that.first, that.second)) {\n                warn('weird_assignment', that);\n            }\n            return that;\n        });\n        x.assign = true;\n        if (op) {\n            if (syntax[op].type) {\n                x.type = syntax[op].type;\n            }\n            if (syntax[op].bitwise) {\n                x.bitwise = true;\n            }\n        }\n        return x;\n    }\n\n\n    function bitwise(s, p) {\n        var x = infix(s, p, 'number');\n        x.bitwise = true;\n        return x;\n    }\n\n\n    function suffix(s) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            no_space_only(prev_token, token);\n            if (!option.plusplus) {\n                warn('unexpected_a', this);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warn('bad_operand', this);\n            }\n            this.first = left;\n            this.arity = 'suffix';\n            return this;\n        };\n        return x;\n    }\n\n\n    function optional_identifier() {\n        if (next_token.identifier) {\n            advance();\n            if (option.safe && banned[token.string]) {\n                warn('adsafe_a', token);\n            } else if (token.reserved && !option.es5) {\n                warn('expected_identifier_a_reserved', token);\n            }\n            return token.string;\n        }\n    }\n\n\n    function identifier() {\n        var i = optional_identifier();\n        if (!i) {\n            stop(token.id === 'function' && next_token.id === '('\n                ? 'name_function'\n                : 'expected_identifier_a');\n        }\n        return i;\n    }\n\n\n    function statement() {\n\n        var label, old_scope = scope, the_statement;\n\n// We don't like the empty statement.\n\n        if (next_token.id === ';') {\n            warn('unexpected_a');\n            semicolon();\n            return;\n        }\n\n// Is this a labeled statement?\n\n        if (next_token.identifier && !next_token.reserved && peek().id === ':') {\n            edge('label');\n            label = next_token;\n            advance();\n            advance(':');\n            scope = Object.create(old_scope);\n            add_label(label, 'label');\n            if (next_token.labeled !== true) {\n                warn('label_a_b', next_token, label.string, artifact());\n            } else if (jx.test(label.string + ':')) {\n                warn('url', label);\n            } else if (funct === global_funct) {\n                stop('unexpected_a', token);\n            }\n            next_token.label = label;\n        }\n\n// Parse the statement.\n\n        if (token.id !== 'else') {\n            edge();\n        }\n        step_in('statement');\n        the_statement = expression(0, true);\n        if (the_statement) {\n\n// Look for the final semicolon.\n\n            if (the_statement.arity === 'statement') {\n                if (the_statement.id === 'switch' ||\n                        (the_statement.block && the_statement.id !== 'do')) {\n                    spaces();\n                } else {\n                    semicolon();\n                }\n            } else {\n\n// If this is an expression statement, determine if it is acceptable.\n// We do not like\n//      new Blah();\n// statments. If it is to be used at all, new should only be used to make\n// objects, not side effects. The expression statements we do like do\n// assignment or invocation or delete.\n\n                if (the_statement.id === '(') {\n                    if (the_statement.first.id === 'new') {\n                        warn('bad_new');\n                    }\n                } else if (!the_statement.assign &&\n                        the_statement.id !== 'delete' &&\n                        the_statement.id !== '++' &&\n                        the_statement.id !== '--') {\n                    warn('assignment_function_expression', token);\n                }\n                semicolon();\n            }\n        }\n        step_out();\n        scope = old_scope;\n        return the_statement;\n    }\n\n\n    function statements() {\n        var array = [], disruptor, the_statement;\n\n// A disrupt statement may not be followed by any other statement.\n// If the last statement is disrupt, then the sequence is disrupt.\n\n        while (next_token.postscript !== true) {\n            if (next_token.id === ';') {\n                warn('unexpected_a', next_token);\n                semicolon();\n            } else {\n                if (next_token.string === 'use strict') {\n                    if ((!node_js && xmode !== 'script') || funct !== global_funct || array.length > 0) {\n                        warn('function_strict');\n                    }\n                    use_strict();\n                }\n                if (disruptor) {\n                    warn('unreachable_a_b', next_token, next_token.string,\n                        disruptor.string);\n                    disruptor = null;\n                }\n                the_statement = statement();\n                if (the_statement) {\n                    array.push(the_statement);\n                    if (the_statement.disrupt) {\n                        disruptor = the_statement;\n                        array.disrupt = true;\n                    }\n                }\n            }\n        }\n        return array;\n    }\n\n\n    function block(ordinary) {\n\n// array block is array sequence of statements wrapped in braces.\n// ordinary is false for function bodies and try blocks.\n// ordinary is true for if statements, while, etc.\n\n        var array,\n            curly = next_token,\n            old_in_block = in_block,\n            old_scope = scope,\n            old_strict_mode = strict_mode;\n\n        in_block = ordinary;\n        scope = Object.create(scope);\n        spaces();\n        if (next_token.id === '{') {\n            advance('{');\n            step_in();\n            if (!ordinary && !use_strict() && !old_strict_mode &&\n                    !option.sloppy && funct['(context)'] === global_funct) {\n                warn('missing_use_strict');\n            }\n            array = statements();\n            strict_mode = old_strict_mode;\n            step_out('}', curly);\n        } else if (!ordinary) {\n            stop('expected_a_b', next_token, '{', artifact());\n        } else {\n            warn('expected_a_b', next_token, '{', artifact());\n            array = [statement()];\n            array.disrupt = array[0].disrupt;\n        }\n        funct['(verb)'] = null;\n        scope = old_scope;\n        in_block = old_in_block;\n        if (ordinary && array.length === 0) {\n            warn('empty_block');\n        }\n        return array;\n    }\n\n\n    function tally_property(name) {\n        if (option.properties && typeof property_type[name] !== 'string') {\n            warn('unexpected_property_a', token, name);\n        }\n        if (typeof member[name] === 'number') {\n            member[name] += 1;\n        } else {\n            member[name] = 1;\n        }\n    }\n\n\n// ECMAScript parser\n\n    syntax['(identifier)'] = {\n        id: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var name = this.string,\n                variable = scope[name],\n                site,\n                writeable;\n\n// If the variable is not in scope, then we may have an undeclared variable.\n// Check the predefined list. If it was predefined, create the global\n// variable.\n\n            if (typeof variable !== 'object') {\n                writeable = predefined[name];\n                if (typeof writeable === 'boolean') {\n                    global_scope[name] = variable = {\n                        string:    name,\n                        writeable: writeable,\n                        funct:     global_funct\n                    };\n                    global_funct[name] = 'var';\n\n// But if the variable is not in scope, and is not predefined, and if we are not\n// in the global scope, then we have an undefined variable error.\n\n                } else {\n                    if (!option.undef) {\n                        warn('used_before_a', token);\n                    }\n                    scope[name] = variable = {\n                        string: name,\n                        writeable: true,\n                        funct: funct\n                    };\n                    funct[name] = 'undef';\n                }\n\n            }\n            site = variable.funct;\n\n// The name is in scope and defined in the current function.\n\n            if (funct === site) {\n\n//      Change 'unused' to 'var', and reject labels.\n\n                switch (funct[name]) {\n                case 'becoming':\n                    warn('unexpected_a', token);\n                    funct[name] = 'var';\n                    break;\n                case 'unused':\n                    funct[name] = 'var';\n                    break;\n                case 'unparam':\n                    funct[name] = 'parameter';\n                    break;\n                case 'unction':\n                    funct[name] = 'function';\n                    break;\n                case 'label':\n                    warn('a_label', token, name);\n                    break;\n                }\n\n// If the name is already defined in the current\n// function, but not as outer, then there is a scope error.\n\n            } else {\n                switch (funct[name]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warn('a_scope', token, name);\n                    break;\n                case 'label':\n                    warn('a_label', token, name);\n                    break;\n                case 'outer':\n                case 'global':\n                    break;\n                default:\n\n// If the name is defined in an outer function, make an outer entry, and if\n// it was unused, make it var.\n\n                    switch (site[name]) {\n                    case 'becoming':\n                    case 'closure':\n                    case 'function':\n                    case 'parameter':\n                    case 'unction':\n                    case 'unused':\n                    case 'var':\n                        site[name] = 'closure';\n                        funct[name] = site === global_funct\n                            ? 'global'\n                            : 'outer';\n                        break;\n                    case 'unparam':\n                        site[name] = 'parameter';\n                        funct[name] = 'outer';\n                        break;\n                    case 'undef':\n                        funct[name] = 'undef';\n                        break;\n                    case 'label':\n                        warn('a_label', token, name);\n                        break;\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            stop('expected_operator_a');\n        }\n    };\n\n// Build the syntax table by declaring the syntactic elements.\n\n    type('(array)', 'array');\n    type('(color)', 'color');\n    type('(function)', 'function');\n    type('(number)', 'number', return_this);\n    type('(object)', 'object');\n    type('(string)', 'string', return_this);\n    type('(boolean)', 'boolean', return_this);\n    type('(range)', 'range');\n    type('(regexp)', 'regexp', return_this);\n\n    ultimate('(begin)');\n    ultimate('(end)');\n    ultimate('(error)');\n    postscript(symbol('</'));\n    symbol('<!');\n    symbol('<!--');\n    symbol('-->');\n    postscript(symbol('}'));\n    symbol(')');\n    symbol(']');\n    postscript(symbol('\"'));\n    postscript(symbol('\\''));\n    symbol(';');\n    symbol(':');\n    symbol(',');\n    symbol('#');\n    symbol('@');\n    symbol('*/');\n    postscript(reserve('case'));\n    reserve('catch');\n    postscript(reserve('default'));\n    reserve('else');\n    reserve('finally');\n\n    reservevar('arguments', function (x) {\n        if (strict_mode && funct === global_funct) {\n            warn('strict', x);\n        } else if (option.safe) {\n            warn('adsafe_a', x);\n        }\n    });\n    reservevar('eval', function (x) {\n        if (option.safe) {\n            warn('adsafe_a', x);\n        }\n    });\n    constant('false', 'boolean');\n    constant('Infinity', 'number');\n    constant('NaN', 'number');\n    constant('null', '');\n    reservevar('this', function (x) {\n        if (option.safe) {\n            warn('adsafe_a', x);\n        } else if (strict_mode && funct['(token)'].arity === 'statement' &&\n                funct['(name)'].charAt(0) > 'Z') {\n            warn('strict', x);\n        }\n    });\n    constant('true', 'boolean');\n    constant('undefined', '');\n\n    infix('?', 30, function (left, that) {\n        step_in('?');\n        that.first = expected_condition(expected_relation(left));\n        that.second = expression(0);\n        spaces();\n        step_out();\n        var colon = next_token;\n        advance(':');\n        step_in(':');\n        spaces();\n        that.third = expression(10);\n        that.arity = 'ternary';\n        if (are_similar(that.second, that.third)) {\n            warn('weird_ternary', colon);\n        } else if (are_similar(that.first, that.second)) {\n            warn('use_or', that);\n        }\n        step_out();\n        return that;\n    });\n\n    infix('||', 40, function (left, that) {\n        function paren_check(that) {\n            if (that.id === '&&' && !that.paren) {\n                warn('and', that);\n            }\n            return that;\n        }\n\n        that.first = paren_check(expected_condition(expected_relation(left)));\n        that.second = paren_check(expected_relation(expression(40)));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    infix('&&', 50, function (left, that) {\n        that.first = expected_condition(expected_relation(left));\n        that.second = expected_relation(expression(50));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    prefix('void', function () {\n        this.first = expression(0);\n        this.arity = 'prefix';\n        if (option.es5) {\n            warn('expected_a_b', this, 'undefined', 'void');\n        } else if (this.first.number !== 0) {\n            warn('expected_a_b', this.first, '0', artifact(this.first));\n        }\n        this.type = 'undefined';\n        return this;\n    });\n\n    bitwise('|', 70);\n    bitwise('^', 80);\n    bitwise('&', 90);\n\n    relation('==', '===');\n    relation('===');\n    relation('!=', '!==');\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n\n    bitwise('<<', 120);\n    bitwise('>>', 120);\n    bitwise('>>>', 120);\n\n    infix('in', 120, function (left, that) {\n        warn('infix_in', that);\n        that.left = left;\n        that.right = expression(130);\n        return that;\n    }, 'boolean');\n    infix('instanceof', 120, null, 'boolean');\n    infix('+', 130, function (left, that) {\n        if (left.id === '(number)') {\n            if (left.number === 0) {\n                warn('unexpected_a', left, '0');\n            }\n        } else if (left.id === '(string)') {\n            if (left.string === '') {\n                warn('expected_a_b', left, 'String', '\\'\\'');\n            }\n        }\n        var right = expression(130);\n        if (right.id === '(number)') {\n            if (right.number === 0) {\n                warn('unexpected_a', right, '0');\n            }\n        } else if (right.id === '(string)') {\n            if (right.string === '') {\n                warn('expected_a_b', right, 'String', '\\'\\'');\n            }\n        }\n        if (left.id === right.id) {\n            if (left.id === '(string)' || left.id === '(number)') {\n                if (left.id === '(string)') {\n                    left.string += right.string;\n                    if (jx.test(left.string)) {\n                        warn('url', left);\n                    }\n                } else {\n                    left.number += right.number;\n                }\n                left.thru = right.thru;\n                return left;\n            }\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('+++', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('-', 130, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(130);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number -= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n    prefix('-');\n    prefix('---', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('---', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('*', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number *= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n    infix('/', 140, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number /= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n    infix('%', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number %= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n\n    suffix('++');\n    prefix('++');\n\n    suffix('--');\n    prefix('--');\n    prefix('delete', function () {\n        one_space();\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warn('deleted');\n        }\n        this.first = p;\n        return this;\n    });\n\n\n    prefix('~', function () {\n        no_space_only();\n        if (!option.bitwise) {\n            warn('unexpected_a', this);\n        }\n        expression(150);\n        return this;\n    }, 'number');\n    prefix('!', function () {\n        no_space_only();\n        this.first = expected_condition(expression(150));\n        this.arity = 'prefix';\n        if (bang[this.first.id] === true || this.first.assign) {\n            warn('confusing_a', this);\n        }\n        return this;\n    }, 'boolean');\n    prefix('typeof', null, 'string');\n    prefix('new', function () {\n        one_space();\n        var c = expression(160), n, p, v;\n        this.first = c;\n        if (c.id !== 'function') {\n            if (c.identifier) {\n                switch (c.string) {\n                case 'Object':\n                    warn('use_object', token);\n                    break;\n                case 'Array':\n                    if (next_token.id === '(') {\n                        p = next_token;\n                        p.first = this;\n                        advance('(');\n                        if (next_token.id !== ')') {\n                            n = expression(0);\n                            p.second = [n];\n                            if (n.type !== 'number' || next_token.id === ',') {\n                                warn('use_array', p);\n                            }\n                            while (next_token.id === ',') {\n                                advance(',');\n                                p.second.push(expression(0));\n                            }\n                        } else {\n                            warn('use_array', token);\n                        }\n                        advance(')', p);\n                        return p;\n                    }\n                    warn('use_array', token);\n                    break;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warn('not_a_constructor', c);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warn('function_eval');\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                case 'this':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        v = c.string.charAt(0);\n                        if (!option.newcap && (v < 'A' || v > 'Z')) {\n                            warn('constructor_name_a', token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warn('bad_constructor', token);\n                }\n            }\n        } else {\n            warn('weird_new', this);\n        }\n        if (next_token.id !== '(') {\n            warn('missing_a', next_token, '()');\n        }\n        return this;\n    });\n\n    infix('(', 160, function (left, that) {\n        var p;\n        if (indent && indent.mode === 'expression') {\n            no_space(prev_token, token);\n        } else {\n            no_space_only(prev_token, token);\n        }\n        if (!left.immed && left.id === 'function') {\n            warn('wrap_immediate');\n        }\n        p = [];\n        if (left.identifier) {\n            if (left.string.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                if (left.string !== 'Number' && left.string !== 'String' &&\n                        left.string !== 'Boolean' && left.string !== 'Date') {\n                    if (left.string === 'Math' || left.string === 'JSON') {\n                        warn('not_a_function', left);\n                    } else if (left.string === 'Object') {\n                        warn('use_object', token);\n                    } else if (left.string === 'Array' || !option.newcap) {\n                        warn('missing_a', left, 'new');\n                    }\n                }\n            }\n        } else if (left.id === '.') {\n            if (option.safe && left.first.string === 'Math' &&\n                    left.second === 'random') {\n                warn('adsafe_a', left);\n            } else if (left.second.string === 'split' &&\n                    left.first.id === '(string)') {\n                warn('use_array', left.second);\n            }\n        }\n        step_in();\n        if (next_token.id !== ')') {\n            no_space();\n            for (;;) {\n                edge();\n                p.push(expression(10));\n                if (next_token.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        no_space();\n        step_out(')', that);\n        if (typeof left === 'object') {\n            if (left.string === 'parseInt' && p.length === 1) {\n                warn('radix', left);\n            }\n            if (!option.evil) {\n                if (left.string === 'eval' || left.string === 'Function' ||\n                        left.string === 'execScript') {\n                    warn('evil', left);\n                } else if (p[0] && p[0].id === '(string)' &&\n                        (left.string === 'setTimeout' ||\n                        left.string === 'setInterval')) {\n                    warn('implied_evil', left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warn('bad_invocation', left);\n            }\n        }\n        that.first = left;\n        that.second = p;\n        return that;\n    }, '', true);\n\n    prefix('(', function () {\n        step_in('expression');\n        no_space();\n        edge();\n        if (next_token.id === 'function') {\n            next_token.immed = true;\n        }\n        var value = expression(0);\n        value.paren = true;\n        no_space();\n        step_out(')', this);\n        if (value.id === 'function') {\n            if (next_token.id === '(') {\n                warn('move_invocation');\n            } else {\n                warn('bad_wrap', this);\n            }\n        }\n        return value;\n    });\n\n    infix('.', 170, function (left, that) {\n        no_space(prev_token, token);\n        no_space();\n        var name = identifier(), type;\n        if (typeof name === 'string') {\n            tally_property(name);\n        }\n        that.first = left;\n        that.second = token;\n        if (left && left.string === 'arguments' &&\n                (name === 'callee' || name === 'caller')) {\n            warn('avoid_a', left, 'arguments.' + name);\n        } else if (!option.evil && left && left.string === 'document' &&\n                (name === 'write' || name === 'writeln')) {\n            warn('write_is_wrong', left);\n        } else if (option.adsafe) {\n            if (!adsafe_top && left.string === 'ADSAFE') {\n                if (name === 'id' || name === 'lib') {\n                    warn('adsafe_a', that);\n                } else if (name === 'go') {\n                    if (xmode !== 'script') {\n                        warn('adsafe_a', that);\n                    } else if (adsafe_went || next_token.id !== '(' ||\n                            peek(0).id !== '(string)' ||\n                            peek(0).string !== adsafe_id ||\n                            peek(1).id !== ',') {\n                        stop('adsafe_a', that, 'go');\n                    }\n                    adsafe_went = true;\n                    adsafe_may = false;\n                }\n            }\n            adsafe_top = false;\n        }\n        if (!option.evil && (name === 'eval' || name === 'execScript')) {\n            warn('evil');\n        } else if (option.safe) {\n            for (;;) {\n                if (banned[name] === true) {\n                    warn('adsafe_a', token, name);\n                }\n                if (typeof predefined[left.string] !== 'boolean' ||    //// check for writeable\n                        next_token.id === '(') {\n                    break;\n                }\n                if (next_token.id !== '.') {\n                    warn('adsafe_a', that);\n                    break;\n                }\n                advance('.');\n                token.first = that;\n                token.second = name;\n                that = token;\n                name = identifier();\n                if (typeof name === 'string') {\n                    tally_property(name);\n                }\n            }\n        }\n        type = property_type[name];\n        if (type && typeof type === 'string' && type !== '*') {\n            that.type = type;\n        }\n        return that;\n    }, '', true);\n\n    infix('[', 170, function (left, that) {\n        var e, s;\n        no_space_only(prev_token, token);\n        no_space();\n        step_in();\n        edge();\n        e = expression(0);\n        switch (e.type) {\n        case 'number':\n            if (e.id === '(number)' && left.id === 'arguments') {\n                warn('use_param', left);\n            }\n            break;\n        case 'string':\n            if (e.id === '(string)') {\n                if (option.safe && (banned[e.string] ||\n                        e.string.charAt(0) === '_' || e.string.slice(-1) === '_')) {\n                    warn('adsafe_subscript_a', e);\n                } else if (!option.evil &&\n                        (e.string === 'eval' || e.string === 'execScript')) {\n                    warn('evil', e);\n                } else if (!option.sub && ix.test(e.string)) {\n                    s = syntax[e.string];\n                    if (!s || !s.reserved) {\n                        warn('subscript', e);\n                    }\n                }\n                tally_property(e.string);\n            } else if (option.safe && e.id !== 'typeof') {\n                warn('adsafe_subscript_a', e);\n            }\n            break;\n        case undefined:\n            if (option.safe) {\n                warn('adsafe_subscript_a', e);\n            }\n            break;\n        default:\n            if (option.safe) {\n                warn('adsafe_subscript_a', e);\n            }\n        }\n        step_out(']', that);\n        no_space(prev_token, token);\n        that.first = left;\n        that.second = e;\n        return that;\n    }, '', true);\n\n    prefix('[', function () {\n        this.arity = 'prefix';\n        this.first = [];\n        step_in('array');\n        while (next_token.id !== '(end)') {\n            while (next_token.id === ',') {\n                warn('unexpected_a', next_token);\n                advance(',');\n            }\n            if (next_token.id === ']') {\n                break;\n            }\n            indent.wrap = false;\n            edge();\n            this.first.push(expression(10));\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id === ']' && !option.es5) {\n                    warn('unexpected_a', token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        step_out(']', this);\n        return this;\n    }, 170);\n\n\n    function property_name() {\n        var id = optional_identifier(true);\n        if (!id) {\n            if (next_token.id === '(string)') {\n                id = next_token.string;\n                if (option.safe) {\n                    if (banned[id]) {\n                        warn('adsafe_a');\n                    } else if (id.charAt(0) === '_' ||\n                            id.charAt(id.length - 1) === '_') {\n                        warn('dangling_a');\n                    }\n                }\n                advance();\n            } else if (next_token.id === '(number)') {\n                id = next_token.number.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function function_params() {\n        var id, paren = next_token, params = [];\n        advance('(');\n        step_in();\n        no_space();\n        if (next_token.id === ')') {\n            no_space();\n            step_out(')', paren);\n            return;\n        }\n        for (;;) {\n            edge();\n            id = identifier();\n            params.push(token);\n            add_label(token, option.unparam ? 'parameter' : 'unparam');\n            if (next_token.id === ',') {\n                comma();\n            } else {\n                no_space();\n                step_out(')', paren);\n                return params;\n            }\n        }\n    }\n\n\n\n    function do_function(func, name) {\n        var old_funct      = funct,\n            old_option     = option,\n            old_scope      = scope;\n        funct = {\n            '(name)'     : name || '\\'' + (anonname || '').replace(nx, sanitize) + '\\'',\n            '(line)'     : next_token.line,\n            '(context)'  : old_funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(token)'    : func\n        };\n        option = Object.create(old_option);\n        scope = Object.create(old_scope);\n        functions.push(funct);\n        func.name = name;\n        if (name) {\n            add_label(func, 'function', name);\n        }\n        func.writeable = false;\n        func.first = funct['(params)'] = function_params();\n        one_space();\n        func.block = block(false);\n        if (funct['(old_property_type)']) {\n            property_type = funct['(old_property_type)'];\n            delete funct['(old_property_type)'];\n        }\n        if (option.confusion) {\n            funct['(confusion)'] = true;\n        }\n        funct      = old_funct;\n        option     = old_option;\n        scope      = old_scope;\n    }\n\n\n    assignop('=');\n    assignop('+=', '+');\n    assignop('-=', '-');\n    assignop('*=', '*');\n    assignop('/=', '/').nud = function () {\n        stop('slash_equal');\n    };\n    assignop('%=', '%');\n    assignop('&=', '&');\n    assignop('|=', '|');\n    assignop('^=', '^');\n    assignop('<<=', '<<');\n    assignop('>>=', '>>');\n    assignop('>>>=', '>>>');\n\n\n    prefix('{', function () {\n        var get, i, j, name, p, set, seen = {};\n        this.arity = 'prefix';\n        this.first = [];\n        step_in();\n        while (next_token.id !== '}') {\n            indent.wrap = false;\n\n// JSLint recognizes the ES5 extension for get/set in object literals,\n// but requires that they be used in pairs.\n\n            edge();\n            if (next_token.string === 'get' && peek().id !== ':') {\n                if (!option.es5) {\n                    warn('es5');\n                }\n                get = next_token;\n                advance('get');\n                one_space_only();\n                name = next_token;\n                i = property_name();\n                if (!i) {\n                    stop('missing_property');\n                }\n                get.string = '';\n                do_function(get);\n                if (funct['(loopage)']) {\n                    warn('function_loop', get);\n                }\n                p = get.first;\n                if (p) {\n                    warn('parameter_a_get_b', p[0], p[0].string, i);\n                }\n                comma();\n                set = next_token;\n                spaces();\n                edge();\n                advance('set');\n                set.string = '';\n                one_space_only();\n                j = property_name();\n                if (i !== j) {\n                    stop('expected_a_b', token, i, j || next_token.string);\n                }\n                do_function(set);\n                if (set.block.length === 0) {\n                    warn('missing_a', token, 'throw');\n                }\n                p = set.first;\n                if (!p || p.length !== 1) {\n                    stop('parameter_set_a', set, 'value');\n                } else if (p[0].string !== 'value') {\n                    stop('expected_a_b', p[0], 'value', p[0].string);\n                }\n                name.first = [get, set];\n            } else {\n                name = next_token;\n                i = property_name();\n                if (typeof i !== 'string') {\n                    stop('missing_property');\n                }\n                advance(':');\n                spaces();\n                name.first = expression(10);\n            }\n            this.first.push(name);\n            if (seen[i] === true) {\n                warn('duplicate_a', next_token, i);\n            }\n            seen[i] = true;\n            tally_property(i);\n            if (next_token.id !== ',') {\n                break;\n            }\n            for (;;) {\n                comma();\n                if (next_token.id !== ',') {\n                    break;\n                }\n                warn('unexpected_a', next_token);\n            }\n            if (next_token.id === '}' && !option.es5) {\n                warn('unexpected_a', token);\n            }\n        }\n        step_out('}', this);\n        return this;\n    });\n\n    stmt('{', function () {\n        warn('statement_block');\n        this.arity = 'statement';\n        this.block = statements();\n        this.disrupt = this.block.disrupt;\n        advance('}', this);\n        return this;\n    });\n\n    stmt('/*global', directive);\n    stmt('/*globals', directive);\n    stmt('/*jslint', directive);\n    stmt('/*member', directive);\n    stmt('/*members', directive);\n    stmt('/*property', directive);\n    stmt('/*properties', directive);\n\n    stmt('var', function () {\n\n// JavaScript does not have block scope. It only has function scope. So,\n// declaring a variable in a block can have unexpected consequences.\n\n// var.first will contain an array, the array containing name tokens\n// and assignment tokens.\n\n        var assign, id, name;\n\n        if (funct['(vars)'] && !option.vars) {\n            warn('combine_var');\n        } else if (funct !== global_funct) {\n            funct['(vars)'] = true;\n        }\n        this.arity = 'statement';\n        this.first = [];\n        step_in('var');\n        for (;;) {\n            name = next_token;\n            id = identifier();\n            add_label(name, 'becoming');\n\n            if (next_token.id === '=') {\n                assign = next_token;\n                assign.first = name;\n                spaces();\n                advance('=');\n                spaces();\n                if (next_token.id === 'undefined') {\n                    warn('unnecessary_initialize', token, id);\n                }\n                if (peek(0).id === '=' && next_token.identifier) {\n                    stop('var_a_not');\n                }\n                assign.second = expression(0);\n                assign.arity = 'infix';\n                this.first.push(assign);\n            } else {\n                this.first.push(name);\n            }\n            if (funct[id] === 'becoming') {\n                funct[id] = 'unused';\n            }\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n            indent.wrap = false;\n            if (var_mode && next_token.line === token.line &&\n                    this.first.length === 1) {\n                var_mode = null;\n                indent.open = false;\n                indent.at -= option.indent;\n            }\n            spaces();\n            edge();\n        }\n        var_mode = null;\n        step_out();\n        return this;\n    });\n\n    stmt('function', function () {\n        one_space();\n        if (in_block) {\n            warn('function_block', token);\n        }\n        var name = next_token, id = identifier();\n        add_label(name, 'unction');\n        no_space();\n        this.arity = 'statement';\n        do_function(this, id);\n        if (next_token.id === '(' && next_token.line === token.line) {\n            stop('function_statement');\n        }\n        return this;\n    });\n\n    prefix('function', function () {\n        if (!option.anon) {\n            one_space();\n        }\n        var id = optional_identifier();\n        if (id) {\n            no_space();\n        } else {\n            id = '';\n        }\n        do_function(this, id);\n        if (funct['(loopage)']) {\n            warn('function_loop');\n        }\n        this.arity = 'function';\n        return this;\n    });\n\n    stmt('if', function () {\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block(true);\n        if (next_token.id === 'else') {\n            one_space();\n            advance('else');\n            one_space();\n            this['else'] = next_token.id === 'if' || next_token.id === 'switch'\n                ? statement(true)\n                : block(true);\n            if (this['else'].disrupt && this.block.disrupt) {\n                this.disrupt = true;\n            }\n        }\n        return this;\n    });\n\n    stmt('try', function () {\n\n// try.first    The catch variable\n// try.second   The catch clause\n// try.third    The finally clause\n// try.block    The try block\n\n        var exception_variable, old_scope, paren;\n        if (option.adsafe) {\n            warn('adsafe_a', this);\n        }\n        one_space();\n        this.arity = 'statement';\n        this.block = block(false);\n        if (next_token.id === 'catch') {\n            one_space();\n            advance('catch');\n            one_space();\n            paren = next_token;\n            advance('(');\n            step_in('control');\n            no_space();\n            edge();\n            old_scope = scope;\n            scope = Object.create(old_scope);\n            exception_variable = next_token.string;\n            this.first = exception_variable;\n            if (!next_token.identifier) {\n                warn('expected_identifier_a', next_token);\n            } else {\n                add_label(next_token, 'exception');\n            }\n            advance();\n            no_space();\n            step_out(')', paren);\n            one_space();\n            this.second = block(false);\n            scope = old_scope;\n        }\n        if (next_token.id === 'finally') {\n            one_space();\n            advance('finally');\n            one_space();\n            this.third = block(false);\n        } else if (!this.second) {\n            stop('expected_a_b', next_token, 'catch', artifact());\n        }\n        return this;\n    });\n\n    labeled_stmt('while', function () {\n        one_space();\n        var paren = next_token;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_relation(expression(0));\n        if (this.first.id !== 'true') {\n            expected_condition(this.first, bundle.unexpected_a);\n        }\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    reserve('with');\n\n    labeled_stmt('switch', function () {\n\n// switch.first         the switch expression\n// switch.second        the array of cases. A case is 'case' or 'default' token:\n//    case.first        the array of case expressions\n//    case.second       the array of statements\n// If all of the arrays of statements are disrupt, then the switch is disrupt.\n\n        var cases = [],\n            old_in_block = in_block,\n            particular,\n            the_case = next_token,\n            unbroken = true;\n\n        function find_duplicate_case(value) {\n            if (are_similar(particular, value)) {\n                warn('duplicate_a', value);\n            }\n        }\n\n        funct['(breakage)'] += 1;\n        one_space();\n        advance('(');\n        no_space();\n        step_in();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', the_case);\n        one_space();\n        advance('{');\n        step_in();\n        in_block = true;\n        this.second = [];\n        while (next_token.id === 'case') {\n            the_case = next_token;\n            cases.forEach(find_duplicate_case);\n            the_case.first = [];\n            the_case.arity = 'case';\n            spaces();\n            edge('case');\n            advance('case');\n            for (;;) {\n                one_space();\n                particular = expression(0);\n                cases.forEach(find_duplicate_case);\n                cases.push(particular);\n                the_case.first.push(particular);\n                if (particular.id === 'NaN') {\n                    warn('unexpected_a', particular);\n                }\n                no_space_only();\n                advance(':');\n                if (next_token.id !== 'case') {\n                    break;\n                }\n                spaces();\n                edge('case');\n                advance('case');\n            }\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (particular.disrupt) {\n                    if (particular.id === 'break') {\n                        unbroken = false;\n                    }\n                } else {\n                    warn('missing_a_after_b', next_token, 'break', 'case');\n                }\n            } else {\n                warn('empty_case');\n            }\n            this.second.push(the_case);\n        }\n        if (this.second.length === 0) {\n            warn('missing_a', next_token, 'case');\n        }\n        if (next_token.id === 'default') {\n            spaces();\n            the_case = next_token;\n            the_case.arity = 'case';\n            edge('case');\n            advance('default');\n            no_space_only();\n            advance(':');\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (unbroken && particular.disrupt && particular.id !== 'break') {\n                    this.disrupt = true;\n                }\n            }\n            this.second.push(the_case);\n        }\n        funct['(breakage)'] -= 1;\n        spaces();\n        step_out('}', this);\n        in_block = old_in_block;\n        return this;\n    });\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        return this;\n    });\n\n    labeled_stmt('do', function () {\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        one_space();\n        this.arity = 'statement';\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        one_space();\n        advance('while');\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in();\n        no_space();\n        edge();\n        this.first = expected_condition(expected_relation(expression(0)), bundle.unexpected_a);\n        no_space();\n        step_out(')', paren);\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    labeled_stmt('for', function () {\n\n        var blok, filter, ok = false, paren = next_token, value;\n        this.arity = 'statement';\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        if (next_token.id === ';') {\n            no_space();\n            advance(';');\n            no_space();\n            advance(';');\n            no_space();\n            advance(')');\n            blok = block(true);\n        } else {\n            step_in('control');\n            spaces(this, paren);\n            no_space();\n            if (next_token.id === 'var') {\n                stop('move_var');\n            }\n            edge();\n            if (peek(0).id === 'in') {\n                this.forin = true;\n                value = next_token;\n                switch (funct[value.string]) {\n                case 'unused':\n                    funct[value.string] = 'var';\n                    break;\n                case 'closure':\n                case 'var':\n                    break;\n                default:\n                    warn('bad_in_a', value);\n                }\n                advance();\n                advance('in');\n                this.first = value;\n                this.second = expression(20);\n                step_out(')', paren);\n                blok = block(true);\n                if (!option.forin) {\n                    if (blok.length === 1 && typeof blok[0] === 'object' &&\n                            blok[0].string === 'if' && !blok[0]['else']) {\n                        filter = blok[0].first;\n                        while (filter.id === '&&') {\n                            filter = filter.first;\n                        }\n                        switch (filter.id) {\n                        case '===':\n                        case '!==':\n                            ok = filter.first.id === '['\n                                ? filter.first.first.string === this.second.string &&\n                                    filter.first.second.string === this.first.string\n                                : filter.first.id === 'typeof' &&\n                                    filter.first.first.id === '[' &&\n                                    filter.first.first.first.string === this.second.string &&\n                                    filter.first.first.second.string === this.first.string;\n                            break;\n                        case '(':\n                            ok = filter.first.id === '.' && ((\n                                filter.first.first.string === this.second.string &&\n                                filter.first.second.string === 'hasOwnProperty' &&\n                                filter.second[0].string === this.first.string\n                            ) || (\n                                filter.first.first.string === 'ADSAFE' &&\n                                filter.first.second.string === 'has' &&\n                                filter.second[0].string === this.second.string &&\n                                filter.second[1].string === this.first.string\n                            ) || (\n                                filter.first.first.id === '.' &&\n                                filter.first.first.first.id === '.' &&\n                                filter.first.first.first.first.string === 'Object' &&\n                                filter.first.first.first.second.string === 'prototype' &&\n                                filter.first.first.second.string === 'hasOwnProperty' &&\n                                filter.first.second.string === 'call' &&\n                                filter.second[0].string === this.second.string &&\n                                filter.second[1].string === this.first.string\n                            ));\n                            break;\n                        }\n                    }\n                    if (!ok) {\n                        warn('for_if', this);\n                    }\n                }\n            } else {\n                edge();\n                this.first = [];\n                for (;;) {\n                    this.first.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                semicolon();\n                edge();\n                this.second = expected_relation(expression(0));\n                if (this.second.id !== 'true') {\n                    expected_condition(this.second, bundle.unexpected_a);\n                }\n                semicolon(token);\n                if (next_token.id === ';') {\n                    stop('expected_a_b', next_token, ')', ';');\n                }\n                this.third = [];\n                edge();\n                for (;;) {\n                    this.third.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                no_space();\n                step_out(')', paren);\n                one_space();\n                blok = block(true);\n            }\n        }\n        if (blok.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        this.block = blok;\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    disrupt_stmt('break', function () {\n        var label = next_token.string;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label].funct !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('continue', function () {\n        if (!option['continue']) {\n            warn('unexpected_a', this);\n        }\n        var label = next_token.string;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label].funct !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('return', function () {\n        if (funct === global_funct) {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        if (next_token.id !== ';' && next_token.line === token.line) {\n            one_space_only();\n            if (next_token.id === '/' || next_token.id === '(regexp)') {\n                warn('wrap_regexp');\n            }\n            this.first = expression(20);\n        }\n        return this;\n    });\n\n    disrupt_stmt('throw', function () {\n        this.arity = 'statement';\n        one_space_only();\n        this.first = expression(20);\n        return this;\n    });\n\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n// Harmony reserved words\n\n    reserve('implements');\n    reserve('interface');\n    reserve('let');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n    reserve('yield');\n\n\n// Type inference\n\n//     function get_type(one) {\n//         var type;\n//         if (typeof one === 'string') {\n//             return one;\n//         } else if (one.type) {\n//             return one.type;\n//         } else if (one.id === '.') {\n//             type = property_type[one.second.string];\n//             return typeof type === 'string' ? type : '';\n//         } else {\n//             return ((one.identifier && scope[one.string]) || one).type;\n//         }\n//     }\n\n\n//     function match_type(one_type, two_type, one, two) {\n//         if (one_type === two_type) {\n//             return true;\n//         } else {\n//             if (!funct.confusion && !two.warn) {\n//                 if (typeof one !== 'string') {\n//                     if (one.id === '.') {\n//                         one_type = '.' + one.second.string + ': ' + one_type;\n//                     } else {\n//                         one_type = one.string + ': ' + one_type;\n//                     }\n//                 }\n//                 if (two.id === '.') {\n//                     two_type = '.' + two.second.string + ': ' + one_type;\n//                 } else {\n//                     two_type = two.string + ': ' + one_type;\n//                 }\n//                 warn('type_confusion_a_b', two, one_type, two_type);\n//                 two.warn = true;\n//             }\n//             return false;\n//         }\n//     }\n\n\n//     function conform(one, two) {\n//\n// // The conform function takes a type string and a token, or two tokens.\n//\n//         var one_type = typeof one === 'string' ? one : one.type,\n//             two_type = two.type,\n//             two_thing;\n//\n// // If both tokens already have a type, and if they match, then we are done.\n// // Once a token has a type, it is locked. Neither token will change, but if\n// // they do not match, there will be a warning.\n//\n//         if (one_type) {\n//             if (two_type) {\n//                 match_type(one_type, two_type, one, two);\n//             } else {\n//\n// // two does not have a type, so look deeper. If two is a variable or property,\n// // then use its type if it has one, and make the deep type one's type if it\n// // doesn't. If the type was *, or if there was a mismatch, don't change the\n// // deep type.\n//\n//                 two_thing = two.id === '(identifier)'\n//                     ? scope[two.string]\n//                     : two.id === '.'\n//                     ? property_type[two.second.string]\n//                     : null;\n//                 if (two_thing) {\n//                     two_type = two_thing.type;\n//                     if (two_type) {\n//                         if (two_type !== '*') {\n//                             if (!match_type(one_type, two_type, one, two)) {\n//                                 return '';\n//                             }\n//                         }\n//                     } else {\n//                         two_thing.type = one_type;\n//                     }\n//                 }\n//\n// // In any case, we give two a type.\n//\n//                 two.type = one_type;\n//                 type_state_change = true;\n//                 return one_type;\n//             }\n//\n// // one does not have a type, but two does, so do the old switcheroo.\n//\n//         } else {\n//             if (two_type) {\n//                 return conform(two, one);\n//\n// // Neither token has a type yet. So we have to look deeper to see if either\n// // is a variable or property.\n//\n//             } else {\n//                 if (one.id === '(identifier)') {\n//                     one_type = scope[one.string].type;\n//                     if (one_type && one_type !== '*') {\n//                         one.type = one_type;\n//                         return conform(one, two);\n//                     }\n//                 } else if (one.id === '.') {\n//                     one_type = property_type[one.second.string];\n//                     if (one_type && one_type !== '*') {\n//                         one.type = scope[one.string].type;\n//                         return conform(one, two);\n//                     }\n//                 }\n//                 if (two.id === '(identifier)') {\n//                     two_type = scope[two.string].type;\n//                     if (two_type && two_type !== '*') {\n//                         two.type = two_type;\n//                         return conform(two, one);\n//                     }\n//                 } else if (two.id === '.') {\n//                     two_type = property_type[two.second.string];\n//                     if (two_type && two_type !== '*') {\n//                         two.type = scope[two.string].type;\n//                         return conform(two, one);\n//                     }\n//                 }\n//             }\n//         }\n//\n// // Return a falsy string if we were unable to determine the type of either token.\n//\n//         return '';\n//     }\n\n//     function conform_array(type, array) {\n//         array.forEach(function (item) {\n//             return conform(type, item);\n//         }, type);\n//     }\n\n\n//     function infer(node) {\n//         if (Array.isArray(node)) {\n//             node.forEach(infer);\n//         } else {\n//             switch (node.arity) {\n//             case 'statement':\n//                 infer_statement[node.id](node);\n//                 break;\n//             case 'infix':\n//                 infer(node.first);\n//                 infer(node.second);\n//                 switch (node.id) {\n//                 case '(':\n//                     conform('function', node.first);\n//                     break;\n//                 default:\n//                     stop('unfinished');\n//                 }\n//                 break;\n//             case 'number':\n//             case 'string':\n//             case 'boolean':\n//                 break;\n//             default:\n//                 stop('unfinished');\n//             }\n//         }\n//     }\n\n\n//     infer_statement = {\n//         'var': function (node) {\n//             var i, item, list = node.first;\n//             for (i = 0; i < list.length; i += 1) {\n//                 item = list[i];\n//                 if (item.id === '=') {\n//                     infer(item.second);\n//                     conform(item.first, item.second);\n//                     conform(item.first, item);\n//                 }\n//             }\n//         },\n//         'for': function (node) {\n//             infer(node.first);\n//             infer(node.second);\n//             if (node.forin) {\n//                 conform('string', node.first);\n//                 conform('object', node.second);\n//             } else {\n//                 infer(node.third);\n//                 conform_array('number', node.first);\n//                 conform('boolean', node.second);\n//                 conform_array('number', node.third);\n//             }\n//             infer(node.block);\n//         }\n//     };\n\n\n//     function infer_types(node) {\n//         do {\n//             funct = global_funct;\n//             scope = global_scope;\n//             type_state_change = false;\n//             infer(node);\n//         } while (type_state_change);\n//     }\n\n\n// Parse JSON\n\n    function json_value() {\n\n        function json_object() {\n            var brace = next_token, object = {};\n            advance('{');\n            if (next_token.id !== '}') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        advance(',');\n                    }\n                    if (next_token.id !== '(string)') {\n                        warn('expected_string_a');\n                    }\n                    if (object[next_token.string] === true) {\n                        warn('duplicate_a');\n                    } else if (next_token.string === '__proto__') {\n                        warn('dangling_a');\n                    } else {\n                        object[next_token.string] = true;\n                    }\n                    advance();\n                    advance(':');\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === '}') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance('}', brace);\n        }\n\n        function json_array() {\n            var bracket = next_token;\n            advance('[');\n            if (next_token.id !== ']') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        advance(',');\n                    }\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === ']') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance(']', bracket);\n        }\n\n        switch (next_token.id) {\n        case '{':\n            json_object();\n            break;\n        case '[':\n            json_array();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            no_space_only();\n            advance('(number)');\n            break;\n        default:\n            stop('unexpected_a');\n        }\n    }\n\n\n// CSS parsing.\n\n    function css_name() {\n        if (next_token.identifier) {\n            advance();\n            return true;\n        }\n    }\n\n\n    function css_number() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance('(number)');\n            return true;\n        }\n    }\n\n\n    function css_string() {\n        if (next_token.id === '(string)') {\n            advance();\n            return true;\n        }\n    }\n\n    function css_color() {\n        var i, number, paren, value;\n        if (next_token.identifier) {\n            value = next_token.string;\n            if (value === 'rgb' || value === 'rgba') {\n                advance();\n                paren = next_token;\n                advance('(');\n                for (i = 0; i < 3; i += 1) {\n                    if (i) {\n                        comma();\n                    }\n                    number = next_token.number;\n                    if (next_token.id !== '(number)' || number < 0) {\n                        warn('expected_positive_a', next_token);\n                        advance();\n                    } else {\n                        advance();\n                        if (next_token.id === '%') {\n                            advance('%');\n                            if (number > 100) {\n                                warn('expected_percent_a', token, number);\n                            }\n                        } else {\n                            if (number > 255) {\n                                warn('expected_small_a', token, number);\n                            }\n                        }\n                    }\n                }\n                if (value === 'rgba') {\n                    comma();\n                    number = next_token.number;\n                    if (next_token.id !== '(number)' || number < 0 || number > 1) {\n                        warn('expected_fraction_a', next_token);\n                    }\n                    advance();\n                    if (next_token.id === '%') {\n                        warn('unexpected_a');\n                        advance('%');\n                    }\n                }\n                advance(')', paren);\n                return true;\n            } else if (css_colorData[next_token.string] === true) {\n                advance();\n                return true;\n            }\n        } else if (next_token.id === '(color)') {\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_length() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.id !== '(string)' &&\n                    css_lengthData[next_token.string] === true) {\n                no_space_only();\n                advance();\n            } else if (+token.number !== 0) {\n                warn('expected_linear_a');\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_line_height() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.id !== '(string)' &&\n                    css_lengthData[next_token.string] === true) {\n                no_space_only();\n                advance();\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_width() {\n        if (next_token.identifier) {\n            switch (next_token.string) {\n            case 'thin':\n            case 'medium':\n            case 'thick':\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n\n    function css_margin() {\n        if (next_token.identifier) {\n            if (next_token.string === 'auto') {\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n    function css_attr() {\n        if (next_token.identifier && next_token.string === 'attr') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_comma_list() {\n        while (next_token.id !== ';') {\n            if (!css_name() && !css_string()) {\n                warn('expected_name_a');\n            }\n            if (next_token.id !== ',') {\n                return true;\n            }\n            comma();\n        }\n    }\n\n\n    function css_counter() {\n        if (next_token.identifier && next_token.string === 'counter') {\n            advance();\n            advance('(');\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        if (next_token.identifier && next_token.string === 'counters') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_radius() {\n        return css_length() && (next_token.id !== '(number)' || css_length());\n    }\n\n\n    function css_shape() {\n        var i;\n        if (next_token.identifier && next_token.string === 'rect') {\n            advance();\n            advance('(');\n            for (i = 0; i < 4; i += 1) {\n                if (!css_length()) {\n                    warn('expected_number_a');\n                    break;\n                }\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_url() {\n        var c, url;\n        if (next_token.identifier && next_token.string === 'url') {\n            next_token = lex.range('(', ')');\n            url = next_token.string;\n            c = url.charAt(0);\n            if (c === '\"' || c === '\\'') {\n                if (url.slice(-1) !== c) {\n                    warn('bad_url_a');\n                } else {\n                    url = url.slice(1, -1);\n                    if (url.indexOf(c) >= 0) {\n                        warn('bad_url_a');\n                    }\n                }\n            }\n            if (!url) {\n                warn('missing_url');\n            }\n            if (ux.test(url)) {\n                stop('bad_url_a');\n            }\n            urls.push(url);\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    css_any = [css_url, function () {\n        for (;;) {\n            if (next_token.identifier) {\n                switch (next_token.string.toLowerCase()) {\n                case 'url':\n                    css_url();\n                    break;\n                case 'expression':\n                    warn('unexpected_a');\n                    advance();\n                    break;\n                default:\n                    advance();\n                }\n            } else {\n                if (next_token.id === ';' || next_token.id === '!'  ||\n                        next_token.id === '(end)' || next_token.id === '}') {\n                    return true;\n                }\n                advance();\n            }\n        }\n    }];\n\n\n    function font_face() {\n        advance_identifier('font-family');\n        advance(':');\n        if (!css_name() && !css_string()) {\n            stop('expected_name_a');\n        }\n        semicolon();\n        advance_identifier('src');\n        advance(':');\n        while (true) {\n            if (next_token.string === 'local') {\n                advance_identifier('local');\n                advance('(');\n                if (ux.test(next_token.string)) {\n                    stop('bad_url_a');\n                }\n\n                if (!css_name() && !css_string()) {\n                    stop('expected_name_a');\n                }\n                advance(')');\n            } else if (!css_url()) {\n                stop('expected_a_b', next_token, 'url', artifact());\n            }\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n        }\n        semicolon();\n    }\n\n\n    css_border_style = [\n        'none', 'dashed', 'dotted', 'double', 'groove',\n        'hidden', 'inset', 'outset', 'ridge', 'solid'\n    ];\n\n    css_break = [\n        'auto', 'always', 'avoid', 'left', 'right'\n    ];\n\n    css_media = {\n        'all': true,\n        'braille': true,\n        'embossed': true,\n        'handheld': true,\n        'print': true,\n        'projection': true,\n        'screen': true,\n        'speech': true,\n        'tty': true,\n        'tv': true\n    };\n\n    css_overflow = [\n        'auto', 'hidden', 'scroll', 'visible'\n    ];\n\n    css_attribute_data = {\n        background: [\n            true, 'background-attachment', 'background-color',\n            'background-image', 'background-position', 'background-repeat'\n        ],\n        'background-attachment': ['scroll', 'fixed'],\n        'background-color': ['transparent', css_color],\n        'background-image': ['none', css_url],\n        'background-position': [\n            2, [css_length, 'top', 'bottom', 'left', 'right', 'center']\n        ],\n        'background-repeat': [\n            'repeat', 'repeat-x', 'repeat-y', 'no-repeat'\n        ],\n        'border': [true, 'border-color', 'border-style', 'border-width'],\n        'border-bottom': [\n            true, 'border-bottom-color', 'border-bottom-style',\n            'border-bottom-width'\n        ],\n        'border-bottom-color': css_color,\n        'border-bottom-left-radius': css_radius,\n        'border-bottom-right-radius': css_radius,\n        'border-bottom-style': css_border_style,\n        'border-bottom-width': css_width,\n        'border-collapse': ['collapse', 'separate'],\n        'border-color': ['transparent', 4, css_color],\n        'border-left': [\n            true, 'border-left-color', 'border-left-style', 'border-left-width'\n        ],\n        'border-left-color': css_color,\n        'border-left-style': css_border_style,\n        'border-left-width': css_width,\n        'border-radius': function () {\n            function count(separator) {\n                var n = 1;\n                if (separator) {\n                    advance(separator);\n                }\n                if (!css_length()) {\n                    return false;\n                }\n                while (next_token.id === '(number)') {\n                    if (!css_length()) {\n                        return false;\n                    }\n                    n += 1;\n                }\n                if (n > 4) {\n                    warn('bad_style');\n                }\n                return true;\n            }\n\n            return count() && (next_token.id !== '/' || count('/'));\n        },\n        'border-right': [\n            true, 'border-right-color', 'border-right-style',\n            'border-right-width'\n        ],\n        'border-right-color': css_color,\n        'border-right-style': css_border_style,\n        'border-right-width': css_width,\n        'border-spacing': [2, css_length],\n        'border-style': [4, css_border_style],\n        'border-top': [\n            true, 'border-top-color', 'border-top-style', 'border-top-width'\n        ],\n        'border-top-color': css_color,\n        'border-top-left-radius': css_radius,\n        'border-top-right-radius': css_radius,\n        'border-top-style': css_border_style,\n        'border-top-width': css_width,\n        'border-width': [4, css_width],\n        bottom: [css_length, 'auto'],\n        'caption-side' : ['bottom', 'left', 'right', 'top'],\n        clear: ['both', 'left', 'none', 'right'],\n        clip: [css_shape, 'auto'],\n        color: css_color,\n        content: [\n            'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',\n            css_string, css_url, css_counter, css_attr\n        ],\n        'counter-increment': [\n            css_name, 'none'\n        ],\n        'counter-reset': [\n            css_name, 'none'\n        ],\n        cursor: [\n            css_url, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',\n            'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',\n            'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'\n        ],\n        direction: ['ltr', 'rtl'],\n        display: [\n            'block', 'compact', 'inline', 'inline-block', 'inline-table',\n            'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',\n            'table-cell', 'table-column', 'table-column-group',\n            'table-footer-group', 'table-header-group', 'table-row',\n            'table-row-group'\n        ],\n        'empty-cells': ['show', 'hide'],\n        'float': ['left', 'none', 'right'],\n        font: [\n            'caption', 'icon', 'menu', 'message-box', 'small-caption',\n            'status-bar', true, 'font-size', 'font-style', 'font-weight',\n            'font-family'\n        ],\n        'font-family': css_comma_list,\n        'font-size': [\n            'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',\n            'xx-large', 'larger', 'smaller', css_length\n        ],\n        'font-size-adjust': ['none', css_number],\n        'font-stretch': [\n            'normal', 'wider', 'narrower', 'ultra-condensed',\n            'extra-condensed', 'condensed', 'semi-condensed',\n            'semi-expanded', 'expanded', 'extra-expanded'\n        ],\n        'font-style': [\n            'normal', 'italic', 'oblique'\n        ],\n        'font-variant': [\n            'normal', 'small-caps'\n        ],\n        'font-weight': [\n            'normal', 'bold', 'bolder', 'lighter', css_number\n        ],\n        height: [css_length, 'auto'],\n        left: [css_length, 'auto'],\n        'letter-spacing': ['normal', css_length],\n        'line-height': ['normal', css_line_height],\n        'list-style': [\n            true, 'list-style-image', 'list-style-position', 'list-style-type'\n        ],\n        'list-style-image': ['none', css_url],\n        'list-style-position': ['inside', 'outside'],\n        'list-style-type': [\n            'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',\n            'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',\n            'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',\n            'hiragana-iroha', 'katakana-oroha', 'none'\n        ],\n        margin: [4, css_margin],\n        'margin-bottom': css_margin,\n        'margin-left': css_margin,\n        'margin-right': css_margin,\n        'margin-top': css_margin,\n        'marker-offset': [css_length, 'auto'],\n        'max-height': [css_length, 'none'],\n        'max-width': [css_length, 'none'],\n        'min-height': css_length,\n        'min-width': css_length,\n        opacity: css_number,\n        outline: [true, 'outline-color', 'outline-style', 'outline-width'],\n        'outline-color': ['invert', css_color],\n        'outline-style': [\n            'dashed', 'dotted', 'double', 'groove', 'inset', 'none',\n            'outset', 'ridge', 'solid'\n        ],\n        'outline-width': css_width,\n        overflow: css_overflow,\n        'overflow-x': css_overflow,\n        'overflow-y': css_overflow,\n        padding: [4, css_length],\n        'padding-bottom': css_length,\n        'padding-left': css_length,\n        'padding-right': css_length,\n        'padding-top': css_length,\n        'page-break-after': css_break,\n        'page-break-before': css_break,\n        position: ['absolute', 'fixed', 'relative', 'static'],\n        quotes: [8, css_string],\n        right: [css_length, 'auto'],\n        'table-layout': ['auto', 'fixed'],\n        'text-align': ['center', 'justify', 'left', 'right'],\n        'text-decoration': [\n            'none', 'underline', 'overline', 'line-through', 'blink'\n        ],\n        'text-indent': css_length,\n        'text-shadow': ['none', 4, [css_color, css_length]],\n        'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],\n        top: [css_length, 'auto'],\n        'unicode-bidi': ['normal', 'embed', 'bidi-override'],\n        'vertical-align': [\n            'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',\n            'text-bottom', css_length\n        ],\n        visibility: ['visible', 'hidden', 'collapse'],\n        'white-space': [\n            'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'\n        ],\n        width: [css_length, 'auto'],\n        'word-spacing': ['normal', css_length],\n        'word-wrap': ['break-word', 'normal'],\n        'z-index': ['auto', css_number]\n    };\n\n    function style_attribute() {\n        var v;\n        while (next_token.id === '*' || next_token.id === '#' ||\n                next_token.string === '_') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance();\n        }\n        if (next_token.id === '-') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance('-');\n            if (!next_token.identifier) {\n                warn('expected_nonstandard_style_attribute');\n            }\n            advance();\n            return css_any;\n        } else {\n            if (!next_token.identifier) {\n                warn('expected_style_attribute');\n            } else {\n                if (Object.prototype.hasOwnProperty.call(css_attribute_data,\n                        next_token.string)) {\n                    v = css_attribute_data[next_token.string];\n                } else {\n                    v = css_any;\n                    if (!option.css) {\n                        warn('unrecognized_style_attribute_a');\n                    }\n                }\n            }\n            advance();\n            return v;\n        }\n    }\n\n\n    function style_value(v) {\n\n        /*jslint confusion: true */\n\n        var i = 0,\n            n,\n            once,\n            match,\n            round,\n            start = 0,\n            vi;\n        switch (typeof v) {\n        case 'function':\n            return v();\n        case 'string':\n            if (next_token.identifier && next_token.string === v) {\n                advance();\n                return true;\n            }\n            return false;\n        }\n        for (;;) {\n            if (i >= v.length) {\n                return false;\n            }\n            vi = v[i];\n            i += 1;\n            if (typeof vi === 'boolean') {\n                break;\n            } else if (typeof vi === 'number') {\n                n = vi;\n                vi = v[i];\n                i += 1;\n            } else {\n                n = 1;\n            }\n            match = false;\n            while (n > 0) {\n                if (style_value(vi)) {\n                    match = true;\n                    n -= 1;\n                } else {\n                    break;\n                }\n            }\n            if (match) {\n                return true;\n            }\n        }\n        start = i;\n        once = [];\n        for (;;) {\n            round = false;\n            for (i = start; i < v.length; i += 1) {\n                if (!once[i]) {\n                    if (style_value(css_attribute_data[v[i]])) {\n                        match = true;\n                        round = true;\n                        once[i] = true;\n                        break;\n                    }\n                }\n            }\n            if (!round) {\n                return match;\n            }\n        }\n    }\n\n    function style_child() {\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.string === 'n' && next_token.identifier) {\n                no_space_only();\n                advance();\n                if (next_token.id === '+') {\n                    no_space_only();\n                    advance('+');\n                    no_space_only();\n                    advance('(number)');\n                }\n            }\n            return;\n        } else {\n            if (next_token.identifier &&\n                    (next_token.string === 'odd' || next_token.string === 'even')) {\n                advance();\n                return;\n            }\n        }\n        warn('unexpected_a');\n    }\n\n    function substyle() {\n        var v;\n        for (;;) {\n            if (next_token.id === '}' || next_token.id === '(end)' ||\n                    (xquote && next_token.id === xquote)) {\n                return;\n            }\n            v = style_attribute();\n            advance(':');\n            if (next_token.identifier && next_token.string === 'inherit') {\n                advance();\n            } else {\n                if (!style_value(v)) {\n                    warn('unexpected_a');\n                    advance();\n                }\n            }\n            if (next_token.id === '!') {\n                advance('!');\n                no_space_only();\n                if (next_token.identifier && next_token.string === 'important') {\n                    advance();\n                } else {\n                    warn('expected_a_b',\n                        next_token, 'important', artifact());\n                }\n            }\n            if (next_token.id === '}' || next_token.id === xquote) {\n                warn('expected_a_b', next_token, ';', artifact());\n            } else {\n                semicolon();\n            }\n        }\n    }\n\n    function style_selector() {\n        if (next_token.identifier) {\n            if (!Object.prototype.hasOwnProperty.call(html_tag, option.cap\n                    ? next_token.string.toLowerCase()\n                    : next_token.string)) {\n                warn('expected_tagname_a');\n            }\n            advance();\n        } else {\n            switch (next_token.id) {\n            case '>':\n            case '+':\n                advance();\n                style_selector();\n                break;\n            case ':':\n                advance(':');\n                switch (next_token.string) {\n                case 'active':\n                case 'after':\n                case 'before':\n                case 'checked':\n                case 'disabled':\n                case 'empty':\n                case 'enabled':\n                case 'first-child':\n                case 'first-letter':\n                case 'first-line':\n                case 'first-of-type':\n                case 'focus':\n                case 'hover':\n                case 'last-child':\n                case 'last-of-type':\n                case 'link':\n                case 'only-of-type':\n                case 'root':\n                case 'target':\n                case 'visited':\n                    advance_identifier(next_token.string);\n                    break;\n                case 'lang':\n                    advance_identifier('lang');\n                    advance('(');\n                    if (!next_token.identifier) {\n                        warn('expected_lang_a');\n                    }\n                    advance(')');\n                    break;\n                case 'nth-child':\n                case 'nth-last-child':\n                case 'nth-last-of-type':\n                case 'nth-of-type':\n                    advance_identifier(next_token.string);\n                    advance('(');\n                    style_child();\n                    advance(')');\n                    break;\n                case 'not':\n                    advance_identifier('not');\n                    advance('(');\n                    if (next_token.id === ':' && peek(0).string === 'not') {\n                        warn('not');\n                    }\n                    style_selector();\n                    advance(')');\n                    break;\n                default:\n                    warn('expected_pseudo_a');\n                }\n                break;\n            case '#':\n                advance('#');\n                if (!next_token.identifier) {\n                    warn('expected_id_a');\n                }\n                advance();\n                break;\n            case '*':\n                advance('*');\n                break;\n            case '.':\n                advance('.');\n                if (!next_token.identifier) {\n                    warn('expected_class_a');\n                }\n                advance();\n                break;\n            case '[':\n                advance('[');\n                if (!next_token.identifier) {\n                    warn('expected_attribute_a');\n                }\n                advance();\n                if (next_token.id === '=' || next_token.string === '~=' ||\n                        next_token.string === '$=' ||\n                        next_token.string === '|=' ||\n                        next_token.id === '*=' ||\n                        next_token.id === '^=') {\n                    advance();\n                    if (next_token.id !== '(string)') {\n                        warn('expected_string_a');\n                    }\n                    advance();\n                }\n                advance(']');\n                break;\n            default:\n                stop('expected_selector_a');\n            }\n        }\n    }\n\n    function style_pattern() {\n        if (next_token.id === '{') {\n            warn('expected_style_pattern');\n        }\n        for (;;) {\n            style_selector();\n            if (next_token.id === '</' || next_token.id === '{' ||\n                    next_token.id === '}' || next_token.id === '(end)') {\n                return '';\n            }\n            if (next_token.id === ',') {\n                comma();\n            }\n        }\n    }\n\n    function style_list() {\n        while (next_token.id !== '}' && next_token.id !== '</' &&\n                next_token.id !== '(end)') {\n            style_pattern();\n            xmode = 'styleproperty';\n            if (next_token.id === ';') {\n                semicolon();\n            } else {\n                advance('{');\n                substyle();\n                xmode = 'style';\n                advance('}');\n            }\n        }\n    }\n\n    function styles() {\n        var i;\n        while (next_token.id === '@') {\n            i = peek();\n            advance('@');\n            switch (next_token.string) {\n            case 'import':\n                advance_identifier('import');\n                if (!css_url()) {\n                    warn('expected_a_b',\n                        next_token, 'url', artifact());\n                    advance();\n                }\n                semicolon();\n                break;\n            case 'media':\n                advance_identifier('media');\n                for (;;) {\n                    if (!next_token.identifier || css_media[next_token.string] !== true) {\n                        stop('expected_media_a');\n                    }\n                    advance();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                advance('{');\n                style_list();\n                advance('}');\n                break;\n            case 'font-face':\n                advance_identifier('font-face');\n                advance('{');\n                font_face();\n                advance('}');\n                break;\n            default:\n                stop('expected_at_a');\n            }\n        }\n        style_list();\n    }\n\n\n// Parse HTML\n\n    function do_begin(n) {\n        if (n !== 'html' && !option.fragment) {\n            if (n === 'div' && option.adsafe) {\n                stop('adsafe_fragment');\n            } else {\n                stop('expected_a_b', token, 'html', n);\n            }\n        }\n        if (option.adsafe) {\n            if (n === 'html') {\n                stop('adsafe_html', token);\n            }\n            if (option.fragment) {\n                if (n !== 'div') {\n                    stop('adsafe_div', token);\n                }\n            } else {\n                stop('adsafe_fragment', token);\n            }\n        }\n        option.browser = true;\n    }\n\n    function do_attribute(a, v) {\n        var u, x;\n        if (a === 'id') {\n            u = typeof v === 'string' ? v.toUpperCase() : '';\n            if (ids[u] === true) {\n                warn('duplicate_a', next_token, v);\n            }\n            if (!/^[A-Za-z][A-Za-z0-9._:\\-]*$/.test(v)) {\n                warn('bad_id_a', next_token, v);\n            } else if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    adsafe_id = v;\n                    if (!/^[A-Z]+_$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                }\n            }\n            x = v.search(dx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'class' || a === 'type' || a === 'name') {\n            x = v.search(qx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'href' || a === 'background' ||\n                a === 'content' || a === 'data' ||\n                a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {\n            if (option.safe && ux.test(v)) {\n                stop('bad_url_a', next_token, v);\n            }\n            urls.push(v);\n        } else if (a === 'for') {\n            if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    warn('adsafe_bad_id');\n                }\n            }\n        } else if (a === 'name') {\n            if (option.adsafe && v.indexOf('_') >= 0) {\n                warn('adsafe_name_a', next_token, v);\n            }\n        }\n    }\n\n    function do_tag(name, attribute) {\n        var i, tag = html_tag[name], script, x;\n        src = false;\n        if (!tag) {\n            stop(\n                bundle.unrecognized_tag_a,\n                next_token,\n                name === name.toLowerCase()\n                    ? name\n                    : name + ' (capitalization error)'\n            );\n        }\n        if (stack.length > 0) {\n            if (name === 'html') {\n                stop('unexpected_a', token, name);\n            }\n            x = tag.parent;\n            if (x) {\n                if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {\n                    stop('tag_a_in_b', token, name, x);\n                }\n            } else if (!option.adsafe && !option.fragment) {\n                i = stack.length;\n                do {\n                    if (i <= 0) {\n                        stop('tag_a_in_b', token, name, 'body');\n                    }\n                    i -= 1;\n                } while (stack[i].name !== 'body');\n            }\n        }\n        switch (name) {\n        case 'div':\n            if (option.adsafe && stack.length === 1 && !adsafe_id) {\n                warn('adsafe_missing_id');\n            }\n            break;\n        case 'script':\n            xmode = 'script';\n            advance('>');\n            if (attribute.lang) {\n                warn('lang', token);\n            }\n            if (option.adsafe && stack.length !== 1) {\n                warn('adsafe_placement', token);\n            }\n            if (attribute.src) {\n                if (option.adsafe && (!adsafe_may || !approved[attribute.src])) {\n                    warn('adsafe_source', token);\n                }\n                if (attribute.type) {\n                    warn('type', token);\n                }\n            } else {\n                step_in(next_token.from);\n                edge();\n                use_strict();\n                adsafe_top = true;\n                script = statements();\n\n// JSLint is also the static analyzer for ADsafe. See www.ADsafe.org.\n\n                if (option.adsafe) {\n                    if (adsafe_went) {\n                        stop('adsafe_script', token);\n                    }\n                    if (script.length !== 1 ||\n                            aint(script[0],             'id',     '(') ||\n                            aint(script[0].first,       'id',     '.') ||\n                            aint(script[0].first.first, 'string', 'ADSAFE') ||\n                            aint(script[0].second[0],   'string', adsafe_id)) {\n                        stop('adsafe_id_go');\n                    }\n                    switch (script[0].first.second.string) {\n                    case 'id':\n                        if (adsafe_may || adsafe_went ||\n                                script[0].second.length !== 1) {\n                            stop('adsafe_id', next_token);\n                        }\n                        adsafe_may = true;\n                        break;\n                    case 'go':\n                        if (adsafe_went) {\n                            stop('adsafe_go');\n                        }\n                        if (script[0].second.length !== 2 ||\n                                aint(script[0].second[1], 'id', 'function') ||\n                                !script[0].second[1].first ||\n                                aint(script[0].second[1].first[0], 'string', 'dom') ||\n                                script[0].second[1].first.length > 2 ||\n                                (script[0].second[1].first.length === 2 &&\n                                aint(script[0].second[1].first[1], 'string', 'lib'))) {\n                            stop('adsafe_go', next_token);\n                        }\n                        adsafe_went = true;\n                        break;\n                    default:\n                        stop('adsafe_id_go');\n                    }\n                }\n                indent = null;\n            }\n            xmode = 'html';\n            advance('</');\n            advance_identifier('script');\n            xmode = 'outer';\n            break;\n        case 'style':\n            xmode = 'style';\n            advance('>');\n            styles();\n            xmode = 'html';\n            advance('</');\n            advance_identifier('style');\n            break;\n        case 'input':\n            switch (attribute.type) {\n            case 'button':\n            case 'checkbox':\n            case 'radio':\n            case 'reset':\n            case 'submit':\n                break;\n            case 'file':\n            case 'hidden':\n            case 'image':\n            case 'password':\n            case 'text':\n                if (option.adsafe && attribute.autocomplete !== 'off') {\n                    warn('adsafe_autocomplete');\n                }\n                break;\n            default:\n                warn('bad_type');\n            }\n            break;\n        case 'applet':\n        case 'body':\n        case 'embed':\n        case 'frame':\n        case 'frameset':\n        case 'head':\n        case 'iframe':\n        case 'noembed':\n        case 'noframes':\n        case 'object':\n        case 'param':\n            if (option.adsafe) {\n                warn('adsafe_tag', next_token, name);\n            }\n            break;\n        }\n    }\n\n\n    function closetag(name) {\n        return '</' + name + '>';\n    }\n\n    function html() {\n\n        /*jslint confusion: true */\n\n        var attribute, attributes, is_empty, name, old_white = option.white,\n            quote, tag_name, tag, wmode;\n        xmode = 'html';\n        xquote = '';\n        stack = null;\n        for (;;) {\n            switch (next_token.string) {\n            case '<':\n                xmode = 'html';\n                advance('<');\n                attributes = {};\n                tag_name = next_token;\n                name = tag_name.string;\n                advance_identifier(name);\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                tag_name.name = name;\n                if (!stack) {\n                    stack = [];\n                    do_begin(name);\n                }\n                tag = html_tag[name];\n                if (typeof tag !== 'object') {\n                    stop('unrecognized_tag_a', tag_name, name);\n                }\n                is_empty = tag.empty;\n                tag_name.type = name;\n                for (;;) {\n                    if (next_token.id === '/') {\n                        advance('/');\n                        if (next_token.id !== '>') {\n                            warn('expected_a_b', next_token, '>', artifact());\n                        }\n                        break;\n                    }\n                    if (next_token.id && next_token.id.charAt(0) === '>') {\n                        break;\n                    }\n                    if (!next_token.identifier) {\n                        if (next_token.id === '(end)' || next_token.id === '(error)') {\n                            warn('expected_a_b', next_token, '>', artifact());\n                        }\n                        warn('bad_name_a');\n                    }\n                    option.white = false;\n                    spaces();\n                    attribute = next_token.string;\n                    option.white = old_white;\n                    advance();\n                    if (!option.cap && attribute !== attribute.toLowerCase()) {\n                        warn('attribute_case_a', token);\n                    }\n                    attribute = attribute.toLowerCase();\n                    xquote = '';\n                    if (Object.prototype.hasOwnProperty.call(attributes, attribute)) {\n                        warn('duplicate_a', token, attribute);\n                    }\n                    if (attribute.slice(0, 2) === 'on') {\n                        if (!option.on) {\n                            warn('html_handlers');\n                        }\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            stop('expected_a_b', next_token, '\"', artifact());\n                        }\n                        xquote = quote;\n                        wmode = option.white;\n                        option.white = true;\n                        advance(quote);\n                        use_strict();\n                        statements();\n                        option.white = wmode;\n                        if (next_token.id !== quote) {\n                            stop('expected_a_b', next_token, quote, artifact());\n                        }\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else if (attribute === 'style') {\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            stop('expected_a_b', next_token, '\"', artifact());\n                        }\n                        xmode = 'styleproperty';\n                        xquote = quote;\n                        advance(quote);\n                        substyle();\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else {\n                        if (next_token.id === '=') {\n                            advance('=');\n                            tag = next_token.string;\n                            if (!next_token.identifier &&\n                                    next_token.id !== '\"' &&\n                                    next_token.id !== '\\'' &&\n                                    next_token.id !== '(string)' &&\n                                    next_token.id !== '(string)' &&\n                                    next_token.id !== '(color)') {\n                                warn('expected_attribute_value_a', token, attribute);\n                            }\n                            advance();\n                        } else {\n                            tag = true;\n                        }\n                    }\n                    attributes[attribute] = tag;\n                    do_attribute(attribute, tag);\n                }\n                do_tag(name, attributes);\n                if (!is_empty) {\n                    stack.push(tag_name);\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '</':\n                xmode = 'html';\n                advance('</');\n                if (!next_token.identifier) {\n                    warn('bad_name_a');\n                }\n                name = next_token.string;\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                advance();\n                if (!stack) {\n                    stop('unexpected_a', next_token, closetag(name));\n                }\n                tag_name = stack.pop();\n                if (!tag_name) {\n                    stop('unexpected_a', next_token, closetag(name));\n                }\n                if (tag_name.name !== name) {\n                    stop('expected_a_b',\n                        next_token, closetag(tag_name.name), closetag(name));\n                }\n                if (next_token.id !== '>') {\n                    stop('expected_a_b', next_token, '>', artifact());\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '<!':\n                if (option.safe) {\n                    warn('adsafe_a');\n                }\n                xmode = 'html';\n                for (;;) {\n                    advance();\n                    if (next_token.id === '>' || next_token.id === '(end)') {\n                        break;\n                    }\n                    if (next_token.string.indexOf('--') >= 0) {\n                        stop('unexpected_a', next_token, '--');\n                    }\n                    if (next_token.string.indexOf('<') >= 0) {\n                        stop('unexpected_a', next_token, '<');\n                    }\n                    if (next_token.string.indexOf('>') >= 0) {\n                        stop('unexpected_a', next_token, '>');\n                    }\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '(end)':\n                return;\n            default:\n                if (next_token.id === '(end)') {\n                    stop('missing_a', next_token,\n                        '</' + stack[stack.length - 1].string + '>');\n                } else {\n                    advance();\n                }\n            }\n            if (stack && stack.length === 0 && (option.adsafe ||\n                    !option.fragment || next_token.id === '(end)')) {\n                break;\n            }\n        }\n        if (next_token.id !== '(end)') {\n            stop('unexpected_a');\n        }\n    }\n\n\n// The actual JSLINT function itself.\n\n    itself = function JSLint(the_source, the_option) {\n\n        var i, predef, tree;\n        JSLINT.errors = [];\n        JSLINT.tree = '';\n        begin = prev_token = token = next_token =\n            Object.create(syntax['(begin)']);\n        predefined = {};\n        add_to_predefined(standard);\n        property_type = Object.create(standard_property_type);\n        if (the_option) {\n            option = Object.create(the_option);\n            predef = option.predef;\n            if (predef) {\n                if (Array.isArray(predef)) {\n                    for (i = 0; i < predef.length; i += 1) {\n                        predefined[predef[i]] = true;\n                    }\n                } else if (typeof predef === 'object') {\n                    add_to_predefined(predef);\n                }\n            }\n            do_safe();\n        } else {\n            option = {};\n        }\n        option.indent = +option.indent || 4;\n        option.maxerr = +option.maxerr || 50;\n        adsafe_id = '';\n        adsafe_may = adsafe_top = adsafe_went = false;\n        approved = {};\n        if (option.approved) {\n            for (i = 0; i < option.approved.length; i += 1) {\n                approved[option.approved[i]] = option.approved[i];\n            }\n        } else {\n            approved.test = 'test';\n        }\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        global_scope = scope = {};\n        global_funct = funct = {\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n\n        comments_off = false;\n        ids = {};\n        in_block = false;\n        indent = null;\n        json_mode = false;\n        lookahead = [];\n        member = {};\n        node_js = false;\n        prereg = true;\n        src = false;\n        stack = null;\n        strict_mode = false;\n        urls = [];\n        var_mode = null;\n        warnings = 0;\n        xmode = '';\n        lex.init(the_source);\n\n        assume();\n\n        try {\n            advance();\n            if (next_token.id === '(number)') {\n                stop('unexpected_a');\n            } else if (next_token.string.charAt(0) === '<') {\n                html();\n                if (option.adsafe && !adsafe_went) {\n                    warn('adsafe_go', this);\n                }\n            } else {\n                switch (next_token.id) {\n                case '{':\n                case '[':\n                    json_mode = true;\n                    json_value();\n                    break;\n                case '@':\n                case '*':\n                case '#':\n                case '.':\n                case ':':\n                    xmode = 'style';\n                    advance();\n                    if (token.id !== '@' || !next_token.identifier ||\n                            next_token.string !== 'charset' || token.line !== 1 ||\n                            token.from !== 1) {\n                        stop('css');\n                    }\n                    advance();\n                    if (next_token.id !== '(string)' &&\n                            next_token.string !== 'UTF-8') {\n                        stop('css');\n                    }\n                    advance();\n                    semicolon();\n                    styles();\n                    break;\n\n                default:\n                    if (option.adsafe && option.fragment) {\n                        stop('expected_a_b',\n                            next_token, '<div>', artifact());\n                    }\n\n// If the first token is a semicolon, ignore it. This is sometimes used when\n// files are intended to be appended to files that may be sloppy. A sloppy\n// file may be depending on semicolon insertion on its last line.\n\n                    step_in(1);\n                    if (next_token.id === ';' && !node_js) {\n                        semicolon();\n                    }\n                    adsafe_top = true;\n                    tree = statements();\n                    begin.first = tree;\n                    JSLINT.tree = begin;\n                    // infer_types(tree);\n                    if (option.adsafe && (tree.length !== 1 ||\n                            aint(tree[0], 'id', '(') ||\n                            aint(tree[0].first, 'id', '.') ||\n                            aint(tree[0].first.first, 'string', 'ADSAFE') ||\n                            aint(tree[0].first.second, 'string', 'lib') ||\n                            tree[0].second.length !== 2 ||\n                            tree[0].second[0].id !== '(string)' ||\n                            aint(tree[0].second[1], 'id', 'function'))) {\n                        stop('adsafe_lib');\n                    }\n                    if (tree.disrupt) {\n                        warn('weird_program', prev_token);\n                    }\n                }\n            }\n            indent = null;\n            advance('(end)');\n        } catch (e) {\n            if (e) {        // `~\n                JSLINT.errors.push({\n                    reason    : e.message,\n                    line      : e.line || next_token.line,\n                    character : e.character || next_token.from\n                }, null);\n            }\n        }\n        return JSLINT.errors.length === 0;\n    };\n\n\n// Data summary.\n\n    itself.data = function () {\n        var data = {functions: []},\n            function_data,\n            globals,\n            i,\n            j,\n            kind,\n            members = [],\n            name,\n            the_function,\n            undef = [],\n            unused = [];\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (json_mode) {\n            data.json = true;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(global_scope).filter(function (value) {\n            return value.charAt(0) !== '(' && typeof standard[value] !== 'boolean';\n        });\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            the_function = functions[i];\n            function_data = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                function_data[functionicity[j]] = [];\n            }\n            for (name in the_function) {\n                if (Object.prototype.hasOwnProperty.call(the_function, name)) {\n                    if (name.charAt(0) !== '(') {\n                        kind = the_function[name];\n                        if (kind === 'unction' || kind === 'unparam') {\n                            kind = 'unused';\n                        }\n                        if (Array.isArray(function_data[kind])) {\n                            function_data[kind].push(name);\n                            if (kind === 'unused') {\n                                unused.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            } else if (kind === 'undef') {\n                                undef.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            }\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (function_data[functionicity[j]].length === 0) {\n                    delete function_data[functionicity[j]];\n                }\n            }\n            function_data.name = the_function['(name)'];\n            function_data.params = the_function['(params)'];\n            function_data.line = the_function['(line)'];\n            data.functions.push(function_data);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n        if (undef.length > 0) {\n            data['undefined'] = undef;\n        }\n\n        members = [];\n        for (name in member) {\n            if (typeof member[name] === 'number') {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n\n    itself.report = function (errors_only) {\n        var data = itself.data(), err, evidence, i, italics, j, key, keys, length,\n            mem = '', name, names, output = [], snippets, the_function, type,\n            warning;\n\n        function detail(h, value) {\n            var comma_needed, singularity;\n            if (Array.isArray(value)) {\n                output.push('<div><i>' + h + '</i> ');\n                value.sort().forEach(function (item) {\n                    if (item !== singularity) {\n                        singularity = item;\n                        output.push((comma_needed ? ', ' : '') + singularity);\n                        comma_needed = true;\n                    }\n                });\n                output.push('</div>');\n            } else if (value) {\n                output.push('<div><i>' + h + '</i> ' + value + '</div>');\n            }\n        }\n\n        if (data.errors || data.unused || data['undefined']) {\n            err = true;\n            output.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    warning = data.errors[i];\n                    if (warning) {\n                        evidence = warning.evidence || '';\n                        output.push('<p>Problem' + (isFinite(warning.line)\n                            ? ' at line ' + String(warning.line) +\n                                ' character ' + String(warning.character)\n                            : '') +\n                            ': ' + warning.reason.entityify() +\n                            '</p><p class=evidence>' +\n                            (evidence && (evidence.length > 80\n                                ? evidence.slice(0, 77) + '...'\n                                : evidence).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data['undefined']) {\n                snippets = [];\n                for (i = 0; i < data['undefined'].length; i += 1) {\n                    snippets[i] = '<code><u>' + data['undefined'][i].name + '</u></code>&nbsp;<i>' +\n                        String(data['undefined'][i].line) + ' </i> <small>' +\n                        data['undefined'][i]['function'] + '</small>';\n                }\n                output.push('<p><i>Undefined variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.unused) {\n                snippets = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    snippets[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        String(data.unused[i].line) + ' </i> <small>' +\n                        data.unused[i]['function'] + '</small>';\n                }\n                output.push('<p><i>Unused variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.json) {\n                output.push('<p>JSON: bad.</p>');\n            }\n            output.push('</div>');\n        }\n\n        if (!errors_only) {\n\n            output.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (xmode === 'style') {\n                output.push('<p>CSS.</p>');\n            } else if (data.json && !err) {\n                output.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                output.push('<div><i>Global</i> ' +\n                    data.globals.sort().join(', ') + '</div>');\n            } else {\n                output.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                the_function = data.functions[i];\n                names = [];\n                if (the_function.params) {\n                    for (j = 0; j < the_function.params.length; j += 1) {\n                        names[j] = the_function.params[j].string;\n                    }\n                }\n                output.push('<br><div class=function><i>' +\n                    String(the_function.line) + '</i> ' +\n                    the_function.name.entityify() +\n                    '(' + names.join(', ') + ')</div>');\n                detail('<big><b>Undefined</b></big>', the_function['undefined']);\n                detail('<big><b>Unused</b></big>', the_function.unused);\n                detail('Closure', the_function.closure);\n                detail('Variable', the_function['var']);\n                detail('Exception', the_function.exception);\n                detail('Outer', the_function.outer);\n                detail('Global', the_function.global);\n                detail('Label', the_function.label);\n            }\n\n            if (data.member) {\n                keys = Object.keys(data.member);\n                if (keys.length) {\n                    keys = keys.sort();\n                    output.push('<br><pre id=properties>/*properties<br>');\n                    mem = '    ';\n                    italics = 0;\n                    j = 0;\n                    if (option.confusion) {\n                        for (i = 0; i < keys.length; i += 1) {\n                            key = keys[i];\n                            if (typeof standard_property_type[key] !== 'string') {\n                                name = ix.test(key)\n                                    ? key\n                                    : '\\'' + key.entityify().replace(nx, sanitize) + '\\'';\n                                if (data.member[key] === 1) {\n                                    name = '<i>' + name + '</i>';\n                                    italics += 1;\n                                    j = 1;\n                                }\n                                if (i < keys.length - 1) {\n                                    name += ', ';\n                                }\n                                if (mem.length + name.length - (italics * 7) > 80) {\n                                    output.push(mem + '<br>');\n                                    mem = '    ';\n                                    italics = j;\n                                }\n                                mem += name;\n                                j = 0;\n                            }\n                        }\n                    } else {\n                        for (i = 0; i < keys.length; i += 1) {\n                            key = keys[i];\n                            type = property_type[key];\n                            if (typeof type !== 'string') {\n                                type = '';\n                            }\n                            if (standard_property_type[key] !== type) {\n                                name = ix.test(key)\n                                    ? key\n                                    : '\\'' + key.entityify().replace(nx, sanitize) + '\\'';\n                                length += name.length + 2;\n                                if (data.member[key] === 1) {\n                                    name = '<i>' + name + '</i>';\n                                    italics += 1;\n                                    j = 1;\n                                }\n                                if (type) {\n                                    name += ': ' + type;\n                                }\n                                if (i < keys.length - 1) {\n                                    name += ', ';\n                                }\n                                if (mem.length + name.length - (italics * 7) > 80) {\n                                    output.push(mem + '<br>');\n                                    mem = '    ';\n                                    italics = j;\n                                }\n                                mem += name;\n                                j = 0;\n                            }\n                        }\n                    }\n                    output.push(mem + '<br>*/</pre>');\n                }\n                output.push('</div>');\n            }\n        }\n        return output.join('');\n    };\n    itself.jslint = itself;\n\n    itself.edition = '2012-01-13';\n\n    return itself;\n}());\n\ndefine(\"thirdparty/jslint/jslint\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, JSLINT, PathUtils */\n\n/**\n * Allows JSLint to run on the current document and report results in a UI panel.\n *\n */\ndefine('language/JSLintUtils',['require','exports','module','thirdparty/path-utils/path-utils.min','thirdparty/jslint/jslint','command/Commands','command/CommandManager','document/DocumentManager','preferences/PreferencesManager','utils/PerfUtils','strings','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    // Load dependent non-module scripts\n    require(\"thirdparty/path-utils/path-utils.min\");\n    require(\"thirdparty/jslint/jslint\");\n    \n    // Load dependent modules\n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        Strings                 = require(\"strings\"),\n        EditorManager           = require(\"editor/EditorManager\");\n    \n    /**\n     * @private\n     * @type {PreferenceStorage}\n     */\n    var _prefs = null;\n    \n    /**\n     * @private\n     * @type {boolean}\n     */\n    var _enabled = true;\n    \n    /**\n     * @return {boolean} Enabled state of JSLint.\n     */\n    function getEnabled() {\n        return _enabled;\n    }\n    \n    /**\n     * Run JSLint on the current document. Reports results to the main UI. Displays\n     * a gold star when no errors are found.\n     */\n    function run() {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        \n        var perfTimerDOM,\n            perfTimerLint;\n\n        var ext = currentDoc ? PathUtils.filenameExtension(currentDoc.file.fullPath) : \"\";\n        var $lintResults = $(\"#jslint-results\");\n        var $lintStatus = $(\"#lint-status\");\n        \n        if (getEnabled() && /^(\\.js|\\.htm|\\.html)$/i.test(ext)) {\n            perfTimerLint = PerfUtils.markStart(\"JSLint linting:\\t\" + (!currentDoc || currentDoc.file.fullPath));\n            var text = currentDoc.getText();\n            \n            // If a line contains only whitespace, remove the whitespace\n            // This should be doable with a regexp: text.replace(/\\r[\\x20|\\t]+\\r/g, \"\\r\\r\");,\n            // but that doesn't work.\n            var i, arr = text.split(\"\\n\");\n            for (i = 0; i < arr.length; i++) {\n                if (!arr[i].match(/\\S/)) {\n                    arr[i] = \"\";\n                }\n            }\n            text = arr.join(\"\\n\");\n            \n            var result = JSLINT(text, null);\n\n            PerfUtils.addMeasurement(perfTimerLint);\n            perfTimerDOM = PerfUtils.markStart(\"JSLint DOM:\\t\" + (!currentDoc || currentDoc.file.fullPath));\n            \n            if (!result) {\n                var $errorTable = $(\"<table class='zebra-striped condensed-table' />\")\n                                   .append(\"<tbody>\");\n                var $selectedRow;\n                \n                JSLINT.errors.forEach(function (item, i) {\n                    if (item) {\n                        var makeCell = function (content) {\n                            return $(\"<td/>\").text(content);\n                        };\n                        \n                        // Add row to error table\n                        var $row = $(\"<tr/>\")\n                            .append(makeCell(item.line))\n                            .append(makeCell(item.reason))\n                            .append(makeCell(item.evidence || \"\"))\n                            .appendTo($errorTable);\n                        \n                        $row.click(function () {\n                            if ($selectedRow) {\n                                $selectedRow.removeClass(\"selected\");\n                            }\n                            $row.addClass(\"selected\");\n                            $selectedRow = $row;\n                            \n                            var editor = EditorManager.getCurrentFullEditor();\n                            editor.setCursorPos(item.line - 1, item.character - 1);\n                            EditorManager.focusEditor();\n                        });\n                    }\n                });\n\n                $(\"#jslint-results .table-container\")\n                    .empty()\n                    .append($errorTable);\n                $lintResults.show();\n                $lintStatus.hide();\n            } else {\n                $lintResults.hide();\n                $lintStatus.show();\n            }\n\n            PerfUtils.addMeasurement(perfTimerDOM);\n\n        } else {\n            // JSLint is disabled or does not apply to the current file, hide\n            // both the results and the gold star\n            $lintResults.hide();\n            $lintStatus.hide();\n        }\n        \n        EditorManager.resizeEditor();\n    }\n    \n    /**\n     * @private\n     * Update DocumentManager listeners.\n     */\n    function _updateListeners() {\n        if (_enabled) {\n            // register our event listeners\n            $(DocumentManager)\n                .on(\"currentDocumentChange.jslint\", function () {\n                    run();\n                })\n                .on(\"documentSaved.jslint\", function (event, document) {\n                    if (document === DocumentManager.getCurrentDocument()) {\n                        run();\n                    }\n                });\n        } else {\n            $(DocumentManager).off(\".jslint\");\n        }\n    }\n    \n    function _setEnabled(enabled) {\n        _enabled = enabled;\n        \n        CommandManager.get(Commands.TOGGLE_JSLINT).setChecked(_enabled);\n        _updateListeners();\n        _prefs.setValue(\"enabled\", _enabled);\n    \n        // run immediately\n        run();\n    }\n    \n    /**\n     * Enable or disable JSLint.\n     * @param {boolean} enabled Enabled state.\n     */\n    function setEnabled(enabled) {\n        if (_enabled !== enabled) {\n            _setEnabled(enabled);\n        }\n    }\n    \n    /** Command to toggle enablement */\n    function _handleToggleJSLint() {\n        setEnabled(!getEnabled());\n    }\n    \n    \n    // Register command handlers\n    CommandManager.register(Strings.CMD_JSLINT, Commands.TOGGLE_JSLINT, _handleToggleJSLint);\n    \n    // Init PreferenceStorage\n    _prefs = PreferencesManager.getPreferenceStorage(module.id, { enabled: true });\n    _setEnabled(_prefs.getValue(\"enabled\"));\n    \n    // Define public API\n    exports.run = run;\n    exports.getEnabled = getEnabled;\n    exports.setEnabled = setEnabled;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n/*\n* Displays an auto suggest pop-up list of files to allow the user to quickly navigate to a file and lines\n* within a file.\n* Uses FileIndexManger to supply the file list.\n* \n* TODO (issue 333) - currently jquery smart auto complete is used for the pop-up list. While it mostly works\n* it has several issues, so it should be replace with an alternative. Issues:\n* - only accepts an array of strings. A list of objects is preferred to avoid some workarounds to display \n*   both the path and filename.\n* - the pop-up position logic has flaws that require CSS workarounds\n* - the pop-up properties cannot be modified once the object is constructed\n*/\n\n\ndefine('search/QuickOpen',['require','exports','module','project/FileIndexManager','document/DocumentManager','editor/EditorManager','command/CommandManager','strings','utils/StringUtils','command/Commands','project/ProjectManager'],function (require, exports, module) {\n    \n    \n    var FileIndexManager    = require(\"project/FileIndexManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Commands            = require(\"command/Commands\"),\n        ProjectManager      = require(\"project/ProjectManager\");\n    \n\n    /** @type Array.<QuickOpenPlugin> */\n    var plugins = [];\n\n    /** @type {QuickOpenPlugin} */\n    var currentPlugin = null;\n\n    /** @type Array.<FileInfo>*/\n    var fileList;\n\n    /**\n     * Remembers the current document that was displayed when showDialog() was called\n     * The current document is restored if the user presses escape\n     * @type {string} full path\n     */\n    var origDocPath;\n\n    /**\n     * Remembers the selection in the document origDocPath that was present when showDialog() was called.\n     * Focusing on an item can cause the current and and/or selection to change, so this variable restores it.\n     * The cursor position is restored if the user presses escape.\n     * @type ?{start:{line:number, ch:number}, end:{line:number, ch:number}}\n     */\n    var origSelection;\n\n    var dialogOpen = false;\n\n    /**\n     * Defines API for new QuickOpen plug-ins\n     */\n    function QuickOpenPlugin(name, fileTypes, done, search, match, itemFocus, itemSelect, resultsFormatter) {\n        \n        this.name = name;\n        this.fileTypes = fileTypes;\n        this.done = done;\n        this.search = search;\n        this.match = match;\n        this.itemFocus = itemFocus;\n        this.itemSelect = itemSelect;\n        this.resultsFormatter = resultsFormatter;\n    }\n    \n    /**\n     * Creates and registers a new QuickOpenPlugin\n     *\n     * @param { name: string, \n     *          fileTypes:Array.<string>} plugin,\n     *          done: function(),\n     *          search: function(string):Array.<string>,\n     *          match: function(string):boolean,\n     *          itemFocus: functon(HTMLLIElement),\n     *          itemSelect: functon(HTMLLIElement),\n     *          resultsFormatter: ?Functon(string, string):string }\n     *\n     * @returns {QuickOpenPlugin} plugin\n     *\n     * Parameter Documentation:\n     *\n     * name - plug-in name\n     * filetypes - file types array. Example: [\"js\", \"css\", \"txt\"]. An empty array\n     *      indicates all file types.\n     * done - called when quick open is complete. Plug-in should clear its internal state.\n     * search - takes a query string and returns an array of strings that match the query.\n     * match - takes a query string and returns true if this plug-in wants to provide\n     *      results for this query.\n     * itemFocus - performs an action when a result has focus. \n     *      The focused HTMLLIElement is passed as an argument.\n     * itemSelect - performs an action when a result is chosen.\n     *      The selected HTMLLIElement is passed as an argument.\n     * resultFormatter - takes a query string and an item string and returns \n     *      a <LI> item to insert into the displayed search results. If null, default is provided.\n     */\n    function addQuickOpenPlugin(pluginDef) {\n        plugins.push(new QuickOpenPlugin(\n            pluginDef.name,\n            pluginDef.fileTypes,\n            pluginDef.done,\n            pluginDef.search,\n            pluginDef.match,\n            pluginDef.itemFocus,\n            pluginDef.itemSelect,\n            pluginDef.resultsFormatter\n        ));\n    }\n\n    /**\n    * QuickNavigateDialog class\n    * @constructor\n    */\n    function QuickNavigateDialog() {\n        this.$searchField = undefined; // defined when showDialog() is called\n    }\n\n    /**\n     * Creates a dialog div floating on top of the current code mirror editor\n     */\n    QuickNavigateDialog.prototype._createDialogDiv = function (template) {\n        this.dialog = $(\"<div />\")\n                          .attr(\"class\", \"CodeMirror-dialog\")\n                          .html(\"<div align='right'>\" + template + \"</div>\")\n                          .prependTo($(\"#editor-holder\"));\n    };\n\n    function _filenameFromPath(path, includeExtension) {\n        var end;\n        if (includeExtension) {\n            end = path.length;\n        } else {\n            end = path.lastIndexOf(\".\");\n        }\n        return path.slice(path.lastIndexOf(\"/\") + 1, end);\n    }\n\n    /**\n     * Attempts to extract a line number from the query where the line number\n     * is followed by a colon. Callers should explicitly test result with isNaN()\n     * \n     * @param {string} query string to extract line number from\n     * @returns {number} line number. Returns NaN to indicate no line numbeer was found\n     */\n    function extractLineNumber(query) {\n        // only match : at beginning of query for now\n        // TODO: match any location of : when QuickOpen._handleItemFocus() is modified to\n        // dynamic open files\n        if (query.indexOf(\":\") !== 0) {\n            return NaN;\n        }\n\n        var result = NaN;\n        var regInfo = query.match(/(!?:)(\\d+)/); // colon followed by a digit\n        if (regInfo) {\n            result = regInfo[2] - 1;\n        }\n\n        return result;\n    }\n    \n    /**\n     * Navigates to the appropriate file and file location given the selected item \n     * and closes the dialog.\n     *\n     * Note, if selectedItem is null quick search should inspect $searchField for text\n     * that may have not matched anything in in the list, but may have information\n     * for carrying out an action.\n     */\n    QuickNavigateDialog.prototype._handleItemSelect = function (selectedItem) {\n\n        // This is a work-around to select first item when a selection event occurs\n        // (usually from pressing the enter key) and no item is selected in the list.\n        // This is a work-around since  Smart auto complete doesn't select the first item\n        if (!selectedItem) {\n            selectedItem = $(\".smart_autocomplete_container > li:first-child\").get(0);\n        }\n\n\n        // Delegate to current plugin\n        if (currentPlugin) {\n            currentPlugin.itemSelect(selectedItem);\n        } else {\n\n            // extract line number\n            var cursor,\n                query = this.$searchField.val(),\n                gotoLine = extractLineNumber(query);\n            if (!isNaN(gotoLine)) {\n                cursor = {line: gotoLine, ch: 0};\n            }\n\n            // Extract file path\n            var fullPath;\n            if (selectedItem) {\n                fullPath = decodeURIComponent($(selectedItem).attr(\"data-fullpath\"));\n            }\n\n            // Nagivate to file and line number\n            if (fullPath) {\n                CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath})\n                    .done(function () {\n                        if (!isNaN(gotoLine)) {\n                            EditorManager.getCurrentFullEditor().setCursorPos(cursor);\n                        }\n                    });\n            } else if (!isNaN(gotoLine)) {\n                EditorManager.getCurrentFullEditor().setCursorPos(cursor);\n            }\n        }\n\n\n        this._close();\n        EditorManager.focusEditor();\n    };\n\n    /**\n     * Opens the file specified by selected item if there is no current plug-in, otherwise defers handling\n     * to the currentPlugin\n     */\n    QuickNavigateDialog.prototype._handleItemFocus = function (selectedItem) {\n        if (currentPlugin) {\n            currentPlugin.itemFocus(selectedItem);\n        }\n        // TODO: Disable opening files on focus for now since this causes focus related bugs between \n        // the editor and the search field. \n        // Also, see related code in _handleItemFocus\n        /*\n        else {\n            var fullPath = $(selectedItem).attr(\"data-fullpath\");\n            if (fullPath) {\n                fullPath = decodeURIComponent(fullPath);\n                CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath, focusEditor: false});\n            }\n        }\n        */\n        \n    };\n\n    /**\n     * KeyUp is for cases that handle AFTER a character has been committed to $searchField\n     *\n     */\n    QuickNavigateDialog.prototype._handleKeyUp = function (e) {\n        var query = this.$searchField.val();\n\n        // extract line number\n        var gotoLine = extractLineNumber(query);\n        if (!isNaN(gotoLine)) {\n            var from = {line: gotoLine, ch: 0};\n            var to = {line: gotoLine, ch: 99999};\n            \n            EditorManager.getCurrentFullEditor().setSelection(from, to);\n        }\n\n        // Remove current plugin if the query stops matching\n        if (currentPlugin && !currentPlugin.match(query)) {\n            currentPlugin = null;\n        }\n\n        if ($(\".smart_autocomplete_highlight\").length === 0) {\n            this._handleItemFocus($(\".smart_autocomplete_container > li:first-child\"));\n        }\n    };\n\n    /**\n     * Close the dialog when the ENTER (13) or ESC (27) key is pressed\n     *\n     * Note, when keydown is handled $searchField does not yet have the character added\n     * for the current event e. \n     */\n    QuickNavigateDialog.prototype._handleKeyDown = function (e) {\n\n        // TODO: pass event through KeyMap.translateKeyboardEvent() to get friendly names\n        // instead of using these constants here. Note, translateKeyboardEvent() doesn't yet\n        // make friendly names for the escape and enter key.\n        var ESCKey = 27, EnterKey = 13;\n\n        // clear the query on ESC key and restore document and cursor position\n        if (e.keyCode === EnterKey || e.keyCode === ESCKey) {\n            e.stopPropagation();\n            e.preventDefault();\n\n            if (e.keyCode === ESCKey) {\n\n                // restore previously viewed doc if user navigated away from it\n                if (origDocPath) {\n                    CommandManager.execute(Commands.FILE_OPEN, {fullPath: origDocPath})\n                        .done(function () {\n                            if (origSelection) {\n                                EditorManager.getCurrentFullEditor().setSelection(origSelection.start, origSelection.end);\n                            }\n                        });\n                }\n\n                this._close();\n            }\n\n            if (e.keyCode === EnterKey) {\n                this._handleItemSelect($(\".smart_autocomplete_highlight\").get(0));\n            }\n            \n        }\n    };\n\n\n    /**\n    * Closes the search dialog and notifies all quick open plugins that\n    * searching is done. \n    */\n    QuickNavigateDialog.prototype._close = function () {\n\n        if (!dialogOpen) {\n            return;\n        }\n        dialogOpen = false;\n\n        var i;\n        for (i = 0; i < plugins.length; i++) {\n            var plugin = plugins[i];\n            plugin.done();\n        }\n\n        // Ty TODO: disabled for now while file switching is disabled in _handleItemFocus\n        //JSLintUtils.setEnabled(true);\n\n        EditorManager.focusEditor();\n\n        this.dialog.remove();\n        $(\".smart_autocomplete_container\").remove();\n\n        $(window.document).off(\"mousedown\", this.handleDocumentClick);\n    };\n    \n    function filterFileList(query) {\n        var filteredList = $.map(fileList, function (fileInfo) {\n            // match query against filename only (not the full path)\n            var path = fileInfo.fullPath;\n            var filename = _filenameFromPath(path, true);\n            if (filename.toLowerCase().indexOf(query.toLowerCase()) !== -1) {\n                return path;\n            } else {\n                return null;\n            }\n        }).sort(function (a, b) {\n            a = a.toLowerCase();\n            b = b.toLowerCase();\n            //first,  sort by filename without extension\n            var filenameA = _filenameFromPath(a, false);\n            var filenameB = _filenameFromPath(b, false);\n            if (filenameA < filenameB) {\n                return -1;\n            } else if (filenameA > filenameB) {\n                return 1;\n            } else {\n                // filename is the same, compare including extension\n                filenameA = _filenameFromPath(a, true);\n                filenameB = _filenameFromPath(b, true);\n                if (filenameA < filenameB) {\n                    return -1;\n                } else if (filenameA > filenameB) {\n                    return 1;\n                } else {\n                    return 0;\n                }\n            }\n        });\n\n        return filteredList;\n    }\n\n    function _handleFilter(query) {\n        var curDoc = DocumentManager.getCurrentDocument();\n        if (curDoc) {\n            var filename = _filenameFromPath(curDoc.file.fullPath, true);\n            var extension = filename.slice(filename.lastIndexOf(\".\") + 1, filename.length);\n\n            var i;\n            for (i = 0; i < plugins.length; i++) {\n                var plugin = plugins[i];\n                var extensionMatch = plugin.fileTypes.indexOf(extension) !== -1 || plugin.fileTypes.length === 0;\n                if (extensionMatch &&  plugin.match && plugin.match(query)) {\n                    currentPlugin = plugin;\n                    return plugin.search(query);\n                }\n            }\n        }\n\n        currentPlugin = null;\n        return filterFileList(query);\n    }\n\n    function defaultResultsFormatter(item, query) {\n        query = query.slice(query.indexOf(\"@\") + 1, query.length);\n\n        // Escape both query and item so the replace works properly below\n        query = StringUtils.htmlEscape(query);\n        item = StringUtils.htmlEscape(item);\n\n        var displayName;\n        if (query.length > 0) {\n            // make the users query bold within the item's text\n            displayName = item.replace(\n                new RegExp(StringUtils.regexEscape(query), \"gi\"),\n                \"<strong>$&</strong>\"\n            );\n        } else {\n            displayName = item;\n        }\n\n        return \"<li>\" + displayName + \"</li>\";\n    }\n\n\n\n    function _handleResultsFormatter(item) {\n        var query = $(\"input#quickOpenSearch\").val();\n\n        if (currentPlugin) {\n            // Plugins use their own formatter or the default formatter\n            var formatter = currentPlugin.resultsFormatter || defaultResultsFormatter;\n            return formatter(item, query);\n        } else {\n            // Use the filename formatter\n            query = StringUtils.htmlEscape(query);\n            var filename = StringUtils.htmlEscape(_filenameFromPath(item, true));\n            var rPath = StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(item));\n\n            var displayName;\n            if (query.length > 0) {\n                // make the users query bold within the item's text\n                displayName = filename.replace(\n                    new RegExp(StringUtils.regexEscape(query), \"gi\"),\n                    \"<strong>$&</strong>\"\n                );\n            } else {\n                displayName = filename;\n            }\n\n            return \"<li data-fullpath='\" + encodeURIComponent(item) + \"'>\" + displayName +\n                \"<br /><span class='quick-open-path'>\" + rPath + \"</span></li>\";\n        }\n    }\n\n\n    function setSearchFieldValue(prefix, initialString) {\n        prefix = prefix || \"\";\n        initialString = initialString || \"\";\n        initialString = prefix + initialString;\n\n        \n        var $field = $(\"input#quickOpenSearch\");\n        if ($field) {\n            $field.val(initialString);\n            $field.get(0).setSelectionRange(prefix.length, initialString.length);\n        }\n    }\n    \n    /**\n     * Close the dialog when the user clicks outside of it. Note, auto smart complete has a \"lostFocus\" event that is\n     * supposed to capture this event, but it also gets triggered on keyUp which doesn't work for quick find.\n     */\n    QuickNavigateDialog.prototype.handleDocumentClick = function (e) {\n        if ($(this.dialog).find(e.target).length === 0 && $(\".smart_autocomplete_container\").find(e.target).length === 0) {\n            this._close();\n        }\n    };\n\n    /**\n    * Shows the search dialog and initializes the auto suggestion list with filenames from the current project\n    */\n    QuickNavigateDialog.prototype.showDialog = function (prefix, initialString) {\n        var that = this;\n\n        if (dialogOpen) {\n            return;\n        }\n        dialogOpen = true;\n\n        this.handleDocumentClick = this.handleDocumentClick.bind(this);\n        $(window.document).on(\"mousedown\", this.handleDocumentClick);\n\n\n        // Ty TODO: disabled for now while file switching is disabled in _handleItemFocus\n        // To improve performance during list selection disable JSLint until a document is chosen or dialog is closed\n        //JSLintUtils.setEnabled(false);\n\n        var curDoc = DocumentManager.getCurrentDocument();\n        origDocPath = curDoc ? curDoc.file.fullPath : null;\n        if (curDoc) {\n            origSelection = EditorManager.getCurrentFullEditor().getSelection();\n        } else {\n            origSelection = null;\n        }\n\n        // Get the file list and initialize the smart auto completes\n        FileIndexManager.getFileInfoList(\"all\")\n            .done(function (files) {\n                fileList = files;\n                var dialogHTML = Strings.CMD_QUICK_OPEN + \": <input type='text' autocomplete='off' id='quickOpenSearch' style='width: 30em'>\";\n                that._createDialogDiv(dialogHTML);\n                that.$searchField = $(\"input#quickOpenSearch\");\n\n\n                that.$searchField.smartAutoComplete({\n                    source: files,\n                    maxResults: 20,\n                    minCharLimit: 0,\n                    autocompleteFocused: true,\n                    forceSelect: false,\n                    typeAhead: false,   // won't work right now because smart auto complete \n                                        // using internal raw results instead of filtered results for matching\n                    filter: _handleFilter,\n                    resultFormatter: _handleResultsFormatter\n                });\n        \n                that.$searchField.bind({\n                    itemSelect: function (e, selectedItem) { that._handleItemSelect(selectedItem); },\n                    itemFocus: function (e, selectedItem) { that._handleItemFocus(selectedItem); },\n                    keydown: function (e) { that._handleKeyDown(e); },\n                    keyup: function (e, query) { that._handleKeyUp(e); }\n                    // Note: lostFocus event DOESN'T work because auto smart complete catches the key up from shift-command-o and immediately\n                    // triggers lostFocus\n                });\n        \n                setSearchFieldValue(prefix, initialString);\n            });\n    };\n\n    function getCurrentEditorSelectedText() {\n        var currentEditor = EditorManager.getFocusedEditor();\n        return (currentEditor && currentEditor.getSelectedText()) || \"\";\n    }\n\n    function doSearch(prefix, initialString) {\n        if (dialogOpen) {\n            setSearchFieldValue(prefix, initialString);\n        } else {\n            var dialog = new QuickNavigateDialog();\n            dialog.showDialog(prefix, initialString);\n        }\n    }\n\n    function doFileSearch() {\n        doSearch(\"\", getCurrentEditorSelectedText());\n    }\n\n    function doGotoLine() {\n        // TODO: Brackets doesn't support disabled menu items right now, when it does goto line and\n        // goto definition should be disabled when there is not a current document\n        if (DocumentManager.getCurrentDocument()) {\n            doSearch(\":\", \"\");\n        }\n    }\n\n\n    // TODO: should provide a way for QuickOpenJSSymbol to create this function as a plug-in\n    function doDefinitionSearch() {\n        if (DocumentManager.getCurrentDocument()) {\n            doSearch(\"@\", getCurrentEditorSelectedText());\n        }\n    }\n\n\n\n    // TODO: allow QuickOpenJS to register it's own commands and key bindings\n    CommandManager.register(Strings.CMD_QUICK_OPEN,         Commands.NAVIGATE_QUICK_OPEN,       doFileSearch);\n    CommandManager.register(Strings.CMD_GOTO_DEFINITION,    Commands.NAVIGATE_GOTO_DEFINITION,  doDefinitionSearch);\n    CommandManager.register(Strings.CMD_GOTO_LINE,          Commands.NAVIGATE_GOTO_LINE,        doGotoLine);\n\n    exports.addQuickOpenPlugin = addQuickOpenPlugin;\n});\n\n/**\n * @license RequireJS text 1.0.8 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n/*jslint regexp: true, plusplus: true, sloppy: true */\n/*global require: false, XMLHttpRequest: false, ActiveXObject: false,\n  define: false, window: false, process: false, Packages: false,\n  java: false, location: false */\n\n(function () {\n    var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        hasLocation = typeof location !== 'undefined' && location.href,\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\n        defaultHostName = hasLocation && location.hostname,\n        defaultPort = hasLocation && (location.port || undefined),\n        buildMap = [];\n\n    define('text',[],function () {\n        var text, fs;\n\n        text = {\n            version: '1.0.8',\n\n            strip: function (content) {\n                //Strips <?xml ...?> declarations so that external SVG and XML\n                //documents can be added to a document without worry. Also, if the string\n                //is an HTML document, only the part inside the body tag is returned.\n                if (content) {\n                    content = content.replace(xmlRegExp, \"\");\n                    var matches = content.match(bodyRegExp);\n                    if (matches) {\n                        content = matches[1];\n                    }\n                } else {\n                    content = \"\";\n                }\n                return content;\n            },\n\n            jsEscape: function (content) {\n                return content.replace(/(['\\\\])/g, '\\\\$1')\n                    .replace(/[\\f]/g, \"\\\\f\")\n                    .replace(/[\\b]/g, \"\\\\b\")\n                    .replace(/[\\n]/g, \"\\\\n\")\n                    .replace(/[\\t]/g, \"\\\\t\")\n                    .replace(/[\\r]/g, \"\\\\r\");\n            },\n\n            createXhr: function () {\n                //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n                var xhr, i, progId;\n                if (typeof XMLHttpRequest !== \"undefined\") {\n                    return new XMLHttpRequest();\n                } else if (typeof ActiveXObject !== \"undefined\") {\n                    for (i = 0; i < 3; i++) {\n                        progId = progIds[i];\n                        try {\n                            xhr = new ActiveXObject(progId);\n                        } catch (e) {}\n\n                        if (xhr) {\n                            progIds = [progId];  // so faster next time\n                            break;\n                        }\n                    }\n                }\n\n                return xhr;\n            },\n\n            /**\n             * Parses a resource name into its component parts. Resource names\n             * look like: module/name.ext!strip, where the !strip part is\n             * optional.\n             * @param {String} name the resource name\n             * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\n             * where strip is a boolean.\n             */\n            parseName: function (name) {\n                var strip = false, index = name.indexOf(\".\"),\n                    modName = name.substring(0, index),\n                    ext = name.substring(index + 1, name.length);\n\n                index = ext.indexOf(\"!\");\n                if (index !== -1) {\n                    //Pull off the strip arg.\n                    strip = ext.substring(index + 1, ext.length);\n                    strip = strip === \"strip\";\n                    ext = ext.substring(0, index);\n                }\n\n                return {\n                    moduleName: modName,\n                    ext: ext,\n                    strip: strip\n                };\n            },\n\n            xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\n\n            /**\n             * Is an URL on another domain. Only works for browser use, returns\n             * false in non-browser environments. Only used to know if an\n             * optimized .js version of a text resource should be loaded\n             * instead.\n             * @param {String} url\n             * @returns Boolean\n             */\n            useXhr: function (url, protocol, hostname, port) {\n                var match = text.xdRegExp.exec(url),\n                    uProtocol, uHostName, uPort;\n                if (!match) {\n                    return true;\n                }\n                uProtocol = match[2];\n                uHostName = match[3];\n\n                uHostName = uHostName.split(':');\n                uPort = uHostName[1];\n                uHostName = uHostName[0];\n\n                return (!uProtocol || uProtocol === protocol) &&\n                       (!uHostName || uHostName === hostname) &&\n                       ((!uPort && !uHostName) || uPort === port);\n            },\n\n            finishLoad: function (name, strip, content, onLoad, config) {\n                content = strip ? text.strip(content) : content;\n                if (config.isBuild) {\n                    buildMap[name] = content;\n                }\n                onLoad(content);\n            },\n\n            load: function (name, req, onLoad, config) {\n                //Name has format: some.module.filext!strip\n                //The strip part is optional.\n                //if strip is present, then that means only get the string contents\n                //inside a body tag in an HTML string. For XML/SVG content it means\n                //removing the <?xml ...?> declarations so the content can be inserted\n                //into the current doc without problems.\n\n                // Do not bother with the work if a build and text will\n                // not be inlined.\n                if (config.isBuild && !config.inlineText) {\n                    onLoad();\n                    return;\n                }\n\n                var parsed = text.parseName(name),\n                    nonStripName = parsed.moduleName + '.' + parsed.ext,\n                    url = req.toUrl(nonStripName),\n                    useXhr = (config && config.text && config.text.useXhr) ||\n                             text.useXhr;\n\n                //Load the text. Use XHR if possible and in a browser.\n                if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\n                    text.get(url, function (content) {\n                        text.finishLoad(name, parsed.strip, content, onLoad, config);\n                    });\n                } else {\n                    //Need to fetch the resource across domains. Assume\n                    //the resource has been optimized into a JS module. Fetch\n                    //by the module name + extension, but do not include the\n                    //!strip part to avoid file system issues.\n                    req([nonStripName], function (content) {\n                        text.finishLoad(parsed.moduleName + '.' + parsed.ext,\n                                        parsed.strip, content, onLoad, config);\n                    });\n                }\n            },\n\n            write: function (pluginName, moduleName, write, config) {\n                if (buildMap.hasOwnProperty(moduleName)) {\n                    var content = text.jsEscape(buildMap[moduleName]);\n                    write.asModule(pluginName + \"!\" + moduleName,\n                                   \"define(function () { return '\" +\n                                       content +\n                                   \"';});\\n\");\n                }\n            },\n\n            writeFile: function (pluginName, moduleName, req, write, config) {\n                var parsed = text.parseName(moduleName),\n                    nonStripName = parsed.moduleName + '.' + parsed.ext,\n                    //Use a '.js' file name so that it indicates it is a\n                    //script that can be loaded across domains.\n                    fileName = req.toUrl(parsed.moduleName + '.' +\n                                         parsed.ext) + '.js';\n\n                //Leverage own load() method to load plugin value, but only\n                //write out values that do not have the strip argument,\n                //to avoid any potential issues with ! in file names.\n                text.load(nonStripName, req, function (value) {\n                    //Use own write() method to construct full module value.\n                    //But need to create shell that translates writeFile's\n                    //write() to the right interface.\n                    var textWrite = function (contents) {\n                        return write(fileName, contents);\n                    };\n                    textWrite.asModule = function (moduleName, contents) {\n                        return write.asModule(moduleName, fileName, contents);\n                    };\n\n                    text.write(pluginName, nonStripName, textWrite, config);\n                }, config);\n            }\n        };\n\n        if (text.createXhr()) {\n            text.get = function (url, callback) {\n                var xhr = text.createXhr();\n                xhr.open('GET', url, true);\n                xhr.onreadystatechange = function (evt) {\n                    //Do not explicitly handle errors, those should be\n                    //visible via console output in the browser.\n                    if (xhr.readyState === 4) {\n                        callback(xhr.responseText);\n                    }\n                };\n                xhr.send(null);\n            };\n        } else if (typeof process !== \"undefined\" &&\n                 process.versions &&\n                 !!process.versions.node) {\n            //Using special require.nodeRequire, something added by r.js.\n            fs = require.nodeRequire('fs');\n\n            text.get = function (url, callback) {\n                var file = fs.readFileSync(url, 'utf8');\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\n                if (file.indexOf('\\uFEFF') === 0) {\n                    file = file.substring(1);\n                }\n                callback(file);\n            };\n        } else if (typeof Packages !== 'undefined') {\n            //Why Java, why is this so awkward?\n            text.get = function (url, callback) {\n                var encoding = \"utf-8\",\n                    file = new java.io.File(url),\n                    lineSeparator = java.lang.System.getProperty(\"line.separator\"),\n                    input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\n                    stringBuffer, line,\n                    content = '';\n                try {\n                    stringBuffer = new java.lang.StringBuffer();\n                    line = input.readLine();\n\n                    // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\n                    // http://www.unicode.org/faq/utf_bom.html\n\n                    // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\n                    // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\n                    if (line && line.length() && line.charAt(0) === 0xfeff) {\n                        // Eat the BOM, since we've already found the encoding on this file,\n                        // and we plan to concatenating this buffer with others; the BOM should\n                        // only appear at the top of a file.\n                        line = line.substring(1);\n                    }\n\n                    stringBuffer.append(line);\n\n                    while ((line = input.readLine()) !== null) {\n                        stringBuffer.append(lineSeparator);\n                        stringBuffer.append(line);\n                    }\n                    //Make sure we return a JavaScript string and not a Java string.\n                    content = String(stringBuffer.toString()); //String\n                } finally {\n                    input.close();\n                }\n                callback(content);\n            };\n        }\n\n        return text;\n    });\n}());\n\ndefine('text!htmlContent/main-view.html',[],function () { return '<!-- \\n  Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\\n   \\n  Permission is hereby granted, free of charge, to any person obtaining a\\n  copy of this software and associated documentation files (the \"Software\"), \\n  to deal in the Software without restriction, including without limitation \\n  the rights to use, copy, modify, merge, publish, distribute, sublicense, \\n  and/or sell copies of the Software, and to permit persons to whom the \\n  Software is furnished to do so, subject to the following conditions:\\n   \\n  The above copyright notice and this permission notice shall be included in\\n  all copies or substantial portions of the Software.\\n   \\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \\n  DEALINGS IN THE SOFTWARE.\\n-->\\n\\n\\n<!--\\n    This is the HTML for the body tag of index.html. It is loaded dynamically by the \\n    htmlContentLoad module and localized using a combination of mustache.js and i18n.js.\\n\\n    LOCALIZATION NOTE:\\n    All display text for this file must use templating so the text can be localized.\\n    \\n    English text goes in src/nls/root/strings.js. All other translations go in the strings.js file for\\n    the specific local in the nls folder. If a translation is missing for a specific key English\\n    is used as a fallback\\n\\n    Strings should be referenced using the double brackets syntax.\\n    Example: {{keyname}}. Note, all strings are HTML escaped unless the form \\n    {{&keyname}} is used.\\n\\n-->\\n\\n<!-- Main UI -->\\n    <div class=\"main-view\">\\n        <div id=\"sidebar-resizer\"></div>\\n        <div id=\"sidebar\" class=\"sidebar quiet-scrollbars\">\\n            <!-- Left-hand \\'Project panel\\' -->\\n            <div id=\"projects\" class=\"panel\">\\n                <div id=\"project-header\"></div>\\n                <div id=\"file-section\">\\n                    <div id=\"open-files-container\">\\n                        <!-- This will contain a dynamically generated <ul> at runtime -->\\n                        <ul>\\n                        </ul>\\n                    </div>\\n                \\n                    <div id=\"project-files-header\" class=\"project-file-header-area\">\\n                        <span id=\"project-title\" class=\"title\"></span>\\n                    </div>\\n                    <div id=\"project-files-container\">\\n                    <!-- This will contain a dynamically generated <ul> hierarchy at runtime -->\\n                    </div>\\n                </div>\\n            </div>\\n        </div>\\n        \\n        <!-- Right-hand content: toolbar, editor, bottom panels -->\\n        <div class=\"content\">\\n            <!-- Toolbar containing menus, filename, and icons -->\\n            <div id=\"main-toolbar\" class=\"toolbar\">\\n                <!-- Menu bar -->\\n                <ul class=\"nav\" data-dropdown=\"dropdown\">\\n                </ul>\\n                \\n                <!-- Toolbar -->\\n                <div class=\"buttons\">\\n                    <span id=\"update-notification\" title=\"{{UPDATE_NOTIFICATION_TOOLTIP}}\"></span>\\n\\n                    <span class=\"experimental-label\">{{EXPERIMENTAL_BUILD}}</span>\\n                    \\n                    <a href=\"#\" id=\"toolbar-go-live\"></a> <!-- tooltip for this is set in JS -->\\n                    \\n                    <span id=\"gold-star\" title=\"No JSLint errors - good job!\">\\n                        &#9733;\\n                    </span>\\n                </div>\\n                \\n                <!-- Filename label -->\\n                <div class=\"title-wrapper\">\\n                    <span class=\"title\"></span>&nbsp;<span class=\\'dirty-dot\\' style=\"visibility:hidden;\">•</span>\\n                </div>\\n            </div>\\n            \\n            <div id=\"editor-holder\">\\n                <div id=\"not-editor\">\\n                    <div id=\"not-editor-content\">[&nbsp;&nbsp;]</div>\\n                </div>\\n            </div>\\n            \\n            <div id=\"jslint-results\" class=\"bottom-panel\">\\n                <div class=\"toolbar simple-toolbar-layout\">\\n                    <div class=\"title\">{{JSLINT_ERRORS}}</div>\\n                </div>\\n                <div class=\"table-container\"></div>\\n            </div>\\n            <div id=\"search-results\" class=\"bottom-panel\">\\n                <div class=\"toolbar simple-toolbar-layout\">\\n                    <div class=\"title\">{{SEARCH_RESULTS}}</div>\\n                    <div class=\"title\" id=\"search-result-summary\"></div>\\n                    <a href=\"#\" class=\"close\">&times;</a>\\n                </div>\\n                <div class=\"table-container\"></div>\\n            </div>\\n        </div>\\n    </div>\\n\\n    <!-- Modal Windows -->\\n    <div class=\"error-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <a href=\"#\" class=\"close\">&times;</a>\\n            <h1 class=\"dialog-title\">Error</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{OK}}</a>\\n        </div>\\n    </div>\\n    <div class=\"save-close-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <a href=\"#\" class=\"close\">&times;</a>\\n            <h1 class=\"dialog-title\">{{SAVE_CHANGES}}</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"dontsave\">{{DONT_SAVE}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{SAVE}}</a>\\n            <a href=\"#\" class=\"dialog-button btn\" data-button-id=\"cancel\">{{CANCEL}}</a>\\n        </div>\\n    </div>\\n    <div class=\"ext-changed-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">Title goes here</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"dontsave\">{{RELOAD_FROM_DISK}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"cancel\">{{KEEP_CHANGES_IN_EDITOR}}</a>\\n        </div>\\n    </div>\\n    <div class=\"ext-deleted-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">Title goes here</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"dontsave\">{{CLOSE_DONT_SAVE}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"cancel\">{{KEEP_CHANGES_IN_EDITOR}}</a>\\n        </div>\\n    </div>\\n    <div class=\"live-development-error-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">Title goes here</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"cancel\">{{CANCEL}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{RELAUNCH_CHROME}}</a>\\n        </div>\\n    </div>\\n    <div class=\"about-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">{{ABOUT}}</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <img class=\"about-icon\" src=\"styles/images/brackets_icon.svg\">\\n            <div class=\"about-text\">\\n                <h2>{{BRACKETS}}</h2>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE1}} <span id=\"about-build-number\"><!-- populated programmatically --></span></p>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE2}}</p>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE3}}<span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span>{{ABOUT_TEXT_LINE4}}</p>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE5}}<span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span></p>\\n            </div>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{CLOSE}}</a>\\n        </div>\\n    </div>\\n    <div class=\"update-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">{{UPDATE_AVAILABLE_TITLE}}</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <img class=\"update-icon\" src=\"styles/images/update_large_icon.svg\">\\n            <div class=\"update-text\">\\n                <p class=\"dialog-message\">{{UPDATE_MESSAGE}}</p>\\n                <div class=\"update-info\">\\n                </div>\\n            </div>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"cancel\">{{CANCEL}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"download\">{{GET_IT_NOW}}</a>\\n        </div>\\n    </div>\\n    <div id=\"context-menu-bar\">\\n        <ul data-dropdown=\"dropdown\"></ul>\\n    </div>\\n    <div id=\"codehint-menu-bar\">\\n        <ul data-dropdown=\"dropdown\"></ul>\\n    </div>';});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, brackets, window */\n\n/**\n * ExtensionLoader searches the filesystem for extensions, then creates a new context for each one and loads it\n */\n\ndefine('utils/ExtensionLoader',['require','exports','module','file/NativeFileSystem','file/FileUtils','utils/Async'],function (require, exports, module) {\n    \n\n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        FileUtils           = require(\"file/FileUtils\"),\n        Async               = require(\"utils/Async\"),\n        contexts            = {};\n    /**\n     * Returns the require.js require context used to load an extension\n     *\n     * @param {!string} name, used to identify the extension\n     * @return {!Object} A require.js require object used to load the extension, or undefined if \n     * there is no require object ith that name\n     */\n    function getRequireContextForExtension(name) {\n        return contexts[name];\n    }\n\n    \n    /**\n     * Loads the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!string} baseUrl, URL path relative to index.html, where the main JS file can be found\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when the extension is loaded.\n     */\n    function loadExtension(name, config, entryPoint) {\n        var result = new $.Deferred(),\n            extensionRequire = brackets.libRequire.config({\n                context: name,\n                baseUrl: config.baseUrl,\n                /* FIXME (issue #1087): can we pass this from the global require context instead of hardcoding twice? */\n                paths: {\n                    \"text\" : \"../../../thirdparty/text\",\n                    \"i18n\" : \"../../../thirdparty/i18n\"\n                },\n                locale: window.localStorage.getItem(\"locale\") || brackets.app.language\n            });\n        contexts[name] = extensionRequire;\n\n        console.log(\"[Extension] starting to load \" + config.baseUrl);\n        \n        extensionRequire([entryPoint], function () {\n            console.log(\"[Extension] finished loading \" + config.baseUrl);\n            result.resolve();\n        });\n        \n        return result.promise();\n    }\n\n    /**\n     * Runs unit tests for the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!string} baseUrl, URL path relative to index.html, where the main JS file can be found\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function testExtension(name, config, entryPoint) {\n        var result = new $.Deferred(),\n            extensionPath = FileUtils.getNativeBracketsDirectoryPath();\n        \n        // Assumes the caller's window.location context is /test/SpecRunner.html\n        extensionPath = extensionPath.replace(\"brackets/test\", \"brackets/src\"); // convert from \"test\" to \"src\"\n        extensionPath += \"/\" + config.baseUrl + \"/\" + entryPoint + \".js\";\n\n        var fileExists = false, statComplete = false;\n        brackets.fs.stat(extensionPath, function (err, stat) {\n            statComplete = true;\n            if (err === brackets.fs.NO_ERROR && stat.isFile()) {\n                // unit test file exists\n                var extensionRequire = brackets.libRequire.config({\n                    context: name,\n                    baseUrl: \"../src/\" + config.baseUrl,\n                    paths: config.paths\n                });\n    \n                console.log(\"[Extension] loading unit test \" + config.baseUrl);\n                extensionRequire([entryPoint], function () {\n                    console.log(\"[Extension] loaded unit tests \" + config.baseUrl);\n                    result.resolve();\n                });\n            } else {\n                result.reject();\n            }\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Loads a file entryPoint from each extension folder within the baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!string} baseUrl, URL path relative to index.html that maps to the same place as directory\n     * @param {!string} entryPoint Module name to load (without .js suffix)\n     * @param {function} processExtension \n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function _loadAll(directory, config, entryPoint, processExtension) {\n        var result = new $.Deferred();\n        \n        NativeFileSystem.requestNativeFileSystem(directory,\n            function (rootEntry) {\n                rootEntry.createReader().readEntries(\n                    function (entries) {\n                        var i,\n                            extensions = [];\n                        \n                        for (i = 0; i < entries.length; i++) {\n                            if (entries[i].isDirectory) {\n                                // FUTURE (JRB): read package.json instead of just using the entrypoint \"main\".\n                                // Also, load sub-extensions defined in package.json.\n                                extensions.push(entries[i].name);\n                            }\n                        }\n\n                        if (extensions.length === 0) {\n                            result.resolve();\n                            return;\n                        }\n                        \n                        Async.doInParallel(extensions, function (item) {\n                            var extConfig = {\n                                baseUrl: config.baseUrl + \"/\" + item,\n                                paths: config.paths\n                            };\n                            return processExtension(item, extConfig, entryPoint);\n                        }).always(function () {\n                            // Always resolve the promise even when the extension entry point is missing\n                            result.resolve();\n                        });\n                    },\n                    function (error) {\n                        console.log(\"[Extension] Error -- could not read native directory: \" + directory);\n                    }\n                );\n            },\n            function (error) {\n                console.log(\"[Extension] Error -- could not open native directory: \" + directory);\n            });\n        \n        return result.promise();\n    }\n    \n    /**\n     * Loads the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!string} baseUrl, URL path relative to index.html that maps to the same place as directory\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function loadAllExtensionsInNativeDirectory(directory, baseUrl) {\n        return _loadAll(directory, {baseUrl: baseUrl}, \"main\", loadExtension);\n    }\n    \n    /**\n     * Runs unit test for the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!string} baseUrl, URL path relative to index.html that maps to the same place as directory\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function testAllExtensionsInNativeDirectory(directory, baseUrl) {\n        var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(),\n            config = {\n                baseUrl: baseUrl\n            };\n        \n        config.paths = {\n            \"perf\": bracketsPath + \"/perf\",\n            \"spec\": bracketsPath + \"/spec\"\n        };\n        \n        return _loadAll(directory, config, \"unittests\", testExtension);\n    }\n    \n    exports.getRequireContextForExtension = getRequireContextForExtension;\n    exports.loadExtension = loadExtension;\n    exports.testExtension = testExtension;\n    exports.loadAllExtensionsInNativeDirectory = loadAllExtensionsInNativeDirectory;\n    exports.testAllExtensionsInNativeDirectory = testAllExtensionsInNativeDirectory;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, document, window, brackets  */\n\ndefine('project/SidebarView',['require','exports','module','project/ProjectManager','project/WorkingSetView','command/CommandManager','command/Commands','strings','preferences/PreferencesManager','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    var ProjectManager          = require(\"project/ProjectManager\"),\n        WorkingSetView          = require(\"project/WorkingSetView\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Commands                = require(\"command/Commands\"),\n        Strings                 = require(\"strings\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\"),\n        EditorManager           = require(\"editor/EditorManager\");\n\n    var isSidebarClosed         = false;\n\n    var PREFERENCES_CLIENT_ID = \"com.adobe.brackets.SidebarView\",\n        defaultPrefs = { sidebarWidth: 200, sidebarClosed: false };\n\n    // These vars are initialized by the htmlContentLoadComplete handler\n    // below since they refer to DOM elements\n    var $sidebar,\n        $sidebarMenuText,\n        $sidebarResizer,\n        $openFilesContainer,\n        $projectTitle,\n        $projectFilesContainer;\n    \n    /**\n     * @private\n     * Update project title when the project root changes\n     */\n    function _updateProjectTitle() {\n        $projectTitle.html(ProjectManager.getProjectRoot().name);\n        $projectTitle.attr(\"title\", ProjectManager.getProjectRoot().fullPath);\n    }\n    \n    /**\n     * @private\n     * Sets sidebar width and resizes editor. Does not change internal sidebar open/closed state.\n     * @param {number} width Optional width in pixels. If null or undefined, the default width is used.\n     * @param {!boolean} updateMenu Updates \"View\" menu label to indicate current sidebar state.\n     * @param {!boolean} displayTriangle Display selection marker triangle in the active view.\n     */\n    function _setWidth(width, updateMenu, displayTriangle) {\n        // if we specify a width with the handler call, use that. Otherwise use\n        // the greater of the current width or 200 (200 is the minimum width we'd snap back to)\n        \n        var prefs                   = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),\n            sidebarWidth            = Math.max(prefs.getValue(\"sidebarWidth\"), 10);\n        \n        width = width || Math.max($sidebar.width(), sidebarWidth);\n        \n        if (typeof displayTriangle === \"boolean\") {\n            var display = (displayTriangle) ? \"block\" : \"none\";\n            $sidebar.find(\".sidebar-selection-triangle\").css(\"display\", display);\n        }\n        \n        if (isSidebarClosed) {\n            $sidebarResizer.css(\"left\", 0);\n        } else {\n            $sidebar.width(width);\n            $sidebarResizer.css(\"left\", width - 1);\n            \n            // the following three lines help resize things when the sidebar shows\n            // but ultimately these should go into ProjectManager.js with a \"notify\" \n            // event that we can just call from anywhere instead of hard-coding it.\n            // waiting on a ProjectManager refactor to add that. \n            $sidebar.find(\".sidebar-selection\").width(width);\n            \n            if (width > 10) {\n                prefs.setValue(\"sidebarWidth\", width);\n            }\n        }\n        \n        if (updateMenu) {\n            var text = (isSidebarClosed) ? Strings.CMD_SHOW_SIDEBAR : Strings.CMD_HIDE_SIDEBAR;\n            CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(text);\n        }\n        EditorManager.resizeEditor();\n    }\n    \n    /**\n     * Toggle sidebar visibility.\n     */\n    function toggleSidebar(width) {\n        if (isSidebarClosed) {\n            $sidebar.show();\n        } else {\n            $sidebar.hide();\n        }\n        \n        isSidebarClosed = !isSidebarClosed;\n        \n        var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs);\n        prefs.setValue(\"sidebarClosed\", isSidebarClosed);\n        _setWidth(width, true, !isSidebarClosed);\n    }\n    \n    /**\n     * @private\n     * Install sidebar resize handling.\n     */\n    function _initSidebarResizer() {\n        var $mainView               = $(\".main-view\"),\n            $body                   = $(document.body),\n            prefs                   = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),\n            sidebarWidth            = prefs.getValue(\"sidebarWidth\"),\n            startingSidebarPosition = sidebarWidth,\n            animationRequest        = null,\n            isMouseDown             = false;\n        \n        $sidebarResizer.css(\"left\", sidebarWidth - 1);\n        \n        if (prefs.getValue(\"sidebarClosed\")) {\n            toggleSidebar(sidebarWidth);\n        } else {\n            _setWidth(sidebarWidth, true, true);\n        }\n        \n        $sidebarResizer.on(\"dblclick\", function () {\n            if ($sidebar.width() < 10) {\n                //mousedown is fired first. Sidebar is already toggeled open to at least 10px.\n                _setWidth(null, true, true);\n                $projectFilesContainer.triggerHandler(\"scroll\");\n                $openFilesContainer.triggerHandler(\"scroll\");\n            } else {\n                toggleSidebar(sidebarWidth);\n            }\n        });\n        $sidebarResizer.on(\"mousedown.sidebar\", function (e) {\n            var startX = e.clientX,\n                newWidth = Math.max(e.clientX, 0),\n                doResize = true;\n            \n            isMouseDown = true;\n\n            // take away the shadows (for performance reasons during sidebarmovement)\n            $sidebar.find(\".scroller-shadow\").css(\"display\", \"none\");\n            \n            $body.toggleClass(\"resizing\");\n            \n            // check to see if we're currently in hidden mode\n            if (isSidebarClosed) {\n                toggleSidebar(1);\n            }\n                        \n            \n            animationRequest = window.webkitRequestAnimationFrame(function doRedraw() {\n                // only run this if the mouse is down so we don't constantly loop even \n                // after we're done resizing.\n                if (!isMouseDown) {\n                    return;\n                }\n                    \n                // if we've gone below 10 pixels on a mouse move, and the\n                // sidebar is shrinking, hide the sidebar automatically an\n                // unbind the mouse event. \n                if ((startX > 10) && (newWidth < 10)) {\n                    toggleSidebar(startingSidebarPosition);\n                    $mainView.off(\"mousemove.sidebar\");\n                        \n                    // turn off the mouseup event so that it doesn't fire twice and retoggle the \n                    // resizing class\n                    $mainView.off(\"mouseup.sidebar\");\n                    $body.toggleClass(\"resizing\");\n                    doResize = false;\n                    startX = 0;\n                        \n                    // force isMouseDown so that we don't keep calling requestAnimationFrame\n                    // this keeps the sidebar from stuttering\n                    isMouseDown = false;\n                        \n                }\n                \n                if (doResize) {\n                    // for right now, displayTriangle is always going to be false for _setWidth\n                    // because we want to hide it when we move, and _setWidth only gets called\n                    // on mousemove now.\n                    _setWidth(newWidth, false, false);\n                }\n                \n                animationRequest = window.webkitRequestAnimationFrame(doRedraw);\n            });\n            \n            $mainView.on(\"mousemove.sidebar\", function (e) {\n                newWidth = Math.max(e.clientX, 0);\n                \n                e.preventDefault();\n            });\n                \n            $mainView.one(\"mouseup.sidebar\", function (e) {\n                isMouseDown = false;\n                \n                // replace shadows and triangle\n                $sidebar.find(\".sidebar-selection-triangle\").css(\"display\", \"block\");\n                $sidebar.find(\".scroller-shadow\").css(\"display\", \"block\");\n                \n                $projectFilesContainer.triggerHandler(\"scroll\");\n                $openFilesContainer.triggerHandler(\"scroll\");\n                $mainView.off(\"mousemove.sidebar\");\n                $body.toggleClass(\"resizing\");\n                startingSidebarPosition = $sidebar.width();\n            });\n            \n            e.preventDefault();\n        });\n    }\n\n    // Initialize items dependent on HTML DOM\n    $(brackets).on(\"htmlContentLoadComplete\", function () {\n        $sidebar                = $(\"#sidebar\");\n        $sidebarMenuText        = $(\"#menu-view-hide-sidebar span\");\n        $sidebarResizer         = $(\"#sidebar-resizer\");\n        $openFilesContainer     = $(\"#open-files-container\");\n        $projectTitle           = $(\"#project-title\");\n        $projectFilesContainer  = $(\"#project-files-container\");\n\n        // init\n        WorkingSetView.create($openFilesContainer);\n        _initSidebarResizer();\n    });\n    \n    $(ProjectManager).on(\"projectOpen\", _updateProjectTitle);\n    CommandManager.register(Strings.CMD_HIDE_SIDEBAR,       Commands.VIEW_HIDE_SIDEBAR,     toggleSidebar);\n    \n    // Define public API\n    exports.toggleSidebar = toggleSidebar;\n});\ndefine('text!buildNumber.json',[],function () { return '{\\n    \"buildNumber\": 100\\n}\\n';});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils, window */\n\n/**\n *  Utilities functions for displaying update notifications\n *\n */\ndefine('utils/UpdateNotification',['require','exports','module','widgets/Dialogs','utils/NativeApp','preferences/PreferencesManager','strings','utils/StringUtils','text!buildNumber.json'],function (require, exports, module) {\n    \n    \n    var Dialogs             = require(\"widgets/Dialogs\"),\n        NativeApp           = require(\"utils/NativeApp\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        BuildNumberJSON     = require(\"text!buildNumber.json\");\n    \n    // Current build number.\n    var _buildNumber = JSON.parse(BuildNumberJSON).buildNumber;\n    \n    // PreferenceStorage\n    var _prefs = PreferencesManager.getPreferenceStorage(module.id, {lastNotifiedBuildNumber: 0});\n        \n    // This is the last version we notified the user about. If checkForUpdate()\n    // is called with \"false\", only show the update notification dialog if there\n    // is an update newer than this one. This value is saved in preferences.\n    var _lastNotifiedBuildNumber = _prefs.getValue(\"lastNotifiedBuildNumber\");\n    \n    // Last time the versionInfoURL was fetched\n    var _lastInfoURLFetchTime = _prefs.getValue(\"lastInfoURLFetchTime\");\n\n    // URL to load version info from. By default this is loaded no more than once a day. If \n    // you force an update check it is always loaded.\n    \n    // URL to fetch the version information.\n    var _versionInfoURL = \"http://dev.brackets.io/updates/stable/\"; // {locale}.json will be appended\n    \n    // Information on all posted builds of Brackets. This is an Array, where each element is \n    // an Object with the following fields:\n    //\n    //  {Number} buildNumber Number of the build\n    //  {String} versionString String representation of the build number (ie \"Sprint 14\")\n    //  {String} dateString Date of the build\n    //  {String} releaseNotesURL URL of the release notes for this build\n    //  {String} downloadURL URL to download this build\n    //  {Array} newFeatures Array of new features in this build. Each entry has two fields:\n    //      {String} name Name of the feature\n    //      {String} description Description of the feature\n    //\n    // This array must be reverse sorted by buildNumber (newest build info first)\n    \n    /**\n     * @private\n     * Flag that indicates if we've added a click handler to the update notification icon.\n     */\n    var _addedClickHandler = false;\n    \n    /**\n     * Get a data structure that has information for all builds of Brackets.\n     *\n     * If force is true, the information is always fetched from _versionInfoURL.\n     * If force is false, we try to use cached information. If more than\n     * 24 hours have passed since the last fetch, or if cached data can't be found, \n     * the data is fetched again.\n     *\n     * If new data is fetched and dontCache is false, the data is saved in preferences\n     * for quick fetching later.\n     */\n    function _getUpdateInformation(force, dontCache) {\n        var result = new $.Deferred();\n        var fetchData = false;\n        var data;\n        \n        // If force is true, always fetch\n        if (force) {\n            fetchData = true;\n        }\n        \n        // If we don't have data saved in prefs, fetch\n        data = _prefs.getValue(\"updateInfo\");\n        if (!data) {\n            fetchData = true;\n        }\n        \n        // If more than 24 hours have passed since our last fetch, fetch again\n        if ((new Date()).getTime() > _lastInfoURLFetchTime + (1000 * 60 * 60 * 24)) {\n            fetchData = true;\n        }\n        \n        if (fetchData) {\n            $.ajax(_versionInfoURL, {\n                dataType: \"text\",\n                complete: function (jqXHR, status) {\n                    if (status === \"success\") {\n                        try {\n                            data = JSON.parse(jqXHR.responseText);\n                            if (!dontCache) {\n                                _lastInfoURLFetchTime = (new Date()).getTime();\n                                _prefs.setValue(\"lastInfoURLFetchTime\", _lastInfoURLFetchTime);\n                                _prefs.setValue(\"updateInfo\", data);\n                            }\n                            result.resolve(data);\n                        } catch (e) {\n                            console.log(\"Error parsing version information\");\n                            console.log(e);\n                            result.reject();\n                        }\n                    }\n                },\n                error: function (jqXHR, status, error) {\n                    // When loading data for unit tests, the error handler is \n                    // called but the responseText is valid. Try to use it here,\n                    // but *don't* save the results in prefs.\n                    \n                    if (!jqXHR.responseText) {\n                        // Text is NULL or empty string, reject().\n                        result.reject();\n                        return;\n                    }\n                    \n                    try {\n                        data = JSON.parse(jqXHR.responseText);\n                        result.resolve(data);\n                    } catch (e) {\n                        result.reject();\n                    }\n                }\n            });\n        } else {\n            result.resolve(data);\n        }\n        \n        return result.promise();\n    }\n    \n    /**\n     * Return a new array of version information that is newer than \"buildNumber\".\n     * Returns null if there is no new version information.\n     */\n    function _stripOldVersionInfo(versionInfo, buildNumber) {\n        // Do a simple linear search. Since we are going in reverse-chronological order, we\n        // should get through the search quickly.\n        var lastIndex = 0;\n        var len = versionInfo.length;\n        \n        while (lastIndex < len) {\n            if (versionInfo[lastIndex].buildNumber <= buildNumber) {\n                break;\n            }\n            lastIndex++;\n        }\n        \n        if (lastIndex > 0) {\n            return versionInfo.slice(0, lastIndex);\n        }\n        \n        // No new version info\n        return null;\n    }\n    \n    /**\n     * Show a dialog that shows the update \n     */\n    function _showUpdateNotificationDialog(updates) {\n        Dialogs.showModalDialog(Dialogs.DIALOG_ID_UPDATE)\n            .done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_DOWNLOAD) {\n                    // The first entry in the updates array has the latest download link\n                    NativeApp.openURLInDefaultBrowser(updates[0].downloadURL);\n                }\n            });\n        \n        // Populate the update data\n        var $dlg = $(\".update-dialog.instance\");\n        var $updateList = $dlg.find(\".update-info\");\n        \n        // TODO: Use a template instead of hand-rolling HTML code\n        updates.forEach(function (item, index) {\n            var $features = $(\"<ul>\");\n            \n            item.newFeatures.forEach(function (feature, index) {\n                $features.append(\n                    \"<li><b>\" +\n                        StringUtils.htmlEscape(feature.name) +\n                        \"</b> - \" +\n                        StringUtils.htmlEscape(feature.description) +\n                        \"</li>\"\n                );\n            });\n            \n            var $item = $(\"<div>\")\n                .append(\"<h3>\" +\n                        StringUtils.htmlEscape(item.versionString) +\n                        \" - \" +\n                        StringUtils.htmlEscape(item.dateString) +\n                        \" (<a href='#' data-url='\" + item.releaseNotesURL + \"'>\" +\n                        Strings.RELEASE_NOTES +\n                        \"</a>)</h3>\")\n                .append($features)\n                .appendTo($updateList);\n        });\n        \n        $dlg.on(\"click\", \"a\", function (e) {\n            var url = $(e.target).attr(\"data-url\");\n            \n            if (url) {\n                // Make sure the URL has a domain that we know about\n                if (/(brackets\\.io|github\\.com|adobe\\.com)$/i.test(PathUtils.parseUrl(url).hostname)) {\n                    NativeApp.openURLInDefaultBrowser(url);\n                }\n            }\n        });\n    }\n    \n    /**\n     * Check for updates. If \"force\" is true, update notification dialogs are always displayed \n     * (if an update is available). If \"force\" is false, the update notification is only \n     * displayed for newly available updates.\n     * \n     * If an update is available, show the \"update available\" notification icon in the title bar.\n     *\n     * @param {boolean} force If true, always show the notification dialog.\n     * @param {Object} _testValues This should only be used for testing purposes. See comments for details.\n     * @return {$.Promise} jQuery Promise object that is resolved or rejected after the update check is complete.\n     */\n    function checkForUpdate(force, _testValues) {\n        // The second param, if non-null, is an Object containing value overrides. Values\n        // in the object temporarily override the local values. This should *only* be used for testing.\n        // If any overrides are set, permanent changes are not made (including showing\n        // the update notification icon and saving prefs).\n        var oldValues;\n        var usingOverrides = false; // true if any of the values are overridden.\n        var result = new $.Deferred();\n        \n        if (_testValues) {\n            oldValues = {};\n            \n            if (_testValues.hasOwnProperty(\"_buildNumber\")) {\n                oldValues._buildNumber = _buildNumber;\n                _buildNumber = _testValues._buildNumber;\n                usingOverrides = true;\n            }\n\n            if (_testValues.hasOwnProperty(\"_lastNotifiedBuildNumber\")) {\n                oldValues._lastNotifiedBuildNumber = _lastNotifiedBuildNumber;\n                _lastNotifiedBuildNumber = _testValues._lastNotifiedBuildNumber;\n                usingOverrides = true;\n            }\n\n            if (_testValues.hasOwnProperty(\"_versionInfoURL\")) {\n                oldValues._versionInfoURL = _versionInfoURL;\n                _versionInfoURL = _testValues._versionInfoURL;\n                usingOverrides = true;\n            }\n        }\n        \n        _getUpdateInformation(force || usingOverrides, usingOverrides)\n            .done(function (versionInfo) {\n                // Get all available updates\n                var allUpdates = _stripOldVersionInfo(versionInfo, _buildNumber);\n                \n                if (allUpdates) {\n                    // Always show the \"update available\" icon if any updates are available\n                    var $updateNotification = $(\"#update-notification\");\n                    \n                    $updateNotification.css(\"display\", \"inline-block\");\n                    if (!_addedClickHandler) {\n                        _addedClickHandler = true;\n                        $updateNotification.on(\"click\", function () {\n                            checkForUpdate(true);\n                        });\n                    }\n                \n                    // Only show the update dialog if force = true, or if the user hasn't been \n                    // alerted of this update\n                    if (force || allUpdates[0].buildNumber >  _lastNotifiedBuildNumber) {\n                        _showUpdateNotificationDialog(allUpdates);\n                        \n                        // Update prefs with the last notified build number\n                        _lastNotifiedBuildNumber = allUpdates[0].buildNumber;\n                        // Don't save prefs is we have overridden values\n                        if (!usingOverrides) {\n                            _prefs.setValue(\"lastNotifiedBuildNumber\", _lastNotifiedBuildNumber);\n                        }\n                    }\n                } else if (force) {\n                    // No updates are available. If force == true, let the user know.\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_ERROR,\n                        Strings.NO_UPDATE_TITLE,\n                        Strings.NO_UPDATE_MESSAGE\n                    );\n                }\n        \n                if (oldValues) {\n                    if (oldValues.hasOwnProperty(\"_buildNumber\")) {\n                        _buildNumber = oldValues._buildNumber;\n                    }\n                    if (oldValues.hasOwnProperty(\"_lastNotifiedBuildNumber\")) {\n                        _lastNotifiedBuildNumber = oldValues._lastNotifiedBuildNumber;\n                    }\n                    if (oldValues.hasOwnProperty(\"_versionInfoURL\")) {\n                        _versionInfoURL = oldValues._versionInfoURL;\n                    }\n                }\n                result.resolve();\n            })\n            .fail(function () {\n                result.reject();\n            });\n        \n        return result.promise();\n    }\n    \n    // Append locale to version info URL\n    _versionInfoURL += (window.localStorage.getItem(\"locale\") || brackets.app.language) + \".json\";\n    \n    // Define public API\n    exports.checkForUpdate = checkForUpdate;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, window */\n\ndefine('utils/UrlParams',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * Convert between URL querystring and name/value pairs. Decodes and encodes URL parameters.\n     */\n    function UrlParams() {\n        this._store = {};\n    }\n    \n    /**\n     * Parse the window location by default. Optionally specify a URL to parse.\n     * @param {string} url\n     */\n    UrlParams.prototype.parse = function (url) {\n        if (url) {\n            url = url.substring(indexOf(\"?\") + 1);\n        } else {\n            url = window.document.location.search.substring(1);\n        }\n        \n        var urlParams = url.split(\"&\"),\n            p,\n            self = this;\n        \n        urlParams.forEach(function (param) {\n            p = param.split(\"=\");\n            self._store[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);\n        });\n    };\n    \n    /**\n     * Store a name/value string pair\n     * @param {!string} name\n     * @param {!string} value\n     */\n    UrlParams.prototype.put = function (name, value) {\n        this._store[name] = value;\n    };\n    \n    /**\n     * Retreive a value by name\n     * @param {!string} name\n     */\n    UrlParams.prototype.get = function (name) {\n        return this._store[name];\n    };\n    \n    /**\n     * Encode name/value pairs as URI components.\n     */\n    UrlParams.prototype.toString = function () {\n        var strs = [],\n            self = this;\n        \n        Object.keys(self._store).forEach(function (key) {\n            strs.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(self._store[key]));\n        });\n        \n        return strs.join(\"&\");\n    };\n\n    // Define public API\n    exports.UrlParams = UrlParams;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n\n/**\n * Text-editing commands that apply to whichever Editor is currently focused\n */\ndefine('editor/EditorCommandHandlers',['require','exports','module','command/Commands','strings','command/CommandManager','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var Commands           = require(\"command/Commands\"),\n        Strings            = require(\"strings\"),\n        CommandManager     = require(\"command/CommandManager\"),\n        EditorManager      = require(\"editor/EditorManager\");\n    \n    \n    /**\n     * List of constants\n     */\n    var DIRECTION_UP    = -1;\n    var DIRECTION_DOWN  = +1;\n    \n    /**\n     * Add or remove line-comment tokens to all the lines in the selected range, preserving selection\n     * and cursor position. Applies to currently focused Editor.\n     * \n     * If all non-whitespace lines are already commented out, then we uncomment; otherwise we comment\n     * out. Commenting out adds \"//\" to at column 0 of every line. Uncommenting removes the first \"//\"\n     * on each line (if any - empty lines might not have one).\n     */\n    function lineCommentSlashSlash(editor) {\n        \n        var doc = editor.document;\n        var sel = editor.getSelection();\n        var startLine = sel.start.line;\n        var endLine = sel.end.line;\n        \n        // Is a range of text selected? (vs just an insertion pt)\n        var hasSelection = (startLine !== endLine) || (sel.start.ch !== sel.end.ch);\n        \n        // In full-line selection, cursor pos is start of next line - but don't want to modify that line\n        if (sel.end.ch === 0 && hasSelection) {\n            endLine--;\n        }\n        \n        // Decide if we're commenting vs. un-commenting\n        // Are there any non-blank lines that aren't commented out? (We ignore blank lines because\n        // some editors like Sublime don't comment them out)\n        var containsUncommented = false;\n        var i;\n        var line;\n        for (i = startLine; i <= endLine; i++) {\n            line = doc.getLine(i);\n            // A line is commented out if it starts with 0-N whitespace chars, then \"//\"\n            if (!line.match(/^\\s*\\/\\//) && line.match(/\\S/)) {\n                containsUncommented = true;\n                break;\n            }\n        }\n        \n        // Make the edit\n        doc.batchOperation(function () {\n            \n            if (containsUncommented) {\n                // Comment out - prepend \"//\" to each line\n                for (i = startLine; i <= endLine; i++) {\n                    doc.replaceRange(\"//\", {line: i, ch: 0});\n                }\n                \n                // Make sure selection includes \"//\" that was added at start of range\n                if (sel.start.ch === 0 && hasSelection) {\n                    // use *current* selection end, which has been updated for our text insertions\n                    editor.setSelection({line: startLine, ch: 0}, editor.getSelection().end);\n                }\n                \n            } else {\n                // Uncomment - remove first \"//\" on each line (if any)\n                for (i = startLine; i <= endLine; i++) {\n                    line = doc.getLine(i);\n                    var commentI = line.indexOf(\"//\");\n                    if (commentI !== -1) {\n                        doc.replaceRange(\"\", {line: i, ch: commentI}, {line: i, ch: commentI + 2});\n                    }\n                }\n            }\n        });\n        \n    }\n\n    /**\n     * Invokes a language-specific line-comment/uncomment handler\n     * @param {?Editor} editor If unspecified, applies to the currently focused editor\n     */\n    function lineComment(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        var mode = editor.getModeForSelection();\n        \n        // Currently we only support languages with \"//\" commenting\n        if (mode === \"javascript\" || mode === \"less\") {\n            lineCommentSlashSlash(editor);\n        }\n    }\n    \n    \n    /**\n     * Duplicates the selected text, or current line if no selection. The cursor/selection is left\n     * on the second copy.\n     */\n    function duplicateText(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        var sel = editor.getSelection(),\n            hasSelection = (sel.start.line !== sel.end.line) || (sel.start.ch !== sel.end.ch),\n            delimiter = \"\";\n\n        if (!hasSelection) {\n            sel.start.ch = 0;\n            sel.end = {line: sel.start.line + 1, ch: 0};\n            if (sel.end.line === editor.lineCount()) {\n                delimiter = \"\\n\";\n            }\n        }\n\n        // Make the edit\n        var doc = editor.document;\n\n        var selectedText = doc.getRange(sel.start, sel.end) + delimiter;\n        doc.replaceRange(selectedText, sel.start);\n    }\n    \n    /**\n     * Moves the selected text, or current line if no selection. The cursor/selection \n     * moves with the line/lines.\n     * @param {Editor} editor - target editor\n     * @param {Number} direction - direction of the move (-1,+1) => (Up,Down)\n     */\n    function moveLine(editor, direction) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        var doc = editor.document,\n            sel = editor.getSelection(),\n            originalSel = editor.getSelection(),\n            hasSelection = (sel.start.line !== sel.end.line) || (sel.start.ch !== sel.end.ch);\n        \n        sel.start.ch = 0;\n        // The end of the selection becomes the start of the next line, if it isn't already\n        if (!hasSelection || sel.end.ch !== 0) {\n            sel.end = {line: sel.end.line + 1, ch: 0};\n        }\n        \n        // Make the move\n        switch (direction) {\n        case DIRECTION_UP:\n            if (sel.start.line !== 0) {\n                doc.batchOperation(function () {\n                    var prevText = doc.getRange({ line: sel.start.line - 1, ch: 0 }, sel.start);\n                    \n                    if (sel.end.line === editor.lineCount()) {\n                        prevText = \"\\n\" + prevText.substring(0, prevText.length - 1);\n                    }\n                    \n                    doc.replaceRange(\"\", { line: sel.start.line - 1, ch: 0 }, sel.start);\n                    doc.replaceRange(prevText, { line: sel.end.line - 1, ch: 0 });\n                    \n                    // Make sure CodeMirror hasn't expanded the selection to include\n                    // the line we inserted below.\n                    originalSel.start.line--;\n                    originalSel.end.line--;\n                    editor.setSelection(originalSel.start, originalSel.end);\n                });\n            }\n            break;\n        case DIRECTION_DOWN:\n            if (sel.end.line < editor.lineCount()) {\n                doc.batchOperation(function () {\n                    var nextText = doc.getRange(sel.end, { line: sel.end.line + 1, ch: 0 });\n                    \n                    var deletionStart = sel.end;\n                    if (sel.end.line === editor.lineCount() - 1) {\n                        nextText += \"\\n\";\n                        deletionStart = { line: sel.end.line - 1, ch: doc.getLine(sel.end.line - 1).length };\n                    }\n    \n                    doc.replaceRange(\"\", deletionStart, { line: sel.end.line + 1, ch: 0 });\n                    doc.replaceRange(nextText, { line: sel.start.line, ch: 0 });\n                });\n            }\n            break;\n        }\n    }\n    \n    /**\n     * Moves the selected text, or current line if no selection, one line up. The cursor/selection \n     * moves with the line/lines.\n     */\n    function moveLineUp(editor) {\n        moveLine(editor, DIRECTION_UP);\n    }\n    \n    /**\n     * Moves the selected text, or current line if no selection, one line down. The cursor/selection \n     * moves with the line/lines.\n     */\n    function moveLineDown(editor) {\n        moveLine(editor, DIRECTION_DOWN);\n    }\n\n    /**\n     * Indent a line of text if no selection. Otherwise, indent all lines in selection.\n     */\n    function indentText() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        editor._codeMirror.execCommand(\"indentMore\");\n    }\n    \n    /**\n     * Unindent a line of text if no selection. Otherwise, unindent all lines in selection.\n     */\n    function unidentText() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        editor._codeMirror.execCommand(\"indentLess\");\n    }\n        \n    // Register commands\n    CommandManager.register(Strings.CMD_INDENT,         Commands.EDIT_INDENT,       indentText);\n    CommandManager.register(Strings.CMD_UNINDENT,       Commands.EDIT_UNINDENT,     unidentText);\n    CommandManager.register(Strings.CMD_COMMENT,        Commands.EDIT_LINE_COMMENT, lineComment);\n    CommandManager.register(Strings.CMD_DUPLICATE,      Commands.EDIT_DUPLICATE,    duplicateText);\n    CommandManager.register(Strings.CMD_LINE_UP,        Commands.EDIT_LINE_UP,      moveLineUp);\n    CommandManager.register(Strings.CMD_LINE_DOWN,      Commands.EDIT_LINE_DOWN,    moveLineDown);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window */\n\ndefine('debug/DebugCommandHandlers',['require','exports','module','command/Commands','command/CommandManager','editor/Editor','strings','utils/PerfUtils','utils/NativeApp','file/NativeFileSystem','file/FileUtils','utils/UpdateNotification'],function (require, exports, module) {\n    \n    \n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Editor                  = require(\"editor/Editor\").Editor,\n        Strings                 = require(\"strings\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        NativeApp               = require(\"utils/NativeApp\"),\n        NativeFileSystem        = require(\"file/NativeFileSystem\").NativeFileSystem,\n        FileUtils               = require(\"file/FileUtils\"),\n        UpdateNotification      = require(\"utils/UpdateNotification\");\n    \n    function handleShowDeveloperTools(commandData) {\n        brackets.app.showDeveloperTools();\n    }\n    \n    function _handleUseTabChars() {\n        var useTabs = !Editor.getUseTabChar();\n        Editor.setUseTabChar(useTabs);\n        CommandManager.get(Commands.TOGGLE_USE_TAB_CHARS).setChecked(useTabs);\n    }\n    \n    \n    // Implements the 'Run Tests' menu to bring up the Jasmine unit test window\n    var _testWindow = null;\n    function _handleRunUnitTests() {\n        if (_testWindow) {\n            try {\n                _testWindow.location.reload(true);\n            } catch (e) {\n                _testWindow = null;  // the window was probably closed\n            }\n        }\n\n        if (!_testWindow) {\n            _testWindow = window.open(\"../test/SpecRunner.html\", \"brackets-test\", \"width=\" + $(window).width() + \",height=\" + $(window).height());\n            _testWindow.location.reload(true); // if it was opened before, we need to reload because it will be cached\n        }\n    }\n    \n    function _handleShowPerfData() {\n        var $perfHeader = $(\"<div class='modal-header' />\")\n            .append(\"<a href='#' class='close'>&times;</a>\")\n            .append(\"<h1 class='dialog-title'>Performance Data</h1>\")\n            .append(\"<div align=right>Raw data (copy paste out): <textarea rows=1 style='width:30px; height:8px; overflow: hidden; resize: none' id='brackets-perf-raw-data'>\" + PerfUtils.getDelimitedPerfData() + \"</textarea></div>\");\n        \n        var $perfBody = $(\"<div class='modal-body' style='padding: 0; max-height: 500px; overflow: auto;' />\");\n\n        var $data = $(\"<table class='zebra-striped condensed-table'>\")\n            .append(\"<thead><th>Operation</th><th>Time (ms)</th></thead>\")\n            .append(\"<tbody />\")\n            .appendTo($perfBody);\n        \n        var makeCell = function (content) {\n            return $(\"<td/>\").text(content);\n        };\n        \n        var getValue = function (entry) {\n            // entry is either an Array or a number\n            if (Array.isArray(entry)) {\n                // For Array of values, return: minimum/average/maximum/last\n                var i, e, avg, sum = 0, min = Number.MAX_VALUE, max = 0;\n                \n                for (i = 0; i < entry.length; i++) {\n                    e = entry[i];\n                    min = Math.min(min, e);\n                    sum += e;\n                    max = Math.max(max, e);\n                }\n                avg = Math.round(sum / entry.length);\n                return String(min) + \"/\" + String(avg) + \"/\" + String(max) + \"/\" + String(e);\n            } else {\n                return entry;\n            }\n        };\n            \n        var testName;\n        var perfData = PerfUtils.getData();\n        for (testName in perfData) {\n            if (perfData.hasOwnProperty(testName)) {\n                // Add row to error table\n                $(\"<tr/>\")\n                    .append(makeCell(testName))\n                    .append(makeCell(getValue(perfData[testName])))\n                    .appendTo($data);\n            }\n        }\n                                                     \n        $(\"<div class='modal hide' />\")\n            .append($perfHeader)\n            .append($perfBody)\n            .appendTo(window.document.body)\n            .modal({\n                backdrop: \"static\",\n                show: true\n            });\n\n        // Select the raw perf data field on click since select all doesn't \n        // work outside of the editor\n        $(\"#brackets-perf-raw-data\").click(function () {\n            $(this).focus().select();\n        });\n    }\n    \n    function _handleNewBracketsWindow() {\n        window.open(window.location.href);\n    }\n\n    function _handleSwitchLanguage() {\n        var stringsPath = FileUtils.getNativeBracketsDirectoryPath() + \"/nls\";\n        NativeFileSystem.requestNativeFileSystem(stringsPath, function (dirEntry) {\n            dirEntry.createReader().readEntries(function (entries) {\n\n                var $activeLanguage,\n                    $submit,\n                    locale;\n                \n                function setLanguage(event) {\n                    if ($activeLanguage) {\n                        $activeLanguage.css(\"font-weight\", \"normal\");\n                    }\n                    $activeLanguage = $(event.currentTarget);\n                    locale = $activeLanguage.data(\"locale\");\n                    \n                    $activeLanguage.css(\"font-weight\", \"bold\");\n                    $submit.attr(\"disabled\", false);\n                }\n    \n                var $modal = $(\"<div class='modal hide' />\");\n    \n                var $header = $(\"<div class='modal-header' />\")\n                    .append(\"<a href='#' class='close'>&times;</a>\")\n                    .append(\"<h1 class='dialog-title'>\" + Strings.LANGUAGE_TITLE + \"</h1>\")\n                    .appendTo($modal);\n                  \n                var $body = $(\"<div class='modal-body' style='max-height: 500px; overflow: auto;' />\")\n                    .appendTo($modal);\n\n                var $p = $(\"<p class='dialog-message'>\")\n                    .text(Strings.LANGUAGE_MESSAGE)\n                    .appendTo($body);\n\n                var $ul = $(\"<ul>\")\n                    .on(\"click\", \"li\", setLanguage)\n                    .appendTo($p);\n                \n                var $footer = $(\"<div class='modal-footer' />\")\n                    .appendTo($modal);\n                \n                var $cancel = $(\"<button class='dialog-button btn left'>\")\n                    .on(\"click\", function () {\n                        $modal.modal('hide');\n                    })\n                    .text(Strings.LANGUAGE_CANCEL)\n                    .appendTo($footer);\n                \n                $submit = $(\"<button class='dialog-button btn primary'>\")\n                    .text(Strings.LANGUAGE_SUBMIT)\n                    .on(\"click\", function () {\n                        if (!$activeLanguage) {\n                            return;\n                        }\n                        if (locale) {\n                            window.localStorage.setItem(\"locale\", locale);\n                        } else {\n                            window.localStorage.removeItem(\"locale\");\n                        }\n                        \n                        CommandManager.execute(Commands.DEBUG_REFRESH_WINDOW);\n                    })\n                    .attr(\"disabled\", \"disabled\")\n                    .appendTo($footer);\n                \n                $modal\n                    .appendTo(window.document.body)\n                    .modal({\n                        backdrop: \"static\",\n                        show: true\n                    })\n                    .on(\"hidden\", function () {\n                        $(this).remove();\n                    });\n\n                // add system default\n                var $li = $(\"<li>\")\n                    .text(\"system default\")\n                    .data(\"locale\", null)\n                    .appendTo($ul);\n                \n                // add english\n                $li = $(\"<li>\")\n                    .text(\"en\")\n                    .data(\"locale\", \"en\")\n                    .appendTo($ul);\n                \n                // inspect all children of dirEntry\n                entries.forEach(function (entry) {\n                    if (entry.isDirectory && entry.name.match(/^[a-z]{2}(-[A-Z]{2})?$/)) {\n                        var language = entry.name;\n                        var $li = $(\"<li>\")\n                            .text(entry.name)\n                            .data(\"locale\", language)\n                            .appendTo($ul);\n                    }\n                });\n            });\n        });\n    }\n    \n    function _handleShowExtensionsFolder() {\n        brackets.app.showExtensionsFolder(\n            FileUtils.convertToNativePath(window.location.href),\n            function (err) {\n                // Ignore errors\n            }\n        );\n    }\n    \n    function _handleCheckForUpdates() {\n        UpdateNotification.checkForUpdate(true);\n    }\n    \n    /* Register all the command handlers */\n    \n    // Show Developer Tools (optionally enabled)\n    CommandManager.register(Strings.CMD_SHOW_DEV_TOOLS,      Commands.DEBUG_SHOW_DEVELOPER_TOOLS,   handleShowDeveloperTools)\n        .setEnabled(!!brackets.app.showDeveloperTools);\n    CommandManager.register(Strings.CMD_NEW_BRACKETS_WINDOW, Commands.DEBUG_NEW_BRACKETS_WINDOW,    _handleNewBracketsWindow);\n    CommandManager.register(Strings.CMD_SHOW_EXTENSIONS_FOLDER, Commands.DEBUG_SHOW_EXT_FOLDER,     _handleShowExtensionsFolder);\n    CommandManager.register(Strings.CMD_RUN_UNIT_TESTS,      Commands.DEBUG_RUN_UNIT_TESTS,         _handleRunUnitTests);\n    CommandManager.register(Strings.CMD_SHOW_PERF_DATA,      Commands.DEBUG_SHOW_PERF_DATA,         _handleShowPerfData);\n    CommandManager.register(Strings.CMD_SWITCH_LANGUAGE,     Commands.DEBUG_SWITCH_LANGUAGE,        _handleSwitchLanguage);\n    \n    CommandManager.register(Strings.CMD_USE_TAB_CHARS,       Commands.TOGGLE_USE_TAB_CHARS,         _handleUseTabChars)\n        .setChecked(Editor.getUseTabChar());\n    \n    CommandManager.register(Strings.CMD_CHECK_FOR_UPDATE,    Commands.CHECK_FOR_UPDATE,             _handleCheckForUpdates);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, window, $ */\n\ndefine('view/ViewCommandHandlers',['require','exports','module','command/Commands','command/CommandManager','strings','project/ProjectManager','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Strings                 = require(\"strings\"),\n        ProjectManager          = require(\"project/ProjectManager\"),\n        EditorManager           = require(\"editor/EditorManager\");\n    \n    /**\n     * @const\n     * @type {string}\n     */\n    var DYNAMIC_FONT_STYLE_ID = \"codemirror-dynamic-fonts\";\n\n    function _removeDynamicFontSize(refresh) {\n        $(\"#\" + DYNAMIC_FONT_STYLE_ID).remove();\n        if (refresh) {\n            EditorManager.getCurrentFullEditor().refreshAll();\n        }\n    }\n    \n    /**\n     * @private\n     * Increases or decreases the editor's font size.\n     * @param {number} -1 to make the font smaller; 1 to make it bigger.\n     */\n    function _adjustFontSize(direction) {\n        var styleId = \"codemirror-dynamic-fonts\";\n\n        var fsStyle = $(\".CodeMirror-scroll\").css(\"font-size\");\n        var lhStyle = $(\".CodeMirror-scroll\").css(\"line-height\");\n\n        var validFont = /^[\\d\\.]+(px|em)$/;\n        \n        // Make sure the font size and line height are expressed in terms\n        // we can handle (px or em). If not, simply bail.\n        if (fsStyle.search(validFont) === -1 || lhStyle.search(validFont) === -1) {\n            return;\n        }\n        \n        // Guaranteed to work by the validation above.\n        var fsUnits = fsStyle.substring(fsStyle.length - 2, fsStyle.length);\n        var lhUnits = lhStyle.substring(lhStyle.length - 2, lhStyle.length);\n\n        var fsOld = parseFloat(fsStyle.substring(0, fsStyle.length - 2));\n        var lhOld = parseFloat(lhStyle.substring(0, lhStyle.length - 2));\n\n        var fsDelta = (fsUnits === \"px\") ? 1 : 0.1;\n        var lhDelta = (lhUnits === \"px\") ? 1 : 0.1;\n\n        if (direction === -1) {\n            fsDelta *= -1;\n            lhDelta *= -1;\n        }\n\n        var fsNew = fsOld + fsDelta;\n        var lhNew = lhOld + lhDelta;\n        \n        var fsStr = fsNew + fsUnits;\n        var lhStr = lhNew + lhUnits;\n\n        // Don't let the fonts get too small.\n        if (direction === -1 && ((fsUnits === \"px\" && fsNew <= 1) || (fsUnits === \"em\" && fsNew <= 0.1))) {\n            return;\n        }\n\n        // It's necessary to inject a new rule to address all editors.\n        _removeDynamicFontSize(false);\n        var style = $(\"<style type='text/css'></style>\").attr(\"id\", DYNAMIC_FONT_STYLE_ID);\n        style.html(\".CodeMirror-scroll {\" +\n                   \"font-size: \"   + fsStr + \" !important;\" +\n                   \"line-height: \" + lhStr + \" !important;}\");\n        $(\"head\").append(style);\n        \n        var editor = EditorManager.getCurrentFullEditor();\n        editor.refreshAll();\n        \n        // Scroll the document back to its original position. This can only happen\n        // if the font size is specified in pixels (which it currently is).\n        if (fsUnits === \"px\") {\n            var scrollPos = editor.getScrollPos();\n            var scrollDeltaX = Math.round(scrollPos.x / lhOld);\n            var scrollDeltaY = Math.round(scrollPos.y / lhOld);\n            editor.setScrollPos(scrollPos.x + (scrollDeltaX * direction),\n                                scrollPos.y + (scrollDeltaY * direction));\n        }\n\n    }\n    \n    function _handleIncreaseFontSize() {\n        _adjustFontSize(1);\n    }\n\n    function _handleDecreaseFontSize() {\n        _adjustFontSize(-1);\n    }\n    \n    function _handleRestoreFontSize() {\n        _removeDynamicFontSize(true);\n    }\n    \n    CommandManager.register(Strings.CMD_INCREASE_FONT_SIZE, Commands.VIEW_INCREASE_FONT_SIZE, _handleIncreaseFontSize);\n    CommandManager.register(Strings.CMD_DECREASE_FONT_SIZE, Commands.VIEW_DECREASE_FONT_SIZE, _handleDecreaseFontSize);\n    CommandManager.register(Strings.CMD_RESTORE_FONT_SIZE,  Commands.VIEW_RESTORE_FONT_SIZE,  _handleRestoreFontSize);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, PathUtils, window */\n\n/*\n * Adds a \"find in files\" command to allow the user to find all occurances of a string in all files in\n * the project.\n * \n * The keyboard shortcut is Cmd(Ctrl)-Shift-F.\n *\n * FUTURE:\n *  - Proper UI for both dialog and results\n *  - Refactor dialog class and share with Quick File Open\n *  - Search files in working set that are *not* in the project\n *  - Handle matches that span mulitple lines\n *  - Refactor UI from functionality to enable unit testing\n */\n\n\ndefine('search/FindInFiles',['require','exports','module','utils/Async','command/CommandManager','command/Commands','strings','utils/StringUtils','document/DocumentManager','editor/EditorManager','project/FileIndexManager'],function (require, exports, module) {\n    \n    \n    var Async               = require(\"utils/Async\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileIndexManager    = require(\"project/FileIndexManager\");\n\n    // This dialog class was mostly copied from QuickOpen. We should have a common dialog\n    // class that everyone can use.\n    \n    /**\n    * FindInFilesDialog class\n    * @constructor\n    *\n    */\n    function FindInFilesDialog() {\n        this.closed = false;\n        this.result = null; // $.Deferred\n    }\n\n    /**\n    * Creates a dialog div floating on top of the current code mirror editor\n    */\n    FindInFilesDialog.prototype._createDialogDiv = function (template) {\n        this.dialog = $(\"<div />\")\n                          .attr(\"class\", \"CodeMirror-dialog\")\n                          .html(\"<div>\" + template + \"</div>\")\n                          .prependTo($(\"#editor-holder\"));\n    };\n    \n    /**\n    * Closes the search dialog and resolves the promise that showDialog returned\n    */\n    FindInFilesDialog.prototype._close = function (value) {\n        if (this.closed) {\n            return;\n        }\n        \n        this.closed = true;\n        this.dialog.remove();\n        EditorManager.focusEditor();\n        this.result.resolve(value);\n    };\n        \n    /**\n    * Shows the search dialog \n    * @param {?string} initialString Default text to prepopulate the search field with\n    * @returns {$.Promise} that is resolved with the string to search for\n    */\n    FindInFilesDialog.prototype.showDialog = function (initialString) {\n        var dialogHTML = Strings.CMD_FIND_IN_FILES +\n            \": <input type='text' id='findInFilesInput' style='width: 10em'> <span style='color: #888'>(\" +\n            Strings.SEARCH_REGEXP_INFO  + \")</span>\";\n        this.result = new $.Deferred();\n        this._createDialogDiv(dialogHTML);\n        var $searchField = $(\"input#findInFilesInput\");\n        var that = this;\n        \n        $searchField.attr(\"value\", initialString || \"\");\n        $searchField.get(0).select();\n        \n        $searchField.bind(\"keydown\", function (event) {\n            if (event.keyCode === 13 || event.keyCode === 27) {  // Enter/Return key or Esc key\n                event.stopPropagation();\n                event.preventDefault();\n                \n                var query = $searchField.val();\n                \n                if (event.keyCode === 27) {\n                    query = null;\n                }\n                \n                that._close(query);\n            }\n        })\n            .blur(function () {\n                that._close(null);\n            })\n            .focus();\n        \n        return this.result.promise();\n    };\n\n\n    function _getSearchMatches(contents, queryExpr) {\n        // Quick exit if not found\n        if (contents.search(queryExpr) === -1) {\n            return null;\n        }\n        \n        var trimmedContents = contents;\n        var startPos = 0;\n        var matchStart;\n        var matches = [];\n        \n        \n        var match;\n        var lines = StringUtils.getLines(contents);\n        while ((match = queryExpr.exec(contents)) !== null) {\n            var lineNum = StringUtils.offsetToLineNum(lines, match.index);\n            var line = lines[lineNum];\n            var ch = match.index - contents.lastIndexOf(\"\\n\", match.index) - 1;  // 0-based index\n            var matchLength = match[0].length;\n            \n            // Don't store more than 200 chars per line\n            line = line.substr(0, Math.min(200, line.length));\n            \n            matches.push({\n                start: {line: lineNum, ch: ch},\n                end: {line: lineNum, ch: ch + matchLength},\n                line: line\n            });\n        }\n\n        return matches;\n    }\n        \n    function _showSearchResults(searchResults) {\n        var $searchResultsDiv = $(\"#search-results\");\n        \n        if (searchResults && searchResults.length) {\n            var $resultTable = $(\"<table class='zebra-striped condensed-table' />\")\n                                .append(\"<tbody>\");\n            \n            // Count the total number of matches\n            var numMatches = 0;\n            searchResults.forEach(function (item) {\n                numMatches += item.matches.length;\n            });\n            \n            // Show result summary in header\n            $(\"#search-result-summary\")\n                .text(\"- \" + numMatches + \" match\" + (numMatches > 1 ? \"es\" : \"\") +\n                      \" in \" + searchResults.length + \" file\" + (searchResults.length > 1 ? \"s\" : \"\") +\n                     (numMatches > 100 ? \" (showing the first 100 matches)\" : \"\"))\n                .prepend(\"&nbsp;\");  // putting a normal space before the \"-\" is not enough\n            \n            var resultsDisplayed = 0;\n            \n            searchResults.forEach(function (item) {\n                if (item && resultsDisplayed < 100) {\n                    var makeCell = function (content) {\n                        return $(\"<td/>\").html(content);\n                    };\n                    \n                    var esc = function (str) {\n                        str = str.replace(/</g, \"&lt;\");\n                        str = str.replace(/>/g, \"&gt;\");\n                        return str;\n                    };\n                    \n                    var highlightMatch = function (line, start, end) {\n                        return esc(line.substr(0, start)) + \"<span class='highlight'>\" + esc(line.substring(start, end)) + \"</span>\" + esc(line.substr(end));\n                    };\n                    \n                    // Add row for file name\n                    $(\"<tr class='file-section' />\")\n                        .append(\"<td colspan='3'>File: <b>\" + item.fullPath + \"</b></td>\")\n                        .click(function () {\n                            // Clicking file section header collapses/expands result rows for that file\n                            var $fileHeader = $(this);\n                            $fileHeader.nextUntil(\".file-section\").toggle();\n                        })\n                        .appendTo($resultTable);\n                    \n                    // Add row for each match in file\n                    item.matches.forEach(function (match) {\n                        if (resultsDisplayed < 100) {\n                            var $row = $(\"<tr/>\")\n                                .append(makeCell(\" \"))      // Indent\n                                .append(makeCell(\"line: \" + (match.start.line + 1)))\n                                .append(makeCell(highlightMatch(match.line, match.start.ch, match.end.ch)))\n                                .appendTo($resultTable);\n                            \n                            $row.click(function () {\n                                CommandManager.execute(Commands.FILE_OPEN, {fullPath: item.fullPath})\n                                    .done(function (doc) {\n                                        // Opened document is now the current main editor\n                                        EditorManager.getCurrentFullEditor().setSelection(match.start, match.end);\n                                    });\n                            });\n                            resultsDisplayed++;\n                        }\n                    });\n                    \n                }\n            });\n            \n            $(\"#search-results .table-container\")\n                .empty()\n                .append($resultTable);\n            \n            $(\"#search-results .close\")\n                .one(\"click\", function () {\n                    $searchResultsDiv.hide();\n                    EditorManager.resizeEditor();\n                });\n            \n            $searchResultsDiv.show();\n        } else {\n            $searchResultsDiv.hide();\n        }\n        \n        EditorManager.resizeEditor();\n    }\n    \n    function _getQueryRegExp(query) {\n        // If query is a regular expression, use it directly\n        var isRE = query.match(/^\\/(.*)\\/(g|i)*$/);\n        if (isRE) {\n            // Make sure the 'g' flag is set\n            var flags = isRE[2] || \"g\";\n            if (flags.search(\"g\") === -1) {\n                flags += \"g\";\n            }\n            return new RegExp(isRE[1], flags);\n        }\n\n        // Query is a string. Turn it into a case-insensitive regexp\n        \n        // Escape regex special chars\n        query = query.replace(/([(){}\\[\\].\\^$|?+*\\\\])/g, \"\\\\$1\");\n        return new RegExp(query, \"gi\");\n    }\n    \n    /**\n    * Displays a non-modal embedded dialog above the code mirror editor that allows the user to do\n    * a find operation across all files in the project.\n    */\n    function doFindInFiles() {\n\n        var dialog = new FindInFilesDialog();\n        var searchResults = [];\n        \n        // Default to searching for the current selection\n        var currentEditor = EditorManager.getFocusedEditor();\n        var initialString = currentEditor && currentEditor.getSelectedText();\n                            \n        dialog.showDialog(initialString)\n            .done(function (query) {\n                if (query) {\n                    var queryExpr = _getQueryRegExp(query);\n                    FileIndexManager.getFileInfoList(\"all\")\n                        .done(function (fileListResult) {\n                            Async.doInParallel(fileListResult, function (fileInfo) {\n                                var result = new $.Deferred();\n                                \n                                DocumentManager.getDocumentForPath(fileInfo.fullPath)\n                                    .done(function (doc) {\n                                        var matches = _getSearchMatches(doc.getText(), queryExpr);\n                                        \n                                        if (matches && matches.length) {\n                                            searchResults.push({\n                                                fullPath: fileInfo.fullPath,\n                                                matches: matches\n                                            });\n                                        }\n                                        result.resolve();\n                                    })\n                                    .fail(function (error) {\n                                        // Error reading this file. This is most likely because the file isn't a text file.\n                                        // Resolve here so we move on to the next file.\n                                        result.resolve();\n                                    });\n                                \n                                return result.promise();\n                            })\n                                .done(function () {\n                                    _showSearchResults(searchResults);\n                                })\n                                .fail(function () {\n                                    console.log(\"find in files failed.\");\n                                });\n                        });\n                }\n            });\n    }\n\n    CommandManager.register(Strings.CMD_FIND_IN_FILES,  Commands.EDIT_FIND_IN_FILES,    doFindInFiles);\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, doReplace */\n\n/*\n * Adds Find and Replace commands\n * \n * Define search commands. Depends on dialog.js or another\n * implementation of the openDialog method.\n *\n * This code was copied from CodeMirror2/lib/util/search.js so that the UI strings \n * could be localized.\n *\n * Replace works a little oddly -- it will do the replace on the next findNext press.\n * You prevent a replace by making sure the match is no longer selected when hitting\n * findNext.\n *\n */\n\n\ndefine('search/FindReplace',['require','exports','module','command/CommandManager','command/Commands','strings','editor/EditorManager'],function (require, exports, module) {\n    \n\n    var CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        EditorManager       = require(\"editor/EditorManager\");\n\n    function SearchState() {\n        this.posFrom = this.posTo = this.query = null;\n        this.marked = [];\n    }\n\n    function getSearchState(cm) {\n        if (!cm._searchState) {\n            cm._searchState = new SearchState();\n        }\n        return cm._searchState;\n    }\n\n    function getSearchCursor(cm, query, pos) {\n        // Heuristic: if the query string is all lowercase, do a case insensitive search.\n        return cm.getSearchCursor(query, pos, typeof query === \"string\" && query === query.toLowerCase());\n    }\n\n    function dialog(cm, text, shortText, f) {\n        if (cm.openDialog) {\n            cm.openDialog(text, f);\n        } else {\n            f(prompt(shortText, \"\"));\n        }\n    }\n\n    function confirmDialog(cm, text, shortText, fs) {\n        if (cm.openConfirm) {\n            cm.openConfirm(text, fs);\n        } else if (confirm(shortText)) {\n            fs[0]();\n        }\n    }\n\n    function parseQuery(query) {\n        var isRE = query.match(/^\\/(.*)\\/([a-z]*)$/);\n        return isRE ? new RegExp(isRE[1], isRE[2].indexOf(\"i\") === -1 ? \"\" : \"i\") : query;\n    }\n\n    function findNext(cm, rev) {\n        cm.operation(function () {\n            var state = getSearchState(cm);\n            var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);\n            if (!cursor.find(rev)) {\n                cursor = getSearchCursor(cm, state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});\n                if (!cursor.find(rev)) {\n                    return;\n                }\n            }\n            cm.setSelection(cursor.from(), cursor.to());\n            state.posFrom = cursor.from();\n            state.posTo = cursor.to();\n        });\n    }\n\n    var queryDialog = Strings.CMD_FIND +\n            ': <input type=\"text\" style=\"width: 10em\"/> <span style=\"color: #888\">(' +\n            Strings.SEARCH_REGEXP_INFO  + ')</span>';\n\n    function doSearch(cm, rev) {\n        var state = getSearchState(cm);\n        if (state.query) {\n            return findNext(cm, rev);\n        }\n        dialog(cm, queryDialog, Strings.CMD_FIND, function (query) {\n            cm.operation(function () {\n                if (!query || state.query) {\n                    return;\n                }\n                state.query = parseQuery(query);\n                if (cm.lineCount() < 2000) { // This is too expensive on big documents.\n                    var cursor = getSearchCursor(cm, query);\n                    while (cursor.findNext()) {\n                        state.marked.push(cm.markText(cursor.from(), cursor.to(), \"CodeMirror-searching\"));\n                    }\n                }\n                state.posFrom = state.posTo = cm.getCursor();\n                findNext(cm, rev);\n            });\n        });\n    }\n\n    function clearSearch(cm) {\n        cm.operation(function () {\n            var state = getSearchState(cm),\n                i;\n            if (!state.query) {\n                return;\n            }\n            state.query = null;\n            for (i = 0; i < state.marked.length; ++i) {\n                state.marked[i].clear();\n            }\n            state.marked.length = 0;\n        });\n    }\n\n    var replaceQueryDialog = Strings.CMD_REPLACE +\n            ': <input type=\"text\" style=\"width: 10em\"/> <span style=\"color: #888\">(' +\n            Strings.SEARCH_REGEXP_INFO  + ')</span>';\n    var replacementQueryDialog = Strings.WITH +\n            ': <input type=\"text\" style=\"width: 10em\"/>';\n    // style buttons to match height/margins/border-radius of text input boxes\n    var style = ' style=\"padding:5px 15px;border:1px #999 solid;border-radius:3px;margin:2px 2px 5px;\"';\n    var doReplaceConfirm = Strings.CMD_REPLACE +\n            '? <button' + style + '>' + Strings.BUTTON_YES +\n            '</button> <button' + style + '>' + Strings.BUTTON_NO +\n            '</button> <button' + style + '>' + Strings.BUTTON_STOP + '</button>';\n\n    function replace(cm, all) {\n        dialog(cm, replaceQueryDialog, Strings.CMD_REPLACE, function (query) {\n            if (!query) {\n                return;\n            }\n            query = parseQuery(query);\n            dialog(cm, replacementQueryDialog, Strings.WITH, function (text) {\n                var match,\n                    fnMatch = function (w, i) { return match[i]; };\n                if (all) {\n                    cm.compoundChange(function () {\n                        cm.operation(function () {\n                            var cursor = getSearchCursor(cm, query);\n                            while (cursor.findNext()) {\n                                if (typeof query !== \"string\") {\n                                    match = cm.getRange(cursor.from(), cursor.to()).match(query);\n                                    cursor.replace(text.replace(/\\$(\\d)/, fnMatch));\n                                } else {\n                                    cursor.replace(text);\n                                }\n                            }\n                        });\n                    });\n                } else {\n                    clearSearch(cm);\n                    var cursor = getSearchCursor(cm, query, cm.getCursor());\n                    var advance = function () {\n                        var start = cursor.from(),\n                            match = cursor.findNext();\n                        if (!match) {\n                            cursor = getSearchCursor(cm, query);\n                            match = cursor.findNext();\n                            if (!match ||\n                                    (start && cursor.from().line === start.line && cursor.from().ch === start.ch)) {\n                                return;\n                            }\n                        }\n                        cm.setSelection(cursor.from(), cursor.to());\n                        confirmDialog(cm, doReplaceConfirm, Strings.CMD_REPLACE + \"?\",\n                                                    [function () { doReplace(match); }, advance]);\n                    };\n                    var doReplace = function (match) {\n                        cursor.replace(typeof query === \"string\" ? text :\n                                            text.replace(/\\$(\\d)/, fnMatch));\n                        advance();\n                    };\n                    advance();\n                }\n            });\n        });\n    }\n\n    function _launchFind() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            var codeMirror = editor._codeMirror;\n\n            // Bring up CodeMirror's existing search bar UI\n            clearSearch(codeMirror);\n            doSearch(codeMirror);\n\n            // Prepopulate the search field with the current selection, if any\n            $(\".CodeMirror-dialog input[type='text']\")\n                .attr(\"value\", codeMirror.getSelection())\n                .get(0).select();\n        }\n    }\n\n    function _findNext() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            doSearch(editor._codeMirror);\n        }\n    }\n\n    function _findPrevious() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            doSearch(editor._codeMirror, true);\n        }\n    }\n\n    function _replace() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            replace(editor._codeMirror);\n        }\n    }\n\n    CommandManager.register(Strings.CMD_FIND,           Commands.EDIT_FIND,          _launchFind);\n    CommandManager.register(Strings.CMD_FIND_NEXT,      Commands.EDIT_FIND_NEXT,     _findNext);\n    CommandManager.register(Strings.CMD_REPLACE,        Commands.EDIT_REPLACE,       _replace);\n    CommandManager.register(Strings.CMD_FIND_PREVIOUS,  Commands.EDIT_FIND_PREVIOUS, _findPrevious);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * ExtensionUtils defines utility methods for implementing extensions.\n */\ndefine('utils/ExtensionUtils',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * Loads a style sheet relative to the extension module.\n     *\n     * @param {!module} module Module provided by RequireJS\n     * @param {!string} path Relative path from the extension folder to a CSS file\n     * @return {!$.Promise} A promise object that is resolved if the CSS file can be loaded.\n     */\n    function loadStyleSheet(module, path) {\n        var modulePath = module.uri.substr(0, module.uri.lastIndexOf(\"/\") + 1),\n            url = encodeURI(modulePath + path),\n            result = new $.Deferred();\n\n        // Make a request for the same file in order to record success or failure.\n        // The link element's onload and onerror events are not consistently supported.\n        $.get(url).done(function () {\n            var $link = $(\"<link/>\");\n            \n            $link.attr({\n                type:       \"text/css\",\n                rel:        \"stylesheet\",\n                href:       url\n            });\n            \n            $(\"head\").append($link[0]);\n            \n            result.resolve($link[0]);\n        }).fail(function (err) {\n            result.reject(err);\n        });\n        \n        return result;\n    }\n    \n    exports.loadStyleSheet = loadStyleSheet;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n /**\n  * This is JavaScript API exposed to the native shell when Brackets is run in a native shell rather than a browser.\n  */\ndefine('utils/ShellAPI',['require','exports','module','command/CommandManager'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var CommandManager     = require(\"command/CommandManager\");\n\n    /**\n     * The native function BracketsShellAPI::DispatchBracketsJSCommand calls this function in order to enable\n     * calling Brackets commands from the native shell.\n     */\n    function executeCommand(eventName) {\n        var evt = window.document.createEvent(\"Event\");\n        evt.initEvent(eventName, false, true);\n        \n        CommandManager.execute(eventName, {evt: evt});\n        \n        //return if default was prevented\n        return evt.defaultPrevented;\n    }\n\n    exports.executeCommand = executeCommand;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global require, define, brackets: true, $, PathUtils, window, navigator, Mustache */\n\nrequire.config({\n    paths: {\n        \"text\" : \"thirdparty/text\",\n        \"i18n\" : \"thirdparty/i18n\"\n    },\n    // Use custom brackets property until CEF sets the correct navigator.language\n    // NOTE: When we change to navigator.language here, we also should change to\n    // navigator.language in ExtensionLoader (when making require contexts for each\n    // extension).\n    locale: window.localStorage.getItem(\"locale\") || brackets.app.language\n});\n\n/**\n * brackets is the root of the Brackets codebase. This file pulls in all other modules as\n * dependencies (or dependencies thereof), initializes the UI, and binds global menus & keyboard\n * shortcuts to their Commands.\n *\n * TODO: (issue #264) break out the definition of brackets into a separate module from the application controller logic\n *\n * Unlike other modules, this one can be accessed without an explicit require() because it exposes\n * a global object, window.brackets.\n *\n * Events:\n *      htmlContentLoadComplete - sent when the HTML DOM is fully loaded. Modules should not touch\n *      or modify DOM elements before this event is sent.\n */\ndefine('brackets',['require','exports','module','widgets/bootstrap-dropdown','widgets/bootstrap-modal','thirdparty/path-utils/path-utils.min','thirdparty/smart-auto-complete/jquery.smart_autocomplete','LiveDevelopment/main','project/ProjectManager','document/DocumentManager','editor/EditorManager','editor/CSSInlineEditor','language/JSUtils','project/WorkingSetView','document/DocumentCommandHandlers','project/FileViewController','project/FileSyncManager','command/KeyBindingManager','command/Commands','command/CommandManager','utils/BuildInfoUtils','editor/CodeHintManager','language/JSLintUtils','utils/PerfUtils','project/FileIndexManager','search/QuickOpen','command/Menus','file/FileUtils','text!htmlContent/main-view.html','strings','widgets/Dialogs','utils/ExtensionLoader','project/SidebarView','utils/Async','utils/UpdateNotification','utils/UrlParams','document/ChangedDocumentTracker','editor/EditorCommandHandlers','debug/DebugCommandHandlers','view/ViewCommandHandlers','search/FindInFiles','search/FindReplace','utils/ExtensionUtils','utils/ShellAPI','preferences/PreferencesManager','command/CommandManager','language/CSSUtils','LiveDevelopment/LiveDevelopment','LiveDevelopment/Inspector/Inspector','utils/NativeApp','utils/ExtensionUtils','utils/UpdateNotification'],function (require, exports, module) {\n    \n    \n    // Load dependent non-module scripts\n    require(\"widgets/bootstrap-dropdown\");\n    require(\"widgets/bootstrap-modal\");\n    require(\"thirdparty/path-utils/path-utils.min\");\n    require(\"thirdparty/smart-auto-complete/jquery.smart_autocomplete\");\n\n    // Load LiveDeveopment\n    require(\"LiveDevelopment/main\");\n    \n    // Load dependent modules\n    var ProjectManager          = require(\"project/ProjectManager\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        CSSInlineEditor         = require(\"editor/CSSInlineEditor\"),\n        JSUtils                 = require(\"language/JSUtils\"),\n        WorkingSetView          = require(\"project/WorkingSetView\"),\n        DocumentCommandHandlers = require(\"document/DocumentCommandHandlers\"),\n        FileViewController      = require(\"project/FileViewController\"),\n        FileSyncManager         = require(\"project/FileSyncManager\"),\n        KeyBindingManager       = require(\"command/KeyBindingManager\"),\n        Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        BuildInfoUtils          = require(\"utils/BuildInfoUtils\"),\n        CodeHintManager         = require(\"editor/CodeHintManager\"),\n        JSLintUtils             = require(\"language/JSLintUtils\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        FileIndexManager        = require(\"project/FileIndexManager\"),\n        QuickOpen               = require(\"search/QuickOpen\"),\n        Menus                   = require(\"command/Menus\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        MainViewHTML            = require(\"text!htmlContent/main-view.html\"),\n        Strings                 = require(\"strings\"),\n        Dialogs                 = require(\"widgets/Dialogs\"),\n        ExtensionLoader         = require(\"utils/ExtensionLoader\"),\n        SidebarView             = require(\"project/SidebarView\"),\n        Async                   = require(\"utils/Async\"),\n        UpdateNotification      = require(\"utils/UpdateNotification\"),\n        UrlParams               = require(\"utils/UrlParams\").UrlParams;\n\n    // Local variables\n    var bracketsReady           = false,\n        bracketsReadyHandlers   = [],\n        params                  = new UrlParams();\n    \n    // read URL params\n    params.parse();\n            \n    //Load modules that self-register and just need to get included in the main project\n    require(\"document/ChangedDocumentTracker\");\n    require(\"editor/EditorCommandHandlers\");\n    require(\"debug/DebugCommandHandlers\");\n    require(\"view/ViewCommandHandlers\");\n    require(\"search/FindInFiles\");\n    require(\"search/FindReplace\");\n    require(\"utils/ExtensionUtils\");\n\n    function _callBracketsReadyHandler(handler) {\n        try {\n            handler();\n        } catch (e) {\n            console.log(\"Exception when calling a 'brackets done loading' handler\");\n            console.log(e);\n        }\n    }\n\n    function _onBracketsReady() {\n        var i;\n        bracketsReady = true;\n        for (i = 0; i < bracketsReadyHandlers.length; i++) {\n            _callBracketsReadyHandler(bracketsReadyHandlers[i]);\n        }\n        bracketsReadyHandlers = [];\n    }\n\n    // WARNING: This event won't fire if ANY extension fails to load or throws an error during init.\n    // To fix this, we need to make a change to _initExtensions (filed as issue 1029)\n    function _registerBracketsReadyHandler(handler) {\n        if (bracketsReady) {\n            _callBracketsReadyHandler(handler);\n        } else {\n            bracketsReadyHandlers.push(handler);\n        }\n    }\n    \n    // TODO: Issue 949 - the following code should be shared\n    \n    function _initGlobalBrackets() {\n        // Define core brackets namespace if it isn't already defined\n        //\n        // We can't simply do 'brackets = {}' to define it in the global namespace because\n        // we're in \"use strict\" mode. Most likely, 'window' will always point to the global\n        // object when this code is running. However, in case it isn't (e.g. if we're running \n        // inside Node for CI testing) we use this trick to get the global object.\n        //\n        // Taken from:\n        //   http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript\n        var Fn = Function, global = (new Fn(\"return this\"))();\n        if (!global.brackets) {\n            global.brackets = {};\n        }\n        \n        // Uncomment the following line to force all low level file i/o routines to complete\n        // asynchronously. This should only be done for testing/debugging.\n        // NOTE: Make sure this line is commented out again before committing!\n        //brackets.forceAsyncCallbacks = true;\n    \n        // Load native shell when brackets is run in a native shell rather than the browser\n        // TODO: (issue #266) load conditionally\n        brackets.shellAPI = require(\"utils/ShellAPI\");\n        \n        brackets.inBrowser = !brackets.hasOwnProperty(\"fs\");\n        \n        brackets.platform = (global.navigator.platform === \"MacIntel\" || global.navigator.platform === \"MacPPC\") ? \"mac\" : \"win\";\n        \n        // Loading extensions requires creating new require.js contexts, which requires access to the global 'require' object\n        // that always gets hidden by the 'require' in the AMD wrapper. We store this in the brackets object here so that \n        // the ExtensionLoader doesn't have to have access to the global object.\n        brackets.libRequire = global.require;\n\n        // Also store our current require.js context (the one that loads brackets core modules) so that extensions can use it\n        // Note: we change the name to \"getModule\" because this won't do exactly the same thing as 'require' in AMD-wrapped\n        // modules. The extension will only be able to load modules that have already been loaded once.\n        brackets.getModule = require;\n\n        // Provide a way for anyone (including code not using require) to register a handler for the brackets 'ready' event\n        // This event is like $(document).ready in that it will call the handler immediately if brackets is already done loading\n        //\n        // WARNING: This event won't fire if ANY extension fails to load or throws an error during init.\n        // To fix this, we need to make a change to _initExtensions (filed as issue 1029)\n        //\n        // TODO (issue 1034): We *could* use a $.Deferred for this, except deferred objects enter a broken\n        // state if any resolution callback throws an exception. Since third parties (e.g. extensions) may\n        // add callbacks to this, we need to be robust to exceptions\n        brackets.ready = _registerBracketsReadyHandler;\n    }\n    \n    // TODO: (issue 1029) Add timeout to main extension loading promise, so that we always call this function\n    // Making this fix will fix a warning (search for issue 1029) related to the brackets 'ready' event.\n    function _initExtensions() {\n        // allow unit tests to override which plugin folder(s) to load\n        var paths = params.get(\"extensions\") || \"default,user\";\n        \n        return Async.doInParallel(paths.split(\",\"), function (item) {\n            return ExtensionLoader.loadAllExtensionsInNativeDirectory(\n                FileUtils.getNativeBracketsDirectoryPath() + \"/extensions/\" + item,\n                \"extensions/\" + item\n            );\n        });\n    }\n    \n    function _initTest() {\n        // TODO: (issue #265) Make sure the \"test\" object is not included in final builds\n        // All modules that need to be tested from the context of the application\n        // must to be added to this object. The unit tests cannot just pull\n        // in the modules since they would run in context of the unit test window,\n        // and would not have access to the app html/css.\n        brackets.test = {\n            PreferencesManager      : require(\"preferences/PreferencesManager\"),\n            ProjectManager          : ProjectManager,\n            DocumentCommandHandlers : DocumentCommandHandlers,\n            FileViewController      : FileViewController,\n            DocumentManager         : DocumentManager,\n            EditorManager           : EditorManager,\n            Commands                : Commands,\n            WorkingSetView          : WorkingSetView,\n            JSLintUtils             : JSLintUtils,\n            PerfUtils               : PerfUtils,\n            JSUtils                 : JSUtils,\n            CommandManager          : require(\"command/CommandManager\"),\n            FileSyncManager         : FileSyncManager,\n            FileIndexManager        : FileIndexManager,\n            Menus                   : Menus,\n            KeyBindingManager       : KeyBindingManager,\n            CodeHintManager         : CodeHintManager,\n            CSSUtils                : require(\"language/CSSUtils\"),\n            LiveDevelopment         : require(\"LiveDevelopment/LiveDevelopment\"),\n            Inspector               : require(\"LiveDevelopment/Inspector/Inspector\"),\n            NativeApp               : require(\"utils/NativeApp\"),\n            ExtensionUtils          : require(\"utils/ExtensionUtils\"),\n            UpdateNotification      : require(\"utils/UpdateNotification\"),\n            doneLoading             : false\n        };\n\n        brackets.ready(function () {\n            brackets.test.doneLoading = true;\n        });\n    }\n    \n    function _initDragAndDropListeners() {\n        // Prevent unhandled drag and drop of files into the browser from replacing \n        // the entire Brackets app. This doesn't prevent children from choosing to\n        // handle drops.\n        $(window.document.body)\n            .on(\"dragover\", function (event) {\n                if (event.originalEvent.dataTransfer.files) {\n                    event.stopPropagation();\n                    event.preventDefault();\n                    event.originalEvent.dataTransfer.dropEffect = \"none\";\n                }\n            })\n            .on(\"drop\", function (event) {\n                if (event.originalEvent.dataTransfer.files) {\n                    event.stopPropagation();\n                    event.preventDefault();\n                }\n            });\n    }\n    \n    function _initCommandHandlers() {\n        // Most command handlers are automatically registered when their module is loaded (see \"modules\n        // that self-register\" above for some). A few commands need an extra kick here though:\n        \n        DocumentCommandHandlers.init($(\"#main-toolbar\"));\n        \n        // About dialog\n        CommandManager.register(Strings.CMD_ABOUT,  Commands.HELP_ABOUT, function () {\n            // If we've successfully determined a \"build number\" via .git metadata, add it to dialog\n            var bracketsSHA = BuildInfoUtils.getBracketsSHA(),\n                bracketsAppSHA = BuildInfoUtils.getBracketsAppSHA(),\n                versionLabel = \"\";\n            if (bracketsSHA) {\n                versionLabel += \" (\" + bracketsSHA.substr(0, 7) + \")\";\n            }\n            if (bracketsAppSHA) {\n                versionLabel += \" (shell \" + bracketsAppSHA.substr(0, 7) + \")\";\n            }\n            $(\"#about-build-number\").text(versionLabel);\n            \n            Dialogs.showModalDialog(Dialogs.DIALOG_ID_ABOUT);\n        });\n    }\n    \n    function _initWindowListeners() {\n        // TODO: (issue 269) to support IE, need to listen to document instead (and even then it may not work when focus is in an input field?)\n        $(window).focus(function () {\n            FileSyncManager.syncOpenDocuments();\n            FileIndexManager.markDirty();\n        });\n        \n    }\n            \n    function _onReady() {\n        // Add the platform (mac or win) to the body tag so we can have platform-specific CSS rules\n        $(\"body\").addClass(\"platform-\" + brackets.platform);\n        \n        EditorManager.setEditorHolder($(\"#editor-holder\"));\n\n        // Let the user know Brackets doesn't run in a web browser yet\n        if (brackets.inBrowser) {\n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_ERROR,\n                Strings.ERROR_BRACKETS_IN_BROWSER_TITLE,\n                Strings.ERROR_BRACKETS_IN_BROWSER\n            );\n        }\n\n        _initDragAndDropListeners();\n        _initCommandHandlers();\n        KeyBindingManager.init();\n        Menus.init(); // key bindings should be initialized first\n        _initWindowListeners();\n        \n        // Read \"build number\" SHAs off disk at the time the matching Brackets JS code is being loaded, instead\n        // of later, when they may have been updated to a different version\n        BuildInfoUtils.init();\n\n        // Use quiet scrollbars if we aren't on Lion. If we're on Lion, only\n        // use native scroll bars when the mouse is not plugged in or when\n        // using the \"Always\" scroll bar setting. \n        var osxMatch = /Mac OS X 10\\D([\\d+])\\D/.exec(navigator.userAgent);\n        if (osxMatch && osxMatch[1] && Number(osxMatch[1]) >= 7) {\n            // test a scrolling div for scrollbars\n            var $testDiv = $(\"<div style='position:fixed;left:-50px;width:50px;height:50px;overflow:auto;'><div style='width:100px;height:100px;'/></div>\").appendTo(window.document.body);\n            \n            if ($testDiv.outerWidth() === $testDiv.get(0).clientWidth) {\n                $(\".sidebar\").removeClass(\"quiet-scrollbars\");\n            }\n            \n            $testDiv.remove();\n        }\n        \n        PerfUtils.addMeasurement(\"Application Startup\");\n        \n        // finish UI initialization before loading extensions\n        var initialProjectPath = ProjectManager.getInitialProjectPath();\n        ProjectManager.openProject(initialProjectPath).done(function () {\n            _initTest();\n            _initExtensions().always(_onBracketsReady);\n        });\n        \n        // Check for updates\n        if (!params.get(\"skipUpdateCheck\")) {\n            UpdateNotification.checkForUpdate();\n        }\n    }\n            \n    // Main Brackets initialization\n    _initGlobalBrackets();\n\n    // Localize MainViewHTML and inject into <BODY> tag\n    $('body').html(Mustache.render(MainViewHTML, Strings));\n    // modules that depend on the HTML DOM should listen to\n    // the htmlContentLoadComplete event.\n    $(brackets).trigger(\"htmlContentLoadComplete\");\n\n    $(window.document).ready(_onReady);\n    \n});\n\n/* ============================================================\n * bootstrap-dropdown.js v1.4.0\n * http://twitter.github.com/bootstrap/javascript.html#dropdown\n * ============================================================\n * Copyright 2011 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ============================================================ */\n\n\n!function( $ ){\n\n  \"use strict\"\n\n  /* DROPDOWN PLUGIN DEFINITION\n   * ========================== */\n\n  $.fn.dropdown = function ( selector ) {\n    return this.each(function () {\n      $(this).delegate(selector || d, 'click', function (e) {\n        var li = $(this).parent('li')\n          , isActive = li.hasClass('open')\n\n        clearMenus()\n        !isActive && li.toggleClass('open')\n        return false\n      })\n    })\n  }\n\n  /* APPLY TO STANDARD DROPDOWN ELEMENTS\n   * =================================== */\n\n  var d = 'a.menu, .dropdown-toggle'\n\n  function clearMenus() {\n    $(d).parent('li').removeClass('open')\n  }\n\n  $(function () {\n    $('html').bind(\"click\", clearMenus)\n    $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' )\n  })\n\n}( window.jQuery || window.ender );\n\ndefine(\"widgets/bootstrap-dropdown\", function(){});\n\n/* =========================================================\n * bootstrap-modal.js v1.4.0\n * http://twitter.github.com/bootstrap/javascript.html#modal\n * =========================================================\n * Copyright 2011 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================= */\n\n\n!function( $ ){\n\n  \"use strict\"\n\n /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)\n  * ======================================================= */\n\n  var transitionEnd\n\n  $(document).ready(function () {\n\n    $.support.transition = (function () {\n      var thisBody = document.body || document.documentElement\n        , thisStyle = thisBody.style\n        , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined\n      return support\n    })()\n\n    // set CSS transition event type\n    if ( $.support.transition ) {\n      transitionEnd = \"TransitionEnd\"\n      if ( $.browser.webkit ) {\n        transitionEnd = \"webkitTransitionEnd\"\n      } else if ( $.browser.mozilla ) {\n        transitionEnd = \"transitionend\"\n      } else if ( $.browser.opera ) {\n        transitionEnd = \"oTransitionEnd\"\n      }\n    }\n\n  })\n\n\n /* MODAL PUBLIC CLASS DEFINITION\n  * ============================= */\n\n  var Modal = function ( content, options ) {\n    this.settings = $.extend({}, $.fn.modal.defaults, options)\n    this.$element = $(content)\n      .delegate('.close', 'click.modal', $.proxy(this.hide, this))\n\n    if ( this.settings.show ) {\n      this.show()\n    }\n\n    return this\n  }\n\n  Modal.prototype = {\n\n      toggle: function () {\n        return this[!this.isShown ? 'show' : 'hide']()\n      }\n\n    , show: function () {\n        var that = this\n        this.isShown = true\n        this.$element.trigger('show')\n\n        escape.call(this)\n        backdrop.call(this, function () {\n          var transition = $.support.transition && that.$element.hasClass('fade')\n\n          that.$element\n            .appendTo(document.body)\n            .show()\n\n          if (transition) {\n            that.$element[0].offsetWidth // force reflow\n          }\n\n          that.$element.addClass('in')\n\n          transition ?\n            that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) :\n            that.$element.trigger('shown')\n\n        })\n\n        return this\n      }\n\n    , hide: function (e) {\n        e && e.preventDefault()\n\n        if ( !this.isShown ) {\n          return this\n        }\n\n        var that = this\n        this.isShown = false\n\n        escape.call(this)\n\n        this.$element\n          .trigger('hide')\n          .removeClass('in')\n\n        $.support.transition && this.$element.hasClass('fade') ?\n          hideWithTransition.call(this) :\n          hideModal.call(this)\n\n        return this\n      }\n\n  }\n\n\n /* MODAL PRIVATE METHODS\n  * ===================== */\n\n  function hideWithTransition() {\n    // firefox drops transitionEnd events :{o\n    var that = this\n      , timeout = setTimeout(function () {\n          that.$element.unbind(transitionEnd)\n          hideModal.call(that)\n        }, 500)\n\n    this.$element.one(transitionEnd, function () {\n      clearTimeout(timeout)\n      hideModal.call(that)\n    })\n  }\n\n  function hideModal (that) {\n    this.$element\n      .hide()\n      .trigger('hidden')\n\n    backdrop.call(this)\n  }\n\n  function backdrop ( callback ) {\n    var that = this\n      , animate = this.$element.hasClass('fade') ? 'fade' : ''\n    if ( this.isShown && this.settings.backdrop ) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      if ( this.settings.backdrop != 'static' ) {\n        this.$backdrop.click($.proxy(this.hide, this))\n      }\n\n      if ( doAnimate ) {\n        this.$backdrop[0].offsetWidth // force reflow\n      }\n\n      this.$backdrop.addClass('in')\n\n      doAnimate ?\n        this.$backdrop.one(transitionEnd, callback) :\n        callback()\n\n    } else if ( !this.isShown && this.$backdrop ) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) :\n        removeBackdrop.call(this)\n\n    } else if ( callback ) {\n       callback()\n    }\n  }\n\n  function removeBackdrop() {\n    this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  function escape() {\n    var that = this\n    if ( this.isShown && this.settings.keyboard ) {\n      $(document).bind('keyup.modal', function ( e ) {\n        if ( e.which == 27 ) {\n          that.hide()\n        }\n      })\n    } else if ( !this.isShown ) {\n      $(document).unbind('keyup.modal')\n    }\n  }\n\n\n /* MODAL PLUGIN DEFINITION\n  * ======================= */\n\n  $.fn.modal = function ( options ) {\n    var modal = this.data('modal')\n\n    if (!modal) {\n\n      if (typeof options == 'string') {\n        options = {\n          show: /show|toggle/.test(options)\n        }\n      }\n\n      return this.each(function () {\n        $(this).data('modal', new Modal(this, options))\n      })\n    }\n\n    if ( options === true ) {\n      return modal\n    }\n\n    if ( typeof options == 'string' ) {\n      modal[options]()\n    } else if ( modal ) {\n      modal.toggle()\n    }\n\n    return this\n  }\n\n  $.fn.modal.Modal = Modal\n\n  $.fn.modal.defaults = {\n    backdrop: false\n  , keyboard: false\n  , show: false\n  }\n\n\n /* MODAL DATA- IMPLEMENTATION\n  * ========================== */\n\n  $(document).ready(function () {\n    $('body').delegate('[data-controls-modal]', 'click', function (e) {\n      e.preventDefault()\n      var $this = $(this).data('show', true)\n      $('#' + $this.attr('data-controls-modal')).modal( $this.data() )\n    })\n  })\n\n}( window.jQuery || window.ender );\n\ndefine(\"widgets/bootstrap-modal\", function(){});\n\n// path-utils.js - version 0.1\n// Copyright (c) 2011, Kin Blas\n// All rights reserved.\n// \n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n//     * Redistributions of source code must retain the above copyright\n//       notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above copyright\n//       notice, this list of conditions and the following disclaimer in the\n//       documentation and/or other materials provided with the distribution.\n//     * Neither the name of the <organization> nor the\n//       names of its contributors may be used to endorse or promote products\n//       derived from this software without specific prior written permission.\n// \n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\n// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n(function(l){function m(a){return function(e){return b.parseUrl(e)[a]}}var b={urlParseRE:/^(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#\\.]*(?:\\.[^\\?#\\.]+)*(\\.[^\\?#\\.]+)|[^\\?#]*)))?(\\?[^#]+)?)(#.*)?/,parsedUrlPropNames:\"href,hrefNoHash,hrefNoSearch,domain,protocol,doubleSlash,authority,userinfo,username,password,host,hostname,port,pathname,directory,filename,filenameExtension,search,hash\".split(\",\"),\ndefaultPorts:{http:\"80\",https:\"443\",ftp:\"20\",ftps:\"990\"},parseUrl:function(a){if(a&&typeof a===\"object\")return a;var a=b.urlParseRE.exec(a||\"\")||[],e=b.parsedUrlPropNames,c=e.length,f={},d;for(d=0;d<c;d++)f[e[d]]=a[d]||\"\";return f},port:function(a){a=b.parseUrl(a);return a.port||b.defaultPorts[a.protocol]},isSameDomain:function(a,e){return b.parseUrl(a).domain===b.parseUrl(e).domain},isRelativeUrl:function(a){return b.parseUrl(a).protocol===\"\"},isAbsoluteUrl:function(a){return b.parseUrl(a).protocol!==\n\"\"},makePathAbsolute:function(a,e){if(a&&a.charAt(0)===\"/\")return a;for(var a=a||\"\",c=(e=e?e.replace(/^\\/|(\\/[^\\/]*|[^\\/]+)$/g,\"\"):\"\")?e.split(\"/\"):[],b=a.split(\"/\"),d=0;d<b.length;d++){var j=b[d];switch(j){case \".\":break;case \"..\":c.length&&c.pop();break;default:c.push(j)}}return\"/\"+c.join(\"/\")},makePathRelative:function(a,b){for(var b=b?b.replace(/^\\/|\\/?[^\\/]*$/g,\"\"):\"\",a=a?a.replace(/^\\//,\"\"):\"\",c=b?b.split(\"/\"):[],f=a.split(\"/\"),d=[],j=c.length,g=false,i=0;i<j;i++)(g=g||f[0]!==c[i])?d.push(\"..\"):\nf.shift();return d.concat(f).join(\"/\")},makeUrlAbsolute:function(a,e){if(!b.isRelativeUrl(a))return a;var c=b.parseUrl(a),f=b.parseUrl(e),d=c.protocol||f.protocol,g=c.protocol?c.doubleSlash:c.doubleSlash||f.doubleSlash,h=c.authority||f.authority,i=c.pathname!==\"\",k=b.makePathAbsolute(c.pathname||f.filename,f.pathname);return d+g+h+k+(c.search||!i&&f.search||\"\")+c.hash}},g,h,k=b.parsedUrlPropNames,n=k.length;for(g=0;g<n;g++)h=k[g],b[h]||(b[h]=m(h));l.PathUtils=b})(window);\n\ndefine(\"thirdparty/path-utils/path-utils.min\", function(){});\n\n/**\n * Smart Auto Complete plugin \n * \n * Copyright (c) 2011 Lakshan Perera (laktek.com)\n * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)  licenses.\n * \n*/\n\n/*\n Requirements: jQuery 1.5 or above\n\n  Usage:\n  $(target).smartAutoComplete({options})\n\n  Options:\n  minCharLimit: (integer) minimum characters user have to type before invoking the autocomplete (default: 1)\n  maxCharLimit: (integer) maximum characters user can type while invoking the autocomplete (default: null (unlimited))\n  maxResults: (integer) maximum number of results to return (default: null (unlimited))\n  delay: (integer) delay before autocomplete starts (default: 0)\n  disabled: (boolean) whether autocomplete disabled on the field (default: false)\n  forceSelect: (boolean) If set to true, field will be always filled with best matching result, without leaving the custom input.\n               Better to enable this option, if you want autocomplete field to behave similar to a HTML select field. (Check Example 2 in the demo)\n               (default: false)\n  typeAhead: (boolean) If set to true, it will offer the best matching result in grey within the field; that can be auto-completed by pressing the right arrow-key or enter.\n             This is similar to behaviour in Google Instant Search's query field (Check Example 3 in the demo) \n             (default: false)\n  source:  (string/array) you can supply an array with items or a string containing a URL to fetch items for the source\n           this is optional if you prefer to have your own filter method \n  filter: (function) define a custom function that would return matching items to the entered text (this will override the default filtering algorithm)\n          should return an array or a Deferred object (ajax call)\n          parameters available: term, source \n  resultFormatter: (function) the function you supply here will be called to format the output of an individual result.\n                   should return a string\n                   parameters available: result \n  resultsContainer: (selector) to which element(s) the result should be appended.\n  resultElement: (selector) references to the result elements collection (e.g. li, div.result) \n\n  Events:\n  keyIn: fires when user types into the field (parameters: query)\n  resultsReady: fires when the filter function returns (parameters: results)\n  showResults: fires when results are shown (parameters: results)\n  noResults: fires when filter returns an empty array\n  itemSelect: fires when user selects an item from the result list (paramters: item)\n  itemFocus: fires when user highlights an item with mouse or arrow keys (paramters: item)\n  itemUnfocus: fires when user moves out from an highlighted item (paramters: item)\n  lostFocus: fires when autocomplete field loses focus by user clicking outside of the field or focusing on another field. Also, this event is fired when a value is selected\n\n })\n*/\n\n(function($){\n  $.fn.smartAutoComplete = function(){    \n\n    if(arguments.length < 1){\n      // get the smart autocomplete object of the first element and return \n      var first_element = this[0];\n      return $(first_element).data(\"smart-autocomplete\")\n    }\n\n    var default_filter_matcher = function(term, source, context){\n                                    var matcher = new RegExp(term.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, \"\\\\$&\"), \"i\" );\n\n                                    return $.grep(source, function(value) {\n                                      return matcher.test( value );\n                                    });\n\n                                 }\n\n    var default_options = {\n                            minCharLimit: 1, \n                            maxCharLimit: null, \n                            maxResults: null,\n                            delay: 0,\n                            disabled: false,\n                            forceSelect: false,\n                            typeAhead: false,\n                            resultElement: \"li\",\n                            resultFormatter: function(r){ return (\"<li>\" + r + \"</li>\"); },\n                            filter: function(term, source){    \n                              var context = this;\n                              var options = $(context).data('smart-autocomplete');\n                              \n\n                              //when source is an array\n                              if($.type(source) === \"array\") {\n                                // directly map\n                                var results = default_filter_matcher(term, source, context);\n                                return results; \n                              }\n                              //when source is a string\n                              else if($.type(source) === \"string\"){\n                                // treat the string as a URL endpoint\n                                // pass the query as 'term'\n                                \n                                return $.Deferred(function(dfd){ \n                                  $.ajax({\n                                    url: source,\n                                    data: {\"term\": term},\n                                    dataType: \"json\"\n                                  }).success( function(data){\n                                    dfd.resolve( default_filter_matcher(term, data, context) );          \n                                  }); \n                                }).promise();\n                                \n                              }\n\n                            },\n\n                            alignResultsContainer: false,\n\n                            clearResults: function(){\n                              //remove type ahead field\n                              var type_ahead_field = $(this.context).prev(\".smart_autocomplete_type_ahead_field\");\n                              $(this.context).css({ background: type_ahead_field.css(\"background\") });\n                              type_ahead_field.remove();\n                              \n                              //clear results div\n                              $(this.resultsContainer).html(\"\");\n                            },\n\n                            setCurrentSelectionToContext: function(){\n                                if(this.rawResults.length > 0 && this.currentSelection >= 0)\n                                  $(this.context).val(this.rawResults[(this.currentSelection)]);\n                            },\n\n                            setItemSelected: function(val){\n                              this.itemSelected = val;\n                            },\n\n                            autocompleteFocused: false,\n\n                            setAutocompleteFocused: function(val){\n                              this.autocompleteFocused = val;\n                            }\n\n    };\n\n    //define the default events\n    $.event.special.keyIn = {\n      setup: function(){ return false; }, \n\n      _default: function(ev){\n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n        var source = options.source || null;\n        var filter = options.filter;\n        var maxChars = (options.maxCharLimit > 0 ?  options.maxCharLimit : Number.POSITIVE_INFINITY)\n\n        //event specific data\n        var query = ev.smartAutocompleteData.query;\n\n        if(options.disabled || (query.length > maxChars)){\n          return false;\n        }\n\n        //set item selected property\n        options.setItemSelected(false);\n\n        //set autocomplete focused\n        options.setAutocompleteFocused(true);\n\n        //call the filter function with delay\n        setTimeout(function(){\n          $.when( filter.apply(options, [query, options.source]) ).done(function( results ){\n            //do the trimming\n            var trimmed_results = (options.maxResults > 0 ? results.splice(0, options.maxResults) : results);\n\n            $(context).trigger('resultsReady', [trimmed_results]);\n          });\n        }, options.delay);\n      }\n    };\n\n    $.event.special.resultsReady = {\n      setup: function(){ return false },\n\n      _default: function(ev){\n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n\n        //event specific data\n        var results = ev.smartAutocompleteData.results;\n\n        //exit if smart complete is disabled\n        if(options.disabled)\n          return false;\n\n        //clear all previous results \n        $(context).smartAutoComplete().clearResults();\n\n        //save the raw results\n        options.rawResults = results;\n\n        //fire the no match event and exit if no matching results\n        if(results.length < 1){\n          $(context).trigger('noResults');\n          return false\n        }\n\n        //call the results formatter function\n        var formatted_results = $.map(results, function(result){\n        return options.resultFormatter.apply(options, [result]);\n        });\n\n        var formatted_results_html = formatted_results.join(\"\");\n\n        //append the results to the container\n        if(options.resultsContainer)\n          $(options.resultsContainer).append(formatted_results_html);\n\n        //trigger results ready event\n        $(context).trigger('showResults', [results]);\n      }             \n    };\n\n    $.event.special.showResults = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n        var results_container = $(options.resultsContainer);\n\n        //event specific data\n        var raw_results = ev.smartAutocompleteData.results; \n\n        //type ahead\n        if(options.typeAhead && (raw_results[0].substr(0, $(context).val().length) == $(context).val()) ){\n          var suggestion = raw_results[0]; //options.typeAheadExtractor($(context).val(), raw_results[0]); \n          \n          //add new typeAhead field\n          $(context).before(\"<input class='smart_autocomplete_type_ahead_field' type='text' autocomplete='off' disabled='disabled' value='\" + suggestion + \"'/>\");\n\n          $(context).css({\n            position: \"relative\",\n            zIndex: 2,\n            background: 'transparent'\n          });\n\n          var typeAheadField = $(context).prev(\"input\");\n          typeAheadField.css({\n            position: \"absolute\",\n            zIndex: 1,\n            overflow: 'hidden',\n            background: $(context).css(\"background\"),\n            borderColor: 'transparent',\n            width: $(context).width(),\n            color: 'silver'\n          });\n\n          //trigger item over for first item\n          options.currentSelection = 0;\n          if(results_container)\n            $(context).trigger('itemFocus', results_container.children()[options.currentSelection]);\n        }\n\n        //show the results container after aligning it with the field \n        if(results_container){\n          if(options.alignResultsContainer){\n            results_container.css({ \n                  position: \"absolute\",\n                  top: function(){ return $(context).offset().top + $(context).height(); }, \n                  left: function(){ return $(context).offset().left; }, \n                  width: function(){ return $(context).width(); }, \n                  zIndex: 1000\n            })\n          }  \n          results_container.show();\n        }\n\n      }\n    };\n\n    $.event.special.noResults = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n        var result_container = $(options.resultsContainer);\n\n        if(result_container){\n         //clear previous results\n         options.clearResults(); \n        }\n\n      }\n    };\n\n    $.event.special.itemSelect = { \n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n\n        //event specific data\n        var selected_item = ev.smartAutocompleteData.item;\n\n        //get the text from selected item\n        var selected_value = $(selected_item).text() || $(selected_item).val();\n        //set it as the value of the autocomplete field\n        $(context).val(selected_value); \n\n        //set item selected property\n        options.setItemSelected(true);\n\n        //set number of current chars in field \n        options.originalCharCount = $(context).val().length;\n        \n        //trigger lost focus\n        $(context).trigger('lostFocus');\n      }\n    };\n\n    $.event.special.itemFocus = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n\n        //event specific data\n        var item = ev.smartAutocompleteData.item;\n\n        $(item).addClass(\"smart_autocomplete_highlight\");\n      }\n    };\n\n    $.event.special.itemUnfocus = { \n      setup: function(){ return false },\n\n      _default: function(ev){    \n\n        //event specific data\n        var item = ev.smartAutocompleteData.item;\n\n        $(item).removeClass(\"smart_autocomplete_highlight\");\n      }\n    }\n\n    $.event.special.lostFocus = {\n      setup: function(){ return false },\n\n      _default: function(ev){    \n        var context = ev.target;\n        var options = $(context).data(\"smart-autocomplete\");\n\n        //if force select is selected and no item is selected, clear currently entered text \n        if(options.forceSelect && !options.itemSelected)\n          $(options.context).val(\"\");\n\n        //unset autocomplete focused\n        options.setAutocompleteFocused(false);\n\n        //clear results\n        options.clearResults(); \n\n        //hide the results container\n        if(options.resultsContainer)\n          $(options.resultsContainer).hide();\n\n        //set current selection to null\n        options.currentSelection = null;\n      }\n    };\n\n    var passed_options = arguments[0];\n\n    return this.each(function(i) { \n      //set the options\n      var options = $.extend(default_options, $(this).data(\"smart-autocomplete\"), passed_options);\n      //set the context\n      options['context'] = this;\n\n      //if a result container is not defined\n      if($.type(options.resultsContainer) === 'undefined' ){\n        //define the default result container if it is already not defined\n        var default_container = $(\"<ul class='smart_autocomplete_container' style='display:none'></ul>\");\n        default_container.appendTo(\"body\");\n\n        options.resultsContainer = default_container;\n        options.alignResultsContainer = true;\n      }\n\n      $(this).data(\"smart-autocomplete\", options);\n\n      // bind user events\n      $(this).keyup(function(ev){\n        //get the options\n        var options = $(this).data(\"smart-autocomplete\");\n\n        //up arrow\n        if(ev.keyCode == '38'){\n\n          if(options.resultsContainer){\n            var current_selection = options.currentSelection || 0;\n            var result_suggestions = $(options.resultsContainer).children();\n\n            if(current_selection >= 0)\n              $(options.context).trigger('itemUnfocus', result_suggestions[current_selection] );\n\n            if(--current_selection <= 0)\n              current_selection = 0;\n\n            options['currentSelection'] = current_selection;\n\n            $(options.context).trigger('itemFocus', [ result_suggestions[current_selection] ] );\n          }\n        }\n\n        //down arrow\n        else if(ev.keyCode == '40'){\n\n          if(options.resultsContainer && options.resultsContainer.is(':visible')){\n            var current_selection = options.currentSelection;\n            var result_suggestions = $(options.resultsContainer).children();\n\n            if(current_selection >= 0)\n              $(options.context).trigger('itemUnfocus', result_suggestions[current_selection] );\n\n            if(isNaN(current_selection) || null == current_selection || (++current_selection >= result_suggestions.length) )\n              current_selection = 0;\n\n            options['currentSelection'] = current_selection;\n\n            $(options.context).trigger('itemFocus', [ result_suggestions[current_selection] ] );\n          }\n          //trigger keyIn event on down key\n          else {\n            $(options.context).trigger('keyIn', [$(this).val()]); \n          }\n          \n        }\n\n        //right arrow & enter key\n        else if(ev.keyCode == '39' || ev.keyCode == '13'){\n          var type_ahead_field = $(options.context).prev('.smart_autocomplete_type_ahead_field');\n          if(options.resultsContainer && $(options.resultsContainer).is(':visible')){\n            var current_selection = options.currentSelection;\n            var result_suggestions = $(options.resultsContainer).children();\n\n            $(options.context).trigger('itemSelect', [ result_suggestions[current_selection] ] );\n          }\n          else if(options.typeAhead && type_ahead_field.is(':visible'))\n            $(options.context).trigger('itemSelect', [ type_ahead_field ] );\n\n          return false;\n        }\n\n        else {\n         var current_char_count = $(options.context).val().length;\n         //check whether the string has modified\n         if(options.originalCharCount == current_char_count)\n           return;\n\n         //check minimum and maximum number of characters are typed\n         if(current_char_count >= options.minCharLimit){\n          $(options.context).trigger('keyIn', [$(this).val()]); \n         }\n         else{\n            if(options.autocompleteFocused){ \n              options.currentSelection = null;\n              $(options.context).trigger('lostFocus');\n            }\n         }\n\n        }\n      });\n\n      $(this).focus(function(){\n        //if the field is in a form capture the return key event \n        $(this).closest(\"form\").bind(\"keydown.block_for_smart_autocomplete\", function(ev){\n          var type_ahead_field = $(options.context).prev('.smart_autocomplete_type_ahead_field');\n          if(ev.keyCode == '13'){\n            if(options.resultsContainer && $(options.resultsContainer).is(':visible')){\n              var current_selection = options.currentSelection;\n              var result_suggestions = $(options.resultsContainer).children();\n\n              $(options.context).trigger('itemSelect', [ result_suggestions[current_selection] ] );\n              return false;\n            }\n            else if(options.typeAhead && type_ahead_field.is(':visible') ){\n              $(options.context).trigger('itemSelect', [ type_ahead_field ] );\n              return false;\n            }\n          }\n        });\n\n        if(options.forceSelect){\n          $(this).select(); \n        }\n      });\n\n      //check for loosing focus on smart complete field and results container\n      //$(this).blur(function(ev){\n      $(document).bind(\"focusin click\", function(ev){\n        if(options.autocompleteFocused){ \n          var elemIsParent = $.contains(options.resultsContainer[0], ev.target);\n          if(ev.target == options.resultsContainer[0] || ev.target == options.context || elemIsParent) return\n\n          $(options.context).closest(\"form\").unbind(\"keydown.block_for_smart_autocomplete\");\n          $(options.context).trigger('lostFocus');\n        }\n      });\n\n      //bind events to results container\n      $(options.resultsContainer).delegate(options.resultElement, 'mouseenter.smart_autocomplete', function(){\n        var current_selection = options.currentSelection || 0;\n        var result_suggestions = $(options.resultsContainer).children();\n\n        options['currentSelection'] = $(this).prevAll().length;\n\n        $(options.context).trigger('itemFocus', [this] );\n          \n      });\n\n      $(options.resultsContainer).delegate(options.resultElement, 'mouseleave.smart_autocomplete', function(){\n        $(options.context).trigger('itemUnfocus', [this] );\n      });\n\n      $(options.resultsContainer).delegate(options.resultElement, 'click.smart_autocomplete', function(){\n        $(options.context).trigger('itemSelect', [this]);\n        return false\n      });\n\n      //bind plugin specific events\n      $(this).bind({\n        keyIn: function(ev, query){ ev.smartAutocompleteData  = {'query': query }; },\n        resultsReady: function(ev, results){ ev.smartAutocompleteData  = {'results': results }; }, \n        showResults: function(ev, results){ ev.smartAutocompleteData = {'results': results } },\n        noResults: function(){},\n        lostFocus: function(){},\n        itemSelect: function(ev, item){ ev.smartAutocompleteData = {'item': item }; },\n        itemFocus: function(ev, item){ ev.smartAutocompleteData = {'item': item }; },\n        itemUnfocus: function(ev, item){ ev.smartAutocompleteData = {'item': item }; }\n      });\n    });\n      \n  }\n})(jQuery);\n\ndefine(\"thirdparty/smart-auto-complete/jquery.smart_autocomplete\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n/**\n * Utilities for working with Deferred, Promise, and other asynchronous processes.\n */\ndefine('utils/Async',['require','exports','module'],function (require, exports, module) {\n    \n    \n    // Further ideas for Async utilities...\n    //  - Utilities for blocking UI until a Promise completes?\n    //  - A \"SuperDeferred\" could feature some very useful enhancements:\n    //     - API for cancellation (non guaranteed, best attempt)\n    //     - Easier way to add a timeout clause (withTimeout() wrapper below is more verbose)\n    //     - Encapsulate the task kickoff code so you can start it later, e.g. superDeferred.start()\n    //  - Deferred/Promise are unable to do anything akin to a 'finally' block. It'd be nice if we\n    //    could harvest exceptions across all steps of an async process and pipe them to a handler,\n    //    so that we don't leave UI-blocking overlays up forever, etc. But this is hard: we'd have\n    //    wrap every async callback (including low-level native ones that don't use [Super]Deferred)\n    //    to catch exceptions, and then understand which Deferred(s) the code *would* have resolved/\n    //    rejected had it run to completion.\n    \n\n    /**\n     * Executes a series of tasks in parallel, returning a \"master\" Promise that is resolved once\n     * all the tasks have resolved. If one or more tasks fail, behavior depends on the failFast\n     * flag:\n     *   - If true, the master Promise is rejected as soon as the first task fails. The remaining\n     *     tasks continue to completion in the background.\n     *   - If false, the master Promise is rejected after all tasks have completed.\n     *\n     * If nothing fails:          (M = master promise; 1-4 = tasks; d = done; F = fail)\n     *  M  ------------d\n     *  1 >---d        .\n     *  2 >------d     .\n     *  3 >---------d  .\n     *  4 >------------d\n     *\n     * With failFast = false:\n     *  M  ------------F\n     *  1 >---d     .  .\n     *  2 >------d  .  .\n     *  3 >---------F  .\n     *  4 >------------d\n     *\n     * With failFast = true: -- equivalent to $.when()\n     *  M  ---------F\n     *  1 >---d     .\n     *  2 >------d  .\n     *  3 >---------F\n     *  4 >------------d   (#4 continues even though master Promise has failed)\n     * (Note: if tasks finish synchronously, the behavior is more like failFast=false because you\n     * won't get a chance to respond to the master Promise until after all items have been processed)\n     *\n     * To perform task-specific work after an individual task completes, attach handlers to each\n     * Promise before beginProcessItem() returns it.\n     *\n     * Note: don't use this if individual tasks (or their done/fail handlers) could ever show a user-\n     * visible dialog: because they run in parallel, you could show multiple dialogs atop each other.\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @param {!boolean} failFast\n     * @return {$.Promise}\n     */\n    function doInParallel(items, beginProcessItem, failFast) {\n        var promises = [];\n        var masterDeferred = new $.Deferred();\n        \n        if (items.length === 0) {\n            masterDeferred.resolve();\n            \n        } else {\n            var numCompleted = 0;\n            var hasFailed = false;\n            \n            items.forEach(function (item, i) {\n                var itemPromise = beginProcessItem(item, i);\n                promises.push(itemPromise);\n                \n                itemPromise.fail(function () {\n                    if (failFast) {\n                        masterDeferred.reject();\n                    } else {\n                        hasFailed = true;\n                    }\n                });\n                itemPromise.always(function () {\n                    numCompleted++;\n                    if (numCompleted === items.length) {\n                        if (hasFailed) {\n                            masterDeferred.reject();\n                        } else {\n                            masterDeferred.resolve();\n                        }\n                    }\n                });\n            });\n            \n        }\n        \n        return masterDeferred.promise();\n    }\n    \n    /**\n     * Executes a series of tasks in serial (task N does not begin until task N-1 has completed).\n     * Returns a \"master\" Promise that is resolved once all the tasks have resolved. If one or more\n     * tasks fail, behavior depends on the failAndStopFast flag:\n     *   - If true, the master Promise is rejected as soon as the first task fails. The remaining\n     *     tasks are never started (the serial sequence is stopped).\n     *   - If false, the master Promise is rejected after all tasks have completed.\n     *\n     * If nothing fails:\n     *  M  ------------d\n     *  1 >---d        .\n     *  2     >--d     .\n     *  3        >--d  .\n     *  4           >--d\n     *\n     * With failAndStopFast = false:\n     *  M  ------------F\n     *  1 >---d     .  .\n     *  2     >--d  .  .\n     *  3        >--F  .\n     *  4           >--d\n     *\n     * With failAndStopFast = true:\n     *  M  ---------F\n     *  1 >---d     .\n     *  2     >--d  .\n     *  3        >--F\n     *  4          (#4 never runs)\n     *\n     * To perform task-specific work after an individual task completes, attach handlers to each\n     * Promise before beginProcessItem() returns it.\n     * \n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @param {!boolean} failAndStopFast\n     * @return {$.Promise}\n     */\n    function doSequentially(items, beginProcessItem, failAndStopFast) {\n\n        var masterDeferred = new $.Deferred(),\n            hasFailed = false;\n        \n        function doItem(i) {\n            if (i >= items.length) {\n                if (hasFailed) {\n                    masterDeferred.reject();\n                } else {\n                    masterDeferred.resolve();\n                }\n                return;\n            }\n            \n            var itemPromise = beginProcessItem(items[i], i);\n            \n            itemPromise.done(function () {\n                doItem(i + 1);\n            });\n            itemPromise.fail(function () {\n                if (failAndStopFast) {\n                    masterDeferred.reject();\n                    // note: we do NOT process any further items in this case\n                } else {\n                    hasFailed = true;\n                    doItem(i + 1);\n                }\n            });\n        }\n        \n        doItem(0);\n        \n        return masterDeferred.promise();\n    }\n    \n    /**\n     * Executes a series of tasks sequentially in time-slices less than maxBlockingTime.\n     * Processing yields by idleTime between time-slices.\n     * \n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} fnProcessItem\n     * @param {!number} maxBlockingTime\n     * @param {!number} idleTime\n     * @return {$.Promise}\n     */\n    function doSequentiallyInBackground(items, fnProcessItem, maxBlockingTime, idleTime) {\n        \n        maxBlockingTime = maxBlockingTime || 15;\n        idleTime = idleTime || 30;\n        \n        var sliceStartTime = (new Date()).getTime();\n        \n        return doSequentially(items, function (item, i) {\n            var result = new $.Deferred();\n            \n            // process the next item\n            fnProcessItem(item, i);\n            \n            // if we've exhausted our maxBlockingTime\n            if ((new Date()).getTime() - sliceStartTime >= maxBlockingTime) {\n                //yield\n                window.setTimeout(function () {\n                    sliceStartTime = (new Date()).getTime();\n                    result.resolve();\n                }, idleTime);\n            } else {\n                //continue processing\n                result.resolve();\n            }\n\n            return result;\n        }, false);\n    }\n    \n    \n    /**\n     * Executes a series of tasks in parallel, saving up error info from any that fail along the way.\n     * Returns a Promise that is only resolved/rejected once all tasks are complete. This is\n     * essentially a wrapper around doInParallel(..., false).\n     *\n     * If one or more tasks failed, the entire \"master\" promise is rejected at the end - with one\n     * argument: an array objects, one per failed task. Each error object contains:\n     *  - item -- the entry in items whose task failed\n     *  - error -- the first argument passed to the fail() handler when the task failed\n     *\n     * @param {!Array.<*>} items\n     * @param {!function(*, number):Promise} beginProcessItem\n     * @return {$.Promise}\n     */\n    function doInParallel_aggregateErrors(items, beginProcessItem) {\n        var errors = [];\n        \n        var masterDeferred = new $.Deferred();\n        \n        var parallelResult = doInParallel(\n            items,\n            function (item, i) {\n                var itemResult = beginProcessItem(item, i);\n                itemResult.fail(function (error) {\n                    errors.push({ item: item, error: error });\n                });\n                return itemResult;\n            },\n            false\n        );\n        \n        parallelResult\n            .done(function () {\n                masterDeferred.resolve();\n            })\n            .fail(function () {\n                masterDeferred.reject(errors);\n            });\n        \n        return masterDeferred.promise();\n    }\n    \n    \n    /** Value passed to fail() handlers that have been triggered due to withTimeout()'s timeout */\n    var ERROR_TIMEOUT = {};\n    \n    /**\n     * Adds timeout-driven failure to a Promise: returns a new Promise that is resolved/rejected when\n     * the given original Promise is resolved/rejected, OR is rejected after the given delay - whichever\n     * happens first.\n     * \n     * If the original Promise is resolved/rejected first, done()/fail() handlers receive arguments\n     * piped from the original Promise. If the timeout occurs first instead, fail() is called with the\n     * token Async.ERROR_TIMEOUT.\n     * \n     * @param {$.Promise} promise\n     * @param {number} timeout\n     * @return {$.Promise}\n     */\n    function withTimeout(promise, timeout) {\n        var wrapper = new $.Deferred();\n        \n        var timer = window.setTimeout(function () {\n            wrapper.reject(ERROR_TIMEOUT);\n        }, timeout);\n        promise.always(function () {\n            window.clearTimeout(timer);\n        });\n        \n        // If the wrapper was already rejected due to timeout, the Promise's calls to resolve/reject\n        // won't do anything\n        promise.pipe(wrapper.resolve, wrapper.reject);\n        \n        return wrapper.promise();\n    }\n    \n    \n\n    // Define public API\n    exports.doInParallel   = doInParallel;\n    exports.doSequentially = doSequentially;\n    exports.doSequentiallyInBackground = doSequentiallyInBackground;\n    exports.doInParallel_aggregateErrors = doInParallel_aggregateErrors;\n    exports.withTimeout    = withTimeout;\n    exports.ERROR_TIMEOUT  = ERROR_TIMEOUT;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/\n/*global $, define, brackets, FileError, InvalidateStateError */\n\ndefine('file/NativeFileSystem',['require','exports','module','utils/Async'],function (require, exports, module) {\n    \n    \n    var Async = require(\"utils/Async\");\n\n    /*\n     * Generally NativeFileSystem mimics the File API working draft\n     * http://www.w3.org/TR/file-system-api/. The w3 entry point\n     * requestFileSystem is replaced with our own requestNativeFileSystem.\n     *\n     * The current implementation is incomplete and noteably does not\n     * support the Blob data type and synchronous APIs. DirectoryEntry\n     * and FileEntry read/write capabilities are mostly implemented, but\n     * delete is not. File writing is limited to UTF-8 text.\n     */\n    var NativeFileSystem = {\n        \n        /** \n         * Amount of time we wait for async calls to return (in milliseconds)\n         * Not all async calls are wrapped with something that times out and \n         * calls the error callback. Timeouts are not specified in the W3C spec.\n         * @const\n         * @type {number}\n         */\n        ASYNC_TIMEOUT: 2000,\n        \n        /** showOpenDialog\n         *\n         * @param {bool} allowMultipleSelection\n         * @param {bool} chooseDirectories\n         * @param {string} title\n         * @param {string} initialPath\n         * @param {Array.<string>} fileTypes\n         * @param {function(...)} successCallback\n         * @param {function(...)} errorCallback\n         * @constructor\n         */\n        showOpenDialog: function (allowMultipleSelection,\n                                  chooseDirectories,\n                                  title,\n                                  initialPath,\n                                  fileTypes,\n                                  successCallback,\n                                  errorCallback) {\n            if (!successCallback) {\n                return;\n            }\n\n            var files = brackets.fs.showOpenDialog(\n                allowMultipleSelection,\n                chooseDirectories,\n                title,\n                initialPath,\n                fileTypes,\n                function (err, data) {\n                    if (!err) {\n                        successCallback(data);\n                    } else if (errorCallback) {\n                        errorCallback(NativeFileSystem._nativeToFileError(err));\n                    }\n                }\n            );\n        },\n\n        /** requestNativeFileSystem\n         *\n         * @param {string} path\n         * @param {function(...)} successCallback\n         * @param {function(...)} errorCallback\n         */\n        requestNativeFileSystem: function (path, successCallback, errorCallback) {\n            brackets.fs.stat(path, function (err, data) {\n                if (!err) {\n                    // FIXME (issue #247): return a NativeFileSystem object\n                    var root = new NativeFileSystem.DirectoryEntry(path);\n                    successCallback(root);\n                } else if (errorCallback) {\n                    errorCallback(NativeFileSystem._nativeToFileError(err));\n                }\n            });\n        },\n\n        _nativeToFileError: function (nativeErr) {\n            var error;\n\n            switch (nativeErr) {\n                // We map ERR_UNKNOWN and ERR_INVALID_PARAMS to SECURITY_ERR,\n                // since there aren't specific mappings for these.\n            case brackets.fs.ERR_UNKNOWN:\n            case brackets.fs.ERR_INVALID_PARAMS:\n                error = FileError.SECURITY_ERR;\n                break;\n            case brackets.fs.ERR_NOT_FOUND:\n                error = FileError.NOT_FOUND_ERR;\n                break;\n            case brackets.fs.ERR_CANT_READ:\n                error = FileError.NOT_READABLE_ERR;\n                break;\n            // It might seem like you should use FileError.ENCODING_ERR for this,\n            // but according to the spec that's for malformed URLs.\n            case brackets.fs.ERR_UNSUPPORTED_ENCODING:\n                error = FileError.SECURITY_ERR;\n                break;\n            case brackets.fs.ERR_CANT_WRITE:\n                error = FileError.NO_MODIFICATION_ALLOWED_ERR;\n                break;\n            case brackets.fs.ERR_OUT_OF_SPACE:\n                error = FileError.QUOTA_EXCEEDED_ERR;\n                break;\n            case brackets.fs.PATH_EXISTS_ERR:\n                error = FileError.PATH_EXISTS_ERR;\n                break;\n            default:\n                // The HTML file spec says SECURITY_ERR is a catch-all to be used in situations\n                // not covered by other error codes. \n                error = FileError.SECURITY_ERR;\n            }\n            return new NativeFileSystem.FileError(error);\n        }\n    };\n    \n    /** class: Encodings\n     *\n     * Static class that contains constants for file\n     * encoding types.\n     */\n    NativeFileSystem.Encodings = {};\n    NativeFileSystem.Encodings.UTF8 = \"UTF-8\";\n    NativeFileSystem.Encodings.UTF16 = \"UTF-16\";\n    \n    /** class: _FSEncodings\n     *\n     * Internal static class that contains constants for file\n     * encoding types to be used by internal file system\n     * implimentation.\n    */\n    NativeFileSystem._FSEncodings = {};\n    NativeFileSystem._FSEncodings.UTF8 = \"utf8\";\n    NativeFileSystem._FSEncodings.UTF16 = \"utf16\";\n    \n    /**\n     * Converts an IANA encoding name to internal encoding name.\n     * http://www.iana.org/assignments/character-sets\n     *\n     * @param {String} encoding The IANA encoding string.\n     */\n    NativeFileSystem.Encodings._IANAToFS = function (encoding) {\n        //IANA names are case-insensitive\n        encoding = encoding.toUpperCase();\n\n        switch (encoding) {\n        case (NativeFileSystem.Encodings.UTF8):\n            return NativeFileSystem._FSEncodings.UTF8;\n        case (NativeFileSystem.Encodings.UTF16):\n            return NativeFileSystem._FSEncodings.UTF16;\n        default:\n            return undefined;\n        }\n    };\n    \n    var Encodings = NativeFileSystem.Encodings;\n    var _FSEncodings = NativeFileSystem._FSEncodings;\n    \n    /** class: Entry\n     *\n     * @param {string} name\n     * @param {string} isFile\n     * @constructor\n     */\n    NativeFileSystem.Entry = function (fullPath, isDirectory) {\n        this.isDirectory = isDirectory;\n        this.isFile = !isDirectory;\n        \n        if (fullPath) {\n            // add trailing \"/\" to directory paths\n            if (isDirectory && (fullPath.charAt(fullPath.length - 1) !== \"/\")) {\n                fullPath = fullPath.concat(\"/\");\n            }\n        }\n        \n        this.fullPath = fullPath;\n\n        this.name = null; // default if extraction fails\n        if (fullPath) {\n            var pathParts = fullPath.split(\"/\");\n            \n            // Extract name from the end of the fullPath (account for trailing slash(es))\n            while (!this.name && pathParts.length) {\n                this.name = pathParts.pop();\n            }\n        }\n\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-filesystem\n        this.filesystem = null;\n    };\n    \n    NativeFileSystem.Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-moveTo\n    };\n    \n    NativeFileSystem.Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-copyTo\n    };\n    \n    NativeFileSystem.Entry.prototype.toURL = function (mimeType) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-toURL\n    };\n    \n    NativeFileSystem.Entry.prototype.remove = function (successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-remove\n    };\n    \n    NativeFileSystem.Entry.prototype.getParent = function (successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-remove\n    };\n    \n    NativeFileSystem.Entry.prototype.getMetadata = function (successCallBack, errorCallback) {\n        brackets.fs.stat(this.fullPath, function (err, stat) {\n            if (err === brackets.fs.NO_ERROR) {\n                var metadata = new NativeFileSystem.Metadata(stat.mtime);\n                successCallBack(metadata);\n            } else {\n                errorCallback(NativeFileSystem._nativeToFileError(err));\n            }\n        });\n    };\n\n\n    /**\n     * Stores information about a FileEntry\n    */\n    NativeFileSystem.Metadata = function (modificationTime) {\n        // modificationTime is read only\n        this.modificationTime = modificationTime;\n    };\n\n    /** class: FileEntry\n     * This interface represents a file on a file system.\n     *\n     * @param {string} name\n     * @constructor\n     * @extends {Entry}\n     */\n    NativeFileSystem.FileEntry = function (name) {\n        NativeFileSystem.Entry.call(this, name, false);\n    };\n    NativeFileSystem.FileEntry.prototype = new NativeFileSystem.Entry();\n\n    NativeFileSystem.FileEntry.prototype.toString = function () {\n        return \"[FileEntry \" + this.fullPath + \"]\";\n    };\n    \n    /**\n     * Creates a new FileWriter associated with the file that this FileEntry represents.\n     *\n     * @param {function (FileWriter)} successCallback\n     * @param {function (FileError)} errorCallback\n     */\n    NativeFileSystem.FileEntry.prototype.createWriter = function (successCallback, errorCallback) {\n        var fileEntry = this;\n\n        // [NoInterfaceObject]\n        // interface FileWriter : FileSaver\n        var FileWriter = function (data) {\n            NativeFileSystem.FileSaver.call(this, data);\n\n            // FileWriter private memeber vars\n            this._length = 0;\n            this._position = 0;\n        };\n\n        FileWriter.prototype.length = function () {\n            return this._length;\n        };\n\n        FileWriter.prototype.position = function () {\n            return this._position;\n        };\n\n        // TODO (issue #241): handle Blob data instead of string\n        FileWriter.prototype.write = function (data) {\n            if (data === null || data === undefined) {\n                throw new Error();\n            }\n\n            if (this.readyState === NativeFileSystem.FileSaver.WRITING) {\n                throw new NativeFileSystem.FileException(NativeFileSystem.FileException.INVALID_STATE_ERR);\n            }\n\n            this._readyState = NativeFileSystem.FileSaver.WRITING;\n\n            if (this.onwritestart) {\n                // TODO (issue #241): progressevent\n                this.onwritestart();\n            }\n\n            var self = this;\n\n            brackets.fs.writeFile(fileEntry.fullPath, data, _FSEncodings.UTF8, function (err) {\n\n                if ((err !== brackets.fs.NO_ERROR) && self.onerror) {\n                    var fileError = NativeFileSystem._nativeToFileError(err);\n\n                    // TODO (issue #241): set readonly FileSaver.error attribute\n                    // self._error = fileError;\n                    self.onerror(fileError);\n\n                    // TODO (issue #241): partial write, update length and position\n                }\n                // else {\n                    // TODO (issue #241): After changing data argument to Blob, use\n                    // Blob.size to update position and length upon successful\n                    // completion of a write.\n\n                    // self.position = ;\n                    // self.length = ;\n                // }\n\n                // DONE is set regardless of error\n                self._readyState = NativeFileSystem.FileSaver.DONE;\n                \n                if (self.onwrite) {\n                    // TODO (issue #241): progressevent\n                    self.onwrite();\n                }\n\n                if (self.onwriteend) {\n                    // TODO (issue #241): progressevent\n                    self.onwriteend();\n                }\n            });\n        };\n\n        FileWriter.prototype.seek = function (offset) {\n        };\n\n        FileWriter.prototype.truncate = function (size) {\n        };\n\n        var fileWriter = new FileWriter();\n\n        // initialize file length\n        var result = new $.Deferred();\n        brackets.fs.readFile(fileEntry.fullPath, _FSEncodings.UTF8, function (err, contents) {\n            // Ignore \"file not found\" errors. It's okay if the file doesn't exist yet.\n            if (err !== brackets.fs.ERR_NOT_FOUND) {\n                fileWriter._err = err;\n            }\n            \n            if (contents) {\n                fileWriter._length = contents.length;\n            }\n            \n            result.resolve();\n        });\n\n        result.done(function () {\n            if (fileWriter._err && (errorCallback !== undefined)) {\n                errorCallback(NativeFileSystem._nativeToFileError(fileWriter._err));\n            } else if (successCallback !== undefined) {\n                successCallback(fileWriter);\n            }\n        });\n    };\n\n    /**\n     * Obtains the File objecte for a FileEntry object\n     *\n     * @param {function(...)} successCallback\n     * @param {function(...)} errorCallback\n     */\n    NativeFileSystem.FileEntry.prototype.file = function (successCallback, errorCallback) {\n        var newFile = new NativeFileSystem.File(this);\n        successCallback(newFile);\n\n        // TODO (issue #241): errorCallback\n    };\n\n    /**\n     * This interface extends the FileException interface described in to add\n     * several new error codes. Any errors that need to be reported synchronously,\n     * including all that occur during use of the synchronous filesystem methods,\n     * are reported using the FileException exception.\n     *\n     * @param {number} code The code attribute, on getting, must return one of the\n     * constants of the FileException exception, which must be the most appropriate\n     * code from the table below.\n     */\n    NativeFileSystem.FileException = function (code) {\n        this.code = code || 0;\n    };\n\n    // FileException constants\n    Object.defineProperties(\n        NativeFileSystem.FileException,\n        {\n            NOT_FOUND_ERR:                { value: 1, writable: false },\n            SECURITY_ERR:                 { value: 2, writable: false },\n            ABORT_ERR:                    { value: 3, writable: false },\n            NOT_READABLE_ERR:             { value: 4, writable: false },\n            ENCODING_ERR:                 { value: 5, writable: false },\n            NO_MODIFICATION_ALLOWED_ERR:  { value: 6, writable: false },\n            INVALID_STATE_ERR:            { value: 7, writable: false },\n            SYNTAX_ERR:                   { value: 8, writable: false },\n            QUOTA_EXCEEDED_ERR:           { value: 10, writable: false }\n        }\n    );\n\n    /**\n     * This interface provides methods to monitor the asynchronous writing of blobs\n     * to disk using progress events and event handler attributes.\n     *\n     * This interface is specified to be used within the context of the global\n     * object (Window) and within Web Workers.\n     *\n     * @param {Blob} data\n     * @constructor\n     */\n    NativeFileSystem.FileSaver = function (data) {\n        // FileSaver private member vars\n        this._data = data;\n        this._readyState = NativeFileSystem.FileSaver.INIT;\n        this._error = null;\n    };\n\n    // FileSaver constants\n    Object.defineProperties(\n        NativeFileSystem.FileSaver,\n        {\n            INIT:     { value: 1, writable: false },\n            WRITING:  { value: 2, writable: false },\n            DONE:     { value: 3, writable: false }\n        }\n    );\n\n    // FileSaver methods\n\n    /**\n     *\n     */\n    NativeFileSystem.FileSaver.prototype.readyState = function () {\n        return this._readyState;\n    };\n\n    // TODO (issue #241): http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void\n    NativeFileSystem.FileSaver.prototype.abort = function () {\n        // If readyState is DONE or INIT, terminate this overall series of steps without doing anything else..\n        if (this._readyState === NativeFileSystem.FileSaver.INIT || this._readyState === NativeFileSystem.FileSaver.DONE) {\n            return;\n        }\n\n        // TODO (issue #241): Terminate any steps having to do with writing a file.\n\n        // Set the error attribute to a FileError object with the code ABORT_ERR.\n        this._error = new NativeFileSystem.FileError(FileError.ABORT_ERR);\n\n        // Set readyState to DONE.\n        this._readyState = NativeFileSystem.FileSaver.DONE;\n\n        /*\n        TODO (issue #241): \n        Dispatch a progress event called abort\n        Dispatch a progress event called writeend\n        Stop dispatching any further progress events.\n        Terminate this overall set of steps.\n        */\n    };\n\n    /**\n     * This interface represents a directory on a file system.\n     *\n     * @constructor\n     * @param {string} name\n     * @extends {Entry}\n     */\n    NativeFileSystem.DirectoryEntry = function (name) {\n        NativeFileSystem.Entry.call(this, name, true);\n\n        // TODO (issue #241): void removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback);\n    };\n    NativeFileSystem.DirectoryEntry.prototype = new NativeFileSystem.Entry();\n    \n    NativeFileSystem.DirectoryEntry.prototype.toString = function () {\n        return \"[DirectoryEntry \" + this.fullPath + \"]\";\n    };\n    \n    NativeFileSystem.DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-DirectoryEntry-getDirectory\n    };\n    \n    NativeFileSystem.DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {\n        // TODO (issue #241)\n        // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-DirectoryEntry-removeRecursively\n    };\n\n    NativeFileSystem.DirectoryEntry.prototype.createReader = function () {\n        var dirReader = new NativeFileSystem.DirectoryReader();\n        dirReader._directory = this;\n\n        return dirReader;\n    };\n\n    /**\n     * Creates or looks up a file.\n     *\n     * @param {string} path Either an absolute path or a relative path from this\n     *        DirectoryEntry to the file to be looked up or created. It is an error\n     *        to attempt to create a file whose immediate parent does not yet\n     *        exist.\n     * @param {Object.<string, boolean>} options\n     * @param {function (number)} successCallback\n     * @param {function (number)} errorCallback\n     */\n    NativeFileSystem.DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {\n        var fileFullPath = path;\n        \n        function isRelativePath(path) {\n            // If the path contains a colons it must be a full path on Windows (colons are\n            // not valid path characters on mac or in URIs)\n            if (path.indexOf(\":\") !== -1) {\n                return false;\n            }\n            \n            // For everyone else, absolute paths start with a \"/\"\n            return path[0] !== \"/\";\n        }\n\n        // resolve relative paths relative to the DirectoryEntry\n        if (isRelativePath(path)) {\n            fileFullPath = this.fullPath + path;\n        }\n\n        var createFileEntry = function () {\n            if (successCallback) {\n                successCallback(new NativeFileSystem.FileEntry(fileFullPath));\n            }\n        };\n\n        var createFileError = function (err) {\n            if (errorCallback) {\n                errorCallback(NativeFileSystem._nativeToFileError(err));\n            }\n        };\n\n        // Use stat() to check if file exists\n        brackets.fs.stat(fileFullPath, function (err, stats) {\n            if ((err === brackets.fs.NO_ERROR)) {\n                // NO_ERROR implies the path already exists\n\n                // throw error if the file the path is a directory\n                if (stats.isDirectory()) {\n                    if (errorCallback) {\n                        errorCallback(new NativeFileSystem.FileError(FileError.TYPE_MISMATCH_ERR));\n                    }\n\n                    return;\n                }\n\n                // throw error if the file exists but create is exclusive\n                if (options.create && options.exclusive) {\n                    if (errorCallback) {\n                        errorCallback(new NativeFileSystem.FileError(FileError.PATH_EXISTS_ERR));\n                    }\n\n                    return;\n                }\n\n                // Create a file entry for the existing file. If create == true,\n                // a file entry is created without error.\n                createFileEntry();\n            } else if (err === brackets.fs.ERR_NOT_FOUND) {\n                // ERR_NOT_FOUND implies we write a new, empty file\n\n                // create the file\n                if (options.create) {\n                    brackets.fs.writeFile(fileFullPath, \"\", _FSEncodings.UTF8, function (err) {\n                        if (err) {\n                            createFileError(err);\n                        } else {\n                            createFileEntry();\n                        }\n                    });\n\n                    return;\n                }\n\n                // throw error if file not found and the create == false\n                if (errorCallback) {\n                    errorCallback(new NativeFileSystem.FileError(FileError.NOT_FOUND_ERR));\n                }\n            } else {\n                // all other brackets.fs.stat() errors\n                createFileError(err);\n            }\n        });\n    };\n\n    /** class: DirectoryReader\n     */\n    NativeFileSystem.DirectoryReader = function () {\n\n    };\n\n    /** readEntries\n     *\n     * @param {function(...)} successCallback\n     * @param {function(...)} errorCallback\n     * @returns {Array.<Entry>}\n     */\n    NativeFileSystem.DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {\n        var rootPath = this._directory.fullPath;\n        brackets.fs.readdir(rootPath, function (err, filelist) {\n            if (!err) {\n                var entries = [];\n                var lastError = null;\n\n                // stat() to determine type of each entry, then populare entries array with objects\n                var masterPromise = Async.doInParallel(filelist, function (filename, index) {\n                    \n                    var deferred = new $.Deferred();\n                    var itemFullPath = rootPath + filelist[index];\n                    \n                    brackets.fs.stat(itemFullPath, function (statErr, statData) {\n                        if (!statErr) {\n                            if (statData.isDirectory()) {\n                                entries[index] = new NativeFileSystem.DirectoryEntry(itemFullPath);\n                            } else if (statData.isFile()) {\n                                entries[index] = new NativeFileSystem.FileEntry(itemFullPath);\n                            } else {\n                                entries[index] = null;  // neither a file nor a dir, so don't include it\n                            }\n                            deferred.resolve();\n                        } else {\n                            lastError = NativeFileSystem._nativeToFileError(statErr);\n                            deferred.reject(lastError);\n                        }\n                    });\n                    \n                    return deferred.promise();\n                }, true);\n\n                // We want the error callback to get called after some timeout (in case some deferreds don't return).\n                // So, we need to wrap masterPromise in another deferred that has this timeout functionality    \n                var timeoutWrapper = Async.withTimeout(masterPromise, NativeFileSystem.ASYNC_TIMEOUT);\n\n                // Add the callbacks to this top-level Promise, which wraps all the individual deferred objects\n                timeoutWrapper.then(\n                    function () { // success\n                        // The entries array may have null values if stat returned things that were\n                        // neither a file nor a dir. So, we need to clean those out.\n                        var cleanedEntries = [], i;\n                        for (i = 0; i < entries.length; i++) {\n                            if (entries[i]) {\n                                cleanedEntries.push(entries[i]);\n                            }\n                        }\n                        successCallback(cleanedEntries);\n                    },\n                    function (err) { // error\n                        if (err === Async.ERROR_TIMEOUT) {\n                            // SECURITY_ERR is the HTML5 File catch-all error, and there isn't anything\n                            // more fitting for a timeout.\n                            err = new NativeFileSystem.FileError(FileError.SECURITY_ERR);\n                        } else {\n                            err = lastError;\n                        }\n                        \n                        if (errorCallback) {\n                            errorCallback(err);\n                        }\n                    }\n                );\n\n            } else { // There was an error reading the initial directory.\n                errorCallback(NativeFileSystem._nativeToFileError(err));\n            }\n        });\n    };\n\n    /** class: FileReader\n     *\n     * @extends {EventTarget}\n     */\n    NativeFileSystem.FileReader = function () {\n        // TODO (issue #241): this classes should extend EventTarget\n\n        // states\n        this.EMPTY = 0;\n        this.LOADING = 1;\n        this.DONE = 2;\n\n        // readyState is read only\n        this.readyState = this.EMPTY;\n\n        // File or Blob data\n        // TODO (issue #241): readonly attribute any result;\n        // TODO (issue #241): readonly attribute DOMError error;\n\n        // event handler attributes\n        this.onloadstart = null;\n        this.onprogress = null;\n        this.onload = null;\n        this.onabort = null;\n        this.onerror = null;\n        this.onloadend = null;\n    };\n    // TODO (issue #241): extend EventTarget (draft status, not implememnted in webkit)\n    // NativeFileSystem.FileReader.prototype = new NativeFileSystem.EventTarget()\n    \n    NativeFileSystem.FileReader.prototype.readAsArrayBuffer = function (blob) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsArrayBuffer\n    };\n    \n    NativeFileSystem.FileReader.prototype.readAsBinaryString = function (blob) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsBinaryStringAsync\n    };\n    \n    NativeFileSystem.FileReader.prototype.readAsDataURL = function (blob) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsDataURL\n    };\n    \n    NativeFileSystem.FileReader.prototype.abort = function () {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-abort\n    };\n    \n    /** readAsText\n     *\n     * @param {Blob} blob\n     * @param {string} encoding (IANA Encoding Name)\n     */\n    NativeFileSystem.FileReader.prototype.readAsText = function (blob, encoding) {\n        var self = this;\n\n        if (!encoding) {\n            encoding = Encodings.UTF8;\n        }\n        \n        var internalEncoding  = Encodings._IANAToFS(encoding);\n\n        if (this.readyState === this.LOADING) {\n            throw new InvalidateStateError();\n        }\n\n        this.readyState = this.LOADING;\n\n        if (this.onloadstart) {\n            this.onloadstart(); // TODO (issue #241): progressevent\n        }\n\n        brackets.fs.readFile(blob._fullPath, internalEncoding, function (err, data) {\n\n            // TODO (issue #241): the event objects passed to these event handlers is fake and incomplete right now\n            var fakeEvent = {\n                loaded: 0,\n                total: 0\n            };\n\n            // The target for this event is the FileReader and the data/err result is stored in the FileReader\n            fakeEvent.target = self;\n            self.result = data;\n            self.error = NativeFileSystem._nativeToFileError(err);\n\n            if (err) {\n                self.readyState = self.DONE;\n                if (self.onerror) {\n                    self.onerror(fakeEvent);\n                }\n            } else {\n                self.readyState = self.DONE;\n\n                // TODO (issue #241): this should be the file/blob size, but we don't have code to get that yet, so for know assume a file size of 1\n                // and since we read the file in one go, assume 100% after the first read\n                fakeEvent.loaded = 1;\n                fakeEvent.total = 1;\n\n                if (self.onprogress) {\n                    self.onprogress(fakeEvent);\n                }\n\n                // TODO (issue #241): onabort not currently supported since our native implementation doesn't support it\n                // if (self.onabort)\n                //    self.onabort(fakeEvent);\n\n                if (self.onload) {\n                    self.onload(fakeEvent);\n                }\n\n                if (self.onloadend) {\n                    self.onloadend();\n                }\n            }\n\n        });\n    };\n\n    /** class: Blob\n     *\n     * @constructor\n     * param {Entry} entry\n     */\n    NativeFileSystem.Blob = function (fullPath) {\n        this._fullPath = fullPath;\n        \n        // TODO (issue #241): implement, readonly\n        this.size = 0;\n        \n        // TODO (issue #241): implement, readonly\n        this.type = null;\n    };\n    \n    NativeFileSystem.Blob.prototype.slice = function (start, end, contentType) {\n        // TODO (issue #241): implement\n        // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-slice\n    };\n    \n    /** class: File\n     *\n     * @constructor\n     * param {Entry} entry\n     * @extends {Blob}\n     */\n    NativeFileSystem.File = function (entry) {\n        NativeFileSystem.Blob.call(this, entry.fullPath);\n        \n        // TODO (issue #241): implement, readonly\n        this.name = \"\";\n        \n        // TODO (issue #241): implement, readonly\n        this.lastModifiedDate = null;\n    };\n\n    /** class: FileError\n     *\n     * Implementation of HTML file API error code return class. Note that we don't\n     * actually define the error codes here--we rely on the browser's built-in FileError\n     * class's constants. In other words, external clients of this API should always\n     * use FileError.<constant-name>, not NativeFileSystem.FileError.<constant-name>.\n     *\n     * @constructor\n     * @param {number} code The error code to return with this FileError. Must be\n     * one of the codes defined in the FileError class.\n     */\n    NativeFileSystem.FileError = function (code) {\n        this.code = code || 0;\n    };\n\n    // Define public API\n    exports.NativeFileSystem    = NativeFileSystem;\n});\n\n/*\n * jsTree 1.0-rc3\n * http://jstree.com/\n *\n * Copyright (c) 2010 Ivan Bozhanov (vakata.com)\n *\n * Licensed same as jquery - under the terms of either the MIT License or the GPL Version 2 License\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n *\n * $Date: 2011-02-09 01:17:14 +0200 (ср, 09 февр 2011) $\n * $Revision: 236 $\n */\n\n/*jslint browser: true, onevar: true, undef: true, bitwise: true, strict: true */\n/*global window : false, clearInterval: false, clearTimeout: false, document: false, setInterval: false, setTimeout: false, jQuery: false, navigator: false, XSLTProcessor: false, DOMParser: false, XMLSerializer: false*/\n\n\n\n// top wrapper to prevent multiple inclusion (is this OK?)\n(function () { if(jQuery && jQuery.jstree) { return; }\n    var is_ie6 = false, is_ie7 = false, is_ff2 = false;\n\n/* \n * jsTree core\n */\n(function ($) {\n    // Common functions not related to jsTree \n    // decided to move them to a `vakata` \"namespace\"\n    $.vakata = {};\n    // CSS related functions\n    $.vakata.css = {\n        get_css : function(rule_name, delete_flag, sheet) {\n            rule_name = rule_name.toLowerCase();\n            var css_rules = sheet.cssRules || sheet.rules,\n                j = 0;\n            do {\n                if(css_rules.length && j > css_rules.length + 5) { return false; }\n                if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) {\n                    if(delete_flag === true) {\n                        if(sheet.removeRule) { sheet.removeRule(j); }\n                        if(sheet.deleteRule) { sheet.deleteRule(j); }\n                        return true;\n                    }\n                    else { return css_rules[j]; }\n                }\n            }\n            while (css_rules[++j]);\n            return false;\n        },\n        add_css : function(rule_name, sheet) {\n            if($.jstree.css.get_css(rule_name, false, sheet)) { return false; }\n            if(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); }\n            return $.vakata.css.get_css(rule_name);\n        },\n        remove_css : function(rule_name, sheet) { \n            return $.vakata.css.get_css(rule_name, true, sheet); \n        },\n        add_sheet : function(opts) {\n            var tmp = false, is_new = true;\n            if(opts.str) {\n                if(opts.title) { tmp = $(\"style[id='\" + opts.title + \"-stylesheet']\")[0]; }\n                if(tmp) { is_new = false; }\n                else {\n                    tmp = document.createElement(\"style\");\n                    tmp.setAttribute('type',\"text/css\");\n                    if(opts.title) { tmp.setAttribute(\"id\", opts.title + \"-stylesheet\"); }\n                }\n                if(tmp.styleSheet) {\n                    if(is_new) { \n                        document.getElementsByTagName(\"head\")[0].appendChild(tmp); \n                        tmp.styleSheet.cssText = opts.str; \n                    }\n                    else {\n                        tmp.styleSheet.cssText = tmp.styleSheet.cssText + \" \" + opts.str; \n                    }\n                }\n                else {\n                    tmp.appendChild(document.createTextNode(opts.str));\n                    document.getElementsByTagName(\"head\")[0].appendChild(tmp);\n                }\n                return tmp.sheet || tmp.styleSheet;\n            }\n            if(opts.url) {\n                if(document.createStyleSheet) {\n                    try { tmp = document.createStyleSheet(opts.url); } catch (e) { }\n                }\n                else {\n                    tmp         = document.createElement('link');\n                    tmp.rel     = 'stylesheet';\n                    tmp.type    = 'text/css';\n                    tmp.media   = \"all\";\n                    tmp.href    = opts.url;\n                    document.getElementsByTagName(\"head\")[0].appendChild(tmp);\n                    return tmp.styleSheet;\n                }\n            }\n        }\n    };\n\n    // private variables \n    var instances = [],         // instance array (used by $.jstree.reference/create/focused)\n        focused_instance = -1,  // the index in the instance array of the currently focused instance\n        plugins = {},           // list of included plugins\n        prepared_move = {};     // for the move_node function\n\n    // jQuery plugin wrapper (thanks to jquery UI widget function)\n    $.fn.jstree = function (settings) {\n        var isMethodCall = (typeof settings == 'string'), // is this a method call like $().jstree(\"open_node\")\n            args = Array.prototype.slice.call(arguments, 1), \n            returnValue = this;\n\n        // if a method call execute the method on all selected instances\n        if(isMethodCall) {\n            if(settings.substring(0, 1) == '_') { return returnValue; }\n            this.each(function() {\n                var instance = instances[$.data(this, \"jstree_instance_id\")],\n                    methodValue = (instance && $.isFunction(instance[settings])) ? instance[settings].apply(instance, args) : instance;\n                    if(typeof methodValue !== \"undefined\" && (settings.indexOf(\"is_\") === 0 || (methodValue !== true && methodValue !== false))) { returnValue = methodValue; return false; }\n            });\n        }\n        else {\n            this.each(function() {\n                // extend settings and allow for multiple hashes and $.data\n                var instance_id = $.data(this, \"jstree_instance_id\"),\n                    a = [],\n                    b = settings ? $.extend({}, true, settings) : {},\n                    c = $(this), \n                    s = false, \n                    t = [];\n                a = a.concat(args);\n                if(c.data(\"jstree\")) { a.push(c.data(\"jstree\")); }\n                b = a.length ? $.extend.apply(null, [true, b].concat(a)) : b;\n\n                // if an instance already exists, destroy it first\n                if(typeof instance_id !== \"undefined\" && instances[instance_id]) { instances[instance_id].destroy(); }\n                // push a new empty object to the instances array\n                instance_id = parseInt(instances.push({}),10) - 1;\n                // store the jstree instance id to the container element\n                $.data(this, \"jstree_instance_id\", instance_id);\n                // clean up all plugins\n                b.plugins = $.isArray(b.plugins) ? b.plugins : $.jstree.defaults.plugins.slice();\n                b.plugins.unshift(\"core\");\n                // only unique plugins\n                b.plugins = b.plugins.sort().join(\",,\").replace(/(,|^)([^,]+)(,,\\2)+(,|$)/g,\"$1$2$4\").replace(/,,+/g,\",\").replace(/,$/,\"\").split(\",\");\n\n                // extend defaults with passed data\n                s = $.extend(true, {}, $.jstree.defaults, b);\n                s.plugins = b.plugins;\n                $.each(plugins, function (i, val) { \n                    if($.inArray(i, s.plugins) === -1) { s[i] = null; delete s[i]; } \n                    else { t.push(i); }\n                });\n                s.plugins = t;\n\n                // push the new object to the instances array (at the same time set the default classes to the container) and init\n                instances[instance_id] = new $.jstree._instance(instance_id, $(this).addClass(\"jstree jstree-\" + instance_id), s); \n                // init all activated plugins for this instance\n                $.each(instances[instance_id]._get_settings().plugins, function (i, val) { instances[instance_id].data[val] = {}; });\n                $.each(instances[instance_id]._get_settings().plugins, function (i, val) { if(plugins[val]) { plugins[val].__init.apply(instances[instance_id]); } });\n                // initialize the instance\n                setTimeout(function() { if(instances[instance_id]) { instances[instance_id].init(); } }, 0);\n            });\n        }\n        // return the jquery selection (or if it was a method call that returned a value - the returned value)\n        return returnValue;\n    };\n    // object to store exposed functions and objects\n    $.jstree = {\n        defaults : {\n            plugins : []\n        },\n        _focused : function () { return instances[focused_instance] || null; },\n        _reference : function (needle) { \n            // get by instance id\n            if(instances[needle]) { return instances[needle]; }\n            // get by DOM (if still no luck - return null\n            var o = $(needle); \n            if(!o.length && typeof needle === \"string\") { o = $(\"#\" + needle); }\n            if(!o.length) { return null; }\n            return instances[o.closest(\".jstree\").data(\"jstree_instance_id\")] || null; \n        },\n        _instance : function (index, container, settings) { \n            // for plugins to store data in\n            this.data = { core : {} };\n            this.get_settings   = function () { return $.extend(true, {}, settings); };\n            this._get_settings  = function () { return settings; };\n            this.get_index      = function () { return index; };\n            this.get_container  = function () { return container; };\n            this.get_container_ul = function () { return container.children(\"ul:eq(0)\"); };\n            this._set_settings  = function (s) { \n                settings = $.extend(true, {}, settings, s);\n            };\n        },\n        _fn : { },\n        plugin : function (pname, pdata) {\n            pdata = $.extend({}, {\n                __init      : $.noop, \n                __destroy   : $.noop,\n                _fn         : {},\n                defaults    : false\n            }, pdata);\n            plugins[pname] = pdata;\n\n            $.jstree.defaults[pname] = pdata.defaults;\n            $.each(pdata._fn, function (i, val) {\n                val.plugin      = pname;\n                val.old         = $.jstree._fn[i];\n                $.jstree._fn[i] = function () {\n                    var rslt,\n                        func = val,\n                        args = Array.prototype.slice.call(arguments),\n                        evnt = new $.Event(\"before.jstree\"),\n                        rlbk = false;\n\n                    if(this.data.core.locked === true && i !== \"unlock\" && i !== \"is_locked\") { return; }\n\n                    // Check if function belongs to the included plugins of this instance\n                    do {\n                        if(func && func.plugin && $.inArray(func.plugin, this._get_settings().plugins) !== -1) { break; }\n                        func = func.old;\n                    } while(func);\n                    if(!func) { return; }\n\n                    // context and function to trigger events, then finally call the function\n                    if(i.indexOf(\"_\") === 0) {\n                        rslt = func.apply(this, args);\n                    }\n                    else {\n                        rslt = this.get_container().triggerHandler(evnt, { \"func\" : i, \"inst\" : this, \"args\" : args, \"plugin\" : func.plugin });\n                        if(rslt === false) { return; }\n                        if(typeof rslt !== \"undefined\") { args = rslt; }\n\n                        rslt = func.apply(\n                            $.extend({}, this, { \n                                __callback : function (data) { \n                                    this.get_container().triggerHandler( i + '.jstree', { \"inst\" : this, \"args\" : args, \"rslt\" : data, \"rlbk\" : rlbk });\n                                },\n                                __rollback : function () { \n                                    rlbk = this.get_rollback();\n                                    return rlbk;\n                                },\n                                __call_old : function (replace_arguments) {\n                                    return func.old.apply(this, (replace_arguments ? Array.prototype.slice.call(arguments, 1) : args ) );\n                                }\n                            }), args);\n                    }\n\n                    // return the result\n                    return rslt;\n                };\n                $.jstree._fn[i].old = val.old;\n                $.jstree._fn[i].plugin = pname;\n            });\n        },\n        rollback : function (rb) {\n            if(rb) {\n                if(!$.isArray(rb)) { rb = [ rb ]; }\n                $.each(rb, function (i, val) {\n                    instances[val.i].set_rollback(val.h, val.d);\n                });\n            }\n        }\n    };\n    // set the prototype for all instances\n    $.jstree._fn = $.jstree._instance.prototype = {};\n\n    // load the css when DOM is ready\n    $(function() {\n        // code is copied from jQuery ($.browser is deprecated + there is a bug in IE)\n        var u = navigator.userAgent.toLowerCase(),\n            v = (u.match( /.+?(?:rv|it|ra|ie)[\\/: ]([\\d.]+)/ ) || [0,'0'])[1],\n            css_string = '' + \n                '.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; } ' + \n                '.jstree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; } ' + \n                '.jstree-rtl li { margin-left:0; margin-right:18px; } ' + \n                '.jstree > ul > li { margin-left:0px; } ' + \n                '.jstree-rtl > ul > li { margin-right:0px; } ' + \n                '.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; } ' + \n                '.jstree a { display:inline-block; line-height:16px; height:16px; color:black; white-space:nowrap; text-decoration:none; padding:1px 2px; margin:0; } ' + \n                '.jstree a:focus { outline: none; } ' + \n                '.jstree a > ins { height:16px; width:16px; } ' + \n                '.jstree a > .jstree-icon { margin-right:3px; } ' + \n                '.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; } ' + \n                'li.jstree-open > ul { display:block; } ' + \n                'li.jstree-closed > ul { display:none; } ';\n        // Correct IE 6 (does not support the > CSS selector)\n        if(/msie/.test(u) && parseInt(v, 10) == 6) { \n            is_ie6 = true;\n\n            // fix image flicker and lack of caching\n            try {\n                document.execCommand(\"BackgroundImageCache\", false, true);\n            } catch (err) { }\n\n            css_string += '' + \n                '.jstree li { height:18px; margin-left:0; margin-right:0; } ' + \n                '.jstree li li { margin-left:18px; } ' + \n                '.jstree-rtl li li { margin-left:0px; margin-right:18px; } ' + \n                'li.jstree-open ul { display:block; } ' + \n                'li.jstree-closed ul { display:none !important; } ' + \n                '.jstree li a { display:inline; border-width:0 !important; padding:0px 2px !important; } ' + \n                '.jstree li a ins { height:16px; width:16px; margin-right:3px; } ' + \n                '.jstree-rtl li a ins { margin-right:0px; margin-left:3px; } ';\n        }\n        // Correct IE 7 (shifts anchor nodes onhover)\n        if(/msie/.test(u) && parseInt(v, 10) == 7) { \n            is_ie7 = true;\n            css_string += '.jstree li a { border-width:0 !important; padding:0px 2px !important; } ';\n        }\n        // correct ff2 lack of display:inline-block\n        if(!/compatible/.test(u) && /mozilla/.test(u) && parseFloat(v, 10) < 1.9) {\n            is_ff2 = true;\n            css_string += '' + \n                '.jstree ins { display:-moz-inline-box; } ' + \n                '.jstree li { line-height:12px; } ' + // WHY??\n                '.jstree a { display:-moz-inline-box; } ' + \n                '.jstree .jstree-no-icons .jstree-checkbox { display:-moz-inline-stack !important; } ';\n                /* this shouldn't be here as it is theme specific */\n        }\n        // the default stylesheet\n        $.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n    });\n\n    // core functions (open, close, create, update, delete)\n    $.jstree.plugin(\"core\", {\n        __init : function () {\n            this.data.core.locked = false;\n            this.data.core.to_open = this.get_settings().core.initially_open;\n            this.data.core.to_load = this.get_settings().core.initially_load;\n        },\n        defaults : { \n            html_titles : false,\n            animation   : 500,\n            initially_open : [],\n            initially_load : [],\n            open_parents : true,\n            notify_plugins : true,\n            rtl         : false,\n            load_open   : false,\n            strings     : {\n                loading     : \"Loading ...\",\n                new_node    : \"New node\",\n                multiple_selection : \"Multiple selection\"\n            }\n        },\n        _fn : { \n            init    : function () { \n                this.set_focus(); \n                if(this._get_settings().core.rtl) {\n                    this.get_container().addClass(\"jstree-rtl\").css(\"direction\", \"rtl\");\n                }\n                this.get_container().html(\"<ul><li class='jstree-last jstree-leaf'><ins>&#160;</ins><a class='jstree-loading' href='#'><ins class='jstree-icon'>&#160;</ins>\" + this._get_string(\"loading\") + \"</a></li></ul>\");\n                this.data.core.li_height = this.get_container_ul().find(\"li.jstree-closed, li.jstree-leaf\").eq(0).height() || 18;\n\n                this.get_container()\n                    .delegate(\"li > ins\", \"click.jstree\", $.proxy(function (event) {\n                            var trgt = $(event.target);\n                            // if(trgt.is(\"ins\") && event.pageY - trgt.offset().top < this.data.core.li_height) { this.toggle_node(trgt); }\n                            this.toggle_node(trgt);\n                        }, this))\n                    .bind(\"mousedown.jstree\", $.proxy(function () { \n                            this.set_focus(); // This used to be setTimeout(set_focus,0) - why?\n                        }, this))\n                    .bind(\"dblclick.jstree\", function (event) { \n                        var sel;\n                        if(document.selection && document.selection.empty) { document.selection.empty(); }\n                        else {\n                            if(window.getSelection) {\n                                sel = window.getSelection();\n                                try { \n                                    sel.removeAllRanges();\n                                    sel.collapse();\n                                } catch (err) { }\n                            }\n                        }\n                    });\n                if(this._get_settings().core.notify_plugins) {\n                    this.get_container()\n                        .bind(\"load_node.jstree\", $.proxy(function (e, data) { \n                                var o = this._get_node(data.rslt.obj),\n                                    t = this;\n                                if(o === -1) { o = this.get_container_ul(); }\n                                if(!o.length) { return; }\n                                o.find(\"li\").each(function () {\n                                    var th = $(this);\n                                    if(th.data(\"jstree\")) {\n                                        $.each(th.data(\"jstree\"), function (plugin, values) {\n                                            if(t.data[plugin] && $.isFunction(t[\"_\" + plugin + \"_notify\"])) {\n                                                t[\"_\" + plugin + \"_notify\"].call(t, th, values);\n                                            }\n                                        });\n                                    }\n                                });\n                            }, this));\n                }\n                if(this._get_settings().core.load_open) {\n                    this.get_container()\n                        .bind(\"load_node.jstree\", $.proxy(function (e, data) { \n                                var o = this._get_node(data.rslt.obj),\n                                    t = this;\n                                if(o === -1) { o = this.get_container_ul(); }\n                                if(!o.length) { return; }\n                                o.find(\"li.jstree-open:not(:has(ul))\").each(function () {\n                                    t.load_node(this, $.noop, $.noop);\n                                });\n                            }, this));\n                }\n                this.__callback();\n                this.load_node(-1, function () { this.loaded(); this.reload_nodes(); });\n            },\n            destroy : function () { \n                var i,\n                    n = this.get_index(),\n                    s = this._get_settings(),\n                    _this = this;\n\n                $.each(s.plugins, function (i, val) {\n                    try { plugins[val].__destroy.apply(_this); } catch(err) { }\n                });\n                this.__callback();\n                // set focus to another instance if this one is focused\n                if(this.is_focused()) { \n                    for(i in instances) { \n                        if(instances.hasOwnProperty(i) && i != n) { \n                            instances[i].set_focus(); \n                            break; \n                        } \n                    }\n                }\n                // if no other instance found\n                if(n === focused_instance) { focused_instance = -1; }\n                // remove all traces of jstree in the DOM (only the ones set using jstree*) and cleans all events\n                this.get_container()\n                    .unbind(\".jstree\")\n                    .undelegate(\".jstree\")\n                    .removeData(\"jstree_instance_id\")\n                    .find(\"[class^='jstree']\")\n                        .andSelf()\n                        .attr(\"class\", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });\n                $(document)\n                    .unbind(\".jstree-\" + n)\n                    .undelegate(\".jstree-\" + n);\n                // remove the actual data\n                instances[n] = null;\n                delete instances[n];\n            },\n\n            _core_notify : function (n, data) {\n                if(data.opened) {\n                    this.open_node(n, false, true);\n                }\n            },\n\n            lock : function () {\n                this.data.core.locked = true;\n                this.get_container().children(\"ul\").addClass(\"jstree-locked\").css(\"opacity\",\"0.7\");\n                this.__callback({});\n            },\n            unlock : function () {\n                this.data.core.locked = false;\n                this.get_container().children(\"ul\").removeClass(\"jstree-locked\").css(\"opacity\",\"1\");\n                this.__callback({});\n            },\n            is_locked : function () { return this.data.core.locked; },\n            save_opened : function () {\n                var _this = this;\n                this.data.core.to_open = [];\n                this.get_container_ul().find(\"li.jstree-open\").each(function () { \n                    if(this.id) { _this.data.core.to_open.push(\"#\" + this.id.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\")); }\n                });\n                this.__callback(_this.data.core.to_open);\n            },\n            save_loaded : function () { },\n            reload_nodes : function (is_callback) {\n                var _this = this,\n                    done = true,\n                    current = [],\n                    remaining = [];\n                if(!is_callback) { \n                    this.data.core.reopen = false; \n                    this.data.core.refreshing = true; \n                    this.data.core.to_open = $.map($.makeArray(this.data.core.to_open), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n                    this.data.core.to_load = $.map($.makeArray(this.data.core.to_load), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n                    if(this.data.core.to_open.length) {\n                        this.data.core.to_load = this.data.core.to_load.concat(this.data.core.to_open);\n                    }\n                }\n                if(this.data.core.to_load.length) {\n                    $.each(this.data.core.to_load, function (i, val) {\n                        if(val == \"#\") { return true; }\n                        if($(val).length) { current.push(val); }\n                        else { remaining.push(val); }\n                    });\n                    if(current.length) {\n                        this.data.core.to_load = remaining;\n                        $.each(current, function (i, val) { \n                            if(!_this._is_loaded(val)) {\n                                _this.load_node(val, function () { _this.reload_nodes(true); }, function () { _this.reload_nodes(true); });\n                                done = false;\n                            }\n                        });\n                    }\n                }\n                if(this.data.core.to_open.length) {\n                    $.each(this.data.core.to_open, function (i, val) {\n                        _this.open_node(val, false, true); \n                    });\n                }\n                if(done) { \n                    // TODO: find a more elegant approach to syncronizing returning requests\n                    if(this.data.core.reopen) { clearTimeout(this.data.core.reopen); }\n                    this.data.core.reopen = setTimeout(function () { _this.__callback({}, _this); }, 50);\n                    this.data.core.refreshing = false;\n                    this.reopen();\n                }\n            },\n            reopen : function () {\n                var _this = this;\n                if(this.data.core.to_open.length) {\n                    $.each(this.data.core.to_open, function (i, val) {\n                        _this.open_node(val, false, true); \n                    });\n                }\n                this.__callback({});\n            },\n            refresh : function (obj) {\n                var _this = this;\n                this.save_opened();\n                if(!obj) { obj = -1; }\n                obj = this._get_node(obj);\n                if(!obj) { obj = -1; }\n                if(obj !== -1) { obj.children(\"UL\").remove(); }\n                else { this.get_container_ul().empty(); }\n                this.load_node(obj, function () { _this.__callback({ \"obj\" : obj}); _this.reload_nodes(); });\n            },\n            // Dummy function to fire after the first load (so that there is a jstree.loaded event)\n            loaded  : function () { \n                this.__callback(); \n            },\n            // deal with focus\n            set_focus   : function () { \n                if(this.is_focused()) { return; }\n                var f = $.jstree._focused();\n                if(f) { f.unset_focus(); }\n\n                this.get_container().addClass(\"jstree-focused\"); \n                focused_instance = this.get_index(); \n                this.__callback();\n            },\n            is_focused  : function () { \n                return focused_instance == this.get_index(); \n            },\n            unset_focus : function () {\n                if(this.is_focused()) {\n                    this.get_container().removeClass(\"jstree-focused\"); \n                    focused_instance = -1; \n                }\n                this.__callback();\n            },\n\n            // traverse\n            _get_node       : function (obj) { \n                var $obj = $(obj, this.get_container()); \n                if($obj.is(\".jstree\") || obj == -1) { return -1; } \n                $obj = $obj.closest(\"li\", this.get_container()); \n                return $obj.length ? $obj : false; \n            },\n            _get_next       : function (obj, strict) {\n                obj = this._get_node(obj);\n                if(obj === -1) { return this.get_container().find(\"> ul > li:first-child\"); }\n                if(!obj.length) { return false; }\n                if(strict) { return (obj.nextAll(\"li\").size() > 0) ? obj.nextAll(\"li:eq(0)\") : false; }\n\n                if(obj.hasClass(\"jstree-open\")) { return obj.find(\"li:eq(0)\"); }\n                else if(obj.nextAll(\"li\").size() > 0) { return obj.nextAll(\"li:eq(0)\"); }\n                else { return obj.parentsUntil(\".jstree\",\"li\").next(\"li\").eq(0); }\n            },\n            _get_prev       : function (obj, strict) {\n                obj = this._get_node(obj);\n                if(obj === -1) { return this.get_container().find(\"> ul > li:last-child\"); }\n                if(!obj.length) { return false; }\n                if(strict) { return (obj.prevAll(\"li\").length > 0) ? obj.prevAll(\"li:eq(0)\") : false; }\n\n                if(obj.prev(\"li\").length) {\n                    obj = obj.prev(\"li\").eq(0);\n                    while(obj.hasClass(\"jstree-open\")) { obj = obj.children(\"ul:eq(0)\").children(\"li:last\"); }\n                    return obj;\n                }\n                else { var o = obj.parentsUntil(\".jstree\",\"li:eq(0)\"); return o.length ? o : false; }\n            },\n            _get_parent     : function (obj) {\n                obj = this._get_node(obj);\n                if(obj == -1 || !obj.length) { return false; }\n                var o = obj.parentsUntil(\".jstree\", \"li:eq(0)\");\n                return o.length ? o : -1;\n            },\n            _get_children   : function (obj) {\n                obj = this._get_node(obj);\n                if(obj === -1) { return this.get_container().children(\"ul:eq(0)\").children(\"li\"); }\n                if(!obj.length) { return false; }\n                return obj.children(\"ul:eq(0)\").children(\"li\");\n            },\n            get_path        : function (obj, id_mode) {\n                var p = [],\n                    _this = this;\n                obj = this._get_node(obj);\n                if(obj === -1 || !obj || !obj.length) { return false; }\n                obj.parentsUntil(\".jstree\", \"li\").each(function () {\n                    p.push( id_mode ? this.id : _this.get_text(this) );\n                });\n                p.reverse();\n                p.push( id_mode ? obj.attr(\"id\") : this.get_text(obj) );\n                return p;\n            },\n\n            // string functions\n            _get_string : function (key) {\n                return this._get_settings().core.strings[key] || key;\n            },\n\n            is_open     : function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass(\"jstree-open\"); },\n            is_closed   : function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass(\"jstree-closed\"); },\n            is_leaf     : function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass(\"jstree-leaf\"); },\n            correct_state   : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj || obj === -1) { return false; }\n                obj.removeClass(\"jstree-closed jstree-open\").addClass(\"jstree-leaf\").children(\"ul\").remove();\n                this.__callback({ \"obj\" : obj });\n            },\n            // open/close\n            open_node   : function (obj, callback, skip_animation) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                if(!obj.hasClass(\"jstree-closed\")) { if(callback) { callback.call(); } return false; }\n                var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,\n                    t = this;\n                if(!this._is_loaded(obj)) {\n                    obj.children(\"a\").addClass(\"jstree-loading\");\n                    this.load_node(obj, function () { t.open_node(obj, callback, skip_animation); }, callback);\n                }\n                else {\n                    if(this._get_settings().core.open_parents) {\n                        obj.parentsUntil(\".jstree\",\".jstree-closed\").each(function () {\n                            t.open_node(this, false, true);\n                        });\n                    }\n                    if(s) { obj.children(\"ul\").css(\"display\",\"none\"); }\n                    obj.removeClass(\"jstree-closed\").addClass(\"jstree-open\").children(\"a\").removeClass(\"jstree-loading\");\n                    if(s) { obj.children(\"ul\").stop(true, true).slideDown(s, function () { this.style.display = \"\"; t.after_open(obj); }); }\n                    else { t.after_open(obj); }\n                    this.__callback({ \"obj\" : obj });\n                    if(callback) { callback.call(); }\n                }\n            },\n            after_open  : function (obj) { this.__callback({ \"obj\" : obj }); },\n            close_node  : function (obj, skip_animation) {\n                obj = this._get_node(obj);\n                var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,\n                    t = this;\n                if(!obj.length || !obj.hasClass(\"jstree-open\")) { return false; }\n                if(s) { obj.children(\"ul\").attr(\"style\",\"display:block !important\"); }\n                obj.removeClass(\"jstree-open\").addClass(\"jstree-closed\");\n                if(s) { obj.children(\"ul\").stop(true, true).slideUp(s, function () { this.style.display = \"\"; t.after_close(obj); }); }\n                else { t.after_close(obj); }\n                this.__callback({ \"obj\" : obj });\n            },\n            after_close : function (obj) { this.__callback({ \"obj\" : obj }); },\n            toggle_node : function (obj) {\n                obj = this._get_node(obj);\n                if(obj.hasClass(\"jstree-closed\")) { return this.open_node(obj); }\n                if(obj.hasClass(\"jstree-open\")) { return this.close_node(obj); }\n            },\n            open_all    : function (obj, do_animation, original_obj) {\n                obj = obj ? this._get_node(obj) : -1;\n                if(!obj || obj === -1) { obj = this.get_container_ul(); }\n                if(original_obj) { \n                    obj = obj.find(\"li.jstree-closed\");\n                }\n                else {\n                    original_obj = obj;\n                    if(obj.is(\".jstree-closed\")) { obj = obj.find(\"li.jstree-closed\").andSelf(); }\n                    else { obj = obj.find(\"li.jstree-closed\"); }\n                }\n                var _this = this;\n                obj.each(function () { \n                    var __this = this; \n                    if(!_this._is_loaded(this)) { _this.open_node(this, function() { _this.open_all(__this, do_animation, original_obj); }, !do_animation); }\n                    else { _this.open_node(this, false, !do_animation); }\n                });\n                // so that callback is fired AFTER all nodes are open\n                if(original_obj.find('li.jstree-closed').length === 0) { this.__callback({ \"obj\" : original_obj }); }\n            },\n            close_all   : function (obj, do_animation) {\n                var _this = this;\n                obj = obj ? this._get_node(obj) : this.get_container();\n                if(!obj || obj === -1) { obj = this.get_container_ul(); }\n                obj.find(\"li.jstree-open\").andSelf().each(function () { _this.close_node(this, !do_animation); });\n                this.__callback({ \"obj\" : obj });\n            },\n            clean_node  : function (obj) {\n                obj = obj && obj != -1 ? $(obj) : this.get_container_ul();\n                obj = obj.is(\"li\") ? obj.find(\"li\").andSelf() : obj.find(\"li\");\n                obj.removeClass(\"jstree-last\")\n                    .filter(\"li:last-child\").addClass(\"jstree-last\").end()\n                    .filter(\":has(li)\")\n                        .not(\".jstree-open\").removeClass(\"jstree-leaf\").addClass(\"jstree-closed\");\n                obj.not(\".jstree-open, .jstree-closed\").addClass(\"jstree-leaf\").children(\"ul\").remove();\n                this.__callback({ \"obj\" : obj });\n            },\n            // rollback\n            get_rollback : function () { \n                this.__callback();\n                return { i : this.get_index(), h : this.get_container().children(\"ul\").clone(true), d : this.data }; \n            },\n            set_rollback : function (html, data) {\n                this.get_container().empty().append(html);\n                this.data = data;\n                this.__callback();\n            },\n            // Dummy functions to be overwritten by any datastore plugin included\n            load_node   : function (obj, s_call, e_call) { this.__callback({ \"obj\" : obj }); },\n            _is_loaded  : function (obj) { return true; },\n\n            // Basic operations: create\n            create_node : function (obj, position, js, callback, is_loaded) {\n                obj = this._get_node(obj);\n                position = typeof position === \"undefined\" ? \"last\" : position;\n                var d = $(\"<li />\"),\n                    s = this._get_settings().core,\n                    tmp;\n\n                if(obj !== -1 && !obj.length) { return false; }\n                if(!is_loaded && !this._is_loaded(obj)) { this.load_node(obj, function () { this.create_node(obj, position, js, callback, true); }); return false; }\n\n                this.__rollback();\n\n                if(typeof js === \"string\") { js = { \"data\" : js }; }\n                if(!js) { js = {}; }\n                if(js.attr) { d.attr(js.attr); }\n                if(js.metadata) { d.data(js.metadata); }\n                if(js.state) { d.addClass(\"jstree-\" + js.state); }\n                if(!js.data) { js.data = this._get_string(\"new_node\"); }\n                if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }\n                $.each(js.data, function (i, m) {\n                    tmp = $(\"<a />\");\n                    if($.isFunction(m)) { m = m.call(this, js); }\n                    if(typeof m == \"string\") { tmp.attr('href','#')[ s.html_titles ? \"html\" : \"text\" ](m); }\n                    else {\n                        if(!m.attr) { m.attr = {}; }\n                        if(!m.attr.href) { m.attr.href = '#'; }\n                        tmp.attr(m.attr)[ s.html_titles ? \"html\" : \"text\" ](m.title);\n                        if(m.language) { tmp.addClass(m.language); }\n                    }\n                    tmp.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n                    if(!m.icon && js.icon) { m.icon = js.icon; }\n                    if(m.icon) { \n                        if(m.icon.indexOf(\"/\") === -1) { tmp.children(\"ins\").addClass(m.icon); }\n                        else { tmp.children(\"ins\").css(\"background\",\"url('\" + m.icon + \"') center center no-repeat\"); }\n                    }\n                    d.append(tmp);\n                });\n                d.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n                if(obj === -1) {\n                    obj = this.get_container();\n                    if(position === \"before\") { position = \"first\"; }\n                    if(position === \"after\") { position = \"last\"; }\n                }\n                switch(position) {\n                    case \"before\": obj.before(d); tmp = this._get_parent(obj); break;\n                    case \"after\" : obj.after(d);  tmp = this._get_parent(obj); break;\n                    case \"inside\":\n                    case \"first\" :\n                        if(!obj.children(\"ul\").length) { obj.append(\"<ul />\"); }\n                        obj.children(\"ul\").prepend(d);\n                        tmp = obj;\n                        break;\n                    case \"last\":\n                        if(!obj.children(\"ul\").length) { obj.append(\"<ul />\"); }\n                        obj.children(\"ul\").append(d);\n                        tmp = obj;\n                        break;\n                    default:\n                        if(!obj.children(\"ul\").length) { obj.append(\"<ul />\"); }\n                        if(!position) { position = 0; }\n                        tmp = obj.children(\"ul\").children(\"li\").eq(position);\n                        if(tmp.length) { tmp.before(d); }\n                        else { obj.children(\"ul\").append(d); }\n                        tmp = obj;\n                        break;\n                }\n                if(tmp === -1 || tmp.get(0) === this.get_container().get(0)) { tmp = -1; }\n                this.clean_node(tmp);\n                this.__callback({ \"obj\" : d, \"parent\" : tmp });\n                if(callback) { callback.call(this, d); }\n                return d;\n            },\n            // Basic operations: rename (deal with text)\n            get_text    : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                var s = this._get_settings().core.html_titles;\n                obj = obj.children(\"a:eq(0)\");\n                if(s) {\n                    obj = obj.clone();\n                    obj.children(\"INS\").remove();\n                    return obj.html();\n                }\n                else {\n                    obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n                    return obj.nodeValue;\n                }\n            },\n            set_text    : function (obj, val) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                obj = obj.children(\"a:eq(0)\");\n                if(this._get_settings().core.html_titles) {\n                    var tmp = obj.children(\"INS\").clone();\n                    obj.html(val).prepend(tmp);\n                    this.__callback({ \"obj\" : obj, \"name\" : val });\n                    return true;\n                }\n                else {\n                    obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n                    this.__callback({ \"obj\" : obj, \"name\" : val });\n                    return (obj.nodeValue = val);\n                }\n            },\n            rename_node : function (obj, val) {\n                obj = this._get_node(obj);\n                this.__rollback();\n                if(obj && obj.length && this.set_text.apply(this, Array.prototype.slice.call(arguments))) { this.__callback({ \"obj\" : obj, \"name\" : val }); }\n            },\n            // Basic operations: deleting nodes\n            delete_node : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                this.__rollback();\n                var p = this._get_parent(obj), prev = $([]), t = this;\n                obj.each(function () {\n                    prev = prev.add(t._get_prev(this));\n                });\n                obj = obj.detach();\n                if(p !== -1 && p.find(\"> ul > li\").length === 0) {\n                    p.removeClass(\"jstree-open jstree-closed\").addClass(\"jstree-leaf\");\n                }\n                this.clean_node(p);\n                this.__callback({ \"obj\" : obj, \"prev\" : prev, \"parent\" : p });\n                return obj;\n            },\n            prepare_move : function (o, r, pos, cb, is_cb) {\n                var p = {};\n\n                p.ot = $.jstree._reference(o) || this;\n                p.o = p.ot._get_node(o);\n                p.r = r === - 1 ? -1 : this._get_node(r);\n                p.p = (typeof pos === \"undefined\" || pos === false) ? \"last\" : pos; // TODO: move to a setting\n                if(!is_cb && prepared_move.o && prepared_move.o[0] === p.o[0] && prepared_move.r[0] === p.r[0] && prepared_move.p === p.p) {\n                    this.__callback(prepared_move);\n                    if(cb) { cb.call(this, prepared_move); }\n                    return;\n                }\n                p.ot = $.jstree._reference(p.o) || this;\n                p.rt = $.jstree._reference(p.r) || this; // r === -1 ? p.ot : $.jstree._reference(p.r) || this\n                if(p.r === -1 || !p.r) {\n                    p.cr = -1;\n                    switch(p.p) {\n                        case \"first\":\n                        case \"before\":\n                        case \"inside\":\n                            p.cp = 0; \n                            break;\n                        case \"after\":\n                        case \"last\":\n                            p.cp = p.rt.get_container().find(\" > ul > li\").length; \n                            break;\n                        default:\n                            p.cp = p.p;\n                            break;\n                    }\n                }\n                else {\n                    if(!/^(before|after)$/.test(p.p) && !this._is_loaded(p.r)) {\n                        return this.load_node(p.r, function () { this.prepare_move(o, r, pos, cb, true); });\n                    }\n                    switch(p.p) {\n                        case \"before\":\n                            p.cp = p.r.index();\n                            p.cr = p.rt._get_parent(p.r);\n                            break;\n                        case \"after\":\n                            p.cp = p.r.index() + 1;\n                            p.cr = p.rt._get_parent(p.r);\n                            break;\n                        case \"inside\":\n                        case \"first\":\n                            p.cp = 0;\n                            p.cr = p.r;\n                            break;\n                        case \"last\":\n                            p.cp = p.r.find(\" > ul > li\").length; \n                            p.cr = p.r;\n                            break;\n                        default: \n                            p.cp = p.p;\n                            p.cr = p.r;\n                            break;\n                    }\n                }\n                p.np = p.cr == -1 ? p.rt.get_container() : p.cr;\n                p.op = p.ot._get_parent(p.o);\n                p.cop = p.o.index();\n                if(p.op === -1) { p.op = p.ot ? p.ot.get_container() : this.get_container(); }\n                if(!/^(before|after)$/.test(p.p) && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp++; }\n                //if(p.p === \"before\" && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp--; }\n                p.or = p.np.find(\" > ul > li:nth-child(\" + (p.cp + 1) + \")\");\n                prepared_move = p;\n                this.__callback(prepared_move);\n                if(cb) { cb.call(this, prepared_move); }\n            },\n            check_move : function () {\n                var obj = prepared_move, ret = true, r = obj.r === -1 ? this.get_container() : obj.r;\n                if(!obj || !obj.o || obj.or[0] === obj.o[0]) { return false; }\n                if(obj.op && obj.np && obj.op[0] === obj.np[0] && obj.cp - 1 === obj.o.index()) { return false; }\n                obj.o.each(function () { \n                    if(r.parentsUntil(\".jstree\", \"li\").andSelf().index(this) !== -1) { ret = false; return false; }\n                });\n                return ret;\n            },\n            move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {\n                if(!is_prepared) { \n                    return this.prepare_move(obj, ref, position, function (p) {\n                        this.move_node(p, false, false, is_copy, true, skip_check);\n                    });\n                }\n                if(is_copy) { \n                    prepared_move.cy = true;\n                }\n                if(!skip_check && !this.check_move()) { return false; }\n\n                this.__rollback();\n                var o = false;\n                if(is_copy) {\n                    o = obj.o.clone(true);\n                    o.find(\"*[id]\").andSelf().each(function () {\n                        if(this.id) { this.id = \"copy_\" + this.id; }\n                    });\n                }\n                else { o = obj.o; }\n\n                if(obj.or.length) { obj.or.before(o); }\n                else { \n                    if(!obj.np.children(\"ul\").length) { $(\"<ul />\").appendTo(obj.np); }\n                    obj.np.children(\"ul:eq(0)\").append(o); \n                }\n\n                try { \n                    obj.ot.clean_node(obj.op);\n                    obj.rt.clean_node(obj.np);\n                    if(!obj.op.find(\"> ul > li\").length) {\n                        obj.op.removeClass(\"jstree-open jstree-closed\").addClass(\"jstree-leaf\").children(\"ul\").remove();\n                    }\n                } catch (e) { }\n\n                if(is_copy) { \n                    prepared_move.cy = true;\n                    prepared_move.oc = o; \n                }\n                this.__callback(prepared_move);\n                return prepared_move;\n            },\n            _get_move : function () { return prepared_move; }\n        }\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree ui plugin\n * This plugins handles selecting/deselecting/hovering/dehovering nodes\n */\n(function ($) {\n    var scrollbar_width, e1, e2;\n    $(function() {\n        if (/msie/.test(navigator.userAgent.toLowerCase())) {\n            e1 = $('<textarea cols=\"10\" rows=\"2\"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');\n            e2 = $('<textarea cols=\"10\" rows=\"2\" style=\"overflow: hidden;\"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');\n            scrollbar_width = e1.width() - e2.width();\n            e1.add(e2).remove();\n        } \n        else {\n            e1 = $('<div />').css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: 0 })\n                    .prependTo('body').append('<div />').find('div').css({ width: '100%', height: 200 });\n            scrollbar_width = 100 - e1.width();\n            e1.parent().remove();\n        }\n    });\n    $.jstree.plugin(\"ui\", {\n        __init : function () { \n            this.data.ui.selected = $(); \n            this.data.ui.last_selected = false; \n            this.data.ui.hovered = null;\n            this.data.ui.to_select = this.get_settings().ui.initially_select;\n\n            this.get_container()\n                .delegate(\"a\", \"click.jstree\", $.proxy(function (event) {\n                        event.preventDefault();\n                        event.currentTarget.blur();\n                        if(!$(event.currentTarget).hasClass(\"jstree-loading\")) {\n                            this.select_node(event.currentTarget, true, event);\n                        }\n                    }, this))\n                .delegate(\"a\", \"mouseenter.jstree\", $.proxy(function (event) {\n                        if(!$(event.currentTarget).hasClass(\"jstree-loading\")) {\n                            this.hover_node(event.target);\n                        }\n                    }, this))\n                .delegate(\"a\", \"mouseleave.jstree\", $.proxy(function (event) {\n                        if(!$(event.currentTarget).hasClass(\"jstree-loading\")) {\n                            this.dehover_node(event.target);\n                        }\n                    }, this))\n                .bind(\"reopen.jstree\", $.proxy(function () { \n                        this.reselect();\n                    }, this))\n                .bind(\"get_rollback.jstree\", $.proxy(function () { \n                        this.dehover_node();\n                        this.save_selected();\n                    }, this))\n                .bind(\"set_rollback.jstree\", $.proxy(function () { \n                        this.reselect();\n                    }, this))\n                .bind(\"close_node.jstree\", $.proxy(function (event, data) { \n                        var s = this._get_settings().ui,\n                            obj = this._get_node(data.rslt.obj),\n                            clk = (obj && obj.length) ? obj.children(\"ul\").find(\"a.jstree-clicked\") : $(),\n                            _this = this;\n                        if(s.selected_parent_close === false || !clk.length) { return; }\n                        clk.each(function () { \n                            _this.deselect_node(this);\n                            if(s.selected_parent_close === \"select_parent\") { _this.select_node(obj); }\n                        });\n                    }, this))\n                .bind(\"delete_node.jstree\", $.proxy(function (event, data) { \n                        var s = this._get_settings().ui.select_prev_on_delete,\n                            obj = this._get_node(data.rslt.obj),\n                            clk = (obj && obj.length) ? obj.find(\"a.jstree-clicked\") : [],\n                            _this = this;\n                        clk.each(function () { _this.deselect_node(this); });\n                        if(s && clk.length) { \n                            data.rslt.prev.each(function () { \n                                if(this.parentNode) { _this.select_node(this); return false; /* if return false is removed all prev nodes will be selected */}\n                            });\n                        }\n                    }, this))\n                .bind(\"move_node.jstree\", $.proxy(function (event, data) { \n                        if(data.rslt.cy) { \n                            data.rslt.oc.find(\"a.jstree-clicked\").removeClass(\"jstree-clicked\");\n                        }\n                    }, this));\n        },\n        defaults : {\n            select_limit : -1, // 0, 1, 2 ... or -1 for unlimited\n            select_multiple_modifier : \"ctrl\", // on, or ctrl, shift, alt\n            select_range_modifier : \"shift\",\n            selected_parent_close : \"select_parent\", // false, \"deselect\", \"select_parent\"\n            selected_parent_open : true,\n            select_prev_on_delete : true,\n            disable_selecting_children : false,\n            initially_select : []\n        },\n        _fn : { \n            _get_node : function (obj, allow_multiple) {\n                if(typeof obj === \"undefined\" || obj === null) { return allow_multiple ? this.data.ui.selected : this.data.ui.last_selected; }\n                var $obj = $(obj, this.get_container()); \n                if($obj.is(\".jstree\") || obj == -1) { return -1; } \n                $obj = $obj.closest(\"li\", this.get_container()); \n                return $obj.length ? $obj : false; \n            },\n            _ui_notify : function (n, data) {\n                if(data.selected) {\n                    this.select_node(n, false);\n                }\n            },\n            save_selected : function () {\n                var _this = this;\n                this.data.ui.to_select = [];\n                this.data.ui.selected.each(function () { if(this.id) { _this.data.ui.to_select.push(\"#\" + this.id.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\")); } });\n                this.__callback(this.data.ui.to_select);\n            },\n            reselect : function () {\n                var _this = this,\n                    s = this.data.ui.to_select;\n                s = $.map($.makeArray(s), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n                // this.deselect_all(); WHY deselect, breaks plugin state notifier?\n                $.each(s, function (i, val) { if(val && val !== \"#\") { _this.select_node(val); } });\n                this.data.ui.selected = this.data.ui.selected.filter(function () { return this.parentNode; });\n                this.__callback();\n            },\n            refresh : function (obj) {\n                this.save_selected();\n                return this.__call_old();\n            },\n            hover_node : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                //if(this.data.ui.hovered && obj.get(0) === this.data.ui.hovered.get(0)) { return; }\n                if(!obj.hasClass(\"jstree-hovered\")) { this.dehover_node(); }\n                this.data.ui.hovered = obj.children(\"a\").addClass(\"jstree-hovered\").parent();\n                // brackets: jstree uses default scroll bar widths, and there's no clean way to override the code from brackets, which causes continuous scrolling, so just disable for now\n                //this._fix_scroll(obj);\n                this.__callback({ \"obj\" : obj });\n            },\n            dehover_node : function () {\n                var obj = this.data.ui.hovered, p;\n                if(!obj || !obj.length) { return false; }\n                p = obj.children(\"a\").removeClass(\"jstree-hovered\").parent();\n                if(this.data.ui.hovered[0] === p[0]) { this.data.ui.hovered = null; }\n                this.__callback({ \"obj\" : obj });\n            },\n            select_node : function (obj, check, e) {\n                obj = this._get_node(obj);\n                if(obj == -1 || !obj || !obj.length) { return false; }\n                var s = this._get_settings().ui,\n                    is_multiple = (s.select_multiple_modifier == \"on\" || (s.select_multiple_modifier !== false && e && e[s.select_multiple_modifier + \"Key\"])),\n                    is_range = (s.select_range_modifier !== false && e && e[s.select_range_modifier + \"Key\"] && this.data.ui.last_selected && this.data.ui.last_selected[0] !== obj[0] && this.data.ui.last_selected.parent()[0] === obj.parent()[0]),\n                    is_selected = this.is_selected(obj),\n                    proceed = true,\n                    t = this;\n                if(check) {\n                    if(s.disable_selecting_children && is_multiple && \n                        (\n                            (obj.parentsUntil(\".jstree\",\"li\").children(\"a.jstree-clicked\").length) ||\n                            (obj.children(\"ul\").find(\"a.jstree-clicked:eq(0)\").length)\n                        )\n                    ) {\n                        return false;\n                    }\n                    proceed = false;\n                    switch(!0) {\n                        case (is_range):\n                            this.data.ui.last_selected.addClass(\"jstree-last-selected\");\n                            obj = obj[ obj.index() < this.data.ui.last_selected.index() ? \"nextUntil\" : \"prevUntil\" ](\".jstree-last-selected\").andSelf();\n                            if(s.select_limit == -1 || obj.length < s.select_limit) {\n                                this.data.ui.last_selected.removeClass(\"jstree-last-selected\");\n                                this.data.ui.selected.each(function () {\n                                    if(this !== t.data.ui.last_selected[0]) { t.deselect_node(this); }\n                                });\n                                is_selected = false;\n                                proceed = true;\n                            }\n                            else {\n                                proceed = false;\n                            }\n                            break;\n                        case (is_selected && !is_multiple): \n                            this.deselect_all();\n                            is_selected = false;\n                            proceed = true;\n                            break;\n                        case (!is_selected && !is_multiple): \n                            if(s.select_limit == -1 || s.select_limit > 0) {\n                                this.deselect_all();\n                                proceed = true;\n                            }\n                            break;\n                        case (is_selected && is_multiple): \n                            this.deselect_node(obj);\n                            break;\n                        case (!is_selected && is_multiple): \n                            if(s.select_limit == -1 || this.data.ui.selected.length + 1 <= s.select_limit) { \n                                proceed = true;\n                            }\n                            break;\n                    }\n                }\n                if(proceed && !is_selected) {\n                    if(!is_range) { this.data.ui.last_selected = obj; }\n                    obj.children(\"a\").addClass(\"jstree-clicked\");\n                    if(s.selected_parent_open) {\n                        obj.parents(\".jstree-closed\").each(function () { t.open_node(this, false, true); });\n                    }\n                    this.data.ui.selected = this.data.ui.selected.add(obj);\n                    this._fix_scroll(obj.eq(0));\n                    this.__callback({ \"obj\" : obj, \"e\" : e });\n                }\n            },\n            _fix_scroll : function (obj) {\n                var c = this.get_container()[0], t;\n                if(c.scrollHeight > c.offsetHeight) {\n                    obj = this._get_node(obj);\n                    if(!obj || obj === -1 || !obj.length || !obj.is(\":visible\")) { return; }\n                    t = obj.offset().top - this.get_container().offset().top;\n                    if(t < 0) { \n                        c.scrollTop = c.scrollTop + t - 1; \n                    }\n                    if(t + this.data.core.li_height + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0) > c.offsetHeight) { \n                        c.scrollTop = c.scrollTop + (t - c.offsetHeight + this.data.core.li_height + 1 + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0)); \n                    }\n                }\n            },\n            deselect_node : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                if(this.is_selected(obj)) {\n                    obj.children(\"a\").removeClass(\"jstree-clicked\");\n                    this.data.ui.selected = this.data.ui.selected.not(obj);\n                    if(this.data.ui.last_selected.get(0) === obj.get(0)) { this.data.ui.last_selected = this.data.ui.selected.eq(0); }\n                    this.__callback({ \"obj\" : obj });\n                }\n            },\n            toggle_select : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return false; }\n                if(this.is_selected(obj)) { this.deselect_node(obj); }\n                else { this.select_node(obj); }\n            },\n            is_selected : function (obj) { return this.data.ui.selected.index(this._get_node(obj)) >= 0; },\n            get_selected : function (context) { \n                return context ? $(context).find(\"a.jstree-clicked\").parent() : this.data.ui.selected; \n            },\n            deselect_all : function (context) {\n                var ret = context ? $(context).find(\"a.jstree-clicked\").parent() : this.get_container().find(\"a.jstree-clicked\").parent();\n                ret.children(\"a.jstree-clicked\").removeClass(\"jstree-clicked\");\n                this.data.ui.selected = $([]);\n                this.data.ui.last_selected = false;\n                this.__callback({ \"obj\" : ret });\n            }\n        }\n    });\n    // include the selection plugin by default\n    $.jstree.defaults.plugins.push(\"ui\");\n})(jQuery);\n//*/\n\n/* \n * jsTree CRRM plugin\n * Handles creating/renaming/removing/moving nodes by user interaction.\n */\n(function ($) {\n    $.jstree.plugin(\"crrm\", { \n        __init : function () {\n            this.get_container()\n                .bind(\"move_node.jstree\", $.proxy(function (e, data) {\n                    if(this._get_settings().crrm.move.open_onmove) {\n                        var t = this;\n                        data.rslt.np.parentsUntil(\".jstree\").andSelf().filter(\".jstree-closed\").each(function () {\n                            t.open_node(this, false, true);\n                        });\n                    }\n                }, this));\n        },\n        defaults : {\n            input_width_limit : 200,\n            move : {\n                always_copy         : false, // false, true or \"multitree\"\n                open_onmove         : true,\n                default_position    : \"last\",\n                check_move          : function (m) { return true; }\n            }\n        },\n        _fn : {\n            _show_input : function (obj, callback) {\n                obj = this._get_node(obj);\n                var rtl = this._get_settings().core.rtl,\n                    w = this._get_settings().crrm.input_width_limit,\n                    w1 = obj.children(\"ins\").width(),\n                    w2 = obj.find(\"> a:visible > ins\").width() * obj.find(\"> a:visible > ins\").length,\n                    t = this.get_text(obj),\n                    h1 = $(\"<div />\", { css : { \"position\" : \"absolute\", \"top\" : \"-200px\", \"left\" : (rtl ? \"0px\" : \"-1000px\"), \"visibility\" : \"hidden\" } }).appendTo(\"body\"),\n                    h2 = obj.css(\"position\",\"relative\").append(\n                    $(\"<input />\", { \n                        \"value\" : t,\n                        \"class\" : \"jstree-rename-input\",\n                        // \"size\" : t.length,\n                        \"css\" : {\n                            \"padding\" : \"0\",\n                            \"border\" : \"1px solid silver\",\n                            \"position\" : \"absolute\",\n                            \"left\"  : (rtl ? \"auto\" : (w1 + w2 + 4) + \"px\"),\n                            \"right\" : (rtl ? (w1 + w2 + 4) + \"px\" : \"auto\"),\n                            \"top\" : \"0px\",\n                            \"height\" : (this.data.core.li_height - 2) + \"px\",\n                            \"lineHeight\" : (this.data.core.li_height - 2) + \"px\",\n                            \"width\" : \"150px\" // will be set a bit further down\n                        },\n                        \"blur\" : $.proxy(function () {\n                            var i = obj.children(\".jstree-rename-input\"),\n                                v = i.val();\n                            if(v === \"\") { v = t; }\n                            h1.remove();\n                            i.remove(); // rollback purposes\n                            this.set_text(obj,t); // rollback purposes\n                            this.rename_node(obj, v);\n                            callback.call(this, obj, v, t);\n                            obj.css(\"position\",\"\");\n                        }, this),\n                        \"keyup\" : function (event) {\n                            var key = event.keyCode || event.which;\n                            if(key == 27) { this.value = t; this.blur(); return; }\n                            else if(key == 13) { this.blur(); return; }\n                            else {\n                                h2.width(Math.min(h1.text(\"pW\" + this.value).width(),w));\n                            }\n                        },\n                        \"keypress\" : function(event) {\n                            var key = event.keyCode || event.which;\n                            if(key == 13) { return false; }\n                        }\n                    })\n                ).children(\".jstree-rename-input\"); \n                this.set_text(obj, \"\");\n                h1.css({\n                        fontFamily      : h2.css('fontFamily')      || '',\n                        fontSize        : h2.css('fontSize')        || '',\n                        fontWeight      : h2.css('fontWeight')      || '',\n                        fontStyle       : h2.css('fontStyle')       || '',\n                        fontStretch     : h2.css('fontStretch')     || '',\n                        fontVariant     : h2.css('fontVariant')     || '',\n                        letterSpacing   : h2.css('letterSpacing')   || '',\n                        wordSpacing     : h2.css('wordSpacing')     || ''\n                });\n                h2.width(Math.min(h1.text(\"pW\" + h2[0].value).width(),w))[0].select();\n            },\n            rename : function (obj) {\n                obj = this._get_node(obj);\n                this.__rollback();\n                var f = this.__callback;\n                this._show_input(obj, function (obj, new_name, old_name) { \n                    f.call(this, { \"obj\" : obj, \"new_name\" : new_name, \"old_name\" : old_name });\n                });\n            },\n            create : function (obj, position, js, callback, skip_rename) {\n                var t, _this = this;\n                obj = this._get_node(obj);\n                if(!obj) { obj = -1; }\n                this.__rollback();\n                t = this.create_node(obj, position, js, function (t) {\n                    var p = this._get_parent(t),\n                        pos = $(t).index();\n                    if(callback) { callback.call(this, t); }\n                    if(p.length && p.hasClass(\"jstree-closed\")) { this.open_node(p, false, true); }\n                    if(!skip_rename) { \n                        this._show_input(t, function (obj, new_name, old_name) { \n                            _this.__callback({ \"obj\" : obj, \"name\" : new_name, \"parent\" : p, \"position\" : pos });\n                        });\n                    }\n                    else { _this.__callback({ \"obj\" : t, \"name\" : this.get_text(t), \"parent\" : p, \"position\" : pos }); }\n                });\n                return t;\n            },\n            remove : function (obj) {\n                obj = this._get_node(obj, true);\n                var p = this._get_parent(obj), prev = this._get_prev(obj);\n                this.__rollback();\n                obj = this.delete_node(obj);\n                if(obj !== false) { this.__callback({ \"obj\" : obj, \"prev\" : prev, \"parent\" : p }); }\n            },\n            check_move : function () {\n                if(!this.__call_old()) { return false; }\n                var s = this._get_settings().crrm.move;\n                if(!s.check_move.call(this, this._get_move())) { return false; }\n                return true;\n            },\n            move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {\n                var s = this._get_settings().crrm.move;\n                if(!is_prepared) { \n                    if(typeof position === \"undefined\") { position = s.default_position; }\n                    if(position === \"inside\" && !s.default_position.match(/^(before|after)$/)) { position = s.default_position; }\n                    return this.__call_old(true, obj, ref, position, is_copy, false, skip_check);\n                }\n                // if the move is already prepared\n                if(s.always_copy === true || (s.always_copy === \"multitree\" && obj.rt.get_index() !== obj.ot.get_index() )) {\n                    is_copy = true;\n                }\n                this.__call_old(true, obj, ref, position, is_copy, true, skip_check);\n            },\n\n            cut : function (obj) {\n                obj = this._get_node(obj, true);\n                if(!obj || !obj.length) { return false; }\n                this.data.crrm.cp_nodes = false;\n                this.data.crrm.ct_nodes = obj;\n                this.__callback({ \"obj\" : obj });\n            },\n            copy : function (obj) {\n                obj = this._get_node(obj, true);\n                if(!obj || !obj.length) { return false; }\n                this.data.crrm.ct_nodes = false;\n                this.data.crrm.cp_nodes = obj;\n                this.__callback({ \"obj\" : obj });\n            },\n            paste : function (obj) { \n                obj = this._get_node(obj);\n                if(!obj || !obj.length) { return false; }\n                var nodes = this.data.crrm.ct_nodes ? this.data.crrm.ct_nodes : this.data.crrm.cp_nodes;\n                if(!this.data.crrm.ct_nodes && !this.data.crrm.cp_nodes) { return false; }\n                if(this.data.crrm.ct_nodes) { this.move_node(this.data.crrm.ct_nodes, obj); this.data.crrm.ct_nodes = false; }\n                if(this.data.crrm.cp_nodes) { this.move_node(this.data.crrm.cp_nodes, obj, false, true); }\n                this.__callback({ \"obj\" : obj, \"nodes\" : nodes });\n            }\n        }\n    });\n    // include the crr plugin by default\n    // $.jstree.defaults.plugins.push(\"crrm\");\n})(jQuery);\n//*/\n\n/* \n * jsTree themes plugin\n * Handles loading and setting themes, as well as detecting path to themes, etc.\n */\n(function ($) {\n    var themes_loaded = [];\n    // this variable stores the path to the themes folder - if left as false - it will be autodetected\n    $.jstree._themes = false;\n    $.jstree.plugin(\"themes\", {\n        __init : function () { \n            this.get_container()\n                .bind(\"init.jstree\", $.proxy(function () {\n                        var s = this._get_settings().themes;\n                        this.data.themes.dots = s.dots; \n                        this.data.themes.icons = s.icons; \n                        this.set_theme(s.theme, s.url);\n                    }, this))\n                .bind(\"loaded.jstree\", $.proxy(function () {\n                        // bound here too, as simple HTML tree's won't honor dots & icons otherwise\n                        if(!this.data.themes.dots) { this.hide_dots(); }\n                        else { this.show_dots(); }\n                        if(!this.data.themes.icons) { this.hide_icons(); }\n                        else { this.show_icons(); }\n                    }, this));\n        },\n        defaults : { \n            theme : \"default\", \n            url : false,\n            dots : true,\n            icons : true\n        },\n        _fn : {\n            set_theme : function (theme_name, theme_url) {\n                if(!theme_name) { return false; }\n                if(!theme_url) { theme_url = $.jstree._themes + theme_name + '/style.css'; }\n                if($.inArray(theme_url, themes_loaded) == -1) {\n                    $.vakata.css.add_sheet({ \"url\" : theme_url });\n                    themes_loaded.push(theme_url);\n                }\n                if(this.data.themes.theme != theme_name) {\n                    this.get_container().removeClass('jstree-' + this.data.themes.theme);\n                    this.data.themes.theme = theme_name;\n                }\n                this.get_container().addClass('jstree-' + theme_name);\n                if(!this.data.themes.dots) { this.hide_dots(); }\n                else { this.show_dots(); }\n                if(!this.data.themes.icons) { this.hide_icons(); }\n                else { this.show_icons(); }\n                this.__callback();\n            },\n            get_theme   : function () { return this.data.themes.theme; },\n\n            show_dots   : function () { this.data.themes.dots = true; this.get_container().children(\"ul\").removeClass(\"jstree-no-dots\"); },\n            hide_dots   : function () { this.data.themes.dots = false; this.get_container().children(\"ul\").addClass(\"jstree-no-dots\"); },\n            toggle_dots : function () { if(this.data.themes.dots) { this.hide_dots(); } else { this.show_dots(); } },\n\n            show_icons  : function () { this.data.themes.icons = true; this.get_container().children(\"ul\").removeClass(\"jstree-no-icons\"); },\n            hide_icons  : function () { this.data.themes.icons = false; this.get_container().children(\"ul\").addClass(\"jstree-no-icons\"); },\n            toggle_icons: function () { if(this.data.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }\n        }\n    });\n    // autodetect themes path\n    $(function () {\n        if($.jstree._themes === false) {\n            $(\"script\").each(function () { \n                if(this.src.toString().match(/jquery\\.jstree[^\\/]*?\\.js(\\?.*)?$/)) { \n                    $.jstree._themes = this.src.toString().replace(/jquery\\.jstree[^\\/]*?\\.js(\\?.*)?$/, \"\") + 'themes/'; \n                    return false; \n                }\n            });\n        }\n        if($.jstree._themes === false) { $.jstree._themes = \"themes/\"; }\n    });\n    // include the themes plugin by default\n    $.jstree.defaults.plugins.push(\"themes\");\n})(jQuery);\n//*/\n\n/*\n * jsTree hotkeys plugin\n * Enables keyboard navigation for all tree instances\n * Depends on the jstree ui & jquery hotkeys plugins\n */\n(function ($) {\n    var bound = [];\n    function exec(i, event) {\n        var f = $.jstree._focused(), tmp;\n        if(f && f.data && f.data.hotkeys && f.data.hotkeys.enabled) { \n            tmp = f._get_settings().hotkeys[i];\n            if(tmp) { return tmp.call(f, event); }\n        }\n    }\n    $.jstree.plugin(\"hotkeys\", {\n        __init : function () {\n            if(typeof $.hotkeys === \"undefined\") { throw \"jsTree hotkeys: jQuery hotkeys plugin not included.\"; }\n            if(!this.data.ui) { throw \"jsTree hotkeys: jsTree UI plugin not included.\"; }\n            $.each(this._get_settings().hotkeys, function (i, v) {\n                if(v !== false && $.inArray(i, bound) == -1) {\n                    $(document).bind(\"keydown\", i, function (event) { return exec(i, event); });\n                    bound.push(i);\n                }\n            });\n            this.get_container()\n                .bind(\"lock.jstree\", $.proxy(function () {\n                        if(this.data.hotkeys.enabled) { this.data.hotkeys.enabled = false; this.data.hotkeys.revert = true; }\n                    }, this))\n                .bind(\"unlock.jstree\", $.proxy(function () {\n                        if(this.data.hotkeys.revert) { this.data.hotkeys.enabled = true; }\n                    }, this));\n            this.enable_hotkeys();\n        },\n        defaults : {\n            \"up\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                this.hover_node(this._get_prev(o));\n                return false; \n            },\n            \"ctrl+up\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                this.hover_node(this._get_prev(o));\n                return false; \n            },\n            \"shift+up\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                this.hover_node(this._get_prev(o));\n                return false; \n            },\n            \"down\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                this.hover_node(this._get_next(o));\n                return false;\n            },\n            \"ctrl+down\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                this.hover_node(this._get_next(o));\n                return false;\n            },\n            \"shift+down\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                this.hover_node(this._get_next(o));\n                return false;\n            },\n            \"left\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected;\n                if(o) {\n                    if(o.hasClass(\"jstree-open\")) { this.close_node(o); }\n                    else { this.hover_node(this._get_prev(o)); }\n                }\n                return false;\n            },\n            \"ctrl+left\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected;\n                if(o) {\n                    if(o.hasClass(\"jstree-open\")) { this.close_node(o); }\n                    else { this.hover_node(this._get_prev(o)); }\n                }\n                return false;\n            },\n            \"shift+left\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected;\n                if(o) {\n                    if(o.hasClass(\"jstree-open\")) { this.close_node(o); }\n                    else { this.hover_node(this._get_prev(o)); }\n                }\n                return false;\n            },\n            \"right\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected;\n                if(o && o.length) {\n                    if(o.hasClass(\"jstree-closed\")) { this.open_node(o); }\n                    else { this.hover_node(this._get_next(o)); }\n                }\n                return false;\n            },\n            \"ctrl+right\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected;\n                if(o && o.length) {\n                    if(o.hasClass(\"jstree-closed\")) { this.open_node(o); }\n                    else { this.hover_node(this._get_next(o)); }\n                }\n                return false;\n            },\n            \"shift+right\" : function () { \n                var o = this.data.ui.hovered || this.data.ui.last_selected;\n                if(o && o.length) {\n                    if(o.hasClass(\"jstree-closed\")) { this.open_node(o); }\n                    else { this.hover_node(this._get_next(o)); }\n                }\n                return false;\n            },\n            \"space\" : function () { \n                if(this.data.ui.hovered) { this.data.ui.hovered.children(\"a:eq(0)\").click(); } \n                return false; \n            },\n            \"ctrl+space\" : function (event) { \n                event.type = \"click\";\n                if(this.data.ui.hovered) { this.data.ui.hovered.children(\"a:eq(0)\").trigger(event); } \n                return false; \n            },\n            \"shift+space\" : function (event) { \n                event.type = \"click\";\n                if(this.data.ui.hovered) { this.data.ui.hovered.children(\"a:eq(0)\").trigger(event); } \n                return false; \n            },\n            \"f2\" : function () { this.rename(this.data.ui.hovered || this.data.ui.last_selected); },\n            \"del\" : function () { this.remove(this.data.ui.hovered || this._get_node(null)); }\n        },\n        _fn : {\n            enable_hotkeys : function () {\n                this.data.hotkeys.enabled = true;\n            },\n            disable_hotkeys : function () {\n                this.data.hotkeys.enabled = false;\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree JSON plugin\n * The JSON data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.\n */\n(function ($) {\n    $.jstree.plugin(\"json_data\", {\n        __init : function() {\n            var s = this._get_settings().json_data;\n            if(s.progressive_unload) {\n                this.get_container().bind(\"after_close.jstree\", function (e, data) {\n                    data.rslt.obj.children(\"ul\").remove();\n                });\n            }\n        },\n        defaults : { \n            // `data` can be a function:\n            //  * accepts two arguments - node being loaded and a callback to pass the result to\n            //  * will be executed in the current tree's scope & ajax won't be supported\n            data : false, \n            ajax : false,\n            correct_state : true,\n            progressive_render : false,\n            progressive_unload : false\n        },\n        _fn : {\n            load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_json(obj, function () { _this.__callback({ \"obj\" : _this._get_node(obj) }); s_call.call(this); }, e_call); },\n            _is_loaded : function (obj) { \n                var s = this._get_settings().json_data;\n                obj = this._get_node(obj); \n                return obj == -1 || !obj || (!s.ajax && !s.progressive_render && !$.isFunction(s.data)) || obj.is(\".jstree-open, .jstree-leaf\") || obj.children(\"ul\").children(\"li\").length > 0;\n            },\n            refresh : function (obj) {\n                obj = this._get_node(obj);\n                var s = this._get_settings().json_data;\n                if(obj && obj !== -1 && s.progressive_unload && ($.isFunction(s.data) || !!s.ajax)) {\n                    obj.removeData(\"jstree_children\");\n                }\n                return this.__call_old();\n            },\n            load_node_json : function (obj, s_call, e_call) {\n                var s = this.get_settings().json_data, d,\n                    error_func = function () {},\n                    success_func = function () {};\n                obj = this._get_node(obj);\n\n                if(obj && obj !== -1 && (s.progressive_render || s.progressive_unload) && !obj.is(\".jstree-open, .jstree-leaf\") && obj.children(\"ul\").children(\"li\").length === 0 && obj.data(\"jstree_children\")) {\n                    d = this._parse_json(obj.data(\"jstree_children\"), obj);\n                    if(d) {\n                        obj.append(d);\n                        if(!s.progressive_unload) { obj.removeData(\"jstree_children\"); }\n                    }\n                    this.clean_node(obj);\n                    if(s_call) { s_call.call(this); }\n                    return;\n                }\n\n                if(obj && obj !== -1) {\n                    if(obj.data(\"jstree_is_loading\")) { return; }\n                    else { obj.data(\"jstree_is_loading\",true); }\n                }\n                switch(!0) {\n                    case (!s.data && !s.ajax): throw \"Neither data nor ajax settings supplied.\";\n                    // function option added here for easier model integration (also supporting async - see callback)\n                    case ($.isFunction(s.data)):\n                        s.data.call(this, obj, $.proxy(function (d) {\n                            d = this._parse_json(d, obj);\n                            if(!d) { \n                                if(obj === -1 || !obj) {\n                                    if(s.correct_state) { this.get_container().children(\"ul\").empty(); }\n                                }\n                                else {\n                                    obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                    obj.removeData(\"jstree_is_loading\");\n                                    if(s.correct_state) { this.correct_state(obj); }\n                                }\n                                if(e_call) { e_call.call(this); }\n                            }\n                            else {\n                                if(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n                                else { obj.append(d).children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.removeData(\"jstree_is_loading\"); }\n                                this.clean_node(obj);\n                                if(s_call) { s_call.call(this); }\n                            }\n                        }, this));\n                        break;\n                    case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):\n                        if(!obj || obj == -1) {\n                            d = this._parse_json(s.data, obj);\n                            if(d) {\n                                this.get_container().children(\"ul\").empty().append(d.children());\n                                this.clean_node();\n                            }\n                            else { \n                                if(s.correct_state) { this.get_container().children(\"ul\").empty(); }\n                            }\n                        }\n                        if(s_call) { s_call.call(this); }\n                        break;\n                    case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):\n                        error_func = function (x, t, e) {\n                            var ef = this.get_settings().json_data.ajax.error; \n                            if(ef) { ef.call(this, x, t, e); }\n                            if(obj != -1 && obj.length) {\n                                obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                obj.removeData(\"jstree_is_loading\");\n                                if(t === \"success\" && s.correct_state) { this.correct_state(obj); }\n                            }\n                            else {\n                                if(t === \"success\" && s.correct_state) { this.get_container().children(\"ul\").empty(); }\n                            }\n                            if(e_call) { e_call.call(this); }\n                        };\n                        success_func = function (d, t, x) {\n                            var sf = this.get_settings().json_data.ajax.success; \n                            if(sf) { d = sf.call(this,d,t,x) || d; }\n                            if(d === \"\" || (d && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") === \"\") || (!$.isArray(d) && !$.isPlainObject(d))) {\n                                return error_func.call(this, x, t, \"\");\n                            }\n                            d = this._parse_json(d, obj);\n                            if(d) {\n                                if(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n                                else { obj.append(d).children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.removeData(\"jstree_is_loading\"); }\n                                this.clean_node(obj);\n                                if(s_call) { s_call.call(this); }\n                            }\n                            else {\n                                if(obj === -1 || !obj) {\n                                    if(s.correct_state) { \n                                        this.get_container().children(\"ul\").empty(); \n                                        if(s_call) { s_call.call(this); }\n                                    }\n                                }\n                                else {\n                                    obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                    obj.removeData(\"jstree_is_loading\");\n                                    if(s.correct_state) { \n                                        this.correct_state(obj);\n                                        if(s_call) { s_call.call(this); } \n                                    }\n                                }\n                            }\n                        };\n                        s.ajax.context = this;\n                        s.ajax.error = error_func;\n                        s.ajax.success = success_func;\n                        if(!s.ajax.dataType) { s.ajax.dataType = \"json\"; }\n                        if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }\n                        if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }\n                        $.ajax(s.ajax);\n                        break;\n                }\n            },\n            _parse_json : function (js, obj, is_callback) {\n                var d = false, \n                    p = this._get_settings(),\n                    s = p.json_data,\n                    t = p.core.html_titles,\n                    tmp, i, j, ul1, ul2;\n\n                if(!js) { return d; }\n                if(s.progressive_unload && obj && obj !== -1) { \n                    obj.data(\"jstree_children\", d);\n                }\n                if($.isArray(js)) {\n                    d = $();\n                    if(!js.length) { return false; }\n                    for(i = 0, j = js.length; i < j; i++) {\n                        tmp = this._parse_json(js[i], obj, true);\n                        if(tmp.length) { d = d.add(tmp); }\n                    }\n                }\n                else {\n                    if(typeof js == \"string\") { js = { data : js }; }\n                    if(!js.data && js.data !== \"\") { return d; }\n                    d = $(\"<li />\");\n                    if(js.attr) { d.attr(js.attr); }\n                    if(js.metadata) { d.data(js.metadata); }\n                    if(js.state) { d.addClass(\"jstree-\" + js.state); }\n                    if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }\n                    $.each(js.data, function (i, m) {\n                        tmp = $(\"<a />\");\n                        if($.isFunction(m)) { m = m.call(this, js); }\n                        if(typeof m == \"string\") { tmp.attr('href','#')[ t ? \"html\" : \"text\" ](m); }\n                        else {\n                            if(!m.attr) { m.attr = {}; }\n                            if(!m.attr.href) { m.attr.href = '#'; }\n                            tmp.attr(m.attr)[ t ? \"html\" : \"text\" ](m.title);\n                            if(m.language) { tmp.addClass(m.language); }\n                        }\n                        tmp.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n                        if(!m.icon && js.icon) { m.icon = js.icon; }\n                        if(m.icon) { \n                            if(m.icon.indexOf(\"/\") === -1) { tmp.children(\"ins\").addClass(m.icon); }\n                            else { tmp.children(\"ins\").css(\"background\",\"url('\" + m.icon + \"') center center no-repeat\"); }\n                        }\n                        d.append(tmp);\n                    });\n                    d.prepend(\"<ins class='jstree-icon'>&#160;</ins>\");\n                    if(js.children) { \n                        if(s.progressive_render && js.state !== \"open\") {\n                            d.addClass(\"jstree-closed\").data(\"jstree_children\", js.children);\n                        }\n                        else {\n                            if(s.progressive_unload) { d.data(\"jstree_children\", js.children); }\n                            if($.isArray(js.children) && js.children.length) {\n                                tmp = this._parse_json(js.children, obj, true);\n                                if(tmp.length) {\n                                    ul2 = $(\"<ul />\");\n                                    ul2.append(tmp);\n                                    d.append(ul2);\n                                }\n                            }\n                        }\n                    }\n                }\n                if(!is_callback) {\n                    ul1 = $(\"<ul />\");\n                    ul1.append(d);\n                    d = ul1;\n                }\n                return d;\n            },\n            get_json : function (obj, li_attr, a_attr, is_callback) {\n                var result = [], \n                    s = this._get_settings(), \n                    _this = this,\n                    tmp1, tmp2, li, a, t, lang;\n                obj = this._get_node(obj);\n                if(!obj || obj === -1) { obj = this.get_container().find(\"> ul > li\"); }\n                li_attr = $.isArray(li_attr) ? li_attr : [ \"id\", \"class\" ];\n                if(!is_callback && this.data.types) { li_attr.push(s.types.type_attr); }\n                a_attr = $.isArray(a_attr) ? a_attr : [ ];\n\n                obj.each(function () {\n                    li = $(this);\n                    tmp1 = { data : [] };\n                    if(li_attr.length) { tmp1.attr = { }; }\n                    $.each(li_attr, function (i, v) { \n                        tmp2 = li.attr(v); \n                        if(tmp2 && tmp2.length && tmp2.replace(/jstree[^ ]*/ig,'').length) {\n                            tmp1.attr[v] = (\" \" + tmp2).replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\"); \n                        }\n                    });\n                    if(li.hasClass(\"jstree-open\")) { tmp1.state = \"open\"; }\n                    if(li.hasClass(\"jstree-closed\")) { tmp1.state = \"closed\"; }\n                    if(li.data()) { tmp1.metadata = li.data(); }\n                    a = li.children(\"a\");\n                    a.each(function () {\n                        t = $(this);\n                        if(\n                            a_attr.length || \n                            $.inArray(\"languages\", s.plugins) !== -1 || \n                            t.children(\"ins\").get(0).style.backgroundImage.length || \n                            (t.children(\"ins\").get(0).className && t.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').length)\n                        ) { \n                            lang = false;\n                            if($.inArray(\"languages\", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {\n                                $.each(s.languages, function (l, lv) {\n                                    if(t.hasClass(lv)) {\n                                        lang = lv;\n                                        return false;\n                                    }\n                                });\n                            }\n                            tmp2 = { attr : { }, title : _this.get_text(t, lang) }; \n                            $.each(a_attr, function (k, z) {\n                                tmp2.attr[z] = (\" \" + (t.attr(z) || \"\")).replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\");\n                            });\n                            if($.inArray(\"languages\", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {\n                                $.each(s.languages, function (k, z) {\n                                    if(t.hasClass(z)) { tmp2.language = z; return true; }\n                                });\n                            }\n                            if(t.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\\s+$/ig,\"\").length) {\n                                tmp2.icon = t.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\");\n                            }\n                            if(t.children(\"ins\").get(0).style.backgroundImage.length) {\n                                tmp2.icon = t.children(\"ins\").get(0).style.backgroundImage.replace(\"url(\",\"\").replace(\")\",\"\");\n                            }\n                        }\n                        else {\n                            tmp2 = _this.get_text(t);\n                        }\n                        if(a.length > 1) { tmp1.data.push(tmp2); }\n                        else { tmp1.data = tmp2; }\n                    });\n                    li = li.find(\"> ul > li\");\n                    if(li.length) { tmp1.children = _this.get_json(li, li_attr, a_attr, true); }\n                    result.push(tmp1);\n                });\n                return result;\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree languages plugin\n * Adds support for multiple language versions in one tree\n * This basically allows for many titles coexisting in one node, but only one of them being visible at any given time\n * This is useful for maintaining the same structure in many languages (hence the name of the plugin)\n */\n(function ($) {\n    $.jstree.plugin(\"languages\", {\n        __init : function () { this._load_css();  },\n        defaults : [],\n        _fn : {\n            set_lang : function (i) { \n                var langs = this._get_settings().languages,\n                    st = false,\n                    selector = \".jstree-\" + this.get_index() + ' a';\n                if(!$.isArray(langs) || langs.length === 0) { return false; }\n                if($.inArray(i,langs) == -1) {\n                    if(!!langs[i]) { i = langs[i]; }\n                    else { return false; }\n                }\n                if(i == this.data.languages.current_language) { return true; }\n                st = $.vakata.css.get_css(selector + \".\" + this.data.languages.current_language, false, this.data.languages.language_css);\n                if(st !== false) { st.style.display = \"none\"; }\n                st = $.vakata.css.get_css(selector + \".\" + i, false, this.data.languages.language_css);\n                if(st !== false) { st.style.display = \"\"; }\n                this.data.languages.current_language = i;\n                this.__callback(i);\n                return true;\n            },\n            get_lang : function () {\n                return this.data.languages.current_language;\n            },\n            _get_string : function (key, lang) {\n                var langs = this._get_settings().languages,\n                    s = this._get_settings().core.strings;\n                if($.isArray(langs) && langs.length) {\n                    lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;\n                }\n                if(s[lang] && s[lang][key]) { return s[lang][key]; }\n                if(s[key]) { return s[key]; }\n                return key;\n            },\n            get_text : function (obj, lang) {\n                obj = this._get_node(obj) || this.data.ui.last_selected;\n                if(!obj.size()) { return false; }\n                var langs = this._get_settings().languages,\n                    s = this._get_settings().core.html_titles;\n                if($.isArray(langs) && langs.length) {\n                    lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;\n                    obj = obj.children(\"a.\" + lang);\n                }\n                else { obj = obj.children(\"a:eq(0)\"); }\n                if(s) {\n                    obj = obj.clone();\n                    obj.children(\"INS\").remove();\n                    return obj.html();\n                }\n                else {\n                    obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n                    return obj.nodeValue;\n                }\n            },\n            set_text : function (obj, val, lang) {\n                obj = this._get_node(obj) || this.data.ui.last_selected;\n                if(!obj.size()) { return false; }\n                var langs = this._get_settings().languages,\n                    s = this._get_settings().core.html_titles,\n                    tmp;\n                if($.isArray(langs) && langs.length) {\n                    lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;\n                    obj = obj.children(\"a.\" + lang);\n                }\n                else { obj = obj.children(\"a:eq(0)\"); }\n                if(s) {\n                    tmp = obj.children(\"INS\").clone();\n                    obj.html(val).prepend(tmp);\n                    this.__callback({ \"obj\" : obj, \"name\" : val, \"lang\" : lang });\n                    return true;\n                }\n                else {\n                    obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];\n                    this.__callback({ \"obj\" : obj, \"name\" : val, \"lang\" : lang });\n                    return (obj.nodeValue = val);\n                }\n            },\n            _load_css : function () {\n                var langs = this._get_settings().languages,\n                    str = \"/* languages css */\",\n                    selector = \".jstree-\" + this.get_index() + ' a',\n                    ln;\n                if($.isArray(langs) && langs.length) {\n                    this.data.languages.current_language = langs[0];\n                    for(ln = 0; ln < langs.length; ln++) {\n                        str += selector + \".\" + langs[ln] + \" {\";\n                        if(langs[ln] != this.data.languages.current_language) { str += \" display:none; \"; }\n                        str += \" } \";\n                    }\n                    this.data.languages.language_css = $.vakata.css.add_sheet({ 'str' : str, 'title' : \"jstree-languages\" });\n                }\n            },\n            create_node : function (obj, position, js, callback) {\n                var t = this.__call_old(true, obj, position, js, function (t) {\n                    var langs = this._get_settings().languages,\n                        a = t.children(\"a\"),\n                        ln;\n                    if($.isArray(langs) && langs.length) {\n                        for(ln = 0; ln < langs.length; ln++) {\n                            if(!a.is(\".\" + langs[ln])) {\n                                t.append(a.eq(0).clone().removeClass(langs.join(\" \")).addClass(langs[ln]));\n                            }\n                        }\n                        a.not(\".\" + langs.join(\", .\")).remove();\n                    }\n                    if(callback) { callback.call(this, t); }\n                });\n                return t;\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/*\n * jsTree cookies plugin\n * Stores the currently opened/selected nodes in a cookie and then restores them\n * Depends on the jquery.cookie plugin\n */\n(function ($) {\n    $.jstree.plugin(\"cookies\", {\n        __init : function () {\n            if(typeof $.cookie === \"undefined\") { throw \"jsTree cookie: jQuery cookie plugin not included.\"; }\n\n            var s = this._get_settings().cookies,\n                tmp;\n            if(!!s.save_loaded) {\n                tmp = $.cookie(s.save_loaded);\n                if(tmp && tmp.length) { this.data.core.to_load = tmp.split(\",\"); }\n            }\n            if(!!s.save_opened) {\n                tmp = $.cookie(s.save_opened);\n                if(tmp && tmp.length) { this.data.core.to_open = tmp.split(\",\"); }\n            }\n            if(!!s.save_selected) {\n                tmp = $.cookie(s.save_selected);\n                if(tmp && tmp.length && this.data.ui) { this.data.ui.to_select = tmp.split(\",\"); }\n            }\n            this.get_container()\n                .one( ( this.data.ui ? \"reselect\" : \"reopen\" ) + \".jstree\", $.proxy(function () {\n                    this.get_container()\n                        .bind(\"open_node.jstree close_node.jstree select_node.jstree deselect_node.jstree\", $.proxy(function (e) { \n                                if(this._get_settings().cookies.auto_save) { this.save_cookie((e.handleObj.namespace + e.handleObj.type).replace(\"jstree\",\"\")); }\n                            }, this));\n                }, this));\n        },\n        defaults : {\n            save_loaded     : \"jstree_load\",\n            save_opened     : \"jstree_open\",\n            save_selected   : \"jstree_select\",\n            auto_save       : true,\n            cookie_options  : {}\n        },\n        _fn : {\n            save_cookie : function (c) {\n                if(this.data.core.refreshing) { return; }\n                var s = this._get_settings().cookies;\n                if(!c) { // if called manually and not by event\n                    if(s.save_loaded) {\n                        this.save_loaded();\n                        $.cookie(s.save_loaded, this.data.core.to_load.join(\",\"), s.cookie_options);\n                    }\n                    if(s.save_opened) {\n                        this.save_opened();\n                        $.cookie(s.save_opened, this.data.core.to_open.join(\",\"), s.cookie_options);\n                    }\n                    if(s.save_selected && this.data.ui) {\n                        this.save_selected();\n                        $.cookie(s.save_selected, this.data.ui.to_select.join(\",\"), s.cookie_options);\n                    }\n                    return;\n                }\n                switch(c) {\n                    case \"open_node\":\n                    case \"close_node\":\n                        if(!!s.save_opened) { \n                            this.save_opened(); \n                            $.cookie(s.save_opened, this.data.core.to_open.join(\",\"), s.cookie_options); \n                        }\n                        if(!!s.save_loaded) { \n                            this.save_loaded(); \n                            $.cookie(s.save_loaded, this.data.core.to_load.join(\",\"), s.cookie_options); \n                        }\n                        break;\n                    case \"select_node\":\n                    case \"deselect_node\":\n                        if(!!s.save_selected && this.data.ui) { \n                            this.save_selected(); \n                            $.cookie(s.save_selected, this.data.ui.to_select.join(\",\"), s.cookie_options); \n                        }\n                        break;\n                }\n            }\n        }\n    });\n    // include cookies by default\n    // $.jstree.defaults.plugins.push(\"cookies\");\n})(jQuery);\n//*/\n\n/*\n * jsTree sort plugin\n * Sorts items alphabetically (or using any other function)\n */\n(function ($) {\n    $.jstree.plugin(\"sort\", {\n        __init : function () {\n            this.get_container()\n                .bind(\"load_node.jstree\", $.proxy(function (e, data) {\n                        var obj = this._get_node(data.rslt.obj);\n                        obj = obj === -1 ? this.get_container().children(\"ul\") : obj.children(\"ul\");\n                        this.sort(obj);\n                    }, this))\n                .bind(\"rename_node.jstree create_node.jstree create.jstree\", $.proxy(function (e, data) {\n                        this.sort(data.rslt.obj.parent());\n                    }, this))\n                .bind(\"move_node.jstree\", $.proxy(function (e, data) {\n                        var m = data.rslt.np == -1 ? this.get_container() : data.rslt.np;\n                        this.sort(m.children(\"ul\"));\n                    }, this));\n        },\n        defaults : function (a, b) { return this.get_text(a) > this.get_text(b) ? 1 : -1; },\n        _fn : {\n            sort : function (obj) {\n                var s = this._get_settings().sort,\n                    t = this;\n                obj.append($.makeArray(obj.children(\"li\")).sort($.proxy(s, t)));\n                obj.find(\"> li > ul\").each(function() { t.sort($(this)); });\n                this.clean_node(obj);\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/*\n * jsTree DND plugin\n * Drag and drop plugin for moving/copying nodes\n */\n(function ($) {\n    var o = false,\n        r = false,\n        m = false,\n        ml = false,\n        sli = false,\n        sti = false,\n        dir1 = false,\n        dir2 = false,\n        last_pos = false;\n    $.vakata.dnd = {\n        is_down : false,\n        is_drag : false,\n        helper : false,\n        scroll_spd : 10,\n        init_x : 0,\n        init_y : 0,\n        threshold : 5,\n        helper_left : 5,\n        helper_top : 10,\n        user_data : {},\n\n        drag_start : function (e, data, html) { \n            if($.vakata.dnd.is_drag) { $.vakata.drag_stop({}); }\n            try {\n                e.currentTarget.unselectable = \"on\";\n                e.currentTarget.onselectstart = function() { return false; };\n                if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = \"none\"; }\n            } catch(err) { }\n            $.vakata.dnd.init_x = e.pageX;\n            $.vakata.dnd.init_y = e.pageY;\n            $.vakata.dnd.user_data = data;\n            $.vakata.dnd.is_down = true;\n            $.vakata.dnd.helper = $(\"<div id='vakata-dragged' />\").html(html); //.fadeTo(10,0.25);\n            $(document).bind(\"mousemove\", $.vakata.dnd.drag);\n            $(document).bind(\"mouseup\", $.vakata.dnd.drag_stop);\n            return false;\n        },\n        drag : function (e) { \n            if(!$.vakata.dnd.is_down) { return; }\n            if(!$.vakata.dnd.is_drag) {\n                if(Math.abs(e.pageX - $.vakata.dnd.init_x) > 5 || Math.abs(e.pageY - $.vakata.dnd.init_y) > 5) { \n                    $.vakata.dnd.helper.appendTo(\"body\");\n                    $.vakata.dnd.is_drag = true;\n                    $(document).triggerHandler(\"drag_start.vakata\", { \"event\" : e, \"data\" : $.vakata.dnd.user_data });\n                }\n                else { return; }\n            }\n\n            // maybe use a scrolling parent element instead of document?\n            if(e.type === \"mousemove\") { // thought of adding scroll in order to move the helper, but mouse poisition is n/a\n                var d = $(document), t = d.scrollTop(), l = d.scrollLeft();\n                if(e.pageY - t < 20) { \n                    if(sti && dir1 === \"down\") { clearInterval(sti); sti = false; }\n                    if(!sti) { dir1 = \"up\"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() - $.vakata.dnd.scroll_spd); }, 150); }\n                }\n                else { \n                    if(sti && dir1 === \"up\") { clearInterval(sti); sti = false; }\n                }\n                if($(window).height() - (e.pageY - t) < 20) {\n                    if(sti && dir1 === \"up\") { clearInterval(sti); sti = false; }\n                    if(!sti) { dir1 = \"down\"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() + $.vakata.dnd.scroll_spd); }, 150); }\n                }\n                else { \n                    if(sti && dir1 === \"down\") { clearInterval(sti); sti = false; }\n                }\n\n                if(e.pageX - l < 20) {\n                    if(sli && dir2 === \"right\") { clearInterval(sli); sli = false; }\n                    if(!sli) { dir2 = \"left\"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() - $.vakata.dnd.scroll_spd); }, 150); }\n                }\n                else { \n                    if(sli && dir2 === \"left\") { clearInterval(sli); sli = false; }\n                }\n                if($(window).width() - (e.pageX - l) < 20) {\n                    if(sli && dir2 === \"left\") { clearInterval(sli); sli = false; }\n                    if(!sli) { dir2 = \"right\"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() + $.vakata.dnd.scroll_spd); }, 150); }\n                }\n                else { \n                    if(sli && dir2 === \"right\") { clearInterval(sli); sli = false; }\n                }\n            }\n\n            $.vakata.dnd.helper.css({ left : (e.pageX + $.vakata.dnd.helper_left) + \"px\", top : (e.pageY + $.vakata.dnd.helper_top) + \"px\" });\n            $(document).triggerHandler(\"drag.vakata\", { \"event\" : e, \"data\" : $.vakata.dnd.user_data });\n        },\n        drag_stop : function (e) {\n            if(sli) { clearInterval(sli); }\n            if(sti) { clearInterval(sti); }\n            $(document).unbind(\"mousemove\", $.vakata.dnd.drag);\n            $(document).unbind(\"mouseup\", $.vakata.dnd.drag_stop);\n            $(document).triggerHandler(\"drag_stop.vakata\", { \"event\" : e, \"data\" : $.vakata.dnd.user_data });\n            $.vakata.dnd.helper.remove();\n            $.vakata.dnd.init_x = 0;\n            $.vakata.dnd.init_y = 0;\n            $.vakata.dnd.user_data = {};\n            $.vakata.dnd.is_down = false;\n            $.vakata.dnd.is_drag = false;\n        }\n    };\n    $(function() {\n        var css_string = '#vakata-dragged { display:block; margin:0 0 0 0; padding:4px 4px 4px 24px; position:absolute; top:-2000px; line-height:16px; z-index:10000; } ';\n        $.vakata.css.add_sheet({ str : css_string, title : \"vakata\" });\n    });\n\n    $.jstree.plugin(\"dnd\", {\n        __init : function () {\n            this.data.dnd = {\n                active : false,\n                after : false,\n                inside : false,\n                before : false,\n                off : false,\n                prepared : false,\n                w : 0,\n                to1 : false,\n                to2 : false,\n                cof : false,\n                cw : false,\n                ch : false,\n                i1 : false,\n                i2 : false,\n                mto : false\n            };\n            this.get_container()\n                .bind(\"mouseenter.jstree\", $.proxy(function (e) {\n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            if(this.data.themes) {\n                                m.attr(\"class\", \"jstree-\" + this.data.themes.theme); \n                                if(ml) { ml.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n                                $.vakata.dnd.helper.attr(\"class\", \"jstree-dnd-helper jstree-\" + this.data.themes.theme);\n                            }\n                            //if($(e.currentTarget).find(\"> ul > li\").length === 0) {\n                            if(e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(\".jstree:eq(0)\")[0] !== e.target) { // node should not be from the same tree\n                                var tr = $.jstree._reference(e.target), dc;\n                                if(tr.data.dnd.foreign) {\n                                    dc = tr._get_settings().dnd.drag_check.call(this, { \"o\" : o, \"r\" : tr.get_container(), is_root : true });\n                                    if(dc === true || dc.inside === true || dc.before === true || dc.after === true) {\n                                        $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n                                    }\n                                }\n                                else {\n                                    tr.prepare_move(o, tr.get_container(), \"last\");\n                                    if(tr.check_move()) {\n                                        $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n                                    }\n                                }\n                            }\n                        }\n                    }, this))\n                .bind(\"mouseup.jstree\", $.proxy(function (e) {\n                        //if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && $(e.currentTarget).find(\"> ul > li\").length === 0) {\n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(\".jstree:eq(0)\")[0] !== e.target) { // node should not be from the same tree\n                            var tr = $.jstree._reference(e.currentTarget), dc;\n                            if(tr.data.dnd.foreign) {\n                                dc = tr._get_settings().dnd.drag_check.call(this, { \"o\" : o, \"r\" : tr.get_container(), is_root : true });\n                                if(dc === true || dc.inside === true || dc.before === true || dc.after === true) {\n                                    tr._get_settings().dnd.drag_finish.call(this, { \"o\" : o, \"r\" : tr.get_container(), is_root : true });\n                                }\n                            }\n                            else {\n                                tr.move_node(o, tr.get_container(), \"last\", e[tr._get_settings().dnd.copy_modifier + \"Key\"]);\n                            }\n                        }\n                    }, this))\n                .bind(\"mouseleave.jstree\", $.proxy(function (e) {\n                        if(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === \"jstree-marker-line\") {\n                            return false; \n                        }\n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n                            if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n                            if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }\n                            if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }\n                            if($.vakata.dnd.helper.children(\"ins\").hasClass(\"jstree-ok\")) {\n                                $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n                            }\n                        }\n                    }, this))\n                .bind(\"mousemove.jstree\", $.proxy(function (e) {\n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            var cnt = this.get_container()[0];\n\n                            // Horizontal scroll\n                            if(e.pageX + 24 > this.data.dnd.cof.left + this.data.dnd.cw) {\n                                if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n                                this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft += $.vakata.dnd.scroll_spd; }, cnt), 100);\n                            }\n                            else if(e.pageX - 24 < this.data.dnd.cof.left) {\n                                if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n                                this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft -= $.vakata.dnd.scroll_spd; }, cnt), 100);\n                            }\n                            else {\n                                if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n                            }\n\n                            // Vertical scroll\n                            if(e.pageY + 24 > this.data.dnd.cof.top + this.data.dnd.ch) {\n                                if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n                                this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop += $.vakata.dnd.scroll_spd; }, cnt), 100);\n                            }\n                            else if(e.pageY - 24 < this.data.dnd.cof.top) {\n                                if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n                                this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop -= $.vakata.dnd.scroll_spd; }, cnt), 100);\n                            }\n                            else {\n                                if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n                            }\n\n                        }\n                    }, this))\n                .bind(\"scroll.jstree\", $.proxy(function (e) { \n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && m && ml) {\n                            m.hide();\n                            ml.hide();\n                        }\n                    }, this))\n                .delegate(\"a\", \"mousedown.jstree\", $.proxy(function (e) { \n                        if(e.which === 1) {\n                            this.start_drag(e.currentTarget, e);\n                            return false;\n                        }\n                    }, this))\n                .delegate(\"a\", \"mouseenter.jstree\", $.proxy(function (e) { \n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            this.dnd_enter(e.currentTarget);\n                        }\n                    }, this))\n                .delegate(\"a\", \"mousemove.jstree\", $.proxy(function (e) { \n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            if(!r || !r.length || r.children(\"a\")[0] !== e.currentTarget) {\n                                this.dnd_enter(e.currentTarget);\n                            }\n                            if(typeof this.data.dnd.off.top === \"undefined\") { this.data.dnd.off = $(e.target).offset(); }\n                            this.data.dnd.w = (e.pageY - (this.data.dnd.off.top || 0)) % this.data.core.li_height;\n                            if(this.data.dnd.w < 0) { this.data.dnd.w += this.data.core.li_height; }\n                            this.dnd_show();\n                        }\n                    }, this))\n                .delegate(\"a\", \"mouseleave.jstree\", $.proxy(function (e) { \n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            if(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === \"jstree-marker-line\") {\n                                return false; \n                            }\n                                if(m) { m.hide(); }\n                                if(ml) { ml.hide(); }\n                            /*\n                            var ec = $(e.currentTarget).closest(\"li\"), \n                                er = $(e.relatedTarget).closest(\"li\");\n                            if(er[0] !== ec.prev()[0] && er[0] !== ec.next()[0]) {\n                                if(m) { m.hide(); }\n                                if(ml) { ml.hide(); }\n                            }\n                            */\n                            this.data.dnd.mto = setTimeout( \n                                (function (t) { return function () { t.dnd_leave(e); }; })(this),\n                            0);\n                        }\n                    }, this))\n                .delegate(\"a\", \"mouseup.jstree\", $.proxy(function (e) { \n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {\n                            this.dnd_finish(e);\n                        }\n                    }, this));\n\n            $(document)\n                .bind(\"drag_stop.vakata\", $.proxy(function () {\n                        if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }\n                        if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }\n                        if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }\n                        if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }\n                        this.data.dnd.after     = false;\n                        this.data.dnd.before    = false;\n                        this.data.dnd.inside    = false;\n                        this.data.dnd.off       = false;\n                        this.data.dnd.prepared  = false;\n                        this.data.dnd.w         = false;\n                        this.data.dnd.to1       = false;\n                        this.data.dnd.to2       = false;\n                        this.data.dnd.i1        = false;\n                        this.data.dnd.i2        = false;\n                        this.data.dnd.active    = false;\n                        this.data.dnd.foreign   = false;\n                        if(m) { m.css({ \"top\" : \"-2000px\" }); }\n                        if(ml) { ml.css({ \"top\" : \"-2000px\" }); }\n                    }, this))\n                .bind(\"drag_start.vakata\", $.proxy(function (e, data) {\n                        if(data.data.jstree) { \n                            var et = $(data.event.target);\n                            if(et.closest(\".jstree\").hasClass(\"jstree-\" + this.get_index())) {\n                                this.dnd_enter(et);\n                            }\n                        }\n                    }, this));\n                /*\n                .bind(\"keydown.jstree-\" + this.get_index() + \" keyup.jstree-\" + this.get_index(), $.proxy(function(e) {\n                        if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && !this.data.dnd.foreign) {\n                            var h = $.vakata.dnd.helper.children(\"ins\");\n                            if(e[this._get_settings().dnd.copy_modifier + \"Key\"] && h.hasClass(\"jstree-ok\")) {\n                                h.parent().html(h.parent().html().replace(/ \\(Copy\\)$/, \"\") + \" (Copy)\");\n                            } \n                            else {\n                                h.parent().html(h.parent().html().replace(/ \\(Copy\\)$/, \"\"));\n                            }\n                        }\n                    }, this)); */\n\n\n\n            var s = this._get_settings().dnd;\n            if(s.drag_target) {\n                $(document)\n                    .delegate(s.drag_target, \"mousedown.jstree-\" + this.get_index(), $.proxy(function (e) {\n                        o = e.target;\n                        $.vakata.dnd.drag_start(e, { jstree : true, obj : e.target }, \"<ins class='jstree-icon'></ins>\" + $(e.target).text() );\n                        if(this.data.themes) { \n                            if(m) { m.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n                            if(ml) { ml.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n                            $.vakata.dnd.helper.attr(\"class\", \"jstree-dnd-helper jstree-\" + this.data.themes.theme); \n                        }\n                        $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n                        var cnt = this.get_container();\n                        this.data.dnd.cof = cnt.offset();\n                        this.data.dnd.cw = parseInt(cnt.width(),10);\n                        this.data.dnd.ch = parseInt(cnt.height(),10);\n                        this.data.dnd.foreign = true;\n                        e.preventDefault();\n                    }, this));\n            }\n            if(s.drop_target) {\n                $(document)\n                    .delegate(s.drop_target, \"mouseenter.jstree-\" + this.get_index(), $.proxy(function (e) {\n                            if(this.data.dnd.active && this._get_settings().dnd.drop_check.call(this, { \"o\" : o, \"r\" : $(e.target), \"e\" : e })) {\n                                $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n                            }\n                        }, this))\n                    .delegate(s.drop_target, \"mouseleave.jstree-\" + this.get_index(), $.proxy(function (e) {\n                            if(this.data.dnd.active) {\n                                $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n                            }\n                        }, this))\n                    .delegate(s.drop_target, \"mouseup.jstree-\" + this.get_index(), $.proxy(function (e) {\n                            if(this.data.dnd.active && $.vakata.dnd.helper.children(\"ins\").hasClass(\"jstree-ok\")) {\n                                this._get_settings().dnd.drop_finish.call(this, { \"o\" : o, \"r\" : $(e.target), \"e\" : e });\n                            }\n                        }, this));\n            }\n        },\n        defaults : {\n            copy_modifier   : \"ctrl\",\n            check_timeout   : 100,\n            open_timeout    : 500,\n            drop_target     : \".jstree-drop\",\n            drop_check      : function (data) { return true; },\n            drop_finish     : $.noop,\n            drag_target     : \".jstree-draggable\",\n            drag_finish     : $.noop,\n            drag_check      : function (data) { return { after : false, before : false, inside : true }; }\n        },\n        _fn : {\n            dnd_prepare : function () {\n                if(!r || !r.length) { return; }\n                this.data.dnd.off = r.offset();\n                if(this._get_settings().core.rtl) {\n                    this.data.dnd.off.right = this.data.dnd.off.left + r.width();\n                }\n                if(this.data.dnd.foreign) {\n                    var a = this._get_settings().dnd.drag_check.call(this, { \"o\" : o, \"r\" : r });\n                    this.data.dnd.after = a.after;\n                    this.data.dnd.before = a.before;\n                    this.data.dnd.inside = a.inside;\n                    this.data.dnd.prepared = true;\n                    return this.dnd_show();\n                }\n                this.prepare_move(o, r, \"before\");\n                this.data.dnd.before = this.check_move();\n                this.prepare_move(o, r, \"after\");\n                this.data.dnd.after = this.check_move();\n                if(this._is_loaded(r)) {\n                    this.prepare_move(o, r, \"inside\");\n                    this.data.dnd.inside = this.check_move();\n                }\n                else {\n                    this.data.dnd.inside = false;\n                }\n                this.data.dnd.prepared = true;\n                return this.dnd_show();\n            },\n            dnd_show : function () {\n                if(!this.data.dnd.prepared) { return; }\n                var o = [\"before\",\"inside\",\"after\"],\n                    r = false,\n                    rtl = this._get_settings().core.rtl,\n                    pos;\n                if(this.data.dnd.w < this.data.core.li_height/3) { o = [\"before\",\"inside\",\"after\"]; }\n                else if(this.data.dnd.w <= this.data.core.li_height*2/3) {\n                    o = this.data.dnd.w < this.data.core.li_height/2 ? [\"inside\",\"before\",\"after\"] : [\"inside\",\"after\",\"before\"];\n                }\n                else { o = [\"after\",\"inside\",\"before\"]; }\n                $.each(o, $.proxy(function (i, val) { \n                    if(this.data.dnd[val]) {\n                        $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-ok\");\n                        r = val;\n                        return false;\n                    }\n                }, this));\n                if(r === false) { $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\"); }\n                \n                pos = rtl ? (this.data.dnd.off.right - 18) : (this.data.dnd.off.left + 10);\n                switch(r) {\n                    case \"before\":\n                        m.css({ \"left\" : pos + \"px\", \"top\" : (this.data.dnd.off.top - 6) + \"px\" }).show();\n                        if(ml) { ml.css({ \"left\" : (pos + 8) + \"px\", \"top\" : (this.data.dnd.off.top - 1) + \"px\" }).show(); }\n                        break;\n                    case \"after\":\n                        m.css({ \"left\" : pos + \"px\", \"top\" : (this.data.dnd.off.top + this.data.core.li_height - 6) + \"px\" }).show();\n                        if(ml) { ml.css({ \"left\" : (pos + 8) + \"px\", \"top\" : (this.data.dnd.off.top + this.data.core.li_height - 1) + \"px\" }).show(); }\n                        break;\n                    case \"inside\":\n                        m.css({ \"left\" : pos + ( rtl ? -4 : 4) + \"px\", \"top\" : (this.data.dnd.off.top + this.data.core.li_height/2 - 5) + \"px\" }).show();\n                        if(ml) { ml.hide(); }\n                        break;\n                    default:\n                        m.hide();\n                        if(ml) { ml.hide(); }\n                        break;\n                }\n                last_pos = r;\n                return r;\n            },\n            dnd_open : function () {\n                this.data.dnd.to2 = false;\n                this.open_node(r, $.proxy(this.dnd_prepare,this), true);\n            },\n            dnd_finish : function (e) {\n                if(this.data.dnd.foreign) {\n                    if(this.data.dnd.after || this.data.dnd.before || this.data.dnd.inside) {\n                        this._get_settings().dnd.drag_finish.call(this, { \"o\" : o, \"r\" : r, \"p\" : last_pos });\n                    }\n                }\n                else {\n                    this.dnd_prepare();\n                    this.move_node(o, r, last_pos, e[this._get_settings().dnd.copy_modifier + \"Key\"]);\n                }\n                o = false;\n                r = false;\n                m.hide();\n                if(ml) { ml.hide(); }\n            },\n            dnd_enter : function (obj) {\n                if(this.data.dnd.mto) { \n                    clearTimeout(this.data.dnd.mto);\n                    this.data.dnd.mto = false;\n                }\n                var s = this._get_settings().dnd;\n                this.data.dnd.prepared = false;\n                r = this._get_node(obj);\n                if(s.check_timeout) { \n                    // do the calculations after a minimal timeout (users tend to drag quickly to the desired location)\n                    if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }\n                    this.data.dnd.to1 = setTimeout($.proxy(this.dnd_prepare, this), s.check_timeout); \n                }\n                else { \n                    this.dnd_prepare(); \n                }\n                if(s.open_timeout) { \n                    if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }\n                    if(r && r.length && r.hasClass(\"jstree-closed\")) { \n                        // if the node is closed - open it, then recalculate\n                        this.data.dnd.to2 = setTimeout($.proxy(this.dnd_open, this), s.open_timeout);\n                    }\n                }\n                else {\n                    if(r && r.length && r.hasClass(\"jstree-closed\")) { \n                        this.dnd_open();\n                    }\n                }\n            },\n            dnd_leave : function (e) {\n                this.data.dnd.after     = false;\n                this.data.dnd.before    = false;\n                this.data.dnd.inside    = false;\n                $.vakata.dnd.helper.children(\"ins\").attr(\"class\",\"jstree-invalid\");\n                m.hide();\n                if(ml) { ml.hide(); }\n                if(r && r[0] === e.target.parentNode) {\n                    if(this.data.dnd.to1) {\n                        clearTimeout(this.data.dnd.to1);\n                        this.data.dnd.to1 = false;\n                    }\n                    if(this.data.dnd.to2) {\n                        clearTimeout(this.data.dnd.to2);\n                        this.data.dnd.to2 = false;\n                    }\n                }\n            },\n            start_drag : function (obj, e) {\n                o = this._get_node(obj);\n                if(this.data.ui && this.is_selected(o)) { o = this._get_node(null, true); }\n                var dt = o.length > 1 ? this._get_string(\"multiple_selection\") : this.get_text(o),\n                    cnt = this.get_container();\n                if(!this._get_settings().core.html_titles) { dt = dt.replace(/</ig,\"&lt;\").replace(/>/ig,\"&gt;\"); }\n                $.vakata.dnd.drag_start(e, { jstree : true, obj : o }, \"<ins class='jstree-icon'></ins>\" + dt );\n                if(this.data.themes) { \n                    if(m) { m.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n                    if(ml) { ml.attr(\"class\", \"jstree-\" + this.data.themes.theme); }\n                    $.vakata.dnd.helper.attr(\"class\", \"jstree-dnd-helper jstree-\" + this.data.themes.theme); \n                }\n                this.data.dnd.cof = cnt.offset();\n                this.data.dnd.cw = parseInt(cnt.width(),10);\n                this.data.dnd.ch = parseInt(cnt.height(),10);\n                this.data.dnd.active = true;\n            }\n        }\n    });\n    $(function() {\n        var css_string = '' + \n            '#vakata-dragged ins { display:block; text-decoration:none; width:16px; height:16px; margin:0 0 0 0; padding:0; position:absolute; top:4px; left:4px; ' + \n            ' -moz-border-radius:4px; border-radius:4px; -webkit-border-radius:4px; ' +\n            '} ' + \n            '#vakata-dragged .jstree-ok { background:green; } ' + \n            '#vakata-dragged .jstree-invalid { background:red; } ' + \n            '#jstree-marker { padding:0; margin:0; font-size:12px; overflow:hidden; height:12px; width:8px; position:absolute; top:-30px; z-index:10001; background-repeat:no-repeat; display:none; background-color:transparent; text-shadow:1px 1px 1px white; color:black; line-height:10px; } ' + \n            '#jstree-marker-line { padding:0; margin:0; line-height:0%; font-size:1px; overflow:hidden; height:1px; width:100px; position:absolute; top:-30px; z-index:10000; background-repeat:no-repeat; display:none; background-color:#456c43; ' + \n            ' cursor:pointer; border:1px solid #eeeeee; border-left:0; -moz-box-shadow: 0px 0px 2px #666; -webkit-box-shadow: 0px 0px 2px #666; box-shadow: 0px 0px 2px #666; ' + \n            ' -moz-border-radius:1px; border-radius:1px; -webkit-border-radius:1px; ' +\n            '}' + \n            '';\n        $.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n        m = $(\"<div />\").attr({ id : \"jstree-marker\" }).hide().html(\"&raquo;\")\n            .bind(\"mouseleave mouseenter\", function (e) { \n                m.hide();\n                ml.hide();\n                e.preventDefault(); \n                e.stopImmediatePropagation(); \n                return false; \n            })\n            .appendTo(\"body\");\n        ml = $(\"<div />\").attr({ id : \"jstree-marker-line\" }).hide()\n            .bind(\"mouseup\", function (e) { \n                if(r && r.length) { \n                    r.children(\"a\").trigger(e); \n                    e.preventDefault(); \n                    e.stopImmediatePropagation(); \n                    return false; \n                } \n            })\n            .bind(\"mouseleave\", function (e) { \n                var rt = $(e.relatedTarget);\n                if(rt.is(\".jstree\") || rt.closest(\".jstree\").length === 0) {\n                    if(r && r.length) { \n                        r.children(\"a\").trigger(e); \n                        m.hide();\n                        ml.hide();\n                        e.preventDefault(); \n                        e.stopImmediatePropagation(); \n                        return false; \n                    }\n                }\n            })\n            .appendTo(\"body\");\n        $(document).bind(\"drag_start.vakata\", function (e, data) {\n            if(data.data.jstree) { m.show(); if(ml) { ml.show(); } }\n        });\n        $(document).bind(\"drag_stop.vakata\", function (e, data) {\n            if(data.data.jstree) { m.hide(); if(ml) { ml.hide(); } }\n        });\n    });\n})(jQuery);\n//*/\n\n/*\n * jsTree checkbox plugin\n * Inserts checkboxes in front of every node\n * Depends on the ui plugin\n * DOES NOT WORK NICELY WITH MULTITREE DRAG'N'DROP\n */\n(function ($) {\n    $.jstree.plugin(\"checkbox\", {\n        __init : function () {\n            this.data.checkbox.noui = this._get_settings().checkbox.override_ui;\n            if(this.data.ui && this.data.checkbox.noui) {\n                this.select_node = this.deselect_node = this.deselect_all = $.noop;\n                this.get_selected = this.get_checked;\n            }\n\n            this.get_container()\n                .bind(\"open_node.jstree create_node.jstree clean_node.jstree refresh.jstree\", $.proxy(function (e, data) { \n                        this._prepare_checkboxes(data.rslt.obj);\n                    }, this))\n                .bind(\"loaded.jstree\", $.proxy(function (e) {\n                        this._prepare_checkboxes();\n                    }, this))\n                .delegate( (this.data.ui && this.data.checkbox.noui ? \"a\" : \"ins.jstree-checkbox\") , \"click.jstree\", $.proxy(function (e) {\n                        e.preventDefault();\n                        if(this._get_node(e.target).hasClass(\"jstree-checked\")) { this.uncheck_node(e.target); }\n                        else { this.check_node(e.target); }\n                        if(this.data.ui && this.data.checkbox.noui) {\n                            this.save_selected();\n                            if(this.data.cookies) { this.save_cookie(\"select_node\"); }\n                        }\n                        else {\n                            e.stopImmediatePropagation();\n                            return false;\n                        }\n                    }, this));\n        },\n        defaults : {\n            override_ui : false,\n            two_state : false,\n            real_checkboxes : false,\n            checked_parent_open : true,\n            real_checkboxes_names : function (n) { return [ (\"check_\" + (n[0].id || Math.ceil(Math.random() * 10000))) , 1]; }\n        },\n        __destroy : function () {\n            this.get_container()\n                .find(\"input.jstree-real-checkbox\").removeClass(\"jstree-real-checkbox\").end()\n                .find(\"ins.jstree-checkbox\").remove();\n        },\n        _fn : {\n            _checkbox_notify : function (n, data) {\n                if(data.checked) {\n                    this.check_node(n, false);\n                }\n            },\n            _prepare_checkboxes : function (obj) {\n                obj = !obj || obj == -1 ? this.get_container().find(\"> ul > li\") : this._get_node(obj);\n                if(obj === false) { return; } // added for removing root nodes\n                var c, _this = this, t, ts = this._get_settings().checkbox.two_state, rc = this._get_settings().checkbox.real_checkboxes, rcn = this._get_settings().checkbox.real_checkboxes_names;\n                obj.each(function () {\n                    t = $(this);\n                    c = t.is(\"li\") && (t.hasClass(\"jstree-checked\") || (rc && t.children(\":checked\").length)) ? \"jstree-checked\" : \"jstree-unchecked\";\n                    t.find(\"li\").andSelf().each(function () {\n                        var $t = $(this), nm;\n                        $t.children(\"a\" + (_this.data.languages ? \"\" : \":eq(0)\") ).not(\":has(.jstree-checkbox)\").prepend(\"<ins class='jstree-checkbox'>&#160;</ins>\").parent().not(\".jstree-checked, .jstree-unchecked\").addClass( ts ? \"jstree-unchecked\" : c );\n                        if(rc) {\n                            if(!$t.children(\":checkbox\").length) {\n                                nm = rcn.call(_this, $t);\n                                $t.prepend(\"<input type='checkbox' class='jstree-real-checkbox' id='\" + nm[0] + \"' name='\" + nm[0] + \"' value='\" + nm[1] + \"' />\");\n                            }\n                            else {\n                                $t.children(\":checkbox\").addClass(\"jstree-real-checkbox\");\n                            }\n                        }\n                        if(!ts) {\n                            if(c === \"jstree-checked\" || $t.hasClass(\"jstree-checked\") || $t.children(':checked').length) {\n                                $t.find(\"li\").andSelf().addClass(\"jstree-checked\").children(\":checkbox\").prop(\"checked\", true);\n                            }\n                        }\n                        else {\n                            if($t.hasClass(\"jstree-checked\") || $t.children(':checked').length) {\n                                $t.addClass(\"jstree-checked\").children(\":checkbox\").prop(\"checked\", true);\n                            }\n                        }\n                    });\n                });\n                if(!ts) {\n                    obj.find(\".jstree-checked\").parent().parent().each(function () { _this._repair_state(this); }); \n                }\n            },\n            change_state : function (obj, state) {\n                obj = this._get_node(obj);\n                var coll = false, rc = this._get_settings().checkbox.real_checkboxes;\n                if(!obj || obj === -1) { return false; }\n                state = (state === false || state === true) ? state : obj.hasClass(\"jstree-checked\");\n                if(this._get_settings().checkbox.two_state) {\n                    if(state) { \n                        obj.removeClass(\"jstree-checked\").addClass(\"jstree-unchecked\"); \n                        if(rc) { obj.children(\":checkbox\").prop(\"checked\", false); }\n                    }\n                    else { \n                        obj.removeClass(\"jstree-unchecked\").addClass(\"jstree-checked\"); \n                        if(rc) { obj.children(\":checkbox\").prop(\"checked\", true); }\n                    }\n                }\n                else {\n                    if(state) { \n                        coll = obj.find(\"li\").andSelf();\n                        if(!coll.filter(\".jstree-checked, .jstree-undetermined\").length) { return false; }\n                        coll.removeClass(\"jstree-checked jstree-undetermined\").addClass(\"jstree-unchecked\"); \n                        if(rc) { coll.children(\":checkbox\").prop(\"checked\", false); }\n                    }\n                    else { \n                        coll = obj.find(\"li\").andSelf();\n                        if(!coll.filter(\".jstree-unchecked, .jstree-undetermined\").length) { return false; }\n                        coll.removeClass(\"jstree-unchecked jstree-undetermined\").addClass(\"jstree-checked\"); \n                        if(rc) { coll.children(\":checkbox\").prop(\"checked\", true); }\n                        if(this.data.ui) { this.data.ui.last_selected = obj; }\n                        this.data.checkbox.last_selected = obj;\n                    }\n                    obj.parentsUntil(\".jstree\", \"li\").each(function () {\n                        var $this = $(this);\n                        if(state) {\n                            if($this.children(\"ul\").children(\"li.jstree-checked, li.jstree-undetermined\").length) {\n                                $this.parentsUntil(\".jstree\", \"li\").andSelf().removeClass(\"jstree-checked jstree-unchecked\").addClass(\"jstree-undetermined\");\n                                if(rc) { $this.parentsUntil(\".jstree\", \"li\").andSelf().children(\":checkbox\").prop(\"checked\", false); }\n                                return false;\n                            }\n                            else {\n                                $this.removeClass(\"jstree-checked jstree-undetermined\").addClass(\"jstree-unchecked\");\n                                if(rc) { $this.children(\":checkbox\").prop(\"checked\", false); }\n                            }\n                        }\n                        else {\n                            if($this.children(\"ul\").children(\"li.jstree-unchecked, li.jstree-undetermined\").length) {\n                                $this.parentsUntil(\".jstree\", \"li\").andSelf().removeClass(\"jstree-checked jstree-unchecked\").addClass(\"jstree-undetermined\");\n                                if(rc) { $this.parentsUntil(\".jstree\", \"li\").andSelf().children(\":checkbox\").prop(\"checked\", false); }\n                                return false;\n                            }\n                            else {\n                                $this.removeClass(\"jstree-unchecked jstree-undetermined\").addClass(\"jstree-checked\");\n                                if(rc) { $this.children(\":checkbox\").prop(\"checked\", true); }\n                            }\n                        }\n                    });\n                }\n                if(this.data.ui && this.data.checkbox.noui) { this.data.ui.selected = this.get_checked(); }\n                this.__callback(obj);\n                return true;\n            },\n            check_node : function (obj) {\n                if(this.change_state(obj, false)) { \n                    obj = this._get_node(obj);\n                    if(this._get_settings().checkbox.checked_parent_open) {\n                        var t = this;\n                        obj.parents(\".jstree-closed\").each(function () { t.open_node(this, false, true); });\n                    }\n                    this.__callback({ \"obj\" : obj }); \n                }\n            },\n            uncheck_node : function (obj) {\n                if(this.change_state(obj, true)) { this.__callback({ \"obj\" : this._get_node(obj) }); }\n            },\n            check_all : function () {\n                var _this = this, \n                    coll = this._get_settings().checkbox.two_state ? this.get_container_ul().find(\"li\") : this.get_container_ul().children(\"li\");\n                coll.each(function () {\n                    _this.change_state(this, false);\n                });\n                this.__callback();\n            },\n            uncheck_all : function () {\n                var _this = this,\n                    coll = this._get_settings().checkbox.two_state ? this.get_container_ul().find(\"li\") : this.get_container_ul().children(\"li\");\n                coll.each(function () {\n                    _this.change_state(this, true);\n                });\n                this.__callback();\n            },\n\n            is_checked : function(obj) {\n                obj = this._get_node(obj);\n                return obj.length ? obj.is(\".jstree-checked\") : false;\n            },\n            get_checked : function (obj, get_all) {\n                obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);\n                return get_all || this._get_settings().checkbox.two_state ? obj.find(\".jstree-checked\") : obj.find(\"> ul > .jstree-checked, .jstree-undetermined > ul > .jstree-checked\");\n            },\n            get_unchecked : function (obj, get_all) { \n                obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);\n                return get_all || this._get_settings().checkbox.two_state ? obj.find(\".jstree-unchecked\") : obj.find(\"> ul > .jstree-unchecked, .jstree-undetermined > ul > .jstree-unchecked\");\n            },\n\n            show_checkboxes : function () { this.get_container().children(\"ul\").removeClass(\"jstree-no-checkboxes\"); },\n            hide_checkboxes : function () { this.get_container().children(\"ul\").addClass(\"jstree-no-checkboxes\"); },\n\n            _repair_state : function (obj) {\n                obj = this._get_node(obj);\n                if(!obj.length) { return; }\n                if(this._get_settings().checkbox.two_state) {\n                    obj.find('li').andSelf().not('.jstree-checked').removeClass('jstree-undetermined').addClass('jstree-unchecked').children(':checkbox').prop('checked', true);\n                    return;\n                }\n                var rc = this._get_settings().checkbox.real_checkboxes,\n                    a = obj.find(\"> ul > .jstree-checked\").length,\n                    b = obj.find(\"> ul > .jstree-undetermined\").length,\n                    c = obj.find(\"> ul > li\").length;\n                if(c === 0) { if(obj.hasClass(\"jstree-undetermined\")) { this.change_state(obj, false); } }\n                else if(a === 0 && b === 0) { this.change_state(obj, true); }\n                else if(a === c) { this.change_state(obj, false); }\n                else { \n                    obj.parentsUntil(\".jstree\",\"li\").andSelf().removeClass(\"jstree-checked jstree-unchecked\").addClass(\"jstree-undetermined\");\n                    if(rc) { obj.parentsUntil(\".jstree\", \"li\").andSelf().children(\":checkbox\").prop(\"checked\", false); }\n                }\n            },\n            reselect : function () {\n                if(this.data.ui && this.data.checkbox.noui) { \n                    var _this = this,\n                        s = this.data.ui.to_select;\n                    s = $.map($.makeArray(s), function (n) { return \"#\" + n.toString().replace(/^#/,\"\").replace(/\\\\\\//g,\"/\").replace(/\\//g,\"\\\\\\/\").replace(/\\\\\\./g,\".\").replace(/\\./g,\"\\\\.\").replace(/\\:/g,\"\\\\:\"); });\n                    this.deselect_all();\n                    $.each(s, function (i, val) { _this.check_node(val); });\n                    this.__callback();\n                }\n                else { \n                    this.__call_old(); \n                }\n            },\n            save_loaded : function () {\n                var _this = this;\n                this.data.core.to_load = [];\n                this.get_container_ul().find(\"li.jstree-closed.jstree-undetermined\").each(function () {\n                    if(this.id) { _this.data.core.to_load.push(\"#\" + this.id); }\n                });\n            }\n        }\n    });\n    $(function() {\n        var css_string = '.jstree .jstree-real-checkbox { display:none; } ';\n        $.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree XML plugin\n * The XML data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.\n */\n(function ($) {\n    $.vakata.xslt = function (xml, xsl, callback) {\n        var rs = \"\", xm, xs, processor, support;\n        // TODO: IE9 no XSLTProcessor, no document.recalc\n        if(document.recalc) {\n            xm = document.createElement('xml');\n            xs = document.createElement('xml');\n            xm.innerHTML = xml;\n            xs.innerHTML = xsl;\n            $(\"body\").append(xm).append(xs);\n            setTimeout( (function (xm, xs, callback) {\n                return function () {\n                    callback.call(null, xm.transformNode(xs.XMLDocument));\n                    setTimeout( (function (xm, xs) { return function () { $(xm).remove(); $(xs).remove(); }; })(xm, xs), 200);\n                };\n            })(xm, xs, callback), 100);\n            return true;\n        }\n        if(typeof window.DOMParser !== \"undefined\" && typeof window.XMLHttpRequest !== \"undefined\" && typeof window.XSLTProcessor === \"undefined\") {\n            xml = new DOMParser().parseFromString(xml, \"text/xml\");\n            xsl = new DOMParser().parseFromString(xsl, \"text/xml\");\n            // alert(xml.transformNode());\n            // callback.call(null, new XMLSerializer().serializeToString(rs));\n            \n        }\n        if(typeof window.DOMParser !== \"undefined\" && typeof window.XMLHttpRequest !== \"undefined\" && typeof window.XSLTProcessor !== \"undefined\") {\n            processor = new XSLTProcessor();\n            support = $.isFunction(processor.transformDocument) ? (typeof window.XMLSerializer !== \"undefined\") : true;\n            if(!support) { return false; }\n            xml = new DOMParser().parseFromString(xml, \"text/xml\");\n            xsl = new DOMParser().parseFromString(xsl, \"text/xml\");\n            if($.isFunction(processor.transformDocument)) {\n                rs = document.implementation.createDocument(\"\", \"\", null);\n                processor.transformDocument(xml, xsl, rs, null);\n                callback.call(null, new XMLSerializer().serializeToString(rs));\n                return true;\n            }\n            else {\n                processor.importStylesheet(xsl);\n                rs = processor.transformToFragment(xml, document);\n                callback.call(null, $(\"<div />\").append(rs).html());\n                return true;\n            }\n        }\n        return false;\n    };\n    var xsl = {\n        'nest' : '<' + '?xml version=\"1.0\" encoding=\"utf-8\" ?>' + \n            '<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >' + \n            '<xsl:output method=\"html\" encoding=\"utf-8\" omit-xml-declaration=\"yes\" standalone=\"no\" indent=\"no\" media-type=\"text/html\" />' + \n            '<xsl:template match=\"/\">' + \n            '   <xsl:call-template name=\"nodes\">' + \n            '       <xsl:with-param name=\"node\" select=\"/root\" />' + \n            '   </xsl:call-template>' + \n            '</xsl:template>' + \n            '<xsl:template name=\"nodes\">' + \n            '   <xsl:param name=\"node\" />' + \n            '   <ul>' + \n            '   <xsl:for-each select=\"$node/item\">' + \n            '       <xsl:variable name=\"children\" select=\"count(./item) &gt; 0\" />' + \n            '       <li>' + \n            '           <xsl:attribute name=\"class\">' + \n            '               <xsl:if test=\"position() = last()\">jstree-last </xsl:if>' + \n            '               <xsl:choose>' + \n            '                   <xsl:when test=\"@state = \\'open\\'\">jstree-open </xsl:when>' + \n            '                   <xsl:when test=\"$children or @hasChildren or @state = \\'closed\\'\">jstree-closed </xsl:when>' + \n            '                   <xsl:otherwise>jstree-leaf </xsl:otherwise>' + \n            '               </xsl:choose>' + \n            '               <xsl:value-of select=\"@class\" />' + \n            '           </xsl:attribute>' + \n            '           <xsl:for-each select=\"@*\">' + \n            '               <xsl:if test=\"name() != \\'class\\' and name() != \\'state\\' and name() != \\'hasChildren\\'\">' + \n            '                   <xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n            '               </xsl:if>' + \n            '           </xsl:for-each>' + \n            '   <ins class=\"jstree-icon\"><xsl:text>&#xa0;</xsl:text></ins>' + \n            '           <xsl:for-each select=\"content/name\">' + \n            '               <a>' + \n            '               <xsl:attribute name=\"href\">' + \n            '                   <xsl:choose>' + \n            '                   <xsl:when test=\"@href\"><xsl:value-of select=\"@href\" /></xsl:when>' + \n            '                   <xsl:otherwise>#</xsl:otherwise>' + \n            '                   </xsl:choose>' + \n            '               </xsl:attribute>' + \n            '               <xsl:attribute name=\"class\"><xsl:value-of select=\"@lang\" /> <xsl:value-of select=\"@class\" /></xsl:attribute>' + \n            '               <xsl:attribute name=\"style\"><xsl:value-of select=\"@style\" /></xsl:attribute>' + \n            '               <xsl:for-each select=\"@*\">' + \n            '                   <xsl:if test=\"name() != \\'style\\' and name() != \\'class\\' and name() != \\'href\\'\">' + \n            '                       <xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n            '                   </xsl:if>' + \n            '               </xsl:for-each>' + \n            '                   <ins>' + \n            '                       <xsl:attribute name=\"class\">jstree-icon ' + \n            '                           <xsl:if test=\"string-length(attribute::icon) > 0 and not(contains(@icon,\\'/\\'))\"><xsl:value-of select=\"@icon\" /></xsl:if>' + \n            '                       </xsl:attribute>' + \n            '                       <xsl:if test=\"string-length(attribute::icon) > 0 and contains(@icon,\\'/\\')\"><xsl:attribute name=\"style\">background:url(<xsl:value-of select=\"@icon\" />) center center no-repeat;</xsl:attribute></xsl:if>' + \n            '                       <xsl:text>&#xa0;</xsl:text>' + \n            '                   </ins>' + \n            '                   <xsl:copy-of select=\"./child::node()\" />' + \n            '               </a>' + \n            '           </xsl:for-each>' + \n            '           <xsl:if test=\"$children or @hasChildren\"><xsl:call-template name=\"nodes\"><xsl:with-param name=\"node\" select=\"current()\" /></xsl:call-template></xsl:if>' + \n            '       </li>' + \n            '   </xsl:for-each>' + \n            '   </ul>' + \n            '</xsl:template>' + \n            '</xsl:stylesheet>',\n\n        'flat' : '<' + '?xml version=\"1.0\" encoding=\"utf-8\" ?>' + \n            '<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >' + \n            '<xsl:output method=\"html\" encoding=\"utf-8\" omit-xml-declaration=\"yes\" standalone=\"no\" indent=\"no\" media-type=\"text/xml\" />' + \n            '<xsl:template match=\"/\">' + \n            '   <ul>' + \n            '   <xsl:for-each select=\"//item[not(@parent_id) or @parent_id=0 or not(@parent_id = //item/@id)]\">' + /* the last `or` may be removed */\n            '       <xsl:call-template name=\"nodes\">' + \n            '           <xsl:with-param name=\"node\" select=\".\" />' + \n            '           <xsl:with-param name=\"is_last\" select=\"number(position() = last())\" />' + \n            '       </xsl:call-template>' + \n            '   </xsl:for-each>' + \n            '   </ul>' + \n            '</xsl:template>' + \n            '<xsl:template name=\"nodes\">' + \n            '   <xsl:param name=\"node\" />' + \n            '   <xsl:param name=\"is_last\" />' + \n            '   <xsl:variable name=\"children\" select=\"count(//item[@parent_id=$node/attribute::id]) &gt; 0\" />' + \n            '   <li>' + \n            '   <xsl:attribute name=\"class\">' + \n            '       <xsl:if test=\"$is_last = true()\">jstree-last </xsl:if>' + \n            '       <xsl:choose>' + \n            '           <xsl:when test=\"@state = \\'open\\'\">jstree-open </xsl:when>' + \n            '           <xsl:when test=\"$children or @hasChildren or @state = \\'closed\\'\">jstree-closed </xsl:when>' + \n            '           <xsl:otherwise>jstree-leaf </xsl:otherwise>' + \n            '       </xsl:choose>' + \n            '       <xsl:value-of select=\"@class\" />' + \n            '   </xsl:attribute>' + \n            '   <xsl:for-each select=\"@*\">' + \n            '       <xsl:if test=\"name() != \\'parent_id\\' and name() != \\'hasChildren\\' and name() != \\'class\\' and name() != \\'state\\'\">' + \n            '       <xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n            '       </xsl:if>' + \n            '   </xsl:for-each>' + \n            '   <ins class=\"jstree-icon\"><xsl:text>&#xa0;</xsl:text></ins>' + \n            '   <xsl:for-each select=\"content/name\">' + \n            '       <a>' + \n            '       <xsl:attribute name=\"href\">' + \n            '           <xsl:choose>' + \n            '           <xsl:when test=\"@href\"><xsl:value-of select=\"@href\" /></xsl:when>' + \n            '           <xsl:otherwise>#</xsl:otherwise>' + \n            '           </xsl:choose>' + \n            '       </xsl:attribute>' + \n            '       <xsl:attribute name=\"class\"><xsl:value-of select=\"@lang\" /> <xsl:value-of select=\"@class\" /></xsl:attribute>' + \n            '       <xsl:attribute name=\"style\"><xsl:value-of select=\"@style\" /></xsl:attribute>' + \n            '       <xsl:for-each select=\"@*\">' + \n            '           <xsl:if test=\"name() != \\'style\\' and name() != \\'class\\' and name() != \\'href\\'\">' + \n            '               <xsl:attribute name=\"{name()}\"><xsl:value-of select=\".\" /></xsl:attribute>' + \n            '           </xsl:if>' + \n            '       </xsl:for-each>' + \n            '           <ins>' + \n            '               <xsl:attribute name=\"class\">jstree-icon ' + \n            '                   <xsl:if test=\"string-length(attribute::icon) > 0 and not(contains(@icon,\\'/\\'))\"><xsl:value-of select=\"@icon\" /></xsl:if>' + \n            '               </xsl:attribute>' + \n            '               <xsl:if test=\"string-length(attribute::icon) > 0 and contains(@icon,\\'/\\')\"><xsl:attribute name=\"style\">background:url(<xsl:value-of select=\"@icon\" />) center center no-repeat;</xsl:attribute></xsl:if>' + \n            '               <xsl:text>&#xa0;</xsl:text>' + \n            '           </ins>' + \n            '           <xsl:copy-of select=\"./child::node()\" />' + \n            '       </a>' + \n            '   </xsl:for-each>' + \n            '   <xsl:if test=\"$children\">' + \n            '       <ul>' + \n            '       <xsl:for-each select=\"//item[@parent_id=$node/attribute::id]\">' + \n            '           <xsl:call-template name=\"nodes\">' + \n            '               <xsl:with-param name=\"node\" select=\".\" />' + \n            '               <xsl:with-param name=\"is_last\" select=\"number(position() = last())\" />' + \n            '           </xsl:call-template>' + \n            '       </xsl:for-each>' + \n            '       </ul>' + \n            '   </xsl:if>' + \n            '   </li>' + \n            '</xsl:template>' + \n            '</xsl:stylesheet>'\n    },\n    escape_xml = function(string) {\n        return string\n            .toString()\n            .replace(/&/g, '&amp;')\n            .replace(/</g, '&lt;')\n            .replace(/>/g, '&gt;')\n            .replace(/\"/g, '&quot;')\n            .replace(/'/g, '&apos;');\n    };\n    $.jstree.plugin(\"xml_data\", {\n        defaults : { \n            data : false,\n            ajax : false,\n            xsl : \"flat\",\n            clean_node : false,\n            correct_state : true,\n            get_skip_empty : false,\n            get_include_preamble : true\n        },\n        _fn : {\n            load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_xml(obj, function () { _this.__callback({ \"obj\" : _this._get_node(obj) }); s_call.call(this); }, e_call); },\n            _is_loaded : function (obj) { \n                var s = this._get_settings().xml_data;\n                obj = this._get_node(obj);\n                return obj == -1 || !obj || (!s.ajax && !$.isFunction(s.data)) || obj.is(\".jstree-open, .jstree-leaf\") || obj.children(\"ul\").children(\"li\").size() > 0;\n            },\n            load_node_xml : function (obj, s_call, e_call) {\n                var s = this.get_settings().xml_data,\n                    error_func = function () {},\n                    success_func = function () {};\n\n                obj = this._get_node(obj);\n                if(obj && obj !== -1) {\n                    if(obj.data(\"jstree_is_loading\")) { return; }\n                    else { obj.data(\"jstree_is_loading\",true); }\n                }\n                switch(!0) {\n                    case (!s.data && !s.ajax): throw \"Neither data nor ajax settings supplied.\";\n                    case ($.isFunction(s.data)):\n                        s.data.call(this, obj, $.proxy(function (d) {\n                            this.parse_xml(d, $.proxy(function (d) {\n                                if(d) {\n                                    d = d.replace(/ ?xmlns=\"[^\"]*\"/ig, \"\");\n                                    if(d.length > 10) {\n                                        d = $(d);\n                                        if(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n                                        else { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d); obj.removeData(\"jstree_is_loading\"); }\n                                        if(s.clean_node) { this.clean_node(obj); }\n                                        if(s_call) { s_call.call(this); }\n                                    }\n                                    else {\n                                        if(obj && obj !== -1) { \n                                            obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                            obj.removeData(\"jstree_is_loading\");\n                                            if(s.correct_state) { \n                                                this.correct_state(obj);\n                                                if(s_call) { s_call.call(this); } \n                                            }\n                                        }\n                                        else {\n                                            if(s.correct_state) { \n                                                this.get_container().children(\"ul\").empty();\n                                                if(s_call) { s_call.call(this); } \n                                            }\n                                        }\n                                    }\n                                }\n                            }, this));\n                        }, this));\n                        break;\n                    case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):\n                        if(!obj || obj == -1) {\n                            this.parse_xml(s.data, $.proxy(function (d) {\n                                if(d) {\n                                    d = d.replace(/ ?xmlns=\"[^\"]*\"/ig, \"\");\n                                    if(d.length > 10) {\n                                        d = $(d);\n                                        this.get_container().children(\"ul\").empty().append(d.children());\n                                        if(s.clean_node) { this.clean_node(obj); }\n                                        if(s_call) { s_call.call(this); }\n                                    }\n                                }\n                                else { \n                                    if(s.correct_state) { \n                                        this.get_container().children(\"ul\").empty(); \n                                        if(s_call) { s_call.call(this); }\n                                    }\n                                }\n                            }, this));\n                        }\n                        break;\n                    case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):\n                        error_func = function (x, t, e) {\n                            var ef = this.get_settings().xml_data.ajax.error; \n                            if(ef) { ef.call(this, x, t, e); }\n                            if(obj !== -1 && obj.length) {\n                                obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                obj.removeData(\"jstree_is_loading\");\n                                if(t === \"success\" && s.correct_state) { this.correct_state(obj); }\n                            }\n                            else {\n                                if(t === \"success\" && s.correct_state) { this.get_container().children(\"ul\").empty(); }\n                            }\n                            if(e_call) { e_call.call(this); }\n                        };\n                        success_func = function (d, t, x) {\n                            d = x.responseText;\n                            var sf = this.get_settings().xml_data.ajax.success; \n                            if(sf) { d = sf.call(this,d,t,x) || d; }\n                            if(d === \"\" || (d && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") === \"\")) {\n                                return error_func.call(this, x, t, \"\");\n                            }\n                            this.parse_xml(d, $.proxy(function (d) {\n                                if(d) {\n                                    d = d.replace(/ ?xmlns=\"[^\"]*\"/ig, \"\");\n                                    if(d.length > 10) {\n                                        d = $(d);\n                                        if(obj === -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()); }\n                                        else { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d); obj.removeData(\"jstree_is_loading\"); }\n                                        if(s.clean_node) { this.clean_node(obj); }\n                                        if(s_call) { s_call.call(this); }\n                                    }\n                                    else {\n                                        if(obj && obj !== -1) { \n                                            obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                            obj.removeData(\"jstree_is_loading\");\n                                            if(s.correct_state) { \n                                                this.correct_state(obj);\n                                                if(s_call) { s_call.call(this); } \n                                            }\n                                        }\n                                        else {\n                                            if(s.correct_state) { \n                                                this.get_container().children(\"ul\").empty();\n                                                if(s_call) { s_call.call(this); } \n                                            }\n                                        }\n                                    }\n                                }\n                            }, this));\n                        };\n                        s.ajax.context = this;\n                        s.ajax.error = error_func;\n                        s.ajax.success = success_func;\n                        if(!s.ajax.dataType) { s.ajax.dataType = \"xml\"; }\n                        if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }\n                        if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }\n                        $.ajax(s.ajax);\n                        break;\n                }\n            },\n            parse_xml : function (xml, callback) {\n                var s = this._get_settings().xml_data;\n                $.vakata.xslt(xml, xsl[s.xsl], callback);\n            },\n            get_xml : function (tp, obj, li_attr, a_attr, is_callback) {\n                var result = \"\", \n                    s = this._get_settings(), \n                    _this = this,\n                    tmp1, tmp2, li, a, lang;\n                if(!tp) { tp = \"flat\"; }\n                if(!is_callback) { is_callback = 0; }\n                obj = this._get_node(obj);\n                if(!obj || obj === -1) { obj = this.get_container().find(\"> ul > li\"); }\n                li_attr = $.isArray(li_attr) ? li_attr : [ \"id\", \"class\" ];\n                if(!is_callback && this.data.types && $.inArray(s.types.type_attr, li_attr) === -1) { li_attr.push(s.types.type_attr); }\n\n                a_attr = $.isArray(a_attr) ? a_attr : [ ];\n\n                if(!is_callback) { \n                    if(s.xml_data.get_include_preamble) { \n                        result += '<' + '?xml version=\"1.0\" encoding=\"UTF-8\"?' + '>'; \n                    }\n                    result += \"<root>\"; \n                }\n                obj.each(function () {\n                    result += \"<item\";\n                    li = $(this);\n                    $.each(li_attr, function (i, v) { \n                        var t = li.attr(v);\n                        if(!s.xml_data.get_skip_empty || typeof t !== \"undefined\") {\n                            result += \" \" + v + \"=\\\"\" + escape_xml((\" \" + (t || \"\")).replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\")) + \"\\\"\"; \n                        }\n                    });\n                    if(li.hasClass(\"jstree-open\")) { result += \" state=\\\"open\\\"\"; }\n                    if(li.hasClass(\"jstree-closed\")) { result += \" state=\\\"closed\\\"\"; }\n                    if(tp === \"flat\") { result += \" parent_id=\\\"\" + escape_xml(is_callback) + \"\\\"\"; }\n                    result += \">\";\n                    result += \"<content>\";\n                    a = li.children(\"a\");\n                    a.each(function () {\n                        tmp1 = $(this);\n                        lang = false;\n                        result += \"<name\";\n                        if($.inArray(\"languages\", s.plugins) !== -1) {\n                            $.each(s.languages, function (k, z) {\n                                if(tmp1.hasClass(z)) { result += \" lang=\\\"\" + escape_xml(z) + \"\\\"\"; lang = z; return false; }\n                            });\n                        }\n                        if(a_attr.length) { \n                            $.each(a_attr, function (k, z) {\n                                var t = tmp1.attr(z);\n                                if(!s.xml_data.get_skip_empty || typeof t !== \"undefined\") {\n                                    result += \" \" + z + \"=\\\"\" + escape_xml((\" \" + t || \"\").replace(/ jstree[^ ]*/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\")) + \"\\\"\";\n                                }\n                            });\n                        }\n                        if(tmp1.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\\s+$/ig,\"\").length) {\n                            result += ' icon=\"' + escape_xml(tmp1.children(\"ins\").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\\s+$/ig,\" \").replace(/^ /,\"\").replace(/ $/,\"\")) + '\"';\n                        }\n                        if(tmp1.children(\"ins\").get(0).style.backgroundImage.length) {\n                            result += ' icon=\"' + escape_xml(tmp1.children(\"ins\").get(0).style.backgroundImage.replace(\"url(\",\"\").replace(\")\",\"\").replace(/'/ig,\"\").replace(/\"/ig,\"\")) + '\"';\n                        }\n                        result += \">\";\n                        result += \"<![CDATA[\" + _this.get_text(tmp1, lang) + \"]]>\";\n                        result += \"</name>\";\n                    });\n                    result += \"</content>\";\n                    tmp2 = li[0].id || true;\n                    li = li.find(\"> ul > li\");\n                    if(li.length) { tmp2 = _this.get_xml(tp, li, li_attr, a_attr, tmp2); }\n                    else { tmp2 = \"\"; }\n                    if(tp == \"nest\") { result += tmp2; }\n                    result += \"</item>\";\n                    if(tp == \"flat\") { result += tmp2; }\n                });\n                if(!is_callback) { result += \"</root>\"; }\n                return result;\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/*\n * jsTree search plugin\n * Enables both sync and async search on the tree\n * DOES NOT WORK WITH JSON PROGRESSIVE RENDER\n */\n(function ($) {\n    $.expr[':'].jstree_contains = function(a,i,m){\n        return (a.textContent || a.innerText || \"\").toLowerCase().indexOf(m[3].toLowerCase())>=0;\n    };\n    $.expr[':'].jstree_title_contains = function(a,i,m) {\n        return (a.getAttribute(\"title\") || \"\").toLowerCase().indexOf(m[3].toLowerCase())>=0;\n    };\n    $.jstree.plugin(\"search\", {\n        __init : function () {\n            this.data.search.str = \"\";\n            this.data.search.result = $();\n            if(this._get_settings().search.show_only_matches) {\n                this.get_container()\n                    .bind(\"search.jstree\", function (e, data) {\n                        $(this).children(\"ul\").find(\"li\").hide().removeClass(\"jstree-last\");\n                        data.rslt.nodes.parentsUntil(\".jstree\").andSelf().show()\n                            .filter(\"ul\").each(function () { $(this).children(\"li:visible\").eq(-1).addClass(\"jstree-last\"); });\n                    })\n                    .bind(\"clear_search.jstree\", function () {\n                        $(this).children(\"ul\").find(\"li\").css(\"display\",\"\").end().end().jstree(\"clean_node\", -1);\n                    });\n            }\n        },\n        defaults : {\n            ajax : false,\n            search_method : \"jstree_contains\", // for case insensitive - jstree_contains\n            show_only_matches : false\n        },\n        _fn : {\n            search : function (str, skip_async) {\n                if($.trim(str) === \"\") { this.clear_search(); return; }\n                var s = this.get_settings().search, \n                    t = this,\n                    error_func = function () { },\n                    success_func = function () { };\n                this.data.search.str = str;\n\n                if(!skip_async && s.ajax !== false && this.get_container_ul().find(\"li.jstree-closed:not(:has(ul)):eq(0)\").length > 0) {\n                    this.search.supress_callback = true;\n                    error_func = function () { };\n                    success_func = function (d, t, x) {\n                        var sf = this.get_settings().search.ajax.success; \n                        if(sf) { d = sf.call(this,d,t,x) || d; }\n                        this.data.search.to_open = d;\n                        this._search_open();\n                    };\n                    s.ajax.context = this;\n                    s.ajax.error = error_func;\n                    s.ajax.success = success_func;\n                    if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, str); }\n                    if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, str); }\n                    if(!s.ajax.data) { s.ajax.data = { \"search_string\" : str }; }\n                    if(!s.ajax.dataType || /^json/.exec(s.ajax.dataType)) { s.ajax.dataType = \"json\"; }\n                    $.ajax(s.ajax);\n                    return;\n                }\n                if(this.data.search.result.length) { this.clear_search(); }\n                this.data.search.result = this.get_container().find(\"a\" + (this.data.languages ? \".\" + this.get_lang() : \"\" ) + \":\" + (s.search_method) + \"(\" + this.data.search.str + \")\");\n                this.data.search.result.addClass(\"jstree-search\").parent().parents(\".jstree-closed\").each(function () {\n                    t.open_node(this, false, true);\n                });\n                this.__callback({ nodes : this.data.search.result, str : str });\n            },\n            clear_search : function (str) {\n                this.data.search.result.removeClass(\"jstree-search\");\n                this.__callback(this.data.search.result);\n                this.data.search.result = $();\n            },\n            _search_open : function (is_callback) {\n                var _this = this,\n                    done = true,\n                    current = [],\n                    remaining = [];\n                if(this.data.search.to_open.length) {\n                    $.each(this.data.search.to_open, function (i, val) {\n                        if(val == \"#\") { return true; }\n                        if($(val).length && $(val).is(\".jstree-closed\")) { current.push(val); }\n                        else { remaining.push(val); }\n                    });\n                    if(current.length) {\n                        this.data.search.to_open = remaining;\n                        $.each(current, function (i, val) { \n                            _this.open_node(val, function () { _this._search_open(true); }); \n                        });\n                        done = false;\n                    }\n                }\n                if(done) { this.search(this.data.search.str, true); }\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree contextmenu plugin\n */\n(function ($) {\n    $.vakata.context = {\n        hide_on_mouseleave : false,\n\n        cnt     : $(\"<div id='vakata-contextmenu' />\"),\n        vis     : false,\n        tgt     : false,\n        par     : false,\n        func    : false,\n        data    : false,\n        rtl     : false,\n        show    : function (s, t, x, y, d, p, rtl) {\n            $.vakata.context.rtl = !!rtl;\n            var html = $.vakata.context.parse(s), h, w;\n            if(!html) { return; }\n            $.vakata.context.vis = true;\n            $.vakata.context.tgt = t;\n            $.vakata.context.par = p || t || null;\n            $.vakata.context.data = d || null;\n            $.vakata.context.cnt\n                .html(html)\n                .css({ \"visibility\" : \"hidden\", \"display\" : \"block\", \"left\" : 0, \"top\" : 0 });\n\n            if($.vakata.context.hide_on_mouseleave) {\n                $.vakata.context.cnt\n                    .one(\"mouseleave\", function(e) { $.vakata.context.hide(); });\n            }\n\n            h = $.vakata.context.cnt.height();\n            w = $.vakata.context.cnt.width();\n            if(x + w > $(document).width()) { \n                x = $(document).width() - (w + 5); \n                $.vakata.context.cnt.find(\"li > ul\").addClass(\"right\"); \n            }\n            if(y + h > $(document).height()) { \n                y = y - (h + t[0].offsetHeight); \n                $.vakata.context.cnt.find(\"li > ul\").addClass(\"bottom\"); \n            }\n\n            $.vakata.context.cnt\n                .css({ \"left\" : x, \"top\" : y })\n                .find(\"li:has(ul)\")\n                    .bind(\"mouseenter\", function (e) { \n                        var w = $(document).width(),\n                            h = $(document).height(),\n                            ul = $(this).children(\"ul\").show(); \n                        if(w !== $(document).width()) { ul.toggleClass(\"right\"); }\n                        if(h !== $(document).height()) { ul.toggleClass(\"bottom\"); }\n                    })\n                    .bind(\"mouseleave\", function (e) { \n                        $(this).children(\"ul\").hide(); \n                    })\n                    .end()\n                .css({ \"visibility\" : \"visible\" })\n                .show();\n            $(document).triggerHandler(\"context_show.vakata\");\n        },\n        hide    : function () {\n            $.vakata.context.vis = false;\n            $.vakata.context.cnt.attr(\"class\",\"\").css({ \"visibility\" : \"hidden\" });\n            $(document).triggerHandler(\"context_hide.vakata\");\n        },\n        parse   : function (s, is_callback) {\n            if(!s) { return false; }\n            var str = \"\",\n                tmp = false,\n                was_sep = true;\n            if(!is_callback) { $.vakata.context.func = {}; }\n            str += \"<ul>\";\n            $.each(s, function (i, val) {\n                if(!val) { return true; }\n                $.vakata.context.func[i] = val.action;\n                if(!was_sep && val.separator_before) {\n                    str += \"<li class='vakata-separator vakata-separator-before'></li>\";\n                }\n                was_sep = false;\n                str += \"<li class='\" + (val._class || \"\") + (val._disabled ? \" jstree-contextmenu-disabled \" : \"\") + \"'><ins \";\n                if(val.icon && val.icon.indexOf(\"/\") === -1) { str += \" class='\" + val.icon + \"' \"; }\n                if(val.icon && val.icon.indexOf(\"/\") !== -1) { str += \" style='background:url(\" + val.icon + \") center center no-repeat;' \"; }\n                str += \">&#160;</ins><a href='#' rel='\" + i + \"'>\";\n                if(val.submenu) {\n                    str += \"<span style='float:\" + ($.vakata.context.rtl ? \"left\" : \"right\") + \";'>&raquo;</span>\";\n                }\n                str += val.label + \"</a>\";\n                if(val.submenu) {\n                    tmp = $.vakata.context.parse(val.submenu, true);\n                    if(tmp) { str += tmp; }\n                }\n                str += \"</li>\";\n                if(val.separator_after) {\n                    str += \"<li class='vakata-separator vakata-separator-after'></li>\";\n                    was_sep = true;\n                }\n            });\n            str = str.replace(/<li class\\='vakata-separator vakata-separator-after'\\><\\/li\\>$/,\"\");\n            str += \"</ul>\";\n            $(document).triggerHandler(\"context_parse.vakata\");\n            return str.length > 10 ? str : false;\n        },\n        exec    : function (i) {\n            if($.isFunction($.vakata.context.func[i])) {\n                // if is string - eval and call it!\n                $.vakata.context.func[i].call($.vakata.context.data, $.vakata.context.par);\n                return true;\n            }\n            else { return false; }\n        }\n    };\n    $(function () {\n        var css_string = '' + \n            '#vakata-contextmenu { display:block; visibility:hidden; left:0; top:-200px; position:absolute; margin:0; padding:0; min-width:180px; background:#ebebeb; border:1px solid silver; z-index:10000; *width:180px; } ' + \n            '#vakata-contextmenu ul { min-width:180px; *width:180px; } ' + \n            '#vakata-contextmenu ul, #vakata-contextmenu li { margin:0; padding:0; list-style-type:none; display:block; } ' + \n            '#vakata-contextmenu li { line-height:20px; min-height:20px; position:relative; padding:0px; } ' + \n            '#vakata-contextmenu li a { padding:1px 6px; line-height:17px; display:block; text-decoration:none; margin:1px 1px 0 1px; } ' + \n            '#vakata-contextmenu li ins { float:left; width:16px; height:16px; text-decoration:none; margin-right:2px; } ' + \n            '#vakata-contextmenu li a:hover, #vakata-contextmenu li.vakata-hover > a { background:gray; color:white; } ' + \n            '#vakata-contextmenu li ul { display:none; position:absolute; top:-2px; left:100%; background:#ebebeb; border:1px solid gray; } ' + \n            '#vakata-contextmenu .right { right:100%; left:auto; } ' + \n            '#vakata-contextmenu .bottom { bottom:-1px; top:auto; } ' + \n            '#vakata-contextmenu li.vakata-separator { min-height:0; height:1px; line-height:1px; font-size:1px; overflow:hidden; margin:0 2px; background:silver; /* border-top:1px solid #fefefe; */ padding:0; } ';\n        $.vakata.css.add_sheet({ str : css_string, title : \"vakata\" });\n        $.vakata.context.cnt\n            .delegate(\"a\",\"click\", function (e) { e.preventDefault(); })\n            .delegate(\"a\",\"mouseup\", function (e) {\n                if(!$(this).parent().hasClass(\"jstree-contextmenu-disabled\") && $.vakata.context.exec($(this).attr(\"rel\"))) {\n                    $.vakata.context.hide();\n                }\n                else { $(this).blur(); }\n            })\n            .delegate(\"a\",\"mouseover\", function () {\n                $.vakata.context.cnt.find(\".vakata-hover\").removeClass(\"vakata-hover\");\n            })\n            .appendTo(\"body\");\n        $(document).bind(\"mousedown\", function (e) { if($.vakata.context.vis && !$.contains($.vakata.context.cnt[0], e.target)) { $.vakata.context.hide(); } });\n        if(typeof $.hotkeys !== \"undefined\") {\n            $(document)\n                .bind(\"keydown\", \"up\", function (e) { \n                    if($.vakata.context.vis) { \n                        var o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\".vakata-hover\").removeClass(\"vakata-hover\").prevAll(\"li:not(.vakata-separator)\").first();\n                        if(!o.length) { o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\"li:not(.vakata-separator)\").last(); }\n                        o.addClass(\"vakata-hover\");\n                        e.stopImmediatePropagation(); \n                        e.preventDefault();\n                    } \n                })\n                .bind(\"keydown\", \"down\", function (e) { \n                    if($.vakata.context.vis) { \n                        var o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\".vakata-hover\").removeClass(\"vakata-hover\").nextAll(\"li:not(.vakata-separator)\").first();\n                        if(!o.length) { o = $.vakata.context.cnt.find(\"ul:visible\").last().children(\"li:not(.vakata-separator)\").first(); }\n                        o.addClass(\"vakata-hover\");\n                        e.stopImmediatePropagation(); \n                        e.preventDefault();\n                    } \n                })\n                .bind(\"keydown\", \"right\", function (e) { \n                    if($.vakata.context.vis) { \n                        $.vakata.context.cnt.find(\".vakata-hover\").children(\"ul\").show().children(\"li:not(.vakata-separator)\").removeClass(\"vakata-hover\").first().addClass(\"vakata-hover\");\n                        e.stopImmediatePropagation(); \n                        e.preventDefault();\n                    } \n                })\n                .bind(\"keydown\", \"left\", function (e) { \n                    if($.vakata.context.vis) { \n                        $.vakata.context.cnt.find(\".vakata-hover\").children(\"ul\").hide().children(\".vakata-separator\").removeClass(\"vakata-hover\");\n                        e.stopImmediatePropagation(); \n                        e.preventDefault();\n                    } \n                })\n                .bind(\"keydown\", \"esc\", function (e) { \n                    $.vakata.context.hide(); \n                    e.preventDefault();\n                })\n                .bind(\"keydown\", \"space\", function (e) { \n                    $.vakata.context.cnt.find(\".vakata-hover\").last().children(\"a\").click();\n                    e.preventDefault();\n                });\n        }\n    });\n\n    $.jstree.plugin(\"contextmenu\", {\n        __init : function () {\n            this.get_container()\n                .delegate(\"a\", \"contextmenu.jstree\", $.proxy(function (e) {\n                        e.preventDefault();\n                        if(!$(e.currentTarget).hasClass(\"jstree-loading\")) {\n                            this.show_contextmenu(e.currentTarget, e.pageX, e.pageY);\n                        }\n                    }, this))\n                .delegate(\"a\", \"click.jstree\", $.proxy(function (e) {\n                        if(this.data.contextmenu) {\n                            $.vakata.context.hide();\n                        }\n                    }, this))\n                .bind(\"destroy.jstree\", $.proxy(function () {\n                        // TODO: move this to descruct method\n                        if(this.data.contextmenu) {\n                            $.vakata.context.hide();\n                        }\n                    }, this));\n            $(document).bind(\"context_hide.vakata\", $.proxy(function () { this.data.contextmenu = false; }, this));\n        },\n        defaults : { \n            select_node : false, // requires UI plugin\n            show_at_node : true,\n            items : { // Could be a function that should return an object like this one\n                \"create\" : {\n                    \"separator_before\"  : false,\n                    \"separator_after\"   : true,\n                    \"label\"             : \"Create\",\n                    \"action\"            : function (obj) { this.create(obj); }\n                },\n                \"rename\" : {\n                    \"separator_before\"  : false,\n                    \"separator_after\"   : false,\n                    \"label\"             : \"Rename\",\n                    \"action\"            : function (obj) { this.rename(obj); }\n                },\n                \"remove\" : {\n                    \"separator_before\"  : false,\n                    \"icon\"              : false,\n                    \"separator_after\"   : false,\n                    \"label\"             : \"Delete\",\n                    \"action\"            : function (obj) { if(this.is_selected(obj)) { this.remove(); } else { this.remove(obj); } }\n                },\n                \"ccp\" : {\n                    \"separator_before\"  : true,\n                    \"icon\"              : false,\n                    \"separator_after\"   : false,\n                    \"label\"             : \"Edit\",\n                    \"action\"            : false,\n                    \"submenu\" : { \n                        \"cut\" : {\n                            \"separator_before\"  : false,\n                            \"separator_after\"   : false,\n                            \"label\"             : \"Cut\",\n                            \"action\"            : function (obj) { this.cut(obj); }\n                        },\n                        \"copy\" : {\n                            \"separator_before\"  : false,\n                            \"icon\"              : false,\n                            \"separator_after\"   : false,\n                            \"label\"             : \"Copy\",\n                            \"action\"            : function (obj) { this.copy(obj); }\n                        },\n                        \"paste\" : {\n                            \"separator_before\"  : false,\n                            \"icon\"              : false,\n                            \"separator_after\"   : false,\n                            \"label\"             : \"Paste\",\n                            \"action\"            : function (obj) { this.paste(obj); }\n                        }\n                    }\n                }\n            }\n        },\n        _fn : {\n            show_contextmenu : function (obj, x, y) {\n                obj = this._get_node(obj);\n                var s = this.get_settings().contextmenu,\n                    a = obj.children(\"a:visible:eq(0)\"),\n                    o = false,\n                    i = false;\n                if(s.select_node && this.data.ui && !this.is_selected(obj)) {\n                    this.deselect_all();\n                    this.select_node(obj, true);\n                }\n                if(s.show_at_node || typeof x === \"undefined\" || typeof y === \"undefined\") {\n                    o = a.offset();\n                    x = o.left;\n                    y = o.top + this.data.core.li_height;\n                }\n                i = obj.data(\"jstree\") && obj.data(\"jstree\").contextmenu ? obj.data(\"jstree\").contextmenu : s.items;\n                if($.isFunction(i)) { i = i.call(this, obj); }\n                this.data.contextmenu = true;\n                $.vakata.context.show(i, a, x, y, this, obj, this._get_settings().core.rtl);\n                if(this.data.themes) { $.vakata.context.cnt.attr(\"class\", \"jstree-\" + this.data.themes.theme + \"-context\"); }\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree types plugin\n * Adds support types of nodes\n * You can set an attribute on each li node, that represents its type.\n * According to the type setting the node may get custom icon/validation rules\n */\n(function ($) {\n    $.jstree.plugin(\"types\", {\n        __init : function () {\n            var s = this._get_settings().types;\n            this.data.types.attach_to = [];\n            this.get_container()\n                .bind(\"init.jstree\", $.proxy(function () { \n                        var types = s.types, \n                            attr  = s.type_attr, \n                            icons_css = \"\", \n                            _this = this;\n\n                        $.each(types, function (i, tp) {\n                            $.each(tp, function (k, v) { \n                                if(!/^(max_depth|max_children|icon|valid_children)$/.test(k)) { _this.data.types.attach_to.push(k); }\n                            });\n                            if(!tp.icon) { return true; }\n                            if( tp.icon.image || tp.icon.position) {\n                                if(i == \"default\")  { icons_css += '.jstree-' + _this.get_index() + ' a > .jstree-icon { '; }\n                                else                { icons_css += '.jstree-' + _this.get_index() + ' li[' + attr + '=\"' + i + '\"] > a > .jstree-icon { '; }\n                                if(tp.icon.image)   { icons_css += ' background-image:url(' + tp.icon.image + '); '; }\n                                if(tp.icon.position){ icons_css += ' background-position:' + tp.icon.position + '; '; }\n                                else                { icons_css += ' background-position:0 0; '; }\n                                icons_css += '} ';\n                            }\n                        });\n                        if(icons_css !== \"\") { $.vakata.css.add_sheet({ 'str' : icons_css, title : \"jstree-types\" }); }\n                    }, this))\n                .bind(\"before.jstree\", $.proxy(function (e, data) { \n                        var s, t, \n                            o = this._get_settings().types.use_data ? this._get_node(data.args[0]) : false, \n                            d = o && o !== -1 && o.length ? o.data(\"jstree\") : false;\n                        if(d && d.types && d.types[data.func] === false) { e.stopImmediatePropagation(); return false; }\n                        if($.inArray(data.func, this.data.types.attach_to) !== -1) {\n                            if(!data.args[0] || (!data.args[0].tagName && !data.args[0].jquery)) { return; }\n                            s = this._get_settings().types.types;\n                            t = this._get_type(data.args[0]);\n                            if(\n                                ( \n                                    (s[t] && typeof s[t][data.func] !== \"undefined\") || \n                                    (s[\"default\"] && typeof s[\"default\"][data.func] !== \"undefined\") \n                                ) && this._check(data.func, data.args[0]) === false\n                            ) {\n                                e.stopImmediatePropagation();\n                                return false;\n                            }\n                        }\n                    }, this));\n            if(is_ie6) {\n                this.get_container()\n                    .bind(\"load_node.jstree set_type.jstree\", $.proxy(function (e, data) {\n                            var r = data && data.rslt && data.rslt.obj && data.rslt.obj !== -1 ? this._get_node(data.rslt.obj).parent() : this.get_container_ul(),\n                                c = false,\n                                s = this._get_settings().types;\n                            $.each(s.types, function (i, tp) {\n                                if(tp.icon && (tp.icon.image || tp.icon.position)) {\n                                    c = i === \"default\" ? r.find(\"li > a > .jstree-icon\") : r.find(\"li[\" + s.type_attr + \"='\" + i + \"'] > a > .jstree-icon\");\n                                    if(tp.icon.image) { c.css(\"backgroundImage\",\"url(\" + tp.icon.image + \")\"); }\n                                    c.css(\"backgroundPosition\", tp.icon.position || \"0 0\");\n                                }\n                            });\n                        }, this));\n            }\n        },\n        defaults : {\n            // defines maximum number of root nodes (-1 means unlimited, -2 means disable max_children checking)\n            max_children        : -1,\n            // defines the maximum depth of the tree (-1 means unlimited, -2 means disable max_depth checking)\n            max_depth           : -1,\n            // defines valid node types for the root nodes\n            valid_children      : \"all\",\n\n            // whether to use $.data\n            use_data : false, \n            // where is the type stores (the rel attribute of the LI element)\n            type_attr : \"rel\",\n            // a list of types\n            types : {\n                // the default type\n                \"default\" : {\n                    \"max_children\"  : -1,\n                    \"max_depth\"     : -1,\n                    \"valid_children\": \"all\"\n\n                    // Bound functions - you can bind any other function here (using boolean or function)\n                    //\"select_node\" : true\n                }\n            }\n        },\n        _fn : {\n            _types_notify : function (n, data) {\n                if(data.type && this._get_settings().types.use_data) {\n                    this.set_type(data.type, n);\n                }\n            },\n            _get_type : function (obj) {\n                obj = this._get_node(obj);\n                return (!obj || !obj.length) ? false : obj.attr(this._get_settings().types.type_attr) || \"default\";\n            },\n            set_type : function (str, obj) {\n                obj = this._get_node(obj);\n                var ret = (!obj.length || !str) ? false : obj.attr(this._get_settings().types.type_attr, str);\n                if(ret) { this.__callback({ obj : obj, type : str}); }\n                return ret;\n            },\n            _check : function (rule, obj, opts) {\n                obj = this._get_node(obj);\n                var v = false, t = this._get_type(obj), d = 0, _this = this, s = this._get_settings().types, data = false;\n                if(obj === -1) { \n                    if(!!s[rule]) { v = s[rule]; }\n                    else { return; }\n                }\n                else {\n                    if(t === false) { return; }\n                    data = s.use_data ? obj.data(\"jstree\") : false;\n                    if(data && data.types && typeof data.types[rule] !== \"undefined\") { v = data.types[rule]; }\n                    else if(!!s.types[t] && typeof s.types[t][rule] !== \"undefined\") { v = s.types[t][rule]; }\n                    else if(!!s.types[\"default\"] && typeof s.types[\"default\"][rule] !== \"undefined\") { v = s.types[\"default\"][rule]; }\n                }\n                if($.isFunction(v)) { v = v.call(this, obj); }\n                if(rule === \"max_depth\" && obj !== -1 && opts !== false && s.max_depth !== -2 && v !== 0) {\n                    // also include the node itself - otherwise if root node it is not checked\n                    obj.children(\"a:eq(0)\").parentsUntil(\".jstree\",\"li\").each(function (i) {\n                        // check if current depth already exceeds global tree depth\n                        if(s.max_depth !== -1 && s.max_depth - (i + 1) <= 0) { v = 0; return false; }\n                        d = (i === 0) ? v : _this._check(rule, this, false);\n                        // check if current node max depth is already matched or exceeded\n                        if(d !== -1 && d - (i + 1) <= 0) { v = 0; return false; }\n                        // otherwise - set the max depth to the current value minus current depth\n                        if(d >= 0 && (d - (i + 1) < v || v < 0) ) { v = d - (i + 1); }\n                        // if the global tree depth exists and it minus the nodes calculated so far is less than `v` or `v` is unlimited\n                        if(s.max_depth >= 0 && (s.max_depth - (i + 1) < v || v < 0) ) { v = s.max_depth - (i + 1); }\n                    });\n                }\n                return v;\n            },\n            check_move : function () {\n                if(!this.__call_old()) { return false; }\n                var m  = this._get_move(),\n                    s  = m.rt._get_settings().types,\n                    mc = m.rt._check(\"max_children\", m.cr),\n                    md = m.rt._check(\"max_depth\", m.cr),\n                    vc = m.rt._check(\"valid_children\", m.cr),\n                    ch = 0, d = 1, t;\n\n                if(vc === \"none\") { return false; } \n                if($.isArray(vc) && m.ot && m.ot._get_type) {\n                    m.o.each(function () {\n                        if($.inArray(m.ot._get_type(this), vc) === -1) { d = false; return false; }\n                    });\n                    if(d === false) { return false; }\n                }\n                if(s.max_children !== -2 && mc !== -1) {\n                    ch = m.cr === -1 ? this.get_container().find(\"> ul > li\").not(m.o).length : m.cr.find(\"> ul > li\").not(m.o).length;\n                    if(ch + m.o.length > mc) { return false; }\n                }\n                if(s.max_depth !== -2 && md !== -1) {\n                    d = 0;\n                    if(md === 0) { return false; }\n                    if(typeof m.o.d === \"undefined\") {\n                        // TODO: deal with progressive rendering and async when checking max_depth (how to know the depth of the moved node)\n                        t = m.o;\n                        while(t.length > 0) {\n                            t = t.find(\"> ul > li\");\n                            d ++;\n                        }\n                        m.o.d = d;\n                    }\n                    if(md - m.o.d < 0) { return false; }\n                }\n                return true;\n            },\n            create_node : function (obj, position, js, callback, is_loaded, skip_check) {\n                if(!skip_check && (is_loaded || this._is_loaded(obj))) {\n                    var p  = (typeof position == \"string\" && position.match(/^before|after$/i) && obj !== -1) ? this._get_parent(obj) : this._get_node(obj),\n                        s  = this._get_settings().types,\n                        mc = this._check(\"max_children\", p),\n                        md = this._check(\"max_depth\", p),\n                        vc = this._check(\"valid_children\", p),\n                        ch;\n                    if(typeof js === \"string\") { js = { data : js }; }\n                    if(!js) { js = {}; }\n                    if(vc === \"none\") { return false; } \n                    if($.isArray(vc)) {\n                        if(!js.attr || !js.attr[s.type_attr]) { \n                            if(!js.attr) { js.attr = {}; }\n                            js.attr[s.type_attr] = vc[0]; \n                        }\n                        else {\n                            if($.inArray(js.attr[s.type_attr], vc) === -1) { return false; }\n                        }\n                    }\n                    if(s.max_children !== -2 && mc !== -1) {\n                        ch = p === -1 ? this.get_container().find(\"> ul > li\").length : p.find(\"> ul > li\").length;\n                        if(ch + 1 > mc) { return false; }\n                    }\n                    if(s.max_depth !== -2 && md !== -1 && (md - 1) < 0) { return false; }\n                }\n                return this.__call_old(true, obj, position, js, callback, is_loaded, skip_check);\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree HTML plugin\n * The HTML data store. Datastores are build by replacing the `load_node` and `_is_loaded` functions.\n */\n(function ($) {\n    $.jstree.plugin(\"html_data\", {\n        __init : function () { \n            // this used to use html() and clean the whitespace, but this way any attached data was lost\n            this.data.html_data.original_container_html = this.get_container().find(\" > ul > li\").clone(true);\n            // remove white space from LI node - otherwise nodes appear a bit to the right\n            this.data.html_data.original_container_html.find(\"li\").andSelf().contents().filter(function() { return this.nodeType == 3; }).remove();\n        },\n        defaults : { \n            data : false,\n            ajax : false,\n            correct_state : true\n        },\n        _fn : {\n            load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_html(obj, function () { _this.__callback({ \"obj\" : _this._get_node(obj) }); s_call.call(this); }, e_call); },\n            _is_loaded : function (obj) { \n                obj = this._get_node(obj); \n                return obj == -1 || !obj || (!this._get_settings().html_data.ajax && !$.isFunction(this._get_settings().html_data.data)) || obj.is(\".jstree-open, .jstree-leaf\") || obj.children(\"ul\").children(\"li\").size() > 0;\n            },\n            load_node_html : function (obj, s_call, e_call) {\n                var d,\n                    s = this.get_settings().html_data,\n                    error_func = function () {},\n                    success_func = function () {};\n                obj = this._get_node(obj);\n                if(obj && obj !== -1) {\n                    if(obj.data(\"jstree_is_loading\")) { return; }\n                    else { obj.data(\"jstree_is_loading\",true); }\n                }\n                switch(!0) {\n                    case ($.isFunction(s.data)):\n                        s.data.call(this, obj, $.proxy(function (d) {\n                            if(d && d !== \"\" && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") !== \"\") {\n                                d = $(d);\n                                if(!d.is(\"ul\")) { d = $(\"<ul />\").append(d); }\n                                if(obj == -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()).find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); }\n                                else { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d).children(\"ul\").find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); obj.removeData(\"jstree_is_loading\"); }\n                                this.clean_node(obj);\n                                if(s_call) { s_call.call(this); }\n                            }\n                            else {\n                                if(obj && obj !== -1) {\n                                    obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                    obj.removeData(\"jstree_is_loading\");\n                                    if(s.correct_state) { \n                                        this.correct_state(obj);\n                                        if(s_call) { s_call.call(this); } \n                                    }\n                                }\n                                else {\n                                    if(s.correct_state) { \n                                        this.get_container().children(\"ul\").empty();\n                                        if(s_call) { s_call.call(this); } \n                                    }\n                                }\n                            }\n                        }, this));\n                        break;\n                    case (!s.data && !s.ajax):\n                        if(!obj || obj == -1) {\n                            this.get_container()\n                                .children(\"ul\").empty()\n                                .append(this.data.html_data.original_container_html)\n                                .find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end()\n                                .filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\");\n                            this.clean_node();\n                        }\n                        if(s_call) { s_call.call(this); }\n                        break;\n                    case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):\n                        if(!obj || obj == -1) {\n                            d = $(s.data);\n                            if(!d.is(\"ul\")) { d = $(\"<ul />\").append(d); }\n                            this.get_container()\n                                .children(\"ul\").empty().append(d.children())\n                                .find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end()\n                                .filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\");\n                            this.clean_node();\n                        }\n                        if(s_call) { s_call.call(this); }\n                        break;\n                    case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):\n                        obj = this._get_node(obj);\n                        error_func = function (x, t, e) {\n                            var ef = this.get_settings().html_data.ajax.error; \n                            if(ef) { ef.call(this, x, t, e); }\n                            if(obj != -1 && obj.length) {\n                                obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                obj.removeData(\"jstree_is_loading\");\n                                if(t === \"success\" && s.correct_state) { this.correct_state(obj); }\n                            }\n                            else {\n                                if(t === \"success\" && s.correct_state) { this.get_container().children(\"ul\").empty(); }\n                            }\n                            if(e_call) { e_call.call(this); }\n                        };\n                        success_func = function (d, t, x) {\n                            var sf = this.get_settings().html_data.ajax.success; \n                            if(sf) { d = sf.call(this,d,t,x) || d; }\n                            if(d === \"\" || (d && d.toString && d.toString().replace(/^[\\s\\n]+$/,\"\") === \"\")) {\n                                return error_func.call(this, x, t, \"\");\n                            }\n                            if(d) {\n                                d = $(d);\n                                if(!d.is(\"ul\")) { d = $(\"<ul />\").append(d); }\n                                if(obj == -1 || !obj) { this.get_container().children(\"ul\").empty().append(d.children()).find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); }\n                                else { obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\"); obj.append(d).children(\"ul\").find(\"li, a\").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== \"INS\"; }).prepend(\"<ins class='jstree-icon'>&#160;</ins>\").end().filter(\"a\").children(\"ins:first-child\").not(\".jstree-icon\").addClass(\"jstree-icon\"); obj.removeData(\"jstree_is_loading\"); }\n                                this.clean_node(obj);\n                                if(s_call) { s_call.call(this); }\n                            }\n                            else {\n                                if(obj && obj !== -1) {\n                                    obj.children(\"a.jstree-loading\").removeClass(\"jstree-loading\");\n                                    obj.removeData(\"jstree_is_loading\");\n                                    if(s.correct_state) { \n                                        this.correct_state(obj);\n                                        if(s_call) { s_call.call(this); } \n                                    }\n                                }\n                                else {\n                                    if(s.correct_state) { \n                                        this.get_container().children(\"ul\").empty();\n                                        if(s_call) { s_call.call(this); } \n                                    }\n                                }\n                            }\n                        };\n                        s.ajax.context = this;\n                        s.ajax.error = error_func;\n                        s.ajax.success = success_func;\n                        if(!s.ajax.dataType) { s.ajax.dataType = \"html\"; }\n                        if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }\n                        if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }\n                        $.ajax(s.ajax);\n                        break;\n                }\n            }\n        }\n    });\n    // include the HTML data plugin by default\n    $.jstree.defaults.plugins.push(\"html_data\");\n})(jQuery);\n//*/\n\n/* \n * jsTree themeroller plugin\n * Adds support for jQuery UI themes. Include this at the end of your plugins list, also make sure \"themes\" is not included.\n */\n(function ($) {\n    $.jstree.plugin(\"themeroller\", {\n        __init : function () {\n            var s = this._get_settings().themeroller;\n            this.get_container()\n                .addClass(\"ui-widget-content\")\n                .addClass(\"jstree-themeroller\")\n                .delegate(\"a\",\"mouseenter.jstree\", function (e) {\n                    if(!$(e.currentTarget).hasClass(\"jstree-loading\")) {\n                        $(this).addClass(s.item_h);\n                    }\n                })\n                .delegate(\"a\",\"mouseleave.jstree\", function () {\n                    $(this).removeClass(s.item_h);\n                })\n                .bind(\"init.jstree\", $.proxy(function (e, data) { \n                        data.inst.get_container().find(\"> ul > li > .jstree-loading > ins\").addClass(\"ui-icon-refresh\");\n                        this._themeroller(data.inst.get_container().find(\"> ul > li\"));\n                    }, this))\n                .bind(\"open_node.jstree create_node.jstree\", $.proxy(function (e, data) { \n                        this._themeroller(data.rslt.obj);\n                    }, this))\n                .bind(\"loaded.jstree refresh.jstree\", $.proxy(function (e) {\n                        this._themeroller();\n                    }, this))\n                .bind(\"close_node.jstree\", $.proxy(function (e, data) {\n                        this._themeroller(data.rslt.obj);\n                    }, this))\n                .bind(\"delete_node.jstree\", $.proxy(function (e, data) {\n                        this._themeroller(data.rslt.parent);\n                    }, this))\n                .bind(\"correct_state.jstree\", $.proxy(function (e, data) {\n                        data.rslt.obj\n                            .children(\"ins.jstree-icon\").removeClass(s.opened + \" \" + s.closed + \" ui-icon\").end()\n                            .find(\"> a > ins.ui-icon\")\n                                .filter(function() { \n                                    return this.className.toString()\n                                        .replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n                                        .indexOf(\"ui-icon-\") === -1; \n                                }).removeClass(s.item_open + \" \" + s.item_clsd).addClass(s.item_leaf || \"jstree-no-icon\");\n                    }, this))\n                .bind(\"select_node.jstree\", $.proxy(function (e, data) {\n                        data.rslt.obj.children(\"a\").addClass(s.item_a);\n                    }, this))\n                .bind(\"deselect_node.jstree deselect_all.jstree\", $.proxy(function (e, data) {\n                        this.get_container()\n                            .find(\"a.\" + s.item_a).removeClass(s.item_a).end()\n                            .find(\"a.jstree-clicked\").addClass(s.item_a);\n                    }, this))\n                .bind(\"dehover_node.jstree\", $.proxy(function (e, data) {\n                        data.rslt.obj.children(\"a\").removeClass(s.item_h);\n                    }, this))\n                .bind(\"hover_node.jstree\", $.proxy(function (e, data) {\n                        this.get_container()\n                            .find(\"a.\" + s.item_h).not(data.rslt.obj).removeClass(s.item_h);\n                        data.rslt.obj.children(\"a\").addClass(s.item_h);\n                    }, this))\n                .bind(\"move_node.jstree\", $.proxy(function (e, data) {\n                        this._themeroller(data.rslt.o);\n                        this._themeroller(data.rslt.op);\n                    }, this));\n        },\n        __destroy : function () {\n            var s = this._get_settings().themeroller,\n                c = [ \"ui-icon\" ];\n            $.each(s, function (i, v) {\n                v = v.split(\" \");\n                if(v.length) { c = c.concat(v); }\n            });\n            this.get_container()\n                .removeClass(\"ui-widget-content\")\n                .find(\".\" + c.join(\", .\")).removeClass(c.join(\" \"));\n        },\n        _fn : {\n            _themeroller : function (obj) {\n                var s = this._get_settings().themeroller;\n                obj = !obj || obj == -1 ? this.get_container_ul() : this._get_node(obj).parent();\n                obj\n                    .find(\"li.jstree-closed\")\n                        .children(\"ins.jstree-icon\").removeClass(s.opened).addClass(\"ui-icon \" + s.closed).end()\n                        .children(\"a\").addClass(s.item)\n                            .children(\"ins.jstree-icon\").addClass(\"ui-icon\")\n                                .filter(function() { \n                                    return this.className.toString()\n                                        .replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n                                        .indexOf(\"ui-icon-\") === -1; \n                                }).removeClass(s.item_leaf + \" \" + s.item_open).addClass(s.item_clsd || \"jstree-no-icon\")\n                                .end()\n                            .end()\n                        .end()\n                    .end()\n                    .find(\"li.jstree-open\")\n                        .children(\"ins.jstree-icon\").removeClass(s.closed).addClass(\"ui-icon \" + s.opened).end()\n                        .children(\"a\").addClass(s.item)\n                            .children(\"ins.jstree-icon\").addClass(\"ui-icon\")\n                                .filter(function() { \n                                    return this.className.toString()\n                                        .replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n                                        .indexOf(\"ui-icon-\") === -1; \n                                }).removeClass(s.item_leaf + \" \" + s.item_clsd).addClass(s.item_open || \"jstree-no-icon\")\n                                .end()\n                            .end()\n                        .end()\n                    .end()\n                    .find(\"li.jstree-leaf\")\n                        .children(\"ins.jstree-icon\").removeClass(s.closed + \" ui-icon \" + s.opened).end()\n                        .children(\"a\").addClass(s.item)\n                            .children(\"ins.jstree-icon\").addClass(\"ui-icon\")\n                                .filter(function() { \n                                    return this.className.toString()\n                                        .replace(s.item_clsd,\"\").replace(s.item_open,\"\").replace(s.item_leaf,\"\")\n                                        .indexOf(\"ui-icon-\") === -1; \n                                }).removeClass(s.item_clsd + \" \" + s.item_open).addClass(s.item_leaf || \"jstree-no-icon\");\n            }\n        },\n        defaults : {\n            \"opened\"    : \"ui-icon-triangle-1-se\",\n            \"closed\"    : \"ui-icon-triangle-1-e\",\n            \"item\"      : \"ui-state-default\",\n            \"item_h\"    : \"ui-state-hover\",\n            \"item_a\"    : \"ui-state-active\",\n            \"item_open\" : \"ui-icon-folder-open\",\n            \"item_clsd\" : \"ui-icon-folder-collapsed\",\n            \"item_leaf\" : \"ui-icon-document\"\n        }\n    });\n    $(function() {\n        var css_string = '' + \n            '.jstree-themeroller .ui-icon { overflow:visible; } ' + \n            '.jstree-themeroller a { padding:0 2px; } ' + \n            '.jstree-themeroller .jstree-no-icon { display:none; }';\n        $.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n    });\n})(jQuery);\n//*/\n\n/* \n * jsTree unique plugin\n * Forces different names amongst siblings (still a bit experimental)\n * NOTE: does not check language versions (it will not be possible to have nodes with the same title, even in different languages)\n */\n(function ($) {\n    $.jstree.plugin(\"unique\", {\n        __init : function () {\n            this.get_container()\n                .bind(\"before.jstree\", $.proxy(function (e, data) { \n                        var nms = [], res = true, p, t;\n                        if(data.func == \"move_node\") {\n                            // obj, ref, position, is_copy, is_prepared, skip_check\n                            if(data.args[4] === true) {\n                                if(data.args[0].o && data.args[0].o.length) {\n                                    data.args[0].o.children(\"a\").each(function () { nms.push($(this).text().replace(/^\\s+/g,\"\")); });\n                                    res = this._check_unique(nms, data.args[0].np.find(\"> ul > li\").not(data.args[0].o), \"move_node\");\n                                }\n                            }\n                        }\n                        if(data.func == \"create_node\") {\n                            // obj, position, js, callback, is_loaded\n                            if(data.args[4] || this._is_loaded(data.args[0])) {\n                                p = this._get_node(data.args[0]);\n                                if(data.args[1] && (data.args[1] === \"before\" || data.args[1] === \"after\")) {\n                                    p = this._get_parent(data.args[0]);\n                                    if(!p || p === -1) { p = this.get_container(); }\n                                }\n                                if(typeof data.args[2] === \"string\") { nms.push(data.args[2]); }\n                                else if(!data.args[2] || !data.args[2].data) { nms.push(this._get_string(\"new_node\")); }\n                                else { nms.push(data.args[2].data); }\n                                res = this._check_unique(nms, p.find(\"> ul > li\"), \"create_node\");\n                            }\n                        }\n                        if(data.func == \"rename_node\") {\n                            // obj, val\n                            nms.push(data.args[1]);\n                            t = this._get_node(data.args[0]);\n                            p = this._get_parent(t);\n                            if(!p || p === -1) { p = this.get_container(); }\n                            res = this._check_unique(nms, p.find(\"> ul > li\").not(t), \"rename_node\");\n                        }\n                        if(!res) {\n                            e.stopPropagation();\n                            return false;\n                        }\n                    }, this));\n        },\n        defaults : { \n            error_callback : $.noop\n        },\n        _fn : { \n            _check_unique : function (nms, p, func) {\n                var cnms = [];\n                p.children(\"a\").each(function () { cnms.push($(this).text().replace(/^\\s+/g,\"\")); });\n                if(!cnms.length || !nms.length) { return true; }\n                cnms = cnms.sort().join(\",,\").replace(/(,|^)([^,]+)(,,\\2)+(,|$)/g,\"$1$2$4\").replace(/,,+/g,\",\").replace(/,$/,\"\").split(\",\");\n                if((cnms.length + nms.length) != cnms.concat(nms).sort().join(\",,\").replace(/(,|^)([^,]+)(,,\\2)+(,|$)/g,\"$1$2$4\").replace(/,,+/g,\",\").replace(/,$/,\"\").split(\",\").length) {\n                    this._get_settings().unique.error_callback.call(null, nms, p, func);\n                    return false;\n                }\n                return true;\n            },\n            check_move : function () {\n                if(!this.__call_old()) { return false; }\n                var p = this._get_move(), nms = [];\n                if(p.o && p.o.length) {\n                    p.o.children(\"a\").each(function () { nms.push($(this).text().replace(/^\\s+/g,\"\")); });\n                    return this._check_unique(nms, p.np.find(\"> ul > li\").not(p.o), \"check_move\");\n                }\n                return true;\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n/*\n * jsTree wholerow plugin\n * Makes select and hover work on the entire width of the node\n * MAY BE HEAVY IN LARGE DOM\n */\n(function ($) {\n    $.jstree.plugin(\"wholerow\", {\n        __init : function () {\n            if(!this.data.ui) { throw \"jsTree wholerow: jsTree UI plugin not included.\"; }\n            this.data.wholerow.html = false;\n            this.data.wholerow.to = false;\n            this.get_container()\n                .bind(\"init.jstree\", $.proxy(function (e, data) { \n                        this._get_settings().core.animation = 0;\n                    }, this))\n                .bind(\"open_node.jstree create_node.jstree clean_node.jstree loaded.jstree\", $.proxy(function (e, data) { \n                        this._prepare_wholerow_span( data && data.rslt && data.rslt.obj ? data.rslt.obj : -1 );\n                    }, this))\n                .bind(\"search.jstree clear_search.jstree reopen.jstree after_open.jstree after_close.jstree create_node.jstree delete_node.jstree clean_node.jstree\", $.proxy(function (e, data) { \n                        if(this.data.to) { clearTimeout(this.data.to); }\n                        this.data.to = setTimeout( (function (t, o) { return function() { t._prepare_wholerow_ul(o); }; })(this,  data && data.rslt && data.rslt.obj ? data.rslt.obj : -1), 0);\n                    }, this))\n                .bind(\"deselect_all.jstree\", $.proxy(function (e, data) { \n                        this.get_container().find(\" > .jstree-wholerow .jstree-clicked\").removeClass(\"jstree-clicked \" + (this.data.themeroller ? this._get_settings().themeroller.item_a : \"\" ));\n                    }, this))\n                .bind(\"select_node.jstree deselect_node.jstree \", $.proxy(function (e, data) { \n                        data.rslt.obj.each(function () { \n                            var ref = data.inst.get_container().find(\" > .jstree-wholerow li:visible:eq(\" + ( parseInt((($(this).offset().top - data.inst.get_container().offset().top + data.inst.get_container()[0].scrollTop) / data.inst.data.core.li_height),10)) + \")\");\n                            // ref.children(\"a\")[e.type === \"select_node\" ? \"addClass\" : \"removeClass\"](\"jstree-clicked\");\n                            ref.children(\"a\").attr(\"class\",data.rslt.obj.children(\"a\").attr(\"class\"));\n                        });\n                    }, this))\n                .bind(\"hover_node.jstree dehover_node.jstree\", $.proxy(function (e, data) { \n                        this.get_container().find(\" > .jstree-wholerow .jstree-hovered\").removeClass(\"jstree-hovered \" + (this.data.themeroller ? this._get_settings().themeroller.item_h : \"\" ));\n                        if(e.type === \"hover_node\") {\n                            var ref = this.get_container().find(\" > .jstree-wholerow li:visible:eq(\" + ( parseInt(((data.rslt.obj.offset().top - this.get_container().offset().top + this.get_container()[0].scrollTop) / this.data.core.li_height),10)) + \")\");\n                            // ref.children(\"a\").addClass(\"jstree-hovered\");\n                            ref.children(\"a\").attr(\"class\",data.rslt.obj.children(\".jstree-hovered\").attr(\"class\"));\n                        }\n                    }, this))\n                .delegate(\".jstree-wholerow-span, ins.jstree-icon, li\", \"click.jstree\", function (e) {\n                        var n = $(e.currentTarget);\n                        if(e.target.tagName === \"A\" || (e.target.tagName === \"INS\" && n.closest(\"li\").is(\".jstree-open, .jstree-closed\"))) { return; }\n                        n.closest(\"li\").children(\"a:visible:eq(0)\").click();\n                        e.stopImmediatePropagation();\n                    })\n                .delegate(\"li\", \"mouseover.jstree\", $.proxy(function (e) {\n                        e.stopImmediatePropagation();\n                        if($(e.currentTarget).children(\".jstree-hovered, .jstree-clicked\").length) { return false; }\n                        this.hover_node(e.currentTarget);\n                        return false;\n                    }, this))\n                .delegate(\"li\", \"mouseleave.jstree\", $.proxy(function (e) {\n                        if($(e.currentTarget).children(\"a\").hasClass(\"jstree-hovered\").length) { return; }\n                        this.dehover_node(e.currentTarget);\n                    }, this));\n            if(is_ie7 || is_ie6) {\n                $.vakata.css.add_sheet({ str : \".jstree-\" + this.get_index() + \" { position:relative; } \", title : \"jstree\" });\n            }\n        },\n        defaults : {\n        },\n        __destroy : function () {\n            this.get_container().children(\".jstree-wholerow\").remove();\n            this.get_container().find(\".jstree-wholerow-span\").remove();\n        },\n        _fn : {\n            _prepare_wholerow_span : function (obj) {\n                obj = !obj || obj == -1 ? this.get_container().find(\"> ul > li\") : this._get_node(obj);\n                if(obj === false) { return; } // added for removing root nodes\n                obj.each(function () {\n                    $(this).find(\"li\").andSelf().each(function () {\n                        var $t = $(this);\n                        if($t.children(\".jstree-wholerow-span\").length) { return true; }\n                        $t.prepend(\"<span class='jstree-wholerow-span' style='width:\" + ($t.parentsUntil(\".jstree\",\"li\").length * 18) + \"px;'>&#160;</span>\");\n                    });\n                });\n            },\n            _prepare_wholerow_ul : function () {\n                var o = this.get_container().children(\"ul\").eq(0), h = o.html();\n                o.addClass(\"jstree-wholerow-real\");\n                if(this.data.wholerow.last_html !== h) {\n                    this.data.wholerow.last_html = h;\n                    this.get_container().children(\".jstree-wholerow\").remove();\n                    this.get_container().append(\n                        o.clone().removeClass(\"jstree-wholerow-real\")\n                            .wrapAll(\"<div class='jstree-wholerow' />\").parent()\n                            .width(o.parent()[0].scrollWidth)\n                            .css(\"top\", (o.height() + ( is_ie7 ? 5 : 0)) * -1 )\n                            .find(\"li[id]\").each(function () { this.removeAttribute(\"id\"); }).end()\n                    );\n                }\n            }\n        }\n    });\n    $(function() {\n        var css_string = '' + \n            '.jstree .jstree-wholerow-real { position:relative; z-index:1; } ' + \n            '.jstree .jstree-wholerow-real li { cursor:pointer; } ' + \n            '.jstree .jstree-wholerow-real a { border-left-color:transparent !important; border-right-color:transparent !important; } ' + \n            '.jstree .jstree-wholerow { position:relative; z-index:0; height:0; } ' + \n            '.jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { width:100%; } ' + \n            '.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li, .jstree .jstree-wholerow a { margin:0 !important; padding:0 !important; } ' + \n            '.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { background:transparent !important; }' + \n            '.jstree .jstree-wholerow ins, .jstree .jstree-wholerow span, .jstree .jstree-wholerow input { display:none !important; }' + \n            '.jstree .jstree-wholerow a, .jstree .jstree-wholerow a:hover { text-indent:-9999px; !important; width:100%; padding:0 !important; border-right-width:0px !important; border-left-width:0px !important; } ' + \n            '.jstree .jstree-wholerow-span { position:absolute; left:0; margin:0px; padding:0; height:18px; border-width:0; padding:0; z-index:0; }';\n        if(is_ff2) {\n            css_string += '' + \n                '.jstree .jstree-wholerow a { display:block; height:18px; margin:0; padding:0; border:0; } ' + \n                '.jstree .jstree-wholerow-real a { border-color:transparent !important; } ';\n        }\n        if(is_ie7 || is_ie6) {\n            css_string += '' + \n                '.jstree .jstree-wholerow, .jstree .jstree-wholerow li, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow a { margin:0; padding:0; line-height:18px; } ' + \n                '.jstree .jstree-wholerow a { display:block; height:18px; line-height:18px; overflow:hidden; } ';\n        }\n        $.vakata.css.add_sheet({ str : css_string, title : \"jstree\" });\n    });\n})(jQuery);\n//*/\n\n/*\n* jsTree model plugin\n* This plugin gets jstree to use a class model to retrieve data, creating great dynamism\n*/\n(function ($) {\n    var nodeInterface = [\"getChildren\",\"getChildrenCount\",\"getAttr\",\"getName\",\"getProps\"],\n        validateInterface = function(obj, inter) {\n            var valid = true;\n            obj = obj || {};\n            inter = [].concat(inter);\n            $.each(inter, function (i, v) {\n                if(!$.isFunction(obj[v])) { valid = false; return false; }\n            });\n            return valid;\n        };\n    $.jstree.plugin(\"model\", {\n        __init : function () {\n            if(!this.data.json_data) { throw \"jsTree model: jsTree json_data plugin not included.\"; }\n            this._get_settings().json_data.data = function (n, b) {\n                var obj = (n == -1) ? this._get_settings().model.object : n.data(\"jstree_model\");\n                if(!validateInterface(obj, nodeInterface)) { return b.call(null, false); }\n                if(this._get_settings().model.async) {\n                    obj.getChildren($.proxy(function (data) {\n                        this.model_done(data, b);\n                    }, this));\n                }\n                else {\n                    this.model_done(obj.getChildren(), b);\n                }\n            };\n        },\n        defaults : {\n            object : false,\n            id_prefix : false,\n            async : false\n        },\n        _fn : {\n            model_done : function (data, callback) {\n                var ret = [], \n                    s = this._get_settings(),\n                    _this = this;\n\n                if(!$.isArray(data)) { data = [data]; }\n                $.each(data, function (i, nd) {\n                    var r = nd.getProps() || {};\n                    r.attr = nd.getAttr() || {};\n                    if(nd.getChildrenCount()) { r.state = \"closed\"; }\n                    r.data = nd.getName();\n                    if(!$.isArray(r.data)) { r.data = [r.data]; }\n                    if(_this.data.types && $.isFunction(nd.getType)) {\n                        r.attr[s.types.type_attr] = nd.getType();\n                    }\n                    if(r.attr.id && s.model.id_prefix) { r.attr.id = s.model.id_prefix + r.attr.id; }\n                    if(!r.metadata) { r.metadata = { }; }\n                    r.metadata.jstree_model = nd;\n                    ret.push(r);\n                });\n                callback.call(null, ret);\n            }\n        }\n    });\n})(jQuery);\n//*/\n\n})();\ndefine(\"thirdparty/jstree_pre1.0_fix_1/jquery.jstree\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * PreferenceStorage defines an interface for persisting preference data as\n * name/value pairs for a module or plugin.\n */\ndefine('preferences/PreferenceStorage',['require','exports','module','preferences/PreferencesManager'],function (require, exports, module) {\n    \n    \n    var PreferencesManager = require(\"preferences/PreferencesManager\");\n    \n    /**\n     * @private\n     * Validate JSON keys and values.\n     */\n    function _validateJSONPair(key, value) {\n        if (typeof key === \"string\") {\n            // validate temporary JSON\n            var temp = {},\n                error = null;\n            temp[key] = value;\n            \n            try {\n                temp = JSON.parse(JSON.stringify(temp));\n            } catch (err) {\n                error = err;\n            }\n            \n            // set value to JSON storage if no errors occurred\n            if (!error && (temp[key] !== undefined)) {\n                return true;\n            } else {\n                throw new Error(\"Value '\" + value + \"' for key '\" + key + \"' must be a valid JSON value\");\n            }\n        } else {\n            throw new Error(\"Preference key '\" + key + \"' must be a string\");\n        }\n    }\n    \n    /**\n     * @private\n     * Save to persistent storage.\n     */\n    function _commit() {\n        PreferencesManager.savePreferences();\n    }\n    \n    /**\n     * Creates a new PreferenceStorage object.\n     * @param {!string} clientID Unique identifier for PreferencesManager to\n     *  associate this PreferenceStorage data with.\n     * @param {!object} json JSON object to persist preference data.\n     */\n    function PreferenceStorage(clientID, json) {\n        this._clientID = clientID;\n        this._json = json;\n    }\n    \n    /**\n     * Unique clientID for this PreferenceStorage object.\n     * @return {!string} clientID\n     */\n    PreferenceStorage.prototype.getClientID = function () {\n        return this._clientID;\n    };\n    \n    /**\n     * Removes a preference from this PreferenceStorage object.\n     * @param {!string} key A unique identifier\n     */\n    PreferenceStorage.prototype.remove = function (key) {\n        // remove value from JSON storage\n        delete this._json[key];\n        _commit();\n    };\n    \n    /**\n     * Assigns a value for a key. Overwrites existing value if present.\n     * @param {!string} key A unique identifier\n     * @param {object} value A valid JSON value\n     */\n    PreferenceStorage.prototype.setValue = function (key, value) {\n        if (_validateJSONPair(key, value)) {\n            this._json[key] = value;\n            _commit();\n        }\n    };\n    \n    /**\n     * Retreive the value associated with the specified key.\n     * @param {!string} key Key name to lookup.\n     * @return {object} Returns the value for the key or undefined.\n     */\n    PreferenceStorage.prototype.getValue = function (key) {\n        return this._json[key];\n    };\n    \n    /**\n     * Return all name-value pairs as a single JSON object.\n     * @return {!object} JSON object containing name/value pairs for all keys\n     *  in this PreferenceStorage object.\n     */\n    PreferenceStorage.prototype.getAllValues = function () {\n        return JSON.parse(JSON.stringify(this._json));\n    };\n    \n    /**\n     * Writes name-value pairs from a JSON object as preference properties.\n     * Invalid JSON values throw an error and all changes are discarded.\n     *\n     * @param {!object} obj A JSON object with zero or more preference properties to write.\n     * @param {boolean} append Defaults to false. When true, properties in the JSON object\n     *  overwrite and/or append to the existing set of preference properties. When false,\n     *  all existing preferences are deleted before writing new properties from the JSON object.\n     */\n    PreferenceStorage.prototype.setAllValues = function (obj, append) {\n        var self = this,\n            error = null;\n        \n        // validate all name/value pairs before committing\n        $.each(obj, function (key, value) {\n            try {\n                _validateJSONPair(key, value);\n            } catch (err) {\n                // fail fast\n                error = err;\n                return false;\n            }\n        });\n        \n        // skip changes if any error is detected\n        if (error) {\n            throw error;\n        }\n        \n        // delete all exiting properties if not appending\n        if (!append) {\n            $.each(this._json, function (key, value) {\n                delete self._json[key];\n            });\n        }\n        \n        // copy properties from incoming JSON object\n        $.each(obj, function (key, value) {\n            self._json[key] = value;\n        });\n        \n        _commit();\n    };\n    \n    exports.PreferenceStorage = PreferenceStorage;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, localStorage */\n\n/**\n * PreferencesManager\n *\n */\ndefine('preferences/PreferencesManager',['require','exports','module','preferences/PreferenceStorage'],function (require, exports, module) {\n    \n    \n    var PreferenceStorage = require(\"preferences/PreferenceStorage\").PreferenceStorage;\n    \n    var PREFERENCES_KEY = \"com.adobe.brackets.preferences\";\n\n    // Private Properties\n    var preferencesKey,\n        prefStorage,\n        persistentStorage,\n        doLoadPreferences   = false;\n\n    /**\n     * Retreive preferences data for the given clientID.\n     *\n     * @param {string} clientID Unique identifier\n     * @param {string} defaults Default preferences stored as JSON\n     * @return {PreferenceStorage} \n     */\n    function getPreferenceStorage(clientID, defaults) {\n        if ((clientID === undefined) || (clientID === null)) {\n            throw new Error(\"Invalid clientID\");\n        }\n\n        var prefs = prefStorage[clientID];\n\n        if (prefs === undefined) {\n            // create a new empty preferences object\n            prefs = (defaults && JSON.stringify(defaults)) ? defaults : {};\n            prefStorage[clientID] = prefs;\n        }\n\n        return new PreferenceStorage(clientID, prefs);\n    }\n\n    /**\n     * Save all preference clients.\n     */\n    function savePreferences() {\n        // save all preferences\n        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));\n    }\n\n    /**\n     * @private\n     * Reset preferences and callbacks\n     */\n    function _reset() {\n        prefStorage = {};\n\n        // Note that storage.clear() is not used. Production and unit test code\n        // both rely on the same backing storage but unique item keys.\n        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));\n    }\n\n    /**\n     * @private\n     * Initialize persistent storage implementation\n     */\n    function _initStorage(storage) {\n        persistentStorage = storage;\n\n        if (doLoadPreferences) {\n            prefStorage = JSON.parse(persistentStorage.getItem(preferencesKey));\n        }\n\n        // initialize empty preferences if none were found in storage\n        if (!prefStorage) {\n            _reset();\n        }\n    }\n\n    // Check localStorage for a preferencesKey. Production and unit test keys\n    // are used to keep preferences separate within the same storage implementation.\n    preferencesKey = localStorage.getItem(\"preferencesKey\");\n\n    if (!preferencesKey) {\n        // use default key if none is found\n        preferencesKey = PREFERENCES_KEY;\n        doLoadPreferences = true;\n    } else {\n        // using a non-default key, check for additional settings\n        doLoadPreferences = !!(localStorage.getItem(\"doLoadPreferences\"));\n    }\n\n    // Use localStorage by default\n    _initStorage(localStorage);\n\n    // Public API\n    exports.getPreferenceStorage    = getPreferenceStorage;\n    exports.savePreferences         = savePreferences;\n\n    // Unit test use only\n    exports._reset                  = _reset;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n /**\n  * Manages global application commands that can be called from menu items, key bindings, or subparts\n  * of the application.\n  */\ndefine('command/CommandManager',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * Map of all registered global commands\n     * @type Object.<commandID: string, Command>\n     */\n    var _commands = {};\n    \n    /**\n     * Temporary copy of commands map for restoring after testing\n     * TODO (issue #1039): implement separate require contexts for unit tests\n     * @type Object.<commandID: string, Command>\n     */\n    var _commandsOriginal = {};\n    \n    /**\n     * @constructor\n     * @private\n     *\n     * @param {string} name - text that will be displayed in the UI to represent command\n     * @param {string} id\n     * @param {function} commandFn - the function that is called when the command is executed.\n     *\n     * TODO: where should this be triggered, The Command or Exports?\n     * Events:\n     *      enabledStateChange\n     *      checkedStateChange\n     *      keyBindingAdded\n     *      keyBindingRemoved\n     */\n    function Command(name, id, commandFn) {\n        this._name = name;\n        this._id = id;\n        this._commandFn = commandFn;\n        this._checked = undefined;\n        this._enabled = true;\n    }\n\n    /** @return {Command} */\n    Command.prototype.getID = function () {\n        return this._id;\n    };\n\n    /**\n     * Executes the command. Additional arguments are passed to the executing function\n     *\n     * @return {$.Promise} a jQuery promise that will be resolved when the command completes.\n     */\n    Command.prototype.execute = function () {\n        if (!this._enabled) {\n            return;\n        }\n        \n        var result = this._commandFn.apply(this, arguments);\n        if (!result) {\n            return (new $.Deferred()).resolve().promise();\n        } else {\n            return result;\n        }\n    };\n\n    /** @return {boolean} */\n    Command.prototype.getEnabled = function () {\n        return this._enabled;\n    };\n\n    /** \n     * Sets enabled state of Command and dispatches \"enabledStateChange\"\n     * when the enabled state changes.\n     * @param {boolean} enabled\n     */\n    Command.prototype.setEnabled = function (enabled) {\n        var changed = this._enabled !== enabled;\n        this._enabled = enabled;\n\n        if (changed) {\n            $(this).triggerHandler(\"enabledStateChange\");\n        }\n    };\n\n    /** \n     * Sets enabled state of Command and dispatches \"checkedStateChange\"\n     * when the enabled state changes.\n     * @param {boolean} checked\n     */\n    Command.prototype.setChecked = function (checked) {\n        var changed = this._checked !== checked;\n        this._checked = checked;\n\n        if (changed) {\n            $(this).triggerHandler(\"checkedStateChange\");\n        }\n    };\n\n    /** @return {boolean} */\n    Command.prototype.getChecked = function () {\n        return this._checked;\n    };\n\n    /**\n     * Sets the name of the Command and dispatches \"nameChange\" so that\n     * UI that reflects the command name can update.\n     * \n     * Note, a Command name can appear in either HTML or native UI\n     * so HTML tags should not be used. To add a Unicode character,\n     * use \\uXXXX instead of an HTML entity.\n     * \n     * @param {string} name\n     */\n    Command.prototype.setName = function (name) {\n        var changed = this._name !== name;\n        this._name = name;\n\n        if (changed) {\n            $(this).triggerHandler(\"nameChange\");\n        }\n    };\n\n    /** @return {string} */\n    Command.prototype.getName = function () {\n        return this._name;\n    };\n\n\n\n    /**\n     * Registers a global command.\n     * @param {string} name - text that will be displayed in the UI to represent command\n     * @param {string} id - unique identifier for command.\n     *      Core commands in Brackets use a simple command title as an id, for example \"open.file\".\n     *      Extensions should use the following format: \"author.myextension.mycommandname\". \n     *      For example, \"lschmitt.csswizard.format.css\".\n     * @param {function(...)} commandFn - the function to call when the command is executed. Any arguments passed to\n     *     execute() (after the id) are passed as arguments to the function. If the function is asynchronous,\n     *     it must return a jQuery promise that is resolved when the command completes. Otherwise, the\n     *     CommandManager will assume it is synchronous, and return a promise that is already resolved.\n     * @return {?Command}\n     */\n    function register(name, id, commandFn) {\n        if (_commands[id]) {\n            console.log(\"Attempting to register an already-registered command: \" + id);\n            return null;\n        }\n        if (!name || !id || !commandFn) {\n            throw new Error(\"Attempting to register a command with a missing name, id, or command function:\" + name + \" \" + id);\n        }\n\n        var command = new Command(name, id, commandFn);\n        _commands[id] = command;\n        return command;\n    }\n\n    /**\n     * Clear all commands for unit testing, but first make copy of commands so that\n     * they can be restored afterward\n     */\n    function _testReset() {\n        _commandsOriginal = _commands;\n        _commands = {};\n    }\n\n    /**\n     * Restore original commands after test and release copy\n     */\n    function _testRestore() {\n        _commands = _commandsOriginal;\n        _commandsOriginal = {};\n    }\n    \n    /**\n     * Retrieves a Command object by id\n     * @param {string} id\n     * @return {Command}\n     */\n    function get(id) {\n        return _commands[id];\n    }\n    \n    /**\n     * Returns the ids of all registered commands\n     * @return {Array.<string>}\n     */\n    function getAll() {\n        return Object.keys(_commands);\n    }\n\n    /**\n     * Looks up and runs a global command. Additional arguments are passed to the command.\n     *\n     * @param {string} id The ID of the command to run.\n     * @return {$.Promise} a jQuery promise that will be resolved when the command completes.\n     */\n    function execute(id) {\n        var command = _commands[id];\n        if (command) {\n            return command.execute.apply(command, Array.prototype.slice.call(arguments, 1));\n        } else {\n            return (new $.Deferred()).reject().promise();\n        }\n    }\n\n    // Define public API\n    exports.register        = register;\n    exports.execute         = execute;\n    exports.get             = get;\n    exports.getAll          = getAll;\n    exports._testReset      = _testReset;\n    exports._testRestore    = _testRestore;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\ndefine('command/Commands',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * List of constants for global command IDs.\n     */\n\n    // FILE\n    exports.FILE_NEW                    = \"file.new\";\n    exports.FILE_OPEN                   = \"file.open\";\n    exports.FILE_OPEN_FOLDER            = \"file.openFolder\";\n    exports.FILE_SAVE                   = \"file.save\";\n    exports.FILE_SAVE_ALL               = \"file.saveAll\";\n    exports.FILE_CLOSE                  = \"file.close\";\n    exports.FILE_CLOSE_ALL              = \"file.close_all\";\n    exports.FILE_CLOSE_WINDOW           = \"file.close_window\"; // string must MATCH string in native code (brackets_extensions)\n    exports.FILE_ADD_TO_WORKING_SET     = \"file.addToWorkingSet\";\n    exports.FILE_LIVE_FILE_PREVIEW      = \"file.liveFilePreview\";\n    exports.FILE_QUIT                   = \"file.quit\"; // string must MATCH string in native code (brackets_extensions)\n\n    // EDIT\n    exports.EDIT_UNDO                   = \"edit.undo\";\n    exports.EDIT_REDO                   = \"edit.redo\";\n    exports.EDIT_CUT                    = \"edit.cut\";\n    exports.EDIT_COPY                   = \"edit.copy\";\n    exports.EDIT_PASTE                  = \"edit.paste\";\n    exports.EDIT_SELECT_ALL             = \"edit.selectAll\";\n    exports.EDIT_FIND                   = \"edit.find\";\n    exports.EDIT_FIND_IN_FILES          = \"edit.findInFiles\";\n    exports.EDIT_FIND_NEXT              = \"edit.findNext\";\n    exports.EDIT_FIND_PREVIOUS          = \"edit.findPrevious\";\n    exports.EDIT_REPLACE                = \"edit.replace\";\n    exports.EDIT_INDENT                 = \"edit.indent\";\n    exports.EDIT_UNINDENT               = \"edit.unindent\";\n    exports.EDIT_DUPLICATE              = \"edit.duplicate\";\n    exports.EDIT_LINE_COMMENT           = \"edit.lineComment\";\n    exports.EDIT_LINE_UP                = \"edit.lineUp\";\n    exports.EDIT_LINE_DOWN              = \"edit.lineDown\";\n    exports.TOGGLE_USE_TAB_CHARS        = \"debug.useTabChars\";\n\n    // VIEW\n    exports.VIEW_HIDE_SIDEBAR           = \"view.toggleSidebar\";\n    exports.VIEW_INCREASE_FONT_SIZE     = \"view.increaseFontSize\";\n    exports.VIEW_DECREASE_FONT_SIZE     = \"view.decreaseFontSize\";\n    exports.VIEW_RESTORE_FONT_SIZE      = \"view.restoreFontSize\";\n    exports.TOGGLE_JSLINT               = \"debug.jslint\";\n    \n    // Navigate\n    exports.NAVIGATE_NEXT_DOC           = \"navigate.nextDoc\";\n    exports.NAVIGATE_PREV_DOC           = \"navigate.prevDoc\";\n    exports.NAVIGATE_QUICK_OPEN         = \"navigate.quickOpen\";\n    exports.NAVIGATE_GOTO_DEFINITION    = \"navigate.gotoDefinition\";\n    exports.NAVIGATE_GOTO_LINE          = \"navigate.gotoLine\";\n    exports.TOGGLE_QUICK_EDIT           = \"navigate.toggleQuickEdit\";\n    exports.QUICK_EDIT_NEXT_MATCH       = \"navigate.nextMatch\";\n    exports.QUICK_EDIT_PREV_MATCH       = \"navigate.previousMatch\";\n\n    // Debug\n    exports.DEBUG_REFRESH_WINDOW        = \"debug.refreshWindow\"; // string must MATCH string in native code (brackets_extensions)\n    exports.DEBUG_SHOW_DEVELOPER_TOOLS  = \"debug.showDeveloperTools\";\n    exports.DEBUG_RUN_UNIT_TESTS        = \"debug.runUnitTests\";\n    exports.DEBUG_SHOW_PERF_DATA        = \"debug.showPerfData\";\n    exports.DEBUG_NEW_BRACKETS_WINDOW   = \"debug.newBracketsWindow\";\n    exports.DEBUG_SHOW_EXT_FOLDER       = \"debug.showExtensionsFolder\";\n    exports.DEBUG_SWITCH_LANGUAGE       = \"debug.switchLanguage\";\n    exports.CHECK_FOR_UPDATE            = \"app.checkForUpdate\";\n\n    // Command that does nothing. Can be used for place holder menuItems\n    \n    exports.HELP_ABOUT                  = \"help.about\";\n\n    // File shell callbacks\n    exports.APP_ABORT_QUIT              = \"app.abort_quit\"; // string must MATCH string in native code (appshell_extensions)\n});\n\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */\n/*global define, $, brackets, window */\n\n/**\n * Manages the mapping of keyboard inputs to commands.\n */\ndefine('command/KeyBindingManager',['require','exports','module','command/CommandManager'],function (require, exports, module) {\n    \n\n    var CommandManager = require(\"command/CommandManager\");\n\n    /**\n     * Maps normalized shortcut descriptor to key binding info.\n     * @type {!Object.<string, {commandID: string, key: string, displayKey: string}>}\n     */\n    var _keyMap = {};\n\n    /**\n     * Maps commandID to the list of shortcuts that are bound to it.\n     * @type {!Object.<string, Array.<{key: string, displayKey: string}>>}\n     */\n    var _commandMap = {};\n\n    /**\n     * Allow clients to toggle key binding\n     */\n    var _enabled = true;\n\n    /**\n     * @private\n     */\n    function _reset() {\n        _keyMap = {};\n        _commandMap = {};\n    }\n\n    /**\n     * @private\n     * Initialize an empty keymap as the current keymap. It overwrites the current keymap if there is one.\n     * builds the keyDescriptor string from the given parts\n     * @param {boolean} hasCtrl Is Ctrl key enabled\n     * @param {boolean} hasAlt Is Alt key enabled\n     * @param {boolean} hasShift Is Shift key enabled\n     * @param {string} key The key that's pressed\n     * @return {string} The normalized key descriptor\n     */\n    function _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key) {\n        if (!key) {\n            console.log(\"KeyBindingManager _buildKeyDescriptor() - No key provided!\");\n            return \"\";\n        }\n        \n        var keyDescriptor = [];\n       \n        if (hasMacCtrl) {\n            keyDescriptor.push(\"Ctrl\");\n        }\n        if (hasAlt) {\n            keyDescriptor.push(\"Alt\");\n        }\n        if (hasShift) {\n            keyDescriptor.push(\"Shift\");\n        }\n\n        if (hasCtrl) {\n            // Windows display Ctrl first, Mac displays Command symbol last\n            if (brackets.platform === \"mac\") {\n                keyDescriptor.push(\"Cmd\");\n            } else {\n                keyDescriptor.unshift(\"Ctrl\");\n            }\n        }\n\n        keyDescriptor.push(key);\n        \n        return keyDescriptor.join(\"-\");\n    }\n    \n    \n    /**\n     * normalizes the incoming key descriptor so the modifier keys are always specified in the correct order\n     * @param {string} The string for a key descriptor, can be in any order, the result will be Ctrl-Alt-Shift-<Key>\n     * @return {string} The normalized key descriptor or null if the descriptor invalid\n     */\n    function normalizeKeyDescriptorString(origDescriptor) {\n        var hasMacCtrl = false,\n            hasCtrl = false,\n            hasAlt = false,\n            hasShift = false,\n            key = \"\",\n            error = false;\n\n        function _compareModifierString(left, right, previouslyFound, origDescriptor) {\n            if (!left || !right) {\n                return false;\n            }\n            left = left.trim().toLowerCase();\n            right = right.trim().toLowerCase();\n            var matched = (left.length > 0 && left === right);\n            if (matched && previouslyFound) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Modifier defined twice: \" + origDescriptor);\n            }\n            return matched;\n        }\n        \n        origDescriptor.split(\"-\").forEach(function parseDescriptor(ele, i, arr) {\n            if (_compareModifierString(\"ctrl\", ele, hasCtrl)) {\n                if (brackets.platform === \"mac\") {\n                    hasMacCtrl = true;\n                } else {\n                    hasCtrl = true;\n                }\n            } else if (_compareModifierString(\"cmd\", ele, hasCtrl, origDescriptor)) {\n                hasCtrl = true;\n            } else if (_compareModifierString(\"alt\", ele, hasAlt, origDescriptor)) {\n                hasAlt = true;\n            } else if (_compareModifierString(\"opt\", ele, hasAlt, origDescriptor)) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Opt getting mapped to Alt from: \" + origDescriptor);\n                hasAlt = true;\n            } else if (_compareModifierString(\"shift\", ele, hasShift, origDescriptor)) {\n                hasShift = true;\n            } else if (key.length > 0) {\n                console.log(\"KeyBindingManager normalizeKeyDescriptorString() - Multiple keys defined. Using key: \" + key + \" from: \" + origDescriptor);\n                error = true;\n            } else {\n                key = ele;\n            }\n        });\n        \n        if (error) {\n            return null;\n        }\n\n        // Check to see if the binding is for \"-\".\n        if (key === \"\" && origDescriptor.search(/^.+--$/) !== -1) {\n            key = \"-\";\n        }\n        \n        // '+' char is valid if it's the only key. Keyboard shortcut strings should use\n        // unicode characters (unescaped). Keyboard shortcut display strings may use\n        // unicode escape sequences (e.g. \\u20AC euro sign)\n        if ((key.indexOf(\"+\")) >= 0 && (key.length > 1)) {\n            return null;\n        }\n        \n        return _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key);\n    }\n    \n    /**\n     * @private\n     * Looks for keycodes that have os-inconsistent keys and fixes them.\n     * @param {number} The keycode from the keyboard event.\n     * @param {string} The current best guess at what the key is.\n     * @return {string} If the key is OS-inconsistent, the correct key; otherwise, the original key.\n     **/\n    function _mapKeycodeToKey(keycode, key) {\n        switch (keycode) {\n        case 186:\n            return \";\";\n        case 187:\n            return \"=\";\n        case 188:\n            return \",\";\n        case 189:\n            return \"-\";\n        case 190:\n            return \".\";\n        case 191:\n            return \"/\";\n        case 192:\n            return \"`\";\n        case 219:\n            return \"[\";\n        case 220:\n            return \"\\\\\";\n        case 221:\n            return \"]\";\n        case 222:\n            return \"'\";\n        default:\n            return key;\n        }\n    }\n    \n    /**\n     * Takes a keyboard event and translates it into a key in a key map\n     */\n    function _translateKeyboardEvent(event) {\n        var hasMacCtrl = (brackets.platform === \"win\") ? false : (event.ctrlKey),\n            hasCtrl = (brackets.platform === \"win\") ? (event.ctrlKey) : (event.metaKey),\n            hasAlt = (event.altKey),\n            hasShift = (event.shiftKey),\n            key = String.fromCharCode(event.keyCode);\n        \n        //From the W3C, if we can get the KeyboardEvent.keyIdentifier then look here\n        //As that will let us use keys like then function keys \"F5\" for commands. The\n        //full set of values we can use is here\n        //http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set\n        var ident = event.keyIdentifier;\n        if (ident) {\n            if (ident.charAt(0) === \"U\" && ident.charAt(1) === \"+\") {\n                //This is a unicode code point like \"U+002A\", get the 002A and use that\n                key = String.fromCharCode(parseInt(ident.substring(2), 16));\n            } else {\n                //This is some non-character key, just use the raw identifier\n                key = ident;\n            }\n        }\n        \n        // Translate some keys to their common names\n        if (key === \"\\t\") {\n            key = \"Tab\";\n        } else if (key === \" \") {\n            key = \"Space\";\n        } else {\n            key = _mapKeycodeToKey(event.keyCode, key);\n        }\n\n        return _buildKeyDescriptor(hasMacCtrl, hasCtrl, hasAlt, hasShift, key);\n    }\n    \n    /**\n     * Convert normalized key representation to display appropriate for platform.\n     * @param {!string} descriptor Normalized key descriptor.\n     * @return {!string} Display/Operating system appropriate string\n     */\n    function formatKeyDescriptor(descriptor) {\n        var displayStr;\n        \n        if (brackets.platform === \"mac\") {\n            displayStr = descriptor.replace(/-/g, \"\");          // remove dashes\n            displayStr = displayStr.replace(\"Ctrl\", \"\\u2303\");  // Ctrl > control symbol\n            displayStr = displayStr.replace(\"Cmd\", \"\\u2318\");   // Cmd > command symbol\n            displayStr = displayStr.replace(\"Shift\", \"\\u21E7\"); // Shift > shift symbol\n            displayStr = displayStr.replace(\"Alt\", \"\\u2325\");   // Alt > option symbol\n        } else {\n            displayStr = descriptor.replace(/-/g, \"+\");\n        }\n\n        return displayStr;\n    }\n\n    /**\n     * @private\n     * @param {string} A normalized key-description string.\n     * @return {boolean} true if the key is already assigned, false otherwise.\n     */\n    function _isKeyAssigned(key) {\n        return (_keyMap[key] !== undefined);\n    }\n\n    /**\n     * @private\n     *\n     * @param {string} commandID\n     * @param {string|{{key: string, displayKey: string}}} keyBinding - a single shortcut.\n     * @param {?string} platform - undefined indicates all platforms\n     * @return {?{key: string, displayKey:String}} Returns a record for valid key bindings\n     */\n    function _addBinding(commandID, keyBinding, platform) {\n        var key,\n            result = null,\n            normalized,\n            normalizedDisplay,\n            explicitPlatform = keyBinding.platform || platform,\n            targetPlatform = explicitPlatform || brackets.platform,\n            command;\n        \n        // skip if this binding doesn't match the current platform\n        if (targetPlatform !== brackets.platform) {\n            return null;\n        }\n        \n        key = (keyBinding.key) || keyBinding;\n        if (brackets.platform === \"mac\" && explicitPlatform === undefined) {\n            key = key.replace(\"Ctrl\", \"Cmd\");\n            if (keyBinding.displayKey !== undefined) {\n                keyBinding.displayKey = keyBinding.displayKey.replace(\"Ctrl\", \"Cmd\");\n            }\n        }\n        normalized = normalizeKeyDescriptorString(key);\n        \n        // skip if the key binding is invalid \n        if (!normalized) {\n            console.log(\"Failed to normalize \" + key);\n            return null;\n        }\n        \n        // skip if the key is already assigned\n        if (_isKeyAssigned(normalized)) {\n            console.log(\"Cannot assign \" + normalized + \" to \" + commandID +\n                        \". It is already assigned to \" + _keyMap[normalized]);\n            return null;\n        }\n        \n        // optional display-friendly string (e.g. CMD-+ instead of CMD-=)\n        normalizedDisplay = (keyBinding.displayKey) ? normalizeKeyDescriptorString(keyBinding.displayKey) : normalized;\n        \n        // 1-to-many commandID mapping to key binding\n        if (!_commandMap[commandID]) {\n            _commandMap[commandID] = [];\n        }\n        \n        result = {key: normalized, displayKey: normalizedDisplay};\n        _commandMap[commandID].push(result);\n        \n        // 1-to-1 key binding to commandID\n        _keyMap[normalized] = {commandID: commandID, key: normalized, displayKey: normalizedDisplay};\n        \n        // notify listeners\n        command = CommandManager.get(commandID);\n        \n        if (command) {\n            $(command).triggerHandler(\"keyBindingAdded\", [result]);\n        }\n        \n        return result;\n    }\n\n    /**\n     * Returns a copy of the keymap\n     * @returns {!Object.<string, {commandID: string, key: string, displayKey: string}>}\n     */\n    function getKeymap() {\n        return $.extend({}, _keyMap);\n    }\n\n    /**\n     * Process the keybinding for the current key.\n     *\n     * @param {string} A key-description string.\n     * @return {boolean} true if the key was processed, false otherwise\n     */\n    function handleKey(key) {\n        if (_enabled && _keyMap[key]) {\n            CommandManager.execute(_keyMap[key].commandID);\n            return true;\n        }\n        return false;\n    }\n\n    // TODO (issue #414): Replace this temporary fix with a more robust solution to handle focus and modality\n    /**\n     * Enable or disable key bindings. Clients such as dialogs may wish to disable \n     * global key bindings temporarily.\n     *\n     * @param {string} A key-description string.\n     * @return {boolean} true if the key was processed, false otherwise\n     */\n    function setEnabled(value) {\n        _enabled = value;\n    }\n\n    /**\n     * Add one or more key bindings to a particular Command.\n     * \n     * @param {!string} commandID\n     * @param {?({key: string, displayKey: string} | Array.<{key: string, displayKey: string, platform: string)}>}  keyBindings - a single key binding\n     *      or an array of keybindings. Example: \"Shift-Cmd-F\". Mac and Win key equivalents are automatically\n     *      mapped to each other. Use displayKey property to display a different string (e.g. \"CMD+\" instead of \"CMD=\").\n     * @param {?string} platform - the target OS of the keyBindings either \"mac\" or \"win\". If undefined, all platforms will use\n     *      the key binding. Ignored if keyBindings is passed an Array.\n     * @return {{key: string, displayKey:String}|Array.<{key: string, displayKey:String}>} Returns record(s) for valid key binding(s)\n     */\n    function addBinding(commandID, keyBindings, platform) {\n        if ((commandID === null) || (commandID === undefined) || !keyBindings) {\n            return;\n        }\n        \n        var normalizedBindings = [],\n            targetPlatform,\n            results;\n\n        if (Array.isArray(keyBindings)) {\n            var keyBinding;\n            results = [];\n                                            \n            keyBindings.forEach(function (keyBindingRequest) {\n                keyBinding = _addBinding(commandID, keyBindingRequest, keyBindingRequest.platform);\n                \n                if (keyBinding) {\n                    results.push(keyBinding);\n                }\n            });\n        } else {\n            results = _addBinding(commandID, keyBindings, platform);\n        }\n        \n        return results;\n    }\n\n    /**\n     * Remove a key binding from _keymap\n     *\n     * @param {!string} key - a key-description string that may or may not be normalized.\n     * @param {?string} platform - OS from which to remove the binding (all platforms if unspecified)\n     */\n    function removeBinding(key, platform) {\n        if (!key || ((platform !== null) && (platform !== undefined) && (platform !== brackets.platform))) {\n            return;\n        }\n\n        var normalizedKey = normalizeKeyDescriptorString(key);\n        \n        if (!normalizedKey) {\n            console.log(\"Fail to nomalize \" + key);\n        } else if (_isKeyAssigned(normalizedKey)) {\n            var binding = _keyMap[normalizedKey],\n                command = CommandManager.get(binding.commandID),\n                bindings = _commandMap[binding.commandID];\n            \n            // delete key binding record\n            delete _keyMap[normalizedKey];\n            \n            if (bindings) {\n                // delete mapping from command to key binding\n                _commandMap[binding.commandID] = bindings.filter(function (b) {\n                    return (b.key !== normalizedKey);\n                });\n    \n                if (command) {\n                    $(command).triggerHandler(\"keyBindingRemoved\", [{key: normalizedKey, displayKey: binding.displayKey}]);\n                }\n            }\n        }\n    }\n    \n    /**\n     * Retrieve key bindings currently associated with a command\n     *\n     * @param {!string} command - A command ID\n     * @return {!Array.<{{key: string, displayKey: string}}>} An array of associated key bindings.\n     */\n    function getKeyBindings(commandID) {\n        var bindings = _commandMap[commandID];\n        return bindings || [];\n    }\n\n    /**\n     * Install keydown event listener.\n     */\n    function init() {\n        // init\n        window.document.body.addEventListener(\n            \"keydown\",\n            function (event) {\n                if (handleKey(_translateKeyboardEvent(event))) {\n                    event.stopPropagation();\n                }\n            },\n            true\n        );\n    }\n\n    // unit test only\n    exports._reset = _reset;\n\n    // Define public API\n    exports.init = init;\n    exports.getKeymap = getKeymap;\n    exports.handleKey = handleKey;\n    exports.setEnabled = setEnabled;\n    exports.addBinding = addBinding;\n    exports.removeBinding = removeBinding;\n    exports.formatKeyDescriptor = formatKeyDescriptor;\n    exports.getKeyBindings = getKeyBindings;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window */\n\n/**\n * Utilities for creating and managing standard modal dialogs.\n */\ndefine('widgets/Dialogs',['require','exports','module','command/KeyBindingManager'],function (require, exports, module) {\n    \n    \n    var KeyBindingManager = require(\"command/KeyBindingManager\");\n\n    var DIALOG_BTN_CANCEL = \"cancel\",\n        DIALOG_BTN_OK = \"ok\",\n        DIALOG_BTN_DONTSAVE = \"dontsave\",\n        DIALOG_CANCELED = \"_canceled\",\n        DIALOG_BTN_DOWNLOAD = \"download\";\n    \n    // TODO: (issue #258) In future, we should templatize the HTML for the dialogs rather than having \n    // it live directly in the HTML.\n    var DIALOG_ID_ERROR = \"error-dialog\",\n        DIALOG_ID_SAVE_CLOSE = \"save-close-dialog\",\n        DIALOG_ID_EXT_CHANGED = \"ext-changed-dialog\",\n        DIALOG_ID_EXT_DELETED = \"ext-deleted-dialog\",\n        DIALOG_ID_LIVE_DEVELOPMENT = \"live-development-error-dialog\",\n        DIALOG_ID_ABOUT = \"about-dialog\",\n        DIALOG_ID_UPDATE = \"update-dialog\";\n\n    function _dismissDialog(dlg, buttonId) {\n        dlg.data(\"buttonId\", buttonId);\n        dlg.modal(true).hide();\n    }\n    \n    function _hasButton(dlg, buttonId) {\n        return dlg.find(\"[data-button-id='\" + buttonId + \"']\");\n    }\n\n    var _handleKeyDown = function (e) {\n        var primaryBtn = this.find(\".primary\"),\n            buttonId = null,\n            which = String.fromCharCode(e.which);\n        \n        if (e.which === 13) {\n            // Click primary button\n            if (primaryBtn) {\n                buttonId = primaryBtn.attr(\"data-button-id\");\n            }\n        } else if (e.which === 32) {\n            // Space bar on focused button\n            this.find(\".dialog-button:focus\").click();\n        } else if (brackets.platform === \"mac\") {\n            // CMD+D Don't Save\n            if (e.metaKey && (which === \"D\")) {\n                if (_hasButton(this, DIALOG_BTN_DONTSAVE)) {\n                    buttonId = DIALOG_BTN_DONTSAVE;\n                }\n            // FIXME (issue #418) CMD+. Cancel swallowed by native shell\n            } else if (e.metaKey && (e.which === 190)) {\n                buttonId = DIALOG_BTN_CANCEL;\n            }\n        } else { // if (brackets.platform === \"win\") {\n            // 'N' Don't Save\n            if (which === \"N\") {\n                if (_hasButton(this, DIALOG_BTN_DONTSAVE)) {\n                    buttonId = DIALOG_BTN_DONTSAVE;\n                }\n            }\n        }\n        \n        if (buttonId) {\n            _dismissDialog(this, buttonId);\n        } else if (!($.contains(this.get(0), e.target)) ||\n                  ($(e.target).filter(\":input\").length === 0)) {\n            // Stop the event if the target is not inside the dialog\n            // or if the target is not a form element.\n            // TODO (issue #414): more robust handling of dialog scoped\n            //                    vs. global key bindings\n            e.stopPropagation();\n            e.preventDefault();\n        }\n    };\n    \n    /**\n     * General purpose modal dialog. Assumes that:\n     * -- the root tag of the dialog is marked with a unique class name (passed as dlgClass), as well as the\n     *    classes \"template modal hide\".\n     * -- the HTML for the dialog contains elements with \"title\" and \"message\" classes, as well as a number \n     *    of elements with \"dialog-button\" class, each of which has a \"data-button-id\".\n     *\n     * @param {string} dlgClass The class of the dialog node in the HTML.\n     * @param {string=} title The title of the error dialog. Can contain HTML markup. If unspecified, title in\n     *      the HTML template is used unchanged.\n     * @param {string=} message The message to display in the error dialog. Can contain HTML markup. If\n     *      unspecified, body in the HTML template is used unchanged.\n     * @return {$.Promise} a promise that will be resolved with the ID of the clicked button when the dialog\n     *     is dismissed. Never rejected.\n     */\n    function showModalDialog(dlgClass, title, message) {\n        var result = $.Deferred(),\n            promise = result.promise();\n        \n        // We clone the HTML rather than using it directly so that if two dialogs of the same\n        // type happen to show up, they can appear at the same time. (This is an edge case that\n        // shouldn't happen often, but we can't prevent it from happening since everything is\n        // asynchronous.)\n        var $dlg = $(\".\" + dlgClass + \".template\")\n            .clone()\n            .removeClass(\"template\")\n            .addClass(\"instance\")\n            .appendTo(window.document.body);\n        \n        if ($dlg.length === 0) {\n            throw new Error(\"Dialog id \" + dlgClass + \" does not exist\");\n        }\n\n        // Save the dialog promise for unit tests\n        $dlg.data(\"promise\", promise);\n\n        // Set title and message\n        if (title) {\n            $(\".dialog-title\", $dlg).html(title);\n        }\n        if (message) {\n            $(\".dialog-message\", $dlg).html(message);\n        }\n\n        var handleKeyDown = _handleKeyDown.bind($dlg);\n\n        // Pipe dialog-closing notification back to client code\n        $dlg.one(\"hidden\", function () {\n            var buttonId = $dlg.data(\"buttonId\");\n            if (!buttonId) {    // buttonId will be undefined if closed via Bootstrap's \"x\" button\n                buttonId = DIALOG_BTN_CANCEL;\n            }\n            \n            // Let call stack return before notifying that dialog has closed; this avoids issue #191\n            // if the handler we're triggering might show another dialog (as long as there's no\n            // fade-out animation)\n            window.setTimeout(function () {\n                result.resolve(buttonId);\n            }, 0);\n            \n            // Remove the dialog instance from the DOM.\n            $dlg.remove();\n\n            // Remove keydown event handler\n            window.document.body.removeEventListener(\"keydown\", handleKeyDown, true);\n            KeyBindingManager.setEnabled(true);\n        }).one(\"shown\", function () {\n            // Set focus to the default button\n            var primaryBtn = $dlg.find(\".primary\");\n\n            if (primaryBtn) {\n                primaryBtn.focus();\n            }\n\n            // Listen for dialog keyboard shortcuts\n            window.document.body.addEventListener(\"keydown\", handleKeyDown, true);\n            KeyBindingManager.setEnabled(false);\n        });\n        \n        // Click handler for buttons\n        $dlg.one(\"click\", \".dialog-button\", function (e) {\n            _dismissDialog($dlg, $(this).attr(\"data-button-id\"));\n        });\n\n        // Run the dialog\n        $dlg.modal({\n            backdrop: \"static\",\n            show: true,\n            keyboard: true\n        });\n\n        return promise;\n    }\n    \n    /**\n     * Immediately closes any dialog instances with the given class. The dialog callback for each instance will \n     * be called with the special buttonId DIALOG_CANCELED (note: callback is run asynchronously).\n     */\n    function cancelModalDialogIfOpen(dlgClass) {\n        $(\".\" + dlgClass + \".instance\").each(function (index, dlg) {\n            if ($(dlg).is(\":visible\")) {   // Bootstrap breaks if try to hide dialog that's already hidden\n                _dismissDialog($(dlg), DIALOG_CANCELED);\n            }\n        });\n    }\n    \n    exports.DIALOG_BTN_CANCEL = DIALOG_BTN_CANCEL;\n    exports.DIALOG_BTN_OK = DIALOG_BTN_OK;\n    exports.DIALOG_BTN_DONTSAVE = DIALOG_BTN_DONTSAVE;\n    exports.DIALOG_CANCELED = DIALOG_CANCELED;\n    exports.DIALOG_BTN_DOWNLOAD = DIALOG_BTN_DOWNLOAD;\n    \n    exports.DIALOG_ID_ERROR = DIALOG_ID_ERROR;\n    exports.DIALOG_ID_SAVE_CLOSE = DIALOG_ID_SAVE_CLOSE;\n    exports.DIALOG_ID_EXT_CHANGED = DIALOG_ID_EXT_CHANGED;\n    exports.DIALOG_ID_EXT_DELETED = DIALOG_ID_EXT_DELETED;\n    exports.DIALOG_ID_LIVE_DEVELOPMENT = DIALOG_ID_LIVE_DEVELOPMENT;\n    exports.DIALOG_ID_ABOUT = DIALOG_ID_ABOUT;\n    exports.DIALOG_ID_UPDATE = DIALOG_ID_UPDATE;\n    \n    exports.showModalDialog = showModalDialog;\n    exports.cancelModalDialogIfOpen = cancelModalDialogIfOpen;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, brackets, $, window */\n\n/**\n * This is a collection of utility functions for gathering performance data.\n */\ndefine('utils/PerfUtils',['require','exports','module'],function (require, exports, module) {\n    \n\n    /**\n     * Flag to enable/disable performance data gathering. Default is true (enabled)\n     * @type {boolean} enabled\n     */\n    var enabled = true;\n    \n    /**\n     * Peformance data is stored in this hash object. The key is the name of the\n     * test (passed to markStart/addMeasurement), and the value is the time, in \n     * milliseconds, that it took to run the test. If multiple runs of the same test\n     * are made, the value is an Array with each run stored as an entry in the Array.\n     */\n    var perfData = {};\n    \n    /**\n     * Active tests. This is a hash of all tests that have had markStart() called,\n     * but have not yet had addMeasurement() called.\n     */\n    var activeTests = {};\n\n    /**\n     * Updatable tests. This is a hash of all tests that have had markStart() called,\n     * and have had updateMeasurement() called. Caller must explicitly remove tests\n     * from this list using finalizeMeasurement()\n     */\n    var updatableTests = {};\n    \n    /**\n     * Hash of measurement IDs\n     */\n    var perfMeasurementIds = {};\n    \n    /**\n     * @private\n     * A unique key to log performance data\n     *\n     * @param {!string} id Unique ID for this measurement name\n     * @param {!name} name A short name for this measurement\n     */\n    function PerfMeasurement(id, name) {\n        this.id = id;\n        this.name = name;\n    }\n    \n    /**\n     * Create a new PerfMeasurement key. Adds itself to the module export.\n     * Can be accessed on the module, e.g. PerfUtils.MY_PERF_KEY.\n     *\n     * @param {!string} id Unique ID for this measurement name\n     * @param {!name} name A short name for this measurement\n     */\n    function createPerfMeasurement(id, name) {\n        if (perfMeasurementIds[id]) {\n            throw new Error(\"Performance measurement \" + id + \" is already defined\");\n        }\n        \n        var pm = new PerfMeasurement(id, name);\n        exports[id] = pm;\n        \n        return pm;\n    }\n    \n    /**\n     * @private\n     * Convert a PerfMeasurement instance to it's id. Otherwise uses the string name for backwards compatibility.\n     */\n    function toMeasurementId(o) {\n        return (o instanceof PerfMeasurement) ? o.id : o;\n    }\n    \n    /**\n     * @private\n     * Helper function for markStart()\n     *\n     * @param {string} name  Timer name.\n     * @param {number} time  Timer start time.\n     */\n    function _markStart(name, time) {\n        if (activeTests[name]) {\n            throw new Error(\"Recursive tests with the same name are not supported. Timer name: \" + name);\n        }\n        \n        activeTests[name] = { startTime: time };\n    }\n    \n    /**\n     * Start a new named timer. The name should be as descriptive as possible, since\n     * this name will appear as an entry in the performance report. \n     * For example: \"Open file: /Users/brackets/src/ProjectManager.js\"\n     *\n     * Multiple timers can be opened simultaneously, but all open timers must have\n     * a unique name.\n     *\n     * @param {(string|Array.<string>)} name  Single name or an Array of names.\n     * @returns {string} timer name. Returned for convenience to store and use\n     *      for calling addMeasure(). Since name is often creating via concatenating\n     *      strings this return value allows clients to construct the name once.\n     */\n    function markStart(name) {\n        if (!enabled) {\n            return;\n        }\n\n        var time = brackets.app.getElapsedMilliseconds();\n        name = toMeasurementId(name);\n\n        // Array of names can be passed in to have multiple timers with same start time\n        if (Array.isArray(name)) {\n            var i;\n            for (i = 0; i < name.length; i++) {\n                _markStart(name[i], time);\n            }\n        } else {\n            _markStart(name, time);\n        }\n\n        return name;\n    }\n    \n    /**\n     * Stop a timer and add its measurements to the performance data.\n     *\n     * Multiple measurements can be stored for any given name. If there are\n     * multiple values for a name, they are stored in an Array.\n     *\n     * If markStart() was not called for the specified timer, the\n     * measured time is relative to app startup.\n     *\n     * @param {string} name  Timer name.\n     */\n    function addMeasurement(name) {\n        if (!enabled) {\n            return;\n        }\n\n        var elapsedTime = brackets.app.getElapsedMilliseconds();\n        name = toMeasurementId(name);\n        \n        if (activeTests[name]) {\n            elapsedTime -= activeTests[name].startTime;\n            delete activeTests[name];\n        }\n        \n        if (perfData[name]) {\n            // We have existing data, add to it\n            if (Array.isArray(perfData[name])) {\n                perfData[name].push(elapsedTime);\n            } else {\n                // Current data is a number, convert to Array\n                perfData[name] = [perfData[name], elapsedTime];\n            }\n        } else {\n            perfData[name] = elapsedTime;\n        }\n\n        // Real time logging\n        //console.log(name + \" \" + elapsedTime);\n    }\n\n    /**\n     * This function is similar to addMeasurement(), but it allows timing the\n     * *last* event, when you don't know which event will be the last one.\n     *\n     * Tests that are in the activeTests list, have not yet been added, so add\n     * measurements to the performance data, and move test to updatableTests list.\n     * A test is moved to the updatable list so that it no longer passes isActive().\n     *\n     * Tests that are already in the updatableTests list are updated.\n     *\n     * Caller must explicitly remove test from the updatableTests list using\n     * finalizeMeasurement().\n     *\n     * If markStart() was not called for the specified timer, there is no way to\n     * determine if this is the first or subsequent call, so the measurement is\n     * not updatable, and it is handled in addMeasurement().\n     *\n     * @param {string} name  Timer name.\n     */\n    function updateMeasurement(name) {\n        var elapsedTime = brackets.app.getElapsedMilliseconds();\n\n        name = toMeasurementId(name);\n\n        if (updatableTests[name]) {\n            // update existing measurement\n            elapsedTime -= updatableTests[name].startTime;\n            \n            // update\n            if (perfData[name] && Array.isArray(perfData[name])) {\n                // We have existing data and it's an array, so update the last entry\n                perfData[name][perfData[name].length - 1] = elapsedTime;\n            } else {\n                // No current data or a single entry, so set/update it\n                perfData[name] = elapsedTime;\n            }\n            \n        } else {\n            // not yet in updatable list\n\n            if (activeTests[name]) {\n                // save startTime in updatable list before addMeasurement() deletes it\n                updatableTests[name] = { startTime: activeTests[name].startTime };\n            }\n            \n            // let addMeasurement() handle the initial case\n            addMeasurement(name);\n        }\n    }\n\n    /**\n     * Remove timer from lists so next action starts a new measurement\n     * \n     * updateMeasurement may not have been called, so timer may be\n     * in either or neither list, but should never be in both.\n     *\n     * @param {string} name  Timer name.\n     */\n    function finalizeMeasurement(name) {\n\n        name = toMeasurementId(name);\n\n        if (activeTests[name]) {\n            delete activeTests[name];\n        }\n\n        if (updatableTests[name]) {\n            delete updatableTests[name];\n        }\n    }\n    \n    /**\n     * Returns whether a timer is active or not, where \"active\" means that\n     * timer has been started with addMark(), but has not been added to perfdata\n     * with addMeasurement().\n     *\n     * @param {string} name  Timer name.\n     * @return {boolean} Whether a timer is active or not.\n     */\n    function isActive(name) {\n        return (activeTests[name]) ? true : false;\n    }\n\n    /**\n      * Returns the performance data as a tab deliminted string\n      * @returns {string}\n      */\n    function getDelimitedPerfData() {\n        var getValue = function (entry) {\n            // return single value, or tab deliminted values for an array\n            if (Array.isArray(entry)) {\n                var i, values = \"\";\n                 \n                for (i = 0; i < entry.length; i++) {\n                    values += entry[i];\n                    if (i < entry.length - 1) {\n                        values += \", \";\n                    }\n                }\n                return values;\n            } else {\n                return entry;\n            }\n        };\n\n        var testName,\n            index,\n            result = \"\";\n        $.each(perfData, function (testName, entry) {\n            result += getValue(entry) + \"\\t\" + testName + \"\\n\";\n        });\n\n        return result;\n    }\n    \n    /**\n     * Returns the measured value for the given measurement name.\n     * @param {string|PerfMeasurement} name The measurement to retreive.\n     */\n    function getData(name) {\n        if (!name) {\n            return perfData;\n        }\n        \n        return perfData[toMeasurementId(name)];\n    }\n    \n    function searchData(regExp) {\n        var keys = Object.keys(perfData).filter(function (key) {\n            return regExp.test(key);\n        });\n        \n        var datas = [];\n        \n        keys.forEach(function (key) {\n            datas.push(perfData[key]);\n        });\n        \n        return datas;\n    }\n    \n    /**\n     * Clear all logs including metric data and active tests.\n     */\n    function clear() {\n        perfData = {};\n        activeTests = {};\n        updatableTests = {};\n    }\n    \n    // create performance measurement constants\n    createPerfMeasurement(\"INLINE_EDITOR_OPEN\", \"Open inline editor\");\n    createPerfMeasurement(\"INLINE_EDITOR_CLOSE\", \"Close inline editor\");\n    \n    // extensions may create additional measurement constants during their lifecycle\n\n    exports.addMeasurement          = addMeasurement;\n    exports.finalizeMeasurement     = finalizeMeasurement;\n    exports.isActive                = isActive;\n    exports.markStart               = markStart;\n    exports.getData                 = getData;\n    exports.searchData              = searchData;\n    exports.updateMeasurement       = updateMeasurement;\n    exports.getDelimitedPerfData    = getDelimitedPerfData;\n    exports.createPerfMeasurement   = createPerfMeasurement;\n    exports.clear                   = clear;\n});\n\n/**\n * @license RequireJS i18n 1.0.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n/*jslint regexp: false, nomen: false, plusplus: false, strict: false */\n/*global require: false, navigator: false, define: false */\n\n/**\n * This plugin handles i18n! prefixed modules. It does the following:\n *\n * 1) A regular module can have a dependency on an i18n bundle, but the regular\n * module does not want to specify what locale to load. So it just specifies\n * the top-level bundle, like \"i18n!nls/colors\".\n *\n * This plugin will load the i18n bundle at nls/colors, see that it is a root/master\n * bundle since it does not have a locale in its name. It will then try to find\n * the best match locale available in that master bundle, then request all the\n * locale pieces for that best match locale. For instance, if the locale is \"en-us\",\n * then the plugin will ask for the \"en-us\", \"en\" and \"root\" bundles to be loaded\n * (but only if they are specified on the master bundle).\n *\n * Once all the bundles for the locale pieces load, then it mixes in all those\n * locale pieces into each other, then finally sets the context.defined value\n * for the nls/colors bundle to be that mixed in locale.\n *\n * 2) A regular module specifies a specific locale to load. For instance,\n * i18n!nls/fr-fr/colors. In this case, the plugin needs to load the master bundle\n * first, at nls/colors, then figure out what the best match locale is for fr-fr,\n * since maybe only fr or just root is defined for that locale. Once that best\n * fit is found, all of its locale pieces need to have their bundles loaded.\n *\n * Once all the bundles for the locale pieces load, then it mixes in all those\n * locale pieces into each other, then finally sets the context.defined value\n * for the nls/fr-fr/colors bundle to be that mixed in locale.\n */\n(function () {\n    //regexp for reconstructing the master bundle name from parts of the regexp match\n    //nlsRegExp.exec(\"foo/bar/baz/nls/en-ca/foo\") gives:\n    //[\"foo/bar/baz/nls/en-ca/foo\", \"foo/bar/baz/nls/\", \"/\", \"/\", \"en-ca\", \"foo\"]\n    //nlsRegExp.exec(\"foo/bar/baz/nls/foo\") gives:\n    //[\"foo/bar/baz/nls/foo\", \"foo/bar/baz/nls/\", \"/\", \"/\", \"foo\", \"\"]\n    //so, if match[5] is blank, it means this is the top bundle definition.\n    var nlsRegExp = /(^.*(^|\\/)nls(\\/|$))([^\\/]*)\\/?([^\\/]*)/,\n        empty = {};\n\n    //Helper function to avoid repeating code. Lots of arguments in the\n    //desire to stay functional and support RequireJS contexts without having\n    //to know about the RequireJS contexts.\n    function addPart(locale, master, needed, toLoad, prefix, suffix) {\n        if (master[locale]) {\n            needed.push(locale);\n            if (master[locale] === true || master[locale] === 1) {\n                toLoad.push(prefix + locale + '/' + suffix);\n            }\n        }\n    }\n\n    function addIfExists(req, locale, toLoad, prefix, suffix) {\n        var fullName = prefix + locale + '/' + suffix;\n        if (require._fileExists(req.toUrl(fullName))) {\n            toLoad.push(fullName);\n        }\n    }\n\n    /**\n     * Simple function to mix in properties from source into target,\n     * but only if target does not already have a property of the same name.\n     * This is not robust in IE for transferring methods that match\n     * Object.prototype names, but the uses of mixin here seem unlikely to\n     * trigger a problem related to that.\n     */\n    function mixin(target, source, force) {\n        for (var prop in source) {\n            if (!(prop in empty) && (!(prop in target) || force)) {\n                target[prop] = source[prop];\n            }\n        }\n    }\n\n    define('i18n',{\n        version: '1.0.0',\n        /**\n         * Called when a dependency needs to be loaded.\n         */\n        load: function (name, req, onLoad, config) {\n            config = config || {};\n\n            var masterName,\n                match = nlsRegExp.exec(name),\n                prefix = match[1],\n                locale = match[4],\n                suffix = match[5],\n                parts = locale.split(\"-\"),\n                toLoad = [],\n                value = {},\n                i, part, current = \"\";\n\n            //If match[5] is blank, it means this is the top bundle definition,\n            //so it does not have to be handled. Locale-specific requests\n            //will have a match[4] value but no match[5]\n            if (match[5]) {\n                //locale-specific bundle\n                prefix = match[1];\n                masterName = prefix + suffix;\n            } else {\n                //Top-level bundle.\n                masterName = name;\n                suffix = match[4];\n                locale = config.locale || (config.locale =\n                        typeof navigator === \"undefined\" ? \"root\" :\n                        (navigator.language ||\n                         navigator.userLanguage || \"root\").toLowerCase());\n                parts = locale.split(\"-\");\n            }\n\n            if (config.isBuild) {\n                //Check for existence of all locale possible files and\n                //require them if exist.\n                toLoad.push(masterName);\n                addIfExists(req, \"root\", toLoad, prefix, suffix);\n                for (i = 0; (part = parts[i]); i++) {\n                    current += (current ? \"-\" : \"\") + part;\n                    addIfExists(req, current, toLoad, prefix, suffix);\n                }\n\n                req(toLoad, function () {\n                    onLoad();\n                });\n            } else {\n                //First, fetch the master bundle, it knows what locales are available.\n                req([masterName], function (master) {\n                    //Figure out the best fit\n                    var needed = [];\n\n                    //Always allow for root, then do the rest of the locale parts.\n                    addPart(\"root\", master, needed, toLoad, prefix, suffix);\n                    for (i = 0; (part = parts[i]); i++) {\n                        current += (current ? \"-\" : \"\") + part;\n                        addPart(current, master, needed, toLoad, prefix, suffix);\n                    }\n\n                    //Load all the parts missing.\n                    req(toLoad, function () {\n                        var i, partBundle;\n                        for (i = needed.length - 1; i > -1 && (part = needed[i]); i--) {\n                            partBundle = master[part];\n                            if (partBundle === true || partBundle === 1) {\n                                partBundle = req(prefix + part + '/' + suffix);\n                            }\n                            mixin(value, partBundle);\n                        }\n\n                        //All done, notify the loader.\n                        onLoad(value);\n                    });\n                });\n            }\n        }\n    });\n}());\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\ndefine('nls/strings',['require','exports','module'],function (require, exports, module) {\n    \n    \n    \n    // Code that needs to display user strings should call require(\"strings\") to load\n    // src/strings.js. This file will dynamically load strings.js for the specified brackets.locale.\n    //\n    // See the README.md file in this folder for information on how to add a new translation for\n    // another language or locale.\n    //\n    // TODO: dynamically populate the local prefix list below?\n    module.exports = {\n        root: true,\n        \"de\": true,\n        \"fr\": true\n    };\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\ndefine('nls/root/strings',{\n    /**\n     * Errors\n     */\n\n    // General file io error strings\n    \"GENERIC_ERROR\"                     : \"(error {0})\",\n    \"NOT_FOUND_ERR\"                     : \"The file could not be found.\",\n    \"NOT_READABLE_ERR\"                  : \"The file could not be read.\",\n    \"NO_MODIFICATION_ALLOWED_ERR\"       : \"The target directory cannot be modified.\",\n    \"NO_MODIFICATION_ALLOWED_ERR_FILE\"  : \"The permissions do not allow you to make modifications.\",\n\n    // Project error strings\n    \"ERROR_LOADING_PROJECT\"             : \"Error loading project\",\n    \"OPEN_DIALOG_ERROR\"                 : \"An error occurred when showing the open file dialog. (error {0})\",\n    \"REQUEST_NATIVE_FILE_SYSTEM_ERROR\"  : \"An error occurred when trying to load the directory <span class='dialog-filename'>{0}</span>. (error {1})\",\n    \"READ_DIRECTORY_ENTRIES_ERROR\"      : \"An error occurred when reading the contents of the directory <span class='dialog-filename'>{0}</span>. (error {1})\",\n\n    // File open/save error string\n    \"ERROR_OPENING_FILE_TITLE\"          : \"Error opening file\",\n    \"ERROR_OPENING_FILE\"                : \"An error occurred when trying to open the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_RELOADING_FILE_TITLE\"        : \"Error reloading changes from disk\",\n    \"ERROR_RELOADING_FILE\"              : \"An error occurred when trying to reload the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"ERROR_SAVING_FILE_TITLE\"           : \"Error saving file\",\n    \"ERROR_SAVING_FILE\"                 : \"An error occurred when trying to save the file <span class='dialog-filename'>{0}</span>. {1}\",\n    \"INVALID_FILENAME_TITLE\"            : \"Invalid file name\",\n    \"INVALID_FILENAME_MESSAGE\"          : \"Filenames cannot contain the following characters: /?*:;{}<>\\\\|\",\n    \"FILE_ALREADY_EXISTS\"               : \"The file <span class='dialog-filename'>{0}</span> already exists.\",\n    \"ERROR_CREATING_FILE_TITLE\"         : \"Error creating file\",\n    \"ERROR_CREATING_FILE\"               : \"An error occurred when trying to create the file <span class='dialog-filename'>{0}</span>. {1}\",\n\n    // Application error strings\n    \"ERROR_BRACKETS_IN_BROWSER_TITLE\"   : \"Oops! Brackets doesn't run in browsers yet.\",\n    \"ERROR_BRACKETS_IN_BROWSER\"         : \"Brackets is built in HTML, but right now it runs as a desktop app so you can use it to edit local files. Please use the application shell in the <b>github.com/adobe/brackets-app</b> repo to run Brackets.\",\n\n    // FileIndexManager error string\n    \"ERROR_MAX_FILES_TITLE\"             : \"Error Indexing Files\",\n    \"ERROR_MAX_FILES\"                   : \"The maximum number of files have been indexed. Actions that look up files in the index may function incorrectly.\",\n    \n    // CSSManager error strings\n    \"ERROR_PARSE_TITLE\"                 : \"Error parsing CSS file(s):\",\n\n    // Live Development error strings\n    \"ERROR_LAUNCHING_BROWSER_TITLE\"     : \"Error launching browser\",\n    \"ERROR_CANT_FIND_CHROME\"            : \"The Google Chrome browser could not be found. Please make sure it is installed.\",\n    \"ERROR_LAUNCHING_BROWSER\"           : \"An error occurred when launching the browser. (error {0})\",\n    \n    \"LIVE_DEVELOPMENT_ERROR_TITLE\"      : \"Live Development Error\",\n    \"LIVE_DEVELOPMENT_ERROR_MESSAGE\"    : \"A live development connection to Chrome could not be established. For live development to work, Chrome needs to be started with remote debugging enabled.<br /><br />Would you like to relaunch Chrome and enable remote debugging?\",\n    \"LIVE_DEV_NEED_HTML_MESSAGE\"        : \"Open an HTML file in order to launch live preview.\",\n    \n    \"LIVE_DEV_STATUS_TIP_NOT_CONNECTED\" : \"Live File Preview\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS1\"     : \"Live File Preview: Connecting...\",\n    \"LIVE_DEV_STATUS_TIP_PROGRESS2\"     : \"Live File Preview: Initializing...\",\n    \"LIVE_DEV_STATUS_TIP_CONNECTED\"     : \"Disconnect Live File Preview\",\n    \n    \"SAVE_CLOSE_TITLE\"                  : \"Save Changes\",\n    \"SAVE_CLOSE_MESSAGE\"                : \"Do you want to save the changes you made in the document <span class='dialog-filename'>{0}</span>?\",\n    \"SAVE_CLOSE_MULTI_MESSAGE\"          : \"Do you want to save your changes to the following files?\",\n    \"EXT_MODIFIED_TITLE\"                : \"External Changes\",\n    \"EXT_MODIFIED_MESSAGE\"              : \"<span class='dialog-filename'>{0}</span> has been modified on disk, but also has unsaved changes in Brackets.<br /><br />Which version do you want to keep?\",\n    \"EXT_DELETED_MESSAGE\"               : \"<span class='dialog-filename'>{0}</span> has been deleted on disk, but has unsaved changes in Brackets.<br /><br />Do you want to keep your changes?\",\n    \n    // Find, Replace, Find in Files\n    \"SEARCH_REGEXP_INFO\"                : \"Use /re/ syntax for regexp search\",\n    \"WITH\"                              : \"With\",\n    \"BUTTON_YES\"                        : \"Yes\",\n    \"BUTTON_NO\"                         : \"No\",\n    \"BUTTON_STOP\"                       : \"Stop\",\n\n    \"OPEN_FILE\"                         : \"Open File\",\n\n    \"RELEASE_NOTES\"                     : \"Release Notes\",\n    \"NO_UPDATE_TITLE\"                   : \"You're up to date!\",\n    \"NO_UPDATE_MESSAGE\"                 : \"You are running the latest version of Brackets.\",\n\n    // Switch language\n    \"LANGUAGE_TITLE\"                    : \"Switch Language\",\n    \"LANGUAGE_MESSAGE\"                  : \"Please select the desired language from the list below:\",\n    \"LANGUAGE_SUBMIT\"                   : \"Reload Brackets\",\n    \"LANGUAGE_CANCEL\"                   : \"Cancel\",\n\n    /**\n     * ProjectManager\n     */\n\n    \"UNTITLED\" : \"Untitled\",\n\n    /**\n     * Command Name Constants\n     */\n\n    // File menu commands\n    \"FILE_MENU\"                           : \"File\",\n    \"CMD_FILE_NEW\"                        : \"New\",\n    \"CMD_FILE_OPEN\"                       : \"Open\\u2026\",\n    \"CMD_ADD_TO_WORKING_SET\"              : \"Add To Working Set\",\n    \"CMD_OPEN_FOLDER\"                     : \"Open Folder\\u2026\",\n    \"CMD_FILE_CLOSE\"                      : \"Close\",\n    \"CMD_FILE_CLOSE_ALL\"                  : \"Close All\",\n    \"CMD_FILE_SAVE\"                       : \"Save\",\n    \"CMD_FILE_SAVE_ALL\"                   : \"Save All\",\n    \"CMD_LIVE_FILE_PREVIEW\"               : \"Live File Preview\",\n    \"CMD_QUIT\"                            : \"Quit\",\n\n    // Edit menu commands\n    \"EDIT_MENU\"                           : \"Edit\",\n    \"CMD_SELECT_ALL\"                      : \"Select All\",\n    \"CMD_FIND\"                            : \"Find\",\n    \"CMD_FIND_IN_FILES\"                   : \"Find in Files\",\n    \"CMD_FIND_NEXT\"                       : \"Find Next\",\n    \"CMD_FIND_PREVIOUS\"                   : \"Find Previous\",\n    \"CMD_REPLACE\"                         : \"Replace\",\n    \"CMD_INDENT\"                          : \"Indent\",\n    \"CMD_UNINDENT\"                        : \"Unindent\",\n    \"CMD_DUPLICATE\"                       : \"Duplicate\",\n    \"CMD_COMMENT\"                         : \"Comment/Uncomment Lines\",\n    \"CMD_LINE_UP\"                         : \"Move Line(s) Up\",\n    \"CMD_LINE_DOWN\"                       : \"Move Line(s) Down\",\n     \n    // View menu commands\n    \"VIEW_MENU\"                           : \"View\",\n    \"CMD_HIDE_SIDEBAR\"                    : \"Hide Sidebar\",\n    \"CMD_SHOW_SIDEBAR\"                    : \"Show Sidebar\",\n    \"CMD_INCREASE_FONT_SIZE\"              : \"Increase Font Size\",\n    \"CMD_DECREASE_FONT_SIZE\"              : \"Decrease Font Size\",\n    \"CMD_RESTORE_FONT_SIZE\"               : \"Restore Font Size\",\n\n    // Navigate menu Commands\n    \"NAVIGATE_MENU\"                       : \"Navigate\",\n    \"CMD_QUICK_OPEN\"                      : \"Quick Open\",\n    \"CMD_GOTO_LINE\"                       : \"Go to Line\",\n    \"CMD_GOTO_DEFINITION\"                 : \"Go to Definition\",\n    \"CMD_TOGGLE_QUICK_EDIT\"               : \"Quick Edit\",\n    \"CMD_QUICK_EDIT_PREV_MATCH\"           : \"Previous Match\",\n    \"CMD_QUICK_EDIT_NEXT_MATCH\"           : \"Next Match\",\n    \"CMD_NEXT_DOC\"                        : \"Next Document\",\n    \"CMD_PREV_DOC\"                        : \"Previous Document\",\n    \n    // Debug menu commands\n    \"DEBUG_MENU\"                          : \"Debug\",\n    \"CMD_REFRESH_WINDOW\"                  : \"Reload Brackets\",\n    \"CMD_SHOW_DEV_TOOLS\"                  : \"Show Developer Tools\",\n    \"CMD_RUN_UNIT_TESTS\"                  : \"Run Tests\",\n    \"CMD_JSLINT\"                          : \"Enable JSLint\",\n    \"CMD_SHOW_PERF_DATA\"                  : \"Show Performance Data\",\n    \"CMD_NEW_BRACKETS_WINDOW\"             : \"New Brackets Window\",\n    \"CMD_SHOW_EXTENSIONS_FOLDER\"          : \"Show Extensions Folder\",\n    \"CMD_USE_TAB_CHARS\"                   : \"Use Tab Characters\",\n    \"CMD_SWITCH_LANGUAGE\"                 : \"Switch Language\",\n    \"CMD_CHECK_FOR_UPDATE\"                : \"Check for Updates\",\n\n    // Help menu commands\n    \"CMD_ABOUT\"                           : \"About\",\n\n    // Special commands invoked by the native shell\n    \"CMD_CLOSE_WINDOW\"                    : \"Close Window\",\n    \"CMD_ABORT_QUIT\"                      : \"Abort Quit\",\n\n    // Strings for main-view.html\n    \"EXPERIMENTAL_BUILD\"                   : \"Experimental Build\",\n    \"JSLINT_ERRORS\"                        : \"JSLint Errors\",\n    \"SEARCH_RESULTS\"                       : \"Search Results\",\n    \"OK\"                                   : \"OK\",\n    \"DONT_SAVE\"                            : \"Don't Save\",\n    \"SAVE\"                                 : \"Save\",\n    \"CANCEL\"                               : \"Cancel\",\n    \"RELOAD_FROM_DISK\"                     : \"Reload from Disk\",\n    \"KEEP_CHANGES_IN_EDITOR\"               : \"Keep Changes in Editor\",\n    \"CLOSE_DONT_SAVE\"                      : \"Close (Don't Save)\",\n    \"RELAUNCH_CHROME\"                      : \"Relaunch Chrome\",\n    \"ABOUT\"                                : \"About\",\n    \"BRACKETS\"                             : \"Brackets\",\n    \"CLOSE\"                                : \"Close\",\n    \"ABOUT_TEXT_LINE1\"                     : \"sprint 13 experimental build \",\n    \"ABOUT_TEXT_LINE2\"                     : \"Copyright 2012 Adobe Systems Incorporated and its licensors. All rights reserved.\",\n    \"ABOUT_TEXT_LINE3\"                     : \"Notices; terms and conditions pertaining to third party software are located at \",\n    \"ABOUT_TEXT_LINE4\"                     : \" and incorporated by reference herein.\",\n    \"ABOUT_TEXT_LINE5\"                     : \"Documentation and source at \",\n    \"UPDATE_NOTIFICATION_TOOLTIP\"          : \"There's a new build of Brackets available! Click here for details.\",\n    \"UPDATE_AVAILABLE_TITLE\"               : \"Update Available\",\n    \"UPDATE_MESSAGE\"                       : \"Hey, there's a new build of Brackets available. Here are some of the new features:\",\n    \"GET_IT_NOW\"                           : \"Get it now!\"\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define */\n\n/**\n * This file provides the interface to user visible strings in Brackets. Code that needs\n * to display strings should should load this module by calling var Strings = require(\"strings\").\n * The i18n plugin will dynamically load the strings for the right locale and populate\n * the exports variable. See src\\nls\\strings.js for the master file of English strings.\n */\ndefine('strings',['require','exports','module','i18n!nls/strings'],function (require, exports, module) {\n    \n\n    module.exports = require(\"i18n!nls/strings\");\n\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n *  Utilities functions related to string manipulation\n *\n */\ndefine('utils/StringUtils',['require','exports','module'],function (require, exports, module) {\n    \n\n    /**\n     * Format a string by replacing placeholder symbols with passed in arguments.\n     *\n     * Example: var formatted = StringUtils.format(\"Hello {0}\", \"World\");\n     *\n     * @param {string} str The base string\n     * @param {...} Arguments to be substituted into the string\n     *\n     * @return {string} Formatted string\n     */\n    function format(str) {\n        // arguments[0] is the base string, so we need to adjust index values here\n        var args = [].slice.call(arguments, 1);\n        return str.replace(/\\{(\\d+)\\}/g, function (match, num) {\n            return typeof args[num] !== \"undefined\" ? args[num] : match;\n        });\n    }\n\n    function htmlEscape(str) {\n        return String(str)\n            .replace(/&/g, \"&amp;\")\n            .replace(/\"/g, \"&quot;\")\n            .replace(/'/g, \"&#39;\")\n            .replace(/</g, \"&lt;\")\n            .replace(/>/g, \"&gt;\");\n    }\n\n    function regexEscape(str) {\n        return str.replace(/([.?*+\\^$\\[\\]\\\\(){}|\\-])/g, \"\\\\$1\");\n    }\n\n    // Periods (aka \"dots\") are allowed in HTML identifiers, but jQuery interprets\n    // them as the start of a class selector, so they need to be escaped\n    function jQueryIdEscape(str) {\n        return str.replace(/\\./g, \"\\\\.\");\n    }\n\n    /**\n     * Splits the text by new line characters and returns an array of lines\n     * @param {string} text\n     * @return {Array.<string>} lines\n     */\n    function getLines(text) {\n        return text.split(\"\\n\");\n    }\n\n    /**\n     * Returns a line number corresponding to an offset in some text. The text can\n     * be specified as a single string or as an array of strings that correspond to\n     * the lines of the string.\n     *\n     * Specify the text in lines when repeatedly calling the function on the same\n     * text in a loop. Use getLines() to divide the text into lines, then repeatedly call\n     * this function to compute a line number from the offset.\n     *\n     * @param {string | Array.<string>} textOrLines - string or array of lines from which\n     *      to compute the line number from the offset\n     * @param {number} offset\n     * @return {number} line number\n     */\n    function offsetToLineNum(textOrLines, offset) {\n        if (Array.isArray(textOrLines)) {\n            var lines = textOrLines,\n                total = 0,\n                line;\n            for (line = 0; line < lines.length; line++) {\n                if (total < offset) {\n                    // add 1 per line since /n were removed by splitting, but they needed to \n                    // contribute to the total offset count\n                    total += lines[line].length + 1;\n                } else if (total === offset) {\n                    return line;\n                } else {\n                    return line - 1;\n                }\n            }\n\n            // if offset is NOT over the total then offset is in the last line\n            if (offset <= total) {\n                return line - 1;\n            } else {\n                return undefined;\n            }\n        } else {\n            return textOrLines.substr(0, offset).split(\"\\n\").length - 1;\n        }\n    }\n\n    // Define public API\n    exports.format          = format;\n    exports.htmlEscape      = htmlEscape;\n    exports.regexEscape     = regexEscape;\n    exports.jQueryIdEscape  = jQueryIdEscape;\n    exports.getLines        = getLines;\n    exports.offsetToLineNum = offsetToLineNum;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, FileError, brackets, unescape, window */\n\n/**\n * Set of utilites for working with files and text content.\n */\ndefine('file/FileUtils',['require','exports','module','file/NativeFileSystem','utils/PerfUtils','widgets/Dialogs','strings','utils/StringUtils'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Encodings           = NativeFileSystem.Encodings;\n\n    \n    /**\n     * Asynchronously reads a file as UTF-8 encoded text.\n     * @return {$.Promise} a jQuery promise that will be resolved with the \n     *  file's text content plus its timestamp, or rejected with a FileError if\n     *  the file can not be read.\n     */\n    function readAsText(fileEntry) {\n        var result = new $.Deferred(),\n            reader;\n\n        // Measure performance\n        var perfTimerName = PerfUtils.markStart(\"readAsText:\\t\" + fileEntry.fullPath);\n        result.always(function () {\n            PerfUtils.addMeasurement(perfTimerName);\n        });\n\n        // Read file\n        reader = new NativeFileSystem.FileReader();\n        fileEntry.file(function (file) {\n            reader.onload = function (event) {\n                var text = event.target.result;\n                \n                fileEntry.getMetadata(\n                    function (metadata) {\n                        result.resolve(text, metadata.modificationTime);\n                    },\n                    function (error) {\n                        result.reject(error);\n                    }\n                );\n            };\n\n            reader.onerror = function (event) {\n                result.reject(event.target.error);\n            };\n\n            reader.readAsText(file, Encodings.UTF8);\n        });\n\n        return result.promise();\n    }\n    \n    /**\n     * Asynchronously writes a file as UTF-8 encoded text.\n     * @param {!FileEntry} fileEntry\n     * @param {!string} text\n     * @return {$.Promise} a jQuery promise that will be resolved when\n     * file writing completes, or rejected with a FileError.\n     */\n    function writeText(fileEntry, text) {\n        var result = new $.Deferred();\n        \n        fileEntry.createWriter(function (fileWriter) {\n            fileWriter.onwriteend = function (e) {\n                result.resolve();\n            };\n            fileWriter.onerror = function (err) {\n                result.reject(err);\n            };\n\n            // TODO (issue #241): NativeFileSystem.BlobBulder\n            fileWriter.write(text);\n        });\n        \n        return result.promise();\n    }\n\n    /** @const */\n    var LINE_ENDINGS_CRLF = \"CRLF\";\n    /** @const */\n    var LINE_ENDINGS_LF = \"LF\";\n    \n    /**\n     * Returns the standard line endings for the current platform\n     * @return {LINE_ENDINGS_CRLF|LINE_ENDINGS_LF}\n     */\n    function getPlatformLineEndings() {\n        return brackets.platform === \"win\" ? LINE_ENDINGS_CRLF : LINE_ENDINGS_LF;\n    }\n    \n    /**\n     * Scans the first 1000 chars of the text to determine how it encodes line endings. Returns\n     * null if usage is mixed or if no line endings found.\n     * @param {!string} text\n     * @return {null|LINE_ENDINGS_CRLF|LINE_ENDINGS_LF}\n     */\n    function sniffLineEndings(text) {\n        var subset = text.substr(0, 1000);  // (length is clipped to text.length)\n        var hasCRLF = /\\r\\n/.test(subset);\n        var hasLF = /[^\\r]\\n/.test(subset);\n        \n        if ((hasCRLF && hasLF) || (!hasCRLF && !hasLF)) {\n            return null;\n        } else {\n            return hasCRLF ? LINE_ENDINGS_CRLF : LINE_ENDINGS_LF;\n        }\n    }\n\n    /**\n     * Translates any line ending types in the given text to the be the single form specified\n     * @param {!string} text\n     * @param {null|LINE_ENDINGS_CRLF|LINE_ENDINGS_LF} lineEndings\n     * @return {string}\n     */\n    function translateLineEndings(text, lineEndings) {\n        if (lineEndings !== LINE_ENDINGS_CRLF && lineEndings !== LINE_ENDINGS_LF) {\n            lineEndings = getPlatformLineEndings();\n        }\n        \n        var eolStr = (lineEndings === LINE_ENDINGS_CRLF ? \"\\r\\n\" : \"\\n\");\n        var findAnyEol = /\\r\\n|\\r|\\n/g;\n        \n        return text.replace(findAnyEol, eolStr);\n    }\n\n    function getFileErrorString(code) {\n        // There are a few error codes that we have specific error messages for. The rest are\n        // displayed with a generic \"(error N)\" message.\n        var result;\n\n        if (code === FileError.NOT_FOUND_ERR) {\n            result = Strings.NOT_FOUND_ERR;\n        } else if (code === FileError.NOT_READABLE_ERR) {\n            result = Strings.NOT_READABLE_ERR;\n        } else if (code === FileError.NO_MODIFICATION_ALLOWED_ERR) {\n            result = Strings.NO_MODIFICATION_ALLOWED_ERR_FILE;\n        } else {\n            result = StringUtils.format(Strings.GENERIC_ERROR, code);\n        }\n\n        return result;\n    }\n    \n    function showFileOpenError(code, path) {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_OPENING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_OPENING_FILE,\n                StringUtils.htmlEscape(path),\n                getFileErrorString(code)\n            )\n        );\n    }\n\n    /**\n     * Convert a URI path to a native path.\n     * On both platforms, this unescapes the URI\n     * On windows, URI paths start with a \"/\", but have a drive letter (\"C:\"). In this\n     * case, remove the initial \"/\".\n     * @param {!string} path\n     * @return {string}\n     */\n    function convertToNativePath(path) {\n        path = unescape(path);\n        if (path.indexOf(\":\") !== -1 && path[0] === \"/\") {\n            return path.substr(1);\n        }\n        \n        return path;\n    }\n\n    /**\n     * Returns a native absolute path to the 'brackets' source directory.\n     * Note that this only works when run in brackets/src/index.html, so it does\n     * not work for unit tests (which is run from brackets/test/SpecRunner.html)\n     * @return {string}\n     */\n    function getNativeBracketsDirectoryPath() {\n        var pathname = decodeURI(window.location.pathname);\n        var directory = pathname.substr(0, pathname.lastIndexOf(\"/\"));\n        return convertToNativePath(directory);\n    }\n    \n    /**\n     * Given the module object passed to JS module define function,\n     * convert the path (which is relative to the current window)\n     * to a native absolute path.\n     * Returns a native absolute path to the module folder.\n     * @return {string}\n     */\n    function getNativeModuleDirectoryPath(module) {\n        var path, relPath, index, pathname;\n\n        if (module && module.uri) {\n\n            // Remove window name from base path. Maintain trailing slash.\n            pathname = decodeURI(window.location.pathname);\n            path = convertToNativePath(pathname.substr(0, pathname.lastIndexOf(\"/\") + 1));\n\n            // Remove module name from relative path. Remove trailing slash.\n            pathname = decodeURI(module.uri);\n            relPath = pathname.substr(0, pathname.lastIndexOf(\"/\"));\n\n            // handle leading \"../\" in relative directory\n            while (relPath.substr(0, 3) === \"../\") {\n                path = path.substr(0, path.length - 1); // strip trailing slash from base path\n                index = path.lastIndexOf(\"/\");          // find next slash from end\n                if (index !== -1) {\n                    path = path.substr(0, index + 1);   // remove last dir while maintaining slash\n                }\n                relPath = relPath.substr(3);            // remove leading \"../\" from relative path\n            }\n            path += relPath;\n        }\n        return path;\n    }\n\n    // Define public API\n    exports.LINE_ENDINGS_CRLF              = LINE_ENDINGS_CRLF;\n    exports.LINE_ENDINGS_LF                = LINE_ENDINGS_LF;\n    exports.getPlatformLineEndings         = getPlatformLineEndings;\n    exports.sniffLineEndings               = sniffLineEndings;\n    exports.translateLineEndings           = translateLineEndings;\n    exports.showFileOpenError              = showFileOpenError;\n    exports.getFileErrorString             = getFileErrorString;\n    exports.readAsText                     = readAsText;\n    exports.writeText                      = writeText;\n    exports.convertToNativePath            = convertToNativePath;\n    exports.getNativeBracketsDirectoryPath = getNativeBracketsDirectoryPath;\n    exports.getNativeModuleDirectoryPath   = getNativeModuleDirectoryPath;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\ndefine('language/HTMLUtils',['require','exports','module'],function (require, exports, module) {\n    \n    \n    //constants\n    var TAG_NAME = \"tagName\",\n        ATTR_NAME = \"attr.name\",\n        ATTR_VALUE = \"attr.value\";\n    \n    /**\n     * @private\n     * moves the current context backwards by one token\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function _movePrevToken(ctx) {\n        if (ctx.pos.ch <= 0 || ctx.token.start <= 0) {\n            //move up a line\n            if (ctx.pos.line <= 0) {\n                return false; //at the top already\n            }\n            ctx.pos.line--;\n            ctx.pos.ch = ctx.editor.getLine(ctx.pos.line).length;\n        } else {\n            ctx.pos.ch = ctx.token.start;\n        }\n        ctx.token = ctx.editor.getTokenAt(ctx.pos);\n        return true;\n    }\n    \n    /**\n     * @private\n     * moves the current context forward by one token\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function _moveNextToken(ctx) {\n        var eol = ctx.editor.getLine(ctx.pos.line).length;\n        if (ctx.pos.ch >= eol || ctx.token.end >= eol) {\n            //move down a line\n            if (ctx.pos.line >= ctx.editor.lineCount() - 1) {\n                return false; //at the bottom\n            }\n            ctx.pos.line++;\n            ctx.pos.ch = 0;\n        } else {\n            ctx.pos.ch = ctx.token.end + 1;\n        }\n        ctx.token = ctx.editor.getTokenAt(ctx.pos);\n        return true;\n    }\n    \n   /**\n     * @private\n     * moves the current context in the given direction, skipping any whitespace it hits\n     * @param {function} moveFxn the funciton to move the context\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx\n     * @return {boolean} whether the context changed\n     */\n    function _moveSkippingWhitespace(moveFxn, ctx) {\n        if (!moveFxn(ctx)) {\n            return false;\n        }\n        while (!ctx.token.className && ctx.token.string.trim().length === 0) {\n            if (!moveFxn(ctx)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n   /**\n     * @private\n     * creates a context object\n     * @param {CodeMirror} editor\n     * @param {{ch:{string}, line:{number}} pos\n     * @return {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}\n     */\n    function _getInitialContext(editor, pos) {\n        return {\n            \"editor\": editor,\n            \"pos\": pos,\n            \"token\": editor.getTokenAt(pos)\n        };\n    }\n    \n    /**\n     * @private\n     * in the given context, get the character offset of pos from the start of the token\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {number}\n     */\n    function _offsetInToken(ctx) {\n        var offset = ctx.pos.ch - ctx.token.start;\n        if (offset < 0) {\n            console.log(\"CodeHintUtils: _offsetInToken - Invalid context: the pos what not in the current token!\");\n        }\n        return offset;\n    }\n \n   /**\n     * @private\n     * Sometimes as attr values are getting typed, if the quotes aren't balanced yet\n     * some extra 'non attribute value' text gets included in the token. This attempts\n     * to assure the attribute value we grab is always good\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return { val:{string}, offset:{number}}\n     */\n    function _extractAttrVal(ctx) {\n        var attrValue = ctx.token.string,\n            startChar = attrValue.charAt(0),\n            endChar = attrValue.charAt(attrValue.length - 1),\n            offset = _offsetInToken(ctx),\n            foundEqualSign = false;\n        \n        //If this is a fully quoted value, return the whole\n        //thing regardless of position\n        if (attrValue.length > 1 &&\n                (startChar === \"'\" || startChar === '\"') &&\n                endChar === startChar) {\n            \n            // Find an equal sign before the end quote. If found, \n            // then the user may be entering an attribute value right before \n            // another attribute and we're getting a false balanced string.\n            // An example of this case is <link rel\" href=\"foo\"> where the \n            // cursor is right after the first double quote.\n            foundEqualSign = (attrValue.match(/\\=\\s*['\"]$/) !== null);\n            \n            if (!foundEqualSign) {\n                //strip the quotes and return;\n                attrValue = attrValue.substring(1, attrValue.length - 1);\n                offset = offset - 1 > attrValue.length ? attrValue.length : offset - 1;\n                return {val: attrValue, offset: offset, quoteChar: startChar, hasEndQuote: true};\n            }\n        }\n        \n        if (foundEqualSign) {\n            var spaceIndex = attrValue.indexOf(\" \");\n            attrValue = attrValue.substring(0, (spaceIndex > offset) ? spaceIndex : offset);\n        } else if (offset > 0) {\n            //The att value it getting edit in progress. There is possible extra\n            //stuff in this token state since the quote isn't closed, so we assume\n            //the stuff from the quote to the current pos is definitely in the attribute \n            //value.\n            attrValue = attrValue.substring(0, offset);\n        }\n        \n        //If the attrValue start with a quote, trim that now\n        startChar = attrValue.charAt(0);\n        if (startChar === \"'\" || startChar === '\"') {\n            attrValue = attrValue.substring(1);\n            offset--;\n        } else {\n            startChar = \"\";\n        }\n        \n        return {val: attrValue, offset: offset, quoteChar: startChar, hasEndQuote: false};\n    }\n    \n    /**\n     * @private\n     * Gets the tagname from where ever you are in the currect state\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string}\n     */\n    function _extractTagName(ctx) {\n        if (ctx.token.state.tagName) {\n            return ctx.token.state.tagName; //XML mode\n        } else if (ctx.token.state.htmlState) {\n            return ctx.token.state.htmlState.tagName; //HTML mode\n        }\n        // Some mixed modes that offer HTML as a nested mode don't actually expose the HTML state\n        return null;\n    }\n    \n    /**\n     * Creates a tagInfo object and assures all the values are entered or are empty strings\n     * @param {string} tokenType what is getting edited and should be hinted\n     * @param {number} offset where the cursor is for the part getting hinted\n     * @param {string} tagName The name of the tag\n     * @param {string} attrName The name of the attribute\n     * @param {string} attrValue The value of the attribute\n     * @return {{tagName:string, attr{name:string, value:string}, hint:{type:{string}, offset{number}}}}\n     *              A tagInfo object with some context about the current tag hint.            \n     */\n    function createTagInfo(tokenType, offset, tagName, attrName, attrValue, valueAssigned, quoteChar, hasEndQuote) {\n        return { tagName: tagName || \"\",\n                 attr:\n                    { name: attrName || \"\",\n                      value: attrValue || \"\",\n                      valueAssigned: valueAssigned || false,\n                      quoteChar: quoteChar || \"\",\n                      hasEndQuote: hasEndQuote || false },\n                 position:\n                    { tokenType: tokenType || \"\",\n                      offset: offset || 0 } };\n    }\n    \n    /**\n     * @private\n     * Gets the taginfo starting from the attribute value and moving backwards\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @return {string}\n     */\n    function _getTagInfoStartingFromAttrValue(ctx) {\n        // Assume we in the attr value\n        // and validate that by going backwards\n        var attrInfo = _extractAttrVal(ctx),\n            attrVal = attrInfo.val,\n            offset = attrInfo.offset,\n            quoteChar = attrInfo.quoteChar,\n            hasEndQuote = attrInfo.hasEndQuote,\n            strLength = ctx.token.string.length;\n        \n        if (ctx.token.className === \"string\" && ctx.pos.ch === ctx.token.end && strLength > 1) {\n            var firstChar = ctx.token.string[0],\n                lastChar = ctx.token.string[strLength - 1];\n            \n            // We get here only when the cursor is immediately on the right of the end quote\n            // of an attribute value. So we want to return an empty tag info so that the caller\n            // can dismiss the code hint popup if it is still open.\n            if (firstChar === lastChar && (firstChar === \"'\" || firstChar === \"\\\"\")) {\n                return createTagInfo();\n            }\n        }\n        \n        //Move to the prev token, and check if it's \"=\"\n        if (!_moveSkippingWhitespace(_movePrevToken, ctx) || ctx.token.string !== \"=\") {\n            return createTagInfo();\n        }\n        \n        //Move to the prev token, and check if it's an attribute\n        if (!_moveSkippingWhitespace(_movePrevToken, ctx) || ctx.token.className !== \"attribute\") {\n            return createTagInfo();\n        }\n        \n        var attrName = ctx.token.string;\n        var tagName = _extractTagName(ctx);\n \n        //We're good. \n        return createTagInfo(ATTR_VALUE, offset, tagName, attrName, attrVal, true, quoteChar, hasEndQuote);\n    }\n\n    /**\n     * @private\n     * Gets the taginfo starting from the attribute name and moving forwards\n     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context\n     * @param {boolean} isPriorAttr indicates whether we're getting info for a prior attribute\n     * @return {string}\n     */\n    function _getTagInfoStartingFromAttrName(ctx, isPriorAttr) {\n        //Verify We're in the attribute name, move forward and try to extract the rest of\n        //the info. If the user it typing the attr the rest might not be here\n        if (isPriorAttr === false && ctx.token.className !== \"attribute\") {\n            return createTagInfo();\n        }\n        \n        var tagName = _extractTagName(ctx);\n        var attrName = ctx.token.string;\n        var offset = _offsetInToken(ctx);\n        \n        if (!_moveSkippingWhitespace(_moveNextToken, ctx) || ctx.token.string !== \"=\") {\n            return createTagInfo(ATTR_NAME, offset, tagName, attrName);\n        }\n        \n        if (!_moveSkippingWhitespace(_moveNextToken, ctx)) {\n            return createTagInfo(ATTR_NAME, offset, tagName, attrName);\n        }\n        //this should be the attrvalue\n        var attrInfo = _extractAttrVal(ctx),\n            attrVal = attrInfo.val,\n            quoteChar = attrInfo.quoteChar,\n            hasEndQuote = attrInfo.hasEndQuote;\n        \n        return createTagInfo(ATTR_NAME, offset, tagName, attrName, attrVal, true, quoteChar, hasEndQuote);\n    }\n    \n    /**\n     * Figure out if we're in a tag, and if we are return info about what to hint about it\n     * An example token stream for this tag is <span id=\"open-files-disclosure-arrow\"></span> : \n     *      className:tag       string:\"<span\"\n     *      className:          string:\" \"\n     *      className:attribute string:\"id\"\n     *      className:          string:\"=\"\n     *      className:string    string:\"\"open-files-disclosure-arrow\"\"\n     *      className:tag       string:\"></span>\"\n     * @param {Editor} editor An instance of a Brackets editor\n     * @param {{ch: number, line: number}} constPos  A CM pos (likely from editor.getCursor())\n     * @return {{tagName:string, attr{name:string, value:string}, hint:{type:{string}, offset{number}}}}\n     *              A tagInfo object with some context about the current tag hint.\n     */\n    function getTagInfo(editor, constPos) {\n        //we're going to changing pos a lot, but we don't want to mess up\n        //the pos the caller passed in so we use extend to make a safe copy of it.  \n        //This is what pass by value in c++ would do.   \n        var pos = $.extend({}, constPos),\n            ctx = _getInitialContext(editor._codeMirror, pos),\n            offset = _offsetInToken(ctx),\n            tagInfo,\n            tokenType;\n        \n        // check if this is inside a style block.\n        if (editor.getModeForSelection() !== \"html\") {\n            return createTagInfo();\n        }\n        \n        //check and see where we are in the tag\n        if (ctx.token.string.length > 0 && ctx.token.string.trim().length === 0) {\n\n            // token at (i.e. before) pos is whitespace, so test token at next pos\n            //\n            // note: getTokenAt() does range checking for ch. If it detects that ch is past\n            // EOL, it uses EOL, same token is returned, and the following condition fails,\n            // so we don't need to worry about testPos being valid.\n            var testPos = {ch: ctx.pos.ch + 1, line: ctx.pos.line},\n                testToken = editor._codeMirror.getTokenAt(testPos);\n\n            if (testToken.string.length > 0 && testToken.string.trim().length > 0 &&\n                    testToken.string.charAt(0) !== \">\") {\n                // pos has whitespace before it and non-whitespace after it, so use token after\n                ctx.token = testToken;\n\n                if (ctx.token.className === \"tag\") {\n                    // check to see if the cursor is just before a \"<\" but not in any tag.\n                    if (ctx.token.string.charAt(0) === \"<\") {\n                        return createTagInfo();\n                    }\n                } else if (ctx.token.className === \"attribute\") {\n                    // check to see if the user is going to add a new attr before an existing one\n                    return _getTagInfoStartingFromAttrName(ctx, false);\n                } else if (ctx.token.className === \"string\") {\n                    // we're either before a \"=\" or an attribute value.\n                    return createTagInfo();\n                }\n\n                ctx.pos = testPos;\n                // Get the new offset from test token and subtract one for testPos adjustment\n                offset = _offsetInToken(ctx) - 1;\n            } else {\n                // We get here if \">\" or white spaces after testPos.\n                // next, see what's before pos\n                if (!_movePrevToken(ctx)) {\n                    return createTagInfo();\n                }\n            \n                if (ctx.token.className !== \"tag\") {\n                    //if wasn't the tag name, assume it was an attr value\n                    tagInfo = _getTagInfoStartingFromAttrValue(ctx);\n\n                    //if it wasn't an attr value, assume it was an empty attr (ie. attr with no value)\n                    if (!tagInfo.tagName) {\n                        tagInfo = _getTagInfoStartingFromAttrName(ctx, true);\n                    }\n\n                    //We don't want to give context for the previous attr\n                    //and we want it to look like the user is going to add a new attr\n                    if (tagInfo.tagName) {\n                        return createTagInfo(ATTR_NAME, 0, tagInfo.tagName);\n                    }\n                    return createTagInfo();\n                }\n                \n                //we know the tag was here, so they user is adding an attr name\n                tokenType = ATTR_NAME;\n                offset = 0;\n            }\n        }\n        \n        if (ctx.token.className === \"tag\") {\n            // Check if the user just typed a white space after \"<\" that made an existing tag invalid.\n            if (ctx.token.string.indexOf(\"< \") === 0) {\n                return createTagInfo();\n            }\n            \n            //check to see if this is the closing of a tag (either the start or end)\n            if (ctx.token.string === \">\" ||\n                    (ctx.token.string.charAt(0) === \"<\" && ctx.token.string.charAt(1) === \"/\")) {\n                return createTagInfo();\n            }\n            \n            if (!tokenType) {\n                tokenType = TAG_NAME;\n                offset--; //need to take off 1 for the leading \"<\"\n            }\n            \n            //we're actually in the tag, just return that as we have no relevant \n            //info about what attr is selected\n            return createTagInfo(tokenType, offset, _extractTagName(ctx));\n        }\n        \n        if (ctx.token.string === \"=\") {\n            // To discourage unquoted attribute value usage we intentionally return an invalid tag info here.\n            // This will also spare us from handling the conversion between quoted and unquoted attribute values.\n            return createTagInfo();\n        }\n        \n        if (ctx.token.className === \"attribute\") {\n            tagInfo = _getTagInfoStartingFromAttrName(ctx, false);\n        } else {\n            // if we're not at a tag, \"=\", or attribute name, assume we're in the value\n            tagInfo = _getTagInfoStartingFromAttrValue(ctx);\n        }\n        \n        if (tokenType && tagInfo.tagName) {\n            tagInfo.position.tokenType = tokenType;\n            tagInfo.position.offset = offset;\n        }\n        \n        return tagInfo;\n    }\n    \n    \n    /**\n     * Returns an Array of info about all <style> blocks in the given Editor's HTML document (assumes\n     * the Editor contains HTML text).\n     * @param {!Editor} editor\n     */\n    function findStyleBlocks(editor) {\n        // Start scanning from beginning of file\n        var ctx = _getInitialContext(editor._codeMirror, {line: 0, ch: 0});\n        \n        var styleBlocks = [];\n        var currentStyleBlock = null;\n        var inStyleBlock = false;\n        \n        while (_moveNextToken(ctx)) {\n            if (inStyleBlock) {\n                // Check for end of this <style> block\n                if (ctx.token.state.mode !== \"css\") {\n                    currentStyleBlock.text = editor.document.getRange(currentStyleBlock.start, currentStyleBlock.end);\n                    inStyleBlock = false;\n                } else {\n                    currentStyleBlock.end = { line: ctx.pos.line, ch: ctx.pos.ch };\n                }\n            } else {\n                // Check for start of a <style> block\n                if (ctx.token.state.mode === \"css\") {\n                    currentStyleBlock = {\n                        start: { line: ctx.pos.line, ch: ctx.pos.ch }\n                    };\n                    styleBlocks.push(currentStyleBlock);\n                    inStyleBlock = true;\n                }\n                // else, random token in non-CSS content: ignore\n            }\n        }\n        \n        return styleBlocks;\n    }\n    \n    \n    // Define public API\n    exports.TAG_NAME = TAG_NAME;\n    exports.ATTR_NAME = ATTR_NAME;\n    exports.ATTR_VALUE = ATTR_VALUE;\n    \n    exports.getTagInfo = getTagInfo;\n    //The createTagInfo is really only for the unit tests so they can make the same structure to \n    //compare results with\n    exports.createTagInfo = createTagInfo;\n    exports.findStyleBlocks = findStyleBlocks;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window */\n\n/**\n * Utilities for managing pop-ups.\n */\ndefine('widgets/PopUpManager',['require','exports','module','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    var EditorManager = require(\"editor/EditorManager\");\n    \n    var _popUps = [];\n        \n    /**\n     * Add Esc key handling for a popup DOM element.\n     *\n     * @param {!jQuery} $popUp jQuery object for the DOM element pop-up\n     * @param {function} removeHandler Pop-up specific remove (e.g. display:none or DOM removal)\n     * @param {?Boolean} autoAddRemove - Specify true to indicate the PopUpManager should \n     *      add/remove the popup from the DOM when the popup is open/closed. Specify false\n     *      when the popup is either always persistant in the DOM or the add/remove is handled \n     *      external to the PopupManager \n     *      \n     */\n    function addPopUp($popUp, removeHandler, autoAddRemove) {\n        autoAddRemove = autoAddRemove || false;\n        \n        _popUps.push($popUp[0]);\n        $popUp.data(\"PopUpManager-autoAddRemove\", autoAddRemove);\n        $popUp.data(\"PopUpManager-removeHandler\", removeHandler);\n        \n        if (autoAddRemove) {\n            $(window.document.body).append($popUp);\n        }\n    }\n    \n    /**\n     * Remove Esc key handling for a pop-up. Removes the pop-up from the DOM\n     * if the pop-up is currently visible and was not originally attached.\n     *\n     * @param {!jQuery} $popUp\n     */\n    function removePopUp($popUp) {\n        var index = _popUps.indexOf($popUp[0]);\n        if (index >= 0) {\n            var autoAddRemove = $popUp.data(\"PopUpManager-autoAddRemove\"),\n                removeHandler = $popUp.data(\"PopUpManager-removeHandler\");\n            \n            if (removeHandler && $popUp.find(\":visible\").length > 0) {\n                removeHandler();\n            }\n            \n            if (autoAddRemove) {\n                $popUp.remove();\n                _popUps = _popUps.slice(index);\n            }\n        }\n    }\n    \n    function _keydownCaptureListener(keyEvent) {\n        if (keyEvent.keyCode !== 27) { // escape key\n            return;\n        }\n        \n        // allow the popUp to prevent closing\n        var $popUp,\n            i,\n            event = new $.Event(\"popUpClose\");\n        \n        for (i = _popUps.length - 1; i >= 0; i--) {\n            $popUp = $(_popUps[i]);\n            \n            if ($popUp.find(\":visible\").length > 0) {\n                $popUp.trigger(event);\n                \n                if (!event.isDefaultPrevented()) {\n                    // Stop the DOM event from propagating\n                    keyEvent.stopImmediatePropagation();\n                    \n                    removePopUp($popUp);\n\n                    // TODO: right now Menus and Context Menus do not take focus away from\n                    // the editor. We need to have a focus manager to correctly manage focus\n                    // between editors and other UI elements.\n                    // For now we don't set focus here and assume individual popups\n                    // adjust focus if necessary\n                    // See story in Trello card #404\n                    //EditorManager.focusEditor();\n                }\n                \n                break;\n            }\n        }\n    }\n    \n    window.document.body.addEventListener(\"keydown\", _keydownCaptureListener, true);\n    \n    exports.addPopUp        = addPopUp;\n    exports.removePopUp     = removePopUp;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\ndefine('utils/ViewUtils',['require','exports','module'],function (require, exports, module) {\n    \n    \n    var SCROLL_SHADOW_HEIGHT = 5;\n    \n    /**\n     * @private\n     */\n    var _resizeHandlers = [];\n\n    /** \n     * Positions shadow background elements to indicate vertical scrolling.\n     * @param {!DOMElement} $displayElement the DOMElement that displays the shadow\n     * @param {!Object} $scrollElement the object that is scrolled\n     * @param {!DOMElement} $shadowTop div .scroller-shadow.top\n     * @param {!DOMElement} $shadowBottom div .scroller-shadow.bottom\n     * @param {boolean} isPositionFixed When using absolute position, top remains at 0.\n     */\n    function _updateScrollerShadow($displayElement, $scrollElement, $shadowTop, $shadowBottom, isPositionFixed) {\n        var offsetTop           = 0,\n            scrollElement       = $scrollElement.get(0),\n            scrollTop           = scrollElement.scrollTop,\n            topShadowOffset     = Math.min(scrollTop - SCROLL_SHADOW_HEIGHT, 0),\n            displayElementWidth = $displayElement.width();\n        \n        if ($shadowTop) {\n            $shadowTop.css(\"background-position\", \"0px \" + topShadowOffset + \"px\");\n            \n            if (isPositionFixed) {\n                offsetTop = $displayElement.offset().top;\n                $shadowTop.css(\"top\", offsetTop);\n            }\n            \n            if (isPositionFixed) {\n                $shadowTop.css(\"width\", displayElementWidth);\n            }\n        }\n        \n        if ($shadowBottom) {\n            var clientHeight        = scrollElement.clientHeight,\n                outerHeight         = $displayElement.outerHeight(),\n                scrollHeight        = scrollElement.scrollHeight,\n                bottomOffset        = outerHeight - clientHeight,\n                bottomShadowOffset  = SCROLL_SHADOW_HEIGHT; // outside of shadow div viewport\n            \n            if (scrollHeight > clientHeight) {\n                bottomShadowOffset -= Math.min(SCROLL_SHADOW_HEIGHT, (scrollHeight - (scrollTop + clientHeight)));\n            }\n    \n            $shadowBottom.css(\"background-position\", \"0px \" + bottomShadowOffset + \"px\");\n            $shadowBottom.css(\"top\", offsetTop + outerHeight - SCROLL_SHADOW_HEIGHT);\n            $shadowBottom.css(\"width\", displayElementWidth);\n        }\n    }\n\n    function getOrCreateShadow($displayElement, position, isPositionFixed) {\n        var $findShadow = $displayElement.find(\".scroller-shadow.\" + position);\n\n        if ($findShadow.length === 0) {\n            $findShadow = $(window.document.createElement(\"div\")).addClass(\"scroller-shadow \" + position);\n            $displayElement.append($findShadow);\n        }\n        \n        if (!isPositionFixed) {\n            // position is fixed by default\n            $findShadow.css(\"position\", \"absolute\");\n            $findShadow.css(position, \"0\");\n        }\n\n        return $findShadow;\n    }\n\n    /** \n     * Installs event handlers for updatng shadow background elements to indicate vertical scrolling.\n     * @param {!DOMElement} displayElement the DOMElement that displays the shadow. Must fire\n     *  \"contentChanged\" events when the element is resized or repositioned.\n     * @param {?Object} scrollElement the object that is scrolled. Must fire \"scroll\" events\n     *  when the element is scrolled. If null, the displayElement is used.\n     * @param {?boolean} showBottom optionally show the bottom shadow\n     */\n    function addScrollerShadow(displayElement, scrollElement, showBottom) {\n        // use fixed positioning when the display and scroll elements are the same\n        var isPositionFixed = false;\n        \n        if (!scrollElement) {\n            scrollElement = displayElement;\n            isPositionFixed = true;\n        }\n        \n        // update shadows when the scrolling element is scrolled\n        var $displayElement = $(displayElement),\n            $scrollElement = $(scrollElement);\n        \n        var $shadowTop = getOrCreateShadow($displayElement, \"top\", isPositionFixed);\n        var $shadowBottom = (showBottom) ? getOrCreateShadow($displayElement, \"bottom\", isPositionFixed) : null;\n        \n        var doUpdate = function () {\n            _updateScrollerShadow($displayElement, $scrollElement, $shadowTop, $shadowBottom, isPositionFixed);\n        };\n        \n        $scrollElement.on(\"scroll.scroller-shadow\", doUpdate);\n        $displayElement.on(\"contentChanged.scroller-shadow\", doUpdate);\n        \n        // update immediately\n        doUpdate();\n    }\n    \n    /**\n     * Remove scroller-shadow effect.\n     * @param {!DOMElement} displayElement the DOMElement that displays the shadow\n     * @param {?Object} scrollElement the object that is scrolled\n     */\n    function removeScrollerShadow(displayElement, scrollElement) {\n        if (!scrollElement) {\n            scrollElement = displayElement;\n        }\n        \n        var $displayElement = $(displayElement),\n            $scrollElement = $(scrollElement);\n        \n        // remove scrollerShadow elements from DOM\n        $displayElement.find(\".scroller-shadow.top\").remove();\n        $displayElement.find(\".scroller-shadow.bottom\").remove();\n        \n        // remove event handlers\n        $scrollElement.off(\"scroll.scroller-shadow\");\n        $displayElement.off(\"contentChanged.scroller-shadow\");\n    }\n    \n    /** \n     * Within a scrolling DOMElement, creates and positions a styled selection\n     * div to align a single selected list item from a ul list element.\n     *\n     * Assumptions:\n     * - scrollElement is a child of the #file-section div\n     * - ul list element fires a \"selectionChanged\" event after the\n     *   selectedClassName is assigned to a new list item\n     * \n     * @param {!DOMElement} scrollElement A DOMElement containing a ul list element\n     * @param {!string} selectedClassName A CSS class name on at most one list item in the contained list\n     */\n    function sidebarList($scrollerElement, selectedClassName, leafClassName) {\n        var $listElement = $scrollerElement.find(\"ul\"),\n            $selectionMarker,\n            $selectionTriangle,\n            $sidebar = $(\"#sidebar\"),\n            showTriangle = true;\n        \n        // build selectionMarker and position absolute within the scroller\n        $selectionMarker = $(window.document.createElement(\"div\")).addClass(\"sidebar-selection\");\n        $scrollerElement.prepend($selectionMarker);\n        \n        // enable scrolling\n        $scrollerElement.css(\"overflow\", \"auto\");\n        \n        // use relative postioning for clipping the selectionMarker within the scrollElement\n        $scrollerElement.css(\"position\", \"relative\");\n        \n        // build selectionTriangle and position fixed to the window\n        $selectionTriangle = $(window.document.createElement(\"div\")).addClass(\"sidebar-selection-triangle\");\n        \n        $scrollerElement.append($selectionTriangle);\n        \n        selectedClassName = \".\" + (selectedClassName || \"selected\");\n        \n        var updateSelectionTriangle = function () {\n            var selectionMarkerHeight = $selectionMarker.height(),\n                selectionMarkerOffset = $selectionMarker.offset(),\n                scrollerOffset = $scrollerElement.offset(),\n                triangleHeight = $selectionTriangle.outerHeight(),\n                scrollerTop = scrollerOffset.top,\n                scrollerBottom = scrollerTop + $scrollerElement.outerHeight(),\n                scrollerLeft = scrollerOffset.left,\n                triangleTop = selectionMarkerOffset.top;\n            \n            $selectionTriangle.css(\"top\", triangleTop);\n            $selectionTriangle.css(\"left\", $sidebar.width() - $selectionTriangle.outerWidth());\n            $selectionTriangle.toggleClass(\"triangle-visible\", showTriangle);\n            \n            var triangleClipOffsetYBy = Math.floor((selectionMarkerHeight - triangleHeight) / 2),\n                triangleBottom = triangleTop + triangleHeight + triangleClipOffsetYBy;\n            \n            if (triangleTop < scrollerTop || triangleBottom > scrollerBottom) {\n                $selectionTriangle.css(\"clip\", \"rect(\" + Math.max(scrollerTop - triangleTop - triangleClipOffsetYBy, 0) + \"px, auto, \" +\n                                           (triangleHeight - Math.max(triangleBottom - scrollerBottom, 0)) + \"px, auto)\");\n            } else {\n                $selectionTriangle.css(\"clip\", \"\");\n            }\n        };\n        \n        var updateSelectionMarker = function (event, reveal) {\n            // find the selected list item\n            var $listItem = $listElement.find(selectedClassName).closest(\"li\");\n            \n            if (leafClassName) {\n                showTriangle = $listItem.hasClass(leafClassName);\n            }\n            \n            // always hide selection visuals first to force layout (issue #719)\n            $selectionTriangle.hide();\n            $selectionMarker.hide();\n            \n            if ($listItem.length === 1) {\n                // list item position is relative to scroller\n                var selectionMarkerTop = $listItem.offset().top - $scrollerElement.offset().top + $scrollerElement.get(0).scrollTop;\n                    \n                // force selection width to match scroller\n                $selectionMarker.width($scrollerElement.get(0).scrollWidth);\n                \n                // move the selectionMarker position to align with the list item\n                $selectionMarker.css(\"top\", selectionMarkerTop);\n                $selectionMarker.show();\n                \n                updateSelectionTriangle();\n                $selectionTriangle.show();\n            \n                // fully scroll to the selectionMarker if it's not initially in the viewport\n                var scrollerElement = $scrollerElement.get(0),\n                    scrollerHeight = scrollerElement.clientHeight,\n                    selectionMarkerHeight = $selectionMarker.height(),\n                    selectionMarkerBottom = selectionMarkerTop + selectionMarkerHeight,\n                    currentScrollBottom = scrollerElement.scrollTop + scrollerHeight;\n                \n                // update scrollTop to reveal the selected list item\n                if (reveal) {\n                    if (selectionMarkerTop >= currentScrollBottom) {\n                        $listItem.get(0).scrollIntoView(false);\n                    } else if (selectionMarkerBottom <= scrollerElement.scrollTop) {\n                        $listItem.get(0).scrollIntoView(true);\n                    }\n                }\n            }\n        };\n        \n        $listElement.on(\"selectionChanged\", updateSelectionMarker);\n        $scrollerElement.on(\"scroll\", updateSelectionTriangle);\n        \n        // update immediately\n        updateSelectionMarker();\n        \n        // update clipping when the window resizes\n        _resizeHandlers.push(updateSelectionTriangle);\n    }\n    \n    /**\n     * @private\n     */\n    function _handleResize() {\n        _resizeHandlers.forEach(function (f) {\n            f.apply();\n        });\n    }\n\n    /**\n     * Within a scrolling DOMElement, if necessary, scroll element into viewport.\n     *\n     * To Perform the minimum amount of scrolling necessary, cases should be handled as follows:\n     * - element already completely in view : no scrolling\n     * - element above    viewport          : scroll view so element is at top\n     * - element left of  viewport          : scroll view so element is at left\n     * - element below    viewport          : scroll view so element is at bottom\n     * - element right of viewport          : scroll view so element is at right\n     *\n     * Assumptions:\n     * - $view is a scrolling container\n     *\n     * @param {!DOMElement} $view - A jQuery scrolling container\n     * @param {!DOMElement} $element - A jQuery element\n     * @param {?boolean} scrollHorizontal - whether to also scroll horizonally\n     */\n    function scrollElementIntoView($view, $element, scrollHorizontal) {\n        var viewOffset = $view.offset(),\n            viewScroller = $view.get(0),\n            element = $element.get(0),\n            elementOffset = $element.offset();\n\n        // scroll minimum amount\n        if (elementOffset.top + $element.height() >= (viewOffset.top + $view.height())) {\n            // below viewport\n            element.scrollIntoView(false);\n        } else if (elementOffset.top <= viewOffset.top) {\n            // above viewport\n            element.scrollIntoView(true);\n        }\n\n        if (scrollHorizontal) {\n            if (elementOffset.left < 0) {\n                $view.scrollLeft($view.scrollLeft() + elementOffset.left);\n            } else if (elementOffset.left + $element.width() >= viewOffset.left + $view.width()) {\n                $view.scrollLeft(elementOffset.left - viewOffset.left);\n            }\n        }\n    }\n    \n    // handle all resize handlers in a single listener\n    $(window).resize(_handleResize);\n\n    // Define public API\n    exports.SCROLL_SHADOW_HEIGHT    = SCROLL_SHADOW_HEIGHT;\n    exports.addScrollerShadow       = addScrollerShadow;\n    exports.removeScrollerShadow    = removeScrollerShadow;\n    exports.sidebarList             = sidebarList;\n    exports.scrollElementIntoView   = scrollElementIntoView;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window, brackets */\n\ndefine('editor/CodeHintManager',['require','exports','module','language/HTMLUtils','command/Menus','utils/StringUtils','editor/EditorManager','widgets/PopUpManager','utils/ViewUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var HTMLUtils       = require(\"language/HTMLUtils\"),\n        Menus           = require(\"command/Menus\"),\n        StringUtils     = require(\"utils/StringUtils\"),\n        EditorManager   = require(\"editor/EditorManager\"),\n        PopUpManager    = require(\"widgets/PopUpManager\"),\n        ViewUtils       = require(\"utils/ViewUtils\");\n\n\n    var hintProviders = [],\n        hintList,\n        shouldShowHintsOnKeyUp = false;\n\n\n    /**\n     * @constructor\n     *\n     * Displays a popup list of code completions.\n     * Currently only HTML tags are supported, but this will greatly be extended in coming sprint\n     * to include: extensibility API, HTML attributes hints, JavaScript hints, CSS hints\n     */\n    function CodeHintList() {\n        this.currentProvider = null;\n        this.query = {queryStr: null};\n        this.displayList = [];\n        this.options = {\n            maxResults: 999\n        };\n\n        this.opened = false;\n        this.selectedIndex = -1;\n        this.editor = null;\n\n        this.$hintMenu = $(\"<li class='dropdown codehint-menu'></li>\");\n        var $toggle = $(\"<a href='#' class='dropdown-toggle'></a>\")\n            .hide();\n\n        this.$hintMenu.append($toggle)\n            .append(\"<ul class='dropdown-menu'></ul>\");\n    }\n\n    /**\n     * @private\n     * Enters the code completion text into the editor\n     * @string {string} completion - text to insert into current code editor\n     */\n    CodeHintList.prototype._handleItemClick = function (completion) {\n        this.currentProvider.handleSelect(completion, this.editor, this.editor.getCursorPos());\n        this.close();\n    };\n\n    /**\n     * Adds a single item to the hint list\n     * @param {string} name\n     */\n    CodeHintList.prototype.addItem = function (name) {\n        var self = this;\n        var displayName = name.replace(\n            new RegExp(StringUtils.regexEscape(this.query.queryStr), \"i\"),\n            \"<strong>$&</strong>\"\n        );\n\n        var $item = $(\"<li><a href='#'><span class='codehint-item'>\" + displayName + \"</span></a></li>\")\n            .on(\"click\", function (e) {\n                // Don't let the click propagate upward (otherwise it will hit the close handler in\n                // bootstrap-dropdown).\n                e.stopPropagation();\n                self._handleItemClick(name);\n            });\n\n        this.$hintMenu.find(\"ul.dropdown-menu\")\n            .append($item);\n    };\n\n    /**\n     * Rebuilds the hint list based on this.query\n     */\n    CodeHintList.prototype.updateList = function () {\n        this.displayList = this.currentProvider.search(this.query);\n        this.buildListView();\n    };\n\n    /**\n     * Removes all list items from hint list\n     */\n    CodeHintList.prototype.clearList = function () {\n        this.$hintMenu.find(\"li\").remove();\n    };\n            \n    /**\n     * Rebuilds the list items for the hint list based on this.displayList\n     */\n    CodeHintList.prototype.buildListView = function () {\n        this.clearList();\n        var self = this;\n        var count = 0;\n        $.each(this.displayList, function (index, item) {\n            if (count > self.options.maxResults) {\n                return false;\n            }\n            self.addItem(item);\n            count++;\n        });\n\n        if (count === 0) {\n            this.close();\n        } else {\n            // Select the first item in the list\n            this.setSelectedIndex(0);\n        }\n    };\n\n\n    /**\n     * Selects the item in the hint list specified by index\n     * @param {Number} index\n     */\n    CodeHintList.prototype.setSelectedIndex = function (index) {\n        var items = this.$hintMenu.find(\"li\");\n        \n        // Range check\n        index = Math.max(0, Math.min(index, items.length - 1));\n        \n        // Clear old highlight\n        if (this.selectedIndex !== -1) {\n            $(items[this.selectedIndex]).find(\"a\").removeClass(\"highlight\");\n        }\n        \n        // Highlight the new selected item\n        this.selectedIndex = index;\n\n        if (this.selectedIndex !== -1) {\n            var $item = $(items[this.selectedIndex]);\n            var $view = this.$hintMenu.find(\"ul.dropdown-menu\");\n\n            ViewUtils.scrollElementIntoView($view, $item, false);\n            $item.find(\"a\").addClass(\"highlight\");\n        }\n    };\n    \n    /**\n     * Handles key presses when the hint list is being displayed\n     * @param {Editor} editor\n     * @param {KeyBoardEvent} keyEvent\n     */\n    CodeHintList.prototype.handleKeyEvent = function (editor, event) {\n        var keyCode = event.keyCode;\n        \n        // Up arrow, down arrow and enter key are always handled here\n        if (event.type !== \"keypress\" &&\n                (keyCode === 38 || keyCode === 40 || keyCode === 13 ||\n                keyCode === 33 || keyCode === 34)) {\n\n            if (event.type === \"keydown\") {\n                if (keyCode === 38) {\n                    // Up arrow\n                    this.setSelectedIndex(this.selectedIndex - 1);\n                } else if (keyCode === 40) {\n                    // Down arrow\n                    this.setSelectedIndex(this.selectedIndex + 1);\n                } else if (keyCode === 33) {\n                    // Page Up\n                    this.setSelectedIndex(this.selectedIndex - this.getItemsPerPage());\n                } else if (keyCode === 34) {\n                    // Page Down\n                    this.setSelectedIndex(this.selectedIndex + this.getItemsPerPage());\n                } else {\n                    // Enter/return key\n                    // Trigger a click handler to commmit the selected item\n                    $(this.$hintMenu.find(\"li\")[this.selectedIndex]).triggerHandler(\"click\");\n                }\n            }\n            \n            event.preventDefault();\n            return;\n        }\n        \n        // All other key events trigger a rebuild of the list, but only\n        // on keyup events\n        if (event.type !== \"keyup\") {\n            return;\n        }\n\n        this.query = this.currentProvider.getQueryInfo(this.editor, this.editor.getCursorPos());\n        this.updateList();\n\n        // Update the CodeHintList location\n        if (this.displayList.length) {\n            var hintPos = this.calcHintListLocation();\n            this.$hintMenu.css({\"left\": hintPos.left, \"top\": hintPos.top});\n        }\n    };\n\n    /**\n     * Return true if the CodeHintList is open.\n     * @return {Boolean}\n     */\n    CodeHintList.prototype.isOpen = function () {\n        // We don't get a notification when the dropdown closes. The best\n        // we can do is keep an \"opened\" flag and check to see if we\n        // still have the \"open\" class applied.\n        if (this.opened && !this.$hintMenu.hasClass(\"open\")) {\n            this.opened = false;\n        }\n        \n        return this.opened;\n    };\n    \n    /**\n     * Displays the hint list at the current cursor position\n     * @param {Editor} editor\n     */\n    CodeHintList.prototype.open = function (editor) {\n        var self = this;\n        this.editor = editor;\n\n        Menus.closeAll();\n\n        this.currentProvider = null;\n        $.each(hintProviders, function (index, item) {\n            var query = item.getQueryInfo(self.editor, self.editor.getCursorPos());\n            if (query.queryStr !== null) {\n                self.query = query;\n                self.currentProvider = item;\n                return false;\n            }\n        });\n        if (!this.currentProvider) {\n            return;\n        }\n\n        this.updateList();\n    \n        if (this.displayList.length) {\n            // Need to add the menu to the DOM before trying to calculate its ideal location.\n            $(\"#codehint-menu-bar > ul\").append(this.$hintMenu);\n            \n            var hintPos = this.calcHintListLocation();\n            \n            this.$hintMenu.addClass(\"open\")\n                       .css({\"left\": hintPos.left, \"top\": hintPos.top});\n            this.opened = true;\n            \n            PopUpManager.addPopUp(this.$hintMenu, function () {\n                self.close();\n            });\n        }\n    };\n\n    /**\n     * Closes the hint list\n     */\n    CodeHintList.prototype.close = function () {\n        // TODO: Due to #1381, this won't get called if the user clicks out of the code hint menu.\n        // That's (sort of) okay right now since it doesn't really matter if a single old invisible\n        // code hint list is lying around (it'll get closed the next time the user pops up a code\n        // hint). Once #1381 is fixed this issue should go away.\n        this.$hintMenu.removeClass(\"open\");\n        this.opened = false;\n        this.currentProvider = null;\n        \n        PopUpManager.removePopUp(this.$hintMenu);\n        this.$hintMenu.remove();\n        if (hintList === this) {\n            hintList = null;\n        }\n    };\n        \n    /**\n     * Computes top left location for hint list so that the list is not clipped by the window\n     * @return {Object.<left: Number, top: Number> }\n     */\n    CodeHintList.prototype.calcHintListLocation = function () {\n        var cursor = this.editor._codeMirror.cursorCoords(),\n            posTop  = cursor.y,\n            posLeft = cursor.x,\n            $window = $(window),\n            $menuWindow = this.$hintMenu.children(\"ul\");\n\n        // TODO Ty: factor out menu repositioning logic so code hints and Context menus share code\n        // adjust positioning so menu is not clipped off bottom or right\n        var bottomOverhang = posTop + 25 + $menuWindow.height() - $window.height();\n        if (bottomOverhang > 0) {\n            posTop -= (27 + $menuWindow.height());\n        }\n        // todo: should be shifted by line height\n        posTop -= 15;   // shift top for hidden parent element\n        //posLeft += 5;\n\n        var rightOverhang = posLeft + $menuWindow.width() - $window.width();\n        if (rightOverhang > 0) {\n            posLeft = Math.max(0, posLeft - rightOverhang);\n        }\n\n        return {left: posLeft, top: posTop};\n    };\n\n    /**\n     * @private\n     * Calculate the number of items per scroll page. Used for PageUp and PageDown.\n     * @return {number}\n     */\n    CodeHintList.prototype.getItemsPerPage = function () {\n        var itemsPerPage = 1,\n            $items = this.$hintMenu.find(\"li\"),\n            $view = this.$hintMenu.find(\"ul.dropdown-menu\"),\n            itemHeight;\n\n        if ($items.length !== 0) {\n            itemHeight = $($items[0]).height();\n            if (itemHeight) {\n                // round down to integer value\n                itemsPerPage = Math.floor($view.height() / itemHeight);\n                itemsPerPage = Math.max(1, Math.min(itemsPerPage, $items.length));\n            }\n        }\n\n        return itemsPerPage;\n    };\n        \n     /**\n      * Show the code hint list near the current cursor position for the specified editor\n      * @param {Editor}\n      */\n    function showHint(editor) {\n        if (hintList) {\n            hintList.close();\n        }\n        hintList = new CodeHintList();\n        hintList.open(editor);\n    }\n    \n    /**\n     * Handles keys related to displaying, searching, and navigating the hint list\n     * @param {Editor} editor\n     * @param {KeyboardEvent} event\n     */\n    function handleKeyEvent(editor, event) {\n        var provider = null;\n        \n        // Check for Control+Space\n        if (event.type === \"keydown\" && event.keyCode === 32 && event.ctrlKey) {\n            showHint(editor);\n            event.preventDefault();\n        } else if (event.type === \"keypress\") {\n            // Check if any provider wants to show hints on this key.\n            $.each(hintProviders, function (index, item) {\n                if (item.shouldShowHintsOnKey(String.fromCharCode(event.charCode))) {\n                    provider = item;\n                    return false;\n                }\n            });\n            \n            shouldShowHintsOnKeyUp = !!provider;\n        } else if (event.type === \"keyup\") {\n            if (shouldShowHintsOnKeyUp) {\n                shouldShowHintsOnKeyUp = false;\n                showHint(editor);\n            }\n        }\n\n        // Pass to the hint list, if it's open\n        if (hintList && hintList.isOpen()) {\n            shouldShowHintsOnKeyUp = false;\n            hintList.handleKeyEvent(editor, event);\n        }\n    }\n\n    /**\n     * Registers an object that is able to provide code hints. When the user requests a code\n     * hint getQueryInfo() will be called on every hint provider. Providers should examine\n     * the state of the editor and return a search query object with a filter string if hints \n     * can be provided. search() will then be called allowing the hint provider to create a \n     * list of hints for the search query. When the user chooses a hint handleSelect() is called\n     * so that the hint provider can insert the hint into the editor.\n     *\n     * @param {Object.< getQueryInfo: function(editor, cursor),\n     *                  search: function(string),\n     *                  handleSelect: function(string, Editor, cursor),\n     *                  shouldShowHintsOnKey: function(string)>}\n     *\n     * Parameter Details:\n     * - getQueryInfo - examines cursor location of editor and returns an object representing\n     *      the search query to be used for hinting. queryStr is a required property of the search object\n     *      and a client may provide other properties on the object to carry more context about the query.\n     * - search - takes a query object and returns an array of hint strings based on the queryStr property\n     *      of the query object.\n     * - handleSelect - takes a completion string and inserts it into the editor near the cursor\n     *      position\n     * - shouldShowHintsOnKey - inspects the char code and returns true if it wants to show code hints on that key.\n     */\n    function registerHintProvider(providerInfo) {\n        hintProviders.push(providerInfo);\n    }\n\n    /**\n     * Expose CodeHintList for unit testing\n     */\n    function _getCodeHintList() {\n        return hintList;\n    }\n    \n    // Define public API\n    exports.handleKeyEvent          = handleKeyEvent;\n    exports.showHint                = showHint;\n    exports._getCodeHintList        = _getCodeHintList;\n    exports.registerHintProvider    = registerHintProvider;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror */\n\n/**\n */\ndefine('document/TextRange',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * @constructor\n     *\n     * Stores a range of lines that is automatically maintained as the Document changes. The range\n     * MAY drop out of sync with the Document in certain edge cases; startLine & endLine will become\n     * null when that happens.\n     *\n     * Important: you must dispose() a TextRange when you're done with it. Because TextRange addRef()s\n     * the Document (in order to listen to it), you will leak Documents otherwise.\n     *\n     * TextRange dispatches two events:\n     *  - change -- When the range changes (due to a Document change)\n     *  - lostSync -- When the backing Document changes in such a way that the range can no longer\n     *          accurately be maintained. Generally, occurs whenever an edit spans a range boundary.\n     *          After this, startLine & endLine will be unusable (set to null).\n     * These events only ever occur in response to Document changes, so if you are already listening\n     * to the Document, you could ignore the TextRange events and just read its updated value in your\n     * own Document change handler.\n     *\n     * @param {!Document} document\n     * @param {number} startLine First line in range (0-based, inclusive)\n     * @param {number} endLine   Last line in range (0-based, inclusive)\n     */\n    function TextRange(document, startLine, endLine) {\n        this.startLine = startLine;\n        this.endLine = endLine;\n        \n        this.document = document;\n        document.addRef();\n        // store this-bound version of listener so we can remove them later\n        this._handleDocumentChange = this._handleDocumentChange.bind(this);\n        $(document).on(\"change\", this._handleDocumentChange);\n    }\n    \n    /** Detaches from the Document. The TextRange will no longer update or send change events */\n    TextRange.prototype.dispose = function (editor, change) {\n        // Disconnect from Document\n        this.document.releaseRef();\n        $(this.document).off(\"change\", this._handleDocumentChange);\n    };\n    \n    \n    /** @type {!Document} */\n    TextRange.prototype.document = null;\n    /** @type {?number} Null after \"lostSync\" is dispatched */\n    TextRange.prototype.startLine = null;\n    /** @type {?number} Null after \"lostSync\" is dispatched */\n    TextRange.prototype.endLine = null;\n    \n    \n    /**\n     * Applies a single Document change object (out of the linked list of multiple such objects)\n     * to this range. Returns true if the range was changed as a result.\n     */\n    TextRange.prototype._applySingleChangeToRange = function (change) {\n        // console.log(this + \" applying change to (\" +\n        //         (change.from && (change.from.line+\",\"+change.from.ch)) + \" - \" +\n        //         (change.to && (change.to.line+\",\"+change.to.ch)) + \")\");\n        \n        // Special case: the range is no longer meaningful since the entire text was replaced\n        if (!change.from || !change.to) {\n            this.startLine = null;\n            this.endLine = null;\n            return true;\n            \n        // Special case: certain changes around the edges of the range are problematic, because\n        // if they're undone, we'll be unable to determine how to fix up the range to include the\n        // undone content. (The \"undo\" will just look like an insertion outside our bounds.) So\n        // in those cases, we destroy the range instead of fixing it up incorrectly. The specific\n        // cases are:\n        // 1. Edit crosses the start boundary of the inline editor (defined as character 0 \n        //    of the first line).\n        // 2. Edit crosses the end boundary of the inline editor (defined as the newline at\n        //    the end of the last line).\n        // Note: we also used to disallow edits that start at the beginning of the range (character 0\n        //    of the first line) if they crossed a newline. This was a vestige from before case #1\n        //    was added; now that edits crossing the top boundary (actually, undos of such edits) are\n        //    out of the picture, edits on the first line of the range unambiguously belong inside it.\n        } else if ((change.from.line < this.startLine && change.to.line >= this.startLine) ||\n                   (change.from.line <= this.endLine && change.to.line > this.endLine)) {\n            this.startLine = null;\n            this.endLine = null;\n            return true;\n            \n        // Normal case: update the range end points if any content was added before them. Note that\n        // we don't rely on line handles for this since we want to gracefully handle cases where the\n        // start or end line was deleted during a change.\n        } else {\n            var numAdded = change.text.length - (change.to.line - change.from.line + 1);\n            var hasChanged = false;\n            \n            // This logic is so simple because we've already excluded all cases where the change\n            // crosses the range boundaries\n            if (change.to.line < this.startLine) {\n                this.startLine += numAdded;\n                hasChanged = true;\n            }\n            if (change.to.line <= this.endLine) {\n                this.endLine += numAdded;\n                hasChanged = true;\n            }\n            \n            // console.log(\"Now \" + this);\n            \n            return hasChanged;\n        }\n    };\n    \n    /**\n     * Updates the range based on the changeList from a Document \"change\" event. Dispatches a\n     * \"change\" event if the range was adjusted at all. Dispatches a \"lostSync\" event instead if the\n     * range can no longer be accurately maintained.\n     */\n    TextRange.prototype._applyChangesToRange = function (changeList) {\n        var hasChanged = false;\n        var change;\n        for (change = changeList; change; change = change.next) {\n            // Apply this step of the change list\n            var result = this._applySingleChangeToRange(change);\n            hasChanged = hasChanged || result;\n            \n            // If we lost sync with the range, just bail now\n            if (this.startLine === null || this.endLine === null) {\n                $(this).triggerHandler(\"lostSync\");\n                break;\n            }\n        }\n        \n        if (hasChanged) {\n            $(this).triggerHandler(\"change\");\n        }\n    };\n    \n    TextRange.prototype._handleDocumentChange = function (event, doc, changeList) {\n        this._applyChangesToRange(changeList);\n    };\n    \n    \n    /* (pretty toString(), to aid debugging) */\n    TextRange.prototype.toString = function () {\n        return \"[TextRange \" + this.startLine + \"-\" + this.endLine + \" in \" + this.document + \"]\";\n    };\n    \n    \n    // Define public API\n    exports.TextRange = TextRange;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\n/**\n * Editor is a 1-to-1 wrapper for a CodeMirror editor instance. It layers on Brackets-specific\n * functionality and provides APIs that cleanly pass through the bits of CodeMirror that the rest\n * of our codebase may want to interact with. An Editor is always backed by a Document, and stays\n * in sync with its content; because Editor keeps the Document alive, it's important to always\n * destroy() an Editor that's going away so it can release its Document ref.\n *\n * For now, there's a distinction between the \"master\" Editor for a Document - which secretly acts\n * as the Document's internal model of the text state - and the multitude of \"slave\" secondary Editors\n * which, via Document, sync their changes to and from that master.\n *\n * For now, direct access to the underlying CodeMirror object is still possible via _codeMirror --\n * but this is considered deprecated and may go away.\n *  \n * The Editor object dispatches the following events:\n *    - keyEvent -- When any key event happens in the editor (whether it changes the text or not).\n *          Event handlers are passed ({Editor}, {KeyboardEvent}). The 2nd arg is the raw DOM event.\n *          Note: most listeners will only want to respond when event.type === \"keypress\".\n *    - cursorActivity -- When the user moves the cursor or changes the selection, or an edit occurs.\n *          Note: do not listen to this in order to be generally informed of edits--listen to the\n *          \"change\" event on Document instead.\n *    - scroll -- When the editor is scrolled, either by user action or programmatically.\n *    - lostContent -- When the backing Document changes in such a way that this Editor is no longer\n *          able to display accurate text. This occurs if the Document's file is deleted, or in certain\n *          Document->editor syncing edge cases that we do not yet support (the latter cause will\n *          eventually go away). \n *\n * The Editor also dispatches \"change\" events internally, but you should listen for those on\n * Documents, not Editors.\n *\n * These are jQuery events, so to listen for them you do something like this:\n *    $(editorInstance).on(\"eventname\", handler);\n */\ndefine('editor/Editor',['require','exports','module','editor/EditorManager','editor/CodeHintManager','command/Commands','command/CommandManager','command/Menus','utils/PerfUtils','strings','document/TextRange','utils/ViewUtils'],function (require, exports, module) {\n    \n    \n    var EditorManager   = require(\"editor/EditorManager\"),\n        CodeHintManager = require(\"editor/CodeHintManager\"),\n        Commands        = require(\"command/Commands\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        Menus           = require(\"command/Menus\"),\n        PerfUtils       = require(\"utils/PerfUtils\"),\n        Strings         = require(\"strings\"),\n        TextRange       = require(\"document/TextRange\").TextRange,\n        ViewUtils       = require(\"utils/ViewUtils\");\n    \n\n    /**\n     * @private\n     * Handle Tab key press.\n     * @param {!CodeMirror} instance CodeMirror instance.\n     */\n    function _handleTabKey(instance) {\n        // Tab key handling is done as follows:\n        // 1. If the selection is before any text and the indentation is to the left of \n        //    the proper indentation then indent it to the proper place. Otherwise,\n        //    add another tab. In either case, move the insertion point to the \n        //    beginning of the text.\n        // 2. If the selection is after the first non-space character, and is not an \n        //    insertion point, indent the entire line(s).\n        // 3. If the selection is after the first non-space character, and is an \n        //    insertion point, insert a tab character or the appropriate number \n        //    of spaces to pad to the nearest tab boundary.\n        var from = instance.getCursor(true),\n            to = instance.getCursor(false),\n            line = instance.getLine(from.line),\n            indentAuto = false,\n            insertTab = false;\n        \n        if (from.line === to.line) {\n            if (line.search(/\\S/) > to.ch || to.ch === 0) {\n                indentAuto = true;\n            }\n        }\n\n        if (indentAuto) {\n            var currentLength = line.length;\n            CodeMirror.commands.indentAuto(instance);\n            // If the amount of whitespace didn't change, insert another tab\n            if (instance.getLine(from.line).length === currentLength) {\n                insertTab = true;\n                to.ch = 0;\n            }\n        } else if (instance.somethingSelected()) {\n            CodeMirror.commands.indentMore(instance);\n        } else {\n            insertTab = true;\n        }\n        \n        if (insertTab) {\n            if (instance.getOption(\"indentWithTabs\")) {\n                CodeMirror.commands.insertTab(instance);\n            } else {\n                var i, ins = \"\", numSpaces = instance.getOption(\"tabSize\");\n                numSpaces -= to.ch % numSpaces;\n                for (i = 0; i < numSpaces; i++) {\n                    ins += \" \";\n                }\n                instance.replaceSelection(ins, \"end\");\n            }\n        }\n    }\n    \n    /**\n     * @private\n     * Handle left arrow, right arrow, backspace and delete keys when soft tabs are used.\n     * @param {!CodeMirror} instance CodeMirror instance \n     * @param {number} direction Direction of movement: 1 for forward, -1 for backward\n     * @param {function} functionName name of the CodeMirror function to call\n     * @return {boolean} true if key was handled\n     */\n    function _handleSoftTabNavigation(instance, direction, functionName) {\n        var handled = false;\n        if (!instance.getOption(\"indentWithTabs\")) {\n            var cursor = instance.getCursor(),\n                tabSize = instance.getOption(\"tabSize\"),\n                jump = cursor.ch % tabSize,\n                line = instance.getLine(cursor.line);\n\n            if (direction === 1) {\n                jump = tabSize - jump;\n\n                if (cursor.ch + jump > line.length) { // Jump would go beyond current line\n                    return false;\n                }\n\n                if (line.substr(cursor.ch, jump).search(/\\S/) === -1) {\n                    instance[functionName](jump, \"char\");\n                    handled = true;\n                }\n            } else {\n                // Quick exit if we are at the beginning of the line\n                if (cursor.ch === 0) {\n                    return false;\n                }\n                \n                // If we are on the tab boundary, jump by the full amount, \n                // but not beyond the start of the line.\n                if (jump === 0) {\n                    jump = tabSize;\n                }\n\n                // Search backwards to the first non-space character\n                var offset = line.substr(cursor.ch - jump, jump).search(/\\s*$/g);\n\n                if (offset !== -1) { // Adjust to jump to first non-space character\n                    jump -= offset;\n                }\n\n                if (jump > 0) {\n                    instance[functionName](-jump, \"char\");\n                    handled = true;\n                }\n            }\n        }\n\n        return handled;\n    }\n    \n    /**\n     * Checks if the user just typed a closing brace/bracket/paren, and considers automatically\n     * back-indenting it if so.\n     */\n    function _checkElectricChars(jqEvent, editor, event) {\n        var instance = editor._codeMirror;\n        if (event.type === \"keypress\") {\n            var keyStr = String.fromCharCode(event.which || event.keyCode);\n            if (/[\\]\\{\\}\\)]/.test(keyStr)) {\n                // If all text before the cursor is whitespace, auto-indent it\n                var cursor = instance.getCursor();\n                var lineStr = instance.getLine(cursor.line);\n                var nonWS = lineStr.search(/\\S/);\n                \n                if (nonWS === -1 || nonWS >= cursor.ch) {\n                    // Need to do the auto-indent on a timeout to ensure\n                    // the keypress is handled before auto-indenting.\n                    // This is the same timeout value used by the\n                    // electricChars feature in CodeMirror.\n                    window.setTimeout(function () {\n                        instance.indentLine(cursor.line);\n                    }, 75);\n                }\n            }\n        }\n    }\n\n    function _handleKeyEvents(jqEvent, editor, event) {\n        _checkElectricChars(jqEvent, editor, event);\n\n        // Pass the key event to the code hint manager. It may call preventDefault() on the event.\n        CodeHintManager.handleKeyEvent(editor, event);\n    }\n\n    function _handleSelectAll() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            editor._selectAllVisible();\n        }\n    }\n    \n    \n    /**\n     * List of all current (non-destroy()ed) Editor instances. Needed when changing global preferences\n     * that affect all editors, e.g. tabbing or color scheme settings.\n     * @type {Array.<Editor>}\n     */\n    var _instances = [];\n    \n    /** @type {boolean}  Global setting: When inserting new text, use tab characters? (instead of spaces) */\n    var _useTabChar = false;\n    \n    \n    \n    /**\n     * @constructor\n     *\n     * Creates a new CodeMirror editor instance bound to the given Document. The Document need not have\n     * a \"master\" Editor realized yet, even if makeMasterEditor is false; in that case, the first time\n     * an edit occurs we will automatically ask EditorManager to create a \"master\" editor to render the\n     * Document modifiable.\n     *\n     * ALWAYS call destroy() when you are done with an Editor - otherwise it will leak a Document ref.\n     *\n     * @param {!Document} document  \n     * @param {!boolean} makeMasterEditor  If true, this Editor will set itself as the (secret) \"master\"\n     *          Editor for the Document. If false, this Editor will attach to the Document as a \"slave\"/\n     *          secondary editor.\n     * @param {!string} mode  Syntax-highlighting language mode; \"\" means plain-text mode.\n     *          See {@link EditorUtils#getModeFromFileExtension()}.\n     * @param {!jQueryObject} container  Container to add the editor to.\n     * @param {!Object<string, function(Editor)>} additionalKeys  Mapping of keyboard shortcuts to\n     *          custom handler functions. Mapping is in CodeMirror format\n     * @param {{startLine: number, endLine: number}=} range If specified, range of lines within the document\n     *          to display in this editor. Inclusive.\n     */\n    function Editor(document, makeMasterEditor, mode, container, additionalKeys, range) {\n        var self = this;\n        \n        _instances.push(this);\n        \n        // Attach to document: add ref & handlers\n        this.document = document;\n        document.addRef();\n        \n        if (range) {    // attach this first: want range updated before we process a change\n            this._visibleRange = new TextRange(document, range.startLine, range.endLine);\n        }\n        \n        // store this-bound version of listeners so we can remove them later\n        this._handleDocumentChange = this._handleDocumentChange.bind(this);\n        this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);\n        $(document).on(\"change\", this._handleDocumentChange);\n        $(document).on(\"deleted\", this._handleDocumentDeleted);\n        \n        // (if makeMasterEditor, we attach the Doc back to ourselves below once we're fully initialized)\n        \n        this._inlineWidgets = [];\n        \n        // Editor supplies some standard keyboard behavior extensions of its own\n        var codeMirrorKeyMap = {\n            \"Tab\": _handleTabKey,\n            \"Shift-Tab\": \"indentLess\",\n\n            \"Left\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, -1, \"moveH\")) {\n                    CodeMirror.commands.goCharLeft(instance);\n                }\n            },\n            \"Right\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, 1, \"moveH\")) {\n                    CodeMirror.commands.goCharRight(instance);\n                }\n            },\n            \"Backspace\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, -1, \"deleteH\")) {\n                    CodeMirror.commands.delCharLeft(instance);\n                }\n            },\n            \"Delete\": function (instance) {\n                if (!_handleSoftTabNavigation(instance, 1, \"deleteH\")) {\n                    CodeMirror.commands.delCharRight(instance);\n                }\n            },\n            \"Esc\": function (instance) {\n                self.removeAllInlineWidgets();\n            },\n            \"Shift-Delete\": \"cut\",\n            \"Ctrl-Insert\": \"copy\",\n            \"Shift-Insert\": \"paste\"\n        };\n        \n        EditorManager.mergeExtraKeys(self, codeMirrorKeyMap, additionalKeys);\n        \n        // We'd like null/\"\" to mean plain text mode. CodeMirror defaults to plaintext for any\n        // unrecognized mode, but it complains on the console in that fallback case: so, convert\n        // here so we're always explicit, avoiding console noise.\n        if (!mode) {\n            mode = \"text/plain\";\n        }\n        \n        // Create the CodeMirror instance\n        // (note: CodeMirror doesn't actually require using 'new', but jslint complains without it)\n        this._codeMirror = new CodeMirror(container, {\n            electricChars: false,   // we use our own impl of this to avoid CodeMirror bugs; see _checkElectricChars()\n            indentUnit: 4,\n            indentWithTabs: _useTabChar,\n            lineNumbers: true,\n            matchBrackets: true,\n            dragDrop: false,    // work around issue #1123\n            extraKeys: codeMirrorKeyMap\n        });\n        \n        this._installEditorListeners();\n        \n        $(this)\n            .on(\"keyEvent\", _handleKeyEvents)\n            .on(\"change\", this._handleEditorChange.bind(this));\n        \n        // Set code-coloring mode BEFORE populating with text, to avoid a flash of uncolored text\n        this._codeMirror.setOption(\"mode\", mode);\n        \n        // Initially populate with text. This will send a spurious change event, so need to make\n        // sure this is understood as a 'sync from document' case, not a genuine edit\n        this._duringSync = true;\n        this._resetText(document.getText());\n        this._duringSync = false;\n        \n        if (range) {\n            // Hide all lines other than those we want to show. We do this rather than trimming the\n            // text itself so that the editor still shows accurate line numbers.\n            this._codeMirror.operation(function () {\n                var i;\n                for (i = 0; i < range.startLine; i++) {\n                    self._hideLine(i);\n                }\n                var lineCount = self.lineCount();\n                for (i = range.endLine + 1; i < lineCount; i++) {\n                    self._hideLine(i);\n                }\n            });\n            this.setCursorPos(range.startLine, 0);\n        }\n\n        // Now that we're fully initialized, we can point the document back at us if needed\n        if (makeMasterEditor) {\n            document._makeEditable(this);\n        }\n        \n        // Add scrollTop property to this object for the scroll shadow code to use\n        Object.defineProperty(this, \"scrollTop\", {\n            get: function () {\n                return this._codeMirror.getScrollInfo().y;\n            }\n        });\n    }\n    \n    /**\n     * Removes this editor from the DOM and detaches from the Document. If this is the \"master\"\n     * Editor that is secretly providing the Document's backing state, then the Document reverts to\n     * a read-only string-backed mode.\n     */\n    Editor.prototype.destroy = function () {\n        // CodeMirror docs for getWrapperElement() say all you have to do is \"Remove this from your\n        // tree to delete an editor instance.\"\n        $(this.getRootElement()).remove();\n        \n        _instances.splice(_instances.indexOf(this), 1);\n        \n        // Disconnect from Document\n        this.document.releaseRef();\n        $(this.document).off(\"change\", this._handleDocumentChange);\n        $(this.document).off(\"deleted\", this._handleDocumentDeleted);\n        \n        if (this._visibleRange) {   // TextRange also refs the Document\n            this._visibleRange.dispose();\n        }\n        \n        // If we're the Document's master editor, disconnecting from it has special meaning\n        if (this.document._masterEditor === this) {\n            this.document._makeNonEditable();\n        }\n        \n        // Destroying us destroys any inline widgets we're hosting. Make sure their closeCallbacks\n        // run, at least, since they may also need to release Document refs\n        this._inlineWidgets.forEach(function (inlineWidget) {\n            inlineWidget.onClosed();\n        });\n    };\n    \n        \n    /** \n     * Handles Select All specially when we have a visible range in order to work around\n     * bugs in CodeMirror when lines are hidden.\n     */\n    Editor.prototype._selectAllVisible = function () {\n        var startLine = this.getFirstVisibleLine(),\n            endLine = this.getLastVisibleLine();\n        this.setSelection({line: startLine, ch: 0},\n                          {line: endLine, ch: this.document.getLine(endLine).length});\n    };\n    \n    Editor.prototype._applyChanges = function (changeList) {\n        var self = this;\n        \n        // _visibleRange has already updated via its own Document listener. See if this change caused\n        // it to lose sync. If so, our whole view is stale - signal our owner to close us.\n        if (this._visibleRange) {\n            if (this._visibleRange.startLine === null || this._visibleRange.endLine === null) {\n                $(self).triggerHandler(\"lostContent\");\n                return;\n            }\n        }\n        \n        // Apply text changes to CodeMirror editor\n        var cm = this._codeMirror;\n        cm.operation(function () {\n            var change, newText;\n            for (change = changeList; change; change = change.next) {\n                newText = change.text.join('\\n');\n                if (!change.from || !change.to) {\n                    if (change.from || change.to) {\n                        console.assert(false, \"Change record received with only one end undefined--replacing entire text\");\n                    }\n                    cm.setValue(newText);\n                } else {\n                    cm.replaceRange(newText, change.from, change.to);\n                }\n                \n            }\n        });\n        \n        // The update above may have inserted new lines - must hide any that fall outside our range\n        if (self._visibleRange) {\n            cm.operation(function () {\n                // TODO: could make this more efficient by only iterating across the min-max line\n                // range of the union of all changes\n                var i;\n                for (i = 0; i < cm.lineCount(); i++) {\n                    if (i < self._visibleRange.startLine || i > self._visibleRange.endLine) {\n                        self._hideLine(i);\n                    } else {\n                        // Double-check that the set of NON-hidden lines matches our range too\n                        console.assert(!cm.getLineHandle(i).hidden);\n                    }\n                }\n            });\n        }\n    };\n    \n    /**\n     * Responds to changes in the CodeMirror editor's text, syncing the changes to the Document.\n     * There are several cases where we want to ignore a CodeMirror change:\n     *  - if we're the master editor, editor changes can be ignored because Document is already listening\n     *    for our changes\n     *  - if we're a secondary editor, editor changes should be ignored if they were caused by us reacting\n     *    to a Document change\n     */\n    Editor.prototype._handleEditorChange = function (event, editor, changeList) {\n        // we're currently syncing from the Document, so don't echo back TO the Document\n        if (this._duringSync) {\n            return;\n        }\n        \n        // Secondary editor: force creation of \"master\" editor backing the model, if doesn't exist yet\n        this.document._ensureMasterEditor();\n        \n        if (this.document._masterEditor !== this) {\n            // Secondary editor:\n            // we're not the ground truth; if we got here, this was a real editor change (not a\n            // sync from the real ground truth), so we need to sync from us into the document\n            // (which will directly push the change into the master editor).\n            // FUTURE: Technically we should add a replaceRange() method to Document and go through\n            // that instead of talking to its master editor directly. It's not clear yet exactly\n            // what the right Document API would be, though.\n            this._duringSync = true;\n            this.document._masterEditor._applyChanges(changeList);\n            this._duringSync = false;\n        }\n        // Else, Master editor:\n        // we're the ground truth; nothing else to do, since Document listens directly to us\n        // note: this change might have been a real edit made by the user, OR this might have\n        // been a change synced from another editor\n        \n        if (this._visibleRange) {\n            // _visibleRange has already updated via its own Document listener, when we pushed our\n            // change into the Document above (_masterEditor._applyChanges()). But changes due to our\n            // own edits should never cause the range to lose sync - verify that.\n            if (this._visibleRange.startLine === null || this._visibleRange.endLine === null) {\n                throw new Error(\"ERROR: Typing in Editor should not destroy its own _visibleRange\");\n            }\n        }\n    };\n    \n    /**\n     * Responds to changes in the Document's text, syncing the changes into our CodeMirror instance.\n     * There are several cases where we want to ignore a Document change:\n     *  - if we're the master editor, Document changes should be ignored becuase we already have the right\n     *    text (either the change originated with us, or it has already been set into us by Document)\n     *  - if we're a secondary editor, Document changes should be ignored if they were caused by us sending\n     *    the document an editor change that originated with us\n     */\n    Editor.prototype._handleDocumentChange = function (event, doc, changeList) {\n        var change;\n        \n        // we're currently syncing to the Document, so don't echo back FROM the Document\n        if (this._duringSync) {\n            return;\n        }\n        \n        if (this.document._masterEditor !== this) {\n            // Secondary editor:\n            // we're not the ground truth; and if we got here, this was a Document change that\n            // didn't come from us (e.g. a sync from another editor, a direct programmatic change\n            // to the document, or a sync from external disk changes)... so sync from the Document\n            this._duringSync = true;\n            this._applyChanges(changeList);\n            this._duringSync = false;\n        }\n        // Else, Master editor:\n        // we're the ground truth; nothing to do since Document change is just echoing our\n        // editor changes\n    };\n    \n    /**\n     * Responds to the Document's underlying file being deleted. The Document is now basically dead,\n     * so we must close.\n     */\n    Editor.prototype._handleDocumentDeleted = function () {\n        $(this).triggerHandler(\"lostContent\");\n    };\n    \n    \n    /**\n     * Install singleton event handlers on the CodeMirror instance, translating them into multi-\n     * listener-capable jQuery events on the Editor instance.\n     */\n    Editor.prototype._installEditorListeners = function () {\n        var self = this;\n        \n        // FUTURE: if this list grows longer, consider making this a more generic mapping\n        // NOTE: change is a \"private\" event--others shouldn't listen to it on Editor, only on\n        // Document\n        this._codeMirror.setOption(\"onChange\", function (instance, changeList) {\n            $(self).triggerHandler(\"change\", [self, changeList]);\n        });\n        this._codeMirror.setOption(\"onKeyEvent\", function (instance, event) {\n            $(self).triggerHandler(\"keyEvent\", [self, event]);\n            return event.defaultPrevented;   // false tells CodeMirror we didn't eat the event\n        });\n        this._codeMirror.setOption(\"onCursorActivity\", function (instance) {\n            $(self).triggerHandler(\"cursorActivity\", [self]);\n        });\n        this._codeMirror.setOption(\"onScroll\", function (instance) {\n            // close all dropdowns on scroll\n            Menus.closeAll();\n\n            $(self).triggerHandler(\"scroll\", [self]);\n        \n            // notify all inline widgets of a position change\n            self._fireWidgetOffsetTopChanged(self.getFirstVisibleLine() - 1);\n        });\n    };\n    \n    /**\n     * Sets the contents of the editor and clears the undo/redo history. Dispatches a change event.\n     * Semi-private: only Document should call this.\n     * @param {!string} text\n     */\n    Editor.prototype._resetText = function (text) {\n        var perfTimerName = PerfUtils.markStart(\"Edtitor._resetText()\\t\" + (!this.document || this.document.file.fullPath));\n\n        var cursorPos = this.getCursorPos(),\n            scrollPos = this.getScrollPos();\n        \n        // This *will* fire a change event, but we clear the undo immediately afterward\n        this._codeMirror.setValue(text);\n        \n        // Make sure we can't undo back to the empty state before setValue()\n        this._codeMirror.clearHistory();\n        \n        // restore cursor and scroll positions\n        this.setCursorPos(cursorPos);\n        this.setScrollPos(scrollPos.x, scrollPos.y);\n\n        PerfUtils.addMeasurement(perfTimerName);\n    };\n    \n    \n    /**\n     * Gets the current cursor position within the editor. If there is a selection, returns whichever\n     * end of the range the cursor lies at.\n     * @return !{line:number, ch:number}\n     */\n    Editor.prototype.getCursorPos = function () {\n        return this._codeMirror.getCursor();\n    };\n    \n    /**\n     * Sets the cursor position within the editor. Removes any selection.\n     * @param {number} line The 0 based line number.\n     * @param {number=} ch  The 0 based character position; treated as 0 if unspecified.\n     */\n    Editor.prototype.setCursorPos = function (line, ch) {\n        this._codeMirror.setCursor(line, ch);\n    };\n\n    /**\n     * Given a position, returns its index within the text (assuming \\n newlines)\n     * @param {!{line:number, ch:number}}\n     * @return {number}\n     */\n    Editor.prototype.indexFromPos = function (coords) {\n        return this._codeMirror.indexFromPos(coords);\n    };\n\n    /**\n     * Returns true if pos is between start and end (inclusive at both ends)\n     * @param {{line:number, ch:number}} pos\n     * @param {{line:number, ch:number}} start\n     * @param {{line:number, ch:number}} end\n     *\n     */\n    Editor.prototype.posWithinRange = function (pos, start, end) {\n        var startIndex = this.indexFromPos(start),\n            endIndex = this.indexFromPos(end),\n            posIndex = this.indexFromPos(pos);\n\n        return posIndex >= startIndex && posIndex <= endIndex;\n    };\n    \n    /**\n     * @return {boolean} True if there's a text selection; false if there's just an insertion point\n     */\n    Editor.prototype.hasSelection = function () {\n        return this._codeMirror.somethingSelected();\n    };\n    \n    /**\n     * Gets the current selection. Start is inclusive, end is exclusive. If there is no selection,\n     * returns the current cursor position as both the start and end of the range (i.e. a selection\n     * of length zero).\n     * @return {!{start:{line:number, ch:number}, end:{line:number, ch:number}}}\n     */\n    Editor.prototype.getSelection = function () {\n        var selStart = this._codeMirror.getCursor(true),\n            selEnd   = this._codeMirror.getCursor(false);\n        return { start: selStart, end: selEnd };\n    };\n    \n    /**\n     * @return {!string} The currently selected text, or \"\" if no selection. Includes \\n if the\n     * selection spans multiple lines (does NOT reflect the Document's line-endings style).\n     */\n    Editor.prototype.getSelectedText = function () {\n        return this._codeMirror.getSelection();\n    };\n    \n    /**\n     * Sets the current selection. Start is inclusive, end is exclusive. Places the cursor at the\n     * end of the selection range.\n     * @param {!{line:number, ch:number}} start\n     * @param {!{line:number, ch:number}} end\n     */\n    Editor.prototype.setSelection = function (start, end) {\n        this._codeMirror.setSelection(start, end);\n    };\n\n    /**\n     * Selects word that the given pos lies within or adjacent to. If pos isn't touching a word\n     * (e.g. within a token like \"//\"), moves the cursor to pos without selecting a range.\n     * @param {!{line:number, ch:number}}\n     */\n    Editor.prototype.selectWordAt = function (pos) {\n        this._codeMirror.selectWordAt(pos);\n    };\n    \n\n    /**\n     * Gets the total number of lines in the the document (includes lines not visible in the viewport)\n     * @returns {!number}\n     */\n    Editor.prototype.lineCount = function () {\n        return this._codeMirror.lineCount();\n    };\n    \n    /**\n     * Gets the number of the first visible line in the editor.\n     * @returns {number} The 0-based index of the first visible line.\n     */\n    Editor.prototype.getFirstVisibleLine = function () {\n        return (this._visibleRange ? this._visibleRange.startLine : 0);\n    };\n    \n    /**\n     * Gets the number of the last visible line in the editor.\n     * @returns {number} The 0-based index of the last visible line.\n     */\n    Editor.prototype.getLastVisibleLine = function () {\n        return (this._visibleRange ? this._visibleRange.endLine : this.lineCount() - 1);\n    };\n\n    // FUTURE change to \"hideLines()\" API that hides a range of lines at once in a single operation, then fires offsetTopChanged afterwards.\n    /* Hides the specified line number in the editor\n     * @param {!number}\n     */\n    Editor.prototype._hideLine = function (lineNumber) {\n        var value = this._codeMirror.hideLine(lineNumber);\n        \n        // when this line is hidden, notify all following inline widgets of a position change\n        this._fireWidgetOffsetTopChanged(lineNumber);\n        \n        return value;\n    };\n\n    /**\n     * Gets the total height of the document in pixels (not the viewport)\n     * @param {!boolean} includePadding\n     * @returns {!number} height in pixels\n     */\n    Editor.prototype.totalHeight = function (includePadding) {\n        return this._codeMirror.totalHeight(includePadding);\n    };\n\n    /**\n     * Gets the scroller element from the editor.\n     * @returns {!HTMLDivElement} scroller\n     */\n    Editor.prototype.getScrollerElement = function () {\n        return this._codeMirror.getScrollerElement();\n    };\n    \n    /**\n     * Gets the root DOM node of the editor.\n     * @returns {Object} The editor's root DOM node.\n     */\n    Editor.prototype.getRootElement = function () {\n        return this._codeMirror.getWrapperElement();\n    };\n    \n    /**\n     * Gets the lineSpace element within the editor (the container around the individual lines of code).\n     * FUTURE: This is fairly CodeMirror-specific. Logic that depends on this may break if we switch\n     * editors.\n     * @returns {Object} The editor's lineSpace element.\n     */\n    Editor.prototype._getLineSpaceElement = function () {\n        return $(\".CodeMirror-lines\", this.getScrollerElement()).children().get(0);\n    };\n    \n    /**\n     * Returns the current scroll position of the editor.\n     * @returns {{x:number, y:number}} The x,y scroll position in pixels\n     */\n    Editor.prototype.getScrollPos = function () {\n        return this._codeMirror.getScrollInfo();\n    };\n    \n    /**\n     * Sets the current scroll position of the editor.\n     * @param {number} x scrollLeft position in pixels\n     * @param {number} y scrollTop position in pixels\n     */\n    Editor.prototype.setScrollPos = function (x, y) {\n        this._codeMirror.scrollTo(x, y);\n    };\n\n    /**\n     * Adds an inline widget below the given line. If any inline widget was already open for that\n     * line, it is closed without warning.\n     * @param {!{line:number, ch:number}} pos  Position in text to anchor the inline.\n     * @param {!InlineWidget} inlineWidget The widget to add.\n     */\n    Editor.prototype.addInlineWidget = function (pos, inlineWidget) {\n        var self = this;\n        inlineWidget.id = this._codeMirror.addInlineWidget(pos, inlineWidget.htmlContent, inlineWidget.height, function (id) {\n            self._removeInlineWidgetInternal(id);\n            inlineWidget.onClosed();\n        });\n        this._inlineWidgets.push(inlineWidget);\n        inlineWidget.onAdded();\n        \n        // once this widget is added, notify all following inline widgets of a position change\n        this._fireWidgetOffsetTopChanged(pos.line);\n    };\n    \n    /**\n     * Removes all inline widgets\n     */\n    Editor.prototype.removeAllInlineWidgets = function () {\n        // copy the array because _removeInlineWidgetInternal will modifying the original\n        var widgets = [].concat(this.getInlineWidgets());\n        \n        widgets.forEach(function (widget) {\n            this.removeInlineWidget(widget);\n        }, this);\n    };\n    \n    /**\n     * Removes the given inline widget.\n     * @param {number} inlineWidget The widget to remove.\n     */\n    Editor.prototype.removeInlineWidget = function (inlineWidget) {\n        var lineNum = this._getInlineWidgetLineNumber(inlineWidget);\n        \n        // _removeInlineWidgetInternal will get called from the destroy callback in CodeMirror.\n        this._codeMirror.removeInlineWidget(inlineWidget.id);\n        \n        // once this widget is removed, notify all following inline widgets of a position change\n        this._fireWidgetOffsetTopChanged(lineNum);\n    };\n    \n    /**\n     * Cleans up the given inline widget from our internal list of widgets.\n     * @param {number} inlineId  id returned by addInlineWidget().\n     */\n    Editor.prototype._removeInlineWidgetInternal = function (inlineId) {\n        var i;\n        var l = this._inlineWidgets.length;\n        for (i = 0; i < l; i++) {\n            if (this._inlineWidgets[i].id === inlineId) {\n                this._inlineWidgets.splice(i, 1);\n                break;\n            }\n        }\n    };\n\n    /**\n     * Returns a list of all inline widgets currently open in this editor. Each entry contains the\n     * inline's id, and the data parameter that was passed to addInlineWidget().\n     * @return {!Array.<{id:number, data:Object}>}\n     */\n    Editor.prototype.getInlineWidgets = function () {\n        return this._inlineWidgets;\n    };\n\n    /**\n     * Sets the height of an inline widget in this editor. \n     * @param {!InlineWidget} inlineWidget The widget whose height should be set.\n     * @param {!number} height The height of the widget.\n     * @param {boolean} ensureVisible Whether to scroll the entire widget into view.\n     */\n    Editor.prototype.setInlineWidgetHeight = function (inlineWidget, height, ensureVisible) {\n        var info = this._codeMirror.getInlineWidgetInfo(inlineWidget.id),\n            oldHeight = (info && info.height) || 0;\n        \n        this._codeMirror.setInlineWidgetHeight(inlineWidget.id, height, ensureVisible);\n        \n        // update position for all following inline editors\n        if (oldHeight !== height) {\n            var lineNum = this._getInlineWidgetLineNumber(inlineWidget);\n            this._fireWidgetOffsetTopChanged(lineNum);\n        }\n    };\n    \n    /**\n     * @private\n     * Get the starting line number for an inline widget.\n     * @param {!InlineWidget} inlineWidget \n     * @return {number} The line number of the widget or -1 if not found.\n     */\n    Editor.prototype._getInlineWidgetLineNumber = function (inlineWidget) {\n        var info = this._codeMirror.getInlineWidgetInfo(inlineWidget.id);\n        return (info && info.line) || -1;\n    };\n    \n    /**\n     * @private\n     * Fire \"offsetTopChanged\" events when inline editor positions change due to\n     * height changes of other inline editors.\n     * @param {!InlineWidget} inlineWidget \n     */\n    Editor.prototype._fireWidgetOffsetTopChanged = function (lineNum) {\n        var self = this,\n            otherLineNum;\n        \n        this.getInlineWidgets().forEach(function (other) {\n            otherLineNum = self._getInlineWidgetLineNumber(other);\n            \n            if (otherLineNum > lineNum) {\n                $(other).triggerHandler(\"offsetTopChanged\");\n            }\n        });\n    };\n    \n    /** Gives focus to the editor control */\n    Editor.prototype.focus = function () {\n        this._codeMirror.focus();\n    };\n    \n    /** Returns true if the editor has focus */\n    Editor.prototype.hasFocus = function () {\n        // The CodeMirror instance wrapper has a \"CodeMirror-focused\" class set when focused\n        return $(this.getScrollerElement()).hasClass(\"CodeMirror-focused\");\n    };\n    \n    /**\n     * Re-renders the editor UI\n     */\n    Editor.prototype.refresh = function () {\n        this._codeMirror.refresh();\n    };\n    \n    /**\n     * Re-renders the editor, and all children inline editors.\n     */\n    Editor.prototype.refreshAll = function () {\n        this.refresh();\n        this.getInlineWidgets().forEach(function (multilineEditor, i, arr) {\n            multilineEditor.sizeInlineWidgetToContents(true);\n            multilineEditor._updateRelatedContainer();\n            multilineEditor.editors.forEach(function (editor, j, arr) {\n                editor.refresh();\n            });\n        });\n    };\n    \n    /**\n     * Shows or hides the editor within its parent. Does not force its ancestors to\n     * become visible.\n     * @param {boolean} show true to show the editor, false to hide it\n     */\n    Editor.prototype.setVisible = function (show) {\n        $(this.getRootElement()).css(\"display\", (show ? \"\" : \"none\"));\n        this._codeMirror.refresh();\n        if (show) {\n            this._inlineWidgets.forEach(function (inlineWidget) {\n                inlineWidget.onParentShown();\n            });\n        }\n    };\n    \n    /**\n     * Returns true if the editor is fully visible--i.e., is in the DOM, all ancestors are\n     * visible, and has a non-zero width/height.\n     */\n    Editor.prototype.isFullyVisible = function () {\n        return $(this.getRootElement()).is(\":visible\");\n    };\n    \n    /**\n     * Gets the syntax-highlighting mode for the current selection or cursor position. (The mode may\n     * vary within one file due to embedded languages, e.g. JS embedded in an HTML script block).\n     *\n     * Returns null if the mode at the start of the selection differs from the mode at the end -\n     * an *approximation* of whether the mode is consistent across the whole range (a pattern like\n     * A-B-A would return A as the mode, not null).\n     *\n     * @return {?string} Name of syntax-highlighting mode; see {@link EditorUtils#getModeFromFileExtension()}.\n     */\n    Editor.prototype.getModeForSelection = function () {\n        var sel = this.getSelection();\n        \n        // Check for mixed mode info (meaning mode varies depending on position)\n        // TODO (#921): this only works for certain mixed modes; some do not expose this info\n        var startState = this._codeMirror.getTokenAt(sel.start).state;\n        if (startState.mode) {\n            var startMode = startState.mode;\n            \n            // If mixed mode, check that mode is the same at start & end of selection\n            if (sel.start.line !== sel.end.line || sel.start.ch !== sel.end.ch) {\n                var endState = this._codeMirror.getTokenAt(sel.end).state;\n                var endMode = endState.mode;\n                if (startMode !== endMode) {\n                    return null;\n                }\n            }\n            return startMode;\n            \n        } else {\n            // Mode does not vary: just use the editor-wide mode\n            return this._codeMirror.getOption(\"mode\");\n        }\n    };\n    \n    /**\n     * The Document we're bound to\n     * @type {!Document}\n     */\n    Editor.prototype.document = null;\n    \n    /**\n     * If true, we're in the middle of syncing to/from the Document. Used to ignore spurious change\n     * events caused by us (vs. change events caused by others, which we need to pay attention to).\n     * @type {!boolean}\n     */\n    Editor.prototype._duringSync = false;\n    \n    /**\n     * @private\n     * NOTE: this is actually \"semi-private\": EditorManager also accesses this field... as well as\n     * a few other modules. However, we should try to gradually move most code away from talking to\n     * CodeMirror directly.\n     * @type {!CodeMirror}\n     */\n    Editor.prototype._codeMirror = null;\n    \n    /**\n     * @private\n     * @type {!Array.<{id:number, data:Object}>}\n     */\n    Editor.prototype._inlineWidgets = null;\n\n    /**\n     * @private\n     * @type {?TextRange}\n     */\n    Editor.prototype._visibleRange = null;\n    \n    \n    // Global settings that affect all Editor instances (both currently open Editors as well as those created\n    // in the future)\n\n    /**\n     * Sets whether to use tab characters (vs. spaces) when inserting new text. Affects all Editors.\n     * @param {boolean} value\n     */\n    Editor.setUseTabChar = function (value) {\n        _useTabChar = value;\n        _instances.forEach(function (editor) {\n            editor._codeMirror.setOption(\"indentWithTabs\", _useTabChar);\n        });\n    };\n    \n    /** @type {boolean}  Gets whether all Editors use tab characters (vs. spaces) when inserting new text */\n    Editor.getUseTabChar = function (value) {\n        return _useTabChar;\n    };\n\n    \n    // Global commands that affect the currently focused Editor instance, wherever it may be\n    CommandManager.register(Strings.CMD_SELECT_ALL,     Commands.EDIT_SELECT_ALL, _handleSelectAll);\n\n    // Define public API\n    exports.Editor = Editor;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\ndefine('editor/InlineWidget',['require','exports','module','editor/EditorManager'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var EditorManager       = require(\"editor/EditorManager\");\n    \n    /**\n     * @constructor\n     *\n     */\n    function InlineWidget() {\n        var self = this;\n        \n        // create the outer wrapper div\n        this.htmlContent = window.document.createElement(\"div\");\n        this.$htmlContent = $(this.htmlContent).addClass(\"inline-widget\");\n        this.$htmlContent.append(\"<div class='shadow top' />\")\n            .append(\"<div class='shadow bottom' />\");\n        \n        this.$htmlContent.on(\"keydown\", function (e) {\n            if (e.keyCode === 27) {\n                self.close();\n                e.stopImmediatePropagation();\n            }\n        });\n    }\n    InlineWidget.prototype.htmlContent = null;\n    InlineWidget.prototype.$htmlContent = null;\n    InlineWidget.prototype.id = null;\n    InlineWidget.prototype.hostEditor = null;\n\n    /**\n     * Initial height of inline widget in pixels. Can be changed later via hostEditor.setInlineWidgetHeight()\n     * @type {number}\n     */\n    InlineWidget.prototype.height = 0;\n    \n    /**\n     * Closes this inline widget and all its contained Editors\n     */\n    InlineWidget.prototype.close = function () {\n        var shouldMoveFocus = this._editorHasFocus();\n        EditorManager.closeInlineWidget(this.hostEditor, this, shouldMoveFocus);\n        // closeInlineWidget() causes our onClosed() handler to be called\n    };\n    \n    /**\n     * Called any time inline is closed, whether manually or automatically\n     */\n    InlineWidget.prototype.onClosed = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * Called once content is parented in the host editor's DOM. Useful for performing tasks like setting\n     * focus or measuring content, which require htmlContent to be in the DOM tree.\n     */\n    InlineWidget.prototype.onAdded = function () {\n        // do nothing - base implementation\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineWidget.prototype.load = function (hostEditor) {\n        this.hostEditor = hostEditor;\n\n        // TODO: incomplete impelementation. It's not clear yet if InlineTextEditor\n        // will fuction as an abstract class or as generic inline editor implementation\n        // that just shows a range of text. See CSSInlineEditor.css for an implementation of load()\n    };\n    \n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineWidget.prototype.onParentShown = function () {\n        // do nothing - base implementation\n    };\n\n    exports.InlineWidget = InlineWidget;\n\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n// FUTURE: Merge part (or all) of this class with MultiRangeInlineEditor\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\ndefine('editor/InlineTextEditor',['require','exports','module','document/DocumentManager','editor/EditorManager','command/CommandManager','command/Commands','editor/InlineWidget'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        InlineWidget        = require(\"editor/InlineWidget\").InlineWidget;\n\n    /**\n     * Returns editor holder width (not CodeMirror's width).\n     * @private\n     */\n    function _editorHolderWidth() {\n        return $(\"#editor-holder\").width();\n    }\n\n    /**\n     * Shows or hides the dirty indicator\n     * @private\n     */\n    function _showDirtyIndicator($indicatorDiv, isDirty) {\n        // Show or hide the dirty indicator by adjusting\n        // the width of the div.\n        $indicatorDiv.css(\"width\", isDirty ? 16 : 0);\n    }\n    \n    /**\n     * Respond to dirty flag change event. If the dirty flag is associated with an inline editor,\n     * show (or hide) the dirty indicator.\n     * @private\n     */\n    function _dirtyFlagChangeHandler(event, doc) {\n        var $dirtyIndicators = $(\".inlineEditorHolder .dirty-indicator\"),\n            $indicator;\n        \n        $.each($dirtyIndicators, function (index, indicator) {\n            $indicator = $(indicator);\n            if ($indicator.data(\"fullPath\") === doc.file.fullPath) {\n                _showDirtyIndicator($indicator, doc.isDirty);\n            }\n        });\n    }\n    \n    /**\n     * @constructor\n     * @extends {InlineWidget}\n     */\n    function InlineTextEditor() {\n        InlineWidget.call(this);\n\n        /* @type {Array.<{Editor}>}*/\n        this.editors = [];\n    }\n    InlineTextEditor.prototype = new InlineWidget();\n    InlineTextEditor.prototype.constructor = InlineTextEditor;\n    InlineTextEditor.prototype.parentClass = InlineWidget.prototype;\n    \n    InlineTextEditor.prototype.editors = null;\n\n   /**\n     * Given a host editor and its inline editors, find the widest gutter and make all the others match\n     * @param {!Editor} hostEditor Host editor containing all the inline editors to sync\n     * @private\n     */\n    function _syncGutterWidths(hostEditor) {\n        var allHostedEditors = EditorManager.getInlineEditors(hostEditor);\n        \n        // add the host itself to the list too\n        allHostedEditors.push(hostEditor);\n        \n        var maxWidth = 0;\n        allHostedEditors.forEach(function (editor) {\n            var $gutter = $(editor._codeMirror.getGutterElement());\n            $gutter.css(\"min-width\", \"\");\n            var curWidth = $gutter.width();\n            if (curWidth > maxWidth) {\n                maxWidth = curWidth;\n            }\n        });\n        \n        if (allHostedEditors.length === 1) {\n            //There's only the host, just bail\n            allHostedEditors[0]._codeMirror.setOption(\"gutter\", true);\n            return;\n        }\n        \n        maxWidth = maxWidth + \"px\";\n        allHostedEditors.forEach(function (editor) {\n            $(editor._codeMirror.getGutterElement()).css(\"min-width\", maxWidth);\n            editor._codeMirror.setOption(\"gutter\", true);\n        });\n    }\n\n    /**\n     * Called any time inline was closed, whether manually (via close()) or automatically\n     */\n    InlineTextEditor.prototype.onClosed = function () {\n        _syncGutterWidths(this.hostEditor);\n        \n        this.editors.forEach(function (editor) {\n            editor.destroy(); //release ref on Document\n        });\n    };\n    \n    /**\n     * Update the inline editor's height when the number of lines change\n     * @param {boolean} force the editor to resize\n     */\n    InlineTextEditor.prototype.sizeInlineWidgetToContents = function (force) {\n        var i,\n            len = this.editors.length,\n            editor;\n        \n        // TODO: only handles 1 editor right now. Add multiple editor support when\n        // the design is finalized\n\n        // Reize the editors to the content\n        for (i = 0; i < len; i++) {\n            // Only supports 1 editor right now\n            if (i === 1) {\n                break;\n            }\n            \n            editor = this.editors[i];\n            \n            if (editor.isFullyVisible()) {\n                var height = editor.totalHeight(true);\n                if (force || height !== this.height) {\n                    $(editor.getScrollerElement()).height(height);\n                    this.height = height;\n                    editor.refresh();\n                }\n            }\n        }\n    };\n\n    /**\n     * Some tasks have to wait until we've been parented into the outer editor\n     * @param {string} the inline ID that is generated by CodeMirror after the widget that holds the inline\n     *  editor is constructed and added to the DOM\n     */\n    InlineTextEditor.prototype.onAdded = function () {\n        this.editors.forEach(function (editor) {\n            editor.refresh();\n        });\n        \n        _syncGutterWidths(this.hostEditor);\n        \n        // Set initial size\n        // Note that the second argument here (ensureVisibility) is only used by CSSInlineEditor.\n        // FUTURE: Should clean up this API so it's consistent between the two.\n        this.sizeInlineWidgetToContents(true, true);\n        \n        this.editors[0].focus();\n    };\n\n    /**\n     *\n     * @param {Document} doc\n     * @param {number} startLine of text to show in inline editor\n     * @param {number} endLine of text to show in inline editor\n     * @param {HTMLDivElement} container container to hold the inline editor\n     */\n    InlineTextEditor.prototype.createInlineEditorFromText = function (doc, startLine, endLine, container, additionalKeys) {\n        var self = this;\n        \n        var range = {\n            startLine: startLine,\n            endLine: endLine\n        };\n        \n        // root container holding header & editor\n        var $wrapperDiv = $(\"<div/>\");\n        var wrapperDiv = $wrapperDiv[0];\n        \n        // header containing filename, dirty indicator, line number\n        var $header = $(\"<div/>\").addClass(\"inline-editor-header\");\n        var $filenameInfo = $(\"<a/>\").addClass(\"filename\");\n        \n        // dirty indicator, with file path stored on it\n        var $dirtyIndicatorDiv = $(\"<div/>\")\n            .addClass(\"dirty-indicator\")\n            .width(0); // initialize indicator as hidden\n        $dirtyIndicatorDiv.data(\"fullPath\", doc.file.fullPath);\n        \n        var $lineNumber = $(\"<span class='line-number'>\" + (startLine + 1) + \"</span>\");\n\n        // wrap filename & line number in clickable link with tooltip\n        $filenameInfo.append($dirtyIndicatorDiv)\n            .append(doc.file.name + \" : \")\n            .append($lineNumber)\n            .attr(\"title\", doc.file.fullPath);\n        \n        // clicking filename jumps to full editor view\n        $filenameInfo.click(function () {\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: doc.file.fullPath })\n                .done(function () {\n                    EditorManager.getCurrentFullEditor().setCursorPos(startLine);\n                });\n        });\n\n        $header.append($filenameInfo);\n        $wrapperDiv.append($header);\n        \n        \n        // Create actual Editor instance\n        var inlineInfo = EditorManager.createInlineEditorForDocument(doc, range, wrapperDiv, additionalKeys);\n        this.editors.push(inlineInfo.editor);\n        container.appendChild(wrapperDiv);\n\n        // Size editor to content whenever it changes (via edits here or any other view of the doc)\n        $(inlineInfo.editor).on(\"change\", function () {\n            self.sizeInlineWidgetToContents();\n            \n            // And update line number since a change to the Editor equals a change to the Document,\n            // which may mean a change to the line range too\n            $lineNumber.text(inlineInfo.editor.getFirstVisibleLine() + 1);\n        });\n        \n        // If Document's file is deleted, or Editor loses sync with Document, just close\n        $(inlineInfo.editor).on(\"lostContent\", function () {\n            // Note: this closes the entire inline widget if any one Editor loses sync. This seems\n            // better than leaving it open but suddenly removing one rule from the result list.\n            self.close();\n        });\n        \n        // set dirty indicator state\n        _showDirtyIndicator($dirtyIndicatorDiv, doc.isDirty);\n    };\n\n    /**\n     * @param {Editor} hostEditor\n     */\n    InlineTextEditor.prototype.load = function (hostEditor) {\n        this.hostEditor = hostEditor;\n\n        // TODO: incomplete impelementation. It's not clear yet if InlineTextEditor\n        // will fuction as an abstract class or as generic inline editor implementation\n        // that just shows a range of text. See CSSInlineEditor.css for an implementation of load()\n    };\n\n    /**\n     * Called when the editor containing the inline is made visible.\n     */\n    InlineTextEditor.prototype.onParentShown = function () {\n        // We need to call this explicitly whenever the host editor is reshown, since\n        // we don't actually resize the inline editor while its host is invisible (see\n        // isFullyVisible() check in sizeInlineWidgetToContents()).\n        this.sizeInlineWidgetToContents(true);\n    };\n    \n    InlineTextEditor.prototype._editorHasFocus = function () {\n        return this.editors.some(function (editor) {\n            return editor.hasFocus();\n        });\n    };\n        \n    \n    // consolidate all dirty document updates\n    $(DocumentManager).on(\"dirtyFlagChange\", _dirtyFlagChangeHandler);\n\n    exports.InlineTextEditor = InlineTextEditor;\n\n});\n\nCodeMirror.defineMode(\"xml\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var Kludges = parserConfig.htmlMode ? {\n    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,\n                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,\n                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,\n                      'track': true, 'wbr': true},\n    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,\n                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,\n                       'th': true, 'tr': true},\n    contextGrabbers: {\n      'dd': {'dd': true, 'dt': true},\n      'dt': {'dd': true, 'dt': true},\n      'li': {'li': true},\n      'option': {'option': true, 'optgroup': true},\n      'optgroup': {'optgroup': true},\n      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,\n            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,\n            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,\n            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,\n            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},\n      'rp': {'rp': true, 'rt': true},\n      'rt': {'rp': true, 'rt': true},\n      'tbody': {'tbody': true, 'tfoot': true},\n      'td': {'td': true, 'th': true},\n      'tfoot': {'tbody': true},\n      'th': {'td': true, 'th': true},\n      'thead': {'tbody': true, 'tfoot': true},\n      'tr': {'tr': true}\n    },\n    doNotIndent: {\"pre\": true},\n    allowUnquoted: true,\n    allowMissing: false\n  } : {\n    autoSelfClosers: {},\n    implicitlyClosed: {},\n    contextGrabbers: {},\n    doNotIndent: {},\n    allowUnquoted: false,\n    allowMissing: false\n  };\n  var alignCDATA = parserConfig.alignCDATA;\n\n  // Return variables for tokenizers\n  var tagName, type;\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var ch = stream.next();\n    if (ch == \"<\") {\n      if (stream.eat(\"!\")) {\n        if (stream.eat(\"[\")) {\n          if (stream.match(\"CDATA[\")) return chain(inBlock(\"atom\", \"]]>\"));\n          else return null;\n        }\n        else if (stream.match(\"--\")) return chain(inBlock(\"comment\", \"-->\"));\n        else if (stream.match(\"DOCTYPE\", true, true)) {\n          stream.eatWhile(/[\\w\\._\\-]/);\n          return chain(doctype(1));\n        }\n        else return null;\n      }\n      else if (stream.eat(\"?\")) {\n        stream.eatWhile(/[\\w\\._\\-]/);\n        state.tokenize = inBlock(\"meta\", \"?>\");\n        return \"meta\";\n      }\n      else {\n        type = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n        stream.eatSpace();\n        tagName = \"\";\n        var c;\n        while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n        state.tokenize = inTag;\n        return \"tag\";\n      }\n    }\n    else if (ch == \"&\") {\n      var ok;\n      if (stream.eat(\"#\")) {\n        if (stream.eat(\"x\")) {\n          ok = stream.eatWhile(/[a-fA-F\\d]/) && stream.eat(\";\");          \n        } else {\n          ok = stream.eatWhile(/[\\d]/) && stream.eat(\";\");\n        }\n      } else {\n        ok = stream.eatWhile(/[\\w\\.\\-:]/) && stream.eat(\";\");\n      }\n      return ok ? \"atom\" : \"error\";\n    }\n    else {\n      stream.eatWhile(/[^&<]/);\n      return null;\n    }\n  }\n\n  function inTag(stream, state) {\n    var ch = stream.next();\n    if (ch == \">\" || (ch == \"/\" && stream.eat(\">\"))) {\n      state.tokenize = inText;\n      type = ch == \">\" ? \"endTag\" : \"selfcloseTag\";\n      return \"tag\";\n    }\n    else if (ch == \"=\") {\n      type = \"equals\";\n      return null;\n    }\n    else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return state.tokenize(stream, state);\n    }\n    else {\n      stream.eatWhile(/[^\\s\\u00a0=<>\\\"\\'\\/?]/);\n      return \"word\";\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inTag;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n  function doctype(depth) {\n    return function(stream, state) {\n      var ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == \"<\") {\n          state.tokenize = doctype(depth + 1);\n          return state.tokenize(stream, state);\n        } else if (ch == \">\") {\n          if (depth == 1) {\n            state.tokenize = inText;\n            break;\n          } else {\n            state.tokenize = doctype(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n      }\n      return \"meta\";\n    };\n  }\n\n  var curState, setStyle;\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushContext(tagName, startOfLine) {\n    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);\n    curState.context = {\n      prev: curState.context,\n      tagName: tagName,\n      indent: curState.indented,\n      startOfLine: startOfLine,\n      noIndent: noIndent\n    };\n  }\n  function popContext() {\n    if (curState.context) curState.context = curState.context.prev;\n  }\n\n  function element(type) {\n    if (type == \"openTag\") {\n      curState.tagName = tagName;\n      return cont(attributes, endtag(curState.startOfLine));\n    } else if (type == \"closeTag\") {\n      var err = false;\n      if (curState.context) {\n        if (curState.context.tagName != tagName) {\n          if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {\n            popContext();\n          }\n          err = !curState.context || curState.context.tagName != tagName;\n        }\n      } else {\n        err = true;\n      }\n      if (err) setStyle = \"error\";\n      return cont(endclosetag(err));\n    }\n    return cont();\n  }\n  function endtag(startOfLine) {\n    return function(type) {\n      if (type == \"selfcloseTag\" ||\n          (type == \"endTag\" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {\n        maybePopContext(curState.tagName.toLowerCase());\n        return cont();\n      }\n      if (type == \"endTag\") {\n        maybePopContext(curState.tagName.toLowerCase());\n        pushContext(curState.tagName, startOfLine);\n        return cont();\n      }\n      return cont();\n    };\n  }\n  function endclosetag(err) {\n    return function(type) {\n      if (err) setStyle = \"error\";\n      if (type == \"endTag\") { popContext(); return cont(); }\n      setStyle = \"error\";\n      return cont(arguments.callee);\n    }\n  }\n  function maybePopContext(nextTagName) {\n    var parentTagName;\n    while (true) {\n      if (!curState.context) {\n        return;\n      }\n      parentTagName = curState.context.tagName.toLowerCase();\n      if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||\n          !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {\n        return;\n      }\n      popContext();\n    }\n  }\n\n  function attributes(type) {\n    if (type == \"word\") {setStyle = \"attribute\"; return cont(attribute, attributes);}\n    if (type == \"endTag\" || type == \"selfcloseTag\") return pass();\n    setStyle = \"error\";\n    return cont(attributes);\n  }\n  function attribute(type) {\n    if (type == \"equals\") return cont(attvalue, attributes);\n    if (!Kludges.allowMissing) setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfcloseTag\") ? pass() : cont();\n  }\n  function attvalue(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    if (type == \"word\" && Kludges.allowUnquoted) {setStyle = \"string\"; return cont();}\n    setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfCloseTag\") ? pass() : cont();\n  }\n  function attvaluemaybe(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    else return pass();\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        state.startOfLine = true;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n\n      setStyle = type = tagName = null;\n      var style = state.tokenize(stream, state);\n      state.type = type;\n      if ((style || type) && style != \"comment\") {\n        curState = state;\n        while (true) {\n          var comb = state.cc.pop() || element;\n          if (comb(type || style)) break;\n        }\n      }\n      state.startOfLine = false;\n      return setStyle || style;\n    },\n\n    indent: function(state, textAfter, fullLine) {\n      var context = state.context;\n      if ((state.tokenize != inTag && state.tokenize != inText) ||\n          context && context.noIndent)\n        return fullLine ? fullLine.match(/^(\\s*)/)[0].length : 0;\n      if (alignCDATA && /<!\\[CDATA\\[/.test(textAfter)) return 0;\n      if (context && /^<\\//.test(textAfter))\n        context = context.prev;\n      while (context && !context.startOfLine)\n        context = context.prev;\n      if (context) return context.indent + indentUnit;\n      else return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.indented != b.indented || a.tokenize != b.tokenize) return false;\n      for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {\n        if (!ca || !cb) return ca == cb;\n        if (ca.tagName != cb.tagName) return false;\n      }\n    },\n\n    electricChars: \"/\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/xml\", \"xml\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/html\"))\n  CodeMirror.defineMIME(\"text/html\", {name: \"xml\", htmlMode: true});\n\ndefine(\"thirdparty/CodeMirror2/mode/xml/xml\", function(){});\n\nCodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var jsonMode = parserConfig.json;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n    return {\n      \"if\": A, \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": C, \"delete\": C, \"throw\": C,\n      \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n      \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom\n    };\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next == end && !escaped)\n        return false;\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return escaped;\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n\n  function jsTokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, jsTokenString(ch));\n    else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch))\n      return ret(ch);\n    else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    }      \n    else if (/\\d/.test(ch) || ch == \"-\" && stream.eat(/\\d/)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, jsTokenComment);\n      }\n      else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else if (state.reAllowed) {\n        nextUntilUnescaped(stream, \"/\");\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string-2\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", null, stream.current());\n      }\n    }\n    else if (ch == \"#\") {\n        stream.skipToEnd();\n        return ret(\"error\", \"error\");\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", null, stream.current());\n    }\n    else {\n      stream.eatWhile(/[\\w\\$_]/);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return (known && state.kwAllowed) ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function jsTokenString(quote) {\n    return function(stream, state) {\n      if (!nextUntilUnescaped(stream, quote))\n        state.tokenize = jsTokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function jsTokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true};\n\n  function JSLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n  }\n\n  function parseJS(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n  \n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n        return style;\n      }\n    }\n  }\n\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      for (var v = state.localVars; v; v = v.next)\n        if (v.name == varname) return;\n      state.localVars = {name: varname, next: state.localVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    if (!cx.state.context) cx.state.localVars = defaultVars;\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state;\n      state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    return function expecting(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(arguments.callee);\n    };\n  }\n\n  function statement(type) {\n    if (type == \"var\") return cont(pushlex(\"vardef\"), vardef1, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), expression, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    if (type == \";\") return cont();\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), expect(\"(\"), pushlex(\")\"), forspec1, expect(\")\"),\n                                      poplex, statement, poplex);\n    if (type == \"variable\") return cont(pushlex(\"stat\"), maybelabel);\n    if (type == \"switch\") return cont(pushlex(\"form\"), expression, pushlex(\"}\", \"switch\"), expect(\"{\"),\n                                         block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                        statement, poplex, popcontext);\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex, maybeoperator);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(objprop, \"}\"), poplex, maybeoperator);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n    \n  function maybeoperator(type, value) {\n    if (type == \"operator\" && /\\+\\+|--/.test(value)) return cont(maybeoperator);\n    if (type == \"operator\" || type == \":\") return cont(expression);\n    if (type == \";\") return;\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(expression, \")\"), poplex, maybeoperator);\n    if (type == \".\") return cont(property, maybeoperator);\n    if (type == \"[\") return cont(pushlex(\"]\"), expression, expect(\"]\"), poplex, maybeoperator);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperator, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type) {\n    if (type == \"variable\") cx.marked = \"property\";\n    if (atomicTypes.hasOwnProperty(type)) return cont(expect(\":\"), expression);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") return cont(what, proceed);\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function commaSeparated(type) {\n      if (type == end) return cont();\n      else return pass(what, proceed);\n    };\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function vardef1(type, value) {\n    if (type == \"variable\"){register(value); return cont(vardef2);}\n    return cont();\n  }\n  function vardef2(type, value) {\n    if (value == \"=\") return cont(expression, vardef2);\n    if (type == \",\") return cont(vardef1);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef1, forspec2);\n    if (type == \";\") return pass(forspec2);\n    if (type == \"variable\") return cont(formaybein);\n    return pass(forspec2);\n  }\n  function formaybein(type, value) {\n    if (value == \"in\") return cont(expression);\n    return cont(maybeoperator, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\") return cont(expression);\n    return cont(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushlex(\")\"), pushcontext, commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type, value) {\n    if (type == \"variable\") {register(value); return cont();}\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: jsTokenBase,\n        reAllowed: true,\n        kwAllowed: true,\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: 0\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.reAllowed = !!(type == \"operator\" || type == \"keyword c\" || type.match(/^[\\[{}\\(,;:]$/));\n      state.kwAllowed = type != '.';\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != jsTokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n      if (type == \"vardef\") return lexical.indented + 4;\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"stat\" || type == \"form\") return lexical.indented + indentUnit;\n      else if (lexical.info == \"switch\" && !closing)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \":{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\n\ndefine(\"thirdparty/CodeMirror2/mode/javascript/javascript\", function(){});\n\nCodeMirror.defineMode(\"css\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\\\\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"#\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"atom\", \"hash\");\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,.+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]]/.test(ch)) {\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"variable\", \"variable\");\n    }\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context != \"rule\") style = \"string-2\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = \"number\";\n        else if (!context || context == \"@media{\") style = \"tag\";\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/css\", \"css\");\n\ndefine(\"thirdparty/CodeMirror2/mode/css/css\", function(){});\n\n/*\nLESS mode - http://www.lesscss.org/\nPorted to CodeMirror by Peter Kroon\n*/\n\nCodeMirror.defineMode(\"less\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n  //html5 tags\n  var tags = [\"a\",\"abbr\",\"acronym\",\"address\",\"applet\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"basefont\",\"bdi\",\"bdo\",\"big\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"command\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"dir\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"font\",\"footer\",\"form\",\"frame\",\"frameset\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"keygen\",\"kbd\",\"label\",\"legend\",\"li\",\"link\",\"map\",\"mark\",\"menu\",\"meta\",\"meter\",\"nav\",\"noframes\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strike\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"track\",\"tt\",\"u\",\"ul\",\"var\",\"video\",\"wbr\"];\n  \n  function inTagsArray(val){\n      for(var i=0; i<tags.length; i++){\n          if(val === tags[i]){\n              return true;\n          }\n      }\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"/\") { // lesscss e.g.: .png will not be parsed as a class\n      if(stream.eat(\"/\")){\n        state.tokenize = tokenSComment\n        return tokenSComment(stream, state);\n      }else{\n        stream.eatWhile(/[\\a-zA-Z0-9\\-_.\\s]/);\n        if(/\\/|\\)|#/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == \")\")))return ret(\"string\", \"string\");//let url(/images/logo.png) without quotes return as string\n        return ret(\"number\", \"unit\");\n      }\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,+<>*\\/]/.test(ch)) {//removed . dot character original was [,.+>*\\/]\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\\[\\]]\n      if(ch == \":\"){\n        stream.eatWhile(/[active|hover|link|visited]/);\n        if( stream.current().match(/active|hover|link|visited/)){\n          return ret(\"tag\", \"tag\");\n        }else{\n          return ret(null, ch); \n        }\n      }else{\n        return ret(null, ch);\n      }\n    }\n    else if (ch == \".\") { // lesscss\n      stream.eatWhile(/[\\a-zA-Z0-9\\-_]/);\n      return ret(\"tag\", \"tag\");\n    }\n    else if (ch == \"#\") { // lesscss\n      //we don't eat white-space, we want the hex color and or id only\n      stream.eatWhile(/[A-Za-z0-9]/);\n      //check if there is a proper hex color length e.g. #eee || #eeeEEE\n      if(stream.current().length ===4 || stream.current().length ===7){\n          if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream\n            //when not a valid hex value, parse as id\n            if(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret(\"atom\", \"tag\");\n            //eat white-space\n            stream.eatSpace();\n            //when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]\n            if( /[\\/<>.(){!$%^&*_\\-\\\\?=+\\|#'~`]/.test(stream.peek()) )return ret(\"atom\", \"tag\");\n            //#time { color: #aaa }\n            else if(stream.peek() == \"}\" )return ret(\"number\", \"unit\");\n            //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa\n            else if( /[a-zA-Z\\\\]/.test(stream.peek()) )return ret(\"atom\", \"tag\");\n            //when a hex value is on the end of a line, parse as id\n            else if(stream.eol())return ret(\"atom\", \"tag\");\n            //default\n            else return ret(\"number\", \"unit\");\n          }else{//when not a valid hexvalue in the current stream e.g. #footer\n            stream.eatWhile(/[\\w\\\\\\-]/);\n            return ret(\"atom\", \"tag\"); \n          }\n      }else{\n        stream.eatWhile(/[\\w\\\\\\-]/);        \n        return ret(\"atom\", \"tag\");\n      }\n    }\n    else if (ch == \"&\") {\n      stream.eatWhile(/[\\w\\-]/);\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-_%.{]/);\n      if(stream.current().match(/http|https/) != null){\n        stream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n        return ret(\"string\", \"string\");\n      }else if(stream.peek() == \"<\" || stream.peek() == \">\"){\n        return ret(\"tag\", \"tag\");\n      }else if( stream.peek().match(/\\(/) != null ){// lessc\n        return ret(null, ch);\n      }else if (stream.peek() == \"/\" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)\n        return ret(\"string\", \"string\");\n      }else if( stream.current().match(/\\-\\d|\\-.\\d/) ){ // lesscss match e.g.: -5px -0.4 etc... only colorize the minus sign\n        //stream.backUp(stream.current().length-1); //commment out these 2 comment if you want the minus sign to be parsed as null -500px\n        //return ret(null, ch);\n        return ret(\"number\", \"unit\");\n      }else if( inTagsArray(stream.current()) ){ // lesscss match html tags\n        return ret(\"tag\", \"tag\");\n      }else if( /\\/|[\\s\\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == \"/\")) && stream.current().indexOf(\".\") !== -1){\n        if(stream.current().substring(stream.current().length-1,stream.current().length) == \"{\"){\n            stream.backUp(1);\n            return ret(\"tag\", \"tag\");\n        }//end if\n        if( (stream.eatSpace() && stream.peek().match(/[{<>.a-zA-Z]/) != null)  || stream.eol() )return ret(\"tag\", \"tag\");//e.g. button.icon-plus\n        return ret(\"string\", \"string\");//let url(/images/logo.png) without quotes return as string\n      }else if( stream.eol() ){\n          if(stream.current().substring(stream.current().length-1,stream.current().length) == \"{\")stream.backUp(1);\n          return ret(\"tag\", \"tag\");\n      }else{\n        return ret(\"variable\", \"variable\");\n      }\n    }\n    \n  }\n\n  function tokenSComment(stream, state) {// SComment = Slash comment\n    stream.skipToEnd();\n    state.tokenize = tokenBase;\n    return ret(\"comment\", \"comment\");\n  }\n    \n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) { \n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context == \"rule\") style = \"atom\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = null; //\"tag\"\n        else if (!context || context == \"@media{\"){ \n            style = stream.current()    == \"when\"   ? \"variable\"    : \n            stream.string.match(/#/g)   != undefined    ? null      : \n            /[\\s,|\\s\\)]/.test(stream.peek())        ? \"tag\"     : null;\n        }\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-less\", \"less\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/css\"))\n  CodeMirror.defineMIME(\"text/css\", \"less\");\n\ndefine(\"thirdparty/CodeMirror2/mode/less/less\", function(){});\n\nCodeMirror.defineMode(\"htmlmixed\", function(config, parserConfig) {\n  var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n  var unknownScriptMode = CodeMirror.getMode(config, \"text/plain\");\n  var jsMode = CodeMirror.getMode(config, \"javascript\");\n  var cssMode = CodeMirror.getMode(config, \"css\");\n\n  function html(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style == \"tag\" && stream.current() == \">\" && state.htmlState.context) {\n      if (/^script$/i.test(state.htmlState.context.tagName)) {\n        // Script block: mode to change to depends on type attribute\n        var scriptType = stream.string.match(/type\\s*=\\s*[\"'](.+)[\"']/i);\n        scriptType = scriptType && scriptType[1];\n        if (!scriptType || scriptType.match(/(text|application)\\/(java|ecma)script/i)) {\n          state.token = javascript;\n          state.localState = jsMode.startState(htmlMode.indent(state.htmlState, \"\"));\n          state.mode = \"javascript\";\n        } else if (scriptType.match(/\\/x-handlebars-template/i) || scriptType.match(/\\/x-mustache/i)) {\n            // Handlebars or Mustache template: leave it in HTML mode\n        } else {\n          state.token = unknownScript;\n          state.localState = null;\n          state.mode = \"\";\n        }\n      }\n      else if (/^style$/i.test(state.htmlState.context.tagName)) {\n        state.token = css;\n        state.localState = cssMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"css\";\n      }\n    }\n    return style;\n  }\n  function maybeBackup(stream, pat, style) {\n    var cur = stream.current();\n    var close = cur.search(pat);\n    if (close > -1) stream.backUp(cur.length - close);\n    return style;\n  }\n  function unknownScript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       unknownScriptMode.token(stream, state.localState));\n  }\n  function javascript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       jsMode.token(stream, state.localState));\n  }\n  function css(stream, state) {\n    if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n                       cssMode.token(stream, state.localState));\n  }\n\n  return {\n    startState: function() {\n      var state = htmlMode.startState();\n      return {token: html, localState: null, mode: \"html\", htmlState: state};\n    },\n\n    copyState: function(state) {\n      if (state.localState)\n        var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);\n      return {token: state.token, localState: local, mode: state.mode,\n              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == html || /^\\s*<\\//.test(textAfter))\n        return htmlMode.indent(state.htmlState, textAfter);\n      else if (state.token == javascript)\n        return jsMode.indent(state.localState, textAfter);\n      else if (state.token == css)\n        return cssMode.indent(state.localState, textAfter);\n      else  // unknownScriptMode\n        return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.mode != b.mode) return false;\n      if (a.localState) return CodeMirror.Pass;\n      return htmlMode.compareStates(a.htmlState, b.htmlState);\n    },\n\n    electricChars: \"/{}:\"\n  }\n}, \"xml\", \"javascript\", \"css\");\n\nCodeMirror.defineMIME(\"text/html\", \"htmlmixed\");\n\ndefine(\"thirdparty/CodeMirror2/mode/htmlmixed/htmlmixed\", function(){});\n\nCodeMirror.defineMode(\"clike\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      keywords = parserConfig.keywords || {},\n      builtin = parserConfig.builtin || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    if (builtin.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\n(function() {\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  var cKeywords = \"auto if break int case long char register continue return default short do sizeof \" +\n    \"double static else struct entry switch extern typedef float union for unsigned \" +\n    \"goto while enum void const signed volatile\";\n\n  function cppHook(stream, state) {\n    if (!state.startOfLine) return false;\n    stream.skipToEnd();\n    return \"meta\";\n  }\n\n  // C#-style strings where \"\" escapes a quote.\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  CodeMirror.defineMIME(\"text/x-csrc\", {\n    name: \"clike\",\n    keywords: words(cKeywords),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null\"),\n    hooks: {\"#\": cppHook}\n  });\n  CodeMirror.defineMIME(\"text/x-c++src\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \" asm dynamic_cast namespace reinterpret_cast try bool explicit new \" +\n                    \"static_cast typeid catch operator template typename class friend private \" +\n                    \"this using const_cast inline public throw virtual delete mutable protected \" +\n                    \"wchar_t\"),\n    blockKeywords: words(\"catch class do else finally for if struct switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\"#\": cppHook}\n  });\n  CodeMirror.defineMIME(\"text/x-java\", {\n    name: \"clike\",\n    keywords: words(\"abstract assert boolean break byte case catch char class const continue default \" + \n                    \"do double else enum extends final finally float for goto if implements import \" +\n                    \"instanceof int interface long native new package private protected public \" +\n                    \"return short static strictfp super switch synchronized this throw throws transient \" +\n                    \"try void volatile while\"),\n    blockKeywords: words(\"catch class do else finally for if switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n  CodeMirror.defineMIME(\"text/x-csharp\", {\n    name: \"clike\",\n    keywords: words(\"abstract as base break case catch checked class const continue\" + \n                    \" default delegate do else enum event explicit extern finally fixed for\" + \n                    \" foreach goto if implicit in interface internal is lock namespace new\" + \n                    \" operator out override params private protected public readonly ref return sealed\" + \n                    \" sizeof stackalloc static struct switch this throw try typeof unchecked\" + \n                    \" unsafe using virtual void volatile while add alias ascending descending dynamic from get\" + \n                    \" global group into join let orderby partial remove select set value var yield\"),\n    blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n    builtin: words(\"Boolean Byte Char DateTime DateTimeOffset Decimal Double\" +\n                    \" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32\" +\n                    \" UInt64 bool byte char decimal double short int long object\"  +\n                    \" sbyte float string ushort uint ulong\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        if (stream.eat('\"')) {\n          state.tokenize = tokenAtString;\n          return tokenAtString(stream, state);\n        }\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n  CodeMirror.defineMIME(\"text/x-scala\", {\n    name: \"clike\",\n    keywords: words(\n      \n      /* scala */\n      \"abstract case catch class def do else extends false final finally for forSome if \" +\n      \"implicit import lazy match new null object override package private protected return \" +\n      \"sealed super this throw trait try trye type val var while with yield _ : = => <- <: \" +\n      \"<% >: # @ \" +\n                    \n      /* package scala */\n      \"assert assume require print println printf readLine readBoolean readByte readShort \" +\n      \"readChar readInt readLong readFloat readDouble \" +\n      \n      \"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either \" +\n      \"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable \" +\n      \"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering \" +\n      \"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder \" +\n      \"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: \" +\n      \n      /* package java.lang */            \n      \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n      \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n      \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n      \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n      \n      \n    ),\n    blockKeywords: words(\"catch class do else finally for forSome if match switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n}());\n\ndefine(\"thirdparty/CodeMirror2/mode/clike/clike\", function(){});\n\n(function() {\n  function keywords(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  function heredoc(delim) {\n    return function(stream, state) {\n      if (stream.match(delim)) state.tokenize = null;\n      else stream.skipToEnd();\n      return \"string\";\n    }\n  }\n  var phpConfig = {\n    name: \"clike\",\n    keywords: keywords(\"abstract and array as break case catch class clone const continue declare default \" +\n                       \"do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final \" +\n                       \"for foreach function global goto if implements interface instanceof namespace \" +\n                       \"new or private protected public static switch throw trait try use var while xor \" +\n                       \"die echo empty exit eval include include_once isset list require require_once return \" +\n                       \"print unset __halt_compiler self static parent\"),\n    blockKeywords: keywords(\"catch do else elseif for foreach if switch try while\"),\n    atoms: keywords(\"true false null TRUE FALSE NULL\"),\n    multiLineStrings: true,\n    hooks: {\n      \"$\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"variable-2\";\n      },\n      \"<\": function(stream, state) {\n        if (stream.match(/<</)) {\n          stream.eatWhile(/[\\w\\.]/);\n          state.tokenize = heredoc(stream.current().slice(3));\n          return state.tokenize(stream, state);\n        }\n        return false;\n      },\n      \"#\": function(stream, state) {\n        while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n        return \"comment\";\n      },\n      \"/\": function(stream, state) {\n        if (stream.eat(\"/\")) {\n          while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n          return \"comment\";\n        }\n        return false;\n      }\n    }\n  };\n\n  CodeMirror.defineMode(\"php\", function(config, parserConfig) {\n    var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n    var jsMode = CodeMirror.getMode(config, \"javascript\");\n    var cssMode = CodeMirror.getMode(config, \"css\");\n    var phpMode = CodeMirror.getMode(config, phpConfig);\n\n    function dispatch(stream, state) { // TODO open PHP inside text/css\n      var isPHP = state.mode == \"php\";\n      if (stream.sol() && state.pending != '\"') state.pending = null;\n      if (state.curMode == htmlMode) {\n        if (stream.match(/^<\\?\\w*/)) {\n          state.curMode = phpMode;\n          state.curState = state.php;\n          state.curClose = \"?>\";\n      state.mode = \"php\";\n          return \"meta\";\n        }\n        if (state.pending == '\"') {\n          while (!stream.eol() && stream.next() != '\"') {}\n          var style = \"string\";\n        } else if (state.pending && stream.pos < state.pending.end) {\n          stream.pos = state.pending.end;\n          var style = state.pending.style;\n        } else {\n          var style = htmlMode.token(stream, state.curState);\n        }\n        state.pending = null;\n        var cur = stream.current(), openPHP = cur.search(/<\\?/);\n        if (openPHP != -1) {\n          if (style == \"string\" && /\\\"$/.test(cur) && !/\\?>/.test(cur)) state.pending = '\"';\n          else state.pending = {end: stream.pos, style: style};\n          stream.backUp(cur.length - openPHP);\n        } else if (style == \"tag\" && stream.current() == \">\" && state.curState.context) {\n          if (/^script$/i.test(state.curState.context.tagName)) {\n            state.curMode = jsMode;\n            state.curState = jsMode.startState(htmlMode.indent(state.curState, \"\"));\n            state.curClose = /^<\\/\\s*script\\s*>/i;\n        state.mode = \"javascript\";\n          }\n          else if (/^style$/i.test(state.curState.context.tagName)) {\n            state.curMode = cssMode;\n            state.curState = cssMode.startState(htmlMode.indent(state.curState, \"\"));\n            state.curClose = /^<\\/\\s*style\\s*>/i;\n            state.mode = \"css\";\n          }\n        }\n        return style;\n      } else if ((!isPHP || state.php.tokenize == null) &&\n                 stream.match(state.curClose, isPHP)) {\n        state.curMode = htmlMode;\n        state.curState = state.html;\n        state.curClose = null;\n    state.mode = \"html\";\n        if (isPHP) return \"meta\";\n        else return dispatch(stream, state);\n      } else {\n        return state.curMode.token(stream, state.curState);\n      }\n    }\n\n    return {\n      startState: function() {\n        var html = htmlMode.startState();\n        return {html: html,\n                php: phpMode.startState(),\n                curMode: parserConfig.startOpen ? phpMode : htmlMode,\n                curState: parserConfig.startOpen ? phpMode.startState() : html,\n                curClose: parserConfig.startOpen ? /^\\?>/ : null,\n        mode: parserConfig.startOpen ? \"php\" : \"html\",\n                pending: null}\n      },\n\n      copyState: function(state) {\n        var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),\n            php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;\n        if (state.curState == html) cur = htmlNew;\n        else if (state.curState == php) cur = phpNew;\n        else cur = CodeMirror.copyState(state.curMode, state.curState);\n        return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,\n                curClose: state.curClose, mode: state.mode,\n                pending: state.pending};\n      },\n\n      token: dispatch,\n\n      indent: function(state, textAfter) {\n        if ((state.curMode != phpMode && /^\\s*<\\//.test(textAfter)) ||\n            (state.curMode == phpMode && /^\\?>/.test(textAfter)))\n          return htmlMode.indent(state.html, textAfter);\n        return state.curMode.indent(state.curState, textAfter);\n      },\n\n      electricChars: \"/{}:\"\n    }\n  }, \"xml\", \"clike\", \"javascript\", \"css\");\n  CodeMirror.defineMIME(\"application/x-httpd-php\", \"php\");\n  CodeMirror.defineMIME(\"application/x-httpd-php-open\", {name: \"php\", startOpen: true});\n  CodeMirror.defineMIME(\"text/x-php\", phpConfig);\n})();\n\ndefine(\"thirdparty/CodeMirror2/mode/php/php\", function(){});\n\n/**\n * Link to the project's GitHub page:\n * https://github.com/pickhardt/coffeescript-codemirror-mode\n */\nCodeMirror.defineMode('coffeescript', function(conf) {\n    var ERRORCLASS = 'error';\n\n    function wordRegexp(words) {\n        return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n    }\n\n    var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!\\?]\");\n    var singleDelimiters = new RegExp('^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]');\n    var doubleOperators = new RegExp(\"^((\\->)|(\\=>)|(\\\\+\\\\+)|(\\\\+\\\\=)|(\\\\-\\\\-)|(\\\\-\\\\=)|(\\\\*\\\\*)|(\\\\*\\\\=)|(\\\\/\\\\/)|(\\\\/\\\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))\");\n    var doubleDelimiters = new RegExp(\"^((\\\\.\\\\.)|(\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n    var tripleDelimiters = new RegExp(\"^((\\\\.\\\\.\\\\.)|(//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\n    var identifiers = new RegExp(\"^[_A-Za-z$][_A-Za-z$0-9]*\");\n\n    var wordOperators = wordRegexp(['and', 'or', 'not',\n                                    'is', 'isnt', 'in',\n                                    'instanceof', 'typeof']);\n    var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',\n                          'switch', 'try', 'catch', 'finally', 'class'];\n    var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',\n                          'do', 'in', 'of', 'new', 'return', 'then',\n                          'this', 'throw', 'when', 'until'];\n\n    var keywords = wordRegexp(indentKeywords.concat(commonKeywords));\n\n    indentKeywords = wordRegexp(indentKeywords);\n\n\n    var stringPrefixes = new RegExp(\"^('{3}|\\\"{3}|['\\\"])\");\n    var regexPrefixes = new RegExp(\"^(/{3}|/)\");\n    var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];\n    var constants = wordRegexp(commonConstants);\n\n    // Tokenizers\n    function tokenBase(stream, state) {\n        // Handle scope changes\n        if (stream.sol()) {\n            var scopeOffset = state.scopes[0].offset;\n            if (stream.eatSpace()) {\n                var lineOffset = stream.indentation();\n                if (lineOffset > scopeOffset) {\n                    return 'indent';\n                } else if (lineOffset < scopeOffset) {\n                    return 'dedent';\n                }\n                return null;\n            } else {\n                if (scopeOffset > 0) {\n                    dedent(stream, state);\n                }\n            }\n        }\n        if (stream.eatSpace()) {\n            return null;\n        }\n\n        var ch = stream.peek();\n\n        // Handle docco title comment (single line)\n        if (stream.match(\"####\")) {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n        // Handle multi line comments\n        if (stream.match(\"###\")) {\n            state.tokenize = longComment;\n            return state.tokenize(stream, state);\n        }\n\n        // Single line comment\n        if (ch === '#') {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n        // Handle number literals\n        if (stream.match(/^-?[0-9\\.]/, false)) {\n            var floatLiteral = false;\n            // Floats\n            if (stream.match(/^-?\\d*\\.\\d+(e[\\+\\-]?\\d+)?/i)) {\n              floatLiteral = true;\n            }\n            if (stream.match(/^-?\\d+\\.\\d*/)) {\n              floatLiteral = true;\n            }\n            if (stream.match(/^-?\\.\\d+/)) {\n              floatLiteral = true;\n            }\n\n            if (floatLiteral) {\n                // prevent from getting extra . on 1..\n                if (stream.peek() == \".\"){\n                    stream.backUp(1);\n                }\n                return 'number';\n            }\n            // Integers\n            var intLiteral = false;\n            // Hex\n            if (stream.match(/^-?0x[0-9a-f]+/i)) {\n              intLiteral = true;\n            }\n            // Decimal\n            if (stream.match(/^-?[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n                intLiteral = true;\n            }\n            // Zero by itself with no other piece of number.\n            if (stream.match(/^-?0(?![\\dx])/i)) {\n              intLiteral = true;\n            }\n            if (intLiteral) {\n                return 'number';\n            }\n        }\n\n        // Handle strings\n        if (stream.match(stringPrefixes)) {\n            state.tokenize = tokenFactory(stream.current(), 'string');\n            return state.tokenize(stream, state);\n        }\n        // Handle regex literals\n        if (stream.match(regexPrefixes)) {\n            if (stream.current() != '/' || stream.match(/^.*\\//, false)) { // prevent highlight of division\n                state.tokenize = tokenFactory(stream.current(), 'string-2');\n                return state.tokenize(stream, state);\n            } else {\n                stream.backUp(1);\n            }\n        }\n\n        // Handle operators and delimiters\n        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {\n            return 'punctuation';\n        }\n        if (stream.match(doubleOperators)\n            || stream.match(singleOperators)\n            || stream.match(wordOperators)) {\n            return 'operator';\n        }\n        if (stream.match(singleDelimiters)) {\n            return 'punctuation';\n        }\n\n        if (stream.match(constants)) {\n            return 'atom';\n        }\n\n        if (stream.match(keywords)) {\n            return 'keyword';\n        }\n\n        if (stream.match(identifiers)) {\n            return 'variable';\n        }\n\n        // Handle non-detected items\n        stream.next();\n        return ERRORCLASS;\n    }\n\n    function tokenFactory(delimiter, outclass) {\n        var singleline = delimiter.length == 1;\n        return function tokenString(stream, state) {\n            while (!stream.eol()) {\n                stream.eatWhile(/[^'\"\\/\\\\]/);\n                if (stream.eat('\\\\')) {\n                    stream.next();\n                    if (singleline && stream.eol()) {\n                        return outclass;\n                    }\n                } else if (stream.match(delimiter)) {\n                    state.tokenize = tokenBase;\n                    return outclass;\n                } else {\n                    stream.eat(/['\"\\/]/);\n                }\n            }\n            if (singleline) {\n                if (conf.mode.singleLineStringErrors) {\n                    outclass = ERRORCLASS\n                } else {\n                    state.tokenize = tokenBase;\n                }\n            }\n            return outclass;\n        };\n    }\n\n    function longComment(stream, state) {\n        while (!stream.eol()) {\n            stream.eatWhile(/[^#]/);\n            if (stream.match(\"###\")) {\n                state.tokenize = tokenBase;\n                break;\n            }\n            stream.eatWhile(\"#\");\n        }\n        return \"comment\"\n    }\n\n    function indent(stream, state, type) {\n        type = type || 'coffee';\n        var indentUnit = 0;\n        if (type === 'coffee') {\n            for (var i = 0; i < state.scopes.length; i++) {\n                if (state.scopes[i].type === 'coffee') {\n                    indentUnit = state.scopes[i].offset + conf.indentUnit;\n                    break;\n                }\n            }\n        } else {\n            indentUnit = stream.column() + stream.current().length;\n        }\n        state.scopes.unshift({\n            offset: indentUnit,\n            type: type\n        });\n    }\n\n    function dedent(stream, state) {\n        if (state.scopes.length == 1) return;\n        if (state.scopes[0].type === 'coffee') {\n            var _indent = stream.indentation();\n            var _indent_index = -1;\n            for (var i = 0; i < state.scopes.length; ++i) {\n                if (_indent === state.scopes[i].offset) {\n                    _indent_index = i;\n                    break;\n                }\n            }\n            if (_indent_index === -1) {\n                return true;\n            }\n            while (state.scopes[0].offset !== _indent) {\n                state.scopes.shift();\n            }\n            return false\n        } else {\n            state.scopes.shift();\n            return false;\n        }\n    }\n\n    function tokenLexer(stream, state) {\n        var style = state.tokenize(stream, state);\n        var current = stream.current();\n\n        // Handle '.' connected identifiers\n        if (current === '.') {\n            style = state.tokenize(stream, state);\n            current = stream.current();\n            if (style === 'variable') {\n                return 'variable';\n            } else {\n                return ERRORCLASS;\n            }\n        }\n\n        // Handle properties\n        if (current === '@') {\n            stream.eat('@');\n            return 'keyword';\n        }\n\n        // Handle scope changes.\n        if (current === 'return') {\n            state.dedent += 1;\n        }\n        if (((current === '->' || current === '=>') &&\n                  !state.lambda &&\n                  state.scopes[0].type == 'coffee' &&\n                  stream.peek() === '')\n               || style === 'indent') {\n            indent(stream, state);\n        }\n        var delimiter_index = '[({'.indexOf(current);\n        if (delimiter_index !== -1) {\n            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));\n        }\n        if (indentKeywords.exec(current)){\n            indent(stream, state);\n        }\n        if (current == 'then'){\n            dedent(stream, state);\n        }\n\n\n        if (style === 'dedent') {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        delimiter_index = '])}'.indexOf(current);\n        if (delimiter_index !== -1) {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {\n            if (state.scopes.length > 1) state.scopes.shift();\n            state.dedent -= 1;\n        }\n\n        return style;\n    }\n\n    var external = {\n        startState: function(basecolumn) {\n            return {\n              tokenize: tokenBase,\n              scopes: [{offset:basecolumn || 0, type:'coffee'}],\n              lastToken: null,\n              lambda: false,\n              dedent: 0\n          };\n        },\n\n        token: function(stream, state) {\n            var style = tokenLexer(stream, state);\n\n            state.lastToken = {style:style, content: stream.current()};\n\n            if (stream.eol() && stream.lambda) {\n                state.lambda = false;\n            }\n\n            return style;\n        },\n\n        indent: function(state, textAfter) {\n            if (state.tokenize != tokenBase) {\n                return 0;\n            }\n\n            return state.scopes[0].offset;\n        }\n\n    };\n    return external;\n});\n\nCodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');\n\ndefine(\"thirdparty/CodeMirror2/mode/coffeescript/coffeescript\", function(){});\n\n/**\n * Author: Hans Engel\n * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)\n */\nCodeMirror.defineMode(\"clojure\", function (config, mode) {\n    var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\", TAG = \"tag\",\n        ATOM = \"atom\", NUMBER = \"number\", BRACKET = \"bracket\", KEYWORD = \"keyword\";\n    var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;\n\n    function makeKeywords(str) {\n        var obj = {}, words = str.split(\" \");\n        for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n        return obj;\n    }\n\n    var atoms = makeKeywords(\"true false nil\");\n    \n    var keywords = makeKeywords(\n      \"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle\");\n\n    var builtins = makeKeywords(\n        \"* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq\");\n\n    var indentKeys = makeKeywords(\n        // Built-ins\n        \"ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch \" +\n\n        // Binding forms\n        \"let letfn binding loop for doseq dotimes when-let if-let \" +\n\n        // Data structures\n        \"defstruct struct-map assoc \" +\n\n        // clojure.test\n        \"testing deftest \" +\n\n        // contrib\n        \"handler-case handle dotrace deftrace\");\n\n    var tests = {\n        digit: /\\d/,\n        digit_or_colon: /[\\d:]/,\n        hex: /[0-9a-fA-F]/,\n        sign: /[+-]/,\n        exponent: /[eE]/,\n        keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n        basic: /[\\w\\$_\\-]/,\n        lang_keyword: /[\\w*+!\\-_?:\\/]/\n    };\n\n    function stateStack(indent, type, prev) { // represents a state stack object\n        this.indent = indent;\n        this.type = type;\n        this.prev = prev;\n    }\n\n    function pushStack(state, indent, type) {\n        state.indentStack = new stateStack(indent, type, state.indentStack);\n    }\n\n    function popStack(state) {\n        state.indentStack = state.indentStack.prev;\n    }\n\n    function isNumber(ch, stream){\n        // hex\n        if ( ch === '0' && 'x' == stream.peek().toLowerCase() ) {\n            stream.eat('x');\n            stream.eatWhile(tests.hex);\n            return true;\n        }\n\n        // leading sign\n        if ( ch == '+' || ch == '-' ) {\n          stream.eat(tests.sign);\n          ch = stream.next();\n        }\n\n        if ( tests.digit.test(ch) ) {\n            stream.eat(ch);\n            stream.eatWhile(tests.digit);\n\n            if ( '.' == stream.peek() ) {\n                stream.eat('.');\n                stream.eatWhile(tests.digit);\n            }\n\n            if ( 'e' == stream.peek().toLowerCase() ) {\n                stream.eat(tests.exponent);\n                stream.eat(tests.sign);\n                stream.eatWhile(tests.digit);\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    return {\n        startState: function () {\n            return {\n                indentStack: null,\n                indentation: 0,\n                mode: false\n            };\n        },\n\n        token: function (stream, state) {\n            if (state.indentStack == null && stream.sol()) {\n                // update indentation, but only if indentStack is empty\n                state.indentation = stream.indentation();\n            }\n\n            // skip spaces\n            if (stream.eatSpace()) {\n                return null;\n            }\n            var returnType = null;\n\n            switch(state.mode){\n                case \"string\": // multi-line string parsing mode\n                    var next, escaped = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"\\\"\" && !escaped) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        escaped = !escaped && next == \"\\\\\";\n                    }\n                    returnType = STRING; // continue on in string mode\n                    break;\n                default: // default parsing mode\n                    var ch = stream.next();\n\n                    if (ch == \"\\\"\") {\n                        state.mode = \"string\";\n                        returnType = STRING;\n                    } else if (ch == \"'\" && !( tests.digit_or_colon.test(stream.peek()) )) {\n                        returnType = ATOM;\n                    } else if (ch == \";\") { // comment\n                        stream.skipToEnd(); // rest of the line is a comment\n                        returnType = COMMENT;\n                    } else if (isNumber(ch,stream)){\n                        returnType = NUMBER;\n                    } else if (ch == \"(\" || ch == \"[\") {\n                        var keyWord = ''; var indentTemp = stream.column();\n                        /**\n                        Either\n                        (indent-word ..\n                        (non-indent-word ..\n                        (;something else, bracket, etc.\n                        */\n\n                        if (ch == \"(\") while ((letter = stream.eat(tests.keyword_char)) != null) {\n                            keyWord += letter;\n                        }\n\n                        if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word\n                            pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);\n                        } else { // non-indent word\n                            // we continue eating the spaces\n                            stream.eatSpace();\n                            if (stream.eol() || stream.peek() == \";\") {\n                                // nothing significant after\n                                // we restart indentation 1 space after\n                                pushStack(state, indentTemp + 1, ch);\n                            } else {\n                                pushStack(state, indentTemp + stream.current().length, ch); // else we match\n                            }\n                        }\n                        stream.backUp(stream.current().length - 1); // undo all the eating\n\n                        returnType = BRACKET;\n                    } else if (ch == \")\" || ch == \"]\") {\n                        returnType = BRACKET;\n                        if (state.indentStack != null && state.indentStack.type == (ch == \")\" ? \"(\" : \"[\")) {\n                            popStack(state);\n                        }\n                    } else if ( ch == \":\" ) {\n                        stream.eatWhile(tests.lang_keyword);\n                        return ATOM;\n                    } else {\n                        stream.eatWhile(tests.basic);\n\n                        if (keywords && keywords.propertyIsEnumerable(stream.current())) {\n                            returnType = KEYWORD;\n                        } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {\n                            returnType = BUILTIN;\n                        } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {\n                            returnType = ATOM;\n                        } else returnType = null;\n                    }\n            }\n\n            return returnType;\n        },\n\n        indent: function (state, textAfter) {\n            if (state.indentStack == null) return state.indentation;\n            return state.indentStack.indent;\n        }\n    };\n});\n\nCodeMirror.defineMIME(\"text/x-clojure\", \"clojure\");\n\ndefine(\"thirdparty/CodeMirror2/mode/clojure/clojure\", function(){});\n\n// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)\n// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)\nCodeMirror.defineMode(\"perl\",function(config,parserConfig){\n    // http://perldoc.perl.org\n    var PERL={                      //   null - magic touch\n                            //   1 - keyword\n                            //   2 - def\n                            //   3 - atom\n                            //   4 - operator\n                            //   5 - variable-2 (predefined)\n                            //   [x,y] - x=1,2,3; y=must be defined if x{...}\n                        //  PERL operators\n        '->'                :   4,\n        '++'                :   4,\n        '--'                :   4,\n        '**'                :   4,\n                            //   ! ~ \\ and unary + and -\n        '=~'                :   4,\n        '!~'                :   4,\n        '*'             :   4,\n        '/'             :   4,\n        '%'             :   4,\n        'x'             :   4,\n        '+'             :   4,\n        '-'             :   4,\n        '.'             :   4,\n        '<<'                :   4,\n        '>>'                :   4,\n                            //   named unary operators\n        '<'             :   4,\n        '>'             :   4,\n        '<='                :   4,\n        '>='                :   4,\n        'lt'                :   4,\n        'gt'                :   4,\n        'le'                :   4,\n        'ge'                :   4,\n        '=='                :   4,\n        '!='                :   4,\n        '<=>'               :   4,\n        'eq'                :   4,\n        'ne'                :   4,\n        'cmp'               :   4,\n        '~~'                :   4,\n        '&'             :   4,\n        '|'             :   4,\n        '^'             :   4,\n        '&&'                :   4,\n        '||'                :   4,\n        '//'                :   4,\n        '..'                :   4,\n        '...'               :   4,\n        '?'             :   4,\n        ':'             :   4,\n        '='             :   4,\n        '+='                :   4,\n        '-='                :   4,\n        '*='                :   4,  //   etc. ???\n        ','             :   4,\n        '=>'                :   4,\n        '::'                :   4,\n                            //   list operators (rightward)\n        'not'               :   4,\n        'and'               :   4,\n        'or'                :   4,\n        'xor'               :   4,\n                        //  PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)\n        'BEGIN'             :   [5,1],\n        'END'               :   [5,1],\n        'PRINT'             :   [5,1],\n        'PRINTF'            :   [5,1],\n        'GETC'              :   [5,1],\n        'READ'              :   [5,1],\n        'READLINE'          :   [5,1],\n        'DESTROY'           :   [5,1],\n        'TIE'               :   [5,1],\n        'TIEHANDLE'         :   [5,1],\n        'UNTIE'             :   [5,1],\n        'STDIN'             :    5,\n        'STDIN_TOP'         :    5,\n        'STDOUT'            :    5,\n        'STDOUT_TOP'            :    5,\n        'STDERR'            :    5,\n        'STDERR_TOP'            :    5,\n        '$ARG'              :    5,\n        '$_'                :    5,\n        '@ARG'              :    5,\n        '@_'                :    5,\n        '$LIST_SEPARATOR'       :    5,\n        '$\"'                :    5,\n        '$PROCESS_ID'           :    5,\n        '$PID'              :    5,\n        '$$'                :    5,\n        '$REAL_GROUP_ID'        :    5,\n        '$GID'              :    5,\n        '$('                :    5,\n        '$EFFECTIVE_GROUP_ID'       :    5,\n        '$EGID'             :    5,\n        '$)'                :    5,\n        '$PROGRAM_NAME'         :    5,\n        '$0'                :    5,\n        '$SUBSCRIPT_SEPARATOR'      :    5,\n        '$SUBSEP'           :    5,\n        '$;'                :    5,\n        '$REAL_USER_ID'         :    5,\n        '$UID'              :    5,\n        '$<'                :    5,\n        '$EFFECTIVE_USER_ID'        :    5,\n        '$EUID'             :    5,\n        '$>'                :    5,\n        '$a'                :    5,\n        '$b'                :    5,\n        '$COMPILING'            :    5,\n        '$^C'               :    5,\n        '$DEBUGGING'            :    5,\n        '$^D'               :    5,\n        '${^ENCODING}'          :    5,\n        '$ENV'              :    5,\n        '%ENV'              :    5,\n        '$SYSTEM_FD_MAX'        :    5,\n        '$^F'               :    5,\n        '@F'                :    5,\n        '${^GLOBAL_PHASE}'      :    5,\n        '$^H'               :    5,\n        '%^H'               :    5,\n        '@INC'              :    5,\n        '%INC'              :    5,\n        '$INPLACE_EDIT'         :    5,\n        '$^I'               :    5,\n        '$^M'               :    5,\n        '$OSNAME'           :    5,\n        '$^O'               :    5,\n        '${^OPEN}'          :    5,\n        '$PERLDB'           :    5,\n        '$^P'               :    5,\n        '$SIG'              :    5,\n        '%SIG'              :    5,\n        '$BASETIME'         :    5,\n        '$^T'               :    5,\n        '${^TAINT}'         :    5,\n        '${^UNICODE}'           :    5,\n        '${^UTF8CACHE}'         :    5,\n        '${^UTF8LOCALE}'        :    5,\n        '$PERL_VERSION'         :    5,\n        '$^V'               :    5,\n        '${^WIN32_SLOPPY_STAT}'     :    5,\n        '$EXECUTABLE_NAME'      :    5,\n        '$^X'               :    5,\n        '$1'                :    5, // - regexp $1, $2...\n        '$MATCH'            :    5,\n        '$&'                :    5,\n        '${^MATCH}'         :    5,\n        '$PREMATCH'         :    5,\n        '$`'                :    5,\n        '${^PREMATCH}'          :    5,\n        '$POSTMATCH'            :    5,\n        \"$'\"                :    5,\n        '${^POSTMATCH}'         :    5,\n        '$LAST_PAREN_MATCH'     :    5,\n        '$+'                :    5,\n        '$LAST_SUBMATCH_RESULT'     :    5,\n        '$^N'               :    5,\n        '@LAST_MATCH_END'       :    5,\n        '@+'                :    5,\n        '%LAST_PAREN_MATCH'     :    5,\n        '%+'                :    5,\n        '@LAST_MATCH_START'     :    5,\n        '@-'                :    5,\n        '%LAST_MATCH_START'     :    5,\n        '%-'                :    5,\n        '$LAST_REGEXP_CODE_RESULT'  :    5,\n        '$^R'               :    5,\n        '${^RE_DEBUG_FLAGS}'        :    5,\n        '${^RE_TRIE_MAXBUF}'        :    5,\n        '$ARGV'             :    5,\n        '@ARGV'             :    5,\n        'ARGV'              :    5,\n        'ARGVOUT'           :    5,\n        '$OUTPUT_FIELD_SEPARATOR'   :    5,\n        '$OFS'              :    5,\n        '$,'                :    5,\n        '$INPUT_LINE_NUMBER'        :    5,\n        '$NR'               :    5,\n        '$.'                :    5,\n        '$INPUT_RECORD_SEPARATOR'   :    5,\n        '$RS'               :    5,\n        '$/'                :    5,\n        '$OUTPUT_RECORD_SEPARATOR'  :    5,\n        '$ORS'              :    5,\n        '$\\\\'               :    5,\n        '$OUTPUT_AUTOFLUSH'     :    5,\n        '$|'                :    5,\n        '$ACCUMULATOR'          :    5,\n        '$^A'               :    5,\n        '$FORMAT_FORMFEED'      :    5,\n        '$^L'               :    5,\n        '$FORMAT_PAGE_NUMBER'       :    5,\n        '$%'                :    5,\n        '$FORMAT_LINES_LEFT'        :    5,\n        '$-'                :    5,\n        '$FORMAT_LINE_BREAK_CHARACTERS' :    5,\n        '$:'                :    5,\n        '$FORMAT_LINES_PER_PAGE'    :    5,\n        '$='                :    5,\n        '$FORMAT_TOP_NAME'      :    5,\n        '$^'                :    5,\n        '$FORMAT_NAME'          :    5,\n        '$~'                :    5,\n        '${^CHILD_ERROR_NATIVE}'    :    5,\n        '$EXTENDED_OS_ERROR'        :    5,\n        '$^E'               :    5,\n        '$EXCEPTIONS_BEING_CAUGHT'  :    5,\n        '$^S'               :    5,\n        '$WARNING'          :    5,\n        '$^W'               :    5,\n        '${^WARNING_BITS}'      :    5,\n        '$OS_ERROR'         :    5,\n        '$ERRNO'            :    5,\n        '$!'                :    5,\n        '%OS_ERROR'         :    5,\n        '%ERRNO'            :    5,\n        '%!'                :    5,\n        '$CHILD_ERROR'          :    5,\n        '$?'                :    5,\n        '$EVAL_ERROR'           :    5,\n        '$@'                :    5,\n        '$OFMT'             :    5,\n        '$#'                :    5,\n        '$*'                :    5,\n        '$ARRAY_BASE'           :    5,\n        '$['                :    5,\n        '$OLD_PERL_VERSION'     :    5,\n        '$]'                :    5,\n                        //  PERL blocks\n        'if'                :[1,1],\n        elsif               :[1,1],\n        'else'              :[1,1],\n        'while'             :[1,1],\n        unless              :[1,1],\n        'for'               :[1,1],\n        foreach             :[1,1],\n                        //  PERL functions\n        'abs'               :1, // - absolute value function\n        accept              :1, // - accept an incoming socket connect\n        alarm               :1, // - schedule a SIGALRM\n        'atan2'             :1, // - arctangent of Y/X in the range -PI to PI\n        bind                :1, // - binds an address to a socket\n        binmode             :1, // - prepare binary files for I/O\n        bless               :1, // - create an object\n        bootstrap           :1, //\n        'break'             :1, // - break out of a \"given\" block\n        caller              :1, // - get context of the current subroutine call\n        chdir               :1, // - change your current working directory\n        chmod               :1, // - changes the permissions on a list of files\n        chomp               :1, // - remove a trailing record separator from a string\n        chop                :1, // - remove the last character from a string\n        chown               :1, // - change the owership on a list of files\n        chr             :1, // - get character this number represents\n        chroot              :1, // - make directory new root for path lookups\n        close               :1, // - close file (or pipe or socket) handle\n        closedir            :1, // - close directory handle\n        connect             :1, // - connect to a remote socket\n        'continue'          :[1,1], // - optional trailing block in a while or foreach\n        'cos'               :1, // - cosine function\n        crypt               :1, // - one-way passwd-style encryption\n        dbmclose            :1, // - breaks binding on a tied dbm file\n        dbmopen             :1, // - create binding on a tied dbm file\n        'default'           :1, //\n        defined             :1, // - test whether a value, variable, or function is defined\n        'delete'            :1, // - deletes a value from a hash\n        die             :1, // - raise an exception or bail out\n        'do'                :1, // - turn a BLOCK into a TERM\n        dump                :1, // - create an immediate core dump\n        each                :1, // - retrieve the next key/value pair from a hash\n        endgrent            :1, // - be done using group file\n        endhostent          :1, // - be done using hosts file\n        endnetent           :1, // - be done using networks file\n        endprotoent         :1, // - be done using protocols file\n        endpwent            :1, // - be done using passwd file\n        endservent          :1, // - be done using services file\n        eof             :1, // - test a filehandle for its end\n        'eval'              :1, // - catch exceptions or compile and run code\n        'exec'              :1, // - abandon this program to run another\n        exists              :1, // - test whether a hash key is present\n        exit                :1, // - terminate this program\n        'exp'               :1, // - raise I to a power\n        fcntl               :1, // - file control system call\n        fileno              :1, // - return file descriptor from filehandle\n        flock               :1, // - lock an entire file with an advisory lock\n        fork                :1, // - create a new process just like this one\n        format              :1, // - declare a picture format with use by the write() function\n        formline            :1, // - internal function used for formats\n        getc                :1, // - get the next character from the filehandle\n        getgrent            :1, // - get next group record\n        getgrgid            :1, // - get group record given group user ID\n        getgrnam            :1, // - get group record given group name\n        gethostbyaddr           :1, // - get host record given its address\n        gethostbyname           :1, // - get host record given name\n        gethostent          :1, // - get next hosts record\n        getlogin            :1, // - return who logged in at this tty\n        getnetbyaddr            :1, // - get network record given its address\n        getnetbyname            :1, // - get networks record given name\n        getnetent           :1, // - get next networks record\n        getpeername         :1, // - find the other end of a socket connection\n        getpgrp             :1, // - get process group\n        getppid             :1, // - get parent process ID\n        getpriority         :1, // - get current nice value\n        getprotobyname          :1, // - get protocol record given name\n        getprotobynumber        :1, // - get protocol record numeric protocol\n        getprotoent         :1, // - get next protocols record\n        getpwent            :1, // - get next passwd record\n        getpwnam            :1, // - get passwd record given user login name\n        getpwuid            :1, // - get passwd record given user ID\n        getservbyname           :1, // - get services record given its name\n        getservbyport           :1, // - get services record given numeric port\n        getservent          :1, // - get next services record\n        getsockname         :1, // - retrieve the sockaddr for a given socket\n        getsockopt          :1, // - get socket options on a given socket\n        given               :1, //\n        glob                :1, // - expand filenames using wildcards\n        gmtime              :1, // - convert UNIX time into record or string using Greenwich time\n        'goto'              :1, // - create spaghetti code\n        grep                :1, // - locate elements in a list test true against a given criterion\n        hex             :1, // - convert a string to a hexadecimal number\n        'import'            :1, // - patch a module's namespace into your own\n        index               :1, // - find a substring within a string\n        'int'               :1, // - get the integer portion of a number\n        ioctl               :1, // - system-dependent device control system call\n        'join'              :1, // - join a list into a string using a separator\n        keys                :1, // - retrieve list of indices from a hash\n        kill                :1, // - send a signal to a process or process group\n        last                :1, // - exit a block prematurely\n        lc              :1, // - return lower-case version of a string\n        lcfirst             :1, // - return a string with just the next letter in lower case\n        length              :1, // - return the number of bytes in a string\n        'link'              :1, // - create a hard link in the filesytem\n        listen              :1, // - register your socket as a server\n        local               : 2,    // - create a temporary value for a global variable (dynamic scoping)\n        localtime           :1, // - convert UNIX time into record or string using local time\n        lock                :1, // - get a thread lock on a variable, subroutine, or method\n        'log'               :1, // - retrieve the natural logarithm for a number\n        lstat               :1, // - stat a symbolic link\n        m               :null,  // - match a string with a regular expression pattern\n        map             :1, // - apply a change to a list to get back a new list with the changes\n        mkdir               :1, // - create a directory\n        msgctl              :1, // - SysV IPC message control operations\n        msgget              :1, // - get SysV IPC message queue\n        msgrcv              :1, // - receive a SysV IPC message from a message queue\n        msgsnd              :1, // - send a SysV IPC message to a message queue\n        my              : 2,    // - declare and assign a local variable (lexical scoping)\n        'new'               :1, //\n        next                :1, // - iterate a block prematurely\n        no              :1, // - unimport some module symbols or semantics at compile time\n        oct             :1, // - convert a string to an octal number\n        open                :1, // - open a file, pipe, or descriptor\n        opendir             :1, // - open a directory\n        ord             :1, // - find a character's numeric representation\n        our             : 2,    // - declare and assign a package variable (lexical scoping)\n        pack                :1, // - convert a list into a binary representation\n        'package'           :1, // - declare a separate global namespace\n        pipe                :1, // - open a pair of connected filehandles\n        pop             :1, // - remove the last element from an array and return it\n        pos             :1, // - find or set the offset for the last/next m//g search\n        print               :1, // - output a list to a filehandle\n        printf              :1, // - output a formatted list to a filehandle\n        prototype           :1, // - get the prototype (if any) of a subroutine\n        push                :1, // - append one or more elements to an array\n        q               :null,  // - singly quote a string\n        qq              :null,  // - doubly quote a string\n        qr              :null,  // - Compile pattern\n        quotemeta           :null,  // - quote regular expression magic characters\n        qw              :null,  // - quote a list of words\n        qx              :null,  // - backquote quote a string\n        rand                :1, // - retrieve the next pseudorandom number\n        read                :1, // - fixed-length buffered input from a filehandle\n        readdir             :1, // - get a directory from a directory handle\n        readline            :1, // - fetch a record from a file\n        readlink            :1, // - determine where a symbolic link is pointing\n        readpipe            :1, // - execute a system command and collect standard output\n        recv                :1, // - receive a message over a Socket\n        redo                :1, // - start this loop iteration over again\n        ref             :1, // - find out the type of thing being referenced\n        rename              :1, // - change a filename\n        require             :1, // - load in external functions from a library at runtime\n        reset               :1, // - clear all variables of a given name\n        'return'            :1, // - get out of a function early\n        reverse             :1, // - flip a string or a list\n        rewinddir           :1, // - reset directory handle\n        rindex              :1, // - right-to-left substring search\n        rmdir               :1, // - remove a directory\n        s               :null,  // - replace a pattern with a string\n        say             :1, // - print with newline\n        scalar              :1, // - force a scalar context\n        seek                :1, // - reposition file pointer for random-access I/O\n        seekdir             :1, // - reposition directory pointer\n        select              :1, // - reset default output or do I/O multiplexing\n        semctl              :1, // - SysV semaphore control operations\n        semget              :1, // - get set of SysV semaphores\n        semop               :1, // - SysV semaphore operations\n        send                :1, // - send a message over a socket\n        setgrent            :1, // - prepare group file for use\n        sethostent          :1, // - prepare hosts file for use\n        setnetent           :1, // - prepare networks file for use\n        setpgrp             :1, // - set the process group of a process\n        setpriority         :1, // - set a process's nice value\n        setprotoent         :1, // - prepare protocols file for use\n        setpwent            :1, // - prepare passwd file for use\n        setservent          :1, // - prepare services file for use\n        setsockopt          :1, // - set some socket options\n        shift               :1, // - remove the first element of an array, and return it\n        shmctl              :1, // - SysV shared memory operations\n        shmget              :1, // - get SysV shared memory segment identifier\n        shmread             :1, // - read SysV shared memory\n        shmwrite            :1, // - write SysV shared memory\n        shutdown            :1, // - close down just half of a socket connection\n        'sin'               :1, // - return the sine of a number\n        sleep               :1, // - block for some number of seconds\n        socket              :1, // - create a socket\n        socketpair          :1, // - create a pair of sockets\n        'sort'              :1, // - sort a list of values\n        splice              :1, // - add or remove elements anywhere in an array\n        'split'             :1, // - split up a string using a regexp delimiter\n        sprintf             :1, // - formatted print into a string\n        'sqrt'              :1, // - square root function\n        srand               :1, // - seed the random number generator\n        stat                :1, // - get a file's status information\n        state               :1, // - declare and assign a state variable (persistent lexical scoping)\n        study               :1, // - optimize input data for repeated searches\n        'sub'               :1, // - declare a subroutine, possibly anonymously\n        'substr'            :1, // - get or alter a portion of a stirng\n        symlink             :1, // - create a symbolic link to a file\n        syscall             :1, // - execute an arbitrary system call\n        sysopen             :1, // - open a file, pipe, or descriptor\n        sysread             :1, // - fixed-length unbuffered input from a filehandle\n        sysseek             :1, // - position I/O pointer on handle used with sysread and syswrite\n        system              :1, // - run a separate program\n        syswrite            :1, // - fixed-length unbuffered output to a filehandle\n        tell                :1, // - get current seekpointer on a filehandle\n        telldir             :1, // - get current seekpointer on a directory handle\n        tie             :1, // - bind a variable to an object class\n        tied                :1, // - get a reference to the object underlying a tied variable\n        time                :1, // - return number of seconds since 1970\n        times               :1, // - return elapsed time for self and child processes\n        tr              :null,  // - transliterate a string\n        truncate            :1, // - shorten a file\n        uc              :1, // - return upper-case version of a string\n        ucfirst             :1, // - return a string with just the next letter in upper case\n        umask               :1, // - set file creation mode mask\n        undef               :1, // - remove a variable or function definition\n        unlink              :1, // - remove one link to a file\n        unpack              :1, // - convert binary structure into normal perl variables\n        unshift             :1, // - prepend more elements to the beginning of a list\n        untie               :1, // - break a tie binding to a variable\n        use             :1, // - load in a module at compile time\n        utime               :1, // - set a file's last access and modify times\n        values              :1, // - return a list of the values in a hash\n        vec             :1, // - test or set particular bits in a string\n        wait                :1, // - wait for any child process to die\n        waitpid             :1, // - wait for a particular child process to die\n        wantarray           :1, // - get void vs scalar vs list context of current subroutine call\n        warn                :1, // - print debugging info\n        when                :1, //\n        write               :1, // - print a picture record\n        y               :null}; // - transliterate a string\n\n    var RXstyle=\"string-2\";\n    var RXmodifiers=/[goseximacplud]/;      // NOTE: \"m\", \"s\", \"y\" and \"tr\" need to correct real modifiers for each regexp type\n\n    function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)\n        state.chain=null;                               //                                                          12   3tail\n        state.style=null;\n        state.tail=null;\n        state.tokenize=function(stream,state){\n            var e=false,c,i=0;\n            while(c=stream.next()){\n                if(c===chain[i]&&!e){\n                    if(chain[++i]!==undefined){\n                        state.chain=chain[i];\n                        state.style=style;\n                        state.tail=tail}\n                    else if(tail)\n                        stream.eatWhile(tail);\n                    state.tokenize=tokenPerl;\n                    return style}\n                e=!e&&c==\"\\\\\"}\n            return style};\n        return state.tokenize(stream,state)}\n\n    function tokenSOMETHING(stream,state,string){\n        state.tokenize=function(stream,state){\n            if(stream.string==string)\n                state.tokenize=tokenPerl;\n            stream.skipToEnd();\n            return \"string\"};\n        return state.tokenize(stream,state)}\n\n    function tokenPerl(stream,state){\n        if(stream.eatSpace())\n            return null;\n        if(state.chain)\n            return tokenChain(stream,state,state.chain,state.style,state.tail);\n        if(stream.match(/^\\-?[\\d\\.]/,false))\n            if(stream.match(/^(\\-?(\\d*\\.\\d+(e[+-]?\\d+)?|\\d+\\.\\d*)|0x[\\da-fA-F]+|0b[01]+|\\d+(e[+-]?\\d+)?)/))\n                return 'number';\n        if(stream.match(/^<<(?=\\w)/)){          // NOTE: <<SOMETHING\\n...\\nSOMETHING\\n\n            stream.eatWhile(/\\w/);\n            return tokenSOMETHING(stream,state,stream.current().substr(2))}\n        if(stream.sol()&&stream.match(/^\\=item(?!\\w)/)){// NOTE: \\n=item...\\n=cut\\n\n            return tokenSOMETHING(stream,state,'=cut')}\n        var ch=stream.next();\n        if(ch=='\"'||ch==\"'\"){               // NOTE: ' or \" or <<'SOMETHING'\\n...\\nSOMETHING\\n or <<\"SOMETHING\"\\n...\\nSOMETHING\\n\n            if(stream.prefix(3)==\"<<\"+ch){\n                var p=stream.pos;\n                stream.eatWhile(/\\w/);\n                var n=stream.current().substr(1);\n                if(n&&stream.eat(ch))\n                    return tokenSOMETHING(stream,state,n);\n                stream.pos=p}\n            return tokenChain(stream,state,[ch],\"string\")}\n        if(ch==\"q\"){\n            var c=stream.look(-2);\n            if(!(c&&/\\w/.test(c))){\n                c=stream.look(0);\n                if(c==\"x\"){\n                    c=stream.look(1);\n                    if(c==\"(\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n                    if(c==\"[\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n                    if(c==\"{\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n                    if(c==\"<\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}\n                    if(/[\\^'\"!~\\/]/.test(c)){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}\n                else if(c==\"q\"){\n                    c=stream.look(1);\n                    if(c==\"(\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\")\"],\"string\")}\n                    if(c==\"[\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"]\"],\"string\")}\n                    if(c==\"{\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"}\"],\"string\")}\n                    if(c==\"<\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\">\"],\"string\")}\n                    if(/[\\^'\"!~\\/]/.test(c)){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[stream.eat(c)],\"string\")}}\n                else if(c==\"w\"){\n                    c=stream.look(1);\n                    if(c==\"(\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\")\"],\"bracket\")}\n                    if(c==\"[\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"]\"],\"bracket\")}\n                    if(c==\"{\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"}\"],\"bracket\")}\n                    if(c==\"<\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\">\"],\"bracket\")}\n                    if(/[\\^'\"!~\\/]/.test(c)){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[stream.eat(c)],\"bracket\")}}\n                else if(c==\"r\"){\n                    c=stream.look(1);\n                    if(c==\"(\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n                    if(c==\"[\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n                    if(c==\"{\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n                    if(c==\"<\"){\n                        stream.eatSuffix(2);\n                        return tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}\n                    if(/[\\^'\"!~\\/]/.test(c)){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}\n                else if(/[\\^'\"!~\\/(\\[{<]/.test(c)){\n                    if(c==\"(\"){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[\")\"],\"string\")}\n                    if(c==\"[\"){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[\"]\"],\"string\")}\n                    if(c==\"{\"){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[\"}\"],\"string\")}\n                    if(c==\"<\"){\n                        stream.eatSuffix(1);\n                        return tokenChain(stream,state,[\">\"],\"string\")}\n                    if(/[\\^'\"!~\\/]/.test(c)){\n                        return tokenChain(stream,state,[stream.eat(c)],\"string\")}}}}\n        if(ch==\"m\"){\n            var c=stream.look(-2);\n            if(!(c&&/\\w/.test(c))){\n                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                if(c){\n                    if(/[\\^'\"!~\\/]/.test(c)){\n                        return tokenChain(stream,state,[c],RXstyle,RXmodifiers)}\n                    if(c==\"(\"){\n                        return tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n                    if(c==\"[\"){\n                        return tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n                    if(c==\"{\"){\n                        return tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n                    if(c==\"<\"){\n                        return tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}}}}\n        if(ch==\"s\"){\n            var c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n            if(!c){\n                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                if(c){\n                    if(c==\"[\")\n                        return tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n                    if(c==\"{\")\n                        return tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n                    if(c==\"<\")\n                        return tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n                    if(c==\"(\")\n                        return tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}\n        if(ch==\"y\"){\n            var c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n            if(!c){\n                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                if(c){\n                    if(c==\"[\")\n                        return tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n                    if(c==\"{\")\n                        return tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n                    if(c==\"<\")\n                        return tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n                    if(c==\"(\")\n                        return tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}\n        if(ch==\"t\"){\n            var c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n            if(!c){\n                c=stream.eat(\"r\");if(c){\n                c=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n                if(c){\n                    if(c==\"[\")\n                        return tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n                    if(c==\"{\")\n                        return tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n                    if(c==\"<\")\n                        return tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n                    if(c==\"(\")\n                        return tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n                    return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}}\n        if(ch==\"`\"){\n            return tokenChain(stream,state,[ch],\"variable-2\")}\n        if(ch==\"/\"){\n            if(!/~\\s*$/.test(stream.prefix()))\n                return \"operator\";\n            else\n                return tokenChain(stream,state,[ch],RXstyle,RXmodifiers)}\n        if(ch==\"$\"){\n            var p=stream.pos;\n            if(stream.eatWhile(/\\d/)||stream.eat(\"{\")&&stream.eatWhile(/\\d/)&&stream.eat(\"}\"))\n                return \"variable-2\";\n            else\n                stream.pos=p}\n        if(/[$@%]/.test(ch)){\n            var p=stream.pos;\n            if(stream.eat(\"^\")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\\\\-#?@;:&`~\\^!\\[\\]*'\"$+.,\\/<>()]/)){\n                var c=stream.current();\n                if(PERL[c])\n                    return \"variable-2\"}\n            stream.pos=p}\n        if(/[$@%&]/.test(ch)){\n            if(stream.eatWhile(/[\\w$\\[\\]]/)||stream.eat(\"{\")&&stream.eatWhile(/[\\w$\\[\\]]/)&&stream.eat(\"}\")){\n                var c=stream.current();\n                if(PERL[c])\n                    return \"variable-2\";\n                else\n                    return \"variable\"}}\n        if(ch==\"#\"){\n            if(stream.look(-2)!=\"$\"){\n                stream.skipToEnd();\n                return \"comment\"}}\n        if(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/.test(ch)){\n            var p=stream.pos;\n            stream.eatWhile(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/);\n            if(PERL[stream.current()])\n                return \"operator\";\n            else\n                stream.pos=p}\n        if(ch==\"_\"){\n            if(stream.pos==1){\n                if(stream.suffix(6)==\"_END__\"){\n                    return tokenChain(stream,state,['\\0'],\"comment\")}\n                else if(stream.suffix(7)==\"_DATA__\"){\n                    return tokenChain(stream,state,['\\0'],\"variable-2\")}\n                else if(stream.suffix(7)==\"_C__\"){\n                    return tokenChain(stream,state,['\\0'],\"string\")}}}\n        if(/\\w/.test(ch)){\n            var p=stream.pos;\n            if(stream.look(-2)==\"{\"&&(stream.look(0)==\"}\"||stream.eatWhile(/\\w/)&&stream.look(0)==\"}\"))\n                return \"string\";\n            else\n                stream.pos=p}\n        if(/[A-Z]/.test(ch)){\n            var l=stream.look(-2);\n            var p=stream.pos;\n            stream.eatWhile(/[A-Z_]/);\n            if(/[\\da-z]/.test(stream.look(0))){\n                stream.pos=p}\n            else{\n                var c=PERL[stream.current()];\n                if(!c)\n                    return \"meta\";\n                if(c[1])\n                    c=c[0];\n                if(l!=\":\"){\n                    if(c==1)\n                        return \"keyword\";\n                    else if(c==2)\n                        return \"def\";\n                    else if(c==3)\n                        return \"atom\";\n                    else if(c==4)\n                        return \"operator\";\n                    else if(c==5)\n                        return \"variable-2\";\n                    else\n                        return \"meta\"}\n                else\n                    return \"meta\"}}\n        if(/[a-zA-Z_]/.test(ch)){\n            var l=stream.look(-2);\n            stream.eatWhile(/\\w/);\n            var c=PERL[stream.current()];\n            if(!c)\n                return \"meta\";\n            if(c[1])\n                c=c[0];\n            if(l!=\":\"){\n                if(c==1)\n                    return \"keyword\";\n                else if(c==2)\n                    return \"def\";\n                else if(c==3)\n                    return \"atom\";\n                else if(c==4)\n                    return \"operator\";\n                else if(c==5)\n                    return \"variable-2\";\n                else\n                    return \"meta\"}\n            else\n                return \"meta\"}\n        return null}\n\n    return{\n        startState:function(){\n            return{\n                tokenize:tokenPerl,\n                chain:null,\n                style:null,\n                tail:null}},\n        token:function(stream,state){\n            return (state.tokenize||tokenPerl)(stream,state)},\n        electricChars:\"{}\"}});\n\nCodeMirror.defineMIME(\"text/x-perl\", \"perl\");\n\n// it's like \"peek\", but need for look-ahead or look-behind if index < 0\nCodeMirror.StringStream.prototype.look=function(c){\n    return this.string.charAt(this.pos+(c||0))};\n\n// return a part of prefix of current stream from current position\nCodeMirror.StringStream.prototype.prefix=function(c){\n    if(c){\n        var x=this.pos-c;\n        return this.string.substr((x>=0?x:0),c)}\n    else{\n        return this.string.substr(0,this.pos-1)}};\n\n// return a part of suffix of current stream from current position\nCodeMirror.StringStream.prototype.suffix=function(c){\n    var y=this.string.length;\n    var x=y-this.pos+1;\n    return this.string.substr(this.pos,(c&&c<y?c:x))};\n\n// return a part of suffix of current stream from current position and change current position\nCodeMirror.StringStream.prototype.nsuffix=function(c){\n    var p=this.pos;\n    var l=c||(this.string.length-this.pos+1);\n    this.pos+=l;\n    return this.string.substr(p,l)};\n\n// eating and vomiting a part of stream from current position\nCodeMirror.StringStream.prototype.eatSuffix=function(c){\n    var x=this.pos+c;\n    var y;\n    if(x<=0)\n        this.pos=0;\n    else if(x>=(y=this.string.length-1))\n        this.pos=y;\n    else\n        this.pos=x};\n\ndefine(\"thirdparty/CodeMirror2/mode/perl/perl\", function(){});\n\nCodeMirror.defineMode(\"ruby\", function(config, parserConfig) {\n  function wordObj(words) {\n    var o = {};\n    for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;\n    return o;\n  }\n  var keywords = wordObj([\n    \"alias\", \"and\", \"BEGIN\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"defined?\", \"do\", \"else\",\n    \"elsif\", \"END\", \"end\", \"ensure\", \"false\", \"for\", \"if\", \"in\", \"module\", \"next\", \"not\", \"or\",\n    \"redo\", \"rescue\", \"retry\", \"return\", \"self\", \"super\", \"then\", \"true\", \"undef\", \"unless\",\n    \"until\", \"when\", \"while\", \"yield\", \"nil\", \"raise\", \"throw\", \"catch\", \"fail\", \"loop\", \"callcc\",\n    \"caller\", \"lambda\", \"proc\", \"public\", \"protected\", \"private\", \"require\", \"load\",\n    \"require_relative\", \"extend\", \"autoload\"\n  ]);\n  var indentWords = wordObj([\"def\", \"class\", \"case\", \"for\", \"while\", \"do\", \"module\", \"then\",\n                             \"catch\", \"loop\", \"proc\", \"begin\"]);\n  var dedentWords = wordObj([\"end\", \"until\"]);\n  var matching = {\"[\": \"]\", \"{\": \"}\", \"(\": \")\"};\n  var curPunc;\n\n  function chain(newtok, stream, state) {\n    state.tokenize.push(newtok);\n    return newtok(stream, state);\n  }\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    if (stream.sol() && stream.match(\"=begin\") && stream.eol()) {\n      state.tokenize.push(readBlockComment);\n      return \"comment\";\n    }\n    if (stream.eatSpace()) return null;\n    var ch = stream.next(), m;\n    if (ch == \"`\" || ch == \"'\" || ch == '\"' ||\n        (ch == \"/\" && !stream.eol() && stream.peek() != \" \")) {\n      return chain(readQuoted(ch, \"string\", ch == '\"' || ch == \"`\"), stream, state);\n    } else if (ch == \"%\") {\n      var style, embed = false;\n      if (stream.eat(\"s\")) style = \"atom\";\n      else if (stream.eat(/[WQ]/)) { style = \"string\"; embed = true; }\n      else if (stream.eat(/[wxqr]/)) style = \"string\";\n      var delim = stream.eat(/[^\\w\\s]/);\n      if (!delim) return \"operator\";\n      if (matching.propertyIsEnumerable(delim)) delim = matching[delim];\n      return chain(readQuoted(delim, style, embed, true), stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"<\" && (m = stream.match(/^<-?[\\`\\\"\\']?([a-zA-Z_?]\\w*)[\\`\\\"\\']?(?:;|$)/))) {\n      return chain(readHereDoc(m[1]), stream, state);\n    } else if (ch == \"0\") {\n      if (stream.eat(\"x\")) stream.eatWhile(/[\\da-fA-F]/);\n      else if (stream.eat(\"b\")) stream.eatWhile(/[01]/);\n      else stream.eatWhile(/[0-7]/);\n      return \"number\";\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^[\\d_]*(?:\\.[\\d_]+)?(?:[eE][+\\-]?[\\d_]+)?/);\n      return \"number\";\n    } else if (ch == \"?\") {\n      while (stream.match(/^\\\\[CM]-/)) {}\n      if (stream.eat(\"\\\\\")) stream.eatWhile(/\\w/);\n      else stream.next();\n      return \"string\";\n    } else if (ch == \":\") {\n      if (stream.eat(\"'\")) return chain(readQuoted(\"'\", \"atom\", false), stream, state);\n      if (stream.eat('\"')) return chain(readQuoted('\"', \"atom\", true), stream, state);\n      stream.eatWhile(/[\\w\\?]/);\n      return \"atom\";\n    } else if (ch == \"@\") {\n      stream.eat(\"@\");\n      stream.eatWhile(/[\\w\\?]/);\n      return \"variable-2\";\n    } else if (ch == \"$\") {\n      stream.next();\n      stream.eatWhile(/[\\w\\?]/);\n      return \"variable-3\";\n    } else if (/\\w/.test(ch)) {\n      stream.eatWhile(/[\\w\\?]/);\n      if (stream.eat(\":\")) return \"atom\";\n      return \"ident\";\n    } else if (ch == \"|\" && (state.varList || state.lastTok == \"{\" || state.lastTok == \"do\")) {\n      curPunc = \"|\";\n      return null;\n    } else if (/[\\(\\)\\[\\]{}\\\\;]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    } else if (ch == \"-\" && stream.eat(\">\")) {\n      return \"arrow\";\n    } else if (/[=+\\-\\/*:\\.^%<>~|]/.test(ch)) {\n      stream.eatWhile(/[=+\\-\\/*:\\.^%<>~|]/);\n      return \"operator\";\n    } else {\n      return null;\n    }\n  }\n\n  function tokenBaseUntilBrace() {\n    var depth = 1;\n    return function(stream, state) {\n      if (stream.peek() == \"}\") {\n        depth--;\n        if (depth == 0) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length-1](stream, state);\n        }\n      } else if (stream.peek() == \"{\") {\n        depth++;\n      }\n      return tokenBase(stream, state);\n    };\n  }\n  function readQuoted(quote, style, embed, unescaped) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && (unescaped || !escaped)) {\n          state.tokenize.pop();\n          break;\n        }\n        if (embed && ch == \"#\" && !escaped && stream.eat(\"{\")) {\n          state.tokenize.push(tokenBaseUntilBrace(arguments.callee));\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return style;\n    };\n  }\n  function readHereDoc(phrase) {\n    return function(stream, state) {\n      if (stream.match(phrase)) state.tokenize.pop();\n      else stream.skipToEnd();\n      return \"string\";\n    };\n  }\n  function readBlockComment(stream, state) {\n    if (stream.sol() && stream.match(\"=end\") && stream.eol())\n      state.tokenize.pop();\n    stream.skipToEnd();\n    return \"comment\";\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: [tokenBase],\n              indented: 0,\n              context: {type: \"top\", indented: -config.indentUnit},\n              continuedLine: false,\n              lastTok: null,\n              varList: false};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) state.indented = stream.indentation();\n      var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;\n      if (style == \"ident\") {\n        var word = stream.current();\n        style = keywords.propertyIsEnumerable(stream.current()) ? \"keyword\"\n          : /^[A-Z]/.test(word) ? \"tag\"\n          : (state.lastTok == \"def\" || state.lastTok == \"class\" || state.varList) ? \"def\"\n          : \"variable\";\n        if (indentWords.propertyIsEnumerable(word)) kwtype = \"indent\";\n        else if (dedentWords.propertyIsEnumerable(word)) kwtype = \"dedent\";\n        else if ((word == \"if\" || word == \"unless\") && stream.column() == stream.indentation())\n          kwtype = \"indent\";\n      }\n      if (curPunc || (style && style != \"comment\")) state.lastTok = word || curPunc || style;\n      if (curPunc == \"|\") state.varList = !state.varList;\n\n      if (kwtype == \"indent\" || /[\\(\\[\\{]/.test(curPunc))\n        state.context = {prev: state.context, type: curPunc || style, indented: state.indented};\n      else if ((kwtype == \"dedent\" || /[\\)\\]\\}]/.test(curPunc)) && state.context.prev)\n        state.context = state.context.prev;\n\n      if (stream.eol())\n        state.continuedLine = (curPunc == \"\\\\\" || style == \"operator\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0);\n      var ct = state.context;\n      var closing = ct.type == matching[firstChar] ||\n        ct.type == \"keyword\" && /^(?:end|until|else|elsif|when|rescue)\\b/.test(textAfter);\n      return ct.indented + (closing ? 0 : config.indentUnit) +\n        (state.continuedLine ? config.indentUnit : 0);\n    },\n     electricChars: \"}de\" // enD and rescuE\n\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-ruby\", \"ruby\");\n\n\ndefine(\"thirdparty/CodeMirror2/mode/ruby/ruby\", function(){});\n\n/*\n *  MySQL Mode for CodeMirror 2 by MySQL-Tools\n *  @author James Thorne (partydroid)\n *  @link   http://github.com/partydroid/MySQL-Tools\n *  @link   http://mysqltools.org\n *  @version 02/Jan/2012\n*/\nCodeMirror.defineMode(\"mysql\", function(config) {\n  var indentUnit = config.indentUnit;\n  var curPunc;\n\n  function wordRegexp(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var ops = wordRegexp([\"str\", \"lang\", \"langmatches\", \"datatype\", \"bound\", \"sameterm\", \"isiri\", \"isuri\",\n                        \"isblank\", \"isliteral\", \"union\", \"a\"]);\n  var keywords = wordRegexp([\n    ('ACCESSIBLE'),('ALTER'),('AS'),('BEFORE'),('BINARY'),('BY'),('CASE'),('CHARACTER'),('COLUMN'),('CONTINUE'),('CROSS'),('CURRENT_TIMESTAMP'),('DATABASE'),('DAY_MICROSECOND'),('DEC'),('DEFAULT'),\n    ('DESC'),('DISTINCT'),('DOUBLE'),('EACH'),('ENCLOSED'),('EXIT'),('FETCH'),('FLOAT8'),('FOREIGN'),('GRANT'),('HIGH_PRIORITY'),('HOUR_SECOND'),('IN'),('INNER'),('INSERT'),('INT2'),('INT8'),\n    ('INTO'),('JOIN'),('KILL'),('LEFT'),('LINEAR'),('LOCALTIME'),('LONG'),('LOOP'),('MATCH'),('MEDIUMTEXT'),('MINUTE_SECOND'),('NATURAL'),('NULL'),('OPTIMIZE'),('OR'),('OUTER'),('PRIMARY'),\n    ('RANGE'),('READ_WRITE'),('REGEXP'),('REPEAT'),('RESTRICT'),('RIGHT'),('SCHEMAS'),('SENSITIVE'),('SHOW'),('SPECIFIC'),('SQLSTATE'),('SQL_CALC_FOUND_ROWS'),('STARTING'),('TERMINATED'),\n    ('TINYINT'),('TRAILING'),('UNDO'),('UNLOCK'),('USAGE'),('UTC_DATE'),('VALUES'),('VARCHARACTER'),('WHERE'),('WRITE'),('ZEROFILL'),('ALL'),('AND'),('ASENSITIVE'),('BIGINT'),('BOTH'),('CASCADE'),\n    ('CHAR'),('COLLATE'),('CONSTRAINT'),('CREATE'),('CURRENT_TIME'),('CURSOR'),('DAY_HOUR'),('DAY_SECOND'),('DECLARE'),('DELETE'),('DETERMINISTIC'),('DIV'),('DUAL'),('ELSEIF'),('EXISTS'),('FALSE'),\n    ('FLOAT4'),('FORCE'),('FULLTEXT'),('HAVING'),('HOUR_MINUTE'),('IGNORE'),('INFILE'),('INSENSITIVE'),('INT1'),('INT4'),('INTERVAL'),('ITERATE'),('KEYS'),('LEAVE'),('LIMIT'),('LOAD'),('LOCK'),\n    ('LONGTEXT'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MEDIUMINT'),('MINUTE_MICROSECOND'),('MODIFIES'),('NO_WRITE_TO_BINLOG'),('ON'),('OPTIONALLY'),('OUT'),('PRECISION'),('PURGE'),('READS'),\n    ('REFERENCES'),('RENAME'),('REQUIRE'),('REVOKE'),('SCHEMA'),('SELECT'),('SET'),('SPATIAL'),('SQLEXCEPTION'),('SQL_BIG_RESULT'),('SSL'),('TABLE'),('TINYBLOB'),('TO'),('TRUE'),('UNIQUE'),\n    ('UPDATE'),('USING'),('UTC_TIMESTAMP'),('VARCHAR'),('WHEN'),('WITH'),('YEAR_MONTH'),('ADD'),('ANALYZE'),('ASC'),('BETWEEN'),('BLOB'),('CALL'),('CHANGE'),('CHECK'),('CONDITION'),('CONVERT'),\n    ('CURRENT_DATE'),('CURRENT_USER'),('DATABASES'),('DAY_MINUTE'),('DECIMAL'),('DELAYED'),('DESCRIBE'),('DISTINCTROW'),('DROP'),('ELSE'),('ESCAPED'),('EXPLAIN'),('FLOAT'),('FOR'),('FROM'),\n    ('GROUP'),('HOUR_MICROSECOND'),('IF'),('INDEX'),('INOUT'),('INT'),('INT3'),('INTEGER'),('IS'),('KEY'),('LEADING'),('LIKE'),('LINES'),('LOCALTIMESTAMP'),('LONGBLOB'),('LOW_PRIORITY'),\n    ('MEDIUMBLOB'),('MIDDLEINT'),('MOD'),('NOT'),('NUMERIC'),('OPTION'),('ORDER'),('OUTFILE'),('PROCEDURE'),('READ'),('REAL'),('RELEASE'),('REPLACE'),('RETURN'),('RLIKE'),('SECOND_MICROSECOND'),\n    ('SEPARATOR'),('SMALLINT'),('SQL'),('SQLWARNING'),('SQL_SMALL_RESULT'),('STRAIGHT_JOIN'),('THEN'),('TINYTEXT'),('TRIGGER'),('UNION'),('UNSIGNED'),('USE'),('UTC_TIME'),('VARBINARY'),('VARYING'),\n    ('WHILE'),('XOR'),('FULL'),('COLUMNS'),('MIN'),('MAX'),('STDEV'),('COUNT')\n  ]);\n  var operatorChars = /[*+\\-<>=&|]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    curPunc = null;\n    if (ch == \"$\" || ch == \"?\") {\n      stream.match(/^[\\w\\d]*/);\n      return \"variable-2\";\n    }\n    else if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n      stream.match(/^[^\\s\\u00a0>]*>?/);\n      return \"atom\";\n    }\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"`\") {\n      state.tokenize = tokenOpLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    else if (ch == \"-\") {\n        ch2 = stream.next();\n        if(ch2==\"-\")\n        {\n            stream.skipToEnd();\n            return \"comment\";\n        }\n\n    }\n    else if (operatorChars.test(ch)) {\n      stream.eatWhile(operatorChars);\n      return null;\n    }\n    else if (ch == \":\") {\n      stream.eatWhile(/[\\w\\d\\._\\-]/);\n      return \"atom\";\n    }\n    else {\n      stream.eatWhile(/[_\\w\\d]/);\n      if (stream.eat(\":\")) {\n        stream.eatWhile(/[\\w\\d_\\-]/);\n        return \"atom\";\n      }\n      var word = stream.current(), type;\n      if (ops.test(word))\n        return null;\n      else if (keywords.test(word))\n        return \"keyword\";\n      else\n        return \"variable\";\n    }\n  }\n\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n\n  function tokenOpLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"variable-2\";\n    };\n  }\n\n\n  function pushContext(state, type, col) {\n    state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n  }\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              context: null,\n              indent: 0,\n              col: 0};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null) state.context.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n        state.context.align = true;\n      }\n\n      if (curPunc == \"(\") pushContext(state, \")\", stream.column());\n      else if (curPunc == \"[\") pushContext(state, \"]\", stream.column());\n      else if (curPunc == \"{\") pushContext(state, \"}\", stream.column());\n      else if (/[\\]\\}\\)]/.test(curPunc)) {\n        while (state.context && state.context.type == \"pattern\") popContext(state);\n        if (state.context && curPunc == state.context.type) popContext(state);\n      }\n      else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n      else if (/atom|string|variable/.test(style) && state.context) {\n        if (/[\\}\\]]/.test(state.context.type))\n          pushContext(state, \"pattern\", stream.column());\n        else if (state.context.type == \"pattern\" && !state.context.align) {\n          state.context.align = true;\n          state.context.col = stream.column();\n        }\n      }\n\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var firstChar = textAfter && textAfter.charAt(0);\n      var context = state.context;\n      if (/[\\]\\}]/.test(firstChar))\n        while (context && context.type == \"pattern\") context = context.prev;\n\n      var closing = context && firstChar == context.type;\n      if (!context)\n        return 0;\n      else if (context.type == \"pattern\")\n        return context.col;\n      else if (context.align)\n        return context.col + (closing ? 0 : 1);\n      else\n        return context.indent + (closing ? 0 : indentUnit);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-mysql\", \"mysql\");\n\ndefine(\"thirdparty/CodeMirror2/mode/mysql/mysql\", function(){});\n\nCodeMirror.defineMode(\"diff\", function() {\n\n  var TOKEN_NAMES = {\n    '+': 'tag',\n    '-': 'string',\n    '@': 'meta'\n  };\n\n  return {\n    token: function(stream) {\n      var tw_pos = stream.string.search(/[\\t ]+?$/);\n\n      if (!stream.sol() || tw_pos === 0) {\n        stream.skipToEnd();\n        return (\"error \" + (\n          TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');\n      }\n\n      var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();\n\n      if (tw_pos === -1) {\n        stream.skipToEnd();\n      } else {\n        stream.pos = tw_pos;\n      }\n\n      return token_name;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-diff\", \"diff\");\n\ndefine(\"thirdparty/CodeMirror2/mode/diff/diff\", function(){});\n\nCodeMirror.defineMode(\"markdown\", function(cmCfg, modeCfg) {\n\n  var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });\n\n  var header   = 'header'\n  ,   code     = 'comment'\n  ,   quote    = 'quote'\n  ,   list     = 'string'\n  ,   hr       = 'hr'\n  ,   linktext = 'link'\n  ,   linkhref = 'string'\n  ,   em       = 'em'\n  ,   strong   = 'strong'\n  ,   emstrong = 'emstrong';\n\n  var hrRE = /^([*\\-=_])(?:\\s*\\1){2,}\\s*$/\n  ,   ulRE = /^[*\\-+]\\s+/\n  ,   olRE = /^[0-9]+\\.\\s+/\n  ,   headerRE = /^(?:\\={3,}|-{3,})$/\n  ,   textRE = /^[^\\[*_\\\\<>`]+/;\n\n  function switchInline(stream, state, f) {\n    state.f = state.inline = f;\n    return f(stream, state);\n  }\n\n  function switchBlock(stream, state, f) {\n    state.f = state.block = f;\n    return f(stream, state);\n  }\n\n\n  // Blocks\n\n  function blankLine(state) {\n    // Reset EM state\n    state.em = false;\n    // Reset STRONG state\n    state.strong = false;\n    return null;\n  }\n\n  function blockNormal(stream, state) {\n    var match;\n    if (state.indentationDiff >= 4) {\n      state.indentation -= state.indentationDiff;\n      stream.skipToEnd();\n      return code;\n    } else if (stream.eatSpace()) {\n      return null;\n    } else if (stream.peek() === '#' || stream.match(headerRE)) {\n      state.header = true;\n    } else if (stream.eat('>')) {\n      state.indentation++;\n      state.quote = true;\n    } else if (stream.peek() === '[') {\n      return switchInline(stream, state, footnoteLink);\n    } else if (stream.match(hrRE, true)) {\n      return hr;\n    } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {\n      state.indentation += match[0].length;\n      return list;\n    }\n    \n    return switchInline(stream, state, state.inline);\n  }\n\n  function htmlBlock(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {\n      state.f = inlineNormal;\n      state.block = blockNormal;\n    }\n    return style;\n  }\n\n\n  // Inline\n  function getType(state) {\n    var styles = [];\n    \n    if (state.strong) { styles.push(state.em ? emstrong : strong); }\n    else if (state.em) { styles.push(em); }\n    \n    if (state.header) { styles.push(header); }\n    if (state.quote) { styles.push(quote); }\n\n    return styles.length ? styles.join(' ') : null;\n  }\n\n  function handleText(stream, state) {\n    if (stream.match(textRE, true)) {\n      return getType(state);\n    }\n    return undefined;        \n  }\n\n  function inlineNormal(stream, state) {\n    var style = state.text(stream, state)\n    if (typeof style !== 'undefined')\n      return style;\n    \n    var ch = stream.next();\n    \n    if (ch === '\\\\') {\n      stream.next();\n      return getType(state);\n    }\n    if (ch === '`') {\n      return switchInline(stream, state, inlineElement(code, '`'));\n    }\n    if (ch === '[') {\n      return switchInline(stream, state, linkText);\n    }\n    if (ch === '<' && stream.match(/^\\w/, false)) {\n      stream.backUp(1);\n      return switchBlock(stream, state, htmlBlock);\n    }\n\n    var t = getType(state);\n    if (ch === '*' || ch === '_') {\n      if (stream.eat(ch)) {\n        return (state.strong = !state.strong) ? getType(state) : t;\n      }\n      return (state.em = !state.em) ? getType(state) : t;\n    }\n    \n    return getType(state);\n  }\n\n  function linkText(stream, state) {\n    while (!stream.eol()) {\n      var ch = stream.next();\n      if (ch === '\\\\') stream.next();\n      if (ch === ']') {\n        state.inline = state.f = linkHref;\n        return linktext;\n      }\n    }\n    return linktext;\n  }\n\n  function linkHref(stream, state) {\n    stream.eatSpace();\n    var ch = stream.next();\n    if (ch === '(' || ch === '[') {\n      return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));\n    }\n    return 'error';\n  }\n\n  function footnoteLink(stream, state) {\n    if (stream.match(/^[^\\]]*\\]:/, true)) {\n      state.f = footnoteUrl;\n      return linktext;\n    }\n    return switchInline(stream, state, inlineNormal);\n  }\n\n  function footnoteUrl(stream, state) {\n    stream.eatSpace();\n    stream.match(/^[^\\s]+/, true);\n    state.f = state.inline = inlineNormal;\n    return linkhref;\n  }\n\n  function inlineRE(endChar) {\n    if (!inlineRE[endChar]) {\n      // match any not-escaped-non-endChar and any escaped char\n      // then match endChar or eol\n      inlineRE[endChar] = new RegExp('^(?:[^\\\\\\\\\\\\' + endChar + ']|\\\\\\\\.)*(?:\\\\' + endChar + '|$)');\n    }\n    return inlineRE[endChar];\n  }\n\n  function inlineElement(type, endChar, next) {\n    next = next || inlineNormal;\n    return function(stream, state) {\n      stream.match(inlineRE(endChar));\n      state.inline = state.f = next;\n      return type;\n    };\n  }\n\n  return {\n    startState: function() {\n      return {\n        f: blockNormal,\n        \n        block: blockNormal,\n        htmlState: htmlMode.startState(),\n        indentation: 0,\n        \n        inline: inlineNormal,\n        text: handleText,\n        em: false,\n        strong: false,\n        header: false,\n        quote: false\n      };\n    },\n\n    copyState: function(s) {\n      return {\n        f: s.f,\n        \n        block: s.block,\n        htmlState: CodeMirror.copyState(htmlMode, s.htmlState),\n        indentation: s.indentation,\n        \n        inline: s.inline,\n        text: s.text,\n        em: s.em,\n        strong: s.strong,\n        header: s.header,\n        quote: s.quote\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (stream.match(/^\\s*$/, true)) { return blankLine(state); }\n\n        // Reset state.header\n        state.header = false;\n        // Reset state.quote\n        state.quote = false;\n\n        state.f = state.block;\n        var indentation = stream.match(/^\\s*/, true)[0].replace(/\\t/g, '    ').length;\n        state.indentationDiff = indentation - state.indentation;\n        state.indentation = indentation;\n        if (indentation > 0) { return null; }\n      }\n      return state.f(stream, state);\n    },\n\n    blankLine: blankLine,\n\n    getType: getType\n  };\n\n}, \"xml\");\n\nCodeMirror.defineMIME(\"text/x-markdown\", \"markdown\");\n\ndefine(\"thirdparty/CodeMirror2/mode/markdown/markdown\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, PathUtils, FileError, brackets */\n\n/**\n * Set of utilites for working with the code editor\n */\ndefine('editor/EditorUtils',['require','exports','module','thirdparty/path-utils/path-utils.min','thirdparty/CodeMirror2/mode/xml/xml','thirdparty/CodeMirror2/mode/javascript/javascript','thirdparty/CodeMirror2/mode/css/css','thirdparty/CodeMirror2/mode/less/less','thirdparty/CodeMirror2/mode/htmlmixed/htmlmixed','thirdparty/CodeMirror2/mode/clike/clike','thirdparty/CodeMirror2/mode/php/php','thirdparty/CodeMirror2/mode/coffeescript/coffeescript','thirdparty/CodeMirror2/mode/clojure/clojure','thirdparty/CodeMirror2/mode/perl/perl','thirdparty/CodeMirror2/mode/ruby/ruby','thirdparty/CodeMirror2/mode/mysql/mysql','thirdparty/CodeMirror2/mode/diff/diff','thirdparty/CodeMirror2/mode/markdown/markdown'],function (require, exports, module) {\n    \n\n    require(\"thirdparty/path-utils/path-utils.min\");\n    require(\"thirdparty/CodeMirror2/mode/xml/xml\");\n    require(\"thirdparty/CodeMirror2/mode/javascript/javascript\");\n    require(\"thirdparty/CodeMirror2/mode/css/css\");\n    require(\"thirdparty/CodeMirror2/mode/less/less\");\n    require(\"thirdparty/CodeMirror2/mode/htmlmixed/htmlmixed\");\n    require(\"thirdparty/CodeMirror2/mode/clike/clike\");\n    require(\"thirdparty/CodeMirror2/mode/php/php\");\n    require(\"thirdparty/CodeMirror2/mode/coffeescript/coffeescript\");\n    require(\"thirdparty/CodeMirror2/mode/clojure/clojure\");\n    require(\"thirdparty/CodeMirror2/mode/perl/perl\");\n    require(\"thirdparty/CodeMirror2/mode/ruby/ruby\");\n    require(\"thirdparty/CodeMirror2/mode/mysql/mysql\");\n    require(\"thirdparty/CodeMirror2/mode/diff/diff\");\n    require(\"thirdparty/CodeMirror2/mode/markdown/markdown\");\n\n    /**\n     * @private\n     * Given a file URL, determines the mode to use based\n     * off the file's extension.\n     * @param {string} fileUrl  A cannonical file URL to extract the extension from\n     */\n    function getModeFromFileExtension(fileUrl) {\n        var ext = PathUtils.filenameExtension(fileUrl);\n        //incase the arg is just the ext\n        if (!ext) {\n            ext = fileUrl;\n        }\n        if (ext.charAt(0) === \".\") {\n            ext = ext.substr(1);\n        }\n\n        switch (ext) {\n\n        case \"js\":\n            return \"javascript\";\n\n        case \"json\":\n            return {name: \"javascript\", json: true};\n\n        case \"css\":\n            return \"css\";\n\n        case \"less\":\n            return \"less\";\n\n        case \"html\":\n        case \"htm\":\n        case \"xhtml\":\n        case \"cfm\":\n        case \"cfc\":\n            return \"htmlmixed\";\n\n        case \"xml\":\n            return \"xml\";\n\n        case \"php\":\n        case \"php3\":\n        case \"php4\":\n        case \"php5\":\n        case \"phtm\":\n        case \"phtml\":\n            return \"php\";\n\n        case \"cc\":\n        case \"cp\":\n        case \"cpp\":\n        case \"c++\":\n        case \"cxx\":\n        case \"hh\":\n        case \"hpp\":\n        case \"hxx\":\n        case \"h++\":\n        case \"ii\":\n            return \"text/x-c++src\";\n\n        case \"c\":\n        case \"h\":\n        case \"i\":\n            return \"text/x-csrc\";\n\n        case \"cs\":\n            return \"text/x-csharp\";\n\n        case \"java\":\n            return \"text/x-java\";\n\n        case \"coffee\":\n            return \"coffeescript\";\n\n        case \"clj\":\n            return \"clojure\";\n\n        case \"pl\":\n            return \"perl\";\n\n        case \"rb\":\n            return \"ruby\";\n\n        case \"sql\":\n            return \"mysql\";\n\n        case \"diff\":\n        case \"patch\":\n            return \"diff\";\n\n        case \"md\":\n            return \"markdown\";\n\n        default:\n            console.log(\"Called EditorUtils.js _getModeFromFileExtensions with an unhandled file extension: \" + ext);\n            return \"\";\n        }\n    }\n\n    // Define public API\n    exports.getModeFromFileExtension = getModeFromFileExtension;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\n/**\n * EditorManager owns the UI for the editor area. This essentially mirrors the 'current document'\n * property maintained by DocumentManager's model.\n *\n * Note that there is a little bit of unusual overlap between EditorManager and DocumentManager:\n * because the Document state is actually stored in the CodeMirror editor UI, DocumentManager is\n * not a pure headless model. Each Document encapsulates an editor instance, and thus EditorManager\n * must have some knowledge about Document's internal state (we access its _editor property).\n *\n * This module dispatches the following events:\n *    - focusedEditorChange -- When the focused editor (full or inline) changes and size/visibility are complete.\n */\ndefine('editor/EditorManager',['require','exports','module','file/FileUtils','command/Commands','command/CommandManager','document/DocumentManager','utils/PerfUtils','editor/Editor','editor/InlineTextEditor','editor/EditorUtils','utils/ViewUtils','strings'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var FileUtils           = require(\"file/FileUtils\"),\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Editor              = require(\"editor/Editor\").Editor,\n        InlineTextEditor    = require(\"editor/InlineTextEditor\").InlineTextEditor,\n        EditorUtils         = require(\"editor/EditorUtils\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        Strings             = require(\"strings\");\n    \n    /** @type {jQueryObject} DOM node that contains all editors (visible and hidden alike) */\n    var _editorHolder = null;\n    \n    /** @type {Editor} */\n    var _currentEditor = null;\n    /** @type {Document} */\n    var _currentEditorsDocument = null;\n    \n    /** @type {number} Used by {@link #_updateEditorSize()} */\n    var _resizeTimeout = null;\n    \n    /**\n     * Registered inline-editor widget providers. See {@link #registerInlineEditProvider()}.\n     * @type {Array.<function(...)>}\n     */\n    var _inlineEditProviders = [];\n    \n    \n    /**\n     * Adds keyboard command handlers to an Editor instance.\n     * @param {Editor} editor \n     * @param {!Object.<string,function(Editor)>} to destination key mapping\n     * @param {!Object.<string,function(Editor)>} from source key mapping\n     */\n    function mergeExtraKeys(editor, to, from) {\n        // Merge in the additionalKeys we were passed\n        function wrapEventHandler(externalHandler) {\n            return function (instance) {\n                externalHandler(editor);\n            };\n        }\n        var key;\n        for (key in from) {\n            if (from.hasOwnProperty(key)) {\n                if (to.hasOwnProperty(key)) {\n                    console.log(\"Warning: overwriting standard Editor shortcut \" + key);\n                }\n                to[key] = (editor !== null) ? wrapEventHandler(from[key]) : from[key];\n            }\n        }\n    }\n    \n    /**\n     * Creates a new Editor bound to the given Document. The editor's mode is inferred based on the\n     * file extension. The editor is appended to the given container as a visible child.\n     * @param {!Document} doc  Document for the Editor's content\n     * @param {!boolean} makeMasterEditor  If true, the Editor will set itself as the private \"master\"\n     *          Editor for the Document. If false, the Editor will attach to the Document as a \"slave.\"\n     * @param {!jQueryObject} container  Container to add the editor to.\n     * @param {{startLine: number, endLine: number}=} range If specified, range of lines within the document\n     *          to display in this editor. Inclusive.\n     * @return {Editor} the newly created editor.\n     */\n    function _createEditorForDocument(doc, makeMasterEditor, container, range, additionalKeys) {\n        var mode = EditorUtils.getModeFromFileExtension(doc.file.fullPath);\n        \n        return new Editor(doc, makeMasterEditor, mode, container, additionalKeys, range);\n    }\n    \n    /**\n     * @private\n     * Bound to Ctrl+E on outermost editors.\n     * @param {!Editor} editor the candidate host editor\n     * @return {$.Promise} a promise that will be resolved when an InlineWidget \n     *      is created or rejected when no inline editors are available.\n     */\n    function _openInlineWidget(editor) {\n        PerfUtils.markStart(PerfUtils.INLINE_EDITOR_OPEN);\n        \n        // Run through inline-editor providers until one responds\n        var pos = editor.getCursorPos(),\n            inlinePromise,\n            i,\n            result = new $.Deferred();\n        \n        for (i = 0; i < _inlineEditProviders.length && !inlinePromise; i++) {\n            var provider = _inlineEditProviders[i];\n            inlinePromise = provider(editor, pos);\n        }\n        \n        // If one of them will provide a widget, show it inline once ready\n        if (inlinePromise) {\n            inlinePromise.done(function (inlineWidget) {\n                editor.addInlineWidget(pos, inlineWidget);\n                PerfUtils.addMeasurement(PerfUtils.INLINE_EDITOR_OPEN);\n                result.resolve();\n            }).fail(function () {\n                // terminate timer that was started above\n                PerfUtils.finalizeMeasurement(PerfUtils.INLINE_EDITOR_OPEN);\n                result.reject();\n            });\n        } else {\n            // terminate timer that was started above\n            PerfUtils.finalizeMeasurement(PerfUtils.INLINE_EDITOR_OPEN);\n            result.reject();\n        }\n        \n        return result.promise();\n    }\n    \n    /**\n     * Removes the given widget UI from the given hostEditor (agnostic of what the widget's content\n     * is). The widget's onClosed() callback will be run as a result.\n     * @param {!Editor} hostEditor The editor containing the widget.\n     * @param {!InlineWidget} inlineWidget The inline widget to close.\n     * @param {!boolean} moveFocus  If true, focuses hostEditor and ensures the cursor position lies\n     *      near the inline's location.\n     */\n    function closeInlineWidget(hostEditor, inlineWidget, moveFocus) {\n        if (moveFocus) {\n            // Place cursor back on the line just above the inline (the line from which it was opened)\n            // If cursor's already on that line, leave it be to preserve column position\n            var widgetLine = hostEditor._codeMirror.getInlineWidgetInfo(inlineWidget.id).line;\n            var cursorLine = hostEditor.getCursorPos().line;\n            if (cursorLine !== widgetLine) {\n                hostEditor.setCursorPos({ line: widgetLine, pos: 0 });\n            }\n            \n            hostEditor.focus();\n        }\n        \n        hostEditor.removeInlineWidget(inlineWidget);\n    }\n    \n    /**\n     * Registers a new inline provider. When _openInlineWidget() is called each registered inline\n     * widget is called and asked if it wants to provide an inline widget given the current cursor\n     * location and document.\n     * @param {function} provider \n     *      Parameters: \n     *      {!Editor} editor, {!{line:Number, ch:Number}} pos\n     *      \n     *      Returns:\n     *      {$.Promise} a promise that will be resolved with an inlineWidget\n     *      or null to indicate the provider doesn't create an editor in this case\n     */\n    function registerInlineEditProvider(provider) {\n        _inlineEditProviders.push(provider);\n    }\n    \n    /**\n     * @private\n     * Given a host editor, return a list of all Editors in all its open inline widgets. (Ignoring\n     * any other inline widgets that might be open but don't contain Editors).\n     * @param {!Editor} hostEditor\n     * @return {Array.<Editor>}\n     *\n     */\n    function getInlineEditors(hostEditor) {\n        var inlineEditors = [];\n        hostEditor.getInlineWidgets().forEach(function (widget) {\n            if (widget instanceof InlineTextEditor) {\n                inlineEditors = inlineEditors.concat(widget.editors);\n            }\n        });\n        return inlineEditors;\n    }\n    \n    \n    \n    /**\n     * @private\n     * Creates a new \"full-size\" (not inline) Editor for the given Document, and sets it as the\n     * Document's master backing editor. The editor is not yet visible; to show it, use\n     * DocumentManager.setCurrentDocument().\n     * Semi-private: should only be called within this module or by Document.\n     * @param {!Document} document  Document whose main/full Editor to create\n     */\n    function _createFullEditorForDocument(document) {\n        // Create editor; make it initially invisible\n        var container = _editorHolder.get(0);\n        var editor = _createEditorForDocument(document, true, container);\n        editor.setVisible(false);\n    }\n    \n    /** Returns the visible full-size Editor corresponding to DocumentManager.getCurrentDocument() */\n    function getCurrentFullEditor() {\n        // This *should* always be equivalent to DocumentManager.getCurrentDocument()._masterEditor\n        return _currentEditor;\n    }\n\n    \n    /**\n     * Creates a new inline Editor instance for the given Document. The editor's mode is inferred\n     * based on the file extension. The editor is not yet visible or attached to a host editor.\n     * @param {!Document} doc  Document for the Editor's content\n     * @param {?{startLine:Number, endLine:Number}} range  If specified, all lines outside the given\n     *      range are hidden from the editor. Range is inclusive. Line numbers start at 0.\n     * @param {HTMLDivContainer} inlineContent\n     * @param  {function(inlineWidget)} closeThisInline\n     *\n     * @return {{content:DOMElement, editor:Editor}}\n     */\n    function createInlineEditorForDocument(doc, range, inlineContent, additionalKeys) {\n        // Create the Editor\n        var inlineEditor = _createEditorForDocument(doc, false, inlineContent, range, additionalKeys);\n        \n        $(exports).triggerHandler(\"focusedEditorChange\", inlineEditor);\n        \n        return { content: inlineContent, editor: inlineEditor };\n    }\n    \n    \n    /**\n     * Disposes the given Document's full-size editor if the doc is no longer \"open\" from the user's\n     * standpoint - not in the working set and not currentDocument).\n     * \n     * Destroying the full-size editor releases ONE ref to the Document; if inline editors or other\n     * UI elements are still referencing the Document it will still be 'open' (kept alive) from\n     * DocumentManager's standpoint. However, destroying the full-size editor does remove the backing\n     * \"master\" editor from the Document, rendering it immutable until either inline-editor edits or\n     * currentDocument change triggers _createFullEditorForDocument() full-size editor again.\n     *\n     * In certain edge cases, this is called directly by DocumentManager; see _gcDocuments() for details.\n     *\n     * @param {!Document} document Document whose \"master\" editor we may destroy\n     */\n    function _destroyEditorIfUnneeded(document) {\n        var editor = document._masterEditor;\n\n        if (!editor) {\n            return;\n        }\n        \n        // If outgoing editor is no longer needed, dispose it\n        var isCurrentDocument = (DocumentManager.getCurrentDocument() === document);\n        var isInWorkingSet = (DocumentManager.findInWorkingSet(document.file.fullPath) !== -1);\n        if (!isCurrentDocument && !isInWorkingSet) {\n            // Destroy the editor widget (which un-refs the Document and reverts it to read-only mode)\n            editor.destroy();\n            \n            // Our callers should really ensure this, but just for safety...\n            if (_currentEditor === editor) {\n                _currentEditorsDocument = null;\n                _currentEditor = null;\n            }\n        }\n    }\n\n    /** Focus the currently visible full-size editor. If no editor visible, does nothing. */\n    function focusEditor() {\n        if (_currentEditor) {\n            _currentEditor.focus();\n        }\n    }\n    \n    \n    /** \n     * Resize the editor. This should only be called if the contents of the editor holder are changed\n     * or if the height of the editor holder changes (except for overall window resizes, which are\n     * already taken care of automatically).\n     * @see #_updateEditorSize()\n     */\n    function resizeEditor() {\n        if (_currentEditor) {\n            $(_currentEditor.getScrollerElement()).height(_editorHolder.height());\n            _currentEditor.refresh();\n        }\n    }\n    \n    /**\n     * NJ's editor-resizing fix. Whenever the window resizes, we immediately adjust the editor's\n     * height.\n     * @see #resizeEditor()\n     */\n    function _updateEditorSize() {\n        // The editor itself will call refresh() when it gets the window resize event.\n        if (_currentEditor) {\n            $(_currentEditor.getScrollerElement()).height(_editorHolder.height());\n        }\n    }\n    \n    \n    /**\n     * @private\n     */\n    function _doShow(document) {\n        // Show new editor\n        _currentEditorsDocument = document;\n        _currentEditor = document._masterEditor;\n        \n        _currentEditor.setVisible(true);\n        \n        // Window may have been resized since last time editor was visible, so kick it now\n        resizeEditor();\n        \n        $(exports).triggerHandler(\"focusedEditorChange\", _currentEditor);\n    }\n\n    /**\n     * Make the given document's editor visible in the UI, hiding whatever was\n     * visible before. Creates a new editor if none is assigned.\n     * @param {!Document} document\n     */\n    function _showEditor(document) {\n        // Hide whatever was visible before\n        if (!_currentEditor) {\n            $(\"#not-editor\").css(\"display\", \"none\");\n        } else {\n            _currentEditor.setVisible(false);\n            _destroyEditorIfUnneeded(_currentEditorsDocument);\n        }\n        \n        // Ensure a main editor exists for this document to show in the UI\n        if (!document._masterEditor) {\n            // Editor doesn't exist: populate a new Editor with the text\n            _createFullEditorForDocument(document);\n        }\n        \n        _doShow(document);\n    }\n    \n\n    /** Hide the currently visible editor and show a placeholder UI in its place */\n    function _showNoEditor() {\n        if (_currentEditor) {\n            _currentEditor.setVisible(false);\n            _destroyEditorIfUnneeded(_currentEditorsDocument);\n            \n            _currentEditorsDocument = null;\n            _currentEditor = null;\n            \n            $(\"#not-editor\").css(\"display\", \"\");\n        \n            $(exports).triggerHandler(\"focusedEditorChange\", _currentEditor);\n        }\n    }\n\n    /** Handles changes to DocumentManager.getCurrentDocument() */\n    function _onCurrentDocumentChange() {\n        var doc = DocumentManager.getCurrentDocument(),\n            container = _editorHolder.get(0);\n        \n        var perfTimerName = PerfUtils.markStart(\"EditorManager._onCurrentDocumentChange():\\t\" + (!doc || doc.file.fullPath));\n\n        // Remove scroller-shadow from the current editor\n        if (_currentEditor) {\n            ViewUtils.removeScrollerShadow(container, _currentEditor);\n        }\n        \n        // Update the UI to show the right editor (or nothing), and also dispose old editor if no\n        // longer needed.\n        if (doc) {\n            _showEditor(doc);\n            ViewUtils.addScrollerShadow(container, _currentEditor);\n        } else {\n            _showNoEditor();\n        }\n\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n    \n    /** Handles removals from DocumentManager's working set list */\n    function _onWorkingSetRemove(event, removedFile) {\n        // There's one case where an editor should be disposed even though the current document\n        // didn't change: removing a document from the working set (via the \"X\" button). (This may\n        // also cover the case where the document WAS current, if the editor-swap happens before the\n        // removal from the working set.\n        var doc = DocumentManager.getOpenDocumentForPath(removedFile.fullPath);\n        if (doc) {\n            _destroyEditorIfUnneeded(doc);\n        }\n        // else, file was listed in working set but never shown in the editor - ignore\n    }\n\n    function _onWorkingSetRemoveList(event, removedFiles) {\n        removedFiles.forEach(function (removedFile) {\n            _onWorkingSetRemove(event, removedFile);\n        });\n    }\n\n    // Note: there are several paths that can lead to an editor getting destroyed\n    //  - file was in working set, but not in current editor; then closed (via working set \"X\" button)\n    //      --> handled by _onWorkingSetRemove()\n    //  - file was in current editor, but not in working set; then navigated away from\n    //      --> handled by _onCurrentDocumentChange()\n    //  - file was in current editor, but not in working set; then closed (via File > Close) (and thus\n    //    implicitly navigated away from)\n    //      --> handled by _onCurrentDocumentChange()\n    //  - file was in current editor AND in working set; then closed (via File > Close OR working set\n    //    \"X\" button) (and thus implicitly navigated away from)\n    //      --> handled by _onWorkingSetRemove() currently, but could be _onCurrentDocumentChange()\n    //      just as easily (depends on the order of events coming from DocumentManager)\n    \n    /**\n     * Designates the DOM node that will contain the currently active editor instance. EditorManager\n     * will own the content of this DOM node.\n     * @param {!jQueryObject} holder\n     */\n    function setEditorHolder(holder) {\n        if (_currentEditor) {\n            throw new Error(\"Cannot change editor area after an editor has already been created!\");\n        }\n        \n        _editorHolder = holder;\n    }\n    \n    /**\n     * Returns the currently focused inline widget.\n     * @returns {?{widget:!InlineTextEditor, editor:!Editor}}\n     */\n    function getFocusedInlineWidget() {\n        var result = null;\n        \n        if (_currentEditor) {\n            _currentEditor.getInlineWidgets().forEach(function (widget) {\n                if (widget instanceof InlineTextEditor) {\n                    widget.editors.forEach(function (editor) {\n                        if (editor.hasFocus()) {\n                            result = { widget: widget, editor: editor };\n                        }\n                    });\n                }\n            });\n        }\n        \n        return result;\n    }\n    \n    /**\n     * Returns the currently focused editor instance (full-sized OR inline editor).\n     * @returns {Editor}\n     */\n    function getFocusedEditor() {\n        if (_currentEditor) {\n            \n            // See if any inlines have focus\n            var focusedInline = getFocusedInlineWidget();\n            if (focusedInline) {\n                return focusedInline.editor;\n            }\n\n            // otherwise, see if full-sized editor has focus\n            if (_currentEditor.hasFocus()) {\n                return _currentEditor;\n            }\n        }\n        \n        return null;\n    }\n \n    /**\n     * Toggle Quick Edit command handler\n     * @return {!Promise} A promise resolved with true if an inline editor\n     *   is opened or false when closed. The promise is rejected if there\n     *   is no current editor or an inline editor is not created.\n     */\n    function _toggleQuickEdit() {\n        var result = new $.Deferred();\n        \n        if (_currentEditor) {\n            var inlineWidget = null,\n                focusedWidgetResult = getFocusedInlineWidget();\n            \n            if (focusedWidgetResult) {\n                inlineWidget = focusedWidgetResult.widget;\n            }\n            \n            if (inlineWidget) {\n                // an inline widget's editor has focus, so close it\n                PerfUtils.markStart(PerfUtils.INLINE_EDITOR_CLOSE);\n                inlineWidget.close();\n                PerfUtils.addMeasurement(PerfUtils.INLINE_EDITOR_CLOSE);\n        \n                // return a resolved promise to CommandManager\n                result.resolve(false);\n            } else {\n                // main editor has focus, so create an inline editor\n                _openInlineWidget(_currentEditor).done(function () {\n                    result.resolve(true);\n                }).fail(function () {\n                    result.reject();\n                });\n            }\n        } else {\n            // Can not open an inline editor without a host editor\n            result.reject();\n        }\n        \n        return result.promise();\n    }\n\n    CommandManager.register(Strings.CMD_TOGGLE_QUICK_EDIT, Commands.TOGGLE_QUICK_EDIT, _toggleQuickEdit);\n    \n    // Initialize: register listeners\n    $(DocumentManager).on(\"currentDocumentChange\", _onCurrentDocumentChange);\n    $(DocumentManager).on(\"workingSetRemove\", _onWorkingSetRemove);\n    $(DocumentManager).on(\"workingSetRemoveList\", _onWorkingSetRemoveList);\n\n    // Add this as a capture handler so we're guaranteed to run it before the editor does its own\n    // refresh on resize.\n    window.addEventListener(\"resize\", _updateEditorSize, true);\n    \n    // For unit tests\n    exports._openInlineWidget = _openInlineWidget;\n    \n    // Define public API\n    exports.setEditorHolder = setEditorHolder;\n    exports.getCurrentFullEditor = getCurrentFullEditor;\n    exports.createInlineEditorForDocument = createInlineEditorForDocument;\n    exports._createFullEditorForDocument = _createFullEditorForDocument;\n    exports._destroyEditorIfUnneeded = _destroyEditorIfUnneeded;\n    exports.focusEditor = focusEditor;\n    exports.getFocusedEditor = getFocusedEditor;\n    exports.getFocusedInlineWidget = getFocusedInlineWidget;\n    exports.resizeEditor = resizeEditor;\n    exports.registerInlineEditProvider = registerInlineEditProvider;\n    exports.getInlineEditors = getInlineEditors;\n    exports.closeInlineWidget = closeInlineWidget;\n    exports.mergeExtraKeys = mergeExtraKeys;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window, MouseEvent */\n\ndefine('command/Menus',['require','exports','module','command/Commands','command/KeyBindingManager','editor/EditorManager','strings','utils/StringUtils','command/CommandManager','widgets/PopUpManager'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var Commands                = require(\"command/Commands\"),\n        KeyBindingManager       = require(\"command/KeyBindingManager\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        Strings                 = require(\"strings\"),\n        StringUtils             = require(\"utils/StringUtils\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        PopUpManager            = require(\"widgets/PopUpManager\");\n\n    /**\n     * Brackets Application Menu Constants\n     * @enum {string}\n     */\n    var AppMenuBar = {\n        FILE_MENU:     \"file-menu\",\n        EDIT_MENU:     \"edit-menu\",\n        VIEW_MENU :    \"view-menu\",\n        NAVIGATE_MENU: \"navigate-menu\",\n        DEBUG_MENU:    \"debug-menu\"\n    };\n\n    /**\n     * Brackets Context Menu Constants\n     * @enum {string}\n     */\n    var ContextMenuIds = {\n        EDITOR_MENU:        \"editor-context-menu\",\n        INLINE_EDITOR_MENU: \"inline-editor-context-menu\",\n        PROJECT_MENU:       \"project-context-menu\"\n    };\n\n\n    /**\n     * Brackets Application Menu Section Constants\n     * It is preferred that plug-ins specify the location of new MenuItems\n     * in terms of a menu section rather than a specific MenuItem. This provides\n     * looser coupling to Bracket's internal MenuItems and makes menu organization\n     * more semantic. \n     * Use these constants as the \"relativeID\" parameter when calling addMenuItem() and\n     * specify a position of FIRST_IN_SECTION or LAST_IN_SECTION.\n     *\n     * Menu sections are denoted by dividers or the beginning/end of a menu\n     */\n    var MenuSection = {\n        // Menu Section                     Command ID to mark the section\n        FILE_OPEN_CLOSE_COMMANDS:           {sectionMarker: Commands.FILE_NEW},\n        FILE_SAVE_COMMANDS:                 {sectionMarker: Commands.FILE_SAVE},\n        FILE_LIVE:                          {sectionMarker: Commands.FILE_LIVE_FILE_PREVIEW},\n\n        EDIT_SELECTION_COMMANDS:            {sectionMarker: Commands.EDIT_SELECT_ALL},\n        EDIT_FIND:                          {sectionMarker: Commands.EDIT_FIND},\n        EDIT_REPLACE_COMMANDS:              {sectionMarker: Commands.EDIT_REPLACE},\n        EDIT_MODIFY_SELECTION:              {sectionMarker: Commands.EDIT_INDENT},\n\n        VIEW_HIDESHOW_COMMANDS:             {sectionMarker: Commands.VIEW_HIDE_SIDEBAR},\n        VIEW_FONTSIZE_COMMANDS:             {sectionMarker: Commands.VIEW_INCREASE_FONT_SIZE},\n\n        NAVIGATE_GOTO_COMMANDS:             {sectionMarker: Commands.NAVIGATE_QUICK_OPEN},\n        NAVIGATE_QUICK_EDIT_COMMANDS:       {sectionMarker: Commands.TOGGLE_QUICK_EDIT}\n    };\n\n    \n    /**\n      * Insertion position constants\n      * Used by addMenu(), addMenuItem(), and addSubMenu() to\n      * specify the relative position of a newly created menu object\n      * @enum {string}\n      */\n    var BEFORE =            \"before\";\n    var AFTER =             \"after\";\n    var FIRST =             \"first\";\n    var LAST =              \"last\";\n    var FIRST_IN_SECTION =  \"firstInSection\";\n    var LAST_IN_SECTION =   \"lastInSection\";\n\n    /**\n      * Other constants\n      */\n    var DIVIDER = \"---\";\n\n    /**\n     * Maps menuID's to Menu objects\n     * @type {Object.<string, Menu>}\n     */\n    var menuMap = {};\n\n    /**\n     * Maps contextMenuID's to ContextMenu objects\n     * @type {Object.<string, ContextMenu>}\n     */\n    var contextMenuMap = {};\n\n    /**\n     * Maps menuItemID's to MenuItem objects\n     * @type {Object.<string, MenuItem>}\n     */\n    var menuItemMap = {};\n    \n    /**\n     * Retrieves the Menu object for the corresponding id. \n     * @param {string} id\n     * @return {Menu}\n     */\n    function getMenu(id) {\n        return menuMap[id];\n    }\n\n    /**\n     * Retrieves the ContextMenu object for the corresponding id. \n     * @param {string} id\n     * @return {ContextMenu}\n     */\n    function getContextMenu(id) {\n        return contextMenuMap[id];\n    }\n\n    /**\n     * Retrieves the MenuItem object for the corresponding id. \n     * @param {string} id\n     * @return {MenuItem}\n     */\n    function getMenuItem(id) {\n        return menuItemMap[id];\n    }\n\n    function _getHTMLMenu(id) {\n        return $(\"#\" + StringUtils.jQueryIdEscape(id)).get(0);\n    }\n\n    function _getHTMLMenuItem(id) {\n        return $(\"#\" + StringUtils.jQueryIdEscape(id)).get(0);\n    }\n    \n    function _addKeyBindingToMenuItem($menuItem, key, displayKey) {\n        var $shortcut = $menuItem.find(\".menu-shortcut\");\n        \n        if ($shortcut.length === 0) {\n            $shortcut = $(\"<span class='menu-shortcut' />\");\n            $menuItem.append($shortcut);\n        }\n        \n        $shortcut.data(\"key\", key);\n        $shortcut.text(KeyBindingManager.formatKeyDescriptor(displayKey));\n    }\n    \n    function _addExistingKeyBinding(menuItem) {\n        var bindings = KeyBindingManager.getKeyBindings(menuItem.getCommand().getID()),\n            binding = null;\n        \n        if (bindings.length > 0) {\n            // add the latest key binding\n            binding = bindings[bindings.length - 1];\n            _addKeyBindingToMenuItem($(_getHTMLMenuItem(menuItem.id)), binding.key, binding.displayKey);\n        }\n        \n        return binding;\n    }\n    \n    /** NOT IMPLEMENTED\n     * Removes MenuItem\n     * \n     * TODO Question: for convenience should API provide a way to remove related\n     * keybindings and Command object?\n     */\n    // function removeMenuItem(id) {\n    //    NOT IMPLEMENTED\n    // }\n\n    var _menuDividerIDCount = 1;\n    function _getNextMenuItemDividerID() {\n        return \"brackets-menuDivider-\" + _menuDividerIDCount++;\n    }\n\n    // Help function for inserting elements into a list\n    function _insertInList($list, $element, position, $relativeElement) {\n        // Determine where to insert. Default is LAST.\n        var inserted = false;\n        if (position) {\n\n            // Adjust relative position for menu section positions since $relativeElement\n            // has already been resolved by _getRelativeMenuItem() to a menuItem\n            if (position === FIRST_IN_SECTION) {\n                position = BEFORE;\n            } else if (position === LAST_IN_SECTION) {\n                position = AFTER;\n            }\n\n            if (position === FIRST) {\n                $list.prepend($element);\n                inserted = true;\n            } else if ($relativeElement && $relativeElement.length > 0) {\n                if (position === AFTER) {\n                    $relativeElement.after($element);\n                    inserted = true;\n                } else if (position === BEFORE) {\n                    $relativeElement.before($element);\n                    inserted = true;\n                }\n            }\n        }\n\n        // Default to LAST\n        if (!inserted) {\n            $list.append($element);\n        }\n    }\n\n    /**\n     * @constructor\n     * @private\n     *\n     * MenuItem represents a single menu item that executes a Command or a menu divider. MenuItems\n     * may have a sub-menu. A MenuItem may correspond to an HTML-based\n     * menu item or a native menu item if Brackets is running in a native application shell\n     *\n     * Since MenuItems may have a native implementation clients should create MenuItems through \n     * addMenuItem() and should NOT construct a MenuItem object directly. \n     * Clients should also not access HTML content of a menu directly and instead use\n     * the MenuItem API to query and modify menus items.\n     *\n     * MenuItems are views on to Command objects so modify the underlying Command to modify the\n     * name, enabled, and checked state of a MenuItem. The MenuItem will update automatically\n     *\n     * @param {string} id\n     * @param {string|Command} command - the Command this MenuItem will reflect.\n     *                                   Use DIVIDER to specify a menu divider\n     */\n    function MenuItem(id, command) {\n        this.id = id;\n        this.isDivider = (command === DIVIDER);\n\n        if (!this.isDivider) {\n            // Bind event handlers\n            this._enabledChanged = this._enabledChanged.bind(this);\n            this._checkedChanged = this._checkedChanged.bind(this);\n            this._nameChanged = this._nameChanged.bind(this);\n            this._keyBindingAdded = this._keyBindingAdded.bind(this);\n            this._keyBindingRemoved = this._keyBindingRemoved.bind(this);\n\n            this._command = command;\n            $(this._command)\n                .on(\"enabledStateChange\", this._enabledChanged)\n                .on(\"checkedStateChange\", this._checkedChanged)\n                .on(\"nameChange\", this._nameChanged)\n                .on(\"keyBindingAdded\", this._keyBindingAdded)\n                .on(\"keyBindingRemoved\", this._keyBindingRemoved);\n        }\n    }\n\n    /**\n     * @constructor\n     * @private\n     *\n     * Menu represents a top-level menu in the menu bar. A Menu may correspond to an HTML-based\n     * menu or a native menu if Brackets is running in a native application shell. \n     * \n     * Since menus may have a native implementation clients should create Menus through \n     * addMenu() and should NOT construct a Menu object directly. \n     * Clients should also not access HTML content of a menu directly and instead use\n     * the Menu API to query and modify menus.\n     *\n     */\n    function Menu(id) {\n        this.id = id;\n    }\n\n    Menu.prototype._getMenuItemId = function (commandId) {\n        return (this.id + \"-\" + commandId);\n    };\n\n    /**\n     * Determine MenuItem in this Menu, that has the specified command\n     *\n     * @param {Command} command - the command to search for.\n     * @return {?HTMLLIElement} menu item list element\n     */\n    Menu.prototype._getMenuItemForCommand = function (command) {\n        if (!command) {\n            return null;\n        }\n        var foundMenuItem = menuItemMap[this._getMenuItemId(command.getID())];\n        if (!foundMenuItem) {\n            return null;\n        }\n        return $(_getHTMLMenuItem(foundMenuItem.id)).closest(\"li\");\n    };\n\n    /**\n     * Determine relative MenuItem\n     *\n     * @param {?string} relativeID - id of command (future: sub-menu).\n     * @param {?string} position - only needed when relativeID is a MenuSection\n     * @return {?HTMLLIElement} menu item list element\n     */\n    Menu.prototype._getRelativeMenuItem = function (relativeID, position) {\n        var $relativeElement,\n            key,\n            menuItem,\n            map,\n            foundMenuItem;\n        \n        if (relativeID) {\n            if (position === FIRST_IN_SECTION || position === LAST_IN_SECTION) {\n                if (!relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.log(\"Bad Parameter in _getRelativeMenuItem(): relativeID must be a MenuSection when position refers to a menu section\");\n                    return null;\n                }\n\n                // Determine the $relativeElement by traversing the sibling list and\n                // stop at the first divider found\n                // TODO: simplify using nextUntil()/prevUntil()\n                var $sectionMarker = this._getMenuItemForCommand(CommandManager.get(relativeID.sectionMarker));\n                if (!$sectionMarker) {\n                    console.log(\"_getRelativeMenuItem(): MenuSection \" + relativeID.sectionMarker +\n                                \" not found in Menu \" + this.id);\n                    return null;\n                }\n                var $listElem = $sectionMarker;\n                $relativeElement = $listElem;\n                while (true) {\n                    $listElem = (position === FIRST_IN_SECTION ? $listElem.prev() : $listElem.next());\n                    if ($listElem.length === 0) {\n                        break;\n                    } else if ($listElem.find(\".divider\").length > 0) {\n                        break;\n                    } else {\n                        $relativeElement = $listElem;\n                    }\n                }\n                \n            } else {\n                if (relativeID.hasOwnProperty(\"sectionMarker\")) {\n                    console.log(\"Bad Parameter in _getRelativeMenuItem(): if relativeID is a MenuSection, position must be FIRST_IN_SECTION or LAST_IN_SECTION\");\n                    return null;\n                }\n                \n                // handle FIRST, LAST, BEFORE, & AFTER\n                var command = CommandManager.get(relativeID);\n                if (command) {\n                    // Lookup Command for this Command id\n                    // Find MenuItem that has this command\n                    $relativeElement = this._getMenuItemForCommand(command);\n                }\n                if (!$relativeElement) {\n                    console.log(\"_getRelativeMenuItem(): MenuItem with Command id \" + relativeID +\n                                \" not found in Menu \" + this.id);\n                    return null;\n                }\n            }\n            \n            return $relativeElement;\n            \n        } else if (position && position !== FIRST && position !== LAST) {\n            console.log(\"Bad Parameter in _getRelativeMenuItem(): relative position specified with no relativeID\");\n            return null;\n        }\n        \n        return $relativeElement;\n    };\n    \n    /**\n     * Adds a new menu item with the specified id and display text. The insertion position is\n     * specified via the relativeID and position arguments which describe a position \n     * relative to another MenuItem or MenuGroup. It is preferred that plug-ins \n     * insert new  MenuItems relative to a menu section rather than a specific \n     * MenuItem (see Menu Section Constants).\n     *\n     * TODO: Sub-menus are not yet supported, but when they are implemented this API will\n     * allow adding new MenuItems to sub-menus as well.\n     *\n     * Note, keyBindings are bound to Command objects not MenuItems. The provided keyBindings\n     *      will be bound to the supplied Command object rather than the MenuItem.\n     * \n     * @param {!string | Command} command - the command the menu will execute.\n     *      Pass Menus.DIVIDER for a menu divider, or just call addMenuDivider() instead.\n     * @param {?string | Array.<{key: string, platform: string}>}  keyBindings - register one\n     *      one or more key bindings to associate with the supplied command.\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants). \n     * @param {?string} relativeID - id of command or menu section (future: sub-menu) that \n     *      the new menuItem will be positioned relative to. Required for all position constants\n     *      except FIRST and LAST.\n     *\n     * @return {MenuItem} the newly created MenuItem\n     */\n    Menu.prototype.addMenuItem = function (command, keyBindings, position, relativeID) {\n        var id,\n            $menuItem,\n            $link,\n            menuItem,\n            name,\n            commandID;\n\n        if (!command) {\n            throw new Error(\"addMenuItem(): missing required parameters: command\");\n        }\n\n        if (typeof (command) === \"string\") {\n            if (command === DIVIDER) {\n                name = DIVIDER;\n                commandID = _getNextMenuItemDividerID();\n            } else {\n                commandID = command;\n                command = CommandManager.get(commandID);\n                if (!command) {\n                    throw new Error(\"addMenuItem(): commandID not found: \" + commandID);\n                }\n                name = command.getName();\n            }\n        } else {\n            commandID = command.getID();\n        }\n\n        // Internal id is the a composite of the parent menu id and the command id.\n        id = this._getMenuItemId(commandID);\n        \n        if (menuItemMap[id]) {\n            console.log(\"MenuItem added with same id of existing MenuItem: \" + id);\n            return null;\n        }\n\n        // create MenuItem\n        menuItem = new MenuItem(id, command);\n        menuItemMap[id] = menuItem;\n\n        // create MenuItem DOM\n        if (name === DIVIDER) {\n            $menuItem = $(\"<li><hr class='divider' /></li>\");\n        } else {\n            // Create the HTML Menu\n            $menuItem = $(\"<li><a href='#' id='\" + id + \"'> <span class='menu-name'></span></a></li>\");\n\n            $menuItem.on(\"click\", function () {\n                menuItem._command.execute();\n            });\n        }\n\n        // Insert menu item\n        var $relativeElement = this._getRelativeMenuItem(relativeID, position);\n        _insertInList($(\"li#\" + StringUtils.jQueryIdEscape(this.id) + \" > ul.dropdown-menu\"),\n                      $menuItem, position, $relativeElement);\n\n        // Initialize MenuItem state\n        if (!menuItem.isDivider) {\n            if (keyBindings) {\n                // Add key bindings. The MenuItem listens to the Command object to update MenuItem DOM with shortcuts.\n                if (!Array.isArray(keyBindings)) {\n                    keyBindings = [keyBindings];\n                }\n                \n                // Note that keyBindings passed during MenuItem creation take precedent over any existing key bindings\n                KeyBindingManager.addBinding(commandID, keyBindings);\n            } else {\n                // Look for existing key bindings\n                _addExistingKeyBinding(menuItem, commandID);\n            }\n\n            menuItem._checkedChanged();\n            menuItem._enabledChanged();\n            menuItem._nameChanged();\n        }\n\n        return menuItem;\n    };\n\n    /**\n     * Inserts divider item in menu.\n     * @param {?string} position - constant defining the position of new the divider relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants). \n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new \n     *      divider will be positioned relative to. Required for all position constants\n     *      except FIRST and LAST\n     * \n     * @return {MenuItem} the newly created divider\n     */\n    Menu.prototype.addMenuDivider = function (position, relativeID) {\n        return this.addMenuItem(DIVIDER, \"\", position, relativeID);\n    };\n\n    /**\n     * NOT IMPLEMENTED\n     * Alternative JSON based API to addMenuItem()\n     * \n     * All properties are required unless noted as optional.\n     *\n     * @param { Array.<{\n     *              id:         string,\n     *              command:    string | Command,\n     *              ?bindings:   string | Array.<{key: string, platform: string}>,\n     *          }>} jsonStr\n     *        }\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants). \n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new \n     *      menuItem will be positioned relative to. Required when position is \n     *      AFTER or BEFORE, ignored when position is FIRST or LAST.\n     *\n     * @return {MenuItem} the newly created MenuItem\n     */\n    // Menu.prototype.createMenuItemsFromJSON = function (jsonStr, position, relativeID) {\n    //     NOT IMPLEMENTED\n    // };\n\n\n    /**\n     * NOT IMPLEMENTED\n     * @param {!string} text displayed in menu item\n     * @param {!string} id\n     * @param {?string} position - constant defining the position of new the MenuItem relative\n     *      to other MenuItems. Default is LAST.  (see Insertion position constants) \n     * @param {?string} relativeID - id of menuItem, sub-menu, or menu section that the new \n     *      menuItem will be positioned relative to. Required when position is \n     *      AFTER or BEFORE, ignored when position is FIRST or LAST.\n     * \n     * @return {MenuItem} newly created menuItem for sub-menu\n     */\n    // MenuItem.prototype.createSubMenu = function (text, id, position, relativeID) {\n    //     NOT IMPLEMENTED\n    // };\n\n    /**\n     * Gets the Command associated with a MenuItem\n     * @return {Command}\n     */\n    MenuItem.prototype.getCommand = function () {\n        return this._command;\n    };\n\n    /**\n     * NOT IMPLEMENTED\n     * Returns the parent MenuItem if the menu item is a sub-menu, returns null otherwise.\n     * @return {MenuItem}\n     */\n    // MenuItem.prototype.getParentMenuItem = function () {\n    //     NOT IMPLEMENTED;\n    // };\n\n    /**\n     * Returns the parent Menu for this MenuItem\n     * @return {Menu} \n     */\n    MenuItem.prototype.getParentMenu = function () {\n        var parent = $(_getHTMLMenuItem(this.id)).parents(\".dropdown\").get(0);\n        if (!parent) {\n            return null;\n        }\n\n        return getMenu(parent.id);\n    };\n    \n    /**\n     * Synchronizes MenuItem checked state with underlying Command checked state\n     */\n    MenuItem.prototype._checkedChanged = function () {\n        var checked = this._command.getChecked();\n        // Note, checked can also be undefined, so we explicitly check\n        // for truthiness and don't use toggleClass().\n        if (checked) {\n            $(_getHTMLMenuItem(this.id)).addClass(\"checked\");\n        } else {\n            $(_getHTMLMenuItem(this.id)).removeClass(\"checked\");\n        }\n    };\n\n    /**\n     * Synchronizes MenuItem enabled state with underlying Command enabled state\n     */\n    MenuItem.prototype._enabledChanged = function () {\n        $(_getHTMLMenuItem(this.id)).toggleClass(\"disabled\", !this._command.getEnabled());\n    };\n\n    /**\n     * Synchronizes MenuItem name with underlying Command name\n     */\n    MenuItem.prototype._nameChanged = function () {\n        $(_getHTMLMenuItem(this.id)).find(\".menu-name\").text(this._command.getName());\n    };\n    \n    /**\n     * @private\n     * Updates MenuItem DOM with a keyboard shortcut label\n     */\n    MenuItem.prototype._keyBindingAdded = function (event, keyBinding) {\n        _addKeyBindingToMenuItem($(_getHTMLMenuItem(this.id)), keyBinding.key, keyBinding.displayKey);\n    };\n    \n    /**\n     * @private\n     * Updates MenuItem DOM to remove keyboard shortcut label\n     */\n    MenuItem.prototype._keyBindingRemoved = function (event, keyBinding) {\n        var $shortcut = $(_getHTMLMenuItem(this.id)).find(\".menu-shortcut\");\n        \n        if ($shortcut.length > 0 && $shortcut.data(\"key\") === keyBinding.key) {\n            // check for any other bindings\n            if (_addExistingKeyBinding(this) === null) {\n                $shortcut.empty();\n            }\n        }\n    };\n\n    /**\n     * Closes all menus that are open\n     */\n    function closeAll() {\n        $(\".dropdown\").removeClass(\"open\");\n    }\n    \n    /**\n     * Adds a top-level menu to the application menu bar which may be native or HTML-based.\n     *\n     * @param {!string} name - display text for menu \n     * @param {!string} id - unique identifier for a menu.\n     *      Core Menus in Brackets use a simple  title as an id, for example \"file-menu\".\n     *      Extensions should use the following format: \"author.myextension.mymenuname\". \n     * @param {?string} position - constant defining the position of new the Menu relative\n     *  to other Menus. Default is LAST (see Insertion position constants).\n     *      \n     * @param {?string} relativeID - id of Menu the new Menu will be positioned relative to. Required\n     *      when position is AFTER or BEFORE, ignored when position is FIRST or LAST\n     * \n     * @return {?Menu} the newly created Menu\n     */\n    function addMenu(name, id, position, relativeID) {\n        name = StringUtils.htmlEscape(name);\n        var $menubar = $(\"#main-toolbar .nav\"),\n            menu;\n\n        if (!name || !id) {\n            throw new Error(\"call to addMenu() is missing required parameters\");\n        }\n        \n        // Guard against duplicate menu ids\n        if (menuMap[id]) {\n            console.log(\"Menu added with same name and id of existing Menu: \" + id);\n            return null;\n        }\n\n        menu = new Menu(id);\n        menuMap[id] = menu;\n\n        var $toggle = $(\"<a href='#' class='dropdown-toggle'>\" + name + \"</a>\"),\n            $popUp = $(\"<ul class='dropdown-menu'></ul>\"),\n            $newMenu = $(\"<li class='dropdown' id='\" + id + \"'></li>\").append($toggle).append($popUp);\n\n        // Insert menu\n        var $relativeElement = relativeID && $(_getHTMLMenu(relativeID));\n        _insertInList($menubar, $newMenu, position, $relativeElement);\n        \n        // Install ESC key handling\n        PopUpManager.addPopUp($popUp, closeAll, false);\n\n        // todo error handling\n\n        return menu;\n    }\n\n\n    /**\n     * @constructor\n     * @extends {Menu}\n     *\n     * Represents a context menu that can open at a specific location in the UI. \n     *\n     * Clients should not create this object directly and should instead use registerContextMenu()\n     * to create new ContextMenu objects.\n     *\n     * Context menus in brackets may be HTML-based or native so clients should not reach into\n     * the HTML and should instead manipulate ContextMenus through the API.\n     *\n     * Events:\n     *      beforeContextMenuOpen\n     *      contextMenuClose\n     *\n     */\n    function ContextMenu(id) {\n        this.id = id;\n        this.menu = new Menu(id);\n\n        var $newMenu = $(\"<li class='dropdown context-menu' id='\" + StringUtils.jQueryIdEscape(id) + \"'></li>\"),\n            $popUp = $(\"<ul class='dropdown-menu'></ul>\"),\n            $toggle = $(\"<a href='#' class='dropdown-toggle'></a>\").hide();\n\n        // assemble the menu fragments\n        $newMenu.append($toggle).append($popUp);\n\n        // insert into DOM\n        $(\"#context-menu-bar > ul\").append($newMenu);\n        \n        var self = this;\n        PopUpManager.addPopUp($popUp,\n            function () {\n                self.close();\n            },\n            false);\n    }\n    ContextMenu.prototype = new Menu();\n    ContextMenu.prototype.constructor = ContextMenu;\n    ContextMenu.prototype.parentClass = Menu.prototype;\n\n\n    /**\n     * Displays the ContextMenu at the specified location and dispatches the \n     * \"beforeContextMenuOpen\" event.The menu location may be adjusted to prevent\n     * clipping by the browser window. All other menus and ContextMenus will be closed\n     * bofore a new menu is shown.\n     *\n     * @param {MouseEvent | {pageX:number, pageY:number}} mouseOrLocation - pass a MouseEvent\n     *      to display the menu near the mouse or pass in an object with page x/y coordinates\n     *      for a specific location.\n     */\n    ContextMenu.prototype.open = function (mouseOrLocation) {\n\n        if (!mouseOrLocation || !mouseOrLocation.hasOwnProperty(\"pageX\") || !mouseOrLocation.hasOwnProperty(\"pageY\")) {\n            throw new Error(\"ContextMenu open(): missing required parameter\");\n        }\n\n        var $window = $(window),\n            escapedId = StringUtils.jQueryIdEscape(this.id),\n            $menuAnchor = $(\"#\" + escapedId),\n            $menuWindow = $(\"#\" + escapedId + \" > ul\"),\n            posTop  = mouseOrLocation.pageY,\n            posLeft = mouseOrLocation.pageX;\n\n        // only show context menu if it has menu items\n        if ($menuWindow.children().length <= 0) {\n            return;\n        }\n\n        $(this).triggerHandler(\"beforeContextMenuOpen\");\n\n        // close all other dropdowns\n        closeAll();\n\n        // adjust positioning so menu is not clipped off bottom or right\n        var bottomOverhang = posTop + 25 + $menuWindow.height() - $window.height();\n        if (bottomOverhang > 0) {\n            posTop = Math.max(0, posTop - bottomOverhang);\n        }\n        posTop -= 30;   // shift top for hidden parent element\n        posLeft += 5;\n\n        var rightOverhang = posLeft + $menuWindow.width() - $window.width();\n        if (rightOverhang > 0) {\n            posLeft = Math.max(0, posLeft - rightOverhang);\n        }\n\n        // open the context menu at final location\n        $menuAnchor.addClass(\"open\")\n                   .css({\"left\": posLeft, \"top\": posTop});\n    };\n\n    /**\n     * Closes the context menu and dispatches the \"contextMenuClose\" event.\n     */\n    ContextMenu.prototype.close = function () {\n        $(\"#\" + StringUtils.jQueryIdEscape(this.id)).removeClass(\"open\");\n\n        $(this).triggerHandler(\"contextMenuClose\");\n    };\n\n    /**\n     * Registers new context menu with Brackets. \n\n     * Extensions should generally use the predefined context menus built into Brackets. Use this \n     * API to add a new context menu to UI that is specific to an extension.\n     *\n     * After registering  a new context menu clients should:\n     *      - use addMenuItem() to add items to the context menu\n     *      - call open() to show the context menu. \n     *      For example:\n     *      $(\"#my_ID\").contextmenu(function (e) {\n     *          if (e.which === 3) {\n     *              my_cmenu.open(e);\n     *          }\n     *      });\n     *\n     * To make menu items be contextual to things like selection, listen for the \"beforeContextMenuOpen\"\n     * to make changes to Command objects before the context menu is shown. MenuItems are views of\n     * Commands, which control a MenuItem's name, enabled state, and checked state.\n     *\n     * @param {string} id - unique identifier for context menu.\n     *      Core context menus in Brackets use a simple title as an id.\n     *      Extensions should use the following format: \"author.myextension.mycontextmenu name\"\n     * @return {?ContextMenu} the newly created context menu\n     */\n    function registerContextMenu(id) {\n        if (!id) {\n            throw new Error(\"call to registerContextMenu() is missing required parameters\");\n        }\n        \n        // Guard against duplicate menu ids\n        if (contextMenuMap[id]) {\n            console.log(\"Context Menu added with same name and id of existing Context Menu: \" + id);\n            return null;\n        }\n\n        var cmenu = new ContextMenu(id);\n        contextMenuMap[id] = cmenu;\n        return cmenu;\n    }\n\n    /** NOT IMPLEMENTED\n     * Removes Menu\n     */\n    // function removeMenu(id) {\n    //     NOT IMPLEMENTED\n    // }\n\n\n    function init() {\n\n        /*\n         * File menu\n         */\n        var menu;\n        menu = addMenu(Strings.FILE_MENU, AppMenuBar.FILE_MENU);\n        menu.addMenuItem(Commands.FILE_NEW,                 \"Ctrl-N\");\n        menu.addMenuItem(Commands.FILE_OPEN,                \"Ctrl-O\");\n        menu.addMenuItem(Commands.FILE_OPEN_FOLDER);\n        menu.addMenuItem(Commands.FILE_CLOSE,               \"Ctrl-W\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_SAVE,                \"Ctrl-S\");\n        menu.addMenuItem(Commands.FILE_SAVE_ALL,            \"Ctrl-Alt-S\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW,   \"Ctrl-Alt-P\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.FILE_QUIT,                \"Ctrl-Q\");\n\n        /*\n         * Edit  menu\n         */\n        menu = addMenu(Strings.EDIT_MENU, AppMenuBar.EDIT_MENU);\n        menu.addMenuItem(Commands.EDIT_SELECT_ALL,          \"Ctrl-A\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_FIND,                \"Ctrl-F\");\n        menu.addMenuItem(Commands.EDIT_FIND_IN_FILES,       \"Ctrl-Shift-F\");\n        menu.addMenuItem(Commands.EDIT_FIND_NEXT,           [{key: \"F3\",     platform: \"win\"},\n                                                             {key: \"Cmd-G\", platform: \"mac\"}]);\n\n        menu.addMenuItem(Commands.EDIT_FIND_PREVIOUS,       [{key: \"Shift-F3\",      platform: \"win\"},\n                                                             {key:  \"Cmd-Shift-G\", platform: \"mac\"}]);\n\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_REPLACE,             [{key: \"Ctrl-H\",     platform: \"win\"},\n                                                             {key: \"Cmd-Alt-F\", platform: \"mac\"}]);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_INDENT,          [{key: \"Indent\", displayKey: \"Tab\"}]);\n        menu.addMenuItem(Commands.EDIT_UNINDENT,        [{key: \"Unindent\", displayKey: \"Shift-Tab\"}]);\n        menu.addMenuItem(Commands.EDIT_DUPLICATE,       \"Ctrl-D\");\n        menu.addMenuItem(Commands.EDIT_LINE_UP,         [{key: \"Ctrl-Shift-Up\", displayKey: \"Ctrl-Shift-\\u2191\",\n                                                          platform: \"win\"},\n                                                         {key:  \"Cmd-Ctrl-Up\", displayKey: \"Cmd-Ctrl-\\u2191\",\n                                                          platform: \"mac\"}]);\n        menu.addMenuItem(Commands.EDIT_LINE_DOWN,       [{key: \"Ctrl-Shift-Down\", displayKey: \"Ctrl-Shift-\\u2193\",\n                                                          platform: \"win\"},\n                                                         {key:  \"Cmd-Ctrl-Down\", displayKey: \"Cmd-Ctrl-\\u2193\",\n                                                          platform: \"mac\"}]);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.EDIT_LINE_COMMENT,    \"Ctrl-/\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_USE_TAB_CHARS);\n\n        /*\n         * View menu\n         */\n        menu = addMenu(Strings.VIEW_MENU, AppMenuBar.VIEW_MENU);\n        menu.addMenuItem(Commands.VIEW_HIDE_SIDEBAR,        \"Ctrl-Shift-H\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.VIEW_INCREASE_FONT_SIZE, [{key: \"Ctrl-=\", displayKey: \"Ctrl-+\"}]);\n        menu.addMenuItem(Commands.VIEW_DECREASE_FONT_SIZE, [{key: \"Ctrl--\", displayKey: \"Ctrl-\\u2212\"}]);\n        menu.addMenuItem(Commands.VIEW_RESTORE_FONT_SIZE, \"Ctrl-0\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_JSLINT);\n\n        /*\n         * Navigate menu\n         */\n        menu = addMenu(Strings.NAVIGATE_MENU, AppMenuBar.NAVIGATE_MENU);\n        menu.addMenuItem(Commands.NAVIGATE_QUICK_OPEN,      \"Ctrl-Shift-O\");\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_LINE,       [{key: \"Ctrl-G\", platform: \"win\"},\n                                                             {key: \"Cmd-L\", platform: \"mac\"}]);\n\n        menu.addMenuItem(Commands.NAVIGATE_GOTO_DEFINITION, \"Ctrl-T\");\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.TOGGLE_QUICK_EDIT,        \"Ctrl-E\");\n        menu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH,    {key: \"Alt-Up\", displayKey: \"Alt-\\u2191\"});\n        menu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH,    {key: \"Alt-Down\", displayKey: \"Alt-\\u2193\"});\n\n        /*\n         * Debug menu\n         */\n        menu = addMenu(Strings.DEBUG_MENU, AppMenuBar.DEBUG_MENU);\n        menu.addMenuItem(Commands.DEBUG_SHOW_DEVELOPER_TOOLS, [{key: \"F12\",        platform: \"win\"},\n                                                               {key: \"Cmd-Opt-I\", platform: \"mac\"}]);\n        menu.addMenuItem(Commands.DEBUG_REFRESH_WINDOW, [{key: \"F5\",     platform: \"win\"},\n                                                         {key: \"Cmd-R\", platform:  \"mac\"}]);\n        menu.addMenuItem(Commands.DEBUG_NEW_BRACKETS_WINDOW);\n        menu.addMenuItem(Commands.DEBUG_SHOW_EXT_FOLDER);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.DEBUG_SWITCH_LANGUAGE);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.DEBUG_RUN_UNIT_TESTS);\n        menu.addMenuItem(Commands.DEBUG_SHOW_PERF_DATA);\n        menu.addMenuDivider();\n        menu.addMenuItem(Commands.CHECK_FOR_UPDATE);\n\n\n        /*\n         * Context Menus\n         */\n        var project_cmenu = registerContextMenu(ContextMenuIds.PROJECT_MENU);\n        project_cmenu.addMenuItem(Commands.FILE_NEW);\n\n        var editor_cmenu = registerContextMenu(ContextMenuIds.EDITOR_MENU);\n        editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);\n\n        var inline_editor_cmenu = registerContextMenu(ContextMenuIds.INLINE_EDITOR_MENU);\n        inline_editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);\n        inline_editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);\n        inline_editor_cmenu.addMenuDivider();\n        inline_editor_cmenu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH);\n        inline_editor_cmenu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH);\n        \n        /**\n         * Context menu for code editors (both full-size and inline)\n         * Auto selects the word the user clicks if the click does not occur over\n         * an existing selection\n         */\n        $(\"#editor-holder\").on(\"contextmenu\", function (e) {\n            if ($(e.target).parents(\".CodeMirror-gutter\").length !== 0) {\n                return;\n            }\n            \n            // Note: on mousedown before this event, CodeMirror automatically checks mouse pos, and\n            // if not clicking on a selection moves the cursor to click location. When triggered\n            // from keyboard, no pre-processing occurs and the cursor/selection is left as is.\n            \n            var editor = EditorManager.getFocusedEditor(),\n                inlineWidget = EditorManager.getFocusedInlineWidget();\n            \n            if (editor) {\n                // If there's just an insertion point select the word token at the cursor pos so\n                // it's more clear what the context menu applies to.\n                if (!editor.hasSelection()) {\n                    editor.selectWordAt(editor.getCursorPos());\n                    \n                    // Prevent menu from overlapping text by moving it down a little\n                    // Temporarily backout this change for now to help mitigate issue #1111,\n                    // which only happens if mouse is not over context menu. Better fix\n                    // requires change to bootstrap, which is too risky for now.\n                    //e.pageY += 6;\n                }\n                \n                if (inlineWidget) {\n                    inline_editor_cmenu.open(e);\n                } else {\n                    editor_cmenu.open(e);\n                }\n            }\n        });\n\n        /**\n         * Context menu for folder tree & working set list\n         *\n         * TODO (#1069): change selection on right mousedown if not on something already selected\n         */\n        $(\"#projects\").on(\"contextmenu\", function (e) {\n            project_cmenu.open(e);\n        });\n\n        // Prevent the browser context menu since Brackets creates a custom context menu\n        $(window).contextmenu(function (e) {\n            e.preventDefault();\n        });\n        \n        /*\n         * General menu event processing\n         */\n        // Prevent clicks on top level menus and menu items from taking focus\n        $(window.document).on(\"mousedown\", \".dropdown\", function (e) {\n            e.preventDefault();\n        });\n\n        // Switch menus when the mouse enters an adjacent menu\n        // Only open the menu if another one has already been opened\n        // by clicking\n        $(window.document).on(\"mouseenter\", \"#main-toolbar .dropdown\", function (e) {\n            var open = $(this).siblings(\".open\");\n            if (open.length > 0) {\n                open.removeClass(\"open\");\n                $(this).addClass(\"open\");\n            }\n        });\n    }\n\n    // Define public API\n    exports.init = init;\n    exports.AppMenuBar = AppMenuBar;\n    exports.ContextMenuIds = ContextMenuIds;\n    exports.MenuSection = MenuSection;\n    exports.BEFORE = BEFORE;\n    exports.AFTER = AFTER;\n    exports.LAST = LAST;\n    exports.FIRST = FIRST;\n    exports.FIRST_IN_SECTION = FIRST_IN_SECTION;\n    exports.LAST_IN_SECTION = LAST_IN_SECTION;\n    exports.DIVIDER = DIVIDER;\n    exports.getMenu = getMenu;\n    exports.getMenuItem = getMenuItem;\n    exports.getContextMenu = getContextMenu;\n    exports.addMenu = addMenu;\n    exports.registerContextMenu = registerContextMenu;\n    exports.closeAll = closeAll;\n    exports.Menu = Menu;\n    exports.MenuItem = MenuItem;\n    exports.ContextMenu = ContextMenu;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * Responsible for coordinating file selection between views by permitting only one view\n * to show the current file selection at a time. Currently, only WorkingSetView and \n * ProjectManager can show file selection. In general the WorkingSetView takes higher\n * priority until the user selects a file in the ProjectManager.\n *\n * Events dispatched:\n * - documentSelectionFocusChange - indicates a document change has caused the focus to \n *   change between the working set and file tree.\n *\n * - fileViewFocusChange - indicates the selection focus has changed between the working\n *   set and the project tree, but the document selection has NOT changed\n *\n * Current file selection rules in views:\n * - select a file in WorkingSetView > select in WorkingSetView\n * - add a file to the WorkingSetView > select in WorkingSetView\n * - select a file in ProjectManager > select in ProjectManager\n * - open a file from places other than the WorkingSetView or ProjectManager > \n *       select file in WorkignSetView if its in the working set, otherwise select in ProjectManager\n */\n\ndefine('project/FileViewController',['require','exports','module','document/DocumentManager','command/CommandManager','editor/EditorManager','utils/PerfUtils','command/Commands'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var DocumentManager     = require(\"document/DocumentManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Commands            = require(\"command/Commands\");\n\n    /** \n     * Tracks whether a \"currentDocumentChange\" notification occured due to a call to \n     * openAndSelectDocument.\n     * @see FileviewController.openAndSelectDocument\n     * @private \n     */\n    var _curDocChangedDueToMe = false;\n    var WORKING_SET_VIEW = \"WorkingSetView\";\n    var PROJECT_MANAGER = \"ProjectManager\";\n\n    /**\n     * @private\n     * @see FileViewController.getFileSelectionFocus()\n     */\n    var _fileSelectionFocus = PROJECT_MANAGER;\n    \n    /** \n     * Change the doc selection to the working set when ever a new file is added to the working set\n     */\n    $(DocumentManager).on(\"workingSetAdd\", function (event, addedFile) {\n        _fileSelectionFocus = WORKING_SET_VIEW;\n        $(exports).triggerHandler(\"documentSelectionFocusChange\");\n    });\n\n    /** \n      * Update the file selection focus when ever the current document changes\n      */\n    $(DocumentManager).on(\"currentDocumentChange\", function (event) {\n        var perfTimerName;\n        // The the cause of the doc change was not openAndSelectDocument, so pick the best fileSelectionFocus\n        if (!_curDocChangedDueToMe) {\n            var curDoc = DocumentManager.getCurrentDocument();\n            perfTimerName = PerfUtils.markStart(\"FileViewController._onCurrentDocumentChange():\\t\" + (!curDoc || curDoc.file.fullPath));\n            if (curDoc && DocumentManager.findInWorkingSet(curDoc.file.fullPath) !== -1) {\n                _fileSelectionFocus = WORKING_SET_VIEW;\n            } else {\n                _fileSelectionFocus = PROJECT_MANAGER;\n            }\n        }\n\n        $(exports).triggerHandler(\"documentSelectionFocusChange\");\n\n        if (!_curDocChangedDueToMe) {\n            PerfUtils.addMeasurement(perfTimerName);\n        }\n    });\n    \n    /** \n     * @private\n     * @returns {$.Promise}\n     */\n    function _selectCurrentDocument() {\n        // If fullPath corresonds to the current doc being viewed then opening the file won't\n        // trigger a currentDocumentChanged event, so we need to trigger a documentSelectionFocusChange \n        // in this case to signify the selection focus has changed even though the current document has not.\n        $(exports).triggerHandler(\"documentSelectionFocusChange\");\n        \n        // Ensure the editor has focus even though we didn't open a new file.\n        EditorManager.focusEditor();\n    }\n\n    /**\n     * Modifies the selection focus in the project side bar. A file can either be selected\n     * in the working set (the open files) or in the file tree, but not both.\n     * @param {String} fileSelectionFocus - either PROJECT_MANAGER or WORKING_SET_VIEW\n     */\n    function setFileViewFocus(fileSelectionFocus) {\n        if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {\n            throw new Error(\"Bad parameter passed to FileViewController.setFileViewFocus\");\n        }\n\n        _fileSelectionFocus = fileSelectionFocus;\n        $(exports).triggerHandler(\"fileViewFocusChange\");\n    }\n\n    /** \n     * Opens a document if it's not open and selects the file in the UI corresponding to\n     * fileSelectionFocus\n     * @param {!fullPath}\n     * @param {string} - must be either WORKING_SET_VIEW or PROJECT_MANAGER\n     * @returns {$.Promise}\n     */\n    function openAndSelectDocument(fullPath, fileSelectionFocus) {\n        var result;\n\n        if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {\n            throw new Error(\"Bad parameter passed to FileViewController.openAndSelectDocument\");\n        }\n\n        // Opening files are asynchronous and we want to know when this function caused a file\n        // to open so that _fileSelectionFocus is set appropriatly. _curDocChangedDueToMe is set here\n        // and checked in the currentDocumentChange handler\n        _curDocChangedDueToMe = true;\n\n        _fileSelectionFocus = fileSelectionFocus;\n\n        // If fullPath corresonds to the current doc being viewed then opening the file won't\n        // trigger a currentDocumentChanged event, so we need to trigger a documentSelectionFocusChange \n        // in this case to signify the selection focus has changed even though the current document has not.\n        var curDoc = DocumentManager.getCurrentDocument();\n        if (curDoc && curDoc.file.fullPath === fullPath) {\n            _selectCurrentDocument();\n            result = (new $.Deferred()).resolve().promise();\n        } else {\n            result = CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath});\n        }\n        \n        // clear after notification is done\n        result.always(function () {\n            _curDocChangedDueToMe = false;\n        });\n        \n        return result;\n    }\n\n    /** \n     * Opens the specified document if it's not already open, adds it to the working set,\n     * and selects it in the WorkingSetView\n     * @param {!fullPath}\n     * @param {?String} selectIn - specify either WORING_SET_VIEW or PROJECT_MANAGER.\n     *      Default is WORING_SET_VIEW.\n     * @return {!$.Promise}\n     */\n    function addToWorkingSetAndSelect(fullPath, selectIn) {\n        var result = new $.Deferred(),\n            promise = CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath});\n\n        // This properly handles sending the right nofications in cases where the document\n        // is already the current one. In that case we will want to notify with\n        // documentSelectionFocusChange so the views change their selection\n        promise.done(function (doc) {\n            // FILE_ADD_TO_WORKING_SET command sets the current document. Update the \n            // selection focus and trigger documentSelectionFocusChange event\n            _fileSelectionFocus = selectIn || WORKING_SET_VIEW;\n            _selectCurrentDocument();\n            \n            result.resolve(doc);\n        }).fail(function (err) {\n            result.reject(err);\n        });\n\n        return result.promise();\n    }\n\n    /**\n     * returns either WORKING_SET_VIEW or PROJECT_MANAGER\n     * @return {!String}\n     */\n    function getFileSelectionFocus() {\n        return _fileSelectionFocus;\n    }\n\n\n\n    // Define public API\n    exports.getFileSelectionFocus = getFileSelectionFocus;\n    exports.openAndSelectDocument = openAndSelectDocument;\n    exports.addToWorkingSetAndSelect = addToWorkingSetAndSelect;\n    exports.setFileViewFocus = setFileViewFocus;\n    exports.WORKING_SET_VIEW = WORKING_SET_VIEW;\n    exports.PROJECT_MANAGER = PROJECT_MANAGER;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, FileError, window */\n\n/**\n * ProjectManager is the model for the set of currently open project. It is responsible for\n * creating and updating the project tree when projects are opened and when changes occur to\n * the file tree.\n *\n * This module dispatches these events:\n *    - beforeProjectClose -- before _projectRoot changes\n *    - projectOpen        -- after  _projectRoot changes\n *\n * These are jQuery events, so to listen for them you do something like this:\n *    $(ProjectManager).on(\"eventname\", handler);\n */\ndefine('project/ProjectManager',['require','exports','module','thirdparty/jstree_pre1.0_fix_1/jquery.jstree','file/NativeFileSystem','preferences/PreferencesManager','document/DocumentManager','command/CommandManager','command/Commands','widgets/Dialogs','command/Menus','utils/StringUtils','strings','project/FileViewController','utils/PerfUtils','utils/ViewUtils','file/FileUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent non-module scripts\n    require(\"thirdparty/jstree_pre1.0_fix_1/jquery.jstree\");\n\n    // Load dependent modules\n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Menus               = require(\"command/Menus\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Strings             = require(\"strings\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        ViewUtils           = require(\"utils/ViewUtils\"),\n        FileUtils           = require(\"file/FileUtils\");\n    \n    /**\n     * @private\n     * Reference to the tree control container div. Initialized by\n     * htmlContentLoadComplete handler\n     * @type {jQueryObject}\n     */\n    var $projectTreeContainer;\n    \n    /**\n     * @private\n     * Reference to the tree control\n     * @type {jQueryObject}\n     */\n    var _projectTree = null;\n    \n    /**\n     * @private\n     * Reference to previous selected jstree leaf node when ProjectManager had\n     * selection focus from FileViewController.\n     * @type {DOMElement}\n     */\n    var _lastSelected = null;\n    \n    /**\n     * @private\n     * Internal flag to suppress firing of selectionChanged event.\n     * @type {boolean}\n     */\n    var _suppressSelectionChange = false;\n    \n    /**\n     * @private\n     * Reference to the tree control UL element\n     * @type {DOMElement}\n     */\n    var $projectTreeList;\n    \n    /**\n     * @private\n     * @see getProjectRoot()\n     */\n    var _projectRoot = null;\n\n    /**\n     * Unique PreferencesManager clientID\n     */\n    var PREFERENCES_CLIENT_ID = \"com.adobe.brackets.ProjectManager\";\n    \n    /**\n     * @private\n     * @type {PreferenceStorage}\n     */\n    var _prefs = null;\n\n    /**\n     * @private\n     * Used to initialize jstree state\n     */\n    var _projectInitialLoad = {\n        previous        : [],   /* array of arrays containing full paths to open at each depth of the tree */\n        id              : 0,    /* incrementing id */\n        fullPathToIdMap : {}    /* mapping of fullPath to tree node id attr */\n    };\n    \n    /**\n     * @private\n     */\n    function _hasFileSelectionFocus() {\n        return FileViewController.getFileSelectionFocus() === FileViewController.PROJECT_MANAGER;\n    }\n    \n    /**\n     * @private\n     */\n    function _redraw(selectionChanged, reveal) {\n        reveal = (reveal === undefined) ? true : reveal;\n        \n        // redraw selection\n        if ($projectTreeList) {\n            if (selectionChanged && !_suppressSelectionChange) {\n                $projectTreeList.triggerHandler(\"selectionChanged\", reveal);\n            }\n\n            // reposition the selection triangle\n            $projectTreeContainer.triggerHandler(\"scroll\");\n            \n            // in-lieu of resize events, manually trigger contentChanged for every\n            // FileViewController focus change. This event triggers scroll shadows\n            // on the jstree to update. documentSelectionFocusChange fires when\n            // a new file is added and removed (causing a new selection) from the working set\n            _projectTree.triggerHandler(\"contentChanged\");\n        }\n    }\n    \n    /**\n     * Returns the FileEntry or DirectoryEntry corresponding to the selected item, or null\n     * if no item is selected.\n     *\n     * @return {?Entry}\n     */\n    function getSelectedItem() {\n        var selected = _projectTree.jstree(\"get_selected\");\n        if (selected) {\n            return selected.data(\"entry\");\n        }\n        return null;\n    }\n\n    function _fileViewFocusChange() {\n        _redraw(true);\n    }\n    \n    function _documentSelectionFocusChange() {\n        var curDoc = DocumentManager.getCurrentDocument();\n        if (curDoc && _hasFileSelectionFocus()) {\n            $(\"#project-files-container li\").is(function (index) {\n                var entry = $(this).data(\"entry\");\n                if (entry && entry.fullPath === curDoc.file.fullPath && !_projectTree.jstree(\"is_selected\", $(this))) {\n                    //we don't want to trigger another selection change event, so manually deselect\n                    //and select without sending out notifications\n                    _projectTree.jstree(\"deselect_all\");\n                    _projectTree.jstree(\"select_node\", $(this), false);\n                    return true;\n                }\n                return false;\n            });\n        } else if (_projectTree !== null) {\n            _projectTree.jstree(\"deselect_all\");\n            _lastSelected = null;\n        }\n        \n        _redraw(true);\n    }\n\n    /**\n     * Returns the root folder of the currently loaded project, or null if no project is open (during\n     * startup, or running outside of app shell).\n     * @return {DirectoryEntry}\n     */\n    function getProjectRoot() {\n        return _projectRoot;\n    }\n    \n    /**\n     * Returns true if absPath lies within the project, false otherwise.\n     * Does not support paths containing \"..\"\n     */\n    function isWithinProject(absPath) {\n        return (_projectRoot && absPath.indexOf(_projectRoot.fullPath) === 0);\n    }\n    /**\n     * If absPath lies within the project, returns a project-relative path. Else returns absPath\n     * unmodified.\n     * Does not support paths containing \"..\"\n     */\n    function makeProjectRelativeIfPossible(absPath) {\n        if (isWithinProject(absPath)) {\n            return absPath.slice(_projectRoot.fullPath.length);\n        }\n        return absPath;\n    }\n\n    /**\n     * Initial project path is stored in prefs, which defaults to brackets/src\n     */\n    function getInitialProjectPath() {\n        return _prefs.getValue(\"projectPath\");\n    }\n\n    /**\n     * @private\n     * Get prefs tree state lookup key for given project path.\n     */\n    function _getTreeStateKey(path) {\n        // generate unique tree state key for this project path\n        var key = \"projectTreeState_\" + path;\n\n        // normalize to always have slash at end\n        if (key[key.length - 1] !== \"/\") {\n            key += \"/\";\n        }\n        return key;\n    }\n\n    /**\n     * @private\n     * Save ProjectManager project path and tree state.\n     */\n    function _savePreferences() {\n        \n        // save the current project\n        _prefs.setValue(\"projectPath\", _projectRoot.fullPath);\n\n        // save jstree state\n        var openNodes = [],\n            projectPathLength = _projectRoot.fullPath.length,\n            entry,\n            fullPath,\n            shortPath,\n            depth;\n\n        // Query open nodes by class selector\n        $(\".jstree-open:visible\").each(function (index) {\n            entry = $(this).data(\"entry\");\n\n            if (entry.fullPath) {\n                fullPath = entry.fullPath;\n\n                // Truncate project path prefix, remove the trailing slash\n                shortPath = fullPath.slice(projectPathLength, -1);\n\n                // Determine depth of the node by counting path separators.\n                // Children at the root have depth of zero\n                depth = shortPath.split(\"/\").length - 1;\n\n                // Map tree depth to list of open nodes\n                if (openNodes[depth] === undefined) {\n                    openNodes[depth] = [];\n                }\n\n                openNodes[depth].push(fullPath);\n            }\n        });\n\n        // Store the open nodes by their full path and persist to storage\n        _prefs.setValue(_getTreeStateKey(_projectRoot.fullPath), openNodes);\n    }\n    \n    /**\n     * @private\n     */\n    function _forceSelection(current, target) {\n        // select_node will force the target to be revealed. Instead,\n        // keep the scroller position stable.\n        var savedScrollTop = $projectTreeContainer.get(0).scrollTop;\n        \n        // suppress selectionChanged event from firing by jstree select_node\n        _suppressSelectionChange = true;\n        _projectTree.jstree(\"deselect_node\", current);\n        _projectTree.jstree(\"select_node\", target, false);\n        _suppressSelectionChange = false;\n        \n        $projectTreeContainer.get(0).scrollTop = savedScrollTop;\n        \n        _redraw(true, false);\n    }\n\n    /**\n     * @private\n     * Given an input to jsTree's json_data.data setting, display the data in the file tree UI\n     * (replacing any existing file tree that was previously displayed). This input could be\n     * raw JSON data, or it could be a dataprovider function. See jsTree docs for details:\n     * http://www.jstree.com/documentation/json_data\n     */\n    function _renderTree(treeDataProvider) {\n        var result = new $.Deferred(),\n            suppressToggleOpen = false;\n\n        // Instantiate tree widget\n        // (jsTree is smart enough to replace the old tree if there's already one there)\n        $projectTreeContainer.hide();\n        _projectTree = $projectTreeContainer\n            .jstree(\n                {\n                    plugins : [\"ui\", \"themes\", \"json_data\", \"crrm\", \"sort\"],\n                    json_data : { data: treeDataProvider, correct_state: false },\n                    core : { animation: 0 },\n                    themes : { theme: \"brackets\", url: \"styles/jsTreeTheme.css\", dots: false, icons: false },\n                        //(note: our actual jsTree theme CSS lives in brackets.less; we specify an empty .css\n                        // file because jsTree insists on loading one itself)\n                    strings : { loading : \"Loading ...\", new_node : \"New node\" },\n                    sort :  function (a, b) {\n                        if (brackets.platform === \"win\") {\n                            // Windows: prepend folder names with a '0' and file names with a '1' so folders are listed first\n                            var a1 = ($(a).hasClass(\"jstree-leaf\") ? \"1\" : \"0\") + this.get_text(a).toLowerCase(),\n                                b1 = ($(b).hasClass(\"jstree-leaf\") ? \"1\" : \"0\") + this.get_text(b).toLowerCase();\n                            return (a1 > b1) ? 1 : -1;\n                        } else {\n                            return this.get_text(a).toLowerCase() > this.get_text(b).toLowerCase() ? 1 : -1;\n                        }\n                    }\n                }\n            )\n            .bind(\n                \"before.jstree\",\n                function (event, data) {\n                    if (data.func === \"toggle_node\") {\n                        // jstree will automaticaly select parent node when the parent is closed\n                        // and any descendant is selected. Prevent the select_node handler from\n                        // immediately toggling open again in this case.\n                        suppressToggleOpen = _projectTree.jstree(\"is_open\", data.args[0]);\n                    }\n                }\n            )\n            .bind(\n                \"select_node.jstree\",\n                function (event, data) {\n                    var entry = data.rslt.obj.data(\"entry\");\n                    if (entry.isFile) {\n                        var openResult = FileViewController.openAndSelectDocument(entry.fullPath, FileViewController.PROJECT_MANAGER);\n                    \n                        openResult.done(function () {\n                            // update when tree display state changes\n                            _redraw(true);\n                            _lastSelected = data.rslt.obj;\n                        }).fail(function () {\n                            if (_lastSelected) {\n                                // revert this new selection and restore previous selection\n                                _forceSelection(data.rslt.obj, _lastSelected);\n                            } else {\n                                _projectTree.jstree(\"deselect_all\");\n                                _lastSelected = null;\n                            }\n                        });\n                    } else {\n                        FileViewController.setFileViewFocus(FileViewController.PROJECT_MANAGER);\n                        // show selection marker on folders\n                        _redraw(true);\n                        \n                        // toggle folder open/closed\n                        // suppress if this selection was triggered by clicking the disclousre triangle\n                        if (!suppressToggleOpen) {\n                            _projectTree.jstree(\"toggle_node\", data.rslt.obj);\n                        }\n                    }\n                    \n                    suppressToggleOpen = false;\n                }\n            )\n            .bind(\n                \"reopen.jstree\",\n                function (event, data) {\n                    // This handler fires for the initial load and subsequent\n                    // reload_nodes events. For each depth level of the tree, we open\n                    // the saved nodes by a fullPath lookup.\n                    if (_projectInitialLoad.previous.length > 0) {\n                        // load previously open nodes by increasing depth\n                        var toOpenPaths = _projectInitialLoad.previous.shift(),\n                            toOpenIds   = [],\n                            node        = null;\n        \n                        // use path to lookup ID\n                        $.each(toOpenPaths, function (index, value) {\n                            node = _projectInitialLoad.fullPathToIdMap[value];\n                            \n                            if (node) {\n                                toOpenIds.push(node);\n                            }\n                        });\n        \n                        // specify nodes to open and load\n                        data.inst.data.core.to_open = toOpenIds;\n                        _projectTree.jstree(\"reload_nodes\", false);\n                    }\n                    if (_projectInitialLoad.previous.length === 0) {\n                        // resolve after all paths are opened\n                        result.resolve();\n                    }\n                }\n            )\n            .bind(\n                \"scroll.jstree\",\n                function (e) {\n                    // close all dropdowns on scroll\n                    Menus.closeAll();\n                }\n            )\n            .bind(\n                \"loaded.jstree open_node.jstree close_node.jstree\",\n                function (event, data) {\n                    if (event.type === \"open_node\") {\n                        // select the current document if it becomes visible when this folder is opened\n                        var curDoc = DocumentManager.getCurrentDocument();\n                        \n                        if (_hasFileSelectionFocus() && curDoc) {\n                            var entry = data.rslt.obj.data(\"entry\");\n                            \n                            if (curDoc.file.fullPath.indexOf(entry.fullPath) === 0) {\n                                _forceSelection(data.rslt.obj, _lastSelected);\n                            } else {\n                                _redraw(true, false);\n                            }\n                        }\n                    } else if (event.type === \"close_node\") {\n                        // always update selection marker position when collapsing a node\n                        _redraw(true, false);\n                    } else {\n                        _redraw(false);\n                    }\n                    \n                    _savePreferences();\n                }\n            )\n            .bind(\n                \"mousedown.jstree\",\n                function (event) {\n                    // select tree node on right-click\n                    if (event.which === 3) {\n                        var treenode = $(event.target).closest(\"li\");\n                        if (treenode) {\n                            var saveSuppressToggleOpen = suppressToggleOpen;\n                            \n                            // don't toggle open folders (just select)\n                            suppressToggleOpen = true;\n                            _projectTree.jstree(\"deselect_all\");\n                            _projectTree.jstree(\"select_node\", treenode, false);\n                            suppressToggleOpen = saveSuppressToggleOpen;\n                        }\n                    }\n                }\n            );\n\n        // jstree has a default event handler for dblclick that attempts to clear the\n        // global window selection (presumably because it doesn't want text within the tree\n        // to be selected). This ends up messing up CodeMirror, and we don't need this anyway\n        // since we've turned off user selection of UI text globally. So we just unbind it,\n        // and add our own double-click handler here.\n        // Filed this bug against jstree at https://github.com/vakata/jstree/issues/163\n        _projectTree.bind(\"init.jstree\", function () {\n            // install scroller shadows\n            ViewUtils.addScrollerShadow(_projectTree.get(0));\n            \n            _projectTree\n                .unbind(\"dblclick.jstree\")\n                .bind(\"dblclick.jstree\", function (event) {\n                    var entry = $(event.target).closest(\"li\").data(\"entry\");\n                    if (entry && entry.isFile) {\n                        FileViewController.addToWorkingSetAndSelect(entry.fullPath);\n                    }\n                });\n\n            // fire selection changed events for sidebar-selection\n            $projectTreeList = $projectTreeContainer.find(\"ul\");\n            ViewUtils.sidebarList($projectTreeContainer, \"jstree-clicked\", \"jstree-leaf\");\n            $projectTreeContainer.show();\n        });\n\n        return result.promise();\n    }\n    \n    /** @param {Entry} entry File or directory to filter */\n    function shouldShow(entry) {\n        return [\".git\", \".svn\", \".DS_Store\", \"Thumbs.db\"].indexOf(entry.name) === -1;\n    }\n\n    /**\n     * @private\n     * Given an array of NativeFileSystem entries, returns a JSON array representing them in the format\n     * required by jsTree. Saves the corresponding Entry object as metadata (which jsTree will store in\n     * the DOM via $.data()).\n     *\n     * Does NOT recursively traverse the file system: folders are marked as expandable but are given no\n     * children initially.\n     *\n     * @param {Array.<Entry>} entries  Array of NativeFileSystem entry objects.\n     * @return {Array} jsTree node data: array of JSON objects\n     */\n    function _convertEntriesToJSON(entries) {\n        var jsonEntryList = [],\n            entry,\n            entryI;\n\n        for (entryI = 0; entryI < entries.length; entryI++) {\n            entry = entries[entryI];\n            \n            if (shouldShow(entry)) {\n                var jsonEntry = {\n                    data: entry.name,\n                    attr: { id: \"node\" + _projectInitialLoad.id++ },\n                    metadata: { entry: entry }\n                };\n                if (entry.isDirectory) {\n                    jsonEntry.children = [];\n                    jsonEntry.state = \"closed\";\n                }\n    \n                // For more info on jsTree's JSON format see: http://www.jstree.com/documentation/json_data\n                jsonEntryList.push(jsonEntry);\n    \n                // Map path to ID to initialize loaded and opened states\n                _projectInitialLoad.fullPathToIdMap[entry.fullPath] = jsonEntry.attr.id;\n            }\n        }\n        return jsonEntryList;\n    }\n\n    /**\n     * @private\n     * Called by jsTree when the user has expanded a node that has never been expanded before. We call\n     * jsTree back asynchronously with the node's immediate children data once the subfolder is done\n     * being fetched.\n     *\n     * @param {jQueryObject} treeNode  jQ object for the DOM node being expanded\n     * @param {function(Array)} jsTreeCallback  jsTree callback to provide children to\n     */\n    function _treeDataProvider(treeNode, jsTreeCallback) {\n        var dirEntry, isProjectRoot = false;\n\n        if (treeNode === -1) {\n            // Special case: root of tree\n            dirEntry = _projectRoot;\n            isProjectRoot = true;\n        } else {\n            // All other nodes: the DirectoryEntry is saved as jQ data in the tree (by _convertEntriesToJSON())\n            dirEntry = treeNode.data(\"entry\");\n        }\n\n        // Fetch dirEntry's contents\n        dirEntry.createReader().readEntries(\n            function (entries) {\n                var subtreeJSON = _convertEntriesToJSON(entries),\n                    wasNodeOpen = false,\n                    emptyDirectory = (subtreeJSON.length === 0);\n                \n                if (emptyDirectory) {\n                    if (!isProjectRoot) {\n                        wasNodeOpen = treeNode.hasClass(\"jstree-open\");\n                    } else {\n                        // project root is a special case, add a placeholder\n                        subtreeJSON.push({});\n                    }\n                }\n                \n                jsTreeCallback(subtreeJSON);\n                \n                if (!isProjectRoot && emptyDirectory) {\n                    // If the directory is empty, force it to appear as an open or closed node.\n                    // This is a workaround for issue #149 where jstree would show this node as a leaf.\n                    var classToAdd = (wasNodeOpen) ? \"jstree-closed\" : \"jstree-open\";\n                    \n                    treeNode.removeClass(\"jstree-leaf jstree-closed jstree-open\")\n                            .addClass(classToAdd);\n                }\n            },\n            function (error) {\n                Dialogs.showModalDialog(\n                    Dialogs.DIALOG_ID_ERROR,\n                    Strings.ERROR_LOADING_PROJECT,\n                    StringUtils.format(Strings.READ_DIRECTORY_ENTRIES_ERROR,\n                        StringUtils.htmlEscape(dirEntry.fullPath),\n                        error.code)\n                );\n            }\n        );\n\n    }\n    \n    /** Returns the full path to the default project folder. The path is currently the brackets src folder.\n     * TODO: (issue #267): Brackets does not yet support operating when there is no project folder. This code will likely\n     * not be needed when this support is added.\n     * @private\n     * @return {!string} fullPath reference\n     */\n    function _getDefaultProjectPath() {\n        var loadedPath = decodeURI(window.location.pathname);\n        var bracketsSrc = loadedPath.substr(0, loadedPath.lastIndexOf(\"/\"));\n        \n        bracketsSrc = FileUtils.convertToNativePath(bracketsSrc);\n\n        return bracketsSrc;\n    }\n    \n    /**\n     * Loads the given folder as a project. Normally, you would call openProject() instead to let the\n     * user choose a folder.\n     *\n     * @param {string} rootPath  Absolute path to the root folder of the project. \n     *  If rootPath is undefined or null, the last open project will be restored.\n     * @return {$.Promise} A promise object that will be resolved when the\n     *  project is loaded and tree is rendered, or rejected if the project path\n     *  fails to load.\n     */\n    function _loadProject(rootPath) {\n        if (_projectRoot) {\n            // close current project\n            $(exports).triggerHandler(\"beforeProjectClose\", _projectRoot);\n        }\n\n        // close all the old files\n        DocumentManager.closeAll();\n\n        // reset tree node id's\n        _projectInitialLoad.id = 0;\n\n        var result = new $.Deferred(),\n            resultRenderTree;\n\n        // restore project tree state from last time this project was open\n        _projectInitialLoad.previous = _prefs.getValue(_getTreeStateKey(rootPath)) || [];\n\n        // Populate file tree as long as we aren't running in the browser\n        if (!brackets.inBrowser) {\n            // Point at a real folder structure on local disk\n            NativeFileSystem.requestNativeFileSystem(rootPath,\n                function (rootEntry) {\n                    var projectRootChanged = (!_projectRoot || !rootEntry)\n                        || _projectRoot.fullPath !== rootEntry.fullPath;\n\n                    // Success!\n                    var perfTimerName = PerfUtils.markStart(\"Load Project: \" + rootPath);\n\n                    _projectRoot = rootEntry;\n\n                    // The tree will invoke our \"data provider\" function to populate the top-level items, then\n                    // go idle until a node is expanded - at which time it'll call us again to fetch the node's\n                    // immediate children, and so on.\n                    resultRenderTree = _renderTree(_treeDataProvider);\n\n                    resultRenderTree.done(function () {\n                        if (projectRootChanged) {\n                            $(exports).triggerHandler(\"projectOpen\", _projectRoot);\n                        }\n                        \n                        result.resolve();\n                    });\n                    resultRenderTree.fail(function () {\n                        PerfUtils.terminateMeasurement(perfTimerName);\n                        result.reject();\n                    });\n                    resultRenderTree.always(function () {\n                        PerfUtils.addMeasurement(perfTimerName);\n                    });\n                },\n                function (error) {\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_ERROR,\n                        Strings.ERROR_LOADING_PROJECT,\n                        StringUtils.format(\n                            Strings.REQUEST_NATIVE_FILE_SYSTEM_ERROR,\n                            StringUtils.htmlEscape(rootPath),\n                            error.code,\n                            function () {\n                                result.reject();\n                            }\n                        )\n                    ).done(function () {\n                        // The project folder stored in preference doesn't exist, so load the default \n                        // project directory.\n                        // TODO (issue #267): When Brackets supports having no project directory\n                        // defined this code will need to change\n                        return _loadProject(_getDefaultProjectPath());\n                    });\n                }\n                );\n        }\n\n        return result.promise();\n    }\n\n    /**\n     * Open a new project. Currently, Brackets must always have a project open, so\n     * this method handles both closing the current project and opening a new project.\n     *\n     * @param {string=} path Optional absolute path to the root folder of the project. \n     *  If path is undefined or null, displays a  dialog where the user can choose a\n     *  folder to load. If the user cancels the dialog, nothing more happens.\n     * @return {$.Promise} A promise object that will be resolved when the\n     *  project is loaded and tree is rendered, or rejected if the project path\n     *  fails to load.\n     */\n    function openProject(path) {\n\n        var result = new $.Deferred();\n\n        // Confirm any unsaved changes first. We run the command in \"prompt-only\" mode, meaning it won't\n        // actually close any documents even on success; we'll do that manually after the user also oks\n        //the folder-browse dialog.\n        CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })\n            .done(function () {\n                if (path) {\n                    // use specified path\n                    _loadProject(path).pipe(result.resolve, result.reject);\n                } else {\n                    // Pop up a folder browse dialog\n                    NativeFileSystem.showOpenDialog(false, true, \"Choose a folder\", _projectRoot.fullPath, null,\n                        function (files) {\n                            // If length == 0, user canceled the dialog; length should never be > 1\n                            if (files.length > 0) {\n                                // Load the new project into the folder tree\n                                _loadProject(files[0]).pipe(result.resolve, result.reject);\n                            } else {\n                                result.reject();\n                            }\n                        },\n                        function (error) {\n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_LOADING_PROJECT,\n                                StringUtils.format(Strings.OPEN_DIALOG_ERROR, error.code)\n                            );\n                            result.reject();\n                        }\n                        );\n                }\n            })\n            .fail(function () {\n                result.reject();\n            });\n\n        // if fail, don't open new project: user canceled (or we failed to save its unsaved changes)\n        return result.promise();\n    }\n\n\n    /**\n     * Create a new item in the project tree.\n     *\n     * @param baseDir {string} Full path of the directory where the item should go\n     * @param initialName {string} Initial name for the item\n     * @param skipRename {boolean} If true, don't allow the user to rename the item\n     * @return {$.Promise} A promise object that will be resolved with the FileEntry\n     *  of the created object, or rejected if the user cancelled or entered an illegal\n     *  filename.\n     */\n    function createNewItem(baseDir, initialName, skipRename) {\n        var node                = null,\n            selection           = _projectTree.jstree(\"get_selected\"),\n            selectionEntry      = null,\n            position            = \"inside\",\n            escapeKeyPressed    = false,\n            result              = new $.Deferred(),\n            wasNodeOpen         = true;\n\n        // get the FileEntry or DirectoryEntry\n        if (selection) {\n            selectionEntry = selection.data(\"entry\");\n        }\n\n        // move selection to parent DirectoryEntry\n        if (selectionEntry) {\n            if (selectionEntry.isFile) {\n                position = \"after\";\n                \n                var parent = $.jstree._reference(_projectTree)._get_parent(selection);\n                \n                if (typeof (parent.data) === \"function\") {\n                    // get Entry from tree node\n                    // note that the jstree root will return undefined\n                    selectionEntry = parent.data(\"entry\");\n                } else {\n                    // reset here. will be replaced with project root.\n                    selectionEntry = null;\n                }\n            } else if (selectionEntry.isDirectory) {\n                wasNodeOpen = selection.hasClass(\"jstree-open\");\n            }\n        }\n\n        // use the project root DirectoryEntry\n        if (!selectionEntry) {\n            selectionEntry = getProjectRoot();\n        }\n\n        _projectTree.on(\"create.jstree\", function (event, data) {\n            $(event.target).off(\"create.jstree\");\n\n            function errorCleanup() {\n                // TODO (issue #115): If an error occurred, we should allow the user to fix the filename.\n                // For now we just remove the node so you have to start again.\n                var parent = data.inst._get_parent(data.rslt.obj);\n                \n                _projectTree.jstree(\"remove\", data.rslt.obj);\n                \n                // Restore tree node state and styling when errors occur.\n                // parent returns -1 when at the root\n                if (parent && (parent !== -1)) {\n                    var methodName = (wasNodeOpen) ? \"open_node\" : \"close_node\";\n                    var classToAdd = (wasNodeOpen) ? \"jstree-open\" : \"jstree-closed\";\n                    \n                    // This is a workaround for issue #149 where jstree would show this node as a leaf.\n                    _projectTree.jstree(methodName, parent);\n                    parent.removeClass(\"jstree-leaf jstree-closed jstree-open\")\n                          .addClass(classToAdd);\n                }\n                \n                result.reject();\n            }\n\n            if (!escapeKeyPressed) {\n                // Validate file name\n                // TODO (issue #270): There are some filenames like COM1, LPT3, etc. that are not valid on Windows.\n                // We may want to add checks for those here.\n                // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx\n                if (data.rslt.name.search(/[\\/?*:;\\{\\}<>\\\\|]+/) !== -1) {\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_ERROR,\n                        Strings.INVALID_FILENAME_TITLE,\n                        Strings.INVALID_FILENAME_MESSAGE\n                    );\n\n                    errorCleanup();\n                    return;\n                }\n\n                // Use getFile() to create the new file\n                selectionEntry.getFile(\n                    data.rslt.name,\n                    {create: true, exclusive: true},\n                    function (entry) {\n                        data.rslt.obj.data(\"entry\", entry);\n                        _projectTree.jstree(\"select_node\", data.rslt.obj, true);\n                        result.resolve(entry);\n                    },\n                    function (error) {\n                        if ((error.code === FileError.PATH_EXISTS_ERR)\n                                || (error.code === FileError.TYPE_MISMATCH_ERR)) {\n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.INVALID_FILENAME_TITLE,\n                                StringUtils.format(Strings.FILE_ALREADY_EXISTS,\n                                    StringUtils.htmlEscape(data.rslt.name))\n                            );\n                        } else {\n                            var errString = error.code === FileError.NO_MODIFICATION_ALLOWED_ERR ?\n                                             Strings.NO_MODIFICATION_ALLOWED_ERR :\n                                             StringUtils.format(String.GENERIC_ERROR, error.code);\n\n                            var errMsg = StringUtils.format(Strings.ERROR_CREATING_FILE,\n                                            StringUtils.htmlEscape(data.rslt.name),\n                                            errString);\n                          \n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_CREATING_FILE_TITLE,\n                                errMsg\n                            );\n                        }\n\n                        errorCleanup();\n                    }\n                );\n            } else { //escapeKeyPressed\n                errorCleanup();\n            }\n        });\n        \n        // TODO (issue #115): Need API to get tree node for baseDir.\n        // In the meantime, pass null for node so new item is placed\n        // relative to the selection\n        node = selection;\n        \n        // Open the node before creating the new child\n        _projectTree.jstree(\"open_node\", node);\n\n        // Create the node and open the editor\n        _projectTree.jstree(\"create\", node, position, {data: initialName}, null, skipRename);\n\n        if (!skipRename) {\n            var $renameInput = _projectTree.find(\".jstree-rename-input\");\n\n            $renameInput.on(\"keydown\", function (event) {\n                // Listen for escape key on keydown, so we can remove the node in the create.jstree handler above\n                if (event.keyCode === 27) {\n                    escapeKeyPressed = true;\n                }\n            });\n\n            ViewUtils.scrollElementIntoView(_projectTree, $renameInput, true);\n        }\n        \n        return result.promise();\n    }\n\n    /**\n     * Forces createNewItem() to complete by removing focus from the rename field which causes\n     * the new file to be written to disk\n     */\n    function forceFinishRename() {\n        $(\".jstree-rename-input\").blur();\n    }\n\n\n    // Initialize variables and listeners that depend on the HTML DOM\n    $(brackets).on(\"htmlContentLoadComplete\", function () {\n        $projectTreeContainer = $(\"#project-files-container\");\n\n        $(\"#open-files-container\").on(\"contentChanged\", function () {\n            _redraw(false); // redraw jstree when working set size changes\n        });\n    });\n\n    // Init PreferenceStorage\n    var defaults = {\n        projectPath:      _getDefaultProjectPath()  /* initialize to brackets source */\n    };\n    _prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaults);\n\n    // Event Handlers\n    $(FileViewController).on(\"documentSelectionFocusChange\", _documentSelectionFocusChange);\n    $(FileViewController).on(\"fileViewFocusChange\", _fileViewFocusChange);\n\n    // Commands\n    CommandManager.register(Strings.CMD_OPEN_FOLDER,    Commands.FILE_OPEN_FOLDER,  openProject);\n\n    // Define public API\n    exports.getProjectRoot          = getProjectRoot;\n    exports.isWithinProject         = isWithinProject;\n    exports.makeProjectRelativeIfPossible = makeProjectRelativeIfPossible;\n    exports.shouldShow              = shouldShow;\n    exports.openProject             = openProject;\n    exports.getSelectedItem         = getSelectedItem;\n    exports.getInitialProjectPath   = getInitialProjectPath;\n    exports.createNewItem           = createNewItem;\n    exports.forceFinishRename       = forceFinishRename;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * DocumentManager maintains a list of currently 'open' Documents. It also owns the list of files in\n * the working set, and the notion of which Document is currently shown in the main editor UI area.\n * \n * Document is the model for a file's contents; it dispatches events whenever those contents change.\n * To transiently inspect a file's content, simply get a Document and call getText() on it. However,\n * to be notified of Document changes or to modify a Document, you MUST call addRef() to ensure the\n * Document instance 'stays alive' and is shared by all other who read/modify that file. ('Open'\n * Documents are all Documents that are 'kept alive', i.e. have ref count > 0).\n *\n * To get a Document, call getDocumentForPath(); never new up a Document yourself.\n * \n * Secretly, a Document may use an Editor instance to act as the model for its internal state. (This\n * is unavoidable because CodeMirror does not separate its model from its UI). Documents are not\n * modifiable until they have a backing 'master Editor'. Creation of the backing Editor is owned by\n * EditorManager. A Document only gets a backing Editor if it becomes the currentDocument, or if edits\n * occur in any Editor (inline or full-sized) bound to the Document; there is currently no other way\n * to ensure a Document is modifiable.\n *\n * A non-modifiable Document may still dispatch change notifications, if the Document was changed\n * externally on disk.\n *\n * Aside from the text content, Document tracks a few pieces of metadata - notably, whether there are\n * any unsaved changes.\n *\n * This module dispatches several events:\n *    - dirtyFlagChange -- When any Document's isDirty flag changes. The 2nd arg to the listener is the\n *      Document whose flag changed.\n *    - documentSaved -- When a Document's changes have been saved. The 2nd arg to the listener is the \n *      Document that has been saved.\n *    - currentDocumentChange -- When the value of getCurrentDocument() changes.\n *    - workingSetAdd -- When a file is added to the working set (see getWorkingSet()). The 2nd arg\n *      to the listener is the added FileEntry.\n *    - workingSetAddList -- When a list of files are added to the working set (e.g. project open, multiple file open).\n *      The 2nd arg to the listener is the array of added FileEntry objects.\n *    - workingSetRemove -- When a file is removed from the working set (see getWorkingSet()). The\n *      2nd arg to the listener is the removed FileEntry.\n *    - workingSetRemoveList -- When a list of files is to be removed from the working set (e.g. project close).\n *      The 2nd arg to the listener is the array of removed FileEntry objects.\n *\n * These are jQuery events, so to listen for them you do something like this:\n *    $(DocumentManager).on(\"eventname\", handler);\n */\ndefine('document/DocumentManager',['require','exports','module','file/NativeFileSystem','project/ProjectManager','editor/EditorManager','preferences/PreferencesManager','file/FileUtils','command/CommandManager','utils/Async','utils/PerfUtils','command/Commands'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        ProjectManager      = require(\"project/ProjectManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Async               = require(\"utils/Async\"),\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        Commands            = require(\"command/Commands\");\n    \n    /**\n     * Unique PreferencesManager clientID\n     */\n    var PREFERENCES_CLIENT_ID = \"com.adobe.brackets.DocumentManager\";\n    \n    /**\n     * @private\n     * @see DocumentManager.getCurrentDocument()\n     */\n    var _currentDocument = null;\n    \n    /**\n     * @private\n     * @type {PreferenceStorage}\n     */\n    var _prefs = {};\n    \n    /**\n     * Returns the Document that is currently open in the editor UI. May be null.\n     * When this changes, DocumentManager dispatches a \"currentDocumentChange\" event. The current\n     * document always has a backing Editor (Document._masterEditor != null) and is thus modifiable.\n     * @return {?Document}\n     */\n    function getCurrentDocument() {\n        return _currentDocument;\n    }\n    \n    /**\n     * @private\n     * @type {Array.<FileEntry>}\n     * @see DocumentManager.getWorkingSet()\n     */\n    var _workingSet = [];\n    \n    /**\n     * @private\n     * Contains the same set of items as _workinSet, but ordered by how recently they were _currentDocument (0 = most recent).\n     * @type {Array.<FileEntry>}\n     */\n    var _workingSetMRUOrder = [];\n    \n    /**\n     * While true, the MRU order is frozen\n     * @type {boolean}\n     */\n    var _documentNavPending = false;\n    \n    /**\n     * While true, allow preferences to be saved\n     * @type {boolean}\n     */\n    var _isProjectChanging = false;\n    \n    /**\n     * All documents with refCount > 0. Maps Document.file.fullPath -> Document.\n     * @private\n     * @type {Object.<string, Document>}\n     */\n    var _openDocuments = {};\n    \n    /**\n     * Returns a list of items in the working set in UI list order. May be 0-length, but never null.\n     *\n     * When a file is added this list, DocumentManager dispatches a \"workingSetAdd\" event.\n     * When a file is removed from list, DocumentManager dispatches a \"workingSetRemove\" event.\n     * To listen for ALL changes to this list, you must listen for both events.\n     *\n     * Which items belong in the working set is managed entirely by DocumentManager. Callers cannot\n     * (yet) change this collection on their own.\n     *\n     * @return {Array.<FileEntry>}\n     */\n    function getWorkingSet() {\n        return _workingSet;\n        // TODO: (issue #297) return a clone to prevent meddling?\n    }\n\n    /** \n     * Returns the index of the file matching fullPath in the working set.\n     * Returns -1 if not found.\n     * @param {!string} fullPath\n     * @param {Array.<FileEntry>=} list Pass this arg to search a different array of files. Internal\n     *          use only.\n     * @returns {number} index\n     */\n    function findInWorkingSet(fullPath, list) {\n        list = list || _workingSet;\n        \n        var ret = -1;\n        var found = list.some(function findByPath(file, i) {\n                ret = i;\n                return file.fullPath === fullPath;\n            });\n            \n        return (found ? ret : -1);\n    }\n\n    /**\n     * Returns all Documents that are 'open' in the UI somewhere (for now, this means open in an\n     * inline editor and/or a full-size editor). Only these Documents can be modified, and only\n     * these Documents are synced with external changes on disk.\n     * @return {Array.<Document>}\n     */\n    function getAllOpenDocuments() {\n        var result = [];\n        var path;\n        for (path in _openDocuments) {\n            if (_openDocuments.hasOwnProperty(path)) {\n                result.push(_openDocuments[path]);\n            }\n        }\n        return result;\n    }\n    \n    \n    /**\n     * Adds the given file to the end of the working set list, if it is not already in the list.\n     * Does not change which document is currently open in the editor. Completes synchronously.\n     * @param {!FileEntry} file\n     */\n    function addToWorkingSet(file) {\n        // If doc is already in working set, don't add it again\n        if (findInWorkingSet(file.fullPath) !== -1) {\n            return;\n        }\n        \n        // Add\n        _workingSet.push(file);\n        \n        // Add to MRU order: either first or last, depending on whether it's already the current doc or not\n        if (_currentDocument && _currentDocument.file.fullPath === file.fullPath) {\n            _workingSetMRUOrder.unshift(file);\n        } else {\n            _workingSetMRUOrder.push(file);\n        }\n        \n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetAdd\", file);\n    }\n\n    /**\n     * Adds the given file list to the end of the working set list.\n     * Does not change which document is currently open in the editor.\n     * More efficient than calling addToWorkingSet() (in a loop) for\n     * a list of files because there's only 1 redraw at the end\n     * @param {!FileEntryArray} fileList\n     */\n    function addListToWorkingSet(fileList) {\n        var uniqueFileList = [];\n\n        // Process only files not already in working set\n        fileList.forEach(function (file) {\n            // If doc is already in working set, don't add it again\n            if (findInWorkingSet(file.fullPath) === -1) {\n                uniqueFileList.push(file);\n\n                // Add\n                _workingSet.push(file);\n\n                // Add to MRU order: either first or last, depending on whether it's already the current doc or not\n                if (_currentDocument && _currentDocument.file.fullPath === file.fullPath) {\n                    _workingSetMRUOrder.unshift(file);\n                } else {\n                    _workingSetMRUOrder.push(file);\n                }\n            }\n        });\n\n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetAddList\", [uniqueFileList]);\n    }\n\n    /**\n     * Removes the given file from the working set list, if it was in the list. Does not change\n     * the current editor even if it's for this file.\n     * @param {!FileEntry} file\n     */\n    function removeFromWorkingSet(file) {\n        // If doc isn't in working set, do nothing\n        var index = findInWorkingSet(file.fullPath);\n        if (index === -1) {\n            return;\n        }\n        \n        // Remove\n        _workingSet.splice(index, 1);\n        _workingSetMRUOrder.splice(findInWorkingSet(file.fullPath, _workingSetMRUOrder), 1);\n        \n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetRemove\", file);\n    }\n\n    /**\n     * Removes all files from the working set list.\n     */\n    function _removeAllFromWorkingSet() {\n        var fileList = _workingSet;\n\n        // Remove all\n        _workingSet = [];\n        _workingSetMRUOrder = [];\n\n        // Dispatch event\n        $(exports).triggerHandler(\"workingSetRemoveList\", [fileList]);\n    }\n\n    /**\n     * Moves document to the front of the MRU list, IF it's in the working set; no-op otherwise.\n     * @param {!Document}\n     */\n    function _markMostRecent(doc) {\n        var mruI = findInWorkingSet(doc.file.fullPath, _workingSetMRUOrder);\n        if (mruI !== -1) {\n            _workingSetMRUOrder.splice(mruI, 1);\n            _workingSetMRUOrder.unshift(doc.file);\n        }\n    }\n    \n    \n    /**\n     * Indicate that changes to currentDocument are temporary for now, and should not update the MRU\n     * ordering of the working set. Useful for next/previous keyboard navigation (until Ctrl is released)\n     * or for incremental-search style document preview like Quick Open will eventually have.\n     * Can be called any number of times, and ended by a single finalizeDocumentNavigation() call.\n     */\n    function beginDocumentNavigation() {\n        _documentNavPending = true;\n    }\n    \n    /**\n     * Un-freezes the MRU list after one or more beginDocumentNavigation() calls. Whatever document is\n     * current is bumped to the front of the MRU list.\n     */\n    function finalizeDocumentNavigation() {\n        if (_documentNavPending) {\n            _documentNavPending = false;\n            \n            _markMostRecent(_currentDocument);\n        }\n    }\n    \n    \n    /**\n     * Changes currentDocument to the given Document, firing currentDocumentChange, which in turn\n     * causes this Document's main editor UI to be shown in the editor pane, updates the selection\n     * in the file tree / working set UI, etc. This call may also add the item to the working set.\n     * \n     * @param {!Document} document  The Document to make current. May or may not already be in the\n     *      working set.\n     */\n    function setCurrentDocument(doc) {\n        \n        // If this doc is already current, do nothing\n        if (_currentDocument === doc) {\n            return;\n        }\n\n        var perfTimerName = PerfUtils.markStart(\"setCurrentDocument:\\t\" + doc.file.fullPath);\n        \n        // If file not within project tree, add it to working set right now (don't wait for it to\n        // become dirty)\n        if (!ProjectManager.isWithinProject(doc.file.fullPath)) {\n            addToWorkingSet(doc.file);\n        }\n        \n        // Adjust MRU working set ordering (except while in the middle of a Ctrl+Tab sequence)\n        if (!_documentNavPending) {\n            _markMostRecent(doc);\n        }\n        \n        // Make it the current document\n        _currentDocument = doc;\n        $(exports).triggerHandler(\"currentDocumentChange\");\n        // (this event triggers EditorManager to actually switch editors in the UI)\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n    \n    /** Changes currentDocument to null, causing no full Editor to be shown in the UI */\n    function _clearCurrentDocument() {\n        // If editor already blank, do nothing\n        if (!_currentDocument) {\n            return;\n        }\n        \n        // Change model & dispatch event\n        _currentDocument = null;\n        $(exports).triggerHandler(\"currentDocumentChange\");\n        // (this event triggers EditorManager to actually clear the editor UI)\n    }\n    \n    /**\n     * Closes the full editor for the given file (if there is one), and removes it from the working\n     * set. Any other editors for this Document remain open. Discards any unsaved changes - it is\n     * expected that the UI has already confirmed with the user before calling this.\n     *\n     * Changes currentDocument if this file was the current document (may change to null).\n     *\n     * This is a subset of notifyFileDeleted(). Use this for the user-facing Close command.\n     *\n     * @param {!FileEntry} file\n     */\n    function closeFullEditor(file) {\n        // If this was the current document shown in the editor UI, we're going to switch to a\n        // different document (or none if working set has no other options)\n        if (_currentDocument && _currentDocument.file.fullPath === file.fullPath) {\n            var wsIndex = findInWorkingSet(file.fullPath);\n            \n            // Decide which doc to show in editor after this one\n            var nextFile;\n            if (wsIndex === -1) {\n                // If doc wasn't in working set, use bottommost working set item\n                if (_workingSet.length > 0) {\n                    nextFile = _workingSet[_workingSet.length  - 1];\n                }\n                // else: leave nextDocument null; editor area will be blank\n            } else {\n                // If doc was in working set, use item next to it (below if possible)\n                if (wsIndex < _workingSet.length - 1) {\n                    nextFile = _workingSet[wsIndex + 1];\n                } else if (wsIndex > 0) {\n                    nextFile = _workingSet[wsIndex - 1];\n                }\n                // else: leave nextDocument null; editor area will be blank\n            }\n            \n            // Switch editor to next document (or blank it out)\n            if (nextFile) {\n                CommandManager.execute(Commands.FILE_OPEN, { fullPath: nextFile.fullPath });\n            } else {\n                _clearCurrentDocument();\n            }\n        }\n        \n        // (Now we're guaranteed that the current document is not the one we're closing)\n        console.assert(!(_currentDocument && _currentDocument.file.fullPath === file.fullPath));\n        \n        // Remove closed doc from working set, if it was in there\n        // This happens regardless of whether the document being closed was the current one or not\n        removeFromWorkingSet(file);\n        \n        // Note: EditorManager will dispose the closed document's now-unneeded editor either in\n        // response to the editor-swap call above, or the removeFromWorkingSet() call, depending on\n        // circumstances. See notes in EditorManager for more.\n    }\n\n    /**\n     * Equivalent to calling closeFullEditor() for all Documents. Same caveat: this discards any\n     * unsaved changes, so the UI should confirm with the user before calling this.\n     */\n    function closeAll() {\n        _clearCurrentDocument();\n        _removeAllFromWorkingSet();\n    }\n    \n    \n    /**\n     * Cleans up any loose Documents whose only ref is its own master Editor, and that Editor is not\n     * rooted in the UI anywhere. This can happen if the Editor is auto-created via Document APIs that\n     * trigger _ensureMasterEditor() without making it dirty. E.g. a command invoked on the focused\n     * inline editor makes no-op edits or does a read-only operation.\n     */\n    function _gcDocuments() {\n        getAllOpenDocuments().forEach(function (doc) {\n            // Is the only ref to this document its own master Editor?\n            if (doc._refCount === 1 && doc._masterEditor) {\n                // Destroy the Editor if it's not being kept alive by the UI\n                EditorManager._destroyEditorIfUnneeded(doc);\n            }\n        });\n    }\n    \n    \n    /**\n     * @constructor\n     * Model for the contents of a single file and its current modification state.\n     * See DocumentManager documentation for important usage notes.\n     *\n     * Document dispatches these events:\n     *\n     * change -- When the text of the editor changes (including due to undo/redo). \n     *\n     *        Passes ({Document}, {ChangeList}), where ChangeList is a linked list (NOT an array)\n     *        of change record objects. Each change record looks like:\n     *\n     *            { from: start of change, expressed as {line: <line number>, ch: <character offset>},\n     *              to: end of change, expressed as {line: <line number>, ch: <chracter offset>},\n     *              text: array of lines of text to replace existing text,\n     *              next: next change record in the linked list, or undefined if this is the last record }\n     *      \n     *        The line and ch offsets are both 0-based.\n     *\n     *        The ch offset in \"from\" is inclusive, but the ch offset in \"to\" is exclusive. For example,\n     *        an insertion of new content (without replacing existing content) is expressed by a range\n     *        where from and to are the same.\n     *\n     *        If \"from\" and \"to\" are undefined, then this is a replacement of the entire text content.\n     *\n     *        IMPORTANT: If you listen for the \"change\" event, you MUST also addRef() the document \n     *        (and releaseRef() it whenever you stop listening). You should also listen to the \"deleted\"\n     *        event.\n     *  \n     *        (FUTURE: this is a modified version of the raw CodeMirror change event format; may want to make \n     *        it an ordinary array)\n     *\n     * deleted -- When the file for this document has been deleted. All views onto the document should\n     *      be closed. The document will no longer be editable or dispatch \"change\" events.\n     *\n     * @param {!FileEntry} file  Need not lie within the project.\n     * @param {!Date} initialTimestamp  File's timestamp when we read it off disk.\n     * @param {!string} rawText  Text content of the file.\n     */\n    function Document(file, initialTimestamp, rawText) {\n        if (!(this instanceof Document)) {  // error if constructor called without 'new'\n            throw new Error(\"Document constructor must be called with 'new'\");\n        }\n        if (_openDocuments[file.fullPath]) {\n            throw new Error(\"Creating a document when one already exists, for: \" + file);\n        }\n        \n        this.file = file;\n        this.refreshText(rawText, initialTimestamp);\n        \n        // This is a good point to clean up any old dangling Documents\n        _gcDocuments();\n    }\n    \n    /**\n     * Number of clients who want this Document to stay alive. The Document is listed in\n     * DocumentManager._openDocuments whenever refCount > 0.\n     */\n    Document.prototype._refCount = 0;\n    \n    /**\n     * The FileEntry for this document. Need not lie within the project.\n     * @type {!FileEntry}\n     */\n    Document.prototype.file = null;\n    \n    /**\n     * Whether this document has unsaved changes or not.\n     * When this changes on any Document, DocumentManager dispatches a \"dirtyFlagChange\" event.\n     * @type {boolean}\n     */\n    Document.prototype.isDirty = false;\n    \n    /**\n     * What we expect the file's timestamp to be on disk. If the timestamp differs from this, then\n     * it means the file was modified by an app other than Brackets.\n     * @type {!Date}\n     */\n    Document.prototype.diskTimestamp = null;\n    \n    /**\n     * The text contents of the file, or null if our backing model is _masterEditor.\n     * @type {?string}\n     */\n    Document.prototype._text = null;\n    \n    /**\n     * Editor object representing the full-size editor UI for this document. May be null if Document\n     * has not yet been modified or been the currentDocument; in that case, our backing model is the\n     * string _text.\n     * @type {?Editor}\n     */\n    Document.prototype._masterEditor = null;\n    \n    /**\n     * The content's line-endings style. If a Document is created on empty text, or text with\n     * inconsistent line endings, defaults to the current platform's standard endings.\n     * @type {FileUtils.LINE_ENDINGS_CRLF|FileUtils.LINE_ENDINGS_LF}\n     */\n    Document.prototype._lineEndings = null;\n\n    /** Add a ref to keep this Document alive */\n    Document.prototype.addRef = function () {\n        //console.log(\"+++REF+++ \"+this);\n        \n        if (this._refCount === 0) {\n            //console.log(\"+++ adding to open list\");\n            if (_openDocuments[this.file.fullPath]) {\n                throw new Error(\"Document for this path already in _openDocuments!\");\n            }\n\n            _openDocuments[this.file.fullPath] = this;\n            $(exports).triggerHandler(\"afterDocumentCreate\", this);\n        }\n        this._refCount++;\n    };\n    /** Remove a ref that was keeping this Document alive */\n    Document.prototype.releaseRef = function () {\n        //console.log(\"---REF--- \"+this);\n\n        this._refCount--;\n        if (this._refCount < 0) {\n            throw new Error(\"Document ref count has fallen below zero!\");\n        }\n        if (this._refCount === 0) {\n            //console.log(\"--- removing from open list\");\n            if (!_openDocuments[this.file.fullPath]) {\n                throw new Error(\"Document with references was not in _openDocuments!\");\n            }\n\n            $(exports).triggerHandler(\"beforeDocumentDelete\", this);\n            delete _openDocuments[this.file.fullPath];\n        }\n    };\n    \n    /**\n     * Attach a backing Editor to the Document, enabling setText() to be called. Assumes Editor has\n     * already been initialized with the value of getText(). ONLY Editor should call this (and only\n     * when EditorManager has told it to act as the master editor).\n     * @param {!Editor} masterEditor\n     */\n    Document.prototype._makeEditable = function (masterEditor) {\n        if (this._masterEditor) {\n            throw new Error(\"Document is already editable\");\n        } else {\n            this._text = null;\n            this._masterEditor = masterEditor;\n            $(masterEditor).on(\"change\", this._handleEditorChange.bind(this));\n        }\n    };\n    \n    /**\n     * Detach the backing Editor from the Document, disallowing setText(). The text content is\n     * stored back onto _text so other Document clients continue to have read-only access. ONLY\n     * Editor.destroy() should call this.\n     */\n    Document.prototype._makeNonEditable = function () {\n        if (!this._masterEditor) {\n            throw new Error(\"Document is already non-editable\");\n        } else {\n            // _text represents the raw text, so fetch without normalized line endings\n            this._text = this.getText(true);\n            this._masterEditor = null;\n        }\n    };\n    \n    /**\n     * Guarantees that _masterEditor is non-null. If needed, asks EditorManager to create a new master\n     * editor bound to this Document (which in turn causes Document._makeEditable() to be called).\n     * Should ONLY be called by Editor and Document.\n     */\n    Document.prototype._ensureMasterEditor = function () {\n        if (!this._masterEditor) {\n            EditorManager._createFullEditorForDocument(this);\n        }\n    };\n    \n    /**\n     * Returns the document's current contents; may not be saved to disk yet. Whenever this\n     * value changes, the Document dispatches a \"change\" event.\n     *\n     * @param {boolean=} useOriginalLineEndings If true, line endings in the result depend on the\n     *      Document's line endings setting (based on OS & the original text loaded from disk).\n     *      If false, line endings are always \\n (like all the other Document text getter methods).\n     * @return {string}\n     */\n    Document.prototype.getText = function (useOriginalLineEndings) {\n        if (this._masterEditor) {\n            // CodeMirror.getValue() always returns text with LF line endings; fix up to match line\n            // endings preferred by the document, if necessary\n            var codeMirrorText = this._masterEditor._codeMirror.getValue();\n            if (useOriginalLineEndings) {\n                if (this._lineEndings === FileUtils.LINE_ENDINGS_CRLF) {\n                    return codeMirrorText.replace(/\\n/g, \"\\r\\n\");\n                }\n            }\n            return codeMirrorText;\n            \n        } else {\n            // Optimized path that doesn't require creating master editor\n            if (useOriginalLineEndings) {\n                return this._text;\n            } else {\n                return this._text.replace(/\\r\\n/g, \"\\n\");\n            }\n        }\n    };\n    \n    /**\n     * Sets the contents of the document. Treated as an edit. Line endings will be rewritten to\n     * match the document's current line-ending style.\n     * @param {!string} text The text to replace the contents of the document with.\n     */\n    Document.prototype.setText = function (text) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.setValue(text);\n        // _handleEditorChange() triggers \"change\" event\n    };\n    \n    /**\n     * Sets the contents of the document. Treated as reloading the document from disk: the document\n     * will be marked clean with a new timestamp, the undo/redo history is cleared, and we re-check\n     * the text's line-ending style. CAN be called even if there is no backing editor.\n     * @param {!string} text The text to replace the contents of the document with.\n     * @param {!Date} newTimestamp Timestamp of file at the time we read its new contents from disk.\n     */\n    Document.prototype.refreshText = function (text, newTimestamp) {\n        var perfTimerName = PerfUtils.markStart(\"refreshText:\\t\" + (!this.file || this.file.fullPath));\n\n        if (this._masterEditor) {\n            this._masterEditor._resetText(text);\n            // _handleEditorChange() triggers \"change\" event for us\n        } else {\n            this._text = text;\n            // We fake a change record here that looks like CodeMirror's text change records, but\n            // omits \"from\" and \"to\", by which we mean the entire text has changed.\n            // TODO: Dumb to split it here just to join it again in the change handler, but this is\n            // the CodeMirror change format. Should we document our change format to allow this to\n            // either be an array of lines or a single string?\n            $(this).triggerHandler(\"change\", [this, {text: text.split(/\\r?\\n/)}]);\n        }\n        this._markClean();\n        this.diskTimestamp = newTimestamp;\n        \n        // Sniff line-ending style\n        this._lineEndings = FileUtils.sniffLineEndings(text);\n        if (!this._lineEndings) {\n            this._lineEndings = FileUtils.getPlatformLineEndings();\n        }\n\n        PerfUtils.addMeasurement(perfTimerName);\n    };\n    \n    /**\n     * Adds, replaces, or removes text. If a range is given, the text at that range is replaced with the\n     * given new text; if text == \"\", then the entire range is effectively deleted. If 'end' is omitted,\n     * then the new text is inserted at that point and all existing text is preserved. Line endings will\n     * be rewritten to match the document's current line-ending style.\n     * @param {!string} text  Text to insert or replace the range with\n     * @param {!{line:number, ch:number}} start  Start of range, inclusive (if 'to' specified) or insertion point (if not)\n     * @param {?{line:number, ch:number}} end  End of range, exclusive; optional\n     */\n    Document.prototype.replaceRange = function (text, start, end) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.replaceRange(text, start, end);\n        // _handleEditorChange() triggers \"change\" event\n    };\n    \n    /**\n     * Returns the characters in the given range. Line endings are normalized to '\\n'.\n     * @param {!{line:number, ch:number}} start  Start of range, inclusive\n     * @param {!{line:number, ch:number}} end  End of range, exclusive\n     * @return {!string}\n     */\n    Document.prototype.getRange = function (start, end) {\n        this._ensureMasterEditor();\n        return this._masterEditor._codeMirror.getRange(start, end);\n    };\n    \n    /**\n     * Returns the text of the given line (excluding any line ending characters)\n     * @param {number} Zero-based line number\n     * @return {!string}\n     */\n    Document.prototype.getLine = function (lineNum) {\n        this._ensureMasterEditor();\n        return this._masterEditor._codeMirror.getLine(lineNum);\n    };\n    \n    /**\n     * Batches a series of related Document changes. Repeated calls to replaceRange() should be wrapped in a\n     * batch for efficiency. Begins the batch, calls doOperation(), ends the batch, and then returns.\n     * @param {function()} doOperation\n     */\n    Document.prototype.batchOperation = function (doOperation) {\n        this._ensureMasterEditor();\n        this._masterEditor._codeMirror.operation(doOperation);\n    };\n    \n    /**\n     * Handles changes from the master backing Editor. Changes are triggered either by direct edits\n     * to that Editor's UI, OR by our setText()/refreshText() methods.\n     * @private\n     */\n    Document.prototype._handleEditorChange = function (event, editor, changeList) {\n        // On any change, mark the file dirty. In the future, we should make it so that if you\n        // undo back to the last saved state, we mark the file clean.\n        var wasDirty = this.isDirty;\n        this.isDirty = editor._codeMirror.isDirty();\n        \n        // If file just became dirty, notify listeners, and add it to working set (if not already there)\n        if (wasDirty !== this.isDirty) {\n            $(exports).triggerHandler(\"dirtyFlagChange\", [this]);\n            addToWorkingSet(this.file);\n        }\n        \n        // Notify that Document's text has changed\n        // TODO: This needs to be kept in sync with SpecRunnerUtils.createMockDocument(). In the\n        // future, we should fix things so that we either don't need mock documents or that this\n        // is factored so it will just run in both.\n        $(this).triggerHandler(\"change\", [this, changeList]);\n    };\n    \n    /**\n     * @private\n     */\n    Document.prototype._markClean = function () {\n        this.isDirty = false;\n        if (this._masterEditor) {\n            this._masterEditor._codeMirror.markClean();\n        }\n        $(exports).triggerHandler(\"dirtyFlagChange\", this);\n    };\n    \n    /** \n     * Called when the document is saved (which currently happens in DocumentCommandHandlers). Marks the\n     * document not dirty and notifies listeners of the save.\n     */\n    Document.prototype.notifySaved = function () {\n        if (!this._masterEditor) {\n            console.log(\"### Warning: saving a Document that is not modifiable!\");\n        }\n        \n        this._markClean();\n        $(exports).triggerHandler(\"documentSaved\", this);\n        \n        // TODO: (issue #295) fetching timestamp async creates race conditions (albeit unlikely ones)\n        var thisDoc = this;\n        this.file.getMetadata(\n            function (metadata) {\n                thisDoc.diskTimestamp = metadata.modificationTime;\n            },\n            function (error) {\n                console.log(\"Error updating timestamp after saving file: \" + thisDoc.file.fullPath);\n            }\n        );\n    };\n    \n    /* (pretty toString(), to aid debugging) */\n    Document.prototype.toString = function () {\n        var dirtyInfo = (this.isDirty ? \" (dirty!)\" : \" (clean)\");\n        var editorInfo = (this._masterEditor ? \" (Editable)\" : \" (Non-editable)\");\n        var refInfo = \" refs:\" + this._refCount;\n        return \"[Document \" + this.file.fullPath + dirtyInfo + editorInfo + refInfo + \"]\";\n    };\n    \n    /**\n     * Gets an existing open Document for the given file, or creates a new one if the Document is\n     * not currently open ('open' means referenced by the UI somewhere). Always use this method to\n     * get Documents; do not call the Document constructor directly. This method is safe to call\n     * in parallel.\n     *\n     * If you are going to hang onto the Document for more than just the duration of a command - e.g.\n     * if you are going to display its contents in a piece of UI - then you must addRef() the Document\n     * and listen for changes on it. (Note: opening the Document in an Editor automatically manages\n     * refs and listeners for that Editor UI).\n     *\n     * @param {!string} fullPath\n     * @return {$.Promise} A promise object that will be resolved with the Document, or rejected\n     *      with a FileError if the file is not yet open and can't be read from disk.\n     */\n    function getDocumentForPath(fullPath) {\n        var doc             = _openDocuments[fullPath],\n            pendingPromise  = getDocumentForPath._pendingDocumentPromises[fullPath];\n\n        if (doc) {\n            // use existing document\n            return new $.Deferred().resolve(doc).promise();\n        } else if (pendingPromise) {\n            // wait for the result of a previous request\n            return pendingPromise;\n        } else {\n            var result = new $.Deferred(),\n                promise = result.promise();\n            \n            // log this document's Promise as pending\n            getDocumentForPath._pendingDocumentPromises[fullPath] = promise;\n\n            // create a new document\n            var fileEntry = new NativeFileSystem.FileEntry(fullPath),\n                perfTimerName = PerfUtils.markStart(\"getDocumentForPath:\\t\" + fullPath);\n\n            result.done(function () {\n                PerfUtils.addMeasurement(perfTimerName);\n            }).fail(function () {\n                PerfUtils.finalizeMeasurement(perfTimerName);\n            });\n\n            FileUtils.readAsText(fileEntry)\n                .always(function () {\n                    // document is no longer pending\n                    delete getDocumentForPath._pendingDocumentPromises[fullPath];\n                })\n                .done(function (rawText, readTimestamp) {\n                    doc = new Document(fileEntry, readTimestamp, rawText);\n                    result.resolve(doc);\n                })\n                .fail(function (fileError) {\n                    result.reject(fileError);\n                });\n            \n            return promise;\n        }\n    }\n    \n    /**\n     * Document promises that are waiting to be resolved. It is possible for multiple clients\n     * to request the same document simultaneously before the initial request has completed.\n     * In particular, this happens at app startup where the working set is created and the\n     * intial active document is opened in an editor. This is essential to ensure that only\n     * 1 Document exists for any FileEntry.\n     * @private\n     * @type {Object.<string, $.Promise>}\n     */\n    getDocumentForPath._pendingDocumentPromises = {};\n    \n    /**\n     * Returns the existing open Document for the given file, or null if the file is not open ('open'\n     * means referenced by the UI somewhere). If you will hang onto the Document, you must addRef()\n     * it; see {@link getDocumentForPath()} for details.\n     */\n    function getOpenDocumentForPath(fullPath) {\n        return _openDocuments[fullPath];\n    }\n    \n    \n    /**\n     * Reacts to a file being deleted: if there is a Document for this file, causes it to dispatch a\n     * \"deleted\" event; ensures it's not the currentDocument; and removes this file from the working\n     * set. These actions in turn cause all open editors for this file to close. Discards any unsaved\n     * changes - it is expected that the UI has already confirmed with the user before calling.\n     *\n     * To simply close a main editor when the file hasn't been deleted, use closeFullEditor() or FILE_CLOSE.\n     *\n     * FUTURE: Instead of an explicit notify, we should eventually listen for deletion events on some\n     * sort of \"project file model,\" making this just a private event handler.\n     */\n    function notifyFileDeleted(file) {\n        // First ensure it's not currentDocument, and remove from working set\n        closeFullEditor(file);\n        \n        // Notify all other editors to close as well\n        var doc = getOpenDocumentForPath(file.fullPath);\n        if (doc) {\n            $(doc).triggerHandler(\"deleted\");\n        }\n        \n        // At this point, all those other views SHOULD have released the Doc\n        if (doc && doc._refCount > 0) {\n            console.log(\"WARNING: deleted Document still has \" + doc._refCount + \" references. Did someone addRef() without listening for 'deleted'?\");\n        }\n    }\n    \n    \n    /**\n     * Get the next or previous file in the working set, in MRU order (relative to currentDocument).\n     * @param {Number} inc  -1 for previous, +1 for next; no other values allowed\n     * @return {?FileEntry}  null if working set empty\n     */\n    function getNextPrevFile(inc) {\n        if (inc !== -1 && inc !== +1) {\n            throw new Error(\"Illegal argument: inc = \" + inc);\n        }\n        \n        if (_currentDocument) {\n            var mruI = findInWorkingSet(_currentDocument.file.fullPath, _workingSetMRUOrder);\n            if (mruI === -1) {\n                // If doc not in working set, return most recent working set item\n                if (_workingSetMRUOrder.length > 0) {\n                    return _workingSetMRUOrder[0];\n                }\n            } else {\n                // If doc is in working set, return next/prev item with wrap-around\n                var newI = mruI + inc;\n                if (newI >= _workingSetMRUOrder.length) {\n                    newI = 0;\n                } else if (newI < 0) {\n                    newI = _workingSetMRUOrder.length - 1;\n                }\n                \n                return _workingSetMRUOrder[newI];\n            }\n        }\n        \n        // If no doc open or working set empty, there is no \"next\" file\n        return null;\n    }\n    \n    \n    /**\n     * @private\n     * Preferences callback. Saves the document file paths for the working set.\n     */\n    function _savePreferences() {\n\n        if (_isProjectChanging) {\n            return;\n        }\n        \n        // save the working set file paths\n        var files       = [],\n            isActive    = false,\n            workingSet  = getWorkingSet(),\n            currentDoc  = getCurrentDocument(),\n            projectRoot = ProjectManager.getProjectRoot();\n\n        if (!projectRoot) {\n            return;\n        }\n\n        workingSet.forEach(function (file, index) {\n            // flag the currently active editor\n            isActive = currentDoc && (file.fullPath === currentDoc.file.fullPath);\n\n            files.push({\n                file: file.fullPath,\n                active: isActive\n            });\n        });\n\n        // append file root to make file list unique for each project\n        _prefs.setValue(\"files_\" + projectRoot.fullPath, files);\n    }\n\n    /**\n     * @private\n     * Handle beforeProjectClose event\n     */\n    function _beforeProjectClose() {\n        _savePreferences();\n\n        // When app is shutdown via shortcut key, the command goes directly to the\n        // app shell, so we can't reliably fire the beforeProjectClose event on\n        // app shutdown. To compensate, we listen for currentDocumentChange,\n        // workingSetAdd, and workingSetRemove events so that the prefs for\n        // last project used get updated. But when switching projects, after\n        // the beforeProjectChange event gets fired, DocumentManager.closeAll()\n        // causes workingSetRemove event to get fired and update the prefs to an empty\n        // list. So, temporarily (until projectOpen event) disallow saving prefs.\n        _isProjectChanging = true;\n    }\n\n    /**\n     * @private\n     * Initializes the working set.\n     */\n    function _projectOpen() {\n        _isProjectChanging = false;\n        \n        // file root is appended for each project\n        var projectRoot = ProjectManager.getProjectRoot(),\n            files = _prefs.getValue(\"files_\" + projectRoot.fullPath);\n\n        if (!files) {\n            return;\n        }\n\n        var filesToOpen = [],\n            activeFile;\n\n        // Add all files to the working set without verifying that\n        // they still exist on disk (for faster project switching)\n        files.forEach(function (value, index) {\n            filesToOpen.push(new NativeFileSystem.FileEntry(value.file));\n            if (value.active) {\n                activeFile = value.file;\n            }\n        });\n        addListToWorkingSet(filesToOpen);\n\n        // Initialize the active editor\n        if (!activeFile && _workingSet.length > 0) {\n            activeFile = _workingSet[0].fullPath;\n        }\n\n        if (activeFile) {\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: activeFile });\n        }\n    }\n\n\n    // Define public API\n    exports.Document = Document;\n    exports.getCurrentDocument = getCurrentDocument;\n    exports.getDocumentForPath = getDocumentForPath;\n    exports.getOpenDocumentForPath = getOpenDocumentForPath;\n    exports.getWorkingSet = getWorkingSet;\n    exports.findInWorkingSet = findInWorkingSet;\n    exports.getAllOpenDocuments = getAllOpenDocuments;\n    exports.setCurrentDocument = setCurrentDocument;\n    exports.addToWorkingSet = addToWorkingSet;\n    exports.addListToWorkingSet = addListToWorkingSet;\n    exports.removeFromWorkingSet = removeFromWorkingSet;\n    exports.getNextPrevFile = getNextPrevFile;\n    exports.beginDocumentNavigation = beginDocumentNavigation;\n    exports.finalizeDocumentNavigation = finalizeDocumentNavigation;\n    exports.closeFullEditor = closeFullEditor;\n    exports.closeAll = closeAll;\n    exports.notifyFileDeleted = notifyFileDeleted;\n\n    // Setup preferences\n    _prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID);\n    $(exports).bind(\"currentDocumentChange workingSetAdd workingSetAddList workingSetRemove workingSetRemoveList\", _savePreferences);\n    \n    // Performance measurements\n    PerfUtils.createPerfMeasurement(\"DOCUMENT_MANAGER_GET_DOCUMENT_FOR_PATH\", \"DocumentManager.getDocumentForPath()\");\n\n    // Handle project change events\n    $(ProjectManager).on(\"projectOpen\", _projectOpen);\n    $(ProjectManager).on(\"beforeProjectClose\", _beforeProjectClose);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50*/\n/*global $, define, brackets, FileError */\n\ndefine('utils/NativeApp',['require','exports','module','utils/Async'],function (require, exports, module) {\n    \n    \n    var Async = require(\"utils/Async\");\n\n    /**\n     * @private\n     * Map an fs error code to a FileError.\n     */\n    function _browserErrToFileError(err) {\n        if (err === brackets.fs.ERR_NOT_FOUND) {\n            return FileError.NOT_FOUND_ERR;\n        }\n        \n        // All other errors are mapped to the generic \"security\" error\n        return FileError.SECURITY_ERR;\n    }\n    \n    var liveBrowserOpenedPIDs = [];\n    var liveBrowserUserDataDir = \"\";\n\n    /** openLiveBrowser\n     *\n     * @param {string} url\n     * @return {$.Promise} \n     */\n    function openLiveBrowser(url, enableRemoteDebugging) {\n        var result = new $.Deferred();\n        \n        brackets.app.openLiveBrowser(url, enableRemoteDebugging, function onRun(err, pid) {\n            if (!err) {\n                liveBrowserOpenedPIDs.push(pid);\n                result.resolve(pid);\n            } else {\n                result.reject(_browserErrToFileError(err));\n            }\n        }, liveBrowserUserDataDir);\n        \n        return result.promise();\n    }\n    \n    /** closeLiveBrowser\n     *\n     * @return {$.Promise}\n     */\n    function closeLiveBrowser(pid) {\n        var result = new $.Deferred();\n        \n        if (isNaN(pid)) {\n            pid = 0;\n        }\n        console.log(\"calling to close: \" + pid);\n        brackets.app.closeLiveBrowser(function (err) {\n            console.log(\"called closing: \" + pid + \" with err: \" + err);\n            if (!err) {\n                var i = liveBrowserOpenedPIDs.indexOf(pid);\n                if (i !== -1) {\n                    liveBrowserOpenedPIDs.splice(i, 1);\n                }\n                result.resolve();\n            } else {\n                result.reject(_browserErrToFileError(err));\n            }\n        }, pid);\n        \n        return result.promise();\n    }\n    \n    /** closeAllLiveBrowsers\n     * Closes all the browsers that were tracked on open\n     * TODO: does not seem to work on Windows\n     * @return {$.Promise}\n     */\n    function closeAllLiveBrowsers() {\n        //make a copy incase the array is edited as we iterate\n        var closeIDs = liveBrowserOpenedPIDs.concat();\n        return Async.doSequentially(closeIDs, closeLiveBrowser, false);\n    }\n    \n    /** _setLiveBrowserUserDataDir\n     * For Unit Tests only, changes the default dir the browser use for it's user data\n     * @return {$.Promise}\n     */\n    function _setLiveBrowserUserDataDir(path) {\n        liveBrowserUserDataDir = path;\n    }\n    \n    /**\n     * Opens a URL in the system default browser\n     */\n    function openURLInDefaultBrowser(url) {\n        brackets.app.openURLInDefaultBrowser(function (err) {}, url);\n    }\n    \n\n    // Define public API\n    exports.openLiveBrowser = openLiveBrowser;\n    exports.closeLiveBrowser = closeLiveBrowser;\n    exports.closeAllLiveBrowsers = closeAllLiveBrowsers;\n    exports.openURLInDefaultBrowser = openURLInDefaultBrowser;\n    //API for Unit Tests\n    exports._setLiveBrowserUserDataDir = _setLiveBrowserUserDataDir;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, WebSocket, FileError, window, XMLHttpRequest */\n\n /**\n * Inspector manages the connection to Chrome/Chromium's remote debugger.\n * See inspector.html for the documentation of the remote debugger.\n *\n * # SETUP\n *\n * To enable remote debugging in Chrome or Chromium open either application\n * with the following parameters:\n *\n *   --enable-remote-debugger --remote-debugging-port=9222\n *\n * This will open an HTTP server on the specified port, which can be used to\n * browse the available remote debugger sessions. In general, every open\n * browser tab can host an individual remote debugger session. The\n * available interfaces can be exported by requesting:\n *\n *   http://127.0.0.1:9222/json\n *\n * The response is a JSON-formatted array that specifies all available remote\n * debugger sessions including the remote debugging web sockets.\n *\n * Inspector can connect directly to a web socket via `connect(socketURL)`, or\n * it can find the web socket that corresponds to the tab at the given URL and\n * connect to it via `connectToURL(url)`. The later returns a promise. To \n * disconnect use `disconnect()`.\n *\n * # EVENTS\n *\n * Inspector dispatches several connectivity-related events + all remote debugger\n * events (see below). Event handlers are attached via `on(event, function)` and\n * detached via `off(event, function)`.\n *\n *   `connect`    Inspector did successfully connect to the remote debugger\n *   `disconnect` Inspector did disconnect from the remote debugger\n *   `error`      Inspector encountered an error\n *   `message`    Inspector received a message from the remote debugger - this\n *                  provides a low-level entry point to remote debugger events\n *\n * # REMOTE DEBUGGER COMMANDS\n *\n * Commands are executed by calling `{Domain}.{Command}()` with the parameters\n * specified in the order of the remote debugger documentation. These command\n * functions are generated automatically at runtime from Inspector.json. The\n * actual implementation of these functions is found in\n * `_send(method, signature, varargs)`, which verifies, serializes, and\n * transmits the command to the remote debugger. If the last parameter of any\n * command function call is a function, it will be used as the callback.\n *\n * # REMOTE DEBUGGER EVENTS\n *\n * Debugger events are dispatched as regular events using {Domain}.{Event} as\n * the event name. The handler function will be called with a single parameter\n * that stores all returned values as an object.\n */\ndefine('LiveDevelopment/Inspector/Inspector',['require','exports','module'],function Inspector(require, exports, module) {\n    \n\n    // jQuery exports object for events\n    var $exports = $(exports);\n\n    var _messageId = 1; // id used for remote method calls, auto-incrementing\n    var _messageCallbacks = {}; // {id -> function} for remote method calls\n    var _socket; // remote debugger WebSocket\n    var _connectDeferred; // The deferred connect\n\n    /** Check a parameter value against the given signature\n     * This only checks for optional parameters, not types\n     * Type checking is complex because of $ref and done on the remote end anyways\n     * @param {signature}\n     * @param {value}\n     */\n    function _verifySignature(signature, value) {\n        if (value === undefined) {\n            console.assert(signature.optional === true, \"Missing argument: \" + signature.name);\n        }\n        return true;\n    }\n\n    /** Send a message to the remote debugger\n     * All passed arguments after the signature are passed on as parameters.\n     * If the last argument is a function, it is used as the callback function.\n     * @param {string} remote method\n     * @param {object} the method signature\n     */\n    function _send(method, signature, varargs) {\n        if (!_socket) {\n            // FUTURE: Our current implementation closes and re-opens an inspector connection whenever\n            // a new HTML file is selected. If done quickly enough, pending requests from the previous\n            // connection could come in before the new socket connection is established. For now we \n            // simply ignore this condition. \n            // This race condition will go away once we support multiple inspector connections and turn\n            // off auto re-opening when a new HTML file is selected.\n            return;\n        }\n\n        console.assert(_socket, \"You must connect to the WebSocket before sending messages.\");\n        var id, callback, args, i, params = {};\n\n        // extract the parameters, the callback function, and the message id\n        args = Array.prototype.slice.call(arguments, 2);\n        if (typeof args[args.length - 1] === \"function\") {\n            id = _messageId++;\n            _messageCallbacks[id] = args.pop();\n        } else {\n            id = 0;\n        }\n\n        // verify the parameters against the method signature\n        // this also constructs the params object of type {name -> value}\n        for (i in signature) {\n            if (_verifySignature(args[i], signature[i])) {\n                params[signature[i].name] = args[i];\n            }\n        }\n        _socket.send(JSON.stringify({ method: method, id: id, params: params }));\n    }\n\n    /** WebSocket did close */\n    function _onDisconnect() {\n        _socket = undefined;\n        $exports.triggerHandler(\"disconnect\");\n    }\n\n    /** WebSocket reported an error */\n    function _onError(error) {\n        $exports.triggerHandler(\"error\", [error]);\n    }\n\n    /** WebSocket did open */\n    function _onConnect() {\n        $exports.triggerHandler(\"connect\");\n    }\n\n    /** Received message from the WebSocket\n     * A message can be one of three things:\n     *   1. an error -> report it\n     *   2. the response to a previous command -> run the stored callback\n     *   3. an event -> trigger an event handler method\n     * @param {object} message\n     */\n    function _onMessage(message) {\n        var response = JSON.parse(message.data);\n        $exports.triggerHandler(\"message\", [response]);\n        if (response.error) {\n            $exports.triggerHandler(\"error\", [response.error]);\n        } else if (response.result) {\n            if (_messageCallbacks[response.id]) {\n                _messageCallbacks[response.id](response.result);\n            }\n        } else {\n            var domainAndMethod = response.method.split(\".\");\n            var domain = domainAndMethod[0];\n            var method = domainAndMethod[1];\n            $(exports[domain]).triggerHandler(method, response.params);\n        }\n    }\n\n\n    /** Public Functions *****************************************************/\n\n    /** Get the available debugger sockets from the remote debugger\n     * @param {string} host IP or name\n     * @param {integer} debugger port\n     */\n    function getAvailableSockets(host, port) {\n        if (!host) {\n            host = \"127.0.0.1\";\n        }\n        if (!port) {\n            port = 9222;\n        }\n        var def = new $.Deferred();\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"http://\" + host + \":\" + port + \"/json\");\n        request.onload = function onLoad() {\n            var sockets = JSON.parse(request.response);\n            def.resolve(sockets);\n        };\n        request.onerror = function onError() {\n            def.reject(request.response);\n        };\n        request.send(null);\n        return def.promise();\n    }\n\n    /** Register a handler to be called when the given event is triggered\n     * @param {string} event name\n     * @param {function} handler function\n     */\n    function on(name, handler) {\n        $exports.on(name, handler);\n    }\n\n    /** Remove the given or all event handler(s) for the given event or remove all event handlers\n     * @param {string} optional event name\n     * @param {function} optional handler function\n     */\n    function off(name, handler) {\n        $exports.off(name, handler);\n    }\n\n    /** Disconnect from the remote debugger WebSocket */\n    function disconnect() {\n        if (_socket) {\n            if (_socket.readyState === 1) {\n                _socket.close();\n            } else {\n                delete _socket.onmessage;\n                delete _socket.onopen;\n                delete _socket.onclose;\n                delete _socket.onerror;\n            }\n            _socket = undefined;\n        }\n    }\n\n    /** Connect to the remote debugger WebSocket at the given URL\n     * @param {string} WebSocket URL\n     */\n    function connect(socketURL) {\n        disconnect();\n        _socket = new WebSocket(socketURL);\n        _socket.onmessage = _onMessage;\n        _socket.onopen = _onConnect;\n        _socket.onclose = _onDisconnect;\n        _socket.onerror = _onError;\n    }\n\n    /** Connect to the remote debugger of the page that is at the given URL\n     * @param {string} url\n     */\n    function connectToURL(url) {\n        if (_connectDeferred) {\n            // reject an existing connection attempt\n            _connectDeferred.reject(\"CANCEL\");\n        }\n        var deferred = new $.Deferred();\n        _connectDeferred = deferred;\n        var promise = getAvailableSockets();\n        promise.done(function onGetAvailableSockets(response) {\n            if (deferred.isRejected()) {\n                return;\n            }\n            var i, page;\n            for (i in response) {\n                page = response[i];\n                if (page.webSocketDebuggerUrl && page.url.search(url) === 0) {\n                    connect(page.webSocketDebuggerUrl);\n                    deferred.resolve();\n                    return;\n                }\n            }\n            deferred.reject(FileError.ERR_NOT_FOUND); // Reject with a \"not found\" error\n        });\n        promise.fail(function onFail(err) {\n            deferred.reject(err);\n        });\n        return deferred.promise();\n    }\n\n    /** Check if the inspector is connected */\n    function connected() {\n        return _socket !== undefined;\n    }\n\n    /** Initialize the Inspector\n     * Read the Inspector.json configuration and define the command objects\n     * -> Inspector.domain.command()\n     */\n    function init(theConfig) {\n        exports.config = theConfig;\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"LiveDevelopment/Inspector/Inspector.json\");\n        request.onload = function onLoad() {\n            var InspectorJSON = JSON.parse(request.response);\n            var i, j, domain, domainDef, command;\n            for (i in InspectorJSON.domains) {\n                domain = InspectorJSON.domains[i];\n                exports[domain.domain] = {};\n                for (j in domain.commands) {\n                    command = domain.commands[j];\n                    exports[domain.domain][command.name] = _send.bind(undefined, domain.domain + \".\" + command.name, command.parameters);\n                }\n            }\n        };\n        request.send(null);\n    }\n\n    // Export public functions\n    exports.getAvailableSockets = getAvailableSockets;\n    exports.on = on;\n    exports.off = off;\n    exports.disconnect = disconnect;\n    exports.connect = connect;\n    exports.connectToURL = connectToURL;\n    exports.connected = connected;\n    exports.init = init;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, XMLHttpRequest */\n\n/**\n * RemoteAgent defines and provides an interface for custom remote functions\n * loaded from RemoteFunctions. Remote commands are executed via\n * `call(name, varargs)`.\n *\n * Remote events are dispatched as events on this object.\n */\ndefine('LiveDevelopment/Agents/RemoteAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector'],function RemoteAgent(require, exports, module) {\n    \n\n    var $exports = $(exports);\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _load; // deferred load\n    var _objectId; // the object id of the remote object\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"LiveDevelopment/Agents/RemoteFunctions.js\");\n        request.onload = function onLoad() {\n            var run = \"window._LD=\" + request.response + \"()\";\n            Inspector.Runtime.evaluate(run, function onEvaluate(res) {\n                console.assert(!res.wasThrown, res.result.description);\n                _objectId = res.result.objectId;\n                _load.resolve();\n            });\n        };\n        request.send(null);\n    }\n\n    // WebInspector Event: DOM.attributeModified\n    function _onAttributeModified(event, res) {\n        // res = {nodeId, name, value}\n        var matches = /^data-ld-(.*)/.exec(res.name);\n        if (matches) {\n            $exports.triggerHandler(matches[1], res);\n        }\n    }\n\n    /** Call a remote function\n     * The parameters are passed on to the remote functions. Nodes are resolved\n     * and sent as objectIds.\n     * @param {string} function name\n     */\n    function call(method, varargs) {\n        console.assert(_objectId, \"Attempted to call remote method without objectId set.\");\n        var args = Array.prototype.slice.call(arguments, 1);\n\n        // if the last argument is a function it is the callback function\n        var callback;\n        if (typeof args[args.length - 1] === \"function\") {\n            callback = args.pop();\n        }\n\n        // Resolve node parameters\n        var i;\n        for (i in args) {\n            if (args[i].nodeId) {\n                args[i] = args[i].resolve();\n            }\n        }\n        $.when.apply(undefined, args).then(function onResolvedAllNodes() {\n            var i, arg, params = [];\n            for (i in arguments) {\n                arg = args[i];\n                if (arg.objectId) {\n                    params.push({objectId: arg.objectId});\n                } else {\n                    params.push({value: arg});\n                }\n            }\n            Inspector.Runtime.callFunctionOn(_objectId, \"_LD.\" + method, params, undefined, callback);\n        });\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        $(Inspector.Page).on(\"loadEventFired.RemoteAgent\", _onLoadEventFired);\n        $(Inspector.DOM).on(\"attributeModified.RemoteAgent\", _onAttributeModified);\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Page).off(\".RemoteAgent\");\n        $(Inspector.DOM).off(\".RemoteAgent\");\n    }\n\n    // Export public functions\n    exports.call = call;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * DOMHelpers is a collection of functions used by the DOMAgent exports `eachNode(src, callback)`\n */\ndefine('LiveDevelopment/Agents/DOMHelpers',['require','exports','module'],function DOMHelpersModule(require, exports, module) {\n    \n\n    /** Test if the given character is a quote character\n     * {char} source character\n     * {char} escape (previous) character\n     * {char} quote character\n     */\n    function _isQuote(c, escape, quote) {\n        if (escape === \"\\\\\") {\n            return false;\n        }\n        if (quote !== undefined) {\n            return c === quote;\n        }\n        return c === \"\\\"\" || c === \"'\";\n    }\n\n    /** Remove quotes from the string and adjust escaped quotes\n     * @param {string} source string\n     */\n    function _removeQuotes(src) {\n        if (_isQuote(src[0]) && src[src.length - 1] === src[0]) {\n            var q = src[0];\n            src = src.substr(1, src.length - 2);\n            src = src.replace(\"\\\\\" + q, q);\n        }\n        return src;\n    }\n\n    /** Find the next match using several constraints\n     * @param {string} source string\n     * @param {string} or [{regex}, {length}] the match definition\n     * @param {integer} ignore characters before this offset\n     * @param {boolean} watch for quotes\n     * @param [{string},{string}] watch for comments\n     */\n    function _find(src, match, skip, quotes, comments) {\n        if (typeof match === \"string\") {\n            match = [match, match.length];\n        }\n        if (skip === undefined) {\n            skip = 0;\n        }\n        var i, activeQuote, isComment = false;\n        for (i = skip; i < src.length; i++) {\n            if (quotes && _isQuote(src[i], src[i - 1], activeQuote)) {\n                // starting quote\n                activeQuote = activeQuote ? undefined : src[i];\n            } else if (!activeQuote) {\n                if (comments && !isComment && src.substr(i, comments[0].length) === comments[0]) {\n                    // opening comment\n                    isComment = true;\n                    i += comments[0].length - 1;\n                } else if (isComment) {\n                    // we are commented\n                    if (src.substr(i, comments[1].length) === comments[1]) {\n                        isComment = false;\n                        i += comments[1].length - 1;\n                    }\n                } else if (src.substr(i, match[1]).search(match[0]) === 0) {\n                    // match\n                    return i;\n                }\n            }\n        }\n        return -1;\n    }\n\n    /** Callback iterator using `_find` */\n    function _findEach(src, match, quotes, comments, callback) {\n        var from = 0;\n        var to;\n        while (from < src.length) {\n            to = _find(src, match, from, quotes, comments);\n            if (to < 0) {\n                to = src.length;\n            }\n            callback(src.substr(from, to - from));\n            from = to + 1;\n        }\n    }\n\n    /** Find the next tag\n     * @param {string} source string\n     * @param {integer} ignore characters before this offset\n     */\n    function _findTag(src, skip) {\n        var from, to, inc;\n        from = _find(src, [/<[a-z!\\/]/, 2], skip);\n        if (from < 0) {\n            return null;\n        }\n        if (src.substr(from, 4) === \"<!--\") {\n            // html comments\n            to = _find(src, \"-->\", from + 4);\n            inc = 3;\n        } else if (src.substr(from, 7) === \"<script\") {\n            // script tag\n            to = _find(src, \"</script>\", from + 7);\n            inc = 9;\n        } else {\n            to = _find(src, \">\", from + 1, true);\n            inc = 1;\n        }\n        if (to < 0) {\n            return null;\n        }\n        return {from: from, length: to + inc - from};\n    }\n\n    /** Extract tag attributes from the given source of a single tag\n     * @param {string} source content\n     */\n    function _extractAttributes(content) {\n\n        // remove the node name and the closing bracket and optional slash\n        content = content.replace(/^<\\S+\\s*/, \"\");\n        content = content.replace(/\\s*\\/?>$/, \"\");\n        if (content.length === 0) {\n            return;\n        }\n\n        // go through the items and identify key value pairs split by =\n        var index, key, value;\n        var attributes = {};\n        _findEach(content, [/\\s/, 1], true, undefined, function each(item) {\n            index = item.search(\"=\");\n            if (index < 0) {\n                return;\n            }\n\n            // get the key\n            key = item.substr(0, index).trim();\n            if (key.length === 0) {\n                return;\n            }\n\n            // get the value\n            value = item.substr(index + 1).trim();\n            value = _removeQuotes(value);\n            attributes[key] = value;\n        });\n\n        return attributes;\n    }\n\n    /** Extract the node payload\n     * @param {string} source content\n     */\n    function extractPayload(content) {\n        var payload = {};\n\n        if (content[0] !== \"<\") {\n            // text\n            payload.nodeType = 3;\n            payload.nodeValue = content;\n        } else if (content.substr(0, 4) === \"<!--\") {\n            // comment\n            payload.nodeType = 8;\n            payload.nodeValue = content.substr(4, content.length - 7);\n        } else if (content[1] === \"!\") {\n            // doctype\n            payload.nodeType = 10;\n        } else {\n            // regular element\n            payload.nodeType = 1;\n            payload.nodeName = /^<([^>\\s]+)/.exec(content)[1].toUpperCase();\n            payload.attributes = _extractAttributes(content);\n\n            // closing node (/ at the beginning)\n            if (payload.nodeName[0] === \"/\") {\n                payload.nodeName = payload.nodeName.substr(1);\n                payload.closing = true;\n            }\n\n            // closed node (/ at the end)\n            if (content[content.length - 2] === \"/\") {\n                payload.closed = true;\n            }\n        }\n        return payload;\n    }\n\n    /** Split the source string into payloads representing individual nodes\n     * @param {string} source\n     * @param {function(payload)} callback\n     */\n    // split a string into individual node contents\n    function eachNode(src, callback) {\n        var index = 0;\n        var text, range, length, payload;\n        var x = 0;\n        while (index < src.length) {\n\n            // find the next tag\n            range = _findTag(src, index);\n            if (!range) {\n                range = { from: src.length, length: 0 };\n            }\n\n            // add the text before the tag\n            length = range.from - index;\n            if (length > 0) {\n                text = src.substr(index, length);\n                if (/\\S/.test(text)) {\n                    payload = extractPayload(text);\n                    payload.sourceOffset = index;\n                    payload.sourceLength = length;\n                    callback(payload);\n                }\n            }\n\n            // add the tag\n            if (range.length > 0) {\n                payload = extractPayload(src.substr(range.from, range.length));\n                payload.sourceOffset = range.from;\n                payload.sourceLength = range.length;\n                callback(payload);\n            }\n\n            // advance\n            index = range.from + range.length;\n        }\n    }\n\n    // Export public functions\n    exports.extractPayload = extractPayload;\n    exports.eachNode = eachNode;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * DOMNode represents a node in the DOM tree. It is constructed from a payload\n * similar to {DOM.Node} and supports all basic tree operations. If a node has\n * a nodeId it is registered with the `DOMAgent` via `addNode()`. The node's\n * sourceOffset and sourceLength is stored as its location and length. Nodes can\n * iterated using `each()` or `find()`. `dump` shows the entire tree on the console.\n */\ndefine('LiveDevelopment/Agents/DOMNode',['require','exports','module','LiveDevelopment/Agents/DOMHelpers'],function DOMNodeModule(require, exports, module) {\n    \n\n    var DOMHelpers = require(\"LiveDevelopment/Agents/DOMHelpers\");\n\n    /** Fill a string to the given length (used for debug output)\n     * @param {string} source string\n     * @param {integer} length\n     * @param {char} fill character\n     */\n    function _fill(string, length, c) {\n        if (c === undefined) {\n            c = \" \";\n        }\n        while (string.length < length) {\n            string += c;\n        }\n        return string;\n    }\n\n    /** Construct a find condition (used in `find` and `findParent`)\n     * The match can be a callback returning true or false, the node\n     * name or the node type.\n     * @param {function} or {string} or {number} match criteria\n     */\n    function _makeFindCondition(match) {\n        switch (typeof match) {\n        case \"function\":\n            return match;\n        case \"string\":\n            return function findCondition(name, node) {\n                return node.name === name;\n            }.bind(undefined, match.toUpperCase());\n        case \"number\":\n            return function findCondition(type, node) {\n                return node.type === type;\n            }.bind(undefined, match);\n        default:\n            console.error(\"Invalid find condition: \" + match);\n        }\n    }\n\n    /** Constructor\n     * @param {DOMAgent} the agent is passed to avoid circular relationships\n     * @param {DOM.Node} node payload\n     */\n    var DOMNode = function DOMNode(agent, payload) {\n        this.agent = agent;\n        this.children = [];\n        this.attributes = {};\n\n        // set the payload\n        if (typeof payload === \"string\") {\n            payload = DOMHelpers.extractPayload(payload);\n        }\n        if (payload) {\n            this.setPayload(payload);\n        }\n        this.agent.addNode(this);\n    };\n\n    var TYPE_ELEMENT = DOMNode.TYPE_ELEMENT = 1; // element node\n    var TYPE_ATTRIBUTE = DOMNode.TYPE_ATTRIBUTE = 2; // attribute node (unused)\n    var TYPE_TEXT = DOMNode.TYPE_TEXT = 3; // text node\n    var TYPE_COMMENT = DOMNode.TYPE_COMMENT = 8; // comment node <!-- -->\n    var TYPE_DOCUMENT = DOMNode.TYPE_DOCUMENT = 9; // document node <!DOCUMENT>\n\n    /** Remove a node */\n    DOMNode.prototype.remove = function remove() {\n        this.agent.removeNode(this);\n        if (this.parent) {\n            this.parent.removeChild(this);\n        }\n    };\n\n\n    /** Node Payload ***********************************************************/\n\n    /** Set the node payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.setPayload = function setPayload(payload) {\n        this.nodeId = payload.nodeId;\n        this.type = payload.nodeType;\n        if (payload.nodeName) {\n            this.name = payload.nodeName;\n        }\n        if (payload.nodeValue) {\n            this.value = payload.nodeValue;\n        }\n        this.attributes = {};\n        if (payload.attributes) {\n            var i, k, v;\n            for (i = 0; i < payload.attributes.length; i += 2) {\n                k = payload.attributes[i];\n                v = payload.attributes[i + 1];\n                this.attributes[k] = v;\n            }\n        }\n        if (payload.sourceOffset) {\n            this.location = payload.sourceOffset;\n        }\n        if (payload.sourceLength) {\n            this.length = payload.sourceLength;\n        } else {\n            if (this.value) {\n                this.length = this.value.length;\n            } else if (this.name) {\n                this.length = this.name.length + 2;\n            }\n        }\n        if (payload.children) {\n            this.setChildrenPayload(payload.children);\n        } else if (payload.childNodeCount) {\n            this.agent.requestChildNodes(this);\n        }\n    };\n\n    /** Create child nodes from the given payload\n     * @param [{DOM.Node}] payload of the children\n     */\n    DOMNode.prototype.setChildrenPayload = function setChildrenPayload(childrenPayload) {\n        var i, payload, node;\n        for (i in childrenPayload) {\n            payload = childrenPayload[i];\n            node = new DOMNode(this.agent, payload);\n            this.appendChild(node);\n        }\n    };\n\n    /** Construct the payload for this node */\n    DOMNode.prototype.payload = function payload() {\n        var res = { type: this.type };\n        if (this.nodeType === TYPE_ELEMENT) {\n            res.nodeName = this.name;\n        } else {\n            res.value = this.value;\n        }\n        return res;\n    };\n\n    /** Find the next node that matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.findParentForNextNodeMatchingPayload = function findParentForNextNodeMatchingPayload(payload) {\n        var parent = this.canHaveChildren() ? this : this.parent;\n        while (parent && !parent.matchesPayload(payload)) {\n            parent = parent.parent;\n        }\n        return parent;\n    };\n\n    /** Find the next node that matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.findNextNodeMatchingPayload = function findNextNodeMatchingPayload(payload) {\n        var next = this.nextNode();\n        while (next && !next.matchesPayload(payload)) {\n            next = next.nextNode();\n        }\n        return next;\n    };\n\n    /** Test if the node matches the given payload\n     * @param {DOM.Node} payload\n     */\n    DOMNode.prototype.matchesPayload = function matchesPayload(payload) {\n        var r = false;\n        if (this.type === payload.nodeType) {\n            switch (this.type) {\n            case 1:\n                r = this.name === payload.nodeName;\n                break;\n            case 3:\n                // TODO payload.nodeValue's HTML Entities must be decoded\n                // r = this.value === payload.nodeValue;\n                r = true;\n                break;\n            default:\n                r = true;\n            }\n        }\n        // Useful output for debugging this - do not remove\n        // console.debug(this.type + \",\" + this.name + \",\" + this.value + \" = \" + payload.nodeType + \",\" + payload.nodeName + \",\" + payload.value + \" -> \" + r);\n        return r;\n    };\n\n    /** Resolve the node and retrieve its objectId from the remote debugger */\n    DOMNode.prototype.resolve = function resolve() {\n        var def = new $.Deferred();\n        if (this.objectId) {\n            def.resolve(this);\n        } else if (!this.nodeId) {\n            def.reject();\n        } else {\n            this.agent.resolveNode(this, function onResolve(res) {\n                this.objectId = res.object.objectId;\n                def.resolve(this);\n            }.bind(this));\n        }\n        return def.promise();\n    };\n\n\n    /** Tree Operations ******************************************************/\n\n    /** Can the node have children? */\n    DOMNode.prototype.canHaveChildren = function canHaveChildren() {\n        return (this.type === 1 && !this.closed && !this.closing && this.nodeName !== \"LINK\");\n    };\n\n    /** Remove a child\n     * @param {DOMNode} child node to remove\n     */\n    DOMNode.prototype.removeChild = function removeChild(node) {\n        this.children.splice(this.indexOfChild(node), 1);\n        delete node.parent;\n    };\n\n    /** Insert a child node at the given index\n     * @param {DOMNode} node to insert\n     * @param {integer} optional index (node is appended if missing)\n     */\n    DOMNode.prototype.insertChildAt = function insertChildAt(node, index) {\n        if (node.parent) {\n            node.parent.removeChild(node);\n        }\n        if (!index || index < 0 || index > this.children.length) {\n            index = this.children.length;\n        }\n        this.children.splice(index, 0, node);\n        node.parent = this;\n        return node;\n    };\n\n    /** Append a child to this node\n     * @param {DOMNode} child node to append\n     */\n    DOMNode.prototype.appendChild = function appendChild(node) {\n        return this.insertChildAt(node);\n    };\n\n    /** Insert a child node after the given node\n     * @param {DOMNode} child node to insert\n     * @param {DOMNode} existing child node\n     */\n    DOMNode.prototype.insertChildAfter = function insertChildAfter(node, sibling) {\n        var index = this.indexOfChild(sibling);\n        if (index >= 0) {\n            index++;\n        }\n        return this.insertChildAt(node, index);\n    };\n\n    /** Insert a child node before the given node\n     * @param {DOMNode} child node to insert\n     * @param {DOMNode} existing child node\n     */\n    DOMNode.prototype.insertChildBefore = function insertChildBefore(node, sibling) {\n        var index = this.indexOfChild(sibling);\n        return this.insertChildAt(node, index);\n    };\n\n    /** Determine the index of a child node\n     * @param {DOMNode} child node\n     */\n    DOMNode.prototype.indexOfChild = function indexOfChild(node) {\n        if (!node) {\n            return -1;\n        }\n        var i;\n        for (i in this.children) {\n            if (this.children[i] === node) {\n                return parseInt(i, 0);\n            }\n        }\n        return -1;\n    };\n\n    /** Get the previous sibling */\n    DOMNode.prototype.previousSibling = function previousSibling() {\n        if (!this.parent) {\n            return null;\n        }\n        return this.parent.children[this.parent.indexOfChild(this) - 1];\n    };\n\n    /** Get the next sibling */\n    DOMNode.prototype.nextSibling = function nextSibling() {\n        if (!this.parent) {\n            return null;\n        }\n        return this.parent.children[this.parent.indexOfChild(this) + 1];\n    };\n\n    /** Get the previous node */\n    DOMNode.prototype.previousNode = function previousNode() {\n        var node = this.previousSibling();\n        if (node) {\n            if (node.children.length > 0) {\n                node = node.children[node.children.length - 1];\n            }\n        } else {\n            node = this.parent;\n        }\n        return node;\n    };\n\n    /** Get the next node */\n    DOMNode.prototype.nextNode = function nextNode() {\n        if (this.children.length > 0) {\n            // return the first child\n            return this.children[0];\n        }\n        // return this or any ancestor's next sibling\n        var node, parent = this;\n        while (parent) {\n            node = parent.nextSibling();\n            if (node) {\n                return node;\n            }\n            parent = parent.parent;\n        }\n        return null;\n    };\n\n    /** Traverse the tree\n     * @param {function({DOM.Node})} called for this node and all descendants\n     */\n    DOMNode.prototype.each = function each(callback) {\n        if (callback(this) === false) {\n            return false;\n        }\n        var i;\n        for (i in this.children) {\n            if (this.children[i].each(callback) === false) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    /** Find a node in the tree\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.find = function find(match) {\n        var findCondition = _makeFindCondition(match);\n        var node = null;\n        this.each(function each(n) {\n            if (findCondition(n)) {\n                node = n;\n                return false;\n            }\n        });\n        return node;\n    };\n\n    /** Find all nodes with the given find condition\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.findAll = function findAll(match) {\n        var nodes = [];\n        var findCondition = _makeFindCondition(match);\n        this.each(function each(node) {\n            if (findCondition(node)) {\n                nodes.push(node);\n            }\n        });\n        return nodes;\n    };\n\n    /** Iterate over all parent nodes\n     * @param {function({DOM.Node})} called for each ancestor\n     */\n    DOMNode.prototype.eachParent = function eachParent(callback) {\n        var node = this.parent;\n        while (node) {\n            if (callback(node) === false) {\n                return;\n            }\n            node = node.parent;\n        }\n        return null;\n    };\n\n    /** Find a parent node that matches the find condition\n     * @param {function} or {string} or {integer} find condition\n     */\n    DOMNode.prototype.findParent = function findParent(findCondition) {\n        var theParent = null;\n        this.eachParent(function each(parent) {\n            if (findCondition(parent)) {\n                theParent = parent;\n                return false;\n            }\n        });\n        return theParent;\n    };\n\n    /** Find the root of the tree */\n    DOMNode.prototype.root = function root() {\n        var node = this;\n        while (node.parent) {\n            node = node.parent;\n        }\n        return node;\n    };\n\n\n   /** Node Info ***********************************************************/\n\n   /** Test if the given location is inside this node\n    * @param {integer} location\n    * @param {boolean} also include children\n    */\n    DOMNode.prototype.isAtLocation = function isAtLocation(location, includeChildren) {\n        if (includeChildren === undefined) {\n            includeChildren = true;\n        }\n        if (!this.location || location < this.location) {\n            return false;\n        }\n        var to;\n        if (includeChildren && this.closeLocation) {\n            to = this.closeLocation + this.closeLength;\n        } else {\n            to = this.location + this.length;\n        }\n        if (this.type === TYPE_TEXT) {\n            to += 1;\n        }\n        return location < to;\n    };\n\n    /** Test if this node is empty */\n    DOMNode.prototype.isEmpty = function isEmpty() {\n        return this.type === TYPE_TEXT && /^\\s*$/.test(this.value);\n    };\n\n    /** Debug Output */\n    DOMNode.prototype.toString = function toString() {\n        var r;\n        switch (this.type) {\n        case TYPE_ELEMENT:\n            r = \"<\" + this.name + \">\";\n            break;\n        case TYPE_ATTRIBUTE:\n            r = \"[ATTRIBUTE]\";\n            break;\n        case TYPE_TEXT:\n            r = this.value.replace(/\\s+/, \" \").substr(0, 40);\n            break;\n        case TYPE_COMMENT:\n            r = \"<!--\" + this.value.replace(/\\s+/, \" \").substr(0, 33) + \"-->\";\n            break;\n        case TYPE_DOCUMENT:\n            r = \"<!DOCTYPE>\";\n            break;\n        }\n        return r;\n    };\n\n    /** Detailed Debug Output */\n    DOMNode.prototype.dump = function dump(pre) {\n        if (pre === undefined) {\n            pre = \"\";\n        }\n        var r = pre + this.toString();\n        if (this.location) {\n            r = _fill(r, 60);\n            r += \" (\" + this.location + \",\" + (this.location + this.length) + \")\";\n            if (this.closeLocation) {\n                r += \" (\" + this.closeLocation + \",\" + (this.closeLocation + this.closeLength) + \")\";\n            }\n        }\n        if (this.nodeId) {\n            r = _fill(r, 80);\n            r += \" {\" + this.nodeId + \"}\";\n        }\n        console.info(r);\n        pre += \". \";\n        var i;\n        for (i in this.children) {\n            this.children[i].dump(pre);\n        }\n    };\n\n    return DOMNode;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, XMLHttpRequest */\n\n/**\n * DOMAgent constructs and maintains a tree of {DOMNode}s that represents the\n * rendered DOM tree in the remote browser. Nodes can be accessed by id or\n * location (source offset). To update the DOM tree in response to a change of\n * the source document (replace [from,to] with text) call\n * `applyChange(from, to, text)`.\n *\n * The DOMAgent triggers `getDocument` once it has loaded\n * the document.\n */\ndefine('LiveDevelopment/Agents/DOMAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/DOMNode','LiveDevelopment/Agents/DOMHelpers'],function DOMAgent(require, exports, module) {\n    \n\n    var $exports = $(exports);\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var DOMNode = require(\"LiveDevelopment/Agents/DOMNode\");\n    var DOMHelpers = require(\"LiveDevelopment/Agents/DOMHelpers\");\n\n    var _load; // {$.Deferred} load promise\n    var _idToNode; // {nodeId -> node}\n    var _pendingRequests; // {integer} number of pending requests before initial loading is complete\n\n    /** Get the last node before the given location\n     * @param {integer} location\n     */\n    function nodeBeforeLocation(location) {\n        var node;\n        exports.root.each(function each(n) {\n            if (!n.location || location < n.location) {\n                return true;\n            }\n            if (!node || node.location < n.location) {\n                node = n;\n            }\n        });\n        return node;\n    }\n\n    /** Get the element node that encloses the given location\n     * @param {location}\n     */\n    function allNodesAtLocation(location) {\n        var nodes = [];\n        exports.root.each(function each(n) {\n            if (n.type === DOMNode.TYPE_ELEMENT && n.isAtLocation(location)) {\n                nodes.push(n);\n            }\n        });\n        return nodes;\n    }\n\n    /** Get the node at the given location\n     * @param {location}\n     */\n    function nodeAtLocation(location) {\n        return exports.root.find(function each(n) {\n            return n.isAtLocation(location, false);\n        });\n    }\n\n    /** Find the node for the given id\n     * @param {DOMNode} node\n     */\n    function nodeWithId(nodeId) {\n        return _idToNode[nodeId];\n    }\n\n    /** Update the node index\n     * @param {DOMNode} node\n     */\n    function removeNode(node) {\n        if (node.nodeId) {\n            delete _idToNode[node.nodeId];\n        }\n    }\n\n    /** Update the node index\n     * @param {DOMNode} node\n     */\n    function addNode(node) {\n        if (node.nodeId) {\n            _idToNode[node.nodeId] = node;\n        }\n    }\n\n    /** Request the child nodes for a node\n     * @param {DOMNode} node\n     */\n    function requestChildNodes(node) {\n        if (_pendingRequests >= 0) {\n            _pendingRequests++;\n        }\n        Inspector.DOM.requestChildNodes(node.nodeId);\n    }\n\n    /** Resolve a node\n     * @param {DOMNode} node\n     */\n    function resolveNode(node, callback) {\n        console.assert(node.nodeId, \"Attempted to resolve node without id\");\n        Inspector.DOM.resolveNode(node.nodeId, callback);\n    }\n\n    /** Eliminate the query string from a URL\n     * @param {string} URL\n     */\n    function _cleanURL(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Map the DOM document to the source text\n     * @param {string} source\n     */\n    function _mapDocumentToSource(source) {\n        var node = exports.root;\n        DOMHelpers.eachNode(source, function each(payload) {\n            if (!node) {\n                return true;\n            }\n            if (payload.closing) {\n                var parent = node.findParentForNextNodeMatchingPayload(payload);\n                if (!parent) {\n                    return console.warn(\"Matching Parent not at \" + payload.sourceOffset + \" (\" + payload.nodeName + \")\");\n                }\n                parent.closeLocation = payload.sourceOffset;\n                parent.closeLength = payload.sourceLength;\n            } else {\n                var next = node.findNextNodeMatchingPayload(payload);\n                if (!next) {\n                    return console.warn(\"Skipping Source Node at \" + payload.sourceOffset);\n                }\n                node = next;\n                node.location = payload.sourceOffset;\n                node.length = payload.sourceLength;\n                if (payload.closed) {\n                    node.closed = payload.closed;\n                }\n            }\n        });\n    }\n\n    /** Load the source document and match it with the DOM tree*/\n    function _onFinishedLoadingDOM() {\n        console.assert(exports.url.substr(0, 7) === \"file://\", \"Can only load file urls\");\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", exports.url);\n        request.onload = function onLoad() {\n            _mapDocumentToSource(request.response);\n            _load.resolve();\n        };\n        request.onerror = function onError() {\n            _load.reject(\"Could not load source file at \" + exports.url);\n        };\n        request.send(null);\n    }\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        Inspector.DOM.getDocument(function onGetDocument(res) {\n            $exports.triggerHandler(\"getDocument\", res);\n            // res = {root}\n            _idToNode = {};\n            _pendingRequests = 0;\n            exports.root = new DOMNode(exports, res.root);\n        });\n    }\n\n    // WebInspector Event: Page.frameNavigated\n    function _onFrameNavigated(event, res) {\n        // res = {frame}\n        exports.url = _cleanURL(res.frame.url);\n    }\n\n     // WebInspector Event: DOM.documentUpdated\n    function _onDocumentUpdated(event, res) {\n        // res = {}\n    }\n\n    // WebInspector Event: DOM.setChildNodes\n    function _onSetChildNodes(event, res) {\n        // res = {parentId, nodes}\n        var node = nodeWithId(res.parentId);\n        node.setChildrenPayload(res.nodes);\n        if (_pendingRequests > 0 && --_pendingRequests === 0) {\n            _onFinishedLoadingDOM();\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeCountUpdated\n    function _onChildNodeCountUpdated(event, res) {\n        // res = {nodeId, childNodeCount}\n        if (res.nodeId > 0) {\n            Inspector.DOM.requestChildNodes(res.nodeId);\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeInserted\n    function _onChildNodeInserted(event, res) {\n        // res = {parentNodeId, previousNodeId, node}\n        if (res.node.nodeId > 0) {\n            var parent = nodeWithId(res.parentNodeId);\n            var previousNode = nodeWithId(res.previousNodeId);\n            var node = new DOMNode(exports, res.node);\n            parent.insertChildAfter(node, previousNode);\n        }\n    }\n\n    // WebInspector Event: DOM.childNodeRemoved\n    function _onChildNodeRemoved(event, res) {\n        // res = {parentNodeId, nodeId}\n        if (res.nodeId > 0) {\n            var node = nodeWithId(res.nodeId);\n            node.remove();\n        }\n    }\n\n    /** Apply a change\n     * @param {integer} start offset of the change\n     * @param {integer} end offset of the change\n     * @param {string} change text\n     */\n    function applyChange(from, to, text) {\n        var delta = from - to + text.length;\n        var node = nodeAtLocation(from);\n\n        // insert a text node\n        if (!node) {\n            if (!(/^\\s*$/).test(text)) {\n                console.warn(\"Inserting nodes not supported.\");\n                node = nodeBeforeLocation(from);\n            }\n        } else if (node.type === 3) {\n            // update a text node\n            var value = node.value.substr(0, from - node.location);\n            value += text;\n            value += node.value.substr(to - node.location);\n            node.value = value;\n            Inspector.DOM.setNodeValue(node.nodeId, node.value);\n        } else {\n            console.warn(\"Changing non-text nodes not supported.\");\n        }\n\n        // adjust the location of all nodes after the change\n        if (node) {\n            node.length += delta;\n            exports.root.each(function each(n) {\n                if (n.location > node.location) {\n                    n.location += delta;\n                }\n            });\n        }\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        $(Inspector.Page)\n            .on(\"frameNavigated.DOMAgent\", _onFrameNavigated)\n            .on(\"loadEventFired.DOMAgent\", _onLoadEventFired);\n        $(Inspector.DOM)\n            .on(\"documentUpdated.DOMAgent\", _onDocumentUpdated)\n            .on(\"setChildNodes.DOMAgent\", _onSetChildNodes)\n            .on(\"childNodeCountUpdated.DOMAgent\", _onChildNodeCountUpdated)\n            .on(\"childNodeInserted.DOMAgent\", _onChildNodeInserted)\n            .on(\"childNodeRemoved.DOMAgent\", _onChildNodeRemoved);\n        Inspector.Page.enable();\n        Inspector.Page.reload();\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Page).off(\".DOMAgent\");\n        $(Inspector.DOM).off(\".DOMAgent\");\n    }\n\n    // Export private functions\n    exports.nodeBeforeLocation = nodeBeforeLocation;\n    exports.allNodesAtLocation = allNodesAtLocation;\n    exports.nodeAtLocation = nodeAtLocation;\n    exports.nodeWithId = nodeWithId;\n    exports.removeNode = removeNode;\n    exports.addNode = addNode;\n    exports.requestChildNodes = requestChildNodes;\n    exports.applyChange = applyChange;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * HighlightAgent dispatches events for highlight requests from in-browser\n * highlight requests, and allows highlighting nodes and rules in the browser.\n *\n * Trigger \"highlight\" when a node should be highlighted\n */\ndefine('LiveDevelopment/Agents/HighlightAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/DOMAgent'],function HighlightAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n\n    var _highlight; // active highlight\n\n    // Remote Event: Highlight\n    function _onRemoteHighlight(event, res) {\n        var node;\n        if (res.value === \"1\") {\n            node = DOMAgent.nodeWithId(res.nodeId);\n        }\n        $(exports).triggerHandler(\"highlight\", node);\n    }\n\n    /** Hide in-browser highlighting */\n    function hide() {\n        switch (_highlight.type) {\n        case \"node\":\n            Inspector.DOM.hideHighlight();\n            break;\n        case \"css\":\n            RemoteAgent.call(\"hideHighlight\");\n            break;\n        }\n        _highlight = {};\n    }\n\n    /** Highlight a single node using DOM.highlightNode\n     * @param {DOMNode} node\n     */\n    function node(n) {\n        if (!Inspector.config.highlight) {\n            return;\n        }\n\n        // go to the parent of a text node\n        if (n && n.type === 3) {\n            n = n.parent;\n        }\n\n        // node cannot be highlighted\n        if (!n || !n.nodeId || n.type !== 1) {\n            return hide();\n        }\n\n        // node is already highlighted\n        if (_highlight.type === \"node\" && _highlight.ref === n.nodeId) {\n            return;\n        }\n\n        // highlight the node\n        _highlight = {type: \"node\", ref: n.nodeId};\n        Inspector.DOM.highlightNode(n.nodeId, Inspector.config.highlightConfig);\n    }\n\n    /** Highlight all nodes affected by a CSS rule\n     * @param {string} rule selector\n     */\n    function rule(name) {\n        if (_highlight.rule === name) {\n            return;\n        }\n        hide();\n        _highlight = {type: \"css\", ref: name};\n        RemoteAgent.call(\"highlightRule\", name);\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _highlight = {};\n        $(RemoteAgent).on(\"highlight.HighlightAgent\", _onRemoteHighlight);\n    }\n\n    /** Clean up */\n    function unload() {\n        $(RemoteAgent).off(\".HighlightAgent\");\n    }\n\n    // Export public functions\n    exports.hide = hide;\n    exports.node = node;\n    exports.rule = rule;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * HTMLDocument manages a single HTML source document\n *\n * # EDITING\n *\n * Editing the document will cause the corresponding node to be updated\n * by calling `applyChanges` on the DOMAgent. This will only work for\n * altering text nodes and will break when attempting to change DOM elements\n * or inserting or deleting nodes.\n *\n * # HIGHLIGHTING\n *\n * HTMLDocument supports highlighting nodes from the HighlightAgent and\n * highlighting the DOMNode corresponding to the cursor position in the\n * editor.\n */\ndefine('LiveDevelopment/Documents/HTMLDocument',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/HighlightAgent'],function HTMLDocumentModule(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var HighlightAgent = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /** Constructor\n     *\n     * @param Document the source document from Brackets\n     */\n    var HTMLDocument = function HTMLDocument(doc, editor) {\n        this.doc = doc;\n        this.editor = editor;\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onChange = this.onChange.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        $(HighlightAgent).on(\"highlight\", this.onHighlight);\n        $(this.editor).on(\"change\", this.onChange);\n        $(this.editor).on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n    };\n\n    /** Close the document */\n    HTMLDocument.prototype.close = function close() {\n        $(HighlightAgent).off(\"highlight\", this.onHighlight);\n        $(this.editor).off(\"change\", this.onChange);\n        $(this.editor).off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity by the editor */\n    HTMLDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n        var codeMirror = this.editor._codeMirror;\n        if (Inspector.config.highlight) {\n            var location = codeMirror.indexFromPos(codeMirror.getCursor());\n            var node = DOMAgent.allNodesAtLocation(location).pop();\n            HighlightAgent.node(node);\n        }\n    };\n\n    /** Triggered on change by the editor */\n    HTMLDocument.prototype.onChange = function onChange(event, editor, change) {\n        var codeMirror = this.editor._codeMirror;\n        while (change) {\n            var from = codeMirror.indexFromPos(change.from);\n            var to = codeMirror.indexFromPos(change.to);\n            var text = change.text.join(\"\\n\");\n            DOMAgent.applyChange(from, to, text);\n            change = change.next;\n        }\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    HTMLDocument.prototype.onHighlight = function onHighlight(node) {\n        if (!node || !node.location) {\n            if (this._highlight) {\n                this._highlight.clear();\n                delete this._highlight;\n            }\n            return;\n        }\n        var codeMirror = this.editor._codeMirror;\n        var to, from = codeMirror.posFromIndex(node.location);\n        if (node.closeLocation) {\n            to = node.closeLocation + node.closeLength;\n        } else {\n            to = node.location + node.length;\n        }\n        to = codeMirror.posFromIndex(to);\n        if (this._highlight) {\n            this._highlight.clear();\n        }\n        this._highlight = codeMirror.markText(from, to, \"highlight\");\n    };\n\n    // Export the class\n    module.exports = HTMLDocument;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, PathUtils */\n\n/**\n * CSSAgent keeps track of loaded style sheets and allows reloading them\n * from a {Document}.\n */\n\ndefine('LiveDevelopment/Agents/CSSAgent',['require','exports','module','thirdparty/path-utils/path-utils.min','LiveDevelopment/Inspector/Inspector'],function CSSAgent(require, exports, module) {\n    \n\n    require(\"thirdparty/path-utils/path-utils.min\");\n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _load; // {$.Deferred} load promise\n    var _urlToStyle; // {url -> loaded} style definition\n\n    /** \n     * Create a canonicalized version of the given URL, stripping off query strings and hashes.\n     * @param {string} url the URL to canonicalize\n     * @return the canonicalized URL\n     */\n    function _canonicalize(url) {\n        return PathUtils.parseUrl(url).hrefNoSearch;\n    }\n\n    // WebInspector Event: Page.loadEventFired\n    function _onLoadEventFired(event, res) {\n        // res = {timestamp}\n        _urlToStyle = {};\n        Inspector.CSS.getAllStyleSheets(function onGetAllStyleSheets(res) {\n            var i, header;\n            for (i in res.headers) {\n                header = res.headers[i];\n                _urlToStyle[_canonicalize(header.sourceURL)] = header;\n            }\n            _load.resolve();\n        });\n    }\n\n    /** Get a style sheet for a url\n     * @param {string} url\n     */\n    function styleForURL(url) {\n        return _urlToStyle[_canonicalize(url)];\n    }\n\n    /** Get a list of all loaded stylesheet files by URL */\n    function getStylesheetURLs() {\n        var urls = [], url;\n        for (url in _urlToStyle) {\n            if (_urlToStyle.hasOwnProperty(url)) {\n                urls.push(url);\n            }\n        }\n        return urls;\n    }\n\n    /** Reload a CSS style sheet from a document\n     * @param {Document} document\n     */\n    function reloadCSSForDocument(doc) {\n        var style = styleForURL(doc.url);\n        console.assert(style, \"Style Sheet for document not loaded: \" + doc.url);\n        Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());\n    }\n\n    /** Empties a CSS style sheet given a document that has been deleted\n     * @param {Document} document\n     */\n    function clearCSSForDocument(doc) {\n        var style = styleForURL(doc.url);\n        console.assert(style, \"Style Sheet for document not loaded: \" + doc.url);\n        Inspector.CSS.setStyleSheetText(style.styleSheetId, \"\");\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _load = new $.Deferred();\n        $(Inspector.Page).on(\"loadEventFired.CSSAgent\", _onLoadEventFired);\n        return _load.promise();\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Page).off(\".CSSAgent\");\n    }\n\n    // Export public functions\n    exports.styleForURL = styleForURL;\n    exports.getStylesheetURLs = getStylesheetURLs;\n    exports.reloadCSSForDocument = reloadCSSForDocument;\n    exports.clearCSSForDocument = clearCSSForDocument;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * CSSDocument manages a single CSS source document\n *\n * # EDITING\n *\n * Editing the document will cause the style sheet to be reloaded via the\n * CSSAgent, which immediately updates the appearance of the rendered document.\n *\n * # HIGHLIGHTING\n *\n * CSSDocument supports highlighting nodes from the HighlightAgent and\n * highlighting all DOMNode corresponding to the rule at the cursor position\n * in the editor.\n *\n * # EVENTS\n *\n * CSSDocument dispatches these events:\n *  deleted - When the file for the underlying Document has been deleted. The\n *      2nd argument to the listener will be this CSSDocument.\n */\ndefine('LiveDevelopment/Documents/CSSDocument',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/CSSAgent','LiveDevelopment/Agents/HighlightAgent'],function CSSDocumentModule(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var CSSAgent = require(\"LiveDevelopment/Agents/CSSAgent\");\n    var HighlightAgent = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /** Constructor\n     *\n     * @param Document the source document from Brackets\n     */\n    var CSSDocument = function CSSDocument(doc, editor, inspector) {\n        this.doc = doc;\n\n        // FUTURE: Highlighting is currently disabled, since this code doesn't yet know\n        // how to deal with different editors pointing at the same document.\n/*\n        this.editor = editor;\n        this._highlight = [];\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        $(HighlightAgent).on(\"highlight\", this.onHighlight);\n*/\n\n        // Add a ref to the doc since we're listening for change events\n        this.doc.addRef();\n        this.onChange = this.onChange.bind(this);\n        this.onDeleted = this.onDeleted.bind(this);\n        $(this.doc).on(\"change\", this.onChange);\n        $(this.doc).on(\"deleted\", this.onDeleted);\n\n/*\n        $(this.editor).on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n*/\n\n        // get the style sheet\n        this.styleSheet = CSSAgent.styleForURL(this.doc.url);\n\n        // WebInspector Command: CSS.getStyleSheet\n        Inspector.CSS.getStyleSheet(this.styleSheet.styleSheetId, function callback(res) {\n            // res = {styleSheet}\n            this.rules = res.styleSheet.rules;\n        }.bind(this));\n\n        // If the CSS document is dirty, push the changes into the browser now\n        if (doc.isDirty) {\n            CSSAgent.reloadCSSForDocument(this.doc);\n        }\n    };\n\n    /** Get the browser version of the StyleSheet object */\n    CSSDocument.prototype.getStyleSheetFromBrowser = function getStyleSheetFromBrowser() {\n        var deferred = new $.Deferred();\n\n        // WebInspector Command: CSS.getStyleSheet\n        Inspector.CSS.getStyleSheet(this.styleSheet.styleSheetId, function callback(res) {\n            // res = {styleSheet}\n            if (res.styleSheet) {\n                deferred.resolve(res.styleSheet);\n            } else {\n                deferred.reject();\n            }\n        });\n\n        return deferred.promise();\n    };\n\n    /** Get the browser version of the source */\n    CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() {\n        var deferred = new $.Deferred();\n\n        this.getStyleSheetFromBrowser().done(function onDone(styleSheet) {\n            deferred.resolve(styleSheet.text);\n        }).fail(function onFail() {\n            deferred.reject();\n        });\n\n        return deferred.promise();\n    };\n\n    /** Close the document */\n    CSSDocument.prototype.close = function close() {\n        $(this.doc).off(\"change\", this.onChange);\n        $(this.doc).off(\"deleted\", this.onDeleted);\n        this.doc.releaseRef();\n/*\n        $(HighlightAgent).off(\"highlight\", this.onHighlight);\n        $(this.editor).off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n*/\n    };\n\n    // find a rule in the given rules\n    CSSDocument.prototype.ruleAtLocation = function ruleAtLocation(location) {\n        var i, rule;\n        for (i in this.rules) {\n            rule = this.rules[i];\n            if (rule.selectorRange.start <= location && location <= rule.style.range.end) {\n                return rule;\n            }\n        }\n        return null;\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity of the editor */\n    CSSDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n        if (Inspector.config.highlight) {\n            var codeMirror = this.editor._codeMirror;\n            var location = codeMirror.indexFromPos(codeMirror.getCursor());\n            var rule = this.ruleAtLocation(location);\n            if (rule) {\n                HighlightAgent.rule(rule.selectorText);\n            } else {\n                HighlightAgent.hide();\n            }\n        }\n    };\n\n    /** Triggered whenever the Document is edited */\n    CSSDocument.prototype.onChange = function onChange(event, editor, change) {\n        // brute force: update the CSS\n        CSSAgent.reloadCSSForDocument(this.doc);\n    };\n    /** Triggered if the Document's file is deleted */\n    CSSDocument.prototype.onDeleted = function onDeleted(event, editor, change) {\n        // clear the CSS\n        CSSAgent.clearCSSForDocument(this.doc);\n\n        // shut down, since our Document is now dead\n        this.close();\n        $(this).triggerHandler(\"deleted\", [this]);\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    CSSDocument.prototype.onHighlight = function onHighlight(node) {\n        // clear an existing highlight\n        var i;\n        for (i in this._highlight) {\n            this._highlight[i].clear();\n        }\n        this._highlight = [];\n        if (!node || !node.location) {\n            return;\n        }\n\n        // WebInspector Command: CSS.getMatchedStylesForNode\n        Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) {\n            // res = {matchedCSSRules, pseudoElements, inherited}\n            var codeMirror = this.editor._codeMirror;\n            var i, rule, from, to;\n            for (i in res.matchedCSSRules) {\n                rule = res.matchedCSSRules[i];\n                if (rule.ruleId && rule.ruleId.styleSheetId === this.styleSheet.styleSheetId) {\n                    from = codeMirror.posFromIndex(rule.selectorRange.start);\n                    to = codeMirror.posFromIndex(rule.style.range.end);\n                    this._highlight.push(codeMirror.markText(from, to, \"highlight\"));\n                }\n            }\n        }.bind(this));\n    };\n\n    // Export the class\n    module.exports = CSSDocument;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * ScriptAgent tracks all executed scripts, defines internal breakpoints, and\n * interfaces with the remote debugger.\n */\ndefine('LiveDevelopment/Agents/ScriptAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent'],function ScriptAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n\n    var _load; // the load promise\n    var _urlToScript; // url -> script info\n    var _idToScript; // id -> script info\n    var _insertTrace; // the last recorded trace of a DOM insertion\n\n    /** Add a call stack trace to a node\n     * @param {integer} node id\n     * @param [{Debugger.CallFrame}] call stack\n     */\n    function _addTraceToNode(nodeId, trace) {\n        var node = DOMAgent.nodeWithId(nodeId);\n        node.trace = trace;\n    }\n\n    // TODO: should the parameter to this be an ID rather than a URL?\n    /** Get the script information for a given url\n     * @param {string} url\n     */\n    function scriptWithId(url) {\n        return _idToScript[url];\n    }\n\n    // TODO: Strip off query/hash strings from URL (see CSSAgent._canonicalize())\n    /** Get the script information for a given url\n     * @param {string} url\n     */\n    function scriptForURL(url) {\n        return _urlToScript[url];\n    }\n\n    // DOMAgent Event: Document root loaded\n    function _onGetDocument(event, res) {\n        Inspector.DOMDebugger.setDOMBreakpoint(res.root.nodeId, \"subtree-modified\");\n        _load.resolve();\n    }\n\n    // WebInspector Event: DOM.childNodeInserted\n    function _onChildNodeInserted(event, res) {\n        // res = {parentNodeId, previousNodeId, node}\n        if (_insertTrace) {\n            var node = DOMAgent.nodeWithId(res.node.nodeId);\n            node.trace = _insertTrace;\n            _insertTrace = undefined;\n        }\n    }\n\n    // TODO: Strip off query/hash strings from URL (see CSSAgent._canonicalize())\n    // WebInspector Event: Debugger.scriptParsed\n    function _onScriptParsed(event, res) {\n        // res = {scriptId, url, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL}\n        _idToScript[res.scriptId] = res;\n        _urlToScript[res.url] = res;\n    }\n\n    // WebInspector Event: Debugger.scriptFailedToParse\n    function _onScriptFailedToParse(event, res) {\n        // res = {url, scriptSource, startLine, errorLine, errorMessage}\n    }\n\n    // WebInspector Event: Debugger.paused\n    function _onPaused(event, res) {\n        // res = {callFrames, reason, data}\n        switch (res.reason) {\n\n        // Exception\n        case \"exception\":\n            Inspector.Debugger.resume();\n            // var callFrame = res.callFrames[0];\n            // var script = scriptWithId(callFrame.location.scriptId);\n            break;\n\n        // DOMBreakpoint\n        case \"DOM\":\n            Inspector.Debugger.resume();\n            if (res.data.type === \"subtree-modified\" && res.data.insertion === true) {\n                _insertTrace = res.callFrames;\n            }\n            break;\n        }\n\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _urlToScript = {};\n        _idToScript = {};\n        _load = new $.Deferred();\n        Inspector.Debugger.enable();\n        Inspector.Debugger.setPauseOnExceptions(\"uncaught\");\n        $(DOMAgent).on(\"getDocument.ScriptAgent\", _onGetDocument);\n        $(Inspector.Debugger)\n            .on(\"scriptParsed.ScriptAgent\", _onScriptParsed)\n            .on(\"scriptFailedToParse.ScriptAgent\", _onScriptFailedToParse)\n            .on(\"paused.ScriptAgent\", _onPaused);\n        $(Inspector.DOM).on(\"childNodeInserted.ScriptAgent\", _onChildNodeInserted);\n        return _load;\n    }\n\n    /** Clean up */\n    function unload() {\n        $(DOMAgent).off(\".ScriptAgent\");\n        $(Inspector.Debugger).off(\".ScriptAgent\");\n        $(Inspector.DOM).off(\".ScriptAgent\");\n    }\n\n    // Export public functions\n    exports.scriptWithId = scriptWithId;\n    exports.scriptForURL = scriptForURL;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * JSDocument manages a single JavaScript source document\n *\n * # EDITING\n *\n * Editing the document will cause the script to be reloaded via the\n * ScriptAgent, which updates the implementation of all functions without\n * loosing any state. To support redrawing canvases, jQuery must be loaded\n * and a rerender method must be attached to every canvas that clears and\n * renders the canvas.\n *\n * # HIGHLIGHTING\n *\n * JSDocument supports highlighting nodes from the HighlightAgent. Support\n * for highlighting the nodes that were created / touched by the current\n * line is missing.\n */\ndefine('LiveDevelopment/Documents/JSDocument',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/ScriptAgent','LiveDevelopment/Agents/HighlightAgent'],function JSDocumentModule(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var ScriptAgent = require(\"LiveDevelopment/Agents/ScriptAgent\");\n    var HighlightAgent = require(\"LiveDevelopment/Agents/HighlightAgent\");\n\n    /** Constructor\n     *\n     * @param {Document} the source document\n     */\n    var JSDocument = function JSDocument(doc, editor) {\n        this.doc = doc;\n        this.editor = editor;\n        this.script = ScriptAgent.scriptForURL(this.doc.url);\n        this.onHighlight = this.onHighlight.bind(this);\n        this.onChange = this.onChange.bind(this);\n        this.onCursorActivity = this.onCursorActivity.bind(this);\n        $(HighlightAgent).on(\"highlight\", this.onHighlight);\n        $(this.editor).on(\"change\", this.onChange);\n        $(this.editor).on(\"cursorActivity\", this.onCursorActivity);\n        this.onCursorActivity();\n    };\n\n    /** Close the document */\n    JSDocument.prototype.close = function close() {\n        $(HighlightAgent).off(\"highlight\", this.onHighlight);\n        $(this.editor).off(\"change\", this.onChange);\n        $(this.editor).off(\"cursorActivity\", this.onCursorActivity);\n        this.onHighlight();\n    };\n\n\n    /** Event Handlers *******************************************************/\n\n    /** Triggered on cursor activity by the editor */\n    JSDocument.prototype.onCursorActivity = function onCursorActivity(event, editor) {\n    };\n\n    /** Triggered on change by the editor */\n    JSDocument.prototype.onChange = function onChange(event, editor, change) {\n        var src = this.doc.getText();\n        Inspector.Debugger.setScriptSource(this.script.scriptId, src, function onSetScriptSource(res) {\n            Inspector.Runtime.evaluate(\"if($)$(\\\"canvas\\\").each(function(i,e){if(e.rerender)e.rerender()})\");\n        }.bind(this));\n    };\n\n    /** Triggered by the HighlightAgent to highlight a node in the editor */\n    JSDocument.prototype.onHighlight = function onHighlight(node) {\n        // clear an existing highlight\n        var codeMirror = this.editor._codeMirror;\n        var i;\n        for (i in this._highlight) {\n            codeMirror.setLineClass(this._highlight[i]);\n        }\n        this._highlight = [];\n        if (!node || !node.trace) {\n            return;\n        }\n\n        // go through the trace and find highlight the lines of this script\n        var callFrame, line;\n        for (i in node.trace) {\n            callFrame = node.trace[i];\n            if (callFrame.location && callFrame.location.scriptId === this.script.scriptId) {\n                line = callFrame.location.lineNumber;\n                codeMirror.setLineClass(line, \"highlight\");\n                this._highlight.push(line);\n            }\n        }\n    };\n\n    // Export the class\n    module.exports = JSDocument;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * ConsoleAgent forwards all console message from the remote console to the\n * local console.\n */\ndefine('LiveDevelopment/Agents/ConsoleAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector'],function ConsoleAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _lastMessage; // {Console.ConsoleMessage} the last received message\n\n    /** Log a remote message to the local console\n     * @param {Console.ConsoleMessage} message\n     */\n    function _log(message) {\n        var level = message.level;\n        if (level === \"warning\") {\n            level = \"warn\";\n        }\n        var text = \"ConsoleAgent: \" + message.text;\n        if (message.stackTrace) {\n            var callFrame = message.stackTrace[0];\n            text += \" in \" + callFrame.functionName + \":\" + callFrame.columnNumber;\n        }\n        console[level](text);\n    }\n\n    // WebInspector Event: Console.messageAdded\n    function _onMessageAdded(event, res) {\n        // res = {message}\n        _lastMessage = res.message;\n        _log(_lastMessage);\n    }\n\n    // WebInspector Event: Console.messageRepeatCountUpdated\n    function _onMessageRepeatCountUpdated(event, res) {\n        // res = {count}\n        if (_lastMessage) {\n            _log(_lastMessage);\n        }\n    }\n\n    // WebInspector Event: Console.messagesCleared\n    function _onMessagesCleared(event, res) {\n        // res = {}\n    }\n\n    /** Initialize the agent */\n    function load() {\n        Inspector.Console.enable();\n        $(Inspector.Console)\n            .on(\"messageAdded.ConsoleAgent\", _onMessageAdded)\n            .on(\"messageRepeatCountUpdated.ConsoleAgent\", _onMessageRepeatCountUpdated)\n            .on(\"messagesCleared.ConsoleAgent\", _onMessagesCleared);\n    }\n\n    /** Clean up */\n    function unload() {\n        $(Inspector.Console).off(\".ConsoleAgent\");\n    }\n\n    // Export public functions\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * NetworkAgent tracks all resources loaded by the remote debugger. Use\n * `wasURLRequested(url)` to query whether a resource was loaded.\n */\ndefine('LiveDevelopment/Agents/NetworkAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector'],function NetworkAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    var _urlRequested; // url -> request info\n\n    /** Return the URL without the query string\n     * @param {string} URL\n     */\n    function _urlWithoutQueryString(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Return the resource information for a given URL\n     * @param {string} url\n     */\n    function wasURLRequested(url) {\n        return _urlRequested && _urlRequested[url];\n    }\n\n    // WebInspector Event: Network.requestWillBeSent\n    function _onRequestWillBeSent(event, res) {\n        // res = {requestId, frameId, loaderId, documentURL, request, timestamp, initiator, stackTrace, redirectResponse}\n        var url = _urlWithoutQueryString(res.request.url);\n        _urlRequested[url] = true;\n    }\n\n    /** Initialize the agent */\n    function load() {\n        _urlRequested = {};\n        Inspector.Network.enable();\n        $(Inspector.Network).on(\"requestWillBeSent.NetworkAgent\", _onRequestWillBeSent);\n    }\n\n    /** Unload the agent */\n    function unload() {\n        $(Inspector.Network).off(\".NetworkAgent\");\n    }\n\n    // Export public functions\n    exports.wasURLRequested = wasURLRequested;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, brackets, $, window */\n\n/**\n * GotoAgent constructs and responds to the in-browser goto dialog.\n */\ndefine('LiveDevelopment/Agents/GotoAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/ScriptAgent','LiveDevelopment/Agents/RemoteAgent','document/DocumentManager','editor/EditorManager'],function GotoAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var ScriptAgent = require(\"LiveDevelopment/Agents/ScriptAgent\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n\n    var DocumentManager = require(\"document/DocumentManager\");\n    var EditorManager = require(\"editor/EditorManager\");\n\n    /** Return the URL without the query string\n     * @param {string} URL\n     */\n    function _urlWithoutQueryString(url) {\n        var index = url.search(/[#\\?]/);\n        if (index >= 0) {\n            url = url.substr(0, index);\n        }\n        return url;\n    }\n\n    /** Get the file component of the given url\n     * @param {string} URL\n     */\n    function _fileFromURL(url) {\n        var comp = url.split(\"/\");\n        return comp[comp.length - 1];\n    }\n\n    /** Make the given node a target for goto\n     * @param [] targets array\n     * @param {DOMNode} node\n     */\n    function _makeHTMLTarget(targets, node) {\n        if (node.location) {\n            var target = {};\n            var url = DOMAgent.url;\n            var location = node.location;\n            if (node.canHaveChildren()) {\n                location += node.length;\n            }\n            url += \":\" + location;\n            var name = \"&lt;\" + node.name + \"&gt;\";\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"html\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Make the given css rule a target for goto\n     * @param [] targets array\n     * @param {CSS.Rule} node\n     */\n    function _makeCSSTarget(targets, rule) {\n        if (rule.sourceURL) {\n            var target = {};\n            var url = rule.sourceURL;\n            url += \":\" + rule.style.range.start;\n            var name = rule.selectorText;\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"css\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Make the given javascript callFrame the target for goto\n     * @param [] targets array\n     * @param {Debugger.CallFrame} node\n     */\n    function _makeJSTarget(targets, callFrame) {\n        var script = ScriptAgent.scriptWithId(callFrame.location.scriptId);\n        if (script && script.url) {\n            var target = {};\n            var url = script.url;\n            url += \":\" + callFrame.location.lineNumber + \",\" + callFrame.location.columnNumber;\n            var name = callFrame.functionName;\n            if (name === \"\") {\n                name = \"anonymous function\";\n            }\n            var file = _fileFromURL(url);\n            targets.push({\"type\": \"js\", \"url\": url, \"name\": name, \"file\": file});\n        }\n    }\n\n    /** Gather options where to go to from the given source node */\n    function _onRemoteShowGoto(event, res) {\n        // res = {nodeId, name, value}\n        var node = DOMAgent.nodeWithId(res.nodeId);\n\n        // get all css rules that apply to the given node\n        Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onMatchedStyles(res) {\n            var i, callFrame, name, script, url, rule, targets = [];\n            _makeHTMLTarget(targets, node);\n            for (i in node.trace) {\n                _makeJSTarget(targets, node.trace[i]);\n            }\n            for (i in res.matchedCSSRules) {\n                _makeCSSTarget(targets, res.matchedCSSRules[i]);\n            }\n            RemoteAgent.call(\"showGoto\", targets);\n        });\n    }\n\n    /** Point the master editor to the given location\n     * @param {integer} location in file\n     */\n    function openLocation(location, noFlash) {\n        var editor = EditorManager.getCurrentFullEditor();\n        var codeMirror = editor._codeMirror;\n        if (typeof location === \"number\") {\n            location = codeMirror.posFromIndex(location);\n        }\n        codeMirror.setCursor(location);\n        editor.focus();\n\n        if (!noFlash) {\n            codeMirror.setLineClass(location.line, \"flash\");\n            window.setTimeout(codeMirror.setLineClass.bind(codeMirror, location.line), 1000);\n        }\n    }\n\n    /** Open the editor at the given url and editor location\n     * @param {string} url\n     * @param {integer} optional location in file\n     */\n    function open(url, location, noFlash) {\n        console.assert(url.substr(0, 7) === \"file://\", \"Cannot open non-file URLs\");\n\n        var result = new $.Deferred();\n        \n        url = _urlWithoutQueryString(url);\n        // Extract the path, also strip the third slash when on Windows\n        var path = url.slice(brackets.platform === \"win\" ? 8 : 7);\n        var promise = DocumentManager.getDocumentForPath(path);\n        promise.done(function onDone(doc) {\n            DocumentManager.setCurrentDocument(doc);\n            if (location) {\n                openLocation(location, noFlash);\n            }\n            result.resolve();\n        });\n        promise.fail(function onErr(err) {\n            console.error(err);\n            result.reject(err);\n        });\n\n        return result.promise();\n    }\n\n    /** Go to the given source node */\n    function _onRemoteGoto(event, res) {\n        // res = {nodeId, name, value}\n        var location, url = res.value;\n        var matches = /^(.*):([^:]+)$/.exec(url);\n        if (matches) {\n            url = matches[1];\n            location = matches[2].split(\",\");\n            if (location.length === 1) {\n                location = parseInt(location[0], 10);\n            } else {\n                location = { line: parseInt(location[0], 10), ch: parseInt(location[1], 10) };\n            }\n        }\n        open(url, location);\n    }\n\n    /** Initialize the agent */\n    function load() {\n        $(RemoteAgent)\n            .on(\"showgoto.GotoAgent\", _onRemoteShowGoto)\n            .on(\"goto.GotoAgent\", _onRemoteGoto);\n    }\n\n    /** Initialize the agent */\n    function unload() {\n        $(RemoteAgent).off(\".GotoAgent\");\n    }\n\n    // Export public functions\n    exports.openLocation = openLocation;\n    exports.open = open;\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $ */\n\n/**\n * EditAgent propagates changes from the in-document editor to the source\n * document.\n */\ndefine('LiveDevelopment/Agents/EditAgent',['require','exports','module','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/GotoAgent','editor/EditorManager'],function EditAgent(require, exports, module) {\n    \n\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n    var DOMAgent = require(\"LiveDevelopment/Agents/DOMAgent\");\n    var RemoteAgent = require(\"LiveDevelopment/Agents/RemoteAgent\");\n    var GotoAgent = require(\"LiveDevelopment/Agents/GotoAgent\");\n\n    var EditorManager = require(\"editor/EditorManager\");\n\n    /** Find changed characters\n     * @param {string} old value\n     * @param {string} changed value\n     * @return {from, to, text}\n     */\n    function _findChangedCharacters(oldValue, value) {\n        if (oldValue === value) {\n            return undefined;\n        }\n        var length = oldValue.length;\n        var index = 0;\n\n        // find the first character that changed\n        var i;\n        for (i = 0; i < length; i++) {\n            if (value[i] !== oldValue[i]) {\n                break;\n            }\n        }\n        index += i;\n        value = value.substr(i);\n        length -= i;\n\n        // find the last character that changed\n        for (i = 0; i < length; i++) {\n            if (value[value.length - 1 - i] !== oldValue[oldValue.length - 1 - i]) {\n                break;\n            }\n        }\n        length -= i;\n        value = value.substr(0, value.length - i);\n\n        return { from: index, to: index + length, text: value };\n    }\n\n    // Remote Event: Go to the given source node\n    function _onRemoteEdit(event, res) {\n        // res = {nodeId, name, value}\n        var node = DOMAgent.nodeWithId(res.nodeId);\n        node = node.children[0];\n        if (!node.location) {\n            return;\n        }\n        GotoAgent.open(DOMAgent.url);\n        var editor = EditorManager.getCurrentFullEditor();\n        var codeMirror = editor._codeMirror;\n        var change = _findChangedCharacters(node.value, res.value);\n        if (change) {\n            var from = codeMirror.posFromIndex(node.location + change.from);\n            var to = codeMirror.posFromIndex(node.location + change.to);\n            editor.document.replaceRange(change.text, from, to);\n\n            var newPos = codeMirror.posFromIndex(node.location + change.from + change.text.length);\n            editor.setCursorPos(newPos.line, newPos.ch);\n        }\n    }\n\n    /** Initialize the agent */\n    function load() {\n        $(RemoteAgent).on(\"edit.EditAgent\", _onRemoteEdit);\n    }\n\n    /** Initialize the agent */\n    function unload() {\n        $(RemoteAgent).off(\".EditAgent\");\n    }\n\n    // Export public functions\n    exports.load = load;\n    exports.unload = unload;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, FileError, brackets, window */\n\n/**\n * LiveDevelopment manages the Inspector, all Agents, and the active LiveDocument\n *\n * # STARTING\n *\n * To start a session call `open`. This will read the currentDocument from brackets,\n * launch the LiveBrowser (currently Chrome) with the remote debugger port open,\n * establish the Inspector connection to the remote debugger, and finally load all\n * agents.\n *\n * # STOPPING\n *\n * To stop a session call `close`. This will close the active browser window,\n * disconnect the Inspector, unload all agents, and clean up.\n *\n * # STATUS\n *\n * Status updates are dispatched as `statusChange` jQuery events. The status\n * codes are:\n *\n * -1: Error\n * 0: Inactive\n * 1: Connecting to the remote debugger\n * 2: Loading agents\n * 3: Active\n */\ndefine('LiveDevelopment/LiveDevelopment',['require','exports','module','document/DocumentManager','editor/EditorManager','utils/NativeApp','widgets/Dialogs','strings','utils/StringUtils','LiveDevelopment/Inspector/Inspector','LiveDevelopment/Documents/HTMLDocument','LiveDevelopment/Documents/CSSDocument','LiveDevelopment/Documents/JSDocument','LiveDevelopment/Agents/ConsoleAgent','LiveDevelopment/Agents/RemoteAgent','LiveDevelopment/Agents/NetworkAgent','LiveDevelopment/Agents/DOMAgent','LiveDevelopment/Agents/CSSAgent','LiveDevelopment/Agents/ScriptAgent','LiveDevelopment/Agents/HighlightAgent','LiveDevelopment/Agents/GotoAgent','LiveDevelopment/Agents/EditAgent'],function LiveDevelopment(require, exports, module) {\n    \n\n    // Status Codes\n    var STATUS_ERROR          = exports.STATUS_ERROR = -1;\n    var STATUS_INACTIVE       = exports.STATUS_INACTIVE = 0;\n    var STATUS_CONNECTING     = exports.STATUS_CONNECTING = 1;\n    var STATUS_LOADING_AGENTS = exports.STATUS_LOADING_AGENTS = 2;\n    var STATUS_ACTIVE         = exports.STATUS_ACTIVE = 3;\n\n    var DocumentManager = require(\"document/DocumentManager\");\n    var EditorManager = require(\"editor/EditorManager\");\n    var NativeApp = require(\"utils/NativeApp\");\n    var Dialogs = require(\"widgets/Dialogs\");\n    var Strings = require(\"strings\");\n    var StringUtils = require(\"utils/StringUtils\");\n\n    // Inspector\n    var Inspector = require(\"LiveDevelopment/Inspector/Inspector\");\n\n    // Documents\n    var HTMLDocument = require(\"LiveDevelopment/Documents/HTMLDocument\");\n    var CSSDocument = require(\"LiveDevelopment/Documents/CSSDocument\");\n    var JSDocument = require(\"LiveDevelopment/Documents/JSDocument\");\n\n    // Agents\n    var agents = {\n        \"console\": require(\"LiveDevelopment/Agents/ConsoleAgent\"),\n        \"remote\": require(\"LiveDevelopment/Agents/RemoteAgent\"),\n        \"network\": require(\"LiveDevelopment/Agents/NetworkAgent\"),\n        \"dom\": require(\"LiveDevelopment/Agents/DOMAgent\"),\n        \"css\": require(\"LiveDevelopment/Agents/CSSAgent\"),\n        \"script\": require(\"LiveDevelopment/Agents/ScriptAgent\"),\n        \"highlight\": require(\"LiveDevelopment/Agents/HighlightAgent\"),\n        \"goto\": require(\"LiveDevelopment/Agents/GotoAgent\"),\n        \"edit\": require(\"LiveDevelopment/Agents/EditAgent\")\n    };\n\n    // Some agents are still experimental, so we don't enable them all by default\n    // However, extensions can enable them by calling enableAgent().\n    // This object is used as a set (thus all properties have the value 'true').\n    // Property names should match property names in the 'agents' object.\n    var _enabledAgentNames = {\n        \"console\": true,\n        \"remote\": true,\n        \"network\": true,\n        \"dom\": true,\n        \"css\": true\n    };\n    // store the names (matching property names in the 'agent' object) of agents that we've loaded\n    var _loadedAgentNames = [];\n\n    var _htmlDocumentPath; // the path of the html file open for live development\n    var _liveDocument; // the document open for live editing.\n    var _relatedDocuments; // CSS and JS documents that are used by the live HTML document\n\n    /** Augments the given Brackets document with information that's useful for live development. */\n    function _setDocInfo(doc) {\n        // FUTURE: some of these things should just be moved into core Document; others should\n        // be in a LiveDevelopment-specific object attached to the doc.\n        var matches = /^(.*\\/)(.+\\.([^.]+))$/.exec(doc.file.fullPath);\n        if (matches) {\n            var prefix = \"file://\";\n\n            // The file.fullPath on Windows starts with a drive letter (\"C:\").\n            // In order to make it a valid file: URL we need to add an \n            // additional slash to the prefix.\n            if (brackets.platform === \"win\") {\n                prefix += \"/\";\n            }\n\n            doc.extension = matches[3];\n            doc.url = encodeURI(prefix + doc.file.fullPath);\n\n            // the root represents the document that should be displayed in the browser\n            // for live development (the file for HTML files, index.html for others)\n            var fileName = /^html?$/.test(matches[3]) ? matches[2] : \"index.html\";\n            doc.root = {url: encodeURI(prefix + matches[1] + fileName)};\n        }\n    }\n\n    /** Get the current document from the document manager\n     * _adds extension, url and root to the document\n     */\n    function _getCurrentDocument() {\n        var doc = DocumentManager.getCurrentDocument();\n        if (doc) {\n            _setDocInfo(doc);\n        }\n        return doc;\n    }\n\n    /** Determine which document class should be used for a given document\n     * @param {Document} document\n     */\n    function _classForDocument(doc) {\n        switch (doc.extension) {\n        case \"css\":\n            return CSSDocument;\n        /* FUTURE:\n        case \"js\":\n            return JSDocument;\n        case \"html\":\n        case \"htm\":\n            return HTMLDocument;\n        default:\n            throw \"Invalid document type: \" + doc.extension;\n        */\n        }\n\n        return null;\n    }\n\n    /**\n     * Removes the given CSS/JSDocument from _relatedDocuments. Signals that the\n     * given file is no longer associated with the HTML document that is live (e.g.\n     * if the related file has been deleted on disk).\n     */\n    function _handleRelatedDocumentDeleted(event, liveDoc) {\n        var index = _relatedDocuments.indexOf(liveDoc);\n        if (index !== -1) {\n            $(liveDoc).on(\"deleted\", _handleRelatedDocumentDeleted);\n            _relatedDocuments.splice(index, 1);\n        }\n    }\n\n    /** Close a live document */\n    function _closeDocument() {\n        if (_liveDocument) {\n            _liveDocument.close();\n            _liveDocument = undefined;\n        }\n        if (_relatedDocuments) {\n            _relatedDocuments.forEach(function (liveDoc) {\n                liveDoc.close();\n                $(liveDoc).off(\"deleted\", _handleRelatedDocumentDeleted);\n            });\n            _relatedDocuments = undefined;\n        }\n    }\n\n    /** Create a live version of a Brackets document */\n    function _createDocument(doc, editor) {\n        var DocClass = _classForDocument(doc);\n        if (DocClass) {\n            return new DocClass(doc, editor);\n        } else {\n            return null;\n        }\n    }\n\n    /** Convert a file: URL to a local full file path */\n    function _urlToPath(url) {\n        var path;\n        if (url.indexOf(\"file://\") === 0) {\n            path = url.slice(7);\n            if (path && brackets.platform === \"win\" && path.charAt(0) === \"/\") {\n                path = path.slice(1);\n            }\n        }\n        return decodeURI(path);\n    }\n\n    /** Open a live document\n     * @param {Document} source document to open\n     */\n    function _openDocument(doc, editor) {\n        _closeDocument();\n        _liveDocument = _createDocument(doc, editor);\n\n        // Gather related CSS documents.\n        // FUTURE: Gather related JS documents as well.\n        _relatedDocuments = [];\n        agents.css.getStylesheetURLs().forEach(function (url) {\n            // FUTURE: when we get truly async file handling, we might need to prevent other\n            // stuff from happening while we wait to add these listeners\n            DocumentManager.getDocumentForPath(_urlToPath(url))\n                .done(function (doc) {\n                    _setDocInfo(doc);\n                    var liveDoc = _createDocument(doc);\n                    if (liveDoc) {\n                        _relatedDocuments.push(liveDoc);\n                        $(liveDoc).on(\"deleted\", _handleRelatedDocumentDeleted);\n                    }\n                });\n        });\n    }\n\n    /** Unload the agents */\n    function unloadAgents() {\n        _loadedAgentNames.forEach(function (name) {\n            agents[name].unload();\n        });\n        _loadedAgentNames = [];\n    }\n\n    /** Load the agents */\n    function loadAgents() {\n        var name, promises = [];\n        for (name in _enabledAgentNames) {\n            if (_enabledAgentNames.hasOwnProperty(name) && agents[name].load) {\n                promises.push(agents[name].load());\n                _loadedAgentNames.push(name);\n            }\n        }\n        return promises;\n    }\n\n    /** Enable an agent. Takes effect next time a connection is made. Does not affect\n     *  current live development sessions.\n     *\n     *  @param {string} name of agent to enable\n     */\n    function enableAgent(name) {\n        if (agents.hasOwnProperty(name) && !_enabledAgentNames.hasOwnProperty(name)) {\n            _enabledAgentNames[name] = true;\n        }\n    }\n\n    /** Disable an agent. Takes effect next time a connection is made. Does not affect\n     *  current live development sessions.\n     *\n     *  @param {string} name of agent to disable\n     */\n    function disableAgent(name) {\n        if (_enabledAgentNames.hasOwnProperty(name)) {\n            delete _enabledAgentNames[name];\n        }\n    }\n\n    /** Update the status\n     * @param {integer} new status\n     */\n    function _setStatus(status) {\n        exports.status = status;\n        $(exports).triggerHandler(\"statusChange\", status);\n    }\n\n    /** Triggered by Inspector.error */\n    function _onError(event, error) {\n        var message = error.message;\n\n        // Additional information, like exactly which parameter could not be processed.\n        var data = error.data;\n        if (Array.isArray(data)) {\n            message += \"\\n\" + data.join(\"\\n\");\n        }\n\n        // Show the message, but include the error object for further information (e.g. error code)\n        console.error(message, error);\n    }\n\n    /** Run when all agents are loaded */\n    function _onLoad() {\n        var doc = _getCurrentDocument();\n        if (doc) {\n            var editor = EditorManager.getCurrentFullEditor();\n            _openDocument(doc, editor);\n        }\n        _setStatus(STATUS_ACTIVE);\n    }\n\n    /** Triggered by Inspector.connect */\n    function _onConnect(event) {\n        var promises = loadAgents();\n        _setStatus(STATUS_LOADING_AGENTS);\n        $.when.apply(undefined, promises).then(_onLoad, _onError);\n    }\n\n    /** Triggered by Inspector.disconnect */\n    function _onDisconnect(event) {\n        unloadAgents();\n        _closeDocument();\n        _setStatus(STATUS_INACTIVE);\n    }\n\n    /** Open the Connection and go live */\n    function open() {\n        var result = new $.Deferred(),\n            promise = result.promise();\n        var doc = _getCurrentDocument();\n        var browserStarted = false;\n        var retryCount = 0;\n\n        function showWrongDocError() {\n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_ERROR,\n                Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n                Strings.LIVE_DEV_NEED_HTML_MESSAGE\n            );\n            result.reject(\"WRONG_DOC\");\n        }\n\n        if (!doc || !doc.root) {\n            showWrongDocError();\n\n        } else {\n            // For Sprint 6, we only open live development connections for HTML files\n            // FUTURE: Remove this test when we support opening connections for different\n            // file types.\n            if (!doc.extension || doc.extension.indexOf(\"htm\") !== 0) {\n                showWrongDocError();\n                return promise;\n            }\n\n            _setStatus(STATUS_CONNECTING);\n            Inspector.connectToURL(doc.root.url).then(result.resolve, function onConnectFail(err) {\n                if (err === \"CANCEL\") {\n                    result.reject(err);\n                    return;\n                }\n                if (retryCount > 6) {\n                    _setStatus(STATUS_ERROR);\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_LIVE_DEVELOPMENT,\n                        Strings.LIVE_DEVELOPMENT_ERROR_TITLE,\n                        Strings.LIVE_DEVELOPMENT_ERROR_MESSAGE\n                    ).done(function (id) {\n                        if (id === Dialogs.DIALOG_BTN_OK) {\n                            // User has chosen to reload Chrome, quit the running instance\n                            _setStatus(STATUS_INACTIVE);\n                            NativeApp.closeLiveBrowser()\n                                .done(function () {\n                                    browserStarted = false;\n                                    window.setTimeout(function () {\n                                        open().then(result.resolve, result.reject);\n                                    });\n                                })\n                                .fail(function (err) {\n                                    // Report error?\n                                    _setStatus(STATUS_ERROR);\n                                    browserStarted = false;\n                                    result.reject(\"CLOSE_LIVE_BROWSER\");\n                                });\n                        } else {\n                            result.reject(\"CANCEL\");\n                        }\n                    });\n                    return;\n                }\n                retryCount++;\n\n                if (!browserStarted && exports.status !== STATUS_ERROR) {\n                    // If err === FileError.ERR_NOT_FOUND, it means a remote debugger connection\n                    // is available, but the requested URL is not loaded in the browser. In that\n                    // case we want to launch the live browser (to open the url in a new tab)\n                    // without using the --remote-debugging-port flag. This works around issues\n                    // on Windows where Chrome can't be opened more than once with the\n                    // --remote-debugging-port flag set.\n                    NativeApp.openLiveBrowser(\n                        doc.root.url,\n                        err !== FileError.ERR_NOT_FOUND\n                    )\n                        .done(function () {\n                            browserStarted = true;\n                        })\n                        .fail(function (err) {\n                            var message;\n\n                            _setStatus(STATUS_ERROR);\n                            if (err === FileError.NOT_FOUND_ERR) {\n                                message = Strings.ERROR_CANT_FIND_CHROME;\n                            } else {\n                                message = StringUtils.format(Strings.ERROR_LAUNCHING_BROWSER, err);\n                            }\n\n                            Dialogs.showModalDialog(\n                                Dialogs.DIALOG_ID_ERROR,\n                                Strings.ERROR_LAUNCHING_BROWSER_TITLE,\n                                message\n                            );\n\n                            result.reject(\"OPEN_LIVE_BROWSER\");\n                        });\n                }\n\n                if (exports.status !== STATUS_ERROR) {\n                    window.setTimeout(function retryConnect() {\n                        Inspector.connectToURL(doc.root.url).then(result.resolve, onConnectFail);\n                    }, 500);\n                }\n            });\n        }\n\n        return promise;\n    }\n\n    /** Close the Connection */\n    function close() {\n        if (Inspector.connected()) {\n            Inspector.Runtime.evaluate(\"window.close()\");\n        }\n        Inspector.disconnect();\n        _setStatus(STATUS_INACTIVE);\n    }\n\n    /** Triggered by a document change from the DocumentManager */\n    function _onDocumentChange() {\n        var doc = _getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        if (Inspector.connected()) {\n            if (agents.network && agents.network.wasURLRequested(doc.url)) {\n                _closeDocument();\n                var editor = EditorManager.getCurrentFullEditor();\n                _openDocument(doc, editor);\n            } else {\n                /* FUTURE: support live connections for docments other than html */\n                if (doc.extension && doc.extension.indexOf(\"htm\") === 0 && doc.file.fullPath !== _htmlDocumentPath) {\n                    close();\n                    window.setTimeout(open);\n                    _htmlDocumentPath = doc.file.fullPath;\n                }\n            }\n        } else if (exports.config.autoconnect) {\n            window.setTimeout(open);\n        }\n    }\n\n    function getLiveDocForPath(path) {\n        var docsToSearch = [];\n        if (_relatedDocuments) {\n            docsToSearch = docsToSearch.concat(_relatedDocuments);\n        }\n        if (_liveDocument) {\n            docsToSearch = docsToSearch.concat(_liveDocument);\n        }\n        var foundDoc;\n        docsToSearch.some(function matchesPath(ele) {\n            if (ele.doc.file.fullPath === path) {\n                foundDoc = ele;\n                return true;\n            }\n            return false;\n        });\n\n        return foundDoc;\n    }\n\n    /** Hide any active highlighting */\n    function hideHighlight() {\n        if (Inspector.connected() && agents.highlight) {\n            agents.highlight.hide();\n        }\n    }\n\n    /** Initialize the LiveDevelopment Session */\n    function init(theConfig) {\n        exports.config = theConfig;\n        $(Inspector).on(\"connect\", _onConnect)\n            .on(\"disconnect\", _onDisconnect)\n            .on(\"error\", _onError);\n        $(DocumentManager).on(\"currentDocumentChange\", _onDocumentChange);\n    }\n\n    // Export public functions\n    exports.agents = agents;\n    exports.open = open;\n    exports.close = close;\n    exports.enableAgent = enableAgent;\n    exports.disableAgent = disableAgent;\n    exports.getLiveDocForPath = getLiveDocForPath;\n    exports.hideHighlight = hideHighlight;\n    exports.init = init;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, forin: true, maxerr: 50, regexp: true */\n/*global define, $, less, window, XMLHttpRequest */\n\n/**\n * main integrates LiveDevelopment into Brackets\n *\n * This module creates two menu items:\n *\n *  \"Go Live\": open or close a Live Development session and visualize the status\n *  \"Highlight\": toggle source highlighting\n *\n * @require DocumentManager\n */\ndefine('LiveDevelopment/main',['require','exports','module','document/DocumentManager','command/Commands','LiveDevelopment/LiveDevelopment','LiveDevelopment/Inspector/Inspector','command/CommandManager','strings'],function main(require, exports, module) {\n    \n\n    var DocumentManager = require(\"document/DocumentManager\"),\n        Commands        = require(\"command/Commands\"),\n        LiveDevelopment = require(\"LiveDevelopment/LiveDevelopment\"),\n        Inspector       = require(\"LiveDevelopment/Inspector/Inspector\"),\n        CommandManager  = require(\"command/CommandManager\"),\n        Strings = require(\"strings\");\n\n    var config = {\n        debug: true, // enable debug output and helpers\n        autoconnect: false, // go live automatically after startup?\n        highlight: false, // enable highlighting?\n        highlightConfig: { // the highlight configuration for the Inspector\n            borderColor:  {r: 255, g: 229, b: 153, a: 0.66},\n            contentColor: {r: 111, g: 168, b: 220, a: 0.55},\n            marginColor:  {r: 246, g: 178, b: 107, a: 0.66},\n            paddingColor: {r: 147, g: 196, b: 125, a: 0.66},\n            showInfo: true\n        }\n    };\n    var _checkMark = \"✓\"; // Check mark character\n    // Status labels/styles are ordered: error, not connected, progress1, progress2, connected.\n    var _statusTooltip = [Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, Strings.LIVE_DEV_STATUS_TIP_PROGRESS1,\n                          Strings.LIVE_DEV_STATUS_TIP_PROGRESS2, Strings.LIVE_DEV_STATUS_TIP_CONNECTED];  // Status indicator tooltip\n    var _statusStyle = [\"warning\", \"\", \"info\", \"info\", \"success\"];  // Status indicator's CSS class\n    var _allStatusStyles = _statusStyle.join(\" \");\n\n    var _$btnGoLive; // reference to the GoLive button\n    var _$btnHighlight; // reference to the HighlightButton\n\n    /** Load Live Development LESS Style */\n    function _loadStyles() {\n        var request = new XMLHttpRequest();\n        request.open(\"GET\", \"LiveDevelopment/main.less\", true);\n        request.onload = function onLoad(event) {\n            var parser = new less.Parser();\n            parser.parse(request.responseText, function onParse(err, tree) {\n                console.assert(!err, err);\n                $(\"<style>\" + tree.toCSS() + \"</style>\")\n                    .appendTo(window.document.head);\n            });\n        };\n        request.send(null);\n    }\n\n    /**\n     * Change the appearance of a button. Omit text to remove any extra text; omit style to return to default styling;\n     * omit tooltip to leave tooltip unchanged.\n     */\n    function _setLabel($btn, text, style, tooltip) {\n        // Clear text/styles from previous status\n        $(\"span\", $btn).remove();\n        $btn.removeClass(_allStatusStyles);\n\n        // Set text/styles for new status\n        if (text && text.length > 0) {\n            $(\"<span class=\\\"label\\\">\")\n                .addClass(style)\n                .text(text)\n                .appendTo($btn);\n        } else {\n            $btn.addClass(style);\n        }\n\n        if (tooltip) {\n            $btn.attr(\"title\", tooltip);\n        }\n    }\n\n    /** Toggles LiveDevelopment and synchronizes the state of UI elements that reports LiveDevelopment status */\n    function _handleGoLiveCommand() {\n        if (LiveDevelopment.status >= LiveDevelopment.STATUS_CONNECTING) {\n            LiveDevelopment.close();\n            // TODO Ty: when checkmark support lands, remove checkmark\n        } else {\n            LiveDevelopment.open();\n            // TODO Ty: when checkmark support lands, add checkmark\n        }\n    }\n\n    /** Create the menu item \"Go Live\" */\n    function _setupGoLiveButton() {\n        _$btnGoLive = $(\"#toolbar-go-live\");\n        _$btnGoLive.click(function onGoLive() {\n            _handleGoLiveCommand();\n        });\n        $(LiveDevelopment).on(\"statusChange\", function statusChange(event, status) {\n            // status starts at -1 (error), so add one when looking up name and style\n            // See the comments at the top of LiveDevelopment.js for details on the \n            // various status codes.\n            _setLabel(_$btnGoLive, null, _statusStyle[status + 1], _statusTooltip[status + 1]);\n        });\n\n        // Initialize tooltip for 'not connected' state\n        _setLabel(_$btnGoLive, null, _statusStyle[1], _statusTooltip[1]);\n    }\n\n    /** Create the menu item \"Highlight\" */\n    function _setupHighlightButton() {\n        // TODO: this should be moved into index.html like the Go Live button once it's re-enabled\n        _$btnHighlight = $(\"<a href=\\\"#\\\">Highlight </a>\");\n        $(\".nav\").append($(\"<li>\").append(_$btnHighlight));\n        _$btnHighlight.click(function onClick() {\n            config.highlight = !config.highlight;\n            if (config.highlight) {\n                _setLabel(_$btnHighlight, _checkMark, \"success\");\n            } else {\n                _setLabel(_$btnHighlight);\n                LiveDevelopment.hideHighlight();\n            }\n        });\n        if (config.highlight) {\n            _setLabel(_$btnHighlight, _checkMark, \"success\");\n        }\n    }\n\n    /** Setup window references to useful LiveDevelopment modules */\n    function _setupDebugHelpers() {\n        window.ld = LiveDevelopment;\n        window.i = Inspector;\n        window.report = function report(params) { window.params = params; console.info(params); };\n    }\n\n    /** Initialize LiveDevelopment */\n    function init() {\n        Inspector.init(config);\n        LiveDevelopment.init(config);\n        _loadStyles();\n        _setupGoLiveButton();\n        /* _setupHighlightButton(); FUTURE - Highlight button */\n        if (config.debug) {\n            _setupDebugHelpers();\n        }\n    }\n    window.setTimeout(init);\n\n    CommandManager.register(Strings.CMD_LIVE_FILE_PREVIEW,  Commands.FILE_LIVE_FILE_PREVIEW, _handleGoLiveCommand);\n\n    // Export public functions\n    exports.init = init;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils */\n\n/*\n * Manages a collection of FileIndexes where each index maintains a list of information about\n * files that meet the criteria specified by the index. The indexes are created lazily when\n * they are queried and marked dirty when Brackets becomes active.\n *\n * TODO (issue 325 ) - FileIndexer doesn't currently add a file to the index when the user createa\n * a new file within brackets.\n *\n */\n\n\ndefine('project/FileIndexManager',['require','exports','module','file/NativeFileSystem','utils/PerfUtils','project/ProjectManager','widgets/Dialogs','strings'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PerfUtils           = require(\"utils/PerfUtils\"),\n        ProjectManager      = require(\"project/ProjectManager\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\");\n\n    /**\n     * All the indexes are stored in this object. The key is the name of the index\n     * and the value is a FileIndex. \n     */\n    var _indexList = {};\n\n    /**\n     * Tracks whether _indexList should be considered dirty and invalid. Calls that access\n     * any data in _indexList should call syncFileIndex prior to accessing the data.\n     * @type {boolean}\n     */\n    var _indexListDirty = true;\n\n    /** class FileIndex\n     *\n     * A FileIndex contains an array of fileInfos that meet the criteria specified by\n     * the filterFunction. FileInfo's in the fileInfo array should unique map to one file.\n     *  \n     * @constructor\n     * @param {!string} indexname\n     * @param {function({!entry})} filterFunction returns true to indicate the entry\n     *                             should be included in the index\n     */\n    function FileIndex(indexName, filterFunction) {\n        this.name = indexName;\n        this.fileInfos = [];\n        this.filterFunction = filterFunction;\n    }\n\n    /** class FileInfo\n     * \n     *  Class to hold info about a file that a FileIndex wishes to retain.\n     *\n     * @constructor\n     * @param {!string}\n     */\n    function FileInfo(entry) {\n        this.name = entry.name;\n        this.fullPath = entry.fullPath;\n    }\n\n\n    /**\n    * Adds a new index to _indexList and marks the list dirty \n    *\n    * A future performance optimization is to only build the new index rather than \n    * marking them all dirty\n    *\n    * @private\n    * @param {!string} indexName must be unque\n    * @param {!function({entry} filterFunction should return true to include an\n    *   entry in the index\n\n    */\n    function _addIndex(indexName, filterFunction) {\n        if (_indexList.hasOwnProperty(indexName)) {\n            throw new Error(\"Duplicate index name\");\n        }\n        if (typeof filterFunction !== \"function\") {\n            throw new Error(\"Invalid arguments\");\n        }\n\n        _indexList[indexName] = new FileIndex(indexName, filterFunction);\n\n        _indexListDirty = true;\n    }\n\n\n    /**\n    * Checks the entry against the filterFunction for each index and adds\n    * a fileInfo to the index if the entry meets the criteria. FileInfo's are\n    * shared between indexes.\n    *\n    * @private\n    * @param {!entry} entry to be added to the indexes\n    */\n    // future use when files are incrementally added\n    //\n    function _addFileToIndexes(entry) {\n\n        // skip invisible files\n        if (!ProjectManager.shouldShow(entry)) {\n            return;\n        }\n\n        var fileInfo = new FileInfo(entry);\n        //console.log(entry.name);\n  \n        $.each(_indexList, function (indexName, index) {\n            if (index.filterFunction(entry)) {\n                index.fileInfos.push(fileInfo);\n            }\n        });\n    }\n    \n  /**\n    * Error dialog when max files in index is hit\n    */\n    function _showMaxFilesDialog() {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_MAX_FILES_TITLE,\n            Strings.ERROR_MAX_FILES\n        );\n    }\n\n    /* Recursively visits all files that are descendent of dirEntry and adds\n    * files files to each index when the file matches the filter critera\n    * @private\n    * @param {!DirectoryEntry} dirEntry\n    * @returns {$.Promise}\n    */\n    function _scanDirectorySubTree(dirEntry) {\n        if (!dirEntry) {\n            throw new Error(\"Bad dirEntry passed to _scanDirectorySubTree\");\n        }\n\n        // keep track of directories as they are asynchronously read. We know we are done\n        // when dirInProgress becomes empty again.\n        var state = { fileCount: 0,\n                      dirInProgress: {},    // directory names that are in progress of being read\n                      dirError: {},         // directory names with read errors. key=dir path, value=error\n                      maxFilesHit: false    // used to show warning dialog only once\n                    };\n\n        var deferred = new $.Deferred();\n\n        // inner helper function\n        function _dirScanDone() {\n            var key;\n            for (key in state.dirInProgress) {\n                if (state.dirInProgress.hasOwnProperty(key)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _finishDirScan(dirEntry) {\n            //console.log(\"finished: \" + dirEntry.fullPath);\n            delete state.dirInProgress[dirEntry.fullPath];\n\n            if (_dirScanDone()) {\n                //console.log(\"dir scan completly done\");\n                deferred.resolve();\n            }\n        }\n\n        // inner helper function\n        function _scanDirectoryRecurse(dirEntry) {\n            // skip invisible directories\n            if (!ProjectManager.shouldShow(dirEntry)) {\n                return;\n            }\n\n            state.dirInProgress[dirEntry.fullPath] = true;\n            //console.log(\"started dir: \" + dirEntry.fullPath);\n\n            dirEntry.createReader().readEntries(\n                // success callback\n                function (entries) {\n                    // inspect all children of dirEntry\n                    entries.forEach(function (entry) {\n                        // For now limit the number of files that are indexed by preventing adding files\n                        // or scanning additional directories once a max has been hit. Also notify the \n                        // user once via a dialog. This limit could be increased\n                        // if files were indexed in a worker thread so scanning didn't block the UI\n                        if (state.fileCount > 10000) {\n                            if (!state.maxFilesHit) {\n                                state.maxFilesHit = true;\n                                _showMaxFilesDialog();\n                            }\n                            return;\n                        }\n\n                        if (entry.isFile) {\n                            _addFileToIndexes(entry);\n                            state.fileCount++;\n\n                        } else if (entry.isDirectory) {\n                            _scanDirectoryRecurse(entry);\n                        }\n                    });\n\n                    _finishDirScan(dirEntry);\n                },\n                // error callback\n                function (error) {\n                    state.dirError[dirEntry.fullPath] = error;\n                    _finishDirScan(dirEntry);\n                }\n            );\n        }\n\n        _scanDirectoryRecurse(dirEntry);\n\n        return deferred.promise();\n    }\n    \n    \n\n\n    \n    // debug \n    function _logFileList(list) {\n        list.forEach(function (fileInfo) {\n            console.log(fileInfo.name);\n        });\n        console.log(\"length: \" + list.length);\n    }\n    \n\n    /**\n    * Clears the fileInfo array for all the indexes in _indexList\n    * @private\n    */\n    function _clearIndexes() {\n        $.each(_indexList, function (indexName, index) {\n            index.fileInfos = [];\n        });\n    }\n\n    /**\n     * Markes all file indexes dirty\n     */\n    function markDirty() {\n        _indexListDirty = true;\n    }\n\n    /**\n     * Used by syncFileIndex function to prevent reentrancy\n     * @private\n     */\n    var _syncFileIndexReentracyGuard = false;\n\n    /**\n    * Clears and rebuilds all of the fileIndexes and sets _indexListDirty to false\n    * @return {$.Promise} resolved when index has been updated\n    */\n    function syncFileIndex() {\n\n        // TODO (issue 330) - allow multiple calls to syncFileIndex to be batched up so that this code isn't necessary\n        if (_syncFileIndexReentracyGuard) {\n            throw new Error(\"syncFileIndex cannot be called Recursively\");\n        }\n\n        _syncFileIndexReentracyGuard = true;\n\n        var rootDir = ProjectManager.getProjectRoot();\n        if (_indexListDirty) {\n            PerfUtils.markStart(PerfUtils.FILE_INDEX_MANAGER_SYNC);\n\n            _clearIndexes();\n\n            return _scanDirectorySubTree(rootDir)\n                .done(function () {\n                    PerfUtils.addMeasurement(PerfUtils.FILE_INDEX_MANAGER_SYNC);\n                    _indexListDirty = false;\n                    _syncFileIndexReentracyGuard = false;\n\n                    //_logFileList(_indexList[\"all\"].fileInfos);\n                    //_logFileList(_indexList[\"css\"].fileInfos);\n                });\n        } else {\n            _syncFileIndexReentracyGuard = false;\n            return $.Deferred().resolve().promise();\n        }\n    }\n\n    /**\n    * Returns the FileInfo array for the specified index\n    * @param {!string} indexname\n    * @return {$.Promise} a promise that is resolved with an Array of FileInfo's\n    */\n    function getFileInfoList(indexName) {\n        var result = new $.Deferred();\n\n        if (!_indexList.hasOwnProperty(indexName)) {\n            throw new Error(\"indexName not found\");\n        }\n\n        syncFileIndex()\n            .done(function () {\n                result.resolve(_indexList[indexName].fileInfos);\n            });\n\n        return result.promise();\n    }\n    \n    /**\n     * Calls the filterFunction on every in the index specified by indexName\n     * and return a a new list of FileInfo's\n     * @param {!string}\n     * @param {function({string})} filterFunction\n     * @return {$.Promise} a promise that is resolved with an Array of FileInfo's\n     */\n    function getFilteredList(indexName, filterFunction) {\n        var result = new $.Deferred();\n\n        if (!_indexList.hasOwnProperty(indexName)) {\n            throw new Error(\"indexName not found\");\n        }\n\n        syncFileIndex()\n            .done(function () {\n                var resultList = [];\n                getFileInfoList(indexName)\n                    .done(function (fileList) {\n                        resultList = fileList.filter(function (fileInfo) {\n                            return filterFunction(fileInfo.name);\n                        });\n\n                        result.resolve(resultList);\n                    });\n            });\n\n        return result.promise();\n    }\n    \n    /**\n     * returns an array of fileInfo's that match the filename parameter\n     * @param {!string} indexName\n     * @param {!filename}\n     * @return {$.Promise} a promise that is resolved with an Array of FileInfo's\n     */\n    function getFilenameMatches(indexName, filename) {\n        return getFilteredList(indexName, function (item) {\n            return item === filename;\n        });\n    }\n    \n    /**\n    * Add the indexes\n    */\n\n    _addIndex(\n        \"all\",\n        function (entry) {\n            return true;\n        }\n    );\n\n    _addIndex(\n        \"css\",\n        function (entry) {\n            var filename = entry.name;\n            return PathUtils.filenameExtension(filename) === \".css\";\n        }\n    );\n    \n    $(ProjectManager).on(\"projectOpen\", function (event, projectRoot) {\n        markDirty();\n    });\n    \n    PerfUtils.createPerfMeasurement(\"FILE_INDEX_MANAGER_SYNC\", \"syncFileIndex\");\n\n    exports.markDirty = markDirty;\n    exports.getFileInfoList = getFileInfoList;\n    exports.getFilenameMatches = getFilenameMatches;\n\n\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, _parseRuleList: true */\n\n// JSLint Note: _parseRuleList() is cyclical dependency, not a global function.\n// It was added to this list to prevent JSLint warning about being used before being defined.\n\n/**\n * Set of utilities for simple parsing of CSS text.\n */\ndefine('language/CSSUtils',['require','exports','module','utils/Async','document/DocumentManager','editor/EditorManager','language/HTMLUtils','project/FileIndexManager','file/NativeFileSystem'],function (require, exports, module) {\n    \n    \n    var Async               = require(\"utils/Async\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        HTMLUtils           = require(\"language/HTMLUtils\"),\n        FileIndexManager    = require(\"project/FileIndexManager\"),\n        NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem;\n\n    /**\n     * Extracts all CSS selectors from the given text\n     * Returns an array of selectors. Each selector is an object with the following properties:\n         selector:                 the text of the selector (note: comma separated selector groups like \n                                   \"h1, h2\" are broken into separate selectors)\n         ruleStartLine:            line in the text where the rule (including preceding comment) appears\n         ruleStartChar:            column in the line where the rule (including preceding comment) starts\n         selectorStartLine:        line in the text where the selector appears\n         selectorStartChar:        column in the line where the selector starts\n         selectorEndLine:          line where the selector ends\n         selectorEndChar:          column where the selector ends\n         selectorGroupStartLine:   line where the comma-separated selector group (e.g. .foo, .bar, .baz)\n                                   starts that this selector (e.g. .baz) is part of. Particularly relevant for\n                                   groups that are on multiple lines.\n         selectorGroupStartChar:   column in line where the selector group starts.\n         declListStartLine:        line where the declaration list for the rule starts\n         declListStartChar:        column in line where the declaration list for the rule starts\n         declListEndLine:          line where the declaration list for the rule ends\n         declListEndChar:          column in the line where the declaration list for the rule ends\n     * @param text {!String} CSS text to extract from\n     * @return {Array.<Object>} Array with objects specifying selectors.\n     */\n    function extractAllSelectors(text) {\n        var selectors = [];\n        var mode = CodeMirror.getMode({indentUnit: 2}, \"css\");\n        var state, lines, lineCount;\n        var token, style, stream, line;\n        var currentSelector = \"\";\n        var ruleStartChar = -1, ruleStartLine = -1;\n        var selectorStartChar = -1, selectorStartLine = -1;\n        var selectorGroupStartLine = -1, selectorGroupStartChar = -1;\n        var declListStartLine = -1, declListStartChar = -1;\n\n        // implement _firstToken()/_nextToken() methods to\n        // provide a single stream of tokens\n        \n        function _hasStream() {\n            while (stream.eol()) {\n                line++;\n                if (line >= lineCount) {\n                    return false;\n                }\n                if (currentSelector.match(/\\S/)) {\n                    // If we are in a current selector and starting a newline,\n                    // make sure there is whitespace in the selector\n                    currentSelector += \" \";\n                }\n                stream = new CodeMirror.StringStream(lines[line]);\n            }\n            return true;\n        }\n        \n        function _firstToken() {\n            state = CodeMirror.startState(mode);\n            lines = CodeMirror.splitLines(text);\n            lineCount = lines.length;\n            if (lineCount === 0) {\n                return false;\n            }\n            line = 0;\n            stream = new CodeMirror.StringStream(lines[line]);\n            if (!_hasStream()) {\n                return false;\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            return true;\n        }\n        \n        function _nextToken() {\n            // advance the stream past this token\n            stream.start = stream.pos;\n            if (!_hasStream()) {\n                return false;\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            return true;\n        }\n        \n        function _firstTokenSkippingWhitespace() {\n            if (!_firstToken()) {\n                return false;\n            }\n            while (!token.match(/\\S/)) {\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        \n        function _nextTokenSkippingWhitespace() {\n            if (!_nextToken()) {\n                return false;\n            }\n            while (!token.match(/\\S/)) {\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _isStartComment() {\n            return (token.match(/^\\/\\*/));\n        }\n        \n        function _parseComment() {\n            while (!token.match(/\\*\\/$/)) {\n                if (!_nextToken()) {\n                    break;\n                }\n            }\n        }\n\n        function _nextTokenSkippingComments() {\n            if (!_nextToken()) {\n                return false;\n            }\n            while (_isStartComment()) {\n                _parseComment();\n                if (!_nextToken()) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function _parseSelector() {\n            \n            currentSelector = \"\";\n            selectorStartChar = stream.start;\n            selectorStartLine = line;\n            \n            // Everything until the next ',' or '{' is part of the current selector\n            while (token !== \",\" && token !== \"{\") {\n                currentSelector += token;\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n            }\n\n            currentSelector = currentSelector.trim();\n            if (currentSelector !== \"\") {\n                selectors.push({selector: currentSelector,\n                                ruleStartLine: ruleStartLine,\n                                ruleStartChar: ruleStartChar,\n                                selectorStartLine: selectorStartLine,\n                                selectorStartChar: selectorStartChar,\n                                declListEndLine: -1,\n                                selectorEndLine: line,\n                                selectorEndChar: stream.start - 1, // stream.start points to the first char of the non-selector token\n                                selectorGroupStartLine: selectorGroupStartLine,\n                                selectorGroupStartChar: selectorGroupStartChar\n                               });\n                currentSelector = \"\";\n            }\n            selectorStartChar = -1;\n        }\n        \n        function _parseSelectorList() {\n\n            selectorGroupStartLine = line;\n            selectorGroupStartChar = stream.start;\n\n            _parseSelector();\n            while (token === \",\") {\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n                _parseSelector();\n            }\n        }\n\n        function _parseDeclarationList() {\n\n            var j;\n            declListStartLine = line;\n            declListStartChar = stream.start;\n\n            // Since we're now in a declaration list, that means we also finished\n            // parsing the whole selector group. Therefore, reset selectorGroupStartLine\n            // so that next time we parse a selector we know it's a new group\n            selectorGroupStartLine = -1;\n            selectorGroupStartChar = -1;\n            ruleStartLine = -1;\n            ruleStartChar = -1;\n\n            // Skip everything until the next '}'\n            while (token !== \"}\") {\n                if (!_nextTokenSkippingComments()) {\n                    break;\n                }\n            }\n            \n            // assign this declaration list position to every selector on the stack\n            // that doesn't have a declaration list start and end line\n            for (j = selectors.length - 1; j >= 0; j--) {\n                if (selectors[j].declListEndLine !== -1) {\n                    break;\n                } else {\n                    selectors[j].declListStartLine = declListStartLine;\n                    selectors[j].declListStartChar = declListStartChar;\n                    selectors[j].declListEndLine = line;\n                    selectors[j].declListEndChar = stream.pos - 1; // stream.pos actually points to the char after the }\n                }\n            }\n        }\n        \n        function includeCommentInNextRule() {\n            if (ruleStartChar !== -1) {\n                return false;       // already included\n            }\n            if (stream.start > 0 && lines[line].substr(0, stream.start).indexOf(\"}\") !== -1) {\n                return false;       // on same line as '}', so it's for previous rule\n            }\n            return true;\n        }\n        \n        function _isStartAtRule() {\n            return (token.match(/^@/));\n        }\n        \n        function _parseAtRule() {\n\n            // reset these fields to ignore comments preceding @rules\n            ruleStartLine = -1;\n            ruleStartChar = -1;\n            selectorStartLine = -1;\n            selectorStartChar = -1;\n            selectorGroupStartLine = -1;\n            selectorGroupStartChar = -1;\n            \n            if (token.match(/@media/i)) {\n                // @media rule holds a rule list\n                \n                // Skip everything until the opening '{'\n                while (token !== \"{\") {\n                    if (!_nextTokenSkippingComments()) {\n                        break;\n                    }\n                }\n                _nextTokenSkippingWhitespace();    // skip past '{', to next non-ws token\n\n                // Parse rules until we see '}'\n                _parseRuleList(\"}\");\n\n            } else if (token.match(/@(charset|import|namespace)/i)) {\n                \n                // This code handles @rules in this format:\n                //   @rule ... ;\n                // Skip everything until the next ';'\n                while (token !== \";\") {\n                    if (!_nextTokenSkippingComments()) {\n                        break;\n                    }\n                }\n                \n            } else {\n                // This code handle @rules that use this format:\n                //    @rule ... { ... }\n                // such as @page, @keyframes (also -webkit-keyframes, etc.), and @font-face.\n                // Skip everything until the next '}'\n                while (token !== \"}\") {\n                    if (!_nextTokenSkippingComments()) {\n                        break;\n                    }\n                }\n            }\n        }\n\n        // parse a style rule\n        function _parseRule() {\n            _parseSelectorList();\n            _parseDeclarationList();\n        }\n        \n        function _parseRuleList(escapeToken) {\n            \n            while ((!escapeToken) || token !== escapeToken) {\n                if (_isStartAtRule()) {\n                    // @rule\n                    _parseAtRule();\n    \n                } else if (_isStartComment()) {\n                    // comment - make this part of style rule\n                    if (includeCommentInNextRule()) {\n                        ruleStartChar = stream.start;\n                        ruleStartLine = line;\n                    }\n                    _parseComment();\n    \n                } else {\n                    // Otherwise, it's style rule\n                    if (ruleStartChar === -1) {\n                        ruleStartChar = stream.start;\n                        ruleStartLine = line;\n                    }\n                    _parseRule();\n                }\n                \n                if (!_nextTokenSkippingWhitespace()) {\n                    break;\n                }\n            }\n        }\n        \n        // Do parsing\n\n        if (_firstTokenSkippingWhitespace()) {\n\n            // Style sheet is a rule list\n            _parseRuleList();\n        }\n\n        return selectors;\n    }\n    \n    /*\n     * This code can be used to create an \"independent\" HTML document that can be passed to jQuery\n     * calls. Allows using jQuery's CSS selector engine without actually putting anything in the browser's DOM\n     *\n    var _htmlDoctype = document.implementation.createDocumentType('html',\n        '-//W3C//DTD XHTML 1.0 Strict//EN',\n        'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'\n    );\n    var _htmlDocument = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', _htmlDoctype);\n\n    function checkIfSelectorSelectsHTML(selector, theHTML) {\n        $('html', _htmlDocument).html(theHTML);\n        return ($(selector, _htmlDocument).length > 0);\n    }\n    */\n    \n    /**\n     * Finds all instances of the specified selector in \"text\".\n     * Returns an Array of Objects with start and end properties.\n     *\n     * For Sprint 4, we only support simple selectors. This function will need to change\n     * dramatically to support full selectors.\n     *\n     * FUTURE: (JRB) It would be nice to eventually use the browser/jquery to do the selector evaluation.\n     * One way to do this would be to take the user's HTML, add a special attribute to every tag with a UID,\n     * and then construct a DOM (using the commented out code above). Then, give this DOM and the selector to \n     * jquery and ask what matches. If the node that the user's cursor is in comes back from jquery, then \n     * we know the selector applies.\n     *\n     * @param text {!String} CSS text to search\n     * @param selector {!String} selector to search for\n     * @return {Array.<{selectorGroupStartLine:number, declListEndLine:number, selector:string}>}\n     *      Array of objects containing the start and end line numbers (0-based, inclusive range) for each\n     *      matched selector.\n     */\n    function _findAllMatchingSelectorsInText(text, selector) {\n        var allSelectors = extractAllSelectors(text);\n        var result = [];\n        var i;\n        \n        // For sprint 4 we only match the rightmost simple selector, and ignore \n        // attribute selectors and pseudo selectors\n        var classOrIdSelector = selector[0] === \".\" || selector[0] === \"#\";\n        var prefix = \"\";\n        \n        // Escape initial \".\" in selector, if present.\n        if (selector[0] === \".\") {\n            selector = \"\\\\\" + selector;\n        }\n        \n        if (!classOrIdSelector) {\n            // Tag selectors must have nothing or whitespace before it.\n            selector = \"(^|\\\\s)\" + selector;\n        }\n        \n        var re = new RegExp(selector + \"(\\\\[[^\\\\]]*\\\\]|:{1,2}[\\\\w-()]+|\\\\.[\\\\w-]+|#[\\\\w-]+)*\\\\s*$\", classOrIdSelector ? \"\" : \"i\");\n        allSelectors.forEach(function (entry) {\n            if (entry.selector.search(re) !== -1) {\n                result.push(entry);\n            } else if (!classOrIdSelector) {\n                // Special case for tag selectors - match \"*\" as the rightmost character\n                if (entry.selector.trim().search(/\\*$/) !== -1) {\n                    result.push(entry);\n                }\n            }\n        });\n        \n        return result;\n    }\n    \n    \n    /**\n     * Converts the results of _findAllMatchingSelectorsInText() into a simpler bag of data and\n     * appends those new objects to the given 'resultSelectors' Array.\n     * @param {Array.<{document:Document, lineStart:number, lineEnd:number}>} resultSelectors\n     * @param {Array.<{selectorGroupStartLine:number, declListEndLine:number, selector:string}>} selectorsToAdd\n     * @param {!Document} sourceDoc\n     * @param {!number} lineOffset Amount to offset all line number info by. Used if the first line\n     *          of the parsed CSS text is not the first line of the sourceDoc.\n     */\n    function _addSelectorsToResults(resultSelectors, selectorsToAdd, sourceDoc, lineOffset) {\n        selectorsToAdd.forEach(function (selectorInfo) {\n            resultSelectors.push({\n                name: selectorInfo.selector,\n                document: sourceDoc,\n                lineStart: selectorInfo.ruleStartLine + lineOffset,\n                lineEnd: selectorInfo.declListEndLine + lineOffset\n            });\n        });\n    }\n    \n    /** Finds matching selectors in CSS files; adds them to 'resultSelectors' */\n    function _findMatchingRulesInCSSFiles(selector, resultSelectors) {\n        var result          = new $.Deferred(),\n            cssFilesResult  = FileIndexManager.getFileInfoList(\"css\");\n        \n        // Load one CSS file and search its contents\n        function _loadFileAndScan(fullPath, selector) {\n            var oneFileResult = new $.Deferred();\n            \n            DocumentManager.getDocumentForPath(fullPath)\n                .done(function (doc) {\n                    // Find all matching rules for the given CSS file's content, and add them to the\n                    // overall search result\n                    var oneCSSFileMatches = _findAllMatchingSelectorsInText(doc.getText(), selector);\n                    _addSelectorsToResults(resultSelectors, oneCSSFileMatches, doc, 0);\n                    \n                    oneFileResult.resolve();\n                })\n                .fail(function (error) {\n                    oneFileResult.reject(error);\n                });\n        \n            return oneFileResult.promise();\n        }\n        \n        // Load index of all CSS files; then process each CSS file in turn (see above)\n        cssFilesResult.done(function (fileInfos) {\n            Async.doInParallel(fileInfos, function (fileInfo, number) {\n                return _loadFileAndScan(fileInfo.fullPath, selector);\n            })\n                .pipe(result.resolve, result.reject);\n        });\n        \n        return result.promise();\n    }\n    \n    /** Finds matching selectors in the <style> block of a single HTML file; adds them to 'resultSelectors' */\n    function _findMatchingRulesInStyleBlocks(htmlDocument, selector, resultSelectors) {\n        // HTMLUtils requires a real CodeMirror instance; make sure we can give it the right Editor\n        var htmlEditor = EditorManager.getCurrentFullEditor();\n        if (htmlEditor.document !== htmlDocument) {\n            console.error(\"Cannot search for <style> blocks in HTML file other than current editor\");\n            return;\n        }\n        \n        // Find all <style> blocks in the HTML file\n        var styleBlocks = HTMLUtils.findStyleBlocks(htmlEditor);\n        \n        styleBlocks.forEach(function (styleBlockInfo) {\n            // Search this one <style> block's content, appending results to 'resultSelectors'\n            var oneStyleBlockMatches = _findAllMatchingSelectorsInText(styleBlockInfo.text, selector);\n            _addSelectorsToResults(resultSelectors, oneStyleBlockMatches, htmlDocument, styleBlockInfo.start.line);\n        });\n    }\n    \n    /**\n     * Return all rules matching the specified selector.\n     * For Sprint 4, we only look at the rightmost simple selector. For example, searching for \".foo\" will \n     * match these rules:\n     *  .foo {}\n     *  div .foo {}\n     *  div.foo {}\n     *  div .foo[bar=\"42\"] {}\n     *  div .foo:hovered {}\n     *  div .foo::first-child\n     * but will *not* match these rules:\n     *  .foobar {}\n     *  .foo .bar {}\n     *  div .foo .bar {}\n     *  .foo.bar {}\n     *\n     * @param {!String} selector The selector to match. This can be a tag selector, class selector or id selector\n     * @param {?Document} htmlDocument An HTML file for context (so we can search <style> blocks)\n     * @return {$.Promise} that will be resolved with an Array of objects containing the\n     *      source document, start line, and end line (0-based, inclusive range) for each matching declaration list.\n     *      Does not addRef() the documents returned in the array.\n     */\n    function findMatchingRules(selector, htmlDocument) {\n        var result          = new $.Deferred(),\n            resultSelectors = [];\n        \n        // Synchronously search for matches in <style> blocks\n        if (htmlDocument) {\n            _findMatchingRulesInStyleBlocks(htmlDocument, selector, resultSelectors);\n        }\n        \n        // Asynchronously search for matches in all the project's CSS files\n        // (results are appended together in same 'resultSelectors' array)\n        _findMatchingRulesInCSSFiles(selector, resultSelectors)\n            .done(function () {\n                result.resolve(resultSelectors);\n            })\n            .fail(function (error) {\n                result.reject(error);\n            });\n        \n        return result.promise();\n    }\n    \n    \n    exports._findAllMatchingSelectorsInText = _findAllMatchingSelectorsInText; // For testing only\n    exports.findMatchingRules = findMatchingRules;\n    exports.extractAllSelectors = extractAllSelectors;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n// FUTURE: Merge part (or all) of this class with InlineTextEditor\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\n/**\n * An inline editor for displaying and editing multiple text ranges. Each range corresponds to a \n * contiguous set of lines in a file. \n * \n * In the current implementation, only one range is visible at a time. A list on the right side\n * of the editor allows the user to select which range is visible. \n *\n * This module does not dispatch any events.\n */\n\ndefine('editor/MultiRangeInlineEditor',['require','exports','module','document/TextRange','editor/InlineTextEditor','editor/EditorManager','command/Commands','strings','command/CommandManager','utils/PerfUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var TextRange           = require(\"document/TextRange\").TextRange,\n        InlineTextEditor    = require(\"editor/InlineTextEditor\").InlineTextEditor,\n        EditorManager       = require(\"editor/EditorManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\");\n\n    /**\n     * Remove trailing \"px\" from a style size value.\n     * @param {!JQuery} $target Element in DOM\n     * @param {!string} styleName Style name to query\n     * @return {number} Style value converted from string to number, removing \"px\" units\n     */\n    function _parseStyleSize($target, styleName) {\n        return parseInt($target.css(styleName), 10);\n    }\n    \n    \n    /**\n     * @constructor\n     * Stores one search result: its source file, line range, etc. plus the DOM node representing it\n     * in the results list.\n     */\n    function SearchResultItem(rangeResult) {\n        this.name = rangeResult.name;\n        this.textRange = new TextRange(rangeResult.document, rangeResult.lineStart, rangeResult.lineEnd);\n        // this.$listItem is assigned in load()\n    }\n    SearchResultItem.prototype.name = null;\n    SearchResultItem.prototype.textRange = null;\n    SearchResultItem.prototype.$listItem = null;\n    \n    function _updateRangeLabel(listItem, range) {\n        var text = range.name + \" \" + range.textRange.document.file.name + \" : \" + (range.textRange.startLine + 1);\n        listItem.text(text);\n        listItem.attr(\"title\", text);\n    }\n    \n    /**\n     * @constructor\n     * @param {Array.<{name:String,document:Document,startLine:number,endLine:number}>} ranges The text ranges to display.\n     * @extends {InlineTextEditor}\n     */\n    function MultiRangeInlineEditor(ranges) {\n        InlineTextEditor.call(this);\n        \n        // Store the results to show in the range list. This creates TextRanges bound to the Document,\n        // which will stay up to date automatically (but we must be sure to detach them later)\n        this._ranges = ranges.map(function (rangeResult) {\n            return new SearchResultItem(rangeResult);\n        });\n        \n        this._selectedRangeIndex = -1;\n    }\n    MultiRangeInlineEditor.prototype = new InlineTextEditor();\n    MultiRangeInlineEditor.prototype.constructor = MultiRangeInlineEditor;\n    MultiRangeInlineEditor.prototype.parentClass = InlineTextEditor.prototype;\n    \n    MultiRangeInlineEditor.prototype.$editorsDiv = null;\n    MultiRangeInlineEditor.prototype.$relatedContainer = null;\n    MultiRangeInlineEditor.prototype.$selectedMarker = null;\n    \n    /** @type {Array.<SearchResultItem>} */\n    MultiRangeInlineEditor.prototype._ranges = null;\n    MultiRangeInlineEditor.prototype._selectedRangeIndex = null;\n\n    /** \n     * @override\n     * @param {!Editor} hostEditor  Outer Editor instance that inline editor will sit within.\n     * \n     */\n    MultiRangeInlineEditor.prototype.load = function (hostEditor) {\n        this.parentClass.load.call(this, hostEditor);\n        \n        // Container to hold all editors\n        var self = this;\n\n        // Bind event handlers\n        this._updateRelatedContainer = this._updateRelatedContainer.bind(this);\n        this._ensureCursorVisible = this._ensureCursorVisible.bind(this);\n        this._handleChange = this._handleChange.bind(this);\n        this._onClick = this._onClick.bind(this);\n\n        // Create DOM to hold editors and related list\n        this.$editorsDiv = $(window.document.createElement(\"div\")).addClass(\"inlineEditorHolder\");\n        \n        // Outer container for border-left and scrolling\n        this.$relatedContainer = $(window.document.createElement(\"div\")).addClass(\"related-container\");\n        this._relatedContainerInserted = false;\n        this._relatedContainerInsertedHandler = this._relatedContainerInsertedHandler.bind(this);\n        \n        // FIXME (jasonsj): deprecated event http://www.w3.org/TR/DOM-Level-3-Events/\n        this.$relatedContainer.on(\"DOMNodeInserted\", this._relatedContainerInsertedHandler);\n        \n        // List \"selection\" highlight\n        this.$selectedMarker = $(window.document.createElement(\"div\")).appendTo(this.$relatedContainer).addClass(\"selection\");\n        \n        // Inner container\n        var $related = $(window.document.createElement(\"div\")).appendTo(this.$relatedContainer).addClass(\"related\");\n        \n        // Range list\n        var $rangeList = $(window.document.createElement(\"ul\")).appendTo($related);\n        \n        // create range list & add listeners for range textrange changes\n        var rangeItemText;\n        this._ranges.forEach(function (range, i) {\n            // Create list item UI\n            var $rangeItem = $(window.document.createElement(\"li\")).appendTo($rangeList);\n            _updateRangeLabel($rangeItem, range);\n            $rangeItem.mousedown(function () {\n                self.setSelectedIndex(i);\n            });\n\n            self._ranges[i].$listItem = $rangeItem;\n            \n            // Update list item as TextRange changes\n            $(self._ranges[i].textRange).on(\"change\", function () {\n                _updateRangeLabel($rangeItem, range);\n            });\n            \n            // If TextRange lost sync, react just as we do for an inline Editor's lostContent event:\n            // close the whole inline widget\n            $(self._ranges[i].textRange).on(\"lostSync\", function () {\n                self.close();\n            });\n        });\n        \n        // select the first range\n        self.setSelectedIndex(0);\n        \n        // attach to main container\n        this.$htmlContent.append(this.$editorsDiv).append(this.$relatedContainer);\n        \n        // initialize position based on the main #editor-holder\n        window.setTimeout(this._updateRelatedContainer, 0);\n        \n        // Changes to the host editor should update the relatedContainer\n        // Note: normally it's not kosher to listen to changes on a specific editor,\n        // but in this case we're specifically concerned with changes in the given\n        // editor, not general document changes.\n        $(this.hostEditor).on(\"change\", this._updateRelatedContainer);\n        \n        // Update relatedContainer when this widget's position changes\n        $(this).on(\"offsetTopChanged\", this._updateRelatedContainer);\n        \n        // Listen to the window resize event to reposition the relatedContainer\n        // when the hostEditor's scrollbars visibility changes\n        $(window).on(\"resize\", this._updateRelatedContainer);\n        \n        // Listen for clicks directly on us, so we can set focus back to the editor\n        this.$htmlContent.on(\"click\", this._onClick);\n    };\n\n    /**\n     * Specify the range that is shown in the editor.\n     *\n     * @param {!number} index The index of the range to select.\n     */\n    MultiRangeInlineEditor.prototype.setSelectedIndex = function (index) {\n        var newIndex = Math.min(Math.max(0, index), this._ranges.length - 1);\n        \n        if (newIndex === this._selectedRangeIndex) {\n            return;\n        }\n\n        // Remove selected class(es)\n        var previousItem = (this._selectedRangeIndex >= 0) ? this._ranges[this._selectedRangeIndex].$listItem : null;\n        \n        if (previousItem) {\n            previousItem.toggleClass(\"selected\", false);\n        }\n        \n        this._selectedRangeIndex = newIndex;\n        \n        var $rangeItem = this._ranges[this._selectedRangeIndex].$listItem;\n        \n        this._ranges[this._selectedRangeIndex].$listItem.toggleClass(\"selected\", true);\n\n        // Remove previous editors\n        $(this.editors[0]).off(\"change\", this._updateRelatedContainer);\n\n        this.editors.forEach(function (editor) {\n            editor.destroy(); //release ref on Document\n        });\n        \n        this.editors = [];\n        this.$editorsDiv.children().remove();\n\n        // Add new editor\n        var range = this._getSelectedRange();\n        this.createInlineEditorFromText(range.textRange.document, range.textRange.startLine, range.textRange.endLine, this.$editorsDiv.get(0));\n        this.editors[0].focus();\n\n        // Changes in size to the inline editor should update the relatedContainer\n        // Note: normally it's not kosher to listen to changes on a specific editor,\n        // but in this case we're specifically concerned with changes in the given\n        // editor, not general document changes.\n        $(this.editors[0]).on(\"change\", this._handleChange);\n        \n        // Cursor activity in the inline editor may cause us to horizontally scroll.\n        $(this.editors[0]).on(\"cursorActivity\", this._ensureCursorVisible);\n\n        \n        this.editors[0].refresh();\n        // ensureVisibility is set to false because we don't want to scroll the main editor when the user selects a view\n        this.sizeInlineWidgetToContents(true, false);\n        this._updateRelatedContainer();\n\n        // scroll the selection to the rangeItem, use setTimeout to wait for DOM updates\n        var self = this;\n        window.setTimeout(function () {\n            var containerHeight = self.$relatedContainer.height(),\n                itemTop = $rangeItem.position().top,\n                scrollTop = self.$relatedContainer.scrollTop();\n            \n            self.$selectedMarker.css(\"top\", itemTop);\n            self.$selectedMarker.height($rangeItem.outerHeight());\n            \n            if (containerHeight <= 0) {\n                return;\n            }\n            \n            var paddingTop = _parseStyleSize($rangeItem.parent(), \"paddingTop\");\n            \n            if ((itemTop - paddingTop) < scrollTop) {\n                self.$relatedContainer.scrollTop(itemTop - paddingTop);\n            } else {\n                var itemBottom = itemTop + $rangeItem.height() + _parseStyleSize($rangeItem.parent(), \"paddingBottom\");\n                \n                if (itemBottom > (scrollTop + containerHeight)) {\n                    self.$relatedContainer.scrollTop(itemBottom - containerHeight);\n                }\n            }\n        }, 0);\n    };\n\n    /**\n     * Called any time inline is closed, whether manually (via closeThisInline()) or automatically\n     */\n    MultiRangeInlineEditor.prototype.onClosed = function () {\n        this.parentClass.onClosed.call(this); // super.onClosed()\n        \n        // remove resize handlers for relatedContainer\n        $(this.hostEditor).off(\"change\", this._updateRelatedContainer);\n        $(this.editors[0]).off(\"change\", this._handleChange);\n        $(this.editors[0]).off(\"cursorActivity\", this._ensureCursorVisible);\n        $(this).off(\"offsetTopChanged\", this._updateRelatedContainer);\n        $(window).off(\"resize\", this._updateRelatedContainer);\n        \n        // de-ref all the Documents in the search results\n        this._ranges.forEach(function (searchResult) {\n            searchResult.textRange.dispose();\n        });\n    };\n    \n    /**\n     * @private\n     * Set _relatedContainerInserted flag once the $relatedContainer is inserted in the DOM.\n     */\n    MultiRangeInlineEditor.prototype._relatedContainerInsertedHandler = function () {\n        this.$relatedContainer.off(\"DOMNodeInserted\", this._relatedContainerInsertedHandler);\n        this._relatedContainerInserted = true;\n    };\n    \n    /**\n     * Prevent clicks in the dead areas of the inlineWidget from changing the focus and insertion point in the editor.\n     * This is done by detecting clicks in the inlineWidget that are not inside the editor or the range list and\n     * restoring focus and the insertion point.\n     */\n    MultiRangeInlineEditor.prototype._onClick = function (event) {\n        var childEditor = this.editors[0],\n            editorRoot = childEditor.getRootElement(),\n            editorPos = $(editorRoot).offset();\n        \n        function containsClick($parent) {\n            return $parent.find(event.target) > 0 || $parent[0] === event.target;\n        }\n        \n        // Ignore clicks in editor and clicks on filename link\n        if (!containsClick($(editorRoot)) && !containsClick($(\".filename\", this.$editorsDiv))) {\n            childEditor.focus();\n            // Only set the cursor if the click isn't in the range list.\n            if (!containsClick(this.$relatedContainer)) {\n                if (event.pageY < editorPos.top) {\n                    childEditor.setCursorPos(0, 0);\n                } else if (event.pageY > editorPos.top + $(editorRoot).height()) {\n                    var lastLine = childEditor.getLastVisibleLine();\n                    childEditor.setCursorPos(lastLine, childEditor.document.getLine(lastLine).length);\n                }\n            }\n        }\n    };\n    \n    /**\n     * Set the size, position, and clip rect of the range list.\n     */\n    MultiRangeInlineEditor.prototype._updateRelatedContainer = function () {\n        var borderThickness = (this.$htmlContent.outerHeight() - this.$htmlContent.innerHeight()) / 2;\n        this.$relatedContainer.css(\"top\", this.$htmlContent.offset().top + borderThickness);\n        this.$relatedContainer.height(this.$htmlContent.height());\n        \n        // Because we're using position: fixed, we need to explicitly clip the range list if it crosses\n        // out of the top or bottom of the scroller area.\n        var hostScroller = this.hostEditor.getScrollerElement(),\n            rcTop = this.$relatedContainer.offset().top,\n            rcHeight = this.$relatedContainer.outerHeight(),\n            rcBottom = rcTop + rcHeight,\n            scrollerOffset = $(hostScroller).offset(),\n            scrollerTop = scrollerOffset.top,\n            scrollerBottom = scrollerTop + hostScroller.clientHeight,\n            scrollerLeft = scrollerOffset.left,\n            rightOffset = $(window.document.body).outerWidth() - (scrollerLeft + hostScroller.clientWidth);\n        if (rcTop < scrollerTop || rcBottom > scrollerBottom) {\n            this.$relatedContainer.css(\"clip\", \"rect(\" + Math.max(scrollerTop - rcTop, 0) + \"px, auto, \" +\n                                       (rcHeight - Math.max(rcBottom - scrollerBottom, 0)) + \"px, auto)\");\n        } else {\n            this.$relatedContainer.css(\"clip\", \"\");\n        }\n        \n        // Constrain relatedContainer width to half of the scroller width\n        var relatedContainerWidth = this.$relatedContainer.width();\n        if (this._relatedContainerInserted) {\n            if (this._relatedContainerDefaultWidth === undefined) {\n                this._relatedContainerDefaultWidth = relatedContainerWidth;\n            }\n            \n            var halfWidth = Math.floor(hostScroller.clientWidth / 2);\n            relatedContainerWidth = Math.min(this._relatedContainerDefaultWidth, halfWidth);\n            this.$relatedContainer.width(relatedContainerWidth);\n        }\n        \n        // Position immediately to the left of the main editor's scrollbar.\n        this.$relatedContainer.css(\"right\", rightOffset + \"px\");\n\n        // Add extra padding to the right edge of the widget to account for the range list.\n        this.$htmlContent.css(\"padding-right\", this.$relatedContainer.outerWidth() + \"px\");\n        \n        // Set the minimum width of the widget (which doesn't include the padding) to the width\n        // of CodeMirror's linespace, so that the total width will be at least as large as the\n        // width of the host editor's code plus the padding for the range list. We need to do this\n        // rather than just setting min-width to 100% because adding padding for the range list\n        // actually pushes out the width of the container, so we would end up continuously\n        // growing the overall width.\n        // This is a bit of a hack since it relies on knowing some detail about the innards of CodeMirror.\n        var lineSpace = this.hostEditor._getLineSpaceElement(),\n            minWidth = $(lineSpace).offset().left - this.$htmlContent.offset().left + lineSpace.scrollWidth;\n        this.$htmlContent.css(\"min-width\", minWidth + \"px\");\n    };\n    \n    /**\n     * Based on the position of the cursor in the inline editor, determine whether we need to change the\n     * scroll position of the host editor to ensure that the cursor is visible.\n     */\n    MultiRangeInlineEditor.prototype._ensureCursorVisible = function () {\n        if ($.contains(this.editors[0].getRootElement(), window.document.activeElement)) {\n            var cursorCoords = this.editors[0]._codeMirror.cursorCoords(),\n                lineSpaceOffset = $(this.editors[0]._getLineSpaceElement()).offset(),\n                rangeListOffset = this.$relatedContainer.offset();\n            // If we're off the left-hand side, we just want to scroll it into view normally. But\n            // if we're underneath the range list on the right, we want to ask the host editor to \n            // scroll far enough that the current cursor position is visible to the left of the range \n            // list. (Because we always add extra padding for the range list, this is always possible.)\n            if (cursorCoords.x >= rangeListOffset.left) {\n                cursorCoords.x += this.$relatedContainer.outerWidth();\n            }\n            \n            // Vertically, we want to set the scroll position relative to the overall host editor, not\n            // the lineSpace of the widget itself. Also, we can't use the lineSpace here, because its top\n            // position just corresponds to whatever CodeMirror happens to have rendered at the top. So\n            // we need to figure out our position relative to the top of the virtual scroll area, which is\n            // the top of the actual scroller minus the scroll position.\n            var scrollerTop = $(this.hostEditor.getScrollerElement()).offset().top - this.hostEditor.getScrollPos().y;\n            this.hostEditor._codeMirror.scrollIntoView(cursorCoords.x - lineSpaceOffset.left,\n                                                       cursorCoords.y - scrollerTop,\n                                                       cursorCoords.x - lineSpaceOffset.left,\n                                                       cursorCoords.yBot - scrollerTop);\n        }\n    };\n    \n    /**\n     * Handle a change event from the editor. Update the related container and make sure the\n     * cursor is visible.\n     */\n    MultiRangeInlineEditor.prototype._handleChange = function () {\n        this._updateRelatedContainer();\n        this._ensureCursorVisible();\n    };\n\n    /**\n     * @return {Array.<SearchResultItem>}\n     */\n    MultiRangeInlineEditor.prototype._getRanges = function () {\n        return this._ranges;\n    };\n\n    /**\n     * @return {!SearchResultItem}\n     */\n    MultiRangeInlineEditor.prototype._getSelectedRange = function () {\n        return this._ranges[this._selectedRangeIndex];\n    };\n\n    /**\n     * Display the next range in the range list\n     */\n    MultiRangeInlineEditor.prototype._selectNextRange = function () {\n        this.setSelectedIndex(this._selectedRangeIndex + 1);\n    };\n    \n    /**\n     *  Display the previous range in the range list\n     */\n    MultiRangeInlineEditor.prototype._selectPreviousRange = function () {\n        this.setSelectedIndex(this._selectedRangeIndex - 1);\n    };\n\n    /**\n     * Sizes the inline widget height to be the maximum between the range list height and the editor height\n     * @override \n     * @param {boolean} force the editor to resize\n     * @param {boolean} ensureVisibility makes the parent editor scroll to display the inline editor. Default true.\n     */\n    MultiRangeInlineEditor.prototype.sizeInlineWidgetToContents = function (force, ensureVisibility) {\n        // Size the code mirror editors height to the editor content\n        this.parentClass.sizeInlineWidgetToContents.call(this, force);\n        // Size the widget height to the max between the editor content and the related ranges list\n        var widgetHeight = Math.max(this.$relatedContainer.find(\".related\").height(), this.$editorsDiv.height());\n        this.hostEditor.setInlineWidgetHeight(this, widgetHeight, ensureVisibility);\n\n        // The related ranges container size itself based on htmlContent which is set by setInlineWidgetHeight above.\n        this._updateRelatedContainer();\n    };\n\n    /**\n     * Returns the currently focused MultiRangeInlineEditor.\n     * @returns {MultiRangeInlineEditor}\n     */\n    function _getFocusedMultiRangeInlineEditor() {\n        \n        var focusedMultiRangeInlineEditor = null,\n            result = EditorManager.getFocusedInlineWidget();\n        \n        if (result) {\n            var focusedWidget = result.widget;\n            if (focusedWidget && focusedWidget instanceof MultiRangeInlineEditor) {\n                focusedMultiRangeInlineEditor = focusedWidget;\n            }\n        }\n        \n        return focusedMultiRangeInlineEditor;\n    }\n\n    /**\n     * Previous Range command handler\n     */\n    function _previousRange() {\n        var focusedMultiRangeInlineEditor = _getFocusedMultiRangeInlineEditor();\n        if (focusedMultiRangeInlineEditor) {\n            focusedMultiRangeInlineEditor._selectPreviousRange();\n        }\n    }\n    \n    /**\n     * Next Range command handler\n     */\n    function _nextRange() {\n        var focusedMultiRangeInlineEditor = _getFocusedMultiRangeInlineEditor();\n        if (focusedMultiRangeInlineEditor) {\n            focusedMultiRangeInlineEditor._selectNextRange();\n        }\n    }\n    \n    CommandManager.register(Strings.CMD_QUICK_EDIT_PREV_MATCH,      Commands.QUICK_EDIT_PREV_MATCH, _previousRange);\n    CommandManager.register(Strings.CMD_QUICK_EDIT_NEXT_MATCH,      Commands.QUICK_EDIT_NEXT_MATCH, _nextRange);\n\n    exports.MultiRangeInlineEditor = MultiRangeInlineEditor;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, window */\n\ndefine('editor/CSSInlineEditor',['require','exports','module','language/CSSUtils','editor/EditorManager','language/HTMLUtils','editor/MultiRangeInlineEditor'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var CSSUtils                = require(\"language/CSSUtils\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        HTMLUtils               = require(\"language/HTMLUtils\"),\n        MultiRangeInlineEditor  = require(\"editor/MultiRangeInlineEditor\").MultiRangeInlineEditor;\n\n    /**\n     * Given a position in an HTML editor, returns the relevant selector for the attribute/tag\n     * surrounding that position, or \"\" if none is found.\n     * @param {!Editor} editor\n     * @private\n     */\n    function _getSelectorName(editor, pos) {\n        var tagInfo = HTMLUtils.getTagInfo(editor, pos),\n            selectorName = \"\";\n        \n        if (tagInfo.position.tokenType === HTMLUtils.TAG_NAME) {\n            // Type selector\n            selectorName = tagInfo.tagName;\n        } else if (tagInfo.position.tokenType === HTMLUtils.ATTR_NAME ||\n                   tagInfo.position.tokenType === HTMLUtils.ATTR_VALUE) {\n            if (tagInfo.attr.name === \"class\") {\n                // Class selector. We only look for the class name\n                // that includes the insertion point. For example, if\n                // the attribute is: \n                //   class=\"error-dialog modal hide\"\n                // and the insertion point is inside \"modal\", we want \".modal\"\n                var attributeValue = tagInfo.attr.value;\n                var startIndex = attributeValue.substr(0, tagInfo.position.offset).lastIndexOf(\" \");\n                var endIndex = attributeValue.indexOf(\" \", tagInfo.position.offset);\n                selectorName = \".\" +\n                    attributeValue.substring(\n                        startIndex === -1 ? 0 : startIndex + 1,\n                        endIndex === -1 ? attributeValue.length : endIndex\n                    );\n                \n                // If the insertion point is surrounded by space, selectorName is \".\"\n                // Check for that here\n                if (selectorName === \".\") {\n                    selectorName = \"\";\n                }\n            } else if (tagInfo.attr.name === \"id\") {\n                // ID selector\n                selectorName = \"#\" + tagInfo.attr.value;\n            }\n        }\n        \n        return selectorName;\n    }\n\n    /**\n     * This function is registered with EditManager as an inline editor provider. It creates a CSSInlineEditor\n     * when cursor is on an HTML tag name, class attribute, or id attribute, find associated\n     * CSS rules and show (one/all of them) in an inline editor.\n     *\n     * @param {!Editor} editor\n     * @param {!{line:Number, ch:Number}} pos\n     * @return {$.Promise} a promise that will be resolved with an InlineWidget\n     *      or null if we're not going to provide anything.\n     */\n    function htmlToCSSProvider(hostEditor, pos) {\n        // Only provide a CSS editor when cursor is in HTML content\n        if (hostEditor.getModeForSelection() !== \"html\") {\n            return null;\n        }\n        \n        // Only provide CSS editor if the selection is within a single line\n        var sel = hostEditor.getSelection(false);\n        if (sel.start.line !== sel.end.line) {\n            return null;\n        }\n        \n        // Always use the selection start for determining selector name. The pos\n        // parameter is usually the selection end.        \n        var selectorName = _getSelectorName(hostEditor, hostEditor.getSelection(false).start);\n        if (selectorName === \"\") {\n            return null;\n        }\n\n        var result = new $.Deferred();\n\n        CSSUtils.findMatchingRules(selectorName, hostEditor.document)\n            .done(function (rules) {\n                if (rules && rules.length > 0) {\n                    var cssInlineEditor = new MultiRangeInlineEditor(rules);\n                    cssInlineEditor.load(hostEditor);\n                    \n                    result.resolve(cssInlineEditor);\n                } else {\n                    // No matching rules were found.\n                    result.reject();\n                }\n            })\n            .fail(function () {\n                console.log(\"Error in findMatchingRules()\");\n                result.reject();\n            });\n        \n        return result.promise();\n    }\n\n    EditorManager.registerInlineEditProvider(htmlToCSSProvider);\n\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n/**\n * Defines a ChangedDocumentTracker class to monitor changes to files in the current project.\n */\ndefine('document/ChangedDocumentTracker',['require','exports','module','document/DocumentManager','project/ProjectManager'],function (require, exports, module) {\n    \n    \n    var DocumentManager = require(\"document/DocumentManager\"),\n        ProjectManager  = require(\"project/ProjectManager\");\n    \n    /**\n     * Tracks \"change\" events on opened Documents. Used to monitor changes\n     * to documents in-memory and update caches. Assumes all documents have\n     * changed when the Brackets window loses and regains focus. Does not\n     * read timestamps of files on disk. Clients may optionally track file\n     * timestamps on disk independently.\n     */\n    function ChangedDocumentTracker() {\n        var self = this;\n        \n        this._changedPaths = {};\n        this._windowFocus = true;\n        this._addListener = this._addListener.bind(this);\n        this._removeListener = this._removeListener.bind(this);\n        this._onChange = this._onChange.bind(this);\n        this._onWindowFocus = this._onWindowFocus.bind(this);\n\n        $(DocumentManager).on(\"afterDocumentCreate\", function (event, doc) {\n            // Only track documents in the current project\n            if (ProjectManager.isWithinProject(doc.file.fullPath)) {\n                self._addListener(doc);\n            }\n        });\n\n        $(DocumentManager).on(\"beforeDocumentDelete\", function (event, doc) {\n            // In case a document somehow remains loaded after its project\n            // has been closed, unconditionally attempt to remove the listener.\n            self._removeListener(doc);\n        });\n\n        $(window).focus(this._onWindowFocus);\n    }\n    \n    /**\n     * @private\n     * Assumes all files are changed when the window loses and regains focus.\n     */\n    ChangedDocumentTracker.prototype._addListener = function (doc) {\n        $(doc).on(\"change\", this._onChange);\n    };\n\n    /**\n     * @private\n     */\n    ChangedDocumentTracker.prototype._removeListener = function (doc) {\n        $(doc).off(\"change\", this._onChange);\n    };\n\n    /**\n     * @private\n     * Assumes all files are changed when the window loses and regains focus.\n     */\n    ChangedDocumentTracker.prototype._onWindowFocus = function (event, doc) {\n        this._windowFocus = true;\n    };\n    \n    /**\n     * @private\n     * Tracks changed documents.\n     */\n    ChangedDocumentTracker.prototype._onChange = function (event, doc) {\n        // if it was already changed, and the client hasn't reset the tracker,\n        // then leave it changed.\n        this._changedPaths[doc.file.fullPath] = true;\n    };\n    \n    /**\n     * Empty the set of dirty paths. Begin tracking new dirty documents. \n     */\n    ChangedDocumentTracker.prototype.reset = function () {\n        this._changedPaths = {};\n        this._windowFocus = false;\n    };\n    \n    /**\n     * Check if a file path is dirty.\n     * @param {!string} file path\n     * @return {!boolean} Returns true if the file was dirtied since the last reset.\n     */\n    ChangedDocumentTracker.prototype.isPathChanged = function (path) {\n        return this._windowFocus || this._changedPaths[path];\n    };\n    \n    /**\n     * Get the set of changed paths since the last reset.\n     * @return {Array.<string>} Changed file paths\n     */\n    ChangedDocumentTracker.prototype.getChangedPaths = function () {\n        return $.makeArray(this._changedPaths);\n    };\n\n    module.exports = ChangedDocumentTracker;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils, CodeMirror */\n\n/**\n * Set of utilities for simple parsing of JS text.\n */\ndefine('language/JSUtils',['require','exports','module','utils/Async','document/DocumentManager','document/ChangedDocumentTracker','file/NativeFileSystem','utils/PerfUtils','utils/StringUtils'],function (require, exports, module) {\n    \n    \n    // Load brackets modules\n    var Async                   = require(\"utils/Async\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        ChangedDocumentTracker  = require(\"document/ChangedDocumentTracker\"),\n        NativeFileSystem        = require(\"file/NativeFileSystem\").NativeFileSystem,\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        StringUtils             = require(\"utils/StringUtils\");\n\n    /**\n     * Tracks dirty documents between invocations of findMatchingFunctions.\n     * @type {ChangedDocumentTracker}\n     */\n    var _changedDocumentTracker = new ChangedDocumentTracker();\n    \n    /**\n     * Function matching regular expression. Recognizes the forms:\n     * \"function functionName()\", \"functionName = function()\", and\n     * \"functionName: function()\".\n     *\n     * Note: JavaScript identifier matching is not strictly to spec. This\n     * RegExp matches any sequence of characters that is not whitespace.\n     * @type {RegExp}\n     */\n    var _functionRegExp = /(function\\s+([$_A-Za-z\\u007F-\\uFFFF][$_A-Za-z0-9\\u007F-\\uFFFF]*)\\s*(\\([^)]*\\)))|(([$_A-Za-z\\u007F-\\uFFFF][$_A-Za-z0-9\\u007F-\\uFFFF]*)\\s*[:=]\\s*function\\s*(\\([^)]*\\)))/g;\n    \n    /**\n     * @private\n     * Return an Array with names and offsets for all functions in the specified text\n     * @param {!string} text Document text\n     * @return {Object.<string, Array.<{offsetStart: number, offsetEnd: number}>}\n     */\n    function _findAllFunctionsInText(text) {\n        var results = {},\n            functionName,\n            match;\n        \n        PerfUtils.markStart(PerfUtils.JSUTILS_REGEXP);\n        \n        while ((match = _functionRegExp.exec(text)) !== null) {\n            functionName = (match[2] || match[5]).trim();\n            \n            if (!Array.isArray(results[functionName])) {\n                results[functionName] = [];\n            }\n            \n            results[functionName].push({offsetStart: match.index});\n        }\n        \n        PerfUtils.addMeasurement(PerfUtils.JSUTILS_REGEXP);\n        \n        return results;\n    }\n    \n    // Given the start offset of a function definition (before the opening brace), find\n    // the end offset for the function (the closing \"}\"). Returns the position one past the\n    // close brace. Properly ignores braces inside comments, strings, and regexp literals.\n    function _getFunctionEndOffset(text, offsetStart) {\n        var mode = CodeMirror.getMode({}, \"javascript\");\n        var state = CodeMirror.startState(mode), stream, style, token;\n        var curOffset = offsetStart, length = text.length, blockCount = 0, lineStart;\n        var foundStartBrace = false;\n        \n        // Get a stream for the next line, and update curOffset and lineStart to point to the \n        // beginning of that next line. Returns false if we're at the end of the text.\n        function nextLine() {\n            if (stream) {\n                curOffset++; // account for \\n\n                if (curOffset >= length) {\n                    return false;\n                }\n            }\n            lineStart = curOffset;\n            var lineEnd = text.indexOf(\"\\n\", lineStart);\n            if (lineEnd === -1) {\n                lineEnd = length;\n            }\n            stream = new CodeMirror.StringStream(text.slice(curOffset, lineEnd));\n            return true;\n        }\n        \n        // Get the next token, updating the style and token to refer to the current\n        // token, and updating the curOffset to point to the end of the token (relative\n        // to the start of the original text).\n        function nextToken() {\n            if (curOffset >= length) {\n                return false;\n            }\n            if (stream) {\n                // Set the start of the next token to the current stream position.\n                stream.start = stream.pos;\n            }\n            while (!stream || stream.eol()) {\n                if (!nextLine()) {\n                    return false;\n                }\n            }\n            style = mode.token(stream, state);\n            token = stream.current();\n            curOffset = lineStart + stream.pos;\n            return true;\n        }\n\n        while (nextToken()) {\n            if (style !== \"comment\" && style !== \"regexp\" && style !== \"string\") {\n                if (token === \"{\") {\n                    foundStartBrace = true;\n                    blockCount++;\n                } else if (token === \"}\") {\n                    blockCount--;\n                }\n            }\n\n            // blockCount starts at 0, so we don't want to check if it hits 0\n            // again until we've actually gone past the start of the function body.\n            if (foundStartBrace && blockCount <= 0) {\n                return curOffset;\n            }\n        }\n        \n        // Shouldn't get here, but if we do, return the end of the text as the offset.\n        return length;\n    }\n\n    /**\n     * @private\n     * Computes function offsetEnd, lineStart and lineEnd. Appends a result record to rangeResults.\n     * @param {!Document} doc\n     * @param {!string} functionName\n     * @param {!Array.<{offsetStart: number, offsetEnd: number}>} functions\n     * @param {!Array.<{document: Document, name: string, lineStart: number, lineEnd: number}>} rangeResults\n     */\n    function _computeOffsets(doc, functionName, functions, rangeResults) {\n        var text    = doc.getText(),\n            lines   = StringUtils.getLines(text);\n        \n        functions.forEach(function (funcEntry) {\n            if (!funcEntry.offsetEnd) {\n                PerfUtils.markStart(PerfUtils.JSUTILS_END_OFFSET);\n                \n                funcEntry.offsetEnd = _getFunctionEndOffset(text, funcEntry.offsetStart);\n                funcEntry.lineStart = StringUtils.offsetToLineNum(lines, funcEntry.offsetStart);\n                funcEntry.lineEnd   = StringUtils.offsetToLineNum(lines, funcEntry.offsetEnd);\n                \n                PerfUtils.addMeasurement(PerfUtils.JSUTILS_END_OFFSET);\n            }\n            \n            rangeResults.push({\n                document:   doc,\n                name:       functionName,\n                lineStart:  funcEntry.lineStart,\n                lineEnd:    funcEntry.lineEnd\n            });\n        });\n    }\n    \n    /**\n     * @private\n     * Read a file and build a function list. Result is cached in fileInfo.\n     * @param {!FileInfo} fileInfo File to parse\n     * @param {!$.Deferred} result Deferred to resolve with all functions found and the document\n     */\n    function _readFile(fileInfo, result) {\n        DocumentManager.getDocumentForPath(fileInfo.fullPath)\n            .done(function (doc) {\n                var allFunctions = _findAllFunctionsInText(doc.getText());\n                \n                // Cache the result in the fileInfo object\n                fileInfo.JSUtils = {};\n                fileInfo.JSUtils.functions = allFunctions;\n                fileInfo.JSUtils.timestamp = doc.diskTimestamp;\n                \n                result.resolve({doc: doc, functions: allFunctions});\n            })\n            .fail(function (error) {\n                result.reject(error);\n            });\n    }\n    \n    /**\n     * Determines if the document function cache is up to date. \n     * @param {FileInfo} fileInfo\n     * @return {$.Promise} A promise resolved with true with true when a function cache is available for the document. Resolves\n     *   with false when there is no cache or the cache is stale.\n     */\n    function _shouldGetFromCache(fileInfo) {\n        var result = new $.Deferred(),\n            isChanged = _changedDocumentTracker.isPathChanged(fileInfo.fullPath);\n        \n        if (isChanged && fileInfo.JSUtils) {\n            // See if it's dirty and in the working set first\n            var doc = DocumentManager.getOpenDocumentForPath(fileInfo.fullPath);\n            \n            if (doc && doc.isDirty) {\n                result.resolve(false);\n            } else {\n                // If a cache exists, check the timestamp on disk\n                var file = new NativeFileSystem.FileEntry(fileInfo.fullPath);\n                \n                file.getMetadata(\n                    function (metadata) {\n                        result.resolve(fileInfo.JSUtils.timestamp === metadata.diskTimestamp);\n                    },\n                    function (error) {\n                        result.reject(error);\n                    }\n                );\n            }\n        } else {\n            // Use the cache if the file did not change and the cache exists\n            result.resolve(!isChanged && fileInfo.JSUtils);\n        }\n\n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Compute lineStart and lineEnd for each matched function\n     * @param {!Array.<{doc: Document, fileInfo: FileInfo, functions: Array.<offsetStart: number, offsetEnd: number>}>} docEntries\n     * @param {!string} functionName\n     * @param {!Array.<document: Document, name: string, lineStart: number, lineEnd: number>} rangeResults\n     * @return {$.Promise} A promise resolved with an array of document ranges to populate a MultiRangeInlineEditor.\n     */\n    function _getOffsetsForFunction(docEntries, functionName) {\n        // Filter for documents that contain the named function\n        var result              = new $.Deferred(),\n            matchedDocuments    = [],\n            rangeResults        = [],\n            functionsInDocument;\n        \n        docEntries.forEach(function (docEntry) {\n            functionsInDocument = docEntry.functions[functionName];\n            \n            if (functionsInDocument) {\n                matchedDocuments.push({doc: docEntry.doc, fileInfo: docEntry.fileInfo, functions: functionsInDocument});\n            }\n        });\n        \n        Async.doInParallel(matchedDocuments, function (docEntry) {\n            var doc         = docEntry.doc,\n                oneResult   = new $.Deferred();\n            \n            // doc will be undefined if we hit the cache\n            if (!doc) {\n                DocumentManager.getDocumentForPath(docEntry.fileInfo.fullPath)\n                    .done(function (fetchedDoc) {\n                        _computeOffsets(fetchedDoc, functionName, docEntry.functions, rangeResults);\n                    })\n                    .always(function () {\n                        oneResult.resolve();\n                    });\n            } else {\n                _computeOffsets(doc, functionName, docEntry.functions, rangeResults);\n                oneResult.resolve();\n            }\n            \n            return oneResult.promise();\n        }).done(function () {\n            result.resolve(rangeResults);\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n     * Resolves with a record containing the Document or FileInfo and an Array of all\n     * function names with offsets for the specified file. Results may be cached.\n     * @param {FileInfo} fileInfo\n     * @return {$.Promise} A promise resolved with a document info object that\n     *   contains a map of all function names from the document and each function's start offset. \n     */\n    function _getFunctionsForFile(fileInfo) {\n        var result = new $.Deferred();\n            \n        _shouldGetFromCache(fileInfo)\n            .done(function (useCache) {\n                if (useCache) {\n                    // Return cached data. doc property is undefined since we hit the cache.\n                    // _getOffsets() will fetch the Document if necessary.\n                    result.resolve({/*doc: undefined,*/fileInfo: fileInfo, functions: fileInfo.JSUtils.functions});\n                } else {\n                    _readFile(fileInfo, result);\n                }\n            }).fail(function (err) {\n                result.reject(err);\n            });\n        \n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Get all functions for each FileInfo.\n     * @param {Array.<FileInfo>} fileInfos\n     * @return {$.Promise} A promise resolved with an array of document info objects that each\n     *   contain a map of all function names from the document and each function's start offset.\n     */\n    function _getFunctionsInFiles(fileInfos) {\n        var result          = new $.Deferred(),\n            docEntries      = [];\n        \n        PerfUtils.markStart(PerfUtils.JSUTILS_GET_ALL_FUNCTIONS);\n        \n        Async.doInParallel(fileInfos, function (fileInfo) {\n            var oneResult = new $.Deferred();\n            \n            _getFunctionsForFile(fileInfo)\n                .done(function (docInfo) {\n                    docEntries.push(docInfo);\n                })\n                .always(function (error) {\n                    // If one file fails, continue to search\n                    oneResult.resolve();\n                });\n            \n            return oneResult.promise();\n        }).always(function () {\n            // Reset ChangedDocumentTracker now that the cache is up to date.\n            _changedDocumentTracker.reset();\n            \n            PerfUtils.addMeasurement(PerfUtils.JSUTILS_GET_ALL_FUNCTIONS);\n            result.resolve(docEntries);\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n     * Return all functions that have the specified name.\n     *\n     * @param {!String} functionName The name to match.\n     * @param {!Array.<FileIndexManager.FileInfo>} fileInfos The array of files to search.\n     * @return {$.Promise} that will be resolved with an Array of objects containing the\n     *      source document, start line, and end line (0-based, inclusive range) for each matching function list.\n     *      Does not addRef() the documents returned in the array.\n     */\n    function findMatchingFunctions(functionName, fileInfos) {\n        var result          = new $.Deferred(),\n            jsFiles         = [],\n            docEntries      = [];\n        \n        // Filter fileInfos for .js files\n        jsFiles = fileInfos.filter(function (fileInfo) {\n            return (/^\\.js/i).test(PathUtils.filenameExtension(fileInfo.fullPath));\n        });\n        \n        // RegExp search (or cache lookup) for all functions in the project\n        _getFunctionsInFiles(jsFiles).done(function (docEntries) {\n            // Compute offsets for all matched functions\n            _getOffsetsForFunction(docEntries, functionName).done(function (rangeResults) {\n                result.resolve(rangeResults);\n            });\n        });\n        \n        return result.promise();\n    }\n\n    /**\n     * Finds all instances of the specified functionName in \"text\".\n     * Returns an Array of Objects with start and end properties.\n     *\n     * @param text {!String} JS text to search\n     * @param functionName {!String} function name to search for\n     * @return {Array.<{offset:number, functionName:string}>}\n     *      Array of objects containing the start offset for each matched function name.\n     */\n    function findAllMatchingFunctionsInText(text, functionName) {\n        var allFunctions = _findAllFunctionsInText(text);\n        var result = [];\n        var lines = text.split(\"\\n\");\n        \n        $.each(allFunctions, function (index, functions) {\n            if (index === functionName || functionName === \"*\") {\n                functions.forEach(function (funcEntry) {\n                    var endOffset = _getFunctionEndOffset(text, funcEntry.offsetStart);\n                    result.push({\n                        name: index,\n                        lineStart: StringUtils.offsetToLineNum(lines, funcEntry.offsetStart),\n                        lineEnd: StringUtils.offsetToLineNum(lines, endOffset)\n                    });\n                });\n            }\n        });\n         \n        return result;\n    }\n    \n    PerfUtils.createPerfMeasurement(\"JSUTILS_GET_ALL_FUNCTIONS\", \"Parallel file search across project\");\n    PerfUtils.createPerfMeasurement(\"JSUTILS_REGEXP\", \"RegExp search for all functions\");\n    PerfUtils.createPerfMeasurement(\"JSUTILS_END_OFFSET\", \"Find end offset for a single matched function\");\n\n    exports.findAllMatchingFunctionsInText = findAllMatchingFunctionsInText;\n    exports._getFunctionEndOffset = _getFunctionEndOffset; // For testing only\n    exports.findMatchingFunctions = findMatchingFunctions;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $  */\n\n/**\n * WorkingSetView generates the UI for the list of the files user is editing based on the model provided by EditorManager.\n * The UI allows the user to see what files are open/dirty and allows them to close files and specify the current editor.\n *\n */\ndefine('project/WorkingSetView',['require','exports','module','document/DocumentManager','command/CommandManager','command/Commands','editor/EditorManager','project/FileViewController','file/NativeFileSystem','utils/ViewUtils'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var DocumentManager       = require(\"document/DocumentManager\"),\n        CommandManager        = require(\"command/CommandManager\"),\n        Commands              = require(\"command/Commands\"),\n        EditorManager         = require(\"editor/EditorManager\"),\n        FileViewController    = require(\"project/FileViewController\"),\n        NativeFileSystem      = require(\"file/NativeFileSystem\").NativeFileSystem,\n        ViewUtils             = require(\"utils/ViewUtils\");\n    \n    \n    /** Each list item in the working set stores a references to the related document in the list item's data.  \n     *  Use listItem.data(_FILE_KEY) to get the document reference\n     */\n    var _FILE_KEY = \"file\",\n        $openFilesContainer,\n        $openFilesList;\n    \n    /**\n     * @private\n     * Redraw selection when list size changes or DocumentManager currentDocument changes.\n     */\n    function _fireSelectionChanged() {\n        // redraw selection\n        $openFilesList.trigger(\"selectionChanged\");\n\n        // in-lieu of resize events, manually trigger contentChanged to update scroll shadows\n        $openFilesContainer.triggerHandler(\"contentChanged\");\n    }\n\n    /**\n     * @private\n     * adds the style 'vertical-scroll' if a vertical scroll bar is present\n     */\n    function _adjustForScrollbars() {\n        if ($openFilesContainer[0].scrollHeight > $openFilesContainer[0].clientHeight) {\n            if (!$openFilesContainer.hasClass(\"vertical-scroll\")) {\n                $openFilesContainer.addClass(\"vertical-scroll\");\n            }\n        } else {\n            $openFilesContainer.removeClass(\"vertical-scroll\");\n        }\n    }\n    \n    /**\n     * @private\n     * Shows/Hides open files list based on working set content.\n     */\n    function _redraw() {\n        if (DocumentManager.getWorkingSet().length === 0) {\n            $openFilesContainer.hide();\n        } else {\n            $openFilesContainer.show();\n        }\n        _adjustForScrollbars();\n        _fireSelectionChanged();\n    }\n    \n    /** \n     * Updates the appearance of the list element based on the parameters provided\n     * @private\n     * @param {!HTMLLIElement} listElement\n     * @param {bool} isDirty \n     * @param {bool} canClose\n     */\n    function _updateFileStatusIcon(listElement, isDirty, canClose) {\n        var $fileStatusIcon = listElement.find(\".file-status-icon\");\n        var showIcon = isDirty || canClose;\n\n        // remove icon if its not needed\n        if (!showIcon && $fileStatusIcon.length !== 0) {\n            $fileStatusIcon.remove();\n            $fileStatusIcon = null;\n            \n        // create icon if its needed and doesn't exist\n        } else if (showIcon && $fileStatusIcon.length === 0) {\n            \n            $fileStatusIcon = $(\"<div class='file-status-icon'></div>\")\n                .prependTo(listElement)\n                .mousedown(function (e) {\n                    // stopPropagation of mousedown for fileStatusIcon so the parent <LI> item, which\n                    // selects documents on mousedown, doesn't select the document in the case \n                    // when the click is on fileStatusIcon\n                    e.stopPropagation();\n                })\n                .click(function () {\n                    // Clicking the \"X\" button is equivalent to File > Close; it doesn't merely\n                    // remove a file from the working set\n                    var file = listElement.data(_FILE_KEY);\n                    CommandManager.execute(Commands.FILE_CLOSE, {file: file});\n                });\n        }\n\n        // Set icon's class\n        if ($fileStatusIcon) {\n            // cast to Boolean needed because toggleClass() distinguishes true/false from truthy/falsy\n            $fileStatusIcon.toggleClass(\"dirty\", Boolean(isDirty));\n            $fileStatusIcon.toggleClass(\"can-close\", Boolean(canClose));\n        }\n    }\n    \n    /** \n     * Updates the appearance of the list element based on the parameters provided.\n     * @private\n     * @param {!HTMLLIElement} listElement\n     * @param {?Document} selectedDoc\n     */\n    function _updateListItemSelection(listItem, selectedDoc) {\n        var shouldBeSelected = (selectedDoc && $(listItem).data(_FILE_KEY).fullPath === selectedDoc.file.fullPath);\n        \n        // cast to Boolean needed because toggleClass() distinguishes true/false from truthy/falsy\n        $(listItem).toggleClass(\"selected\", Boolean(shouldBeSelected));\n    }\n\n    function isOpenAndDirty(file) {\n        var docIfOpen = DocumentManager.getOpenDocumentForPath(file.fullPath);\n        return (docIfOpen && docIfOpen.isDirty);\n    }\n    \n    /** \n     * Builds the UI for a new list item and inserts in into the end of the list\n     * @private\n     * @param {FileEntry} file\n     * @return {HTMLLIElement} newListItem\n     */\n    function _createNewListItem(file) {\n        var curDoc = DocumentManager.getCurrentDocument();\n\n        // Create new list item with a link\n        var $link = $(\"<a href='#'></a>\").text(file.name);\n        var $newItem = $(\"<li></li>\")\n            .append($link)\n            .data(_FILE_KEY, file);\n\n        $openFilesContainer.find(\"ul\").append($newItem);\n        \n        // working set item might never have been opened; if so, then it's definitely not dirty\n\n        // Update the listItem's apperance\n        _updateFileStatusIcon($newItem, isOpenAndDirty(file), false);\n        _updateListItemSelection($newItem, curDoc);\n\n        $newItem.mousedown(function (e) {\n            FileViewController.openAndSelectDocument(file.fullPath, FileViewController.WORKING_SET_VIEW);\n            e.preventDefault();\n        });\n\n        $newItem.hover(\n            function () {\n                _updateFileStatusIcon($(this), isOpenAndDirty(file), true);\n            },\n            function () {\n                _updateFileStatusIcon($(this), isOpenAndDirty(file), false);\n            }\n        );\n    }\n    \n    /** \n     * Deletes all the list items in the view and rebuilds them from the working set model\n     * @private\n     */\n    function _rebuildWorkingSet() {\n        $openFilesContainer.find(\"ul\").empty();\n\n        DocumentManager.getWorkingSet().forEach(function (file) {\n            _createNewListItem(file);\n        });\n\n        _redraw();\n    }\n\n    /**\n     * Finds the listItem item assocated with the file. Returns null if not found.\n     * @private\n     * @param {!FileEntry} file\n     * @return {HTMLLIItem}\n     */\n    function _findListItemFromFile(file) {\n        var result = null;\n\n        if (file) {\n            var items = $openFilesContainer.find(\"ul\").children();\n            items.each(function () {\n                var $listItem = $(this);\n                if ($listItem.data(_FILE_KEY).fullPath === file.fullPath) {\n                    result = $listItem;\n                    return false;\n                    // breaks each\n                }\n            });\n        }\n\n        return result;\n    }\n\n    /**\n     * @private\n     */\n    function _scrollSelectedDocIntoView() {\n        if (FileViewController.getFileSelectionFocus() !== FileViewController.WORKING_SET_VIEW) {\n            return;\n        }\n\n        var doc = DocumentManager.getCurrentDocument();\n        if (!doc) {\n            return;\n        }\n\n        var $selectedDoc = _findListItemFromFile(doc.file);\n        if (!$selectedDoc) {\n            return;\n        }\n\n        ViewUtils.scrollElementIntoView($openFilesContainer, $selectedDoc, false);\n    }\n\n    /** \n     * @private\n     */\n    function _updateListSelection() {\n        var doc;\n        if (FileViewController.getFileSelectionFocus() === FileViewController.WORKING_SET_VIEW) {\n            doc = DocumentManager.getCurrentDocument();\n        } else {\n            doc = null;\n        }\n            \n        // Iterate through working set list and update the selection on each\n        var items = $openFilesContainer.find(\"ul\").children().each(function () {\n            _updateListItemSelection(this, doc);\n        });\n\n        // Make sure selection is in view\n        _scrollSelectedDocIntoView();\n\n        _fireSelectionChanged();\n    }\n\n    /** \n     * @private\n     */\n    function _handleFileAdded(file) {\n        _createNewListItem(file);\n        _redraw();\n    }\n\n    /**\n     * @private\n     */\n    function _handleFileListAdded(files) {\n        files.forEach(function (file) {\n            _createNewListItem(file);\n        });\n        _redraw();\n    }\n\n    /** \n     * @private\n     */\n    function _handleDocumentSelectionChange() {\n        _updateListSelection();\n        _fireSelectionChanged();\n    }\n\n    /** \n     * @private\n     * @param {FileEntry} file \n     */\n    function _handleFileRemoved(file) {\n        var $listItem = _findListItemFromFile(file);\n        if ($listItem) {\n            $listItem.remove();\n        }\n\n        _redraw();\n    }\n\n    function _handleRemoveList(removedFiles) {\n        removedFiles.forEach(function (file) {\n            var $listItem = _findListItemFromFile(file);\n            if ($listItem) {\n                $listItem.remove();\n            }\n        });\n\n        _redraw();\n    }\n\n    /** \n     * @private\n     * @param {Document} doc \n     */\n    function _handleDirtyFlagChanged(doc) {\n        var listItem = _findListItemFromFile(doc.file);\n        if (listItem) {\n            var canClose = $(listItem).find(\".can-close\").length === 1;\n            _updateFileStatusIcon(listItem, doc.isDirty, canClose);\n        }\n\n    }\n\n    function create(element) {\n        // Init DOM element\n        $openFilesContainer = element;\n        $openFilesList = $openFilesContainer.find(\"ul\");\n        \n        // Register listeners\n        $(DocumentManager).on(\"workingSetAdd\", function (event, addedFile) {\n            _handleFileAdded(addedFile);\n        });\n\n        $(DocumentManager).on(\"workingSetAddList\", function (event, addedFiles) {\n            _handleFileListAdded(addedFiles);\n        });\n\n        $(DocumentManager).on(\"workingSetRemove\", function (event, removedFile) {\n            _handleFileRemoved(removedFile);\n        });\n\n        $(DocumentManager).on(\"workingSetRemoveList\", function (event, removedFiles) {\n            _handleRemoveList(removedFiles);\n        });\n\n        $(DocumentManager).on(\"dirtyFlagChange\", function (event, doc) {\n            _handleDirtyFlagChanged(doc);\n        });\n    \n        $(FileViewController).on(\"documentSelectionFocusChange fileViewFocusChange\", _handleDocumentSelectionChange);\n        \n        // Show scroller shadows when open-files-container scrolls\n        ViewUtils.addScrollerShadow($openFilesContainer[0], null, true);\n        ViewUtils.sidebarList($openFilesContainer);\n        \n        _redraw();\n    }\n    \n    exports.create = create;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils, window */\n\ndefine('document/DocumentCommandHandlers',['require','exports','module','thirdparty/path-utils/path-utils.min','command/CommandManager','command/Commands','command/KeyBindingManager','file/NativeFileSystem','project/ProjectManager','document/DocumentManager','editor/EditorManager','project/FileViewController','file/FileUtils','utils/StringUtils','utils/Async','widgets/Dialogs','strings','preferences/PreferencesManager','utils/PerfUtils'],function (require, exports, module) {\n    \n    \n    require(\"thirdparty/path-utils/path-utils.min\");\n    \n    // Load dependent modules\n    var CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        KeyBindingManager   = require(\"command/KeyBindingManager\"),\n        NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        ProjectManager      = require(\"project/ProjectManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileViewController  = require(\"project/FileViewController\"),\n        FileUtils           = require(\"file/FileUtils\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Async               = require(\"utils/Async\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        PerfUtils           = require(\"utils/PerfUtils\");\n    \n    /**\n     * Handlers for commands related to document handling (opening, saving, etc.)\n     */\n    \n    /** @type {jQueryObject} Container for label shown above editor; must be an inline element */\n    var _$title = null;\n    /** @type {jQueryObject} Container for dirty dot; must be an inline element */\n    var _$dirtydot = null;\n    /** @type {jQueryObject} Container for _$title; need not be an inline element */\n    var _$titleWrapper = null;\n    /** @type {string} Label shown above editor for current document: filename and potentially some of its path */\n    var _currentTitlePath = null;\n    \n    /** @type {jQueryObject} Container for _$titleWrapper; if changing title changes this element's height, must kick editor to resize */\n    var _$titleContainerToolbar = null;\n    /** @type {Number} Last known height of _$titleContainerToolbar */\n    var _lastToolbarHeight = null;\n    \n    function updateTitle() {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        if (currentDoc) {\n            _$title.text(_currentTitlePath);\n            _$title.attr(\"title\", currentDoc.file.fullPath);\n            // dirty dot is always in DOM so layout doesn't change, and visibility is toggled\n            _$dirtydot.css(\"visibility\", (currentDoc.isDirty) ? \"visible\" : \"hidden\");\n        } else {\n            _$title.text(\"\");\n            _$title.attr(\"title\", \"\");\n            _$dirtydot.css(\"visibility\", \"hidden\");\n        }\n        \n        // Set _$titleWrapper to a fixed width just large enough to accomodate _$title. This seems equivalent to what\n        // the browser would do automatically, but the CSS trick we use for layout requires _$titleWrapper to have a\n        // fixed width set on it (see the \"#main-toolbar.toolbar\" CSS rule for details).\n        _$titleWrapper.css(\"width\", \"\");\n        var newWidth = _$title.width();\n        _$titleWrapper.css(\"width\", newWidth);\n        \n        // Changing the width of the title may cause the toolbar layout to change height, which needs to resize the\n        // editor beneath it (toolbar changing height due to window resize is already caught by EditorManager).\n        var newToolbarHeight = _$titleContainerToolbar.height();\n        if (_lastToolbarHeight !== newToolbarHeight) {\n            _lastToolbarHeight = newToolbarHeight;\n            EditorManager.resizeEditor();\n        }\n    }\n    \n    function handleCurrentDocumentChange() {\n        var newDocument = DocumentManager.getCurrentDocument();\n        var perfTimerName = PerfUtils.markStart(\"DocumentCommandHandlers._onCurrentDocumentChange():\\t\" + (!newDocument || newDocument.file.fullPath));\n        \n        if (newDocument) {\n            var fullPath = newDocument.file.fullPath;\n    \n            // In the main toolbar, show the project-relative path (if the file is inside the current project)\n            // or the full absolute path (if it's not in the project).\n            _currentTitlePath = ProjectManager.makeProjectRelativeIfPossible(fullPath);\n            \n        } else {\n            _currentTitlePath = null;\n        }\n        \n        // Update title text & \"dirty dot\" display\n        updateTitle();\n\n        PerfUtils.addMeasurement(perfTimerName);\n    }\n    \n    function handleDirtyChange(event, changedDoc) {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        \n        if (currentDoc && changedDoc.file.fullPath === currentDoc.file.fullPath) {\n            updateTitle();\n        }\n    }\n\n    /**\n     * @private\n     * Creates a document and displays an editor for the specified file path.\n     * @param {!string} fullPath\n     * @return {$.Promise} a jQuery promise that will be resolved with a\n     *  document for the specified file path, or rejected if the file can not be read.\n     */\n    function doOpen(fullPath) {\n        var result = new $.Deferred();\n\n        if (!fullPath) {\n            console.log(\"doOpen() called without fullPath\");\n            result.reject();\n        } else {\n            var perfTimerName = PerfUtils.markStart(\"Open File:\\t\" + fullPath);\n            result.always(function () {\n                PerfUtils.addMeasurement(perfTimerName);\n            });\n            \n            // Load the file if it was never open before, and then switch to it in the UI\n            DocumentManager.getDocumentForPath(fullPath)\n                .done(function (doc) {\n                    DocumentManager.setCurrentDocument(doc);\n                    result.resolve(doc);\n                })\n                .fail(function (fileError) {\n                    FileUtils.showFileOpenError(fileError.code, fullPath).done(function () {\n                        // For performance, we do lazy checking of file existence, so it may be in working set\n                        DocumentManager.removeFromWorkingSet(new NativeFileSystem.FileEntry(fullPath));\n                        EditorManager.focusEditor();\n                        result.reject();\n                    });\n                });\n        }\n\n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Used to track the default directory for the file open dialog\n     */\n    var _defaultOpenDialogFullPath = null;\n    \n    /**\n     * @private\n     * Creates a document and displays an editor for the specified file path. \n     * If no path is specified, a file prompt is provided for input.\n     * @param {?string} fullPath - The path of the file to open; if it's null we'll prompt for it\n     * @return {$.Promise} a jQuery promise that will be resolved with a new \n     *  document for the specified file path, or rejected if the file can not be read.\n     */\n    function _doOpenWithOptionalPath(fullPath) {\n        var result;\n        if (!fullPath) {\n            // Create placeholder deferred\n            result = new $.Deferred();\n            \n            //first time through, default to the current project path\n            if (!_defaultOpenDialogFullPath) {\n                _defaultOpenDialogFullPath = ProjectManager.getProjectRoot().fullPath;\n            }\n            // Prompt the user with a dialog\n            NativeFileSystem.showOpenDialog(true, false, Strings.OPEN_FILE, _defaultOpenDialogFullPath,\n                null, function (paths) {\n                    var i;\n                    \n                    if (paths.length > 0) {\n                        // Add all files to the working set without verifying that\n                        // they still exist on disk (for faster opening)\n                        var filesToOpen = [];\n                        paths.forEach(function (file) {\n                            filesToOpen.push(new NativeFileSystem.FileEntry(file));\n                        });\n                        DocumentManager.addListToWorkingSet(filesToOpen);\n                        \n                        doOpen(paths[paths.length - 1])\n                            .done(function (doc) {\n                                var url = PathUtils.parseUrl(doc.file.fullPath);\n                                //reconstruct the url but use the directory and stop there\n                                _defaultOpenDialogFullPath = url.protocol + url.doubleSlash + url.authority + url.directory;\n                                \n                                DocumentManager.addToWorkingSet(doc.file);\n                            })\n                            // Send the resulting document that was opened\n                            .pipe(result.resolve, result.reject);\n                    } else {\n                        // Reject if the user canceled the dialog\n                        result.reject();\n                    }\n                });\n        } else {\n            result = doOpen(fullPath);\n        }\n        \n        return result.promise();\n    }\n\n    /**\n     * Opens the given file and makes it the current document. Does NOT add it to the working set.\n     * @param {!{fullPath:string}} Params for FILE_OPEN command\n     */\n    function handleFileOpen(commandData) {\n        var fullPath = null;\n        if (commandData) {\n            fullPath = commandData.fullPath;\n        }\n        \n        return _doOpenWithOptionalPath(fullPath)\n            .always(EditorManager.focusEditor);\n    }\n\n    /**\n     * Opens the given file, makes it the current document, AND adds it to the working set.\n     * @param {!{fullPath:string}} Params for FILE_OPEN command\n     */\n    function handleFileAddToWorkingSet(commandData) {\n        return handleFileOpen(commandData).done(function (doc) {\n            // addToWorkingSet is synchronous\n            DocumentManager.addToWorkingSet(doc.file);\n        });\n    }\n\n    /**\n     * @private\n     * Ensures the suggested file name doesn't already exit.\n     * @param {string} dir  The directory to use\n     * @param {string} baseFileName  The base to start with, \"-n\" will get appened to make unique\n     * @param {string} fileExt  The file extension\n     * @return {$.Promise} a jQuery promise that will be resolved with a unique name starting with \n     *   the given base name\n     */\n    function _getUntitledFileSuggestion(dir, baseFileName, fileExt) {\n        var result = new $.Deferred();\n        var suggestedName = baseFileName + fileExt;\n        var dirEntry = new NativeFileSystem.DirectoryEntry(dir);\n\n        result.progress(function attemptNewName(suggestedName, nextIndexToUse) {\n            if (nextIndexToUse > 99) {\n                //we've tried this enough\n                result.reject();\n                return;\n            }\n\n            //check this name\n            dirEntry.getFile(\n                suggestedName,\n                {},\n                function successCallback(entry) {\n                    //file exists, notify to the next progress\n                    result.notify(baseFileName + \"-\" + nextIndexToUse + fileExt, nextIndexToUse + 1);\n                },\n                function errorCallback(error) {\n                    //most likely error is FNF, user is better equiped to handle the rest\n                    result.resolve(suggestedName);\n                }\n            );\n        });\n\n        //kick it off\n        result.notify(baseFileName + fileExt, 1);\n\n        return result.promise();\n    }\n\n    /**\n     * Prevents re-entrancy into handleFileNewInProject()\n     *\n     * handleFileNewInProject() first prompts the user to name a file and then asynchronously writes the file when the\n     * filename field loses focus. This boolean prevent additional calls to handleFileNewInProject() when an existing\n     * file creation call is outstanding\n     */\n    var fileNewInProgress = false;\n\n    function handleFileNewInProject() {\n\n        if (fileNewInProgress) {\n            ProjectManager.forceFinishRename();\n            return;\n        }\n        fileNewInProgress = true;\n\n        // Determine the directory to put the new file\n        // If a file is currently selected, put it next to it.\n        // If a directory is currently selected, put it in it.\n        // If nothing is selected, put it at the root of the project\n        var baseDir,\n            selected = ProjectManager.getSelectedItem() || ProjectManager.getProjectRoot();\n        \n        baseDir = selected.fullPath;\n        if (selected.isFile) {\n            baseDir = baseDir.substr(0, baseDir.lastIndexOf(\"/\"));\n        }\n        \n        // Create the new node. The createNewItem function does all the heavy work\n        // of validating file name, creating the new file and selecting.\n        var deferred = _getUntitledFileSuggestion(baseDir, Strings.UNTITLED, \".js\");\n        var createWithSuggestedName = function (suggestedName) {\n            ProjectManager.createNewItem(baseDir, suggestedName, false)\n                .pipe(deferred.resolve, deferred.reject, deferred.notify)\n                .always(function () { fileNewInProgress = false; })\n                .done(function (entry) {\n                    FileViewController.addToWorkingSetAndSelect(entry.fullPath, FileViewController.PROJECT_MANAGER);\n                });\n        };\n\n        deferred.done(createWithSuggestedName);\n        deferred.fail(function createWithDefault() { createWithSuggestedName(\"Untitled.js\"); });\n        return deferred;\n    }\n    \n    function showSaveFileError(code, path) {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_SAVING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_SAVING_FILE,\n                StringUtils.htmlEscape(path),\n                FileUtils.getFileErrorString(code)\n            )\n        );\n    }\n    \n    /** Note: if there is an error, the promise is not rejected until the user has dimissed the dialog */\n    function doSave(docToSave) {\n        var result = new $.Deferred();\n        \n        function handleError(error, fileEntry) {\n            showSaveFileError(error.code, fileEntry.fullPath)\n                .always(function () {\n                    result.reject(error);\n                });\n        }\n            \n        if (docToSave && docToSave.isDirty) {\n            var fileEntry = docToSave.file;\n            var writeError = false;\n            \n            fileEntry.createWriter(\n                function (writer) {\n                    writer.onwriteend = function () {\n                        // Per spec, onwriteend is called after onerror too\n                        if (!writeError) {\n                            docToSave.notifySaved();\n                            result.resolve();\n                        }\n                    };\n                    writer.onerror = function (error) {\n                        writeError = true;\n                        handleError(error, fileEntry);\n                    };\n\n                    // We don't want normalized line endings, so it's important to pass true to getText()\n                    writer.write(docToSave.getText(true));\n                },\n                function (error) {\n                    handleError(error, fileEntry);\n                }\n            );\n        } else {\n            result.resolve();\n        }\n        result.always(function () {\n            EditorManager.focusEditor();\n        });\n        return result.promise();\n    }\n    \n    /**\n     * Saves the given file. If no file specified, assumes the current document.\n     * @param {?{doc: Document}} commandData  Document to close, or null\n     * @return {$.Promise} a promise that is resolved after the save completes\n     */\n    function handleFileSave(commandData) {\n        // Default to current document if doc is null\n        var doc = null;\n        if (commandData) {\n            doc = commandData.doc;\n        }\n        if (!doc) {\n            var focusedEditor = EditorManager.getFocusedEditor();\n            \n            if (focusedEditor) {\n                doc = focusedEditor.document;\n            }\n            \n            // doc may still be null, e.g. if no editors are open, but doSave() does a null check on\n            // doc and makes sure the document is dirty before saving.\n        }\n        \n        return doSave(doc);\n    }\n    \n    /**\n     * Saves all unsaved documents. Returns a Promise that will be resolved once ALL the save\n     * operations have been completed. If ANY save operation fails, an error dialog is immediately\n     * shown and the other files wait to save until it is dismissed; after all files have been\n     * processed, the Promise is rejected if any ONE save operation failed.\n     *\n     * @return {$.Promise}\n     */\n    function saveAll() {\n        // Do in serial because doSave shows error UI for each file, and we don't want to stack\n        // multiple dialogs on top of each other\n        return Async.doSequentially(\n            DocumentManager.getWorkingSet(),\n            function (file) {\n                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n                if (doc) {\n                    return doSave(doc);\n                } else {\n                    // working set entry that was never actually opened - ignore\n                    return (new $.Deferred()).resolve().promise();\n                }\n            },\n            false\n        );\n    }\n    \n    /**\n     * Saves all unsaved documents.\n     * @return {$.Promise} a promise that is resolved once ALL the saves have been completed; or rejected\n     *      after all operations completed if any ONE of them failed.\n     */\n    function handleFileSaveAll() {\n        return saveAll();\n    }\n    \n    /**\n     * Reverts the Document to the current contents of its file on disk. Discards any unsaved changes\n     * in the Document.\n     * @param {Document} doc\n     * @return {$.Promise} a Promise that's resolved when done, or rejected with a FileError if the\n     *      file cannot be read (after showing an error dialog to the user).\n     */\n    function doRevert(doc) {\n        var result = new $.Deferred();\n        \n        FileUtils.readAsText(doc.file)\n            .done(function (text, readTimestamp) {\n                doc.refreshText(text, readTimestamp);\n                result.resolve();\n            })\n            .fail(function (error) {\n                FileUtils.showFileOpenError(error.code, doc.file.fullPath)\n                    .always(function () {\n                        result.reject(error);\n                    });\n            });\n        \n        return result.promise();\n    }\n    \n\n    /**\n     * Closes the specified file: removes it from the working set, and closes the main editor if one\n     * is open. Prompts user about saving changes first, if document is dirty.\n     *\n     * @param {?{file: FileEntry, promptOnly:boolean}} commandData  Optional bag of arguments:\n     *      file - File to close; assumes the current document if not specified.\n     *      promptOnly - If true, only displays the relevant confirmation UI and does NOT actually\n     *          close the document. This is useful when chaining file-close together with other user\n     *          prompts that may be cancelable.\n     * @return {$.Promise} a promise that is resolved when the file is closed, or if no file is open.\n     *      FUTURE: should we reject the promise if no file is open?\n     */\n    function handleFileClose(commandData) {\n        // If not specified, file defaults to null; promptOnly defaults to falsy\n        var file       = commandData && commandData.file,\n            promptOnly = commandData && commandData.promptOnly;\n        \n        // utility function for handleFileClose: closes document & removes from working set\n        function doClose(file) {\n            if (!promptOnly) {\n                // This selects a different document if the working set has any other options\n                DocumentManager.closeFullEditor(file);\n            \n                EditorManager.focusEditor();\n            }\n        }\n        \n        \n        var result = new $.Deferred(), promise = result.promise();\n        \n        // Default to current document if doc is null\n        if (!file) {\n            if (DocumentManager.getCurrentDocument()) {\n                file = DocumentManager.getCurrentDocument().file;\n            }\n        }\n        \n        // No-op if called when nothing is open; TODO: (issue #273) should command be grayed out instead?\n        if (!file) {\n            result.resolve();\n            return promise;\n        }\n        \n        var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n        \n        if (doc && doc.isDirty) {\n            // Document is dirty: prompt to save changes before closing\n            var filename = PathUtils.parseUrl(doc.file.fullPath).filename;\n            \n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_SAVE_CLOSE,\n                Strings.SAVE_CLOSE_TITLE,\n                StringUtils.format(Strings.SAVE_CLOSE_MESSAGE, StringUtils.htmlEscape(filename))\n            ).done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                    result.reject();\n                } else if (id === Dialogs.DIALOG_BTN_OK) {\n                    // \"Save\" case: wait until we confirm save has succeeded before closing\n                    doSave(doc)\n                        .done(function () {\n                            doClose(file);\n                            result.resolve();\n                        })\n                        .fail(function () {\n                            result.reject();\n                        });\n                } else {\n                    // \"Don't Save\" case: even though we're closing the main editor, other views of\n                    // the Document may remain in the UI. So we need to revert the Document to a clean\n                    // copy of whatever's on disk.\n                    doClose(file);\n                    \n                    // Only reload from disk if we've executed the Close for real,\n                    // *and* if at least one other view still exists\n                    if (!promptOnly && DocumentManager.getOpenDocumentForPath(file.fullPath)) {\n                        doRevert(doc)\n                            .pipe(result.resolve, result.reject);\n                    } else {\n                        result.resolve();\n                    }\n                }\n            });\n            result.always(function () {\n                EditorManager.focusEditor();\n            });\n        } else {\n            // File is not open, or IS open but Document not dirty: close immediately\n            doClose(file);\n            EditorManager.focusEditor();\n            result.resolve();\n        }\n        return promise;\n    }\n    \n    /**\n     * Closes all open documents; equivalent to calling handleFileClose() for each document, except\n     * that unsaved changes are confirmed once, in bulk.\n     * @param {?{promptOnly: boolean}}  If true, only displays the relevant confirmation UI and does NOT\n     *          actually close any documents. This is useful when chaining close-all together with\n     *          other user prompts that may be cancelable.\n     * @return {$.Promise} a promise that is resolved when all files are closed\n     */\n    function handleFileCloseAll(commandData) {\n        var result = new $.Deferred();\n        \n        var unsavedDocs = [];\n        DocumentManager.getWorkingSet().forEach(function (file) {\n            var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);\n            if (doc && doc.isDirty) {\n                unsavedDocs.push(doc);\n            }\n        });\n        \n        if (unsavedDocs.length === 0) {\n            // No unsaved changes, so we can proceed without a prompt\n            result.resolve();\n            \n        } else if (unsavedDocs.length === 1) {\n            // Only one unsaved file: show the usual single-file-close confirmation UI\n            var fileCloseArgs = { file: unsavedDocs[0].file, promptOnly: commandData.promptOnly };\n\n            handleFileClose(fileCloseArgs).done(function () {\n                // still need to close any other, non-unsaved documents\n                result.resolve();\n            }).fail(function () {\n                result.reject();\n            });\n            \n        } else {\n            // Multiple unsaved files: show a single bulk prompt listing all files\n            var message = Strings.SAVE_CLOSE_MULTI_MESSAGE;\n            \n            message += \"<ul>\";\n            unsavedDocs.forEach(function (doc) {\n                message += \"<li><span class='dialog-filename'>\"\n                    + StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n                    + \"</span></li>\";\n            });\n            message += \"</ul>\";\n            \n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_SAVE_CLOSE,\n                Strings.SAVE_CLOSE_TITLE,\n                message\n            ).done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_CANCEL) {\n                    result.reject();\n                } else if (id === Dialogs.DIALOG_BTN_OK) {\n                    // Save all unsaved files, then if that succeeds, close all\n                    saveAll().done(function () {\n                        result.resolve();\n                    }).fail(function () {\n                        result.reject();\n                    });\n                } else {\n                    // \"Don't Save\" case--we can just go ahead and close all  files.\n                    result.resolve();\n                }\n            });\n        }\n        \n        // If all the unsaved-changes confirmations pan out above, then go ahead & close all editors\n        // NOTE: this still happens before any done() handlers added by our caller, because jQ\n        // guarantees that handlers run in the order they are added.\n        result.done(function () {\n            if (!commandData || !commandData.promptOnly) {\n                DocumentManager.closeAll();\n            }\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n    * @private - tracks our closing state if we get called again\n    */\n    var _windowGoingAway = false;\n    \n    /**\n    * @private\n    * Common implementation for close/quit/reload which all mostly\n    * the same except for the final step\n    */\n    function _handleWindowGoingAway(commandData, postCloseHandler, failHandler) {\n        if (_windowGoingAway) {\n            //if we get called back while we're closing, then just return\n            return (new $.Deferred()).resolve().promise();\n        }\n        \n        //prevent the default action of closing the window until we can save all the files\n        if (commandData && commandData.evt && commandData.evt.cancelable) {\n            commandData.evt.preventDefault();\n        }\n\n        return CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })\n            .done(function () {\n                _windowGoingAway = true;\n                PreferencesManager.savePreferences();\n                postCloseHandler();\n            })\n            .fail(function () {\n                _windowGoingAway = false;\n                if (failHandler) {\n                    failHandler();\n                }\n            });\n    }\n\n    /**\n    * @private\n    * Implementation for abortQuit callback to reset quit sequence settings\n    */\n    function _handleAbortQuit() {\n        _windowGoingAway = false;\n    }\n    \n    /** Confirms any unsaved changes, then closes the window */\n    function handleFileCloseWindow(commandData) {\n        return _handleWindowGoingAway(\n            commandData,\n            function () {\n                window.close();\n            },\n            function () {\n                // if fail, tell the app to abort any pending quit operation.\n                // TODO: remove this if statement when we move to the new CEF3 shell\n                if (brackets.app.abortQuit) {\n                    brackets.app.abortQuit();\n                }\n            }\n        );\n    }\n    \n    /** Closes the window, then quits the app */\n    function handleFileQuit(commandData) {\n        return _handleWindowGoingAway(\n            commandData,\n            function () {\n                brackets.app.quit();\n            },\n            function () {\n                // if fail, don't exit: user canceled (or asked us to save changes first, but we failed to do so)\n                // TODO: remove this if statement when we move to the new CEF3 shell\n                if (brackets.app.abortQuit) {\n                    brackets.app.abortQuit();\n                }\n            }\n        );\n    }\n\n    /** Does a full reload of the browser window */\n    function handleFileReload(commandData) {\n        return _handleWindowGoingAway(commandData, function () {\n            window.location.reload(true);\n        });\n    }\n    \n    \n    /** Are we already listening for a keyup to call detectDocumentNavEnd()? */\n    var _addedNavKeyHandler = false;\n    \n    /**\n     * When the Ctrl key is released, if we were in the middle of a next/prev document navigation\n     * sequence, now is the time to end it and update the MRU order. If we allowed the order to update\n     * on every next/prev increment, the 1st & 2nd entries would just switch places forever and we'd\n     * never get further down the list.\n     * @param {jQueryEvent} event Key-up event\n     */\n    function detectDocumentNavEnd(event) {\n        if (event.keyCode === 17) {  // Ctrl key\n            DocumentManager.finalizeDocumentNavigation();\n            \n            _addedNavKeyHandler = false;\n            $(window.document.body).off(\"keyup\", detectDocumentNavEnd);\n        }\n    }\n    \n    /** Navigate to the next/previous (MRU) document. Don't update MRU order yet */\n    function goNextPrevDoc(inc) {\n        var file = DocumentManager.getNextPrevFile(inc);\n        if (file) {\n            DocumentManager.beginDocumentNavigation();\n            CommandManager.execute(Commands.FILE_OPEN, { fullPath: file.fullPath });\n            \n            // Listen for ending of Ctrl+Tab sequence\n            if (!_addedNavKeyHandler) {\n                _addedNavKeyHandler = true;\n                $(window.document.body).keyup(detectDocumentNavEnd);\n            }\n        }\n    }\n    \n    function handleGoNextDoc() {\n        goNextPrevDoc(+1);\n    }\n    function handleGoPrevDoc() {\n        goNextPrevDoc(-1);\n    }\n    \n\n    function init($titleContainerToolbar) {\n        _$titleContainerToolbar = $titleContainerToolbar;\n        _$titleWrapper = $(\".title-wrapper\", _$titleContainerToolbar);\n        _$title = $(\".title\", _$titleWrapper);\n        _$dirtydot = $(\".dirty-dot\", _$titleWrapper);\n\n        // Register global commands\n        CommandManager.register(Strings.CMD_FILE_OPEN,          Commands.FILE_OPEN, handleFileOpen);\n        CommandManager.register(Strings.CMD_ADD_TO_WORKING_SET, Commands.FILE_ADD_TO_WORKING_SET, handleFileAddToWorkingSet);\n        // TODO: (issue #274) For now, hook up File > New to the \"new in project\" handler. Eventually\n        // File > New should open a new blank tab, and handleFileNewInProject should\n        // be called from a \"+\" button in the project\n        CommandManager.register(Strings.CMD_FILE_NEW,           Commands.FILE_NEW, handleFileNewInProject);\n        CommandManager.register(Strings.CMD_FILE_SAVE,          Commands.FILE_SAVE, handleFileSave);\n        CommandManager.register(Strings.CMD_FILE_SAVE_ALL,      Commands.FILE_SAVE_ALL, handleFileSaveAll);\n\n        CommandManager.register(Strings.CMD_FILE_CLOSE,         Commands.FILE_CLOSE, handleFileClose);\n        CommandManager.register(Strings.CMD_FILE_CLOSE_ALL,     Commands.FILE_CLOSE_ALL, handleFileCloseAll);\n        CommandManager.register(Strings.CMD_CLOSE_WINDOW,       Commands.FILE_CLOSE_WINDOW, handleFileCloseWindow);\n        CommandManager.register(Strings.CMD_QUIT,               Commands.FILE_QUIT, handleFileQuit);\n        CommandManager.register(Strings.CMD_REFRESH_WINDOW,     Commands.DEBUG_REFRESH_WINDOW, handleFileReload);\n        CommandManager.register(Strings.CMD_NEXT_DOC,           Commands.NAVIGATE_NEXT_DOC, handleGoNextDoc);\n        CommandManager.register(Strings.CMD_PREV_DOC,           Commands.NAVIGATE_PREV_DOC, handleGoPrevDoc);\n        CommandManager.register(Strings.CMD_ABORT_QUIT,         Commands.APP_ABORT_QUIT, _handleAbortQuit);\n\n        KeyBindingManager.addBinding(Commands.NAVIGATE_NEXT_DOC, [{key: \"Ctrl-Tab\",   platform: \"win\"},\n                                                                    {key: \"Ctrl-Tab\",  platform:  \"mac\"}]);\n        KeyBindingManager.addBinding(Commands.NAVIGATE_PREV_DOC, [{key: \"Ctrl-Shift-Tab\",   platform: \"win\"},\n                                                                    {key: \"Ctrl-Shift-Tab\",  platform:  \"mac\"}]);\n        \n        // Listen for changes that require updating the editor titlebar\n        $(DocumentManager).on(\"dirtyFlagChange\", handleDirtyChange);\n        $(DocumentManager).on(\"currentDocumentChange\", handleCurrentDocumentChange);\n    }\n\n    // Define public API\n    exports.init = init;\n});\n\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, FileError */\n\n/**\n * FileSyncManager is a set of utilities to help track external modifications to the files and folders\n * in the currently open project.\n *\n * Currently, we look for external changes purely by checking file timestamps against the last-sync\n * timestamp recorded on Document. Later, we will use actual native directory-watching callbacks\n * instead.\n *\n * FUTURE: Whenever we have a 'project file tree model,' we should manipulate that instead of notifying\n * DocumentManager directly. DocumentManager, the tree UI, etc. then all listen to that model for changes.\n */\ndefine('project/FileSyncManager',['require','exports','module','project/ProjectManager','document/DocumentManager','editor/EditorManager','command/Commands','command/CommandManager','utils/Async','widgets/Dialogs','strings','utils/StringUtils','file/FileUtils'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var ProjectManager      = require(\"project/ProjectManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        Commands            = require(\"command/Commands\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Async               = require(\"utils/Async\"),\n        Dialogs             = require(\"widgets/Dialogs\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        FileUtils           = require(\"file/FileUtils\");\n\n    \n    /**\n     * Guard to spot re-entrancy while syncOpenDocuments() is still in progress\n     * @type {boolean}\n     */\n    var _alreadyChecking = false;\n    \n    /**\n     * If true, we should bail from the syncOpenDocuments() process and then re-run it. See\n     * comments in syncOpenDocuments() for how this works.\n     * @type {boolean}\n     */\n    var _restartPending = false;\n    \n    /** @type {Array.<Document>} */\n    var toReload;\n    /** @type {Array.<Document>} */\n    var toClose;\n    /** @type {Array.<Document>} */\n    var editConflicts;\n    /** @type {Array.<Document>} */\n    var deleteConflicts;\n    \n    \n    /**\n     * Scans all the given Documents for changes on disk, and sorts them into four buckets,\n     * populating the corresponding arrays:\n     *  toReload        - changed on disk; unchanged within Brackets\n     *  toClose         - deleted on disk; unchanged within Brackets\n     *  editConflicts   - changed on disk; also dirty in Brackets\n     *  deleteConflicts - deleted on disk; also dirty in Brackets\n     *\n     * @param {!Array.<Document>} docs\n     * @return {$.Promise}  Resolved when all scanning done, or rejected immediately if there's any\n     *      error while reading file timestamps. Errors are logged but no UI is shown.\n     */\n    function findExternalChanges(docs) {\n\n        toReload = [];\n        toClose = [];\n        editConflicts = [];\n        deleteConflicts = [];\n    \n        function checkDoc(doc) {\n            var result = new $.Deferred();\n            \n            // Check file timestamp / existence\n            doc.file.getMetadata(\n                function (metadata) {\n                    // Does file's timestamp differ from last sync time on the Document?\n                    if (metadata.modificationTime.getTime() !== doc.diskTimestamp.getTime()) {\n                        if (doc.isDirty) {\n                            editConflicts.push(doc);\n                        } else {\n                            toReload.push(doc);\n                        }\n                    }\n                    result.resolve();\n                },\n                function (error) {\n                    // File has been deleted externally\n                    if (error.code === FileError.NOT_FOUND_ERR) {\n                        if (doc.isDirty) {\n                            deleteConflicts.push(doc);\n                        } else {\n                            toClose.push(doc);\n                        }\n                        result.resolve();\n                    } else {\n                        // Some other error fetching metadata: treat as a real error\n                        console.log(\"Error checking modification status of \" + doc.file.fullPath, error.code);\n                        result.reject();\n                    }\n                }\n            );\n            return result.promise();\n        }\n        \n        // Check all docs in parallel\n        // (fail fast b/c we won't continue syncing if there was any error fetching timestamps)\n        return Async.doInParallel(docs, checkDoc, true);\n    }\n    \n    /**\n     * Scans all the files in the working set that do not have Documents (and thus were not scanned\n     * by findExternalChanges()). If any were deleted on disk, removes them from the working set.\n     */\n    function syncUnopenWorkingSet() {\n        // We only care about working set entries that have never been open (have no Document).\n        var unopenWorkingSetFiles = DocumentManager.getWorkingSet().filter(function (wsFile) {\n            return !DocumentManager.getOpenDocumentForPath(wsFile.fullPath);\n        });\n        \n        function checkWorkingSetFile(file) {\n            var result = new $.Deferred();\n            \n            file.getMetadata(\n                function (metadata) {\n                    // File still exists\n                    result.resolve();\n                },\n                function (error) {\n                    // File has been deleted externally\n                    if (error.code === FileError.NOT_FOUND_ERR) {\n                        DocumentManager.notifyFileDeleted(file);\n                        result.resolve();\n                    } else {\n                        // Some other error fetching metadata: treat as a real error\n                        console.log(\"Error checking for deletion of \" + file.fullPath, error.code);\n                        result.reject();\n                    }\n                }\n            );\n            return result.promise();\n        }\n        \n        // Check all these files in parallel\n        return Async.doInParallel(unopenWorkingSetFiles, checkWorkingSetFile, false);\n    }\n    \n    \n    /**\n     * Reloads the Document's contents from disk, discarding any unsaved changes in the editor.\n     *\n     * @param {!Document} doc\n     * @return {$.Promise} Resolved after editor has been refreshed; rejected if unable to load the\n     *      file's new content. Errors are logged but no UI is shown.\n     */\n    function reloadDoc(doc) {\n        \n        var promise = FileUtils.readAsText(doc.file);\n        \n        promise.done(function (text, readTimestamp) {\n            doc.refreshText(text, readTimestamp);\n        });\n        promise.fail(function (error) {\n            console.log(\"Error reloading contents of \" + doc.file.fullPath, error.code);\n        });\n        return promise;\n    }\n    \n    /**\n     * Reloads all the documents in \"toReload\" silently (no prompts). The operations are all run\n     * in parallel.\n     * @return {$.Promise} Resolved/rejected after all reloads done; will be rejected if any one\n     *      file's reload failed. Errors are logged (by reloadDoc()) but no UI is shown.\n     */\n    function reloadChangedDocs() {\n        // Reload each doc in turn, and once all are (async) done, signal that we're done\n        return Async.doInParallel(toReload, reloadDoc, false);\n    }\n    \n    /**\n     * @param {FileError} error\n     * @param {!Document} doc\n     * @return {$.Promise}\n     */\n    function showReloadError(error, doc) {\n        return Dialogs.showModalDialog(\n            Dialogs.DIALOG_ID_ERROR,\n            Strings.ERROR_RELOADING_FILE_TITLE,\n            StringUtils.format(\n                Strings.ERROR_RELOADING_FILE,\n                StringUtils.htmlEscape(doc.file.fullPath),\n                FileUtils.getFileErrorString(error.code)\n            )\n        );\n    }\n    \n    \n    /**\n     * Closes all the documents in \"toClose\" silently (no prompts). Completes synchronously.\n     */\n    function closeDeletedDocs() {\n        toClose.forEach(function (doc) {\n            DocumentManager.notifyFileDeleted(doc.file);\n        });\n    }\n    \n    \n    /**\n     * Walks through all the documents in \"editConflicts\" & \"deleteConflicts\" and prompts the user\n     * about each one. Processing is sequential: if the user chooses to reload a document, the next\n     * prompt is not shown until after the reload has completed.\n     *\n     * @return {$.Promise} Resolved/rejected after all documents have been prompted and (if\n     *      applicable) reloaded (and any resulting error UI has been dismissed). Rejected if any\n     *      one reload failed.\n     */\n    function presentConflicts() {\n        \n        var allConflicts = editConflicts.concat(deleteConflicts);\n        \n        function presentConflict(doc, i) {\n            var result = new $.Deferred(), promise = result.promise();\n            \n            // If window has been re-focused, skip all remaining conflicts so the sync can bail & restart\n            if (_restartPending) {\n                result.resolve();\n                return promise;\n            }\n            \n            var message;\n            var dialogId;\n            var toClose;\n            \n            // Prompt UI varies depending on whether the file on disk was modified vs. deleted\n            if (i < editConflicts.length) {\n                toClose = false;\n                dialogId = Dialogs.DIALOG_ID_EXT_CHANGED;\n                message = StringUtils.format(\n                    Strings.EXT_MODIFIED_MESSAGE,\n                    StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n                );\n                \n            } else {\n                toClose = true;\n                dialogId = Dialogs.DIALOG_ID_EXT_DELETED;\n                message = StringUtils.format(\n                    Strings.EXT_DELETED_MESSAGE,\n                    StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(doc.file.fullPath))\n                );\n            }\n            \n            Dialogs.showModalDialog(dialogId, Strings.EXT_MODIFIED_TITLE, message)\n                .done(function (id) {\n                    if (id === Dialogs.DIALOG_BTN_DONTSAVE) {\n                        if (toClose) {\n                            // Discard - close all editors\n                            DocumentManager.notifyFileDeleted(doc.file);\n                            result.resolve();\n                        } else {\n                            // Discard - load changes from disk\n                            reloadDoc(doc)\n                                .done(function () {\n                                    result.resolve();\n                                })\n                                .fail(function (error) {\n                                    // Unable to load changed version from disk - show error UI\n                                    showReloadError(error, doc)\n                                        .always(function () {\n                                            // After user dismisses, move on to next conflict prompt\n                                            result.reject();\n                                        });\n                                });\n                        }\n                        \n                    } else {\n                        // Cancel - if user doesn't manually save or close, we'll prompt again next\n                        // time window is reactivated;\n                        // OR programmatically canceled due to _resetPending - we'll skip all\n                        // remaining files in the conflicts list (see above)\n                        result.resolve();\n                    }\n                });\n            \n            return promise;\n        }\n        \n        // Begin walking through the conflicts, one at a time\n        return Async.doSequentially(allConflicts, presentConflict, false);\n    }\n    \n    \n    \n    /**\n     * Check to see whether any open files have been modified by an external app since the last time\n     * Brackets synced up with the copy on disk (either by loading or saving the file). For clean\n     * files, we silently upate the editor automatically. For files with unsaved changes, we prompt\n     * the user.\n     */\n    function syncOpenDocuments() {\n        \n        // We can become \"re-entrant\" if the user leaves & then returns to Brackets before we're\n        // done -- easy if a prompt dialog is left open. Since the user may have left Brackets to\n        // revert some of the disk changes, etc. we want to cancel the current sync and immediately\n        // begin a new one. We let the orig sync run until the user-visible dialog phase, then\n        // bail; if we're already there we programmatically close the dialog to bail right away.\n        if (_alreadyChecking) {\n            _restartPending = true;\n            \n            // Close dialog if it was open. This will 'unblock' presentConflict(), which bails back\n            // to us immediately upon seeing _restartPending. We then restart the sync - see below\n            Dialogs.cancelModalDialogIfOpen(Dialogs.DIALOG_ID_EXT_CHANGED);\n            Dialogs.cancelModalDialogIfOpen(Dialogs.DIALOG_ID_EXT_DELETED);\n            \n            return;\n        }\n        \n        _alreadyChecking = true;\n        \n        \n        // Syncing proceeds in four phases:\n        //  1) Check all open files for external modifications\n        //  2) Check any other working set entries (that are not open) for deletion, and remove\n        //     from working set if deleted\n        //  3) Refresh all Documents that are clean (if file changed on disk)\n        //  4) Close all Documents that are clean (if file deleted on disk)\n        //  5) Prompt about any Documents that are dirty (if file changed/deleted on disk)\n        // Each phase fully completes (asynchronously) before the next one begins.\n        \n        \n        // 1) Check for external modifications\n        var allDocs = DocumentManager.getAllOpenDocuments();\n        \n        findExternalChanges(allDocs)\n            .done(function () {\n                // 2) Check un-open working set entries for deletion (& \"close\" if needed)\n                syncUnopenWorkingSet()\n                    .always(function () {\n                        // If we were unable to check any un-open files for deletion, silently ignore\n                        // (after logging to console). This doesn't have any bearing on syncing truly\n                        // open Documents (which we've already successfully checked).\n                        \n                        // 3) Reload clean docs as needed\n                        reloadChangedDocs()\n                            .always(function () {\n                                // 4) Close clean docs as needed\n                                // This phase completes synchronously\n                                closeDeletedDocs();\n                                \n                                // 5) Prompt for dirty editors (conflicts)\n                                presentConflicts()\n                                    .always(function () {\n                                        if (_restartPending) {\n                                            // Restart the sync if needed\n                                            _restartPending = false;\n                                            _alreadyChecking = false;\n                                            syncOpenDocuments();\n                                        } else {\n                                            // We're really done!\n                                            _alreadyChecking = false;\n                                            \n                                            // If we showed a dialog, restore focus to editor\n                                            if (editConflicts.length > 0 || deleteConflicts.length > 0) {\n                                                EditorManager.focusEditor();\n                                            }\n                                            \n                                            // (Any errors that ocurred during presentConflicts() have already\n                                            // shown UI & been dismissed, so there's no fail() handler here)\n                                        }\n                                    });\n                            });\n                            // Note: if any auto-reloads failed, we silently ignore (after logging to console)\n                            // and we still continue onto phase 4 and try to process those files anyway.\n                            // (We'll retry the auto-reloads next time window is activated... and evenually\n                            // we'll also be double checking before each Save).\n                    });\n            }).fail(function () {\n                // Unable to fetch timestamps for some reason - silently ignore (after logging to console)\n                // (We'll retry next time window is activated... and evenually we'll also be double\n                // checking before each Save).\n                \n                // We can't go on without knowing which files are dirty, so bail now\n                _alreadyChecking = false;\n            });\n        \n    }\n    \n    \n    // Define public API\n    exports.syncOpenDocuments = syncOpenDocuments;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * Utilities for determining the current \"build number\" / version\n */\ndefine('utils/BuildInfoUtils',['require','exports','module','file/NativeFileSystem','file/FileUtils'],function (require, exports, module) {\n    \n    \n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        FileUtils           = require(\"file/FileUtils\");\n    \n    \n    var _bracketsSHA = null;\n    var _bracketsAppSHA = null;\n    \n    /**\n     * @return {?string} the Git SHA of the brackets submodule at the time when Brackets launched,\n     *      or null if no Git metadata was found on disk.\n     */\n    function getBracketsSHA() {\n        return _bracketsSHA;\n    }\n    \n    /**\n     * @return {?string} the Git SHA of the brackets-app module at the time when Brackets launched,\n     *      or null if no Git metadata was found on disk.\n     */\n    function getBracketsAppSHA() {\n        return _bracketsAppSHA;\n    }\n    \n    \n    /**\n     * Loads a SHA from Git metadata file. If the file contains a symbolic ref name, follows the ref\n     * and loads the SHA from that file in turn.\n     */\n    function _loadSHA(path, callback) {\n        var fileEntry = new NativeFileSystem.FileEntry(path);\n        var reader = new NativeFileSystem.FileReader();\n        \n        var result = new $.Deferred();\n        \n        // HEAD contains a SHA in detached-head mode; otherwise it contains a relative path\n        // to a file in /refs which in turn contains the SHA\n        fileEntry.file(function (file) {\n            reader.onload = function (event) {\n                var text = event.target.result;\n                \n                if (text.indexOf(\"ref: \") === 0) {\n                    var basePath = path.substr(0, path.lastIndexOf(\"/\"));\n                    var refRelPath = text.substr(5).trim();\n                    _loadSHA(basePath + \"/\" + refRelPath, callback)\n                        .pipe(result.resolve, result.reject);\n                } else {\n                    result.resolve(text);\n                }\n            };\n            reader.onerror = function (event) {\n                result.reject();\n            };\n            \n            reader.readAsText(file, \"utf8\");\n        });\n        \n        return result.promise();\n    }\n    \n    function init() {\n        // Look for Git metadata on disk to load the SHAs for 'brackets' and 'brackets-app'. Done on\n        // startup instead of on demand because the version that's currently running is what was\n        // loaded at startup (the src on disk may be updated to a different version later).\n        // Git metadata may be missing (e.g. in the per-sprint ZIP builds) - silently ignore if so.\n        var bracketsSrc = FileUtils.getNativeBracketsDirectoryPath();\n        var bracketsGitRoot = bracketsSrc + \"/../../.git/\";\n        var bracketsSubmoduleRoot_inParent = bracketsGitRoot + \"modules/brackets/\";\n        var bracketsSubmoduleRoot_inSubmodule = bracketsSrc + \"/../.git/\";\n        \n        _loadSHA(bracketsGitRoot + \"HEAD\")\n            .done(function (text) {\n                _bracketsAppSHA = text;\n            });\n        \n        // brackets submodule metadata may be in brackets/.git OR a subfolder of brackets-app/.git,\n        // so try both locations\n        _loadSHA(bracketsSubmoduleRoot_inSubmodule + \"HEAD\")\n            .done(function (text) {\n                _bracketsSHA = text;\n            })\n            .fail(function () {\n                _loadSHA(bracketsSubmoduleRoot_inParent + \"HEAD\")\n                    .done(function (text) {\n                        _bracketsSHA = text;\n                    });\n            });\n    }\n    \n    \n    // Define public API\n    exports.init                = init;\n    exports.getBracketsSHA      = getBracketsSHA;\n    exports.getBracketsAppSHA   = getBracketsAppSHA;\n});\n// jslint.js\n// 2012-01-13\n\n// Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n\n// The Software shall be used for Good, not Evil.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// WARNING: JSLint will hurt your feelings.\n\n// JSLINT is a global function. It takes two parameters.\n\n//     var myResult = JSLINT(source, option);\n\n// The first parameter is either a string or an array of strings. If it is a\n// string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n// is assumed that each string represents one line. The source can be a\n// JavaScript text, or HTML text, or a JSON text, or a CSS text.\n\n// The second parameter is an optional object of options that control the\n// operation of JSLINT. Most of the options are booleans: They are all\n// optional and have a default value of false. One of the options, predef,\n// can be an array of names, which will be used to declare global variables,\n// or an object whose keys are used as global names, with a boolean value\n// that determines if they are assignable.\n\n// If it checks out, JSLINT returns true. Otherwise, it returns false.\n\n// If false, you can inspect JSLINT.errors to find out the problems.\n// JSLINT.errors is an array of objects containing these properties:\n\n//  {\n//      line      : The line (relative to 0) at which the lint was found\n//      character : The character (relative to 0) at which the lint was found\n//      reason    : The problem\n//      evidence  : The text line in which the problem occurred\n//      raw       : The raw message before the details were inserted\n//      a         : The first detail\n//      b         : The second detail\n//      c         : The third detail\n//      d         : The fourth detail\n//  }\n\n// If a stopping error was found, a null will be the last element of the\n// JSLINT.errors array. A stopping error means that JSLint was not confident\n// enough to continue. It does not necessarily mean that the error was\n// especially heinous.\n\n// You can request a Function Report, which shows all of the functions\n// and the parameters and vars that they use. This can be used to find\n// implied global variables and other problems. The report is in HTML and\n// can be inserted in an HTML <body>.\n\n//     var myReport = JSLINT.report(errors_only);\n\n// If errors_only is true, then the report will be limited to only errors.\n\n// You can request a data structure that contains JSLint's results.\n\n//     var myData = JSLINT.data();\n\n// It returns a structure with this form:\n\n//     {\n//         errors: [\n//             {\n//                 line: NUMBER,\n//                 character: NUMBER,\n//                 reason: STRING,\n//                 evidence: STRING\n//             }\n//         ],\n//         functions: [\n//             {\n//                 name: STRING,\n//                 line: NUMBER,\n//                 last: NUMBER,\n//                 params: [\n//                     {\n//                         string: STRING\n//                     }\n//                 ],\n//                 closure: [\n//                     STRING\n//                 ],\n//                 var: [\n//                     STRING\n//                 ],\n//                 exception: [\n//                     STRING\n//                 ],\n//                 outer: [\n//                     STRING\n//                 ],\n//                 unused: [\n//                     STRING\n//                 ],\n//                 undef: [\n//                     STRING\n//                 ],\n//                 global: [\n//                     STRING\n//                 ],\n//                 label: [\n//                     STRING\n//                 ]\n//             }\n//         ],\n//         globals: [\n//             STRING\n//         ],\n//         member: {\n//             STRING: NUMBER\n//         },\n//         urls: [\n//             STRING\n//         ],\n//         json: BOOLEAN\n//     }\n\n// Empty arrays will not be included.\n\n// You can obtain the parse tree that JSLint constructed while parsing. The\n// latest tree is kept in JSLINT.tree. A nice stringication can be produced\n// with\n\n//     JSON.stringify(JSLINT.tree, [\n//         'string',  'arity', 'name',  'first',\n//         'second', 'third', 'block', 'else'\n//     ], 4));\n\n// JSLint provides three directives. They look like slashstar comments, and\n// allow for setting options, declaring global variables, and establishing a\n// set of allowed property names.\n\n// These directives respect function scope.\n\n// The jslint directive is a special comment that can set one or more options.\n// The current option set is\n\n//     anon       true, if the space may be omitted in anonymous function declarations\n//     bitwise    true, if bitwise operators should be allowed\n//     browser    true, if the standard browser globals should be predefined\n//     cap        true, if upper case HTML should be allowed\n//     confusion  true, if types can be used inconsistently\n//     'continue' true, if the continuation statement should be tolerated\n//     css        true, if CSS workarounds should be tolerated\n//     debug      true, if debugger statements should be allowed\n//     devel      true, if logging should be allowed (console, alert, etc.)\n//     eqeq       true, if == should be allowed\n//     es5        true, if ES5 syntax should be allowed\n//     evil       true, if eval should be allowed\n//     forin      true, if for in statements need not filter\n//     fragment   true, if HTML fragments should be allowed\n//     indent     the indentation factor\n//     maxerr     the maximum number of errors to allow\n//     maxlen     the maximum length of a source line\n//     newcap     true, if constructor names capitalization is ignored\n//     node       true, if Node.js globals should be predefined\n//     nomen      true, if names may have dangling _\n//     on         true, if HTML event handlers should be allowed\n//     passfail   true, if the scan should stop on first error\n//     plusplus   true, if increment/decrement should be allowed\n//     properties true, if all property names must be declared with /*properties*/\n//     regexp     true, if the . should be allowed in regexp literals\n//     rhino      true, if the Rhino environment globals should be predefined\n//     undef      true, if variables can be declared out of order\n//     unparam    true, if unused parameters should be tolerated\n//     sloppy     true, if the  pragma is optional\n//     sub        true, if all forms of subscript notation are tolerated\n//     vars       true, if multiple var statements per function should be allowed\n//     white      true, if sloppy whitespace is tolerated\n//     widget     true  if the Yahoo Widgets globals should be predefined\n//     windows    true, if MS Windows-specific globals should be predefined\n\n// For example:\n\n/*jslint\n    evil: true, nomen: true, regexp: true\n*/\n\n// The properties directive declares an exclusive list of property names.\n// Any properties named in the program that are not in the list will\n// produce a warning.\n\n// For example:\n\n/*properties\n    '\\b': string, '\\t': string, '\\n': string, '\\f': string, '\\r': string,\n    '!=': boolean, '!==': boolean, '\"': string, '%': boolean, '\\'': string,\n    '(begin)', '(breakage)': number, '(confusion)': boolean,\n    '(context)': object, '(error)', '(identifier)', '(line)': number,\n    '(loopage)': number, '(name)', '(old_property_type)', '(params)',\n    '(scope)': object, '(token)', '(vars)', '(verb)', '*': boolean,\n    '+': boolean, '-': boolean, '/': *, '<': boolean, '<=': boolean,\n    '==': boolean, '===': boolean, '>': boolean, '>=': boolean,\n    ADSAFE: boolean, Array, Date, E: string, Function, LN10: string,\n    LN2: string, LOG10E: string, LOG2E: string, MAX_VALUE: string,\n    MIN_VALUE: string, NEGATIVE_INFINITY: string, Object, PI: string,\n    POSITIVE_INFINITY: string, SQRT1_2: string, SQRT2: string, '\\\\': string,\n    a: object, a_label: string, a_not_allowed: string, a_not_defined: string,\n    a_scope: string, abbr: object, acronym: object, address: object, adsafe,\n    adsafe_a: string, adsafe_autocomplete: string, adsafe_bad_id: string,\n    adsafe_div: string, adsafe_fragment: string, adsafe_go: string,\n    adsafe_html: string, adsafe_id: string, adsafe_id_go: string,\n    adsafe_lib: string, adsafe_lib_second: string, adsafe_missing_id: string,\n    adsafe_name_a: string, adsafe_placement: string, adsafe_prefix_a: string,\n    adsafe_script: string, adsafe_source: string, adsafe_subscript_a: string,\n    adsafe_tag: string, all: boolean, already_defined: string, and: string,\n    anon, applet: object, apply: string, approved: array, area: object,\n    arity: string, article: object, aside: object, assign: boolean,\n    assign_exception: string, assignment_function_expression: string,\n    at: number, attribute_case_a: string, audio: object, autocomplete: string,\n    avoid_a: string, b: *, background: array, 'background-attachment': array,\n    'background-color': array, 'background-image': array,\n    'background-position': array, 'background-repeat': array,\n    bad_assignment: string, bad_color_a: string, bad_constructor: string,\n    bad_entity: string, bad_html: string, bad_id_a: string, bad_in_a: string,\n    bad_invocation: string, bad_name_a: string, bad_new: string,\n    bad_number: string, bad_operand: string, bad_style: string,\n    bad_type: string, bad_url_a: string, bad_wrap: string, base: object,\n    bdo: object, big: object, bind: string, bitwise: boolean, block: array,\n    blockquote: object, body: object, border: array, 'border-bottom': array,\n    'border-bottom-color', 'border-bottom-left-radius',\n    'border-bottom-right-radius', 'border-bottom-style': array,\n    'border-bottom-width', 'border-collapse': array, 'border-color': array,\n    'border-left': array, 'border-left-color', 'border-left-style': array,\n    'border-left-width', 'border-radius', 'border-right': array,\n    'border-right-color', 'border-right-style': array, 'border-right-width',\n    'border-spacing': array, 'border-style': array, 'border-top': array,\n    'border-top-color', 'border-top-left-radius', 'border-top-right-radius',\n    'border-top-style': array, 'border-top-width', 'border-width': array,\n    bottom: array, br: object, braille: boolean, browser: boolean,\n    button: object, c, call: string, canvas: object, cap, caption: object,\n    'caption-side': array, ceil: string, center: object, charAt: *,\n    charCodeAt: *, character, cite: object, clear: array, clip: array, closure,\n    cm: boolean, code: object, col: object, colgroup: object, color,\n    combine_var: string, command: object, concat: string,\n    conditional_assignment: string, confusing_a: string,\n    confusing_regexp: string, confusion: boolean, constructor: string,\n    constructor_name_a: string, content: array, continue, control_a: string,\n    'counter-increment': array, 'counter-reset': array, create: *, css: string,\n    cursor: array, d, dangerous_comment: string, dangling_a: string,\n    data: function object, datalist: object, dd: object, debug,\n    defineProperties: string, defineProperty: string, del: object,\n    deleted: string, details: object, devel: boolean, dfn: object,\n    dialog: object, dir: object, direction: array, display: array,\n    disrupt: boolean, div: object, dl: object, dt: object, duplicate_a: string,\n    edge: string, edition: string, else, em: *, embed: object,\n    embossed: boolean, empty: boolean, 'empty-cells': array,\n    empty_block: string, empty_case: string, empty_class: string,\n    entityify: function, eqeq, errors: array, es5: string, eval, every: string,\n    evidence, evil: string, ex: boolean, exception, exec: *,\n    expected_a: string, expected_a_at_b_c: string, expected_a_b: string,\n    expected_a_b_from_c_d: string, expected_at_a: string,\n    expected_attribute_a: string, expected_attribute_value_a: string,\n    expected_class_a: string, expected_fraction_a: string,\n    expected_id_a: string, expected_identifier_a: string,\n    expected_identifier_a_reserved: string, expected_lang_a: string,\n    expected_linear_a: string, expected_media_a: string,\n    expected_name_a: string, expected_nonstandard_style_attribute: string,\n    expected_number_a: string, expected_operator_a: string,\n    expected_percent_a: string, expected_positive_a: string,\n    expected_pseudo_a: string, expected_selector_a: string,\n    expected_small_a: string, expected_space_a_b: string,\n    expected_string_a: string, expected_style_attribute: string,\n    expected_style_pattern: string, expected_tagname_a: string,\n    expected_type_a: string, f: string, fieldset: object, figure: object,\n    filter: *, first: *, flag, float: array, floor: *, font: *, 'font-family',\n    'font-size': array, 'font-size-adjust': array, 'font-stretch': array,\n    'font-style': array, 'font-variant': array, 'font-weight': array,\n    footer: object, for, forEach: *, for_if: string, forin, form: object,\n    fragment, frame: object, frameset: object, freeze: string, from: number,\n    fromCharCode: function, fud: function, funct: object, function,\n    function_block: string, function_eval: string, function_loop: string,\n    function_statement: string, function_strict: string, functions: array,\n    getDate: string, getDay: string, getFullYear: string, getHours: string,\n    getMilliseconds: string, getMinutes: string, getMonth: string,\n    getOwnPropertyDescriptor: string, getOwnPropertyNames: string,\n    getPrototypeOf: string, getSeconds: string, getTime: string,\n    getTimezoneOffset: string, getUTCDate: string, getUTCDay: string,\n    getUTCFullYear: string, getUTCHours: string, getUTCMilliseconds: string,\n    getUTCMinutes: string, getUTCMonth: string, getUTCSeconds: string,\n    getYear: string, global, globals, h1: object, h2: object, h3: object,\n    h4: object, h5: object, h6: object, handheld: boolean, hasOwnProperty: *,\n    head: object, header: object, height: array, hgroup: object, hr: object,\n    'hta:application': object, html: *, html_confusion_a: string,\n    html_handlers: string, i: object, id: string, identifier: boolean,\n    identifier_function: string, iframe: object, img: object, immed: boolean,\n    implied_evil: string, in, indent: number, indexOf: *, infix_in: string,\n    init: function, input: object, ins: object, insecure_a: string,\n    isAlpha: function, isArray: function boolean, isDigit: function,\n    isExtensible: string, isFrozen: string, isNaN: string,\n    isPrototypeOf: string, isSealed: string, join: *, jslint: function boolean,\n    json: boolean, kbd: object, keygen: object, keys: *, label: object,\n    label_a_b: string, labeled: boolean, lang: string, lastIndex: string,\n    lastIndexOf: *, lbp: number, leading_decimal_a: string, led: function,\n    left: array, legend: object, length: *, 'letter-spacing': array,\n    li: object, lib: boolean, line: number, 'line-height': array, link: object,\n    'list-style': array, 'list-style-image': array,\n    'list-style-position': array, 'list-style-type': array, map: *,\n    margin: array, 'margin-bottom', 'margin-left', 'margin-right',\n    'margin-top', mark: object, 'marker-offset': array, match: function,\n    'max-height': array, 'max-width': array, maxerr: number,\n    maxlen: number, member: object, menu: object, message, meta: object,\n    meter: object, 'min-height': function, 'min-width': function,\n    missing_a: string, missing_a_after_b: string, missing_option: string,\n    missing_property: string, missing_space_a_b: string, missing_url: string,\n    missing_use_strict: string, mixed: string, mm: boolean, mode: string,\n    move_invocation: string, move_var: string, n: string, name: string,\n    name_function: string, nav: object, nested_comment: string,\n    newcap: boolean, node: boolean, noframes: object, nomen, noscript: object,\n    not: string, not_a_constructor: string, not_a_defined: string,\n    not_a_function: string, not_a_label: string, not_a_scope: string,\n    not_greater: string, now: string, nud: function, number: number,\n    object: object, ol: object, on, opacity, open: boolean, optgroup: object,\n    option: object, outer: regexp, outline: array, 'outline-color': array,\n    'outline-style': array, 'outline-width', output: object, overflow: array,\n    'overflow-x': array, 'overflow-y': array, p: object, padding: array,\n    'padding-bottom': function, 'padding-left': function,\n    'padding-right': function, 'padding-top': function,\n    'page-break-after': array, 'page-break-before': array, param: object,\n    parameter_a_get_b: string, parameter_set_a: string, params: array,\n    paren: boolean, parent: string, parse: string, passfail, pc: boolean,\n    plusplus, pop: *, position: array, postscript: boolean, pre: object,\n    predef, preventExtensions: string, print: boolean, progress: object,\n    projection: boolean, properties: boolean, propertyIsEnumerable: string,\n    prototype: string, pt: boolean, push: *, px: boolean, q: object, quote,\n    quotes: array, r: string, radix: string, range: function, raw,\n    read_only: string, reason, redefinition_a: string, reduce: string,\n    reduceRight: string, regexp, replace: function, report: function,\n    reserved: boolean, reserved_a: string, reverse: string, rhino: boolean,\n    right: array, rp: object, rt: object, ruby: object, safe: boolean,\n    samp: object, scanned_a_b: string, screen: boolean, script: object,\n    seal: string, search: function, second: *, section: object, select: object,\n    setDate: string, setDay: string, setFullYear: string, setHours: string,\n    setMilliseconds: string, setMinutes: string, setMonth: string,\n    setSeconds: string, setTime: string, setTimezoneOffset: string,\n    setUTCDate: string, setUTCDay: string, setUTCFullYear: string,\n    setUTCHours: string, setUTCMilliseconds: string, setUTCMinutes: string,\n    setUTCMonth: string, setUTCSeconds: string, setYear: string, shift: *,\n    slash_equal: string, slice: string, sloppy, small: object, some: string,\n    sort: *, source: object, span: object, speech: boolean, splice: string,\n    split: function, src, statement_block: string, stopping: string,\n    strange_loop: string, strict: string, string: string, stringify: string,\n    strong: object, style: *, styleproperty: regexp, sub: object,\n    subscript: string, substr: *, substring: string, sup: object,\n    supplant: function, t: string, table: object, 'table-layout': array,\n    tag_a_in_b: string, tbody: object, td: object, test: *,\n    'text-align': array, 'text-decoration': array, 'text-indent': function,\n    'text-shadow': array, 'text-transform': array, textarea: object,\n    tfoot: object, th: object, thead: object, third: array, thru: number,\n    time: object, title: object, toDateString: string, toExponential: string,\n    toFixed: string, toISOString: string, toJSON: string,\n    toLocaleDateString: string, toLocaleLowerCase: string,\n    toLocaleString: string, toLocaleTimeString: string,\n    toLocaleUpperCase: string, toLowerCase: *, toPrecision: string,\n    toString: function, toTimeString: string, toUTCString: string,\n    toUpperCase: *, token: function, too_long: string, too_many: string,\n    top: array, tr: object, trailing_decimal_a: string, tree: string,\n    trim: string, tt: object, tty: boolean, tv: boolean, type: string,\n    type_confusion_a_b: string, u: object, ul: object, unclosed: string,\n    unclosed_comment: string, unclosed_regexp: string, undef: boolean,\n    undefined, unescaped_a: string, unexpected_a: string,\n    unexpected_char_a_b: string, unexpected_comment: string,\n    unexpected_property_a: string, unexpected_space_a_b: string,\n    'unicode-bidi': array, unnecessary_initialize: string,\n    unnecessary_use: string, unparam, unreachable_a_b: string,\n    unrecognized_style_attribute_a: string, unrecognized_tag_a: string,\n    unsafe: string, unshift: string, unused: array, url: string, urls: array,\n    use_array: string, use_braces: string, use_charAt: string,\n    use_object: string, use_or: string, use_param: string,\n    used_before_a: string, valueOf: string, var: object, var_a_not: string,\n    vars, 'vertical-align': array, video: object, visibility: array,\n    warn: boolean, was: object, weird_assignment: string,\n    weird_condition: string, weird_new: string, weird_program: string,\n    weird_relation: string, weird_ternary: string, white: boolean,\n    'white-space': array, widget: boolean, width: array, windows: boolean,\n    'word-spacing': array, 'word-wrap': array, wrap: boolean,\n    wrap_immediate: string, wrap_regexp: string, write_is_wrong: string,\n    writeable: boolean, 'z-index': array\n*/\n\n// The global directive is used to declare global variables that can\n// be accessed by the program. If a declaration is true, then the variable\n// is writeable. Otherwise, it is read-only.\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSLINT function itself. That function is also an object that\n// can contain data and other functions.\n\nvar JSLINT = (function () {\n    \n\n    function array_to_object(array, value) {\n\n// Make an object from an array of keys and a common value.\n\n        var i, length = array.length, object = {};\n        for (i = 0; i < length; i += 1) {\n            object[array[i]] = value;\n        }\n        return object;\n    }\n\n\n    var adsafe_id,      // The widget's ADsafe id.\n        adsafe_may,     // The widget may load approved scripts.\n        adsafe_top,     // At the top of the widget script.\n        adsafe_went,    // ADSAFE.go has been called.\n        allowed_option = {\n            anon      : true,\n            bitwise   : true,\n            browser   : true,\n            cap       : true,\n            confusion : true,\n            'continue': true,\n            css       : true,\n            debug     : true,\n            devel     : true,\n            eqeq      : true,\n            es5       : true,\n            evil      : true,\n            forin     : true,\n            fragment  : true,\n            indent    :   10,\n            maxerr    : 1000,\n            maxlen    :  256,\n            newcap    : true,\n            node      : true,\n            nomen     : true,\n            on        : true,\n            passfail  : true,\n            plusplus  : true,\n            properties: true,\n            regexp    : true,\n            rhino     : true,\n            undef     : true,\n            unparam   : true,\n            sloppy    : true,\n            sub       : true,\n            vars      : true,\n            white     : true,\n            widget    : true,\n            windows   : true\n        },\n        anonname,       // The guessed name for anonymous functions.\n        approved,       // ADsafe approved urls.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n// These are property names that should not be permitted in the safe subset.\n\n        banned = array_to_object([\n            'arguments', 'callee', 'caller', 'constructor', 'eval', 'prototype',\n            'stack', 'unwatch', 'valueOf', 'watch'\n        ], true),\n        begin,          // The root token\n\n// browser contains a set of global names that are commonly provided by a\n// web browser environment.\n\n        browser = array_to_object([\n            'clearInterval', 'clearTimeout', 'document', 'event', 'frames',\n            'history', 'Image', 'localStorage', 'location', 'name', 'navigator',\n            'Option', 'parent', 'screen', 'sessionStorage', 'setInterval',\n            'setTimeout', 'Storage', 'window', 'XMLHttpRequest'\n        ], false),\n\n// bundle contains the text messages.\n\n        bundle = {\n            a_label: \"'{a}' is a statement label.\",\n            a_not_allowed: \"'{a}' is not allowed.\",\n            a_not_defined: \"'{a}' is not defined.\",\n            a_scope: \"'{a}' used out of scope.\",\n            adsafe_a: \"ADsafe violation: '{a}'.\",\n            adsafe_autocomplete: \"ADsafe autocomplete violation.\",\n            adsafe_bad_id: \"ADSAFE violation: bad id.\",\n            adsafe_div: \"ADsafe violation: Wrap the widget in a div.\",\n            adsafe_fragment: \"ADSAFE: Use the fragment option.\",\n            adsafe_go: \"ADsafe violation: Misformed ADSAFE.go.\",\n            adsafe_html: \"Currently, ADsafe does not operate on whole HTML \" +\n                \"documents. It operates on <div> fragments and .js files.\",\n            adsafe_id: \"ADsafe violation: id does not match.\",\n            adsafe_id_go: \"ADsafe violation: Missing ADSAFE.id or ADSAFE.go.\",\n            adsafe_lib: \"ADsafe lib violation.\",\n            adsafe_lib_second: \"ADsafe: The second argument to lib must be a function.\",\n            adsafe_missing_id: \"ADSAFE violation: missing ID_.\",\n            adsafe_name_a: \"ADsafe name violation: '{a}'.\",\n            adsafe_placement: \"ADsafe script placement violation.\",\n            adsafe_prefix_a: \"ADsafe violation: An id must have a '{a}' prefix\",\n            adsafe_script: \"ADsafe script violation.\",\n            adsafe_source: \"ADsafe unapproved script source.\",\n            adsafe_subscript_a: \"ADsafe subscript '{a}'.\",\n            adsafe_tag: \"ADsafe violation: Disallowed tag '{a}'.\",\n            already_defined: \"'{a}' is already defined.\",\n            and: \"The '&&' subexpression should be wrapped in parens.\",\n            assign_exception: \"Do not assign to the exception parameter.\",\n            assignment_function_expression: \"Expected an assignment or \" +\n                \"function call and instead saw an expression.\",\n            attribute_case_a: \"Attribute '{a}' not all lower case.\",\n            avoid_a: \"Avoid '{a}'.\",\n            bad_assignment: \"Bad assignment.\",\n            bad_color_a: \"Bad hex color '{a}'.\",\n            bad_constructor: \"Bad constructor.\",\n            bad_entity: \"Bad entity.\",\n            bad_html: \"Bad HTML string\",\n            bad_id_a: \"Bad id: '{a}'.\",\n            bad_in_a: \"Bad for in variable '{a}'.\",\n            bad_invocation: \"Bad invocation.\",\n            bad_name_a: \"Bad name: '{a}'.\",\n            bad_new: \"Do not use 'new' for side effects.\",\n            bad_number: \"Bad number '{a}'.\",\n            bad_operand: \"Bad operand.\",\n            bad_style: \"Bad style.\",\n            bad_type: \"Bad type.\",\n            bad_url_a: \"Bad url '{a}'.\",\n            bad_wrap: \"Do not wrap function literals in parens unless they \" +\n                \"are to be immediately invoked.\",\n            combine_var: \"Combine this with the previous 'var' statement.\",\n            conditional_assignment: \"Expected a conditional expression and \" +\n                \"instead saw an assignment.\",\n            confusing_a: \"Confusing use of '{a}'.\",\n            confusing_regexp: \"Confusing regular expression.\",\n            constructor_name_a: \"A constructor name '{a}' should start with \" +\n                \"an uppercase letter.\",\n            control_a: \"Unexpected control character '{a}'.\",\n            css: \"A css file should begin with @charset 'UTF-8';\",\n            dangling_a: \"Unexpected dangling '_' in '{a}'.\",\n            dangerous_comment: \"Dangerous comment.\",\n            deleted: \"Only properties should be deleted.\",\n            duplicate_a: \"Duplicate '{a}'.\",\n            empty_block: \"Empty block.\",\n            empty_case: \"Empty case.\",\n            empty_class: \"Empty class.\",\n            es5: \"This is an ES5 feature.\",\n            evil: \"eval is evil.\",\n            expected_a: \"Expected '{a}'.\",\n            expected_a_b: \"Expected '{a}' and instead saw '{b}'.\",\n            expected_a_b_from_c_d: \"Expected '{a}' to match '{b}' from line \" +\n                \"{c} and instead saw '{d}'.\",\n            expected_at_a: \"Expected an at-rule, and instead saw @{a}.\",\n            expected_a_at_b_c: \"Expected '{a}' at column {b}, not column {c}.\",\n            expected_attribute_a: \"Expected an attribute, and instead saw [{a}].\",\n            expected_attribute_value_a: \"Expected an attribute value and \" +\n                \"instead saw '{a}'.\",\n            expected_class_a: \"Expected a class, and instead saw .{a}.\",\n            expected_fraction_a: \"Expected a number between 0 and 1 and \" +\n                \"instead saw '{a}'\",\n            expected_id_a: \"Expected an id, and instead saw #{a}.\",\n            expected_identifier_a: \"Expected an identifier and instead saw '{a}'.\",\n            expected_identifier_a_reserved: \"Expected an identifier and \" +\n                \"instead saw '{a}' (a reserved word).\",\n            expected_linear_a: \"Expected a linear unit and instead saw '{a}'.\",\n            expected_lang_a: \"Expected a lang code, and instead saw :{a}.\",\n            expected_media_a: \"Expected a CSS media type, and instead saw '{a}'.\",\n            expected_name_a: \"Expected a name and instead saw '{a}'.\",\n            expected_nonstandard_style_attribute: \"Expected a non-standard \" +\n                \"style attribute and instead saw '{a}'.\",\n            expected_number_a: \"Expected a number and instead saw '{a}'.\",\n            expected_operator_a: \"Expected an operator and instead saw '{a}'.\",\n            expected_percent_a: \"Expected a percentage and instead saw '{a}'\",\n            expected_positive_a: \"Expected a positive number and instead saw '{a}'\",\n            expected_pseudo_a: \"Expected a pseudo, and instead saw :{a}.\",\n            expected_selector_a: \"Expected a CSS selector, and instead saw {a}.\",\n            expected_small_a: \"Expected a small positive integer and instead saw '{a}'\",\n            expected_space_a_b: \"Expected exactly one space between '{a}' and '{b}'.\",\n            expected_string_a: \"Expected a string and instead saw {a}.\",\n            expected_style_attribute: \"Excepted a style attribute, and instead saw '{a}'.\",\n            expected_style_pattern: \"Expected a style pattern, and instead saw '{a}'.\",\n            expected_tagname_a: \"Expected a tagName, and instead saw {a}.\",\n            expected_type_a: \"Expected a type, and instead saw {a}.\",\n            for_if: \"The body of a for in should be wrapped in an if \" +\n                \"statement to filter unwanted properties from the prototype.\",\n            function_block: \"Function statements should not be placed in blocks. \" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\",\n            function_eval: \"The Function constructor is eval.\",\n            function_loop: \"Don't make functions within a loop.\",\n            function_statement: \"Function statements are not invocable. \" +\n                \"Wrap the whole function invocation in parens.\",\n            function_strict: \"Use the function form of 'use strict'.\",\n            html_confusion_a: \"HTML confusion in regular expression '<{a}'.\",\n            html_handlers: \"Avoid HTML event handlers.\",\n            identifier_function: \"Expected an identifier in an assignment \" +\n                \"and instead saw a function invocation.\",\n            implied_evil: \"Implied eval is evil. Pass a function instead of a string.\",\n            infix_in: \"Unexpected 'in'. Compare with undefined, or use the \" +\n                \"hasOwnProperty method instead.\",\n            insecure_a: \"Insecure '{a}'.\",\n            isNaN: \"Use the isNaN function to compare with NaN.\",\n            label_a_b: \"Label '{a}' on '{b}' statement.\",\n            lang: \"lang is deprecated.\",\n            leading_decimal_a: \"A leading decimal point can be confused with a dot: '.{a}'.\",\n            missing_a: \"Missing '{a}'.\",\n            missing_a_after_b: \"Missing '{a}' after '{b}'.\",\n            missing_option: \"Missing option value.\",\n            missing_property: \"Missing property name.\",\n            missing_space_a_b: \"Missing space between '{a}' and '{b}'.\",\n            missing_url: \"Missing url.\",\n            missing_use_strict: \"Missing 'use strict' statement.\",\n            mixed: \"Mixed spaces and tabs.\",\n            move_invocation: \"Move the invocation into the parens that \" +\n                \"contain the function.\",\n            move_var: \"Move 'var' declarations to the top of the function.\",\n            name_function: \"Missing name in function statement.\",\n            nested_comment: \"Nested comment.\",\n            not: \"Nested not.\",\n            not_a_constructor: \"Do not use {a} as a constructor.\",\n            not_a_defined: \"'{a}' has not been fully defined yet.\",\n            not_a_function: \"'{a}' is not a function.\",\n            not_a_label: \"'{a}' is not a label.\",\n            not_a_scope: \"'{a}' is out of scope.\",\n            not_greater: \"'{a}' should not be greater than '{b}'.\",\n            parameter_a_get_b: \"Unexpected parameter '{a}' in get {b} function.\",\n            parameter_set_a: \"Expected parameter (value) in set {a} function.\",\n            radix: \"Missing radix parameter.\",\n            read_only: \"Read only.\",\n            redefinition_a: \"Redefinition of '{a}'.\",\n            reserved_a: \"Reserved name '{a}'.\",\n            scanned_a_b: \"{a} ({b}% scanned).\",\n            slash_equal: \"A regular expression literal can be confused with '/='.\",\n            statement_block: \"Expected to see a statement and instead saw a block.\",\n            stopping: \"Stopping. \",\n            strange_loop: \"Strange loop.\",\n            strict: \"Strict violation.\",\n            subscript: \"['{a}'] is better written in dot notation.\",\n            tag_a_in_b: \"A '<{a}>' must be within '<{b}>'.\",\n            too_long: \"Line too long.\",\n            too_many: \"Too many errors.\",\n            trailing_decimal_a: \"A trailing decimal point can be confused \" +\n                \"with a dot: '.{a}'.\",\n            type: \"type is unnecessary.\",\n            type_confusion_a_b: \"Type confusion: {a} and {b}.\",\n            unclosed: \"Unclosed string.\",\n            unclosed_comment: \"Unclosed comment.\",\n            unclosed_regexp: \"Unclosed regular expression.\",\n            unescaped_a: \"Unescaped '{a}'.\",\n            unexpected_a: \"Unexpected '{a}'.\",\n            unexpected_char_a_b: \"Unexpected character '{a}' in {b}.\",\n            unexpected_comment: \"Unexpected comment.\",\n            unexpected_property_a: \"Unexpected /*property*/ '{a}'.\",\n            unexpected_space_a_b: \"Unexpected space between '{a}' and '{b}'.\",\n            unnecessary_initialize: \"It is not necessary to initialize '{a}' \" +\n                \"to 'undefined'.\",\n            unnecessary_use: \"Unnecessary 'use strict'.\",\n            unreachable_a_b: \"Unreachable '{a}' after '{b}'.\",\n            unrecognized_style_attribute_a: \"Unrecognized style attribute '{a}'.\",\n            unrecognized_tag_a: \"Unrecognized tag '<{a}>'.\",\n            unsafe: \"Unsafe character.\",\n            url: \"JavaScript URL.\",\n            use_array: \"Use the array literal notation [].\",\n            use_braces: \"Spaces are hard to count. Use {{a}}.\",\n            use_charAt: \"Use the charAt method.\",\n            use_object: \"Use the object literal notation {}.\",\n            use_or: \"Use the || operator.\",\n            use_param: \"Use a named parameter.\",\n            used_before_a: \"'{a}' was used before it was defined.\",\n            var_a_not: \"Variable {a} was not declared correctly.\",\n            weird_assignment: \"Weird assignment.\",\n            weird_condition: \"Weird condition.\",\n            weird_new: \"Weird construction. Delete 'new'.\",\n            weird_program: \"Weird program.\",\n            weird_relation: \"Weird relation.\",\n            weird_ternary: \"Weird ternary.\",\n            wrap_immediate: \"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\",\n            wrap_regexp: \"Wrap the /regexp/ literal in parens to \" +\n                \"disambiguate the slash operator.\",\n            write_is_wrong: \"document.write can be a form of eval.\"\n        },\n        comments_off,\n        css_attribute_data,\n        css_any,\n\n        css_colorData = array_to_object([\n            \"aliceblue\", \"antiquewhite\", \"aqua\", \"aquamarine\", \"azure\", \"beige\",\n            \"bisque\", \"black\", \"blanchedalmond\", \"blue\", \"blueviolet\", \"brown\",\n            \"burlywood\", \"cadetblue\", \"chartreuse\", \"chocolate\", \"coral\",\n            \"cornflowerblue\", \"cornsilk\", \"crimson\", \"cyan\", \"darkblue\",\n            \"darkcyan\", \"darkgoldenrod\", \"darkgray\", \"darkgreen\", \"darkkhaki\",\n            \"darkmagenta\", \"darkolivegreen\", \"darkorange\", \"darkorchid\",\n            \"darkred\", \"darksalmon\", \"darkseagreen\", \"darkslateblue\",\n            \"darkslategray\", \"darkturquoise\", \"darkviolet\", \"deeppink\",\n            \"deepskyblue\", \"dimgray\", \"dodgerblue\", \"firebrick\", \"floralwhite\",\n            \"forestgreen\", \"fuchsia\", \"gainsboro\", \"ghostwhite\", \"gold\",\n            \"goldenrod\", \"gray\", \"green\", \"greenyellow\", \"honeydew\", \"hotpink\",\n            \"indianred\", \"indigo\", \"ivory\", \"khaki\", \"lavender\",\n            \"lavenderblush\", \"lawngreen\", \"lemonchiffon\", \"lightblue\",\n            \"lightcoral\", \"lightcyan\", \"lightgoldenrodyellow\", \"lightgreen\",\n            \"lightpink\", \"lightsalmon\", \"lightseagreen\", \"lightskyblue\",\n            \"lightslategray\", \"lightsteelblue\", \"lightyellow\", \"lime\",\n            \"limegreen\", \"linen\", \"magenta\", \"maroon\", \"mediumaquamarine\",\n            \"mediumblue\", \"mediumorchid\", \"mediumpurple\", \"mediumseagreen\",\n            \"mediumslateblue\", \"mediumspringgreen\", \"mediumturquoise\",\n            \"mediumvioletred\", \"midnightblue\", \"mintcream\", \"mistyrose\",\n            \"moccasin\", \"navajowhite\", \"navy\", \"oldlace\", \"olive\", \"olivedrab\",\n            \"orange\", \"orangered\", \"orchid\", \"palegoldenrod\", \"palegreen\",\n            \"paleturquoise\", \"palevioletred\", \"papayawhip\", \"peachpuff\",\n            \"peru\", \"pink\", \"plum\", \"powderblue\", \"purple\", \"red\", \"rosybrown\",\n            \"royalblue\", \"saddlebrown\", \"salmon\", \"sandybrown\", \"seagreen\",\n            \"seashell\", \"sienna\", \"silver\", \"skyblue\", \"slateblue\", \"slategray\",\n            \"snow\", \"springgreen\", \"steelblue\", \"tan\", \"teal\", \"thistle\",\n            \"tomato\", \"turquoise\", \"violet\", \"wheat\", \"white\", \"whitesmoke\",\n            \"yellow\", \"yellowgreen\",\n\n            \"activeborder\", \"activecaption\", \"appworkspace\", \"background\",\n            \"buttonface\", \"buttonhighlight\", \"buttonshadow\", \"buttontext\",\n            \"captiontext\", \"graytext\", \"highlight\", \"highlighttext\",\n            \"inactiveborder\", \"inactivecaption\", \"inactivecaptiontext\",\n            \"infobackground\", \"infotext\", \"menu\", \"menutext\", \"scrollbar\",\n            \"threeddarkshadow\", \"threedface\", \"threedhighlight\",\n            \"threedlightshadow\", \"threedshadow\", \"window\", \"windowframe\",\n            \"windowtext\"\n        ], true),\n\n        css_border_style,\n        css_break,\n\n        css_lengthData = {\n            '%': true,\n            'cm': true,\n            'em': true,\n            'ex': true,\n            'in': true,\n            'mm': true,\n            'pc': true,\n            'pt': true,\n            'px': true\n        },\n\n        css_media,\n        css_overflow,\n\n        descapes = {\n            'b': '\\b',\n            't': '\\t',\n            'n': '\\n',\n            'f': '\\f',\n            'r': '\\r',\n            '\"': '\"',\n            '/': '/',\n            '\\\\': '\\\\'\n        },\n\n        devel = array_to_object([\n            'alert', 'confirm', 'console', 'Debug', 'opera', 'prompt', 'WSH'\n        ], false),\n        directive,\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\\'': '\\\\\\'',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function, including the labels used in\n                        // the function, as well as (breakage),\n                        // (context), (loopage), (name), (params), (token),\n                        // (vars), (verb)\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label', 'outer', 'undef',\n            'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n        global_funct,   // The global body\n        global_scope,   // The global scope\n        html_tag = {\n            a:        {},\n            abbr:     {},\n            acronym:  {},\n            address:  {},\n            applet:   {},\n            area:     {empty: true, parent: ' map '},\n            article:  {},\n            aside:    {},\n            audio:    {},\n            b:        {},\n            base:     {empty: true, parent: ' head '},\n            bdo:      {},\n            big:      {},\n            blockquote: {},\n            body:     {parent: ' html noframes '},\n            br:       {empty: true},\n            button:   {},\n            canvas:   {parent: ' body p div th td '},\n            caption:  {parent: ' table '},\n            center:   {},\n            cite:     {},\n            code:     {},\n            col:      {empty: true, parent: ' table colgroup '},\n            colgroup: {parent: ' table '},\n            command:  {parent: ' menu '},\n            datalist: {},\n            dd:       {parent: ' dl '},\n            del:      {},\n            details:  {},\n            dialog:   {},\n            dfn:      {},\n            dir:      {},\n            div:      {},\n            dl:       {},\n            dt:       {parent: ' dl '},\n            em:       {},\n            embed:    {},\n            fieldset: {},\n            figure:   {},\n            font:     {},\n            footer:   {},\n            form:     {},\n            frame:    {empty: true, parent: ' frameset '},\n            frameset: {parent: ' html frameset '},\n            h1:       {},\n            h2:       {},\n            h3:       {},\n            h4:       {},\n            h5:       {},\n            h6:       {},\n            head:     {parent: ' html '},\n            header:   {},\n            hgroup:   {},\n            hr:       {empty: true},\n            'hta:application':\n                      {empty: true, parent: ' head '},\n            html:     {parent: '*'},\n            i:        {},\n            iframe:   {},\n            img:      {empty: true},\n            input:    {empty: true},\n            ins:      {},\n            kbd:      {},\n            keygen:   {},\n            label:    {},\n            legend:   {parent: ' details fieldset figure '},\n            li:       {parent: ' dir menu ol ul '},\n            link:     {empty: true, parent: ' head '},\n            map:      {},\n            mark:     {},\n            menu:     {},\n            meta:     {empty: true, parent: ' head noframes noscript '},\n            meter:    {},\n            nav:      {},\n            noframes: {parent: ' html body '},\n            noscript: {parent: ' body head noframes '},\n            object:   {},\n            ol:       {},\n            optgroup: {parent: ' select '},\n            option:   {parent: ' optgroup select '},\n            output:   {},\n            p:        {},\n            param:    {empty: true, parent: ' applet object '},\n            pre:      {},\n            progress: {},\n            q:        {},\n            rp:       {},\n            rt:       {},\n            ruby:     {},\n            samp:     {},\n            script:   {empty: true, parent: ' body div frame head iframe p pre span '},\n            section:  {},\n            select:   {},\n            small:    {},\n            span:     {},\n            source:   {},\n            strong:   {},\n            style:    {parent: ' head ', empty: true},\n            sub:      {},\n            sup:      {},\n            table:    {},\n            tbody:    {parent: ' table '},\n            td:       {parent: ' tr '},\n            textarea: {},\n            tfoot:    {parent: ' table '},\n            th:       {parent: ' tr '},\n            thead:    {parent: ' table '},\n            time:     {},\n            title:    {parent: ' head '},\n            tr:       {parent: ' table tbody thead tfoot '},\n            tt:       {},\n            u:        {},\n            ul:       {},\n            'var':    {},\n            video:    {}\n        },\n\n        ids,            // HTML ids\n        in_block,\n        indent,\n//         infer_statement,// Inference rules for statements\n        is_type = array_to_object([\n            '*', 'array', 'boolean', 'function', 'number', 'object',\n            'regexp', 'string'\n        ], true),\n        itself,         // JSLint itself\n        json_mode,\n        lex,            // the tokenizer\n        lines,\n        lookahead,\n        member,\n        node = array_to_object([\n            'Buffer', 'clearInterval', 'clearTimeout', 'console', 'exports',\n            'global', 'module', 'process', 'querystring', 'require',\n            'setInterval', 'setTimeout', '__dirname', '__filename'\n        ], false),\n        node_js,\n        numbery = array_to_object(['indexOf', 'lastIndexOf', 'search'], true),\n        next_token,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prev_token,\n        property_type,\n        regexp_flag = array_to_object(['g', 'i', 'm'], true),\n        return_this = function return_this() {\n            return this;\n        },\n        rhino = array_to_object([\n            'defineClass', 'deserialize', 'gc', 'help', 'load', 'loadClass',\n            'print', 'quit', 'readFile', 'readUrl', 'runCommand', 'seal',\n            'serialize', 'spawn', 'sync', 'toint32', 'version'\n        ], false),\n\n        scope,      // An object containing an object for each variable in scope\n        semicolon_coda = array_to_object([';', '\"', '\\'', ')'], true),\n        src,\n        stack,\n\n// standard contains the global names that are provided by the\n// ECMAScript standard.\n\n        standard = array_to_object([\n            'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent',\n            'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError',\n            'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number', 'Object',\n            'parseInt', 'parseFloat', 'RangeError', 'ReferenceError', 'RegExp',\n            'String', 'SyntaxError', 'TypeError', 'URIError'\n        ], false),\n\n        standard_property_type = {\n            E                   : 'number',\n            LN2                 : 'number',\n            LN10                : 'number',\n            LOG2E               : 'number',\n            LOG10E              : 'number',\n            MAX_VALUE           : 'number',\n            MIN_VALUE           : 'number',\n            NEGATIVE_INFINITY   : 'number',\n            PI                  : 'number',\n            POSITIVE_INFINITY   : 'number',\n            SQRT1_2             : 'number',\n            SQRT2               : 'number',\n            apply               : 'function',\n            bind                : 'function function',\n            call                : 'function',\n            ceil                : 'function number',\n            charAt              : 'function string',\n            concat              : 'function',\n            constructor         : 'function object',\n            create              : 'function object',\n            defineProperty      : 'function object',\n            defineProperties    : 'function object',\n            every               : 'function boolean',\n            exec                : 'function array',\n            filter              : 'function array',\n            floor               : 'function number',\n            forEach             : 'function',\n            freeze              : 'function object',\n            getDate             : 'function number',\n            getDay              : 'function number',\n            getFullYear         : 'function number',\n            getHours            : 'function number',\n            getMilliseconds     : 'function number',\n            getMinutes          : 'function number',\n            getMonth            : 'function number',\n            getOwnPropertyDescriptor\n                                : 'function object',\n            getOwnPropertyNames : 'function array',\n            getPrototypeOf      : 'function object',\n            getSeconds          : 'function number',\n            getTime             : 'function number',\n            getTimezoneOffset   : 'function number',\n            getUTCDate          : 'function number',\n            getUTCDay           : 'function number',\n            getUTCFullYear      : 'function number',\n            getUTCHours         : 'function number',\n            getUTCMilliseconds  : 'function number',\n            getUTCMinutes       : 'function number',\n            getUTCMonth         : 'function number',\n            getUTCSeconds       : 'function number',\n            getYear             : 'function number',\n            hasOwnProperty      : 'function boolean',\n            indexOf             : 'function number',\n            isExtensible        : 'function boolean',\n            isFrozen            : 'function boolean',\n            isPrototypeOf       : 'function boolean',\n            isSealed            : 'function boolean',\n            join                : 'function string',\n            keys                : 'function array',\n            lastIndexOf         : 'function number',\n            lastIndex           : 'number',\n            length              : 'number',\n            map                 : 'function array',\n            now                 : 'function number',\n            parse               : 'function',\n            pop                 : 'function',\n            preventExtensions   : 'function object',\n            propertyIsEnumerable: 'function boolean',\n            prototype           : 'object',\n            push                : 'function number',\n            reduce              : 'function',\n            reduceRight         : 'function',\n            reverse             : 'function',\n            seal                : 'function object',\n            setDate             : 'function',\n            setDay              : 'function',\n            setFullYear         : 'function',\n            setHours            : 'function',\n            setMilliseconds     : 'function',\n            setMinutes          : 'function',\n            setMonth            : 'function',\n            setSeconds          : 'function',\n            setTime             : 'function',\n            setTimezoneOffset   : 'function',\n            setUTCDate          : 'function',\n            setUTCDay           : 'function',\n            setUTCFullYear      : 'function',\n            setUTCHours         : 'function',\n            setUTCMilliseconds  : 'function',\n            setUTCMinutes       : 'function',\n            setUTCMonth         : 'function',\n            setUTCSeconds       : 'function',\n            setYear             : 'function',\n            shift               : 'function',\n            slice               : 'function',\n            some                : 'function boolean',\n            sort                : 'function',\n            splice              : 'function',\n            stringify           : 'function string',\n            substr              : 'function string',\n            substring           : 'function string',\n            test                : 'function boolean',\n            toDateString        : 'function string',\n            toExponential       : 'function string',\n            toFixed             : 'function string',\n            toJSON              : 'function',\n            toISOString         : 'function string',\n            toLocaleDateString  : 'function string',\n            toLocaleLowerCase   : 'function string',\n            toLocaleUpperCase   : 'function string',\n            toLocaleString      : 'function string',\n            toLocaleTimeString  : 'function string',\n            toLowerCase         : 'function string',\n            toPrecision         : 'function string',\n            toTimeString        : 'function string',\n            toUpperCase         : 'function string',\n            toUTCString         : 'function string',\n            trim                : 'function string',\n            unshift             : 'function number',\n            valueOf             : 'function'\n        },\n\n        strict_mode,\n        syntax = {},\n        tab,\n        token,\n//         type_state_change,\n        urls,\n        var_mode,\n        warnings,\n\n// widget contains the global names which are provided to a Yahoo\n// (fna Konfabulator) widget.\n\n        widget = array_to_object([\n            'alert', 'animator', 'appleScript', 'beep', 'bytesToUIString',\n            'Canvas', 'chooseColor', 'chooseFile', 'chooseFolder',\n            'closeWidget', 'COM', 'convertPathToHFS', 'convertPathToPlatform',\n            'CustomAnimation', 'escape', 'FadeAnimation', 'filesystem', 'Flash',\n            'focusWidget', 'form', 'FormField', 'Frame', 'HotKey', 'Image',\n            'include', 'isApplicationRunning', 'iTunes', 'konfabulatorVersion',\n            'log', 'md5', 'MenuItem', 'MoveAnimation', 'openURL', 'play',\n            'Point', 'popupMenu', 'preferenceGroups', 'preferences', 'print',\n            'prompt', 'random', 'Rectangle', 'reloadWidget', 'ResizeAnimation',\n            'resolvePath', 'resumeUpdates', 'RotateAnimation', 'runCommand',\n            'runCommandInBg', 'saveAs', 'savePreferences', 'screen',\n            'ScrollBar', 'showWidgetPreferences', 'sleep', 'speak', 'Style',\n            'suppressUpdates', 'system', 'tellWidget', 'Text', 'TextArea',\n            'Timer', 'unescape', 'updateNow', 'URL', 'Web', 'widget', 'Window',\n            'XMLDOM', 'XMLHttpRequest', 'yahooCheckLogin', 'yahooLogin',\n            'yahooLogout'\n        ], true),\n\n        windows = array_to_object([\n            'ActiveXObject', 'CScript', 'Debug', 'Enumerator', 'System',\n            'VBArray', 'WScript', 'WSH'\n        ], false),\n\n//  xmode is used to adapt to the exceptions in html parsing.\n//  It can have these states:\n//      ''      .js script file\n//      'html'\n//      'outer'\n//      'script'\n//      'style'\n//      'scriptstring'\n//      'styleproperty'\n\n        xmode,\n        xquote,\n\n// Regular expressions. Some of these are stupidly long.\n\n// unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i,\n// carriage return, or carriage return linefeed\n        crx = /\\r/g,\n        crlfx = /\\r\\n/g,\n// unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n// query characters for ids\n        dx = /[\\[\\]\\/\\\\\"'*<>.&:(){}+=#]/,\n// html token\n        hx = /^\\s*(['\"=>\\/&#]|<(?:\\/|\\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\\-:]*|[0-9]+|--)/,\n// identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,\n// javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i,\n// star slash\n        lx = /\\*\\/|\\/\\*/,\n// characters in strings that need escapement\n        nx = /[\\u0000-\\u001f'\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n// outer html token\n        ox = /[>&]|<[\\/!]?|--/,\n// attributes characters\n        qx = /[^a-zA-Z0-9+\\-_\\/ ]/,\n// style\n        sx = /^\\s*([{}:#%.=,>+\\[\\]@()\"';]|[*$\\^~]=|[a-zA-Z_][a-zA-Z0-9_\\-]*|[0-9]+|<\\/|\\/\\*)/,\n        ssx = /^\\s*([@#!\"'};:\\-%.=,+\\[\\]()*_]|[a-zA-Z][a-zA-Z0-9._\\-]*|\\/\\*?|\\d+(?:\\.\\d+)?|<\\/)/,\n// token\n        tx = /^\\s*([(){}\\[\\]\\?.,:;'\"~#@`]|={1,3}|\\/(\\*(jslint|properties|property|members?|globals?)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|[\\^%]=?|&[&=]?|\\|[|=]?|>{1,3}=?|<(?:[\\/=!]|\\!(\\[|--)?|<=?)?|\\!={0,2}|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\\.[0-9]*)?(?:[eE][+\\-]?[0-9]+)?)/,\n// url badness\n        ux = /&|\\+|\\u00AD|\\.\\.|\\/\\*|%[^;]|base64|url|expression|data|mailto|script/i,\n\n        rx = {\n            outer: hx,\n            html: hx,\n            style: sx,\n            styleproperty: ssx\n        };\n\n\n    function F() {}     // Used by Object.create\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.prototype.filter !== 'function') {\n        Array.prototype.filter = function (f) {\n            var i, length = this.length, result = [], value;\n            for (i = 0; i < length; i += 1) {\n                try {\n                    value = this[i];\n                    if (f(value)) {\n                        result.push(value);\n                    }\n                } catch (ignore) {\n                }\n            }\n            return result;\n        };\n    }\n\n    if (typeof Array.prototype.forEach !== 'function') {\n        Array.prototype.forEach = function (f) {\n            var i, length = this.length;\n            for (i = 0; i < length; i += 1) {\n                try {\n                    f(this[i]);\n                } catch (ignore) {\n                }\n            }\n        };\n    }\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (!Object.prototype.hasOwnProperty.call(Object, 'create')) {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var array = [], key;\n            for (key in o) {\n                if (Object.prototype.hasOwnProperty.call(o, key)) {\n                    array.push(key);\n                }\n            }\n            return array;\n        };\n    }\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var replacement = o[b];\n                return typeof replacement === 'string' ||\n                    typeof replacement === 'number' ? replacement : a;\n            });\n        };\n    }\n\n\n    function sanitize(a) {\n\n//  Escapify a troublesome character.\n\n        return escapes[a] ||\n            '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n    }\n\n\n    function add_to_predefined(group) {\n        Object.keys(group).forEach(function (name) {\n            predefined[name] = group[name];\n        });\n    }\n\n\n    function assume() {\n        if (!option.safe) {\n            if (option.rhino) {\n                add_to_predefined(rhino);\n                option.rhino = false;\n            }\n            if (option.devel) {\n                add_to_predefined(devel);\n                option.devel = false;\n            }\n            if (option.browser) {\n                add_to_predefined(browser);\n                option.browser = false;\n            }\n            if (option.windows) {\n                add_to_predefined(windows);\n                option.windows = false;\n            }\n            if (option.node) {\n                add_to_predefined(node);\n                option.node = false;\n                node_js = true;\n            }\n            if (option.widget) {\n                add_to_predefined(widget);\n                option.widget = false;\n            }\n        }\n        if (option.type) {\n            option.confusion = true;\n        }\n    }\n\n\n// Produce an error warning.\n\n    function artifact(tok) {\n        if (!tok) {\n            tok = next_token;\n        }\n        return tok.number || tok.string;\n    }\n\n    function quit(message, line, character) {\n        throw {\n            name: 'JSLintError',\n            line: line,\n            character: character,\n            message: bundle.scanned_a_b.supplant({\n                a: message,\n                b: Math.floor((line / lines.length) * 100)\n            })\n        };\n    }\n\n    function warn(message, offender, a, b, c, d) {\n        var character, line, warning;\n        offender = offender || next_token;  // `~\n        line = offender.line || 0;\n        character = offender.from || 0;\n        warning = {\n            id: '(error)',\n            raw: bundle[message] || message,\n            evidence: lines[line - 1] || '',\n            line: line,\n            character: character,\n            a: a || (offender.id === '(number)'\n                ? String(offender.number)\n                : offender.string),\n            b: b,\n            c: c,\n            d: d\n        };\n        warning.reason = warning.raw.supplant(warning);\n        JSLINT.errors.push(warning);\n        if (option.passfail) {\n            quit(bundle.stopping, line, character);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(bundle.too_many, line, character);\n        }\n        return warning;\n    }\n\n    function warn_at(message, line, character, a, b, c, d) {\n        return warn(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function stop(message, offender, a, b, c, d) {\n        var warning = warn(message, offender, a, b, c, d);\n        quit(bundle.stopping, warning.line, warning.character);\n    }\n\n    function stop_at(message, line, character, a, b, c, d) {\n        return stop(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function expected_at(at) {\n        if (!option.white && next_token.from !== at) {\n            warn('expected_a_at_b_c', next_token, '', at,\n                next_token.from);\n        }\n    }\n\n    function aint(it, name, expected) {\n        if (it[name] !== expected) {\n            warn('expected_a_b', it, expected, it[name]);\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n// lexical analysis and token construction\n\n    lex = (function lex() {\n        var character, c, from, length, line, pos, source_row;\n\n// Private lex methods\n\n        function next_line() {\n            var at;\n            if (line >= lines.length) {\n                return false;\n            }\n            character = 1;\n            source_row = lines[line];\n            line += 1;\n            at = source_row.search(/ \\t/);\n            if (at >= 0) {\n                warn_at('mixed', line, at + 1);\n            }\n            source_row = source_row.replace(/\\t/g, tab);\n            at = source_row.search(cx);\n            if (at >= 0) {\n                warn_at('unsafe', line, at);\n            }\n            if (option.maxlen && option.maxlen < source_row.length) {\n                warn_at('too_long', line, source_row.length);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var id, the_token;\n            if (type === '(string)' || type === '(range)') {\n                if (jx.test(value)) {\n                    warn_at('url', line, from);\n                }\n            }\n            the_token = Object.create(syntax[(\n                type === '(punctuator)' || (type === '(identifier)' &&\n                        Object.prototype.hasOwnProperty.call(syntax, value))\n                    ? value\n                    : type\n            )] || syntax['(error)']);\n            if (type === '(identifier)') {\n                the_token.identifier = true;\n                if (value === '__iterator__' || value === '__proto__') {\n                    stop_at('reserved_a', line, from, value);\n                } else if (!option.nomen &&\n                        (value.charAt(0) === '_' ||\n                        value.charAt(value.length - 1) === '_')) {\n                    warn_at('dangling_a', line, from, value);\n                }\n            }\n            if (type === '(number)') {\n                the_token.number = +value;\n            } else if (value !== undefined) {\n                the_token.string = String(value);\n            }\n            the_token.line = line;\n            the_token.from = from;\n            the_token.thru = character;\n            id = the_token.id;\n            prereg = id && (\n                ('(,=:[!&|?{};'.indexOf(id.charAt(id.length - 1)) >= 0) ||\n                id === 'return' || id === 'case'\n            );\n            return the_token;\n        }\n\n        function match(x) {\n            var exec = x.exec(source_row), first;\n            if (exec) {\n                length = exec[0].length;\n                first = exec[1];\n                c = first.charAt(0);\n                source_row = source_row.slice(length);\n                from = character + length - first.length;\n                character += length;\n                return first;\n            }\n        }\n\n        function string(x) {\n            var c, pos = 0, r = '', result;\n\n            function hex(n) {\n                var i = parseInt(source_row.substr(pos + 1, n), 16);\n                pos += n;\n                if (i >= 32 && i <= 126 &&\n                        i !== 34 && i !== 92 && i !== 39) {\n                    warn_at('unexpected_a', line, character, '\\\\');\n                }\n                character += n;\n                c = String.fromCharCode(i);\n            }\n\n            if (json_mode && x !== '\"') {\n                warn_at('expected_a', line, character, '\"');\n            }\n\n            if (xquote === x || (xmode === 'scriptstring' && !xquote)) {\n                return it('(punctuator)', x);\n            }\n\n            for (;;) {\n                while (pos >= source_row.length) {\n                    pos = 0;\n                    if (xmode !== 'html' || !next_line()) {\n                        stop_at('unclosed', line, from);\n                    }\n                }\n                c = source_row.charAt(pos);\n                if (c === x) {\n                    character += 1;\n                    source_row = source_row.slice(pos + 1);\n                    result = it('(string)', r);\n                    result.quote = x;\n                    return result;\n                }\n                if (c < ' ') {\n                    if (c === '\\n' || c === '\\r') {\n                        break;\n                    }\n                    warn_at('control_a', line, character + pos,\n                        source_row.slice(0, pos));\n                } else if (c === xquote) {\n                    warn_at('bad_html', line, character + pos);\n                } else if (c === '<') {\n                    if (option.safe && xmode === 'html') {\n                        warn_at('adsafe_a', line, character + pos, c);\n                    } else if (source_row.charAt(pos + 1) === '/' && (xmode || option.safe)) {\n                        warn_at('expected_a_b', line, character,\n                            '<\\\\/', '</');\n                    } else if (source_row.charAt(pos + 1) === '!' && (xmode || option.safe)) {\n                        warn_at('unexpected_a', line, character, '<!');\n                    }\n                } else if (c === '\\\\') {\n                    if (xmode === 'html') {\n                        if (option.safe) {\n                            warn_at('adsafe_a', line, character + pos, c);\n                        }\n                    } else if (xmode === 'styleproperty') {\n                        pos += 1;\n                        character += 1;\n                        c = source_row.charAt(pos);\n                        if (c !== x) {\n                            warn_at('unexpected_a', line, character, '\\\\');\n                        }\n                    } else {\n                        pos += 1;\n                        character += 1;\n                        c = source_row.charAt(pos);\n                        switch (c) {\n                        case '':\n                            if (!option.es5) {\n                                warn_at('es5', line, character);\n                            }\n                            next_line();\n                            pos = -1;\n                            break;\n                        case xquote:\n                            warn_at('bad_html', line, character + pos);\n                            break;\n                        case '\\'':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\\\'');\n                            }\n                            break;\n                        case 'u':\n                            hex(4);\n                            break;\n                        case 'v':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\v');\n                            }\n                            c = '\\v';\n                            break;\n                        case 'x':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\x');\n                            }\n                            hex(2);\n                            break;\n                        default:\n                            c = descapes[c];\n                            if (typeof c !== 'string') {\n                                warn_at('unexpected_a', line, character, '\\\\');\n                            }\n                        }\n                    }\n                }\n                r += c;\n                character += 1;\n                pos += 1;\n            }\n        }\n\n        function number(snippet) {\n            var digit;\n            if (xmode !== 'style' && xmode !== 'styleproperty' &&\n                    source_row.charAt(0).isAlpha()) {\n                warn_at('expected_space_a_b',\n                    line, character, c, source_row.charAt(0));\n            }\n            if (c === '0') {\n                digit = snippet.charAt(1);\n                if (digit.isDigit()) {\n                    if (token.id !== '.' && xmode !== 'styleproperty') {\n                        warn_at('unexpected_a', line, character, snippet);\n                    }\n                } else if (json_mode && (digit === 'x' || digit === 'X')) {\n                    warn_at('unexpected_a', line, character, '0x');\n                }\n            }\n            if (snippet.slice(snippet.length - 1) === '.') {\n                warn_at('trailing_decimal_a', line, character, snippet);\n            }\n            if (xmode !== 'style') {\n                digit = +snippet;\n                if (!isFinite(digit)) {\n                    warn_at('bad_number', line, character, snippet);\n                }\n                snippet = digit;\n            }\n            return it('(number)', snippet);\n        }\n\n        function comment(snippet) {\n            if (comments_off || src || (xmode && xmode !== 'script' &&\n                    xmode !== 'style' && xmode !== 'styleproperty')) {\n                warn_at('unexpected_comment', line, character);\n            } else if (xmode === 'script' && /<\\//i.test(source_row)) {\n                warn_at('unexpected_a', line, character, '<\\/');\n            } else if (option.safe && ax.test(snippet)) {\n                warn_at('dangerous_comment', line, character);\n            }\n        }\n\n        function regexp() {\n            var b,\n                bit,\n                captures = 0,\n                depth = 0,\n                flag = '',\n                high,\n                letter,\n                length = 0,\n                low,\n                potential,\n                quote,\n                result;\n            for (;;) {\n                b = true;\n                c = source_row.charAt(length);\n                length += 1;\n                switch (c) {\n                case '':\n                    stop_at('unclosed_regexp', line, from);\n                    return;\n                case '/':\n                    if (depth > 0) {\n                        warn_at('unescaped_a', line, from + length, '/');\n                    }\n                    c = source_row.slice(0, length - 1);\n                    potential = Object.create(regexp_flag);\n                    for (;;) {\n                        letter = source_row.charAt(length);\n                        if (potential[letter] !== true) {\n                            break;\n                        }\n                        potential[letter] = false;\n                        length += 1;\n                        flag += letter;\n                    }\n                    if (source_row.charAt(length).isAlpha()) {\n                        stop_at('unexpected_a', line, from, source_row.charAt(length));\n                    }\n                    character += length;\n                    source_row = source_row.slice(length);\n                    quote = source_row.charAt(0);\n                    if (quote === '/' || quote === '*') {\n                        stop_at('confusing_regexp', line, from);\n                    }\n                    result = it('(regexp)', c);\n                    result.flag = flag;\n                    return result;\n                case '\\\\':\n                    c = source_row.charAt(length);\n                    if (c < ' ') {\n                        warn_at('control_a', line, from + length, String(c));\n                    } else if (c === '<') {\n                        warn_at(bundle.unexpected_a, line, from + length, '\\\\');\n                    }\n                    length += 1;\n                    break;\n                case '(':\n                    depth += 1;\n                    b = false;\n                    if (source_row.charAt(length) === '?') {\n                        length += 1;\n                        switch (source_row.charAt(length)) {\n                        case ':':\n                        case '=':\n                        case '!':\n                            length += 1;\n                            break;\n                        default:\n                            warn_at(bundle.expected_a_b, line, from + length,\n                                ':', source_row.charAt(length));\n                        }\n                    } else {\n                        captures += 1;\n                    }\n                    break;\n                case '|':\n                    b = false;\n                    break;\n                case ')':\n                    if (depth === 0) {\n                        warn_at('unescaped_a', line, from + length, ')');\n                    } else {\n                        depth -= 1;\n                    }\n                    break;\n                case ' ':\n                    pos = 1;\n                    while (source_row.charAt(length) === ' ') {\n                        length += 1;\n                        pos += 1;\n                    }\n                    if (pos > 1) {\n                        warn_at('use_braces', line, from + length, pos);\n                    }\n                    break;\n                case '[':\n                    c = source_row.charAt(length);\n                    if (c === '^') {\n                        length += 1;\n                        if (!option.regexp) {\n                            warn_at('insecure_a', line, from + length, c);\n                        } else if (source_row.charAt(length) === ']') {\n                            stop_at('unescaped_a', line, from + length, '^');\n                        }\n                    }\n                    bit = false;\n                    if (c === ']') {\n                        warn_at('empty_class', line, from + length - 1);\n                        bit = true;\n                    }\nklass:              do {\n                        c = source_row.charAt(length);\n                        length += 1;\n                        switch (c) {\n                        case '[':\n                        case '^':\n                            warn_at('unescaped_a', line, from + length, c);\n                            bit = true;\n                            break;\n                        case '-':\n                            if (bit) {\n                                bit = false;\n                            } else {\n                                warn_at('unescaped_a', line, from + length, '-');\n                                bit = true;\n                            }\n                            break;\n                        case ']':\n                            if (!bit) {\n                                warn_at('unescaped_a', line, from + length - 1, '-');\n                            }\n                            break klass;\n                        case '\\\\':\n                            c = source_row.charAt(length);\n                            if (c < ' ') {\n                                warn_at(bundle.control_a, line, from + length, String(c));\n                            } else if (c === '<') {\n                                warn_at(bundle.unexpected_a, line, from + length, '\\\\');\n                            }\n                            length += 1;\n                            bit = true;\n                            break;\n                        case '/':\n                            warn_at('unescaped_a', line, from + length - 1, '/');\n                            bit = true;\n                            break;\n                        case '<':\n                            if (xmode === 'script') {\n                                c = source_row.charAt(length);\n                                if (c === '!' || c === '/') {\n                                    warn_at(bundle.html_confusion_a, line,\n                                        from + length, c);\n                                }\n                            }\n                            bit = true;\n                            break;\n                        default:\n                            bit = true;\n                        }\n                    } while (c);\n                    break;\n                case '.':\n                    if (!option.regexp) {\n                        warn_at('insecure_a', line, from + length, c);\n                    }\n                    break;\n                case ']':\n                case '?':\n                case '{':\n                case '}':\n                case '+':\n                case '*':\n                    warn_at('unescaped_a', line, from + length, c);\n                    break;\n                case '<':\n                    if (xmode === 'script') {\n                        c = source_row.charAt(length);\n                        if (c === '!' || c === '/') {\n                            warn_at(bundle.html_confusion_a, line, from + length, c);\n                        }\n                    }\n                    break;\n                }\n                if (b) {\n                    switch (source_row.charAt(length)) {\n                    case '?':\n                    case '+':\n                    case '*':\n                        length += 1;\n                        if (source_row.charAt(length) === '?') {\n                            length += 1;\n                        }\n                        break;\n                    case '{':\n                        length += 1;\n                        c = source_row.charAt(length);\n                        if (c < '0' || c > '9') {\n                            warn_at(bundle.expected_number_a, line,\n                                from + length, c);\n                        }\n                        length += 1;\n                        low = +c;\n                        for (;;) {\n                            c = source_row.charAt(length);\n                            if (c < '0' || c > '9') {\n                                break;\n                            }\n                            length += 1;\n                            low = +c + (low * 10);\n                        }\n                        high = low;\n                        if (c === ',') {\n                            length += 1;\n                            high = Infinity;\n                            c = source_row.charAt(length);\n                            if (c >= '0' && c <= '9') {\n                                length += 1;\n                                high = +c;\n                                for (;;) {\n                                    c = source_row.charAt(length);\n                                    if (c < '0' || c > '9') {\n                                        break;\n                                    }\n                                    length += 1;\n                                    high = +c + (high * 10);\n                                }\n                            }\n                        }\n                        if (source_row.charAt(length) !== '}') {\n                            warn_at(bundle.expected_a_b, line, from + length,\n                                '}', c);\n                        } else {\n                            length += 1;\n                        }\n                        if (source_row.charAt(length) === '?') {\n                            length += 1;\n                        }\n                        if (low > high) {\n                            warn_at(bundle.not_greater, line, from + length,\n                                low, high);\n                        }\n                        break;\n                    }\n                }\n            }\n            c = source_row.slice(0, length - 1);\n            character += length;\n            source_row = source_row.slice(length);\n            return it('(regexp)', c);\n        }\n\n// Public lex methods\n\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source\n                        .replace(crlfx, '\\n')\n                        .replace(crx, '\\n')\n                        .split('\\n');\n                } else {\n                    lines = source;\n                }\n                line = 0;\n                next_line();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (source_row.charAt(0) !== begin) {\n                    stop_at('expected_a_b', line, character, begin,\n                        source_row.charAt(0));\n                }\n                for (;;) {\n                    source_row = source_row.slice(1);\n                    character += 1;\n                    c = source_row.charAt(0);\n                    switch (c) {\n                    case '':\n                        stop_at('missing_a', line, character, c);\n                        break;\n                    case end:\n                        source_row = source_row.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case xquote:\n                    case '\\\\':\n                        warn_at('unexpected_a', line, character, c);\n                        break;\n                    }\n                    value += c;\n                }\n            },\n\n// token -- this is called by advance to get the next token.\n\n            token: function () {\n                var c, i, snippet;\n\n                for (;;) {\n                    while (!source_row) {\n                        if (!next_line()) {\n                            return it('(end)');\n                        }\n                    }\n                    while (xmode === 'outer') {\n                        i = source_row.search(ox);\n                        if (i === 0) {\n                            break;\n                        } else if (i > 0) {\n                            character += 1;\n                            source_row = source_row.slice(i);\n                            break;\n                        } else {\n                            if (!next_line()) {\n                                return it('(end)', '');\n                            }\n                        }\n                    }\n                    snippet = match(rx[xmode] || tx);\n                    if (!snippet) {\n                        if (source_row) {\n                            if (source_row.charAt(0) === ' ') {\n                                if (!option.white) {\n                                    warn_at('unexpected_a', line, character,\n                                        '(space)');\n                                }\n                                character += 1;\n                                source_row = '';\n                            } else {\n                                stop_at('unexpected_a', line, character,\n                                    source_row.charAt(0));\n                            }\n                        }\n                    } else {\n\n//      identifier\n\n                        c = snippet.charAt(0);\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', snippet);\n                        }\n\n//      number\n\n                        if (c.isDigit()) {\n                            return number(snippet);\n                        }\n                        switch (snippet) {\n\n//      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(snippet);\n\n//      // comment\n\n                        case '//':\n                            comment(source_row);\n                            source_row = '';\n                            break;\n\n//      /* comment\n\n                        case '/*':\n                            for (;;) {\n                                i = source_row.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                comment(source_row);\n                                if (!next_line()) {\n                                    stop_at('unclosed_comment', line, character);\n                                }\n                            }\n                            comment(source_row.slice(0, i));\n                            character += i + 2;\n                            if (source_row.charAt(i) === '/') {\n                                stop_at('nested_comment', line, character);\n                            }\n                            source_row = source_row.slice(i + 2);\n                            break;\n\n                        case '':\n                            break;\n//      /\n                        case '/':\n                            if (token.id === '/=') {\n                                stop_at(\n                                    bundle.slash_equal,\n                                    line,\n                                    from\n                                );\n                            }\n                            return prereg\n                                ? regexp()\n                                : it('(punctuator)', snippet);\n\n//      punctuator\n\n                        case '<!--':\n                            length = line;\n//                            c = character;\n                            for (;;) {\n                                i = source_row.indexOf('--');\n                                if (i >= 0) {\n                                    break;\n                                }\n                                i = source_row.indexOf('<!');\n                                if (i >= 0) {\n                                    stop_at('nested_comment',\n                                        line, character + i);\n                                }\n                                if (!next_line()) {\n                                    stop_at('unclosed_comment', length, c);\n                                }\n                            }\n                            length = source_row.indexOf('<!');\n                            if (length >= 0 && length < i) {\n                                stop_at('nested_comment',\n                                    line, character + length);\n                            }\n                            character += i;\n                            if (source_row.charAt(i + 2) !== '>') {\n                                stop_at('expected_a', line, character, '-->');\n                            }\n                            character += 3;\n                            source_row = source_row.slice(i + 3);\n                            break;\n                        case '#':\n                            if (xmode === 'html' || xmode === 'styleproperty') {\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    if ((c < '0' || c > '9') &&\n                                            (c < 'a' || c > 'f') &&\n                                            (c < 'A' || c > 'F')) {\n                                        break;\n                                    }\n                                    character += 1;\n                                    source_row = source_row.slice(1);\n                                    snippet += c;\n                                }\n                                if (snippet.length !== 4 && snippet.length !== 7) {\n                                    warn_at('bad_color_a', line,\n                                        from + length, snippet);\n                                }\n                                return it('(color)', snippet);\n                            }\n                            return it('(punctuator)', snippet);\n\n                        default:\n                            if (xmode === 'outer' && c === '&') {\n                                character += 1;\n                                source_row = source_row.slice(1);\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    character += 1;\n                                    source_row = source_row.slice(1);\n                                    if (c === ';') {\n                                        break;\n                                    }\n                                    if (!((c >= '0' && c <= '9') ||\n                                            (c >= 'a' && c <= 'z') ||\n                                            c === '#')) {\n                                        stop_at('bad_entity', line, from + length,\n                                            character);\n                                    }\n                                }\n                                break;\n                            }\n                            return it('(punctuator)', snippet);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function add_label(token, kind, name) {\n\n// Define the symbol in the current function in the current scope.\n\n        name = name || token.string;\n\n// Global variables cannot be created in the safe subset. If a global variable\n// already exists, do nothing. If it is predefined, define it.\n\n        if (funct === global_funct) {\n            if (option.safe) {\n                warn('adsafe_a', token, name);\n            }\n            if (typeof global_funct[name] !== 'string') {\n                token.writeable = typeof predefined[name] === 'boolean'\n                    ? predefined[name]\n                    : true;\n                token.funct = funct;\n                global_scope[name] = token;\n            }\n            if (kind === 'becoming') {\n                kind = 'var';\n            }\n\n// Ordinary variables.\n\n        } else {\n\n// Warn if the variable already exists.\n\n            if (typeof funct[name] === 'string') {\n                if (funct[name] === 'undef') {\n                    if (!option.undef) {\n                        warn('used_before_a', token, name);\n                    }\n                    kind = 'var';\n                } else {\n                    warn('already_defined', token, name);\n                }\n            } else {\n\n// Add the symbol to the current function.\n\n                token.funct = funct;\n                token.writeable = true;\n                scope[name] = token;\n            }\n        }\n        funct[name] = kind;\n    }\n\n\n    function peek(distance) {\n\n// Peek ahead to a future token. The distance is how far ahead to look. The\n// default is the next token.\n\n        var found, slot = 0;\n\n        distance = distance || 0;\n        while (slot <= distance) {\n            found = lookahead[slot];\n            if (!found) {\n                found = lookahead[slot] = lex.token();\n            }\n            slot += 1;\n        }\n        return found;\n    }\n\n\n    function advance(id, match) {\n\n// Produce the next token, also looking for programming errors.\n\n        if (indent) {\n\n// If indentation checking was requested, then inspect all of the line breakings.\n// The var statement is tricky because the names might be aligned or not. We\n// look at the first line break after the var to determine the programmer's\n// intention.\n\n            if (var_mode && next_token.line !== token.line) {\n                if ((var_mode !== indent || !next_token.edge) &&\n                        next_token.from === indent.at -\n                        (next_token.edge ? option.indent : 0)) {\n                    var dent = indent;\n                    for (;;) {\n                        dent.at -= option.indent;\n                        if (dent === var_mode) {\n                            break;\n                        }\n                        dent = dent.was;\n                    }\n                    dent.open = false;\n                }\n                var_mode = null;\n            }\n            if (next_token.id === '?' && indent.mode === ':' &&\n                    token.line !== next_token.line) {\n                indent.at -= option.indent;\n            }\n            if (indent.open) {\n\n// If the token is an edge.\n\n                if (next_token.edge) {\n                    if (next_token.edge === 'label') {\n                        expected_at(1);\n                    } else if (next_token.edge === 'case' || indent.mode === 'statement') {\n                        expected_at(indent.at - option.indent);\n                    } else if (indent.mode !== 'array' || next_token.line !== token.line) {\n                        expected_at(indent.at);\n                    }\n\n// If the token is not an edge, but is the first token on the line.\n\n                } else if (next_token.line !== token.line) {\n                    if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                    indent.wrap = true;\n                }\n            } else if (next_token.line !== token.line) {\n                if (next_token.edge) {\n                    expected_at(indent.at);\n                } else {\n                    indent.wrap = true;\n                    if (indent.mode === 'statement' || indent.mode === 'var') {\n                        expected_at(indent.at + option.indent);\n                    } else if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                }\n            }\n        }\n\n        switch (token.id) {\n        case '(number)':\n            if (next_token.id === '.') {\n                warn('trailing_decimal_a');\n            }\n            break;\n        case '-':\n            if (next_token.id === '-' || next_token.id === '--') {\n                warn('confusing_a');\n            }\n            break;\n        case '+':\n            if (next_token.id === '+' || next_token.id === '++') {\n                warn('confusing_a');\n            }\n            break;\n        }\n        if (token.id === '(string)' || token.identifier) {\n            anonname = token.string;\n        }\n\n        if (id && next_token.id !== id) {\n            if (match) {\n                warn('expected_a_b_from_c_d', next_token, id,\n                    match.id, match.line, artifact());\n            } else if (!next_token.identifier || next_token.string !== id) {\n                warn('expected_a_b', next_token, id, artifact());\n            }\n        }\n        prev_token = token;\n        token = next_token;\n        next_token = lookahead.shift() || lex.token();\n    }\n\n\n    function advance_identifier(string) {\n        if (next_token.identifier && next_token.string === string) {\n            advance();\n        } else {\n            warn('expected_a_b', next_token, string, artifact());\n        }\n    }\n\n\n    function do_safe() {\n        if (option.adsafe) {\n            option.safe = true;\n        }\n        if (option.safe) {\n            option.browser     =\n                option['continue'] =\n                option.css     =\n                option.debug   =\n                option.devel   =\n                option.evil    =\n                option.forin   =\n                option.newcap  =\n                option.nomen   =\n                option.on      =\n                option.rhino   =\n                option.sloppy  =\n                option.sub     =\n                option.undef   =\n                option.widget  =\n                option.windows = false;\n\n\n            delete predefined.Array;\n            delete predefined.Date;\n            delete predefined.Function;\n            delete predefined.Object;\n            delete predefined['eval'];\n\n            add_to_predefined({\n                ADSAFE: false,\n                lib: false\n            });\n        }\n    }\n\n\n    function do_globals() {\n        var name, writeable;\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            advance();\n            writeable = false;\n            if (next_token.id === ':') {\n                advance(':');\n                switch (next_token.id) {\n                case 'true':\n                    writeable = predefined[name] !== false;\n                    advance('true');\n                    break;\n                case 'false':\n                    advance('false');\n                    break;\n                default:\n                    stop('unexpected_a');\n                }\n            }\n            predefined[name] = writeable;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    function do_jslint() {\n        var name, value;\n        while (next_token.id === '(string)' || next_token.identifier) {\n            name = next_token.string;\n            if (!allowed_option[name]) {\n                stop('unexpected_a');\n            }\n            advance();\n            if (next_token.id !== ':') {\n                stop('expected_a_b', next_token, ':', artifact());\n            }\n            advance(':');\n            if (typeof allowed_option[name] === 'number') {\n                value = next_token.number;\n                if (value > allowed_option[name] || value <= 0 ||\n                        Math.floor(value) !== value) {\n                    stop('expected_small_a');\n                }\n                option[name] = value;\n            } else {\n                if (next_token.id === 'true') {\n                    option[name] = true;\n                } else if (next_token.id === 'false') {\n                    option[name] = false;\n                } else {\n                    stop('unexpected_a');\n                }\n            }\n            advance();\n            if (next_token.id === ',') {\n                advance(',');\n            }\n        }\n        assume();\n    }\n\n\n    function do_properties() {\n        var name, type;\n        option.properties = true;\n        if (!funct['(old_property_type)']) {\n            funct['(old_property_type)'] = property_type;\n            property_type = Object.create(property_type);\n        }\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            type = '';\n            advance();\n            if (next_token.id === ':') {\n                advance(':');\n                if (next_token.id === 'function') {\n                    advance('function');\n                    if (is_type[next_token.string] === true) {\n                        type = 'function ' + next_token.string;\n                        advance();\n                    } else {\n                        type = 'function';\n                    }\n                } else {\n                    type = next_token.string;\n                    if (is_type[type] !== true) {\n                        warn('expected_type_a', next_token);\n                        type = '';\n                    }\n                    advance();\n                }\n            }\n            property_type[name] = type;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    directive = function directive() {\n        var command = this.id,\n            old_comments_off = comments_off,\n            old_indent = indent;\n        comments_off = true;\n        indent = null;\n        if (next_token.line === token.line && next_token.from === token.thru) {\n            warn('missing_space_a_b', next_token, artifact(token), artifact());\n        }\n        if (lookahead.length > 0) {\n            warn('unexpected_a', this);\n        }\n        switch (command) {\n        case '/*properties':\n        case '/*property':\n        case '/*members':\n        case '/*member':\n            do_properties();\n            break;\n        case '/*jslint':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            do_jslint();\n            break;\n        case '/*globals':\n        case '/*global':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            do_globals();\n            break;\n        default:\n            stop('unexpected_a', this);\n        }\n        comments_off = old_comments_off;\n        advance('*/');\n        indent = old_indent;\n    };\n\n\n// Indentation intention\n\n    function edge(mode) {\n        next_token.edge = indent ? indent.open && (mode || 'edge') : '';\n    }\n\n\n    function step_in(mode) {\n        var open;\n        if (typeof mode === 'number') {\n            indent = {\n                at: +mode,\n                open: true,\n                was: indent\n            };\n        } else if (mode === 'statement') {\n            indent = {\n                at: indent.at,\n                open: true,\n                was: indent\n            };\n        } else if (!indent) {\n            indent = {\n                at: 1,\n                mode: 'statement',\n                open: true\n            };\n        } else {\n            open = mode === 'var' || next_token.line !== token.line;\n            indent = {\n                at: (open || mode === 'control'\n                    ? indent.at + option.indent\n                    : indent.at) + (indent.wrap ? option.indent : 0),\n                mode: mode,\n                open: open,\n                was: indent\n            };\n            if (mode === 'var' && open) {\n                var_mode = indent;\n            }\n        }\n    }\n\n    function step_out(id, symbol) {\n        if (id) {\n            if (indent && indent.open) {\n                indent.at -= option.indent;\n                edge();\n            }\n            advance(id, symbol);\n        }\n        if (indent) {\n            indent = indent.was;\n        }\n    }\n\n// Functions for conformance of whitespace.\n\n    function one_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && !option.white &&\n                (token.line !== right.line ||\n                token.thru + 1 !== right.from)) {\n            warn('expected_space_a_b', right, artifact(token), artifact(right));\n        }\n    }\n\n    function one_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru + 1 !== right.from))) {\n            warn('expected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function no_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if ((!option.white || xmode === 'styleproperty' || xmode === 'style') &&\n                left.thru !== right.from && left.line === right.line) {\n            warn('unexpected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function no_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru !== right.from))) {\n            warn('unexpected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function spaces(left, right) {\n        if (!option.white) {\n            left = left || token;\n            right = right || next_token;\n            if (left.thru === right.from && left.line === right.line) {\n                warn('missing_space_a_b', right, artifact(left), artifact(right));\n            }\n        }\n    }\n\n    function comma() {\n        if (next_token.id !== ',') {\n            warn_at('expected_a_b', token.line, token.thru, ',', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(',');\n            spaces();\n        }\n    }\n\n\n    function semicolon() {\n        if (next_token.id !== ';') {\n            warn_at('expected_a_b', token.line, token.thru, ';', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(';');\n            if (semicolon_coda[next_token.id] !== true) {\n                spaces();\n            }\n        }\n    }\n\n    function use_strict() {\n        if (next_token.string === 'use strict') {\n            if (strict_mode) {\n                warn('unnecessary_use');\n            }\n            edge();\n            advance();\n            semicolon();\n            strict_mode = true;\n            option.newcap = false;\n            option.undef = false;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n    function are_similar(a, b) {\n        if (a === b) {\n            return true;\n        }\n        if (Array.isArray(a)) {\n            if (Array.isArray(b) && a.length === b.length) {\n                var i;\n                for (i = 0; i < a.length; i += 1) {\n                    if (!are_similar(a[i], b[i])) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n            return false;\n        }\n        if (Array.isArray(b)) {\n            return false;\n        }\n        if (a.id === '(number)' && b.id === '(number)') {\n            return a.number === b.number;\n        }\n        if (a.arity === b.arity && a.string === b.string) {\n            switch (a.arity) {\n            case 'prefix':\n            case 'suffix':\n            case undefined:\n                return a.id === b.id && are_similar(a.first, b.first);\n            case 'infix':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second);\n            case 'ternary':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second) &&\n                    are_similar(a.third, b.third);\n            case 'function':\n            case 'regexp':\n                return false;\n            default:\n                return true;\n            }\n        } else {\n            if (a.id === '.' && b.id === '[' && b.arity === 'infix') {\n                return a.second.string === b.second.string && b.second.id === '(string)';\n            } else if (a.id === '[' && a.arity === 'infix' && b.id === '.') {\n                return a.second.string === b.second.string && a.second.id === '(string)';\n            }\n        }\n        return false;\n    }\n\n\n// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n\n// rbp is the right binding power.\n// initial indicates that this is the first expression of a statement.\n\n        var left;\n        if (next_token.id === '(end)') {\n            stop('unexpected_a', token, next_token.id);\n        }\n        advance();\n        if (option.safe && scope[token.string] &&\n                scope[token.string] === global_scope[token.string] &&\n                (next_token.id !== '(' && next_token.id !== '.')) {\n            warn('adsafe_a', token);\n        }\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.string;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (next_token.id === '(number)' && token.id === '.') {\n                    warn('leading_decimal_a', token, artifact());\n                    advance();\n                    return token;\n                } else {\n                    stop('expected_identifier_a', token, token.id);\n                }\n            }\n            while (rbp < next_token.lbp) {\n                advance();\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    stop('expected_operator_a', token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p || 0,\n                string: s\n            };\n        }\n        return x;\n    }\n\n    function postscript(x) {\n        x.postscript = true;\n        return x;\n    }\n\n    function ultimate(s) {\n        var x = symbol(s, 0);\n        x.from = 1;\n        x.thru = 1;\n        x.line = 0;\n        x.edge = 'edge';\n        s.string = s;\n        return postscript(x);\n    }\n\n\n    function stmt(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n    function labeled_stmt(s, f) {\n        var x = stmt(s, f);\n        x.labeled = true;\n    }\n\n    function disrupt_stmt(s, f) {\n        var x = stmt(s, f);\n        x.disrupt = true;\n    }\n\n\n    function reserve_name(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f, type) {\n        var x = symbol(s, 150);\n        reserve_name(x);\n        x.nud = typeof f === 'function'\n            ? f\n            : function () {\n                if (s === 'typeof') {\n                    one_space();\n                } else {\n                    no_space_only();\n                }\n                this.first = expression(150);\n                this.arity = 'prefix';\n                if (this.id === '++' || this.id === '--') {\n                    if (!option.plusplus) {\n                        warn('unexpected_a', this);\n                    } else if ((!this.first.identifier || this.first.reserved) &&\n                            this.first.id !== '.' && this.first.id !== '[') {\n                        warn('bad_operand', this);\n                    }\n                }\n                this.type = type;\n                return this;\n            };\n        return x;\n    }\n\n\n    function type(s, t, nud) {\n        var x = symbol(s);\n        x.arity = x.type = t;\n        if (nud) {\n            x.nud = nud;\n        }\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        if (typeof f === 'function') {\n            x.nud = f;\n        }\n        return x;\n    }\n\n\n    function constant(name, type) {\n        var x = reserve(name);\n        x.type = type;\n        x.string = name;\n        x.nud = return_this;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, p, f, type, w) {\n        var x = symbol(s, p);\n        reserve_name(x);\n        x.led = function (left) {\n            this.arity = 'infix';\n            if (!w) {\n                spaces(prev_token, token);\n                spaces();\n            }\n            if (!option.bitwise && this.bitwise) {\n                warn('unexpected_a', this);\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            } else {\n                this.first = left;\n                this.second = expression(p);\n                return this;\n            }\n        };\n        if (type) {\n            x.type = type;\n        }\n        return x;\n    }\n\n    function expected_relation(node, message) {\n        if (node.assign) {\n            warn(message || bundle.conditional_assignment, node);\n        }\n        return node;\n    }\n\n    function expected_condition(node, message) {\n        switch (node.id) {\n        case '[':\n        case '-':\n            if (node.arity !== 'infix') {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        case 'false':\n        case 'function':\n        case 'Infinity':\n        case 'NaN':\n        case 'null':\n        case 'true':\n        case 'undefined':\n        case 'void':\n        case '(number)':\n        case '(regexp)':\n        case '(string)':\n        case '{':\n            warn(message || bundle.weird_condition, node);\n            break;\n        case '(':\n            if (node.first.id === '.' && numbery[node.first.second.string] === true) {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        }\n        return node;\n    }\n\n    function check_relation(node) {\n        switch (node.arity) {\n        case 'prefix':\n            switch (node.id) {\n            case '{':\n            case '[':\n                warn('unexpected_a', node);\n                break;\n            case '!':\n                warn('confusing_a', node);\n                break;\n            }\n            break;\n        case 'function':\n        case 'regexp':\n            warn('unexpected_a', node);\n            break;\n        default:\n            if (node.id  === 'NaN') {\n                warn('isnan', node);\n            }\n        }\n        return node;\n    }\n\n\n    function relation(s, eqeq) {\n        return infix(s, 100, function (left, that) {\n            check_relation(left);\n            if (eqeq && !option.eqeq) {\n                warn('expected_a_b', that, eqeq, that.id);\n            }\n            var right = expression(100);\n            if (are_similar(left, right) ||\n                    ((left.id === '(string)' || left.id === '(number)') &&\n                    (right.id === '(string)' || right.id === '(number)'))) {\n                warn('weird_relation', that);\n            }\n            that.first = left;\n            that.second = check_relation(right);\n            return that;\n        }, 'boolean');\n    }\n\n\n    function assignop(s, op) {\n        var x = infix(s, 20, function (left, that) {\n            var l;\n            that.first = left;\n            if (left.identifier) {\n                if (scope[left.string]) {\n                    if (scope[left.string].writeable === false) {\n                        warn('read_only', left);\n                    }\n                } else {\n                    stop('read_only');\n                }\n            } else if (option.safe) {\n                l = left;\n                do {\n                    if (typeof predefined[l.string] === 'boolean') {\n                        warn('adsafe_a', l);\n                    }\n                    l = l.first;\n                } while (l);\n            }\n            if (left === syntax['function']) {\n                warn('identifier_function', token);\n            }\n            if (left.id === '.' || left.id === '[') {\n                if (!left.first || left.first.string === 'arguments') {\n                    warn('bad_assignment', that);\n                }\n            } else if (left.identifier) {\n                if (!left.reserved && funct[left.string] === 'exception') {\n                    warn('assign_exception', left);\n                }\n            } else {\n                warn('bad_assignment', that);\n            }\n            that.second = expression(19);\n            if (that.id === '=' && are_similar(that.first, that.second)) {\n                warn('weird_assignment', that);\n            }\n            return that;\n        });\n        x.assign = true;\n        if (op) {\n            if (syntax[op].type) {\n                x.type = syntax[op].type;\n            }\n            if (syntax[op].bitwise) {\n                x.bitwise = true;\n            }\n        }\n        return x;\n    }\n\n\n    function bitwise(s, p) {\n        var x = infix(s, p, 'number');\n        x.bitwise = true;\n        return x;\n    }\n\n\n    function suffix(s) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            no_space_only(prev_token, token);\n            if (!option.plusplus) {\n                warn('unexpected_a', this);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warn('bad_operand', this);\n            }\n            this.first = left;\n            this.arity = 'suffix';\n            return this;\n        };\n        return x;\n    }\n\n\n    function optional_identifier() {\n        if (next_token.identifier) {\n            advance();\n            if (option.safe && banned[token.string]) {\n                warn('adsafe_a', token);\n            } else if (token.reserved && !option.es5) {\n                warn('expected_identifier_a_reserved', token);\n            }\n            return token.string;\n        }\n    }\n\n\n    function identifier() {\n        var i = optional_identifier();\n        if (!i) {\n            stop(token.id === 'function' && next_token.id === '('\n                ? 'name_function'\n                : 'expected_identifier_a');\n        }\n        return i;\n    }\n\n\n    function statement() {\n\n        var label, old_scope = scope, the_statement;\n\n// We don't like the empty statement.\n\n        if (next_token.id === ';') {\n            warn('unexpected_a');\n            semicolon();\n            return;\n        }\n\n// Is this a labeled statement?\n\n        if (next_token.identifier && !next_token.reserved && peek().id === ':') {\n            edge('label');\n            label = next_token;\n            advance();\n            advance(':');\n            scope = Object.create(old_scope);\n            add_label(label, 'label');\n            if (next_token.labeled !== true) {\n                warn('label_a_b', next_token, label.string, artifact());\n            } else if (jx.test(label.string + ':')) {\n                warn('url', label);\n            } else if (funct === global_funct) {\n                stop('unexpected_a', token);\n            }\n            next_token.label = label;\n        }\n\n// Parse the statement.\n\n        if (token.id !== 'else') {\n            edge();\n        }\n        step_in('statement');\n        the_statement = expression(0, true);\n        if (the_statement) {\n\n// Look for the final semicolon.\n\n            if (the_statement.arity === 'statement') {\n                if (the_statement.id === 'switch' ||\n                        (the_statement.block && the_statement.id !== 'do')) {\n                    spaces();\n                } else {\n                    semicolon();\n                }\n            } else {\n\n// If this is an expression statement, determine if it is acceptable.\n// We do not like\n//      new Blah();\n// statments. If it is to be used at all, new should only be used to make\n// objects, not side effects. The expression statements we do like do\n// assignment or invocation or delete.\n\n                if (the_statement.id === '(') {\n                    if (the_statement.first.id === 'new') {\n                        warn('bad_new');\n                    }\n                } else if (!the_statement.assign &&\n                        the_statement.id !== 'delete' &&\n                        the_statement.id !== '++' &&\n                        the_statement.id !== '--') {\n                    warn('assignment_function_expression', token);\n                }\n                semicolon();\n            }\n        }\n        step_out();\n        scope = old_scope;\n        return the_statement;\n    }\n\n\n    function statements() {\n        var array = [], disruptor, the_statement;\n\n// A disrupt statement may not be followed by any other statement.\n// If the last statement is disrupt, then the sequence is disrupt.\n\n        while (next_token.postscript !== true) {\n            if (next_token.id === ';') {\n                warn('unexpected_a', next_token);\n                semicolon();\n            } else {\n                if (next_token.string === 'use strict') {\n                    if ((!node_js && xmode !== 'script') || funct !== global_funct || array.length > 0) {\n                        warn('function_strict');\n                    }\n                    use_strict();\n                }\n                if (disruptor) {\n                    warn('unreachable_a_b', next_token, next_token.string,\n                        disruptor.string);\n                    disruptor = null;\n                }\n                the_statement = statement();\n                if (the_statement) {\n                    array.push(the_statement);\n                    if (the_statement.disrupt) {\n                        disruptor = the_statement;\n                        array.disrupt = true;\n                    }\n                }\n            }\n        }\n        return array;\n    }\n\n\n    function block(ordinary) {\n\n// array block is array sequence of statements wrapped in braces.\n// ordinary is false for function bodies and try blocks.\n// ordinary is true for if statements, while, etc.\n\n        var array,\n            curly = next_token,\n            old_in_block = in_block,\n            old_scope = scope,\n            old_strict_mode = strict_mode;\n\n        in_block = ordinary;\n        scope = Object.create(scope);\n        spaces();\n        if (next_token.id === '{') {\n            advance('{');\n            step_in();\n            if (!ordinary && !use_strict() && !old_strict_mode &&\n                    !option.sloppy && funct['(context)'] === global_funct) {\n                warn('missing_use_strict');\n            }\n            array = statements();\n            strict_mode = old_strict_mode;\n            step_out('}', curly);\n        } else if (!ordinary) {\n            stop('expected_a_b', next_token, '{', artifact());\n        } else {\n            warn('expected_a_b', next_token, '{', artifact());\n            array = [statement()];\n            array.disrupt = array[0].disrupt;\n        }\n        funct['(verb)'] = null;\n        scope = old_scope;\n        in_block = old_in_block;\n        if (ordinary && array.length === 0) {\n            warn('empty_block');\n        }\n        return array;\n    }\n\n\n    function tally_property(name) {\n        if (option.properties && typeof property_type[name] !== 'string') {\n            warn('unexpected_property_a', token, name);\n        }\n        if (typeof member[name] === 'number') {\n            member[name] += 1;\n        } else {\n            member[name] = 1;\n        }\n    }\n\n\n// ECMAScript parser\n\n    syntax['(identifier)'] = {\n        id: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var name = this.string,\n                variable = scope[name],\n                site,\n                writeable;\n\n// If the variable is not in scope, then we may have an undeclared variable.\n// Check the predefined list. If it was predefined, create the global\n// variable.\n\n            if (typeof variable !== 'object') {\n                writeable = predefined[name];\n                if (typeof writeable === 'boolean') {\n                    global_scope[name] = variable = {\n                        string:    name,\n                        writeable: writeable,\n                        funct:     global_funct\n                    };\n                    global_funct[name] = 'var';\n\n// But if the variable is not in scope, and is not predefined, and if we are not\n// in the global scope, then we have an undefined variable error.\n\n                } else {\n                    if (!option.undef) {\n                        warn('used_before_a', token);\n                    }\n                    scope[name] = variable = {\n                        string: name,\n                        writeable: true,\n                        funct: funct\n                    };\n                    funct[name] = 'undef';\n                }\n\n            }\n            site = variable.funct;\n\n// The name is in scope and defined in the current function.\n\n            if (funct === site) {\n\n//      Change 'unused' to 'var', and reject labels.\n\n                switch (funct[name]) {\n                case 'becoming':\n                    warn('unexpected_a', token);\n                    funct[name] = 'var';\n                    break;\n                case 'unused':\n                    funct[name] = 'var';\n                    break;\n                case 'unparam':\n                    funct[name] = 'parameter';\n                    break;\n                case 'unction':\n                    funct[name] = 'function';\n                    break;\n                case 'label':\n                    warn('a_label', token, name);\n                    break;\n                }\n\n// If the name is already defined in the current\n// function, but not as outer, then there is a scope error.\n\n            } else {\n                switch (funct[name]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warn('a_scope', token, name);\n                    break;\n                case 'label':\n                    warn('a_label', token, name);\n                    break;\n                case 'outer':\n                case 'global':\n                    break;\n                default:\n\n// If the name is defined in an outer function, make an outer entry, and if\n// it was unused, make it var.\n\n                    switch (site[name]) {\n                    case 'becoming':\n                    case 'closure':\n                    case 'function':\n                    case 'parameter':\n                    case 'unction':\n                    case 'unused':\n                    case 'var':\n                        site[name] = 'closure';\n                        funct[name] = site === global_funct\n                            ? 'global'\n                            : 'outer';\n                        break;\n                    case 'unparam':\n                        site[name] = 'parameter';\n                        funct[name] = 'outer';\n                        break;\n                    case 'undef':\n                        funct[name] = 'undef';\n                        break;\n                    case 'label':\n                        warn('a_label', token, name);\n                        break;\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            stop('expected_operator_a');\n        }\n    };\n\n// Build the syntax table by declaring the syntactic elements.\n\n    type('(array)', 'array');\n    type('(color)', 'color');\n    type('(function)', 'function');\n    type('(number)', 'number', return_this);\n    type('(object)', 'object');\n    type('(string)', 'string', return_this);\n    type('(boolean)', 'boolean', return_this);\n    type('(range)', 'range');\n    type('(regexp)', 'regexp', return_this);\n\n    ultimate('(begin)');\n    ultimate('(end)');\n    ultimate('(error)');\n    postscript(symbol('</'));\n    symbol('<!');\n    symbol('<!--');\n    symbol('-->');\n    postscript(symbol('}'));\n    symbol(')');\n    symbol(']');\n    postscript(symbol('\"'));\n    postscript(symbol('\\''));\n    symbol(';');\n    symbol(':');\n    symbol(',');\n    symbol('#');\n    symbol('@');\n    symbol('*/');\n    postscript(reserve('case'));\n    reserve('catch');\n    postscript(reserve('default'));\n    reserve('else');\n    reserve('finally');\n\n    reservevar('arguments', function (x) {\n        if (strict_mode && funct === global_funct) {\n            warn('strict', x);\n        } else if (option.safe) {\n            warn('adsafe_a', x);\n        }\n    });\n    reservevar('eval', function (x) {\n        if (option.safe) {\n            warn('adsafe_a', x);\n        }\n    });\n    constant('false', 'boolean');\n    constant('Infinity', 'number');\n    constant('NaN', 'number');\n    constant('null', '');\n    reservevar('this', function (x) {\n        if (option.safe) {\n            warn('adsafe_a', x);\n        } else if (strict_mode && funct['(token)'].arity === 'statement' &&\n                funct['(name)'].charAt(0) > 'Z') {\n            warn('strict', x);\n        }\n    });\n    constant('true', 'boolean');\n    constant('undefined', '');\n\n    infix('?', 30, function (left, that) {\n        step_in('?');\n        that.first = expected_condition(expected_relation(left));\n        that.second = expression(0);\n        spaces();\n        step_out();\n        var colon = next_token;\n        advance(':');\n        step_in(':');\n        spaces();\n        that.third = expression(10);\n        that.arity = 'ternary';\n        if (are_similar(that.second, that.third)) {\n            warn('weird_ternary', colon);\n        } else if (are_similar(that.first, that.second)) {\n            warn('use_or', that);\n        }\n        step_out();\n        return that;\n    });\n\n    infix('||', 40, function (left, that) {\n        function paren_check(that) {\n            if (that.id === '&&' && !that.paren) {\n                warn('and', that);\n            }\n            return that;\n        }\n\n        that.first = paren_check(expected_condition(expected_relation(left)));\n        that.second = paren_check(expected_relation(expression(40)));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    infix('&&', 50, function (left, that) {\n        that.first = expected_condition(expected_relation(left));\n        that.second = expected_relation(expression(50));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    prefix('void', function () {\n        this.first = expression(0);\n        this.arity = 'prefix';\n        if (option.es5) {\n            warn('expected_a_b', this, 'undefined', 'void');\n        } else if (this.first.number !== 0) {\n            warn('expected_a_b', this.first, '0', artifact(this.first));\n        }\n        this.type = 'undefined';\n        return this;\n    });\n\n    bitwise('|', 70);\n    bitwise('^', 80);\n    bitwise('&', 90);\n\n    relation('==', '===');\n    relation('===');\n    relation('!=', '!==');\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n\n    bitwise('<<', 120);\n    bitwise('>>', 120);\n    bitwise('>>>', 120);\n\n    infix('in', 120, function (left, that) {\n        warn('infix_in', that);\n        that.left = left;\n        that.right = expression(130);\n        return that;\n    }, 'boolean');\n    infix('instanceof', 120, null, 'boolean');\n    infix('+', 130, function (left, that) {\n        if (left.id === '(number)') {\n            if (left.number === 0) {\n                warn('unexpected_a', left, '0');\n            }\n        } else if (left.id === '(string)') {\n            if (left.string === '') {\n                warn('expected_a_b', left, 'String', '\\'\\'');\n            }\n        }\n        var right = expression(130);\n        if (right.id === '(number)') {\n            if (right.number === 0) {\n                warn('unexpected_a', right, '0');\n            }\n        } else if (right.id === '(string)') {\n            if (right.string === '') {\n                warn('expected_a_b', right, 'String', '\\'\\'');\n            }\n        }\n        if (left.id === right.id) {\n            if (left.id === '(string)' || left.id === '(number)') {\n                if (left.id === '(string)') {\n                    left.string += right.string;\n                    if (jx.test(left.string)) {\n                        warn('url', left);\n                    }\n                } else {\n                    left.number += right.number;\n                }\n                left.thru = right.thru;\n                return left;\n            }\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('+++', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('-', 130, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(130);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number -= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n    prefix('-');\n    prefix('---', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('---', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('*', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number *= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n    infix('/', 140, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number /= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n    infix('%', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number %= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    }, 'number');\n\n    suffix('++');\n    prefix('++');\n\n    suffix('--');\n    prefix('--');\n    prefix('delete', function () {\n        one_space();\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warn('deleted');\n        }\n        this.first = p;\n        return this;\n    });\n\n\n    prefix('~', function () {\n        no_space_only();\n        if (!option.bitwise) {\n            warn('unexpected_a', this);\n        }\n        expression(150);\n        return this;\n    }, 'number');\n    prefix('!', function () {\n        no_space_only();\n        this.first = expected_condition(expression(150));\n        this.arity = 'prefix';\n        if (bang[this.first.id] === true || this.first.assign) {\n            warn('confusing_a', this);\n        }\n        return this;\n    }, 'boolean');\n    prefix('typeof', null, 'string');\n    prefix('new', function () {\n        one_space();\n        var c = expression(160), n, p, v;\n        this.first = c;\n        if (c.id !== 'function') {\n            if (c.identifier) {\n                switch (c.string) {\n                case 'Object':\n                    warn('use_object', token);\n                    break;\n                case 'Array':\n                    if (next_token.id === '(') {\n                        p = next_token;\n                        p.first = this;\n                        advance('(');\n                        if (next_token.id !== ')') {\n                            n = expression(0);\n                            p.second = [n];\n                            if (n.type !== 'number' || next_token.id === ',') {\n                                warn('use_array', p);\n                            }\n                            while (next_token.id === ',') {\n                                advance(',');\n                                p.second.push(expression(0));\n                            }\n                        } else {\n                            warn('use_array', token);\n                        }\n                        advance(')', p);\n                        return p;\n                    }\n                    warn('use_array', token);\n                    break;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warn('not_a_constructor', c);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warn('function_eval');\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                case 'this':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        v = c.string.charAt(0);\n                        if (!option.newcap && (v < 'A' || v > 'Z')) {\n                            warn('constructor_name_a', token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warn('bad_constructor', token);\n                }\n            }\n        } else {\n            warn('weird_new', this);\n        }\n        if (next_token.id !== '(') {\n            warn('missing_a', next_token, '()');\n        }\n        return this;\n    });\n\n    infix('(', 160, function (left, that) {\n        var p;\n        if (indent && indent.mode === 'expression') {\n            no_space(prev_token, token);\n        } else {\n            no_space_only(prev_token, token);\n        }\n        if (!left.immed && left.id === 'function') {\n            warn('wrap_immediate');\n        }\n        p = [];\n        if (left.identifier) {\n            if (left.string.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                if (left.string !== 'Number' && left.string !== 'String' &&\n                        left.string !== 'Boolean' && left.string !== 'Date') {\n                    if (left.string === 'Math' || left.string === 'JSON') {\n                        warn('not_a_function', left);\n                    } else if (left.string === 'Object') {\n                        warn('use_object', token);\n                    } else if (left.string === 'Array' || !option.newcap) {\n                        warn('missing_a', left, 'new');\n                    }\n                }\n            }\n        } else if (left.id === '.') {\n            if (option.safe && left.first.string === 'Math' &&\n                    left.second === 'random') {\n                warn('adsafe_a', left);\n            } else if (left.second.string === 'split' &&\n                    left.first.id === '(string)') {\n                warn('use_array', left.second);\n            }\n        }\n        step_in();\n        if (next_token.id !== ')') {\n            no_space();\n            for (;;) {\n                edge();\n                p.push(expression(10));\n                if (next_token.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        no_space();\n        step_out(')', that);\n        if (typeof left === 'object') {\n            if (left.string === 'parseInt' && p.length === 1) {\n                warn('radix', left);\n            }\n            if (!option.evil) {\n                if (left.string === 'eval' || left.string === 'Function' ||\n                        left.string === 'execScript') {\n                    warn('evil', left);\n                } else if (p[0] && p[0].id === '(string)' &&\n                        (left.string === 'setTimeout' ||\n                        left.string === 'setInterval')) {\n                    warn('implied_evil', left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warn('bad_invocation', left);\n            }\n        }\n        that.first = left;\n        that.second = p;\n        return that;\n    }, '', true);\n\n    prefix('(', function () {\n        step_in('expression');\n        no_space();\n        edge();\n        if (next_token.id === 'function') {\n            next_token.immed = true;\n        }\n        var value = expression(0);\n        value.paren = true;\n        no_space();\n        step_out(')', this);\n        if (value.id === 'function') {\n            if (next_token.id === '(') {\n                warn('move_invocation');\n            } else {\n                warn('bad_wrap', this);\n            }\n        }\n        return value;\n    });\n\n    infix('.', 170, function (left, that) {\n        no_space(prev_token, token);\n        no_space();\n        var name = identifier(), type;\n        if (typeof name === 'string') {\n            tally_property(name);\n        }\n        that.first = left;\n        that.second = token;\n        if (left && left.string === 'arguments' &&\n                (name === 'callee' || name === 'caller')) {\n            warn('avoid_a', left, 'arguments.' + name);\n        } else if (!option.evil && left && left.string === 'document' &&\n                (name === 'write' || name === 'writeln')) {\n            warn('write_is_wrong', left);\n        } else if (option.adsafe) {\n            if (!adsafe_top && left.string === 'ADSAFE') {\n                if (name === 'id' || name === 'lib') {\n                    warn('adsafe_a', that);\n                } else if (name === 'go') {\n                    if (xmode !== 'script') {\n                        warn('adsafe_a', that);\n                    } else if (adsafe_went || next_token.id !== '(' ||\n                            peek(0).id !== '(string)' ||\n                            peek(0).string !== adsafe_id ||\n                            peek(1).id !== ',') {\n                        stop('adsafe_a', that, 'go');\n                    }\n                    adsafe_went = true;\n                    adsafe_may = false;\n                }\n            }\n            adsafe_top = false;\n        }\n        if (!option.evil && (name === 'eval' || name === 'execScript')) {\n            warn('evil');\n        } else if (option.safe) {\n            for (;;) {\n                if (banned[name] === true) {\n                    warn('adsafe_a', token, name);\n                }\n                if (typeof predefined[left.string] !== 'boolean' ||    //// check for writeable\n                        next_token.id === '(') {\n                    break;\n                }\n                if (next_token.id !== '.') {\n                    warn('adsafe_a', that);\n                    break;\n                }\n                advance('.');\n                token.first = that;\n                token.second = name;\n                that = token;\n                name = identifier();\n                if (typeof name === 'string') {\n                    tally_property(name);\n                }\n            }\n        }\n        type = property_type[name];\n        if (type && typeof type === 'string' && type !== '*') {\n            that.type = type;\n        }\n        return that;\n    }, '', true);\n\n    infix('[', 170, function (left, that) {\n        var e, s;\n        no_space_only(prev_token, token);\n        no_space();\n        step_in();\n        edge();\n        e = expression(0);\n        switch (e.type) {\n        case 'number':\n            if (e.id === '(number)' && left.id === 'arguments') {\n                warn('use_param', left);\n            }\n            break;\n        case 'string':\n            if (e.id === '(string)') {\n                if (option.safe && (banned[e.string] ||\n                        e.string.charAt(0) === '_' || e.string.slice(-1) === '_')) {\n                    warn('adsafe_subscript_a', e);\n                } else if (!option.evil &&\n                        (e.string === 'eval' || e.string === 'execScript')) {\n                    warn('evil', e);\n                } else if (!option.sub && ix.test(e.string)) {\n                    s = syntax[e.string];\n                    if (!s || !s.reserved) {\n                        warn('subscript', e);\n                    }\n                }\n                tally_property(e.string);\n            } else if (option.safe && e.id !== 'typeof') {\n                warn('adsafe_subscript_a', e);\n            }\n            break;\n        case undefined:\n            if (option.safe) {\n                warn('adsafe_subscript_a', e);\n            }\n            break;\n        default:\n            if (option.safe) {\n                warn('adsafe_subscript_a', e);\n            }\n        }\n        step_out(']', that);\n        no_space(prev_token, token);\n        that.first = left;\n        that.second = e;\n        return that;\n    }, '', true);\n\n    prefix('[', function () {\n        this.arity = 'prefix';\n        this.first = [];\n        step_in('array');\n        while (next_token.id !== '(end)') {\n            while (next_token.id === ',') {\n                warn('unexpected_a', next_token);\n                advance(',');\n            }\n            if (next_token.id === ']') {\n                break;\n            }\n            indent.wrap = false;\n            edge();\n            this.first.push(expression(10));\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id === ']' && !option.es5) {\n                    warn('unexpected_a', token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        step_out(']', this);\n        return this;\n    }, 170);\n\n\n    function property_name() {\n        var id = optional_identifier(true);\n        if (!id) {\n            if (next_token.id === '(string)') {\n                id = next_token.string;\n                if (option.safe) {\n                    if (banned[id]) {\n                        warn('adsafe_a');\n                    } else if (id.charAt(0) === '_' ||\n                            id.charAt(id.length - 1) === '_') {\n                        warn('dangling_a');\n                    }\n                }\n                advance();\n            } else if (next_token.id === '(number)') {\n                id = next_token.number.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function function_params() {\n        var id, paren = next_token, params = [];\n        advance('(');\n        step_in();\n        no_space();\n        if (next_token.id === ')') {\n            no_space();\n            step_out(')', paren);\n            return;\n        }\n        for (;;) {\n            edge();\n            id = identifier();\n            params.push(token);\n            add_label(token, option.unparam ? 'parameter' : 'unparam');\n            if (next_token.id === ',') {\n                comma();\n            } else {\n                no_space();\n                step_out(')', paren);\n                return params;\n            }\n        }\n    }\n\n\n\n    function do_function(func, name) {\n        var old_funct      = funct,\n            old_option     = option,\n            old_scope      = scope;\n        funct = {\n            '(name)'     : name || '\\'' + (anonname || '').replace(nx, sanitize) + '\\'',\n            '(line)'     : next_token.line,\n            '(context)'  : old_funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(token)'    : func\n        };\n        option = Object.create(old_option);\n        scope = Object.create(old_scope);\n        functions.push(funct);\n        func.name = name;\n        if (name) {\n            add_label(func, 'function', name);\n        }\n        func.writeable = false;\n        func.first = funct['(params)'] = function_params();\n        one_space();\n        func.block = block(false);\n        if (funct['(old_property_type)']) {\n            property_type = funct['(old_property_type)'];\n            delete funct['(old_property_type)'];\n        }\n        if (option.confusion) {\n            funct['(confusion)'] = true;\n        }\n        funct      = old_funct;\n        option     = old_option;\n        scope      = old_scope;\n    }\n\n\n    assignop('=');\n    assignop('+=', '+');\n    assignop('-=', '-');\n    assignop('*=', '*');\n    assignop('/=', '/').nud = function () {\n        stop('slash_equal');\n    };\n    assignop('%=', '%');\n    assignop('&=', '&');\n    assignop('|=', '|');\n    assignop('^=', '^');\n    assignop('<<=', '<<');\n    assignop('>>=', '>>');\n    assignop('>>>=', '>>>');\n\n\n    prefix('{', function () {\n        var get, i, j, name, p, set, seen = {};\n        this.arity = 'prefix';\n        this.first = [];\n        step_in();\n        while (next_token.id !== '}') {\n            indent.wrap = false;\n\n// JSLint recognizes the ES5 extension for get/set in object literals,\n// but requires that they be used in pairs.\n\n            edge();\n            if (next_token.string === 'get' && peek().id !== ':') {\n                if (!option.es5) {\n                    warn('es5');\n                }\n                get = next_token;\n                advance('get');\n                one_space_only();\n                name = next_token;\n                i = property_name();\n                if (!i) {\n                    stop('missing_property');\n                }\n                get.string = '';\n                do_function(get);\n                if (funct['(loopage)']) {\n                    warn('function_loop', get);\n                }\n                p = get.first;\n                if (p) {\n                    warn('parameter_a_get_b', p[0], p[0].string, i);\n                }\n                comma();\n                set = next_token;\n                spaces();\n                edge();\n                advance('set');\n                set.string = '';\n                one_space_only();\n                j = property_name();\n                if (i !== j) {\n                    stop('expected_a_b', token, i, j || next_token.string);\n                }\n                do_function(set);\n                if (set.block.length === 0) {\n                    warn('missing_a', token, 'throw');\n                }\n                p = set.first;\n                if (!p || p.length !== 1) {\n                    stop('parameter_set_a', set, 'value');\n                } else if (p[0].string !== 'value') {\n                    stop('expected_a_b', p[0], 'value', p[0].string);\n                }\n                name.first = [get, set];\n            } else {\n                name = next_token;\n                i = property_name();\n                if (typeof i !== 'string') {\n                    stop('missing_property');\n                }\n                advance(':');\n                spaces();\n                name.first = expression(10);\n            }\n            this.first.push(name);\n            if (seen[i] === true) {\n                warn('duplicate_a', next_token, i);\n            }\n            seen[i] = true;\n            tally_property(i);\n            if (next_token.id !== ',') {\n                break;\n            }\n            for (;;) {\n                comma();\n                if (next_token.id !== ',') {\n                    break;\n                }\n                warn('unexpected_a', next_token);\n            }\n            if (next_token.id === '}' && !option.es5) {\n                warn('unexpected_a', token);\n            }\n        }\n        step_out('}', this);\n        return this;\n    });\n\n    stmt('{', function () {\n        warn('statement_block');\n        this.arity = 'statement';\n        this.block = statements();\n        this.disrupt = this.block.disrupt;\n        advance('}', this);\n        return this;\n    });\n\n    stmt('/*global', directive);\n    stmt('/*globals', directive);\n    stmt('/*jslint', directive);\n    stmt('/*member', directive);\n    stmt('/*members', directive);\n    stmt('/*property', directive);\n    stmt('/*properties', directive);\n\n    stmt('var', function () {\n\n// JavaScript does not have block scope. It only has function scope. So,\n// declaring a variable in a block can have unexpected consequences.\n\n// var.first will contain an array, the array containing name tokens\n// and assignment tokens.\n\n        var assign, id, name;\n\n        if (funct['(vars)'] && !option.vars) {\n            warn('combine_var');\n        } else if (funct !== global_funct) {\n            funct['(vars)'] = true;\n        }\n        this.arity = 'statement';\n        this.first = [];\n        step_in('var');\n        for (;;) {\n            name = next_token;\n            id = identifier();\n            add_label(name, 'becoming');\n\n            if (next_token.id === '=') {\n                assign = next_token;\n                assign.first = name;\n                spaces();\n                advance('=');\n                spaces();\n                if (next_token.id === 'undefined') {\n                    warn('unnecessary_initialize', token, id);\n                }\n                if (peek(0).id === '=' && next_token.identifier) {\n                    stop('var_a_not');\n                }\n                assign.second = expression(0);\n                assign.arity = 'infix';\n                this.first.push(assign);\n            } else {\n                this.first.push(name);\n            }\n            if (funct[id] === 'becoming') {\n                funct[id] = 'unused';\n            }\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n            indent.wrap = false;\n            if (var_mode && next_token.line === token.line &&\n                    this.first.length === 1) {\n                var_mode = null;\n                indent.open = false;\n                indent.at -= option.indent;\n            }\n            spaces();\n            edge();\n        }\n        var_mode = null;\n        step_out();\n        return this;\n    });\n\n    stmt('function', function () {\n        one_space();\n        if (in_block) {\n            warn('function_block', token);\n        }\n        var name = next_token, id = identifier();\n        add_label(name, 'unction');\n        no_space();\n        this.arity = 'statement';\n        do_function(this, id);\n        if (next_token.id === '(' && next_token.line === token.line) {\n            stop('function_statement');\n        }\n        return this;\n    });\n\n    prefix('function', function () {\n        if (!option.anon) {\n            one_space();\n        }\n        var id = optional_identifier();\n        if (id) {\n            no_space();\n        } else {\n            id = '';\n        }\n        do_function(this, id);\n        if (funct['(loopage)']) {\n            warn('function_loop');\n        }\n        this.arity = 'function';\n        return this;\n    });\n\n    stmt('if', function () {\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block(true);\n        if (next_token.id === 'else') {\n            one_space();\n            advance('else');\n            one_space();\n            this['else'] = next_token.id === 'if' || next_token.id === 'switch'\n                ? statement(true)\n                : block(true);\n            if (this['else'].disrupt && this.block.disrupt) {\n                this.disrupt = true;\n            }\n        }\n        return this;\n    });\n\n    stmt('try', function () {\n\n// try.first    The catch variable\n// try.second   The catch clause\n// try.third    The finally clause\n// try.block    The try block\n\n        var exception_variable, old_scope, paren;\n        if (option.adsafe) {\n            warn('adsafe_a', this);\n        }\n        one_space();\n        this.arity = 'statement';\n        this.block = block(false);\n        if (next_token.id === 'catch') {\n            one_space();\n            advance('catch');\n            one_space();\n            paren = next_token;\n            advance('(');\n            step_in('control');\n            no_space();\n            edge();\n            old_scope = scope;\n            scope = Object.create(old_scope);\n            exception_variable = next_token.string;\n            this.first = exception_variable;\n            if (!next_token.identifier) {\n                warn('expected_identifier_a', next_token);\n            } else {\n                add_label(next_token, 'exception');\n            }\n            advance();\n            no_space();\n            step_out(')', paren);\n            one_space();\n            this.second = block(false);\n            scope = old_scope;\n        }\n        if (next_token.id === 'finally') {\n            one_space();\n            advance('finally');\n            one_space();\n            this.third = block(false);\n        } else if (!this.second) {\n            stop('expected_a_b', next_token, 'catch', artifact());\n        }\n        return this;\n    });\n\n    labeled_stmt('while', function () {\n        one_space();\n        var paren = next_token;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_relation(expression(0));\n        if (this.first.id !== 'true') {\n            expected_condition(this.first, bundle.unexpected_a);\n        }\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    reserve('with');\n\n    labeled_stmt('switch', function () {\n\n// switch.first         the switch expression\n// switch.second        the array of cases. A case is 'case' or 'default' token:\n//    case.first        the array of case expressions\n//    case.second       the array of statements\n// If all of the arrays of statements are disrupt, then the switch is disrupt.\n\n        var cases = [],\n            old_in_block = in_block,\n            particular,\n            the_case = next_token,\n            unbroken = true;\n\n        function find_duplicate_case(value) {\n            if (are_similar(particular, value)) {\n                warn('duplicate_a', value);\n            }\n        }\n\n        funct['(breakage)'] += 1;\n        one_space();\n        advance('(');\n        no_space();\n        step_in();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', the_case);\n        one_space();\n        advance('{');\n        step_in();\n        in_block = true;\n        this.second = [];\n        while (next_token.id === 'case') {\n            the_case = next_token;\n            cases.forEach(find_duplicate_case);\n            the_case.first = [];\n            the_case.arity = 'case';\n            spaces();\n            edge('case');\n            advance('case');\n            for (;;) {\n                one_space();\n                particular = expression(0);\n                cases.forEach(find_duplicate_case);\n                cases.push(particular);\n                the_case.first.push(particular);\n                if (particular.id === 'NaN') {\n                    warn('unexpected_a', particular);\n                }\n                no_space_only();\n                advance(':');\n                if (next_token.id !== 'case') {\n                    break;\n                }\n                spaces();\n                edge('case');\n                advance('case');\n            }\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (particular.disrupt) {\n                    if (particular.id === 'break') {\n                        unbroken = false;\n                    }\n                } else {\n                    warn('missing_a_after_b', next_token, 'break', 'case');\n                }\n            } else {\n                warn('empty_case');\n            }\n            this.second.push(the_case);\n        }\n        if (this.second.length === 0) {\n            warn('missing_a', next_token, 'case');\n        }\n        if (next_token.id === 'default') {\n            spaces();\n            the_case = next_token;\n            the_case.arity = 'case';\n            edge('case');\n            advance('default');\n            no_space_only();\n            advance(':');\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (unbroken && particular.disrupt && particular.id !== 'break') {\n                    this.disrupt = true;\n                }\n            }\n            this.second.push(the_case);\n        }\n        funct['(breakage)'] -= 1;\n        spaces();\n        step_out('}', this);\n        in_block = old_in_block;\n        return this;\n    });\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        return this;\n    });\n\n    labeled_stmt('do', function () {\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        one_space();\n        this.arity = 'statement';\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        one_space();\n        advance('while');\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in();\n        no_space();\n        edge();\n        this.first = expected_condition(expected_relation(expression(0)), bundle.unexpected_a);\n        no_space();\n        step_out(')', paren);\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    labeled_stmt('for', function () {\n\n        var blok, filter, ok = false, paren = next_token, value;\n        this.arity = 'statement';\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        if (next_token.id === ';') {\n            no_space();\n            advance(';');\n            no_space();\n            advance(';');\n            no_space();\n            advance(')');\n            blok = block(true);\n        } else {\n            step_in('control');\n            spaces(this, paren);\n            no_space();\n            if (next_token.id === 'var') {\n                stop('move_var');\n            }\n            edge();\n            if (peek(0).id === 'in') {\n                this.forin = true;\n                value = next_token;\n                switch (funct[value.string]) {\n                case 'unused':\n                    funct[value.string] = 'var';\n                    break;\n                case 'closure':\n                case 'var':\n                    break;\n                default:\n                    warn('bad_in_a', value);\n                }\n                advance();\n                advance('in');\n                this.first = value;\n                this.second = expression(20);\n                step_out(')', paren);\n                blok = block(true);\n                if (!option.forin) {\n                    if (blok.length === 1 && typeof blok[0] === 'object' &&\n                            blok[0].string === 'if' && !blok[0]['else']) {\n                        filter = blok[0].first;\n                        while (filter.id === '&&') {\n                            filter = filter.first;\n                        }\n                        switch (filter.id) {\n                        case '===':\n                        case '!==':\n                            ok = filter.first.id === '['\n                                ? filter.first.first.string === this.second.string &&\n                                    filter.first.second.string === this.first.string\n                                : filter.first.id === 'typeof' &&\n                                    filter.first.first.id === '[' &&\n                                    filter.first.first.first.string === this.second.string &&\n                                    filter.first.first.second.string === this.first.string;\n                            break;\n                        case '(':\n                            ok = filter.first.id === '.' && ((\n                                filter.first.first.string === this.second.string &&\n                                filter.first.second.string === 'hasOwnProperty' &&\n                                filter.second[0].string === this.first.string\n                            ) || (\n                                filter.first.first.string === 'ADSAFE' &&\n                                filter.first.second.string === 'has' &&\n                                filter.second[0].string === this.second.string &&\n                                filter.second[1].string === this.first.string\n                            ) || (\n                                filter.first.first.id === '.' &&\n                                filter.first.first.first.id === '.' &&\n                                filter.first.first.first.first.string === 'Object' &&\n                                filter.first.first.first.second.string === 'prototype' &&\n                                filter.first.first.second.string === 'hasOwnProperty' &&\n                                filter.first.second.string === 'call' &&\n                                filter.second[0].string === this.second.string &&\n                                filter.second[1].string === this.first.string\n                            ));\n                            break;\n                        }\n                    }\n                    if (!ok) {\n                        warn('for_if', this);\n                    }\n                }\n            } else {\n                edge();\n                this.first = [];\n                for (;;) {\n                    this.first.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                semicolon();\n                edge();\n                this.second = expected_relation(expression(0));\n                if (this.second.id !== 'true') {\n                    expected_condition(this.second, bundle.unexpected_a);\n                }\n                semicolon(token);\n                if (next_token.id === ';') {\n                    stop('expected_a_b', next_token, ')', ';');\n                }\n                this.third = [];\n                edge();\n                for (;;) {\n                    this.third.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                no_space();\n                step_out(')', paren);\n                one_space();\n                blok = block(true);\n            }\n        }\n        if (blok.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        this.block = blok;\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    disrupt_stmt('break', function () {\n        var label = next_token.string;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label].funct !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('continue', function () {\n        if (!option['continue']) {\n            warn('unexpected_a', this);\n        }\n        var label = next_token.string;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label].funct !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('return', function () {\n        if (funct === global_funct) {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        if (next_token.id !== ';' && next_token.line === token.line) {\n            one_space_only();\n            if (next_token.id === '/' || next_token.id === '(regexp)') {\n                warn('wrap_regexp');\n            }\n            this.first = expression(20);\n        }\n        return this;\n    });\n\n    disrupt_stmt('throw', function () {\n        this.arity = 'statement';\n        one_space_only();\n        this.first = expression(20);\n        return this;\n    });\n\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n// Harmony reserved words\n\n    reserve('implements');\n    reserve('interface');\n    reserve('let');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n    reserve('yield');\n\n\n// Type inference\n\n//     function get_type(one) {\n//         var type;\n//         if (typeof one === 'string') {\n//             return one;\n//         } else if (one.type) {\n//             return one.type;\n//         } else if (one.id === '.') {\n//             type = property_type[one.second.string];\n//             return typeof type === 'string' ? type : '';\n//         } else {\n//             return ((one.identifier && scope[one.string]) || one).type;\n//         }\n//     }\n\n\n//     function match_type(one_type, two_type, one, two) {\n//         if (one_type === two_type) {\n//             return true;\n//         } else {\n//             if (!funct.confusion && !two.warn) {\n//                 if (typeof one !== 'string') {\n//                     if (one.id === '.') {\n//                         one_type = '.' + one.second.string + ': ' + one_type;\n//                     } else {\n//                         one_type = one.string + ': ' + one_type;\n//                     }\n//                 }\n//                 if (two.id === '.') {\n//                     two_type = '.' + two.second.string + ': ' + one_type;\n//                 } else {\n//                     two_type = two.string + ': ' + one_type;\n//                 }\n//                 warn('type_confusion_a_b', two, one_type, two_type);\n//                 two.warn = true;\n//             }\n//             return false;\n//         }\n//     }\n\n\n//     function conform(one, two) {\n//\n// // The conform function takes a type string and a token, or two tokens.\n//\n//         var one_type = typeof one === 'string' ? one : one.type,\n//             two_type = two.type,\n//             two_thing;\n//\n// // If both tokens already have a type, and if they match, then we are done.\n// // Once a token has a type, it is locked. Neither token will change, but if\n// // they do not match, there will be a warning.\n//\n//         if (one_type) {\n//             if (two_type) {\n//                 match_type(one_type, two_type, one, two);\n//             } else {\n//\n// // two does not have a type, so look deeper. If two is a variable or property,\n// // then use its type if it has one, and make the deep type one's type if it\n// // doesn't. If the type was *, or if there was a mismatch, don't change the\n// // deep type.\n//\n//                 two_thing = two.id === '(identifier)'\n//                     ? scope[two.string]\n//                     : two.id === '.'\n//                     ? property_type[two.second.string]\n//                     : null;\n//                 if (two_thing) {\n//                     two_type = two_thing.type;\n//                     if (two_type) {\n//                         if (two_type !== '*') {\n//                             if (!match_type(one_type, two_type, one, two)) {\n//                                 return '';\n//                             }\n//                         }\n//                     } else {\n//                         two_thing.type = one_type;\n//                     }\n//                 }\n//\n// // In any case, we give two a type.\n//\n//                 two.type = one_type;\n//                 type_state_change = true;\n//                 return one_type;\n//             }\n//\n// // one does not have a type, but two does, so do the old switcheroo.\n//\n//         } else {\n//             if (two_type) {\n//                 return conform(two, one);\n//\n// // Neither token has a type yet. So we have to look deeper to see if either\n// // is a variable or property.\n//\n//             } else {\n//                 if (one.id === '(identifier)') {\n//                     one_type = scope[one.string].type;\n//                     if (one_type && one_type !== '*') {\n//                         one.type = one_type;\n//                         return conform(one, two);\n//                     }\n//                 } else if (one.id === '.') {\n//                     one_type = property_type[one.second.string];\n//                     if (one_type && one_type !== '*') {\n//                         one.type = scope[one.string].type;\n//                         return conform(one, two);\n//                     }\n//                 }\n//                 if (two.id === '(identifier)') {\n//                     two_type = scope[two.string].type;\n//                     if (two_type && two_type !== '*') {\n//                         two.type = two_type;\n//                         return conform(two, one);\n//                     }\n//                 } else if (two.id === '.') {\n//                     two_type = property_type[two.second.string];\n//                     if (two_type && two_type !== '*') {\n//                         two.type = scope[two.string].type;\n//                         return conform(two, one);\n//                     }\n//                 }\n//             }\n//         }\n//\n// // Return a falsy string if we were unable to determine the type of either token.\n//\n//         return '';\n//     }\n\n//     function conform_array(type, array) {\n//         array.forEach(function (item) {\n//             return conform(type, item);\n//         }, type);\n//     }\n\n\n//     function infer(node) {\n//         if (Array.isArray(node)) {\n//             node.forEach(infer);\n//         } else {\n//             switch (node.arity) {\n//             case 'statement':\n//                 infer_statement[node.id](node);\n//                 break;\n//             case 'infix':\n//                 infer(node.first);\n//                 infer(node.second);\n//                 switch (node.id) {\n//                 case '(':\n//                     conform('function', node.first);\n//                     break;\n//                 default:\n//                     stop('unfinished');\n//                 }\n//                 break;\n//             case 'number':\n//             case 'string':\n//             case 'boolean':\n//                 break;\n//             default:\n//                 stop('unfinished');\n//             }\n//         }\n//     }\n\n\n//     infer_statement = {\n//         'var': function (node) {\n//             var i, item, list = node.first;\n//             for (i = 0; i < list.length; i += 1) {\n//                 item = list[i];\n//                 if (item.id === '=') {\n//                     infer(item.second);\n//                     conform(item.first, item.second);\n//                     conform(item.first, item);\n//                 }\n//             }\n//         },\n//         'for': function (node) {\n//             infer(node.first);\n//             infer(node.second);\n//             if (node.forin) {\n//                 conform('string', node.first);\n//                 conform('object', node.second);\n//             } else {\n//                 infer(node.third);\n//                 conform_array('number', node.first);\n//                 conform('boolean', node.second);\n//                 conform_array('number', node.third);\n//             }\n//             infer(node.block);\n//         }\n//     };\n\n\n//     function infer_types(node) {\n//         do {\n//             funct = global_funct;\n//             scope = global_scope;\n//             type_state_change = false;\n//             infer(node);\n//         } while (type_state_change);\n//     }\n\n\n// Parse JSON\n\n    function json_value() {\n\n        function json_object() {\n            var brace = next_token, object = {};\n            advance('{');\n            if (next_token.id !== '}') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        advance(',');\n                    }\n                    if (next_token.id !== '(string)') {\n                        warn('expected_string_a');\n                    }\n                    if (object[next_token.string] === true) {\n                        warn('duplicate_a');\n                    } else if (next_token.string === '__proto__') {\n                        warn('dangling_a');\n                    } else {\n                        object[next_token.string] = true;\n                    }\n                    advance();\n                    advance(':');\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === '}') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance('}', brace);\n        }\n\n        function json_array() {\n            var bracket = next_token;\n            advance('[');\n            if (next_token.id !== ']') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        advance(',');\n                    }\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === ']') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance(']', bracket);\n        }\n\n        switch (next_token.id) {\n        case '{':\n            json_object();\n            break;\n        case '[':\n            json_array();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            no_space_only();\n            advance('(number)');\n            break;\n        default:\n            stop('unexpected_a');\n        }\n    }\n\n\n// CSS parsing.\n\n    function css_name() {\n        if (next_token.identifier) {\n            advance();\n            return true;\n        }\n    }\n\n\n    function css_number() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance('(number)');\n            return true;\n        }\n    }\n\n\n    function css_string() {\n        if (next_token.id === '(string)') {\n            advance();\n            return true;\n        }\n    }\n\n    function css_color() {\n        var i, number, paren, value;\n        if (next_token.identifier) {\n            value = next_token.string;\n            if (value === 'rgb' || value === 'rgba') {\n                advance();\n                paren = next_token;\n                advance('(');\n                for (i = 0; i < 3; i += 1) {\n                    if (i) {\n                        comma();\n                    }\n                    number = next_token.number;\n                    if (next_token.id !== '(number)' || number < 0) {\n                        warn('expected_positive_a', next_token);\n                        advance();\n                    } else {\n                        advance();\n                        if (next_token.id === '%') {\n                            advance('%');\n                            if (number > 100) {\n                                warn('expected_percent_a', token, number);\n                            }\n                        } else {\n                            if (number > 255) {\n                                warn('expected_small_a', token, number);\n                            }\n                        }\n                    }\n                }\n                if (value === 'rgba') {\n                    comma();\n                    number = next_token.number;\n                    if (next_token.id !== '(number)' || number < 0 || number > 1) {\n                        warn('expected_fraction_a', next_token);\n                    }\n                    advance();\n                    if (next_token.id === '%') {\n                        warn('unexpected_a');\n                        advance('%');\n                    }\n                }\n                advance(')', paren);\n                return true;\n            } else if (css_colorData[next_token.string] === true) {\n                advance();\n                return true;\n            }\n        } else if (next_token.id === '(color)') {\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_length() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.id !== '(string)' &&\n                    css_lengthData[next_token.string] === true) {\n                no_space_only();\n                advance();\n            } else if (+token.number !== 0) {\n                warn('expected_linear_a');\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_line_height() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.id !== '(string)' &&\n                    css_lengthData[next_token.string] === true) {\n                no_space_only();\n                advance();\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_width() {\n        if (next_token.identifier) {\n            switch (next_token.string) {\n            case 'thin':\n            case 'medium':\n            case 'thick':\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n\n    function css_margin() {\n        if (next_token.identifier) {\n            if (next_token.string === 'auto') {\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n    function css_attr() {\n        if (next_token.identifier && next_token.string === 'attr') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_comma_list() {\n        while (next_token.id !== ';') {\n            if (!css_name() && !css_string()) {\n                warn('expected_name_a');\n            }\n            if (next_token.id !== ',') {\n                return true;\n            }\n            comma();\n        }\n    }\n\n\n    function css_counter() {\n        if (next_token.identifier && next_token.string === 'counter') {\n            advance();\n            advance('(');\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        if (next_token.identifier && next_token.string === 'counters') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_radius() {\n        return css_length() && (next_token.id !== '(number)' || css_length());\n    }\n\n\n    function css_shape() {\n        var i;\n        if (next_token.identifier && next_token.string === 'rect') {\n            advance();\n            advance('(');\n            for (i = 0; i < 4; i += 1) {\n                if (!css_length()) {\n                    warn('expected_number_a');\n                    break;\n                }\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_url() {\n        var c, url;\n        if (next_token.identifier && next_token.string === 'url') {\n            next_token = lex.range('(', ')');\n            url = next_token.string;\n            c = url.charAt(0);\n            if (c === '\"' || c === '\\'') {\n                if (url.slice(-1) !== c) {\n                    warn('bad_url_a');\n                } else {\n                    url = url.slice(1, -1);\n                    if (url.indexOf(c) >= 0) {\n                        warn('bad_url_a');\n                    }\n                }\n            }\n            if (!url) {\n                warn('missing_url');\n            }\n            if (ux.test(url)) {\n                stop('bad_url_a');\n            }\n            urls.push(url);\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    css_any = [css_url, function () {\n        for (;;) {\n            if (next_token.identifier) {\n                switch (next_token.string.toLowerCase()) {\n                case 'url':\n                    css_url();\n                    break;\n                case 'expression':\n                    warn('unexpected_a');\n                    advance();\n                    break;\n                default:\n                    advance();\n                }\n            } else {\n                if (next_token.id === ';' || next_token.id === '!'  ||\n                        next_token.id === '(end)' || next_token.id === '}') {\n                    return true;\n                }\n                advance();\n            }\n        }\n    }];\n\n\n    function font_face() {\n        advance_identifier('font-family');\n        advance(':');\n        if (!css_name() && !css_string()) {\n            stop('expected_name_a');\n        }\n        semicolon();\n        advance_identifier('src');\n        advance(':');\n        while (true) {\n            if (next_token.string === 'local') {\n                advance_identifier('local');\n                advance('(');\n                if (ux.test(next_token.string)) {\n                    stop('bad_url_a');\n                }\n\n                if (!css_name() && !css_string()) {\n                    stop('expected_name_a');\n                }\n                advance(')');\n            } else if (!css_url()) {\n                stop('expected_a_b', next_token, 'url', artifact());\n            }\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n        }\n        semicolon();\n    }\n\n\n    css_border_style = [\n        'none', 'dashed', 'dotted', 'double', 'groove',\n        'hidden', 'inset', 'outset', 'ridge', 'solid'\n    ];\n\n    css_break = [\n        'auto', 'always', 'avoid', 'left', 'right'\n    ];\n\n    css_media = {\n        'all': true,\n        'braille': true,\n        'embossed': true,\n        'handheld': true,\n        'print': true,\n        'projection': true,\n        'screen': true,\n        'speech': true,\n        'tty': true,\n        'tv': true\n    };\n\n    css_overflow = [\n        'auto', 'hidden', 'scroll', 'visible'\n    ];\n\n    css_attribute_data = {\n        background: [\n            true, 'background-attachment', 'background-color',\n            'background-image', 'background-position', 'background-repeat'\n        ],\n        'background-attachment': ['scroll', 'fixed'],\n        'background-color': ['transparent', css_color],\n        'background-image': ['none', css_url],\n        'background-position': [\n            2, [css_length, 'top', 'bottom', 'left', 'right', 'center']\n        ],\n        'background-repeat': [\n            'repeat', 'repeat-x', 'repeat-y', 'no-repeat'\n        ],\n        'border': [true, 'border-color', 'border-style', 'border-width'],\n        'border-bottom': [\n            true, 'border-bottom-color', 'border-bottom-style',\n            'border-bottom-width'\n        ],\n        'border-bottom-color': css_color,\n        'border-bottom-left-radius': css_radius,\n        'border-bottom-right-radius': css_radius,\n        'border-bottom-style': css_border_style,\n        'border-bottom-width': css_width,\n        'border-collapse': ['collapse', 'separate'],\n        'border-color': ['transparent', 4, css_color],\n        'border-left': [\n            true, 'border-left-color', 'border-left-style', 'border-left-width'\n        ],\n        'border-left-color': css_color,\n        'border-left-style': css_border_style,\n        'border-left-width': css_width,\n        'border-radius': function () {\n            function count(separator) {\n                var n = 1;\n                if (separator) {\n                    advance(separator);\n                }\n                if (!css_length()) {\n                    return false;\n                }\n                while (next_token.id === '(number)') {\n                    if (!css_length()) {\n                        return false;\n                    }\n                    n += 1;\n                }\n                if (n > 4) {\n                    warn('bad_style');\n                }\n                return true;\n            }\n\n            return count() && (next_token.id !== '/' || count('/'));\n        },\n        'border-right': [\n            true, 'border-right-color', 'border-right-style',\n            'border-right-width'\n        ],\n        'border-right-color': css_color,\n        'border-right-style': css_border_style,\n        'border-right-width': css_width,\n        'border-spacing': [2, css_length],\n        'border-style': [4, css_border_style],\n        'border-top': [\n            true, 'border-top-color', 'border-top-style', 'border-top-width'\n        ],\n        'border-top-color': css_color,\n        'border-top-left-radius': css_radius,\n        'border-top-right-radius': css_radius,\n        'border-top-style': css_border_style,\n        'border-top-width': css_width,\n        'border-width': [4, css_width],\n        bottom: [css_length, 'auto'],\n        'caption-side' : ['bottom', 'left', 'right', 'top'],\n        clear: ['both', 'left', 'none', 'right'],\n        clip: [css_shape, 'auto'],\n        color: css_color,\n        content: [\n            'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',\n            css_string, css_url, css_counter, css_attr\n        ],\n        'counter-increment': [\n            css_name, 'none'\n        ],\n        'counter-reset': [\n            css_name, 'none'\n        ],\n        cursor: [\n            css_url, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',\n            'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',\n            'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'\n        ],\n        direction: ['ltr', 'rtl'],\n        display: [\n            'block', 'compact', 'inline', 'inline-block', 'inline-table',\n            'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',\n            'table-cell', 'table-column', 'table-column-group',\n            'table-footer-group', 'table-header-group', 'table-row',\n            'table-row-group'\n        ],\n        'empty-cells': ['show', 'hide'],\n        'float': ['left', 'none', 'right'],\n        font: [\n            'caption', 'icon', 'menu', 'message-box', 'small-caption',\n            'status-bar', true, 'font-size', 'font-style', 'font-weight',\n            'font-family'\n        ],\n        'font-family': css_comma_list,\n        'font-size': [\n            'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',\n            'xx-large', 'larger', 'smaller', css_length\n        ],\n        'font-size-adjust': ['none', css_number],\n        'font-stretch': [\n            'normal', 'wider', 'narrower', 'ultra-condensed',\n            'extra-condensed', 'condensed', 'semi-condensed',\n            'semi-expanded', 'expanded', 'extra-expanded'\n        ],\n        'font-style': [\n            'normal', 'italic', 'oblique'\n        ],\n        'font-variant': [\n            'normal', 'small-caps'\n        ],\n        'font-weight': [\n            'normal', 'bold', 'bolder', 'lighter', css_number\n        ],\n        height: [css_length, 'auto'],\n        left: [css_length, 'auto'],\n        'letter-spacing': ['normal', css_length],\n        'line-height': ['normal', css_line_height],\n        'list-style': [\n            true, 'list-style-image', 'list-style-position', 'list-style-type'\n        ],\n        'list-style-image': ['none', css_url],\n        'list-style-position': ['inside', 'outside'],\n        'list-style-type': [\n            'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',\n            'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',\n            'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',\n            'hiragana-iroha', 'katakana-oroha', 'none'\n        ],\n        margin: [4, css_margin],\n        'margin-bottom': css_margin,\n        'margin-left': css_margin,\n        'margin-right': css_margin,\n        'margin-top': css_margin,\n        'marker-offset': [css_length, 'auto'],\n        'max-height': [css_length, 'none'],\n        'max-width': [css_length, 'none'],\n        'min-height': css_length,\n        'min-width': css_length,\n        opacity: css_number,\n        outline: [true, 'outline-color', 'outline-style', 'outline-width'],\n        'outline-color': ['invert', css_color],\n        'outline-style': [\n            'dashed', 'dotted', 'double', 'groove', 'inset', 'none',\n            'outset', 'ridge', 'solid'\n        ],\n        'outline-width': css_width,\n        overflow: css_overflow,\n        'overflow-x': css_overflow,\n        'overflow-y': css_overflow,\n        padding: [4, css_length],\n        'padding-bottom': css_length,\n        'padding-left': css_length,\n        'padding-right': css_length,\n        'padding-top': css_length,\n        'page-break-after': css_break,\n        'page-break-before': css_break,\n        position: ['absolute', 'fixed', 'relative', 'static'],\n        quotes: [8, css_string],\n        right: [css_length, 'auto'],\n        'table-layout': ['auto', 'fixed'],\n        'text-align': ['center', 'justify', 'left', 'right'],\n        'text-decoration': [\n            'none', 'underline', 'overline', 'line-through', 'blink'\n        ],\n        'text-indent': css_length,\n        'text-shadow': ['none', 4, [css_color, css_length]],\n        'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],\n        top: [css_length, 'auto'],\n        'unicode-bidi': ['normal', 'embed', 'bidi-override'],\n        'vertical-align': [\n            'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',\n            'text-bottom', css_length\n        ],\n        visibility: ['visible', 'hidden', 'collapse'],\n        'white-space': [\n            'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'\n        ],\n        width: [css_length, 'auto'],\n        'word-spacing': ['normal', css_length],\n        'word-wrap': ['break-word', 'normal'],\n        'z-index': ['auto', css_number]\n    };\n\n    function style_attribute() {\n        var v;\n        while (next_token.id === '*' || next_token.id === '#' ||\n                next_token.string === '_') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance();\n        }\n        if (next_token.id === '-') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance('-');\n            if (!next_token.identifier) {\n                warn('expected_nonstandard_style_attribute');\n            }\n            advance();\n            return css_any;\n        } else {\n            if (!next_token.identifier) {\n                warn('expected_style_attribute');\n            } else {\n                if (Object.prototype.hasOwnProperty.call(css_attribute_data,\n                        next_token.string)) {\n                    v = css_attribute_data[next_token.string];\n                } else {\n                    v = css_any;\n                    if (!option.css) {\n                        warn('unrecognized_style_attribute_a');\n                    }\n                }\n            }\n            advance();\n            return v;\n        }\n    }\n\n\n    function style_value(v) {\n\n        /*jslint confusion: true */\n\n        var i = 0,\n            n,\n            once,\n            match,\n            round,\n            start = 0,\n            vi;\n        switch (typeof v) {\n        case 'function':\n            return v();\n        case 'string':\n            if (next_token.identifier && next_token.string === v) {\n                advance();\n                return true;\n            }\n            return false;\n        }\n        for (;;) {\n            if (i >= v.length) {\n                return false;\n            }\n            vi = v[i];\n            i += 1;\n            if (typeof vi === 'boolean') {\n                break;\n            } else if (typeof vi === 'number') {\n                n = vi;\n                vi = v[i];\n                i += 1;\n            } else {\n                n = 1;\n            }\n            match = false;\n            while (n > 0) {\n                if (style_value(vi)) {\n                    match = true;\n                    n -= 1;\n                } else {\n                    break;\n                }\n            }\n            if (match) {\n                return true;\n            }\n        }\n        start = i;\n        once = [];\n        for (;;) {\n            round = false;\n            for (i = start; i < v.length; i += 1) {\n                if (!once[i]) {\n                    if (style_value(css_attribute_data[v[i]])) {\n                        match = true;\n                        round = true;\n                        once[i] = true;\n                        break;\n                    }\n                }\n            }\n            if (!round) {\n                return match;\n            }\n        }\n    }\n\n    function style_child() {\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.string === 'n' && next_token.identifier) {\n                no_space_only();\n                advance();\n                if (next_token.id === '+') {\n                    no_space_only();\n                    advance('+');\n                    no_space_only();\n                    advance('(number)');\n                }\n            }\n            return;\n        } else {\n            if (next_token.identifier &&\n                    (next_token.string === 'odd' || next_token.string === 'even')) {\n                advance();\n                return;\n            }\n        }\n        warn('unexpected_a');\n    }\n\n    function substyle() {\n        var v;\n        for (;;) {\n            if (next_token.id === '}' || next_token.id === '(end)' ||\n                    (xquote && next_token.id === xquote)) {\n                return;\n            }\n            v = style_attribute();\n            advance(':');\n            if (next_token.identifier && next_token.string === 'inherit') {\n                advance();\n            } else {\n                if (!style_value(v)) {\n                    warn('unexpected_a');\n                    advance();\n                }\n            }\n            if (next_token.id === '!') {\n                advance('!');\n                no_space_only();\n                if (next_token.identifier && next_token.string === 'important') {\n                    advance();\n                } else {\n                    warn('expected_a_b',\n                        next_token, 'important', artifact());\n                }\n            }\n            if (next_token.id === '}' || next_token.id === xquote) {\n                warn('expected_a_b', next_token, ';', artifact());\n            } else {\n                semicolon();\n            }\n        }\n    }\n\n    function style_selector() {\n        if (next_token.identifier) {\n            if (!Object.prototype.hasOwnProperty.call(html_tag, option.cap\n                    ? next_token.string.toLowerCase()\n                    : next_token.string)) {\n                warn('expected_tagname_a');\n            }\n            advance();\n        } else {\n            switch (next_token.id) {\n            case '>':\n            case '+':\n                advance();\n                style_selector();\n                break;\n            case ':':\n                advance(':');\n                switch (next_token.string) {\n                case 'active':\n                case 'after':\n                case 'before':\n                case 'checked':\n                case 'disabled':\n                case 'empty':\n                case 'enabled':\n                case 'first-child':\n                case 'first-letter':\n                case 'first-line':\n                case 'first-of-type':\n                case 'focus':\n                case 'hover':\n                case 'last-child':\n                case 'last-of-type':\n                case 'link':\n                case 'only-of-type':\n                case 'root':\n                case 'target':\n                case 'visited':\n                    advance_identifier(next_token.string);\n                    break;\n                case 'lang':\n                    advance_identifier('lang');\n                    advance('(');\n                    if (!next_token.identifier) {\n                        warn('expected_lang_a');\n                    }\n                    advance(')');\n                    break;\n                case 'nth-child':\n                case 'nth-last-child':\n                case 'nth-last-of-type':\n                case 'nth-of-type':\n                    advance_identifier(next_token.string);\n                    advance('(');\n                    style_child();\n                    advance(')');\n                    break;\n                case 'not':\n                    advance_identifier('not');\n                    advance('(');\n                    if (next_token.id === ':' && peek(0).string === 'not') {\n                        warn('not');\n                    }\n                    style_selector();\n                    advance(')');\n                    break;\n                default:\n                    warn('expected_pseudo_a');\n                }\n                break;\n            case '#':\n                advance('#');\n                if (!next_token.identifier) {\n                    warn('expected_id_a');\n                }\n                advance();\n                break;\n            case '*':\n                advance('*');\n                break;\n            case '.':\n                advance('.');\n                if (!next_token.identifier) {\n                    warn('expected_class_a');\n                }\n                advance();\n                break;\n            case '[':\n                advance('[');\n                if (!next_token.identifier) {\n                    warn('expected_attribute_a');\n                }\n                advance();\n                if (next_token.id === '=' || next_token.string === '~=' ||\n                        next_token.string === '$=' ||\n                        next_token.string === '|=' ||\n                        next_token.id === '*=' ||\n                        next_token.id === '^=') {\n                    advance();\n                    if (next_token.id !== '(string)') {\n                        warn('expected_string_a');\n                    }\n                    advance();\n                }\n                advance(']');\n                break;\n            default:\n                stop('expected_selector_a');\n            }\n        }\n    }\n\n    function style_pattern() {\n        if (next_token.id === '{') {\n            warn('expected_style_pattern');\n        }\n        for (;;) {\n            style_selector();\n            if (next_token.id === '</' || next_token.id === '{' ||\n                    next_token.id === '}' || next_token.id === '(end)') {\n                return '';\n            }\n            if (next_token.id === ',') {\n                comma();\n            }\n        }\n    }\n\n    function style_list() {\n        while (next_token.id !== '}' && next_token.id !== '</' &&\n                next_token.id !== '(end)') {\n            style_pattern();\n            xmode = 'styleproperty';\n            if (next_token.id === ';') {\n                semicolon();\n            } else {\n                advance('{');\n                substyle();\n                xmode = 'style';\n                advance('}');\n            }\n        }\n    }\n\n    function styles() {\n        var i;\n        while (next_token.id === '@') {\n            i = peek();\n            advance('@');\n            switch (next_token.string) {\n            case 'import':\n                advance_identifier('import');\n                if (!css_url()) {\n                    warn('expected_a_b',\n                        next_token, 'url', artifact());\n                    advance();\n                }\n                semicolon();\n                break;\n            case 'media':\n                advance_identifier('media');\n                for (;;) {\n                    if (!next_token.identifier || css_media[next_token.string] !== true) {\n                        stop('expected_media_a');\n                    }\n                    advance();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                advance('{');\n                style_list();\n                advance('}');\n                break;\n            case 'font-face':\n                advance_identifier('font-face');\n                advance('{');\n                font_face();\n                advance('}');\n                break;\n            default:\n                stop('expected_at_a');\n            }\n        }\n        style_list();\n    }\n\n\n// Parse HTML\n\n    function do_begin(n) {\n        if (n !== 'html' && !option.fragment) {\n            if (n === 'div' && option.adsafe) {\n                stop('adsafe_fragment');\n            } else {\n                stop('expected_a_b', token, 'html', n);\n            }\n        }\n        if (option.adsafe) {\n            if (n === 'html') {\n                stop('adsafe_html', token);\n            }\n            if (option.fragment) {\n                if (n !== 'div') {\n                    stop('adsafe_div', token);\n                }\n            } else {\n                stop('adsafe_fragment', token);\n            }\n        }\n        option.browser = true;\n    }\n\n    function do_attribute(a, v) {\n        var u, x;\n        if (a === 'id') {\n            u = typeof v === 'string' ? v.toUpperCase() : '';\n            if (ids[u] === true) {\n                warn('duplicate_a', next_token, v);\n            }\n            if (!/^[A-Za-z][A-Za-z0-9._:\\-]*$/.test(v)) {\n                warn('bad_id_a', next_token, v);\n            } else if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    adsafe_id = v;\n                    if (!/^[A-Z]+_$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                }\n            }\n            x = v.search(dx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'class' || a === 'type' || a === 'name') {\n            x = v.search(qx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'href' || a === 'background' ||\n                a === 'content' || a === 'data' ||\n                a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {\n            if (option.safe && ux.test(v)) {\n                stop('bad_url_a', next_token, v);\n            }\n            urls.push(v);\n        } else if (a === 'for') {\n            if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    warn('adsafe_bad_id');\n                }\n            }\n        } else if (a === 'name') {\n            if (option.adsafe && v.indexOf('_') >= 0) {\n                warn('adsafe_name_a', next_token, v);\n            }\n        }\n    }\n\n    function do_tag(name, attribute) {\n        var i, tag = html_tag[name], script, x;\n        src = false;\n        if (!tag) {\n            stop(\n                bundle.unrecognized_tag_a,\n                next_token,\n                name === name.toLowerCase()\n                    ? name\n                    : name + ' (capitalization error)'\n            );\n        }\n        if (stack.length > 0) {\n            if (name === 'html') {\n                stop('unexpected_a', token, name);\n            }\n            x = tag.parent;\n            if (x) {\n                if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {\n                    stop('tag_a_in_b', token, name, x);\n                }\n            } else if (!option.adsafe && !option.fragment) {\n                i = stack.length;\n                do {\n                    if (i <= 0) {\n                        stop('tag_a_in_b', token, name, 'body');\n                    }\n                    i -= 1;\n                } while (stack[i].name !== 'body');\n            }\n        }\n        switch (name) {\n        case 'div':\n            if (option.adsafe && stack.length === 1 && !adsafe_id) {\n                warn('adsafe_missing_id');\n            }\n            break;\n        case 'script':\n            xmode = 'script';\n            advance('>');\n            if (attribute.lang) {\n                warn('lang', token);\n            }\n            if (option.adsafe && stack.length !== 1) {\n                warn('adsafe_placement', token);\n            }\n            if (attribute.src) {\n                if (option.adsafe && (!adsafe_may || !approved[attribute.src])) {\n                    warn('adsafe_source', token);\n                }\n                if (attribute.type) {\n                    warn('type', token);\n                }\n            } else {\n                step_in(next_token.from);\n                edge();\n                use_strict();\n                adsafe_top = true;\n                script = statements();\n\n// JSLint is also the static analyzer for ADsafe. See www.ADsafe.org.\n\n                if (option.adsafe) {\n                    if (adsafe_went) {\n                        stop('adsafe_script', token);\n                    }\n                    if (script.length !== 1 ||\n                            aint(script[0],             'id',     '(') ||\n                            aint(script[0].first,       'id',     '.') ||\n                            aint(script[0].first.first, 'string', 'ADSAFE') ||\n                            aint(script[0].second[0],   'string', adsafe_id)) {\n                        stop('adsafe_id_go');\n                    }\n                    switch (script[0].first.second.string) {\n                    case 'id':\n                        if (adsafe_may || adsafe_went ||\n                                script[0].second.length !== 1) {\n                            stop('adsafe_id', next_token);\n                        }\n                        adsafe_may = true;\n                        break;\n                    case 'go':\n                        if (adsafe_went) {\n                            stop('adsafe_go');\n                        }\n                        if (script[0].second.length !== 2 ||\n                                aint(script[0].second[1], 'id', 'function') ||\n                                !script[0].second[1].first ||\n                                aint(script[0].second[1].first[0], 'string', 'dom') ||\n                                script[0].second[1].first.length > 2 ||\n                                (script[0].second[1].first.length === 2 &&\n                                aint(script[0].second[1].first[1], 'string', 'lib'))) {\n                            stop('adsafe_go', next_token);\n                        }\n                        adsafe_went = true;\n                        break;\n                    default:\n                        stop('adsafe_id_go');\n                    }\n                }\n                indent = null;\n            }\n            xmode = 'html';\n            advance('</');\n            advance_identifier('script');\n            xmode = 'outer';\n            break;\n        case 'style':\n            xmode = 'style';\n            advance('>');\n            styles();\n            xmode = 'html';\n            advance('</');\n            advance_identifier('style');\n            break;\n        case 'input':\n            switch (attribute.type) {\n            case 'button':\n            case 'checkbox':\n            case 'radio':\n            case 'reset':\n            case 'submit':\n                break;\n            case 'file':\n            case 'hidden':\n            case 'image':\n            case 'password':\n            case 'text':\n                if (option.adsafe && attribute.autocomplete !== 'off') {\n                    warn('adsafe_autocomplete');\n                }\n                break;\n            default:\n                warn('bad_type');\n            }\n            break;\n        case 'applet':\n        case 'body':\n        case 'embed':\n        case 'frame':\n        case 'frameset':\n        case 'head':\n        case 'iframe':\n        case 'noembed':\n        case 'noframes':\n        case 'object':\n        case 'param':\n            if (option.adsafe) {\n                warn('adsafe_tag', next_token, name);\n            }\n            break;\n        }\n    }\n\n\n    function closetag(name) {\n        return '</' + name + '>';\n    }\n\n    function html() {\n\n        /*jslint confusion: true */\n\n        var attribute, attributes, is_empty, name, old_white = option.white,\n            quote, tag_name, tag, wmode;\n        xmode = 'html';\n        xquote = '';\n        stack = null;\n        for (;;) {\n            switch (next_token.string) {\n            case '<':\n                xmode = 'html';\n                advance('<');\n                attributes = {};\n                tag_name = next_token;\n                name = tag_name.string;\n                advance_identifier(name);\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                tag_name.name = name;\n                if (!stack) {\n                    stack = [];\n                    do_begin(name);\n                }\n                tag = html_tag[name];\n                if (typeof tag !== 'object') {\n                    stop('unrecognized_tag_a', tag_name, name);\n                }\n                is_empty = tag.empty;\n                tag_name.type = name;\n                for (;;) {\n                    if (next_token.id === '/') {\n                        advance('/');\n                        if (next_token.id !== '>') {\n                            warn('expected_a_b', next_token, '>', artifact());\n                        }\n                        break;\n                    }\n                    if (next_token.id && next_token.id.charAt(0) === '>') {\n                        break;\n                    }\n                    if (!next_token.identifier) {\n                        if (next_token.id === '(end)' || next_token.id === '(error)') {\n                            warn('expected_a_b', next_token, '>', artifact());\n                        }\n                        warn('bad_name_a');\n                    }\n                    option.white = false;\n                    spaces();\n                    attribute = next_token.string;\n                    option.white = old_white;\n                    advance();\n                    if (!option.cap && attribute !== attribute.toLowerCase()) {\n                        warn('attribute_case_a', token);\n                    }\n                    attribute = attribute.toLowerCase();\n                    xquote = '';\n                    if (Object.prototype.hasOwnProperty.call(attributes, attribute)) {\n                        warn('duplicate_a', token, attribute);\n                    }\n                    if (attribute.slice(0, 2) === 'on') {\n                        if (!option.on) {\n                            warn('html_handlers');\n                        }\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            stop('expected_a_b', next_token, '\"', artifact());\n                        }\n                        xquote = quote;\n                        wmode = option.white;\n                        option.white = true;\n                        advance(quote);\n                        use_strict();\n                        statements();\n                        option.white = wmode;\n                        if (next_token.id !== quote) {\n                            stop('expected_a_b', next_token, quote, artifact());\n                        }\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else if (attribute === 'style') {\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            stop('expected_a_b', next_token, '\"', artifact());\n                        }\n                        xmode = 'styleproperty';\n                        xquote = quote;\n                        advance(quote);\n                        substyle();\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else {\n                        if (next_token.id === '=') {\n                            advance('=');\n                            tag = next_token.string;\n                            if (!next_token.identifier &&\n                                    next_token.id !== '\"' &&\n                                    next_token.id !== '\\'' &&\n                                    next_token.id !== '(string)' &&\n                                    next_token.id !== '(string)' &&\n                                    next_token.id !== '(color)') {\n                                warn('expected_attribute_value_a', token, attribute);\n                            }\n                            advance();\n                        } else {\n                            tag = true;\n                        }\n                    }\n                    attributes[attribute] = tag;\n                    do_attribute(attribute, tag);\n                }\n                do_tag(name, attributes);\n                if (!is_empty) {\n                    stack.push(tag_name);\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '</':\n                xmode = 'html';\n                advance('</');\n                if (!next_token.identifier) {\n                    warn('bad_name_a');\n                }\n                name = next_token.string;\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                advance();\n                if (!stack) {\n                    stop('unexpected_a', next_token, closetag(name));\n                }\n                tag_name = stack.pop();\n                if (!tag_name) {\n                    stop('unexpected_a', next_token, closetag(name));\n                }\n                if (tag_name.name !== name) {\n                    stop('expected_a_b',\n                        next_token, closetag(tag_name.name), closetag(name));\n                }\n                if (next_token.id !== '>') {\n                    stop('expected_a_b', next_token, '>', artifact());\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '<!':\n                if (option.safe) {\n                    warn('adsafe_a');\n                }\n                xmode = 'html';\n                for (;;) {\n                    advance();\n                    if (next_token.id === '>' || next_token.id === '(end)') {\n                        break;\n                    }\n                    if (next_token.string.indexOf('--') >= 0) {\n                        stop('unexpected_a', next_token, '--');\n                    }\n                    if (next_token.string.indexOf('<') >= 0) {\n                        stop('unexpected_a', next_token, '<');\n                    }\n                    if (next_token.string.indexOf('>') >= 0) {\n                        stop('unexpected_a', next_token, '>');\n                    }\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '(end)':\n                return;\n            default:\n                if (next_token.id === '(end)') {\n                    stop('missing_a', next_token,\n                        '</' + stack[stack.length - 1].string + '>');\n                } else {\n                    advance();\n                }\n            }\n            if (stack && stack.length === 0 && (option.adsafe ||\n                    !option.fragment || next_token.id === '(end)')) {\n                break;\n            }\n        }\n        if (next_token.id !== '(end)') {\n            stop('unexpected_a');\n        }\n    }\n\n\n// The actual JSLINT function itself.\n\n    itself = function JSLint(the_source, the_option) {\n\n        var i, predef, tree;\n        JSLINT.errors = [];\n        JSLINT.tree = '';\n        begin = prev_token = token = next_token =\n            Object.create(syntax['(begin)']);\n        predefined = {};\n        add_to_predefined(standard);\n        property_type = Object.create(standard_property_type);\n        if (the_option) {\n            option = Object.create(the_option);\n            predef = option.predef;\n            if (predef) {\n                if (Array.isArray(predef)) {\n                    for (i = 0; i < predef.length; i += 1) {\n                        predefined[predef[i]] = true;\n                    }\n                } else if (typeof predef === 'object') {\n                    add_to_predefined(predef);\n                }\n            }\n            do_safe();\n        } else {\n            option = {};\n        }\n        option.indent = +option.indent || 4;\n        option.maxerr = +option.maxerr || 50;\n        adsafe_id = '';\n        adsafe_may = adsafe_top = adsafe_went = false;\n        approved = {};\n        if (option.approved) {\n            for (i = 0; i < option.approved.length; i += 1) {\n                approved[option.approved[i]] = option.approved[i];\n            }\n        } else {\n            approved.test = 'test';\n        }\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        global_scope = scope = {};\n        global_funct = funct = {\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n\n        comments_off = false;\n        ids = {};\n        in_block = false;\n        indent = null;\n        json_mode = false;\n        lookahead = [];\n        member = {};\n        node_js = false;\n        prereg = true;\n        src = false;\n        stack = null;\n        strict_mode = false;\n        urls = [];\n        var_mode = null;\n        warnings = 0;\n        xmode = '';\n        lex.init(the_source);\n\n        assume();\n\n        try {\n            advance();\n            if (next_token.id === '(number)') {\n                stop('unexpected_a');\n            } else if (next_token.string.charAt(0) === '<') {\n                html();\n                if (option.adsafe && !adsafe_went) {\n                    warn('adsafe_go', this);\n                }\n            } else {\n                switch (next_token.id) {\n                case '{':\n                case '[':\n                    json_mode = true;\n                    json_value();\n                    break;\n                case '@':\n                case '*':\n                case '#':\n                case '.':\n                case ':':\n                    xmode = 'style';\n                    advance();\n                    if (token.id !== '@' || !next_token.identifier ||\n                            next_token.string !== 'charset' || token.line !== 1 ||\n                            token.from !== 1) {\n                        stop('css');\n                    }\n                    advance();\n                    if (next_token.id !== '(string)' &&\n                            next_token.string !== 'UTF-8') {\n                        stop('css');\n                    }\n                    advance();\n                    semicolon();\n                    styles();\n                    break;\n\n                default:\n                    if (option.adsafe && option.fragment) {\n                        stop('expected_a_b',\n                            next_token, '<div>', artifact());\n                    }\n\n// If the first token is a semicolon, ignore it. This is sometimes used when\n// files are intended to be appended to files that may be sloppy. A sloppy\n// file may be depending on semicolon insertion on its last line.\n\n                    step_in(1);\n                    if (next_token.id === ';' && !node_js) {\n                        semicolon();\n                    }\n                    adsafe_top = true;\n                    tree = statements();\n                    begin.first = tree;\n                    JSLINT.tree = begin;\n                    // infer_types(tree);\n                    if (option.adsafe && (tree.length !== 1 ||\n                            aint(tree[0], 'id', '(') ||\n                            aint(tree[0].first, 'id', '.') ||\n                            aint(tree[0].first.first, 'string', 'ADSAFE') ||\n                            aint(tree[0].first.second, 'string', 'lib') ||\n                            tree[0].second.length !== 2 ||\n                            tree[0].second[0].id !== '(string)' ||\n                            aint(tree[0].second[1], 'id', 'function'))) {\n                        stop('adsafe_lib');\n                    }\n                    if (tree.disrupt) {\n                        warn('weird_program', prev_token);\n                    }\n                }\n            }\n            indent = null;\n            advance('(end)');\n        } catch (e) {\n            if (e) {        // `~\n                JSLINT.errors.push({\n                    reason    : e.message,\n                    line      : e.line || next_token.line,\n                    character : e.character || next_token.from\n                }, null);\n            }\n        }\n        return JSLINT.errors.length === 0;\n    };\n\n\n// Data summary.\n\n    itself.data = function () {\n        var data = {functions: []},\n            function_data,\n            globals,\n            i,\n            j,\n            kind,\n            members = [],\n            name,\n            the_function,\n            undef = [],\n            unused = [];\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (json_mode) {\n            data.json = true;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(global_scope).filter(function (value) {\n            return value.charAt(0) !== '(' && typeof standard[value] !== 'boolean';\n        });\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            the_function = functions[i];\n            function_data = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                function_data[functionicity[j]] = [];\n            }\n            for (name in the_function) {\n                if (Object.prototype.hasOwnProperty.call(the_function, name)) {\n                    if (name.charAt(0) !== '(') {\n                        kind = the_function[name];\n                        if (kind === 'unction' || kind === 'unparam') {\n                            kind = 'unused';\n                        }\n                        if (Array.isArray(function_data[kind])) {\n                            function_data[kind].push(name);\n                            if (kind === 'unused') {\n                                unused.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            } else if (kind === 'undef') {\n                                undef.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            }\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (function_data[functionicity[j]].length === 0) {\n                    delete function_data[functionicity[j]];\n                }\n            }\n            function_data.name = the_function['(name)'];\n            function_data.params = the_function['(params)'];\n            function_data.line = the_function['(line)'];\n            data.functions.push(function_data);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n        if (undef.length > 0) {\n            data['undefined'] = undef;\n        }\n\n        members = [];\n        for (name in member) {\n            if (typeof member[name] === 'number') {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n\n    itself.report = function (errors_only) {\n        var data = itself.data(), err, evidence, i, italics, j, key, keys, length,\n            mem = '', name, names, output = [], snippets, the_function, type,\n            warning;\n\n        function detail(h, value) {\n            var comma_needed, singularity;\n            if (Array.isArray(value)) {\n                output.push('<div><i>' + h + '</i> ');\n                value.sort().forEach(function (item) {\n                    if (item !== singularity) {\n                        singularity = item;\n                        output.push((comma_needed ? ', ' : '') + singularity);\n                        comma_needed = true;\n                    }\n                });\n                output.push('</div>');\n            } else if (value) {\n                output.push('<div><i>' + h + '</i> ' + value + '</div>');\n            }\n        }\n\n        if (data.errors || data.unused || data['undefined']) {\n            err = true;\n            output.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    warning = data.errors[i];\n                    if (warning) {\n                        evidence = warning.evidence || '';\n                        output.push('<p>Problem' + (isFinite(warning.line)\n                            ? ' at line ' + String(warning.line) +\n                                ' character ' + String(warning.character)\n                            : '') +\n                            ': ' + warning.reason.entityify() +\n                            '</p><p class=evidence>' +\n                            (evidence && (evidence.length > 80\n                                ? evidence.slice(0, 77) + '...'\n                                : evidence).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data['undefined']) {\n                snippets = [];\n                for (i = 0; i < data['undefined'].length; i += 1) {\n                    snippets[i] = '<code><u>' + data['undefined'][i].name + '</u></code>&nbsp;<i>' +\n                        String(data['undefined'][i].line) + ' </i> <small>' +\n                        data['undefined'][i]['function'] + '</small>';\n                }\n                output.push('<p><i>Undefined variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.unused) {\n                snippets = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    snippets[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        String(data.unused[i].line) + ' </i> <small>' +\n                        data.unused[i]['function'] + '</small>';\n                }\n                output.push('<p><i>Unused variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.json) {\n                output.push('<p>JSON: bad.</p>');\n            }\n            output.push('</div>');\n        }\n\n        if (!errors_only) {\n\n            output.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (xmode === 'style') {\n                output.push('<p>CSS.</p>');\n            } else if (data.json && !err) {\n                output.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                output.push('<div><i>Global</i> ' +\n                    data.globals.sort().join(', ') + '</div>');\n            } else {\n                output.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                the_function = data.functions[i];\n                names = [];\n                if (the_function.params) {\n                    for (j = 0; j < the_function.params.length; j += 1) {\n                        names[j] = the_function.params[j].string;\n                    }\n                }\n                output.push('<br><div class=function><i>' +\n                    String(the_function.line) + '</i> ' +\n                    the_function.name.entityify() +\n                    '(' + names.join(', ') + ')</div>');\n                detail('<big><b>Undefined</b></big>', the_function['undefined']);\n                detail('<big><b>Unused</b></big>', the_function.unused);\n                detail('Closure', the_function.closure);\n                detail('Variable', the_function['var']);\n                detail('Exception', the_function.exception);\n                detail('Outer', the_function.outer);\n                detail('Global', the_function.global);\n                detail('Label', the_function.label);\n            }\n\n            if (data.member) {\n                keys = Object.keys(data.member);\n                if (keys.length) {\n                    keys = keys.sort();\n                    output.push('<br><pre id=properties>/*properties<br>');\n                    mem = '    ';\n                    italics = 0;\n                    j = 0;\n                    if (option.confusion) {\n                        for (i = 0; i < keys.length; i += 1) {\n                            key = keys[i];\n                            if (typeof standard_property_type[key] !== 'string') {\n                                name = ix.test(key)\n                                    ? key\n                                    : '\\'' + key.entityify().replace(nx, sanitize) + '\\'';\n                                if (data.member[key] === 1) {\n                                    name = '<i>' + name + '</i>';\n                                    italics += 1;\n                                    j = 1;\n                                }\n                                if (i < keys.length - 1) {\n                                    name += ', ';\n                                }\n                                if (mem.length + name.length - (italics * 7) > 80) {\n                                    output.push(mem + '<br>');\n                                    mem = '    ';\n                                    italics = j;\n                                }\n                                mem += name;\n                                j = 0;\n                            }\n                        }\n                    } else {\n                        for (i = 0; i < keys.length; i += 1) {\n                            key = keys[i];\n                            type = property_type[key];\n                            if (typeof type !== 'string') {\n                                type = '';\n                            }\n                            if (standard_property_type[key] !== type) {\n                                name = ix.test(key)\n                                    ? key\n                                    : '\\'' + key.entityify().replace(nx, sanitize) + '\\'';\n                                length += name.length + 2;\n                                if (data.member[key] === 1) {\n                                    name = '<i>' + name + '</i>';\n                                    italics += 1;\n                                    j = 1;\n                                }\n                                if (type) {\n                                    name += ': ' + type;\n                                }\n                                if (i < keys.length - 1) {\n                                    name += ', ';\n                                }\n                                if (mem.length + name.length - (italics * 7) > 80) {\n                                    output.push(mem + '<br>');\n                                    mem = '    ';\n                                    italics = j;\n                                }\n                                mem += name;\n                                j = 0;\n                            }\n                        }\n                    }\n                    output.push(mem + '<br>*/</pre>');\n                }\n                output.push('</div>');\n            }\n        }\n        return output.join('');\n    };\n    itself.jslint = itself;\n\n    itself.edition = '2012-01-13';\n\n    return itself;\n}());\n\ndefine(\"thirdparty/jslint/jslint\", function(){});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, JSLINT, PathUtils */\n\n/**\n * Allows JSLint to run on the current document and report results in a UI panel.\n *\n */\ndefine('language/JSLintUtils',['require','exports','module','thirdparty/path-utils/path-utils.min','thirdparty/jslint/jslint','command/Commands','command/CommandManager','document/DocumentManager','preferences/PreferencesManager','utils/PerfUtils','strings','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    // Load dependent non-module scripts\n    require(\"thirdparty/path-utils/path-utils.min\");\n    require(\"thirdparty/jslint/jslint\");\n    \n    // Load dependent modules\n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        Strings                 = require(\"strings\"),\n        EditorManager           = require(\"editor/EditorManager\");\n    \n    /**\n     * @private\n     * @type {PreferenceStorage}\n     */\n    var _prefs = null;\n    \n    /**\n     * @private\n     * @type {boolean}\n     */\n    var _enabled = true;\n    \n    /**\n     * @return {boolean} Enabled state of JSLint.\n     */\n    function getEnabled() {\n        return _enabled;\n    }\n    \n    /**\n     * Run JSLint on the current document. Reports results to the main UI. Displays\n     * a gold star when no errors are found.\n     */\n    function run() {\n        var currentDoc = DocumentManager.getCurrentDocument();\n        \n        var perfTimerDOM,\n            perfTimerLint;\n\n        var ext = currentDoc ? PathUtils.filenameExtension(currentDoc.file.fullPath) : \"\";\n        var $lintResults = $(\"#jslint-results\");\n        var $lintStatus = $(\"#lint-status\");\n        \n        if (getEnabled() && /^(\\.js|\\.htm|\\.html)$/i.test(ext)) {\n            perfTimerLint = PerfUtils.markStart(\"JSLint linting:\\t\" + (!currentDoc || currentDoc.file.fullPath));\n            var text = currentDoc.getText();\n            \n            // If a line contains only whitespace, remove the whitespace\n            // This should be doable with a regexp: text.replace(/\\r[\\x20|\\t]+\\r/g, \"\\r\\r\");,\n            // but that doesn't work.\n            var i, arr = text.split(\"\\n\");\n            for (i = 0; i < arr.length; i++) {\n                if (!arr[i].match(/\\S/)) {\n                    arr[i] = \"\";\n                }\n            }\n            text = arr.join(\"\\n\");\n            \n            var result = JSLINT(text, null);\n\n            PerfUtils.addMeasurement(perfTimerLint);\n            perfTimerDOM = PerfUtils.markStart(\"JSLint DOM:\\t\" + (!currentDoc || currentDoc.file.fullPath));\n            \n            if (!result) {\n                var $errorTable = $(\"<table class='zebra-striped condensed-table' />\")\n                                   .append(\"<tbody>\");\n                var $selectedRow;\n                \n                JSLINT.errors.forEach(function (item, i) {\n                    if (item) {\n                        var makeCell = function (content) {\n                            return $(\"<td/>\").text(content);\n                        };\n                        \n                        // Add row to error table\n                        var $row = $(\"<tr/>\")\n                            .append(makeCell(item.line))\n                            .append(makeCell(item.reason))\n                            .append(makeCell(item.evidence || \"\"))\n                            .appendTo($errorTable);\n                        \n                        $row.click(function () {\n                            if ($selectedRow) {\n                                $selectedRow.removeClass(\"selected\");\n                            }\n                            $row.addClass(\"selected\");\n                            $selectedRow = $row;\n                            \n                            var editor = EditorManager.getCurrentFullEditor();\n                            editor.setCursorPos(item.line - 1, item.character - 1);\n                            EditorManager.focusEditor();\n                        });\n                    }\n                });\n\n                $(\"#jslint-results .table-container\")\n                    .empty()\n                    .append($errorTable);\n                $lintResults.show();\n                $lintStatus.hide();\n            } else {\n                $lintResults.hide();\n                $lintStatus.show();\n            }\n\n            PerfUtils.addMeasurement(perfTimerDOM);\n\n        } else {\n            // JSLint is disabled or does not apply to the current file, hide\n            // both the results and the gold star\n            $lintResults.hide();\n            $lintStatus.hide();\n        }\n        \n        EditorManager.resizeEditor();\n    }\n    \n    /**\n     * @private\n     * Update DocumentManager listeners.\n     */\n    function _updateListeners() {\n        if (_enabled) {\n            // register our event listeners\n            $(DocumentManager)\n                .on(\"currentDocumentChange.jslint\", function () {\n                    run();\n                })\n                .on(\"documentSaved.jslint\", function (event, document) {\n                    if (document === DocumentManager.getCurrentDocument()) {\n                        run();\n                    }\n                });\n        } else {\n            $(DocumentManager).off(\".jslint\");\n        }\n    }\n    \n    function _setEnabled(enabled) {\n        _enabled = enabled;\n        \n        CommandManager.get(Commands.TOGGLE_JSLINT).setChecked(_enabled);\n        _updateListeners();\n        _prefs.setValue(\"enabled\", _enabled);\n    \n        // run immediately\n        run();\n    }\n    \n    /**\n     * Enable or disable JSLint.\n     * @param {boolean} enabled Enabled state.\n     */\n    function setEnabled(enabled) {\n        if (_enabled !== enabled) {\n            _setEnabled(enabled);\n        }\n    }\n    \n    /** Command to toggle enablement */\n    function _handleToggleJSLint() {\n        setEnabled(!getEnabled());\n    }\n    \n    \n    // Register command handlers\n    CommandManager.register(Strings.CMD_JSLINT, Commands.TOGGLE_JSLINT, _handleToggleJSLint);\n    \n    // Init PreferenceStorage\n    _prefs = PreferencesManager.getPreferenceStorage(module.id, { enabled: true });\n    _setEnabled(_prefs.getValue(\"enabled\"));\n    \n    // Define public API\n    exports.run = run;\n    exports.getEnabled = getEnabled;\n    exports.setEnabled = setEnabled;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n/*\n* Displays an auto suggest pop-up list of files to allow the user to quickly navigate to a file and lines\n* within a file.\n* Uses FileIndexManger to supply the file list.\n* \n* TODO (issue 333) - currently jquery smart auto complete is used for the pop-up list. While it mostly works\n* it has several issues, so it should be replace with an alternative. Issues:\n* - only accepts an array of strings. A list of objects is preferred to avoid some workarounds to display \n*   both the path and filename.\n* - the pop-up position logic has flaws that require CSS workarounds\n* - the pop-up properties cannot be modified once the object is constructed\n*/\n\n\ndefine('search/QuickOpen',['require','exports','module','project/FileIndexManager','document/DocumentManager','editor/EditorManager','command/CommandManager','strings','utils/StringUtils','command/Commands','project/ProjectManager'],function (require, exports, module) {\n    \n    \n    var FileIndexManager    = require(\"project/FileIndexManager\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        Commands            = require(\"command/Commands\"),\n        ProjectManager      = require(\"project/ProjectManager\");\n    \n\n    /** @type Array.<QuickOpenPlugin> */\n    var plugins = [];\n\n    /** @type {QuickOpenPlugin} */\n    var currentPlugin = null;\n\n    /** @type Array.<FileInfo>*/\n    var fileList;\n\n    /**\n     * Remembers the current document that was displayed when showDialog() was called\n     * The current document is restored if the user presses escape\n     * @type {string} full path\n     */\n    var origDocPath;\n\n    /**\n     * Remembers the selection in the document origDocPath that was present when showDialog() was called.\n     * Focusing on an item can cause the current and and/or selection to change, so this variable restores it.\n     * The cursor position is restored if the user presses escape.\n     * @type ?{start:{line:number, ch:number}, end:{line:number, ch:number}}\n     */\n    var origSelection;\n\n    var dialogOpen = false;\n\n    /**\n     * Defines API for new QuickOpen plug-ins\n     */\n    function QuickOpenPlugin(name, fileTypes, done, search, match, itemFocus, itemSelect, resultsFormatter) {\n        \n        this.name = name;\n        this.fileTypes = fileTypes;\n        this.done = done;\n        this.search = search;\n        this.match = match;\n        this.itemFocus = itemFocus;\n        this.itemSelect = itemSelect;\n        this.resultsFormatter = resultsFormatter;\n    }\n    \n    /**\n     * Creates and registers a new QuickOpenPlugin\n     *\n     * @param { name: string, \n     *          fileTypes:Array.<string>} plugin,\n     *          done: function(),\n     *          search: function(string):Array.<string>,\n     *          match: function(string):boolean,\n     *          itemFocus: functon(HTMLLIElement),\n     *          itemSelect: functon(HTMLLIElement),\n     *          resultsFormatter: ?Functon(string, string):string }\n     *\n     * @returns {QuickOpenPlugin} plugin\n     *\n     * Parameter Documentation:\n     *\n     * name - plug-in name\n     * filetypes - file types array. Example: [\"js\", \"css\", \"txt\"]. An empty array\n     *      indicates all file types.\n     * done - called when quick open is complete. Plug-in should clear its internal state.\n     * search - takes a query string and returns an array of strings that match the query.\n     * match - takes a query string and returns true if this plug-in wants to provide\n     *      results for this query.\n     * itemFocus - performs an action when a result has focus. \n     *      The focused HTMLLIElement is passed as an argument.\n     * itemSelect - performs an action when a result is chosen.\n     *      The selected HTMLLIElement is passed as an argument.\n     * resultFormatter - takes a query string and an item string and returns \n     *      a <LI> item to insert into the displayed search results. If null, default is provided.\n     */\n    function addQuickOpenPlugin(pluginDef) {\n        plugins.push(new QuickOpenPlugin(\n            pluginDef.name,\n            pluginDef.fileTypes,\n            pluginDef.done,\n            pluginDef.search,\n            pluginDef.match,\n            pluginDef.itemFocus,\n            pluginDef.itemSelect,\n            pluginDef.resultsFormatter\n        ));\n    }\n\n    /**\n    * QuickNavigateDialog class\n    * @constructor\n    */\n    function QuickNavigateDialog() {\n        this.$searchField = undefined; // defined when showDialog() is called\n    }\n\n    /**\n     * Creates a dialog div floating on top of the current code mirror editor\n     */\n    QuickNavigateDialog.prototype._createDialogDiv = function (template) {\n        this.dialog = $(\"<div />\")\n                          .attr(\"class\", \"CodeMirror-dialog\")\n                          .html(\"<div align='right'>\" + template + \"</div>\")\n                          .prependTo($(\"#editor-holder\"));\n    };\n\n    function _filenameFromPath(path, includeExtension) {\n        var end;\n        if (includeExtension) {\n            end = path.length;\n        } else {\n            end = path.lastIndexOf(\".\");\n        }\n        return path.slice(path.lastIndexOf(\"/\") + 1, end);\n    }\n\n    /**\n     * Attempts to extract a line number from the query where the line number\n     * is followed by a colon. Callers should explicitly test result with isNaN()\n     * \n     * @param {string} query string to extract line number from\n     * @returns {number} line number. Returns NaN to indicate no line numbeer was found\n     */\n    function extractLineNumber(query) {\n        // only match : at beginning of query for now\n        // TODO: match any location of : when QuickOpen._handleItemFocus() is modified to\n        // dynamic open files\n        if (query.indexOf(\":\") !== 0) {\n            return NaN;\n        }\n\n        var result = NaN;\n        var regInfo = query.match(/(!?:)(\\d+)/); // colon followed by a digit\n        if (regInfo) {\n            result = regInfo[2] - 1;\n        }\n\n        return result;\n    }\n    \n    /**\n     * Navigates to the appropriate file and file location given the selected item \n     * and closes the dialog.\n     *\n     * Note, if selectedItem is null quick search should inspect $searchField for text\n     * that may have not matched anything in in the list, but may have information\n     * for carrying out an action.\n     */\n    QuickNavigateDialog.prototype._handleItemSelect = function (selectedItem) {\n\n        // This is a work-around to select first item when a selection event occurs\n        // (usually from pressing the enter key) and no item is selected in the list.\n        // This is a work-around since  Smart auto complete doesn't select the first item\n        if (!selectedItem) {\n            selectedItem = $(\".smart_autocomplete_container > li:first-child\").get(0);\n        }\n\n\n        // Delegate to current plugin\n        if (currentPlugin) {\n            currentPlugin.itemSelect(selectedItem);\n        } else {\n\n            // extract line number\n            var cursor,\n                query = this.$searchField.val(),\n                gotoLine = extractLineNumber(query);\n            if (!isNaN(gotoLine)) {\n                cursor = {line: gotoLine, ch: 0};\n            }\n\n            // Extract file path\n            var fullPath;\n            if (selectedItem) {\n                fullPath = decodeURIComponent($(selectedItem).attr(\"data-fullpath\"));\n            }\n\n            // Nagivate to file and line number\n            if (fullPath) {\n                CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath})\n                    .done(function () {\n                        if (!isNaN(gotoLine)) {\n                            EditorManager.getCurrentFullEditor().setCursorPos(cursor);\n                        }\n                    });\n            } else if (!isNaN(gotoLine)) {\n                EditorManager.getCurrentFullEditor().setCursorPos(cursor);\n            }\n        }\n\n\n        this._close();\n        EditorManager.focusEditor();\n    };\n\n    /**\n     * Opens the file specified by selected item if there is no current plug-in, otherwise defers handling\n     * to the currentPlugin\n     */\n    QuickNavigateDialog.prototype._handleItemFocus = function (selectedItem) {\n        if (currentPlugin) {\n            currentPlugin.itemFocus(selectedItem);\n        }\n        // TODO: Disable opening files on focus for now since this causes focus related bugs between \n        // the editor and the search field. \n        // Also, see related code in _handleItemFocus\n        /*\n        else {\n            var fullPath = $(selectedItem).attr(\"data-fullpath\");\n            if (fullPath) {\n                fullPath = decodeURIComponent(fullPath);\n                CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath, focusEditor: false});\n            }\n        }\n        */\n        \n    };\n\n    /**\n     * KeyUp is for cases that handle AFTER a character has been committed to $searchField\n     *\n     */\n    QuickNavigateDialog.prototype._handleKeyUp = function (e) {\n        var query = this.$searchField.val();\n\n        // extract line number\n        var gotoLine = extractLineNumber(query);\n        if (!isNaN(gotoLine)) {\n            var from = {line: gotoLine, ch: 0};\n            var to = {line: gotoLine, ch: 99999};\n            \n            EditorManager.getCurrentFullEditor().setSelection(from, to);\n        }\n\n        // Remove current plugin if the query stops matching\n        if (currentPlugin && !currentPlugin.match(query)) {\n            currentPlugin = null;\n        }\n\n        if ($(\".smart_autocomplete_highlight\").length === 0) {\n            this._handleItemFocus($(\".smart_autocomplete_container > li:first-child\"));\n        }\n    };\n\n    /**\n     * Close the dialog when the ENTER (13) or ESC (27) key is pressed\n     *\n     * Note, when keydown is handled $searchField does not yet have the character added\n     * for the current event e. \n     */\n    QuickNavigateDialog.prototype._handleKeyDown = function (e) {\n\n        // TODO: pass event through KeyMap.translateKeyboardEvent() to get friendly names\n        // instead of using these constants here. Note, translateKeyboardEvent() doesn't yet\n        // make friendly names for the escape and enter key.\n        var ESCKey = 27, EnterKey = 13;\n\n        // clear the query on ESC key and restore document and cursor position\n        if (e.keyCode === EnterKey || e.keyCode === ESCKey) {\n            e.stopPropagation();\n            e.preventDefault();\n\n            if (e.keyCode === ESCKey) {\n\n                // restore previously viewed doc if user navigated away from it\n                if (origDocPath) {\n                    CommandManager.execute(Commands.FILE_OPEN, {fullPath: origDocPath})\n                        .done(function () {\n                            if (origSelection) {\n                                EditorManager.getCurrentFullEditor().setSelection(origSelection.start, origSelection.end);\n                            }\n                        });\n                }\n\n                this._close();\n            }\n\n            if (e.keyCode === EnterKey) {\n                this._handleItemSelect($(\".smart_autocomplete_highlight\").get(0));\n            }\n            \n        }\n    };\n\n\n    /**\n    * Closes the search dialog and notifies all quick open plugins that\n    * searching is done. \n    */\n    QuickNavigateDialog.prototype._close = function () {\n\n        if (!dialogOpen) {\n            return;\n        }\n        dialogOpen = false;\n\n        var i;\n        for (i = 0; i < plugins.length; i++) {\n            var plugin = plugins[i];\n            plugin.done();\n        }\n\n        // Ty TODO: disabled for now while file switching is disabled in _handleItemFocus\n        //JSLintUtils.setEnabled(true);\n\n        EditorManager.focusEditor();\n\n        this.dialog.remove();\n        $(\".smart_autocomplete_container\").remove();\n\n        $(window.document).off(\"mousedown\", this.handleDocumentClick);\n    };\n    \n    function filterFileList(query) {\n        var filteredList = $.map(fileList, function (fileInfo) {\n            // match query against filename only (not the full path)\n            var path = fileInfo.fullPath;\n            var filename = _filenameFromPath(path, true);\n            if (filename.toLowerCase().indexOf(query.toLowerCase()) !== -1) {\n                return path;\n            } else {\n                return null;\n            }\n        }).sort(function (a, b) {\n            a = a.toLowerCase();\n            b = b.toLowerCase();\n            //first,  sort by filename without extension\n            var filenameA = _filenameFromPath(a, false);\n            var filenameB = _filenameFromPath(b, false);\n            if (filenameA < filenameB) {\n                return -1;\n            } else if (filenameA > filenameB) {\n                return 1;\n            } else {\n                // filename is the same, compare including extension\n                filenameA = _filenameFromPath(a, true);\n                filenameB = _filenameFromPath(b, true);\n                if (filenameA < filenameB) {\n                    return -1;\n                } else if (filenameA > filenameB) {\n                    return 1;\n                } else {\n                    return 0;\n                }\n            }\n        });\n\n        return filteredList;\n    }\n\n    function _handleFilter(query) {\n        var curDoc = DocumentManager.getCurrentDocument();\n        if (curDoc) {\n            var filename = _filenameFromPath(curDoc.file.fullPath, true);\n            var extension = filename.slice(filename.lastIndexOf(\".\") + 1, filename.length);\n\n            var i;\n            for (i = 0; i < plugins.length; i++) {\n                var plugin = plugins[i];\n                var extensionMatch = plugin.fileTypes.indexOf(extension) !== -1 || plugin.fileTypes.length === 0;\n                if (extensionMatch &&  plugin.match && plugin.match(query)) {\n                    currentPlugin = plugin;\n                    return plugin.search(query);\n                }\n            }\n        }\n\n        currentPlugin = null;\n        return filterFileList(query);\n    }\n\n    function defaultResultsFormatter(item, query) {\n        query = query.slice(query.indexOf(\"@\") + 1, query.length);\n\n        // Escape both query and item so the replace works properly below\n        query = StringUtils.htmlEscape(query);\n        item = StringUtils.htmlEscape(item);\n\n        var displayName;\n        if (query.length > 0) {\n            // make the users query bold within the item's text\n            displayName = item.replace(\n                new RegExp(StringUtils.regexEscape(query), \"gi\"),\n                \"<strong>$&</strong>\"\n            );\n        } else {\n            displayName = item;\n        }\n\n        return \"<li>\" + displayName + \"</li>\";\n    }\n\n\n\n    function _handleResultsFormatter(item) {\n        var query = $(\"input#quickOpenSearch\").val();\n\n        if (currentPlugin) {\n            // Plugins use their own formatter or the default formatter\n            var formatter = currentPlugin.resultsFormatter || defaultResultsFormatter;\n            return formatter(item, query);\n        } else {\n            // Use the filename formatter\n            query = StringUtils.htmlEscape(query);\n            var filename = StringUtils.htmlEscape(_filenameFromPath(item, true));\n            var rPath = StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(item));\n\n            var displayName;\n            if (query.length > 0) {\n                // make the users query bold within the item's text\n                displayName = filename.replace(\n                    new RegExp(StringUtils.regexEscape(query), \"gi\"),\n                    \"<strong>$&</strong>\"\n                );\n            } else {\n                displayName = filename;\n            }\n\n            return \"<li data-fullpath='\" + encodeURIComponent(item) + \"'>\" + displayName +\n                \"<br /><span class='quick-open-path'>\" + rPath + \"</span></li>\";\n        }\n    }\n\n\n    function setSearchFieldValue(prefix, initialString) {\n        prefix = prefix || \"\";\n        initialString = initialString || \"\";\n        initialString = prefix + initialString;\n\n        \n        var $field = $(\"input#quickOpenSearch\");\n        if ($field) {\n            $field.val(initialString);\n            $field.get(0).setSelectionRange(prefix.length, initialString.length);\n        }\n    }\n    \n    /**\n     * Close the dialog when the user clicks outside of it. Note, auto smart complete has a \"lostFocus\" event that is\n     * supposed to capture this event, but it also gets triggered on keyUp which doesn't work for quick find.\n     */\n    QuickNavigateDialog.prototype.handleDocumentClick = function (e) {\n        if ($(this.dialog).find(e.target).length === 0 && $(\".smart_autocomplete_container\").find(e.target).length === 0) {\n            this._close();\n        }\n    };\n\n    /**\n    * Shows the search dialog and initializes the auto suggestion list with filenames from the current project\n    */\n    QuickNavigateDialog.prototype.showDialog = function (prefix, initialString) {\n        var that = this;\n\n        if (dialogOpen) {\n            return;\n        }\n        dialogOpen = true;\n\n        this.handleDocumentClick = this.handleDocumentClick.bind(this);\n        $(window.document).on(\"mousedown\", this.handleDocumentClick);\n\n\n        // Ty TODO: disabled for now while file switching is disabled in _handleItemFocus\n        // To improve performance during list selection disable JSLint until a document is chosen or dialog is closed\n        //JSLintUtils.setEnabled(false);\n\n        var curDoc = DocumentManager.getCurrentDocument();\n        origDocPath = curDoc ? curDoc.file.fullPath : null;\n        if (curDoc) {\n            origSelection = EditorManager.getCurrentFullEditor().getSelection();\n        } else {\n            origSelection = null;\n        }\n\n        // Get the file list and initialize the smart auto completes\n        FileIndexManager.getFileInfoList(\"all\")\n            .done(function (files) {\n                fileList = files;\n                var dialogHTML = Strings.CMD_QUICK_OPEN + \": <input type='text' autocomplete='off' id='quickOpenSearch' style='width: 30em'>\";\n                that._createDialogDiv(dialogHTML);\n                that.$searchField = $(\"input#quickOpenSearch\");\n\n\n                that.$searchField.smartAutoComplete({\n                    source: files,\n                    maxResults: 20,\n                    minCharLimit: 0,\n                    autocompleteFocused: true,\n                    forceSelect: false,\n                    typeAhead: false,   // won't work right now because smart auto complete \n                                        // using internal raw results instead of filtered results for matching\n                    filter: _handleFilter,\n                    resultFormatter: _handleResultsFormatter\n                });\n        \n                that.$searchField.bind({\n                    itemSelect: function (e, selectedItem) { that._handleItemSelect(selectedItem); },\n                    itemFocus: function (e, selectedItem) { that._handleItemFocus(selectedItem); },\n                    keydown: function (e) { that._handleKeyDown(e); },\n                    keyup: function (e, query) { that._handleKeyUp(e); }\n                    // Note: lostFocus event DOESN'T work because auto smart complete catches the key up from shift-command-o and immediately\n                    // triggers lostFocus\n                });\n        \n                setSearchFieldValue(prefix, initialString);\n            });\n    };\n\n    function getCurrentEditorSelectedText() {\n        var currentEditor = EditorManager.getFocusedEditor();\n        return (currentEditor && currentEditor.getSelectedText()) || \"\";\n    }\n\n    function doSearch(prefix, initialString) {\n        if (dialogOpen) {\n            setSearchFieldValue(prefix, initialString);\n        } else {\n            var dialog = new QuickNavigateDialog();\n            dialog.showDialog(prefix, initialString);\n        }\n    }\n\n    function doFileSearch() {\n        doSearch(\"\", getCurrentEditorSelectedText());\n    }\n\n    function doGotoLine() {\n        // TODO: Brackets doesn't support disabled menu items right now, when it does goto line and\n        // goto definition should be disabled when there is not a current document\n        if (DocumentManager.getCurrentDocument()) {\n            doSearch(\":\", \"\");\n        }\n    }\n\n\n    // TODO: should provide a way for QuickOpenJSSymbol to create this function as a plug-in\n    function doDefinitionSearch() {\n        if (DocumentManager.getCurrentDocument()) {\n            doSearch(\"@\", getCurrentEditorSelectedText());\n        }\n    }\n\n\n\n    // TODO: allow QuickOpenJS to register it's own commands and key bindings\n    CommandManager.register(Strings.CMD_QUICK_OPEN,         Commands.NAVIGATE_QUICK_OPEN,       doFileSearch);\n    CommandManager.register(Strings.CMD_GOTO_DEFINITION,    Commands.NAVIGATE_GOTO_DEFINITION,  doDefinitionSearch);\n    CommandManager.register(Strings.CMD_GOTO_LINE,          Commands.NAVIGATE_GOTO_LINE,        doGotoLine);\n\n    exports.addQuickOpenPlugin = addQuickOpenPlugin;\n});\n\n/**\n * @license RequireJS text 1.0.8 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n/*jslint regexp: true, plusplus: true, sloppy: true */\n/*global require: false, XMLHttpRequest: false, ActiveXObject: false,\n  define: false, window: false, process: false, Packages: false,\n  java: false, location: false */\n\n(function () {\n    var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        hasLocation = typeof location !== 'undefined' && location.href,\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\n        defaultHostName = hasLocation && location.hostname,\n        defaultPort = hasLocation && (location.port || undefined),\n        buildMap = [];\n\n    define('text',[],function () {\n        var text, fs;\n\n        text = {\n            version: '1.0.8',\n\n            strip: function (content) {\n                //Strips <?xml ...?> declarations so that external SVG and XML\n                //documents can be added to a document without worry. Also, if the string\n                //is an HTML document, only the part inside the body tag is returned.\n                if (content) {\n                    content = content.replace(xmlRegExp, \"\");\n                    var matches = content.match(bodyRegExp);\n                    if (matches) {\n                        content = matches[1];\n                    }\n                } else {\n                    content = \"\";\n                }\n                return content;\n            },\n\n            jsEscape: function (content) {\n                return content.replace(/(['\\\\])/g, '\\\\$1')\n                    .replace(/[\\f]/g, \"\\\\f\")\n                    .replace(/[\\b]/g, \"\\\\b\")\n                    .replace(/[\\n]/g, \"\\\\n\")\n                    .replace(/[\\t]/g, \"\\\\t\")\n                    .replace(/[\\r]/g, \"\\\\r\");\n            },\n\n            createXhr: function () {\n                //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n                var xhr, i, progId;\n                if (typeof XMLHttpRequest !== \"undefined\") {\n                    return new XMLHttpRequest();\n                } else if (typeof ActiveXObject !== \"undefined\") {\n                    for (i = 0; i < 3; i++) {\n                        progId = progIds[i];\n                        try {\n                            xhr = new ActiveXObject(progId);\n                        } catch (e) {}\n\n                        if (xhr) {\n                            progIds = [progId];  // so faster next time\n                            break;\n                        }\n                    }\n                }\n\n                return xhr;\n            },\n\n            /**\n             * Parses a resource name into its component parts. Resource names\n             * look like: module/name.ext!strip, where the !strip part is\n             * optional.\n             * @param {String} name the resource name\n             * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\n             * where strip is a boolean.\n             */\n            parseName: function (name) {\n                var strip = false, index = name.indexOf(\".\"),\n                    modName = name.substring(0, index),\n                    ext = name.substring(index + 1, name.length);\n\n                index = ext.indexOf(\"!\");\n                if (index !== -1) {\n                    //Pull off the strip arg.\n                    strip = ext.substring(index + 1, ext.length);\n                    strip = strip === \"strip\";\n                    ext = ext.substring(0, index);\n                }\n\n                return {\n                    moduleName: modName,\n                    ext: ext,\n                    strip: strip\n                };\n            },\n\n            xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\n\n            /**\n             * Is an URL on another domain. Only works for browser use, returns\n             * false in non-browser environments. Only used to know if an\n             * optimized .js version of a text resource should be loaded\n             * instead.\n             * @param {String} url\n             * @returns Boolean\n             */\n            useXhr: function (url, protocol, hostname, port) {\n                var match = text.xdRegExp.exec(url),\n                    uProtocol, uHostName, uPort;\n                if (!match) {\n                    return true;\n                }\n                uProtocol = match[2];\n                uHostName = match[3];\n\n                uHostName = uHostName.split(':');\n                uPort = uHostName[1];\n                uHostName = uHostName[0];\n\n                return (!uProtocol || uProtocol === protocol) &&\n                       (!uHostName || uHostName === hostname) &&\n                       ((!uPort && !uHostName) || uPort === port);\n            },\n\n            finishLoad: function (name, strip, content, onLoad, config) {\n                content = strip ? text.strip(content) : content;\n                if (config.isBuild) {\n                    buildMap[name] = content;\n                }\n                onLoad(content);\n            },\n\n            load: function (name, req, onLoad, config) {\n                //Name has format: some.module.filext!strip\n                //The strip part is optional.\n                //if strip is present, then that means only get the string contents\n                //inside a body tag in an HTML string. For XML/SVG content it means\n                //removing the <?xml ...?> declarations so the content can be inserted\n                //into the current doc without problems.\n\n                // Do not bother with the work if a build and text will\n                // not be inlined.\n                if (config.isBuild && !config.inlineText) {\n                    onLoad();\n                    return;\n                }\n\n                var parsed = text.parseName(name),\n                    nonStripName = parsed.moduleName + '.' + parsed.ext,\n                    url = req.toUrl(nonStripName),\n                    useXhr = (config && config.text && config.text.useXhr) ||\n                             text.useXhr;\n\n                //Load the text. Use XHR if possible and in a browser.\n                if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\n                    text.get(url, function (content) {\n                        text.finishLoad(name, parsed.strip, content, onLoad, config);\n                    });\n                } else {\n                    //Need to fetch the resource across domains. Assume\n                    //the resource has been optimized into a JS module. Fetch\n                    //by the module name + extension, but do not include the\n                    //!strip part to avoid file system issues.\n                    req([nonStripName], function (content) {\n                        text.finishLoad(parsed.moduleName + '.' + parsed.ext,\n                                        parsed.strip, content, onLoad, config);\n                    });\n                }\n            },\n\n            write: function (pluginName, moduleName, write, config) {\n                if (buildMap.hasOwnProperty(moduleName)) {\n                    var content = text.jsEscape(buildMap[moduleName]);\n                    write.asModule(pluginName + \"!\" + moduleName,\n                                   \"define(function () { return '\" +\n                                       content +\n                                   \"';});\\n\");\n                }\n            },\n\n            writeFile: function (pluginName, moduleName, req, write, config) {\n                var parsed = text.parseName(moduleName),\n                    nonStripName = parsed.moduleName + '.' + parsed.ext,\n                    //Use a '.js' file name so that it indicates it is a\n                    //script that can be loaded across domains.\n                    fileName = req.toUrl(parsed.moduleName + '.' +\n                                         parsed.ext) + '.js';\n\n                //Leverage own load() method to load plugin value, but only\n                //write out values that do not have the strip argument,\n                //to avoid any potential issues with ! in file names.\n                text.load(nonStripName, req, function (value) {\n                    //Use own write() method to construct full module value.\n                    //But need to create shell that translates writeFile's\n                    //write() to the right interface.\n                    var textWrite = function (contents) {\n                        return write(fileName, contents);\n                    };\n                    textWrite.asModule = function (moduleName, contents) {\n                        return write.asModule(moduleName, fileName, contents);\n                    };\n\n                    text.write(pluginName, nonStripName, textWrite, config);\n                }, config);\n            }\n        };\n\n        if (text.createXhr()) {\n            text.get = function (url, callback) {\n                var xhr = text.createXhr();\n                xhr.open('GET', url, true);\n                xhr.onreadystatechange = function (evt) {\n                    //Do not explicitly handle errors, those should be\n                    //visible via console output in the browser.\n                    if (xhr.readyState === 4) {\n                        callback(xhr.responseText);\n                    }\n                };\n                xhr.send(null);\n            };\n        } else if (typeof process !== \"undefined\" &&\n                 process.versions &&\n                 !!process.versions.node) {\n            //Using special require.nodeRequire, something added by r.js.\n            fs = require.nodeRequire('fs');\n\n            text.get = function (url, callback) {\n                var file = fs.readFileSync(url, 'utf8');\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\n                if (file.indexOf('\\uFEFF') === 0) {\n                    file = file.substring(1);\n                }\n                callback(file);\n            };\n        } else if (typeof Packages !== 'undefined') {\n            //Why Java, why is this so awkward?\n            text.get = function (url, callback) {\n                var encoding = \"utf-8\",\n                    file = new java.io.File(url),\n                    lineSeparator = java.lang.System.getProperty(\"line.separator\"),\n                    input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\n                    stringBuffer, line,\n                    content = '';\n                try {\n                    stringBuffer = new java.lang.StringBuffer();\n                    line = input.readLine();\n\n                    // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\n                    // http://www.unicode.org/faq/utf_bom.html\n\n                    // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\n                    // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\n                    if (line && line.length() && line.charAt(0) === 0xfeff) {\n                        // Eat the BOM, since we've already found the encoding on this file,\n                        // and we plan to concatenating this buffer with others; the BOM should\n                        // only appear at the top of a file.\n                        line = line.substring(1);\n                    }\n\n                    stringBuffer.append(line);\n\n                    while ((line = input.readLine()) !== null) {\n                        stringBuffer.append(lineSeparator);\n                        stringBuffer.append(line);\n                    }\n                    //Make sure we return a JavaScript string and not a Java string.\n                    content = String(stringBuffer.toString()); //String\n                } finally {\n                    input.close();\n                }\n                callback(content);\n            };\n        }\n\n        return text;\n    });\n}());\n\ndefine('text!htmlContent/main-view.html',[],function () { return '<!-- \\n  Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\\n   \\n  Permission is hereby granted, free of charge, to any person obtaining a\\n  copy of this software and associated documentation files (the \"Software\"), \\n  to deal in the Software without restriction, including without limitation \\n  the rights to use, copy, modify, merge, publish, distribute, sublicense, \\n  and/or sell copies of the Software, and to permit persons to whom the \\n  Software is furnished to do so, subject to the following conditions:\\n   \\n  The above copyright notice and this permission notice shall be included in\\n  all copies or substantial portions of the Software.\\n   \\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \\n  DEALINGS IN THE SOFTWARE.\\n-->\\n\\n\\n<!--\\n    This is the HTML for the body tag of index.html. It is loaded dynamically by the \\n    htmlContentLoad module and localized using a combination of mustache.js and i18n.js.\\n\\n    LOCALIZATION NOTE:\\n    All display text for this file must use templating so the text can be localized.\\n    \\n    English text goes in src/nls/root/strings.js. All other translations go in the strings.js file for\\n    the specific local in the nls folder. If a translation is missing for a specific key English\\n    is used as a fallback\\n\\n    Strings should be referenced using the double brackets syntax.\\n    Example: {{keyname}}. Note, all strings are HTML escaped unless the form \\n    {{&keyname}} is used.\\n\\n-->\\n\\n<!-- Main UI -->\\n    <div class=\"main-view\">\\n        <div id=\"sidebar-resizer\"></div>\\n        <div id=\"sidebar\" class=\"sidebar quiet-scrollbars\">\\n            <!-- Left-hand \\'Project panel\\' -->\\n            <div id=\"projects\" class=\"panel\">\\n                <div id=\"project-header\"></div>\\n                <div id=\"file-section\">\\n                    <div id=\"open-files-container\">\\n                        <!-- This will contain a dynamically generated <ul> at runtime -->\\n                        <ul>\\n                        </ul>\\n                    </div>\\n                \\n                    <div id=\"project-files-header\" class=\"project-file-header-area\">\\n                        <span id=\"project-title\" class=\"title\"></span>\\n                    </div>\\n                    <div id=\"project-files-container\">\\n                    <!-- This will contain a dynamically generated <ul> hierarchy at runtime -->\\n                    </div>\\n                </div>\\n            </div>\\n        </div>\\n        \\n        <!-- Right-hand content: toolbar, editor, bottom panels -->\\n        <div class=\"content\">\\n            <!-- Toolbar containing menus, filename, and icons -->\\n            <div id=\"main-toolbar\" class=\"toolbar\">\\n                <!-- Menu bar -->\\n                <ul class=\"nav\" data-dropdown=\"dropdown\">\\n                </ul>\\n                \\n                <!-- Toolbar -->\\n                <div class=\"buttons\">\\n                    <span id=\"update-notification\" title=\"{{UPDATE_NOTIFICATION_TOOLTIP}}\"></span>\\n\\n                    <span class=\"experimental-label\">{{EXPERIMENTAL_BUILD}}</span>\\n                    \\n                    <a href=\"#\" id=\"toolbar-go-live\"></a> <!-- tooltip for this is set in JS -->\\n                    \\n                    <span id=\"gold-star\" title=\"No JSLint errors - good job!\">\\n                        &#9733;\\n                    </span>\\n                </div>\\n                \\n                <!-- Filename label -->\\n                <div class=\"title-wrapper\">\\n                    <span class=\"title\"></span>&nbsp;<span class=\\'dirty-dot\\' style=\"visibility:hidden;\">•</span>\\n                </div>\\n            </div>\\n            \\n            <div id=\"editor-holder\">\\n                <div id=\"not-editor\">\\n                    <div id=\"not-editor-content\">[&nbsp;&nbsp;]</div>\\n                </div>\\n            </div>\\n            \\n            <div id=\"jslint-results\" class=\"bottom-panel\">\\n                <div class=\"toolbar simple-toolbar-layout\">\\n                    <div class=\"title\">{{JSLINT_ERRORS}}</div>\\n                </div>\\n                <div class=\"table-container\"></div>\\n            </div>\\n            <div id=\"search-results\" class=\"bottom-panel\">\\n                <div class=\"toolbar simple-toolbar-layout\">\\n                    <div class=\"title\">{{SEARCH_RESULTS}}</div>\\n                    <div class=\"title\" id=\"search-result-summary\"></div>\\n                    <a href=\"#\" class=\"close\">&times;</a>\\n                </div>\\n                <div class=\"table-container\"></div>\\n            </div>\\n        </div>\\n    </div>\\n\\n    <!-- Modal Windows -->\\n    <div class=\"error-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <a href=\"#\" class=\"close\">&times;</a>\\n            <h1 class=\"dialog-title\">Error</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{OK}}</a>\\n        </div>\\n    </div>\\n    <div class=\"save-close-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <a href=\"#\" class=\"close\">&times;</a>\\n            <h1 class=\"dialog-title\">{{SAVE_CHANGES}}</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"dontsave\">{{DONT_SAVE}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{SAVE}}</a>\\n            <a href=\"#\" class=\"dialog-button btn\" data-button-id=\"cancel\">{{CANCEL}}</a>\\n        </div>\\n    </div>\\n    <div class=\"ext-changed-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">Title goes here</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"dontsave\">{{RELOAD_FROM_DISK}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"cancel\">{{KEEP_CHANGES_IN_EDITOR}}</a>\\n        </div>\\n    </div>\\n    <div class=\"ext-deleted-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">Title goes here</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"dontsave\">{{CLOSE_DONT_SAVE}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"cancel\">{{KEEP_CHANGES_IN_EDITOR}}</a>\\n        </div>\\n    </div>\\n    <div class=\"live-development-error-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">Title goes here</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <p class=\"dialog-message\">Message goes here</p>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"cancel\">{{CANCEL}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{RELAUNCH_CHROME}}</a>\\n        </div>\\n    </div>\\n    <div class=\"about-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">{{ABOUT}}</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <img class=\"about-icon\" src=\"styles/images/brackets_icon.svg\">\\n            <div class=\"about-text\">\\n                <h2>{{BRACKETS}}</h2>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE1}} <span id=\"about-build-number\"><!-- populated programmatically --></span></p>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE2}}</p>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE3}}<span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span>{{ABOUT_TEXT_LINE4}}</p>\\n                <p class=\"dialog-message\">{{ABOUT_TEXT_LINE5}}<span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span></p>\\n            </div>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"ok\">{{CLOSE}}</a>\\n        </div>\\n    </div>\\n    <div class=\"update-dialog template modal hide\">\\n        <div class=\"modal-header\">\\n            <h1 class=\"dialog-title\">{{UPDATE_AVAILABLE_TITLE}}</h1>\\n        </div>\\n        <div class=\"modal-body\">\\n            <img class=\"update-icon\" src=\"styles/images/update_large_icon.svg\">\\n            <div class=\"update-text\">\\n                <p class=\"dialog-message\">{{UPDATE_MESSAGE}}</p>\\n                <div class=\"update-info\">\\n                </div>\\n            </div>\\n        </div>\\n        <div class=\"modal-footer\">\\n            <a href=\"#\" class=\"dialog-button btn left\" data-button-id=\"cancel\">{{CANCEL}}</a>\\n            <a href=\"#\" class=\"dialog-button btn primary\" data-button-id=\"download\">{{GET_IT_NOW}}</a>\\n        </div>\\n    </div>\\n    <div id=\"context-menu-bar\">\\n        <ul data-dropdown=\"dropdown\"></ul>\\n    </div>\\n    <div id=\"codehint-menu-bar\">\\n        <ul data-dropdown=\"dropdown\"></ul>\\n    </div>';});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, CodeMirror, brackets, window */\n\n/**\n * ExtensionLoader searches the filesystem for extensions, then creates a new context for each one and loads it\n */\n\ndefine('utils/ExtensionLoader',['require','exports','module','file/NativeFileSystem','file/FileUtils','utils/Async'],function (require, exports, module) {\n    \n\n    var NativeFileSystem    = require(\"file/NativeFileSystem\").NativeFileSystem,\n        FileUtils           = require(\"file/FileUtils\"),\n        Async               = require(\"utils/Async\"),\n        contexts            = {};\n    /**\n     * Returns the require.js require context used to load an extension\n     *\n     * @param {!string} name, used to identify the extension\n     * @return {!Object} A require.js require object used to load the extension, or undefined if \n     * there is no require object ith that name\n     */\n    function getRequireContextForExtension(name) {\n        return contexts[name];\n    }\n\n    \n    /**\n     * Loads the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!string} baseUrl, URL path relative to index.html, where the main JS file can be found\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when the extension is loaded.\n     */\n    function loadExtension(name, config, entryPoint) {\n        var result = new $.Deferred(),\n            extensionRequire = brackets.libRequire.config({\n                context: name,\n                baseUrl: config.baseUrl,\n                /* FIXME (issue #1087): can we pass this from the global require context instead of hardcoding twice? */\n                paths: {\n                    \"text\" : \"../../../thirdparty/text\",\n                    \"i18n\" : \"../../../thirdparty/i18n\"\n                },\n                locale: window.localStorage.getItem(\"locale\") || brackets.app.language\n            });\n        contexts[name] = extensionRequire;\n\n        console.log(\"[Extension] starting to load \" + config.baseUrl);\n        \n        extensionRequire([entryPoint], function () {\n            console.log(\"[Extension] finished loading \" + config.baseUrl);\n            result.resolve();\n        });\n        \n        return result.promise();\n    }\n\n    /**\n     * Runs unit tests for the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} name, used to identify the extension\n     * @param {!string} baseUrl, URL path relative to index.html, where the main JS file can be found\n     * @param {!string} entryPoint, name of the main js file to load\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function testExtension(name, config, entryPoint) {\n        var result = new $.Deferred(),\n            extensionPath = FileUtils.getNativeBracketsDirectoryPath();\n        \n        // Assumes the caller's window.location context is /test/SpecRunner.html\n        extensionPath = extensionPath.replace(\"brackets/test\", \"brackets/src\"); // convert from \"test\" to \"src\"\n        extensionPath += \"/\" + config.baseUrl + \"/\" + entryPoint + \".js\";\n\n        var fileExists = false, statComplete = false;\n        brackets.fs.stat(extensionPath, function (err, stat) {\n            statComplete = true;\n            if (err === brackets.fs.NO_ERROR && stat.isFile()) {\n                // unit test file exists\n                var extensionRequire = brackets.libRequire.config({\n                    context: name,\n                    baseUrl: \"../src/\" + config.baseUrl,\n                    paths: config.paths\n                });\n    \n                console.log(\"[Extension] loading unit test \" + config.baseUrl);\n                extensionRequire([entryPoint], function () {\n                    console.log(\"[Extension] loaded unit tests \" + config.baseUrl);\n                    result.resolve();\n                });\n            } else {\n                result.reject();\n            }\n        });\n        \n        return result.promise();\n    }\n    \n    /**\n     * @private\n     * Loads a file entryPoint from each extension folder within the baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!string} baseUrl, URL path relative to index.html that maps to the same place as directory\n     * @param {!string} entryPoint Module name to load (without .js suffix)\n     * @param {function} processExtension \n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function _loadAll(directory, config, entryPoint, processExtension) {\n        var result = new $.Deferred();\n        \n        NativeFileSystem.requestNativeFileSystem(directory,\n            function (rootEntry) {\n                rootEntry.createReader().readEntries(\n                    function (entries) {\n                        var i,\n                            extensions = [];\n                        \n                        for (i = 0; i < entries.length; i++) {\n                            if (entries[i].isDirectory) {\n                                // FUTURE (JRB): read package.json instead of just using the entrypoint \"main\".\n                                // Also, load sub-extensions defined in package.json.\n                                extensions.push(entries[i].name);\n                            }\n                        }\n\n                        if (extensions.length === 0) {\n                            result.resolve();\n                            return;\n                        }\n                        \n                        Async.doInParallel(extensions, function (item) {\n                            var extConfig = {\n                                baseUrl: config.baseUrl + \"/\" + item,\n                                paths: config.paths\n                            };\n                            return processExtension(item, extConfig, entryPoint);\n                        }).always(function () {\n                            // Always resolve the promise even when the extension entry point is missing\n                            result.resolve();\n                        });\n                    },\n                    function (error) {\n                        console.log(\"[Extension] Error -- could not read native directory: \" + directory);\n                    }\n                );\n            },\n            function (error) {\n                console.log(\"[Extension] Error -- could not open native directory: \" + directory);\n            });\n        \n        return result.promise();\n    }\n    \n    /**\n     * Loads the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!string} baseUrl, URL path relative to index.html that maps to the same place as directory\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function loadAllExtensionsInNativeDirectory(directory, baseUrl) {\n        return _loadAll(directory, {baseUrl: baseUrl}, \"main\", loadExtension);\n    }\n    \n    /**\n     * Runs unit test for the extension that lives at baseUrl into its own Require.js context\n     *\n     * @param {!string} directory, an absolute native path that contains a directory of extensions.\n     *                  each subdirectory is interpreted as an independent extension\n     * @param {!string} baseUrl, URL path relative to index.html that maps to the same place as directory\n     * @return {!$.Promise} A promise object that is resolved when all extensions complete loading.\n     */\n    function testAllExtensionsInNativeDirectory(directory, baseUrl) {\n        var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(),\n            config = {\n                baseUrl: baseUrl\n            };\n        \n        config.paths = {\n            \"perf\": bracketsPath + \"/perf\",\n            \"spec\": bracketsPath + \"/spec\"\n        };\n        \n        return _loadAll(directory, config, \"unittests\", testExtension);\n    }\n    \n    exports.getRequireContextForExtension = getRequireContextForExtension;\n    exports.loadExtension = loadExtension;\n    exports.testExtension = testExtension;\n    exports.loadAllExtensionsInNativeDirectory = loadAllExtensionsInNativeDirectory;\n    exports.testAllExtensionsInNativeDirectory = testAllExtensionsInNativeDirectory;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, document, window, brackets  */\n\ndefine('project/SidebarView',['require','exports','module','project/ProjectManager','project/WorkingSetView','command/CommandManager','command/Commands','strings','preferences/PreferencesManager','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    var ProjectManager          = require(\"project/ProjectManager\"),\n        WorkingSetView          = require(\"project/WorkingSetView\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Commands                = require(\"command/Commands\"),\n        Strings                 = require(\"strings\"),\n        PreferencesManager      = require(\"preferences/PreferencesManager\"),\n        EditorManager           = require(\"editor/EditorManager\");\n\n    var isSidebarClosed         = false;\n\n    var PREFERENCES_CLIENT_ID = \"com.adobe.brackets.SidebarView\",\n        defaultPrefs = { sidebarWidth: 200, sidebarClosed: false };\n\n    // These vars are initialized by the htmlContentLoadComplete handler\n    // below since they refer to DOM elements\n    var $sidebar,\n        $sidebarMenuText,\n        $sidebarResizer,\n        $openFilesContainer,\n        $projectTitle,\n        $projectFilesContainer;\n    \n    /**\n     * @private\n     * Update project title when the project root changes\n     */\n    function _updateProjectTitle() {\n        $projectTitle.html(ProjectManager.getProjectRoot().name);\n        $projectTitle.attr(\"title\", ProjectManager.getProjectRoot().fullPath);\n    }\n    \n    /**\n     * @private\n     * Sets sidebar width and resizes editor. Does not change internal sidebar open/closed state.\n     * @param {number} width Optional width in pixels. If null or undefined, the default width is used.\n     * @param {!boolean} updateMenu Updates \"View\" menu label to indicate current sidebar state.\n     * @param {!boolean} displayTriangle Display selection marker triangle in the active view.\n     */\n    function _setWidth(width, updateMenu, displayTriangle) {\n        // if we specify a width with the handler call, use that. Otherwise use\n        // the greater of the current width or 200 (200 is the minimum width we'd snap back to)\n        \n        var prefs                   = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),\n            sidebarWidth            = Math.max(prefs.getValue(\"sidebarWidth\"), 10);\n        \n        width = width || Math.max($sidebar.width(), sidebarWidth);\n        \n        if (typeof displayTriangle === \"boolean\") {\n            var display = (displayTriangle) ? \"block\" : \"none\";\n            $sidebar.find(\".sidebar-selection-triangle\").css(\"display\", display);\n        }\n        \n        if (isSidebarClosed) {\n            $sidebarResizer.css(\"left\", 0);\n        } else {\n            $sidebar.width(width);\n            $sidebarResizer.css(\"left\", width - 1);\n            \n            // the following three lines help resize things when the sidebar shows\n            // but ultimately these should go into ProjectManager.js with a \"notify\" \n            // event that we can just call from anywhere instead of hard-coding it.\n            // waiting on a ProjectManager refactor to add that. \n            $sidebar.find(\".sidebar-selection\").width(width);\n            \n            if (width > 10) {\n                prefs.setValue(\"sidebarWidth\", width);\n            }\n        }\n        \n        if (updateMenu) {\n            var text = (isSidebarClosed) ? Strings.CMD_SHOW_SIDEBAR : Strings.CMD_HIDE_SIDEBAR;\n            CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(text);\n        }\n        EditorManager.resizeEditor();\n    }\n    \n    /**\n     * Toggle sidebar visibility.\n     */\n    function toggleSidebar(width) {\n        if (isSidebarClosed) {\n            $sidebar.show();\n        } else {\n            $sidebar.hide();\n        }\n        \n        isSidebarClosed = !isSidebarClosed;\n        \n        var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs);\n        prefs.setValue(\"sidebarClosed\", isSidebarClosed);\n        _setWidth(width, true, !isSidebarClosed);\n    }\n    \n    /**\n     * @private\n     * Install sidebar resize handling.\n     */\n    function _initSidebarResizer() {\n        var $mainView               = $(\".main-view\"),\n            $body                   = $(document.body),\n            prefs                   = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),\n            sidebarWidth            = prefs.getValue(\"sidebarWidth\"),\n            startingSidebarPosition = sidebarWidth,\n            animationRequest        = null,\n            isMouseDown             = false;\n        \n        $sidebarResizer.css(\"left\", sidebarWidth - 1);\n        \n        if (prefs.getValue(\"sidebarClosed\")) {\n            toggleSidebar(sidebarWidth);\n        } else {\n            _setWidth(sidebarWidth, true, true);\n        }\n        \n        $sidebarResizer.on(\"dblclick\", function () {\n            if ($sidebar.width() < 10) {\n                //mousedown is fired first. Sidebar is already toggeled open to at least 10px.\n                _setWidth(null, true, true);\n                $projectFilesContainer.triggerHandler(\"scroll\");\n                $openFilesContainer.triggerHandler(\"scroll\");\n            } else {\n                toggleSidebar(sidebarWidth);\n            }\n        });\n        $sidebarResizer.on(\"mousedown.sidebar\", function (e) {\n            var startX = e.clientX,\n                newWidth = Math.max(e.clientX, 0),\n                doResize = true;\n            \n            isMouseDown = true;\n\n            // take away the shadows (for performance reasons during sidebarmovement)\n            $sidebar.find(\".scroller-shadow\").css(\"display\", \"none\");\n            \n            $body.toggleClass(\"resizing\");\n            \n            // check to see if we're currently in hidden mode\n            if (isSidebarClosed) {\n                toggleSidebar(1);\n            }\n                        \n            \n            animationRequest = window.webkitRequestAnimationFrame(function doRedraw() {\n                // only run this if the mouse is down so we don't constantly loop even \n                // after we're done resizing.\n                if (!isMouseDown) {\n                    return;\n                }\n                    \n                // if we've gone below 10 pixels on a mouse move, and the\n                // sidebar is shrinking, hide the sidebar automatically an\n                // unbind the mouse event. \n                if ((startX > 10) && (newWidth < 10)) {\n                    toggleSidebar(startingSidebarPosition);\n                    $mainView.off(\"mousemove.sidebar\");\n                        \n                    // turn off the mouseup event so that it doesn't fire twice and retoggle the \n                    // resizing class\n                    $mainView.off(\"mouseup.sidebar\");\n                    $body.toggleClass(\"resizing\");\n                    doResize = false;\n                    startX = 0;\n                        \n                    // force isMouseDown so that we don't keep calling requestAnimationFrame\n                    // this keeps the sidebar from stuttering\n                    isMouseDown = false;\n                        \n                }\n                \n                if (doResize) {\n                    // for right now, displayTriangle is always going to be false for _setWidth\n                    // because we want to hide it when we move, and _setWidth only gets called\n                    // on mousemove now.\n                    _setWidth(newWidth, false, false);\n                }\n                \n                animationRequest = window.webkitRequestAnimationFrame(doRedraw);\n            });\n            \n            $mainView.on(\"mousemove.sidebar\", function (e) {\n                newWidth = Math.max(e.clientX, 0);\n                \n                e.preventDefault();\n            });\n                \n            $mainView.one(\"mouseup.sidebar\", function (e) {\n                isMouseDown = false;\n                \n                // replace shadows and triangle\n                $sidebar.find(\".sidebar-selection-triangle\").css(\"display\", \"block\");\n                $sidebar.find(\".scroller-shadow\").css(\"display\", \"block\");\n                \n                $projectFilesContainer.triggerHandler(\"scroll\");\n                $openFilesContainer.triggerHandler(\"scroll\");\n                $mainView.off(\"mousemove.sidebar\");\n                $body.toggleClass(\"resizing\");\n                startingSidebarPosition = $sidebar.width();\n            });\n            \n            e.preventDefault();\n        });\n    }\n\n    // Initialize items dependent on HTML DOM\n    $(brackets).on(\"htmlContentLoadComplete\", function () {\n        $sidebar                = $(\"#sidebar\");\n        $sidebarMenuText        = $(\"#menu-view-hide-sidebar span\");\n        $sidebarResizer         = $(\"#sidebar-resizer\");\n        $openFilesContainer     = $(\"#open-files-container\");\n        $projectTitle           = $(\"#project-title\");\n        $projectFilesContainer  = $(\"#project-files-container\");\n\n        // init\n        WorkingSetView.create($openFilesContainer);\n        _initSidebarResizer();\n    });\n    \n    $(ProjectManager).on(\"projectOpen\", _updateProjectTitle);\n    CommandManager.register(Strings.CMD_HIDE_SIDEBAR,       Commands.VIEW_HIDE_SIDEBAR,     toggleSidebar);\n    \n    // Define public API\n    exports.toggleSidebar = toggleSidebar;\n});\ndefine('text!buildNumber.json',[],function () { return '{\\n    \"buildNumber\": 100\\n}\\n';});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, PathUtils, window */\n\n/**\n *  Utilities functions for displaying update notifications\n *\n */\ndefine('utils/UpdateNotification',['require','exports','module','widgets/Dialogs','utils/NativeApp','preferences/PreferencesManager','strings','utils/StringUtils','text!buildNumber.json'],function (require, exports, module) {\n    \n    \n    var Dialogs             = require(\"widgets/Dialogs\"),\n        NativeApp           = require(\"utils/NativeApp\"),\n        PreferencesManager  = require(\"preferences/PreferencesManager\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        BuildNumberJSON     = require(\"text!buildNumber.json\");\n    \n    // Current build number.\n    var _buildNumber = JSON.parse(BuildNumberJSON).buildNumber;\n    \n    // PreferenceStorage\n    var _prefs = PreferencesManager.getPreferenceStorage(module.id, {lastNotifiedBuildNumber: 0});\n        \n    // This is the last version we notified the user about. If checkForUpdate()\n    // is called with \"false\", only show the update notification dialog if there\n    // is an update newer than this one. This value is saved in preferences.\n    var _lastNotifiedBuildNumber = _prefs.getValue(\"lastNotifiedBuildNumber\");\n    \n    // Last time the versionInfoURL was fetched\n    var _lastInfoURLFetchTime = _prefs.getValue(\"lastInfoURLFetchTime\");\n\n    // URL to load version info from. By default this is loaded no more than once a day. If \n    // you force an update check it is always loaded.\n    \n    // URL to fetch the version information.\n    var _versionInfoURL = \"http://dev.brackets.io/updates/stable/\"; // {locale}.json will be appended\n    \n    // Information on all posted builds of Brackets. This is an Array, where each element is \n    // an Object with the following fields:\n    //\n    //  {Number} buildNumber Number of the build\n    //  {String} versionString String representation of the build number (ie \"Sprint 14\")\n    //  {String} dateString Date of the build\n    //  {String} releaseNotesURL URL of the release notes for this build\n    //  {String} downloadURL URL to download this build\n    //  {Array} newFeatures Array of new features in this build. Each entry has two fields:\n    //      {String} name Name of the feature\n    //      {String} description Description of the feature\n    //\n    // This array must be reverse sorted by buildNumber (newest build info first)\n    \n    /**\n     * @private\n     * Flag that indicates if we've added a click handler to the update notification icon.\n     */\n    var _addedClickHandler = false;\n    \n    /**\n     * Get a data structure that has information for all builds of Brackets.\n     *\n     * If force is true, the information is always fetched from _versionInfoURL.\n     * If force is false, we try to use cached information. If more than\n     * 24 hours have passed since the last fetch, or if cached data can't be found, \n     * the data is fetched again.\n     *\n     * If new data is fetched and dontCache is false, the data is saved in preferences\n     * for quick fetching later.\n     */\n    function _getUpdateInformation(force, dontCache) {\n        var result = new $.Deferred();\n        var fetchData = false;\n        var data;\n        \n        // If force is true, always fetch\n        if (force) {\n            fetchData = true;\n        }\n        \n        // If we don't have data saved in prefs, fetch\n        data = _prefs.getValue(\"updateInfo\");\n        if (!data) {\n            fetchData = true;\n        }\n        \n        // If more than 24 hours have passed since our last fetch, fetch again\n        if ((new Date()).getTime() > _lastInfoURLFetchTime + (1000 * 60 * 60 * 24)) {\n            fetchData = true;\n        }\n        \n        if (fetchData) {\n            $.ajax(_versionInfoURL, {\n                dataType: \"text\",\n                complete: function (jqXHR, status) {\n                    if (status === \"success\") {\n                        try {\n                            data = JSON.parse(jqXHR.responseText);\n                            if (!dontCache) {\n                                _lastInfoURLFetchTime = (new Date()).getTime();\n                                _prefs.setValue(\"lastInfoURLFetchTime\", _lastInfoURLFetchTime);\n                                _prefs.setValue(\"updateInfo\", data);\n                            }\n                            result.resolve(data);\n                        } catch (e) {\n                            console.log(\"Error parsing version information\");\n                            console.log(e);\n                            result.reject();\n                        }\n                    }\n                },\n                error: function (jqXHR, status, error) {\n                    // When loading data for unit tests, the error handler is \n                    // called but the responseText is valid. Try to use it here,\n                    // but *don't* save the results in prefs.\n                    \n                    if (!jqXHR.responseText) {\n                        // Text is NULL or empty string, reject().\n                        result.reject();\n                        return;\n                    }\n                    \n                    try {\n                        data = JSON.parse(jqXHR.responseText);\n                        result.resolve(data);\n                    } catch (e) {\n                        result.reject();\n                    }\n                }\n            });\n        } else {\n            result.resolve(data);\n        }\n        \n        return result.promise();\n    }\n    \n    /**\n     * Return a new array of version information that is newer than \"buildNumber\".\n     * Returns null if there is no new version information.\n     */\n    function _stripOldVersionInfo(versionInfo, buildNumber) {\n        // Do a simple linear search. Since we are going in reverse-chronological order, we\n        // should get through the search quickly.\n        var lastIndex = 0;\n        var len = versionInfo.length;\n        \n        while (lastIndex < len) {\n            if (versionInfo[lastIndex].buildNumber <= buildNumber) {\n                break;\n            }\n            lastIndex++;\n        }\n        \n        if (lastIndex > 0) {\n            return versionInfo.slice(0, lastIndex);\n        }\n        \n        // No new version info\n        return null;\n    }\n    \n    /**\n     * Show a dialog that shows the update \n     */\n    function _showUpdateNotificationDialog(updates) {\n        Dialogs.showModalDialog(Dialogs.DIALOG_ID_UPDATE)\n            .done(function (id) {\n                if (id === Dialogs.DIALOG_BTN_DOWNLOAD) {\n                    // The first entry in the updates array has the latest download link\n                    NativeApp.openURLInDefaultBrowser(updates[0].downloadURL);\n                }\n            });\n        \n        // Populate the update data\n        var $dlg = $(\".update-dialog.instance\");\n        var $updateList = $dlg.find(\".update-info\");\n        \n        // TODO: Use a template instead of hand-rolling HTML code\n        updates.forEach(function (item, index) {\n            var $features = $(\"<ul>\");\n            \n            item.newFeatures.forEach(function (feature, index) {\n                $features.append(\n                    \"<li><b>\" +\n                        StringUtils.htmlEscape(feature.name) +\n                        \"</b> - \" +\n                        StringUtils.htmlEscape(feature.description) +\n                        \"</li>\"\n                );\n            });\n            \n            var $item = $(\"<div>\")\n                .append(\"<h3>\" +\n                        StringUtils.htmlEscape(item.versionString) +\n                        \" - \" +\n                        StringUtils.htmlEscape(item.dateString) +\n                        \" (<a href='#' data-url='\" + item.releaseNotesURL + \"'>\" +\n                        Strings.RELEASE_NOTES +\n                        \"</a>)</h3>\")\n                .append($features)\n                .appendTo($updateList);\n        });\n        \n        $dlg.on(\"click\", \"a\", function (e) {\n            var url = $(e.target).attr(\"data-url\");\n            \n            if (url) {\n                // Make sure the URL has a domain that we know about\n                if (/(brackets\\.io|github\\.com|adobe\\.com)$/i.test(PathUtils.parseUrl(url).hostname)) {\n                    NativeApp.openURLInDefaultBrowser(url);\n                }\n            }\n        });\n    }\n    \n    /**\n     * Check for updates. If \"force\" is true, update notification dialogs are always displayed \n     * (if an update is available). If \"force\" is false, the update notification is only \n     * displayed for newly available updates.\n     * \n     * If an update is available, show the \"update available\" notification icon in the title bar.\n     *\n     * @param {boolean} force If true, always show the notification dialog.\n     * @param {Object} _testValues This should only be used for testing purposes. See comments for details.\n     * @return {$.Promise} jQuery Promise object that is resolved or rejected after the update check is complete.\n     */\n    function checkForUpdate(force, _testValues) {\n        // The second param, if non-null, is an Object containing value overrides. Values\n        // in the object temporarily override the local values. This should *only* be used for testing.\n        // If any overrides are set, permanent changes are not made (including showing\n        // the update notification icon and saving prefs).\n        var oldValues;\n        var usingOverrides = false; // true if any of the values are overridden.\n        var result = new $.Deferred();\n        \n        if (_testValues) {\n            oldValues = {};\n            \n            if (_testValues.hasOwnProperty(\"_buildNumber\")) {\n                oldValues._buildNumber = _buildNumber;\n                _buildNumber = _testValues._buildNumber;\n                usingOverrides = true;\n            }\n\n            if (_testValues.hasOwnProperty(\"_lastNotifiedBuildNumber\")) {\n                oldValues._lastNotifiedBuildNumber = _lastNotifiedBuildNumber;\n                _lastNotifiedBuildNumber = _testValues._lastNotifiedBuildNumber;\n                usingOverrides = true;\n            }\n\n            if (_testValues.hasOwnProperty(\"_versionInfoURL\")) {\n                oldValues._versionInfoURL = _versionInfoURL;\n                _versionInfoURL = _testValues._versionInfoURL;\n                usingOverrides = true;\n            }\n        }\n        \n        _getUpdateInformation(force || usingOverrides, usingOverrides)\n            .done(function (versionInfo) {\n                // Get all available updates\n                var allUpdates = _stripOldVersionInfo(versionInfo, _buildNumber);\n                \n                if (allUpdates) {\n                    // Always show the \"update available\" icon if any updates are available\n                    var $updateNotification = $(\"#update-notification\");\n                    \n                    $updateNotification.css(\"display\", \"inline-block\");\n                    if (!_addedClickHandler) {\n                        _addedClickHandler = true;\n                        $updateNotification.on(\"click\", function () {\n                            checkForUpdate(true);\n                        });\n                    }\n                \n                    // Only show the update dialog if force = true, or if the user hasn't been \n                    // alerted of this update\n                    if (force || allUpdates[0].buildNumber >  _lastNotifiedBuildNumber) {\n                        _showUpdateNotificationDialog(allUpdates);\n                        \n                        // Update prefs with the last notified build number\n                        _lastNotifiedBuildNumber = allUpdates[0].buildNumber;\n                        // Don't save prefs is we have overridden values\n                        if (!usingOverrides) {\n                            _prefs.setValue(\"lastNotifiedBuildNumber\", _lastNotifiedBuildNumber);\n                        }\n                    }\n                } else if (force) {\n                    // No updates are available. If force == true, let the user know.\n                    Dialogs.showModalDialog(\n                        Dialogs.DIALOG_ID_ERROR,\n                        Strings.NO_UPDATE_TITLE,\n                        Strings.NO_UPDATE_MESSAGE\n                    );\n                }\n        \n                if (oldValues) {\n                    if (oldValues.hasOwnProperty(\"_buildNumber\")) {\n                        _buildNumber = oldValues._buildNumber;\n                    }\n                    if (oldValues.hasOwnProperty(\"_lastNotifiedBuildNumber\")) {\n                        _lastNotifiedBuildNumber = oldValues._lastNotifiedBuildNumber;\n                    }\n                    if (oldValues.hasOwnProperty(\"_versionInfoURL\")) {\n                        _versionInfoURL = oldValues._versionInfoURL;\n                    }\n                }\n                result.resolve();\n            })\n            .fail(function () {\n                result.reject();\n            });\n        \n        return result.promise();\n    }\n    \n    // Append locale to version info URL\n    _versionInfoURL += (window.localStorage.getItem(\"locale\") || brackets.app.language) + \".json\";\n    \n    // Define public API\n    exports.checkForUpdate = checkForUpdate;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, window */\n\ndefine('utils/UrlParams',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * Convert between URL querystring and name/value pairs. Decodes and encodes URL parameters.\n     */\n    function UrlParams() {\n        this._store = {};\n    }\n    \n    /**\n     * Parse the window location by default. Optionally specify a URL to parse.\n     * @param {string} url\n     */\n    UrlParams.prototype.parse = function (url) {\n        if (url) {\n            url = url.substring(indexOf(\"?\") + 1);\n        } else {\n            url = window.document.location.search.substring(1);\n        }\n        \n        var urlParams = url.split(\"&\"),\n            p,\n            self = this;\n        \n        urlParams.forEach(function (param) {\n            p = param.split(\"=\");\n            self._store[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);\n        });\n    };\n    \n    /**\n     * Store a name/value string pair\n     * @param {!string} name\n     * @param {!string} value\n     */\n    UrlParams.prototype.put = function (name, value) {\n        this._store[name] = value;\n    };\n    \n    /**\n     * Retreive a value by name\n     * @param {!string} name\n     */\n    UrlParams.prototype.get = function (name) {\n        return this._store[name];\n    };\n    \n    /**\n     * Encode name/value pairs as URI components.\n     */\n    UrlParams.prototype.toString = function () {\n        var strs = [],\n            self = this;\n        \n        Object.keys(self._store).forEach(function (key) {\n            strs.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(self._store[key]));\n        });\n        \n        return strs.join(\"&\");\n    };\n\n    // Define public API\n    exports.UrlParams = UrlParams;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n\n/**\n * Text-editing commands that apply to whichever Editor is currently focused\n */\ndefine('editor/EditorCommandHandlers',['require','exports','module','command/Commands','strings','command/CommandManager','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    // Load dependent modules\n    var Commands           = require(\"command/Commands\"),\n        Strings            = require(\"strings\"),\n        CommandManager     = require(\"command/CommandManager\"),\n        EditorManager      = require(\"editor/EditorManager\");\n    \n    \n    /**\n     * List of constants\n     */\n    var DIRECTION_UP    = -1;\n    var DIRECTION_DOWN  = +1;\n    \n    /**\n     * Add or remove line-comment tokens to all the lines in the selected range, preserving selection\n     * and cursor position. Applies to currently focused Editor.\n     * \n     * If all non-whitespace lines are already commented out, then we uncomment; otherwise we comment\n     * out. Commenting out adds \"//\" to at column 0 of every line. Uncommenting removes the first \"//\"\n     * on each line (if any - empty lines might not have one).\n     */\n    function lineCommentSlashSlash(editor) {\n        \n        var doc = editor.document;\n        var sel = editor.getSelection();\n        var startLine = sel.start.line;\n        var endLine = sel.end.line;\n        \n        // Is a range of text selected? (vs just an insertion pt)\n        var hasSelection = (startLine !== endLine) || (sel.start.ch !== sel.end.ch);\n        \n        // In full-line selection, cursor pos is start of next line - but don't want to modify that line\n        if (sel.end.ch === 0 && hasSelection) {\n            endLine--;\n        }\n        \n        // Decide if we're commenting vs. un-commenting\n        // Are there any non-blank lines that aren't commented out? (We ignore blank lines because\n        // some editors like Sublime don't comment them out)\n        var containsUncommented = false;\n        var i;\n        var line;\n        for (i = startLine; i <= endLine; i++) {\n            line = doc.getLine(i);\n            // A line is commented out if it starts with 0-N whitespace chars, then \"//\"\n            if (!line.match(/^\\s*\\/\\//) && line.match(/\\S/)) {\n                containsUncommented = true;\n                break;\n            }\n        }\n        \n        // Make the edit\n        doc.batchOperation(function () {\n            \n            if (containsUncommented) {\n                // Comment out - prepend \"//\" to each line\n                for (i = startLine; i <= endLine; i++) {\n                    doc.replaceRange(\"//\", {line: i, ch: 0});\n                }\n                \n                // Make sure selection includes \"//\" that was added at start of range\n                if (sel.start.ch === 0 && hasSelection) {\n                    // use *current* selection end, which has been updated for our text insertions\n                    editor.setSelection({line: startLine, ch: 0}, editor.getSelection().end);\n                }\n                \n            } else {\n                // Uncomment - remove first \"//\" on each line (if any)\n                for (i = startLine; i <= endLine; i++) {\n                    line = doc.getLine(i);\n                    var commentI = line.indexOf(\"//\");\n                    if (commentI !== -1) {\n                        doc.replaceRange(\"\", {line: i, ch: commentI}, {line: i, ch: commentI + 2});\n                    }\n                }\n            }\n        });\n        \n    }\n\n    /**\n     * Invokes a language-specific line-comment/uncomment handler\n     * @param {?Editor} editor If unspecified, applies to the currently focused editor\n     */\n    function lineComment(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        var mode = editor.getModeForSelection();\n        \n        // Currently we only support languages with \"//\" commenting\n        if (mode === \"javascript\" || mode === \"less\") {\n            lineCommentSlashSlash(editor);\n        }\n    }\n    \n    \n    /**\n     * Duplicates the selected text, or current line if no selection. The cursor/selection is left\n     * on the second copy.\n     */\n    function duplicateText(editor) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n\n        var sel = editor.getSelection(),\n            hasSelection = (sel.start.line !== sel.end.line) || (sel.start.ch !== sel.end.ch),\n            delimiter = \"\";\n\n        if (!hasSelection) {\n            sel.start.ch = 0;\n            sel.end = {line: sel.start.line + 1, ch: 0};\n            if (sel.end.line === editor.lineCount()) {\n                delimiter = \"\\n\";\n            }\n        }\n\n        // Make the edit\n        var doc = editor.document;\n\n        var selectedText = doc.getRange(sel.start, sel.end) + delimiter;\n        doc.replaceRange(selectedText, sel.start);\n    }\n    \n    /**\n     * Moves the selected text, or current line if no selection. The cursor/selection \n     * moves with the line/lines.\n     * @param {Editor} editor - target editor\n     * @param {Number} direction - direction of the move (-1,+1) => (Up,Down)\n     */\n    function moveLine(editor, direction) {\n        editor = editor || EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        var doc = editor.document,\n            sel = editor.getSelection(),\n            originalSel = editor.getSelection(),\n            hasSelection = (sel.start.line !== sel.end.line) || (sel.start.ch !== sel.end.ch);\n        \n        sel.start.ch = 0;\n        // The end of the selection becomes the start of the next line, if it isn't already\n        if (!hasSelection || sel.end.ch !== 0) {\n            sel.end = {line: sel.end.line + 1, ch: 0};\n        }\n        \n        // Make the move\n        switch (direction) {\n        case DIRECTION_UP:\n            if (sel.start.line !== 0) {\n                doc.batchOperation(function () {\n                    var prevText = doc.getRange({ line: sel.start.line - 1, ch: 0 }, sel.start);\n                    \n                    if (sel.end.line === editor.lineCount()) {\n                        prevText = \"\\n\" + prevText.substring(0, prevText.length - 1);\n                    }\n                    \n                    doc.replaceRange(\"\", { line: sel.start.line - 1, ch: 0 }, sel.start);\n                    doc.replaceRange(prevText, { line: sel.end.line - 1, ch: 0 });\n                    \n                    // Make sure CodeMirror hasn't expanded the selection to include\n                    // the line we inserted below.\n                    originalSel.start.line--;\n                    originalSel.end.line--;\n                    editor.setSelection(originalSel.start, originalSel.end);\n                });\n            }\n            break;\n        case DIRECTION_DOWN:\n            if (sel.end.line < editor.lineCount()) {\n                doc.batchOperation(function () {\n                    var nextText = doc.getRange(sel.end, { line: sel.end.line + 1, ch: 0 });\n                    \n                    var deletionStart = sel.end;\n                    if (sel.end.line === editor.lineCount() - 1) {\n                        nextText += \"\\n\";\n                        deletionStart = { line: sel.end.line - 1, ch: doc.getLine(sel.end.line - 1).length };\n                    }\n    \n                    doc.replaceRange(\"\", deletionStart, { line: sel.end.line + 1, ch: 0 });\n                    doc.replaceRange(nextText, { line: sel.start.line, ch: 0 });\n                });\n            }\n            break;\n        }\n    }\n    \n    /**\n     * Moves the selected text, or current line if no selection, one line up. The cursor/selection \n     * moves with the line/lines.\n     */\n    function moveLineUp(editor) {\n        moveLine(editor, DIRECTION_UP);\n    }\n    \n    /**\n     * Moves the selected text, or current line if no selection, one line down. The cursor/selection \n     * moves with the line/lines.\n     */\n    function moveLineDown(editor) {\n        moveLine(editor, DIRECTION_DOWN);\n    }\n\n    /**\n     * Indent a line of text if no selection. Otherwise, indent all lines in selection.\n     */\n    function indentText() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        editor._codeMirror.execCommand(\"indentMore\");\n    }\n    \n    /**\n     * Unindent a line of text if no selection. Otherwise, unindent all lines in selection.\n     */\n    function unidentText() {\n        var editor = EditorManager.getFocusedEditor();\n        if (!editor) {\n            return;\n        }\n        \n        editor._codeMirror.execCommand(\"indentLess\");\n    }\n        \n    // Register commands\n    CommandManager.register(Strings.CMD_INDENT,         Commands.EDIT_INDENT,       indentText);\n    CommandManager.register(Strings.CMD_UNINDENT,       Commands.EDIT_UNINDENT,     unidentText);\n    CommandManager.register(Strings.CMD_COMMENT,        Commands.EDIT_LINE_COMMENT, lineComment);\n    CommandManager.register(Strings.CMD_DUPLICATE,      Commands.EDIT_DUPLICATE,    duplicateText);\n    CommandManager.register(Strings.CMD_LINE_UP,        Commands.EDIT_LINE_UP,      moveLineUp);\n    CommandManager.register(Strings.CMD_LINE_DOWN,      Commands.EDIT_LINE_DOWN,    moveLineDown);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, brackets, window */\n\ndefine('debug/DebugCommandHandlers',['require','exports','module','command/Commands','command/CommandManager','editor/Editor','strings','utils/PerfUtils','utils/NativeApp','file/NativeFileSystem','file/FileUtils','utils/UpdateNotification'],function (require, exports, module) {\n    \n    \n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Editor                  = require(\"editor/Editor\").Editor,\n        Strings                 = require(\"strings\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        NativeApp               = require(\"utils/NativeApp\"),\n        NativeFileSystem        = require(\"file/NativeFileSystem\").NativeFileSystem,\n        FileUtils               = require(\"file/FileUtils\"),\n        UpdateNotification      = require(\"utils/UpdateNotification\");\n    \n    function handleShowDeveloperTools(commandData) {\n        brackets.app.showDeveloperTools();\n    }\n    \n    function _handleUseTabChars() {\n        var useTabs = !Editor.getUseTabChar();\n        Editor.setUseTabChar(useTabs);\n        CommandManager.get(Commands.TOGGLE_USE_TAB_CHARS).setChecked(useTabs);\n    }\n    \n    \n    // Implements the 'Run Tests' menu to bring up the Jasmine unit test window\n    var _testWindow = null;\n    function _handleRunUnitTests() {\n        if (_testWindow) {\n            try {\n                _testWindow.location.reload(true);\n            } catch (e) {\n                _testWindow = null;  // the window was probably closed\n            }\n        }\n\n        if (!_testWindow) {\n            _testWindow = window.open(\"../test/SpecRunner.html\", \"brackets-test\", \"width=\" + $(window).width() + \",height=\" + $(window).height());\n            _testWindow.location.reload(true); // if it was opened before, we need to reload because it will be cached\n        }\n    }\n    \n    function _handleShowPerfData() {\n        var $perfHeader = $(\"<div class='modal-header' />\")\n            .append(\"<a href='#' class='close'>&times;</a>\")\n            .append(\"<h1 class='dialog-title'>Performance Data</h1>\")\n            .append(\"<div align=right>Raw data (copy paste out): <textarea rows=1 style='width:30px; height:8px; overflow: hidden; resize: none' id='brackets-perf-raw-data'>\" + PerfUtils.getDelimitedPerfData() + \"</textarea></div>\");\n        \n        var $perfBody = $(\"<div class='modal-body' style='padding: 0; max-height: 500px; overflow: auto;' />\");\n\n        var $data = $(\"<table class='zebra-striped condensed-table'>\")\n            .append(\"<thead><th>Operation</th><th>Time (ms)</th></thead>\")\n            .append(\"<tbody />\")\n            .appendTo($perfBody);\n        \n        var makeCell = function (content) {\n            return $(\"<td/>\").text(content);\n        };\n        \n        var getValue = function (entry) {\n            // entry is either an Array or a number\n            if (Array.isArray(entry)) {\n                // For Array of values, return: minimum/average/maximum/last\n                var i, e, avg, sum = 0, min = Number.MAX_VALUE, max = 0;\n                \n                for (i = 0; i < entry.length; i++) {\n                    e = entry[i];\n                    min = Math.min(min, e);\n                    sum += e;\n                    max = Math.max(max, e);\n                }\n                avg = Math.round(sum / entry.length);\n                return String(min) + \"/\" + String(avg) + \"/\" + String(max) + \"/\" + String(e);\n            } else {\n                return entry;\n            }\n        };\n            \n        var testName;\n        var perfData = PerfUtils.getData();\n        for (testName in perfData) {\n            if (perfData.hasOwnProperty(testName)) {\n                // Add row to error table\n                $(\"<tr/>\")\n                    .append(makeCell(testName))\n                    .append(makeCell(getValue(perfData[testName])))\n                    .appendTo($data);\n            }\n        }\n                                                     \n        $(\"<div class='modal hide' />\")\n            .append($perfHeader)\n            .append($perfBody)\n            .appendTo(window.document.body)\n            .modal({\n                backdrop: \"static\",\n                show: true\n            });\n\n        // Select the raw perf data field on click since select all doesn't \n        // work outside of the editor\n        $(\"#brackets-perf-raw-data\").click(function () {\n            $(this).focus().select();\n        });\n    }\n    \n    function _handleNewBracketsWindow() {\n        window.open(window.location.href);\n    }\n\n    function _handleSwitchLanguage() {\n        var stringsPath = FileUtils.getNativeBracketsDirectoryPath() + \"/nls\";\n        NativeFileSystem.requestNativeFileSystem(stringsPath, function (dirEntry) {\n            dirEntry.createReader().readEntries(function (entries) {\n\n                var $activeLanguage,\n                    $submit,\n                    locale;\n                \n                function setLanguage(event) {\n                    if ($activeLanguage) {\n                        $activeLanguage.css(\"font-weight\", \"normal\");\n                    }\n                    $activeLanguage = $(event.currentTarget);\n                    locale = $activeLanguage.data(\"locale\");\n                    \n                    $activeLanguage.css(\"font-weight\", \"bold\");\n                    $submit.attr(\"disabled\", false);\n                }\n    \n                var $modal = $(\"<div class='modal hide' />\");\n    \n                var $header = $(\"<div class='modal-header' />\")\n                    .append(\"<a href='#' class='close'>&times;</a>\")\n                    .append(\"<h1 class='dialog-title'>\" + Strings.LANGUAGE_TITLE + \"</h1>\")\n                    .appendTo($modal);\n                  \n                var $body = $(\"<div class='modal-body' style='max-height: 500px; overflow: auto;' />\")\n                    .appendTo($modal);\n\n                var $p = $(\"<p class='dialog-message'>\")\n                    .text(Strings.LANGUAGE_MESSAGE)\n                    .appendTo($body);\n\n                var $ul = $(\"<ul>\")\n                    .on(\"click\", \"li\", setLanguage)\n                    .appendTo($p);\n                \n                var $footer = $(\"<div class='modal-footer' />\")\n                    .appendTo($modal);\n                \n                var $cancel = $(\"<button class='dialog-button btn left'>\")\n                    .on(\"click\", function () {\n                        $modal.modal('hide');\n                    })\n                    .text(Strings.LANGUAGE_CANCEL)\n                    .appendTo($footer);\n                \n                $submit = $(\"<button class='dialog-button btn primary'>\")\n                    .text(Strings.LANGUAGE_SUBMIT)\n                    .on(\"click\", function () {\n                        if (!$activeLanguage) {\n                            return;\n                        }\n                        if (locale) {\n                            window.localStorage.setItem(\"locale\", locale);\n                        } else {\n                            window.localStorage.removeItem(\"locale\");\n                        }\n                        \n                        CommandManager.execute(Commands.DEBUG_REFRESH_WINDOW);\n                    })\n                    .attr(\"disabled\", \"disabled\")\n                    .appendTo($footer);\n                \n                $modal\n                    .appendTo(window.document.body)\n                    .modal({\n                        backdrop: \"static\",\n                        show: true\n                    })\n                    .on(\"hidden\", function () {\n                        $(this).remove();\n                    });\n\n                // add system default\n                var $li = $(\"<li>\")\n                    .text(\"system default\")\n                    .data(\"locale\", null)\n                    .appendTo($ul);\n                \n                // add english\n                $li = $(\"<li>\")\n                    .text(\"en\")\n                    .data(\"locale\", \"en\")\n                    .appendTo($ul);\n                \n                // inspect all children of dirEntry\n                entries.forEach(function (entry) {\n                    if (entry.isDirectory && entry.name.match(/^[a-z]{2}(-[A-Z]{2})?$/)) {\n                        var language = entry.name;\n                        var $li = $(\"<li>\")\n                            .text(entry.name)\n                            .data(\"locale\", language)\n                            .appendTo($ul);\n                    }\n                });\n            });\n        });\n    }\n    \n    function _handleShowExtensionsFolder() {\n        brackets.app.showExtensionsFolder(\n            FileUtils.convertToNativePath(window.location.href),\n            function (err) {\n                // Ignore errors\n            }\n        );\n    }\n    \n    function _handleCheckForUpdates() {\n        UpdateNotification.checkForUpdate(true);\n    }\n    \n    /* Register all the command handlers */\n    \n    // Show Developer Tools (optionally enabled)\n    CommandManager.register(Strings.CMD_SHOW_DEV_TOOLS,      Commands.DEBUG_SHOW_DEVELOPER_TOOLS,   handleShowDeveloperTools)\n        .setEnabled(!!brackets.app.showDeveloperTools);\n    CommandManager.register(Strings.CMD_NEW_BRACKETS_WINDOW, Commands.DEBUG_NEW_BRACKETS_WINDOW,    _handleNewBracketsWindow);\n    CommandManager.register(Strings.CMD_SHOW_EXTENSIONS_FOLDER, Commands.DEBUG_SHOW_EXT_FOLDER,     _handleShowExtensionsFolder);\n    CommandManager.register(Strings.CMD_RUN_UNIT_TESTS,      Commands.DEBUG_RUN_UNIT_TESTS,         _handleRunUnitTests);\n    CommandManager.register(Strings.CMD_SHOW_PERF_DATA,      Commands.DEBUG_SHOW_PERF_DATA,         _handleShowPerfData);\n    CommandManager.register(Strings.CMD_SWITCH_LANGUAGE,     Commands.DEBUG_SWITCH_LANGUAGE,        _handleSwitchLanguage);\n    \n    CommandManager.register(Strings.CMD_USE_TAB_CHARS,       Commands.TOGGLE_USE_TAB_CHARS,         _handleUseTabChars)\n        .setChecked(Editor.getUseTabChar());\n    \n    CommandManager.register(Strings.CMD_CHECK_FOR_UPDATE,    Commands.CHECK_FOR_UPDATE,             _handleCheckForUpdates);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, window, $ */\n\ndefine('view/ViewCommandHandlers',['require','exports','module','command/Commands','command/CommandManager','strings','project/ProjectManager','editor/EditorManager'],function (require, exports, module) {\n    \n    \n    var Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        Strings                 = require(\"strings\"),\n        ProjectManager          = require(\"project/ProjectManager\"),\n        EditorManager           = require(\"editor/EditorManager\");\n    \n    /**\n     * @const\n     * @type {string}\n     */\n    var DYNAMIC_FONT_STYLE_ID = \"codemirror-dynamic-fonts\";\n\n    function _removeDynamicFontSize(refresh) {\n        $(\"#\" + DYNAMIC_FONT_STYLE_ID).remove();\n        if (refresh) {\n            EditorManager.getCurrentFullEditor().refreshAll();\n        }\n    }\n    \n    /**\n     * @private\n     * Increases or decreases the editor's font size.\n     * @param {number} -1 to make the font smaller; 1 to make it bigger.\n     */\n    function _adjustFontSize(direction) {\n        var styleId = \"codemirror-dynamic-fonts\";\n\n        var fsStyle = $(\".CodeMirror-scroll\").css(\"font-size\");\n        var lhStyle = $(\".CodeMirror-scroll\").css(\"line-height\");\n\n        var validFont = /^[\\d\\.]+(px|em)$/;\n        \n        // Make sure the font size and line height are expressed in terms\n        // we can handle (px or em). If not, simply bail.\n        if (fsStyle.search(validFont) === -1 || lhStyle.search(validFont) === -1) {\n            return;\n        }\n        \n        // Guaranteed to work by the validation above.\n        var fsUnits = fsStyle.substring(fsStyle.length - 2, fsStyle.length);\n        var lhUnits = lhStyle.substring(lhStyle.length - 2, lhStyle.length);\n\n        var fsOld = parseFloat(fsStyle.substring(0, fsStyle.length - 2));\n        var lhOld = parseFloat(lhStyle.substring(0, lhStyle.length - 2));\n\n        var fsDelta = (fsUnits === \"px\") ? 1 : 0.1;\n        var lhDelta = (lhUnits === \"px\") ? 1 : 0.1;\n\n        if (direction === -1) {\n            fsDelta *= -1;\n            lhDelta *= -1;\n        }\n\n        var fsNew = fsOld + fsDelta;\n        var lhNew = lhOld + lhDelta;\n        \n        var fsStr = fsNew + fsUnits;\n        var lhStr = lhNew + lhUnits;\n\n        // Don't let the fonts get too small.\n        if (direction === -1 && ((fsUnits === \"px\" && fsNew <= 1) || (fsUnits === \"em\" && fsNew <= 0.1))) {\n            return;\n        }\n\n        // It's necessary to inject a new rule to address all editors.\n        _removeDynamicFontSize(false);\n        var style = $(\"<style type='text/css'></style>\").attr(\"id\", DYNAMIC_FONT_STYLE_ID);\n        style.html(\".CodeMirror-scroll {\" +\n                   \"font-size: \"   + fsStr + \" !important;\" +\n                   \"line-height: \" + lhStr + \" !important;}\");\n        $(\"head\").append(style);\n        \n        var editor = EditorManager.getCurrentFullEditor();\n        editor.refreshAll();\n        \n        // Scroll the document back to its original position. This can only happen\n        // if the font size is specified in pixels (which it currently is).\n        if (fsUnits === \"px\") {\n            var scrollPos = editor.getScrollPos();\n            var scrollDeltaX = Math.round(scrollPos.x / lhOld);\n            var scrollDeltaY = Math.round(scrollPos.y / lhOld);\n            editor.setScrollPos(scrollPos.x + (scrollDeltaX * direction),\n                                scrollPos.y + (scrollDeltaY * direction));\n        }\n\n    }\n    \n    function _handleIncreaseFontSize() {\n        _adjustFontSize(1);\n    }\n\n    function _handleDecreaseFontSize() {\n        _adjustFontSize(-1);\n    }\n    \n    function _handleRestoreFontSize() {\n        _removeDynamicFontSize(true);\n    }\n    \n    CommandManager.register(Strings.CMD_INCREASE_FONT_SIZE, Commands.VIEW_INCREASE_FONT_SIZE, _handleIncreaseFontSize);\n    CommandManager.register(Strings.CMD_DECREASE_FONT_SIZE, Commands.VIEW_DECREASE_FONT_SIZE, _handleDecreaseFontSize);\n    CommandManager.register(Strings.CMD_RESTORE_FONT_SIZE,  Commands.VIEW_RESTORE_FONT_SIZE,  _handleRestoreFontSize);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, PathUtils, window */\n\n/*\n * Adds a \"find in files\" command to allow the user to find all occurances of a string in all files in\n * the project.\n * \n * The keyboard shortcut is Cmd(Ctrl)-Shift-F.\n *\n * FUTURE:\n *  - Proper UI for both dialog and results\n *  - Refactor dialog class and share with Quick File Open\n *  - Search files in working set that are *not* in the project\n *  - Handle matches that span mulitple lines\n *  - Refactor UI from functionality to enable unit testing\n */\n\n\ndefine('search/FindInFiles',['require','exports','module','utils/Async','command/CommandManager','command/Commands','strings','utils/StringUtils','document/DocumentManager','editor/EditorManager','project/FileIndexManager'],function (require, exports, module) {\n    \n    \n    var Async               = require(\"utils/Async\"),\n        CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        StringUtils         = require(\"utils/StringUtils\"),\n        DocumentManager     = require(\"document/DocumentManager\"),\n        EditorManager       = require(\"editor/EditorManager\"),\n        FileIndexManager    = require(\"project/FileIndexManager\");\n\n    // This dialog class was mostly copied from QuickOpen. We should have a common dialog\n    // class that everyone can use.\n    \n    /**\n    * FindInFilesDialog class\n    * @constructor\n    *\n    */\n    function FindInFilesDialog() {\n        this.closed = false;\n        this.result = null; // $.Deferred\n    }\n\n    /**\n    * Creates a dialog div floating on top of the current code mirror editor\n    */\n    FindInFilesDialog.prototype._createDialogDiv = function (template) {\n        this.dialog = $(\"<div />\")\n                          .attr(\"class\", \"CodeMirror-dialog\")\n                          .html(\"<div>\" + template + \"</div>\")\n                          .prependTo($(\"#editor-holder\"));\n    };\n    \n    /**\n    * Closes the search dialog and resolves the promise that showDialog returned\n    */\n    FindInFilesDialog.prototype._close = function (value) {\n        if (this.closed) {\n            return;\n        }\n        \n        this.closed = true;\n        this.dialog.remove();\n        EditorManager.focusEditor();\n        this.result.resolve(value);\n    };\n        \n    /**\n    * Shows the search dialog \n    * @param {?string} initialString Default text to prepopulate the search field with\n    * @returns {$.Promise} that is resolved with the string to search for\n    */\n    FindInFilesDialog.prototype.showDialog = function (initialString) {\n        var dialogHTML = Strings.CMD_FIND_IN_FILES +\n            \": <input type='text' id='findInFilesInput' style='width: 10em'> <span style='color: #888'>(\" +\n            Strings.SEARCH_REGEXP_INFO  + \")</span>\";\n        this.result = new $.Deferred();\n        this._createDialogDiv(dialogHTML);\n        var $searchField = $(\"input#findInFilesInput\");\n        var that = this;\n        \n        $searchField.attr(\"value\", initialString || \"\");\n        $searchField.get(0).select();\n        \n        $searchField.bind(\"keydown\", function (event) {\n            if (event.keyCode === 13 || event.keyCode === 27) {  // Enter/Return key or Esc key\n                event.stopPropagation();\n                event.preventDefault();\n                \n                var query = $searchField.val();\n                \n                if (event.keyCode === 27) {\n                    query = null;\n                }\n                \n                that._close(query);\n            }\n        })\n            .blur(function () {\n                that._close(null);\n            })\n            .focus();\n        \n        return this.result.promise();\n    };\n\n\n    function _getSearchMatches(contents, queryExpr) {\n        // Quick exit if not found\n        if (contents.search(queryExpr) === -1) {\n            return null;\n        }\n        \n        var trimmedContents = contents;\n        var startPos = 0;\n        var matchStart;\n        var matches = [];\n        \n        \n        var match;\n        var lines = StringUtils.getLines(contents);\n        while ((match = queryExpr.exec(contents)) !== null) {\n            var lineNum = StringUtils.offsetToLineNum(lines, match.index);\n            var line = lines[lineNum];\n            var ch = match.index - contents.lastIndexOf(\"\\n\", match.index) - 1;  // 0-based index\n            var matchLength = match[0].length;\n            \n            // Don't store more than 200 chars per line\n            line = line.substr(0, Math.min(200, line.length));\n            \n            matches.push({\n                start: {line: lineNum, ch: ch},\n                end: {line: lineNum, ch: ch + matchLength},\n                line: line\n            });\n        }\n\n        return matches;\n    }\n        \n    function _showSearchResults(searchResults) {\n        var $searchResultsDiv = $(\"#search-results\");\n        \n        if (searchResults && searchResults.length) {\n            var $resultTable = $(\"<table class='zebra-striped condensed-table' />\")\n                                .append(\"<tbody>\");\n            \n            // Count the total number of matches\n            var numMatches = 0;\n            searchResults.forEach(function (item) {\n                numMatches += item.matches.length;\n            });\n            \n            // Show result summary in header\n            $(\"#search-result-summary\")\n                .text(\"- \" + numMatches + \" match\" + (numMatches > 1 ? \"es\" : \"\") +\n                      \" in \" + searchResults.length + \" file\" + (searchResults.length > 1 ? \"s\" : \"\") +\n                     (numMatches > 100 ? \" (showing the first 100 matches)\" : \"\"))\n                .prepend(\"&nbsp;\");  // putting a normal space before the \"-\" is not enough\n            \n            var resultsDisplayed = 0;\n            \n            searchResults.forEach(function (item) {\n                if (item && resultsDisplayed < 100) {\n                    var makeCell = function (content) {\n                        return $(\"<td/>\").html(content);\n                    };\n                    \n                    var esc = function (str) {\n                        str = str.replace(/</g, \"&lt;\");\n                        str = str.replace(/>/g, \"&gt;\");\n                        return str;\n                    };\n                    \n                    var highlightMatch = function (line, start, end) {\n                        return esc(line.substr(0, start)) + \"<span class='highlight'>\" + esc(line.substring(start, end)) + \"</span>\" + esc(line.substr(end));\n                    };\n                    \n                    // Add row for file name\n                    $(\"<tr class='file-section' />\")\n                        .append(\"<td colspan='3'>File: <b>\" + item.fullPath + \"</b></td>\")\n                        .click(function () {\n                            // Clicking file section header collapses/expands result rows for that file\n                            var $fileHeader = $(this);\n                            $fileHeader.nextUntil(\".file-section\").toggle();\n                        })\n                        .appendTo($resultTable);\n                    \n                    // Add row for each match in file\n                    item.matches.forEach(function (match) {\n                        if (resultsDisplayed < 100) {\n                            var $row = $(\"<tr/>\")\n                                .append(makeCell(\" \"))      // Indent\n                                .append(makeCell(\"line: \" + (match.start.line + 1)))\n                                .append(makeCell(highlightMatch(match.line, match.start.ch, match.end.ch)))\n                                .appendTo($resultTable);\n                            \n                            $row.click(function () {\n                                CommandManager.execute(Commands.FILE_OPEN, {fullPath: item.fullPath})\n                                    .done(function (doc) {\n                                        // Opened document is now the current main editor\n                                        EditorManager.getCurrentFullEditor().setSelection(match.start, match.end);\n                                    });\n                            });\n                            resultsDisplayed++;\n                        }\n                    });\n                    \n                }\n            });\n            \n            $(\"#search-results .table-container\")\n                .empty()\n                .append($resultTable);\n            \n            $(\"#search-results .close\")\n                .one(\"click\", function () {\n                    $searchResultsDiv.hide();\n                    EditorManager.resizeEditor();\n                });\n            \n            $searchResultsDiv.show();\n        } else {\n            $searchResultsDiv.hide();\n        }\n        \n        EditorManager.resizeEditor();\n    }\n    \n    function _getQueryRegExp(query) {\n        // If query is a regular expression, use it directly\n        var isRE = query.match(/^\\/(.*)\\/(g|i)*$/);\n        if (isRE) {\n            // Make sure the 'g' flag is set\n            var flags = isRE[2] || \"g\";\n            if (flags.search(\"g\") === -1) {\n                flags += \"g\";\n            }\n            return new RegExp(isRE[1], flags);\n        }\n\n        // Query is a string. Turn it into a case-insensitive regexp\n        \n        // Escape regex special chars\n        query = query.replace(/([(){}\\[\\].\\^$|?+*\\\\])/g, \"\\\\$1\");\n        return new RegExp(query, \"gi\");\n    }\n    \n    /**\n    * Displays a non-modal embedded dialog above the code mirror editor that allows the user to do\n    * a find operation across all files in the project.\n    */\n    function doFindInFiles() {\n\n        var dialog = new FindInFilesDialog();\n        var searchResults = [];\n        \n        // Default to searching for the current selection\n        var currentEditor = EditorManager.getFocusedEditor();\n        var initialString = currentEditor && currentEditor.getSelectedText();\n                            \n        dialog.showDialog(initialString)\n            .done(function (query) {\n                if (query) {\n                    var queryExpr = _getQueryRegExp(query);\n                    FileIndexManager.getFileInfoList(\"all\")\n                        .done(function (fileListResult) {\n                            Async.doInParallel(fileListResult, function (fileInfo) {\n                                var result = new $.Deferred();\n                                \n                                DocumentManager.getDocumentForPath(fileInfo.fullPath)\n                                    .done(function (doc) {\n                                        var matches = _getSearchMatches(doc.getText(), queryExpr);\n                                        \n                                        if (matches && matches.length) {\n                                            searchResults.push({\n                                                fullPath: fileInfo.fullPath,\n                                                matches: matches\n                                            });\n                                        }\n                                        result.resolve();\n                                    })\n                                    .fail(function (error) {\n                                        // Error reading this file. This is most likely because the file isn't a text file.\n                                        // Resolve here so we move on to the next file.\n                                        result.resolve();\n                                    });\n                                \n                                return result.promise();\n                            })\n                                .done(function () {\n                                    _showSearchResults(searchResults);\n                                })\n                                .fail(function () {\n                                    console.log(\"find in files failed.\");\n                                });\n                        });\n                }\n            });\n    }\n\n    CommandManager.register(Strings.CMD_FIND_IN_FILES,  Commands.EDIT_FIND_IN_FILES,    doFindInFiles);\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */\n/*global define, $, doReplace */\n\n/*\n * Adds Find and Replace commands\n * \n * Define search commands. Depends on dialog.js or another\n * implementation of the openDialog method.\n *\n * This code was copied from CodeMirror2/lib/util/search.js so that the UI strings \n * could be localized.\n *\n * Replace works a little oddly -- it will do the replace on the next findNext press.\n * You prevent a replace by making sure the match is no longer selected when hitting\n * findNext.\n *\n */\n\n\ndefine('search/FindReplace',['require','exports','module','command/CommandManager','command/Commands','strings','editor/EditorManager'],function (require, exports, module) {\n    \n\n    var CommandManager      = require(\"command/CommandManager\"),\n        Commands            = require(\"command/Commands\"),\n        Strings             = require(\"strings\"),\n        EditorManager       = require(\"editor/EditorManager\");\n\n    function SearchState() {\n        this.posFrom = this.posTo = this.query = null;\n        this.marked = [];\n    }\n\n    function getSearchState(cm) {\n        if (!cm._searchState) {\n            cm._searchState = new SearchState();\n        }\n        return cm._searchState;\n    }\n\n    function getSearchCursor(cm, query, pos) {\n        // Heuristic: if the query string is all lowercase, do a case insensitive search.\n        return cm.getSearchCursor(query, pos, typeof query === \"string\" && query === query.toLowerCase());\n    }\n\n    function dialog(cm, text, shortText, f) {\n        if (cm.openDialog) {\n            cm.openDialog(text, f);\n        } else {\n            f(prompt(shortText, \"\"));\n        }\n    }\n\n    function confirmDialog(cm, text, shortText, fs) {\n        if (cm.openConfirm) {\n            cm.openConfirm(text, fs);\n        } else if (confirm(shortText)) {\n            fs[0]();\n        }\n    }\n\n    function parseQuery(query) {\n        var isRE = query.match(/^\\/(.*)\\/([a-z]*)$/);\n        return isRE ? new RegExp(isRE[1], isRE[2].indexOf(\"i\") === -1 ? \"\" : \"i\") : query;\n    }\n\n    function findNext(cm, rev) {\n        cm.operation(function () {\n            var state = getSearchState(cm);\n            var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);\n            if (!cursor.find(rev)) {\n                cursor = getSearchCursor(cm, state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});\n                if (!cursor.find(rev)) {\n                    return;\n                }\n            }\n            cm.setSelection(cursor.from(), cursor.to());\n            state.posFrom = cursor.from();\n            state.posTo = cursor.to();\n        });\n    }\n\n    var queryDialog = Strings.CMD_FIND +\n            ': <input type=\"text\" style=\"width: 10em\"/> <span style=\"color: #888\">(' +\n            Strings.SEARCH_REGEXP_INFO  + ')</span>';\n\n    function doSearch(cm, rev) {\n        var state = getSearchState(cm);\n        if (state.query) {\n            return findNext(cm, rev);\n        }\n        dialog(cm, queryDialog, Strings.CMD_FIND, function (query) {\n            cm.operation(function () {\n                if (!query || state.query) {\n                    return;\n                }\n                state.query = parseQuery(query);\n                if (cm.lineCount() < 2000) { // This is too expensive on big documents.\n                    var cursor = getSearchCursor(cm, query);\n                    while (cursor.findNext()) {\n                        state.marked.push(cm.markText(cursor.from(), cursor.to(), \"CodeMirror-searching\"));\n                    }\n                }\n                state.posFrom = state.posTo = cm.getCursor();\n                findNext(cm, rev);\n            });\n        });\n    }\n\n    function clearSearch(cm) {\n        cm.operation(function () {\n            var state = getSearchState(cm),\n                i;\n            if (!state.query) {\n                return;\n            }\n            state.query = null;\n            for (i = 0; i < state.marked.length; ++i) {\n                state.marked[i].clear();\n            }\n            state.marked.length = 0;\n        });\n    }\n\n    var replaceQueryDialog = Strings.CMD_REPLACE +\n            ': <input type=\"text\" style=\"width: 10em\"/> <span style=\"color: #888\">(' +\n            Strings.SEARCH_REGEXP_INFO  + ')</span>';\n    var replacementQueryDialog = Strings.WITH +\n            ': <input type=\"text\" style=\"width: 10em\"/>';\n    // style buttons to match height/margins/border-radius of text input boxes\n    var style = ' style=\"padding:5px 15px;border:1px #999 solid;border-radius:3px;margin:2px 2px 5px;\"';\n    var doReplaceConfirm = Strings.CMD_REPLACE +\n            '? <button' + style + '>' + Strings.BUTTON_YES +\n            '</button> <button' + style + '>' + Strings.BUTTON_NO +\n            '</button> <button' + style + '>' + Strings.BUTTON_STOP + '</button>';\n\n    function replace(cm, all) {\n        dialog(cm, replaceQueryDialog, Strings.CMD_REPLACE, function (query) {\n            if (!query) {\n                return;\n            }\n            query = parseQuery(query);\n            dialog(cm, replacementQueryDialog, Strings.WITH, function (text) {\n                var match,\n                    fnMatch = function (w, i) { return match[i]; };\n                if (all) {\n                    cm.compoundChange(function () {\n                        cm.operation(function () {\n                            var cursor = getSearchCursor(cm, query);\n                            while (cursor.findNext()) {\n                                if (typeof query !== \"string\") {\n                                    match = cm.getRange(cursor.from(), cursor.to()).match(query);\n                                    cursor.replace(text.replace(/\\$(\\d)/, fnMatch));\n                                } else {\n                                    cursor.replace(text);\n                                }\n                            }\n                        });\n                    });\n                } else {\n                    clearSearch(cm);\n                    var cursor = getSearchCursor(cm, query, cm.getCursor());\n                    var advance = function () {\n                        var start = cursor.from(),\n                            match = cursor.findNext();\n                        if (!match) {\n                            cursor = getSearchCursor(cm, query);\n                            match = cursor.findNext();\n                            if (!match ||\n                                    (start && cursor.from().line === start.line && cursor.from().ch === start.ch)) {\n                                return;\n                            }\n                        }\n                        cm.setSelection(cursor.from(), cursor.to());\n                        confirmDialog(cm, doReplaceConfirm, Strings.CMD_REPLACE + \"?\",\n                                                    [function () { doReplace(match); }, advance]);\n                    };\n                    var doReplace = function (match) {\n                        cursor.replace(typeof query === \"string\" ? text :\n                                            text.replace(/\\$(\\d)/, fnMatch));\n                        advance();\n                    };\n                    advance();\n                }\n            });\n        });\n    }\n\n    function _launchFind() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            var codeMirror = editor._codeMirror;\n\n            // Bring up CodeMirror's existing search bar UI\n            clearSearch(codeMirror);\n            doSearch(codeMirror);\n\n            // Prepopulate the search field with the current selection, if any\n            $(\".CodeMirror-dialog input[type='text']\")\n                .attr(\"value\", codeMirror.getSelection())\n                .get(0).select();\n        }\n    }\n\n    function _findNext() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            doSearch(editor._codeMirror);\n        }\n    }\n\n    function _findPrevious() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            doSearch(editor._codeMirror, true);\n        }\n    }\n\n    function _replace() {\n        var editor = EditorManager.getFocusedEditor();\n        if (editor) {\n            replace(editor._codeMirror);\n        }\n    }\n\n    CommandManager.register(Strings.CMD_FIND,           Commands.EDIT_FIND,          _launchFind);\n    CommandManager.register(Strings.CMD_FIND_NEXT,      Commands.EDIT_FIND_NEXT,     _findNext);\n    CommandManager.register(Strings.CMD_REPLACE,        Commands.EDIT_REPLACE,       _replace);\n    CommandManager.register(Strings.CMD_FIND_PREVIOUS,  Commands.EDIT_FIND_PREVIOUS, _findPrevious);\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $ */\n\n/**\n * ExtensionUtils defines utility methods for implementing extensions.\n */\ndefine('utils/ExtensionUtils',['require','exports','module'],function (require, exports, module) {\n    \n    \n    /**\n     * Loads a style sheet relative to the extension module.\n     *\n     * @param {!module} module Module provided by RequireJS\n     * @param {!string} path Relative path from the extension folder to a CSS file\n     * @return {!$.Promise} A promise object that is resolved if the CSS file can be loaded.\n     */\n    function loadStyleSheet(module, path) {\n        var modulePath = module.uri.substr(0, module.uri.lastIndexOf(\"/\") + 1),\n            url = encodeURI(modulePath + path),\n            result = new $.Deferred();\n\n        // Make a request for the same file in order to record success or failure.\n        // The link element's onload and onerror events are not consistently supported.\n        $.get(url).done(function () {\n            var $link = $(\"<link/>\");\n            \n            $link.attr({\n                type:       \"text/css\",\n                rel:        \"stylesheet\",\n                href:       url\n            });\n            \n            $(\"head\").append($link[0]);\n            \n            result.resolve($link[0]);\n        }).fail(function (err) {\n            result.reject(err);\n        });\n        \n        return result;\n    }\n    \n    exports.loadStyleSheet = loadStyleSheet;\n});\n\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global define, $, window */\n\n /**\n  * This is JavaScript API exposed to the native shell when Brackets is run in a native shell rather than a browser.\n  */\ndefine('utils/ShellAPI',['require','exports','module','command/CommandManager'],function (require, exports, module) {\n    \n\n    // Load dependent modules\n    var CommandManager     = require(\"command/CommandManager\");\n\n    /**\n     * The native function BracketsShellAPI::DispatchBracketsJSCommand calls this function in order to enable\n     * calling Brackets commands from the native shell.\n     */\n    function executeCommand(eventName) {\n        var evt = window.document.createEvent(\"Event\");\n        evt.initEvent(eventName, false, true);\n        \n        CommandManager.execute(eventName, {evt: evt});\n        \n        //return if default was prevented\n        return evt.defaultPrevented;\n    }\n\n    exports.executeCommand = executeCommand;\n});\n/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n\n/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */\n/*global require, define, brackets: true, $, PathUtils, window, navigator, Mustache */\n\nrequire.config({\n    paths: {\n        \"text\" : \"thirdparty/text\",\n        \"i18n\" : \"thirdparty/i18n\"\n    },\n    // Use custom brackets property until CEF sets the correct navigator.language\n    // NOTE: When we change to navigator.language here, we also should change to\n    // navigator.language in ExtensionLoader (when making require contexts for each\n    // extension).\n    locale: window.localStorage.getItem(\"locale\") || brackets.app.language\n});\n\n/**\n * brackets is the root of the Brackets codebase. This file pulls in all other modules as\n * dependencies (or dependencies thereof), initializes the UI, and binds global menus & keyboard\n * shortcuts to their Commands.\n *\n * TODO: (issue #264) break out the definition of brackets into a separate module from the application controller logic\n *\n * Unlike other modules, this one can be accessed without an explicit require() because it exposes\n * a global object, window.brackets.\n *\n * Events:\n *      htmlContentLoadComplete - sent when the HTML DOM is fully loaded. Modules should not touch\n *      or modify DOM elements before this event is sent.\n */\ndefine('brackets',['require','exports','module','widgets/bootstrap-dropdown','widgets/bootstrap-modal','thirdparty/path-utils/path-utils.min','thirdparty/smart-auto-complete/jquery.smart_autocomplete','LiveDevelopment/main','project/ProjectManager','document/DocumentManager','editor/EditorManager','editor/CSSInlineEditor','language/JSUtils','project/WorkingSetView','document/DocumentCommandHandlers','project/FileViewController','project/FileSyncManager','command/KeyBindingManager','command/Commands','command/CommandManager','utils/BuildInfoUtils','editor/CodeHintManager','language/JSLintUtils','utils/PerfUtils','project/FileIndexManager','search/QuickOpen','command/Menus','file/FileUtils','text!htmlContent/main-view.html','strings','widgets/Dialogs','utils/ExtensionLoader','project/SidebarView','utils/Async','utils/UpdateNotification','utils/UrlParams','document/ChangedDocumentTracker','editor/EditorCommandHandlers','debug/DebugCommandHandlers','view/ViewCommandHandlers','search/FindInFiles','search/FindReplace','utils/ExtensionUtils','utils/ShellAPI','preferences/PreferencesManager','command/CommandManager','language/CSSUtils','LiveDevelopment/LiveDevelopment','LiveDevelopment/Inspector/Inspector','utils/NativeApp','utils/ExtensionUtils','utils/UpdateNotification'],function (require, exports, module) {\n    \n    \n    // Load dependent non-module scripts\n    require(\"widgets/bootstrap-dropdown\");\n    require(\"widgets/bootstrap-modal\");\n    require(\"thirdparty/path-utils/path-utils.min\");\n    require(\"thirdparty/smart-auto-complete/jquery.smart_autocomplete\");\n\n    // Load LiveDeveopment\n    require(\"LiveDevelopment/main\");\n    \n    // Load dependent modules\n    var ProjectManager          = require(\"project/ProjectManager\"),\n        DocumentManager         = require(\"document/DocumentManager\"),\n        EditorManager           = require(\"editor/EditorManager\"),\n        CSSInlineEditor         = require(\"editor/CSSInlineEditor\"),\n        JSUtils                 = require(\"language/JSUtils\"),\n        WorkingSetView          = require(\"project/WorkingSetView\"),\n        DocumentCommandHandlers = require(\"document/DocumentCommandHandlers\"),\n        FileViewController      = require(\"project/FileViewController\"),\n        FileSyncManager         = require(\"project/FileSyncManager\"),\n        KeyBindingManager       = require(\"command/KeyBindingManager\"),\n        Commands                = require(\"command/Commands\"),\n        CommandManager          = require(\"command/CommandManager\"),\n        BuildInfoUtils          = require(\"utils/BuildInfoUtils\"),\n        CodeHintManager         = require(\"editor/CodeHintManager\"),\n        JSLintUtils             = require(\"language/JSLintUtils\"),\n        PerfUtils               = require(\"utils/PerfUtils\"),\n        FileIndexManager        = require(\"project/FileIndexManager\"),\n        QuickOpen               = require(\"search/QuickOpen\"),\n        Menus                   = require(\"command/Menus\"),\n        FileUtils               = require(\"file/FileUtils\"),\n        MainViewHTML            = require(\"text!htmlContent/main-view.html\"),\n        Strings                 = require(\"strings\"),\n        Dialogs                 = require(\"widgets/Dialogs\"),\n        ExtensionLoader         = require(\"utils/ExtensionLoader\"),\n        SidebarView             = require(\"project/SidebarView\"),\n        Async                   = require(\"utils/Async\"),\n        UpdateNotification      = require(\"utils/UpdateNotification\"),\n        UrlParams               = require(\"utils/UrlParams\").UrlParams;\n\n    // Local variables\n    var bracketsReady           = false,\n        bracketsReadyHandlers   = [],\n        params                  = new UrlParams();\n    \n    // read URL params\n    params.parse();\n            \n    //Load modules that self-register and just need to get included in the main project\n    require(\"document/ChangedDocumentTracker\");\n    require(\"editor/EditorCommandHandlers\");\n    require(\"debug/DebugCommandHandlers\");\n    require(\"view/ViewCommandHandlers\");\n    require(\"search/FindInFiles\");\n    require(\"search/FindReplace\");\n    require(\"utils/ExtensionUtils\");\n\n    function _callBracketsReadyHandler(handler) {\n        try {\n            handler();\n        } catch (e) {\n            console.log(\"Exception when calling a 'brackets done loading' handler\");\n            console.log(e);\n        }\n    }\n\n    function _onBracketsReady() {\n        var i;\n        bracketsReady = true;\n        for (i = 0; i < bracketsReadyHandlers.length; i++) {\n            _callBracketsReadyHandler(bracketsReadyHandlers[i]);\n        }\n        bracketsReadyHandlers = [];\n    }\n\n    // WARNING: This event won't fire if ANY extension fails to load or throws an error during init.\n    // To fix this, we need to make a change to _initExtensions (filed as issue 1029)\n    function _registerBracketsReadyHandler(handler) {\n        if (bracketsReady) {\n            _callBracketsReadyHandler(handler);\n        } else {\n            bracketsReadyHandlers.push(handler);\n        }\n    }\n    \n    // TODO: Issue 949 - the following code should be shared\n    \n    function _initGlobalBrackets() {\n        // Define core brackets namespace if it isn't already defined\n        //\n        // We can't simply do 'brackets = {}' to define it in the global namespace because\n        // we're in \"use strict\" mode. Most likely, 'window' will always point to the global\n        // object when this code is running. However, in case it isn't (e.g. if we're running \n        // inside Node for CI testing) we use this trick to get the global object.\n        //\n        // Taken from:\n        //   http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript\n        var Fn = Function, global = (new Fn(\"return this\"))();\n        if (!global.brackets) {\n            global.brackets = {};\n        }\n        \n        // Uncomment the following line to force all low level file i/o routines to complete\n        // asynchronously. This should only be done for testing/debugging.\n        // NOTE: Make sure this line is commented out again before committing!\n        //brackets.forceAsyncCallbacks = true;\n    \n        // Load native shell when brackets is run in a native shell rather than the browser\n        // TODO: (issue #266) load conditionally\n        brackets.shellAPI = require(\"utils/ShellAPI\");\n        \n        brackets.inBrowser = !brackets.hasOwnProperty(\"fs\");\n        \n        brackets.platform = (global.navigator.platform === \"MacIntel\" || global.navigator.platform === \"MacPPC\") ? \"mac\" : \"win\";\n        \n        // Loading extensions requires creating new require.js contexts, which requires access to the global 'require' object\n        // that always gets hidden by the 'require' in the AMD wrapper. We store this in the brackets object here so that \n        // the ExtensionLoader doesn't have to have access to the global object.\n        brackets.libRequire = global.require;\n\n        // Also store our current require.js context (the one that loads brackets core modules) so that extensions can use it\n        // Note: we change the name to \"getModule\" because this won't do exactly the same thing as 'require' in AMD-wrapped\n        // modules. The extension will only be able to load modules that have already been loaded once.\n        brackets.getModule = require;\n\n        // Provide a way for anyone (including code not using require) to register a handler for the brackets 'ready' event\n        // This event is like $(document).ready in that it will call the handler immediately if brackets is already done loading\n        //\n        // WARNING: This event won't fire if ANY extension fails to load or throws an error during init.\n        // To fix this, we need to make a change to _initExtensions (filed as issue 1029)\n        //\n        // TODO (issue 1034): We *could* use a $.Deferred for this, except deferred objects enter a broken\n        // state if any resolution callback throws an exception. Since third parties (e.g. extensions) may\n        // add callbacks to this, we need to be robust to exceptions\n        brackets.ready = _registerBracketsReadyHandler;\n    }\n    \n    // TODO: (issue 1029) Add timeout to main extension loading promise, so that we always call this function\n    // Making this fix will fix a warning (search for issue 1029) related to the brackets 'ready' event.\n    function _initExtensions() {\n        // allow unit tests to override which plugin folder(s) to load\n        var paths = params.get(\"extensions\") || \"default,user\";\n        \n        return Async.doInParallel(paths.split(\",\"), function (item) {\n            return ExtensionLoader.loadAllExtensionsInNativeDirectory(\n                FileUtils.getNativeBracketsDirectoryPath() + \"/extensions/\" + item,\n                \"extensions/\" + item\n            );\n        });\n    }\n    \n    function _initTest() {\n        // TODO: (issue #265) Make sure the \"test\" object is not included in final builds\n        // All modules that need to be tested from the context of the application\n        // must to be added to this object. The unit tests cannot just pull\n        // in the modules since they would run in context of the unit test window,\n        // and would not have access to the app html/css.\n        brackets.test = {\n            PreferencesManager      : require(\"preferences/PreferencesManager\"),\n            ProjectManager          : ProjectManager,\n            DocumentCommandHandlers : DocumentCommandHandlers,\n            FileViewController      : FileViewController,\n            DocumentManager         : DocumentManager,\n            EditorManager           : EditorManager,\n            Commands                : Commands,\n            WorkingSetView          : WorkingSetView,\n            JSLintUtils             : JSLintUtils,\n            PerfUtils               : PerfUtils,\n            JSUtils                 : JSUtils,\n            CommandManager          : require(\"command/CommandManager\"),\n            FileSyncManager         : FileSyncManager,\n            FileIndexManager        : FileIndexManager,\n            Menus                   : Menus,\n            KeyBindingManager       : KeyBindingManager,\n            CodeHintManager         : CodeHintManager,\n            CSSUtils                : require(\"language/CSSUtils\"),\n            LiveDevelopment         : require(\"LiveDevelopment/LiveDevelopment\"),\n            Inspector               : require(\"LiveDevelopment/Inspector/Inspector\"),\n            NativeApp               : require(\"utils/NativeApp\"),\n            ExtensionUtils          : require(\"utils/ExtensionUtils\"),\n            UpdateNotification      : require(\"utils/UpdateNotification\"),\n            doneLoading             : false\n        };\n\n        brackets.ready(function () {\n            brackets.test.doneLoading = true;\n        });\n    }\n    \n    function _initDragAndDropListeners() {\n        // Prevent unhandled drag and drop of files into the browser from replacing \n        // the entire Brackets app. This doesn't prevent children from choosing to\n        // handle drops.\n        $(window.document.body)\n            .on(\"dragover\", function (event) {\n                if (event.originalEvent.dataTransfer.files) {\n                    event.stopPropagation();\n                    event.preventDefault();\n                    event.originalEvent.dataTransfer.dropEffect = \"none\";\n                }\n            })\n            .on(\"drop\", function (event) {\n                if (event.originalEvent.dataTransfer.files) {\n                    event.stopPropagation();\n                    event.preventDefault();\n                }\n            });\n    }\n    \n    function _initCommandHandlers() {\n        // Most command handlers are automatically registered when their module is loaded (see \"modules\n        // that self-register\" above for some). A few commands need an extra kick here though:\n        \n        DocumentCommandHandlers.init($(\"#main-toolbar\"));\n        \n        // About dialog\n        CommandManager.register(Strings.CMD_ABOUT,  Commands.HELP_ABOUT, function () {\n            // If we've successfully determined a \"build number\" via .git metadata, add it to dialog\n            var bracketsSHA = BuildInfoUtils.getBracketsSHA(),\n                bracketsAppSHA = BuildInfoUtils.getBracketsAppSHA(),\n                versionLabel = \"\";\n            if (bracketsSHA) {\n                versionLabel += \" (\" + bracketsSHA.substr(0, 7) + \")\";\n            }\n            if (bracketsAppSHA) {\n                versionLabel += \" (shell \" + bracketsAppSHA.substr(0, 7) + \")\";\n            }\n            $(\"#about-build-number\").text(versionLabel);\n            \n            Dialogs.showModalDialog(Dialogs.DIALOG_ID_ABOUT);\n        });\n    }\n    \n    function _initWindowListeners() {\n        // TODO: (issue 269) to support IE, need to listen to document instead (and even then it may not work when focus is in an input field?)\n        $(window).focus(function () {\n            FileSyncManager.syncOpenDocuments();\n            FileIndexManager.markDirty();\n        });\n        \n    }\n            \n    function _onReady() {\n        // Add the platform (mac or win) to the body tag so we can have platform-specific CSS rules\n        $(\"body\").addClass(\"platform-\" + brackets.platform);\n        \n        EditorManager.setEditorHolder($(\"#editor-holder\"));\n\n        // Let the user know Brackets doesn't run in a web browser yet\n        if (brackets.inBrowser) {\n            Dialogs.showModalDialog(\n                Dialogs.DIALOG_ID_ERROR,\n                Strings.ERROR_BRACKETS_IN_BROWSER_TITLE,\n                Strings.ERROR_BRACKETS_IN_BROWSER\n            );\n        }\n\n        _initDragAndDropListeners();\n        _initCommandHandlers();\n        KeyBindingManager.init();\n        Menus.init(); // key bindings should be initialized first\n        _initWindowListeners();\n        \n        // Read \"build number\" SHAs off disk at the time the matching Brackets JS code is being loaded, instead\n        // of later, when they may have been updated to a different version\n        BuildInfoUtils.init();\n\n        // Use quiet scrollbars if we aren't on Lion. If we're on Lion, only\n        // use native scroll bars when the mouse is not plugged in or when\n        // using the \"Always\" scroll bar setting. \n        var osxMatch = /Mac OS X 10\\D([\\d+])\\D/.exec(navigator.userAgent);\n        if (osxMatch && osxMatch[1] && Number(osxMatch[1]) >= 7) {\n            // test a scrolling div for scrollbars\n            var $testDiv = $(\"<div style='position:fixed;left:-50px;width:50px;height:50px;overflow:auto;'><div style='width:100px;height:100px;'/></div>\").appendTo(window.document.body);\n            \n            if ($testDiv.outerWidth() === $testDiv.get(0).clientWidth) {\n                $(\".sidebar\").removeClass(\"quiet-scrollbars\");\n            }\n            \n            $testDiv.remove();\n        }\n        \n        PerfUtils.addMeasurement(\"Application Startup\");\n        \n        // finish UI initialization before loading extensions\n        var initialProjectPath = ProjectManager.getInitialProjectPath();\n        ProjectManager.openProject(initialProjectPath).done(function () {\n            _initTest();\n            _initExtensions().always(_onBracketsReady);\n        });\n        \n        // Check for updates\n        if (!params.get(\"skipUpdateCheck\")) {\n            UpdateNotification.checkForUpdate();\n        }\n    }\n            \n    // Main Brackets initialization\n    _initGlobalBrackets();\n\n    // Localize MainViewHTML and inject into <BODY> tag\n    $('body').html(Mustache.render(MainViewHTML, Strings));\n    // modules that depend on the HTML DOM should listen to\n    // the htmlContentLoadComplete event.\n    $(brackets).trigger(\"htmlContentLoadComplete\");\n\n    $(window.document).ready(_onReady);\n    \n});\n/*!\n * jQuery JavaScript Library v1.8.0\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: Thu Aug 09 2012 16:24:48 GMT-0400 (Eastern Daylight Time)\n */\n(function( window, undefined ) {\nvar\n    // A central reference to the root jQuery(document)\n    rootjQuery,\n\n    // The deferred used on DOM ready\n    readyList,\n\n    // Use the correct document accordingly with window argument (sandbox)\n    document = window.document,\n    location = window.location,\n    navigator = window.navigator,\n\n    // Map over jQuery in case of overwrite\n    _jQuery = window.jQuery,\n\n    // Map over the $ in case of overwrite\n    _$ = window.$,\n\n    // Save a reference to some core methods\n    core_push = Array.prototype.push,\n    core_slice = Array.prototype.slice,\n    core_indexOf = Array.prototype.indexOf,\n    core_toString = Object.prototype.toString,\n    core_hasOwn = Object.prototype.hasOwnProperty,\n    core_trim = String.prototype.trim,\n\n    // Define a local copy of jQuery\n    jQuery = function( selector, context ) {\n        // The jQuery object is actually just the init constructor 'enhanced'\n        return new jQuery.fn.init( selector, context, rootjQuery );\n    },\n\n    // Used for matching numbers\n    core_pnum = /[\\-+]?(?:\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/.source,\n\n    // Used for detecting and trimming whitespace\n    core_rnotwhite = /\\S/,\n    core_rspace = /\\s+/,\n\n    // IE doesn't match non-breaking spaces with \\s\n    rtrim = core_rnotwhite.test(\"\\xA0\") ? (/^[\\s\\xA0]+|[\\s\\xA0]+$/g) : /^\\s+|\\s+$/g,\n\n    // A simple way to check for HTML strings\n    // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n    rquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n    // Match a standalone tag\n    rsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n    // JSON RegExp\n    rvalidchars = /^[\\],:{}\\s]*$/,\n    rvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n    rvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n    rvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/g,\n\n    // Matches dashed string for camelizing\n    rmsPrefix = /^-ms-/,\n    rdashAlpha = /-([\\da-z])/gi,\n\n    // Used by jQuery.camelCase as callback to replace()\n    fcamelCase = function( all, letter ) {\n        return ( letter + \"\" ).toUpperCase();\n    },\n\n    // The ready event handler and self cleanup method\n    DOMContentLoaded = function() {\n        if ( document.addEventListener ) {\n            document.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n            jQuery.ready();\n        } else if ( document.readyState === \"complete\" ) {\n            // we're here because readyState === \"complete\" in oldIE\n            // which is good enough for us to call the dom ready!\n            document.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n            jQuery.ready();\n        }\n    },\n\n    // [[Class]] -> type pairs\n    class2type = {};\n\njQuery.fn = jQuery.prototype = {\n    constructor: jQuery,\n    init: function( selector, context, rootjQuery ) {\n        var match, elem, ret, doc;\n\n        // Handle $(\"\"), $(null), $(undefined), $(false)\n        if ( !selector ) {\n            return this;\n        }\n\n        // Handle $(DOMElement)\n        if ( selector.nodeType ) {\n            this.context = this[0] = selector;\n            this.length = 1;\n            return this;\n        }\n\n        // Handle HTML strings\n        if ( typeof selector === \"string\" ) {\n            if ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n                // Assume that strings that start and end with <> are HTML and skip the regex check\n                match = [ null, selector, null ];\n\n            } else {\n                match = rquickExpr.exec( selector );\n            }\n\n            // Match html or make sure no context is specified for #id\n            if ( match && (match[1] || !context) ) {\n\n                // HANDLE: $(html) -> $(array)\n                if ( match[1] ) {\n                    context = context instanceof jQuery ? context[0] : context;\n                    doc = ( context && context.nodeType ? context.ownerDocument || context : document );\n\n                    // scripts is true for back-compat\n                    selector = jQuery.parseHTML( match[1], doc, true );\n                    if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n                        this.attr.call( selector, context, true );\n                    }\n\n                    return jQuery.merge( this, selector );\n\n                // HANDLE: $(#id)\n                } else {\n                    elem = document.getElementById( match[2] );\n\n                    // Check parentNode to catch when Blackberry 4.6 returns\n                    // nodes that are no longer in the document #6963\n                    if ( elem && elem.parentNode ) {\n                        // Handle the case where IE and Opera return items\n                        // by name instead of ID\n                        if ( elem.id !== match[2] ) {\n                            return rootjQuery.find( selector );\n                        }\n\n                        // Otherwise, we inject the element directly into the jQuery object\n                        this.length = 1;\n                        this[0] = elem;\n                    }\n\n                    this.context = document;\n                    this.selector = selector;\n                    return this;\n                }\n\n            // HANDLE: $(expr, $(...))\n            } else if ( !context || context.jquery ) {\n                return ( context || rootjQuery ).find( selector );\n\n            // HANDLE: $(expr, context)\n            // (which is just equivalent to: $(context).find(expr)\n            } else {\n                return this.constructor( context ).find( selector );\n            }\n\n        // HANDLE: $(function)\n        // Shortcut for document ready\n        } else if ( jQuery.isFunction( selector ) ) {\n            return rootjQuery.ready( selector );\n        }\n\n        if ( selector.selector !== undefined ) {\n            this.selector = selector.selector;\n            this.context = selector.context;\n        }\n\n        return jQuery.makeArray( selector, this );\n    },\n\n    // Start with an empty selector\n    selector: \"\",\n\n    // The current version of jQuery being used\n    jquery: \"1.8.0\",\n\n    // The default length of a jQuery object is 0\n    length: 0,\n\n    // The number of elements contained in the matched element set\n    size: function() {\n        return this.length;\n    },\n\n    toArray: function() {\n        return core_slice.call( this );\n    },\n\n    // Get the Nth element in the matched element set OR\n    // Get the whole matched element set as a clean array\n    get: function( num ) {\n        return num == null ?\n\n            // Return a 'clean' array\n            this.toArray() :\n\n            // Return just the object\n            ( num < 0 ? this[ this.length + num ] : this[ num ] );\n    },\n\n    // Take an array of elements and push it onto the stack\n    // (returning the new matched element set)\n    pushStack: function( elems, name, selector ) {\n\n        // Build a new jQuery matched element set\n        var ret = jQuery.merge( this.constructor(), elems );\n\n        // Add the old object onto the stack (as a reference)\n        ret.prevObject = this;\n\n        ret.context = this.context;\n\n        if ( name === \"find\" ) {\n            ret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n        } else if ( name ) {\n            ret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n        }\n\n        // Return the newly-formed element set\n        return ret;\n    },\n\n    // Execute a callback for every element in the matched set.\n    // (You can seed the arguments with an array of args, but this is\n    // only used internally.)\n    each: function( callback, args ) {\n        return jQuery.each( this, callback, args );\n    },\n\n    ready: function( fn ) {\n        // Add the callback\n        jQuery.ready.promise().done( fn );\n\n        return this;\n    },\n\n    eq: function( i ) {\n        i = +i;\n        return i === -1 ?\n            this.slice( i ) :\n            this.slice( i, i + 1 );\n    },\n\n    first: function() {\n        return this.eq( 0 );\n    },\n\n    last: function() {\n        return this.eq( -1 );\n    },\n\n    slice: function() {\n        return this.pushStack( core_slice.apply( this, arguments ),\n            \"slice\", core_slice.call(arguments).join(\",\") );\n    },\n\n    map: function( callback ) {\n        return this.pushStack( jQuery.map(this, function( elem, i ) {\n            return callback.call( elem, i, elem );\n        }));\n    },\n\n    end: function() {\n        return this.prevObject || this.constructor(null);\n    },\n\n    // For internal use only.\n    // Behaves like an Array's method, not like a jQuery method.\n    push: core_push,\n    sort: [].sort,\n    splice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n    var options, name, src, copy, copyIsArray, clone,\n        target = arguments[0] || {},\n        i = 1,\n        length = arguments.length,\n        deep = false;\n\n    // Handle a deep copy situation\n    if ( typeof target === \"boolean\" ) {\n        deep = target;\n        target = arguments[1] || {};\n        // skip the boolean and the target\n        i = 2;\n    }\n\n    // Handle case when target is a string or something (possible in deep copy)\n    if ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n        target = {};\n    }\n\n    // extend jQuery itself if only one argument is passed\n    if ( length === i ) {\n        target = this;\n        --i;\n    }\n\n    for ( ; i < length; i++ ) {\n        // Only deal with non-null/undefined values\n        if ( (options = arguments[ i ]) != null ) {\n            // Extend the base object\n            for ( name in options ) {\n                src = target[ name ];\n                copy = options[ name ];\n\n                // Prevent never-ending loop\n                if ( target === copy ) {\n                    continue;\n                }\n\n                // Recurse if we're merging plain objects or arrays\n                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n                    if ( copyIsArray ) {\n                        copyIsArray = false;\n                        clone = src && jQuery.isArray(src) ? src : [];\n\n                    } else {\n                        clone = src && jQuery.isPlainObject(src) ? src : {};\n                    }\n\n                    // Never move original objects, clone them\n                    target[ name ] = jQuery.extend( deep, clone, copy );\n\n                // Don't bring in undefined values\n                } else if ( copy !== undefined ) {\n                    target[ name ] = copy;\n                }\n            }\n        }\n    }\n\n    // Return the modified object\n    return target;\n};\n\njQuery.extend({\n    noConflict: function( deep ) {\n        if ( window.$ === jQuery ) {\n            window.$ = _$;\n        }\n\n        if ( deep && window.jQuery === jQuery ) {\n            window.jQuery = _jQuery;\n        }\n\n        return jQuery;\n    },\n\n    // Is the DOM ready to be used? Set to true once it occurs.\n    isReady: false,\n\n    // A counter to track how many items to wait for before\n    // the ready event fires. See #6781\n    readyWait: 1,\n\n    // Hold (or release) the ready event\n    holdReady: function( hold ) {\n        if ( hold ) {\n            jQuery.readyWait++;\n        } else {\n            jQuery.ready( true );\n        }\n    },\n\n    // Handle when the DOM is ready\n    ready: function( wait ) {\n\n        // Abort if there are pending holds or we're already ready\n        if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n            return;\n        }\n\n        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n        if ( !document.body ) {\n            return setTimeout( jQuery.ready, 1 );\n        }\n\n        // Remember that the DOM is ready\n        jQuery.isReady = true;\n\n        // If a normal DOM Ready event fired, decrement, and wait if need be\n        if ( wait !== true && --jQuery.readyWait > 0 ) {\n            return;\n        }\n\n        // If there are functions bound, to execute\n        readyList.resolveWith( document, [ jQuery ] );\n\n        // Trigger any bound ready events\n        if ( jQuery.fn.trigger ) {\n            jQuery( document ).trigger(\"ready\").off(\"ready\");\n        }\n    },\n\n    // See test/unit/core.js for details concerning isFunction.\n    // Since version 1.3, DOM methods and functions like alert\n    // aren't supported. They return false on IE (#2968).\n    isFunction: function( obj ) {\n        return jQuery.type(obj) === \"function\";\n    },\n\n    isArray: Array.isArray || function( obj ) {\n        return jQuery.type(obj) === \"array\";\n    },\n\n    isWindow: function( obj ) {\n        return obj != null && obj == obj.window;\n    },\n\n    isNumeric: function( obj ) {\n        return !isNaN( parseFloat(obj) ) && isFinite( obj );\n    },\n\n    type: function( obj ) {\n        return obj == null ?\n            String( obj ) :\n            class2type[ core_toString.call(obj) ] || \"object\";\n    },\n\n    isPlainObject: function( obj ) {\n        // Must be an Object.\n        // Because of IE, we also have to check the presence of the constructor property.\n        // Make sure that DOM nodes and window objects don't pass through, as well\n        if ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n            return false;\n        }\n\n        try {\n            // Not own constructor property must be Object\n            if ( obj.constructor &&\n                !core_hasOwn.call(obj, \"constructor\") &&\n                !core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n                return false;\n            }\n        } catch ( e ) {\n            // IE8,9 Will throw exceptions on certain host objects #9897\n            return false;\n        }\n\n        // Own properties are enumerated firstly, so to speed up,\n        // if last one is own, then all properties are own.\n\n        var key;\n        for ( key in obj ) {}\n\n        return key === undefined || core_hasOwn.call( obj, key );\n    },\n\n    isEmptyObject: function( obj ) {\n        var name;\n        for ( name in obj ) {\n            return false;\n        }\n        return true;\n    },\n\n    error: function( msg ) {\n        throw new Error( msg );\n    },\n\n    // data: string of html\n    // context (optional): If specified, the fragment will be created in this context, defaults to document\n    // scripts (optional): If true, will include scripts passed in the html string\n    parseHTML: function( data, context, scripts ) {\n        var parsed;\n        if ( !data || typeof data !== \"string\" ) {\n            return null;\n        }\n        if ( typeof context === \"boolean\" ) {\n            scripts = context;\n            context = 0;\n        }\n        context = context || document;\n\n        // Single tag\n        if ( (parsed = rsingleTag.exec( data )) ) {\n            return [ context.createElement( parsed[1] ) ];\n        }\n\n        parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );\n        return jQuery.merge( [],\n            (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );\n    },\n\n    parseJSON: function( data ) {\n        if ( !data || typeof data !== \"string\") {\n            return null;\n        }\n\n        // Make sure leading/trailing whitespace is removed (IE can't handle it)\n        data = jQuery.trim( data );\n\n        // Attempt to parse using the native JSON parser first\n        if ( window.JSON && window.JSON.parse ) {\n            return window.JSON.parse( data );\n        }\n\n        // Make sure the incoming data is actual JSON\n        // Logic borrowed from http://json.org/json2.js\n        if ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n            .replace( rvalidtokens, \"]\" )\n            .replace( rvalidbraces, \"\")) ) {\n\n            return ( new Function( \"return \" + data ) )();\n\n        }\n        jQuery.error( \"Invalid JSON: \" + data );\n    },\n\n    // Cross-browser xml parsing\n    parseXML: function( data ) {\n        var xml, tmp;\n        if ( !data || typeof data !== \"string\" ) {\n            return null;\n        }\n        try {\n            if ( window.DOMParser ) { // Standard\n                tmp = new DOMParser();\n                xml = tmp.parseFromString( data , \"text/xml\" );\n            } else { // IE\n                xml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n                xml.async = \"false\";\n                xml.loadXML( data );\n            }\n        } catch( e ) {\n            xml = undefined;\n        }\n        if ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n            jQuery.error( \"Invalid XML: \" + data );\n        }\n        return xml;\n    },\n\n    noop: function() {},\n\n    // Evaluates a script in a global context\n    // Workarounds based on findings by Jim Driscoll\n    // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n    globalEval: function( data ) {\n        if ( data && core_rnotwhite.test( data ) ) {\n            // We use execScript on Internet Explorer\n            // We use an anonymous function so that context is window\n            // rather than jQuery in Firefox\n            ( window.execScript || function( data ) {\n                window[ \"eval\" ].call( window, data );\n            } )( data );\n        }\n    },\n\n    // Convert dashed to camelCase; used by the css and data modules\n    // Microsoft forgot to hump their vendor prefix (#9572)\n    camelCase: function( string ) {\n        return string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n    },\n\n    nodeName: function( elem, name ) {\n        return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n    },\n\n    // args is for internal usage only\n    each: function( obj, callback, args ) {\n        var name,\n            i = 0,\n            length = obj.length,\n            isObj = length === undefined || jQuery.isFunction( obj );\n\n        if ( args ) {\n            if ( isObj ) {\n                for ( name in obj ) {\n                    if ( callback.apply( obj[ name ], args ) === false ) {\n                        break;\n                    }\n                }\n            } else {\n                for ( ; i < length; ) {\n                    if ( callback.apply( obj[ i++ ], args ) === false ) {\n                        break;\n                    }\n                }\n            }\n\n        // A special, fast, case for the most common use of each\n        } else {\n            if ( isObj ) {\n                for ( name in obj ) {\n                    if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {\n                        break;\n                    }\n                }\n            } else {\n                for ( ; i < length; ) {\n                    if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {\n                        break;\n                    }\n                }\n            }\n        }\n\n        return obj;\n    },\n\n    // Use native String.trim function wherever possible\n    trim: core_trim ?\n        function( text ) {\n            return text == null ?\n                \"\" :\n                core_trim.call( text );\n        } :\n\n        // Otherwise use our own trimming functionality\n        function( text ) {\n            return text == null ?\n                \"\" :\n                text.toString().replace( rtrim, \"\" );\n        },\n\n    // results is for internal usage only\n    makeArray: function( arr, results ) {\n        var type,\n            ret = results || [];\n\n        if ( arr != null ) {\n            // The window, strings (and functions) also have 'length'\n            // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n            type = jQuery.type( arr );\n\n            if ( arr.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( arr ) ) {\n                core_push.call( ret, arr );\n            } else {\n                jQuery.merge( ret, arr );\n            }\n        }\n\n        return ret;\n    },\n\n    inArray: function( elem, arr, i ) {\n        var len;\n\n        if ( arr ) {\n            if ( core_indexOf ) {\n                return core_indexOf.call( arr, elem, i );\n            }\n\n            len = arr.length;\n            i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n            for ( ; i < len; i++ ) {\n                // Skip accessing in sparse arrays\n                if ( i in arr && arr[ i ] === elem ) {\n                    return i;\n                }\n            }\n        }\n\n        return -1;\n    },\n\n    merge: function( first, second ) {\n        var l = second.length,\n            i = first.length,\n            j = 0;\n\n        if ( typeof l === \"number\" ) {\n            for ( ; j < l; j++ ) {\n                first[ i++ ] = second[ j ];\n            }\n\n        } else {\n            while ( second[j] !== undefined ) {\n                first[ i++ ] = second[ j++ ];\n            }\n        }\n\n        first.length = i;\n\n        return first;\n    },\n\n    grep: function( elems, callback, inv ) {\n        var retVal,\n            ret = [],\n            i = 0,\n            length = elems.length;\n        inv = !!inv;\n\n        // Go through the array, only saving the items\n        // that pass the validator function\n        for ( ; i < length; i++ ) {\n            retVal = !!callback( elems[ i ], i );\n            if ( inv !== retVal ) {\n                ret.push( elems[ i ] );\n            }\n        }\n\n        return ret;\n    },\n\n    // arg is for internal usage only\n    map: function( elems, callback, arg ) {\n        var value, key,\n            ret = [],\n            i = 0,\n            length = elems.length,\n            // jquery objects are treated as arrays\n            isArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n        // Go through the array, translating each of the items to their\n        if ( isArray ) {\n            for ( ; i < length; i++ ) {\n                value = callback( elems[ i ], i, arg );\n\n                if ( value != null ) {\n                    ret[ ret.length ] = value;\n                }\n            }\n\n        // Go through every key on the object,\n        } else {\n            for ( key in elems ) {\n                value = callback( elems[ key ], key, arg );\n\n                if ( value != null ) {\n                    ret[ ret.length ] = value;\n                }\n            }\n        }\n\n        // Flatten any nested arrays\n        return ret.concat.apply( [], ret );\n    },\n\n    // A global GUID counter for objects\n    guid: 1,\n\n    // Bind a function to a context, optionally partially applying any\n    // arguments.\n    proxy: function( fn, context ) {\n        var tmp, args, proxy;\n\n        if ( typeof context === \"string\" ) {\n            tmp = fn[ context ];\n            context = fn;\n            fn = tmp;\n        }\n\n        // Quick check to determine if target is callable, in the spec\n        // this throws a TypeError, but we will just return undefined.\n        if ( !jQuery.isFunction( fn ) ) {\n            return undefined;\n        }\n\n        // Simulated bind\n        args = core_slice.call( arguments, 2 );\n        proxy = function() {\n            return fn.apply( context, args.concat( core_slice.call( arguments ) ) );\n        };\n\n        // Set the guid of unique handler to the same of original handler, so it can be removed\n        proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n        return proxy;\n    },\n\n    // Multifunctional method to get and set values of a collection\n    // The value/s can optionally be executed if it's a function\n    access: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n        var exec,\n            bulk = key == null,\n            i = 0,\n            length = elems.length;\n\n        // Sets many values\n        if ( key && typeof key === \"object\" ) {\n            for ( i in key ) {\n                jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n            }\n            chainable = 1;\n\n        // Sets one value\n        } else if ( value !== undefined ) {\n            // Optionally, function values get executed if exec is true\n            exec = pass === undefined && jQuery.isFunction( value );\n\n            if ( bulk ) {\n                // Bulk operations only iterate when executing function values\n                if ( exec ) {\n                    exec = fn;\n                    fn = function( elem, key, value ) {\n                        return exec.call( jQuery( elem ), value );\n                    };\n\n                // Otherwise they run against the entire set\n                } else {\n                    fn.call( elems, value );\n                    fn = null;\n                }\n            }\n\n            if ( fn ) {\n                for (; i < length; i++ ) {\n                    fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n                }\n            }\n\n            chainable = 1;\n        }\n\n        return chainable ?\n            elems :\n\n            // Gets\n            bulk ?\n                fn.call( elems ) :\n                length ? fn( elems[0], key ) : emptyGet;\n    },\n\n    now: function() {\n        return ( new Date() ).getTime();\n    }\n});\n\njQuery.ready.promise = function( obj ) {\n    if ( !readyList ) {\n\n        readyList = jQuery.Deferred();\n\n        // Catch cases where $(document).ready() is called after the\n        // browser event has already occurred.\n        if ( document.readyState === \"complete\" || ( document.readyState !== \"loading\" && document.addEventListener ) ) {\n            // Handle it asynchronously to allow scripts the opportunity to delay ready\n            setTimeout( jQuery.ready, 1 );\n\n        // Standards-based browsers support DOMContentLoaded\n        } else if ( document.addEventListener ) {\n            // Use the handy event callback\n            document.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n            // A fallback to window.onload, that will always work\n            window.addEventListener( \"load\", jQuery.ready, false );\n\n        // If IE event model is used\n        } else {\n            // Ensure firing before onload, maybe late but safe also for iframes\n            document.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n            // A fallback to window.onload, that will always work\n            window.attachEvent( \"onload\", jQuery.ready );\n\n            // If IE and not a frame\n            // continually check to see if the document is ready\n            var top = false;\n\n            try {\n                top = window.frameElement == null && document.documentElement;\n            } catch(e) {}\n\n            if ( top && top.doScroll ) {\n                (function doScrollCheck() {\n                    if ( !jQuery.isReady ) {\n\n                        try {\n                            // Use the trick by Diego Perini\n                            // http://javascript.nwbox.com/IEContentLoaded/\n                            top.doScroll(\"left\");\n                        } catch(e) {\n                            return setTimeout( doScrollCheck, 50 );\n                        }\n\n                        // and execute any waiting functions\n                        jQuery.ready();\n                    }\n                })();\n            }\n        }\n    }\n    return readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n    class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n    var object = optionsCache[ options ] = {};\n    jQuery.each( options.split( core_rspace ), function( _, flag ) {\n        object[ flag ] = true;\n    });\n    return object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *  options: an optional list of space-separated options that will change how\n *          the callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *  once:           will ensure the callback list can only be fired once (like a Deferred)\n *\n *  memory:         will keep track of previous values and will call any callback added\n *                  after the list has been fired right away with the latest \"memorized\"\n *                  values (like a Deferred)\n *\n *  unique:         will ensure a callback can only be added once (no duplicate in the list)\n *\n *  stopOnFalse:    interrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n    // Convert options from String-formatted to Object-formatted if needed\n    // (we check in cache first)\n    options = typeof options === \"string\" ?\n        ( optionsCache[ options ] || createOptions( options ) ) :\n        jQuery.extend( {}, options );\n\n    var // Last fire value (for non-forgettable lists)\n        memory,\n        // Flag to know if list was already fired\n        fired,\n        // Flag to know if list is currently firing\n        firing,\n        // First callback to fire (used internally by add and fireWith)\n        firingStart,\n        // End of the loop when firing\n        firingLength,\n        // Index of currently firing callback (modified by remove if needed)\n        firingIndex,\n        // Actual callback list\n        list = [],\n        // Stack of fire calls for repeatable lists\n        stack = !options.once && [],\n        // Fire callbacks\n        fire = function( data ) {\n            memory = options.memory && data;\n            fired = true;\n            firingIndex = firingStart || 0;\n            firingStart = 0;\n            firingLength = list.length;\n            firing = true;\n            for ( ; list && firingIndex < firingLength; firingIndex++ ) {\n                if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n                    memory = false; // To prevent further calls using add\n                    break;\n                }\n            }\n            firing = false;\n            if ( list ) {\n                if ( stack ) {\n                    if ( stack.length ) {\n                        fire( stack.shift() );\n                    }\n                } else if ( memory ) {\n                    list = [];\n                } else {\n                    self.disable();\n                }\n            }\n        },\n        // Actual Callbacks object\n        self = {\n            // Add a callback or a collection of callbacks to the list\n            add: function() {\n                if ( list ) {\n                    // First, we save the current length\n                    var start = list.length;\n                    (function add( args ) {\n                        jQuery.each( args, function( _, arg ) {\n                            if ( jQuery.isFunction( arg ) && ( !options.unique || !self.has( arg ) ) ) {\n                                list.push( arg );\n                            } else if ( arg && arg.length ) {\n                                // Inspect recursively\n                                add( arg );\n                            }\n                        });\n                    })( arguments );\n                    // Do we need to add the callbacks to the\n                    // current firing batch?\n                    if ( firing ) {\n                        firingLength = list.length;\n                    // With memory, if we're not firing then\n                    // we should call right away\n                    } else if ( memory ) {\n                        firingStart = start;\n                        fire( memory );\n                    }\n                }\n                return this;\n            },\n            // Remove a callback from the list\n            remove: function() {\n                if ( list ) {\n                    jQuery.each( arguments, function( _, arg ) {\n                        var index;\n                        while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n                            list.splice( index, 1 );\n                            // Handle firing indexes\n                            if ( firing ) {\n                                if ( index <= firingLength ) {\n                                    firingLength--;\n                                }\n                                if ( index <= firingIndex ) {\n                                    firingIndex--;\n                                }\n                            }\n                        }\n                    });\n                }\n                return this;\n            },\n            // Control if a given callback is in the list\n            has: function( fn ) {\n                return jQuery.inArray( fn, list ) > -1;\n            },\n            // Remove all callbacks from the list\n            empty: function() {\n                list = [];\n                return this;\n            },\n            // Have the list do nothing anymore\n            disable: function() {\n                list = stack = memory = undefined;\n                return this;\n            },\n            // Is it disabled?\n            disabled: function() {\n                return !list;\n            },\n            // Lock the list in its current state\n            lock: function() {\n                stack = undefined;\n                if ( !memory ) {\n                    self.disable();\n                }\n                return this;\n            },\n            // Is it locked?\n            locked: function() {\n                return !stack;\n            },\n            // Call all callbacks with the given context and arguments\n            fireWith: function( context, args ) {\n                args = args || [];\n                args = [ context, args.slice ? args.slice() : args ];\n                if ( list && ( !fired || stack ) ) {\n                    if ( firing ) {\n                        stack.push( args );\n                    } else {\n                        fire( args );\n                    }\n                }\n                return this;\n            },\n            // Call all the callbacks with the given arguments\n            fire: function() {\n                self.fireWith( this, arguments );\n                return this;\n            },\n            // To know if the callbacks have already been called at least once\n            fired: function() {\n                return !!fired;\n            }\n        };\n\n    return self;\n};\njQuery.extend({\n\n    Deferred: function( func ) {\n        var tuples = [\n                // action, add listener, listener list, final state\n                [ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n                [ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n                [ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n            ],\n            state = \"pending\",\n            promise = {\n                state: function() {\n                    return state;\n                },\n                always: function() {\n                    deferred.done( arguments ).fail( arguments );\n                    return this;\n                },\n                then: function( /* fnDone, fnFail, fnProgress */ ) {\n                    var fns = arguments;\n                    return jQuery.Deferred(function( newDefer ) {\n                        jQuery.each( tuples, function( i, tuple ) {\n                            var action = tuple[ 0 ],\n                                fn = fns[ i ];\n                            // deferred[ done | fail | progress ] for forwarding actions to newDefer\n                            deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?\n                                function() {\n                                    var returned = fn.apply( this, arguments );\n                                    if ( returned && jQuery.isFunction( returned.promise ) ) {\n                                        returned.promise()\n                                            .done( newDefer.resolve )\n                                            .fail( newDefer.reject )\n                                            .progress( newDefer.notify );\n                                    } else {\n                                        newDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n                                    }\n                                } :\n                                newDefer[ action ]\n                            );\n                        });\n                        fns = null;\n                    }).promise();\n                },\n                // Get a promise for this deferred\n                // If obj is provided, the promise aspect is added to the object\n                promise: function( obj ) {\n                    return typeof obj === \"object\" ? jQuery.extend( obj, promise ) : promise;\n                }\n            },\n            deferred = {};\n\n        // Keep pipe for back-compat\n        promise.pipe = promise.then;\n\n        // Add list-specific methods\n        jQuery.each( tuples, function( i, tuple ) {\n            var list = tuple[ 2 ],\n                stateString = tuple[ 3 ];\n\n            // promise[ done | fail | progress ] = list.add\n            promise[ tuple[1] ] = list.add;\n\n            // Handle state\n            if ( stateString ) {\n                list.add(function() {\n                    // state = [ resolved | rejected ]\n                    state = stateString;\n\n                // [ reject_list | resolve_list ].disable; progress_list.lock\n                }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n            }\n\n            // deferred[ resolve | reject | notify ] = list.fire\n            deferred[ tuple[0] ] = list.fire;\n            deferred[ tuple[0] + \"With\" ] = list.fireWith;\n        });\n\n        // Make the deferred a promise\n        promise.promise( deferred );\n\n        // Call given func if any\n        if ( func ) {\n            func.call( deferred, deferred );\n        }\n\n        // All done!\n        return deferred;\n    },\n\n    // Deferred helper\n    when: function( subordinate /* , ..., subordinateN */ ) {\n        var i = 0,\n            resolveValues = core_slice.call( arguments ),\n            length = resolveValues.length,\n\n            // the count of uncompleted subordinates\n            remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n            // the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n            deferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n            // Update function for both resolve and progress values\n            updateFunc = function( i, contexts, values ) {\n                return function( value ) {\n                    contexts[ i ] = this;\n                    values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n                    if( values === progressValues ) {\n                        deferred.notifyWith( contexts, values );\n                    } else if ( !( --remaining ) ) {\n                        deferred.resolveWith( contexts, values );\n                    }\n                };\n            },\n\n            progressValues, progressContexts, resolveContexts;\n\n        // add listeners to Deferred subordinates; treat others as resolved\n        if ( length > 1 ) {\n            progressValues = new Array( length );\n            progressContexts = new Array( length );\n            resolveContexts = new Array( length );\n            for ( ; i < length; i++ ) {\n                if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n                    resolveValues[ i ].promise()\n                        .done( updateFunc( i, resolveContexts, resolveValues ) )\n                        .fail( deferred.reject )\n                        .progress( updateFunc( i, progressContexts, progressValues ) );\n                } else {\n                    --remaining;\n                }\n            }\n        }\n\n        // if we're not waiting on anything, resolve the master\n        if ( !remaining ) {\n            deferred.resolveWith( resolveContexts, resolveValues );\n        }\n\n        return deferred.promise();\n    }\n});\njQuery.support = (function() {\n\n    var support,\n        all,\n        a,\n        select,\n        opt,\n        input,\n        fragment,\n        eventName,\n        i,\n        isSupported,\n        clickFn,\n        div = document.createElement(\"div\");\n\n    // Preliminary tests\n    div.setAttribute( \"className\", \"t\" );\n    div.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n    all = div.getElementsByTagName(\"*\");\n    a = div.getElementsByTagName(\"a\")[ 0 ];\n    a.style.cssText = \"top:1px;float:left;opacity:.5\";\n\n    // Can't get basic test support\n    if ( !all || !all.length || !a ) {\n        return {};\n    }\n\n    // First batch of supports tests\n    select = document.createElement(\"select\");\n    opt = select.appendChild( document.createElement(\"option\") );\n    input = div.getElementsByTagName(\"input\")[ 0 ];\n\n    support = {\n        // IE strips leading whitespace when .innerHTML is used\n        leadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n        // Make sure that tbody elements aren't automatically inserted\n        // IE will insert them into empty tables\n        tbody: !div.getElementsByTagName(\"tbody\").length,\n\n        // Make sure that link elements get serialized correctly by innerHTML\n        // This requires a wrapper element in IE\n        htmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n        // Get the style information from getAttribute\n        // (IE uses .cssText instead)\n        style: /top/.test( a.getAttribute(\"style\") ),\n\n        // Make sure that URLs aren't manipulated\n        // (IE normalizes it by default)\n        hrefNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n        // Make sure that element opacity exists\n        // (IE uses filter instead)\n        // Use a regex to work around a WebKit issue. See #5145\n        opacity: /^0.5/.test( a.style.opacity ),\n\n        // Verify style float existence\n        // (IE uses styleFloat instead of cssFloat)\n        cssFloat: !!a.style.cssFloat,\n\n        // Make sure that if no value is specified for a checkbox\n        // that it defaults to \"on\".\n        // (WebKit defaults to \"\" instead)\n        checkOn: ( input.value === \"on\" ),\n\n        // Make sure that a selected-by-default option has a working selected property.\n        // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n        optSelected: opt.selected,\n\n        // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n        getSetAttribute: div.className !== \"t\",\n\n        // Tests for enctype support on a form(#6743)\n        enctype: !!document.createElement(\"form\").enctype,\n\n        // Makes sure cloning an html5 element does not cause problems\n        // Where outerHTML is undefined, this still works\n        html5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n        // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n        boxModel: ( document.compatMode === \"CSS1Compat\" ),\n\n        // Will be defined later\n        submitBubbles: true,\n        changeBubbles: true,\n        focusinBubbles: false,\n        deleteExpando: true,\n        noCloneEvent: true,\n        inlineBlockNeedsLayout: false,\n        shrinkWrapBlocks: false,\n        reliableMarginRight: true,\n        boxSizingReliable: true,\n        pixelPosition: false\n    };\n\n    // Make sure checked status is properly cloned\n    input.checked = true;\n    support.noCloneChecked = input.cloneNode( true ).checked;\n\n    // Make sure that the options inside disabled selects aren't marked as disabled\n    // (WebKit marks them as disabled)\n    select.disabled = true;\n    support.optDisabled = !opt.disabled;\n\n    // Test to see if it's possible to delete an expando from an element\n    // Fails in Internet Explorer\n    try {\n        delete div.test;\n    } catch( e ) {\n        support.deleteExpando = false;\n    }\n\n    if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n        div.attachEvent( \"onclick\", clickFn = function() {\n            // Cloning a node shouldn't copy over any\n            // bound event handlers (IE does this)\n            support.noCloneEvent = false;\n        });\n        div.cloneNode( true ).fireEvent(\"onclick\");\n        div.detachEvent( \"onclick\", clickFn );\n    }\n\n    // Check if a radio maintains its value\n    // after being appended to the DOM\n    input = document.createElement(\"input\");\n    input.value = \"t\";\n    input.setAttribute( \"type\", \"radio\" );\n    support.radioValue = input.value === \"t\";\n\n    input.setAttribute( \"checked\", \"checked\" );\n\n    // #11217 - WebKit loses check when the name is after the checked attribute\n    input.setAttribute( \"name\", \"t\" );\n\n    div.appendChild( input );\n    fragment = document.createDocumentFragment();\n    fragment.appendChild( div.lastChild );\n\n    // WebKit doesn't clone checked state correctly in fragments\n    support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n    // Check if a disconnected checkbox will retain its checked\n    // value of true after appended to the DOM (IE6/7)\n    support.appendChecked = input.checked;\n\n    fragment.removeChild( input );\n    fragment.appendChild( div );\n\n    // Technique from Juriy Zaytsev\n    // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n    // We only care about the case where non-standard event systems\n    // are used, namely in IE. Short-circuiting here helps us to\n    // avoid an eval call (in setAttribute) which can cause CSP\n    // to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n    if ( div.attachEvent ) {\n        for ( i in {\n            submit: true,\n            change: true,\n            focusin: true\n        }) {\n            eventName = \"on\" + i;\n            isSupported = ( eventName in div );\n            if ( !isSupported ) {\n                div.setAttribute( eventName, \"return;\" );\n                isSupported = ( typeof div[ eventName ] === \"function\" );\n            }\n            support[ i + \"Bubbles\" ] = isSupported;\n        }\n    }\n\n    // Run tests that need a body at doc ready\n    jQuery(function() {\n        var container, div, tds, marginDiv,\n            divReset = \"padding:0;margin:0;border:0;display:block;overflow:hidden;\",\n            body = document.getElementsByTagName(\"body\")[0];\n\n        if ( !body ) {\n            // Return for frameset docs that don't have a body\n            return;\n        }\n\n        container = document.createElement(\"div\");\n        container.style.cssText = \"visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px\";\n        body.insertBefore( container, body.firstChild );\n\n        // Construct the test element\n        div = document.createElement(\"div\");\n        container.appendChild( div );\n\n        // Check if table cells still have offsetWidth/Height when they are set\n        // to display:none and there are still other visible table cells in a\n        // table row; if so, offsetWidth/Height are not reliable for use when\n        // determining if an element has been hidden directly using\n        // display:none (it is still safe to use offsets if a parent element is\n        // hidden; don safety goggles and see bug #4512 for more information).\n        // (only IE 8 fails this test)\n        div.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n        tds = div.getElementsByTagName(\"td\");\n        tds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n        isSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n        tds[ 0 ].style.display = \"\";\n        tds[ 1 ].style.display = \"none\";\n\n        // Check if empty table cells still have offsetWidth/Height\n        // (IE <= 8 fail this test)\n        support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n        // Check box-sizing and margin behavior\n        div.innerHTML = \"\";\n        div.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n        support.boxSizing = ( div.offsetWidth === 4 );\n        support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n        // NOTE: To any future maintainer, window.getComputedStyle was used here\n        // instead of getComputedStyle because it gave a better gzip size.\n        // The difference between window.getComputedStyle and getComputedStyle is\n        // 7 bytes\n        if ( window.getComputedStyle ) {\n            support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n            support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n            // Check if div with explicit width and no margin-right incorrectly\n            // gets computed margin-right based on width of container. For more\n            // info see bug #3333\n            // Fails in WebKit before Feb 2011 nightlies\n            // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n            marginDiv = document.createElement(\"div\");\n            marginDiv.style.cssText = div.style.cssText = divReset;\n            marginDiv.style.marginRight = marginDiv.style.width = \"0\";\n            div.style.width = \"1px\";\n            div.appendChild( marginDiv );\n            support.reliableMarginRight =\n                !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n        }\n\n        if ( typeof div.style.zoom !== \"undefined\" ) {\n            // Check if natively block-level elements act like inline-block\n            // elements when setting their display to 'inline' and giving\n            // them layout\n            // (IE < 8 does this)\n            div.innerHTML = \"\";\n            div.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n            support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n            // Check if elements with layout shrink-wrap their children\n            // (IE 6 does this)\n            div.style.display = \"block\";\n            div.style.overflow = \"visible\";\n            div.innerHTML = \"<div></div>\";\n            div.firstChild.style.width = \"5px\";\n            support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n            container.style.zoom = 1;\n        }\n\n        // Null elements to avoid leaks in IE\n        body.removeChild( container );\n        container = div = tds = marginDiv = null;\n    });\n\n    // Null elements to avoid leaks in IE\n    fragment.removeChild( div );\n    all = a = select = opt = input = fragment = div = null;\n\n    return support;\n})();\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n    rmultiDash = /([A-Z])/g;\n\njQuery.extend({\n    cache: {},\n\n    deletedIds: [],\n\n    // Please use with caution\n    uuid: 0,\n\n    // Unique for each copy of jQuery on the page\n    // Non-digits removed to match rinlinejQuery\n    expando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n    // The following elements throw uncatchable exceptions if you\n    // attempt to add expando properties to them.\n    noData: {\n        \"embed\": true,\n        // Ban all objects except for Flash (which handle expandos)\n        \"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n        \"applet\": true\n    },\n\n    hasData: function( elem ) {\n        elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n        return !!elem && !isEmptyDataObject( elem );\n    },\n\n    data: function( elem, name, data, pvt /* Internal Use Only */ ) {\n        if ( !jQuery.acceptData( elem ) ) {\n            return;\n        }\n\n        var thisCache, ret,\n            internalKey = jQuery.expando,\n            getByName = typeof name === \"string\",\n\n            // We have to handle DOM nodes and JS objects differently because IE6-7\n            // can't GC object references properly across the DOM-JS boundary\n            isNode = elem.nodeType,\n\n            // Only DOM nodes need the global jQuery cache; JS object data is\n            // attached directly to the object so GC can occur automatically\n            cache = isNode ? jQuery.cache : elem,\n\n            // Only defining an ID for JS objects if its cache already exists allows\n            // the code to shortcut on the same path as a DOM node with no cache\n            id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n        // Avoid doing any more work than we need to when trying to get data on an\n        // object that has no data at all\n        if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n            return;\n        }\n\n        if ( !id ) {\n            // Only DOM nodes need a new unique ID for each element since their data\n            // ends up in the global cache\n            if ( isNode ) {\n                elem[ internalKey ] = id = jQuery.deletedIds.pop() || ++jQuery.uuid;\n            } else {\n                id = internalKey;\n            }\n        }\n\n        if ( !cache[ id ] ) {\n            cache[ id ] = {};\n\n            // Avoids exposing jQuery metadata on plain JS objects when the object\n            // is serialized using JSON.stringify\n            if ( !isNode ) {\n                cache[ id ].toJSON = jQuery.noop;\n            }\n        }\n\n        // An object can be passed to jQuery.data instead of a key/value pair; this gets\n        // shallow copied over onto the existing cache\n        if ( typeof name === \"object\" || typeof name === \"function\" ) {\n            if ( pvt ) {\n                cache[ id ] = jQuery.extend( cache[ id ], name );\n            } else {\n                cache[ id ].data = jQuery.extend( cache[ id ].data, name );\n            }\n        }\n\n        thisCache = cache[ id ];\n\n        // jQuery data() is stored in a separate object inside the object's internal data\n        // cache in order to avoid key collisions between internal data and user-defined\n        // data.\n        if ( !pvt ) {\n            if ( !thisCache.data ) {\n                thisCache.data = {};\n            }\n\n            thisCache = thisCache.data;\n        }\n\n        if ( data !== undefined ) {\n            thisCache[ jQuery.camelCase( name ) ] = data;\n        }\n\n        // Check for both converted-to-camel and non-converted data property names\n        // If a data property was specified\n        if ( getByName ) {\n\n            // First Try to find as-is property data\n            ret = thisCache[ name ];\n\n            // Test for null|undefined property data\n            if ( ret == null ) {\n\n                // Try to find the camelCased property\n                ret = thisCache[ jQuery.camelCase( name ) ];\n            }\n        } else {\n            ret = thisCache;\n        }\n\n        return ret;\n    },\n\n    removeData: function( elem, name, pvt /* Internal Use Only */ ) {\n        if ( !jQuery.acceptData( elem ) ) {\n            return;\n        }\n\n        var thisCache, i, l,\n\n            isNode = elem.nodeType,\n\n            // See jQuery.data for more information\n            cache = isNode ? jQuery.cache : elem,\n            id = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n        // If there is already no cache entry for this object, there is no\n        // purpose in continuing\n        if ( !cache[ id ] ) {\n            return;\n        }\n\n        if ( name ) {\n\n            thisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n            if ( thisCache ) {\n\n                // Support array or space separated string names for data keys\n                if ( !jQuery.isArray( name ) ) {\n\n                    // try the string as a key before any manipulation\n                    if ( name in thisCache ) {\n                        name = [ name ];\n                    } else {\n\n                        // split the camel cased version by spaces unless a key with the spaces exists\n                        name = jQuery.camelCase( name );\n                        if ( name in thisCache ) {\n                            name = [ name ];\n                        } else {\n                            name = name.split(\" \");\n                        }\n                    }\n                }\n\n                for ( i = 0, l = name.length; i < l; i++ ) {\n                    delete thisCache[ name[i] ];\n                }\n\n                // If there is no data left in the cache, we want to continue\n                // and let the cache object itself get destroyed\n                if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n                    return;\n                }\n            }\n        }\n\n        // See jQuery.data for more information\n        if ( !pvt ) {\n            delete cache[ id ].data;\n\n            // Don't destroy the parent cache unless the internal data object\n            // had been the only thing left in it\n            if ( !isEmptyDataObject( cache[ id ] ) ) {\n                return;\n            }\n        }\n\n        // Destroy the cache\n        if ( isNode ) {\n            jQuery.cleanData( [ elem ], true );\n\n        // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n        } else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n            delete cache[ id ];\n\n        // When all else fails, null\n        } else {\n            cache[ id ] = null;\n        }\n    },\n\n    // For internal use only.\n    _data: function( elem, name, data ) {\n        return jQuery.data( elem, name, data, true );\n    },\n\n    // A method for determining if a DOM node can handle the data expando\n    acceptData: function( elem ) {\n        var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n        // nodes accept data unless otherwise specified; rejection can be conditional\n        return !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n    }\n});\n\njQuery.fn.extend({\n    data: function( key, value ) {\n        var parts, part, attr, name, l,\n            elem = this[0],\n            i = 0,\n            data = null;\n\n        // Gets all values\n        if ( key === undefined ) {\n            if ( this.length ) {\n                data = jQuery.data( elem );\n\n                if ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n                    attr = elem.attributes;\n                    for ( l = attr.length; i < l; i++ ) {\n                        name = attr[i].name;\n\n                        if ( name.indexOf( \"data-\" ) === 0 ) {\n                            name = jQuery.camelCase( name.substring(5) );\n\n                            dataAttr( elem, name, data[ name ] );\n                        }\n                    }\n                    jQuery._data( elem, \"parsedAttrs\", true );\n                }\n            }\n\n            return data;\n        }\n\n        // Sets multiple values\n        if ( typeof key === \"object\" ) {\n            return this.each(function() {\n                jQuery.data( this, key );\n            });\n        }\n\n        parts = key.split( \".\", 2 );\n        parts[1] = parts[1] ? \".\" + parts[1] : \"\";\n        part = parts[1] + \"!\";\n\n        return jQuery.access( this, function( value ) {\n\n            if ( value === undefined ) {\n                data = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n                // Try to fetch any internally stored data first\n                if ( data === undefined && elem ) {\n                    data = jQuery.data( elem, key );\n                    data = dataAttr( elem, key, data );\n                }\n\n                return data === undefined && parts[1] ?\n                    this.data( parts[0] ) :\n                    data;\n            }\n\n            parts[1] = value;\n            this.each(function() {\n                var self = jQuery( this );\n\n                self.triggerHandler( \"setData\" + part, parts );\n                jQuery.data( this, key, value );\n                self.triggerHandler( \"changeData\" + part, parts );\n            });\n        }, null, value, arguments.length > 1, null, false );\n    },\n\n    removeData: function( key ) {\n        return this.each(function() {\n            jQuery.removeData( this, key );\n        });\n    }\n});\n\nfunction dataAttr( elem, key, data ) {\n    // If nothing was found internally, try to fetch any\n    // data from the HTML5 data-* attribute\n    if ( data === undefined && elem.nodeType === 1 ) {\n\n        var name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n        data = elem.getAttribute( name );\n\n        if ( typeof data === \"string\" ) {\n            try {\n                data = data === \"true\" ? true :\n                data === \"false\" ? false :\n                data === \"null\" ? null :\n                // Only convert to a number if it doesn't change the string\n                +data + \"\" === data ? +data :\n                rbrace.test( data ) ? jQuery.parseJSON( data ) :\n                    data;\n            } catch( e ) {}\n\n            // Make sure we set the data so it isn't changed later\n            jQuery.data( elem, key, data );\n\n        } else {\n            data = undefined;\n        }\n    }\n\n    return data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n    var name;\n    for ( name in obj ) {\n\n        // if the public data object is empty, the private is still empty\n        if ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n            continue;\n        }\n        if ( name !== \"toJSON\" ) {\n            return false;\n        }\n    }\n\n    return true;\n}\njQuery.extend({\n    queue: function( elem, type, data ) {\n        var queue;\n\n        if ( elem ) {\n            type = ( type || \"fx\" ) + \"queue\";\n            queue = jQuery._data( elem, type );\n\n            // Speed up dequeue by getting out quickly if this is just a lookup\n            if ( data ) {\n                if ( !queue || jQuery.isArray(data) ) {\n                    queue = jQuery._data( elem, type, jQuery.makeArray(data) );\n                } else {\n                    queue.push( data );\n                }\n            }\n            return queue || [];\n        }\n    },\n\n    dequeue: function( elem, type ) {\n        type = type || \"fx\";\n\n        var queue = jQuery.queue( elem, type ),\n            fn = queue.shift(),\n            hooks = jQuery._queueHooks( elem, type ),\n            next = function() {\n                jQuery.dequeue( elem, type );\n            };\n\n        // If the fx queue is dequeued, always remove the progress sentinel\n        if ( fn === \"inprogress\" ) {\n            fn = queue.shift();\n        }\n\n        if ( fn ) {\n\n            // Add a progress sentinel to prevent the fx queue from being\n            // automatically dequeued\n            if ( type === \"fx\" ) {\n                queue.unshift( \"inprogress\" );\n            }\n\n            // clear up the last queue stop function\n            delete hooks.stop;\n            fn.call( elem, next, hooks );\n        }\n        if ( !queue.length && hooks ) {\n            hooks.empty.fire();\n        }\n    },\n\n    // not intended for public consumption - generates a queueHooks object, or returns the current one\n    _queueHooks: function( elem, type ) {\n        var key = type + \"queueHooks\";\n        return jQuery._data( elem, key ) || jQuery._data( elem, key, {\n            empty: jQuery.Callbacks(\"once memory\").add(function() {\n                jQuery.removeData( elem, type + \"queue\", true );\n                jQuery.removeData( elem, key, true );\n            })\n        });\n    }\n});\n\njQuery.fn.extend({\n    queue: function( type, data ) {\n        var setter = 2;\n\n        if ( typeof type !== \"string\" ) {\n            data = type;\n            type = \"fx\";\n            setter--;\n        }\n\n        if ( arguments.length < setter ) {\n            return jQuery.queue( this[0], type );\n        }\n\n        return data === undefined ?\n            this :\n            this.each(function() {\n                var queue = jQuery.queue( this, type, data );\n\n                // ensure a hooks for this queue\n                jQuery._queueHooks( this, type );\n\n                if ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n                    jQuery.dequeue( this, type );\n                }\n            });\n    },\n    dequeue: function( type ) {\n        return this.each(function() {\n            jQuery.dequeue( this, type );\n        });\n    },\n    // Based off of the plugin by Clint Helfers, with permission.\n    // http://blindsignals.com/index.php/2009/07/jquery-delay/\n    delay: function( time, type ) {\n        time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n        type = type || \"fx\";\n\n        return this.queue( type, function( next, hooks ) {\n            var timeout = setTimeout( next, time );\n            hooks.stop = function() {\n                clearTimeout( timeout );\n            };\n        });\n    },\n    clearQueue: function( type ) {\n        return this.queue( type || \"fx\", [] );\n    },\n    // Get a promise resolved when queues of a certain type\n    // are emptied (fx is the type by default)\n    promise: function( type, obj ) {\n        var tmp,\n            count = 1,\n            defer = jQuery.Deferred(),\n            elements = this,\n            i = this.length,\n            resolve = function() {\n                if ( !( --count ) ) {\n                    defer.resolveWith( elements, [ elements ] );\n                }\n            };\n\n        if ( typeof type !== \"string\" ) {\n            obj = type;\n            type = undefined;\n        }\n        type = type || \"fx\";\n\n        while( i-- ) {\n            if ( (tmp = jQuery._data( elements[ i ], type + \"queueHooks\" )) && tmp.empty ) {\n                count++;\n                tmp.empty.add( resolve );\n            }\n        }\n        resolve();\n        return defer.promise( obj );\n    }\n});\nvar nodeHook, boolHook, fixSpecified,\n    rclass = /[\\t\\r\\n]/g,\n    rreturn = /\\r/g,\n    rtype = /^(?:button|input)$/i,\n    rfocusable = /^(?:button|input|object|select|textarea)$/i,\n    rclickable = /^a(?:rea|)$/i,\n    rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n    getSetAttribute = jQuery.support.getSetAttribute;\n\njQuery.fn.extend({\n    attr: function( name, value ) {\n        return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n    },\n\n    removeAttr: function( name ) {\n        return this.each(function() {\n            jQuery.removeAttr( this, name );\n        });\n    },\n\n    prop: function( name, value ) {\n        return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n    },\n\n    removeProp: function( name ) {\n        name = jQuery.propFix[ name ] || name;\n        return this.each(function() {\n            // try/catch handles cases where IE balks (such as removing a property on window)\n            try {\n                this[ name ] = undefined;\n                delete this[ name ];\n            } catch( e ) {}\n        });\n    },\n\n    addClass: function( value ) {\n        var classNames, i, l, elem,\n            setClass, c, cl;\n\n        if ( jQuery.isFunction( value ) ) {\n            return this.each(function( j ) {\n                jQuery( this ).addClass( value.call(this, j, this.className) );\n            });\n        }\n\n        if ( value && typeof value === \"string\" ) {\n            classNames = value.split( core_rspace );\n\n            for ( i = 0, l = this.length; i < l; i++ ) {\n                elem = this[ i ];\n\n                if ( elem.nodeType === 1 ) {\n                    if ( !elem.className && classNames.length === 1 ) {\n                        elem.className = value;\n\n                    } else {\n                        setClass = \" \" + elem.className + \" \";\n\n                        for ( c = 0, cl = classNames.length; c < cl; c++ ) {\n                            if ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n                                setClass += classNames[ c ] + \" \";\n                            }\n                        }\n                        elem.className = jQuery.trim( setClass );\n                    }\n                }\n            }\n        }\n\n        return this;\n    },\n\n    removeClass: function( value ) {\n        var removes, className, elem, c, cl, i, l;\n\n        if ( jQuery.isFunction( value ) ) {\n            return this.each(function( j ) {\n                jQuery( this ).removeClass( value.call(this, j, this.className) );\n            });\n        }\n        if ( (value && typeof value === \"string\") || value === undefined ) {\n            removes = ( value || \"\" ).split( core_rspace );\n\n            for ( i = 0, l = this.length; i < l; i++ ) {\n                elem = this[ i ];\n                if ( elem.nodeType === 1 && elem.className ) {\n\n                    className = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\n                    // loop over each item in the removal list\n                    for ( c = 0, cl = removes.length; c < cl; c++ ) {\n                        // Remove until there is nothing to remove,\n                        while ( className.indexOf(\" \" + removes[ c ] + \" \") > -1 ) {\n                            className = className.replace( \" \" + removes[ c ] + \" \" , \" \" );\n                        }\n                    }\n                    elem.className = value ? jQuery.trim( className ) : \"\";\n                }\n            }\n        }\n\n        return this;\n    },\n\n    toggleClass: function( value, stateVal ) {\n        var type = typeof value,\n            isBool = typeof stateVal === \"boolean\";\n\n        if ( jQuery.isFunction( value ) ) {\n            return this.each(function( i ) {\n                jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n            });\n        }\n\n        return this.each(function() {\n            if ( type === \"string\" ) {\n                // toggle individual class names\n                var className,\n                    i = 0,\n                    self = jQuery( this ),\n                    state = stateVal,\n                    classNames = value.split( core_rspace );\n\n                while ( (className = classNames[ i++ ]) ) {\n                    // check each className given, space separated list\n                    state = isBool ? state : !self.hasClass( className );\n                    self[ state ? \"addClass\" : \"removeClass\" ]( className );\n                }\n\n            } else if ( type === \"undefined\" || type === \"boolean\" ) {\n                if ( this.className ) {\n                    // store className if set\n                    jQuery._data( this, \"__className__\", this.className );\n                }\n\n                // toggle whole className\n                this.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n            }\n        });\n    },\n\n    hasClass: function( selector ) {\n        var className = \" \" + selector + \" \",\n            i = 0,\n            l = this.length;\n        for ( ; i < l; i++ ) {\n            if ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n                return true;\n            }\n        }\n\n        return false;\n    },\n\n    val: function( value ) {\n        var hooks, ret, isFunction,\n            elem = this[0];\n\n        if ( !arguments.length ) {\n            if ( elem ) {\n                hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n                if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n                    return ret;\n                }\n\n                ret = elem.value;\n\n                return typeof ret === \"string\" ?\n                    // handle most common string cases\n                    ret.replace(rreturn, \"\") :\n                    // handle cases where value is null/undef or number\n                    ret == null ? \"\" : ret;\n            }\n\n            return;\n        }\n\n        isFunction = jQuery.isFunction( value );\n\n        return this.each(function( i ) {\n            var val,\n                self = jQuery(this);\n\n            if ( this.nodeType !== 1 ) {\n                return;\n            }\n\n            if ( isFunction ) {\n                val = value.call( this, i, self.val() );\n            } else {\n                val = value;\n            }\n\n            // Treat null/undefined as \"\"; convert numbers to string\n            if ( val == null ) {\n                val = \"\";\n            } else if ( typeof val === \"number\" ) {\n                val += \"\";\n            } else if ( jQuery.isArray( val ) ) {\n                val = jQuery.map(val, function ( value ) {\n                    return value == null ? \"\" : value + \"\";\n                });\n            }\n\n            hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n            // If set returns undefined, fall back to normal setting\n            if ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n                this.value = val;\n            }\n        });\n    }\n});\n\njQuery.extend({\n    valHooks: {\n        option: {\n            get: function( elem ) {\n                // attributes.value is undefined in Blackberry 4.7 but\n                // uses .value. See #6932\n                var val = elem.attributes.value;\n                return !val || val.specified ? elem.value : elem.text;\n            }\n        },\n        select: {\n            get: function( elem ) {\n                var value, i, max, option,\n                    index = elem.selectedIndex,\n                    values = [],\n                    options = elem.options,\n                    one = elem.type === \"select-one\";\n\n                // Nothing was selected\n                if ( index < 0 ) {\n                    return null;\n                }\n\n                // Loop through all the selected options\n                i = one ? index : 0;\n                max = one ? index + 1 : options.length;\n                for ( ; i < max; i++ ) {\n                    option = options[ i ];\n\n                    // Don't return options that are disabled or in a disabled optgroup\n                    if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n                            (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n                        // Get the specific value for the option\n                        value = jQuery( option ).val();\n\n                        // We don't need an array for one selects\n                        if ( one ) {\n                            return value;\n                        }\n\n                        // Multi-Selects return an array\n                        values.push( value );\n                    }\n                }\n\n                // Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n                if ( one && !values.length && options.length ) {\n                    return jQuery( options[ index ] ).val();\n                }\n\n                return values;\n            },\n\n            set: function( elem, value ) {\n                var values = jQuery.makeArray( value );\n\n                jQuery(elem).find(\"option\").each(function() {\n                    this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n                });\n\n                if ( !values.length ) {\n                    elem.selectedIndex = -1;\n                }\n                return values;\n            }\n        }\n    },\n\n    // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9\n    attrFn: {},\n\n    attr: function( elem, name, value, pass ) {\n        var ret, hooks, notxml,\n            nType = elem.nodeType;\n\n        // don't get/set attributes on text, comment and attribute nodes\n        if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n            return;\n        }\n\n        if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {\n            return jQuery( elem )[ name ]( value );\n        }\n\n        // Fallback to prop when attributes are not supported\n        if ( typeof elem.getAttribute === \"undefined\" ) {\n            return jQuery.prop( elem, name, value );\n        }\n\n        notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n        // All attributes are lowercase\n        // Grab necessary hook if one is defined\n        if ( notxml ) {\n            name = name.toLowerCase();\n            hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n        }\n\n        if ( value !== undefined ) {\n\n            if ( value === null ) {\n                jQuery.removeAttr( elem, name );\n                return;\n\n            } else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n                return ret;\n\n            } else {\n                elem.setAttribute( name, \"\" + value );\n                return value;\n            }\n\n        } else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n            return ret;\n\n        } else {\n\n            ret = elem.getAttribute( name );\n\n            // Non-existent attributes return null, we normalize to undefined\n            return ret === null ?\n                undefined :\n                ret;\n        }\n    },\n\n    removeAttr: function( elem, value ) {\n        var propName, attrNames, name, isBool,\n            i = 0;\n\n        if ( value && elem.nodeType === 1 ) {\n\n            attrNames = value.split( core_rspace );\n\n            for ( ; i < attrNames.length; i++ ) {\n                name = attrNames[ i ];\n\n                if ( name ) {\n                    propName = jQuery.propFix[ name ] || name;\n                    isBool = rboolean.test( name );\n\n                    // See #9699 for explanation of this approach (setting first, then removal)\n                    // Do not do this for boolean attributes (see #10870)\n                    if ( !isBool ) {\n                        jQuery.attr( elem, name, \"\" );\n                    }\n                    elem.removeAttribute( getSetAttribute ? name : propName );\n\n                    // Set corresponding property to false for boolean attributes\n                    if ( isBool && propName in elem ) {\n                        elem[ propName ] = false;\n                    }\n                }\n            }\n        }\n    },\n\n    attrHooks: {\n        type: {\n            set: function( elem, value ) {\n                // We can't allow the type property to be changed (since it causes problems in IE)\n                if ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n                    jQuery.error( \"type property can't be changed\" );\n                } else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n                    // Setting the type on a radio button after the value resets the value in IE6-9\n                    // Reset value to it's default in case type is set after value\n                    // This is for element creation\n                    var val = elem.value;\n                    elem.setAttribute( \"type\", value );\n                    if ( val ) {\n                        elem.value = val;\n                    }\n                    return value;\n                }\n            }\n        },\n        // Use the value property for back compat\n        // Use the nodeHook for button elements in IE6/7 (#1954)\n        value: {\n            get: function( elem, name ) {\n                if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n                    return nodeHook.get( elem, name );\n                }\n                return name in elem ?\n                    elem.value :\n                    null;\n            },\n            set: function( elem, value, name ) {\n                if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n                    return nodeHook.set( elem, value, name );\n                }\n                // Does not return so that setAttribute is also used\n                elem.value = value;\n            }\n        }\n    },\n\n    propFix: {\n        tabindex: \"tabIndex\",\n        readonly: \"readOnly\",\n        \"for\": \"htmlFor\",\n        \"class\": \"className\",\n        maxlength: \"maxLength\",\n        cellspacing: \"cellSpacing\",\n        cellpadding: \"cellPadding\",\n        rowspan: \"rowSpan\",\n        colspan: \"colSpan\",\n        usemap: \"useMap\",\n        frameborder: \"frameBorder\",\n        contenteditable: \"contentEditable\"\n    },\n\n    prop: function( elem, name, value ) {\n        var ret, hooks, notxml,\n            nType = elem.nodeType;\n\n        // don't get/set properties on text, comment and attribute nodes\n        if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n            return;\n        }\n\n        notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n        if ( notxml ) {\n            // Fix name and attach hooks\n            name = jQuery.propFix[ name ] || name;\n            hooks = jQuery.propHooks[ name ];\n        }\n\n        if ( value !== undefined ) {\n            if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n                return ret;\n\n            } else {\n                return ( elem[ name ] = value );\n            }\n\n        } else {\n            if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n                return ret;\n\n            } else {\n                return elem[ name ];\n            }\n        }\n    },\n\n    propHooks: {\n        tabIndex: {\n            get: function( elem ) {\n                // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n                // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n                var attributeNode = elem.getAttributeNode(\"tabindex\");\n\n                return attributeNode && attributeNode.specified ?\n                    parseInt( attributeNode.value, 10 ) :\n                    rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n                        0 :\n                        undefined;\n            }\n        }\n    }\n});\n\n// Hook for boolean attributes\nboolHook = {\n    get: function( elem, name ) {\n        // Align boolean attributes with corresponding properties\n        // Fall back to attribute presence where some booleans are not supported\n        var attrNode,\n            property = jQuery.prop( elem, name );\n        return property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n            name.toLowerCase() :\n            undefined;\n    },\n    set: function( elem, value, name ) {\n        var propName;\n        if ( value === false ) {\n            // Remove boolean attributes when set to false\n            jQuery.removeAttr( elem, name );\n        } else {\n            // value is true since we know at this point it's type boolean and not false\n            // Set boolean attributes to the same name and set the DOM property\n            propName = jQuery.propFix[ name ] || name;\n            if ( propName in elem ) {\n                // Only set the IDL specifically if it already exists on the element\n                elem[ propName ] = true;\n            }\n\n            elem.setAttribute( name, name.toLowerCase() );\n        }\n        return name;\n    }\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n    fixSpecified = {\n        name: true,\n        id: true,\n        coords: true\n    };\n\n    // Use this for any attribute in IE6/7\n    // This fixes almost every IE6/7 issue\n    nodeHook = jQuery.valHooks.button = {\n        get: function( elem, name ) {\n            var ret;\n            ret = elem.getAttributeNode( name );\n            return ret && ( fixSpecified[ name ] ? ret.value !== \"\" : ret.specified ) ?\n                ret.value :\n                undefined;\n        },\n        set: function( elem, value, name ) {\n            // Set the existing or create a new attribute node\n            var ret = elem.getAttributeNode( name );\n            if ( !ret ) {\n                ret = document.createAttribute( name );\n                elem.setAttributeNode( ret );\n            }\n            return ( ret.value = value + \"\" );\n        }\n    };\n\n    // Set width and height to auto instead of 0 on empty string( Bug #8150 )\n    // This is for removals\n    jQuery.each([ \"width\", \"height\" ], function( i, name ) {\n        jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n            set: function( elem, value ) {\n                if ( value === \"\" ) {\n                    elem.setAttribute( name, \"auto\" );\n                    return value;\n                }\n            }\n        });\n    });\n\n    // Set contenteditable to false on removals(#10429)\n    // Setting to empty string throws an error as an invalid value\n    jQuery.attrHooks.contenteditable = {\n        get: nodeHook.get,\n        set: function( elem, value, name ) {\n            if ( value === \"\" ) {\n                value = \"false\";\n            }\n            nodeHook.set( elem, value, name );\n        }\n    };\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n    jQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n        jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n            get: function( elem ) {\n                var ret = elem.getAttribute( name, 2 );\n                return ret === null ? undefined : ret;\n            }\n        });\n    });\n}\n\nif ( !jQuery.support.style ) {\n    jQuery.attrHooks.style = {\n        get: function( elem ) {\n            // Return undefined in the case of empty string\n            // Normalize to lowercase since IE uppercases css property names\n            return elem.style.cssText.toLowerCase() || undefined;\n        },\n        set: function( elem, value ) {\n            return ( elem.style.cssText = \"\" + value );\n        }\n    };\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n    jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n        get: function( elem ) {\n            var parent = elem.parentNode;\n\n            if ( parent ) {\n                parent.selectedIndex;\n\n                // Make sure that it also works with optgroups, see #5701\n                if ( parent.parentNode ) {\n                    parent.parentNode.selectedIndex;\n                }\n            }\n            return null;\n        }\n    });\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n    jQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n    jQuery.each([ \"radio\", \"checkbox\" ], function() {\n        jQuery.valHooks[ this ] = {\n            get: function( elem ) {\n                // Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n                return elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n            }\n        };\n    });\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n    jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n        set: function( elem, value ) {\n            if ( jQuery.isArray( value ) ) {\n                return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n            }\n        }\n    });\n});\nvar rformElems = /^(?:textarea|input|select)$/i,\n    rtypenamespace = /^([^\\.]*|)(?:\\.(.+)|)$/,\n    rhoverHack = /(?:^|\\s)hover(\\.\\S+|)\\b/,\n    rkeyEvent = /^key/,\n    rmouseEvent = /^(?:mouse|contextmenu)|click/,\n    rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n    hoverHack = function( events ) {\n        return jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n    };\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n    add: function( elem, types, handler, data, selector ) {\n\n        var elemData, eventHandle, events,\n            t, tns, type, namespaces, handleObj,\n            handleObjIn, handlers, special;\n\n        // Don't attach events to noData or text/comment nodes (allow plain objects tho)\n        if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n            return;\n        }\n\n        // Caller can pass in an object of custom data in lieu of the handler\n        if ( handler.handler ) {\n            handleObjIn = handler;\n            handler = handleObjIn.handler;\n            selector = handleObjIn.selector;\n        }\n\n        // Make sure that the handler has a unique ID, used to find/remove it later\n        if ( !handler.guid ) {\n            handler.guid = jQuery.guid++;\n        }\n\n        // Init the element's event structure and main handler, if this is the first\n        events = elemData.events;\n        if ( !events ) {\n            elemData.events = events = {};\n        }\n        eventHandle = elemData.handle;\n        if ( !eventHandle ) {\n            elemData.handle = eventHandle = function( e ) {\n                // Discard the second event of a jQuery.event.trigger() and\n                // when an event is called after a page has unloaded\n                return typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n                    jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n                    undefined;\n            };\n            // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n            eventHandle.elem = elem;\n        }\n\n        // Handle multiple events separated by a space\n        // jQuery(...).bind(\"mouseover mouseout\", fn);\n        types = jQuery.trim( hoverHack(types) ).split( \" \" );\n        for ( t = 0; t < types.length; t++ ) {\n\n            tns = rtypenamespace.exec( types[t] ) || [];\n            type = tns[1];\n            namespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n            // If event changes its type, use the special event handlers for the changed type\n            special = jQuery.event.special[ type ] || {};\n\n            // If selector defined, determine special event api type, otherwise given type\n            type = ( selector ? special.delegateType : special.bindType ) || type;\n\n            // Update special based on newly reset type\n            special = jQuery.event.special[ type ] || {};\n\n            // handleObj is passed to all event handlers\n            handleObj = jQuery.extend({\n                type: type,\n                origType: tns[1],\n                data: data,\n                handler: handler,\n                guid: handler.guid,\n                selector: selector,\n                namespace: namespaces.join(\".\")\n            }, handleObjIn );\n\n            // Init the event handler queue if we're the first\n            handlers = events[ type ];\n            if ( !handlers ) {\n                handlers = events[ type ] = [];\n                handlers.delegateCount = 0;\n\n                // Only use addEventListener/attachEvent if the special events handler returns false\n                if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n                    // Bind the global event handler to the element\n                    if ( elem.addEventListener ) {\n                        elem.addEventListener( type, eventHandle, false );\n\n                    } else if ( elem.attachEvent ) {\n                        elem.attachEvent( \"on\" + type, eventHandle );\n                    }\n                }\n            }\n\n            if ( special.add ) {\n                special.add.call( elem, handleObj );\n\n                if ( !handleObj.handler.guid ) {\n                    handleObj.handler.guid = handler.guid;\n                }\n            }\n\n            // Add to the element's handler list, delegates in front\n            if ( selector ) {\n                handlers.splice( handlers.delegateCount++, 0, handleObj );\n            } else {\n                handlers.push( handleObj );\n            }\n\n            // Keep track of which events have ever been used, for event optimization\n            jQuery.event.global[ type ] = true;\n        }\n\n        // Nullify elem to prevent memory leaks in IE\n        elem = null;\n    },\n\n    global: {},\n\n    // Detach an event or set of events from an element\n    remove: function( elem, types, handler, selector, mappedTypes ) {\n\n        var t, tns, type, origType, namespaces, origCount,\n            j, events, special, eventType, handleObj,\n            elemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n        if ( !elemData || !(events = elemData.events) ) {\n            return;\n        }\n\n        // Once for each type.namespace in types; type may be omitted\n        types = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n        for ( t = 0; t < types.length; t++ ) {\n            tns = rtypenamespace.exec( types[t] ) || [];\n            type = origType = tns[1];\n            namespaces = tns[2];\n\n            // Unbind all events (on this namespace, if provided) for the element\n            if ( !type ) {\n                for ( type in events ) {\n                    jQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n                }\n                continue;\n            }\n\n            special = jQuery.event.special[ type ] || {};\n            type = ( selector? special.delegateType : special.bindType ) || type;\n            eventType = events[ type ] || [];\n            origCount = eventType.length;\n            namespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null;\n\n            // Remove matching events\n            for ( j = 0; j < eventType.length; j++ ) {\n                handleObj = eventType[ j ];\n\n                if ( ( mappedTypes || origType === handleObj.origType ) &&\n                     ( !handler || handler.guid === handleObj.guid ) &&\n                     ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n                     ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n                    eventType.splice( j--, 1 );\n\n                    if ( handleObj.selector ) {\n                        eventType.delegateCount--;\n                    }\n                    if ( special.remove ) {\n                        special.remove.call( elem, handleObj );\n                    }\n                }\n            }\n\n            // Remove generic event handler if we removed something and no more handlers exist\n            // (avoids potential for endless recursion during removal of special event handlers)\n            if ( eventType.length === 0 && origCount !== eventType.length ) {\n                if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n                    jQuery.removeEvent( elem, type, elemData.handle );\n                }\n\n                delete events[ type ];\n            }\n        }\n\n        // Remove the expando if it's no longer used\n        if ( jQuery.isEmptyObject( events ) ) {\n            delete elemData.handle;\n\n            // removeData also checks for emptiness and clears the expando if empty\n            // so use it instead of delete\n            jQuery.removeData( elem, \"events\", true );\n        }\n    },\n\n    // Events that are safe to short-circuit if no handlers are attached.\n    // Native DOM events should not be added, they may have inline handlers.\n    customEvent: {\n        \"getData\": true,\n        \"setData\": true,\n        \"changeData\": true\n    },\n\n    trigger: function( event, data, elem, onlyHandlers ) {\n        // Don't do events on text and comment nodes\n        if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n            return;\n        }\n\n        // Event object or event type\n        var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,\n            type = event.type || event,\n            namespaces = [];\n\n        // focus/blur morphs to focusin/out; ensure we're not firing them right now\n        if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n            return;\n        }\n\n        if ( type.indexOf( \"!\" ) >= 0 ) {\n            // Exclusive events trigger only for the exact event (no namespaces)\n            type = type.slice(0, -1);\n            exclusive = true;\n        }\n\n        if ( type.indexOf( \".\" ) >= 0 ) {\n            // Namespaced trigger; create a regexp to match event type in handle()\n            namespaces = type.split(\".\");\n            type = namespaces.shift();\n            namespaces.sort();\n        }\n\n        if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n            // No jQuery handlers for this event type, and it can't have inline handlers\n            return;\n        }\n\n        // Caller can pass in an Event, Object, or just an event type string\n        event = typeof event === \"object\" ?\n            // jQuery.Event object\n            event[ jQuery.expando ] ? event :\n            // Object literal\n            new jQuery.Event( type, event ) :\n            // Just the event type (string)\n            new jQuery.Event( type );\n\n        event.type = type;\n        event.isTrigger = true;\n        event.exclusive = exclusive;\n        event.namespace = namespaces.join( \".\" );\n        event.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null;\n        ontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n        // Handle a global trigger\n        if ( !elem ) {\n\n            // TODO: Stop taunting the data cache; remove global events and always attach to document\n            cache = jQuery.cache;\n            for ( i in cache ) {\n                if ( cache[ i ].events && cache[ i ].events[ type ] ) {\n                    jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n                }\n            }\n            return;\n        }\n\n        // Clean up the event in case it is being reused\n        event.result = undefined;\n        if ( !event.target ) {\n            event.target = elem;\n        }\n\n        // Clone any incoming data and prepend the event, creating the handler arg list\n        data = data != null ? jQuery.makeArray( data ) : [];\n        data.unshift( event );\n\n        // Allow special events to draw outside the lines\n        special = jQuery.event.special[ type ] || {};\n        if ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n            return;\n        }\n\n        // Determine event propagation path in advance, per W3C events spec (#9951)\n        // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n        eventPath = [[ elem, special.bindType || type ]];\n        if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n            bubbleType = special.delegateType || type;\n            cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n            for ( old = elem; cur; cur = cur.parentNode ) {\n                eventPath.push([ cur, bubbleType ]);\n                old = cur;\n            }\n\n            // Only add window if we got to document (e.g., not plain obj or detached DOM)\n            if ( old === (elem.ownerDocument || document) ) {\n                eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n            }\n        }\n\n        // Fire handlers on the event path\n        for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n            cur = eventPath[i][0];\n            event.type = eventPath[i][1];\n\n            handle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n            if ( handle ) {\n                handle.apply( cur, data );\n            }\n            // Note that this is a bare JS function and not a jQuery handler\n            handle = ontype && cur[ ontype ];\n            if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n                event.preventDefault();\n            }\n        }\n        event.type = type;\n\n        // If nobody prevented the default action, do it now\n        if ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n            if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n                !(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n                // Call a native DOM method on the target with the same name name as the event.\n                // Can't use an .isFunction() check here because IE6/7 fails that test.\n                // Don't do default actions on window, that's where global variables be (#6170)\n                // IE<9 dies on focus/blur to hidden element (#1486)\n                if ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n                    // Don't re-trigger an onFOO event when we call its FOO() method\n                    old = elem[ ontype ];\n\n                    if ( old ) {\n                        elem[ ontype ] = null;\n                    }\n\n                    // Prevent re-triggering of the same event, since we already bubbled it above\n                    jQuery.event.triggered = type;\n                    elem[ type ]();\n                    jQuery.event.triggered = undefined;\n\n                    if ( old ) {\n                        elem[ ontype ] = old;\n                    }\n                }\n            }\n        }\n\n        return event.result;\n    },\n\n    dispatch: function( event ) {\n\n        // Make a writable jQuery.Event from the native event object\n        event = jQuery.event.fix( event || window.event );\n\n        var i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related,\n            handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n            delegateCount = handlers.delegateCount,\n            args = [].slice.call( arguments ),\n            run_all = !event.exclusive && !event.namespace,\n            special = jQuery.event.special[ event.type ] || {},\n            handlerQueue = [];\n\n        // Use the fix-ed jQuery.Event rather than the (read-only) native event\n        args[0] = event;\n        event.delegateTarget = this;\n\n        // Call the preDispatch hook for the mapped type, and let it bail if desired\n        if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n            return;\n        }\n\n        // Determine handlers that should run if there are delegated events\n        // Avoid non-left-click bubbling in Firefox (#3861)\n        if ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n            // Pregenerate a single jQuery object for reuse with .is()\n            jqcur = jQuery(this);\n            jqcur.context = this;\n\n            for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n                // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #xxxx)\n                if ( cur.disabled !== true || event.type !== \"click\" ) {\n                    selMatch = {};\n                    matches = [];\n                    jqcur[0] = cur;\n                    for ( i = 0; i < delegateCount; i++ ) {\n                        handleObj = handlers[ i ];\n                        sel = handleObj.selector;\n\n                        if ( selMatch[ sel ] === undefined ) {\n                            selMatch[ sel ] = jqcur.is( sel );\n                        }\n                        if ( selMatch[ sel ] ) {\n                            matches.push( handleObj );\n                        }\n                    }\n                    if ( matches.length ) {\n                        handlerQueue.push({ elem: cur, matches: matches });\n                    }\n                }\n            }\n        }\n\n        // Add the remaining (directly-bound) handlers\n        if ( handlers.length > delegateCount ) {\n            handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n        }\n\n        // Run delegates first; they may want to stop propagation beneath us\n        for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n            matched = handlerQueue[ i ];\n            event.currentTarget = matched.elem;\n\n            for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n                handleObj = matched.matches[ j ];\n\n                // Triggered event must either 1) be non-exclusive and have no namespace, or\n                // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n                if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n                    event.data = handleObj.data;\n                    event.handleObj = handleObj;\n\n                    ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n                            .apply( matched.elem, args );\n\n                    if ( ret !== undefined ) {\n                        event.result = ret;\n                        if ( ret === false ) {\n                            event.preventDefault();\n                            event.stopPropagation();\n                        }\n                    }\n                }\n            }\n        }\n\n        // Call the postDispatch hook for the mapped type\n        if ( special.postDispatch ) {\n            special.postDispatch.call( this, event );\n        }\n\n        return event.result;\n    },\n\n    // Includes some event props shared by KeyEvent and MouseEvent\n    // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n    props: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n    fixHooks: {},\n\n    keyHooks: {\n        props: \"char charCode key keyCode\".split(\" \"),\n        filter: function( event, original ) {\n\n            // Add which for key events\n            if ( event.which == null ) {\n                event.which = original.charCode != null ? original.charCode : original.keyCode;\n            }\n\n            return event;\n        }\n    },\n\n    mouseHooks: {\n        props: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n        filter: function( event, original ) {\n            var eventDoc, doc, body,\n                button = original.button,\n                fromElement = original.fromElement;\n\n            // Calculate pageX/Y if missing and clientX/Y available\n            if ( event.pageX == null && original.clientX != null ) {\n                eventDoc = event.target.ownerDocument || document;\n                doc = eventDoc.documentElement;\n                body = eventDoc.body;\n\n                event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n                event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n            }\n\n            // Add relatedTarget, if necessary\n            if ( !event.relatedTarget && fromElement ) {\n                event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n            }\n\n            // Add which for click: 1 === left; 2 === middle; 3 === right\n            // Note: button is not normalized, so don't use it\n            if ( !event.which && button !== undefined ) {\n                event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n            }\n\n            return event;\n        }\n    },\n\n    fix: function( event ) {\n        if ( event[ jQuery.expando ] ) {\n            return event;\n        }\n\n        // Create a writable copy of the event object and normalize some properties\n        var i, prop,\n            originalEvent = event,\n            fixHook = jQuery.event.fixHooks[ event.type ] || {},\n            copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n        event = jQuery.Event( originalEvent );\n\n        for ( i = copy.length; i; ) {\n            prop = copy[ --i ];\n            event[ prop ] = originalEvent[ prop ];\n        }\n\n        // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n        if ( !event.target ) {\n            event.target = originalEvent.srcElement || document;\n        }\n\n        // Target should not be a text node (#504, Safari)\n        if ( event.target.nodeType === 3 ) {\n            event.target = event.target.parentNode;\n        }\n\n        // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)\n        event.metaKey = !!event.metaKey;\n\n        return fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n    },\n\n    special: {\n        ready: {\n            // Make sure the ready event is setup\n            setup: jQuery.bindReady\n        },\n\n        load: {\n            // Prevent triggered image.load events from bubbling to window.load\n            noBubble: true\n        },\n\n        focus: {\n            delegateType: \"focusin\"\n        },\n        blur: {\n            delegateType: \"focusout\"\n        },\n\n        beforeunload: {\n            setup: function( data, namespaces, eventHandle ) {\n                // We only want to do this special case on windows\n                if ( jQuery.isWindow( this ) ) {\n                    this.onbeforeunload = eventHandle;\n                }\n            },\n\n            teardown: function( namespaces, eventHandle ) {\n                if ( this.onbeforeunload === eventHandle ) {\n                    this.onbeforeunload = null;\n                }\n            }\n        }\n    },\n\n    simulate: function( type, elem, event, bubble ) {\n        // Piggyback on a donor event to simulate a different one.\n        // Fake originalEvent to avoid donor's stopPropagation, but if the\n        // simulated event prevents default then we do the same on the donor.\n        var e = jQuery.extend(\n            new jQuery.Event(),\n            event,\n            { type: type,\n                isSimulated: true,\n                originalEvent: {}\n            }\n        );\n        if ( bubble ) {\n            jQuery.event.trigger( e, null, elem );\n        } else {\n            jQuery.event.dispatch.call( elem, e );\n        }\n        if ( e.isDefaultPrevented() ) {\n            event.preventDefault();\n        }\n    }\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n    function( elem, type, handle ) {\n        if ( elem.removeEventListener ) {\n            elem.removeEventListener( type, handle, false );\n        }\n    } :\n    function( elem, type, handle ) {\n        var name = \"on\" + type;\n\n        if ( elem.detachEvent ) {\n\n            // #8545, #7054, preventing memory leaks for custom events in IE6-8 –\n            // detachEvent needed property on element, by name of that event, to properly expose it to GC\n            if ( typeof elem[ name ] === \"undefined\" ) {\n                elem[ name ] = null;\n            }\n\n            elem.detachEvent( name, handle );\n        }\n    };\n\njQuery.Event = function( src, props ) {\n    // Allow instantiation without the 'new' keyword\n    if ( !(this instanceof jQuery.Event) ) {\n        return new jQuery.Event( src, props );\n    }\n\n    // Event object\n    if ( src && src.type ) {\n        this.originalEvent = src;\n        this.type = src.type;\n\n        // Events bubbling up the document may have been marked as prevented\n        // by a handler lower down the tree; reflect the correct value.\n        this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n            src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n    // Event type\n    } else {\n        this.type = src;\n    }\n\n    // Put explicitly provided properties onto the event object\n    if ( props ) {\n        jQuery.extend( this, props );\n    }\n\n    // Create a timestamp if incoming event doesn't have one\n    this.timeStamp = src && src.timeStamp || jQuery.now();\n\n    // Mark it as fixed\n    this[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n    return false;\n}\nfunction returnTrue() {\n    return true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n    preventDefault: function() {\n        this.isDefaultPrevented = returnTrue;\n\n        var e = this.originalEvent;\n        if ( !e ) {\n            return;\n        }\n\n        // if preventDefault exists run it on the original event\n        if ( e.preventDefault ) {\n            e.preventDefault();\n\n        // otherwise set the returnValue property of the original event to false (IE)\n        } else {\n            e.returnValue = false;\n        }\n    },\n    stopPropagation: function() {\n        this.isPropagationStopped = returnTrue;\n\n        var e = this.originalEvent;\n        if ( !e ) {\n            return;\n        }\n        // if stopPropagation exists run it on the original event\n        if ( e.stopPropagation ) {\n            e.stopPropagation();\n        }\n        // otherwise set the cancelBubble property of the original event to true (IE)\n        e.cancelBubble = true;\n    },\n    stopImmediatePropagation: function() {\n        this.isImmediatePropagationStopped = returnTrue;\n        this.stopPropagation();\n    },\n    isDefaultPrevented: returnFalse,\n    isPropagationStopped: returnFalse,\n    isImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n    mouseenter: \"mouseover\",\n    mouseleave: \"mouseout\"\n}, function( orig, fix ) {\n    jQuery.event.special[ orig ] = {\n        delegateType: fix,\n        bindType: fix,\n\n        handle: function( event ) {\n            var ret,\n                target = this,\n                related = event.relatedTarget,\n                handleObj = event.handleObj,\n                selector = handleObj.selector;\n\n            // For mousenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n                event.type = handleObj.origType;\n                ret = handleObj.handler.apply( this, arguments );\n                event.type = fix;\n            }\n            return ret;\n        }\n    };\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n    jQuery.event.special.submit = {\n        setup: function() {\n            // Only need this for delegated form submit events\n            if ( jQuery.nodeName( this, \"form\" ) ) {\n                return false;\n            }\n\n            // Lazy-add a submit handler when a descendant form may potentially be submitted\n            jQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n                // Node name check avoids a VML-related crash in IE (#9807)\n                var elem = e.target,\n                    form = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n                if ( form && !jQuery._data( form, \"_submit_attached\" ) ) {\n                    jQuery.event.add( form, \"submit._submit\", function( event ) {\n                        event._submit_bubble = true;\n                    });\n                    jQuery._data( form, \"_submit_attached\", true );\n                }\n            });\n            // return undefined since we don't need an event listener\n        },\n\n        postDispatch: function( event ) {\n            // If form was submitted by the user, bubble the event up the tree\n            if ( event._submit_bubble ) {\n                delete event._submit_bubble;\n                if ( this.parentNode && !event.isTrigger ) {\n                    jQuery.event.simulate( \"submit\", this.parentNode, event, true );\n                }\n            }\n        },\n\n        teardown: function() {\n            // Only need this for delegated form submit events\n            if ( jQuery.nodeName( this, \"form\" ) ) {\n                return false;\n            }\n\n            // Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n            jQuery.event.remove( this, \"._submit\" );\n        }\n    };\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n    jQuery.event.special.change = {\n\n        setup: function() {\n\n            if ( rformElems.test( this.nodeName ) ) {\n                // IE doesn't fire change on a check/radio until blur; trigger it on click\n                // after a propertychange. Eat the blur-change in special.change.handle.\n                // This still fires onchange a second time for check/radio after blur.\n                if ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n                    jQuery.event.add( this, \"propertychange._change\", function( event ) {\n                        if ( event.originalEvent.propertyName === \"checked\" ) {\n                            this._just_changed = true;\n                        }\n                    });\n                    jQuery.event.add( this, \"click._change\", function( event ) {\n                        if ( this._just_changed && !event.isTrigger ) {\n                            this._just_changed = false;\n                        }\n                        // Allow triggered, simulated change events (#11500)\n                        jQuery.event.simulate( \"change\", this, event, true );\n                    });\n                }\n                return false;\n            }\n            // Delegated event; lazy-add a change handler on descendant inputs\n            jQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n                var elem = e.target;\n\n                if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"_change_attached\" ) ) {\n                    jQuery.event.add( elem, \"change._change\", function( event ) {\n                        if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n                            jQuery.event.simulate( \"change\", this.parentNode, event, true );\n                        }\n                    });\n                    jQuery._data( elem, \"_change_attached\", true );\n                }\n            });\n        },\n\n        handle: function( event ) {\n            var elem = event.target;\n\n            // Swallow native change events from checkbox/radio, we already triggered them above\n            if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n                return event.handleObj.handler.apply( this, arguments );\n            }\n        },\n\n        teardown: function() {\n            jQuery.event.remove( this, \"._change\" );\n\n            return rformElems.test( this.nodeName );\n        }\n    };\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n    jQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n        // Attach a single capturing handler while someone wants focusin/focusout\n        var attaches = 0,\n            handler = function( event ) {\n                jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n            };\n\n        jQuery.event.special[ fix ] = {\n            setup: function() {\n                if ( attaches++ === 0 ) {\n                    document.addEventListener( orig, handler, true );\n                }\n            },\n            teardown: function() {\n                if ( --attaches === 0 ) {\n                    document.removeEventListener( orig, handler, true );\n                }\n            }\n        };\n    });\n}\n\njQuery.fn.extend({\n\n    on: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n        var origFn, type;\n\n        // Types can be a map of types/handlers\n        if ( typeof types === \"object\" ) {\n            // ( types-Object, selector, data )\n            if ( typeof selector !== \"string\" ) { // && selector != null\n                // ( types-Object, data )\n                data = data || selector;\n                selector = undefined;\n            }\n            for ( type in types ) {\n                this.on( type, selector, data, types[ type ], one );\n            }\n            return this;\n        }\n\n        if ( data == null && fn == null ) {\n            // ( types, fn )\n            fn = selector;\n            data = selector = undefined;\n        } else if ( fn == null ) {\n            if ( typeof selector === \"string\" ) {\n                // ( types, selector, fn )\n                fn = data;\n                data = undefined;\n            } else {\n                // ( types, data, fn )\n                fn = data;\n                data = selector;\n                selector = undefined;\n            }\n        }\n        if ( fn === false ) {\n            fn = returnFalse;\n        } else if ( !fn ) {\n            return this;\n        }\n\n        if ( one === 1 ) {\n            origFn = fn;\n            fn = function( event ) {\n                // Can use an empty set, since event contains the info\n                jQuery().off( event );\n                return origFn.apply( this, arguments );\n            };\n            // Use same guid so caller can remove using origFn\n            fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n        }\n        return this.each( function() {\n            jQuery.event.add( this, types, fn, data, selector );\n        });\n    },\n    one: function( types, selector, data, fn ) {\n        return this.on( types, selector, data, fn, 1 );\n    },\n    off: function( types, selector, fn ) {\n        var handleObj, type;\n        if ( types && types.preventDefault && types.handleObj ) {\n            // ( event )  dispatched jQuery.Event\n            handleObj = types.handleObj;\n            jQuery( types.delegateTarget ).off(\n                handleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n                handleObj.selector,\n                handleObj.handler\n            );\n            return this;\n        }\n        if ( typeof types === \"object\" ) {\n            // ( types-object [, selector] )\n            for ( type in types ) {\n                this.off( type, selector, types[ type ] );\n            }\n            return this;\n        }\n        if ( selector === false || typeof selector === \"function\" ) {\n            // ( types [, fn] )\n            fn = selector;\n            selector = undefined;\n        }\n        if ( fn === false ) {\n            fn = returnFalse;\n        }\n        return this.each(function() {\n            jQuery.event.remove( this, types, fn, selector );\n        });\n    },\n\n    bind: function( types, data, fn ) {\n        return this.on( types, null, data, fn );\n    },\n    unbind: function( types, fn ) {\n        return this.off( types, null, fn );\n    },\n\n    live: function( types, data, fn ) {\n        jQuery( this.context ).on( types, this.selector, data, fn );\n        return this;\n    },\n    die: function( types, fn ) {\n        jQuery( this.context ).off( types, this.selector || \"**\", fn );\n        return this;\n    },\n\n    delegate: function( selector, types, data, fn ) {\n        return this.on( types, selector, data, fn );\n    },\n    undelegate: function( selector, types, fn ) {\n        // ( namespace ) or ( selector, types [, fn] )\n        return arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n    },\n\n    trigger: function( type, data ) {\n        return this.each(function() {\n            jQuery.event.trigger( type, data, this );\n        });\n    },\n    triggerHandler: function( type, data ) {\n        if ( this[0] ) {\n            return jQuery.event.trigger( type, data, this[0], true );\n        }\n    },\n\n    toggle: function( fn ) {\n        // Save reference to arguments for access in closure\n        var args = arguments,\n            guid = fn.guid || jQuery.guid++,\n            i = 0,\n            toggler = function( event ) {\n                // Figure out which function to execute\n                var lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n                jQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n                // Make sure that clicks stop\n                event.preventDefault();\n\n                // and execute the function\n                return args[ lastToggle ].apply( this, arguments ) || false;\n            };\n\n        // link all the functions, so any of them can unbind this click handler\n        toggler.guid = guid;\n        while ( i < args.length ) {\n            args[ i++ ].guid = guid;\n        }\n\n        return this.click( toggler );\n    },\n\n    hover: function( fnOver, fnOut ) {\n        return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n    }\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n    \"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n    \"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n    // Handle event binding\n    jQuery.fn[ name ] = function( data, fn ) {\n        if ( fn == null ) {\n            fn = data;\n            data = null;\n        }\n\n        return arguments.length > 0 ?\n            this.on( name, null, data, fn ) :\n            this.trigger( name );\n    };\n\n    if ( rkeyEvent.test( name ) ) {\n        jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n    }\n\n    if ( rmouseEvent.test( name ) ) {\n        jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n    }\n});\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2012 jQuery Foundation and other contributors\n *  Released under the MIT license\n *  http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar cachedruns,\n    dirruns,\n    sortOrder,\n    siblingCheck,\n    assertGetIdNotName,\n\n    document = window.document,\n    docElem = document.documentElement,\n\n    strundefined = \"undefined\",\n    hasDuplicate = false,\n    baseHasDuplicate = true,\n    done = 0,\n    slice = [].slice,\n    push = [].push,\n\n    expando = ( \"sizcache\" + Math.random() ).replace( \".\", \"\" ),\n\n    // Regex\n\n    // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n    whitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n    // http://www.w3.org/TR/css3-syntax/#characters\n    characterEncoding = \"(?:\\\\\\\\.|[-\\\\w]|[^\\\\x00-\\\\xa0])+\",\n\n    // Loosely modeled on CSS identifier characters\n    // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)\n    // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n    identifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n    // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n    operators = \"([*^$|!~]?=)\",\n    attributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n        \"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n    pseudos = \":(\" + characterEncoding + \")(?:\\\\((?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\2|((?:[^,]|\\\\\\\\,|(?:,(?=[^\\\\[]*\\\\]))|(?:,(?=[^\\\\(]*\\\\))))*))\\\\)|)\",\n    pos = \":(nth|eq|gt|lt|first|last|even|odd)(?:\\\\((\\\\d*)\\\\)|)(?=[^-]|$)\",\n    combinators = whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\",\n    groups = \"(?=[^\\\\x20\\\\t\\\\r\\\\n\\\\f])(?:\\\\\\\\.|\" + attributes + \"|\" + pseudos.replace( 2, 7 ) + \"|[^\\\\\\\\(),])+\",\n\n    // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n    rtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n    rcombinators = new RegExp( \"^\" + combinators ),\n\n    // All simple (non-comma) selectors, excluding insignifant trailing whitespace\n    rgroups = new RegExp( groups + \"?(?=\" + whitespace + \"*,|$)\", \"g\" ),\n\n    // A selector, or everything after leading whitespace\n    // Optionally followed in either case by a \")\" for terminating sub-selectors\n    rselector = new RegExp( \"^(?:(?!,)(?:(?:^|,)\" + whitespace + \"*\" + groups + \")*?|\" + whitespace + \"*(.*?))(\\\\)|$)\" ),\n\n    // All combinators and selector components (attribute test, tag, pseudo, etc.), the latter appearing together when consecutive\n    rtokens = new RegExp( groups.slice( 19, -6 ) + \"\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])+|\" + combinators, \"g\" ),\n\n    // Easily-parseable/retrievable ID or TAG or CLASS selectors\n    rquickExpr = /^(?:#([\\w\\-]+)|(\\w+)|\\.([\\w\\-]+))$/,\n\n    rsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n    rendsWithNot = /:not\\($/,\n\n    rheader = /h\\d/i,\n    rinputs = /input|select|textarea|button/i,\n\n    rbackslash = /\\\\(?!\\\\)/g,\n\n    matchExpr = {\n        \"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n        \"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n        \"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n        \"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"[-\", \"[-\\\\*\" ) + \")\" ),\n        \"ATTR\": new RegExp( \"^\" + attributes ),\n        \"PSEUDO\": new RegExp( \"^\" + pseudos ),\n        \"CHILD\": new RegExp( \"^:(only|nth|last|first)-child(?:\\\\(\" + whitespace +\n            \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n            \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n        \"POS\": new RegExp( pos, \"ig\" ),\n        // For use in libraries implementing .is()\n        \"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|\" + pos, \"i\" )\n    },\n\n    classCache = {},\n    cachedClasses = [],\n    compilerCache = {},\n    cachedSelectors = [],\n\n    // Mark a function for use in filtering\n    markFunction = function( fn ) {\n        fn.sizzleFilter = true;\n        return fn;\n    },\n\n    // Returns a function to use in pseudos for input types\n    createInputFunction = function( type ) {\n        return function( elem ) {\n            // Check the input's nodeName and type\n            return elem.nodeName.toLowerCase() === \"input\" && elem.type === type;\n        };\n    },\n\n    // Returns a function to use in pseudos for buttons\n    createButtonFunction = function( type ) {\n        return function( elem ) {\n            var name = elem.nodeName.toLowerCase();\n            return (name === \"input\" || name === \"button\") && elem.type === type;\n        };\n    },\n\n    // Used for testing something on an element\n    assert = function( fn ) {\n        var pass = false,\n            div = document.createElement(\"div\");\n        try {\n            pass = fn( div );\n        } catch (e) {}\n        // release memory in IE\n        div = null;\n        return pass;\n    },\n\n    // Check if attributes should be retrieved by attribute nodes\n    assertAttributes = assert(function( div ) {\n        div.innerHTML = \"<select></select>\";\n        var type = typeof div.lastChild.getAttribute(\"multiple\");\n        // IE8 returns a string for some attributes even when not present\n        return type !== \"boolean\" && type !== \"string\";\n    }),\n\n    // Check if getElementById returns elements by name\n    // Check if getElementsByName privileges form controls or returns elements by ID\n    assertUsableName = assert(function( div ) {\n        // Inject content\n        div.id = expando + 0;\n        div.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n        docElem.insertBefore( div, docElem.firstChild );\n\n        // Test\n        var pass = document.getElementsByName &&\n            // buggy browsers will return fewer than the correct 2\n            document.getElementsByName( expando ).length ===\n            // buggy browsers will return more than the correct 0\n            2 + document.getElementsByName( expando + 0 ).length;\n        assertGetIdNotName = !document.getElementById( expando );\n\n        // Cleanup\n        docElem.removeChild( div );\n\n        return pass;\n    }),\n\n    // Check if the browser returns only elements\n    // when doing getElementsByTagName(\"*\")\n    assertTagNameNoComments = assert(function( div ) {\n        div.appendChild( document.createComment(\"\") );\n        return div.getElementsByTagName(\"*\").length === 0;\n    }),\n\n    // Check if getAttribute returns normalized href attributes\n    assertHrefNotNormalized = assert(function( div ) {\n        div.innerHTML = \"<a href='#'></a>\";\n        return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n            div.firstChild.getAttribute(\"href\") === \"#\";\n    }),\n\n    // Check if getElementsByClassName can be trusted\n    assertUsableClassName = assert(function( div ) {\n        // Opera can't find a second classname (in 9.6)\n        div.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n        if ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n            return false;\n        }\n\n        // Safari caches class attributes, doesn't catch changes (in 3.2)\n        div.lastChild.className = \"e\";\n        return div.getElementsByClassName(\"e\").length !== 1;\n    });\n\nvar Sizzle = function( selector, context, results, seed ) {\n    results = results || [];\n    context = context || document;\n    var match, elem, xml, m,\n        nodeType = context.nodeType;\n\n    if ( nodeType !== 1 && nodeType !== 9 ) {\n        return [];\n    }\n\n    if ( !selector || typeof selector !== \"string\" ) {\n        return results;\n    }\n\n    xml = isXML( context );\n\n    if ( !xml && !seed ) {\n        if ( (match = rquickExpr.exec( selector )) ) {\n            // Speed-up: Sizzle(\"#ID\")\n            if ( (m = match[1]) ) {\n                if ( nodeType === 9 ) {\n                    elem = context.getElementById( m );\n                    // Check parentNode to catch when Blackberry 4.6 returns\n                    // nodes that are no longer in the document #6963\n                    if ( elem && elem.parentNode ) {\n                        // Handle the case where IE, Opera, and Webkit return items\n                        // by name instead of ID\n                        if ( elem.id === m ) {\n                            results.push( elem );\n                            return results;\n                        }\n                    } else {\n                        return results;\n                    }\n                } else {\n                    // Context is not a document\n                    if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n                        contains( context, elem ) && elem.id === m ) {\n                        results.push( elem );\n                        return results;\n                    }\n                }\n\n            // Speed-up: Sizzle(\"TAG\")\n            } else if ( match[2] ) {\n                push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n                return results;\n\n            // Speed-up: Sizzle(\".CLASS\")\n            } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {\n                push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n                return results;\n            }\n        }\n    }\n\n    // All others\n    return select( selector, context, results, seed, xml );\n};\n\nvar Expr = Sizzle.selectors = {\n\n    // Can be adjusted by the user\n    cacheLength: 50,\n\n    match: matchExpr,\n\n    order: [ \"ID\", \"TAG\" ],\n\n    attrHandle: {},\n\n    createPseudo: markFunction,\n\n    find: {\n        \"ID\": assertGetIdNotName ?\n            function( id, context, xml ) {\n                if ( typeof context.getElementById !== strundefined && !xml ) {\n                    var m = context.getElementById( id );\n                    // Check parentNode to catch when Blackberry 4.6 returns\n                    // nodes that are no longer in the document #6963\n                    return m && m.parentNode ? [m] : [];\n                }\n            } :\n            function( id, context, xml ) {\n                if ( typeof context.getElementById !== strundefined && !xml ) {\n                    var m = context.getElementById( id );\n\n                    return m ?\n                        m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n                            [m] :\n                            undefined :\n                        [];\n                }\n            },\n\n        \"TAG\": assertTagNameNoComments ?\n            function( tag, context ) {\n                if ( typeof context.getElementsByTagName !== strundefined ) {\n                    return context.getElementsByTagName( tag );\n                }\n            } :\n            function( tag, context ) {\n                var results = context.getElementsByTagName( tag );\n\n                // Filter out possible comments\n                if ( tag === \"*\" ) {\n                    var elem,\n                        tmp = [],\n                        i = 0;\n\n                    for ( ; (elem = results[i]); i++ ) {\n                        if ( elem.nodeType === 1 ) {\n                            tmp.push( elem );\n                        }\n                    }\n\n                    return tmp;\n                }\n                return results;\n            }\n    },\n\n    relative: {\n        \">\": { dir: \"parentNode\", first: true },\n        \" \": { dir: \"parentNode\" },\n        \"+\": { dir: \"previousSibling\", first: true },\n        \"~\": { dir: \"previousSibling\" }\n    },\n\n    preFilter: {\n        \"ATTR\": function( match ) {\n            match[1] = match[1].replace( rbackslash, \"\" );\n\n            // Move the given value to match[3] whether quoted or unquoted\n            match[3] = ( match[4] || match[5] || \"\" ).replace( rbackslash, \"\" );\n\n            if ( match[2] === \"~=\" ) {\n                match[3] = \" \" + match[3] + \" \";\n            }\n\n            return match.slice( 0, 4 );\n        },\n\n        \"CHILD\": function( match ) {\n            /* matches from matchExpr.CHILD\n                1 type (only|nth|...)\n                2 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n                3 xn-component of xn+y argument ([+-]?\\d*n|)\n                4 sign of xn-component\n                5 x of xn-component\n                6 sign of y-component\n                7 y of y-component\n            */\n            match[1] = match[1].toLowerCase();\n\n            if ( match[1] === \"nth\" ) {\n                // nth-child requires argument\n                if ( !match[2] ) {\n                    Sizzle.error( match[0] );\n                }\n\n                // numeric x and y parameters for Expr.filter.CHILD\n                // remember that false/true cast respectively to 0/1\n                match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === \"even\" || match[2] === \"odd\" ) );\n                match[4] = +( ( match[6] + match[7] ) || match[2] === \"odd\" );\n\n            // other types prohibit arguments\n            } else if ( match[2] ) {\n                Sizzle.error( match[0] );\n            }\n\n            return match;\n        },\n\n        \"PSEUDO\": function( match ) {\n            var argument,\n                unquoted = match[4];\n\n            if ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n                return null;\n            }\n\n            // Relinquish our claim on characters in `unquoted` from a closing parenthesis on\n            if ( unquoted && (argument = rselector.exec( unquoted )) && argument.pop() ) {\n\n                match[0] = match[0].slice( 0, argument[0].length - unquoted.length - 1 );\n                unquoted = argument[0].slice( 0, -1 );\n            }\n\n            // Quoted or unquoted, we have the full argument\n            // Return only captures needed by the pseudo filter method (type and argument)\n            match.splice( 2, 3, unquoted || match[3] );\n            return match;\n        }\n    },\n\n    filter: {\n        \"ID\": assertGetIdNotName ?\n            function( id ) {\n                id = id.replace( rbackslash, \"\" );\n                return function( elem ) {\n                    return elem.getAttribute(\"id\") === id;\n                };\n            } :\n            function( id ) {\n                id = id.replace( rbackslash, \"\" );\n                return function( elem ) {\n                    var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n                    return node && node.value === id;\n                };\n            },\n\n        \"TAG\": function( nodeName ) {\n            if ( nodeName === \"*\" ) {\n                return function() { return true; };\n            }\n            nodeName = nodeName.replace( rbackslash, \"\" ).toLowerCase();\n\n            return function( elem ) {\n                return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n            };\n        },\n\n        \"CLASS\": function( className ) {\n            var pattern = classCache[ className ];\n            if ( !pattern ) {\n                pattern = classCache[ className ] = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" );\n                cachedClasses.push( className );\n                // Avoid too large of a cache\n                if ( cachedClasses.length > Expr.cacheLength ) {\n                    delete classCache[ cachedClasses.shift() ];\n                }\n            }\n            return function( elem ) {\n                return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n            };\n        },\n\n        \"ATTR\": function( name, operator, check ) {\n            if ( !operator ) {\n                return function( elem ) {\n                    return Sizzle.attr( elem, name ) != null;\n                };\n            }\n\n            return function( elem ) {\n                var result = Sizzle.attr( elem, name ),\n                    value = result + \"\";\n\n                if ( result == null ) {\n                    return operator === \"!=\";\n                }\n\n                switch ( operator ) {\n                    case \"=\":\n                        return value === check;\n                    case \"!=\":\n                        return value !== check;\n                    case \"^=\":\n                        return check && value.indexOf( check ) === 0;\n                    case \"*=\":\n                        return check && value.indexOf( check ) > -1;\n                    case \"$=\":\n                        return check && value.substr( value.length - check.length ) === check;\n                    case \"~=\":\n                        return ( \" \" + value + \" \" ).indexOf( check ) > -1;\n                    case \"|=\":\n                        return value === check || value.substr( 0, check.length + 1 ) === check + \"-\";\n                }\n            };\n        },\n\n        \"CHILD\": function( type, argument, first, last ) {\n\n            if ( type === \"nth\" ) {\n                var doneName = done++;\n\n                return function( elem ) {\n                    var parent, diff,\n                        count = 0,\n                        node = elem;\n\n                    if ( first === 1 && last === 0 ) {\n                        return true;\n                    }\n\n                    parent = elem.parentNode;\n\n                    if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) {\n                        for ( node = parent.firstChild; node; node = node.nextSibling ) {\n                            if ( node.nodeType === 1 ) {\n                                node.sizset = ++count;\n                                if ( node === elem ) {\n                                    break;\n                                }\n                            }\n                        }\n\n                        parent[ expando ] = doneName;\n                    }\n\n                    diff = elem.sizset - last;\n\n                    if ( first === 0 ) {\n                        return diff === 0;\n\n                    } else {\n                        return ( diff % first === 0 && diff / first >= 0 );\n                    }\n                };\n            }\n\n            return function( elem ) {\n                var node = elem;\n\n                switch ( type ) {\n                    case \"only\":\n                    case \"first\":\n                        while ( (node = node.previousSibling) ) {\n                            if ( node.nodeType === 1 ) {\n                                return false;\n                            }\n                        }\n\n                        if ( type === \"first\" ) {\n                            return true;\n                        }\n\n                        node = elem;\n\n                        /* falls through */\n                    case \"last\":\n                        while ( (node = node.nextSibling) ) {\n                            if ( node.nodeType === 1 ) {\n                                return false;\n                            }\n                        }\n\n                        return true;\n                }\n            };\n        },\n\n        \"PSEUDO\": function( pseudo, argument, context, xml ) {\n            // pseudo-class names are case-insensitive\n            // http://www.w3.org/TR/selectors/#pseudo-classes\n            // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n            var fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ];\n\n            if ( !fn ) {\n                Sizzle.error( \"unsupported pseudo: \" + pseudo );\n            }\n\n            // The user may set fn.sizzleFilter to indicate\n            // that arguments are needed to create the filter function\n            // just as Sizzle does\n            if ( !fn.sizzleFilter ) {\n                return fn;\n            }\n\n            return fn( argument, context, xml );\n        }\n    },\n\n    pseudos: {\n        \"not\": markFunction(function( selector, context, xml ) {\n            // Trim the selector passed to compile\n            // to avoid treating leading and trailing\n            // spaces as combinators\n            var matcher = compile( selector.replace( rtrim, \"$1\" ), context, xml );\n            return function( elem ) {\n                return !matcher( elem );\n            };\n        }),\n\n        \"enabled\": function( elem ) {\n            return elem.disabled === false;\n        },\n\n        \"disabled\": function( elem ) {\n            return elem.disabled === true;\n        },\n\n        \"checked\": function( elem ) {\n            // In CSS3, :checked should return both checked and selected elements\n            // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n            var nodeName = elem.nodeName.toLowerCase();\n            return (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n        },\n\n        \"selected\": function( elem ) {\n            // Accessing this property makes selected-by-default\n            // options in Safari work properly\n            if ( elem.parentNode ) {\n                elem.parentNode.selectedIndex;\n            }\n\n            return elem.selected === true;\n        },\n\n        \"parent\": function( elem ) {\n            return !Expr.pseudos[\"empty\"]( elem );\n        },\n\n        \"empty\": function( elem ) {\n            // http://www.w3.org/TR/selectors/#empty-pseudo\n            // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n            //   not comment, processing instructions, or others\n            // Thanks to Diego Perini for the nodeName shortcut\n            //   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n            var nodeType;\n            elem = elem.firstChild;\n            while ( elem ) {\n                if ( elem.nodeName > \"@\" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {\n                    return false;\n                }\n                elem = elem.nextSibling;\n            }\n            return true;\n        },\n\n        \"contains\": markFunction(function( text ) {\n            return function( elem ) {\n                return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n            };\n        }),\n\n        \"has\": markFunction(function( selector ) {\n            return function( elem ) {\n                return Sizzle( selector, elem ).length > 0;\n            };\n        }),\n\n        \"header\": function( elem ) {\n            return rheader.test( elem.nodeName );\n        },\n\n        \"text\": function( elem ) {\n            var type, attr;\n            // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n            // use getAttribute instead to test this case\n            return elem.nodeName.toLowerCase() === \"input\" &&\n                (type = elem.type) === \"text\" &&\n                ( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === type );\n        },\n\n        // Input types\n        \"radio\": createInputFunction(\"radio\"),\n        \"checkbox\": createInputFunction(\"checkbox\"),\n        \"file\": createInputFunction(\"file\"),\n        \"password\": createInputFunction(\"password\"),\n        \"image\": createInputFunction(\"image\"),\n\n        \"submit\": createButtonFunction(\"submit\"),\n        \"reset\": createButtonFunction(\"reset\"),\n\n        \"button\": function( elem ) {\n            var name = elem.nodeName.toLowerCase();\n            return name === \"input\" && elem.type === \"button\" || name === \"button\";\n        },\n\n        \"input\": function( elem ) {\n            return rinputs.test( elem.nodeName );\n        },\n\n        \"focus\": function( elem ) {\n            var doc = elem.ownerDocument;\n            return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);\n        },\n\n        \"active\": function( elem ) {\n            return elem === elem.ownerDocument.activeElement;\n        }\n    },\n\n    setFilters: {\n        \"first\": function( elements, argument, not ) {\n            return not ? elements.slice( 1 ) : [ elements[0] ];\n        },\n\n        \"last\": function( elements, argument, not ) {\n            var elem = elements.pop();\n            return not ? elements : [ elem ];\n        },\n\n        \"even\": function( elements, argument, not ) {\n            var results = [],\n                i = not ? 1 : 0,\n                len = elements.length;\n            for ( ; i < len; i = i + 2 ) {\n                results.push( elements[i] );\n            }\n            return results;\n        },\n\n        \"odd\": function( elements, argument, not ) {\n            var results = [],\n                i = not ? 0 : 1,\n                len = elements.length;\n            for ( ; i < len; i = i + 2 ) {\n                results.push( elements[i] );\n            }\n            return results;\n        },\n\n        \"lt\": function( elements, argument, not ) {\n            return not ? elements.slice( +argument ) : elements.slice( 0, +argument );\n        },\n\n        \"gt\": function( elements, argument, not ) {\n            return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 );\n        },\n\n        \"eq\": function( elements, argument, not ) {\n            var elem = elements.splice( +argument, 1 );\n            return not ? elements : elem;\n        }\n    }\n};\n\n// Deprecated\nExpr.setFilters[\"nth\"] = Expr.setFilters[\"eq\"];\n\n// Back-compat\nExpr.filters = Expr.pseudos;\n\n// IE6/7 return a modified href\nif ( !assertHrefNotNormalized ) {\n    Expr.attrHandle = {\n        \"href\": function( elem ) {\n            return elem.getAttribute( \"href\", 2 );\n        },\n        \"type\": function( elem ) {\n            return elem.getAttribute(\"type\");\n        }\n    };\n}\n\n// Add getElementsByName if usable\nif ( assertUsableName ) {\n    Expr.order.push(\"NAME\");\n    Expr.find[\"NAME\"] = function( name, context ) {\n        if ( typeof context.getElementsByName !== strundefined ) {\n            return context.getElementsByName( name );\n        }\n    };\n}\n\n// Add getElementsByClassName if usable\nif ( assertUsableClassName ) {\n    Expr.order.splice( 1, 0, \"CLASS\" );\n    Expr.find[\"CLASS\"] = function( className, context, xml ) {\n        if ( typeof context.getElementsByClassName !== strundefined && !xml ) {\n            return context.getElementsByClassName( className );\n        }\n    };\n}\n\n// If slice is not available, provide a backup\ntry {\n    slice.call( docElem.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n    slice = function( i ) {\n        var elem, results = [];\n        for ( ; (elem = this[i]); i++ ) {\n            results.push( elem );\n        }\n        return results;\n    };\n}\n\nvar isXML = Sizzle.isXML = function( elem ) {\n    // documentElement is verified for cases where it doesn't yet exist\n    // (such as loading iframes in IE - #4833)\n    var documentElement = elem && (elem.ownerDocument || elem).documentElement;\n    return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n// Element contains another\nvar contains = Sizzle.contains = docElem.compareDocumentPosition ?\n    function( a, b ) {\n        return !!( a.compareDocumentPosition( b ) & 16 );\n    } :\n    docElem.contains ?\n    function( a, b ) {\n        var adown = a.nodeType === 9 ? a.documentElement : a,\n            bup = b.parentNode;\n        return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );\n    } :\n    function( a, b ) {\n        while ( (b = b.parentNode) ) {\n            if ( b === a ) {\n                return true;\n            }\n        }\n        return false;\n    };\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var node,\n        ret = \"\",\n        i = 0,\n        nodeType = elem.nodeType;\n\n    if ( nodeType ) {\n        if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n            // Use textContent for elements\n            // innerText usage removed for consistency of new lines (see #11153)\n            if ( typeof elem.textContent === \"string\" ) {\n                return elem.textContent;\n            } else {\n                // Traverse its children\n                for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n                    ret += getText( elem );\n                }\n            }\n        } else if ( nodeType === 3 || nodeType === 4 ) {\n            return elem.nodeValue;\n        }\n        // Do not include comment or processing instruction nodes\n    } else {\n\n        // If no nodeType, this is expected to be an array\n        for ( ; (node = elem[i]); i++ ) {\n            // Do not traverse comment nodes\n            ret += getText( node );\n        }\n    }\n    return ret;\n};\n\nSizzle.attr = function( elem, name ) {\n    var attr,\n        xml = isXML( elem );\n\n    if ( !xml ) {\n        name = name.toLowerCase();\n    }\n    if ( Expr.attrHandle[ name ] ) {\n        return Expr.attrHandle[ name ]( elem );\n    }\n    if ( assertAttributes || xml ) {\n        return elem.getAttribute( name );\n    }\n    attr = elem.getAttributeNode( name );\n    return attr ?\n        typeof elem[ name ] === \"boolean\" ?\n            elem[ name ] ? name : null :\n            attr.specified ? attr.value : null :\n        null;\n};\n\nSizzle.error = function( msg ) {\n    throw new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n// Check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n    return (baseHasDuplicate = 0);\n});\n\n\nif ( docElem.compareDocumentPosition ) {\n    sortOrder = function( a, b ) {\n        if ( a === b ) {\n            hasDuplicate = true;\n            return 0;\n        }\n\n        return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?\n            a.compareDocumentPosition :\n            a.compareDocumentPosition(b) & 4\n        ) ? -1 : 1;\n    };\n\n} else {\n    sortOrder = function( a, b ) {\n        // The nodes are identical, we can exit early\n        if ( a === b ) {\n            hasDuplicate = true;\n            return 0;\n\n        // Fallback to using sourceIndex (in IE) if it's available on both nodes\n        } else if ( a.sourceIndex && b.sourceIndex ) {\n            return a.sourceIndex - b.sourceIndex;\n        }\n\n        var al, bl,\n            ap = [],\n            bp = [],\n            aup = a.parentNode,\n            bup = b.parentNode,\n            cur = aup;\n\n        // If the nodes are siblings (or identical) we can do a quick check\n        if ( aup === bup ) {\n            return siblingCheck( a, b );\n\n        // If no parents were found then the nodes are disconnected\n        } else if ( !aup ) {\n            return -1;\n\n        } else if ( !bup ) {\n            return 1;\n        }\n\n        // Otherwise they're somewhere else in the tree so we need\n        // to build up a full list of the parentNodes for comparison\n        while ( cur ) {\n            ap.unshift( cur );\n            cur = cur.parentNode;\n        }\n\n        cur = bup;\n\n        while ( cur ) {\n            bp.unshift( cur );\n            cur = cur.parentNode;\n        }\n\n        al = ap.length;\n        bl = bp.length;\n\n        // Start walking down the tree looking for a discrepancy\n        for ( var i = 0; i < al && i < bl; i++ ) {\n            if ( ap[i] !== bp[i] ) {\n                return siblingCheck( ap[i], bp[i] );\n            }\n        }\n\n        // We ended someplace up the tree so do a sibling check\n        return i === al ?\n            siblingCheck( a, bp[i], -1 ) :\n            siblingCheck( ap[i], b, 1 );\n    };\n\n    siblingCheck = function( a, b, ret ) {\n        if ( a === b ) {\n            return ret;\n        }\n\n        var cur = a.nextSibling;\n\n        while ( cur ) {\n            if ( cur === b ) {\n                return -1;\n            }\n\n            cur = cur.nextSibling;\n        }\n\n        return 1;\n    };\n}\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n    var elem,\n        i = 1;\n\n    if ( sortOrder ) {\n        hasDuplicate = baseHasDuplicate;\n        results.sort( sortOrder );\n\n        if ( hasDuplicate ) {\n            for ( ; (elem = results[i]); i++ ) {\n                if ( elem === results[ i - 1 ] ) {\n                    results.splice( i--, 1 );\n                }\n            }\n        }\n    }\n\n    return results;\n};\n\nfunction multipleContexts( selector, contexts, results, seed ) {\n    var i = 0,\n        len = contexts.length;\n    for ( ; i < len; i++ ) {\n        Sizzle( selector, contexts[i], results, seed );\n    }\n}\n\nfunction handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) {\n    var results,\n        fn = Expr.setFilters[ posfilter.toLowerCase() ];\n\n    if ( !fn ) {\n        Sizzle.error( posfilter );\n    }\n\n    if ( selector || !(results = seed) ) {\n        multipleContexts( selector || \"*\", contexts, (results = []), seed );\n    }\n\n    return results.length > 0 ? fn( results, argument, not ) : [];\n}\n\nfunction handlePOS( selector, context, results, seed, groups ) {\n    var match, not, anchor, ret, elements, currentContexts, part, lastIndex,\n        i = 0,\n        len = groups.length,\n        rpos = matchExpr[\"POS\"],\n        // This is generated here in case matchExpr[\"POS\"] is extended\n        rposgroups = new RegExp( \"^\" + rpos.source + \"(?!\" + whitespace + \")\", \"i\" ),\n        // This is for making sure non-participating\n        // matching groups are represented cross-browser (IE6-8)\n        setUndefined = function() {\n            var i = 1,\n                len = arguments.length - 2;\n            for ( ; i < len; i++ ) {\n                if ( arguments[i] === undefined ) {\n                    match[i] = undefined;\n                }\n            }\n        };\n\n    for ( ; i < len; i++ ) {\n        // Reset regex index to 0\n        rpos.exec(\"\");\n        selector = groups[i];\n        ret = [];\n        anchor = 0;\n        elements = seed;\n        while ( (match = rpos.exec( selector )) ) {\n            lastIndex = rpos.lastIndex = match.index + match[0].length;\n            if ( lastIndex > anchor ) {\n                part = selector.slice( anchor, match.index );\n                anchor = lastIndex;\n                currentContexts = [ context ];\n\n                if ( rcombinators.test(part) ) {\n                    if ( elements ) {\n                        currentContexts = elements;\n                    }\n                    elements = seed;\n                }\n\n                if ( (not = rendsWithNot.test( part )) ) {\n                    part = part.slice( 0, -5 ).replace( rcombinators, \"$&*\" );\n                }\n\n                if ( match.length > 1 ) {\n                    match[0].replace( rposgroups, setUndefined );\n                }\n                elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not );\n            }\n        }\n\n        if ( elements ) {\n            ret = ret.concat( elements );\n\n            if ( (part = selector.slice( anchor )) && part !== \")\" ) {\n                if ( rcombinators.test(part) ) {\n                    multipleContexts( part, ret, results, seed );\n                } else {\n                    Sizzle( part, context, results, seed ? seed.concat(elements) : elements );\n                }\n            } else {\n                push.apply( results, ret );\n            }\n        } else {\n            Sizzle( selector, context, results, seed );\n        }\n    }\n\n    // Do not sort if this is a single filter\n    return len === 1 ? results : Sizzle.uniqueSort( results );\n}\n\nfunction tokenize( selector, context, xml ) {\n    var tokens, soFar, type,\n        groups = [],\n        i = 0,\n\n        // Catch obvious selector issues: terminal \")\"; nonempty fallback match\n        // rselector never fails to match *something*\n        match = rselector.exec( selector ),\n        matched = !match.pop() && !match.pop(),\n        selectorGroups = matched && selector.match( rgroups ) || [\"\"],\n\n        preFilters = Expr.preFilter,\n        filters = Expr.filter,\n        checkContext = !xml && context !== document;\n\n    for ( ; (soFar = selectorGroups[i]) != null && matched; i++ ) {\n        groups.push( tokens = [] );\n\n        // Need to make sure we're within a narrower context if necessary\n        // Adding a descendant combinator will generate what is needed\n        if ( checkContext ) {\n            soFar = \" \" + soFar;\n        }\n\n        while ( soFar ) {\n            matched = false;\n\n            // Combinators\n            if ( (match = rcombinators.exec( soFar )) ) {\n                soFar = soFar.slice( match[0].length );\n\n                // Cast descendant combinators to space\n                matched = tokens.push({ part: match.pop().replace( rtrim, \" \" ), captures: match });\n            }\n\n            // Filters\n            for ( type in filters ) {\n                if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n                    (match = preFilters[ type ]( match, context, xml )) ) ) {\n\n                    soFar = soFar.slice( match.shift().length );\n                    matched = tokens.push({ part: type, captures: match });\n                }\n            }\n\n            if ( !matched ) {\n                break;\n            }\n        }\n    }\n\n    if ( !matched ) {\n        Sizzle.error( selector );\n    }\n\n    return groups;\n}\n\nfunction addCombinator( matcher, combinator, context ) {\n    var dir = combinator.dir,\n        doneName = done++;\n\n    if ( !matcher ) {\n        // If there is no matcher to check, check against the context\n        matcher = function( elem ) {\n            return elem === context;\n        };\n    }\n    return combinator.first ?\n        function( elem, context ) {\n            while ( (elem = elem[ dir ]) ) {\n                if ( elem.nodeType === 1 ) {\n                    return matcher( elem, context ) && elem;\n                }\n            }\n        } :\n        function( elem, context ) {\n            var cache,\n                dirkey = doneName + \".\" + dirruns,\n                cachedkey = dirkey + \".\" + cachedruns;\n            while ( (elem = elem[ dir ]) ) {\n                if ( elem.nodeType === 1 ) {\n                    if ( (cache = elem[ expando ]) === cachedkey ) {\n                        return elem.sizset;\n                    } else if ( typeof cache === \"string\" && cache.indexOf(dirkey) === 0 ) {\n                        if ( elem.sizset ) {\n                            return elem;\n                        }\n                    } else {\n                        elem[ expando ] = cachedkey;\n                        if ( matcher( elem, context ) ) {\n                            elem.sizset = true;\n                            return elem;\n                        }\n                        elem.sizset = false;\n                    }\n                }\n            }\n        };\n}\n\nfunction addMatcher( higher, deeper ) {\n    return higher ?\n        function( elem, context ) {\n            var result = deeper( elem, context );\n            return result && higher( result === true ? elem : result, context );\n        } :\n        deeper;\n}\n\n// [\"TAG\", \">\", \"ID\", \" \", \"CLASS\"]\nfunction matcherFromTokens( tokens, context, xml ) {\n    var token, matcher,\n        i = 0;\n\n    for ( ; (token = tokens[i]); i++ ) {\n        if ( Expr.relative[ token.part ] ) {\n            matcher = addCombinator( matcher, Expr.relative[ token.part ], context );\n        } else {\n            token.captures.push( context, xml );\n            matcher = addMatcher( matcher, Expr.filter[ token.part ].apply( null, token.captures ) );\n        }\n    }\n\n    return matcher;\n}\n\nfunction matcherFromGroupMatchers( matchers ) {\n    return function( elem, context ) {\n        var matcher,\n            j = 0;\n        for ( ; (matcher = matchers[j]); j++ ) {\n            if ( matcher(elem, context) ) {\n                return true;\n            }\n        }\n        return false;\n    };\n}\n\nvar compile = Sizzle.compile = function( selector, context, xml ) {\n    var tokens, group, i,\n        cached = compilerCache[ selector ];\n\n    // Return a cached group function if already generated (context dependent)\n    if ( cached && cached.context === context ) {\n        return cached;\n    }\n\n    // Generate a function of recursive functions that can be used to check each element\n    group = tokenize( selector, context, xml );\n    for ( i = 0; (tokens = group[i]); i++ ) {\n        group[i] = matcherFromTokens( tokens, context, xml );\n    }\n\n    // Cache the compiled function\n    cached = compilerCache[ selector ] = matcherFromGroupMatchers( group );\n    cached.context = context;\n    cached.runs = cached.dirruns = 0;\n    cachedSelectors.push( selector );\n    // Ensure only the most recent are cached\n    if ( cachedSelectors.length > Expr.cacheLength ) {\n        delete compilerCache[ cachedSelectors.shift() ];\n    }\n    return cached;\n};\n\nSizzle.matches = function( expr, elements ) {\n    return Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n    return Sizzle( expr, null, null, [ elem ] ).length > 0;\n};\n\nvar select = function( selector, context, results, seed, xml ) {\n    // Remove excessive whitespace\n    selector = selector.replace( rtrim, \"$1\" );\n    var elements, matcher, i, len, elem, token,\n        type, findContext, notTokens,\n        match = selector.match( rgroups ),\n        tokens = selector.match( rtokens ),\n        contextNodeType = context.nodeType;\n\n    // POS handling\n    if ( matchExpr[\"POS\"].test(selector) ) {\n        return handlePOS( selector, context, results, seed, match );\n    }\n\n    if ( seed ) {\n        elements = slice.call( seed, 0 );\n\n    // To maintain document order, only narrow the\n    // set if there is one group\n    } else if ( match && match.length === 1 ) {\n\n        // Take a shortcut and set the context if the root selector is an ID\n        if ( tokens.length > 1 && contextNodeType === 9 && !xml &&\n                (match = matchExpr[\"ID\"].exec( tokens[0] )) ) {\n\n            context = Expr.find[\"ID\"]( match[1], context, xml )[0];\n            if ( !context ) {\n                return results;\n            }\n\n            selector = selector.slice( tokens.shift().length );\n        }\n\n        findContext = ( (match = rsibling.exec( tokens[0] )) && !match.index && context.parentNode ) || context;\n\n        // Get the last token, excluding :not\n        notTokens = tokens.pop();\n        token = notTokens.split(\":not\")[0];\n\n        for ( i = 0, len = Expr.order.length; i < len; i++ ) {\n            type = Expr.order[i];\n\n            if ( (match = matchExpr[ type ].exec( token )) ) {\n                elements = Expr.find[ type ]( (match[1] || \"\").replace( rbackslash, \"\" ), findContext, xml );\n\n                if ( elements == null ) {\n                    continue;\n                }\n\n                if ( token === notTokens ) {\n                    selector = selector.slice( 0, selector.length - notTokens.length ) +\n                        token.replace( matchExpr[ type ], \"\" );\n\n                    if ( !selector ) {\n                        push.apply( results, slice.call(elements, 0) );\n                    }\n                }\n                break;\n            }\n        }\n    }\n\n    // Only loop over the given elements once\n    // If selector is empty, we're already done\n    if ( selector ) {\n        matcher = compile( selector, context, xml );\n        dirruns = matcher.dirruns++;\n\n        if ( elements == null ) {\n            elements = Expr.find[\"TAG\"]( \"*\", (rsibling.test( selector ) && context.parentNode) || context );\n        }\n        for ( i = 0; (elem = elements[i]); i++ ) {\n            cachedruns = matcher.runs++;\n            if ( matcher(elem, context) ) {\n                results.push( elem );\n            }\n        }\n    }\n\n    return results;\n};\n\nif ( document.querySelectorAll ) {\n    (function() {\n        var disconnectedMatch,\n            oldSelect = select,\n            rescape = /'|\\\\/g,\n            rattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n            rbuggyQSA = [],\n            // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n            // A support test would require too much code (would include document ready)\n            // just skip matchesSelector for :active\n            rbuggyMatches = [\":active\"],\n            matches = docElem.matchesSelector ||\n                docElem.mozMatchesSelector ||\n                docElem.webkitMatchesSelector ||\n                docElem.oMatchesSelector ||\n                docElem.msMatchesSelector;\n\n        // Build QSA regex\n        // Regex strategy adopted from Diego Perini\n        assert(function( div ) {\n            div.innerHTML = \"<select><option selected></option></select>\";\n\n            // IE8 - Some boolean attributes are not treated correctly\n            if ( !div.querySelectorAll(\"[selected]\").length ) {\n                rbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n            }\n\n            // Webkit/Opera - :checked should return selected option elements\n            // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n            // IE8 throws error here (do not put tests after this one)\n            if ( !div.querySelectorAll(\":checked\").length ) {\n                rbuggyQSA.push(\":checked\");\n            }\n        });\n\n        assert(function( div ) {\n\n            // Opera 10-12/IE9 - ^= $= *= and empty values\n            // Should not select anything\n            div.innerHTML = \"<p test=''></p>\";\n            if ( div.querySelectorAll(\"[test^='']\").length ) {\n                rbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n            }\n\n            // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n            // IE8 throws error here (do not put tests after this one)\n            div.innerHTML = \"<input type='hidden'>\";\n            if ( !div.querySelectorAll(\":enabled\").length ) {\n                rbuggyQSA.push(\":enabled\", \":disabled\");\n            }\n        });\n\n        rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\n        select = function( selector, context, results, seed, xml ) {\n            // Only use querySelectorAll when not filtering,\n            // when this is not xml,\n            // and when no QSA bugs apply\n            if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n                if ( context.nodeType === 9 ) {\n                    try {\n                        push.apply( results, slice.call(context.querySelectorAll( selector ), 0) );\n                        return results;\n                    } catch(qsaError) {}\n                // qSA works strangely on Element-rooted queries\n                // We can work around this by specifying an extra ID on the root\n                // and working up from there (Thanks to Andrew Dupont for the technique)\n                // IE 8 doesn't work on object elements\n                } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n                    var old = context.getAttribute(\"id\"),\n                        nid = old || expando,\n                        newContext = rsibling.test( selector ) && context.parentNode || context;\n\n                    if ( old ) {\n                        nid = nid.replace( rescape, \"\\\\$&\" );\n                    } else {\n                        context.setAttribute( \"id\", nid );\n                    }\n\n                    try {\n                        push.apply( results, slice.call( newContext.querySelectorAll(\n                            selector.replace( rgroups, \"[id='\" + nid + \"'] $&\" )\n                        ), 0 ) );\n                        return results;\n                    } catch(qsaError) {\n                    } finally {\n                        if ( !old ) {\n                            context.removeAttribute(\"id\");\n                        }\n                    }\n                }\n            }\n\n            return oldSelect( selector, context, results, seed, xml );\n        };\n\n        if ( matches ) {\n            assert(function( div ) {\n                // Check to see if it's possible to do matchesSelector\n                // on a disconnected node (IE 9)\n                disconnectedMatch = matches.call( div, \"div\" );\n\n                // This should fail with an exception\n                // Gecko does not error, returns false instead\n                try {\n                    matches.call( div, \"[test!='']:sizzle\" );\n                    rbuggyMatches.push( Expr.match.PSEUDO );\n                } catch ( e ) {}\n            });\n\n            // rbuggyMatches always contains :active, so no need for a length check\n            rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join(\"|\") );\n\n            Sizzle.matchesSelector = function( elem, expr ) {\n                // Make sure that attribute selectors are quoted\n                expr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n                // rbuggyMatches always contains :active, so no need for an existence check\n                if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {\n                    try {\n                        var ret = matches.call( elem, expr );\n\n                        // IE 9's matchesSelector returns false on disconnected nodes\n                        if ( ret || disconnectedMatch ||\n                                // As well, disconnected nodes are said to be in a document\n                                // fragment in IE 9\n                                elem.document && elem.document.nodeType !== 11 ) {\n                            return ret;\n                        }\n                    } catch(e) {}\n                }\n\n                return Sizzle( expr, null, null, [ elem ] ).length > 0;\n            };\n        }\n    })();\n}\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n    rparentsprev = /^(?:parents|prev(?:Until|All))/,\n    isSimple = /^.[^:#\\[\\.,]*$/,\n    rneedsContext = jQuery.expr.match.needsContext,\n    // methods guaranteed to produce a unique set when starting from a unique set\n    guaranteedUnique = {\n        children: true,\n        contents: true,\n        next: true,\n        prev: true\n    };\n\njQuery.fn.extend({\n    find: function( selector ) {\n        var i, l, length, n, r, ret,\n            self = this;\n\n        if ( typeof selector !== \"string\" ) {\n            return jQuery( selector ).filter(function() {\n                for ( i = 0, l = self.length; i < l; i++ ) {\n                    if ( jQuery.contains( self[ i ], this ) ) {\n                        return true;\n                    }\n                }\n            });\n        }\n\n        ret = this.pushStack( \"\", \"find\", selector );\n\n        for ( i = 0, l = this.length; i < l; i++ ) {\n            length = ret.length;\n            jQuery.find( selector, this[i], ret );\n\n            if ( i > 0 ) {\n                // Make sure that the results are unique\n                for ( n = length; n < ret.length; n++ ) {\n                    for ( r = 0; r < length; r++ ) {\n                        if ( ret[r] === ret[n] ) {\n                            ret.splice(n--, 1);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        return ret;\n    },\n\n    has: function( target ) {\n        var i,\n            targets = jQuery( target, this ),\n            len = targets.length;\n\n        return this.filter(function() {\n            for ( i = 0; i < len; i++ ) {\n                if ( jQuery.contains( this, targets[i] ) ) {\n                    return true;\n                }\n            }\n        });\n    },\n\n    not: function( selector ) {\n        return this.pushStack( winnow(this, selector, false), \"not\", selector);\n    },\n\n    filter: function( selector ) {\n        return this.pushStack( winnow(this, selector, true), \"filter\", selector );\n    },\n\n    is: function( selector ) {\n        return !!selector && (\n            typeof selector === \"string\" ?\n                // If this is a positional/relative selector, check membership in the returned set\n                // so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n                rneedsContext.test( selector ) ?\n                    jQuery( selector, this.context ).index( this[0] ) >= 0 :\n                    jQuery.filter( selector, this ).length > 0 :\n                this.filter( selector ).length > 0 );\n    },\n\n    closest: function( selectors, context ) {\n        var cur,\n            i = 0,\n            l = this.length,\n            ret = [],\n            pos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n                jQuery( selectors, context || this.context ) :\n                0;\n\n        for ( ; i < l; i++ ) {\n            cur = this[i];\n\n            while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n                if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n                    ret.push( cur );\n                    break;\n                }\n                cur = cur.parentNode;\n            }\n        }\n\n        ret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n        return this.pushStack( ret, \"closest\", selectors );\n    },\n\n    // Determine the position of an element within\n    // the matched set of elements\n    index: function( elem ) {\n\n        // No argument, return index in parent\n        if ( !elem ) {\n            return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n        }\n\n        // index in selector\n        if ( typeof elem === \"string\" ) {\n            return jQuery.inArray( this[0], jQuery( elem ) );\n        }\n\n        // Locate the position of the desired element\n        return jQuery.inArray(\n            // If it receives a jQuery object, the first element is used\n            elem.jquery ? elem[0] : elem, this );\n    },\n\n    add: function( selector, context ) {\n        var set = typeof selector === \"string\" ?\n                jQuery( selector, context ) :\n                jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n            all = jQuery.merge( this.get(), set );\n\n        return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n            all :\n            jQuery.unique( all ) );\n    },\n\n    addBack: function( selector ) {\n        return this.add( selector == null ?\n            this.prevObject : this.prevObject.filter(selector)\n        );\n    }\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n    return !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\nfunction sibling( cur, dir ) {\n    do {\n        cur = cur[ dir ];\n    } while ( cur && cur.nodeType !== 1 );\n\n    return cur;\n}\n\njQuery.each({\n    parent: function( elem ) {\n        var parent = elem.parentNode;\n        return parent && parent.nodeType !== 11 ? parent : null;\n    },\n    parents: function( elem ) {\n        return jQuery.dir( elem, \"parentNode\" );\n    },\n    parentsUntil: function( elem, i, until ) {\n        return jQuery.dir( elem, \"parentNode\", until );\n    },\n    next: function( elem ) {\n        return sibling( elem, \"nextSibling\" );\n    },\n    prev: function( elem ) {\n        return sibling( elem, \"previousSibling\" );\n    },\n    nextAll: function( elem ) {\n        return jQuery.dir( elem, \"nextSibling\" );\n    },\n    prevAll: function( elem ) {\n        return jQuery.dir( elem, \"previousSibling\" );\n    },\n    nextUntil: function( elem, i, until ) {\n        return jQuery.dir( elem, \"nextSibling\", until );\n    },\n    prevUntil: function( elem, i, until ) {\n        return jQuery.dir( elem, \"previousSibling\", until );\n    },\n    siblings: function( elem ) {\n        return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n    },\n    children: function( elem ) {\n        return jQuery.sibling( elem.firstChild );\n    },\n    contents: function( elem ) {\n        return jQuery.nodeName( elem, \"iframe\" ) ?\n            elem.contentDocument || elem.contentWindow.document :\n            jQuery.merge( [], elem.childNodes );\n    }\n}, function( name, fn ) {\n    jQuery.fn[ name ] = function( until, selector ) {\n        var ret = jQuery.map( this, fn, until );\n\n        if ( !runtil.test( name ) ) {\n            selector = until;\n        }\n\n        if ( selector && typeof selector === \"string\" ) {\n            ret = jQuery.filter( selector, ret );\n        }\n\n        ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n        if ( this.length > 1 && rparentsprev.test( name ) ) {\n            ret = ret.reverse();\n        }\n\n        return this.pushStack( ret, name, core_slice.call( arguments ).join(\",\") );\n    };\n});\n\njQuery.extend({\n    filter: function( expr, elems, not ) {\n        if ( not ) {\n            expr = \":not(\" + expr + \")\";\n        }\n\n        return elems.length === 1 ?\n            jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n            jQuery.find.matches(expr, elems);\n    },\n\n    dir: function( elem, dir, until ) {\n        var matched = [],\n            cur = elem[ dir ];\n\n        while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n            if ( cur.nodeType === 1 ) {\n                matched.push( cur );\n            }\n            cur = cur[dir];\n        }\n        return matched;\n    },\n\n    sibling: function( n, elem ) {\n        var r = [];\n\n        for ( ; n; n = n.nextSibling ) {\n            if ( n.nodeType === 1 && n !== elem ) {\n                r.push( n );\n            }\n        }\n\n        return r;\n    }\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n    // Can't pass null or undefined to indexOf in Firefox 4\n    // Set to 0 to skip string check\n    qualifier = qualifier || 0;\n\n    if ( jQuery.isFunction( qualifier ) ) {\n        return jQuery.grep(elements, function( elem, i ) {\n            var retVal = !!qualifier.call( elem, i, elem );\n            return retVal === keep;\n        });\n\n    } else if ( qualifier.nodeType ) {\n        return jQuery.grep(elements, function( elem, i ) {\n            return ( elem === qualifier ) === keep;\n        });\n\n    } else if ( typeof qualifier === \"string\" ) {\n        var filtered = jQuery.grep(elements, function( elem ) {\n            return elem.nodeType === 1;\n        });\n\n        if ( isSimple.test( qualifier ) ) {\n            return jQuery.filter(qualifier, filtered, !keep);\n        } else {\n            qualifier = jQuery.filter( qualifier, filtered );\n        }\n    }\n\n    return jQuery.grep(elements, function( elem, i ) {\n        return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n    });\n}\nfunction createSafeFragment( document ) {\n    var list = nodeNames.split( \"|\" ),\n    safeFrag = document.createDocumentFragment();\n\n    if ( safeFrag.createElement ) {\n        while ( list.length ) {\n            safeFrag.createElement(\n                list.pop()\n            );\n        }\n    }\n    return safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n        \"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n    rinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n    rleadingWhitespace = /^\\s+/,\n    rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n    rtagName = /<([\\w:]+)/,\n    rtbody = /<tbody/i,\n    rhtml = /<|&#?\\w+;/,\n    rnoInnerhtml = /<(?:script|style|link)/i,\n    rnocache = /<(?:script|object|embed|option|style)/i,\n    rnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n    rcheckableType = /^(?:checkbox|radio)$/,\n    // checked=\"checked\" or checked\n    rchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n    rscriptType = /\\/(java|ecma)script/i,\n    rcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)|[\\]\\-]{2}>\\s*$/g,\n    wrapMap = {\n        option: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n        legend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n        thead: [ 1, \"<table>\", \"</table>\" ],\n        tr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n        td: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n        col: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n        area: [ 1, \"<map>\", \"</map>\" ],\n        _default: [ 0, \"\", \"\" ]\n    },\n    safeFragment = createSafeFragment( document ),\n    fragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n// unless wrapped in a div with non-breaking characters in front of it.\nif ( !jQuery.support.htmlSerialize ) {\n    wrapMap._default = [ 1, \"X<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n    text: function( value ) {\n        return jQuery.access( this, function( value ) {\n            return value === undefined ?\n                jQuery.text( this ) :\n                this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n        }, null, value, arguments.length );\n    },\n\n    wrapAll: function( html ) {\n        if ( jQuery.isFunction( html ) ) {\n            return this.each(function(i) {\n                jQuery(this).wrapAll( html.call(this, i) );\n            });\n        }\n\n        if ( this[0] ) {\n            // The elements to wrap the target around\n            var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n            if ( this[0].parentNode ) {\n                wrap.insertBefore( this[0] );\n            }\n\n            wrap.map(function() {\n                var elem = this;\n\n                while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n                    elem = elem.firstChild;\n                }\n\n                return elem;\n            }).append( this );\n        }\n\n        return this;\n    },\n\n    wrapInner: function( html ) {\n        if ( jQuery.isFunction( html ) ) {\n            return this.each(function(i) {\n                jQuery(this).wrapInner( html.call(this, i) );\n            });\n        }\n\n        return this.each(function() {\n            var self = jQuery( this ),\n                contents = self.contents();\n\n            if ( contents.length ) {\n                contents.wrapAll( html );\n\n            } else {\n                self.append( html );\n            }\n        });\n    },\n\n    wrap: function( html ) {\n        var isFunction = jQuery.isFunction( html );\n\n        return this.each(function(i) {\n            jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n        });\n    },\n\n    unwrap: function() {\n        return this.parent().each(function() {\n            if ( !jQuery.nodeName( this, \"body\" ) ) {\n                jQuery( this ).replaceWith( this.childNodes );\n            }\n        }).end();\n    },\n\n    append: function() {\n        return this.domManip(arguments, true, function( elem ) {\n            if ( this.nodeType === 1 || this.nodeType === 11 ) {\n                this.appendChild( elem );\n            }\n        });\n    },\n\n    prepend: function() {\n        return this.domManip(arguments, true, function( elem ) {\n            if ( this.nodeType === 1 || this.nodeType === 11 ) {\n                this.insertBefore( elem, this.firstChild );\n            }\n        });\n    },\n\n    before: function() {\n        if ( !isDisconnected( this[0] ) ) {\n            return this.domManip(arguments, false, function( elem ) {\n                this.parentNode.insertBefore( elem, this );\n            });\n        }\n\n        if ( arguments.length ) {\n            var set = jQuery.clean( arguments );\n            return this.pushStack( jQuery.merge( set, this ), \"before\", this.selector );\n        }\n    },\n\n    after: function() {\n        if ( !isDisconnected( this[0] ) ) {\n            return this.domManip(arguments, false, function( elem ) {\n                this.parentNode.insertBefore( elem, this.nextSibling );\n            });\n        }\n\n        if ( arguments.length ) {\n            var set = jQuery.clean( arguments );\n            return this.pushStack( jQuery.merge( this, set ), \"after\", this.selector );\n        }\n    },\n\n    // keepData is for internal use only--do not document\n    remove: function( selector, keepData ) {\n        var elem,\n            i = 0;\n\n        for ( ; (elem = this[i]) != null; i++ ) {\n            if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n                if ( !keepData && elem.nodeType === 1 ) {\n                    jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n                    jQuery.cleanData( [ elem ] );\n                }\n\n                if ( elem.parentNode ) {\n                    elem.parentNode.removeChild( elem );\n                }\n            }\n        }\n\n        return this;\n    },\n\n    empty: function() {\n        var elem,\n            i = 0;\n\n        for ( ; (elem = this[i]) != null; i++ ) {\n            // Remove element nodes and prevent memory leaks\n            if ( elem.nodeType === 1 ) {\n                jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n            }\n\n            // Remove any remaining nodes\n            while ( elem.firstChild ) {\n                elem.removeChild( elem.firstChild );\n            }\n        }\n\n        return this;\n    },\n\n    clone: function( dataAndEvents, deepDataAndEvents ) {\n        dataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n        deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n        return this.map( function () {\n            return jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n        });\n    },\n\n    html: function( value ) {\n        return jQuery.access( this, function( value ) {\n            var elem = this[0] || {},\n                i = 0,\n                l = this.length;\n\n            if ( value === undefined ) {\n                return elem.nodeType === 1 ?\n                    elem.innerHTML.replace( rinlinejQuery, \"\" ) :\n                    undefined;\n            }\n\n            // See if we can take a shortcut and just use innerHTML\n            if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n                ( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n                ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n                !wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n                value = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n                try {\n                    for (; i < l; i++ ) {\n                        // Remove element nodes and prevent memory leaks\n                        elem = this[i] || {};\n                        if ( elem.nodeType === 1 ) {\n                            jQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n                            elem.innerHTML = value;\n                        }\n                    }\n\n                    elem = 0;\n\n                // If using innerHTML throws an exception, use the fallback method\n                } catch(e) {}\n            }\n\n            if ( elem ) {\n                this.empty().append( value );\n            }\n        }, null, value, arguments.length );\n    },\n\n    replaceWith: function( value ) {\n        if ( !isDisconnected( this[0] ) ) {\n            // Make sure that the elements are removed from the DOM before they are inserted\n            // this can help fix replacing a parent with child elements\n            if ( jQuery.isFunction( value ) ) {\n                return this.each(function(i) {\n                    var self = jQuery(this), old = self.html();\n                    self.replaceWith( value.call( this, i, old ) );\n                });\n            }\n\n            if ( typeof value !== \"string\" ) {\n                value = jQuery( value ).detach();\n            }\n\n            return this.each(function() {\n                var next = this.nextSibling,\n                    parent = this.parentNode;\n\n                jQuery( this ).remove();\n\n                if ( next ) {\n                    jQuery(next).before( value );\n                } else {\n                    jQuery(parent).append( value );\n                }\n            });\n        }\n\n        return this.length ?\n            this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n            this;\n    },\n\n    detach: function( selector ) {\n        return this.remove( selector, true );\n    },\n\n    domManip: function( args, table, callback ) {\n\n        // Flatten any nested arrays\n        args = [].concat.apply( [], args );\n\n        var results, first, fragment, iNoClone,\n            i = 0,\n            value = args[0],\n            scripts = [],\n            l = this.length;\n\n        // We can't cloneNode fragments that contain checked, in WebKit\n        if ( !jQuery.support.checkClone && l > 1 && typeof value === \"string\" && rchecked.test( value ) ) {\n            return this.each(function() {\n                jQuery(this).domManip( args, table, callback );\n            });\n        }\n\n        if ( jQuery.isFunction(value) ) {\n            return this.each(function(i) {\n                var self = jQuery(this);\n                args[0] = value.call( this, i, table ? self.html() : undefined );\n                self.domManip( args, table, callback );\n            });\n        }\n\n        if ( this[0] ) {\n            results = jQuery.buildFragment( args, this, scripts );\n            fragment = results.fragment;\n            first = fragment.firstChild;\n\n            if ( fragment.childNodes.length === 1 ) {\n                fragment = first;\n            }\n\n            if ( first ) {\n                table = table && jQuery.nodeName( first, \"tr\" );\n\n                // Use the original fragment for the last item instead of the first because it can end up\n                // being emptied incorrectly in certain situations (#8070).\n                // Fragments from the fragment cache must always be cloned and never used in place.\n                for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {\n                    callback.call(\n                        table && jQuery.nodeName( this[i], \"table\" ) ?\n                            findOrAppend( this[i], \"tbody\" ) :\n                            this[i],\n                        i === iNoClone ?\n                            fragment :\n                            jQuery.clone( fragment, true, true )\n                    );\n                }\n            }\n\n            // Fix #11809: Avoid leaking memory\n            fragment = first = null;\n\n            if ( scripts.length ) {\n                jQuery.each( scripts, function( i, elem ) {\n                    if ( elem.src ) {\n                        if ( jQuery.ajax ) {\n                            jQuery.ajax({\n                                url: elem.src,\n                                type: \"GET\",\n                                dataType: \"script\",\n                                async: false,\n                                global: false,\n                                \"throws\": true\n                            });\n                        } else {\n                            jQuery.error(\"no ajax\");\n                        }\n                    } else {\n                        jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n                    }\n\n                    if ( elem.parentNode ) {\n                        elem.parentNode.removeChild( elem );\n                    }\n                });\n            }\n        }\n\n        return this;\n    }\n});\n\nfunction findOrAppend( elem, tag ) {\n    return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n    if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n        return;\n    }\n\n    var type, i, l,\n        oldData = jQuery._data( src ),\n        curData = jQuery._data( dest, oldData ),\n        events = oldData.events;\n\n    if ( events ) {\n        delete curData.handle;\n        curData.events = {};\n\n        for ( type in events ) {\n            for ( i = 0, l = events[ type ].length; i < l; i++ ) {\n                jQuery.event.add( dest, type, events[ type ][ i ] );\n            }\n        }\n    }\n\n    // make the cloned public data object a copy from the original\n    if ( curData.data ) {\n        curData.data = jQuery.extend( {}, curData.data );\n    }\n}\n\nfunction cloneFixAttributes( src, dest ) {\n    var nodeName;\n\n    // We do not need to do anything for non-Elements\n    if ( dest.nodeType !== 1 ) {\n        return;\n    }\n\n    // clearAttributes removes the attributes, which we don't want,\n    // but also removes the attachEvent events, which we *do* want\n    if ( dest.clearAttributes ) {\n        dest.clearAttributes();\n    }\n\n    // mergeAttributes, in contrast, only merges back on the\n    // original attributes, not the events\n    if ( dest.mergeAttributes ) {\n        dest.mergeAttributes( src );\n    }\n\n    nodeName = dest.nodeName.toLowerCase();\n\n    if ( nodeName === \"object\" ) {\n        // IE6-10 improperly clones children of object elements using classid.\n        // IE10 throws NoModificationAllowedError if parent is null, #12132.\n        if ( dest.parentNode ) {\n            dest.outerHTML = src.outerHTML;\n        }\n\n        // This path appears unavoidable for IE9. When cloning an object\n        // element in IE9, the outerHTML strategy above is not sufficient.\n        // If the src has innerHTML and the destination does not,\n        // copy the src.innerHTML into the dest.innerHTML. #10324\n        if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {\n            dest.innerHTML = src.innerHTML;\n        }\n\n    } else if ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n        // IE6-8 fails to persist the checked state of a cloned checkbox\n        // or radio button. Worse, IE6-7 fail to give the cloned element\n        // a checked appearance if the defaultChecked value isn't also set\n\n        dest.defaultChecked = dest.checked = src.checked;\n\n        // IE6-7 get confused and end up setting the value of a cloned\n        // checkbox/radio button to an empty string instead of \"on\"\n        if ( dest.value !== src.value ) {\n            dest.value = src.value;\n        }\n\n    // IE6-8 fails to return the selected option to the default selected\n    // state when cloning options\n    } else if ( nodeName === \"option\" ) {\n        dest.selected = src.defaultSelected;\n\n    // IE6-8 fails to set the defaultValue to the correct value when\n    // cloning other types of input fields\n    } else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n        dest.defaultValue = src.defaultValue;\n\n    // IE blanks contents when cloning scripts\n    } else if ( nodeName === \"script\" && dest.text !== src.text ) {\n        dest.text = src.text;\n    }\n\n    // Event data gets referenced instead of copied if the expando\n    // gets copied too\n    dest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, context, scripts ) {\n    var fragment, cacheable, cachehit,\n        first = args[ 0 ];\n\n    // Set context from what may come in as undefined or a jQuery collection or a node\n    context = context || document;\n    context = (context[0] || context).ownerDocument || context[0] || context;\n\n    // Ensure that an attr object doesn't incorrectly stand in as a document object\n    // Chrome and Firefox seem to allow this to occur and will throw exception\n    // Fixes #8950\n    if ( typeof context.createDocumentFragment === \"undefined\" ) {\n        context = document;\n    }\n\n    // Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n    // Cloning options loses the selected state, so don't cache them\n    // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n    // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n    // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n    if ( args.length === 1 && typeof first === \"string\" && first.length < 512 && context === document &&\n        first.charAt(0) === \"<\" && !rnocache.test( first ) &&\n        (jQuery.support.checkClone || !rchecked.test( first )) &&\n        (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n        // Mark cacheable and look for a hit\n        cacheable = true;\n        fragment = jQuery.fragments[ first ];\n        cachehit = fragment !== undefined;\n    }\n\n    if ( !fragment ) {\n        fragment = context.createDocumentFragment();\n        jQuery.clean( args, context, fragment, scripts );\n\n        // Update the cache, but only store false\n        // unless this is a second parsing of the same content\n        if ( cacheable ) {\n            jQuery.fragments[ first ] = cachehit && fragment;\n        }\n    }\n\n    return { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n    appendTo: \"append\",\n    prependTo: \"prepend\",\n    insertBefore: \"before\",\n    insertAfter: \"after\",\n    replaceAll: \"replaceWith\"\n}, function( name, original ) {\n    jQuery.fn[ name ] = function( selector ) {\n        var elems,\n            i = 0,\n            ret = [],\n            insert = jQuery( selector ),\n            l = insert.length,\n            parent = this.length === 1 && this[0].parentNode;\n\n        if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {\n            insert[ original ]( this[0] );\n            return this;\n        } else {\n            for ( ; i < l; i++ ) {\n                elems = ( i > 0 ? this.clone(true) : this ).get();\n                jQuery( insert[i] )[ original ]( elems );\n                ret = ret.concat( elems );\n            }\n\n            return this.pushStack( ret, name, insert.selector );\n        }\n    };\n});\n\nfunction getAll( elem ) {\n    if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n        return elem.getElementsByTagName( \"*\" );\n\n    } else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n        return elem.querySelectorAll( \"*\" );\n\n    } else {\n        return [];\n    }\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n    if ( rcheckableType.test( elem.type ) ) {\n        elem.defaultChecked = elem.checked;\n    }\n}\n\njQuery.extend({\n    clone: function( elem, dataAndEvents, deepDataAndEvents ) {\n        var srcElements,\n            destElements,\n            i,\n            clone;\n\n        if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n            clone = elem.cloneNode( true );\n\n        // IE<=8 does not properly clone detached, unknown element nodes\n        } else {\n            fragmentDiv.innerHTML = elem.outerHTML;\n            fragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n        }\n\n        if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n                (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n            // IE copies events bound via attachEvent when using cloneNode.\n            // Calling detachEvent on the clone will also remove the events\n            // from the original. In order to get around this, we use some\n            // proprietary methods to clear the events. Thanks to MooTools\n            // guys for this hotness.\n\n            cloneFixAttributes( elem, clone );\n\n            // Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n            srcElements = getAll( elem );\n            destElements = getAll( clone );\n\n            // Weird iteration because IE will replace the length property\n            // with an element if you are cloning the body and one of the\n            // elements on the page has a name or id of \"length\"\n            for ( i = 0; srcElements[i]; ++i ) {\n                // Ensure that the destination node is not null; Fixes #9587\n                if ( destElements[i] ) {\n                    cloneFixAttributes( srcElements[i], destElements[i] );\n                }\n            }\n        }\n\n        // Copy the events from the original to the clone\n        if ( dataAndEvents ) {\n            cloneCopyEvent( elem, clone );\n\n            if ( deepDataAndEvents ) {\n                srcElements = getAll( elem );\n                destElements = getAll( clone );\n\n                for ( i = 0; srcElements[i]; ++i ) {\n                    cloneCopyEvent( srcElements[i], destElements[i] );\n                }\n            }\n        }\n\n        srcElements = destElements = null;\n\n        // Return the cloned set\n        return clone;\n    },\n\n    clean: function( elems, context, fragment, scripts ) {\n        var j, safe, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,\n            i = 0,\n            ret = [];\n\n        // Ensure that context is a document\n        if ( !context || typeof context.createDocumentFragment === \"undefined\" ) {\n            context = document;\n        }\n\n        // Use the already-created safe fragment if context permits\n        for ( safe = context === document && safeFragment; (elem = elems[i]) != null; i++ ) {\n            if ( typeof elem === \"number\" ) {\n                elem += \"\";\n            }\n\n            if ( !elem ) {\n                continue;\n            }\n\n            // Convert html string into DOM nodes\n            if ( typeof elem === \"string\" ) {\n                if ( !rhtml.test( elem ) ) {\n                    elem = context.createTextNode( elem );\n                } else {\n                    // Ensure a safe container in which to render the html\n                    safe = safe || createSafeFragment( context );\n                    div = div || safe.appendChild( context.createElement(\"div\") );\n\n                    // Fix \"XHTML\"-style tags in all browsers\n                    elem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n                    // Go to html and back, then peel off extra wrappers\n                    tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n                    wrap = wrapMap[ tag ] || wrapMap._default;\n                    depth = wrap[0];\n                    div.innerHTML = wrap[1] + elem + wrap[2];\n\n                    // Move to the right depth\n                    while ( depth-- ) {\n                        div = div.lastChild;\n                    }\n\n                    // Remove IE's autoinserted <tbody> from table fragments\n                    if ( !jQuery.support.tbody ) {\n\n                        // String was a <table>, *may* have spurious <tbody>\n                        hasBody = rtbody.test(elem);\n                            tbody = tag === \"table\" && !hasBody ?\n                                div.firstChild && div.firstChild.childNodes :\n\n                                // String was a bare <thead> or <tfoot>\n                                wrap[1] === \"<table>\" && !hasBody ?\n                                    div.childNodes :\n                                    [];\n\n                        for ( j = tbody.length - 1; j >= 0 ; --j ) {\n                            if ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n                                tbody[ j ].parentNode.removeChild( tbody[ j ] );\n                            }\n                        }\n                    }\n\n                    // IE completely kills leading whitespace when innerHTML is used\n                    if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n                        div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n                    }\n\n                    elem = div.childNodes;\n\n                    // Remember the top-level container for proper cleanup\n                    div = safe.lastChild;\n                }\n            }\n\n            if ( elem.nodeType ) {\n                ret.push( elem );\n            } else {\n                ret = jQuery.merge( ret, elem );\n            }\n        }\n\n        // Fix #11356: Clear elements from safeFragment\n        if ( div ) {\n            safe.removeChild( div );\n            elem = div = safe = null;\n        }\n\n        // Reset defaultChecked for any radios and checkboxes\n        // about to be appended to the DOM in IE 6/7 (#8060)\n        if ( !jQuery.support.appendChecked ) {\n            for ( i = 0; (elem = ret[i]) != null; i++ ) {\n                if ( jQuery.nodeName( elem, \"input\" ) ) {\n                    fixDefaultChecked( elem );\n                } else if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n                    jQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n                }\n            }\n        }\n\n        // Append elements to a provided document fragment\n        if ( fragment ) {\n            // Special handling of each script element\n            handleScript = function( elem ) {\n                // Check if we consider it executable\n                if ( !elem.type || rscriptType.test( elem.type ) ) {\n                    // Detach the script and store it in the scripts array (if provided) or the fragment\n                    // Return truthy to indicate that it has been handled\n                    return scripts ?\n                        scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :\n                        fragment.appendChild( elem );\n                }\n            };\n\n            for ( i = 0; (elem = ret[i]) != null; i++ ) {\n                // Check if we're done after handling an executable script\n                if ( !( jQuery.nodeName( elem, \"script\" ) && handleScript( elem ) ) ) {\n                    // Append to fragment and handle embedded scripts\n                    fragment.appendChild( elem );\n                    if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n                        // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration\n                        jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName(\"script\") ), handleScript );\n\n                        // Splice the scripts into ret after their former ancestor and advance our index beyond them\n                        ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n                        i += jsTags.length;\n                    }\n                }\n            }\n        }\n\n        return ret;\n    },\n\n    cleanData: function( elems, /* internal */ acceptData ) {\n        var data, id, elem, type,\n            i = 0,\n            internalKey = jQuery.expando,\n            cache = jQuery.cache,\n            deleteExpando = jQuery.support.deleteExpando,\n            special = jQuery.event.special;\n\n        for ( ; (elem = elems[i]) != null; i++ ) {\n\n            if ( acceptData || jQuery.acceptData( elem ) ) {\n\n                id = elem[ internalKey ];\n                data = id && cache[ id ];\n\n                if ( data ) {\n                    if ( data.events ) {\n                        for ( type in data.events ) {\n                            if ( special[ type ] ) {\n                                jQuery.event.remove( elem, type );\n\n                            // This is a shortcut to avoid jQuery.event.remove's overhead\n                            } else {\n                                jQuery.removeEvent( elem, type, data.handle );\n                            }\n                        }\n                    }\n\n                    // Remove cache only if it was not already removed by jQuery.event.remove\n                    if ( cache[ id ] ) {\n\n                        delete cache[ id ];\n\n                        // IE does not allow us to delete expando properties from nodes,\n                        // nor does it have a removeAttribute function on Document nodes;\n                        // we must handle all of these cases\n                        if ( deleteExpando ) {\n                            delete elem[ internalKey ];\n\n                        } else if ( elem.removeAttribute ) {\n                            elem.removeAttribute( internalKey );\n\n                        } else {\n                            elem[ internalKey ] = null;\n                        }\n\n                        jQuery.deletedIds.push( id );\n                    }\n                }\n            }\n        }\n    }\n});\n// Limit scope pollution from any deprecated API\n(function() {\n\nvar matched, browser;\n\n// Use of jQuery.browser is frowned upon.\n// More details: http://api.jquery.com/jQuery.browser\n// jQuery.uaMatch maintained for back-compat\njQuery.uaMatch = function( ua ) {\n    ua = ua.toLowerCase();\n\n    var match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n        /(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n        /(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n        /(msie) ([\\w.]+)/.exec( ua ) ||\n        ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n        [];\n\n    return {\n        browser: match[ 1 ] || \"\",\n        version: match[ 2 ] || \"0\"\n    };\n};\n\nmatched = jQuery.uaMatch( navigator.userAgent );\nbrowser = {};\n\nif ( matched.browser ) {\n    browser[ matched.browser ] = true;\n    browser.version = matched.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\n// Maintained for back-compat only\nif ( browser.webkit ) {\n    browser.safari = true;\n}\n\njQuery.browser = browser;\n\njQuery.sub = function() {\n    function jQuerySub( selector, context ) {\n        return new jQuerySub.fn.init( selector, context );\n    }\n    jQuery.extend( true, jQuerySub, this );\n    jQuerySub.superclass = this;\n    jQuerySub.fn = jQuerySub.prototype = this();\n    jQuerySub.fn.constructor = jQuerySub;\n    jQuerySub.sub = this.sub;\n    jQuerySub.fn.init = function init( selector, context ) {\n        if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n            context = jQuerySub( context );\n        }\n\n        return jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n    };\n    jQuerySub.fn.init.prototype = jQuerySub.fn;\n    var rootjQuerySub = jQuerySub(document);\n    return jQuerySub;\n};\n    \n})();\nvar curCSS, iframe, iframeDoc,\n    ralpha = /alpha\\([^)]*\\)/i,\n    ropacity = /opacity=([^)]*)/,\n    rposition = /^(top|right|bottom|left)$/,\n    rmargin = /^margin/,\n    rnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n    rnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n    rrelNum = new RegExp( \"^([-+])=(\" + core_pnum + \")\", \"i\" ),\n    elemdisplay = {},\n\n    cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n    cssNormalTransform = {\n        letterSpacing: 0,\n        fontWeight: 400,\n        lineHeight: 1\n    },\n\n    cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n    cssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ],\n\n    eventsToggle = jQuery.fn.toggle;\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n    // shortcut for names that are not vendor prefixed\n    if ( name in style ) {\n        return name;\n    }\n\n    // check for vendor prefixed names\n    var capName = name.charAt(0).toUpperCase() + name.slice(1),\n        origName = name,\n        i = cssPrefixes.length;\n\n    while ( i-- ) {\n        name = cssPrefixes[ i ] + capName;\n        if ( name in style ) {\n            return name;\n        }\n    }\n\n    return origName;\n}\n\nfunction isHidden( elem, el ) {\n    elem = el || elem;\n    return jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n    var elem, display,\n        values = [],\n        index = 0,\n        length = elements.length;\n\n    for ( ; index < length; index++ ) {\n        elem = elements[ index ];\n        if ( !elem.style ) {\n            continue;\n        }\n        values[ index ] = jQuery._data( elem, \"olddisplay\" );\n        if ( show ) {\n            // Reset the inline display of this element to learn if it is\n            // being hidden by cascaded rules or not\n            if ( !values[ index ] && elem.style.display === \"none\" ) {\n                elem.style.display = \"\";\n            }\n\n            // Set elements which have been overridden with display: none\n            // in a stylesheet to whatever the default browser style is\n            // for such an element\n            if ( elem.style.display === \"\" && isHidden( elem ) ) {\n                values[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n            }\n        } else {\n            display = curCSS( elem, \"display\" );\n\n            if ( !values[ index ] && display !== \"none\" ) {\n                jQuery._data( elem, \"olddisplay\", display );\n            }\n        }\n    }\n\n    // Set the display of most of the elements in a second loop\n    // to avoid the constant reflow\n    for ( index = 0; index < length; index++ ) {\n        elem = elements[ index ];\n        if ( !elem.style ) {\n            continue;\n        }\n        if ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n            elem.style.display = show ? values[ index ] || \"\" : \"none\";\n        }\n    }\n\n    return elements;\n}\n\njQuery.fn.extend({\n    css: function( name, value ) {\n        return jQuery.access( this, function( elem, name, value ) {\n            return value !== undefined ?\n                jQuery.style( elem, name, value ) :\n                jQuery.css( elem, name );\n        }, name, value, arguments.length > 1 );\n    },\n    show: function() {\n        return showHide( this, true );\n    },\n    hide: function() {\n        return showHide( this );\n    },\n    toggle: function( state, fn2 ) {\n        var bool = typeof state === \"boolean\";\n\n        if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {\n            return eventsToggle.apply( this, arguments );\n        }\n\n        return this.each(function() {\n            if ( bool ? state : isHidden( this ) ) {\n                jQuery( this ).show();\n            } else {\n                jQuery( this ).hide();\n            }\n        });\n    }\n});\n\njQuery.extend({\n    // Add in style property hooks for overriding the default\n    // behavior of getting and setting a style property\n    cssHooks: {\n        opacity: {\n            get: function( elem, computed ) {\n                if ( computed ) {\n                    // We should always get a number back from opacity\n                    var ret = curCSS( elem, \"opacity\" );\n                    return ret === \"\" ? \"1\" : ret;\n\n                }\n            }\n        }\n    },\n\n    // Exclude the following css properties to add px\n    cssNumber: {\n        \"fillOpacity\": true,\n        \"fontWeight\": true,\n        \"lineHeight\": true,\n        \"opacity\": true,\n        \"orphans\": true,\n        \"widows\": true,\n        \"zIndex\": true,\n        \"zoom\": true\n    },\n\n    // Add in properties whose names you wish to fix before\n    // setting or getting the value\n    cssProps: {\n        // normalize float css property\n        \"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n    },\n\n    // Get and set the style property on a DOM Node\n    style: function( elem, name, value, extra ) {\n        // Don't set styles on text and comment nodes\n        if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n            return;\n        }\n\n        // Make sure that we're working with the right name\n        var ret, type, hooks,\n            origName = jQuery.camelCase( name ),\n            style = elem.style;\n\n        name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n        // gets hook for the prefixed version\n        // followed by the unprefixed version\n        hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n        // Check if we're setting a value\n        if ( value !== undefined ) {\n            type = typeof value;\n\n            // convert relative number strings (+= or -=) to relative numbers. #7345\n            if ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n                value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n                // Fixes bug #9237\n                type = \"number\";\n            }\n\n            // Make sure that NaN and null values aren't set. See: #7116\n            if ( value == null || type === \"number\" && isNaN( value ) ) {\n                return;\n            }\n\n            // If a number was passed in, add 'px' to the (except for certain CSS properties)\n            if ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n                value += \"px\";\n            }\n\n            // If a hook was provided, use that value, otherwise just set the specified value\n            if ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n                // Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n                // Fixes bug #5509\n                try {\n                    style[ name ] = value;\n                } catch(e) {}\n            }\n\n        } else {\n            // If a hook was provided get the non-computed value from there\n            if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n                return ret;\n            }\n\n            // Otherwise just get the value from the style object\n            return style[ name ];\n        }\n    },\n\n    css: function( elem, name, numeric, extra ) {\n        var val, num, hooks,\n            origName = jQuery.camelCase( name );\n\n        // Make sure that we're working with the right name\n        name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n        // gets hook for the prefixed version\n        // followed by the unprefixed version\n        hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n        // If a hook was provided get the computed value from there\n        if ( hooks && \"get\" in hooks ) {\n            val = hooks.get( elem, true, extra );\n        }\n\n        // Otherwise, if a way to get the computed value exists, use that\n        if ( val === undefined ) {\n            val = curCSS( elem, name );\n        }\n\n        //convert \"normal\" to computed value\n        if ( val === \"normal\" && name in cssNormalTransform ) {\n            val = cssNormalTransform[ name ];\n        }\n\n        // Return, converting to number if forced or a qualifier was provided and val looks numeric\n        if ( numeric || extra !== undefined ) {\n            num = parseFloat( val );\n            return numeric || jQuery.isNumeric( num ) ? num || 0 : val;\n        }\n        return val;\n    },\n\n    // A method for quickly swapping in/out CSS properties to get correct calculations\n    swap: function( elem, options, callback ) {\n        var ret, name,\n            old = {};\n\n        // Remember the old values, and insert the new ones\n        for ( name in options ) {\n            old[ name ] = elem.style[ name ];\n            elem.style[ name ] = options[ name ];\n        }\n\n        ret = callback.call( elem );\n\n        // Revert the old values\n        for ( name in options ) {\n            elem.style[ name ] = old[ name ];\n        }\n\n        return ret;\n    }\n});\n\n// NOTE: To any future maintainer, we've used both window.getComputedStyle\n// and getComputedStyle here to produce a better gzip size\nif ( window.getComputedStyle ) {\n    curCSS = function( elem, name ) {\n        var ret, width, minWidth, maxWidth,\n            computed = getComputedStyle( elem, null ),\n            style = elem.style;\n\n        if ( computed ) {\n\n            ret = computed[ name ];\n            if ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n                ret = jQuery.style( elem, name );\n            }\n\n            // A tribute to the \"awesome hack by Dean Edwards\"\n            // Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n            // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n            // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n            if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n                width = style.width;\n                minWidth = style.minWidth;\n                maxWidth = style.maxWidth;\n\n                style.minWidth = style.maxWidth = style.width = ret;\n                ret = computed.width;\n\n                style.width = width;\n                style.minWidth = minWidth;\n                style.maxWidth = maxWidth;\n            }\n        }\n\n        return ret;\n    };\n} else if ( document.documentElement.currentStyle ) {\n    curCSS = function( elem, name ) {\n        var left, rsLeft,\n            ret = elem.currentStyle && elem.currentStyle[ name ],\n            style = elem.style;\n\n        // Avoid setting ret to empty string here\n        // so we don't default to auto\n        if ( ret == null && style && style[ name ] ) {\n            ret = style[ name ];\n        }\n\n        // From the awesome hack by Dean Edwards\n        // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n        // If we're not dealing with a regular pixel number\n        // but a number that has a weird ending, we need to convert it to pixels\n        // but not position css attributes, as those are proportional to the parent element instead\n        // and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n        if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n            // Remember the original values\n            left = style.left;\n            rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n            // Put in the new values to get a computed value out\n            if ( rsLeft ) {\n                elem.runtimeStyle.left = elem.currentStyle.left;\n            }\n            style.left = name === \"fontSize\" ? \"1em\" : ret;\n            ret = style.pixelLeft + \"px\";\n\n            // Revert the changed values\n            style.left = left;\n            if ( rsLeft ) {\n                elem.runtimeStyle.left = rsLeft;\n            }\n        }\n\n        return ret === \"\" ? \"auto\" : ret;\n    };\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n    var matches = rnumsplit.exec( value );\n    return matches ?\n            Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n            value;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox ) {\n    var i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n        // If we already have the right measurement, avoid augmentation\n        4 :\n        // Otherwise initialize for horizontal or vertical properties\n        name === \"width\" ? 1 : 0,\n\n        val = 0;\n\n    for ( ; i < 4; i += 2 ) {\n        // both box models exclude margin, so add it if we want it\n        if ( extra === \"margin\" ) {\n            // we use jQuery.css instead of curCSS here\n            // because of the reliableMarginRight CSS hook!\n            val += jQuery.css( elem, extra + cssExpand[ i ], true );\n        }\n\n        // From this point on we use curCSS for maximum performance (relevant in animations)\n        if ( isBorderBox ) {\n            // border-box includes padding, so remove it if we want content\n            if ( extra === \"content\" ) {\n                val -= parseFloat( curCSS( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n            }\n\n            // at this point, extra isn't border nor margin, so remove border\n            if ( extra !== \"margin\" ) {\n                val -= parseFloat( curCSS( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n            }\n        } else {\n            // at this point, extra isn't content, so add padding\n            val += parseFloat( curCSS( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\n            // at this point, extra isn't content nor padding, so add border\n            if ( extra !== \"padding\" ) {\n                val += parseFloat( curCSS( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n            }\n        }\n    }\n\n    return val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n    // Start with offset property, which is equivalent to the border-box value\n    var val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n        valueIsBorderBox = true,\n        isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\" ) === \"border-box\";\n\n    if ( val <= 0 ) {\n        // Fall back to computed then uncomputed css if necessary\n        val = curCSS( elem, name );\n        if ( val < 0 || val == null ) {\n            val = elem.style[ name ];\n        }\n\n        // Computed unit is not pixels. Stop here and return.\n        if ( rnumnonpx.test(val) ) {\n            return val;\n        }\n\n        // we need the check for style in case a browser which returns unreliable values\n        // for getComputedStyle silently falls back to the reliable elem.style\n        valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n        // Normalize \"\", auto, and prepare for extra\n        val = parseFloat( val ) || 0;\n    }\n\n    // use the active box-sizing model to add/subtract irrelevant styles\n    return ( val +\n        augmentWidthOrHeight(\n            elem,\n            name,\n            extra || ( isBorderBox ? \"border\" : \"content\" ),\n            valueIsBorderBox\n        )\n    ) + \"px\";\n}\n\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n    if ( elemdisplay[ nodeName ] ) {\n        return elemdisplay[ nodeName ];\n    }\n\n    var elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( document.body ),\n        display = elem.css(\"display\");\n    elem.remove();\n\n    // If the simple way fails,\n    // get element's real default display by attaching it to a temp iframe\n    if ( display === \"none\" || display === \"\" ) {\n        // Use the already-created iframe if possible\n        iframe = document.body.appendChild(\n            iframe || jQuery.extend( document.createElement(\"iframe\"), {\n                frameBorder: 0,\n                width: 0,\n                height: 0\n            })\n        );\n\n        // Create a cacheable copy of the iframe document on first call.\n        // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n        // document to it; WebKit & Firefox won't allow reusing the iframe document.\n        if ( !iframeDoc || !iframe.createElement ) {\n            iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n            iframeDoc.write(\"<!doctype html><html><body>\");\n            iframeDoc.close();\n        }\n\n        elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );\n\n        display = curCSS( elem, \"display\" );\n        document.body.removeChild( iframe );\n    }\n\n    // Store the correct default display\n    elemdisplay[ nodeName ] = display;\n\n    return display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n    jQuery.cssHooks[ name ] = {\n        get: function( elem, computed, extra ) {\n            if ( computed ) {\n                if ( elem.offsetWidth !== 0 || curCSS( elem, \"display\" ) !== \"none\" ) {\n                    return getWidthOrHeight( elem, name, extra );\n                } else {\n                    return jQuery.swap( elem, cssShow, function() {\n                        return getWidthOrHeight( elem, name, extra );\n                    });\n                }\n            }\n        },\n\n        set: function( elem, value, extra ) {\n            return setPositiveNumber( elem, value, extra ?\n                augmentWidthOrHeight(\n                    elem,\n                    name,\n                    extra,\n                    jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\" ) === \"border-box\"\n                ) : 0\n            );\n        }\n    };\n});\n\nif ( !jQuery.support.opacity ) {\n    jQuery.cssHooks.opacity = {\n        get: function( elem, computed ) {\n            // IE uses filters for opacity\n            return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n                ( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n                computed ? \"1\" : \"\";\n        },\n\n        set: function( elem, value ) {\n            var style = elem.style,\n                currentStyle = elem.currentStyle,\n                opacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n                filter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n            // IE has trouble with opacity if it does not have layout\n            // Force it by setting the zoom level\n            style.zoom = 1;\n\n            // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n            if ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n                style.removeAttribute ) {\n\n                // Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n                // if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n                // style.removeAttribute is IE Only, but so apparently is this code path...\n                style.removeAttribute( \"filter\" );\n\n                // if there there is no filter style applied in a css rule, we are done\n                if ( currentStyle && !currentStyle.filter ) {\n                    return;\n                }\n            }\n\n            // otherwise, set new filter values\n            style.filter = ralpha.test( filter ) ?\n                filter.replace( ralpha, opacity ) :\n                filter + \" \" + opacity;\n        }\n    };\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n    if ( !jQuery.support.reliableMarginRight ) {\n        jQuery.cssHooks.marginRight = {\n            get: function( elem, computed ) {\n                // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n                // Work around by temporarily setting element display to inline-block\n                return jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n                    if ( computed ) {\n                        return curCSS( elem, \"marginRight\" );\n                    }\n                });\n            }\n        };\n    }\n\n    // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n    // getComputedStyle returns percent when specified for top/left/bottom/right\n    // rather than make the css module depend on the offset module, we just check for it here\n    if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n        jQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n            jQuery.cssHooks[ prop ] = {\n                get: function( elem, computed ) {\n                    if ( computed ) {\n                        var ret = curCSS( elem, prop );\n                        // if curCSS returns percentage, fallback to offset\n                        return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + \"px\" : ret;\n                    }\n                }\n            };\n        });\n    }\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n    jQuery.expr.filters.hidden = function( elem ) {\n        return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, \"display\" )) === \"none\");\n    };\n\n    jQuery.expr.filters.visible = function( elem ) {\n        return !jQuery.expr.filters.hidden( elem );\n    };\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n    margin: \"\",\n    padding: \"\",\n    border: \"Width\"\n}, function( prefix, suffix ) {\n    jQuery.cssHooks[ prefix + suffix ] = {\n        expand: function( value ) {\n            var i,\n\n                // assumes a single number if not a string\n                parts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n                expanded = {};\n\n            for ( i = 0; i < 4; i++ ) {\n                expanded[ prefix + cssExpand[ i ] + suffix ] =\n                    parts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n            }\n\n            return expanded;\n        }\n    };\n\n    if ( !rmargin.test( prefix ) ) {\n        jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n    }\n});\nvar r20 = /%20/g,\n    rbracket = /\\[\\]$/,\n    rCRLF = /\\r?\\n/g,\n    rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n    rselectTextarea = /^(?:select|textarea)/i;\n\njQuery.fn.extend({\n    serialize: function() {\n        return jQuery.param( this.serializeArray() );\n    },\n    serializeArray: function() {\n        return this.map(function(){\n            return this.elements ? jQuery.makeArray( this.elements ) : this;\n        })\n        .filter(function(){\n            return this.name && !this.disabled &&\n                ( this.checked || rselectTextarea.test( this.nodeName ) ||\n                    rinput.test( this.type ) );\n        })\n        .map(function( i, elem ){\n            var val = jQuery( this ).val();\n\n            return val == null ?\n                null :\n                jQuery.isArray( val ) ?\n                    jQuery.map( val, function( val, i ){\n                        return { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n                    }) :\n                    { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n        }).get();\n    }\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n    var prefix,\n        s = [],\n        add = function( key, value ) {\n            // If value is a function, invoke it and return its value\n            value = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n            s[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n        };\n\n    // Set traditional to true for jQuery <= 1.3.2 behavior.\n    if ( traditional === undefined ) {\n        traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n    }\n\n    // If an array was passed in, assume that it is an array of form elements.\n    if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n        // Serialize the form elements\n        jQuery.each( a, function() {\n            add( this.name, this.value );\n        });\n\n    } else {\n        // If traditional, encode the \"old\" way (the way 1.3.2 or older\n        // did it), otherwise encode params recursively.\n        for ( prefix in a ) {\n            buildParams( prefix, a[ prefix ], traditional, add );\n        }\n    }\n\n    // Return the resulting serialization\n    return s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n    var name;\n\n    if ( jQuery.isArray( obj ) ) {\n        // Serialize array item.\n        jQuery.each( obj, function( i, v ) {\n            if ( traditional || rbracket.test( prefix ) ) {\n                // Treat each array item as a scalar.\n                add( prefix, v );\n\n            } else {\n                // If array item is non-scalar (array or object), encode its\n                // numeric index to resolve deserialization ambiguity issues.\n                // Note that rack (as of 1.0.0) can't currently deserialize\n                // nested arrays properly, and attempting to do so may cause\n                // a server error. Possible fixes are to modify rack's\n                // deserialization algorithm or to provide an option or flag\n                // to force array serialization to be shallow.\n                buildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n            }\n        });\n\n    } else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n        // Serialize object item.\n        for ( name in obj ) {\n            buildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n        }\n\n    } else {\n        // Serialize scalar item.\n        add( prefix, obj );\n    }\n}\nvar // Document location\n    ajaxLocation,\n    // Document location segments\n    ajaxLocParts,\n\n    rhash = /#.*$/,\n    rheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n    // #7653, #8125, #8152: local protocol detection\n    rlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n    rnoContent = /^(?:GET|HEAD)$/,\n    rprotocol = /^\\/\\//,\n    rquery = /\\?/,\n    rscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n    rts = /([?&])_=[^&]*/,\n    rurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n    // Keep a copy of the old load method\n    _load = jQuery.fn.load,\n\n    /* Prefilters\n     * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n     * 2) These are called:\n     *    - BEFORE asking for a transport\n     *    - AFTER param serialization (s.data is a string if s.processData is true)\n     * 3) key is the dataType\n     * 4) the catchall symbol \"*\" can be used\n     * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n     */\n    prefilters = {},\n\n    /* Transports bindings\n     * 1) key is the dataType\n     * 2) the catchall symbol \"*\" can be used\n     * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n     */\n    transports = {},\n\n    // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n    allTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n    ajaxLocation = location.href;\n} catch( e ) {\n    // Use the href attribute of an A element\n    // since IE will modify it given document.location\n    ajaxLocation = document.createElement( \"a\" );\n    ajaxLocation.href = \"\";\n    ajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n    // dataTypeExpression is optional and defaults to \"*\"\n    return function( dataTypeExpression, func ) {\n\n        if ( typeof dataTypeExpression !== \"string\" ) {\n            func = dataTypeExpression;\n            dataTypeExpression = \"*\";\n        }\n\n        var dataType, list, placeBefore,\n            dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),\n            i = 0,\n            length = dataTypes.length;\n\n        if ( jQuery.isFunction( func ) ) {\n            // For each dataType in the dataTypeExpression\n            for ( ; i < length; i++ ) {\n                dataType = dataTypes[ i ];\n                // We control if we're asked to add before\n                // any existing element\n                placeBefore = /^\\+/.test( dataType );\n                if ( placeBefore ) {\n                    dataType = dataType.substr( 1 ) || \"*\";\n                }\n                list = structure[ dataType ] = structure[ dataType ] || [];\n                // then we add to the structure accordingly\n                list[ placeBefore ? \"unshift\" : \"push\" ]( func );\n            }\n        }\n    };\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n        dataType /* internal */, inspected /* internal */ ) {\n\n    dataType = dataType || options.dataTypes[ 0 ];\n    inspected = inspected || {};\n\n    inspected[ dataType ] = true;\n\n    var selection,\n        list = structure[ dataType ],\n        i = 0,\n        length = list ? list.length : 0,\n        executeOnly = ( structure === prefilters );\n\n    for ( ; i < length && ( executeOnly || !selection ); i++ ) {\n        selection = list[ i ]( options, originalOptions, jqXHR );\n        // If we got redirected to another dataType\n        // we try there if executing only and not done already\n        if ( typeof selection === \"string\" ) {\n            if ( !executeOnly || inspected[ selection ] ) {\n                selection = undefined;\n            } else {\n                options.dataTypes.unshift( selection );\n                selection = inspectPrefiltersOrTransports(\n                        structure, options, originalOptions, jqXHR, selection, inspected );\n            }\n        }\n    }\n    // If we're only executing or nothing was selected\n    // we try the catchall dataType if not done already\n    if ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n        selection = inspectPrefiltersOrTransports(\n                structure, options, originalOptions, jqXHR, \"*\", inspected );\n    }\n    // unnecessary when only executing (prefilters)\n    // but it'll be ignored by the caller in that case\n    return selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n    var key, deep,\n        flatOptions = jQuery.ajaxSettings.flatOptions || {};\n    for ( key in src ) {\n        if ( src[ key ] !== undefined ) {\n            ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n        }\n    }\n    if ( deep ) {\n        jQuery.extend( true, target, deep );\n    }\n}\n\njQuery.fn.load = function( url, params, callback ) {\n    if ( typeof url !== \"string\" && _load ) {\n        return _load.apply( this, arguments );\n    }\n\n    // Don't do a request if no elements are being requested\n    if ( !this.length ) {\n        return this;\n    }\n\n    var selector, type, response,\n        self = this,\n        off = url.indexOf(\" \");\n\n    if ( off >= 0 ) {\n        selector = url.slice( off, url.length );\n        url = url.slice( 0, off );\n    }\n\n    // If it's a function\n    if ( jQuery.isFunction( params ) ) {\n\n        // We assume that it's the callback\n        callback = params;\n        params = undefined;\n\n    // Otherwise, build a param string\n    } else if ( typeof params === \"object\" ) {\n        type = \"POST\";\n    }\n\n    // Request the remote document\n    jQuery.ajax({\n        url: url,\n\n        // if \"type\" variable is undefined, then \"GET\" method will be used\n        type: type,\n        dataType: \"html\",\n        data: params,\n        complete: function( jqXHR, status ) {\n            if ( callback ) {\n                self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n            }\n        }\n    }).done(function( responseText ) {\n\n        // Save response for use in complete callback\n        response = arguments;\n\n        // See if a selector was specified\n        self.html( selector ?\n\n            // Create a dummy div to hold the results\n            jQuery(\"<div>\")\n\n                // inject the contents of the document in, removing the scripts\n                // to avoid any 'Permission Denied' errors in IE\n                .append( responseText.replace( rscript, \"\" ) )\n\n                // Locate the specified elements\n                .find( selector ) :\n\n            // If not, just inject the full result\n            responseText );\n\n    });\n\n    return this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n    jQuery.fn[ o ] = function( f ){\n        return this.on( o, f );\n    };\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n    jQuery[ method ] = function( url, data, callback, type ) {\n        // shift arguments if data argument was omitted\n        if ( jQuery.isFunction( data ) ) {\n            type = type || callback;\n            callback = data;\n            data = undefined;\n        }\n\n        return jQuery.ajax({\n            type: method,\n            url: url,\n            data: data,\n            success: callback,\n            dataType: type\n        });\n    };\n});\n\njQuery.extend({\n\n    getScript: function( url, callback ) {\n        return jQuery.get( url, undefined, callback, \"script\" );\n    },\n\n    getJSON: function( url, data, callback ) {\n        return jQuery.get( url, data, callback, \"json\" );\n    },\n\n    // Creates a full fledged settings object into target\n    // with both ajaxSettings and settings fields.\n    // If target is omitted, writes into ajaxSettings.\n    ajaxSetup: function( target, settings ) {\n        if ( settings ) {\n            // Building a settings object\n            ajaxExtend( target, jQuery.ajaxSettings );\n        } else {\n            // Extending ajaxSettings\n            settings = target;\n            target = jQuery.ajaxSettings;\n        }\n        ajaxExtend( target, settings );\n        return target;\n    },\n\n    ajaxSettings: {\n        url: ajaxLocation,\n        isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n        global: true,\n        type: \"GET\",\n        contentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n        processData: true,\n        async: true,\n        /*\n        timeout: 0,\n        data: null,\n        dataType: null,\n        username: null,\n        password: null,\n        cache: null,\n        throws: false,\n        traditional: false,\n        headers: {},\n        */\n\n        accepts: {\n            xml: \"application/xml, text/xml\",\n            html: \"text/html\",\n            text: \"text/plain\",\n            json: \"application/json, text/javascript\",\n            \"*\": allTypes\n        },\n\n        contents: {\n            xml: /xml/,\n            html: /html/,\n            json: /json/\n        },\n\n        responseFields: {\n            xml: \"responseXML\",\n            text: \"responseText\"\n        },\n\n        // List of data converters\n        // 1) key format is \"source_type destination_type\" (a single space in-between)\n        // 2) the catchall symbol \"*\" can be used for source_type\n        converters: {\n\n            // Convert anything to text\n            \"* text\": window.String,\n\n            // Text to html (true = no transformation)\n            \"text html\": true,\n\n            // Evaluate text as a json expression\n            \"text json\": jQuery.parseJSON,\n\n            // Parse text as xml\n            \"text xml\": jQuery.parseXML\n        },\n\n        // For options that shouldn't be deep extended:\n        // you can add your own custom options here if\n        // and when you create one that shouldn't be\n        // deep extended (see ajaxExtend)\n        flatOptions: {\n            context: true,\n            url: true\n        }\n    },\n\n    ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n    ajaxTransport: addToPrefiltersOrTransports( transports ),\n\n    // Main method\n    ajax: function( url, options ) {\n\n        // If url is an object, simulate pre-1.5 signature\n        if ( typeof url === \"object\" ) {\n            options = url;\n            url = undefined;\n        }\n\n        // Force options to be an object\n        options = options || {};\n\n        var // ifModified key\n            ifModifiedKey,\n            // Response headers\n            responseHeadersString,\n            responseHeaders,\n            // transport\n            transport,\n            // timeout handle\n            timeoutTimer,\n            // Cross-domain detection vars\n            parts,\n            // To know if global events are to be dispatched\n            fireGlobals,\n            // Loop variable\n            i,\n            // Create the final options object\n            s = jQuery.ajaxSetup( {}, options ),\n            // Callbacks context\n            callbackContext = s.context || s,\n            // Context for global events\n            // It's the callbackContext if one was provided in the options\n            // and if it's a DOM node or a jQuery collection\n            globalEventContext = callbackContext !== s &&\n                ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n                        jQuery( callbackContext ) : jQuery.event,\n            // Deferreds\n            deferred = jQuery.Deferred(),\n            completeDeferred = jQuery.Callbacks( \"once memory\" ),\n            // Status-dependent callbacks\n            statusCode = s.statusCode || {},\n            // Headers (they are sent all at once)\n            requestHeaders = {},\n            requestHeadersNames = {},\n            // The jqXHR state\n            state = 0,\n            // Default abort message\n            strAbort = \"canceled\",\n            // Fake xhr\n            jqXHR = {\n\n                readyState: 0,\n\n                // Caches the header\n                setRequestHeader: function( name, value ) {\n                    if ( !state ) {\n                        var lname = name.toLowerCase();\n                        name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n                        requestHeaders[ name ] = value;\n                    }\n                    return this;\n                },\n\n                // Raw string\n                getAllResponseHeaders: function() {\n                    return state === 2 ? responseHeadersString : null;\n                },\n\n                // Builds headers hashtable if needed\n                getResponseHeader: function( key ) {\n                    var match;\n                    if ( state === 2 ) {\n                        if ( !responseHeaders ) {\n                            responseHeaders = {};\n                            while( ( match = rheaders.exec( responseHeadersString ) ) ) {\n                                responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n                            }\n                        }\n                        match = responseHeaders[ key.toLowerCase() ];\n                    }\n                    return match === undefined ? null : match;\n                },\n\n                // Overrides response content-type header\n                overrideMimeType: function( type ) {\n                    if ( !state ) {\n                        s.mimeType = type;\n                    }\n                    return this;\n                },\n\n                // Cancel the request\n                abort: function( statusText ) {\n                    statusText = statusText || strAbort;\n                    if ( transport ) {\n                        transport.abort( statusText );\n                    }\n                    done( 0, statusText );\n                    return this;\n                }\n            };\n\n        // Callback for when everything is done\n        // It is defined here because jslint complains if it is declared\n        // at the end of the function (which would be more logical and readable)\n        function done( status, nativeStatusText, responses, headers ) {\n            var isSuccess, success, error, response, modified,\n                statusText = nativeStatusText;\n\n            // Called once\n            if ( state === 2 ) {\n                return;\n            }\n\n            // State is \"done\" now\n            state = 2;\n\n            // Clear timeout if it exists\n            if ( timeoutTimer ) {\n                clearTimeout( timeoutTimer );\n            }\n\n            // Dereference transport for early garbage collection\n            // (no matter how long the jqXHR object will be used)\n            transport = undefined;\n\n            // Cache response headers\n            responseHeadersString = headers || \"\";\n\n            // Set readyState\n            jqXHR.readyState = status > 0 ? 4 : 0;\n\n            // Get response data\n            if ( responses ) {\n                response = ajaxHandleResponses( s, jqXHR, responses );\n            }\n\n            // If successful, handle type chaining\n            if ( status >= 200 && status < 300 || status === 304 ) {\n\n                // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n                if ( s.ifModified ) {\n\n                    modified = jqXHR.getResponseHeader(\"Last-Modified\");\n                    if ( modified ) {\n                        jQuery.lastModified[ ifModifiedKey ] = modified;\n                    }\n                    modified = jqXHR.getResponseHeader(\"Etag\");\n                    if ( modified ) {\n                        jQuery.etag[ ifModifiedKey ] = modified;\n                    }\n                }\n\n                // If not modified\n                if ( status === 304 ) {\n\n                    statusText = \"notmodified\";\n                    isSuccess = true;\n\n                // If we have data\n                } else {\n\n                    isSuccess = ajaxConvert( s, response );\n                    statusText = isSuccess.state;\n                    success = isSuccess.data;\n                    error = isSuccess.error;\n                    isSuccess = !error;\n                }\n            } else {\n                // We extract error from statusText\n                // then normalize statusText and status for non-aborts\n                error = statusText;\n                if ( !statusText || status ) {\n                    statusText = \"error\";\n                    if ( status < 0 ) {\n                        status = 0;\n                    }\n                }\n            }\n\n            // Set data for the fake xhr object\n            jqXHR.status = status;\n            jqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n            // Success/Error\n            if ( isSuccess ) {\n                deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n            } else {\n                deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n            }\n\n            // Status-dependent callbacks\n            jqXHR.statusCode( statusCode );\n            statusCode = undefined;\n\n            if ( fireGlobals ) {\n                globalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n                        [ jqXHR, s, isSuccess ? success : error ] );\n            }\n\n            // Complete\n            completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n            if ( fireGlobals ) {\n                globalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n                // Handle the global AJAX counter\n                if ( !( --jQuery.active ) ) {\n                    jQuery.event.trigger( \"ajaxStop\" );\n                }\n            }\n        }\n\n        // Attach deferreds\n        deferred.promise( jqXHR );\n        jqXHR.success = jqXHR.done;\n        jqXHR.error = jqXHR.fail;\n        jqXHR.complete = completeDeferred.add;\n\n        // Status-dependent callbacks\n        jqXHR.statusCode = function( map ) {\n            if ( map ) {\n                var tmp;\n                if ( state < 2 ) {\n                    for ( tmp in map ) {\n                        statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n                    }\n                } else {\n                    tmp = map[ jqXHR.status ];\n                    jqXHR.always( tmp );\n                }\n            }\n            return this;\n        };\n\n        // Remove hash character (#7531: and string promotion)\n        // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n        // We also use the url parameter if available\n        s.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n        // Extract dataTypes list\n        s.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( core_rspace );\n\n        // Determine if a cross-domain request is in order\n        if ( s.crossDomain == null ) {\n            parts = rurl.exec( s.url.toLowerCase() );\n            s.crossDomain = !!( parts &&\n                ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n                    ( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n                        ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n            );\n        }\n\n        // Convert data if not already a string\n        if ( s.data && s.processData && typeof s.data !== \"string\" ) {\n            s.data = jQuery.param( s.data, s.traditional );\n        }\n\n        // Apply prefilters\n        inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n        // If request was aborted inside a prefilter, stop there\n        if ( state === 2 ) {\n            return jqXHR;\n        }\n\n        // We can fire global events as of now if asked to\n        fireGlobals = s.global;\n\n        // Uppercase the type\n        s.type = s.type.toUpperCase();\n\n        // Determine if request has content\n        s.hasContent = !rnoContent.test( s.type );\n\n        // Watch for a new set of requests\n        if ( fireGlobals && jQuery.active++ === 0 ) {\n            jQuery.event.trigger( \"ajaxStart\" );\n        }\n\n        // More options handling for requests with no content\n        if ( !s.hasContent ) {\n\n            // If data is available, append data to url\n            if ( s.data ) {\n                s.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n                // #9682: remove data so that it's not used in an eventual retry\n                delete s.data;\n            }\n\n            // Get ifModifiedKey before adding the anti-cache parameter\n            ifModifiedKey = s.url;\n\n            // Add anti-cache in url if needed\n            if ( s.cache === false ) {\n\n                var ts = jQuery.now(),\n                    // try replacing _= if it is there\n                    ret = s.url.replace( rts, \"$1_=\" + ts );\n\n                // if nothing was replaced, add timestamp to the end\n                s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n            }\n        }\n\n        // Set the correct header, if data is being sent\n        if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n            jqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n        }\n\n        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n        if ( s.ifModified ) {\n            ifModifiedKey = ifModifiedKey || s.url;\n            if ( jQuery.lastModified[ ifModifiedKey ] ) {\n                jqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n            }\n            if ( jQuery.etag[ ifModifiedKey ] ) {\n                jqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n            }\n        }\n\n        // Set the Accepts header for the server, depending on the dataType\n        jqXHR.setRequestHeader(\n            \"Accept\",\n            s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n                s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n                s.accepts[ \"*\" ]\n        );\n\n        // Check for headers option\n        for ( i in s.headers ) {\n            jqXHR.setRequestHeader( i, s.headers[ i ] );\n        }\n\n        // Allow custom headers/mimetypes and early abort\n        if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n                // Abort if not done already and return\n                return jqXHR.abort();\n\n        }\n\n        // aborting is no longer a cancellation\n        strAbort = \"abort\";\n\n        // Install callbacks on deferreds\n        for ( i in { success: 1, error: 1, complete: 1 } ) {\n            jqXHR[ i ]( s[ i ] );\n        }\n\n        // Get transport\n        transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n        // If no transport, we auto-abort\n        if ( !transport ) {\n            done( -1, \"No Transport\" );\n        } else {\n            jqXHR.readyState = 1;\n            // Send global event\n            if ( fireGlobals ) {\n                globalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n            }\n            // Timeout\n            if ( s.async && s.timeout > 0 ) {\n                timeoutTimer = setTimeout( function(){\n                    jqXHR.abort( \"timeout\" );\n                }, s.timeout );\n            }\n\n            try {\n                state = 1;\n                transport.send( requestHeaders, done );\n            } catch (e) {\n                // Propagate exception as error if not done\n                if ( state < 2 ) {\n                    done( -1, e );\n                // Simply rethrow otherwise\n                } else {\n                    throw e;\n                }\n            }\n        }\n\n        return jqXHR;\n    },\n\n    // Counter for holding the number of active queries\n    active: 0,\n\n    // Last-Modified header cache for next request\n    lastModified: {},\n    etag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n    var ct, type, finalDataType, firstDataType,\n        contents = s.contents,\n        dataTypes = s.dataTypes,\n        responseFields = s.responseFields;\n\n    // Fill responseXXX fields\n    for ( type in responseFields ) {\n        if ( type in responses ) {\n            jqXHR[ responseFields[type] ] = responses[ type ];\n        }\n    }\n\n    // Remove auto dataType and get content-type in the process\n    while( dataTypes[ 0 ] === \"*\" ) {\n        dataTypes.shift();\n        if ( ct === undefined ) {\n            ct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n        }\n    }\n\n    // Check if we're dealing with a known content-type\n    if ( ct ) {\n        for ( type in contents ) {\n            if ( contents[ type ] && contents[ type ].test( ct ) ) {\n                dataTypes.unshift( type );\n                break;\n            }\n        }\n    }\n\n    // Check to see if we have a response for the expected dataType\n    if ( dataTypes[ 0 ] in responses ) {\n        finalDataType = dataTypes[ 0 ];\n    } else {\n        // Try convertible dataTypes\n        for ( type in responses ) {\n            if ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n                finalDataType = type;\n                break;\n            }\n            if ( !firstDataType ) {\n                firstDataType = type;\n            }\n        }\n        // Or just use first one\n        finalDataType = finalDataType || firstDataType;\n    }\n\n    // If we found a dataType\n    // We add the dataType to the list if needed\n    // and return the corresponding response\n    if ( finalDataType ) {\n        if ( finalDataType !== dataTypes[ 0 ] ) {\n            dataTypes.unshift( finalDataType );\n        }\n        return responses[ finalDataType ];\n    }\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n    var conv, conv2, current, tmp,\n        // Work with a copy of dataTypes in case we need to modify it for conversion\n        dataTypes = s.dataTypes.slice(),\n        prev = dataTypes[ 0 ],\n        converters = {},\n        i = 0;\n\n    // Apply the dataFilter if provided\n    if ( s.dataFilter ) {\n        response = s.dataFilter( response, s.dataType );\n    }\n\n    // Create converters map with lowercased keys\n    if ( dataTypes[ 1 ] ) {\n        for ( conv in s.converters ) {\n            converters[ conv.toLowerCase() ] = s.converters[ conv ];\n        }\n    }\n\n    // Convert to each sequential dataType, tolerating list modification\n    for ( ; (current = dataTypes[++i]); ) {\n\n        // There's only work to do if current dataType is non-auto\n        if ( current !== \"*\" ) {\n\n            // Convert response if prev dataType is non-auto and differs from current\n            if ( prev !== \"*\" && prev !== current ) {\n\n                // Seek a direct converter\n                conv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n                // If none found, seek a pair\n                if ( !conv ) {\n                    for ( conv2 in converters ) {\n\n                        // If conv2 outputs current\n                        tmp = conv2.split(\" \");\n                        if ( tmp[ 1 ] === current ) {\n\n                            // If prev can be converted to accepted input\n                            conv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n                                converters[ \"* \" + tmp[ 0 ] ];\n                            if ( conv ) {\n                                // Condense equivalence converters\n                                if ( conv === true ) {\n                                    conv = converters[ conv2 ];\n\n                                // Otherwise, insert the intermediate dataType\n                                } else if ( converters[ conv2 ] !== true ) {\n                                    current = tmp[ 0 ];\n                                    dataTypes.splice( i--, 0, current );\n                                }\n\n                                break;\n                            }\n                        }\n                    }\n                }\n\n                // Apply converter (if not an equivalence)\n                if ( conv !== true ) {\n\n                    // Unless errors are allowed to bubble, catch and return them\n                    if ( conv && s[\"throws\"] ) {\n                        response = conv( response );\n                    } else {\n                        try {\n                            response = conv( response );\n                        } catch ( e ) {\n                            return { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n                        }\n                    }\n                }\n            }\n\n            // Update prev for next iteration\n            prev = current;\n        }\n    }\n\n    return { state: \"success\", data: response };\n}\nvar oldCallbacks = [],\n    rquestion = /\\?/,\n    rjsonp = /(=)\\?(?=&|$)|\\?\\?/,\n    nonce = jQuery.now();\n\n// Default jsonp settings\njQuery.ajaxSetup({\n    jsonp: \"callback\",\n    jsonpCallback: function() {\n        var callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n        this[ callback ] = true;\n        return callback;\n    }\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n    var callbackName, overwritten, responseContainer,\n        data = s.data,\n        url = s.url,\n        hasCallback = s.jsonp !== false,\n        replaceInUrl = hasCallback && rjsonp.test( url ),\n        replaceInData = hasCallback && !replaceInUrl && typeof data === \"string\" &&\n            !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") &&\n            rjsonp.test( data );\n\n    // Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n    if ( s.dataTypes[ 0 ] === \"jsonp\" || replaceInUrl || replaceInData ) {\n\n        // Get callback name, remembering preexisting value associated with it\n        callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n            s.jsonpCallback() :\n            s.jsonpCallback;\n        overwritten = window[ callbackName ];\n\n        // Insert callback into url or form data\n        if ( replaceInUrl ) {\n            s.url = url.replace( rjsonp, \"$1\" + callbackName );\n        } else if ( replaceInData ) {\n            s.data = data.replace( rjsonp, \"$1\" + callbackName );\n        } else if ( hasCallback ) {\n            s.url += ( rquestion.test( url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n        }\n\n        // Use data converter to retrieve json after script execution\n        s.converters[\"script json\"] = function() {\n            if ( !responseContainer ) {\n                jQuery.error( callbackName + \" was not called\" );\n            }\n            return responseContainer[ 0 ];\n        };\n\n        // force json dataType\n        s.dataTypes[ 0 ] = \"json\";\n\n        // Install callback\n        window[ callbackName ] = function() {\n            responseContainer = arguments;\n        };\n\n        // Clean-up function (fires after converters)\n        jqXHR.always(function() {\n            // Restore preexisting value\n            window[ callbackName ] = overwritten;\n\n            // Save back as free\n            if ( s[ callbackName ] ) {\n                // make sure that re-using the options doesn't screw things around\n                s.jsonpCallback = originalSettings.jsonpCallback;\n\n                // save the callback name for future use\n                oldCallbacks.push( callbackName );\n            }\n\n            // Call if it was a function and we have a response\n            if ( responseContainer && jQuery.isFunction( overwritten ) ) {\n                overwritten( responseContainer[ 0 ] );\n            }\n\n            responseContainer = overwritten = undefined;\n        });\n\n        // Delegate to script\n        return \"script\";\n    }\n});\n// Install script dataType\njQuery.ajaxSetup({\n    accepts: {\n        script: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n    },\n    contents: {\n        script: /javascript|ecmascript/\n    },\n    converters: {\n        \"text script\": function( text ) {\n            jQuery.globalEval( text );\n            return text;\n        }\n    }\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n    if ( s.cache === undefined ) {\n        s.cache = false;\n    }\n    if ( s.crossDomain ) {\n        s.type = \"GET\";\n        s.global = false;\n    }\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n    // This transport only deals with cross domain requests\n    if ( s.crossDomain ) {\n\n        var script,\n            head = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n        return {\n\n            send: function( _, callback ) {\n\n                script = document.createElement( \"script\" );\n\n                script.async = \"async\";\n\n                if ( s.scriptCharset ) {\n                    script.charset = s.scriptCharset;\n                }\n\n                script.src = s.url;\n\n                // Attach handlers for all browsers\n                script.onload = script.onreadystatechange = function( _, isAbort ) {\n\n                    if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n                        // Handle memory leak in IE\n                        script.onload = script.onreadystatechange = null;\n\n                        // Remove the script\n                        if ( head && script.parentNode ) {\n                            head.removeChild( script );\n                        }\n\n                        // Dereference the script\n                        script = undefined;\n\n                        // Callback if not abort\n                        if ( !isAbort ) {\n                            callback( 200, \"success\" );\n                        }\n                    }\n                };\n                // Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n                // This arises when a base node is used (#2709 and #4378).\n                head.insertBefore( script, head.firstChild );\n            },\n\n            abort: function() {\n                if ( script ) {\n                    script.onload( 0, 1 );\n                }\n            }\n        };\n    }\n});\nvar xhrCallbacks,\n    // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n    xhrOnUnloadAbort = window.ActiveXObject ? function() {\n        // Abort all pending requests\n        for ( var key in xhrCallbacks ) {\n            xhrCallbacks[ key ]( 0, 1 );\n        }\n    } : false,\n    xhrId = 0;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n    try {\n        return new window.XMLHttpRequest();\n    } catch( e ) {}\n}\n\nfunction createActiveXHR() {\n    try {\n        return new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n    } catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n    /* Microsoft failed to properly\n     * implement the XMLHttpRequest in IE7 (can't request local files),\n     * so we use the ActiveXObject when it is available\n     * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n     * we need a fallback.\n     */\n    function() {\n        return !this.isLocal && createStandardXHR() || createActiveXHR();\n    } :\n    // For all other browsers, use the standard XMLHttpRequest object\n    createStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n    jQuery.extend( jQuery.support, {\n        ajax: !!xhr,\n        cors: !!xhr && ( \"withCredentials\" in xhr )\n    });\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n    jQuery.ajaxTransport(function( s ) {\n        // Cross domain only allowed if supported through XMLHttpRequest\n        if ( !s.crossDomain || jQuery.support.cors ) {\n\n            var callback;\n\n            return {\n                send: function( headers, complete ) {\n\n                    // Get a new xhr\n                    var handle, i,\n                        xhr = s.xhr();\n\n                    // Open the socket\n                    // Passing null username, generates a login popup on Opera (#2865)\n                    if ( s.username ) {\n                        xhr.open( s.type, s.url, s.async, s.username, s.password );\n                    } else {\n                        xhr.open( s.type, s.url, s.async );\n                    }\n\n                    // Apply custom fields if provided\n                    if ( s.xhrFields ) {\n                        for ( i in s.xhrFields ) {\n                            xhr[ i ] = s.xhrFields[ i ];\n                        }\n                    }\n\n                    // Override mime type if needed\n                    if ( s.mimeType && xhr.overrideMimeType ) {\n                        xhr.overrideMimeType( s.mimeType );\n                    }\n\n                    // X-Requested-With header\n                    // For cross-domain requests, seeing as conditions for a preflight are\n                    // akin to a jigsaw puzzle, we simply never set it to be sure.\n                    // (it can always be set on a per-request basis or even using ajaxSetup)\n                    // For same-domain requests, won't change header if already provided.\n                    if ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n                        headers[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n                    }\n\n                    // Need an extra try/catch for cross domain requests in Firefox 3\n                    try {\n                        for ( i in headers ) {\n                            xhr.setRequestHeader( i, headers[ i ] );\n                        }\n                    } catch( _ ) {}\n\n                    // Do send the request\n                    // This may raise an exception which is actually\n                    // handled in jQuery.ajax (so no try/catch here)\n                    xhr.send( ( s.hasContent && s.data ) || null );\n\n                    // Listener\n                    callback = function( _, isAbort ) {\n\n                        var status,\n                            statusText,\n                            responseHeaders,\n                            responses,\n                            xml;\n\n                        // Firefox throws exceptions when accessing properties\n                        // of an xhr when a network error occurred\n                        // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n                        try {\n\n                            // Was never called and is aborted or complete\n                            if ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n                                // Only called once\n                                callback = undefined;\n\n                                // Do not keep as active anymore\n                                if ( handle ) {\n                                    xhr.onreadystatechange = jQuery.noop;\n                                    if ( xhrOnUnloadAbort ) {\n                                        delete xhrCallbacks[ handle ];\n                                    }\n                                }\n\n                                // If it's an abort\n                                if ( isAbort ) {\n                                    // Abort it manually if needed\n                                    if ( xhr.readyState !== 4 ) {\n                                        xhr.abort();\n                                    }\n                                } else {\n                                    status = xhr.status;\n                                    responseHeaders = xhr.getAllResponseHeaders();\n                                    responses = {};\n                                    xml = xhr.responseXML;\n\n                                    // Construct response list\n                                    if ( xml && xml.documentElement /* #4958 */ ) {\n                                        responses.xml = xml;\n                                    }\n\n                                    // When requesting binary data, IE6-9 will throw an exception\n                                    // on any attempt to access responseText (#11426)\n                                    try {\n                                        responses.text = xhr.responseText;\n                                    } catch( _ ) {\n                                    }\n\n                                    // Firefox throws an exception when accessing\n                                    // statusText for faulty cross-domain requests\n                                    try {\n                                        statusText = xhr.statusText;\n                                    } catch( e ) {\n                                        // We normalize with Webkit giving an empty statusText\n                                        statusText = \"\";\n                                    }\n\n                                    // Filter status for non standard behaviors\n\n                                    // If the request is local and we have data: assume a success\n                                    // (success with no data won't get notified, that's the best we\n                                    // can do given current implementations)\n                                    if ( !status && s.isLocal && !s.crossDomain ) {\n                                        status = responses.text ? 200 : 404;\n                                    // IE - #1450: sometimes returns 1223 when it should be 204\n                                    } else if ( status === 1223 ) {\n                                        status = 204;\n                                    }\n                                }\n                            }\n                        } catch( firefoxAccessException ) {\n                            if ( !isAbort ) {\n                                complete( -1, firefoxAccessException );\n                            }\n                        }\n\n                        // Call complete if needed\n                        if ( responses ) {\n                            complete( status, statusText, responses, responseHeaders );\n                        }\n                    };\n\n                    if ( !s.async ) {\n                        // if we're in sync mode we fire the callback\n                        callback();\n                    } else if ( xhr.readyState === 4 ) {\n                        // (IE6 & IE7) if it's in cache and has been\n                        // retrieved directly we need to fire the callback\n                        setTimeout( callback, 0 );\n                    } else {\n                        handle = ++xhrId;\n                        if ( xhrOnUnloadAbort ) {\n                            // Create the active xhrs callbacks list if needed\n                            // and attach the unload handler\n                            if ( !xhrCallbacks ) {\n                                xhrCallbacks = {};\n                                jQuery( window ).unload( xhrOnUnloadAbort );\n                            }\n                            // Add to list of active xhrs callbacks\n                            xhrCallbacks[ handle ] = callback;\n                        }\n                        xhr.onreadystatechange = callback;\n                    }\n                },\n\n                abort: function() {\n                    if ( callback ) {\n                        callback(0,1);\n                    }\n                }\n            };\n        }\n    });\n}\nvar fxNow, timerId,\n    rfxtypes = /^(?:toggle|show|hide)$/,\n    rfxnum = new RegExp( \"^(?:([-+])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n    rrun = /queueHooks$/,\n    animationPrefilters = [ defaultPrefilter ],\n    tweeners = {\n        \"*\": [function( prop, value ) {\n            var end, unit, prevScale,\n                tween = this.createTween( prop, value ),\n                parts = rfxnum.exec( value ),\n                target = tween.cur(),\n                start = +target || 0,\n                scale = 1;\n\n            if ( parts ) {\n                end = +parts[2];\n                unit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n                // We need to compute starting value\n                if ( unit !== \"px\" && start ) {\n                    // Iteratively approximate from a nonzero starting point\n                    // Prefer the current property, because this process will be trivial if it uses the same units\n                    // Fallback to end or a simple constant\n                    start = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n                    do {\n                        // If previous iteration zeroed out, double until we get *something*\n                        // Use a string for doubling factor so we don't accidentally see scale as unchanged below\n                        prevScale = scale = scale || \".5\";\n\n                        // Adjust and apply\n                        start = start / scale;\n                        jQuery.style( tween.elem, prop, start + unit );\n\n                        // Update scale, tolerating zeroes from tween.cur()\n                        scale = tween.cur() / target;\n\n                    // Stop looping if we've hit the mark or scale is unchanged\n                    } while ( scale !== 1 && scale !== prevScale );\n                }\n\n                tween.unit = unit;\n                tween.start = start;\n                // If a +=/-= token was provided, we're doing a relative animation\n                tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n            }\n            return tween;\n        }]\n    };\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n    setTimeout(function() {\n        fxNow = undefined;\n    }, 0 );\n    return ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n    jQuery.each( props, function( prop, value ) {\n        var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n            index = 0,\n            length = collection.length;\n        for ( ; index < length; index++ ) {\n            if ( collection[ index ].call( animation, prop, value ) ) {\n\n                // we're done with this property\n                return;\n            }\n        }\n    });\n}\n\nfunction Animation( elem, properties, options ) {\n    var result,\n        index = 0,\n        tweenerIndex = 0,\n        length = animationPrefilters.length,\n        deferred = jQuery.Deferred().always( function() {\n            // don't match elem in the :animated selector\n            delete tick.elem;\n        }),\n        tick = function() {\n            var currentTime = fxNow || createFxNow(),\n                remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n                percent = 1 - ( remaining / animation.duration || 0 ),\n                index = 0,\n                length = animation.tweens.length;\n\n            for ( ; index < length ; index++ ) {\n                animation.tweens[ index ].run( percent );\n            }\n\n            deferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n            if ( percent < 1 && length ) {\n                return remaining;\n            } else {\n                deferred.resolveWith( elem, [ animation ] );\n                return false;\n            }\n        },\n        animation = deferred.promise({\n            elem: elem,\n            props: jQuery.extend( {}, properties ),\n            opts: jQuery.extend( true, { specialEasing: {} }, options ),\n            originalProperties: properties,\n            originalOptions: options,\n            startTime: fxNow || createFxNow(),\n            duration: options.duration,\n            tweens: [],\n            createTween: function( prop, end, easing ) {\n                var tween = jQuery.Tween( elem, animation.opts, prop, end,\n                        animation.opts.specialEasing[ prop ] || animation.opts.easing );\n                animation.tweens.push( tween );\n                return tween;\n            },\n            stop: function( gotoEnd ) {\n                var index = 0,\n                    // if we are going to the end, we want to run all the tweens\n                    // otherwise we skip this part\n                    length = gotoEnd ? animation.tweens.length : 0;\n\n                for ( ; index < length ; index++ ) {\n                    animation.tweens[ index ].run( 1 );\n                }\n\n                // resolve when we played the last frame\n                // otherwise, reject\n                if ( gotoEnd ) {\n                    deferred.resolveWith( elem, [ animation, gotoEnd ] );\n                } else {\n                    deferred.rejectWith( elem, [ animation, gotoEnd ] );\n                }\n                return this;\n            }\n        }),\n        props = animation.props;\n\n    propFilter( props, animation.opts.specialEasing );\n\n    for ( ; index < length ; index++ ) {\n        result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n        if ( result ) {\n            return result;\n        }\n    }\n\n    createTweens( animation, props );\n\n    if ( jQuery.isFunction( animation.opts.start ) ) {\n        animation.opts.start.call( elem, animation );\n    }\n\n    jQuery.fx.timer(\n        jQuery.extend( tick, {\n            anim: animation,\n            queue: animation.opts.queue,\n            elem: elem\n        })\n    );\n\n    // attach callbacks from options\n    return animation.progress( animation.opts.progress )\n        .done( animation.opts.done, animation.opts.complete )\n        .fail( animation.opts.fail )\n        .always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n    var index, name, easing, value, hooks;\n\n    // camelCase, specialEasing and expand cssHook pass\n    for ( index in props ) {\n        name = jQuery.camelCase( index );\n        easing = specialEasing[ name ];\n        value = props[ index ];\n        if ( jQuery.isArray( value ) ) {\n            easing = value[ 1 ];\n            value = props[ index ] = value[ 0 ];\n        }\n\n        if ( index !== name ) {\n            props[ name ] = value;\n            delete props[ index ];\n        }\n\n        hooks = jQuery.cssHooks[ name ];\n        if ( hooks && \"expand\" in hooks ) {\n            value = hooks.expand( value );\n            delete props[ name ];\n\n            // not quite $.extend, this wont overwrite keys already present.\n            // also - reusing 'index' from above because we have the correct \"name\"\n            for ( index in value ) {\n                if ( !( index in props ) ) {\n                    props[ index ] = value[ index ];\n                    specialEasing[ index ] = easing;\n                }\n            }\n        } else {\n            specialEasing[ name ] = easing;\n        }\n    }\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n    tweener: function( props, callback ) {\n        if ( jQuery.isFunction( props ) ) {\n            callback = props;\n            props = [ \"*\" ];\n        } else {\n            props = props.split(\" \");\n        }\n\n        var prop,\n            index = 0,\n            length = props.length;\n\n        for ( ; index < length ; index++ ) {\n            prop = props[ index ];\n            tweeners[ prop ] = tweeners[ prop ] || [];\n            tweeners[ prop ].unshift( callback );\n        }\n    },\n\n    prefilter: function( callback, prepend ) {\n        if ( prepend ) {\n            animationPrefilters.unshift( callback );\n        } else {\n            animationPrefilters.push( callback );\n        }\n    }\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n    var index, prop, value, length, dataShow, tween, hooks, oldfire,\n        anim = this,\n        style = elem.style,\n        orig = {},\n        handled = [],\n        hidden = elem.nodeType && isHidden( elem );\n\n    // handle queue: false promises\n    if ( !opts.queue ) {\n        hooks = jQuery._queueHooks( elem, \"fx\" );\n        if ( hooks.unqueued == null ) {\n            hooks.unqueued = 0;\n            oldfire = hooks.empty.fire;\n            hooks.empty.fire = function() {\n                if ( !hooks.unqueued ) {\n                    oldfire();\n                }\n            };\n        }\n        hooks.unqueued++;\n\n        anim.always(function() {\n            // doing this makes sure that the complete handler will be called\n            // before this completes\n            anim.always(function() {\n                hooks.unqueued--;\n                if ( !jQuery.queue( elem, \"fx\" ).length ) {\n                    hooks.empty.fire();\n                }\n            });\n        });\n    }\n\n    // height/width overflow pass\n    if ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n        // Make sure that nothing sneaks out\n        // Record all 3 overflow attributes because IE does not\n        // change the overflow attribute when overflowX and\n        // overflowY are set to the same value\n        opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n        // Set display property to inline-block for height/width\n        // animations on inline elements that are having width/height animated\n        if ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n                jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n            // inline-level elements accept inline-block;\n            // block-level elements need to be inline with layout\n            if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n                style.display = \"inline-block\";\n\n            } else {\n                style.zoom = 1;\n            }\n        }\n    }\n\n    if ( opts.overflow ) {\n        style.overflow = \"hidden\";\n        if ( !jQuery.support.shrinkWrapBlocks ) {\n            anim.done(function() {\n                style.overflow = opts.overflow[ 0 ];\n                style.overflowX = opts.overflow[ 1 ];\n                style.overflowY = opts.overflow[ 2 ];\n            });\n        }\n    }\n\n\n    // show/hide pass\n    for ( index in props ) {\n        value = props[ index ];\n        if ( rfxtypes.exec( value ) ) {\n            delete props[ index ];\n            if ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n                continue;\n            }\n            handled.push( index );\n        }\n    }\n\n    length = handled.length;\n    if ( length ) {\n        dataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n        if ( hidden ) {\n            jQuery( elem ).show();\n        } else {\n            anim.done(function() {\n                jQuery( elem ).hide();\n            });\n        }\n        anim.done(function() {\n            var prop;\n            jQuery.removeData( elem, \"fxshow\", true );\n            for ( prop in orig ) {\n                jQuery.style( elem, prop, orig[ prop ] );\n            }\n        });\n        for ( index = 0 ; index < length ; index++ ) {\n            prop = handled[ index ];\n            tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n            orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n            if ( !( prop in dataShow ) ) {\n                dataShow[ prop ] = tween.start;\n                if ( hidden ) {\n                    tween.end = tween.start;\n                    tween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n                }\n            }\n        }\n    }\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n    return new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n    constructor: Tween,\n    init: function( elem, options, prop, end, easing, unit ) {\n        this.elem = elem;\n        this.prop = prop;\n        this.easing = easing || \"swing\";\n        this.options = options;\n        this.start = this.now = this.cur();\n        this.end = end;\n        this.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n    },\n    cur: function() {\n        var hooks = Tween.propHooks[ this.prop ];\n\n        return hooks && hooks.get ?\n            hooks.get( this ) :\n            Tween.propHooks._default.get( this );\n    },\n    run: function( percent ) {\n        var eased,\n            hooks = Tween.propHooks[ this.prop ];\n\n        this.pos = eased = jQuery.easing[ this.easing ]( percent, this.options.duration * percent, 0, 1, this.options.duration );\n        this.now = ( this.end - this.start ) * eased + this.start;\n\n        if ( this.options.step ) {\n            this.options.step.call( this.elem, this.now, this );\n        }\n\n        if ( hooks && hooks.set ) {\n            hooks.set( this );\n        } else {\n            Tween.propHooks._default.set( this );\n        }\n        return this;\n    }\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n    _default: {\n        get: function( tween ) {\n            var result;\n\n            if ( tween.elem[ tween.prop ] != null &&\n                (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n                return tween.elem[ tween.prop ];\n            }\n\n            // passing any value as a 4th parameter to .css will automatically\n            // attempt a parseFloat and fallback to a string if the parse fails\n            // so, simple values such as \"10px\" are parsed to Float.\n            // complex values such as \"rotate(1rad)\" are returned as is.\n            result = jQuery.css( tween.elem, tween.prop, false, \"\" );\n            // Empty strings, null, undefined and \"auto\" are converted to 0.\n            return !result || result === \"auto\" ? 0 : result;\n        },\n        set: function( tween ) {\n            // use step hook for back compat - use cssHook if its there - use .style if its\n            // available and use plain properties where available\n            if ( jQuery.fx.step[ tween.prop ] ) {\n                jQuery.fx.step[ tween.prop ]( tween );\n            } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n                jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n            } else {\n                tween.elem[ tween.prop ] = tween.now;\n            }\n        }\n    }\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n    set: function( tween ) {\n        if ( tween.elem.nodeType && tween.elem.parentNode ) {\n            tween.elem[ tween.prop ] = tween.now;\n        }\n    }\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n    var cssFn = jQuery.fn[ name ];\n    jQuery.fn[ name ] = function( speed, easing, callback ) {\n        return speed == null || typeof speed === \"boolean\" ||\n            // special check for .toggle( handler, handler, ... )\n            ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?\n            cssFn.apply( this, arguments ) :\n            this.animate( genFx( name, true ), speed, easing, callback );\n    };\n});\n\njQuery.fn.extend({\n    fadeTo: function( speed, to, easing, callback ) {\n\n        // show any hidden elements after setting opacity to 0\n        return this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n            // animate to the value specified\n            .end().animate({ opacity: to }, speed, easing, callback );\n    },\n    animate: function( prop, speed, easing, callback ) {\n        var empty = jQuery.isEmptyObject( prop ),\n            optall = jQuery.speed( speed, easing, callback ),\n            doAnimation = function() {\n                // Operate on a copy of prop so per-property easing won't be lost\n                var anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n                // Empty animations resolve immediately\n                if ( empty ) {\n                    anim.stop( true );\n                }\n            };\n\n        return empty || optall.queue === false ?\n            this.each( doAnimation ) :\n            this.queue( optall.queue, doAnimation );\n    },\n    stop: function( type, clearQueue, gotoEnd ) {\n        var stopQueue = function( hooks ) {\n            var stop = hooks.stop;\n            delete hooks.stop;\n            stop( gotoEnd );\n        };\n\n        if ( typeof type !== \"string\" ) {\n            gotoEnd = clearQueue;\n            clearQueue = type;\n            type = undefined;\n        }\n        if ( clearQueue && type !== false ) {\n            this.queue( type || \"fx\", [] );\n        }\n\n        return this.each(function() {\n            var dequeue = true,\n                index = type != null && type + \"queueHooks\",\n                timers = jQuery.timers,\n                data = jQuery._data( this );\n\n            if ( index ) {\n                if ( data[ index ] && data[ index ].stop ) {\n                    stopQueue( data[ index ] );\n                }\n            } else {\n                for ( index in data ) {\n                    if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n                        stopQueue( data[ index ] );\n                    }\n                }\n            }\n\n            for ( index = timers.length; index--; ) {\n                if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n                    timers[ index ].anim.stop( gotoEnd );\n                    dequeue = false;\n                    timers.splice( index, 1 );\n                }\n            }\n\n            // start the next in the queue if the last step wasn't forced\n            // timers currently will call their complete callbacks, which will dequeue\n            // but only if they were gotoEnd\n            if ( dequeue || !gotoEnd ) {\n                jQuery.dequeue( this, type );\n            }\n        });\n    }\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n    var which,\n        attrs = { height: type },\n        i = 0;\n\n    // if we include width, step value is 1 to do all cssExpand values,\n    // if we don't include width, step value is 2 to skip over Left and Right\n    for( ; i < 4 ; i += 2 - includeWidth ) {\n        which = cssExpand[ i ];\n        attrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n    }\n\n    if ( includeWidth ) {\n        attrs.opacity = attrs.width = type;\n    }\n\n    return attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n    slideDown: genFx(\"show\"),\n    slideUp: genFx(\"hide\"),\n    slideToggle: genFx(\"toggle\"),\n    fadeIn: { opacity: \"show\" },\n    fadeOut: { opacity: \"hide\" },\n    fadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n    jQuery.fn[ name ] = function( speed, easing, callback ) {\n        return this.animate( props, speed, easing, callback );\n    };\n});\n\njQuery.speed = function( speed, easing, fn ) {\n    var opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n        complete: fn || !fn && easing ||\n            jQuery.isFunction( speed ) && speed,\n        duration: speed,\n        easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n    };\n\n    opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n        opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n    // normalize opt.queue - true/undefined/null -> \"fx\"\n    if ( opt.queue == null || opt.queue === true ) {\n        opt.queue = \"fx\";\n    }\n\n    // Queueing\n    opt.old = opt.complete;\n\n    opt.complete = function() {\n        if ( jQuery.isFunction( opt.old ) ) {\n            opt.old.call( this );\n        }\n\n        if ( opt.queue ) {\n            jQuery.dequeue( this, opt.queue );\n        }\n    };\n\n    return opt;\n};\n\njQuery.easing = {\n    linear: function( p ) {\n        return p;\n    },\n    swing: function( p ) {\n        return 0.5 - Math.cos( p*Math.PI ) / 2;\n    }\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n    var timer,\n        timers = jQuery.timers,\n        i = 0;\n\n    for ( ; i < timers.length; i++ ) {\n        timer = timers[ i ];\n        // Checks the timer has not already been removed\n        if ( !timer() && timers[ i ] === timer ) {\n            timers.splice( i--, 1 );\n        }\n    }\n\n    if ( !timers.length ) {\n        jQuery.fx.stop();\n    }\n};\n\njQuery.fx.timer = function( timer ) {\n    if ( timer() && jQuery.timers.push( timer ) && !timerId ) {\n        timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n    }\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.stop = function() {\n    clearInterval( timerId );\n    timerId = null;\n};\n\njQuery.fx.speeds = {\n    slow: 600,\n    fast: 200,\n    // Default speed\n    _default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n    jQuery.expr.filters.animated = function( elem ) {\n        return jQuery.grep(jQuery.timers, function( fn ) {\n            return elem === fn.elem;\n        }).length;\n    };\n}\nvar rroot = /^(?:body|html)$/i;\n\njQuery.fn.offset = function( options ) {\n    if ( arguments.length ) {\n        return options === undefined ?\n            this :\n            this.each(function( i ) {\n                jQuery.offset.setOffset( this, options, i );\n            });\n    }\n\n    var box, docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, top, left,\n        elem = this[ 0 ],\n        doc = elem && elem.ownerDocument;\n\n    if ( !doc ) {\n        return;\n    }\n\n    if ( (body = doc.body) === elem ) {\n        return jQuery.offset.bodyOffset( elem );\n    }\n\n    docElem = doc.documentElement;\n\n    // Make sure we're not dealing with a disconnected DOM node\n    if ( !jQuery.contains( docElem, elem ) ) {\n        return { top: 0, left: 0 };\n    }\n\n    box = elem.getBoundingClientRect();\n    win = getWindow( doc );\n    clientTop  = docElem.clientTop  || body.clientTop  || 0;\n    clientLeft = docElem.clientLeft || body.clientLeft || 0;\n    scrollTop  = win.pageYOffset || docElem.scrollTop;\n    scrollLeft = win.pageXOffset || docElem.scrollLeft;\n    top  = box.top  + scrollTop  - clientTop;\n    left = box.left + scrollLeft - clientLeft;\n\n    return { top: top, left: left };\n};\n\njQuery.offset = {\n\n    bodyOffset: function( body ) {\n        var top = body.offsetTop,\n            left = body.offsetLeft;\n\n        if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n            top  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n            left += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n        }\n\n        return { top: top, left: left };\n    },\n\n    setOffset: function( elem, options, i ) {\n        var position = jQuery.css( elem, \"position\" );\n\n        // set position first, in-case top/left are set even on static elem\n        if ( position === \"static\" ) {\n            elem.style.position = \"relative\";\n        }\n\n        var curElem = jQuery( elem ),\n            curOffset = curElem.offset(),\n            curCSSTop = jQuery.css( elem, \"top\" ),\n            curCSSLeft = jQuery.css( elem, \"left\" ),\n            calculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n            props = {}, curPosition = {}, curTop, curLeft;\n\n        // need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n        if ( calculatePosition ) {\n            curPosition = curElem.position();\n            curTop = curPosition.top;\n            curLeft = curPosition.left;\n        } else {\n            curTop = parseFloat( curCSSTop ) || 0;\n            curLeft = parseFloat( curCSSLeft ) || 0;\n        }\n\n        if ( jQuery.isFunction( options ) ) {\n            options = options.call( elem, i, curOffset );\n        }\n\n        if ( options.top != null ) {\n            props.top = ( options.top - curOffset.top ) + curTop;\n        }\n        if ( options.left != null ) {\n            props.left = ( options.left - curOffset.left ) + curLeft;\n        }\n\n        if ( \"using\" in options ) {\n            options.using.call( elem, props );\n        } else {\n            curElem.css( props );\n        }\n    }\n};\n\n\njQuery.fn.extend({\n\n    position: function() {\n        if ( !this[0] ) {\n            return;\n        }\n\n        var elem = this[0],\n\n        // Get *real* offsetParent\n        offsetParent = this.offsetParent(),\n\n        // Get correct offsets\n        offset       = this.offset(),\n        parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n        // Subtract element margins\n        // note: when an element has margin: auto the offsetLeft and marginLeft\n        // are the same in Safari causing offset.left to incorrectly be 0\n        offset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n        offset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n        // Add offsetParent borders\n        parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n        parentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n        // Subtract the two offsets\n        return {\n            top:  offset.top  - parentOffset.top,\n            left: offset.left - parentOffset.left\n        };\n    },\n\n    offsetParent: function() {\n        return this.map(function() {\n            var offsetParent = this.offsetParent || document.body;\n            while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n                offsetParent = offsetParent.offsetParent;\n            }\n            return offsetParent || document.body;\n        });\n    }\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n    var top = /Y/.test( prop );\n\n    jQuery.fn[ method ] = function( val ) {\n        return jQuery.access( this, function( elem, method, val ) {\n            var win = getWindow( elem );\n\n            if ( val === undefined ) {\n                return win ? (prop in win) ? win[ prop ] :\n                    win.document.documentElement[ method ] :\n                    elem[ method ];\n            }\n\n            if ( win ) {\n                win.scrollTo(\n                    !top ? val : jQuery( win ).scrollLeft(),\n                     top ? val : jQuery( win ).scrollTop()\n                );\n\n            } else {\n                elem[ method ] = val;\n            }\n        }, method, val, arguments.length, null );\n    };\n});\n\nfunction getWindow( elem ) {\n    return jQuery.isWindow( elem ) ?\n        elem :\n        elem.nodeType === 9 ?\n            elem.defaultView || elem.parentWindow :\n            false;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n    jQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n        // margin is only for outerHeight, outerWidth\n        jQuery.fn[ funcName ] = function( margin, value ) {\n            var chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n                extra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n            return jQuery.access( this, function( elem, type, value ) {\n                var doc;\n\n                if ( jQuery.isWindow( elem ) ) {\n                    // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n                    // isn't a whole lot we can do. See pull request at this URL for discussion:\n                    // https://github.com/jquery/jquery/pull/764\n                    return elem.document.documentElement[ \"client\" + name ];\n                }\n\n                // Get document width or height\n                if ( elem.nodeType === 9 ) {\n                    doc = elem.documentElement;\n\n                    // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n                    // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n                    return Math.max(\n                        elem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n                        elem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n                        doc[ \"client\" + name ]\n                    );\n                }\n\n                return value === undefined ?\n                    // Get width or height on the element, requesting but not forcing parseFloat\n                    jQuery.css( elem, type, value, extra ) :\n\n                    // Set width or height on the element\n                    jQuery.style( elem, type, value, extra );\n            }, type, chainable ? margin : undefined, chainable );\n        };\n    });\n});\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n    define( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );\n"
  },
  {
    "path": "test/perf/OpenFile-perf-files/jquery.mobile-1.1.0.css",
    "content": "/*\n* jQuery Mobile Framework 1.1.0 db342b1f315c282692791aa870455901fdb46a55\n* http://jquerymobile.com\n*\n* Copyright 2011 (c) jQuery Project\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n*/\n/* Swatches */\n/* A\n-----------------------------------------------------------------------------------------------------------*/\n.ui-bar-a {\n\tborder: 1px solid \t\t#333 /*{a-bar-border}*/;\n\tbackground: \t\t\t#111111 /*{a-bar-background-color}*/;\n\tcolor: \t\t\t\t\t#ffffff /*{a-bar-color}*/;\n\tfont-weight: bold;\n\ttext-shadow: 0 /*{a-bar-shadow-x}*/ -1px /*{a-bar-shadow-y}*/ 1px /*{a-bar-shadow-radius}*/ #000000 /*{a-bar-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #3c3c3c /*{a-bar-background-start}*/), to( #111 /*{a-bar-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/);\n}\n.ui-bar-a, \n.ui-bar-a input, \n.ui-bar-a select, \n.ui-bar-a textarea, \n.ui-bar-a button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-bar-a .ui-link-inherit {\n\tcolor: #fff /*{a-bar-color}*/;\n}\n.ui-bar-a .ui-link {\n\tcolor: #7cc4e7 /*{a-bar-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-a .ui-link:hover {\n\tcolor: #2489CE /*{a-bar-link-hover}*/;\n}\n.ui-bar-a .ui-link:active {\n\tcolor: #2489CE /*{a-bar-link-active}*/;\n}\n.ui-bar-a .ui-link:visited {\n    color: #2489CE /*{a-bar-link-visited}*/;\n}\n.ui-body-a,\n.ui-overlay-a {\n\tborder: 1px solid \t\t#444 /*{a-body-border}*/;\n\tbackground: \t\t\t#222 /*{a-body-background-color}*/;\n\tcolor: \t\t\t\t\t#fff /*{a-body-color}*/;\n\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 1px /*{a-body-shadow-radius}*/ #111 /*{a-body-shadow-color}*/;\n\tfont-weight: normal;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #444 /*{a-body-background-start}*/), to( #222 /*{a-body-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/);\t\n}\n.ui-overlay-a {\n\tbackground-image: none;\n\tborder-width: 0;\n}\n.ui-body-a,\n.ui-body-a input,\n.ui-body-a select,\n.ui-body-a textarea,\n.ui-body-a button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-body-a .ui-link-inherit {\n\tcolor: \t#fff /*{a-body-color}*/;\n}\n.ui-body-a .ui-link {\n\tcolor: #2489CE /*{a-body-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-body-a .ui-link:hover {\n\tcolor: #2489CE /*{a-body-link-hover}*/;\n}\n.ui-body-a .ui-link:active {\n\tcolor: #2489CE /*{a-body-link-active}*/;\n}\n.ui-body-a .ui-link:visited {\n    color: #2489CE /*{a-body-link-visited}*/;\n}\n.ui-btn-up-a {\n\tborder: 1px solid \t\t#111 /*{a-bup-border}*/;\n\tbackground: \t\t\t#333 /*{a-bup-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{a-bup-color}*/;\n\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 1px /*{a-bup-shadow-radius}*/ #111 /*{a-bup-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #444444 /*{a-bup-background-start}*/), to( #2d2d2d /*{a-bup-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/);\n}\n.ui-btn-up-a a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{a-bup-color}*/;\n}\n.ui-btn-hover-a {\n\tborder: 1px solid \t\t#000 /*{a-bhover-border}*/;\n\tbackground: \t\t\t#444444 /*{a-bhover-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{a-bhover-color}*/;\n\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 1px /*{a-bhover-shadow-radius}*/ #111 /*{a-bhover-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #555555 /*{a-bhover-background-start}*/), to( #383838 /*{a-bhover-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/);\n}\n.ui-btn-hover-a a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{a-bhover-color}*/;\n}\n.ui-btn-down-a {\n\tborder: 1px solid \t\t#000 /*{a-bdown-border}*/;\n\tbackground: \t\t\t#222 /*{a-bdown-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{a-bdown-color}*/;\n\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 1px /*{a-bdown-shadow-radius}*/ #111 /*{a-bdown-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #202020 /*{a-bdown-background-start}*/), to( #2c2c2c /*{a-bdown-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/);\n}\n.ui-btn-down-a a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{a-bdown-color}*/;\n}\n.ui-btn-up-a,\n.ui-btn-hover-a,\n.ui-btn-down-a {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n\ttext-decoration: none;\n}\n/* B\n-----------------------------------------------------------------------------------------------------------*/\n.ui-bar-b {\n\tborder: 1px solid \t\t#456f9a /*{b-bar-border}*/;\n\tbackground: \t\t\t#5e87b0 /*{b-bar-background-color}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n\tfont-weight: bold;\n\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 1px /*{b-bar-shadow-radius}*/ #3e6790 /*{b-bar-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #6facd5 /*{b-bar-background-start}*/), to( #497bae /*{b-bar-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/);\n}\n.ui-bar-b,\n.ui-bar-b input,\n.ui-bar-b select,\n.ui-bar-b textarea,\n.ui-bar-b button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-bar-b .ui-link-inherit {\n\tcolor: \t#fff /*{b-bar-color}*/;\n}\n.ui-bar-b .ui-link {\n\tcolor: #ddf0f8 /*{b-bar-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-b .ui-link:hover {\n\tcolor: #ddf0f8 /*{b-bar-link-hover}*/;\n}\n.ui-bar-b .ui-link:active {\n\tcolor: #ddf0f8 /*{b-bar-link-active}*/;\n}\n.ui-bar-b .ui-link:visited {\n    color: #ddf0f8 /*{b-bar-link-visited}*/;\n}\n.ui-body-b,\n.ui-overlay-b {\n\tborder: 1px solid \t\t#999 /*{b-body-border}*/;\n\tbackground: \t\t\t#f3f3f3 /*{b-body-background-color}*/;\n\tcolor: \t\t\t\t\t#222222 /*{b-body-color}*/;\n\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ #fff /*{b-body-shadow-color}*/;\n\tfont-weight: normal;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #ddd /*{b-body-background-start}*/), to( #ccc /*{b-body-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/);\n}\n.ui-overlay-b {\n\tbackground-image: none;\n\tborder-width: 0;\n}\n.ui-body-b,\n.ui-body-b input,\n.ui-body-b select,\n.ui-body-b textarea,\n.ui-body-b button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-body-b .ui-link-inherit {\n\tcolor: \t#333333 /*{b-body-color}*/;\n}\n.ui-body-b .ui-link {\n\tcolor: #2489CE /*{b-body-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-body-b .ui-link:hover {\n\tcolor: #2489CE /*{b-body-link-hover}*/;\n}\n.ui-body-b .ui-link:active {\n\tcolor: #2489CE /*{b-body-link-active}*/;\n}\n.ui-body-b .ui-link:visited {\n    color: #2489CE /*{b-body-link-visited}*/;\n}\n.ui-btn-up-b {\n\tborder: 1px solid \t\t#044062 /*{b-bup-border}*/;\n\tbackground: \t\t\t#396b9e /*{b-bup-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 1px /*{b-bup-shadow-radius}*/ #194b7e /*{b-bup-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #5f9cc5 /*{b-bup-background-start}*/), to( #396b9e /*{b-bup-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/);\n}\n.ui-btn-up-b a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n}\n.ui-btn-hover-b {\n\tborder: 1px solid \t\t#00415e /*{b-bhover-border}*/;\n\tbackground: \t\t\t#4b88b6 /*{b-bhover-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 1px /*{b-bhover-shadow-radius}*/ #194b7e /*{b-bhover-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #6facd5 /*{b-bhover-background-start}*/), to( #4272a4 /*{b-bhover-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/);\n}\n.ui-btn-hover-b a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n}\n.ui-btn-down-b {\n\tborder: 1px solid \t\t#225377 /*{b-bdown-border}*/;\n\tbackground: \t\t\t#4e89c5 /*{b-bdown-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 1px /*{b-bdown-shadow-radius}*/ #194b7e /*{b-bdown-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #295b8e /*{b-bdown-background-start}*/), to( #3e79b5 /*{b-bdown-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/);\n}\n.ui-btn-down-b a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n}\n.ui-btn-up-b,\n.ui-btn-hover-b,\n.ui-btn-down-b {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n\ttext-decoration: none;\n}\n/* C\n-----------------------------------------------------------------------------------------------------------*/\n.ui-bar-c {\n\tborder: 1px solid \t\t#B3B3B3 /*{c-bar-border}*/;\n\tbackground: \t\t\t#eeeeee /*{c-bar-background-color}*/;\n\tcolor: \t\t\t\t\t#3E3E3E /*{c-bar-color}*/;\n\tfont-weight: bold;\n\ttext-shadow: 0 /*{c-bar-shadow-x}*/ 1px /*{c-bar-shadow-y}*/ 1px /*{c-bar-shadow-radius}*/ \t#fff /*{c-bar-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #f0f0f0 /*{c-bar-background-start}*/), to( #ddd /*{c-bar-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/);\n}\n.ui-bar-c .ui-link-inherit {\n\tcolor: \t#3E3E3E /*{c-bar-color}*/;\n}\n.ui-bar-c .ui-link {\n\tcolor: #7cc4e7 /*{c-bar-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-c .ui-link:hover {\n\tcolor: #2489CE /*{c-bar-link-hover}*/;\n}\n.ui-bar-c .ui-link:active {\n\tcolor: #2489CE /*{c-bar-link-active}*/;\n}\n.ui-bar-c .ui-link:visited {\n    color: #2489CE /*{c-bar-link-visited}*/;\n}\n.ui-bar-c,\n.ui-bar-c input,\n.ui-bar-c select,\n.ui-bar-c textarea,\n.ui-bar-c button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-body-c,\n.ui-overlay-c {\n\tborder: 1px solid \t\t#aaa /*{c-body-border}*/;\n\tcolor: \t\t\t\t\t#333333 /*{c-body-color}*/;\n\ttext-shadow: 0 /*{c-body-shadow-x}*/ 1px /*{c-body-shadow-y}*/ 0 /*{c-body-shadow-radius}*/ #fff /*{c-body-shadow-color}*/;\n\tbackground: \t\t\t#f9f9f9 /*{c-body-background-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #f9f9f9 /*{c-body-background-start}*/), to( #eeeeee /*{c-body-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/);\n}\n.ui-overlay-c {\n\tbackground-image: none;\n\tborder-width: 0;\n}\n.ui-body-c,\n.ui-body-c input,\n.ui-body-c select,\n.ui-body-c textarea,\n.ui-body-c button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-body-c .ui-link-inherit {\n\tcolor: \t#333333 /*{c-body-color}*/;\n}\n.ui-body-c .ui-link {\n\tcolor: #2489CE /*{c-body-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-body-c .ui-link:hover {\n\tcolor: #2489CE /*{c-body-link-hover}*/;\n}\n.ui-body-c .ui-link:active {\n\tcolor: #2489CE /*{c-body-link-active}*/;\n}\n.ui-body-c .ui-link:visited {\n    color: #2489CE /*{c-body-link-visited}*/;\n}\n.ui-btn-up-c {\n\tborder: 1px solid \t\t#ccc /*{c-bup-border}*/;\n\tbackground: \t\t\t#eee /*{c-bup-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#222 /*{c-bup-color}*/;\n\ttext-shadow: 0 /*{c-bup-shadow-x}*/ 1px /*{c-bup-shadow-y}*/ 0 /*{c-bup-shadow-radius}*/ #ffffff /*{c-bup-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #ffffff /*{c-bup-background-start}*/), to( #f1f1f1 /*{c-bup-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/);\n}\n.ui-btn-up-c a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#2F3E46 /*{c-bup-color}*/;\n}\n.ui-btn-hover-c {\n\tborder: 1px solid \t\t#bbb /*{c-bhover-border}*/;\n\tbackground: \t\t\t#dfdfdf /*{c-bhover-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#222 /*{c-bhover-color}*/;\n\ttext-shadow: 0 /*{c-bhover-shadow-x}*/ 1px /*{c-bhover-shadow-y}*/ 0 /*{c-bhover-shadow-radius}*/ #ffffff /*{c-bhover-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #f6f6f6 /*{c-bhover-background-start}*/), to( #e0e0e0 /*{c-bhover-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #f9f9f9 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/);\n}\n.ui-btn-hover-c a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#2F3E46 /*{c-bhover-color}*/;\n}\n.ui-btn-down-c {\n\tborder: 1px solid \t\t#bbb /*{c-bdown-border}*/;\n\tbackground: \t\t\t#d6d6d6 /*{c-bdown-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#222 /*{c-bdown-color}*/;\n\ttext-shadow: 0 /*{c-bdown-shadow-x}*/ 1px /*{c-bdown-shadow-y}*/ 0 /*{c-bdown-shadow-radius}*/ #ffffff /*{c-bdown-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #d0d0d0 /*{c-bdown-background-start}*/), to( #dfdfdf /*{c-bdown-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/);\n}\n.ui-btn-down-c a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#2F3E46 /*{c-bdown-color}*/;\n}\n.ui-btn-up-c,\n.ui-btn-hover-c,\n.ui-btn-down-c {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n\ttext-decoration: none;\n}\n/* D\n-----------------------------------------------------------------------------------------------------------*/\n.ui-bar-d {\n\tborder: 1px solid \t\t#bbb /*{d-bar-border}*/;\n\tbackground: \t\t\t#bbb /*{d-bar-background-color}*/;\n\tcolor: \t\t\t\t\t#333 /*{d-bar-color}*/;\n\ttext-shadow: 0 /*{d-bar-shadow-x}*/ 1px /*{d-bar-shadow-y}*/ 0 /*{d-bar-shadow-radius}*/ #eee /*{d-bar-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #ddd /*{d-bar-background-start}*/), to( #bbb /*{d-bar-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/);\n}\n.ui-bar-d,\n.ui-bar-d input,\n.ui-bar-d select,\n.ui-bar-d textarea,\n.ui-bar-d button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-bar-d .ui-link-inherit {\n\tcolor: \t#333333 /*{d-bar-color}*/;\n}\n.ui-bar-d .ui-link {\n\tcolor: #2489CE /*{d-bar-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-d .ui-link:hover {\n\tcolor: #2489CE /*{d-bar-link-hover}*/;\n}\n.ui-bar-d .ui-link:active {\n\tcolor: #2489CE /*{d-bar-link-active}*/;\n}\n.ui-bar-d .ui-link:visited {\n    color: #2489CE /*{d-bar-link-visited}*/;\n}\n.ui-body-d,\n.ui-overlay-d {\n\tborder: 1px solid \t\t#bbb /*{d-body-border}*/;\n\tcolor: \t\t\t\t\t#333333 /*{d-body-color}*/;\n\ttext-shadow: 0 /*{d-body-shadow-x}*/ 1px /*{d-body-shadow-y}*/ 0 /*{d-body-shadow-radius}*/ \t#fff /*{d-body-shadow-color}*/;\n\tbackground: \t\t\t#ffffff /*{d-body-background-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #fff), to( #fff /*{d-body-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/);\n}\n.ui-overlay-d {\n\tbackground-image: none;\n\tborder-width: 0;\n}\n.ui-body-d,\n.ui-body-d input,\n.ui-body-d select,\n.ui-body-d textarea,\n.ui-body-d button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-body-d .ui-link-inherit {\n\tcolor: \t#333333 /*{d-body-color}*/;\n}\n.ui-body-d .ui-link {\n\tcolor: #2489CE /*{d-body-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-body-d .ui-link:hover {\n\tcolor: #2489CE /*{d-body-link-hover}*/;\n}\n.ui-body-d .ui-link:active {\n\tcolor: #2489CE /*{d-body-link-active}*/;\n}\n.ui-body-d .ui-link:visited {\n    color: #2489CE /*{d-body-link-visited}*/;\n}\n.ui-btn-up-d {\n\tborder: 1px solid \t\t#bbb /*{d-bup-border}*/;\n\tbackground: \t\t\t#fff /*{d-bup-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#333 /*{d-bup-color}*/;\n\ttext-shadow: 0 /*{d-bup-shadow-x}*/ 1px /*{d-bup-shadow-y}*/ 0 /*{d-bup-shadow-radius}*/ #fff /*{d-bup-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #fafafa), to( #f6f6f6 /*{d-bup-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/);\n}\n.ui-btn-up-d a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#333 /*{d-bup-color}*/;\n}\n.ui-btn-hover-d {\n\tborder: 1px solid \t\t#aaa /*{d-bhover-border}*/;\n\tbackground: \t\t\t#eeeeee /*{d-bhover-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#333 /*{d-bhover-color}*/;\n\tcursor: pointer;\n\ttext-shadow: 0 /*{d-bhover-shadow-x}*/ 1px /*{d-bhover-shadow-y}*/ 0 /*{d-bhover-shadow-radius}*/ \t#fff /*{d-bhover-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #eee), to( #fff /*{d-bhover-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/);\n}\n.ui-btn-hover-d a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#333 /*{d-bhover-color}*/;\n}\n.ui-btn-down-d {\n\tborder: 1px solid \t\t#aaa /*{d-bdown-border}*/;\n\tbackground: \t\t\t#eee /*{d-bdown-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#333 /*{d-bdown-color}*/;\n\ttext-shadow: 0 /*{d-bdown-shadow-x}*/ 1px /*{d-bdown-shadow-y}*/ 0 /*{d-bdown-shadow-radius}*/ \t#ffffff /*{d-bdown-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #e5e5e5 /*{d-bdown-background-start}*/), to( #f2f2f2 /*{d-bdown-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/);\n}\n.ui-btn-down-d a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#333 /*{d-bdown-color}*/;\n}\n.ui-btn-up-d,\n.ui-btn-hover-d,\n.ui-btn-down-d {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n\ttext-decoration: none;\n}\n/* E\n-----------------------------------------------------------------------------------------------------------*/\n.ui-bar-e {\n\tborder: 1px solid \t\t#F7C942 /*{e-bar-border}*/;\n\tbackground: \t\t\t#fadb4e /*{e-bar-background-color}*/;\n\tcolor: \t\t\t\t\t#333 /*{e-bar-color}*/;\n\ttext-shadow: 0 /*{e-bar-shadow-x}*/ 1px /*{e-bar-shadow-y}*/ 0 /*{e-bar-shadow-radius}*/ \t#fff /*{e-bar-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #fceda7 /*{e-bar-background-start}*/), to( #fbef7e /*{e-bar-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/);\n}\n.ui-bar-e,\n.ui-bar-e input,\n.ui-bar-e select,\n.ui-bar-e textarea,\n.ui-bar-e button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-bar-e .ui-link-inherit {\n\tcolor: \t#333333 /*{e-bar-color}*/;\n}\n.ui-bar-e .ui-link {\n\tcolor: #2489CE /*{e-bar-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-e .ui-link:hover {\n\tcolor: #2489CE /*{e-bar-link-hover}*/;\n}\n.ui-bar-e .ui-link:active {\n\tcolor: #2489CE /*{e-bar-link-active}*/;\n}\n.ui-bar-e .ui-link:visited {\n    color: #2489CE /*{e-bar-link-visited}*/;\n}\n.ui-body-e,\n.ui-overlay-e {\n\tborder: 1px solid \t\t#F7C942 /*{e-body-border}*/;\n\tcolor: \t\t\t\t\t#222222 /*{e-body-color}*/;\n\ttext-shadow: 0 /*{e-body-shadow-x}*/ 1px /*{e-body-shadow-y}*/ 0 /*{e-body-shadow-radius}*/ \t#fff /*{e-body-shadow-color}*/;\n\tbackground: \t\t\t#fff9df /*{e-body-background-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #fffadf /*{e-body-background-start}*/), to( #fff3a5 /*{e-body-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/);\n}\n.ui-overlay-e {\n\tbackground-image: none;\n\tborder-width: 0;\n}\n.ui-body-e,\n.ui-body-e input,\n.ui-body-e select,\n.ui-body-e textarea,\n.ui-body-e button {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-body-e .ui-link-inherit {\n\tcolor: \t#333333 /*{e-body-color}*/;\n}\n.ui-body-e .ui-link {\n\tcolor: #2489CE /*{e-body-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-body-e .ui-link:hover {\n\tcolor: #2489CE /*{e-body-link-hover}*/;\n}\n.ui-body-e .ui-link:active {\n\tcolor: #2489CE /*{e-body-link-active}*/;\n}\n.ui-body-e .ui-link:visited {\n    color: #2489CE /*{e-body-link-visited}*/;\n}\n.ui-btn-up-e {\n\tborder: 1px solid \t\t#F4C63f /*{e-bup-border}*/;\n\tbackground: \t\t\t#fadb4e /*{e-bup-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#222 /*{e-bup-color}*/;\n\ttext-shadow: 0 /*{e-bup-shadow-x}*/ 1px /*{e-bup-shadow-y}*/ 0 /*{e-bup-shadow-radius}*/ \t#fff /*{e-bup-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #ffefaa /*{e-bup-background-start}*/), to( #ffe155 /*{e-bup-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/);\n}\n.ui-btn-up-e a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#222 /*{e-bup-color}*/;\n}\n.ui-btn-hover-e {\n\tborder: 1px solid \t\t#F2C43d /*{e-bhover-border}*/;\n\tbackground: \t\t\t#fbe26f /*{e-bhover-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#111 /*{e-bhover-color}*/;\n\ttext-shadow: 0 /*{e-bhover-shadow-x}*/ 1px /*{e-bhover-shadow-y}*/ 0 /*{e-bhover-shadow-radius}*/ \t#fff /*{e-bhover-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #fff5ba /*{e-bhover-background-start}*/), to( #fbdd52 /*{e-bhover-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/);\n}\n.ui-btn-hover-e a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#333 /*{e-bhover-color}*/;\n}\n.ui-btn-down-e {\n\tborder: 1px solid \t\t#F2C43d /*{e-bdown-border}*/;\n\tbackground: \t\t\t#fceda7 /*{e-bdown-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#111 /*{e-bdown-color}*/;\n\ttext-shadow: 0 /*{e-bdown-shadow-x}*/ 1px /*{e-bdown-shadow-y}*/ 0 /*{e-bdown-shadow-radius}*/ \t#ffffff /*{e-bdown-shadow-color}*/;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #f8d94c /*{e-bdown-background-start}*/), to( #fadb4e /*{e-bdown-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/);\n}\n.ui-btn-down-e a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#333 /*{e-bdown-color}*/;\n}\n.ui-btn-up-e,\n.ui-btn-hover-e,\n.ui-btn-down-e {\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n\ttext-decoration: none;\n}\n/* Structure */\n/* links within \"buttons\" \n-----------------------------------------------------------------------------------------------------------*/\na.ui-link-inherit {\n\ttext-decoration: none !important;\n}\n/* Active class used as the \"on\" state across all themes\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-active {\n\tborder: 1px solid \t\t#2373a5 /*{global-active-border}*/;\n\tbackground: \t\t\t#5393c5 /*{global-active-background-color}*/;\n\tfont-weight: bold;\n\tcolor: \t\t\t\t\t#fff /*{global-active-color}*/;\n\tcursor: pointer;\n\ttext-shadow: 0 /*{global-active-shadow-x}*/ 1px /*{global-active-shadow-y}*/ 1px /*{global-active-shadow-radius}*/ #3373a5 /*{global-active-shadow-color}*/;\n\ttext-decoration: none;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from( #5393c5 /*{global-active-background-start}*/), to( #6facd5 /*{global-active-background-end}*/)); /* Saf4+, Chrome */\n\tbackground-image: -webkit-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* Chrome 10+, Saf5.1+ */\n\tbackground-image:    -moz-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* FF3.6 */\n\tbackground-image:     -ms-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* IE10 */\n\tbackground-image:      -o-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* Opera 11.10+ */\n\tbackground-image:         linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/);\n\tfont-family: Helvetica, Arial, sans-serif /*{global-font-family}*/;\n}\n.ui-btn-active a.ui-link-inherit {\n\tcolor: \t\t\t\t\t#fff /*{global-active-color}*/;\n}\n/* button inner top highlight\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-inner {\n\tborder-top: 1px solid \t#fff;\n\tborder-color: \t\t\trgba(255,255,255,.3);\n}\n/* corner rounding classes\n-----------------------------------------------------------------------------------------------------------*/\n.ui-corner-tl {\n\t-moz-border-radius-topleft: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-top-left-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-top-left-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-tr {\n\t-moz-border-radius-topright: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-top-right-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-top-right-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-bl {\n\t-moz-border-radius-bottomleft: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-bottom-left-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-bottom-left-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-br {\n\t-moz-border-radius-bottomright: \t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/;\n\tborder-bottom-right-radius: \t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-top {\n\t-moz-border-radius-topleft: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-top-left-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-top-left-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n\t-moz-border-radius-topright: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-top-right-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-top-right-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-bottom {\n\t-moz-border-radius-bottomleft: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-bottom-left-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-bottom-left-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n\t-moz-border-radius-bottomright: \t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/;\n\tborder-bottom-right-radius: \t\t.6em /*{global-radii-blocks}*/;\n\t}\n.ui-corner-right {\n\t-moz-border-radius-topright: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-top-right-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-top-right-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n\t-moz-border-radius-bottomright: \t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/;\n\tborder-bottom-right-radius: \t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-left {\n\t-moz-border-radius-topleft: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-top-left-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-top-left-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n\t-moz-border-radius-bottomleft: \t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-bottom-left-radius: \t.6em /*{global-radii-blocks}*/;\n\tborder-bottom-left-radius: \t\t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-all {\n\t-moz-border-radius: \t\t\t\t.6em /*{global-radii-blocks}*/;\n\t-webkit-border-radius: \t\t\t\t.6em /*{global-radii-blocks}*/;\n\tborder-radius: \t\t\t\t\t\t.6em /*{global-radii-blocks}*/;\n}\n.ui-corner-none {\n\t-moz-border-radius: \t\t\t\t   0;\n\t-webkit-border-radius: \t\t\t\t   0;\n\tborder-radius: \t\t\t\t\t\t   0;\n}\n/* Form field separator\n-----------------------------------------------------------------------------------------------------------*/\n.ui-br {\n\tborder-bottom: rgb(130,130,130);\n\tborder-bottom: rgba(130,130,130,.3);\n\tborder-bottom-width: 1px;\n\tborder-bottom-style: solid;\n}\n/* Interaction cues\n-----------------------------------------------------------------------------------------------------------*/\n.ui-disabled {\n\topacity: \t\t\t\t\t\t\t.3;\n}\n.ui-disabled,\n.ui-disabled a {\n\tcursor: default !important;\n\tpointer-events: none;\n}\n.ui-disabled .ui-btn-text {\n\t-ms-filter:\"progid:DXImageTransform.Microsoft.Alpha(opacity=30)\";\n\tfilter: alpha(opacity=30);\n\tzoom: 1;\n}\n/* Icons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-icon,\n.ui-icon-searchfield:after {\n\tbackground: \t\t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground: \t\t\t\t\t\trgba(0,0,0,.4) /*{global-icon-disc}*/;\n\tbackground-image: url(images/icons-18-white.png) /*{global-icon-set}*/;\n\tbackground-repeat: no-repeat;\n\t-moz-border-radius: \t\t\t\t9px;\n\t-webkit-border-radius: \t\t\t\t9px;\n\tborder-radius: \t\t\t\t\t\t9px;\n}\n/* Alt icon color\n-----------------------------------------------------------------------------------------------------------*/\n.ui-icon-alt {\n\tbackground: \t\t\t\t\t\t#fff;\n\tbackground: \t\t\t\t\t\trgba(255,255,255,.3);\n\tbackground-image: url(images/icons-18-black.png);\n\tbackground-repeat: no-repeat;\n}\n/* HD/\"retina\" sprite\n-----------------------------------------------------------------------------------------------------------*/\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (min--moz-device-pixel-ratio: 1.5),\n       only screen and (min-resolution: 240dpi) {\n\t\n\t.ui-icon-plus, .ui-icon-minus, .ui-icon-delete, .ui-icon-arrow-r,\n\t.ui-icon-arrow-l, .ui-icon-arrow-u, .ui-icon-arrow-d, .ui-icon-check,\n\t.ui-icon-gear, .ui-icon-refresh, .ui-icon-forward, .ui-icon-back,\n\t.ui-icon-grid, .ui-icon-star, .ui-icon-alert, .ui-icon-info, .ui-icon-home, .ui-icon-search, .ui-icon-searchfield:after, \n\t.ui-icon-checkbox-off, .ui-icon-checkbox-on, .ui-icon-radio-off, .ui-icon-radio-on {\n\t\tbackground-image: url(images/icons-36-white.png);\n\t\t-moz-background-size: 776px 18px;\n\t\t-o-background-size: 776px 18px;\n\t\t-webkit-background-size: 776px 18px;\n\t\tbackground-size: 776px 18px;\n\t}\n\t.ui-icon-alt {\n\t\tbackground-image: url(images/icons-36-black.png);\n\t}\n}\n/* plus minus */\n.ui-icon-plus {\n\tbackground-position: \t-0 50%;\n}\n.ui-icon-minus {\n\tbackground-position: \t-36px 50%;\n}\n/* delete/close */\n.ui-icon-delete {\n\tbackground-position: \t-72px 50%;\n}\n/* arrows */\n.ui-icon-arrow-r {\n\tbackground-position: \t-108px 50%;\n}\n.ui-icon-arrow-l {\n\tbackground-position: \t-144px 50%;\n}\n.ui-icon-arrow-u {\n\tbackground-position: \t-180px 50%;\n}\n.ui-icon-arrow-d {\n\tbackground-position: \t-216px 50%;\n}\n/* misc */\n.ui-icon-check {\n\tbackground-position: \t-252px 50%;\n}\n.ui-icon-gear {\n\tbackground-position: \t-288px 50%;\n}\n.ui-icon-refresh {\n\tbackground-position: \t-324px 50%;\n}\n.ui-icon-forward {\n\tbackground-position: \t-360px 50%;\n}\n.ui-icon-back {\n\tbackground-position: \t-396px 50%;\n}\n.ui-icon-grid {\n\tbackground-position: \t-432px 50%;\n}\n.ui-icon-star {\n\tbackground-position: \t-468px 50%;\n}\n.ui-icon-alert {\n\tbackground-position: \t-504px 50%;\n}\n.ui-icon-info {\n\tbackground-position: \t-540px 50%;\n}\n.ui-icon-home {\n\tbackground-position: \t-576px 50%;\n}\n.ui-icon-search,\n.ui-icon-searchfield:after {\n\tbackground-position: \t-612px 50%;\n}\n.ui-icon-checkbox-off {\n\tbackground-position: \t-684px 50%;\n}\n.ui-icon-checkbox-on {\n\tbackground-position: \t-648px 50%;\n}\n.ui-icon-radio-off {\n\tbackground-position: \t-756px 50%;\n}\n.ui-icon-radio-on {\n\tbackground-position: \t-720px 50%;\n}\n/* checks,radios */\n.ui-checkbox .ui-icon {\n\t-moz-border-radius: 3px;\n\t-webkit-border-radius: 3px;\n\tborder-radius: 3px;\n}\n.ui-icon-checkbox-off,\n.ui-icon-radio-off {\n\tbackground-color: transparent;\t\n}\n.ui-checkbox-on .ui-icon,\n.ui-radio-on .ui-icon {\n\tbackground-color: #4596ce /*{global-active-background-color}*/; /* NOTE: this hex should match the active state color. It's repeated here for cascade */\n}\n/* loading icon */\n.ui-icon-loading {\n\tbackground: url(images/ajax-loader.gif);\n\tbackground-size: 46px 46px;\n}\n/* Button corner classes\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-corner-tl {\n\t-moz-border-radius-topleft: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-top-left-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-top-left-radius: \t\t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-tr {\n\t-moz-border-radius-topright: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-top-right-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-top-right-radius: \t\t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-bl {\n\t-moz-border-radius-bottomleft: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-bottom-left-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-bottom-left-radius: \t\t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-br {\n\t-moz-border-radius-bottomright: \t1em /*{global-radii-buttons}*/;\n\t-webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/;\n\tborder-bottom-right-radius: \t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-top {\n\t-moz-border-radius-topleft: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-top-left-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-top-left-radius: \t\t\t1em /*{global-radii-buttons}*/;\n\t-moz-border-radius-topright: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-top-right-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-top-right-radius: \t\t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-bottom {\n\t-moz-border-radius-bottomleft: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-bottom-left-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-bottom-left-radius: \t\t\t1em /*{global-radii-buttons}*/;\n\t-moz-border-radius-bottomright: \t1em /*{global-radii-buttons}*/;\n\t-webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/;\n\tborder-bottom-right-radius: \t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-right {\n\t -moz-border-radius-topright: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-top-right-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-top-right-radius: \t\t\t1em /*{global-radii-buttons}*/;\n\t-moz-border-radius-bottomright: \t1em /*{global-radii-buttons}*/;\n\t-webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/;\n\tborder-bottom-right-radius: \t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-left {\n\t-moz-border-radius-topleft: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-top-left-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-top-left-radius: \t\t\t1em /*{global-radii-buttons}*/;\n\t-moz-border-radius-bottomleft: \t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-bottom-left-radius: \t1em /*{global-radii-buttons}*/;\n\tborder-bottom-left-radius: \t\t\t1em /*{global-radii-buttons}*/;\n}\n.ui-btn-corner-all {\n\t-moz-border-radius: \t\t\t\t1em /*{global-radii-buttons}*/;\n\t-webkit-border-radius: \t\t\t\t1em /*{global-radii-buttons}*/;\n\tborder-radius: \t\t\t\t\t\t1em /*{global-radii-buttons}*/;\n}\n/* radius clip workaround for cleaning up corner trapping */\n.ui-corner-tl,\n.ui-corner-tr,\n.ui-corner-bl, \n.ui-corner-br,\n.ui-corner-top,\n.ui-corner-bottom, \n.ui-corner-right,\n.ui-corner-left,\n.ui-corner-all,\n.ui-btn-corner-tl,\n.ui-btn-corner-tr,\n.ui-btn-corner-bl, \n.ui-btn-corner-br,\n.ui-btn-corner-top,\n.ui-btn-corner-bottom, \n.ui-btn-corner-right,\n.ui-btn-corner-left,\n.ui-btn-corner-all {\n  -webkit-background-clip: padding-box;\n     -moz-background-clip: padding;\n          background-clip: padding-box;\n}\n/* Overlay / modal\n-----------------------------------------------------------------------------------------------------------*/\n.ui-overlay {\n\tbackground: #666;\n\topacity: .5;\n\tfilter: Alpha(Opacity=50);\n\tposition: absolute;\n\twidth: 100%;\n\theight: 100%;\n}\n.ui-overlay-shadow {\n\t-moz-box-shadow: 0px 0px 12px \t\t\trgba(0,0,0,.6);\n\t-webkit-box-shadow: 0px 0px 12px \t\trgba(0,0,0,.6);\n\tbox-shadow: 0px 0px 12px \t\t\t\trgba(0,0,0,.6);\n}\n.ui-shadow {\n\t-moz-box-shadow: 0px 1px 4px /*{global-box-shadow-size}*/ \t\t\trgba(0,0,0,.3) /*{global-box-shadow-color}*/;\n\t-webkit-box-shadow: 0px 1px 4px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.3) /*{global-box-shadow-color}*/;\n\tbox-shadow: 0px 1px 4px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.3) /*{global-box-shadow-color}*/;\n}\n.ui-bar-a .ui-shadow,\n.ui-bar-b .ui-shadow ,\n.ui-bar-c .ui-shadow  {\n\t-moz-box-shadow: 0px 1px 0 \t\t\t\trgba(255,255,255,.3);\n\t-webkit-box-shadow: 0px 1px 0 \t\t\trgba(255,255,255,.3);\n\tbox-shadow: 0px 1px 0 \t\t\t\t\trgba(255,255,255,.3);\n}\n.ui-shadow-inset {\n\t-moz-box-shadow: inset 0px 1px 4px \t\trgba(0,0,0,.2);\n\t-webkit-box-shadow: inset 0px 1px 4px \trgba(0,0,0,.2);\n\tbox-shadow: inset 0px 1px 4px \t\t\trgba(0,0,0,.2);\n}\n.ui-icon-shadow {\n\t-moz-box-shadow: 0px 1px 0 \t\t\t\trgba(255,255,255,.4) /*{global-icon-shadow}*/;\n\t-webkit-box-shadow: 0px 1px 0 \t\t\trgba(255,255,255,.4) /*{global-icon-shadow}*/;\n\tbox-shadow: 0px 1px 0 \t\t\t\t\trgba(255,255,255,.4) /*{global-icon-shadow}*/;\n}\n/* Focus state - set here for specificity (note: these classes are added by JavaScript)\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn:focus {\n\toutline: 0;\n}\n.ui-focus,\n.ui-btn:focus {\n\t-moz-box-shadow: 0px 0px 12px \t\t#387bbe /*{global-active-background-color}*/;\n\t-webkit-box-shadow: 0px 0px 12px \t#387bbe /*{global-active-background-color}*/;\n\tbox-shadow: 0px 0px 12px \t\t\t#387bbe /*{global-active-background-color}*/;\n}\n/* unset box shadow in browsers that don't do it right\n-----------------------------------------------------------------------------------------------------------*/\n.ui-mobile-nosupport-boxshadow * {\n\t-moz-box-shadow: none !important;\n\t-webkit-box-shadow: none !important;\n\tbox-shadow: none !important;\n}\n/* ...and bring back focus */\n.ui-mobile-nosupport-boxshadow .ui-focus,\n.ui-mobile-nosupport-boxshadow .ui-btn:focus {\n\toutline-width: 1px;\n\toutline-style: dotted;\n}\n/* some unsets - more probably needed */\n.ui-mobile, .ui-mobile body { height: 99.9%; }\n.ui-mobile fieldset, .ui-page { padding: 0; margin: 0; }\n.ui-mobile a img, .ui-mobile fieldset { border-width: 0; }\n/* responsive page widths */\n.ui-mobile-viewport {  margin: 0; overflow-x: visible; -webkit-text-size-adjust: none; -ms-text-size-adjust:none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }\n/* Issue #2066 */\nbody.ui-mobile-viewport,\ndiv.ui-mobile-viewport { overflow-x: hidden; }\n/* \"page\" containers - full-screen views, one should always be in view post-pageload */\n.ui-mobile [data-role=page], .ui-mobile [data-role=dialog], .ui-page { top: 0; left: 0; width: 100%; min-height: 100%; position: absolute; display: none; border: 0; }\n.ui-mobile .ui-page-active { display: block; overflow: visible; }\n/* on ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n.ui-page { outline: none; }\n/*orientations from js are available */\n@media screen and (orientation: portrait){\n.ui-mobile, .ui-mobile .ui-page { min-height: 420px; }\n}\n@media screen and (orientation: landscape){\n.ui-mobile, .ui-mobile .ui-page { min-height: 300px; }\n}\n/* loading screen */\n.ui-loading .ui-loader { display: block; }\n.ui-loader { display: none; z-index: 9999999; position: fixed; top: 50%; box-shadow: 0 1px 1px -1px #fff; left: 50%; border:0; }\n.ui-loader-default { background: none; opacity: .18; width: 46px; height: 46px; margin-left: -23px; margin-top: -23px; }\n.ui-loader-verbose { width: 200px; opacity: .88; height: auto; margin-left: -110px; margin-top: -43px; padding: 10px; }\n.ui-loader-default h1 { font-size: 0; width: 0; height: 0; overflow: hidden; }\n.ui-loader-verbose h1 { font-size: 16px; margin: 0; text-align: center; }\n.ui-loader .ui-icon { background-color: #000; display: block; margin: 0; width: 44px; height: 44px; padding: 1px; -webkit-border-radius: 36px; -moz-border-radius: 36px; border-radius: 36px; }\n.ui-loader-verbose .ui-icon { margin: 0 auto 10px; opacity: .75; }\n.ui-loader-textonly { padding: 15px; margin-left: -115px;  }\n.ui-loader-textonly .ui-icon { display: none; }\n.ui-loader-fakefix { position: absolute; }\n/*fouc*/\n.ui-mobile-rendering > * { visibility: hidden; }\n/*headers, content panels*/\n.ui-bar, .ui-body { position: relative; padding: .4em 15px;  overflow: hidden; display: block;  clear:both;  }\n.ui-bar { font-size: 16px; margin: 0; }\n.ui-bar h1, .ui-bar h2, .ui-bar h3, .ui-bar h4, .ui-bar h5, .ui-bar h6 { margin: 0; padding: 0; font-size: 16px; display: inline-block; }\n.ui-header, .ui-footer { position: relative; border-left-width: 0; border-right-width: 0; }\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right,\n.ui-footer .ui-btn-left,\n.ui-footer .ui-btn-right { position: absolute; top: 3px; }\n.ui-header .ui-btn-left,\n.ui-footer .ui-btn-left { left: 5px; }\n.ui-header .ui-btn-right,\n.ui-footer .ui-btn-right { right: 5px; }\n.ui-footer .ui-btn-icon-notext,\n.ui-header .ui-btn-icon-notext { top: 6px; }\n.ui-header .ui-title, .ui-footer .ui-title { min-height: 1.1em; text-align: center; font-size: 16px; display: block; margin: .6em 30% .8em;  padding: 0;  text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; }\n.ui-footer .ui-title { margin: .6em 15px .8em;  }\n/*content area*/\n.ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; }\n/* icons sizing */\n.ui-icon { width: 18px; height: 18px; }\n/* non-js content hiding */\n.ui-nojs { position: absolute; left: -9999px; }\n/* accessible content hiding */\n.ui-hide-label label,\n.ui-hidden-accessible { position: absolute !important; left: -9999px; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }\n/* Transitions originally inspired by those from jQtouch, nice work, folks */\n.ui-mobile-viewport-transitioning,\n.ui-mobile-viewport-transitioning .ui-page {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n}\n.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n}\n.out {\n\t-webkit-animation-timing-function: ease-in;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-timing-function: ease-in;\n\t-moz-animation-duration: 225;\n}\n@-webkit-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-moz-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-webkit-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@-moz-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n.fade.out {\n\topacity: 0;\n\t-webkit-animation-duration: 125ms;\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-duration: 125ms;\n\t-moz-animation-name: fadeout;\n}\n.fade.in {\n\topacity: 1;\n\t-webkit-animation-duration: 225ms;\n\t-webkit-animation-name: fadein;\n\t-moz-animation-duration: 225ms;\n\t-moz-animation-name: fadein;\n}\n.pop {\n\t-webkit-transform-origin: 50% 50%;\n\t-moz-transform-origin: 50% 50%;\n}\n.pop.in {\n\t-webkit-transform: scale(1);\n\t-moz-transform: scale(1);\n    opacity: 1;\n\t-webkit-animation-name: popin;\n\t-moz-animation-name: popin;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-duration: 350ms;\n}\n.pop.out {\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-name: fadeout;\n\topacity: 0;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-duration: 100ms;\n}\n.pop.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n}\n.pop.out.reverse {\n\t-webkit-transform: scale(.8);\n\t-moz-transform: scale(.8);\n\t-webkit-animation-name: popout;\n\t-moz-animation-name: popout;\n}\n@-webkit-keyframes popin {\n    from {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-moz-keyframes popin {\n    from {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-webkit-keyframes popout {\n    from {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@-moz-keyframes popout {\n    from {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n}\n/* keyframes for slidein from sides */\n@-webkit-keyframes slideinfromright {\n    from { -webkit-transform: translateX(100%); }\n    to { -webkit-transform: translateX(0); }\n}\n@-moz-keyframes slideinfromright {\n    from { -moz-transform: translateX(100%); }\n    to { -moz-transform: translateX(0); }\n}\n@-webkit-keyframes slideinfromleft {\n    from { -webkit-transform: translateX(-100%); }\n    to { -webkit-transform: translateX(0); }\n}\n@-moz-keyframes slideinfromleft {\n    from { -moz-transform: translateX(-100%); }\n    to { -moz-transform: translateX(0); }\n}\n/* keyframes for slideout to sides */\n@-webkit-keyframes slideouttoleft {\n    from { -webkit-transform: translateX(0); }\n    to { -webkit-transform: translateX(-100%); }\n}\n@-moz-keyframes slideouttoleft {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(-100%); }\n}\n@-webkit-keyframes slideouttoright {\n    from { -webkit-transform: translateX(0); }\n    to { -webkit-transform: translateX(100%); }\n}\n@-moz-keyframes slideouttoright {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(100%); }\n}\n.slide.out, .slide.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n}\n.slide.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n}\n.slide.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: slideinfromright;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromright;\n}\n.slide.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n}\n.slide.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: slideinfromleft;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromleft;\n}\n.slidefade.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-duration: 225ms;\n}\n.slidefade.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-animation-duration: 200ms;\n}\n.slidefade.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\t-webkit-animation-duration: 200ms;\n\t-moz-animation-duration: 200ms;\n}\n.slidefade.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-animation-duration: 200ms;\n}\n/* slide down */\n.slidedown.out {\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-duration: 100ms;\n}\n.slidedown.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfromtop;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfromtop;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-duration: 250ms;\n}\n.slidedown.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-duration: 150ms;\n}\n.slidedown.out.reverse {\n\t-webkit-transform: translateY(-100%);\n\t-moz-transform: translateY(-100%);\n\t-webkit-animation-name: slideouttotop;\n\t-moz-animation-name: slideouttotop;\n\t-webkit-animation-duration: 200ms;\n\t-moz-animation-duration: 200ms;\n}\n@-webkit-keyframes slideinfromtop {\n    from { -webkit-transform: translateY(-100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfromtop {\n    from { -moz-transform: translateY(-100%); }\n    to { -moz-transform: translateY(0); }\n}\n@-webkit-keyframes slideouttotop {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(-100%); }\n}\n@-moz-keyframes slideouttotop {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(-100%); }\n}\n/* slide up */\n.slideup.out {\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-duration: 100ms;\n}\n.slideup.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfrombottom;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfrombottom;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-duration: 250ms;\n}\n.slideup.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-duration: 150ms;\n}\n.slideup.out.reverse {\n\t-webkit-transform: translateY(100%);\n\t-moz-transform: translateY(100%);\n\t-webkit-animation-name: slideouttobottom;\n\t-moz-animation-name: slideouttobottom;\n\t-webkit-animation-duration: 200ms;\n\t-moz-animation-duration: 200ms;\n}\n@-webkit-keyframes slideinfrombottom {\n    from { -webkit-transform: translateY(100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfrombottom {\n    from { -moz-transform: translateY(100%); }\n    to { -moz-transform: translateY(0); }\n}\n@-webkit-keyframes slideouttobottom {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(100%); }\n}\n@-moz-keyframes slideouttobottom {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(100%); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-flip {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tposition: absolute;\n}\n.flip {\n\t-webkit-backface-visibility:hidden;\n\t-webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-backface-visibility:hidden;\n\t-moz-transform:translateX(0);\n}\n.flip.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 175ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 175ms;\n}\n.flip.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 225ms;\n}\n.flip.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n}\n.flip.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-turn {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tposition: absolute;\n}\n.turn {\n\t-webkit-backface-visibility:hidden;\n\t-webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-webkit-transform-origin: 0;\n\t\n\t-moz-backface-visibility:hidden;\n\t-moz-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-transform-origin: 0;\n}\n.turn.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 125ms;\n\t-moz-animation-duration: 125ms;\n}\n.turn.in {\n\t-webkit-animation-name: flipintoright;\n\t-moz-animation-name: flipintoright;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-duration: 250ms;\n\t\n}\n.turn.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n}\n.turn.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n/* flow transition */\n.flow {\n\t-webkit-transform-origin: 50% 30%;\n\t-moz-transform-origin: 50% 30%;\t\n\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n}\n.ui-dialog.flow {\n\t-webkit-transform-origin: none;\n\t-moz-transform-origin: none;\t\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n}\n.flow.out {\n\t-webkit-transform: translateX(-100%) scale(.7);\n\t-webkit-animation-name: flowouttoleft;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(-100%) scale(.7);\n\t-moz-animation-name: flowouttoleft;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n}\n.flow.in {\n\t-webkit-transform: translateX(0) scale(1);\n\t-webkit-animation-name: flowinfromright;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(0) scale(1);\n\t-moz-animation-name: flowinfromright;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n}\n.flow.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: flowouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: flowouttoright;\n}\n.flow.in.reverse {\n\t-webkit-animation-name: flowinfromleft;\n\t-moz-animation-name: flowinfromleft;\n}\n@-webkit-keyframes flowouttoleft {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(-100%) scale(.7); }\n}\n@-moz-keyframes flowouttoleft {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(-100%) scale(.7); }\n}\n@-webkit-keyframes flowouttoright {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform:  translateX(100%) scale(.7); }\n}\n@-moz-keyframes flowouttoright {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(100%) scale(.7); }\n}\n@-webkit-keyframes flowinfromleft {\n    0% { -webkit-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromleft {\n    0% { -moz-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@-webkit-keyframes flowinfromright {\n    0% { -webkit-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromright {\n    0% { -moz-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n/* content configurations. */\n.ui-grid-a, .ui-grid-b, .ui-grid-c, .ui-grid-d { overflow: hidden; }\n.ui-block-a, .ui-block-b, .ui-block-c, .ui-block-d, .ui-block-e { margin: 0; padding: 0; border: 0; float: left; min-height:1px;}\n/* grid solo: 100 - single item fallback */\n.ui-grid-solo .ui-block-a { width: 100%; float: none; }\n/* grid a: 50/50 */\n.ui-grid-a .ui-block-a, .ui-grid-a .ui-block-b { width: 50%; }\n.ui-grid-a .ui-block-a { clear: left; }\n/* grid b: 33/33/33 */\n.ui-grid-b .ui-block-a, .ui-grid-b .ui-block-b, .ui-grid-b .ui-block-c { width: 33.333%; }\n.ui-grid-b .ui-block-a { clear: left; }\n/* grid c: 25/25/25/25 */\n.ui-grid-c .ui-block-a, .ui-grid-c .ui-block-b, .ui-grid-c .ui-block-c, .ui-grid-c .ui-block-d { width: 25%; }\n.ui-grid-c .ui-block-a { clear: left; }\n/* grid d: 20/20/20/20/20 */\n.ui-grid-d .ui-block-a, .ui-grid-d .ui-block-b, .ui-grid-d .ui-block-c, .ui-grid-d .ui-block-d, .ui-grid-d .ui-block-e { width: 20%; }\n.ui-grid-d .ui-block-a { clear: left; }\n/* fixed page header & footer configuration */\n.ui-header-fixed,\n.ui-footer-fixed {\n\tleft: 0;\n\tright: 0;\n\twidth: 100%;\n\tposition: fixed;\n\tz-index: 1000;\n}\n.ui-header-fixed {\n\ttop: 0;\n}\n.ui-footer-fixed {\n\tbottom: 0;\n}\n.ui-header-fullscreen,\n.ui-footer-fullscreen {\n\topacity: .9;\n}\n.ui-page-header-fixed {\n\tpadding-top: 2.5em;\n}\n.ui-page-footer-fixed {\n\tpadding-bottom: 3em;\n}\n.ui-page-header-fullscreen .ui-content,\n.ui-page-footer-fullscreen .ui-content {\n\tpadding: 0;\n}\n.ui-fixed-hidden {\n\tposition: absolute;\n}\n.ui-page-header-fullscreen .ui-fixed-hidden,\n.ui-page-footer-fullscreen .ui-fixed-hidden {\n\tleft: -99999em;\n}\n.ui-header-fixed .ui-btn,\n.ui-footer-fixed .ui-btn { \n\tz-index: 10;\n}\n.ui-navbar { overflow: hidden;  }\n.ui-navbar ul, .ui-navbar-expanded ul { list-style:none; padding: 0; margin: 0; position: relative; display: block; border: 0;}\n.ui-navbar-collapsed ul { float: left; width: 75%; margin-right: -2px; }\n.ui-navbar-collapsed .ui-navbar-toggle { float: left; width: 25%; }\n.ui-navbar li.ui-navbar-truncate { position: absolute; left: -9999px; top: -9999px; }\n.ui-navbar li .ui-btn, .ui-navbar .ui-navbar-toggle .ui-btn { display: block; font-size: 12px; text-align: center; margin: 0; border-right-width: 0; max-width: 100%; }\n.ui-navbar li .ui-btn {  margin-right: -1px; }\n.ui-navbar li .ui-btn:last-child { margin-right: 0; }\n.ui-header .ui-navbar li .ui-btn, .ui-header .ui-navbar .ui-navbar-toggle .ui-btn,\n.ui-footer .ui-navbar li .ui-btn, .ui-footer .ui-navbar .ui-navbar-toggle .ui-btn { border-top-width: 0; border-bottom-width: 0; }\n.ui-navbar .ui-btn-inner { padding-left: 2px; padding-right: 2px; }\n.ui-navbar-noicons li .ui-btn .ui-btn-inner, .ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner { padding-top: .8em; padding-bottom: .9em; }\n/*expanded page styles*/\n.ui-navbar-expanded .ui-btn { margin: 0; font-size: 14px; }\n.ui-navbar-expanded .ui-btn-inner { padding-left: 5px; padding-right: 5px;  }\n.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner { padding: 45px 5px 15px; text-align: center; }\n.ui-navbar-expanded .ui-btn-icon-top .ui-icon { top: 15px; }\n.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner { padding: 15px 5px 45px; text-align: center; }\n.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon { bottom: 15px; }\n.ui-navbar-expanded li .ui-btn .ui-btn-inner { min-height: 2.5em; }\n.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner { padding-top: 1.8em; padding-bottom: 1.9em; }\n.ui-btn { display: block; text-align: center; cursor:pointer;  position: relative; margin: .5em 5px; padding: 0; }\n.ui-mini { margin: .25em 5px; }\n.ui-btn-inner { padding: .6em 20px; min-width: .75em; display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; zoom: 1; }\n.ui-btn input, .ui-btn button { z-index: 2; }\n.ui-btn-left, .ui-btn-right, .ui-btn-inline { display: inline-block; }\n.ui-btn-block { display: block; }\n.ui-header .ui-btn,\n.ui-footer .ui-btn { display: inline-block; margin: 0; }\n.ui-header .ui-btn-inner,\n.ui-footer .ui-btn-inner,\n.ui-mini .ui-btn-inner { font-size: 12.5px; padding: .55em 11px .5em; }\n.ui-header .ui-fullsize .ui-btn-inner,\n.ui-footer .ui-fullsize .ui-btn-inner { font-size: 16px; padding: .6em 25px; }\n.ui-btn-icon-notext { width: 24px; height: 24px; }\n.ui-btn-icon-notext .ui-btn-inner { padding: 0; height: 100%; }\n.ui-btn-icon-notext .ui-btn-inner .ui-icon { margin: 2px 1px 2px 3px; }\n.ui-btn-text { position: relative; z-index: 1; width: 100%; }\n.ui-btn-icon-notext .ui-btn-text { position: absolute; left: -9999px; }\n.ui-btn-icon-left .ui-btn-inner { padding-left: 40px; }\n.ui-btn-icon-right .ui-btn-inner { padding-right: 40px; }\n.ui-btn-icon-top .ui-btn-inner { padding-top: 40px; }\n.ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 40px; }\n.ui-header .ui-btn-icon-left .ui-btn-inner,\n.ui-footer .ui-btn-icon-left .ui-btn-inner,\n.ui-mini .ui-btn-icon-left .ui-btn-inner { padding-left: 30px; }\n.ui-header .ui-btn-icon-right .ui-btn-inner,\n.ui-footer .ui-btn-icon-right .ui-btn-inner,\n.ui-mini .ui-btn-icon-right .ui-btn-inner { padding-right: 30px; }\n.ui-header .ui-btn-icon-top .ui-btn-inner,\n.ui-footer .ui-btn-icon-top .ui-btn-inner,\n.ui-mini .ui-btn-icon-top .ui-btn-inner { padding: 30px 3px .5em 3px; }\n.ui-header .ui-btn-icon-bottom .ui-btn-inner,\n.ui-footer .ui-btn-icon-bottom .ui-btn-inner,\n.ui-mini .ui-btn-icon-bottom .ui-btn-inner { padding: .55em 3px 30px 3px; }\n/*btn icon positioning*/\n.ui-btn-icon-notext .ui-icon { display: block; z-index: 0;}\n.ui-btn-icon-left .ui-btn-inner .ui-icon, .ui-btn-icon-right .ui-btn-inner .ui-icon { position: absolute; top: 50%; margin-top: -9px; }\n.ui-btn-icon-top .ui-btn-inner .ui-icon, .ui-btn-icon-bottom .ui-btn-inner .ui-icon { position: absolute; left: 50%;  margin-left: -9px; }\n.ui-btn-icon-left .ui-icon { left: 10px; }\n.ui-btn-icon-right .ui-icon { right: 10px; }\n.ui-btn-icon-top .ui-icon { top: 10px; }\n.ui-btn-icon-bottom .ui-icon { top: auto; bottom: 10px; }\n.ui-header .ui-btn-icon-left .ui-icon,\n.ui-footer .ui-btn-icon-left .ui-icon,\n.ui-mini.ui-btn-icon-left .ui-icon,\n.ui-mini .ui-btn-icon-left .ui-icon { left: 5px; }\n.ui-header .ui-btn-icon-right .ui-icon,\n.ui-footer .ui-btn-icon-right .ui-icon,\n.ui-mini.ui-btn-icon-right .ui-icon,\n.ui-mini .ui-btn-icon-right .ui-icon { right: 5px; }\n.ui-header .ui-btn-icon-top .ui-icon,\n.ui-footer .ui-btn-icon-top .ui-icon,\n.ui-mini.ui-btn-icon-top .ui-icon,\n.ui-mini .ui-btn-icon-top .ui-icon { top: 5px; }\n.ui-header .ui-btn-icon-bottom .ui-icon,\n.ui-footer .ui-btn-icon-bottom .ui-icon,\n.ui-mini.ui-btn-icon-bottom .ui-icon,\n.ui-mini .ui-btn-icon-bottom .ui-icon { bottom: 5px; }\n/*hiding native button,inputs */\n.ui-btn-hidden { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: button; opacity: .1; cursor: pointer; background: #fff; background: rgba(255,255,255,0); filter: Alpha(Opacity=.0001); font-size: 1px; border: none; text-indent: -9999px; }\n.ui-collapsible { margin: .5em 0; }\n.ui-collapsible-heading { font-size: 16px; display: block; margin: 0 -8px; padding: 0; border-width: 0 0 1px 0; position: relative; }\n.ui-collapsible-heading a { text-align: left; margin: 0;  }\n.ui-collapsible-heading .ui-btn-inner,\n.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner { padding-left: 40px; }\n.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner { padding-left: 12px; padding-right: 40px; }\n.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,\n.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner { padding-right: 40px; text-align: center; }\n.ui-collapsible-heading a span.ui-btn { position: absolute; left: 6px; top: 50%; margin: -12px 0 0 0; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; }\n.ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 10px 0; }\n.ui-collapsible-heading a span.ui-btn .ui-icon { left: 0; margin-top: -10px; }\n.ui-collapsible-heading-status { position: absolute; top: -9999px; left:0px; }\n.ui-collapsible-content {\n\tdisplay: block;\n\tmargin:  0 -8px;\n\tpadding: 10px 16px;\n\tborder-top:  none;      /* Overrides ui-btn-up-* */\n\tbackground-image: none; /* Overrides ui-btn-up-* */\n\tfont-weight: normal;    /* Overrides ui-btn-up-* */\n}\n.ui-collapsible-content-collapsed { display: none; }\n.ui-collapsible-set { margin: .5em 0; }\n.ui-collapsible-set .ui-collapsible { margin: -1px 0 0; }\n.ui-controlgroup, fieldset.ui-controlgroup { padding: 0; margin: 0em 0 .5em; zoom: 1; }\n.ui-bar .ui-controlgroup { margin: 0 .3em; }\n.ui-controlgroup-label { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .4em; }\n.ui-controlgroup-controls { display: block; width: 100%;}\n.ui-controlgroup li { list-style: none; }\n.ui-controlgroup-vertical .ui-btn,\n.ui-controlgroup-vertical .ui-checkbox, .ui-controlgroup-vertical .ui-radio { margin: 0; border-bottom-width: 0;  }\n.ui-controlgroup-controls label.ui-select { position: absolute; left: -9999px; }\n.ui-controlgroup-vertical .ui-controlgroup-last { border-bottom-width: 1px; }\n.ui-controlgroup-horizontal { padding: 0; }\n.ui-controlgroup-horizontal .ui-btn-inner { text-align:center; }\n.ui-controlgroup-horizontal .ui-btn, .ui-controlgroup-horizontal .ui-select { display: inline-block; margin: 0 -6px 0 0; }\n.ui-controlgroup-horizontal .ui-checkbox, .ui-controlgroup-horizontal .ui-radio { float: left; clear: none; margin: 0 -1px 0 0; }\n.ui-controlgroup-horizontal .ui-checkbox .ui-btn, .ui-controlgroup-horizontal .ui-radio .ui-btn,\n.ui-controlgroup-horizontal .ui-checkbox:last-child, .ui-controlgroup-horizontal .ui-radio:last-child { margin-right: 0; }\n.ui-controlgroup-horizontal .ui-controlgroup-last { margin-right: 0; }\n.ui-controlgroup .ui-checkbox label, .ui-controlgroup .ui-radio label { font-size: 16px;  }\n/* conflicts with listview..\n.ui-controlgroup .ui-btn-icon-notext { width: 30px; height: 30px; text-indent: -9999px; }\n.ui-controlgroup .ui-btn-icon-notext .ui-btn-inner {  padding: 5px 6px 5px 5px; }\n*/\n@media all and (min-width: 450px){\n\t.ui-field-contain .ui-controlgroup-label { vertical-align: top; display: inline-block;  width: 20%;  margin: 0 2% 0 0;  }\n\t.ui-field-contain .ui-controlgroup-controls { width: 60%; display: inline-block; }\n\t.ui-field-contain .ui-controlgroup .ui-select { width: 100%; } \n\t.ui-field-contain .ui-controlgroup-horizontal .ui-select { width: auto; }\n}\t\n.ui-dialog {\n\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n}\n.ui-dialog-contain { width: 92.5%; max-width: 500px; margin: 10% auto 15px auto; padding: 0; }\n.ui-dialog .ui-header {\n\tmargin-top: 15%;\n\tborder: none;\n\toverflow: hidden;\n}\n.ui-dialog .ui-header, \n.ui-dialog .ui-content, \n.ui-dialog .ui-footer { \n\tdisplay: block;\n\tposition: relative; \n\twidth: auto;\n}\n.ui-dialog .ui-header, \n.ui-dialog .ui-footer  { \n\tz-index: 10; \n\tpadding: 0;\n}\n.ui-dialog .ui-footer {\n\tpadding: 0 15px; \n}\n.ui-dialog .ui-content { \n\tpadding: 15px; \n}\n.ui-dialog { \n\tmargin-top: -15px;  \n}\n.ui-checkbox, .ui-radio { position: relative; clear: both; margin: .2em 0 .5em; z-index: 1;  }\n.ui-checkbox .ui-btn, .ui-radio .ui-btn { margin: 0; text-align: left; z-index: 2; }\n.ui-checkbox .ui-btn-inner, .ui-radio .ui-btn-inner { white-space: normal; }\n.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner { padding-left: 45px; }\n.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner { padding-left: 36px; }\n.ui-checkbox .ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; }\n.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner { padding-right: 36px; }\n.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner { padding-right: 0; padding-left: 0; text-align: center; }\n.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner, .ui-radio .ui-btn-icon-bottom .ui-btn-inner { padding-right: 0; padding-left: 0; text-align: center; }\n.ui-checkbox .ui-icon, .ui-radio .ui-icon { top: 1.1em; }\n.ui-checkbox .ui-btn-icon-left .ui-icon, .ui-radio .ui-btn-icon-left .ui-icon { left: 15px; }\n.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon, .ui-radio .ui-mini.ui-btn-icon-left .ui-icon { left: 9px; }\n.ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon { right: 15px; }\n.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon, .ui-radio .ui-mini.ui-btn-icon-right .ui-icon { right: 9px; }\n.ui-checkbox .ui-btn-icon-top .ui-icon, .ui-radio .ui-btn-icon-top .ui-icon { top: 10px; }\n.ui-checkbox .ui-btn-icon-bottom .ui-icon, .ui-radio .ui-btn-icon-bottom .ui-icon { top: auto; bottom: 10px; }\n.ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon { right: 15px; }\n.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon, .ui-radio .ui-mini.ui-btn-icon-right .ui-icon { right: 9px; }\n/* input, label positioning */\n.ui-checkbox input,.ui-radio input { position:absolute; left:20px; top:50%; width: 10px; height: 10px;  margin:-5px 0 0 0; outline: 0 !important; z-index: 1; }\n.ui-field-contain, fieldset.ui-field-contain { padding: .8em 0; margin: 0; border-width: 0 0 1px 0; overflow: visible; }\n.ui-field-contain:first-child { border-top-width: 0; }\n.ui-header .ui-field-contain-left,\n.ui-header .ui-field-contain-right {\n\tposition: absolute;\n\ttop: 0;\n\twidth: 25%;\n}\n.ui-header .ui-field-contain-left {\n\tleft: 1em;\n}\n.ui-header .ui-field-contain-right {\n\tright: 1em;\n}\n@media all and (min-width: 450px){\n\t.ui-field-contain, .ui-mobile fieldset.ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; }\n}\n.ui-select { display: block; position: relative; }\n.ui-select select { position: absolute; left: -9999px; top: -9999px; }\n.ui-select .ui-btn { overflow: hidden; opacity: 1; margin: 0; }\n/* Fixes #2588 — When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select—including “inherit”—without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n.ui-select .ui-btn select { cursor: pointer; -webkit-appearance: button; left: 0; top:0; width: 100%;  min-height: 1.5em; min-height: 100%; height: 3em; max-height: 100%; opacity: 0; -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\"; filter: alpha(opacity=0); z-index: 2; }\n.ui-select .ui-disabled { opacity: .3; }\n@-moz-document url-prefix() {.ui-select .ui-btn select { opacity: 0.0001; }}\n.ui-select .ui-btn select.ui-select-nativeonly { opacity: 1; text-indent: 0; }\n.ui-select .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } \n.ui-select .ui-btn-icon-right .ui-icon { right: 15px;  }\n.ui-select .ui-mini.ui-btn-icon-right .ui-icon { right: 7px;  }\n/* labels */\nlabel.ui-select { font-size: 16px; line-height: 1.4;  font-weight: normal; margin: 0 0 .3em; display: block; }\n/*listbox*/\n.ui-select .ui-btn-text, .ui-selectmenu .ui-btn-text { display: block; min-height: 1em; overflow: hidden !important;\n/* This !important is required for iPad Safari specifically. See https://github.com/jquery/jquery-mobile/issues/2647 */ }\n.ui-select .ui-btn-text { text-overflow: ellipsis; }\n.ui-selectmenu { position: absolute; padding: 0; z-index: 1100 !important; width: 80%; max-width: 350px; padding: 6px; }\n.ui-selectmenu .ui-listview { margin: 0; }\n.ui-selectmenu .ui-btn.ui-li-divider { cursor: default; }\n.ui-selectmenu-hidden { top: -9999px; left: -9999px; }\n.ui-selectmenu-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%;  z-index: 99; }\n.ui-screen-hidden, .ui-selectmenu-list .ui-li .ui-icon { display: none; }\n.ui-selectmenu-list .ui-li .ui-icon { display: block; }\n.ui-li.ui-selectmenu-placeholder { display: none; }\n.ui-selectmenu .ui-header .ui-title { margin: 0.6em 46px 0.8em; }\n@media all and (min-width: 450px){\t\n\t.ui-field-contain label.ui-select { vertical-align: top;  display: inline-block;  width: 20%;  margin: 0 2% 0 0; }\n\t.ui-field-contain .ui-select { width: 60%; display: inline-block; }\n}\t\n/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button.  this shim's content in there */\n.ui-selectmenu .ui-header h1:after { content: '.'; visibility: hidden; }\nlabel.ui-input-text { font-size: 16px; line-height: 1.4; display: block; font-weight: normal; margin: 0 0 .3em; }\ninput.ui-input-text, textarea.ui-input-text { background-image: none; padding: .4em; line-height: 1.4; font-size: 16px; display: block; width: 97%; outline: 0; }\n.ui-header input.ui-input-text,\n.ui-footer input.ui-input-text { margin-left: 1.25%; padding: .4em 1%; width: 95.5% } /* Note that padding left/right on text inputs is factored into how the element is displayed in Firefox, but does not actually pad the text inside it. */\n input.ui-input-text { -webkit-appearance: none; }\ntextarea.ui-input-text { height: 50px; -webkit-transition: height 200ms linear; -moz-transition: height 200ms linear; -o-transition: height 200ms linear; transition: height 200ms linear; }\n.ui-input-search { padding: 0 30px; background-image: none; position: relative; }\n.ui-icon-searchfield:after { position: absolute; left: 7px; top: 50%; margin-top: -9px; content: \"\"; width: 18px; height: 18px; opacity: .5; }\n.ui-input-search input.ui-input-text { border: none; width: 98%; padding: .4em 0; margin: 0; display: block; background: transparent none; outline: 0 !important; }\n.ui-input-search .ui-input-clear { position: absolute; right: 0; top: 50%; margin-top: -13px; }\n.ui-mini .ui-input-clear { right: -3px; }\n.ui-input-search .ui-input-clear-hidden { display: none; }\ninput.ui-mini, .ui-mini input, textarea.ui-mini { font-size: 14px; }\ntextarea.ui-mini { height: 45px; }\n/* orientation adjustments - incomplete!*/\n@media all and (min-width: 450px){\n\t.ui-field-contain label.ui-input-text  { vertical-align: top; display: inline-block;  width: 20%;  margin: 0 2% 0 0 }\n\t.ui-field-contain input.ui-input-text, \n\t.ui-field-contain textarea.ui-input-text, \n\t.ui-field-contain .ui-input-search { width: 60%; display: inline-block; } \n\t.ui-field-contain .ui-input-search { width: 50%; }\n\t.ui-hide-label input.ui-input-text, \n\t.ui-hide-label textarea.ui-input-text, \n\t.ui-hide-label .ui-input-search { padding: .4em; width: 97%; } \n\t.ui-input-search input.ui-input-text { width: 98%; /*echos rule from above*/ }\n}\n.ui-listview { margin: 0; counter-reset: listnumbering; }\n.ui-content .ui-listview { margin: -15px; }\n.ui-content .ui-listview-inset { margin: 1em 0;  }\n.ui-listview, .ui-li { list-style:none; padding:0; }\n.ui-li, .ui-li.ui-field-contain { display: block; margin:0; position: relative; overflow: visible; text-align: left; border-width: 0; border-top-width: 1px; }\n.ui-li .ui-btn-text a.ui-link-inherit { text-overflow: ellipsis; overflow: hidden; white-space: nowrap;  }\n.ui-li-divider, .ui-li-static { padding: .5em 15px; font-size: 14px; font-weight: bold;  }\n.ui-li-divider { counter-reset: listnumbering;  }\nol.ui-listview .ui-link-inherit:before, ol.ui-listview .ui-li-static:before, .ui-li-dec { font-size: .8em; display: inline-block; padding-right: .3em; font-weight: normal;counter-increment: listnumbering; content: counter(listnumbering) \". \"; }\nol.ui-listview .ui-li-jsnumbering:before { content: \"\" !important; } /* to avoid chance of duplication */\n.ui-listview-inset .ui-li { border-right-width: 1px; border-left-width: 1px; }\n.ui-li:last-child, .ui-li.ui-field-contain:last-child { border-bottom-width: 1px; }\n.ui-li>.ui-btn-inner { display: block; position: relative; padding: 0; }\n.ui-li .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li { padding: .7em 15px .7em 15px; display: block; }\n.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-thumb  { min-height: 60px; padding-left: 100px; }\n.ui-li-has-icon .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-icon {  min-height: 20px; padding-left: 40px; }\n.ui-li-has-count .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-count { padding-right: 45px; }\n.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-arrow { padding-right: 30px; }\n.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-arrow.ui-li-has-count { padding-right: 75px; }\n.ui-li-has-count .ui-btn-text { padding-right: 15px; }\n.ui-li-heading { font-size: 16px; font-weight: bold; display: block; margin: .6em 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;  }\n.ui-li-desc {  font-size: 12px; font-weight: normal; display: block; margin: -.5em 0 .6em; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }\n.ui-li-thumb, .ui-listview .ui-li-icon { position: absolute; left: 1px; top: 0; max-height: 80px; max-width: 80px; }\n.ui-listview .ui-li-icon { max-height: 40px; max-width: 40px; left: 10px; top: .9em; }\n.ui-li-thumb, .ui-listview .ui-li-icon, .ui-li-content { float: left; margin-right: 10px; }\n.ui-li-aside { float: right; width: 50%; text-align: right; margin: .3em 0; }\n@media all and (min-width: 480px){\n\t .ui-li-aside { width: 45%; }\n}\t \n.ui-li-divider { cursor: default; }\n.ui-li-has-alt .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-alt { padding-right: 95px; }\n.ui-li-has-count .ui-li-count { position: absolute; font-size: 11px; font-weight: bold; padding: .2em .5em; top: 50%; margin-top: -.9em; right: 48px; }\n.ui-li-divider .ui-li-count, .ui-li-static .ui-li-count { right: 10px; }\n.ui-li-has-alt .ui-li-count { right: 55px; }\n.ui-li-link-alt { position: absolute; width: 40px; height: 100%; border-width: 0; border-left-width: 1px; top: 0; right: 0; margin: 0; padding: 0; z-index: 2; }\n.ui-li-link-alt .ui-btn { overflow: hidden; position: absolute; right: 8px; top: 50%; margin: -11px 0 0 0; border-bottom-width: 1px; z-index: -1;}\n.ui-li-link-alt .ui-btn-inner { padding: 0; height: 100%; position: absolute; width: 100%; top: 0; left: 0;}\n.ui-li-link-alt .ui-btn .ui-icon { right: 50%; margin-right: -9px;  }\n.ui-listview * .ui-btn-inner > .ui-btn > .ui-btn-inner { border-top: 0px; }\n.ui-listview-filter { border-width: 0; overflow: hidden; margin: -15px -15px 15px -15px }\n.ui-listview-filter .ui-input-search { margin: 5px; width: auto; display: block; }\n.ui-listview-filter-inset { margin: -15px -5px -15px -5px; background: transparent; }\n.ui-li.ui-screen-hidden{display:none;}\n/* Odd iPad positioning issue. */\n@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {\n    .ui-li .ui-btn-text { overflow:  visible; }\n}\nlabel.ui-slider { font-size: 16px; line-height: 1.4;  font-weight: normal; margin: 0 0 .3em; display: block; }\ninput.ui-slider-input,\n.ui-field-contain input.ui-slider-input { display: inline-block; width: 50px; }\nselect.ui-slider-switch { display: none; }\ndiv.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 65%; }\ndiv.ui-slider-mini { height: 12px; margin-left: 10px; }\ndiv.ui-slider-bg { border: none; height: 100%; padding-right: 8px; }\n.ui-controlgroup a.ui-slider-handle, a.ui-slider-handle { position: absolute; z-index: 1;  top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; outline: 0; }\na.ui-slider-handle .ui-btn-inner { padding: 0; height: 100%; }\ndiv.ui-slider-mini a.ui-slider-handle { height: 14px; width: 14px; margin: -8px 0 0 -7px; }\ndiv.ui-slider-mini a.ui-slider-handle .ui-btn-inner { height: 30px; width: 30px; padding: 0; margin: -9px 0 0 -9px; }\n@media all and (min-width: 450px){\n\t.ui-field-contain label.ui-slider { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; }\n\t.ui-field-contain div.ui-slider { width: 43%; }\n\t.ui-field-contain div.ui-slider-switch { width: 5.5em; }\n}\t\ndiv.ui-slider-switch { height: 32px; margin-left: 0; width: 5.8em; }\na.ui-slider-handle-snapping { -webkit-transition: left 70ms linear; -moz-transition: left 70ms linear; }\ndiv.ui-slider-switch .ui-slider-handle {  margin-top: 1px;  }\n.ui-slider-inneroffset { margin: 0 16px; position: relative; z-index: 1; }\ndiv.ui-slider-switch.ui-slider-mini { width: 5em; height: 29px; }\ndiv.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset { margin: 0 15px 0 14px; }\ndiv.ui-slider-switch.ui-slider-mini .ui-slider-handle { width: 25px; height: 25px; margin: 1px 0 0 -13px; }\ndiv.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner { height: 30px; width: 30px; padding: 0; margin: 0; }\nspan.ui-slider-label { position: absolute; text-align: center; width: 100%; overflow: hidden; font-size: 16px; top: 0; line-height: 2; min-height: 100%; border-width: 0; white-space: nowrap; }\n.ui-slider-mini span.ui-slider-label { font-size: 14px; }\nspan.ui-slider-label-a { z-index: 1; left: 0; text-indent: -1.5em; }\nspan.ui-slider-label-b { z-index: 0; right: 0; text-indent: 1.5em;}\n.ui-slider-inline { width: 120px; display: inline-block; }\n"
  },
  {
    "path": "test/perf/OpenFile-perf-files/jquery.mobile-1.1.0.js",
    "content": "/*\n* jQuery Mobile Framework 1.1.0 db342b1f315c282692791aa870455901fdb46a55\n* http://jquerymobile.com\n*\n* Copyright 2011 (c) jQuery Project\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n*/\n(function ( root, doc, factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine( [ \"jquery\" ], function ( $ ) {\n\t\t\tfactory( $, root, doc );\n\t\t\treturn $.mobile;\n\t\t});\n\t} else {\n\t\t// Browser globals\n\t\tfactory( root.jQuery, root, doc );\n\t}\n}( this, document, function ( $, window, document, undefined ) {\n\n\n// This plugin is an experiment for abstracting away the touch and mouse\n// events so that developers don't have to worry about which method of input\n// the device their document is loaded on supports.\n//\n// The idea here is to allow the developer to register listeners for the\n// basic mouse events, such as mousedown, mousemove, mouseup, and click,\n// and the plugin will take care of registering the correct listeners\n// behind the scenes to invoke the listener at the fastest possible time\n// for that device, while still retaining the order of event firing in\n// the traditional mouse environment, should multiple handlers be registered\n// on the same element for different events.\n//\n// The current version exposes the following virtual events to jQuery bind methods:\n// \"vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel\"\n\n(function( $, window, document, undefined ) {\n\nvar dataPropertyName = \"virtualMouseBindings\",\n\ttouchTargetPropertyName = \"virtualTouchID\",\n\tvirtualEventNames = \"vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel\".split( \" \" ),\n\ttouchEventProps = \"clientX clientY pageX pageY screenX screenY\".split( \" \" ),\n\tmouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],\n\tmouseEventProps = $.event.props.concat( mouseHookProps ),\n\tactiveDocHandlers = {},\n\tresetTimerID = 0,\n\tstartX = 0,\n\tstartY = 0,\n\tdidScroll = false,\n\tclickBlockList = [],\n\tblockMouseTriggers = false,\n\tblockTouchTriggers = false,\n\teventCaptureSupported = \"addEventListener\" in document,\n\t$document = $( document ),\n\tnextTouchID = 1,\n\tlastTouchID = 0;\n\n$.vmouse = {\n\tmoveDistanceThreshold: 10,\n\tclickDistanceThreshold: 10,\n\tresetTimerDuration: 1500\n};\n\nfunction getNativeEvent( event ) {\n\n\twhile ( event && typeof event.originalEvent !== \"undefined\" ) {\n\t\tevent = event.originalEvent;\n\t}\n\treturn event;\n}\n\nfunction createVirtualEvent( event, eventType ) {\n\n\tvar t = event.type,\n\t\toe, props, ne, prop, ct, touch, i, j;\n\n\tevent = $.Event(event);\n\tevent.type = eventType;\n\n\toe = event.originalEvent;\n\tprops = $.event.props;\n\n\t// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280\n\t// https://github.com/jquery/jquery-mobile/issues/3280\n\tif ( t.search( /^(mouse|click)/ ) > -1 ) {\n\t\tprops = mouseEventProps;\n\t}\n\n\t// copy original event properties over to the new event\n\t// this would happen if we could call $.event.fix instead of $.Event\n\t// but we don't have a way to force an event to be fixed multiple times\n\tif ( oe ) {\n\t\tfor ( i = props.length, prop; i; ) {\n\t\t\tprop = props[ --i ];\n\t\t\tevent[ prop ] = oe[ prop ];\n\t\t}\n\t}\n\n\t// make sure that if the mouse and click virtual events are generated\n\t// without a .which one is defined\n\tif ( t.search(/mouse(down|up)|click/) > -1 && !event.which ){\n\t\tevent.which = 1;\n\t}\n\n\tif ( t.search(/^touch/) !== -1 ) {\n\t\tne = getNativeEvent( oe );\n\t\tt = ne.touches;\n\t\tct = ne.changedTouches;\n\t\ttouch = ( t && t.length ) ? t[0] : ( (ct && ct.length) ? ct[ 0 ] : undefined );\n\n\t\tif ( touch ) {\n\t\t\tfor ( j = 0, len = touchEventProps.length; j < len; j++){\n\t\t\t\tprop = touchEventProps[ j ];\n\t\t\t\tevent[ prop ] = touch[ prop ];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn event;\n}\n\nfunction getVirtualBindingFlags( element ) {\n\n\tvar flags = {},\n\t\tb, k;\n\n\twhile ( element ) {\n\n\t\tb = $.data( element, dataPropertyName );\n\n\t\tfor (  k in b ) {\n\t\t\tif ( b[ k ] ) {\n\t\t\t\tflags[ k ] = flags.hasVirtualBinding = true;\n\t\t\t}\n\t\t}\n\t\telement = element.parentNode;\n\t}\n\treturn flags;\n}\n\nfunction getClosestElementWithVirtualBinding( element, eventType ) {\n\tvar b;\n\twhile ( element ) {\n\n\t\tb = $.data( element, dataPropertyName );\n\n\t\tif ( b && ( !eventType || b[ eventType ] ) ) {\n\t\t\treturn element;\n\t\t}\n\t\telement = element.parentNode;\n\t}\n\treturn null;\n}\n\nfunction enableTouchBindings() {\n\tblockTouchTriggers = false;\n}\n\nfunction disableTouchBindings() {\n\tblockTouchTriggers = true;\n}\n\nfunction enableMouseBindings() {\n\tlastTouchID = 0;\n\tclickBlockList.length = 0;\n\tblockMouseTriggers = false;\n\n\t// When mouse bindings are enabled, our\n\t// touch bindings are disabled.\n\tdisableTouchBindings();\n}\n\nfunction disableMouseBindings() {\n\t// When mouse bindings are disabled, our\n\t// touch bindings are enabled.\n\tenableTouchBindings();\n}\n\nfunction startResetTimer() {\n\tclearResetTimer();\n\tresetTimerID = setTimeout(function(){\n\t\tresetTimerID = 0;\n\t\tenableMouseBindings();\n\t}, $.vmouse.resetTimerDuration );\n}\n\nfunction clearResetTimer() {\n\tif ( resetTimerID ){\n\t\tclearTimeout( resetTimerID );\n\t\tresetTimerID = 0;\n\t}\n}\n\nfunction triggerVirtualEvent( eventType, event, flags ) {\n\tvar ve;\n\n\tif ( ( flags && flags[ eventType ] ) ||\n\t\t\t\t( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {\n\n\t\tve = createVirtualEvent( event, eventType );\n\n\t\t$( event.target).trigger( ve );\n\t}\n\n\treturn ve;\n}\n\nfunction mouseEventCallback( event ) {\n\tvar touchID = $.data(event.target, touchTargetPropertyName);\n\n\tif ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ){\n\t\tvar ve = triggerVirtualEvent( \"v\" + event.type, event );\n\t\tif ( ve ) {\n\t\t\tif ( ve.isDefaultPrevented() ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t\tif ( ve.isPropagationStopped() ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t\tif ( ve.isImmediatePropagationStopped() ) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction handleTouchStart( event ) {\n\n\tvar touches = getNativeEvent( event ).touches,\n\t\ttarget, flags;\n\n\tif ( touches && touches.length === 1 ) {\n\n\t\ttarget = event.target;\n\t\tflags = getVirtualBindingFlags( target );\n\n\t\tif ( flags.hasVirtualBinding ) {\n\n\t\t\tlastTouchID = nextTouchID++;\n\t\t\t$.data( target, touchTargetPropertyName, lastTouchID );\n\n\t\t\tclearResetTimer();\n\n\t\t\tdisableMouseBindings();\n\t\t\tdidScroll = false;\n\n\t\t\tvar t = getNativeEvent( event ).touches[ 0 ];\n\t\t\tstartX = t.pageX;\n\t\t\tstartY = t.pageY;\n\n\t\t\ttriggerVirtualEvent( \"vmouseover\", event, flags );\n\t\t\ttriggerVirtualEvent( \"vmousedown\", event, flags );\n\t\t}\n\t}\n}\n\nfunction handleScroll( event ) {\n\tif ( blockTouchTriggers ) {\n\t\treturn;\n\t}\n\n\tif ( !didScroll ) {\n\t\ttriggerVirtualEvent( \"vmousecancel\", event, getVirtualBindingFlags( event.target ) );\n\t}\n\n\tdidScroll = true;\n\tstartResetTimer();\n}\n\nfunction handleTouchMove( event ) {\n\tif ( blockTouchTriggers ) {\n\t\treturn;\n\t}\n\n\tvar t = getNativeEvent( event ).touches[ 0 ],\n\t\tdidCancel = didScroll,\n\t\tmoveThreshold = $.vmouse.moveDistanceThreshold;\n\t\tdidScroll = didScroll ||\n\t\t\t( Math.abs(t.pageX - startX) > moveThreshold ||\n\t\t\t\tMath.abs(t.pageY - startY) > moveThreshold ),\n\t\tflags = getVirtualBindingFlags( event.target );\n\n\tif ( didScroll && !didCancel ) {\n\t\ttriggerVirtualEvent( \"vmousecancel\", event, flags );\n\t}\n\n\ttriggerVirtualEvent( \"vmousemove\", event, flags );\n\tstartResetTimer();\n}\n\nfunction handleTouchEnd( event ) {\n\tif ( blockTouchTriggers ) {\n\t\treturn;\n\t}\n\n\tdisableTouchBindings();\n\n\tvar flags = getVirtualBindingFlags( event.target ),\n\t\tt;\n\ttriggerVirtualEvent( \"vmouseup\", event, flags );\n\n\tif ( !didScroll ) {\n\t\tvar ve = triggerVirtualEvent( \"vclick\", event, flags );\n\t\tif ( ve && ve.isDefaultPrevented() ) {\n\t\t\t// The target of the mouse events that follow the touchend\n\t\t\t// event don't necessarily match the target used during the\n\t\t\t// touch. This means we need to rely on coordinates for blocking\n\t\t\t// any click that is generated.\n\t\t\tt = getNativeEvent( event ).changedTouches[ 0 ];\n\t\t\tclickBlockList.push({\n\t\t\t\ttouchID: lastTouchID,\n\t\t\t\tx: t.clientX,\n\t\t\t\ty: t.clientY\n\t\t\t});\n\n\t\t\t// Prevent any mouse events that follow from triggering\n\t\t\t// virtual event notifications.\n\t\t\tblockMouseTriggers = true;\n\t\t}\n\t}\n\ttriggerVirtualEvent( \"vmouseout\", event, flags);\n\tdidScroll = false;\n\n\tstartResetTimer();\n}\n\nfunction hasVirtualBindings( ele ) {\n\tvar bindings = $.data( ele, dataPropertyName ),\n\t\tk;\n\n\tif ( bindings ) {\n\t\tfor ( k in bindings ) {\n\t\t\tif ( bindings[ k ] ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction dummyMouseHandler(){}\n\nfunction getSpecialEventObject( eventType ) {\n\tvar realType = eventType.substr( 1 );\n\n\treturn {\n\t\tsetup: function( data, namespace ) {\n\t\t\t// If this is the first virtual mouse binding for this element,\n\t\t\t// add a bindings object to its data.\n\n\t\t\tif ( !hasVirtualBindings( this ) ) {\n\t\t\t\t$.data( this, dataPropertyName, {});\n\t\t\t}\n\n\t\t\t// If setup is called, we know it is the first binding for this\n\t\t\t// eventType, so initialize the count for the eventType to zero.\n\t\t\tvar bindings = $.data( this, dataPropertyName );\n\t\t\tbindings[ eventType ] = true;\n\n\t\t\t// If this is the first virtual mouse event for this type,\n\t\t\t// register a global handler on the document.\n\n\t\t\tactiveDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;\n\n\t\t\tif ( activeDocHandlers[ eventType ] === 1 ) {\n\t\t\t\t$document.bind( realType, mouseEventCallback );\n\t\t\t}\n\n\t\t\t// Some browsers, like Opera Mini, won't dispatch mouse/click events\n\t\t\t// for elements unless they actually have handlers registered on them.\n\t\t\t// To get around this, we register dummy handlers on the elements.\n\n\t\t\t$( this ).bind( realType, dummyMouseHandler );\n\n\t\t\t// For now, if event capture is not supported, we rely on mouse handlers.\n\t\t\tif ( eventCaptureSupported ) {\n\t\t\t\t// If this is the first virtual mouse binding for the document,\n\t\t\t\t// register our touchstart handler on the document.\n\n\t\t\t\tactiveDocHandlers[ \"touchstart\" ] = ( activeDocHandlers[ \"touchstart\" ] || 0) + 1;\n\n\t\t\t\tif (activeDocHandlers[ \"touchstart\" ] === 1) {\n\t\t\t\t\t$document.bind( \"touchstart\", handleTouchStart )\n\t\t\t\t\t\t.bind( \"touchend\", handleTouchEnd )\n\n\t\t\t\t\t\t// On touch platforms, touching the screen and then dragging your finger\n\t\t\t\t\t\t// causes the window content to scroll after some distance threshold is\n\t\t\t\t\t\t// exceeded. On these platforms, a scroll prevents a click event from being\n\t\t\t\t\t\t// dispatched, and on some platforms, even the touchend is suppressed. To\n\t\t\t\t\t\t// mimic the suppression of the click event, we need to watch for a scroll\n\t\t\t\t\t\t// event. Unfortunately, some platforms like iOS don't dispatch scroll\n\t\t\t\t\t\t// events until *AFTER* the user lifts their finger (touchend). This means\n\t\t\t\t\t\t// we need to watch both scroll and touchmove events to figure out whether\n\t\t\t\t\t\t// or not a scroll happenens before the touchend event is fired.\n\n\t\t\t\t\t\t.bind( \"touchmove\", handleTouchMove )\n\t\t\t\t\t\t.bind( \"scroll\", handleScroll );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function( data, namespace ) {\n\t\t\t// If this is the last virtual binding for this eventType,\n\t\t\t// remove its global handler from the document.\n\n\t\t\t--activeDocHandlers[ eventType ];\n\n\t\t\tif ( !activeDocHandlers[ eventType ] ) {\n\t\t\t\t$document.unbind( realType, mouseEventCallback );\n\t\t\t}\n\n\t\t\tif ( eventCaptureSupported ) {\n\t\t\t\t// If this is the last virtual mouse binding in existence,\n\t\t\t\t// remove our document touchstart listener.\n\n\t\t\t\t--activeDocHandlers[ \"touchstart\" ];\n\n\t\t\t\tif ( !activeDocHandlers[ \"touchstart\" ] ) {\n\t\t\t\t\t$document.unbind( \"touchstart\", handleTouchStart )\n\t\t\t\t\t\t.unbind( \"touchmove\", handleTouchMove )\n\t\t\t\t\t\t.unbind( \"touchend\", handleTouchEnd )\n\t\t\t\t\t\t.unbind( \"scroll\", handleScroll );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar $this = $( this ),\n\t\t\t\tbindings = $.data( this, dataPropertyName );\n\n\t\t\t// teardown may be called when an element was\n\t\t\t// removed from the DOM. If this is the case,\n\t\t\t// jQuery core may have already stripped the element\n\t\t\t// of any data bindings so we need to check it before\n\t\t\t// using it.\n\t\t\tif ( bindings ) {\n\t\t\t\tbindings[ eventType ] = false;\n\t\t\t}\n\n\t\t\t// Unregister the dummy event handler.\n\n\t\t\t$this.unbind( realType, dummyMouseHandler );\n\n\t\t\t// If this is the last virtual mouse binding on the\n\t\t\t// element, remove the binding data from the element.\n\n\t\t\tif ( !hasVirtualBindings( this ) ) {\n\t\t\t\t$this.removeData( dataPropertyName );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Expose our custom events to the jQuery bind/unbind mechanism.\n\nfor ( var i = 0; i < virtualEventNames.length; i++ ){\n\t$.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );\n}\n\n// Add a capture click handler to block clicks.\n// Note that we require event capture support for this so if the device\n// doesn't support it, we punt for now and rely solely on mouse events.\nif ( eventCaptureSupported ) {\n\tdocument.addEventListener( \"click\", function( e ){\n\t\tvar cnt = clickBlockList.length,\n\t\t\ttarget = e.target,\n\t\t\tx, y, ele, i, o, touchID;\n\n\t\tif ( cnt ) {\n\t\t\tx = e.clientX;\n\t\t\ty = e.clientY;\n\t\t\tthreshold = $.vmouse.clickDistanceThreshold;\n\n\t\t\t// The idea here is to run through the clickBlockList to see if\n\t\t\t// the current click event is in the proximity of one of our\n\t\t\t// vclick events that had preventDefault() called on it. If we find\n\t\t\t// one, then we block the click.\n\t\t\t//\n\t\t\t// Why do we have to rely on proximity?\n\t\t\t//\n\t\t\t// Because the target of the touch event that triggered the vclick\n\t\t\t// can be different from the target of the click event synthesized\n\t\t\t// by the browser. The target of a mouse/click event that is syntehsized\n\t\t\t// from a touch event seems to be implementation specific. For example,\n\t\t\t// some browsers will fire mouse/click events for a link that is near\n\t\t\t// a touch event, even though the target of the touchstart/touchend event\n\t\t\t// says the user touched outside the link. Also, it seems that with most\n\t\t\t// browsers, the target of the mouse/click event is not calculated until the\n\t\t\t// time it is dispatched, so if you replace an element that you touched\n\t\t\t// with another element, the target of the mouse/click will be the new\n\t\t\t// element underneath that point.\n\t\t\t//\n\t\t\t// Aside from proximity, we also check to see if the target and any\n\t\t\t// of its ancestors were the ones that blocked a click. This is necessary\n\t\t\t// because of the strange mouse/click target calculation done in the\n\t\t\t// Android 2.1 browser, where if you click on an element, and there is a\n\t\t\t// mouse/click handler on one of its ancestors, the target will be the\n\t\t\t// innermost child of the touched element, even if that child is no where\n\t\t\t// near the point of touch.\n\n\t\t\tele = target;\n\n\t\t\twhile ( ele ) {\n\t\t\t\tfor ( i = 0; i < cnt; i++ ) {\n\t\t\t\t\to = clickBlockList[ i ];\n\t\t\t\t\ttouchID = 0;\n\n\t\t\t\t\tif ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||\n\t\t\t\t\t\t\t\t$.data( ele, touchTargetPropertyName ) === o.touchID ) {\n\t\t\t\t\t\t// XXX: We may want to consider removing matches from the block list\n\t\t\t\t\t\t//      instead of waiting for the reset timer to fire.\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tele = ele.parentNode;\n\t\t\t}\n\t\t}\n\t}, true);\n}\n})( jQuery, window, document );\n\n\n\n// Script: jQuery hashchange event\n// \n// *Version: 1.3, Last updated: 7/21/2010*\n// \n// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/\n// GitHub       - http://github.com/cowboy/jquery-hashchange/\n// Source       - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js\n// (Minified)   - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)\n// \n// About: License\n// \n// Copyright (c) 2010 \"Cowboy\" Ben Alman,\n// Dual licensed under the MIT and GPL licenses.\n// http://benalman.com/about/license/\n// \n// About: Examples\n// \n// These working examples, complete with fully commented code, illustrate a few\n// ways in which this plugin can be used.\n// \n// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/\n// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/\n// \n// About: Support and Testing\n// \n// Information about what version or versions of jQuery this plugin has been\n// tested with, what browsers it has been tested in, and where the unit tests\n// reside (so you can test it yourself).\n// \n// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2\n// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,\n//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.\n// Unit Tests      - http://benalman.com/code/projects/jquery-hashchange/unit/\n// \n// About: Known issues\n// \n// While this jQuery hashchange event implementation is quite stable and\n// robust, there are a few unfortunate browser bugs surrounding expected\n// hashchange event-based behaviors, independent of any JavaScript\n// window.onhashchange abstraction. See the following examples for more\n// information:\n// \n// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/\n// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/\n// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/\n// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/\n// \n// Also note that should a browser natively support the window.onhashchange \n// event, but not report that it does, the fallback polling loop will be used.\n// \n// About: Release History\n// \n// 1.3   - (7/21/2010) Reorganized IE6/7 Iframe code to make it more\n//         \"removable\" for mobile-only development. Added IE6/7 document.title\n//         support. Attempted to make Iframe as hidden as possible by using\n//         techniques from http://www.paciellogroup.com/blog/?p=604. Added \n//         support for the \"shortcut\" format $(window).hashchange( fn ) and\n//         $(window).hashchange() like jQuery provides for built-in events.\n//         Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and\n//         lowered its default value to 50. Added <jQuery.fn.hashchange.domain>\n//         and <jQuery.fn.hashchange.src> properties plus document-domain.html\n//         file to address access denied issues when setting document.domain in\n//         IE6/7.\n// 1.2   - (2/11/2010) Fixed a bug where coming back to a page using this plugin\n//         from a page on another domain would cause an error in Safari 4. Also,\n//         IE6/7 Iframe is now inserted after the body (this actually works),\n//         which prevents the page from scrolling when the event is first bound.\n//         Event can also now be bound before DOM ready, but it won't be usable\n//         before then in IE6/7.\n// 1.1   - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug\n//         where browser version is incorrectly reported as 8.0, despite\n//         inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.\n// 1.0   - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special\n//         window.onhashchange functionality into a separate plugin for users\n//         who want just the basic event & back button support, without all the\n//         extra awesomeness that BBQ provides. This plugin will be included as\n//         part of jQuery BBQ, but also be available separately.\n\n(function($,window,undefined){\n  // Reused string.\n  var str_hashchange = 'hashchange',\n    \n    // Method / object references.\n    doc = document,\n    fake_onhashchange,\n    special = $.event.special,\n    \n    // Does the browser support window.onhashchange? Note that IE8 running in\n    // IE7 compatibility mode reports true for 'onhashchange' in window, even\n    // though the event isn't supported, so also test document.documentMode.\n    doc_mode = doc.documentMode,\n    supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );\n  \n  // Get location.hash (or what you'd expect location.hash to be) sans any\n  // leading #. Thanks for making this necessary, Firefox!\n  function get_fragment( url ) {\n    url = url || location.href;\n    return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );\n  };\n  \n  // Method: jQuery.fn.hashchange\n  // \n  // Bind a handler to the window.onhashchange event or trigger all bound\n  // window.onhashchange event handlers. This behavior is consistent with\n  // jQuery's built-in event handlers.\n  // \n  // Usage:\n  // \n  // > jQuery(window).hashchange( [ handler ] );\n  // \n  // Arguments:\n  // \n  //  handler - (Function) Optional handler to be bound to the hashchange\n  //    event. This is a \"shortcut\" for the more verbose form:\n  //    jQuery(window).bind( 'hashchange', handler ). If handler is omitted,\n  //    all bound window.onhashchange event handlers will be triggered. This\n  //    is a shortcut for the more verbose\n  //    jQuery(window).trigger( 'hashchange' ). These forms are described in\n  //    the <hashchange event> section.\n  // \n  // Returns:\n  // \n  //  (jQuery) The initial jQuery collection of elements.\n  \n  // Allow the \"shortcut\" format $(elem).hashchange( fn ) for binding and\n  // $(elem).hashchange() for triggering, like jQuery does for built-in events.\n  $.fn[ str_hashchange ] = function( fn ) {\n    return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );\n  };\n  \n  // Property: jQuery.fn.hashchange.delay\n  // \n  // The numeric interval (in milliseconds) at which the <hashchange event>\n  // polling loop executes. Defaults to 50.\n  \n  // Property: jQuery.fn.hashchange.domain\n  // \n  // If you're setting document.domain in your JavaScript, and you want hash\n  // history to work in IE6/7, not only must this property be set, but you must\n  // also set document.domain BEFORE jQuery is loaded into the page. This\n  // property is only applicable if you are supporting IE6/7 (or IE8 operating\n  // in \"IE7 compatibility\" mode).\n  // \n  // In addition, the <jQuery.fn.hashchange.src> property must be set to the\n  // path of the included \"document-domain.html\" file, which can be renamed or\n  // modified if necessary (note that the document.domain specified must be the\n  // same in both your main JavaScript as well as in this file).\n  // \n  // Usage:\n  // \n  // jQuery.fn.hashchange.domain = document.domain;\n  \n  // Property: jQuery.fn.hashchange.src\n  // \n  // If, for some reason, you need to specify an Iframe src file (for example,\n  // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can\n  // do so using this property. Note that when using this property, history\n  // won't be recorded in IE6/7 until the Iframe src file loads. This property\n  // is only applicable if you are supporting IE6/7 (or IE8 operating in \"IE7\n  // compatibility\" mode).\n  // \n  // Usage:\n  // \n  // jQuery.fn.hashchange.src = 'path/to/file.html';\n  \n  $.fn[ str_hashchange ].delay = 50;\n  /*\n  $.fn[ str_hashchange ].domain = null;\n  $.fn[ str_hashchange ].src = null;\n  */\n  \n  // Event: hashchange event\n  // \n  // Fired when location.hash changes. In browsers that support it, the native\n  // HTML5 window.onhashchange event is used, otherwise a polling loop is\n  // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to\n  // see if the hash has changed. In IE6/7 (and IE8 operating in \"IE7\n  // compatibility\" mode), a hidden Iframe is created to allow the back button\n  // and hash-based history to work.\n  // \n  // Usage as described in <jQuery.fn.hashchange>:\n  // \n  // > // Bind an event handler.\n  // > jQuery(window).hashchange( function(e) {\n  // >   var hash = location.hash;\n  // >   ...\n  // > });\n  // > \n  // > // Manually trigger the event handler.\n  // > jQuery(window).hashchange();\n  // \n  // A more verbose usage that allows for event namespacing:\n  // \n  // > // Bind an event handler.\n  // > jQuery(window).bind( 'hashchange', function(e) {\n  // >   var hash = location.hash;\n  // >   ...\n  // > });\n  // > \n  // > // Manually trigger the event handler.\n  // > jQuery(window).trigger( 'hashchange' );\n  // \n  // Additional Notes:\n  // \n  // * The polling loop and Iframe are not created until at least one handler\n  //   is actually bound to the 'hashchange' event.\n  // * If you need the bound handler(s) to execute immediately, in cases where\n  //   a location.hash exists on page load, via bookmark or page refresh for\n  //   example, use jQuery(window).hashchange() or the more verbose \n  //   jQuery(window).trigger( 'hashchange' ).\n  // * The event can be bound before DOM ready, but since it won't be usable\n  //   before then in IE6/7 (due to the necessary Iframe), recommended usage is\n  //   to bind it inside a DOM ready handler.\n  \n  // Override existing $.event.special.hashchange methods (allowing this plugin\n  // to be defined after jQuery BBQ in BBQ's source code).\n  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {\n    \n    // Called only when the first 'hashchange' event is bound to window.\n    setup: function() {\n      // If window.onhashchange is supported natively, there's nothing to do..\n      if ( supports_onhashchange ) { return false; }\n      \n      // Otherwise, we need to create our own. And we don't want to call this\n      // until the user binds to the event, just in case they never do, since it\n      // will create a polling loop and possibly even a hidden Iframe.\n      $( fake_onhashchange.start );\n    },\n    \n    // Called only when the last 'hashchange' event is unbound from window.\n    teardown: function() {\n      // If window.onhashchange is supported natively, there's nothing to do..\n      if ( supports_onhashchange ) { return false; }\n      \n      // Otherwise, we need to stop ours (if possible).\n      $( fake_onhashchange.stop );\n    }\n    \n  });\n  \n  // fake_onhashchange does all the work of triggering the window.onhashchange\n  // event for browsers that don't natively support it, including creating a\n  // polling loop to watch for hash changes and in IE 6/7 creating a hidden\n  // Iframe to enable back and forward.\n  fake_onhashchange = (function(){\n    var self = {},\n      timeout_id,\n      \n      // Remember the initial hash so it doesn't get triggered immediately.\n      last_hash = get_fragment(),\n      \n      fn_retval = function(val){ return val; },\n      history_set = fn_retval,\n      history_get = fn_retval;\n    \n    // Start the polling loop.\n    self.start = function() {\n      timeout_id || poll();\n    };\n    \n    // Stop the polling loop.\n    self.stop = function() {\n      timeout_id && clearTimeout( timeout_id );\n      timeout_id = undefined;\n    };\n    \n    // This polling loop checks every $.fn.hashchange.delay milliseconds to see\n    // if location.hash has changed, and triggers the 'hashchange' event on\n    // window when necessary.\n    function poll() {\n      var hash = get_fragment(),\n        history_hash = history_get( last_hash );\n      \n      if ( hash !== last_hash ) {\n        history_set( last_hash = hash, history_hash );\n        \n        $(window).trigger( str_hashchange );\n        \n      } else if ( history_hash !== last_hash ) {\n        location.href = location.href.replace( /#.*/, '' ) + history_hash;\n      }\n      \n      timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );\n    };\n    \n    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n    // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv\n    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n    $.browser.msie && !supports_onhashchange && (function(){\n      // Not only do IE6/7 need the \"magical\" Iframe treatment, but so does IE8\n      // when running in \"IE7 compatibility\" mode.\n      \n      var iframe,\n        iframe_src;\n      \n      // When the event is bound and polling starts in IE 6/7, create a hidden\n      // Iframe for history handling.\n      self.start = function(){\n        if ( !iframe ) {\n          iframe_src = $.fn[ str_hashchange ].src;\n          iframe_src = iframe_src && iframe_src + get_fragment();\n          \n          // Create hidden Iframe. Attempt to make Iframe as hidden as possible\n          // by using techniques from http://www.paciellogroup.com/blog/?p=604.\n          iframe = $('<iframe tabindex=\"-1\" title=\"empty\"/>').hide()\n            \n            // When Iframe has completely loaded, initialize the history and\n            // start polling.\n            .one( 'load', function(){\n              iframe_src || history_set( get_fragment() );\n              poll();\n            })\n            \n            // Load Iframe src if specified, otherwise nothing.\n            .attr( 'src', iframe_src || 'javascript:0' )\n            \n            // Append Iframe after the end of the body to prevent unnecessary\n            // initial page scrolling (yes, this works).\n            .insertAfter( 'body' )[0].contentWindow;\n          \n          // Whenever `document.title` changes, update the Iframe's title to\n          // prettify the back/next history menu entries. Since IE sometimes\n          // errors with \"Unspecified error\" the very first time this is set\n          // (yes, very useful) wrap this with a try/catch block.\n          doc.onpropertychange = function(){\n            try {\n              if ( event.propertyName === 'title' ) {\n                iframe.document.title = doc.title;\n              }\n            } catch(e) {}\n          };\n          \n        }\n      };\n      \n      // Override the \"stop\" method since an IE6/7 Iframe was created. Even\n      // if there are no longer any bound event handlers, the polling loop\n      // is still necessary for back/next to work at all!\n      self.stop = fn_retval;\n      \n      // Get history by looking at the hidden Iframe's location.hash.\n      history_get = function() {\n        return get_fragment( iframe.location.href );\n      };\n      \n      // Set a new history item by opening and then closing the Iframe\n      // document, *then* setting its location.hash. If document.domain has\n      // been set, update that as well.\n      history_set = function( hash, history_hash ) {\n        var iframe_doc = iframe.document,\n          domain = $.fn[ str_hashchange ].domain;\n        \n        if ( hash !== history_hash ) {\n          // Update Iframe with any initial `document.title` that might be set.\n          iframe_doc.title = doc.title;\n          \n          // Opening the Iframe's document after it has been closed is what\n          // actually adds a history entry.\n          iframe_doc.open();\n          \n          // Set document.domain for the Iframe document as well, if necessary.\n          domain && iframe_doc.write( '<script>document.domain=\"' + domain + '\"</script>' );\n          \n          iframe_doc.close();\n          \n          // Update the Iframe's hash, for great justice.\n          iframe.location.hash = hash;\n        }\n      };\n      \n    })();\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    \n    return self;\n  })();\n  \n})(jQuery,this);\n\n/*!\n * jQuery UI Widget @VERSION\n *\n * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Widget\n */\n\n(function( $, undefined ) {\n\n// jQuery 1.4+\nif ( $.cleanData ) {\n\tvar _cleanData = $.cleanData;\n\t$.cleanData = function( elems ) {\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t}\n\t\t_cleanData( elems );\n\t};\n} else {\n\tvar _remove = $.fn.remove;\n\t$.fn.remove = function( selector, keepData ) {\n\t\treturn this.each(function() {\n\t\t\tif ( !keepData ) {\n\t\t\t\tif ( !selector || $.filter( selector, [ this ] ).length ) {\n\t\t\t\t\t$( \"*\", this ).add( [ this ] ).each(function() {\n\t\t\t\t\t\t$( this ).triggerHandler( \"remove\" );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn _remove.call( $(this), selector, keepData );\n\t\t});\n\t};\n}\n\n$.widget = function( name, base, prototype ) {\n\tvar namespace = name.split( \".\" )[ 0 ],\n\t\tfullName;\n\tname = name.split( \".\" )[ 1 ];\n\tfullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\t// create selector for plugin\n\t$.expr[ \":\" ][ fullName ] = function( elem ) {\n\t\treturn !!$.data( elem, name );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\t$[ namespace ][ name ] = function( options, element ) {\n\t\t// allow instantiation without initializing for simple inheritance\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\n\tvar basePrototype = new base();\n\t// we need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n//\t$.each( basePrototype, function( key, val ) {\n//\t\tif ( $.isPlainObject(val) ) {\n//\t\t\tbasePrototype[ key ] = $.extend( {}, val );\n//\t\t}\n//\t});\n\tbasePrototype.options = $.extend( true, {}, basePrototype.options );\n\t$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,\n\t\twidgetBaseClass: fullName\n\t}, prototype );\n\n\t$.widget.bridge( name, $[ namespace ][ name ] );\n};\n\n$.widget.bridge = function( name, object ) {\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\",\n\t\t\targs = Array.prototype.slice.call( arguments, 1 ),\n\t\t\treturnValue = this;\n\n\t\t// allow multiple hashes to be passed on init\n\t\toptions = !isMethodCall && args.length ?\n\t\t\t$.extend.apply( null, [ true, options ].concat(args) ) :\n\t\t\toptions;\n\n\t\t// prevent calls to internal methods\n\t\tif ( isMethodCall && options.charAt( 0 ) === \"_\" ) {\n\t\t\treturn returnValue;\n\t\t}\n\n\t\tif ( isMethodCall ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = $.data( this, name );\n\t\t\t\tif ( !instance ) {\n\t\t\t\t\tthrow \"cannot call methods on \" + name + \" prior to initialization; \" +\n\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\";\n\t\t\t\t}\n\t\t\t\tif ( !$.isFunction( instance[options] ) ) {\n\t\t\t\t\tthrow \"no such method '\" + options + \"' for \" + name + \" widget instance\";\n\t\t\t\t}\n\t\t\t\tvar methodValue = instance[ options ].apply( instance, args );\n\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\treturnValue = methodValue;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = $.data( this, name );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} )._init();\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, name, new object( options, this ) );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( options, element ) {\n\t// allow instantiation without initializing for simple inheritance\n\tif ( arguments.length ) {\n\t\tthis._createWidget( options, element );\n\t}\n};\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\toptions: {\n\t\tdisabled: false\n\t},\n\t_createWidget: function( options, element ) {\n\t\t// $.widget.bridge stores the plugin instance, but we do it anyway\n\t\t// so that it's stored even before the _create function runs\n\t\t$.data( element, this.widgetName, this );\n\t\tthis.element = $( element );\n\t\tthis.options = $.extend( true, {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tvar self = this;\n\t\tthis.element.bind( \"remove.\" + this.widgetName, function() {\n\t\t\tself.destroy();\n\t\t});\n\n\t\tthis._create();\n\t\tthis._trigger( \"create\" );\n\t\tthis._init();\n\t},\n\t_getCreateOptions: function() {\n\t\tvar options = {};\n\t\tif ( $.metadata ) {\n\t\t\toptions = $.metadata.get( element )[ this.widgetName ];\n\t\t}\n\t\treturn options;\n\t},\n\t_create: function() {},\n\t_init: function() {},\n\n\tdestroy: function() {\n\t\tthis.element\n\t\t\t.unbind( \".\" + this.widgetName )\n\t\t\t.removeData( this.widgetName );\n\t\tthis.widget()\n\t\t\t.unbind( \".\" + this.widgetName )\n\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t.removeClass(\n\t\t\t\tthis.widgetBaseClass + \"-disabled \" +\n\t\t\t\t\"ui-state-disabled\" );\n\t},\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key;\n\n\t\tif ( arguments.length === 0 ) {\n\t\t\t// don't return a reference to the internal hash\n\t\t\treturn $.extend( {}, this.options );\n\t\t}\n\n\t\tif  (typeof key === \"string\" ) {\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn this.options[ key ];\n\t\t\t}\n\t\t\toptions = {};\n\t\t\toptions[ key ] = value;\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\t_setOptions: function( options ) {\n\t\tvar self = this;\n\t\t$.each( options, function( key, value ) {\n\t\t\tself._setOption( key, value );\n\t\t});\n\n\t\treturn this;\n\t},\n\t_setOption: function( key, value ) {\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.widget()\n\t\t\t\t[ value ? \"addClass\" : \"removeClass\"](\n\t\t\t\t\tthis.widgetBaseClass + \"-disabled\" + \" \" +\n\t\t\t\t\t\"ui-state-disabled\" )\n\t\t\t\t.attr( \"aria-disabled\", value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tenable: function() {\n\t\treturn this._setOption( \"disabled\", false );\n\t},\n\tdisable: function() {\n\t\treturn this._setOption( \"disabled\", true );\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar callback = this.options[ type ];\n\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\t\tdata = data || {};\n\n\t\t// copy original event properties over to the new event\n\t\t// this would happen if we could call $.event.fix instead of $.Event\n\t\t// but we don't have a way to force an event to be fixed multiple times\n\t\tif ( event.originalEvent ) {\n\t\t\tfor ( var i = $.event.props.length, prop; i; ) {\n\t\t\t\tprop = $.event.props[ --i ];\n\t\t\t\tevent[ prop ] = event.originalEvent[ prop ];\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\n\t\treturn !( $.isFunction(callback) &&\n\t\t\tcallback.call( this.element[0], event, data ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.widget\", {\n\t// decorate the parent _createWidget to trigger `widgetinit` for users\n\t// who wish to do post post `widgetcreate` alterations/additions\n\t//\n\t// TODO create a pull request for jquery ui to trigger this event\n\t// in the original _createWidget\n\t_createWidget: function() {\n\t\t$.Widget.prototype._createWidget.apply( this, arguments );\n\t\tthis._trigger( 'init' );\n\t},\n\n\t_getCreateOptions: function() {\n\n\t\tvar elem = this.element,\n\t\t\toptions = {};\n\n\t\t$.each( this.options, function( option ) {\n\n\t\t\tvar value = elem.jqmData( option.replace( /[A-Z]/g, function( c ) {\n\t\t\t\t\t\t\treturn \"-\" + c.toLowerCase();\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\n\t\t\tif ( value !== undefined ) {\n\t\t\t\toptions[ option ] = value;\n\t\t\t}\n\t\t});\n\n\t\treturn options;\n\t},\n\n\tenhanceWithin: function( target, useKeepNative ) {\n\t\tthis.enhance( $( this.options.initSelector, $( target )), useKeepNative );\n\t},\n\n\tenhance: function( targets, useKeepNative ) {\n\t\tvar page, keepNative, $widgetElements = $( targets ), self = this;\n\n\t\t// if ignoreContentEnabled is set to true the framework should\n\t\t// only enhance the selected elements when they do NOT have a\n\t\t// parent with the data-namespace-ignore attribute\n\t\t$widgetElements = $.mobile.enhanceable( $widgetElements );\n\n\t\tif ( useKeepNative && $widgetElements.length ) {\n\t\t\t// TODO remove dependency on the page widget for the keepNative.\n\t\t\t// Currently the keepNative value is defined on the page prototype so\n\t\t\t// the method is as well\n\t\t\tpage = $.mobile.closestPageData( $widgetElements );\n\t\t\tkeepNative = (page && page.keepNativeSelector()) || \"\";\n\n\t\t\t$widgetElements = $widgetElements.not( keepNative );\n\t\t}\n\n\t\t$widgetElements[ this.widgetName ]();\n\t},\n\n\traise: function( msg ) {\n\t\tthrow \"Widget [\" + this.widgetName + \"]: \" + msg;\n\t}\n});\n\n})( jQuery );\n\n(function( $, window, undefined ) {\n\n\tvar nsNormalizeDict = {};\n\n\t// jQuery.mobile configurable options\n\t$.mobile = $.extend( {}, {\n\n\t\t// Version of the jQuery Mobile Framework\n\t\tversion: \"1.1.0\",\n\n\t\t// Namespace used framework-wide for data-attrs. Default is no namespace\n\t\tns: \"\",\n\n\t\t// Define the url parameter used for referencing widget-generated sub-pages.\n\t\t// Translates to to example.html&ui-page=subpageIdentifier\n\t\t// hash segment before &ui-page= is used to make Ajax request\n\t\tsubPageUrlKey: \"ui-page\",\n\n\t\t// Class assigned to page currently in view, and during transitions\n\t\tactivePageClass: \"ui-page-active\",\n\n\t\t// Class used for \"active\" button state, from CSS framework\n\t\tactiveBtnClass: \"ui-btn-active\",\n\n\t\t// Class used for \"focus\" form element state, from CSS framework\n\t\tfocusClass: \"ui-focus\",\n\n\t\t// Automatically handle clicks and form submissions through Ajax, when same-domain\n\t\tajaxEnabled: true,\n\n\t\t// Automatically load and show pages based on location.hash\n\t\thashListeningEnabled: true,\n\n\t\t// disable to prevent jquery from bothering with links\n\t\tlinkBindingEnabled: true,\n\n\t\t// Set default page transition - 'none' for no transitions\n\t\tdefaultPageTransition: \"fade\",\n\n\t\t// Set maximum window width for transitions to apply - 'false' for no limit\n\t\tmaxTransitionWidth: false,\n\n\t\t// Minimum scroll distance that will be remembered when returning to a page\n\t\tminScrollBack: 250,\n\n\t\t// DEPRECATED: the following property is no longer in use, but defined until 2.0 to prevent conflicts\n\t\ttouchOverflowEnabled: false,\n\n\t\t// Set default dialog transition - 'none' for no transitions\n\t\tdefaultDialogTransition: \"pop\",\n\n\t\t// Show loading message during Ajax requests\n\t\t// if false, message will not appear, but loading classes will still be toggled on html el\n\t\tloadingMessage: \"loading\",\n\n\t\t// Error response message - appears when an Ajax page request fails\n\t\tpageLoadErrorMessage: \"Error Loading Page\",\n\n\t\t// Should the text be visble in the loading message?\n\t\tloadingMessageTextVisible: false,\n\n\t\t// When the text is visible, what theme does the loading box use?\n\t\tloadingMessageTheme: \"a\",\n\n\t\t// For error messages, which theme does the box uses?\n\t\tpageLoadErrorMessageTheme: \"e\",\n\n\t\t//automatically initialize the DOM when it's ready\n\t\tautoInitializePage: true,\n\n\t\tpushStateEnabled: true,\n\n\t\t// allows users to opt in to ignoring content by marking a parent element as\n\t\t// data-ignored\n\t\tignoreContentEnabled: false,\n\n\t\t// turn of binding to the native orientationchange due to android orientation behavior\n\t\torientationChangeEnabled: true,\n\n\t\tbuttonMarkup: {\n\t\t\thoverDelay: 200\n\t\t},\n\n\t\t// TODO might be useful upstream in jquery itself ?\n\t\tkeyCode: {\n\t\t\tALT: 18,\n\t\t\tBACKSPACE: 8,\n\t\t\tCAPS_LOCK: 20,\n\t\t\tCOMMA: 188,\n\t\t\tCOMMAND: 91,\n\t\t\tCOMMAND_LEFT: 91, // COMMAND\n\t\t\tCOMMAND_RIGHT: 93,\n\t\t\tCONTROL: 17,\n\t\t\tDELETE: 46,\n\t\t\tDOWN: 40,\n\t\t\tEND: 35,\n\t\t\tENTER: 13,\n\t\t\tESCAPE: 27,\n\t\t\tHOME: 36,\n\t\t\tINSERT: 45,\n\t\t\tLEFT: 37,\n\t\t\tMENU: 93, // COMMAND_RIGHT\n\t\t\tNUMPAD_ADD: 107,\n\t\t\tNUMPAD_DECIMAL: 110,\n\t\t\tNUMPAD_DIVIDE: 111,\n\t\t\tNUMPAD_ENTER: 108,\n\t\t\tNUMPAD_MULTIPLY: 106,\n\t\t\tNUMPAD_SUBTRACT: 109,\n\t\t\tPAGE_DOWN: 34,\n\t\t\tPAGE_UP: 33,\n\t\t\tPERIOD: 190,\n\t\t\tRIGHT: 39,\n\t\t\tSHIFT: 16,\n\t\t\tSPACE: 32,\n\t\t\tTAB: 9,\n\t\t\tUP: 38,\n\t\t\tWINDOWS: 91 // COMMAND\n\t\t},\n\n\t\t// Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value\n\t\tsilentScroll: function( ypos ) {\n\t\t\tif ( $.type( ypos ) !== \"number\" ) {\n\t\t\t\typos = $.mobile.defaultHomeScroll;\n\t\t\t}\n\n\t\t\t// prevent scrollstart and scrollstop events\n\t\t\t$.event.special.scrollstart.enabled = false;\n\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.scrollTo( 0, ypos );\n\t\t\t\t$( document ).trigger( \"silentscroll\", { x: 0, y: ypos });\n\t\t\t}, 20 );\n\n\t\t\tsetTimeout(function() {\n\t\t\t\t$.event.special.scrollstart.enabled = true;\n\t\t\t}, 150 );\n\t\t},\n\n\t\t// Expose our cache for testing purposes.\n\t\tnsNormalizeDict: nsNormalizeDict,\n\n\t\t// Take a data attribute property, prepend the namespace\n\t\t// and then camel case the attribute string. Add the result\n\t\t// to our nsNormalizeDict so we don't have to do this again.\n\t\tnsNormalize: function( prop ) {\n\t\t\tif ( !prop ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn nsNormalizeDict[ prop ] || ( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );\n\t\t},\n\n\t\tgetInheritedTheme: function( el, defaultTheme ) {\n\n\t\t\t// Find the closest parent with a theme class on it. Note that\n\t\t\t// we are not using $.fn.closest() on purpose here because this\n\t\t\t// method gets called quite a bit and we need it to be as fast\n\t\t\t// as possible.\n\n\t\t\tvar e = el[ 0 ],\n\t\t\t\tltr = \"\",\n\t\t\t\tre = /ui-(bar|body|overlay)-([a-z])\\b/,\n\t\t\t\tc, m;\n\n\t\t\twhile ( e ) {\n\t\t\t\tvar c = e.className || \"\";\n\t\t\t\tif ( ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) {\n\t\t\t\t\t// We found a parent with a theme class\n\t\t\t\t\t// on it so bail from this loop.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\te = e.parentNode;\n\t\t\t}\n\n\t\t\t// Return the theme letter we found, if none, return the\n\t\t\t// specified default.\n\n\t\t\treturn ltr || defaultTheme || \"a\";\n\t\t},\n\n\t\t// TODO the following $ and $.fn extensions can/probably should be moved into jquery.mobile.core.helpers\n\t\t//\n\t\t// Find the closest javascript page element to gather settings data jsperf test\n\t\t// http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit\n\t\t// possibly naive, but it shows that the parsing overhead for *just* the page selector vs\n\t\t// the page and dialog selector is negligable. This could probably be speed up by\n\t\t// doing a similar parent node traversal to the one found in the inherited theme code above\n\t\tclosestPageData: function( $target ) {\n\t\t\treturn $target\n\t\t\t\t.closest(':jqmData(role=\"page\"), :jqmData(role=\"dialog\")')\n\t\t\t\t.data(\"page\");\n\t\t},\n\n\t\tenhanceable: function( $set ) {\n\t\t\treturn this.haveParents( $set, \"enhance\" );\n\t\t},\n\n\t\thijackable: function( $set ) {\n\t\t\treturn this.haveParents( $set, \"ajax\" );\n\t\t},\n\n\t\thaveParents: function( $set, attr ) {\n\t\t\tif( !$.mobile.ignoreContentEnabled ){\n\t\t\t\treturn $set;\n\t\t\t}\n\n\t\t\tvar count = $set.length,\n\t\t\t\t$newSet = $(),\n\t\t\t\te, $element, excluded;\n\n\t\t\tfor ( var i = 0; i < count; i++ ) {\n\t\t\t\t$element = $set.eq( i );\n\t\t\t\texcluded = false;\n\t\t\t\te = $set[ i ];\n\n\t\t\t\twhile ( e ) {\n\t\t\t\t\tvar c = e.getAttribute ? e.getAttribute( \"data-\" + $.mobile.ns + attr ) : \"\";\n\n\t\t\t\t\tif ( c === \"false\" ) {\n\t\t\t\t\t\texcluded = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\te = e.parentNode;\n\t\t\t\t}\n\n\t\t\t\tif ( !excluded ) {\n\t\t\t\t\t$newSet = $newSet.add( $element );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $newSet;\n\t\t}\n\t}, $.mobile );\n\n\t// Mobile version of data and removeData and hasData methods\n\t// ensures all data is set and retrieved using jQuery Mobile's data namespace\n\t$.fn.jqmData = function( prop, value ) {\n\t\tvar result;\n\t\tif ( typeof prop != \"undefined\" ) {\n\t\t\tif ( prop ) {\n\t\t\t\tprop = $.mobile.nsNormalize( prop );\n\t\t\t}\n\t\t\tresult = this.data.apply( this, arguments.length < 2 ? [ prop ] : [ prop, value ] );\n\t\t}\n\t\treturn result;\n\t};\n\n\t$.jqmData = function( elem, prop, value ) {\n\t\tvar result;\n\t\tif ( typeof prop != \"undefined\" ) {\n\t\t\tresult = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );\n\t\t}\n\t\treturn result;\n\t};\n\n\t$.fn.jqmRemoveData = function( prop ) {\n\t\treturn this.removeData( $.mobile.nsNormalize( prop ) );\n\t};\n\n\t$.jqmRemoveData = function( elem, prop ) {\n\t\treturn $.removeData( elem, $.mobile.nsNormalize( prop ) );\n\t};\n\n\t$.fn.removeWithDependents = function() {\n\t\t$.removeWithDependents( this );\n\t};\n\n\t$.removeWithDependents = function( elem ) {\n\t\tvar $elem = $( elem );\n\n\t\t( $elem.jqmData('dependents') || $() ).remove();\n\t\t$elem.remove();\n\t};\n\n\t$.fn.addDependents = function( newDependents ) {\n\t\t$.addDependents( $(this), newDependents );\n\t};\n\n\t$.addDependents = function( elem, newDependents ) {\n\t\tvar dependents = $(elem).jqmData( 'dependents' ) || $();\n\n\t\t$(elem).jqmData( 'dependents', $.merge(dependents, newDependents) );\n\t};\n\n\t// note that this helper doesn't attempt to handle the callback\n\t// or setting of an html elements text, its only purpose is\n\t// to return the html encoded version of the text in all cases. (thus the name)\n\t$.fn.getEncodedText = function() {\n\t\treturn $( \"<div/>\" ).text( $(this).text() ).html();\n\t};\n\n\t// fluent helper function for the mobile namespaced equivalent\n\t$.fn.jqmEnhanceable = function() {\n\t\treturn $.mobile.enhanceable( this );\n\t};\n\n\t$.fn.jqmHijackable = function() {\n\t\treturn $.mobile.hijackable( this );\n\t};\n\n\t// Monkey-patching Sizzle to filter the :jqmData selector\n\tvar oldFind = $.find,\n\t\tjqmDataRE = /:jqmData\\(([^)]*)\\)/g;\n\n\t$.find = function( selector, context, ret, extra ) {\n\t\tselector = selector.replace( jqmDataRE, \"[data-\" + ( $.mobile.ns || \"\" ) + \"$1]\" );\n\n\t\treturn oldFind.call( this, selector, context, ret, extra );\n\t};\n\n\t$.extend( $.find, oldFind );\n\n\t$.find.matches = function( expr, set ) {\n\t\treturn $.find( expr, null, null, set );\n\t};\n\n\t$.find.matchesSelector = function( node, expr ) {\n\t\treturn $.find( expr, null, null, [ node ] ).length > 0;\n\t};\n})( jQuery, this );\n\n\n(function( $, undefined ) {\n\nvar $window = $( window ),\n\t$html = $( \"html\" );\n\n/* $.mobile.media method: pass a CSS media type or query and get a bool return\n\tnote: this feature relies on actual media query support for media queries, though types will work most anywhere\n\texamples:\n\t\t$.mobile.media('screen') // tests for screen media type\n\t\t$.mobile.media('screen and (min-width: 480px)') // tests for screen media type with window width > 480px\n\t\t$.mobile.media('@media screen and (-webkit-min-device-pixel-ratio: 2)') // tests for webkit 2x pixel ratio (iPhone 4)\n*/\n$.mobile.media = (function() {\n\t// TODO: use window.matchMedia once at least one UA implements it\n\tvar cache = {},\n\t\ttestDiv = $( \"<div id='jquery-mediatest'>\" ),\n\t\tfakeBody = $( \"<body>\" ).append( testDiv );\n\n\treturn function( query ) {\n\t\tif ( !( query in cache ) ) {\n\t\t\tvar styleBlock = document.createElement( \"style\" ),\n\t\t\t\tcssrule = \"@media \" + query + \" { #jquery-mediatest { position:absolute; } }\";\n\n\t\t\t//must set type for IE!\n\t\t\tstyleBlock.type = \"text/css\";\n\n\t\t\tif ( styleBlock.styleSheet  ){\n\t\t\t\tstyleBlock.styleSheet.cssText = cssrule;\n\t\t\t} else {\n\t\t\t\tstyleBlock.appendChild( document.createTextNode(cssrule) );\n\t\t\t}\n\n\t\t\t$html.prepend( fakeBody ).prepend( styleBlock );\n\t\t\tcache[ query ] = testDiv.css( \"position\" ) === \"absolute\";\n\t\t\tfakeBody.add( styleBlock ).remove();\n\t\t}\n\t\treturn cache[ query ];\n\t};\n})();\n\n})(jQuery);\n\n(function( $, undefined ) {\n\nvar fakeBody = $( \"<body>\" ).prependTo( \"html\" ),\n\tfbCSS = fakeBody[ 0 ].style,\n\tvendors = [ \"Webkit\", \"Moz\", \"O\" ],\n\twebos = \"palmGetResource\" in window, //only used to rule out scrollTop\n\toperamini = window.operamini && ({}).toString.call( window.operamini ) === \"[object OperaMini]\",\n\tbb = window.blackberry; //only used to rule out box shadow, as it's filled opaque on BB\n\n// thx Modernizr\nfunction propExists( prop ) {\n\tvar uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),\n\t\tprops = ( prop + \" \" + vendors.join( uc_prop + \" \" ) + uc_prop ).split( \" \" );\n\n\tfor ( var v in props ){\n\t\tif ( fbCSS[ props[ v ] ] !== undefined ) {\n\t\t\treturn true;\n\t\t}\n\t}\n}\n\nfunction validStyle( prop, value, check_vend ) {\n\tvar div = document.createElement('div'),\n\t\tuc = function( txt ) {\n\t\t\treturn txt.charAt( 0 ).toUpperCase() + txt.substr( 1 )\n\t\t},\n\t\tvend_pref = function( vend ) {\n\t\t\treturn  \"-\" + vend.charAt( 0 ).toLowerCase() + vend.substr( 1 ) + \"-\";\n\t\t},\n\t\tcheck_style = function( vend ) {\n\t\t\tvar vend_prop = vend_pref( vend ) + prop + \": \" + value + \";\",\n\t\t\t\tuc_vend = uc( vend ),\n\t\t\t\tpropStyle = uc_vend + uc( prop );\n\t\t\n\t\t\tdiv.setAttribute( \"style\", vend_prop );\n\t\t\n\t\t\tif( !!div.style[ propStyle ] ) {\n\t\t\t\tret = true;\n\t\t\t}\n\t\t},\n\t\tcheck_vends = check_vend ? [ check_vend ] : vendors,\n\t\tret;\n\n\tfor( i = 0; i < check_vends.length; i++ ) {\n\t\tcheck_style( check_vends[i] );\n\t}\n\treturn !!ret;\n}\n\n// Thanks to Modernizr src for this test idea. `perspective` check is limited to Moz to prevent a false positive for 3D transforms on Android.\nfunction transform3dTest() {\n\tvar prop = \"transform-3d\";\n\treturn validStyle( 'perspective', '10px', 'moz' ) || $.mobile.media( \"(-\" + vendors.join( \"-\" + prop + \"),(-\" ) + \"-\" + prop + \"),(\" + prop + \")\" );\n}\n\n// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )\nfunction baseTagTest() {\n\tvar fauxBase = location.protocol + \"//\" + location.host + location.pathname + \"ui-dir/\",\n\t\tbase = $( \"head base\" ),\n\t\tfauxEle = null,\n\t\thref = \"\",\n\t\tlink, rebase;\n\n\tif ( !base.length ) {\n\t\tbase = fauxEle = $( \"<base>\", { \"href\": fauxBase }).appendTo( \"head\" );\n\t} else {\n\t\thref = base.attr( \"href\" );\n\t}\n\n\tlink = $( \"<a href='testurl' />\" ).prependTo( fakeBody );\n\trebase = link[ 0 ].href;\n\tbase[ 0 ].href = href || location.pathname;\n\n\tif ( fauxEle ) {\n\t\tfauxEle.remove();\n\t}\n\treturn rebase.indexOf( fauxBase ) === 0;\n}\n\n\n// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683\n// allows for inclusion of IE 6+, including Windows Mobile 7\n$.extend( $.mobile, { browser: {} } );\n$.mobile.browser.ie = (function() {\n\tvar v = 3,\n\tdiv = document.createElement( \"div\" ),\n\ta = div.all || [];\n\n\t// added {} to silence closure compiler warnings. registering my dislike of all things\n\t// overly clever here for future reference\n\twhile ( div.innerHTML = \"<!--[if gt IE \" + ( ++v ) + \"]><br><![endif]-->\", a[ 0 ] ){};\n\n\treturn v > 4 ? v : !v;\n})();\n\n\n$.extend( $.support, {\n\torientation: \"orientation\" in window && \"onorientationchange\" in window,\n\ttouch: \"ontouchend\" in document,\n\tcssTransitions: \"WebKitTransitionEvent\" in window || validStyle( 'transition', 'height 100ms linear' ),\n\tpushState: \"pushState\" in history && \"replaceState\" in history,\n\tmediaquery: $.mobile.media( \"only all\" ),\n\tcssPseudoElement: !!propExists( \"content\" ),\n\ttouchOverflow: !!propExists( \"overflowScrolling\" ),\n\tcssTransform3d: transform3dTest(),\n\tboxShadow: !!propExists( \"boxShadow\" ) && !bb,\n\tscrollTop: ( \"pageXOffset\" in window || \"scrollTop\" in document.documentElement || \"scrollTop\" in fakeBody[ 0 ] ) && !webos && !operamini,\n\tdynamicBaseTag: baseTagTest()\n});\n\nfakeBody.remove();\n\n\n// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)\n// or that generally work better browsing in regular http for full page refreshes (Opera Mini)\n// Note: This detection below is used as a last resort.\n// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible\nvar nokiaLTE7_3 = (function(){\n\n\tvar ua = window.navigator.userAgent;\n\n\t//The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older\n\treturn ua.indexOf( \"Nokia\" ) > -1 &&\n\t\t\t( ua.indexOf( \"Symbian/3\" ) > -1 || ua.indexOf( \"Series60/5\" ) > -1 ) &&\n\t\t\tua.indexOf( \"AppleWebKit\" ) > -1 &&\n\t\t\tua.match( /(BrowserNG|NokiaBrowser)\\/7\\.[0-3]/ );\n})();\n\n// Support conditions that must be met in order to proceed\n// default enhanced qualifications are media query support OR IE 7+\n$.mobile.gradeA = function(){\n\treturn $.support.mediaquery || $.mobile.browser.ie && $.mobile.browser.ie >= 7;\n};\n\n$.mobile.ajaxBlacklist =\n\t\t\t// BlackBerry browsers, pre-webkit\n\t\t\twindow.blackberry && !window.WebKitPoint ||\n\t\t\t// Opera Mini\n\t\t\toperamini ||\n\t\t\t// Symbian webkits pre 7.3\n\t\t\tnokiaLTE7_3;\n\n// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices\n// to render the stylesheets when they're referenced before this script, as we'd recommend doing.\n// This simply reappends the CSS in place, which for some reason makes it apply\nif ( nokiaLTE7_3 ) {\n\t$(function() {\n\t\t$( \"head link[rel='stylesheet']\" ).attr( \"rel\", \"alternate stylesheet\" ).attr( \"rel\", \"stylesheet\" );\n\t});\n}\n\n// For ruling out shadows via css\nif ( !$.support.boxShadow ) {\n\t$( \"html\" ).addClass( \"ui-mobile-nosupport-boxshadow\" );\n}\n\n})( jQuery );\n\n(function( $, window, undefined ) {\n\n// add new event shortcuts\n$.each( ( \"touchstart touchmove touchend orientationchange throttledresize \" +\n\t\t\t\t\t\"tap taphold swipe swipeleft swiperight scrollstart scrollstop\" ).split( \" \" ), function( i, name ) {\n\n\t$.fn[ name ] = function( fn ) {\n\t\treturn fn ? this.bind( name, fn ) : this.trigger( name );\n\t};\n\n\t$.attrFn[ name ] = true;\n});\n\nvar supportTouch = $.support.touch,\n\tscrollEvent = \"touchmove scroll\",\n\ttouchStartEvent = supportTouch ? \"touchstart\" : \"mousedown\",\n\ttouchStopEvent = supportTouch ? \"touchend\" : \"mouseup\",\n\ttouchMoveEvent = supportTouch ? \"touchmove\" : \"mousemove\";\n\nfunction triggerCustomEvent( obj, eventType, event ) {\n\tvar originalType = event.type;\n\tevent.type = eventType;\n\t$.event.handle.call( obj, event );\n\tevent.type = originalType;\n}\n\n// also handles scrollstop\n$.event.special.scrollstart = {\n\n\tenabled: true,\n\n\tsetup: function() {\n\n\t\tvar thisObject = this,\n\t\t\t$this = $( thisObject ),\n\t\t\tscrolling,\n\t\t\ttimer;\n\n\t\tfunction trigger( event, state ) {\n\t\t\tscrolling = state;\n\t\t\ttriggerCustomEvent( thisObject, scrolling ? \"scrollstart\" : \"scrollstop\", event );\n\t\t}\n\n\t\t// iPhone triggers scroll after a small delay; use touchmove instead\n\t\t$this.bind( scrollEvent, function( event ) {\n\n\t\t\tif ( !$.event.special.scrollstart.enabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( !scrolling ) {\n\t\t\t\ttrigger( event, true );\n\t\t\t}\n\n\t\t\tclearTimeout( timer );\n\t\t\ttimer = setTimeout(function() {\n\t\t\t\ttrigger( event, false );\n\t\t\t}, 50 );\n\t\t});\n\t}\n};\n\n// also handles taphold\n$.event.special.tap = {\n\tsetup: function() {\n\t\tvar thisObject = this,\n\t\t\t$this = $( thisObject );\n\n\t\t$this.bind( \"vmousedown\", function( event ) {\n\n\t\t\tif ( event.which && event.which !== 1 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar origTarget = event.target,\n\t\t\t\torigEvent = event.originalEvent,\n\t\t\t\ttimer;\n\n\t\t\tfunction clearTapTimer() {\n\t\t\t\tclearTimeout( timer );\n\t\t\t}\n\n\t\t\tfunction clearTapHandlers() {\n\t\t\t\tclearTapTimer();\n\n\t\t\t\t$this.unbind( \"vclick\", clickHandler )\n\t\t\t\t\t.unbind( \"vmouseup\", clearTapTimer );\n\t\t\t\t$( document ).unbind( \"vmousecancel\", clearTapHandlers );\n\t\t\t}\n\n\t\t\tfunction clickHandler(event) {\n\t\t\t\tclearTapHandlers();\n\n\t\t\t\t// ONLY trigger a 'tap' event if the start target is\n\t\t\t\t// the same as the stop target.\n\t\t\t\tif ( origTarget == event.target ) {\n\t\t\t\t\ttriggerCustomEvent( thisObject, \"tap\", event );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this.bind( \"vmouseup\", clearTapTimer )\n\t\t\t\t.bind( \"vclick\", clickHandler );\n\t\t\t$( document ).bind( \"vmousecancel\", clearTapHandlers );\n\n\t\t\ttimer = setTimeout(function() {\n\t\t\t\t\ttriggerCustomEvent( thisObject, \"taphold\", $.Event( \"taphold\", { target: origTarget } ) );\n\t\t\t}, 750 );\n\t\t});\n\t}\n};\n\n// also handles swipeleft, swiperight\n$.event.special.swipe = {\n\tscrollSupressionThreshold: 10, // More than this horizontal displacement, and we will suppress scrolling.\n\n\tdurationThreshold: 1000, // More time than this, and it isn't a swipe.\n\n\thorizontalDistanceThreshold: 30,  // Swipe horizontal displacement must be more than this.\n\n\tverticalDistanceThreshold: 75,  // Swipe vertical displacement must be less than this.\n\n\tsetup: function() {\n\t\tvar thisObject = this,\n\t\t\t$this = $( thisObject );\n\n\t\t$this.bind( touchStartEvent, function( event ) {\n\t\t\tvar data = event.originalEvent.touches ?\n\t\t\t\t\t\t\t\tevent.originalEvent.touches[ 0 ] : event,\n\t\t\t\tstart = {\n\t\t\t\t\ttime: ( new Date() ).getTime(),\n\t\t\t\t\tcoords: [ data.pageX, data.pageY ],\n\t\t\t\t\torigin: $( event.target )\n\t\t\t\t},\n\t\t\t\tstop;\n\n\t\t\tfunction moveHandler( event ) {\n\n\t\t\t\tif ( !start ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar data = event.originalEvent.touches ?\n\t\t\t\t\t\tevent.originalEvent.touches[ 0 ] : event;\n\n\t\t\t\tstop = {\n\t\t\t\t\ttime: ( new Date() ).getTime(),\n\t\t\t\t\tcoords: [ data.pageX, data.pageY ]\n\t\t\t\t};\n\n\t\t\t\t// prevent scrolling\n\t\t\t\tif ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this.bind( touchMoveEvent, moveHandler )\n\t\t\t\t.one( touchStopEvent, function( event ) {\n\t\t\t\t\t$this.unbind( touchMoveEvent, moveHandler );\n\n\t\t\t\t\tif ( start && stop ) {\n\t\t\t\t\t\tif ( stop.time - start.time < $.event.special.swipe.durationThreshold &&\n\t\t\t\t\t\t\t\tMath.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&\n\t\t\t\t\t\t\t\tMath.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {\n\n\t\t\t\t\t\t\tstart.origin.trigger( \"swipe\" )\n\t\t\t\t\t\t\t\t.trigger( start.coords[0] > stop.coords[ 0 ] ? \"swipeleft\" : \"swiperight\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstart = stop = undefined;\n\t\t\t\t});\n\t\t});\n\t}\n};\n\n(function( $, window ) {\n\t// \"Cowboy\" Ben Alman\n\n\tvar win = $( window ),\n\t\tspecial_event,\n\t\tget_orientation,\n\t\tlast_orientation,\n\t\tinitial_orientation_is_landscape,\n\t\tinitial_orientation_is_default,\n\t\tportrait_map = { \"0\": true, \"180\": true };\n\n\t// It seems that some device/browser vendors use window.orientation values 0 and 180 to\n\t// denote the \"default\" orientation. For iOS devices, and most other smart-phones tested,\n\t// the default orientation is always \"portrait\", but in some Android and RIM based tablets,\n\t// the default orientation is \"landscape\". The following code attempts to use the window\n\t// dimensions to figure out what the current orientation is, and then makes adjustments\n\t// to the to the portrait_map if necessary, so that we can properly decode the\n\t// window.orientation value whenever get_orientation() is called.\n\t//\n\t// Note that we used to use a media query to figure out what the orientation the browser\n\t// thinks it is in:\n\t//\n\t//     initial_orientation_is_landscape = $.mobile.media(\"all and (orientation: landscape)\");\n\t//\n\t// but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1,\n\t// where the browser *ALWAYS* applied the landscape media query. This bug does not\n\t// happen on iPad.\n\n\tif ( $.support.orientation ) {\n\n\t\t// Check the window width and height to figure out what the current orientation\n\t\t// of the device is at this moment. Note that we've initialized the portrait map\n\t\t// values to 0 and 180, *AND* we purposely check for landscape so that if we guess\n\t\t// wrong, , we default to the assumption that portrait is the default orientation.\n\t\t// We use a threshold check below because on some platforms like iOS, the iPhone\n\t\t// form-factor can report a larger width than height if the user turns on the\n\t\t// developer console. The actual threshold value is somewhat arbitrary, we just\n\t\t// need to make sure it is large enough to exclude the developer console case.\n\n\t\tvar ww = window.innerWidth || $( window ).width(),\n\t\t\twh = window.innerHeight || $( window ).height(),\n\t\t\tlandscape_threshold = 50;\n\n\t\tinitial_orientation_is_landscape = ww > wh && ( ww - wh ) > landscape_threshold;\n\n\n\t\t// Now check to see if the current window.orientation is 0 or 180.\n\t\tinitial_orientation_is_default = portrait_map[ window.orientation ];\n\n\t\t// If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR*\n\t\t// if the initial orientation is portrait, but window.orientation reports 90 or -90, we\n\t\t// need to flip our portrait_map values because landscape is the default orientation for\n\t\t// this device/browser.\n\t\tif ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) {\n\t\t\tportrait_map = { \"-90\": true, \"90\": true };\n\t\t}\n\t}\n\n\t$.event.special.orientationchange = special_event = {\n\t\tsetup: function() {\n\t\t\t// If the event is supported natively, return false so that jQuery\n\t\t\t// will bind to the event using DOM methods.\n\t\t\tif ( $.support.orientation && $.mobile.orientationChangeEnabled ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Get the current orientation to avoid initial double-triggering.\n\t\t\tlast_orientation = get_orientation();\n\n\t\t\t// Because the orientationchange event doesn't exist, simulate the\n\t\t\t// event by testing window dimensions on resize.\n\t\t\twin.bind( \"throttledresize\", handler );\n\t\t},\n\t\tteardown: function(){\n\t\t\t// If the event is not supported natively, return false so that\n\t\t\t// jQuery will unbind the event using DOM methods.\n\t\t\tif ( $.support.orientation && $.mobile.orientationChangeEnabled ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Because the orientationchange event doesn't exist, unbind the\n\t\t\t// resize event handler.\n\t\t\twin.unbind( \"throttledresize\", handler );\n\t\t},\n\t\tadd: function( handleObj ) {\n\t\t\t// Save a reference to the bound event handler.\n\t\t\tvar old_handler = handleObj.handler;\n\n\n\t\t\thandleObj.handler = function( event ) {\n\t\t\t\t// Modify event object, adding the .orientation property.\n\t\t\t\tevent.orientation = get_orientation();\n\n\t\t\t\t// Call the originally-bound event handler and return its result.\n\t\t\t\treturn old_handler.apply( this, arguments );\n\t\t\t};\n\t\t}\n\t};\n\n\t// If the event is not supported natively, this handler will be bound to\n\t// the window resize event to simulate the orientationchange event.\n\tfunction handler() {\n\t\t// Get the current orientation.\n\t\tvar orientation = get_orientation();\n\n\t\tif ( orientation !== last_orientation ) {\n\t\t\t// The orientation has changed, so trigger the orientationchange event.\n\t\t\tlast_orientation = orientation;\n\t\t\twin.trigger( \"orientationchange\" );\n\t\t}\n\t}\n\n\t// Get the current page orientation. This method is exposed publicly, should it\n\t// be needed, as jQuery.event.special.orientationchange.orientation()\n\t$.event.special.orientationchange.orientation = get_orientation = function() {\n\t\tvar isPortrait = true, elem = document.documentElement;\n\n\t\t// prefer window orientation to the calculation based on screensize as\n\t\t// the actual screen resize takes place before or after the orientation change event\n\t\t// has been fired depending on implementation (eg android 2.3 is before, iphone after).\n\t\t// More testing is required to determine if a more reliable method of determining the new screensize\n\t\t// is possible when orientationchange is fired. (eg, use media queries + element + opacity)\n\t\tif ( $.support.orientation ) {\n\t\t\t// if the window orientation registers as 0 or 180 degrees report\n\t\t\t// portrait, otherwise landscape\n\t\t\tisPortrait = portrait_map[ window.orientation ];\n\t\t} else {\n\t\t\tisPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;\n\t\t}\n\n\t\treturn isPortrait ? \"portrait\" : \"landscape\";\n\t};\n\n})( jQuery, window );\n\n\n// throttled resize event\n(function() {\n\n\t$.event.special.throttledresize = {\n\t\tsetup: function() {\n\t\t\t$( this ).bind( \"resize\", handler );\n\t\t},\n\t\tteardown: function(){\n\t\t\t$( this ).unbind( \"resize\", handler );\n\t\t}\n\t};\n\n\tvar throttle = 250,\n\t\thandler = function() {\n\t\t\tcurr = ( new Date() ).getTime();\n\t\t\tdiff = curr - lastCall;\n\n\t\t\tif ( diff >= throttle ) {\n\n\t\t\t\tlastCall = curr;\n\t\t\t\t$( this ).trigger( \"throttledresize\" );\n\n\t\t\t} else {\n\n\t\t\t\tif ( heldCall ) {\n\t\t\t\t\tclearTimeout( heldCall );\n\t\t\t\t}\n\n\t\t\t\t// Promise a held call will still execute\n\t\t\t\theldCall = setTimeout( handler, throttle - diff );\n\t\t\t}\n\t\t},\n\t\tlastCall = 0,\n\t\theldCall,\n\t\tcurr,\n\t\tdiff;\n})();\n\n\n$.each({\n\tscrollstop: \"scrollstart\",\n\ttaphold: \"tap\",\n\tswipeleft: \"swipe\",\n\tswiperight: \"swipe\"\n}, function( event, sourceEvent ) {\n\n\t$.event.special[ event ] = {\n\t\tsetup: function() {\n\t\t\t$( this ).bind( sourceEvent, $.noop );\n\t\t}\n\t};\n});\n\n})( jQuery, this );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.page\", $.mobile.widget, {\n\toptions: {\n\t\ttheme: \"c\",\n\t\tdomCache: false,\n\t\tkeepNativeDefault: \":jqmData(role='none'), :jqmData(role='nojs')\"\n\t},\n\n\t_create: function() {\n\t\t\n\t\tvar self = this;\n\t\t\n\t\t// if false is returned by the callbacks do not create the page\n\t\tif( self._trigger( \"beforecreate\" ) === false ){\n\t\t\treturn false;\n\t\t}\n\n\t\tself.element\n\t\t\t.attr( \"tabindex\", \"0\" )\n\t\t\t.addClass( \"ui-page ui-body-\" + self.options.theme )\n\t\t\t.bind( \"pagebeforehide\", function(){\n\t\t\t\tself.removeContainerBackground();\n\t\t\t} )\n\t\t\t.bind( \"pagebeforeshow\", function(){\n\t\t\t\tself.setContainerBackground();\n\t\t\t} );\n\n\t},\n\t\n\tremoveContainerBackground: function(){\n\t\t$.mobile.pageContainer.removeClass( \"ui-overlay-\" + $.mobile.getInheritedTheme( this.element.parent() ) );\n\t},\n\t\n\t// set the page container background to the page theme\n\tsetContainerBackground: function( theme ){\n\t\tif( this.options.theme ){\n\t\t\t$.mobile.pageContainer.addClass( \"ui-overlay-\" + ( theme || this.options.theme ) );\n\t\t}\n\t},\n\n\tkeepNativeSelector: function() {\n\t\tvar options = this.options,\n\t\t\tkeepNativeDefined = options.keepNative && $.trim(options.keepNative);\n\n\t\tif( keepNativeDefined && options.keepNative !== options.keepNativeDefault ){\n\t\t\treturn [options.keepNative, options.keepNativeDefault].join(\", \");\n\t\t}\n\n\t\treturn options.keepNativeDefault;\n\t}\n});\n})( jQuery );\n\n\n(function( $, window, undefined ) {\n\nvar createHandler = function( sequential ){\n\t\n\t// Default to sequential\n\tif( sequential === undefined ){\n\t\tsequential = true;\n\t}\n\t\n\treturn function( name, reverse, $to, $from ) {\n\n\t\tvar deferred = new $.Deferred(),\n\t\t\treverseClass = reverse ? \" reverse\" : \"\",\n\t\t\tactive\t= $.mobile.urlHistory.getActive(),\n\t\t\ttoScroll = active.lastScroll || $.mobile.defaultHomeScroll,\n\t\t\tscreenHeight = $.mobile.getScreenHeight(),\n\t\t\tmaxTransitionOverride = $.mobile.maxTransitionWidth !== false && $( window ).width() > $.mobile.maxTransitionWidth,\n\t\t\tnone = !$.support.cssTransitions || maxTransitionOverride || !name || name === \"none\",\n\t\t\ttoggleViewportClass = function(){\n\t\t\t\t$.mobile.pageContainer.toggleClass( \"ui-mobile-viewport-transitioning viewport-\" + name );\n\t\t\t},\n\t\t\tscrollPage = function(){\n\t\t\t\t// By using scrollTo instead of silentScroll, we can keep things better in order\n\t\t\t\t// Just to be precautios, disable scrollstart listening like silentScroll would\n\t\t\t\t$.event.special.scrollstart.enabled = false;\n\t\t\t\t\n\t\t\t\twindow.scrollTo( 0, toScroll );\n\t\t\t\t\n\t\t\t\t// reenable scrollstart listening like silentScroll would\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t$.event.special.scrollstart.enabled = true;\n\t\t\t\t}, 150 );\n\t\t\t},\n\t\t\tcleanFrom = function(){\n\t\t\t\t$from\n\t\t\t\t\t.removeClass( $.mobile.activePageClass + \" out in reverse \" + name )\n\t\t\t\t\t.height( \"\" );\n\t\t\t},\n\t\t\tstartOut = function(){\n\t\t\t\t// if it's not sequential, call the doneOut transition to start the TO page animating in simultaneously\n\t\t\t\tif( !sequential ){\n\t\t\t\t\tdoneOut();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$from.animationComplete( doneOut );\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Set the from page's height and start it transitioning out\n\t\t\t\t// Note: setting an explicit height helps eliminate tiling in the transitions\n\t\t\t\t$from\n\t\t\t\t\t.height( screenHeight + $(window ).scrollTop() )\n\t\t\t\t\t.addClass( name + \" out\" + reverseClass );\n\t\t\t},\n\t\t\t\n\t\t\tdoneOut = function() {\n\n\t\t\t\tif ( $from && sequential ) {\n\t\t\t\t\tcleanFrom();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tstartIn();\n\t\t\t},\n\t\t\t\n\t\t\tstartIn = function(){\t\n\t\t\t\n\t\t\t\t$to.addClass( $.mobile.activePageClass );\t\t\t\t\n\t\t\t\n\t\t\t\t// Send focus to page as it is now display: block\n\t\t\t\t$.mobile.focusPage( $to );\n\n\t\t\t\t// Set to page height\n\t\t\t\t$to.height( screenHeight + toScroll );\n\t\t\t\t\n\t\t\t\tscrollPage();\n\t\t\t\t\n\t\t\t\tif( !none ){\n\t\t\t\t\t$to.animationComplete( doneIn );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$to.addClass( name + \" in\" + reverseClass );\n\t\t\t\t\n\t\t\t\tif( none ){\n\t\t\t\t\tdoneIn();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t},\n\t\t\n\t\t\tdoneIn = function() {\n\t\t\t\n\t\t\t\tif ( !sequential ) {\n\t\t\t\t\t\n\t\t\t\t\tif( $from ){\n\t\t\t\t\t\tcleanFrom();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\n\t\t\t\t$to\n\t\t\t\t\t.removeClass( \"out in reverse \" + name )\n\t\t\t\t\t.height( \"\" );\n\t\t\t\t\n\t\t\t\ttoggleViewportClass();\n\t\t\t\t\n\t\t\t\t// In some browsers (iOS5), 3D transitions block the ability to scroll to the desired location during transition\n\t\t\t\t// This ensures we jump to that spot after the fact, if we aren't there already.\n\t\t\t\tif( $( window ).scrollTop() !== toScroll ){\n\t\t\t\t\tscrollPage();\n\t\t\t\t}\n\n\t\t\t\tdeferred.resolve( name, reverse, $to, $from, true );\n\t\t\t};\n\n\t\ttoggleViewportClass();\n\t\n\t\tif ( $from && !none ) {\n\t\t\tstartOut();\n\t\t}\n\t\telse {\n\t\t\tdoneOut();\n\t\t}\n\n\t\treturn deferred.promise();\n\t};\n}\n\n// generate the handlers from the above\nvar sequentialHandler = createHandler(),\n\tsimultaneousHandler = createHandler( false );\n\n// Make our transition handler the public default.\n$.mobile.defaultTransitionHandler = sequentialHandler;\n\n//transition handler dictionary for 3rd party transitions\n$.mobile.transitionHandlers = {\n\t\"default\": $.mobile.defaultTransitionHandler,\n\t\"sequential\": sequentialHandler,\n\t\"simultaneous\": simultaneousHandler\n};\n\n$.mobile.transitionFallbacks = {};\n\n})( jQuery, this );\n\n( function( $, undefined ) {\n\n\t//define vars for interal use\n\tvar $window = $( window ),\n\t\t$html = $( 'html' ),\n\t\t$head = $( 'head' ),\n\n\t\t//url path helpers for use in relative url management\n\t\tpath = {\n\n\t\t\t// This scary looking regular expression parses an absolute URL or its relative\n\t\t\t// variants (protocol, site, document, query, and hash), into the various\n\t\t\t// components (protocol, host, path, query, fragment, etc that make up the\n\t\t\t// URL as well as some other commonly used sub-parts. When used with RegExp.exec()\n\t\t\t// or String.match, it parses the URL into a results array that looks like this:\n\t\t\t//\n\t\t\t//     [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content\n\t\t\t//     [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread\n\t\t\t//     [2]: http://jblas:password@mycompany.com:8080/mail/inbox\n\t\t\t//     [3]: http://jblas:password@mycompany.com:8080\n\t\t\t//     [4]: http:\n\t\t\t//     [5]: //\n\t\t\t//     [6]: jblas:password@mycompany.com:8080\n\t\t\t//     [7]: jblas:password\n\t\t\t//     [8]: jblas\n\t\t\t//     [9]: password\n\t\t\t//    [10]: mycompany.com:8080\n\t\t\t//    [11]: mycompany.com\n\t\t\t//    [12]: 8080\n\t\t\t//    [13]: /mail/inbox\n\t\t\t//    [14]: /mail/\n\t\t\t//    [15]: inbox\n\t\t\t//    [16]: ?msg=1234&type=unread\n\t\t\t//    [17]: #msg-content\n\t\t\t//\n\t\t\turlParseRE: /^(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#]*)))?(\\?[^#]+)?)(#.*)?/,\n\n\t\t\t//Parse a URL into a structure that allows easy access to\n\t\t\t//all of the URL components by name.\n\t\t\tparseUrl: function( url ) {\n\t\t\t\t// If we're passed an object, we'll assume that it is\n\t\t\t\t// a parsed url object and just return it back to the caller.\n\t\t\t\tif ( $.type( url ) === \"object\" ) {\n\t\t\t\t\treturn url;\n\t\t\t\t}\n\n\t\t\t\tvar matches = path.urlParseRE.exec( url || \"\" ) || [];\n\n\t\t\t\t\t// Create an object that allows the caller to access the sub-matches\n\t\t\t\t\t// by name. Note that IE returns an empty string instead of undefined,\n\t\t\t\t\t// like all other browsers do, so we normalize everything so its consistent\n\t\t\t\t\t// no matter what browser we're running on.\n\t\t\t\t\treturn {\n\t\t\t\t\t\thref:         matches[  0 ] || \"\",\n\t\t\t\t\t\threfNoHash:   matches[  1 ] || \"\",\n\t\t\t\t\t\threfNoSearch: matches[  2 ] || \"\",\n\t\t\t\t\t\tdomain:       matches[  3 ] || \"\",\n\t\t\t\t\t\tprotocol:     matches[  4 ] || \"\",\n\t\t\t\t\t\tdoubleSlash:  matches[  5 ] || \"\",\n\t\t\t\t\t\tauthority:    matches[  6 ] || \"\",\n\t\t\t\t\t\tusername:     matches[  8 ] || \"\",\n\t\t\t\t\t\tpassword:     matches[  9 ] || \"\",\n\t\t\t\t\t\thost:         matches[ 10 ] || \"\",\n\t\t\t\t\t\thostname:     matches[ 11 ] || \"\",\n\t\t\t\t\t\tport:         matches[ 12 ] || \"\",\n\t\t\t\t\t\tpathname:     matches[ 13 ] || \"\",\n\t\t\t\t\t\tdirectory:    matches[ 14 ] || \"\",\n\t\t\t\t\t\tfilename:     matches[ 15 ] || \"\",\n\t\t\t\t\t\tsearch:       matches[ 16 ] || \"\",\n\t\t\t\t\t\thash:         matches[ 17 ] || \"\"\n\t\t\t\t\t};\n\t\t\t},\n\n\t\t\t//Turn relPath into an asbolute path. absPath is\n\t\t\t//an optional absolute path which describes what\n\t\t\t//relPath is relative to.\n\t\t\tmakePathAbsolute: function( relPath, absPath ) {\n\t\t\t\tif ( relPath && relPath.charAt( 0 ) === \"/\" ) {\n\t\t\t\t\treturn relPath;\n\t\t\t\t}\n\n\t\t\t\trelPath = relPath || \"\";\n\t\t\t\tabsPath = absPath ? absPath.replace( /^\\/|(\\/[^\\/]*|[^\\/]+)$/g, \"\" ) : \"\";\n\n\t\t\t\tvar absStack = absPath ? absPath.split( \"/\" ) : [],\n\t\t\t\t\trelStack = relPath.split( \"/\" );\n\t\t\t\tfor ( var i = 0; i < relStack.length; i++ ) {\n\t\t\t\t\tvar d = relStack[ i ];\n\t\t\t\t\tswitch ( d ) {\n\t\t\t\t\t\tcase \".\":\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"..\":\n\t\t\t\t\t\t\tif ( absStack.length ) {\n\t\t\t\t\t\t\t\tabsStack.pop();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tabsStack.push( d );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn \"/\" + absStack.join( \"/\" );\n\t\t\t},\n\n\t\t\t//Returns true if both urls have the same domain.\n\t\t\tisSameDomain: function( absUrl1, absUrl2 ) {\n\t\t\t\treturn path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain;\n\t\t\t},\n\n\t\t\t//Returns true for any relative variant.\n\t\t\tisRelativeUrl: function( url ) {\n\t\t\t\t// All relative Url variants have one thing in common, no protocol.\n\t\t\t\treturn path.parseUrl( url ).protocol === \"\";\n\t\t\t},\n\n\t\t\t//Returns true for an absolute url.\n\t\t\tisAbsoluteUrl: function( url ) {\n\t\t\t\treturn path.parseUrl( url ).protocol !== \"\";\n\t\t\t},\n\n\t\t\t//Turn the specified realtive URL into an absolute one. This function\n\t\t\t//can handle all relative variants (protocol, site, document, query, fragment).\n\t\t\tmakeUrlAbsolute: function( relUrl, absUrl ) {\n\t\t\t\tif ( !path.isRelativeUrl( relUrl ) ) {\n\t\t\t\t\treturn relUrl;\n\t\t\t\t}\n\n\t\t\t\tvar relObj = path.parseUrl( relUrl ),\n\t\t\t\t\tabsObj = path.parseUrl( absUrl ),\n\t\t\t\t\tprotocol = relObj.protocol || absObj.protocol,\n\t\t\t\t\tdoubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash ),\n\t\t\t\t\tauthority = relObj.authority || absObj.authority,\n\t\t\t\t\thasPath = relObj.pathname !== \"\",\n\t\t\t\t\tpathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),\n\t\t\t\t\tsearch = relObj.search || ( !hasPath && absObj.search ) || \"\",\n\t\t\t\t\thash = relObj.hash;\n\n\t\t\t\treturn protocol + doubleSlash + authority + pathname + search + hash;\n\t\t\t},\n\n\t\t\t//Add search (aka query) params to the specified url.\n\t\t\taddSearchParams: function( url, params ) {\n\t\t\t\tvar u = path.parseUrl( url ),\n\t\t\t\t\tp = ( typeof params === \"object\" ) ? $.param( params ) : params,\n\t\t\t\t\ts = u.search || \"?\";\n\t\t\t\treturn u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== \"?\" ? \"&\" : \"\" ) + p + ( u.hash || \"\" );\n\t\t\t},\n\n\t\t\tconvertUrlToDataUrl: function( absUrl ) {\n\t\t\t\tvar u = path.parseUrl( absUrl );\n\t\t\t\tif ( path.isEmbeddedPage( u ) ) {\n\t\t\t\t    // For embedded pages, remove the dialog hash key as in getFilePath(),\n\t\t\t\t    // otherwise the Data Url won't match the id of the embedded Page.\n\t\t\t\t\treturn u.hash.split( dialogHashKey )[0].replace( /^#/, \"\" );\n\t\t\t\t} else if ( path.isSameDomain( u, documentBase ) ) {\n\t\t\t\t\treturn u.hrefNoHash.replace( documentBase.domain, \"\" );\n\t\t\t\t}\n\t\t\t\treturn absUrl;\n\t\t\t},\n\n\t\t\t//get path from current hash, or from a file path\n\t\t\tget: function( newPath ) {\n\t\t\t\tif( newPath === undefined ) {\n\t\t\t\t\tnewPath = location.hash;\n\t\t\t\t}\n\t\t\t\treturn path.stripHash( newPath ).replace( /[^\\/]*\\.[^\\/*]+$/, '' );\n\t\t\t},\n\n\t\t\t//return the substring of a filepath before the sub-page key, for making a server request\n\t\t\tgetFilePath: function( path ) {\n\t\t\t\tvar splitkey = '&' + $.mobile.subPageUrlKey;\n\t\t\t\treturn path && path.split( splitkey )[0].split( dialogHashKey )[0];\n\t\t\t},\n\n\t\t\t//set location hash to path\n\t\t\tset: function( path ) {\n\t\t\t\tlocation.hash = path;\n\t\t\t},\n\n\t\t\t//test if a given url (string) is a path\n\t\t\t//NOTE might be exceptionally naive\n\t\t\tisPath: function( url ) {\n\t\t\t\treturn ( /\\// ).test( url );\n\t\t\t},\n\n\t\t\t//return a url path with the window's location protocol/hostname/pathname removed\n\t\t\tclean: function( url ) {\n\t\t\t\treturn url.replace( documentBase.domain, \"\" );\n\t\t\t},\n\n\t\t\t//just return the url without an initial #\n\t\t\tstripHash: function( url ) {\n\t\t\t\treturn url.replace( /^#/, \"\" );\n\t\t\t},\n\n\t\t\t//remove the preceding hash, any query params, and dialog notations\n\t\t\tcleanHash: function( hash ) {\n\t\t\t\treturn path.stripHash( hash.replace( /\\?.*$/, \"\" ).replace( dialogHashKey, \"\" ) );\n\t\t\t},\n\n\t\t\t//check whether a url is referencing the same domain, or an external domain or different protocol\n\t\t\t//could be mailto, etc\n\t\t\tisExternal: function( url ) {\n\t\t\t\tvar u = path.parseUrl( url );\n\t\t\t\treturn u.protocol && u.domain !== documentUrl.domain ? true : false;\n\t\t\t},\n\n\t\t\thasProtocol: function( url ) {\n\t\t\t\treturn ( /^(:?\\w+:)/ ).test( url );\n\t\t\t},\n\n\t\t\t//check if the specified url refers to the first page in the main application document.\n\t\t\tisFirstPageUrl: function( url ) {\n\t\t\t\t// We only deal with absolute paths.\n\t\t\t\tvar u = path.parseUrl( path.makeUrlAbsolute( url, documentBase ) ),\n\n\t\t\t\t\t// Does the url have the same path as the document?\n\t\t\t\t\tsamePath = u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ),\n\n\t\t\t\t\t// Get the first page element.\n\t\t\t\t\tfp = $.mobile.firstPage,\n\n\t\t\t\t\t// Get the id of the first page element if it has one.\n\t\t\t\t\tfpId = fp && fp[0] ? fp[0].id : undefined;\n\n\t\t\t\t\t// The url refers to the first page if the path matches the document and\n\t\t\t\t\t// it either has no hash value, or the hash is exactly equal to the id of the\n\t\t\t\t\t// first page element.\n\t\t\t\t\treturn samePath && ( !u.hash || u.hash === \"#\" || ( fpId && u.hash.replace( /^#/, \"\" ) === fpId ) );\n\t\t\t},\n\n\t\t\tisEmbeddedPage: function( url ) {\n\t\t\t\tvar u = path.parseUrl( url );\n\n\t\t\t\t//if the path is absolute, then we need to compare the url against\n\t\t\t\t//both the documentUrl and the documentBase. The main reason for this\n\t\t\t\t//is that links embedded within external documents will refer to the\n\t\t\t\t//application document, whereas links embedded within the application\n\t\t\t\t//document will be resolved against the document base.\n\t\t\t\tif ( u.protocol !== \"\" ) {\n\t\t\t\t\treturn ( u.hash && ( u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ) ) );\n\t\t\t\t}\n\t\t\t\treturn (/^#/).test( u.href );\n\t\t\t}\n\t\t},\n\n\t\t//will be defined when a link is clicked and given an active class\n\t\t$activeClickedLink = null,\n\n\t\t//urlHistory is purely here to make guesses at whether the back or forward button was clicked\n\t\t//and provide an appropriate transition\n\t\turlHistory = {\n\t\t\t// Array of pages that are visited during a single page load.\n\t\t\t// Each has a url and optional transition, title, and pageUrl (which represents the file path, in cases where URL is obscured, such as dialogs)\n\t\t\tstack: [],\n\n\t\t\t//maintain an index number for the active page in the stack\n\t\t\tactiveIndex: 0,\n\n\t\t\t//get active\n\t\t\tgetActive: function() {\n\t\t\t\treturn urlHistory.stack[ urlHistory.activeIndex ];\n\t\t\t},\n\n\t\t\tgetPrev: function() {\n\t\t\t\treturn urlHistory.stack[ urlHistory.activeIndex - 1 ];\n\t\t\t},\n\n\t\t\tgetNext: function() {\n\t\t\t\treturn urlHistory.stack[ urlHistory.activeIndex + 1 ];\n\t\t\t},\n\n\t\t\t// addNew is used whenever a new page is added\n\t\t\taddNew: function( url, transition, title, pageUrl, role ) {\n\t\t\t\t//if there's forward history, wipe it\n\t\t\t\tif( urlHistory.getNext() ) {\n\t\t\t\t\turlHistory.clearForward();\n\t\t\t\t}\n\n\t\t\t\turlHistory.stack.push( {url : url, transition: transition, title: title, pageUrl: pageUrl, role: role } );\n\n\t\t\t\turlHistory.activeIndex = urlHistory.stack.length - 1;\n\t\t\t},\n\n\t\t\t//wipe urls ahead of active index\n\t\t\tclearForward: function() {\n\t\t\t\turlHistory.stack = urlHistory.stack.slice( 0, urlHistory.activeIndex + 1 );\n\t\t\t},\n\n\t\t\tdirectHashChange: function( opts ) {\n\t\t\t\tvar back , forward, newActiveIndex, prev = this.getActive();\n\n\t\t\t\t// check if url isp in history and if it's ahead or behind current page\n\t\t\t\t$.each( urlHistory.stack, function( i, historyEntry ) {\n\n\t\t\t\t\t//if the url is in the stack, it's a forward or a back\n\t\t\t\t\tif( opts.currentUrl === historyEntry.url ) {\n\t\t\t\t\t\t//define back and forward by whether url is older or newer than current page\n\t\t\t\t\t\tback = i < urlHistory.activeIndex;\n\t\t\t\t\t\tforward = !back;\n\t\t\t\t\t\tnewActiveIndex = i;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// save new page index, null check to prevent falsey 0 result\n\t\t\t\tthis.activeIndex = newActiveIndex !== undefined ? newActiveIndex : this.activeIndex;\n\n\t\t\t\tif( back ) {\n\t\t\t\t\t( opts.either || opts.isBack )( true );\n\t\t\t\t} else if( forward ) {\n\t\t\t\t\t( opts.either || opts.isForward )( false );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t//disable hashchange event listener internally to ignore one change\n\t\t\t//toggled internally when location.hash is updated to match the url of a successful page load\n\t\t\tignoreNextHashChange: false\n\t\t},\n\n\t\t//define first selector to receive focus when a page is shown\n\t\tfocusable = \"[tabindex],a,button:visible,select:visible,input\",\n\n\t\t//queue to hold simultanious page transitions\n\t\tpageTransitionQueue = [],\n\n\t\t//indicates whether or not page is in process of transitioning\n\t\tisPageTransitioning = false,\n\n\t\t//nonsense hash change key for dialogs, so they create a history entry\n\t\tdialogHashKey = \"&ui-state=dialog\",\n\n\t\t//existing base tag?\n\t\t$base = $head.children( \"base\" ),\n\n\t\t//tuck away the original document URL minus any fragment.\n\t\tdocumentUrl = path.parseUrl( location.href ),\n\n\t\t//if the document has an embedded base tag, documentBase is set to its\n\t\t//initial value. If a base tag does not exist, then we default to the documentUrl.\n\t\tdocumentBase = $base.length ? path.parseUrl( path.makeUrlAbsolute( $base.attr( \"href\" ), documentUrl.href ) ) : documentUrl,\n\n\t\t//cache the comparison once.\n\t\tdocumentBaseDiffers = ( documentUrl.hrefNoHash !== documentBase.hrefNoHash );\n\n\t\t//base element management, defined depending on dynamic base tag support\n\t\tvar base = $.support.dynamicBaseTag ? {\n\n\t\t\t//define base element, for use in routing asset urls that are referenced in Ajax-requested markup\n\t\t\telement: ( $base.length ? $base : $( \"<base>\", { href: documentBase.hrefNoHash } ).prependTo( $head ) ),\n\n\t\t\t//set the generated BASE element's href attribute to a new page's base path\n\t\t\tset: function( href ) {\n\t\t\t\tbase.element.attr( \"href\", path.makeUrlAbsolute( href, documentBase ) );\n\t\t\t},\n\n\t\t\t//set the generated BASE element's href attribute to a new page's base path\n\t\t\treset: function() {\n\t\t\t\tbase.element.attr( \"href\", documentBase.hrefNoHash );\n\t\t\t}\n\n\t\t} : undefined;\n\n/*\n\tinternal utility functions\n--------------------------------------*/\n\n\n\t//direct focus to the page title, or otherwise first focusable element\n\t$.mobile.focusPage = function ( page ) {\n\t\tvar autofocus = page.find(\"[autofocus]\"),\n\t\t\tpageTitle = page.find( \".ui-title:eq(0)\" );\n\n\t\tif( autofocus.length ) {\n\t\t\tautofocus.focus();\n\t\t\treturn;\n\t\t}\n\n\t\tif( pageTitle.length ) {\n\t\t\tpageTitle.focus();\n\t\t}\n\t\telse{\n\t\t\tpage.focus();\n\t\t}\n\t}\n\n\t//remove active classes after page transition or error\n\tfunction removeActiveLinkClass( forceRemoval ) {\n\t\tif( !!$activeClickedLink && ( !$activeClickedLink.closest( '.ui-page-active' ).length || forceRemoval ) ) {\n\t\t\t$activeClickedLink.removeClass( $.mobile.activeBtnClass );\n\t\t}\n\t\t$activeClickedLink = null;\n\t}\n\n\tfunction releasePageTransitionLock() {\n\t\tisPageTransitioning = false;\n\t\tif( pageTransitionQueue.length > 0 ) {\n\t\t\t$.mobile.changePage.apply( null, pageTransitionQueue.pop() );\n\t\t}\n\t}\n\n\t// Save the last scroll distance per page, before it is hidden\n\tvar setLastScrollEnabled = true,\n\t\tsetLastScroll, delayedSetLastScroll;\n\n\tsetLastScroll = function() {\n\t\t// this barrier prevents setting the scroll value based on the browser\n\t\t// scrolling the window based on a hashchange\n\t\tif( !setLastScrollEnabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar active = $.mobile.urlHistory.getActive();\n\n\t\tif( active ) {\n\t\t\tvar lastScroll = $window.scrollTop();\n\n\t\t\t// Set active page's lastScroll prop.\n\t\t\t// If the location we're scrolling to is less than minScrollBack, let it go.\n\t\t\tactive.lastScroll = lastScroll < $.mobile.minScrollBack ? $.mobile.defaultHomeScroll : lastScroll;\n\t\t}\n\t};\n\n\t// bind to scrollstop to gather scroll position. The delay allows for the hashchange\n\t// event to fire and disable scroll recording in the case where the browser scrolls\n\t// to the hash targets location (sometimes the top of the page). once pagechange fires\n\t// getLastScroll is again permitted to operate\n\tdelayedSetLastScroll = function() {\n\t\tsetTimeout( setLastScroll, 100 );\n\t};\n\n\t// disable an scroll setting when a hashchange has been fired, this only works\n\t// because the recording of the scroll position is delayed for 100ms after\n\t// the browser might have changed the position because of the hashchange\n\t$window.bind( $.support.pushState ? \"popstate\" : \"hashchange\", function() {\n\t \tsetLastScrollEnabled = false;\n\t});\n\n\t// handle initial hashchange from chrome :(\n\t$window.one( $.support.pushState ? \"popstate\" : \"hashchange\", function() {\n\t\tsetLastScrollEnabled = true;\n\t});\n\n\t// wait until the mobile page container has been determined to bind to pagechange\n\t$window.one( \"pagecontainercreate\", function(){\n\t\t// once the page has changed, re-enable the scroll recording\n\t\t$.mobile.pageContainer.bind( \"pagechange\", function() {\n\n\t \t\tsetLastScrollEnabled = true;\n\n\t\t\t// remove any binding that previously existed on the get scroll\n\t\t\t// which may or may not be different than the scroll element determined for\n\t\t\t// this page previously\n\t\t\t$window.unbind( \"scrollstop\", delayedSetLastScroll );\n\n\t\t\t// determine and bind to the current scoll element which may be the window\n\t\t\t// or in the case of touch overflow the element with touch overflow\n\t\t\t$window.bind( \"scrollstop\", delayedSetLastScroll );\n\t\t});\n\t});\n\n\t// bind to scrollstop for the first page as \"pagechange\" won't be fired in that case\n\t$window.bind( \"scrollstop\", delayedSetLastScroll );\n\n\t//function for transitioning between two existing pages\n\tfunction transitionPages( toPage, fromPage, transition, reverse ) {\n\n\t\tif( fromPage ) {\n\t\t\t//trigger before show/hide events\n\t\t\tfromPage.data( \"page\" )._trigger( \"beforehide\", null, { nextPage: toPage } );\n\t\t}\n\n\t\ttoPage.data( \"page\" )._trigger( \"beforeshow\", null, { prevPage: fromPage || $( \"\" ) } );\n\n\t\t//clear page loader\n\t\t$.mobile.hidePageLoadingMsg();\n\t\t\n\t\t// If transition is defined, check if css 3D transforms are supported, and if not, if a fallback is specified\n\t\tif( transition && !$.support.cssTransform3d && $.mobile.transitionFallbacks[ transition ] ){\n\t\t\ttransition = $.mobile.transitionFallbacks[ transition ];\n\t\t}\n\t\t\n\t\t//find the transition handler for the specified transition. If there\n\t\t//isn't one in our transitionHandlers dictionary, use the default one.\n\t\t//call the handler immediately to kick-off the transition.\n\t\tvar th = $.mobile.transitionHandlers[ transition || \"default\" ] || $.mobile.defaultTransitionHandler,\n\t\t\tpromise = th( transition, reverse, toPage, fromPage );\n\n\t\tpromise.done(function() {\n\n\t\t\t//trigger show/hide events\n\t\t\tif( fromPage ) {\n\t\t\t\tfromPage.data( \"page\" )._trigger( \"hide\", null, { nextPage: toPage } );\n\t\t\t}\n\n\t\t\t//trigger pageshow, define prevPage as either fromPage or empty jQuery obj\n\t\t\ttoPage.data( \"page\" )._trigger( \"show\", null, { prevPage: fromPage || $( \"\" ) } );\n\t\t});\n\n\t\treturn promise;\n\t}\n\n\t//simply set the active page's minimum height to screen height, depending on orientation\n\tfunction getScreenHeight(){\n\t\t// Native innerHeight returns more accurate value for this across platforms, \n\t\t// jQuery version is here as a normalized fallback for platforms like Symbian\n\t\treturn window.innerHeight || $( window ).height();\n\t}\n\n\t$.mobile.getScreenHeight = getScreenHeight;\n\n\t//simply set the active page's minimum height to screen height, depending on orientation\n\tfunction resetActivePageHeight(){\n\t\tvar aPage = $( \".\" + $.mobile.activePageClass ),\n\t\t\taPagePadT = parseFloat( aPage.css( \"padding-top\" ) ),\n\t\t\taPagePadB = parseFloat( aPage.css( \"padding-bottom\" ) );\n\t\t\t\t\n\t\taPage.css( \"min-height\", getScreenHeight() - aPagePadT - aPagePadB );\n\t}\n\n\t//shared page enhancements\n\tfunction enhancePage( $page, role ) {\n\t\t// If a role was specified, make sure the data-role attribute\n\t\t// on the page element is in sync.\n\t\tif( role ) {\n\t\t\t$page.attr( \"data-\" + $.mobile.ns + \"role\", role );\n\t\t}\n\n\t\t//run page plugin\n\t\t$page.page();\n\t}\n\n/* exposed $.mobile methods\t */\n\n\t//animation complete callback\n\t$.fn.animationComplete = function( callback ) {\n\t\tif( $.support.cssTransitions ) {\n\t\t\treturn $( this ).one( 'webkitAnimationEnd animationend', callback );\n\t\t}\n\t\telse{\n\t\t\t// defer execution for consistency between webkit/non webkit\n\t\t\tsetTimeout( callback, 0 );\n\t\t\treturn $( this );\n\t\t}\n\t};\n\n\t//expose path object on $.mobile\n\t$.mobile.path = path;\n\n\t//expose base object on $.mobile\n\t$.mobile.base = base;\n\n\t//history stack\n\t$.mobile.urlHistory = urlHistory;\n\n\t$.mobile.dialogHashKey = dialogHashKey;\n\n\n\n\t//enable cross-domain page support\n\t$.mobile.allowCrossDomainPages = false;\n\n\t//return the original document url\n\t$.mobile.getDocumentUrl = function(asParsedObject) {\n\t\treturn asParsedObject ? $.extend( {}, documentUrl ) : documentUrl.href;\n\t};\n\n\t//return the original document base url\n\t$.mobile.getDocumentBase = function(asParsedObject) {\n\t\treturn asParsedObject ? $.extend( {}, documentBase ) : documentBase.href;\n\t};\n\n\t$.mobile._bindPageRemove = function() {\n\t\tvar page = $(this);\n\n\t\t// when dom caching is not enabled or the page is embedded bind to remove the page on hide\n\t\tif( !page.data(\"page\").options.domCache\n\t\t\t\t&& page.is(\":jqmData(external-page='true')\") ) {\n\n\t\t\tpage.bind( 'pagehide.remove', function() {\n\t\t\t\tvar $this = $( this ),\n\t\t\t\t\tprEvent = new $.Event( \"pageremove\" );\n\n\t\t\t\t$this.trigger( prEvent );\n\n\t\t\t\tif( !prEvent.isDefaultPrevented() ){\n\t\t\t\t\t$this.removeWithDependents();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// Load a page into the DOM.\n\t$.mobile.loadPage = function( url, options ) {\n\t\t// This function uses deferred notifications to let callers\n\t\t// know when the page is done loading, or if an error has occurred.\n\t\tvar deferred = $.Deferred(),\n\n\t\t\t// The default loadPage options with overrides specified by\n\t\t\t// the caller.\n\t\t\tsettings = $.extend( {}, $.mobile.loadPage.defaults, options ),\n\n\t\t\t// The DOM element for the page after it has been loaded.\n\t\t\tpage = null,\n\n\t\t\t// If the reloadPage option is true, and the page is already\n\t\t\t// in the DOM, dupCachedPage will be set to the page element\n\t\t\t// so that it can be removed after the new version of the\n\t\t\t// page is loaded off the network.\n\t\t\tdupCachedPage = null,\n\n\t\t\t// determine the current base url\n\t\t\tfindBaseWithDefault = function(){\n\t\t\t\tvar closestBase = ( $.mobile.activePage && getClosestBaseUrl( $.mobile.activePage ) );\n\t\t\t\treturn closestBase || documentBase.hrefNoHash;\n\t\t\t},\n\n\t\t\t// The absolute version of the URL passed into the function. This\n\t\t\t// version of the URL may contain dialog/subpage params in it.\n\t\t\tabsUrl = path.makeUrlAbsolute( url, findBaseWithDefault() );\n\n\n\t\t// If the caller provided data, and we're using \"get\" request,\n\t\t// append the data to the URL.\n\t\tif ( settings.data && settings.type === \"get\" ) {\n\t\t\tabsUrl = path.addSearchParams( absUrl, settings.data );\n\t\t\tsettings.data = undefined;\n\t\t}\n\n\t\t// If the caller is using a \"post\" request, reloadPage must be true\n\t\tif(  settings.data && settings.type === \"post\" ){\n\t\t\tsettings.reloadPage = true;\n\t\t}\n\n\t\t\t// The absolute version of the URL minus any dialog/subpage params.\n\t\t\t// In otherwords the real URL of the page to be loaded.\n\t\tvar fileUrl = path.getFilePath( absUrl ),\n\n\t\t\t// The version of the Url actually stored in the data-url attribute of\n\t\t\t// the page. For embedded pages, it is just the id of the page. For pages\n\t\t\t// within the same domain as the document base, it is the site relative\n\t\t\t// path. For cross-domain pages (Phone Gap only) the entire absolute Url\n\t\t\t// used to load the page.\n\t\t\tdataUrl = path.convertUrlToDataUrl( absUrl );\n\n\t\t// Make sure we have a pageContainer to work with.\n\t\tsettings.pageContainer = settings.pageContainer || $.mobile.pageContainer;\n\n\t\t// Check to see if the page already exists in the DOM.\n\t\tpage = settings.pageContainer.children( \":jqmData(url='\" + dataUrl + \"')\" );\n\n\t\t// If we failed to find the page, check to see if the url is a\n\t\t// reference to an embedded page. If so, it may have been dynamically\n\t\t// injected by a developer, in which case it would be lacking a data-url\n\t\t// attribute and in need of enhancement.\n\t\tif ( page.length === 0 && dataUrl && !path.isPath( dataUrl ) ) {\n\t\t\tpage = settings.pageContainer.children( \"#\" + dataUrl )\n\t\t\t\t.attr( \"data-\" + $.mobile.ns + \"url\", dataUrl );\n\t\t}\n\n\t\t// If we failed to find a page in the DOM, check the URL to see if it\n\t\t// refers to the first page in the application. If it isn't a reference\n\t\t// to the first page and refers to non-existent embedded page, error out.\n\t\tif ( page.length === 0 ) {\n\t\t\tif ( $.mobile.firstPage && path.isFirstPageUrl( fileUrl ) ) {\n\t\t\t\t// Check to make sure our cached-first-page is actually\n\t\t\t\t// in the DOM. Some user deployed apps are pruning the first\n\t\t\t\t// page from the DOM for various reasons, we check for this\n\t\t\t\t// case here because we don't want a first-page with an id\n\t\t\t\t// falling through to the non-existent embedded page error\n\t\t\t\t// case. If the first-page is not in the DOM, then we let\n\t\t\t\t// things fall through to the ajax loading code below so\n\t\t\t\t// that it gets reloaded.\n\t\t\t\tif ( $.mobile.firstPage.parent().length ) {\n\t\t\t\t\tpage = $( $.mobile.firstPage );\n\t\t\t\t}\n\t\t\t} else if ( path.isEmbeddedPage( fileUrl )  ) {\n\t\t\t\tdeferred.reject( absUrl, options );\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\t\t}\n\n\t\t// Reset base to the default document base.\n\t\tif ( base ) {\n\t\t\tbase.reset();\n\t\t}\n\n\t\t// If the page we are interested in is already in the DOM,\n\t\t// and the caller did not indicate that we should force a\n\t\t// reload of the file, we are done. Otherwise, track the\n\t\t// existing page as a duplicated.\n\t\tif ( page.length ) {\n\t\t\tif ( !settings.reloadPage ) {\n\t\t\t\tenhancePage( page, settings.role );\n\t\t\t\tdeferred.resolve( absUrl, options, page );\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\t\t\tdupCachedPage = page;\n\t\t}\n\n\t\tvar mpc = settings.pageContainer,\n\t\t\tpblEvent = new $.Event( \"pagebeforeload\" ),\n\t\t\ttriggerData = { url: url, absUrl: absUrl, dataUrl: dataUrl, deferred: deferred, options: settings };\n\n\t\t// Let listeners know we're about to load a page.\n\t\tmpc.trigger( pblEvent, triggerData );\n\n\t\t// If the default behavior is prevented, stop here!\n\t\tif( pblEvent.isDefaultPrevented() ){\n\t\t\treturn deferred.promise();\n\t\t}\n\n\t\tif ( settings.showLoadMsg ) {\n\n\t\t\t// This configurable timeout allows cached pages a brief delay to load without showing a message\n\t\t\tvar loadMsgDelay = setTimeout(function(){\n\t\t\t\t\t$.mobile.showPageLoadingMsg();\n\t\t\t\t}, settings.loadMsgDelay ),\n\n\t\t\t\t// Shared logic for clearing timeout and removing message.\n\t\t\t\thideMsg = function(){\n\n\t\t\t\t\t// Stop message show timer\n\t\t\t\t\tclearTimeout( loadMsgDelay );\n\n\t\t\t\t\t// Hide loading message\n\t\t\t\t\t$.mobile.hidePageLoadingMsg();\n\t\t\t\t};\n\t\t}\n\n\t\tif ( !( $.mobile.allowCrossDomainPages || path.isSameDomain( documentUrl, absUrl ) ) ) {\n\t\t\tdeferred.reject( absUrl, options );\n\t\t} else {\n\t\t\t// Load the new page.\n\t\t\t$.ajax({\n\t\t\t\turl: fileUrl,\n\t\t\t\ttype: settings.type,\n\t\t\t\tdata: settings.data,\n\t\t\t\tdataType: \"html\",\n\t\t\t\tsuccess: function( html, textStatus, xhr ) {\n\t\t\t\t\t//pre-parse html to check for a data-url,\n\t\t\t\t\t//use it as the new fileUrl, base path, etc\n\t\t\t\t\tvar all = $( \"<div></div>\" ),\n\n\t\t\t\t\t\t//page title regexp\n\t\t\t\t\t\tnewPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1,\n\n\t\t\t\t\t\t// TODO handle dialogs again\n\t\t\t\t\t\tpageElemRegex = new RegExp( \"(<[^>]+\\\\bdata-\" + $.mobile.ns + \"role=[\\\"']?page[\\\"']?[^>]*>)\" ),\n\t\t\t\t\t\tdataUrlRegex = new RegExp( \"\\\\bdata-\" + $.mobile.ns + \"url=[\\\"']?([^\\\"'>]*)[\\\"']?\" );\n\n\n\t\t\t\t\t// data-url must be provided for the base tag so resource requests can be directed to the\n\t\t\t\t\t// correct url. loading into a temprorary element makes these requests immediately\n\t\t\t\t\tif( pageElemRegex.test( html )\n\t\t\t\t\t\t\t&& RegExp.$1\n\t\t\t\t\t\t\t&& dataUrlRegex.test( RegExp.$1 )\n\t\t\t\t\t\t\t&& RegExp.$1 ) {\n\t\t\t\t\t\turl = fileUrl = path.getFilePath( RegExp.$1 );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( base ) {\n\t\t\t\t\t\tbase.set( fileUrl );\n\t\t\t\t\t}\n\n\t\t\t\t\t//workaround to allow scripts to execute when included in page divs\n\t\t\t\t\tall.get( 0 ).innerHTML = html;\n\t\t\t\t\tpage = all.find( \":jqmData(role='page'), :jqmData(role='dialog')\" ).first();\n\n\t\t\t\t\t//if page elem couldn't be found, create one and insert the body element's contents\n\t\t\t\t\tif( !page.length ){\n\t\t\t\t\t\tpage = $( \"<div data-\" + $.mobile.ns + \"role='page'>\" + html.split( /<\\/?body[^>]*>/gmi )[1] + \"</div>\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( newPageTitle && !page.jqmData( \"title\" ) ) {\n\t\t\t\t\t\tif ( ~newPageTitle.indexOf( \"&\" ) ) {\n\t\t\t\t\t\t\tnewPageTitle = $( \"<div>\" + newPageTitle + \"</div>\" ).text();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpage.jqmData( \"title\", newPageTitle );\n\t\t\t\t\t}\n\n\t\t\t\t\t//rewrite src and href attrs to use a base url\n\t\t\t\t\tif( !$.support.dynamicBaseTag ) {\n\t\t\t\t\t\tvar newPath = path.get( fileUrl );\n\t\t\t\t\t\tpage.find( \"[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]\" ).each(function() {\n\t\t\t\t\t\t\tvar thisAttr = $( this ).is( '[href]' ) ? 'href' :\n\t\t\t\t\t\t\t\t\t$(this).is('[src]') ? 'src' : 'action',\n\t\t\t\t\t\t\t\tthisUrl = $( this ).attr( thisAttr );\n\n\t\t\t\t\t\t\t// XXX_jblas: We need to fix this so that it removes the document\n\t\t\t\t\t\t\t//            base URL, and then prepends with the new page URL.\n\t\t\t\t\t\t\t//if full path exists and is same, chop it - helps IE out\n\t\t\t\t\t\t\tthisUrl = thisUrl.replace( location.protocol + '//' + location.host + location.pathname, '' );\n\n\t\t\t\t\t\t\tif( !/^(\\w+:|#|\\/)/.test( thisUrl ) ) {\n\t\t\t\t\t\t\t\t$( this ).attr( thisAttr, newPath + thisUrl );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t//append to page and enhance\n\t\t\t\t\t// TODO taging a page with external to make sure that embedded pages aren't removed\n\t\t\t\t\t//      by the various page handling code is bad. Having page handling code in many\n\t\t\t\t\t//      places is bad. Solutions post 1.0\n\t\t\t\t\tpage\n\t\t\t\t\t\t.attr( \"data-\" + $.mobile.ns + \"url\", path.convertUrlToDataUrl( fileUrl ) )\n\t\t\t\t\t\t.attr( \"data-\" + $.mobile.ns + \"external-page\", true )\n\t\t\t\t\t\t.appendTo( settings.pageContainer );\n\n\t\t\t\t\t// wait for page creation to leverage options defined on widget\n\t\t\t\t\tpage.one( 'pagecreate', $.mobile._bindPageRemove );\n\n\t\t\t\t\tenhancePage( page, settings.role );\n\n\t\t\t\t\t// Enhancing the page may result in new dialogs/sub pages being inserted\n\t\t\t\t\t// into the DOM. If the original absUrl refers to a sub-page, that is the\n\t\t\t\t\t// real page we are interested in.\n\t\t\t\t\tif ( absUrl.indexOf( \"&\" + $.mobile.subPageUrlKey ) > -1 ) {\n\t\t\t\t\t\tpage = settings.pageContainer.children( \":jqmData(url='\" + dataUrl + \"')\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t//bind pageHide to removePage after it's hidden, if the page options specify to do so\n\n\t\t\t\t\t// Remove loading message.\n\t\t\t\t\tif ( settings.showLoadMsg ) {\n\t\t\t\t\t\thideMsg();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add the page reference and xhr to our triggerData.\n\t\t\t\t\ttriggerData.xhr = xhr;\n\t\t\t\t\ttriggerData.textStatus = textStatus;\n\t\t\t\t\ttriggerData.page = page;\n\n\t\t\t\t\t// Let listeners know the page loaded successfully.\n\t\t\t\t\tsettings.pageContainer.trigger( \"pageload\", triggerData );\n\n\t\t\t\t\tdeferred.resolve( absUrl, options, page, dupCachedPage );\n\t\t\t\t},\n\t\t\t\terror: function( xhr, textStatus, errorThrown ) {\n\t\t\t\t\t//set base back to current path\n\t\t\t\t\tif( base ) {\n\t\t\t\t\t\tbase.set( path.get() );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add error info to our triggerData.\n\t\t\t\t\ttriggerData.xhr = xhr;\n\t\t\t\t\ttriggerData.textStatus = textStatus;\n\t\t\t\t\ttriggerData.errorThrown = errorThrown;\n\n\t\t\t\t\tvar plfEvent = new $.Event( \"pageloadfailed\" );\n\n\t\t\t\t\t// Let listeners know the page load failed.\n\t\t\t\t\tsettings.pageContainer.trigger( plfEvent, triggerData );\n\n\t\t\t\t\t// If the default behavior is prevented, stop here!\n\t\t\t\t\t// Note that it is the responsibility of the listener/handler\n\t\t\t\t\t// that called preventDefault(), to resolve/reject the\n\t\t\t\t\t// deferred object within the triggerData.\n\t\t\t\t\tif( plfEvent.isDefaultPrevented() ){\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove loading message.\n\t\t\t\t\tif ( settings.showLoadMsg ) {\n\n\t\t\t\t\t\t// Remove loading message.\n\t\t\t\t\t\thideMsg();\n\n\t\t\t\t\t\t// show error message\n\t\t\t\t\t\t$.mobile.showPageLoadingMsg( $.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true );\n\n\t\t\t\t\t\t// hide after delay\n\t\t\t\t\t\tsetTimeout( $.mobile.hidePageLoadingMsg, 1500 );\n\t\t\t\t\t}\n\n\t\t\t\t\tdeferred.reject( absUrl, options );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn deferred.promise();\n\t};\n\n\t$.mobile.loadPage.defaults = {\n\t\ttype: \"get\",\n\t\tdata: undefined,\n\t\treloadPage: false,\n\t\trole: undefined, // By default we rely on the role defined by the @data-role attribute.\n\t\tshowLoadMsg: false,\n\t\tpageContainer: undefined,\n\t\tloadMsgDelay: 50 // This delay allows loads that pull from browser cache to occur without showing the loading message.\n\t};\n\n\t// Show a specific page in the page container.\n\t$.mobile.changePage = function( toPage, options ) {\n\t\t// If we are in the midst of a transition, queue the current request.\n\t\t// We'll call changePage() once we're done with the current transition to\n\t\t// service the request.\n\t\tif( isPageTransitioning ) {\n\t\t\tpageTransitionQueue.unshift( arguments );\n\t\t\treturn;\n\t\t}\n\n\t\tvar settings = $.extend( {}, $.mobile.changePage.defaults, options );\n\n\t\t// Make sure we have a pageContainer to work with.\n\t\tsettings.pageContainer = settings.pageContainer || $.mobile.pageContainer;\n\n\t\t// Make sure we have a fromPage.\n\t\tsettings.fromPage = settings.fromPage || $.mobile.activePage;\n\n\t\tvar mpc = settings.pageContainer,\n\t\t\tpbcEvent = new $.Event( \"pagebeforechange\" ),\n\t\t\ttriggerData = { toPage: toPage, options: settings };\n\n\t\t// Let listeners know we're about to change the current page.\n\t\tmpc.trigger( pbcEvent, triggerData );\n\n\t\t// If the default behavior is prevented, stop here!\n\t\tif( pbcEvent.isDefaultPrevented() ){\n\t\t\treturn;\n\t\t}\n\n\t\t// We allow \"pagebeforechange\" observers to modify the toPage in the trigger\n\t\t// data to allow for redirects. Make sure our toPage is updated.\n\n\t\ttoPage = triggerData.toPage;\n\n\t\t// Set the isPageTransitioning flag to prevent any requests from\n\t\t// entering this method while we are in the midst of loading a page\n\t\t// or transitioning.\n\n\t\tisPageTransitioning = true;\n\n\t\t// If the caller passed us a url, call loadPage()\n\t\t// to make sure it is loaded into the DOM. We'll listen\n\t\t// to the promise object it returns so we know when\n\t\t// it is done loading or if an error ocurred.\n\t\tif ( typeof toPage == \"string\" ) {\n\t\t\t$.mobile.loadPage( toPage, settings )\n\t\t\t\t.done(function( url, options, newPage, dupCachedPage ) {\n\t\t\t\t\tisPageTransitioning = false;\n\t\t\t\t\toptions.duplicateCachedPage = dupCachedPage;\n\t\t\t\t\t$.mobile.changePage( newPage, options );\n\t\t\t\t})\n\t\t\t\t.fail(function( url, options ) {\n\t\t\t\t\tisPageTransitioning = false;\n\n\t\t\t\t\t//clear out the active button state\n\t\t\t\t\tremoveActiveLinkClass( true );\n\n\t\t\t\t\t//release transition lock so navigation is free again\n\t\t\t\t\treleasePageTransitionLock();\n\t\t\t\t\tsettings.pageContainer.trigger( \"pagechangefailed\", triggerData );\n\t\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are going to the first-page of the application, we need to make\n\t\t// sure settings.dataUrl is set to the application document url. This allows\n\t\t// us to avoid generating a document url with an id hash in the case where the\n\t\t// first-page of the document has an id attribute specified.\n\t\tif ( toPage[ 0 ] === $.mobile.firstPage[ 0 ] && !settings.dataUrl ) {\n\t\t\tsettings.dataUrl = documentUrl.hrefNoHash;\n\t\t}\n\n\t\t// The caller passed us a real page DOM element. Update our\n\t\t// internal state and then trigger a transition to the page.\n\t\tvar fromPage = settings.fromPage,\n\t\t\turl = ( settings.dataUrl && path.convertUrlToDataUrl( settings.dataUrl ) ) || toPage.jqmData( \"url\" ),\n\t\t\t// The pageUrl var is usually the same as url, except when url is obscured as a dialog url. pageUrl always contains the file path\n\t\t\tpageUrl = url,\n\t\t\tfileUrl = path.getFilePath( url ),\n\t\t\tactive = urlHistory.getActive(),\n\t\t\tactiveIsInitialPage = urlHistory.activeIndex === 0,\n\t\t\thistoryDir = 0,\n\t\t\tpageTitle = document.title,\n\t\t\tisDialog = settings.role === \"dialog\" || toPage.jqmData( \"role\" ) === \"dialog\";\n\n\t\t// By default, we prevent changePage requests when the fromPage and toPage\n\t\t// are the same element, but folks that generate content manually/dynamically\n\t\t// and reuse pages want to be able to transition to the same page. To allow\n\t\t// this, they will need to change the default value of allowSamePageTransition\n\t\t// to true, *OR*, pass it in as an option when they manually call changePage().\n\t\t// It should be noted that our default transition animations assume that the\n\t\t// formPage and toPage are different elements, so they may behave unexpectedly.\n\t\t// It is up to the developer that turns on the allowSamePageTransitiona option\n\t\t// to either turn off transition animations, or make sure that an appropriate\n\t\t// animation transition is used.\n\t\tif( fromPage && fromPage[0] === toPage[0] && !settings.allowSamePageTransition ) {\n\t\t\tisPageTransitioning = false;\n\t\t\tmpc.trigger( \"pagechange\", triggerData );\n\t\t\treturn;\n\t\t}\n\n\t\t// We need to make sure the page we are given has already been enhanced.\n\t\tenhancePage( toPage, settings.role );\n\n\t\t// If the changePage request was sent from a hashChange event, check to see if the\n\t\t// page is already within the urlHistory stack. If so, we'll assume the user hit\n\t\t// the forward/back button and will try to match the transition accordingly.\n\t\tif( settings.fromHashChange ) {\n\t\t\turlHistory.directHashChange({\n\t\t\t\tcurrentUrl:\turl,\n\t\t\t\tisBack:\t\tfunction() { historyDir = -1; },\n\t\t\t\tisForward:\tfunction() { historyDir = 1; }\n\t\t\t});\n\t\t}\n\n\t\t// Kill the keyboard.\n\t\t// XXX_jblas: We need to stop crawling the entire document to kill focus. Instead,\n\t\t//            we should be tracking focus with a delegate() handler so we already have\n\t\t//            the element in hand at this point.\n\t\t// Wrap this in a try/catch block since IE9 throw \"Unspecified error\" if document.activeElement\n\t\t// is undefined when we are in an IFrame.\n\t\ttry {\n\t\t\tif(document.activeElement && document.activeElement.nodeName.toLowerCase() != 'body') {\n\t\t\t\t$(document.activeElement).blur();\n\t\t\t} else {\n\t\t\t\t$( \"input:focus, textarea:focus, select:focus\" ).blur();\n\t\t\t}\n\t\t} catch(e) {}\n\n\t\t// If we're displaying the page as a dialog, we don't want the url\n\t\t// for the dialog content to be used in the hash. Instead, we want\n\t\t// to append the dialogHashKey to the url of the current page.\n\t\tif ( isDialog && active ) {\n\t\t\t// on the initial page load active.url is undefined and in that case should\n\t\t\t// be an empty string. Moving the undefined -> empty string back into\n\t\t\t// urlHistory.addNew seemed imprudent given undefined better represents\n\t\t\t// the url state\n\t\t\turl = ( active.url || \"\" ) + dialogHashKey;\n\t\t}\n\n\t\t// Set the location hash.\n\t\tif( settings.changeHash !== false && url ) {\n\t\t\t//disable hash listening temporarily\n\t\t\turlHistory.ignoreNextHashChange = true;\n\t\t\t//update hash and history\n\t\t\tpath.set( url );\n\t\t}\n\n\t\t// if title element wasn't found, try the page div data attr too\n\t\t// If this is a deep-link or a reload ( active === undefined ) then just use pageTitle\n\t\tvar newPageTitle = ( !active )? pageTitle : toPage.jqmData( \"title\" ) || toPage.children(\":jqmData(role='header')\").find(\".ui-title\" ).getEncodedText();\n\t\tif( !!newPageTitle && pageTitle == document.title ) {\n\t\t\tpageTitle = newPageTitle;\n\t\t}\n\t\tif ( !toPage.jqmData( \"title\" ) ) {\n\t\t\ttoPage.jqmData( \"title\", pageTitle );\n\t\t}\n\n\t\t// Make sure we have a transition defined.\n\t\tsettings.transition = settings.transition\n\t\t\t|| ( ( historyDir && !activeIsInitialPage ) ? active.transition : undefined )\n\t\t\t|| ( isDialog ? $.mobile.defaultDialogTransition : $.mobile.defaultPageTransition );\n\n\t\t//add page to history stack if it's not back or forward\n\t\tif( !historyDir ) {\n\t\t\turlHistory.addNew( url, settings.transition, pageTitle, pageUrl, settings.role );\n\t\t}\n\n\t\t//set page title\n\t\tdocument.title = urlHistory.getActive().title;\n\n\t\t//set \"toPage\" as activePage\n\t\t$.mobile.activePage = toPage;\n\n\t\t// If we're navigating back in the URL history, set reverse accordingly.\n\t\tsettings.reverse = settings.reverse || historyDir < 0;\n\n\t\ttransitionPages( toPage, fromPage, settings.transition, settings.reverse )\n\t\t\t.done(function( name, reverse, $to, $from, alreadyFocused ) {\n\t\t\t\tremoveActiveLinkClass();\n\n\t\t\t\t//if there's a duplicateCachedPage, remove it from the DOM now that it's hidden\n\t\t\t\tif ( settings.duplicateCachedPage ) {\n\t\t\t\t\tsettings.duplicateCachedPage.remove();\n\t\t\t\t}\n\n\t\t\t\t// Send focus to the newly shown page. Moved from promise .done binding in transitionPages\n\t\t\t\t// itself to avoid ie bug that reports offsetWidth as > 0 (core check for visibility)\n\t\t\t\t// despite visibility: hidden addresses issue #2965\n\t\t\t\t// https://github.com/jquery/jquery-mobile/issues/2965\n\t\t\t\tif( !alreadyFocused ){\n\t\t\t\t\t$.mobile.focusPage( toPage );\n\t\t\t\t}\n\n\t\t\t\treleasePageTransitionLock();\n\n\t\t\t\t// Let listeners know we're all done changing the current page.\n\t\t\t\tmpc.trigger( \"pagechange\", triggerData );\n\t\t\t});\n\t};\n\n\t$.mobile.changePage.defaults = {\n\t\ttransition: undefined,\n\t\treverse: false,\n\t\tchangeHash: true,\n\t\tfromHashChange: false,\n\t\trole: undefined, // By default we rely on the role defined by the @data-role attribute.\n\t\tduplicateCachedPage: undefined,\n\t\tpageContainer: undefined,\n\t\tshowLoadMsg: true, //loading message shows by default when pages are being fetched during changePage\n\t\tdataUrl: undefined,\n\t\tfromPage: undefined,\n\t\tallowSamePageTransition: false\n\t};\n\n/* Event Bindings - hashchange, submit, and click */\n\tfunction findClosestLink( ele )\n\t{\n\t\twhile ( ele ) {\n\t\t\t// Look for the closest element with a nodeName of \"a\".\n\t\t\t// Note that we are checking if we have a valid nodeName\n\t\t\t// before attempting to access it. This is because the\n\t\t\t// node we get called with could have originated from within\n\t\t\t// an embedded SVG document where some symbol instance elements\n\t\t\t// don't have nodeName defined on them, or strings are of type\n\t\t\t// SVGAnimatedString.\n\t\t\tif ( ( typeof ele.nodeName === \"string\" ) && ele.nodeName.toLowerCase() == \"a\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tele = ele.parentNode;\n\t\t}\n\t\treturn ele;\n\t}\n\n\t// The base URL for any given element depends on the page it resides in.\n\tfunction getClosestBaseUrl( ele )\n\t{\n\t\t// Find the closest page and extract out its url.\n\t\tvar url = $( ele ).closest( \".ui-page\" ).jqmData( \"url\" ),\n\t\t\tbase = documentBase.hrefNoHash;\n\n\t\tif ( !url || !path.isPath( url ) ) {\n\t\t\turl = base;\n\t\t}\n\n\t\treturn path.makeUrlAbsolute( url, base);\n\t}\n\n\n\t//The following event bindings should be bound after mobileinit has been triggered\n\t//the following function is called in the init file\n\t$.mobile._registerInternalEvents = function(){\n\n\t\t//bind to form submit events, handle with Ajax\n\t\t$( document ).delegate( \"form\", \"submit\", function( event ) {\n\t\t\tvar $this = $( this );\n\n\t\t\tif( !$.mobile.ajaxEnabled ||\n\t\t\t\t\t// test that the form is, itself, ajax false\n\t\t\t\t\t$this.is(\":jqmData(ajax='false')\") ||\n\t\t\t\t\t// test that $.mobile.ignoreContentEnabled is set and\n\t\t\t\t\t// the form or one of it's parents is ajax=false\n\t\t\t\t\t!$this.jqmHijackable().length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar type = $this.attr( \"method\" ),\n\t\t\t\ttarget = $this.attr( \"target\" ),\n\t\t\t\turl = $this.attr( \"action\" );\n\n\t\t\t// If no action is specified, browsers default to using the\n\t\t\t// URL of the document containing the form. Since we dynamically\n\t\t\t// pull in pages from external documents, the form should submit\n\t\t\t// to the URL for the source document of the page containing\n\t\t\t// the form.\n\t\t\tif ( !url ) {\n\t\t\t\t// Get the @data-url for the page containing the form.\n\t\t\t\turl = getClosestBaseUrl( $this );\n\t\t\t\tif ( url === documentBase.hrefNoHash ) {\n\t\t\t\t\t// The url we got back matches the document base,\n\t\t\t\t\t// which means the page must be an internal/embedded page,\n\t\t\t\t\t// so default to using the actual document url as a browser\n\t\t\t\t\t// would.\n\t\t\t\t\turl = documentUrl.hrefNoSearch;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\turl = path.makeUrlAbsolute(  url, getClosestBaseUrl($this) );\n\n\t\t\t//external submits use regular HTTP\n\t\t\tif( path.isExternal( url ) || target ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$.mobile.changePage(\n\t\t\t\turl,\n\t\t\t\t{\n\t\t\t\t\ttype:\t\ttype && type.length && type.toLowerCase() || \"get\",\n\t\t\t\t\tdata:\t\t$this.serialize(),\n\t\t\t\t\ttransition:\t$this.jqmData( \"transition\" ),\n\t\t\t\t\tdirection:\t$this.jqmData( \"direction\" ),\n\t\t\t\t\treloadPage:\ttrue\n\t\t\t\t}\n\t\t\t);\n\t\t\tevent.preventDefault();\n\t\t});\n\n\t\t//add active state on vclick\n\t\t$( document ).bind( \"vclick\", function( event ) {\n\t\t\t// if this isn't a left click we don't care. Its important to note\n\t\t\t// that when the virtual event is generated it will create the which attr\n\t\t\tif ( event.which > 1 || !$.mobile.linkBindingEnabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar link = findClosestLink( event.target );\n\n\t\t\t// split from the previous return logic to avoid find closest where possible\n\t\t\t// TODO teach $.mobile.hijackable to operate on raw dom elements so the link wrapping\n\t\t\t// can be avoided\n\t\t\tif ( !$(link).jqmHijackable().length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( link ) {\n\t\t\t\tif ( path.parseUrl( link.getAttribute( \"href\" ) || \"#\" ).hash !== \"#\" ) {\n\t\t\t\t\tremoveActiveLinkClass( true );\n\t\t\t\t\t$activeClickedLink = $( link ).closest( \".ui-btn\" ).not( \".ui-disabled\" );\n\t\t\t\t\t$activeClickedLink.addClass( $.mobile.activeBtnClass );\n\t\t\t\t\t$( \".\" + $.mobile.activePageClass + \" .ui-btn\" ).not( link ).blur();\n\n\t\t\t\t\t// By caching the href value to data and switching the href to a #, we can avoid address bar showing in iOS. The click handler resets the href during its initial steps if this data is present\n\t\t\t\t\t$( link )\n\t\t\t\t\t\t.jqmData( \"href\", $( link  ).attr( \"href\" )  )\n\t\t\t\t\t\t.attr( \"href\", \"#\" );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// click routing - direct to HTTP or Ajax, accordingly\n\t\t$( document ).bind( \"click\", function( event ) {\n\t\t\tif( !$.mobile.linkBindingEnabled ){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar link = findClosestLink( event.target ), $link = $( link ), httpCleanup;\n\n\t\t\t// If there is no link associated with the click or its not a left\n\t\t\t// click we want to ignore the click\n\t\t\t// TODO teach $.mobile.hijackable to operate on raw dom elements so the link wrapping\n\t\t\t// can be avoided\n\t\t\tif ( !link || event.which > 1 || !$link.jqmHijackable().length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//remove active link class if external (then it won't be there if you come back)\n\t\t\thttpCleanup = function(){\n\t\t\t\twindow.setTimeout( function() { removeActiveLinkClass( true ); }, 200 );\n\t\t\t};\n\n\t\t\t// If there's data cached for the real href value, set the link's href back to it again. This pairs with an address bar workaround from the vclick handler\n\t\t\tif( $link.jqmData( \"href\" ) ){\n\t\t\t\t$link.attr( \"href\", $link.jqmData( \"href\" ) );\n\t\t\t}\n\n\t\t\t//if there's a data-rel=back attr, go back in history\n\t\t\tif( $link.is( \":jqmData(rel='back')\" ) ) {\n\t\t\t\twindow.history.back();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar baseUrl = getClosestBaseUrl( $link ),\n\n\t\t\t\t//get href, if defined, otherwise default to empty hash\n\t\t\t\thref = path.makeUrlAbsolute( $link.attr( \"href\" ) || \"#\", baseUrl );\n\n\t\t\t//if ajax is disabled, exit early\n\t\t\tif( !$.mobile.ajaxEnabled && !path.isEmbeddedPage( href ) ){\n\t\t\t\thttpCleanup();\n\t\t\t\t//use default click handling\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// XXX_jblas: Ideally links to application pages should be specified as\n\t\t\t//            an url to the application document with a hash that is either\n\t\t\t//            the site relative path or id to the page. But some of the\n\t\t\t//            internal code that dynamically generates sub-pages for nested\n\t\t\t//            lists and select dialogs, just write a hash in the link they\n\t\t\t//            create. This means the actual URL path is based on whatever\n\t\t\t//            the current value of the base tag is at the time this code\n\t\t\t//            is called. For now we are just assuming that any url with a\n\t\t\t//            hash in it is an application page reference.\n\t\t\tif ( href.search( \"#\" ) != -1 ) {\n\t\t\t\thref = href.replace( /[^#]*#/, \"\" );\n\t\t\t\tif ( !href ) {\n\t\t\t\t\t//link was an empty hash meant purely\n\t\t\t\t\t//for interaction, so we ignore it.\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t} else if ( path.isPath( href ) ) {\n\t\t\t\t\t//we have apath so make it the href we want to load.\n\t\t\t\t\thref = path.makeUrlAbsolute( href, baseUrl );\n\t\t\t\t} else {\n\t\t\t\t\t//we have a simple id so use the documentUrl as its base.\n\t\t\t\t\thref = path.makeUrlAbsolute( \"#\" + href, documentUrl.hrefNoHash );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\t// Should we handle this link, or let the browser deal with it?\n\t\t\tvar useDefaultUrlHandling = $link.is( \"[rel='external']\" ) || $link.is( \":jqmData(ajax='false')\" ) || $link.is( \"[target]\" ),\n\n\t\t\t\t// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR\n\t\t\t\t// requests if the document doing the request was loaded via the file:// protocol.\n\t\t\t\t// This is usually to allow the application to \"phone home\" and fetch app specific\n\t\t\t\t// data. We normally let the browser handle external/cross-domain urls, but if the\n\t\t\t\t// allowCrossDomainPages option is true, we will allow cross-domain http/https\n\t\t\t\t// requests to go through our page loading logic.\n\t\t\t\tisCrossDomainPageLoad = ( $.mobile.allowCrossDomainPages && documentUrl.protocol === \"file:\" && href.search( /^https?:/ ) != -1 ),\n\n\t\t\t\t//check for protocol or rel and its not an embedded page\n\t\t\t\t//TODO overlap in logic from isExternal, rel=external check should be\n\t\t\t\t//     moved into more comprehensive isExternalLink\n\t\t\t\tisExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !isCrossDomainPageLoad );\n\n\t\t\tif( isExternal ) {\n\t\t\t\thttpCleanup();\n\t\t\t\t//use default click handling\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//use ajax\n\t\t\tvar transition = $link.jqmData( \"transition\" ),\n\t\t\t\tdirection = $link.jqmData( \"direction\" ),\n\t\t\t\treverse = ( direction && direction === \"reverse\" ) ||\n\t\t\t\t\t\t\t// deprecated - remove by 1.0\n\t\t\t\t\t\t\t$link.jqmData( \"back\" ),\n\n\t\t\t\t//this may need to be more specific as we use data-rel more\n\t\t\t\trole = $link.attr( \"data-\" + $.mobile.ns + \"rel\" ) || undefined;\n\n\t\t\t$.mobile.changePage( href, { transition: transition, reverse: reverse, role: role } );\n\t\t\tevent.preventDefault();\n\t\t});\n\n\t\t//prefetch pages when anchors with data-prefetch are encountered\n\t\t$( document ).delegate( \".ui-page\", \"pageshow.prefetch\", function() {\n\t\t\tvar urls = [];\n\t\t\t$( this ).find( \"a:jqmData(prefetch)\" ).each(function(){\n\t\t\t\tvar $link = $(this),\n\t\t\t\t\turl = $link.attr( \"href\" );\n\n\t\t\t\tif ( url && $.inArray( url, urls ) === -1 ) {\n\t\t\t\t\turls.push( url );\n\n\t\t\t\t\t$.mobile.loadPage( url, {role: $link.attr(\"data-\" + $.mobile.ns + \"rel\")} );\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\t$.mobile._handleHashChange = function( hash ) {\n\t\t\t//find first page via hash\n\t\t\tvar to = path.stripHash( hash ),\n\t\t\t\t//transition is false if it's the first page, undefined otherwise (and may be overridden by default)\n\t\t\t\ttransition = $.mobile.urlHistory.stack.length === 0 ? \"none\" : undefined,\n\n\t\t\t\t// default options for the changPage calls made after examining the current state\n\t\t\t\t// of the page and the hash\n\t\t\t\tchangePageOptions = {\n\t\t\t\t\ttransition: transition,\n\t\t\t\t\tchangeHash: false,\n\t\t\t\t\tfromHashChange: true\n\t\t\t\t};\n\n\t\t\t//if listening is disabled (either globally or temporarily), or it's a dialog hash\n\t\t\tif( !$.mobile.hashListeningEnabled || urlHistory.ignoreNextHashChange ) {\n\t\t\t\turlHistory.ignoreNextHashChange = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// special case for dialogs\n\t\t\tif( urlHistory.stack.length > 1 && to.indexOf( dialogHashKey ) > -1 ) {\n\n\t\t\t\t// If current active page is not a dialog skip the dialog and continue\n\t\t\t\t// in the same direction\n\t\t\t\tif(!$.mobile.activePage.is( \".ui-dialog\" )) {\n\t\t\t\t\t//determine if we're heading forward or backward and continue accordingly past\n\t\t\t\t\t//the current dialog\n\t\t\t\t\turlHistory.directHashChange({\n\t\t\t\t\t\tcurrentUrl: to,\n\t\t\t\t\t\tisBack: function() { window.history.back(); },\n\t\t\t\t\t\tisForward: function() { window.history.forward(); }\n\t\t\t\t\t});\n\n\t\t\t\t\t// prevent changePage()\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\t// if the current active page is a dialog and we're navigating\n\t\t\t\t\t// to a dialog use the dialog objected saved in the stack\n\t\t\t\t\turlHistory.directHashChange({\n\t\t\t\t\t\tcurrentUrl: to,\n\n\t\t\t\t\t\t// regardless of the direction of the history change\n\t\t\t\t\t\t// do the following\n\t\t\t\t\t\teither: function( isBack ) {\n\t\t\t\t\t\t\tvar active = $.mobile.urlHistory.getActive();\n\n\t\t\t\t\t\t\tto = active.pageUrl;\n\n\t\t\t\t\t\t\t// make sure to set the role, transition and reversal\n\t\t\t\t\t\t\t// as most of this is lost by the domCache cleaning\n\t\t\t\t\t\t\t$.extend( changePageOptions, {\n\t\t\t\t\t\t\t\trole: active.role,\n\t\t\t\t\t\t\t\ttransition:\t active.transition,\n\t\t\t\t\t\t\t\treverse: isBack\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//if to is defined, load it\n\t\t\tif ( to ) {\n\t\t\t\t// At this point, 'to' can be one of 3 things, a cached page element from\n\t\t\t\t// a history stack entry, an id, or site-relative/absolute URL. If 'to' is\n\t\t\t\t// an id, we need to resolve it against the documentBase, not the location.href,\n\t\t\t\t// since the hashchange could've been the result of a forward/backward navigation\n\t\t\t\t// that crosses from an external page/dialog to an internal page/dialog.\n\t\t\t\tto = ( typeof to === \"string\" && !path.isPath( to ) ) ? ( path.makeUrlAbsolute( '#' + to, documentBase ) ) : to;\n\t\t\t\t$.mobile.changePage( to, changePageOptions );\n\t\t\t}\telse {\n\t\t\t\t//there's no hash, go to the first page in the dom\n\t\t\t\t$.mobile.changePage( $.mobile.firstPage, changePageOptions );\n\t\t\t}\n\t\t};\n\n\t\t//hashchange event handler\n\t\t$window.bind( \"hashchange\", function( e, triggered ) {\n\t\t\t$.mobile._handleHashChange( location.hash );\n\t\t});\n\n\t\t//set page min-heights to be device specific\n\t\t$( document ).bind( \"pageshow\", resetActivePageHeight );\n\t\t$( window ).bind( \"throttledresize\", resetActivePageHeight );\n\n\t};//_registerInternalEvents callback\n\n})( jQuery );\n\n( function( $, window ) {\n\t// For now, let's Monkeypatch this onto the end of $.mobile._registerInternalEvents\n\t// Scope self to pushStateHandler so we can reference it sanely within the\n\t// methods handed off as event handlers\n\tvar\tpushStateHandler = {},\n\t\tself = pushStateHandler,\n\t\t$win = $( window ),\n\t\turl = $.mobile.path.parseUrl( location.href );\n\n\t$.extend( pushStateHandler, {\n\t\t// TODO move to a path helper, this is rather common functionality\n\t\tinitialFilePath: (function() {\n\t\t\treturn url.pathname + url.search;\n\t\t})(),\n\n\t\tinitialHref: url.hrefNoHash,\n\n\t\tstate: function() {\n\t\t\treturn {\n\t\t\t\thash: location.hash || \"#\" + self.initialFilePath,\n\t\t\t\ttitle: document.title,\n\n\t\t\t\t// persist across refresh\n\t\t\t\tinitialHref: self.initialHref\n\t\t\t};\n\t\t},\n\n\t\tresetUIKeys: function( url ) {\n\t\t\tvar dialog = $.mobile.dialogHashKey,\n\t\t\t\tsubkey = \"&\" + $.mobile.subPageUrlKey,\n\t\t\t\tdialogIndex = url.indexOf( dialog );\n\n\t\t\tif( dialogIndex > -1 ) {\n\t\t\t\turl = url.slice( 0, dialogIndex ) + \"#\" + url.slice( dialogIndex );\n\t\t\t} else if( url.indexOf( subkey ) > -1 ) {\n\t\t\t\turl = url.split( subkey ).join( \"#\" + subkey );\n\t\t\t}\n\n\t\t\treturn url;\n\t\t},\n\n\t\thashValueAfterReset: function( url ) {\n\t\t\tvar resetUrl = self.resetUIKeys( url );\n\t\t\treturn $.mobile.path.parseUrl( resetUrl ).hash;\n\t\t},\n\n\t\t// TODO sort out a single barrier to hashchange functionality\n\t\tnextHashChangePrevented: function( value ) {\n\t\t\t$.mobile.urlHistory.ignoreNextHashChange = value;\n\t\t\tself.onHashChangeDisabled = value;\n\t\t},\n\n\t\t// on hash change we want to clean up the url\n\t\t// NOTE this takes place *after* the vanilla navigation hash change\n\t\t// handling has taken place and set the state of the DOM\n\t\tonHashChange: function( e ) {\n\t\t\t// disable this hash change\n\t\t\tif( self.onHashChangeDisabled ){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar href, state,\n\t\t\t\thash = location.hash,\n\t\t\t\tisPath = $.mobile.path.isPath( hash ),\n\t\t\t\tresolutionUrl = isPath ? location.href : $.mobile.getDocumentUrl();\n\n\t\t\thash = isPath ? hash.replace( \"#\", \"\" ) : hash;\n\n\n\t\t\t// propulate the hash when its not available\n\t\t\tstate = self.state();\n\n\t\t\t// make the hash abolute with the current href\n\t\t\thref = $.mobile.path.makeUrlAbsolute( hash, resolutionUrl );\n\n\t\t\tif ( isPath ) {\n\t\t\t\thref = self.resetUIKeys( href );\n\t\t\t}\n\n\t\t\t// replace the current url with the new href and store the state\n\t\t\t// Note that in some cases we might be replacing an url with the\n\t\t\t// same url. We do this anyways because we need to make sure that\n\t\t\t// all of our history entries have a state object associated with\n\t\t\t// them. This allows us to work around the case where window.history.back()\n\t\t\t// is called to transition from an external page to an embedded page.\n\t\t\t// In that particular case, a hashchange event is *NOT* generated by the browser.\n\t\t\t// Ensuring each history entry has a state object means that onPopState()\n\t\t\t// will always trigger our hashchange callback even when a hashchange event\n\t\t\t// is not fired.\n\t\t\thistory.replaceState( state, document.title, href );\n\t\t},\n\n\t\t// on popstate (ie back or forward) we need to replace the hash that was there previously\n\t\t// cleaned up by the additional hash handling\n\t\tonPopState: function( e ) {\n\t\t\tvar poppedState = e.originalEvent.state,\n\t\t\t\ttimeout, fromHash, toHash, hashChanged;\n\n\t\t\t// if there's no state its not a popstate we care about, eg chrome's initial popstate\n\t\t\tif( poppedState ) {\n\t\t\t\t// the active url in the history stack will still be from the previous state\n\t\t\t\t// so we can use it to verify if a hashchange will be fired from the popstate\n\t\t\t\tfromHash = self.hashValueAfterReset( $.mobile.urlHistory.getActive().url );\n\n\t\t\t\t// the hash stored in the state popped off the stack will be our currenturl or\n\t\t\t\t// the url to which we wish to navigate\n\t\t\t\ttoHash = self.hashValueAfterReset( poppedState.hash.replace(\"#\", \"\") );\n\n\t\t\t\t// if the hashes of the urls are different we must assume that the browser\n\t\t\t\t// will fire a hashchange\n\t\t\t\thashChanged = fromHash !== toHash;\n\n\t\t\t\t// unlock hash handling once the hashchange caused be the popstate has fired\n\t\t\t\tif( hashChanged ) {\n\t\t\t\t\t$win.one( \"hashchange.pushstate\", function() {\n\t\t\t\t\t\tself.nextHashChangePrevented( false );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// enable hash handling for the the _handleHashChange call\n\t\t\t\tself.nextHashChangePrevented( false );\n\n\t\t\t\t// change the page based on the hash\n\t\t\t\t$.mobile._handleHashChange( poppedState.hash );\n\n\t\t\t\t// only prevent another hash change handling if a hash change will be fired\n\t\t\t\t// by the browser\n\t\t\t\tif( hashChanged ) {\n\t\t\t\t\t// disable hash handling until one of the above timers fires\n\t\t\t\t\tself.nextHashChangePrevented( true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tinit: function() {\n\t\t\t$win.bind( \"hashchange\", self.onHashChange );\n\n\t\t\t// Handle popstate events the occur through history changes\n\t\t\t$win.bind( \"popstate\", self.onPopState );\n\n\t\t\t// if there's no hash, we need to replacestate for returning to home\n\t\t\tif ( location.hash === \"\" ) {\n\t\t\t\thistory.replaceState( self.state(), document.title, location.href );\n\t\t\t}\n\t\t}\n\t});\n\n\t$( function() {\n\t\tif( $.mobile.pushStateEnabled && $.support.pushState ){\n\t\t\tpushStateHandler.init();\n\t\t}\n\t});\n})( jQuery, this );\n\n/*\n* fallback transition for pop in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.pop = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slide in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n// Use the simultaneous transition handler for slide transitions\n$.mobile.transitionHandlers.slide = $.mobile.transitionHandlers.simultaneous;\n\n// Set the slide transition's fallback to \"fade\"\n$.mobile.transitionFallbacks.slide = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slidedown in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.slidedown = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slideup in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.slideup = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for flip in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.flip = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for flow in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.flow = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for turn in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.turn = \"fade\";\n\n})( jQuery, this );\n\n(function( $, undefined ) {\n\n$.mobile.page.prototype.options.degradeInputs = {\n\tcolor: false,\n\tdate: false,\n\tdatetime: false,\n\t\"datetime-local\": false,\n\temail: false,\n\tmonth: false,\n\tnumber: false,\n\trange: \"number\",\n\tsearch: \"text\",\n\ttel: false,\n\ttime: false,\n\turl: false,\n\tweek: false\n};\n\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\n\tvar page = $.mobile.closestPageData($(e.target)), options;\n\n\tif( !page ) {\n\t\treturn;\n\t}\n\n\toptions = page.options;\n\n\t// degrade inputs to avoid poorly implemented native functionality\n\t$( e.target ).find( \"input\" ).not( page.keepNativeSelector() ).each(function() {\n\t\tvar $this = $( this ),\n\t\t\ttype = this.getAttribute( \"type\" ),\n\t\t\toptType = options.degradeInputs[ type ] || \"text\";\n\n\t\tif ( options.degradeInputs[ type ] ) {\n\t\t\tvar html = $( \"<div>\" ).html( $this.clone() ).html(),\n\t\t\t\t// In IE browsers, the type sometimes doesn't exist in the cloned markup, so we replace the closing tag instead\n\t\t\t\thasType = html.indexOf( \" type=\" ) > -1,\n\t\t\t\tfindstr = hasType ? /\\s+type=[\"']?\\w+['\"]?/ : /\\/?>/,\n\t\t\t\trepstr = \" type=\\\"\" + optType + \"\\\" data-\" + $.mobile.ns + \"type=\\\"\" + type + \"\\\"\" + ( hasType ? \"\" : \">\" );\n\n\t\t\t$this.replaceWith( html.replace( findstr, repstr ) );\n\t\t}\n\t});\n\n});\n\n})( jQuery );\n\n(function( $, window, undefined ) {\n\n$.widget( \"mobile.dialog\", $.mobile.widget, {\n\toptions: {\n\t\tcloseBtnText \t: \"Close\",\n\t\toverlayTheme\t: \"a\",\n\t\tinitSelector\t: \":jqmData(role='dialog')\"\n\t},\n\t_create: function() {\n\t\tvar self = this,\n\t\t\t$el = this.element,\n\t\t\theaderCloseButton = $( \"<a href='#' data-\" + $.mobile.ns + \"icon='delete' data-\" + $.mobile.ns + \"iconpos='notext'>\"+ this.options.closeBtnText + \"</a>\" ),\n\t\t\tdialogWrap = $(\"<div/>\", {\n\t\t\t\t\t\"role\" : \"dialog\",\n\t\t\t\t\t\"class\" : \"ui-dialog-contain ui-corner-all ui-overlay-shadow\"\n\t\t\t\t});\n\n\t\t$el.addClass( \"ui-dialog ui-overlay-\" + this.options.overlayTheme );\n\t\t\n\t\t// Class the markup for dialog styling\n\t\t// Set aria role\n\t\t$el\n\t\t\t.wrapInner( dialogWrap )\n\t\t\t.children()\n\t\t\t\t.find( \":jqmData(role='header')\" )\n\t\t\t\t\t.prepend( headerCloseButton )\n\t\t\t\t.end()\n\t\t\t\t.children( ':first-child')\n\t\t\t\t\t.addClass( \"ui-corner-top\" )\n\t\t\t\t.end()\n\t\t\t\t.children( \":last-child\" )\n\t\t\t\t\t.addClass( \"ui-corner-bottom\" );\n\n\t\t// this must be an anonymous function so that select menu dialogs can replace\n\t\t// the close method. This is a change from previously just defining data-rel=back\n\t\t// on the button and letting nav handle it\n\t\t//\n\t\t// Use click rather than vclick in order to prevent the possibility of unintentionally\n\t\t// reopening the dialog if the dialog opening item was directly under the close button.\n\t\theaderCloseButton.bind( \"click\", function() {\n\t\t\tself.close();\n\t\t});\n\n\t\t/* bind events\n\t\t\t- clicks and submits should use the closing transition that the dialog opened with\n\t\t\t  unless a data-transition is specified on the link/form\n\t\t\t- if the click was on the close button, or the link has a data-rel=\"back\" it'll go back in history naturally\n\t\t*/\n\t\t$el.bind( \"vclick submit\", function( event ) {\n\t\t\tvar $target = $( event.target ).closest( event.type === \"vclick\" ? \"a\" : \"form\" ),\n\t\t\t\tactive;\n\n\t\t\tif ( $target.length && !$target.jqmData( \"transition\" ) ) {\n\n\t\t\t\tactive = $.mobile.urlHistory.getActive() || {};\n\n\t\t\t\t$target.attr( \"data-\" + $.mobile.ns + \"transition\", ( active.transition || $.mobile.defaultDialogTransition ) )\n\t\t\t\t\t.attr( \"data-\" + $.mobile.ns + \"direction\", \"reverse\" );\n\t\t\t}\n\t\t})\n\t\t.bind( \"pagehide\", function( e, ui ) {\n\t\t\t$( this ).find( \".\" + $.mobile.activeBtnClass ).removeClass( $.mobile.activeBtnClass );\n\t\t})\n\t\t// Override the theme set by the page plugin on pageshow\n\t\t.bind( \"pagebeforeshow\", function(){\n\t\t\tif( self.options.overlayTheme ){\n\t\t\t\tself.element\n\t\t\t\t\t.page( \"removeContainerBackground\" )\n\t\t\t\t\t.page( \"setContainerBackground\", self.options.overlayTheme );\n\t\t\t}\n\t\t});\n\t},\n\n\t// Close method goes back in history\n\tclose: function() {\n\t\twindow.history.back();\n\t}\n});\n\n//auto self-init widgets\n$( document ).delegate( $.mobile.dialog.prototype.options.initSelector, \"pagecreate\", function(){\n\t$.mobile.dialog.prototype.enhance( this );\n});\n\n})( jQuery, this );\n\n(function( $, undefined ) {\n\n$.fn.fieldcontain = function( options ) {\n\treturn this.addClass( \"ui-field-contain ui-body ui-br\" );\n};\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$( \":jqmData(role='fieldcontain')\", e.target ).jqmEnhanceable().fieldcontain();\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.fn.grid = function( options ) {\n\treturn this.each(function() {\n\n\t\tvar $this = $( this ),\n\t\t\to = $.extend({\n\t\t\t\tgrid: null\n\t\t\t},options),\n\t\t\t$kids = $this.children(),\n\t\t\tgridCols = {solo:1, a:2, b:3, c:4, d:5},\n\t\t\tgrid = o.grid,\n\t\t\titerator;\n\n\t\t\tif ( !grid ) {\n\t\t\t\tif ( $kids.length <= 5 ) {\n\t\t\t\t\tfor ( var letter in gridCols ) {\n\t\t\t\t\t\tif ( gridCols[ letter ] === $kids.length ) {\n\t\t\t\t\t\t\tgrid = letter;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tgrid = \"a\";\n\t\t\t\t}\n\t\t\t}\n\t\t\titerator = gridCols[grid];\n\n\t\t$this.addClass( \"ui-grid-\" + grid );\n\n\t\t$kids.filter( \":nth-child(\" + iterator + \"n+1)\" ).addClass( \"ui-block-a\" );\n\n\t\tif ( iterator > 1 ) {\n\t\t\t$kids.filter( \":nth-child(\" + iterator + \"n+2)\" ).addClass( \"ui-block-b\" );\n\t\t}\n\t\tif ( iterator > 2 ) {\n\t\t\t$kids.filter( \":nth-child(3n+3)\" ).addClass( \"ui-block-c\" );\n\t\t}\n\t\tif ( iterator > 3 ) {\n\t\t\t$kids.filter( \":nth-child(4n+4)\" ).addClass( \"ui-block-d\" );\n\t\t}\n\t\tif ( iterator > 4 ) {\n\t\t\t$kids.filter( \":nth-child(5n+5)\" ).addClass( \"ui-block-e\" );\n\t\t}\n\t});\n};\n})( jQuery );\n\n(function( $, undefined ) {\n\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$( \":jqmData(role='nojs')\", e.target ).addClass( \"ui-nojs\" );\n\t\n});\n\n})( jQuery );\n\n( function( $, undefined ) {\n\n$.fn.buttonMarkup = function( options ) {\n\tvar $workingSet = this;\n\n\t// Enforce options to be of type string\n\toptions = ( options && ( $.type( options ) == \"object\" ) )? options : {};\n\tfor ( var i = 0; i < $workingSet.length; i++ ) {\n\t\tvar el = $workingSet.eq( i ),\n\t\t\te = el[ 0 ],\n\t\t\to = $.extend( {}, $.fn.buttonMarkup.defaults, {\n\t\t\t\ticon:       options.icon       !== undefined ? options.icon       : el.jqmData( \"icon\" ),\n\t\t\t\ticonpos:    options.iconpos    !== undefined ? options.iconpos    : el.jqmData( \"iconpos\" ),\n\t\t\t\ttheme:      options.theme      !== undefined ? options.theme      : el.jqmData( \"theme\" ) || $.mobile.getInheritedTheme( el, \"c\" ),\n\t\t\t\tinline:     options.inline     !== undefined ? options.inline     : el.jqmData( \"inline\" ),\n\t\t\t\tshadow:     options.shadow     !== undefined ? options.shadow     : el.jqmData( \"shadow\" ),\n\t\t\t\tcorners:    options.corners    !== undefined ? options.corners    : el.jqmData( \"corners\" ),\n\t\t\t\ticonshadow: options.iconshadow !== undefined ? options.iconshadow : el.jqmData( \"iconshadow\" ),\n\t\t\t\tmini:       options.mini       !== undefined ? options.mini       : el.jqmData( \"mini\" )\n\t\t\t}, options ),\n\n\t\t\t// Classes Defined\n\t\t\tinnerClass = \"ui-btn-inner\",\n\t\t\ttextClass = \"ui-btn-text\",\n\t\t\tbuttonClass, iconClass,\n\t\t\t// Button inner markup\n\t\t\tbuttonInner,\n\t\t\tbuttonText,\n\t\t\tbuttonIcon,\n\t\t\tbuttonElements;\n\n\t\t$.each(o, function(key, value) {\n\t\t\te.setAttribute( \"data-\" + $.mobile.ns + key, value );\n\t\t\tel.jqmData(key, value);\n\t\t});\n\n\t\t// Check if this element is already enhanced\n\t\tbuttonElements = $.data(((e.tagName === \"INPUT\" || e.tagName === \"BUTTON\") ? e.parentNode : e), \"buttonElements\");\n\n\t\tif (buttonElements) {\n\t\t\te = buttonElements.outer;\n\t\t\tel = $(e);\n\t\t\tbuttonInner = buttonElements.inner;\n\t\t\tbuttonText = buttonElements.text;\n\t\t\t// We will recreate this icon below\n\t\t\t$(buttonElements.icon).remove();\n\t\t\tbuttonElements.icon = null;\n\t\t}\n\t\telse {\n\t\t\tbuttonInner = document.createElement( o.wrapperEls );\n\t\t\tbuttonText = document.createElement( o.wrapperEls );\n\t\t}\n\t\tbuttonIcon = o.icon ? document.createElement( \"span\" ) : null;\n\n\t\tif ( attachEvents && !buttonElements) {\n\t\t\tattachEvents();\n\t\t}\n\t\t\n\t\t// if not, try to find closest theme container\t\n\t\tif ( !o.theme ) {\n\t\t\to.theme = $.mobile.getInheritedTheme( el, \"c\" );\t\n\t\t}\t\t\n\n\t\tbuttonClass = \"ui-btn ui-btn-up-\" + o.theme;\n\t\tbuttonClass += o.inline ? \" ui-btn-inline\" : \"\";\n\t\tbuttonClass += o.shadow ? \" ui-shadow\" : \"\";\n\t\tbuttonClass += o.corners ? \" ui-btn-corner-all\" : \"\";\n\n\t\tif ( o.mini !== undefined ) {\n\t\t\t// Used to control styling in headers/footers, where buttons default to `mini` style.\n\t\t\tbuttonClass += o.mini ? \" ui-mini\" : \" ui-fullsize\";\n\t\t}\n\t\t\n\t\tif ( o.inline !== undefined ) {\t\t\t\n\t\t\t// Used to control styling in headers/footers, where buttons default to `mini` style.\n\t\t\tbuttonClass += o.inline === false ? \" ui-btn-block\" : \" ui-btn-inline\";\n\t\t}\n\t\t\n\t\t\n\t\tif ( o.icon ) {\n\t\t\to.icon = \"ui-icon-\" + o.icon;\n\t\t\to.iconpos = o.iconpos || \"left\";\n\n\t\t\ticonClass = \"ui-icon \" + o.icon;\n\n\t\t\tif ( o.iconshadow ) {\n\t\t\t\ticonClass += \" ui-icon-shadow\";\n\t\t\t}\n\t\t}\n\n\t\tif ( o.iconpos ) {\n\t\t\tbuttonClass += \" ui-btn-icon-\" + o.iconpos;\n\n\t\t\tif ( o.iconpos == \"notext\" && !el.attr( \"title\" ) ) {\n\t\t\t\tel.attr( \"title\", el.getEncodedText() );\n\t\t\t}\n\t\t}\n    \n\t\tinnerClass += o.corners ? \" ui-btn-corner-all\" : \"\";\n\n\t\tif ( o.iconpos && o.iconpos === \"notext\" && !el.attr( \"title\" ) ) {\n\t\t\tel.attr( \"title\", el.getEncodedText() );\n\t\t}\n\n\t\tif ( buttonElements ) {\n\t\t\tel.removeClass( buttonElements.bcls || \"\" );\n\t\t}\n\t\tel.removeClass( \"ui-link\" ).addClass( buttonClass );\n\n\t\tbuttonInner.className = innerClass;\n\n\t\tbuttonText.className = textClass;\n\t\tif ( !buttonElements ) {\n\t\t\tbuttonInner.appendChild( buttonText );\n\t\t}\n\t\tif ( buttonIcon ) {\n\t\t\tbuttonIcon.className = iconClass;\n\t\t\tif ( !(buttonElements && buttonElements.icon) ) {\n\t\t\t\tbuttonIcon.appendChild( document.createTextNode(\"\\u00a0\") );\n\t\t\t\tbuttonInner.appendChild( buttonIcon );\n\t\t\t}\n\t\t}\n\n\t\twhile ( e.firstChild && !buttonElements) {\n\t\t\tbuttonText.appendChild( e.firstChild );\n\t\t}\n\n\t\tif ( !buttonElements ) {\n\t\t\te.appendChild( buttonInner );\n\t\t}\n\n\t\t// Assign a structure containing the elements of this button to the elements of this button. This\n\t\t// will allow us to recognize this as an already-enhanced button in future calls to buttonMarkup().\n\t\tbuttonElements = {\n\t\t\tbcls  : buttonClass,\n\t\t\touter : e,\n\t\t\tinner : buttonInner,\n\t\t\ttext  : buttonText,\n\t\t\ticon  : buttonIcon\n\t\t};\n\n\t\t$.data(e,           'buttonElements', buttonElements);\n\t\t$.data(buttonInner, 'buttonElements', buttonElements);\n\t\t$.data(buttonText,  'buttonElements', buttonElements);\n\t\tif (buttonIcon) {\n\t\t\t$.data(buttonIcon, 'buttonElements', buttonElements);\n\t\t}\n\t}\n\n\treturn this;\n};\n\n$.fn.buttonMarkup.defaults = {\n\tcorners: true,\n\tshadow: true,\n\ticonshadow: true,\n\twrapperEls: \"span\"\n};\n\nfunction closestEnabledButton( element ) {\n    var cname;\n\n    while ( element ) {\n\t\t// Note that we check for typeof className below because the element we\n\t\t// handed could be in an SVG DOM where className on SVG elements is defined to\n\t\t// be of a different type (SVGAnimatedString). We only operate on HTML DOM\n\t\t// elements, so we look for plain \"string\".\n        cname = ( typeof element.className === 'string' ) && (element.className + ' ');\n        if ( cname && cname.indexOf(\"ui-btn \") > -1 && cname.indexOf(\"ui-disabled \") < 0 ) {\n            break;\n        }\n\n        element = element.parentNode;\n    }\n\n    return element;\n}\n\nvar attachEvents = function() {\n\tvar hoverDelay = $.mobile.buttonMarkup.hoverDelay, hov, foc;\n\n\t$( document ).bind( {\n\t\t\"vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart\": function( event ) {\n\t\t\tvar theme,\n\t\t\t\t$btn = $( closestEnabledButton( event.target ) ),\n\t\t\t\tevt = event.type;\n\t\t\n\t\t\tif ( $btn.length ) {\n\t\t\t\ttheme = $btn.attr( \"data-\" + $.mobile.ns + \"theme\" );\n\t\t\n\t\t\t\tif ( evt === \"vmousedown\" ) {\n\t\t\t\t\tif ( $.support.touch ) {\n\t\t\t\t\t\thov = setTimeout(function() {\n\t\t\t\t\t\t\t$btn.removeClass( \"ui-btn-up-\" + theme ).addClass( \"ui-btn-down-\" + theme );\n\t\t\t\t\t\t}, hoverDelay );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$btn.removeClass( \"ui-btn-up-\" + theme ).addClass( \"ui-btn-down-\" + theme );\n\t\t\t\t\t}\n\t\t\t\t} else if ( evt === \"vmousecancel\" || evt === \"vmouseup\" ) {\n\t\t\t\t\t$btn.removeClass( \"ui-btn-down-\" + theme ).addClass( \"ui-btn-up-\" + theme );\n\t\t\t\t} else if ( evt === \"vmouseover\" || evt === \"focus\" ) {\n\t\t\t\t\tif ( $.support.touch ) {\n\t\t\t\t\t\tfoc = setTimeout(function() {\n\t\t\t\t\t\t\t$btn.removeClass( \"ui-btn-up-\" + theme ).addClass( \"ui-btn-hover-\" + theme );\n\t\t\t\t\t\t}, hoverDelay );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$btn.removeClass( \"ui-btn-up-\" + theme ).addClass( \"ui-btn-hover-\" + theme );\n\t\t\t\t\t}\n\t\t\t\t} else if ( evt === \"vmouseout\" || evt === \"blur\" || evt === \"scrollstart\" ) {\n\t\t\t\t\t$btn.removeClass( \"ui-btn-hover-\" + theme  + \" ui-btn-down-\" + theme ).addClass( \"ui-btn-up-\" + theme );\n\t\t\t\t\tif ( hov ) {\n\t\t\t\t\t\tclearTimeout( hov );\n\t\t\t\t\t}\n\t\t\t\t\tif ( foc ) {\n\t\t\t\t\t\tclearTimeout( foc );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"focusin focus\": function( event ){\n\t\t\t$( closestEnabledButton( event.target ) ).addClass( $.mobile.focusClass );\n\t\t},\n\t\t\"focusout blur\": function( event ){\n\t\t\t$( closestEnabledButton( event.target ) ).removeClass( $.mobile.focusClass );\n\t\t}\n\t});\n\n\tattachEvents = null;\n};\n\n//links in bars, or those with  data-role become buttons\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\n\t$( \":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a\", e.target )\n\t\t.not( \".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')\" )\n\t\t.buttonMarkup();\n});\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n\n$.mobile.page.prototype.options.backBtnText  = \"Back\";\n$.mobile.page.prototype.options.addBackBtn   = false;\n$.mobile.page.prototype.options.backBtnTheme = null;\n$.mobile.page.prototype.options.headerTheme  = \"a\";\n$.mobile.page.prototype.options.footerTheme  = \"a\";\n$.mobile.page.prototype.options.contentTheme = null;\n\n$( document ).delegate( \":jqmData(role='page'), :jqmData(role='dialog')\", \"pagecreate\", function( e ) {\n\n\tvar $page = $( this ),\n\t\to = $page.data( \"page\" ).options,\n\t\tpageRole = $page.jqmData( \"role\" ),\n\t\tpageTheme = o.theme;\n\n\t$( \":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')\", this )\n\t\t.jqmEnhanceable()\n\t\t.each(function() {\n\n\t\tvar $this = $( this ),\n\t\t\trole = $this.jqmData( \"role\" ),\n\t\t\ttheme = $this.jqmData( \"theme\" ),\n\t\t\tcontentTheme = theme || o.contentTheme || ( pageRole === \"dialog\" && pageTheme ),\n\t\t\t$headeranchors,\n\t\t\tleftbtn,\n\t\t\trightbtn,\n\t\t\tbackBtn;\n\n\t\t$this.addClass( \"ui-\" + role );\n\n\t\t//apply theming and markup modifications to page,header,content,footer\n\t\tif ( role === \"header\" || role === \"footer\" ) {\n\n\t\t\tvar thisTheme = theme || ( role === \"header\" ? o.headerTheme : o.footerTheme ) || pageTheme;\n\n\t\t\t$this\n\t\t\t\t//add theme class\n\t\t\t\t.addClass( \"ui-bar-\" + thisTheme )\n\t\t\t\t// Add ARIA role\n\t\t\t\t.attr( \"role\", role === \"header\" ? \"banner\" : \"contentinfo\" );\n\n\t\t\tif( role === \"header\") {\n\t\t\t\t// Right,left buttons\n\t\t\t\t$headeranchors\t= $this.children( \"a\" );\n\t\t\t\tleftbtn\t= $headeranchors.hasClass( \"ui-btn-left\" );\n\t\t\t\trightbtn = $headeranchors.hasClass( \"ui-btn-right\" );\n\n\t\t\t\tleftbtn = leftbtn || $headeranchors.eq( 0 ).not( \".ui-btn-right\" ).addClass( \"ui-btn-left\" ).length;\n\n\t\t\t\trightbtn = rightbtn || $headeranchors.eq( 1 ).addClass( \"ui-btn-right\" ).length;\n\t\t\t}\n\n\t\t\t// Auto-add back btn on pages beyond first view\n\t\t\tif ( o.addBackBtn &&\n\t\t\t\trole === \"header\" &&\n\t\t\t\t$( \".ui-page\" ).length > 1 &&\n\t\t\t\t$page.jqmData( \"url\" ) !== $.mobile.path.stripHash( location.hash ) &&\n\t\t\t\t!leftbtn ) {\n\n\t\t\t\tbackBtn = $( \"<a href='#' class='ui-btn-left' data-\"+ $.mobile.ns +\"rel='back' data-\"+ $.mobile.ns +\"icon='arrow-l'>\"+ o.backBtnText +\"</a>\" )\n\t\t\t\t\t// If theme is provided, override default inheritance\n\t\t\t\t\t.attr( \"data-\"+ $.mobile.ns +\"theme\", o.backBtnTheme || thisTheme )\n\t\t\t\t\t.prependTo( $this );\n\t\t\t}\n\n\t\t\t// Page title\n\t\t\t$this.children( \"h1, h2, h3, h4, h5, h6\" )\n\t\t\t\t.addClass( \"ui-title\" )\n\t\t\t\t// Regardless of h element number in src, it becomes h1 for the enhanced page\n\t\t\t\t.attr({\n\t\t\t\t\t\"role\": \"heading\",\n\t\t\t\t\t\"aria-level\": \"1\"\n\t\t\t\t});\n\n\t\t} else if ( role === \"content\" ) {\n\t\t\tif ( contentTheme ) {\n\t\t\t    $this.addClass( \"ui-body-\" + ( contentTheme ) );\n\t\t\t}\n\n\t\t\t// Add ARIA role\n\t\t\t$this.attr( \"role\", \"main\" );\n\t\t}\n\t});\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.collapsible\", $.mobile.widget, {\n\toptions: {\n\t\texpandCueText: \" click to expand contents\",\n\t\tcollapseCueText: \" click to collapse contents\",\n\t\tcollapsed: true,\n\t\theading: \"h1,h2,h3,h4,h5,h6,legend\",\n\t\ttheme: null,\n\t\tcontentTheme: null,\n\t\ticonTheme: \"d\",\n\t\tmini: false,\n\t\tinitSelector: \":jqmData(role='collapsible')\"\n\t},\n\t_create: function() {\n\n\t\tvar $el = this.element,\n\t\t\to = this.options,\n\t\t\tcollapsible = $el.addClass( \"ui-collapsible\" ),\n\t\t\tcollapsibleHeading = $el.children( o.heading ).first(),\n\t\t\tcollapsibleContent = collapsible.wrapInner( \"<div class='ui-collapsible-content'></div>\" ).find( \".ui-collapsible-content\" ),\n\t\t\tcollapsibleSet = $el.closest( \":jqmData(role='collapsible-set')\" ).addClass( \"ui-collapsible-set\" );\n\n\t\t// Replace collapsibleHeading if it's a legend\n\t\tif ( collapsibleHeading.is( \"legend\" ) ) {\n\t\t\tcollapsibleHeading = $( \"<div role='heading'>\"+ collapsibleHeading.html() +\"</div>\" ).insertBefore( collapsibleHeading );\n\t\t\tcollapsibleHeading.next().remove();\n\t\t}\n\n\t\t// If we are in a collapsible set\n\t\tif ( collapsibleSet.length ) {\n\t\t\t// Inherit the theme from collapsible-set\n\t\t\tif ( !o.theme ) {\n\t\t\t\to.theme = collapsibleSet.jqmData(\"theme\") || $.mobile.getInheritedTheme( collapsibleSet, \"c\" );\n\t\t\t}\n\t\t\t// Inherit the content-theme from collapsible-set\n\t\t\tif ( !o.contentTheme ) {\n\t\t\t\to.contentTheme = collapsibleSet.jqmData( \"content-theme\" );\n\t\t\t}\n\n\t\t\t// Gets the preference icon position in the set\n\t\t\tif ( !o.iconPos ) {\n\t\t\t\to.iconPos = collapsibleSet.jqmData( \"iconpos\" );\n\t\t\t}\n\n\t\t\tif( !o.mini ) {\n\t\t\t\to.mini = collapsibleSet.jqmData( \"mini\" );\n\t\t\t}\n\t\t}\n\t\tcollapsibleContent.addClass( ( o.contentTheme ) ? ( \"ui-body-\" + o.contentTheme ) : \"\");\n\n\t\tcollapsibleHeading\n\t\t\t//drop heading in before content\n\t\t\t.insertBefore( collapsibleContent )\n\t\t\t//modify markup & attributes\n\t\t\t.addClass( \"ui-collapsible-heading\" )\n\t\t\t.append( \"<span class='ui-collapsible-heading-status'></span>\" )\n\t\t\t.wrapInner( \"<a href='#' class='ui-collapsible-heading-toggle'></a>\" )\n\t\t\t.find( \"a\" )\n\t\t\t\t.first()\n\t\t\t\t.buttonMarkup({\n\t\t\t\t\tshadow: false,\n\t\t\t\t\tcorners: false,\n\t\t\t\t\ticonpos: $el.jqmData( \"iconpos\" ) || o.iconPos || \"left\",\n\t\t\t\t\ticon: \"plus\",\n\t\t\t\t\tmini: o.mini,\n\t\t\t\t\ttheme: o.theme\n\t\t\t\t})\n\t\t\t.add( \".ui-btn-inner\", $el )\n\t\t\t\t.addClass( \"ui-corner-top ui-corner-bottom\" );\n\n\t\t//events\n\t\tcollapsible\n\t\t\t.bind( \"expand collapse\", function( event ) {\n\t\t\t\tif ( !event.isDefaultPrevented() ) {\n\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\tvar $this = $( this ),\n\t\t\t\t\t\tisCollapse = ( event.type === \"collapse\" ),\n\t\t\t\t\t    contentTheme = o.contentTheme;\n\n\t\t\t\t\tcollapsibleHeading\n\t\t\t\t\t\t.toggleClass( \"ui-collapsible-heading-collapsed\", isCollapse)\n\t\t\t\t\t\t.find( \".ui-collapsible-heading-status\" )\n\t\t\t\t\t\t\t.text( isCollapse ? o.expandCueText : o.collapseCueText )\n\t\t\t\t\t\t.end()\n\t\t\t\t\t\t.find( \".ui-icon\" )\n\t\t\t\t\t\t\t.toggleClass( \"ui-icon-minus\", !isCollapse )\n\t\t\t\t\t\t\t.toggleClass( \"ui-icon-plus\", isCollapse );\n\n\t\t\t\t\t$this.toggleClass( \"ui-collapsible-collapsed\", isCollapse );\n\t\t\t\t\tcollapsibleContent.toggleClass( \"ui-collapsible-content-collapsed\", isCollapse ).attr( \"aria-hidden\", isCollapse );\n\n\t\t\t\t\tif ( contentTheme && ( !collapsibleSet.length || collapsible.jqmData( \"collapsible-last\" ) ) ) {\n\t\t\t\t\t\tcollapsibleHeading\n\t\t\t\t\t\t\t.find( \"a\" ).first().add( collapsibleHeading.find( \".ui-btn-inner\" ) )\n\t\t\t\t\t\t\t.toggleClass( \"ui-corner-bottom\", isCollapse );\n\t\t\t\t\t\tcollapsibleContent.toggleClass( \"ui-corner-bottom\", !isCollapse );\n\t\t\t\t\t}\n\t\t\t\t\tcollapsibleContent.trigger( \"updatelayout\" );\n\t\t\t\t}\n\t\t\t})\n\t\t\t.trigger( o.collapsed ? \"collapse\" : \"expand\" );\n\n\t\tcollapsibleHeading\n\t\t\t.bind( \"click\", function( event ) {\n\n\t\t\t\tvar type = collapsibleHeading.is( \".ui-collapsible-heading-collapsed\" ) ?\n\t\t\t\t\t\t\t\t\t\t\"expand\" : \"collapse\";\n\n\t\t\t\tcollapsible.trigger( type );\n\n\t\t\t\tevent.preventDefault();\n\t\t\t});\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.collapsible.prototype.enhanceWithin( e.target );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.collapsibleset\", $.mobile.widget, {\n\toptions: {\n\t\tinitSelector: \":jqmData(role='collapsible-set')\"\n\t},\n\t_create: function() {\n\t\tvar $el = this.element.addClass( \"ui-collapsible-set\" ),\n\t\t\to = this.options;\n\n\t\t// Inherit the theme from collapsible-set\n\t\tif ( !o.theme ) {\n\t\t\to.theme = $.mobile.getInheritedTheme( $el, \"c\" );\n\t\t}\n\t\t// Inherit the content-theme from collapsible-set\n\t\tif ( !o.contentTheme ) {\n\t\t\to.contentTheme = $el.jqmData( \"content-theme\" );\n\t\t}\n\n\t\tif ( !o.corners ) {\n\t\t\to.corners = $el.jqmData( \"corners\" ) === undefined ? true : false;\n\t\t}\n\n\t\t// Initialize the collapsible set if it's not already initialized\n\t\tif ( !$el.jqmData( \"collapsiblebound\" ) ) {\n\t\t\t$el\n\t\t\t\t.jqmData( \"collapsiblebound\", true )\n\t\t\t\t.bind( \"expand collapse\", function( event ) {\n\t\t\t\t\tvar isCollapse = ( event.type === \"collapse\" ),\n\t\t\t\t\t\tcollapsible = $( event.target ).closest( \".ui-collapsible\" ),\n\t\t\t\t\t\twidget = collapsible.data( \"collapsible\" ),\n\t\t\t\t\t    contentTheme = widget.options.contentTheme;\n\t\t\t\t\tif ( contentTheme && collapsible.jqmData( \"collapsible-last\" ) ) {\n\t\t\t\t\t\tcollapsible.find( widget.options.heading ).first()\n\t\t\t\t\t\t\t.find( \"a\" ).first()\n\t\t\t\t\t\t\t.add( \".ui-btn-inner\" )\n\t\t\t\t\t\t\t.toggleClass( \"ui-corner-bottom\", isCollapse );\n\t\t\t\t\t\tcollapsible.find( \".ui-collapsible-content\" ).toggleClass( \"ui-corner-bottom\", !isCollapse );\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( \"expand\", function( event ) {\n\t\t\t\t\t$( event.target )\n\t\t\t\t\t\t.closest( \".ui-collapsible\" )\n\t\t\t\t\t\t.siblings( \".ui-collapsible\" )\n\t\t\t\t\t\t.trigger( \"collapse\" );\n\t\t\t\t});\n\t\t}\n\t},\n\n\t_init: function() {\n\t\tthis.refresh();\n\t},\n\n\trefresh: function() {\n\t\tvar $el = this.element,\n\t\t\to = this.options,\n\t\t\tcollapsiblesInSet = $el.children( \":jqmData(role='collapsible')\" );\n\n\t\t$.mobile.collapsible.prototype.enhance( collapsiblesInSet.not( \".ui-collapsible\" ) );\n\n\t\t// clean up borders\n\t\tcollapsiblesInSet.each( function() {\n\t\t\t$( this ).find( $.mobile.collapsible.prototype.options.heading )\n\t\t\t\t.find( \"a\" ).first()\n\t\t\t\t.add( \".ui-btn-inner\" )\n\t\t\t\t.removeClass( \"ui-corner-top ui-corner-bottom\" );\n\t\t});\n\n\t\tcollapsiblesInSet.first()\n\t\t\t.find( \"a\" )\n\t\t\t\t.first()\n\t\t\t\t.addClass( o.corners ? \"ui-corner-top\" : \"\" )\n\t\t\t\t.find( \".ui-btn-inner\" )\n\t\t\t\t\t.addClass( \"ui-corner-top\" );\n\n\t\tcollapsiblesInSet.last()\n\t\t\t.jqmData( \"collapsible-last\", true )\n\t\t\t.find( \"a\" )\n\t\t\t\t.first()\n\t\t\t\t.addClass( o.corners ? \"ui-corner-bottom\" : \"\" )\n\t\t\t\t.find( \".ui-btn-inner\" )\n\t\t\t\t\t.addClass( \"ui-corner-bottom\" );\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.collapsibleset.prototype.enhanceWithin( e.target );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.navbar\", $.mobile.widget, {\n\toptions: {\n\t\ticonpos: \"top\",\n\t\tgrid: null,\n\t\tinitSelector: \":jqmData(role='navbar')\"\n\t},\n\n\t_create: function(){\n\n\t\tvar $navbar = this.element,\n\t\t\t$navbtns = $navbar.find( \"a\" ),\n\t\t\ticonpos = $navbtns.filter( \":jqmData(icon)\" ).length ?\n\t\t\t\t\t\t\t\t\tthis.options.iconpos : undefined;\n\n\t\t$navbar.addClass( \"ui-navbar\" )\n\t\t\t.attr( \"role\",\"navigation\" )\n\t\t\t.find( \"ul\" )\n\t\t\t.jqmEnhanceable()\n\t\t\t.grid({ grid: this.options.grid });\n\n\t\tif ( !iconpos ) {\n\t\t\t$navbar.addClass( \"ui-navbar-noicons\" );\n\t\t}\n\n\t\t$navbtns.buttonMarkup({\n\t\t\tcorners:\tfalse,\n\t\t\tshadow:\t\tfalse,\n\t\t\tinline:     true,\n\t\t\ticonpos:\ticonpos\n\t\t});\n\n\t\t$navbar.delegate( \"a\", \"vclick\", function( event ) {\n\t\t\tif( !$(event.target).hasClass(\"ui-disabled\") ) {\n\t\t\t\t$navbtns.removeClass( $.mobile.activeBtnClass );\n\t\t\t\t$( this ).addClass( $.mobile.activeBtnClass );\n\t\t\t}\n\t\t});\n\n\t\t// Buttons in the navbar with ui-state-persist class should regain their active state before page show\n\t\t$navbar.closest( \".ui-page\" ).bind( \"pagebeforeshow\", function() {\n\t\t\t$navbtns.filter( \".ui-state-persist\" ).addClass( $.mobile.activeBtnClass );\n\t\t});\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.navbar.prototype.enhanceWithin( e.target );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n//Keeps track of the number of lists per page UID\n//This allows support for multiple nested list in the same page\n//https://github.com/jquery/jquery-mobile/issues/1617\nvar listCountPerPage = {};\n\n$.widget( \"mobile.listview\", $.mobile.widget, {\n\n\toptions: {\n\t\ttheme: null,\n\t\tcountTheme: \"c\",\n\t\theaderTheme: \"b\",\n\t\tdividerTheme: \"b\",\n\t\tsplitIcon: \"arrow-r\",\n\t\tsplitTheme: \"b\",\n\t\tmini: false,\n\t\tinset: false,\n\t\tinitSelector: \":jqmData(role='listview')\"\n\t},\n\n\t_create: function() {\n\t\tvar t = this,\n\t\t\tlistviewClasses = \"\";\n\t\t\t\n\t\tlistviewClasses += t.options.inset ? \" ui-listview-inset ui-corner-all ui-shadow \" : \"\";\n\t\tlistviewClasses += t.element.jqmData( \"mini\" ) || t.options.mini === true ? \" ui-mini\" : \"\";\n\t\t\n\t\t// create listview markup\n\t\tt.element.addClass(function( i, orig ) {\n\t\t\treturn orig + \" ui-listview \" + listviewClasses;\n\t\t});\n\n\t\tt.refresh( true );\n\t},\n\n\t_removeCorners: function( li, which ) {\n\t\tvar top = \"ui-corner-top ui-corner-tr ui-corner-tl\",\n\t\t\tbot = \"ui-corner-bottom ui-corner-br ui-corner-bl\";\n\n\t\tli = li.add( li.find( \".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb\" ) );\n\n\t\tif ( which === \"top\" ) {\n\t\t\tli.removeClass( top );\n\t\t} else if ( which === \"bottom\" ) {\n\t\t\tli.removeClass( bot );\n\t\t} else {\n\t\t\tli.removeClass( top + \" \" + bot );\n\t\t}\n\t},\n\n\t_refreshCorners: function( create ) {\n\t\tvar $li,\n\t\t\t$visibleli,\n\t\t\t$topli,\n\t\t\t$bottomli;\n\n\t\tif ( this.options.inset ) {\n\t\t\t$li = this.element.children( \"li\" );\n\t\t\t// at create time the li are not visible yet so we need to rely on .ui-screen-hidden\n\t\t\t$visibleli = create?$li.not( \".ui-screen-hidden\" ):$li.filter( \":visible\" );\n\n\t\t\tthis._removeCorners( $li );\n\n\t\t\t// Select the first visible li element\n\t\t\t$topli = $visibleli.first()\n\t\t\t\t.addClass( \"ui-corner-top\" );\n\n\t\t\t$topli.add( $topli.find( \".ui-btn-inner\" )\n\t\t\t\t\t.not( \".ui-li-link-alt span:first-child\" ) )\n                                .addClass( \"ui-corner-top\" )\n                                .end()\n\t\t\t\t.find( \".ui-li-link-alt, .ui-li-link-alt span:first-child\" )\n\t\t\t\t\t.addClass( \"ui-corner-tr\" )\n\t\t\t\t.end()\n\t\t\t\t.find( \".ui-li-thumb\" )\n\t\t\t\t\t.not(\".ui-li-icon\")\n\t\t\t\t\t.addClass( \"ui-corner-tl\" );\n\n\t\t\t// Select the last visible li element\n\t\t\t$bottomli = $visibleli.last()\n\t\t\t\t.addClass( \"ui-corner-bottom\" );\n\n\t\t\t$bottomli.add( $bottomli.find( \".ui-btn-inner\" ) )\n\t\t\t\t.find( \".ui-li-link-alt\" )\n\t\t\t\t\t.addClass( \"ui-corner-br\" )\n\t\t\t\t.end()\n\t\t\t\t.find( \".ui-li-thumb\" )\n\t\t\t\t\t.not(\".ui-li-icon\")\n\t\t\t\t\t.addClass( \"ui-corner-bl\" );\n\t\t}\n\t\tif ( !create ) {\n\t\t\tthis.element.trigger( \"updatelayout\" );\n\t\t}\n\t},\n\n\t// This is a generic utility method for finding the first\n\t// node with a given nodeName. It uses basic DOM traversal\n\t// to be fast and is meant to be a substitute for simple\n\t// $.fn.closest() and $.fn.children() calls on a single\n\t// element. Note that callers must pass both the lowerCase\n\t// and upperCase version of the nodeName they are looking for.\n\t// The main reason for this is that this function will be\n\t// called many times and we want to avoid having to lowercase\n\t// the nodeName from the element every time to ensure we have\n\t// a match. Note that this function lives here for now, but may\n\t// be moved into $.mobile if other components need a similar method.\n\t_findFirstElementByTagName: function( ele, nextProp, lcName, ucName )\n\t{\n\t\tvar dict = {};\n\t\tdict[ lcName ] = dict[ ucName ] = true;\n\t\twhile ( ele ) {\n\t\t\tif ( dict[ ele.nodeName ] ) {\n\t\t\t\treturn ele;\n\t\t\t}\n\t\t\tele = ele[ nextProp ];\n\t\t}\n\t\treturn null;\n\t},\n\t_getChildrenByTagName: function( ele, lcName, ucName )\n\t{\n\t\tvar results = [],\n\t\t\tdict = {};\n\t\tdict[ lcName ] = dict[ ucName ] = true;\n\t\tele = ele.firstChild;\n\t\twhile ( ele ) {\n\t\t\tif ( dict[ ele.nodeName ] ) {\n\t\t\t\tresults.push( ele );\n\t\t\t}\n\t\t\tele = ele.nextSibling;\n\t\t}\n\t\treturn $( results );\n\t},\n\n\t_addThumbClasses: function( containers )\n\t{\n\t\tvar i, img, len = containers.length;\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\timg = $( this._findFirstElementByTagName( containers[ i ].firstChild, \"nextSibling\", \"img\", \"IMG\" ) );\n\t\t\tif ( img.length ) {\n\t\t\t\timg.addClass( \"ui-li-thumb\" );\n\t\t\t\t$( this._findFirstElementByTagName( img[ 0 ].parentNode, \"parentNode\", \"li\", \"LI\" ) ).addClass( img.is( \".ui-li-icon\" ) ? \"ui-li-has-icon\" : \"ui-li-has-thumb\" );\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function( create ) {\n\t\tthis.parentPage = this.element.closest( \".ui-page\" );\n\t\tthis._createSubPages();\n\n\t\tvar o = this.options,\n\t\t\t$list = this.element,\n\t\t\tself = this,\n\t\t\tdividertheme = $list.jqmData( \"dividertheme\" ) || o.dividerTheme,\n\t\t\tlistsplittheme = $list.jqmData( \"splittheme\" ),\n\t\t\tlistspliticon = $list.jqmData( \"spliticon\" ),\n\t\t\tli = this._getChildrenByTagName( $list[ 0 ], \"li\", \"LI\" ),\n\t\t\tcounter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], \"ol\" ) ? 0 : 1,\n\t\t\titemClassDict = {},\n\t\t\titem, itemClass, itemTheme,\n\t\t\ta, last, splittheme, countParent, icon, imgParents, img, linkIcon;\n\n\t\tif ( counter ) {\n\t\t\t$list.find( \".ui-li-dec\" ).remove();\n\t\t}\n\n\t\tif ( !o.theme ) {\n\t\t\to.theme = $.mobile.getInheritedTheme( this.element, \"c\" );\n\t\t}\n\n\t\tfor ( var pos = 0, numli = li.length; pos < numli; pos++ ) {\n\t\t\titem = li.eq( pos );\n\t\t\titemClass = \"ui-li\";\n\n\t\t\t// If we're creating the element, we update it regardless\n\t\t\tif ( create || !item.hasClass( \"ui-li\" ) ) {\n\t\t\t\titemTheme = item.jqmData(\"theme\") || o.theme;\n\t\t\t\ta = this._getChildrenByTagName( item[ 0 ], \"a\", \"A\" );\n\n\t\t\t\tif ( a.length ) {\n\t\t\t\t\ticon = item.jqmData(\"icon\");\n\n\t\t\t\t\titem.buttonMarkup({\n\t\t\t\t\t\twrapperEls: \"div\",\n\t\t\t\t\t\tshadow: false,\n\t\t\t\t\t\tcorners: false,\n\t\t\t\t\t\ticonpos: \"right\",\n\t\t\t\t\t\ticon: a.length > 1 || icon === false ? false : icon || \"arrow-r\",\n\t\t\t\t\t\ttheme: itemTheme\n\t\t\t\t\t});\n\n\t\t\t\t\tif ( ( icon != false ) && ( a.length == 1 ) ) {\n\t\t\t\t\t\titem.addClass( \"ui-li-has-arrow\" );\n\t\t\t\t\t}\n\n\t\t\t\t\ta.first().removeClass( \"ui-link\" ).addClass( \"ui-link-inherit\" );\n\n\t\t\t\t\tif ( a.length > 1 ) {\n\t\t\t\t\t\titemClass += \" ui-li-has-alt\";\n\n\t\t\t\t\t\tlast = a.last();\n\t\t\t\t\t\tsplittheme = listsplittheme || last.jqmData( \"theme\" ) || o.splitTheme;\n\t\t\t\t\t\tlinkIcon = last.jqmData(\"icon\");\n\n\t\t\t\t\t\tlast.appendTo(item)\n\t\t\t\t\t\t\t.attr( \"title\", last.getEncodedText() )\n\t\t\t\t\t\t\t.addClass( \"ui-li-link-alt\" )\n\t\t\t\t\t\t\t.empty()\n\t\t\t\t\t\t\t.buttonMarkup({\n\t\t\t\t\t\t\t\tshadow: false,\n\t\t\t\t\t\t\t\tcorners: false,\n\t\t\t\t\t\t\t\ttheme: itemTheme,\n\t\t\t\t\t\t\t\ticon: false,\n\t\t\t\t\t\t\t\ticonpos: false\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.find( \".ui-btn-inner\" )\n\t\t\t\t\t\t\t\t.append(\n\t\t\t\t\t\t\t\t\t$( document.createElement( \"span\" ) ).buttonMarkup({\n\t\t\t\t\t\t\t\t\t\tshadow: true,\n\t\t\t\t\t\t\t\t\t\tcorners: true,\n\t\t\t\t\t\t\t\t\t\ttheme: splittheme,\n\t\t\t\t\t\t\t\t\t\ticonpos: \"notext\",\n\t\t\t\t\t\t\t\t\t\t// link icon overrides list item icon overrides ul element overrides options\n\t\t\t\t\t\t\t\t\t\ticon: linkIcon || icon || listspliticon || o.splitIcon\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if ( item.jqmData( \"role\" ) === \"list-divider\" ) {\n\n\t\t\t\t\titemClass += \" ui-li-divider ui-bar-\" + dividertheme;\n\t\t\t\t\titem.attr( \"role\", \"heading\" );\n\n\t\t\t\t\t//reset counter when a divider heading is encountered\n\t\t\t\t\tif ( counter ) {\n\t\t\t\t\t\tcounter = 1;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\titemClass += \" ui-li-static ui-body-\" + itemTheme;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( counter && itemClass.indexOf( \"ui-li-divider\" ) < 0 ) {\n\t\t\t\tcountParent = item.is( \".ui-li-static:first\" ) ? item : item.find( \".ui-link-inherit\" );\n\n\t\t\t\tcountParent.addClass( \"ui-li-jsnumbering\" )\n\t\t\t\t\t.prepend( \"<span class='ui-li-dec'>\" + (counter++) + \". </span>\" );\n\t\t\t}\n\n\t\t\t// Instead of setting item class directly on the list item and its\n\t\t\t// btn-inner at this point in time, push the item into a dictionary\n\t\t\t// that tells us what class to set on it so we can do this after this\n\t\t\t// processing loop is finished.\n\n\t\t\tif ( !itemClassDict[ itemClass ] ) {\n\t\t\t\titemClassDict[ itemClass ] = [];\n\t\t\t}\n\n\t\t\titemClassDict[ itemClass ].push( item[ 0 ] );\n\t\t}\n\n\t\t// Set the appropriate listview item classes on each list item\n\t\t// and their btn-inner elements. The main reason we didn't do this\n\t\t// in the for-loop above is because we can eliminate per-item function overhead\n\t\t// by calling addClass() and children() once or twice afterwards. This\n\t\t// can give us a significant boost on platforms like WP7.5.\n\n\t\tfor ( itemClass in itemClassDict ) {\n\t\t\t$( itemClassDict[ itemClass ] ).addClass( itemClass ).children( \".ui-btn-inner\" ).addClass( itemClass );\n\t\t}\n\n\t\t$list.find( \"h1, h2, h3, h4, h5, h6\" ).addClass( \"ui-li-heading\" )\n\t\t\t.end()\n\n\t\t\t.find( \"p, dl\" ).addClass( \"ui-li-desc\" )\n\t\t\t.end()\n\n\t\t\t.find( \".ui-li-aside\" ).each(function() {\n\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\t$this.prependTo( $this.parent() ); //shift aside to front for css float\n\t\t\t\t})\n\t\t\t.end()\n\n\t\t\t.find( \".ui-li-count\" ).each( function() {\n\t\t\t\t\t$( this ).closest( \"li\" ).addClass( \"ui-li-has-count\" );\n\t\t\t\t}).addClass( \"ui-btn-up-\" + ( $list.jqmData( \"counttheme\" ) || this.options.countTheme) + \" ui-btn-corner-all\" );\n\n\t\t// The idea here is to look at the first image in the list item\n\t\t// itself, and any .ui-link-inherit element it may contain, so we\n\t\t// can place the appropriate classes on the image and list item.\n\t\t// Note that we used to use something like:\n\t\t//\n\t\t//    li.find(\">img:eq(0), .ui-link-inherit>img:eq(0)\").each( ... );\n\t\t//\n\t\t// But executing a find() like that on Windows Phone 7.5 took a\n\t\t// really long time. Walking things manually with the code below\n\t\t// allows the 400 listview item page to load in about 3 seconds as\n\t\t// opposed to 30 seconds.\n\n\t\tthis._addThumbClasses( li );\n\t\tthis._addThumbClasses( $list.find( \".ui-link-inherit\" ) );\n\n\t\tthis._refreshCorners( create );\n\t},\n\n\t//create a string for ID/subpage url creation\n\t_idStringEscape: function( str ) {\n\t\treturn str.replace(/[^a-zA-Z0-9]/g, '-');\n\t},\n\n\t_createSubPages: function() {\n\t\tvar parentList = this.element,\n\t\t\tparentPage = parentList.closest( \".ui-page\" ),\n\t\t\tparentUrl = parentPage.jqmData( \"url\" ),\n\t\t\tparentId = parentUrl || parentPage[ 0 ][ $.expando ],\n\t\t\tparentListId = parentList.attr( \"id\" ),\n\t\t\to = this.options,\n\t\t\tdns = \"data-\" + $.mobile.ns,\n\t\t\tself = this,\n\t\t\tpersistentFooterID = parentPage.find( \":jqmData(role='footer')\" ).jqmData( \"id\" ),\n\t\t\thasSubPages;\n\n\t\tif ( typeof listCountPerPage[ parentId ] === \"undefined\" ) {\n\t\t\tlistCountPerPage[ parentId ] = -1;\n\t\t}\n\n\t\tparentListId = parentListId || ++listCountPerPage[ parentId ];\n\n\t\t$( parentList.find( \"li>ul, li>ol\" ).toArray().reverse() ).each(function( i ) {\n\t\t\tvar self = this,\n\t\t\t\tlist = $( this ),\n\t\t\t\tlistId = list.attr( \"id\" ) || parentListId + \"-\" + i,\n\t\t\t\tparent = list.parent(),\n\t\t\t\tnodeEls = $( list.prevAll().toArray().reverse() ),\n\t\t\t\tnodeEls = nodeEls.length ? nodeEls : $( \"<span>\" + $.trim(parent.contents()[ 0 ].nodeValue) + \"</span>\" ),\n\t\t\t\ttitle = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text\n\t\t\t\tid = ( parentUrl || \"\" ) + \"&\" + $.mobile.subPageUrlKey + \"=\" + listId,\n\t\t\t\ttheme = list.jqmData( \"theme\" ) || o.theme,\n\t\t\t\tcountTheme = list.jqmData( \"counttheme\" ) || parentList.jqmData( \"counttheme\" ) || o.countTheme,\n\t\t\t\tnewPage, anchor;\n\n\t\t\t//define hasSubPages for use in later removal\n\t\t\thasSubPages = true;\n\n\t\t\tnewPage = list.detach()\n\t\t\t\t\t\t.wrap( \"<div \" + dns + \"role='page' \" +\tdns + \"url='\" + id + \"' \" + dns + \"theme='\" + theme + \"' \" + dns + \"count-theme='\" + countTheme + \"'><div \" + dns + \"role='content'></div></div>\" )\n\t\t\t\t\t\t.parent()\n\t\t\t\t\t\t\t.before( \"<div \" + dns + \"role='header' \" + dns + \"theme='\" + o.headerTheme + \"'><div class='ui-title'>\" + title + \"</div></div>\" )\n\t\t\t\t\t\t\t.after( persistentFooterID ? $( \"<div \" + dns + \"role='footer' \" + dns + \"id='\"+ persistentFooterID +\"'>\") : \"\" )\n\t\t\t\t\t\t\t.parent()\n\t\t\t\t\t\t\t\t.appendTo( $.mobile.pageContainer );\n\n\t\t\tnewPage.page();\n\n\t\t\tanchor = parent.find('a:first');\n\n\t\t\tif ( !anchor.length ) {\n\t\t\t\tanchor = $( \"<a/>\" ).html( nodeEls || title ).prependTo( parent.empty() );\n\t\t\t}\n\n\t\t\tanchor.attr( \"href\", \"#\" + id );\n\n\t\t}).listview();\n\n\t\t// on pagehide, remove any nested pages along with the parent page, as long as they aren't active\n\t\t// and aren't embedded\n\t\tif( hasSubPages &&\n\t\t\tparentPage.is( \":jqmData(external-page='true')\" ) &&\n\t\t\tparentPage.data(\"page\").options.domCache === false ) {\n\n\t\t\tvar newRemove = function( e, ui ){\n\t\t\t\tvar nextPage = ui.nextPage, npURL;\n\n\t\t\t\tif( ui.nextPage ){\n\t\t\t\t\tnpURL = nextPage.jqmData( \"url\" );\n\t\t\t\t\tif( npURL.indexOf( parentUrl + \"&\" + $.mobile.subPageUrlKey ) !== 0 ){\n\t\t\t\t\t\tself.childPages().remove();\n\t\t\t\t\t\tparentPage.remove();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// unbind the original page remove and replace with our specialized version\n\t\t\tparentPage\n\t\t\t\t.unbind( \"pagehide.remove\" )\n\t\t\t\t.bind( \"pagehide.remove\", newRemove);\n\t\t}\n\t},\n\n\t// TODO sort out a better way to track sub pages of the listview this is brittle\n\tchildPages: function(){\n\t\tvar parentUrl = this.parentPage.jqmData( \"url\" );\n\n\t\treturn $( \":jqmData(url^='\"+  parentUrl + \"&\" + $.mobile.subPageUrlKey +\"')\");\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.listview.prototype.enhanceWithin( e.target );\n});\n\n})( jQuery );\n\n/*\n* \"checkboxradio\" plugin\n*/\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.checkboxradio\", $.mobile.widget, {\n\toptions: {\n\t\ttheme: null,\n\t\tinitSelector: \"input[type='checkbox'],input[type='radio']\"\n\t},\n\t_create: function() {\n\t\tvar self = this,\n\t\t\tinput = this.element,\n\t\t\tinheritAttr = function( input, dataAttr ) {\n\t\t\t\treturn input.jqmData( dataAttr ) || input.closest( \"form,fieldset\" ).jqmData( dataAttr )\n\t\t\t},\n\t\t\t// NOTE: Windows Phone could not find the label through a selector\n\t\t\t// filter works though.\n\t\t\tparentLabel = $( input ).closest( \"label\" ),\n\t\t\tlabel = parentLabel.length ? parentLabel : $( input ).closest( \"form,fieldset,:jqmData(role='page'),:jqmData(role='dialog')\" ).find( \"label\" ).filter( \"[for='\" + input[0].id + \"']\" ),\n\t\t\tinputtype = input[0].type,\n\t\t\tmini = inheritAttr( input, \"mini\" ),\n\t\t\tcheckedState = inputtype + \"-on\",\n\t\t\tuncheckedState = inputtype + \"-off\",\n\t\t\ticon = input.parents( \":jqmData(type='horizontal')\" ).length ? undefined : uncheckedState,\n\t\t\ticonpos = inheritAttr( input, \"iconpos\" ),\n\t\t\tactiveBtn = icon ? \"\" : \" \" + $.mobile.activeBtnClass,\n\t\t\tcheckedClass = \"ui-\" + checkedState + activeBtn,\n\t\t\tuncheckedClass = \"ui-\" + uncheckedState,\n\t\t\tcheckedicon = \"ui-icon-\" + checkedState,\n\t\t\tuncheckedicon = \"ui-icon-\" + uncheckedState;\n\n\t\tif ( inputtype !== \"checkbox\" && inputtype !== \"radio\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Expose for other methods\n\t\t$.extend( this, {\n\t\t\tlabel: label,\n\t\t\tinputtype: inputtype,\n\t\t\tcheckedClass: checkedClass,\n\t\t\tuncheckedClass: uncheckedClass,\n\t\t\tcheckedicon: checkedicon,\n\t\t\tuncheckedicon: uncheckedicon\n\t\t});\n\n\t\t// If there's no selected theme check the data attr\n\t\tif( !this.options.theme ) {\n\t\t\tthis.options.theme = $.mobile.getInheritedTheme( this.element, \"c\" );\n\t\t}\n\n\t\tlabel.buttonMarkup({\n\t\t\ttheme: this.options.theme,\n\t\t\ticon: icon,\n\t\t\tshadow: false,\n\t\t\tmini: mini,\n\t\t\ticonpos: iconpos\n\t\t});\n\n\t\t// Wrap the input + label in a div\n\t\tvar wrapper = document.createElement('div');\n\t\twrapper.className = 'ui-' + inputtype;\n\n\t\tinput.add( label ).wrapAll( wrapper );\n\n\t\tlabel.bind({\n\t\t\tvmouseover: function( event ) {\n\t\t\t\tif ( $( this ).parent().is( \".ui-disabled\" ) ) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tvclick: function( event ) {\n\t\t\t\tif ( input.is( \":disabled\" ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tself._cacheVals();\n\n\t\t\t\tinput.prop( \"checked\", inputtype === \"radio\" && true || !input.prop( \"checked\" ) );\n\n\t\t\t\t// trigger click handler's bound directly to the input as a substitute for\n\t\t\t\t// how label clicks behave normally in the browsers\n\t\t\t\t// TODO: it would be nice to let the browser's handle the clicks and pass them\n\t\t\t\t//       through to the associate input. we can swallow that click at the parent\n\t\t\t\t//       wrapper element level\n\t\t\t\tinput.triggerHandler( 'click' );\n\n\t\t\t\t// Input set for common radio buttons will contain all the radio\n\t\t\t\t// buttons, but will not for checkboxes. clearing the checked status\n\t\t\t\t// of other radios ensures the active button state is applied properly\n\t\t\t\tself._getInputSet().not( input ).prop( \"checked\", false );\n\n\t\t\t\tself._updateAll();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\tinput\n\t\t\t.bind({\n\t\t\t\tvmousedown: function() {\n\t\t\t\t\tself._cacheVals();\n\t\t\t\t},\n\n\t\t\t\tvclick: function() {\n\t\t\t\t\tvar $this = $(this);\n\n\t\t\t\t\t// Adds checked attribute to checked input when keyboard is used\n\t\t\t\t\tif ( $this.is( \":checked\" ) ) {\n\n\t\t\t\t\t\t$this.prop( \"checked\", true);\n\t\t\t\t\t\tself._getInputSet().not($this).prop( \"checked\", false );\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t$this.prop( \"checked\", false );\n\t\t\t\t\t}\n\n\t\t\t\t\tself._updateAll();\n\t\t\t\t},\n\n\t\t\t\tfocus: function() {\n\t\t\t\t\tlabel.addClass( $.mobile.focusClass );\n\t\t\t\t},\n\n\t\t\t\tblur: function() {\n\t\t\t\t\tlabel.removeClass( $.mobile.focusClass );\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.refresh();\n\t},\n\n\t_cacheVals: function() {\n\t\tthis._getInputSet().each(function() {\n\t\t\t$(this).jqmData( \"cacheVal\", this.checked );\n\t\t});\n\t},\n\n\t//returns either a set of radios with the same name attribute, or a single checkbox\n\t_getInputSet: function(){\n\t\tif(this.inputtype === \"checkbox\") {\n\t\t\treturn this.element;\n\t\t}\n\n\t\treturn this.element.closest( \"form,fieldset,:jqmData(role='page')\" )\n\t\t\t.find( \"input[name='\"+ this.element[0].name +\"'][type='\"+ this.inputtype +\"']\" );\n\t},\n\n\t_updateAll: function() {\n\t\tvar self = this;\n\n\t\tthis._getInputSet().each(function() {\n\t\t\tvar $this = $(this);\n\n\t\t\tif ( this.checked || self.inputtype === \"checkbox\" ) {\n\t\t\t\t$this.trigger( \"change\" );\n\t\t\t}\n\t\t})\n\t\t.checkboxradio( \"refresh\" );\n\t},\n\n\trefresh: function() {\n\t\tvar input = this.element[0],\n\t\t\tlabel = this.label,\n\t\t\ticon = label.find( \".ui-icon\" );\n\n\t\tif ( input.checked ) {\n\t\t\tlabel.addClass( this.checkedClass ).removeClass( this.uncheckedClass );\n\t\t\ticon.addClass( this.checkedicon ).removeClass( this.uncheckedicon );\n\t\t} else {\n\t\t\tlabel.removeClass( this.checkedClass ).addClass( this.uncheckedClass );\n\t\t\ticon.removeClass( this.checkedicon ).addClass( this.uncheckedicon );\n\t\t}\n\n\t\tif ( input.disabled ) {\n\t\t\tthis.disable();\n\t\t} else {\n\t\t\tthis.enable();\n\t\t}\n\t},\n\n\tdisable: function() {\n\t\tthis.element.prop( \"disabled\", true ).parent().addClass( \"ui-disabled\" );\n\t},\n\n\tenable: function() {\n\t\tthis.element.prop( \"disabled\", false ).parent().removeClass( \"ui-disabled\" );\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.checkboxradio.prototype.enhanceWithin( e.target, true );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.button\", $.mobile.widget, {\n\toptions: {\n\t\ttheme: null,\n\t\ticon: null,\n\t\ticonpos: null,\n\t\tinline: false,\n\t\tcorners: true,\n\t\tshadow: true,\n\t\ticonshadow: true,\n\t\tinitSelector: \"button, [type='button'], [type='submit'], [type='reset'], [type='image']\",\n\t\tmini: false\n\t},\n\t_create: function() {\n\t\tvar $el = this.element,\n\t\t\t$button,\n\t\t\to = this.options,\n\t\t\ttype,\n\t\t\tname,\n\t\t\tclasses = \"\",\n\t\t\t$buttonPlaceholder;\n\n\t\t// if this is a link, check if it's been enhanced and, if not, use the right function\n\t\tif( $el[ 0 ].tagName === \"A\" ) {\n\t \t \t!$el.hasClass( \"ui-btn\" ) && $el.buttonMarkup();\n\t \t \treturn;\n \t \t}\n\n\t\t// get the inherited theme\n\t\t// TODO centralize for all widgets\n\t\tif ( !this.options.theme ) {\n\t\t\tthis.options.theme = $.mobile.getInheritedTheme( this.element, \"c\" );\n\t\t}\n\n\t\t// TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577\n\t\t/* if( $el[0].className.length ) {\n\t\t\tclasses = $el[0].className;\n\t\t} */\n\t\tif( !!~$el[0].className.indexOf( \"ui-btn-left\" ) ) {\n\t\t\tclasses = \"ui-btn-left\";\n\t\t}\n\n\t\tif(  !!~$el[0].className.indexOf( \"ui-btn-right\" ) ) {\n\t\t\tclasses = \"ui-btn-right\";\n\t\t}\n\n\t\t// Add ARIA role\n\t\tthis.button = $( \"<div></div>\" )\n\t\t\t.text( $el.text() || $el.val() )\n\t\t\t.insertBefore( $el )\n\t\t\t.buttonMarkup({\n\t\t\t\ttheme: o.theme,\n\t\t\t\ticon: o.icon,\n\t\t\t\ticonpos: o.iconpos,\n\t\t\t\tinline: o.inline,\n\t\t\t\tcorners: o.corners,\n\t\t\t\tshadow: o.shadow,\n\t\t\t\ticonshadow: o.iconshadow,\n\t\t\t\tmini: o.mini\n\t\t\t})\n\t\t\t.addClass( classes )\n\t\t\t.append( $el.addClass( \"ui-btn-hidden\" ) );\n\n        $button = this.button;\n\t\ttype = $el.attr( \"type\" );\n\t\tname = $el.attr( \"name\" );\n\n\t\t// Add hidden input during submit if input type=\"submit\" has a name.\n\t\tif ( type !== \"button\" && type !== \"reset\" && name ) {\n\t\t\t\t$el.bind( \"vclick\", function() {\n\t\t\t\t\t// Add hidden input if it doesn’t already exist.\n\t\t\t\t\tif( $buttonPlaceholder === undefined ) {\n\t\t\t\t\t\t$buttonPlaceholder = $( \"<input>\", {\n\t\t\t\t\t\t\ttype: \"hidden\",\n\t\t\t\t\t\t\tname: $el.attr( \"name\" ),\n\t\t\t\t\t\t\tvalue: $el.attr( \"value\" )\n\t\t\t\t\t\t}).insertBefore( $el );\n\n\t\t\t\t\t\t// Bind to doc to remove after submit handling\n\t\t\t\t\t\t$( document ).one(\"submit\", function(){\n\t\t\t\t\t\t\t$buttonPlaceholder.remove();\n\n\t\t\t\t\t\t\t// reset the local var so that the hidden input\n\t\t\t\t\t\t\t// will be re-added on subsequent clicks\n\t\t\t\t\t\t\t$buttonPlaceholder = undefined;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\n        $el.bind({\n            focus: function() {\n                $button.addClass( $.mobile.focusClass );\n            },\n\n            blur: function() {\n                $button.removeClass( $.mobile.focusClass );\n            }\n        });\n\n\t\tthis.refresh();\n\t},\n\n\tenable: function() {\n\t\tthis.element.attr( \"disabled\", false );\n\t\tthis.button.removeClass( \"ui-disabled\" ).attr( \"aria-disabled\", false );\n\t\treturn this._setOption( \"disabled\", false );\n\t},\n\n\tdisable: function() {\n\t\tthis.element.attr( \"disabled\", true );\n\t\tthis.button.addClass( \"ui-disabled\" ).attr( \"aria-disabled\", true );\n\t\treturn this._setOption( \"disabled\", true );\n\t},\n\n\trefresh: function() {\n\t\tvar $el = this.element;\n\n\t\tif ( $el.prop(\"disabled\") ) {\n\t\t\tthis.disable();\n\t\t} else {\n\t\t\tthis.enable();\n\t\t}\n\n\t\t// Grab the button's text element from its implementation-independent data item\n\t\t$( this.button.data( 'buttonElements' ).text ).text( $el.text() || $el.val() );\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.button.prototype.enhanceWithin( e.target, true );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.fn.controlgroup = function( options ) {\n\tfunction flipClasses( els, flCorners  ) {\n\t\tels.removeClass( \"ui-btn-corner-all ui-shadow\" )\n\t\t\t.eq( 0 ).addClass( flCorners[ 0 ] )\n\t\t\t.end()\n\t\t\t.last().addClass( flCorners[ 1 ] ).addClass( \"ui-controlgroup-last\" );\n\t}\n\n\treturn this.each(function() {\n\t\tvar $el = $( this ),\n\t\t\to = $.extend({\n\t\t\t\t\t\tdirection: $el.jqmData( \"type\" ) || \"vertical\",\n\t\t\t\t\t\tshadow: false,\n\t\t\t\t\t\texcludeInvisible: true,\n\t\t\t\t\t\tmini: $el.jqmData( \"mini\" )\n\t\t\t\t\t}, options ),\n\t\t\tgroupheading = $el.children( \"legend\" ),\n\t\t\tflCorners = o.direction == \"horizontal\" ? [ \"ui-corner-left\", \"ui-corner-right\" ] : [ \"ui-corner-top\", \"ui-corner-bottom\" ],\n\t\t\ttype = $el.find( \"input\" ).first().attr( \"type\" );\n\n\t\t// Replace legend with more stylable replacement div\n\t\tif ( groupheading.length ) {\n\t\t\t$el.wrapInner( \"<div class='ui-controlgroup-controls'></div>\" );\n\t\t\t$( \"<div role='heading' class='ui-controlgroup-label'>\" + groupheading.html() + \"</div>\" ).insertBefore( $el.children(0) );\n\t\t\tgroupheading.remove();\n\t\t}\n\n\t\t$el.addClass( \"ui-corner-all ui-controlgroup ui-controlgroup-\" + o.direction );\n\n\t\tflipClasses( $el.find( \".ui-btn\" + ( o.excludeInvisible ? \":visible\" : \"\" ) ).not('.ui-slider-handle'), flCorners );\n\t\tflipClasses( $el.find( \".ui-btn-inner\" ), flCorners );\n\n\t\tif ( o.shadow ) {\n\t\t\t$el.addClass( \"ui-shadow\" );\n\t\t}\n\n\t\tif ( o.mini ) {\n\t\t\t$el.addClass( \"ui-mini\" );\n\t\t}\n\n\t});\n};\n\n// The pagecreate handler for controlgroup is in jquery.mobile.init because of the soft-dependency on the wrapped widgets\n\n})(jQuery);\n\n(function( $, undefined ) {\n\n$( document ).bind( \"pagecreate create\", function( e ){\n\n\t//links within content areas, tests included with page\n\t$( e.target )\n\t\t.find( \"a\" )\n\t\t.jqmEnhanceable()\n\t\t.not( \".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')\" )\n\t\t.addClass( \"ui-link\" );\n\n});\n\n})( jQuery );\n\n\n( function( $ ) {\n\tvar\tmeta = $( \"meta[name=viewport]\" ),\n        initialContent = meta.attr( \"content\" ),\n        disabledZoom = initialContent + \",maximum-scale=1, user-scalable=no\",\n        enabledZoom = initialContent + \",maximum-scale=10, user-scalable=yes\",\n\t\tdisabledInitially = /(user-scalable[\\s]*=[\\s]*no)|(maximum-scale[\\s]*=[\\s]*1)[$,\\s]/.test( initialContent );\n\t\n\t$.mobile.zoom = $.extend( {}, {\n\t\tenabled: !disabledInitially,\n\t\tlocked: false,\n\t\tdisable: function( lock ) {\n\t\t\tif( !disabledInitially && !$.mobile.zoom.locked ){\n\t        \tmeta.attr( \"content\", disabledZoom );\n\t        \t$.mobile.zoom.enabled = false;\n\t\t\t\t$.mobile.zoom.locked = lock || false;\n\t\t\t}\n\t\t},\n\t\tenable: function( unlock ) {\n\t\t\tif( !disabledInitially && ( !$.mobile.zoom.locked || unlock === true ) ){\n\t\t        meta.attr( \"content\", enabledZoom );\n\t\t        $.mobile.zoom.enabled = true;\n\t\t\t\t$.mobile.zoom.locked = false;\n\t\t\t}\n\t\t},\n\t\trestore: function() {\n\t\t\tif( !disabledInitially ){\n\t        \tmeta.attr( \"content\", initialContent );\n\t        \t$.mobile.zoom.enabled = true;\n\t\t\t}\n\t\t}\n\t});\n\n}( jQuery ));\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.textinput\", $.mobile.widget, {\n\toptions: {\n\t\ttheme: null,\n\t\t// This option defaults to true on iOS devices.\n\t\tpreventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( \"AppleWebKit\" ) > -1,\n\t\tinitSelector: \"input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type])\",\n\t\tclearSearchButtonText: \"clear text\"\n\t},\n\n\t_create: function() {\n\n\t\tvar input = this.element,\n\t\t\to = this.options,\n\t\t\ttheme = o.theme || $.mobile.getInheritedTheme( this.element, \"c\" ),\n\t\t\tthemeclass  = \" ui-body-\" + theme,\n\t\t\tmini = input.jqmData(\"mini\") == true,\n\t\t\tminiclass = mini ? \" ui-mini\" : \"\",\n\t\t\tfocusedEl, clearbtn;\n\n\t\t$( \"label[for='\" + input.attr( \"id\" ) + \"']\" ).addClass( \"ui-input-text\" );\n\n\t\tfocusedEl = input.addClass(\"ui-input-text ui-body-\"+ theme );\n\n\t\t// XXX: Temporary workaround for issue 785 (Apple bug 8910589).\n\t\t//      Turn off autocorrect and autocomplete on non-iOS 5 devices\n\t\t//      since the popup they use can't be dismissed by the user. Note\n\t\t//      that we test for the presence of the feature by looking for\n\t\t//      the autocorrect property on the input element. We currently\n\t\t//      have no test for iOS 5 or newer so we're temporarily using\n\t\t//      the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas\n\t\tif ( typeof input[0].autocorrect !== \"undefined\" && !$.support.touchOverflow ) {\n\t\t\t// Set the attribute instead of the property just in case there\n\t\t\t// is code that attempts to make modifications via HTML.\n\t\t\tinput[0].setAttribute( \"autocorrect\", \"off\" );\n\t\t\tinput[0].setAttribute( \"autocomplete\", \"off\" );\n\t\t}\n\n\n\t\t//\"search\" input widget\n\t\tif ( input.is( \"[type='search'],:jqmData(type='search')\" ) ) {\n\n\t\t\tfocusedEl = input.wrap( \"<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield\" + themeclass + miniclass + \"'></div>\" ).parent();\n\t\t\tclearbtn = $( \"<a href='#' class='ui-input-clear' title='\" + o.clearSearchButtonText + \"'>\" + o.clearSearchButtonText + \"</a>\" )\n\t\t\t\t.bind('click', function( event ) {\n\t\t\t\t\tinput\n\t\t\t\t\t\t.val( \"\" )\n\t\t\t\t\t\t.focus()\n\t\t\t\t\t\t.trigger( \"change\" );\n\t\t\t\t\tclearbtn.addClass( \"ui-input-clear-hidden\" );\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t})\n\t\t\t\t.appendTo( focusedEl )\n\t\t\t\t.buttonMarkup({\n\t\t\t\t\ticon: \"delete\",\n\t\t\t\t\ticonpos: \"notext\",\n\t\t\t\t\tcorners: true,\n\t\t\t\t\tshadow: true,\n\t\t\t\t\tmini: mini\n\t\t\t\t});\n\n\t\t\tfunction toggleClear() {\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tclearbtn.toggleClass( \"ui-input-clear-hidden\", !input.val() );\n\t\t\t\t}, 0);\n\t\t\t}\n\n\t\t\ttoggleClear();\n\n\t\t\tinput.bind('paste cut keyup focus change blur', toggleClear);\n\n\t\t} else {\n\t\t\tinput.addClass( \"ui-corner-all ui-shadow-inset\" + themeclass + miniclass );\n\t\t}\n\n\t\tinput.focus(function() {\n\t\t\t\tfocusedEl.addClass( $.mobile.focusClass );\n\t\t\t})\n\t\t\t.blur(function(){\n\t\t\t\tfocusedEl.removeClass( $.mobile.focusClass );\n\t\t\t})\n\t\t\t// In many situations, iOS will zoom into the select upon tap, this prevents that from happening\n\t\t\t.bind( \"focus\", function() {\n\t\t\t\tif( o.preventFocusZoom ){\n\t\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t\t}\n\t\t\t})\n\t\t\t.bind( \"blur\", function() {\n\t\t\t\tif( o.preventFocusZoom ){\n\t\t\t\t\t$.mobile.zoom.enable( true );\n\t\t\t\t}\n\t\t\t});\n\n\t\t// Autogrow\n\t\tif ( input.is( \"textarea\" ) ) {\n\t\t\tvar extraLineHeight = 15,\n\t\t\t\tkeyupTimeoutBuffer = 100,\n\t\t\t\tkeyup = function() {\n\t\t\t\t\tvar scrollHeight = input[ 0 ].scrollHeight,\n\t\t\t\t\t\tclientHeight = input[ 0 ].clientHeight;\n\n\t\t\t\t\tif ( clientHeight < scrollHeight ) {\n\t\t\t\t\t\tinput.height(scrollHeight + extraLineHeight);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tkeyupTimeout;\n\n\t\t\tinput.keyup(function() {\n\t\t\t\tclearTimeout( keyupTimeout );\n\t\t\t\tkeyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );\n\t\t\t});\n\n\t\t\t// binding to pagechange here ensures that for pages loaded via\n\t\t\t// ajax the height is recalculated without user input\n\t\t\t$( document ).one( \"pagechange\", keyup );\n\n\t\t\t// Issue 509: the browser is not providing scrollHeight properly until the styles load\n\t\t\tif ( $.trim( input.val() ) ) {\n\t\t\t\t// bind to the window load to make sure the height is calculated based on BOTH\n\t\t\t\t// the DOM and CSS\n\t\t\t\t$( window ).load( keyup );\n\t\t\t}\n\t\t}\n\t},\n\n\tdisable: function(){\n\t\t( this.element.attr( \"disabled\", true ).is( \"[type='search'],:jqmData(type='search')\" ) ?\n\t\t\tthis.element.parent() : this.element ).addClass( \"ui-disabled\" );\n\t},\n\n\tenable: function(){\n\t\t( this.element.attr( \"disabled\", false).is( \"[type='search'],:jqmData(type='search')\" ) ?\n\t\t\tthis.element.parent() : this.element ).removeClass( \"ui-disabled\" );\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.textinput.prototype.enhanceWithin( e.target, true );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.mobile.listview.prototype.options.filter = false;\n$.mobile.listview.prototype.options.filterPlaceholder = \"Filter items...\";\n$.mobile.listview.prototype.options.filterTheme = \"c\";\n$.mobile.listview.prototype.options.filterCallback = function( text, searchValue ){\n\treturn text.toLowerCase().indexOf( searchValue ) === -1;\n};\n\n$( document ).delegate( \":jqmData(role='listview')\", \"listviewcreate\", function() {\n\n\tvar list = $( this ),\n\t\tlistview = list.data( \"listview\" );\n\n\tif ( !listview.options.filter ) {\n\t\treturn;\n\t}\n\n\tvar wrapper = $( \"<form>\", {\n\t\t\t\"class\": \"ui-listview-filter ui-bar-\" + listview.options.filterTheme,\n\t\t\t\"role\": \"search\"\n\t\t}),\n\t\tsearch = $( \"<input>\", {\n\t\t\tplaceholder: listview.options.filterPlaceholder\n\t\t})\n\t\t.attr( \"data-\" + $.mobile.ns + \"type\", \"search\" )\n\t\t.jqmData( \"lastval\", \"\" )\n\t\t.bind( \"keyup change\", function() {\n\n\t\t\tvar $this = $(this),\n\t\t\t\tval = this.value.toLowerCase(),\n\t\t\t\tlistItems = null,\n\t\t\t\tlastval = $this.jqmData( \"lastval\" ) + \"\",\n\t\t\t\tchildItems = false,\n\t\t\t\titemtext = \"\",\n\t\t\t\titem;\n\n\t\t\t// Change val as lastval for next execution\n\t\t\t$this.jqmData( \"lastval\" , val );\n\t\t\tif ( val.length < lastval.length || val.indexOf(lastval) !== 0 ) {\n\n\t\t\t\t// Removed chars or pasted something totally different, check all items\n\t\t\t\tlistItems = list.children();\n\t\t\t} else {\n\n\t\t\t\t// Only chars added, not removed, only use visible subset\n\t\t\t\tlistItems = list.children( \":not(.ui-screen-hidden)\" );\n\t\t\t}\n\n\t\t\tif ( val ) {\n\n\t\t\t\t// This handles hiding regular rows without the text we search for\n\t\t\t\t// and any list dividers without regular rows shown under it\n\n\t\t\t\tfor ( var i = listItems.length - 1; i >= 0; i-- ) {\n\t\t\t\t\titem = $( listItems[ i ] );\n\t\t\t\t\titemtext = item.jqmData( \"filtertext\" ) || item.text();\n\n\t\t\t\t\tif ( item.is( \"li:jqmData(role=list-divider)\" ) ) {\n\n\t\t\t\t\t\titem.toggleClass( \"ui-filter-hidequeue\" , !childItems );\n\n\t\t\t\t\t\t// New bucket!\n\t\t\t\t\t\tchildItems = false;\n\n\t\t\t\t\t} else if ( listview.options.filterCallback( itemtext, val ) ) {\n\n\t\t\t\t\t\t//mark to be hidden\n\t\t\t\t\t\titem.toggleClass( \"ui-filter-hidequeue\" , true );\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// There's a shown item in the bucket\n\t\t\t\t\t\tchildItems = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Show items, not marked to be hidden\n\t\t\t\tlistItems\n\t\t\t\t\t.filter( \":not(.ui-filter-hidequeue)\" )\n\t\t\t\t\t.toggleClass( \"ui-screen-hidden\", false );\n\n\t\t\t\t// Hide items, marked to be hidden\n\t\t\t\tlistItems\n\t\t\t\t\t.filter( \".ui-filter-hidequeue\" )\n\t\t\t\t\t.toggleClass( \"ui-screen-hidden\", true )\n\t\t\t\t\t.toggleClass( \"ui-filter-hidequeue\", false );\n\n\t\t\t} else {\n\n\t\t\t\t//filtervalue is empty => show all\n\t\t\t\tlistItems.toggleClass( \"ui-screen-hidden\", false );\n\t\t\t}\n\t\t\tlistview._refreshCorners();\n\t\t})\n\t\t.appendTo( wrapper )\n\t\t.textinput();\n\n\tif ( listview.options.inset ) {\n\t\twrapper.addClass( \"ui-listview-filter-inset\" );\n\t}\n\n\twrapper.bind( \"submit\", function() {\n\t\treturn false;\n\t})\n\t.insertBefore( list );\n});\n\n})( jQuery );\n\n( function( $, undefined ) {\n\n$.widget( \"mobile.slider\", $.mobile.widget, {\n\toptions: {\n\t\ttheme: null,\n\t\ttrackTheme: null,\n\t\tdisabled: false,\n\t\tinitSelector: \"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')\",\n\t\tmini: false\n\t},\n\n\t_create: function() {\n\n\t\t// TODO: Each of these should have comments explain what they're for\n\t\tvar self = this,\n\n\t\t\tcontrol = this.element,\n\n\t\t\tparentTheme = $.mobile.getInheritedTheme( control, \"c\" ),\n\n\t\t\ttheme = this.options.theme || parentTheme,\n\n\t\t\ttrackTheme = this.options.trackTheme || parentTheme,\n\n\t\t\tcType = control[ 0 ].nodeName.toLowerCase(),\n\n\t\t\tselectClass = ( cType == \"select\" ) ? \"ui-slider-switch\" : \"\",\n\n\t\t\tcontrolID = control.attr( \"id\" ),\n\n\t\t\tlabelID = controlID + \"-label\",\n\n\t\t\tlabel = $( \"[for='\"+ controlID +\"']\" ).attr( \"id\", labelID ),\n\n\t\t\tval = function() {\n\t\t\t\treturn  cType == \"input\"  ? parseFloat( control.val() ) : control[0].selectedIndex;\n\t\t\t},\n\n\t\t\tmin =  cType == \"input\" ? parseFloat( control.attr( \"min\" ) ) : 0,\n\n\t\t\tmax =  cType == \"input\" ? parseFloat( control.attr( \"max\" ) ) : control.find( \"option\" ).length-1,\n\n\t\t\tstep = window.parseFloat( control.attr( \"step\" ) || 1 ),\n\n\t\t\tinlineClass = ( this.options.inline || control.jqmData(\"inline\") == true ) ? \" ui-slider-inline\" : \"\",\n\n\t\t\tminiClass = ( this.options.mini || control.jqmData(\"mini\") ) ? \" ui-slider-mini\" : \"\",\n\n\n\t\t\tdomHandle = document.createElement('a'),\n\t\t\thandle = $( domHandle ),\n\t\t\tdomSlider = document.createElement('div'),\n\t\t\tslider = $( domSlider ),\n\n\t\t\tvaluebg = control.jqmData(\"highlight\") && cType != \"select\" ? (function() {\n\t\t\t\tvar bg = document.createElement('div');\n\t\t\t\tbg.className = 'ui-slider-bg ui-btn-active ui-btn-corner-all';\n\t\t\t\treturn $( bg ).prependTo( slider );\n\t\t\t})() : false,\n\n\t\t\toptions;\n\n        domHandle.setAttribute( 'href', \"#\" );\n\t\tdomSlider.setAttribute('role','application');\n\t\tdomSlider.className = ['ui-slider ',selectClass,\" ui-btn-down-\",trackTheme,' ui-btn-corner-all', inlineClass, miniClass].join(\"\");\n\t\tdomHandle.className = 'ui-slider-handle';\n\t\tdomSlider.appendChild(domHandle);\n\n\t\thandle.buttonMarkup({ corners: true, theme: theme, shadow: true })\n\t\t\t\t.attr({\n\t\t\t\t\t\"role\": \"slider\",\n\t\t\t\t\t\"aria-valuemin\": min,\n\t\t\t\t\t\"aria-valuemax\": max,\n\t\t\t\t\t\"aria-valuenow\": val(),\n\t\t\t\t\t\"aria-valuetext\": val(),\n\t\t\t\t\t\"title\": val(),\n\t\t\t\t\t\"aria-labelledby\": labelID\n\t\t\t\t});\n\n\t\t$.extend( this, {\n\t\t\tslider: slider,\n\t\t\thandle: handle,\n\t\t\tvaluebg: valuebg,\n\t\t\tdragging: false,\n\t\t\tbeforeStart: null,\n\t\t\tuserModified: false,\n\t\t\tmouseMoved: false\n\t\t});\n\n\t\tif ( cType == \"select\" ) {\n\t\t\tvar wrapper = document.createElement('div');\n\t\t\twrapper.className = 'ui-slider-inneroffset';\n\n\t\t\tfor(var j = 0,length = domSlider.childNodes.length;j < length;j++){\n\t\t\t\twrapper.appendChild(domSlider.childNodes[j]);\n\t\t\t}\n\n\t\t\tdomSlider.appendChild(wrapper);\n\n\t\t\t// slider.wrapInner( \"<div class='ui-slider-inneroffset'></div>\" );\n\n\t\t\t// make the handle move with a smooth transition\n\t\t\thandle.addClass( \"ui-slider-handle-snapping\" );\n\n\t\t\toptions = control.find( \"option\" );\n\n\t\t\tfor(var i = 0, optionsCount = options.length; i < optionsCount; i++){\n\t\t\t\tvar side = !i ? \"b\":\"a\",\n\t\t\t\t\tsliderTheme = !i ? \" ui-btn-down-\" + trackTheme :( \" \" + $.mobile.activeBtnClass ),\n\t\t\t\t\tsliderLabel = document.createElement('div'),\n\t\t\t\t\tsliderImg = document.createElement('span');\n\n\t\t\t\tsliderImg.className = ['ui-slider-label ui-slider-label-',side,sliderTheme,\" ui-btn-corner-all\"].join(\"\");\n\t\t\t\tsliderImg.setAttribute('role','img');\n\t\t\t\tsliderImg.appendChild(document.createTextNode(options[i].innerHTML));\n\t\t\t\t$(sliderImg).prependTo( slider );\n\t\t\t}\n\n\t\t\tself._labels = $( \".ui-slider-label\", slider );\n\n\t\t}\n\n\t\tlabel.addClass( \"ui-slider\" );\n\n\t\t// monitor the input for updated values\n\t\tcontrol.addClass( cType === \"input\" ? \"ui-slider-input\" : \"ui-slider-switch\" )\n\t\t\t.change( function() {\n\t\t\t\t// if the user dragged the handle, the \"change\" event was triggered from inside refresh(); don't call refresh() again\n\t\t\t\tif (!self.mouseMoved) {\n\t\t\t\t\tself.refresh( val(), true );\n\t\t\t\t}\n\t\t\t})\n\t\t\t.keyup( function() { // necessary?\n\t\t\t\tself.refresh( val(), true, true );\n\t\t\t})\n\t\t\t.blur( function() {\n\t\t\t\tself.refresh( val(), true );\n\t\t\t});\n\n\t\t// prevent screen drag when slider activated\n\t\t$( document ).bind( \"vmousemove\", function( event ) {\n\t\t\tif ( self.dragging ) {\n\t\t\t\t// self.mouseMoved must be updated before refresh() because it will be used in the control \"change\" event\n\t\t\t\tself.mouseMoved = true;\n\n\t\t\t\tif ( cType === \"select\" ) {\n\t\t\t\t\t// make the handle move in sync with the mouse\n\t\t\t\t\thandle.removeClass( \"ui-slider-handle-snapping\" );\n\t\t\t\t}\n\n\t\t\t\tself.refresh( event );\n\n\t\t\t\t// only after refresh() you can calculate self.userModified\n\t\t\t\tself.userModified = self.beforeStart !== control[0].selectedIndex;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\tslider.bind( \"vmousedown\", function( event ) {\n\t\t\tself.dragging = true;\n\t\t\tself.userModified = false;\n\t\t\tself.mouseMoved = false;\n\n\t\t\tif ( cType === \"select\" ) {\n\t\t\t\tself.beforeStart = control[0].selectedIndex;\n\t\t\t}\n\n\t\t\tself.refresh( event );\n\t\t\treturn false;\n\t\t})\n\t\t.bind( \"vclick\", false );\n\n\t\tslider.add( document )\n\t\t\t.bind( \"vmouseup\", function() {\n\t\t\t\tif ( self.dragging ) {\n\n\t\t\t\t\tself.dragging = false;\n\n\t\t\t\t\tif ( cType === \"select\") {\n\n\t\t\t\t\t\t// make the handle move with a smooth transition\n\t\t\t\t\t\thandle.addClass( \"ui-slider-handle-snapping\" );\n\n\t\t\t\t\t\tif ( self.mouseMoved ) {\n\n\t\t\t\t\t\t\t// this is a drag, change the value only if user dragged enough\n\t\t\t\t\t\t\tif ( self.userModified ) {\n\t\t\t\t\t\t\t\tself.refresh( self.beforeStart == 0 ? 1 : 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tself.refresh( self.beforeStart );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t// this is just a click, change the value\n\t\t\t\t\t\t\tself.refresh( self.beforeStart == 0 ? 1 : 0 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tself.mouseMoved = false;\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\n\t\tslider.insertAfter( control );\n\n\t\t// Only add focus class to toggle switch, sliders get it automatically from ui-btn\n\t\tif( cType == 'select' ) {\n\t\t\tthis.handle.bind({\n\t\t\t\tfocus: function() {\n\t\t\t\t\tslider.addClass( $.mobile.focusClass );\n\t\t\t\t},\n\n\t\t\t\tblur: function() {\n\t\t\t\t\tslider.removeClass( $.mobile.focusClass );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tthis.handle.bind({\n\t\t\t// NOTE force focus on handle\n\t\t\tvmousedown: function() {\n\t\t\t\t$( this ).focus();\n\t\t\t},\n\n\t\t\tvclick: false,\n\n\t\t\tkeydown: function( event ) {\n\t\t\t\tvar index = val();\n\n\t\t\t\tif ( self.options.disabled ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// In all cases prevent the default and mark the handle as active\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\t\tcase $.mobile.keyCode.HOME:\n\t\t\t\t\tcase $.mobile.keyCode.END:\n\t\t\t\t\tcase $.mobile.keyCode.PAGE_UP:\n\t\t\t\t\tcase $.mobile.keyCode.PAGE_DOWN:\n\t\t\t\t\tcase $.mobile.keyCode.UP:\n\t\t\t\t\tcase $.mobile.keyCode.RIGHT:\n\t\t\t\t\tcase $.mobile.keyCode.DOWN:\n\t\t\t\t\tcase $.mobile.keyCode.LEFT:\n\t\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t\tif ( !self._keySliding ) {\n\t\t\t\t\t\t\tself._keySliding = true;\n\t\t\t\t\t\t\t$( this ).addClass( \"ui-state-active\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// move the slider according to the keypress\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\t\tcase $.mobile.keyCode.HOME:\n\t\t\t\t\t\tself.refresh( min );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.mobile.keyCode.END:\n\t\t\t\t\t\tself.refresh( max );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.mobile.keyCode.PAGE_UP:\n\t\t\t\t\tcase $.mobile.keyCode.UP:\n\t\t\t\t\tcase $.mobile.keyCode.RIGHT:\n\t\t\t\t\t\tself.refresh( index + step );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $.mobile.keyCode.PAGE_DOWN:\n\t\t\t\t\tcase $.mobile.keyCode.DOWN:\n\t\t\t\t\tcase $.mobile.keyCode.LEFT:\n\t\t\t\t\t\tself.refresh( index - step );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}, // remove active mark\n\n\t\t\tkeyup: function( event ) {\n\t\t\t\tif ( self._keySliding ) {\n\t\t\t\t\tself._keySliding = false;\n\t\t\t\t\t$( this ).removeClass( \"ui-state-active\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\t});\n\n\t\tthis.refresh(undefined, undefined, true);\n\t},\n\n\trefresh: function( val, isfromControl, preventInputUpdate ) {\n\n\t\tif ( this.options.disabled || this.element.attr('disabled')) {\n\t\t\tthis.disable();\n\t\t}\n\n\t\tvar control = this.element, percent,\n\t\t\tcType = control[0].nodeName.toLowerCase(),\n\t\t\tmin = cType === \"input\" ? parseFloat( control.attr( \"min\" ) ) : 0,\n\t\t\tmax = cType === \"input\" ? parseFloat( control.attr( \"max\" ) ) : control.find( \"option\" ).length - 1,\n\t\t\tstep = (cType === \"input\" && parseFloat( control.attr( \"step\" ) ) > 0) ? parseFloat(control.attr(\"step\")) : 1;\n\n\t\tif ( typeof val === \"object\" ) {\n\t\t\tvar data = val,\n\t\t\t\t// a slight tolerance helped get to the ends of the slider\n\t\t\t\ttol = 8;\n\t\t\tif ( !this.dragging ||\n\t\t\t\t\tdata.pageX < this.slider.offset().left - tol ||\n\t\t\t\t\tdata.pageX > this.slider.offset().left + this.slider.width() + tol ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpercent = Math.round( ( ( data.pageX - this.slider.offset().left ) / this.slider.width() ) * 100 );\n\t\t} else {\n\t\t\tif ( val == null ) {\n\t\t\t\tval = cType === \"input\" ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;\n\t\t\t}\n\t\t\tpercent = ( parseFloat( val ) - min ) / ( max - min ) * 100;\n\t\t}\n\n\t\tif ( isNaN( percent ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( percent < 0 ) {\n\t\t\tpercent = 0;\n\t\t}\n\n\t\tif ( percent > 100 ) {\n\t\t\tpercent = 100;\n\t\t}\n\n\t\tvar newval = ( percent / 100 ) * ( max - min ) + min;\n\n\t\t//from jQuery UI slider, the following source will round to the nearest step\n\t\tvar valModStep = ( newval - min ) % step;\n\t\tvar alignValue = newval - valModStep;\n\n\t\tif ( Math.abs( valModStep ) * 2 >= step ) {\n\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n\t\t}\n\t\t// Since JavaScript has problems with large floats, round\n\t\t// the final value to 5 digits after the decimal point (see jQueryUI: #4124)\n\t\tnewval = parseFloat( alignValue.toFixed(5) );\n\n\t\tif ( newval < min ) {\n\t\t\tnewval = min;\n\t\t}\n\n\t\tif ( newval > max ) {\n\t\t\tnewval = max;\n\t\t}\n\n\t\tthis.handle.css( \"left\", percent + \"%\" );\n\t\tthis.handle.attr( {\n\t\t\t\t\"aria-valuenow\": cType === \"input\" ? newval : control.find( \"option\" ).eq( newval ).attr( \"value\" ),\n\t\t\t\t\"aria-valuetext\": cType === \"input\" ? newval : control.find( \"option\" ).eq( newval ).getEncodedText(),\n\t\t\t\ttitle: cType === \"input\" ? newval : control.find( \"option\" ).eq( newval ).getEncodedText()\n\t\t\t});\n\t\tthis.valuebg && this.valuebg.css( \"width\", percent + \"%\" );\n\n\t\t// drag the label widths\n\t\tif ( this._labels ) {\n\t\t\tvar handlePercent = this.handle.width() / this.slider.width() * 100,\n\t\t\t\taPercent = percent && handlePercent + ( 100 - handlePercent ) * percent / 100,\n\t\t\t\tbPercent = percent === 100 ? 0 : Math.min( handlePercent + 100 - aPercent, 100 );\n\n\t\t\tthis._labels.each(function(){\n\t\t\t\tvar ab = $(this).is( \".ui-slider-label-a\" );\n\t\t\t\t$( this ).width( ( ab ? aPercent : bPercent  ) + \"%\" );\n\t\t\t});\n\t\t}\n\n\t\tif ( !preventInputUpdate ) {\n\t\t\tvar valueChanged = false;\n\n\t\t\t// update control\"s value\n\t\t\tif ( cType === \"input\" ) {\n\t\t\t\tvalueChanged = control.val() !== newval;\n\t\t\t\tcontrol.val( newval );\n\t\t\t} else {\n\t\t\t\tvalueChanged = control[ 0 ].selectedIndex !== newval;\n\t\t\t\tcontrol[ 0 ].selectedIndex = newval;\n\t\t\t}\n\t\t\tif ( !isfromControl && valueChanged ) {\n\t\t\t\tcontrol.trigger( \"change\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tenable: function() {\n\t\tthis.element.attr( \"disabled\", false );\n\t\tthis.slider.removeClass( \"ui-disabled\" ).attr( \"aria-disabled\", false );\n\t\treturn this._setOption( \"disabled\", false );\n\t},\n\n\tdisable: function() {\n\t\tthis.element.attr( \"disabled\", true );\n\t\tthis.slider.addClass( \"ui-disabled\" ).attr( \"aria-disabled\", true );\n\t\treturn this._setOption( \"disabled\", true );\n\t}\n\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.slider.prototype.enhanceWithin( e.target, true );\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.selectmenu\", $.mobile.widget, {\n\toptions: {\n\t\ttheme: null,\n\t\tdisabled: false,\n\t\ticon: \"arrow-d\",\n\t\ticonpos: \"right\",\n\t\tinline: false,\n\t\tcorners: true,\n\t\tshadow: true,\n\t\ticonshadow: true,\n\t\toverlayTheme: \"a\",\n\t\thidePlaceholderMenuItems: true,\n\t\tcloseText: \"Close\",\n\t\tnativeMenu: true,\n\t\t// This option defaults to true on iOS devices.\n\t\tpreventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( \"AppleWebKit\" ) > -1,\n\t\tinitSelector: \"select:not(:jqmData(role='slider'))\",\n\t\tmini: false\n\t},\n\n\t_button: function(){\n\t\treturn $( \"<div/>\" );\n\t},\n\n\t_setDisabled: function( value ) {\n\t\tthis.element.attr( \"disabled\", value );\n\t\tthis.button.attr( \"aria-disabled\", value );\n\t\treturn this._setOption( \"disabled\", value );\n\t},\n\n\t_focusButton : function() {\n\t\tvar self = this;\n\n\t\tsetTimeout( function() {\n\t\t\tself.button.focus();\n\t\t}, 40);\n\t},\n\n  _selectOptions: function() {\n    return this.select.find( \"option\" );\n  },\n\n\t// setup items that are generally necessary for select menu extension\n\t_preExtension: function(){\n\t\tvar classes = \"\";\n\t\t// TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577\n\t\t/* if( $el[0].className.length ) {\n\t\t\tclasses = $el[0].className;\n\t\t} */\n\t\tif( !!~this.element[0].className.indexOf( \"ui-btn-left\" ) ) {\n\t\t\tclasses =  \" ui-btn-left\";\n\t\t}\n\t\t\n\t\tif(  !!~this.element[0].className.indexOf( \"ui-btn-right\" ) ) {\n\t\t\tclasses = \" ui-btn-right\";\n\t\t}\n\t\t\n\t\tthis.select = this.element.wrap( \"<div class='ui-select\" + classes + \"'>\" );\n\t\tthis.selectID  = this.select.attr( \"id\" );\n\t\tthis.label = $( \"label[for='\"+ this.selectID +\"']\" ).addClass( \"ui-select\" );\n\t\tthis.isMultiple = this.select[ 0 ].multiple;\n\t\tif ( !this.options.theme ) {\n\t\t\tthis.options.theme = $.mobile.getInheritedTheme( this.select, \"c\" );\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._preExtension();\n\n \t\t// Allows for extension of the native select for custom selects and other plugins\n\t\t// see select.custom for example extension\n\t\t// TODO explore plugin registration\n\t\tthis._trigger( \"beforeCreate\" );\n\n\t\tthis.button = this._button();\n\n\t\tvar self = this,\n\n\t\t\toptions = this.options,\n\n\t\t\t// IE throws an exception at options.item() function when\n\t\t\t// there is no selected item\n\t\t\t// select first in this case\n\t\t\tselectedIndex = this.select[ 0 ].selectedIndex == -1 ? 0 : this.select[ 0 ].selectedIndex,\n\n\t\t\t// TODO values buttonId and menuId are undefined here\n\t\t\tbutton = this.button\n\t\t\t\t.text( $( this.select[ 0 ].options.item( selectedIndex ) ).text() )\n\t\t\t\t.insertBefore( this.select )\n\t\t\t\t.buttonMarkup( {\n\t\t\t\t\ttheme: options.theme,\n\t\t\t\t\ticon: options.icon,\n\t\t\t\t\ticonpos: options.iconpos,\n\t\t\t\t\tinline: options.inline,\n\t\t\t\t\tcorners: options.corners,\n\t\t\t\t\tshadow: options.shadow,\n\t\t\t\t\ticonshadow: options.iconshadow,\n\t\t\t\t\tmini: options.mini\n\t\t\t\t});\n\n\t\t// Opera does not properly support opacity on select elements\n\t\t// In Mini, it hides the element, but not its text\n\t\t// On the desktop,it seems to do the opposite\n\t\t// for these reasons, using the nativeMenu option results in a full native select in Opera\n\t\tif ( options.nativeMenu && window.opera && window.opera.version ) {\n\t\t\tthis.select.addClass( \"ui-select-nativeonly\" );\n\t\t}\n\n\t\t// Add counter for multi selects\n\t\tif ( this.isMultiple ) {\n\t\t\tthis.buttonCount = $( \"<span>\" )\n\t\t\t\t.addClass( \"ui-li-count ui-btn-up-c ui-btn-corner-all\" )\n\t\t\t\t.hide()\n\t\t\t\t.appendTo( button.addClass('ui-li-has-count') );\n\t\t}\n\n\t\t// Disable if specified\n\t\tif ( options.disabled || this.element.attr('disabled')) {\n\t\t\tthis.disable();\n\t\t}\n\n\t\t// Events on native select\n\t\tthis.select.change( function() {\n\t\t\tself.refresh();\n\t\t});\n\n\t\tthis.build();\n\t},\n\n\tbuild: function() {\n\t\tvar self = this;\n\n\t\tthis.select\n\t\t\t.appendTo( self.button )\n\t\t\t.bind( \"vmousedown\", function() {\n\t\t\t\t// Add active class to button\n\t\t\t\tself.button.addClass( $.mobile.activeBtnClass );\n\t\t\t})\n            .bind( \"focus\", function() {\n                self.button.addClass( $.mobile.focusClass );\n            })\n            .bind( \"blur\", function() {\n                self.button.removeClass( $.mobile.focusClass );\n            })\n\t\t\t.bind( \"focus vmouseover\", function() {\n\t\t\t\tself.button.trigger( \"vmouseover\" );\n\t\t\t})\n\t\t\t.bind( \"vmousemove\", function() {\n\t\t\t\t// Remove active class on scroll/touchmove\n\t\t\t\tself.button.removeClass( $.mobile.activeBtnClass );\n\t\t\t})\n\t\t\t.bind( \"change blur vmouseout\", function() {\n\t\t\t\tself.button.trigger( \"vmouseout\" )\n\t\t\t\t\t.removeClass( $.mobile.activeBtnClass );\n\t\t\t})\n\t\t\t.bind( \"change blur\", function() {\n\t\t\t\tself.button.removeClass( \"ui-btn-down-\" + self.options.theme );\n\t\t\t});\n\n\t\t// In many situations, iOS will zoom into the select upon tap, this prevents that from happening\n\t\tself.button.bind( \"vmousedown\", function() {\n\t\t\tif( self.options.preventFocusZoom ){\n\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t}\n\t\t})\n\t\t.bind( \"mouseup\", function() {\n\t\t\tif( self.options.preventFocusZoom ){\n\t\t\t\t$.mobile.zoom.enable( true );\n\t\t\t}\n\t\t});\n\t},\n\n\tselected: function() {\n\t\treturn this._selectOptions().filter( \":selected\" );\n\t},\n\n\tselectedIndices: function() {\n\t\tvar self = this;\n\n\t\treturn this.selected().map( function() {\n\t\t\treturn self._selectOptions().index( this );\n\t\t}).get();\n\t},\n\n\tsetButtonText: function() {\n\t\tvar self = this, selected = this.selected();\n\n\t\tthis.button.find( \".ui-btn-text\" ).text( function() {\n\t\t\tif ( !self.isMultiple ) {\n\t\t\t\treturn selected.text();\n\t\t\t}\n\n\t\t\treturn selected.length ? selected.map( function() {\n\t\t\t\treturn $( this ).text();\n\t\t\t}).get().join( \", \" ) : self.placeholder;\n\t\t});\n\t},\n\n\tsetButtonCount: function() {\n\t\tvar selected = this.selected();\n\n\t\t// multiple count inside button\n\t\tif ( this.isMultiple ) {\n\t\t\tthis.buttonCount[ selected.length > 1 ? \"show\" : \"hide\" ]().text( selected.length );\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tthis.setButtonText();\n\t\tthis.setButtonCount();\n\t},\n\n\t// open and close preserved in native selects\n\t// to simplify users code when looping over selects\n\topen: $.noop,\n\tclose: $.noop,\n\n\tdisable: function() {\n\t\tthis._setDisabled( true );\n\t\tthis.button.addClass( \"ui-disabled\" );\n\t},\n\n\tenable: function() {\n\t\tthis._setDisabled( false );\n\t\tthis.button.removeClass( \"ui-disabled\" );\n\t}\n});\n\n//auto self-init widgets\n$( document ).bind( \"pagecreate create\", function( e ){\n\t$.mobile.selectmenu.prototype.enhanceWithin( e.target, true );\n});\n})( jQuery );\n\n/*\n* custom \"selectmenu\" plugin\n*/\n\n(function( $, undefined ) {\n\tvar extendSelect = function( widget ){\n\n\t\tvar select = widget.select,\n\t\t\tselectID  = widget.selectID,\n\t\t\tlabel = widget.label,\n\t\t\tthisPage = widget.select.closest( \".ui-page\" ),\n\t\t\tscreen = $( \"<div>\", {\"class\": \"ui-selectmenu-screen ui-screen-hidden\"} ).appendTo( thisPage ),\n\t\t\tselectOptions = widget._selectOptions(),\n\t\t\tisMultiple = widget.isMultiple = widget.select[ 0 ].multiple,\n\t\t\tbuttonId = selectID + \"-button\",\n\t\t\tmenuId = selectID + \"-menu\",\n\t\t\tmenuPage = $( \"<div data-\" + $.mobile.ns + \"role='dialog' data-\" +$.mobile.ns + \"theme='\"+ widget.options.theme +\"' data-\" +$.mobile.ns + \"overlay-theme='\"+ widget.options.overlayTheme +\"'>\" +\n\t\t\t\t\"<div data-\" + $.mobile.ns + \"role='header'>\" +\n\t\t\t\t\"<div class='ui-title'>\" + label.getEncodedText() + \"</div>\"+\n\t\t\t\t\"</div>\"+\n\t\t\t\t\"<div data-\" + $.mobile.ns + \"role='content'></div>\"+\n\t\t\t\t\"</div>\" ),\n\n\t\t\tlistbox =  $(\"<div>\", { \"class\": \"ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-\" + widget.options.overlayTheme + \" \" + $.mobile.defaultDialogTransition } ).insertAfter(screen),\n\n\t\t\tlist = $( \"<ul>\", {\n\t\t\t\t\"class\": \"ui-selectmenu-list\",\n\t\t\t\t\"id\": menuId,\n\t\t\t\t\"role\": \"listbox\",\n\t\t\t\t\"aria-labelledby\": buttonId\n\t\t\t}).attr( \"data-\" + $.mobile.ns + \"theme\", widget.options.theme ).appendTo( listbox ),\n\n\t\t\theader = $( \"<div>\", {\n\t\t\t\t\"class\": \"ui-header ui-bar-\" + widget.options.theme\n\t\t\t}).prependTo( listbox ),\n\n\t\t\theaderTitle = $( \"<h1>\", {\n\t\t\t\t\"class\": \"ui-title\"\n\t\t\t}).appendTo( header ),\n\n\t\t\tmenuPageContent,\n\t\t\tmenuPageClose,\n\t\t\theaderClose;\n\n\t\tif( widget.isMultiple ) {\n\t\t\theaderClose = $( \"<a>\", {\n\t\t\t\t\"text\": widget.options.closeText,\n\t\t\t\t\"href\": \"#\",\n\t\t\t\t\"class\": \"ui-btn-left\"\n\t\t\t}).attr( \"data-\" + $.mobile.ns + \"iconpos\", \"notext\" ).attr( \"data-\" + $.mobile.ns + \"icon\", \"delete\" ).appendTo( header ).buttonMarkup();\n\t\t}\n\n\t\t$.extend( widget, {\n\t\t\tselect: widget.select,\n\t\t\tselectID: selectID,\n\t\t\tbuttonId: buttonId,\n\t\t\tmenuId: menuId,\n\t\t\tthisPage: thisPage,\n\t\t\tmenuPage: menuPage,\n\t\t\tlabel: label,\n\t\t\tscreen: screen,\n\t\t\tselectOptions: selectOptions,\n\t\t\tisMultiple: isMultiple,\n\t\t\ttheme: widget.options.theme,\n\t\t\tlistbox: listbox,\n\t\t\tlist: list,\n\t\t\theader: header,\n\t\t\theaderTitle: headerTitle,\n\t\t\theaderClose: headerClose,\n\t\t\tmenuPageContent: menuPageContent,\n\t\t\tmenuPageClose: menuPageClose,\n\t\t\tplaceholder: \"\",\n\n\t\t\tbuild: function() {\n\t\t\t\tvar self = this;\n\n\t\t\t\t// Create list from select, update state\n\t\t\t\tself.refresh();\n\n\t\t\t\tself.select.attr( \"tabindex\", \"-1\" ).focus(function() {\n\t\t\t\t\t$( this ).blur();\n\t\t\t\t\tself.button.focus();\n\t\t\t\t});\n\n\t\t\t\t// Button events\n\t\t\t\tself.button.bind( \"vclick keydown\" , function( event ) {\n\t\t\t\t\tif ( event.type == \"vclick\" ||\n\t\t\t\t\t\t\t event.keyCode && ( event.keyCode === $.mobile.keyCode.ENTER ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent.keyCode === $.mobile.keyCode.SPACE ) ) {\n\n\t\t\t\t\t\tself.open();\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Events for list items\n\t\t\t\tself.list.attr( \"role\", \"listbox\" )\n\t\t\t\t\t.bind( \"focusin\", function( e ){\n\t\t\t\t\t\t$( e.target )\n\t\t\t\t\t\t\t.attr( \"tabindex\", \"0\" )\n\t\t\t\t\t\t\t.trigger( \"vmouseover\" );\n\n\t\t\t\t\t})\n\t\t\t\t\t.bind( \"focusout\", function( e ){\n\t\t\t\t\t\t$( e.target )\n\t\t\t\t\t\t\t.attr( \"tabindex\", \"-1\" )\n\t\t\t\t\t\t\t.trigger( \"vmouseout\" );\n\t\t\t\t\t})\n\t\t\t\t\t.delegate( \"li:not(.ui-disabled, .ui-li-divider)\", \"click\", function( event ) {\n\n\t\t\t\t\t\t// index of option tag to be selected\n\t\t\t\t\t\tvar oldIndex = self.select[ 0 ].selectedIndex,\n\t\t\t\t\t\t\tnewIndex = self.list.find( \"li:not(.ui-li-divider)\" ).index( this ),\n\t\t\t\t\t\t\toption = self._selectOptions().eq( newIndex )[ 0 ];\n\n\t\t\t\t\t\t// toggle selected status on the tag for multi selects\n\t\t\t\t\t\toption.selected = self.isMultiple ? !option.selected : true;\n\n\t\t\t\t\t\t// toggle checkbox class for multiple selects\n\t\t\t\t\t\tif ( self.isMultiple ) {\n\t\t\t\t\t\t\t$( this ).find( \".ui-icon\" )\n\t\t\t\t\t\t\t\t.toggleClass( \"ui-icon-checkbox-on\", option.selected )\n\t\t\t\t\t\t\t\t.toggleClass( \"ui-icon-checkbox-off\", !option.selected );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// trigger change if value changed\n\t\t\t\t\t\tif ( self.isMultiple || oldIndex !== newIndex ) {\n\t\t\t\t\t\t\tself.select.trigger( \"change\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//hide custom select for single selects only\n\t\t\t\t\t\tif ( !self.isMultiple ) {\n\t\t\t\t\t\t\tself.close();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t})\n\t\t\t\t\t.keydown(function( event ) {  //keyboard events for menu items\n\t\t\t\t\t\tvar target = $( event.target ),\n\t\t\t\t\t\t\tli = target.closest( \"li\" ),\n\t\t\t\t\t\t\tprev, next;\n\n\t\t\t\t\t\t// switch logic based on which key was pressed\n\t\t\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\t\t\t\t// up or left arrow keys\n\t\t\t\t\t\t case 38:\n\t\t\t\t\t\t\tprev = li.prev().not( \".ui-selectmenu-placeholder\" );\n\n\t\t\t\t\t\t\tif( prev.is( \".ui-li-divider\" ) ) {\n\t\t\t\t\t\t\t\tprev = prev.prev();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// if there's a previous option, focus it\n\t\t\t\t\t\t\tif ( prev.length ) {\n\t\t\t\t\t\t\t\ttarget\n\t\t\t\t\t\t\t\t\t.blur()\n\t\t\t\t\t\t\t\t\t.attr( \"tabindex\", \"-1\" );\n\n\t\t\t\t\t\t\t\tprev.addClass( \"ui-btn-down-\" + widget.options.theme ).find( \"a\" ).first().focus();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t// down or right arrow keys\n\t\t\t\t\t\t case 40:\n\t\t\t\t\t\t\tnext = li.next();\n\n\t\t\t\t\t\t\tif( next.is( \".ui-li-divider\" ) ) {\n\t\t\t\t\t\t\t\tnext = next.next();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// if there's a next option, focus it\n\t\t\t\t\t\t\tif ( next.length ) {\n\t\t\t\t\t\t\t\ttarget\n\t\t\t\t\t\t\t\t\t.blur()\n\t\t\t\t\t\t\t\t\t.attr( \"tabindex\", \"-1\" );\n\n\t\t\t\t\t\t\t\tnext.addClass( \"ui-btn-down-\" + widget.options.theme ).find( \"a\" ).first().focus();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t// If enter or space is pressed, trigger click\n\t\t\t\t\t\t case 13:\n\t\t\t\t\t\t case 32:\n\t\t\t\t\t\t\ttarget.trigger( \"click\" );\n\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t// button refocus ensures proper height calculation\n\t\t\t\t// by removing the inline style and ensuring page inclusion\n\t\t\t\tself.menuPage.bind( \"pagehide\", function() {\n\t\t\t\t\tself.list.appendTo( self.listbox );\n\t\t\t\t\tself._focusButton();\n\n\t\t\t\t\t// TODO centralize page removal binding / handling in the page plugin.\n\t\t\t\t\t// Suggestion from @jblas to do refcounting\n\t\t\t\t\t//\n\t\t\t\t\t// TODO extremely confusing dependency on the open method where the pagehide.remove\n\t\t\t\t\t// bindings are stripped to prevent the parent page from disappearing. The way\n\t\t\t\t\t// we're keeping pages in the DOM right now sucks\n\t\t\t\t\t//\n\t\t\t\t\t// rebind the page remove that was unbound in the open function\n\t\t\t\t\t// to allow for the parent page removal from actions other than the use\n\t\t\t\t\t// of a dialog sized custom select\n\t\t\t\t\t//\n\t\t\t\t\t// doing this here provides for the back button on the custom select dialog\n\t\t\t\t\t$.mobile._bindPageRemove.call( self.thisPage );\n\t\t\t\t});\n\n\t\t\t\t// Events on \"screen\" overlay\n\t\t\t\tself.screen.bind( \"vclick\", function( event ) {\n\t\t\t\t\tself.close();\n\t\t\t\t});\n\n\t\t\t\t// Close button on small overlays\n\t\t\t\tif( self.isMultiple ){\n\t\t\t\t\tself.headerClose.click( function() {\n\t\t\t\t\t\tif ( self.menuType == \"overlay\" ) {\n\t\t\t\t\t\t\tself.close();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// track this dependency so that when the parent page\n\t\t\t\t// is removed on pagehide it will also remove the menupage\n\t\t\t\tself.thisPage.addDependents( this.menuPage );\n\t\t\t},\n\n\t\t\t_isRebuildRequired: function() {\n\t\t\t\tvar list = this.list.find( \"li\" ),\n\t\t\t\t\toptions = this._selectOptions();\n\n\t\t\t\t// TODO exceedingly naive method to determine difference\n\t\t\t\t// ignores value changes etc in favor of a forcedRebuild\n\t\t\t\t// from the user in the refresh method\n\t\t\t\treturn options.text() !== list.text();\n\t\t\t},\n\n\t\t\trefresh: function( forceRebuild , foo ){\n\t\t\t\tvar self = this,\n\t\t\t\tselect = this.element,\n\t\t\t\tisMultiple = this.isMultiple,\n\t\t\t\toptions = this._selectOptions(),\n\t\t\t\tselected = this.selected(),\n\t\t\t\t// return an array of all selected index's\n\t\t\t\tindicies = this.selectedIndices();\n\n\t\t\t\tif (  forceRebuild || this._isRebuildRequired() ) {\n\t\t\t\t\tself._buildList();\n\t\t\t\t}\n\n\t\t\t\tself.setButtonText();\n\t\t\t\tself.setButtonCount();\n\n\t\t\t\tself.list.find( \"li:not(.ui-li-divider)\" )\n\t\t\t\t\t.removeClass( $.mobile.activeBtnClass )\n\t\t\t\t\t.attr( \"aria-selected\", false )\n\t\t\t\t\t.each(function( i ) {\n\n\t\t\t\t\t\tif ( $.inArray( i, indicies ) > -1 ) {\n\t\t\t\t\t\t\tvar item = $( this );\n\n\t\t\t\t\t\t\t// Aria selected attr\n\t\t\t\t\t\t\titem.attr( \"aria-selected\", true );\n\n\t\t\t\t\t\t\t// Multiple selects: add the \"on\" checkbox state to the icon\n\t\t\t\t\t\t\tif ( self.isMultiple ) {\n\t\t\t\t\t\t\t\titem.find( \".ui-icon\" ).removeClass( \"ui-icon-checkbox-off\" ).addClass( \"ui-icon-checkbox-on\" );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif( item.is( \".ui-selectmenu-placeholder\" ) ) {\n\t\t\t\t\t\t\t\t\titem.next().addClass( $.mobile.activeBtnClass );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\titem.addClass( $.mobile.activeBtnClass );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t},\n\n\t\t\tclose: function() {\n\t\t\t\tif ( this.options.disabled || !this.isOpen ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar self = this;\n\n\t\t\t\tif ( self.menuType == \"page\" ) {\n\t\t\t\t\t// doesn't solve the possible issue with calling change page\n\t\t\t\t\t// where the objects don't define data urls which prevents dialog key\n\t\t\t\t\t// stripping - changePage has incoming refactor\n\t\t\t\t\twindow.history.back();\n\t\t\t\t} else {\n\t\t\t\t\tself.screen.addClass( \"ui-screen-hidden\" );\n\t\t\t\t\tself.listbox.addClass( \"ui-selectmenu-hidden\" ).removeAttr( \"style\" ).removeClass( \"in\" );\n\t\t\t\t\tself.list.appendTo( self.listbox );\n\t\t\t\t\tself._focusButton();\n\t\t\t\t}\n\n\t\t\t\t// allow the dialog to be closed again\n\t\t\t\tself.isOpen = false;\n\t\t\t},\n\n\t\t\topen: function() {\n\t\t\t\tif ( this.options.disabled ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar self = this,\n          $window = $( window ),\n          selfListParent = self.list.parent(),\n\t\t\t\t\tmenuHeight = selfListParent.outerHeight(),\n\t\t\t\t\tmenuWidth = selfListParent.outerWidth(),\n\t\t\t\t\tactivePage = $( \".ui-page-active\" ),\n\t\t\t\t\ttScrollElem = activePage,\n\t\t\t\t\tscrollTop = $window.scrollTop(),\n\t\t\t\t\tbtnOffset = self.button.offset().top,\n\t\t\t\t\tscreenHeight = $window.height(),\n\t\t\t\t\tscreenWidth = $window.width();\n\n\t\t\t\t//add active class to button\n\t\t\t\tself.button.addClass( $.mobile.activeBtnClass );\n\n\t\t\t\t//remove after delay\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.button.removeClass( $.mobile.activeBtnClass );\n\t\t\t\t}, 300);\n\n\t\t\t\tfunction focusMenuItem() {\n\t\t\t\t\tself.list.find( \".\" + $.mobile.activeBtnClass + \" a\" ).focus();\n\t\t\t\t}\n\n\t\t\t\tif ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {\n\n\t\t\t\t\tself.menuPage.appendTo( $.mobile.pageContainer ).page();\n\t\t\t\t\tself.menuPageContent = menuPage.find( \".ui-content\" );\n\t\t\t\t\tself.menuPageClose = menuPage.find( \".ui-header a\" );\n\n\t\t\t\t\t// prevent the parent page from being removed from the DOM,\n\t\t\t\t\t// otherwise the results of selecting a list item in the dialog\n\t\t\t\t\t// fall into a black hole\n\t\t\t\t\tself.thisPage.unbind( \"pagehide.remove\" );\n\n\t\t\t\t\t//for WebOS/Opera Mini (set lastscroll using button offset)\n\t\t\t\t\tif ( scrollTop == 0 && btnOffset > screenHeight ) {\n\t\t\t\t\t\tself.thisPage.one( \"pagehide\", function() {\n\t\t\t\t\t\t\t$( this ).jqmData( \"lastScroll\", btnOffset );\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tself.menuPage.one( \"pageshow\", function() {\n\t\t\t\t\t\tfocusMenuItem();\n\t\t\t\t\t\tself.isOpen = true;\n\t\t\t\t\t});\n\n\t\t\t\t\tself.menuType = \"page\";\n\t\t\t\t\tself.menuPageContent.append( self.list );\n\t\t\t\t\tself.menuPage.find(\"div .ui-title\").text(self.label.text());\n\t\t\t\t\t$.mobile.changePage( self.menuPage, {\n\t\t\t\t\t\ttransition: $.mobile.defaultDialogTransition\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tself.menuType = \"overlay\";\n\n\t\t\t\t\tself.screen.height( $(document).height() )\n\t\t\t\t\t\t.removeClass( \"ui-screen-hidden\" );\n\n\t\t\t\t\t// Try and center the overlay over the button\n\t\t\t\t\tvar roomtop = btnOffset - scrollTop,\n\t\t\t\t\t\troombot = scrollTop + screenHeight - btnOffset,\n\t\t\t\t\t\thalfheight = menuHeight / 2,\n\t\t\t\t\t\tmaxwidth = parseFloat( self.list.parent().css( \"max-width\" ) ),\n\t\t\t\t\t\tnewtop, newleft;\n\n\t\t\t\t\tif ( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ) {\n\t\t\t\t\t\tnewtop = btnOffset + ( self.button.outerHeight() / 2 ) - halfheight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// 30px tolerance off the edges\n\t\t\t\t\t\tnewtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the menuwidth is smaller than the screen center is\n\t\t\t\t\tif ( menuWidth < maxwidth ) {\n\t\t\t\t\t\tnewleft = ( screenWidth - menuWidth ) / 2;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t//otherwise insure a >= 30px offset from the left\n\t\t\t\t\t\tnewleft = self.button.offset().left + self.button.outerWidth() / 2 - menuWidth / 2;\n\n\t\t\t\t\t\t// 30px tolerance off the edges\n\t\t\t\t\t\tif ( newleft < 30 ) {\n\t\t\t\t\t\t\tnewleft = 30;\n\t\t\t\t\t\t} else if ( (newleft + menuWidth) > screenWidth ) {\n\t\t\t\t\t\t\tnewleft = screenWidth - menuWidth - 30;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tself.listbox.append( self.list )\n\t\t\t\t\t\t.removeClass( \"ui-selectmenu-hidden\" )\n\t\t\t\t\t\t.css({\n\t\t\t\t\t\t\ttop: newtop,\n\t\t\t\t\t\t\tleft: newleft\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.addClass( \"in\" );\n\n\t\t\t\t\tfocusMenuItem();\n\n\t\t\t\t\t// duplicate with value set in page show for dialog sized selects\n\t\t\t\t\tself.isOpen = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t_buildList: function() {\n\t\t\t\tvar self = this,\n\t\t\t\t\to = this.options,\n\t\t\t\t\tplaceholder = this.placeholder,\n\t\t\t\t\tneedPlaceholder = true,\n\t\t\t\t\toptgroups = [],\n\t\t\t\t\tlis = [],\n\t\t\t\t\tdataIcon = self.isMultiple ? \"checkbox-off\" : \"false\";\n\n\t\t\t\tself.list.empty().filter( \".ui-listview\" ).listview( \"destroy\" );\n\n\t\t\t\tvar $options = self.select.find(\"option\"),\n\t\t\t\t\tnumOptions = $options.length,\n\t\t\t\t\tselect = this.select[ 0 ],\n\t\t\t\t\tdataPrefix = 'data-' + $.mobile.ns,\n\t\t\t\t\tdataIndexAttr = dataPrefix + 'option-index',\n\t\t\t\t\tdataIconAttr = dataPrefix + 'icon',\n\t\t\t\t\tdataRoleAttr = dataPrefix + 'role',\n\t\t\t\t\tfragment = document.createDocumentFragment(),\n\t\t\t\t\toptGroup;\n\n\t\t\t\tfor (var i = 0; i < numOptions;i++){\n\t\t\t\t\tvar option = $options[i],\n\t\t\t\t\t\t$option = $(option),\n\t\t\t\t\t\tparent = option.parentNode,\n\t\t\t\t\t\ttext = $option.text(),\n\t\t\t\t\t\tanchor  = document.createElement('a'),\n\t\t\t\t\t\tclasses = [];\n\n\t\t\t\t\tanchor.setAttribute('href','#');\n\t\t\t\t\tanchor.appendChild(document.createTextNode(text));\n\n\t\t\t\t\t// Are we inside an optgroup?\n\t\t\t\t\tif (parent !== select && parent.nodeName.toLowerCase() === \"optgroup\"){\n\t\t\t\t\t\tvar optLabel = parent.getAttribute('label');\n\t\t\t\t\t\tif ( optLabel != optGroup) {\n\t\t\t\t\t\t\tvar divider = document.createElement('li');\n\t\t\t\t\t\t\tdivider.setAttribute(dataRoleAttr,'list-divider');\n\t\t\t\t\t\t\tdivider.setAttribute('role','option');\n\t\t\t\t\t\t\tdivider.setAttribute('tabindex','-1');\n\t\t\t\t\t\t\tdivider.appendChild(document.createTextNode(optLabel));\n\t\t\t\t\t\t\tfragment.appendChild(divider);\n\t\t\t\t\t\t\toptGroup = optLabel;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (needPlaceholder && (!option.getAttribute( \"value\" ) || text.length == 0 || $option.jqmData( \"placeholder\" ))) {\n\t\t\t\t\t\tneedPlaceholder = false;\n\t\t\t\t\t\tif ( o.hidePlaceholderMenuItems ) {\n\t\t\t\t\t\t\tclasses.push( \"ui-selectmenu-placeholder\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!placeholder) {\n\t\t\t\t\t\t\tplaceholder = self.placeholder = text;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar item = document.createElement('li');\n\t\t\t\t\tif ( option.disabled ) {\n\t\t\t\t\t\tclasses.push( \"ui-disabled\" );\n\t\t\t\t\t\titem.setAttribute('aria-disabled',true);\n\t\t\t\t\t}\n\t\t\t\t\titem.setAttribute(dataIndexAttr,i);\n\t\t\t\t\titem.setAttribute(dataIconAttr,dataIcon);\n\t\t\t\t\titem.className = classes.join(\" \");\n\t\t\t\t\titem.setAttribute('role','option');\n\t\t\t\t\tanchor.setAttribute('tabindex','-1');\n\t\t\t\t\titem.appendChild(anchor);\n\t\t\t\t\tfragment.appendChild(item);\n\t\t\t\t}\n\n\t\t\t\tself.list[0].appendChild(fragment);\n\n\t\t\t\t// Hide header if it's not a multiselect and there's no placeholder\n\t\t\t\tif ( !this.isMultiple && !placeholder.length ) {\n\t\t\t\t\tthis.header.hide();\n\t\t\t\t} else {\n\t\t\t\t\tthis.headerTitle.text( this.placeholder );\n\t\t\t\t}\n\n\t\t\t\t// Now populated, create listview\n\t\t\t\tself.list.listview();\n\t\t\t},\n\n\t\t\t_button: function(){\n\t\t\t\treturn $( \"<a>\", {\n\t\t\t\t\t\"href\": \"#\",\n\t\t\t\t\t\"role\": \"button\",\n\t\t\t\t\t// TODO value is undefined at creation\n\t\t\t\t\t\"id\": this.buttonId,\n\t\t\t\t\t\"aria-haspopup\": \"true\",\n\n\t\t\t\t\t// TODO value is undefined at creation\n\t\t\t\t\t\"aria-owns\": this.menuId\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t};\n\n\t// issue #3894 - core doesn't triggered events on disabled delegates\n\t$( document ).bind( \"selectmenubeforecreate\", function( event ){\n\t\tvar selectmenuWidget = $( event.target ).data( \"selectmenu\" );\n\n\t\tif( !selectmenuWidget.options.nativeMenu ){\n\t\t\textendSelect( selectmenuWidget );\n\t\t}\n\t});\n})( jQuery );\n\n(function( $, undefined ) {\n\n\n\t$.widget( \"mobile.fixedtoolbar\", $.mobile.widget, {\n\t\toptions: {\n\t\t\tvisibleOnPageShow: true,\n\t\t\tdisablePageZoom: true,\n\t\t\ttransition: \"slide\", //can be none, fade, slide (slide maps to slideup or slidedown)\n\t\t\tfullscreen: false,\n\t\t\ttapToggle: true,\n\t\t\ttapToggleBlacklist: \"a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed\",\n\t\t\thideDuringFocus: \"input, textarea, select\",\n\t\t\tupdatePagePadding: true,\n\t\t\ttrackPersistentToolbars: true,\n\n\t\t\t// Browser detection! Weeee, here we go...\n\t\t\t// Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.\n\t\t\t// Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.\n\t\t\t// Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window\n\t\t\t// The following function serves to rule out some popular browsers with known fixed-positioning issues\n\t\t\t// This is a plugin option like any other, so feel free to improve or overwrite it\n\t\t\tsupportBlacklist: function(){\n\t\t\t\tvar w = window,\n\t\t\t\t\tua = navigator.userAgent,\n\t\t\t\t\tplatform = navigator.platform,\n\t\t\t\t\t// Rendering engine is Webkit, and capture major version\n\t\t\t\t\twkmatch = ua.match( /AppleWebKit\\/([0-9]+)/ ),\n\t\t\t\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n\t\t\t\t\tffmatch = ua.match( /Fennec\\/([0-9]+)/ ),\n\t\t\t\t\tffversion = !!ffmatch && ffmatch[ 1 ],\n\t\t\t\t\toperammobilematch = ua.match( /Opera Mobi\\/([0-9]+)/ ),\n\t\t\t\t\tomversion = !!operammobilematch && operammobilematch[ 1 ];\n\n\t\t\t\tif(\n\t\t\t\t\t// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)\n\t\t\t\t\t( ( platform.indexOf( \"iPhone\" ) > -1 || platform.indexOf( \"iPad\" ) > -1  || platform.indexOf( \"iPod\" ) > -1 ) && wkversion && wkversion < 534 )\n\t\t\t\t\t||\n\t\t\t\t\t// Opera Mini\n\t\t\t\t\t( w.operamini && ({}).toString.call( w.operamini ) === \"[object OperaMini]\" )\n\t\t\t\t\t||\n\t\t\t\t\t( operammobilematch && omversion < 7458 )\n\t\t\t\t\t||\n\t\t\t\t\t//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)\n\t\t\t\t\t( ua.indexOf( \"Android\" ) > -1 && wkversion && wkversion < 533 )\n\t\t\t\t\t||\n\t\t\t\t\t// Firefox Mobile before 6.0 -\n\t\t\t\t\t( ffversion && ffversion < 6 )\n\t\t\t\t\t||\n\t\t\t\t\t// WebOS less than 3\n\t\t\t\t\t( \"palmGetResource\" in window && wkversion && wkversion < 534 )\n\t\t\t\t\t||\n\t\t\t\t\t// MeeGo\n\t\t\t\t\t( ua.indexOf( \"MeeGo\" ) > -1 && ua.indexOf( \"NokiaBrowser/8.5.0\" ) > -1 )\n\t\t\t\t){\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tinitSelector: \":jqmData(position='fixed')\"\n\t\t},\n\n\t\t_create: function() {\n\n\t\t\tvar self = this,\n\t\t\t\to = self.options,\n\t\t\t\t$el = self.element,\n\t\t\t\ttbtype = $el.is( \":jqmData(role='header')\" ) ? \"header\" : \"footer\",\n\t\t\t\t$page = $el.closest(\".ui-page\");\n\n\t\t\t// Feature detecting support for\n\t\t\tif( o.supportBlacklist() ){\n\t\t\t\tself.destroy();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$el.addClass( \"ui-\"+ tbtype +\"-fixed\" );\n\n\t\t\t// \"fullscreen\" overlay positioning\n\t\t\tif( o.fullscreen ){\n\t\t\t\t$el.addClass( \"ui-\"+ tbtype +\"-fullscreen\" );\n\t\t\t\t$page.addClass( \"ui-page-\" + tbtype + \"-fullscreen\" );\n\t\t\t}\n\t\t\t// If not fullscreen, add class to page to set top or bottom padding\n\t\t\telse{\n\t\t\t\t$page.addClass( \"ui-page-\" + tbtype + \"-fixed\" );\n\t\t\t}\n\n\t\t\tself._addTransitionClass();\n\t\t\tself._bindPageEvents();\n\t\t\tself._bindToggleHandlers();\n\t\t},\n\n\t\t_addTransitionClass: function(){\n\t\t\tvar tclass = this.options.transition;\n\n\t\t\tif( tclass && tclass !== \"none\" ){\n\t\t\t\t// use appropriate slide for header or footer\n\t\t\t\tif( tclass === \"slide\" ){\n\t\t\t\t\ttclass = this.element.is( \".ui-header\" ) ? \"slidedown\" : \"slideup\";\n\t\t\t\t}\n\n\t\t\t\tthis.element.addClass( tclass );\n\t\t\t}\n\t\t},\n\n\t\t_bindPageEvents: function(){\n\t\t\tvar self = this,\n\t\t\t\to = self.options,\n\t\t\t\t$el = self.element;\n\n\t\t\t//page event bindings\n\t\t\t// Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up\n\t\t\t// This method is meant to disable zoom while a fixed-positioned toolbar page is visible\n\t\t\t$el.closest( \".ui-page\" )\n\t\t\t\t.bind( \"pagebeforeshow\", function(){\n\t\t\t\t\tif( o.disablePageZoom ){\n\t\t\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t\t\t}\n\t\t\t\t\tif( !o.visibleOnPageShow ){\n\t\t\t\t\t\tself.hide( true );\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.bind( \"webkitAnimationStart animationstart updatelayout\", function(){\n\t\t\t\t\tif( o.updatePagePadding ){\n\t\t\t\t\t\tself.updatePagePadding();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( \"pageshow\", function(){\n\t\t\t\t\tself.updatePagePadding();\n\t\t\t\t\tif( o.updatePagePadding ){\n\t\t\t\t\t\t$( window ).bind( \"throttledresize.\" + self.widgetName, function(){\n\t\t\t\t\t\t \tself.updatePagePadding();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( \"pagebeforehide\", function( e, ui ){\n\t\t\t\t\tif( o.disablePageZoom ){\n\t\t\t\t\t\t$.mobile.zoom.enable( true );\n\t\t\t\t\t}\n\t\t\t\t\tif( o.updatePagePadding ){\n\t\t\t\t\t\t$( window ).unbind( \"throttledresize.\" + self.widgetName );\n\t\t\t\t\t}\n\n\t\t\t\t\tif( o.trackPersistentToolbars ){\n\t\t\t\t\t\tvar thisFooter = $( \".ui-footer-fixed:jqmData(id)\", this ),\n\t\t\t\t\t\t\tthisHeader = $( \".ui-header-fixed:jqmData(id)\", this ),\n\t\t\t\t\t\t\tnextFooter = thisFooter.length && ui.nextPage && $( \".ui-footer-fixed:jqmData(id='\" + thisFooter.jqmData( \"id\" ) + \"')\", ui.nextPage ),\n\t\t\t\t\t\t\tnextHeader = thisHeader.length && ui.nextPage && $( \".ui-header-fixed:jqmData(id='\" + thisHeader.jqmData( \"id\" ) + \"')\", ui.nextPage );\n\n\t\t\t\t\t\tnextFooter = nextFooter || $();\n\n\t\t\t\t\t\t\tif( nextFooter.length || nextHeader.length ){\n\n\t\t\t\t\t\t\t\tnextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );\n\n\t\t\t\t\t\t\t\tui.nextPage.one( \"pageshow\", function(){\n\t\t\t\t\t\t\t\t\tnextFooter.add( nextHeader ).appendTo( this );\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t},\n\n\t\t_visible: true,\n\n\t\t// This will set the content element's top or bottom padding equal to the toolbar's height\n\t\tupdatePagePadding: function() {\n\t\t\tvar $el = this.element,\n\t\t\t\theader = $el.is( \".ui-header\" );\n\n\t\t\t// This behavior only applies to \"fixed\", not \"fullscreen\"\n\t\t\tif( this.options.fullscreen ){ return; }\n\n\t\t\t$el.closest( \".ui-page\" ).css( \"padding-\" + ( header ? \"top\" : \"bottom\" ), $el.outerHeight() );\n\t\t},\n\t\t\n\t\t_useTransition: function( notransition ){\n\t\t\tvar $win = $( window ),\n\t\t\t\t$el = this.element,\n\t\t\t\tscroll = $win.scrollTop(),\n\t\t\t\telHeight = $el.height(),\n\t\t\t\tpHeight = $el.closest( \".ui-page\" ).height(),\n\t\t\t\tviewportHeight = $.mobile.getScreenHeight(),\n\t\t\t\ttbtype = $el.is( \":jqmData(role='header')\" ) ? \"header\" : \"footer\";\n\t\t\t\t\n\t\t\treturn !notransition &&\n\t\t\t\t( this.options.transition && this.options.transition !== \"none\" &&\n\t\t\t\t(\n\t\t\t\t\t( tbtype === \"header\" && !this.options.fullscreen && scroll > elHeight ) ||\n\t\t\t\t\t( tbtype === \"footer\" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )\n\t\t\t\t) || this.options.fullscreen\n\t\t\t\t);\n\t\t},\n\n\t\tshow: function( notransition ){\n\t\t\tvar hideClass = \"ui-fixed-hidden\",\n\t\t\t\t$el = this.element;\n\n\t\t\t\tif( this._useTransition( notransition ) ){\n\t\t\t\t$el\n\t\t\t\t\t.removeClass( \"out \" + hideClass )\n\t\t\t\t\t.addClass( \"in\" );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t$el.removeClass( hideClass );\n\t\t\t}\n\t\t\tthis._visible = true;\n\t\t},\n\n\t\thide: function( notransition ){\n\t\t\tvar hideClass = \"ui-fixed-hidden\",\n\t\t\t\t$el = this.element,\n\t\t\t\t// if it's a slide transition, our new transitions need the reverse class as well to slide outward\n\t\t\t\toutclass = \"out\" + ( this.options.transition === \"slide\" ? \" reverse\" : \"\" );\n\n\t\t\tif( this._useTransition( notransition ) ){\n\t\t\t\t$el\n\t\t\t\t\t.addClass( outclass )\n\t\t\t\t\t.removeClass( \"in\" )\n\t\t\t\t\t.animationComplete( function(){\n\t\t\t\t\t\t$el.addClass( hideClass ).removeClass( outclass );\n\t\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\t$el.addClass( hideClass ).removeClass( outclass );\n\t\t\t}\n\t\t\tthis._visible = false;\n\t\t},\n\n\t\ttoggle: function(){\n\t\t\tthis[ this._visible ? \"hide\" : \"show\" ]();\n\t\t},\n\n\t\t_bindToggleHandlers: function(){\n\t\t\tvar self = this,\n\t\t\t\to = self.options,\n\t\t\t\t$el = self.element;\n\n\t\t\t// tap toggle\n\t\t\t$el.closest( \".ui-page\" )\n\t\t\t\t.bind( \"vclick\", function( e ){\n\t\t\t\t\tif( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ){\n\t\t\t\t\t\tself.toggle();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( \"focusin focusout\", function( e ){\n\t\t\t\t\tif( screen.width < 500 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( \".ui-header-fixed, .ui-footer-fixed\" ).length ){\n\t\t\t\t\t\tself[ ( e.type === \"focusin\" && self._visible ) ? \"hide\" : \"show\" ]();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t},\n\n\t\tdestroy: function(){\n\t\t\tthis.element.removeClass( \"ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden\" );\n\t\t\tthis.element.closest( \".ui-page\" ).removeClass( \"ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen\" );\n\t\t}\n\n\t});\n\n\t//auto self-init widgets\n\t$( document )\n\t\t.bind( \"pagecreate create\", function( e ){\n\t\t\t\n\t\t\t// DEPRECATED in 1.1: support for data-fullscreen=true|false on the page element.\n\t\t\t// This line ensures it still works, but we recommend moving the attribute to the toolbars themselves.\n\t\t\tif( $( e.target ).jqmData( \"fullscreen\" ) ){\n\t\t\t\t$( $.mobile.fixedtoolbar.prototype.options.initSelector, e.target ).not( \":jqmData(fullscreen)\" ).jqmData( \"fullscreen\", true );\n\t\t\t}\n\t\t\t\n\t\t\t$.mobile.fixedtoolbar.prototype.enhanceWithin( e.target );\n\t\t});\n\n})( jQuery );\n\n( function( $, window ) {\n\t\n\t// This fix addresses an iOS bug, so return early if the UA claims it's something else.\n\tif( !(/iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( \"AppleWebKit\" ) > -1 ) ){\n\t\treturn;\n\t}\n\t\n    var zoom = $.mobile.zoom,\n\t\tevt, x, y, z, aig;\n\t\n    function checkTilt( e ){\n\t\tevt = e.originalEvent;\n\t\taig = evt.accelerationIncludingGravity;\n\t\t\n\t\tx = Math.abs( aig.x );\n\t\ty = Math.abs( aig.y );\n\t\tz = Math.abs( aig.z );\n\t\t\t\t\n\t\t// If portrait orientation and in one of the danger zones\n        if( !window.orientation && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ){\n\t\t\tif( zoom.enabled ){\n\t\t\t\tzoom.disable();\n\t\t\t}        \t\n        }\n\t\telse if( !zoom.enabled ){\n\t\t\tzoom.enable();\n        }\n    }\n\n    $( window )\n\t\t.bind( \"orientationchange.iosorientationfix\", zoom.enable )\n\t\t.bind( \"devicemotion.iosorientationfix\", checkTilt );\n\n}( jQuery, this ));\n\n( function( $, window, undefined ) {\n\tvar\t$html = $( \"html\" ),\n\t\t\t$head = $( \"head\" ),\n\t\t\t$window = $( window );\n\n \t// trigger mobileinit event - useful hook for configuring $.mobile settings before they're used\n\t$( window.document ).trigger( \"mobileinit\" );\n\n\t// support conditions\n\t// if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,\n\t// otherwise, proceed with the enhancements\n\tif ( !$.mobile.gradeA() ) {\n\t\treturn;\n\t}\n\n\t// override ajaxEnabled on platforms that have known conflicts with hash history updates\n\t// or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)\n\tif ( $.mobile.ajaxBlacklist ) {\n\t\t$.mobile.ajaxEnabled = false;\n\t}\n\n\t// Add mobile, initial load \"rendering\" classes to docEl\n\t$html.addClass( \"ui-mobile ui-mobile-rendering\" );\n\n\t// This is a fallback. If anything goes wrong (JS errors, etc), or events don't fire,\n\t// this ensures the rendering class is removed after 5 seconds, so content is visible and accessible\n\tsetTimeout( hideRenderingClass, 5000 );\n\n\t// loading div which appears during Ajax requests\n\t// will not appear if $.mobile.loadingMessage is false\n\tvar loaderClass = \"ui-loader\",\n\t\t$loader = $( \"<div class='\" + loaderClass + \"'><span class='ui-icon ui-icon-loading'></span><h1></h1></div>\" );\n\n\t// For non-fixed supportin browsers. Position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top\n\tfunction fakeFixLoader(){\n\t\tvar activeBtn = $( \".\" + $.mobile.activeBtnClass ).first();\n\n\t\t$loader\n\t\t\t.css({\n\t\t\t\ttop: $.support.scrollTop && $window.scrollTop() + $window.height() / 2 ||\n\t\t\t\tactiveBtn.length && activeBtn.offset().top || 100\n\t\t\t});\n\t}\n\n\t// check position of loader to see if it appears to be \"fixed\" to center\n\t// if not, use abs positioning\n\tfunction checkLoaderPosition(){\n\t\tvar offset = $loader.offset(),\n\t\t\tscrollTop = $window.scrollTop(),\n\t\t\tscreenHeight = $.mobile.getScreenHeight();\n\n\t\tif( offset.top < scrollTop || (offset.top - scrollTop) > screenHeight ) {\n\t\t\t$loader.addClass( \"ui-loader-fakefix\" );\n\t\t\tfakeFixLoader();\n\t\t\t$window\n\t\t\t\t.unbind( \"scroll\", checkLoaderPosition )\n\t\t\t\t.bind( \"scroll\", fakeFixLoader );\n\t\t}\n\t}\n\n\t//remove initial build class (only present on first pageshow)\n\tfunction hideRenderingClass(){\n\t\t$html.removeClass( \"ui-mobile-rendering\" );\n\t}\n\n\t$.extend($.mobile, {\n\t\t// turn on/off page loading message.\n\t\tshowPageLoadingMsg: function( theme, msgText, textonly ) {\n\t\t\t$html.addClass( \"ui-loading\" );\n\n\t\t\tif ( $.mobile.loadingMessage ) {\n\t\t\t\t// text visibility from argument takes priority\n\t\t\t\tvar textVisible = textonly || $.mobile.loadingMessageTextVisible;\n\n\t\t\t\ttheme = theme || $.mobile.loadingMessageTheme,\n\n\t\t\t\t$loader\n\t\t\t\t\t.attr( \"class\", loaderClass + \" ui-corner-all ui-body-\" + ( theme || \"a\" ) + \" ui-loader-\" + ( textVisible ? \"verbose\" : \"default\" ) + ( textonly ? \" ui-loader-textonly\" : \"\" ) )\n\t\t\t\t\t.find( \"h1\" )\n\t\t\t\t\t\t.text( msgText || $.mobile.loadingMessage )\n\t\t\t\t\t\t.end()\n\t\t\t\t\t.appendTo( $.mobile.pageContainer );\n\n\t\t\t\tcheckLoaderPosition();\n\t\t\t\t$window.bind( \"scroll\", checkLoaderPosition );\n\t\t\t}\n\t\t},\n\n\t\thidePageLoadingMsg: function() {\n\t\t\t$html.removeClass( \"ui-loading\" );\n\n\t\t\tif( $.mobile.loadingMessage ){\n\t\t\t\t$loader.removeClass( \"ui-loader-fakefix\" );\n\t\t\t}\n\n\t\t\t$( window ).unbind( \"scroll\", fakeFixLoader );\n\t\t\t$( window ).unbind( \"scroll\", checkLoaderPosition );\n\t\t},\n\n\t\t// find and enhance the pages in the dom and transition to the first page.\n\t\tinitializePage: function() {\n\t\t\t// find present pages\n\t\t\tvar $pages = $( \":jqmData(role='page'), :jqmData(role='dialog')\" );\n\n\t\t\t// if no pages are found, create one with body's inner html\n\t\t\tif ( !$pages.length ) {\n\t\t\t\t$pages = $( \"body\" ).wrapInner( \"<div data-\" + $.mobile.ns + \"role='page'></div>\" ).children( 0 );\n\t\t\t}\n\n\t\t\t// add dialogs, set data-url attrs\n\t\t\t$pages.each(function() {\n\t\t\t\tvar $this = $(this);\n\n\t\t\t\t// unless the data url is already set set it to the pathname\n\t\t\t\tif ( !$this.jqmData(\"url\") ) {\n\t\t\t\t\t$this.attr( \"data-\" + $.mobile.ns + \"url\", $this.attr( \"id\" ) || location.pathname + location.search );\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)\n\t\t\t$.mobile.firstPage = $pages.first();\n\n\t\t\t// define page container\n\t\t\t$.mobile.pageContainer = $pages.first().parent().addClass( \"ui-mobile-viewport\" );\n\n\t\t\t// alert listeners that the pagecontainer has been determined for binding\n\t\t\t// to events triggered on it\n\t\t\t$window.trigger( \"pagecontainercreate\" );\n\n\t\t\t// cue page loading message\n\t\t\t$.mobile.showPageLoadingMsg();\n\n\t\t\t//remove initial build class (only present on first pageshow)\n\t\t\thideRenderingClass();\n\n\t\t\t// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM\n\t\t\tif ( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ) {\n\t\t\t\t$.mobile.changePage( $.mobile.firstPage, { transition: \"none\", reverse: true, changeHash: false, fromHashChange: true } );\n\t\t\t}\n\t\t\t// otherwise, trigger a hashchange to load a deeplink\n\t\t\telse {\n\t\t\t\t$window.trigger( \"hashchange\", [ true ] );\n\t\t\t}\n\t\t}\n\t});\n\n\t// initialize events now, after mobileinit has occurred\n\t$.mobile._registerInternalEvents();\n\n\t// check which scrollTop value should be used by scrolling to 1 immediately at domready\n\t// then check what the scroll top is. Android will report 0... others 1\n\t// note that this initial scroll won't hide the address bar. It's just for the check.\n\t$(function() {\n\t\twindow.scrollTo( 0, 1 );\n\n\t\t// if defaultHomeScroll hasn't been set yet, see if scrollTop is 1\n\t\t// it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)\n\t\t// so if it's 1, use 0 from now on\n\t\t$.mobile.defaultHomeScroll = ( !$.support.scrollTop || $(window).scrollTop() === 1 ) ? 0 : 1;\n\n\n\t\t// TODO: Implement a proper registration mechanism with dependency handling in order to not have exceptions like the one below\n\t\t//auto self-init widgets for those widgets that have a soft dependency on others\n\t\tif ( $.fn.controlgroup ) {\n\t\t\t$( document ).bind( \"pagecreate create\", function( e ){\n\t\t\t\t$( \":jqmData(role='controlgroup')\", e.target )\n\t\t\t\t\t.jqmEnhanceable()\n\t\t\t\t\t.controlgroup({ excludeInvisible: false });\n\t\t\t});\n\t\t}\n\n\t\t//dom-ready inits\n\t\tif( $.mobile.autoInitializePage ){\n\t\t\t$.mobile.initializePage();\n\t\t}\n\n\t\t// window load event\n\t\t// hide iOS browser chrome on load\n\t\t$window.load( $.mobile.silentScroll );\n\t});\n}( jQuery, this ));\n\n\n}));\n"
  },
  {
    "path": "test/perf/OpenFile-perf-files/jquery_ui_index.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n\t\t<title>jQuery UI Example Page</title>\n\t\t<link type=\"text/css\" href=\"css/smoothness/jquery-ui-1.8.16.custom.css\" rel=\"stylesheet\" />\t\n\t\t<script type=\"text/javascript\" src=\"js/jquery-1.6.2.min.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"js/jquery-ui-1.8.16.custom.min.js\"></script>\n\t\t<script type=\"text/javascript\">\n\t\t\t$(function(){\n\n\t\t\t\t// Accordion\n\t\t\t\t$(\"#accordion\").accordion({ header: \"h3\" });\n\n\t\t\t\t//Autocomplete\n\t\t\t\t$(\"#autocomplete\").autocomplete({\n\t\t\t\t\tsource: [\"c++\", \"java\", \"php\", \"coldfusion\", \"javascript\", \"asp\", \"ruby\", \"python\", \"c\", \"scala\", \"groovy\", \"haskell\", \"perl\"]\n\t\t\t\t});\n\n\t\t\t\t// Button\n\t\t\t\t$(\"#button\").button();\n\t\t\t\t$(\"#radioset\").buttonset();\n\n\t\t\t\t// Tabs\n\t\t\t\t$('#tabs').tabs();\n\t\n\n\t\t\t\t// Dialog\t\t\t\n\t\t\t\t$('#dialog').dialog({\n\t\t\t\t\tautoOpen: false,\n\t\t\t\t\twidth: 600,\n\t\t\t\t\tbuttons: {\n\t\t\t\t\t\t\"Ok\": function() { \n\t\t\t\t\t\t\t$(this).dialog(\"close\"); \n\t\t\t\t\t\t}, \n\t\t\t\t\t\t\"Cancel\": function() { \n\t\t\t\t\t\t\t$(this).dialog(\"close\"); \n\t\t\t\t\t\t} \n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t// Dialog Link\n\t\t\t\t$('#dialog_link').click(function(){\n\t\t\t\t\t$('#dialog').dialog('open');\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\n\t\t\t\t// Datepicker\n\t\t\t\t$('#datepicker').datepicker({\n\t\t\t\t\tinline: true\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t// Slider\n\t\t\t\t$('#slider').slider({\n\t\t\t\t\trange: true,\n\t\t\t\t\tvalues: [17, 67]\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t// Progressbar\n\t\t\t\t$(\"#progressbar\").progressbar({\n\t\t\t\t\tvalue: 20 \n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t//hover states on the static widgets\n\t\t\t\t$('#dialog_link, ul#icons li').hover(\n\t\t\t\t\tfunction() { $(this).addClass('ui-state-hover'); }, \n\t\t\t\t\tfunction() { $(this).removeClass('ui-state-hover'); }\n\t\t\t\t);\n\t\t\t\t\n\t\t\t});\n\t\t</script>\n\t\t<style type=\"text/css\">\n\t\t\t/*demo page css*/\n\t\t\tbody{ font: 62.5% \"Trebuchet MS\", sans-serif; margin: 50px;}\n\t\t\t.demoHeaders { margin-top: 2em; }\n\t\t\t#dialog_link {padding: .4em 1em .4em 20px;text-decoration: none;position: relative;}\n\t\t\t#dialog_link span.ui-icon {margin: 0 5px 0 0;position: absolute;left: .2em;top: 50%;margin-top: -8px;}\n\t\t\tul#icons {margin: 0; padding: 0;}\n\t\t\tul#icons li {margin: 2px; position: relative; padding: 4px 0; cursor: pointer; float: left;  list-style: none;}\n\t\t\tul#icons span.ui-icon {float: left; margin: 0 4px;}\n\t\t</style>\t\n\t</head>\n\t<body>\n\t<h1>Welcome to jQuery UI!</h1>\n\t<p style=\"font-size: 1.3em; line-height: 1.5; margin: 1em 0; width: 50%;\">This page demonstrates the widgets you downloaded using the theme you selected in the download builder. We've included and linked to minified versions of <a href=\"js/jquery-1.6.2.min.js\">jQuery</a>, your personalized copy of <a href=\"js/jquery-ui-1.8.16.custom.min.js\">jQuery UI (js/jquery-ui-1.8.16.custom.min.js)</a>, and <a href=\"css/smoothness/jquery-ui-1.8.16.custom.css\">css/smoothness/jquery-ui-1.8.16.custom.css</a> which imports the entire jQuery UI CSS Framework. You can choose to link a subset of the CSS Framework depending on your needs. </p>\n\t<p style=\"font-size: 1.2em; line-height: 1.5; margin: 1em 0; width: 50%;\">You've downloaded components and a theme that are compatible with jQuery 1.3+. Please make sure you are using jQuery 1.3+ in your production environment.</p>\t\n\n\t<p style=\"font-weight: bold; margin: 2em 0 1em; font-size: 1.3em;\">YOUR COMPONENTS:</p>\n\t\t\n\t\t<!-- Accordion -->\n\t\t<h2 class=\"demoHeaders\">Accordion</h2>\n\t\t<div id=\"accordion\">\n\t\t\t<div>\n\t\t\t\t<h3><a href=\"#\">First</a></h3>\n\t\t\t\t<div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h3><a href=\"#\">Second</a></h3>\n\t\t\t\t<div>Phasellus mattis tincidunt nibh.</div>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h3><a href=\"#\">Third</a></h3>\n\t\t\t\t<div>Nam dui erat, auctor a, dignissim quis.</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Autocomplete -->\n\t\t<h2 class=\"demoHeaders\">Autocomplete</h2>\n\t\t<div>\n\t\t\t<input id=\"autocomplete\" style=\"z-index: 100; position: relative\" title=\"type &quot;a&quot;\" />\n\t\t</div>\n\t\t\n\n\t\t<!-- Button -->\n\t\t<h2 class=\"demoHeaders\">Button</h2>\n\t\t<button id=\"button\">A button element</button>\n\t\t<form style=\"margin-top: 1em;\">\n\t\t\t<div id=\"radioset\">\n\t\t\t\t<input type=\"radio\" id=\"radio1\" name=\"radio\" /><label for=\"radio1\">Choice 1</label>\n\t\t\t\t<input type=\"radio\" id=\"radio2\" name=\"radio\" checked=\"checked\" /><label for=\"radio2\">Choice 2</label>\n\t\t\t\t<input type=\"radio\" id=\"radio3\" name=\"radio\" /><label for=\"radio3\">Choice 3</label>\n\t\t\t</div>\n\t\t</form>\n\t\t\n\t\n\t\t<!-- Tabs -->\n\t\t<h2 class=\"demoHeaders\">Tabs</h2>\n\t\t<div id=\"tabs\">\n\t\t\t<ul>\n\t\t\t\t<li><a href=\"#tabs-1\">First</a></li>\n\t\t\t\t<li><a href=\"#tabs-2\">Second</a></li>\n\t\t\t\t<li><a href=\"#tabs-3\">Third</a></li>\n\t\t\t</ul>\n\t\t\t<div id=\"tabs-1\">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>\n\t\t\t<div id=\"tabs-2\">Phasellus mattis tincidunt nibh. Cras orci urna, blandit id, pretium vel, aliquet ornare, felis. Maecenas scelerisque sem non nisl. Fusce sed lorem in enim dictum bibendum.</div>\n\t\t\t<div id=\"tabs-3\">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>\n\t\t</div>\n\t\n\t\t<!-- Dialog NOTE: Dialog is not generated by UI in this demo so it can be visually styled in themeroller-->\n\t\t<h2 class=\"demoHeaders\">Dialog</h2>\n\t\t<p><a href=\"#\" id=\"dialog_link\" class=\"ui-state-default ui-corner-all\"><span class=\"ui-icon ui-icon-newwin\"></span>Open Dialog</a></p>\n\t\t\n\t\t\n\t\t<h2 class=\"demoHeaders\">Overlay and Shadow Classes <em>(not currently used in UI widgets)</em></h2>\n\t\t<div style=\"position: relative; width: 96%; height: 200px; padding:1% 4%; overflow:hidden;\" class=\"fakewindowcontain\">\n\t\t\t<p>Lorem ipsum dolor sit amet,  Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. </p><p>Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. </p><p>Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. </p><p>Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. </p>\n\t\t\t\n\t\t\t<!-- ui-dialog -->\n\t\t\t<div class=\"ui-overlay\"><div class=\"ui-widget-overlay\"></div><div class=\"ui-widget-shadow ui-corner-all\" style=\"width: 302px; height: 152px; position: absolute; left: 50px; top: 30px;\"></div></div>\n\t\t\t<div style=\"position: absolute; width: 280px; height: 130px;left: 50px; top: 30px; padding: 10px;\" class=\"ui-widget ui-widget-content ui-corner-all\">\n\t\t\t\t<div class=\"ui-dialog-content ui-widget-content\" style=\"background: none; border: 0;\">\n\t\t\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\n\t\t</div>\n\n\t\t\n\t\t<!-- ui-dialog -->\n\t\t<div id=\"dialog\" title=\"Dialog Title\">\n\t\t\t<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n\t\t</div>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t<h2 class=\"demoHeaders\">Framework Icons (content color preview)</h2>\n\t\t<ul id=\"icons\" class=\"ui-widget ui-helper-clearfix\">\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-n\"><span class=\"ui-icon ui-icon-carat-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-ne\"><span class=\"ui-icon ui-icon-carat-1-ne\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-e\"><span class=\"ui-icon ui-icon-carat-1-e\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-se\"><span class=\"ui-icon ui-icon-carat-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-s\"><span class=\"ui-icon ui-icon-carat-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-sw\"><span class=\"ui-icon ui-icon-carat-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-w\"><span class=\"ui-icon ui-icon-carat-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-1-nw\"><span class=\"ui-icon ui-icon-carat-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-2-n-s\"><span class=\"ui-icon ui-icon-carat-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-carat-2-e-w\"><span class=\"ui-icon ui-icon-carat-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-n\"><span class=\"ui-icon ui-icon-triangle-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-ne\"><span class=\"ui-icon ui-icon-triangle-1-ne\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-e\"><span class=\"ui-icon ui-icon-triangle-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-se\"><span class=\"ui-icon ui-icon-triangle-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-s\"><span class=\"ui-icon ui-icon-triangle-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-sw\"><span class=\"ui-icon ui-icon-triangle-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-w\"><span class=\"ui-icon ui-icon-triangle-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-1-nw\"><span class=\"ui-icon ui-icon-triangle-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-2-n-s\"><span class=\"ui-icon ui-icon-triangle-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-triangle-2-e-w\"><span class=\"ui-icon ui-icon-triangle-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-n\"><span class=\"ui-icon ui-icon-arrow-1-n\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-ne\"><span class=\"ui-icon ui-icon-arrow-1-ne\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-e\"><span class=\"ui-icon ui-icon-arrow-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-se\"><span class=\"ui-icon ui-icon-arrow-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-s\"><span class=\"ui-icon ui-icon-arrow-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-sw\"><span class=\"ui-icon ui-icon-arrow-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-w\"><span class=\"ui-icon ui-icon-arrow-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-1-nw\"><span class=\"ui-icon ui-icon-arrow-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-n-s\"><span class=\"ui-icon ui-icon-arrow-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-ne-sw\"><span class=\"ui-icon ui-icon-arrow-2-ne-sw\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-e-w\"><span class=\"ui-icon ui-icon-arrow-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-2-se-nw\"><span class=\"ui-icon ui-icon-arrow-2-se-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-n\"><span class=\"ui-icon ui-icon-arrowstop-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-e\"><span class=\"ui-icon ui-icon-arrowstop-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-s\"><span class=\"ui-icon ui-icon-arrowstop-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowstop-1-w\"><span class=\"ui-icon ui-icon-arrowstop-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-n\"><span class=\"ui-icon ui-icon-arrowthick-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-ne\"><span class=\"ui-icon ui-icon-arrowthick-1-ne\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-e\"><span class=\"ui-icon ui-icon-arrowthick-1-e\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-se\"><span class=\"ui-icon ui-icon-arrowthick-1-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-s\"><span class=\"ui-icon ui-icon-arrowthick-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-sw\"><span class=\"ui-icon ui-icon-arrowthick-1-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-w\"><span class=\"ui-icon ui-icon-arrowthick-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-1-nw\"><span class=\"ui-icon ui-icon-arrowthick-1-nw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-n-s\"><span class=\"ui-icon ui-icon-arrowthick-2-n-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-ne-sw\"><span class=\"ui-icon ui-icon-arrowthick-2-ne-sw\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-e-w\"><span class=\"ui-icon ui-icon-arrowthick-2-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthick-2-se-nw\"><span class=\"ui-icon ui-icon-arrowthick-2-se-nw\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-n\"><span class=\"ui-icon ui-icon-arrowthickstop-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-e\"><span class=\"ui-icon ui-icon-arrowthickstop-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-s\"><span class=\"ui-icon ui-icon-arrowthickstop-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowthickstop-1-w\"><span class=\"ui-icon ui-icon-arrowthickstop-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-w\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-n\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-e\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturnthick-1-s\"><span class=\"ui-icon ui-icon-arrowreturnthick-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-w\"><span class=\"ui-icon ui-icon-arrowreturn-1-w\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-n\"><span class=\"ui-icon ui-icon-arrowreturn-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-e\"><span class=\"ui-icon ui-icon-arrowreturn-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowreturn-1-s\"><span class=\"ui-icon ui-icon-arrowreturn-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-w\"><span class=\"ui-icon ui-icon-arrowrefresh-1-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-n\"><span class=\"ui-icon ui-icon-arrowrefresh-1-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-e\"><span class=\"ui-icon ui-icon-arrowrefresh-1-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrowrefresh-1-s\"><span class=\"ui-icon ui-icon-arrowrefresh-1-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-4\"><span class=\"ui-icon ui-icon-arrow-4\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-arrow-4-diag\"><span class=\"ui-icon ui-icon-arrow-4-diag\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-extlink\"><span class=\"ui-icon ui-icon-extlink\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-newwin\"><span class=\"ui-icon ui-icon-newwin\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-refresh\"><span class=\"ui-icon ui-icon-refresh\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-shuffle\"><span class=\"ui-icon ui-icon-shuffle\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-transfer-e-w\"><span class=\"ui-icon ui-icon-transfer-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-transferthick-e-w\"><span class=\"ui-icon ui-icon-transferthick-e-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-folder-collapsed\"><span class=\"ui-icon ui-icon-folder-collapsed\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-folder-open\"><span class=\"ui-icon ui-icon-folder-open\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-document\"><span class=\"ui-icon ui-icon-document\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-document-b\"><span class=\"ui-icon ui-icon-document-b\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-note\"><span class=\"ui-icon ui-icon-note\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-mail-closed\"><span class=\"ui-icon ui-icon-mail-closed\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-mail-open\"><span class=\"ui-icon ui-icon-mail-open\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-suitcase\"><span class=\"ui-icon ui-icon-suitcase\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-comment\"><span class=\"ui-icon ui-icon-comment\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-person\"><span class=\"ui-icon ui-icon-person\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-print\"><span class=\"ui-icon ui-icon-print\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-trash\"><span class=\"ui-icon ui-icon-trash\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-locked\"><span class=\"ui-icon ui-icon-locked\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-unlocked\"><span class=\"ui-icon ui-icon-unlocked\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-bookmark\"><span class=\"ui-icon ui-icon-bookmark\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-tag\"><span class=\"ui-icon ui-icon-tag\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-home\"><span class=\"ui-icon ui-icon-home\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-flag\"><span class=\"ui-icon ui-icon-flag\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-calculator\"><span class=\"ui-icon ui-icon-calculator\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-cart\"><span class=\"ui-icon ui-icon-cart\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pencil\"><span class=\"ui-icon ui-icon-pencil\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-clock\"><span class=\"ui-icon ui-icon-clock\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-disk\"><span class=\"ui-icon ui-icon-disk\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-calendar\"><span class=\"ui-icon ui-icon-calendar\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-zoomin\"><span class=\"ui-icon ui-icon-zoomin\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-zoomout\"><span class=\"ui-icon ui-icon-zoomout\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-search\"><span class=\"ui-icon ui-icon-search\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-wrench\"><span class=\"ui-icon ui-icon-wrench\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-gear\"><span class=\"ui-icon ui-icon-gear\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-heart\"><span class=\"ui-icon ui-icon-heart\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-star\"><span class=\"ui-icon ui-icon-star\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-link\"><span class=\"ui-icon ui-icon-link\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-cancel\"><span class=\"ui-icon ui-icon-cancel\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-plus\"><span class=\"ui-icon ui-icon-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-plusthick\"><span class=\"ui-icon ui-icon-plusthick\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-minus\"><span class=\"ui-icon ui-icon-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-minusthick\"><span class=\"ui-icon ui-icon-minusthick\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-close\"><span class=\"ui-icon ui-icon-close\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-closethick\"><span class=\"ui-icon ui-icon-closethick\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-key\"><span class=\"ui-icon ui-icon-key\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-lightbulb\"><span class=\"ui-icon ui-icon-lightbulb\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-scissors\"><span class=\"ui-icon ui-icon-scissors\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-clipboard\"><span class=\"ui-icon ui-icon-clipboard\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-copy\"><span class=\"ui-icon ui-icon-copy\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-contact\"><span class=\"ui-icon ui-icon-contact\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-image\"><span class=\"ui-icon ui-icon-image\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-video\"><span class=\"ui-icon ui-icon-video\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-script\"><span class=\"ui-icon ui-icon-script\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-alert\"><span class=\"ui-icon ui-icon-alert\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-info\"><span class=\"ui-icon ui-icon-info\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-notice\"><span class=\"ui-icon ui-icon-notice\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-help\"><span class=\"ui-icon ui-icon-help\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-check\"><span class=\"ui-icon ui-icon-check\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-bullet\"><span class=\"ui-icon ui-icon-bullet\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-radio-off\"><span class=\"ui-icon ui-icon-radio-off\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-radio-on\"><span class=\"ui-icon ui-icon-radio-on\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pin-w\"><span class=\"ui-icon ui-icon-pin-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pin-s\"><span class=\"ui-icon ui-icon-pin-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-play\"><span class=\"ui-icon ui-icon-play\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-pause\"><span class=\"ui-icon ui-icon-pause\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-next\"><span class=\"ui-icon ui-icon-seek-next\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-prev\"><span class=\"ui-icon ui-icon-seek-prev\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-end\"><span class=\"ui-icon ui-icon-seek-end\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-seek-first\"><span class=\"ui-icon ui-icon-seek-first\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-stop\"><span class=\"ui-icon ui-icon-stop\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-eject\"><span class=\"ui-icon ui-icon-eject\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-volume-off\"><span class=\"ui-icon ui-icon-volume-off\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-volume-on\"><span class=\"ui-icon ui-icon-volume-on\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-power\"><span class=\"ui-icon ui-icon-power\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-signal-diag\"><span class=\"ui-icon ui-icon-signal-diag\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-signal\"><span class=\"ui-icon ui-icon-signal\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-0\"><span class=\"ui-icon ui-icon-battery-0\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-1\"><span class=\"ui-icon ui-icon-battery-1\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-2\"><span class=\"ui-icon ui-icon-battery-2\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-battery-3\"><span class=\"ui-icon ui-icon-battery-3\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-plus\"><span class=\"ui-icon ui-icon-circle-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-minus\"><span class=\"ui-icon ui-icon-circle-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-close\"><span class=\"ui-icon ui-icon-circle-close\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-e\"><span class=\"ui-icon ui-icon-circle-triangle-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-s\"><span class=\"ui-icon ui-icon-circle-triangle-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-w\"><span class=\"ui-icon ui-icon-circle-triangle-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-triangle-n\"><span class=\"ui-icon ui-icon-circle-triangle-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-e\"><span class=\"ui-icon ui-icon-circle-arrow-e\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-s\"><span class=\"ui-icon ui-icon-circle-arrow-s\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-w\"><span class=\"ui-icon ui-icon-circle-arrow-w\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-arrow-n\"><span class=\"ui-icon ui-icon-circle-arrow-n\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-zoomin\"><span class=\"ui-icon ui-icon-circle-zoomin\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-zoomout\"><span class=\"ui-icon ui-icon-circle-zoomout\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circle-check\"><span class=\"ui-icon ui-icon-circle-check\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circlesmall-plus\"><span class=\"ui-icon ui-icon-circlesmall-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circlesmall-minus\"><span class=\"ui-icon ui-icon-circlesmall-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-circlesmall-close\"><span class=\"ui-icon ui-icon-circlesmall-close\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-squaresmall-plus\"><span class=\"ui-icon ui-icon-squaresmall-plus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-squaresmall-minus\"><span class=\"ui-icon ui-icon-squaresmall-minus\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-squaresmall-close\"><span class=\"ui-icon ui-icon-squaresmall-close\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-dotted-vertical\"><span class=\"ui-icon ui-icon-grip-dotted-vertical\"></span></li>\n\t\t\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-dotted-horizontal\"><span class=\"ui-icon ui-icon-grip-dotted-horizontal\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-solid-vertical\"><span class=\"ui-icon ui-icon-grip-solid-vertical\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-solid-horizontal\"><span class=\"ui-icon ui-icon-grip-solid-horizontal\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-gripsmall-diagonal-se\"><span class=\"ui-icon ui-icon-gripsmall-diagonal-se\"></span></li>\n\t\t<li class=\"ui-state-default ui-corner-all\" title=\".ui-icon-grip-diagonal-se\"><span class=\"ui-icon ui-icon-grip-diagonal-se\"></span></li>\n\t\t</ul>\n\n\t\n\t\t<!-- Slider -->\n\t\t<h2 class=\"demoHeaders\">Slider</h2>\n\t\t<div id=\"slider\"></div>\n\t\n\t\t<!-- Datepicker -->\n\t\t<h2 class=\"demoHeaders\">Datepicker</h2>\n\t\t<div id=\"datepicker\"></div>\n\t\n\t\t<!-- Progressbar -->\n\t\t<h2 class=\"demoHeaders\">Progressbar</h2>\t\n\t\t<div id=\"progressbar\"></div>\n\t\t\t\n\t\t<!-- Highlight / Error -->\n\t\t<h2 class=\"demoHeaders\">Highlight / Error</h2>\n\t\t<div class=\"ui-widget\">\n\t\t\t<div class=\"ui-state-highlight ui-corner-all\" style=\"margin-top: 20px; padding: 0 .7em;\"> \n\t\t\t\t<p><span class=\"ui-icon ui-icon-info\" style=\"float: left; margin-right: .3em;\"></span>\n\t\t\t\t<strong>Hey!</strong> Sample ui-state-highlight style.</p>\n\t\t\t</div>\n\t\t</div>\n\t\t<br/>\n\t\t<div class=\"ui-widget\">\n\t\t\t<div class=\"ui-state-error ui-corner-all\" style=\"padding: 0 .7em;\"> \n\t\t\t\t<p><span class=\"ui-icon ui-icon-alert\" style=\"float: left; margin-right: .3em;\"></span> \n\t\t\t\t<strong>Alert:</strong> Sample ui-state-error style.</p>\n\t\t\t</div>\n\t\t</div>\n\n\t</body>\n</html>\n\n\n"
  },
  {
    "path": "test/perf/OpenFile-perf-files/quiet-scrollbars.css",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *  \n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"), \n * to deal in the Software without restriction, including without limitation \n * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n * and/or sell copies of the Software, and to permit persons to whom the \n * Software is furnished to do so, subject to the following conditions:\n *  \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *  \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * DEALINGS IN THE SOFTWARE.\n * \n */\n\n/* Temporary implementation of unobtrusive scrollbars. \n   FUTURE: These currently rely on nonstandard WebKit styles, and don't have all the right behavior. \n   Longer-term, we'll need to implement custom scrollbars. */\n\n.quiet-scrollbars ::-webkit-scrollbar {\n    width: 9px;\n    height: 9px;\n}\n\n.quiet-scrollbars ::-webkit-scrollbar-corner {\n    background-color: transparent;\n}\n\n.quiet-scrollbars ::-webkit-scrollbar-thumb {\n    background-color: rgba(0,0,0,0);\n}\n\n/* This looks like a dupe, but without it the thumb doesn't fade in\n * properly, probably due to flakiness in how these styles are handled\n * in the build of WebKit that's in CEF.\n */\n.quiet-scrollbars ::-webkit-scrollbar-corner {\n    background-color: transparent;\n}\n\n/* The data URIs for the thumb were generated from the Fireworks files in \n * styles/vertical-thumb-fw-outline.png and styles/horiz-thumb-fw-outline.png.\n */\n.quiet-scrollbars #open-files-container:hover::-webkit-scrollbar-thumb:vertical, \n.quiet-scrollbars #project-files-container:hover::-webkit-scrollbar-thumb:vertical {\n    -webkit-border-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAUCAYAAABf2RdVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABV0RVh0Q3JlYXRpb24gVGltZQA0LzIzLzEyckCqugAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAACPSURBVCiR7ZIhDoNAEEXfkJCsxKBJimTPwA3mDHvqsXWrquqaIH5FKUk3XKAJT87789U3SQkYgZ5fNuABvDpgrLUOOefZzBYzW3LOc6112J/pgL6UMkZE+lZERCqlHO0m6WZmCydICuDencmWK/Tfoc3dn63YbxsAkpKkyd1XwD/eV0nT7jBJAO2Ej+kCvAFNxTqyZCNcEQAAAABJRU5ErkJggg==\") 9 0;\n    border-color: transparent;\n    border-width: 9px 0;\n    min-height: 20px;\n}\n\n.quiet-scrollbars #open-files-container:hover::-webkit-scrollbar-thumb:horizontal, \n.quiet-scrollbars #project-files-container:hover::-webkit-scrollbar-thumb:horizontal {\n    -webkit-border-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABV0RVh0Q3JlYXRpb24gVGltZQA0LzIzLzEyckCqugAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAACLSURBVCiRrdIxCgIxEEbhfxYFOyuxCCLazjGmTu6YKyRV7hFLCzshlcXCQoqxMWCd5B3gqx6pKgAcAJwA7NFfBVB2P+zsnLvGGI89kois3vtijAGp6sU5d+vFWsy85ZyfpKp3IuIRrKWqj2UG9N8CoFprP6MQM28NLCGE1wgqImtK6Q2g0uxtGjitL9E6N1T9Wl8CAAAAAElFTkSuQmCC\") 0 9;\n    border-color: transparent;\n    border-width: 0 9px;\n    min-width: 20px;\n}\n"
  },
  {
    "path": "test/perf/Performance-test.js",
    "content": "/*\n * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*global describe, beforeEach, afterEach, it, runs, waitsForDone */\n\n// TODO: Eventually we should have a brackets performance test suite that is separate from the unit tests\n\ndefine(function (require, exports, module) {\n    'use strict';\n\n    // Load dependent modules\n    var CommandManager,             // loaded from brackets.test\n        Commands,                   // loaded from brackets.test\n        DocumentCommandHandlers,    // loaded from brackets.test\n        PerfUtils,                  // loaded from brackets.test\n        DocumentManager,            // loaded from brackets.test\n        SpecRunnerUtils             = require(\"spec/SpecRunnerUtils\"),\n        UnitTestReporter            = require(\"test/UnitTestReporter\");\n\n    var jsLintCommand, jsLintPrevSetting;\n\n    describe(\"Performance Tests\", function () {\n\n        this.category = \"performance\";\n\n        // Note: this tests assumes that the \"brackets-scenario\" repo is in the same folder\n        //       as the \"brackets-app\"\n        //\n        // TODO: these tests rely on real world example files that cannot be on open source.\n        // We should replace these with test files that can be in the public repro.\n        var testPath = SpecRunnerUtils.getTestPath(\"/perf/OpenFile-perf-files/\"),\n            testWindow;\n\n        function openFile(path) {\n            var fullPath = testPath + path;\n            runs(function () {\n                var promise = CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath});\n                waitsForDone(promise);\n            });\n\n            runs(function () {\n                var reporter = UnitTestReporter.getActiveReporter();\n                reporter.logTestWindow(/Open File:\\t,*/, path);\n                reporter.clearTestWindow();\n            });\n        }\n\n        beforeEach(function () {\n            SpecRunnerUtils.createTestWindowAndRun(this, function (w) {\n                testWindow = w;\n\n                // Load module instances from brackets.test\n                CommandManager      = testWindow.brackets.test.CommandManager;\n                Commands            = testWindow.brackets.test.Commands;\n                DocumentCommandHandlers = testWindow.brackets.test.DocumentCommandHandlers;\n                DocumentManager     = testWindow.brackets.test.DocumentManager;\n                PerfUtils           = testWindow.brackets.test.PerfUtils;\n\n                jsLintCommand = CommandManager.get(\"jslint.toggleEnabled\");\n                if (jsLintCommand) {\n                    jsLintPrevSetting = jsLintCommand.getChecked();\n                    if (jsLintPrevSetting) {\n                        jsLintCommand.execute();\n                    }\n                }\n            });\n        });\n\n        afterEach(function () {\n            testWindow              = null;\n            CommandManager          = null;\n            Commands                = null;\n            DocumentCommandHandlers = null;\n            DocumentManager         = null;\n            PerfUtils               = null;\n            SpecRunnerUtils.closeTestWindow();\n        });\n\n\n        // TODO: right now these are in a single test because performance results are\n        // tied to a window, so we need one window for all the tests. Need to think\n        // more about how performance tests should ultimately work.\n        it(\"File open performance\", function () {\n            openFile(\"brackets-concat.js\"); // 3.4MB\n            openFile(\"jquery_ui_index.html\");\n            openFile(\"blank.js\");\n            openFile(\"InlineWidget.js\");\n            openFile(\"quiet-scrollbars.css\");\n            openFile(\"England(Chinese).htm\");\n            openFile(\"jquery.mobile-1.1.0.css\");\n            openFile(\"jquery.mobile-1.1.0.min.css\");\n            openFile(\"jquery.mobile-1.1.0.js\");\n            openFile(\"jquery.mobile-1.1.0.min.js\");\n        });\n    });\n});\n"
  },
  {
    "path": "test/polyfills.js",
    "content": "(function () {\n    \"use strict\";\n\n    if (!Function.prototype.bind) {\n        Function.prototype.bind = function (oThis) {\n            if (typeof this !== \"function\") {\n                // closest thing possible to the ECMAScript 5\n                // internal IsCallable function\n                throw new TypeError(\"Function.prototype.bind - what is trying to be bound is not callable\");\n            }\n\n            var aArgs = Array.prototype.slice.call(arguments, 1),\n                fToBind = this,\n                FNOP = function () {},\n                fBound = function () {\n                    return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));\n                };\n\n            FNOP.prototype = this.prototype;\n            fBound.prototype = new FNOP();\n\n            return fBound;\n        };\n    }\n}());\n"
  },
  {
    "path": "test/smokes/citrus completed/css/desktop.css",
    "content": "@charset \"utf-8\";\n/* CSS Document */\n\narticle,\naside,\nfigure,\nfooter,\nheader,\nnav,\nsection {\n\tdisplay: block;\n\tmargin: 0;\n\tpadding: 0;\n}\nbody {\n\tbackground-color: #66b034;\n\tcolor: #000;\n\tfont-family: \"Trebuchet MS\", Arial, Helvetica, sans-serif;\n\tmargin: 0;\n\tpadding: 00;\n}\n#container {\n\tmargin: 0 auto;\n\twidth: 840px;\n}\n#logo {\n\tbackground-image: url(../images/lrg_logo.png);\n\tbackground-repeat: no-repeat;\n\theight: 138px;\n\twidth: 100%;\n}\n#logo h1, #logo h2 {\n\tposition: absolute;\n\ttop: -500px;\n}\nnav {\n\tpadding-top: 150px;\n}\n#maincontent {\n\tmargin-top: 80px;\n\tpadding: 10px 0;\n}\nul {\n\tmargin: 0;\n\tpadding: 0;\n}\nnav ul {\n\tfont-size: 20px;\n\tfont-weight: bold;\n\tlist-style: none;\n\tmargin-bottom: 15px;\n}\nnav ul li {\n\tfloat: left;\n}\nnav ul a {\n\tborder: 1px solid #618a37;\n\tborder-radius: 8px;\n\tbox-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);\n\tcolor: #fff;\n\tdisplay: block;\n\tpadding: 10px;\n\ttext-align:center;\n\ttext-decoration: none;\n\tmargin: 5px 0;\n\t-moz-box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);\n\t-webkit-box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);\n\ttext-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);\n\twidth: 140px;\n}\nnav ul a:link,\nnav ul a:visited {\n\tbackground: rgba(255,255,255,0.2);\n}\nnav ul a:hover, \nnav ul a:active,\nnav ul a:focus {\n\tbackground: rgba(255,255,255,0.4);\n}\nnav ul li:hover {\n\tmargin-top:-10px;\n}\nnav ul li {\n\tfloat: left;\n\t-webkit-transition-duration:.5s;\n\t-webkit-transition-property:margin-top;\n\t-webkit-transition-timing-function:ease-in-out;\n\t-o-transition-duration:.5s;\n\t-o-transition-property:margin-top;\n\t-o-transition-timing-function:ease-in-out;\n\t-moz-transition-duration:.5s;\n\t-moz-transition-property:margin-top;\n\t-moz-transition-timing-function:ease-in-out;\n\ttransition-duration:.5s;\n\ttransition-property:margin-top;\n\ttransition-timing-function:ease-in-out;\n}\n#vision {\n\tbackground-image: url(../images/lrg_hero.jpg);\n\tbackground-repeat: no-repeat;\n\tfont-family: \"Palatino Linotype\", \"Book Antiqua\", Palatino, serif;\n\tfont-size: 32px;\n\tfont-weight: bold;\n\theight: 237px;\n\tline-height: 1.2;\n\tmargin-bottom: 20px;\n\tpadding: 60px 370px 0 40px;\n\twidth: 409px;\n}\n.pod {\n\tbackground: #fff;\n\tfloat: left;\n\tmargin-right: 13px;\n\tpadding: 10px;\n\twidth: 244px;\n}\n.podContent {\n\theight: 181px;\n\tmargin-top: 10px;\n\toverflow: hidden;\n\twidth: 244px;\n}\n#news .podContent {\n\tmargin-top: 12px;\n\toverflow: auto;\n}\n#news .podContent p {\n\tfont-size: 15px;\n\tmargin-bottom: 5px;\n\tmargin-left: 6px;\n\tmargin-top: 5px;\n}\n.pod h1 {\n\tbackground: #ccc;\n\tbackground-image: url(../images/icon_chevron.png);\n\tbackground-position: 95%;\n\tbackground-repeat: no-repeat;\n\tcolor: #000;\n\tfont-size:16px;\n\tfont-weight: normal;\n\tmargin: 0 0 10px 0;\n\tpadding: 5px;\n}\na.block {\n\tdisplay: block;\n\ttext-decoration: none;\n}\ntime {\n\tdisplay: inline-block;\n\tfont-weight: bold;\n\twidth: 2.5em;\n}\nfooter {\n\tclear: both;\n\tcolor: #fff;\n\tpadding: 10px 0;\n}\nfooter p {\n\tmargin: 0 0 5px 0;\n}\n#phone {\n\tcolor: #000;\n\tfont-weight: bold;\n}\n#facebookTwitter {\n\tfloat: right;\n\tmargin-right: 25px;\n}"
  },
  {
    "path": "test/smokes/citrus completed/css/phone.css",
    "content": "@charset \"utf-8\";\n#container {\n\twidth: 100%;\n}\n#logo {\n\tbackground-image: url(../images/sml_logo.png);\n\theight: auto;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\twidth: 270px;\n}\nnav {\n\tpadding-top: 100px;\n}\nnav ul {\n\tfont-size: 24px;\n}\nnav ul a {\n\tpadding-right: 0;\n\twidth: 97%;\n}\nnav ul li {\n\tfloat: none;\n}\nnav ul li:hover {\n\tmargin-top: 0;\n}\n#maincontent {\n\tmargin-top: 0;\n\tpadding: 0;\n}\n#vision {\n\tbackground-image: none;\n\tfont-size: 16px;\n\theight: auto;\n\tline-height: normal;\n\tpadding-top: 0;\n\twidth: 280px;\n}\n/* Uncomment the declarations in the following rules to hide the images in the pods. */\n.pod {\n\twidth: 305px;\n\t/*padding-bottom:0;*/\n}\n/*.pod h1 {\n\tmargin-bottom:0;\n}*/\n.podContent {\n\twidth: 302px;\n\theight: 180px;\n\t/*display:none;*/\n}\n/*#news .podContent {\n\tdisplay:block;\n}*/\nfooter p {\n\tmargin-left: 5px;\n}\n#facebookTwitter {\n\tmargin-right: 5px;\n}"
  },
  {
    "path": "test/smokes/server-tests/css/tablet.css",
    "content": "@charset \"utf-8\";\n#container {\n\twidth: 700px;\n}\n#logo {\n\tbackground-image: url(../images/med_logo.png);\n\theight: 100px;\n}\nnav {\n\tpadding-top: 110px;\n}\nnav ul {\n\tfont-size: 18px;\n}\nnav ul a {\n\twidth: 114px;\n}\n#maincontent {\n\tmargin-left: 5px;\n\tpadding: 0;\n\twidth: 700px;\n}\n#vision {\n\tbackground-image: url(../images/med_hero.jpg);\n\tfont-size: 26px;\n\theight: 217px;\n\tpadding-top: 45px;\n\tpadding-right: 350px;\n\twidth: 289px;\n}\n.pod {\n\twidth: 305px;\n}\n.podContent {\n\twidth: 302px;\n\theight: 180px;\n}\n#events {\n\tmargin-left: 7px;\n}\n#news {\n\tmargin-top: 20px;\n\twidth: 650px;\n}\nfooter p {\n\tmargin-left: 5px;\n}"
  },
  {
    "path": "test/smokes/server-tests/pathRel.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<meta name=\"viewport\" content=\"width=device-width\">\n<title>Citrus Cafe</title>\n<link href=\"css/citrus_mq.css\" rel=\"stylesheet\" type=\"text/css\">\n</head>\n\n<body>\n<div id=\"container\">\n  <header id=\"logo\">\n      <h1>Citrus Cafe</h1>\n      <h2>Sustainable, organic and natural</h2>\n    <nav>\n      <ul>\n        <li><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Menus</a></li>\n        <li><a href=\"#\">Reservations</a></li>\n        <li><a href=\"#\">Gallery</a></li>\n        <li><a href=\"#\">Contact</a></li>\n      </ul>\n    </nav>\n  </header>\n  <div id=\"maincontent\">\n    <article id=\"vision\">A new neighborhood kitchen using only organic and sustainable ingredients all locally sourced.</article>\n<section class=\"pod\"> \n  <a href=\"#\" class=\"block\"><h1>Today's specials</h1></a>\n  <figure class=\"podContent\"><img src=\"images/specials.jpg\" width=\"302\" height=\"180\" alt=\"Soup and salad\"></figure>\n</section>\n<section class=\"pod\" id=\"events\">\n  <a href=\"#\" class=\"block\"><h1>Events</h1></a>\n  <figure class=\"podContent\"><img src=\"images/events.jpg\" width=\"302\" height=\"180\" alt=\"Cafe interior\"></figure>\n</section>\n<section class=\"pod\" id=\"news\">\n  <a href=\"#\" class=\"block\"><h1>News</h1></a>\n  <article class=\"podContent\">\n    <p>\n      <time datetime=\"2010-09-01\">9/1</time>\nCelebrity Guest Chef Night</p>\n    <p>\n      <time datetime=\"2010-09-03\">9/3</time>\nNew Menu Samplers!</p>\n    <p>\n      <time datetime=\"2010-09-04\">9/4</time>\nChef Citrus Style</p>\n    <p>\n      <time datetime=\"2010-09-23\">9/23</time>\nPork Pork and More Pork</p>\n    <p>\n      <time datetime=\"2010-10-01\">10/1</time>\nCelebrity Guest Chef Night</p>\n    <p>\n      <time datetime=\"2010-1003\">10/3</time>\nNew Menu Samplers!</p>\n    <p>\n      <time datetime=\"2010-10-04\">10/4</time>\nIron Chef Citrus Style</p>\n  </article>\n</section>\n  </div>\n  <footer>\n    <div id=\"facebookTwitter\"><img src=\"images/icon_facebook.png\" width=\"24\" height=\"25\" alt=\"Facebook icon\"><img src=\"images/icon_twitter.png\" width=\"24\" height=\"25\" alt=\"Twitter icon\"></div>\n    <p><strong>Citrus Cafe</strong> 601 Townsend St, San Francisco, CA, 94117</p>\n    <p id=\"phone\">415-555-5555</p>\n  </footer>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "test/smokes/server-tests/pathRoot.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<meta name=\"viewport\" content=\"width=device-width\">\n<title>Citrus Cafe</title>\n<link href=\"/server-tests/css/citrus_mq.css\" rel=\"stylesheet\" type=\"text/css\">\n</head>\n\n<body>\n<div id=\"container\">\n  <header id=\"logo\">\n    <h1>Citrus Cafe</h1>\n    <h2>Sustainable, organic and natural</h2>\n    <nav>\n      <ul>\n        <li><a href=\"#\">Home</a></li>\n        <li><a href=\"#\">Menus</a></li>\n        <li><a href=\"#\">Reservations</a></li>\n        <li><a href=\"#\">Gallery</a></li>\n        <li><a href=\"#\">Contact</a></li>\n      </ul>\n    </nav>\n  </header>\n  <div id=\"maincontent\">\n    <article id=\"vision\">A new neighborhood kitchen using only organic and sustainable ingredients all locally sourced.</article>\n    <section class=\"pod\"> \n      <a href=\"#\" class=\"block\"><h1>Today's specials</h1></a>\n      <figure class=\"podContent\"><img src=\"/server-tests/images/specials.jpg\" width=\"302\" height=\"180\" alt=\"Soup and salad\"></figure>\n    </section>\n    <section class=\"pod\" id=\"events\">\n      <a href=\"#\" class=\"block\"><h1>Events</h1></a>\n      <figure class=\"podContent\"><img src=\"/server-tests/images/events.jpg\" width=\"302\" height=\"180\" alt=\"Cafe interior\"></figure>\n    </section>\n    <section class=\"pod\" id=\"news\">\n      <a href=\"#\" class=\"block\"><h1>News</h1></a>\n      <article class=\"podContent\">\n        <p>\n          <time datetime=\"2010-09-01\">9/1</time>\n          Celebrity Guest Chef Night</p>\n        <p>\n          <time datetime=\"2010-09-03\">9/3</time>\n          New Menu Samplers!</p>\n        <p>\n          <time datetime=\"2010-09-04\">9/4</time>\n          Chef Citrus Style</p>\n        <p>\n          <time datetime=\"2010-09-23\">9/23</time>\n          Pork Pork and More Pork</p>\n        <p>\n          <time datetime=\"2010-10-01\">10/1</time>\n          Celebrity Guest Chef Night</p>\n        <p>\n          <time datetime=\"2010-1003\">10/3</time>\n          New Menu Samplers!</p>\n        <p>\n          <time datetime=\"2010-10-04\">10/4</time>\n          Iron Chef Citrus Style</p>\n      </article>\n    </section>\n  </div>\n  <footer>\n    <div id=\"facebookTwitter\"><img src=\"/server-tests/images/icon_facebook.png\" width=\"24\" height=\"25\" alt=\"Facebook icon\"><img src=\"/server-tests/images/icon_twitter.png\" width=\"24\" height=\"25\" alt=\"Twitter icon\"></div>\n    <p><strong>Citrus Cafe</strong> 601 Townsend St, San Francisco, CA, 94117</p>\n    <p id=\"phone\">415-555-5555</p>\n  </footer>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "test/spec/KeyBindingManager-test-files/blank.json",
    "content": ""
  },
  {
    "path": "test/spec/LiveDevelopment-MultiBrowser-test-files/simple1.js",
    "content": ""
  },
  {
    "path": "test/spec/LiveDevelopment-chrome-user-data/Default/User StyleSheets/Custom.css",
    "content": ""
  },
  {
    "path": "test/spec/LiveDevelopment-test-files/simple1.js",
    "content": ""
  },
  {
    "path": "test/spec/LowLevelFileIO-test-files/emptyfile.txt",
    "content": ""
  },
  {
    "path": "test/spec/PreferencesBase-test-files/empty.json",
    "content": ""
  },
  {
    "path": "test/spec/ProjectManager-test-files/directory/interiorfile.js",
    "content": ""
  },
  {
    "path": "test/spec/ProjectManager-test-files/file.js",
    "content": ""
  },
  {
    "path": "test/spec/ProjectManager-test-files/git/index",
    "content": ""
  },
  {
    "path": "test/spec/ProjectManager-test-files/toDelete1/file.js",
    "content": ""
  },
  {
    "path": "test/spec/Theme-test-files/empty.css",
    "content": ""
  },
  {
    "path": "test/spec/Theme-test-files/empty.less",
    "content": ""
  },
  {
    "path": "test/spec/Theme-test-files/empty.txt",
    "content": ""
  },
  {
    "path": "test/spec/WorkingSetView-test-files/directory/directory/file_one.js",
    "content": ""
  },
  {
    "path": "test/spec/WorkingSetView-test-files/directory/file_one.js",
    "content": ""
  },
  {
    "path": "test/spec/WorkingSetView-test-files/file_four.html",
    "content": ""
  },
  {
    "path": "test/spec/WorkingSetView-test-files/file_three.js",
    "content": ""
  },
  {
    "path": "test/spec/WorkingSetView-test-files/file_two.js",
    "content": ""
  },
  {
    "path": "test/spec/WorkingSetView-test-files/file_zero.css",
    "content": ""
  },
  {
    "path": "test/spec/extension-test-files/basic-valid-theme-1.0/theme.less",
    "content": ""
  }
]